machine + QOM queue, 2020-10-06

* QOM documentation fixes and cleanups (Eduardo Habkost)
 * user-mode: Prune build dependencies (Philippe Mathieu-Daudé)
 * qom: Improve error message (Philippe Mathieu-Daudé)
 * numa: hmat: require parent cache description before the next
   level one (Igor Mammedov)
 -----BEGIN PGP SIGNATURE-----
 
 iQJIBAABCAAyFiEEWjIv1avE09usz9GqKAeTb5hNxaYFAl986v8UHGVoYWJrb3N0
 QHJlZGhhdC5jb20ACgkQKAeTb5hNxaaiAQ//Q81DvgnT6HkW4VleY6Qx3q8TfKfp
 m1H71YA1SKa1cuTbzDkb/7J5SYwrL/tWaLlcWwVIRs5LYoexAbGo2sOJnt85L/We
 WNUdPHyFUWuX/pXsX8F5du6x4xvXnd3I8HqSrjZf1LCUkdbfvQUK1yDG6gZJAfsC
 BCs4uJG2d3NE44mAqhhy3fl+qFs8p0FwBOFZ7M3UZXU5vgWhgZKpT8svUH4GuuXQ
 +0YHpJjvXHcug4cD2LpUuQ49j40BvXZFdoGDMpY6RJai/50kIw78PBenG6DX/QKR
 I0B03Qz7TMl8d5XAuDU2vfyMLW2Ow5rlxO56/fXkRYDEngb7pWwiH6KXENzY2jkm
 gfif8di8i/Kt9WKNJ8Eba7ulFmhRlybEFLSNCxUPJpq8LS0anRxHsuDS4GwgChWw
 Pe9sw1qSlf5iKqo1Erj9U3kWmFbZ7WvqApE3OCKEGbmxCe6beTcX4+1IaQ+01RYO
 or38ZGznCjiEmHaQBESzjV72TD+2gKDjYbcMMt5AWytBdtV3pY8JYXe/C0YeovT7
 X8KCZpizyyDWSmPq/+3Z2KVCCkX4+TjRaRyxkJ0ECCrCXsrCGt0F5rogV6Y58Rmh
 hBEW0ydpY3TjUIZG1rpaeeJSNMr+9O0Ut76OAowd86SYLsu6+jgG9pyzQ1S0pD24
 gP/2kKSr2xG1T9Q=
 =hTTy
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into staging

machine + QOM queue, 2020-10-06

* QOM documentation fixes and cleanups (Eduardo Habkost)
* user-mode: Prune build dependencies (Philippe Mathieu-Daudé)
* qom: Improve error message (Philippe Mathieu-Daudé)
* numa: hmat: require parent cache description before the next
  level one (Igor Mammedov)

# gpg: Signature made Tue 06 Oct 2020 23:09:03 BST
# gpg:                using RSA key 5A322FD5ABC4D3DBACCFD1AA2807936F984DC5A6
# gpg:                issuer "ehabkost@redhat.com"
# gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>" [full]
# Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF  D1AA 2807 936F 984D C5A6

* remotes/ehabkost/tags/machine-next-pull-request: (21 commits)
  numa: hmat: require parent cache description before the next level one
  kernel-doc: Remove $decl_type='type name' hack
  memory: Explicitly tag doc comments for structs
  qom: Explicitly tag doc comments for typedefs and structs
  kernel-doc: Handle function typedefs without asterisks
  kernel-doc: Handle function typedefs that return pointers
  docs/devel/qom: Avoid long lines
  docs/devel/qom: Remove usage of <code>
  docs/devel/qom: Use *emphasis* for emphasis
  docs/devel/qom: Fix indentation of code blocks
  docs/devel/qom: Fix indentation of bulleted list
  qom: Fix DECLARE_*CHECKER documentation
  qom: Improve error message displayed with missing object properties
  hw/core/cpu: Add missing 'exec/cpu-common.h' include
  hw/core/qdev-properties: Extract system-mode specific properties
  hw/core/qdev-properties: Export some integer-related functions
  hw/core/qdev-properties: Export qdev_prop_enum
  hw/core/qdev-properties: Export enum-related functions
  hw/core/qdev-properties: Fix code style
  hw/core/qdev-properties: Use qemu_strtoul() in set_pci_host_devaddr()
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-10-08 11:32:54 +01:00
commit a1d22c668a
11 changed files with 829 additions and 783 deletions

View file

@ -8,9 +8,9 @@ The QEMU Object Model provides a framework for registering user creatable
types and instantiating objects from those types. QOM provides the following types and instantiating objects from those types. QOM provides the following
features: features:
- System for dynamically registering types - System for dynamically registering types
- Support for single-inheritance of types - Support for single-inheritance of types
- Multiple inheritance of stateless interfaces - Multiple inheritance of stateless interfaces
.. code-block:: c .. code-block:: c
:caption: Creating a minimal type :caption: Creating a minimal type
@ -174,17 +174,17 @@ dynamically cast it to an object that implements the interface.
Methods Methods
======= =======
A <emphasis>method</emphasis> is a function within the namespace scope of A *method* is a function within the namespace scope of
a class. It usually operates on the object instance by passing it as a a class. It usually operates on the object instance by passing it as a
strongly-typed first argument. strongly-typed first argument.
If it does not operate on an object instance, it is dubbed If it does not operate on an object instance, it is dubbed
<emphasis>class method</emphasis>. *class method*.
Methods cannot be overloaded. That is, the #ObjectClass and method name Methods cannot be overloaded. That is, the #ObjectClass and method name
uniquely identity the function to be called; the signature does not vary uniquely identity the function to be called; the signature does not vary
except for trailing varargs. except for trailing varargs.
Methods are always <emphasis>virtual</emphasis>. Overriding a method in Methods are always *virtual*. Overriding a method in
#TypeInfo.class_init of a subclass leads to any user of the class obtained #TypeInfo.class_init of a subclass leads to any user of the class obtained
via OBJECT_GET_CLASS() accessing the overridden function. via OBJECT_GET_CLASS() accessing the overridden function.
The original function is not automatically invoked. It is the responsibility The original function is not automatically invoked. It is the responsibility
@ -284,28 +284,29 @@ in the header file:
.. code-block:: c .. code-block:: c
:caption: Declaring a simple type :caption: Declaring a simple type
OBJECT_DECLARE_SIMPLE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE) OBJECT_DECLARE_SIMPLE_TYPE(MyDevice, my_device,
MY_DEVICE, DEVICE)
This is equivalent to the following: This is equivalent to the following:
.. code-block:: c .. code-block:: c
:caption: Expansion from declaring a simple type :caption: Expansion from declaring a simple type
typedef struct MyDevice MyDevice; typedef struct MyDevice MyDevice;
typedef struct MyDeviceClass MyDeviceClass; typedef struct MyDeviceClass MyDeviceClass;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(MyDeviceClass, object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(MyDeviceClass, object_unref)
#define MY_DEVICE_GET_CLASS(void *obj) \ #define MY_DEVICE_GET_CLASS(void *obj) \
OBJECT_GET_CLASS(MyDeviceClass, obj, TYPE_MY_DEVICE) OBJECT_GET_CLASS(MyDeviceClass, obj, TYPE_MY_DEVICE)
#define MY_DEVICE_CLASS(void *klass) \ #define MY_DEVICE_CLASS(void *klass) \
OBJECT_CLASS_CHECK(MyDeviceClass, klass, TYPE_MY_DEVICE) OBJECT_CLASS_CHECK(MyDeviceClass, klass, TYPE_MY_DEVICE)
#define MY_DEVICE(void *obj) #define MY_DEVICE(void *obj)
OBJECT_CHECK(MyDevice, obj, TYPE_MY_DEVICE) OBJECT_CHECK(MyDevice, obj, TYPE_MY_DEVICE)
struct MyDeviceClass { struct MyDeviceClass {
DeviceClass parent_class; DeviceClass parent_class;
}; };
The 'struct MyDevice' needs to be declared separately. The 'struct MyDevice' needs to be declared separately.
If the type requires virtual functions to be declared in the class If the type requires virtual functions to be declared in the class
@ -319,33 +320,33 @@ In the simple case the OBJECT_DEFINE_TYPE macro is suitable:
.. code-block:: c .. code-block:: c
:caption: Defining a simple type :caption: Defining a simple type
OBJECT_DEFINE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE) OBJECT_DEFINE_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE)
This is equivalent to the following: This is equivalent to the following:
.. code-block:: c .. code-block:: c
:caption: Expansion from defining a simple type :caption: Expansion from defining a simple type
static void my_device_finalize(Object *obj); static void my_device_finalize(Object *obj);
static void my_device_class_init(ObjectClass *oc, void *data); static void my_device_class_init(ObjectClass *oc, void *data);
static void my_device_init(Object *obj); static void my_device_init(Object *obj);
static const TypeInfo my_device_info = { static const TypeInfo my_device_info = {
.parent = TYPE_DEVICE, .parent = TYPE_DEVICE,
.name = TYPE_MY_DEVICE, .name = TYPE_MY_DEVICE,
.instance_size = sizeof(MyDevice), .instance_size = sizeof(MyDevice),
.instance_init = my_device_init, .instance_init = my_device_init,
.instance_finalize = my_device_finalize, .instance_finalize = my_device_finalize,
.class_size = sizeof(MyDeviceClass), .class_size = sizeof(MyDeviceClass),
.class_init = my_device_class_init, .class_init = my_device_class_init,
}; };
static void static void
my_device_register_types(void) my_device_register_types(void)
{ {
type_register_static(&my_device_info); type_register_static(&my_device_info);
} }
type_init(my_device_register_types); type_init(my_device_register_types);
This is sufficient to get the type registered with the type This is sufficient to get the type registered with the type
system, and the three standard methods now need to be implemented system, and the three standard methods now need to be implemented
@ -358,9 +359,10 @@ This accepts an array of interface type names.
.. code-block:: c .. code-block:: c
:caption: Defining a simple type implementing interfaces :caption: Defining a simple type implementing interfaces
OBJECT_DEFINE_TYPE_WITH_INTERFACES(MyDevice, my_device, OBJECT_DEFINE_TYPE_WITH_INTERFACES(MyDevice, my_device,
MY_DEVICE, DEVICE, MY_DEVICE, DEVICE,
{ TYPE_USER_CREATABLE }, { NULL }) { TYPE_USER_CREATABLE },
{ NULL })
If the type is not intended to be instantiated, then then If the type is not intended to be instantiated, then then
the OBJECT_DEFINE_ABSTRACT_TYPE() macro can be used instead: the OBJECT_DEFINE_ABSTRACT_TYPE() macro can be used instead:
@ -368,7 +370,8 @@ the OBJECT_DEFINE_ABSTRACT_TYPE() macro can be used instead:
.. code-block:: c .. code-block:: c
:caption: Defining a simple abstract type :caption: Defining a simple abstract type
OBJECT_DEFINE_ABSTRACT_TYPE(MyDevice, my_device, MY_DEVICE, DEVICE) OBJECT_DEFINE_ABSTRACT_TYPE(MyDevice, my_device,
MY_DEVICE, DEVICE)

