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