pc, virtio enhancements

Memory hot-unplug support for pc, MSI-X
 mapping update speedup for virtio-pci,
 misc refactorings and bugfixes.
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJVUFj/AAoJECgfDbjSjVRpteQH+gKoOMKilM6qvgdQS9vduFJ+
 lDHNnmfgzWjVMEetiUOc9hImfEEyTyDFrkSI3wf4a8RZ7UnnDKD8hZR1nToySJPd
 SuDP/EdtXYtInIMjc1MUUrJEP6qtjjgM+IbikVzHDxCeekrTMFz2w05MZ+V+hxI5
 8b8ndPNfjX3ciIRjHKZ2u6hKEemhzxr1yyKTnJVGDN07hmfMbCyLsiWnFfShZwfv
 g7USgiXjFfpvU5Q7QWpiCapfAaEpevRqieGzRjSbPy5Frm3XT7v+hWbFnvIJqUPj
 5/SMV8I4qtKQe15Qah292HB//oaFM/AvRtHWvQkre3YIqFwyCYimQtjqoRCYC1E=
 =x0ub
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging

pc, virtio enhancements

Memory hot-unplug support for pc, MSI-X
mapping update speedup for virtio-pci,
misc refactorings and bugfixes.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Mon May 11 08:23:43 2015 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream: (28 commits)
  acpi: update expected files for memory unplug
  virtio-scsi: Move DEFINE_VIRTIO_SCSI_FEATURES to virtio-scsi
  virtio-net: Move DEFINE_VIRTIO_NET_FEATURES to virtio-net
  pci: Merge pci_nic_init() into pci_nic_init_nofail()
  acpi: add a missing backslash to the \_SB scope.
  qmp-event: add event notification for memory hot unplug error
  acpi: add hardware implementation for memory hot unplug
  acpi: fix "Memory device control fields" register
  acpi: extend aml_field() to support UpdateRule
  acpi, mem-hotplug: add unplug cb for memory device
  acpi, mem-hotplug: add unplug request cb for memory device
  acpi, mem-hotplug: add acpi_memory_slot_status() to get MemStatus
  docs: update documentation for memory hot unplug
  virtio: coding style tweak
  pci: remove hard-coded bar size in msix_init_exclusive_bar()
  virtio-pci: speedup MSI-X masking and unmasking
  virtio: introduce vector to virtqueues mapping
  virtio-ccw: using VIRTIO_NO_VECTOR instead of 0 for invalid virtqueue
  monitor: check return value of qemu_find_net_clients_except()
  monitor: replace the magic number 255 with MAX_QUEUE_NUM
  ...

Conflicts:
	hw/s390x/s390-virtio-bus.c

[PMM: fixed conflict in s390_virtio_scsi_properties and
s390_virtio_net_properties arrays; since the result of the
two conflicting patches is to empty the property arrays
completely, the conflict resolution is to remove them entirely.]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2015-05-11 16:21:50 +01:00
commit 0403b0f539
42 changed files with 673 additions and 221 deletions

View File

@ -4,9 +4,7 @@ QEMU memory hotplug
This document explains how to use the memory hotplug feature in QEMU,
which is present since v2.1.0.
Please, note that memory hotunplug is not supported yet. This means
that you're able to add memory, but you're not able to remove it.
Also, proper guest support is required for memory hotplug to work.
Guest support is required for memory hotplug to work.
Basic RAM hotplug
-----------------
@ -74,3 +72,22 @@ comes from regular RAM, 1GB is a 1GB hugepage page and 256MB is from
-device pc-dimm,id=dimm1,memdev=mem1 \
-object memory-backend-file,id=mem2,size=256M,mem-path=/mnt/hugepages-2MB \
-device pc-dimm,id=dimm2,memdev=mem2
RAM hot-unplug
---------------
In order to be able to hot unplug pc-dimm device, QEMU has to be told the ids
of pc-dimm device and memory backend object. The ids were assigned when you hot
plugged memory.
Two monitor commands are used to hot unplug memory:
- "device_del": deletes a front-end pc-dimm device
- "object_del": deletes a memory backend object
For example, assuming that the pc-dimm device with id "dimm1" exists, and its memory
backend is "mem1", the following commands tries to remove it.
(qemu) device_del dimm1
(qemu) object_del mem1

View File

@ -232,6 +232,23 @@ Example:
{ "event": "GUEST_PANICKED",
"data": { "action": "pause" } }
MEM_HOT_UNPLUG_ERROR
--------------------
Emitted when memory hot unplug error occurs.
Data:
- "device": device name (json-string)
- "msg": Informative message (e.g., reason for the error) (json-string)
Example:
{ "event": "MEM_HOT_UNPLUG_ERROR"
"data": { "device": "dimm1",
"msg": "acpi: device unplug for unsupported device"
},
"timestamp": { "seconds": 1265044230, "microseconds": 450486 } }
NIC_RX_FILTER_CHANGED
---------------------

View File

@ -2,7 +2,7 @@ QEMU<->ACPI BIOS memory hotplug interface
--------------------------------------
ACPI BIOS GPE.3 handler is dedicated for notifying OS about memory hot-add
events.
and hot-remove events.
Memory hot-plug interface (IO port 0xa00-0xa17, 1-4 byte access):
---------------------------------------------------------------
@ -19,7 +19,9 @@ Memory hot-plug interface (IO port 0xa00-0xa17, 1-4 byte access):
1: Device insert event, used to distinguish device for which
no device check event to OSPM was issued.
It's valid only when bit 1 is set.
2-7: reserved and should be ignored by OSPM
2: Device remove event, used to distinguish device for which
no device eject request to OSPM was issued.
3-7: reserved and should be ignored by OSPM
[0x15-0x17] reserved
write access:
@ -31,14 +33,62 @@ Memory hot-plug interface (IO port 0xa00-0xa17, 1-4 byte access):
[0xc-0x13] reserved, writes into it are ignored
[0x14] Memory device control fields
bits:
0: reserved, OSPM must clear it before writing to register
0: reserved, OSPM must clear it before writing to register.
Due to BUG in versions prior 2.4 that field isn't cleared
when other fields are written. Keep it reserved and don't
try to reuse it.
1: if set to 1 clears device insert event, set by OSPM
after it has emitted device check event for the
selected memory device
2-7: reserved, OSPM must clear them before writing to register
2: if set to 1 clears device remove event, set by OSPM
after it has emitted device eject request for the
selected memory device
3: if set to 1 initiates device eject, set by OSPM when it
triggers memory device removal and calls _EJ0 method
4-7: reserved, OSPM must clear them before writing to register
Selecting memory device slot beyond present range has no effect on platform:
- write accesses to memory hot-plug registers not documented above are
ignored
- read accesses to memory hot-plug registers not documented above return
all bits set to 1.
Memory hot remove process diagram:
----------------------------------
+-------------++-----------------------++------------------+
|1.QEMU||2.QEMU||3.QEMU|
|device_del+---->+deviceunplugrequest+----->+SendSCItoguest,|
|||cb||returncontrolto|
+-------------++-----------------------+|management|
+------------------+
+---------------------------------------------------------------------+
+---------------------++-------------------------+
|OSPM:|removeevent|OSPM:|
|sendEjectRequest,||Scanmemorydevices|
|clearremoveevent+<-------------+foreventflags|
||||
+---------------------++-------------------------+
|
|
+---------v--------++-----------------------+
|GuestOS:|success|OSPM:|
|processEjection+----------->+Execute_EJ0method, |
|request ||setejectbitinflags|
+------------------++-----------------------+
|failure|
vv
+------------------------++-----------------------+
|OSPM:||QEMU:|
|setOSTevent&status||calldeviceunplugcb|
|fields|||
+------------------------++-----------------------+
||
vv
+------------------++-------------------+
|QEMU:||QEMU:|
|SendOSTQMPevent||Senddevicedeleted|
|||QMPevent|
+------------------+||
+-------------------+

