diff options
Diffstat (limited to 'arch/x86/kernel/resource.c')
-rw-r--r-- | arch/x86/kernel/resource.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c index 407a900da9df..89638af2ff19 100644 --- a/arch/x86/kernel/resource.c +++ b/arch/x86/kernel/resource.c | |||
@@ -1,11 +1,47 @@ | |||
1 | #include <linux/ioport.h> | 1 | #include <linux/ioport.h> |
2 | #include <asm/e820.h> | 2 | #include <asm/e820.h> |
3 | 3 | ||
4 | static void resource_clip(struct resource *res, resource_size_t start, | ||
5 | resource_size_t end) | ||
6 | { | ||
7 | resource_size_t low = 0, high = 0; | ||
8 | |||
9 | if (res->end < start || res->start > end) | ||
10 | return; /* no conflict */ | ||
11 | |||
12 | if (res->start < start) | ||
13 | low = start - res->start; | ||
14 | |||
15 | if (res->end > end) | ||
16 | high = res->end - end; | ||
17 | |||
18 | /* Keep the area above or below the conflict, whichever is larger */ | ||
19 | if (low > high) | ||
20 | res->end = start - 1; | ||
21 | else | ||
22 | res->start = end + 1; | ||
23 | } | ||
24 | |||
25 | static void remove_e820_regions(struct resource *avail) | ||
26 | { | ||
27 | int i; | ||
28 | struct e820entry *entry; | ||
29 | |||
30 | for (i = 0; i < e820.nr_map; i++) { | ||
31 | entry = &e820.map[i]; | ||
32 | |||
33 | resource_clip(avail, entry->addr, | ||
34 | entry->addr + entry->size - 1); | ||
35 | } | ||
36 | } | ||
37 | |||
4 | void arch_remove_reservations(struct resource *avail) | 38 | void arch_remove_reservations(struct resource *avail) |
5 | { | 39 | { |
6 | /* Trim out BIOS area (low 1MB) */ | 40 | /* Trim out BIOS area (low 1MB) and E820 regions */ |
7 | if (avail->flags & IORESOURCE_MEM) { | 41 | if (avail->flags & IORESOURCE_MEM) { |
8 | if (avail->start < BIOS_END) | 42 | if (avail->start < BIOS_END) |
9 | avail->start = BIOS_END; | 43 | avail->start = BIOS_END; |
44 | |||
45 | remove_e820_regions(avail); | ||
10 | } | 46 | } |
11 | } | 47 | } |