[patch] vEFI SRAT support

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

 



Hi,

Here's a patch adding SRAT support to the vEFI image. It's fairly basic,
simply putting all vCPUs and memory onto node zero.

The benefit of creating the SRAT, even for smaller systems is that the
current Linux kernels rely on it to count possibly CPUs, and without it,
they will allocate per-CPU space for 32 CPUs. It should result in
slightly less kernel memory being consumed for small setups and it
allows for booting guests with > 32 vCPUs (and > 64 with older kernels).

I also changed the ACPI OEM ID to say XenKVM instead of just Xen, hope
thats ok. If you prefer, feel free to ignore this part. Last I added
a typecase to the memcpy() #define to avoid a compiler warning.

Cheers,
Jes


Implement basic ACPI SRAT support.

This implementation simply puts all CPUs and memory onto node 0.

For Linux guests it is preffered to have an SRAT, even for small
configurations as recent kernels rely on it to determine per-CPU
allocations. If no SRAT is found, the kernel will allocate space for
32 CPUs. This is also required in order to boot more than 32 vCPUs
with recent kernels, and more than 64 vCPUs with older kernels.

Signed-off-by: Jes Sorensen <jes@xxxxxxx>

diff -r eb97cb2936d6 edk2-sparse/EdkXenPkg/Dxe/XenAcpi/acpi2_0.h
--- a/edk2-sparse/EdkXenPkg/Dxe/XenAcpi/acpi2_0.h	Tue Mar  3 05:38:15 2009
+++ b/edk2-sparse/EdkXenPkg/Dxe/XenAcpi/acpi2_0.h	Wed Jun  3 09:23:12 2009
@@ -54,7 +54,7 @@
     uint32_t creator_revision;
 };
 
-#define ACPI_OEM_ID             "Xen"
+#define ACPI_OEM_ID             "XenKVM"
 #define ACPI_OEM_TABLE_ID       "HVM"
 #define ACPI_OEM_REVISION       0
 
@@ -351,6 +351,7 @@
 #define ACPI_2_0_XSDT_SIGNATURE ASCII32('X','S','D','T')
 #define ACPI_2_0_TCPA_SIGNATURE ASCII32('T','C','P','A')
 #define ACPI_2_0_HPET_SIGNATURE ASCII32('H','P','E','T')
+#define ACPI_2_0_SRAT_SIGNATURE ASCII32('S','R','A','T')
 
 /*
  * Table revision numbers.
@@ -362,6 +363,49 @@
 #define ACPI_2_0_XSDT_REVISION 0x01
 #define ACPI_2_0_TCPA_REVISION 0x02
 #define ACPI_2_0_HPET_REVISION 0x01
+#define ACPI_2_0_SRAT_REVISION 0x02
+
+/*
+ * Processor Local APIC/SAPIC Affinity Structure
+ */
+struct acpi_20_srat_cpu_affinity {
+    uint8_t  type;
+    uint8_t  length;
+    uint8_t  proximity_domain_lo;
+    uint8_t  apic_id;
+    uint32_t flags;
+    uint8_t  local_sapic_eid;
+    uint8_t  proximity_domain_hi[3];
+    uint32_t reserved;
+};
+
+#define ACPI_SRAT_CPU_ENABLED 1
+
+/*
+ * Memory Affinity Structure
+ */
+struct acpi_20_srat_memory_affinity {
+    uint8_t  type;
+    uint8_t  length;
+    uint32_t proximity_domain;
+    uint16_t reserved0;
+    uint64_t base_address;
+    uint64_t base_length;
+    uint32_t reserved1;
+    uint32_t flags;
+    uint64_t reserved2;
+};
+
+#define ACPI_SRAT_MEMORY_ENABLED 1
+
+/*
+ * System Resource Affinity Table (SRAT)
+ */
+struct acpi_20_srat {
+    struct acpi_header header;
+    uint32_t reserved0;     /* Must be 1 */
+    uint64_t reserved1;
+};
 
 #pragma pack ()
 
diff -r eb97cb2936d6 edk2-sparse/EdkXenPkg/Dxe/XenAcpi/build.c
--- a/edk2-sparse/EdkXenPkg/Dxe/XenAcpi/build.c	Tue Mar  3 05:38:15 2009
+++ b/edk2-sparse/EdkXenPkg/Dxe/XenAcpi/build.c	Wed Jun  3 09:23:12 2009
@@ -25,7 +26,7 @@
 #else
 #define memset(ptr,v,len) SetMem(ptr,len,v)
 #define memcpy(dst,src,len) CopyMem(dst,src,len)
-#define strncpy(dst,src,len) AsciiStrnCpy(dst,src,len)
+#define strncpy(dst,src,len) AsciiStrnCpy((char *)dst,src,len)
 #define offsetof(TYPE, MEMBER) ((UINTN) &((TYPE *)0)->MEMBER)
 #define LAPIC_BASE_ADDRESS 0xFEE00000
 #define IOSAPIC_BASE_ADDRESS   0xFEC00000
