aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAlexander van Heukelum <heukelum@mailshack.com>2008-03-01 11:09:12 -0500
committerIngo Molnar <mingo@elte.hu>2008-04-17 11:40:51 -0400
commitdedd04be71cea3d5adb14c8f674e801911c89a2f (patch)
tree616250e345885a6f43dba0f407280d0304997ae3 /arch
parent823c248e7cc75b4f22da914b01f8e5433cff197e (diff)
x86: reserve end-of-conventional-memory to 1MB on 32-bit
This patch adds explicit detection of the EBDA and reservation of the rom and adapter address space 0xa0000-0x100000 to the i386 kernels. Before this patch, the EBDA size was hardcoded as 4Kb. Also, the reservation of the adapter range was done by modifying the e820 map which is now not necessary any longer, and that code is removed from copy_e820_map. The amount of conventional memory and the start of the EBDA are detected by reading the BIOS data area directly. Paravirtual environments do not provide this area, so we bail out early in that case. They will just have to set up a correct memory map to start with. Signed-off-by: Alexander van Heukelum <heukelum@fastmail.fm> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/e820_32.c27
-rw-r--r--arch/x86/kernel/setup_32.c64
2 files changed, 58 insertions, 33 deletions
diff --git a/arch/x86/kernel/e820_32.c b/arch/x86/kernel/e820_32.c
index 80444c5c9b14..0240cd778365 100644
--- a/arch/x86/kernel/e820_32.c
+++ b/arch/x86/kernel/e820_32.c
@@ -450,38 +450,25 @@ int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
450 * thinkpad 560x, for example, does not cooperate with the memory 450 * thinkpad 560x, for example, does not cooperate with the memory
451 * detection code.) 451 * detection code.)
452 */ 452 */
453int __init copy_e820_map(struct e820entry * biosmap, int nr_map) 453int __init copy_e820_map(struct e820entry *biosmap, int nr_map)
454{ 454{
455 /* Only one memory region (or negative)? Ignore it */ 455 /* Only one memory region (or negative)? Ignore it */
456 if (nr_map < 2) 456 if (nr_map < 2)
457 return -1; 457 return -1;
458 458
459 do { 459 do {
460 unsigned long long start = biosmap->addr; 460 u64 start = biosmap->addr;
461 unsigned long long size = biosmap->size; 461 u64 size = biosmap->size;
462 unsigned long long end = start + size; 462 u64 end = start + size;
463 unsigned long type = biosmap->type; 463 u32 type = biosmap->type;
464 464
465 /* Overflow in 64 bits? Ignore the memory map. */ 465 /* Overflow in 64 bits? Ignore the memory map. */
466 if (start > end) 466 if (start > end)
467 return -1; 467 return -1;
468 468
469 /*
470 * Some BIOSes claim RAM in the 640k - 1M region.
471 * Not right. Fix it up.
472 */
473 if (type == E820_RAM) {
474 if (start < 0x100000ULL && end > 0xA0000ULL) {
475 if (start < 0xA0000ULL)
476 add_memory_region(start, 0xA0000ULL-start, type);
477 if (end <= 0x100000ULL)
478 continue;
479 start = 0x100000ULL;
480 size = end - start;
481 }
482 }
483 add_memory_region(start, size, type); 469 add_memory_region(start, size, type);
484 } while (biosmap++,--nr_map); 470 } while (biosmap++, --nr_map);
471
485 return 0; 472 return 0;
486} 473}
487 474
diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
index 2b3e5d45176b..14e293edd23f 100644
--- a/arch/x86/kernel/setup_32.c
+++ b/arch/x86/kernel/setup_32.c
@@ -385,15 +385,60 @@ unsigned long __init find_max_low_pfn(void)
385 return max_low_pfn; 385 return max_low_pfn;
386} 386}
387 387
388#define BIOS_EBDA_SEGMENT 0x40E
389#define BIOS_LOWMEM_KILOBYTES 0x413
390
388/* 391/*
389 * workaround for Dell systems that neglect to reserve EBDA 392 * The BIOS places the EBDA/XBDA at the top of conventional
393 * memory, and usually decreases the reported amount of
394 * conventional memory (int 0x12) too. This also contains a
395 * workaround for Dell systems that neglect to reserve EBDA.
396 * The same workaround also avoids a problem with the AMD768MPX
397 * chipset: reserve a page before VGA to prevent PCI prefetch
398 * into it (errata #56). Usually the page is reserved anyways,
399 * unless you have no PS/2 mouse plugged in.
390 */ 400 */
391static void __init reserve_ebda_region(void) 401static void __init reserve_ebda_region(void)
392{ 402{
393 unsigned int addr; 403 unsigned int lowmem, ebda_addr;
394 addr = get_bios_ebda(); 404
395 if (addr) 405 /* To determine the position of the EBDA and the */
396 reserve_bootmem(addr, PAGE_SIZE, BOOTMEM_DEFAULT); 406 /* end of conventional memory, we need to look at */
407 /* the BIOS data area. In a paravirtual environment */
408 /* that area is absent. We'll just have to assume */
409 /* that the paravirt case can handle memory setup */
410 /* correctly, without our help. */
411#ifdef CONFIG_PARAVIRT
412 if ((boot_params.hdr.version >= 0x207) &&
413 (boot_params.hdr.hardware_subarch != 0)) {
414 return;
415 }
416#endif
417
418 /* end of low (conventional) memory */
419 lowmem = *(unsigned short *)__va(BIOS_LOWMEM_KILOBYTES);
420 lowmem <<= 10;
421
422 /* start of EBDA area */
423 ebda_addr = *(unsigned short *)__va(BIOS_EBDA_SEGMENT);
424 ebda_addr <<= 4;
425
426 /* Fixup: bios puts an EBDA in the top 64K segment */
427 /* of conventional memory, but does not adjust lowmem. */
428 if ((lowmem - ebda_addr) <= 0x10000)
429 lowmem = ebda_addr;
430
431 /* Fixup: bios does not report an EBDA at all. */
432 /* Some old Dells seem to need 4k anyhow (bugzilla 2990) */
433 if ((ebda_addr == 0) && (lowmem >= 0x9f000))
434 lowmem = 0x9f000;
435
436 /* Paranoia: should never happen, but... */
437 if ((lowmem == 0) || (lowmem >= 0x100000))
438 lowmem = 0x9f000;
439
440 /* reserve all memory between lowmem and the 1MB mark */
441 reserve_bootmem(lowmem, 0x100000 - lowmem, BOOTMEM_DEFAULT);
397} 442}
398 443
399#ifndef CONFIG_NEED_MULTIPLE_NODES 444#ifndef CONFIG_NEED_MULTIPLE_NODES
@@ -617,16 +662,9 @@ void __init setup_bootmem_allocator(void)
617 */ 662 */
618 reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT); 663 reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
619 664
620 /* reserve EBDA region, it's a 4K region */ 665 /* reserve EBDA region */
621 reserve_ebda_region(); 666 reserve_ebda_region();
622 667
623 /* could be an AMD 768MPX chipset. Reserve a page before VGA to prevent
624 PCI prefetch into it (errata #56). Usually the page is reserved anyways,
625 unless you have no PS/2 mouse plugged in. */
626 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
627 boot_cpu_data.x86 == 6)
628 reserve_bootmem(0xa0000 - 4096, 4096, BOOTMEM_DEFAULT);
629
630#ifdef CONFIG_SMP 668#ifdef CONFIG_SMP
631 /* 669 /*
632 * But first pinch a few for the stack/trampoline stuff 670 * But first pinch a few for the stack/trampoline stuff