SRAT v1 support
Subsystems (4)
Recent linux kernels suppose that the SRAT table is in rev 2 format (ACPI 3.0), but some BIOSes still provide SRAT table in rev 1. The rev 2 of the SRAT extension mainly provides an extension of the "proximity_domain" item from 8 bits to 32 bits, using a "reserved" field of the structure. When the "reserved" field is not null, linux finds a wrong proximity domain, and numa initialization is wrong.
Following patch tests the SRAT revision to allow a correct initialization:
This patch tests the version of SRAT ACPI table to allow supporting SRAT rev 1 and SRAT rev 2.
arch/x86/kernel/acpi/boot.c 2009-03-16 14:52:07.000000000 +0100 renamed from arch/x86/kernel/acpi/boot.c 2009-03-12 14:41:38.000000000 +0100 +0 -0
@@ -260,7 +260,8 @@
}
static int __init
-acpi_parse_lapic(struct acpi_subtable_header * header, const unsigned long end) +acpi_parse_lapic(const struct acpi_subtable_header * const header,
+ const unsigned long end, const int rev)
{
struct acpi_madt_local_apic *processor = NULL;@@ -285,7 +286,8 @@
}
static int __init
-acpi_parse_sapic(struct acpi_subtable_header *header, const unsigned long end) +acpi_parse_sapic(const struct acpi_subtable_header * const header,
+ const unsigned long end, const int rev)
{
struct acpi_madt_local_sapic *processor = NULL;@@ -303,8 +305,8 @@
}
static int __init
-acpi_parse_lapic_addr_ovr(struct acpi_subtable_header * header,
- const unsigned long end)
+acpi_parse_lapic_addr_ovr(const struct acpi_subtable_header * const header,
+ const unsigned long end, const int rev)
{
struct acpi_madt_local_apic_override *lapic_addr_ovr = NULL;@@ -319,7 +321,8 @@
}
static int __init
-acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long end) +acpi_parse_lapic_nmi(const struct acpi_subtable_header * const header,
+ const unsigned long end, const int rev)
{
struct acpi_madt_local_apic_nmi *lapic_nmi = NULL;@@ -341,7 +344,8 @@
#ifdef CONFIG_X86_IO_APIC
static int __init
-acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end) +acpi_parse_ioapic(const struct acpi_subtable_header * const header,
+ const unsigned long end, const int rev)
{
struct acpi_madt_io_apic *ioapic = NULL;@@ -392,8 +396,8 @@
}
static int __init
-acpi_parse_int_src_ovr(struct acpi_subtable_header * header,
- const unsigned long end)
+acpi_parse_int_src_ovr(const struct acpi_subtable_header * const header,
+ const unsigned long end, const int rev)
{
struct acpi_madt_interrupt_override *intsrc = NULL;@@ -426,7 +430,8 @@
}
static int __init
-acpi_parse_nmi_src(struct acpi_subtable_header * header, const unsigned long end) +acpi_parse_nmi_src(const struct acpi_subtable_header * const header,
+ const unsigned long end, const int rev)
{
struct acpi_madt_nmi_source *nmi_src = NULL;arch/x86/mm/srat_64.c 2009-03-16 15:25:18.000000000 +0100 renamed from arch/x86/mm/srat_64.c 2009-03-12 14:41:38.000000000 +0100 +0 -0
@@ -220,7 +220,7 @@
/* Callback for parsing of the Proximity Domain <-> Memory Area mappings */ void __init
-acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma) +acpi_numa_memory_affinity_init(const struct acpi_srat_mem_affinity * const ma, const int rev)
{
struct bootnode *nd, oldnode;
unsigned long start, end;
@@ -240,7 +240,18 @@
return;
start = ma->base_address;
end = start + ma->length;
- pxm = ma->proximity_domain;
+ switch (rev){
+ case ACPI_SRAT_MEM_AFF_ACPI2:+ pxm = ma->_2.proximity_domain;
+ break;
+ case ACPI_SRAT_MEM_AFF_ACPI3:
+ pxm = ma->_3.proximity_domain;
+ break;
+ default:
+ printk(KERN_ERR "SRAT: unknown memory affinity revision %d+1\n", rev);
+ bad_srat();
+ return;
+ }
node = setup_node(pxm);
if (node < 0) {
printk(KERN_ERR "SRAT: Too many proximity domains.\n");drivers/acpi/numa.c 2009-03-16 15:25:59.000000000 +0100 renamed from drivers/acpi/numa.c 2009-03-12 14:41:43.000000000 +0100 +0 -0
@@ -88,7 +88,8 @@
#endif /* 0 */
static void __init
-acpi_table_print_srat_entry(struct acpi_subtable_header *header) +acpi_table_print_srat_entry(const struct acpi_subtable_header * const header,
+ const int rev)
{
ACPI_FUNCTION_NAME("acpi_table_print_srat_entry");
@@ -116,13 +117,25 @@
case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
#ifdef ACPI_DEBUG_OUTPUT
{- struct acpi_srat_mem_affinity *p =
- (struct acpi_srat_mem_affinity *)header;
+ struct acpi_srat_mem_affinity *p = (struct acpi_srat_mem_affinity *)header;
+ int pxm;
+
+ switch (rev){
+ case ACPI_SRAT_MEM_AFF_ACPI2:
+ pxm = p->_2.proximity_domain;
+ break;
+ case ACPI_SRAT_MEM_AFF_ACPI3:
+ pxm = p->_3.proximity_domain;
+ break;
+ default:
+ printk(KERN_ERR "SRAT: unknown memory affinity revision %d+1\n", rev);
+ pxm = 0;
+ }
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"SRAT Memory (0x%lx length 0x%lx) in proximity
domain %d %s%s\n",
(unsigned long)p->base_address,
(unsigned long)p->length,
- p->proximity_domain,
+ pxm,
(p->flags & ACPI_SRAT_MEM_ENABLED)?
"enabled" : "disabled",
(p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE)?@@ -181,8 +194,8 @@
}
static int __init
-acpi_parse_processor_affinity(struct acpi_subtable_header * header,
- const unsigned long end)
+acpi_parse_processor_affinity(const struct acpi_subtable_header * const header,
+ const unsigned long end, const int rev)
{
struct acpi_srat_cpu_affinity *processor_affinity;@@ -190,7 +203,7 @@
if (!processor_affinity)
return -EINVAL;- acpi_table_print_srat_entry(header);
+ acpi_table_print_srat_entry(header, rev);
/* let architecture-dependent part to do it */
acpi_numa_processor_affinity_init(processor_affinity);@@ -199,8 +212,8 @@
}
static int __init
-acpi_parse_memory_affinity(struct acpi_subtable_header * header,
- const unsigned long end)
+acpi_parse_memory_affinity(const struct acpi_subtable_header * const header,
+ const unsigned long end, const int rev)
{
struct acpi_srat_mem_affinity *memory_affinity;@@ -208,10 +221,10 @@
if (!memory_affinity)
return -EINVAL;- acpi_table_print_srat_entry(header);
+ acpi_table_print_srat_entry(header, rev);
/* let architecture-dependent part to do it */
- acpi_numa_memory_affinity_init(memory_affinity);
+ acpi_numa_memory_affinity_init(memory_affinity, rev);
return 0; }
@@ -239,7 +252,7 @@
int __init acpi_numa_init(void)
{
- /* SRAT: Static Resource Affinity Table */
+ /* SRAT: Static/System Resource Affinity Table */
if (!acpi_table_parse(ACPI_SIG_SRAT, acpi_parse_srat)) {
acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
acpi_parse_processor_affinity, NR_CPUS);drivers/acpi/tables.c 2009-03-16 15:01:05.000000000 +0100 renamed from drivers/acpi/tables.c 2009-03-12 14:41:43.000000000 +0100 +0 -0
@@ -44,7 +44,7 @@
static int acpi_apic_instance __initdata;
-void acpi_table_print_madt_entry(struct acpi_subtable_header *header) +void acpi_table_print_madt_entry(const struct acpi_subtable_header * const header)
{
if (!header)
return;
@@ -206,7 +206,7 @@
table_end) {
if (entry->type == entry_id
&& (!max_entries || count++ < max_entries))- if (handler(entry, table_end))
+ if (handler(entry, table_end, table_header->revision))
return -EINVAL;
entry = (struct acpi_subtable_header *)
include/acpi/actbl1.h 2009-03-16 14:53:14.000000000 +0100 renamed from include/acpi/actbl1.h 2009-03-12 14:41:40.000000000 +0100 +0 -0
@@ -1193,16 +1193,26 @@
};
/* 1: Memory Affinity */
+#define ACPI_SRAT_MEM_AFF_ACPI2 1 +#define ACPI_SRAT_MEM_AFF_ACPI3 2
struct acpi_srat_mem_affinity {
struct acpi_subtable_header header;
- u32 proximity_domain;
- u16 reserved; /* Reserved, must be zero */
+ union {+ struct { /* ACPI 2 */
+ u8 proximity_domain;
+ u8 reserved[5]; /* Reserved, must be zero */
+ } _2;
+ struct { /* ACPI 3 */
+ u32 proximity_domain;
+ u16 reserved; /* Reserved, must be zero */
+ } _3;
+ };
u64 base_address;
u64 length;
- u32 reserved1;
+ u32 reserved1;
u32 flags;- u64 reserved2; /* Reserved, must be zero */
+ u64 reserved2; /* Reserved, must be zero */
};
/* Flags */
include/linux/acpi.h 2009-03-16 15:19:07.000000000 +0100 renamed from include/linux/acpi.h 2009-03-12 14:41:40.000000000 +0100 +0 -0
@@ -76,7 +76,8 @@
typedef int (*acpi_table_handler) (struct acpi_table_header *table);
-typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end); +typedef int (*acpi_table_entry_handler) (const struct acpi_subtable_header * const header,
+ const unsigned long end, const int revision);
char * __acpi_map_table (unsigned long phys_addr, unsigned long size);
int early_acpi_boot_init(void);
@@ -91,12 +92,12 @@
int entry_id, acpi_table_entry_handler handler, unsigned intmax_entries);
int acpi_table_parse_madt (enum acpi_madt_type id, acpi_table_entry_handler handler, unsigned int max_entries); int acpi_parse_mcfg (struct acpi_table_header *header);
-void acpi_table_print_madt_entry (struct acpi_subtable_header *madt);
+void acpi_table_print_madt_entry (const struct acpi_subtable_header * const madt);
/* the following four functions are architecture-dependent */
void acpi_numa_slit_init (struct acpi_table_slit *slit);
void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa);
-void acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma);
+void acpi_numa_memory_affinity_init (const struct acpi_srat_mem_affinity * const ma, const int rev); void acpi_numa_arch_fixup(void);
#ifdef CONFIG_ACPI_HOTPLUG_CPU
Quoted 21 lines · xb
Recent linux kernels suppose that the SRAT table is in rev 2 format (ACPI 3.0), but some BIOSes still provide SRAT table in rev 1.
The rev 2 of the SRAT extension mainly provides an extension of the "proximity_domain" item from 8 bits to 32 bits, using a "reserved" field of the structure.
When the "reserved" field is not null, linux finds a wrong proximity domain, and numa initialization is wrong.
Following patch tests the SRAT revision to allow a correct initialization:This patch tests the version of SRAT ACPI table to allow supporting SRAT rev 1 and SRAT rev 2.
diff -Nru
linux-2.6.29-rc7-orig/arch/x86/kernel/acpi/boot.clinux-2.6.29-rc7-tmp/arch/x86/kernel/acpi/boot.c
---linux-2.6.29-rc7-orig/arch/x86/kernel/acpi/boot.c2009-03-12 14:41:38.000000000 +0100
+++linux-2.6.29-rc7-tmp/arch/x86/kernel/acpi/boot.c2009-03-16 14:52:07.000000000 +0100(quoted diff) +0
-0@@ -260,7 +260,8 @@ }
Quoted 5 lines
static int
__init
-acpi_parse_lapic(structacpi_subtable_header* header, const unsigned long end)
+acpi_parse_lapic(const structacpi_subtable_header* const header,
+ const unsigned long end, const int rev)
do we need to pass that rev all over around?
looks like we could use one srat_version or pxm_mask variable to get the same result.
YH
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
yes, could be simpler :-)
I just saw that Kurt Garloff from Suse has published 3 patches on
kernel mailing list that fixes the SRAT v1 issue:
[PATCH 0/3]: Discard reserved PXM bits for SRAT v1 [PATCH 1/3]: Store SRAT revision
[PATCH 2/3]: x86-64: Handle SRAT v1 and v2 consistently
It looks OK for us.
Thanks.
Xavier
Quoted 43 lines · Yinghai Lu
Quoted 25 lines · xb
Recent linux kernels suppose that the SRAT table is in rev 2 format (ACPI 3.0), but some BIOSes still provide SRAT table in rev 1.
The rev 2 of the SRAT extension mainly provides an extension of the "proximity_domain" item from 8 bits to 32 bits, using a "reserved" field of the structure.
When the "reserved" field is not null, linux finds a wrong proximity domain, and numa initialization is wrong.
Following patch tests the SRAT revision to allow a correct initialization:This patch tests the version of SRAT ACPI table to allow supporting SRAT rev 1 and SRAT rev 2.
diff -Nru
linux-2.6.29-rc7-orig/arch/x86/kernel/acpi/boot.clinux-2.6.29-rc7-tmp/arch/x86/kernel/acpi/boot.c
---linux-2.6.29-rc7-orig/arch/x86/kernel/acpi/boot.c2009-03-12
14:41:38.000000000 +0100
+++linux-2.6.29-rc7-tmp/arch/x86/kernel/acpi/boot.c2009-03-16
14:52:07.000000000 +0100(quoted diff) +0
-0@@ -260,7 +260,8 @@ }static int
__init
-acpi_parse_lapic(structacpi_subtable_header* header, const unsigned long end)Review
Quoted 2 lines
(quoted diff) +2
-0+acpi_parse_lapic(const struct acpi_subtable_header * const header, + const unsigned long end, const int rev)do we need to pass that rev all over around?
looks like we could use one
srat_versionorpxm_maskvariable to get the same result.YH
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html