Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx>
# HG changeset patch
# User andre.przywara@xxxxxxx
# Date 1186568085 -7200
# Node ID 1f3def9d51b4aacdb87862166998c29622649dcc
# Parent f5e9f20109d9dc3c82bfadcedd4af77a35e8c5fb
export SRAT table to the guest
diff -r f5e9f20109d9 -r 1f3def9d51b4 tools/firmware/hvmloader/acpi/acpi2_0.h
--- a/tools/firmware/hvmloader/acpi/acpi2_0.h Wed Aug 08 11:02:12 2007 +0200
+++ b/tools/firmware/hvmloader/acpi/acpi2_0.h Wed Aug 08 12:14:45 2007 +0200
@@ -369,6 +369,61 @@ struct acpi_20_madt_intsrcovr {
};
/*
+ * System Resource Affinity Table header definition (SRAT).
+ */
+struct acpi_20_srat {
+ struct acpi_header header;
+ uint32_t table_revision;
+ uint32_t reserved2[2];
+};
+
+#define ACPI_SRAT_TABLE_REVISION 1
+
+/*
+ * System Resource Affinity Table structure types.
+ */
+#define ACPI_PROCESSOR_AFFIN 0x00
+#define ACPI_MEMORY_AFFIN 0x01
+
+struct acpi_20_srat_processor {
+ uint8_t type;
+ uint8_t length;
+ uint8_t domain;
+ uint8_t apic_id;
+ uint32_t flags;
+ uint8_t sapic_id;
+ uint8_t domain_hi[3];
+ uint32_t reserved;
+};
+
+/*
+ * Local APIC Affinity Flags. All other bits are reserved and must be 0.
+ */
+#define ACPI_LOCAL_APIC_AFFIN_ENABLED (1 << 0)
+
+struct acpi_20_srat_memory {
+ uint8_t type;
+ uint8_t length;
+ uint8_t domain;
+ uint8_t domain_hi[3]; /* this is ACPI 3.0, reserved in 2.0 */
+ uint16_t reserved;
+ uint32_t base_address_lo;
+ uint32_t base_address_hi;
+ uint32_t length_lo;
+ uint32_t length_hi;
+ uint32_t reserved2;
+ uint32_t flags;
+ uint32_t reserved3[2];
+};
+
+/*
+ * Memory Affinity Flags. All other bits are reserved and must be 0.
+ */
+#define ACPI_MEM_AFFIN_ENABLED (1 << 0)
+#define ACPI_MEM_AFFIN_HOTPLUGGABLE (1 << 1)
+#define ACPI_MEM_AFFIN_NONVOLATILE (1 << 2) /* this is ACPI 3.0 */
+
+/*
* Table Signatures.
*/
#define ACPI_2_0_RSDP_SIGNATURE ASCII64('R','S','D',' ','P','T','R',' ')
@@ -379,6 +434,7 @@ struct acpi_20_madt_intsrcovr {
#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.
@@ -391,6 +447,7 @@ struct acpi_20_madt_intsrcovr {
#define ACPI_2_0_TCPA_REVISION 0x02
#define ACPI_2_0_HPET_REVISION 0x01
#define ACPI_1_0_FADT_REVISION 0x01
+#define ACPI_2_0_SRAT_REVISION 0x01
#pragma pack ()
diff -r f5e9f20109d9 -r 1f3def9d51b4 tools/firmware/hvmloader/acpi/build.c
--- a/tools/firmware/hvmloader/acpi/build.c Wed Aug 08 11:02:12 2007 +0200
+++ b/tools/firmware/hvmloader/acpi/build.c Wed Aug 08 12:14:45 2007 +0200
@@ -20,6 +20,9 @@
#include "ssdt_tpm.h"
#include "../config.h"
#include "../util.h"
+#include "../e820.h"
+
+#define ONEMB 0x100000
#define align16(sz) (((sz) + 15) & ~15)
#define fixed_strcpy(d, s) strncpy((d), (s), sizeof(d))
@@ -45,6 +48,135 @@ static void set_checksum(
p = table;
p[checksum_offset] = -sum;
+}
+
+static int vcpu_to_numa_node (int vcpu_id, int nr_vcpus)
+{
+
+ return ( vcpu_id * get_numanodes() ) / nr_vcpus;
+}
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
+static uint64_t guessmemsize (void)
+{
+ uint64_t ret = 0;
+ struct e820entry *map = HVM_E820;
+ int i;
+
+ for ( i = 0; i < *HVM_E820_NR ; i++)
+ {
+ if (map[i].addr == ONEMB )
+ ret+=map[i].size + PAGE_SIZE * 3 + ONEMB;
+ if (map[i].addr == (1ULL << 32))
+ ret+=map[i].size;
+ }
+ return ret;
+}
+
+int construct_srat(struct acpi_20_srat *srat)
+{
+ struct acpi_20_srat_processor *processor;
+ struct acpi_20_srat_memory *memory;
+ struct e820entry *map = HVM_E820;
+ int i, offset = 0;
+ uint64_t hvm_node_mem;
+
+ memset(srat, 0, sizeof(*srat));
+ srat->header.signature = ACPI_2_0_SRAT_SIGNATURE;
+ srat->header.revision = ACPI_2_0_SRAT_REVISION;
+ fixed_strcpy(srat->header.oem_id, ACPI_OEM_ID);
+ fixed_strcpy(srat->header.oem_table_id, ACPI_OEM_TABLE_ID);
+ srat->header.oem_revision = ACPI_OEM_REVISION;
+ srat->header.creator_id = ACPI_CREATOR_ID;
+ srat->header.creator_revision = ACPI_CREATOR_REVISION;
+ srat->table_revision = ACPI_SRAT_TABLE_REVISION;
+ offset += sizeof(*srat);
+
+ processor = (struct acpi_20_srat_processor *)(srat + 1);
+ for ( i = 0; i < get_vcpu_nr(); i++ )
+ {
+ memset(processor, 0, sizeof(*processor));
+ processor->type = ACPI_PROCESSOR_AFFIN;
+ processor->length = sizeof(*processor);
+ processor->domain = vcpu_to_numa_node (i, get_vcpu_nr());
+ processor->apic_id = LAPIC_ID(i);
+ processor->flags = ACPI_LOCAL_APIC_AFFIN_ENABLED;
+ processor->sapic_id= 0;
+ offset += sizeof(*processor);
+ processor++;
+ }
+
+ /*
+ * Equally distribute the memory on all NUMA nodes. Round up the size
+ * of available memory to whole megabytes, as (at least) Linux cannot cope
+ * with uneven NUMA node boundaries. The remaining part of memory will be
+ * assigned to the last NUMA node. The mapping of the first MB is copied
+ * from the E820 map and assigned to node 0
+ */
+ hvm_node_mem = guessmemsize()+ONEMB-1;
+ hvm_node_mem = hvm_node_mem >> 20;
+ /* 64bit/32bit will not work because of missing libgcc */
+ hvm_node_mem = (uint32_t)hvm_node_mem / get_numanodes();
+ hvm_node_mem = hvm_node_mem << 20;
+
+ memory = (struct acpi_20_srat_memory *)(processor);
+ for ( i = 0; i < *HVM_E820_NR; i++ )
+ {
+ if ( map[i].type != E820_RAM ) continue;
+ if ( map[i].addr >= ONEMB ) break;
+
+ memset(memory, 0, sizeof(*memory));
+ memory->type = ACPI_MEMORY_AFFIN;
+ memory->length = sizeof(*memory);
+ memory->domain = 0;
+ memory->base_address_lo = map[i].addr & 0xFFFFFFFFL;
+ memory->base_address_hi = map[i].addr >> 32;
+ memory->length_lo = map[i].size & 0xFFFFFFFFL;
+ memory->length_hi = map[i].size >> 32;
+ memory->flags = ACPI_MEM_AFFIN_ENABLED;
+
+ offset += sizeof(*memory);
+ memory++;
+ }
+
+ for ( i = 0; i < get_numanodes(); i++ )
+ {
+ memset(memory, 0, sizeof(*memory));
+ memory->type = ACPI_MEMORY_AFFIN;
+ memory->length = sizeof(*memory);
+ memory->domain = i;
+ if ( i == 0 )
+ {
+ memory->base_address_lo = ONEMB;
+ memory->base_address_hi = 0;
+ memory->length_lo = ( hvm_node_mem - ONEMB ) & 0xFFFFFFFFL;
+ memory->length_hi = ( hvm_node_mem - ONEMB ) >> 32;
+ } else
+ if ( i == get_numanodes()-1 )
+ {
+ memory->base_address_lo = (i * hvm_node_mem) & 0xFFFFFFFFL;
+ memory->base_address_hi = (i * hvm_node_mem) >> 32;
+ memory->length_lo = (guessmemsize()-hvm_node_mem*i) &
0xFFFFFFFFL;
+ memory->length_hi = (guessmemsize()-hvm_node_mem*i) >> 32;
+ } else
+ {
+ memory->base_address_lo = (i * hvm_node_mem) & 0xFFFFFFFFL;
+ memory->base_address_hi = (i * hvm_node_mem) >> 32;
+ memory->length_lo = hvm_node_mem & 0xFFFFFFFFL;
+ memory->length_hi = hvm_node_mem >> 32;
+ }
+ memory->flags = ACPI_MEM_AFFIN_ENABLED;
+ offset += sizeof(*memory);
+ memory++;
+ }
+
+ srat->header.length = offset;
+ set_checksum(srat, offsetof(struct acpi_header, checksum), offset);
+
+ return align16(offset);
}
int construct_madt(struct acpi_20_madt *madt)
@@ -196,7 +328,7 @@ int construct_processor_objects(uint8_t
}
/* NameString */
- strncpy(p, pr_scope, strlen(pr_scope));
+ strncpy( (char*) p, pr_scope, strlen(pr_scope));
p += strlen(pr_scope);
/*
@@ -223,6 +355,7 @@ int construct_secondary_tables(uint8_t *
int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs)
{
int offset = 0, nr_tables = 0;
+ struct acpi_20_srat *srat;
struct acpi_20_madt *madt;
struct acpi_20_hpet *hpet;
struct acpi_20_tcpa *tcpa;
@@ -235,6 +368,14 @@ int construct_secondary_tables(uint8_t *
madt = (struct acpi_20_madt *)&buf[offset];
offset += construct_madt(madt);
table_ptrs[nr_tables++] = (unsigned long)madt;
+ }
+
+ /* SRAT. */
+ if ( get_numanodes() > 0 )
+ {
+ srat = (struct acpi_20_srat *)&buf[offset];
+ offset += construct_srat(srat);
+ table_ptrs[nr_tables++] = (unsigned long)srat;
}
/* HPET. */
diff -r f5e9f20109d9 -r 1f3def9d51b4 tools/firmware/hvmloader/util.c
--- a/tools/firmware/hvmloader/util.c Wed Aug 08 11:02:12 2007 +0200
+++ b/tools/firmware/hvmloader/util.c Wed Aug 08 12:14:45 2007 +0200
@@ -574,6 +574,12 @@ int get_vcpu_nr(void)
return (t ? t->nr_vcpus : 1);
}
+int get_numanodes(void)
+{
+ struct hvm_info_table *t = get_hvm_info_table();
+ return (t ? t->numanodes : 1);
+}
+
int get_acpi_enabled(void)
{
struct hvm_info_table *t = get_hvm_info_table();
diff -r f5e9f20109d9 -r 1f3def9d51b4 tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h Wed Aug 08 11:02:12 2007 +0200
+++ b/tools/firmware/hvmloader/util.h Wed Aug 08 12:14:45 2007 +0200
@@ -54,6 +54,7 @@ void cpuid(uint32_t idx, uint32_t *eax,
/* HVM-builder info. */
int get_vcpu_nr(void);
+int get_numanodes(void);
int get_acpi_enabled(void);
int get_apic_mode(void);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|