Huang, Ying | 0c51a96 | 2008-06-02 14:26:23 +0800 | [diff] [blame] | 1 | #include <linux/kernel.h> |
| 2 | #include <linux/init.h> |
Yinghai Lu | 72d7c3b | 2010-08-25 13:39:17 -0700 | [diff] [blame] | 3 | #include <linux/memblock.h> |
Huang, Ying | 0c51a96 | 2008-06-02 14:26:23 +0800 | [diff] [blame] | 4 | |
| 5 | #include <asm/setup.h> |
| 6 | #include <asm/bios_ebda.h> |
| 7 | |
Huang, Ying | 0c51a96 | 2008-06-02 14:26:23 +0800 | [diff] [blame] | 8 | /* |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 9 | * This function reserves all conventional PC system BIOS related |
| 10 | * firmware memory areas (some of which are data, some of which |
| 11 | * are code), that must not be used by the kernel as available |
| 12 | * RAM. |
| 13 | * |
Huang, Ying | 0c51a96 | 2008-06-02 14:26:23 +0800 | [diff] [blame] | 14 | * The BIOS places the EBDA/XBDA at the top of conventional |
| 15 | * memory, and usually decreases the reported amount of |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 16 | * conventional memory (int 0x12) too. |
H. Peter Anvin | 7c10093 | 2013-02-27 12:46:40 -0800 | [diff] [blame] | 17 | * |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 18 | * This means that as a first approximation on most systems we can |
| 19 | * guess the reserved BIOS area by looking at the low BIOS RAM size |
| 20 | * value and assume that everything above that value (up to 1MB) is |
| 21 | * reserved. |
| 22 | * |
| 23 | * But life in firmware country is not that simple: |
| 24 | * |
| 25 | * - This code also contains a quirk for Dell systems that neglect |
| 26 | * to reserve the EBDA area in the 'RAM size' value ... |
| 27 | * |
| 28 | * - The same quirk also avoids a problem with the AMD768MPX |
| 29 | * chipset: reserve a page before VGA to prevent PCI prefetch |
| 30 | * into it (errata #56). (Usually the page is reserved anyways, |
| 31 | * unless you have no PS/2 mouse plugged in.) |
| 32 | * |
| 33 | * - Plus paravirt systems don't have a reliable value in the |
| 34 | * 'BIOS RAM size' pointer we can rely on, so we must quirk |
| 35 | * them too. |
| 36 | * |
| 37 | * Due to those various problems this function is deliberately |
| 38 | * very conservative and tries to err on the side of reserving |
| 39 | * too much, to not risk reserving too little. |
| 40 | * |
| 41 | * Losing a small amount of memory in the bottom megabyte is |
| 42 | * rarely a problem, as long as we have enough memory to install |
| 43 | * the SMP bootup trampoline which *must* be in this area. |
| 44 | * |
| 45 | * Using memory that is in use by the BIOS or by some DMA device |
| 46 | * the BIOS didn't shut down *is* a big problem to the kernel, |
| 47 | * obviously. |
Huang, Ying | 0c51a96 | 2008-06-02 14:26:23 +0800 | [diff] [blame] | 48 | */ |
H. Peter Anvin | 7c10093 | 2013-02-27 12:46:40 -0800 | [diff] [blame] | 49 | |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 50 | #define BIOS_RAM_SIZE_KB_PTR 0x413 |
H. Peter Anvin | 7c10093 | 2013-02-27 12:46:40 -0800 | [diff] [blame] | 51 | |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 52 | #define BIOS_START_MIN 0x20000U /* 128K, less than this is insane */ |
| 53 | #define BIOS_START_MAX 0x9f000U /* 640K, absolute maximum */ |
| 54 | |
| 55 | void __init reserve_bios_regions(void) |
Huang, Ying | 0c51a96 | 2008-06-02 14:26:23 +0800 | [diff] [blame] | 56 | { |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 57 | unsigned int bios_start, ebda_start; |
Huang, Ying | 0c51a96 | 2008-06-02 14:26:23 +0800 | [diff] [blame] | 58 | |
H. Peter Anvin | 7c10093 | 2013-02-27 12:46:40 -0800 | [diff] [blame] | 59 | /* |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 60 | * NOTE: In a paravirtual environment the BIOS reserved |
| 61 | * area is absent. We'll just have to assume that the |
| 62 | * paravirt case can handle memory setup correctly, |
| 63 | * without our help. |
H. Peter Anvin | 7c10093 | 2013-02-27 12:46:40 -0800 | [diff] [blame] | 64 | */ |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 65 | if (!x86_platform.legacy.reserve_bios_regions) |
Huang, Ying | 0c51a96 | 2008-06-02 14:26:23 +0800 | [diff] [blame] | 66 | return; |
| 67 | |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 68 | /* |
| 69 | * BIOS RAM size is encoded in kilobytes, convert it |
| 70 | * to bytes to get a first guess at where the BIOS |
| 71 | * firmware area starts: |
| 72 | */ |
| 73 | bios_start = *(unsigned short *)__va(BIOS_RAM_SIZE_KB_PTR); |
| 74 | bios_start <<= 10; |
Huang, Ying | 0c51a96 | 2008-06-02 14:26:23 +0800 | [diff] [blame] | 75 | |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 76 | /* |
| 77 | * If bios_start is less than 128K, assume it is bogus |
Andy Lutomirski | 6a79296 | 2016-07-21 14:16:52 -0700 | [diff] [blame] | 78 | * and bump it up to 640K. Similarly, if bios_start is above 640K, |
| 79 | * don't trust it. |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 80 | */ |
Andy Lutomirski | 6a79296 | 2016-07-21 14:16:52 -0700 | [diff] [blame] | 81 | if (bios_start < BIOS_START_MIN || bios_start > BIOS_START_MAX) |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 82 | bios_start = BIOS_START_MAX; |
H. Peter Anvin | 7c10093 | 2013-02-27 12:46:40 -0800 | [diff] [blame] | 83 | |
Andy Lutomirski | 6a79296 | 2016-07-21 14:16:52 -0700 | [diff] [blame] | 84 | /* Get the start address of the EBDA page: */ |
| 85 | ebda_start = get_bios_ebda(); |
| 86 | |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 87 | /* |
Andy Lutomirski | 6a79296 | 2016-07-21 14:16:52 -0700 | [diff] [blame] | 88 | * If the EBDA start address is sane and is below the BIOS region, |
| 89 | * then also reserve everything from the EBDA start address up to |
| 90 | * the BIOS region. |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 91 | */ |
Andy Lutomirski | 6a79296 | 2016-07-21 14:16:52 -0700 | [diff] [blame] | 92 | if (ebda_start >= BIOS_START_MIN && ebda_start < bios_start) |
| 93 | bios_start = ebda_start; |
Huang, Ying | 0c51a96 | 2008-06-02 14:26:23 +0800 | [diff] [blame] | 94 | |
Ingo Molnar | edce212 | 2016-07-21 09:53:52 +0200 | [diff] [blame] | 95 | /* Reserve all memory between bios_start and the 1MB mark: */ |
| 96 | memblock_reserve(bios_start, 0x100000 - bios_start); |
Huang, Ying | 0c51a96 | 2008-06-02 14:26:23 +0800 | [diff] [blame] | 97 | } |