pc, pci, misc bugfixes

A bunch of bugfixes for 2.2.
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJUc4AjAAoJECgfDbjSjVRp084IAIYh48pK0MrCTSrDh2/3UCkN
 Z+htfYS9uEpJHbIeJrn4u1e2Z90bgcovq8Cg36pUeGZtI5CVZYv/lmPjcOwJEruX
 RIveOes87S58rp39mM2/24k1lp2u6VyS+QlrQlmO/ukKEz4ABhy0yF70yTuldX3b
 RQ6d1aa/MaEsEx/iTWcQo6cDIdeWUYg8Mt34fSLfcphbHcSC02t8VCOX9cOR4jR9
 80Lf78LGEdTCMexrcxs392o7npZGJLzCTWXLRtf6Q4/uPBM8Cmq60yt8JI0WCqbT
 ram3XLv9u7GwPgeAp5HPKVV/LxRsDf5HjET3fW8QwbrUP2BvQ5PCgzKCUY6sT20=
 =akFH
 -----END PGP SIGNATURE-----

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

pc, pci, misc bugfixes

A bunch of bugfixes for 2.2.

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

# gpg: Signature made Mon 24 Nov 2014 18:59:47 GMT using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream:
  pc: acpi: mark all possible CPUs as enabled in SRAT
  pcie: fix improper use of negative value
  pcie: fix typo in pcie_cap_deverr_init()
  target-i386: move generic memory hotplug methods to DSDTs
  acpi-build: mark RAM dirty on table update
  hw/pci: fix crash on shpc error flow
  pc: count in 1Gb hugepage alignment when sizing hotplug-memory container
  pc: explicitly check maxmem limit when adding DIMM
  pc: pc-dimm: use backend alignment during address auto allocation
  pc: align DIMM's address/size by backend's alignment value
  memory: expose alignment used for allocating RAM as MemoryRegion API
  pc: limit DIMM address and size to page aligned values
  pc: make pc_dimm_plug() more readble
  pc: kvm: check if KVM has free memory slots to avoid abort()
  qemu-char: fix tcp_get_fds

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2014-11-24 19:31:50 +00:00
commit ca6028185d
35 changed files with 1962 additions and 1025 deletions

9
exec.c
View file

