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

1.1       root        1: /*
                      2:  *     <ofmem_sparc64.c>
                      3:  *
                      4:  *     OF Memory manager
                      5:  *
                      6:  *   Copyright (C) 1999-2004 Samuel Rydh ([email protected])
                      7:  *   Copyright (C) 2004 Stefan Reinauer
                      8:  *
                      9:  *   This program is free software; you can redistribute it and/or
                     10:  *   modify it under the terms of the GNU General Public License
                     11:  *   as published by the Free Software Foundation
                     12:  *
                     13:  */
                     14: 
                     15: #include "config.h"
                     16: #include "libopenbios/bindings.h"
                     17: #include "libc/string.h"
1.1.1.2 ! root       18: #include "arch/sparc64/ofmem_sparc64.h"
1.1       root       19: #include "spitfire.h"
                     20: 
                     21: #define OF_MALLOC_BASE         ((char*)OFMEM + ALIGN_SIZE(sizeof(ofmem_t), 8))
                     22: 
1.1.1.2 ! root       23: #define MEMSIZE (128 * 1024)
1.1       root       24: static union {
                     25:        char memory[MEMSIZE];
                     26:        ofmem_t ofmem;
                     27: } s_ofmem_data;
                     28: 
                     29: #define OFMEM          (&s_ofmem_data.ofmem)
                     30: #define TOP_OF_RAM     (s_ofmem_data.memory + MEMSIZE)
                     31: 
                     32: translation_t **g_ofmem_translations = &s_ofmem_data.ofmem.trans;
                     33: 
1.1.1.2 ! root       34: ucell *va2ttedata = 0;
1.1       root       35: extern uint64_t qemu_mem_size;
                     36: 
                     37: static inline size_t ALIGN_SIZE(size_t x, size_t a)
                     38: {
                     39:     return (x + a - 1) & ~(a-1);
                     40: }
                     41: 
                     42: static ucell get_heap_top( void )
                     43: {
                     44:        return (ucell)(TOP_OF_RAM - ALIGN_SIZE(sizeof(retain_t), 8));
                     45: }
                     46: 
                     47: ofmem_t* ofmem_arch_get_private(void)
                     48: {
                     49:        return OFMEM;
                     50: }
                     51: 
                     52: void* ofmem_arch_get_malloc_base(void)
                     53: {
                     54:        return OF_MALLOC_BASE;
                     55: }
                     56: 
                     57: ucell ofmem_arch_get_heap_top(void)
                     58: {
                     59:        return get_heap_top();
                     60: }
                     61: 
                     62: ucell ofmem_arch_get_virt_top(void)
                     63: {
                     64:        return (ucell)TOP_OF_RAM;
                     65: }
                     66: 
                     67: phys_addr_t ofmem_arch_get_phys_top(void)
                     68: {
                     69:        ofmem_t *ofmem = ofmem_arch_get_private();
                     70: 
                     71:        return ofmem->ramsize;
                     72: }
                     73: 
                     74: ucell ofmem_arch_get_iomem_base(void)
                     75: {
                     76:        /* Currently unused */
                     77:        return 0;
                     78: }
                     79: 
                     80: ucell ofmem_arch_get_iomem_top(void)
                     81: {
                     82:        /* Currently unused */
                     83:        return 0;
                     84: }
                     85: 
                     86: retain_t *ofmem_arch_get_retained(void)
                     87: {
                     88:        /* Retained area is at the top of physical RAM */
                     89:        return (retain_t *)(qemu_mem_size - sizeof(retain_t));
                     90: }
                     91: 
                     92: int ofmem_arch_get_translation_entry_size(void)
                     93: {
                     94:        /* Return size of a single MMU package translation property entry in cells */
                     95:        return 3;
                     96: }
                     97: 
                     98: void ofmem_arch_create_translation_entry(ucell *transentry, translation_t *t)
                     99: {
                    100:        /* Generate translation property entry for SPARC. While there is no
                    101:        formal documentation for this, both Linux kernel and OpenSolaris sources
                    102:        expect a translation property entry to have the following layout:
                    103: 
                    104:                virtual address
                    105:                length
                    106:                mode 
                    107:        */
                    108: 
                    109:        transentry[0] = t->virt;
                    110:        transentry[1] = t->size;
                    111:        transentry[2] = t->mode;
                    112: }
                    113: 
                    114: /* Return the size of a memory available entry given the phandle in cells */
                    115: int ofmem_arch_get_available_entry_size(phandle_t ph)
                    116: {
                    117:        if (ph == s_phandle_memory) {
                    118:                return 1 + ofmem_arch_get_physaddr_cellsize();
                    119:        } else {
                    120:                return 1 + 1;
                    121:        }
                    122: }
                    123: 
                    124: /* Generate memory available property entry for Sparc64 */
                    125: void ofmem_arch_create_available_entry(phandle_t ph, ucell *availentry, phys_addr_t start, ucell size)
                    126: {
                    127:        int i = 0;
                    128: 
                    129:        if (ph == s_phandle_memory) {
                    130:                i += ofmem_arch_encode_physaddr(availentry, start);
                    131:        } else {
                    132:                availentry[i++] = start;
                    133:        }
                    134:     
                    135:        availentry[i] = size;
                    136: }
                    137: 
