1 /* 2 ** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 ** Distributed under the terms of the OpenBeOS License. 4 */ 5 #ifndef _KERNEL_ARCH_M68K_030_MMU_H 6 #define _KERNEL_ARCH_M68K_030_MMU_H 7 8 9 #include <SupportDefs.h> 10 #include <string.h> 11 12 #include <arch_mmu.h> 13 14 // global pages only available on 040/060 15 //#define MMU_HAS_GLOBAL_PAGES 16 17 /* This is the normal layout of the descriptors, as per documentation. 18 * When page size > 256, several bits are unused in the LSB of page 19 * addresses, which we can use in addition of other unused bits. 20 * the structs dedlared later reflect this for 4K pages. 21 */ 22 // = names in MC user's manual 23 // or comments 24 struct short_page_directory_entry { 25 // upper 32 bits 26 uint32 addr : 28; // address 27 uint32 accessed : 1; // = used 28 uint32 write_protect : 1; 29 uint32 type : 2; // DT_* 30 }; 31 32 struct long_page_directory_entry { 33 // upper 32 bits 34 uint32 low_up : 1; // limit is lower(1)/upper(0) 35 uint32 limit : 15; 36 uint32 _ones : 6; 37 uint32 _zero2 : 1; 38 uint32 supervisor : 1; 39 uint32 _zero1 : 4; 40 uint32 accessed : 1; // = used 41 uint32 write_protect : 1; 42 uint32 type : 2; 43 // lower 32 bits 44 uint32 addr : 28; // address 45 uint32 unused : 4; // 46 }; 47 48 struct short_page_table_entry { 49 uint32 addr : 24; // address 50 uint32 _zero2 : 1; 51 uint32 cache_disabled : 1; // = cache_inhibit 52 uint32 _zero1 : 1; 53 uint32 dirty : 1; // = modified 54 uint32 accessed : 1; // = used 55 uint32 write_protect : 1; 56 uint32 type : 2; 57 }; 58 59 struct long_page_table_entry { 60 // upper 32 bits 61 uint32 low_up : 1; // limit is lower(1)/upper(0) 62 // limit only used on early table terminators, else unused 63 uint32 limit : 15; 64 uint32 _ones : 6; 65 uint32 _zero3 : 1; 66 uint32 supervisor : 1; 67 uint32 _zero2 : 1; 68 uint32 cache_disabled : 1; // = cache_inhibit 69 uint32 _zero1 : 1; 70 uint32 dirty : 1; // = modified 71 uint32 accessed : 1; // = used 72 uint32 write_protect : 1; 73 uint32 type : 2; 74 // lower 32 bits 75 uint32 addr : 24; // address 76 uint32 unused : 8; // 77 }; 78 79 /* rarely used */ 80 struct short_indirect_entry { 81 // upper 32 bits 82 uint32 addr : 30; // address 83 uint32 type : 2; // DT_* 84 }; 85 86 struct long_indirect_entry { 87 // upper 32 bits 88 uint32 unused1 : 30; 89 uint32 type : 2; 90 // lower 32 bits 91 uint32 addr : 30; // address 92 uint32 unused2 : 2; // 93 }; 94 95 /* for clarity: 96 - the top level page directory will be called "page root", (root or rtdir) 97 - the 2nd level will be "page directory" like on x86, (pgdir) 98 - the 3rd level is a "page table" as on x86. (pgtbl) 99 */ 100 101 typedef struct short_page_directory_entry page_root_entry; 102 typedef struct short_page_directory_entry page_directory_entry; 103 typedef struct long_page_table_entry page_table_entry; 104 typedef struct long_indirect_entry page_indirect_entry; 105 106 /* scalar storage type that maps them */ 107 typedef uint32 page_root_entry_scalar; 108 typedef uint32 page_directory_entry_scalar; 109 typedef uint64 page_table_entry_scalar; 110 typedef uint64 page_indirect_entry_scalar; 111 112 #define DT_ROOT DT_VALID_4 113 #define DT_DIR DT_VALID_8 114 //#define DT_PAGE DT_PAGE :) 115 #define DT_INDIRECT DT_VALID_8 116 117 /* default scalar values for entries */ 118 #define DFL_ROOTENT_VAL 0x00000000 119 #define DFL_DIRENT_VAL 0x00000000 120 // limit disabled, 6bits at 1 121 // (limit isn't used on that level, but just in case) 122 #define DFL_PAGEENT_VAL 0x7FFFFC0000000000LL 123 124 #define NUM_ROOTENT_PER_TBL 128 125 #define NUM_DIRENT_PER_TBL 128 126 #define NUM_PAGEENT_PER_TBL 64 127 128 /* unlike x86, the root/dir/page table sizes are different than B_PAGE_SIZE 129 * so we will have to fit more than one on a page to avoid wasting space. 130 * We will allocate a group of tables with the one we want inside, and 131 * add them from the aligned index needed, to make it easy to free them. 132 */ 133 134 #define SIZ_ROOTTBL (NUM_ROOTENT_PER_TBL * sizeof(page_root_entry)) 135 #define SIZ_DIRTBL (NUM_DIRENT_PER_TBL * sizeof(page_directory_entry)) 136 #define SIZ_PAGETBL (NUM_PAGEENT_PER_TBL * sizeof(page_table_entry)) 137 138 //#define NUM_ROOTTBL_PER_PAGE (B_PAGE_SIZE / SIZ_ROOTTBL) 139 #define NUM_DIRTBL_PER_PAGE (B_PAGE_SIZE / SIZ_DIRTBL) 140 #define NUM_PAGETBL_PER_PAGE (B_PAGE_SIZE / SIZ_PAGETBL) 141 142 /* macros to get the physical page or table number and address of tables from 143 * descriptors */ 144 #if 0 145 /* XXX: 146 suboptimal: 147 struct foo { 148 int a:2; 149 int b:30; 150 } v = {...}; 151 *(int *)0 = (v.b) << 2; 152 generates: 153 sarl $2, %eax 154 sall $2, %eax 155 We use a cast + bitmasking, since all address fields are already shifted 156 */ 157 // from a root entry 158 #define PREA_TO_TA(a) ((a) << 4) 159 #define PREA_TO_PN(a) ((a) >> (12-4)) 160 #define PREA_TO_PA(a) ((a) << 4) 161 #define TA_TO_PREA(a) ((a) >> 4) 162 //... 163 #endif 164 165 // TA: table address 166 // PN: page number 167 // PA: page address 168 // PO: page offset (offset of table in page) 169 // PI: page index (index of table relative to page start) 170 171 // from a root entry 172 #define PRE_TO_TA(a) ((*(uint32 *)(&(a))) & ~((1<<4)-1)) 173 #define PRE_TO_PN(e) ((*(uint32 *)(&(e))) >> 12) 174 #define PRE_TO_PA(e) ((*(uint32 *)(&(e))) & ~((1<<12)-1)) 175 //#define PRE_TO_PO(e) ((*(uint32 *)(&(e))) & ((1<<12)-1)) 176 //#define PRE_TO_PI(e) (((*(uint32 *)(&(e))) & ((1<<12)-1)) / SIZ_DIRTBL) 177 #define TA_TO_PREA(a) ((a) >> 4) 178 // from a directory entry 179 #define PDE_TO_TA(a) ((*(uint32 *)(&(a))) & ~((1<<4)-1)) 180 #define PDE_TO_PN(e) ((*(uint32 *)(&(e))) >> 12) 181 #define PDE_TO_PA(e) ((*(uint32 *)(&(e))) & ~((1<<12)-1)) 182 //#define PDE_TO_PO(e) ((*(uint32 *)(&(e))) & ((1<<12)-1)) 183 //#define PDE_TO_PI(e) (((*(uint32 *)(&(e))) & ((1<<12)-1)) / SIZ_PAGETBL) 184 #define TA_TO_PDEA(a) ((a) >> 4) 185 // from a table entry 186 #define PTE_TO_TA(a) ((((uint32 *)(&(a)))[1]) & ~((1<<8)-1)) 187 #define PTE_TO_PN(e) ((((uint32 *)(&(e)))[1]) >> 12) 188 #define PTE_TO_PA(e) ((((uint32 *)(&(e)))[1]) & ~((1<<12)-1)) 189 #define TA_TO_PTEA(a) ((a) >> 8) 190 // from an indirect entry 191 #define PIE_TO_TA(a) ((((uint32 *)(&(a)))[1]) & ~((1<<2)-1)) 192 #define PIE_TO_PN(e) ((((uint32 *)(&(e)))[1]) >> 12) 193 #define PIE_TO_PA(e) ((((uint32 *)(&(e)))[1]) & ~((1<<12)-1)) 194 #define PIE_TO_PO(e) ((((uint32 *)(&(e)))[1]) & ((1<<12)-(1<<2))) 195 #define TA_TO_PIEA(a) ((a) >> 2) 196 197 /* 7/7/6 split */ 198 #define VADDR_TO_PRENT(va) (((va) / B_PAGE_SIZE) / (64*128)) 199 #define VADDR_TO_PDENT(va) ((((va) / B_PAGE_SIZE) / 64) % 128) 200 #define VADDR_TO_PTENT(va) (((va) / B_PAGE_SIZE) % 64) 201 202 #endif /* _KERNEL_ARCH_M68K_030_MMU_H */ 203