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

pc,pci,virtio: fixes, cleanups

Lots of fixes, cleanups.
CPU hot-unplug improvements.
A new AER property for virtio devices, adding a dummy AER capability.

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

# gpg: Signature made Wed 09 Dec 2020 18:04:28 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: (65 commits)
  hw/virtio-pci Added AER capability.
  hw/virtio-pci Added counter for pcie capabilities offsets.
  pcie_aer: Fix help message of pcie_aer_inject_error command
  x86: ich9: let firmware negotiate 'CPU hot-unplug with SMI' feature
  x86: ich9: factor out "guest_cpu_hotplug_features"
  tests/acpi: update expected files
  x86: acpi: let the firmware handle pending "CPU remove" events in SMM
  tests/acpi: allow expected files change
  x86: acpi: introduce AcpiPmInfo::smi_on_cpu_unplug
  acpi: cpuhp: introduce 'firmware performs eject' status/control bits
  hw/i386/pc: add max combined fw size as machine configuration option
  block/export: avoid g_return_val_if() input validation
  contrib/vhost-user-input: avoid g_return_val_if() input validation
  contrib/vhost-user-gpu: avoid g_return_val_if() input validation
  contrib/vhost-user-blk: avoid g_return_val_if() input validation
  .gitlab-ci: add build-libvhost-user
  libvhost-user: add a simple link test without glib
  libvhost-user: make it a meson subproject
  libvhost-user: drop qemu/osdep.h dependency
  libvhost-user: remove qemu/compiler.h usage
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2020-12-09 20:08:54 +00:00
90 changed files with 1296 additions and 858 deletions
+11
View File
@@ -535,6 +535,17 @@ check-dco:
variables:
GIT_DEPTH: 1000
build-libvhost-user:
stage: build
image: $CI_REGISTRY_IMAGE/qemu/fedora:latest
before_script:
- dnf install -y meson ninja-build
script:
- mkdir subprojects/libvhost-user/build
- cd subprojects/libvhost-user/build
- meson
- ninja
pages:
image: $CI_REGISTRY_IMAGE/qemu/ubuntu2004:latest
stage: test
+4 -2
View File
@@ -11,7 +11,7 @@
*/
#include "qemu/osdep.h"
#include "block/block.h"
#include "contrib/libvhost-user/libvhost-user.h"
#include "subprojects/libvhost-user/libvhost-user.h" /* only for the type definitions */
#include "standard-headers/linux/virtio_blk.h"
#include "qemu/vhost-user-server.h"
#include "vhost-user-blk-server.h"
@@ -267,7 +267,9 @@ vu_blk_get_config(VuDev *vu_dev, uint8_t *config, uint32_t len)
VuServer *server = container_of(vu_dev, VuServer, vu_dev);
VuBlkExport *vexp = container_of(server, VuBlkExport, vu_server);
g_return_val_if_fail(len <= sizeof(struct virtio_blk_config), -1);
if (len > sizeof(struct virtio_blk_config)) {
return -1;
}
memcpy(config, &vexp->blkcfg, len);
return 0;
-4
View File
@@ -1,4 +0,0 @@
libvhost_user = static_library('vhost-user',
files('libvhost-user.c', 'libvhost-user-glib.c'),
build_by_default: false)
vhost_user = declare_dependency(link_with: libvhost_user)
+1 -2
View File
@@ -1,6 +1,5 @@
# FIXME: broken on 32-bit architectures
executable('vhost-user-blk', files('vhost-user-blk.c'),
link_with: libvhost_user,
dependencies: qemuutil,
dependencies: [qemuutil, vhost_user],
build_by_default: false,
install: false)
+4 -3
View File
@@ -17,8 +17,7 @@
#include "qemu/osdep.h"
#include "standard-headers/linux/virtio_blk.h"
#include "contrib/libvhost-user/libvhost-user-glib.h"
#include "contrib/libvhost-user/libvhost-user.h"
#include "libvhost-user-glib.h"
#if defined(__linux__)
#include <linux/fs.h>
@@ -404,7 +403,9 @@ vub_get_config(VuDev *vu_dev, uint8_t *config, uint32_t len)
VugDev *gdev;
VubDev *vdev_blk;
g_return_val_if_fail(len <= sizeof(struct virtio_blk_config), -1);
if (len > sizeof(struct virtio_blk_config)) {
return -1;
}
gdev = container_of(vu_dev, VugDev, parent);
vdev_blk = container_of(gdev, VubDev, parent);
+1 -2
View File
@@ -2,8 +2,7 @@ if 'CONFIG_TOOLS' in config_host and 'CONFIG_VIRGL' in config_host \
and 'CONFIG_GBM' in config_host and 'CONFIG_LINUX' in config_host \
and pixman.found()
executable('vhost-user-gpu', files('vhost-user-gpu.c', 'virgl.c', 'vugbm.c'),
link_with: libvhost_user,
dependencies: [qemuutil, pixman, gbm, virgl],
dependencies: [qemuutil, pixman, gbm, virgl, vhost_user],
install: true,
install_dir: get_option('libexecdir'))
+3 -1
View File
@@ -1044,7 +1044,9 @@ vg_get_config(VuDev *dev, uint8_t *config, uint32_t len)
{
VuGpu *g = container_of(dev, VuGpu, dev.parent);
g_return_val_if_fail(len <= sizeof(struct virtio_gpu_config), -1);
if (len > sizeof(struct virtio_gpu_config)) {
return -1;
}
if (opt_virgl) {
g->virtio_config.num_capsets = vg_virgl_get_num_capsets();
+1 -1
View File
@@ -17,7 +17,7 @@
#include "qemu/osdep.h"
#include "contrib/libvhost-user/libvhost-user-glib.h"
#include "libvhost-user-glib.h"
#include "standard-headers/linux/virtio_gpu.h"
#include "qemu/queue.h"
+4 -3
View File
@@ -12,8 +12,7 @@
#include "qemu/iov.h"
#include "qemu/bswap.h"
#include "qemu/sockets.h"
#include "contrib/libvhost-user/libvhost-user.h"
#include "contrib/libvhost-user/libvhost-user-glib.h"
#include "libvhost-user-glib.h"
#include "standard-headers/linux/virtio_input.h"
#include "qapi/error.h"
@@ -212,7 +211,9 @@ static int vi_get_config(VuDev *dev, uint8_t *config, uint32_t len)
{
VuInput *vi = container_of(dev, VuInput, dev.parent);
g_return_val_if_fail(len <= sizeof(*vi->sel_config), -1);
if (len > sizeof(*vi->sel_config)) {
return -1;
}
if (vi->sel_config) {
memcpy(config, vi->sel_config, len);
+1 -2
View File
@@ -1,5 +1,4 @@
executable('vhost-user-input', files('main.c'),
link_with: libvhost_user,
dependencies: qemuutil,
dependencies: [qemuutil, vhost_user],
build_by_default: targetos == 'linux',
install: false)
+1 -2
View File
@@ -1,7 +1,6 @@
if 'CONFIG_LIBISCSI' in config_host
executable('vhost-user-scsi', files('vhost-user-scsi.c'),
link_with: libvhost_user,
dependencies: [qemuutil, libiscsi],
dependencies: [qemuutil, libiscsi, vhost_user],
build_by_default: targetos == 'linux',
install: false)
endif
+3 -2
View File
@@ -15,7 +15,7 @@
#define inline __attribute__((gnu_inline)) /* required for libiscsi v1.9.0 */
#include <iscsi/scsi-lowlevel.h>
#undef inline
#include "contrib/libvhost-user/libvhost-user-glib.h"
#include "libvhost-user-glib.h"
#include "standard-headers/linux/virtio_scsi.h"
@@ -232,6 +232,7 @@ static void vus_proc_req(VuDev *vu_dev, int idx)
VugDev *gdev;
VusDev *vdev_scsi;
VuVirtq *vq;
VuVirtqElement *elem = NULL;
assert(vu_dev);
@@ -248,7 +249,6 @@ static void vus_proc_req(VuDev *vu_dev, int idx)
g_debug("Got kicked on vq[%d]@%p", idx, vq);
while (1) {
VuVirtqElement *elem;
VirtIOSCSICmdReq *req;
VirtIOSCSICmdResp *rsp;
@@ -288,6 +288,7 @@ static void vus_proc_req(VuDev *vu_dev, int idx)
free(elem);
}
free(elem);
}
static void vus_queue_set_started(VuDev *vu_dev, int idx, bool started)
+14 -5
View File
@@ -56,8 +56,11 @@ read access:
no device check event to OSPM was issued.
It's valid only when bit 0 is set.
2: Device remove event, used to distinguish device for which
no device eject request to OSPM was issued.
3-7: reserved and should be ignored by OSPM
no device eject request to OSPM was issued. Firmware must
ignore this bit.
3: reserved and should be ignored by OSPM
4: if set to 1, OSPM requests firmware to perform device eject.
5-7: reserved and should be ignored by OSPM
[0x5-0x7] reserved
[0x8] Command data: (DWORD access)
contains 0 unless value last stored in 'Command field' is one of:
@@ -79,10 +82,16 @@ write access:
selected CPU device
2: if set to 1 clears device remove event, set by OSPM
after it has emitted device eject request for the
selected CPU device
selected CPU device.
3: if set to 1 initiates device eject, set by OSPM when it
triggers CPU device removal and calls _EJ0 method
4-7: reserved, OSPM must clear them before writing to register
triggers CPU device removal and calls _EJ0 method or by firmware
when bit #4 is set. In case bit #4 were set, it's cleared as
part of device eject.
4: if set to 1, OSPM hands over device eject to firmware.
Firmware shall issue device eject request as described above
(bit #3) and OSPM should not touch device eject bit (#3) in case
it's asked firmware to perform CPU device eject.
5-7: reserved, OSPM must clear them before writing to register
[0x5] Command field: (1 byte access)
value:
0: selects a CPU device with inserting/removing events and
+2 -2
View File
@@ -1302,8 +1302,8 @@ ERST
" -c for correctable error\n\t\t\t"
"<id> = qdev device id\n\t\t\t"
"<error_status> = error string or 32bit\n\t\t\t"
"<tlb header> = 32bit x 4\n\t\t\t"
"<tlb header prefix> = 32bit x 4",
"<tlp header> = 32bit x 4\n\t\t\t"
"<tlp header prefix> = 32bit x 4",
.cmd = hmp_pcie_aer_inject_error,
},
+285
View File
@@ -27,6 +27,9 @@
#include "sysemu/numa.h"
#include "hw/boards.h"
#include "hw/acpi/tpm.h"
#include "hw/pci/pci_host.h"
#include "hw/pci/pci_bus.h"
#include "hw/pci/pci_bridge.h"
static GArray *build_alloc_array(void)
{
@@ -55,6 +58,128 @@ static void build_append_array(GArray *array, GArray *val)
#define ACPI_NAMESEG_LEN 4
void crs_range_insert(GPtrArray *ranges, uint64_t base, uint64_t limit)
{
CrsRangeEntry *entry;
entry = g_malloc(sizeof(*entry));
entry->base = base;
entry->limit = limit;
g_ptr_array_add(ranges, entry);
}
static void crs_range_free(gpointer data)
{
CrsRangeEntry *entry = (CrsRangeEntry *)data;
g_free(entry);
}
void crs_range_set_init(CrsRangeSet *range_set)
{
range_set->io_ranges = g_ptr_array_new_with_free_func(crs_range_free);
range_set->mem_ranges = g_ptr_array_new_with_free_func(crs_range_free);
range_set->mem_64bit_ranges =
g_ptr_array_new_with_free_func(crs_range_free);
}
void crs_range_set_free(CrsRangeSet *range_set)
{
g_ptr_array_free(range_set->io_ranges, true);
g_ptr_array_free(range_set->mem_ranges, true);
g_ptr_array_free(range_set->mem_64bit_ranges, true);
}
static gint crs_range_compare(gconstpointer a, gconstpointer b)
{
CrsRangeEntry *entry_a = *(CrsRangeEntry **)a;
CrsRangeEntry *entry_b = *(CrsRangeEntry **)b;
if (entry_a->base < entry_b->base) {
return -1;
} else if (entry_a->base > entry_b->base) {
return 1;
} else {
return 0;
}
}
/*
* crs_replace_with_free_ranges - given the 'used' ranges within [start - end]
* interval, computes the 'free' ranges from the same interval.
* Example: If the input array is { [a1 - a2],[b1 - b2] }, the function
* will return { [base - a1], [a2 - b1], [b2 - limit] }.
*/
void crs_replace_with_free_ranges(GPtrArray *ranges,
uint64_t start, uint64_t end)
{
GPtrArray *free_ranges = g_ptr_array_new();
uint64_t free_base = start;
int i;
g_ptr_array_sort(ranges, crs_range_compare);
for (i = 0; i < ranges->len; i++) {
CrsRangeEntry *used = g_ptr_array_index(ranges, i);
if (free_base < used->base) {
crs_range_insert(free_ranges, free_base, used->base - 1);
}
free_base = used->limit + 1;
}
if (free_base < end) {
crs_range_insert(free_ranges, free_base, end);
}
g_ptr_array_set_size(ranges, 0);
for (i = 0; i < free_ranges->len; i++) {
g_ptr_array_add(ranges, g_ptr_array_index(free_ranges, i));
}
g_ptr_array_free(free_ranges, true);
}
/*
* crs_range_merge - merges adjacent ranges in the given array.
* Array elements are deleted and replaced with the merged ranges.
*/
static void crs_range_merge(GPtrArray *range)
{
GPtrArray *tmp = g_ptr_array_new_with_free_func(crs_range_free);
CrsRangeEntry *entry;
uint64_t range_base, range_limit;
int i;
if (!range->len) {
return;
}
g_ptr_array_sort(range, crs_range_compare);
entry = g_ptr_array_index(range, 0);
range_base = entry->base;
range_limit = entry->limit;
for (i = 1; i < range->len; i++) {
entry = g_ptr_array_index(range, i);
if (entry->base - 1 == range_limit) {
range_limit = entry->limit;
} else {
crs_range_insert(tmp, range_base, range_limit);
range_base = entry->base;
range_limit = entry->limit;
}
}
crs_range_insert(tmp, range_base, range_limit);
g_ptr_array_set_size(range, 0);
for (i = 0; i < tmp->len; i++) {
entry = g_ptr_array_index(tmp, i);
crs_range_insert(range, entry->base, entry->limit);
}
g_ptr_array_free(tmp, true);
}
static void
build_append_nameseg(GArray *array, const char *seg)
{
@@ -1951,6 +2076,166 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
tpm2_ptr, "TPM2", table_data->len - tpm2_start, 4, NULL, NULL);
}
Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)
{
Aml *crs = aml_resource_template();
CrsRangeSet temp_range_set;
CrsRangeEntry *entry;
uint8_t max_bus = pci_bus_num(host->bus);
uint8_t type;
int devfn;
int i;
crs_range_set_init(&temp_range_set);
for (devfn = 0; devfn < ARRAY_SIZE(host->bus->devices); devfn++) {
uint64_t range_base, range_limit;
PCIDevice *dev = host->bus->devices[devfn];
if (!dev) {
continue;
}
for (i = 0; i < PCI_NUM_REGIONS; i++) {
PCIIORegion *r = &dev->io_regions[i];
range_base = r->addr;
range_limit = r->addr + r->size - 1;
/*
* Work-around for old bioses
* that do not support multiple root buses
*/
if (!range_base || range_base > range_limit) {
continue;
}
if (r->type & PCI_BASE_ADDRESS_SPACE_IO) {
crs_range_insert(temp_range_set.io_ranges,
range_base, range_limit);
} else { /* "memory" */
uint64_t length = range_limit - range_base + 1;
if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
crs_range_insert(temp_range_set.mem_ranges, range_base,
range_limit);
} else {
crs_range_insert(temp_range_set.mem_64bit_ranges,
range_base, range_limit);
}
}
}
type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION;
if (type == PCI_HEADER_TYPE_BRIDGE) {
uint8_t subordinate = dev->config[PCI_SUBORDINATE_BUS];
if (subordinate > max_bus) {
max_bus = subordinate;
}
range_base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO);
range_limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO);
/*
* Work-around for old bioses
* that do not support multiple root buses
*/
if (range_base && range_base <= range_limit) {
crs_range_insert(temp_range_set.io_ranges,
range_base, range_limit);
}
range_base =
pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
range_limit =
pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY);
/*
* Work-around for old bioses
* that do not support multiple root buses
*/
if (range_base && range_base <= range_limit) {
uint64_t length = range_limit - range_base + 1;
if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
crs_range_insert(temp_range_set.mem_ranges,
range_base, range_limit);
} else {
crs_range_insert(temp_range_set.mem_64bit_ranges,
range_base, range_limit);
}
}
range_base =
pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
range_limit =
pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
/*
* Work-around for old bioses
* that do not support multiple root buses
*/
if (range_base && range_base <= range_limit) {
uint64_t length = range_limit - range_base + 1;
if (range_limit <= UINT32_MAX && length <= UINT32_MAX) {
crs_range_insert(temp_range_set.mem_ranges,
range_base, range_limit);
} else {
crs_range_insert(temp_range_set.mem_64bit_ranges,
range_base, range_limit);
}
}
}
}
crs_range_merge(temp_range_set.io_ranges);
for (i = 0; i < temp_range_set.io_ranges->len; i++) {
entry = g_ptr_array_index(temp_range_set.io_ranges, i);
aml_append(crs,
aml_word_io(AML_MIN_FIXED, AML_MAX_FIXED,
AML_POS_DECODE, AML_ENTIRE_RANGE,
0, entry->base, entry->limit, 0,
entry->limit - entry->base + 1));
crs_range_insert(range_set->io_ranges, entry->base, entry->limit);
}
crs_range_merge(temp_range_set.mem_ranges);
for (i = 0; i < temp_range_set.mem_ranges->len; i++) {
entry = g_ptr_array_index(temp_range_set.mem_ranges, i);
assert(entry->limit <= UINT32_MAX &&
(entry->limit - entry->base + 1) <= UINT32_MAX);
aml_append(crs,
aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
AML_MAX_FIXED, AML_NON_CACHEABLE,
AML_READ_WRITE,
0, entry->base, entry->limit, 0,
entry->limit - entry->base + 1));
crs_range_insert(range_set->mem_ranges, entry->base, entry->limit);
}
crs_range_merge(temp_range_set.mem_64bit_ranges);
for (i = 0; i < temp_range_set.mem_64bit_ranges->len; i++) {
entry = g_ptr_array_index(temp_range_set.mem_64bit_ranges, i);
aml_append(crs,
aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
AML_MAX_FIXED, AML_NON_CACHEABLE,
AML_READ_WRITE,
0, entry->base, entry->limit, 0,
entry->limit - entry->base + 1));
crs_range_insert(range_set->mem_64bit_ranges,
entry->base, entry->limit);
}
crs_range_set_free(&temp_range_set);
aml_append(crs,
aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
0,
pci_bus_num(host->bus),
max_bus,
0,
max_bus - pci_bus_num(host->bus) + 1));
return crs;
}
/* ACPI 5.0: 6.4.3.8.2 Serial Bus Connection Descriptors */
static Aml *aml_serial_bus_device(uint8_t serial_bus_type, uint8_t flags,
uint16_t type_flags,
+23 -3
View File
@@ -71,6 +71,7 @@ static uint64_t cpu_hotplug_rd(void *opaque, hwaddr addr, unsigned size)
val |= cdev->cpu ? 1 : 0;
val |= cdev->is_inserting ? 2 : 0;
val |= cdev->is_removing ? 4 : 0;
val |= cdev->fw_remove ? 16 : 0;
trace_cpuhp_acpi_read_flags(cpu_st->selector, val);
break;
case ACPI_CPU_CMD_DATA_OFFSET_RW:
@@ -148,6 +149,14 @@ static void cpu_hotplug_wr(void *opaque, hwaddr addr, uint64_t data,
hotplug_ctrl = qdev_get_hotplug_handler(dev);
hotplug_handler_unplug(hotplug_ctrl, dev, NULL);
object_unparent(OBJECT(dev));
cdev->fw_remove = false;
} else if (data & 16) {
if (!cdev->cpu || cdev->cpu == first_cpu) {
trace_cpuhp_acpi_fw_remove_invalid_cpu(cpu_st->selector);
break;
}
trace_cpuhp_acpi_fw_remove_cpu(cpu_st->selector);
cdev->fw_remove = true;
}
break;
case ACPI_CPU_CMD_OFFSET_WR:
@@ -159,7 +168,8 @@ static void cpu_hotplug_wr(void *opaque, hwaddr addr, uint64_t data,
do {
cdev = &cpu_st->devs[iter];
if (cdev->is_inserting || cdev->is_removing) {
if (cdev->is_inserting || cdev->is_removing ||
cdev->fw_remove) {
cpu_st->selector = iter;
trace_cpuhp_acpi_cpu_has_events(cpu_st->selector,
cdev->is_inserting, cdev->is_removing);
@@ -332,6 +342,7 @@ const VMStateDescription vmstate_cpu_hotplug = {
#define CPU_INSERT_EVENT "CINS"
#define CPU_REMOVE_EVENT "CRMV"
#define CPU_EJECT_EVENT "CEJ0"
#define CPU_FW_EJECT_EVENT "CEJF"
void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
hwaddr io_base,
@@ -384,7 +395,9 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
aml_append(field, aml_named_field(CPU_REMOVE_EVENT, 1));
/* initiates device eject, write only */
aml_append(field, aml_named_field(CPU_EJECT_EVENT, 1));
aml_append(field, aml_reserved_field(4));
/* tell firmware to do device eject, write only */
aml_append(field, aml_named_field(CPU_FW_EJECT_EVENT, 1));
aml_append(field, aml_reserved_field(3));
aml_append(field, aml_named_field(CPU_COMMAND, 8));
aml_append(cpu_ctrl_dev, field);
@@ -419,6 +432,7 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
Aml *ins_evt = aml_name("%s.%s", cphp_res_path, CPU_INSERT_EVENT);
Aml *rm_evt = aml_name("%s.%s", cphp_res_path, CPU_REMOVE_EVENT);
Aml *ej_evt = aml_name("%s.%s", cphp_res_path, CPU_EJECT_EVENT);
Aml *fw_ej_evt = aml_name("%s.%s", cphp_res_path, CPU_FW_EJECT_EVENT);
aml_append(cpus_dev, aml_name_decl("_HID", aml_string("ACPI0010")));
aml_append(cpus_dev, aml_name_decl("_CID", aml_eisaid("PNP0A05")));
@@ -461,7 +475,13 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
aml_append(method, aml_store(idx, cpu_selector));
aml_append(method, aml_store(one, ej_evt));
if (opts.fw_unplugs_cpu) {
aml_append(method, aml_store(one, fw_ej_evt));
aml_append(method, aml_store(aml_int(OVMF_CPUHP_SMI_CMD),
aml_name("%s", opts.smi_path)));
} else {
aml_append(method, aml_store(one, ej_evt));
}
aml_append(method, aml_release(ctrl_lock));
}
aml_append(cpus_dev, method);
+2
View File
@@ -29,6 +29,8 @@ cpuhp_acpi_clear_inserting_evt(uint32_t idx) "idx[0x%"PRIx32"]"
cpuhp_acpi_clear_remove_evt(uint32_t idx) "idx[0x%"PRIx32"]"
cpuhp_acpi_ejecting_invalid_cpu(uint32_t idx) "0x%"PRIx32
cpuhp_acpi_ejecting_cpu(uint32_t idx) "0x%"PRIx32
cpuhp_acpi_fw_remove_invalid_cpu(uint32_t idx) "0x%"PRIx32
cpuhp_acpi_fw_remove_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
+7 -6
View File
@@ -465,14 +465,15 @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid)
/* Unmap the whole notifier's range */
static void smmu_unmap_notifier_range(IOMMUNotifier *n)
{
IOMMUTLBEntry entry;
IOMMUTLBEvent event;
entry.target_as = &address_space_memory;
entry.iova = n->start;
entry.perm = IOMMU_NONE;
entry.addr_mask = n->end - n->start;
event.type = IOMMU_NOTIFIER_UNMAP;
event.entry.target_as = &address_space_memory;
event.entry.iova = n->start;
event.entry.perm = IOMMU_NONE;
event.entry.addr_mask = n->end - n->start;
memory_region_notify_one(n, &entry);
memory_region_notify_iommu_one(n, &event);
}
/* Unmap all notifiers attached to @mr */
+7 -6
View File
@@ -800,7 +800,7 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
uint8_t tg, uint64_t num_pages)
{
SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu);
IOMMUTLBEntry entry;
IOMMUTLBEvent event;
uint8_t granule = tg;
if (!tg) {
@@ -823,12 +823,13 @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
granule = tt->granule_sz;
}
entry.target_as = &address_space_memory;
entry.iova = iova;
entry.addr_mask = num_pages * (1 << granule) - 1;
entry.perm = IOMMU_NONE;
event.type = IOMMU_NOTIFIER_UNMAP;
event.entry.target_as = &address_space_memory;
event.entry.iova = iova;
event.entry.addr_mask = num_pages * (1 << granule) - 1;
event.entry.perm = IOMMU_NONE;
memory_region_notify_one(n, &entry);
memory_region_notify_iommu_one(n, &event);
}
/* invalidate an asid/iova range tuple in all mr's */
+29 -2
View File
@@ -57,6 +57,8 @@
#define ARM_SPI_BASE 32
#define ACPI_BUILD_TABLE_SIZE 0x20000
static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
{
uint16_t i;
@@ -153,7 +155,8 @@ static void acpi_dsdt_add_virtio(Aml *scope,
}
static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
uint32_t irq, bool use_highmem, bool highmem_ecam)
uint32_t irq, bool use_highmem, bool highmem_ecam,
VirtMachineState *vms)
{
int ecam_id = VIRT_ECAM_ID(highmem_ecam);
struct GPEXConfig cfg = {
@@ -161,6 +164,7 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
.pio = memmap[VIRT_PCIE_PIO],
.ecam = memmap[ecam_id],
.irq = irq,
.bus = vms->bus,
};
if (use_highmem) {
@@ -609,7 +613,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO],
(irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS);
acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE),
vms->highmem, vms->highmem_ecam);
vms->highmem, vms->highmem_ecam, vms);
if (vms->acpi_dev) {
build_ged_aml(scope, "\\_SB."GED_DEVICE,
HOTPLUG_HANDLER(vms->acpi_dev),
@@ -654,6 +658,15 @@ struct AcpiBuildState {
bool patched;
} AcpiBuildState;
static void acpi_align_size(GArray *blob, unsigned align)
{
/*
* Align size to multiple of given size. This reduces the chance
* we need to change size in the future (breaking cross version migration).
*/
g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
}
static
void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
{
@@ -741,6 +754,20 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
build_rsdp(tables->rsdp, tables->linker, &rsdp_data);
}
/*
* The align size is 128, warn if 64k is not enough therefore
* the align size could be resized.
*/
if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) {
warn_report("ACPI table size %u exceeds %d bytes,"
" migration may not work",
tables_blob->len, ACPI_BUILD_TABLE_SIZE / 2);
error_printf("Try removing CPUs, NUMA nodes, memory slots"
" or PCI bridges.");
}
acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE);
/* Cleanup memory that's no longer used. */
g_array_free(table_offsets, true);
}

Some files were not shown because too many files have changed in this diff Show More