diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c index bff9152df..98dd06aeb 100644 --- a/hw/qdev-properties.c +++ b/hw/qdev-properties.c @@ -877,6 +877,52 @@ PropertyInfo qdev_prop_pci_devfn = { .max = 0xFFFFFFFFULL, }; +/* --- blocksize --- */ + +static void set_blocksize(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + int16_t *ptr = qdev_get_prop_ptr(dev, prop); + Error *local_err = NULL; + int64_t value; + + if (dev->state != DEV_STATE_CREATED) { + error_set(errp, QERR_PERMISSION_DENIED); + return; + } + + visit_type_int(v, &value, name, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + if (value < prop->info->min || value > prop->info->max) { + error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE, + dev->id?:"", name, value, prop->info->min, + prop->info->max); + return; + } + + /* We rely on power-of-2 blocksizes for bitmasks */ + if ((value & (value - 1)) != 0) { + error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2, + dev->id?:"", name, value); + return; + } + + *ptr = value; +} + +PropertyInfo qdev_prop_blocksize = { + .name = "blocksize", + .get = get_int16, + .set = set_blocksize, + .min = 512, + .max = 65024, +}; + /* --- public helpers --- */ static Property *qdev_prop_walk(Property *props, const char *name) diff --git a/hw/qdev.h b/hw/qdev.h index a8df42f6f..1c109607b 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -223,6 +223,7 @@ extern PropertyInfo qdev_prop_drive; extern PropertyInfo qdev_prop_netdev; extern PropertyInfo qdev_prop_vlan; extern PropertyInfo qdev_prop_pci_devfn; +extern PropertyInfo qdev_prop_blocksize; #define DEFINE_PROP(_name, _state, _field, _prop, _type) { \ .name = (_name), \ @@ -284,6 +285,8 @@ extern PropertyInfo qdev_prop_pci_devfn; #define DEFINE_PROP_LOSTTICKPOLICY(_n, _s, _f, _d) \ DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_losttickpolicy, \ LostTickPolicy) +#define DEFINE_PROP_BLOCKSIZE(_n, _s, _f, _d) \ + DEFINE_PROP_DEFAULT(_n, _s, _f, _d, qdev_prop_blocksize, uint16_t) #define DEFINE_PROP_END_OF_LIST() \ {} diff --git a/qerror.c b/qerror.c index 1f565fc98..96fbe71ae 100644 --- a/qerror.c +++ b/qerror.c @@ -240,6 +240,11 @@ static const QErrorStringTable qerror_table[] = { .error_fmt = QERR_PROPERTY_VALUE_NOT_FOUND, .desc = "Property '%(device).%(property)' can't find value '%(value)'", }, + { + .error_fmt = QERR_PROPERTY_VALUE_NOT_POWER_OF_2, + .desc = "Property '%(device).%(property)' doesn't take " + "value '%(value)', it's not a power of 2", + }, { .error_fmt = QERR_PROPERTY_VALUE_OUT_OF_RANGE, .desc = "Property '%(device).%(property)' doesn't take " diff --git a/qerror.h b/qerror.h index e16f9c27e..5c23c1ff2 100644 --- a/qerror.h +++ b/qerror.h @@ -202,6 +202,10 @@ QError *qobject_to_qerror(const QObject *obj); #define QERR_PROPERTY_VALUE_NOT_FOUND \ "{ 'class': 'PropertyValueNotFound', 'data': { 'device': %s, 'property': %s, 'value': %s } }" +#define QERR_PROPERTY_VALUE_NOT_POWER_OF_2 \ + "{ 'class': 'PropertyValueNotPowerOf2', 'data': { " \ + "'device': %s, 'property': %s, 'value': %"PRId64" } }" + #define QERR_PROPERTY_VALUE_OUT_OF_RANGE \ "{ 'class': 'PropertyValueOutOfRange', 'data': { 'device': %s, 'property': %s, 'value': %"PRId64", 'min': %"PRId64", 'max': %"PRId64" } }"