diff options
-rw-r--r-- | arch/i386/kernel/e820.c | 152 | ||||
-rw-r--r-- | arch/i386/kernel/setup.c | 153 | ||||
-rw-r--r-- | include/asm-i386/e820.h | 2 |
3 files changed, 155 insertions, 152 deletions
diff --git a/arch/i386/kernel/e820.c b/arch/i386/kernel/e820.c index 47c495bf0cbc..b755255f2721 100644 --- a/arch/i386/kernel/e820.c +++ b/arch/i386/kernel/e820.c | |||
@@ -33,6 +33,7 @@ unsigned long pci_mem_start = 0x10000000; | |||
33 | #ifdef CONFIG_PCI | 33 | #ifdef CONFIG_PCI |
34 | EXPORT_SYMBOL(pci_mem_start); | 34 | EXPORT_SYMBOL(pci_mem_start); |
35 | #endif | 35 | #endif |
36 | extern int user_defined_memmap; | ||
36 | struct resource data_resource = { | 37 | struct resource data_resource = { |
37 | .name = "Kernel data", | 38 | .name = "Kernel data", |
38 | .start = 0, | 39 | .start = 0, |
@@ -706,3 +707,154 @@ void __init register_memory(void) | |||
706 | printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n", | 707 | printk("Allocating PCI resources starting at %08lx (gap: %08lx:%08lx)\n", |
707 | pci_mem_start, gapstart, gapsize); | 708 | pci_mem_start, gapstart, gapsize); |
708 | } | 709 | } |
710 | |||
711 | void __init print_memory_map(char *who) | ||
712 | { | ||
713 | int i; | ||
714 | |||
715 | for (i = 0; i < e820.nr_map; i++) { | ||
716 | printk(" %s: %016Lx - %016Lx ", who, | ||
717 | e820.map[i].addr, | ||
718 | e820.map[i].addr + e820.map[i].size); | ||
719 | switch (e820.map[i].type) { | ||
720 | case E820_RAM: printk("(usable)\n"); | ||
721 | break; | ||
722 | case E820_RESERVED: | ||
723 | printk("(reserved)\n"); | ||
724 | break; | ||
725 | case E820_ACPI: | ||
726 | printk("(ACPI data)\n"); | ||
727 | break; | ||
728 | case E820_NVS: | ||
729 | printk("(ACPI NVS)\n"); | ||
730 | break; | ||
731 | default: printk("type %lu\n", e820.map[i].type); | ||
732 | break; | ||
733 | } | ||
734 | } | ||
735 | } | ||
736 | |||
737 | void __init limit_regions(unsigned long long size) | ||
738 | { | ||
739 | unsigned long long current_addr = 0; | ||
740 | int i; | ||
741 | |||
742 | print_memory_map("limit_regions start"); | ||
743 | if (efi_enabled) { | ||
744 | efi_memory_desc_t *md; | ||
745 | void *p; | ||
746 | |||
747 | for (p = memmap.map, i = 0; p < memmap.map_end; | ||
748 | p += memmap.desc_size, i++) { | ||
749 | md = p; | ||
750 | current_addr = md->phys_addr + (md->num_pages << 12); | ||
751 | if (md->type == EFI_CONVENTIONAL_MEMORY) { | ||
752 | if (current_addr >= size) { | ||
753 | md->num_pages -= | ||
754 | (((current_addr-size) + PAGE_SIZE-1) >> PAGE_SHIFT); | ||
755 | memmap.nr_map = i + 1; | ||
756 | return; | ||
757 | } | ||
758 | } | ||
759 | } | ||
760 | } | ||
761 | for (i = 0; i < e820.nr_map; i++) { | ||
762 | current_addr = e820.map[i].addr + e820.map[i].size; | ||
763 | if (current_addr < size) | ||
764 | continue; | ||
765 | |||
766 | if (e820.map[i].type != E820_RAM) | ||
767 | continue; | ||
768 | |||
769 | if (e820.map[i].addr >= size) { | ||
770 | /* | ||
771 | * This region starts past the end of the | ||
772 | * requested size, skip it completely. | ||
773 | */ | ||
774 | e820.nr_map = i; | ||
775 | } else { | ||
776 | e820.nr_map = i + 1; | ||
777 | e820.map[i].size -= current_addr - size; | ||
778 | } | ||
779 | print_memory_map("limit_regions endfor"); | ||
780 | return; | ||
781 | } | ||
782 | print_memory_map("limit_regions endfunc"); | ||
783 | } | ||
784 | |||
785 | /* | ||
786 | * This function checks if the entire range <start,end> is mapped with type. | ||
787 | * | ||
788 | * Note: this function only works correct if the e820 table is sorted and | ||
789 | * not-overlapping, which is the case | ||
790 | */ | ||
791 | int __init | ||
792 | e820_all_mapped(unsigned long s, unsigned long e, unsigned type) | ||
793 | { | ||
794 | u64 start = s; | ||
795 | u64 end = e; | ||
796 | int i; | ||
797 | for (i = 0; i < e820.nr_map; i++) { | ||
798 | struct e820entry *ei = &e820.map[i]; | ||
799 | if (type && ei->type != type) | ||
800 | continue; | ||
801 | /* is the region (part) in overlap with the current region ?*/ | ||
802 | if (ei->addr >= end || ei->addr + ei->size <= start) | ||
803 | continue; | ||
804 | /* if the region is at the beginning of <start,end> we move | ||
805 | * start to the end of the region since it's ok until there | ||
806 | */ | ||
807 | if (ei->addr <= start) | ||
808 | start = ei->addr + ei->size; | ||
809 | /* if start is now at or beyond end, we're done, full | ||
810 | * coverage */ | ||
811 | if (start >= end) | ||
812 | return 1; /* we're done */ | ||
813 | } | ||
814 | return 0; | ||
815 | } | ||
816 | |||
817 | static int __init parse_memmap(char *arg) | ||
818 | { | ||
819 | if (!arg) | ||
820 | return -EINVAL; | ||
821 | |||
822 | if (strcmp(arg, "exactmap") == 0) { | ||
823 | #ifdef CONFIG_CRASH_DUMP | ||
824 | /* If we are doing a crash dump, we | ||
825 | * still need to know the real mem | ||
826 | * size before original memory map is | ||
827 | * reset. | ||
828 | */ | ||
829 | find_max_pfn(); | ||
830 | saved_max_pfn = max_pfn; | ||
831 | #endif | ||
832 | e820.nr_map = 0; | ||
833 | user_defined_memmap = 1; | ||
834 | } else { | ||
835 | /* If the user specifies memory size, we | ||
836 | * limit the BIOS-provided memory map to | ||
837 | * that size. exactmap can be used to specify | ||
838 | * the exact map. mem=number can be used to | ||
839 | * trim the existing memory map. | ||
840 | */ | ||
841 | unsigned long long start_at, mem_size; | ||
842 | |||
843 | mem_size = memparse(arg, &arg); | ||
844 | if (*arg == '@') { | ||
845 | start_at = memparse(arg+1, &arg); | ||
846 | add_memory_region(start_at, mem_size, E820_RAM); | ||
847 | } else if (*arg == '#') { | ||
848 | start_at = memparse(arg+1, &arg); | ||
849 | add_memory_region(start_at, mem_size, E820_ACPI); | ||
850 | } else if (*arg == '$') { | ||
851 | start_at = memparse(arg+1, &arg); | ||
852 | add_memory_region(start_at, mem_size, E820_RESERVED); | ||
853 | } else { | ||
854 | limit_regions(mem_size); | ||
855 | user_defined_memmap = 1; | ||
856 | } | ||
857 | } | ||
858 | return 0; | ||
859 | } | ||
860 | early_param("memmap", parse_memmap); | ||
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 51ed015a1f35..e5bb87aa5a45 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c | |||
@@ -73,7 +73,6 @@ int disable_pse __devinitdata = 0; | |||
73 | /* | 73 | /* |
74 | * Machine setup.. | 74 | * Machine setup.. |
75 | */ | 75 | */ |
76 | extern struct e820map e820; | ||
77 | extern struct resource code_resource; | 76 | extern struct resource code_resource; |
78 | extern struct resource data_resource; | 77 | extern struct resource data_resource; |
79 | 78 | ||
@@ -137,79 +136,6 @@ static char command_line[COMMAND_LINE_SIZE]; | |||
137 | 136 | ||
138 | unsigned char __initdata boot_params[PARAM_SIZE]; | 137 | unsigned char __initdata boot_params[PARAM_SIZE]; |
139 | 138 | ||
140 | static void __init limit_regions(unsigned long long size) | ||
141 | { | ||
142 | unsigned long long current_addr = 0; | ||
143 | int i; | ||
144 | |||
145 | if (efi_enabled) { | ||
146 | efi_memory_desc_t *md; | ||
147 | void *p; | ||
148 | |||
149 | for (p = memmap.map, i = 0; p < memmap.map_end; | ||
150 | p += memmap.desc_size, i++) { | ||
151 | md = p; | ||
152 | current_addr = md->phys_addr + (md->num_pages << 12); | ||
153 | if (md->type == EFI_CONVENTIONAL_MEMORY) { | ||
154 | if (current_addr >= size) { | ||
155 | md->num_pages -= | ||
156 | (((current_addr-size) + PAGE_SIZE-1) >> PAGE_SHIFT); | ||
157 | memmap.nr_map = i + 1; | ||
158 | return; | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | } | ||
163 | for (i = 0; i < e820.nr_map; i++) { | ||
164 | current_addr = e820.map[i].addr + e820.map[i].size; | ||
165 | if (current_addr < size) | ||
166 | continue; | ||
167 | |||
168 | if (e820.map[i].type != E820_RAM) | ||
169 | continue; | ||
170 | |||
171 | if (e820.map[i].addr >= size) { | ||
172 | /* | ||
173 | * This region starts past the end of the | ||
174 | * requested size, skip it completely. | ||
175 | */ | ||
176 | e820.nr_map = i; | ||
177 | } else { | ||
178 | e820.nr_map = i + 1; | ||
179 | e820.map[i].size -= current_addr - size; | ||
180 | } | ||
181 | return; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | #define E820_DEBUG 1 | ||
186 | |||
187 | static void __init print_memory_map(char *who) | ||
188 | { | ||
189 | int i; | ||
190 | |||
191 | for (i = 0; i < e820.nr_map; i++) { | ||
192 | printk(" %s: %016Lx - %016Lx ", who, | ||
193 | e820.map[i].addr, | ||
194 | e820.map[i].addr + e820.map[i].size); | ||
195 | switch (e820.map[i].type) { | ||
196 | case E820_RAM: printk("(usable)\n"); | ||
197 | break; | ||
198 | case E820_RESERVED: | ||
199 | printk("(reserved)\n"); | ||
200 | break; | ||
201 | case E820_ACPI: | ||
202 | printk("(ACPI data)\n"); | ||
203 | break; | ||
204 | case E820_NVS: | ||
205 | printk("(ACPI NVS)\n"); | ||
206 | break; | ||
207 | default: printk("type %lu\n", e820.map[i].type); | ||
208 | break; | ||
209 | } | ||
210 | } | ||
211 | } | ||
212 | |||
213 | #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) | 139 | #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) |
214 | struct edd edd; | 140 | struct edd edd; |
215 | #ifdef CONFIG_EDD_MODULE | 141 | #ifdef CONFIG_EDD_MODULE |
@@ -233,7 +159,7 @@ static inline void copy_edd(void) | |||
233 | } | 159 | } |
234 | #endif | 160 | #endif |
235 | 161 | ||
236 | static int __initdata user_defined_memmap = 0; | 162 | int __initdata user_defined_memmap = 0; |
237 | 163 | ||
238 | /* | 164 | /* |
239 | * "mem=nopentium" disables the 4MB page tables. | 165 | * "mem=nopentium" disables the 4MB page tables. |
@@ -270,51 +196,6 @@ static int __init parse_mem(char *arg) | |||
270 | } | 196 | } |
271 | early_param("mem", parse_mem); | 197 | early_param("mem", parse_mem); |
272 | 198 | ||
273 | static int __init parse_memmap(char *arg) | ||
274 | { | ||
275 | if (!arg) | ||
276 | return -EINVAL; | ||
277 | |||
278 | if (strcmp(arg, "exactmap") == 0) { | ||
279 | #ifdef CONFIG_CRASH_DUMP | ||
280 | /* If we are doing a crash dump, we | ||
281 | * still need to know the real mem | ||
282 | * size before original memory map is | ||
283 | * reset. | ||
284 | */ | ||
285 | find_max_pfn(); | ||
286 | saved_max_pfn = max_pfn; | ||
287 | #endif | ||
288 | e820.nr_map = 0; | ||
289 | user_defined_memmap = 1; | ||
290 | } else { | ||
291 | /* If the user specifies memory size, we | ||
292 | * limit the BIOS-provided memory map to | ||
293 | * that size. exactmap can be used to specify | ||
294 | * the exact map. mem=number can be used to | ||
295 | * trim the existing memory map. | ||
296 | */ | ||
297 | unsigned long long start_at, mem_size; | ||
298 | |||
299 | mem_size = memparse(arg, &arg); | ||
300 | if (*arg == '@') { | ||
301 | start_at = memparse(arg+1, &arg); | ||
302 | add_memory_region(start_at, mem_size, E820_RAM); | ||
303 | } else if (*arg == '#') { | ||
304 | start_at = memparse(arg+1, &arg); | ||
305 | add_memory_region(start_at, mem_size, E820_ACPI); | ||
306 | } else if (*arg == '$') { | ||
307 | start_at = memparse(arg+1, &arg); | ||
308 | add_memory_region(start_at, mem_size, E820_RESERVED); | ||
309 | } else { | ||
310 | limit_regions(mem_size); | ||
311 | user_defined_memmap = 1; | ||
312 | } | ||
313 | } | ||
314 | return 0; | ||
315 | } | ||
316 | early_param("memmap", parse_memmap); | ||
317 | |||
318 | #ifdef CONFIG_PROC_VMCORE | 199 | #ifdef CONFIG_PROC_VMCORE |
319 | /* elfcorehdr= specifies the location of elf core header | 200 | /* elfcorehdr= specifies the location of elf core header |
320 | * stored by the crashed kernel. | 201 | * stored by the crashed kernel. |
@@ -378,38 +259,6 @@ static int __init parse_reservetop(char *arg) | |||
378 | } | 259 | } |
379 | early_param("reservetop", parse_reservetop); | 260 | early_param("reservetop", parse_reservetop); |
380 | 261 | ||
381 | /* | ||
382 | * This function checks if the entire range <start,end> is mapped with type. | ||
383 | * | ||
384 | * Note: this function only works correct if the e820 table is sorted and | ||
385 | * not-overlapping, which is the case | ||
386 | */ | ||
387 | int __init | ||
388 | e820_all_mapped(unsigned long s, unsigned long e, unsigned type) | ||
389 | { | ||
390 | u64 start = s; | ||
391 | u64 end = e; | ||
392 | int i; | ||
393 | for (i = 0; i < e820.nr_map; i++) { | ||
394 | struct e820entry *ei = &e820.map[i]; | ||
395 | if (type && ei->type != type) | ||
396 | continue; | ||
397 | /* is the region (part) in overlap with the current region ?*/ | ||
398 | if (ei->addr >= end || ei->addr + ei->size <= start) | ||
399 | continue; | ||
400 | /* if the region is at the beginning of <start,end> we move | ||
401 | * start to the end of the region since it's ok until there | ||
402 | */ | ||
403 | if (ei->addr <= start) | ||
404 | start = ei->addr + ei->size; | ||
405 | /* if start is now at or beyond end, we're done, full | ||
406 | * coverage */ | ||
407 | if (start >= end) | ||
408 | return 1; /* we're done */ | ||
409 | } | ||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | /* | 262 | /* |
414 | * Determine low and high memory ranges: | 263 | * Determine low and high memory ranges: |
415 | */ | 264 | */ |
diff --git a/include/asm-i386/e820.h b/include/asm-i386/e820.h index 8da4175a5533..395077aba583 100644 --- a/include/asm-i386/e820.h +++ b/include/asm-i386/e820.h | |||
@@ -41,6 +41,8 @@ extern int e820_all_mapped(unsigned long start, unsigned long end, | |||
41 | extern void find_max_pfn(void); | 41 | extern void find_max_pfn(void); |
42 | extern void register_bootmem_low_pages(unsigned long max_low_pfn); | 42 | extern void register_bootmem_low_pages(unsigned long max_low_pfn); |
43 | extern void register_memory(void); | 43 | extern void register_memory(void); |
44 | extern void limit_regions(unsigned long long size); | ||
45 | extern void print_memory_map(char *who); | ||
44 | 46 | ||
45 | #endif/*!__ASSEMBLY__*/ | 47 | #endif/*!__ASSEMBLY__*/ |
46 | 48 | ||