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