View File

@ -26,6 +26,7 @@
#include <string.h>
#include "hw/acpi/aml-build.h"
#include "qemu/bswap.h"
#include "hw/acpi/bios-linker-loader.h"
static GArray *build_alloc_array(void)
{
@ -635,9 +636,11 @@ Aml *aml_reserved_field(unsigned length)
}
/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefField */
Aml *aml_field(const char *name, AmlFieldFlags flags)
Aml *aml_field(const char *name, AmlAccessType type, AmlUpdateRule rule)
{
Aml *var = aml_bundle(0x81 /* FieldOp */, AML_EXT_PACKAGE);
uint8_t flags = rule << 5 | type;
build_append_namestring(var->buf, "%s", name);
build_append_byte(var->buf, flags);
return var;
@ -891,3 +894,60 @@ Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
dec, addr_gran, addr_min, addr_max,
addr_trans, len, flags);
}
void
build_header(GArray *linker, GArray *table_data,
AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
{
memcpy(&h->signature, sig, 4);
h->length = cpu_to_le32(len);
h->revision = rev;
memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6);
memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
memcpy(h->oem_table_id + 4, sig, 4);
h->oem_revision = cpu_to_le32(1);
memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
h->asl_compiler_revision = cpu_to_le32(1);
h->checksum = 0;
/* Checksum to be filled in by Guest linker */
bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
table_data->data, h, len, &h->checksum);
}
void *acpi_data_push(GArray *table_data, unsigned size)
{
unsigned off = table_data->len;
g_array_set_size(table_data, off + size);
return table_data->data + off;
}
unsigned acpi_data_len(GArray *table)
{
#if GLIB_CHECK_VERSION(2, 22, 0)
assert(g_array_get_element_size(table) == 1);
#endif
return table->len;
}
void acpi_add_table(GArray *table_offsets, GArray *table_data)
{
uint32_t offset = cpu_to_le32(table_data->len);
g_array_append_val(table_offsets, offset);
}
void acpi_build_tables_init(AcpiBuildTables *tables)
{
tables->rsdp = g_array_new(false, true /* clear */, 1);
tables->table_data = g_array_new(false, true /* clear */, 1);
tables->tcpalog = g_array_new(false, true /* clear */, 1);
tables->linker = bios_linker_loader_init();
}
void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
{
void *linker_data = bios_linker_loader_cleanup(tables->linker);
g_free(linker_data);
g_array_free(tables->rsdp, true);
g_array_free(tables->table_data, true);
g_array_free(tables->tcpalog, mfre);
}

View File

