diff --git a/exec.c b/exec.c
index f0e2bd32b65ea9e581abbd78d346d943979c8267..71ac104b391486d23c17db9659dc91a3f83f2c43 100644
--- a/exec.c
+++ b/exec.c
@@ -909,14 +909,15 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
uint16_t section);
static subpage_t *subpage_init(AddressSpace *as, hwaddr base);
-static void *(*phys_mem_alloc)(size_t size) = qemu_anon_ram_alloc;
+static void *(*phys_mem_alloc)(size_t size, uint64_t *align) =
+ qemu_anon_ram_alloc;
/*
* Set a custom physical guest memory alloator.
* Accelerators with unusual needs may need this. Hopefully, we can
* get rid of it eventually.
*/
-void phys_mem_set_alloc(void *(*alloc)(size_t))
+void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align))
{
phys_mem_alloc = alloc;
}
@@ -1098,6 +1099,7 @@ static void *file_ram_alloc(RAMBlock *block,
error_propagate(errp, local_err);
goto error;
}
+ block->mr->align = hpagesize;
if (memory < hpagesize) {
error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to "
@@ -1309,7 +1311,8 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp)
if (xen_enabled()) {
xen_ram_alloc(new_block->offset, new_block->length, new_block->mr);
} else {
- new_block->host = phys_mem_alloc(new_block->length);
+ new_block->host = phys_mem_alloc(new_block->length,
+ &new_block->mr->align);
if (!new_block->host) {
error_setg_errno(errp, errno,
"cannot set up guest memory '%s'",
diff --git a/hw/core/loader.c b/hw/core/loader.c
index fc155359f84c7c199ff9b53198702066776eab20..7527fd30367eda138f5f746d4e4641da9f017327 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -811,12 +811,12 @@ err:
return -1;
}
-void *rom_add_blob(const char *name, const void *blob, size_t len,
+ram_addr_t rom_add_blob(const char *name, const void *blob, size_t len,
hwaddr addr, const char *fw_file_name,
FWCfgReadCallback fw_callback, void *callback_opaque)
{
Rom *rom;
- void *data = NULL;
+ ram_addr_t ret = RAM_ADDR_MAX;
rom = g_malloc0(sizeof(*rom));
rom->name = g_strdup(name);
@@ -828,11 +828,13 @@ void *rom_add_blob(const char *name, const void *blob, size_t len,
rom_insert(rom);
if (fw_file_name && fw_cfg) {
char devpath[100];
+ void *data;
snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
if (rom_file_has_mr) {
data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
+ ret = memory_region_get_ram_addr(rom->mr);
} else {
data = rom->data;
}
@@ -841,7 +843,7 @@ void *rom_add_blob(const char *name, const void *blob, size_t len,
fw_callback, callback_opaque,
data, rom->romsize);
}
- return data;
+ return ret;
}
/* This function is specific for elf program because we don't need to allocate
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 4003b6bf9bed4863a438f698671daed6f107de75..b37a397820c7a879dc9a4025129065e3caf2e465 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -56,6 +56,7 @@
#include "qapi/qmp/qint.h"
#include "qom/qom-qobject.h"
+#include "exec/ram_addr.h"
/* These are used to size the ACPI tables for -M pc-i440fx-1.7 and
* -M pc-i440fx-2.0. Even if the actual amount of AML generated grows
@@ -1269,8 +1270,7 @@ acpi_build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
}
static void
-build_srat(GArray *table_data, GArray *linker,
- AcpiCpuInfo *cpu, PcGuestInfo *guest_info)
+build_srat(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
{
AcpiSystemResourceAffinityTable *srat;
AcpiSratProcessorAffinity *core;
@@ -1300,11 +1300,7 @@ build_srat(GArray *table_data, GArray *linker,
core->proximity_lo = curnode;
memset(core->proximity_hi, 0, 3);
core->local_sapic_eid = 0;
- if (test_bit(i, cpu->found_cpus)) {
- core->flags = cpu_to_le32(1);
- } else {
- core->flags = cpu_to_le32(0);
- }
+ core->flags = cpu_to_le32(1);
}
@@ -1511,7 +1507,7 @@ static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
typedef
struct AcpiBuildState {
/* Copy of table in RAM (for patching). */
- uint8_t *table_ram;
+ ram_addr_t table_ram;
uint32_t table_size;
/* Is table patched? */
uint8_t patched;
@@ -1622,7 +1618,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
}
if (guest_info->numa_nodes) {
acpi_add_table(table_offsets, tables->table_data);
- build_srat(tables->table_data, tables->linker, &cpu, guest_info);
+ build_srat(tables->table_data, tables->linker, guest_info);
}
if (acpi_get_mcfg(&mcfg)) {
acpi_add_table(table_offsets, tables->table_data);
@@ -1716,9 +1712,12 @@ static void acpi_build_update(void *build_opaque, uint32_t offset)
acpi_build(build_state->guest_info, &tables);
assert(acpi_data_len(tables.table_data) == build_state->table_size);
- memcpy(build_state->table_ram, tables.table_data->data,
+ memcpy(qemu_get_ram_ptr(build_state->table_ram), tables.table_data->data,
build_state->table_size);
+ cpu_physical_memory_set_dirty_range_nocode(build_state->table_ram,
+ build_state->table_size);
+
acpi_build_tables_cleanup(&tables, true);
}
@@ -1728,7 +1727,7 @@ static void acpi_build_reset(void *build_opaque)
build_state->patched = 0;
}
-static void *acpi_add_rom_blob(AcpiBuildState *build_state, GArray *blob,
+static ram_addr_t acpi_add_rom_blob(AcpiBuildState *build_state, GArray *blob,
const char *name)
{
return rom_add_blob(name, blob->data, acpi_data_len(blob), -1, name,
@@ -1777,6 +1776,7 @@ void acpi_setup(PcGuestInfo *guest_info)
/* Now expose it all to Guest */
build_state->table_ram = acpi_add_rom_blob(build_state, tables.table_data,
ACPI_BUILD_TABLE_FILE);
+ assert(build_state->table_ram != RAM_ADDR_MAX);
build_state->table_size = acpi_data_len(tables.table_data);
acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader");
diff --git a/hw/i386/acpi-dsdt-mem-hotplug.dsl b/hw/i386/acpi-dsdt-mem-hotplug.dsl
new file mode 100644
index 0000000000000000000000000000000000000000..2a36c4799ec69e751460a67e81e351023d648b18
--- /dev/null
+++ b/hw/i386/acpi-dsdt-mem-hotplug.dsl
@@ -0,0 +1,176 @@
+/*
+ * 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 .
+ */
+
+ External(MEMORY_SLOT_NOTIFY_METHOD, MethodObj)
+
+ Scope(\_SB.PCI0) {
+ Device(MEMORY_HOTPLUG_DEVICE) {
+ Name(_HID, "PNP0A06")
+ Name(_UID, "Memory hotplug resources")
+ External(MEMORY_SLOTS_NUMBER, IntObj)
+
+ /* Memory hotplug IO registers */
+ OperationRegion(MEMORY_HOTPLUG_IO_REGION, SystemIO,
+ ACPI_MEMORY_HOTPLUG_BASE,
+ ACPI_MEMORY_HOTPLUG_IO_LEN)
+
+ Name(_CRS, ResourceTemplate() {
+ IO(Decode16, ACPI_MEMORY_HOTPLUG_BASE, ACPI_MEMORY_HOTPLUG_BASE,
+ 0, ACPI_MEMORY_HOTPLUG_IO_LEN, IO)
+ })
+
+ Method(_STA, 0) {
+ If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
+ Return(0x0)
+ }
+ /* present, functioning, decoding, not shown in UI */
+ Return(0xB)
+ }
+
+ Field(MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) {
+ MEMORY_SLOT_ADDR_LOW, 32, // read only
+ MEMORY_SLOT_ADDR_HIGH, 32, // read only
+ MEMORY_SLOT_SIZE_LOW, 32, // read only
+ MEMORY_SLOT_SIZE_HIGH, 32, // read only
+ MEMORY_SLOT_PROXIMITY, 32, // read only
+ }
+ Field(MEMORY_HOTPLUG_IO_REGION, ByteAcc, NoLock, Preserve) {
+ Offset(20),
+ MEMORY_SLOT_ENABLED, 1, // 1 if enabled, read only
+ MEMORY_SLOT_INSERT_EVENT, 1, // (read) 1 if has a insert event. (write) 1 to clear event
+ }
+
+ Mutex (MEMORY_SLOT_LOCK, 0)
+ Field (MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) {
+ MEMORY_SLOT_SLECTOR, 32, // DIMM selector, write only
+ MEMORY_SLOT_OST_EVENT, 32, // _OST event code, write only
+ MEMORY_SLOT_OST_STATUS, 32, // _OST status code, write only
+ }
+
+ Method(MEMORY_SLOT_SCAN_METHOD, 0) {
+ If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
+ Return(Zero)
+ }
+
+ Store(Zero, Local0) // Mem devs iterrator
+ Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
+ while (LLess(Local0, MEMORY_SLOTS_NUMBER)) {
+ Store(Local0, MEMORY_SLOT_SLECTOR) // select Local0 DIMM
+ If (LEqual(MEMORY_SLOT_INSERT_EVENT, One)) { // Memory device needs check
+ MEMORY_SLOT_NOTIFY_METHOD(Local0, 1)
+ Store(1, MEMORY_SLOT_INSERT_EVENT)
+ }
+ // TODO: handle memory eject request
+ Add(Local0, One, Local0) // goto next DIMM
+ }
+ Release(MEMORY_SLOT_LOCK)
+ Return(One)
+ }
+
+ Method(MEMORY_SLOT_STATUS_METHOD, 1) {
+ Store(Zero, Local0)
+
+ Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
+ Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
+
+ If (LEqual(MEMORY_SLOT_ENABLED, One)) {
+ Store(0xF, Local0)
+ }
+
+ Release(MEMORY_SLOT_LOCK)
+ Return(Local0)
+ }
+
+ Method(MEMORY_SLOT_CRS_METHOD, 1, Serialized) {
+ Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
+ Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
+
+ Name(MR64, ResourceTemplate() {
+ QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x0000000000000000, // Address Space Granularity
+ 0x0000000000000000, // Address Range Minimum
+ 0xFFFFFFFFFFFFFFFE, // Address Range Maximum
+ 0x0000000000000000, // Address Translation Offset
+ 0xFFFFFFFFFFFFFFFF, // Address Length
+ ,, MW64, AddressRangeMemory, TypeStatic)
+ })
+
+ CreateDWordField(MR64, 14, MINL)
+ CreateDWordField(MR64, 18, MINH)
+ CreateDWordField(MR64, 38, LENL)
+ CreateDWordField(MR64, 42, LENH)
+ CreateDWordField(MR64, 22, MAXL)
+ CreateDWordField(MR64, 26, MAXH)
+
+ Store(MEMORY_SLOT_ADDR_HIGH, MINH)
+ Store(MEMORY_SLOT_ADDR_LOW, MINL)
+ Store(MEMORY_SLOT_SIZE_HIGH, LENH)
+ Store(MEMORY_SLOT_SIZE_LOW, LENL)
+
+ // 64-bit math: MAX = MIN + LEN - 1
+ Add(MINL, LENL, MAXL)
+ Add(MINH, LENH, MAXH)
+ If (LLess(MAXL, MINL)) {
+ Add(MAXH, One, MAXH)
+ }
+ If (LLess(MAXL, One)) {
+ Subtract(MAXH, One, MAXH)
+ }
+ Subtract(MAXL, One, MAXL)
+
+ If (LEqual(MAXH, Zero)){
+ Name(MR32, ResourceTemplate() {
+ DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
+ Cacheable, ReadWrite,
+ 0x00000000, // Address Space Granularity
+ 0x00000000, // Address Range Minimum
+ 0xFFFFFFFE, // Address Range Maximum
+ 0x00000000, // Address Translation Offset
+ 0xFFFFFFFF, // Address Length
+ ,, MW32, AddressRangeMemory, TypeStatic)
+ })
+ CreateDWordField(MR32, MW32._MIN, MIN)
+ CreateDWordField(MR32, MW32._MAX, MAX)
+ CreateDWordField(MR32, MW32._LEN, LEN)
+ Store(MINL, MIN)
+ Store(MAXL, MAX)
+ Store(LENL, LEN)
+
+ Release(MEMORY_SLOT_LOCK)
+ Return(MR32)
+ }
+
+ Release(MEMORY_SLOT_LOCK)
+ Return(MR64)
+ }
+
+ Method(MEMORY_SLOT_PROXIMITY_METHOD, 1) {
+ Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
+ Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
+ Store(MEMORY_SLOT_PROXIMITY, Local0)
+ Release(MEMORY_SLOT_LOCK)
+ Return(Local0)
+ }
+
+ Method(MEMORY_SLOT_OST_METHOD, 4) {
+ Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
+ Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
+ Store(Arg1, MEMORY_SLOT_OST_EVENT)
+ Store(Arg2, MEMORY_SLOT_OST_STATUS)
+ Release(MEMORY_SLOT_LOCK)
+ }
+ } // Device()
+ } // Scope()
diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
index 559f4b66532bdfe24e19d3d0a2d0bedfb7094de6..a611e07ec8b0b546026d60f4c07148a987856514 100644
--- a/hw/i386/acpi-dsdt.dsl
+++ b/hw/i386/acpi-dsdt.dsl
@@ -297,13 +297,12 @@ DefinitionBlock (
#include "hw/acpi/pc-hotplug.h"
#define CPU_STATUS_BASE PIIX4_CPU_HOTPLUG_IO_BASE
#include "acpi-dsdt-cpu-hotplug.dsl"
+#include "acpi-dsdt-mem-hotplug.dsl"
/****************************************************************
* General purpose events
****************************************************************/
- External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_SCAN_METHOD, MethodObj)
-
Scope(\_GPE) {
Name(_HID, "ACPI0006")
diff --git a/hw/i386/acpi-dsdt.hex.generated b/hw/i386/acpi-dsdt.hex.generated
index a21bf410e5635e949fc0e64ab20b12248999b29e..875570e5b17986d1c2b61b0f25c9acc9c7095318 100644
--- a/hw/i386/acpi-dsdt.hex.generated
+++ b/hw/i386/acpi-dsdt.hex.generated
@@ -3,12 +3,12 @@ static unsigned char AcpiDsdtAmlCode[] = {
0x53,
0x44,
0x54,
-0xf7,
-0xa,
+0x8,
+0xe,
0x0,
0x0,
0x1,
-0x1f,
+0xfc,
0x42,
0x58,
0x50,
@@ -32,8 +32,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
0x54,
0x4c,
0x28,
-0x5,
-0x10,
+0x8,
+0x14,
0x20,
0x10,
0x49,
@@ -2593,6 +2593,791 @@ static unsigned char AcpiDsdtAmlCode[] = {
0xa,
0xb,
0x10,
+0x40,
+0x31,
+0x2e,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x5b,
+0x82,
+0x43,
+0x30,
+0x4d,
+0x48,
+0x50,
+0x44,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xd,
+0x50,
+0x4e,
+0x50,
+0x30,
+0x41,
+0x30,
+0x36,
+0x0,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0xd,
+0x4d,
+0x65,
+0x6d,
+0x6f,
+0x72,
+0x79,
+0x20,
+0x68,
+0x6f,
+0x74,
+0x70,
+0x6c,
+0x75,
+0x67,
+0x20,
+0x72,
+0x65,
+0x73,
+0x6f,
+0x75,
+0x72,
+0x63,
+0x65,
+0x73,
+0x0,
+0x5b,
+0x80,
+0x48,
+0x50,
+0x4d,
+0x52,
+0x1,
+0xb,
+0x0,
+0xa,
+0xa,
+0x18,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0xd,
+0xa,
+0xa,
+0x47,
+0x1,
+0x0,
+0xa,
+0x0,
+0xa,
+0x0,
+0x18,
+0x79,
+0x0,
+0x14,
+0x13,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa0,
+0x9,
+0x93,
+0x4d,
+0x44,
+0x4e,
+0x52,
+0x0,
+0xa4,
+0x0,
+0xa4,
+0xa,
+0xb,
+0x5b,
+0x81,
+0x1f,
+0x48,
+0x50,
+0x4d,
+0x52,
+0x3,
+0x4d,
+0x52,
+0x42,
+0x4c,
+0x20,
+0x4d,
+0x52,
+0x42,
+0x48,
+0x20,
+0x4d,
+0x52,
+0x4c,
+0x4c,
+0x20,
+0x4d,
+0x52,
+0x4c,
+0x48,
+0x20,
+0x4d,
+0x50,
+0x58,
+0x5f,
+0x20,
+0x5b,
+0x81,
+0x13,
+0x48,
+0x50,
+0x4d,
+0x52,
+0x1,
+0x0,
+0x40,
+0xa,
+0x4d,
+0x45,
+0x53,
+0x5f,
+0x1,
+0x4d,
+0x49,
+0x4e,
+0x53,
+0x1,
+0x5b,
+0x1,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0x0,
+0x5b,
+0x81,
+0x15,
+0x48,
+0x50,
+0x4d,
+0x52,
+0x3,
+0x4d,
+0x53,
+0x45,
+0x4c,
+0x20,
+0x4d,
+0x4f,
+0x45,
+0x56,
+0x20,
+0x4d,
+0x4f,
+0x53,
+0x43,
+0x20,
+0x14,
+0x4a,
+0x4,
+0x4d,
+0x53,
+0x43,
+0x4e,
+0x0,
+0xa0,
+0x9,
+0x93,
+0x4d,
+0x44,
+0x4e,
+0x52,
+0x0,
+0xa4,
+0x0,
+0x70,
+0x0,
+0x60,
+0x5b,
+0x23,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xff,
+0xff,
+0xa2,
+0x25,
+0x95,
+0x60,
+0x4d,
+0x44,
+0x4e,
+0x52,
+0x70,
+0x60,
+0x4d,
+0x53,
+0x45,
+0x4c,
+0xa0,
+0x13,
+0x93,
+0x4d,
+0x49,
+0x4e,
+0x53,
+0x1,
+0x4d,
+0x54,
+0x46,
+0x59,
+0x60,
+0x1,
+0x70,
+0x1,
+0x4d,
+0x49,
+0x4e,
+0x53,
+0x72,
+0x60,
+0x1,
+0x60,
+0x5b,
+0x27,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xa4,
+0x1,
+0x14,
+0x2d,
+0x4d,
+0x52,
+0x53,
+0x54,
+0x1,
+0x70,
+0x0,
+0x60,
+0x5b,
+0x23,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xff,
+0xff,
+0x70,
+0x99,
+0x68,
+0x0,
+0x4d,
+0x53,
+0x45,
+0x4c,
+0xa0,
+0xb,
+0x93,
+0x4d,
+0x45,
+0x53,
+0x5f,
+0x1,
+0x70,
+0xa,
+0xf,
+0x60,
+0x5b,
+0x27,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xa4,
+0x60,
+0x14,
+0x41,
+0x18,
+0x4d,
+0x43,
+0x52,
+0x53,
+0x9,
+0x5b,
+0x23,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xff,
+0xff,
+0x70,
+0x99,
+0x68,
+0x0,
+0x4d,
+0x53,
+0x45,
+0x4c,
+0x8,
+0x4d,
+0x52,
+0x36,
+0x34,
+0x11,
+0x33,
+0xa,
+0x30,
+0x8a,
+0x2b,
+0x0,
+0x0,
+0xc,
+0x3,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0xfe,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0x79,
+0x0,
+0x8a,
+0x4d,
+0x52,
+0x36,
+0x34,
+0xa,
+0xe,
+0x4d,
+0x49,
+0x4e,
+0x4c,
+0x8a,
+0x4d,
+0x52,
+0x36,
+0x34,
+0xa,
+0x12,
+0x4d,
+0x49,
+0x4e,
+0x48,
+0x8a,
+0x4d,
+0x52,
+0x36,
+0x34,
+0xa,
+0x26,
+0x4c,
+0x45,
+0x4e,
+0x4c,
+0x8a,
+0x4d,
+0x52,
+0x36,
+0x34,
+0xa,
+0x2a,
+0x4c,
+0x45,
+0x4e,
+0x48,
+0x8a,
+0x4d,
+0x52,
+0x36,
+0x34,
+0xa,
+0x16,
+0x4d,
+0x41,
+0x58,
+0x4c,
+0x8a,
+0x4d,
+0x52,
+0x36,
+0x34,
+0xa,
+0x1a,
+0x4d,
+0x41,
+0x58,
+0x48,
+0x70,
+0x4d,
+0x52,
+0x42,
+0x48,
+0x4d,
+0x49,
+0x4e,
+0x48,
+0x70,
+0x4d,
+0x52,
+0x42,
+0x4c,
+0x4d,
+0x49,
+0x4e,
+0x4c,
+0x70,
+0x4d,
+0x52,
+0x4c,
+0x48,
+0x4c,
+0x45,
+0x4e,
+0x48,
+0x70,
+0x4d,
+0x52,
+0x4c,
+0x4c,
+0x4c,
+0x45,
+0x4e,
+0x4c,
+0x72,
+0x4d,
+0x49,
+0x4e,
+0x4c,
+0x4c,
+0x45,
+0x4e,
+0x4c,
+0x4d,
+0x41,
+0x58,
+0x4c,
+0x72,
+0x4d,
+0x49,
+0x4e,
+0x48,
+0x4c,
+0x45,
+0x4e,
+0x48,
+0x4d,
+0x41,
+0x58,
+0x48,
+0xa0,
+0x14,
+0x95,
+0x4d,
+0x41,
+0x58,
+0x4c,
+0x4d,
+0x49,
+0x4e,
+0x4c,
+0x72,
+0x4d,
+0x41,
+0x58,
+0x48,
+0x1,
+0x4d,
+0x41,
+0x58,
+0x48,
+0xa0,
+0x11,
+0x95,
+0x4d,
+0x41,
+0x58,
+0x4c,
+0x1,
+0x74,
+0x4d,
+0x41,
+0x58,
+0x48,
+0x1,
+0x4d,
+0x41,
+0x58,
+0x48,
+0x74,
+0x4d,
+0x41,
+0x58,
+0x4c,
+0x1,
+0x4d,
+0x41,
+0x58,
+0x4c,
+0xa0,
+0x44,
+0x7,
+0x93,
+0x4d,
+0x41,
+0x58,
+0x48,
+0x0,
+0x8,
+0x4d,
+0x52,
+0x33,
+0x32,
+0x11,
+0x1f,
+0xa,
+0x1c,
+0x87,
+0x17,
+0x0,
+0x0,
+0xc,
+0x3,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0xfe,
+0xff,
+0xff,
+0xff,
+0x0,
+0x0,
+0x0,
+0x0,
+0xff,
+0xff,
+0xff,
+0xff,
+0x79,
+0x0,
+0x8a,
+0x4d,
+0x52,
+0x33,
+0x32,
+0xa,
+0xa,
+0x4d,
+0x49,
+0x4e,
+0x5f,
+0x8a,
+0x4d,
+0x52,
+0x33,
+0x32,
+0xa,
+0xe,
+0x4d,
+0x41,
+0x58,
+0x5f,
+0x8a,
+0x4d,
+0x52,
+0x33,
+0x32,
+0xa,
+0x16,
+0x4c,
+0x45,
+0x4e,
+0x5f,
+0x70,
+0x4d,
+0x49,
+0x4e,
+0x4c,
+0x4d,
+0x49,
+0x4e,
+0x5f,
+0x70,
+0x4d,
+0x41,
+0x58,
+0x4c,
+0x4d,
+0x41,
+0x58,
+0x5f,
+0x70,
+0x4c,
+0x45,
+0x4e,
+0x4c,
+0x4c,
+0x45,
+0x4e,
+0x5f,
+0x5b,
+0x27,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xa4,
+0x4d,
+0x52,
+0x33,
+0x32,
+0x5b,
+0x27,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xa4,
+0x4d,
+0x52,
+0x36,
+0x34,
+0x14,
+0x24,
+0x4d,
+0x50,
+0x58,
+0x4d,
+0x1,
+0x5b,
+0x23,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xff,
+0xff,
+0x70,
+0x99,
+0x68,
+0x0,
+0x4d,
+0x53,
+0x45,
+0x4c,
+0x70,
+0x4d,
+0x50,
+0x58,
+0x5f,
+0x60,
+0x5b,
+0x27,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xa4,
+0x60,
+0x14,
+0x28,
+0x4d,
+0x4f,
+0x53,
+0x54,
+0x4,
+0x5b,
+0x23,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xff,
+0xff,
+0x70,
+0x99,
+0x68,
+0x0,
+0x4d,
+0x53,
+0x45,
+0x4c,
+0x70,
+0x69,
+0x4d,
+0x4f,
+0x45,
+0x56,
+0x70,
+0x6a,
+0x4d,
+0x4f,
+0x53,
+0x43,
+0x5b,
+0x27,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0x10,
0x45,
0xd,
0x5f,
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 1205db83bcb91b3cac48c9b7af65e3e011362ba8..8be50a4ad6a655af4cd9aa1894290a1df9e0370e 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1247,6 +1247,11 @@ FWCfgState *pc_memory_init(MachineState *machine,
pcms->hotplug_memory_base =
ROUND_UP(0x100000000ULL + above_4g_mem_size, 1ULL << 30);
+ if (pcms->enforce_aligned_dimm) {
+ /* size hotplug region assuming 1G page max alignment per slot */
+ hotplug_mem_size += (1ULL << 30) * machine->ram_slots;
+ }
+
if ((pcms->hotplug_memory_base + hotplug_mem_size) <
hotplug_mem_size) {
error_report("unsupported amount of maximum memory: " RAM_ADDR_FMT,
@@ -1545,6 +1550,37 @@ void qemu_register_pc_machine(QEMUMachine *m)
g_free(name);
}
+static int pc_dimm_count(Object *obj, void *opaque)
+{
+ int *count = opaque;
+
+ if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+ (*count)++;
+ }
+
+ object_child_foreach(obj, pc_dimm_count, opaque);
+ return 0;
+}
+
+static int pc_existing_dimms_capacity(Object *obj, void *opaque)
+{
+ Error *local_err = NULL;
+ uint64_t *size = opaque;
+
+ if (object_dynamic_cast(obj, TYPE_PC_DIMM)) {
+ (*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP, &local_err);
+
+ if (local_err) {
+ qerror_report_err(local_err);
+ error_free(local_err);
+ return 1;
+ }
+ }
+
+ object_child_foreach(obj, pc_dimm_count, opaque);
+ return 0;
+}
+
static void pc_dimm_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
@@ -1556,20 +1592,40 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
MemoryRegion *mr = ddc->get_memory_region(dimm);
- uint64_t addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP,
- &local_err);
+ uint64_t existing_dimms_capacity = 0;
+ uint64_t align = TARGET_PAGE_SIZE;
+ uint64_t addr;
+
+ addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err);
if (local_err) {
goto out;
}
+ if (memory_region_get_alignment(mr) && pcms->enforce_aligned_dimm) {
+ align = memory_region_get_alignment(mr);
+ }
+
addr = pc_dimm_get_free_addr(pcms->hotplug_memory_base,
memory_region_size(&pcms->hotplug_memory),
- !addr ? NULL : &addr,
+ !addr ? NULL : &addr, align,
memory_region_size(mr), &local_err);
if (local_err) {
goto out;
}
+ if (pc_existing_dimms_capacity(OBJECT(machine), &existing_dimms_capacity)) {
+ error_setg(&local_err, "failed to get total size of existing DIMMs");
+ goto out;
+ }
+
+ if (existing_dimms_capacity + memory_region_size(mr) >
+ machine->maxram_size - machine->ram_size) {
+ error_setg(&local_err, "not enough space, currently 0x%" PRIx64
+ " in use of total 0x" RAM_ADDR_FMT,
+ existing_dimms_capacity, machine->maxram_size);
+ goto out;
+ }
+
object_property_set_int(OBJECT(dev), addr, PC_DIMM_ADDR_PROP, &local_err);
if (local_err) {
goto out;
@@ -1598,6 +1654,11 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
goto out;
}
+ if (kvm_enabled() && !kvm_has_free_slot(machine)) {
+ error_setg(&local_err, "hypervisor has no free memory slots left");
+ goto out;
+ }
+
memory_region_add_subregion(&pcms->hotplug_memory,
addr - pcms->hotplug_memory_base, mr);
vmstate_register_ram(mr, dev);
@@ -1725,6 +1786,13 @@ static void pc_machine_set_vmport(Object *obj, bool value, Error **errp)
pcms->vmport = value;
}
+static bool pc_machine_get_aligned_dimm(Object *obj, Error **errp)
+{
+ PCMachineState *pcms = PC_MACHINE(obj);
+
+ return pcms->enforce_aligned_dimm;
+}
+
static void pc_machine_initfn(Object *obj)
{
PCMachineState *pcms = PC_MACHINE(obj);
@@ -1737,11 +1805,17 @@ static void pc_machine_initfn(Object *obj)
pc_machine_get_max_ram_below_4g,
pc_machine_set_max_ram_below_4g,
NULL, NULL, NULL);
+
pcms->vmport = !xen_enabled();
object_property_add_bool(obj, PC_MACHINE_VMPORT,
pc_machine_get_vmport,
pc_machine_set_vmport,
NULL);
+
+ pcms->enforce_aligned_dimm = true;
+ object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM,
+ pc_machine_get_aligned_dimm,
+ NULL, NULL);
}
static void pc_machine_class_init(ObjectClass *oc, void *data)
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 7bb97a4923dd7e09303dd76cb47528607233088a..741dffd5f325e974cba60acd0bdc04c7b513d6ed 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -305,10 +305,12 @@ static void pc_init_pci(MachineState *machine)
static void pc_compat_2_1(MachineState *machine)
{
+ PCMachineState *pcms = PC_MACHINE(machine);
smbios_uuid_encoded = false;
x86_cpu_compat_set_features("coreduo", FEAT_1_ECX, CPUID_EXT_VMX, 0);
x86_cpu_compat_set_features("core2duo", FEAT_1_ECX, CPUID_EXT_VMX, 0);
x86_cpu_compat_kvm_no_autodisable(FEAT_8000_0001_ECX, CPUID_EXT3_SVM);
+ pcms->enforce_aligned_dimm = false;
}
static void pc_compat_2_0(MachineState *machine)
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 598e679749c78f8f678e7c831c9e57f2b31ec0ee..e9ba1a273569717fa6fa06d0fe54907f3c2836a1 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -284,6 +284,9 @@ static void pc_q35_init(MachineState *machine)
static void pc_compat_2_1(MachineState *machine)
{
+ PCMachineState *pcms = PC_MACHINE(machine);
+
+ pcms->enforce_aligned_dimm = false;
smbios_uuid_encoded = false;
x86_cpu_compat_set_features("coreduo", FEAT_1_ECX, CPUID_EXT_VMX, 0);
x86_cpu_compat_set_features("core2duo", FEAT_1_ECX, CPUID_EXT_VMX, 0);
diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
index 054b035b08f081d664325f970729d31cd4976bb6..e1cee5d89a78e3c18e5cd1aab5a7728e97564856 100644
--- a/hw/i386/q35-acpi-dsdt.dsl
+++ b/hw/i386/q35-acpi-dsdt.dsl
@@ -405,13 +405,12 @@ DefinitionBlock (
#include "hw/acpi/pc-hotplug.h"
#define CPU_STATUS_BASE ICH9_CPU_HOTPLUG_IO_BASE
#include "acpi-dsdt-cpu-hotplug.dsl"
+#include "acpi-dsdt-mem-hotplug.dsl"
/****************************************************************
* General purpose events
****************************************************************/
- External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_SCAN_METHOD, MethodObj)
-
Scope(\_GPE) {
Name(_HID, "ACPI0006")
diff --git a/hw/i386/q35-acpi-dsdt.hex.generated b/hw/i386/q35-acpi-dsdt.hex.generated
index c9eb4ac6ad19b310fa9f3b068582c7c6eb2dbf44..4807bdf484a354e24c8dafe1a184456f08d5ae93 100644
--- a/hw/i386/q35-acpi-dsdt.hex.generated
+++ b/hw/i386/q35-acpi-dsdt.hex.generated
@@ -3,12 +3,12 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
0x53,
0x44,
0x54,
-0xe5,
-0x1c,
+0xf6,
+0x1f,
0x0,
0x0,
0x1,
-0xb7,
+0x91,
0x42,
0x58,
0x50,
@@ -31,9 +31,9 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
0x4e,
0x54,
0x4c,
-0x15,
-0x11,
-0x13,
+0x28,
+0x8,
+0x14,
0x20,
0x10,
0x49,
@@ -7234,6 +7234,791 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
0xa,
0xb,
0x10,
+0x40,
+0x31,
+0x2e,
+0x5f,
+0x53,
+0x42,
+0x5f,
+0x50,
+0x43,
+0x49,
+0x30,
+0x5b,
+0x82,
+0x43,
+0x30,
+0x4d,
+0x48,
+0x50,
+0x44,
+0x8,
+0x5f,
+0x48,
+0x49,
+0x44,
+0xd,
+0x50,
+0x4e,
+0x50,
+0x30,
+0x41,
+0x30,
+0x36,
+0x0,
+0x8,
+0x5f,
+0x55,
+0x49,
+0x44,
+0xd,
+0x4d,
+0x65,
+0x6d,
+0x6f,
+0x72,
+0x79,
+0x20,
+0x68,
+0x6f,
+0x74,
+0x70,
+0x6c,
+0x75,
+0x67,
+0x20,
+0x72,
+0x65,
+0x73,
+0x6f,
+0x75,
+0x72,
+0x63,
+0x65,
+0x73,
+0x0,
+0x5b,
+0x80,
+0x48,
+0x50,
+0x4d,
+0x52,
+0x1,
+0xb,
+0x0,
+0xa,
+0xa,
+0x18,
+0x8,
+0x5f,
+0x43,
+0x52,
+0x53,
+0x11,
+0xd,
+0xa,
+0xa,
+0x47,
+0x1,
+0x0,
+0xa,
+0x0,
+0xa,
+0x0,
+0x18,
+0x79,
+0x0,
+0x14,
+0x13,
+0x5f,
+0x53,
+0x54,
+0x41,
+0x0,
+0xa0,
+0x9,
+0x93,
+0x4d,
+0x44,
+0x4e,
+0x52,
+0x0,
+0xa4,
+0x0,
+0xa4,
+0xa,
+0xb,
+0x5b,
+0x81,
+0x1f,
+0x48,
+0x50,
+0x4d,
+0x52,
+0x3,
+0x4d,
+0x52,
+0x42,
+0x4c,
+0x20,
+0x4d,
+0x52,
+0x42,
+0x48,
+0x20,
+0x4d,
+0x52,
+0x4c,
+0x4c,
+0x20,
+0x4d,
+0x52,
+0x4c,
+0x48,
+0x20,
+0x4d,
+0x50,
+0x58,
+0x5f,
+0x20,
+0x5b,
+0x81,
+0x13,
+0x48,
+0x50,
+0x4d,
+0x52,
+0x1,
+0x0,
+0x40,
+0xa,
+0x4d,
+0x45,
+0x53,
+0x5f,
+0x1,
+0x4d,
+0x49,
+0x4e,
+0x53,
+0x1,
+0x5b,
+0x1,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0x0,
+0x5b,
+0x81,
+0x15,
+0x48,
+0x50,
+0x4d,
+0x52,
+0x3,
+0x4d,
+0x53,
+0x45,
+0x4c,
+0x20,
+0x4d,
+0x4f,
+0x45,
+0x56,
+0x20,
+0x4d,
+0x4f,
+0x53,
+0x43,
+0x20,
+0x14,
+0x4a,
+0x4,
+0x4d,
+0x53,
+0x43,
+0x4e,
+0x0,
+0xa0,
+0x9,
+0x93,
+0x4d,
+0x44,
+0x4e,
+0x52,
+0x0,
+0xa4,
+0x0,
+0x70,
+0x0,
+0x60,
+0x5b,
+0x23,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xff,
+0xff,
+0xa2,
+0x25,
+0x95,
+0x60,
+0x4d,
+0x44,
+0x4e,
+0x52,
+0x70,
+0x60,
+0x4d,
+0x53,
+0x45,
+0x4c,
+0xa0,
+0x13,
+0x93,
+0x4d,
+0x49,
+0x4e,
+0x53,
+0x1,
+0x4d,
+0x54,
+0x46,
+0x59,
+0x60,
+0x1,
+0x70,
+0x1,
+0x4d,
+0x49,
+0x4e,
+0x53,
+0x72,
+0x60,
+0x1,
+0x60,
+0x5b,
+0x27,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xa4,
+0x1,
+0x14,
+0x2d,
+0x4d,
+0x52,
+0x53,
+0x54,
+0x1,
+0x70,
+0x0,
+0x60,
+0x5b,
+0x23,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xff,
+0xff,
+0x70,
+0x99,
+0x68,
+0x0,
+0x4d,
+0x53,
+0x45,
+0x4c,
+0xa0,
+0xb,
+0x93,
+0x4d,
+0x45,
+0x53,
+0x5f,
+0x1,
+0x70,
+0xa,
+0xf,
+0x60,
+0x5b,
+0x27,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xa4,
+0x60,
+0x14,
+0x41,
+0x18,
+0x4d,
+0x43,
+0x52,
+0x53,
+0x9,
+0x5b,
+0x23,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xff,
+0xff,
+0x70,
+0x99,
+0x68,
+0x0,
+0x4d,
+0x53,
+0x45,
+0x4c,
+0x8,
+0x4d,
+0x52,
+0x36,
+0x34,
+0x11,
+0x33,
+0xa,
+0x30,
+0x8a,
+0x2b,
+0x0,
+0x0,
+0xc,
+0x3,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0xfe,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0xff,
+0x79,
+0x0,
+0x8a,
+0x4d,
+0x52,
+0x36,
+0x34,
+0xa,
+0xe,
+0x4d,
+0x49,
+0x4e,
+0x4c,
+0x8a,
+0x4d,
+0x52,
+0x36,
+0x34,
+0xa,
+0x12,
+0x4d,
+0x49,
+0x4e,
+0x48,
+0x8a,
+0x4d,
+0x52,
+0x36,
+0x34,
+0xa,
+0x26,
+0x4c,
+0x45,
+0x4e,
+0x4c,
+0x8a,
+0x4d,
+0x52,
+0x36,
+0x34,
+0xa,
+0x2a,
+0x4c,
+0x45,
+0x4e,
+0x48,
+0x8a,
+0x4d,
+0x52,
+0x36,
+0x34,
+0xa,
+0x16,
+0x4d,
+0x41,
+0x58,
+0x4c,
+0x8a,
+0x4d,
+0x52,
+0x36,
+0x34,
+0xa,
+0x1a,
+0x4d,
+0x41,
+0x58,
+0x48,
+0x70,
+0x4d,
+0x52,
+0x42,
+0x48,
+0x4d,
+0x49,
+0x4e,
+0x48,
+0x70,
+0x4d,
+0x52,
+0x42,
+0x4c,
+0x4d,
+0x49,
+0x4e,
+0x4c,
+0x70,
+0x4d,
+0x52,
+0x4c,
+0x48,
+0x4c,
+0x45,
+0x4e,
+0x48,
+0x70,
+0x4d,
+0x52,
+0x4c,
+0x4c,
+0x4c,
+0x45,
+0x4e,
+0x4c,
+0x72,
+0x4d,
+0x49,
+0x4e,
+0x4c,
+0x4c,
+0x45,
+0x4e,
+0x4c,
+0x4d,
+0x41,
+0x58,
+0x4c,
+0x72,
+0x4d,
+0x49,
+0x4e,
+0x48,
+0x4c,
+0x45,
+0x4e,
+0x48,
+0x4d,
+0x41,
+0x58,
+0x48,
+0xa0,
+0x14,
+0x95,
+0x4d,
+0x41,
+0x58,
+0x4c,
+0x4d,
+0x49,
+0x4e,
+0x4c,
+0x72,
+0x4d,
+0x41,
+0x58,
+0x48,
+0x1,
+0x4d,
+0x41,
+0x58,
+0x48,
+0xa0,
+0x11,
+0x95,
+0x4d,
+0x41,
+0x58,
+0x4c,
+0x1,
+0x74,
+0x4d,
+0x41,
+0x58,
+0x48,
+0x1,
+0x4d,
+0x41,
+0x58,
+0x48,
+0x74,
+0x4d,
+0x41,
+0x58,
+0x4c,
+0x1,
+0x4d,
+0x41,
+0x58,
+0x4c,
+0xa0,
+0x44,
+0x7,
+0x93,
+0x4d,
+0x41,
+0x58,
+0x48,
+0x0,
+0x8,
+0x4d,
+0x52,
+0x33,
+0x32,
+0x11,
+0x1f,
+0xa,
+0x1c,
+0x87,
+0x17,
+0x0,
+0x0,
+0xc,
+0x3,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0x0,
+0xfe,
+0xff,
+0xff,
+0xff,
+0x0,
+0x0,
+0x0,
+0x0,
+0xff,
+0xff,
+0xff,
+0xff,
+0x79,
+0x0,
+0x8a,
+0x4d,
+0x52,
+0x33,
+0x32,
+0xa,
+0xa,
+0x4d,
+0x49,
+0x4e,
+0x5f,
+0x8a,
+0x4d,
+0x52,
+0x33,
+0x32,
+0xa,
+0xe,
+0x4d,
+0x41,
+0x58,
+0x5f,
+0x8a,
+0x4d,
+0x52,
+0x33,
+0x32,
+0xa,
+0x16,
+0x4c,
+0x45,
+0x4e,
+0x5f,
+0x70,
+0x4d,
+0x49,
+0x4e,
+0x4c,
+0x4d,
+0x49,
+0x4e,
+0x5f,
+0x70,
+0x4d,
+0x41,
+0x58,
+0x4c,
+0x4d,
+0x41,
+0x58,
+0x5f,
+0x70,
+0x4c,
+0x45,
+0x4e,
+0x4c,
+0x4c,
+0x45,
+0x4e,
+0x5f,
+0x5b,
+0x27,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xa4,
+0x4d,
+0x52,
+0x33,
+0x32,
+0x5b,
+0x27,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xa4,
+0x4d,
+0x52,
+0x36,
+0x34,
+0x14,
+0x24,
+0x4d,
+0x50,
+0x58,
+0x4d,
+0x1,
+0x5b,
+0x23,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xff,
+0xff,
+0x70,
+0x99,
+0x68,
+0x0,
+0x4d,
+0x53,
+0x45,
+0x4c,
+0x70,
+0x4d,
+0x50,
+0x58,
+0x5f,
+0x60,
+0x5b,
+0x27,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xa4,
+0x60,
+0x14,
+0x28,
+0x4d,
+0x4f,
+0x53,
+0x54,
+0x4,
+0x5b,
+0x23,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0xff,
+0xff,
+0x70,
+0x99,
+0x68,
+0x0,
+0x4d,
+0x53,
+0x45,
+0x4c,
+0x70,
+0x69,
+0x4d,
+0x4f,
+0x45,
+0x56,
+0x70,
+0x6a,
+0x4d,
+0x4f,
+0x53,
+0x43,
+0x5b,
+0x27,
+0x4d,
+0x4c,
+0x43,
+0x4b,
+0x10,
0x42,
0xa,
0x5f,
diff --git a/hw/i386/ssdt-mem.hex.generated b/hw/i386/ssdt-mem.hex.generated
index 00bd34d269b9d510803bcc5b7009cebaab338c80..b3bfbbda0926f64ff071b92148685f02b497fb5b 100644
--- a/hw/i386/ssdt-mem.hex.generated
+++ b/hw/i386/ssdt-mem.hex.generated
@@ -11,7 +11,7 @@ static unsigned char ssdm_mem_aml[] = {
0x0,
0x0,
0x2,
-0x71,
+0x66,
0x42,
0x58,
0x50,
@@ -34,9 +34,9 @@ static unsigned char ssdm_mem_aml[] = {
0x4e,
0x54,
0x4c,
-0x15,
-0x11,
-0x13,
+0x28,
+0x8,
+0x14,
0x20,
0x10,
0x42,
diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
index 0fd448000b10555a793678524ad6458bd4e8db73..1e3baaed3d7f2d14f9818d68fd2a3e458db19757 100644
--- a/hw/i386/ssdt-misc.dsl
+++ b/hw/i386/ssdt-misc.dsl
@@ -36,6 +36,8 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
Name(P1E, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_length
Name(P1L, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
+ ACPI_EXTRACT_NAME_DWORD_CONST ssdt_mctrl_nr_slots
+ Name(MEMORY_SLOTS_NUMBER, 0x12345678)
}
@@ -117,167 +119,4 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
}
}
}
-
- External(MEMORY_SLOT_NOTIFY_METHOD, MethodObj)
- Scope(\_SB.PCI0) {
- Device(MEMORY_HOTPLUG_DEVICE) {
- Name(_HID, "PNP0A06")
- Name(_UID, "Memory hotplug resources")
-
- ACPI_EXTRACT_NAME_DWORD_CONST ssdt_mctrl_nr_slots
- Name(MEMORY_SLOTS_NUMBER, 0x12345678)
-
- /* Memory hotplug IO registers */
- OperationRegion(MEMORY_HOTPLUG_IO_REGION, SystemIO,
- ACPI_MEMORY_HOTPLUG_BASE,
- ACPI_MEMORY_HOTPLUG_IO_LEN)
-
- Name(_CRS, ResourceTemplate() {
- IO(Decode16, ACPI_MEMORY_HOTPLUG_BASE, ACPI_MEMORY_HOTPLUG_BASE,
- 0, ACPI_MEMORY_HOTPLUG_IO_LEN, IO)
- })
-
- Method(_STA, 0) {
- If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
- Return(0x0)
- }
- /* present, functioning, decoding, not shown in UI */
- Return(0xB)
- }
-
- Field(MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) {
- MEMORY_SLOT_ADDR_LOW, 32, // read only
- MEMORY_SLOT_ADDR_HIGH, 32, // read only
- MEMORY_SLOT_SIZE_LOW, 32, // read only
- MEMORY_SLOT_SIZE_HIGH, 32, // read only
- MEMORY_SLOT_PROXIMITY, 32, // read only
- }
- Field(MEMORY_HOTPLUG_IO_REGION, ByteAcc, NoLock, Preserve) {
- Offset(20),
- MEMORY_SLOT_ENABLED, 1, // 1 if enabled, read only
- MEMORY_SLOT_INSERT_EVENT, 1, // (read) 1 if has a insert event. (write) 1 to clear event
- }
-
- Mutex (MEMORY_SLOT_LOCK, 0)
- Field (MEMORY_HOTPLUG_IO_REGION, DWordAcc, NoLock, Preserve) {
- MEMORY_SLOT_SLECTOR, 32, // DIMM selector, write only
- MEMORY_SLOT_OST_EVENT, 32, // _OST event code, write only
- MEMORY_SLOT_OST_STATUS, 32, // _OST status code, write only
- }
-
- Method(MEMORY_SLOT_SCAN_METHOD, 0) {
- If (LEqual(MEMORY_SLOTS_NUMBER, Zero)) {
- Return(Zero)
- }
-
- Store(Zero, Local0) // Mem devs iterrator
- Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
- while (LLess(Local0, MEMORY_SLOTS_NUMBER)) {
- Store(Local0, MEMORY_SLOT_SLECTOR) // select Local0 DIMM
- If (LEqual(MEMORY_SLOT_INSERT_EVENT, One)) { // Memory device needs check
- MEMORY_SLOT_NOTIFY_METHOD(Local0, 1)
- Store(1, MEMORY_SLOT_INSERT_EVENT)
- }
- // TODO: handle memory eject request
- Add(Local0, One, Local0) // goto next DIMM
- }
- Release(MEMORY_SLOT_LOCK)
- Return(One)
- }
-
- Method(MEMORY_SLOT_STATUS_METHOD, 1) {
- Store(Zero, Local0)
-
- Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
- Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
-
- If (LEqual(MEMORY_SLOT_ENABLED, One)) {
- Store(0xF, Local0)
- }
-
- Release(MEMORY_SLOT_LOCK)
- Return(Local0)
- }
-
- Method(MEMORY_SLOT_CRS_METHOD, 1, Serialized) {
- Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
- Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
-
- Name(MR64, ResourceTemplate() {
- QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
- Cacheable, ReadWrite,
- 0x0000000000000000, // Address Space Granularity
- 0x0000000000000000, // Address Range Minimum
- 0xFFFFFFFFFFFFFFFE, // Address Range Maximum
- 0x0000000000000000, // Address Translation Offset
- 0xFFFFFFFFFFFFFFFF, // Address Length
- ,, MW64, AddressRangeMemory, TypeStatic)
- })
-
- CreateDWordField(MR64, 14, MINL)
- CreateDWordField(MR64, 18, MINH)
- CreateDWordField(MR64, 38, LENL)
- CreateDWordField(MR64, 42, LENH)
- CreateDWordField(MR64, 22, MAXL)
- CreateDWordField(MR64, 26, MAXH)
-
- Store(MEMORY_SLOT_ADDR_HIGH, MINH)
- Store(MEMORY_SLOT_ADDR_LOW, MINL)
- Store(MEMORY_SLOT_SIZE_HIGH, LENH)
- Store(MEMORY_SLOT_SIZE_LOW, LENL)
-
- // 64-bit math: MAX = MIN + LEN - 1
- Add(MINL, LENL, MAXL)
- Add(MINH, LENH, MAXH)
- If (LLess(MAXL, MINL)) {
- Add(MAXH, One, MAXH)
- }
- If (LLess(MAXL, One)) {
- Subtract(MAXH, One, MAXH)
- }
- Subtract(MAXL, One, MAXL)
-
- If (LEqual(MAXH, Zero)){
- Name(MR32, ResourceTemplate() {
- DWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
- Cacheable, ReadWrite,
- 0x00000000, // Address Space Granularity
- 0x00000000, // Address Range Minimum
- 0xFFFFFFFE, // Address Range Maximum
- 0x00000000, // Address Translation Offset
- 0xFFFFFFFF, // Address Length
- ,, MW32, AddressRangeMemory, TypeStatic)
- })
- CreateDWordField(MR32, MW32._MIN, MIN)
- CreateDWordField(MR32, MW32._MAX, MAX)
- CreateDWordField(MR32, MW32._LEN, LEN)
- Store(MINL, MIN)
- Store(MAXL, MAX)
- Store(LENL, LEN)
-
- Release(MEMORY_SLOT_LOCK)
- Return(MR32)
- }
-
- Release(MEMORY_SLOT_LOCK)
- Return(MR64)
- }
-
- Method(MEMORY_SLOT_PROXIMITY_METHOD, 1) {
- Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
- Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
- Store(MEMORY_SLOT_PROXIMITY, Local0)
- Release(MEMORY_SLOT_LOCK)
- Return(Local0)
- }
-
- Method(MEMORY_SLOT_OST_METHOD, 4) {
- Acquire(MEMORY_SLOT_LOCK, 0xFFFF)
- Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM
- Store(Arg1, MEMORY_SLOT_OST_EVENT)
- Store(Arg2, MEMORY_SLOT_OST_STATUS)
- Release(MEMORY_SLOT_LOCK)
- }
- } // Device()
- } // Scope()
}
diff --git a/hw/i386/ssdt-misc.hex.generated b/hw/i386/ssdt-misc.hex.generated
index ba4268a60b986fb38dbae928e58ea0071419c059..cbcf61dcceeb2635c062cb043e967480ee8f38a3 100644
--- a/hw/i386/ssdt-misc.hex.generated
+++ b/hw/i386/ssdt-misc.hex.generated
@@ -2,13 +2,13 @@ static unsigned char acpi_pci64_length[] = {
0x6f
};
static unsigned char acpi_s4_pkg[] = {
-0x8f
+0x99
};
-static unsigned short ssdt_mctrl_nr_slots[] = {
-0x1aa
+static unsigned char ssdt_mctrl_nr_slots[] = {
+0x7d
};
static unsigned char acpi_s3_name[] = {
-0x7c
+0x86
};
static unsigned char acpi_pci32_start[] = {
0x2f
@@ -21,12 +21,12 @@ static unsigned char ssdp_misc_aml[] = {
0x53,
0x44,
0x54,
-0x7e,
-0x4,
+0x6c,
+0x1,
0x0,
0x0,
0x1,
-0x8b,
+0x3,
0x42,
0x58,
0x50,
@@ -49,12 +49,12 @@ static unsigned char ssdp_misc_aml[] = {
0x4e,
0x54,
0x4c,
-0x15,
-0x11,
-0x13,
+0x28,
+0x8,
+0x14,
0x20,
0x10,
-0x42,
+0x4c,
0x5,
0x5c,
0x0,
@@ -136,6 +136,16 @@ static unsigned char ssdp_misc_aml[] = {
0x0,
0x0,
0x0,
+0x8,
+0x4d,
+0x44,
+0x4e,
+0x52,
+0xc,
+0x78,
+0x56,
+0x34,
+0x12,
0x10,
0x29,
0x5c,
@@ -370,809 +380,13 @@ static unsigned char ssdp_misc_aml[] = {
0x49,
0x4f,
0x4d,
-0x58,
-0x10,
-0x4b,
-0x31,
-0x5c,
-0x2e,
-0x5f,
-0x53,
-0x42,
-0x5f,
-0x50,
-0x43,
-0x49,
-0x30,
-0x5b,
-0x82,
-0x4d,
-0x30,
-0x4d,
-0x48,
-0x50,
-0x44,
-0x8,
-0x5f,
-0x48,
-0x49,
-0x44,
-0xd,
-0x50,
-0x4e,
-0x50,
-0x30,
-0x41,
-0x30,
-0x36,
-0x0,
-0x8,
-0x5f,
-0x55,
-0x49,
-0x44,
-0xd,
-0x4d,
-0x65,
-0x6d,
-0x6f,
-0x72,
-0x79,
-0x20,
-0x68,
-0x6f,
-0x74,
-0x70,
-0x6c,
-0x75,
-0x67,
-0x20,
-0x72,
-0x65,
-0x73,
-0x6f,
-0x75,
-0x72,
-0x63,
-0x65,
-0x73,
-0x0,
-0x8,
-0x4d,
-0x44,
-0x4e,
-0x52,
-0xc,
-0x78,
-0x56,
-0x34,
-0x12,
-0x5b,
-0x80,
-0x48,
-0x50,
-0x4d,
-0x52,
-0x1,
-0xb,
-0x0,
-0xa,
-0xa,
-0x18,
-0x8,
-0x5f,
-0x43,
-0x52,
-0x53,
-0x11,
-0xd,
-0xa,
-0xa,
-0x47,
-0x1,
-0x0,
-0xa,
-0x0,
-0xa,
-0x0,
-0x18,
-0x79,
-0x0,
-0x14,
-0x13,
-0x5f,
-0x53,
-0x54,
-0x41,
-0x0,
-0xa0,
-0x9,
-0x93,
-0x4d,
-0x44,
-0x4e,
-0x52,
-0x0,
-0xa4,
-0x0,
-0xa4,
-0xa,
-0xb,
-0x5b,
-0x81,
-0x1f,
-0x48,
-0x50,
-0x4d,
-0x52,
-0x3,
-0x4d,
-0x52,
-0x42,
-0x4c,
-0x20,
-0x4d,
-0x52,
-0x42,
-0x48,
-0x20,
-0x4d,
-0x52,
-0x4c,
-0x4c,
-0x20,
-0x4d,
-0x52,
-0x4c,
-0x48,
-0x20,
-0x4d,
-0x50,
-0x58,
-0x5f,
-0x20,
-0x5b,
-0x81,
-0x13,
-0x48,
-0x50,
-0x4d,
-0x52,
-0x1,
-0x0,
-0x40,
-0xa,
-0x4d,
-0x45,
-0x53,
-0x5f,
-0x1,
-0x4d,
-0x49,
-0x4e,
-0x53,
-0x1,
-0x5b,
-0x1,
-0x4d,
-0x4c,
-0x43,
-0x4b,
-0x0,
-0x5b,
-0x81,
-0x15,
-0x48,
-0x50,
-0x4d,
-0x52,
-0x3,
-0x4d,
-0x53,
-0x45,
-0x4c,
-0x20,
-0x4d,
-0x4f,
-0x45,
-0x56,
-0x20,
-0x4d,
-0x4f,
-0x53,
-0x43,
-0x20,
-0x14,
-0x4a,
-0x4,
-0x4d,
-0x53,
-0x43,
-0x4e,
-0x0,
-0xa0,
-0x9,
-0x93,
-0x4d,
-0x44,
-0x4e,
-0x52,
-0x0,
-0xa4,
-0x0,
-0x70,
-0x0,
-0x60,
-0x5b,
-0x23,
-0x4d,
-0x4c,
-0x43,
-0x4b,
-0xff,
-0xff,
-0xa2,
-0x25,
-0x95,
-0x60,
-0x4d,
-0x44,
-0x4e,
-0x52,
-0x70,
-0x60,
-0x4d,
-0x53,
-0x45,
-0x4c,
-0xa0,
-0x13,
-0x93,
-0x4d,
-0x49,
-0x4e,
-0x53,
-0x1,
-0x4d,
-0x54,
-0x46,
-0x59,
-0x60,
-0x1,
-0x70,
-0x1,
-0x4d,
-0x49,
-0x4e,
-0x53,
-0x72,
-0x60,
-0x1,
-0x60,
-0x5b,
-0x27,
-0x4d,
-0x4c,
-0x43,
-0x4b,
-0xa4,
-0x1,
-0x14,
-0x2d,
-0x4d,
-0x52,
-0x53,
-0x54,
-0x1,
-0x70,
-0x0,
-0x60,
-0x5b,
-0x23,
-0x4d,
-0x4c,
-0x43,
-0x4b,
-0xff,
-0xff,
-0x70,
-0x99,
-0x68,
-0x0,
-0x4d,
-0x53,
-0x45,
-0x4c,
-0xa0,
-0xb,
-0x93,
-0x4d,
-0x45,
-0x53,
-0x5f,
-0x1,
-0x70,
-0xa,
-0xf,
-0x60,
-0x5b,
-0x27,
-0x4d,
-0x4c,
-0x43,
-0x4b,
-0xa4,
-0x60,
-0x14,
-0x41,
-0x18,
-0x4d,
-0x43,
-0x52,
-0x53,
-0x9,
-0x5b,
-0x23,
-0x4d,
-0x4c,
-0x43,
-0x4b,
-0xff,
-0xff,
-0x70,
-0x99,
-0x68,
-0x0,
-0x4d,
-0x53,
-0x45,
-0x4c,
-0x8,
-0x4d,
-0x52,
-0x36,
-0x34,
-0x11,
-0x33,
-0xa,
-0x30,
-0x8a,
-0x2b,
-0x0,
-0x0,
-0xc,
-0x3,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0xfe,
-0xff,
-0xff,
-0xff,
-0xff,
-0xff,
-0xff,
-0xff,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0xff,
-0xff,
-0xff,
-0xff,
-0xff,
-0xff,
-0xff,
-0xff,
-0x79,
-0x0,
-0x8a,
-0x4d,
-0x52,
-0x36,
-0x34,
-0xa,
-0xe,
-0x4d,
-0x49,
-0x4e,
-0x4c,
-0x8a,
-0x4d,
-0x52,
-0x36,
-0x34,
-0xa,
-0x12,
-0x4d,
-0x49,
-0x4e,
-0x48,
-0x8a,
-0x4d,
-0x52,
-0x36,
-0x34,
-0xa,
-0x26,
-0x4c,
-0x45,
-0x4e,
-0x4c,
-0x8a,
-0x4d,
-0x52,
-0x36,
-0x34,
-0xa,
-0x2a,
-0x4c,
-0x45,
-0x4e,
-0x48,
-0x8a,
-0x4d,
-0x52,
-0x36,
-0x34,
-0xa,
-0x16,
-0x4d,
-0x41,
-0x58,
-0x4c,
-0x8a,
-0x4d,
-0x52,
-0x36,
-0x34,
-0xa,
-0x1a,
-0x4d,
-0x41,
-0x58,
-0x48,
-0x70,
-0x4d,
-0x52,
-0x42,
-0x48,
-0x4d,
-0x49,
-0x4e,
-0x48,
-0x70,
-0x4d,
-0x52,
-0x42,
-0x4c,
-0x4d,
-0x49,
-0x4e,
-0x4c,
-0x70,
-0x4d,
-0x52,
-0x4c,
-0x48,
-0x4c,
-0x45,
-0x4e,
-0x48,
-0x70,
-0x4d,
-0x52,
-0x4c,
-0x4c,
-0x4c,
-0x45,
-0x4e,
-0x4c,
-0x72,
-0x4d,
-0x49,
-0x4e,
-0x4c,
-0x4c,
-0x45,
-0x4e,
-0x4c,
-0x4d,
-0x41,
-0x58,
-0x4c,
-0x72,
-0x4d,
-0x49,
-0x4e,
-0x48,
-0x4c,
-0x45,
-0x4e,
-0x48,
-0x4d,
-0x41,
-0x58,
-0x48,
-0xa0,
-0x14,
-0x95,
-0x4d,
-0x41,
-0x58,
-0x4c,
-0x4d,
-0x49,
-0x4e,
-0x4c,
-0x72,
-0x4d,
-0x41,
-0x58,
-0x48,
-0x1,
-0x4d,
-0x41,
-0x58,
-0x48,
-0xa0,
-0x11,
-0x95,
-0x4d,
-0x41,
-0x58,
-0x4c,
-0x1,
-0x74,
-0x4d,
-0x41,
-0x58,
-0x48,
-0x1,
-0x4d,
-0x41,
-0x58,
-0x48,
-0x74,
-0x4d,
-0x41,
-0x58,
-0x4c,
-0x1,
-0x4d,
-0x41,
-0x58,
-0x4c,
-0xa0,
-0x44,
-0x7,
-0x93,
-0x4d,
-0x41,
-0x58,
-0x48,
-0x0,
-0x8,
-0x4d,
-0x52,
-0x33,
-0x32,
-0x11,
-0x1f,
-0xa,
-0x1c,
-0x87,
-0x17,
-0x0,
-0x0,
-0xc,
-0x3,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0x0,
-0xfe,
-0xff,
-0xff,
-0xff,
-0x0,
-0x0,
-0x0,
-0x0,
-0xff,
-0xff,
-0xff,
-0xff,
-0x79,
-0x0,
-0x8a,
-0x4d,
-0x52,
-0x33,
-0x32,
-0xa,
-0xa,
-0x4d,
-0x49,
-0x4e,
-0x5f,
-0x8a,
-0x4d,
-0x52,
-0x33,
-0x32,
-0xa,
-0xe,
-0x4d,
-0x41,
-0x58,
-0x5f,
-0x8a,
-0x4d,
-0x52,
-0x33,
-0x32,
-0xa,
-0x16,
-0x4c,
-0x45,
-0x4e,
-0x5f,
-0x70,
-0x4d,
-0x49,
-0x4e,
-0x4c,
-0x4d,
-0x49,
-0x4e,
-0x5f,
-0x70,
-0x4d,
-0x41,
-0x58,
-0x4c,
-0x4d,
-0x41,
-0x58,
-0x5f,
-0x70,
-0x4c,
-0x45,
-0x4e,
-0x4c,
-0x4c,
-0x45,
-0x4e,
-0x5f,
-0x5b,
-0x27,
-0x4d,
-0x4c,
-0x43,
-0x4b,
-0xa4,
-0x4d,
-0x52,
-0x33,
-0x32,
-0x5b,
-0x27,
-0x4d,
-0x4c,
-0x43,
-0x4b,
-0xa4,
-0x4d,
-0x52,
-0x36,
-0x34,
-0x14,
-0x24,
-0x4d,
-0x50,
-0x58,
-0x4d,
-0x1,
-0x5b,
-0x23,
-0x4d,
-0x4c,
-0x43,
-0x4b,
-0xff,
-0xff,
-0x70,
-0x99,
-0x68,
-0x0,
-0x4d,
-0x53,
-0x45,
-0x4c,
-0x70,
-0x4d,
-0x50,
-0x58,
-0x5f,
-0x60,
-0x5b,
-0x27,
-0x4d,
-0x4c,
-0x43,
-0x4b,
-0xa4,
-0x60,
-0x14,
-0x28,
-0x4d,
-0x4f,
-0x53,
-0x54,
-0x4,
-0x5b,
-0x23,
-0x4d,
-0x4c,
-0x43,
-0x4b,
-0xff,
-0xff,
-0x70,
-0x99,
-0x68,
-0x0,
-0x4d,
-0x53,
-0x45,
-0x4c,
-0x70,
-0x69,
-0x4d,
-0x4f,
-0x45,
-0x56,
-0x70,
-0x6a,
-0x4d,
-0x4f,
-0x53,
-0x43,
-0x5b,
-0x27,
-0x4d,
-0x4c,
-0x43,
-0x4b
+0x58
};
static unsigned char ssdt_isa_pest[] = {
-0xd0
+0xda
};
static unsigned char acpi_s4_name[] = {
-0x88
+0x92
};
static unsigned char acpi_pci64_start[] = {
0x4d
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index a800ea7a9fde2971350f0d2464ae09cd68aed4ad..d431834030db2b7420f9ba8d086ee27a6f75dccc 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -139,19 +139,34 @@ static int pc_dimm_built_list(Object *obj, void *opaque)
uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
uint64_t address_space_size,
- uint64_t *hint, uint64_t size,
+ uint64_t *hint, uint64_t align, uint64_t size,
Error **errp)
{
GSList *list = NULL, *item;
uint64_t new_addr, ret = 0;
uint64_t address_space_end = address_space_start + address_space_size;
+ g_assert(QEMU_ALIGN_UP(address_space_start, align) == address_space_start);
+ g_assert(QEMU_ALIGN_UP(address_space_size, align) == address_space_size);
+
if (!address_space_size) {
error_setg(errp, "memory hotplug is not enabled, "
"please add maxmem option");
goto out;
}
+ if (hint && QEMU_ALIGN_UP(*hint, align) != *hint) {
+ error_setg(errp, "address must be aligned to 0x%" PRIx64 " bytes",
+ align);
+ goto out;
+ }
+
+ if (QEMU_ALIGN_UP(size, align) != size) {
+ error_setg(errp, "backend memory size must be multiple of 0x%"
+ PRIx64, align);
+ goto out;
+ }
+
assert(address_space_end > address_space_start);
object_child_foreach(qdev_get_machine(), pc_dimm_built_list, &list);
@@ -177,7 +192,7 @@ uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
error_setg(errp, "address range conflicts with '%s'", d->id);
goto out;
}
- new_addr = dimm->addr + dimm_size;
+ new_addr = QEMU_ALIGN_UP(dimm->addr + dimm_size, align);
}
}
ret = new_addr;
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 58455bd8542102e0ae2695d67c04f799ff38d805..1abbbb192e73c86652f65a4f07186c217864ae9d 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -145,7 +145,7 @@ void pcie_cap_deverr_init(PCIDevice *dev)
PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE);
pci_long_test_and_set_mask(dev->w1cmask + pos + PCI_EXP_DEVSTA,
PCI_EXP_DEVSTA_CED | PCI_EXP_DEVSTA_NFED |
- PCI_EXP_DEVSTA_URD | PCI_EXP_DEVSTA_URD);
+ PCI_EXP_DEVSTA_FED | PCI_EXP_DEVSTA_URD);
}
void pcie_cap_deverr_reset(PCIDevice *dev)
@@ -229,7 +229,7 @@ static void pcie_cap_slot_hotplug_common(PCIDevice *hotplug_dev,
/* the slot is electromechanically locked.
* This error is propagated up to qdev and then to HMP/QMP.
*/
- error_setg_errno(errp, -EBUSY, "slot is electromechanically locked");
+ error_setg_errno(errp, EBUSY, "slot is electromechanically locked");
}
}
diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c
index 9a390609332170f1910f91d73b1091133705c9a8..27c496e8c30823fb12e22c48a7a1c266e2598450 100644
--- a/hw/pci/shpc.c
+++ b/hw/pci/shpc.c
@@ -663,6 +663,7 @@ void shpc_cleanup(PCIDevice *d, MemoryRegion *bar)
SHPCDevice *shpc = d->shpc;
d->cap_present &= ~QEMU_PCI_CAP_SHPC;
memory_region_del_subregion(bar, &shpc->mmio);
+ object_unparent(OBJECT(&shpc->mmio));
/* TODO: cleanup config space changes? */
g_free(shpc->config);
g_free(shpc->cmask);
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 421a142a0dead246de408827e9291999ffaefce3..0844885eddc1750cc894ca5f1982deffa8a703cb 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -333,7 +333,7 @@ extern uintptr_t tci_tb_ptr;
#if !defined(CONFIG_USER_ONLY)
-void phys_mem_set_alloc(void *(*alloc)(size_t));
+void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align));
struct MemoryRegion *iotlb_to_region(AddressSpace *as, hwaddr index);
bool io_mem_read(struct MemoryRegion *mr, hwaddr addr,
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 74a58b4883a66a714e5e4a4eb07b806f6b84a93c..f64ab5e3e558e043cfbbb65490b03557009b6bf0 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -146,6 +146,7 @@ struct MemoryRegion {
hwaddr addr;
void (*destructor)(MemoryRegion *mr);
ram_addr_t ram_addr;
+ uint64_t align;
bool subpage;
bool terminates;
bool romd_mode;
@@ -838,6 +839,7 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr,
*/
ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr);
+uint64_t memory_region_get_alignment(const MemoryRegion *mr);
/**
* memory_region_del_subregion: Remove a subregion.
*
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 7c3731f1b0c0a2930096ad40071c75b7262b492c..9d85b89e4f04b81090088719549ab56d92ce9a17 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -24,6 +24,8 @@
* address space begins.
* @hotplug_memory: hotplug memory addess space container
* @acpi_dev: link to ACPI PM device that performs ACPI hotplug handling
+ * @enforce_aligned_dimm: check that DIMM's address/size is aligned by
+ * backend's alignment value if provided
*/
struct PCMachineState {
/*< private >*/
@@ -38,12 +40,14 @@ struct PCMachineState {
uint64_t max_ram_below_4g;
bool vmport;
+ bool enforce_aligned_dimm;
};
#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
#define PC_MACHINE_MEMHP_REGION_SIZE "hotplug-memory-region-size"
#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
#define PC_MACHINE_VMPORT "vmport"
+#define PC_MACHINE_ENFORCE_ALIGNED_DIMM "enforce-aligned-dimm"
/**
* PCMachineClass:
diff --git a/include/hw/loader.h b/include/hw/loader.h
index 054c6a22b5785fe109e4ccedf4666c35390ae2da..64816395dcd601ad7dd0e25770aa49b443e843f4 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -59,7 +59,7 @@ extern bool rom_file_has_mr;
int rom_add_file(const char *file, const char *fw_dir,
hwaddr addr, int32_t bootindex,
bool option_rom);
-void *rom_add_blob(const char *name, const void *blob, size_t len,
+ram_addr_t rom_add_blob(const char *name, const void *blob, size_t len,
hwaddr addr, const char *fw_file_name,
FWCfgReadCallback fw_callback, void *callback_opaque);
int rom_add_elf_program(const char *name, void *data, size_t datasize,
diff --git a/include/hw/mem/pc-dimm.h b/include/hw/mem/pc-dimm.h
index 761eeef801519845d7879dd9d52411049df45902..e1dcbbcd587620373c5684486b20d35cc747e7bc 100644
--- a/include/hw/mem/pc-dimm.h
+++ b/include/hw/mem/pc-dimm.h
@@ -72,7 +72,7 @@ typedef struct PCDIMMDeviceClass {
uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
uint64_t address_space_size,
- uint64_t *hint, uint64_t size,
+ uint64_t *hint, uint64_t align, uint64_t size,
Error **errp);
int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index c0324344d59b288be7ac1c53a61c5f63b1db8019..b3300cc239f627c526479652f14977935de4d642 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -5,6 +5,7 @@
#include
#include
#include
+#include
#include
#ifdef __OpenBSD__
#include
@@ -103,7 +104,7 @@ typedef signed int int_fast16_t;
int qemu_daemon(int nochdir, int noclose);
void *qemu_try_memalign(size_t alignment, size_t size);
void *qemu_memalign(size_t alignment, size_t size);
-void *qemu_anon_ram_alloc(size_t size);
+void *qemu_anon_ram_alloc(size_t size, uint64_t *align);
void qemu_vfree(void *ptr);
void qemu_anon_ram_free(void *ptr, size_t size);
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index b0cd657f77b6f60850f87afa127f50987d1bce81..22e42ef236f06c00b02e71d97db268fa26efbfca 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -163,6 +163,7 @@ extern KVMState *kvm_state;
/* external API */
+bool kvm_has_free_slot(MachineState *ms);
int kvm_has_sync_mmu(void);
int kvm_has_vcpu_events(void);
int kvm_has_robust_singlestep(void);
diff --git a/kvm-all.c b/kvm-all.c
index 596e7ce6c3e02719caf9955eb6193d41381678d1..937bc9d9035a420a58351f87fa44ce98a3723d4b 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -132,7 +132,7 @@ static const KVMCapabilityInfo kvm_required_capabilites[] = {
KVM_CAP_LAST_INFO
};
-static KVMSlot *kvm_alloc_slot(KVMState *s)
+static KVMSlot *kvm_get_free_slot(KVMState *s)
{
int i;
@@ -142,6 +142,22 @@ static KVMSlot *kvm_alloc_slot(KVMState *s)
}
}
+ return NULL;
+}
+
+bool kvm_has_free_slot(MachineState *ms)
+{
+ return kvm_get_free_slot(KVM_STATE(ms->accelerator));
+}
+
+static KVMSlot *kvm_alloc_slot(KVMState *s)
+{
+ KVMSlot *slot = kvm_get_free_slot(s);
+
+ if (slot) {
+ return slot;
+ }
+
fprintf(stderr, "%s: no free slot available\n", __func__);
abort();
}
diff --git a/kvm-stub.c b/kvm-stub.c
index 43fc0dd01e0d4f390de7c2657b17981d0e0e5a3e..7ba90c546f55d86d1d953a8d77c81239e4f044ca 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -147,4 +147,9 @@ int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
{
return -ENOSYS;
}
+
+bool kvm_has_free_slot(MachineState *ms)
+{
+ return false;
+}
#endif
diff --git a/memory.c b/memory.c
index 0f4fdc7db7dd978475494ff183267c1ad28f6326..15cf9ebd8423b0b04862df77772f147b085d54fd 100644
--- a/memory.c
+++ b/memory.c
@@ -1749,6 +1749,11 @@ ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
return mr->ram_addr;
}
+uint64_t memory_region_get_alignment(const MemoryRegion *mr)
+{
+ return mr->align;
+}
+
static int cmp_flatrange_addr(const void *addr_, const void *fr_)
{
const AddrRange *addr = addr_;
diff --git a/qemu-char.c b/qemu-char.c
index 4a76f0f805b6db4f66e0eb39ed4f6427f8f1cdda..a8b01da3ee8fdf1561a37b0e273b1a97c9949608 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -88,6 +88,7 @@
#define READ_BUF_LEN 4096
#define READ_RETRIES 10
#define CHR_MAX_FILENAME_SIZE 256
+#define TCP_MAX_FDS 16
/***********************************************************/
/* Socket address helpers */
@@ -2668,6 +2669,8 @@ static int tcp_get_msgfds(CharDriverState *chr, int *fds, int num)
TCPCharDriver *s = chr->opaque;
int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num;
+ assert(num <= TCP_MAX_FDS);
+
if (to_copy) {
int i;
@@ -2762,7 +2765,7 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
struct iovec iov[1];
union {
struct cmsghdr cmsg;
- char control[CMSG_SPACE(sizeof(int))];
+ char control[CMSG_SPACE(sizeof(int) * TCP_MAX_FDS)];
} msg_control;
int flags = 0;
ssize_t ret;
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index d2474711198837df84154499a5c4b037e886932f..50709ba6b5052162fb5230697e9c21c540a827cc 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -404,7 +404,7 @@ int kvm_arch_get_registers(CPUState *cs)
* to grow. We also have to use MAP parameters that avoid
* read-only mapping of guest pages.
*/
-static void *legacy_s390_alloc(size_t size)
+static void *legacy_s390_alloc(size_t size, , uint64_t *align)
{
void *mem;
diff --git a/tests/acpi-test-data/pc/DSDT b/tests/acpi-test-data/pc/DSDT
index d37ec34454e6f3db5e91b777f94e03be67a5f583..ee9cc6781cea3a9515b9a176eea3459f8e4d8655 100644
Binary files a/tests/acpi-test-data/pc/DSDT and b/tests/acpi-test-data/pc/DSDT differ
diff --git a/tests/acpi-test-data/pc/SSDT b/tests/acpi-test-data/pc/SSDT
index eb2d8b698ce6a3a910a05244a3b6cf80bf818fb9..558e4c85b031ec081045aec6cc382a680e9c6009 100644
Binary files a/tests/acpi-test-data/pc/SSDT and b/tests/acpi-test-data/pc/SSDT differ
diff --git a/tests/acpi-test-data/q35/DSDT b/tests/acpi-test-data/q35/DSDT
index 2d2bc4adaf54666fe7864e7f39203411b7c308f7..ef0c75f4236de3e6f727e21991533f2bf8279dee 100644
Binary files a/tests/acpi-test-data/q35/DSDT and b/tests/acpi-test-data/q35/DSDT differ
diff --git a/tests/acpi-test-data/q35/SSDT b/tests/acpi-test-data/q35/SSDT
index 778b79bf428b5d7602b7b80c9434e38c79718bb2..4e45510181c4038505ae1815b76799a2cd0e8808 100644
Binary files a/tests/acpi-test-data/q35/SSDT and b/tests/acpi-test-data/q35/SSDT differ
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index 8c9d80e9fe50002fc6b3a944d896547f89c9c3ec..16fcec2f37e40b94ccc8f7af0ebdaa74f6657af2 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -124,7 +124,7 @@ void *qemu_memalign(size_t alignment, size_t size)
}
/* alloc shared memory pages */
-void *qemu_anon_ram_alloc(size_t size)
+void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment)
{
size_t align = QEMU_VMALLOC_ALIGN;
size_t total = size + align - getpagesize();
@@ -136,6 +136,9 @@ void *qemu_anon_ram_alloc(size_t size)
return NULL;
}
+ if (alignment) {
+ *alignment = align;
+ }
ptr += offset;
total -= offset;
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index a3eab4acba2492ddf5fbb0ea4fde87a1ba456a17..87cfbe08343a1406619543c8ebfe3337fbb67a82 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -67,7 +67,7 @@ void *qemu_memalign(size_t alignment, size_t size)
return qemu_oom_check(qemu_try_memalign(alignment, size));
}
-void *qemu_anon_ram_alloc(size_t size)
+void *qemu_anon_ram_alloc(size_t size, uint64_t *align)
{
void *ptr;