mirror of https://github.com/xqemu/xqemu.git
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:
commit
0403b0f539
|
@ -4,9 +4,7 @@ QEMU memory hotplug
|
||||||
This document explains how to use the memory hotplug feature in QEMU,
|
This document explains how to use the memory hotplug feature in QEMU,
|
||||||
which is present since v2.1.0.
|
which is present since v2.1.0.
|
||||||
|
|
||||||
Please, note that memory hotunplug is not supported yet. This means
|
Guest support is required for memory hotplug to work.
|
||||||
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.
|
|
||||||
|
|
||||||
Basic RAM hotplug
|
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 \
|
-device pc-dimm,id=dimm1,memdev=mem1 \
|
||||||
-object memory-backend-file,id=mem2,size=256M,mem-path=/mnt/hugepages-2MB \
|
-object memory-backend-file,id=mem2,size=256M,mem-path=/mnt/hugepages-2MB \
|
||||||
-device pc-dimm,id=dimm2,memdev=mem2
|
-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
|
||||||
|
|
|
@ -232,6 +232,23 @@ Example:
|
||||||
{ "event": "GUEST_PANICKED",
|
{ "event": "GUEST_PANICKED",
|
||||||
"data": { "action": "pause" } }
|
"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
|
NIC_RX_FILTER_CHANGED
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ QEMU<->ACPI BIOS memory hotplug interface
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
ACPI BIOS GPE.3 handler is dedicated for notifying OS about memory hot-add
|
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):
|
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
|
1: Device insert event, used to distinguish device for which
|
||||||
no device check event to OSPM was issued.
|
no device check event to OSPM was issued.
|
||||||
It's valid only when bit 1 is set.
|
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
|
[0x15-0x17] reserved
|
||||||
|
|
||||||
write access:
|
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
|
[0xc-0x13] reserved, writes into it are ignored
|
||||||
[0x14] Memory device control fields
|
[0x14] Memory device control fields
|
||||||
bits:
|
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
|
1: if set to 1 clears device insert event, set by OSPM
|
||||||
after it has emitted device check event for the
|
after it has emitted device check event for the
|
||||||
selected memory device
|
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:
|
Selecting memory device slot beyond present range has no effect on platform:
|
||||||
- write accesses to memory hot-plug registers not documented above are
|
- write accesses to memory hot-plug registers not documented above are
|
||||||
ignored
|
ignored
|
||||||
- read accesses to memory hot-plug registers not documented above return
|
- read accesses to memory hot-plug registers not documented above return
|
||||||
all bits set to 1.
|
all bits set to 1.
|
||||||
|
|
||||||
|
Memory hot remove process diagram:
|
||||||
|
----------------------------------
|
||||||
|
+-------------+ +-----------------------+ +------------------+
|
||||||
|
| 1. QEMU | | 2. QEMU | |3. QEMU |
|
||||||
|
| device_del +---->+ device unplug request +----->+Send SCI to guest,|
|
||||||
|
| | | cb | |return control to |
|
||||||
|
+-------------+ +-----------------------+ |management |
|
||||||
|
+------------------+
|
||||||
|
|
||||||
|
+---------------------------------------------------------------------+
|
||||||
|
|
||||||
|
+---------------------+ +-------------------------+
|
||||||
|
| OSPM: | remove event | OSPM: |
|
||||||
|
| send Eject Request, | | Scan memory devices |
|
||||||
|
| clear remove event +<-------------+ for event flags |
|
||||||
|
| | | |
|
||||||
|
+---------------------+ +-------------------------+
|
||||||
|
|
|
||||||
|
|
|
||||||
|
+---------v--------+ +-----------------------+
|
||||||
|
| Guest OS: | success | OSPM: |
|
||||||
|
| process Ejection +----------->+ Execute _EJ0 method, |
|
||||||
|
| request | | set eject bit in flags|
|
||||||
|
+------------------+ +-----------------------+
|
||||||
|
|failure |
|
||||||
|
v v
|
||||||
|
+------------------------+ +-----------------------+
|
||||||
|
| OSPM: | | QEMU: |
|
||||||
|
| set OST event & status | | call device unplug cb |
|
||||||
|
| fields | | |
|
||||||
|
+------------------------+ +-----------------------+
|
||||||
|
| |
|
||||||
|
v v
|
||||||
|
+------------------+ +-------------------+
|
||||||
|
|QEMU: | |QEMU: |
|
||||||
|
|Send OST QMP event| |Send device deleted|
|
||||||
|
| | |QMP event |
|
||||||
|
+------------------+ | |
|
||||||
|
+-------------------+
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "hw/acpi/aml-build.h"
|
#include "hw/acpi/aml-build.h"
|
||||||
#include "qemu/bswap.h"
|
#include "qemu/bswap.h"
|
||||||
|
#include "hw/acpi/bios-linker-loader.h"
|
||||||
|
|
||||||
static GArray *build_alloc_array(void)
|
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 */
|
/* 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);
|
Aml *var = aml_bundle(0x81 /* FieldOp */, AML_EXT_PACKAGE);
|
||||||
|
uint8_t flags = rule << 5 | type;
|
||||||
|
|
||||||
build_append_namestring(var->buf, "%s", name);
|
build_append_namestring(var->buf, "%s", name);
|
||||||
build_append_byte(var->buf, flags);
|
build_append_byte(var->buf, flags);
|
||||||
return var;
|
return var;
|
||||||
|
@ -891,3 +894,60 @@ Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
|
||||||
dec, addr_gran, addr_min, addr_max,
|
dec, addr_gran, addr_min, addr_max,
|
||||||
addr_trans, len, flags);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
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"
|
error_setg(errp, "acpi: device unplug request for not supported device"
|
||||||
" type: %s", object_get_typename(OBJECT(dev)));
|
" type: %s", object_get_typename(OBJECT(dev)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
|
void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
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"
|
error_setg(errp, "acpi: device unplug for not supported device"
|
||||||
" type: %s", object_get_typename(OBJECT(dev)));
|
" type: %s", object_get_typename(OBJECT(dev)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
|
void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "hw/acpi/pc-hotplug.h"
|
#include "hw/acpi/pc-hotplug.h"
|
||||||
#include "hw/mem/pc-dimm.h"
|
#include "hw/mem/pc-dimm.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
|
#include "hw/qdev-core.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "qapi-event.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 */
|
case 0x14: /* pack and return is_* fields */
|
||||||
val |= mdev->is_enabled ? 1 : 0;
|
val |= mdev->is_enabled ? 1 : 0;
|
||||||
val |= mdev->is_inserting ? 2 : 0;
|
val |= mdev->is_inserting ? 2 : 0;
|
||||||
|
val |= mdev->is_removing ? 4 : 0;
|
||||||
trace_mhp_acpi_read_flags(mem_st->selector, val);
|
trace_mhp_acpi_read_flags(mem_st->selector, val);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -90,6 +92,9 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
|
||||||
MemHotplugState *mem_st = opaque;
|
MemHotplugState *mem_st = opaque;
|
||||||
MemStatus *mdev;
|
MemStatus *mdev;
|
||||||
ACPIOSTInfo *info;
|
ACPIOSTInfo *info;
|
||||||
|
DeviceState *dev = NULL;
|
||||||
|
HotplugHandler *hotplug_ctrl = NULL;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
if (!mem_st->dev_count) {
|
if (!mem_st->dev_count) {
|
||||||
return;
|
return;
|
||||||
|
@ -127,12 +132,35 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
|
||||||
qapi_event_send_acpi_device_ost(info, &error_abort);
|
qapi_event_send_acpi_device_ost(info, &error_abort);
|
||||||
qapi_free_ACPIOSTInfo(info);
|
qapi_free_ACPIOSTInfo(info);
|
||||||
break;
|
break;
|
||||||
case 0x14:
|
case 0x14: /* set is_* fields */
|
||||||
mdev = &mem_st->devs[mem_st->selector];
|
mdev = &mem_st->devs[mem_st->selector];
|
||||||
if (data & 2) { /* clear insert event */
|
if (data & 2) { /* clear insert event */
|
||||||
mdev->is_inserting = false;
|
mdev->is_inserting = false;
|
||||||
trace_mhp_acpi_clear_insert_evt(mem_st->selector);
|
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;
|
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);
|
memory_region_add_subregion(as, ACPI_MEMORY_HOTPLUG_BASE, &state->io);
|
||||||
}
|
}
|
||||||
|
|
||||||
void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
|
/**
|
||||||
|
* 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)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
MemStatus *mdev;
|
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
|
int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
|
||||||
&local_err);
|
&local_err);
|
||||||
|
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slot >= mem_st->dev_count) {
|
if (slot >= mem_st->dev_count) {
|
||||||
char *dev_path = object_get_canonical_path(OBJECT(dev));
|
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]",
|
"device [%s] returned invalid memory slot[%d]",
|
||||||
dev_path, slot);
|
dev_path, slot);
|
||||||
g_free(dev_path);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mdev = &mem_st->devs[slot];
|
|
||||||
mdev->dimm = dev;
|
mdev->dimm = dev;
|
||||||
mdev->is_enabled = true;
|
mdev->is_enabled = true;
|
||||||
mdev->is_inserting = true;
|
mdev->is_inserting = true;
|
||||||
|
@ -196,6 +246,38 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
|
||||||
return;
|
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 = {
|
static const VMStateDescription vmstate_memhp_sts = {
|
||||||
.name = "memory hotplug device state",
|
.name = "memory hotplug device state",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
|
|
|
@ -361,7 +361,11 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||||
{
|
{
|
||||||
PIIX4PMState *s = PIIX4_PM(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,
|
acpi_pcihp_device_unplug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev,
|
||||||
errp);
|
errp);
|
||||||
} else {
|
} else {
|
||||||
|
@ -373,8 +377,15 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||||
static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev,
|
static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev,
|
||||||
DeviceState *dev, Error **errp)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
|
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"
|
error_setg(errp, "acpi: device unplug for not supported device"
|
||||||
" type: %s", object_get_typename(OBJECT(dev)));
|
" type: %s", object_get_typename(OBJECT(dev)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void piix4_update_bus_hotplug(PCIBus *pci_bus, void *opaque)
|
static void piix4_update_bus_hotplug(PCIBus *pci_bus, void *opaque)
|
||||||
|
|
|
@ -273,7 +273,7 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
|
||||||
dev->alias_required_for_version = required_for_version;
|
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;
|
HotplugHandler *hotplug_ctrl = NULL;
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include "hw/i386/pc.h"
|
#include "hw/i386/pc.h"
|
||||||
#include "target-i386/cpu.h"
|
#include "target-i386/cpu.h"
|
||||||
#include "hw/timer/hpet.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/acpi/acpi.h"
|
||||||
#include "hw/nvram/fw_cfg.h"
|
#include "hw/nvram/fw_cfg.h"
|
||||||
#include "hw/acpi/bios-linker-loader.h"
|
#include "hw/acpi/bios-linker-loader.h"
|
||||||
|
@ -68,9 +68,6 @@
|
||||||
|
|
||||||
#define ACPI_BUILD_TABLE_SIZE 0x20000
|
#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 */
|
/* #define DEBUG_ACPI_BUILD */
|
||||||
#ifdef DEBUG_ACPI_BUILD
|
#ifdef DEBUG_ACPI_BUILD
|
||||||
#define ACPI_BUILD_DPRINTF(fmt, ...) \
|
#define ACPI_BUILD_DPRINTF(fmt, ...) \
|
||||||
|
@ -265,51 +262,8 @@ static void acpi_get_pci_info(PcPciInfo *info)
|
||||||
NULL);
|
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 */
|
#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)
|
static void acpi_align_size(GArray *blob, unsigned align)
|
||||||
{
|
{
|
||||||
/* Align size to multiple of given size. This reduces the chance
|
/* 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));
|
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 */
|
/* FACS */
|
||||||
static void
|
static void
|
||||||
build_facs(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
|
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,
|
aml_append(dev, aml_operation_region("PEOR", aml_system_io,
|
||||||
misc->pvpanic_port, 1));
|
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(field, aml_named_field("PEPT", 8));
|
||||||
aml_append(dev, field);
|
aml_append(dev, field);
|
||||||
|
|
||||||
|
@ -813,7 +761,7 @@ build_ssdt(GArray *table_data, GArray *linker,
|
||||||
aml_append(ssdt, scope);
|
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 */
|
/* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */
|
||||||
dev = aml_device("PCI0." stringify(CPU_HOTPLUG_RESOURCE_DEVICE));
|
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 */
|
/* declare CPU hotplug MMIO region and PRS field to access it */
|
||||||
aml_append(sb_scope, aml_operation_region(
|
aml_append(sb_scope, aml_operation_region(
|
||||||
"PRST", aml_system_io, pm->cpu_hp_io_base, pm->cpu_hp_io_len));
|
"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(field, aml_named_field("PRS", 256));
|
||||||
aml_append(sb_scope, field);
|
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)
|
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_append(field, /* read only */
|
||||||
aml_named_field(stringify(MEMORY_SLOT_ADDR_LOW), 32));
|
aml_named_field(stringify(MEMORY_SLOT_ADDR_LOW), 32));
|
||||||
aml_append(field, /* read only */
|
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_named_field(stringify(MEMORY_SLOT_PROXIMITY), 32));
|
||||||
aml_append(scope, field);
|
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, aml_reserved_field(160 /* bits, Offset(20) */));
|
||||||
aml_append(field, /* 1 if enabled, read only */
|
aml_append(field, /* 1 if enabled, read only */
|
||||||
aml_named_field(stringify(MEMORY_SLOT_ENABLED), 1));
|
aml_named_field(stringify(MEMORY_SLOT_ENABLED), 1));
|
||||||
aml_append(field,
|
aml_append(field,
|
||||||
/*(read) 1 if has a insert event. (write) 1 to clear event */
|
/*(read) 1 if has a insert event. (write) 1 to clear event */
|
||||||
aml_named_field(stringify(MEMORY_SLOT_INSERT_EVENT), 1));
|
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);
|
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_append(field, /* DIMM selector, write only */
|
||||||
aml_named_field(stringify(MEMORY_SLOT_SLECTOR), 32));
|
aml_named_field(stringify(MEMORY_SLOT_SLECTOR), 32));
|
||||||
aml_append(field, /* _OST event code, write only */
|
aml_append(field, /* _OST event code, write only */
|
||||||
|
@ -970,11 +927,17 @@ build_ssdt(GArray *table_data, GArray *linker,
|
||||||
)));
|
)));
|
||||||
aml_append(dev, method);
|
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);
|
aml_append(sb_scope, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* build Method(MEMORY_SLOT_NOTIFY_METHOD, 2) {
|
/* 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);
|
method = aml_method(stringify(MEMORY_SLOT_NOTIFY_METHOD), 2);
|
||||||
for (i = 0; i < nr_mem; i++) {
|
for (i = 0; i < nr_mem; i++) {
|
||||||
|
@ -1293,31 +1256,6 @@ build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
|
||||||
return rsdp_table;
|
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
|
typedef
|
||||||
struct AcpiBuildState {
|
struct AcpiBuildState {
|
||||||
/* Copy of table in RAM (for patching). */
|
/* Copy of table in RAM (for patching). */
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
External(MEMORY_SLOT_PROXIMITY, FieldUnitObj) // read only
|
External(MEMORY_SLOT_PROXIMITY, FieldUnitObj) // read only
|
||||||
External(MEMORY_SLOT_ENABLED, FieldUnitObj) // 1 if enabled, 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_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_SLECTOR, FieldUnitObj) // DIMM selector, write only
|
||||||
External(MEMORY_SLOT_OST_EVENT, FieldUnitObj) // _OST event code, write only
|
External(MEMORY_SLOT_OST_EVENT, FieldUnitObj) // _OST event code, write only
|
||||||
External(MEMORY_SLOT_OST_STATUS, FieldUnitObj) // _OST status 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
|
If (LEqual(MEMORY_SLOT_INSERT_EVENT, One)) { // Memory device needs check
|
||||||
MEMORY_SLOT_NOTIFY_METHOD(Local0, 1)
|
MEMORY_SLOT_NOTIFY_METHOD(Local0, 1)
|
||||||
Store(1, MEMORY_SLOT_INSERT_EVENT)
|
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
|
Add(Local0, One, Local0) // goto next DIMM
|
||||||
}
|
}
|
||||||
Release(MEMORY_SLOT_LOCK)
|
Release(MEMORY_SLOT_LOCK)
|
||||||
|
@ -156,5 +160,12 @@
|
||||||
Store(Arg2, MEMORY_SLOT_OST_STATUS)
|
Store(Arg2, MEMORY_SLOT_OST_STATUS)
|
||||||
Release(MEMORY_SLOT_LOCK)
|
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()
|
} // Device()
|
||||||
} // Scope()
|
} // Scope()
|
||||||
|
|
54
hw/i386/pc.c
54
hw/i386/pc.c
|
@ -1677,6 +1677,52 @@ out:
|
||||||
error_propagate(errp, local_err);
|
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,
|
static void pc_cpu_plug(HotplugHandler *hotplug_dev,
|
||||||
DeviceState *dev, Error **errp)
|
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,
|
static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||||
DeviceState *dev, Error **errp)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
|
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"
|
error_setg(errp, "acpi: device unplug request for not supported device"
|
||||||
" type: %s", object_get_typename(OBJECT(dev)));
|
" type: %s", object_get_typename(OBJECT(dev)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
|
static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
|
||||||
DeviceState *dev, Error **errp)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
|
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"
|
error_setg(errp, "acpi: device unplug for not supported device"
|
||||||
" type: %s", object_get_typename(OBJECT(dev)));
|
" type: %s", object_get_typename(OBJECT(dev)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static HotplugHandler *pc_get_hotpug_handler(MachineState *machine,
|
static HotplugHandler *pc_get_hotpug_handler(MachineState *machine,
|
||||||
|
|
|
@ -310,8 +310,13 @@ static void pc_init_pci(MachineState *machine)
|
||||||
pc_init1(machine, 1, 1);
|
pc_init1(machine, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pc_compat_2_3(MachineState *machine)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static void pc_compat_2_2(MachineState *machine)
|
static void pc_compat_2_2(MachineState *machine)
|
||||||
{
|
{
|
||||||
|
pc_compat_2_3(machine);
|
||||||
rsdp_in_ram = false;
|
rsdp_in_ram = false;
|
||||||
x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
|
x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
|
||||||
x86_cpu_compat_set_features("kvm32", 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);
|
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)
|
static void pc_init_pci_2_2(MachineState *machine)
|
||||||
{
|
{
|
||||||
pc_compat_2_2(machine);
|
pc_compat_2_2(machine);
|
||||||
|
@ -512,19 +523,28 @@ static void pc_xen_hvm_init(MachineState *machine)
|
||||||
.desc = "Standard PC (i440FX + PIIX, 1996)", \
|
.desc = "Standard PC (i440FX + PIIX, 1996)", \
|
||||||
.hot_add_cpu = pc_hot_add_cpu
|
.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, \
|
PC_I440FX_MACHINE_OPTIONS, \
|
||||||
.default_machine_opts = "firmware=bios-256k.bin", \
|
.default_machine_opts = "firmware=bios-256k.bin", \
|
||||||
.default_display = "std"
|
.default_display = "std"
|
||||||
|
|
||||||
static QEMUMachine pc_i440fx_machine_v2_3 = {
|
|
||||||
PC_I440FX_2_3_MACHINE_OPTIONS,
|
static QEMUMachine pc_i440fx_machine_v2_4 = {
|
||||||
.name = "pc-i440fx-2.3",
|
PC_I440FX_2_4_MACHINE_OPTIONS,
|
||||||
|
.name = "pc-i440fx-2.4",
|
||||||
.alias = "pc",
|
.alias = "pc",
|
||||||
.init = pc_init_pci,
|
.init = pc_init_pci,
|
||||||
.is_default = 1,
|
.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
|
#define PC_I440FX_2_2_MACHINE_OPTIONS PC_I440FX_2_3_MACHINE_OPTIONS
|
||||||
|
|
||||||
static QEMUMachine pc_i440fx_machine_v2_2 = {
|
static QEMUMachine pc_i440fx_machine_v2_2 = {
|
||||||
|
@ -970,6 +990,7 @@ static QEMUMachine xenfv_machine = {
|
||||||
|
|
||||||
static void pc_machine_init(void)
|
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_3);
|
||||||
qemu_register_pc_machine(&pc_i440fx_machine_v2_2);
|
qemu_register_pc_machine(&pc_i440fx_machine_v2_2);
|
||||||
qemu_register_pc_machine(&pc_i440fx_machine_v2_1);
|
qemu_register_pc_machine(&pc_i440fx_machine_v2_1);
|
||||||
|
|
|
@ -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)
|
static void pc_compat_2_2(MachineState *machine)
|
||||||
{
|
{
|
||||||
|
pc_compat_2_3(machine);
|
||||||
rsdp_in_ram = false;
|
rsdp_in_ram = false;
|
||||||
x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
|
x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
|
||||||
x86_cpu_compat_set_features("kvm32", 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);
|
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)
|
static void pc_q35_init_2_2(MachineState *machine)
|
||||||
{
|
{
|
||||||
pc_compat_2_2(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, \
|
.hot_add_cpu = pc_hot_add_cpu, \
|
||||||
.units_per_default_bus = 1
|
.units_per_default_bus = 1
|
||||||
|
|
||||||
#define PC_Q35_2_3_MACHINE_OPTIONS \
|
#define PC_Q35_2_4_MACHINE_OPTIONS \
|
||||||
PC_Q35_MACHINE_OPTIONS, \
|
PC_Q35_MACHINE_OPTIONS, \
|
||||||
.default_machine_opts = "firmware=bios-256k.bin", \
|
.default_machine_opts = "firmware=bios-256k.bin", \
|
||||||
.default_display = "std"
|
.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 = {
|
static QEMUMachine pc_q35_machine_v2_3 = {
|
||||||
PC_Q35_2_3_MACHINE_OPTIONS,
|
PC_Q35_2_3_MACHINE_OPTIONS,
|
||||||
.name = "pc-q35-2.3",
|
.name = "pc-q35-2.3",
|
||||||
.alias = "q35",
|
.init = pc_q35_init_2_3,
|
||||||
.init = pc_q35_init,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PC_Q35_2_2_MACHINE_OPTIONS PC_Q35_2_3_MACHINE_OPTIONS
|
#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)
|
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_3);
|
||||||
qemu_register_pc_machine(&pc_q35_machine_v2_2);
|
qemu_register_pc_machine(&pc_q35_machine_v2_2);
|
||||||
qemu_register_pc_machine(&pc_q35_machine_v2_1);
|
qemu_register_pc_machine(&pc_q35_machine_v2_1);
|
||||||
|
|
|
@ -263,6 +263,13 @@ static void vhost_net_stop_one(struct vhost_net *net,
|
||||||
&file);
|
&file);
|
||||||
assert(r >= 0);
|
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) {
|
if (net->nc->info->poll) {
|
||||||
net->nc->info->poll(net->nc, true);
|
net->nc->info->poll(net->nc, true);
|
||||||
|
|
|
@ -446,6 +446,9 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
|
||||||
VirtIONet *n = VIRTIO_NET(vdev);
|
VirtIONet *n = VIRTIO_NET(vdev);
|
||||||
NetClientState *nc = qemu_get_queue(n->nic);
|
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);
|
virtio_add_feature(&features, VIRTIO_NET_F_MAC);
|
||||||
|
|
||||||
if (!peer_has_vnet_hdr(n)) {
|
if (!peer_has_vnet_hdr(n)) {
|
||||||
|
@ -1309,7 +1312,7 @@ static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue)
|
||||||
|
|
||||||
n->multiqueue = 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);
|
virtio_del_queue(vdev, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1552,7 +1555,7 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
|
||||||
vdev, idx, mask);
|
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;
|
int i, config_size = 0;
|
||||||
virtio_add_feature(&host_features, VIRTIO_NET_F_MAC);
|
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;
|
NetClientState *nc;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
virtio_net_set_config_size(n, n->host_features);
|
||||||
virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size);
|
virtio_init(vdev, "virtio-net", VIRTIO_ID_NET, n->config_size);
|
||||||
|
|
||||||
n->max_queues = MAX(n->nic_conf.peers.queues, 1);
|
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[] = {
|
static Property virtio_net_properties[] = {
|
||||||
|
DEFINE_VIRTIO_NET_FEATURES(VirtIONet, host_features),
|
||||||
DEFINE_NIC_PROPERTIES(VirtIONet, nic_conf),
|
DEFINE_NIC_PROPERTIES(VirtIONet, nic_conf),
|
||||||
DEFINE_PROP_UINT32("x-txtimer", VirtIONet, net_conf.txtimer,
|
DEFINE_PROP_UINT32("x-txtimer", VirtIONet, net_conf.txtimer,
|
||||||
TX_TIMER_INTERVAL),
|
TX_TIMER_INTERVAL),
|
||||||
|
|
|
@ -295,29 +295,37 @@ int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char *name;
|
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
|
* Migration compatibility dictates that this remains a 4k
|
||||||
* BAR with the vector table in the lower half and PBA in
|
* 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
|
if (nentries * PCI_MSIX_ENTRY_SIZE > bar_pba_offset) {
|
||||||
#define MSIX_EXCLUSIVE_BAR_TABLE_OFFSET 0
|
bar_pba_offset = nentries * PCI_MSIX_ENTRY_SIZE;
|
||||||
#define MSIX_EXCLUSIVE_BAR_PBA_OFFSET (MSIX_EXCLUSIVE_BAR_SIZE / 2)
|
}
|
||||||
#define MSIX_EXCLUSIVE_CAP_OFFSET 0
|
|
||||||
|
|
||||||
if (nentries * PCI_MSIX_ENTRY_SIZE > MSIX_EXCLUSIVE_BAR_PBA_OFFSET) {
|
if (bar_pba_offset + bar_pba_size > 4096) {
|
||||||
return -EINVAL;
|
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);
|
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);
|
g_free(name);
|
||||||
|
|
||||||
ret = msix_init(dev, nentries, &dev->msix_exclusive_bar, bar_nr,
|
ret = msix_init(dev, nentries, &dev->msix_exclusive_bar, bar_nr,
|
||||||
MSIX_EXCLUSIVE_BAR_TABLE_OFFSET, &dev->msix_exclusive_bar,
|
0, &dev->msix_exclusive_bar,
|
||||||
bar_nr, MSIX_EXCLUSIVE_BAR_PBA_OFFSET,
|
bar_nr, bar_pba_offset,
|
||||||
MSIX_EXCLUSIVE_CAP_OFFSET);
|
0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
43
hw/pci/pci.c
43
hw/pci/pci.c
|
@ -1615,28 +1615,32 @@ static const char * const pci_nic_names[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Initialize a PCI NIC. */
|
/* 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_model,
|
||||||
const char *default_devaddr,
|
const char *default_devaddr)
|
||||||
Error **errp)
|
|
||||||
{
|
{
|
||||||
const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr;
|
const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr;
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
PCIBus *bus;
|
PCIBus *bus;
|
||||||
int devfn;
|
|
||||||
PCIDevice *pci_dev;
|
PCIDevice *pci_dev;
|
||||||
DeviceState *dev;
|
DeviceState *dev;
|
||||||
|
int devfn;
|
||||||
int i;
|
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);
|
i = qemu_find_nic_model(nd, pci_nic_models, default_model);
|
||||||
if (i < 0)
|
if (i < 0) {
|
||||||
return NULL;
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
bus = pci_get_bus_devfn(&devfn, rootbus, devaddr);
|
bus = pci_get_bus_devfn(&devfn, rootbus, devaddr);
|
||||||
if (!bus) {
|
if (!bus) {
|
||||||
error_report("Invalid PCI device address %s for device %s",
|
error_report("Invalid PCI device address %s for device %s",
|
||||||
devaddr, pci_nic_names[i]);
|
devaddr, pci_nic_names[i]);
|
||||||
return NULL;
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_dev = pci_create(bus, devfn, pci_nic_names[i]);
|
pci_dev = pci_create(bus, devfn, pci_nic_names[i]);
|
||||||
|
@ -1644,32 +1648,13 @@ static PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus,
|
||||||
qdev_set_nic_properties(dev, nd);
|
qdev_set_nic_properties(dev, nd);
|
||||||
|
|
||||||
object_property_set_bool(OBJECT(dev), true, "realized", &err);
|
object_property_set_bool(OBJECT(dev), true, "realized", &err);
|
||||||
if (err) {
|
|
||||||
error_propagate(errp, 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) {
|
if (err) {
|
||||||
error_report_err(err);
|
error_report_err(err);
|
||||||
}
|
object_unparent(OBJECT(dev));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
|
return pci_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
PCIDevice *pci_vga_init(PCIBus *bus)
|
PCIDevice *pci_vga_init(PCIBus *bus)
|
||||||
|
|
|
@ -1825,6 +1825,38 @@ static const TypeInfo spapr_machine_info = {
|
||||||
#define SPAPR_COMPAT_2_1 \
|
#define SPAPR_COMPAT_2_1 \
|
||||||
SPAPR_COMPAT_2_2
|
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)
|
static void spapr_machine_2_1_class_init(ObjectClass *oc, void *data)
|
||||||
{
|
{
|
||||||
MachineClass *mc = MACHINE_CLASS(oc);
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
|
@ -1843,6 +1875,7 @@ static const TypeInfo spapr_machine_2_1_info = {
|
||||||
.name = TYPE_SPAPR_MACHINE "2.1",
|
.name = TYPE_SPAPR_MACHINE "2.1",
|
||||||
.parent = TYPE_SPAPR_MACHINE,
|
.parent = TYPE_SPAPR_MACHINE,
|
||||||
.class_init = spapr_machine_2_1_class_init,
|
.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)
|
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",
|
.name = TYPE_SPAPR_MACHINE "2.2",
|
||||||
.parent = TYPE_SPAPR_MACHINE,
|
.parent = TYPE_SPAPR_MACHINE,
|
||||||
.class_init = spapr_machine_2_2_class_init,
|
.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)
|
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->name = "pseries-2.3";
|
||||||
mc->desc = "pSeries Logical Partition (PAPR compliant) v2.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 = {
|
static const TypeInfo spapr_machine_2_3_info = {
|
||||||
.name = TYPE_SPAPR_MACHINE "2.3",
|
.name = TYPE_SPAPR_MACHINE "2.3",
|
||||||
.parent = TYPE_SPAPR_MACHINE,
|
.parent = TYPE_SPAPR_MACHINE,
|
||||||
.class_init = spapr_machine_2_3_class_init,
|
.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)
|
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_1_info);
|
||||||
type_register_static(&spapr_machine_2_2_info);
|
type_register_static(&spapr_machine_2_2_info);
|
||||||
type_register_static(&spapr_machine_2_3_info);
|
type_register_static(&spapr_machine_2_3_info);
|
||||||
|
type_register_static(&spapr_machine_2_4_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
type_init(spapr_machine_register_types)
|
type_init(spapr_machine_register_types)
|
||||||
|
|
|
@ -155,7 +155,6 @@ static void s390_virtio_net_realize(VirtIOS390Device *s390_dev, Error **errp)
|
||||||
DeviceState *vdev = DEVICE(&dev->vdev);
|
DeviceState *vdev = DEVICE(&dev->vdev);
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
virtio_net_set_config_size(&dev->vdev, s390_dev->host_features);
|
|
||||||
virtio_net_set_netclient_name(&dev->vdev, qdev->id,
|
virtio_net_set_netclient_name(&dev->vdev, qdev->id,
|
||||||
object_get_typename(OBJECT(qdev)));
|
object_get_typename(OBJECT(qdev)));
|
||||||
qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
|
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 *******************/
|
/**************** 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)
|
static void s390_virtio_net_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
|
VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
|
||||||
|
|
||||||
k->realize = s390_virtio_net_realize;
|
k->realize = s390_virtio_net_realize;
|
||||||
dc->props = s390_virtio_net_properties;
|
|
||||||
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
|
set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -657,18 +650,12 @@ static const TypeInfo virtio_s390_device_info = {
|
||||||
.abstract = true,
|
.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)
|
static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
|
VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
|
||||||
|
|
||||||
k->realize = s390_virtio_scsi_realize;
|
k->realize = s390_virtio_scsi_realize;
|
||||||
dc->props = s390_virtio_scsi_properties;
|
|
||||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
virtio_queue_set_addr(vdev, index, addr);
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
virtio_queue_set_vector(vdev, index, 0);
|
virtio_queue_set_vector(vdev, index, VIRTIO_NO_VECTOR);
|
||||||
} else {
|
} else {
|
||||||
/* Fail if we don't have a big enough queue. */
|
/* Fail if we don't have a big enough queue. */
|
||||||
/* TODO: Add interface to handle vring.num changing */
|
/* 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);
|
DeviceState *vdev = DEVICE(&dev->vdev);
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
|
|
||||||
virtio_net_set_config_size(&dev->vdev, ccw_dev->host_features[0]);
|
|
||||||
virtio_net_set_netclient_name(&dev->vdev, qdev->id,
|
virtio_net_set_netclient_name(&dev->vdev, qdev->id,
|
||||||
object_get_typename(OBJECT(qdev)));
|
object_get_typename(OBJECT(qdev)));
|
||||||
qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
|
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[] = {
|
static Property virtio_ccw_net_properties[] = {
|
||||||
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
||||||
DEFINE_VIRTIO_NET_FEATURES(VirtioCcwDevice, host_features[0]),
|
|
||||||
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
||||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
@ -1550,7 +1548,6 @@ static const TypeInfo virtio_ccw_balloon = {
|
||||||
|
|
||||||
static Property virtio_ccw_scsi_properties[] = {
|
static Property virtio_ccw_scsi_properties[] = {
|
||||||
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
|
||||||
DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features[0]),
|
|
||||||
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
|
||||||
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
|
|
@ -631,6 +631,10 @@ static void virtio_scsi_set_config(VirtIODevice *vdev,
|
||||||
static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
|
static uint32_t virtio_scsi_get_features(VirtIODevice *vdev,
|
||||||
uint32_t requested_features)
|
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;
|
return requested_features;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -945,6 +949,7 @@ static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp)
|
||||||
|
|
||||||
static Property virtio_scsi_properties[] = {
|
static Property virtio_scsi_properties[] = {
|
||||||
DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSI, parent_obj.conf),
|
DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSI, parent_obj.conf),
|
||||||
|
DEFINE_VIRTIO_SCSI_FEATURES(VirtIOSCSI, host_features),
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -630,28 +630,30 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
|
||||||
{
|
{
|
||||||
VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
|
VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
|
||||||
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
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++) {
|
while (vq) {
|
||||||
if (!virtio_queue_get_num(vdev, queue_no)) {
|
index = virtio_get_queue_index(vq);
|
||||||
|
if (!virtio_queue_get_num(vdev, index)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (virtio_queue_vector(vdev, queue_no) != vector) {
|
ret = virtio_pci_vq_vector_unmask(proxy, index, vector, msg);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ret = virtio_pci_vq_vector_unmask(proxy, queue_no, vector, msg);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto undo;
|
goto undo;
|
||||||
}
|
}
|
||||||
|
vq = virtio_vector_next_queue(vq);
|
||||||
|
++unmasked;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
undo:
|
undo:
|
||||||
while (--queue_no >= 0) {
|
vq = virtio_vector_first_queue(vdev, vector);
|
||||||
if (virtio_queue_vector(vdev, queue_no) != vector) {
|
while (vq && --unmasked >= 0) {
|
||||||
continue;
|
index = virtio_get_queue_index(vq);
|
||||||
}
|
virtio_pci_vq_vector_mask(proxy, index, vector);
|
||||||
virtio_pci_vq_vector_mask(proxy, queue_no, vector);
|
vq = virtio_vector_next_queue(vq);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -660,16 +662,16 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector)
|
||||||
{
|
{
|
||||||
VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
|
VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
|
||||||
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
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++) {
|
while (vq) {
|
||||||
if (!virtio_queue_get_num(vdev, queue_no)) {
|
index = virtio_get_queue_index(vq);
|
||||||
|
if (!virtio_queue_get_num(vdev, index)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (virtio_queue_vector(vdev, queue_no) != vector) {
|
virtio_pci_vq_vector_mask(proxy, index, vector);
|
||||||
continue;
|
vq = virtio_vector_next_queue(vq);
|
||||||
}
|
|
||||||
virtio_pci_vq_vector_mask(proxy, queue_no, vector);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -908,6 +910,13 @@ static const TypeInfo virtio_9p_pci_info = {
|
||||||
* virtio-pci: This is the PCIDevice which has a virtio-pci-bus.
|
* 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. */
|
/* This is called by virtio-bus just after the device is plugged. */
|
||||||
static void virtio_pci_device_plugged(DeviceState *d)
|
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),
|
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
|
||||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
|
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors,
|
||||||
DEV_NVECTORS_UNSPECIFIED),
|
DEV_NVECTORS_UNSPECIFIED),
|
||||||
DEFINE_VIRTIO_SCSI_FEATURES(VirtIOPCIProxy, host_features),
|
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1360,7 +1368,6 @@ static Property virtio_net_properties[] = {
|
||||||
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
|
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
|
||||||
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
|
VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
|
||||||
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
|
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
|
||||||
DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
|
|
||||||
DEFINE_PROP_END_OF_LIST(),
|
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);
|
VirtIONetPCI *dev = VIRTIO_NET_PCI(vpci_dev);
|
||||||
DeviceState *vdev = DEVICE(&dev->vdev);
|
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,
|
virtio_net_set_netclient_name(&dev->vdev, qdev->id,
|
||||||
object_get_typename(OBJECT(qdev)));
|
object_get_typename(OBJECT(qdev)));
|
||||||
qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
|
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->vmstate_change = virtio_pci_vmstate_change;
|
||||||
k->device_plugged = virtio_pci_device_plugged;
|
k->device_plugged = virtio_pci_device_plugged;
|
||||||
k->device_unplugged = virtio_pci_device_unplugged;
|
k->device_unplugged = virtio_pci_device_unplugged;
|
||||||
|
k->query_nvectors = virtio_pci_query_nvectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo virtio_pci_bus_info = {
|
static const TypeInfo virtio_pci_bus_info = {
|
||||||
|
|
|
@ -89,6 +89,7 @@ struct VirtQueue
|
||||||
VirtIODevice *vdev;
|
VirtIODevice *vdev;
|
||||||
EventNotifier guest_notifier;
|
EventNotifier guest_notifier;
|
||||||
EventNotifier host_notifier;
|
EventNotifier host_notifier;
|
||||||
|
QLIST_ENTRY(VirtQueue) node;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* virt queue functions */
|
/* virt queue functions */
|
||||||
|
@ -605,7 +606,7 @@ void virtio_reset(void *opaque)
|
||||||
vdev->vq[i].vring.used = 0;
|
vdev->vq[i].vring.used = 0;
|
||||||
vdev->vq[i].last_avail_idx = 0;
|
vdev->vq[i].last_avail_idx = 0;
|
||||||
vdev->vq[i].pa = 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 = 0;
|
||||||
vdev->vq[i].signalled_used_valid = false;
|
vdev->vq[i].signalled_used_valid = false;
|
||||||
vdev->vq[i].notification = true;
|
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_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)
|
int virtio_queue_get_num(VirtIODevice *vdev, int n)
|
||||||
{
|
{
|
||||||
return vdev->vq[n].vring.num;
|
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)
|
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;
|
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,
|
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);
|
qemu_del_vm_change_state_handler(vdev->vmstate);
|
||||||
g_free(vdev->config);
|
g_free(vdev->config);
|
||||||
g_free(vdev->vq);
|
g_free(vdev->vq);
|
||||||
|
g_free(vdev->vector_queues);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_vmstate_change(void *opaque, int running, RunState state)
|
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,
|
void virtio_init(VirtIODevice *vdev, const char *name,
|
||||||
uint16_t device_id, size_t config_size)
|
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 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->device_id = device_id;
|
||||||
vdev->status = 0;
|
vdev->status = 0;
|
||||||
vdev->isr = 0;
|
vdev->isr = 0;
|
||||||
|
|
|
@ -4,6 +4,18 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include "qemu/compiler.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 {
|
typedef enum {
|
||||||
AML_NO_OPCODE = 0,/* has only data */
|
AML_NO_OPCODE = 0,/* has only data */
|
||||||
|
@ -35,7 +47,13 @@ typedef enum {
|
||||||
aml_dword_acc = 3,
|
aml_dword_acc = 3,
|
||||||
aml_qword_acc = 4,
|
aml_qword_acc = 4,
|
||||||
aml_buffer_acc = 5,
|
aml_buffer_acc = 5,
|
||||||
} AmlFieldFlags;
|
} AmlAccessType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
aml_preserve = 0,
|
||||||
|
aml_write_as_ones = 1,
|
||||||
|
aml_write_as_zeros = 2,
|
||||||
|
} AmlUpdateRule;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
aml_system_memory = 0x00,
|
aml_system_memory = 0x00,
|
||||||
|
@ -93,6 +111,14 @@ typedef enum {
|
||||||
aml_ReadWrite = 1,
|
aml_ReadWrite = 1,
|
||||||
} AmlReadAndWrite;
|
} AmlReadAndWrite;
|
||||||
|
|
||||||
|
typedef
|
||||||
|
struct AcpiBuildTables {
|
||||||
|
GArray *table_data;
|
||||||
|
GArray *rsdp;
|
||||||
|
GArray *tcpalog;
|
||||||
|
GArray *linker;
|
||||||
|
} AcpiBuildTables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init_aml_allocator:
|
* init_aml_allocator:
|
||||||
*
|
*
|
||||||
|
@ -120,7 +146,7 @@ void free_aml_allocator(void);
|
||||||
* Joins Aml elements together and helps to construct AML tables
|
* Joins Aml elements together and helps to construct AML tables
|
||||||
* Examle of usage:
|
* Examle of usage:
|
||||||
* Aml *table = aml_def_block("SSDT", ...);
|
* Aml *table = aml_def_block("SSDT", ...);
|
||||||
* Aml *sb = aml_scope("\_SB");
|
* Aml *sb = aml_scope("\\_SB");
|
||||||
* Aml *dev = aml_device("PCI0");
|
* Aml *dev = aml_device("PCI0");
|
||||||
*
|
*
|
||||||
* aml_append(dev, aml_name_decl("HID", aml_eisaid("PNP0A03")));
|
* 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_package(uint8_t num_elements);
|
||||||
Aml *aml_buffer(void);
|
Aml *aml_buffer(void);
|
||||||
Aml *aml_resource_template(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);
|
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
|
#endif
|
||||||
|
|
|
@ -7,10 +7,17 @@
|
||||||
|
|
||||||
#define ACPI_MEMORY_HOTPLUG_STATUS 8
|
#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 {
|
typedef struct MemStatus {
|
||||||
DeviceState *dimm;
|
DeviceState *dimm;
|
||||||
bool is_enabled;
|
bool is_enabled;
|
||||||
bool is_inserting;
|
bool is_inserting;
|
||||||
|
bool is_removing;
|
||||||
uint32_t ost_event;
|
uint32_t ost_event;
|
||||||
uint32_t ost_status;
|
uint32_t ost_status;
|
||||||
} MemStatus;
|
} 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,
|
void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
|
||||||
DeviceState *dev, Error **errp);
|
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;
|
extern const VMStateDescription vmstate_memory_hotplug;
|
||||||
#define VMSTATE_MEMORY_HOTPLUG(memhp, state) \
|
#define VMSTATE_MEMORY_HOTPLUG(memhp, state) \
|
||||||
|
|
|
@ -43,6 +43,8 @@
|
||||||
#define MEMORY_SLOT_PROXIMITY MPX
|
#define MEMORY_SLOT_PROXIMITY MPX
|
||||||
#define MEMORY_SLOT_ENABLED MES
|
#define MEMORY_SLOT_ENABLED MES
|
||||||
#define MEMORY_SLOT_INSERT_EVENT MINS
|
#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_SLECTOR MSEL
|
||||||
#define MEMORY_SLOT_OST_EVENT MOEV
|
#define MEMORY_SLOT_OST_EVENT MOEV
|
||||||
#define MEMORY_SLOT_OST_STATUS MOSC
|
#define MEMORY_SLOT_OST_STATUS MOSC
|
||||||
|
@ -51,6 +53,7 @@
|
||||||
#define MEMORY_SLOT_CRS_METHOD MCRS
|
#define MEMORY_SLOT_CRS_METHOD MCRS
|
||||||
#define MEMORY_SLOT_OST_METHOD MOST
|
#define MEMORY_SLOT_OST_METHOD MOST
|
||||||
#define MEMORY_SLOT_PROXIMITY_METHOD MPXM
|
#define MEMORY_SLOT_PROXIMITY_METHOD MPXM
|
||||||
|
#define MEMORY_SLOT_EJECT_METHOD MEJ0
|
||||||
#define MEMORY_SLOT_NOTIFY_METHOD MTFY
|
#define MEMORY_SLOT_NOTIFY_METHOD MTFY
|
||||||
#define MEMORY_SLOT_SCAN_METHOD MSCN
|
#define MEMORY_SLOT_SCAN_METHOD MSCN
|
||||||
|
|
||||||
|
|
|
@ -266,6 +266,7 @@ int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
|
||||||
void qdev_init_nofail(DeviceState *dev);
|
void qdev_init_nofail(DeviceState *dev);
|
||||||
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
|
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
|
||||||
int required_for_version);
|
int required_for_version);
|
||||||
|
HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev);
|
||||||
void qdev_unplug(DeviceState *dev, Error **errp);
|
void qdev_unplug(DeviceState *dev, Error **errp);
|
||||||
void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
|
void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev,
|
||||||
DeviceState *dev, Error **errp);
|
DeviceState *dev, Error **errp);
|
||||||
|
|
|
@ -62,6 +62,7 @@ typedef struct VirtioBusClass {
|
||||||
* This is called by virtio-bus just before the device is unplugged.
|
* This is called by virtio-bus just before the device is unplugged.
|
||||||
*/
|
*/
|
||||||
void (*device_unplugged)(DeviceState *d);
|
void (*device_unplugged)(DeviceState *d);
|
||||||
|
int (*query_nvectors)(DeviceState *d);
|
||||||
/*
|
/*
|
||||||
* Does the transport have variable vring alignment?
|
* Does the transport have variable vring alignment?
|
||||||
* (ie can it ever call virtio_queue_set_align()?)
|
* (ie can it ever call virtio_queue_set_align()?)
|
||||||
|
|
|
@ -68,6 +68,7 @@ typedef struct VirtIONet {
|
||||||
uint32_t has_vnet_hdr;
|
uint32_t has_vnet_hdr;
|
||||||
size_t host_hdr_len;
|
size_t host_hdr_len;
|
||||||
size_t guest_hdr_len;
|
size_t guest_hdr_len;
|
||||||
|
uint32_t host_features;
|
||||||
uint8_t has_ufo;
|
uint8_t has_ufo;
|
||||||
int mergeable_rx_bufs;
|
int mergeable_rx_bufs;
|
||||||
uint8_t promisc;
|
uint8_t promisc;
|
||||||
|
@ -137,7 +138,6 @@ typedef struct VirtIONet {
|
||||||
DEFINE_PROP_INT32("x-txburst", _state, _field.txburst, TX_BURST), \
|
DEFINE_PROP_INT32("x-txburst", _state, _field.txburst, TX_BURST), \
|
||||||
DEFINE_PROP_STRING("tx", _state, _field.tx)
|
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,
|
void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
|
||||||
const char *type);
|
const char *type);
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,7 @@ typedef struct VirtIOSCSI {
|
||||||
bool dataplane_fenced;
|
bool dataplane_fenced;
|
||||||
Error *blocker;
|
Error *blocker;
|
||||||
Notifier migration_state_notifier;
|
Notifier migration_state_notifier;
|
||||||
|
uint32_t host_features;
|
||||||
} VirtIOSCSI;
|
} VirtIOSCSI;
|
||||||
|
|
||||||
typedef struct VirtIOSCSIReq {
|
typedef struct VirtIOSCSIReq {
|
||||||
|
|
|
@ -84,6 +84,7 @@ struct VirtIODevice
|
||||||
VMChangeStateEntry *vmstate;
|
VMChangeStateEntry *vmstate;
|
||||||
char *bus_name;
|
char *bus_name;
|
||||||
uint8_t device_endian;
|
uint8_t device_endian;
|
||||||
|
QLIST_HEAD(, VirtQueue) *vector_queues;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct VirtioDeviceClass {
|
typedef struct VirtioDeviceClass {
|
||||||
|
@ -218,6 +219,8 @@ void virtio_queue_set_host_notifier_fd_handler(VirtQueue *vq, bool assign,
|
||||||
bool set_handler);
|
bool set_handler);
|
||||||
void virtio_queue_notify_vq(VirtQueue *vq);
|
void virtio_queue_notify_vq(VirtQueue *vq);
|
||||||
void virtio_irq(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)
|
static inline void virtio_add_feature(uint32_t *features, unsigned int fbit)
|
||||||
{
|
{
|
||||||
|
|
25
monitor.c
25
monitor.c
|
@ -4471,11 +4471,12 @@ void set_link_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||||
len = strlen(str);
|
len = strlen(str);
|
||||||
readline_set_completion_index(rs, len);
|
readline_set_completion_index(rs, len);
|
||||||
if (nb_args == 2) {
|
if (nb_args == 2) {
|
||||||
NetClientState *ncs[255];
|
NetClientState *ncs[MAX_QUEUE_NUM];
|
||||||
int count, i;
|
int count, i;
|
||||||
count = qemu_find_net_clients_except(NULL, ncs,
|
count = qemu_find_net_clients_except(NULL, ncs,
|
||||||
NET_CLIENT_OPTIONS_KIND_NONE, 255);
|
NET_CLIENT_OPTIONS_KIND_NONE,
|
||||||
for (i = 0; i < count; i++) {
|
MAX_QUEUE_NUM);
|
||||||
|
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
|
||||||
const char *name = ncs[i]->name;
|
const char *name = ncs[i]->name;
|
||||||
if (!strncmp(str, name, len)) {
|
if (!strncmp(str, name, len)) {
|
||||||
readline_add_completion(rs, name);
|
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)
|
void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||||
{
|
{
|
||||||
int len, count, i;
|
int len, count, i;
|
||||||
NetClientState *ncs[255];
|
NetClientState *ncs[MAX_QUEUE_NUM];
|
||||||
|
|
||||||
if (nb_args != 2) {
|
if (nb_args != 2) {
|
||||||
return;
|
return;
|
||||||
|
@ -4499,8 +4500,8 @@ void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||||
len = strlen(str);
|
len = strlen(str);
|
||||||
readline_set_completion_index(rs, len);
|
readline_set_completion_index(rs, len);
|
||||||
count = qemu_find_net_clients_except(NULL, ncs, NET_CLIENT_OPTIONS_KIND_NIC,
|
count = qemu_find_net_clients_except(NULL, ncs, NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
255);
|
MAX_QUEUE_NUM);
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
const char *name = ncs[i]->name;
|
const char *name = ncs[i]->name;
|
||||||
if (strncmp(str, name, len)) {
|
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)
|
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;
|
int count, i, len;
|
||||||
|
|
||||||
len = strlen(str);
|
len = strlen(str);
|
||||||
readline_set_completion_index(rs, len);
|
readline_set_completion_index(rs, len);
|
||||||
if (nb_args == 2) {
|
if (nb_args == 2) {
|
||||||
count = qemu_find_net_clients_except(NULL, ncs,
|
count = qemu_find_net_clients_except(NULL, ncs,
|
||||||
NET_CLIENT_OPTIONS_KIND_NONE, 255);
|
NET_CLIENT_OPTIONS_KIND_NONE,
|
||||||
for (i = 0; i < count; i++) {
|
MAX_QUEUE_NUM);
|
||||||
|
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
|
||||||
int id;
|
int id;
|
||||||
char name[16];
|
char name[16];
|
||||||
|
|
||||||
|
@ -4606,8 +4608,9 @@ void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str)
|
||||||
return;
|
return;
|
||||||
} else if (nb_args == 3) {
|
} else if (nb_args == 3) {
|
||||||
count = qemu_find_net_clients_except(NULL, ncs,
|
count = qemu_find_net_clients_except(NULL, ncs,
|
||||||
NET_CLIENT_OPTIONS_KIND_NIC, 255);
|
NET_CLIENT_OPTIONS_KIND_NIC,
|
||||||
for (i = 0; i < count; i++) {
|
MAX_QUEUE_NUM);
|
||||||
|
for (i = 0; i < MIN(count, MAX_QUEUE_NUM); i++) {
|
||||||
int id;
|
int id;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
|
|
|
@ -330,3 +330,17 @@
|
||||||
##
|
##
|
||||||
{ 'event': 'VSERPORT_CHANGE',
|
{ 'event': 'VSERPORT_CHANGE',
|
||||||
'data': { 'id': 'str', 'open': 'bool' } }
|
'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.
|
@ -17,7 +17,7 @@
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "libqtest.h"
|
#include "libqtest.h"
|
||||||
#include "qemu/compiler.h"
|
#include "qemu/compiler.h"
|
||||||
#include "hw/i386/acpi-defs.h"
|
#include "hw/acpi/acpi-defs.h"
|
||||||
#include "hw/i386/smbios.h"
|
#include "hw/i386/smbios.h"
|
||||||
#include "qemu/bitmap.h"
|
#include "qemu/bitmap.h"
|
||||||
|
|
||||||
|
|
|
@ -1562,6 +1562,7 @@ vfio_put_base_device(int fd) "close vdev->fd=%d"
|
||||||
|
|
||||||
#hw/acpi/memory_hotplug.c
|
#hw/acpi/memory_hotplug.c
|
||||||
mhp_acpi_invalid_slot_selected(uint32_t slot) "0x%"PRIx32
|
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_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_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
|
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_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_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_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
|
# hw/i386/pc.c
|
||||||
mhp_pc_dimm_assigned_slot(int slot) "0x%d"
|
mhp_pc_dimm_assigned_slot(int slot) "0x%d"
|
||||||
|
|
Loading…
Reference in New Issue