pc,virtio,pci: fixes, features

Fixes all over the place.
 ACPI index support.
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmBZISUPHG1zdEByZWRo
 YXQuY29tAAoJECgfDbjSjVRpTI4IAKEwjtmm/yQxYPZS0691NA4fzmwVWdnUSe/w
 MMUh6ZyWTAhF4vpQKKiE3jMXt8I4ZkGzo0unB8t4WI5ZqOSHjL2oGvGUGF1i8ab4
 RezIF+PA+m+boVOIcsAUxHHmmYKTFSoR2fEK/ekvd2vFhQFaZoZYkHc+XFURVXCi
 LEgOb/4jAhGPUkaWqaeKkIvAKo2FCqYF6U0XynsG4lV0CfE/xxSiCsdjWlQYFHko
 S8/eyuf3rX28BJ5ltbWYGTXcthgqE2Arqr3sUMgOmAm4OrXkXjniAyfR0Y1A369F
 A33ETiZvLdddldn9wf18QTMwFzczu44edYLr5JFxYhyhTYFgLCk=
 =rH7A
 -----END PGP SIGNATURE-----

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

pc,virtio,pci: fixes, features

Fixes all over the place.
ACPI index support.

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

# gpg: Signature made Mon 22 Mar 2021 22:58:45 GMT
# gpg:                using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469
# gpg:                issuer "mst@redhat.com"
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full]
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>" [full]
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17  0970 C350 3912 AFBE 8E67
#      Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA  8A0D 281F 0DB8 D28D 5469

* remotes/mst/tags/for_upstream:
  acpi: Move setters/getters of oem fields to X86MachineState
  acpi: Set proper maximum size for "etc/acpi/rsdp" blob
  acpi: Move maximum size logic into acpi_add_rom_blob()
  microvm: Don't open-code "etc/table-loader"
  acpi: Set proper maximum size for "etc/table-loader" blob
  tests: acpi: update expected blobs
  pci: acpi: add _DSM method to PCI devices
  acpi: add aml_to_decimalstring() and aml_call6() helpers
  pci: acpi: ensure that acpi-index is unique
  pci: introduce acpi-index property for PCI device
  tests: acpi: temporary whitelist DSDT changes
  virtio-pmem: fix virtio_pmem_resp assign problem
  vhost-user: Monitor slave channel in vhost_user_read()
  vhost-user: Introduce nested event loop in vhost_user_read()
  vhost-user: Convert slave channel to QIOChannelSocket
  vhost-user: Factor out duplicated slave_fd teardown code
  vhost-user: Fix double-close on slave_read() error path
  vhost-user: Drop misleading EAGAIN checks in slave_read()
  virtio: Fix virtio_mmio_read()/virtio_mmio_write()

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-03-23 10:50:44 +00:00
commit 9741498849
35 changed files with 583 additions and 308 deletions

View File

