mirror of https://gitee.com/openkylin/qemu.git
pci, pc, virtio: features, fixes
reconnect for vhost blk tests for UEFI misc other stuff Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJc5AAMAAoJECgfDbjSjVRp57wIAKUAF8mvTaFfl/ge9IKJ0ZSO +dZS+2Zdc52n3Qk2K511hMvMmWD6xO98+VSXzwax2KgfIVCcQyYSCSbkyqZ4XiFg JUobhLHs6W24zn+2T8vZoqe4XWU6Pm1Y6NM72EFuhag8mhFlwWyMjpTwsISbjhGM /FpHsPpB2/c7Uofe8CVmPl55PDqOoIm35YlbH5v6zUtBiPNRgZTDOMtYjl/tyuZC VExs41/G15psNDIFd4dL1Zq6UjQBdu3ALIjIXTmPfg0nFXZn7FrOBRHbXWyzR9Tb rqEDauxb3iGHphgNqeumfrSPXNrfB91Z8AD2aerTcvgUEdbc9QykxS/YM3erkGo= =kkcS -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging pci, pc, virtio: features, fixes reconnect for vhost blk tests for UEFI misc other stuff Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Tue 21 May 2019 14:41:32 BST # gpg: using RSA key 281F0DB8D28D5469 # 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: (34 commits) tests: acpi: print error unable to dump ACPI table during rebuild tests: acpi: refactor rebuild-expected-aml.sh to dump ACPI tables for a specified list of targets tests: acpi: allow to override default accelerator tests: acpi: ignore SMBIOS tests when UEFI firmware is used tests: acpi: add a way to start tests with UEFI firmware tests: acpi: add acpi_find_rsdp_address_uefi() helper tests: acpi: move boot_sector_init() into x86 tests branch tests: acpi: skip FACS table if board uses hw reduced ACPI profile tests: acpi: fetch X_DSDT if pointer to DSDT is 0 tests: acpi: make pointer to RSDP 64bit tests: acpi: make RSDT test routine handle XSDT tests: acpi: make acpi_fetch_table() take size of fetched table pointer tests: acpi: rename acpi_parse_rsdp_table() into acpi_fetch_rsdp_table() pci: Simplify pci_bus_is_root() pcie: Remove redundant test in pcie_mmcfg_data_{read,write}() libvhost-user: fix bad vu_log_write hw/arm/virt-acpi-build: pass AcpiMcfgInfo to build_mcfg() i386, acpi: remove mcfg_ prefix in AcpiMcfgInfo members hw/arm/virt-acpi-build: remove unnecessary variable mcfg_start do not call vhost_net_cleanup() on running net from char user event ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
247ba27c52
|
@ -1484,7 +1484,7 @@ M: Michael S. Tsirkin <mst@redhat.com>
|
|||
S: Supported
|
||||
F: hw/*/*vhost*
|
||||
F: docs/interop/vhost-user.json
|
||||
F: docs/interop/vhost-user.txt
|
||||
F: docs/interop/vhost-user.rst
|
||||
F: contrib/vhost-user-*/
|
||||
F: backends/vhost-user.c
|
||||
F: include/sysemu/vhost-user-backend.h
|
||||
|
|
|
@ -433,7 +433,7 @@ vu_log_write(VuDev *dev, uint64_t address, uint64_t length)
|
|||
page = address / VHOST_LOG_PAGE;
|
||||
while (page * VHOST_LOG_PAGE < address + length) {
|
||||
vu_log_page(dev->log_table, page);
|
||||
page += VHOST_LOG_PAGE;
|
||||
page += 1;
|
||||
}
|
||||
|
||||
vu_log_kick(dev);
|
||||
|
|
|
@ -398,7 +398,8 @@ vub_get_features(VuDev *dev)
|
|||
static uint64_t
|
||||
vub_get_protocol_features(VuDev *dev)
|
||||
{
|
||||
return 1ull << VHOST_USER_PROTOCOL_F_CONFIG;
|
||||
return 1ull << VHOST_USER_PROTOCOL_F_CONFIG |
|
||||
1ull << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -15,4 +15,4 @@ Contents:
|
|||
bitmaps
|
||||
live-block-operations
|
||||
pr-helper
|
||||
|
||||
vhost-user
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -37,14 +37,7 @@
|
|||
#include "hw/pci/pci_bus.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qom/qom-qobject.h"
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# define ACPI_PCIHP_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
|
||||
#else
|
||||
# define ACPI_PCIHP_DPRINTF(format, ...) do { } while (0)
|
||||
#endif
|
||||
#include "trace.h"
|
||||
|
||||
#define ACPI_PCIHP_ADDR 0xae00
|
||||
#define ACPI_PCIHP_SIZE 0x0014
|
||||
|
@ -159,6 +152,8 @@ static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slo
|
|||
int slot = ctz32(slots);
|
||||
PCIBus *bus = acpi_pcihp_find_hotplug_bus(s, bsel);
|
||||
|
||||
trace_acpi_pci_eject_slot(bsel, slot);
|
||||
|
||||
if (!bus) {
|
||||
return;
|
||||
}
|
||||
|
@ -270,6 +265,8 @@ 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)
|
||||
{
|
||||
trace_acpi_pci_unplug(PCI_SLOT(PCI_DEVICE(dev)->devfn),
|
||||
acpi_pcihp_get_bsel(pci_get_bus(PCI_DEVICE(dev))));
|
||||
object_property_set_bool(OBJECT(dev), false, "realized", NULL);
|
||||
}
|
||||
|
||||
|
@ -280,6 +277,9 @@ void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
|
|||
PCIDevice *pdev = PCI_DEVICE(dev);
|
||||
int slot = PCI_SLOT(pdev->devfn);
|
||||
int bsel = acpi_pcihp_get_bsel(pci_get_bus(pdev));
|
||||
|
||||
trace_acpi_pci_unplug_request(bsel, slot);
|
||||
|
||||
if (bsel < 0) {
|
||||
error_setg(errp, "Unsupported bus. Bus doesn't have property '"
|
||||
ACPI_PCIHP_PROP_BSEL "' set");
|
||||
|
@ -306,23 +306,23 @@ static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
|
|||
if (!s->legacy_piix) {
|
||||
s->acpi_pcihp_pci_status[bsel].up = 0;
|
||||
}
|
||||
ACPI_PCIHP_DPRINTF("pci_up_read %" PRIu32 "\n", val);
|
||||
trace_acpi_pci_up_read(val);
|
||||
break;
|
||||
case PCI_DOWN_BASE:
|
||||
val = s->acpi_pcihp_pci_status[bsel].down;
|
||||
ACPI_PCIHP_DPRINTF("pci_down_read %" PRIu32 "\n", val);
|
||||
trace_acpi_pci_down_read(val);
|
||||
break;
|
||||
case PCI_EJ_BASE:
|
||||
/* No feature defined yet */
|
||||
ACPI_PCIHP_DPRINTF("pci_features_read %" PRIu32 "\n", val);
|
||||
trace_acpi_pci_features_read(val);
|
||||
break;
|
||||
case PCI_RMV_BASE:
|
||||
val = s->acpi_pcihp_pci_status[bsel].hotplug_enable;
|
||||
ACPI_PCIHP_DPRINTF("pci_rmv_read %" PRIu32 "\n", val);
|
||||
trace_acpi_pci_rmv_read(val);
|
||||
break;
|
||||
case PCI_SEL_BASE:
|
||||
val = s->hotplug_select;
|
||||
ACPI_PCIHP_DPRINTF("pci_sel_read %" PRIu32 "\n", val);
|
||||
trace_acpi_pci_sel_read(val);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -340,13 +340,11 @@ static void pci_write(void *opaque, hwaddr addr, uint64_t data,
|
|||
break;
|
||||
}
|
||||
acpi_pcihp_eject_slot(s, s->hotplug_select, data);
|
||||
ACPI_PCIHP_DPRINTF("pciej write %" HWADDR_PRIx " <== %" PRIu64 "\n",
|
||||
addr, data);
|
||||
trace_acpi_pci_ej_write(addr, data);
|
||||
break;
|
||||
case PCI_SEL_BASE:
|
||||
s->hotplug_select = s->legacy_piix ? ACPI_PCIHP_BSEL_DEFAULT : data;
|
||||
ACPI_PCIHP_DPRINTF("pcisel write %" HWADDR_PRIx " <== %" PRIu64 "\n",
|
||||
addr, data);
|
||||
trace_acpi_pci_sel_write(addr, data);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -39,14 +39,7 @@
|
|||
#include "hw/acpi/acpi_dev_interface.h"
|
||||
#include "hw/xen/xen.h"
|
||||
#include "qom/cpu.h"
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# define PIIX4_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
|
||||
#else
|
||||
# define PIIX4_DPRINTF(format, ...) do { } while (0)
|
||||
#endif
|
||||
#include "trace.h"
|
||||
|
||||
#define GPE_BASE 0xafe0
|
||||
#define GPE_LEN 4
|
||||
|
@ -583,7 +576,7 @@ static uint64_t gpe_readb(void *opaque, hwaddr addr, unsigned width)
|
|||
PIIX4PMState *s = opaque;
|
||||
uint32_t val = acpi_gpe_ioport_readb(&s->ar, addr);
|
||||
|
||||
PIIX4_DPRINTF("gpe read %" HWADDR_PRIx " == %" PRIu32 "\n", addr, val);
|
||||
trace_piix4_gpe_readb(addr, width, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -592,10 +585,9 @@ static void gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
|
|||
{
|
||||
PIIX4PMState *s = opaque;
|
||||
|
||||
trace_piix4_gpe_writeb(addr, width, val);
|
||||
acpi_gpe_ioport_writeb(&s->ar, addr, val);
|
||||
acpi_update_sci(&s->ar, s->irq);
|
||||
|
||||
PIIX4_DPRINTF("gpe write %" HWADDR_PRIx " <== %" PRIu64 "\n", addr, val);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps piix4_gpe_ops = {
|
||||
|
|
|
@ -31,6 +31,22 @@ cpuhp_acpi_ejecting_cpu(uint32_t idx) "0x%"PRIx32
|
|||
cpuhp_acpi_write_ost_ev(uint32_t slot, uint32_t ev) "idx[0x%"PRIx32"] OST EVENT: 0x%"PRIx32
|
||||
cpuhp_acpi_write_ost_status(uint32_t slot, uint32_t st) "idx[0x%"PRIx32"] OST STATUS: 0x%"PRIx32
|
||||
|
||||
# pcihp.c
|
||||
acpi_pci_eject_slot(unsigned bsel, unsigned slot) "bsel: %u slot: %u"
|
||||
acpi_pci_unplug(int bsel, int slot) "bsel: %d slot: %d"
|
||||
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_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
|
||||
acpi_pci_sel_write(uint64_t addr, uint64_t data) "0x%" PRIx64 " <== %" PRIu64
|
||||
|
||||
# piix4.c
|
||||
piix4_gpe_readb(uint64_t addr, unsigned width, uint64_t val) "addr: 0x%" PRIx64 " width: %d ==> 0x%" PRIx64
|
||||
piix4_gpe_writeb(uint64_t addr, unsigned width, uint64_t val) "addr: 0x%" PRIx64 " width: %d <== 0x%" PRIx64
|
||||
|
||||
# tco.c
|
||||
tco_timer_reload(int ticks, int msec) "ticks=%d (%d ms)"
|
||||
tco_timer_expired(int timeouts_no, bool strap, bool no_reboot) "timeouts_no=%d no_reboot=%d/%d"
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "hw/loader.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/acpi/aml-build.h"
|
||||
#include "hw/acpi/pci.h"
|
||||
#include "hw/pci/pcie_host.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/arm/virt.h"
|
||||
|
@ -546,25 +547,20 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
|||
}
|
||||
|
||||
static void
|
||||
build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info)
|
||||
{
|
||||
AcpiTableMcfg *mcfg;
|
||||
const MemMapEntry *memmap = vms->memmap;
|
||||
int ecam_id = VIRT_ECAM_ID(vms->highmem_ecam);
|
||||
int len = sizeof(*mcfg) + sizeof(mcfg->allocation[0]);
|
||||
int mcfg_start = table_data->len;
|
||||
|
||||
mcfg = acpi_data_push(table_data, len);
|
||||
mcfg->allocation[0].address = cpu_to_le64(memmap[ecam_id].base);
|
||||
mcfg->allocation[0].address = cpu_to_le64(info->base);
|
||||
|
||||
/* Only a single allocation so no need to play with segments */
|
||||
mcfg->allocation[0].pci_segment = cpu_to_le16(0);
|
||||
mcfg->allocation[0].start_bus_number = 0;
|
||||
mcfg->allocation[0].end_bus_number =
|
||||
PCIE_MMCFG_BUS(memmap[ecam_id].size - 1);
|
||||
mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->size - 1);
|
||||
|
||||
build_header(linker, table_data, (void *)(table_data->data + mcfg_start),
|
||||
"MCFG", table_data->len - mcfg_start, 1, NULL, NULL);
|
||||
build_header(linker, table_data, (void *)mcfg, "MCFG", len, 1, NULL, NULL);
|
||||
}
|
||||
|
||||
/* GTDT */
|
||||
|
@ -803,7 +799,13 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
|
|||
build_gtdt(tables_blob, tables->linker, vms);
|
||||
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_mcfg(tables_blob, tables->linker, vms);
|
||||
{
|
||||
AcpiMcfgInfo mcfg = {
|
||||
.base = vms->memmap[VIRT_ECAM_ID(vms->highmem_ecam)].base,
|
||||
.size = vms->memmap[VIRT_ECAM_ID(vms->highmem_ecam)].size,
|
||||
};
|
||||
build_mcfg(tables_blob, tables->linker, &mcfg);
|
||||
}
|
||||
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_spcr(tables_blob, tables->linker, vms);
|
||||
|
|
|
@ -103,7 +103,7 @@ const VhostDevConfigOps blk_ops = {
|
|||
.vhost_dev_config_notifier = vhost_user_blk_handle_config_change,
|
||||
};
|
||||
|
||||
static void vhost_user_blk_start(VirtIODevice *vdev)
|
||||
static int vhost_user_blk_start(VirtIODevice *vdev)
|
||||
{
|
||||
VHostUserBlk *s = VHOST_USER_BLK(vdev);
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
|
||||
|
@ -112,13 +112,13 @@ static void vhost_user_blk_start(VirtIODevice *vdev)
|
|||
|
||||
if (!k->set_guest_notifiers) {
|
||||
error_report("binding does not support guest notifiers");
|
||||
return;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
ret = vhost_dev_enable_notifiers(&s->dev, vdev);
|
||||
if (ret < 0) {
|
||||
error_report("Error enabling host notifiers: %d", -ret);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, true);
|
||||
|
@ -157,12 +157,13 @@ static void vhost_user_blk_start(VirtIODevice *vdev)
|
|||
vhost_virtqueue_mask(&s->dev, vdev, i, false);
|
||||
}
|
||||
|
||||
return;
|
||||
return ret;
|
||||
|
||||
err_guest_notifiers:
|
||||
k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false);
|
||||
err_host_notifiers:
|
||||
vhost_dev_disable_notifiers(&s->dev, vdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void vhost_user_blk_stop(VirtIODevice *vdev)
|
||||
|
@ -190,18 +191,28 @@ static void vhost_user_blk_stop(VirtIODevice *vdev)
|
|||
static void vhost_user_blk_set_status(VirtIODevice *vdev, uint8_t status)
|
||||
{
|
||||
VHostUserBlk *s = VHOST_USER_BLK(vdev);
|
||||
bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK;
|
||||
bool should_start = vdev->started;
|
||||
int ret;
|
||||
|
||||
if (!vdev->vm_running) {
|
||||
should_start = false;
|
||||
}
|
||||
|
||||
if (!s->connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->dev.started == should_start) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (should_start) {
|
||||
vhost_user_blk_start(vdev);
|
||||
ret = vhost_user_blk_start(vdev);
|
||||
if (ret < 0) {
|
||||
error_report("vhost-user-blk: vhost start failed: %s",
|
||||
strerror(-ret));
|
||||
qemu_chr_fe_disconnect(&s->chardev);
|
||||
}
|
||||
} else {
|
||||
vhost_user_blk_stop(vdev);
|
||||
}
|
||||
|
@ -237,10 +248,13 @@ static uint64_t vhost_user_blk_get_features(VirtIODevice *vdev,
|
|||
static void vhost_user_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
||||
{
|
||||
VHostUserBlk *s = VHOST_USER_BLK(vdev);
|
||||
int i;
|
||||
int i, ret;
|
||||
|
||||
if (!(virtio_host_has_feature(vdev, VIRTIO_F_VERSION_1) &&
|
||||
!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1))) {
|
||||
if (!vdev->start_on_kick) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s->connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -251,7 +265,13 @@ static void vhost_user_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
|||
/* Some guests kick before setting VIRTIO_CONFIG_S_DRIVER_OK so start
|
||||
* vhost here instead of waiting for .set_status().
|
||||
*/
|
||||
vhost_user_blk_start(vdev);
|
||||
ret = vhost_user_blk_start(vdev);
|
||||
if (ret < 0) {
|
||||
error_report("vhost-user-blk: vhost start failed: %s",
|
||||
strerror(-ret));
|
||||
qemu_chr_fe_disconnect(&s->chardev);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Kick right away to begin processing requests already in vring */
|
||||
for (i = 0; i < s->dev.nvqs; i++) {
|
||||
|
@ -271,11 +291,103 @@ static void vhost_user_blk_reset(VirtIODevice *vdev)
|
|||
vhost_dev_free_inflight(s->inflight);
|
||||
}
|
||||
|
||||
static int vhost_user_blk_connect(DeviceState *dev)
|
||||
{
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
||||
VHostUserBlk *s = VHOST_USER_BLK(vdev);
|
||||
int ret = 0;
|
||||
|
||||
if (s->connected) {
|
||||
return 0;
|
||||
}
|
||||
s->connected = true;
|
||||
|
||||
s->dev.nvqs = s->num_queues;
|
||||
s->dev.vqs = s->vqs;
|
||||
s->dev.vq_index = 0;
|
||||
s->dev.backend_features = 0;
|
||||
|
||||
vhost_dev_set_config_notifier(&s->dev, &blk_ops);
|
||||
|
||||
ret = vhost_dev_init(&s->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0);
|
||||
if (ret < 0) {
|
||||
error_report("vhost-user-blk: vhost initialization failed: %s",
|
||||
strerror(-ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* restore vhost state */
|
||||
if (vdev->started) {
|
||||
ret = vhost_user_blk_start(vdev);
|
||||
if (ret < 0) {
|
||||
error_report("vhost-user-blk: vhost start failed: %s",
|
||||
strerror(-ret));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vhost_user_blk_disconnect(DeviceState *dev)
|
||||
{
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
||||
VHostUserBlk *s = VHOST_USER_BLK(vdev);
|
||||
|
||||
if (!s->connected) {
|
||||
return;
|
||||
}
|
||||
s->connected = false;
|
||||
|
||||
if (s->dev.started) {
|
||||
vhost_user_blk_stop(vdev);
|
||||
}
|
||||
|
||||
vhost_dev_cleanup(&s->dev);
|
||||
}
|
||||
|
||||
static gboolean vhost_user_blk_watch(GIOChannel *chan, GIOCondition cond,
|
||||
void *opaque)
|
||||
{
|
||||
DeviceState *dev = opaque;
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
||||
VHostUserBlk *s = VHOST_USER_BLK(vdev);
|
||||
|
||||
qemu_chr_fe_disconnect(&s->chardev);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void vhost_user_blk_event(void *opaque, int event)
|
||||
{
|
||||
DeviceState *dev = opaque;
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
||||
VHostUserBlk *s = VHOST_USER_BLK(vdev);
|
||||
|
||||
switch (event) {
|
||||
case CHR_EVENT_OPENED:
|
||||
if (vhost_user_blk_connect(dev) < 0) {
|
||||
qemu_chr_fe_disconnect(&s->chardev);
|
||||
return;
|
||||
}
|
||||
s->watch = qemu_chr_fe_add_watch(&s->chardev, G_IO_HUP,
|
||||
vhost_user_blk_watch, dev);
|
||||
break;
|
||||
case CHR_EVENT_CLOSED:
|
||||
vhost_user_blk_disconnect(dev);
|
||||
if (s->watch) {
|
||||
g_source_remove(s->watch);
|
||||
s->watch = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
||||
VHostUserBlk *s = VHOST_USER_BLK(vdev);
|
||||
struct vhost_virtqueue *vqs = NULL;
|
||||
Error *err = NULL;
|
||||
int i, ret;
|
||||
|
||||
if (!s->chardev.chr) {
|
||||
|
@ -306,27 +418,29 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
|
|||
}
|
||||
|
||||
s->inflight = g_new0(struct vhost_inflight, 1);
|
||||
s->vqs = g_new(struct vhost_virtqueue, s->num_queues);
|
||||
s->watch = 0;
|
||||
s->connected = false;
|
||||
|
||||
s->dev.nvqs = s->num_queues;
|
||||
s->dev.vqs = g_new(struct vhost_virtqueue, s->dev.nvqs);
|
||||
s->dev.vq_index = 0;
|
||||
s->dev.backend_features = 0;
|
||||
vqs = s->dev.vqs;
|
||||
qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, vhost_user_blk_event,
|
||||
NULL, (void *)dev, NULL, true);
|
||||
|
||||
vhost_dev_set_config_notifier(&s->dev, &blk_ops);
|
||||
|
||||
ret = vhost_dev_init(&s->dev, &s->vhost_user, VHOST_BACKEND_TYPE_USER, 0);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "vhost-user-blk: vhost initialization failed: %s",
|
||||
strerror(-ret));
|
||||
reconnect:
|
||||
if (qemu_chr_fe_wait_connected(&s->chardev, &err) < 0) {
|
||||
error_report_err(err);
|
||||
goto virtio_err;
|
||||
}
|
||||
|
||||
/* check whether vhost_user_blk_connect() failed or not */
|
||||
if (!s->connected) {
|
||||
goto reconnect;
|
||||
}
|
||||
|
||||
ret = vhost_dev_get_config(&s->dev, (uint8_t *)&s->blkcfg,
|
||||
sizeof(struct virtio_blk_config));
|
||||
sizeof(struct virtio_blk_config));
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "vhost-user-blk: get block config failed");
|
||||
goto vhost_err;
|
||||
error_report("vhost-user-blk: get block config failed");
|
||||
goto reconnect;
|
||||
}
|
||||
|
||||
if (s->blkcfg.num_queues != s->num_queues) {
|
||||
|
@ -335,10 +449,8 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
return;
|
||||
|
||||
vhost_err:
|
||||
vhost_dev_cleanup(&s->dev);
|
||||
virtio_err:
|
||||
g_free(vqs);
|
||||
g_free(s->vqs);
|
||||
g_free(s->inflight);
|
||||
virtio_cleanup(vdev);
|
||||
vhost_user_cleanup(&s->vhost_user);
|
||||
|
@ -348,12 +460,13 @@ static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp)
|
|||
{
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
||||
VHostUserBlk *s = VHOST_USER_BLK(dev);
|
||||
struct vhost_virtqueue *vqs = s->dev.vqs;
|
||||
|
||||
vhost_user_blk_set_status(vdev, 0);
|
||||
virtio_set_status(vdev, 0);
|
||||
qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, false);
|
||||
vhost_dev_cleanup(&s->dev);
|
||||
vhost_dev_free_inflight(s->inflight);
|
||||
g_free(vqs);
|
||||
g_free(s->vqs);
|
||||
g_free(s->inflight);
|
||||
virtio_cleanup(vdev);
|
||||
vhost_user_cleanup(&s->vhost_user);
|
||||
|
|
|
@ -102,9 +102,26 @@ const size_t hw_compat_2_7_len = G_N_ELEMENTS(hw_compat_2_7);
|
|||
|
||||
GlobalProperty hw_compat_2_6[] = {
|
||||
{ "virtio-mmio", "format_transport_address", "off" },
|
||||
/* Optional because not all virtio-pci devices support legacy mode */
|
||||
{ "virtio-pci", "disable-modern", "on", .optional = true },
|
||||
{ "virtio-pci", "disable-legacy", "off", .optional = true },
|
||||
/*
|
||||
* don't include devices which are modern-only
|
||||
* ie keyboard, mouse, tablet, gpu, vga & crypto
|
||||
*/
|
||||
{ "virtio-9p-pci", "disable-modern", "on" },
|
||||
{ "virtio-9p-pci", "disable-legacy", "off" },
|
||||
{ "virtio-balloon-pci", "disable-modern", "on" },
|
||||
{ "virtio-balloon-pci", "disable-legacy", "off" },
|
||||
{ "virtio-blk-pci", "disable-modern", "on" },
|
||||
{ "virtio-blk-pci", "disable-legacy", "off" },
|
||||
{ "virtio-input-host-pci", "disable-modern", "on" },
|
||||
{ "virtio-input-host-pci", "disable-legacy", "off" },
|
||||
{ "virtio-net-pci", "disable-modern", "on" },
|
||||
{ "virtio-net-pci", "disable-legacy", "off" },
|
||||
{ "virtio-rng-pci", "disable-modern", "on" },
|
||||
{ "virtio-rng-pci", "disable-legacy", "off" },
|
||||
{ "virtio-scsi-pci", "disable-modern", "on" },
|
||||
{ "virtio-scsi-pci", "disable-legacy", "off" },
|
||||
{ "virtio-serial-pci", "disable-modern", "on" },
|
||||
{ "virtio-serial-pci", "disable-legacy", "off" },
|
||||
};
|
||||
const size_t hw_compat_2_6_len = G_N_ELEMENTS(hw_compat_2_6);
|
||||
|
||||
|
|
|
@ -47,7 +47,9 @@ static void virtio_gpu_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
|
|||
Error *local_error = NULL;
|
||||
|
||||
qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
|
||||
virtio_pci_force_virtio_1(vpci_dev);
|
||||
if (!virtio_pci_force_virtio_1(vpci_dev, errp)) {
|
||||
return;
|
||||
}
|
||||
object_property_set_bool(OBJECT(vdev), true, "realized", &local_error);
|
||||
|
||||
if (local_error) {
|
||||
|
|
|
@ -154,7 +154,9 @@ static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
|
|||
|
||||
/* init virtio bits */
|
||||
qdev_set_parent_bus(DEVICE(g), BUS(&vpci_dev->bus));
|
||||
virtio_pci_force_virtio_1(vpci_dev);
|
||||
if (!virtio_pci_force_virtio_1(vpci_dev, errp)) {
|
||||
return;
|
||||
}
|
||||
object_property_set_bool(OBJECT(g), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "hw/i386/x86-iommu.h"
|
||||
|
||||
#include "hw/acpi/aml-build.h"
|
||||
#include "hw/acpi/pci.h"
|
||||
|
||||
#include "qom/qom-qobject.h"
|
||||
#include "hw/i386/amd_iommu.h"
|
||||
|
@ -87,11 +88,6 @@
|
|||
/* Default IOAPIC ID */
|
||||
#define ACPI_BUILD_IOAPIC_ID 0x0
|
||||
|
||||
typedef struct AcpiMcfgInfo {
|
||||
uint64_t mcfg_base;
|
||||
uint32_t mcfg_size;
|
||||
} AcpiMcfgInfo;
|
||||
|
||||
typedef struct AcpiPmInfo {
|
||||
bool s3_disabled;
|
||||
bool s4_disabled;
|
||||
|
@ -2413,29 +2409,16 @@ static void
|
|||
build_mcfg_q35(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info)
|
||||
{
|
||||
AcpiTableMcfg *mcfg;
|
||||
const char *sig;
|
||||
int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
|
||||
|
||||
mcfg = acpi_data_push(table_data, len);
|
||||
mcfg->allocation[0].address = cpu_to_le64(info->mcfg_base);
|
||||
mcfg->allocation[0].address = cpu_to_le64(info->base);
|
||||
/* Only a single allocation so no need to play with segments */
|
||||
mcfg->allocation[0].pci_segment = cpu_to_le16(0);
|
||||
mcfg->allocation[0].start_bus_number = 0;
|
||||
mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->mcfg_size - 1);
|
||||
mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->size - 1);
|
||||
|
||||
/* MCFG is used for ECAM which can be enabled or disabled by guest.
|
||||
* To avoid table size changes (which create migration issues),
|
||||
* always create the table even if there are no allocations,
|
||||
* but set the signature to a reserved value in this case.
|
||||
* ACPI spec requires OSPMs to ignore such tables.
|
||||
*/
|
||||
if (info->mcfg_base == PCIE_BASE_ADDR_UNMAPPED) {
|
||||
/* Reserved signature: ignored by OSPM */
|
||||
sig = "QEMU";
|
||||
} else {
|
||||
sig = "MCFG";
|
||||
}
|
||||
build_header(linker, table_data, (void *)mcfg, sig, len, 1, NULL, NULL);
|
||||
build_header(linker, table_data, (void *)mcfg, "MCFG", len, 1, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2602,12 +2585,15 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
|
|||
if (!o) {
|
||||
return false;
|
||||
}
|
||||
mcfg->mcfg_base = qnum_get_uint(qobject_to(QNum, o));
|
||||
mcfg->base = qnum_get_uint(qobject_to(QNum, o));
|
||||
qobject_unref(o);
|
||||
if (mcfg->base == PCIE_BASE_ADDR_UNMAPPED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
|
||||
assert(o);
|
||||
mcfg->mcfg_size = qnum_get_uint(qobject_to(QNum, o));
|
||||
mcfg->size = qnum_get_uint(qobject_to(QNum, o));
|
||||
qobject_unref(o);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -66,11 +66,6 @@ static int pxb_bus_num(PCIBus *bus)
|
|||
return pxb->bus_nr;
|
||||
}
|
||||
|
||||
static bool pxb_is_root(PCIBus *bus)
|
||||
{
|
||||
return true; /* by definition */
|
||||
}
|
||||
|
||||
static uint16_t pxb_bus_numa_node(PCIBus *bus)
|
||||
{
|
||||
PXBDev *pxb = convert_to_pxb(bus->parent_dev);
|
||||
|
@ -83,7 +78,6 @@ static void pxb_bus_class_init(ObjectClass *class, void *data)
|
|||
PCIBusClass *pbc = PCI_BUS_CLASS(class);
|
||||
|
||||
pbc->bus_num = pxb_bus_num;
|
||||
pbc->is_root = pxb_is_root;
|
||||
pbc->numa_node = pxb_bus_numa_node;
|
||||
}
|
||||
|
||||
|
|
14
hw/pci/pci.c
14
hw/pci/pci.c
|
@ -129,14 +129,9 @@ static void pci_bus_unrealize(BusState *qbus, Error **errp)
|
|||
vmstate_unregister(NULL, &vmstate_pcibus, bus);
|
||||
}
|
||||
|
||||
static bool pcibus_is_root(PCIBus *bus)
|
||||
{
|
||||
return !bus->parent_dev;
|
||||
}
|
||||
|
||||
static int pcibus_num(PCIBus *bus)
|
||||
{
|
||||
if (pcibus_is_root(bus)) {
|
||||
if (pci_bus_is_root(bus)) {
|
||||
return 0; /* pci host bridge */
|
||||
}
|
||||
return bus->parent_dev->config[PCI_SECONDARY_BUS];
|
||||
|
@ -164,7 +159,6 @@ static void pci_bus_class_init(ObjectClass *klass, void *data)
|
|||
k->unrealize = pci_bus_unrealize;
|
||||
k->reset = pcibus_reset;
|
||||
|
||||
pbc->is_root = pcibus_is_root;
|
||||
pbc->bus_num = pcibus_num;
|
||||
pbc->numa_node = pcibus_numa_node;
|
||||
pbc->allows_extended_config_space = pcibus_allows_extended_config_space;
|
||||
|
@ -398,6 +392,7 @@ static void pci_root_bus_init(PCIBus *bus, DeviceState *parent,
|
|||
bus->slot_reserved_mask = 0x0;
|
||||
bus->address_space_mem = address_space_mem;
|
||||
bus->address_space_io = address_space_io;
|
||||
bus->flags |= PCI_BUS_IS_ROOT;
|
||||
|
||||
/* host bridge */
|
||||
QLIST_INIT(&bus->child);
|
||||
|
@ -415,11 +410,6 @@ bool pci_bus_is_express(PCIBus *bus)
|
|||
return object_dynamic_cast(OBJECT(bus), TYPE_PCIE_BUS);
|
||||
}
|
||||
|
||||
bool pci_bus_is_root(PCIBus *bus)
|
||||
{
|
||||
return PCI_BUS_GET_CLASS(bus)->is_root(bus);
|
||||
}
|
||||
|
||||
bool pci_bus_allows_extended_config_space(PCIBus *bus)
|
||||
{
|
||||
return PCI_BUS_GET_CLASS(bus)->allows_extended_config_space(bus);
|
||||
|
|
|
@ -47,11 +47,6 @@ static void pcie_mmcfg_data_write(void *opaque, hwaddr mmcfg_addr,
|
|||
}
|
||||
addr = PCIE_MMCFG_CONFOFFSET(mmcfg_addr);
|
||||
limit = pci_config_size(pci_dev);
|
||||
if (limit <= addr) {
|
||||
/* conventional pci device can be behind pcie-to-pci bridge.
|
||||
256 <= addr < 4K has no effects. */
|
||||
return;
|
||||
}
|
||||
pci_host_config_write_common(pci_dev, addr, limit, val, len);
|
||||
}
|
||||
|
||||
|
@ -70,11 +65,6 @@ static uint64_t pcie_mmcfg_data_read(void *opaque,
|
|||
}
|
||||
addr = PCIE_MMCFG_CONFOFFSET(mmcfg_addr);
|
||||
limit = pci_config_size(pci_dev);
|
||||
if (limit <= addr) {
|
||||
/* conventional pci device can be behind pcie-to-pci bridge.
|
||||
256 <= addr < 4K has no effects. */
|
||||
return ~0x0;
|
||||
}
|
||||
return pci_host_config_read_common(pci_dev, addr, limit, len);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,9 @@ static void virtio_crypto_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
|
|||
}
|
||||
|
||||
qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
|
||||
virtio_pci_force_virtio_1(vpci_dev);
|
||||
if (!virtio_pci_force_virtio_1(vpci_dev, errp)) {
|
||||
return;
|
||||
}
|
||||
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
|
||||
object_property_set_link(OBJECT(vcrypto),
|
||||
OBJECT(vcrypto->vdev.conf.cryptodev), "cryptodev",
|
||||
|
|
|
@ -48,7 +48,9 @@ static void virtio_input_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
|
|||
DeviceState *vdev = DEVICE(&vinput->vdev);
|
||||
|
||||
qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
|
||||
virtio_pci_force_virtio_1(vpci_dev);
|
||||
if (!virtio_pci_force_virtio_1(vpci_dev, errp)) {
|
||||
return;
|
||||
}
|
||||
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "standard-headers/linux/virtio_pci.h"
|
||||
#include "hw/virtio/virtio.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/pci/pci_bus.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/pci/msi.h"
|
||||
|
@ -1721,16 +1722,22 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
|
|||
/* PCI BAR regions must be powers of 2 */
|
||||
pow2ceil(proxy->notify.offset + proxy->notify.size));
|
||||
|
||||
if (proxy->disable_legacy == ON_OFF_AUTO_AUTO) {
|
||||
proxy->disable_legacy = pcie_port ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
|
||||
}
|
||||
|
||||
if (!virtio_pci_modern(proxy) && !virtio_pci_legacy(proxy)) {
|
||||
error_setg(errp, "device cannot work as neither modern nor legacy mode"
|
||||
" is enabled");
|
||||
error_append_hint(errp, "Set either disable-modern or disable-legacy"
|
||||
" to off\n");
|
||||
return;
|
||||
if ((proxy->disable_legacy == ON_OFF_AUTO_ON) ||
|
||||
((proxy->disable_legacy == ON_OFF_AUTO_AUTO) && pcie_port)) {
|
||||
if (proxy->disable_modern) {
|
||||
error_setg(errp, "device cannot work as neither modern nor "
|
||||
"legacy mode is enabled");
|
||||
error_append_hint(errp, "Set either disable-modern or "
|
||||
"disable-legacy to off\n");
|
||||
return;
|
||||
}
|
||||
proxy->mode = VIRTIO_PCI_MODE_MODERN;
|
||||
} else {
|
||||
if (proxy->disable_modern) {
|
||||
proxy->mode = VIRTIO_PCI_MODE_LEGACY;
|
||||
} else {
|
||||
proxy->mode = VIRTIO_PCI_MODE_TRANSITIONAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (pcie_port && pci_is_express(pci_dev)) {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#ifndef QEMU_VIRTIO_PCI_H
|
||||
#define QEMU_VIRTIO_PCI_H
|
||||
|
||||
#include "qapi/error.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "hw/virtio/virtio-bus.h"
|
||||
|
||||
|
@ -118,6 +119,12 @@ typedef struct VirtIOPCIQueue {
|
|||
uint32_t used[2];
|
||||
} VirtIOPCIQueue;
|
||||
|
||||
typedef enum {
|
||||
VIRTIO_PCI_MODE_LEGACY,
|
||||
VIRTIO_PCI_MODE_TRANSITIONAL,
|
||||
VIRTIO_PCI_MODE_MODERN,
|
||||
} VirtIOPCIMode;
|
||||
|
||||
struct VirtIOPCIProxy {
|
||||
PCIDevice pci_dev;
|
||||
MemoryRegion bar;
|
||||
|
@ -142,6 +149,7 @@ struct VirtIOPCIProxy {
|
|||
bool disable_modern;
|
||||
bool ignore_backend_features;
|
||||
OnOffAuto disable_legacy;
|
||||
VirtIOPCIMode mode;
|
||||
uint32_t class_code;
|
||||
uint32_t nvectors;
|
||||
uint32_t dfselect;
|
||||
|
@ -156,23 +164,34 @@ struct VirtIOPCIProxy {
|
|||
|
||||
static inline bool virtio_pci_modern(VirtIOPCIProxy *proxy)
|
||||
{
|
||||
return !proxy->disable_modern;
|
||||
return proxy->mode != VIRTIO_PCI_MODE_LEGACY;
|
||||
}
|
||||
|
||||
static inline bool virtio_pci_legacy(VirtIOPCIProxy *proxy)
|
||||
{
|
||||
return proxy->disable_legacy == ON_OFF_AUTO_OFF;
|
||||
return proxy->mode != VIRTIO_PCI_MODE_MODERN;
|
||||
}
|
||||
|
||||
static inline void virtio_pci_force_virtio_1(VirtIOPCIProxy *proxy)
|
||||
static inline bool virtio_pci_force_virtio_1(VirtIOPCIProxy *proxy,
|
||||
Error **errp)
|
||||
{
|
||||
proxy->disable_modern = false;
|
||||
proxy->disable_legacy = ON_OFF_AUTO_ON;
|
||||
if (proxy->disable_legacy == ON_OFF_AUTO_OFF) {
|
||||
error_setg(errp, "Unable to set disable-legacy=off on a virtio-1.0 "
|
||||
"only device");
|
||||
return false;
|
||||
}
|
||||
if (proxy->disable_modern == true) {
|
||||
error_setg(errp, "Unable to set disable-modern=on on a virtio-1.0 "
|
||||
"only device");
|
||||
return false;
|
||||
}
|
||||
proxy->mode = VIRTIO_PCI_MODE_MODERN;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void virtio_pci_disable_modern(VirtIOPCIProxy *proxy)
|
||||
{
|
||||
proxy->disable_modern = true;
|
||||
proxy->mode = VIRTIO_PCI_MODE_LEGACY;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1162,10 +1162,16 @@ int virtio_set_status(VirtIODevice *vdev, uint8_t val)
|
|||
}
|
||||
}
|
||||
}
|
||||
vdev->started = val & VIRTIO_CONFIG_S_DRIVER_OK;
|
||||
if (unlikely(vdev->start_on_kick && vdev->started)) {
|
||||
vdev->start_on_kick = false;
|
||||
}
|
||||
|
||||
if (k->set_status) {
|
||||
k->set_status(vdev, val);
|
||||
}
|
||||
vdev->status = val;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1208,6 +1214,9 @@ void virtio_reset(void *opaque)
|
|||
k->reset(vdev);
|
||||
}
|
||||
|
||||
vdev->start_on_kick = (virtio_host_has_feature(vdev, VIRTIO_F_VERSION_1) &&
|
||||
!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1));
|
||||
vdev->started = false;
|
||||
vdev->broken = false;
|
||||
vdev->guest_features = 0;
|
||||
vdev->queue_sel = 0;
|
||||
|
@ -1518,14 +1527,21 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align)
|
|||
|
||||
static bool virtio_queue_notify_aio_vq(VirtQueue *vq)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (vq->vring.desc && vq->handle_aio_output) {
|
||||
VirtIODevice *vdev = vq->vdev;
|
||||
|
||||
trace_virtio_queue_notify(vdev, vq - vdev->vq, vq);
|
||||
return vq->handle_aio_output(vdev, vq);
|
||||
ret = vq->handle_aio_output(vdev, vq);
|
||||
|
||||
if (unlikely(vdev->start_on_kick)) {
|
||||
vdev->started = true;
|
||||
vdev->start_on_kick = false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void virtio_queue_notify_vq(VirtQueue *vq)
|
||||
|
@ -1539,6 +1555,11 @@ static void virtio_queue_notify_vq(VirtQueue *vq)
|
|||
|
||||
trace_virtio_queue_notify(vdev, vq - vdev->vq, vq);
|
||||
vq->handle_output(vdev, vq);
|
||||
|
||||
if (unlikely(vdev->start_on_kick)) {
|
||||
vdev->started = true;
|
||||
vdev->start_on_kick = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1556,6 +1577,11 @@ void virtio_queue_notify(VirtIODevice *vdev, int n)
|
|||
} else if (vq->handle_output) {
|
||||
vq->handle_output(vdev, vq);
|
||||
}
|
||||
|
||||
if (unlikely(vdev->start_on_kick)) {
|
||||
vdev->started = true;
|
||||
vdev->start_on_kick = false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t virtio_queue_vector(VirtIODevice *vdev, int n)
|
||||
|
@ -1770,6 +1796,13 @@ static bool virtio_broken_needed(void *opaque)
|
|||
return vdev->broken;
|
||||
}
|
||||
|
||||
static bool virtio_started_needed(void *opaque)
|
||||
{
|
||||
VirtIODevice *vdev = opaque;
|
||||
|
||||
return vdev->started;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_virtqueue = {
|
||||
.name = "virtqueue_state",
|
||||
.version_id = 1,
|
||||
|
@ -1898,6 +1931,17 @@ static const VMStateDescription vmstate_virtio_broken = {
|
|||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_virtio_started = {
|
||||
.name = "virtio/started",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = &virtio_started_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_BOOL(started, VirtIODevice),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_virtio = {
|
||||
.name = "virtio",
|
||||
.version_id = 1,
|
||||
|
@ -1913,6 +1957,7 @@ static const VMStateDescription vmstate_virtio = {
|
|||
&vmstate_virtio_ringsize,
|
||||
&vmstate_virtio_broken,
|
||||
&vmstate_virtio_extra_state,
|
||||
&vmstate_virtio_started,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
@ -2246,7 +2291,7 @@ static void virtio_vmstate_change(void *opaque, int running, RunState state)
|
|||
VirtIODevice *vdev = opaque;
|
||||
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||
bool backend_run = running && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK);
|
||||
bool backend_run = running && vdev->started;
|
||||
vdev->vm_running = running;
|
||||
|
||||
if (backend_run) {
|
||||
|
@ -2286,6 +2331,9 @@ void virtio_init(VirtIODevice *vdev, const char *name,
|
|||
g_malloc0(sizeof(*vdev->vector_queues) * nvectors);
|
||||
}
|
||||
|
||||
vdev->start_on_kick = (virtio_host_has_feature(vdev, VIRTIO_F_VERSION_1) &&
|
||||
!virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1));
|
||||
vdev->started = false;
|
||||
vdev->device_id = device_id;
|
||||
vdev->status = 0;
|
||||
atomic_set(&vdev->isr, 0);
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Support for generating PCI related ACPI tables and passing them to Guests
|
||||
*
|
||||
* Copyright (C) 2006 Fabrice Bellard
|
||||
* Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net>
|
||||
* Copyright (C) 2013-2019 Red Hat Inc
|
||||
* Copyright (C) 2019 Intel Corporation
|
||||
*
|
||||
* Author: Wei Yang <richardw.yang@linux.intel.com>
|
||||
* Author: Michael S. Tsirkin <mst@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef HW_ACPI_PCI_H
|
||||
#define HW_ACPI_PCI_H
|
||||
|
||||
typedef struct AcpiMcfgInfo {
|
||||
uint64_t base;
|
||||
uint32_t size;
|
||||
} AcpiMcfgInfo;
|
||||
|
||||
#endif
|
|
@ -395,7 +395,6 @@ typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin);
|
|||
#define TYPE_PCIE_BUS "PCIE"
|
||||
|
||||
bool pci_bus_is_express(PCIBus *bus);
|
||||
bool pci_bus_is_root(PCIBus *bus);
|
||||
bool pci_bus_allows_extended_config_space(PCIBus *bus);
|
||||
|
||||
void pci_root_bus_new_inplace(PCIBus *bus, size_t bus_size, DeviceState *parent,
|
||||
|
|
|
@ -15,14 +15,19 @@ typedef struct PCIBusClass {
|
|||
BusClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
bool (*is_root)(PCIBus *bus);
|
||||
int (*bus_num)(PCIBus *bus);
|
||||
uint16_t (*numa_node)(PCIBus *bus);
|
||||
bool (*allows_extended_config_space)(PCIBus *bus);
|
||||
} PCIBusClass;
|
||||
|
||||
enum PCIBusFlags {
|
||||
/* This bus is the root of a PCI domain */
|
||||
PCI_BUS_IS_ROOT = 0x0001,
|
||||
};
|
||||
|
||||
struct PCIBus {
|
||||
BusState qbus;
|
||||
enum PCIBusFlags flags;
|
||||
PCIIOMMUFunc iommu_fn;
|
||||
void *iommu_opaque;
|
||||
uint8_t devfn_min;
|
||||
|
@ -47,4 +52,9 @@ struct PCIBus {
|
|||
Notifier machine_done;
|
||||
};
|
||||
|
||||
static inline bool pci_bus_is_root(PCIBus *bus)
|
||||
{
|
||||
return !!(bus->flags & PCI_BUS_IS_ROOT);
|
||||
}
|
||||
|
||||
#endif /* QEMU_PCI_BUS_H */
|
||||
|
|
|
@ -251,8 +251,6 @@ struct PropertyInfo {
|
|||
/**
|
||||
* GlobalProperty:
|
||||
* @used: Set to true if property was used when initializing a device.
|
||||
* @optional: If set to true, GlobalProperty will be skipped without errors
|
||||
* if the property doesn't exist.
|
||||
*
|
||||
* An error is fatal for non-hotplugged devices, when the global is applied.
|
||||
*/
|
||||
|
@ -261,7 +259,6 @@ typedef struct GlobalProperty {
|
|||
const char *property;
|
||||
const char *value;
|
||||
bool used;
|
||||
bool optional;
|
||||
} GlobalProperty;
|
||||
|
||||
static inline void
|
||||
|
|
|
@ -38,6 +38,9 @@ typedef struct VHostUserBlk {
|
|||
struct vhost_dev dev;
|
||||
struct vhost_inflight *inflight;
|
||||
VhostUserState vhost_user;
|
||||
struct vhost_virtqueue *vqs;
|
||||
guint watch;
|
||||
bool connected;
|
||||
} VHostUserBlk;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -105,6 +105,8 @@ struct VirtIODevice
|
|||
uint16_t device_id;
|
||||
bool vm_running;
|
||||
bool broken; /* device in invalid state, needs reset */
|
||||
bool started;
|
||||
bool start_on_kick; /* virtio 1.0 transitional devices support that */
|
||||
VMChangeStateEntry *vmstate;
|
||||
char *bus_name;
|
||||
uint8_t device_endian;
|
||||
|
|
|
@ -236,7 +236,6 @@ static void chr_closed_bh(void *opaque)
|
|||
s = DO_UPCAST(NetVhostUserState, nc, ncs[0]);
|
||||
|
||||
qmp_set_link(name, false, &err);
|
||||
vhost_user_stop(queues, ncs);
|
||||
|
||||
qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, net_vhost_user_event,
|
||||
NULL, opaque, NULL, true);
|
||||
|
|
|
@ -385,9 +385,6 @@ void object_apply_global_props(Object *obj, const GPtrArray *props, Error **errp
|
|||
if (object_dynamic_cast(obj, p->driver) == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (p->optional && !object_property_find(obj, p->property, NULL)) {
|
||||
continue;
|
||||
}
|
||||
p->used = true;
|
||||
object_property_parse(obj, p->value, p->property, &err);
|
||||
if (err != NULL) {
|
||||
|
|
|
@ -51,19 +51,7 @@ uint32_t acpi_find_rsdp_address(QTestState *qts)
|
|||
return off;
|
||||
}
|
||||
|
||||
uint64_t acpi_get_xsdt_address(uint8_t *rsdp_table)
|
||||
{
|
||||
uint64_t xsdt_physical_address;
|
||||
uint8_t revision = rsdp_table[15 /* Revision offset */];
|
||||
|
||||
/* We must have revision 2 if we're looking for an XSDT pointer */
|
||||
g_assert(revision == 2);
|
||||
|
||||
memcpy(&xsdt_physical_address, &rsdp_table[24 /* XsdtAddress offset */], 8);
|
||||
return le64_to_cpu(xsdt_physical_address);
|
||||
}
|
||||
|
||||
void acpi_parse_rsdp_table(QTestState *qts, uint32_t addr, uint8_t *rsdp_table)
|
||||
void acpi_fetch_rsdp_table(QTestState *qts, uint64_t addr, uint8_t *rsdp_table)
|
||||
{
|
||||
uint8_t revision;
|
||||
|
||||
|
@ -91,13 +79,15 @@ void acpi_parse_rsdp_table(QTestState *qts, uint32_t addr, uint8_t *rsdp_table)
|
|||
* actual one.
|
||||
*/
|
||||
void acpi_fetch_table(QTestState *qts, uint8_t **aml, uint32_t *aml_len,
|
||||
const uint8_t *addr_ptr, const char *sig,
|
||||
const uint8_t *addr_ptr, int addr_size, const char *sig,
|
||||
bool verify_checksum)
|
||||
{
|
||||
uint32_t addr, len;
|
||||
uint32_t len;
|
||||
uint64_t addr = 0;
|
||||
|
||||
memcpy(&addr, addr_ptr , sizeof(addr));
|
||||
addr = le32_to_cpu(addr);
|
||||
g_assert(addr_size == 4 || addr_size == 8);
|
||||
memcpy(&addr, addr_ptr , addr_size);
|
||||
addr = le64_to_cpu(addr);
|
||||
qtest_memread(qts, addr + 4, &len, 4); /* Length of ACPI table */
|
||||
*aml_len = le32_to_cpu(len);
|
||||
*aml = g_malloc0(*aml_len);
|
||||
|
@ -111,3 +101,47 @@ void acpi_fetch_table(QTestState *qts, uint8_t **aml, uint32_t *aml_len,
|
|||
g_assert(!acpi_calc_checksum(*aml, *aml_len));
|
||||
}
|
||||
}
|
||||
|
||||
#define GUID_SIZE 16
|
||||
static const uint8_t AcpiTestSupportGuid[GUID_SIZE] = {
|
||||
0xb1, 0xa6, 0x87, 0xab,
|
||||
0x34, 0x20,
|
||||
0xa0, 0xbd,
|
||||
0x71, 0xbd, 0x37, 0x50, 0x07, 0x75, 0x77, 0x85 };
|
||||
|
||||
typedef struct {
|
||||
uint8_t signature_guid[GUID_SIZE];
|
||||
uint64_t rsdp10;
|
||||
uint64_t rsdp20;
|
||||
} __attribute__((packed)) UefiTestSupport;
|
||||
|
||||
/* Wait at most 600 seconds (test is slow with TCG and --enable-debug) */
|
||||
#define TEST_DELAY (1 * G_USEC_PER_SEC / 10)
|
||||
#define TEST_CYCLES MAX((600 * G_USEC_PER_SEC / TEST_DELAY), 1)
|
||||
#define MB 0x100000ULL
|
||||
uint64_t acpi_find_rsdp_address_uefi(QTestState *qts, uint64_t start,
|
||||
uint64_t size)
|
||||
{
|
||||
int i, j;
|
||||
uint8_t data[GUID_SIZE];
|
||||
|
||||
for (i = 0; i < TEST_CYCLES; ++i) {
|
||||
for (j = 0; j < size / MB; j++) {
|
||||
/* look for GUID at every 1Mb block */
|
||||
uint64_t addr = start + j * MB;
|
||||
|
||||
qtest_memread(qts, addr, data, sizeof(data));
|
||||
if (!memcmp(AcpiTestSupportGuid, data, sizeof(data))) {
|
||||
UefiTestSupport ret;
|
||||
|
||||
qtest_memread(qts, addr, &ret, sizeof(ret));
|
||||
ret.rsdp10 = le64_to_cpu(ret.rsdp10);
|
||||
ret.rsdp20 = le64_to_cpu(ret.rsdp20);
|
||||
return ret.rsdp20 ? ret.rsdp20 : ret.rsdp10;
|
||||
}
|
||||
}
|
||||
g_usleep(TEST_DELAY);
|
||||
}
|
||||
g_assert_not_reached();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -46,10 +46,11 @@ typedef struct {
|
|||
|
||||
uint8_t acpi_calc_checksum(const uint8_t *data, int len);
|
||||
uint32_t acpi_find_rsdp_address(QTestState *qts);
|
||||
uint64_t acpi_get_xsdt_address(uint8_t *rsdp_table);
|
||||
void acpi_parse_rsdp_table(QTestState *qts, uint32_t addr, uint8_t *rsdp_table);
|
||||
uint64_t acpi_find_rsdp_address_uefi(QTestState *qts, uint64_t start,
|
||||
uint64_t size);
|
||||
void acpi_fetch_rsdp_table(QTestState *qts, uint64_t addr, uint8_t *rsdp_table);
|
||||
void acpi_fetch_table(QTestState *qts, uint8_t **aml, uint32_t *aml_len,
|
||||
const uint8_t *addr_ptr, const char *sig,
|
||||
const uint8_t *addr_ptr, int addr_size, const char *sig,
|
||||
bool verify_checksum);
|
||||
|
||||
#endif /* TEST_ACPI_UTILS_H */
|
||||
|
|
|
@ -24,9 +24,15 @@
|
|||
#define ACPI_REBUILD_EXPECTED_AML "TEST_ACPI_REBUILD_AML"
|
||||
|
||||
typedef struct {
|
||||
const char *accel;
|
||||
const char *machine;
|
||||
const char *variant;
|
||||
uint32_t rsdp_addr;
|
||||
const char *uefi_fl1;
|
||||
const char *uefi_fl2;
|
||||
const char *cd;
|
||||
const uint64_t ram_start;
|
||||
const uint64_t scan_len;
|
||||
uint64_t rsdp_addr;
|
||||
uint8_t rsdp_table[36 /* ACPI 2.0+ RSDP size */];
|
||||
GArray *tables;
|
||||
uint32_t smbios_ep_addr;
|
||||
|
@ -77,22 +83,13 @@ static void free_test_data(test_data *data)
|
|||
g_array_free(data->tables, true);
|
||||
}
|
||||
|
||||
static void test_acpi_rsdp_address(test_data *data)
|
||||
{
|
||||
uint32_t off = acpi_find_rsdp_address(data->qts);
|
||||
g_assert_cmphex(off, <, 0x100000);
|
||||
data->rsdp_addr = off;
|
||||
}
|
||||
|
||||
static void test_acpi_rsdp_table(test_data *data)
|
||||
{
|
||||
uint8_t *rsdp_table = data->rsdp_table, revision;
|
||||
uint32_t addr = data->rsdp_addr;
|
||||
uint8_t *rsdp_table = data->rsdp_table;
|
||||
|
||||
acpi_parse_rsdp_table(data->qts, addr, rsdp_table);
|
||||
revision = rsdp_table[15 /* Revision offset */];
|
||||
acpi_fetch_rsdp_table(data->qts, data->rsdp_addr, rsdp_table);
|
||||
|
||||
switch (revision) {
|
||||
switch (rsdp_table[15 /* Revision offset */]) {
|
||||
case 0: /* ACPI 1.0 RSDP */
|
||||
/* With rev 1, checksum is only for the first 20 bytes */
|
||||
g_assert(!acpi_calc_checksum(rsdp_table, 20));
|
||||
|
@ -107,21 +104,29 @@ static void test_acpi_rsdp_table(test_data *data)
|
|||
}
|
||||
}
|
||||
|
||||
static void test_acpi_rsdt_table(test_data *data)
|
||||
static void test_acpi_rxsdt_table(test_data *data)
|
||||
{
|
||||
const char *sig = "RSDT";
|
||||
AcpiSdtTable rsdt = {};
|
||||
int entry_size = 4;
|
||||
int addr_off = 16 /* RsdtAddress */;
|
||||
uint8_t *ent;
|
||||
|
||||
/* read RSDT table */
|
||||
if (data->rsdp_table[15 /* Revision offset */] != 0) {
|
||||
addr_off = 24 /* XsdtAddress */;
|
||||
entry_size = 8;
|
||||
sig = "XSDT";
|
||||
}
|
||||
/* read [RX]SDT table */
|
||||
acpi_fetch_table(data->qts, &rsdt.aml, &rsdt.aml_len,
|
||||
&data->rsdp_table[16 /* RsdtAddress */], "RSDT", true);
|
||||
&data->rsdp_table[addr_off], entry_size, sig, true);
|
||||
|
||||
/* Load all tables and add to test list directly RSDT referenced tables */
|
||||
ACPI_FOREACH_RSDT_ENTRY(rsdt.aml, rsdt.aml_len, ent, 4 /* Entry size */) {
|
||||
ACPI_FOREACH_RSDT_ENTRY(rsdt.aml, rsdt.aml_len, ent, entry_size) {
|
||||
AcpiSdtTable ssdt_table = {};
|
||||
|
||||
acpi_fetch_table(data->qts, &ssdt_table.aml, &ssdt_table.aml_len, ent,
|
||||
NULL, true);
|
||||
entry_size, NULL, true);
|
||||
/* Add table to ASL test tables list */
|
||||
g_array_append_val(data->tables, ssdt_table);
|
||||
}
|
||||
|
@ -134,16 +139,29 @@ static void test_acpi_fadt_table(test_data *data)
|
|||
AcpiSdtTable table = g_array_index(data->tables, typeof(table), 0);
|
||||
uint8_t *fadt_aml = table.aml;
|
||||
uint32_t fadt_len = table.aml_len;
|
||||
uint32_t val;
|
||||
int dsdt_offset = 40 /* DSDT */;
|
||||
int dsdt_entry_size = 4;
|
||||
|
||||
g_assert(compare_signature(&table, "FACP"));
|
||||
|
||||
/* Since DSDT/FACS isn't in RSDT, add them to ASL test list manually */
|
||||
acpi_fetch_table(data->qts, &table.aml, &table.aml_len,
|
||||
fadt_aml + 36 /* FIRMWARE_CTRL */, "FACS", false);
|
||||
g_array_append_val(data->tables, table);
|
||||
memcpy(&val, fadt_aml + 112 /* Flags */, 4);
|
||||
val = le32_to_cpu(val);
|
||||
if (!(val & 1UL << 20 /* HW_REDUCED_ACPI */)) {
|
||||
acpi_fetch_table(data->qts, &table.aml, &table.aml_len,
|
||||
fadt_aml + 36 /* FIRMWARE_CTRL */, 4, "FACS", false);
|
||||
g_array_append_val(data->tables, table);
|
||||
}
|
||||
|
||||
memcpy(&val, fadt_aml + dsdt_offset, 4);
|
||||
val = le32_to_cpu(val);
|
||||
if (!val) {
|
||||
dsdt_offset = 140 /* X_DSDT */;
|
||||
dsdt_entry_size = 8;
|
||||
}
|
||||
acpi_fetch_table(data->qts, &table.aml, &table.aml_len,
|
||||
fadt_aml + 40 /* DSDT */, "DSDT", true);
|
||||
fadt_aml + dsdt_offset, dsdt_entry_size, "DSDT", true);
|
||||
g_array_append_val(data->tables, table);
|
||||
|
||||
memset(fadt_aml + 36, 0, 4); /* sanitize FIRMWARE_CTRL ptr */
|
||||
|
@ -177,11 +195,14 @@ static void dump_aml_files(test_data *data, bool rebuild)
|
|||
sdt->aml, ext);
|
||||
fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT,
|
||||
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
|
||||
if (fd < 0) {
|
||||
perror(aml_file);
|
||||
}
|
||||
g_assert(fd >= 0);
|
||||
} else {
|
||||
fd = g_file_open_tmp("aml-XXXXXX", &sdt->aml_file, &error);
|
||||
g_assert_no_error(error);
|
||||
}
|
||||
g_assert(fd >= 0);
|
||||
|
||||
ret = qemu_write_full(fd, sdt->aml, sdt->aml_len);
|
||||
g_assert(ret == sdt->aml_len);
|
||||
|
@ -505,23 +526,44 @@ static void test_smbios_structs(test_data *data)
|
|||
static void test_acpi_one(const char *params, test_data *data)
|
||||
{
|
||||
char *args;
|
||||
bool use_uefi = data->uefi_fl1 && data->uefi_fl2;
|
||||
|
||||
/* Disable kernel irqchip to be able to override apic irq0. */
|
||||
args = g_strdup_printf("-machine %s,accel=%s,kernel-irqchip=off "
|
||||
"-net none -display none %s "
|
||||
"-drive id=hd0,if=none,file=%s,format=raw "
|
||||
"-device ide-hd,drive=hd0 ",
|
||||
data->machine, "kvm:tcg",
|
||||
params ? params : "", disk);
|
||||
if (use_uefi) {
|
||||
/*
|
||||
* TODO: convert '-drive if=pflash' to new syntax (see e33763be7cd3)
|
||||
* when arm/virt boad starts to support it.
|
||||
*/
|
||||
args = g_strdup_printf("-machine %s,accel=%s -nodefaults -nographic "
|
||||
"-drive if=pflash,format=raw,file=%s,readonly "
|
||||
"-drive if=pflash,format=raw,file=%s,snapshot=on -cdrom %s %s",
|
||||
data->machine, data->accel ? data->accel : "kvm:tcg",
|
||||
data->uefi_fl1, data->uefi_fl2, data->cd, params ? params : "");
|
||||
|
||||
} else {
|
||||
/* Disable kernel irqchip to be able to override apic irq0. */
|
||||
args = g_strdup_printf("-machine %s,accel=%s,kernel-irqchip=off "
|
||||
"-net none -display none %s "
|
||||
"-drive id=hd0,if=none,file=%s,format=raw "
|
||||
"-device ide-hd,drive=hd0 ",
|
||||
data->machine, data->accel ? data->accel : "kvm:tcg",
|
||||
params ? params : "", disk);
|
||||
}
|
||||
|
||||
data->qts = qtest_init(args);
|
||||
|
||||
boot_sector_test(data->qts);
|
||||
if (use_uefi) {
|
||||
g_assert(data->scan_len);
|
||||
data->rsdp_addr = acpi_find_rsdp_address_uefi(data->qts,
|
||||
data->ram_start, data->scan_len);
|
||||
} else {
|
||||
boot_sector_test(data->qts);
|
||||
data->rsdp_addr = acpi_find_rsdp_address(data->qts);
|
||||
g_assert_cmphex(data->rsdp_addr, <, 0x100000);
|
||||
}
|
||||
|
||||
data->tables = g_array_new(false, true, sizeof(AcpiSdtTable));
|
||||
test_acpi_rsdp_address(data);
|
||||
test_acpi_rsdp_table(data);
|
||||
test_acpi_rsdt_table(data);
|
||||
test_acpi_rxsdt_table(data);
|
||||
test_acpi_fadt_table(data);
|
||||
|
||||
if (iasl) {
|
||||
|
@ -532,8 +574,15 @@ static void test_acpi_one(const char *params, test_data *data)
|
|||
}
|
||||
}
|
||||
|
||||
test_smbios_entry_point(data);
|
||||
test_smbios_structs(data);
|
||||
/*
|
||||
* TODO: make SMBIOS tests work with UEFI firmware,
|
||||
* Bug on uefi-test-tools to provide entry point:
|
||||
* https://bugs.launchpad.net/qemu/+bug/1821884
|
||||
*/
|
||||
if (!use_uefi) {
|
||||
test_smbios_entry_point(data);
|
||||
test_smbios_structs(data);
|
||||
}
|
||||
|
||||
assert(!global_qtest);
|
||||
qtest_quit(data->qts);
|
||||
|
@ -769,13 +818,14 @@ int main(int argc, char *argv[])
|
|||
const char *arch = qtest_get_arch();
|
||||
int ret;
|
||||
|
||||
ret = boot_sector_init(disk);
|
||||
if(ret)
|
||||
return ret;
|
||||
|
||||
g_test_init(&argc, &argv, NULL);
|
||||
|
||||
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
|
||||
ret = boot_sector_init(disk);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
qtest_add_func("acpi/piix4", test_acpi_piix4_tcg);
|
||||
qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge);
|
||||
qtest_add_func("acpi/q35", test_acpi_q35_tcg);
|
||||
|
|
|
@ -7,21 +7,12 @@
|
|||
#
|
||||
# Authors:
|
||||
# Marcel Apfelbaum <marcel.a@redhat.com>
|
||||
# Igor Mammedov <imammedo@redhat.com>
|
||||
#
|
||||
# This work is licensed under the terms of the GNU GPLv2.
|
||||
# See the COPYING.LIB file in the top-level directory.
|
||||
|
||||
qemu=
|
||||
|
||||
if [ -e x86_64-softmmu/qemu-system-x86_64 ]; then
|
||||
qemu="x86_64-softmmu/qemu-system-x86_64"
|
||||
elif [ -e i386-softmmu/qemu-system-i386 ]; then
|
||||
qemu="i386-softmmu/qemu-system-i386"
|
||||
else
|
||||
echo "Run 'make' to build the qemu exectutable!"
|
||||
echo "Run this script from the build directory."
|
||||
exit 1;
|
||||
fi
|
||||
qemu_bins="x86_64-softmmu/qemu-system-x86_64"
|
||||
|
||||
if [ ! -e "tests/bios-tables-test" ]; then
|
||||
echo "Test: bios-tables-test is required! Run make check before this script."
|
||||
|
@ -29,6 +20,14 @@ if [ ! -e "tests/bios-tables-test" ]; then
|
|||
exit 1;
|
||||
fi
|
||||
|
||||
TEST_ACPI_REBUILD_AML=y QTEST_QEMU_BINARY=$qemu tests/bios-tables-test
|
||||
for qemu in $qemu_bins; do
|
||||
if [ ! -e $qemu ]; then
|
||||
echo "Run 'make' to build the following QEMU executables: $qemu_bins"
|
||||
echo "Also, run this script from the build directory."
|
||||
exit 1;
|
||||
fi
|
||||
TEST_ACPI_REBUILD_AML=y QTEST_QEMU_BINARY=$qemu tests/bios-tables-test
|
||||
done
|
||||
|
||||
|
||||
echo "The files were rebuilt and can be added to git."
|
||||
|
|
|
@ -40,14 +40,14 @@ static uint32_t acpi_find_vgia(QTestState *qts)
|
|||
g_assert_cmphex(rsdp_offset, <, RSDP_ADDR_INVALID);
|
||||
|
||||
|
||||
acpi_parse_rsdp_table(qts, rsdp_offset, rsdp_table);
|
||||
acpi_fetch_rsdp_table(qts, rsdp_offset, rsdp_table);
|
||||
acpi_fetch_table(qts, &rsdt, &rsdt_len, &rsdp_table[16 /* RsdtAddress */],
|
||||
"RSDT", true);
|
||||
4, "RSDT", true);
|
||||
|
||||
ACPI_FOREACH_RSDT_ENTRY(rsdt, rsdt_len, ent, 4 /* Entry size */) {
|
||||
uint8_t *table_aml;
|
||||
|
||||
acpi_fetch_table(qts, &table_aml, &table_length, ent, NULL, true);
|
||||
acpi_fetch_table(qts, &table_aml, &table_length, ent, 4, NULL, true);
|
||||
if (!memcmp(table_aml + 16 /* OEM Table ID */, "VMGENID", 7)) {
|
||||
uint32_t vgia_val;
|
||||
uint8_t *aml = &table_aml[36 /* AML byte-code start */];
|
||||
|
|
Loading…
Reference in New Issue