qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [RFC PATCH v2 04/21][SeaBIOS] acpi: generate hotplug me


From: Wen Congyang
Subject: Re: [Qemu-devel] [RFC PATCH v2 04/21][SeaBIOS] acpi: generate hotplug memory devices
Date: Wed, 11 Jul 2012 18:48:38 +0800
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100413 Fedora/3.0.4-2.fc13 Thunderbird/3.0.4

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 <address@hidden>
> ---
>  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();




reply via email to

[Prev in Thread] Current Thread [Next in Thread]