aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/acpi/Makefile.objs2
-rw-r--r--hw/acpi/acpi_interface.c9
-rw-r--r--hw/acpi/aml-build.c52
-rw-r--r--hw/acpi/bios-linker-loader.c180
-rw-r--r--hw/acpi/core.c2
-rw-r--r--hw/acpi/cpu_hotplug.c246
-rw-r--r--hw/acpi/cpu_hotplug_acpi_table.c136
-rw-r--r--hw/acpi/ich9.c36
-rw-r--r--hw/acpi/memory_hotplug.c12
-rw-r--r--hw/acpi/nvdimm.c22
-rw-r--r--hw/acpi/pcihp.c10
-rw-r--r--hw/acpi/piix4.c23
-rw-r--r--hw/arm/virt-acpi-build.c56
-rw-r--r--hw/i386/acpi-build.c229
-rw-r--r--hw/i386/pc.c5
-rw-r--r--hw/ide/macio.c3
-rw-r--r--hw/ipmi/ipmi.c34
-rw-r--r--hw/ipmi/isa_ipmi_bt.c57
-rw-r--r--hw/ipmi/isa_ipmi_kcs.c56
-rw-r--r--hw/isa/lpc_ich9.c38
-rw-r--r--hw/mem/pc-dimm.c8
-rw-r--r--hw/misc/macio/mac_dbdma.c13
-rw-r--r--hw/ppc/spapr.c36
-rw-r--r--hw/ppc/spapr_iommu.c140
-rw-r--r--hw/ppc/spapr_pci.c28
-rw-r--r--hw/ppc/spapr_vio.c8
-rw-r--r--hw/virtio/vhost.c4
-rw-r--r--include/hw/acpi/acpi.h10
-rw-r--r--include/hw/acpi/acpi_dev_interface.h11
-rw-r--r--include/hw/acpi/aml-build.h9
-rw-r--r--include/hw/acpi/bios-linker-loader.h28
-rw-r--r--include/hw/acpi/cpu_hotplug.h19
-rw-r--r--include/hw/acpi/ich9.h9
-rw-r--r--include/hw/acpi/memory_hotplug.h4
-rw-r--r--include/hw/acpi/pcihp.h5
-rw-r--r--include/hw/ipmi/ipmi.h74
-rw-r--r--include/hw/mem/nvdimm.h3
-rw-r--r--include/hw/mem/pc-dimm.h6
-rw-r--r--include/hw/pci-host/spapr.h2
-rw-r--r--include/hw/ppc/spapr.h14
-rw-r--r--include/hw/virtio/virtio-access.h6
-rw-r--r--include/migration/vmstate.h10
-rw-r--r--include/sysemu/kvm.h1
-rw-r--r--kvm-all.c7
-rw-r--r--target-arm/cpu.h2
-rw-r--r--target-ppc/cpu.h8
-rw-r--r--target-ppc/excp_helper.c8
-rw-r--r--target-ppc/fpu_helper.c2
-rw-r--r--target-ppc/helper.h1
-rw-r--r--target-ppc/helper_regs.h8
-rw-r--r--target-ppc/mmu-hash64.c30
-rw-r--r--target-ppc/mmu_helper.c74
-rw-r--r--target-ppc/translate.c83
-rw-r--r--target-ppc/translate_init.c39
-rw-r--r--tests/acpi-test-data/pc/DSDTbin5587 -> 5503 bytes
-rw-r--r--tests/acpi-test-data/pc/DSDT.bridgebin7446 -> 7362 bytes
-rw-r--r--tests/acpi-test-data/q35/DSDTbin8357 -> 8265 bytes
-rw-r--r--tests/acpi-test-data/q35/DSDT.bridgebin8374 -> 8282 bytes
-rw-r--r--tests/bios-tables-test.c18
-rw-r--r--tests/docker/Makefile.include3
-rw-r--r--trace-events2
61 files changed, 1126 insertions, 815 deletions
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index faee86c5c4..66bd72702b 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -1,6 +1,6 @@
common-obj-$(CONFIG_ACPI_X86) += core.o piix4.o pcihp.o
common-obj-$(CONFIG_ACPI_X86_ICH) += ich9.o tco.o
-common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o cpu_hotplug_acpi_table.o
+common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o
common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o memory_hotplug_acpi_table.o
obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
common-obj-$(CONFIG_ACPI) += acpi_interface.o
diff --git a/hw/acpi/acpi_interface.c b/hw/acpi/acpi_interface.c
index d82131326a..6583917b8e 100644
--- a/hw/acpi/acpi_interface.c
+++ b/hw/acpi/acpi_interface.c
@@ -2,6 +2,15 @@
#include "hw/acpi/acpi_dev_interface.h"
#include "qemu/module.h"
+void acpi_send_event(DeviceState *dev, AcpiEventStatusBits event)
+{
+ AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(dev);
+ if (adevc->send_event) {
+ AcpiDeviceIf *adev = ACPI_DEVICE_IF(dev);
+ adevc->send_event(adev, event);
+ }
+}
+
static void register_types(void)
{
static const TypeInfo acpi_dev_if_info = {
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index cedb74e7cf..123160a94e 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -24,7 +24,6 @@
#include "hw/acpi/aml-build.h"
#include "qemu/bswap.h"
#include "qemu/bitops.h"
-#include "hw/acpi/bios-linker-loader.h"
static GArray *build_alloc_array(void)
{
@@ -406,6 +405,15 @@ Aml *aml_return(Aml *val)
return var;
}
+/* ACPI 1.0b: 16.2.6.3 Debug Objects Encoding: DebugObj */
+Aml *aml_debug(void)
+{
+ Aml *var = aml_alloc();
+ build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
+ build_append_byte(var->buf, 0x31); /* DebugOp */
+ return var;
+}
+
/*
* ACPI 1.0b: 16.2.3 Data Objects Encoding:
* encodes: ByteConst, WordConst, DWordConst, QWordConst, ZeroOp, OneOp
@@ -1407,6 +1415,14 @@ Aml *aml_unicode(const char *str)
return var;
}
+/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefRefOf */
+Aml *aml_refof(Aml *arg)
+{
+ Aml *var = aml_opcode(0x71 /* RefOfOp */);
+ aml_append(var, arg);
+ return var;
+}
+
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefDerefOf */
Aml *aml_derefof(Aml *arg)
{
@@ -1473,10 +1489,12 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target)
}
void
-build_header(GArray *linker, GArray *table_data,
+build_header(BIOSLinker *linker, GArray *table_data,
AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
const char *oem_id, const char *oem_table_id)
{
+ unsigned tbl_offset = (char *)h - table_data->data;
+ unsigned checksum_offset = (char *)&h->checksum - table_data->data;
memcpy(&h->signature, sig, 4);
h->length = cpu_to_le32(len);
h->revision = rev;
@@ -1497,10 +1515,9 @@ build_header(GArray *linker, GArray *table_data,
h->oem_revision = cpu_to_le32(1);
memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
h->asl_compiler_revision = cpu_to_le32(1);
- h->checksum = 0;
/* Checksum to be filled in by Guest linker */
bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
- table_data, h, len, &h->checksum);
+ tbl_offset, len, checksum_offset);
}
void *acpi_data_push(GArray *table_data, unsigned size)
@@ -1518,7 +1535,7 @@ unsigned acpi_data_len(GArray *table)
void acpi_add_table(GArray *table_offsets, GArray *table_data)
{
- uint32_t offset = cpu_to_le32(table_data->len);
+ uint32_t offset = table_data->len;
g_array_append_val(table_offsets, offset);
}
@@ -1532,8 +1549,7 @@ void acpi_build_tables_init(AcpiBuildTables *tables)
void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
{
- void *linker_data = bios_linker_loader_cleanup(tables->linker);
- g_free(linker_data);
+ bios_linker_loader_cleanup(tables->linker);
g_array_free(tables->rsdp, true);
g_array_free(tables->table_data, true);
g_array_free(tables->tcpalog, mfre);
@@ -1541,24 +1557,26 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
/* Build rsdt table */
void
-build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets,
+build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
const char *oem_id, const char *oem_table_id)
{
- AcpiRsdtDescriptorRev1 *rsdt;
- size_t rsdt_len;
int i;
- const int table_data_len = (sizeof(uint32_t) * table_offsets->len);
+ unsigned rsdt_entries_offset;
+ AcpiRsdtDescriptorRev1 *rsdt;
+ const unsigned table_data_len = (sizeof(uint32_t) * table_offsets->len);
+ const unsigned rsdt_entry_size = sizeof(rsdt->table_offset_entry[0]);
+ const size_t rsdt_len = sizeof(*rsdt) + table_data_len;
- rsdt_len = sizeof(*rsdt) + table_data_len;
rsdt = acpi_data_push(table_data, rsdt_len);
- memcpy(rsdt->table_offset_entry, table_offsets->data, table_data_len);
+ rsdt_entries_offset = (char *)rsdt->table_offset_entry - table_data->data;
for (i = 0; i < table_offsets->len; ++i) {
+ uint32_t ref_tbl_offset = g_array_index(table_offsets, uint32_t, i);
+ uint32_t rsdt_entry_offset = rsdt_entries_offset + rsdt_entry_size * i;
+
/* rsdt->table_offset_entry to be filled by Guest linker */
bios_linker_loader_add_pointer(linker,
- ACPI_BUILD_TABLE_FILE,
- ACPI_BUILD_TABLE_FILE,
- table_data, &rsdt->table_offset_entry[i],
- sizeof(uint32_t));
+ ACPI_BUILD_TABLE_FILE, rsdt_entry_offset, rsdt_entry_size,
+ ACPI_BUILD_TABLE_FILE, ref_tbl_offset);
}
build_header(linker, table_data,
(void *)rsdt, "RSDT", rsdt_len, 1, oem_id, oem_table_id);
diff --git a/hw/acpi/bios-linker-loader.c b/hw/acpi/bios-linker-loader.c
index 5153ab151b..d963ebe241 100644
--- a/hw/acpi/bios-linker-loader.c
+++ b/hw/acpi/bios-linker-loader.c
@@ -96,134 +96,170 @@ enum {
};
/*
- * bios_linker_loader_init: allocate a new linker file blob array.
+ * BiosLinkerFileEntry:
+ *
+ * An internal type used for book-keeping file entries
+ */
+typedef struct BiosLinkerFileEntry {
+ char *name; /* file name */
+ GArray *blob; /* data accosiated with @name */
+} BiosLinkerFileEntry;
+
+/*
+ * bios_linker_loader_init: allocate a new linker object instance.
*
* After initialization, linker commands can be added, and will
- * be stored in the array.
+ * be stored in the linker.cmd_blob array.
*/
-GArray *bios_linker_loader_init(void)
+BIOSLinker *bios_linker_loader_init(void)
{
- return g_array_new(false, true /* clear */, 1);
+ BIOSLinker *linker = g_new(BIOSLinker, 1);
+
+ linker->cmd_blob = g_array_new(false, true /* clear */, 1);
+ linker->file_list = g_array_new(false, true /* clear */,
+ sizeof(BiosLinkerFileEntry));
+ return linker;
}
-/* Free linker wrapper and return the linker array. */
-void *bios_linker_loader_cleanup(GArray *linker)
+/* Free linker wrapper */
+void bios_linker_loader_cleanup(BIOSLinker *linker)
{
- return g_array_free(linker, false);
+ int i;
+ BiosLinkerFileEntry *entry;
+
+ g_array_free(linker->cmd_blob, true);
+
+ for (i = 0; i < linker->file_list->len; i++) {
+ entry = &g_array_index(linker->file_list, BiosLinkerFileEntry, i);
+ g_free(entry->name);
+ }
+ g_array_free(linker->file_list, true);
+ g_free(linker);
+}
+
+static const BiosLinkerFileEntry *
+bios_linker_find_file(const BIOSLinker *linker, const char *name)
+{
+ int i;
+ BiosLinkerFileEntry *entry;
+
+ for (i = 0; i < linker->file_list->len; i++) {
+ entry = &g_array_index(linker->file_list, BiosLinkerFileEntry, i);
+ if (!strcmp(entry->name, name)) {
+ return entry;
+ }
+ }
+ return NULL;
}
/*
* bios_linker_loader_alloc: ask guest to load file into guest memory.
*
- * @linker: linker file blob array
- * @file: file to be loaded
+ * @linker: linker object instance
+ * @file_name: name of the file blob to be loaded
+ * @file_blob: pointer to blob corresponding to @file_name
* @alloc_align: required minimal alignment in bytes. Must be a power of 2.
* @alloc_fseg: request allocation in FSEG zone (useful for the RSDP ACPI table)
*
* Note: this command must precede any other linker command using this file.
*/
-void bios_linker_loader_alloc(GArray *linker,
- const char *file,
+void bios_linker_loader_alloc(BIOSLinker *linker,
+ const char *file_name,
+ GArray *file_blob,
uint32_t alloc_align,
bool alloc_fseg)
{
BiosLinkerLoaderEntry entry;
+ BiosLinkerFileEntry file = { g_strdup(file_name), file_blob};
assert(!(alloc_align & (alloc_align - 1)));
+ assert(!bios_linker_find_file(linker, file_name));
+ g_array_append_val(linker->file_list, file);
+
memset(&entry, 0, sizeof entry);
- strncpy(entry.alloc.file, file, sizeof entry.alloc.file - 1);
+ strncpy(entry.alloc.file, file_name, sizeof entry.alloc.file - 1);
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ALLOCATE);
entry.alloc.align = cpu_to_le32(alloc_align);
entry.alloc.zone = alloc_fseg ? BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG :
BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH;
/* Alloc entries must come first, so prepend them */
- g_array_prepend_vals(linker, &entry, sizeof entry);
+ g_array_prepend_vals(linker->cmd_blob, &entry, sizeof entry);
}
/*
- * bios_linker_loader_add_checksum: ask guest to add checksum of file data
- * into (same) file at the specified pointer.
+ * bios_linker_loader_add_checksum: ask guest to add checksum of ACPI
+ * table in the specified file at the specified offset.
*
* Checksum calculation simply sums -X for each byte X in the range
* using 8-bit math (i.e. ACPI checksum).
*
- * @linker: linker file blob array
+ * @linker: linker object instance
* @file: file that includes the checksum to be calculated
* and the data to be checksummed
- * @table: @file blob contents
- * @start, @size: range of data to checksum
- * @checksum: location of the checksum to be patched within file blob
- *
- * Notes:
- * - checksum byte initial value must have been pushed into @table
- * and reside at address @checksum.
- * - @size bytes must have been pushed into @table and reside at address
- * @start.
- * - Guest calculates checksum of specified range of data, result is added to
- * initial value at @checksum into copy of @file in Guest memory.
- * - Range might include the checksum itself.
- * - To avoid confusion, caller must always put 0x0 at @checksum.
- * - @file must be loaded into Guest memory using bios_linker_loader_alloc
+ * @start_offset, @size: range of data in the file to checksum,
+ * relative to the start of file blob
+ * @checksum_offset: location of the checksum to be patched within file blob,
+ * relative to the start of file blob
*/
-void bios_linker_loader_add_checksum(GArray *linker, const char *file,
- GArray *table,
- void *start, unsigned size,
- uint8_t *checksum)
+void bios_linker_loader_add_checksum(BIOSLinker *linker, const char *file_name,
+ unsigned start_offset, unsigned size,
+ unsigned checksum_offset)
{
BiosLinkerLoaderEntry entry;
- ptrdiff_t checksum_offset = (gchar *)checksum - table->data;
- ptrdiff_t start_offset = (gchar *)start - table->data;
+ const BiosLinkerFileEntry *file = bios_linker_find_file(linker, file_name);
- assert(checksum_offset >= 0);
- assert(start_offset >= 0);
- assert(checksum_offset + 1 <= table->len);
- assert(start_offset + size <= table->len);
- assert(*checksum == 0x0);
+ assert(file);
+ assert(start_offset < file->blob->len);
+ assert(start_offset + size <= file->blob->len);
+ assert(checksum_offset >= start_offset);
+ assert(checksum_offset + 1 <= start_offset + size);
+ *(file->blob->data + checksum_offset) = 0;
memset(&entry, 0, sizeof entry);
- strncpy(entry.cksum.file, file, sizeof entry.cksum.file - 1);
+ strncpy(entry.cksum.file, file_name, sizeof entry.cksum.file - 1);
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM);
entry.cksum.offset = cpu_to_le32(checksum_offset);
entry.cksum.start = cpu_to_le32(start_offset);
entry.cksum.length = cpu_to_le32(size);
- g_array_append_vals(linker, &entry, sizeof entry);
+ g_array_append_vals(linker->cmd_blob, &entry, sizeof entry);
}
/*
- * bios_linker_loader_add_pointer: ask guest to add address of source file
- * into destination file at the specified pointer.
+ * bios_linker_loader_add_pointer: ask guest to patch address in
+ * destination file with a pointer to source file
*
- * @linker: linker file blob array
+ * @linker: linker object instance
* @dest_file: destination file that must be changed
+ * @dst_patched_offset: location within destination file blob to be patched
+ * with the pointer to @src_file+@src_offset (i.e. source
+ * blob allocated in guest memory + @src_offset), in bytes
+ * @dst_patched_offset_size: size of the pointer to be patched
+ * at @dst_patched_offset in @dest_file blob, in bytes
* @src_file: source file who's address must be taken
- * @table: @dest_file blob contents array
- * @pointer: location of the pointer to be patched within destination file blob
- * @pointer_size: size of pointer to be patched, in bytes
- *
- * Notes:
- * - @pointer_size bytes must have been pushed into @table
- * and reside at address @pointer.
- * - Guest address is added to initial value at @pointer
- * into copy of @dest_file in Guest memory.
- * e.g. to get start of src_file in guest memory, put 0x0 there
- * to get address of a field at offset 0x10 in src_file, put 0x10 there
- * - Both @dest_file and @src_file must be
- * loaded into Guest memory using bios_linker_loader_alloc
+ * @src_offset: location within source file blob to which
+ * @dest_file+@dst_patched_offset will point to after
+ * firmware's executed ADD_POINTER command
*/
-void bios_linker_loader_add_pointer(GArray *linker,
+void bios_linker_loader_add_pointer(BIOSLinker *linker,
const char *dest_file,
+ uint32_t dst_patched_offset,
+ uint8_t dst_patched_size,
const char *src_file,
- GArray *table, void *pointer,
- uint8_t pointer_size)
+ uint32_t src_offset)
{
+ uint64_t le_src_offset;
BiosLinkerLoaderEntry entry;
- ptrdiff_t offset = (gchar *)pointer - table->data;
+ const BiosLinkerFileEntry *dst_file =
+ bios_linker_find_file(linker, dest_file);
+ const BiosLinkerFileEntry *source_file =
+ bios_linker_find_file(linker, src_file);
- assert(offset >= 0);
- assert(offset + pointer_size <= table->len);
+ assert(dst_patched_offset < dst_file->blob->len);
+ assert(dst_patched_offset + dst_patched_size <= dst_file->blob->len);
+ assert(src_offset < source_file->blob->len);
memset(&entry, 0, sizeof entry);
strncpy(entry.pointer.dest_file, dest_file,
@@ -231,10 +267,14 @@ void bios_linker_loader_add_pointer(GArray *linker,
strncpy(entry.pointer.src_file, src_file,
sizeof entry.pointer.src_file - 1);
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_POINTER);
- entry.pointer.offset = cpu_to_le32(offset);
- entry.pointer.size = pointer_size;
- assert(pointer_size == 1 || pointer_size == 2 ||
- pointer_size == 4 || pointer_size == 8);
+ entry.pointer.offset = cpu_to_le32(dst_patched_offset);
+ entry.pointer.size = dst_patched_size;
+ assert(dst_patched_size == 1 || dst_patched_size == 2 ||
+ dst_patched_size == 4 || dst_patched_size == 8);
+
+ le_src_offset = cpu_to_le64(src_offset);
+ memcpy(dst_file->blob->data + dst_patched_offset,
+ &le_src_offset, dst_patched_size);
- g_array_append_vals(linker, &entry, sizeof entry);
+ g_array_append_vals(linker->cmd_blob, &entry, sizeof entry);
}
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index 1ffd155c11..d24b9a98c8 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -698,7 +698,7 @@ uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr)
}
void acpi_send_gpe_event(ACPIREGS *ar, qemu_irq irq,
- AcpiGPEStatusBits status)
+ AcpiEventStatusBits status)
{
ar->gpe.sts[0] |= status;
acpi_update_sci(ar, irq);
diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c
index 4d86743fde..fe75bd9ac9 100644
--- a/hw/acpi/cpu_hotplug.c
+++ b/hw/acpi/cpu_hotplug.c
@@ -14,6 +14,14 @@
#include "hw/acpi/cpu_hotplug.h"
#include "qapi/error.h"
#include "qom/cpu.h"
+#include "hw/i386/pc.h"
+
+#define CPU_EJECT_METHOD "CPEJ"
+#define CPU_MAT_METHOD "CPMA"
+#define CPU_ON_BITMAP "CPON"
+#define CPU_STATUS_METHOD "CPST"
+#define CPU_STATUS_MAP "PRS"
+#define CPU_SCAN_METHOD "PRSC"
static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
{
@@ -54,19 +62,18 @@ static void acpi_set_cpu_present_bit(AcpiCpuHotplug *g, CPUState *cpu,
g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
}
-void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq,
- AcpiCpuHotplug *g, DeviceState *dev, Error **errp)
+void legacy_acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
+ AcpiCpuHotplug *g, DeviceState *dev, Error **errp)
{
acpi_set_cpu_present_bit(g, CPU(dev), errp);
if (*errp != NULL) {
return;
}
-
- acpi_send_gpe_event(ar, irq, ACPI_CPU_HOTPLUG_STATUS);
+ acpi_send_event(DEVICE(hotplug_dev), ACPI_CPU_HOTPLUG_STATUS);
}
-void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
- AcpiCpuHotplug *gpe_cpu, uint16_t base)
+void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
+ AcpiCpuHotplug *gpe_cpu, uint16_t base)
{
CPUState *cpu;
@@ -77,3 +84,230 @@ void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
gpe_cpu, "acpi-cpu-hotplug", ACPI_GPE_PROC_LEN);
memory_region_add_subregion(parent, base, &gpe_cpu->io);
}
+
+void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
+ uint16_t io_base)
+{
+ Aml *dev;
+ Aml *crs;
+ Aml *pkg;
+ Aml *field;
+ Aml *method;
+ Aml *if_ctx;
+ Aml *else_ctx;
+ int i, apic_idx;
+ Aml *sb_scope = aml_scope("_SB");
+ uint8_t madt_tmpl[8] = {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0};
+ Aml *cpu_id = aml_arg(1);
+ Aml *apic_id = aml_arg(0);
+ Aml *cpu_on = aml_local(0);
+ Aml *madt = aml_local(1);
+ Aml *cpus_map = aml_name(CPU_ON_BITMAP);
+ Aml *zero = aml_int(0);
+ Aml *one = aml_int(1);
+ MachineClass *mc = MACHINE_GET_CLASS(machine);
+ CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
+ PCMachineState *pcms = PC_MACHINE(machine);
+
+ /*
+ * _MAT method - creates an madt apic buffer
+ * apic_id = Arg0 = Local APIC ID
+ * cpu_id = Arg1 = Processor ID
+ * cpu_on = Local0 = CPON flag for this cpu
+ * madt = Local1 = Buffer (in madt apic form) to return
+ */
+ method = aml_method(CPU_MAT_METHOD, 2, AML_NOTSERIALIZED);
+ aml_append(method,
+ aml_store(aml_derefof(aml_index(cpus_map, apic_id)), cpu_on));
+ aml_append(method,
+ aml_store(aml_buffer(sizeof(madt_tmpl), madt_tmpl), madt));
+ /* Update the processor id, lapic id, and enable/disable status */
+ aml_append(method, aml_store(cpu_id, aml_index(madt, aml_int(2))));
+ aml_append(method, aml_store(apic_id, aml_index(madt, aml_int(3))));
+ aml_append(method, aml_store(cpu_on, aml_index(madt, aml_int(4))));
+ aml_append(method, aml_return(madt));
+ aml_append(sb_scope, method);
+
+ /*
+ * _STA method - return ON status of cpu
+ * apic_id = Arg0 = Local APIC ID
+ * cpu_on = Local0 = CPON flag for this cpu
+ */
+ method = aml_method(CPU_STATUS_METHOD, 1, AML_NOTSERIALIZED);
+ aml_append(method,
+ aml_store(aml_derefof(aml_index(cpus_map, apic_id)), cpu_on));
+ if_ctx = aml_if(cpu_on);
+ {
+ aml_append(if_ctx, aml_return(aml_int(0xF)));
+ }
+ aml_append(method, if_ctx);
+ else_ctx = aml_else();
+ {
+ aml_append(else_ctx, aml_return(zero));
+ }
+ aml_append(method, else_ctx);
+ aml_append(sb_scope, method);
+
+ method = aml_method(CPU_EJECT_METHOD, 2, AML_NOTSERIALIZED);
+ aml_append(method, aml_sleep(200));
+ aml_append(sb_scope, method);
+
+ method = aml_method(CPU_SCAN_METHOD, 0, AML_NOTSERIALIZED);
+ {
+ Aml *while_ctx, *if_ctx2, *else_ctx2;
+ Aml *bus_check_evt = aml_int(1);
+ Aml *remove_evt = aml_int(3);
+ Aml *status_map = aml_local(5); /* Local5 = active cpu bitmap */
+ Aml *byte = aml_local(2); /* Local2 = last read byte from bitmap */
+ Aml *idx = aml_local(0); /* Processor ID / APIC ID iterator */
+ Aml *is_cpu_on = aml_local(1); /* Local1 = CPON flag for cpu */
+ Aml *status = aml_local(3); /* Local3 = active state for cpu */
+
+ aml_append(method, aml_store(aml_name(CPU_STATUS_MAP), status_map));
+ aml_append(method, aml_store(zero, byte));
+ aml_append(method, aml_store(zero, idx));
+
+ /* While (idx < SizeOf(CPON)) */
+ while_ctx = aml_while(aml_lless(idx, aml_sizeof(cpus_map)));
+ aml_append(while_ctx,
+ aml_store(aml_derefof(aml_index(cpus_map, idx)), is_cpu_on));
+
+ if_ctx = aml_if(aml_and(idx, aml_int(0x07), NULL));
+ {
+ /* Shift down previously read bitmap byte */
+ aml_append(if_ctx, aml_shiftright(byte, one, byte));
+ }
+ aml_append(while_ctx, if_ctx);
+
+ else_ctx = aml_else();
+ {
+ /* Read next byte from cpu bitmap */
+ aml_append(else_ctx, aml_store(aml_derefof(aml_index(status_map,
+ aml_shiftright(idx, aml_int(3), NULL))), byte));
+ }
+ aml_append(while_ctx, else_ctx);
+
+ aml_append(while_ctx, aml_store(aml_and(byte, one, NULL), status));
+ if_ctx = aml_if(aml_lnot(aml_equal(is_cpu_on, status)));
+ {
+ /* State change - update CPON with new state */
+ aml_append(if_ctx, aml_store(status, aml_index(cpus_map, idx)));
+ if_ctx2 = aml_if(aml_equal(status, one));
+ {
+ aml_append(if_ctx2,
+ aml_call2(AML_NOTIFY_METHOD, idx, bus_check_evt));
+ }
+ aml_append(if_ctx, if_ctx2);
+ else_ctx2 = aml_else();
+ {
+ aml_append(else_ctx2,
+ aml_call2(AML_NOTIFY_METHOD, idx, remove_evt));
+ }
+ }
+ aml_append(if_ctx, else_ctx2);
+ aml_append(while_ctx, if_ctx);
+
+ aml_append(while_ctx, aml_increment(idx)); /* go to next cpu */
+ aml_append(method, while_ctx);
+ }
+ aml_append(sb_scope, method);
+
+ /* The current AML generator can cover the APIC ID range [0..255],
+ * inclusive, for VCPU hotplug. */
+ QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256);
+ g_assert(pcms->apic_id_limit <= ACPI_CPU_HOTPLUG_ID_LIMIT);
+
+ /* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */
+ dev = aml_device("PCI0." stringify(CPU_HOTPLUG_RESOURCE_DEVICE));
+ aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A06")));
+ aml_append(dev,
+ aml_name_decl("_UID", aml_string("CPU Hotplug resources"))
+ );
+ /* device present, functioning, decoding, not shown in UI */
+ aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
+ crs = aml_resource_template();
+ aml_append(crs,
+ aml_io(AML_DECODE16, io_base, io_base, 1, ACPI_GPE_PROC_LEN)
+ );
+ aml_append(dev, aml_name_decl("_CRS", crs));
+ aml_append(sb_scope, dev);
+ /* declare CPU hotplug MMIO region and PRS field to access it */
+ aml_append(sb_scope, aml_operation_region(
+ "PRST", AML_SYSTEM_IO, aml_int(io_base), ACPI_GPE_PROC_LEN));
+ field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE);
+ aml_append(field, aml_named_field("PRS", 256));
+ aml_append(sb_scope, field);
+
+ /* build Processor object for each processor */
+ for (i = 0; i < apic_ids->len; i++) {
+ int apic_id = apic_ids->cpus[i].arch_id;
+
+ assert(apic_id < ACPI_CPU_HOTPLUG_ID_LIMIT);
+
+ dev = aml_processor(i, 0, 0, "CP%.02X", apic_id);
+
+ method = aml_method("_MAT", 0, AML_NOTSERIALIZED);
+ aml_append(method,
+ aml_return(aml_call2(CPU_MAT_METHOD, aml_int(apic_id), aml_int(i))
+ ));
+ aml_append(dev, method);
+
+ method = aml_method("_STA", 0, AML_NOTSERIALIZED);
+ aml_append(method,
+ aml_return(aml_call1(CPU_STATUS_METHOD, aml_int(apic_id))));
+ aml_append(dev, method);
+
+ method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
+ aml_append(method,
+ aml_return(aml_call2(CPU_EJECT_METHOD, aml_int(apic_id),
+ aml_arg(0)))
+ );
+ aml_append(dev, method);
+
+ aml_append(sb_scope, dev);
+ }
+
+ /* build this code:
+ * Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}
+ */
+ /* Arg0 = APIC ID */
+ method = aml_method(AML_NOTIFY_METHOD, 2, AML_NOTSERIALIZED);
+ for (i = 0; i < apic_ids->len; i++) {
+ int apic_id = apic_ids->cpus[i].arch_id;
+
+ if_ctx = aml_if(aml_equal(aml_arg(0), aml_int(apic_id)));
+ aml_append(if_ctx,
+ aml_notify(aml_name("CP%.02X", apic_id), aml_arg(1))
+ );
+ aml_append(method, if_ctx);
+ }
+ aml_append(sb_scope, method);
+
+ /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })"
+ *
+ * Note: The ability to create variable-sized packages was first
+ * introduced in ACPI 2.0. ACPI 1.0 only allowed fixed-size packages
+ * ith up to 255 elements. Windows guests up to win2k8 fail when
+ * VarPackageOp is used.
+ */
+ pkg = pcms->apic_id_limit <= 255 ? aml_package(pcms->apic_id_limit) :
+ aml_varpackage(pcms->apic_id_limit);
+
+ for (i = 0, apic_idx = 0; i < apic_ids->len; i++) {
+ int apic_id = apic_ids->cpus[i].arch_id;
+
+ for (; apic_idx < apic_id; apic_idx++) {
+ aml_append(pkg, aml_int(0));
+ }
+ aml_append(pkg, aml_int(apic_ids->cpus[i].cpu ? 1 : 0));
+ apic_idx = apic_id + 1;
+ }
+ aml_append(sb_scope, aml_name_decl(CPU_ON_BITMAP, pkg));
+ g_free(apic_ids);
+
+ aml_append(ctx, sb_scope);
+
+ method = aml_method("\\_GPE._E02", 0, AML_NOTSERIALIZED);
+ aml_append(method, aml_call0("\\_SB." CPU_SCAN_METHOD));
+ aml_append(ctx, method);
+}
diff --git a/hw/acpi/cpu_hotplug_acpi_table.c b/hw/acpi/cpu_hotplug_acpi_table.c
deleted file mode 100644
index 97bb1092a2..0000000000
--- a/hw/acpi/cpu_hotplug_acpi_table.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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/>.
- */
-
-#include "qemu/osdep.h"
-#include "hw/acpi/cpu_hotplug.h"
-
-void build_cpu_hotplug_aml(Aml *ctx)
-{
- Aml *method;
- Aml *if_ctx;
- Aml *else_ctx;
- Aml *sb_scope = aml_scope("_SB");
- uint8_t madt_tmpl[8] = {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0};
- Aml *cpu_id = aml_arg(0);
- Aml *cpu_on = aml_local(0);
- Aml *madt = aml_local(1);
- Aml *cpus_map = aml_name(CPU_ON_BITMAP);
- Aml *zero = aml_int(0);
- Aml *one = aml_int(1);
-
- /*
- * _MAT method - creates an madt apic buffer
- * cpu_id = Arg0 = Processor ID = Local APIC ID
- * cpu_on = Local0 = CPON flag for this cpu
- * madt = Local1 = Buffer (in madt apic form) to return
- */
- method = aml_method(CPU_MAT_METHOD, 1, AML_NOTSERIALIZED);
- aml_append(method,
- aml_store(aml_derefof(aml_index(cpus_map, cpu_id)), cpu_on));
- aml_append(method,
- aml_store(aml_buffer(sizeof(madt_tmpl), madt_tmpl), madt));
- /* Update the processor id, lapic id, and enable/disable status */
- aml_append(method, aml_store(cpu_id, aml_index(madt, aml_int(2))));
- aml_append(method, aml_store(cpu_id, aml_index(madt, aml_int(3))));
- aml_append(method, aml_store(cpu_on, aml_index(madt, aml_int(4))));
- aml_append(method, aml_return(madt));
- aml_append(sb_scope, method);
-
- /*
- * _STA method - return ON status of cpu
- * cpu_id = Arg0 = Processor ID = Local APIC ID
- * cpu_on = Local0 = CPON flag for this cpu
- */
- method = aml_method(CPU_STATUS_METHOD, 1, AML_NOTSERIALIZED);
- aml_append(method,
- aml_store(aml_derefof(aml_index(cpus_map, cpu_id)), cpu_on));
- if_ctx = aml_if(cpu_on);
- {
- aml_append(if_ctx, aml_return(aml_int(0xF)));
- }
- aml_append(method, if_ctx);
- else_ctx = aml_else();
- {
- aml_append(else_ctx, aml_return(zero));
- }
- aml_append(method, else_ctx);
- aml_append(sb_scope, method);
-
- method = aml_method(CPU_EJECT_METHOD, 2, AML_NOTSERIALIZED);
- aml_append(method, aml_sleep(200));
- aml_append(sb_scope, method);
-
- method = aml_method(CPU_SCAN_METHOD, 0, AML_NOTSERIALIZED);
- {
- Aml *while_ctx, *if_ctx2, *else_ctx2;
- Aml *bus_check_evt = aml_int(1);
- Aml *remove_evt = aml_int(3);
- Aml *status_map = aml_local(5); /* Local5 = active cpu bitmap */
- Aml *byte = aml_local(2); /* Local2 = last read byte from bitmap */
- Aml *idx = aml_local(0); /* Processor ID / APIC ID iterator */
- Aml *is_cpu_on = aml_local(1); /* Local1 = CPON flag for cpu */
- Aml *status = aml_local(3); /* Local3 = active state for cpu */
-
- aml_append(method, aml_store(aml_name(CPU_STATUS_MAP), status_map));
- aml_append(method, aml_store(zero, byte));
- aml_append(method, aml_store(zero, idx));
-
- /* While (idx < SizeOf(CPON)) */
- while_ctx = aml_while(aml_lless(idx, aml_sizeof(cpus_map)));
- aml_append(while_ctx,
- aml_store(aml_derefof(aml_index(cpus_map, idx)), is_cpu_on));
-
- if_ctx = aml_if(aml_and(idx, aml_int(0x07), NULL));
- {
- /* Shift down previously read bitmap byte */
- aml_append(if_ctx, aml_shiftright(byte, one, byte));
- }
- aml_append(while_ctx, if_ctx);
-
- else_ctx = aml_else();
- {
- /* Read next byte from cpu bitmap */
- aml_append(else_ctx, aml_store(aml_derefof(aml_index(status_map,
- aml_shiftright(idx, aml_int(3), NULL))), byte));
- }
- aml_append(while_ctx, else_ctx);
-
- aml_append(while_ctx, aml_store(aml_and(byte, one, NULL), status));
- if_ctx = aml_if(aml_lnot(aml_equal(is_cpu_on, status)));
- {
- /* State change - update CPON with new state */
- aml_append(if_ctx, aml_store(status, aml_index(cpus_map, idx)));
- if_ctx2 = aml_if(aml_equal(status, one));
- {
- aml_append(if_ctx2,
- aml_call2(AML_NOTIFY_METHOD, idx, bus_check_evt));
- }
- aml_append(if_ctx, if_ctx2);
- else_ctx2 = aml_else();
- {
- aml_append(else_ctx2,
- aml_call2(AML_NOTIFY_METHOD, idx, remove_evt));
- }
- }
- aml_append(if_ctx, else_ctx2);
- aml_append(while_ctx, if_ctx);
-
- aml_append(while_ctx, aml_increment(idx)); /* go to next cpu */
- aml_append(method, while_ctx);
- }
- aml_append(sb_scope, method);
-
- aml_append(ctx, sb_scope);
-}
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 27e978f5fd..853c9c4eb7 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -273,8 +273,8 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
pm->powerdown_notifier.notify = pm_powerdown_req;
qemu_register_powerdown_notifier(&pm->powerdown_notifier);
- acpi_cpu_hotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci),
- &pm->gpe_cpu, ICH9_CPU_HOTPLUG_IO_BASE);
+ legacy_acpi_cpu_hotplug_init(pci_address_space_io(lpc_pci),
+ OBJECT(lpc_pci), &pm->gpe_cpu, ICH9_CPU_HOTPLUG_IO_BASE);
if (pm->acpi_memory_hotplug.is_enabled) {
acpi_memory_hotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci),
@@ -430,39 +430,47 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
NULL);
}
-void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp)
+void ich9_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp)
{
- if (pm->acpi_memory_hotplug.is_enabled &&
+ ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
+
+ if (lpc->pm.acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
- acpi_memory_plug_cb(&pm->acpi_regs, pm->irq, &pm->acpi_memory_hotplug,
+ acpi_memory_plug_cb(hotplug_dev, &lpc->pm.acpi_memory_hotplug,
dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
- acpi_cpu_plug_cb(&pm->acpi_regs, pm->irq, &pm->gpe_cpu, dev, errp);
+ legacy_acpi_cpu_plug_cb(hotplug_dev, &lpc->pm.gpe_cpu, dev, errp);
} else {
error_setg(errp, "acpi: device plug request for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
}
}
-void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
- Error **errp)
+void ich9_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp)
{
- if (pm->acpi_memory_hotplug.is_enabled &&
+ ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
+
+ if (lpc->pm.acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
- acpi_memory_unplug_request_cb(&pm->acpi_regs, pm->irq,
- &pm->acpi_memory_hotplug, dev, errp);
+ acpi_memory_unplug_request_cb(hotplug_dev,
+ &lpc->pm.acpi_memory_hotplug, dev,
+ errp);
} else {
error_setg(errp, "acpi: device unplug request for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
}
}
-void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
+void ich9_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp)
{
- if (pm->acpi_memory_hotplug.is_enabled &&
+ ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
+
+ if (lpc->pm.acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
- acpi_memory_unplug_cb(&pm->acpi_memory_hotplug, dev, errp);
+ acpi_memory_unplug_cb(&lpc->pm.acpi_memory_hotplug, dev, errp);
} else {
error_setg(errp, "acpi: device unplug for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index f65a3a21ef..ec4e64b361 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -228,7 +228,7 @@ acpi_memory_slot_status(MemHotplugState *mem_st,
return &mem_st->devs[slot];
}
-void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
+void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
DeviceState *dev, Error **errp)
{
MemStatus *mdev;
@@ -247,13 +247,11 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
mdev->is_enabled = true;
if (dev->hotplugged) {
mdev->is_inserting = true;
-
- /* do ACPI magic */
- acpi_send_gpe_event(ar, irq, ACPI_MEMORY_HOTPLUG_STATUS);
+ acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS);
}
}
-void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq,
+void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev,
MemHotplugState *mem_st,
DeviceState *dev, Error **errp)
{
@@ -265,9 +263,7 @@ void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq,
}
mdev->is_removing = true;
-
- /* Do ACPI magic */
- acpi_send_gpe_event(ar, irq, ACPI_MEMORY_HOTPLUG_STATUS);
+ acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS);
}
void acpi_memory_unplug_cb(MemHotplugState *mem_st,
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index fb925dccae..b4c22627df 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -353,7 +353,7 @@ static GArray *nvdimm_build_device_structure(GSList *device_list)
}
static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
- GArray *table_data, GArray *linker)
+ GArray *table_data, BIOSLinker *linker)
{
GArray *structures = nvdimm_build_device_structure(device_list);
unsigned int header;
@@ -579,7 +579,8 @@ static void nvdimm_build_nvdimm_devices(GSList *device_list, Aml *root_dev)
}
static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
- GArray *table_data, GArray *linker)
+ GArray *table_data, BIOSLinker *linker,
+ GArray *dsm_dma_arrea)
{
Aml *ssdt, *sb_scope, *dev, *field;
int mem_addr_offset, nvdimm_ssdt;
@@ -678,12 +679,12 @@ static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
mem_addr_offset = build_append_named_dword(table_data,
NVDIMM_ACPI_MEM_ADDR);
- bios_linker_loader_alloc(linker, NVDIMM_DSM_MEM_FILE, sizeof(NvdimmDsmIn),
- false /* high memory */);
- bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
- NVDIMM_DSM_MEM_FILE, table_data,
- table_data->data + mem_addr_offset,
- sizeof(uint32_t));
+ bios_linker_loader_alloc(linker,
+ NVDIMM_DSM_MEM_FILE, dsm_dma_arrea,
+ sizeof(NvdimmDsmIn), false /* high memory */);
+ bios_linker_loader_add_pointer(linker,
+ ACPI_BUILD_TABLE_FILE, mem_addr_offset, sizeof(uint32_t),
+ NVDIMM_DSM_MEM_FILE, 0);
build_header(linker, table_data,
(void *)(table_data->data + nvdimm_ssdt),
"SSDT", table_data->len - nvdimm_ssdt, 1, NULL, "NVDIMM");
@@ -691,7 +692,7 @@ static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
}
void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
- GArray *linker)
+ BIOSLinker *linker, GArray *dsm_dma_arrea)
{
GSList *device_list;
@@ -701,6 +702,7 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
return;
}
nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
- nvdimm_build_ssdt(device_list, table_offsets, table_data, linker);
+ nvdimm_build_ssdt(device_list, table_offsets, table_data, linker,
+ dsm_dma_arrea);
g_slist_free(device_list);
}
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 71f4c4e14b..d957d1e30d 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -182,7 +182,7 @@ void acpi_pcihp_reset(AcpiPciHpState *s)
acpi_pcihp_update(s);
}
-void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
+void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
DeviceState *dev, Error **errp)
{
PCIDevice *pdev = PCI_DEVICE(dev);
@@ -202,11 +202,10 @@ void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
}
s->acpi_pcihp_pci_status[bsel].up |= (1U << slot);
-
- acpi_send_gpe_event(ar, irq, ACPI_PCI_HOTPLUG_STATUS);
+ acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
}
-void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
+void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
DeviceState *dev, Error **errp)
{
PCIDevice *pdev = PCI_DEVICE(dev);
@@ -219,8 +218,7 @@ void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
}
s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
-
- acpi_send_gpe_event(ar, irq, ACPI_PCI_HOTPLUG_STATUS);
+ acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
}
static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index b3e3bb306a..c48cb1b91a 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -348,12 +348,11 @@ static void piix4_device_plug_cb(HotplugHandler *hotplug_dev,
if (s->acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
- acpi_memory_plug_cb(&s->ar, s->irq, &s->acpi_memory_hotplug, dev, errp);
+ acpi_memory_plug_cb(hotplug_dev, &s->acpi_memory_hotplug, dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
- acpi_pcihp_device_plug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev,
- errp);
+ acpi_pcihp_device_plug_cb(hotplug_dev, &s->acpi_pci_hotplug, dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
- acpi_cpu_plug_cb(&s->ar, s->irq, &s->gpe_cpu, dev, errp);
+ legacy_acpi_cpu_plug_cb(hotplug_dev, &s->gpe_cpu, dev, errp);
} else {
error_setg(errp, "acpi: device plug request for not supported device"
" type: %s", object_get_typename(OBJECT(dev)));
@@ -367,10 +366,10 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev,
if (s->acpi_memory_hotplug.is_enabled &&
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
- acpi_memory_unplug_request_cb(&s->ar, s->irq, &s->acpi_memory_hotplug,
+ acpi_memory_unplug_request_cb(hotplug_dev, &s->acpi_memory_hotplug,
dev, errp);
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
- acpi_pcihp_device_unplug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev,
+ acpi_pcihp_device_unplug_cb(hotplug_dev, &s->acpi_pci_hotplug, dev,
errp);
} else {
error_setg(errp, "acpi: device unplug request for not supported device"
@@ -571,8 +570,8 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
acpi_pcihp_init(OBJECT(s), &s->acpi_pci_hotplug, bus, parent,
s->use_acpi_pci_hotplug);
- acpi_cpu_hotplug_init(parent, OBJECT(s), &s->gpe_cpu,
- PIIX4_CPU_HOTPLUG_IO_BASE);
+ legacy_acpi_cpu_hotplug_init(parent, OBJECT(s), &s->gpe_cpu,
+ PIIX4_CPU_HOTPLUG_IO_BASE);
if (s->acpi_memory_hotplug.is_enabled) {
acpi_memory_hotplug_init(parent, OBJECT(s), &s->acpi_memory_hotplug);
@@ -586,6 +585,13 @@ static void piix4_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
acpi_memory_ospm_status(&s->acpi_memory_hotplug, list);
}
+static void piix4_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
+{
+ PIIX4PMState *s = PIIX4_PM(adev);
+
+ acpi_send_gpe_event(&s->ar, s->irq, ev);
+}
+
static Property piix4_pm_properties[] = {
DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
@@ -624,6 +630,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data)
hc->unplug_request = piix4_device_unplug_request_cb;
hc->unplug = piix4_device_unplug_cb;
adevc->ospm_status = piix4_ospm_status;
+ adevc->send_event = piix4_send_gpe;
}
static const TypeInfo piix4_pm_info = {
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 83a54203b8..735ab864a0 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -354,11 +354,14 @@ static void acpi_dsdt_add_power_button(Aml *scope)
/* RSDP */
static GArray *
-build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
+build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
{
AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
+ unsigned rsdt_pa_size = sizeof(rsdp->rsdt_physical_address);
+ unsigned rsdt_pa_offset =
+ (char *)&rsdp->rsdt_physical_address - rsdp_table->data;
- bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, 16,
+ bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,
true /* fseg memory */);
memcpy(&rsdp->signature, "RSD PTR ", sizeof(rsdp->signature));
@@ -366,24 +369,21 @@ build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
rsdp->length = cpu_to_le32(sizeof(*rsdp));
rsdp->revision = 0x02;
- /* Point to RSDT */
- rsdp->rsdt_physical_address = cpu_to_le32(rsdt);
/* Address to be filled by Guest linker */
- bios_linker_loader_add_pointer(linker, ACPI_BUILD_RSDP_FILE,
- ACPI_BUILD_TABLE_FILE,
- rsdp_table, &rsdp->rsdt_physical_address,
- sizeof rsdp->rsdt_physical_address);
- rsdp->checksum = 0;
+ bios_linker_loader_add_pointer(linker,
+ ACPI_BUILD_RSDP_FILE, rsdt_pa_offset, rsdt_pa_size,
+ ACPI_BUILD_TABLE_FILE, rsdt_tbl_offset);
+
/* Checksum to be filled by Guest linker */
bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
- rsdp_table, rsdp, sizeof *rsdp,
- &rsdp->checksum);
+ (char *)rsdp - rsdp_table->data, sizeof *rsdp,
+ (char *)&rsdp->checksum - rsdp_table->data);
return rsdp_table;
}
static void
-build_spcr(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
+build_spcr(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
{
AcpiSerialPortConsoleRedirection *spcr;
const MemMapEntry *uart_memmap = &guest_info->memmap[VIRT_UART];
@@ -416,7 +416,7 @@ build_spcr(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
}
static void
-build_srat(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
+build_srat(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
{
AcpiSystemResourceAffinityTable *srat;
AcpiSratProcessorGiccAffinity *core;
@@ -456,13 +456,12 @@ build_srat(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
mem_base += numa_info[i].node_mem;
}
- build_header(linker, table_data,
- (void *)(table_data->data + srat_start), "SRAT",
+ build_header(linker, table_data, (void *)srat, "SRAT",
table_data->len - srat_start, 3, NULL, NULL);
}
static void
-build_mcfg(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
+build_mcfg(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
{
AcpiTableMcfg *mcfg;
const MemMapEntry *memmap = guest_info->memmap;
@@ -482,7 +481,7 @@ build_mcfg(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
/* GTDT */
static void
-build_gtdt(GArray *table_data, GArray *linker)
+build_gtdt(GArray *table_data, BIOSLinker *linker)
{
int gtdt_start = table_data->len;
AcpiGenericTimerTable *gtdt;
@@ -508,7 +507,7 @@ build_gtdt(GArray *table_data, GArray *linker)
/* MADT */
static void
-build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
+build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
{
int madt_start = table_data->len;
const MemMapEntry *memmap = guest_info->memmap;
@@ -567,9 +566,10 @@ build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
/* FADT */
static void
-build_fadt(GArray *table_data, GArray *linker, unsigned dsdt)
+build_fadt(GArray *table_data, BIOSLinker *linker, unsigned dsdt_tbl_offset)
{
AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
+ unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data;
/* Hardware Reduced = 1 and use PSCI 0.2+ and with HVC */
fadt->flags = cpu_to_le32(1 << ACPI_FADT_F_HW_REDUCED_ACPI);
@@ -579,12 +579,10 @@ build_fadt(GArray *table_data, GArray *linker, unsigned dsdt)
/* ACPI v5.1 (fadt->revision.fadt->minor_revision) */
fadt->minor_revision = 0x1;
- fadt->dsdt = cpu_to_le32(dsdt);
/* DSDT address to be filled by Guest linker */
- bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
- ACPI_BUILD_TABLE_FILE,
- table_data, &fadt->dsdt,
- sizeof fadt->dsdt);
+ bios_linker_loader_add_pointer(linker,
+ ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->dsdt),
+ ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset);
build_header(linker, table_data,
(void *)fadt, "FACP", sizeof(*fadt), 5, NULL, NULL);
@@ -592,7 +590,7 @@ build_fadt(GArray *table_data, GArray *linker, unsigned dsdt)
/* DSDT */
static void
-build_dsdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
+build_dsdt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
{
Aml *scope, *dsdt;
const MemMapEntry *memmap = guest_info->memmap;
@@ -652,7 +650,8 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables)
table_offsets = g_array_new(false, true /* clear */,
sizeof(uint32_t));
- bios_linker_loader_alloc(tables->linker, ACPI_BUILD_TABLE_FILE,
+ bios_linker_loader_alloc(tables->linker,
+ ACPI_BUILD_TABLE_FILE, tables_blob,
64, false /* high memory */);
/*
@@ -731,7 +730,7 @@ static void virt_acpi_build_update(void *build_opaque)
acpi_ram_update(build_state->table_mr, tables.table_data);
acpi_ram_update(build_state->rsdp_mr, tables.rsdp);
- acpi_ram_update(build_state->linker_mr, tables.linker);
+ acpi_ram_update(build_state->linker_mr, tables.linker->cmd_blob);
acpi_build_tables_cleanup(&tables, true);
@@ -789,7 +788,8 @@ void virt_acpi_setup(VirtGuestInfo *guest_info)
assert(build_state->table_mr != NULL);
build_state->linker_mr =
- acpi_add_rom_blob(build_state, tables.linker, "etc/table-loader", 0);
+ acpi_add_rom_blob(build_state, tables.linker->cmd_blob,
+ "etc/table-loader", 0);
fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
tables.tcpalog->data, acpi_data_len(tables.tcpalog));
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 279f0d7d05..06d6204749 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -94,7 +94,6 @@ typedef struct AcpiPmInfo {
uint32_t gpe0_blk_len;
uint32_t io_base;
uint16_t cpu_hp_io_base;
- uint16_t cpu_hp_io_len;
uint16_t mem_hp_io_base;
uint16_t mem_hp_io_len;
uint16_t pcihp_io_base;
@@ -142,7 +141,6 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
}
assert(obj);
- pm->cpu_hp_io_len = ACPI_GPE_PROC_LEN;
pm->mem_hp_io_base = ACPI_MEMORY_HOTPLUG_BASE;
pm->mem_hp_io_len = ACPI_MEMORY_HOTPLUG_IO_LEN;
@@ -262,7 +260,7 @@ static void acpi_align_size(GArray *blob, unsigned align)
/* FACS */
static void
-build_facs(GArray *table_data, GArray *linker)
+build_facs(GArray *table_data, BIOSLinker *linker)
{
AcpiFacsDescriptorRev1 *facs = acpi_data_push(table_data, sizeof *facs);
memcpy(&facs->signature, "FACS", 4);
@@ -307,34 +305,31 @@ static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, AcpiPmInfo *pm)
/* FADT */
static void
-build_fadt(GArray *table_data, GArray *linker, AcpiPmInfo *pm,
- unsigned facs, unsigned dsdt,
+build_fadt(GArray *table_data, BIOSLinker *linker, AcpiPmInfo *pm,
+ unsigned facs_tbl_offset, unsigned dsdt_tbl_offset,
const char *oem_id, const char *oem_table_id)
{
AcpiFadtDescriptorRev1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
+ unsigned fw_ctrl_offset = (char *)&fadt->firmware_ctrl - table_data->data;
+ unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data;
- fadt->firmware_ctrl = cpu_to_le32(facs);
/* FACS address to be filled by Guest linker */
- bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
- ACPI_BUILD_TABLE_FILE,
- table_data, &fadt->firmware_ctrl,
- sizeof fadt->firmware_ctrl);
+ bios_linker_loader_add_pointer(linker,
+ ACPI_BUILD_TABLE_FILE, fw_ctrl_offset, sizeof(fadt->firmware_ctrl),
+ ACPI_BUILD_TABLE_FILE, facs_tbl_offset);
- fadt->dsdt = cpu_to_le32(dsdt);
/* DSDT address to be filled by Guest linker */
- bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
- ACPI_BUILD_TABLE_FILE,
- table_data, &fadt->dsdt,
- sizeof fadt->dsdt);
-
fadt_setup(fadt, pm);
+ bios_linker_loader_add_pointer(linker,
+ ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->dsdt),
+ ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset);
build_header(linker, table_data,
(void *)fadt, "FACP", sizeof(*fadt), 1, oem_id, oem_table_id);
}
static void
-build_madt(GArray *table_data, GArray *linker, PCMachineState *pcms)
+build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms)
{
MachineClass *mc = MACHINE_GET_CLASS(pcms);
CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(pcms));
@@ -356,7 +351,7 @@ build_madt(GArray *table_data, GArray *linker, PCMachineState *pcms)
apic->type = ACPI_APIC_PROCESSOR;
apic->length = sizeof(*apic);
- apic->processor_id = apic_id;
+ apic->processor_id = i;
apic->local_apic_id = apic_id;
if (apic_ids->cpus[i].cpu != NULL) {
apic->flags = cpu_to_le32(1);
@@ -943,114 +938,6 @@ static Aml *build_crs(PCIHostState *host,
return crs;
}
-static void build_processor_devices(Aml *sb_scope, MachineState *machine,
- AcpiPmInfo *pm)
-{
- int i, apic_idx;
- Aml *dev;
- Aml *crs;
- Aml *pkg;
- Aml *field;
- Aml *ifctx;
- Aml *method;
- MachineClass *mc = MACHINE_GET_CLASS(machine);
- CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
- PCMachineState *pcms = PC_MACHINE(machine);
-
- /* The current AML generator can cover the APIC ID range [0..255],
- * inclusive, for VCPU hotplug. */
- QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256);
- g_assert(pcms->apic_id_limit <= ACPI_CPU_HOTPLUG_ID_LIMIT);
-
- /* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */
- dev = aml_device("PCI0." stringify(CPU_HOTPLUG_RESOURCE_DEVICE));
- aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A06")));
- aml_append(dev,
- aml_name_decl("_UID", aml_string("CPU Hotplug resources"))
- );
- /* device present, functioning, decoding, not shown in UI */
- aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
- crs = aml_resource_template();
- aml_append(crs,
- aml_io(AML_DECODE16, pm->cpu_hp_io_base, pm->cpu_hp_io_base, 1,
- pm->cpu_hp_io_len)
- );
- aml_append(dev, aml_name_decl("_CRS", crs));
- aml_append(sb_scope, dev);
- /* declare CPU hotplug MMIO region and PRS field to access it */
- aml_append(sb_scope, aml_operation_region(
- "PRST", AML_SYSTEM_IO, aml_int(pm->cpu_hp_io_base), pm->cpu_hp_io_len));
- field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE);
- aml_append(field, aml_named_field("PRS", 256));
- aml_append(sb_scope, field);
-
- /* build Processor object for each processor */
- for (i = 0; i < apic_ids->len; i++) {
- int apic_id = apic_ids->cpus[i].arch_id;
-
- assert(apic_id < ACPI_CPU_HOTPLUG_ID_LIMIT);
-
- dev = aml_processor(apic_id, 0, 0, "CP%.02X", apic_id);
-
- method = aml_method("_MAT", 0, AML_NOTSERIALIZED);
- aml_append(method,
- aml_return(aml_call1(CPU_MAT_METHOD, aml_int(apic_id))));
- aml_append(dev, method);
-
- method = aml_method("_STA", 0, AML_NOTSERIALIZED);
- aml_append(method,
- aml_return(aml_call1(CPU_STATUS_METHOD, aml_int(apic_id))));
- aml_append(dev, method);
-
- method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
- aml_append(method,
- aml_return(aml_call2(CPU_EJECT_METHOD, aml_int(apic_id),
- aml_arg(0)))
- );
- aml_append(dev, method);
-
- aml_append(sb_scope, dev);
- }
-
- /* build this code:
- * Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}
- */
- /* Arg0 = Processor ID = APIC ID */
- method = aml_method(AML_NOTIFY_METHOD, 2, AML_NOTSERIALIZED);
- for (i = 0; i < apic_ids->len; i++) {
- int apic_id = apic_ids->cpus[i].arch_id;
-
- ifctx = aml_if(aml_equal(aml_arg(0), aml_int(apic_id)));
- aml_append(ifctx,
- aml_notify(aml_name("CP%.02X", apic_id), aml_arg(1))
- );
- aml_append(method, ifctx);
- }
- aml_append(sb_scope, method);
-
- /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })"
- *
- * Note: The ability to create variable-sized packages was first
- * introduced in ACPI 2.0. ACPI 1.0 only allowed fixed-size packages
- * ith up to 255 elements. Windows guests up to win2k8 fail when
- * VarPackageOp is used.
- */
- pkg = pcms->apic_id_limit <= 255 ? aml_package(pcms->apic_id_limit) :
- aml_varpackage(pcms->apic_id_limit);
-
- for (i = 0, apic_idx = 0; i < apic_ids->len; i++) {
- int apic_id = apic_ids->cpus[i].arch_id;
-
- for (; apic_idx < apic_id; apic_idx++) {
- aml_append(pkg, aml_int(0));
- }
- aml_append(pkg, aml_int(apic_ids->cpus[i].cpu ? 1 : 0));
- apic_idx = apic_id + 1;
- }
- aml_append(sb_scope, aml_name_decl(CPU_ON_BITMAP, pkg));
- g_free(apic_ids);
-}
-
static void build_memory_devices(Aml *sb_scope, int nr_mem,
uint16_t io_base, uint16_t io_len)
{
@@ -1979,7 +1866,7 @@ static Aml *build_q35_osc_method(void)
}
static void
-build_dsdt(GArray *table_data, GArray *linker,
+build_dsdt(GArray *table_data, BIOSLinker *linker,
AcpiPmInfo *pm, AcpiMiscInfo *misc,
PcPciInfo *pci, MachineState *machine)
{
@@ -2043,7 +1930,7 @@ build_dsdt(GArray *table_data, GArray *linker,
build_q35_pci0_int(dsdt);
}
- build_cpu_hotplug_aml(dsdt);
+ build_legacy_cpu_hotplug_aml(dsdt, machine, pm->cpu_hp_io_base);
build_memory_hotplug_aml(dsdt, nr_mem, pm->mem_hp_io_base,
pm->mem_hp_io_len);
@@ -2051,8 +1938,6 @@ build_dsdt(GArray *table_data, GArray *linker,
{
aml_append(scope, aml_name_decl("_HID", aml_string("ACPI0006")));
- aml_append(scope, aml_method("_L00", 0, AML_NOTSERIALIZED));
-
if (misc->is_piix4) {
method = aml_method("_E01", 0, AML_NOTSERIALIZED);
aml_append(method,
@@ -2060,30 +1945,11 @@ build_dsdt(GArray *table_data, GArray *linker,
aml_append(method, aml_call0("\\_SB.PCI0.PCNT"));
aml_append(method, aml_release(aml_name("\\_SB.PCI0.BLCK")));
aml_append(scope, method);
- } else {
- aml_append(scope, aml_method("_L01", 0, AML_NOTSERIALIZED));
}
- method = aml_method("_E02", 0, AML_NOTSERIALIZED);
- aml_append(method, aml_call0("\\_SB." CPU_SCAN_METHOD));
- aml_append(scope, method);
-
method = aml_method("_E03", 0, AML_NOTSERIALIZED);
aml_append(method, aml_call0(MEMORY_HOTPLUG_HANDLER_PATH));
aml_append(scope, method);
-
- aml_append(scope, aml_method("_L04", 0, AML_NOTSERIALIZED));
- aml_append(scope, aml_method("_L05", 0, AML_NOTSERIALIZED));
- aml_append(scope, aml_method("_L06", 0, AML_NOTSERIALIZED));
- aml_append(scope, aml_method("_L07", 0, AML_NOTSERIALIZED));
- aml_append(scope, aml_method("_L08", 0, AML_NOTSERIALIZED));
- aml_append(scope, aml_method("_L09", 0, AML_NOTSERIALIZED));
- aml_append(scope, aml_method("_L0A", 0, AML_NOTSERIALIZED));
- aml_append(scope, aml_method("_L0B", 0, AML_NOTSERIALIZED));
- aml_append(scope, aml_method("_L0C", 0, AML_NOTSERIALIZED));
- aml_append(scope, aml_method("_L0D", 0, AML_NOTSERIALIZED));
- aml_append(scope, aml_method("_L0E", 0, AML_NOTSERIALIZED));
- aml_append(scope, aml_method("_L0F", 0, AML_NOTSERIALIZED));
}
aml_append(dsdt, scope);
@@ -2322,8 +2188,6 @@ build_dsdt(GArray *table_data, GArray *linker,
sb_scope = aml_scope("\\_SB");
{
- build_processor_devices(sb_scope, machine, pm);
-
build_memory_devices(sb_scope, nr_mem, pm->mem_hp_io_base,
pm->mem_hp_io_len);
@@ -2373,7 +2237,7 @@ build_dsdt(GArray *table_data, GArray *linker,
}
static void
-build_hpet(GArray *table_data, GArray *linker)
+build_hpet(GArray *table_data, BIOSLinker *linker)
{
Acpi20Hpet *hpet;
@@ -2388,32 +2252,31 @@ build_hpet(GArray *table_data, GArray *linker)
}
static void
-build_tpm_tcpa(GArray *table_data, GArray *linker, GArray *tcpalog)
+build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
{
Acpi20Tcpa *tcpa = acpi_data_push(table_data, sizeof *tcpa);
- uint64_t log_area_start_address = acpi_data_len(tcpalog);
+ unsigned log_addr_size = sizeof(tcpa->log_area_start_address);
+ unsigned log_addr_offset =
+ (char *)&tcpa->log_area_start_address - table_data->data;
tcpa->platform_class = cpu_to_le16(TPM_TCPA_ACPI_CLASS_CLIENT);
tcpa->log_area_minimum_length = cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
- tcpa->log_area_start_address = cpu_to_le64(log_area_start_address);
+ acpi_data_push(tcpalog, le32_to_cpu(tcpa->log_area_minimum_length));
- bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE, 1,
+ bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE, tcpalog, 1,
false /* high memory */);
/* log area start address to be filled by Guest linker */
- bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
- ACPI_BUILD_TPMLOG_FILE,
- table_data, &tcpa->log_area_start_address,
- sizeof(tcpa->log_area_start_address));
+ bios_linker_loader_add_pointer(linker,
+ ACPI_BUILD_TABLE_FILE, log_addr_offset, log_addr_size,
+ ACPI_BUILD_TPMLOG_FILE, 0);
build_header(linker, table_data,
(void *)tcpa, "TCPA", sizeof(*tcpa), 2, NULL, NULL);
-
- acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE);
}
static void
-build_tpm2(GArray *table_data, GArray *linker)
+build_tpm2(GArray *table_data, BIOSLinker *linker)
{
Acpi20TPM2 *tpm2_ptr;
@@ -2428,7 +2291,7 @@ build_tpm2(GArray *table_data, GArray *linker)
}
static void
-build_srat(GArray *table_data, GArray *linker, MachineState *machine)
+build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
{
AcpiSystemResourceAffinityTable *srat;
AcpiSratProcessorAffinity *core;
@@ -2525,7 +2388,7 @@ build_srat(GArray *table_data, GArray *linker, MachineState *machine)
}
static void
-build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
+build_mcfg_q35(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info)
{
AcpiTableMcfg *mcfg;
const char *sig;
@@ -2554,7 +2417,7 @@ build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
}
static void
-build_dmar_q35(GArray *table_data, GArray *linker)
+build_dmar_q35(GArray *table_data, BIOSLinker *linker)
{
int dmar_start = table_data->len;
@@ -2578,26 +2441,27 @@ build_dmar_q35(GArray *table_data, GArray *linker)
}
static GArray *
-build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
+build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
{
AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
+ unsigned rsdt_pa_size = sizeof(rsdp->rsdt_physical_address);
+ unsigned rsdt_pa_offset =
+ (char *)&rsdp->rsdt_physical_address - rsdp_table->data;
- bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, 16,
+ bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,
true /* fseg memory */);
memcpy(&rsdp->signature, "RSD PTR ", 8);
memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
- rsdp->rsdt_physical_address = cpu_to_le32(rsdt);
/* Address to be filled by Guest linker */
- bios_linker_loader_add_pointer(linker, ACPI_BUILD_RSDP_FILE,
- ACPI_BUILD_TABLE_FILE,
- rsdp_table, &rsdp->rsdt_physical_address,
- sizeof rsdp->rsdt_physical_address);
- rsdp->checksum = 0;
+ bios_linker_loader_add_pointer(linker,
+ ACPI_BUILD_RSDP_FILE, rsdt_pa_offset, rsdt_pa_size,
+ ACPI_BUILD_TABLE_FILE, rsdt_tbl_offset);
+
/* Checksum to be filled by Guest linker */
bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
- rsdp_table, rsdp, sizeof *rsdp,
- &rsdp->checksum);
+ (char *)rsdp - rsdp_table->data, sizeof *rsdp,
+ (char *)&rsdp->checksum - rsdp_table->data);
return rsdp_table;
}
@@ -2670,7 +2534,8 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
sizeof(uint32_t));
ACPI_BUILD_DPRINTF("init ACPI tables\n");
- bios_linker_loader_alloc(tables->linker, ACPI_BUILD_TABLE_FILE,
+ bios_linker_loader_alloc(tables->linker,
+ ACPI_BUILD_TABLE_FILE, tables_blob,
64 /* Ensure FACS is aligned */,
false /* high memory */);
@@ -2727,7 +2592,8 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
build_dmar_q35(tables_blob, tables->linker);
}
if (pcms->acpi_nvdimm_state.is_enabled) {
- nvdimm_build_acpi(table_offsets, tables_blob, tables->linker);
+ nvdimm_build_acpi(table_offsets, tables_blob, tables->linker,
+ pcms->acpi_nvdimm_state.dsm_mem);
}
/* Add tables supplied by user (if any) */
@@ -2790,7 +2656,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE);
}
- acpi_align_size(tables->linker, ACPI_BUILD_ALIGN_SIZE);
+ acpi_align_size(tables->linker->cmd_blob, ACPI_BUILD_ALIGN_SIZE);
/* Cleanup memory that's no longer used. */
g_array_free(table_offsets, true);
@@ -2830,7 +2696,7 @@ static void acpi_build_update(void *build_opaque)
acpi_ram_update(build_state->rsdp_mr, tables.rsdp);
}
- acpi_ram_update(build_state->linker_mr, tables.linker);
+ acpi_ram_update(build_state->linker_mr, tables.linker->cmd_blob);
acpi_build_tables_cleanup(&tables, true);
}
@@ -2894,7 +2760,8 @@ void acpi_setup(void)
assert(build_state->table_mr != NULL);
build_state->linker_mr =
- acpi_add_rom_blob(build_state, tables.linker, "etc/table-loader", 0);
+ acpi_add_rom_blob(build_state, tables.linker->cmd_blob,
+ "etc/table-loader", 0);
fw_cfg_add_file(pcms->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
tables.tcpalog->data, acpi_data_len(tables.tcpalog));
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index e29ccc8341..92125a8cc8 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -765,8 +765,6 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)
acpi_tables, acpi_tables_len);
fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
- pc_build_smbios(fw_cfg);
-
fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE,
&e820_reserve, sizeof(e820_reserve));
fw_cfg_add_file(fw_cfg, "etc/e820", e820_table,
@@ -1182,6 +1180,9 @@ void pc_machine_done(Notifier *notifier, void *data)
}
acpi_setup();
+ if (pcms->fw_cfg) {
+ pc_build_smbios(pcms->fw_cfg);
+ }
}
void pc_guest_info_init(PCMachineState *pcms)
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 42ad68a1c0..78c10a0406 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -271,7 +271,8 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
if (s->lba == -1) {
/* Non-block ATAPI transfer - just copy to RAM */
s->io_buffer_size = MIN(s->io_buffer_size, io->len);
- cpu_physical_memory_write(io->addr, s->io_buffer, s->io_buffer_size);
+ dma_memory_write(&address_space_memory, io->addr, s->io_buffer,
+ s->io_buffer_size);
ide_atapi_cmd_ok(s);
m->dma_active = false;
goto done;
diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
index 6adec1e990..f09f217e78 100644
--- a/hw/ipmi/ipmi.c
+++ b/hw/ipmi/ipmi.c
@@ -30,6 +30,13 @@
#include "qom/object_interfaces.h"
#include "qapi/visitor.h"
+static uint32_t ipmi_current_uuid = 1;
+
+uint32_t ipmi_next_uuid(void)
+{
+ return ipmi_current_uuid++;
+}
+
static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly)
{
switch (op) {
@@ -122,30 +129,3 @@ static void ipmi_register_types(void)
}
type_init(ipmi_register_types)
-
-static IPMIFwInfo *ipmi_fw_info;
-static unsigned int ipmi_fw_info_len;
-
-static uint32_t current_uuid = 1;
-
-void ipmi_add_fwinfo(IPMIFwInfo *info, Error **errp)
-{
- info->uuid = current_uuid++;
- ipmi_fw_info = g_realloc(ipmi_fw_info,
- sizeof(*ipmi_fw_info) * (ipmi_fw_info_len + 1));
- ipmi_fw_info[ipmi_fw_info_len] = *info;
-}
-
-IPMIFwInfo *ipmi_first_fwinfo(void)
-{
- return ipmi_fw_info;
-}
-
-IPMIFwInfo *ipmi_next_fwinfo(IPMIFwInfo *current)
-{
- current++;
- if (current >= &ipmi_fw_info[ipmi_fw_info_len]) {
- return NULL;
- }
- return current;
-}
diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c
index aaea12ecdd..f03661715c 100644
--- a/hw/ipmi/isa_ipmi_bt.c
+++ b/hw/ipmi/isa_ipmi_bt.c
@@ -390,16 +390,6 @@ static void ipmi_bt_init(IPMIInterface *ii, Error **errp)
memory_region_init_io(&ib->io, NULL, &ipmi_bt_io_ops, ii, "ipmi-bt", 3);
}
-static void ipmi_bt_class_init(IPMIInterfaceClass *iic)
-{
- iic->init = ipmi_bt_init;
- iic->set_atn = ipmi_bt_set_atn;
- iic->handle_rsp = ipmi_bt_handle_rsp;
- iic->handle_if_event = ipmi_bt_handle_event;
- iic->set_irq_enable = ipmi_bt_set_irq_enable;
- iic->reset = ipmi_bt_handle_reset;
-}
-
#define TYPE_ISA_IPMI_BT "isa-ipmi-bt"
#define ISA_IPMI_BT(obj) OBJECT_CHECK(ISAIPMIBTDevice, (obj), \
@@ -409,9 +399,38 @@ typedef struct ISAIPMIBTDevice {
ISADevice dev;
int32_t isairq;
IPMIBT bt;
- IPMIFwInfo fwinfo;
+ uint32_t uuid;
} ISAIPMIBTDevice;
+static void ipmi_bt_get_fwinfo(struct IPMIInterface *ii, IPMIFwInfo *info)
+{
+ ISAIPMIBTDevice *iib = ISA_IPMI_BT(ii);
+
+ info->interface_name = "bt";
+ info->interface_type = IPMI_SMBIOS_BT;
+ info->ipmi_spec_major_revision = 2;
+ info->ipmi_spec_minor_revision = 0;
+ info->base_address = iib->bt.io_base;
+ info->register_length = iib->bt.io_length;
+ info->register_spacing = 1;
+ info->memspace = IPMI_MEMSPACE_IO;
+ info->irq_type = IPMI_LEVEL_IRQ;
+ info->interrupt_number = iib->isairq;
+ info->i2c_slave_address = iib->bt.bmc->slave_addr;
+ info->uuid = iib->uuid;
+}
+
+static void ipmi_bt_class_init(IPMIInterfaceClass *iic)
+{
+ iic->init = ipmi_bt_init;
+ iic->set_atn = ipmi_bt_set_atn;
+ iic->handle_rsp = ipmi_bt_handle_rsp;
+ iic->handle_if_event = ipmi_bt_handle_event;
+ iic->set_irq_enable = ipmi_bt_set_irq_enable;
+ iic->reset = ipmi_bt_handle_reset;
+ iic->get_fwinfo = ipmi_bt_get_fwinfo;
+}
+
static void isa_ipmi_bt_realize(DeviceState *dev, Error **errp)
{
ISADevice *isadev = ISA_DEVICE(dev);
@@ -424,6 +443,8 @@ static void isa_ipmi_bt_realize(DeviceState *dev, Error **errp)
return;
}
+ iib->uuid = ipmi_next_uuid();
+
iib->bt.bmc->intf = ii;
iic->init(ii, errp);
@@ -438,20 +459,6 @@ static void isa_ipmi_bt_realize(DeviceState *dev, Error **errp)
qdev_set_legacy_instance_id(dev, iib->bt.io_base, iib->bt.io_length);
isa_register_ioport(isadev, &iib->bt.io, iib->bt.io_base);
-
- iib->fwinfo.interface_name = "bt";
- iib->fwinfo.interface_type = IPMI_SMBIOS_BT;
- iib->fwinfo.ipmi_spec_major_revision = 2;
- iib->fwinfo.ipmi_spec_minor_revision = 0;
- iib->fwinfo.base_address = iib->bt.io_base;
- iib->fwinfo.register_length = iib->bt.io_length;
- iib->fwinfo.register_spacing = 1;
- iib->fwinfo.memspace = IPMI_MEMSPACE_IO;
- iib->fwinfo.irq_type = IPMI_LEVEL_IRQ;
- iib->fwinfo.interrupt_number = iib->isairq;
- iib->fwinfo.acpi_parent = "\\_SB.PCI0.ISA";
- iib->fwinfo.i2c_slave_address = iib->bt.bmc->slave_addr;
- ipmi_add_fwinfo(&iib->fwinfo, errp);
}
static const VMStateDescription vmstate_ISAIPMIBTDevice = {
diff --git a/hw/ipmi/isa_ipmi_kcs.c b/hw/ipmi/isa_ipmi_kcs.c
index 2742ce06c4..9a38f8a28a 100644
--- a/hw/ipmi/isa_ipmi_kcs.c
+++ b/hw/ipmi/isa_ipmi_kcs.c
@@ -354,16 +354,6 @@ static void ipmi_kcs_init(IPMIInterface *ii, Error **errp)
memory_region_init_io(&ik->io, NULL, &ipmi_kcs_io_ops, ii, "ipmi-kcs", 2);
}
-static void ipmi_kcs_class_init(IPMIInterfaceClass *iic)
-{
- iic->init = ipmi_kcs_init;
- iic->set_atn = ipmi_kcs_set_atn;
- iic->handle_rsp = ipmi_kcs_handle_rsp;
- iic->handle_if_event = ipmi_kcs_handle_event;
- iic->set_irq_enable = ipmi_kcs_set_irq_enable;
-}
-
-
#define TYPE_ISA_IPMI_KCS "isa-ipmi-kcs"
#define ISA_IPMI_KCS(obj) OBJECT_CHECK(ISAIPMIKCSDevice, (obj), \
TYPE_ISA_IPMI_KCS)
@@ -372,9 +362,37 @@ typedef struct ISAIPMIKCSDevice {
ISADevice dev;
int32_t isairq;
IPMIKCS kcs;
- IPMIFwInfo fwinfo;
+ uint32_t uuid;
} ISAIPMIKCSDevice;
+static void ipmi_kcs_get_fwinfo(IPMIInterface *ii, IPMIFwInfo *info)
+{
+ ISAIPMIKCSDevice *iik = ISA_IPMI_KCS(ii);
+
+ info->interface_name = "kcs";
+ info->interface_type = IPMI_SMBIOS_KCS;
+ info->ipmi_spec_major_revision = 2;
+ info->ipmi_spec_minor_revision = 0;
+ info->base_address = iik->kcs.io_base;
+ info->i2c_slave_address = iik->kcs.bmc->slave_addr;
+ info->register_length = iik->kcs.io_length;
+ info->register_spacing = 1;
+ info->memspace = IPMI_MEMSPACE_IO;
+ info->irq_type = IPMI_LEVEL_IRQ;
+ info->interrupt_number = iik->isairq;
+ info->uuid = iik->uuid;
+}
+
+static void ipmi_kcs_class_init(IPMIInterfaceClass *iic)
+{
+ iic->init = ipmi_kcs_init;
+ iic->set_atn = ipmi_kcs_set_atn;
+ iic->handle_rsp = ipmi_kcs_handle_rsp;
+ iic->handle_if_event = ipmi_kcs_handle_event;
+ iic->set_irq_enable = ipmi_kcs_set_irq_enable;
+ iic->get_fwinfo = ipmi_kcs_get_fwinfo;
+}
+
static void ipmi_isa_realize(DeviceState *dev, Error **errp)
{
ISADevice *isadev = ISA_DEVICE(dev);
@@ -387,6 +405,8 @@ static void ipmi_isa_realize(DeviceState *dev, Error **errp)
return;
}
+ iik->uuid = ipmi_next_uuid();
+
iik->kcs.bmc->intf = ii;
iic->init(ii, errp);
@@ -401,20 +421,6 @@ static void ipmi_isa_realize(DeviceState *dev, Error **errp)
qdev_set_legacy_instance_id(dev, iik->kcs.io_base, iik->kcs.io_length);
isa_register_ioport(isadev, &iik->kcs.io, iik->kcs.io_base);
-
- iik->fwinfo.interface_name = "kcs";
- iik->fwinfo.interface_type = IPMI_SMBIOS_KCS;
- iik->fwinfo.ipmi_spec_major_revision = 2;
- iik->fwinfo.ipmi_spec_minor_revision = 0;
- iik->fwinfo.base_address = iik->kcs.io_base;
- iik->fwinfo.i2c_slave_address = iik->kcs.bmc->slave_addr;
- iik->fwinfo.register_length = iik->kcs.io_length;
- iik->fwinfo.register_spacing = 1;
- iik->fwinfo.memspace = IPMI_MEMSPACE_IO;
- iik->fwinfo.irq_type = IPMI_LEVEL_IRQ;
- iik->fwinfo.interrupt_number = iik->isairq;
- iik->fwinfo.acpi_parent = "\\_SB.PCI0.ISA";
- ipmi_add_fwinfo(&iik->fwinfo, errp);
}
const VMStateDescription vmstate_ISAIPMIKCSDevice = {
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index 4f8ca45f6d..2a2d52e69a 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -637,30 +637,6 @@ static void ich9_lpc_realize(PCIDevice *d, Error **errp)
1);
}
-static void ich9_device_plug_cb(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
-{
- ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
-
- ich9_pm_device_plug_cb(&lpc->pm, dev, errp);
-}
-
-static void ich9_device_unplug_request_cb(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
-{
- ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
-
- ich9_pm_device_unplug_request_cb(&lpc->pm, dev, errp);
-}
-
-static void ich9_device_unplug_cb(HotplugHandler *hotplug_dev,
- DeviceState *dev, Error **errp)
-{
- ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
-
- ich9_pm_device_unplug_cb(&lpc->pm, dev, errp);
-}
-
static bool ich9_rst_cnt_needed(void *opaque)
{
ICH9LPCState *lpc = opaque;
@@ -703,6 +679,13 @@ static Property ich9_lpc_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
+static void ich9_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
+{
+ ICH9LPCState *s = ICH9_LPC_DEVICE(adev);
+
+ acpi_send_gpe_event(&s->pm.acpi_regs, s->pm.irq, ev);
+}
+
static void ich9_lpc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -726,10 +709,11 @@ static void ich9_lpc_class_init(ObjectClass *klass, void *data)
* pc_q35_init()
*/
dc->cannot_instantiate_with_device_add_yet = true;
- hc->plug = ich9_device_plug_cb;
- hc->unplug_request = ich9_device_unplug_request_cb;
- hc->unplug = ich9_device_unplug_cb;
+ hc->plug = ich9_pm_device_plug_cb;
+ hc->unplug_request = ich9_pm_device_unplug_request_cb;
+ hc->unplug = ich9_pm_device_unplug_cb;
adevc->ospm_status = ich9_pm_ospm_status;
+ adevc->send_event = ich9_send_gpe;
}
static const TypeInfo ich9_lpc_info = {
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 9e7de56829..6de2275986 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -354,8 +354,9 @@ static void pc_dimm_get_size(Object *obj, Visitor *v, const char *name,
int64_t value;
MemoryRegion *mr;
PCDIMMDevice *dimm = PC_DIMM(obj);
+ PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(obj);
- mr = host_memory_backend_get_memory(dimm->hostmem, errp);
+ mr = ddc->get_memory_region(dimm);
value = memory_region_size(mr);
visit_type_int(v, name, &value, errp);
@@ -399,6 +400,7 @@ static void pc_dimm_init(Object *obj)
static void pc_dimm_realize(DeviceState *dev, Error **errp)
{
PCDIMMDevice *dimm = PC_DIMM(dev);
+ PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
if (!dimm->hostmem) {
error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set");
@@ -411,6 +413,10 @@ static void pc_dimm_realize(DeviceState *dev, Error **errp)
dimm->node, nb_numa_nodes ? nb_numa_nodes : 1);
return;
}
+
+ if (ddc->realize) {
+ ddc->realize(dimm, errp);
+ }
}
static MemoryRegion *pc_dimm_get_memory_region(PCDIMMDevice *dimm)
diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c
index 5632743d36..f116f9c36d 100644
--- a/hw/misc/macio/mac_dbdma.c
+++ b/hw/misc/macio/mac_dbdma.c
@@ -42,6 +42,7 @@
#include "hw/ppc/mac_dbdma.h"
#include "qemu/main-loop.h"
#include "qemu/log.h"
+#include "sysemu/dma.h"
/* debug DBDMA */
//#define DEBUG_DBDMA
@@ -81,8 +82,8 @@ static void dbdma_cmdptr_load(DBDMA_channel *ch)
{
DBDMA_DPRINTF("dbdma_cmdptr_load 0x%08x\n",
ch->regs[DBDMA_CMDPTR_LO]);
- cpu_physical_memory_read(ch->regs[DBDMA_CMDPTR_LO],
- &ch->current, sizeof(dbdma_cmd));
+ dma_memory_read(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO],
+ &ch->current, sizeof(dbdma_cmd));
}
static void dbdma_cmdptr_save(DBDMA_channel *ch)
@@ -92,8 +93,8 @@ static void dbdma_cmdptr_save(DBDMA_channel *ch)
DBDMA_DPRINTF("xfer_status 0x%08x res_count 0x%04x\n",
le16_to_cpu(ch->current.xfer_status),
le16_to_cpu(ch->current.res_count));
- cpu_physical_memory_write(ch->regs[DBDMA_CMDPTR_LO],
- &ch->current, sizeof(dbdma_cmd));
+ dma_memory_write(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO],
+ &ch->current, sizeof(dbdma_cmd));
}
static void kill_channel(DBDMA_channel *ch)
@@ -353,7 +354,7 @@ static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
return;
}
- cpu_physical_memory_read(addr, &val, len);
+ dma_memory_read(&address_space_memory, addr, &val, len);
if (len == 2)
val = (val << 16) | (current->cmd_dep & 0x0000ffff);
@@ -398,7 +399,7 @@ static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
else if (len == 1)
val >>= 24;
- cpu_physical_memory_write(addr, &val, len);
+ dma_memory_write(&address_space_memory, addr, &val, len);
if (conditional_wait(ch))
goto wait;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 44e401ae99..0636642341 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1816,11 +1816,21 @@ static void ppc_spapr_init(MachineState *machine)
/* initialize hotplug memory address space */
if (machine->ram_size < machine->maxram_size) {
ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size;
+ /*
+ * Limit the number of hotpluggable memory slots to half the number
+ * slots that KVM supports, leaving the other half for PCI and other
+ * devices. However ensure that number of slots doesn't drop below 32.
+ */
+ int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 :
+ SPAPR_MAX_RAM_SLOTS;
- if (machine->ram_slots > SPAPR_MAX_RAM_SLOTS) {
+ if (max_memslots < SPAPR_MAX_RAM_SLOTS) {
+ max_memslots = SPAPR_MAX_RAM_SLOTS;
+ }
+ if (machine->ram_slots > max_memslots) {
error_report("Specified number of memory slots %"
PRIu64" exceeds max supported %d",
- machine->ram_slots, SPAPR_MAX_RAM_SLOTS);
+ machine->ram_slots, max_memslots);
exit(1);
}
@@ -2344,18 +2354,36 @@ static const TypeInfo spapr_machine_info = {
type_init(spapr_machine_register_##suffix)
/*
+ * pseries-2.7
+ */
+static void spapr_machine_2_7_instance_options(MachineState *machine)
+{
+}
+
+static void spapr_machine_2_7_class_options(MachineClass *mc)
+{
+ /* Defaults for the latest behaviour inherited from the base class */
+}
+
+DEFINE_SPAPR_MACHINE(2_7, "2.7", true);
+
+/*
* pseries-2.6
*/
+#define SPAPR_COMPAT_2_6 \
+ HW_COMPAT_2_6
+
static void spapr_machine_2_6_instance_options(MachineState *machine)
{
}
static void spapr_machine_2_6_class_options(MachineClass *mc)
{
- /* Defaults for the latest behaviour inherited from the base class */
+ spapr_machine_2_7_class_options(mc);
+ SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_6);
}
-DEFINE_SPAPR_MACHINE(2_6, "2.6", true);
+DEFINE_SPAPR_MACHINE(2_6, "2.6", false);
/*
* pseries-2.5
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 96bb0181a7..a3cc5722f1 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -17,6 +17,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
+#include "qemu/error-report.h"
#include "hw/hw.h"
#include "qemu/log.h"
#include "sysemu/kvm.h"
@@ -137,33 +138,92 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
return ret;
}
+static void spapr_tce_table_pre_save(void *opaque)
+{
+ sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque);
+
+ tcet->mig_table = tcet->table;
+ tcet->mig_nb_table = tcet->nb_table;
+
+ trace_spapr_iommu_pre_save(tcet->liobn, tcet->mig_nb_table,
+ tcet->bus_offset, tcet->page_shift);
+}
+
static int spapr_tce_table_post_load(void *opaque, int version_id)
{
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque);
+ uint32_t old_nb_table = tcet->nb_table;
+ uint64_t old_bus_offset = tcet->bus_offset;
+ uint32_t old_page_shift = tcet->page_shift;
if (tcet->vdev) {
spapr_vio_set_bypass(tcet->vdev, tcet->bypass);
}
+ if (tcet->mig_nb_table != tcet->nb_table) {
+ spapr_tce_table_disable(tcet);
+ }
+
+ if (tcet->mig_nb_table) {
+ if (!tcet->nb_table) {
+ spapr_tce_table_enable(tcet, old_page_shift, old_bus_offset,
+ tcet->mig_nb_table);
+ }
+
+ memcpy(tcet->table, tcet->mig_table,
+ tcet->nb_table * sizeof(tcet->table[0]));
+
+ free(tcet->mig_table);
+ tcet->mig_table = NULL;
+ }
+
+ trace_spapr_iommu_post_load(tcet->liobn, old_nb_table, tcet->nb_table,
+ tcet->bus_offset, tcet->page_shift);
+
return 0;
}
+static bool spapr_tce_table_ex_needed(void *opaque)
+{
+ sPAPRTCETable *tcet = opaque;
+
+ return tcet->bus_offset || tcet->page_shift != 0xC;
+}
+
+static const VMStateDescription vmstate_spapr_tce_table_ex = {
+ .name = "spapr_iommu_ex",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = spapr_tce_table_ex_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64(bus_offset, sPAPRTCETable),
+ VMSTATE_UINT32(page_shift, sPAPRTCETable),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static const VMStateDescription vmstate_spapr_tce_table = {
.name = "spapr_iommu",
.version_id = 2,
.minimum_version_id = 2,
+ .pre_save = spapr_tce_table_pre_save,
.post_load = spapr_tce_table_post_load,
.fields = (VMStateField []) {
/* Sanity check */
VMSTATE_UINT32_EQUAL(liobn, sPAPRTCETable),
- VMSTATE_UINT32_EQUAL(nb_table, sPAPRTCETable),
/* IOMMU state */
+ VMSTATE_UINT32(mig_nb_table, sPAPRTCETable),
VMSTATE_BOOL(bypass, sPAPRTCETable),
- VMSTATE_VARRAY_UINT32(table, sPAPRTCETable, nb_table, 0, vmstate_info_uint64, uint64_t),
+ VMSTATE_VARRAY_UINT32_ALLOC(mig_table, sPAPRTCETable, mig_nb_table, 0,
+ vmstate_info_uint64, uint64_t),
VMSTATE_END_OF_LIST()
},
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_spapr_tce_table_ex,
+ NULL
+ }
};
static MemoryRegionIOMMUOps spapr_iommu_ops = {
@@ -173,17 +233,16 @@ static MemoryRegionIOMMUOps spapr_iommu_ops = {
static int spapr_tce_table_realize(DeviceState *dev)
{
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
+ Object *tcetobj = OBJECT(tcet);
+ char tmp[32];
tcet->fd = -1;
- tcet->table = spapr_tce_alloc_table(tcet->liobn,
- tcet->page_shift,
- tcet->nb_table,
- &tcet->fd,
- tcet->need_vfio);
+ tcet->need_vfio = false;
+ snprintf(tmp, sizeof(tmp), "tce-root-%x", tcet->liobn);
+ memory_region_init(&tcet->root, tcetobj, tmp, UINT64_MAX);
- memory_region_init_iommu(&tcet->iommu, OBJECT(dev), &spapr_iommu_ops,
- "iommu-spapr",
- (uint64_t)tcet->nb_table << tcet->page_shift);
+ snprintf(tmp, sizeof(tmp), "tce-iommu-%x", tcet->liobn);
+ memory_region_init_iommu(&tcet->iommu, tcetobj, &spapr_iommu_ops, tmp, 0);
QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
@@ -225,14 +284,10 @@ void spapr_tce_set_need_vfio(sPAPRTCETable *tcet, bool need_vfio)
tcet->table = newtable;
}
-sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
- uint64_t bus_offset,
- uint32_t page_shift,
- uint32_t nb_table,
- bool need_vfio)
+sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn)
{
sPAPRTCETable *tcet;
- char tmp[64];
+ char tmp[32];
if (spapr_tce_find_by_liobn(liobn)) {
fprintf(stderr, "Attempted to create TCE table with duplicate"
@@ -240,16 +295,8 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
return NULL;
}
- if (!nb_table) {
- return NULL;
- }
-
tcet = SPAPR_TCE_TABLE(object_new(TYPE_SPAPR_TCE_TABLE));
tcet->liobn = liobn;
- tcet->bus_offset = bus_offset;
- tcet->page_shift = page_shift;
- tcet->nb_table = nb_table;
- tcet->need_vfio = need_vfio;
snprintf(tmp, sizeof(tmp), "tce-table-%x", liobn);
object_property_add_child(OBJECT(owner), tmp, OBJECT(tcet), NULL);
@@ -259,19 +306,58 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
return tcet;
}
+void spapr_tce_table_enable(sPAPRTCETable *tcet,
+ uint32_t page_shift, uint64_t bus_offset,
+ uint32_t nb_table)
+{
+ if (tcet->nb_table) {
+ error_report("Warning: trying to enable already enabled TCE table");
+ return;
+ }
+
+ tcet->bus_offset = bus_offset;
+ tcet->page_shift = page_shift;
+ tcet->nb_table = nb_table;
+ tcet->table = spapr_tce_alloc_table(tcet->liobn,
+ tcet->page_shift,
+ tcet->nb_table,
+ &tcet->fd,
+ tcet->need_vfio);
+
+ memory_region_set_size(&tcet->iommu,
+ (uint64_t)tcet->nb_table << tcet->page_shift);
+ memory_region_add_subregion(&tcet->root, tcet->bus_offset, &tcet->iommu);
+}
+
+void spapr_tce_table_disable(sPAPRTCETable *tcet)
+{
+ if (!tcet->nb_table) {
+ return;
+ }
+
+ memory_region_del_subregion(&tcet->root, &tcet->iommu);
+ memory_region_set_size(&tcet->iommu, 0);
+
+ spapr_tce_free_table(tcet->table, tcet->fd, tcet->nb_table);
+ tcet->fd = -1;
+ tcet->table = NULL;
+ tcet->bus_offset = 0;
+ tcet->page_shift = 0;
+ tcet->nb_table = 0;
+}
+
static void spapr_tce_table_unrealize(DeviceState *dev, Error **errp)
{
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
QLIST_REMOVE(tcet, list);
- spapr_tce_free_table(tcet->table, tcet->fd, tcet->nb_table);
- tcet->fd = -1;
+ spapr_tce_table_disable(tcet);
}
MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet)
{
- return &tcet->iommu;
+ return &tcet->root;
}
static void spapr_tce_reset(DeviceState *dev)
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index 856aec7f51..9f28fb3829 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -1310,7 +1310,6 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
PCIBus *bus;
uint64_t msi_window_size = 4096;
sPAPRTCETable *tcet;
- uint32_t nb_table;
if (sphb->index != (uint32_t)-1) {
hwaddr windows_base;
@@ -1462,18 +1461,15 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
}
}
- nb_table = sphb->dma_win_size >> SPAPR_TCE_PAGE_SHIFT;
- tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn,
- 0, SPAPR_TCE_PAGE_SHIFT, nb_table, false);
+ tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn);
if (!tcet) {
error_setg(errp, "Unable to create TCE table for %s",
sphb->dtbusname);
return;
}
- /* Register default 32bit DMA window */
- memory_region_add_subregion(&sphb->iommu_root, sphb->dma_win_addr,
- spapr_tce_get_iommu(tcet));
+ memory_region_add_subregion_overlap(&sphb->iommu_root, 0,
+ spapr_tce_get_iommu(tcet), 0);
sphb->msi = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
}
@@ -1489,8 +1485,25 @@ static int spapr_phb_children_reset(Object *child, void *opaque)
return 0;
}
+void spapr_phb_dma_reset(sPAPRPHBState *sphb)
+{
+ sPAPRTCETable *tcet = spapr_tce_find_by_liobn(sphb->dma_liobn);
+
+ if (tcet && tcet->nb_table) {
+ spapr_tce_table_disable(tcet);
+ }
+
+ /* Register default 32bit DMA window */
+ spapr_tce_table_enable(tcet, SPAPR_TCE_PAGE_SHIFT, sphb->dma_win_addr,
+ sphb->dma_win_size >> SPAPR_TCE_PAGE_SHIFT);
+}
+
static void spapr_phb_reset(DeviceState *qdev)
{
+ sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(qdev);
+
+ spapr_phb_dma_reset(sphb);
+
/* Reset the IOMMU state */
object_child_foreach(OBJECT(qdev), spapr_phb_children_reset, NULL);
@@ -1624,7 +1637,6 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
dc->reset = spapr_phb_reset;
dc->vmsd = &vmstate_spapr_pci;
set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
- dc->cannot_instantiate_with_device_add_yet = false;
hp->plug = spapr_phb_hot_plug_child;
hp->unplug = spapr_phb_hot_unplug_child;
}
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index d084aedadf..3d9b9c60f4 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -483,11 +483,9 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
memory_region_add_subregion_overlap(&dev->mrroot, 0, &dev->mrbypass, 1);
address_space_init(&dev->as, &dev->mrroot, qdev->id);
- dev->tcet = spapr_tce_new_table(qdev, liobn,
- 0,
- SPAPR_TCE_PAGE_SHIFT,
- pc->rtce_window_size >>
- SPAPR_TCE_PAGE_SHIFT, false);
+ dev->tcet = spapr_tce_new_table(qdev, liobn);
+ spapr_tce_table_enable(dev->tcet, SPAPR_TCE_PAGE_SHIFT, 0,
+ pc->rtce_window_size >> SPAPR_TCE_PAGE_SHIFT);
dev->tcet->vdev = dev;
memory_region_add_subregion_overlap(&dev->mrroot, 0,
spapr_tce_get_iommu(dev->tcet), 2);
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 4400718154..81cc5b0ae3 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -767,15 +767,11 @@ static inline bool vhost_needs_vring_endian(VirtIODevice *vdev)
if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
return false;
}
-#ifdef TARGET_IS_BIENDIAN
#ifdef HOST_WORDS_BIGENDIAN
return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_LITTLE;
#else
return vdev->device_endian == VIRTIO_DEVICE_ENDIAN_BIG;
#endif
-#else
- return false;
-#endif
}
static int vhost_virtqueue_set_vring_endian_legacy(struct vhost_dev *dev,
diff --git a/include/hw/acpi/acpi.h b/include/hw/acpi/acpi.h
index dc6ee00885..c717f157fe 100644
--- a/include/hw/acpi/acpi.h
+++ b/include/hw/acpi/acpi.h
@@ -23,6 +23,7 @@
#include "qemu/option.h"
#include "exec/memory.h"
#include "hw/irq.h"
+#include "hw/acpi/acpi_dev_interface.h"
/*
* current device naming scheme supports up to 256 memory devices
@@ -89,13 +90,6 @@
/* PM2_CNT */
#define ACPI_BITMASK_ARB_DISABLE 0x0001
-/* These values are part of guest ABI, and can not be changed */
-typedef enum {
- ACPI_PCI_HOTPLUG_STATUS = 2,
- ACPI_CPU_HOTPLUG_STATUS = 4,
- ACPI_MEMORY_HOTPLUG_STATUS = 8,
-} AcpiGPEStatusBits;
-
/* structs */
typedef struct ACPIPMTimer ACPIPMTimer;
typedef struct ACPIPM1EVT ACPIPM1EVT;
@@ -172,7 +166,7 @@ void acpi_gpe_ioport_writeb(ACPIREGS *ar, uint32_t addr, uint32_t val);
uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr);
void acpi_send_gpe_event(ACPIREGS *ar, qemu_irq irq,
- AcpiGPEStatusBits status);
+ AcpiEventStatusBits status);
void acpi_update_sci(ACPIREGS *acpi_regs, qemu_irq irq);
diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h
index f245f8d236..a0c4a336f2 100644
--- a/include/hw/acpi/acpi_dev_interface.h
+++ b/include/hw/acpi/acpi_dev_interface.h
@@ -4,6 +4,13 @@
#include "qom/object.h"
#include "qapi-types.h"
+/* These values are part of guest ABI, and can not be changed */
+typedef enum {
+ ACPI_PCI_HOTPLUG_STATUS = 2,
+ ACPI_CPU_HOTPLUG_STATUS = 4,
+ ACPI_MEMORY_HOTPLUG_STATUS = 8,
+} AcpiEventStatusBits;
+
#define TYPE_ACPI_DEVICE_IF "acpi-device-interface"
#define ACPI_DEVICE_IF_CLASS(klass) \
@@ -22,11 +29,14 @@ typedef struct AcpiDeviceIf {
Object Parent;
} AcpiDeviceIf;
+void acpi_send_event(DeviceState *dev, AcpiEventStatusBits event);
+
/**
* AcpiDeviceIfClass:
*
* ospm_status: returns status of ACPI device objects, reported
* via _OST method if device supports it.
+ * send_event: inject a specified event into guest
*
* Interface is designed for providing unified interface
* to generic ACPI functionality that could be used without
@@ -39,5 +49,6 @@ typedef struct AcpiDeviceIfClass {
/* <public> */
void (*ospm_status)(AcpiDeviceIf *adev, ACPIOSTInfoList ***list);
+ void (*send_event)(AcpiDeviceIf *adev, AcpiEventStatusBits ev);
} AcpiDeviceIfClass;
#endif
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 7eb51c7885..3952f85eeb 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -3,6 +3,7 @@
#include <glib.h>
#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
@@ -210,7 +211,7 @@ struct AcpiBuildTables {
GArray *table_data;
GArray *rsdp;
GArray *tcpalog;
- GArray *linker;
+ BIOSLinker *linker;
} AcpiBuildTables;
/**
@@ -252,6 +253,7 @@ void aml_append(Aml *parent_ctx, Aml *child);
/* non block AML object primitives */
Aml *aml_name(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
Aml *aml_name_decl(const char *name, Aml *val);
+Aml *aml_debug(void);
Aml *aml_return(Aml *val);
Aml *aml_int(const uint64_t val);
Aml *aml_arg(int pos);
@@ -358,12 +360,13 @@ Aml *aml_create_qword_field(Aml *srcbuf, Aml *index, const char *name);
Aml *aml_varpackage(uint32_t num_elements);
Aml *aml_touuid(const char *uuid);
Aml *aml_unicode(const char *str);
+Aml *aml_refof(Aml *arg);
Aml *aml_derefof(Aml *arg);
Aml *aml_sizeof(Aml *arg);
Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
void
-build_header(GArray *linker, GArray *table_data,
+build_header(BIOSLinker *linker, GArray *table_data,
AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
const char *oem_id, const char *oem_table_id);
void *acpi_data_push(GArray *table_data, unsigned size);
@@ -372,7 +375,7 @@ void acpi_add_table(GArray *table_offsets, GArray *table_data);
void acpi_build_tables_init(AcpiBuildTables *tables);
void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre);
void
-build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets,
+build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
const char *oem_id, const char *oem_table_id);
int
diff --git a/include/hw/acpi/bios-linker-loader.h b/include/hw/acpi/bios-linker-loader.h
index 82f1af6433..a05227eb30 100644
--- a/include/hw/acpi/bios-linker-loader.h
+++ b/include/hw/acpi/bios-linker-loader.h
@@ -3,23 +3,29 @@
#include <glib.h>
-GArray *bios_linker_loader_init(void);
+typedef struct BIOSLinker {
+ GArray *cmd_blob;
+ GArray *file_list;
+} BIOSLinker;
-void bios_linker_loader_alloc(GArray *linker,
- const char *file,
+BIOSLinker *bios_linker_loader_init(void);
+
+void bios_linker_loader_alloc(BIOSLinker *linker,
+ const char *file_name,
+ GArray *file_blob,
uint32_t alloc_align,
bool alloc_fseg);
-void bios_linker_loader_add_checksum(GArray *linker, const char *file,
- GArray *table,
- void *start, unsigned size,
- uint8_t *checksum);
+void bios_linker_loader_add_checksum(BIOSLinker *linker, const char *file,
+ unsigned start_offset, unsigned size,
+ unsigned checksum_offset);
-void bios_linker_loader_add_pointer(GArray *linker,
+void bios_linker_loader_add_pointer(BIOSLinker *linker,
const char *dest_file,
+ uint32_t dst_patched_offset,
+ uint8_t dst_patched_size,
const char *src_file,
- GArray *table, void *pointer,
- uint8_t pointer_size);
+ uint32_t src_offset);
-void *bios_linker_loader_cleanup(GArray *linker);
+void bios_linker_loader_cleanup(BIOSLinker *linker);
#endif
diff --git a/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h
index f22640e389..6fef67ec14 100644
--- a/include/hw/acpi/cpu_hotplug.h
+++ b/include/hw/acpi/cpu_hotplug.h
@@ -15,24 +15,19 @@
#include "hw/acpi/acpi.h"
#include "hw/acpi/pc-hotplug.h"
#include "hw/acpi/aml-build.h"
+#include "hw/hotplug.h"
typedef struct AcpiCpuHotplug {
MemoryRegion io;
uint8_t sts[ACPI_GPE_PROC_LEN];
} AcpiCpuHotplug;
-void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq,
- AcpiCpuHotplug *g, DeviceState *dev, Error **errp);
+void legacy_acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
+ AcpiCpuHotplug *g, DeviceState *dev, Error **errp);
-void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
- AcpiCpuHotplug *gpe_cpu, uint16_t base);
+void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
+ AcpiCpuHotplug *gpe_cpu, uint16_t base);
-#define CPU_EJECT_METHOD "CPEJ"
-#define CPU_MAT_METHOD "CPMA"
-#define CPU_ON_BITMAP "CPON"
-#define CPU_STATUS_METHOD "CPST"
-#define CPU_STATUS_MAP "PRS"
-#define CPU_SCAN_METHOD "PRSC"
-
-void build_cpu_hotplug_aml(Aml *ctx);
+void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
+ uint16_t io_base);
#endif
diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
index 63fa198145..bbd657c59b 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -69,10 +69,11 @@ extern const VMStateDescription vmstate_ich9_pm;
void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp);
-void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp);
-void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
- Error **errp);
-void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
+void ich9_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
+ Error **errp);
+void ich9_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev,
+ DeviceState *dev, Error **errp);
+void ich9_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
Error **errp);
void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list);
diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h
index 3a646b12e0..d2c7452397 100644
--- a/include/hw/acpi/memory_hotplug.h
+++ b/include/hw/acpi/memory_hotplug.h
@@ -32,9 +32,9 @@ typedef struct MemHotplugState {
void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner,
MemHotplugState *state);
-void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
+void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
DeviceState *dev, Error **errp);
-void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq,
+void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev,
MemHotplugState *mem_st,
DeviceState *dev, Error **errp);
void acpi_memory_unplug_cb(MemHotplugState *mem_st,
diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h
index 79a43923e8..04528b78d9 100644
--- a/include/hw/acpi/pcihp.h
+++ b/include/hw/acpi/pcihp.h
@@ -29,6 +29,7 @@
#include "hw/acpi/acpi.h"
#include "migration/vmstate.h"
+#include "hw/hotplug.h"
#define ACPI_PCIHP_IO_BASE_PROP "acpi-pcihp-io-base"
#define ACPI_PCIHP_IO_LEN_PROP "acpi-pcihp-io-len"
@@ -56,9 +57,9 @@ typedef struct AcpiPciHpState {
void acpi_pcihp_init(Object *owner, AcpiPciHpState *, PCIBus *root,
MemoryRegion *address_space_io, bool bridges_enabled);
-void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
+void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
DeviceState *dev, Error **errp);
-void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
+void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
DeviceState *dev, Error **errp);
/* Called on reset */
diff --git a/include/hw/ipmi/ipmi.h b/include/hw/ipmi/ipmi.h
index 74a2b5af96..91b83b5bb0 100644
--- a/include/hw/ipmi/ipmi.h
+++ b/include/hw/ipmi/ipmi.h
@@ -65,6 +65,40 @@ enum ipmi_op {
#define IPMI_SMBIOS_BT 0x03
#define IPMI_SMBIOS_SSIF 0x04
+/*
+ * Used for transferring information to interfaces that add
+ * entries to firmware tables.
+ */
+typedef struct IPMIFwInfo {
+ const char *interface_name;
+ int interface_type;
+ uint8_t ipmi_spec_major_revision;
+ uint8_t ipmi_spec_minor_revision;
+ uint8_t i2c_slave_address;
+ uint32_t uuid;
+
+ uint64_t base_address;
+ uint64_t register_length;
+ uint8_t register_spacing;
+ enum {
+ IPMI_MEMSPACE_IO,
+ IPMI_MEMSPACE_MEM32,
+ IPMI_MEMSPACE_MEM64,
+ IPMI_MEMSPACE_SMBUS
+ } memspace;
+
+ int interrupt_number;
+ enum {
+ IPMI_LEVEL_IRQ,
+ IPMI_EDGE_IRQ
+ } irq_type;
+} IPMIFwInfo;
+
+/*
+ * Called by each instantiated IPMI interface device to get it's uuid.
+ */
+uint32_t ipmi_next_uuid(void);
+
/* IPMI Interface types (KCS, SMIC, BT) are prefixed with this */
#define TYPE_IPMI_INTERFACE_PREFIX "ipmi-interface-"
@@ -127,6 +161,11 @@ typedef struct IPMIInterfaceClass {
* Set by the owner to hold the backend data for the interface.
*/
void *(*get_backend_data)(struct IPMIInterface *s);
+
+ /*
+ * Return the firmware info for a device.
+ */
+ void (*get_fwinfo)(struct IPMIInterface *s, IPMIFwInfo *info);
} IPMIInterfaceClass;
/*
@@ -168,41 +207,6 @@ typedef struct IPMIBmcClass {
*/
void ipmi_bmc_find_and_link(Object *obj, Object **bmc);
-/*
- * Used for transferring information to interfaces that add
- * entries to firmware tables.
- */
-typedef struct IPMIFwInfo {
- const char *interface_name;
- int interface_type;
- uint8_t ipmi_spec_major_revision;
- uint8_t ipmi_spec_minor_revision;
- uint8_t i2c_slave_address;
- uint32_t uuid;
-
- uint64_t base_address;
- uint64_t register_length;
- uint8_t register_spacing;
- enum {
- IPMI_MEMSPACE_IO,
- IPMI_MEMSPACE_MEM32,
- IPMI_MEMSPACE_MEM64,
- IPMI_MEMSPACE_SMBUS
- } memspace;
-
- int interrupt_number;
- enum {
- IPMI_LEVEL_IRQ,
- IPMI_EDGE_IRQ
- } irq_type;
-
- const char *acpi_parent;
-} IPMIFwInfo;
-
-void ipmi_add_fwinfo(IPMIFwInfo *info, Error **errp);
-IPMIFwInfo *ipmi_first_fwinfo(void);
-IPMIFwInfo *ipmi_next_fwinfo(IPMIFwInfo *current);
-
#ifdef IPMI_DEBUG
#define ipmi_debug(fs, ...) \
fprintf(stderr, "IPMI (%s): " fs, __func__, ##__VA_ARGS__)
diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h
index 517de9c366..60ee92b85a 100644
--- a/include/hw/mem/nvdimm.h
+++ b/include/hw/mem/nvdimm.h
@@ -24,6 +24,7 @@
#define QEMU_NVDIMM_H
#include "hw/mem/pc-dimm.h"
+#include "hw/acpi/bios-linker-loader.h"
#define NVDIMM_DEBUG 0
#define nvdimm_debug(fmt, ...) \
@@ -58,5 +59,5 @@ typedef struct AcpiNVDIMMState AcpiNVDIMMState;
void nvdimm_init_acpi_state(AcpiNVDIMMState *state, MemoryRegion *io,
FWCfgState *fw_cfg, Object *owner);
void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
- GArray *linker);
+ BIOSLinker *linker, GArray *dsm_dma_arrea);
#endif
diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
index 8cdc3266b3..67e92d8f7b 100644
--- a/include/hw/mem/pc-dimm.h
+++ b/include/hw/mem/pc-dimm.h
@@ -58,13 +58,17 @@ typedef struct PCDIMMDevice {
/**
* PCDIMMDeviceClass:
- * @get_memory_region: returns #MemoryRegion associated with @dimm
+ * @realize: called after common dimm is realized so that the dimm based
+ * devices get the chance to do specified operations.
+ * @get_memory_region: returns #MemoryRegion associated with @dimm which
+ * is directly mapped into the physical address space of guest
*/
typedef struct PCDIMMDeviceClass {
/* private */
DeviceClass parent_class;
/* public */
+ void (*realize)(PCDIMMDevice *dimm, Error **errp);
MemoryRegion *(*get_memory_region)(PCDIMMDevice *dimm);
} PCDIMMDeviceClass;
diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h
index 03ee006406..7848366b2a 100644
--- a/include/hw/pci-host/spapr.h
+++ b/include/hw/pci-host/spapr.h
@@ -147,4 +147,6 @@ static inline void spapr_phb_vfio_reset(DeviceState *qdev)
}
#endif
+void spapr_phb_dma_reset(sPAPRPHBState *sphb);
+
#endif /* __HW_SPAPR_PCI_H__ */
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 815d5eec45..971df3d0df 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -539,10 +539,12 @@ struct sPAPRTCETable {
uint64_t bus_offset;
uint32_t page_shift;
uint64_t *table;
+ uint32_t mig_nb_table;
+ uint64_t *mig_table;
bool bypass;
bool need_vfio;
int fd;
- MemoryRegion iommu;
+ MemoryRegion root, iommu;
struct VIOsPAPRDevice *vdev; /* for @bypass migration compatibility only */
QLIST_ENTRY(sPAPRTCETable) list;
};
@@ -561,11 +563,11 @@ void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq);
int spapr_h_cas_compose_response(sPAPRMachineState *sm,
target_ulong addr, target_ulong size,
bool cpu_update, bool memory_update);
-sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
- uint64_t bus_offset,
- uint32_t page_shift,
- uint32_t nb_table,
- bool need_vfio);
+sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn);
+void spapr_tce_table_enable(sPAPRTCETable *tcet,
+ uint32_t page_shift, uint64_t bus_offset,
+ uint32_t nb_table);
+void spapr_tce_table_disable(sPAPRTCETable *tcet);
void spapr_tce_set_need_vfio(sPAPRTCETable *tcet, bool need_vfio);
MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet);
diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h
index 8dc84f5203..4b28038146 100644
--- a/include/hw/virtio/virtio-access.h
+++ b/include/hw/virtio/virtio-access.h
@@ -17,9 +17,13 @@
#include "hw/virtio/virtio.h"
#include "exec/address-spaces.h"
+#if defined(TARGET_PPC64) || defined(TARGET_ARM)
+#define LEGACY_VIRTIO_IS_BIENDIAN 1
+#endif
+
static inline bool virtio_access_is_big_endian(VirtIODevice *vdev)
{
-#if defined(TARGET_IS_BIENDIAN)
+#if defined(LEGACY_VIRTIO_IS_BIENDIAN)
return virtio_is_big_endian(vdev);
#elif defined(TARGET_WORDS_BIGENDIAN)
if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 30ecc441de..6c65811aee 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -386,6 +386,16 @@ extern const VMStateInfo vmstate_info_bitmap;
.offset = vmstate_offset_pointer(_state, _field, _type), \
}
+#define VMSTATE_VARRAY_UINT32_ALLOC(_field, _state, _field_num, _version, _info, _type) {\
+ .name = (stringify(_field)), \
+ .version_id = (_version), \
+ .num_offset = vmstate_offset_value(_state, _field_num, uint32_t),\
+ .info = &(_info), \
+ .size = sizeof(_type), \
+ .flags = VMS_VARRAY_UINT32|VMS_POINTER|VMS_ALLOC, \
+ .offset = vmstate_offset_pointer(_state, _field, _type), \
+}
+
#define VMSTATE_VARRAY_UINT16_UNSAFE(_field, _state, _field_num, _version, _info, _type) {\
.name = (stringify(_field)), \
.version_id = (_version), \
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 65569ed438..ad6f837bb4 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -527,4 +527,5 @@ int kvm_set_one_reg(CPUState *cs, uint64_t id, void *source);
* Returns: 0 on success, or a negative errno on failure.
*/
int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target);
+int kvm_get_max_memslots(void);
#endif
diff --git a/kvm-all.c b/kvm-all.c
index d317dcb33e..fbd2d93188 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -126,6 +126,13 @@ static const KVMCapabilityInfo kvm_required_capabilites[] = {
KVM_CAP_LAST_INFO
};
+int kvm_get_max_memslots(void)
+{
+ KVMState *s = KVM_STATE(current_machine->accelerator);
+
+ return s->nr_slots;
+}
+
static KVMSlot *kvm_get_free_slot(KVMMemoryListener *kml)
{
KVMState *s = kvm_state;
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 401955f825..17d80510da 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -29,8 +29,6 @@
# define TARGET_LONG_BITS 32
#endif
-#define TARGET_IS_BIENDIAN 1
-
#define CPUArchState struct CPUARMState
#include "qemu-common.h"
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 98a24a50f3..cb8b9122f3 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -28,8 +28,6 @@
#define TARGET_LONG_BITS 64
#define TARGET_PAGE_BITS 12
-#define TARGET_IS_BIENDIAN 1
-
/* Note that the official physical address space bits is 62-M where M
is implementation dependent. I've not looked up M for the set of
cpus we emulate at the system level. */
@@ -959,7 +957,6 @@ struct CPUPPCState {
ppc_slb_t slb[MAX_SLB_ENTRIES];
int32_t slb_nr;
/* tcg TLB needs flush (deferred slb inval instruction typically) */
- uint32_t tlb_need_flush;
#endif
/* segment registers */
hwaddr htab_base;
@@ -985,6 +982,7 @@ struct CPUPPCState {
target_ulong pb[4];
bool tlb_dirty; /* Set to non-zero when modifying TLB */
bool kvm_sw_tlb; /* non-zero if KVM SW TLB API is active */
+ uint32_t tlb_need_flush; /* Delayed flush needed */
#endif
/* Other registers */
@@ -1050,6 +1048,10 @@ struct CPUPPCState {
hwaddr mpic_iack;
/* true when the external proxy facility mode is enabled */
bool mpic_proxy;
+ /* set when the processor has an HV mode, thus HV priv
+ * instructions and SPRs are diallowed if MSR:HV is 0
+ */
+ bool has_hv_mode;
#endif
/* Those resources are used only during code translation */
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index a37009eb25..30e960e30b 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -709,8 +709,12 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
}
}
#endif
- /* XXX: we don't use hreg_store_msr here as already have treated
- * any special case that could occur. Just store MSR and update hflags
+ /* We don't use hreg_store_msr here as already have treated
+ * any special case that could occur. Just store MSR and update hflags
+ *
+ * Note: We *MUST* not use hreg_store_msr() as-is anyway because it
+ * will prevent setting of the HV bit which some exceptions might need
+ * to do.
*/
env->msr = new_msr & env->msr_mask;
hreg_compute_hflags(env);
diff --git a/target-ppc/fpu_helper.c b/target-ppc/fpu_helper.c
index b67ebca126..6fd56a868d 100644
--- a/target-ppc/fpu_helper.c
+++ b/target-ppc/fpu_helper.c
@@ -1442,7 +1442,7 @@ static inline uint32_t efststeq(CPUPPCState *env, uint32_t op1, uint32_t op2)
#define HELPER_SINGLE_SPE_CMP(name) \
uint32_t helper_e##name(CPUPPCState *env, uint32_t op1, uint32_t op2) \
{ \
- return e##name(env, op1, op2) << 2; \
+ return e##name(env, op1, op2); \
}
/* efststlt */
HELPER_SINGLE_SPE_CMP(fststlt);
diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 0526322f4d..f4410a8369 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -550,6 +550,7 @@ DEF_HELPER_FLAGS_2(tlbiva, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_3(store_slb, TCG_CALL_NO_RWG, void, env, tl, tl)
DEF_HELPER_2(load_slb_esid, tl, env, tl)
DEF_HELPER_2(load_slb_vsid, tl, env, tl)
+DEF_HELPER_2(find_slb_vsid, tl, env, tl)
DEF_HELPER_FLAGS_1(slbia, TCG_CALL_NO_RWG, void, env)
DEF_HELPER_FLAGS_2(slbie, TCG_CALL_NO_RWG, void, env, tl)
#endif
diff --git a/target-ppc/helper_regs.h b/target-ppc/helper_regs.h
index 57da931e3c..8fc09344db 100644
--- a/target-ppc/helper_regs.h
+++ b/target-ppc/helper_regs.h
@@ -95,7 +95,7 @@ static inline void hreg_compute_hflags(CPUPPCState *env)
/* We 'forget' FE0 & FE1: we'll never generate imprecise exceptions */
hflags_mask = (1 << MSR_VR) | (1 << MSR_AP) | (1 << MSR_SA) |
(1 << MSR_PR) | (1 << MSR_FP) | (1 << MSR_SE) | (1 << MSR_BE) |
- (1 << MSR_LE) | (1 << MSR_VSX);
+ (1 << MSR_LE) | (1 << MSR_VSX) | (1 << MSR_IR) | (1 << MSR_DR);
hflags_mask |= (1ULL << MSR_CM) | (1ULL << MSR_SF) | MSR_HVB;
hreg_compute_mem_idx(env);
env->hflags = env->msr & hflags_mask;
@@ -114,8 +114,8 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
excp = 0;
value &= env->msr_mask;
#if !defined(CONFIG_USER_ONLY)
- if (!alter_hv) {
- /* mtmsr cannot alter the hypervisor state */
+ /* Neither mtmsr nor guest state can alter HV */
+ if (!alter_hv || !(env->msr & MSR_HVB)) {
value &= ~MSR_HVB;
value |= env->msr & MSR_HVB;
}
@@ -151,7 +151,7 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
return excp;
}
-#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
+#if !defined(CONFIG_USER_ONLY)
static inline void check_tlb_flush(CPUPPCState *env)
{
CPUState *cs = CPU(ppc_env_get_cpu(env));
diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c
index ea6e99acd1..668da5e226 100644
--- a/target-ppc/mmu-hash64.c
+++ b/target-ppc/mmu-hash64.c
@@ -219,6 +219,24 @@ static int ppc_load_slb_vsid(PowerPCCPU *cpu, target_ulong rb,
return 0;
}
+static int ppc_find_slb_vsid(PowerPCCPU *cpu, target_ulong rb,
+ target_ulong *rt)
+{
+ CPUPPCState *env = &cpu->env;
+ ppc_slb_t *slb;
+
+ if (!msr_is_64bit(env, env->msr)) {
+ rb &= 0xffffffff;
+ }
+ slb = slb_lookup(cpu, rb);
+ if (slb == NULL) {
+ *rt = (target_ulong)-1ul;
+ } else {
+ *rt = slb->vsid;
+ }
+ return 0;
+}
+
void helper_store_slb(CPUPPCState *env, target_ulong rb, target_ulong rs)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
@@ -241,6 +259,18 @@ target_ulong helper_load_slb_esid(CPUPPCState *env, target_ulong rb)
return rt;
}
+target_ulong helper_find_slb_vsid(CPUPPCState *env, target_ulong rb)
+{
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
+ target_ulong rt = 0;
+
+ if (ppc_find_slb_vsid(cpu, rb, &rt) < 0) {
+ helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
+ POWERPC_EXCP_INVAL);
+ }
+ return rt;
+}
+
target_ulong helper_load_slb_vsid(CPUPPCState *env, target_ulong rb)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c
index 1499af72a0..485d5b8fde 100644
--- a/target-ppc/mmu_helper.c
+++ b/target-ppc/mmu_helper.c
@@ -512,18 +512,20 @@ static inline int get_segment_6xx_tlb(CPUPPCState *env, mmu_ctx_t *ctx,
/* Software TLB search */
ret = ppc6xx_tlb_check(env, ctx, eaddr, rw, type);
#if defined(DUMP_PAGE_TABLES)
- if (qemu_log_mask(CPU_LOG_MMU)) {
+ if (qemu_loglevel_mask(CPU_LOG_MMU)) {
+ CPUState *cs = ENV_GET_CPU(env);
hwaddr curaddr;
uint32_t a0, a1, a2, a3;
qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
- "\n", sdr, mask + 0x80);
- for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
+ "\n", env->htab_base, env->htab_mask + 0x80);
+ for (curaddr = env->htab_base;
+ curaddr < (env->htab_base + env->htab_mask + 0x80);
curaddr += 16) {
- a0 = ldl_phys(curaddr);
- a1 = ldl_phys(curaddr + 4);
- a2 = ldl_phys(curaddr + 8);
- a3 = ldl_phys(curaddr + 12);
+ a0 = ldl_phys(cs->as, curaddr);
+ a1 = ldl_phys(cs->as, curaddr + 4);
+ a2 = ldl_phys(cs->as, curaddr + 8);
+ a3 = ldl_phys(cs->as, curaddr + 12);
if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
curaddr, a0, a1, a2, a3);
@@ -894,9 +896,9 @@ static int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
mask = ~(booke206_tlb_to_page_size(env, tlb) - 1);
LOG_SWTLB("%s: TLB ADDR=0x" TARGET_FMT_lx " PID=0x%x MAS1=0x%x MAS2=0x%"
- PRIx64 " mask=0x" TARGET_FMT_lx " MAS7_3=0x%" PRIx64 " MAS8=%x\n",
- __func__, address, pid, tlb->mas1, tlb->mas2, mask, tlb->mas7_3,
- tlb->mas8);
+ PRIx64 " mask=0x%" HWADDR_PRIx " MAS7_3=0x%" PRIx64 " MAS8=0x%"
+ PRIx32 "\n", __func__, address, pid, tlb->mas1, tlb->mas2, mask,
+ tlb->mas7_3, tlb->mas8);
/* Check PID */
tlb_pid = (tlb->mas1 & MAS1_TID_MASK) >> MAS1_TID_SHIFT;
@@ -1746,6 +1748,9 @@ static inline void dump_store_bat(CPUPPCState *env, char ID, int ul, int nr,
void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value)
{
target_ulong mask;
+#if defined(FLUSH_ALL_TLBS)
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
+#endif
dump_store_bat(env, 'I', 0, nr, value);
if (env->IBAT[0][nr] != value) {
@@ -1764,7 +1769,7 @@ void helper_store_ibatu(CPUPPCState *env, uint32_t nr, target_ulong value)
#if !defined(FLUSH_ALL_TLBS)
do_invalidate_BAT(env, env->IBAT[0][nr], mask);
#else
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
#endif
}
}
@@ -1778,6 +1783,9 @@ void helper_store_ibatl(CPUPPCState *env, uint32_t nr, target_ulong value)
void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value)
{
target_ulong mask;
+#if defined(FLUSH_ALL_TLBS)
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
+#endif
dump_store_bat(env, 'D', 0, nr, value);
if (env->DBAT[0][nr] != value) {
@@ -1796,7 +1804,7 @@ void helper_store_dbatu(CPUPPCState *env, uint32_t nr, target_ulong value)
#if !defined(FLUSH_ALL_TLBS)
do_invalidate_BAT(env, env->DBAT[0][nr], mask);
#else
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
#endif
}
}
@@ -1811,6 +1819,7 @@ void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
{
target_ulong mask;
#if defined(FLUSH_ALL_TLBS)
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
int do_inval;
#endif
@@ -1843,7 +1852,7 @@ void helper_store_601_batu(CPUPPCState *env, uint32_t nr, target_ulong value)
}
#if defined(FLUSH_ALL_TLBS)
if (do_inval) {
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
}
#endif
}
@@ -1854,6 +1863,7 @@ void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
#if !defined(FLUSH_ALL_TLBS)
target_ulong mask;
#else
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
int do_inval;
#endif
@@ -1882,7 +1892,7 @@ void helper_store_601_batl(CPUPPCState *env, uint32_t nr, target_ulong value)
env->DBAT[1][nr] = value;
#if defined(FLUSH_ALL_TLBS)
if (do_inval) {
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
}
#endif
}
@@ -1925,8 +1935,8 @@ void ppc_tlb_invalidate_all(CPUPPCState *env)
case POWERPC_MMU_2_06a:
case POWERPC_MMU_2_07:
case POWERPC_MMU_2_07a:
- env->tlb_need_flush = 0;
#endif /* defined(TARGET_PPC64) */
+ env->tlb_need_flush = 0;
tlb_flush(CPU(cpu), 1);
break;
default:
@@ -1939,9 +1949,6 @@ void ppc_tlb_invalidate_all(CPUPPCState *env)
void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
{
#if !defined(FLUSH_ALL_TLBS)
- PowerPCCPU *cpu = ppc_env_get_cpu(env);
- CPUState *cs;
-
addr &= TARGET_PAGE_MASK;
switch (env->mmu_model) {
case POWERPC_MMU_SOFT_6xx:
@@ -1953,28 +1960,12 @@ void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr)
break;
case POWERPC_MMU_32B:
case POWERPC_MMU_601:
- /* tlbie invalidate TLBs for all segments */
- addr &= ~((target_ulong)-1ULL << 28);
- cs = CPU(cpu);
- /* XXX: this case should be optimized,
- * giving a mask to tlb_flush_page
+ /* Actual CPUs invalidate entire congruence classes based on the
+ * geometry of their TLBs and some OSes take that into account,
+ * we just mark the TLB to be flushed later (context synchronizing
+ * event or sync instruction on 32-bit).
*/
- tlb_flush_page(cs, addr | (0x0 << 28));
- tlb_flush_page(cs, addr | (0x1 << 28));
- tlb_flush_page(cs, addr | (0x2 << 28));
- tlb_flush_page(cs, addr | (0x3 << 28));
- tlb_flush_page(cs, addr | (0x4 << 28));
- tlb_flush_page(cs, addr | (0x5 << 28));
- tlb_flush_page(cs, addr | (0x6 << 28));
- tlb_flush_page(cs, addr | (0x7 << 28));
- tlb_flush_page(cs, addr | (0x8 << 28));
- tlb_flush_page(cs, addr | (0x9 << 28));
- tlb_flush_page(cs, addr | (0xA << 28));
- tlb_flush_page(cs, addr | (0xB << 28));
- tlb_flush_page(cs, addr | (0xC << 28));
- tlb_flush_page(cs, addr | (0xD << 28));
- tlb_flush_page(cs, addr | (0xE << 28));
- tlb_flush_page(cs, addr | (0xF << 28));
+ env->tlb_need_flush = 1;
break;
#if defined(TARGET_PPC64)
case POWERPC_MMU_64B:
@@ -2040,13 +2031,12 @@ target_ulong helper_load_sr(CPUPPCState *env, target_ulong sr_num)
void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
{
- PowerPCCPU *cpu = ppc_env_get_cpu(env);
-
qemu_log_mask(CPU_LOG_MMU,
"%s: reg=%d " TARGET_FMT_lx " " TARGET_FMT_lx "\n", __func__,
(int)srnum, value, env->sr[srnum]);
#if defined(TARGET_PPC64)
if (env->mmu_model & POWERPC_MMU_64) {
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
uint64_t esid, vsid;
/* ESID = srnum */
@@ -2075,7 +2065,7 @@ void helper_store_sr(CPUPPCState *env, target_ulong srnum, target_ulong value)
}
}
#else
- tlb_flush(CPU(cpu), 1);
+ env->tlb_need_flush = 1;
#endif
}
}
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 123e42fe6b..b6894751e8 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -193,6 +193,7 @@ struct DisasContext {
uint32_t exception;
/* Routine used to access memory */
bool pr, hv;
+ bool lazy_tlb_flush;
int mem_idx;
int access_type;
/* Translation flags */
@@ -3046,10 +3047,13 @@ static void gen_std(DisasContext *ctx)
rs = rS(ctx->opcode);
if ((ctx->opcode & 0x3) == 0x2) { /* stq */
-
bool legal_in_user_mode = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
bool le_is_supported = (ctx->insns_flags2 & PPC2_LSQ_ISA207) != 0;
+ if (!(ctx->insns_flags & PPC_64BX)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
+ }
+
if (!legal_in_user_mode && ctx->pr) {
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
return;
@@ -3290,12 +3294,17 @@ static void gen_eieio(DisasContext *ctx)
{
}
-#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
+#if !defined(CONFIG_USER_ONLY)
static inline void gen_check_tlb_flush(DisasContext *ctx)
{
- TCGv_i32 t = tcg_temp_new_i32();
- TCGLabel *l = gen_new_label();
+ TCGv_i32 t;
+ TCGLabel *l;
+ if (!ctx->lazy_tlb_flush) {
+ return;
+ }
+ l = gen_new_label();
+ t = tcg_temp_new_i32();
tcg_gen_ld_i32(t, cpu_env, offsetof(CPUPPCState, tlb_need_flush));
tcg_gen_brcondi_i32(TCG_COND_EQ, t, 0, l);
gen_helper_check_tlb_flush(cpu_env);
@@ -3475,10 +3484,14 @@ static void gen_sync(DisasContext *ctx)
uint32_t l = (ctx->opcode >> 21) & 3;
/*
- * For l == 2, it's a ptesync, We need to check for a pending TLB flush.
- * This can only happen in kernel mode however so check MSR_PR as well.
+ * We may need to check for a pending TLB flush.
+ *
+ * We do this on ptesync (l == 2) on ppc64 and any sync pn ppc32.
+ *
+ * Additionally, this can only happen in kernel mode however so
+ * check MSR_PR as well.
*/
- if (l == 2 && !ctx->pr) {
+ if (((l == 2) || !(ctx->insns_flags & PPC_64B)) && !ctx->pr) {
gen_check_tlb_flush(ctx);
}
}
@@ -4108,7 +4121,7 @@ static void gen_hrfid(DisasContext *ctx)
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
/* Restore CPU state */
- if (unlikely(!ctx->hv)) {
+ if (unlikely(ctx->pr || !ctx->hv)) {
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
return;
}
@@ -4338,7 +4351,10 @@ static inline void gen_op_mfspr(DisasContext *ctx)
qemu_log("Trying to read invalid spr %d (0x%03x) at "
TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
}
- gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
+ /* Only generate an exception in user space, otherwise this is a nop */
+ if (ctx->pr) {
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
+ }
}
}
@@ -4490,7 +4506,11 @@ static void gen_mtspr(DisasContext *ctx)
}
fprintf(stderr, "Trying to write invalid spr %d (0x%03x) at "
TARGET_FMT_lx "\n", sprn, sprn, ctx->nip - 4);
- gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
+
+ /* Only generate an exception in user space, otherwise this is a nop */
+ if (ctx->pr) {
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
+ }
}
}
@@ -4834,6 +4854,31 @@ static void gen_slbmfev(DisasContext *ctx)
cpu_gpr[rB(ctx->opcode)]);
#endif
}
+
+static void gen_slbfee_(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
+#else
+ TCGLabel *l1, *l2;
+
+ if (unlikely(ctx->pr)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
+ return;
+ }
+ gen_helper_find_slb_vsid(cpu_gpr[rS(ctx->opcode)], cpu_env,
+ cpu_gpr[rB(ctx->opcode)]);
+ l1 = gen_new_label();
+ l2 = gen_new_label();
+ tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
+ tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rS(ctx->opcode)], -1, l1);
+ tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
+ tcg_gen_br(l2);
+ gen_set_label(l1);
+ tcg_gen_movi_tl(cpu_gpr[rS(ctx->opcode)], 0);
+ gen_set_label(l2);
+#endif
+}
#endif /* defined(TARGET_PPC64) */
/*** Lookaside buffer management ***/
@@ -4845,7 +4890,7 @@ static void gen_tlbia(DisasContext *ctx)
#if defined(CONFIG_USER_ONLY)
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
- if (unlikely(ctx->pr)) {
+ if (unlikely(ctx->pr || !ctx->hv)) {
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
return;
}
@@ -4913,7 +4958,7 @@ static void gen_slbia(DisasContext *ctx)
#if defined(CONFIG_USER_ONLY)
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
#else
- if (unlikely(ctx->pr || !ctx->hv)) {
+ if (unlikely(ctx->pr)) {
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
return;
}
@@ -9931,7 +9976,7 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC),
#if defined(TARGET_PPC64)
GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B),
#endif
-GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC),
+GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001EF801, PPC_MISC),
GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000000, PPC_MISC),
GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE),
GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE),
@@ -9959,6 +10004,7 @@ GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x001F0001, PPC_SEGMENT_64B),
GEN_HANDLER2(slbmfee, "slbmfee", 0x1F, 0x13, 0x1C, 0x001F0001, PPC_SEGMENT_64B),
GEN_HANDLER2(slbmfev, "slbmfev", 0x1F, 0x13, 0x1A, 0x001F0001, PPC_SEGMENT_64B),
+GEN_HANDLER2(slbfee_, "slbfee.", 0x1F, 0x13, 0x1E, 0x001F0000, PPC_SEGMENT_64B),
#endif
GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA),
/* XXX Those instructions will need to be handled differently for
@@ -9967,7 +10013,7 @@ GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x001F0001, PPC_MEM_TLBIE),
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x001F0001, PPC_MEM_TLBIE),
GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC),
#if defined(TARGET_PPC64)
-GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI),
+GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x031FFC01, PPC_SLBI),
GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI),
#endif
GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN),
@@ -11478,8 +11524,10 @@ void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
ctx.exception = POWERPC_EXCP_NONE;
ctx.spr_cb = env->spr_cb;
ctx.pr = msr_pr;
- ctx.hv = !msr_pr && msr_hv;
ctx.mem_idx = env->dmmu_idx;
+#if !defined(CONFIG_USER_ONLY)
+ ctx.hv = msr_hv || !env->has_hv_mode;
+#endif
ctx.insns_flags = env->insns_flags;
ctx.insns_flags2 = env->insns_flags2;
ctx.access_type = -1;
@@ -11489,6 +11537,11 @@ void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
ctx.sf_mode = msr_is_64bit(env, env->msr);
ctx.has_cfar = !!(env->flags & POWERPC_FLAG_CFAR);
#endif
+ if (env->mmu_model == POWERPC_MMU_32B ||
+ env->mmu_model == POWERPC_MMU_601 ||
+ (env->mmu_model & POWERPC_MMU_64B))
+ ctx.lazy_tlb_flush = true;
+
ctx.fpu_enabled = msr_fp;
if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
ctx.spe_enabled = msr_spe;
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 83010768ea..a1db5009c4 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -8024,6 +8024,21 @@ static void gen_spr_power8_book4(CPUPPCState *env)
#endif
}
+static void gen_spr_power7_book4(CPUPPCState *env)
+{
+ /* Add a number of P7 book4 registers */
+#if !defined(CONFIG_USER_ONLY)
+ spr_register_kvm(env, SPR_ACOP, "ACOP",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_ACOP, 0);
+ spr_register_kvm(env, SPR_BOOKS_PID, "PID",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_generic,
+ KVM_REG_PPC_PID, 0);
+#endif
+}
+
static void init_proc_book3s_64(CPUPPCState *env, int version)
{
gen_spr_ne_601(env);
@@ -8066,6 +8081,9 @@ static void init_proc_book3s_64(CPUPPCState *env, int version)
gen_spr_power6_common(env);
gen_spr_power6_dbg(env);
}
+ if (version == BOOK3S_CPU_POWER7) {
+ gen_spr_power7_book4(env);
+ }
if (version >= BOOK3S_CPU_POWER8) {
gen_spr_power8_tce_address_control(env);
gen_spr_power8_ids(env);
@@ -8359,7 +8377,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ |
PPC_MEM_SYNC | PPC_MEM_EIEIO |
PPC_MEM_TLBIE | PPC_MEM_TLBSYNC |
- PPC_64B | PPC_64H | PPC_ALTIVEC |
+ PPC_64B | PPC_64H | PPC_64BX | PPC_ALTIVEC |
PPC_SEGMENT_64B | PPC_SLBI |
PPC_POPCNTB | PPC_POPCNTWD;
pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX | PPC2_ISA205 |
@@ -8450,6 +8468,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
PPC2_TM;
pcc->msr_mask = (1ull << MSR_SF) |
+ (1ull << MSR_SHV) |
(1ull << MSR_TM) |
(1ull << MSR_VR) |
(1ull << MSR_VSX) |
@@ -9854,10 +9873,7 @@ static void ppc_cpu_reset(CPUState *s)
pcc->parent_reset(s);
msr = (target_ulong)0;
- if (0) {
- /* XXX: find a suitable condition to enable the hypervisor mode */
- msr |= (target_ulong)MSR_HVB;
- }
+ msr |= (target_ulong)MSR_HVB;
msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
msr |= (target_ulong)1 << MSR_EP;
@@ -9958,6 +9974,19 @@ static void ppc_cpu_initfn(Object *obj)
env->bfd_mach = pcc->bfd_mach;
env->check_pow = pcc->check_pow;
+ /* Mark HV mode as supported if the CPU has an MSR_HV bit
+ * in the msr_mask. The mask can later be cleared by PAPR
+ * mode but the hv mode support will remain, thus enforcing
+ * that we cannot use priv. instructions in guest in PAPR
+ * mode. For 970 we currently simply don't set HV in msr_mask
+ * thus simulating an "Apple mode" 970. If we ever want to
+ * support 970 HV mode, we'll have to add a processor attribute
+ * of some sort.
+ */
+#if !defined(CONFIG_USER_ONLY)
+ env->has_hv_mode = !!(env->msr_mask & MSR_HVB);
+#endif
+
#if defined(TARGET_PPC64)
if (pcc->sps) {
env->sps = *pcc->sps;
diff --git a/tests/acpi-test-data/pc/DSDT b/tests/acpi-test-data/pc/DSDT
index 9d1274d3c2..8b4f1a09b8 100644
--- a/tests/acpi-test-data/pc/DSDT
+++ b/tests/acpi-test-data/pc/DSDT
Binary files differ
diff --git a/tests/acpi-test-data/pc/DSDT.bridge b/tests/acpi-test-data/pc/DSDT.bridge
index cf48c62aa7..0d09b5cc61 100644
--- a/tests/acpi-test-data/pc/DSDT.bridge
+++ b/tests/acpi-test-data/pc/DSDT.bridge
Binary files differ
diff --git a/tests/acpi-test-data/q35/DSDT b/tests/acpi-test-data/q35/DSDT
index 1c089c34b0..67445428d9 100644
--- a/tests/acpi-test-data/q35/DSDT
+++ b/tests/acpi-test-data/q35/DSDT
Binary files differ
diff --git a/tests/acpi-test-data/q35/DSDT.bridge b/tests/acpi-test-data/q35/DSDT.bridge
index b29fcda0bb..e85f5b1af9 100644
--- a/tests/acpi-test-data/q35/DSDT.bridge
+++ b/tests/acpi-test-data/q35/DSDT.bridge
Binary files differ
diff --git a/tests/bios-tables-test.c b/tests/bios-tables-test.c
index 03528140c1..f0493f8c69 100644
--- a/tests/bios-tables-test.c
+++ b/tests/bios-tables-test.c
@@ -464,7 +464,6 @@ static GArray *load_expected_aml(test_data *data)
{
int i;
AcpiSdtTable *sdt;
- gchar *aml_file = NULL;
GError *error = NULL;
gboolean ret;
@@ -472,6 +471,7 @@ static GArray *load_expected_aml(test_data *data)
for (i = 0; i < data->tables->len; ++i) {
AcpiSdtTable exp_sdt;
uint32_t signature;
+ gchar *aml_file = NULL;
const char *ext = data->variant ? data->variant : "";
sdt = &g_array_index(data->tables, AcpiSdtTable, i);
@@ -484,13 +484,21 @@ static GArray *load_expected_aml(test_data *data)
try_again:
aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine,
(gchar *)&signature, ext);
- if (data->variant && !g_file_test(aml_file, G_FILE_TEST_EXISTS)) {
- g_free(aml_file);
+ if (getenv("V")) {
+ fprintf(stderr, "\nLooking for expected file '%s'\n", aml_file);
+ }
+ if (g_file_test(aml_file, G_FILE_TEST_EXISTS)) {
+ exp_sdt.aml_file = aml_file;
+ } else if (*ext != '\0') {
+ /* try fallback to generic (extention less) expected file */
ext = "";
+ g_free(aml_file);
goto try_again;
}
- exp_sdt.aml_file = aml_file;
- g_assert(g_file_test(aml_file, G_FILE_TEST_EXISTS));
+ g_assert(exp_sdt.aml_file);
+ if (getenv("V")) {
+ fprintf(stderr, "\nUsing expected file '%s'\n", aml_file);
+ }
ret = g_file_get_contents(aml_file, &exp_sdt.aml,
&exp_sdt.aml_len, &error);
g_assert(ret);
diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index 2fd2ca3057..134dc6fff4 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -28,8 +28,7 @@ make-archive-maybe = $(if $(wildcard $1/*), \
" ARCHIVE $(notdir $2)"))
CUR_TIME := $(shell date +%Y-%m-%d-%H.%M.%S.$$$$)
-# Makes the definition constant after the first expansion
-DOCKER_SRC_COPY = $(eval DOCKER_SRC_COPY := docker-src.$(CUR_TIME))$(DOCKER_SRC_COPY)
+DOCKER_SRC_COPY := docker-src.$(CUR_TIME)
$(DOCKER_SRC_COPY):
@mkdir $@
diff --git a/trace-events b/trace-events
index 1c48f6973e..c55d7084fb 100644
--- a/trace-events
+++ b/trace-events
@@ -1430,6 +1430,8 @@ spapr_iommu_pci_indirect(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t i
spapr_iommu_pci_stuff(uint64_t liobn, uint64_t ioba, uint64_t tce_value, uint64_t npages, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tcevalue=0x%"PRIx64" npages=%"PRId64" ret=%"PRId64
spapr_iommu_xlate(uint64_t liobn, uint64_t ioba, uint64_t tce, unsigned perm, unsigned pgsize) "liobn=%"PRIx64" 0x%"PRIx64" -> 0x%"PRIx64" perm=%u mask=%x"
spapr_iommu_new_table(uint64_t liobn, void *table, int fd) "liobn=%"PRIx64" table=%p fd=%d"
+spapr_iommu_pre_save(uint64_t liobn, uint32_t nb, uint64_t offs, uint32_t ps) "liobn=%"PRIx64" %"PRIx32" bus_offset=%"PRIx64" ps=%"PRIu32
+spapr_iommu_post_load(uint64_t liobn, uint32_t pre_nb, uint32_t post_nb, uint64_t offs, uint32_t ps) "liobn=%"PRIx64" %"PRIx32" => %"PRIx32" bus_offset=%"PRIx64" ps=%"PRIu32
# hw/ppc/ppc.c
ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "adjusted from 0x%"PRIx64" to 0x%"PRIx64", diff %"PRId64" (%"PRId64"s)"