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