]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/memory.c
pc: get rid of fixed 8MB memory map (now dynamically between 4 to 16 MB depending...
[plan9front.git] / sys / src / 9 / pc / memory.c
1 /*
2  * Size memory and create the kernel page-tables on the fly while doing so.
3  * Called from main(), this code should only be run by the bootstrap processor.
4  *
5  * MemMin is what the bootstrap code in l.s has already mapped;
6  * MemMax is the limit of physical memory to scan.
7  */
8 #include "u.h"
9 #include "../port/lib.h"
10 #include "mem.h"
11 #include "dat.h"
12 #include "fns.h"
13 #include "io.h"
14 #include "ureg.h"
15
16 #define MEMDEBUG        0
17
18 u32int MemMin = 8*MB;   /* set in l.s */
19
20 enum {
21         MemUPA          = 0,            /* unbacked physical address */
22         MemRAM          = 1,            /* physical memory */
23         MemUMB          = 2,            /* upper memory block (<16MB) */
24         MemReserved     = 3,
25         NMemType        = 4,
26
27         KB              = 1024,
28
29         MemMax          = (3*1024+768)*MB,
30 };
31
32 typedef struct Map Map;
33 struct Map {
34         ulong   size;
35         ulong   addr;
36 };
37
38 typedef struct RMap RMap;
39 struct RMap {
40         char*   name;
41         Map*    map;
42         Map*    mapend;
43
44         Lock;
45 };
46
47 /* 
48  * Memory allocation tracking.
49  */
50 static Map mapupa[16];
51 static RMap rmapupa = {
52         "unallocated unbacked physical memory",
53         mapupa,
54         &mapupa[nelem(mapupa)-1],
55 };
56
57 static Map mapram[16];
58 static RMap rmapram = {
59         "physical memory",
60         mapram,
61         &mapram[nelem(mapram)-1],
62 };
63
64 static Map mapumb[64];
65 static RMap rmapumb = {
66         "upper memory block",
67         mapumb,
68         &mapumb[nelem(mapumb)-1],
69 };
70
71 static Map mapumbrw[16];
72 static RMap rmapumbrw = {
73         "UMB device memory",
74         mapumbrw,
75         &mapumbrw[nelem(mapumbrw)-1],
76 };
77
78 void
79 mapprint(RMap *rmap)
80 {
81         Map *mp;
82
83         print("%s\n", rmap->name);      
84         for(mp = rmap->map; mp->size; mp++)
85                 print("\t%8.8luX %8.8luX (%lud)\n", mp->addr, mp->addr+mp->size, mp->size);
86 }
87
88
89 void
90 memdebug(void)
91 {
92         ulong maxpa, maxpa1, maxpa2;
93
94         maxpa = (nvramread(0x18)<<8)|nvramread(0x17);
95         maxpa1 = (nvramread(0x31)<<8)|nvramread(0x30);
96         maxpa2 = (nvramread(0x16)<<8)|nvramread(0x15);
97         print("maxpa = %luX -> %luX, maxpa1 = %luX maxpa2 = %luX\n",
98                 maxpa, MB+maxpa*KB, maxpa1, maxpa2);
99
100         mapprint(&rmapram);
101         mapprint(&rmapumb);
102         mapprint(&rmapumbrw);
103         mapprint(&rmapupa);
104 }
105
106 void
107 mapfree(RMap* rmap, ulong addr, ulong size)
108 {
109         Map *mp;
110         ulong t;
111
112         if(size <= 0)
113                 return;
114
115         lock(rmap);
116         for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
117                 ;
118
119         if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
120                 (mp-1)->size += size;
121                 if(addr+size == mp->addr){
122                         (mp-1)->size += mp->size;
123                         while(mp->size){
124                                 mp++;
125                                 (mp-1)->addr = mp->addr;
126                                 (mp-1)->size = mp->size;
127                         }
128                 }
129         }
130         else{
131                 if(addr+size == mp->addr && mp->size){
132                         mp->addr -= size;
133                         mp->size += size;
134                 }
135                 else do{
136                         if(mp >= rmap->mapend){
137                                 print("mapfree: %s: losing 0x%luX, %ld\n",
138                                         rmap->name, addr, size);
139                                 break;
140                         }
141                         t = mp->addr;
142                         mp->addr = addr;
143                         addr = t;
144                         t = mp->size;
145                         mp->size = size;
146                         mp++;
147                 }while(size = t);
148         }
149         unlock(rmap);
150 }
151
152 ulong
153 mapalloc(RMap* rmap, ulong addr, int size, int align)
154 {
155         Map *mp;
156         ulong maddr, oaddr;
157
158         lock(rmap);
159         for(mp = rmap->map; mp->size; mp++){
160                 maddr = mp->addr;
161
162                 if(addr){
163                         /*
164                          * A specific address range has been given:
165                          *   if the current map entry is greater then
166                          *   the address is not in the map;
167                          *   if the current map entry does not overlap
168                          *   the beginning of the requested range then
169                          *   continue on to the next map entry;
170                          *   if the current map entry does not entirely
171                          *   contain the requested range then the range
172                          *   is not in the map.
173                          */
174                         if(maddr > addr)
175                                 break;
176                         if(mp->size < addr - maddr)     /* maddr+mp->size < addr, but no overflow */
177                                 continue;
178                         if(addr - maddr > mp->size - size)      /* addr+size > maddr+mp->size, but no overflow */
179                                 break;
180                         maddr = addr;
181                 }
182
183                 if(align > 0)
184                         maddr = ((maddr+align-1)/align)*align;
185                 if(mp->addr+mp->size-maddr < size)
186                         continue;
187
188                 oaddr = mp->addr;
189                 mp->addr = maddr+size;
190                 mp->size -= maddr-oaddr+size;
191                 if(mp->size == 0){
192                         do{
193                                 mp++;
194                                 (mp-1)->addr = mp->addr;
195                         }while((mp-1)->size = mp->size);
196                 }
197
198                 unlock(rmap);
199                 if(oaddr != maddr)
200                         mapfree(rmap, oaddr, maddr-oaddr);
201
202                 return maddr;
203         }
204         unlock(rmap);
205
206         return 0;
207 }
208
209 /*
210  * Allocate from the ram map directly to make page tables.
211  * Called by mmuwalk during e820scan.
212  */
213 void*
214 rampage(void)
215 {
216         ulong m;
217         
218         m = mapalloc(&rmapram, 0, BY2PG, BY2PG);
219         if(m == 0)
220                 return nil;
221         return KADDR(m);
222 }
223
224 static void
225 umbexclude(void)
226 {
227         int size;
228         ulong addr;
229         char *op, *p, *rptr;
230
231         if((p = getconf("umbexclude")) == nil)
232                 return;
233
234         while(p && *p != '\0' && *p != '\n'){
235                 op = p;
236                 addr = strtoul(p, &rptr, 0);
237                 if(rptr == nil || rptr == p || *rptr != '-'){
238                         print("umbexclude: invalid argument <%s>\n", op);
239                         break;
240                 }
241                 p = rptr+1;
242
243                 size = strtoul(p, &rptr, 0) - addr + 1;
244                 if(size <= 0){
245                         print("umbexclude: bad range <%s>\n", op);
246                         break;
247                 }
248                 if(rptr != nil && *rptr == ',')
249                         *rptr++ = '\0';
250                 p = rptr;
251
252                 mapalloc(&rmapumb, addr, size, 0);
253         }
254 }
255
256 static void
257 umbscan(void)
258 {
259         uchar *p;
260
261         /*
262          * Scan the Upper Memory Blocks (0xA0000->0xF0000) for pieces
263          * which aren't used; they can be used later for devices which
264          * want to allocate some virtual address space.
265          * Check for two things:
266          * 1) device BIOS ROM. This should start with a two-byte header
267          *    of 0x55 0xAA, followed by a byte giving the size of the ROM
268          *    in 512-byte chunks. These ROM's must start on a 2KB boundary.
269          * 2) device memory. This is read-write.
270          * There are some assumptions: there's VGA memory at 0xA0000 and
271          * the VGA BIOS ROM is at 0xC0000. Also, if there's no ROM signature
272          * at 0xE0000 then the whole 64KB up to 0xF0000 is theoretically up
273          * for grabs; check anyway.
274          */
275         p = KADDR(0xD0000);
276         while(p < (uchar*)KADDR(0xE0000)){
277                 /*
278                  * Test for 0x55 0xAA before poking obtrusively,
279                  * some machines (e.g. Thinkpad X20) seem to map
280                  * something dynamic here (cardbus?) causing weird
281                  * problems if it is changed.
282                  */
283                 if(p[0] == 0x55 && p[1] == 0xAA){
284                         p += p[2]*512;
285                         continue;
286                 }
287
288                 p[0] = 0xCC;
289                 p[2*KB-1] = 0xCC;
290                 if(p[0] != 0xCC || p[2*KB-1] != 0xCC){
291                         p[0] = 0x55;
292                         p[1] = 0xAA;
293                         p[2] = 4;
294                         if(p[0] == 0x55 && p[1] == 0xAA){
295                                 p += p[2]*512;
296                                 continue;
297                         }
298                         if(p[0] == 0xFF && p[1] == 0xFF)
299                                 mapfree(&rmapumb, PADDR(p), 2*KB);
300                 }
301                 else
302                         mapfree(&rmapumbrw, PADDR(p), 2*KB);
303                 p += 2*KB;
304         }
305
306         p = KADDR(0xE0000);
307         if(p[0] != 0x55 || p[1] != 0xAA){
308                 p[0] = 0xCC;
309                 p[64*KB-1] = 0xCC;
310                 if(p[0] != 0xCC && p[64*KB-1] != 0xCC)
311                         mapfree(&rmapumb, PADDR(p), 64*KB);
312         }
313
314         umbexclude();
315 }
316
317 int
318 checksum(void *v, int n)
319 {
320         uchar *p, s;
321
322         s = 0;
323         p = v;
324         while(n-- > 0)
325                 s += *p++;
326         return s;
327 }
328
329 static void*
330 sigscan(uchar* addr, int len, char* signature)
331 {
332         int sl;
333         uchar *e, *p;
334
335         e = addr+len;
336         sl = strlen(signature);
337         for(p = addr; p+sl < e; p += 16)
338                 if(memcmp(p, signature, sl) == 0)
339                         return p;
340         return nil;
341 }
342
343 void*
344 sigsearch(char* signature)
345 {
346         uintptr p;
347         uchar *bda;
348         void *r;
349
350         /*
351          * Search for the data structure:
352          * 1) within the first KiB of the Extended BIOS Data Area (EBDA), or
353          * 2) within the last KiB of system base memory if the EBDA segment
354          *    is undefined, or
355          * 3) within the BIOS ROM address space between 0xf0000 and 0xfffff
356          *    (but will actually check 0xe0000 to 0xfffff).
357          */
358         bda = KADDR(0x400);
359         if(memcmp(KADDR(0xfffd9), "EISA", 4) == 0){
360                 if((p = (bda[0x0f]<<8)|bda[0x0e]) != 0){
361                         if((r = sigscan(KADDR(p<<4), 1024, signature)) != nil)
362                                 return r;
363                 }
364         }
365
366         if((p = ((bda[0x14]<<8)|bda[0x13])*1024) != 0){
367                 if((r = sigscan(KADDR(p-1024), 1024, signature)) != nil)
368                         return r;
369         }
370         /* hack for virtualbox: look in KiB below 0xa0000 */
371         if((r = sigscan(KADDR(0xa0000-1024), 1024, signature)) != nil)
372                 return r;
373
374         return sigscan(KADDR(0xe0000), 0x20000, signature);
375 }
376
377 static void
378 lowraminit(void)
379 {
380         ulong pa, x;
381         uchar *bda;
382
383         /*
384          * Initialise the memory bank information for conventional memory
385          * (i.e. less than 640KB). The base is the first location after the
386          * bootstrap processor MMU information and the limit is obtained from
387          * the BIOS data area.
388          */
389         x = PADDR(CPU0END);
390         bda = (uchar*)KADDR(0x400);
391         pa = ((bda[0x14]<<8)|bda[0x13])*KB;
392         if(pa > 640*KB)
393                 pa = 640*KB;
394         if(x < pa){
395                 mapfree(&rmapram, x, pa-x);
396                 memset(KADDR(x), 0, pa-x);              /* keep us honest */
397         }
398
399         x = PADDR(PGROUND((ulong)end));
400         pa = MemMin;
401         if(x > pa)
402                 panic("kernel too big");
403         mapfree(&rmapram, x, pa-x);
404         memset(KADDR(x), 0, pa-x);              /* keep us honest */
405 }
406
407 static void
408 ramscan(ulong maxmem)
409 {
410         ulong *k0, kzero, map, maxkpa, maxpa, pa, *pte, *table, *va, vbase, x;
411         int nvalid[NMemType];
412
413         /*
414          * The bootstrap code has has created a prototype page
415          * table which maps the first MemMin of physical memory to KZERO.
416          * The page directory is at m->pdb and the first page of
417          * free memory is after the per-processor MMU information.
418          */
419         pa = MemMin;
420
421         /*
422          * Check if the extended memory size can be obtained from the CMOS.
423          * If it's 0 then it's either not known or >= 64MB. Always check
424          * at least 24MB in case there's a memory gap (up to 8MB) below 16MB;
425          * in this case the memory from the gap is remapped to the top of
426          * memory.
427          * The value in CMOS is supposed to be the number of KB above 1MB.
428          */
429         if(maxmem == 0){
430                 x = (nvramread(0x18)<<8)|nvramread(0x17);
431                 if(x == 0 || x >= (63*KB))
432                         maxpa = MemMax;
433                 else
434                         maxpa = MB+x*KB;
435                 if(maxpa < 24*MB)
436                         maxpa = 24*MB;
437         }else
438                 maxpa = maxmem;
439         maxkpa = (u32int)-KZERO;        /* 2^32 - KZERO */
440
441         /*
442          * March up memory from MemMin to maxpa 1MB at a time,
443          * mapping the first page and checking the page can
444          * be written and read correctly. The page tables are created here
445          * on the fly, allocating from low memory as necessary.
446          */
447         k0 = (ulong*)KADDR(0);
448         kzero = *k0;
449         map = 0;
450         x = 0x12345678;
451         memset(nvalid, 0, sizeof(nvalid));
452         
453         /*
454          * Can't map memory to KADDR(pa) when we're walking because
455          * can only use KADDR for relatively low addresses.
456          * Instead, map each 4MB we scan to the virtual address range
457          * MemMin->MemMin+4MB while we are scanning.
458          */
459         vbase = MemMin;
460         while(pa < maxpa){
461                 /*
462                  * Map the page. Use mapalloc(&rmapram, ...) to make
463                  * the page table if necessary, it will be returned to the
464                  * pool later if it isn't needed.  Map in a fixed range (the second 4M)
465                  * because high physical addresses cannot be passed to KADDR.
466                  */
467                 va = (void*)(vbase + pa%(4*MB));
468                 table = &m->pdb[PDX(va)];
469                 if(pa%(4*MB) == 0){
470                         if(map == 0 && (map = mapalloc(&rmapram, 0, BY2PG, BY2PG)) == 0)
471                                 break;
472                         memset(KADDR(map), 0, BY2PG);
473                         *table = map|PTEWRITE|PTEVALID;
474                         memset(nvalid, 0, sizeof(nvalid));
475                 }
476                 table = KADDR(PPN(*table));
477                 pte = &table[PTX(va)];
478
479                 *pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID;
480                 mmuflushtlb(PADDR(m->pdb));
481                 /*
482                  * Write a pattern to the page and write a different
483                  * pattern to a possible mirror at KZERO. If the data
484                  * reads back correctly the chunk is some type of RAM (possibly
485                  * a linearly-mapped VGA framebuffer, for instance...) and
486                  * can be cleared and added to the memory pool. If not, the
487                  * chunk is marked uncached and added to the UMB pool if <16MB
488                  * or is marked invalid and added to the UPA pool.
489                  */
490                 *va = x;
491                 *k0 = ~x;
492                 if(*va == x){
493                         nvalid[MemRAM] += MB/BY2PG;
494                         mapfree(&rmapram, pa, MB);
495
496                         do{
497                                 *pte++ = pa|PTEWRITE|PTEVALID;
498                                 pa += BY2PG;
499                         }while(pa % MB);
500                         mmuflushtlb(PADDR(m->pdb));
501                         /* memset(va, 0, MB); so damn slow to memset all of memory */
502                 }
503                 else if(pa < 16*MB){
504                         nvalid[MemUMB] += MB/BY2PG;
505                         mapfree(&rmapumb, pa, MB);
506
507                         do{
508                                 *pte++ = pa|PTEWRITE|PTEUNCACHED|PTEVALID;
509                                 pa += BY2PG;
510                         }while(pa % MB);
511                 }
512                 else{
513                         nvalid[MemUPA] += MB/BY2PG;
514                         mapfree(&rmapupa, pa, MB);
515
516                         *pte = 0;
517                         pa += MB;
518                 }
519                 /*
520                  * Done with this 4MB chunk, review the options:
521                  * 1) not physical memory and >=16MB - invalidate the PDB entry;
522                  * 2) physical memory - use the 4MB page extension if possible;
523                  * 3) not physical memory and <16MB - use the 4MB page extension
524                  *    if possible;
525                  * 4) mixed or no 4MB page extension - commit the already
526                  *    initialised space for the page table.
527                  */
528                 if(pa%(4*MB) == 0 && pa >= 32*MB && nvalid[MemUPA] == (4*MB)/BY2PG){
529                         /*
530                          * If we encounter a 4MB chunk of missing memory
531                          * at a sufficiently high offset, call it the end of
532                          * memory.  Otherwise we run the risk of thinking
533                          * that video memory is real RAM.
534                          */
535                         break;
536                 }
537                 if(pa <= maxkpa && pa%(4*MB) == 0){
538                         table = &m->pdb[PDX(KADDR(pa - 4*MB))];
539                         if(nvalid[MemUPA] == (4*MB)/BY2PG)
540                                 *table = 0;
541                         else if(nvalid[MemRAM] == (4*MB)/BY2PG && (m->cpuiddx & Pse))
542                                 *table = (pa - 4*MB)|PTESIZE|PTEWRITE|PTEVALID;
543                         else if(nvalid[MemUMB] == (4*MB)/BY2PG && (m->cpuiddx & Pse))
544                                 *table = (pa - 4*MB)|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID;
545                         else{
546                                 *table = map|PTEWRITE|PTEVALID;
547                                 map = 0;
548                         }
549                 }
550                 mmuflushtlb(PADDR(m->pdb));
551                 x += 0x3141526;
552         }
553         /*
554          * If we didn't reach the end of the 4MB chunk, that part won't
555          * be mapped.  Commit the already initialised space for the page table.
556          */
557         if(pa % (4*MB) && pa <= maxkpa){
558                 m->pdb[PDX(KADDR(pa))] = map|PTEWRITE|PTEVALID;
559                 map = 0;
560         }
561         if(map)
562                 mapfree(&rmapram, map, BY2PG);
563
564         m->pdb[PDX(vbase)] = 0;
565         mmuflushtlb(PADDR(m->pdb));
566
567         mapfree(&rmapupa, pa, (u32int)-pa);
568         *k0 = kzero;
569 }
570
571 typedef struct Emap Emap;
572 struct Emap
573 {
574         int type;
575         uvlong base;
576         uvlong top;
577 };
578 static Emap emap[128];
579 int nemap;
580
581 static int
582 emapcmp(const void *va, const void *vb)
583 {
584         Emap *a, *b;
585         
586         a = (Emap*)va;
587         b = (Emap*)vb;
588         if(a->top < b->top)
589                 return -1;
590         if(a->top > b->top)
591                 return 1;
592         if(a->base < b->base)
593                 return -1;
594         if(a->base > b->base)
595                 return 1;
596         return 0;
597 }
598
599 static void
600 map(ulong base, ulong len, int type)
601 {
602         ulong e, n;
603         ulong *table, flags, maxkpa;
604
605         /*
606          * Split any call crossing MemMin to make below simpler.
607          */
608         if(base < MemMin && len > MemMin-base){
609                 n = MemMin - base;
610                 map(base, n, type);
611                 map(MemMin, len-n, type);
612         }
613         
614         /*
615          * Let lowraminit and umbscan hash out the low MemMin.
616          */
617         if(base < MemMin)
618                 return;
619
620         /*
621          * Any non-memory below 16*MB is used as upper mem blocks.
622          */
623         if(type == MemUPA && base < 16*MB && len > 16*MB-base){
624                 map(base, 16*MB-base, MemUMB);
625                 map(16*MB, len-(16*MB-base), MemUPA);
626                 return;
627         }
628         
629         /*
630          * Memory below CPU0END is reserved for the kernel
631          * and already mapped.
632          */
633         if(base < PADDR(CPU0END)){
634                 n = PADDR(CPU0END) - base;
635                 if(len <= n)
636                         return;
637                 map(PADDR(CPU0END), len-n, type);
638                 return;
639         }
640         
641         /*
642          * Memory between KTZERO and end is the kernel itself
643          * and is already mapped.
644          */
645         if(base < PADDR(KTZERO) && len > PADDR(KTZERO)-base){
646                 map(base, PADDR(KTZERO)-base, type);
647                 return;
648         }
649         if(PADDR(KTZERO) < base && base < PADDR(PGROUND((ulong)end))){
650                 n = PADDR(PGROUND((ulong)end));
651                 if(len <= n)
652                         return;
653                 map(PADDR(PGROUND((ulong)end)), len-n, type);
654                 return;
655         }
656         
657         /*
658          * Now we have a simple case.
659          */
660         // print("map %.8lux %.8lux %d\n", base, base+len, type);
661         switch(type){
662         case MemRAM:
663                 mapfree(&rmapram, base, len);
664                 flags = PTEWRITE|PTEVALID;
665                 break;
666         case MemUMB:
667                 mapfree(&rmapumb, base, len);
668                 flags = PTEWRITE|PTEUNCACHED|PTEVALID;
669                 break;
670         case MemUPA:
671                 mapfree(&rmapupa, base, len);
672                 flags = 0;
673                 break;
674         default:
675         case MemReserved:
676                 flags = 0;
677                 break;
678         }
679         
680         /*
681          * bottom MemMin is already mapped - just twiddle flags.
682          * (not currently used - see above)
683          */
684         if(base < MemMin){
685                 table = KADDR(PPN(m->pdb[PDX(base)]));
686                 e = base+len;
687                 base = PPN(base);
688                 for(; base<e; base+=BY2PG)
689                         table[PTX(base)] |= flags;
690                 return;
691         }
692         
693         /*
694          * Only map from KZERO to 2^32.
695          */
696         if(flags){
697                 maxkpa = -KZERO;
698                 if(base >= maxkpa)
699                         return;
700                 if(len > maxkpa-base)
701                         len = maxkpa - base;
702                 pdbmap(m->pdb, base|flags, base+KZERO, len);
703         }
704 }
705
706 static int
707 e820scan(void)
708 {
709         ulong base, len, last;
710         Emap *e;
711         char *s;
712         int i;
713
714         /* passed by bootloader */
715         if((s = getconf("*e820")) == nil)
716                 if((s = getconf("e820")) == nil)
717                         return -1;
718         nemap = 0;
719         while(nemap < nelem(emap)){
720                 while(*s == ' ')
721                         s++;
722                 if(*s == 0)
723                         break;
724                 e = emap + nemap;
725                 e->type = 1;
726                 if(s[1] == ' '){        /* new format */
727                         e->type = s[0] - '0';
728                         s += 2;
729                 }
730                 e->base = strtoull(s, &s, 16);
731                 if(*s != ' ')
732                         break;
733                 e->top  = strtoull(s, &s, 16);
734                 if(*s != ' ' && *s != 0)
735                         break;
736                 if(e->base < e->top)
737                         nemap++;
738         }
739         if(nemap == 0)
740                 return -1;
741         qsort(emap, nemap, sizeof emap[0], emapcmp);
742         last = 0;
743         for(i=0; i<nemap; i++){ 
744                 e = &emap[i];
745                 /*
746                  * pull out the info but only about the low 32 bits...
747                  */
748                 if(e->base >= (1ULL<<32))
749                         break;
750                 if(e->top <= last)
751                         continue;
752                 if(e->base < last)
753                         base = last;
754                 else
755                         base = e->base;
756                 if(e->top > (1ULL<<32))
757                         len = -base;
758                 else
759                         len = e->top - base;
760                 /*
761                  * If the map skips addresses, mark them available.
762                  */
763                 if(last < base)
764                         map(last, base-last, MemUPA);
765                 map(base, len, (e->type == 1) ? MemRAM : MemReserved);
766                 last = base + len;
767                 if(last == 0)
768                         break;
769         }
770         if(last != 0)
771                 map(last, -last, MemUPA);
772         return 0;
773 }
774
775 void
776 meminit(void)
777 {
778         int i;
779         Map *mp;
780         Confmem *cm;
781         ulong pa, *pte;
782         ulong maxmem, lost;
783         char *p;
784
785         if(p = getconf("*maxmem"))
786                 maxmem = strtoul(p, 0, 0);
787         else
788                 maxmem = 0;
789
790         /*
791          * Set special attributes for memory between 640KB and 1MB:
792          *   VGA memory is writethrough;
793          *   BIOS ROM's/UMB's are uncached;
794          * then scan for useful memory.
795          */
796         for(pa = 0xA0000; pa < 0xC0000; pa += BY2PG){
797                 pte = mmuwalk(m->pdb, (ulong)KADDR(pa), 2, 0);
798                 *pte |= PTEWT;
799         }
800         for(pa = 0xC0000; pa < 0x100000; pa += BY2PG){
801                 pte = mmuwalk(m->pdb, (ulong)KADDR(pa), 2, 0);
802                 *pte |= PTEUNCACHED;
803         }
804         mmuflushtlb(PADDR(m->pdb));
805
806         umbscan();
807         lowraminit();
808         if(e820scan() < 0)
809                 ramscan(maxmem);
810
811         /*
812          * Set the conf entries describing banks of allocatable memory.
813          */
814         for(i=0; i<nelem(mapram) && i<nelem(conf.mem); i++){
815                 mp = &rmapram.map[i];
816                 cm = &conf.mem[i];
817                 cm->base = mp->addr;
818                 cm->npage = mp->size/BY2PG;
819         }
820         
821         lost = 0;
822         for(; i<nelem(mapram); i++)
823                 lost += rmapram.map[i].size;
824         if(lost)
825                 print("meminit - lost %lud bytes\n", lost);
826
827         if(MEMDEBUG)
828                 memdebug();
829 }
830
831 /*
832  * Allocate memory from the upper memory blocks.
833  */
834 ulong
835 umbmalloc(ulong addr, int size, int align)
836 {
837         ulong a;
838
839         if(a = mapalloc(&rmapumb, addr, size, align))
840                 return (ulong)KADDR(a);
841
842         return 0;
843 }
844
845 void
846 umbfree(ulong addr, int size)
847 {
848         mapfree(&rmapumb, PADDR(addr), size);
849 }
850
851 ulong
852 umbrwmalloc(ulong addr, int size, int align)
853 {
854         ulong a;
855         uchar *p;
856
857         if(a = mapalloc(&rmapumbrw, addr, size, align))
858                 return(ulong)KADDR(a);
859
860         /*
861          * Perhaps the memory wasn't visible before
862          * the interface is initialised, so try again.
863          */
864         if((a = umbmalloc(addr, size, align)) == 0)
865                 return 0;
866         p = (uchar*)a;
867         p[0] = 0xCC;
868         p[size-1] = 0xCC;
869         if(p[0] == 0xCC && p[size-1] == 0xCC)
870                 return a;
871         umbfree(a, size);
872
873         return 0;
874 }
875
876 void
877 umbrwfree(ulong addr, int size)
878 {
879         mapfree(&rmapumbrw, PADDR(addr), size);
880 }
881
882 /*
883  * Give out otherwise-unused physical address space
884  * for use in configuring devices.  Note that upaalloc
885  * does not map the physical address into virtual memory.
886  * Call vmap to do that.
887  */
888 ulong
889 upaalloc(int size, int align)
890 {
891         ulong a;
892
893         a = mapalloc(&rmapupa, 0, size, align);
894         if(a == 0){
895                 print("out of physical address space allocating %d\n", size);
896                 mapprint(&rmapupa);
897         }
898         return a;
899 }
900
901 void
902 upafree(ulong pa, int size)
903 {
904         mapfree(&rmapupa, pa, size);
905 }
906
907 void
908 upareserve(ulong pa, int size)
909 {
910         ulong a;
911         
912         a = mapalloc(&rmapupa, pa, size, 0);
913         if(a != pa){
914                 /*
915                  * This can happen when we're using the E820
916                  * map, which might have already reserved some
917                  * of the regions claimed by the pci devices.
918                  */
919         //      print("upareserve: cannot reserve pa=%#.8lux size=%d\n", pa, size);
920                 if(a != 0)
921                         mapfree(&rmapupa, a, size);
922         }
923 }
924
925 void
926 memorysummary(void)
927 {
928         memdebug();
929 }
930