@ -634,6 +634,19 @@ Aml *aml_to_buffer(Aml *src, Aml *dst)
return var;
}
/* ACPI 2.0a: 17.2.4.4 Type 2 Opcodes Encoding: DefToDecimalString */
Aml *aml_to_decimalstring(Aml *src, Aml *dst)
{
Aml *var = aml_opcode(0x97 /* ToDecimalStringOp */);
aml_append(var, src);
if (dst) {
aml_append(var, dst);
} else {
build_append_byte(var->buf, 0x00 /* NullNameOp */);
}
return var;
}
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefStore */
Aml *aml_store(Aml *val, Aml *target)
{
@ -835,6 +848,21 @@ Aml *aml_call5(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4,
return var;
}
/* helper to call method with 5 arguments */
Aml *aml_call6(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4,
Aml *arg5, Aml *arg6)
{
Aml *var = aml_alloc();
build_append_namestring(var->buf, "%s", method);
aml_append(var, arg1);
aml_append(var, arg2);
aml_append(var, arg3);
aml_append(var, arg4);
aml_append(var, arg5);
aml_append(var, arg6);
return var;
}
/*
* ACPI 5.0: 6.4.3.8.1 GPIO Connection Descriptor
* Type 1, Large Item Name 0xC

View File

@ -59,4 +59,3 @@ void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info,
build_header(linker, table_data, (void *)(table_data->data + mcfg_start),
"MCFG", table_data->len - mcfg_start, 1, oem_id, oem_table_id);
}

View File

@ -39,18 +39,34 @@
#include "trace.h"
#define ACPI_PCIHP_ADDR 0xae00
#define ACPI_PCIHP_SIZE 0x0014
#define ACPI_PCIHP_SIZE 0x0018
#define PCI_UP_BASE 0x0000
#define PCI_DOWN_BASE 0x0004
#define PCI_EJ_BASE 0x0008
#define PCI_RMV_BASE 0x000c
#define PCI_SEL_BASE 0x0010
#define PCI_AIDX_BASE 0x0014
typedef struct AcpiPciHpFind {
int bsel;
PCIBus *bus;
} AcpiPciHpFind;
static gint g_cmp_uint32(gconstpointer a, gconstpointer b, gpointer user_data)
{
return a - b;
}
static GSequence *pci_acpi_index_list(void)
{
static GSequence *used_acpi_index_list;
if (!used_acpi_index_list) {
used_acpi_index_list = g_sequence_new(NULL);
}
return used_acpi_index_list;
}
static int acpi_pcihp_get_bsel(PCIBus *bus)
{
Error *local_err = NULL;
@ -251,9 +267,13 @@ void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off)
acpi_pcihp_update(s);
}
#define ONBOARD_INDEX_MAX (16 * 1024 - 1)
void acpi_pcihp_device_pre_plug_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
PCIDevice *pdev = PCI_DEVICE(dev);
/* Only hotplugged devices need the hotplug capability. */
if (dev->hotplugged &&
acpi_pcihp_get_bsel(pci_get_bus(PCI_DEVICE(dev))) < 0) {
@ -261,6 +281,34 @@ void acpi_pcihp_device_pre_plug_cb(HotplugHandler *hotplug_dev,
ACPI_PCIHP_PROP_BSEL "' set");
return;
}
/*
* capped by systemd (see: udev-builtin-net_id.c)
* as it's the only known user honor it to avoid users
* misconfigure QEMU and then wonder why acpi-index doesn't work
*/
if (pdev->acpi_index > ONBOARD_INDEX_MAX) {
error_setg(errp, "acpi-index should be less or equal to %u",
ONBOARD_INDEX_MAX);
return;
}
/*
* make sure that acpi-index is unique across all present PCI devices
*/
if (pdev->acpi_index) {
GSequence *used_indexes = pci_acpi_index_list();
if (g_sequence_lookup(used_indexes, GINT_TO_POINTER(pdev->acpi_index),
g_cmp_uint32, NULL)) {
error_setg(errp, "a PCI device with acpi-index = %" PRIu32
" already exist", pdev->acpi_index);
return;
}
g_sequence_insert_sorted(used_indexes,
GINT_TO_POINTER(pdev->acpi_index),
g_cmp_uint32, NULL);
}
}
void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
@ -299,8 +347,22 @@ void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
DeviceState *dev, Error **errp)
{
PCIDevice *pdev = PCI_DEVICE(dev);
trace_acpi_pci_unplug(PCI_SLOT(PCI_DEVICE(dev)->devfn),
acpi_pcihp_get_bsel(pci_get_bus(PCI_DEVICE(dev))));
/*
* clean up acpi-index so it could reused by another device
*/
if (pdev->acpi_index) {
GSequence *used_indexes = pci_acpi_index_list();
g_sequence_remove(g_sequence_lookup(used_indexes,
GINT_TO_POINTER(pdev->acpi_index),
g_cmp_uint32, NULL));
}
qdev_unrealize(dev);
}
@ -347,7 +409,6 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
trace_acpi_pci_down_read(val);
break;
case PCI_EJ_BASE:
/* No feature defined yet */
trace_acpi_pci_features_read(val);
break;
case PCI_RMV_BASE:
@ -357,6 +418,12 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
case PCI_SEL_BASE:
val = s->hotplug_select;
trace_acpi_pci_sel_read(val);
break;
case PCI_AIDX_BASE:
val = s->acpi_index;
s->acpi_index = 0;
trace_acpi_pci_acpi_index_read(val);
break;
default:
break;
}
@ -367,8 +434,35 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
static void pci_write(void *opaque, hwaddr addr, uint64_t data,
unsigned int size)
{
int slot;
PCIBus *bus;
BusChild *kid, *next;
AcpiPciHpState *s = opaque;
s->acpi_index = 0;
switch (addr) {
case PCI_AIDX_BASE:
/*
* fetch acpi-index for specified slot so that follow up read from
* PCI_AIDX_BASE can return it to guest
*/
slot = ctz32(data);
if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
break;
}
bus = acpi_pcihp_find_hotplug_bus(s, s->hotplug_select);
QTAILQ_FOREACH_SAFE(kid, &bus->qbus.children, sibling, next) {
Object *o = OBJECT(kid->child);
PCIDevice *dev = PCI_DEVICE(o);
if (PCI_SLOT(dev->devfn) == slot) {
s->acpi_index = object_property_get_uint(o, "acpi-index", NULL);
break;
}
}
trace_acpi_pci_acpi_index_write(s->hotplug_select, slot, s->acpi_index);
break;
case PCI_EJ_BASE:
if (s->hotplug_select >= ACPI_PCIHP_MAX_HOTPLUG_BUS) {
break;
@ -413,6 +507,12 @@ void acpi_pcihp_init(Object *owner, AcpiPciHpState *s, PCIBus *root_bus,
OBJ_PROP_FLAG_READ);
}
bool vmstate_acpi_pcihp_use_acpi_index(void *opaque, int version_id)
{
AcpiPciHpState *s = opaque;
return s->acpi_index;
}
const VMStateDescription vmstate_acpi_pcihp_pci_status = {
.name = "acpi_pcihp_pci_status",
.version_id = 1,

View File

@ -297,7 +297,8 @@ static const VMStateDescription vmstate_acpi = {
2, vmstate_pci_status,
struct AcpiPciHpPciStatus),
VMSTATE_PCI_HOTPLUG(acpi_pci_hotplug, PIIX4PMState,
vmstate_test_use_acpi_hotplug_bridge),
vmstate_test_use_acpi_hotplug_bridge,
vmstate_acpi_pcihp_use_acpi_index),
VMSTATE_END_OF_LIST()
},
.subsections = (const VMStateDescription*[]) {

View File

@ -41,6 +41,8 @@ acpi_pci_unplug_request(int bsel, int slot) "bsel: %d slot: %d"
acpi_pci_up_read(uint32_t val) "%" PRIu32
acpi_pci_down_read(uint32_t val) "%" PRIu32
acpi_pci_features_read(uint32_t val) "%" PRIu32
acpi_pci_acpi_index_read(uint32_t val) "%" PRIu32
acpi_pci_acpi_index_write(unsigned bsel, unsigned slot, uint32_t aidx) "bsel: %u slot: %u aidx: %" PRIu32
acpi_pci_rmv_read(uint32_t val) "%" PRIu32
acpi_pci_sel_read(uint32_t val) "%" PRIu32
acpi_pci_ej_write(uint64_t addr, uint64_t data) "0x%" PRIx64 " <== %" PRIu64

View File

@ -27,9 +27,22 @@
#include "hw/loader.h"
MemoryRegion *acpi_add_rom_blob(FWCfgCallback update, void *opaque,
GArray *blob, const char *name,
uint64_t max_size)
GArray *blob, const char *name)
{
uint64_t max_size;
/* Reserve RAM space for tables: add another order of magnitude. */
if (!strcmp(name, ACPI_BUILD_TABLE_FILE)) {
max_size = 0x200000;
} else if (!strcmp(name, ACPI_BUILD_LOADER_FILE)) {
max_size = 0x10000;
} else if (!strcmp(name, ACPI_BUILD_RSDP_FILE)) {
max_size = 0x1000;
} else {
g_assert_not_reached();
}
g_assert(acpi_data_len(blob) <= max_size);
return rom_add_blob(name, blob->data, acpi_data_len(blob), max_size, -1,
name, update, opaque, NULL, true);
}

View File

@ -859,13 +859,13 @@ void virt_acpi_setup(VirtMachineState *vms)
/* Now expose it all to Guest */
build_state->table_mr = acpi_add_rom_blob(virt_acpi_build_update,
build_state, tables.table_data,
ACPI_BUILD_TABLE_FILE,
ACPI_BUILD_TABLE_MAX_SIZE);
ACPI_BUILD_TABLE_FILE);
assert(build_state->table_mr != NULL);
build_state->linker_mr =
acpi_add_rom_blob(virt_acpi_build_update, build_state,
tables.linker->cmd_blob, ACPI_BUILD_LOADER_FILE, 0);
build_state->linker_mr = acpi_add_rom_blob(virt_acpi_build_update,
build_state,
tables.linker->cmd_blob,
ACPI_BUILD_LOADER_FILE);
fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
acpi_data_len(tables.tcpalog));
@ -879,7 +879,7 @@ void virt_acpi_setup(VirtMachineState *vms)
build_state->rsdp_mr = acpi_add_rom_blob(virt_acpi_build_update,
build_state, tables.rsdp,
ACPI_BUILD_RSDP_FILE, 0);
ACPI_BUILD_RSDP_FILE);
qemu_register_reset(virt_acpi_build_reset, build_state);
virt_acpi_build_reset(build_state);

View File

