1 /* $Id: pgtsrmmu.h,v 1.9 1995/11/25 02:32:24 davem Exp $ 2 * pgtsrmmu.h: SRMMU page table defines and code. 3 * 4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 5 */ 6
7 #include <asm/page.h> /* just in case */ 8
9 #ifndef_SPARC_PGTSRMMU_H 10 #define_SPARC_PGTSRMMU_H 11
12 #define SRMMU_PAGE_TABLE_SIZE 0x100 /* 64 entries, 4 bytes a piece */ 13 #define SRMMU_PMD_TABLE_SIZE 0x100 /* 64 entries, 4 bytes a piece */ 14 #define SRMMU_PGD_TABLE_SIZE 0x400 /* 256 entries, 4 bytes a piece */ 15
16 /* PMD_SHIFT determines the size of the area a second-level page table can map */ 17 #defineSRMMU_PMD_SHIFT 18
18 #defineSRMMU_PMD_SIZE (1UL << SRMMU_PMD_SHIFT)
19 #defineSRMMU_PMD_MASK (~(SRMMU_PMD_SIZE-1))
20 #defineSRMMU_PMD_ALIGN(addr) (((addr)+SRMMU_PMD_SIZE-1)&SRMMU_PMD_MASK)
21
22 /* PGDIR_SHIFT determines what a third-level page table entry can map */ 23 #defineSRMMU_PGDIR_SHIFT 24
24 #defineSRMMU_PGDIR_SIZE (1UL << SRMMU_PGDIR_SHIFT)
25 #defineSRMMU_PGDIR_MASK (~(SRMMU_PGDIR_SIZE-1))
26 #defineSRMMU_PGDIR_ALIGN(addr) (((addr)+SRMMU_PGDIR_SIZE-1)&SRMMU_PGDIR_MASK)
27
28 /* 29 * Three-level on SRMMU. 30 */ 31
32 #defineSRMMU_PTRS_PER_PTE 64
33 #defineSRMMU_PTRS_PER_PMD 64
34 #defineSRMMU_PTRS_PER_PGD 256
35
36 /* Just any arbitrary offset to the start of the vmalloc VM area: the 37 * current 8MB value just means that there will be a 8MB "hole" after the 38 * physical memory until the kernel virtual memory starts. That means that 39 * any out-of-bounds memory accesses will hopefully be caught. 40 * The vmalloc() routines leaves a hole of 4kB between each vmalloced 41 * area for the same reason. ;) 42 */ 43 #defineSRMMU_VMALLOC_OFFSET (8*1024*1024)
44 #define SRMMU_VMALLOC_START ((high_memory + SRMMU_VMALLOC_OFFSET) & ~(SRMMU_VMALLOC_OFFSET-1))
45
46 /* 47 * Sparc SRMMU page table fields. 48 */ 49
50 #define_SRMMU_PAGE_VALID (SRMMU_ET_PTE)
51 #define _SRMMU_PMD_VALID (SRMMU_ET_PTD)
52 #define _SRMMU_PGD_VALID (SRMMU_ET_PTD)
53 #define_SRMMU_PAGE_WRITE_USR (SRMMU_ACC_US_RDWR)
54 #define_SRMMU_PAGE_WRITE_KERN (SRMMU_ACC_S_RDWR)
55 #define_SRMMU_PAGE_EXEC (SRMMU_ACC_US_RDEXEC)
56 #define_SRMMU_PAGE_RDONLY (SRMMU_ACC_US_RDONLY)
57 #define_SRMMU_PAGE_NOREAD (SRMMU_ACC_U_ACCDENIED)
58 #define _SRMMU_PAGE_NOCACHE (~SRMMU_PTE_C_MASK)
59 #define_SRMMU_PAGE_PRIV (SRMMU_ACC_S_RDWREXEC)
60 #define_SRMMU_PAGE_REF (SRMMU_PTE_R_MASK)
61 #define_SRMMU_PAGE_DIRTY (SRMMU_PTE_M_MASK)
62 #define_SRMMU_PAGE_COW (SRMMU_ACC_U_RDONLY)
63 #define_SRMMU_PAGE_UNCOW (SRMMU_ACC_US_RDWR)
64
65 /* We want the swapper not to swap out page tables, thus dirty and writable 66 * so that the kernel can change the entries as needed. Also valid for 67 * obvious reasons. 68 */ 69 #define _SRMMU_PAGE_TABLE (_SRMMU_PAGE_VALID | _SRMMU_PAGE_WRITE_KERN | _SRMMU_PAGE_REF | _SRMMU_PAGE_DIRTY)
70 #define _SRMMU_PAGE_CHG_MASK (_SRMMU_PAGE_REF | _SRMMU_PAGE_DIRTY | SRMMU_ET_PTE)
71 #define _SRMMU_PMD_CHG_MASK (SRMMU_ET_PTD)
72 #define _SRMMU_PGD_CHG_MASK (SRMMU_ET_PTD)
73
74 #defineSRMMU_PAGE_NONE__pgprot(_SRMMU_PAGE_VALID | _SRMMU_PAGE_REF)
75 #defineSRMMU_PAGE_SHARED__pgprot(_SRMMU_PAGE_VALID | _SRMMU_PAGE_WRITE_USR | _SRMMU_PAGE_REF)
76 #defineSRMMU_PAGE_COPY__pgprot(_SRMMU_PAGE_VALID | _SRMMU_PAGE_REF | _SRMMU_PAGE_COW)
77 #defineSRMMU_PAGE_READONLY__pgprot(_SRMMU_PAGE_VALID | _SRMMU_PAGE_REF | SRMMU_ACC_US_RDONLY)
78 #defineSRMMU_PAGE_KERNEL__pgprot(_SRMMU_PAGE_VALID | _SRMMU_PAGE_PRIV | SRMMU_PTE_C_MASK)
79 #defineSRMMU_PAGE_INVALID__pgprot(SRMMU_ET_INVALID)
80
81 #define _SRMMU_PAGE_NORMAL(x) __pgprot(_SRMMU_PAGE_VALID | _SRMMU_PAGE_REF | (x))
82
83 /* SRMMU Register addresses */ 84 #define SRMMU_CTRL_REG 0x00000000
85 #defineSRMMU_CTXTBL_PTR 0x00000100
86 #defineSRMMU_CTX_REG 0x00000200
87 #defineSRMMU_FAULT_STATUS 0x00000300
88 #defineSRMMU_FAULT_ADDR 0x00000400
89 #defineSRMMU_AFAULT_STATUS 0x00000500
90 #defineSRMMU_AFAULT_ADDR 0x00000600
91
92 /* The SRMMU control register fields: 93 * ------------------------------------------------------------------- 94 * | IMPL | VERS | SysControl | PSO | Resv | No Fault | Enable | 95 * ------------------------------------------------------------------- 96 * 31 28 27 24 23 8 7 6 2 1 0 97 * 98 * IMPL: Indicates the implementation of this SRMMU, read-only. 99 * VERS: The version of this implementation, again read-only. 100 * SysControl: This is an implementation specific field, the SRMMU 101 * specification does not define anything for this field. 102 * PSO: This determines whether the memory model as seen by the CPU 103 * is Partial Store Order (PSO=1) or Total Store Ordering (PSO=0). 104 * Resv: Don't touch these bits ;) 105 * No Fault: If zero, any fault acts as expected where the fault status 106 * and address registers are updated and a trap hits the CPU. 107 * When this bit is one, on any fault other than in ASI 9, the 108 * MMU updates the status and address fault registers but does 109 * not signal the CPU with a trap. This is useful to beat 110 * race conditions in low-level code when we have to throw 111 * a register window onto the stack in a spill/fill handler 112 * on multiprocessors. 113 * Enable: If one the MMU is doing translations, if zero the addresses 114 * given to the bus are pure physical. 115 */ 116
117 #defineSRMMU_CTREG_IMPL_MASK 0xf0000000
118 #defineSRMMU_CTREG_IMPL_SHIFT 28
119 #defineSRMMU_CTREG_VERS_MASK 0x0f000000
120 #defineSRMMU_CTREG_VERS_SHIFT 24
121 #defineSRMMU_CTREG_SYSCNTRL_MASK 0x00ffff00
122 #defineSRMMU_CTREG_SYSCNTRL_SHIFT 8
123 #defineSRMMU_CTREG_PSO_MASK 0x00000080
124 #defineSRMMU_CTREG_PSO_SHIFT 7
125 #defineSRMMU_CTREG_RESV_MASK 0x0000007c
126 #defineSRMMU_CTREG_RESV_SHIFT 2
127 #defineSRMMU_CTREG_NOFAULT_MASK 0x00000002
128 #defineSRMMU_CTREG_NOFAULT_SHIFT 1
129 #defineSRMMU_CTREG_ENABLE_MASK 0x00000001
130 #defineSRMMU_CTREG_ENABLE_SHIFT 0
131
132 /* Get the MMU control register */ 133 externinlineunsignedintsrmmu_get_mmureg(void)
/* */ 134 { 135 registerunsignedintretval;
136 __asm____volatile__("lda [%%g0] %1, %0\n\t" :
137 "=r" (retval) :
138 "i" (ASI_M_MMUREGS));
139 returnretval;
140 } 141
142 /* Set the MMU control register */ 143 externinlinevoidsrmmu_set_mmureg(unsignedlongregval)
/* */ 144 { 145 __asm____volatile__("sta %0, [%%g0] %1\n\t" : :
146 "r" (regval), "i" (ASI_M_MMUREGS) : "memory");
147
148 return;
149 } 150
151 /* The SRMMU Context Table Pointer Register: 152 * --------------------------------- 153 * | Context Table Pointer | Resv | 154 * --------------------------------- 155 * 31 2 1 0 156 * 157 * This is where the MMU goes to in physical RAM to fetch the 158 * elements in the context table. The non-Resv bits of this 159 * address appear in bits 6-35 of the physical bus during miss 160 * processing, then indexed by the value in the Context Register. 161 * This table must be aligned on a boundary equal to the size of 162 * the table, we provide a nice macro for doing this based upon 163 * the significant bits in the context register. 164 */ 165 #defineSRMMU_CTP_ADDR_MASK 0xfffffffc
166 #defineSRMMU_CTP_ADDR_PADDR_SHIFT 0x4
167 #define SRMMU_CTP_RESV_MASK 0x00000003
168
169 #define SRMMU_SIGBITS_TO_ALIGNMENT(numbits) ((1 << (numbits + 2)))
170
171
172 /* Set the address of the context table. You pass this routine 173 * the physical address, we do the magic shifting for you. 174 */ 175 externinlinevoidsrmmu_set_ctable_ptr(unsignedlongpaddr)
/* */ 176 { 177 unsignedlongctp;
178
179 ctp = (paddr >> SRMMU_CTP_ADDR_PADDR_SHIFT);
180 ctp &= SRMMU_CTP_ADDR_MASK;
181
182 __asm____volatile__("sta %0, [%1] %2\n\t" : :
183 "r" (ctp), "r" (SRMMU_CTXTBL_PTR),
184 "i" (ASI_M_MMUREGS) :
185 "memory");
186 return;
187 } 188
189
190 /* Get the address of the context table. We return the physical 191 * address of the table, again we do the shifting here. 192 */ 193 externinlineunsignedlongsrmmu_get_ctable_ptr(void)
/* */ 194 { 195 registerunsignedintretval;
196
197 __asm____volatile__("lda [%1] %2, %0\n\t" :
198 "=r" (retval) :
199 "r" (SRMMU_CTXTBL_PTR),
200 "i" (ASI_M_MMUREGS));
201
202 retval &= SRMMU_CTP_ADDR_MASK;
203 retval = (retval << SRMMU_CTP_ADDR_PADDR_SHIFT);
204 returnretval;
205 } 206
207 /* Set the context on an SRMMU */ 208 externinlinevoidsrmmu_set_context(intcontext)
/* */ 209 { 210 __asm____volatile__("sta %0, [%1] %2\n\t" : :
211 "r" (context), "r" (SRMMU_CTX_REG),
212 "i" (ASI_M_MMUREGS) : "memory");
213 return;
214 } 215
216 /* Get the context on an SRMMU */ 217 externinlineint srmmu_get_context(void)
/* */ 218 { 219 registerintretval;
220 __asm____volatile__("lda [%1] %2, %0\n\t" :
221 "=r" (retval) :
222 "r" (SRMMU_CTX_REG),
223 "i" (ASI_M_MMUREGS));
224 returnretval;
225 } 226
227 /* SRMMU diagnostic register: 228 * -------------------------------------------------------- 229 * | Virtual Address | PDC entry | DiagReg | Resv | 230 * -------------------------------------------------------- 231 * 31 12 11 4 3 2 1 0 232 * 233 * An SRMMU implementation has the choice of providing this register 234 * and I don't know much about it. 235 */ 236
237 #define SRMMU_DIAG_VADDR_MASK 0xfffff000
238 #define SRMMU_DIAG_PDC_MASK 0x00000ff0
239 #define SRMMU_DIAG_REG_MASK 0x0000000c
240 #define SRMMU_DIAG_RESV_MASK 0x00000003
241
242 /* SRMMU Fault Status Register: 243 * ----------------------------------------------------------- 244 * | Reserved | EBE | L | AT | FT | FAV | OW | 245 * ----------------------------------------------------------- 246 * 31 18 17 10 9 8 7 5 4 2 1 0 247 * 248 * WARNING!!! On certain VERY BROKEN Viking Sun4d modules this register 249 * is complete TOAST! During a fault you cannot trust the values 250 * contained in this register, you must calculate them yourself 251 * by first using the trap program counter to decode the 252 * instruction the code tried to execute (ie. load or store) and 253 * the address they tried to access. I think the Fault Virtual 254 * Address register may be ok on these chips, but who knows. Grrr. 255 * 256 * Reserved: These bits must be zero. 257 * EBE: External bus error bits, implementation dependant (at least 258 * we know what the bits mean on sun4d Viking modules) ;) 259 * L: The level in tree traversal at which the fault occured. The 260 * values are... 0 = context table 261 * 1 = level-1 page table 262 * 2 = level-2 page table 263 * 3 = level-3 page table 264 * AT: Access type field. This is decoded as follows... 265 * 0 -- Load from user data space 266 * 1 -- Load from supervisor data space 267 * 2 -- Read/Execute from user instruction space 268 * 3 -- Read/Execute from supervisor instruction space 269 * 4 -- Store to user data space 270 * 5 -- Store to supervisor data space 271 * 6 -- Store to user instruction space 272 * 7 -- Store to supervisor instruction space (emacs does this) 273 * On the Viking -- TOAST! 274 * FT: This is the fault type field. It is used to determine what was 275 * wrong in the attempted translation. It can be one of... 276 * 0 -- None 277 * 1 -- Invalid address error 278 * 2 -- Protection violation error 279 * 3 -- Priviledge violation error 280 * 4 -- Translation error (your tables are fucked up) 281 * 5 -- Bus access error (you lose) 282 * 6 -- Internal error (might as well have a Viking) 283 * 7 -- Reserved (don't touch) 284 * FAV: Fault Address Valid bit. When set to one the fault address 285 * register contents are valid. It need not be valid for text 286 * faults as the trapped PC tells us this anyway. 287 * OW: The Overwrite Bit, if set to one, this register has been 288 * written to more than once by the hardware since software did 289 * a read. This mean multiple faults have occurred and you have 290 * to a manual page table tree traversal to continue the handling 291 * of the first fault. And on the Viking module.... 292 * 293 * The Fault Address Register is just a 32-bit register representing the 294 * virtual address which caused the fault. It's validity is determined 295 * by the following equation: 296 * if(module==VIKING || FSR.FAV==0) forget_it(); 297 * It's ok for the FAV to be invalid for a text fault because we can 298 * use the trapped program counter, however for a data fault we are SOL. 299 * I'll probably have to write a workaround for this situation too ;-( 300 */ 301
302 #define SRMMU_FSR_RESV_MASK 0xfffc0000 /* Reserved bits */ 303 #define SRMMU_FSR_EBE_MASK 0x0003fc00 /* External Bus Error bits */ 304 #define SRMMU_FSR_EBE_BERR 0x00000400 /* Bus Error */ 305 #define SRMMU_FSR_EBE_BTIMEO 0x00000800 /* Bus Time Out */ 306 #define SRMMU_FSR_EBE_UNCOR 0x00001000 /* Uncorrectable Error */ 307 #define SRMMU_FSR_EBE_UNDEF 0x00002000 /* Undefined Error */ 308 #define SRMMU_FSR_EBE_PARITY 0x00004000 /* Parity error */ 309 #define SRMMU_FSR_EBE_TPARITY 0x00006000 /* Tsunami parity error */ 310 #define SRMMU_FSR_EBE_SBUF 0x00008000 /* Store Buffer error */ 311 #define SRMMU_FSR_EBE_CSA 0x00010000 /* Control space access error (bad ASI) */ 312 #define SRMMU_FSR_EBE_EMRT 0x00020000 /* Viking Emergency Response Team */ 313 #define SRMMU_FSR_L_MASK 0x00000300 /* Fault level bits */ 314 #define SRMMU_FSR_L_CTABLE 0x00000000 /* Context table level flt/err */ 315 #define SRMMU_FSR_L_ONE 0x00000100 /* Level1 ptable flt/err */ 316 #define SRMMU_FSR_L_TWO 0x00000200 /* Level2 ptable flt/err */ 317 #define SRMMU_FSR_L_THREE 0x00000300 /* Level3 ptable flt/err */ 318 #define SRMMU_FSR_AT_MASK 0x000000e0 /* Access Type bits */ 319 #define SRMMU_FSR_AT_LUD 0x00000000 /* Load from User Data space */ 320 #define SRMMU_FSR_AT_LSD 0x00000020 /* What I'll need after writing this code */ 321 #define SRMMU_FSR_AT_RXUI 0x00000040 /* Read/Execute from user text */ 322 #define SRMMU_FSR_AT_RXSI 0x00000060 /* Read/Execute from supv text */ 323 #define SRMMU_FSR_AT_SUD 0x00000080 /* Store to user data space */ 324 #define SRMMU_FSR_AT_SSD 0x000000a0 /* Store to supv data space */ 325 #define SRMMU_FSR_AT_SUI 0x000000c0 /* Store to user text */ 326 #define SRMMU_FSR_AT_SSI 0x000000e0 /* Store to supv text */ 327 #define SRMMU_FSR_FT_MASK 0x0000001c /* Fault Type bits */ 328 #define SRMMU_FSR_FT_NONE 0x00000000 /* No fault occurred */ 329 #define SRMMU_FSR_FT_IADDR 0x00000002 /* Invalid address */ 330 #define SRMMU_FSR_FT_PROT 0x00000004 /* Protection violation */ 331 #define SRMMU_FSR_FT_PRIV 0x00000008 /* Privilege violation */ 332 #define SRMMU_FSR_FT_TRANS 0x0000000a /* Translation error */ 333 #define SRMMU_FSR_FT_BACC 0x0000000c /* Bus Access error */ 334 #define SRMMU_FSR_FT_IACC 0x0000000e /* Internal error */ 335 #define SRMMU_FSR_FT_RESV 0x00000010 /* Reserved, should not get this */ 336 #define SRMMU_FSR_FAV_MASK 0x00000002 /* Fault Address Valid bits */ 337 #define SRMMU_FSR_OW_MASK 0x00000001 /* SFSR OverWritten bits */ 338
339 /* Read the Fault Status Register on the SRMMU */ 340 externinlineunsignedintsrmmu_get_fstatus(void)
/* */ 341 { 342 registerunsignedintretval;
343
344 __asm____volatile__("lda [%1] %2, %0\n\t" :
345 "=r" (retval) :
346 "r" (SRMMU_FAULT_STATUS), "i" (ASI_M_MMUREGS));
347 returnretval;
348 } 349
350 /* Read the Fault Address Register on the SRMMU */ 351 externinlineunsignedint srmmu_get_faddr(void)
/* */ 352 { 353 registerunsignedintretval;
354
355 __asm____volatile__("lda [%1] %2, %0\n\t" :
356 "=r" (retval) :
357 "r" (SRMMU_FAULT_ADDR), "i" (ASI_M_MMUREGS));
358 returnretval;
359 } 360
361 /* SRMMU Asynchronous Fault Status Register: 362 * ----------------------------------------- 363 * | RESERVED |UCE|BTO|BERR|RSV|HFADDR|AFO| 364 * ----------------------------------------- 365 * 31 13 12 11 10 9-8 7-4 0 366 * 367 * UCE: UnCorrectable Error 368 * BTO: Bus TimeOut 369 * BERR: Genreic Bus Error 370 * HFADDR: High 4 bits of the faulting address 371 * AFO: Asynchronous Fault Occurred 372 */ 373 #define SRMMU_AFSR_RESVMASK 0xffffe000
374 #define SRMMU_AFSR_UCE 0x00001000
375 #define SRMMU_AFSR_BTO 0x00000800
376 #define SRMMU_AFSR_BERR 0x00000400
377 #define SRMMU_AFSR_HFADDR 0x000000f0
378 #define SRMMU_AFSR_AFO 0x00000001
379
380 /* Read the asynchronous fault register */ 381 externinlineunsignedint srmmu_get_afstatus(void)
/* */ 382 { 383 registerunsignedintretval;
384
385 __asm____volatile__("lda [%1] %2, %0\n\t" :
386 "=r" (retval) :
387 "r" (SRMMU_AFAULT_STATUS), "i" (ASI_M_MMUREGS));
388 returnretval;
389 } 390
391 /* Read the Asynchronous Fault Address Register on the SRMMU */ 392 externinlineunsignedint srmmu_get_afaddr(void)
/* */ 393 { 394 registerunsignedintretval;
395
396 __asm____volatile__("lda [%1] %2, %0\n\t" :
397 "=r" (retval) :
398 "r" (SRMMU_AFAULT_ADDR), "i" (ASI_M_MMUREGS));
399 returnretval;
400 } 401
402
403 /* Flush the entire TLB cache on the SRMMU. */ 404 externinlinevoidsrmmu_flush_whole_tlb(void)
/* */ 405 { 406 __asm____volatile__("sta %%g0, [%0] %1\n\t": :
407 "r" (0x400), /* Flush entire TLB!! */ 408 "i" (ASI_M_FLUSH_PROBE) : "memory");
409
410 return;
411 } 412
413 /* Probe for an entry in the page-tables of the SRMMU. */ 414 externinlineunsignedlong srmmu_hwprobe(unsignedlongvaddr)
/* */ 415 { 416 unsignedlongretval;
417
418 __asm____volatile__("lda [%1] %2, %0\n\t" :
419 "=r" (retval) :
420 "r" (vaddr | 0x400), "i" (ASI_M_FLUSH_PROBE));
421
422 returnretval;
423 } 424
425 #endif/* !(_SPARC_PGTSRMMU_H) */