]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/memory.c
pc, pc64: more conservative pcirouting
[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 static uintptr
344 convmemsize(void)
345 {
346         uintptr top;
347         uchar *bda;
348
349         bda = KADDR(0x400);
350         top = ((bda[0x14]<<8) | bda[0x13])*KB;
351
352         if(top < 64*KB || top > 640*KB)
353                 top = 640*KB;   /* sanity */
354
355         /* reserved for bios tables (EBDA) */
356         top -= 1*KB;
357
358         return top;
359 }
360
361 void*
362 sigsearch(char* signature)
363 {
364         uintptr p;
365         uchar *bda;
366         void *r;
367
368         /*
369          * Search for the data structure:
370          * 1) within the first KiB of the Extended BIOS Data Area (EBDA), or
371          * 2) within the last KiB of system base memory if the EBDA segment
372          *    is undefined, or
373          * 3) within the BIOS ROM address space between 0xf0000 and 0xfffff
374          *    (but will actually check 0xe0000 to 0xfffff).
375          */
376         bda = KADDR(0x400);
377         if(memcmp(KADDR(0xfffd9), "EISA", 4) == 0){
378                 if((p = (bda[0x0f]<<8)|bda[0x0e]) != 0){
379                         if((r = sigscan(KADDR(p<<4), 1024, signature)) != nil)
380                                 return r;
381                 }
382         }
383         if((r = sigscan(KADDR(convmemsize()), 1024, signature)) != nil)
384                 return r;
385
386         /* hack for virtualbox: look in KiB below 0xa0000 */
387         if((r = sigscan(KADDR(0xa0000-1024), 1024, signature)) != nil)
388                 return r;
389
390         return sigscan(KADDR(0xe0000), 0x20000, signature);
391 }
392
393 static void
394 lowraminit(void)
395 {
396         uintptr pa, x;
397
398         /*
399          * Initialise the memory bank information for conventional memory
400          * (i.e. less than 640KB). The base is the first location after the
401          * bootstrap processor MMU information and the limit is obtained from
402          * the BIOS data area.
403          */
404         x = PADDR(CPU0END);
405         pa = convmemsize();
406         if(x < pa){
407                 mapfree(&rmapram, x, pa-x);
408                 memset(KADDR(x), 0, pa-x);              /* keep us honest */
409         }
410
411         x = PADDR(PGROUND((uintptr)end));
412         pa = MemMin;
413         if(x > pa)
414                 panic("kernel too big");
415         mapfree(&rmapram, x, pa-x);
416         memset(KADDR(x), 0, pa-x);              /* keep us honest */
417 }
418
419 static void
420 ramscan(ulong maxmem)
421 {
422         ulong *k0, kzero, map, maxkpa, maxpa, pa, *pte, *table, *va, vbase, x;
423         int nvalid[NMemType];
424
425         /*
426          * The bootstrap code has has created a prototype page
427          * table which maps the first MemMin of physical memory to KZERO.
428          * The page directory is at m->pdb and the first page of
429          * free memory is after the per-processor MMU information.
430          */
431         pa = MemMin;
432
433         /*
434          * Check if the extended memory size can be obtained from the CMOS.
435          * If it's 0 then it's either not known or >= 64MB. Always check
436          * at least 24MB in case there's a memory gap (up to 8MB) below 16MB;
437          * in this case the memory from the gap is remapped to the top of
438          * memory.
439          * The value in CMOS is supposed to be the number of KB above 1MB.
440          */
441         if(maxmem == 0){
442                 x = (nvramread(0x18)<<8)|nvramread(0x17);
443                 if(x == 0 || x >= (63*KB))
444                         maxpa = MemMax;
445                 else
446                         maxpa = MB+x*KB;
447                 if(maxpa < 24*MB)
448                         maxpa = 24*MB;
449         }else
450                 maxpa = maxmem;
451         maxkpa = (u32int)-KZERO;        /* 2^32 - KZERO */
452
453         /*
454          * March up memory from MemMin to maxpa 1MB at a time,
455          * mapping the first page and checking the page can
456          * be written and read correctly. The page tables are created here
457          * on the fly, allocating from low memory as necessary.
458          */
459         k0 = (ulong*)KADDR(0);
460         kzero = *k0;
461         map = 0;
462         x = 0x12345678;
463         memset(nvalid, 0, sizeof(nvalid));
464         
465         /*
466          * Can't map memory to KADDR(pa) when we're walking because
467          * can only use KADDR for relatively low addresses.
468          * Instead, map each 4MB we scan to the virtual address range
469          * MemMin->MemMin+4MB while we are scanning.
470          */
471         vbase = MemMin;
472         while(pa < maxpa){
473                 /*
474                  * Map the page. Use mapalloc(&rmapram, ...) to make
475                  * the page table if necessary, it will be returned to the
476                  * pool later if it isn't needed.  Map in a fixed range (the second 4M)
477                  * because high physical addresses cannot be passed to KADDR.
478                  */
479                 va = (void*)(vbase + pa%(4*MB));
480                 table = &m->pdb[PDX(va)];
481                 if(pa%(4*MB) == 0){
482                         if(map == 0 && (map = mapalloc(&rmapram, 0, BY2PG, BY2PG)) == 0)
483                                 break;
484                         memset(KADDR(map), 0, BY2PG);
485                         *table = map|PTEWRITE|PTEVALID;
486                         memset(nvalid, 0, sizeof(nvalid));
487                 }
488                 table = KADDR(PPN(*table));
489                 pte = &table[PTX(va)];
490
491                 *pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID;
492                 mmuflushtlb(PADDR(m->pdb));
493                 /*
494                  * Write a pattern to the page and write a different
495                  * pattern to a possible mirror at KZERO. If the data
496                  * reads back correctly the chunk is some type of RAM (possibly
497                  * a linearly-mapped VGA framebuffer, for instance...) and
498                  * can be cleared and added to the memory pool. If not, the
499                  * chunk is marked uncached and added to the UMB pool if <16MB
500                  * or is marked invalid and added to the UPA pool.
501                  */
502                 *va = x;
503                 *k0 = ~x;
504                 if(*va == x){
505                         nvalid[MemRAM] += MB/BY2PG;
506                         mapfree(&rmapram, pa, MB);
507
508                         do{
509                                 *pte++ = pa|PTEWRITE|PTEVALID;
510                                 pa += BY2PG;
511                         }while(pa % MB);
512                         mmuflushtlb(PADDR(m->pdb));
513                         /* memset(va, 0, MB); so damn slow to memset all of memory */
514                 }
515                 else if(pa < 16*MB){
516                         nvalid[MemUMB] += MB/BY2PG;
517                         mapfree(&rmapumb, pa, MB);
518
519                         do{
520                                 *pte++ = pa|PTEWRITE|PTEUNCACHED|PTEVALID;
521                                 pa += BY2PG;
522                         }while(pa % MB);
523                 }
524                 else{
525                         nvalid[MemUPA] += MB/BY2PG;
526                         mapfree(&rmapupa, pa, MB);
527
528                         *pte = 0;
529                         pa += MB;
530                 }
531                 /*
532                  * Done with this 4MB chunk, review the options:
533                  * 1) not physical memory and >=16MB - invalidate the PDB entry;
534                  * 2) physical memory - use the 4MB page extension if possible;
535                  * 3) not physical memory and <16MB - use the 4MB page extension
536                  *    if possible;
537                  * 4) mixed or no 4MB page extension - commit the already
538                  *    initialised space for the page table.
539                  */
540                 if(pa%(4*MB) == 0 && pa >= 32*MB && nvalid[MemUPA] == (4*MB)/BY2PG){
541                         /*
542                          * If we encounter a 4MB chunk of missing memory
543                          * at a sufficiently high offset, call it the end of
544                          * memory.  Otherwise we run the risk of thinking
545                          * that video memory is real RAM.
546                          */
547                         break;
548                 }
549                 if(pa <= maxkpa && pa%(4*MB) == 0){
550                         table = &m->pdb[PDX(KADDR(pa - 4*MB))];
551                         if(nvalid[MemUPA] == (4*MB)/BY2PG)
552                                 *table = 0;
553                         else if(nvalid[MemRAM] == (4*MB)/BY2PG && (m->cpuiddx & Pse))
554                                 *table = (pa - 4*MB)|PTESIZE|PTEWRITE|PTEVALID;
555                         else if(nvalid[MemUMB] == (4*MB)/BY2PG && (m->cpuiddx & Pse))
556                                 *table = (pa - 4*MB)|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID;
557                         else{
558                                 *table = map|PTEWRITE|PTEVALID;
559                                 map = 0;
560                         }
561                 }
562                 mmuflushtlb(PADDR(m->pdb));
563                 x += 0x3141526;
564         }
565         /*
566          * If we didn't reach the end of the 4MB chunk, that part won't
567          * be mapped.  Commit the already initialised space for the page table.
568          */
569         if(pa % (4*MB) && pa <= maxkpa){
570                 m->pdb[PDX(KADDR(pa))] = map|PTEWRITE|PTEVALID;
571                 map = 0;
572         }
573         if(map)
574                 mapfree(&rmapram, map, BY2PG);
575
576         m->pdb[PDX(vbase)] = 0;
577         mmuflushtlb(PADDR(m->pdb));
578
579         mapfree(&rmapupa, pa, (u32int)-pa);
580         *k0 = kzero;
581 }
582
583 typedef struct Emap Emap;
584 struct Emap
585 {
586         int type;
587         uvlong base;
588         uvlong top;
589 };
590 static Emap emap[128];
591 int nemap;
592
593 static int
594 emapcmp(const void *va, const void *vb)
595 {
596         Emap *a, *b;
597         
598         a = (Emap*)va;
599         b = (Emap*)vb;
600         if(a->top < b->top)
601                 return -1;
602         if(a->top > b->top)
603                 return 1;
604         if(a->base < b->base)
605                 return -1;
606         if(a->base > b->base)
607                 return 1;
608         return 0;
609 }
610
611 static void
612 map(ulong base, ulong len, int type)
613 {
614         ulong e, n;
615         ulong *table, flags, maxkpa;
616
617         /*
618          * Split any call crossing MemMin to make below simpler.
619          */
620         if(base < MemMin && len > MemMin-base){
621                 n = MemMin - base;
622                 map(base, n, type);
623                 map(MemMin, len-n, type);
624         }
625         
626         /*
627          * Let lowraminit and umbscan hash out the low MemMin.
628          */
629         if(base < MemMin)
630                 return;
631
632         /*
633          * Any non-memory below 16*MB is used as upper mem blocks.
634          */
635         if(type == MemUPA && base < 16*MB && len > 16*MB-base){
636                 map(base, 16*MB-base, MemUMB);
637                 map(16*MB, len-(16*MB-base), MemUPA);
638                 return;
639         }
640         
641         /*
642          * Memory below CPU0END is reserved for the kernel
643          * and already mapped.
644          */
645         if(base < PADDR(CPU0END)){
646                 n = PADDR(CPU0END) - base;
647                 if(len <= n)
648                         return;
649                 map(PADDR(CPU0END), len-n, type);
650                 return;
651         }
652         
653         /*
654          * Memory between KTZERO and end is the kernel itself
655          * and is already mapped.
656          */
657         if(base < PADDR(KTZERO) && len > PADDR(KTZERO)-base){
658                 map(base, PADDR(KTZERO)-base, type);
659                 return;
660         }
661         if(PADDR(KTZERO) < base && base < PADDR(PGROUND((ulong)end))){
662                 n = PADDR(PGROUND((ulong)end));
663                 if(len <= n)
664                         return;
665                 map(PADDR(PGROUND((ulong)end)), len-n, type);
666                 return;
667         }
668         
669         /*
670          * Now we have a simple case.
671          */
672         // print("map %.8lux %.8lux %d\n", base, base+len, type);
673         switch(type){
674         case MemRAM:
675                 mapfree(&rmapram, base, len);
676                 flags = PTEWRITE|PTEVALID;
677                 break;
678         case MemUMB:
679                 mapfree(&rmapumb, base, len);
680                 flags = PTEWRITE|PTEUNCACHED|PTEVALID;
681                 break;
682         case MemUPA:
683                 mapfree(&rmapupa, base, len);
684                 flags = 0;
685                 break;
686         default:
687         case MemReserved:
688                 flags = 0;
689                 break;
690         }
691         
692         /*
693          * bottom MemMin is already mapped - just twiddle flags.
694          * (not currently used - see above)
695          */
696         if(base < MemMin){
697                 table = KADDR(PPN(m->pdb[PDX(base)]));
698                 e = base+len;
699                 base = PPN(base);
700                 for(; base<e; base+=BY2PG)
701                         table[PTX(base)] |= flags;
702                 return;
703         }
704         
705         /*
706          * Only map from KZERO to 2^32.
707          */
708         if(flags){
709                 maxkpa = -KZERO;
710                 if(base >= maxkpa)
711                         return;
712                 if(len > maxkpa-base)
713                         len = maxkpa - base;
714                 pdbmap(m->pdb, base|flags, base+KZERO, len);
715         }
716 }
717
718 static int
719 e820scan(void)
720 {
721         ulong base, len, last;
722         Emap *e;
723         char *s;
724         int i;
725
726         /* passed by bootloader */
727         if((s = getconf("*e820")) == nil)
728                 if((s = getconf("e820")) == nil)
729                         return -1;
730         nemap = 0;
731         while(nemap < nelem(emap)){
732                 while(*s == ' ')
733                         s++;
734                 if(*s == 0)
735                         break;
736                 e = emap + nemap;
737                 e->type = 1;
738                 if(s[1] == ' '){        /* new format */
739                         e->type = s[0] - '0';
740                         s += 2;
741                 }
742                 e->base = strtoull(s, &s, 16);
743                 if(*s != ' ')
744                         break;
745                 e->top  = strtoull(s, &s, 16);
746                 if(*s != ' ' && *s != 0)
747                         break;
748                 if(e->base < e->top)
749                         nemap++;
750         }
751         if(nemap == 0)
752                 return -1;
753         qsort(emap, nemap, sizeof emap[0], emapcmp);
754         last = 0;
755         for(i=0; i<nemap; i++){ 
756                 e = &emap[i];
757                 /*
758                  * pull out the info but only about the low 32 bits...
759                  */
760                 if(e->base >= (1ULL<<32))
761                         break;
762                 if(e->top <= last)
763                         continue;
764                 if(e->base < last)
765                         base = last;
766                 else
767                         base = e->base;
768                 if(e->top > (1ULL<<32))
769                         len = -base;
770                 else
771                         len = e->top - base;
772                 /*
773                  * If the map skips addresses, mark them available.
774                  */
775                 if(last < base)
776                         map(last, base-last, MemUPA);
777                 map(base, len, (e->type == 1) ? MemRAM : MemReserved);
778                 last = base + len;
779                 if(last == 0)
780                         break;
781         }
782         if(last != 0)
783                 map(last, -last, MemUPA);
784         return 0;
785 }
786
787 void
788 meminit(void)
789 {
790         int i;
791         Map *mp;
792         Confmem *cm;
793         ulong pa, *pte;
794         ulong maxmem, lost;
795         char *p;
796
797         if(p = getconf("*maxmem"))
798                 maxmem = strtoul(p, 0, 0);
799         else
800                 maxmem = 0;
801
802         /*
803          * Set special attributes for memory between 640KB and 1MB:
804          *   VGA memory is writethrough;
805          *   BIOS ROM's/UMB's are uncached;
806          * then scan for useful memory.
807          */
808         for(pa = 0xA0000; pa < 0xC0000; pa += BY2PG){
809                 pte = mmuwalk(m->pdb, (ulong)KADDR(pa), 2, 0);
810                 *pte |= PTEWT;
811         }
812         for(pa = 0xC0000; pa < 0x100000; pa += BY2PG){
813                 pte = mmuwalk(m->pdb, (ulong)KADDR(pa), 2, 0);
814                 *pte |= PTEUNCACHED;
815         }
816         mmuflushtlb(PADDR(m->pdb));
817
818         umbscan();
819         lowraminit();
820         if(e820scan() < 0)
821                 ramscan(maxmem);
822
823         /*
824          * Set the conf entries describing banks of allocatable memory.
825          */
826         for(i=0; i<nelem(mapram) && i<nelem(conf.mem); i++){
827                 mp = &rmapram.map[i];
828                 cm = &conf.mem[i];
829                 cm->base = mp->addr;
830                 cm->npage = mp->size/BY2PG;
831         }
832         
833         lost = 0;
834         for(; i<nelem(mapram); i++)
835                 lost += rmapram.map[i].size;
836         if(lost)
837                 print("meminit - lost %lud bytes\n", lost);
838
839         if(MEMDEBUG)
840                 memdebug();
841 }
842
843 /*
844  * Allocate memory from the upper memory blocks.
845  */
846 ulong
847 umbmalloc(ulong addr, int size, int align)
848 {
849         ulong a;
850
851         if(a = mapalloc(&rmapumb, addr, size, align))
852                 return (ulong)KADDR(a);
853
854         return 0;
855 }
856
857 void
858 umbfree(ulong addr, int size)
859 {
860         mapfree(&rmapumb, PADDR(addr), size);
861 }
862
863 ulong
864 umbrwmalloc(ulong addr, int size, int align)
865 {
866         ulong a;
867         uchar *p;
868
869         if(a = mapalloc(&rmapumbrw, addr, size, align))
870                 return(ulong)KADDR(a);
871
872         /*
873          * Perhaps the memory wasn't visible before
874          * the interface is initialised, so try again.
875          */
876         if((a = umbmalloc(addr, size, align)) == 0)
877                 return 0;
878         p = (uchar*)a;
879         p[0] = 0xCC;
880         p[size-1] = 0xCC;
881         if(p[0] == 0xCC && p[size-1] == 0xCC)
882                 return a;
883         umbfree(a, size);
884
885         return 0;
886 }
887
888 void
889 umbrwfree(ulong addr, int size)
890 {
891         mapfree(&rmapumbrw, PADDR(addr), size);
892 }
893
894 /*
895  * Give out otherwise-unused physical address space
896  * for use in configuring devices.  Note that upaalloc
897  * does not map the physical address into virtual memory.
898  * Call vmap to do that.
899  */
900 ulong
901 upaalloc(int size, int align)
902 {
903         ulong a;
904
905         a = mapalloc(&rmapupa, 0, size, align);
906         if(a == 0){
907                 print("out of physical address space allocating %d\n", size);
908                 mapprint(&rmapupa);
909         }
910         return a;
911 }
912
913 void
914 upafree(ulong pa, int size)
915 {
916         mapfree(&rmapupa, pa, size);
917 }
918
919 void
920 upareserve(ulong pa, int size)
921 {
922         ulong a;
923         
924         a = mapalloc(&rmapupa, pa, size, 0);
925         if(a != pa){
926                 /*
927                  * This can happen when we're using the E820
928                  * map, which might have already reserved some
929                  * of the regions claimed by the pci devices.
930                  */
931         //      print("upareserve: cannot reserve pa=%#.8lux size=%d\n", pa, size);
932                 if(a != 0)
933                         mapfree(&rmapupa, a, size);
934         }
935 }
936
937 void
938 memorysummary(void)
939 {
940         memdebug();
941 }
942