xref: /qemu/target/sparc/mmu_helper.c (revision 74781c08)
1 /*
2  *  Sparc MMU helpers
3  *
4  *  Copyright (c) 2003-2005 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "qemu/osdep.h"
21 #include "qemu/log.h"
22 #include "cpu.h"
23 #include "exec/exec-all.h"
24 #include "exec/page-protection.h"
25 #include "qemu/qemu-print.h"
26 #include "trace.h"
27 
28 /* Sparc MMU emulation */
29 
30 #ifndef TARGET_SPARC64
31 /*
32  * Sparc V8 Reference MMU (SRMMU)
33  */
34 static const int access_table[8][8] = {
35     { 0, 0, 0, 0, 8, 0, 12, 12 },
36     { 0, 0, 0, 0, 8, 0, 0, 0 },
37     { 8, 8, 0, 0, 0, 8, 12, 12 },
38     { 8, 8, 0, 0, 0, 8, 0, 0 },
39     { 8, 0, 8, 0, 8, 8, 12, 12 },
40     { 8, 0, 8, 0, 8, 0, 8, 0 },
41     { 8, 8, 8, 0, 8, 8, 12, 12 },
42     { 8, 8, 8, 0, 8, 8, 8, 0 }
43 };
44 
45 static const int perm_table[2][8] = {
46     {
47         PAGE_READ,
48         PAGE_READ | PAGE_WRITE,
49         PAGE_READ | PAGE_EXEC,
50         PAGE_READ | PAGE_WRITE | PAGE_EXEC,
51         PAGE_EXEC,
52         PAGE_READ | PAGE_WRITE,
53         PAGE_READ | PAGE_EXEC,
54         PAGE_READ | PAGE_WRITE | PAGE_EXEC
55     },
56     {
57         PAGE_READ,
58         PAGE_READ | PAGE_WRITE,
59         PAGE_READ | PAGE_EXEC,
60         PAGE_READ | PAGE_WRITE | PAGE_EXEC,
61         PAGE_EXEC,
62         PAGE_READ,
63         0,
64         0,
65     }
66 };
67 
get_physical_address(CPUSPARCState * env,CPUTLBEntryFull * full,int * access_index,target_ulong address,int rw,int mmu_idx)68 static int get_physical_address(CPUSPARCState *env, CPUTLBEntryFull *full,
69                                 int *access_index, target_ulong address,
70                                 int rw, int mmu_idx)
71 {
72     int access_perms = 0;
73     hwaddr pde_ptr;
74     uint32_t pde;
75     int error_code = 0, is_dirty, is_user;
76     unsigned long page_offset;
77     CPUState *cs = env_cpu(env);
78     MemTxResult result;
79 
80     is_user = mmu_idx == MMU_USER_IDX;
81 
82     if (mmu_idx == MMU_PHYS_IDX) {
83         full->lg_page_size = TARGET_PAGE_BITS;
84         /* Boot mode: instruction fetches are taken from PROM */
85         if (rw == 2 && (env->mmuregs[0] & env->def.mmu_bm)) {
86             full->phys_addr = env->prom_addr | (address & 0x7ffffULL);
87             full->prot = PAGE_READ | PAGE_EXEC;
88             return 0;
89         }
90         full->phys_addr = address;
91         full->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
92         return 0;
93     }
94 
95     *access_index = ((rw & 1) << 2) | (rw & 2) | (is_user ? 0 : 1);
96     full->phys_addr = 0xffffffffffff0000ULL;
97 
98     /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
99     /* Context base + context number */
100     pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
101     pde = address_space_ldl(cs->as, pde_ptr, MEMTXATTRS_UNSPECIFIED, &result);
102     if (result != MEMTX_OK) {
103         return 4 << 2; /* Translation fault, L = 0 */
104     }
105 
106     /* Ctx pde */
107     switch (pde & PTE_ENTRYTYPE_MASK) {
108     default:
109     case 0: /* Invalid */
110         return 1 << 2;
111     case 2: /* L0 PTE, maybe should not happen? */
112     case 3: /* Reserved */
113         return 4 << 2;
114     case 1: /* L0 PDE */
115         pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
116         pde = address_space_ldl(cs->as, pde_ptr,
117                                 MEMTXATTRS_UNSPECIFIED, &result);
118         if (result != MEMTX_OK) {
119             return (1 << 8) | (4 << 2); /* Translation fault, L = 1 */
120         }
121 
122         switch (pde & PTE_ENTRYTYPE_MASK) {
123         default:
124         case 0: /* Invalid */
125             return (1 << 8) | (1 << 2);
126         case 3: /* Reserved */
127             return (1 << 8) | (4 << 2);
128         case 1: /* L1 PDE */
129             pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
130             pde = address_space_ldl(cs->as, pde_ptr,
131                                     MEMTXATTRS_UNSPECIFIED, &result);
132             if (result != MEMTX_OK) {
133                 return (2 << 8) | (4 << 2); /* Translation fault, L = 2 */
134             }
135 
136             switch (pde & PTE_ENTRYTYPE_MASK) {
137             default:
138             case 0: /* Invalid */
139                 return (2 << 8) | (1 << 2);
140             case 3: /* Reserved */
141                 return (2 << 8) | (4 << 2);
142             case 1: /* L2 PDE */
143                 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
144                 pde = address_space_ldl(cs->as, pde_ptr,
145                                         MEMTXATTRS_UNSPECIFIED, &result);
146                 if (result != MEMTX_OK) {
147                     return (3 << 8) | (4 << 2); /* Translation fault, L = 3 */
148                 }
149 
150                 switch (pde & PTE_ENTRYTYPE_MASK) {
151                 default:
152                 case 0: /* Invalid */
153                     return (3 << 8) | (1 << 2);
154                 case 1: /* PDE, should not happen */
155                 case 3: /* Reserved */
156                     return (3 << 8) | (4 << 2);
157                 case 2: /* L3 PTE */
158                     page_offset = 0;
159                 }
160                 full->lg_page_size = TARGET_PAGE_BITS;
161                 break;
162             case 2: /* L2 PTE */
163                 page_offset = address & 0x3f000;
164                 full->lg_page_size = 18;
165             }
166             break;
167         case 2: /* L1 PTE */
168             page_offset = address & 0xfff000;
169             full->lg_page_size = 24;
170             break;
171         }
172     }
173 
174     /* check access */
175     access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
176     error_code = access_table[*access_index][access_perms];
177     if (error_code && !((env->mmuregs[0] & MMU_NF) && is_user)) {
178         return error_code;
179     }
180 
181     /* update page modified and dirty bits */
182     is_dirty = (rw & 1) && !(pde & PG_MODIFIED_MASK);
183     if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
184         pde |= PG_ACCESSED_MASK;
185         if (is_dirty) {
186             pde |= PG_MODIFIED_MASK;
187         }
188         stl_phys_notdirty(cs->as, pde_ptr, pde);
189     }
190 
191     /* the page can be put in the TLB */
192     full->prot = perm_table[is_user][access_perms];
193     if (!(pde & PG_MODIFIED_MASK)) {
194         /* only set write access if already dirty... otherwise wait
195            for dirty access */
196         full->prot &= ~PAGE_WRITE;
197     }
198 
199     /* Even if large ptes, we map only one 4KB page in the cache to
200        avoid filling it too fast */
201     full->phys_addr = ((hwaddr)(pde & PTE_ADDR_MASK) << 4) + page_offset;
202     return error_code;
203 }
204 
205 /* Perform address translation */
sparc_cpu_tlb_fill(CPUState * cs,vaddr address,int size,MMUAccessType access_type,int mmu_idx,bool probe,uintptr_t retaddr)206 bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
207                         MMUAccessType access_type, int mmu_idx,
208                         bool probe, uintptr_t retaddr)
209 {
210     CPUSPARCState *env = cpu_env(cs);
211     CPUTLBEntryFull full = {};
212     target_ulong vaddr;
213     int error_code = 0, access_index;
214 
215     /*
216      * TODO: If we ever need tlb_vaddr_to_host for this target,
217      * then we must figure out how to manipulate FSR and FAR
218      * when both MMU_NF and probe are set.  In the meantime,
219      * do not support this use case.
220      */
221     assert(!probe);
222 
223     address &= TARGET_PAGE_MASK;
224     error_code = get_physical_address(env, &full, &access_index,
225                                       address, access_type, mmu_idx);
226     vaddr = address;
227     if (likely(error_code == 0)) {
228         qemu_log_mask(CPU_LOG_MMU,
229                       "Translate at %" VADDR_PRIx " -> "
230                       HWADDR_FMT_plx ", vaddr " TARGET_FMT_lx "\n",
231                       address, full.phys_addr, vaddr);
232         tlb_set_page_full(cs, mmu_idx, vaddr, &full);
233         return true;
234     }
235 
236     if (env->mmuregs[3]) { /* Fault status register */
237         env->mmuregs[3] = 1; /* overflow (not read before another fault) */
238     }
239     env->mmuregs[3] |= (access_index << 5) | error_code | 2;
240     env->mmuregs[4] = address; /* Fault address register */
241 
242     if ((env->mmuregs[0] & MMU_NF) || env->psret == 0)  {
243         /* No fault mode: if a mapping is available, just override
244            permissions. If no mapping is available, redirect accesses to
245            neverland. Fake/overridden mappings will be flushed when
246            switching to normal mode. */
247         full.prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
248         tlb_set_page_full(cs, mmu_idx, vaddr, &full);
249         return true;
250     } else {
251         if (access_type == MMU_INST_FETCH) {
252             cs->exception_index = TT_TFAULT;
253         } else {
254             cs->exception_index = TT_DFAULT;
255         }
256         cpu_loop_exit_restore(cs, retaddr);
257     }
258 }
259 
mmu_probe(CPUSPARCState * env,target_ulong address,int mmulev)260 target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev)
261 {
262     CPUState *cs = env_cpu(env);
263     hwaddr pde_ptr;
264     uint32_t pde;
265     MemTxResult result;
266 
267     /*
268      * TODO: MMU probe operations are supposed to set the fault
269      * status registers, but we don't do this.
270      */
271 
272     /* Context base + context number */
273     pde_ptr = (hwaddr)(env->mmuregs[1] << 4) +
274         (env->mmuregs[2] << 2);
275     pde = address_space_ldl(cs->as, pde_ptr, MEMTXATTRS_UNSPECIFIED, &result);
276     if (result != MEMTX_OK) {
277         return 0;
278     }
279 
280     switch (pde & PTE_ENTRYTYPE_MASK) {
281     default:
282     case 0: /* Invalid */
283     case 2: /* PTE, maybe should not happen? */
284     case 3: /* Reserved */
285         return 0;
286     case 1: /* L1 PDE */
287         if (mmulev == 3) {
288             return pde;
289         }
290         pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
291         pde = address_space_ldl(cs->as, pde_ptr,
292                                 MEMTXATTRS_UNSPECIFIED, &result);
293         if (result != MEMTX_OK) {
294             return 0;
295         }
296 
297         switch (pde & PTE_ENTRYTYPE_MASK) {
298         default:
299         case 0: /* Invalid */
300         case 3: /* Reserved */
301             return 0;
302         case 2: /* L1 PTE */
303             return pde;
304         case 1: /* L2 PDE */
305             if (mmulev == 2) {
306                 return pde;
307             }
308             pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
309             pde = address_space_ldl(cs->as, pde_ptr,
310                                     MEMTXATTRS_UNSPECIFIED, &result);
311             if (result != MEMTX_OK) {
312                 return 0;
313             }
314 
315             switch (pde & PTE_ENTRYTYPE_MASK) {
316             default:
317             case 0: /* Invalid */
318             case 3: /* Reserved */
319                 return 0;
320             case 2: /* L2 PTE */
321                 return pde;
322             case 1: /* L3 PDE */
323                 if (mmulev == 1) {
324                     return pde;
325                 }
326                 pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
327                 pde = address_space_ldl(cs->as, pde_ptr,
328                                         MEMTXATTRS_UNSPECIFIED, &result);
329                 if (result != MEMTX_OK) {
330                     return 0;
331                 }
332 
333                 switch (pde & PTE_ENTRYTYPE_MASK) {
334                 default:
335                 case 0: /* Invalid */
336                 case 1: /* PDE, should not happen */
337                 case 3: /* Reserved */
338                     return 0;
339                 case 2: /* L3 PTE */
340                     return pde;
341                 }
342             }
343         }
344     }
345     return 0;
346 }
347 
dump_mmu(CPUSPARCState * env)348 void dump_mmu(CPUSPARCState *env)
349 {
350     CPUState *cs = env_cpu(env);
351     target_ulong va, va1, va2;
352     unsigned int n, m, o;
353     hwaddr pa;
354     uint32_t pde;
355 
356     qemu_printf("Root ptr: " HWADDR_FMT_plx ", ctx: %d\n",
357                 (hwaddr)env->mmuregs[1] << 4, env->mmuregs[2]);
358     for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
359         pde = mmu_probe(env, va, 2);
360         if (pde) {
361             pa = cpu_get_phys_page_debug(cs, va);
362             qemu_printf("VA: " TARGET_FMT_lx ", PA: " HWADDR_FMT_plx
363                         " PDE: " TARGET_FMT_lx "\n", va, pa, pde);
364             for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
365                 pde = mmu_probe(env, va1, 1);
366                 if (pde) {
367                     pa = cpu_get_phys_page_debug(cs, va1);
368                     qemu_printf(" VA: " TARGET_FMT_lx ", PA: "
369                                 HWADDR_FMT_plx " PDE: " TARGET_FMT_lx "\n",
370                                 va1, pa, pde);
371                     for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
372                         pde = mmu_probe(env, va2, 0);
373                         if (pde) {
374                             pa = cpu_get_phys_page_debug(cs, va2);
375                             qemu_printf("  VA: " TARGET_FMT_lx ", PA: "
376                                         HWADDR_FMT_plx " PTE: "
377                                         TARGET_FMT_lx "\n",
378                                         va2, pa, pde);
379                         }
380                     }
381                 }
382             }
383         }
384     }
385 }
386 
387 /* Gdb expects all registers windows to be flushed in ram. This function handles
388  * reads (and only reads) in stack frames as if windows were flushed. We assume
389  * that the sparc ABI is followed.
390  */
sparc_cpu_memory_rw_debug(CPUState * cs,vaddr address,uint8_t * buf,int len,bool is_write)391 int sparc_cpu_memory_rw_debug(CPUState *cs, vaddr address,
392                               uint8_t *buf, int len, bool is_write)
393 {
394     CPUSPARCState *env = cpu_env(cs);
395     target_ulong addr = address;
396     int i;
397     int len1;
398     int cwp = env->cwp;
399 
400     if (!is_write) {
401         for (i = 0; i < env->nwindows; i++) {
402             int off;
403             target_ulong fp = env->regbase[cwp * 16 + 22];
404 
405             /* Assume fp == 0 means end of frame.  */
406             if (fp == 0) {
407                 break;
408             }
409 
410             cwp = cpu_cwp_inc(env, cwp + 1);
411 
412             /* Invalid window ? */
413             if (env->wim & (1 << cwp)) {
414                 break;
415             }
416 
417             /* According to the ABI, the stack is growing downward.  */
418             if (addr + len < fp) {
419                 break;
420             }
421 
422             /* Not in this frame.  */
423             if (addr > fp + 64) {
424                 continue;
425             }
426 
427             /* Handle access before this window.  */
428             if (addr < fp) {
429                 len1 = fp - addr;
430                 if (cpu_memory_rw_debug(cs, addr, buf, len1, is_write) != 0) {
431                     return -1;
432                 }
433                 addr += len1;
434                 len -= len1;
435                 buf += len1;
436             }
437 
438             /* Access byte per byte to registers. Not very efficient but speed
439              * is not critical.
440              */
441             off = addr - fp;
442             len1 = 64 - off;
443 
444             if (len1 > len) {
445                 len1 = len;
446             }
447 
448             for (; len1; len1--) {
449                 int reg = cwp * 16 + 8 + (off >> 2);
450                 union {
451                     uint32_t v;
452                     uint8_t c[4];
453                 } u;
454                 u.v = cpu_to_be32(env->regbase[reg]);
455                 *buf++ = u.c[off & 3];
456                 addr++;
457                 len--;
458                 off++;
459             }
460 
461             if (len == 0) {
462                 return 0;
463             }
464         }
465     }
466     return cpu_memory_rw_debug(cs, addr, buf, len, is_write);
467 }
468 
469 #else /* !TARGET_SPARC64 */
470 
471 /* 41 bit physical address space */
ultrasparc_truncate_physical(uint64_t x)472 static inline hwaddr ultrasparc_truncate_physical(uint64_t x)
473 {
474     return x & 0x1ffffffffffULL;
475 }
476 
477 /*
478  * UltraSparc IIi I/DMMUs
479  */
480 
481 /* Returns true if TTE tag is valid and matches virtual address value
482    in context requires virtual address mask value calculated from TTE
483    entry size */
ultrasparc_tag_match(SparcTLBEntry * tlb,uint64_t address,uint64_t context,hwaddr * physical)484 static inline int ultrasparc_tag_match(SparcTLBEntry *tlb,
485                                        uint64_t address, uint64_t context,
486                                        hwaddr *physical)
487 {
488     uint64_t mask = -(8192ULL << 3 * TTE_PGSIZE(tlb->tte));
489 
490     /* valid, context match, virtual address match? */
491     if (TTE_IS_VALID(tlb->tte) &&
492         (TTE_IS_GLOBAL(tlb->tte) || tlb_compare_context(tlb, context))
493         && compare_masked(address, tlb->tag, mask)) {
494         /* decode physical address */
495         *physical = ((tlb->tte & mask) | (address & ~mask)) & 0x1ffffffe000ULL;
496         return 1;
497     }
498 
499     return 0;
500 }
501 
build_sfsr(CPUSPARCState * env,int mmu_idx,int rw)502 static uint64_t build_sfsr(CPUSPARCState *env, int mmu_idx, int rw)
503 {
504     uint64_t sfsr = SFSR_VALID_BIT;
505 
506     switch (mmu_idx) {
507     case MMU_PHYS_IDX:
508         sfsr |= SFSR_CT_NOTRANS;
509         break;
510     case MMU_USER_IDX:
511     case MMU_KERNEL_IDX:
512         sfsr |= SFSR_CT_PRIMARY;
513         break;
514     case MMU_USER_SECONDARY_IDX:
515     case MMU_KERNEL_SECONDARY_IDX:
516         sfsr |= SFSR_CT_SECONDARY;
517         break;
518     case MMU_NUCLEUS_IDX:
519         sfsr |= SFSR_CT_NUCLEUS;
520         break;
521     default:
522         g_assert_not_reached();
523     }
524 
525     if (rw == 1) {
526         sfsr |= SFSR_WRITE_BIT;
527     } else if (rw == 4) {
528         sfsr |= SFSR_NF_BIT;
529     }
530 
531     if (env->pstate & PS_PRIV) {
532         sfsr |= SFSR_PR_BIT;
533     }
534 
535     if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */
536         sfsr |= SFSR_OW_BIT; /* overflow (not read before another fault) */
537     }
538 
539     /* FIXME: ASI field in SFSR must be set */
540 
541     return sfsr;
542 }
543 
get_physical_address_data(CPUSPARCState * env,CPUTLBEntryFull * full,target_ulong address,int rw,int mmu_idx)544 static int get_physical_address_data(CPUSPARCState *env, CPUTLBEntryFull *full,
545                                      target_ulong address, int rw, int mmu_idx)
546 {
547     CPUState *cs = env_cpu(env);
548     unsigned int i;
549     uint64_t sfsr;
550     uint64_t context;
551     bool is_user = false;
552 
553     sfsr = build_sfsr(env, mmu_idx, rw);
554 
555     switch (mmu_idx) {
556     case MMU_PHYS_IDX:
557         g_assert_not_reached();
558     case MMU_USER_IDX:
559         is_user = true;
560         /* fallthru */
561     case MMU_KERNEL_IDX:
562         context = env->dmmu.mmu_primary_context & 0x1fff;
563         break;
564     case MMU_USER_SECONDARY_IDX:
565         is_user = true;
566         /* fallthru */
567     case MMU_KERNEL_SECONDARY_IDX:
568         context = env->dmmu.mmu_secondary_context & 0x1fff;
569         break;
570     default:
571         context = 0;
572         break;
573     }
574 
575     for (i = 0; i < 64; i++) {
576         /* ctx match, vaddr match, valid? */
577         if (ultrasparc_tag_match(&env->dtlb[i], address, context,
578                                  &full->phys_addr)) {
579             int do_fault = 0;
580 
581             if (TTE_IS_IE(env->dtlb[i].tte)) {
582                 full->tlb_fill_flags |= TLB_BSWAP;
583             }
584 
585             /* access ok? */
586             /* multiple bits in SFSR.FT may be set on TT_DFAULT */
587             if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) {
588                 do_fault = 1;
589                 sfsr |= SFSR_FT_PRIV_BIT; /* privilege violation */
590                 trace_mmu_helper_dfault(address, context, mmu_idx, env->tl);
591             }
592             if (rw == 4) {
593                 if (TTE_IS_SIDEEFFECT(env->dtlb[i].tte)) {
594                     do_fault = 1;
595                     sfsr |= SFSR_FT_NF_E_BIT;
596                 }
597             } else {
598                 if (TTE_IS_NFO(env->dtlb[i].tte)) {
599                     do_fault = 1;
600                     sfsr |= SFSR_FT_NFO_BIT;
601                 }
602             }
603 
604             if (do_fault) {
605                 /* faults above are reported with TT_DFAULT. */
606                 cs->exception_index = TT_DFAULT;
607             } else if (!TTE_IS_W_OK(env->dtlb[i].tte) && (rw == 1)) {
608                 do_fault = 1;
609                 cs->exception_index = TT_DPROT;
610 
611                 trace_mmu_helper_dprot(address, context, mmu_idx, env->tl);
612             }
613 
614             if (!do_fault) {
615                 full->prot = PAGE_READ;
616                 if (TTE_IS_W_OK(env->dtlb[i].tte)) {
617                     full->prot |= PAGE_WRITE;
618                 }
619 
620                 TTE_SET_USED(env->dtlb[i].tte);
621 
622                 return 0;
623             }
624 
625             env->dmmu.sfsr = sfsr;
626             env->dmmu.sfar = address; /* Fault address register */
627             env->dmmu.tag_access = (address & ~0x1fffULL) | context;
628             return 1;
629         }
630     }
631 
632     trace_mmu_helper_dmiss(address, context);
633 
634     /*
635      * On MMU misses:
636      * - UltraSPARC IIi: SFSR and SFAR unmodified
637      * - JPS1: SFAR updated and some fields of SFSR updated
638      */
639     env->dmmu.tag_access = (address & ~0x1fffULL) | context;
640     cs->exception_index = TT_DMISS;
641     return 1;
642 }
643 
get_physical_address_code(CPUSPARCState * env,CPUTLBEntryFull * full,target_ulong address,int mmu_idx)644 static int get_physical_address_code(CPUSPARCState *env, CPUTLBEntryFull *full,
645                                      target_ulong address, int mmu_idx)
646 {
647     CPUState *cs = env_cpu(env);
648     unsigned int i;
649     uint64_t context;
650     bool is_user = false;
651 
652     switch (mmu_idx) {
653     case MMU_PHYS_IDX:
654     case MMU_USER_SECONDARY_IDX:
655     case MMU_KERNEL_SECONDARY_IDX:
656         g_assert_not_reached();
657     case MMU_USER_IDX:
658         is_user = true;
659         /* fallthru */
660     case MMU_KERNEL_IDX:
661         context = env->dmmu.mmu_primary_context & 0x1fff;
662         break;
663     default:
664         context = 0;
665         break;
666     }
667 
668     if (env->tl == 0) {
669         /* PRIMARY context */
670         context = env->dmmu.mmu_primary_context & 0x1fff;
671     } else {
672         /* NUCLEUS context */
673         context = 0;
674     }
675 
676     for (i = 0; i < 64; i++) {
677         /* ctx match, vaddr match, valid? */
678         if (ultrasparc_tag_match(&env->itlb[i],
679                                  address, context, &full->phys_addr)) {
680             /* access ok? */
681             if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) {
682                 /* Fault status register */
683                 if (env->immu.sfsr & SFSR_VALID_BIT) {
684                     env->immu.sfsr = SFSR_OW_BIT; /* overflow (not read before
685                                                      another fault) */
686                 } else {
687                     env->immu.sfsr = 0;
688                 }
689                 if (env->pstate & PS_PRIV) {
690                     env->immu.sfsr |= SFSR_PR_BIT;
691                 }
692                 if (env->tl > 0) {
693                     env->immu.sfsr |= SFSR_CT_NUCLEUS;
694                 }
695 
696                 /* FIXME: ASI field in SFSR must be set */
697                 env->immu.sfsr |= SFSR_FT_PRIV_BIT | SFSR_VALID_BIT;
698                 cs->exception_index = TT_TFAULT;
699 
700                 env->immu.tag_access = (address & ~0x1fffULL) | context;
701 
702                 trace_mmu_helper_tfault(address, context);
703 
704                 return 1;
705             }
706             full->prot = PAGE_EXEC;
707             TTE_SET_USED(env->itlb[i].tte);
708             return 0;
709         }
710     }
711 
712     trace_mmu_helper_tmiss(address, context);
713 
714     /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
715     env->immu.tag_access = (address & ~0x1fffULL) | context;
716     cs->exception_index = TT_TMISS;
717     return 1;
718 }
719 
get_physical_address(CPUSPARCState * env,CPUTLBEntryFull * full,int * access_index,target_ulong address,int rw,int mmu_idx)720 static int get_physical_address(CPUSPARCState *env, CPUTLBEntryFull *full,
721                                 int *access_index, target_ulong address,
722                                 int rw, int mmu_idx)
723 {
724     /* ??? We treat everything as a small page, then explicitly flush
725        everything when an entry is evicted.  */
726     full->lg_page_size = TARGET_PAGE_BITS;
727 
728     /* safety net to catch wrong softmmu index use from dynamic code */
729     if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
730         if (rw == 2) {
731             trace_mmu_helper_get_phys_addr_code(env->tl, mmu_idx,
732                                                 env->dmmu.mmu_primary_context,
733                                                 env->dmmu.mmu_secondary_context,
734                                                 address);
735         } else {
736             trace_mmu_helper_get_phys_addr_data(env->tl, mmu_idx,
737                                                 env->dmmu.mmu_primary_context,
738                                                 env->dmmu.mmu_secondary_context,
739                                                 address);
740         }
741     }
742 
743     if (mmu_idx == MMU_PHYS_IDX) {
744         full->phys_addr = ultrasparc_truncate_physical(address);
745         full->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
746         return 0;
747     }
748 
749     if (rw == 2) {
750         return get_physical_address_code(env, full, address, mmu_idx);
751     } else {
752         return get_physical_address_data(env, full, address, rw, mmu_idx);
753     }
754 }
755 
756 /* Perform address translation */
sparc_cpu_tlb_fill(CPUState * cs,vaddr address,int size,MMUAccessType access_type,int mmu_idx,bool probe,uintptr_t retaddr)757 bool sparc_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
758                         MMUAccessType access_type, int mmu_idx,
759                         bool probe, uintptr_t retaddr)
760 {
761     CPUSPARCState *env = cpu_env(cs);
762     CPUTLBEntryFull full = {};
763     int error_code = 0, access_index;
764 
765     address &= TARGET_PAGE_MASK;
766     error_code = get_physical_address(env, &full, &access_index,
767                                       address, access_type, mmu_idx);
768     if (likely(error_code == 0)) {
769         trace_mmu_helper_mmu_fault(address, full.phys_addr, mmu_idx, env->tl,
770                                    env->dmmu.mmu_primary_context,
771                                    env->dmmu.mmu_secondary_context);
772         tlb_set_page_full(cs, mmu_idx, address, &full);
773         return true;
774     }
775     if (probe) {
776         return false;
777     }
778     cpu_loop_exit_restore(cs, retaddr);
779 }
780 
dump_mmu(CPUSPARCState * env)781 void dump_mmu(CPUSPARCState *env)
782 {
783     unsigned int i;
784     const char *mask;
785 
786     qemu_printf("MMU contexts: Primary: %" PRId64 ", Secondary: %"
787                 PRId64 "\n",
788                 env->dmmu.mmu_primary_context,
789                 env->dmmu.mmu_secondary_context);
790     qemu_printf("DMMU Tag Access: %" PRIx64 ", TSB Tag Target: %" PRIx64
791                 "\n", env->dmmu.tag_access, env->dmmu.tsb_tag_target);
792     if ((env->lsu & DMMU_E) == 0) {
793         qemu_printf("DMMU disabled\n");
794     } else {
795         qemu_printf("DMMU dump\n");
796         for (i = 0; i < 64; i++) {
797             switch (TTE_PGSIZE(env->dtlb[i].tte)) {
798             default:
799             case 0x0:
800                 mask = "  8k";
801                 break;
802             case 0x1:
803                 mask = " 64k";
804                 break;
805             case 0x2:
806                 mask = "512k";
807                 break;
808             case 0x3:
809                 mask = "  4M";
810                 break;
811             }
812             if (TTE_IS_VALID(env->dtlb[i].tte)) {
813                 qemu_printf("[%02u] VA: %" PRIx64 ", PA: %llx"
814                             ", %s, %s, %s, %s, ie %s, ctx %" PRId64 " %s\n",
815                             i,
816                             env->dtlb[i].tag & (uint64_t)~0x1fffULL,
817                             TTE_PA(env->dtlb[i].tte),
818                             mask,
819                             TTE_IS_PRIV(env->dtlb[i].tte) ? "priv" : "user",
820                             TTE_IS_W_OK(env->dtlb[i].tte) ? "RW" : "RO",
821                             TTE_IS_LOCKED(env->dtlb[i].tte) ?
822                             "locked" : "unlocked",
823                             TTE_IS_IE(env->dtlb[i].tte) ?
824                             "yes" : "no",
825                             env->dtlb[i].tag & (uint64_t)0x1fffULL,
826                             TTE_IS_GLOBAL(env->dtlb[i].tte) ?
827                             "global" : "local");
828             }
829         }
830     }
831     if ((env->lsu & IMMU_E) == 0) {
832         qemu_printf("IMMU disabled\n");
833     } else {
834         qemu_printf("IMMU dump\n");
835         for (i = 0; i < 64; i++) {
836             switch (TTE_PGSIZE(env->itlb[i].tte)) {
837             default:
838             case 0x0:
839                 mask = "  8k";
840                 break;
841             case 0x1:
842                 mask = " 64k";
843                 break;
844             case 0x2:
845                 mask = "512k";
846                 break;
847             case 0x3:
848                 mask = "  4M";
849                 break;
850             }
851             if (TTE_IS_VALID(env->itlb[i].tte)) {
852                 qemu_printf("[%02u] VA: %" PRIx64 ", PA: %llx"
853                             ", %s, %s, %s, ctx %" PRId64 " %s\n",
854                             i,
855                             env->itlb[i].tag & (uint64_t)~0x1fffULL,
856                             TTE_PA(env->itlb[i].tte),
857                             mask,
858                             TTE_IS_PRIV(env->itlb[i].tte) ? "priv" : "user",
859                             TTE_IS_LOCKED(env->itlb[i].tte) ?
860                             "locked" : "unlocked",
861                             env->itlb[i].tag & (uint64_t)0x1fffULL,
862                             TTE_IS_GLOBAL(env->itlb[i].tte) ?
863                             "global" : "local");
864             }
865         }
866     }
867 }
868 
869 #endif /* TARGET_SPARC64 */
870 
cpu_sparc_get_phys_page(CPUSPARCState * env,hwaddr * phys,target_ulong addr,int rw,int mmu_idx)871 static int cpu_sparc_get_phys_page(CPUSPARCState *env, hwaddr *phys,
872                                    target_ulong addr, int rw, int mmu_idx)
873 {
874     CPUTLBEntryFull full = {};
875     int access_index, ret;
876 
877     ret = get_physical_address(env, &full, &access_index, addr, rw, mmu_idx);
878     if (ret == 0) {
879         *phys = full.phys_addr;
880     }
881     return ret;
882 }
883 
884 #if defined(TARGET_SPARC64)
cpu_get_phys_page_nofault(CPUSPARCState * env,target_ulong addr,int mmu_idx)885 hwaddr cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong addr,
886                                            int mmu_idx)
887 {
888     hwaddr phys_addr;
889 
890     if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 4, mmu_idx) != 0) {
891         return -1;
892     }
893     return phys_addr;
894 }
895 #endif
896 
sparc_cpu_get_phys_page_debug(CPUState * cs,vaddr addr)897 hwaddr sparc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
898 {
899     CPUSPARCState *env = cpu_env(cs);
900     hwaddr phys_addr;
901     int mmu_idx = cpu_mmu_index(cs, false);
902 
903     if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 2, mmu_idx) != 0) {
904         if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) {
905             return -1;
906         }
907     }
908     return phys_addr;
909 }
910 
sparc_cpu_do_unaligned_access(CPUState * cs,vaddr addr,MMUAccessType access_type,int mmu_idx,uintptr_t retaddr)911 G_NORETURN void sparc_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
912                                               MMUAccessType access_type,
913                                               int mmu_idx,
914                                               uintptr_t retaddr)
915 {
916     CPUSPARCState *env = cpu_env(cs);
917 
918 #ifdef TARGET_SPARC64
919     env->dmmu.sfsr = build_sfsr(env, mmu_idx, access_type);
920     env->dmmu.sfar = addr;
921 #else
922     env->mmuregs[4] = addr;
923 #endif
924 
925     cpu_raise_exception_ra(env, TT_UNALIGNED, retaddr);
926 }
927