1 /* $Id: sun2-mmu.c,v 1.14 2009/08/30 14:39:47 fredette Exp $ */
2
3 /* machine/sun2/sun2-mmu.c - implementation of Sun 2 MMU emulation: */
4
5 /*
6 * Copyright (c) 2003 Matt Fredette
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Matt Fredette.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 #include <tme/common.h>
37 _TME_RCSID("$Id: sun2-mmu.c,v 1.14 2009/08/30 14:39:47 fredette Exp $");
38
39 /* includes: */
40 #include "sun2-impl.h"
41
42 /* macros: */
43
44 /* real PTE entry bits: */
45 #define TME_SUN2_PTE_VALID 0x80000000
46 #define TME_SUN2_PTE_PROT 0x7C000000
47 #define TME_SUN2_PTE_FOD 0x02000000
48 #define TME_SUN2_PTE_PGTYPE 0x00C00000
49 #define TME_SUN2_PTE_PGTYPE_MASK 0x00000003
50 #define TME_SUN2_PTE_REF 0x00200000
51 #define TME_SUN2_PTE_MOD 0x00100000
52 #define TME_SUN2_PTE_PGFRAME 0x00000FFF
53
54 /* real PTE page types: */
55 #define TME_SUN2_PGTYPE_OBMEM (0)
56 #define TME_SUN2_PGTYPE_OBIO (1)
57 #define TME_SUN2_PGTYPE_MBMEM (2)
58 #define TME_SUN2_PGTYPE_VME0 (2)
59 #define TME_SUN2_PGTYPE_MBIO (3)
60 #define TME_SUN2_PGTYPE_VME8 (3)
61
62 /* real bus error register bits: */
63 #define TME_SUN2_BUSERR_PARERR_L TME_BIT(0) /* parity error, lower byte */
64 #define TME_SUN2_BUSERR_PARERR_U TME_BIT(1) /* parity error, upper byte */
65 #define TME_SUN2_BUSERR_TIMEOUT TME_BIT(2) /* bus access timed out */
66 #define TME_SUN2_BUSERR_PROTERR TME_BIT(3) /* protection error */
67 #define TME_SUN2_BUSERR_VMEBUSERR TME_BIT(6) /* bus error signaled on VMEbus */
68 #define TME_SUN2_BUSERR_VALID TME_BIT(7) /* page map was valid */
69
70 /* real context count: */
71 #define TME_SUN2_CONTEXT_COUNT (8)
72
73 /* this logs a bus error: */
74 #ifndef TME_NO_LOG
75 static void
_tme_sun2_bus_fault_log(struct tme_sun2 * sun2,struct tme_bus_tlb * tlb,struct tme_bus_cycle * cycle)76 _tme_sun2_bus_fault_log(struct tme_sun2 *sun2, struct tme_bus_tlb *tlb, struct tme_bus_cycle *cycle)
77 {
78 tme_bus_addr32_t virtual_address;
79 struct tme_sun_mmu_pte pte;
80 tme_uint32_t pte_sun2;
81 const char *bus_name;
82 tme_bus_addr32_t physical_address;
83 int rc;
84
85 /* this silences gcc -Wuninitialized: */
86 bus_name = NULL;
87
88 /* recover the virtual address used: */
89 virtual_address = cycle->tme_bus_cycle_address - tlb->tme_bus_tlb_addr_offset;
90
91 /* look up the PTE involved. since this is a real bus error, and
92 not a protection violation or page not present bus error, we
93 assume the system context: */
94 rc = tme_sun_mmu_pte_get(sun2->tme_sun2_mmu,
95 sun2->tme_sun2_context_system,
96 virtual_address,
97 &pte);
98 assert(rc == TME_OK);
99 pte_sun2 = pte.tme_sun_mmu_pte_raw;
100
101 /* form the physical address and get the bus name: */
102 physical_address = (((pte_sun2 & TME_SUN2_PTE_PGFRAME) << TME_SUN2_PAGE_SIZE_LOG2)
103 | (virtual_address & (TME_SUN2_PAGE_SIZE - 1)));
104 switch ((pte_sun2 & TME_SUN2_PTE_PGTYPE) / (TME_SUN2_PTE_PGTYPE / TME_SUN2_PTE_PGTYPE_MASK)) {
105 case TME_SUN2_PGTYPE_OBMEM: bus_name = "obmem"; break;
106 case TME_SUN2_PGTYPE_OBIO: bus_name = "obio"; break;
107 case TME_SUN2_PGTYPE_MBMEM:
108 if (sun2->tme_sun2_has_vme) {
109 bus_name = "VME";
110 }
111 else {
112 bus_name = "mbmem";
113 }
114 break;
115 case TME_SUN2_PGTYPE_MBIO:
116 if (sun2->tme_sun2_has_vme) {
117 bus_name = "VME";
118 physical_address |= 0x800000;
119 }
120 else {
121 bus_name = "mbio";
122 }
123 break;
124 }
125
126 /* log this bus error: */
127 tme_log(TME_SUN2_LOG_HANDLE(sun2), 1000, TME_OK,
128 (TME_SUN2_LOG_HANDLE(sun2),
129 _("%s bus error, physical 0x%08x, virtual 0x%08x, buserr = 0x%02x"),
130 bus_name,
131 physical_address,
132 virtual_address,
133 sun2->tme_sun2_buserr));
134 }
135 #else /* TME_NO_LOG */
136 #define _tme_sun2_bus_fault_log(a, b, c) do { } while (/* CONSTCOND */ 0)
137 #endif /* TME_NO_LOG */
138
139 /* our general bus fault handler: */
140 static int
_tme_sun2_bus_fault_handler(struct tme_sun2 * sun2,struct tme_bus_tlb * tlb,struct tme_bus_cycle * cycle,int rc)141 _tme_sun2_bus_fault_handler(struct tme_sun2 *sun2,
142 struct tme_bus_tlb *tlb,
143 struct tme_bus_cycle *cycle,
144 int rc)
145 {
146 tme_uint16_t buserr;
147
148 /* dispatch on our fault code: */
149 switch (rc) {
150
151 /* bus address nonexistent: */
152 case ENOENT:
153 buserr = TME_SUN2_BUSERR_VALID | TME_SUN2_BUSERR_TIMEOUT;
154 break;
155
156 /* anything else is just a fault: */
157 default:
158 buserr = TME_SUN2_BUSERR_VALID;
159 break;
160 }
161
162 /* set the bus error register: */
163 sun2->tme_sun2_buserr = buserr;
164
165 /* log the fault: */
166 _tme_sun2_bus_fault_log(sun2, tlb, cycle);
167
168 return (rc);
169 }
170
171 /* our obio bus fault handler: */
172 static int
_tme_sun2_obio_fault_handler(void * _sun2,struct tme_bus_tlb * tlb,struct tme_bus_cycle * cycle,int rc)173 _tme_sun2_obio_fault_handler(void *_sun2, struct tme_bus_tlb *tlb, struct tme_bus_cycle *cycle, int rc)
174 {
175 tme_uint8_t all_bits_one[sizeof(tme_uint16_t)];
176
177 /* the sun2 obio bus doesn't generate bus errors, it just reads
178 all-bits-one: */
179 memset(all_bits_one, 0xff, sizeof(all_bits_one));
180 tme_bus_cycle_xfer_memory(cycle,
181 &all_bits_one[0] - cycle->tme_bus_cycle_address,
182 cycle->tme_bus_cycle_address + sizeof(all_bits_one));
183 return (TME_OK);
184 }
185
186 /* our obmem bus fault handler: */
187 static int
_tme_sun2_obmem_fault_handler(void * _sun2,struct tme_bus_tlb * tlb,struct tme_bus_cycle * cycle,int rc)188 _tme_sun2_obmem_fault_handler(void *_sun2, struct tme_bus_tlb *tlb, struct tme_bus_cycle *cycle, int rc)
189 {
190 tme_uint8_t all_bits_one[sizeof(tme_uint16_t)];
191
192 /* the sun2 obmem bus apparently doesn't generate bus errors below
193 0x700000, and instead just reads all-bits-one: */
194 if (cycle->tme_bus_cycle_address < 0x700000) {
195 memset(all_bits_one, 0xff, sizeof(all_bits_one));
196 tme_bus_cycle_xfer_memory(cycle,
197 &all_bits_one[0] - cycle->tme_bus_cycle_address,
198 cycle->tme_bus_cycle_address + sizeof(all_bits_one));
199 return (TME_OK);
200 }
201
202 /* call the common bus fault handler: */
203 return (_tme_sun2_bus_fault_handler((struct tme_sun2 *) _sun2, tlb, cycle, rc));
204 }
205
206 /* our Multibus fault handler: */
207 static int
_tme_sun2_multibus_fault_handler(void * _sun2,struct tme_bus_tlb * tlb,struct tme_bus_cycle * cycle,int rc)208 _tme_sun2_multibus_fault_handler(void *_sun2, struct tme_bus_tlb *tlb, struct tme_bus_cycle *cycle, int rc)
209 {
210
211 /* call the common bus fault handler: */
212 return (_tme_sun2_bus_fault_handler((struct tme_sun2 *) _sun2, tlb, cycle, rc));
213 }
214
215 /* our VMEbus fault handler: */
216 static int
_tme_sun2_vmebus_fault_handler(void * _sun2,struct tme_bus_tlb * tlb,struct tme_bus_cycle * cycle,int rc)217 _tme_sun2_vmebus_fault_handler(void *_sun2, struct tme_bus_tlb *tlb, struct tme_bus_cycle *cycle, int rc)
218 {
219 struct tme_sun2 *sun2;
220
221 /* recover our sun2: */
222 sun2 = (struct tme_sun2 *) _sun2;
223
224 /* call the common bus fault handler: */
225 rc = _tme_sun2_bus_fault_handler((struct tme_sun2 *) _sun2, tlb, cycle, rc);
226
227 /* this bus fault happened on the VMEbus: */
228 sun2->tme_sun2_buserr |= TME_SUN2_BUSERR_VMEBUSERR;
229
230 /* return the fault: */
231 return (rc);
232 }
233
234 /* our page-invalid cycle handler: */
235 static int
_tme_sun2_mmu_invalid(void * _sun2,struct tme_bus_cycle * cycle)236 _tme_sun2_mmu_invalid(void *_sun2, struct tme_bus_cycle *cycle)
237 {
238 struct tme_sun2 *sun2;
239
240 /* recover our sun2: */
241 sun2 = (struct tme_sun2 *) _sun2;
242
243 /* log this bus error: */
244 tme_log(TME_SUN2_LOG_HANDLE(sun2), 1000, TME_OK,
245 (TME_SUN2_LOG_HANDLE(sun2),
246 _("page invalid bus error")));
247
248 /* set the bus error register: */
249 sun2->tme_sun2_buserr = TME_SUN2_BUSERR_PROTERR;
250
251 /* return the fault: */
252 return (EFAULT);
253 }
254
255 /* our protection error cycle handler: */
256 static int
_tme_sun2_mmu_proterr(void * _sun2,struct tme_bus_cycle * cycle)257 _tme_sun2_mmu_proterr(void *_sun2, struct tme_bus_cycle *cycle)
258 {
259 struct tme_sun2 *sun2;
260
261 /* recover our sun2: */
262 sun2 = (struct tme_sun2 *) _sun2;
263
264 /* log this bus error: */
265 tme_log(TME_SUN2_LOG_HANDLE(sun2), 1000, TME_OK,
266 (TME_SUN2_LOG_HANDLE(sun2),
267 _("page protection bus error")));
268
269 /* set the bus error register: */
270 sun2->tme_sun2_buserr = TME_SUN2_BUSERR_VALID | TME_SUN2_BUSERR_PROTERR;
271
272 /* return the fault: */
273 return (EFAULT);
274 }
275
276 /* our m68k TLB filler: */
277 int
_tme_sun2_m68k_tlb_fill(struct tme_m68k_bus_connection * conn_m68k,struct tme_m68k_tlb * tlb_m68k,unsigned int function_code,tme_uint32_t address,unsigned int cycles)278 _tme_sun2_m68k_tlb_fill(struct tme_m68k_bus_connection *conn_m68k, struct tme_m68k_tlb *tlb_m68k,
279 unsigned int function_code, tme_uint32_t address, unsigned int cycles)
280 {
281 struct tme_sun2 *sun2;
282 struct tme_bus_tlb *tlb;
283 unsigned int function_codes_mask;
284 struct tme_bus_tlb tlb_mapping;
285 tme_uint32_t context;
286 tme_uint32_t access;
287 unsigned short tlb_flags;
288
289 /* recover our sun2: */
290 sun2 = (struct tme_sun2 *) conn_m68k->tme_m68k_bus_connection.tme_bus_connection.tme_connection_element->tme_element_private;
291
292 /* get the generic bus TLB: */
293 tlb = &tlb_m68k->tme_m68k_tlb_bus_tlb;
294
295 /* if this is function code three, we handle this ourselves: */
296 if (function_code == TME_M68K_FC_3) {
297
298 /* initialize the TLB entry: */
299 tme_bus_tlb_initialize(tlb);
300
301 /* we cover the entire address space: */
302 tlb->tme_bus_tlb_addr_first = 0;
303 tlb->tme_bus_tlb_addr_last = 0 - (tme_bus_addr32_t) 1;
304
305 /* we allow reading and writing: */
306 tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
307
308 /* our bus cycle handler: */
309 tlb->tme_bus_tlb_cycle_private = sun2;
310 tlb->tme_bus_tlb_cycle = _tme_sun2_control_cycle_handler;
311
312 /* this is good for function code three only: */
313 tlb_m68k->tme_m68k_tlb_function_codes_mask = TME_BIT(TME_M68K_FC_3);
314
315 /* done: */
316 return (TME_OK);
317 }
318
319 /* this must be or a user or supervisor program or data function
320 code: */
321 assert(function_code == TME_M68K_FC_UD
322 || function_code == TME_M68K_FC_UP
323 || function_code == TME_M68K_FC_SD
324 || function_code == TME_M68K_FC_SP);
325
326 /* assume that if this TLB entry ends up good for the supervisor,
327 it's good for the supervisor program function code: */
328 function_codes_mask = TME_BIT(TME_M68K_FC_SP);
329
330 /* if we're in the boot state: */
331 if (__tme_predict_false((sun2->tme_sun2_enable & TME_SUN2_ENA_NOTBOOT) == 0)) {
332
333 /* if this is the supervisor program function code: */
334 if (function_code == TME_M68K_FC_SP) {
335
336 /* fill this TLB entry directly from the obmem bus: */
337 (*sun2->tme_sun2_obmem->tme_bus_tlb_fill)
338 (sun2->tme_sun2_obmem,
339 tlb,
340 TME_SUN2_PROM_BASE | (address & (TME_SUN2_PROM_SIZE - 1)),
341 cycles);
342
343 /* create the mapping TLB entry: */
344 tlb_mapping.tme_bus_tlb_addr_first = address & (((tme_bus_addr32_t) 0) - TME_SUN2_PROM_SIZE);
345 tlb_mapping.tme_bus_tlb_addr_last = address | (TME_SUN2_PROM_SIZE - 1);
346 tlb_mapping.tme_bus_tlb_cycles_ok
347 = TME_BUS_CYCLE_READ;
348
349 /* map the filled TLB entry: */
350 tme_bus_tlb_map(tlb, TME_SUN2_PROM_BASE | (address & (TME_SUN2_PROM_SIZE - 1)), &tlb_mapping, address);
351
352 /* this is good for the supervisor program function code only: */
353 tlb_m68k->tme_m68k_tlb_function_codes_mask
354 = TME_BIT(TME_M68K_FC_SP);
355
356 /* done: */
357 return(TME_OK);
358 }
359
360 /* if this TLB entry ends up good for the supervisor, it's not
361 good for the supervisor program function code: */
362 function_codes_mask = 0;
363 }
364
365 /* start the access: */
366 access
367 = ((cycles & TME_BUS_CYCLE_WRITE)
368 ? TME_SUN_MMU_PTE_PROT_RW
369 : TME_SUN_MMU_PTE_PROT_RO);
370
371 /* if this is a user program or data function code: */
372 if (function_code == TME_M68K_FC_UD
373 || function_code == TME_M68K_FC_UP) {
374 context = sun2->tme_sun2_context_user;
375 access = TME_SUN_MMU_PTE_PROT_USER(access);
376 function_codes_mask = (TME_BIT(TME_M68K_FC_UD) + TME_BIT(TME_M68K_FC_UP));
377 }
378
379 /* otherwise, this is a supervisor program or data function code: */
380 else {
381 context = sun2->tme_sun2_context_system;
382 access = TME_SUN_MMU_PTE_PROT_SYSTEM(access);
383 function_codes_mask += TME_BIT(TME_M68K_FC_SD);
384 }
385
386 /* fill this TLB entry from the MMU: */
387 tlb_flags
388 = tme_sun_mmu_tlb_fill(sun2->tme_sun2_mmu,
389 tlb,
390 context,
391 address,
392 access);
393
394 /* TLB entries are good only for the program and data function
395 codes for the user or supervisor, but never both, because
396 the two types of accesses go through different contexts: */
397 tlb_m68k->tme_m68k_tlb_function_codes_mask = function_codes_mask;
398
399 return (TME_OK);
400 }
401
402 /* our bus TLB filler: */
403 int
_tme_sun2_bus_tlb_fill(struct tme_bus_connection * conn_bus,struct tme_bus_tlb * tlb,tme_bus_addr_t address_wider,unsigned int cycles)404 _tme_sun2_bus_tlb_fill(struct tme_bus_connection *conn_bus, struct tme_bus_tlb *tlb,
405 tme_bus_addr_t address_wider, unsigned int cycles)
406 {
407 struct tme_sun2 *sun2;
408 tme_bus_addr32_t address;
409 struct tme_sun2_bus_connection *conn_sun2;
410 tme_uint32_t base, size;
411 struct tme_bus_tlb tlb_bus;
412
413 /* recover our sun2: */
414 sun2 = (struct tme_sun2 *) conn_bus->tme_bus_connection.tme_connection_element->tme_element_private;
415
416 /* get the normal-width address: */
417 address = address_wider;
418 assert (address == address_wider);
419
420 /* recover the sun2 internal mainbus connection: */
421 conn_sun2 = (struct tme_sun2_bus_connection *) conn_bus;
422
423 /* turn the bus address into a DVMA address: */
424 switch (conn_sun2->tme_sun2_bus_connection_which) {
425
426 /* obio devices can actually see the whole address space: */
427 case TME_SUN2_BUS_OBIO:
428 base = 0x000000;
429 size = 0x1000000;
430 break;
431
432 case TME_SUN2_BUS_MBMEM:
433 base = 0xf00000;
434 size = TME_SUN2_DVMA_SIZE_MBMEM;
435 break;
436
437 case TME_SUN2_BUS_VME:
438 base = 0xf00000;
439 size = TME_SUN2_DVMA_SIZE_VME;
440 break;
441
442 default: abort();
443 }
444
445 assert (!(address & base)
446 && (address < size));
447
448 /* fill this TLB entry from the MMU: */
449 tme_sun_mmu_tlb_fill(sun2->tme_sun2_mmu,
450 tlb,
451 sun2->tme_sun2_context_system,
452 address | base,
453 ((cycles & TME_BUS_CYCLE_WRITE)
454 ? TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_RW)
455 : TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_RO)));
456
457 /* create the mapping TLB entry. we do this even if base == 0,
458 because the TLB entry as currently filled may cover more address
459 space than DVMA space on this machine is supposed to cover: */
460 tlb_bus.tme_bus_tlb_addr_first = 0;
461 tlb_bus.tme_bus_tlb_addr_last = size - 1;
462 tlb_bus.tme_bus_tlb_cycles_ok
463 = (TME_BUS_CYCLE_READ
464 | TME_BUS_CYCLE_WRITE);
465
466 /* map the filled TLB entry: */
467 tme_bus_tlb_map(tlb, address | base, &tlb_bus, address);
468
469 return (TME_OK);
470 }
471
472 /* our post-MMU TLB filler: */
473 static int
_tme_sun2_tlb_fill_mmu(void * _sun2,struct tme_bus_tlb * tlb,struct tme_sun_mmu_pte * pte,tme_uint32_t * _address,unsigned int cycles)474 _tme_sun2_tlb_fill_mmu(void *_sun2, struct tme_bus_tlb *tlb,
475 struct tme_sun_mmu_pte *pte,
476 tme_uint32_t *_address,
477 unsigned int cycles)
478 {
479 struct tme_sun2 *sun2;
480 tme_uint32_t address;
481 unsigned int bus_type;
482 struct tme_bus_connection *conn_bus;
483 tme_bus_fault_handler bus_fault_handler;
484 int rc;
485
486 /* recover our sun2: */
487 sun2 = (struct tme_sun2 *) _sun2;
488
489 /* get the physical page frame and bus type: */
490 address = ((pte->tme_sun_mmu_pte_raw & TME_SUN2_PTE_PGFRAME) << TME_SUN2_PAGE_SIZE_LOG2);
491 bus_type = (pte->tme_sun_mmu_pte_raw & TME_SUN2_PTE_PGTYPE) / (TME_SUN2_PTE_PGTYPE / TME_SUN2_PTE_PGTYPE_MASK);
492
493 /* any mapping of the *first* page of obio space means the PROM.
494 the virtual page frame is actually used to form the physical
495 address: */
496 if (address == 0
497 && bus_type == TME_SUN2_PGTYPE_OBIO) {
498 address = TME_SUN2_PROM_BASE | (*_address & ((TME_SUN2_PROM_SIZE - 1) & ~(TME_SUN2_PAGE_SIZE - 1)));
499 bus_type = TME_SUN2_PGTYPE_OBMEM;
500 }
501
502 /* add in the page offset to finish the address: */
503 address |= *_address & (TME_SUN2_PAGE_SIZE - 1);
504 *_address = address;
505
506 /* if this is obio: */
507 if (bus_type == TME_SUN2_PGTYPE_OBIO) {
508 conn_bus = sun2->tme_sun2_obio;
509 bus_fault_handler = _tme_sun2_obio_fault_handler;
510 }
511
512 /* if this is obmem: */
513 else if (bus_type == TME_SUN2_PGTYPE_OBMEM) {
514 conn_bus = sun2->tme_sun2_obmem;
515 bus_fault_handler = _tme_sun2_obmem_fault_handler;
516 }
517
518 /* if this is the VME bus: */
519 else if (sun2->tme_sun2_has_vme) {
520
521 if (bus_type == TME_SUN2_PGTYPE_VME8) {
522 address |= 0x800000;
523 }
524 else {
525 assert(bus_type == TME_SUN2_PGTYPE_VME0);
526 }
527
528 bus_fault_handler = _tme_sun2_vmebus_fault_handler;
529
530 /* TBD: */
531 abort();
532 }
533
534 /* if this is mbmem: */
535 else if (bus_type == TME_SUN2_PGTYPE_MBMEM) {
536 conn_bus = sun2->tme_sun2_mbmem;
537 bus_fault_handler = _tme_sun2_multibus_fault_handler;
538 }
539
540 /* otherwise, this is mbio: */
541 else {
542 assert(bus_type == TME_SUN2_PGTYPE_MBIO);
543 conn_bus = sun2->tme_sun2_mbio;
544 bus_fault_handler = _tme_sun2_multibus_fault_handler;
545 }
546
547 /* call the bus TLB filler: */
548 rc = ((*conn_bus->tme_bus_tlb_fill)
549 (conn_bus, tlb, address, cycles));
550
551 /* if the bus TLB filler succeeded, add our bus fault handler: */
552 if (rc == TME_OK) {
553 TME_BUS_TLB_FAULT_HANDLER(tlb, bus_fault_handler, sun2);
554 }
555
556 return (rc);
557 }
558
559 /* this gets a PTE from the MMU: */
560 int
_tme_sun2_mmu_pte_get(struct tme_sun2 * sun2,tme_uint32_t address,tme_uint32_t * _pte_sun2)561 _tme_sun2_mmu_pte_get(struct tme_sun2 *sun2, tme_uint32_t address, tme_uint32_t *_pte_sun2)
562 {
563 struct tme_sun_mmu_pte pte;
564 tme_uint32_t pte_sun2;
565 unsigned int pte_flags;
566 int rc;
567
568 /* get the PTE from the MMU: */
569 rc = tme_sun_mmu_pte_get(sun2->tme_sun2_mmu,
570 sun2->tme_sun2_context_user,
571 address,
572 &pte);
573 assert(rc == TME_OK);
574
575 /* form the Sun-2 PTE: */
576 pte_sun2 = pte.tme_sun_mmu_pte_raw;
577 pte_flags = pte.tme_sun_mmu_pte_flags;
578 if (pte_flags & TME_SUN_MMU_PTE_REF) {
579 pte_sun2 |= TME_SUN2_PTE_REF;
580 }
581 if (pte_flags & TME_SUN_MMU_PTE_MOD) {
582 pte_sun2 |= TME_SUN2_PTE_MOD;
583 }
584
585 /* done: */
586 *_pte_sun2 = pte_sun2;
587 tme_log(TME_SUN2_LOG_HANDLE(sun2), 1000, TME_OK,
588 (TME_SUN2_LOG_HANDLE(sun2),
589 _("pte_get: PGMAP[%d:0x%08x] -> 0x%08x"),
590 sun2->tme_sun2_context_user,
591 address,
592 pte_sun2));
593 return (TME_OK);
594 }
595
596 /* this sets a PTE into the MMU: */
597 int
_tme_sun2_mmu_pte_set(struct tme_sun2 * sun2,tme_uint32_t address,tme_uint32_t pte_sun2)598 _tme_sun2_mmu_pte_set(struct tme_sun2 *sun2, tme_uint32_t address, tme_uint32_t pte_sun2)
599 {
600 struct tme_sun_mmu_pte pte;
601 unsigned int pte_flags;
602 #ifndef TME_NO_LOG
603 const char *bus_name;
604 tme_bus_addr32_t physical_address;
605
606 /* this silences gcc -Wuninitialized: */
607 bus_name = NULL;
608
609 /* log this setting: */
610 physical_address = ((pte_sun2 & TME_SUN2_PTE_PGFRAME) << TME_SUN2_PAGE_SIZE_LOG2);
611 switch ((pte_sun2 & TME_SUN2_PTE_PGTYPE) / (TME_SUN2_PTE_PGTYPE / TME_SUN2_PTE_PGTYPE_MASK)) {
612 case TME_SUN2_PGTYPE_OBMEM: bus_name = "obmem"; break;
613 case TME_SUN2_PGTYPE_OBIO: bus_name = "obio"; break;
614 case TME_SUN2_PGTYPE_MBMEM:
615 if (sun2->tme_sun2_has_vme) {
616 bus_name = "VME";
617 }
618 else {
619 bus_name = "mbmem";
620 }
621 break;
622 case TME_SUN2_PGTYPE_MBIO:
623 if (sun2->tme_sun2_has_vme) {
624 bus_name = "VME";
625 physical_address |= 0x800000;
626 }
627 else {
628 bus_name = "mbio";
629 }
630 break;
631 }
632 tme_log(TME_SUN2_LOG_HANDLE(sun2), 1000, TME_OK,
633 (TME_SUN2_LOG_HANDLE(sun2),
634 _("pte_set: PGMAP[%d:0x%08x] <- 0x%08x (%s 0x%08x)"),
635 sun2->tme_sun2_context_user,
636 address,
637 pte_sun2,
638 bus_name,
639 physical_address));
640 #endif /* !TME_NO_LOG */
641
642 pte.tme_sun_mmu_pte_raw = pte_sun2;
643
644 pte_flags = 0;
645 if (pte_sun2 & TME_SUN2_PTE_MOD) {
646 pte_flags |= TME_SUN_MMU_PTE_MOD;
647 }
648 if (pte_sun2 & TME_SUN2_PTE_REF) {
649 pte_flags |= TME_SUN_MMU_PTE_REF;
650 }
651 switch (pte_sun2 & TME_SUN2_PTE_PROT) {
652
653 /* with this protection, the system can read and write,
654 and the user gets a protection error: */
655 case 0x70000000:
656 case 0x74000000:
657 case 0x60000000:
658 pte_flags |=
659 (TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_RW)
660 | TME_SUN_MMU_PTE_PROT_USER(TME_SUN_MMU_PTE_PROT_ERROR));
661 break;
662
663 /* with this protection, the system gets a protection error,
664 and the user gets a protection error: */
665 case 0x30000000:
666 case 0x20000000:
667 case 0x10000000:
668 case 0x00000000:
669 case 0x04000000:
670 pte_flags |=
671 (TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_ERROR)
672 | TME_SUN_MMU_PTE_PROT_USER(TME_SUN_MMU_PTE_PROT_ERROR));
673 break;
674
675 /* with this protection, the system can read and write,
676 and the user can read and write: */
677 case 0x7C000000:
678 case 0x6C000000:
679 pte_flags |=
680 (TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_RW)
681 | TME_SUN_MMU_PTE_PROT_USER(TME_SUN_MMU_PTE_PROT_RW));
682 break;
683
684 /* with this protection, the system can read and write,
685 and the user can read: */
686 case 0x78000000:
687 pte_flags |=
688 (TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_RW)
689 | TME_SUN_MMU_PTE_PROT_USER(TME_SUN_MMU_PTE_PROT_RO));
690 break;
691
692 /* with this protection, the system can read,
693 and the user can read: */
694 case 0x58000000:
695 pte_flags |=
696 (TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_RO)
697 | TME_SUN_MMU_PTE_PROT_USER(TME_SUN_MMU_PTE_PROT_RO));
698 break;
699
700 /* with this protection, the system can read,
701 and the user can read and write: */
702 case 0x5C000000:
703 case 0x4C000000:
704 pte_flags |=
705 (TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_RO)
706 | TME_SUN_MMU_PTE_PROT_USER(TME_SUN_MMU_PTE_PROT_RW));
707 break;
708
709 /* with this protection, the system can read,
710 and the user gets a protection error: */
711 case 0x50000000:
712 case 0x40000000:
713 pte_flags |=
714 (TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_RO)
715 | TME_SUN_MMU_PTE_PROT_USER(TME_SUN_MMU_PTE_PROT_ERROR));
716 break;
717
718 /* with this protection, the system gets a protection error,
719 and the user can read and write: */
720 case 0x3c000000:
721 case 0x0c000000:
722 pte_flags |=
723 (TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_ERROR)
724 | TME_SUN_MMU_PTE_PROT_USER(TME_SUN_MMU_PTE_PROT_RW));
725 break;
726
727 /* with this protection, the system gets a protection error,
728 and the user can read: */
729 case 0x08000000:
730 pte_flags |=
731 (TME_SUN_MMU_PTE_PROT_SYSTEM(TME_SUN_MMU_PTE_PROT_ERROR)
732 | TME_SUN_MMU_PTE_PROT_USER(TME_SUN_MMU_PTE_PROT_RO));
733 break;
734
735 default: abort();
736 }
737 if (pte_sun2 & TME_SUN2_PTE_VALID) {
738 pte_flags |= TME_SUN_MMU_PTE_VALID;
739 }
740 pte.tme_sun_mmu_pte_flags = pte_flags;
741
742 return (tme_sun_mmu_pte_set(sun2->tme_sun2_mmu,
743 sun2->tme_sun2_context_user,
744 address,
745 &pte));
746 }
747
748 /* this is called when the system context register is set: */
749 void
_tme_sun2_mmu_context_system_set(struct tme_sun2 * sun2)750 _tme_sun2_mmu_context_system_set(struct tme_sun2 *sun2)
751 {
752 /* system context register changes are assumed to be rare. if they
753 were frequent, we'd have to allocate 64 TLB sets for each TLB
754 user - one for each possible combination of user context and
755 system context. instead, when the system context register
756 changes, we simply invalidate all TLB entries everywhere: */
757 tme_log(TME_SUN2_LOG_HANDLE(sun2), 1000, TME_OK,
758 (TME_SUN2_LOG_HANDLE(sun2),
759 _("system context now #%d"),
760 sun2->tme_sun2_context_system));
761 tme_sun_mmu_tlbs_invalidate(sun2->tme_sun2_mmu);
762 }
763
764 /* this is called when the user context register is set: */
765 void
_tme_sun2_mmu_context_user_set(struct tme_sun2 * sun2)766 _tme_sun2_mmu_context_user_set(struct tme_sun2 *sun2)
767 {
768 tme_bus_context_t context_base;
769
770 /* NB that even though user and supervisor references use the two
771 different context registers simultaneously, TLB entries for one
772 are never usable by the other. because of this, and because we
773 assume that the system context register rarely changes, we choose
774 not to factor the system context into the context seen by the
775 m68k: */
776
777 /* there are sixteen total contexts. contexts zero through seven
778 are the not-boot (normal) contexts. contexts eight through
779 fifteen are the same contexts, but in the boot state.
780
781 in the boot state, TLB fills for supervisor program references
782 bypass the MMU and are filled to reference the PROM, and data
783 fills are filled as normal using the current context: */
784
785 /* in the not-boot (i.e., normal, state): */
786 if (__tme_predict_true(sun2->tme_sun2_enable & TME_SUN2_ENA_NOTBOOT)) {
787
788 tme_log(TME_SUN2_LOG_HANDLE(sun2), 1000, TME_OK,
789 (TME_SUN2_LOG_HANDLE(sun2),
790 _("user context now #%d"),
791 sun2->tme_sun2_context_user));
792
793 /* the normal state contexts are numbered from zero: */
794 context_base = 0;
795 }
796
797 /* in the boot state: */
798 else {
799
800 tme_log(TME_SUN2_LOG_HANDLE(sun2), 1000, TME_OK,
801 (TME_SUN2_LOG_HANDLE(sun2),
802 _("user context now #%d (boot state)"),
803 sun2->tme_sun2_context_user));
804
805 /* the boot state contexts are numbered from eight: */
806 context_base = TME_SUN2_CONTEXT_COUNT;
807 }
808
809 /* update the m68k bus context register: */
810 *sun2->tme_sun2_m68k_bus_context
811 = (context_base
812 + sun2->tme_sun2_context_user);
813
814 /* NB: unlike the sun3, sun2 DVMA TLBS are always filled using the
815 system context, meaning they don't need to be invalidated when
816 the user context changes, so we don't need to call
817 tme_sun_mmu_context_switched() here: */
818 }
819
820 /* this adds a new TLB set: */
821 int
_tme_sun2_mmu_tlb_set_add(struct tme_bus_connection * conn_bus_asker,struct tme_bus_tlb_set_info * tlb_set_info)822 _tme_sun2_mmu_tlb_set_add(struct tme_bus_connection *conn_bus_asker,
823 struct tme_bus_tlb_set_info *tlb_set_info)
824 {
825 struct tme_sun2 *sun2;
826 int rc;
827
828 /* recover our sun2: */
829 sun2 = (struct tme_sun2 *) conn_bus_asker->tme_bus_connection.tme_connection_element->tme_element_private;
830
831 /* add the TLB set to the MMU: */
832 rc = tme_sun_mmu_tlb_set_add(sun2->tme_sun2_mmu,
833 tlb_set_info);
834 assert (rc == TME_OK);
835
836 /* if this is the TLB set from the m68k: */
837 if (conn_bus_asker->tme_bus_connection.tme_connection_type == TME_CONNECTION_BUS_M68K) {
838
839 /* the m68k must expose a bus context register: */
840 assert (tlb_set_info->tme_bus_tlb_set_info_bus_context != NULL);
841
842 /* save the pointer to the m68k bus context register, and
843 initialize it: */
844 sun2->tme_sun2_m68k_bus_context
845 = tlb_set_info->tme_bus_tlb_set_info_bus_context;
846 _tme_sun2_mmu_context_user_set(sun2);
847
848 /* return the maximum context number. there are eight
849 contexts in the not-boot (normal) state, and each of
850 them has a boot state counterpart: */
851 tlb_set_info->tme_bus_tlb_set_info_bus_context_max
852 = (TME_SUN2_CONTEXT_COUNT
853 + TME_SUN2_CONTEXT_COUNT
854 - 1);
855 }
856
857 return (rc);
858 }
859
860 /* this creates a Sun-2 MMU: */
861 void
_tme_sun2_mmu_new(struct tme_sun2 * sun2)862 _tme_sun2_mmu_new(struct tme_sun2 *sun2)
863 {
864 struct tme_sun_mmu_info mmu_info;
865
866 memset(&mmu_info, 0, sizeof(mmu_info));
867 mmu_info.tme_sun_mmu_info_element = sun2->tme_sun2_element;
868 mmu_info.tme_sun_mmu_info_address_bits = 24;
869 mmu_info.tme_sun_mmu_info_pgoffset_bits = TME_SUN2_PAGE_SIZE_LOG2;
870 mmu_info.tme_sun_mmu_info_pteindex_bits = 4;
871 mmu_info.tme_sun_mmu_info_contexts = TME_SUN2_CONTEXT_COUNT;
872 mmu_info.tme_sun_mmu_info_pmegs = 256;
873 mmu_info.tme_sun_mmu_info_tlb_fill_private = sun2;
874 mmu_info.tme_sun_mmu_info_tlb_fill = _tme_sun2_tlb_fill_mmu;
875 mmu_info.tme_sun_mmu_info_proterr_private = sun2;
876 mmu_info.tme_sun_mmu_info_proterr = _tme_sun2_mmu_proterr;
877 mmu_info.tme_sun_mmu_info_invalid_private = sun2;
878 mmu_info.tme_sun_mmu_info_invalid = _tme_sun2_mmu_invalid;
879 sun2->tme_sun2_mmu = tme_sun_mmu_new(&mmu_info);
880 }
881