aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-04-01 14:13:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-01 14:13:31 -0400
commit9c9cb14387389a70fe40f9be99f243e2a410b0b7 (patch)
treecb927908a099f6448f86871e3bbc3985139db6cd
parent4fe70410d9a219dabb47328effccae7e7f2a6e26 (diff)
parentc549e71d073a6e9a4847497344db28a784061455 (diff)
Merge branch 'x86/setup' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'x86/setup' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: x86, setup: ACPI 3, BIOS workaround for E820-probing code x86, setup: preemptively save/restore edi and ebp around INT 15 E820 x86, setup: mark %esi as clobbered in E820 BIOS call
-rw-r--r--arch/x86/boot/memory.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/arch/x86/boot/memory.c b/arch/x86/boot/memory.c
index 8c3c25f35578..d5d2360763dc 100644
--- a/arch/x86/boot/memory.c
+++ b/arch/x86/boot/memory.c
@@ -2,6 +2,7 @@
2 * 2 *
3 * Copyright (C) 1991, 1992 Linus Torvalds 3 * Copyright (C) 1991, 1992 Linus Torvalds
4 * Copyright 2007 rPath, Inc. - All Rights Reserved 4 * Copyright 2007 rPath, Inc. - All Rights Reserved
5 * Copyright 2009 Intel Corporation; author H. Peter Anvin
5 * 6 *
6 * This file is part of the Linux kernel, and is made available under 7 * This file is part of the Linux kernel, and is made available under
7 * the terms of the GNU General Public License version 2. 8 * the terms of the GNU General Public License version 2.
@@ -16,24 +17,32 @@
16 17
17#define SMAP 0x534d4150 /* ASCII "SMAP" */ 18#define SMAP 0x534d4150 /* ASCII "SMAP" */
18 19
20struct e820_ext_entry {
21 struct e820entry std;
22 u32 ext_flags;
23} __attribute__((packed));
24
19static int detect_memory_e820(void) 25static int detect_memory_e820(void)
20{ 26{
21 int count = 0; 27 int count = 0;
22 u32 next = 0; 28 u32 next = 0;
23 u32 size, id; 29 u32 size, id, edi;
24 u8 err; 30 u8 err;
25 struct e820entry *desc = boot_params.e820_map; 31 struct e820entry *desc = boot_params.e820_map;
32 static struct e820_ext_entry buf; /* static so it is zeroed */
26 33
27 do { 34 do {
28 size = sizeof(struct e820entry); 35 size = sizeof buf;
29 36
30 /* Important: %edx is clobbered by some BIOSes, 37 /* Important: %edx and %esi are clobbered by some BIOSes,
31 so it must be either used for the error output 38 so they must be either used for the error output
32 or explicitly marked clobbered. */ 39 or explicitly marked clobbered. Given that, assume there
33 asm("int $0x15; setc %0" 40 is something out there clobbering %ebp and %edi, too. */
41 asm("pushl %%ebp; int $0x15; popl %%ebp; setc %0"
34 : "=d" (err), "+b" (next), "=a" (id), "+c" (size), 42 : "=d" (err), "+b" (next), "=a" (id), "+c" (size),
35 "=m" (*desc) 43 "=D" (edi), "+m" (buf)
36 : "D" (desc), "d" (SMAP), "a" (0xe820)); 44 : "D" (&buf), "d" (SMAP), "a" (0xe820)
45 : "esi");
37 46
38 /* BIOSes which terminate the chain with CF = 1 as opposed 47 /* BIOSes which terminate the chain with CF = 1 as opposed
39 to %ebx = 0 don't always report the SMAP signature on 48 to %ebx = 0 don't always report the SMAP signature on
@@ -51,8 +60,14 @@ static int detect_memory_e820(void)
51 break; 60 break;
52 } 61 }
53 62
63 /* ACPI 3.0 added the extended flags support. If bit 0
64 in the extended flags is zero, we're supposed to simply
65 ignore the entry -- a backwards incompatible change! */
66 if (size > 20 && !(buf.ext_flags & 1))
67 continue;
68
69 *desc++ = buf.std;
54 count++; 70 count++;
55 desc++;
56 } while (next && count < ARRAY_SIZE(boot_params.e820_map)); 71 } while (next && count < ARRAY_SIZE(boot_params.e820_map));
57 72
58 return boot_params.e820_entries = count; 73 return boot_params.e820_entries = count;