1.1.1.2 ! root      138: /* Unmap a set of pages */
        !           139: void ofmem_arch_unmap_pages(ucell virt, ucell size)
        !           140: {
        !           141:     ucell va;
        !           142: 
        !           143:     /* align address to 8k */
        !           144:     virt &= ~PAGE_MASK_8K;
        !           145: 
        !           146:     /* align size to 8k */
        !           147:     size = (size + PAGE_MASK_8K) & ~PAGE_MASK_8K;
        !           148: 
        !           149:     for (va = virt; va < virt + size; va += PAGE_SIZE_8K) {
        !           150:         itlb_demap(va);
        !           151:         dtlb_demap(va);
        !           152:     }  
        !           153: }
        !           154: 
        !           155: /* Map a set of pages */
        !           156: void ofmem_arch_map_pages(phys_addr_t phys, ucell virt, ucell size, ucell mode)
        !           157: {
        !           158:     unsigned long tte_data, currsize;
        !           159: 
        !           160:     /* Install locked tlb entries now */
        !           161:     if (mode & SPITFIRE_TTE_LOCKED) {
        !           162: 
        !           163:         /* aligned to 8k page */
        !           164:         size = (size + PAGE_MASK_8K) & ~PAGE_MASK_8K;
        !           165: 
        !           166:         while (size > 0) {
        !           167:             currsize = size;
        !           168:             if (currsize >= PAGE_SIZE_4M &&
        !           169:                 (virt & PAGE_MASK_4M) == 0 &&
        !           170:                 (phys & PAGE_MASK_4M) == 0) {
        !           171:                 currsize = PAGE_SIZE_4M;
        !           172:                 tte_data = 6ULL << 60;
        !           173:             } else if (currsize >= PAGE_SIZE_512K &&
        !           174:                    (virt & PAGE_MASK_512K) == 0 &&
        !           175:                    (phys & PAGE_MASK_512K) == 0) {
        !           176:                 currsize = PAGE_SIZE_512K;
        !           177:                 tte_data = 4ULL << 60;
        !           178:             } else if (currsize >= PAGE_SIZE_64K &&
        !           179:                    (virt & PAGE_MASK_64K) == 0 &&
        !           180:                    (phys & PAGE_MASK_64K) == 0) {
        !           181:                 currsize = PAGE_SIZE_64K;
        !           182:                 tte_data = 2ULL << 60;
        !           183:             } else {
        !           184:                 currsize = PAGE_SIZE_8K;
        !           185:                 tte_data = 0;
        !           186:             }
        !           187: 
        !           188:             tte_data |= phys | mode | SPITFIRE_TTE_VALID;
        !           189: 
        !           190:             itlb_load2(virt, tte_data);
        !           191:             dtlb_load2(virt, tte_data);
        !           192:     
        !           193:             size -= currsize;
        !           194:             phys += currsize;
        !           195:             virt += currsize;
        !           196:         }
        !           197:     }
        !           198: }
        !           199: 
