At 07/11/2012 06:31 PM, Vasilis Liaskovitis Wrote: > The memory device generation is guided by qemu paravirt info. Seabios > first uses the info to setup SRAT entries for the hotplug-able memory slots. > Afterwards, build_memssdt uses the created SRAT entries to generate > appropriate memory device objects. One memory device (and corresponding SRAT > entry) is generated for each hotplug-able qemu memslot. Currently no SSDT > memory device is created for initial system memory. > > We only support up to 255 DIMMs for now (PackageOp used for the MEON array can > only describe an array of at most 255 elements. VarPackageOp would be needed to > support more than 255 devices) > > v1->v2: > Seabios reads mems_sts from qemu to build e820_map > SSDT size and some offsets are calculated with extraction macros. > > Signed-off-by: Vasilis Liaskovitis <vasilis.liaskovitis@xxxxxxxxxxxxxxxx> > --- > src/acpi.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- > 1 files changed, 152 insertions(+), 6 deletions(-) > > diff --git a/src/acpi.c b/src/acpi.c > index 55e4607..c83e8c7 100644 > --- a/src/acpi.c > +++ b/src/acpi.c > @@ -510,6 +510,127 @@ build_ssdt(void) > return ssdt; > } > > +#include "ssdt-mem.hex" > + > +/* 0x5B 0x82 DeviceOp PkgLength NameString DimmID */ > +#define MEM_BASE 0xaf80 > +#define SD_MEM (ssdm_mem_aml + *ssdt_mem_start) > +#define SD_MEMSIZEOF (*ssdt_mem_end - *ssdt_mem_start) > +#define SD_OFFSET_MEMHEX (*ssdt_mem_name - *ssdt_mem_start + 2) > +#define SD_OFFSET_MEMID (*ssdt_mem_id - *ssdt_mem_start) > +#define SD_OFFSET_PXMID 31 > +#define SD_OFFSET_MEMSTART 55 > +#define SD_OFFSET_MEMEND 63 > +#define SD_OFFSET_MEMSIZE 79 > + > +u64 nb_hp_memslots = 0; > +struct srat_memory_affinity *mem; > + > +static void build_memdev(u8 *ssdt_ptr, int i, u64 mem_base, u64 mem_len, u8 node) > +{ > + memcpy(ssdt_ptr, SD_MEM, SD_MEMSIZEOF); > + ssdt_ptr[SD_OFFSET_MEMHEX] = getHex(i >> 4); > + ssdt_ptr[SD_OFFSET_MEMHEX+1] = getHex(i); > + ssdt_ptr[SD_OFFSET_MEMID] = i; > + ssdt_ptr[SD_OFFSET_PXMID] = node; > + *(u64*)(ssdt_ptr + SD_OFFSET_MEMSTART) = mem_base; > + *(u64*)(ssdt_ptr + SD_OFFSET_MEMEND) = mem_base + mem_len; > + *(u64*)(ssdt_ptr + SD_OFFSET_MEMSIZE) = mem_len; > +} > + > +static void* > +build_memssdt(void) > +{ > + u64 mem_base; > + u64 mem_len; > + u8 node; > + int i; > + struct srat_memory_affinity *entry = mem; > + u64 nb_memdevs = nb_hp_memslots; > + u8 memslot_status, enabled; > + > + int length = ((1+3+4) > + + (nb_memdevs * SD_MEMSIZEOF) > + + (1+2+5+(12*nb_memdevs)) > + + (6+2+1+(1*nb_memdevs))); > + u8 *ssdt = malloc_high(sizeof(struct acpi_table_header) + length); > + if (! ssdt) { > + warn_noalloc(); > + return NULL; > + } > + u8 *ssdt_ptr = ssdt + sizeof(struct acpi_table_header); > + > + // build Scope(_SB_) header > + *(ssdt_ptr++) = 0x10; // ScopeOp > + ssdt_ptr = encodeLen(ssdt_ptr, length-1, 3); > + *(ssdt_ptr++) = '_'; > + *(ssdt_ptr++) = 'S'; > + *(ssdt_ptr++) = 'B'; > + *(ssdt_ptr++) = '_'; > + > + for (i = 0; i < nb_memdevs; i++) { > + mem_base = (((u64)(entry->base_addr_high) << 32 )| entry->base_addr_low); > + mem_len = (((u64)(entry->length_high) << 32 )| entry->length_low); > + node = entry->proximity[0]; > + build_memdev(ssdt_ptr, i, mem_base, mem_len, node); > + ssdt_ptr += SD_MEMSIZEOF; > + entry++; > + } > + > + // build "Method(MTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CM00, Arg1)} ...}" > + *(ssdt_ptr++) = 0x14; // MethodOp > + ssdt_ptr = encodeLen(ssdt_ptr, 2+5+(12*nb_memdevs), 2); > + *(ssdt_ptr++) = 'M'; > + *(ssdt_ptr++) = 'T'; > + *(ssdt_ptr++) = 'F'; > + *(ssdt_ptr++) = 'Y'; > + *(ssdt_ptr++) = 0x02; > + for (i=0; i<nb_memdevs; i++) { > + *(ssdt_ptr++) = 0xA0; // IfOp > + ssdt_ptr = encodeLen(ssdt_ptr, 11, 1); > + *(ssdt_ptr++) = 0x93; // LEqualOp > + *(ssdt_ptr++) = 0x68; // Arg0Op > + *(ssdt_ptr++) = 0x0A; // BytePrefix > + *(ssdt_ptr++) = i; > + *(ssdt_ptr++) = 0x86; // NotifyOp > + *(ssdt_ptr++) = 'M'; > + *(ssdt_ptr++) = 'P'; > + *(ssdt_ptr++) = getHex(i >> 4); > + *(ssdt_ptr++) = getHex(i); > + *(ssdt_ptr++) = 0x69; // Arg1Op > + } > + > + // build "Name(MEON, Package() { One, One, ..., Zero, Zero, ... })" > + *(ssdt_ptr++) = 0x08; // NameOp > + *(ssdt_ptr++) = 'M'; > + *(ssdt_ptr++) = 'E'; > + *(ssdt_ptr++) = 'O'; > + *(ssdt_ptr++) = 'N'; > + *(ssdt_ptr++) = 0x12; // PackageOp > + ssdt_ptr = encodeLen(ssdt_ptr, 2+1+(1*nb_memdevs), 2); > + *(ssdt_ptr++) = nb_memdevs; > + > + entry = mem; > + memslot_status = 0; > + > + for (i = 0; i < nb_memdevs; i++) { > + enabled = 0; > + if (i % 8 == 0) > + memslot_status = inb(MEM_BASE + i/8); > + enabled = memslot_status & 1; > + mem_base = (((u64)(entry->base_addr_high) << 32 )| entry->base_addr_low); > + mem_len = (((u64)(entry->length_high) << 32 )| entry->length_low); > + *(ssdt_ptr++) = enabled ? 0x01 : 0x00; > + if (enabled) > + add_e820(mem_base, mem_len, E820_RAM); add_e820() is declared in memmap.h. You should include this header file, otherwise, seabios cannot be built. Thanks Wen Congyang > + memslot_status = memslot_status >> 1; > + entry++; > + } > + build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1); > + > + return ssdt; > +} > + > #include "ssdt-pcihp.hex" > > #define PCI_RMV_BASE 0xae0c > @@ -618,9 +739,6 @@ build_srat(void) > { > int nb_numa_nodes = qemu_cfg_get_numa_nodes(); > > - if (nb_numa_nodes == 0) > - return NULL; > - > u64 *numadata = malloc_tmphigh(sizeof(u64) * (MaxCountCPUs + nb_numa_nodes)); > if (!numadata) { > warn_noalloc(); > @@ -629,10 +747,11 @@ build_srat(void) > > qemu_cfg_get_numa_data(numadata, MaxCountCPUs + nb_numa_nodes); > > + qemu_cfg_get_numa_data(&nb_hp_memslots, 1); > struct system_resource_affinity_table *srat; > int srat_size = sizeof(*srat) + > sizeof(struct srat_processor_affinity) * MaxCountCPUs + > - sizeof(struct srat_memory_affinity) * (nb_numa_nodes + 2); > + sizeof(struct srat_memory_affinity) * (nb_numa_nodes + nb_hp_memslots + 2); > > srat = malloc_high(srat_size); > if (!srat) { > @@ -667,7 +786,7 @@ build_srat(void) > * from 640k-1M and possibly another one from 3.5G-4G. > */ > struct srat_memory_affinity *numamem = (void*)core; > - int slots = 0; > + int slots = 0, node; > u64 mem_len, mem_base, next_base = 0; > > acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1); > @@ -694,10 +813,36 @@ build_srat(void) > next_base += (1ULL << 32) - RamSize; > } > acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1); > + > numamem++; > slots++; > + > + } > + mem = (void*)numamem; > + > + if (nb_hp_memslots) { > + u64 *hpmemdata = malloc_tmphigh(sizeof(u64) * (3 * nb_hp_memslots)); > + if (!hpmemdata) { > + warn_noalloc(); > + free(hpmemdata); > + free(numadata); > + return NULL; > + } > + > + qemu_cfg_get_numa_data(hpmemdata, 3 * nb_hp_memslots); > + > + for (i = 1; i < nb_hp_memslots + 1; ++i) { > + mem_base = *hpmemdata++; > + mem_len = *hpmemdata++; > + node = *hpmemdata++; > + acpi_build_srat_memory(numamem, mem_base, mem_len, node, 1); > + numamem++; > + slots++; > + } > + free(hpmemdata); > } > - for (; slots < nb_numa_nodes + 2; slots++) { > + > + for (; slots < nb_numa_nodes + nb_hp_memslots + 2; slots++) { > acpi_build_srat_memory(numamem, 0, 0, 0, 0); > numamem++; > } > @@ -748,6 +893,7 @@ acpi_bios_init(void) > ACPI_INIT_TABLE(build_madt()); > ACPI_INIT_TABLE(build_hpet()); > ACPI_INIT_TABLE(build_srat()); > + ACPI_INIT_TABLE(build_memssdt()); > ACPI_INIT_TABLE(build_pcihp()); > > u16 i, external_tables = qemu_cfg_acpi_additional_tables(); -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html