* [PATCH 4/4] [HVM] inject created SRAT table into the guest
@ 2007-08-13 10:03 Andre Przywara
0 siblings, 0 replies; only message in thread
From: Andre Przywara @ 2007-08-13 10:03 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: Type: text/plain, Size: 55 bytes --]
Signed-off-by: Andre Przywara <andre.przywara@amd.com>
[-- Attachment #2: numa_hvm_guest4.patch --]
[-- Type: text/plain, Size: 9481 bytes --]
# HG changeset patch
# User andre.przywara@amd.com
# 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);
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2007-08-13 10:03 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-08-13 10:03 [PATCH 4/4] [HVM] inject created SRAT table into the guest Andre Przywara
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.