]> Git Repo - qemu.git/blob - target-ppc/mmu-hash32.c
mmu-hash*: Reduce use of access_type
[qemu.git] / target-ppc / mmu-hash32.c
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 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 "cpu.h"
22 #include "helper.h"
23 #include "sysemu/kvm.h"
24 #include "kvm_ppc.h"
25 #include "mmu-hash32.h"
26
27 //#define DEBUG_MMU
28 //#define DEBUG_BAT
29
30 #ifdef DEBUG_MMU
31 #  define LOG_MMU(...) qemu_log(__VA_ARGS__)
32 #  define LOG_MMU_STATE(env) log_cpu_state((env), 0)
33 #else
34 #  define LOG_MMU(...) do { } while (0)
35 #  define LOG_MMU_STATE(...) do { } while (0)
36 #endif
37
38 #ifdef DEBUG_BATS
39 #  define LOG_BATS(...) qemu_log(__VA_ARGS__)
40 #else
41 #  define LOG_BATS(...) do { } while (0)
42 #endif
43
44 struct mmu_ctx_hash32 {
45     hwaddr raddr;      /* Real address              */
46     hwaddr eaddr;      /* Effective address         */
47     int prot;                      /* Protection bits           */
48     hwaddr hash[2];    /* Pagetable hash values     */
49     target_ulong ptem;             /* Virtual segment ID | API  */
50     int key;                       /* Access key                */
51     int nx;                        /* Non-execute area          */
52 };
53
54 #define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
55
56 static int ppc_hash32_pp_check(int key, int pp, int nx)
57 {
58     int access;
59
60     /* Compute access rights */
61     access = 0;
62     if (key == 0) {
63         switch (pp) {
64         case 0x0:
65         case 0x1:
66         case 0x2:
67             access |= PAGE_WRITE;
68             /* No break here */
69         case 0x3:
70             access |= PAGE_READ;
71             break;
72         }
73     } else {
74         switch (pp) {
75         case 0x0:
76             access = 0;
77             break;
78         case 0x1:
79         case 0x3:
80             access = PAGE_READ;
81             break;
82         case 0x2:
83             access = PAGE_READ | PAGE_WRITE;
84             break;
85         }
86     }
87     if (nx == 0) {
88         access |= PAGE_EXEC;
89     }
90
91     return access;
92 }
93
94 static int ppc_hash32_check_prot(int prot, int rwx)
95 {
96     int ret;
97
98     if (rwx == 2) {
99         if (prot & PAGE_EXEC) {
100             ret = 0;
101         } else {
102             ret = -2;
103         }
104     } else if (rwx) {
105         if (prot & PAGE_WRITE) {
106             ret = 0;
107         } else {
108             ret = -2;
109         }
110     } else {
111         if (prot & PAGE_READ) {
112             ret = 0;
113         } else {
114             ret = -2;
115         }
116     }
117
118     return ret;
119 }
120
121 /* Perform BAT hit & translation */
122 static void hash32_bat_size_prot(CPUPPCState *env, target_ulong *blp,
123                                  int *validp, int *protp, target_ulong *BATu,
124                                  target_ulong *BATl)
125 {
126     target_ulong bl;
127     int pp, valid, prot;
128
129     bl = (*BATu & BATU32_BL) << 15;
130     valid = 0;
131     prot = 0;
132     if (((msr_pr == 0) && (*BATu & BATU32_VS)) ||
133         ((msr_pr != 0) && (*BATu & BATU32_VP))) {
134         valid = 1;
135         pp = *BATl & BATL32_PP;
136         if (pp != 0) {
137             prot = PAGE_READ | PAGE_EXEC;
138             if (pp == 0x2) {
139                 prot |= PAGE_WRITE;
140             }
141         }
142     }
143     *blp = bl;
144     *validp = valid;
145     *protp = prot;
146 }
147
148 static void hash32_bat_601_size_prot(CPUPPCState *env, target_ulong *blp,
149                                      int *validp, int *protp,
150                                      target_ulong *BATu, target_ulong *BATl)
151 {
152     target_ulong bl;
153     int key, pp, valid, prot;
154
155     bl = (*BATl & BATL32_601_BL) << 17;
156     LOG_BATS("b %02x ==> bl " TARGET_FMT_lx " msk " TARGET_FMT_lx "\n",
157              (uint8_t)(*BATl & BATL32_601_BL), bl, ~bl);
158     prot = 0;
159     valid = !!(*BATl & BATL32_601_V);
160     if (valid) {
161         pp = *BATu & BATU32_601_PP;
162         if (msr_pr == 0) {
163             key = !!(*BATu & BATU32_601_KS);
164         } else {
165             key = !!(*BATu & BATU32_601_KP);
166         }
167         prot = ppc_hash32_pp_check(key, pp, 0);
168     }
169     *blp = bl;
170     *validp = valid;
171     *protp = prot;
172 }
173
174 static int ppc_hash32_get_bat(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
175                               target_ulong virtual, int rwx)
176 {
177     target_ulong *BATlt, *BATut, *BATu, *BATl;
178     target_ulong BEPIl, BEPIu, bl;
179     int i, valid, prot;
180     int ret = -1;
181
182     LOG_BATS("%s: %cBAT v " TARGET_FMT_lx "\n", __func__,
183              rwx == 2 ? 'I' : 'D', virtual);
184     if (rwx == 2) {
185         BATlt = env->IBAT[1];
186         BATut = env->IBAT[0];
187     } else {
188         BATlt = env->DBAT[1];
189         BATut = env->DBAT[0];
190     }
191     for (i = 0; i < env->nb_BATs; i++) {
192         BATu = &BATut[i];
193         BATl = &BATlt[i];
194         BEPIu = *BATu & BATU32_BEPIU;
195         BEPIl = *BATu & BATU32_BEPIL;
196         if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
197             hash32_bat_601_size_prot(env, &bl, &valid, &prot, BATu, BATl);
198         } else {
199             hash32_bat_size_prot(env, &bl, &valid, &prot, BATu, BATl);
200         }
201         LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
202                  " BATl " TARGET_FMT_lx "\n", __func__,
203                  type == ACCESS_CODE ? 'I' : 'D', i, virtual, *BATu, *BATl);
204         if ((virtual & BATU32_BEPIU) == BEPIu &&
205             ((virtual & BATU32_BEPIL) & ~bl) == BEPIl) {
206             /* BAT matches */
207             if (valid != 0) {
208                 /* Get physical address */
209                 ctx->raddr = (*BATl & BATL32_BRPNU) |
210                     ((virtual & BATU32_BEPIL & bl) | (*BATl & BATL32_BRPNL)) |
211                     (virtual & 0x0001F000);
212                 /* Compute access rights */
213                 ctx->prot = prot;
214                 ret = ppc_hash32_check_prot(ctx->prot, rwx);
215                 if (ret == 0) {
216                     LOG_BATS("BAT %d match: r " TARGET_FMT_plx " prot=%c%c\n",
217                              i, ctx->raddr, ctx->prot & PAGE_READ ? 'R' : '-',
218                              ctx->prot & PAGE_WRITE ? 'W' : '-');
219                 }
220                 break;
221             }
222         }
223     }
224     if (ret < 0) {
225 #if defined(DEBUG_BATS)
226         if (qemu_log_enabled()) {
227             LOG_BATS("no BAT match for " TARGET_FMT_lx ":\n", virtual);
228             for (i = 0; i < 4; i++) {
229                 BATu = &BATut[i];
230                 BATl = &BATlt[i];
231                 BEPIu = *BATu & BATU32_BEPIU;
232                 BEPIl = *BATu & BATU32_BEPIL;
233                 bl = (*BATu & 0x00001FFC) << 15;
234                 LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
235                          " BATl " TARGET_FMT_lx "\n\t" TARGET_FMT_lx " "
236                          TARGET_FMT_lx " " TARGET_FMT_lx "\n",
237                          __func__, type == ACCESS_CODE ? 'I' : 'D', i, virtual,
238                          *BATu, *BATl, BEPIu, BEPIl, bl);
239             }
240         }
241 #endif
242     }
243     /* No hit */
244     return ret;
245 }
246
247 static int pte_check_hash32(struct mmu_ctx_hash32 *ctx, target_ulong pte0,
248                             target_ulong pte1, int h, int rwx)
249 {
250     target_ulong mmask;
251     int access, ret, pp;
252
253     ret = -1;
254     /* Check validity and table match */
255     if ((pte0 & HPTE32_V_VALID) && (h == !!(pte0 & HPTE32_V_SECONDARY))) {
256         /* Check vsid & api */
257         mmask = PTE_CHECK_MASK;
258         pp = pte1 & HPTE32_R_PP;
259         if (HPTE32_V_COMPARE(pte0, ctx->ptem)) {
260             if (ctx->raddr != (hwaddr)-1ULL) {
261                 /* all matches should have equal RPN, WIMG & PP */
262                 if ((ctx->raddr & mmask) != (pte1 & mmask)) {
263                     qemu_log("Bad RPN/WIMG/PP\n");
264                     return -3;
265                 }
266             }
267             /* Compute access rights */
268             access = ppc_hash32_pp_check(ctx->key, pp, ctx->nx);
269             /* Keep the matching PTE informations */
270             ctx->raddr = pte1;
271             ctx->prot = access;
272             ret = ppc_hash32_check_prot(ctx->prot, rwx);
273             if (ret == 0) {
274                 /* Access granted */
275                 LOG_MMU("PTE access granted !\n");
276             } else {
277                 /* Access right violation */
278                 LOG_MMU("PTE access rejected\n");
279             }
280         }
281     }
282
283     return ret;
284 }
285
286 static int ppc_hash32_pte_update_flags(struct mmu_ctx_hash32 *ctx, target_ulong *pte1p,
287                                        int ret, int rwx)
288 {
289     int store = 0;
290
291     /* Update page flags */
292     if (!(*pte1p & HPTE32_R_R)) {
293         /* Update accessed flag */
294         *pte1p |= HPTE32_R_R;
295         store = 1;
296     }
297     if (!(*pte1p & HPTE32_R_C)) {
298         if (rwx == 1 && ret == 0) {
299             /* Update changed flag */
300             *pte1p |= HPTE32_R_C;
301             store = 1;
302         } else {
303             /* Force page fault for first write access */
304             ctx->prot &= ~PAGE_WRITE;
305         }
306     }
307
308     return store;
309 }
310
311 hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash)
312 {
313     return (hash * HASH_PTEG_SIZE_32) & env->htab_mask;
314 }
315
316 /* PTE table lookup */
317 static int find_pte32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx, int h,
318                       int rwx, int target_page_bits)
319 {
320     hwaddr pteg_off;
321     target_ulong pte0, pte1;
322     int i, good = -1;
323     int ret, r;
324
325     ret = -1; /* No entry found */
326     pteg_off = get_pteg_offset32(env, ctx->hash[h]);
327     for (i = 0; i < HPTES_PER_GROUP; i++) {
328         pte0 = ppc_hash32_load_hpte0(env, pteg_off + i*HASH_PTE_SIZE_32);
329         pte1 = ppc_hash32_load_hpte1(env, pteg_off + i*HASH_PTE_SIZE_32);
330         r = pte_check_hash32(ctx, pte0, pte1, h, rwx);
331         LOG_MMU("Load pte from %08" HWADDR_PRIx " => " TARGET_FMT_lx " "
332                 TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
333                 pteg_off + (i * 8), pte0, pte1, (int)(pte0 >> 31), h,
334                 (int)((pte0 >> 6) & 1), ctx->ptem);
335         switch (r) {
336         case -3:
337             /* PTE inconsistency */
338             return -1;
339         case -2:
340             /* Access violation */
341             ret = -2;
342             good = i;
343             break;
344         case -1:
345         default:
346             /* No PTE match */
347             break;
348         case 0:
349             /* access granted */
350             /* XXX: we should go on looping to check all PTEs consistency
351              *      but if we can speed-up the whole thing as the
352              *      result would be undefined if PTEs are not consistent.
353              */
354             ret = 0;
355             good = i;
356             goto done;
357         }
358     }
359     if (good != -1) {
360     done:
361         LOG_MMU("found PTE at addr %08" HWADDR_PRIx " prot=%01x ret=%d\n",
362                 ctx->raddr, ctx->prot, ret);
363         /* Update page flags */
364         pte1 = ctx->raddr;
365         if (ppc_hash32_pte_update_flags(ctx, &pte1, ret, rwx) == 1) {
366             ppc_hash32_store_hpte1(env, pteg_off + good * HASH_PTE_SIZE_32,
367                                    pte1);
368         }
369     }
370
371     /* We have a TLB that saves 4K pages, so let's
372      * split a huge page to 4k chunks */
373     if (target_page_bits != TARGET_PAGE_BITS) {
374         ctx->raddr |= (ctx->eaddr & ((1 << target_page_bits) - 1))
375                       & TARGET_PAGE_MASK;
376     }
377     return ret;
378 }
379
380 static int get_segment32(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
381                          target_ulong eaddr, int rwx)
382 {
383     hwaddr hash;
384     target_ulong vsid;
385     int ds, pr, target_page_bits;
386     int ret, ret2;
387     target_ulong sr, pgidx;
388
389     pr = msr_pr;
390     ctx->eaddr = eaddr;
391
392     sr = env->sr[eaddr >> 28];
393     ctx->key = (((sr & SR32_KP) && (pr != 0)) ||
394                 ((sr & SR32_KS) && (pr == 0))) ? 1 : 0;
395     ds = !!(sr & SR32_T);
396     ctx->nx = !!(sr & SR32_NX);
397     vsid = sr & SR32_VSID;
398     target_page_bits = TARGET_PAGE_BITS;
399     LOG_MMU("Check segment v=" TARGET_FMT_lx " %d " TARGET_FMT_lx " nip="
400             TARGET_FMT_lx " lr=" TARGET_FMT_lx
401             " ir=%d dr=%d pr=%d %d\n",
402             eaddr, (int)(eaddr >> 28), sr, env->nip, env->lr, (int)msr_ir,
403             (int)msr_dr, pr != 0 ? 1 : 0, rwx);
404     pgidx = (eaddr & ~SEGMENT_MASK_256M) >> target_page_bits;
405     hash = vsid ^ pgidx;
406     ctx->ptem = (vsid << 7) | (pgidx >> 10);
407
408     LOG_MMU("pte segment: key=%d ds %d nx %d vsid " TARGET_FMT_lx "\n",
409             ctx->key, ds, ctx->nx, vsid);
410     ret = -1;
411     if (!ds) {
412         /* Check if instruction fetch is allowed, if needed */
413         if (rwx != 2 || ctx->nx == 0) {
414             /* Page address translation */
415             LOG_MMU("htab_base " TARGET_FMT_plx " htab_mask " TARGET_FMT_plx
416                     " hash " TARGET_FMT_plx "\n",
417                     env->htab_base, env->htab_mask, hash);
418             ctx->hash[0] = hash;
419             ctx->hash[1] = ~hash;
420
421             /* Initialize real address with an invalid value */
422             ctx->raddr = (hwaddr)-1ULL;
423             LOG_MMU("0 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
424                     " vsid=" TARGET_FMT_lx " ptem=" TARGET_FMT_lx
425                     " hash=" TARGET_FMT_plx "\n",
426                     env->htab_base, env->htab_mask, vsid, ctx->ptem,
427                     ctx->hash[0]);
428             /* Primary table lookup */
429             ret = find_pte32(env, ctx, 0, rwx, target_page_bits);
430             if (ret < 0) {
431                 /* Secondary table lookup */
432                 LOG_MMU("1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
433                         " vsid=" TARGET_FMT_lx " api=" TARGET_FMT_lx
434                         " hash=" TARGET_FMT_plx "\n", env->htab_base,
435                         env->htab_mask, vsid, ctx->ptem, ctx->hash[1]);
436                 ret2 = find_pte32(env, ctx, 1, rwx, target_page_bits);
437                 if (ret2 != -1) {
438                     ret = ret2;
439                 }
440             }
441 #if defined(DUMP_PAGE_TABLES)
442             if (qemu_log_enabled()) {
443                 hwaddr curaddr;
444                 uint32_t a0, a1, a2, a3;
445
446                 qemu_log("Page table: " TARGET_FMT_plx " len " TARGET_FMT_plx
447                          "\n", sdr, mask + 0x80);
448                 for (curaddr = sdr; curaddr < (sdr + mask + 0x80);
449                      curaddr += 16) {
450                     a0 = ldl_phys(curaddr);
451                     a1 = ldl_phys(curaddr + 4);
452                     a2 = ldl_phys(curaddr + 8);
453                     a3 = ldl_phys(curaddr + 12);
454                     if (a0 != 0 || a1 != 0 || a2 != 0 || a3 != 0) {
455                         qemu_log(TARGET_FMT_plx ": %08x %08x %08x %08x\n",
456                                  curaddr, a0, a1, a2, a3);
457                     }
458                 }
459             }
460 #endif
461         } else {
462             LOG_MMU("No access allowed\n");
463             ret = -3;
464         }
465     } else {
466         target_ulong sr;
467
468         LOG_MMU("direct store...\n");
469         /* Direct-store segment : absolutely *BUGGY* for now */
470
471         /* Direct-store implies a 32-bit MMU.
472          * Check the Segment Register's bus unit ID (BUID).
473          */
474         sr = env->sr[eaddr >> 28];
475         if ((sr & 0x1FF00000) >> 20 == 0x07f) {
476             /* Memory-forced I/O controller interface access */
477             /* If T=1 and BUID=x'07F', the 601 performs a memory access
478              * to SR[28-31] LA[4-31], bypassing all protection mechanisms.
479              */
480             ctx->raddr = ((sr & 0xF) << 28) | (eaddr & 0x0FFFFFFF);
481             ctx->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
482             return 0;
483         }
484
485         if (rwx == 2) {
486             /* No code fetch is allowed in direct-store areas */
487             return -4;
488         }
489
490         switch (env->access_type) {
491         case ACCESS_INT:
492             /* Integer load/store : only access allowed */
493             break;
494         case ACCESS_FLOAT:
495             /* Floating point load/store */
496             return -4;
497         case ACCESS_RES:
498             /* lwarx, ldarx or srwcx. */
499             return -4;
500         case ACCESS_CACHE:
501             /* dcba, dcbt, dcbtst, dcbf, dcbi, dcbst, dcbz, or icbi */
502             /* Should make the instruction do no-op.
503              * As it already do no-op, it's quite easy :-)
504              */
505             ctx->raddr = eaddr;
506             return 0;
507         case ACCESS_EXT:
508             /* eciwx or ecowx */
509             return -4;
510         default:
511             qemu_log("ERROR: instruction should not need "
512                         "address translation\n");
513             return -4;
514         }
515         if ((rwx == 1 || ctx->key != 1) && (rwx == 0 || ctx->key != 0)) {
516             ctx->raddr = eaddr;
517             ret = 2;
518         } else {
519             ret = -2;
520         }
521     }
522
523     return ret;
524 }
525
526 static int ppc_hash32_get_physical_address(CPUPPCState *env, struct mmu_ctx_hash32 *ctx,
527                                            target_ulong eaddr, int rwx)
528 {
529     bool real_mode = (rwx == 2 && msr_ir == 0)
530         || (rwx != 2 && msr_dr == 0);
531
532     if (real_mode) {
533         ctx->raddr = eaddr;
534         ctx->prot = PAGE_READ | PAGE_EXEC | PAGE_WRITE;
535         return 0;
536     } else {
537         int ret = -1;
538
539         /* Try to find a BAT */
540         if (env->nb_BATs != 0) {
541             ret = ppc_hash32_get_bat(env, ctx, eaddr, rwx);
542         }
543         if (ret < 0) {
544             /* We didn't match any BAT entry or don't have BATs */
545             ret = get_segment32(env, ctx, eaddr, rwx);
546         }
547         return ret;
548     }
549 }
550
551 hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong addr)
552 {
553     struct mmu_ctx_hash32 ctx;
554
555     /* FIXME: Will not behave sanely for direct store segments, but
556      * they're almost never used */
557     if (unlikely(ppc_hash32_get_physical_address(env, &ctx, addr, 0)
558                  != 0)) {
559         return -1;
560     }
561
562     return ctx.raddr & TARGET_PAGE_MASK;
563 }
564
565 int ppc_hash32_handle_mmu_fault(CPUPPCState *env, target_ulong address, int rwx,
566                                 int mmu_idx)
567 {
568     struct mmu_ctx_hash32 ctx;
569     int ret = 0;
570
571     ret = ppc_hash32_get_physical_address(env, &ctx, address, rwx);
572     if (ret == 0) {
573         tlb_set_page(env, address & TARGET_PAGE_MASK,
574                      ctx.raddr & TARGET_PAGE_MASK, ctx.prot,
575                      mmu_idx, TARGET_PAGE_SIZE);
576         ret = 0;
577     } else if (ret < 0) {
578         LOG_MMU_STATE(env);
579         if (rwx == 2) {
580             switch (ret) {
581             case -1:
582                 /* No matches in page tables or TLB */
583                 env->exception_index = POWERPC_EXCP_ISI;
584                 env->error_code = 0x40000000;
585                 break;
586             case -2:
587                 /* Access rights violation */
588                 env->exception_index = POWERPC_EXCP_ISI;
589                 env->error_code = 0x08000000;
590                 break;
591             case -3:
592                 /* No execute protection violation */
593                 env->exception_index = POWERPC_EXCP_ISI;
594                 env->error_code = 0x10000000;
595                 break;
596             case -4:
597                 /* Direct store exception */
598                 /* No code fetch is allowed in direct-store areas */
599                 env->exception_index = POWERPC_EXCP_ISI;
600                 env->error_code = 0x10000000;
601                 break;
602             }
603         } else {
604             switch (ret) {
605             case -1:
606                 /* No matches in page tables or TLB */
607                 env->exception_index = POWERPC_EXCP_DSI;
608                 env->error_code = 0;
609                 env->spr[SPR_DAR] = address;
610                 if (rwx == 1) {
611                     env->spr[SPR_DSISR] = 0x42000000;
612                 } else {
613                     env->spr[SPR_DSISR] = 0x40000000;
614                 }
615                 break;
616             case -2:
617                 /* Access rights violation */
618                 env->exception_index = POWERPC_EXCP_DSI;
619                 env->error_code = 0;
620                 env->spr[SPR_DAR] = address;
621                 if (rwx == 1) {
622                     env->spr[SPR_DSISR] = 0x0A000000;
623                 } else {
624                     env->spr[SPR_DSISR] = 0x08000000;
625                 }
626                 break;
627             case -4:
628                 /* Direct store exception */
629                 switch (env->access_type) {
630                 case ACCESS_FLOAT:
631                     /* Floating point load/store */
632                     env->exception_index = POWERPC_EXCP_ALIGN;
633                     env->error_code = POWERPC_EXCP_ALIGN_FP;
634                     env->spr[SPR_DAR] = address;
635                     break;
636                 case ACCESS_RES:
637                     /* lwarx, ldarx or stwcx. */
638                     env->exception_index = POWERPC_EXCP_DSI;
639                     env->error_code = 0;
640                     env->spr[SPR_DAR] = address;
641                     if (rwx == 1) {
642                         env->spr[SPR_DSISR] = 0x06000000;
643                     } else {
644                         env->spr[SPR_DSISR] = 0x04000000;
645                     }
646                     break;
647                 case ACCESS_EXT:
648                     /* eciwx or ecowx */
649                     env->exception_index = POWERPC_EXCP_DSI;
650                     env->error_code = 0;
651                     env->spr[SPR_DAR] = address;
652                     if (rwx == 1) {
653                         env->spr[SPR_DSISR] = 0x06100000;
654                     } else {
655                         env->spr[SPR_DSISR] = 0x04100000;
656                     }
657                     break;
658                 default:
659                     printf("DSI: invalid exception (%d)\n", ret);
660                     env->exception_index = POWERPC_EXCP_PROGRAM;
661                     env->error_code =
662                         POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL;
663                     env->spr[SPR_DAR] = address;
664                     break;
665                 }
666                 break;
667             }
668         }
669 #if 0
670         printf("%s: set exception to %d %02x\n", __func__,
671                env->exception, env->error_code);
672 #endif
673         ret = 1;
674     }
675
676     return ret;
677 }
This page took 0.063475 seconds and 4 git commands to generate.