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:
commit
a1d22c668a
@ -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
|
||||
features:
|
||||
|
||||
- System for dynamically registering types
|
||||
- Support for single-inheritance of types
|
||||
- Multiple inheritance of stateless interfaces
|
||||
- System for dynamically registering types
|
||||
- Support for single-inheritance of types
|
||||
- Multiple inheritance of stateless interfaces
|
||||
|
||||
.. code-block:: c
|
||||
:caption: Creating a minimal type
|
||||
@ -174,17 +174,17 @@ dynamically cast it to an object that implements the interface.
|
||||
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
|
||||
strongly-typed first argument.
|
||||
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
|
||||
uniquely identity the function to be called; the signature does not vary
|
||||
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
|
||||
via OBJECT_GET_CLASS() accessing the overridden function.
|
||||
The original function is not automatically invoked. It is the responsibility
|
||||
@ -284,28 +284,29 @@ in the header file:
|
||||
.. code-block:: c
|
||||
: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:
|
||||
|
||||
.. code-block:: c
|
||||
:caption: Expansion from declaring a simple type
|
||||
|
||||
typedef struct MyDevice MyDevice;
|
||||
typedef struct MyDeviceClass MyDeviceClass;
|
||||
typedef struct MyDevice MyDevice;
|
||||
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) \
|
||||
OBJECT_GET_CLASS(MyDeviceClass, obj, TYPE_MY_DEVICE)
|
||||
#define MY_DEVICE_CLASS(void *klass) \
|
||||
OBJECT_CLASS_CHECK(MyDeviceClass, klass, TYPE_MY_DEVICE)
|
||||
#define MY_DEVICE(void *obj)
|
||||
OBJECT_CHECK(MyDevice, obj, TYPE_MY_DEVICE)
|
||||
#define MY_DEVICE_GET_CLASS(void *obj) \
|
||||
OBJECT_GET_CLASS(MyDeviceClass, obj, TYPE_MY_DEVICE)
|
||||
#define MY_DEVICE_CLASS(void *klass) \
|
||||
OBJECT_CLASS_CHECK(MyDeviceClass, klass, TYPE_MY_DEVICE)
|
||||
#define MY_DEVICE(void *obj)
|
||||
OBJECT_CHECK(MyDevice, obj, TYPE_MY_DEVICE)
|
||||
|
||||
struct MyDeviceClass {
|
||||
DeviceClass parent_class;
|
||||
};
|
||||
struct MyDeviceClass {
|
||||
DeviceClass parent_class;
|
||||
};
|
||||
|
||||
The 'struct MyDevice' needs to be declared separately.
|
||||
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
|
||||
: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:
|
||||
|
||||
.. code-block:: c
|
||||
:caption: Expansion from defining a simple type
|
||||
|
||||
static void my_device_finalize(Object *obj);
|
||||
static void my_device_class_init(ObjectClass *oc, void *data);
|
||||
static void my_device_init(Object *obj);
|
||||
static void my_device_finalize(Object *obj);
|
||||
static void my_device_class_init(ObjectClass *oc, void *data);
|
||||
static void my_device_init(Object *obj);
|
||||
|
||||
static const TypeInfo my_device_info = {
|
||||
.parent = TYPE_DEVICE,
|
||||
.name = TYPE_MY_DEVICE,
|
||||
.instance_size = sizeof(MyDevice),
|
||||
.instance_init = my_device_init,
|
||||
.instance_finalize = my_device_finalize,
|
||||
.class_size = sizeof(MyDeviceClass),
|
||||
.class_init = my_device_class_init,
|
||||
};
|
||||
static const TypeInfo my_device_info = {
|
||||
.parent = TYPE_DEVICE,
|
||||
.name = TYPE_MY_DEVICE,
|
||||
.instance_size = sizeof(MyDevice),
|
||||
.instance_init = my_device_init,
|
||||
.instance_finalize = my_device_finalize,
|
||||
.class_size = sizeof(MyDeviceClass),
|
||||
.class_init = my_device_class_init,
|
||||
};
|
||||
|
||||
static void
|
||||
my_device_register_types(void)
|
||||
{
|
||||
type_register_static(&my_device_info);
|
||||
}
|
||||
type_init(my_device_register_types);
|
||||
static void
|
||||
my_device_register_types(void)
|
||||
{
|
||||
type_register_static(&my_device_info);
|
||||
}
|
||||
type_init(my_device_register_types);
|
||||
|
||||
This is sufficient to get the type registered with the type
|
||||
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
|
||||
:caption: Defining a simple type implementing interfaces
|
||||
|
||||
OBJECT_DEFINE_TYPE_WITH_INTERFACES(MyDevice, my_device,
|
||||
MY_DEVICE, DEVICE,
|
||||
{ TYPE_USER_CREATABLE }, { NULL })
|
||||
OBJECT_DEFINE_TYPE_WITH_INTERFACES(MyDevice, my_device,
|
||||
MY_DEVICE, DEVICE,
|
||||
{ TYPE_USER_CREATABLE },
|
||||
{ NULL })
|
||||
|
||||
If the type is not intended to be instantiated, then then
|
||||
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
|
||||
: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)
|
||||
|
||||
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "exec/log.h"
|
||||
#include "exec/cpu-common.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "sysemu/tcg.h"
|
||||
|
@ -424,7 +424,13 @@ void parse_numa_hmat_cache(MachineState *ms, NumaHmatCacheOptions *node,
|
||||
}
|
||||
|
||||
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 <=
|
||||
ms->numa_state->hmat_cache[node->node_id][node->level - 1]->size)) {
|
||||
error_setg(errp, "Invalid size=%" PRIu64 ", the size of level=%" PRIu8
|
||||
|
30
hw/core/qdev-prop-internal.h
Normal file
30
hw/core/qdev-prop-internal.h
Normal 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
|
@ -11,19 +11,25 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "audio/audio.h"
|
||||
#include "net/net.h"
|
||||
#include "hw/qdev-properties.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 "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/blockdev.h"
|
||||
#include "hw/block/block.h"
|
||||
#include "net/hub.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "chardev/char-fe.h"
|
||||
#include "sysemu/iothread.h"
|
||||
#include "sysemu/tpm_backend.h"
|
||||
#include "net/net.h"
|
||||
#include "hw/pci/pci.h"
|
||||
|
||||
static bool check_prop_still_unset(DeviceState *dev, const char *name,
|
||||
const void *old_val, const char *new_val,
|
||||
@ -280,6 +286,96 @@ const PropertyInfo qdev_prop_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 --- */
|
||||
static void get_netdev(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
@ -465,3 +561,578 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
|
||||
}
|
||||
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,
|
||||
};
|
||||
|
@ -1,22 +1,15 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "net/net.h"
|
||||
#include "hw/qdev-properties.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/qmp/qerror.h"
|
||||
#include "qemu/ctype.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 "chardev/char.h"
|
||||
#include "qemu/uuid.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qdev-prop-internal.h"
|
||||
|
||||
void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
|
||||
Error **errp)
|
||||
@ -52,8 +45,8 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void get_enum(Object *obj, Visitor *v, const char *name, void *opaque,
|
||||
Error **errp)
|
||||
void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
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);
|
||||
}
|
||||
|
||||
static void set_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)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
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 */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@ -275,13 +278,13 @@ const PropertyInfo qdev_prop_uint8 = {
|
||||
.name = "uint8",
|
||||
.get = get_uint8,
|
||||
.set = set_uint8,
|
||||
.set_default_value = set_default_value_uint,
|
||||
.set_default_value = qdev_propinfo_set_default_value_uint,
|
||||
};
|
||||
|
||||
/* --- 16bit integer --- */
|
||||
|
||||
static void get_uint16(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
void qdev_propinfo_get_uint16(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
@ -307,9 +310,9 @@ static void set_uint16(Object *obj, Visitor *v, const char *name,
|
||||
|
||||
const PropertyInfo qdev_prop_uint16 = {
|
||||
.name = "uint16",
|
||||
.get = get_uint16,
|
||||
.get = qdev_propinfo_get_uint16,
|
||||
.set = set_uint16,
|
||||
.set_default_value = set_default_value_uint,
|
||||
.set_default_value = qdev_propinfo_set_default_value_uint,
|
||||
};
|
||||
|
||||
/* --- 32bit integer --- */
|
||||
@ -339,8 +342,8 @@ static void set_uint32(Object *obj, Visitor *v, const char *name,
|
||||
visit_type_uint32(v, name, ptr, errp);
|
||||
}
|
||||
|
||||
static void get_int32(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)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
@ -368,14 +371,14 @@ const PropertyInfo qdev_prop_uint32 = {
|
||||
.name = "uint32",
|
||||
.get = get_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 = {
|
||||
.name = "int32",
|
||||
.get = get_int32,
|
||||
.get = qdev_propinfo_get_int32,
|
||||
.set = set_int32,
|
||||
.set_default_value = set_default_value_int,
|
||||
.set_default_value = qdev_propinfo_set_default_value_int,
|
||||
};
|
||||
|
||||
/* --- 64bit integer --- */
|
||||
@ -434,14 +437,14 @@ const PropertyInfo qdev_prop_uint64 = {
|
||||
.name = "uint64",
|
||||
.get = get_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 = {
|
||||
.name = "int64",
|
||||
.get = get_int64,
|
||||
.set = set_int64,
|
||||
.set_default_value = set_default_value_int,
|
||||
.set_default_value = qdev_propinfo_set_default_value_int,
|
||||
};
|
||||
|
||||
/* --- string --- */
|
||||
@ -494,318 +497,21 @@ const PropertyInfo qdev_prop_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 --- */
|
||||
|
||||
const PropertyInfo qdev_prop_on_off_auto = {
|
||||
.name = "OnOffAuto",
|
||||
.description = "on/off/auto",
|
||||
.enum_table = &OnOffAuto_lookup,
|
||||
.get = get_enum,
|
||||
.set = set_enum,
|
||||
.set_default_value = 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,
|
||||
.get = qdev_propinfo_get_enum,
|
||||
.set = qdev_propinfo_set_enum,
|
||||
.set_default_value = qdev_propinfo_set_default_value_enum,
|
||||
};
|
||||
|
||||
/* --- 32bit unsigned int 'size' type --- */
|
||||
|
||||
static void get_size32(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)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
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 = {
|
||||
.name = "size",
|
||||
.get = get_size32,
|
||||
.get = qdev_propinfo_get_size32,
|
||||
.set = set_size32,
|
||||
.set_default_value = 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,
|
||||
.set_default_value = qdev_propinfo_set_default_value_uint,
|
||||
};
|
||||
|
||||
/* --- UUID --- */
|
||||
@ -1175,7 +711,7 @@ const PropertyInfo qdev_prop_arraylen = {
|
||||
.name = "uint32",
|
||||
.get = get_uint32,
|
||||
.set = set_prop_arraylen,
|
||||
.set_default_value = set_default_value_uint,
|
||||
.set_default_value = qdev_propinfo_set_default_value_uint,
|
||||
};
|
||||
|
||||
/* --- 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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Property *prop;
|
||||
@ -1386,7 +912,7 @@ const PropertyInfo qdev_prop_size = {
|
||||
.name = "size",
|
||||
.get = get_size,
|
||||
.set = set_size,
|
||||
.set_default_value = set_default_value_uint,
|
||||
.set_default_value = qdev_propinfo_set_default_value_uint,
|
||||
};
|
||||
|
||||
/* --- object link property --- */
|
||||
@ -1403,186 +929,3 @@ const PropertyInfo qdev_prop_link = {
|
||||
.name = "link",
|
||||
.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,
|
||||
};
|
||||
|
@ -443,7 +443,7 @@ struct IOMMUMemoryRegion {
|
||||
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.
|
||||
* 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 {
|
||||
/* 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
|
||||
* @fv: the flat view of the address space the region is mapped in
|
||||
|
@ -8,6 +8,7 @@
|
||||
extern const PropertyInfo qdev_prop_bit;
|
||||
extern const PropertyInfo qdev_prop_bit64;
|
||||
extern const PropertyInfo qdev_prop_bool;
|
||||
extern const PropertyInfo qdev_prop_enum;
|
||||
extern const PropertyInfo qdev_prop_uint8;
|
||||
extern const PropertyInfo qdev_prop_uint16;
|
||||
extern const PropertyInfo qdev_prop_uint32;
|
||||
|
@ -31,7 +31,7 @@ typedef struct InterfaceInfo InterfaceInfo;
|
||||
typedef struct ObjectProperty ObjectProperty;
|
||||
|
||||
/**
|
||||
* ObjectPropertyAccessor:
|
||||
* typedef ObjectPropertyAccessor:
|
||||
* @obj: the object that owns the property
|
||||
* @v: the visitor that contains the property data
|
||||
* @name: the name of the property
|
||||
@ -47,7 +47,7 @@ typedef void (ObjectPropertyAccessor)(Object *obj,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* ObjectPropertyResolve:
|
||||
* typedef ObjectPropertyResolve:
|
||||
* @obj: the object that owns the property
|
||||
* @opaque: the opaque registered with the property
|
||||
* @part: the name of the property
|
||||
@ -66,7 +66,7 @@ typedef Object *(ObjectPropertyResolve)(Object *obj,
|
||||
const char *part);
|
||||
|
||||
/**
|
||||
* ObjectPropertyRelease:
|
||||
* typedef ObjectPropertyRelease:
|
||||
* @obj: the object that owns the property
|
||||
* @name: the name of the property
|
||||
* @opaque: the opaque registered with the property
|
||||
@ -78,7 +78,7 @@ typedef void (ObjectPropertyRelease)(Object *obj,
|
||||
void *opaque);
|
||||
|
||||
/**
|
||||
* ObjectPropertyInit:
|
||||
* typedef ObjectPropertyInit:
|
||||
* @obj: the object that owns the property
|
||||
* @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
|
||||
*
|
||||
* Called when an object is being removed from the QOM composition tree.
|
||||
@ -110,7 +110,7 @@ struct ObjectProperty
|
||||
typedef void (ObjectUnparent)(Object *obj);
|
||||
|
||||
/**
|
||||
* ObjectFree:
|
||||
* typedef ObjectFree:
|
||||
* @obj: the object being freed
|
||||
*
|
||||
* Called when an object's last reference is removed.
|
||||
@ -120,7 +120,7 @@ typedef void (ObjectFree)(void *obj);
|
||||
#define OBJECT_CLASS_CAST_CACHE 4
|
||||
|
||||
/**
|
||||
* ObjectClass:
|
||||
* struct ObjectClass:
|
||||
*
|
||||
* The base for all classes. The only thing that #ObjectClass contains is an
|
||||
* 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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
#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
|
||||
* 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.
|
||||
*/
|
||||
#define DECLARE_CLASS_CHECKERS(ClassType, OBJ_NAME, TYPENAME) \
|
||||
@ -370,7 +370,7 @@ struct Object
|
||||
true, { NULL })
|
||||
|
||||
/**
|
||||
* TypeInfo:
|
||||
* struct TypeInfo:
|
||||
* @name: The name of the type.
|
||||
* @parent: The name of the parent type.
|
||||
* @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)
|
||||
|
||||
/**
|
||||
* InterfaceInfo:
|
||||
* struct InterfaceInfo:
|
||||
* @type: The name of the interface.
|
||||
*
|
||||
* The information associated with an interface.
|
||||
@ -506,7 +506,7 @@ struct InterfaceInfo {
|
||||
};
|
||||
|
||||
/**
|
||||
* InterfaceClass:
|
||||
* struct InterfaceClass:
|
||||
* @parent_class: the base class
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
* object this will be the case. For aliases to other objects the caller is
|
||||
* responsible for taking a reference.
|
||||
|
@ -1291,7 +1291,8 @@ ObjectProperty *object_property_find_err(Object *obj, const char *name,
|
||||
{
|
||||
ObjectProperty *prop = object_property_find(obj, name);
|
||||
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;
|
||||
}
|
||||
|
@ -1064,14 +1064,6 @@ sub output_blockhead {
|
||||
sub dump_declaration($$) {
|
||||
no strict 'refs';
|
||||
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;
|
||||
&$func(@_);
|
||||
}
|
||||
@ -1318,8 +1310,8 @@ sub dump_typedef($$) {
|
||||
$x =~ s@/\*.*?\*/@@gos; # strip comments.
|
||||
|
||||
# Parse function prototypes
|
||||
if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
|
||||
$x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) {
|
||||
if ($x =~ /typedef\s+(\w+\s*\**)\s*\(\*?\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
|
||||
$x =~ /typedef\s+(\w+\s*\**)\s*(\w\S+)\s*\s*\((.*)\);/) {
|
||||
|
||||
# Function typedefs
|
||||
$return_type = $1;
|
||||
@ -1928,9 +1920,7 @@ sub process_name($$) {
|
||||
++$warnings;
|
||||
}
|
||||
|
||||
if ($identifier =~ m/^[A-Z]/) {
|
||||
$decl_type = 'type name';
|
||||
} elsif ($identifier =~ m/^struct\b/) {
|
||||
if ($identifier =~ m/^struct\b/) {
|
||||
$decl_type = 'struct';
|
||||
} elsif ($identifier =~ m/^union\b/) {
|
||||
$decl_type = 'union';
|
||||
|
Loading…
Reference in New Issue
Block a user