@ -397,6 +397,13 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
);
aml_append(dev, method);
method = aml_method("_DSM", 4, AML_SERIALIZED);
aml_append(method,
aml_return(aml_call6("PDSM", aml_arg(0), aml_arg(1),
aml_arg(2), aml_arg(3),
aml_name("BSEL"), aml_name("_SUN")))
);
aml_append(dev, method);
aml_append(parent_scope, dev);
build_append_pcihp_notify_entry(notify_method, slot);
@ -424,6 +431,16 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
if (bsel) {
aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
method = aml_method("_DSM", 4, AML_SERIALIZED);
aml_append(method, aml_return(
aml_call6("PDSM", aml_arg(0), aml_arg(1), aml_arg(2),
aml_arg(3), aml_name("BSEL"), aml_name("_SUN"))
));
aml_append(dev, method);
}
if (pc->class_id == PCI_CLASS_DISPLAY_VGA) {
/* add VGA specific AML methods */
int s3d;
@ -446,9 +463,7 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
aml_append(method, aml_return(aml_int(s3d)));
aml_append(dev, method);
} else if (hotplug_enabled_dev) {
/* add _SUN/_EJ0 to make slot hotpluggable */
aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
/* add _EJ0 to make slot hotpluggable */
method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
aml_append(method,
aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
@ -511,6 +526,88 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
qobject_unref(bsel);
}
Aml *aml_pci_device_dsm(void)
{
Aml *method, *UUID, *ifctx, *ifctx1, *ifctx2, *ifctx3, *elsectx;
Aml *acpi_index = aml_local(0);
Aml *zero = aml_int(0);
Aml *bnum = aml_arg(4);
Aml *func = aml_arg(2);
Aml *rev = aml_arg(1);
Aml *sun = aml_arg(5);
method = aml_method("PDSM", 6, AML_SERIALIZED);
/*
* PCI Firmware Specification 3.1
* 4.6. _DSM Definitions for PCI
*/
UUID = aml_touuid("E5C937D0-3553-4D7A-9117-EA4D19C3434D");
ifctx = aml_if(aml_equal(aml_arg(0), UUID));
{
aml_append(ifctx, aml_store(aml_call2("AIDX", bnum, sun), acpi_index));
ifctx1 = aml_if(aml_equal(func, zero));
{
uint8_t byte_list[1];
ifctx2 = aml_if(aml_equal(rev, aml_int(2)));
{
/*
* advertise function 7 if device has acpi-index
* acpi_index values:
* 0: not present (default value)
* FFFFFFFF: not supported (old QEMU without PIDX reg)
* other: device's acpi-index
*/
ifctx3 = aml_if(aml_lnot(
aml_or(aml_equal(acpi_index, zero),
aml_equal(acpi_index, aml_int(0xFFFFFFFF)), NULL)
));
{
byte_list[0] =
1 /* have supported functions */ |
1 << 7 /* support for function 7 */
;
aml_append(ifctx3, aml_return(aml_buffer(1, byte_list)));
}
aml_append(ifctx2, ifctx3);
}
aml_append(ifctx1, ifctx2);
byte_list[0] = 0; /* nothing supported */
aml_append(ifctx1, aml_return(aml_buffer(1, byte_list)));
}
aml_append(ifctx, ifctx1);
elsectx = aml_else();
/*
* PCI Firmware Specification 3.1
* 4.6.7. _DSM for Naming a PCI or PCI Express Device Under
* Operating Systems
*/
ifctx1 = aml_if(aml_equal(func, aml_int(7)));
{
Aml *pkg = aml_package(2);
Aml *ret = aml_local(1);
aml_append(pkg, zero);
/*
* optional, if not impl. should return null string
*/
aml_append(pkg, aml_string("%s", ""));
aml_append(ifctx1, aml_store(pkg, ret));
/*
* update acpi-index to actual value
*/
aml_append(ifctx1, aml_store(acpi_index, aml_index(ret, zero)));
aml_append(ifctx1, aml_return(ret));
}
aml_append(elsectx, ifctx1);
aml_append(ifctx, elsectx);
}
aml_append(method, ifctx);
return method;
}
/**
* build_prt_entry:
* @link_name: link name for PCI route entry
@ -1168,9 +1265,10 @@ static void build_piix4_pci_hotplug(Aml *table)
aml_append(scope, field);
aml_append(scope,
aml_operation_region("BNMR", AML_SYSTEM_IO, aml_int(0xae10), 0x04));
aml_operation_region("BNMR", AML_SYSTEM_IO, aml_int(0xae10), 0x08));
field = aml_field("BNMR", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
aml_append(field, aml_named_field("BNUM", 32));
aml_append(field, aml_named_field("PIDX", 32));
aml_append(scope, field);
aml_append(scope, aml_mutex("BLCK", 0));
@ -1184,6 +1282,18 @@ static void build_piix4_pci_hotplug(Aml *table)
aml_append(method, aml_return(aml_int(0)));
aml_append(scope, method);
method = aml_method("AIDX", 2, AML_NOTSERIALIZED);
aml_append(method, aml_acquire(aml_name("BLCK"), 0xFFFF));
aml_append(method, aml_store(aml_arg(0), aml_name("BNUM")));
aml_append(method,
aml_store(aml_shiftleft(aml_int(1), aml_arg(1)), aml_name("PIDX")));
aml_append(method, aml_store(aml_name("PIDX"), aml_local(0)));
aml_append(method, aml_release(aml_name("BLCK")));
aml_append(method, aml_return(aml_local(0)));
aml_append(scope, method);
aml_append(scope, aml_pci_device_dsm());
aml_append(table, scope);
}
@ -1697,7 +1807,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
build_header(linker, table_data,
(void *)(table_data->data + table_data->len - dsdt->buf->len),
"DSDT", dsdt->buf->len, 1, pcms->oem_id, pcms->oem_table_id);
"DSDT", dsdt->buf->len, 1, x86ms->oem_id, x86ms->oem_table_id);
free_aml_allocator();
}
@ -1874,8 +1984,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
build_header(linker, table_data,
(void *)(table_data->data + srat_start),
"SRAT",
table_data->len - srat_start, 1, pcms->oem_id,
pcms->oem_table_id);
table_data->len - srat_start, 1, x86ms->oem_id,
x86ms->oem_table_id);
}
/*
@ -2228,13 +2338,13 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
if (slic_oem.id) {
oem_id = slic_oem.id;
} else {
oem_id = pcms->oem_id;
oem_id = x86ms->oem_id;
}
if (slic_oem.table_id) {
oem_table_id = slic_oem.table_id;
} else {
oem_table_id = pcms->oem_table_id;
oem_table_id = x86ms->oem_table_id;
}
table_offsets = g_array_new(false, true /* clear */,
@ -2275,30 +2385,30 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
acpi_add_table(table_offsets, tables_blob);
acpi_build_madt(tables_blob, tables->linker, x86ms,
ACPI_DEVICE_IF(x86ms->acpi_dev), pcms->oem_id,
pcms->oem_table_id);
ACPI_DEVICE_IF(x86ms->acpi_dev), x86ms->oem_id,
x86ms->oem_table_id);
vmgenid_dev = find_vmgenid_dev();
if (vmgenid_dev) {
acpi_add_table(table_offsets, tables_blob);
vmgenid_build_acpi(VMGENID(vmgenid_dev), tables_blob,
tables->vmgenid, tables->linker, pcms->oem_id);
tables->vmgenid, tables->linker, x86ms->oem_id);
}
if (misc.has_hpet) {
acpi_add_table(table_offsets, tables_blob);
build_hpet(tables_blob, tables->linker, pcms->oem_id,
pcms->oem_table_id);
build_hpet(tables_blob, tables->linker, x86ms->oem_id,
x86ms->oem_table_id);
}
if (misc.tpm_version != TPM_VERSION_UNSPEC) {
if (misc.tpm_version == TPM_VERSION_1_2) {
acpi_add_table(table_offsets, tables_blob);
build_tpm_tcpa(tables_blob, tables->linker, tables->tcpalog,
pcms->oem_id, pcms->oem_table_id);
x86ms->oem_id, x86ms->oem_table_id);
} else { /* TPM_VERSION_2_0 */
acpi_add_table(table_offsets, tables_blob);
build_tpm2(tables_blob, tables->linker, tables->tcpalog,
pcms->oem_id, pcms->oem_table_id);
x86ms->oem_id, x86ms->oem_table_id);
}
}
if (pcms->numa_nodes) {
@ -2306,40 +2416,40 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
build_srat(tables_blob, tables->linker, machine);
if (machine->numa_state->have_numa_distance) {
acpi_add_table(table_offsets, tables_blob);
build_slit(tables_blob, tables->linker, machine, pcms->oem_id,
pcms->oem_table_id);
build_slit(tables_blob, tables->linker, machine, x86ms->oem_id,
x86ms->oem_table_id);
}
if (machine->numa_state->hmat_enabled) {
acpi_add_table(table_offsets, tables_blob);
build_hmat(tables_blob, tables->linker, machine->numa_state,
pcms->oem_id, pcms->oem_table_id);
x86ms->oem_id, x86ms->oem_table_id);
}
}
if (acpi_get_mcfg(&mcfg)) {
acpi_add_table(table_offsets, tables_blob);
build_mcfg(tables_blob, tables->linker, &mcfg, pcms->oem_id,
pcms->oem_table_id);
build_mcfg(tables_blob, tables->linker, &mcfg, x86ms->oem_id,
x86ms->oem_table_id);
}
if (x86_iommu_get_default()) {
IommuType IOMMUType = x86_iommu_get_type();
if (IOMMUType == TYPE_AMD) {
acpi_add_table(table_offsets, tables_blob);
build_amd_iommu(tables_blob, tables->linker, pcms->oem_id,
pcms->oem_table_id);
build_amd_iommu(tables_blob, tables->linker, x86ms->oem_id,
x86ms->oem_table_id);
} else if (IOMMUType == TYPE_INTEL) {
acpi_add_table(table_offsets, tables_blob);
build_dmar_q35(tables_blob, tables->linker, pcms->oem_id,
pcms->oem_table_id);
build_dmar_q35(tables_blob, tables->linker, x86ms->oem_id,
x86ms->oem_table_id);
}
}
if (machine->nvdimms_state->is_enabled) {
nvdimm_build_acpi(table_offsets, tables_blob, tables->linker,
machine->nvdimms_state, machine->ram_slots,
pcms->oem_id, pcms->oem_table_id);
x86ms->oem_id, x86ms->oem_table_id);
}
acpi_add_table(table_offsets, tables_blob);
build_waet(tables_blob, tables->linker, pcms->oem_id, pcms->oem_table_id);
build_waet(tables_blob, tables->linker, x86ms->oem_id, x86ms->oem_table_id);
/* Add tables supplied by user (if any) */
for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
@ -2358,7 +2468,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
{
AcpiRsdpData rsdp_data = {
.revision = 0,
.oem_id = pcms->oem_id,
.oem_id = x86ms->oem_id,
.xsdt_tbl_offset = NULL,
.rsdt_tbl_offset = &rsdt,
};
@ -2518,13 +2628,12 @@ void acpi_setup(void)
/* Now expose it all to Guest */
build_state->table_mr = acpi_add_rom_blob(acpi_build_update,
build_state, tables.table_data,
ACPI_BUILD_TABLE_FILE,
ACPI_BUILD_TABLE_MAX_SIZE);
ACPI_BUILD_TABLE_FILE);
assert(build_state->table_mr != NULL);
build_state->linker_mr =
acpi_add_rom_blob(acpi_build_update, build_state,
tables.linker->cmd_blob, ACPI_BUILD_LOADER_FILE, 0);
tables.linker->cmd_blob, ACPI_BUILD_LOADER_FILE);
fw_cfg_add_file(x86ms->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
tables.tcpalog->data, acpi_data_len(tables.tcpalog));
@ -2563,7 +2672,7 @@ void acpi_setup(void)
build_state->rsdp = NULL;
build_state->rsdp_mr = acpi_add_rom_blob(acpi_build_update,
build_state, tables.rsdp,
ACPI_BUILD_RSDP_FILE, 0);
ACPI_BUILD_RSDP_FILE);
}
qemu_register_reset(acpi_build_reset, build_state);

