All of lore.kernel.org
 help / color / mirror / Atom feed
From: Igor Mammedov <imammedo@redhat.com>
To: Hu Tao <hutao@cn.fujitsu.com>
Cc: Vasilis Liaskovitis <vasilis.liaskovitis@profitbricks.com>,
	seabios@seabios.org, qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH v5 5/7] acpi: generate hotplug memory devices
Date: Fri, 12 Jul 2013 12:07:30 +0200	[thread overview]
Message-ID: <20130712120730.6867ea18@nial.usersys.redhat.com> (raw)
In-Reply-To: <76d6482dd8dffa881f698fc247a57bf2636e064d.1372237449.git.hutao@cn.fujitsu.com>

On Wed, 26 Jun 2013 17:15:03 +0800
Hu Tao <hutao@cn.fujitsu.com> wrote:

> The memory device generation is guided by qemu paravirt info. Seabios
> uses the info to setup SRAT entries for the hotplug-able memory slots,
> and 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)
> 
> Signed-off-by: Vasilis Liaskovitis <vasilis.liaskovitis@profitbricks.com>
> Signed-off-by: Hu Tao <hutao@cn.fujitsu.com>
> ---
>  src/acpi.c     | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
>  src/paravirt.c |   8 +++
>  2 files changed, 152 insertions(+), 7 deletions(-)
> 
> diff --git a/src/acpi.c b/src/acpi.c
> index ce988e0..e9a0326 100644
> --- a/src/acpi.c
> +++ b/src/acpi.c
> @@ -15,6 +15,8 @@
>  #include "config.h" // CONFIG_*
>  #include "paravirt.h" // RamSize
>  #include "dev-q35.h"
> +#include "memmap.h"
> +#include "paravirt.h"
>  
>  #include "acpi-dsdt.hex"
>  
> @@ -250,11 +252,23 @@ encodeLen(u8 *ssdt_ptr, int length, int bytes)
>  #define PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start)
>  #define PCI_SLOTS 32
>  
> +/* 0x5B 0x82 DeviceOp PkgLength NameString DimmID */
> +#define MEM_BASE 0xaf80
> +#define MEM_AML (ssdm_mem_aml + *ssdt_mem_start)
> +#define MEM_SIZEOF (*ssdt_mem_end - *ssdt_mem_start)
> +#define MEM_OFFSET_HEX (*ssdt_mem_name - *ssdt_mem_start + 2)
> +#define MEM_OFFSET_ID (*ssdt_mem_id - *ssdt_mem_start)
> +#define MEM_OFFSET_PXM 31
> +#define MEM_OFFSET_START 55
> +#define MEM_OFFSET_END   63
> +#define MEM_OFFSET_SIZE  79
> +
>  #define SSDT_SIGNATURE 0x54445353 // SSDT
>  #define SSDT_HEADER_LENGTH 36
>  
>  #include "ssdt-misc.hex"
>  #include "ssdt-pcihp.hex"
> +#include "ssdt-mem.hex"
>  
>  #define PCI_RMV_BASE 0xae0c
>  
> @@ -306,9 +320,100 @@ static void patch_pcihp(int slot, u8 *ssdt_ptr, u32 eject)
>      }
>  }
>  
> +static void build_memdev(u8 *ssdt_ptr, int i, u64 mem_base, u64 mem_len, u8 node)
> +{
> +    memcpy(ssdt_ptr, MEM_AML, MEM_SIZEOF);
> +    ssdt_ptr[MEM_OFFSET_HEX] = getHex(i >> 4);
> +    ssdt_ptr[MEM_OFFSET_HEX+1] = getHex(i);
> +    ssdt_ptr[MEM_OFFSET_ID] = i;
> +    ssdt_ptr[MEM_OFFSET_PXM] = node;
> +    *(u64*)(ssdt_ptr + MEM_OFFSET_START) = cpu_to_le64(mem_base);
> +    *(u64*)(ssdt_ptr + MEM_OFFSET_END) = cpu_to_le64(mem_base + mem_len);
> +    *(u64*)(ssdt_ptr + MEM_OFFSET_SIZE) = cpu_to_le64(mem_len);
> +}
> +
> +static u8 *build_memssdt(u8 *ssdt_ptr, int memssdt_len,
> +                         u64 *numadimmsmap, int nb_memdevs)
> +{
> +    u64 mem_base, mem_len;
> +    u64 *dimm = numadimmsmap;
> +    int node;
> +    int i;
> +
> +    // build Scope(_SB_) header
> +    *(ssdt_ptr++) = 0x10; // ScopeOp
> +    ssdt_ptr = encodeLen(ssdt_ptr, memssdt_len, 3);
> +    *(ssdt_ptr++) = '_';
> +    *(ssdt_ptr++) = 'S';
> +    *(ssdt_ptr++) = 'B';
> +    *(ssdt_ptr++) = '_';
Windows doesn't like much 2 \_SB in one SSDT table, and BSODs.

Just drop it and add stuff to already existing scope or alternatively
create a second SSDT table.

> +    for (i = 0; i < nb_memdevs; i++) {
> +        mem_base = *dimm++;
> +        mem_len = *dimm++;
> +        node = *dimm++;
> +        build_memdev(ssdt_ptr, i, mem_base, mem_len, node);
> +        ssdt_ptr += MEM_SIZEOF;
> +    }
> +
> +    // 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;
> +
> +    dimm = numadimmsmap;
> +    u8 memslot_status = 0, enabled;
> +
> +    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 = *dimm++;
> +        mem_len = *dimm++;
> +        dimm++;  // node
> +        *(ssdt_ptr++) = enabled ? 0x01 : 0x00;
> +        if (enabled)
> +            add_e820(mem_base, mem_len, E820_RAM);
> +        memslot_status = memslot_status >> 1;
> +    }
> +
> +    return ssdt_ptr;
> +}
> +
>  static void*
>  build_ssdt(void)
>  {
> +    int nb_memdevs;
> +    u64 *numadimmsmap;
>      int acpi_cpus = MaxCountCPUs > 0xff ? 0xff : MaxCountCPUs;
>      int length = (sizeof(ssdp_misc_aml)                     // _S3_ / _S4_ / _S5_
>                    + (1+3+4)                                 // Scope(_SB_)
> @@ -318,9 +423,20 @@ build_ssdt(void)
>                    + (1+3+4)                                 // Scope(PCI0)
>                    + ((PCI_SLOTS - 1) * PCIHP_SIZEOF)        // slots
>                    + (1+2+5+(12*(PCI_SLOTS - 1))));          // PCNT
> -    u8 *ssdt = malloc_high(length);
> +
> +    numadimmsmap = romfile_loadfile("etc/numa-dimm-map", &nb_memdevs);
> +    nb_memdevs /= 3 * sizeof(u64);
> +
> +    // for build_memssdt
> +    int memssdt_length = (1+3+4)
> +                         + (nb_memdevs * MEM_SIZEOF)
> +                         + (1+2+5+(12*nb_memdevs))
> +                         + (6+2+1+(1*nb_memdevs));
> +
> +    u8 *ssdt = malloc_high(length + memssdt_length);
>      if (! ssdt) {
>          warn_noalloc();
> +        free(numadimmsmap);
>          return NULL;
>      }
>      u8 *ssdt_ptr = ssdt;
> @@ -411,10 +527,13 @@ build_ssdt(void)
>  
>      ssdt_ptr = build_notify(ssdt_ptr, "PCNT", 1, PCI_SLOTS, "S00_", 1);
>  
> +    ssdt_ptr = build_memssdt(ssdt_ptr, memssdt_length, numadimmsmap, nb_memdevs);
                        ^^^^^^^ name is misleading, since the result of call is not SSDT

> +
>      build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
>  
>      //hexdump(ssdt, ssdt_ptr - ssdt);
>  
> +    free(numadimmsmap);
>      return ssdt;
>  }
>  
> @@ -458,7 +577,7 @@ acpi_build_srat_memory(struct srat_memory_affinity *numamem,
>      numamem->length = sizeof(*numamem);
>      memset(numamem->proximity, 0, 4);
>      numamem->proximity[0] = node;
> -    numamem->flags = cpu_to_le32(!!enabled);
> +    numamem->flags = cpu_to_le32(!!enabled) | cpu_to_le32(0x2);
>      numamem->base_addr = cpu_to_le64(base);
>      numamem->range_length = cpu_to_le64(len);
>  }
> @@ -466,18 +585,22 @@ acpi_build_srat_memory(struct srat_memory_affinity *numamem,
>  static void *
>  build_srat(void)
>  {
> -    int numadatasize, numacpusize;
> +    int numadatasize, numacpusize, nb_numa_dimms;
> +    u64 *numadimmsmap;
>      u64 *numadata = romfile_loadfile("etc/numa-nodes", &numadatasize);
>      u64 *numacpumap = romfile_loadfile("etc/numa-cpu-map", &numacpusize);
> -    if (!numadata || !numacpumap)
> -        goto fail;
> +
>      int max_cpu = numacpusize / sizeof(u64);
>      int nb_numa_nodes = numadatasize / sizeof(u64);
>  
> +    numadimmsmap = romfile_loadfile("etc/numa-dimm-map", &nb_numa_dimms);
> +
> +    nb_numa_dimms /=  3 * sizeof(u64);
> +
>      struct system_resource_affinity_table *srat;
>      int srat_size = sizeof(*srat) +
>          sizeof(struct srat_processor_affinity) * max_cpu +
> -        sizeof(struct srat_memory_affinity) * (nb_numa_nodes + 2);
> +        sizeof(struct srat_memory_affinity) * (nb_numa_nodes + nb_numa_dimms + 2);
>  
>      srat = malloc_high(srat_size);
>      if (!srat) {
> @@ -512,6 +635,7 @@ build_srat(void)
>       */
>      struct srat_memory_affinity *numamem = (void*)core;
>      int slots = 0;
> +    int node;
>      u64 mem_len, mem_base, next_base = 0;
>  
>      acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1);
> @@ -541,7 +665,18 @@ build_srat(void)
>          numamem++;
>          slots++;
>      }
> -    for (; slots < nb_numa_nodes + 2; slots++) {
> +    if (nb_numa_dimms) {
> +        for (i = 1; i < nb_numa_dimms + 1; ++i) {
> +            mem_base = *numadimmsmap++;
> +            mem_len = *numadimmsmap++;
> +            node = *numadimmsmap++;
> +            acpi_build_srat_memory(numamem, mem_base, mem_len, node, 1);
> +            numamem++;
> +            slots++;
> +        }
> +    }
> +
> +    for (; slots < nb_numa_nodes + nb_numa_dimms + 2; slots++) {
>          acpi_build_srat_memory(numamem, 0, 0, 0, 0);
>          numamem++;
>      }
> @@ -550,10 +685,12 @@ build_srat(void)
>  
>      free(numadata);
>      free(numacpumap);
> +    free(numadimmsmap);
>      return srat;
>  fail:
>      free(numadata);
>      free(numacpumap);
> +    free(numadimmsmap);
>      return NULL;
>  }
>  
> diff --git a/src/paravirt.c b/src/paravirt.c
> index d1a5d3e..5925c63 100644
> --- a/src/paravirt.c
> +++ b/src/paravirt.c
> @@ -240,6 +240,14 @@ qemu_cfg_legacy(void)
>                       , sizeof(numacount) + max_cpu*sizeof(u64)
>                       , numacount*sizeof(u64));
>  
> +    u64 dimm_count;
> +    qemu_cfg_select(QEMU_CFG_NUMA);
> +    qemu_cfg_skip((1 + max_cpu + numacount) * sizeof(u64));
> +    qemu_cfg_read(&dimm_count, sizeof(dimm_count));
> +    qemu_romfile_add("etc/numa-dimm-map", QEMU_CFG_NUMA
> +                     , (2 + max_cpu + numacount) * sizeof(u64),
> +                     dimm_count * 3 * sizeof(u64));
> +
>      // e820 data
>      u32 count32;
>      qemu_cfg_read_entry(&count32, QEMU_CFG_E820_TABLE, sizeof(count32));

  reply	other threads:[~2013-07-12 10:09 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-06-26  9:13 [Qemu-devel] [PATCH v5 00/14] ACPI memory hotplug Hu Tao
2013-06-26  9:13 ` [Qemu-devel] [PATCH v5 01/14] qapi: make visit_type_size fallback to v->type_int() Hu Tao
2013-06-26  9:13 ` [Qemu-devel] [PATCH v5 02/14] Add SIZE type to qdev properties Hu Tao
2013-07-08  9:37   ` Andreas Färber
2013-07-12  1:27     ` Hu Tao
2013-06-26  9:13 ` [Qemu-devel] [PATCH v5 03/14] qemu-option: export parse_option_number Hu Tao
2013-06-26  9:13 ` [Qemu-devel] [PATCH v5 04/14] Implement dimm device abstraction Hu Tao
2013-06-26  9:13 ` [Qemu-devel] [PATCH v5 05/14] vl: handle "-device dimm" Hu Tao
2013-06-26  9:46   ` Paolo Bonzini
2013-06-27  5:08     ` Wanlong Gao
2013-06-27  6:55       ` Paolo Bonzini
2013-07-09 16:53         ` Igor Mammedov
2013-07-12  2:39           ` Hu Tao
2013-07-14 16:58             ` Paolo Bonzini
2013-07-16  1:26               ` Hu Tao
2013-07-15 17:05         ` Vasilis Liaskovitis
2013-07-15 17:10           ` Paolo Bonzini
2013-07-15 17:20             ` Vasilis Liaskovitis
2013-07-16  1:27             ` Hu Tao
2013-07-16  6:19               ` Paolo Bonzini
2013-07-16  7:27                 ` Hu Tao
2013-07-16 10:22                   ` Igor Mammedov
2013-07-16 10:19                 ` Igor Mammedov
2013-07-16 10:31                   ` Paolo Bonzini
2013-07-16 12:00                     ` Igor Mammedov
2013-07-16 12:17                       ` Paolo Bonzini
2013-06-26  9:13 ` [Qemu-devel] [PATCH v5 06/14] acpi_piix4 : Implement memory device hotplug registers Hu Tao
2013-06-26  9:13 ` [Qemu-devel] [PATCH v5 07/14] acpi_ich9 " Hu Tao
2013-06-26  9:13 ` [Qemu-devel] [PATCH v5 08/14] memory: record below_4g_mem_size, above_4g_mem_size Hu Tao
2013-06-26  9:13 ` [Qemu-devel] [PATCH v5 09/14] memory controller: initialize dram controller Hu Tao
2013-06-26  9:13 ` [Qemu-devel] [PATCH v5 10/14] pc: Add dimm paravirt SRAT info Hu Tao
2013-07-10 10:10   ` Michael S. Tsirkin
2013-07-11  5:13     ` Igor Mammedov
2013-07-11  8:49       ` Michael S. Tsirkin
2013-07-12  1:33         ` Hu Tao
2013-07-14  5:47           ` Michael S. Tsirkin
2013-06-26  9:13 ` [Qemu-devel] [PATCH v5 11/14] Introduce paravirt interface QEMU_CFG_PCI_WINDOW Hu Tao
2013-06-26  9:13 ` [Qemu-devel] [PATCH v5 12/14] Implement "info memory" and "query-memory" Hu Tao
2013-06-28 20:27   ` Eric Blake
2013-06-26  9:13 ` [Qemu-devel] [PATCH v5 13/14] balloon: update with hotplugged memory Hu Tao
2013-06-26  9:13 ` [Qemu-devel] [PATCH v5 14/14] Implement dimm-info Hu Tao
2013-06-28 20:28   ` Eric Blake
2013-06-26  9:14 ` [Qemu-devel] [PATCH v5 0/7] support for ACPI memory hotplug Hu Tao
2013-06-26  9:14   ` [Qemu-devel] [PATCH v5 1/7] Add ACPI_EXTRACT_DEVICE* macros Hu Tao
2013-06-26  9:15   ` [Qemu-devel] [PATCH v5 2/7] Add SSDT memory device support Hu Tao
2013-06-26  9:15   ` [Qemu-devel] [PATCH v5 3/7] acpi-dsdt: Implement functions for memory hotplug Hu Tao
2013-06-26  9:15   ` [Qemu-devel] [PATCH v5 4/7] set psize to 0 when romfile_loadfile failed Hu Tao
2013-06-26  9:15   ` [Qemu-devel] [PATCH v5 5/7] acpi: generate hotplug memory devices Hu Tao
2013-07-12 10:07     ` Igor Mammedov [this message]
2013-06-26  9:15   ` [Qemu-devel] [PATCH v5 6/7] q35: Add memory hotplug handler Hu Tao
2013-06-26  9:15   ` [Qemu-devel] [PATCH v5 7/7] pci: Use paravirt interface for pcimem_start and pcimem64_start Hu Tao
2013-07-15 20:11     ` Vasilis Liaskovitis
2013-07-07  8:36   ` [Qemu-devel] [PATCH v5 0/7] support for ACPI memory hotplug Michael S. Tsirkin
2013-07-08  9:48 ` [Qemu-devel] [PATCH v5 00/14] " Andreas Färber
2013-07-12  1:30   ` Hu Tao
2013-07-14 16:56   ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130712120730.6867ea18@nial.usersys.redhat.com \
    --to=imammedo@redhat.com \
    --cc=hutao@cn.fujitsu.com \
    --cc=qemu-devel@nongnu.org \
    --cc=seabios@seabios.org \
    --cc=vasilis.liaskovitis@profitbricks.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.