@ -400,15 +400,26 @@ void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp)
void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
Error **errp)
{
error_setg(errp, "acpi: device unplug request for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
if (pm->acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
acpi_memory_unplug_request_cb(&pm->acpi_regs, pm->irq,
&pm->acpi_memory_hotplug, dev, errp);
} else {
error_setg(errp, "acpi: device unplug request for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
}
}
void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
Error **errp)
{
error_setg(errp, "acpi: device unplug for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
if (pm->acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
acpi_memory_unplug_cb(&pm->acpi_memory_hotplug, dev, errp);
} else {
error_setg(errp, "acpi: device unplug for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
}
}
void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)

View File

@ -2,6 +2,7 @@
#include "hw/acpi/pc-hotplug.h"
#include "hw/mem/pc-dimm.h"
#include "hw/boards.h"
#include "hw/qdev-core.h"
#include "trace.h"
#include "qapi-event.h"
@ -75,6 +76,7 @@ static uint64_t acpi_memory_hotplug_read(void *opaque, hwaddr addr,
case 0x14: /* pack and return is_* fields */
val |= mdev->is_enabled ? 1 : 0;
val |= mdev->is_inserting ? 2 : 0;
val |= mdev->is_removing ? 4 : 0;
trace_mhp_acpi_read_flags(mem_st->selector, val);
break;
default:
@ -90,6 +92,9 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
MemHotplugState *mem_st = opaque;
MemStatus *mdev;
ACPIOSTInfo *info;
DeviceState *dev = NULL;
HotplugHandler *hotplug_ctrl = NULL;
Error *local_err = NULL;
if (!mem_st->dev_count) {
return;
@ -127,13 +132,36 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
qapi_event_send_acpi_device_ost(info, &error_abort);
qapi_free_ACPIOSTInfo(info);
break;
case 0x14:
case 0x14: /* set is_* fields */
mdev = &mem_st->devs[mem_st->selector];
if (data & 2) { /* clear insert event */
mdev->is_inserting = false;
trace_mhp_acpi_clear_insert_evt(mem_st->selector);
} else if (data & 4) {
mdev->is_removing = false;
trace_mhp_acpi_clear_remove_evt(mem_st->selector);
} else if (data & 8) {
if (!mdev->is_enabled) {
trace_mhp_acpi_ejecting_invalid_slot(mem_st->selector);
break;
}
dev = DEVICE(mdev->dimm);
hotplug_ctrl = qdev_get_hotplug_handler(dev);
/* call pc-dimm unplug cb */
hotplug_handler_unplug(hotplug_ctrl, dev, &local_err);
if (local_err) {
trace_mhp_acpi_pc_dimm_delete_failed(mem_st->selector);
qapi_event_send_mem_unplug_error(dev->id,
error_get_pretty(local_err),
&error_abort);
break;
}
trace_mhp_acpi_pc_dimm_deleted(mem_st->selector);
}
break;
default:
break;
}
}
@ -163,29 +191,51 @@ void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner,
memory_region_add_subregion(as, ACPI_MEMORY_HOTPLUG_BASE, &state->io);
}
void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
DeviceState *dev, Error **errp)
/**
* acpi_memory_slot_status:
* @mem_st: memory hotplug state
* @dev: device
* @errp: set in case of an error
*
* Obtain a single memory slot status.
*
* This function will be called by memory unplug request cb and unplug cb.
*/
static MemStatus *
acpi_memory_slot_status(MemHotplugState *mem_st,
DeviceState *dev, Error **errp)
{
MemStatus *mdev;
Error *local_err = NULL;
int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
&local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
return NULL;
}
if (slot >= mem_st->dev_count) {
char *dev_path = object_get_canonical_path(OBJECT(dev));
error_setg(errp, "acpi_memory_plug_cb: "
error_setg(errp, "acpi_memory_slot_status: "
"device [%s] returned invalid memory slot[%d]",
dev_path, slot);
g_free(dev_path);
return NULL;
}
return &mem_st->devs[slot];
}
void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
DeviceState *dev, Error **errp)
{
MemStatus *mdev;
mdev = acpi_memory_slot_status(mem_st, dev, errp);
if (!mdev) {
return;
}
mdev = &mem_st->devs[slot];
mdev->dimm = dev;
mdev->is_enabled = true;
mdev->is_inserting = true;
@ -196,6 +246,38 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
return;
}
void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq,
MemHotplugState *mem_st,
DeviceState *dev, Error **errp)
{
MemStatus *mdev;
mdev = acpi_memory_slot_status(mem_st, dev, errp);
if (!mdev) {
return;
}
mdev->is_removing = true;
/* Do ACPI magic */
ar->gpe.sts[0] |= ACPI_MEMORY_HOTPLUG_STATUS;
acpi_update_sci(ar, irq);
}
void acpi_memory_unplug_cb(MemHotplugState *mem_st,
DeviceState *dev, Error **errp)
{
MemStatus *mdev;
mdev = acpi_memory_slot_status(mem_st, dev, errp);
if (!mdev) {
return;
}
mdev->is_enabled = false;
mdev->dimm = NULL;
}
static const VMStateDescription vmstate_memhp_sts = {
.name = "memory hotplug device state",
.version_id = 1,

View File

@ -361,7 +361,11 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev,
{
PIIX4PMState *s = PIIX4_PM(hotplug_dev);
if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
if (s->acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
acpi_memory_unplug_request_cb(&s->ar, s->irq, &s->acpi_memory_hotplug,
dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
acpi_pcihp_device_unplug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev,
errp);
} else {
@ -373,8 +377,15 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev,
static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
error_setg(errp, "acpi: device unplug for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
PIIX4PMState *s = PIIX4_PM(hotplug_dev);
if (s->acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
acpi_memory_unplug_cb(&s->acpi_memory_hotplug, dev, errp);
} else {
error_setg(errp, "acpi: device unplug for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
}
}
static void piix4_update_bus_hotplug(PCIBus *pci_bus, void *opaque)

View File

@ -273,7 +273,7 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
dev->alias_required_for_version = required_for_version;
}
static HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev)
{
HotplugHandler *hotplug_ctrl = NULL;

View File

@ -32,7 +32,7 @@
#include "hw/i386/pc.h"
#include "target-i386/cpu.h"
#include "hw/timer/hpet.h"
#include "hw/i386/acpi-defs.h"
#include "hw/acpi/acpi-defs.h"
#include "hw/acpi/acpi.h"
#include "hw/nvram/fw_cfg.h"
#include "hw/acpi/bios-linker-loader.h"
@ -68,9 +68,6 @@
#define ACPI_BUILD_TABLE_SIZE 0x20000
/* Reserve RAM space for tables: add another order of magnitude. */
#define ACPI_BUILD_TABLE_MAX_SIZE 0x200000
/* #define DEBUG_ACPI_BUILD */
#ifdef DEBUG_ACPI_BUILD
#define ACPI_BUILD_DPRINTF(fmt, ...) \
@ -265,51 +262,8 @@ static void acpi_get_pci_info(PcPciInfo *info)
NULL);
}
#define ACPI_BUILD_APPNAME "Bochs"
#define ACPI_BUILD_APPNAME6 "BOCHS "
#define ACPI_BUILD_APPNAME4 "BXPC"
#define ACPI_BUILD_TABLE_FILE "etc/acpi/tables"
#define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp"
#define ACPI_BUILD_TPMLOG_FILE "etc/tpm/log"
static void
build_header(GArray *linker, GArray *table_data,
AcpiTableHeader *h, const char *sig, int len, uint8_t rev)
{
memcpy(&h->signature, sig, 4);
h->length = cpu_to_le32(len);
h->revision = rev;
memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6);
memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
memcpy(h->oem_table_id + 4, sig, 4);
h->oem_revision = cpu_to_le32(1);
memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
h->asl_compiler_revision = cpu_to_le32(1);
h->checksum = 0;
/* Checksum to be filled in by Guest linker */
bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
table_data->data, h, len, &h->checksum);
}
/* End here */
#define ACPI_PORT_SMI_CMD 0x00b2 /* TODO: this is APM_CNT_IOPORT */
static inline void *acpi_data_push(GArray *table_data, unsigned size)
{
unsigned off = table_data->len;
g_array_set_size(table_data, off + size);
return table_data->data + off;
}
static unsigned acpi_data_len(GArray *table)
{
#if GLIB_CHECK_VERSION(2, 22, 0)
assert(g_array_get_element_size(table) == 1);
#endif
return table->len;
}
static void acpi_align_size(GArray *blob, unsigned align)
{
/* Align size to multiple of given size. This reduces the chance
@ -318,12 +272,6 @@ static void acpi_align_size(GArray *blob, unsigned align)
g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
}
static inline void acpi_add_table(GArray *table_offsets, GArray *table_data)
{
uint32_t offset = cpu_to_le32(table_data->len);
g_array_append_val(table_offsets, offset);
}
/* FACS */
static void
build_facs(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
@ -796,7 +744,7 @@ build_ssdt(GArray *table_data, GArray *linker,
aml_append(dev, aml_operation_region("PEOR", aml_system_io,
misc->pvpanic_port, 1));
field = aml_field("PEOR", aml_byte_acc);
field = aml_field("PEOR", aml_byte_acc, aml_preserve);
aml_append(field, aml_named_field("PEPT", 8));
aml_append(dev, field);
@ -813,7 +761,7 @@ build_ssdt(GArray *table_data, GArray *linker,
aml_append(ssdt, scope);
}
sb_scope = aml_scope("_SB");
sb_scope = aml_scope("\\_SB");
{
/* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */
dev = aml_device("PCI0." stringify(CPU_HOTPLUG_RESOURCE_DEVICE));
@ -833,7 +781,7 @@ build_ssdt(GArray *table_data, GArray *linker,
/* declare CPU hotplug MMIO region and PRS field to access it */
aml_append(sb_scope, aml_operation_region(
"PRST", aml_system_io, pm->cpu_hp_io_base, pm->cpu_hp_io_len));
field = aml_field("PRST", aml_byte_acc);
field = aml_field("PRST", aml_byte_acc, aml_preserve);
aml_append(field, aml_named_field("PRS", 256));
aml_append(sb_scope, field);
@ -907,7 +855,8 @@ build_ssdt(GArray *table_data, GArray *linker,
pm->mem_hp_io_base, pm->mem_hp_io_len)
);
field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_dword_acc);
field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_dword_acc,
aml_preserve);
aml_append(field, /* read only */
aml_named_field(stringify(MEMORY_SLOT_ADDR_LOW), 32));
aml_append(field, /* read only */
@ -920,16 +869,24 @@ build_ssdt(GArray *table_data, GArray *linker,
aml_named_field(stringify(MEMORY_SLOT_PROXIMITY), 32));
aml_append(scope, field);
field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_byte_acc);
field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_byte_acc,
aml_write_as_zeros);
aml_append(field, aml_reserved_field(160 /* bits, Offset(20) */));
aml_append(field, /* 1 if enabled, read only */
aml_named_field(stringify(MEMORY_SLOT_ENABLED), 1));
aml_append(field,
/*(read) 1 if has a insert event. (write) 1 to clear event */
aml_named_field(stringify(MEMORY_SLOT_INSERT_EVENT), 1));
aml_append(field,
/* (read) 1 if has a remove event. (write) 1 to clear event */
aml_named_field(stringify(MEMORY_SLOT_REMOVE_EVENT), 1));
aml_append(field,
/* initiates device eject, write only */
aml_named_field(stringify(MEMORY_SLOT_EJECT), 1));
aml_append(scope, field);
field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_dword_acc);
field = aml_field(stringify(MEMORY_HOTPLUG_IO_REGION), aml_dword_acc,
aml_preserve);
aml_append(field, /* DIMM selector, write only */
aml_named_field(stringify(MEMORY_SLOT_SLECTOR), 32));
aml_append(field, /* _OST event code, write only */
@ -970,11 +927,17 @@ build_ssdt(GArray *table_data, GArray *linker,
)));
aml_append(dev, method);
method = aml_method("_EJ0", 1);
s = BASEPATH stringify(MEMORY_SLOT_EJECT_METHOD);
aml_append(method, aml_return(aml_call2(
s, aml_name("_UID"), aml_arg(0))));
aml_append(dev, method);
aml_append(sb_scope, dev);
}
/* build Method(MEMORY_SLOT_NOTIFY_METHOD, 2) {
* If (LEqual(Arg0, 0x00)) {Notify(MP00, Arg1)} ...
* If (LEqual(Arg0, 0x00)) {Notify(MP00, Arg1)} ... }
*/
method = aml_method(stringify(MEMORY_SLOT_NOTIFY_METHOD), 2);
for (i = 0; i < nr_mem; i++) {
@ -1293,31 +1256,6 @@ build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
return rsdp_table;
}
typedef
struct AcpiBuildTables {
GArray *table_data;
GArray *rsdp;
GArray *tcpalog;
GArray *linker;
} AcpiBuildTables;
static inline void acpi_build_tables_init(AcpiBuildTables *tables)
{
tables->rsdp = g_array_new(false, true /* clear */, 1);
tables->table_data = g_array_new(false, true /* clear */, 1);
tables->tcpalog = g_array_new(false, true /* clear */, 1);
tables->linker = bios_linker_loader_init();
}
static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
{
void *linker_data = bios_linker_loader_cleanup(tables->linker);
g_free(linker_data);
g_array_free(tables->rsdp, true);
g_array_free(tables->table_data, true);
g_array_free(tables->tcpalog, mfre);
}
typedef
struct AcpiBuildState {
/* Copy of table in RAM (for patching). */

View File

@ -29,6 +29,8 @@
External(MEMORY_SLOT_PROXIMITY, FieldUnitObj) // read only
External(MEMORY_SLOT_ENABLED, FieldUnitObj) // 1 if enabled, read only
External(MEMORY_SLOT_INSERT_EVENT, FieldUnitObj) // (read) 1 if has a insert event. (write) 1 to clear event
External(MEMORY_SLOT_REMOVE_EVENT, FieldUnitObj) // (read) 1 if has a remove event. (write) 1 to clear event
External(MEMORY_SLOT_EJECT, FieldUnitObj) // initiates device eject, write only
External(MEMORY_SLOT_SLECTOR, FieldUnitObj) // DIMM selector, write only
External(MEMORY_SLOT_OST_EVENT, FieldUnitObj) // _OST event code, write only
External(MEMORY_SLOT_OST_STATUS, FieldUnitObj) // _OST status code, write only
@ -55,8 +57,10 @@
If (LEqual(MEMORY_SLOT_INSERT_EVENT, One)) { // Memory device needs check
MEMORY_SLOT_NOTIFY_METHOD(Local0, 1)
Store(1, MEMORY_SLOT_INSERT_EVENT)
} Elseif (LEqual(MEMORY_SLOT_REMOVE_EVENT, One)) { // Ejection request
MEMORY_SLOT_NOTIFY_METHOD(Local0, 3)
Store(1, MEMORY_SLOT_REMOVE_EVENT)
}
// TODO: handle memory eject request
Add(Local0, One, Local0) // goto next DIMM
}
Release(MEMORY_SLOT_LOCK)
@ -156,5 +160,12 @@
Store(Arg2, MEMORY_SLOT_OST_STATUS)
Release(MEMORY_SLOT_LOCK)
}
Method(MEMORY_SLOT_EJECT_METHOD, 2) {
Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
Store(1, MEMORY_SLOT_EJECT)
Release(MEMORY_SLOT_LOCK)
}
} // Device()
} // Scope()