1.1       root      200: /************************************************************************/
                    201: /* misc                                                                 */
                    202: /************************************************************************/
                    203: 
                    204: int ofmem_arch_get_physaddr_cellsize(void)
                    205: {
                    206:     return 1;
                    207: }
                    208: 
                    209: int ofmem_arch_encode_physaddr(ucell *p, phys_addr_t value)
                    210: {
                    211:     p[0] = value;
                    212:     return 1;
                    213: }
                    214: 
                    215: ucell ofmem_arch_default_translation_mode( phys_addr_t phys )
                    216: {
                    217:        /* Writable, cacheable */
                    218:        /* not privileged and not locked */
                    219:        return SPITFIRE_TTE_CP | SPITFIRE_TTE_CV | SPITFIRE_TTE_WRITABLE;
                    220: }
                    221: 
                    222: ucell ofmem_arch_io_translation_mode( phys_addr_t phys )
                    223: {
                    224:        /* Writable, not privileged and not locked */
                    225:        return SPITFIRE_TTE_CV | SPITFIRE_TTE_WRITABLE;
                    226: }
                    227: 
1.1.1.2 ! root      228: /* Architecture-specific OFMEM helpers */
        !           229: unsigned long
        !           230: find_tte(unsigned long va)
        !           231: {
        !           232:        translation_t *t = *g_ofmem_translations;
        !           233:        unsigned long tte_data;
        !           234:        
        !           235:        /* Search the ofmem linked list for this virtual address */
        !           236:        while (t != NULL) {
        !           237:                /* Find the correct range */
        !           238:                if (va >= t->virt && va < (t->virt + t->size)) {
        !           239: 
        !           240:                        /* valid tte, 8k size */
        !           241:                        tte_data = SPITFIRE_TTE_VALID;
        !           242: 
        !           243:                        /* mix in phys address mode */
        !           244:                        tte_data |= t->mode;
        !           245: 
        !           246:                        /* mix in page physical address = t->phys + offset */
        !           247:                        tte_data |= t->phys + (va - t->virt);
        !           248: 
        !           249:                        /* return tte_data */
        !           250:                        return tte_data;
        !           251:                }
        !           252:                t = t->next;
        !           253:        }
        !           254: 
        !           255:        /* Couldn't find tte */
        !           256:        return -1;
        !           257: }
        !           258: 
        !           259: /* ITLB handlers */
        !           260: void
        !           261: itlb_load2(unsigned long vaddr, unsigned long tte_data)
        !           262: {
        !           263:     asm("stxa %0, [%1] %2\n"
        !           264:         "stxa %3, [%%g0] %4\n"
        !           265:         : : "r" (vaddr), "r" (48), "i" (ASI_IMMU),
        !           266:           "r" (tte_data), "i" (ASI_ITLB_DATA_IN));
        !           267: }
        !           268: 
        !           269: void
        !           270: itlb_load3(unsigned long vaddr, unsigned long tte_data,
        !           271:            unsigned long tte_index)
        !           272: {
        !           273:     asm("stxa %0, [%1] %2\n"
        !           274:         "stxa %3, [%4] %5\n"
        !           275:         : : "r" (vaddr), "r" (48), "i" (ASI_IMMU),
        !           276:           "r" (tte_data), "r" (tte_index << 3), "i" (ASI_ITLB_DATA_ACCESS));
        !           277: }
        !           278: 
        !           279: unsigned long
        !           280: itlb_faultva(void)
        !           281: {
        !           282:     unsigned long faultva;
        !           283: 
        !           284:     asm("ldxa [%1] %2, %0\n"
        !           285:         : "=r" (faultva)
        !           286:         : "r" (48), "i" (ASI_IMMU));
        !           287: 
        !           288:     return faultva;
        !           289: }
        !           290: 
        !           291: void
        !           292: itlb_demap(unsigned long vaddr)
        !           293: {
        !           294:     asm("stxa %0, [%0] %1\n"
        !           295:         : : "r" (vaddr), "i" (ASI_IMMU_DEMAP));
        !           296: }
        !           297: 
        !           298: /* DTLB handlers */
        !           299: void
        !           300: dtlb_load2(unsigned long vaddr, unsigned long tte_data)
        !           301: {
        !           302:     asm("stxa %0, [%1] %2\n"
        !           303:         "stxa %3, [%%g0] %4\n"
        !           304:         : : "r" (vaddr), "r" (48), "i" (ASI_DMMU),
        !           305:           "r" (tte_data), "i" (ASI_DTLB_DATA_IN));
        !           306: }
        !           307: 
        !           308: void
        !           309: dtlb_load3(unsigned long vaddr, unsigned long tte_data,
        !           310:            unsigned long tte_index)
        !           311: {
        !           312:     asm("stxa %0, [%1] %2\n"
        !           313:         "stxa %3, [%4] %5\n"
        !           314:         : : "r" (vaddr), "r" (48), "i" (ASI_DMMU),
        !           315:           "r" (tte_data), "r" (tte_index << 3), "i" (ASI_DTLB_DATA_ACCESS));
        !           316: }
        !           317: 
        !           318: unsigned long
        !           319: dtlb_faultva(void)
        !           320: {
        !           321:     unsigned long faultva;
        !           322: 
        !           323:     asm("ldxa [%1] %2, %0\n"
        !           324:         : "=r" (faultva)
        !           325:         : "r" (48), "i" (ASI_DMMU));
        !           326: 
        !           327:     return faultva;
        !           328: }
        !           329: 
        !           330: void
        !           331: dtlb_demap(unsigned long vaddr)
        !           332: {
        !           333:     asm("stxa %0, [%0] %1\n"
        !           334:         : : "r" (vaddr), "i" (ASI_DMMU_DEMAP));
        !           335: }
        !           336: 
