1*25210b06SDavid du Colombier /*
2*25210b06SDavid du Colombier * Size memory and create the kernel page-tables on the fly while doing so.
3*25210b06SDavid du Colombier * Called from main(), this code should only be run by the bootstrap processor.
4*25210b06SDavid du Colombier *
5*25210b06SDavid du Colombier * MemMin is what the bootstrap code in l.s has already mapped;
6*25210b06SDavid du Colombier * MemMax is the limit of physical memory to scan.
7*25210b06SDavid du Colombier */
8*25210b06SDavid du Colombier #include "u.h"
9*25210b06SDavid du Colombier #include "../port/lib.h"
10*25210b06SDavid du Colombier #include "mem.h"
11*25210b06SDavid du Colombier #include "dat.h"
12*25210b06SDavid du Colombier #include "fns.h"
13*25210b06SDavid du Colombier #include "io.h"
14*25210b06SDavid du Colombier #include "ureg.h"
15*25210b06SDavid du Colombier
16*25210b06SDavid du Colombier #define MEMDEBUG 0
17*25210b06SDavid du Colombier
18*25210b06SDavid du Colombier enum {
19*25210b06SDavid du Colombier MemUPA = 0, /* unbacked physical address */
20*25210b06SDavid du Colombier MemRAM = 1, /* physical memory */
21*25210b06SDavid du Colombier MemUMB = 2, /* upper memory block (<16MB) */
22*25210b06SDavid du Colombier MemReserved = 3,
23*25210b06SDavid du Colombier NMemType = 4,
24*25210b06SDavid du Colombier
25*25210b06SDavid du Colombier KB = 1024,
26*25210b06SDavid du Colombier };
27*25210b06SDavid du Colombier
28*25210b06SDavid du Colombier typedef struct Map Map;
29*25210b06SDavid du Colombier struct Map {
30*25210b06SDavid du Colombier ulong size;
31*25210b06SDavid du Colombier ulong addr;
32*25210b06SDavid du Colombier };
33*25210b06SDavid du Colombier
34*25210b06SDavid du Colombier typedef struct RMap RMap;
35*25210b06SDavid du Colombier struct RMap {
36*25210b06SDavid du Colombier char* name;
37*25210b06SDavid du Colombier Map* map;
38*25210b06SDavid du Colombier Map* mapend;
39*25210b06SDavid du Colombier
40*25210b06SDavid du Colombier Lock;
41*25210b06SDavid du Colombier };
42*25210b06SDavid du Colombier
43*25210b06SDavid du Colombier /*
44*25210b06SDavid du Colombier * Memory allocation tracking.
45*25210b06SDavid du Colombier */
46*25210b06SDavid du Colombier static Map mapupa[16];
47*25210b06SDavid du Colombier static RMap rmapupa = {
48*25210b06SDavid du Colombier "unallocated unbacked physical addresses",
49*25210b06SDavid du Colombier mapupa,
50*25210b06SDavid du Colombier &mapupa[nelem(mapupa)-1],
51*25210b06SDavid du Colombier };
52*25210b06SDavid du Colombier
53*25210b06SDavid du Colombier static Map mapram[16];
54*25210b06SDavid du Colombier static RMap rmapram = {
55*25210b06SDavid du Colombier "physical memory",
56*25210b06SDavid du Colombier mapram,
57*25210b06SDavid du Colombier &mapram[nelem(mapram)-1],
58*25210b06SDavid du Colombier };
59*25210b06SDavid du Colombier
60*25210b06SDavid du Colombier static Map mapumb[64];
61*25210b06SDavid du Colombier static RMap rmapumb = {
62*25210b06SDavid du Colombier "upper memory block",
63*25210b06SDavid du Colombier mapumb,
64*25210b06SDavid du Colombier &mapumb[nelem(mapumb)-1],
65*25210b06SDavid du Colombier };
66*25210b06SDavid du Colombier
67*25210b06SDavid du Colombier static Map mapumbrw[16];
68*25210b06SDavid du Colombier static RMap rmapumbrw = {
69*25210b06SDavid du Colombier "UMB device memory",
70*25210b06SDavid du Colombier mapumbrw,
71*25210b06SDavid du Colombier &mapumbrw[nelem(mapumbrw)-1],
72*25210b06SDavid du Colombier };
73*25210b06SDavid du Colombier
74*25210b06SDavid du Colombier static void map(ulong base, ulong len, int type);
75*25210b06SDavid du Colombier
76*25210b06SDavid du Colombier void
mapprint(RMap * rmap)77*25210b06SDavid du Colombier mapprint(RMap *rmap)
78*25210b06SDavid du Colombier {
79*25210b06SDavid du Colombier Map *mp;
80*25210b06SDavid du Colombier
81*25210b06SDavid du Colombier print("%s\n", rmap->name);
82*25210b06SDavid du Colombier for(mp = rmap->map; mp->size; mp++)
83*25210b06SDavid du Colombier print("\t%8.8luX %8.8luX (%lud)\n", mp->addr, mp->addr+mp->size, mp->size);
84*25210b06SDavid du Colombier }
85*25210b06SDavid du Colombier
86*25210b06SDavid du Colombier
87*25210b06SDavid du Colombier void
memdebug(void)88*25210b06SDavid du Colombier memdebug(void)
89*25210b06SDavid du Colombier {
90*25210b06SDavid du Colombier ulong maxpa, maxpa1, maxpa2;
91*25210b06SDavid du Colombier
92*25210b06SDavid du Colombier maxpa = (nvramread(0x18)<<8)|nvramread(0x17);
93*25210b06SDavid du Colombier maxpa1 = (nvramread(0x31)<<8)|nvramread(0x30);
94*25210b06SDavid du Colombier maxpa2 = (nvramread(0x16)<<8)|nvramread(0x15);
95*25210b06SDavid du Colombier print("maxpa = %luX -> %luX, maxpa1 = %luX maxpa2 = %luX\n",
96*25210b06SDavid du Colombier maxpa, MB+maxpa*KB, maxpa1, maxpa2);
97*25210b06SDavid du Colombier
98*25210b06SDavid du Colombier mapprint(&rmapram);
99*25210b06SDavid du Colombier mapprint(&rmapumb);
100*25210b06SDavid du Colombier mapprint(&rmapumbrw);
101*25210b06SDavid du Colombier mapprint(&rmapupa);
102*25210b06SDavid du Colombier }
103*25210b06SDavid du Colombier
104*25210b06SDavid du Colombier void
mapfree(RMap * rmap,ulong addr,ulong size)105*25210b06SDavid du Colombier mapfree(RMap* rmap, ulong addr, ulong size)
106*25210b06SDavid du Colombier {
107*25210b06SDavid du Colombier Map *mp;
108*25210b06SDavid du Colombier ulong t;
109*25210b06SDavid du Colombier
110*25210b06SDavid du Colombier if(size <= 0)
111*25210b06SDavid du Colombier return;
112*25210b06SDavid du Colombier
113*25210b06SDavid du Colombier lock(rmap);
114*25210b06SDavid du Colombier for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
115*25210b06SDavid du Colombier ;
116*25210b06SDavid du Colombier
117*25210b06SDavid du Colombier if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
118*25210b06SDavid du Colombier (mp-1)->size += size;
119*25210b06SDavid du Colombier if(addr+size == mp->addr){
120*25210b06SDavid du Colombier (mp-1)->size += mp->size;
121*25210b06SDavid du Colombier while(mp->size){
122*25210b06SDavid du Colombier mp++;
123*25210b06SDavid du Colombier (mp-1)->addr = mp->addr;
124*25210b06SDavid du Colombier (mp-1)->size = mp->size;
125*25210b06SDavid du Colombier }
126*25210b06SDavid du Colombier }
127*25210b06SDavid du Colombier }
128*25210b06SDavid du Colombier else{
129*25210b06SDavid du Colombier if(addr+size == mp->addr && mp->size){
130*25210b06SDavid du Colombier mp->addr -= size;
131*25210b06SDavid du Colombier mp->size += size;
132*25210b06SDavid du Colombier }
133*25210b06SDavid du Colombier else do{
134*25210b06SDavid du Colombier if(mp >= rmap->mapend){
135*25210b06SDavid du Colombier print("mapfree: %s: losing %#luX, %ld\n",
136*25210b06SDavid du Colombier rmap->name, addr, size);
137*25210b06SDavid du Colombier break;
138*25210b06SDavid du Colombier }
139*25210b06SDavid du Colombier t = mp->addr;
140*25210b06SDavid du Colombier mp->addr = addr;
141*25210b06SDavid du Colombier addr = t;
142*25210b06SDavid du Colombier t = mp->size;
143*25210b06SDavid du Colombier mp->size = size;
144*25210b06SDavid du Colombier mp++;
145*25210b06SDavid du Colombier }while(size = t);
146*25210b06SDavid du Colombier }
147*25210b06SDavid du Colombier unlock(rmap);
148*25210b06SDavid du Colombier }
149*25210b06SDavid du Colombier
150*25210b06SDavid du Colombier ulong
mapalloc(RMap * rmap,ulong addr,int size,int align)151*25210b06SDavid du Colombier mapalloc(RMap* rmap, ulong addr, int size, int align)
152*25210b06SDavid du Colombier {
153*25210b06SDavid du Colombier Map *mp;
154*25210b06SDavid du Colombier ulong maddr, oaddr;
155*25210b06SDavid du Colombier
156*25210b06SDavid du Colombier lock(rmap);
157*25210b06SDavid du Colombier for(mp = rmap->map; mp->size; mp++){
158*25210b06SDavid du Colombier maddr = mp->addr;
159*25210b06SDavid du Colombier
160*25210b06SDavid du Colombier if(addr){
161*25210b06SDavid du Colombier /*
162*25210b06SDavid du Colombier * A specific address range has been given:
163*25210b06SDavid du Colombier * if the current map entry is greater then
164*25210b06SDavid du Colombier * the address is not in the map;
165*25210b06SDavid du Colombier * if the current map entry does not overlap
166*25210b06SDavid du Colombier * the beginning of the requested range then
167*25210b06SDavid du Colombier * continue on to the next map entry;
168*25210b06SDavid du Colombier * if the current map entry does not entirely
169*25210b06SDavid du Colombier * contain the requested range then the range
170*25210b06SDavid du Colombier * is not in the map.
171*25210b06SDavid du Colombier */
172*25210b06SDavid du Colombier if(maddr > addr)
173*25210b06SDavid du Colombier break;
174*25210b06SDavid du Colombier if(mp->size < addr - maddr) /* maddr+mp->size < addr, but no overflow */
175*25210b06SDavid du Colombier continue;
176*25210b06SDavid du Colombier if(addr - maddr > mp->size - size) /* addr+size > maddr+mp->size, but no overflow */
177*25210b06SDavid du Colombier break;
178*25210b06SDavid du Colombier maddr = addr;
179*25210b06SDavid du Colombier }
180*25210b06SDavid du Colombier
181*25210b06SDavid du Colombier if(align > 0)
182*25210b06SDavid du Colombier maddr = ((maddr+align-1)/align)*align;
183*25210b06SDavid du Colombier if(mp->addr+mp->size-maddr < size)
184*25210b06SDavid du Colombier continue;
185*25210b06SDavid du Colombier
186*25210b06SDavid du Colombier oaddr = mp->addr;
187*25210b06SDavid du Colombier mp->addr = maddr+size;
188*25210b06SDavid du Colombier mp->size -= maddr-oaddr+size;
189*25210b06SDavid du Colombier if(mp->size == 0){
190*25210b06SDavid du Colombier do{
191*25210b06SDavid du Colombier mp++;
192*25210b06SDavid du Colombier (mp-1)->addr = mp->addr;
193*25210b06SDavid du Colombier }while((mp-1)->size = mp->size);
194*25210b06SDavid du Colombier }
195*25210b06SDavid du Colombier
196*25210b06SDavid du Colombier unlock(rmap);
197*25210b06SDavid du Colombier if(oaddr != maddr)
198*25210b06SDavid du Colombier mapfree(rmap, oaddr, maddr-oaddr);
199*25210b06SDavid du Colombier
200*25210b06SDavid du Colombier return maddr;
201*25210b06SDavid du Colombier }
202*25210b06SDavid du Colombier unlock(rmap);
203*25210b06SDavid du Colombier
204*25210b06SDavid du Colombier return 0;
205*25210b06SDavid du Colombier }
206*25210b06SDavid du Colombier
207*25210b06SDavid du Colombier /*
208*25210b06SDavid du Colombier * Allocate from the ram map directly to make page tables.
209*25210b06SDavid du Colombier * Called by mmuwalk during e820scan.
210*25210b06SDavid du Colombier */
211*25210b06SDavid du Colombier void*
rampage(void)212*25210b06SDavid du Colombier rampage(void)
213*25210b06SDavid du Colombier {
214*25210b06SDavid du Colombier ulong m;
215*25210b06SDavid du Colombier
216*25210b06SDavid du Colombier m = mapalloc(&rmapram, 0, BY2PG, BY2PG);
217*25210b06SDavid du Colombier if(m == 0)
218*25210b06SDavid du Colombier return nil;
219*25210b06SDavid du Colombier return KADDR(m);
220*25210b06SDavid du Colombier }
221*25210b06SDavid du Colombier
222*25210b06SDavid du Colombier static void
umbexclude(void)223*25210b06SDavid du Colombier umbexclude(void)
224*25210b06SDavid du Colombier {
225*25210b06SDavid du Colombier int size;
226*25210b06SDavid du Colombier ulong addr;
227*25210b06SDavid du Colombier char *op, *p, *rptr;
228*25210b06SDavid du Colombier
229*25210b06SDavid du Colombier if((p = getconf("umbexclude")) == nil)
230*25210b06SDavid du Colombier return;
231*25210b06SDavid du Colombier
232*25210b06SDavid du Colombier while(p && *p != '\0' && *p != '\n'){
233*25210b06SDavid du Colombier op = p;
234*25210b06SDavid du Colombier addr = strtoul(p, &rptr, 0);
235*25210b06SDavid du Colombier if(rptr == nil || rptr == p || *rptr != '-'){
236*25210b06SDavid du Colombier print("umbexclude: invalid argument <%s>\n", op);
237*25210b06SDavid du Colombier break;
238*25210b06SDavid du Colombier }
239*25210b06SDavid du Colombier p = rptr+1;
240*25210b06SDavid du Colombier
241*25210b06SDavid du Colombier size = strtoul(p, &rptr, 0) - addr + 1;
242*25210b06SDavid du Colombier if(size <= 0){
243*25210b06SDavid du Colombier print("umbexclude: bad range <%s>\n", op);
244*25210b06SDavid du Colombier break;
245*25210b06SDavid du Colombier }
246*25210b06SDavid du Colombier if(rptr != nil && *rptr == ',')
247*25210b06SDavid du Colombier *rptr++ = '\0';
248*25210b06SDavid du Colombier p = rptr;
249*25210b06SDavid du Colombier
250*25210b06SDavid du Colombier mapalloc(&rmapumb, addr, size, 0);
251*25210b06SDavid du Colombier }
252*25210b06SDavid du Colombier }
253*25210b06SDavid du Colombier
254*25210b06SDavid du Colombier static void
umbscan(void)255*25210b06SDavid du Colombier umbscan(void)
256*25210b06SDavid du Colombier {
257*25210b06SDavid du Colombier uchar o[2], *p;
258*25210b06SDavid du Colombier
259*25210b06SDavid du Colombier /*
260*25210b06SDavid du Colombier * Scan the Upper Memory Blocks (0xA0000->0xF0000) for pieces
261*25210b06SDavid du Colombier * which aren't used; they can be used later for devices which
262*25210b06SDavid du Colombier * want to allocate some virtual address space.
263*25210b06SDavid du Colombier * Check for two things:
264*25210b06SDavid du Colombier * 1) device BIOS ROM. This should start with a two-byte header
265*25210b06SDavid du Colombier * of 0x55 0xAA, followed by a byte giving the size of the ROM
266*25210b06SDavid du Colombier * in 512-byte chunks. These ROM's must start on a 2KB boundary.
267*25210b06SDavid du Colombier * 2) device memory. This is read-write.
268*25210b06SDavid du Colombier * There are some assumptions: there's VGA memory at 0xA0000 and
269*25210b06SDavid du Colombier * the VGA BIOS ROM is at 0xC0000. Also, if there's no ROM signature
270*25210b06SDavid du Colombier * at 0xE0000 then the whole 64KB up to 0xF0000 is theoretically up
271*25210b06SDavid du Colombier * for grabs; check anyway.
272*25210b06SDavid du Colombier */
273*25210b06SDavid du Colombier p = KADDR(0xD0000);
274*25210b06SDavid du Colombier while(p < (uchar*)KADDR(0xE0000)){
275*25210b06SDavid du Colombier /*
276*25210b06SDavid du Colombier * Check for the ROM signature, skip if valid.
277*25210b06SDavid du Colombier */
278*25210b06SDavid du Colombier if(p[0] == 0x55 && p[1] == 0xAA){
279*25210b06SDavid du Colombier p += p[2]*512;
280*25210b06SDavid du Colombier continue;
281*25210b06SDavid du Colombier }
282*25210b06SDavid du Colombier
283*25210b06SDavid du Colombier /*
284*25210b06SDavid du Colombier * Is it writeable? If yes, then stick it in
285*25210b06SDavid du Colombier * the UMB device memory map. A floating bus will
286*25210b06SDavid du Colombier * return 0xff, so add that to the map of the
287*25210b06SDavid du Colombier * UMB space available for allocation.
288*25210b06SDavid du Colombier * If it is neither of those, ignore it.
289*25210b06SDavid du Colombier */
290*25210b06SDavid du Colombier o[0] = p[0];
291*25210b06SDavid du Colombier p[0] = 0xCC;
292*25210b06SDavid du Colombier o[1] = p[2*KB-1];
293*25210b06SDavid du Colombier p[2*KB-1] = 0xCC;
294*25210b06SDavid du Colombier if(p[0] == 0xCC && p[2*KB-1] == 0xCC){
295*25210b06SDavid du Colombier p[0] = o[0];
296*25210b06SDavid du Colombier p[2*KB-1] = o[1];
297*25210b06SDavid du Colombier mapfree(&rmapumbrw, PADDR(p), 2*KB);
298*25210b06SDavid du Colombier }
299*25210b06SDavid du Colombier else if(p[0] == 0xFF && p[1] == 0xFF)
300*25210b06SDavid du Colombier mapfree(&rmapumb, PADDR(p), 2*KB);
301*25210b06SDavid du Colombier p += 2*KB;
302*25210b06SDavid du Colombier }
303*25210b06SDavid du Colombier
304*25210b06SDavid du Colombier p = KADDR(0xE0000);
305*25210b06SDavid du Colombier if(p[0] != 0x55 || p[1] != 0xAA){
306*25210b06SDavid du Colombier p[0] = 0xCC;
307*25210b06SDavid du Colombier p[64*KB-1] = 0xCC;
308*25210b06SDavid du Colombier if(p[0] != 0xCC && p[64*KB-1] != 0xCC)
309*25210b06SDavid du Colombier mapfree(&rmapumb, PADDR(p), 64*KB);
310*25210b06SDavid du Colombier }
311*25210b06SDavid du Colombier
312*25210b06SDavid du Colombier umbexclude();
313*25210b06SDavid du Colombier }
314*25210b06SDavid du Colombier
315*25210b06SDavid du Colombier enum {
316*25210b06SDavid du Colombier Pteflags = (1<<12) - 1,
317*25210b06SDavid du Colombier };
318*25210b06SDavid du Colombier
319*25210b06SDavid du Colombier void
dumppdb(ulong * pdb)320*25210b06SDavid du Colombier dumppdb(ulong *pdb)
321*25210b06SDavid du Colombier {
322*25210b06SDavid du Colombier ulong *pp;
323*25210b06SDavid du Colombier
324*25210b06SDavid du Colombier pdb = (ulong *)((uintptr)pdb & ~Pteflags);
325*25210b06SDavid du Colombier iprint("pdb at phys %#8.8p:\n", PADDR(pdb));
326*25210b06SDavid du Colombier for (pp = pdb; pp < pdb + 1024; pp++)
327*25210b06SDavid du Colombier if (*pp)
328*25210b06SDavid du Colombier iprint("pdb[%3ld]: %#8.8lux\n", pp - pdb, *pp);
329*25210b06SDavid du Colombier }
330*25210b06SDavid du Colombier
331*25210b06SDavid du Colombier void
dumppte(ulong * pdb,int sub,int first)332*25210b06SDavid du Colombier dumppte(ulong *pdb, int sub, int first)
333*25210b06SDavid du Colombier {
334*25210b06SDavid du Colombier ulong *pp, *pte;
335*25210b06SDavid du Colombier
336*25210b06SDavid du Colombier pte = KADDR(pdb[sub]);
337*25210b06SDavid du Colombier pte = (ulong *)((uintptr)pte & ~Pteflags);
338*25210b06SDavid du Colombier if (PADDR(pte) == 0) {
339*25210b06SDavid du Colombier iprint("pdb[%d] unmapped\n", sub);
340*25210b06SDavid du Colombier return;
341*25210b06SDavid du Colombier }
342*25210b06SDavid du Colombier iprint("pdb[%d] pte at phys %#8.8p:\n", sub, PADDR(pte));
343*25210b06SDavid du Colombier for (pp = pte; pp < pte + first; pp++)
344*25210b06SDavid du Colombier if (*pp)
345*25210b06SDavid du Colombier iprint("pte[%3ld]: %#8.8lux\n", pp - pte, *pp);
346*25210b06SDavid du Colombier iprint("...\n");
347*25210b06SDavid du Colombier }
348*25210b06SDavid du Colombier
349*25210b06SDavid du Colombier uintptr
mapping(uintptr va)350*25210b06SDavid du Colombier mapping(uintptr va)
351*25210b06SDavid du Colombier {
352*25210b06SDavid du Colombier ulong *pte;
353*25210b06SDavid du Colombier
354*25210b06SDavid du Colombier pte = KADDR(m->pdb[PDX(va)] & ~Pteflags);
355*25210b06SDavid du Colombier return pte[PTX(va)] & ~Pteflags;
356*25210b06SDavid du Colombier }
357*25210b06SDavid du Colombier
358*25210b06SDavid du Colombier /*
359*25210b06SDavid du Colombier * adjust the maps and make the mmu mappings match the maps
360*25210b06SDavid du Colombier */
361*25210b06SDavid du Colombier static void
lowraminit(void)362*25210b06SDavid du Colombier lowraminit(void)
363*25210b06SDavid du Colombier {
364*25210b06SDavid du Colombier /*
365*25210b06SDavid du Colombier * low memory is in use by bootstrap kernels and ROMs.
366*25210b06SDavid du Colombier * MemReserved is untouchable, so use MemRAM.
367*25210b06SDavid du Colombier * address zero is special to mapalloc, and thus to map, so avoid it.
368*25210b06SDavid du Colombier * we can thus load the new kernel directly at 1MB and up.
369*25210b06SDavid du Colombier */
370*25210b06SDavid du Colombier // map(BY2PG, MB - BY2PG, MemRAM) /* executing this map call is fatal */
371*25210b06SDavid du Colombier mapalloc(&rmapram, BY2PG, Mallocbase - BY2PG, 0);
372*25210b06SDavid du Colombier
373*25210b06SDavid du Colombier /*
374*25210b06SDavid du Colombier * declare all RAM above Mallocbase to be free.
375*25210b06SDavid du Colombier */
376*25210b06SDavid du Colombier map(Mallocbase, MemMax - Mallocbase, MemRAM);
377*25210b06SDavid du Colombier
378*25210b06SDavid du Colombier /* declare rest of physical address space above RAM to be available */
379*25210b06SDavid du Colombier map(MemMax, KZERO-MemMax, MemUPA);
380*25210b06SDavid du Colombier
381*25210b06SDavid du Colombier /* force the new mappings to take effect */
382*25210b06SDavid du Colombier mmuflushtlb(PADDR(m->pdb));
383*25210b06SDavid du Colombier }
384*25210b06SDavid du Colombier
385*25210b06SDavid du Colombier /*
386*25210b06SDavid du Colombier * add region at physical base of len bytes to map for `type', and
387*25210b06SDavid du Colombier * set up page tables to map virtual KZERO|base to physical base.
388*25210b06SDavid du Colombier */
389*25210b06SDavid du Colombier static void
map(ulong base,ulong len,int type)390*25210b06SDavid du Colombier map(ulong base, ulong len, int type)
391*25210b06SDavid du Colombier {
392*25210b06SDavid du Colombier ulong n, flags, maxkpa;
393*25210b06SDavid du Colombier
394*25210b06SDavid du Colombier // iprint("map %.8lux %.8lux %d (", base, base+len, type);
395*25210b06SDavid du Colombier /*
396*25210b06SDavid du Colombier * Split any call crossing MemMin to make below simpler.
397*25210b06SDavid du Colombier */
398*25210b06SDavid du Colombier if(base < MemMin && len > MemMin-base){
399*25210b06SDavid du Colombier n = MemMin - base;
400*25210b06SDavid du Colombier map(base, n, type);
401*25210b06SDavid du Colombier map(MemMin, len-n, type);
402*25210b06SDavid du Colombier return;
403*25210b06SDavid du Colombier }
404*25210b06SDavid du Colombier
405*25210b06SDavid du Colombier switch(type){
406*25210b06SDavid du Colombier case MemRAM:
407*25210b06SDavid du Colombier mapfree(&rmapram, base, len);
408*25210b06SDavid du Colombier flags = PTEWRITE|PTEVALID;
409*25210b06SDavid du Colombier break;
410*25210b06SDavid du Colombier case MemUMB:
411*25210b06SDavid du Colombier mapfree(&rmapumb, base, len);
412*25210b06SDavid du Colombier flags = PTEWRITE|PTEUNCACHED|PTEVALID;
413*25210b06SDavid du Colombier break;
414*25210b06SDavid du Colombier case MemUPA:
415*25210b06SDavid du Colombier mapfree(&rmapupa, base, len);
416*25210b06SDavid du Colombier flags = 0;
417*25210b06SDavid du Colombier break;
418*25210b06SDavid du Colombier default:
419*25210b06SDavid du Colombier case MemReserved:
420*25210b06SDavid du Colombier flags = 0;
421*25210b06SDavid du Colombier break;
422*25210b06SDavid du Colombier }
423*25210b06SDavid du Colombier
424*25210b06SDavid du Colombier /*
425*25210b06SDavid du Colombier * Only map from KZERO to 2^32.
426*25210b06SDavid du Colombier */
427*25210b06SDavid du Colombier if(flags){
428*25210b06SDavid du Colombier maxkpa = -KZERO;
429*25210b06SDavid du Colombier if(base >= maxkpa)
430*25210b06SDavid du Colombier return;
431*25210b06SDavid du Colombier if(len > maxkpa-base)
432*25210b06SDavid du Colombier len = maxkpa - base;
433*25210b06SDavid du Colombier pdbmap(m->pdb, base|flags, base+KZERO, len);
434*25210b06SDavid du Colombier }
435*25210b06SDavid du Colombier }
436*25210b06SDavid du Colombier
437*25210b06SDavid du Colombier void
meminit(void)438*25210b06SDavid du Colombier meminit(void)
439*25210b06SDavid du Colombier {
440*25210b06SDavid du Colombier int i, kzsub;
441*25210b06SDavid du Colombier Map *mp;
442*25210b06SDavid du Colombier Confmem *cm;
443*25210b06SDavid du Colombier ulong pa, *pte;
444*25210b06SDavid du Colombier ulong lost, physpte;
445*25210b06SDavid du Colombier
446*25210b06SDavid du Colombier /* no need to size memory, we don't need much. */
447*25210b06SDavid du Colombier pte = m->pdb + BY2PG/BY2WD; /* see l*.s */
448*25210b06SDavid du Colombier
449*25210b06SDavid du Colombier /* populate pdb with double-mapping of low memory */
450*25210b06SDavid du Colombier kzsub = ((uintptr)KZERO >> (2*PGSHIFT - 4)) / sizeof(ulong);
451*25210b06SDavid du Colombier physpte = (uintptr)PADDR(pte);
452*25210b06SDavid du Colombier for (i = 0; i < LOWPTEPAGES; i++)
453*25210b06SDavid du Colombier m->pdb[kzsub + i] = m->pdb[i] =
454*25210b06SDavid du Colombier PTEVALID | PTEKERNEL | PTEWRITE | (physpte + i * BY2PG);
455*25210b06SDavid du Colombier
456*25210b06SDavid du Colombier /*
457*25210b06SDavid du Colombier * Set special attributes for memory between 640KB and 1MB:
458*25210b06SDavid du Colombier * VGA memory is writethrough;
459*25210b06SDavid du Colombier * BIOS ROM's/UMB's are uncached;
460*25210b06SDavid du Colombier * then scan for useful memory.
461*25210b06SDavid du Colombier */
462*25210b06SDavid du Colombier for(pa = 0xA0000; pa < 0xC0000; pa += BY2PG){
463*25210b06SDavid du Colombier pte = mmuwalk(m->pdb, (ulong)KADDR(pa), 2, 0);
464*25210b06SDavid du Colombier *pte |= PTEWT;
465*25210b06SDavid du Colombier }
466*25210b06SDavid du Colombier for(pa = 0xC0000; pa < 0x100000; pa += BY2PG){
467*25210b06SDavid du Colombier pte = mmuwalk(m->pdb, (ulong)KADDR(pa), 2, 0);
468*25210b06SDavid du Colombier *pte |= PTEUNCACHED;
469*25210b06SDavid du Colombier }
470*25210b06SDavid du Colombier mmuflushtlb(PADDR(m->pdb));
471*25210b06SDavid du Colombier
472*25210b06SDavid du Colombier umbscan();
473*25210b06SDavid du Colombier lowraminit();
474*25210b06SDavid du Colombier
475*25210b06SDavid du Colombier /*
476*25210b06SDavid du Colombier * Set the conf entries describing banks of allocatable memory.
477*25210b06SDavid du Colombier */
478*25210b06SDavid du Colombier for(i=0; i<nelem(mapram) && i<nelem(conf.mem); i++){
479*25210b06SDavid du Colombier mp = &rmapram.map[i];
480*25210b06SDavid du Colombier cm = &conf.mem[i];
481*25210b06SDavid du Colombier cm->base = mp->addr;
482*25210b06SDavid du Colombier cm->npage = mp->size/BY2PG;
483*25210b06SDavid du Colombier if (i == 0 && cm->npage == 0)
484*25210b06SDavid du Colombier panic("meminit: no memory in conf.mem");
485*25210b06SDavid du Colombier }
486*25210b06SDavid du Colombier lost = 0;
487*25210b06SDavid du Colombier for(; i<nelem(mapram); i++)
488*25210b06SDavid du Colombier lost += rmapram.map[i].size;
489*25210b06SDavid du Colombier if(lost)
490*25210b06SDavid du Colombier print("meminit - lost %lud bytes\n", lost);
491*25210b06SDavid du Colombier
492*25210b06SDavid du Colombier if(MEMDEBUG)
493*25210b06SDavid du Colombier memdebug();
494*25210b06SDavid du Colombier }
495*25210b06SDavid du Colombier
496*25210b06SDavid du Colombier /*
497*25210b06SDavid du Colombier * Allocate memory from the upper memory blocks.
498*25210b06SDavid du Colombier */
499*25210b06SDavid du Colombier ulong
umbmalloc(ulong addr,int size,int align)500*25210b06SDavid du Colombier umbmalloc(ulong addr, int size, int align)
501*25210b06SDavid du Colombier {
502*25210b06SDavid du Colombier ulong a;
503*25210b06SDavid du Colombier
504*25210b06SDavid du Colombier if(a = mapalloc(&rmapumb, addr, size, align))
505*25210b06SDavid du Colombier return (ulong)KADDR(a);
506*25210b06SDavid du Colombier
507*25210b06SDavid du Colombier return 0;
508*25210b06SDavid du Colombier }
509*25210b06SDavid du Colombier
510*25210b06SDavid du Colombier void
umbfree(ulong addr,int size)511*25210b06SDavid du Colombier umbfree(ulong addr, int size)
512*25210b06SDavid du Colombier {
513*25210b06SDavid du Colombier mapfree(&rmapumb, PADDR(addr), size);
514*25210b06SDavid du Colombier }
515*25210b06SDavid du Colombier
516*25210b06SDavid du Colombier ulong
umbrwmalloc(ulong addr,int size,int align)517*25210b06SDavid du Colombier umbrwmalloc(ulong addr, int size, int align)
518*25210b06SDavid du Colombier {
519*25210b06SDavid du Colombier ulong a;
520*25210b06SDavid du Colombier uchar o[2], *p;
521*25210b06SDavid du Colombier
522*25210b06SDavid du Colombier if(a = mapalloc(&rmapumbrw, addr, size, align))
523*25210b06SDavid du Colombier return(ulong)KADDR(a);
524*25210b06SDavid du Colombier
525*25210b06SDavid du Colombier /*
526*25210b06SDavid du Colombier * Perhaps the memory wasn't visible before
527*25210b06SDavid du Colombier * the interface is initialised, so try again.
528*25210b06SDavid du Colombier */
529*25210b06SDavid du Colombier if((a = umbmalloc(addr, size, align)) == 0)
530*25210b06SDavid du Colombier return 0;
531*25210b06SDavid du Colombier p = (uchar*)a;
532*25210b06SDavid du Colombier o[0] = p[0];
533*25210b06SDavid du Colombier p[0] = 0xCC;
534*25210b06SDavid du Colombier o[1] = p[size-1];
535*25210b06SDavid du Colombier p[size-1] = 0xCC;
536*25210b06SDavid du Colombier if(p[0] == 0xCC && p[size-1] == 0xCC){
537*25210b06SDavid du Colombier p[0] = o[0];
538*25210b06SDavid du Colombier p[size-1] = o[1];
539*25210b06SDavid du Colombier return a;
540*25210b06SDavid du Colombier }
541*25210b06SDavid du Colombier umbfree(a, size);
542*25210b06SDavid du Colombier
543*25210b06SDavid du Colombier return 0;
544*25210b06SDavid du Colombier }
545*25210b06SDavid du Colombier
546*25210b06SDavid du Colombier void
umbrwfree(ulong addr,int size)547*25210b06SDavid du Colombier umbrwfree(ulong addr, int size)
548*25210b06SDavid du Colombier {
549*25210b06SDavid du Colombier mapfree(&rmapumbrw, PADDR(addr), size);
550*25210b06SDavid du Colombier }
551*25210b06SDavid du Colombier
552*25210b06SDavid du Colombier /*
553*25210b06SDavid du Colombier * Give out otherwise-unused physical address space
554*25210b06SDavid du Colombier * for use in configuring devices. Note that unlike upamalloc
555*25210b06SDavid du Colombier * before it, upaalloc does not map the physical address
556*25210b06SDavid du Colombier * into virtual memory. Call vmap to do that.
557*25210b06SDavid du Colombier */
558*25210b06SDavid du Colombier ulong
upaalloc(int size,int align)559*25210b06SDavid du Colombier upaalloc(int size, int align)
560*25210b06SDavid du Colombier {
561*25210b06SDavid du Colombier ulong a;
562*25210b06SDavid du Colombier
563*25210b06SDavid du Colombier a = mapalloc(&rmapupa, 0, size, align);
564*25210b06SDavid du Colombier if(a == 0){
565*25210b06SDavid du Colombier print("out of physical address space allocating %d\n", size);
566*25210b06SDavid du Colombier mapprint(&rmapupa);
567*25210b06SDavid du Colombier }
568*25210b06SDavid du Colombier return a;
569*25210b06SDavid du Colombier }
570*25210b06SDavid du Colombier
571*25210b06SDavid du Colombier void
upafree(ulong pa,int size)572*25210b06SDavid du Colombier upafree(ulong pa, int size)
573*25210b06SDavid du Colombier {
574*25210b06SDavid du Colombier mapfree(&rmapupa, pa, size);
575*25210b06SDavid du Colombier }
576*25210b06SDavid du Colombier
577*25210b06SDavid du Colombier void
upareserve(ulong pa,int size)578*25210b06SDavid du Colombier upareserve(ulong pa, int size)
579*25210b06SDavid du Colombier {
580*25210b06SDavid du Colombier ulong a;
581*25210b06SDavid du Colombier
582*25210b06SDavid du Colombier a = mapalloc(&rmapupa, pa, size, 0);
583*25210b06SDavid du Colombier if(a != pa){
584*25210b06SDavid du Colombier /*
585*25210b06SDavid du Colombier * This can happen when we're using the E820
586*25210b06SDavid du Colombier * map, which might have already reserved some
587*25210b06SDavid du Colombier * of the regions claimed by the pci devices.
588*25210b06SDavid du Colombier */
589*25210b06SDavid du Colombier // print("upareserve: cannot reserve pa=%#.8lux size=%d\n", pa, size);
590*25210b06SDavid du Colombier if(a != 0)
591*25210b06SDavid du Colombier mapfree(&rmapupa, a, size);
592*25210b06SDavid du Colombier }
593*25210b06SDavid du Colombier }
594*25210b06SDavid du Colombier
595*25210b06SDavid du Colombier void
memorysummary(void)596*25210b06SDavid du Colombier memorysummary(void)
597*25210b06SDavid du Colombier {
598*25210b06SDavid du Colombier memdebug();
599*25210b06SDavid du Colombier }
600*25210b06SDavid du Colombier
601