diff options
author | Yinghai Lu <yhlu.kernel@gmail.com> | 2008-05-29 19:25:56 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-05-31 03:55:56 -0400 |
commit | 9a73aa81ffb993382afed2ed404bc2b330d75427 (patch) | |
tree | f2dcd6078bf711e2ba5731dbd7e2afbb498519dc /arch/x86/kernel/srat_32.c | |
parent | a5481280b29b6a3db912ec100498bd31eaa6d2db (diff) |
x86: 32bit numa srat fix early_ioremap leak
on two node system (16g RAM) with numa config I got this crash:
get_memcfg_from_srat: assigning address to rsdp
RSD PTR v0 [ACPIAM]
ACPI: Too big length in RSDT: 92
failed to get NUMA memory information from SRAT table
NUMA - single node, flat memory mode
Node: 0, start_pfn: 0, end_pfn: 153
Setting physnode_map array to node 0 for pfns:
0
...
Pid: 0, comm: swapper Not tainted 2.6.26-rc4 #4
[<80b41289>] hlt_loop+0x0/0x3
[<8011efa0>] ? alloc_remap+0x50/0x70
[<8079e32e>] alloc_node_mem_map+0x5e/0xa0
[<8012e77b>] ? printk+0x1b/0x20
[<80b590f6>] free_area_init_node+0xc6/0x470
[<80b588fc>] ? __alloc_bootmem_node+0x2c/0x50
[<80b58ad8>] ? find_min_pfn_for_node+0x38/0x70
[<8012e77b>] ? printk+0x1b/0x20
[<80b597c4>] free_area_init_nodes+0x254/0x2d0
[<80b544d7>] zone_sizes_init+0x97/0xa0
[<80b48a03>] setup_arch+0x383/0x530
[<8012e77b>] ? printk+0x1b/0x20
[<80b41aa4>] start_kernel+0x64/0x350
[<80b412d8>] i386_start_kernel+0x8/0x10
=======================
this patch increases the acpi table limit to 32.
Also match early_ioremap() with early_iounmap().
Signed-off-by: Yinghai Lu <yhlu.kernel@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/srat_32.c')
-rw-r--r-- | arch/x86/kernel/srat_32.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/arch/x86/kernel/srat_32.c b/arch/x86/kernel/srat_32.c index 70e4a374b4e8..88971ee166d4 100644 --- a/arch/x86/kernel/srat_32.c +++ b/arch/x86/kernel/srat_32.c | |||
@@ -261,7 +261,7 @@ out_fail: | |||
261 | 261 | ||
262 | struct acpi_static_rsdt { | 262 | struct acpi_static_rsdt { |
263 | struct acpi_table_rsdt table; | 263 | struct acpi_table_rsdt table; |
264 | u32 padding[7]; /* Allow for 7 more table entries */ | 264 | u32 padding[32]; /* Allow for 32 more table entries */ |
265 | }; | 265 | }; |
266 | 266 | ||
267 | int __init get_memcfg_from_srat(void) | 267 | int __init get_memcfg_from_srat(void) |
@@ -297,7 +297,7 @@ int __init get_memcfg_from_srat(void) | |||
297 | } | 297 | } |
298 | 298 | ||
299 | rsdt = (struct acpi_table_rsdt *) | 299 | rsdt = (struct acpi_table_rsdt *) |
300 | early_ioremap(rsdp->rsdt_physical_address, sizeof(struct acpi_table_rsdt)); | 300 | early_ioremap(rsdp->rsdt_physical_address, sizeof(saved_rsdt)); |
301 | 301 | ||
302 | if (!rsdt) { | 302 | if (!rsdt) { |
303 | printk(KERN_WARNING | 303 | printk(KERN_WARNING |
@@ -310,6 +310,7 @@ int __init get_memcfg_from_srat(void) | |||
310 | 310 | ||
311 | if (strncmp(header->signature, ACPI_SIG_RSDT, strlen(ACPI_SIG_RSDT))) { | 311 | if (strncmp(header->signature, ACPI_SIG_RSDT, strlen(ACPI_SIG_RSDT))) { |
312 | printk(KERN_WARNING "ACPI: RSDT signature incorrect\n"); | 312 | printk(KERN_WARNING "ACPI: RSDT signature incorrect\n"); |
313 | early_iounmap(rsdt, sizeof(saved_rsdt)); | ||
313 | goto out_err; | 314 | goto out_err; |
314 | } | 315 | } |
315 | 316 | ||
@@ -319,37 +320,51 @@ int __init get_memcfg_from_srat(void) | |||
319 | * size of RSDT) divided by the size of each entry | 320 | * size of RSDT) divided by the size of each entry |
320 | * (4-byte table pointers). | 321 | * (4-byte table pointers). |
321 | */ | 322 | */ |
322 | tables = (header->length - sizeof(struct acpi_table_header)) / 4; | 323 | tables = (header->length - sizeof(struct acpi_table_header)) / sizeof(u32); |
323 | 324 | ||
324 | if (!tables) | 325 | if (!tables) |
325 | goto out_err; | 326 | goto out_err; |
326 | 327 | ||
327 | memcpy(&saved_rsdt, rsdt, sizeof(saved_rsdt)); | 328 | memcpy(&saved_rsdt, rsdt, sizeof(saved_rsdt)); |
328 | 329 | early_iounmap(rsdt, sizeof(saved_rsdt)); | |
329 | if (saved_rsdt.table.header.length > sizeof(saved_rsdt)) { | 330 | if (saved_rsdt.table.header.length > sizeof(saved_rsdt)) { |
330 | printk(KERN_WARNING "ACPI: Too big length in RSDT: %d\n", | 331 | printk(KERN_WARNING "ACPI: Too big length in RSDT: %d\n", |
331 | saved_rsdt.table.header.length); | 332 | saved_rsdt.table.header.length); |
332 | goto out_err; | 333 | goto out_err; |
333 | } | 334 | } |
334 | 335 | ||
335 | printk("Begin SRAT table scan....\n"); | 336 | printk("Begin SRAT table scan....%d\n", tables); |
336 | 337 | ||
337 | for (i = 0; i < tables; i++) { | 338 | for (i = 0; i < tables; i++){ |
339 | int result; | ||
340 | u32 length; | ||
338 | /* Map in header, then map in full table length. */ | 341 | /* Map in header, then map in full table length. */ |
339 | header = (struct acpi_table_header *) | 342 | header = (struct acpi_table_header *) |
340 | early_ioremap(saved_rsdt.table.table_offset_entry[i], sizeof(struct acpi_table_header)); | 343 | early_ioremap(saved_rsdt.table.table_offset_entry[i], sizeof(struct acpi_table_header)); |
341 | if (!header) | 344 | if (!header) |
342 | break; | 345 | break; |
346 | |||
347 | printk(KERN_INFO "ACPI: %4.4s %08lX, %04X\n", | ||
348 | header->signature, | ||
349 | (unsigned long)saved_rsdt.table.table_offset_entry[i], | ||
350 | header->length); | ||
351 | |||
352 | if (strncmp((char *) &header->signature, ACPI_SIG_SRAT, 4)) { | ||
353 | early_iounmap(header, sizeof(struct acpi_table_header)); | ||
354 | continue; | ||
355 | } | ||
356 | |||
357 | length = header->length; | ||
358 | early_iounmap(header, sizeof(struct acpi_table_header)); | ||
343 | header = (struct acpi_table_header *) | 359 | header = (struct acpi_table_header *) |
344 | early_ioremap(saved_rsdt.table.table_offset_entry[i], header->length); | 360 | early_ioremap(saved_rsdt.table.table_offset_entry[i], length); |
345 | if (!header) | 361 | if (!header) |
346 | break; | 362 | break; |
347 | 363 | ||
348 | if (strncmp((char *) &header->signature, ACPI_SIG_SRAT, 4)) | ||
349 | continue; | ||
350 | |||
351 | /* we've found the srat table. don't need to look at any more tables */ | 364 | /* we've found the srat table. don't need to look at any more tables */ |
352 | return acpi20_parse_srat((struct acpi_table_srat *)header); | 365 | result = acpi20_parse_srat((struct acpi_table_srat *)header); |
366 | early_iounmap(header, length); | ||
367 | return result; | ||
353 | } | 368 | } |
354 | out_err: | 369 | out_err: |
355 | remove_all_active_ranges(); | 370 | remove_all_active_ranges(); |