xref: /plan9-contrib/sys/src/9k/k10/asm.c (revision 094d68186d4cdde21fdab9786d6c843a03693e4e)
19ef1f84bSDavid du Colombier /*
29ef1f84bSDavid du Colombier  * To do:
39ef1f84bSDavid du Colombier  *	find a purpose for this...
49ef1f84bSDavid du Colombier  */
59ef1f84bSDavid du Colombier #include "u.h"
69ef1f84bSDavid du Colombier #include "../port/lib.h"
79ef1f84bSDavid du Colombier #include "mem.h"
89ef1f84bSDavid du Colombier #include "dat.h"
99ef1f84bSDavid du Colombier #include "fns.h"
109ef1f84bSDavid du Colombier 
119ef1f84bSDavid du Colombier enum {
129ef1f84bSDavid du Colombier 	AsmNONE		= 0,
139ef1f84bSDavid du Colombier 	AsmMEMORY	= 1,
149ef1f84bSDavid du Colombier 	AsmRESERVED	= 2,
159ef1f84bSDavid du Colombier 	AsmACPIRECLAIM	= 3,
169ef1f84bSDavid du Colombier 	AsmACPINVS	= 4,
179ef1f84bSDavid du Colombier 
189ef1f84bSDavid du Colombier 	AsmDEV		= 5,
199ef1f84bSDavid du Colombier };
209ef1f84bSDavid du Colombier 
219ef1f84bSDavid du Colombier static Lock asmlock;
229ef1f84bSDavid du Colombier static Asm asmarray[64] = {
239ef1f84bSDavid du Colombier 	{ 0, ~0, AsmNONE, nil, },
249ef1f84bSDavid du Colombier };
259ef1f84bSDavid du Colombier static int asmindex = 1;
269ef1f84bSDavid du Colombier Asm* asmlist = &asmarray[0];
279ef1f84bSDavid du Colombier static Asm* asmfreelist;
289ef1f84bSDavid du Colombier static char* asmtypes[] = {
299ef1f84bSDavid du Colombier 	[AsmNONE]		"none",
309ef1f84bSDavid du Colombier 	[AsmMEMORY]		"mem",
319ef1f84bSDavid du Colombier 	[AsmRESERVED]		"res",
329ef1f84bSDavid du Colombier 	[AsmACPIRECLAIM]	"acpirecl",
339ef1f84bSDavid du Colombier 	[AsmACPINVS]		"acpinvs",
349ef1f84bSDavid du Colombier 	[AsmDEV]		"dev",
359ef1f84bSDavid du Colombier };
369ef1f84bSDavid du Colombier 
379ef1f84bSDavid du Colombier void
asmdump(void)389ef1f84bSDavid du Colombier asmdump(void)
399ef1f84bSDavid du Colombier {
409ef1f84bSDavid du Colombier 	Asm* asm;
419ef1f84bSDavid du Colombier 
429ef1f84bSDavid du Colombier 	print("asm: index %d:\n", asmindex);
439ef1f84bSDavid du Colombier 	for(asm = asmlist; asm != nil; asm = asm->next){
449ef1f84bSDavid du Colombier 		print(" %#P %#P %d (%P)\n",
459ef1f84bSDavid du Colombier 			asm->addr, asm->addr+asm->size,
469ef1f84bSDavid du Colombier 			asm->type, asm->size);
479ef1f84bSDavid du Colombier 	}
489ef1f84bSDavid du Colombier }
499ef1f84bSDavid du Colombier 
509ef1f84bSDavid du Colombier static Asm*
asmnew(uintmem addr,uintmem size,int type)519ef1f84bSDavid du Colombier asmnew(uintmem addr, uintmem size, int type)
529ef1f84bSDavid du Colombier {
539ef1f84bSDavid du Colombier 	Asm * asm;
549ef1f84bSDavid du Colombier 
559ef1f84bSDavid du Colombier 	if(asmfreelist != nil){
569ef1f84bSDavid du Colombier 		asm = asmfreelist;
579ef1f84bSDavid du Colombier 		asmfreelist = asm->next;
589ef1f84bSDavid du Colombier 		asm->next = nil;
599ef1f84bSDavid du Colombier 	}
609ef1f84bSDavid du Colombier 	else{
619ef1f84bSDavid du Colombier 		if(asmindex >= nelem(asmarray))
629ef1f84bSDavid du Colombier 			return nil;
639ef1f84bSDavid du Colombier 		asm = &asmarray[asmindex++];
649ef1f84bSDavid du Colombier 	}
659ef1f84bSDavid du Colombier 	asm->addr = addr;
669ef1f84bSDavid du Colombier 	asm->size = size;
679ef1f84bSDavid du Colombier 	asm->type = type;
689ef1f84bSDavid du Colombier 
699ef1f84bSDavid du Colombier 	return asm;
709ef1f84bSDavid du Colombier }
719ef1f84bSDavid du Colombier 
729ef1f84bSDavid du Colombier int
asmfree(uintmem addr,uintmem size,int type)739ef1f84bSDavid du Colombier asmfree(uintmem addr, uintmem size, int type)
749ef1f84bSDavid du Colombier {
759ef1f84bSDavid du Colombier 	Asm *np, *pp, **ppp;
769ef1f84bSDavid du Colombier 
779ef1f84bSDavid du Colombier 	DBG("asmfree: %#P@%#P, type %d\n", size, addr, type);
789ef1f84bSDavid du Colombier 	if(size == 0)
799ef1f84bSDavid du Colombier 		return 0;
809ef1f84bSDavid du Colombier 
819ef1f84bSDavid du Colombier 	lock(&asmlock);
829ef1f84bSDavid du Colombier 
839ef1f84bSDavid du Colombier 	/*
849ef1f84bSDavid du Colombier 	 * Find either a map entry with an address greater
859ef1f84bSDavid du Colombier 	 * than that being returned, or the end of the map.
869ef1f84bSDavid du Colombier 	 */
879ef1f84bSDavid du Colombier 	pp = nil;
889ef1f84bSDavid du Colombier 	ppp = &asmlist;
899ef1f84bSDavid du Colombier 	for(np = *ppp; np != nil && np->addr <= addr; np = np->next){
909ef1f84bSDavid du Colombier 		pp = np;
919ef1f84bSDavid du Colombier 		ppp = &np->next;
929ef1f84bSDavid du Colombier 	}
939ef1f84bSDavid du Colombier 
949ef1f84bSDavid du Colombier 	if((pp != nil && pp->addr+pp->size > addr)
959ef1f84bSDavid du Colombier 	|| (np != nil && addr+size > np->addr)){
969ef1f84bSDavid du Colombier 		unlock(&asmlock);
979ef1f84bSDavid du Colombier 		DBG("asmfree: overlap %#P@%#P, type %d\n", size, addr, type);
989ef1f84bSDavid du Colombier 		return -1;
999ef1f84bSDavid du Colombier 	}
1009ef1f84bSDavid du Colombier 
1019ef1f84bSDavid du Colombier 	if(pp != nil && pp->type == type && pp->addr+pp->size == addr){
1029ef1f84bSDavid du Colombier 		pp->size += size;
1039ef1f84bSDavid du Colombier 		if(np != nil && np->type == type && addr+size == np->addr){
1049ef1f84bSDavid du Colombier 			pp->size += np->size;
1059ef1f84bSDavid du Colombier 			pp->next = np->next;
1069ef1f84bSDavid du Colombier 
1079ef1f84bSDavid du Colombier 			np->next = asmfreelist;
1089ef1f84bSDavid du Colombier 			asmfreelist = np;
1099ef1f84bSDavid du Colombier 		}
1109ef1f84bSDavid du Colombier 
1119ef1f84bSDavid du Colombier 		unlock(&asmlock);
1129ef1f84bSDavid du Colombier 		return 0;
1139ef1f84bSDavid du Colombier 	}
1149ef1f84bSDavid du Colombier 
1159ef1f84bSDavid du Colombier 	if(np != nil && np->type == type && addr+size == np->addr){
1169ef1f84bSDavid du Colombier 		np->addr -= size;
1179ef1f84bSDavid du Colombier 		np->size += size;
1189ef1f84bSDavid du Colombier 
1199ef1f84bSDavid du Colombier 		unlock(&asmlock);
1209ef1f84bSDavid du Colombier 		return 0;
1219ef1f84bSDavid du Colombier 	}
1229ef1f84bSDavid du Colombier 
1239ef1f84bSDavid du Colombier 	if((pp = asmnew(addr, size, type)) == nil){
1249ef1f84bSDavid du Colombier 		unlock(&asmlock);
1259ef1f84bSDavid du Colombier 		DBG("asmfree: losing %#P@%#P, type %d\n", size, addr, type);
1269ef1f84bSDavid du Colombier 		return -1;
1279ef1f84bSDavid du Colombier 	}
1289ef1f84bSDavid du Colombier 	*ppp = pp;
1299ef1f84bSDavid du Colombier 	pp->next = np;
1309ef1f84bSDavid du Colombier 
1319ef1f84bSDavid du Colombier 	unlock(&asmlock);
1329ef1f84bSDavid du Colombier 
1339ef1f84bSDavid du Colombier 	return 0;
1349ef1f84bSDavid du Colombier }
1359ef1f84bSDavid du Colombier 
1369ef1f84bSDavid du Colombier uintmem
asmalloc(uintmem addr,uintmem size,int type,int align)1379ef1f84bSDavid du Colombier asmalloc(uintmem addr, uintmem size, int type, int align)
1389ef1f84bSDavid du Colombier {
1399ef1f84bSDavid du Colombier 	uintmem a, o;
1409ef1f84bSDavid du Colombier 	Asm *asm, *pp;
1419ef1f84bSDavid du Colombier 
1429ef1f84bSDavid du Colombier 	DBG("asmalloc: %#P@%#P, type %d\n", size, addr, type);
1439ef1f84bSDavid du Colombier 	lock(&asmlock);
1449ef1f84bSDavid du Colombier 	for(pp = nil, asm = asmlist; asm != nil; pp = asm, asm = asm->next){
1459ef1f84bSDavid du Colombier 		if(asm->type != type)
1469ef1f84bSDavid du Colombier 			continue;
1479ef1f84bSDavid du Colombier 		a = asm->addr;
1489ef1f84bSDavid du Colombier 
1499ef1f84bSDavid du Colombier 		if(addr != 0){
1509ef1f84bSDavid du Colombier 			/*
1519ef1f84bSDavid du Colombier 			 * A specific address range has been given:
1529ef1f84bSDavid du Colombier 			 *   if the current map entry is greater then
1539ef1f84bSDavid du Colombier 			 *   the address is not in the map;
1549ef1f84bSDavid du Colombier 			 *   if the current map entry does not overlap
1559ef1f84bSDavid du Colombier 			 *   the beginning of the requested range then
1569ef1f84bSDavid du Colombier 			 *   continue on to the next map entry;
1579ef1f84bSDavid du Colombier 			 *   if the current map entry does not entirely
1589ef1f84bSDavid du Colombier 			 *   contain the requested range then the range
1599ef1f84bSDavid du Colombier 			 *   is not in the map.
1609ef1f84bSDavid du Colombier 			 * The comparisons are strange to prevent
1619ef1f84bSDavid du Colombier 			 * overflow.
1629ef1f84bSDavid du Colombier 			 */
1639ef1f84bSDavid du Colombier 			if(a > addr)
1649ef1f84bSDavid du Colombier 				break;
1659ef1f84bSDavid du Colombier 			if(asm->size < addr - a)
1669ef1f84bSDavid du Colombier 				continue;
1679ef1f84bSDavid du Colombier 			if(addr - a > asm->size - size)
1689ef1f84bSDavid du Colombier 				break;
1699ef1f84bSDavid du Colombier 			a = addr;
1709ef1f84bSDavid du Colombier 		}
1719ef1f84bSDavid du Colombier 
1729ef1f84bSDavid du Colombier 		if(align > 0)
1739ef1f84bSDavid du Colombier 			a = ((a+align-1)/align)*align;
1749ef1f84bSDavid du Colombier 		if(asm->addr+asm->size-a < size)
1759ef1f84bSDavid du Colombier 			continue;
1769ef1f84bSDavid du Colombier 
1779ef1f84bSDavid du Colombier 		o = asm->addr;
1789ef1f84bSDavid du Colombier 		asm->addr = a+size;
1799ef1f84bSDavid du Colombier 		asm->size -= a-o+size;
1809ef1f84bSDavid du Colombier 		if(asm->size == 0){
1819ef1f84bSDavid du Colombier 			if(pp != nil)
1829ef1f84bSDavid du Colombier 				pp->next = asm->next;
1839ef1f84bSDavid du Colombier 			asm->next = asmfreelist;
1849ef1f84bSDavid du Colombier 			asmfreelist = asm;
1859ef1f84bSDavid du Colombier 		}
1869ef1f84bSDavid du Colombier 
1879ef1f84bSDavid du Colombier 		unlock(&asmlock);
1889ef1f84bSDavid du Colombier 		if(o != a)
1899ef1f84bSDavid du Colombier 			asmfree(o, a-o, type);
1909ef1f84bSDavid du Colombier 		return a;
1919ef1f84bSDavid du Colombier 	}
1929ef1f84bSDavid du Colombier 	unlock(&asmlock);
1939ef1f84bSDavid du Colombier 
1949ef1f84bSDavid du Colombier 	return 0;
1959ef1f84bSDavid du Colombier }
1969ef1f84bSDavid du Colombier 
1979ef1f84bSDavid du Colombier static void
asminsert(uintmem addr,uintmem size,int type)1989ef1f84bSDavid du Colombier asminsert(uintmem addr, uintmem size, int type)
1999ef1f84bSDavid du Colombier {
2009ef1f84bSDavid du Colombier 	if(type == AsmNONE || asmalloc(addr, size, AsmNONE, 0) == 0)
2019ef1f84bSDavid du Colombier 		return;
2029ef1f84bSDavid du Colombier 	if(asmfree(addr, size, type) == 0)
2039ef1f84bSDavid du Colombier 		return;
2049ef1f84bSDavid du Colombier 	asmfree(addr, size, 0);
2059ef1f84bSDavid du Colombier }
2069ef1f84bSDavid du Colombier 
2079ef1f84bSDavid du Colombier void
asminit(void)2089ef1f84bSDavid du Colombier asminit(void)
2099ef1f84bSDavid du Colombier {
2109ef1f84bSDavid du Colombier 	sys->pmstart = ROUNDUP(PADDR(end), PGSZ);
2119ef1f84bSDavid du Colombier 	sys->pmend = sys->pmstart;
2129ef1f84bSDavid du Colombier 	asmalloc(0, sys->pmstart, AsmNONE, 0);
2139ef1f84bSDavid du Colombier }
2149ef1f84bSDavid du Colombier 
2159ef1f84bSDavid du Colombier /*
2169ef1f84bSDavid du Colombier  * Notes:
2179ef1f84bSDavid du Colombier  * asmmapinit and asmmodinit called from multiboot;
2189ef1f84bSDavid du Colombier  * subject to change; the numerology here is probably suspect.
2199ef1f84bSDavid du Colombier  * Multiboot defines the alignment of modules as 4096.
2209ef1f84bSDavid du Colombier  */
2219ef1f84bSDavid du Colombier void
asmmapinit(uintmem addr,uintmem size,int type)2229ef1f84bSDavid du Colombier asmmapinit(uintmem addr, uintmem size, int type)
2239ef1f84bSDavid du Colombier {
2249ef1f84bSDavid du Colombier 	DBG("asmmapinit %#P %#P %s\n", addr, size, asmtypes[type]);
2259ef1f84bSDavid du Colombier 
2269ef1f84bSDavid du Colombier 	switch(type){
2279ef1f84bSDavid du Colombier 	default:
2289ef1f84bSDavid du Colombier 		asminsert(addr, size, type);
2299ef1f84bSDavid du Colombier 		break;
2309ef1f84bSDavid du Colombier 	case AsmMEMORY:
2319ef1f84bSDavid du Colombier 		/*
2329ef1f84bSDavid du Colombier 		 * Adjust things for the peculiarities of this
2339ef1f84bSDavid du Colombier 		 * architecture.
2349ef1f84bSDavid du Colombier 		 * Sys->pmend is the largest physical memory address found,
2359ef1f84bSDavid du Colombier 		 * there may be gaps between it and sys->pmstart, the range
2369ef1f84bSDavid du Colombier 		 * and how much of it is occupied, might need to be known
2379ef1f84bSDavid du Colombier 		 * for setting up allocators later.
2389ef1f84bSDavid du Colombier 		 */
2399ef1f84bSDavid du Colombier 		if(addr < 1*MiB || addr+size < sys->pmstart)
2409ef1f84bSDavid du Colombier 			break;
2419ef1f84bSDavid du Colombier 		if(addr < sys->pmstart){
2429ef1f84bSDavid du Colombier 			size -= sys->pmstart - addr;
2439ef1f84bSDavid du Colombier 			addr = sys->pmstart;
2449ef1f84bSDavid du Colombier 		}
2459ef1f84bSDavid du Colombier 		asminsert(addr, size, type);
2469ef1f84bSDavid du Colombier 		sys->pmoccupied += size;
2479ef1f84bSDavid du Colombier 		if(addr+size > sys->pmend)
2489ef1f84bSDavid du Colombier 			sys->pmend = addr+size;
2499ef1f84bSDavid du Colombier 		break;
2509ef1f84bSDavid du Colombier 	}
2519ef1f84bSDavid du Colombier }
2529ef1f84bSDavid du Colombier 
2539ef1f84bSDavid du Colombier void
asmmodinit(u32int start,u32int end,char * s)2549ef1f84bSDavid du Colombier asmmodinit(u32int start, u32int end, char* s)
2559ef1f84bSDavid du Colombier {
2569ef1f84bSDavid du Colombier 	DBG("asmmodinit: %#ux -> %#ux: <%s> %#ux\n",
2579ef1f84bSDavid du Colombier 		start, end, s, ROUNDUP(end, 4096));
2589ef1f84bSDavid du Colombier 
2599ef1f84bSDavid du Colombier 	if(start < sys->pmstart)
2609ef1f84bSDavid du Colombier 		return;
2619ef1f84bSDavid du Colombier 	end = ROUNDUP(end, 4096);
2629ef1f84bSDavid du Colombier 	if(end > sys->pmstart){
2639ef1f84bSDavid du Colombier 		asmalloc(sys->pmstart, end-sys->pmstart, AsmNONE, 0);
2649ef1f84bSDavid du Colombier 		sys->pmstart = end;
2659ef1f84bSDavid du Colombier 	}
2669ef1f84bSDavid du Colombier }
2679ef1f84bSDavid du Colombier 
2689ef1f84bSDavid du Colombier static PTE
asmwalkalloc(usize size)2699ef1f84bSDavid du Colombier asmwalkalloc(usize size)
2709ef1f84bSDavid du Colombier {
2719ef1f84bSDavid du Colombier 	uintmem pa;
2729ef1f84bSDavid du Colombier 
2739ef1f84bSDavid du Colombier 	assert(size == PTSZ && sys->vmunused+size <= sys->vmunmapped);
2749ef1f84bSDavid du Colombier 
2759ef1f84bSDavid du Colombier 	if((pa = mmuphysaddr(sys->vmunused)) != ~0)
2769ef1f84bSDavid du Colombier 		sys->vmunused += size;
2779ef1f84bSDavid du Colombier 
2789ef1f84bSDavid du Colombier 	return pa;
2799ef1f84bSDavid du Colombier }
2809ef1f84bSDavid du Colombier 
2819ef1f84bSDavid du Colombier #include "amd64.h"
2829ef1f84bSDavid du Colombier 
2839ef1f84bSDavid du Colombier static int npg[4];
2849ef1f84bSDavid du Colombier 
2859ef1f84bSDavid du Colombier void
asmmeminit(void)2869ef1f84bSDavid du Colombier asmmeminit(void)
2879ef1f84bSDavid du Colombier {
2889ef1f84bSDavid du Colombier 	Asm* asm;
2899ef1f84bSDavid du Colombier 	PTE *pte;
290*094d6818SDavid du Colombier 	int i, l;
2919ef1f84bSDavid du Colombier 	uintptr n, va;
2929ef1f84bSDavid du Colombier 	uintmem hi, lo, mem, nextmem, pa;
2939ef1f84bSDavid du Colombier 
2949ef1f84bSDavid du Colombier 	/*
2959ef1f84bSDavid du Colombier 	 * to do here (done?):
2969ef1f84bSDavid du Colombier 	 *	map between vmunmapped and vmend to kzero;
2979ef1f84bSDavid du Colombier 	 *	(should the sys->vm* things be physical after all?)
2989ef1f84bSDavid du Colombier 	 *	adjust sys->vm things and asmalloc to compensate;
2999ef1f84bSDavid du Colombier 	 *	run through asmlist and map to kseg2.
3009ef1f84bSDavid du Colombier 	 * do we need a map, like vmap, for best use of mapping kmem?
3019ef1f84bSDavid du Colombier 	 * - in fact, a rewritten pdmap could do the job, no?
3029ef1f84bSDavid du Colombier 	 * have to assume up to vmend is contiguous.
3039ef1f84bSDavid du Colombier 	 * can't mmuphysaddr(sys->vmunmapped) because...
3049ef1f84bSDavid du Colombier 	 *
3059ef1f84bSDavid du Colombier 	 * Assume already 2MiB aligned; currently this is done in mmuinit.
3069ef1f84bSDavid du Colombier 	 */
3079ef1f84bSDavid du Colombier 	assert(m->pgszlg2[1] == 21);
3089ef1f84bSDavid du Colombier 	assert(!((sys->vmunmapped|sys->vmend) & m->pgszmask[1]));
3099ef1f84bSDavid du Colombier 
3109ef1f84bSDavid du Colombier 	if((pa = mmuphysaddr(sys->vmunused)) == ~0)
3119ef1f84bSDavid du Colombier 		panic("asmmeminit 1");
3129ef1f84bSDavid du Colombier 	pa += sys->vmunmapped - sys->vmunused;
3139ef1f84bSDavid du Colombier 	mem = asmalloc(pa, sys->vmend - sys->vmunmapped, AsmMEMORY, 0);
3149ef1f84bSDavid du Colombier 	if(mem != pa)
3159ef1f84bSDavid du Colombier 		panic("asmmeminit 2");
3169ef1f84bSDavid du Colombier 	DBG("asmmeminit: mem %#P\n", mem);
3179ef1f84bSDavid du Colombier 
3189ef1f84bSDavid du Colombier 	while(sys->vmunmapped < sys->vmend){
3199ef1f84bSDavid du Colombier 		l = mmuwalk(sys->vmunmapped, 1, &pte, asmwalkalloc);
3209ef1f84bSDavid du Colombier 		DBG("asmmeminit: %#p l %d\n", sys->vmunmapped, l); USED(l);
3219ef1f84bSDavid du Colombier 		*pte = pa|PtePS|PteRW|PteP;
3229ef1f84bSDavid du Colombier 		sys->vmunmapped += 2*MiB;
3239ef1f84bSDavid du Colombier 		pa += 2*MiB;
3249ef1f84bSDavid du Colombier 	}
3259ef1f84bSDavid du Colombier 
3269ef1f84bSDavid du Colombier 	for(asm = asmlist; asm != nil; asm = asm->next){
3279ef1f84bSDavid du Colombier 		if(asm->type != AsmMEMORY)
3289ef1f84bSDavid du Colombier 			continue;
3299ef1f84bSDavid du Colombier 		va = KSEG2+asm->addr;
3309ef1f84bSDavid du Colombier 		DBG(" %#P %#P %s (%P) va %#p\n",
3319ef1f84bSDavid du Colombier 			asm->addr, asm->addr+asm->size,
3329ef1f84bSDavid du Colombier 			asmtypes[asm->type], asm->size, va);
3339ef1f84bSDavid du Colombier 
3349ef1f84bSDavid du Colombier 		lo = asm->addr;
3359ef1f84bSDavid du Colombier 		hi = asm->addr+asm->size;
3369ef1f84bSDavid du Colombier 		/* Convert a range into pages */
3379ef1f84bSDavid du Colombier 		for(mem = lo; mem < hi; mem = nextmem){
3389ef1f84bSDavid du Colombier 			nextmem = (mem + PGLSZ(0)) & ~m->pgszmask[0];
3399ef1f84bSDavid du Colombier 
3409ef1f84bSDavid du Colombier 			/* Try large pages first */
3419ef1f84bSDavid du Colombier 			for(i = m->npgsz - 1; i >= 0; i--){
3429ef1f84bSDavid du Colombier 				if((mem & m->pgszmask[i]) != 0)
3439ef1f84bSDavid du Colombier 					continue;
3449ef1f84bSDavid du Colombier 				if(mem + PGLSZ(i) > hi)
3459ef1f84bSDavid du Colombier 					continue;
3469ef1f84bSDavid du Colombier 
3479ef1f84bSDavid du Colombier 				/*
3489ef1f84bSDavid du Colombier 				 * This page fits entirely within the range,
3499ef1f84bSDavid du Colombier 				 * mark it as usable.
3509ef1f84bSDavid du Colombier 				 */
3519ef1f84bSDavid du Colombier 				if((l = mmuwalk(va, i, &pte, asmwalkalloc)) < 0)
3529ef1f84bSDavid du Colombier 					panic("asmmeminit 3");
3539ef1f84bSDavid du Colombier 
3549ef1f84bSDavid du Colombier 				*pte = mem|PteRW|PteP;
3559ef1f84bSDavid du Colombier 				if(l > 0)
3569ef1f84bSDavid du Colombier 					*pte |= PtePS;
3579ef1f84bSDavid du Colombier 
3589ef1f84bSDavid du Colombier 				nextmem = mem + PGLSZ(i);
3599ef1f84bSDavid du Colombier 				va += PGLSZ(i);
3609ef1f84bSDavid du Colombier 				npg[i]++;
3619ef1f84bSDavid du Colombier 				break;
3629ef1f84bSDavid du Colombier 			}
3639ef1f84bSDavid du Colombier 		}
3649ef1f84bSDavid du Colombier 
3659ef1f84bSDavid du Colombier 		lo = ROUNDUP(asm->addr, PGSZ);
3669ef1f84bSDavid du Colombier 		asm->base = lo;
3679ef1f84bSDavid du Colombier 		hi = ROUNDDN(hi, PGSZ);
3689ef1f84bSDavid du Colombier 		asm->limit = hi;
3699ef1f84bSDavid du Colombier 		asm->kbase = PTR2UINT(KADDR(asm->base));
3709ef1f84bSDavid du Colombier 	}
3719ef1f84bSDavid du Colombier 
3729ef1f84bSDavid du Colombier 	n = sys->vmend - sys->vmstart;			/* close enough */
373*094d6818SDavid du Colombier 	if(n > 600ull*MiB)
374*094d6818SDavid du Colombier 		n = 600ull*MiB;
375*094d6818SDavid du Colombier 	ialloclimit(n/3);
376*094d6818SDavid du Colombier }
3779ef1f84bSDavid du Colombier 
378*094d6818SDavid du Colombier void
asmumeminit(void)379*094d6818SDavid du Colombier asmumeminit(void)
380*094d6818SDavid du Colombier {
381*094d6818SDavid du Colombier 	Asm *asm;
382*094d6818SDavid du Colombier 	extern void physallocdump(void);
383*094d6818SDavid du Colombier 
3849ef1f84bSDavid du Colombier 	for(asm = asmlist; asm != nil; asm = asm->next){
385*094d6818SDavid du Colombier 		if(asm->type != AsmMEMORY)
3869ef1f84bSDavid du Colombier 			continue;
387*094d6818SDavid du Colombier 		physinit(asm->addr, asm->size);
388*094d6818SDavid du Colombier 		sys->pmpaged += ROUNDDN(asm->limit, 2*MiB) - ROUNDUP(asm->base, 2*MiB);
3899ef1f84bSDavid du Colombier 	}
390*094d6818SDavid du Colombier 	physallocdump();
3919ef1f84bSDavid du Colombier }