View File

@ -1677,6 +1677,52 @@ out:
error_propagate(errp, local_err);
}
static void pc_dimm_unplug_request(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
HotplugHandlerClass *hhc;
Error *local_err = NULL;
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
if (!pcms->acpi_dev) {
error_setg(&local_err,
"memory hotplug is not enabled: missing acpi device");
goto out;
}
hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
out:
error_propagate(errp, local_err);
}
static void pc_dimm_unplug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
MemoryRegion *mr = ddc->get_memory_region(dimm);
HotplugHandlerClass *hhc;
Error *local_err = NULL;
hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
if (local_err) {
goto out;
}
memory_region_del_subregion(&pcms->hotplug_memory, mr);
vmstate_unregister_ram(mr, dev);
object_unparent(OBJECT(dev));
out:
error_propagate(errp, local_err);
}
static void pc_cpu_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
@ -1719,15 +1765,23 @@ static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev,
static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
error_setg(errp, "acpi: device unplug request for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
pc_dimm_unplug_request(hotplug_dev, dev, errp);
} else {
error_setg(errp, "acpi: device unplug request for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
}
}
static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
error_setg(errp, "acpi: device unplug for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
pc_dimm_unplug(hotplug_dev, dev, errp);
} else {
error_setg(errp, "acpi: device unplug for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
}
}
static HotplugHandler *pc_get_hotpug_handler(MachineState *machine,

View File

@ -310,8 +310,13 @@ static void pc_init_pci(MachineState *machine)
pc_init1(machine, 1, 1);
}
static void pc_compat_2_3(MachineState *machine)
{
}
static void pc_compat_2_2(MachineState *machine)
{
pc_compat_2_3(machine);
rsdp_in_ram = false;
x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME);
@ -413,6 +418,12 @@ static void pc_compat_1_2(MachineState *machine)
x86_cpu_compat_kvm_no_autoenable(FEAT_KVM, 1 << KVM_FEATURE_PV_EOI);
}
static void pc_init_pci_2_3(MachineState *machine)
{
pc_compat_2_3(machine);
pc_init_pci(machine);
}
static void pc_init_pci_2_2(MachineState *machine)
{
pc_compat_2_2(machine);
@ -512,19 +523,28 @@ static void pc_xen_hvm_init(MachineState *machine)
.desc = "Standard PC (i440FX + PIIX, 1996)", \
.hot_add_cpu = pc_hot_add_cpu
#define PC_I440FX_2_3_MACHINE_OPTIONS \
#define PC_I440FX_2_4_MACHINE_OPTIONS \
PC_I440FX_MACHINE_OPTIONS, \
.default_machine_opts = "firmware=bios-256k.bin", \
.default_display = "std"
static QEMUMachine pc_i440fx_machine_v2_3 = {
PC_I440FX_2_3_MACHINE_OPTIONS,
.name = "pc-i440fx-2.3",
static QEMUMachine pc_i440fx_machine_v2_4 = {
PC_I440FX_2_4_MACHINE_OPTIONS,
.name = "pc-i440fx-2.4",
.alias = "pc",
.init = pc_init_pci,
.is_default = 1,
};
#define PC_I440FX_2_3_MACHINE_OPTIONS PC_I440FX_2_4_MACHINE_OPTIONS
static QEMUMachine pc_i440fx_machine_v2_3 = {
PC_I440FX_2_3_MACHINE_OPTIONS,
.name = "pc-i440fx-2.3",
.init = pc_init_pci_2_3,
};
#define PC_I440FX_2_2_MACHINE_OPTIONS PC_I440FX_2_3_MACHINE_OPTIONS
static QEMUMachine pc_i440fx_machine_v2_2 = {
@ -970,6 +990,7 @@ static QEMUMachine xenfv_machine = {
static void pc_machine_init(void)
{
qemu_register_pc_machine(&pc_i440fx_machine_v2_4);
qemu_register_pc_machine(&pc_i440fx_machine_v2_3);
qemu_register_pc_machine(&pc_i440fx_machine_v2_2);
qemu_register_pc_machine(&pc_i440fx_machine_v2_1);

View File

@ -289,8 +289,13 @@ static void pc_q35_init(MachineState *machine)
}
}
static void pc_compat_2_3(MachineState *machine)
{
}
static void pc_compat_2_2(MachineState *machine)
{
pc_compat_2_3(machine);
rsdp_in_ram = false;
x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME);
@ -361,6 +366,12 @@ static void pc_compat_1_4(MachineState *machine)
x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
}
static void pc_q35_init_2_3(MachineState *machine)
{
pc_compat_2_3(machine);
pc_q35_init(machine);
}
static void pc_q35_init_2_2(MachineState *machine)
{
pc_compat_2_2(machine);
@ -410,16 +421,24 @@ static void pc_q35_init_1_4(MachineState *machine)
.hot_add_cpu = pc_hot_add_cpu, \
.units_per_default_bus = 1
#define PC_Q35_2_3_MACHINE_OPTIONS \
#define PC_Q35_2_4_MACHINE_OPTIONS \
PC_Q35_MACHINE_OPTIONS, \
.default_machine_opts = "firmware=bios-256k.bin", \
.default_display = "std"
static QEMUMachine pc_q35_machine_v2_4 = {
PC_Q35_2_4_MACHINE_OPTIONS,
.name = "pc-q35-2.4",
.alias = "q35",
.init = pc_q35_init,
};
#define PC_Q35_2_3_MACHINE_OPTIONS PC_Q35_2_4_MACHINE_OPTIONS
static QEMUMachine pc_q35_machine_v2_3 = {
PC_Q35_2_3_MACHINE_OPTIONS,
.name = "pc-q35-2.3",
.alias = "q35",
.init = pc_q35_init,
.init = pc_q35_init_2_3,
};
#define PC_Q35_2_2_MACHINE_OPTIONS PC_Q35_2_3_MACHINE_OPTIONS
@ -506,6 +525,7 @@ static QEMUMachine pc_q35_machine_v1_4 = {
static void pc_q35_machine_init(void)
{
qemu_register_pc_machine(&pc_q35_machine_v2_4);
qemu_register_pc_machine(&pc_q35_machine_v2_3);
qemu_register_pc_machine(&pc_q35_machine_v2_2);
qemu_register_pc_machine(&pc_q35_machine_v2_1);

View File

@ -263,6 +263,13 @@ static void vhost_net_stop_one(struct vhost_net *net,
&file);
assert(r >= 0);
}
} else if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
const VhostOps *vhost_ops = net->dev.vhost_ops;
int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
NULL);
assert(r >= 0);
}
}
if (net->nc->info->poll) {
net->nc->info->poll(net->nc, true);

View File

@ -446,6 +446,9 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
VirtIONet *n = VIRTIO_NET(vdev);
NetClientState *nc = qemu_get_queue(n->nic);
/* Firstly sync all virtio-net possible supported features */
features |= n->host_features;
virtio_add_feature(&features, VIRTIO_NET_F_MAC);
if (!peer_has_vnet_hdr(n)) {
@ -1309,7 +1312,7 @@ static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue)
n->multiqueue = multiqueue;
for (i = 2; i <= n->max_queues * 2 + 1; i++) {
for (i = 2; i < n->max_queues * 2 + 1; i++) {
virtio_del_queue(vdev, i);
}
@ -1552,7 +1555,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
vdev, idx, mask);
}
void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features)
static void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features)
{
int i, config_size = 0;
virtio_add_feature(&host_features, VIRTIO_NET_F_MAC);
@ -1585,6 +1588,7 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
NetClientState *nc;
int i;
virtio_net_set_config_size(n, n->host_features);
virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size);
n->max_queues = MAX(n->nic_conf.peers.queues, 1);
@ -1721,6 +1725,7 @@ static void virtio_net_instance_init(Object *obj)
}
static Property virtio_net_properties[] = {
DEFINE_VIRTIO_NET_FEATURES(VirtIONet, host_features),
DEFINE_NIC_PROPERTIES(VirtIONet, nic_conf),
DEFINE_PROP_UINT32("x-txtimer", VirtIONet, net_conf.txtimer,
TX_TIMER_INTERVAL),

View File

@ -295,29 +295,37 @@ int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries,
{
int ret;
char *name;
uint32_t bar_size = 4096;
uint32_t bar_pba_offset = bar_size / 2;
uint32_t bar_pba_size = (nentries / 8 + 1) * 8;
/*
* Migration compatibility dictates that this remains a 4k
* BAR with the vector table in the lower half and PBA in
* the upper half. Do not use these elsewhere!
* the upper half for nentries which is lower or equal to 128.
* No need to care about using more than 65 entries for legacy
* machine types who has at most 64 queues.
*/
#define MSIX_EXCLUSIVE_BAR_SIZE 4096
#define MSIX_EXCLUSIVE_BAR_TABLE_OFFSET 0
#define MSIX_EXCLUSIVE_BAR_PBA_OFFSET (MSIX_EXCLUSIVE_BAR_SIZE / 2)
#define MSIX_EXCLUSIVE_CAP_OFFSET 0
if (nentries * PCI_MSIX_ENTRY_SIZE > bar_pba_offset) {
bar_pba_offset = nentries * PCI_MSIX_ENTRY_SIZE;
}
if (nentries * PCI_MSIX_ENTRY_SIZE > MSIX_EXCLUSIVE_BAR_PBA_OFFSET) {
return -EINVAL;
if (bar_pba_offset + bar_pba_size > 4096) {
bar_size = bar_pba_offset + bar_pba_size;
}
if (bar_size & (bar_size - 1)) {
bar_size = 1 << qemu_fls(bar_size);
}
name = g_strdup_printf("%s-msix", dev->name);
memory_region_init(&dev->msix_exclusive_bar, OBJECT(dev), name, MSIX_EXCLUSIVE_BAR_SIZE);
memory_region_init(&dev->msix_exclusive_bar, OBJECT(dev), name, bar_size);
g_free(name);
ret = msix_init(dev, nentries, &dev->msix_exclusive_bar, bar_nr,
MSIX_EXCLUSIVE_BAR_TABLE_OFFSET, &dev->msix_exclusive_bar,
bar_nr, MSIX_EXCLUSIVE_BAR_PBA_OFFSET,
MSIX_EXCLUSIVE_CAP_OFFSET);
0, &dev->msix_exclusive_bar,
bar_nr, bar_pba_offset,
0);
if (ret) {
return ret;
}

View File

@ -1615,28 +1615,32 @@ static const char * const pci_nic_names[] = {
};
/* Initialize a PCI NIC. */
static PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus,
PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
const char *default_model,
const char *default_devaddr,
Error **errp)
const char *default_devaddr)
{
const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr;
Error *err = NULL;
PCIBus *bus;
int devfn;
PCIDevice *pci_dev;
DeviceState *dev;
int devfn;
int i;
if (qemu_show_nic_models(nd->model, pci_nic_models)) {
exit(0);
}
i = qemu_find_nic_model(nd, pci_nic_models, default_model);
if (i < 0)
return NULL;
if (i < 0) {
exit(1);
}
bus = pci_get_bus_devfn(&devfn, rootbus, devaddr);
if (!bus) {
error_report("Invalid PCI device address %s for device %s",
devaddr, pci_nic_names[i]);
return NULL;
exit(1);
}
pci_dev = pci_create(bus, devfn, pci_nic_names[i]);
@ -1645,31 +1649,12 @@ static PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus,
object_property_set_bool(OBJECT(dev), true, "realized", &err);
if (err) {
error_propagate(errp, err);
error_report_err(err);
object_unparent(OBJECT(dev));
return NULL;
}
return pci_dev;
}
PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
const char *default_model,
const char *default_devaddr)
{
Error *err = NULL;
PCIDevice *res;
if (qemu_show_nic_models(nd->model, pci_nic_models))
exit(0);
res = pci_nic_init(nd, rootbus, default_model, default_devaddr, &err);
if (!res) {
if (err) {
error_report_err(err);
}
exit(1);
}
return res;
return pci_dev;
}
PCIDevice *pci_vga_init(PCIBus *bus)

