Initialize ofmem at startup. Switch malloc/realloc/free to use ofmem. Implement runtime migration of startup mappings to ofmem. Implement mmu miss handlers to install tlb entries based on ofmem translations list.
Index: openbios-devel/arch/sparc64/lib.c =================================================================== --- openbios-devel.orig/arch/sparc64/lib.c +++ openbios-devel/arch/sparc64/lib.c @@ -34,32 +34,19 @@ int printk( const char *fmt, ... ) return i; }
-#define MEMSIZE ((128 + 256 + 512) * 1024) -static char memory[MEMSIZE]; -static void *memptr=memory; -static int memsize=MEMSIZE; - - void *malloc(int size) { - void *ret=(void *)0; - - if( !size ) - return NULL; - - size = (size + 7) & ~7; + return ofmem_malloc(size); +}
- if(memsize>=size) { - memsize-=size; - ret=memptr; - memptr = (void *)((unsigned long)memptr + size); - } - return ret; +void* realloc( void *ptr, size_t size ) +{ + return ofmem_realloc(ptr, size); }
void free(void *ptr) { - /* Nothing yet */ + ofmem_free(ptr); }
#define PAGE_SIZE_4M (4 * 1024 * 1024) @@ -84,50 +71,44 @@ mmu_close(void)
void ofmem_walk_boot_map(translation_entry_cb cb) { -} - -static int -spitfire_translate(unsigned long virt, unsigned long *p_phys, - unsigned long *p_data, unsigned long *p_size) -{ - unsigned long phys, tag, data, mask, size; + unsigned long phys, virt, size, mode, data, mask; unsigned int i;
for (i = 0; i < 64; i++) { data = spitfire_get_dtlb_data(i); - if (data & 0x8000000000000000ULL) { // Valid entry? + if (data & SPITFIRE_TTE_VALID) { switch ((data >> 61) & 3) { default: - case 0x0: // 8k + case 0x0: /* 8k */ mask = 0xffffffffffffe000ULL; size = PAGE_SIZE_8K; break; - case 0x1: // 64k + case 0x1: /* 64k */ mask = 0xffffffffffff0000ULL; size = PAGE_SIZE_64K; break; - case 0x2: // 512k + case 0x2: /* 512k */ mask = 0xfffffffffff80000ULL; size = PAGE_SIZE_512K; break; - case 0x3: // 4M + case 0x3: /* 4M */ mask = 0xffffffffffc00000ULL; size = PAGE_SIZE_4M; break; } - tag = spitfire_get_dtlb_tag(i); - if ((virt & mask) == (tag & mask)) { - phys = data & mask & 0x000001fffffff000ULL; - phys |= virt & ~mask; - *p_phys = phys; - *p_data = data & 0xfff; - *p_size = size; - return -1; - } + + virt = spitfire_get_dtlb_tag(i); + virt &= mask; + + /* extract 41bit physical address */ + phys = data & 0x000001fffffff000ULL; + phys &= mask; + + mode = data & 0xfff; + + cb(phys, virt, size, mode); } } - - return 0; }
/* @@ -137,18 +118,21 @@ spitfire_translate(unsigned long virt, u static void mmu_translate(void) { - unsigned long virt, phys, data, size; + ucell virt, phys, mode;
virt = POP();
- if (spitfire_translate(virt, &phys, &data, &size)) { - PUSH(phys & 0xffffffff); - PUSH(phys >> 32); - PUSH(data); - PUSH(-1); - return; + phys = ofmem_translate(virt, &mode); + + if (phys != -1UL) { + PUSH(phys & 0xffffffff); + PUSH(phys >> 32); + PUSH(mode); + PUSH(-1); + } + else { + PUSH(0); } - PUSH(0); }
static void @@ -218,13 +202,15 @@ itlb_load(void) }
static void -map_pages(unsigned long virt, unsigned long size, unsigned long phys, - unsigned long mode) +map_pages(unsigned long phys, unsigned long virt, + unsigned long size, unsigned long mode) { - unsigned long tte_data, currsize; + unsigned long tte_data, currsize;
- size = (size + PAGE_MASK_8K) & ~PAGE_MASK_8K; - while (size >= PAGE_SIZE_8K) { + /* aligned to 8k page */ + size = (size + PAGE_MASK_8K) & ~PAGE_MASK_8K; + + while (size > 0) { currsize = size; if (currsize >= PAGE_SIZE_4M && (virt & PAGE_MASK_4M) == 0 && @@ -248,8 +234,9 @@ map_pages(unsigned long virt, unsigned l
tte_data |= phys | mode | SPITFIRE_TTE_VALID;
- dtlb_load2(virt, tte_data); itlb_load2(virt, tte_data); + dtlb_load2(virt, tte_data); + size -= currsize; phys += currsize; virt += currsize; @@ -268,7 +255,7 @@ void ofmem_map_pages(ucell phys, ucell v static void mmu_map(void) { - unsigned long virt, size, mode, phys; + ucell virt, size, mode, phys;
mode = POP(); size = POP(); @@ -276,7 +263,8 @@ mmu_map(void) phys = POP(); phys <<= 32; phys |= POP(); - map_pages(virt, size, phys, mode); + + ofmem_map(phys, virt, size, mode); }
static void @@ -294,22 +282,19 @@ dtlb_demap(unsigned long vaddr) }
static void -unmap_pages(unsigned long virt, unsigned long size) +unmap_pages(ucell virt, ucell size) { - unsigned long phys, data; + ucell va;
- unsigned long currsize; + /* align address to 8k */ + virt &= ~PAGE_MASK_8K;
- // align size + /* align size to 8k */ size = (size + PAGE_MASK_8K) & ~PAGE_MASK_8K;
- while (spitfire_translate(virt, &phys, &data, &currsize)) { - - itlb_demap(virt & ~0x1fffULL); - dtlb_demap(virt & ~0x1fffULL); - - size -= currsize; - virt += currsize; + for (va = virt; va < virt + size; va += PAGE_SIZE_8K) { + itlb_demap(va); + dtlb_demap(va); } }
@@ -325,11 +310,11 @@ void ofmem_unmap_pages(ucell virt, ucell static void mmu_unmap(void) { - unsigned long virt, size; + ucell virt, size;
size = POP(); virt = POP(); - unmap_pages(virt, size); + ofmem_unmap(virt, size); }
/* @@ -339,13 +324,23 @@ mmu_unmap(void) static void mmu_claim(void) { - unsigned long virt, size, align; + ucell virt=-1UL, size, align;
align = POP(); size = POP(); - virt = POP(); - printk("claim virt = %lx size = %lx align = %lx\n", virt, size, align); - PUSH(virt); // XXX + if (!align) { + virt = POP(); + } + + printk("claim virt=" FMT_ucellx " size=" FMT_ucellx " align=" FMT_ucellx + "\n", + virt, size, align); + + virt = ofmem_claim_virt(virt, size, align); + + printk("claimed virt=" FMT_ucellx "\n", virt); + + PUSH(virt); }
/* @@ -355,14 +350,63 @@ mmu_claim(void) static void mmu_release(void) { - unsigned long virt, size; + ucell virt, size;
size = POP(); virt = POP(); - printk("release virt = %lx size = %lx\n", virt, size); - // XXX + printk("release virt=" FMT_ucellx " size=" FMT_ucellx "\n", virt, size); + + ofmem_release(virt, size); +} + +/* ( phys size align --- base ) */ +static void +mem_claim( void ) +{ + ucell phys=-1UL, size, align; + + align = POP(); + size = POP(); + if (!align) { + phys = POP(); + phys <<= 32; + phys |= POP(); + } + + printk("mem_claim phys=" FMT_ucellx " size=" FMT_ucellx + " align=" FMT_ucellx "\n", + phys, size, align); + + phys = ofmem_claim_phys(phys, size, align); + + printk("ofmem_claim_phys result phys=" FMT_ucellx "\n", phys); + + ofmem_map(phys, phys, size, -1); + + PUSH(phys >> 32); + PUSH(phys & 0xffffffffUL); +} + +/* ( phys size --- ) */ +static void +mem_release( void ) +{ + ucell phys, size; + + size = POP(); + phys = POP(); + printk("release virt=" FMT_ucellx " size=" FMT_ucellx "\n", phys, size); + + ofmem_release(phys, size); }
+DECLARE_NODE(memory, INSTALL_OPEN, 0, "/memory"); + +NODE_METHODS( memory ) = { + { "claim", mem_claim }, + { "release", mem_release }, +}; + DECLARE_UNNAMED_NODE(mmu, INSTALL_OPEN, 0);
NODE_METHODS(mmu) = { @@ -381,7 +425,10 @@ void ob_mmu_init(const char *cpuname, ui { char nodebuff[256];
- // MMU node + /* memory node */ + REGISTER_NODE_METHODS(memory, "/memory"); + + /* MMU node */ snprintf(nodebuff, sizeof(nodebuff), "/%s", cpuname); push_str(nodebuff); fword("find-device"); @@ -397,6 +444,8 @@ void ob_mmu_init(const char *cpuname, ui
REGISTER_NODE_METHODS(mmu, nodebuff);
+ ofmem_register(find_dev("/memory"), find_dev("/virtual-memory")); + push_str("/chosen"); fword("find-device");
@@ -409,7 +458,7 @@ void ob_mmu_init(const char *cpuname, ui push_str("/memory"); fword("find-device");
- // All memory: 0 to RAM_size + /* All memory: 0 to RAM_size */ PUSH(0); fword("encode-int"); PUSH(0); @@ -424,108 +473,6 @@ void ob_mmu_init(const char *cpuname, ui push_str("reg"); fword("property");
- // Available memory: 0 to va2pa(_start) - PUSH(0); - fword("encode-int"); - PUSH(0); - fword("encode-int"); - fword("encode+"); - PUSH((va2pa((unsigned long)&_data) - 8192) >> 32); - fword("encode-int"); - fword("encode+"); - PUSH((va2pa((unsigned long)&_data) - 8192) & 0xffffffff); - fword("encode-int"); - fword("encode+"); - push_str("available"); - fword("property"); - - // XXX - // Translations - push_str("/virtual-memory"); - fword("find-device"); - - // 0 to 16M: 1:1 - PUSH(0); - fword("encode-int"); - PUSH(0); - fword("encode-int"); - fword("encode+"); - PUSH(0); - fword("encode-int"); - fword("encode+"); - PUSH(16 * 1024 * 1024); - fword("encode-int"); - fword("encode+"); - PUSH(0x80000000); - fword("encode-int"); - fword("encode+"); - PUSH(0x00000036); - fword("encode-int"); - fword("encode+"); - - // _start to _data: ROM used - PUSH(0); - fword("encode-int"); - fword("encode+"); - PUSH((unsigned long)&_start); - fword("encode-int"); - fword("encode+"); - PUSH(0); - fword("encode-int"); - fword("encode+"); - PUSH((unsigned long)&_data - (unsigned long)&_start); - fword("encode-int"); - fword("encode+"); - PUSH(0x800001ff); - fword("encode-int"); - fword("encode+"); - PUSH(0xf0000074); - fword("encode-int"); - fword("encode+"); - - // _data to _end: end of RAM - PUSH(0); - fword("encode-int"); - fword("encode+"); - PUSH((unsigned long)&_data); - fword("encode-int"); - fword("encode+"); - PUSH(0); - fword("encode-int"); - fword("encode+"); - PUSH((unsigned long)&_data - (unsigned long)&_start); - fword("encode-int"); - fword("encode+"); - PUSH(((va2pa((unsigned long)&_data) - 8192) >> 32) | 0x80000000); - fword("encode-int"); - fword("encode+"); - PUSH(((va2pa((unsigned long)&_data) - 8192) & 0xffffffff) | 0x36); - fword("encode-int"); - fword("encode+"); - - // VGA buffer (128k): 1:1 - PUSH(0x1ff); - fword("encode-int"); - fword("encode+"); - PUSH(0x004a0000); - fword("encode-int"); - fword("encode+"); - PUSH(0); - fword("encode-int"); - fword("encode+"); - PUSH(128 * 1024); - fword("encode-int"); - fword("encode+"); - PUSH(0x800001ff); - fword("encode-int"); - fword("encode+"); - PUSH(0x004a0076); - fword("encode-int"); - fword("encode+"); - - push_str("translations"); - fword("property"); - push_str("/openprom/client-services"); fword("find-device"); bind_func("claim", mmu_claim); Index: openbios-devel/arch/sparc64/openbios.c =================================================================== --- openbios-devel.orig/arch/sparc64/openbios.c +++ openbios-devel/arch/sparc64/openbios.c @@ -20,6 +20,7 @@ #define NO_QEMU_PROTOS #include "openbios/fw_cfg.h" #include "video_subr.h" +#include "ofmem.h"
#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
@@ -495,6 +496,8 @@ int openbios(void) printk("OpenBIOS for Sparc64\n"); #endif
+ ofmem_init(); + collect_sys_info(&sys_info);
dict = malloc(DICTIONARY_SIZE); Index: openbios-devel/arch/sparc64/tree.fs =================================================================== --- openbios-devel.orig/arch/sparc64/tree.fs +++ openbios-devel/arch/sparc64/tree.fs @@ -27,11 +27,12 @@
new-device " memory" device-name + " memory" device-type external : open true ; : close ; \ claim ( phys size align -- base ) - : claim 2drop ; +\ : claim 2drop ; \ release ( phys size -- ) finish-device
@@ -41,7 +42,7 @@ new-device : open true ; : close ; \ claim ( phys size align -- base ) - : claim 2drop ; +\ : claim 2drop ; \ release ( phys size -- ) finish-device
Index: openbios-devel/arch/sparc64/vectors.S =================================================================== --- openbios-devel.orig/arch/sparc64/vectors.S +++ openbios-devel/arch/sparc64/vectors.S @@ -101,6 +101,8 @@ trap_table: ba bug; mov lvl, %g1; nop; nop; nop; nop; nop; nop; #define BTRAPTL1(lvl) BTRAP(lvl) #define BTRAPS(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) BTRAP(x+4) BTRAP(x+5) BTRAP(x+6) BTRAP(x+7) +#define BTRAPS4(x) BTRAP(x) BTRAP(x+1) BTRAP(x+2) BTRAP(x+3) +#define TRAP_HANDLER(routine) ba routine; nop; nop; nop; nop; nop; nop; nop;
#define STACK_BIAS 2047 .globl sparc64_ttable_tl0, sparc64_ttable_tl1 @@ -131,7 +133,16 @@ tl0_irq15: TRAP_IRQ(handler_irq, 15) BTRAPS(0x40) BTRAPS(0x48) #endif BTRAPS(0x50) BTRAPS(0x58) - BTRAPS(0x60) BTRAPS(0x68) + BTRAPS4(0x60) + TRAP_HANDLER(reload_IMMU_tlb) ! 0x64 : instruction_access_MMU_miss + TRAP_HANDLER(reload_IMMU_tlb) ! 0x65 : instruction_access_MMU_miss + TRAP_HANDLER(reload_IMMU_tlb) ! 0x66 : instruction_access_MMU_miss + TRAP_HANDLER(reload_IMMU_tlb) ! 0x67 : instruction_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x68 : data_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x69 : data_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x6A : data_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x6B : data_access_MMU_miss + BTRAPS4(0x6C) ! data_access_protection BTRAPS(0x70) BTRAPS(0x78) tl0_s0n: SPILL_WINDOW tl0_s1n: SPILL_WINDOW @@ -206,7 +217,16 @@ tl1_irq15: TRAP_IRQ(handler_irq, 15) BTRAPS(0x40) BTRAPS(0x48) #endif BTRAPS(0x50) BTRAPS(0x58) - BTRAPS(0x60) BTRAPS(0x68) + BTRAPS4(0x60) + TRAP_HANDLER(reload_IMMU_tlb) ! 0x64 : instruction_access_MMU_miss + TRAP_HANDLER(reload_IMMU_tlb) ! 0x65 : instruction_access_MMU_miss + TRAP_HANDLER(reload_IMMU_tlb) ! 0x66 : instruction_access_MMU_miss + TRAP_HANDLER(reload_IMMU_tlb) ! 0x67 : instruction_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x68 : data_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x69 : data_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x6A : data_access_MMU_miss + TRAP_HANDLER(reload_DMMU_tlb) ! 0x6B : data_access_MMU_miss + BTRAPS4(0x6C) ! data_access_protection BTRAPS(0x70) BTRAPS(0x78) tl1_s0n: SPILL_WINDOW tl1_s1n: SPILL_WINDOW @@ -300,6 +320,86 @@ fill_32bit: restored retry
+ .globl reload_DMMU_tlb, reload_IMMU_tlb + +reload_DMMU_tlb: + mov 6 << 3, %g2 ! va = fault virtual address + ldxa [%g2] ASI_DMMU, %g1 ! from tag access register + + srlx %g1, 13, %g1 ! %g1 = va rounded to 8k page + sllx %g1, 13, %g1 ! + + setx g_ofmem_translations, %g7, %g3 + ldx [%g3], %g3 ! translation_t* t = *g_ofmem_translations +dmmu_next_trans: + ldx [%g3], %g3 + brz %g3, bug ! NULL pointer + nop + ldx [%g3+0x08], %g4 ! t->virt + sub %g1, %g4, %g7 ! %g7 offset = va - t->virt + brlz %g7, dmmu_next_trans ! va < t->virt ? + nop + ldx [%g3+0x10], %g4 ! t->size + sub %g7, %g4, %g4 ! va >= t->virt - t->size ? + brgez %g4, dmmu_next_trans + nop + + ! install 8k tlb entry + + ldx [%g3+0x18], %g4 ! t->phys + add %g4, %g7, %g4 ! %g4 page physical address = t->phys + offset + ldx [%g3+0x20], %g5 ! t->mode + + set 0x80000000, %g2 ! valid tte, 8k size + sllx %g2, 32, %g2 + or %g2, %g5, %g2 ! mix in translation mode + or %g2, %g4, %g3 ! mix in phys addr mode + + mov 6 << 3, %g2 ! page virtual address + stxa %g1, [%g2] ASI_DMMU ! + stxa %g3, [%g0] ASI_DTLB_DATA_IN + + retry + +reload_IMMU_tlb: + mov 6 << 3, %g2 ! va = fault virtual address + ldxa [%g2] ASI_IMMU, %g1 ! from tag access register + + srlx %g1, 13, %g1 ! %g1 = va rounded to 8k page + sllx %g1, 13, %g1 ! + + setx g_ofmem_translations, %g7, %g3 + ldx [%g3], %g3 ! translation_t* t = *g_ofmem_translations +immu_next_trans: + ldx [%g3], %g3 + brz %g3, bug ! NULL pointer + nop + ldx [%g3+0x08], %g4 ! t->virt + sub %g1, %g4, %g7 ! %g7 offset = va - t->virt + brlz %g7, immu_next_trans ! va < t->virt ? + nop + ldx [%g3+0x10], %g4 ! t->size + sub %g7, %g4, %g4 ! va >= t->virt - t->size ? + brgez %g4, immu_next_trans + nop + + ! install 8k tlb entry + + ldx [%g3+0x18], %g4 ! t->phys + add %g4, %g7, %g4 ! %g4 page physical address = t->phys + offset + ldx [%g3+0x20], %g5 ! t->mode + + set 0x80000000, %g2 ! valid tte, 8k size + sllx %g2, 32, %g2 + or %g2, %g5, %g2 ! mix in translation mode + or %g2, %g4, %g3 ! mix in phys addr mode + + mov 6 << 3, %g2 ! page virtual address + stxa %g1, [%g2] ASI_IMMU ! + stxa %g3, [%g0] ASI_ITLB_DATA_IN + + retry + __divide_error: bug: /* Dump the exception and its context */