machine + QOM queue, 2020-09-22
QOM cleanups: * Convert instance properties to class properties (Eduardo Habkost) * simplify object_find_property / object_class_find_property (Daniel P. Berrangé) Deprecated feature removal: * Drop support for invalid topologies (Igor Mammedov) -----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEEWjIv1avE09usz9GqKAeTb5hNxaYFAl9qeb0UHGVoYWJrb3N0 QHJlZGhhdC5jb20ACgkQKAeTb5hNxab1yg//SZmjP5pGaTxWZzuSy7BwDgUWuBqK QoeJJOAmckzbqI4klHB824+oDSGDwE4pE/1QRRZihQOqSceahpD/CILc8CFDbdd4 vf1YQgFP9iJV5GtkllHTahP2/LMAoG/ivU4+SO0VD9UO89bcAG3jNvScZaxbsUoF FzfHm9OtckiWmkm29+r7dvCqfyGRHHXcbEc/mTRRVOqIlnTxSADiCfHjtPmkcK8E vHjXzRIBSjqmGPUZY9FLyFyhYyVNjj2B5PdBLqNqqRgn7/vco9jyUW/qpChdkGAK F24IjLQTq19ndx24+vsyAyvjlJXtu/SBb/OQuAhHhv+RwgnqOJWUp5VTrAK2rphL cOJuaFBbcSmuDN2/0orWdtpnc7kIVddGVshvh1AIbIHLckE5P3PVfCan+PeUqJWj t8WcDXj5HX5wfc5qKpSnds5ekG4aU0f9Cp6WE3zROz7syNfQkw3BFDJyGu5fEfD8 PrjDELQHAEngdzMVoY0bSnX4wtNJG/Pls3xjGJt5V9BM6bffoGY6APt3bZsptDmX VBmpp1hPv23uDP7ONHE+34D0HUQ79IvHJgU8M55R23Qc+s/7zR3FETfblaJerEbl 15tRBL1kNpcCN69wqK57Jh7BEoCbrA2u3GQgGfSWwZcRaS02a6FLkJvFSoHNuFV9 31Js0bePXitbouU= =FSgD -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into staging machine + QOM queue, 2020-09-22 QOM cleanups: * Convert instance properties to class properties (Eduardo Habkost) * simplify object_find_property / object_class_find_property (Daniel P. Berrangé) Deprecated feature removal: * Drop support for invalid topologies (Igor Mammedov) # gpg: Signature made Tue 22 Sep 2020 23:25:01 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: sifive_u: Register "start-in-flash" as class property sifive_e: Register "revb" as class property i440fx: Register i440FX-pcihost properties as class properties machine: Register "memory-backend" as class property xlnx-zcu102: Register properties as class properties cpu/core: Register core-id and nr-threads as class properties s390x: Register all CPU properties as class properties cryptodev-backend: Register "chardev" as class property cryptodev-vhost-user: Register "chardev" as class property smp: drop support for deprecated (invalid topologies) qom: simplify object_find_property / object_class_find_property Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
f7f1d916b2
@ -334,13 +334,6 @@ cryptodev_vhost_user_get_chardev(Object *obj, Error **errp)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void cryptodev_vhost_user_instance_int(Object *obj)
|
||||
{
|
||||
object_property_add_str(obj, "chardev",
|
||||
cryptodev_vhost_user_get_chardev,
|
||||
cryptodev_vhost_user_set_chardev);
|
||||
}
|
||||
|
||||
static void cryptodev_vhost_user_finalize(Object *obj)
|
||||
{
|
||||
CryptoDevBackendVhostUser *s =
|
||||
@ -361,13 +354,17 @@ cryptodev_vhost_user_class_init(ObjectClass *oc, void *data)
|
||||
bc->create_session = cryptodev_vhost_user_sym_create_session;
|
||||
bc->close_session = cryptodev_vhost_user_sym_close_session;
|
||||
bc->do_sym_op = NULL;
|
||||
|
||||
object_class_property_add_str(oc, "chardev",
|
||||
cryptodev_vhost_user_get_chardev,
|
||||
cryptodev_vhost_user_set_chardev);
|
||||
|
||||
}
|
||||
|
||||
static const TypeInfo cryptodev_vhost_user_info = {
|
||||
.name = TYPE_CRYPTODEV_BACKEND_VHOST_USER,
|
||||
.parent = TYPE_CRYPTODEV_BACKEND,
|
||||
.class_init = cryptodev_vhost_user_class_init,
|
||||
.instance_init = cryptodev_vhost_user_instance_int,
|
||||
.instance_finalize = cryptodev_vhost_user_finalize,
|
||||
.instance_size = sizeof(CryptoDevBackendVhostUser),
|
||||
};
|
||||
|
@ -206,10 +206,6 @@ cryptodev_backend_can_be_deleted(UserCreatable *uc)
|
||||
|
||||
static void cryptodev_backend_instance_init(Object *obj)
|
||||
{
|
||||
object_property_add(obj, "queues", "uint32",
|
||||
cryptodev_backend_get_queues,
|
||||
cryptodev_backend_set_queues,
|
||||
NULL, NULL);
|
||||
/* Initialize devices' queues property to 1 */
|
||||
object_property_set_int(obj, "queues", 1, NULL);
|
||||
}
|
||||
@ -230,6 +226,10 @@ cryptodev_backend_class_init(ObjectClass *oc, void *data)
|
||||
ucc->can_be_deleted = cryptodev_backend_can_be_deleted;
|
||||
|
||||
QTAILQ_INIT(&crypto_clients);
|
||||
object_class_property_add(oc, "queues", "uint32",
|
||||
cryptodev_backend_get_queues,
|
||||
cryptodev_backend_set_queues,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
static const TypeInfo cryptodev_backend_info = {
|
||||
|
@ -47,19 +47,6 @@ The 'file' driver for drives is no longer appropriate for character or host
|
||||
devices and will only accept regular files (S_IFREG). The correct driver
|
||||
for these file types is 'host_cdrom' or 'host_device' as appropriate.
|
||||
|
||||
``-smp`` (invalid topologies) (since 3.1)
|
||||
'''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
CPU topology properties should describe whole machine topology including
|
||||
possible CPUs.
|
||||
|
||||
However, historically it was possible to start QEMU with an incorrect topology
|
||||
where *n* <= *sockets* * *cores* * *threads* < *maxcpus*,
|
||||
which could lead to an incorrect topology enumeration by the guest.
|
||||
Support for invalid topologies will be removed, the user must ensure
|
||||
topologies described with -smp include all possible cpus, i.e.
|
||||
*sockets* * *cores* * *threads* = *maxcpus*.
|
||||
|
||||
``-vnc acl`` (since 4.0.0)
|
||||
''''''''''''''''''''''''''
|
||||
|
||||
@ -642,6 +629,19 @@ New machine versions (since 5.1) will not accept the option but it will still
|
||||
work with old machine types. User can check the QAPI schema to see if the legacy
|
||||
option is supported by looking at MachineInfo::numa-mem-supported property.
|
||||
|
||||
``-smp`` (invalid topologies) (removed 5.2)
|
||||
'''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
CPU topology properties should describe whole machine topology including
|
||||
possible CPUs.
|
||||
|
||||
However, historically it was possible to start QEMU with an incorrect topology
|
||||
where *n* <= *sockets* * *cores* * *threads* < *maxcpus*,
|
||||
which could lead to an incorrect topology enumeration by the guest.
|
||||
Support for invalid topologies is removed, the user must ensure
|
||||
topologies described with -smp include all possible cpus, i.e.
|
||||
*sockets* * *cores* * *threads* = *maxcpus*.
|
||||
|
||||
Block devices
|
||||
-------------
|
||||
|
||||
|
@ -169,28 +169,28 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
object_property_set_link(OBJECT(s->cpu), "memory", OBJECT(&s->container),
|
||||
&error_abort);
|
||||
if (object_property_find(OBJECT(s->cpu), "idau", NULL)) {
|
||||
if (object_property_find(OBJECT(s->cpu), "idau")) {
|
||||
object_property_set_link(OBJECT(s->cpu), "idau", s->idau,
|
||||
&error_abort);
|
||||
}
|
||||
if (object_property_find(OBJECT(s->cpu), "init-svtor", NULL)) {
|
||||
if (object_property_find(OBJECT(s->cpu), "init-svtor")) {
|
||||
if (!object_property_set_uint(OBJECT(s->cpu), "init-svtor",
|
||||
s->init_svtor, errp)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (object_property_find(OBJECT(s->cpu), "start-powered-off", NULL)) {
|
||||
if (object_property_find(OBJECT(s->cpu), "start-powered-off")) {
|
||||
if (!object_property_set_bool(OBJECT(s->cpu), "start-powered-off",
|
||||
s->start_powered_off, errp)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (object_property_find(OBJECT(s->cpu), "vfp", NULL)) {
|
||||
if (object_property_find(OBJECT(s->cpu), "vfp")) {
|
||||
if (!object_property_set_bool(OBJECT(s->cpu), "vfp", s->vfp, errp)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (object_property_find(OBJECT(s->cpu), "dsp", NULL)) {
|
||||
if (object_property_find(OBJECT(s->cpu), "dsp")) {
|
||||
if (!object_property_set_bool(OBJECT(s->cpu), "dsp", s->dsp, errp)) {
|
||||
return;
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
|
||||
/* By default A9 CPUs have EL3 enabled. This board does not currently
|
||||
* support EL3 so the CPU EL3 property is disabled before realization.
|
||||
*/
|
||||
if (object_property_find(cpuobj, "has_el3", NULL)) {
|
||||
if (object_property_find(cpuobj, "has_el3")) {
|
||||
object_property_set_bool(cpuobj, "has_el3", false, &error_fatal);
|
||||
}
|
||||
|
||||
|
@ -276,7 +276,7 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
|
||||
if (object_property_find(cpuobj, "reset-cbar")) {
|
||||
object_property_set_int(cpuobj, "reset-cbar", MPCORE_PERIPHBASE,
|
||||
&error_abort);
|
||||
}
|
||||
|
@ -603,7 +603,7 @@ static void integratorcp_init(MachineState *machine)
|
||||
* currently support EL3 so the CPU EL3 property is disabled before
|
||||
* realization.
|
||||
*/
|
||||
if (object_property_find(cpuobj, "has_el3", NULL)) {
|
||||
if (object_property_find(cpuobj, "has_el3")) {
|
||||
object_property_set_bool(cpuobj, "has_el3", false, &error_fatal);
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ static void realview_init(MachineState *machine,
|
||||
* does not currently support EL3 so the CPU EL3 property is disabled
|
||||
* before realization.
|
||||
*/
|
||||
if (object_property_find(cpuobj, "has_el3", NULL)) {
|
||||
if (object_property_find(cpuobj, "has_el3")) {
|
||||
object_property_set_bool(cpuobj, "has_el3", false, &error_fatal);
|
||||
}
|
||||
|
||||
|
@ -703,7 +703,7 @@ static void sbsa_ref_init(MachineState *machine)
|
||||
numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj),
|
||||
&error_fatal);
|
||||
|
||||
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
|
||||
if (object_property_find(cpuobj, "reset-cbar")) {
|
||||
object_property_set_int(cpuobj, "reset-cbar",
|
||||
sbsa_ref_memmap[SBSA_CPUPERIPHS].base,
|
||||
&error_abort);
|
||||
|
@ -213,7 +213,7 @@ static void versatile_init(MachineState *machine, int board_id)
|
||||
* currently support EL3 so the CPU EL3 property is disabled before
|
||||
* realization.
|
||||
*/
|
||||
if (object_property_find(cpuobj, "has_el3", NULL)) {
|
||||
if (object_property_find(cpuobj, "has_el3")) {
|
||||
object_property_set_bool(cpuobj, "has_el3", false, &error_fatal);
|
||||
}
|
||||
|
||||
|
@ -218,12 +218,12 @@ static void init_cpus(MachineState *ms, const char *cpu_type,
|
||||
object_property_set_bool(cpuobj, "has_el3", false, NULL);
|
||||
}
|
||||
if (!virt) {
|
||||
if (object_property_find(cpuobj, "has_el2", NULL)) {
|
||||
if (object_property_find(cpuobj, "has_el2")) {
|
||||
object_property_set_bool(cpuobj, "has_el2", false, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
|
||||
if (object_property_find(cpuobj, "reset-cbar")) {
|
||||
object_property_set_int(cpuobj, "reset-cbar", periphbase,
|
||||
&error_abort);
|
||||
}
|
||||
|
@ -1806,7 +1806,7 @@ static void machvirt_init(MachineState *machine)
|
||||
object_property_set_bool(cpuobj, "has_el3", false, NULL);
|
||||
}
|
||||
|
||||
if (!vms->virt && object_property_find(cpuobj, "has_el2", NULL)) {
|
||||
if (!vms->virt && object_property_find(cpuobj, "has_el2")) {
|
||||
object_property_set_bool(cpuobj, "has_el2", false, NULL);
|
||||
}
|
||||
|
||||
@ -1822,15 +1822,15 @@ static void machvirt_init(MachineState *machine)
|
||||
}
|
||||
|
||||
if (vmc->kvm_no_adjvtime &&
|
||||
object_property_find(cpuobj, "kvm-no-adjvtime", NULL)) {
|
||||
object_property_find(cpuobj, "kvm-no-adjvtime")) {
|
||||
object_property_set_bool(cpuobj, "kvm-no-adjvtime", true, NULL);
|
||||
}
|
||||
|
||||
if (vmc->no_pmu && object_property_find(cpuobj, "pmu", NULL)) {
|
||||
if (vmc->no_pmu && object_property_find(cpuobj, "pmu")) {
|
||||
object_property_set_bool(cpuobj, "pmu", false, NULL);
|
||||
}
|
||||
|
||||
if (object_property_find(cpuobj, "reset-cbar", NULL)) {
|
||||
if (object_property_find(cpuobj, "reset-cbar")) {
|
||||
object_property_set_int(cpuobj, "reset-cbar",
|
||||
vms->memmap[VIRT_CPUPERIPHS].base,
|
||||
&error_abort);
|
||||
@ -1850,7 +1850,7 @@ static void machvirt_init(MachineState *machine)
|
||||
* The property exists only if MemTag is supported.
|
||||
* If it is, we must allocate the ram to back that up.
|
||||
*/
|
||||
if (!object_property_find(cpuobj, "tag-memory", NULL)) {
|
||||
if (!object_property_find(cpuobj, "tag-memory")) {
|
||||
error_report("MTE requested, but not supported "
|
||||
"by the guest CPU");
|
||||
exit(1);
|
||||
|
@ -196,7 +196,7 @@ static void zynq_init(MachineState *machine)
|
||||
* currently support EL3 so the CPU EL3 property is disabled before
|
||||
* realization.
|
||||
*/
|
||||
if (object_property_find(OBJECT(cpu), "has_el3", NULL)) {
|
||||
if (object_property_find(OBJECT(cpu), "has_el3")) {
|
||||
object_property_set_bool(OBJECT(cpu), "has_el3", false, &error_fatal);
|
||||
}
|
||||
|
||||
|
@ -206,20 +206,8 @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
|
||||
|
||||
/* Default to secure mode being disabled */
|
||||
s->secure = false;
|
||||
object_property_add_bool(obj, "secure", zcu102_get_secure,
|
||||
zcu102_set_secure);
|
||||
object_property_set_description(obj, "secure",
|
||||
"Set on/off to enable/disable the ARM "
|
||||
"Security Extensions (TrustZone)");
|
||||
|
||||
/* Default to virt (EL2) being disabled */
|
||||
s->virt = false;
|
||||
object_property_add_bool(obj, "virtualization", zcu102_get_virt,
|
||||
zcu102_set_virt);
|
||||
object_property_set_description(obj, "virtualization",
|
||||
"Set on/off to enable/disable emulating a "
|
||||
"guest CPU which implements the ARM "
|
||||
"Virtualization Extensions");
|
||||
}
|
||||
|
||||
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
|
||||
@ -235,6 +223,19 @@ static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->max_cpus = XLNX_ZYNQMP_NUM_APU_CPUS + XLNX_ZYNQMP_NUM_RPU_CPUS;
|
||||
mc->default_cpus = XLNX_ZYNQMP_NUM_APU_CPUS;
|
||||
mc->default_ram_id = "ddr-ram";
|
||||
|
||||
object_class_property_add_bool(oc, "secure", zcu102_get_secure,
|
||||
zcu102_set_secure);
|
||||
object_class_property_set_description(oc, "secure",
|
||||
"Set on/off to enable/disable the ARM "
|
||||
"Security Extensions (TrustZone)");
|
||||
|
||||
object_class_property_add_bool(oc, "virtualization", zcu102_get_virt,
|
||||
zcu102_set_virt);
|
||||
object_class_property_set_description(oc, "virtualization",
|
||||
"Set on/off to enable/disable emulating a "
|
||||
"guest CPU which implements the ARM "
|
||||
"Virtualization Extensions");
|
||||
}
|
||||
|
||||
static const TypeInfo xlnx_zcu102_machine_init_typeinfo = {
|
||||
|
@ -754,23 +754,15 @@ static void smp_parse(MachineState *ms, QemuOpts *opts)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sockets * cores * threads > ms->smp.max_cpus) {
|
||||
error_report("cpu topology: "
|
||||
"sockets (%u) * cores (%u) * threads (%u) > "
|
||||
"maxcpus (%u)",
|
||||
if (sockets * cores * threads != ms->smp.max_cpus) {
|
||||
error_report("Invalid CPU topology: "
|
||||
"sockets (%u) * cores (%u) * threads (%u) "
|
||||
"!= maxcpus (%u)",
|
||||
sockets, cores, threads,
|
||||
ms->smp.max_cpus);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sockets * cores * threads != ms->smp.max_cpus) {
|
||||
warn_report("Invalid CPU topology deprecated: "
|
||||
"sockets (%u) * cores (%u) * threads (%u) "
|
||||
"!= maxcpus (%u)",
|
||||
sockets, cores, threads,
|
||||
ms->smp.max_cpus);
|
||||
}
|
||||
|
||||
ms->smp.cpus = cpus;
|
||||
ms->smp.cores = cores;
|
||||
ms->smp.threads = threads;
|
||||
@ -874,6 +866,12 @@ static void machine_class_init(ObjectClass *oc, void *data)
|
||||
machine_get_memory_encryption, machine_set_memory_encryption);
|
||||
object_class_property_set_description(oc, "memory-encryption",
|
||||
"Set memory encryption object to use");
|
||||
|
||||
object_class_property_add_str(oc, "memory-backend",
|
||||
machine_get_memdev, machine_set_memdev);
|
||||
object_class_property_set_description(oc, "memory-backend",
|
||||
"Set RAM backend"
|
||||
"Valid value is ID of hostmem based backend");
|
||||
}
|
||||
|
||||
static void machine_class_base_init(ObjectClass *oc, void *data)
|
||||
@ -925,12 +923,6 @@ static void machine_initfn(Object *obj)
|
||||
"Table (HMAT)");
|
||||
}
|
||||
|
||||
object_property_add_str(obj, "memory-backend",
|
||||
machine_get_memdev, machine_set_memdev);
|
||||
object_property_set_description(obj, "memory-backend",
|
||||
"Set RAM backend"
|
||||
"Valid value is ID of hostmem based backend");
|
||||
|
||||
/* Register notifier when init is done for sysbus sanity checks */
|
||||
ms->sysbus_notifier.notify = machine_init_notify;
|
||||
qemu_add_machine_init_done_notifier(&ms->sysbus_notifier);
|
||||
|
@ -460,7 +460,7 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
|
||||
qdev_prop_set_netdev(dev, "netdev", nd->netdev);
|
||||
}
|
||||
if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
|
||||
object_property_find(OBJECT(dev), "vectors", NULL)) {
|
||||
object_property_find(OBJECT(dev), "vectors")) {
|
||||
qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
|
||||
}
|
||||
nd->instantiated = 1;
|
||||
|
@ -93,7 +93,7 @@ bool sysbus_has_irq(SysBusDevice *dev, int n)
|
||||
char *prop = g_strdup_printf("%s[%d]", SYSBUS_DEVICE_GPIO_IRQ, n);
|
||||
ObjectProperty *r;
|
||||
|
||||
r = object_property_find(OBJECT(dev), prop, NULL);
|
||||
r = object_property_find(OBJECT(dev), prop);
|
||||
g_free(prop);
|
||||
|
||||
return (r != NULL);
|
||||
|
@ -66,11 +66,11 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
|
||||
* either all the CPUs have TZ, or none do.
|
||||
*/
|
||||
cpuobj = OBJECT(qemu_get_cpu(0));
|
||||
has_el3 = object_property_find(cpuobj, "has_el3", NULL) &&
|
||||
has_el3 = object_property_find(cpuobj, "has_el3") &&
|
||||
object_property_get_bool(cpuobj, "has_el3", &error_abort);
|
||||
qdev_prop_set_bit(gicdev, "has-security-extensions", has_el3);
|
||||
/* Similarly for virtualization support */
|
||||
has_el2 = object_property_find(cpuobj, "has_el2", NULL) &&
|
||||
has_el2 = object_property_find(cpuobj, "has_el2") &&
|
||||
object_property_get_bool(cpuobj, "has_el2", &error_abort);
|
||||
qdev_prop_set_bit(gicdev, "has-virtualization-extensions", has_el2);
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp)
|
||||
/* Make the GIC's TZ support match the CPUs. We assume that
|
||||
* either all the CPUs have TZ, or none do.
|
||||
*/
|
||||
has_el3 = object_property_find(cpuobj, "has_el3", NULL) &&
|
||||
has_el3 = object_property_find(cpuobj, "has_el3") &&
|
||||
object_property_get_bool(cpuobj, "has_el3", &error_abort);
|
||||
qdev_prop_set_bit(gicdev, "has-security-extensions", has_el3);
|
||||
|
||||
|
@ -69,10 +69,6 @@ static void cpu_core_instance_init(Object *obj)
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
CPUCore *core = CPU_CORE(obj);
|
||||
|
||||
object_property_add(obj, "core-id", "int", core_prop_get_core_id,
|
||||
core_prop_set_core_id, NULL, NULL);
|
||||
object_property_add(obj, "nr-threads", "int", core_prop_get_nr_threads,
|
||||
core_prop_set_nr_threads, NULL, NULL);
|
||||
core->nr_threads = ms->smp.threads;
|
||||
}
|
||||
|
||||
@ -81,6 +77,10 @@ static void cpu_core_class_init(ObjectClass *oc, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
set_bit(DEVICE_CATEGORY_CPU, dc->categories);
|
||||
object_class_property_add(oc, "core-id", "int", core_prop_get_core_id,
|
||||
core_prop_set_core_id, NULL, NULL);
|
||||
object_class_property_add(oc, "nr-threads", "int", core_prop_get_nr_threads,
|
||||
core_prop_set_nr_threads, NULL, NULL);
|
||||
}
|
||||
|
||||
static const TypeInfo cpu_core_type_info = {
|
||||
|
16
hw/i386/pc.c
16
hw/i386/pc.c
@ -746,23 +746,15 @@ void pc_smp_parse(MachineState *ms, QemuOpts *opts)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sockets * dies * cores * threads > ms->smp.max_cpus) {
|
||||
error_report("cpu topology: "
|
||||
"sockets (%u) * dies (%u) * cores (%u) * threads (%u) > "
|
||||
"maxcpus (%u)",
|
||||
if (sockets * dies * cores * threads != ms->smp.max_cpus) {
|
||||
error_report("Invalid CPU topology deprecated: "
|
||||
"sockets (%u) * dies (%u) * cores (%u) * threads (%u) "
|
||||
"!= maxcpus (%u)",
|
||||
sockets, dies, cores, threads,
|
||||
ms->smp.max_cpus);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (sockets * dies * cores * threads != ms->smp.max_cpus) {
|
||||
warn_report("Invalid CPU topology deprecated: "
|
||||
"sockets (%u) * dies (%u) * cores (%u) * threads (%u) "
|
||||
"!= maxcpus (%u)",
|
||||
sockets, dies, cores, threads,
|
||||
ms->smp.max_cpus);
|
||||
}
|
||||
|
||||
ms->smp.cpus = cpus;
|
||||
ms->smp.cores = cores;
|
||||
ms->smp.threads = threads;
|
||||
|
@ -83,7 +83,7 @@ static void set_init_vtor(uint64_t cpuid, uint32_t vtor)
|
||||
Object *cpuobj = OBJECT(arm_get_cpu_by_id(cpuid));
|
||||
|
||||
if (cpuobj) {
|
||||
if (object_property_find(cpuobj, "init-svtor", NULL)) {
|
||||
if (object_property_find(cpuobj, "init-svtor")) {
|
||||
object_property_set_uint(cpuobj, "init-svtor", vtor, &error_abort);
|
||||
}
|
||||
}
|
||||
|
@ -210,22 +210,6 @@ static void i440fx_pcihost_initfn(Object *obj)
|
||||
"pci-conf-idx", 4);
|
||||
memory_region_init_io(&s->data_mem, obj, &pci_host_data_le_ops, s,
|
||||
"pci-conf-data", 4);
|
||||
|
||||
object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_START, "uint32",
|
||||
i440fx_pcihost_get_pci_hole_start,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
object_property_add(obj, PCI_HOST_PROP_PCI_HOLE_END, "uint32",
|
||||
i440fx_pcihost_get_pci_hole_end,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_START, "uint64",
|
||||
i440fx_pcihost_get_pci_hole64_start,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
object_property_add(obj, PCI_HOST_PROP_PCI_HOLE64_END, "uint64",
|
||||
i440fx_pcihost_get_pci_hole64_end,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static void i440fx_pcihost_realize(DeviceState *dev, Error **errp)
|
||||
@ -401,6 +385,22 @@ static void i440fx_pcihost_class_init(ObjectClass *klass, void *data)
|
||||
device_class_set_props(dc, i440fx_props);
|
||||
/* Reason: needs to be wired up by pc_init1 */
|
||||
dc->user_creatable = false;
|
||||
|
||||
object_class_property_add(klass, PCI_HOST_PROP_PCI_HOLE_START, "uint32",
|
||||
i440fx_pcihost_get_pci_hole_start,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
object_class_property_add(klass, PCI_HOST_PROP_PCI_HOLE_END, "uint32",
|
||||
i440fx_pcihost_get_pci_hole_end,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
object_class_property_add(klass, PCI_HOST_PROP_PCI_HOLE64_START, "uint64",
|
||||
i440fx_pcihost_get_pci_hole64_start,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
object_class_property_add(klass, PCI_HOST_PROP_PCI_HOLE64_END, "uint64",
|
||||
i440fx_pcihost_get_pci_hole64_end,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static const TypeInfo i440fx_pcihost_info = {
|
||||
|
@ -1900,7 +1900,7 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
|
||||
* a temporary instance here to be able to check it.
|
||||
*/
|
||||
Object *obj = object_new_with_class(OBJECT_CLASS(dc));
|
||||
if (object_property_find(obj, "netdev", NULL)) {
|
||||
if (object_property_find(obj, "netdev")) {
|
||||
g_ptr_array_add(pci_nic_models, (gpointer)name);
|
||||
}
|
||||
object_unref(obj);
|
||||
|
@ -137,11 +137,6 @@ static void sifive_e_machine_instance_init(Object *obj)
|
||||
SiFiveEState *s = RISCV_E_MACHINE(obj);
|
||||
|
||||
s->revb = false;
|
||||
object_property_add_bool(obj, "revb", sifive_e_machine_get_revb,
|
||||
sifive_e_machine_set_revb);
|
||||
object_property_set_description(obj, "revb",
|
||||
"Set on to tell QEMU that it should model "
|
||||
"the revB HiFive1 board");
|
||||
}
|
||||
|
||||
static void sifive_e_machine_class_init(ObjectClass *oc, void *data)
|
||||
@ -152,6 +147,12 @@ static void sifive_e_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->init = sifive_e_machine_init;
|
||||
mc->max_cpus = 1;
|
||||
mc->default_cpu_type = SIFIVE_E_CPU;
|
||||
|
||||
object_class_property_add_bool(oc, "revb", sifive_e_machine_get_revb,
|
||||
sifive_e_machine_set_revb);
|
||||
object_class_property_set_description(oc, "revb",
|
||||
"Set on to tell QEMU that it should model "
|
||||
"the revB HiFive1 board");
|
||||
}
|
||||
|
||||
static const TypeInfo sifive_e_machine_typeinfo = {
|
||||
|
@ -568,14 +568,6 @@ static void sifive_u_machine_instance_init(Object *obj)
|
||||
SiFiveUState *s = RISCV_U_MACHINE(obj);
|
||||
|
||||
s->start_in_flash = false;
|
||||
object_property_add_bool(obj, "start-in-flash",
|
||||
sifive_u_machine_get_start_in_flash,
|
||||
sifive_u_machine_set_start_in_flash);
|
||||
object_property_set_description(obj, "start-in-flash",
|
||||
"Set on to tell QEMU's ROM to jump to "
|
||||
"flash. Otherwise QEMU will jump to DRAM "
|
||||
"or L2LIM depending on the msel value");
|
||||
|
||||
s->msel = 0;
|
||||
object_property_add(obj, "msel", "uint32",
|
||||
sifive_u_machine_get_uint32_prop,
|
||||
@ -599,6 +591,14 @@ static void sifive_u_machine_class_init(ObjectClass *oc, void *data)
|
||||
mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT;
|
||||
mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1;
|
||||
mc->default_cpus = mc->min_cpus;
|
||||
|
||||
object_class_property_add_bool(oc, "start-in-flash",
|
||||
sifive_u_machine_get_start_in_flash,
|
||||
sifive_u_machine_set_start_in_flash);
|
||||
object_class_property_set_description(oc, "start-in-flash",
|
||||
"Set on to tell QEMU's ROM to jump to "
|
||||
"flash. Otherwise QEMU will jump to DRAM "
|
||||
"or L2LIM depending on the msel value");
|
||||
}
|
||||
|
||||
static const TypeInfo sifive_u_machine_typeinfo = {
|
||||
|
@ -270,10 +270,10 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
|
||||
object_property_set_int(OBJECT(dev), "bootindex", bootindex,
|
||||
&error_abort);
|
||||
}
|
||||
if (object_property_find(OBJECT(dev), "removable", NULL)) {
|
||||
if (object_property_find(OBJECT(dev), "removable")) {
|
||||
qdev_prop_set_bit(dev, "removable", removable);
|
||||
}
|
||||
if (serial && object_property_find(OBJECT(dev), "serial", NULL)) {
|
||||
if (serial && object_property_find(OBJECT(dev), "serial")) {
|
||||
qdev_prop_set_string(dev, "serial", serial);
|
||||
}
|
||||
if (!qdev_prop_set_drive_err(dev, "drive", blk, errp)) {
|
||||
|
@ -1463,14 +1463,52 @@ void object_property_set_default_uint(ObjectProperty *prop, uint64_t value);
|
||||
* object_property_find:
|
||||
* @obj: the object
|
||||
* @name: the name of the property
|
||||
*
|
||||
* Look up a property for an object.
|
||||
*
|
||||
* Return its #ObjectProperty if found, or NULL.
|
||||
*/
|
||||
ObjectProperty *object_property_find(Object *obj, const char *name);
|
||||
|
||||
/**
|
||||
* object_property_find_err:
|
||||
* @obj: the object
|
||||
* @name: the name of the property
|
||||
* @errp: returns an error if this function fails
|
||||
*
|
||||
* Look up a property for an object and return its #ObjectProperty if found.
|
||||
* Look up a property for an object.
|
||||
*
|
||||
* Return its #ObjectProperty if found, or NULL.
|
||||
*/
|
||||
ObjectProperty *object_property_find(Object *obj, const char *name,
|
||||
Error **errp);
|
||||
ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name,
|
||||
Error **errp);
|
||||
ObjectProperty *object_property_find_err(Object *obj,
|
||||
const char *name,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* object_class_property_find:
|
||||
* @klass: the object class
|
||||
* @name: the name of the property
|
||||
*
|
||||
* Look up a property for an object class.
|
||||
*
|
||||
* Return its #ObjectProperty if found, or NULL.
|
||||
*/
|
||||
ObjectProperty *object_class_property_find(ObjectClass *klass,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* object_class_property_find_err:
|
||||
* @klass: the object class
|
||||
* @name: the name of the property
|
||||
* @errp: returns an error if this function fails
|
||||
*
|
||||
* Look up a property for an object class.
|
||||
*
|
||||
* Return its #ObjectProperty if found, or NULL.
|
||||
*/
|
||||
ObjectProperty *object_class_property_find_err(ObjectClass *klass,
|
||||
const char *name,
|
||||
Error **errp);
|
||||
|
||||
typedef struct ObjectPropertyIterator {
|
||||
ObjectClass *nextclass;
|
||||
|
60
qom/object.c
60
qom/object.c
@ -403,7 +403,7 @@ bool object_apply_global_props(Object *obj, const GPtrArray *props,
|
||||
if (object_dynamic_cast(obj, p->driver) == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (p->optional && !object_property_find(obj, p->property, NULL)) {
|
||||
if (p->optional && !object_property_find(obj, p->property)) {
|
||||
continue;
|
||||
}
|
||||
p->used = true;
|
||||
@ -1214,7 +1214,7 @@ object_property_try_add(Object *obj, const char *name, const char *type,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (object_property_find(obj, name, NULL) != NULL) {
|
||||
if (object_property_find(obj, name) != NULL) {
|
||||
error_setg(errp, "attempt to add duplicate property '%s' to object (type '%s')",
|
||||
name, object_get_typename(obj));
|
||||
return NULL;
|
||||
@ -1256,7 +1256,7 @@ object_class_property_add(ObjectClass *klass,
|
||||
{
|
||||
ObjectProperty *prop;
|
||||
|
||||
assert(!object_class_property_find(klass, name, NULL));
|
||||
assert(!object_class_property_find(klass, name));
|
||||
|
||||
prop = g_malloc0(sizeof(*prop));
|
||||
|
||||
@ -1273,24 +1273,27 @@ object_class_property_add(ObjectClass *klass,
|
||||
return prop;
|
||||
}
|
||||
|
||||
ObjectProperty *object_property_find(Object *obj, const char *name,
|
||||
Error **errp)
|
||||
ObjectProperty *object_property_find(Object *obj, const char *name)
|
||||
{
|
||||
ObjectProperty *prop;
|
||||
ObjectClass *klass = object_get_class(obj);
|
||||
|
||||
prop = object_class_property_find(klass, name, NULL);
|
||||
prop = object_class_property_find(klass, name);
|
||||
if (prop) {
|
||||
return prop;
|
||||
}
|
||||
|
||||
prop = g_hash_table_lookup(obj->properties, name);
|
||||
if (prop) {
|
||||
return prop;
|
||||
}
|
||||
return g_hash_table_lookup(obj->properties, name);
|
||||
}
|
||||
|
||||
error_setg(errp, "Property '.%s' not found", name);
|
||||
return NULL;
|
||||
ObjectProperty *object_property_find_err(Object *obj, const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
ObjectProperty *prop = object_property_find(obj, name);
|
||||
if (!prop) {
|
||||
error_setg(errp, "Property '.%s' not found", name);
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
void object_property_iter_init(ObjectPropertyIterator *iter,
|
||||
@ -1320,27 +1323,34 @@ void object_class_property_iter_init(ObjectPropertyIterator *iter,
|
||||
iter->nextclass = object_class_get_parent(klass);
|
||||
}
|
||||
|
||||
ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name,
|
||||
Error **errp)
|
||||
ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name)
|
||||
{
|
||||
ObjectProperty *prop;
|
||||
ObjectClass *parent_klass;
|
||||
|
||||
parent_klass = object_class_get_parent(klass);
|
||||
if (parent_klass) {
|
||||
prop = object_class_property_find(parent_klass, name, NULL);
|
||||
ObjectProperty *prop =
|
||||
object_class_property_find(parent_klass, name);
|
||||
if (prop) {
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
|
||||
prop = g_hash_table_lookup(klass->properties, name);
|
||||
return g_hash_table_lookup(klass->properties, name);
|
||||
}
|
||||
|
||||
ObjectProperty *object_class_property_find_err(ObjectClass *klass,
|
||||
const char *name,
|
||||
Error **errp)
|
||||
{
|
||||
ObjectProperty *prop = object_class_property_find(klass, name);
|
||||
if (!prop) {
|
||||
error_setg(errp, "Property '.%s' not found", name);
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
|
||||
void object_property_del(Object *obj, const char *name)
|
||||
{
|
||||
ObjectProperty *prop = g_hash_table_lookup(obj->properties, name);
|
||||
@ -1355,7 +1365,7 @@ bool object_property_get(Object *obj, const char *name, Visitor *v,
|
||||
Error **errp)
|
||||
{
|
||||
Error *err = NULL;
|
||||
ObjectProperty *prop = object_property_find(obj, name, errp);
|
||||
ObjectProperty *prop = object_property_find_err(obj, name, errp);
|
||||
|
||||
if (prop == NULL) {
|
||||
return false;
|
||||
@ -1374,7 +1384,7 @@ bool object_property_set(Object *obj, const char *name, Visitor *v,
|
||||
Error **errp)
|
||||
{
|
||||
Error *err = NULL;
|
||||
ObjectProperty *prop = object_property_find(obj, name, errp);
|
||||
ObjectProperty *prop = object_property_find_err(obj, name, errp);
|
||||
|
||||
if (prop == NULL) {
|
||||
return false;
|
||||
@ -1590,7 +1600,7 @@ int object_property_get_enum(Object *obj, const char *name,
|
||||
{
|
||||
char *str;
|
||||
int ret;
|
||||
ObjectProperty *prop = object_property_find(obj, name, errp);
|
||||
ObjectProperty *prop = object_property_find_err(obj, name, errp);
|
||||
EnumProperty *enumprop;
|
||||
|
||||
if (prop == NULL) {
|
||||
@ -1647,7 +1657,7 @@ out:
|
||||
|
||||
const char *object_property_get_type(Object *obj, const char *name, Error **errp)
|
||||
{
|
||||
ObjectProperty *prop = object_property_find(obj, name, errp);
|
||||
ObjectProperty *prop = object_property_find_err(obj, name, errp);
|
||||
if (prop == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@ -2025,7 +2035,7 @@ char *object_get_canonical_path(const Object *obj)
|
||||
|
||||
Object *object_resolve_path_component(Object *parent, const char *part)
|
||||
{
|
||||
ObjectProperty *prop = object_property_find(parent, part, NULL);
|
||||
ObjectProperty *prop = object_property_find(parent, part);
|
||||
if (prop == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@ -2724,8 +2734,8 @@ object_property_add_alias(Object *obj, const char *name,
|
||||
ObjectProperty *target_prop;
|
||||
g_autofree char *prop_type = NULL;
|
||||
|
||||
target_prop = object_property_find(target_obj, target_name,
|
||||
&error_abort);
|
||||
target_prop = object_property_find_err(target_obj, target_name,
|
||||
&error_abort);
|
||||
|
||||
if (object_property_is_child(target_prop)) {
|
||||
prop_type = g_strdup_printf("link%s",
|
||||
@ -2758,7 +2768,7 @@ void object_property_set_description(Object *obj, const char *name,
|
||||
{
|
||||
ObjectProperty *op;
|
||||
|
||||
op = object_property_find(obj, name, &error_abort);
|
||||
op = object_property_find_err(obj, name, &error_abort);
|
||||
g_free(op->description);
|
||||
op->description = g_strdup(description);
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
|
||||
|
||||
i = 0;
|
||||
while ((name = cpu_model_advertised_features[i++]) != NULL) {
|
||||
ObjectProperty *prop = object_property_find(obj, name, NULL);
|
||||
ObjectProperty *prop = object_property_find(obj, name);
|
||||
if (prop) {
|
||||
QObject *value;
|
||||
|
||||
|
@ -6828,7 +6828,7 @@ static void x86_cpu_register_bit_prop(X86CPU *cpu,
|
||||
ObjectProperty *op;
|
||||
uint64_t mask = (1ULL << bitnr);
|
||||
|
||||
op = object_property_find(OBJECT(cpu), prop_name, NULL);
|
||||
op = object_property_find(OBJECT(cpu), prop_name);
|
||||
if (op) {
|
||||
fp = op->opaque;
|
||||
assert(fp->w == w);
|
||||
|
@ -10478,7 +10478,7 @@ static void ppc_cpu_parse_featurestr(const char *type, char *features,
|
||||
return;
|
||||
}
|
||||
|
||||
if (object_property_find(machine, "max-cpu-compat", NULL)) {
|
||||
if (object_property_find(machine, "max-cpu-compat")) {
|
||||
int i;
|
||||
char **inpieces;
|
||||
char *s = features;
|
||||
|
@ -302,7 +302,6 @@ static void s390_cpu_initfn(Object *obj)
|
||||
timer_new_ns(QEMU_CLOCK_VIRTUAL, s390x_cpu_timer, cpu);
|
||||
s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
|
||||
#endif
|
||||
s390_cpu_model_register_props(obj);
|
||||
}
|
||||
|
||||
static void s390_cpu_finalize(Object *obj)
|
||||
|
@ -1089,25 +1089,6 @@ static void set_feature_group(Object *obj, Visitor *v, const char *name,
|
||||
}
|
||||
}
|
||||
|
||||
void s390_cpu_model_register_props(Object *obj)
|
||||
{
|
||||
S390FeatGroup group;
|
||||
S390Feat feat;
|
||||
|
||||
for (feat = 0; feat < S390_FEAT_MAX; feat++) {
|
||||
const S390FeatDef *def = s390_feat_def(feat);
|
||||
object_property_add(obj, def->name, "bool", get_feature,
|
||||
set_feature, NULL, (void *) feat);
|
||||
object_property_set_description(obj, def->name, def->desc);
|
||||
}
|
||||
for (group = 0; group < S390_FEAT_GROUP_MAX; group++) {
|
||||
const S390FeatGroupDef *def = s390_feat_group_def(group);
|
||||
object_property_add(obj, def->name, "bool", get_feature_group,
|
||||
set_feature_group, NULL, (void *) group);
|
||||
object_property_set_description(obj, def->name, def->desc);
|
||||
}
|
||||
}
|
||||
|
||||
static void s390_cpu_model_initfn(Object *obj)
|
||||
{
|
||||
S390CPU *cpu = S390_CPU(obj);
|
||||
@ -1215,11 +1196,27 @@ static char *get_description(Object *obj, Error **errp)
|
||||
|
||||
void s390_cpu_model_class_register_props(ObjectClass *oc)
|
||||
{
|
||||
S390FeatGroup group;
|
||||
S390Feat feat;
|
||||
|
||||
object_class_property_add_bool(oc, "migration-safe", get_is_migration_safe,
|
||||
NULL);
|
||||
object_class_property_add_bool(oc, "static", get_is_static,
|
||||
NULL);
|
||||
object_class_property_add_str(oc, "description", get_description, NULL);
|
||||
|
||||
for (feat = 0; feat < S390_FEAT_MAX; feat++) {
|
||||
const S390FeatDef *def = s390_feat_def(feat);
|
||||
object_class_property_add(oc, def->name, "bool", get_feature,
|
||||
set_feature, NULL, (void *) feat);
|
||||
object_class_property_set_description(oc, def->name, def->desc);
|
||||
}
|
||||
for (group = 0; group < S390_FEAT_GROUP_MAX; group++) {
|
||||
const S390FeatGroupDef *def = s390_feat_group_def(group);
|
||||
object_class_property_add(oc, def->name, "bool", get_feature_group,
|
||||
set_feature_group, NULL, (void *) group);
|
||||
object_class_property_set_description(oc, def->name, def->desc);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KVM
|
||||
|
@ -260,7 +260,6 @@ static inline void s390_cpu_unhalt(S390CPU *cpu)
|
||||
|
||||
|
||||
/* cpu_models.c */
|
||||
void s390_cpu_model_register_props(Object *obj);
|
||||
void s390_cpu_model_class_register_props(ObjectClass *oc);
|
||||
void s390_realize_cpu_model(CPUState *cs, Error **errp);
|
||||
ObjectClass *s390_cpu_class_by_name(const char *name);
|
||||
|
Loading…
Reference in New Issue
Block a user