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