@@ -59,6 +60,96 @@
 
     p = table;
     p[checksum_offset] = -sum;
+}
+
+int construct_srat_cpu(uint8_t *buf, int cpu_nr, int node)
+{
+    struct acpi_20_srat_cpu_affinity *cpu;
+
+    cpu = (struct acpi_20_srat_cpu_affinity *)buf;
+
+    cpu->type = 0;
+    cpu->length = sizeof(struct acpi_20_srat_cpu_affinity);
+    cpu->proximity_domain_lo = node;
+    cpu->apic_id = cpu_nr;
+    cpu->flags = ACPI_SRAT_CPU_ENABLED;
+    cpu->local_sapic_eid = 0;
+    memset(cpu->proximity_domain_hi, 0, 3);
+    cpu->reserved = 0;
+    return sizeof(struct acpi_20_srat_cpu_affinity);
+}
+
+int construct_srat_memory(uint8_t *buf, unsigned long start,
+                          unsigned long end, int node, int enabled)
+{
+    struct acpi_20_srat_memory_affinity *mem;
+
+    mem = (struct acpi_20_srat_memory_affinity *)buf;
+
+    mem->type = 1;
+    mem->length = sizeof(struct acpi_20_srat_memory_affinity);
+    mem->proximity_domain = node;
+    mem->reserved0 = 0;
+    mem->base_address = start;
+    mem->base_length = end - start;
+    mem->reserved1 = 0;
+    if (enabled)
+        mem->flags = ACPI_SRAT_MEMORY_ENABLED;
+    else
+        mem->flags = 0;
+    mem->reserved2 = 0;
+    return sizeof(struct acpi_20_srat_memory_affinity);
+}
+
+int construct_srat(uint8_t *buf)
+{
+    struct acpi_20_srat *srat;
+    int size, offset, i;
+    unsigned long start, end;
+
+    srat = (struct acpi_20_srat *)buf;
+    offset = sizeof(struct acpi_20_srat);
+    memset(srat, 0, sizeof(struct acpi_20_srat));
+    srat->header.signature        = ACPI_2_0_SRAT_SIGNATURE;
+    srat->header.revision         = ACPI_2_0_SRAT_REVISION;
+    srat->header.creator_id       = ACPI_CREATOR_ID;
+    srat->header.creator_revision = ACPI_CREATOR_REVISION;
+    strncpy(srat->header.oem_id, ACPI_OEM_ID, 6);
+    strncpy(srat->header.oem_table_id, ACPI_OEM_TABLE_ID, 8);
+    srat->reserved0 = 1;
+    buf += offset;
+
+    /*
+     * Create SRAT CPU entries
+     */
+    for (i = 0; i < get_vcpu_nr(); i++) {
+        size = construct_srat_cpu(buf, i, 0);
+        offset += size;
+        buf += size;
+    }
+
+    /*
+     * Create SRAT memory block entries
+     *
+     * For now we just list all physical memory as being on the same
+     * node. Eventually we should implement multi-node support
+     */
+    start = 0x0;
+    end = 0x100000000;
+    size = construct_srat_memory(buf, start, end, 0, 1);
+    offset += size;
+    buf += size;
+
+    start = 0x100000000;
+    end = 0x40000000000;
+    size = construct_srat_memory(buf, start, end, 0, 1);
+    offset += size;
+    buf += size;
+
+    srat->header.length = offset;
+    set_checksum(srat, offsetof(struct acpi_header, checksum), offset);
+
+    return offset;
 }
 
 int construct_madt(struct acpi_20_madt *madt)
@@ -192,6 +283,7 @@
     int offset = 0, nr_tables = 0;
     struct acpi_20_madt *madt;
     struct acpi_20_hpet *hpet;
+    uint8_t *srat;
 #if 0
     struct acpi_20_tcpa *tcpa;
     static const uint16_t tis_signature[] = {0x0001, 0x0001, 0x0001};
@@ -210,6 +302,11 @@
     hpet = (struct acpi_20_hpet *)&buf[offset];
     offset += construct_hpet(hpet);
     table_ptrs[nr_tables++] = (unsigned long)hpet;
+
+    /* SRAT */
+    srat = &buf[offset];
+    offset += construct_srat(srat);
+    table_ptrs[nr_tables++] = (unsigned long)srat;
 
 #if 0
     /* TPM TCPA and SSDT. */
diff -r eb97cb2936d6 edk2-sparse/env.sh

[Index of Archives]     [Linux KVM Devel]     [Linux Virtualization]     [Big List of Linux Books]     [Linux SCSI]     [Yosemite Forum]

  Powered by Linux