aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/mm
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-01-11 16:43:42 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-11 22:04:51 -0500
commit1584b89c921acefe88881f08d836d80f00600a84 (patch)
tree112d64a284488f490045b19aa910bb1b2abcbff4 /arch/x86_64/mm
parent7a4a76cc1057de0dc96ee481590347aa8c5b9ffb (diff)
[PATCH] x86_64: Validate SLIT table
A lot of Opteron BIOS just pass 10 in all SLIT entries (10 is the normalized unit). This is actually worse than the default heuristic because it leads to pci_distance not knowing the difference between local and remote nodes anymore. This messes up some NUMA heuristics in generic code. In this case it's better to fall back to the default heuristic which just does nodea == nodeb ? 10 : 20. This patch does some basic sanity checking on the SLIT and only accepts the SLIT when it passes. Invariants enforced are: - Node to itself shall be 10 - Any other distance shouldn't be 10 - Distances smaller than 10 are illegal Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64/mm')
-rw-r--r--arch/x86_64/mm/srat.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/arch/x86_64/mm/srat.c b/arch/x86_64/mm/srat.c
index 33340bd1e328..9f69d28652f8 100644
--- a/arch/x86_64/mm/srat.c
+++ b/arch/x86_64/mm/srat.c
@@ -91,9 +91,36 @@ static __init inline int srat_disabled(void)
91 return numa_off || acpi_numa < 0; 91 return numa_off || acpi_numa < 0;
92} 92}
93 93
94/*
95 * A lot of BIOS fill in 10 (= no distance) everywhere. This messes
96 * up the NUMA heuristics which wants the local node to have a smaller
97 * distance than the others.
98 * Do some quick checks here and only use the SLIT if it passes.
99 */
100static __init int slit_valid(struct acpi_table_slit *slit)
101{
102 int i, j;
103 int d = slit->localities;
104 for (i = 0; i < d; i++) {
105 for (j = 0; j < d; j++) {
106 u8 val = slit->entry[d*i + j];
107 if (i == j) {
108 if (val != 10)
109 return 0;
110 } else if (val <= 10)
111 return 0;
112 }
113 }
114 return 1;
115}
116
94/* Callback for SLIT parsing */ 117/* Callback for SLIT parsing */
95void __init acpi_numa_slit_init(struct acpi_table_slit *slit) 118void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
96{ 119{
120 if (!slit_valid(slit)) {
121 printk(KERN_INFO "ACPI: SLIT table looks invalid. Not used.\n");
122 return;
123 }
97 acpi_slit = slit; 124 acpi_slit = slit;
98} 125}
99 126