View file

@ -26,6 +26,7 @@
#include "qemu/log.h" #include "qemu/log.h"
#include "qemu/main-loop.h" #include "qemu/main-loop.h"
#include "exec/log.h" #include "exec/log.h"
#include "exec/cpu-common.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qemu/qemu-print.h" #include "qemu/qemu-print.h"
#include "sysemu/tcg.h" #include "sysemu/tcg.h"

View file

@ -424,7 +424,13 @@ void parse_numa_hmat_cache(MachineState *ms, NumaHmatCacheOptions *node,
} }
if ((node->level > 1) && if ((node->level > 1) &&
ms->numa_state->hmat_cache[node->node_id][node->level - 1] && ms->numa_state->hmat_cache[node->node_id][node->level - 1] == NULL) {
error_setg(errp, "Cache level=%u shall be defined first",
node->level - 1);
return;
}
if ((node->level > 1) &&
(node->size <= (node->size <=
ms->numa_state->hmat_cache[node->node_id][node->level - 1]->size)) { ms->numa_state->hmat_cache[node->node_id][node->level - 1]->size)) {
error_setg(errp, "Invalid size=%" PRIu64 ", the size of level=%" PRIu8 error_setg(errp, "Invalid size=%" PRIu64 ", the size of level=%" PRIu8

View file

@ -0,0 +1,30 @@
/*
* qdev property parsing
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*/
#ifndef HW_CORE_QDEV_PROP_INTERNAL_H
#define HW_CORE_QDEV_PROP_INTERNAL_H
void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp);
void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp);
void qdev_propinfo_set_default_value_enum(ObjectProperty *op,
const Property *prop);
void qdev_propinfo_set_default_value_int(ObjectProperty *op,
const Property *prop);
void qdev_propinfo_set_default_value_uint(ObjectProperty *op,
const Property *prop);
void qdev_propinfo_get_uint16(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp);
void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp);
void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp);
#endif

View file