View File

@ -149,7 +149,7 @@ build_dsdt_microvm(GArray *table_data, BIOSLinker *linker,
g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
build_header(linker, table_data,
(void *)(table_data->data + table_data->len - dsdt->buf->len),
"DSDT", dsdt->buf->len, 2, mms->oem_id, mms->oem_table_id);
"DSDT", dsdt->buf->len, 2, x86ms->oem_id, x86ms->oem_table_id);
free_aml_allocator();
}
@ -201,24 +201,24 @@ static void acpi_build_microvm(AcpiBuildTables *tables,
pmfadt.dsdt_tbl_offset = &dsdt;
pmfadt.xdsdt_tbl_offset = &dsdt;
acpi_add_table(table_offsets, tables_blob);
build_fadt(tables_blob, tables->linker, &pmfadt, mms->oem_id,
mms->oem_table_id);
build_fadt(tables_blob, tables->linker, &pmfadt, x86ms->oem_id,
x86ms->oem_table_id);
acpi_add_table(table_offsets, tables_blob);
acpi_build_madt(tables_blob, tables->linker, X86_MACHINE(machine),
ACPI_DEVICE_IF(x86ms->acpi_dev), mms->oem_id,
mms->oem_table_id);
ACPI_DEVICE_IF(x86ms->acpi_dev), x86ms->oem_id,
x86ms->oem_table_id);
xsdt = tables_blob->len;
build_xsdt(tables_blob, tables->linker, table_offsets, mms->oem_id,
mms->oem_table_id);
build_xsdt(tables_blob, tables->linker, table_offsets, x86ms->oem_id,
x86ms->oem_table_id);
/* RSDP is in FSEG memory, so allocate it separately */
{
AcpiRsdpData rsdp_data = {
/* ACPI 2.0: 5.2.4.3 RSDP Structure */
.revision = 2, /* xsdt needs v2 */
.oem_id = mms->oem_id,
.oem_id = x86ms->oem_id,
.xsdt_tbl_offset = &xsdt,
.rsdt_tbl_offset = NULL,
};
@ -249,16 +249,12 @@ void acpi_setup_microvm(MicrovmMachineState *mms)
acpi_build_microvm(&tables, mms);
/* Now expose it all to Guest */
acpi_add_rom_blob(acpi_build_no_update, NULL,
tables.table_data,
ACPI_BUILD_TABLE_FILE,
ACPI_BUILD_TABLE_MAX_SIZE);
acpi_add_rom_blob(acpi_build_no_update, NULL,
tables.linker->cmd_blob,
"etc/table-loader", 0);
acpi_add_rom_blob(acpi_build_no_update, NULL,
tables.rsdp,
ACPI_BUILD_RSDP_FILE, 0);
acpi_add_rom_blob(acpi_build_no_update, NULL, tables.table_data,
ACPI_BUILD_TABLE_FILE);
acpi_add_rom_blob(acpi_build_no_update, NULL, tables.linker->cmd_blob,
ACPI_BUILD_LOADER_FILE);
acpi_add_rom_blob(acpi_build_no_update, NULL, tables.rsdp,
ACPI_BUILD_RSDP_FILE);
acpi_build_tables_cleanup(&tables, false);
}

