Annotation of qemu/roms/openbios/arch/sparc32/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 "libc/vsprintf.h"
                     11: #include "libopenbios/bindings.h"
1.1.1.2 ! root       12: #include "arch/sparc32/ofmem_sparc32.h"
1.1       root       13: #include "asm/asi.h"
                     14: #include "pgtsrmmu.h"
                     15: #include "openprom.h"
                     16: #include "libopenbios/sys_info.h"
                     17: #include "boot.h"
                     18: #include "romvec.h"
                     19: 
                     20: #define NCTX_SWIFT  0x100
                     21: #define LOWMEMSZ 32 * 1024 * 1024
                     22: 
                     23: #ifdef CONFIG_DEBUG_MEM
                     24: #define DPRINTF(fmt, args...)                   \
                     25:     do { printk(fmt , ##args); } while (0)
                     26: #else
                     27: #define DPRINTF(fmt, args...)
                     28: #endif
                     29: 
                     30: /* Format a string and print it on the screen, just like the libc
                     31:  * function printf.
                     32:  */
                     33: int printk( const char *fmt, ... )
                     34: {
                     35:         char *p, buf[512];
                     36:        va_list args;
                     37:        int i;
                     38: 
                     39:        va_start(args, fmt);
                     40:         i = vsnprintf(buf, sizeof(buf), fmt, args);
                     41:        va_end(args);
                     42: 
                     43:        for( p=buf; *p; p++ )
                     44:                putchar(*p);
                     45:        return i;
                     46: }
                     47: 
                     48: /*
                     49:  * Allocatable memory chunk.
                     50:  */
                     51: struct mem {
                     52:     char *start, *uplim;
                     53:     char *curp;
                     54: };
                     55: 
                     56: struct mem cdvmem;              /* Current device virtual memory space */
                     57: 
                     58: unsigned int va_shift;
1.1.1.2 ! root       59: unsigned long *l1;
1.1       root       60: static unsigned long *context_table;
                     61: 
                     62: static ucell *mem_reg = 0;
                     63: static ucell *mem_avail = 0;
                     64: static ucell *virt_avail = 0;
                     65: 
                     66: static struct linux_mlist_v0 totphys[1];
                     67: static struct linux_mlist_v0 totmap[1];
                     68: static struct linux_mlist_v0 totavail[1];
                     69: 
                     70: struct linux_mlist_v0 *ptphys;
                     71: struct linux_mlist_v0 *ptmap;
                     72: struct linux_mlist_v0 *ptavail;
                     73: 
                     74: /* Private functions for mapping between physical/virtual addresses */ 
                     75: phys_addr_t
                     76: va2pa(unsigned long va)
                     77: {
                     78:     if ((va >= (unsigned long)&_start) &&
                     79:         (va < (unsigned long)&_end))
                     80:         return va - va_shift;
                     81:     else
                     82:         return va;
                     83: }
                     84: 
                     85: unsigned long
                     86: pa2va(phys_addr_t pa)
                     87: {
                     88:     if ((pa + va_shift >= (unsigned long)&_start) &&
                     89:         (pa + va_shift < (unsigned long)&_end))
                     90:         return pa + va_shift;
                     91:     else
                     92:         return pa;
                     93: }
                     94: 
                     95: void *
                     96: malloc(int size)
                     97: {
                     98:     return ofmem_malloc(size);
                     99: }
                    100: 
                    101: void *
                    102: realloc( void *ptr, size_t size )
                    103: {
                    104:     return ofmem_realloc(ptr, size);
                    105: }
                    106: 
                    107: void
                    108: free(void *ptr)
                    109: {
                    110:     ofmem_free(ptr);
                    111: }
                    112: 
                    113: /*
                    114:  * Allocate memory. This is reusable.
                    115:  */
                    116: void
                    117: mem_init(struct mem *t, char *begin, char *limit)
                    118: {
                    119:     t->start = begin;
                    120:     t->uplim = limit;
                    121:     t->curp = begin;
                    122: }
                    123: 
                    124: void *
                    125: mem_alloc(struct mem *t, int size, int align)
                    126: {
                    127:     char *p;
                    128:     unsigned long pa;
                    129: 
                    130:     // The alignment restrictions refer to physical, not virtual
                    131:     // addresses
                    132:     pa = va2pa((unsigned long)t->curp) + (align - 1);
                    133:     pa &= ~(align - 1);
                    134:     p = (char *)pa2va(pa);
                    135: 
                    136:     if ((unsigned long)p >= (unsigned long)t->uplim ||
                    137:         (unsigned long)p + size > (unsigned long)t->uplim)
                    138:         return NULL;
                    139:     t->curp = p + size;
                    140: 
                    141:     return p;
                    142: }
                    143: 
                    144: /*
                    145:  * D5.3 pgmap@ ( va -- pte )
                    146:  */
                    147: static void
                    148: pgmap_fetch(void)
                    149: {
                    150:     uint32_t pte;
                    151:     unsigned long va, pa;
                    152: 
                    153:     va = POP();
                    154: 
                    155:     pa = find_pte(va, 0);
                    156:     if (pa == 1 || pa == 2)
                    157:         goto error;
                    158:     pte = *(uint32_t *)pa;
                    159:     DPRINTF("pgmap@: va 0x%lx pa 0x%lx pte 0x%x\n", va, pa, pte);
                    160: 
                    161:     PUSH(pte);
                    162:     return;
                    163:  error:
                    164:     PUSH(0);
                    165: }
                    166: 
                    167: /*
                    168:  * D5.3 pgmap! ( pte va -- )
                    169:  */
                    170: static void
                    171: pgmap_store(void)
                    172: {
                    173:     uint32_t pte;
                    174:     unsigned long va, pa;
                    175: 
                    176:     va = POP();
                    177:     pte = POP();
                    178: 
                    179:     pa = find_pte(va, 1);
                    180:     *(uint32_t *)pa = pte;
                    181:     DPRINTF("pgmap!: va 0x%lx pa 0x%lx pte 0x%x\n", va, pa, pte);
                    182: }
                    183: 
                    184: /*
                    185:  * D5.3 map-pages ( pa space va size -- )
                    186:  */
                    187: static void
                    188: ob_map_pages(void)
                    189: {
                    190:     unsigned long va;
                    191:     int size;
                    192:     uint64_t pa;
                    193: 
                    194:     size = POP();
                    195:     va = POP();
                    196:     pa = POP();
                    197:     pa <<= 32;
                    198:     pa |= POP() & 0xffffffff;
                    199: 
1.1.1.2 ! root      200:     ofmem_arch_map_pages(pa, va, size, ofmem_arch_default_translation_mode(pa));
1.1       root      201: }
                    202: 
                    203: static void
                    204: update_memory_properties(void)
                    205: {
                    206:     /* Update the device tree memory properties from the master
                    207:        totphys, totmap and totavail romvec arrays */
                    208:     mem_reg[0] = 0;
                    209:     mem_reg[1] = pointer2cell(totphys[0].start_adr);
                    210:     mem_reg[2] = totphys[0].num_bytes;
                    211: 
                    212:     virt_avail[0] = 0;
                    213:     virt_avail[1] = 0;
                    214:     virt_avail[2] = pointer2cell(totmap[0].start_adr);
                    215: 
                    216:     mem_avail[0] = 0;
                    217:     mem_avail[1] = pointer2cell(totavail[0].start_adr);
                    218:     mem_avail[2] = totavail[0].num_bytes;
                    219: }
                    220: 
                    221: static void
                    222: init_romvec_mem(void)
                    223: {
                    224:     ptphys = totphys;
                    225:     ptmap = totmap;
                    226:     ptavail = totavail;
                    227: 
                    228:     /*
                    229:      * Form memory descriptors.
                    230:      */
                    231:     totphys[0].theres_more = NULL;
                    232:     totphys[0].start_adr = (char *) 0;
                    233:     totphys[0].num_bytes = qemu_mem_size;
                    234: 
                    235:     totavail[0].theres_more = NULL;
                    236:     totavail[0].start_adr = (char *) 0;
                    237:     totavail[0].num_bytes = va2pa((int)&_start) - PAGE_SIZE;
                    238: 
                    239:     totmap[0].theres_more = NULL;
                    240:     totmap[0].start_adr = &_start;
                    241:     totmap[0].num_bytes = (unsigned long) &_iomem -
                    242:         (unsigned long) &_start + PAGE_SIZE;
                    243: 
                    244:     /* Pointers to device tree memory properties */
                    245:     mem_reg = malloc(sizeof(ucell) * 3);
                    246:     mem_avail = malloc(sizeof(ucell) * 3);
                    247:     virt_avail = malloc(sizeof(ucell) * 3);
                    248: 
                    249:     update_memory_properties();
                    250: }
                    251: 
                    252: char *obp_dumb_mmap(char *va, int which_io, unsigned int pa,
                    253:                     unsigned int size)
                    254: {
                    255:     uint64_t mpa = ((uint64_t)which_io << 32) | (uint64_t)pa;
                    256: 
1.1.1.2 ! root      257:     ofmem_arch_map_pages(mpa, (unsigned long)va, size, ofmem_arch_default_translation_mode(mpa));
1.1       root      258:     return va;
                    259: }
                    260: 
                    261: void obp_dumb_munmap(__attribute__((unused)) char *va,
                    262:                      __attribute__((unused)) unsigned int size)
                    263: {
                    264:     DPRINTF("obp_dumb_munmap: virta 0x%x, sz %d\n", (unsigned int)va, size);
                    265: }
                    266: 
                    267: char *obp_memalloc(char *va, unsigned int size, unsigned int align)
                    268: {
                    269:     phys_addr_t phys;
                    270:     ucell virt;
                    271: 
                    272:     /* Claim physical memory */
                    273:     phys = ofmem_claim_phys(-1, size, align);
                    274: 
                    275:     /* Claim virtual memory */
                    276:     virt = ofmem_claim_virt(pointer2cell(va), size, 0);
                    277: 
                    278:     /* Map the memory */
                    279:     ofmem_map(phys, virt, size, ofmem_arch_default_translation_mode(phys));
                    280: 
                    281:     return cell2pointer(virt);
                    282: }
                    283: 
                    284: char *obp_dumb_memalloc(char *va, unsigned int size)
                    285: {
                    286:     unsigned long align;
                    287:     int i;
                    288:     
                    289:     /* Solaris seems to assume that the returned value is physically aligned to size. For
                    290:        example, not having this here causes the Solaris 8 kernel to fault because the 
                    291:        IOMMU page table base address is calculated incorrectly. */
                    292: 
                    293:     /* Enforce a minimum alignment of CONFIG_OFMEM_MALLOC_ALIGN, and choose an alignment 
                    294:        which is the next power of 2 higher than the specified size */
                    295:     align = size;
                    296:     if (align <= CONFIG_OFMEM_MALLOC_ALIGN) {
                    297:         align = CONFIG_OFMEM_MALLOC_ALIGN;
                    298:     } else {
                    299:         align--;
                    300:         for (i = 1; i < sizeof(unsigned long) * 8; i<<=1) {
                    301:             align |= align >> i;
                    302:         }
                    303:         align++;
                    304:     }
                    305: 
                    306:     return obp_memalloc(va, size, align);
                    307: }
                    308: 
                    309: void obp_dumb_memfree(__attribute__((unused))char *va,
                    310:                              __attribute__((unused))unsigned sz)
                    311: {
                    312:     DPRINTF("obp_dumb_memfree 0x%p (size %d)\n", va, sz);
                    313: }
                    314: 
                    315: void
                    316: ob_init_mmu(void)
                    317: {
                    318:     ucell *memreg;
                    319:     ucell *virtreg;
                    320:     phys_addr_t virtregsize;
                    321:     ofmem_t *ofmem = ofmem_arch_get_private();
                    322: 
                    323:     init_romvec_mem();
                    324: 
                    325:     /* Find the phandles for the /memory and /virtual-memory nodes */
                    326:     push_str("/memory");
                    327:     fword("find-package");
                    328:     POP();
                    329:     s_phandle_memory = POP();
                    330: 
                    331:     push_str("/virtual-memory");
                    332:     fword("find-package");
                    333:     POP();
                    334:     s_phandle_mmu = POP();
                    335: 
                    336:     ofmem_register(s_phandle_memory, s_phandle_mmu);
                    337: 
                    338:     /* Setup /memory:reg (totphys) property */
                    339:     memreg = malloc(3 * sizeof(ucell));
                    340:     ofmem_arch_encode_physaddr(memreg, 0); /* physical base */
                    341:     memreg[2] = (ucell)ofmem->ramsize; /* size */
                    342: 
                    343:     push_str("/memory");
                    344:     fword("find-device");
                    345:     PUSH(pointer2cell(memreg));
                    346:     PUSH(3 * sizeof(ucell));
                    347:     push_str("reg");
                    348:     PUSH_ph(s_phandle_memory);
                    349:     fword("encode-property");
                    350: 
                    351:     /* Setup /virtual-memory:reg property */
                    352:     virtregsize = ((phys_addr_t)((ucell)-1) + 1) / 2;
                    353:     
                    354:     virtreg = malloc(6 * sizeof(ucell));
                    355:     ofmem_arch_encode_physaddr(virtreg, 0);
                    356:     virtreg[2] = virtregsize;
                    357:     ofmem_arch_encode_physaddr(&virtreg[3], virtregsize);
                    358:     virtreg[5] = virtregsize;
                    359:     
                    360:     push_str("/virtual-memory");
                    361:     fword("find-device");
                    362:     PUSH(pointer2cell(virtreg));
                    363:     PUSH(6 * sizeof(ucell));
                    364:     push_str("reg");
                    365:     PUSH_ph(s_phandle_mmu);
                    366:     fword("encode-property");
                    367:     
                    368:     PUSH(0);
                    369:     fword("active-package!");
                    370:     bind_func("pgmap@", pgmap_fetch);
                    371:     bind_func("pgmap!", pgmap_store);
                    372:     bind_func("map-pages", ob_map_pages);
                    373: }
                    374: 
                    375: /*
                    376:  * Switch page tables.
                    377:  */
                    378: void
                    379: init_mmu_swift(void)
                    380: {
                    381:     unsigned int addr, i;
                    382:     unsigned long pa, va;
                    383:     int size;
                    384: 
                    385:     ofmem_posix_memalign((void *)&context_table, NCTX_SWIFT * sizeof(int),
                    386:                    NCTX_SWIFT * sizeof(int));
                    387:     ofmem_posix_memalign((void *)&l1, 256 * sizeof(int), 256 * sizeof(int));
                    388: 
                    389:     context_table[0] = (((unsigned long)va2pa((unsigned long)l1)) >> 4) |
                    390:         SRMMU_ET_PTD;
                    391: 
                    392:     for (i = 1; i < NCTX_SWIFT; i++) {
                    393:         context_table[i] = SRMMU_ET_INVALID;
                    394:     }
                    395:     for (i = 0; i < 256; i += 4) {
                    396:         l1[i] = SRMMU_ET_INVALID;
                    397:     }
                    398: 
                    399:     // text, rodata, data, and bss mapped to end of RAM
                    400:     va = (unsigned long)&_start;
                    401:     size = (unsigned long)&_end - (unsigned long)&_start;
                    402:     pa = va2pa(va);
1.1.1.2 ! root      403:     ofmem_arch_map_pages(pa, va, size, ofmem_arch_default_translation_mode(pa));
1.1       root      404: 
                    405:     // 1:1 mapping for RAM
1.1.1.2 ! root      406:     ofmem_arch_map_pages(0, 0, LOWMEMSZ, ofmem_arch_default_translation_mode(0));
1.1       root      407: 
                    408:     /*
                    409:      * Flush cache
                    410:      */
                    411:     for (addr = 0; addr < 0x2000; addr += 0x10) {
                    412:         __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
                    413:                               "r" (addr), "i" (ASI_M_DATAC_TAG));
                    414:         __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
                    415:                               "r" (addr<<1), "i" (ASI_M_TXTC_TAG));
                    416:     }
                    417:     srmmu_set_context(0);
                    418:     srmmu_set_ctable_ptr(va2pa((unsigned long)context_table));
                    419:     srmmu_flush_whole_tlb();
                    420: }

unix.superglobalmegacorp.com

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