xref: /openbmc/qemu/target/ppc/mmu-hash32.c (revision 719a1da19ee67cfd3ef5b50f778d0204daaeb0b2)
1 /*
2  *  PowerPC MMU, TLB and BAT emulation helpers for QEMU.
3  *
4  *  Copyright (c) 2003-2007 Jocelyn Mayer
5  *  Copyright (c) 2013 David Gibson, IBM Corporation
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "qemu/osdep.h"
22 #include "cpu.h"
23 #include "exec/exec-all.h"
24 #include "exec/page-protection.h"
25 #include "sysemu/kvm.h"
26 #include "kvm_ppc.h"
27 #include "internal.h"
28 #include "mmu-hash32.h"
29 #include "mmu-books.h"
30 #include "exec/log.h"
31 
32 /* #define DEBUG_BATS */
33 
34 #ifdef DEBUG_BATS
35 #  define LOG_BATS(...) qemu_log_mask(CPU_LOG_MMU, __VA_ARGS__)
36 #else
37 #  define LOG_BATS(...) do { } while (0)
38 #endif
39 
40 static int ppc_hash32_pte_prot(int mmu_idx,
41                                target_ulong sr, ppc_hash_pte32_t pte)
42 {
43     unsigned pp, key;
44 
45     key = ppc_hash32_key(mmuidx_pr(mmu_idx), sr);
46     pp = pte.pte1 & HPTE32_R_PP;
47 
48     return ppc_hash32_prot(key, pp, !!(sr & SR32_NX));
49 }
50 
51 static target_ulong hash32_bat_size(int mmu_idx,
52                                     target_ulong batu, target_ulong batl)
53 {
54     if ((mmuidx_pr(mmu_idx) && !(batu & BATU32_VP))
55         || (!mmuidx_pr(mmu_idx) && !(batu & BATU32_VS))) {
56         return 0;
57     }
58 
59     return BATU32_BEPI & ~((batu & BATU32_BL) << 15);
60 }
61 
62 static int hash32_bat_prot(PowerPCCPU *cpu,
63                            target_ulong batu, target_ulong batl)
64 {
65     int pp, prot;
66 
67     prot = 0;
68     pp = batl & BATL32_PP;
69     if (pp != 0) {
70         prot = PAGE_READ | PAGE_EXEC;
71         if (pp == 0x2) {
72             prot |= PAGE_WRITE;
73         }
74     }
75     return prot;
76 }
77 
78 static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea,
79                                     MMUAccessType access_type, int *prot,
80                                     int mmu_idx)
81 {
82     CPUPPCState *env = &cpu->env;
83     target_ulong *BATlt, *BATut;
84     bool ifetch = access_type == MMU_INST_FETCH;
85     int i;
86 
87     LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
88              ifetch ? 'I' : 'D', ea);
89     if (ifetch) {
90         BATlt = env->IBAT[1];
91         BATut = env->IBAT[0];
92     } else {
93         BATlt = env->DBAT[1];
94         BATut = env->DBAT[0];
95     }
96     for (i = 0; i < env->nb_BATs; i++) {
97         target_ulong batu = BATut[i];
98         target_ulong batl = BATlt[i];
99         target_ulong mask;
100 
101         mask = hash32_bat_size(mmu_idx, batu, batl);
102         LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
103                  " BATl " TARGET_FMT_lx "\n", __func__,
104                  ifetch ? 'I' : 'D', i, ea, batu, batl);
105 
106         if (mask && ((ea & mask) == (batu & BATU32_BEPI))) {
107             hwaddr raddr = (batl & mask) | (ea & ~mask);
108 
109             *prot = hash32_bat_prot(cpu, batu, batl);
110 
111             return raddr & TARGET_PAGE_MASK;
112         }
113     }
114 
115     /* No hit */
116 #if defined(DEBUG_BATS)
117     if (qemu_log_enabled()) {
118         target_ulong *BATu, *BATl;
119         target_ulong BEPIl, BEPIu, bl;
120 
121         LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", ea);
122         for (i = 0; i < 4; i++) {
123             BATu = &BATut[i];
124             BATl = &BATlt[i];
125             BEPIu = *BATu & BATU32_BEPIU;
126             BEPIl = *BATu & BATU32_BEPIL;
127             bl = (*BATu & 0x00001FFC) << 15;
128             LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
129                      " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
130                      TARGET_FMT_lx " " TARGET_FMT_lx "\n",
131                      __func__, ifetch ? 'I' : 'D', i, ea,
132                      *BATu, *BATl, BEPIu, BEPIl, bl);
133         }
134     }
135 #endif
136 
137     return -1;
138 }
139 
140 static bool ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
141                                     target_ulong eaddr,
142                                     MMUAccessType access_type,
143                                     hwaddr *raddr, int *prot, int mmu_idx,
144                                     bool guest_visible)
145 {
146     CPUState *cs = CPU(cpu);
147     CPUPPCState *env = &cpu->env;
148 
149     qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
150 
151     if (access_type == MMU_INST_FETCH) {
152         /* No code fetch is allowed in direct-store areas */
153         if (guest_visible) {
154             cs->exception_index = POWERPC_EXCP_ISI;
155             env->error_code = 0x10000000;
156         }
157         return false;
158     }
159 
160     /*
161      * From ppc_cpu_get_phys_page_debug, env->access_type is not set.
162      * Assume ACCESS_INT for that case.
163      */
164     switch (guest_visible ? env->access_type : ACCESS_INT) {
165     case ACCESS_INT:
166         /* Integer load/store : only access allowed */
167         break;
168     case ACCESS_FLOAT:
169         /* Floating point load/store */
170         cs->exception_index = POWERPC_EXCP_ALIGN;
171         env->error_code = POWERPC_EXCP_ALIGN_FP;
172         env->spr[SPR_DAR] = eaddr;
173         return false;
174     case ACCESS_RES:
175         /* lwarx, ldarx or srwcx. */
176         env->error_code = 0;
177         env->spr[SPR_DAR] = eaddr;
178         if (access_type == MMU_DATA_STORE) {
179             env->spr[SPR_DSISR] = 0x06000000;
180         } else {
181             env->spr[SPR_DSISR] = 0x04000000;
182         }
183         return false;
184     case ACCESS_CACHE:
185         /*
186          * dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi
187          *
188          * Should make the instruction do no-op.  As it already do
189          * no-op, it's quite easy :-)
190          */
191         *raddr = eaddr;
192         return true;
193     case ACCESS_EXT:
194         /* eciwx or ecowx */
195         cs->exception_index = POWERPC_EXCP_DSI;
196         env->error_code = 0;
197         env->spr[SPR_DAR] = eaddr;
198         if (access_type == MMU_DATA_STORE) {
199             env->spr[SPR_DSISR] = 0x06100000;
200         } else {
201             env->spr[SPR_DSISR] = 0x04100000;
202         }
203         return false;
204     default:
205         cpu_abort(cs, "ERROR: insn should not need address translation\n");
206     }
207 
208     if (ppc_hash32_key(mmuidx_pr(mmu_idx), sr)) {
209         *prot = PAGE_READ | PAGE_WRITE;
210     } else {
211         *prot = PAGE_READ;
212     }
213     if (check_prot_access_type(*prot, access_type)) {
214         *raddr = eaddr;
215         return true;
216     }
217 
218     if (guest_visible) {
219         cs->exception_index = POWERPC_EXCP_DSI;
220         env->error_code = 0;
221         env->spr[SPR_DAR] = eaddr;
222         if (access_type == MMU_DATA_STORE) {
223             env->spr[SPR_DSISR] = 0x0a000000;
224         } else {
225             env->spr[SPR_DSISR] = 0x08000000;
226         }
227     }
228     return false;
229 }
230 
231 hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash)
232 {
233     target_ulong mask = ppc_hash32_hpt_mask(cpu);
234 
235     return (hash * HASH_PTEG_SIZE_32) & mask;
236 }
237 
238 static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, hwaddr pteg_off,
239                                      bool secondary, target_ulong ptem,
240                                      ppc_hash_pte32_t *pte)
241 {
242     hwaddr pte_offset = pteg_off;
243     target_ulong pte0, pte1;
244     int i;
245 
246     for (i = 0; i < HPTES_PER_GROUP; i++) {
247         pte0 = ppc_hash32_load_hpte0(cpu, pte_offset);
248         /*
249          * pte0 contains the valid bit and must be read before pte1,
250          * otherwise we might see an old pte1 with a new valid bit and
251          * thus an inconsistent hpte value
252          */
253         smp_rmb();
254         pte1 = ppc_hash32_load_hpte1(cpu, pte_offset);
255 
256         if ((pte0 & HPTE32_V_VALID)
257             && (secondary == !!(pte0 & HPTE32_V_SECONDARY))
258             && HPTE32_V_COMPARE(pte0, ptem)) {
259             pte->pte0 = pte0;
260             pte->pte1 = pte1;
261             return pte_offset;
262         }
263 
264         pte_offset += HASH_PTE_SIZE_32;
265     }
266 
267     return -1;
268 }
269 
270 static void ppc_hash32_set_r(PowerPCCPU *cpu, hwaddr pte_offset, uint32_t pte1)
271 {
272     target_ulong base = ppc_hash32_hpt_base(cpu);
273     hwaddr offset = pte_offset + 6;
274 
275     /* The HW performs a non-atomic byte update */
276     stb_phys(CPU(cpu)->as, base + offset, ((pte1 >> 8) & 0xff) | 0x01);
277 }
278 
279 static void ppc_hash32_set_c(PowerPCCPU *cpu, hwaddr pte_offset, uint64_t pte1)
280 {
281     target_ulong base = ppc_hash32_hpt_base(cpu);
282     hwaddr offset = pte_offset + 7;
283 
284     /* The HW performs a non-atomic byte update */
285     stb_phys(CPU(cpu)->as, base + offset, (pte1 & 0xff) | 0x80);
286 }
287 
288 static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
289                                      target_ulong sr, target_ulong eaddr,
290                                      ppc_hash_pte32_t *pte)
291 {
292     hwaddr pteg_off, pte_offset;
293     hwaddr hash;
294     uint32_t vsid, pgidx, ptem;
295 
296     vsid = sr & SR32_VSID;
297     pgidx = (eaddr & ~SEGMENT_MASK_256M) >> TARGET_PAGE_BITS;
298     hash = vsid ^ pgidx;
299     ptem = (vsid << 7) | (pgidx >> 10);
300 
301     /* Page address translation */
302     qemu_log_mask(CPU_LOG_MMU, "htab_base " HWADDR_FMT_plx
303             " htab_mask " HWADDR_FMT_plx
304             " hash " HWADDR_FMT_plx "\n",
305             ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu), hash);
306 
307     /* Primary PTEG lookup */
308     qemu_log_mask(CPU_LOG_MMU, "0 htab=" HWADDR_FMT_plx "/" HWADDR_FMT_plx
309             " vsid=%" PRIx32 " ptem=%" PRIx32
310             " hash=" HWADDR_FMT_plx "\n",
311             ppc_hash32_hpt_base(cpu), ppc_hash32_hpt_mask(cpu),
312             vsid, ptem, hash);
313     pteg_off = get_pteg_offset32(cpu, hash);
314     pte_offset = ppc_hash32_pteg_search(cpu, pteg_off, 0, ptem, pte);
315     if (pte_offset == -1) {
316         /* Secondary PTEG lookup */
317         qemu_log_mask(CPU_LOG_MMU, "1 htab=" HWADDR_FMT_plx "/" HWADDR_FMT_plx
318                 " vsid=%" PRIx32 " api=%" PRIx32
319                 " hash=" HWADDR_FMT_plx "\n", ppc_hash32_hpt_base(cpu),
320                 ppc_hash32_hpt_mask(cpu), vsid, ptem, ~hash);
321         pteg_off = get_pteg_offset32(cpu, ~hash);
322         pte_offset = ppc_hash32_pteg_search(cpu, pteg_off, 1, ptem, pte);
323     }
324 
325     return pte_offset;
326 }
327 
328 static hwaddr ppc_hash32_pte_raddr(target_ulong sr, ppc_hash_pte32_t pte,
329                                    target_ulong eaddr)
330 {
331     hwaddr rpn = pte.pte1 & HPTE32_R_RPN;
332     hwaddr mask = ~TARGET_PAGE_MASK;
333 
334     return (rpn & ~mask) | (eaddr & mask);
335 }
336 
337 bool ppc_hash32_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
338                       hwaddr *raddrp, int *psizep, int *protp, int mmu_idx,
339                       bool guest_visible)
340 {
341     CPUState *cs = CPU(cpu);
342     CPUPPCState *env = &cpu->env;
343     target_ulong sr;
344     hwaddr pte_offset;
345     ppc_hash_pte32_t pte;
346     int prot;
347     hwaddr raddr;
348 
349     /* There are no hash32 large pages. */
350     *psizep = TARGET_PAGE_BITS;
351 
352     /* 1. Handle real mode accesses */
353     if (mmuidx_real(mmu_idx)) {
354         /* Translation is off */
355         *raddrp = eaddr;
356         *protp = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
357         return true;
358     }
359 
360     /* 2. Check Block Address Translation entries (BATs) */
361     if (env->nb_BATs != 0) {
362         raddr = ppc_hash32_bat_lookup(cpu, eaddr, access_type, protp, mmu_idx);
363         if (raddr != -1) {
364             if (!check_prot_access_type(*protp, access_type)) {
365                 if (guest_visible) {
366                     if (access_type == MMU_INST_FETCH) {
367                         cs->exception_index = POWERPC_EXCP_ISI;
368                         env->error_code = 0x08000000;
369                     } else {
370                         cs->exception_index = POWERPC_EXCP_DSI;
371                         env->error_code = 0;
372                         env->spr[SPR_DAR] = eaddr;
373                         if (access_type == MMU_DATA_STORE) {
374                             env->spr[SPR_DSISR] = 0x0a000000;
375                         } else {
376                             env->spr[SPR_DSISR] = 0x08000000;
377                         }
378                     }
379                 }
380                 return false;
381             }
382             *raddrp = raddr;
383             return true;
384         }
385     }
386 
387     /* 3. Look up the Segment Register */
388     sr = env->sr[eaddr >> 28];
389 
390     /* 4. Handle direct store segments */
391     if (sr & SR32_T) {
392         return ppc_hash32_direct_store(cpu, sr, eaddr, access_type,
393                                        raddrp, protp, mmu_idx, guest_visible);
394     }
395 
396     /* 5. Check for segment level no-execute violation */
397     if (access_type == MMU_INST_FETCH && (sr & SR32_NX)) {
398         if (guest_visible) {
399             cs->exception_index = POWERPC_EXCP_ISI;
400             env->error_code = 0x10000000;
401         }
402         return false;
403     }
404 
405     /* 6. Locate the PTE in the hash table */
406     pte_offset = ppc_hash32_htab_lookup(cpu, sr, eaddr, &pte);
407     if (pte_offset == -1) {
408         if (guest_visible) {
409             if (access_type == MMU_INST_FETCH) {
410                 cs->exception_index = POWERPC_EXCP_ISI;
411                 env->error_code = 0x40000000;
412             } else {
413                 cs->exception_index = POWERPC_EXCP_DSI;
414                 env->error_code = 0;
415                 env->spr[SPR_DAR] = eaddr;
416                 if (access_type == MMU_DATA_STORE) {
417                     env->spr[SPR_DSISR] = 0x42000000;
418                 } else {
419                     env->spr[SPR_DSISR] = 0x40000000;
420                 }
421             }
422         }
423         return false;
424     }
425     qemu_log_mask(CPU_LOG_MMU,
426                 "found PTE at offset %08" HWADDR_PRIx "\n", pte_offset);
427 
428     /* 7. Check access permissions */
429 
430     prot = ppc_hash32_pte_prot(mmu_idx, sr, pte);
431 
432     if (!check_prot_access_type(prot, access_type)) {
433         /* Access right violation */
434         qemu_log_mask(CPU_LOG_MMU, "PTE access rejected\n");
435         if (guest_visible) {
436             if (access_type == MMU_INST_FETCH) {
437                 cs->exception_index = POWERPC_EXCP_ISI;
438                 env->error_code = 0x08000000;
439             } else {
440                 cs->exception_index = POWERPC_EXCP_DSI;
441                 env->error_code = 0;
442                 env->spr[SPR_DAR] = eaddr;
443                 if (access_type == MMU_DATA_STORE) {
444                     env->spr[SPR_DSISR] = 0x0a000000;
445                 } else {
446                     env->spr[SPR_DSISR] = 0x08000000;
447                 }
448             }
449         }
450         return false;
451     }
452 
453     qemu_log_mask(CPU_LOG_MMU, "PTE access granted !\n");
454 
455     /* 8. Update PTE referenced and changed bits if necessary */
456 
457     if (!(pte.pte1 & HPTE32_R_R)) {
458         ppc_hash32_set_r(cpu, pte_offset, pte.pte1);
459     }
460     if (!(pte.pte1 & HPTE32_R_C)) {
461         if (access_type == MMU_DATA_STORE) {
462             ppc_hash32_set_c(cpu, pte_offset, pte.pte1);
463         } else {
464             /*
465              * Treat the page as read-only for now, so that a later write
466              * will pass through this function again to set the C bit
467              */
468             prot &= ~PAGE_WRITE;
469         }
470      }
471 
472     /* 9. Determine the real address from the PTE */
473 
474     *raddrp = ppc_hash32_pte_raddr(sr, pte, eaddr);
475     *protp = prot;
476     return true;
477 }
478