View File

@ -648,51 +648,6 @@ static void microvm_powerdown_req(Notifier *notifier, void *data)
}
}
static char *microvm_machine_get_oem_id(Object *obj, Error **errp)
{
MicrovmMachineState *mms = MICROVM_MACHINE(obj);
return g_strdup(mms->oem_id);
}
static void microvm_machine_set_oem_id(Object *obj, const char *value,
Error **errp)
{
MicrovmMachineState *mms = MICROVM_MACHINE(obj);
size_t len = strlen(value);
if (len > 6) {
error_setg(errp,
"User specified "MICROVM_MACHINE_OEM_ID" value is bigger than "
"6 bytes in size");
return;
}
strncpy(mms->oem_id, value, 6);
}
static char *microvm_machine_get_oem_table_id(Object *obj, Error **errp)
{
MicrovmMachineState *mms = MICROVM_MACHINE(obj);
return g_strdup(mms->oem_table_id);
}
static void microvm_machine_set_oem_table_id(Object *obj, const char *value,
Error **errp)
{
MicrovmMachineState *mms = MICROVM_MACHINE(obj);
size_t len = strlen(value);
if (len > 8) {
error_setg(errp,
"User specified "MICROVM_MACHINE_OEM_TABLE_ID" value is bigger than "
"8 bytes in size");
return;
}
strncpy(mms->oem_table_id, value, 8);
}
static void microvm_machine_initfn(Object *obj)
{
MicrovmMachineState *mms = MICROVM_MACHINE(obj);
@ -714,9 +669,6 @@ static void microvm_machine_initfn(Object *obj)
qemu_add_machine_init_done_notifier(&mms->machine_done);
mms->powerdown_req.notify = microvm_powerdown_req;
qemu_register_powerdown_notifier(&mms->powerdown_req);
mms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
mms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
}
static void microvm_class_init(ObjectClass *oc, void *data)
@ -805,24 +757,6 @@ static void microvm_class_init(ObjectClass *oc, void *data)
MICROVM_MACHINE_AUTO_KERNEL_CMDLINE,
"Set off to disable adding virtio-mmio devices to the kernel cmdline");
object_class_property_add_str(oc, MICROVM_MACHINE_OEM_ID,
microvm_machine_get_oem_id,
microvm_machine_set_oem_id);
object_class_property_set_description(oc, MICROVM_MACHINE_OEM_ID,
"Override the default value of field OEMID "
"in ACPI table header."
"The string may be up to 6 bytes in size");
object_class_property_add_str(oc, MICROVM_MACHINE_OEM_TABLE_ID,
microvm_machine_get_oem_table_id,
microvm_machine_set_oem_table_id);
object_class_property_set_description(oc, MICROVM_MACHINE_OEM_TABLE_ID,
"Override the default value of field OEM Table ID "
"in ACPI table header."
"The string may be up to 8 bytes in size");
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
}

View File

@ -1608,49 +1608,6 @@ static void pc_machine_set_max_fw_size(Object *obj, Visitor *v,
pcms->max_fw_size = value;
}
static char *pc_machine_get_oem_id(Object *obj, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
return g_strdup(pcms->oem_id);
}
static void pc_machine_set_oem_id(Object *obj, const char *value, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
size_t len = strlen(value);
if (len > 6) {
error_setg(errp,
"User specified "PC_MACHINE_OEM_ID" value is bigger than "
"6 bytes in size");
return;
}
strncpy(pcms->oem_id, value, 6);
}
static char *pc_machine_get_oem_table_id(Object *obj, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
return g_strdup(pcms->oem_table_id);
}
static void pc_machine_set_oem_table_id(Object *obj, const char *value,
Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
size_t len = strlen(value);
if (len > 8) {
error_setg(errp,
"User specified "PC_MACHINE_OEM_TABLE_ID" value is bigger than "
"8 bytes in size");
return;
}
strncpy(pcms->oem_table_id, value, 8);
}
static void pc_machine_initfn(Object *obj)
{
@ -1664,8 +1621,6 @@ static void pc_machine_initfn(Object *obj)
pcms->max_ram_below_4g = 0; /* use default */
/* acpi build is enabled by default if machine supports it */
pcms->acpi_build_enabled = PC_MACHINE_GET_CLASS(pcms)->has_acpi_build;
pcms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
pcms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
pcms->smbus_enabled = true;
pcms->sata_enabled = true;
pcms->pit_enabled = true;
@ -1802,24 +1757,6 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
NULL, NULL);
object_class_property_set_description(oc, PC_MACHINE_MAX_FW_SIZE,
"Maximum combined firmware size");
object_class_property_add_str(oc, PC_MACHINE_OEM_ID,
pc_machine_get_oem_id,
pc_machine_set_oem_id);
object_class_property_set_description(oc, PC_MACHINE_OEM_ID,
"Override the default value of field OEMID "
"in ACPI table header."
"The string may be up to 6 bytes in size");
object_class_property_add_str(oc, PC_MACHINE_OEM_TABLE_ID,
pc_machine_get_oem_table_id,
pc_machine_set_oem_table_id);
object_class_property_set_description(oc, PC_MACHINE_OEM_TABLE_ID,
"Override the default value of field OEM Table ID "
"in ACPI table header."
"The string may be up to 8 bytes in size");
}
static const TypeInfo pc_machine_info = {

View File

@ -1201,6 +1201,51 @@ static void x86_machine_set_acpi(Object *obj, Visitor *v, const char *name,
visit_type_OnOffAuto(v, name, &x86ms->acpi, errp);
}
static char *x86_machine_get_oem_id(Object *obj, Error **errp)
{
X86MachineState *x86ms = X86_MACHINE(obj);
return g_strdup(x86ms->oem_id);
}
static void x86_machine_set_oem_id(Object *obj, const char *value, Error **errp)
{
X86MachineState *x86ms = X86_MACHINE(obj);
size_t len = strlen(value);
if (len > 6) {
error_setg(errp,
"User specified "X86_MACHINE_OEM_ID" value is bigger than "
"6 bytes in size");
return;
}
strncpy(x86ms->oem_id, value, 6);
}
static char *x86_machine_get_oem_table_id(Object *obj, Error **errp)
{
X86MachineState *x86ms = X86_MACHINE(obj);
return g_strdup(x86ms->oem_table_id);
}
static void x86_machine_set_oem_table_id(Object *obj, const char *value,
Error **errp)
{
X86MachineState *x86ms = X86_MACHINE(obj);
size_t len = strlen(value);
if (len > 8) {
error_setg(errp,
"User specified "X86_MACHINE_OEM_TABLE_ID
" value is bigger than "
"8 bytes in size");
return;
}
strncpy(x86ms->oem_table_id, value, 8);
}
static void x86_machine_initfn(Object *obj)
{
X86MachineState *x86ms = X86_MACHINE(obj);
@ -1209,6 +1254,8 @@ static void x86_machine_initfn(Object *obj)
x86ms->acpi = ON_OFF_AUTO_AUTO;
x86ms->smp_dies = 1;
x86ms->pci_irq_mask = ACPI_BUILD_PCI_IRQS;
x86ms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6);
x86ms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8);
}
static void x86_machine_class_init(ObjectClass *oc, void *data)
@ -1235,6 +1282,23 @@ static void x86_machine_class_init(ObjectClass *oc, void *data)
NULL, NULL);
object_class_property_set_description(oc, X86_MACHINE_ACPI,
"Enable ACPI");
object_class_property_add_str(oc, X86_MACHINE_OEM_ID,
x86_machine_get_oem_id,
x86_machine_set_oem_id);
object_class_property_set_description(oc, X86_MACHINE_OEM_ID,
"Override the default value of field OEMID "
"in ACPI table header."
"The string may be up to 6 bytes in size");
object_class_property_add_str(oc, X86_MACHINE_OEM_TABLE_ID,
x86_machine_get_oem_table_id,
x86_machine_set_oem_table_id);
object_class_property_set_description(oc, X86_MACHINE_OEM_TABLE_ID,
"Override the default value of field OEM Table ID "
"in ACPI table header."
"The string may be up to 8 bytes in size");
}
static const TypeInfo x86_machine_info = {

View File

@ -79,6 +79,7 @@ static Property pci_props[] = {
QEMU_PCIE_EXTCAP_INIT_BITNR, true),
DEFINE_PROP_STRING("failover_pair_id", PCIDevice,
failover_pair_id),
DEFINE_PROP_UINT32("acpi-index", PCIDevice, acpi_index, 0),
DEFINE_PROP_END_OF_LIST()
};

