2 * Handle the memory map.
3 * The functions here do the job until bootmem takes over.
5 * Getting sanitize_e820_map() in sync with i386 version by applying change:
6 * - Provisions for empty E820 memory regions (reported by certain BIOSes).
7 * Alex Achenbach <xela@slit.de>, December 2002.
8 * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
11 #include <linux/kernel.h>
12 #include <linux/types.h>
13 #include <linux/init.h>
14 #include <linux/bootmem.h>
15 #include <linux/ioport.h>
16 #include <linux/string.h>
17 #include <linux/kexec.h>
18 #include <linux/module.h>
20 #include <linux/suspend.h>
21 #include <linux/pfn.h>
22 #include <linux/pci.h>
24 #include <asm/pgtable.h>
27 #include <asm/proto.h>
28 #include <asm/setup.h>
29 #include <asm/sections.h>
30 #include <asm/kdebug.h>
31 #include <asm/trampoline.h>
34 * PFN of last memory page.
36 unsigned long end_pfn
;
39 * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
40 * The direct mapping extends to max_pfn_mapped, so that we can directly access
41 * apertures, ACPI and other tables without having to play with fixmaps.
43 unsigned long max_pfn_mapped
;
46 * Last pfn which the user wants to use.
48 static unsigned long __initdata end_user_pfn
= MAXMEM
>>PAGE_SHIFT
;
51 * Find the highest page frame number we have available
53 unsigned long __init
e820_end_of_ram(void)
55 unsigned long last_pfn
;
57 last_pfn
= find_max_pfn_with_active_regions();
59 if (last_pfn
> max_pfn_mapped
)
60 max_pfn_mapped
= last_pfn
;
61 if (max_pfn_mapped
> MAXMEM
>>PAGE_SHIFT
)
62 max_pfn_mapped
= MAXMEM
>>PAGE_SHIFT
;
63 if (last_pfn
> end_user_pfn
)
64 last_pfn
= end_user_pfn
;
65 if (last_pfn
> max_pfn_mapped
)
66 last_pfn
= max_pfn_mapped
;
68 printk(KERN_INFO
"max_pfn_mapped = %lu\n", max_pfn_mapped
);
73 * Mark e820 reserved areas as busy for the resource manager.
75 void __init
e820_reserve_resources(void)
80 res
= alloc_bootmem_low(sizeof(struct resource
) * e820
.nr_map
);
81 for (i
= 0; i
< e820
.nr_map
; i
++) {
82 switch (e820
.map
[i
].type
) {
83 case E820_RAM
: res
->name
= "System RAM"; break;
84 case E820_ACPI
: res
->name
= "ACPI Tables"; break;
85 case E820_NVS
: res
->name
= "ACPI Non-volatile Storage"; break;
86 default: res
->name
= "reserved";
88 res
->start
= e820
.map
[i
].addr
;
89 res
->end
= res
->start
+ e820
.map
[i
].size
- 1;
90 res
->flags
= IORESOURCE_MEM
| IORESOURCE_BUSY
;
91 insert_resource(&iomem_resource
, res
);
97 * Find the ranges of physical addresses that do not correspond to
98 * e820 RAM areas and mark the corresponding pages as nosave for software
99 * suspend and suspend to RAM.
101 * This function requires the e820 map to be sorted and without any
102 * overlapping entries and assumes the first e820 area to be RAM.
104 void __init
e820_mark_nosave_regions(void)
109 paddr
= round_down(e820
.map
[0].addr
+ e820
.map
[0].size
, PAGE_SIZE
);
110 for (i
= 1; i
< e820
.nr_map
; i
++) {
111 struct e820entry
*ei
= &e820
.map
[i
];
113 if (paddr
< ei
->addr
)
114 register_nosave_region(PFN_DOWN(paddr
),
117 paddr
= round_down(ei
->addr
+ ei
->size
, PAGE_SIZE
);
118 if (ei
->type
!= E820_RAM
)
119 register_nosave_region(PFN_UP(ei
->addr
),
122 if (paddr
>= (end_pfn
<< PAGE_SHIFT
))
128 * Finds an active region in the address range from start_pfn to last_pfn and
129 * returns its range in ei_startpfn and ei_endpfn for the e820 entry.
131 static int __init
e820_find_active_region(const struct e820entry
*ei
,
132 unsigned long start_pfn
,
133 unsigned long last_pfn
,
134 unsigned long *ei_startpfn
,
135 unsigned long *ei_endpfn
)
137 *ei_startpfn
= round_up(ei
->addr
, PAGE_SIZE
) >> PAGE_SHIFT
;
138 *ei_endpfn
= round_down(ei
->addr
+ ei
->size
, PAGE_SIZE
) >> PAGE_SHIFT
;
140 /* Skip map entries smaller than a page */
141 if (*ei_startpfn
>= *ei_endpfn
)
144 /* Check if max_pfn_mapped should be updated */
145 if (ei
->type
!= E820_RAM
&& *ei_endpfn
> max_pfn_mapped
)
146 max_pfn_mapped
= *ei_endpfn
;
148 /* Skip if map is outside the node */
149 if (ei
->type
!= E820_RAM
|| *ei_endpfn
<= start_pfn
||
150 *ei_startpfn
>= last_pfn
)
153 /* Check for overlaps */
154 if (*ei_startpfn
< start_pfn
)
155 *ei_startpfn
= start_pfn
;
156 if (*ei_endpfn
> last_pfn
)
157 *ei_endpfn
= last_pfn
;
159 /* Obey end_user_pfn to save on memmap */
160 if (*ei_startpfn
>= end_user_pfn
)
162 if (*ei_endpfn
> end_user_pfn
)
163 *ei_endpfn
= end_user_pfn
;
168 /* Walk the e820 map and register active regions within a node */
170 e820_register_active_regions(int nid
, unsigned long start_pfn
,
171 unsigned long last_pfn
)
173 unsigned long ei_startpfn
;
174 unsigned long ei_endpfn
;
177 for (i
= 0; i
< e820
.nr_map
; i
++)
178 if (e820_find_active_region(&e820
.map
[i
],
180 &ei_startpfn
, &ei_endpfn
))
181 add_active_range(nid
, ei_startpfn
, ei_endpfn
);
185 * Find the hole size (in bytes) in the memory range.
186 * @start: starting address of the memory range to scan
187 * @end: ending address of the memory range to scan
189 unsigned long __init
e820_hole_size(unsigned long start
, unsigned long end
)
191 unsigned long start_pfn
= start
>> PAGE_SHIFT
;
192 unsigned long last_pfn
= end
>> PAGE_SHIFT
;
193 unsigned long ei_startpfn
, ei_endpfn
, ram
= 0;
196 for (i
= 0; i
< e820
.nr_map
; i
++) {
197 if (e820_find_active_region(&e820
.map
[i
],
199 &ei_startpfn
, &ei_endpfn
))
200 ram
+= ei_endpfn
- ei_startpfn
;
202 return end
- start
- (ram
<< PAGE_SHIFT
);
205 static void early_panic(char *msg
)
211 /* We're not void only for x86 32-bit compat */
212 char *__init
machine_specific_memory_setup(void)
214 char *who
= "BIOS-e820";
217 * Try to copy the BIOS-supplied E820-map.
219 * Otherwise fake a memory map; one section from 0k->640k,
220 * the next section from 1mb->appropriate_mem_k
222 new_nr
= boot_params
.e820_entries
;
223 sanitize_e820_map(boot_params
.e820_map
,
224 ARRAY_SIZE(boot_params
.e820_map
),
226 boot_params
.e820_entries
= new_nr
;
227 if (copy_e820_map(boot_params
.e820_map
, boot_params
.e820_entries
) < 0)
228 early_panic("Cannot find a valid memory map");
229 printk(KERN_INFO
"BIOS-provided physical RAM map:\n");
232 /* In case someone cares... */
236 static int __init
parse_memopt(char *p
)
240 end_user_pfn
= memparse(p
, &p
);
241 end_user_pfn
>>= PAGE_SHIFT
;
244 early_param("mem", parse_memopt
);
246 static int userdef __initdata
;
248 static int __init
parse_memmap_opt(char *p
)
251 unsigned long long start_at
, mem_size
;
253 if (!strcmp(p
, "exactmap")) {
254 #ifdef CONFIG_CRASH_DUMP
256 * If we are doing a crash dump, we still need to know
257 * the real mem size before original memory map is
260 e820_register_active_regions(0, 0, -1UL);
261 saved_max_pfn
= e820_end_of_ram();
262 remove_all_active_ranges();
271 mem_size
= memparse(p
, &p
);
277 start_at
= memparse(p
+1, &p
);
278 add_memory_region(start_at
, mem_size
, E820_RAM
);
279 } else if (*p
== '#') {
280 start_at
= memparse(p
+1, &p
);
281 add_memory_region(start_at
, mem_size
, E820_ACPI
);
282 } else if (*p
== '$') {
283 start_at
= memparse(p
+1, &p
);
284 add_memory_region(start_at
, mem_size
, E820_RESERVED
);
286 end_user_pfn
= (mem_size
>> PAGE_SHIFT
);
288 return *p
== '\0' ? 0 : -EINVAL
;
290 early_param("memmap", parse_memmap_opt
);
292 void __init
finish_e820_parsing(void)
295 int nr
= e820
.nr_map
;
297 if (sanitize_e820_map(e820
.map
, ARRAY_SIZE(e820
.map
), &nr
) < 0)
298 early_panic("Invalid user supplied memory map");
301 printk(KERN_INFO
"user-defined physical RAM map:\n");
302 e820_print_map("user");
306 int __init
arch_get_ram_range(int slot
, u64
*addr
, u64
*size
)
310 if (slot
< 0 || slot
>= e820
.nr_map
)
312 for (i
= slot
; i
< e820
.nr_map
; i
++) {
313 if (e820
.map
[i
].type
!= E820_RAM
)
317 if (i
== e820
.nr_map
|| e820
.map
[i
].addr
> (max_pfn
<< PAGE_SHIFT
))
319 *addr
= e820
.map
[i
].addr
;
320 *size
= min_t(u64
, e820
.map
[i
].size
+ e820
.map
[i
].addr
,
321 max_pfn
<< PAGE_SHIFT
) - *addr
;