Annotation of qemu/roms/openbios/arch/sparc64/lib.c, revision 1.1.1.2

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.