|
|
1.1 root 1: /* lib.c
2: * tag: simple function library
3: *
4: * Copyright (C) 2003 Stefan Reinauer
5: *
6: * See the file "COPYING" for further information about
7: * the copyright and warranty status of this work.
8: */
9:
10: #include "config.h"
11: #include "libc/vsprintf.h"
12: #include "libopenbios/bindings.h"
13: #include "spitfire.h"
14: #include "libopenbios/sys_info.h"
15: #include "boot.h"
16:
1.1.1.2 ! root 17: #include "arch/sparc64/ofmem_sparc64.h"
1.1 root 18:
19: /* Format a string and print it on the screen, just like the libc
20: * function printf.
21: */
22: int printk( const char *fmt, ... )
23: {
24: char *p, buf[512];
25: va_list args;
26: int i;
27:
28: va_start(args, fmt);
29: i = vsnprintf(buf, sizeof(buf), fmt, args);
30: va_end(args);
31:
32: for( p=buf; *p; p++ )
33: putchar(*p);
34: return i;
35: }
36:
37: /* Private functions for mapping between physical/virtual addresses */
38: phys_addr_t
39: va2pa(unsigned long va)
40: {
41: if ((va >= (unsigned long)&_start) &&
42: (va < (unsigned long)&_end))
43: return va - va_shift;
44: else
45: return va;
46: }
47:
48: unsigned long
49: pa2va(phys_addr_t pa)
50: {
51: if ((pa + va_shift >= (unsigned long)&_start) &&
52: (pa + va_shift < (unsigned long)&_end))
53: return pa + va_shift;
54: else
55: return pa;
56: }
57:
58: void *malloc(int size)
59: {
60: return ofmem_malloc(size);
61: }
62:
63: void* realloc( void *ptr, size_t size )
64: {
65: return ofmem_realloc(ptr, size);
66: }
67:
68: void free(void *ptr)
69: {
70: ofmem_free(ptr);
71: }
72:
73: static void
74: mmu_open(void)
75: {
76: RET(-1);
77: }
78:
79: static void
80: mmu_close(void)
81: {
82: }
83:
84: void ofmem_walk_boot_map(translation_entry_cb cb)
85: {
86: unsigned long phys, virt, size, mode, data, mask;
87: unsigned int i;
88:
89: for (i = 0; i < 64; i++) {
90: data = spitfire_get_dtlb_data(i);
91: if (data & SPITFIRE_TTE_VALID) {
92: switch ((data >> 61) & 3) {
93: default:
94: case 0x0: /* 8k */
95: mask = 0xffffffffffffe000ULL;
96: size = PAGE_SIZE_8K;
97: break;
98: case 0x1: /* 64k */
99: mask = 0xffffffffffff0000ULL;
100: size = PAGE_SIZE_64K;
101: break;
102: case 0x2: /* 512k */
103: mask = 0xfffffffffff80000ULL;
104: size = PAGE_SIZE_512K;
105: break;
106: case 0x3: /* 4M */
107: mask = 0xffffffffffc00000ULL;
108: size = PAGE_SIZE_4M;
109: break;
110: }
111:
112: virt = spitfire_get_dtlb_tag(i);
113: virt &= mask;
114:
115: /* extract 41bit physical address */
116: phys = data & 0x000001fffffff000ULL;
117: phys &= mask;
118:
119: mode = data & 0xfff;
120:
121: cb(phys, virt, size, mode);
122: }
123: }
124: }
125:
126: /*
127: 3.6.5 translate
128: ( virt -- false | phys.lo ... phys.hi mode true )
129: */
130: static void
131: mmu_translate(void)
132: {
133: ucell virt, mode;
134: phys_addr_t phys;
135:
136: virt = POP();
137:
138: phys = ofmem_translate(virt, &mode);
139:
140: if (phys != -1UL) {
141: PUSH(phys & 0xffffffff);
142: PUSH(phys >> 32);
143: PUSH(mode);
144: PUSH(-1);
145: }
146: else {
147: PUSH(0);
148: }
149: }
150:
151: /*
152: * D5.3 pgmap@ ( va -- tte )
153: */
154: static void
155: pgmap_fetch(void)
156: {
1.1.1.2 ! root 157: unsigned long va, tte_data;
1.1 root 158:
1.1.1.2 ! root 159: va = POP();
1.1 root 160:
1.1.1.2 ! root 161: tte_data = find_tte(va);
! 162: if (tte_data == -1)
! 163: goto error;
1.1 root 164:
1.1.1.2 ! root 165: /* return tte_data */
! 166: PUSH(tte_data);
! 167: return;
1.1 root 168:
1.1.1.2 ! root 169: error:
! 170: /* If we get here, there was no entry */
! 171: PUSH(0);
1.1 root 172: }
173:
174: /*
175: ( index tte_data vaddr -- ? )
176: */
177: static void
178: dtlb_load(void)
179: {
180: unsigned long vaddr, tte_data, idx;
181:
182: vaddr = POP();
183: tte_data = POP();
184: idx = POP();
185: dtlb_load3(vaddr, tte_data, idx);
186: }
187:
188: /* MMU D-TLB miss handler */
189: void
190: dtlb_miss_handler(void)
191: {
192: unsigned long faultva, tte_data = 0;
193:
194: /* Grab fault address from MMU and round to nearest 8k page */
195: faultva = dtlb_faultva();
196: faultva >>= 13;
197: faultva <<= 13;
198:
199: /* If a valid va>tte-data routine has been set, invoke that Forth xt instead */
200: if (va2ttedata && *va2ttedata != 0) {
201:
202: /* va>tte-data ( addr cnum -- false | tte-data true ) */
203: PUSH(faultva);
204: PUSH(0);
205: enterforth(*va2ttedata);
206:
207: /* Check the result first... */
208: tte_data = POP();
209: if (!tte_data) {
210: bug();
211: } else {
212: /* Grab the real data */
213: tte_data = POP();
214: }
215: } else {
216: /* Search the ofmem linked list for this virtual address */
1.1.1.2 ! root 217: tte_data = find_tte(faultva);
1.1 root 218: }
219:
220: if (tte_data) {
221: /* Update MMU */
222: dtlb_load2(faultva, tte_data);
223: } else {
224: /* If we got here, there was no translation so fail */
225: bug();
226: }
227:
228: }
229:
230: /*
231: ( index tte_data vaddr -- ? )
232: */
233: static void
234: itlb_load(void)
235: {
236: unsigned long vaddr, tte_data, idx;
237:
238: vaddr = POP();
239: tte_data = POP();
240: idx = POP();
241: itlb_load3(vaddr, tte_data, idx);
242: }
243:
244: /* MMU I-TLB miss handler */
245: void
246: itlb_miss_handler(void)
247: {
248: unsigned long faultva, tte_data = 0;
249:
250: /* Grab fault address from MMU and round to nearest 8k page */
251: faultva = itlb_faultva();
252: faultva >>= 13;
253: faultva <<= 13;
254:
255: /* If a valid va>tte-data routine has been set, invoke that Forth xt instead */
256: if (va2ttedata && *va2ttedata != 0) {
257:
258: /* va>tte-data ( addr cnum -- false | tte-data true ) */
259: PUSH(faultva);
260: PUSH(0);
261: enterforth(*va2ttedata);
262:
263: /* Check the result first... */
264: tte_data = POP();
265: if (!tte_data) {
266: bug();
267: } else {
268: /* Grab the real data */
269: tte_data = POP();
270: }
271: } else {
272: /* Search the ofmem linked list for this virtual address */
1.1.1.2 ! root 273: tte_data = find_tte(faultva);
1.1 root 274: }
275:
276: if (tte_data) {
277: /* Update MMU */
278: itlb_load2(faultva, tte_data);
279: } else {
280: /* If we got here, there was no translation so fail */
281: bug();
282: }
283: }
284:
285: /*
286: 3.6.5 map
287: ( phys.lo ... phys.hi virt size mode -- )
288: */
289: static void
290: mmu_map(void)
291: {
292: ucell virt, size, mode;
293: phys_addr_t phys;
294:
295: mode = POP();
296: size = POP();
297: virt = POP();
298: phys = POP();
299: phys <<= 32;
300: phys |= POP();
301:
302: ofmem_map(phys, virt, size, mode);
303: }
304:
305: /*
306: 3.6.5 unmap
307: ( virt size -- )
308: */
309: static void
310: mmu_unmap(void)
311: {
312: ucell virt, size;
313:
314: size = POP();
315: virt = POP();
316: ofmem_unmap(virt, size);
317: }
318:
319: /*
320: 3.6.5 claim
321: ( virt size align -- base )
322: */
323: static void
324: mmu_claim(void)
325: {
326: ucell virt=-1UL, size, align;
327:
328: align = POP();
329: size = POP();
330: if (!align) {
331: virt = POP();
332: }
333:
334: virt = ofmem_claim_virt(virt, size, align);
335:
336: PUSH(virt);
337: }
338:
339: /*
340: 3.6.5 release
341: ( virt size -- )
342: */
343: static void
344: mmu_release(void)
345: {
346: ucell virt, size;
347:
348: size = POP();
349: virt = POP();
350:
351: ofmem_release_virt(virt, size);
352: }
353:
354: /* ( phys size align --- base ) */
355: static void
356: mem_claim( void )
357: {
358: ucell size, align;
359: phys_addr_t phys=-1UL;
360:
361: align = POP();
362: size = POP();
363: if (!align) {
364: phys = POP();
365: phys <<= 32;
366: phys |= POP();
367: }
368:
369: phys = ofmem_claim_phys(phys, size, align);
370:
371: PUSH(phys & 0xffffffffUL);
372: PUSH(phys >> 32);
373: }
374:
375: /* ( phys size --- ) */
376: static void
377: mem_release( void )
378: {
379: phys_addr_t phys;
380: ucell size;
381:
382: size = POP();
383: phys = POP();
384: phys <<= 32;
385: phys |= POP();
386:
387: ofmem_release_phys(phys, size);
388: }
389:
390: /* ( name-cstr phys size align --- phys ) */
391: static void
392: mem_retain ( void )
393: {
394: ucell size, align;
395: phys_addr_t phys=-1UL;
396:
397: align = POP();
398: size = POP();
399: if (!align) {
400: phys = POP();
401: phys <<= 32;
402: phys |= POP();
403: }
404:
405: /* Currently do nothing with the name */
406: POP();
407:
408: phys = ofmem_retain(phys, size, align);
409:
410: PUSH(phys & 0xffffffffUL);
411: PUSH(phys >> 32);
412: }
413:
414: /* ( virt size align -- baseaddr|-1 ) */
415: static void
416: ciface_claim( void )
417: {
418: ucell align = POP();
419: ucell size = POP();
420: ucell virt = POP();
421: ucell ret = ofmem_claim( virt, size, align );
422:
423: /* printk("ciface_claim: %08x %08x %x\n", virt, size, align ); */
424: PUSH( ret );
425: }
426:
427: /* ( virt size -- ) */
428: static void
429: ciface_release( void )
430: {
431: ucell size = POP();
432: ucell virt = POP();
433: ofmem_release(virt, size);
434: }
435:
436: DECLARE_NODE(memory, INSTALL_OPEN, 0, "/memory");
437:
438: NODE_METHODS( memory ) = {
439: { "claim", mem_claim },
440: { "release", mem_release },
441: { "SUNW,retain", mem_retain },
442: };
443:
444: DECLARE_NODE(mmu, INSTALL_OPEN, 0, "/virtual-memory");
445:
446: NODE_METHODS(mmu) = {
447: { "open", mmu_open },
448: { "close", mmu_close },
449: { "translate", mmu_translate },
450: { "SUNW,dtlb-load", dtlb_load },
451: { "SUNW,itlb-load", itlb_load },
452: { "map", mmu_map },
453: { "unmap", mmu_unmap },
454: { "claim", mmu_claim },
455: { "release", mmu_release },
456: };
457:
458: void ob_mmu_init(const char *cpuname, uint64_t ram_size)
459: {
460: /* memory node */
461: REGISTER_NODE_METHODS(memory, "/memory");
462:
463: /* MMU node */
464: REGISTER_NODE_METHODS(mmu, "/virtual-memory");
465:
466: ofmem_register(find_dev("/memory"), find_dev("/virtual-memory"));
467:
468: push_str("/chosen");
469: fword("find-device");
470:
471: push_str("/virtual-memory");
472: fword("open-dev");
473: fword("encode-int");
474: push_str("mmu");
475: fword("property");
476:
477: push_str("/memory");
478: fword("find-device");
479:
480: /* All memory: 0 to RAM_size */
481: PUSH(0);
482: fword("encode-int");
483: PUSH(0);
484: fword("encode-int");
485: fword("encode+");
486: PUSH((int)(ram_size >> 32));
487: fword("encode-int");
488: fword("encode+");
489: PUSH((int)(ram_size & 0xffffffff));
490: fword("encode-int");
491: fword("encode+");
492: push_str("reg");
493: fword("property");
494:
495: push_str("/openprom/client-services");
496: fword("find-device");
497: bind_func("cif-claim", ciface_claim);
498: bind_func("cif-release", ciface_release);
499:
500: /* Other MMU functions */
501: PUSH(0);
502: fword("active-package!");
503: bind_func("pgmap@", pgmap_fetch);
504:
505: /* Find address of va2ttedata defer word contents for MMU miss handlers */
506: va2ttedata = (ucell *)findword("va>tte-data");
507: va2ttedata++;
508: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.