Commit d094807b9bfe39401e82dce6b7e97a70eb5931be
1 parent
6d506e6d
MMU fix - temporary osi_call support - xec_bc mask fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1437 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
35 additions
and
36 deletions
target-ppc/helper.c
| ... | ... | @@ -22,6 +22,8 @@ |
| 22 | 22 | //#define DEBUG_MMU |
| 23 | 23 | //#define DEBUG_BATS |
| 24 | 24 | //#define DEBUG_EXCEPTIONS |
| 25 | +/* accurate but slower TLB flush in exceptions */ | |
| 26 | +//#define ACCURATE_TLB_FLUSH | |
| 25 | 27 | |
| 26 | 28 | /*****************************************************************************/ |
| 27 | 29 | /* PPC MMU emulation */ |
| ... | ... | @@ -128,7 +130,7 @@ static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va, |
| 128 | 130 | pte0 = ldl_phys(base + (i * 8)); |
| 129 | 131 | pte1 = ldl_phys(base + (i * 8) + 4); |
| 130 | 132 | #if defined (DEBUG_MMU) |
| 131 | - if (loglevel > 0) { | |
| 133 | + if (loglevel > 0) { | |
| 132 | 134 | fprintf(logfile, "Load pte from 0x%08x => 0x%08x 0x%08x " |
| 133 | 135 | "%d %d %d 0x%08x\n", base + (i * 8), pte0, pte1, |
| 134 | 136 | pte0 >> 31, h, (pte0 >> 6) & 1, va); |
| ... | ... | @@ -175,17 +177,17 @@ static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va, |
| 175 | 177 | if (loglevel > 0) |
| 176 | 178 | fprintf(logfile, "PTE access granted !\n"); |
| 177 | 179 | #endif |
| 178 | - good = i; | |
| 179 | - keep = pte1; | |
| 180 | - ret = 0; | |
| 180 | + good = i; | |
| 181 | + keep = pte1; | |
| 182 | + ret = 0; | |
| 181 | 183 | } else { |
| 182 | 184 | /* Access right violation */ |
| 183 | - ret = -2; | |
| 185 | + ret = -2; | |
| 184 | 186 | #if defined (DEBUG_MMU) |
| 185 | 187 | if (loglevel > 0) |
| 186 | 188 | fprintf(logfile, "PTE access rejected\n"); |
| 187 | 189 | #endif |
| 188 | - } | |
| 190 | + } | |
| 189 | 191 | *prot = access; |
| 190 | 192 | } |
| 191 | 193 | } |
| ... | ... | @@ -194,7 +196,7 @@ static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va, |
| 194 | 196 | if (good != -1) { |
| 195 | 197 | *RPN = keep & 0xFFFFF000; |
| 196 | 198 | #if defined (DEBUG_MMU) |
| 197 | - if (loglevel > 0) { | |
| 199 | + if (loglevel > 0) { | |
| 198 | 200 | fprintf(logfile, "found PTE at addr 0x%08x prot=0x%01x ret=%d\n", |
| 199 | 201 | *RPN, *prot, ret); |
| 200 | 202 | } |
| ... | ... | @@ -205,7 +207,7 @@ static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va, |
| 205 | 207 | keep |= 0x00000100; |
| 206 | 208 | store = 1; |
| 207 | 209 | } |
| 208 | - if (!(keep & 0x00000080)) { | |
| 210 | + if (!(keep & 0x00000080)) { | |
| 209 | 211 | if (rw && ret == 0) { |
| 210 | 212 | /* Change flag */ |
| 211 | 213 | keep |= 0x00000080; |
| ... | ... | @@ -251,7 +253,7 @@ static int get_segment (CPUState *env, uint32_t *real, int *prot, |
| 251 | 253 | ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0; |
| 252 | 254 | if ((sr & 0x80000000) == 0) { |
| 253 | 255 | #if defined (DEBUG_MMU) |
| 254 | - if (loglevel > 0) | |
| 256 | + if (loglevel > 0) | |
| 255 | 257 | fprintf(logfile, "pte segment: key=%d n=0x%08x\n", |
| 256 | 258 | key, sr & 0x10000000); |
| 257 | 259 | #endif |
| ... | ... | @@ -604,7 +606,7 @@ void _store_xer (CPUState *env, uint32_t value) |
| 604 | 606 | xer_so = (value >> XER_SO) & 0x01; |
| 605 | 607 | xer_ov = (value >> XER_OV) & 0x01; |
| 606 | 608 | xer_ca = (value >> XER_CA) & 0x01; |
| 607 | - xer_bc = (value >> XER_BC) & 0x1f; | |
| 609 | + xer_bc = (value >> XER_BC) & 0x3f; | |
| 608 | 610 | } |
| 609 | 611 | |
| 610 | 612 | uint32_t _load_msr (CPUState *env) |
| ... | ... | @@ -628,12 +630,12 @@ uint32_t _load_msr (CPUState *env) |
| 628 | 630 | |
| 629 | 631 | void _store_msr (CPUState *env, uint32_t value) |
| 630 | 632 | { |
| 631 | -#if 0 // TRY | |
| 633 | +#ifdef ACCURATE_TLB_FLUSH | |
| 632 | 634 | if (((value >> MSR_IR) & 0x01) != msr_ir || |
| 633 | 635 | ((value >> MSR_DR) & 0x01) != msr_dr) |
| 634 | 636 | { |
| 635 | 637 | /* Flush all tlb when changing translation mode or privilege level */ |
| 636 | - tlb_flush(env, 1); | |
| 638 | + tlb_flush(env, 1); | |
| 637 | 639 | } |
| 638 | 640 | #endif |
| 639 | 641 | msr_pow = (value >> MSR_POW) & 0x03; |
| ... | ... | @@ -660,6 +662,13 @@ void do_interrupt (CPUState *env) |
| 660 | 662 | env->exception_index = -1; |
| 661 | 663 | } |
| 662 | 664 | #else |
| 665 | +static void dump_syscall(CPUState *env) | |
| 666 | +{ | |
| 667 | + fprintf(logfile, "syscall r0=0x%08x r3=0x%08x r4=0x%08x r5=0x%08x r6=0x%08x nip=0x%08x\n", | |
| 668 | + env->gpr[0], env->gpr[3], env->gpr[4], | |
| 669 | + env->gpr[5], env->gpr[6], env->nip); | |
| 670 | +} | |
| 671 | + | |
| 663 | 672 | void do_interrupt (CPUState *env) |
| 664 | 673 | { |
| 665 | 674 | uint32_t msr; |
| ... | ... | @@ -707,11 +716,11 @@ void do_interrupt (CPUState *env) |
| 707 | 716 | */ |
| 708 | 717 | msr &= ~0xFFFF0000; |
| 709 | 718 | env->spr[DSISR] = 0; |
| 710 | - if (env->error_code & EXCP_DSI_TRANSLATE) | |
| 719 | + if ((env->error_code & 0x0f) == EXCP_DSI_TRANSLATE) | |
| 711 | 720 | env->spr[DSISR] |= 0x40000000; |
| 712 | - else if (env->error_code & EXCP_DSI_PROT) | |
| 721 | + else if ((env->error_code & 0x0f) == EXCP_DSI_PROT) | |
| 713 | 722 | env->spr[DSISR] |= 0x08000000; |
| 714 | - else if (env->error_code & EXCP_DSI_NOTSUP) { | |
| 723 | + else if ((env->error_code & 0x0f) == EXCP_DSI_NOTSUP) { | |
| 715 | 724 | env->spr[DSISR] |= 0x80000000; |
| 716 | 725 | if (env->error_code & EXCP_DSI_DIRECT) |
| 717 | 726 | env->spr[DSISR] |= 0x04000000; |
| ... | ... | @@ -819,28 +828,15 @@ void do_interrupt (CPUState *env) |
| 819 | 828 | } |
| 820 | 829 | goto store_next; |
| 821 | 830 | case EXCP_SYSCALL: |
| 831 | + /* NOTE: this is a temporary hack to support graphics OSI | |
| 832 | + calls from the MOL driver */ | |
| 833 | + if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b && | |
| 834 | + env->osi_call) { | |
| 835 | + if (env->osi_call(env) != 0) | |
| 836 | + return; | |
| 837 | + } | |
| 822 | 838 | if (loglevel & CPU_LOG_INT) { |
| 823 | - fprintf(logfile, "syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", | |
| 824 | - env->gpr[0], env->gpr[3], env->gpr[4], | |
| 825 | - env->gpr[5], env->gpr[6]); | |
| 826 | - if (env->gpr[0] == 4 && env->gpr[3] == 1) { | |
| 827 | - int len, addr, i; | |
| 828 | - uint8_t c; | |
| 829 | - | |
| 830 | - fprintf(logfile, "write: "); | |
| 831 | - addr = env->gpr[4]; | |
| 832 | - len = env->gpr[5]; | |
| 833 | - if (len > 64) | |
| 834 | - len = 64; | |
| 835 | - for(i = 0; i < len; i++) { | |
| 836 | - c = 0; | |
| 837 | - cpu_memory_rw_debug(env, addr + i, &c, 1, 0); | |
| 838 | - if (c < 32 || c > 126) | |
| 839 | - c = '.'; | |
| 840 | - fprintf(logfile, "%c", c); | |
| 841 | - } | |
| 842 | - fprintf(logfile, "\n"); | |
| 843 | - } | |
| 839 | + dump_syscall(env); | |
| 844 | 840 | } |
| 845 | 841 | goto store_next; |
| 846 | 842 | case EXCP_TRACE: |
| ... | ... | @@ -887,6 +883,9 @@ void do_interrupt (CPUState *env) |
| 887 | 883 | env->nip = excp << 8; |
| 888 | 884 | env->exception_index = EXCP_NONE; |
| 889 | 885 | /* Invalidate all TLB as we may have changed translation mode */ |
| 886 | +#ifdef ACCURATE_TLB_FLUSH | |
| 887 | + tlb_flush(env, 1); | |
| 888 | +#endif | |
| 890 | 889 | /* ensure that no TB jump will be modified as |
| 891 | 890 | the program flow was changed */ |
| 892 | 891 | #ifdef __sparc__ | ... | ... |