@ -11,19 +11,25 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "audio/audio.h"
#include "net/net.h"
#include "hw/qdev-properties.h" #include "hw/qdev-properties.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "qapi/visitor.h"
#include "qapi/qapi-types-block.h"
#include "qapi/qapi-types-machine.h"
#include "qapi/qapi-types-migration.h"
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
#include "qemu/ctype.h"
#include "qemu/cutils.h"
#include "qemu/units.h"
#include "qemu/error-report.h"
#include "qdev-prop-internal.h"
#include "audio/audio.h"
#include "chardev/char-fe.h"
#include "sysemu/block-backend.h" #include "sysemu/block-backend.h"
#include "sysemu/blockdev.h" #include "sysemu/blockdev.h"
#include "hw/block/block.h" #include "net/net.h"
#include "net/hub.h" #include "hw/pci/pci.h"
#include "qapi/visitor.h"
#include "chardev/char-fe.h"
#include "sysemu/iothread.h"
#include "sysemu/tpm_backend.h"
static bool check_prop_still_unset(DeviceState *dev, const char *name, static bool check_prop_still_unset(DeviceState *dev, const char *name,
const void *old_val, const char *new_val, const void *old_val, const char *new_val,
@ -280,6 +286,96 @@ const PropertyInfo qdev_prop_chr = {
.release = release_chr, .release = release_chr,
}; };
/* --- mac address --- */
/*
* accepted syntax versions:
* 01:02:03:04:05:06
* 01-02-03-04-05-06
*/
static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
MACAddr *mac = qdev_get_prop_ptr(dev, prop);
char buffer[2 * 6 + 5 + 1];
char *p = buffer;
snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
mac->a[0], mac->a[1], mac->a[2],
mac->a[3], mac->a[4], mac->a[5]);
visit_type_str(v, name, &p, errp);
}
static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
MACAddr *mac = qdev_get_prop_ptr(dev, prop);
int i, pos;
char *str;
const char *p;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
if (!visit_type_str(v, name, &str, errp)) {
return;
}
for (i = 0, pos = 0; i < 6; i++, pos += 3) {
long val;
if (!qemu_isxdigit(str[pos])) {
goto inval;
}
if (!qemu_isxdigit(str[pos + 1])) {
goto inval;
}
if (i == 5) {
if (str[pos + 2] != '\0') {
goto inval;
}
} else {
if (str[pos + 2] != ':' && str[pos + 2] != '-') {
goto inval;
}
}
if (qemu_strtol(str + pos, &p, 16, &val) < 0 || val > 0xff) {
goto inval;
}
mac->a[i] = val;
}
g_free(str);
return;
inval:
error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
g_free(str);
}
const PropertyInfo qdev_prop_macaddr = {
.name = "str",
.description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
.get = get_mac,
.set = set_mac,
};
void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
const uint8_t *value)
{
char str[2 * 6 + 5 + 1];
snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
value[0], value[1], value[2], value[3], value[4], value[5]);
object_property_set_str(OBJECT(dev), name, str, &error_abort);
}
/* --- netdev device --- */ /* --- netdev device --- */
static void get_netdev(Object *obj, Visitor *v, const char *name, static void get_netdev(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp) void *opaque, Error **errp)
@ -465,3 +561,578 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
} }
nd->instantiated = 1; nd->instantiated = 1;
} }
/* --- lost tick policy --- */
QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
const PropertyInfo qdev_prop_losttickpolicy = {
.name = "LostTickPolicy",
.enum_table = &LostTickPolicy_lookup,
.get = qdev_propinfo_get_enum,
.set = qdev_propinfo_set_enum,
.set_default_value = qdev_propinfo_set_default_value_enum,
};
/* --- blocksize --- */
/* lower limit is sector size */
#define MIN_BLOCK_SIZE 512
#define MIN_BLOCK_SIZE_STR "512 B"
/*
* upper limit is arbitrary, 2 MiB looks sufficient for all sensible uses, and
* matches qcow2 cluster size limit
*/
#define MAX_BLOCK_SIZE (2 * MiB)
#define MAX_BLOCK_SIZE_STR "2 MiB"
static void set_blocksize(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
uint64_t value;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
if (!visit_type_size(v, name, &value, errp)) {
return;
}
/* value of 0 means "unset" */
if (value && (value < MIN_BLOCK_SIZE || value > MAX_BLOCK_SIZE)) {
error_setg(errp,
"Property %s.%s doesn't take value %" PRIu64
" (minimum: " MIN_BLOCK_SIZE_STR
", maximum: " MAX_BLOCK_SIZE_STR ")",
dev->id ? : "", name, value);
return;
}
/* We rely on power-of-2 blocksizes for bitmasks */
if ((value & (value - 1)) != 0) {
error_setg(errp,
"Property %s.%s doesn't take value '%" PRId64 "', "
"it's not a power of 2", dev->id ?: "", name, (int64_t)value);
return;
}
*ptr = value;
}
const PropertyInfo qdev_prop_blocksize = {
.name = "size",
.description = "A power of two between " MIN_BLOCK_SIZE_STR
" and " MAX_BLOCK_SIZE_STR,
.get = qdev_propinfo_get_size32,
.set = set_blocksize,
.set_default_value = qdev_propinfo_set_default_value_uint,
};
/* --- Block device error handling policy --- */
QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int));
const PropertyInfo qdev_prop_blockdev_on_error = {
.name = "BlockdevOnError",
.description = "Error handling policy, "
"report/ignore/enospc/stop/auto",
.enum_table = &BlockdevOnError_lookup,
.get = qdev_propinfo_get_enum,
.set = qdev_propinfo_set_enum,
.set_default_value = qdev_propinfo_set_default_value_enum,
};
/* --- BIOS CHS translation */
QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
const PropertyInfo qdev_prop_bios_chs_trans = {
.name = "BiosAtaTranslation",
.description = "Logical CHS translation algorithm, "
"auto/none/lba/large/rechs",
.enum_table = &BiosAtaTranslation_lookup,
.get = qdev_propinfo_get_enum,
.set = qdev_propinfo_set_enum,
.set_default_value = qdev_propinfo_set_default_value_enum,
};
/* --- FDC default drive types */
const PropertyInfo qdev_prop_fdc_drive_type = {
.name = "FdcDriveType",
.description = "FDC drive type, "
"144/288/120/none/auto",
.enum_table = &FloppyDriveType_lookup,
.get = qdev_propinfo_get_enum,
.set = qdev_propinfo_set_enum,
.set_default_value = qdev_propinfo_set_default_value_enum,
};
/* --- MultiFDCompression --- */
const PropertyInfo qdev_prop_multifd_compression = {
.name = "MultiFDCompression",
.description = "multifd_compression values, "
"none/zlib/zstd",
.enum_table = &MultiFDCompression_lookup,
.get = qdev_propinfo_get_enum,
.set = qdev_propinfo_set_enum,
.set_default_value = qdev_propinfo_set_default_value_enum,
};
/* --- Reserved Region --- */
/*
* Accepted syntax:
* <low address>:<high address>:<type>
* where low/high addresses are uint64_t in hexadecimal
* and type is a non-negative decimal integer
*/
static void get_reserved_region(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
ReservedRegion *rr = qdev_get_prop_ptr(dev, prop);
char buffer[64];
char *p = buffer;
int rc;
rc = snprintf(buffer, sizeof(buffer), "0x%"PRIx64":0x%"PRIx64":%u",
rr->low, rr->high, rr->type);
assert(rc < sizeof(buffer));
visit_type_str(v, name, &p, errp);
}
static void set_reserved_region(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
ReservedRegion *rr = qdev_get_prop_ptr(dev, prop);
Error *local_err = NULL;
const char *endptr;
char *str;
int ret;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
visit_type_str(v, name, &str, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
ret = qemu_strtou64(str, &endptr, 16, &rr->low);
if (ret) {
error_setg(errp, "start address of '%s'"
" must be a hexadecimal integer", name);
goto out;
}
if (*endptr != ':') {
goto separator_error;
}
ret = qemu_strtou64(endptr + 1, &endptr, 16, &rr->high);
if (ret) {
error_setg(errp, "end address of '%s'"
" must be a hexadecimal integer", name);
goto out;
}
if (*endptr != ':') {
goto separator_error;
}
ret = qemu_strtoui(endptr + 1, &endptr, 10, &rr->type);
if (ret) {
error_setg(errp, "type of '%s'"
" must be a non-negative decimal integer", name);
}
goto out;
separator_error:
error_setg(errp, "reserved region fields must be separated with ':'");
out:
g_free(str);
return;
}
const PropertyInfo qdev_prop_reserved_region = {
.name = "reserved_region",
.description = "Reserved Region, example: 0xFEE00000:0xFEEFFFFF:0",
.get = get_reserved_region,
.set = set_reserved_region,
};
/* --- pci address --- */
/*
* bus-local address, i.e. "$slot" or "$slot.$fn"
*/
static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
unsigned int slot, fn, n;
char *str;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
if (!visit_type_str(v, name, &str, NULL)) {
if (!visit_type_int32(v, name, &value, errp)) {
return;
}
if (value < -1 || value > 255) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
name ? name : "null", "pci_devfn");
return;
}
*ptr = value;
return;
}
if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
fn = 0;
if (sscanf(str, "%x%n", &slot, &n) != 1) {
goto invalid;
}
}
if (str[n] != '\0' || fn > 7 || slot > 31) {
goto invalid;
}
*ptr = slot << 3 | fn;
g_free(str);
return;
invalid:
error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
g_free(str);
}
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
size_t len)
{
int32_t *ptr = qdev_get_prop_ptr(dev, prop);
if (*ptr == -1) {
return snprintf(dest, len, "<unset>");
} else {
return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
}
}
const PropertyInfo qdev_prop_pci_devfn = {
.name = "int32",
.description = "Slot and optional function number, example: 06.0 or 06",
.print = print_pci_devfn,
.get = qdev_propinfo_get_int32,
.set = set_pci_devfn,
.set_default_value = qdev_propinfo_set_default_value_int,
};
/* --- pci host address --- */
static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
char buffer[] = "ffff:ff:ff.f";
char *p = buffer;
int rc = 0;
/*
* Catch "invalid" device reference from vfio-pci and allow the
* default buffer representing the non-existent device to be used.
*/
if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) {
rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d",
addr->domain, addr->bus, addr->slot, addr->function);
assert(rc == sizeof(buffer) - 1);
}
visit_type_str(v, name, &p, errp);
}
/*
* Parse [<domain>:]<bus>:<slot>.<func>
* if <domain> is not supplied, it's assumed to be 0.
*/
static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
char *str, *p;
const char *e;
unsigned long val;
unsigned long dom = 0, bus = 0;
unsigned int slot = 0, func = 0;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
if (!visit_type_str(v, name, &str, errp)) {
return;
}
p = str;
if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0xffff || e == p) {
goto inval;
}
if (*e != ':') {
goto inval;
}
bus = val;
p = (char *)e + 1;
if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) {
goto inval;
}
if (*e == ':') {
dom = bus;
bus = val;
p = (char *)e + 1;
if (qemu_strtoul(p, &e, 16, &val) < 0 || val > 0x1f || e == p) {
goto inval;
}
}
slot = val;
if (*e != '.') {
goto inval;
}
p = (char *)e + 1;
if (qemu_strtoul(p, &e, 10, &val) < 0 || val > 7 || e == p) {
goto inval;
}
func = val;
if (bus > 0xff) {
goto inval;
}
if (*e) {
goto inval;
}
addr->domain = dom;
addr->bus = bus;
addr->slot = slot;
addr->function = func;
g_free(str);
return;
inval:
error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
g_free(str);
}
const PropertyInfo qdev_prop_pci_host_devaddr = {
.name = "str",
.description = "Address (bus/device/function) of "
"the host device, example: 04:10.0",
.get = get_pci_host_devaddr,
.set = set_pci_host_devaddr,
};
/* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */
const PropertyInfo qdev_prop_off_auto_pcibar = {
.name = "OffAutoPCIBAR",
.description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5",
.enum_table = &OffAutoPCIBAR_lookup,
.get = qdev_propinfo_get_enum,
.set = qdev_propinfo_set_enum,
.set_default_value = qdev_propinfo_set_default_value_enum,
};
/* --- PCIELinkSpeed 2_5/5/8/16 -- */
static void get_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop);
int speed;
switch (*p) {
case QEMU_PCI_EXP_LNK_2_5GT:
speed = PCIE_LINK_SPEED_2_5;
break;
case QEMU_PCI_EXP_LNK_5GT:
speed = PCIE_LINK_SPEED_5;
break;
case QEMU_PCI_EXP_LNK_8GT:
speed = PCIE_LINK_SPEED_8;
break;
case QEMU_PCI_EXP_LNK_16GT:
speed = PCIE_LINK_SPEED_16;
break;
default:
/* Unreachable */
abort();
}
visit_type_enum(v, prop->name, &speed, prop->info->enum_table, errp);
}
static void set_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop);
int speed;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
if (!visit_type_enum(v, prop->name, &speed, prop->info->enum_table,
errp)) {
return;
}
switch (speed) {
case PCIE_LINK_SPEED_2_5:
*p = QEMU_PCI_EXP_LNK_2_5GT;
break;
case PCIE_LINK_SPEED_5:
*p = QEMU_PCI_EXP_LNK_5GT;
break;
case PCIE_LINK_SPEED_8:
*p = QEMU_PCI_EXP_LNK_8GT;
break;
case PCIE_LINK_SPEED_16:
*p = QEMU_PCI_EXP_LNK_16GT;
break;
default:
/* Unreachable */
abort();
}
}
const PropertyInfo qdev_prop_pcie_link_speed = {
.name = "PCIELinkSpeed",
.description = "2_5/5/8/16",
.enum_table = &PCIELinkSpeed_lookup,
.get = get_prop_pcielinkspeed,
.set = set_prop_pcielinkspeed,
.set_default_value = qdev_propinfo_set_default_value_enum,
};
/* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */
static void get_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop);
int width;
switch (*p) {
case QEMU_PCI_EXP_LNK_X1:
width = PCIE_LINK_WIDTH_1;
break;
case QEMU_PCI_EXP_LNK_X2:
width = PCIE_LINK_WIDTH_2;
break;
case QEMU_PCI_EXP_LNK_X4:
width = PCIE_LINK_WIDTH_4;
break;
case QEMU_PCI_EXP_LNK_X8:
width = PCIE_LINK_WIDTH_8;
break;
case QEMU_PCI_EXP_LNK_X12:
width = PCIE_LINK_WIDTH_12;
break;
case QEMU_PCI_EXP_LNK_X16:
width = PCIE_LINK_WIDTH_16;
break;
case QEMU_PCI_EXP_LNK_X32:
width = PCIE_LINK_WIDTH_32;
break;
default:
/* Unreachable */
abort();
}
visit_type_enum(v, prop->name, &width, prop->info->enum_table, errp);
}
static void set_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop);
int width;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
if (!visit_type_enum(v, prop->name, &width, prop->info->enum_table,
errp)) {
return;
}
switch (width) {
case PCIE_LINK_WIDTH_1:
*p = QEMU_PCI_EXP_LNK_X1;
break;
case PCIE_LINK_WIDTH_2:
*p = QEMU_PCI_EXP_LNK_X2;
break;
case PCIE_LINK_WIDTH_4:
*p = QEMU_PCI_EXP_LNK_X4;
break;
case PCIE_LINK_WIDTH_8:
*p = QEMU_PCI_EXP_LNK_X8;
break;
case PCIE_LINK_WIDTH_12:
*p = QEMU_PCI_EXP_LNK_X12;
break;
case PCIE_LINK_WIDTH_16:
*p = QEMU_PCI_EXP_LNK_X16;
break;
case PCIE_LINK_WIDTH_32:
*p = QEMU_PCI_EXP_LNK_X32;
break;
default:
/* Unreachable */
abort();
}
}
const PropertyInfo qdev_prop_pcie_link_width = {
.name = "PCIELinkWidth",
.description = "1/2/4/8/12/16/32",
.enum_table = &PCIELinkWidth_lookup,
.get = get_prop_pcielinkwidth,
.set = set_prop_pcielinkwidth,
.set_default_value = qdev_propinfo_set_default_value_enum,
};