View File

@ -1825,6 +1825,38 @@ static const TypeInfo spapr_machine_info = {
#define SPAPR_COMPAT_2_1 \
SPAPR_COMPAT_2_2
static void spapr_compat_2_3(Object *obj)
{
}
static void spapr_compat_2_2(Object *obj)
{
spapr_compat_2_3(obj);
}
static void spapr_compat_2_1(Object *obj)
{
spapr_compat_2_2(obj);
}
static void spapr_machine_2_3_instance_init(Object *obj)
{
spapr_compat_2_3(obj);
spapr_machine_initfn(obj);
}
static void spapr_machine_2_2_instance_init(Object *obj)
{
spapr_compat_2_2(obj);
spapr_machine_initfn(obj);
}
static void spapr_machine_2_1_instance_init(Object *obj)
{
spapr_compat_2_1(obj);
spapr_machine_initfn(obj);
}
static void spapr_machine_2_1_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@ -1843,6 +1875,7 @@ static const TypeInfo spapr_machine_2_1_info = {
.name = TYPE_SPAPR_MACHINE "2.1",
.parent = TYPE_SPAPR_MACHINE,
.class_init = spapr_machine_2_1_class_init,
.instance_init = spapr_machine_2_1_instance_init,
};
static void spapr_machine_2_2_class_init(ObjectClass *oc, void *data)
@ -1862,6 +1895,7 @@ static const TypeInfo spapr_machine_2_2_info = {
.name = TYPE_SPAPR_MACHINE "2.2",
.parent = TYPE_SPAPR_MACHINE,
.class_init = spapr_machine_2_2_class_init,
.instance_init = spapr_machine_2_2_instance_init,
};
static void spapr_machine_2_3_class_init(ObjectClass *oc, void *data)
@ -1870,14 +1904,29 @@ static void spapr_machine_2_3_class_init(ObjectClass *oc, void *data)
mc->name = "pseries-2.3";
mc->desc = "pSeries Logical Partition (PAPR compliant) v2.3";
mc->alias = "pseries";
mc->is_default = 1;
}
static const TypeInfo spapr_machine_2_3_info = {
.name = TYPE_SPAPR_MACHINE "2.3",
.parent = TYPE_SPAPR_MACHINE,
.class_init = spapr_machine_2_3_class_init,
.instance_init = spapr_machine_2_3_instance_init,
};
static void spapr_machine_2_4_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
mc->name = "pseries-2.4";
mc->desc = "pSeries Logical Partition (PAPR compliant) v2.4";
mc->alias = "pseries";
mc->is_default = 1;
}
static const TypeInfo spapr_machine_2_4_info = {
.name = TYPE_SPAPR_MACHINE "2.4",
.parent = TYPE_SPAPR_MACHINE,
.class_init = spapr_machine_2_4_class_init,
};
static void spapr_machine_register_types(void)
@ -1886,6 +1935,7 @@ static void spapr_machine_register_types(void)
type_register_static(&spapr_machine_2_1_info);
type_register_static(&spapr_machine_2_2_info);
type_register_static(&spapr_machine_2_3_info);
type_register_static(&spapr_machine_2_4_info);
}
type_init(spapr_machine_register_types)

