1 /* 2 * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. 3 * Based on code written by Travis Geiselbrecht for NewOS. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include "mmu.h" 10 11 #include <boot/platform.h> 12 #include <boot/stdio.h> 13 #include <boot/kernel_args.h> 14 #include <boot/stage2.h> 15 #include <arch/cpu.h> 16 #include <arch_kernel.h> 17 #include <kernel.h> 18 19 #include <OS.h> 20 21 #include <string.h> 22 23 #include "arch_030_mmu.h" 24 25 26 #define TRACE_MMU 27 #ifdef TRACE_MMU 28 # define TRACE(x) dprintf x 29 #else 30 # define TRACE(x) ; 31 #endif 32 33 34 extern page_root_entry *gPageRoot; 35 36 37 static void 38 initialize(void) 39 { 40 TRACE(("mmu_030:initialize\n")); 41 } 42 43 44 static status_t 45 set_tt(int which, addr_t pa, size_t len, uint32 perms) 46 { 47 TRACE(("mmu_030:set_tt(%d, 0x%lx, 0x%lx, 0x%08lx)\n", which, pa, len, perms)); 48 uint32 mask; 49 uint32 ttr = 0; 50 mask = 0x0000ffff; 51 if (len) { 52 len = (len >> 24) & 0x00ff; 53 while (len >>= 1) 54 mask <<= 1; 55 // enable, cachable(?), r/w 56 // super only 57 // mc68030 user's manual, page 9-57 58 ttr = 0x08043; 59 ttr |= (pa & 0xff000000); 60 ttr |= (mask & 0x00ff0000); 61 } 62 TRACE(("mmu_030:set_tt: 0x%08lx\n", ttr)); 63 64 /* as seen in linux and BSD code, 65 * we need to use .chip pseudo op here as -m68030 doesn't seem to help gas grok it. 66 */ 67 switch (which) { 68 case 0: 69 asm volatile( \ 70 ".chip 68030\n\t" \ 71 "pmove %%tt0,(%0)\n\t" \ 72 ".chip 68k\n\t" \ 73 : : "a"(&ttr)); 74 break; 75 case 1: 76 asm volatile( \ 77 ".chip 68030\n\t" \ 78 "pmove (%0),%%tt1\n" \ 79 ".chip 68k\n\t" \ 80 : : "a"(&ttr)); 81 break; 82 default: 83 return EINVAL; 84 } 85 return B_OK; 86 } 87 88 89 static status_t 90 load_rp(addr_t pa) 91 { 92 TRACE(("mmu_030:load_rp(0x%lx)\n", pa)); 93 long_page_directory_entry entry; 94 *(uint64 *)&entry = DFL_PAGEENT_VAL; 95 entry.type = DT_ROOT; 96 entry.addr = TA_TO_PREA(((addr_t)pa)); 97 98 asm volatile( \ 99 "pmove (%0),%%srp\n" \ 100 "pmove (%0),%%crp\n" \ 101 : : "a"((uint64 *)&entry)); 102 return B_OK; 103 } 104 105 106 static status_t 107 allocate_kernel_pgdirs(void) 108 { 109 page_root_entry *pr = gPageRoot; 110 page_directory_entry *pd; 111 addr_t tbl; 112 int i; 113 114 // we'll fill in the 2nd half with ready made page dirs 115 for (i = NUM_ROOTENT_PER_TBL/2; i < NUM_ROOTENT_PER_TBL; i++) { 116 if (i % NUM_DIRTBL_PER_PAGE) 117 tbl += SIZ_DIRTBL; 118 else 119 tbl = mmu_get_next_page_tables(); 120 pr[i].addr = TA_TO_PREA(tbl); 121 pr[i].type = DT_ROOT; 122 pd = (page_directory_entry *)tbl; 123 for (int32 j = 0; j < NUM_DIRENT_PER_TBL; j++) 124 *(page_directory_entry_scalar *)(&pd[j]) = DFL_DIRENT_VAL; 125 } 126 return B_OK; 127 } 128 129 130 static status_t 131 enable_paging(void) 132 { 133 TRACE(("mmu_030:enable_paging\n")); 134 return B_NO_INIT; 135 } 136 137 138 const struct boot_mmu_ops k030MMUOps = { 139 &initialize, 140 &set_tt, 141 &load_rp, 142 &allocate_kernel_pgdirs, 143 &enable_paging 144 }; 145