View file

@ -1,22 +1,15 @@
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "net/net.h"
#include "hw/qdev-properties.h" #include "hw/qdev-properties.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "hw/pci/pci.h"
#include "qapi/qapi-types-block.h"
#include "qapi/qapi-types-machine.h"
#include "qapi/qapi-types-misc.h" #include "qapi/qapi-types-misc.h"
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
#include "qemu/ctype.h" #include "qemu/ctype.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qapi/qapi-types-migration.h"
#include "hw/block/block.h"
#include "net/hub.h"
#include "qapi/visitor.h" #include "qapi/visitor.h"
#include "chardev/char.h"
#include "qemu/uuid.h" #include "qemu/uuid.h"
#include "qemu/units.h" #include "qemu/units.h"
#include "qemu/cutils.h" #include "qemu/cutils.h"
#include "qdev-prop-internal.h"
void qdev_prop_set_after_realize(DeviceState *dev, const char *name, void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
Error **errp) Error **errp)
@ -52,8 +45,8 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
return ptr; return ptr;
} }
static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque, void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name,
Error **errp) void *opaque, Error **errp)
{ {
DeviceState *dev = DEVICE(obj); DeviceState *dev = DEVICE(obj);
Property *prop = opaque; Property *prop = opaque;
@ -62,8 +55,8 @@ static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque,
visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp); visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
} }
static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque, void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name,
Error **errp) void *opaque, Error **errp)
{ {
DeviceState *dev = DEVICE(obj); DeviceState *dev = DEVICE(obj);
Property *prop = opaque; Property *prop = opaque;
@ -77,12 +70,20 @@ static void set_enum(Object *obj, Visitor *v, const char *name, void *opaque,
visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp); visit_type_enum(v, prop->name, ptr, prop->info->enum_table, errp);
} }
static void set_default_value_enum(ObjectProperty *op, const Property *prop) void qdev_propinfo_set_default_value_enum(ObjectProperty *op,
const Property *prop)
{ {
object_property_set_default_str(op, object_property_set_default_str(op,
qapi_enum_lookup(prop->info->enum_table, prop->defval.i)); qapi_enum_lookup(prop->info->enum_table, prop->defval.i));
} }
const PropertyInfo qdev_prop_enum = {
.name = "enum",
.get = qdev_propinfo_get_enum,
.set = qdev_propinfo_set_enum,
.set_default_value = qdev_propinfo_set_default_value_enum,
};
/* Bit */ /* Bit */
static uint32_t qdev_get_prop_mask(Property *prop) static uint32_t qdev_get_prop_mask(Property *prop)
@ -261,12 +262,14 @@ static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
visit_type_uint8(v, name, ptr, errp); visit_type_uint8(v, name, ptr, errp);
} }
static void set_default_value_int(ObjectProperty *op, const Property *prop) void qdev_propinfo_set_default_value_int(ObjectProperty *op,
const Property *prop)
{ {
object_property_set_default_int(op, prop->defval.i); object_property_set_default_int(op, prop->defval.i);
} }
static void set_default_value_uint(ObjectProperty *op, const Property *prop) void qdev_propinfo_set_default_value_uint(ObjectProperty *op,
const Property *prop)
{ {
object_property_set_default_uint(op, prop->defval.u); object_property_set_default_uint(op, prop->defval.u);
} }
@ -275,13 +278,13 @@ const PropertyInfo qdev_prop_uint8 = {
.name = "uint8", .name = "uint8",
.get = get_uint8, .get = get_uint8,
.set = set_uint8, .set = set_uint8,
.set_default_value = set_default_value_uint, .set_default_value = qdev_propinfo_set_default_value_uint,
}; };
/* --- 16bit integer --- */ /* --- 16bit integer --- */
static void get_uint16(Object *obj, Visitor *v, const char *name, void qdev_propinfo_get_uint16(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp) void *opaque, Error **errp)
{ {
DeviceState *dev = DEVICE(obj); DeviceState *dev = DEVICE(obj);
Property *prop = opaque; Property *prop = opaque;
@ -307,9 +310,9 @@ static void set_uint16(Object *obj, Visitor *v, const char *name,
const PropertyInfo qdev_prop_uint16 = { const PropertyInfo qdev_prop_uint16 = {
.name = "uint16", .name = "uint16",
.get = get_uint16, .get = qdev_propinfo_get_uint16,
.set = set_uint16, .set = set_uint16,
.set_default_value = set_default_value_uint, .set_default_value = qdev_propinfo_set_default_value_uint,
}; };
/* --- 32bit integer --- */ /* --- 32bit integer --- */
@ -339,8 +342,8 @@ static void set_uint32(Object *obj, Visitor *v, const char *name,
visit_type_uint32(v, name, ptr, errp); visit_type_uint32(v, name, ptr, errp);
} }
static void get_int32(Object *obj, Visitor *v, const char *name, void *opaque, void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name,
Error **errp) void *opaque, Error **errp)
{ {
DeviceState *dev = DEVICE(obj); DeviceState *dev = DEVICE(obj);
Property *prop = opaque; Property *prop = opaque;
@ -368,14 +371,14 @@ const PropertyInfo qdev_prop_uint32 = {
.name = "uint32", .name = "uint32",
.get = get_uint32, .get = get_uint32,
.set = set_uint32, .set = set_uint32,
.set_default_value = set_default_value_uint, .set_default_value = qdev_propinfo_set_default_value_uint,
}; };
const PropertyInfo qdev_prop_int32 = { const PropertyInfo qdev_prop_int32 = {
.name = "int32", .name = "int32",
.get = get_int32, .get = qdev_propinfo_get_int32,
.set = set_int32, .set = set_int32,
.set_default_value = set_default_value_int, .set_default_value = qdev_propinfo_set_default_value_int,
}; };
/* --- 64bit integer --- */ /* --- 64bit integer --- */
@ -434,14 +437,14 @@ const PropertyInfo qdev_prop_uint64 = {
.name = "uint64", .name = "uint64",
.get = get_uint64, .get = get_uint64,
.set = set_uint64, .set = set_uint64,
.set_default_value = set_default_value_uint, .set_default_value = qdev_propinfo_set_default_value_uint,
}; };
const PropertyInfo qdev_prop_int64 = { const PropertyInfo qdev_prop_int64 = {
.name = "int64", .name = "int64",
.get = get_int64, .get = get_int64,
.set = set_int64, .set = set_int64,
.set_default_value = set_default_value_int, .set_default_value = qdev_propinfo_set_default_value_int,
}; };
/* --- string --- */ /* --- string --- */
@ -494,318 +497,21 @@ const PropertyInfo qdev_prop_string = {
.set = set_string, .set = set_string,
}; };
/* --- mac address --- */
/*
* accepted syntax versions:
* 01:02:03:04:05:06
* 01-02-03-04-05-06
*/
static void get_mac(Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
MACAddr *mac = qdev_get_prop_ptr(dev, prop);
char buffer[2 * 6 + 5 + 1];
char *p = buffer;
snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
mac->a[0], mac->a[1], mac->a[2],
mac->a[3], mac->a[4], mac->a[5]);
visit_type_str(v, name, &p, errp);
}
static void set_mac(Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
MACAddr *mac = qdev_get_prop_ptr(dev, prop);
int i, pos;
char *str, *p;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
if (!visit_type_str(v, name, &str, errp)) {
return;
}
for (i = 0, pos = 0; i < 6; i++, pos += 3) {
if (!qemu_isxdigit(str[pos])) {
goto inval;
}
if (!qemu_isxdigit(str[pos+1])) {
goto inval;
}
if (i == 5) {
if (str[pos+2] != '\0') {
goto inval;
}
} else {
if (str[pos+2] != ':' && str[pos+2] != '-') {
goto inval;
}
}
mac->a[i] = strtol(str+pos, &p, 16);
}
g_free(str);
return;
inval:
error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
g_free(str);
}
const PropertyInfo qdev_prop_macaddr = {
.name = "str",
.description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
.get = get_mac,
.set = set_mac,
};
/* --- Reserved Region --- */
/*
* Accepted syntax:
* <low address>:<high address>:<type>
* where low/high addresses are uint64_t in hexadecimal
* and type is a non-negative decimal integer
*/
static void get_reserved_region(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
ReservedRegion *rr = qdev_get_prop_ptr(dev, prop);
char buffer[64];
char *p = buffer;
int rc;
rc = snprintf(buffer, sizeof(buffer), "0x%"PRIx64":0x%"PRIx64":%u",
rr->low, rr->high, rr->type);
assert(rc < sizeof(buffer));
visit_type_str(v, name, &p, errp);
}
static void set_reserved_region(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
ReservedRegion *rr = qdev_get_prop_ptr(dev, prop);
Error *local_err = NULL;
const char *endptr;
char *str;
int ret;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
visit_type_str(v, name, &str, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
ret = qemu_strtou64(str, &endptr, 16, &rr->low);
if (ret) {
error_setg(errp, "start address of '%s'"
" must be a hexadecimal integer", name);
goto out;
}
if (*endptr != ':') {
goto separator_error;
}
ret = qemu_strtou64(endptr + 1, &endptr, 16, &rr->high);
if (ret) {
error_setg(errp, "end address of '%s'"
" must be a hexadecimal integer", name);
goto out;
}
if (*endptr != ':') {
goto separator_error;
}
ret = qemu_strtoui(endptr + 1, &endptr, 10, &rr->type);
if (ret) {
error_setg(errp, "type of '%s'"
" must be a non-negative decimal integer", name);
}
goto out;
separator_error:
error_setg(errp, "reserved region fields must be separated with ':'");
out:
g_free(str);
return;
}
const PropertyInfo qdev_prop_reserved_region = {
.name = "reserved_region",
.description = "Reserved Region, example: 0xFEE00000:0xFEEFFFFF:0",
.get = get_reserved_region,
.set = set_reserved_region,
};
/* --- on/off/auto --- */ /* --- on/off/auto --- */
const PropertyInfo qdev_prop_on_off_auto = { const PropertyInfo qdev_prop_on_off_auto = {
.name = "OnOffAuto", .name = "OnOffAuto",
.description = "on/off/auto", .description = "on/off/auto",
.enum_table = &OnOffAuto_lookup, .enum_table = &OnOffAuto_lookup,
.get = get_enum, .get = qdev_propinfo_get_enum,
.set = set_enum, .set = qdev_propinfo_set_enum,
.set_default_value = set_default_value_enum, .set_default_value = qdev_propinfo_set_default_value_enum,
};
/* --- lost tick policy --- */
QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
const PropertyInfo qdev_prop_losttickpolicy = {
.name = "LostTickPolicy",
.enum_table = &LostTickPolicy_lookup,
.get = get_enum,
.set = set_enum,
.set_default_value = set_default_value_enum,
};
/* --- Block device error handling policy --- */
QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int));
const PropertyInfo qdev_prop_blockdev_on_error = {
.name = "BlockdevOnError",
.description = "Error handling policy, "
"report/ignore/enospc/stop/auto",
.enum_table = &BlockdevOnError_lookup,
.get = get_enum,
.set = set_enum,
.set_default_value = set_default_value_enum,
};
/* --- BIOS CHS translation */
QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
const PropertyInfo qdev_prop_bios_chs_trans = {
.name = "BiosAtaTranslation",
.description = "Logical CHS translation algorithm, "
"auto/none/lba/large/rechs",
.enum_table = &BiosAtaTranslation_lookup,
.get = get_enum,
.set = set_enum,
.set_default_value = set_default_value_enum,
};
/* --- FDC default drive types */
const PropertyInfo qdev_prop_fdc_drive_type = {
.name = "FdcDriveType",
.description = "FDC drive type, "
"144/288/120/none/auto",
.enum_table = &FloppyDriveType_lookup,
.get = get_enum,
.set = set_enum,
.set_default_value = set_default_value_enum,
};
/* --- MultiFDCompression --- */
const PropertyInfo qdev_prop_multifd_compression = {
.name = "MultiFDCompression",
.description = "multifd_compression values, "
"none/zlib/zstd",
.enum_table = &MultiFDCompression_lookup,
.get = get_enum,
.set = set_enum,
.set_default_value = set_default_value_enum,
};
/* --- pci address --- */
/*
* bus-local address, i.e. "$slot" or "$slot.$fn"
*/
static void set_pci_devfn(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
unsigned int slot, fn, n;
char *str;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
if (!visit_type_str(v, name, &str, NULL)) {
if (!visit_type_int32(v, name, &value, errp)) {
return;
}
if (value < -1 || value > 255) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
name ? name : "null", "pci_devfn");
return;
}
*ptr = value;
return;
}
if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
fn = 0;
if (sscanf(str, "%x%n", &slot, &n) != 1) {
goto invalid;
}
}
if (str[n] != '\0' || fn > 7 || slot > 31) {
goto invalid;
}
*ptr = slot << 3 | fn;
g_free(str);
return;
invalid:
error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
g_free(str);
}
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
size_t len)
{
int32_t *ptr = qdev_get_prop_ptr(dev, prop);
if (*ptr == -1) {
return snprintf(dest, len, "<unset>");
} else {
return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
}
}
const PropertyInfo qdev_prop_pci_devfn = {
.name = "int32",
.description = "Slot and optional function number, example: 06.0 or 06",
.print = print_pci_devfn,
.get = get_int32,
.set = set_pci_devfn,
.set_default_value = set_default_value_int,
}; };
/* --- 32bit unsigned int 'size' type --- */ /* --- 32bit unsigned int 'size' type --- */
static void get_size32(Object *obj, Visitor *v, const char *name, void *opaque, void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name,
Error **errp) void *opaque, Error **errp)
{ {
DeviceState *dev = DEVICE(obj); DeviceState *dev = DEVICE(obj);
Property *prop = opaque; Property *prop = opaque;
@ -845,179 +551,9 @@ static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,
const PropertyInfo qdev_prop_size32 = { const PropertyInfo qdev_prop_size32 = {
.name = "size", .name = "size",
.get = get_size32, .get = qdev_propinfo_get_size32,
.set = set_size32, .set = set_size32,
.set_default_value = set_default_value_uint, .set_default_value = qdev_propinfo_set_default_value_uint,
};
/* --- blocksize --- */
/* lower limit is sector size */
#define MIN_BLOCK_SIZE 512
#define MIN_BLOCK_SIZE_STR "512 B"
/*
* upper limit is arbitrary, 2 MiB looks sufficient for all sensible uses, and
* matches qcow2 cluster size limit
*/
#define MAX_BLOCK_SIZE (2 * MiB)
#define MAX_BLOCK_SIZE_STR "2 MiB"
static void set_blocksize(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
uint64_t value;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
if (!visit_type_size(v, name, &value, errp)) {
return;
}
/* value of 0 means "unset" */
if (value && (value < MIN_BLOCK_SIZE || value > MAX_BLOCK_SIZE)) {
error_setg(errp,
"Property %s.%s doesn't take value %" PRIu64
" (minimum: " MIN_BLOCK_SIZE_STR
", maximum: " MAX_BLOCK_SIZE_STR ")",
dev->id ? : "", name, value);
return;
}
/* We rely on power-of-2 blocksizes for bitmasks */
if ((value & (value - 1)) != 0) {
error_setg(errp,
"Property %s.%s doesn't take value '%" PRId64 "', it's not a power of 2",
dev->id ?: "", name, (int64_t)value);
return;
}
*ptr = value;
}
const PropertyInfo qdev_prop_blocksize = {
.name = "size",
.description = "A power of two between " MIN_BLOCK_SIZE_STR
" and " MAX_BLOCK_SIZE_STR,
.get = get_size32,
.set = set_blocksize,
.set_default_value = set_default_value_uint,
};
/* --- pci host address --- */
static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
char buffer[] = "ffff:ff:ff.f";
char *p = buffer;
int rc = 0;
/*
* Catch "invalid" device reference from vfio-pci and allow the
* default buffer representing the non-existent device to be used.
*/
if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) {
rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d",
addr->domain, addr->bus, addr->slot, addr->function);
assert(rc == sizeof(buffer) - 1);
}
visit_type_str(v, name, &p, errp);
}
/*
* Parse [<domain>:]<bus>:<slot>.<func>
* if <domain> is not supplied, it's assumed to be 0.
*/
static void set_pci_host_devaddr(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
char *str, *p;
char *e;
unsigned long val;
unsigned long dom = 0, bus = 0;
unsigned int slot = 0, func = 0;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
if (!visit_type_str(v, name, &str, errp)) {
return;
}
p = str;
val = strtoul(p, &e, 16);
if (e == p || *e != ':') {
goto inval;
}
bus = val;
p = e + 1;
val = strtoul(p, &e, 16);
if (e == p) {
goto inval;
}
if (*e == ':') {
dom = bus;
bus = val;
p = e + 1;
val = strtoul(p, &e, 16);
if (e == p) {
goto inval;
}
}
slot = val;
if (*e != '.') {
goto inval;
}
p = e + 1;
val = strtoul(p, &e, 10);
if (e == p) {
goto inval;
}
func = val;
if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
goto inval;
}
if (*e) {
goto inval;
}
addr->domain = dom;
addr->bus = bus;
addr->slot = slot;
addr->function = func;
g_free(str);
return;
inval:
error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
g_free(str);
}
const PropertyInfo qdev_prop_pci_host_devaddr = {
.name = "str",
.description = "Address (bus/device/function) of "
"the host device, example: 04:10.0",
.get = get_pci_host_devaddr,
.set = set_pci_host_devaddr,
}; };
/* --- UUID --- */ /* --- UUID --- */
@ -1175,7 +711,7 @@ const PropertyInfo qdev_prop_arraylen = {
.name = "uint32", .name = "uint32",
.get = get_uint32, .get = get_uint32,
.set = set_prop_arraylen, .set = set_prop_arraylen,
.set_default_value = set_default_value_uint, .set_default_value = qdev_propinfo_set_default_value_uint,
}; };
/* --- public helpers --- */ /* --- public helpers --- */
@ -1269,16 +805,6 @@ void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
object_property_set_str(OBJECT(dev), name, value, &error_abort); object_property_set_str(OBJECT(dev), name, value, &error_abort);
} }
void qdev_prop_set_macaddr(DeviceState *dev, const char *name,
const uint8_t *value)
{
char str[2 * 6 + 5 + 1];
snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
value[0], value[1], value[2], value[3], value[4], value[5]);
object_property_set_str(OBJECT(dev), name, str, &error_abort);
}
void qdev_prop_set_enum(DeviceState *dev, const char *name, int value) void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
{ {
Property *prop; Property *prop;
@ -1386,7 +912,7 @@ const PropertyInfo qdev_prop_size = {
.name = "size", .name = "size",
.get = get_size, .get = get_size,
.set = set_size, .set = set_size,
.set_default_value = set_default_value_uint, .set_default_value = qdev_propinfo_set_default_value_uint,
}; };
/* --- object link property --- */ /* --- object link property --- */
@ -1403,186 +929,3 @@ const PropertyInfo qdev_prop_link = {
.name = "link", .name = "link",
.create = create_link_property, .create = create_link_property,
}; };
/* --- OffAutoPCIBAR off/auto/bar0/bar1/bar2/bar3/bar4/bar5 --- */
const PropertyInfo qdev_prop_off_auto_pcibar = {
.name = "OffAutoPCIBAR",
.description = "off/auto/bar0/bar1/bar2/bar3/bar4/bar5",
.enum_table = &OffAutoPCIBAR_lookup,
.get = get_enum,
.set = set_enum,
.set_default_value = set_default_value_enum,
};
/* --- PCIELinkSpeed 2_5/5/8/16 -- */
static void get_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop);
int speed;
switch (*p) {
case QEMU_PCI_EXP_LNK_2_5GT:
speed = PCIE_LINK_SPEED_2_5;
break;
case QEMU_PCI_EXP_LNK_5GT:
speed = PCIE_LINK_SPEED_5;
break;
case QEMU_PCI_EXP_LNK_8GT:
speed = PCIE_LINK_SPEED_8;
break;
case QEMU_PCI_EXP_LNK_16GT:
speed = PCIE_LINK_SPEED_16;
break;
default:
/* Unreachable */
abort();
}
visit_type_enum(v, prop->name, &speed, prop->info->enum_table, errp);
}
static void set_prop_pcielinkspeed(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
PCIExpLinkSpeed *p = qdev_get_prop_ptr(dev, prop);
int speed;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
if (!visit_type_enum(v, prop->name, &speed, prop->info->enum_table,
errp)) {
return;
}
switch (speed) {
case PCIE_LINK_SPEED_2_5:
*p = QEMU_PCI_EXP_LNK_2_5GT;
break;
case PCIE_LINK_SPEED_5:
*p = QEMU_PCI_EXP_LNK_5GT;
break;
case PCIE_LINK_SPEED_8:
*p = QEMU_PCI_EXP_LNK_8GT;
break;
case PCIE_LINK_SPEED_16:
*p = QEMU_PCI_EXP_LNK_16GT;
break;
default:
/* Unreachable */
abort();
}
}
const PropertyInfo qdev_prop_pcie_link_speed = {
.name = "PCIELinkSpeed",
.description = "2_5/5/8/16",
.enum_table = &PCIELinkSpeed_lookup,
.get = get_prop_pcielinkspeed,
.set = set_prop_pcielinkspeed,
.set_default_value = set_default_value_enum,
};
/* --- PCIELinkWidth 1/2/4/8/12/16/32 -- */
static void get_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop);
int width;
switch (*p) {
case QEMU_PCI_EXP_LNK_X1:
width = PCIE_LINK_WIDTH_1;
break;
case QEMU_PCI_EXP_LNK_X2:
width = PCIE_LINK_WIDTH_2;
break;
case QEMU_PCI_EXP_LNK_X4:
width = PCIE_LINK_WIDTH_4;
break;
case QEMU_PCI_EXP_LNK_X8:
width = PCIE_LINK_WIDTH_8;
break;
case QEMU_PCI_EXP_LNK_X12:
width = PCIE_LINK_WIDTH_12;
break;
case QEMU_PCI_EXP_LNK_X16:
width = PCIE_LINK_WIDTH_16;
break;
case QEMU_PCI_EXP_LNK_X32:
width = PCIE_LINK_WIDTH_32;
break;
default:
/* Unreachable */
abort();
}
visit_type_enum(v, prop->name, &width, prop->info->enum_table, errp);
}
static void set_prop_pcielinkwidth(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
PCIExpLinkWidth *p = qdev_get_prop_ptr(dev, prop);
int width;
if (dev->realized) {
qdev_prop_set_after_realize(dev, name, errp);
return;
}
if (!visit_type_enum(v, prop->name, &width, prop->info->enum_table,
errp)) {
return;
}
switch (width) {
case PCIE_LINK_WIDTH_1:
*p = QEMU_PCI_EXP_LNK_X1;
break;
case PCIE_LINK_WIDTH_2:
*p = QEMU_PCI_EXP_LNK_X2;
break;
case PCIE_LINK_WIDTH_4:
*p = QEMU_PCI_EXP_LNK_X4;
break;
case PCIE_LINK_WIDTH_8:
*p = QEMU_PCI_EXP_LNK_X8;
break;
case PCIE_LINK_WIDTH_12:
*p = QEMU_PCI_EXP_LNK_X12;
break;
case PCIE_LINK_WIDTH_16:
*p = QEMU_PCI_EXP_LNK_X16;
break;
case PCIE_LINK_WIDTH_32:
*p = QEMU_PCI_EXP_LNK_X32;
break;
default:
/* Unreachable */
abort();
}
}
const PropertyInfo qdev_prop_pcie_link_width = {
.name = "PCIELinkWidth",
.description = "1/2/4/8/12/16/32",
.enum_table = &PCIELinkWidth_lookup,
.get = get_prop_pcielinkwidth,
.set = set_prop_pcielinkwidth,
.set_default_value = set_default_value_enum,
};