View File

@ -155,7 +155,6 @@ static void s390_virtio_net_realize(VirtIOS390Device *s390_dev, Error **errp)
DeviceState *vdev = DEVICE(&dev->vdev);
Error *err = NULL;
virtio_net_set_config_size(&dev->vdev, s390_dev->host_features);
virtio_net_set_netclient_name(&dev->vdev, qdev->id,
object_get_typename(OBJECT(qdev)));
qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
@ -537,18 +536,12 @@ static unsigned virtio_s390_get_features(DeviceState *d)
/**************** S390 Virtio Bus Device Descriptions *******************/
static Property s390_virtio_net_properties[] = {
DEFINE_VIRTIO_NET_FEATURES(VirtIOS390Device, host_features),
DEFINE_PROP_END_OF_LIST(),
};
static void s390_virtio_net_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
k->realize = s390_virtio_net_realize;
dc->props = s390_virtio_net_properties;
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
}
@ -657,18 +650,12 @@ static const TypeInfo virtio_s390_device_info = {
.abstract = true,
};
static Property s390_virtio_scsi_properties[] = {
DEFINE_VIRTIO_SCSI_FEATURES(VirtIOS390Device, host_features),
DEFINE_PROP_END_OF_LIST(),
};
static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
k->realize = s390_virtio_scsi_realize;
dc->props = s390_virtio_scsi_properties;
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
}

View File