View File

@ -16,6 +16,7 @@
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-net.h"
#include "chardev/char-fe.h"
#include "io/channel-socket.h"
#include "sysemu/kvm.h"
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
@ -237,7 +238,8 @@ struct vhost_user {
struct vhost_dev *dev;
/* Shared between vhost devs of the same virtio device */
VhostUserState *user;
int slave_fd;
QIOChannel *slave_ioc;
GSource *slave_src;
NotifierWithReturn postcopy_notifier;
struct PostCopyFD postcopy_fd;
uint64_t postcopy_client_bases[VHOST_USER_MAX_RAM_SLOTS];
@ -294,15 +296,27 @@ static int vhost_user_read_header(struct vhost_dev *dev, VhostUserMsg *msg)
return 0;
}
static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
struct vhost_user_read_cb_data {
struct vhost_dev *dev;
VhostUserMsg *msg;
GMainLoop *loop;
int ret;
};
static gboolean vhost_user_read_cb(GIOChannel *source, GIOCondition condition,
gpointer opaque)
{
struct vhost_user_read_cb_data *data = opaque;
struct vhost_dev *dev = data->dev;
VhostUserMsg *msg = data->msg;
struct vhost_user *u = dev->opaque;
CharBackend *chr = u->user->chr;
uint8_t *p = (uint8_t *) msg;
int r, size;
if (vhost_user_read_header(dev, msg) < 0) {
return -1;
data->ret = -1;
goto end;
}
/* validate message size is sane */
@ -310,7 +324,8 @@ static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
error_report("Failed to read msg header."
" Size %d exceeds the maximum %zu.", msg->hdr.size,
VHOST_USER_PAYLOAD_SIZE);
return -1;
data->ret = -1;
goto end;
}
if (msg->hdr.size) {
@ -320,11 +335,84 @@ static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
if (r != size) {
error_report("Failed to read msg payload."
" Read %d instead of %d.", r, msg->hdr.size);
return -1;
data->ret = -1;
goto end;
}
}
return 0;
end:
g_main_loop_quit(data->loop);
return G_SOURCE_REMOVE;
}
static gboolean slave_read(QIOChannel *ioc, GIOCondition condition,
gpointer opaque);
/*
* This updates the read handler to use a new event loop context.
* Event sources are removed from the previous context : this ensures
* that events detected in the previous context are purged. They will
* be re-detected and processed in the new context.
*/
static void slave_update_read_handler(struct vhost_dev *dev,
GMainContext *ctxt)
{
struct vhost_user *u = dev->opaque;
if (!u->slave_ioc) {
return;
}
if (u->slave_src) {
g_source_destroy(u->slave_src);
g_source_unref(u->slave_src);
}
u->slave_src = qio_channel_add_watch_source(u->slave_ioc,
G_IO_IN | G_IO_HUP,
slave_read, dev, NULL,
ctxt);
}
static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
{
struct vhost_user *u = dev->opaque;
CharBackend *chr = u->user->chr;
GMainContext *prev_ctxt = chr->chr->gcontext;
GMainContext *ctxt = g_main_context_new();
GMainLoop *loop = g_main_loop_new(ctxt, FALSE);
struct vhost_user_read_cb_data data = {
.dev = dev,
.loop = loop,
.msg = msg,
.ret = 0
};
/*
* We want to be able to monitor the slave channel fd while waiting
* for chr I/O. This requires an event loop, but we can't nest the
* one to which chr is currently attached : its fd handlers might not
* be prepared for re-entrancy. So we create a new one and switch chr
* to use it.
*/
slave_update_read_handler(dev, ctxt);
qemu_chr_be_update_read_handlers(chr->chr, ctxt);
qemu_chr_fe_add_watch(chr, G_IO_IN | G_IO_HUP, vhost_user_read_cb, &data);
g_main_loop_run(loop);
/*
* Restore the previous event loop context. This also destroys/recreates
* event sources : this guarantees that all pending events in the original
* context that have been processed by the nested loop are purged.
*/
qemu_chr_be_update_read_handlers(chr->chr, prev_ctxt);
slave_update_read_handler(dev, NULL);
g_main_loop_unref(loop);
g_main_context_unref(ctxt);
return data.ret;
}
static int process_message_reply(struct vhost_dev *dev,
@ -1392,56 +1480,39 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev,
return 0;
}
static void slave_read(void *opaque)
static void close_slave_channel(struct vhost_user *u)
{
g_source_destroy(u->slave_src);
g_source_unref(u->slave_src);
u->slave_src = NULL;
object_unref(OBJECT(u->slave_ioc));
u->slave_ioc = NULL;
}
static gboolean slave_read(QIOChannel *ioc, GIOCondition condition,
gpointer opaque)
{
struct vhost_dev *dev = opaque;
struct vhost_user *u = dev->opaque;
VhostUserHeader hdr = { 0, };
VhostUserPayload payload = { 0, };
int size, ret = 0;
Error *local_err = NULL;
gboolean rc = G_SOURCE_CONTINUE;
int ret = 0;
struct iovec iov;
struct msghdr msgh;
int fd[VHOST_USER_SLAVE_MAX_FDS];
char control[CMSG_SPACE(sizeof(fd))];
struct cmsghdr *cmsg;
int i, fdsize = 0;
memset(&msgh, 0, sizeof(msgh));
msgh.msg_iov = &iov;
msgh.msg_iovlen = 1;
msgh.msg_control = control;
msgh.msg_controllen = sizeof(control);
memset(fd, -1, sizeof(fd));
g_autofree int *fd = NULL;
size_t fdsize = 0;
int i;
/* Read header */
iov.iov_base = &hdr;
iov.iov_len = VHOST_USER_HDR_SIZE;
do {
size = recvmsg(u->slave_fd, &msgh, 0);
} while (size < 0 && (errno == EINTR || errno == EAGAIN));
if (size != VHOST_USER_HDR_SIZE) {
error_report("Failed to read from slave.");
if (qio_channel_readv_full_all(ioc, &iov, 1, &fd, &fdsize, &local_err)) {
error_report_err(local_err);
goto err;
}
if (msgh.msg_flags & MSG_CTRUNC) {
error_report("Truncated message.");
goto err;
}
for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
fdsize = cmsg->cmsg_len - CMSG_LEN(0);
memcpy(fd, CMSG_DATA(cmsg), fdsize);
break;
}
}
if (hdr.size > VHOST_USER_PAYLOAD_SIZE) {
error_report("Failed to read msg header."
" Size %d exceeds the maximum %zu.", hdr.size,
@ -1450,12 +1521,8 @@ static void slave_read(void *opaque)
}
/* Read payload */
do {
size = read(u->slave_fd, &payload, hdr.size);
} while (size < 0 && (errno == EINTR || errno == EAGAIN));
if (size != hdr.size) {
error_report("Failed to read payload from slave.");
if (qio_channel_read_all(ioc, (char *) &payload, hdr.size, &local_err)) {
error_report_err(local_err);
goto err;
}
@ -1468,20 +1535,13 @@ static void slave_read(void *opaque)
break;
case VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG:
ret = vhost_user_slave_handle_vring_host_notifier(dev, &payload.area,
fd[0]);
fd ? fd[0] : -1);
break;
default:
error_report("Received unexpected msg type: %d.", hdr.request);
ret = -EINVAL;
}
/* Close the remaining file descriptors. */
for (i = 0; i < fdsize; i++) {
if (fd[i] != -1) {
close(fd[i]);
}
}
/*
* REPLY_ACK feature handling. Other reply types has to be managed
* directly in their request handlers.
@ -1501,28 +1561,25 @@ static void slave_read(void *opaque)
iovec[1].iov_base = &payload;
iovec[1].iov_len = hdr.size;
do {
size = writev(u->slave_fd, iovec, ARRAY_SIZE(iovec));
} while (size < 0 && (errno == EINTR || errno == EAGAIN));
if (size != VHOST_USER_HDR_SIZE + hdr.size) {
error_report("Failed to send msg reply to slave.");
if (qio_channel_writev_all(ioc, iovec, ARRAY_SIZE(iovec), &local_err)) {
error_report_err(local_err);
goto err;
}
}
return;
goto fdcleanup;
err:
qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
close(u->slave_fd);
u->slave_fd = -1;
for (i = 0; i < fdsize; i++) {
if (fd[i] != -1) {
close_slave_channel(u);
rc = G_SOURCE_REMOVE;
fdcleanup:
if (fd) {
for (i = 0; i < fdsize; i++) {
close(fd[i]);
}
}
return;
return rc;
}
static int vhost_setup_slave_channel(struct vhost_dev *dev)
@ -1535,6 +1592,8 @@ static int vhost_setup_slave_channel(struct vhost_dev *dev)
int sv[2], ret = 0;
bool reply_supported = virtio_has_feature(dev->protocol_features,
VHOST_USER_PROTOCOL_F_REPLY_ACK);
Error *local_err = NULL;
QIOChannel *ioc;
if (!virtio_has_feature(dev->protocol_features,
VHOST_USER_PROTOCOL_F_SLAVE_REQ)) {
@ -1546,8 +1605,13 @@ static int vhost_setup_slave_channel(struct vhost_dev *dev)
return -1;
}
u->slave_fd = sv[0];
qemu_set_fd_handler(u->slave_fd, slave_read, NULL, dev);
ioc = QIO_CHANNEL(qio_channel_socket_new_fd(sv[0], &local_err));
if (!ioc) {
error_report_err(local_err);
return -1;
}
u->slave_ioc = ioc;
slave_update_read_handler(dev, NULL);
if (reply_supported) {
msg.hdr.flags |= VHOST_USER_NEED_REPLY_MASK;
@ -1565,9 +1629,7 @@ static int vhost_setup_slave_channel(struct vhost_dev *dev)
out:
close(sv[1]);
if (ret) {
qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
close(u->slave_fd);
u->slave_fd = -1;
close_slave_channel(u);
}
return ret;
@ -1804,7 +1866,6 @@ static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque)
u = g_new0(struct vhost_user, 1);
u->user = opaque;
u->slave_fd = -1;
u->dev = dev;
dev->opaque = u;
@ -1919,10 +1980,8 @@ static int vhost_user_backend_cleanup(struct vhost_dev *dev)
close(u->postcopy_fd.fd);
u->postcopy_fd.handler = NULL;
}
if (u->slave_fd >= 0) {
qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
close(u->slave_fd);
u->slave_fd = -1;
if (u->slave_ioc) {
close_slave_channel(u);
}
g_free(u->region_rb);
u->region_rb = NULL;

View File

@ -112,15 +112,28 @@ static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
if (offset >= VIRTIO_MMIO_CONFIG) {
offset -= VIRTIO_MMIO_CONFIG;
switch (size) {
case 1:
return virtio_config_readb(vdev, offset);
case 2:
return virtio_config_readw(vdev, offset);
case 4:
return virtio_config_readl(vdev, offset);
default:
abort();
if (proxy->legacy) {
switch (size) {
case 1:
return virtio_config_readb(vdev, offset);
case 2:
return virtio_config_readw(vdev, offset);
case 4:
return virtio_config_readl(vdev, offset);
default:
abort();
}
} else {
switch (size) {
case 1:
return virtio_config_modern_readb(vdev, offset);
case 2:
return virtio_config_modern_readw(vdev, offset);
case 4:
return virtio_config_modern_readl(vdev, offset);
default:
abort();
}
}
}
if (size != 4) {
@ -245,20 +258,37 @@ static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value,
if (offset >= VIRTIO_MMIO_CONFIG) {
offset -= VIRTIO_MMIO_CONFIG;
switch (size) {
case 1:
virtio_config_writeb(vdev, offset, value);
break;
case 2:
virtio_config_writew(vdev, offset, value);
break;
case 4:
virtio_config_writel(vdev, offset, value);
break;
default:
abort();
if (proxy->legacy) {
switch (size) {
case 1:
virtio_config_writeb(vdev, offset, value);
break;
case 2:
virtio_config_writew(vdev, offset, value);
break;
case 4:
virtio_config_writel(vdev, offset, value);
break;
default:
abort();
}
return;
} else {
switch (size) {
case 1:
virtio_config_modern_writeb(vdev, offset, value);
break;
case 2:
virtio_config_modern_writew(vdev, offset, value);
break;
case 4:
virtio_config_modern_writel(vdev, offset, value);
break;
default:
abort();
}
return;
}
return;
}
if (size != 4) {
qemu_log_mask(LOG_GUEST_ERROR,

View File

@ -47,7 +47,7 @@ static int worker_cb(void *opaque)
err = 1;
}
virtio_stw_p(req_data->vdev, &req_data->resp.ret, err);
virtio_stl_p(req_data->vdev, &req_data->resp.ret, err);
return 0;
}

View File

@ -4,9 +4,6 @@
#include "hw/acpi/acpi-defs.h"
#include "hw/acpi/bios-linker-loader.h"
/* Reserve RAM space for tables: add another order of magnitude. */
#define ACPI_BUILD_TABLE_MAX_SIZE 0x200000
#define ACPI_BUILD_APPNAME6 "BOCHS "
#define ACPI_BUILD_APPNAME8 "BXPC "
@ -301,6 +298,7 @@ Aml *aml_arg(int pos);
Aml *aml_to_integer(Aml *arg);
Aml *aml_to_hexstring(Aml *src, Aml *dst);
Aml *aml_to_buffer(Aml *src, Aml *dst);
Aml *aml_to_decimalstring(Aml *src, Aml *dst);
Aml *aml_store(Aml *val, Aml *target);
Aml *aml_and(Aml *arg1, Aml *arg2, Aml *dst);
Aml *aml_or(Aml *arg1, Aml *arg2, Aml *dst);
@ -323,6 +321,8 @@ Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3);
Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4);
Aml *aml_call5(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4,
Aml *arg5);
Aml *aml_call6(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4,
Aml *arg5, Aml *arg6);
Aml *aml_gpio_int(AmlConsumerAndProducer con_and_pro,
AmlLevelAndEdge edge_level,
AmlActiveHighAndLow active_level, AmlShared shared,

View File

@ -35,4 +35,5 @@ typedef struct AcpiMcfgInfo {
void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info,
const char *oem_id, const char *oem_table_id);
Aml *aml_pci_device_dsm(void);
#endif

View File

@ -46,6 +46,7 @@ typedef struct AcpiPciHpPciStatus {
typedef struct AcpiPciHpState {
AcpiPciHpPciStatus acpi_pcihp_pci_status[ACPI_PCIHP_MAX_HOTPLUG_BUS];
uint32_t hotplug_select;
uint32_t acpi_index;
PCIBus *root;
MemoryRegion io;
bool legacy_piix;
@ -71,13 +72,17 @@ void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off);
extern const VMStateDescription vmstate_acpi_pcihp_pci_status;
#define VMSTATE_PCI_HOTPLUG(pcihp, state, test_pcihp) \
bool vmstate_acpi_pcihp_use_acpi_index(void *opaque, int version_id);
#define VMSTATE_PCI_HOTPLUG(pcihp, state, test_pcihp, test_acpi_index) \
VMSTATE_UINT32_TEST(pcihp.hotplug_select, state, \
test_pcihp), \
VMSTATE_STRUCT_ARRAY_TEST(pcihp.acpi_pcihp_pci_status, state, \
ACPI_PCIHP_MAX_HOTPLUG_BUS, \
test_pcihp, 1, \
vmstate_acpi_pcihp_pci_status, \
AcpiPciHpPciStatus)
AcpiPciHpPciStatus), \
VMSTATE_UINT32_TEST(pcihp.acpi_index, state, \
test_acpi_index)
#endif

View File

@ -4,6 +4,5 @@
#include "hw/nvram/fw_cfg.h"
MemoryRegion *acpi_add_rom_blob(FWCfgCallback update, void *opaque,
GArray *blob, const char *name,
uint64_t max_size);
GArray *blob, const char *name);
#endif