View file

@ -443,7 +443,7 @@ struct IOMMUMemoryRegion {
QLIST_FOREACH((n), &(mr)->iommu_notify, node) QLIST_FOREACH((n), &(mr)->iommu_notify, node)
/** /**
* MemoryListener: callbacks structure for updates to the physical memory map * struct MemoryListener: callbacks structure for updates to the physical memory map
* *
* Allows a component to adjust to changes in the guest-visible memory map. * Allows a component to adjust to changes in the guest-visible memory map.
* Use with memory_listener_register() and memory_listener_unregister(). * Use with memory_listener_register() and memory_listener_unregister().
@ -681,7 +681,7 @@ struct MemoryListener {
}; };
/** /**
* AddressSpace: describes a mapping of addresses to #MemoryRegion objects * struct AddressSpace: describes a mapping of addresses to #MemoryRegion objects
*/ */
struct AddressSpace { struct AddressSpace {
/* private: */ /* private: */
@ -721,7 +721,7 @@ static inline FlatView *address_space_to_flatview(AddressSpace *as)
/** /**
* MemoryRegionSection: describes a fragment of a #MemoryRegion * struct MemoryRegionSection: describes a fragment of a #MemoryRegion
* *
* @mr: the region, or %NULL if empty * @mr: the region, or %NULL if empty
* @fv: the flat view of the address space the region is mapped in * @fv: the flat view of the address space the region is mapped in

View file

@ -8,6 +8,7 @@
extern const PropertyInfo qdev_prop_bit; extern const PropertyInfo qdev_prop_bit;
extern const PropertyInfo qdev_prop_bit64; extern const PropertyInfo qdev_prop_bit64;
extern const PropertyInfo qdev_prop_bool; extern const PropertyInfo qdev_prop_bool;
extern const PropertyInfo qdev_prop_enum;
extern const PropertyInfo qdev_prop_uint8; extern const PropertyInfo qdev_prop_uint8;
extern const PropertyInfo qdev_prop_uint16; extern const PropertyInfo qdev_prop_uint16;
extern const PropertyInfo qdev_prop_uint32; extern const PropertyInfo qdev_prop_uint32;

View file

@ -31,7 +31,7 @@ typedef struct InterfaceInfo InterfaceInfo;
typedef struct ObjectProperty ObjectProperty; typedef struct ObjectProperty ObjectProperty;
/** /**
* ObjectPropertyAccessor: * typedef ObjectPropertyAccessor:
* @obj: the object that owns the property * @obj: the object that owns the property
* @v: the visitor that contains the property data * @v: the visitor that contains the property data
* @name: the name of the property * @name: the name of the property
@ -47,7 +47,7 @@ typedef void (ObjectPropertyAccessor)(Object *obj,
Error **errp); Error **errp);
/** /**
* ObjectPropertyResolve: * typedef ObjectPropertyResolve:
* @obj: the object that owns the property * @obj: the object that owns the property
* @opaque: the opaque registered with the property * @opaque: the opaque registered with the property
* @part: the name of the property * @part: the name of the property
@ -66,7 +66,7 @@ typedef Object *(ObjectPropertyResolve)(Object *obj,
const char *part); const char *part);
/** /**
* ObjectPropertyRelease: * typedef ObjectPropertyRelease:
* @obj: the object that owns the property * @obj: the object that owns the property
* @name: the name of the property * @name: the name of the property
* @opaque: the opaque registered with the property * @opaque: the opaque registered with the property
@ -78,7 +78,7 @@ typedef void (ObjectPropertyRelease)(Object *obj,
void *opaque); void *opaque);
/** /**
* ObjectPropertyInit: * typedef ObjectPropertyInit:
* @obj: the object that owns the property * @obj: the object that owns the property
* @prop: the property to set * @prop: the property to set
* *
@ -101,7 +101,7 @@ struct ObjectProperty
}; };
/** /**
* ObjectUnparent: * typedef ObjectUnparent:
* @obj: the object that is being removed from the composition tree * @obj: the object that is being removed from the composition tree
* *
* Called when an object is being removed from the QOM composition tree. * Called when an object is being removed from the QOM composition tree.
@ -110,7 +110,7 @@ struct ObjectProperty
typedef void (ObjectUnparent)(Object *obj); typedef void (ObjectUnparent)(Object *obj);
/** /**
* ObjectFree: * typedef ObjectFree:
* @obj: the object being freed * @obj: the object being freed
* *
* Called when an object's last reference is removed. * Called when an object's last reference is removed.
@ -120,7 +120,7 @@ typedef void (ObjectFree)(void *obj);
#define OBJECT_CLASS_CAST_CACHE 4 #define OBJECT_CLASS_CAST_CACHE 4
/** /**
* ObjectClass: * struct ObjectClass:
* *
* The base for all classes. The only thing that #ObjectClass contains is an * The base for all classes. The only thing that #ObjectClass contains is an
* integer type handle. * integer type handle.
@ -140,7 +140,7 @@ struct ObjectClass
}; };
/** /**
* Object: * struct Object:
* *
* The base for all objects. The first member of this object is a pointer to * The base for all objects. The first member of this object is a pointer to
* a #ObjectClass. Since C guarantees that the first member of a structure * a #ObjectClass. Since C guarantees that the first member of a structure
@ -170,7 +170,7 @@ struct Object
* Direct usage of this macro should be avoided, and the complete * Direct usage of this macro should be avoided, and the complete
* OBJECT_DECLARE_TYPE macro is recommended instead. * OBJECT_DECLARE_TYPE macro is recommended instead.
* *
* This macro will provide the three standard type cast functions for a * This macro will provide the instance type cast functions for a
* QOM type. * QOM type.
*/ */
#define DECLARE_INSTANCE_CHECKER(InstanceType, OBJ_NAME, TYPENAME) \ #define DECLARE_INSTANCE_CHECKER(InstanceType, OBJ_NAME, TYPENAME) \
@ -187,7 +187,7 @@ struct Object
* Direct usage of this macro should be avoided, and the complete * Direct usage of this macro should be avoided, and the complete
* OBJECT_DECLARE_TYPE macro is recommended instead. * OBJECT_DECLARE_TYPE macro is recommended instead.
* *
* This macro will provide the three standard type cast functions for a * This macro will provide the class type cast functions for a
* QOM type. * QOM type.
*/ */
#define DECLARE_CLASS_CHECKERS(ClassType, OBJ_NAME, TYPENAME) \ #define DECLARE_CLASS_CHECKERS(ClassType, OBJ_NAME, TYPENAME) \
@ -370,7 +370,7 @@ struct Object
true, { NULL }) true, { NULL })
/** /**
* TypeInfo: * struct TypeInfo:
* @name: The name of the type. * @name: The name of the type.
* @parent: The name of the parent type. * @parent: The name of the parent type.
* @instance_size: The size of the object (derivative of #Object). If * @instance_size: The size of the object (derivative of #Object). If
@ -496,7 +496,7 @@ struct TypeInfo
OBJECT_CLASS_CHECK(class, object_get_class(OBJECT(obj)), name) OBJECT_CLASS_CHECK(class, object_get_class(OBJECT(obj)), name)
/** /**
* InterfaceInfo: * struct InterfaceInfo:
* @type: The name of the interface. * @type: The name of the interface.
* *
* The information associated with an interface. * The information associated with an interface.
@ -506,7 +506,7 @@ struct InterfaceInfo {
}; };
/** /**
* InterfaceClass: * struct InterfaceClass:
* @parent_class: the base class * @parent_class: the base class
* *
* The class for all interfaces. Subclasses of this class should only add * The class for all interfaces. Subclasses of this class should only add
@ -1256,7 +1256,7 @@ char *object_property_get_str(Object *obj, const char *name,
* Writes an object's canonical path to a property. * Writes an object's canonical path to a property.
* *
* If the link property was created with * If the link property was created with
* <code>OBJ_PROP_LINK_STRONG</code> bit, the old target object is * %OBJ_PROP_LINK_STRONG bit, the old target object is
* unreferenced, and a reference is added to the new target object. * unreferenced, and a reference is added to the new target object.
* *
* Returns: %true on success, %false on failure. * Returns: %true on success, %false on failure.
@ -1603,16 +1603,16 @@ void object_property_allow_set_link(const Object *obj, const char *name,
* *
* Links form the graph in the object model. * Links form the graph in the object model.
* *
* The <code>@check()</code> callback is invoked when * The @check() callback is invoked when
* object_property_set_link() is called and can raise an error to prevent the * object_property_set_link() is called and can raise an error to prevent the
* link being set. If <code>@check</code> is NULL, the property is read-only * link being set. If @check is NULL, the property is read-only
* and cannot be set. * and cannot be set.
* *
* Ownership of the pointer that @child points to is transferred to the * Ownership of the pointer that @child points to is transferred to the
* link property. The reference count for <code>*@child</code> is * link property. The reference count for *@child is
* managed by the property from after the function returns till the * managed by the property from after the function returns till the
* property is deleted with object_property_del(). If the * property is deleted with object_property_del(). If the
* <code>@flags</code> <code>OBJ_PROP_LINK_STRONG</code> bit is set, * @flags %OBJ_PROP_LINK_STRONG bit is set,
* the reference count is decremented when the property is deleted or * the reference count is decremented when the property is deleted or
* modified. * modified.
* *
@ -1823,7 +1823,7 @@ ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass,
* Add an alias for a property on an object. This function will add a property * Add an alias for a property on an object. This function will add a property
* of the same type as the forwarded property. * of the same type as the forwarded property.
* *
* The caller must ensure that <code>@target_obj</code> stays alive as long as * The caller must ensure that @target_obj stays alive as long as
* this property exists. In the case of a child object or an alias on the same * this property exists. In the case of a child object or an alias on the same
* object this will be the case. For aliases to other objects the caller is * object this will be the case. For aliases to other objects the caller is
* responsible for taking a reference. * responsible for taking a reference.

View file

@ -1291,7 +1291,8 @@ ObjectProperty *object_property_find_err(Object *obj, const char *name,
{ {
ObjectProperty *prop = object_property_find(obj, name); ObjectProperty *prop = object_property_find(obj, name);
if (!prop) { if (!prop) {
error_setg(errp, "Property '.%s' not found", name); error_setg(errp, "Property '%s.%s' not found",
object_get_typename(obj), name);
} }
return prop; return prop;
} }

View file

@ -1064,14 +1064,6 @@ sub output_blockhead {
sub dump_declaration($$) { sub dump_declaration($$) {
no strict 'refs'; no strict 'refs';
my ($prototype, $file) = @_; my ($prototype, $file) = @_;
if ($decl_type eq 'type name') {
if ($prototype =~ /^(enum|struct|union)\s+/) {
$decl_type = $1;
} else {
return;
}
}
my $func = "dump_" . $decl_type; my $func = "dump_" . $decl_type;
&$func(@_); &$func(@_);
} }
@ -1318,8 +1310,8 @@ sub dump_typedef($$) {
$x =~ s@/\*.*?\*/@@gos; # strip comments. $x =~ s@/\*.*?\*/@@gos; # strip comments.
# Parse function prototypes # Parse function prototypes
if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ || if ($x =~ /typedef\s+(\w+\s*\**)\s*\(\*?\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
$x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) { $x =~ /typedef\s+(\w+\s*\**)\s*(\w\S+)\s*\s*\((.*)\);/) {
# Function typedefs # Function typedefs
$return_type = $1; $return_type = $1;
@ -1928,9 +1920,7 @@ sub process_name($$) {
++$warnings; ++$warnings;
} }
if ($identifier =~ m/^[A-Z]/) { if ($identifier =~ m/^struct\b/) {
$decl_type = 'type name';
} elsif ($identifier =~ m/^struct\b/) {
$decl_type = 'struct'; $decl_type = 'struct';
} elsif ($identifier =~ m/^union\b/) { } elsif ($identifier =~ m/^union\b/) {
$decl_type = 'union'; $decl_type = 'union';