@ -281,7 +281,7 @@ static int virtio_ccw_set_vqs(SubchDev *sch, uint64_t addr, uint32_t align,
virtio_queue_set_addr(vdev, index, addr);
if (!addr) {
virtio_queue_set_vector(vdev, index, 0);
virtio_queue_set_vector(vdev, index, VIRTIO_NO_VECTOR);
} else {
/* Fail if we don't have a big enough queue. */
/* TODO: Add interface to handle vring.num changing */
@ -805,7 +805,6 @@ static void virtio_ccw_net_realize(VirtioCcwDevice *ccw_dev, Error **errp)
DeviceState *vdev = DEVICE(&dev->vdev);
Error *err = NULL;
virtio_net_set_config_size(&dev->vdev, ccw_dev->host_features[0]);
virtio_net_set_netclient_name(&dev->vdev, qdev->id,
object_get_typename(OBJECT(qdev)));
qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
@ -1441,7 +1440,6 @@ static void virtio_ccw_device_unplugged(DeviceState *d)
static Property virtio_ccw_net_properties[] = {
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
DEFINE_VIRTIO_NET_FEATURES(VirtioCcwDevice, host_features[0]),
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_END_OF_LIST(),
@ -1550,7 +1548,6 @@ static const TypeInfo virtio_ccw_balloon = {
static Property virtio_ccw_scsi_properties[] = {
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features[0]),
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_END_OF_LIST(),

View File

@ -631,6 +631,10 @@ static void virtio_scsi_set_config(VirtIODevice *vdev,
static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
uint32_t requested_features)
{
VirtIOSCSI *s = VIRTIO_SCSI(vdev);
/* Firstly sync all virtio-scsi possible supported features */
requested_features |= s->host_features;
return requested_features;
}
@ -945,6 +949,7 @@ static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp)
static Property virtio_scsi_properties[] = {
DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSI, parent_obj.conf),
DEFINE_VIRTIO_SCSI_FEATURES(VirtIOSCSI, host_features),
DEFINE_PROP_END_OF_LIST(),
};

View File

@ -630,28 +630,30 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
{
VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
int ret, queue_no;
VirtQueue *vq = virtio_vector_first_queue(vdev, vector);
int ret, index, unmasked = 0;
for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) {
if (!virtio_queue_get_num(vdev, queue_no)) {
while (vq) {
index = virtio_get_queue_index(vq);
if (!virtio_queue_get_num(vdev, index)) {
break;
}
if (virtio_queue_vector(vdev, queue_no) != vector) {
continue;
}
ret = virtio_pci_vq_vector_unmask(proxy, queue_no, vector, msg);
ret = virtio_pci_vq_vector_unmask(proxy, index, vector, msg);
if (ret < 0) {
goto undo;
}
vq = virtio_vector_next_queue(vq);
++unmasked;
}
return 0;
undo:
while (--queue_no >= 0) {
if (virtio_queue_vector(vdev, queue_no) != vector) {
continue;
}
virtio_pci_vq_vector_mask(proxy, queue_no, vector);
vq = virtio_vector_first_queue(vdev, vector);
while (vq && --unmasked >= 0) {
index = virtio_get_queue_index(vq);
virtio_pci_vq_vector_mask(proxy, index, vector);
vq = virtio_vector_next_queue(vq);
}
return ret;
}
@ -660,16 +662,16 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector)
{
VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
int queue_no;
VirtQueue *vq = virtio_vector_first_queue(vdev, vector);
int index;
for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) {
if (!virtio_queue_get_num(vdev, queue_no)) {
while (vq) {
index = virtio_get_queue_index(vq);
if (!virtio_queue_get_num(vdev, index)) {
break;
}
if (virtio_queue_vector(vdev, queue_no) != vector) {
continue;
}
virtio_pci_vq_vector_mask(proxy, queue_no, vector);
virtio_pci_vq_vector_mask(proxy, index, vector);
vq = virtio_vector_next_queue(vq);
}
}
@ -908,6 +910,13 @@ static const TypeInfo virtio_9p_pci_info = {
* virtio-pci: This is the PCIDevice which has a virtio-pci-bus.
*/
static int virtio_pci_query_nvectors(DeviceState *d)
{
VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
return proxy->nvectors;
}
/* This is called by virtio-bus just after the device is plugged. */
static void virtio_pci_device_plugged(DeviceState *d)
{
@ -1078,7 +1087,6 @@ static Property virtio_scsi_pci_properties[] = {
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
DEV_NVECTORS_UNSPECIFIED),
DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_PROP_END_OF_LIST(),
};
@ -1360,7 +1368,6 @@ static Property virtio_net_properties[] = {
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_PROP_END_OF_LIST(),
};
@ -1370,7 +1377,6 @@ static void virtio_net_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
VirtIONetPCI *dev = VIRTIO_NET_PCI(vpci_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
virtio_net_set_config_size(&dev->vdev, vpci_dev->host_features);
virtio_net_set_netclient_name(&dev->vdev, qdev->id,
object_get_typename(OBJECT(qdev)));
qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
@ -1498,6 +1504,7 @@ static void virtio_pci_bus_class_init(ObjectClass *klass, void *data)
k->vmstate_change = virtio_pci_vmstate_change;
k->device_plugged = virtio_pci_device_plugged;
k->device_unplugged = virtio_pci_device_unplugged;
k->query_nvectors = virtio_pci_query_nvectors;
}
static const TypeInfo virtio_pci_bus_info = {

View File

@ -89,6 +89,7 @@ struct VirtQueue
VirtIODevice *vdev;
EventNotifier guest_notifier;
EventNotifier host_notifier;
QLIST_ENTRY(VirtQueue) node;
};
/* virt queue functions */
@ -605,7 +606,7 @@ void virtio_reset(void *opaque)
vdev->vq[i].vring.used = 0;
vdev->vq[i].last_avail_idx = 0;
vdev->vq[i].pa = 0;
vdev->vq[i].vector = VIRTIO_NO_VECTOR;
virtio_queue_set_vector(vdev, i, VIRTIO_NO_VECTOR);
vdev->vq[i].signalled_used = 0;
vdev->vq[i].signalled_used_valid = false;
vdev->vq[i].notification = true;
@ -730,6 +731,16 @@ void virtio_queue_set_num(VirtIODevice *vdev, int n, int num)
virtqueue_init(&vdev->vq[n]);
}
VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector)
{
return QLIST_FIRST(&vdev->vector_queues[vector]);
}
VirtQueue *virtio_vector_next_queue(VirtQueue *vq)
{
return QLIST_NEXT(vq, node);
}
int virtio_queue_get_num(VirtIODevice *vdev, int n)
{
return vdev->vq[n].vring.num;
@ -780,8 +791,19 @@ uint16_t virtio_queue_vector(VirtIODevice *vdev, int n)
void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector)
{
if (n < VIRTIO_PCI_QUEUE_MAX)
VirtQueue *vq = &vdev->vq[n];
if (n < VIRTIO_PCI_QUEUE_MAX) {
if (vdev->vector_queues &&
vdev->vq[n].vector != VIRTIO_NO_VECTOR) {
QLIST_REMOVE(vq, node);
}
vdev->vq[n].vector = vector;
if (vdev->vector_queues &&
vector != VIRTIO_NO_VECTOR) {
QLIST_INSERT_HEAD(&vdev->vector_queues[vector], vq, node);
}
}
}
VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
@ -1088,6 +1110,7 @@ void virtio_cleanup(VirtIODevice *vdev)
qemu_del_vm_change_state_handler(vdev->vmstate);
g_free(vdev->config);
g_free(vdev->vq);
g_free(vdev->vector_queues);
}
static void virtio_vmstate_change(void *opaque, int running, RunState state)
@ -1125,7 +1148,16 @@ void virtio_instance_init_common(Object *proxy_obj, void *data,
void virtio_init(VirtIODevice *vdev, const char *name,
uint16_t device_id, size_t config_size)
{
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
int i;
int nvectors = k->query_nvectors ? k->query_nvectors(qbus->parent) : 0;
if (nvectors) {
vdev->vector_queues =
g_malloc0(sizeof(*vdev->vector_queues) * nvectors);
}
vdev->device_id = device_id;
vdev->status = 0;
vdev->isr = 0;

View File

@ -4,6 +4,18 @@
#include <stdint.h>
#include <glib.h>
#include "qemu/compiler.h"
#include "hw/acpi/acpi-defs.h"
/* Reserve RAM space for tables: add another order of magnitude. */
#define ACPI_BUILD_TABLE_MAX_SIZE 0x200000
#define ACPI_BUILD_APPNAME "Bochs"
#define ACPI_BUILD_APPNAME6 "BOCHS "
#define ACPI_BUILD_APPNAME4 "BXPC"
#define ACPI_BUILD_TABLE_FILE "etc/acpi/tables"
#define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp"
#define ACPI_BUILD_TPMLOG_FILE "etc/tpm/log"
typedef enum {
AML_NO_OPCODE = 0,/* has only data */
@ -35,7 +47,13 @@ typedef enum {
aml_dword_acc = 3,
aml_qword_acc = 4,
aml_buffer_acc = 5,
} AmlFieldFlags;
} AmlAccessType;
typedef enum {
aml_preserve = 0,
aml_write_as_ones = 1,
aml_write_as_zeros = 2,
} AmlUpdateRule;
typedef enum {
aml_system_memory = 0x00,
@ -93,6 +111,14 @@ typedef enum {
aml_ReadWrite = 1,
} AmlReadAndWrite;
typedef
struct AcpiBuildTables {
GArray *table_data;
GArray *rsdp;
GArray *tcpalog;
GArray *linker;
} AcpiBuildTables;
/**
* init_aml_allocator:
*
@ -120,7 +146,7 @@ void free_aml_allocator(void);
* Joins Aml elements together and helps to construct AML tables
* Examle of usage:
* Aml *table = aml_def_block("SSDT", ...);
* Aml *sb = aml_scope("\_SB");
* Aml *sb = aml_scope("\\_SB");
* Aml *dev = aml_device("PCI0");
*
* aml_append(dev, aml_name_decl("HID", aml_eisaid("PNP0A03")));
@ -185,7 +211,16 @@ Aml *aml_if(Aml *predicate);
Aml *aml_package(uint8_t num_elements);
Aml *aml_buffer(void);
Aml *aml_resource_template(void);
Aml *aml_field(const char *name, AmlFieldFlags flags);
Aml *aml_field(const char *name, AmlAccessType type, AmlUpdateRule rule);
Aml *aml_varpackage(uint32_t num_elements);
void
build_header(GArray *linker, GArray *table_data,
AcpiTableHeader *h, const char *sig, int len, uint8_t rev);
void *acpi_data_push(GArray *table_data, unsigned size);
unsigned acpi_data_len(GArray *table);
void acpi_add_table(GArray *table_offsets, GArray *table_data);
void acpi_build_tables_init(AcpiBuildTables *tables);
void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre);
#endif

View File

@ -7,10 +7,17 @@
#define ACPI_MEMORY_HOTPLUG_STATUS 8
/**
* MemStatus:
* @is_removing: the memory device in slot has been requested to be ejected.
*
* This structure stores memory device's status.
*/
typedef struct MemStatus {
DeviceState *dimm;
bool is_enabled;
bool is_inserting;
bool is_removing;
uint32_t ost_event;
uint32_t ost_status;
} MemStatus;
@ -28,6 +35,11 @@ void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner,
void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
DeviceState *dev, Error **errp);
void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq,
MemHotplugState *mem_st,
DeviceState *dev, Error **errp);
void acpi_memory_unplug_cb(MemHotplugState *mem_st,
DeviceState *dev, Error **errp);
extern const VMStateDescription vmstate_memory_hotplug;
#define VMSTATE_MEMORY_HOTPLUG(memhp, state) \

View File

@ -43,6 +43,8 @@
#define MEMORY_SLOT_PROXIMITY MPX
#define MEMORY_SLOT_ENABLED MES
#define MEMORY_SLOT_INSERT_EVENT MINS
#define MEMORY_SLOT_REMOVE_EVENT MRMV
#define MEMORY_SLOT_EJECT MEJ
#define MEMORY_SLOT_SLECTOR MSEL
#define MEMORY_SLOT_OST_EVENT MOEV
#define MEMORY_SLOT_OST_STATUS MOSC
@ -51,6 +53,7 @@
#define MEMORY_SLOT_CRS_METHOD MCRS
#define MEMORY_SLOT_OST_METHOD MOST
#define MEMORY_SLOT_PROXIMITY_METHOD MPXM
#define MEMORY_SLOT_EJECT_METHOD MEJ0
#define MEMORY_SLOT_NOTIFY_METHOD MTFY
#define MEMORY_SLOT_SCAN_METHOD MSCN

View File

@ -266,6 +266,7 @@ int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
void qdev_init_nofail(DeviceState *dev);
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
int required_for_version);
HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev);
void qdev_unplug(DeviceState *dev, Error **errp);
void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp);