1.1       root      337: /************************************************************************/
                    338: /* init / cleanup                                                       */
                    339: /************************************************************************/
                    340: 
                    341: static int remap_page_range( phys_addr_t phys, ucell virt, ucell size, ucell mode )
                    342: {
                    343:        ofmem_claim_phys(phys, size, 0);
                    344:        ofmem_claim_virt(virt, size, 0);
                    345:        ofmem_map_page_range(phys, virt, size, mode);
                    346:        if (!(mode & SPITFIRE_TTE_LOCKED)) {
                    347:                OFMEM_TRACE("remap_page_range clearing translation " FMT_ucellx
                    348:                                " -> " FMT_ucellx " " FMT_ucellx " mode " FMT_ucellx "\n",
                    349:                                virt, phys, size, mode );
                    350:                ofmem_arch_unmap_pages(virt, size);
                    351:        }
                    352:        return 0;
                    353: }
                    354: 
                    355: #define RETAIN_MAGIC   0x1100220033004400
                    356: 
                    357: void ofmem_init( void )
                    358: {
                    359:        retain_t *retained = ofmem_arch_get_retained();
                    360:        int i;
                    361: 
                    362:        memset(&s_ofmem_data, 0, sizeof(s_ofmem_data));
                    363:        s_ofmem_data.ofmem.ramsize = qemu_mem_size;
                    364: 
                    365:        /* inherit translations set up by entry.S */
                    366:        ofmem_walk_boot_map(remap_page_range);
                    367: 
                    368:         /* Map the memory */
                    369:         ofmem_map_page_range(0, 0, qemu_mem_size, 0x36);
                    370: 
                    371:        if (!(retained->magic == RETAIN_MAGIC)) {
                    372:                OFMEM_TRACE("ofmem_init: no retained magic found, creating\n");
                    373:                retained->magic = RETAIN_MAGIC;
                    374:                retained->numentries = 0;
                    375:        } else {
                    376:                OFMEM_TRACE("ofmem_init: retained magic found, total %lld mappings\n", retained->numentries);   
                    377: 
                    378:                /* Mark physical addresses as used so they are not reallocated */
                    379:                for (i = 0; i < retained->numentries; i++) {
                    380:                        ofmem_claim_phys(retained->retain_phys_range[i].start, 
                    381:                                retained->retain_phys_range[i].size, 0);
                    382:                }
                    383: 
                    384:                /* Reset retained area for next reset */
                    385:                retained->magic = RETAIN_MAGIC;
                    386:                retained->numentries = 0;
                    387:        }
                    388: }

unix.superglobalmegacorp.com

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