Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel'
[palacios.git] / kitten / arch / x86_64 / kernel / e820.c
1 /* 
2  * Handle the memory map.
3  * The functions here do the job until bootmem takes over.
4  * $Id: e820.c,v 1.4 2002/09/19 19:25:32 ak Exp $
5  *
6  *  Getting sanitize_e820_map() in sync with i386 version by applying change:
7  *  -  Provisions for empty E820 memory regions (reported by certain BIOSes).
8  *     Alex Achenbach <xela@slit.de>, December 2002.
9  *  Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
10  *
11  */
12 #include <lwk/kernel.h>
13 #include <lwk/types.h>
14 #include <lwk/init.h>
15 #include <lwk/bootmem.h>
16 #include <lwk/resource.h>
17 #include <lwk/string.h>
18 #include <lwk/linux_compat.h>
19
20 #include <arch/page.h>
21 #include <arch/pgtable.h>
22 #include <arch/e820.h>
23 #include <arch/proto.h>
24 #include <arch/bootsetup.h>
25 #include <arch/sections.h>
26
27 /**
28  * The BIOS "e820" map of memory.
29  */
30 struct e820map e820;
31
32 /* 
33  * PFN of last memory page.
34  */
35 unsigned long end_pfn; 
36 EXPORT_SYMBOL(end_pfn);
37
38 /* 
39  * end_pfn only includes RAM, while end_pfn_map includes all e820 entries.
40  * The direct mapping extends to end_pfn_map, so that we can directly access
41  * apertures, ACPI and other tables without having to play with fixmaps.
42  */ 
43 unsigned long end_pfn_map; 
44
45 /* 
46  * Last pfn which the user wants to use.
47  */
48 unsigned long end_user_pfn = MAXMEM>>PAGE_SHIFT;  
49
50 extern struct resource code_resource, data_resource;
51
52 /* Check for some hardcoded bad areas that early boot is not allowed to touch */ 
53 static inline int bad_addr(unsigned long *addrp, unsigned long size)
54
55         unsigned long addr = *addrp, last = addr + size; 
56
57         /* various gunk below that needed for SMP startup */
58         if (addr < 0x8000) { 
59                 *addrp = 0x8000;
60                 return 1; 
61         }
62
63         /* direct mapping tables of the kernel */
64         if (last >= table_start<<PAGE_SHIFT && addr < table_end<<PAGE_SHIFT) { 
65                 *addrp = table_end << PAGE_SHIFT; 
66                 return 1;
67         } 
68
69         /* initrd image */ 
70         if (LOADER_TYPE && INITRD_START && last >= INITRD_START && 
71             addr < INITRD_START+INITRD_SIZE) { 
72                 *addrp = INITRD_START + INITRD_SIZE; 
73                 return 1;
74         } 
75
76         /* kernel code + 640k memory hole (later should not be needed, but 
77            be paranoid for now) */
78         if (last >= 640*1024 && addr < __pa_symbol(&_end)) { 
79                 *addrp = __pa_symbol(&_end);
80                 return 1;
81         }
82
83         if (last >= ebda_addr && addr < ebda_addr + ebda_size) {
84                 *addrp = ebda_addr + ebda_size;
85                 return 1;
86         }
87
88         /* XXX ramdisk image here? */ 
89         return 0;
90
91
92 /*
93  * This function checks if any part of the range <start,end> is mapped
94  * with type.
95  */
96 int __init
97 e820_any_mapped(unsigned long start, unsigned long end, unsigned type)
98
99         int i;
100         for (i = 0; i < e820.nr_map; i++) { 
101                 struct e820entry *ei = &e820.map[i]; 
102                 if (type && ei->type != type) 
103                         continue;
104                 if (ei->addr >= end || ei->addr + ei->size <= start)
105                         continue; 
106                 return 1; 
107         } 
108         return 0;
109 }
110
111 /*
112  * This function checks if the entire range <start,end> is mapped with type.
113  *
114  * Note: this function only works correct if the e820 table is sorted and
115  * not-overlapping, which is the case
116  */
117 int __init e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
118 {
119         int i;
120         for (i = 0; i < e820.nr_map; i++) {
121                 struct e820entry *ei = &e820.map[i];
122                 if (type && ei->type != type)
123                         continue;
124                 /* is the region (part) in overlap with the current region ?*/
125                 if (ei->addr >= end || ei->addr + ei->size <= start)
126                         continue;
127
128                 /* if the region is at the beginning of <start,end> we move
129                  * start to the end of the region since it's ok until there
130                  */
131                 if (ei->addr <= start)
132                         start = ei->addr + ei->size;
133                 /* if start is now at or beyond end, we're done, full coverage */
134                 if (start >= end)
135                         return 1; /* we're done */
136         }
137         return 0;
138 }
139
140 /* 
141  * Find a free area in a specific range. 
142  */ 
143 unsigned long __init find_e820_area(unsigned long start, unsigned long end, unsigned size) 
144
145         int i; 
146         for (i = 0; i < e820.nr_map; i++) { 
147                 struct e820entry *ei = &e820.map[i]; 
148                 unsigned long addr = ei->addr, last; 
149                 if (ei->type != E820_RAM) 
150                         continue; 
151                 if (addr < start) 
152                         addr = start;
153                 if (addr > ei->addr + ei->size) 
154                         continue; 
155                 while (bad_addr(&addr, size) && addr+size <= ei->addr+ei->size)
156                         ;
157                 last = addr + size;
158                 if (last > ei->addr + ei->size)
159                         continue;
160                 if (last > end) 
161                         continue;
162                 return addr; 
163         } 
164         return -1UL;            
165
166
167 /* 
168  * Free bootmem based on the e820 table for a node.
169  */
170 void __init e820_bootmem_free(unsigned long start, unsigned long end)
171 {
172         int i;
173         for (i = 0; i < e820.nr_map; i++) {
174                 struct e820entry *ei = &e820.map[i]; 
175                 unsigned long last, addr;
176
177                 if (ei->type != E820_RAM || 
178                     ei->addr+ei->size <= start || 
179                     ei->addr >= end)
180                         continue;
181
182                 addr = round_up(ei->addr, PAGE_SIZE);
183                 if (addr < start) 
184                         addr = start;
185
186                 last = round_down(ei->addr + ei->size, PAGE_SIZE); 
187                 if (last >= end)
188                         last = end; 
189
190                 if (last > addr && last-addr >= PAGE_SIZE)
191                         free_bootmem(addr, last-addr);
192         }
193 }
194
195 /*
196  * Find the highest page frame number we have available
197  */
198 unsigned long __init e820_end_of_ram(void)
199 {
200         int i;
201         unsigned long end_pfn = 0;
202         
203         for (i = 0; i < e820.nr_map; i++) {
204                 struct e820entry *ei = &e820.map[i]; 
205                 unsigned long start, end;
206
207                 start = round_up(ei->addr, PAGE_SIZE); 
208                 end = round_down(ei->addr + ei->size, PAGE_SIZE); 
209                 if (start >= end)
210                         continue;
211                 if (ei->type == E820_RAM) { 
212                 if (end > end_pfn<<PAGE_SHIFT)
213                         end_pfn = end>>PAGE_SHIFT;
214                 } else { 
215                         if (end > end_pfn_map<<PAGE_SHIFT) 
216                                 end_pfn_map = end>>PAGE_SHIFT;
217                 } 
218         }
219
220         if (end_pfn > end_pfn_map) 
221                 end_pfn_map = end_pfn;
222         if (end_pfn_map > MAXMEM>>PAGE_SHIFT)
223                 end_pfn_map = MAXMEM>>PAGE_SHIFT;
224         if (end_pfn > end_user_pfn)
225                 end_pfn = end_user_pfn;
226         if (end_pfn > end_pfn_map) 
227                 end_pfn = end_pfn_map; 
228
229         return end_pfn; 
230 }
231
232 /* 
233  * Compute how much memory is missing in a range.
234  * Unlike the other functions in this file the arguments are in page numbers.
235  */
236 unsigned long __init
237 e820_hole_size(unsigned long start_pfn, unsigned long end_pfn)
238 {
239         unsigned long ram = 0;
240         unsigned long start = start_pfn << PAGE_SHIFT;
241         unsigned long end = end_pfn << PAGE_SHIFT;
242         int i;
243         for (i = 0; i < e820.nr_map; i++) {
244                 struct e820entry *ei = &e820.map[i];
245                 unsigned long last, addr;
246
247                 if (ei->type != E820_RAM ||
248                     ei->addr+ei->size <= start ||
249                     ei->addr >= end)
250                         continue;
251
252                 addr = round_up(ei->addr, PAGE_SIZE);
253                 if (addr < start)
254                         addr = start;
255
256                 last = round_down(ei->addr + ei->size, PAGE_SIZE);
257                 if (last >= end)
258                         last = end;
259
260                 if (last > addr)
261                         ram += last - addr;
262         }
263         return ((end - start) - ram) >> PAGE_SHIFT;
264 }
265
266 /*
267  * Mark e820 reserved areas as busy for the resource manager.
268  */
269 void __init e820_reserve_resources(void)
270 {
271         int i;
272         for (i = 0; i < e820.nr_map; i++) {
273                 struct resource *res;
274                 res = alloc_bootmem(sizeof(struct resource));
275                 switch (e820.map[i].type) {
276                 case E820_RAM:  res->name = "System RAM"; break;
277                 case E820_ACPI: res->name = "ACPI Tables"; break;
278                 case E820_NVS:  res->name = "ACPI Non-volatile Storage"; break;
279                 default:        res->name = "reserved";
280                 }
281                 res->start = e820.map[i].addr;
282                 res->end = res->start + e820.map[i].size - 1;
283                 res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
284                 request_resource(&iomem_resource, res);
285                 if (e820.map[i].type == E820_RAM) {
286                         /*
287                          *  We don't know which RAM region contains kernel data,
288                          *  so we try it repeatedly and let the resource manager
289                          *  test it.
290                          */
291                         request_resource(res, &code_resource);
292                         request_resource(res, &data_resource);
293 #ifdef CONFIG_KEXEC
294                         request_resource(res, &crashk_res);
295 #endif
296                 }
297         }
298 }
299
300 /* 
301  * Add a memory region to the kernel e820 map.
302  */ 
303 void __init add_memory_region(unsigned long start, unsigned long size, int type)
304 {
305         int x = e820.nr_map;
306
307         if (x == E820MAX) {
308                 printk(KERN_ERR "Ooops! Too many entries in the memory map!\n");
309                 return;
310         }
311
312         e820.map[x].addr = start;
313         e820.map[x].size = size;
314         e820.map[x].type = type;
315         e820.nr_map++;
316 }
317
318 void __init e820_print_map(char *who)
319 {
320         int i;
321         char type[16];
322         size_t total_size = 0;
323
324         for (i = 0; i < e820.nr_map; i++) {
325                 const struct e820entry * entry = &e820.map[i];
326                 switch (entry->type) {
327                 case E820_RAM:  sprintf(type, "(usable)\n");
328                                 total_size += entry->size;
329                                 break;
330                 case E820_RESERVED:
331                                 sprintf(type, "(reserved)\n");
332                                 break;
333                 case E820_ACPI:
334                                 sprintf(type, "(ACPI data)\n");
335                                 break;
336                 case E820_NVS:
337                                 sprintf(type, "(ACPI NVS)\n");
338                                 break;
339                 default:        sprintf(type, "type %u\n", entry->type);
340                                 break;
341                 }
342
343                 printk(KERN_DEBUG
344                         " %s: %016Lx - %016Lx %s",
345                         who,
346                         (unsigned long long) entry->addr,
347                         (unsigned long long) (entry->addr + entry->size),
348                         type);
349         }
350
351         printk( KERN_DEBUG "Total usable memory %ld bytes\n", total_size );
352 }
353
354 /*
355  * Sanitize the BIOS e820 map.
356  *
357  * Some e820 responses include overlapping entries.  The following 
358  * replaces the original e820 map with a new one, removing overlaps.
359  *
360  */
361 static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
362 {
363         struct change_member {
364                 struct e820entry *pbios; /* pointer to original bios entry */
365                 unsigned long long addr; /* address for this change point */
366         };
367         static struct change_member change_point_list[2*E820MAX] __initdata;
368         static struct change_member *change_point[2*E820MAX] __initdata;
369         static struct e820entry *overlap_list[E820MAX] __initdata;
370         static struct e820entry new_bios[E820MAX] __initdata;
371         struct change_member *change_tmp;
372         unsigned long current_type, last_type;
373         unsigned long long last_addr;
374         int chgidx, still_changing;
375         int overlap_entries;
376         int new_bios_entry;
377         int old_nr, new_nr, chg_nr;
378         int i;
379
380         /*
381                 Visually we're performing the following (1,2,3,4 = memory types)...
382
383                 Sample memory map (w/overlaps):
384                    ____22__________________
385                    ______________________4_
386                    ____1111________________
387                    _44_____________________
388                    11111111________________
389                    ____________________33__
390                    ___________44___________
391                    __________33333_________
392                    ______________22________
393                    ___________________2222_
394                    _________111111111______
395                    _____________________11_
396                    _________________4______
397
398                 Sanitized equivalent (no overlap):
399                    1_______________________
400                    _44_____________________
401                    ___1____________________
402                    ____22__________________
403                    ______11________________
404                    _________1______________
405                    __________3_____________
406                    ___________44___________
407                    _____________33_________
408                    _______________2________
409                    ________________1_______
410                    _________________4______
411                    ___________________2____
412                    ____________________33__
413                    ______________________4_
414         */
415
416         /* if there's only one memory region, don't bother */
417         if (*pnr_map < 2)
418                 return -1;
419
420         old_nr = *pnr_map;
421
422         /* bail out if we find any unreasonable addresses in bios map */
423         for (i=0; i<old_nr; i++)
424                 if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr)
425                         return -1;
426
427         /* create pointers for initial change-point information (for sorting) */
428         for (i=0; i < 2*old_nr; i++)
429                 change_point[i] = &change_point_list[i];
430
431         /* record all known change-points (starting and ending addresses),
432            omitting those that are for empty memory regions */
433         chgidx = 0;
434         for (i=0; i < old_nr; i++)      {
435                 if (biosmap[i].size != 0) {
436                         change_point[chgidx]->addr = biosmap[i].addr;
437                         change_point[chgidx++]->pbios = &biosmap[i];
438                         change_point[chgidx]->addr = biosmap[i].addr + biosmap[i].size;
439                         change_point[chgidx++]->pbios = &biosmap[i];
440                 }
441         }
442         chg_nr = chgidx;
443
444         /* sort change-point list by memory addresses (low -> high) */
445         still_changing = 1;
446         while (still_changing)  {
447                 still_changing = 0;
448                 for (i=1; i < chg_nr; i++)  {
449                         /* if <current_addr> > <last_addr>, swap */
450                         /* or, if current=<start_addr> & last=<end_addr>, swap */
451                         if ((change_point[i]->addr < change_point[i-1]->addr) ||
452                                 ((change_point[i]->addr == change_point[i-1]->addr) &&
453                                  (change_point[i]->addr == change_point[i]->pbios->addr) &&
454                                  (change_point[i-1]->addr != change_point[i-1]->pbios->addr))
455                            )
456                         {
457                                 change_tmp = change_point[i];
458                                 change_point[i] = change_point[i-1];
459                                 change_point[i-1] = change_tmp;
460                                 still_changing=1;
461                         }
462                 }
463         }
464
465         /* create a new bios memory map, removing overlaps */
466         overlap_entries=0;       /* number of entries in the overlap table */
467         new_bios_entry=0;        /* index for creating new bios map entries */
468         last_type = 0;           /* start with undefined memory type */
469         last_addr = 0;           /* start with 0 as last starting address */
470         /* loop through change-points, determining affect on the new bios map */
471         for (chgidx=0; chgidx < chg_nr; chgidx++)
472         {
473                 /* keep track of all overlapping bios entries */
474                 if (change_point[chgidx]->addr == change_point[chgidx]->pbios->addr)
475                 {
476                         /* add map entry to overlap list (> 1 entry implies an overlap) */
477                         overlap_list[overlap_entries++]=change_point[chgidx]->pbios;
478                 }
479                 else
480                 {
481                         /* remove entry from list (order independent, so swap with last) */
482                         for (i=0; i<overlap_entries; i++)
483                         {
484                                 if (overlap_list[i] == change_point[chgidx]->pbios)
485                                         overlap_list[i] = overlap_list[overlap_entries-1];
486                         }
487                         overlap_entries--;
488                 }
489                 /* if there are overlapping entries, decide which "type" to use */
490                 /* (larger value takes precedence -- 1=usable, 2,3,4,4+=unusable) */
491                 current_type = 0;
492                 for (i=0; i<overlap_entries; i++)
493                         if (overlap_list[i]->type > current_type)
494                                 current_type = overlap_list[i]->type;
495                 /* continue building up new bios map based on this information */
496                 if (current_type != last_type)  {
497                         if (last_type != 0)      {
498                                 new_bios[new_bios_entry].size =
499                                         change_point[chgidx]->addr - last_addr;
500                                 /* move forward only if the new size was non-zero */
501                                 if (new_bios[new_bios_entry].size != 0)
502                                         if (++new_bios_entry >= E820MAX)
503                                                 break;  /* no more space left for new bios entries */
504                         }
505                         if (current_type != 0)  {
506                                 new_bios[new_bios_entry].addr = change_point[chgidx]->addr;
507                                 new_bios[new_bios_entry].type = current_type;
508                                 last_addr=change_point[chgidx]->addr;
509                         }
510                         last_type = current_type;
511                 }
512         }
513         new_nr = new_bios_entry;   /* retain count for new bios entries */
514
515         /* copy new bios mapping into original location */
516         memcpy(biosmap, new_bios, new_nr*sizeof(struct e820entry));
517         *pnr_map = new_nr;
518
519         return 0;
520 }
521
522 /*
523  * Copy the BIOS e820 map into a safe place.
524  *
525  * Sanity-check it while we're at it..
526  *
527  * If we're lucky and live on a modern system, the setup code
528  * will have given us a memory map that we can use to properly
529  * set up memory.  If we aren't, we'll fake a memory map.
530  *
531  * We check to see that the memory map contains at least 2 elements
532  * before we'll use it, because the detection code in setup.S may
533  * not be perfect and most every PC known to man has two memory
534  * regions: one from 0 to 640k, and one from 1mb up.  (The IBM
535  * thinkpad 560x, for example, does not cooperate with the memory
536  * detection code.)
537  */
538 static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
539 {
540         /* Only one memory region (or negative)? Ignore it */
541         if (nr_map < 2)
542                 return -1;
543
544         do {
545                 unsigned long start = biosmap->addr;
546                 unsigned long size = biosmap->size;
547                 unsigned long end = start + size;
548                 unsigned long type = biosmap->type;
549
550                 /* Overflow in 64 bits? Ignore the memory map. */
551                 if (start > end)
552                         return -1;
553
554                 /*
555                  * Some BIOSes claim RAM in the 640k - 1M region.
556                  * Not right. Fix it up.
557                  * 
558                  * This should be removed on Hammer which is supposed to not
559                  * have non e820 covered ISA mappings there, but I had some strange
560                  * problems so it stays for now.  -AK
561                  */
562                 if (type == E820_RAM) {
563                         if (start < 0x100000ULL && end > 0xA0000ULL) {
564                                 if (start < 0xA0000ULL)
565                                         add_memory_region(start, 0xA0000ULL-start, type);
566                                 if (end <= 0x100000ULL)
567                                         continue;
568                                 start = 0x100000ULL;
569                                 size = end - start;
570                         }
571                 }
572
573                 add_memory_region(start, size, type);
574         } while (biosmap++,--nr_map);
575         return 0;
576 }
577
578 void __init setup_memory_region(void)
579 {
580         char *who = "BIOS-e820";
581
582         /*
583          * Try to copy the BIOS-supplied E820-map.
584          *
585          * Otherwise fake a memory map; one section from 0k->640k,
586          * the next section from 1mb->appropriate_mem_k
587          */
588         sanitize_e820_map(E820_MAP, &E820_MAP_NR);
589         if (copy_e820_map(E820_MAP, E820_MAP_NR) < 0) {
590                 unsigned long mem_size;
591
592                 /* compare results from other methods and take the greater */
593                 if (ALT_MEM_K < EXT_MEM_K) {
594                         mem_size = EXT_MEM_K;
595                         who = "BIOS-88";
596                 } else {
597                         mem_size = ALT_MEM_K;
598                         who = "BIOS-e801";
599                 }
600
601                 e820.nr_map = 0;
602                 add_memory_region(0, LOWMEMSIZE(), E820_RAM);
603                 add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
604         }
605
606         printk(KERN_DEBUG "BIOS-provided physical RAM map:\n");
607         e820_print_map(who);
608
609         /* This also sets end_pfn_map */
610         end_pfn = e820_end_of_ram();
611 }
612
613 void __init parse_memopt(char *p, char **from) 
614
615         end_user_pfn = memparse(p, from);
616         end_user_pfn >>= PAGE_SHIFT;    
617
618
619 void __init parse_memmapopt(char *p, char **from)
620 {
621         unsigned long long start_at, mem_size;
622
623         mem_size = memparse(p, from);
624         p = *from;
625         if (*p == '@') {
626                 start_at = memparse(p+1, from);
627                 add_memory_region(start_at, mem_size, E820_RAM);
628         } else if (*p == '#') {
629                 start_at = memparse(p+1, from);
630                 add_memory_region(start_at, mem_size, E820_ACPI);
631         } else if (*p == '$') {
632                 start_at = memparse(p+1, from);
633                 add_memory_region(start_at, mem_size, E820_RESERVED);
634         } else {
635                 end_user_pfn = (mem_size >> PAGE_SHIFT);
636         }
637         p = *from;
638 }
639
640 unsigned long pci_mem_start = 0xaeedbabe;
641
642 /*
643  * Search for the biggest gap in the low 32 bits of the e820
644  * memory space.  We pass this space to PCI to assign MMIO resources
645  * for hotplug or unconfigured devices in.
646  * Hopefully the BIOS let enough space left.
647  */
648 __init void e820_setup_gap(void)
649 {
650         unsigned long gapstart, gapsize, round;
651         unsigned long last;
652         int i;
653         int found = 0;
654
655         last = 0x100000000ull;
656         gapstart = 0x10000000;
657         gapsize = 0x400000;
658         i = e820.nr_map;
659         while (--i >= 0) {
660                 unsigned long long start = e820.map[i].addr;
661                 unsigned long long end = start + e820.map[i].size;
662
663                 /*
664                  * Since "last" is at most 4GB, we know we'll
665                  * fit in 32 bits if this condition is true
666                  */
667                 if (last > end) {
668                         unsigned long gap = last - end;
669
670                         if (gap > gapsize) {
671                                 gapsize = gap;
672                                 gapstart = end;
673                                 found = 1;
674                         }
675                 }
676                 if (start < last)
677                         last = start;
678         }
679
680         if (!found) {
681                 gapstart = (end_pfn << PAGE_SHIFT) + 1024*1024;
682                 printk(KERN_ERR "PCI: Warning: Cannot find a gap in the 32bit address range\n"
683                        KERN_ERR "PCI: Unassigned devices with 32bit resource registers may break!\n");
684         }
685
686         /*
687          * See how much we want to round up: start off with
688          * rounding to the next 1MB area.
689          */
690         round = 0x100000;
691         while ((gapsize >> 4) > round)
692                 round += round;
693         /* Fun with two's complement */
694         pci_mem_start = (gapstart + round) & -round;
695
696         printk(KERN_INFO "Allocating PCI resources starting at %lx (gap: %lx:%lx)\n",
697                 pci_mem_start, gapstart, gapsize);
698 }