@ -909,14 +909,15 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
uint16_t section); uint16_t section);
static subpage_t *subpage_init(AddressSpace *as, hwaddr base); 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. * Set a custom physical guest memory alloator.
* Accelerators with unusual needs may need this. Hopefully, we can * Accelerators with unusual needs may need this. Hopefully, we can
* get rid of it eventually. * 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; phys_mem_alloc = alloc;
} }
@ -1098,6 +1099,7 @@ static void *file_ram_alloc(RAMBlock *block,
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto error; goto error;
} }
block->mr->align = hpagesize;
if (memory < hpagesize) { if (memory < hpagesize) {
error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to " 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()) { if (xen_enabled()) {
xen_ram_alloc(new_block->offset, new_block->length, new_block->mr); xen_ram_alloc(new_block->offset, new_block->length, new_block->mr);
} else { } 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) { if (!new_block->host) {
error_setg_errno(errp, errno, error_setg_errno(errp, errno,
"cannot set up guest memory '%s'", "cannot set up guest memory '%s'",

View file

@ -811,12 +811,12 @@ err:
return -1; 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, hwaddr addr, const char *fw_file_name,
FWCfgReadCallback fw_callback, void *callback_opaque) FWCfgReadCallback fw_callback, void *callback_opaque)
{ {
Rom *rom; Rom *rom;
void *data = NULL; ram_addr_t ret = RAM_ADDR_MAX;
rom = g_malloc0(sizeof(*rom)); rom = g_malloc0(sizeof(*rom));
rom->name = g_strdup(name); 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); rom_insert(rom);
if (fw_file_name && fw_cfg) { if (fw_file_name && fw_cfg) {
char devpath[100]; char devpath[100];
void *data;
snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name); snprintf(devpath, sizeof(devpath), "/rom@%s", fw_file_name);
if (rom_file_has_mr) { if (rom_file_has_mr) {
data = rom_set_mr(rom, OBJECT(fw_cfg), devpath); data = rom_set_mr(rom, OBJECT(fw_cfg), devpath);
ret = memory_region_get_ram_addr(rom->mr);
} else { } else {
data = rom->data; data = rom->data;
} }
@ -841,7 +843,7 @@ void *rom_add_blob(const char *name, const void *blob, size_t len,
fw_callback, callback_opaque, fw_callback, callback_opaque,
data, rom->romsize); data, rom->romsize);
} }
return data; return ret;
} }
/* This function is specific for elf program because we don't need to allocate /* This function is specific for elf program because we don't need to allocate

View file

@ -56,6 +56,7 @@
#include "qapi/qmp/qint.h" #include "qapi/qmp/qint.h"
#include "qom/qom-qobject.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 /* 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 * -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 static void
build_srat(GArray *table_data, GArray *linker, build_srat(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
AcpiCpuInfo *cpu, PcGuestInfo *guest_info)
{ {
AcpiSystemResourceAffinityTable *srat; AcpiSystemResourceAffinityTable *srat;
AcpiSratProcessorAffinity *core; AcpiSratProcessorAffinity *core;
@ -1300,11 +1300,7 @@ build_srat(GArray *table_data, GArray *linker,
core->proximity_lo = curnode; core->proximity_lo = curnode;
memset(core->proximity_hi, 0, 3); memset(core->proximity_hi, 0, 3);
core->local_sapic_eid = 0; core->local_sapic_eid = 0;
if (test_bit(i, cpu->found_cpus)) {
core->flags = cpu_to_le32(1); core->flags = cpu_to_le32(1);
} else {
core->flags = cpu_to_le32(0);
}
} }
@ -1511,7 +1507,7 @@ static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
typedef typedef
struct AcpiBuildState { struct AcpiBuildState {
/* Copy of table in RAM (for patching). */ /* Copy of table in RAM (for patching). */
uint8_t *table_ram; ram_addr_t table_ram;
uint32_t table_size; uint32_t table_size;
/* Is table patched? */ /* Is table patched? */
uint8_t patched; uint8_t patched;
@ -1622,7 +1618,7 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
} }
if (guest_info->numa_nodes) { if (guest_info->numa_nodes) {
acpi_add_table(table_offsets, tables->table_data); 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)) { if (acpi_get_mcfg(&mcfg)) {
acpi_add_table(table_offsets, tables->table_data); acpi_add_table(table_offsets, tables->table_data);
@ -1716,7 +1712,10 @@ static void acpi_build_update(void *build_opaque, uint32_t offset)
acpi_build(build_state->guest_info, &tables); acpi_build(build_state->guest_info, &tables);
assert(acpi_data_len(tables.table_data) == build_state->table_size); 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); build_state->table_size);
acpi_build_tables_cleanup(&tables, true); acpi_build_tables_cleanup(&tables, true);
@ -1728,7 +1727,7 @@ static void acpi_build_reset(void *build_opaque)
build_state->patched = 0; 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) const char *name)
{ {
return rom_add_blob(name, blob->data, acpi_data_len(blob), -1, 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 */ /* Now expose it all to Guest */
build_state->table_ram = acpi_add_rom_blob(build_state, tables.table_data, build_state->table_ram = acpi_add_rom_blob(build_state, tables.table_data,
ACPI_BUILD_TABLE_FILE); ACPI_BUILD_TABLE_FILE);
assert(build_state->table_ram != RAM_ADDR_MAX);
build_state->table_size = acpi_data_len(tables.table_data); build_state->table_size = acpi_data_len(tables.table_data);
acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader"); acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader");

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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()

View file

@ -297,13 +297,12 @@ DefinitionBlock (
#include "hw/acpi/pc-hotplug.h" #include "hw/acpi/pc-hotplug.h"
#define CPU_STATUS_BASE PIIX4_CPU_HOTPLUG_IO_BASE #define CPU_STATUS_BASE PIIX4_CPU_HOTPLUG_IO_BASE
#include "acpi-dsdt-cpu-hotplug.dsl" #include "acpi-dsdt-cpu-hotplug.dsl"
#include "acpi-dsdt-mem-hotplug.dsl"
/**************************************************************** /****************************************************************
* General purpose events * General purpose events
****************************************************************/ ****************************************************************/
External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_SCAN_METHOD, MethodObj)
Scope(\_GPE) { Scope(\_GPE) {
Name(_HID, "ACPI0006") Name(_HID, "ACPI0006")

View file

@ -3,12 +3,12 @@ static unsigned char AcpiDsdtAmlCode[] = {
0x53, 0x53,
0x44, 0x44,
0x54, 0x54,
0xf7, 0x8,
0xa, 0xe,
0x0, 0x0,
0x0, 0x0,
0x1, 0x1,
0x1f, 0xfc,
0x42, 0x42,
0x58, 0x58,
0x50, 0x50,
@ -32,8 +32,8 @@ static unsigned char AcpiDsdtAmlCode[] = {
0x54, 0x54,
0x4c, 0x4c,
0x28, 0x28,
0x5, 0x8,
0x10, 0x14,
0x20, 0x20,
0x10, 0x10,
0x49, 0x49,
@ -2593,6 +2593,791 @@ static unsigned char AcpiDsdtAmlCode[] = {
0xa, 0xa,
0xb, 0xb,
0x10, 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, 0x45,
0xd, 0xd,
0x5f, 0x5f,

View file

@ -1247,6 +1247,11 @@ FWCfgState *pc_memory_init(MachineState *machine,
pcms->hotplug_memory_base = pcms->hotplug_memory_base =
ROUND_UP(0x100000000ULL + above_4g_mem_size, 1ULL << 30); 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) < if ((pcms->hotplug_memory_base + hotplug_mem_size) <
hotplug_mem_size) { hotplug_mem_size) {
error_report("unsupported amount of maximum memory: " RAM_ADDR_FMT, error_report("unsupported amount of maximum memory: " RAM_ADDR_FMT,
@ -1545,6 +1550,37 @@ void qemu_register_pc_machine(QEMUMachine *m)
g_free(name); 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, static void pc_dimm_plug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp) DeviceState *dev, Error **errp)
{ {
@ -1556,20 +1592,40 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
PCDIMMDevice *dimm = PC_DIMM(dev); PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
MemoryRegion *mr = ddc->get_memory_region(dimm); MemoryRegion *mr = ddc->get_memory_region(dimm);
uint64_t addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, uint64_t existing_dimms_capacity = 0;
&local_err); 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) { if (local_err) {
goto out; 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, addr = pc_dimm_get_free_addr(pcms->hotplug_memory_base,
memory_region_size(&pcms->hotplug_memory), memory_region_size(&pcms->hotplug_memory),
!addr ? NULL : &addr, !addr ? NULL : &addr, align,
memory_region_size(mr), &local_err); memory_region_size(mr), &local_err);
if (local_err) { if (local_err) {
goto out; 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); object_property_set_int(OBJECT(dev), addr, PC_DIMM_ADDR_PROP, &local_err);
if (local_err) { if (local_err) {
goto out; goto out;
@ -1598,6 +1654,11 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
goto out; 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, memory_region_add_subregion(&pcms->hotplug_memory,
addr - pcms->hotplug_memory_base, mr); addr - pcms->hotplug_memory_base, mr);
vmstate_register_ram(mr, dev); vmstate_register_ram(mr, dev);
@ -1725,6 +1786,13 @@ static void pc_machine_set_vmport(Object *obj, bool value, Error **errp)
pcms->vmport = value; 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) static void pc_machine_initfn(Object *obj)
{ {
PCMachineState *pcms = PC_MACHINE(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_get_max_ram_below_4g,
pc_machine_set_max_ram_below_4g, pc_machine_set_max_ram_below_4g,
NULL, NULL, NULL); NULL, NULL, NULL);
pcms->vmport = !xen_enabled(); pcms->vmport = !xen_enabled();
object_property_add_bool(obj, PC_MACHINE_VMPORT, object_property_add_bool(obj, PC_MACHINE_VMPORT,
pc_machine_get_vmport, pc_machine_get_vmport,
pc_machine_set_vmport, pc_machine_set_vmport,
NULL); 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) static void pc_machine_class_init(ObjectClass *oc, void *data)

View file

@ -305,10 +305,12 @@ static void pc_init_pci(MachineState *machine)
static void pc_compat_2_1(MachineState *machine) static void pc_compat_2_1(MachineState *machine)
{ {
PCMachineState *pcms = PC_MACHINE(machine);
smbios_uuid_encoded = false; smbios_uuid_encoded = false;
x86_cpu_compat_set_features("coreduo", FEAT_1_ECX, CPUID_EXT_VMX, 0); 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_set_features("core2duo", FEAT_1_ECX, CPUID_EXT_VMX, 0);
x86_cpu_compat_kvm_no_autodisable(FEAT_8000_0001_ECX, CPUID_EXT3_SVM); 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) static void pc_compat_2_0(MachineState *machine)

View file

@ -284,6 +284,9 @@ static void pc_q35_init(MachineState *machine)
static void pc_compat_2_1(MachineState *machine) static void pc_compat_2_1(MachineState *machine)
{ {
PCMachineState *pcms = PC_MACHINE(machine);
pcms->enforce_aligned_dimm = false;
smbios_uuid_encoded = false; smbios_uuid_encoded = false;
x86_cpu_compat_set_features("coreduo", FEAT_1_ECX, CPUID_EXT_VMX, 0); 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_set_features("core2duo", FEAT_1_ECX, CPUID_EXT_VMX, 0);

View file

@ -405,13 +405,12 @@ DefinitionBlock (
#include "hw/acpi/pc-hotplug.h" #include "hw/acpi/pc-hotplug.h"
#define CPU_STATUS_BASE ICH9_CPU_HOTPLUG_IO_BASE #define CPU_STATUS_BASE ICH9_CPU_HOTPLUG_IO_BASE
#include "acpi-dsdt-cpu-hotplug.dsl" #include "acpi-dsdt-cpu-hotplug.dsl"
#include "acpi-dsdt-mem-hotplug.dsl"
/**************************************************************** /****************************************************************
* General purpose events * General purpose events
****************************************************************/ ****************************************************************/
External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_SCAN_METHOD, MethodObj)
Scope(\_GPE) { Scope(\_GPE) {
Name(_HID, "ACPI0006") Name(_HID, "ACPI0006")

View file

@ -3,12 +3,12 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
0x53, 0x53,
0x44, 0x44,
0x54, 0x54,
0xe5, 0xf6,
0x1c, 0x1f,
0x0, 0x0,
0x0, 0x0,
0x1, 0x1,
0xb7, 0x91,
0x42, 0x42,
0x58, 0x58,
0x50, 0x50,
@ -31,9 +31,9 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
0x4e, 0x4e,
0x54, 0x54,
0x4c, 0x4c,
0x15, 0x28,
0x11, 0x8,
0x13, 0x14,
0x20, 0x20,
0x10, 0x10,
0x49, 0x49,
@ -7234,6 +7234,791 @@ static unsigned char Q35AcpiDsdtAmlCode[] = {
0xa, 0xa,
0xb, 0xb,
0x10, 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, 0x42,
0xa, 0xa,
0x5f, 0x5f,

View file

@ -11,7 +11,7 @@ static unsigned char ssdm_mem_aml[] = {
0x0, 0x0,
0x0, 0x0,
0x2, 0x2,
0x71, 0x66,
0x42, 0x42,
0x58, 0x58,
0x50, 0x50,
@ -34,9 +34,9 @@ static unsigned char ssdm_mem_aml[] = {
0x4e, 0x4e,
0x54, 0x54,
0x4c, 0x4c,
0x15, 0x28,
0x11, 0x8,
0x13, 0x14,
0x20, 0x20,
0x10, 0x10,
0x42, 0x42,

View file

@ -36,6 +36,8 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
Name(P1E, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) Name(P1E, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 })
ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_length ACPI_EXTRACT_NAME_BUFFER8 acpi_pci64_length
Name(P1L, Buffer() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) 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()
} }

View file

@ -2,13 +2,13 @@ static unsigned char acpi_pci64_length[] = {
0x6f 0x6f
}; };
static unsigned char acpi_s4_pkg[] = { static unsigned char acpi_s4_pkg[] = {
0x8f 0x99
}; };
static unsigned short ssdt_mctrl_nr_slots[] = { static unsigned char ssdt_mctrl_nr_slots[] = {
0x1aa 0x7d
}; };
static unsigned char acpi_s3_name[] = { static unsigned char acpi_s3_name[] = {
0x7c 0x86
}; };
static unsigned char acpi_pci32_start[] = { static unsigned char acpi_pci32_start[] = {
0x2f 0x2f
@ -21,12 +21,12 @@ static unsigned char ssdp_misc_aml[] = {
0x53, 0x53,
0x44, 0x44,
0x54, 0x54,
0x7e, 0x6c,
0x4, 0x1,
0x0, 0x0,
0x0, 0x0,
0x1, 0x1,
0x8b, 0x3,
0x42, 0x42,
0x58, 0x58,
0x50, 0x50,
@ -49,12 +49,12 @@ static unsigned char ssdp_misc_aml[] = {
0x4e, 0x4e,
0x54, 0x54,
0x4c, 0x4c,
0x15, 0x28,
0x11, 0x8,
0x13, 0x14,
0x20, 0x20,
0x10, 0x10,
0x42, 0x4c,
0x5, 0x5,
0x5c, 0x5c,
0x0, 0x0,
@ -136,6 +136,16 @@ static unsigned char ssdp_misc_aml[] = {
0x0, 0x0,
0x0, 0x0,
0x0, 0x0,
0x8,
0x4d,
0x44,
0x4e,
0x52,
0xc,
0x78,
0x56,
0x34,
0x12,
0x10, 0x10,
0x29, 0x29,
0x5c, 0x5c,
@ -370,809 +380,13 @@ static unsigned char ssdp_misc_aml[] = {
0x49, 0x49,
0x4f, 0x4f,
0x4d, 0x4d,
0x58, 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
}; };
static unsigned char ssdt_isa_pest[] = { static unsigned char ssdt_isa_pest[] = {
0xd0 0xda
}; };
static unsigned char acpi_s4_name[] = { static unsigned char acpi_s4_name[] = {
0x88 0x92
}; };
static unsigned char acpi_pci64_start[] = { static unsigned char acpi_pci64_start[] = {
0x4d 0x4d

View file

@ -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 pc_dimm_get_free_addr(uint64_t address_space_start,
uint64_t address_space_size, uint64_t address_space_size,
uint64_t *hint, uint64_t size, uint64_t *hint, uint64_t align, uint64_t size,
Error **errp) Error **errp)
{ {
GSList *list = NULL, *item; GSList *list = NULL, *item;
uint64_t new_addr, ret = 0; uint64_t new_addr, ret = 0;
uint64_t address_space_end = address_space_start + address_space_size; 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) { if (!address_space_size) {
error_setg(errp, "memory hotplug is not enabled, " error_setg(errp, "memory hotplug is not enabled, "
"please add maxmem option"); "please add maxmem option");
goto out; 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); assert(address_space_end > address_space_start);
object_child_foreach(qdev_get_machine(), pc_dimm_built_list, &list); 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); error_setg(errp, "address range conflicts with '%s'", d->id);
goto out; goto out;
} }
new_addr = dimm->addr + dimm_size; new_addr = QEMU_ALIGN_UP(dimm->addr + dimm_size, align);
} }
} }
ret = new_addr; ret = new_addr;

View file

@ -145,7 +145,7 @@ void pcie_cap_deverr_init(PCIDevice *dev)
PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE); PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE);
pci_long_test_and_set_mask(dev->w1cmask + pos + PCI_EXP_DEVSTA, pci_long_test_and_set_mask(dev->w1cmask + pos + PCI_EXP_DEVSTA,
PCI_EXP_DEVSTA_CED | PCI_EXP_DEVSTA_NFED | 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) 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. /* the slot is electromechanically locked.
* This error is propagated up to qdev and then to HMP/QMP. * 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");
} }
} }

View file

@ -663,6 +663,7 @@ void shpc_cleanup(PCIDevice *d, MemoryRegion *bar)
SHPCDevice *shpc = d->shpc; SHPCDevice *shpc = d->shpc;
d->cap_present &= ~QEMU_PCI_CAP_SHPC; d->cap_present &= ~QEMU_PCI_CAP_SHPC;
memory_region_del_subregion(bar, &shpc->mmio); memory_region_del_subregion(bar, &shpc->mmio);
object_unparent(OBJECT(&shpc->mmio));
/* TODO: cleanup config space changes? */ /* TODO: cleanup config space changes? */
g_free(shpc->config); g_free(shpc->config);
g_free(shpc->cmask); g_free(shpc->cmask);

View file

@ -333,7 +333,7 @@ extern uintptr_t tci_tb_ptr;
#if !defined(CONFIG_USER_ONLY) #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); struct MemoryRegion *iotlb_to_region(AddressSpace *as, hwaddr index);
bool io_mem_read(struct MemoryRegion *mr, hwaddr addr, bool io_mem_read(struct MemoryRegion *mr, hwaddr addr,

View file

@ -146,6 +146,7 @@ struct MemoryRegion {
hwaddr addr; hwaddr addr;
void (*destructor)(MemoryRegion *mr); void (*destructor)(MemoryRegion *mr);
ram_addr_t ram_addr; ram_addr_t ram_addr;
uint64_t align;
bool subpage; bool subpage;
bool terminates; bool terminates;
bool romd_mode; 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); 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. * memory_region_del_subregion: Remove a subregion.
* *

View file

@ -24,6 +24,8 @@
* address space begins. * address space begins.
* @hotplug_memory: hotplug memory addess space container * @hotplug_memory: hotplug memory addess space container
* @acpi_dev: link to ACPI PM device that performs ACPI hotplug handling * @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 { struct PCMachineState {
/*< private >*/ /*< private >*/
@ -38,12 +40,14 @@ struct PCMachineState {
uint64_t max_ram_below_4g; uint64_t max_ram_below_4g;
bool vmport; bool vmport;
bool enforce_aligned_dimm;
}; };
#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device" #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
#define PC_MACHINE_MEMHP_REGION_SIZE "hotplug-memory-region-size" #define PC_MACHINE_MEMHP_REGION_SIZE "hotplug-memory-region-size"
#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g" #define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
#define PC_MACHINE_VMPORT "vmport" #define PC_MACHINE_VMPORT "vmport"
#define PC_MACHINE_ENFORCE_ALIGNED_DIMM "enforce-aligned-dimm"
/** /**
* PCMachineClass: * PCMachineClass:

View file

@ -59,7 +59,7 @@ extern bool rom_file_has_mr;
int rom_add_file(const char *file, const char *fw_dir, int rom_add_file(const char *file, const char *fw_dir,
hwaddr addr, int32_t bootindex, hwaddr addr, int32_t bootindex,
bool option_rom); 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, hwaddr addr, const char *fw_file_name,
FWCfgReadCallback fw_callback, void *callback_opaque); FWCfgReadCallback fw_callback, void *callback_opaque);
int rom_add_elf_program(const char *name, void *data, size_t datasize, int rom_add_elf_program(const char *name, void *data, size_t datasize,

View file

@ -72,7 +72,7 @@ typedef struct PCDIMMDeviceClass {
uint64_t pc_dimm_get_free_addr(uint64_t address_space_start, uint64_t pc_dimm_get_free_addr(uint64_t address_space_start,
uint64_t address_space_size, uint64_t address_space_size,
uint64_t *hint, uint64_t size, uint64_t *hint, uint64_t align, uint64_t size,
Error **errp); Error **errp);
int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp); int pc_dimm_get_free_slot(const int *hint, int max_slots, Error **errp);

View file

@ -5,6 +5,7 @@
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#ifdef __OpenBSD__ #ifdef __OpenBSD__
#include <sys/signal.h> #include <sys/signal.h>
@ -103,7 +104,7 @@ typedef signed int int_fast16_t;
int qemu_daemon(int nochdir, int noclose); int qemu_daemon(int nochdir, int noclose);
void *qemu_try_memalign(size_t alignment, size_t size); void *qemu_try_memalign(size_t alignment, size_t size);
void *qemu_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_vfree(void *ptr);
void qemu_anon_ram_free(void *ptr, size_t size); void qemu_anon_ram_free(void *ptr, size_t size);

View file

@ -163,6 +163,7 @@ extern KVMState *kvm_state;
/* external API */ /* external API */
bool kvm_has_free_slot(MachineState *ms);
int kvm_has_sync_mmu(void); int kvm_has_sync_mmu(void);
int kvm_has_vcpu_events(void); int kvm_has_vcpu_events(void);
int kvm_has_robust_singlestep(void); int kvm_has_robust_singlestep(void);

View file

@ -132,7 +132,7 @@ static const KVMCapabilityInfo kvm_required_capabilites[] = {
KVM_CAP_LAST_INFO KVM_CAP_LAST_INFO
}; };
static KVMSlot *kvm_alloc_slot(KVMState *s) static KVMSlot *kvm_get_free_slot(KVMState *s)
{ {
int i; 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__); fprintf(stderr, "%s: no free slot available\n", __func__);
abort(); abort();
} }

View file

@ -147,4 +147,9 @@ int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq)
{ {
return -ENOSYS; return -ENOSYS;
} }
bool kvm_has_free_slot(MachineState *ms)
{
return false;
}
#endif #endif

View file

@ -1749,6 +1749,11 @@ ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
return mr->ram_addr; 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_) static int cmp_flatrange_addr(const void *addr_, const void *fr_)
{ {
const AddrRange *addr = addr_; const AddrRange *addr = addr_;

View file

@ -88,6 +88,7 @@
#define READ_BUF_LEN 4096 #define READ_BUF_LEN 4096
#define READ_RETRIES 10 #define READ_RETRIES 10
#define CHR_MAX_FILENAME_SIZE 256 #define CHR_MAX_FILENAME_SIZE 256
#define TCP_MAX_FDS 16
/***********************************************************/ /***********************************************************/
/* Socket address helpers */ /* Socket address helpers */
@ -2668,6 +2669,8 @@ static int tcp_get_msgfds(CharDriverState *chr, int *fds, int num)
TCPCharDriver *s = chr->opaque; TCPCharDriver *s = chr->opaque;
int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num; int to_copy = (s->read_msgfds_num < num) ? s->read_msgfds_num : num;
assert(num <= TCP_MAX_FDS);
if (to_copy) { if (to_copy) {
int i; int i;
@ -2762,7 +2765,7 @@ static ssize_t tcp_chr_recv(CharDriverState *chr, char *buf, size_t len)
struct iovec iov[1]; struct iovec iov[1];
union { union {
struct cmsghdr cmsg; struct cmsghdr cmsg;
char control[CMSG_SPACE(sizeof(int))]; char control[CMSG_SPACE(sizeof(int) * TCP_MAX_FDS)];
} msg_control; } msg_control;
int flags = 0; int flags = 0;
ssize_t ret; ssize_t ret;

View file

@ -404,7 +404,7 @@ int kvm_arch_get_registers(CPUState *cs)
* to grow. We also have to use MAP parameters that avoid * to grow. We also have to use MAP parameters that avoid
* read-only mapping of guest pages. * 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; void *mem;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -124,7 +124,7 @@ void *qemu_memalign(size_t alignment, size_t size)
} }
/* alloc shared memory pages */ /* 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 align = QEMU_VMALLOC_ALIGN;
size_t total = size + align - getpagesize(); size_t total = size + align - getpagesize();
@ -136,6 +136,9 @@ void *qemu_anon_ram_alloc(size_t size)
return NULL; return NULL;
} }
if (alignment) {
*alignment = align;
}
ptr += offset; ptr += offset;
total -= offset; total -= offset;

View file

@ -67,7 +67,7 @@ void *qemu_memalign(size_t alignment, size_t size)
return qemu_oom_check(qemu_try_memalign(alignment, 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; void *ptr;