View File

@ -62,6 +62,7 @@ typedef struct VirtioBusClass {
* This is called by virtio-bus just before the device is unplugged.
*/
void (*device_unplugged)(DeviceState *d);
int (*query_nvectors)(DeviceState *d);
/*
* Does the transport have variable vring alignment?
* (ie can it ever call virtio_queue_set_align()?)

View File

@ -68,6 +68,7 @@ typedef struct VirtIONet {
uint32_t has_vnet_hdr;
size_t host_hdr_len;
size_t guest_hdr_len;
uint32_t host_features;
uint8_t has_ufo;
int mergeable_rx_bufs;
uint8_t promisc;
@ -137,7 +138,6 @@ typedef struct VirtIONet {
DEFINE_PROP_INT32("x-txburst", _state, _field.txburst, TX_BURST), \
DEFINE_PROP_STRING("tx", _state, _field.tx)
void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features);
void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
const char *type);

View File

@ -98,6 +98,7 @@ typedef struct VirtIOSCSI {
bool dataplane_fenced;
Error *blocker;
Notifier migration_state_notifier;
uint32_t host_features;
} VirtIOSCSI;
typedef struct VirtIOSCSIReq {

View File

@ -84,6 +84,7 @@ struct VirtIODevice
VMChangeStateEntry *vmstate;
char *bus_name;
uint8_t device_endian;
QLIST_HEAD(, VirtQueue) *vector_queues;
};
typedef struct VirtioDeviceClass {
@ -218,6 +219,8 @@ void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign,
bool set_handler);
void virtio_queue_notify_vq(VirtQueue *vq);
void virtio_irq(VirtQueue *vq);
VirtQueue *virtio_vector_first_queue(VirtIODevice *vdev, uint16_t vector);
VirtQueue *virtio_vector_next_queue(VirtQueue *vq);
static inline void virtio_add_feature(uint32_t *features, unsigned int fbit)
{

View File

@ -4471,11 +4471,12 @@ void set_link_completion(ReadLineState *rs, int nb_args, const char *str)
len = strlen(str);
readline_set_completion_index(rs, len);
if (nb_args == 2) {
NetClientState *ncs[255];
NetClientState *ncs[MAX_QUEUE_NUM];
int count, i;
count = qemu_find_net_clients_except(NULL, ncs,
NET_CLIENT_OPTIONS_KIND_NONE, 255);
for (i = 0; i < count; i++) {
NET_CLIENT_OPTIONS_KIND_NONE,
MAX_QUEUE_NUM);
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
const char *name = ncs[i]->name;
if (!strncmp(str, name, len)) {
readline_add_completion(rs, name);
@ -4490,7 +4491,7 @@ void set_link_completion(ReadLineState *rs, int nb_args, const char *str)
void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str)
{
int len, count, i;
NetClientState *ncs[255];
NetClientState *ncs[MAX_QUEUE_NUM];
if (nb_args != 2) {
return;
@ -4499,8 +4500,8 @@ void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str)
len = strlen(str);
readline_set_completion_index(rs, len);
count = qemu_find_net_clients_except(NULL, ncs, NET_CLIENT_OPTIONS_KIND_NIC,
255);
for (i = 0; i < count; i++) {
MAX_QUEUE_NUM);
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
QemuOpts *opts;
const char *name = ncs[i]->name;
if (strncmp(str, name, len)) {
@ -4583,15 +4584,16 @@ void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str)
void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str)
{
NetClientState *ncs[255];
NetClientState *ncs[MAX_QUEUE_NUM];
int count, i, len;
len = strlen(str);
readline_set_completion_index(rs, len);
if (nb_args == 2) {
count = qemu_find_net_clients_except(NULL, ncs,
NET_CLIENT_OPTIONS_KIND_NONE, 255);
for (i = 0; i < count; i++) {
NET_CLIENT_OPTIONS_KIND_NONE,
MAX_QUEUE_NUM);
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
int id;
char name[16];
@ -4606,8 +4608,9 @@ void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str)
return;
} else if (nb_args == 3) {
count = qemu_find_net_clients_except(NULL, ncs,
NET_CLIENT_OPTIONS_KIND_NIC, 255);
for (i = 0; i < count; i++) {
NET_CLIENT_OPTIONS_KIND_NIC,
MAX_QUEUE_NUM);
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
int id;
const char *name;

View File

@ -330,3 +330,17 @@
##
{ 'event': 'VSERPORT_CHANGE',
'data': { 'id': 'str', 'open': 'bool' } }
##
# @MEM_UNPLUG_ERROR
#
# Emitted when memory hot unplug error occurs.
#
# @device: device name
#
# @msg: Informative message
#
# Since: 2.4
##
{ 'event': 'MEM_UNPLUG_ERROR',
'data': { 'device': 'str', 'msg': 'str' } }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -17,7 +17,7 @@
#include "qemu-common.h"
#include "libqtest.h"
#include "qemu/compiler.h"
#include "hw/i386/acpi-defs.h"
#include "hw/acpi/acpi-defs.h"
#include "hw/i386/smbios.h"
#include "qemu/bitmap.h"

View File

@ -1562,6 +1562,7 @@ vfio_put_base_device(int fd) "close vdev->fd=%d"
#hw/acpi/memory_hotplug.c
mhp_acpi_invalid_slot_selected(uint32_t slot) "0x%"PRIx32
mhp_acpi_ejecting_invalid_slot(uint32_t slot) "0x%"PRIx32
mhp_acpi_read_addr_lo(uint32_t slot, uint32_t addr) "slot[0x%"PRIx32"] addr lo: 0x%"PRIx32
mhp_acpi_read_addr_hi(uint32_t slot, uint32_t addr) "slot[0x%"PRIx32"] addr hi: 0x%"PRIx32
mhp_acpi_read_size_lo(uint32_t slot, uint32_t size) "slot[0x%"PRIx32"] size lo: 0x%"PRIx32
@ -1572,6 +1573,9 @@ mhp_acpi_write_slot(uint32_t slot) "set active slot: 0x%"PRIx32
mhp_acpi_write_ost_ev(uint32_t slot, uint32_t ev) "slot[0x%"PRIx32"] OST EVENT: 0x%"PRIx32
mhp_acpi_write_ost_status(uint32_t slot, uint32_t st) "slot[0x%"PRIx32"] OST STATUS: 0x%"PRIx32
mhp_acpi_clear_insert_evt(uint32_t slot) "slot[0x%"PRIx32"] clear insert event"
mhp_acpi_clear_remove_evt(uint32_t slot) "slot[0x%"PRIx32"] clear remove event"
mhp_acpi_pc_dimm_deleted(uint32_t slot) "slot[0x%"PRIx32"] pc-dimm deleted"
mhp_acpi_pc_dimm_delete_failed(uint32_t slot) "slot[0x%"PRIx32"] pc-dimm delete failed"
# hw/i386/pc.c
mhp_pc_dimm_assigned_slot(int slot) "0x%d"