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,6 +22,8 @@ | ||
| 22 | //#define DEBUG_MMU | 22 | //#define DEBUG_MMU |
| 23 | //#define DEBUG_BATS | 23 | //#define DEBUG_BATS |
| 24 | //#define DEBUG_EXCEPTIONS | 24 | //#define DEBUG_EXCEPTIONS |
| 25 | +/* accurate but slower TLB flush in exceptions */ | ||
| 26 | +//#define ACCURATE_TLB_FLUSH | ||
| 25 | 27 | ||
| 26 | /*****************************************************************************/ | 28 | /*****************************************************************************/ |
| 27 | /* PPC MMU emulation */ | 29 | /* PPC MMU emulation */ |
| @@ -128,7 +130,7 @@ static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va, | @@ -128,7 +130,7 @@ static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va, | ||
| 128 | pte0 = ldl_phys(base + (i * 8)); | 130 | pte0 = ldl_phys(base + (i * 8)); |
| 129 | pte1 = ldl_phys(base + (i * 8) + 4); | 131 | pte1 = ldl_phys(base + (i * 8) + 4); |
| 130 | #if defined (DEBUG_MMU) | 132 | #if defined (DEBUG_MMU) |
| 131 | - if (loglevel > 0) { | 133 | + if (loglevel > 0) { |
| 132 | fprintf(logfile, "Load pte from 0x%08x => 0x%08x 0x%08x " | 134 | fprintf(logfile, "Load pte from 0x%08x => 0x%08x 0x%08x " |
| 133 | "%d %d %d 0x%08x\n", base + (i * 8), pte0, pte1, | 135 | "%d %d %d 0x%08x\n", base + (i * 8), pte0, pte1, |
| 134 | pte0 >> 31, h, (pte0 >> 6) & 1, va); | 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,17 +177,17 @@ static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va, | ||
| 175 | if (loglevel > 0) | 177 | if (loglevel > 0) |
| 176 | fprintf(logfile, "PTE access granted !\n"); | 178 | fprintf(logfile, "PTE access granted !\n"); |
| 177 | #endif | 179 | #endif |
| 178 | - good = i; | ||
| 179 | - keep = pte1; | ||
| 180 | - ret = 0; | 180 | + good = i; |
| 181 | + keep = pte1; | ||
| 182 | + ret = 0; | ||
| 181 | } else { | 183 | } else { |
| 182 | /* Access right violation */ | 184 | /* Access right violation */ |
| 183 | - ret = -2; | 185 | + ret = -2; |
| 184 | #if defined (DEBUG_MMU) | 186 | #if defined (DEBUG_MMU) |
| 185 | if (loglevel > 0) | 187 | if (loglevel > 0) |
| 186 | fprintf(logfile, "PTE access rejected\n"); | 188 | fprintf(logfile, "PTE access rejected\n"); |
| 187 | #endif | 189 | #endif |
| 188 | - } | 190 | + } |
| 189 | *prot = access; | 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,7 +196,7 @@ static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va, | ||
| 194 | if (good != -1) { | 196 | if (good != -1) { |
| 195 | *RPN = keep & 0xFFFFF000; | 197 | *RPN = keep & 0xFFFFF000; |
| 196 | #if defined (DEBUG_MMU) | 198 | #if defined (DEBUG_MMU) |
| 197 | - if (loglevel > 0) { | 199 | + if (loglevel > 0) { |
| 198 | fprintf(logfile, "found PTE at addr 0x%08x prot=0x%01x ret=%d\n", | 200 | fprintf(logfile, "found PTE at addr 0x%08x prot=0x%01x ret=%d\n", |
| 199 | *RPN, *prot, ret); | 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,7 +207,7 @@ static int find_pte (uint32_t *RPN, int *prot, uint32_t base, uint32_t va, | ||
| 205 | keep |= 0x00000100; | 207 | keep |= 0x00000100; |
| 206 | store = 1; | 208 | store = 1; |
| 207 | } | 209 | } |
| 208 | - if (!(keep & 0x00000080)) { | 210 | + if (!(keep & 0x00000080)) { |
| 209 | if (rw && ret == 0) { | 211 | if (rw && ret == 0) { |
| 210 | /* Change flag */ | 212 | /* Change flag */ |
| 211 | keep |= 0x00000080; | 213 | keep |= 0x00000080; |
| @@ -251,7 +253,7 @@ static int get_segment (CPUState *env, uint32_t *real, int *prot, | @@ -251,7 +253,7 @@ static int get_segment (CPUState *env, uint32_t *real, int *prot, | ||
| 251 | ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0; | 253 | ((sr & 0x40000000) && msr_pr == 0)) ? 1 : 0; |
| 252 | if ((sr & 0x80000000) == 0) { | 254 | if ((sr & 0x80000000) == 0) { |
| 253 | #if defined (DEBUG_MMU) | 255 | #if defined (DEBUG_MMU) |
| 254 | - if (loglevel > 0) | 256 | + if (loglevel > 0) |
| 255 | fprintf(logfile, "pte segment: key=%d n=0x%08x\n", | 257 | fprintf(logfile, "pte segment: key=%d n=0x%08x\n", |
| 256 | key, sr & 0x10000000); | 258 | key, sr & 0x10000000); |
| 257 | #endif | 259 | #endif |
| @@ -604,7 +606,7 @@ void _store_xer (CPUState *env, uint32_t value) | @@ -604,7 +606,7 @@ void _store_xer (CPUState *env, uint32_t value) | ||
| 604 | xer_so = (value >> XER_SO) & 0x01; | 606 | xer_so = (value >> XER_SO) & 0x01; |
| 605 | xer_ov = (value >> XER_OV) & 0x01; | 607 | xer_ov = (value >> XER_OV) & 0x01; |
| 606 | xer_ca = (value >> XER_CA) & 0x01; | 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 | uint32_t _load_msr (CPUState *env) | 612 | uint32_t _load_msr (CPUState *env) |
| @@ -628,12 +630,12 @@ uint32_t _load_msr (CPUState *env) | @@ -628,12 +630,12 @@ uint32_t _load_msr (CPUState *env) | ||
| 628 | 630 | ||
| 629 | void _store_msr (CPUState *env, uint32_t value) | 631 | void _store_msr (CPUState *env, uint32_t value) |
| 630 | { | 632 | { |
| 631 | -#if 0 // TRY | 633 | +#ifdef ACCURATE_TLB_FLUSH |
| 632 | if (((value >> MSR_IR) & 0x01) != msr_ir || | 634 | if (((value >> MSR_IR) & 0x01) != msr_ir || |
| 633 | ((value >> MSR_DR) & 0x01) != msr_dr) | 635 | ((value >> MSR_DR) & 0x01) != msr_dr) |
| 634 | { | 636 | { |
| 635 | /* Flush all tlb when changing translation mode or privilege level */ | 637 | /* Flush all tlb when changing translation mode or privilege level */ |
| 636 | - tlb_flush(env, 1); | 638 | + tlb_flush(env, 1); |
| 637 | } | 639 | } |
| 638 | #endif | 640 | #endif |
| 639 | msr_pow = (value >> MSR_POW) & 0x03; | 641 | msr_pow = (value >> MSR_POW) & 0x03; |
| @@ -660,6 +662,13 @@ void do_interrupt (CPUState *env) | @@ -660,6 +662,13 @@ void do_interrupt (CPUState *env) | ||
| 660 | env->exception_index = -1; | 662 | env->exception_index = -1; |
| 661 | } | 663 | } |
| 662 | #else | 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 | void do_interrupt (CPUState *env) | 672 | void do_interrupt (CPUState *env) |
| 664 | { | 673 | { |
| 665 | uint32_t msr; | 674 | uint32_t msr; |
| @@ -707,11 +716,11 @@ void do_interrupt (CPUState *env) | @@ -707,11 +716,11 @@ void do_interrupt (CPUState *env) | ||
| 707 | */ | 716 | */ |
| 708 | msr &= ~0xFFFF0000; | 717 | msr &= ~0xFFFF0000; |
| 709 | env->spr[DSISR] = 0; | 718 | env->spr[DSISR] = 0; |
| 710 | - if (env->error_code & EXCP_DSI_TRANSLATE) | 719 | + if ((env->error_code & 0x0f) == EXCP_DSI_TRANSLATE) |
| 711 | env->spr[DSISR] |= 0x40000000; | 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 | env->spr[DSISR] |= 0x08000000; | 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 | env->spr[DSISR] |= 0x80000000; | 724 | env->spr[DSISR] |= 0x80000000; |
| 716 | if (env->error_code & EXCP_DSI_DIRECT) | 725 | if (env->error_code & EXCP_DSI_DIRECT) |
| 717 | env->spr[DSISR] |= 0x04000000; | 726 | env->spr[DSISR] |= 0x04000000; |
| @@ -819,28 +828,15 @@ void do_interrupt (CPUState *env) | @@ -819,28 +828,15 @@ void do_interrupt (CPUState *env) | ||
| 819 | } | 828 | } |
| 820 | goto store_next; | 829 | goto store_next; |
| 821 | case EXCP_SYSCALL: | 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 | if (loglevel & CPU_LOG_INT) { | 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 | goto store_next; | 841 | goto store_next; |
| 846 | case EXCP_TRACE: | 842 | case EXCP_TRACE: |
| @@ -887,6 +883,9 @@ void do_interrupt (CPUState *env) | @@ -887,6 +883,9 @@ void do_interrupt (CPUState *env) | ||
| 887 | env->nip = excp << 8; | 883 | env->nip = excp << 8; |
| 888 | env->exception_index = EXCP_NONE; | 884 | env->exception_index = EXCP_NONE; |
| 889 | /* Invalidate all TLB as we may have changed translation mode */ | 885 | /* Invalidate all TLB as we may have changed translation mode */ |
| 886 | +#ifdef ACCURATE_TLB_FLUSH | ||
| 887 | + tlb_flush(env, 1); | ||
| 888 | +#endif | ||
| 890 | /* ensure that no TB jump will be modified as | 889 | /* ensure that no TB jump will be modified as |
| 891 | the program flow was changed */ | 890 | the program flow was changed */ |
| 892 | #ifdef __sparc__ | 891 | #ifdef __sparc__ |