View File

@ -76,8 +76,6 @@
#define MICROVM_MACHINE_ISA_SERIAL "isa-serial"
#define MICROVM_MACHINE_OPTION_ROMS "x-option-roms"
#define MICROVM_MACHINE_AUTO_KERNEL_CMDLINE "auto-kernel-cmdline"
#define MICROVM_MACHINE_OEM_ID "oem-id"
#define MICROVM_MACHINE_OEM_TABLE_ID "oem-table-id"
struct MicrovmMachineClass {
X86MachineClass parent;
@ -106,8 +104,6 @@ struct MicrovmMachineState {
Notifier machine_done;
Notifier powerdown_req;
struct GPEXConfig gpex;
char *oem_id;
char *oem_table_id;
};
#define TYPE_MICROVM_MACHINE MACHINE_TYPE_NAME("microvm")

View File

@ -46,8 +46,6 @@ typedef struct PCMachineState {
bool pit_enabled;
bool hpet_enabled;
uint64_t max_fw_size;
char *oem_id;
char *oem_table_id;
/* NUMA information: */
uint64_t numa_nodes;
@ -65,8 +63,6 @@ typedef struct PCMachineState {
#define PC_MACHINE_SATA "sata"
#define PC_MACHINE_PIT "pit"
#define PC_MACHINE_MAX_FW_SIZE "max-fw-size"
#define PC_MACHINE_OEM_ID "oem-id"
#define PC_MACHINE_OEM_TABLE_ID "oem-table-id"
/**
* PCMachineClass:
*

View File

@ -67,6 +67,8 @@ struct X86MachineState {
OnOffAuto smm;
OnOffAuto acpi;
char *oem_id;
char *oem_table_id;
/*
* Address space used by IOAPIC device. All IOAPIC interrupts
* will be translated to MSI messages in the address space.
@ -76,6 +78,8 @@ struct X86MachineState {
#define X86_MACHINE_SMM "smm"
#define X86_MACHINE_ACPI "acpi"
#define X86_MACHINE_OEM_ID "oem-id"
#define X86_MACHINE_OEM_TABLE_ID "oem-table-id"
#define TYPE_X86_MACHINE MACHINE_TYPE_NAME("x86")
OBJECT_DECLARE_TYPE(X86MachineState, X86MachineClass, X86_MACHINE)

View File

@ -359,6 +359,7 @@ struct PCIDevice {
/* ID of standby device in net_failover pair */
char *failover_pair_id;
uint32_t acpi_index;
};
void pci_register_bar(PCIDevice *pci_dev, int region_num,

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.