Commit c55e9aefa7c151176e2e88c0f79044580930a970

Authored by j_mayer
1 parent 0a032cbe

PowerPC 4xx software driven TLB fixes + debug traces.

Add code provision for more MMU models support.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2683 c046a42c-6fe2-441c-8c8c-71466251a162
target-ppc/cpu.h
... ... @@ -581,12 +581,12 @@ struct ppc6xx_tlb_t {
581 581  
582 582 typedef struct ppcemb_tlb_t ppcemb_tlb_t;
583 583 struct ppcemb_tlb_t {
584   - target_ulong RPN;
  584 + target_phys_addr_t RPN;
585 585 target_ulong EPN;
586 586 target_ulong PID;
587   - int size;
588   - int prot;
589   - int attr; /* Storage attributes */
  587 + target_ulong size;
  588 + uint32_t prot;
  589 + uint32_t attr; /* Storage attributes */
590 590 };
591 591  
592 592 union ppc_tlb_t {
... ... @@ -765,10 +765,6 @@ struct CPUPPCState {
765 765 int id_tlbs; /* If 1, MMU has separated TLBs for instructions & data */
766 766 int nb_pids; /* Number of available PID registers */
767 767 ppc_tlb_t *tlb; /* TLB is optional. Allocate them only if needed */
768   - /* Callbacks for specific checks on some implementations */
769   - int (*tlb_check_more)(CPUPPCState *env, ppc_tlb_t *tlb, int *prot,
770   - target_ulong vaddr, int rw, int acc_type,
771   - int is_user);
772 768 /* 403 dedicated access protection registers */
773 769 target_ulong pb[4];
774 770  
... ...
target-ppc/helper.c
... ... @@ -657,7 +657,8 @@ int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
657 657 target_ulong mask;
658 658 int i, ret, zsel, zpr;
659 659  
660   - ret = -6;
  660 + ret = -1;
  661 + raddr = -1;
661 662 for (i = 0; i < env->nb_tlb; i++) {
662 663 tlb = &env->tlb[i].tlbe;
663 664 /* Check valid flag */
... ... @@ -691,8 +692,8 @@ int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
691 692 switch (zpr) {
692 693 case 0x0:
693 694 if (msr_pr) {
694   - ret = -3;
695 695 ctx->prot = 0;
  696 + ret = -3;
696 697 break;
697 698 }
698 699 /* No break here */
... ... @@ -702,25 +703,26 @@ int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
702 703 if (!(tlb->prot & PAGE_EXEC)) {
703 704 ret = -3;
704 705 } else {
705   - if (tlb->prot & PAGE_WRITE)
  706 + if (tlb->prot & PAGE_WRITE) {
706 707 ctx->prot = PAGE_READ | PAGE_WRITE;
707   - else
  708 + } else {
708 709 ctx->prot = PAGE_READ;
  710 + }
709 711 ret = 0;
710 712 }
711 713 break;
712 714 case 0x3:
713 715 /* All accesses granted */
714   - ret = 0;
715 716 ctx->prot = PAGE_READ | PAGE_WRITE;
  717 + ret = 0;
716 718 break;
717 719 }
718 720 } else {
719 721 switch (zpr) {
720 722 case 0x0:
721 723 if (msr_pr) {
722   - ret = -2;
723 724 ctx->prot = 0;
  725 + ret = -2;
724 726 break;
725 727 }
726 728 /* No break here */
... ... @@ -728,20 +730,21 @@ int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
728 730 case 0x2:
729 731 /* Check from TLB entry */
730 732 /* Check write protection bit */
731   - if (rw && !(tlb->prot & PAGE_WRITE)) {
732   - ret = -2;
  733 + if (tlb->prot & PAGE_WRITE) {
  734 + ctx->prot = PAGE_READ | PAGE_WRITE;
  735 + ret = 0;
733 736 } else {
734   - ret = 2;
735   - if (tlb->prot & PAGE_WRITE)
736   - ctx->prot = PAGE_READ | PAGE_WRITE;
  737 + ctx->prot = PAGE_READ;
  738 + if (rw)
  739 + ret = -2;
737 740 else
738   - ctx->prot = PAGE_READ;
  741 + ret = 0;
739 742 }
740 743 break;
741 744 case 0x3:
742 745 /* All accesses granted */
743   - ret = 2;
744 746 ctx->prot = PAGE_READ | PAGE_WRITE;
  747 + ret = 0;
745 748 break;
746 749 }
747 750 }
... ... @@ -749,11 +752,17 @@ int mmu4xx_get_physical_address (CPUState *env, mmu_ctx_t *ctx,
749 752 ctx->raddr = raddr;
750 753 if (loglevel) {
751 754 fprintf(logfile, "%s: access granted " ADDRX " => " REGX
752   - " %d\n", __func__, address, ctx->raddr, ctx->prot);
  755 + " %d %d\n", __func__, address, ctx->raddr, ctx->prot,
  756 + ret);
753 757 }
754   - return i;
  758 + return 0;
755 759 }
756 760 }
  761 + if (loglevel) {
  762 + fprintf(logfile, "%s: access refused " ADDRX " => " REGX
  763 + " %d %d\n", __func__, address, raddr, ctx->prot,
  764 + ret);
  765 + }
757 766  
758 767 return ret;
759 768 }
... ... @@ -808,32 +817,49 @@ int get_physical_address (CPUState *env, mmu_ctx_t *ctx, target_ulong eaddr,
808 817 /* No address translation */
809 818 ret = check_physical(env, ctx, eaddr, rw);
810 819 } else {
  820 + ret = -1;
811 821 switch (PPC_MMU(env)) {
812 822 case PPC_FLAGS_MMU_32B:
813 823 case PPC_FLAGS_MMU_SOFT_6xx:
814 824 /* Try to find a BAT */
815   - ret = -1;
816 825 if (check_BATs)
817 826 ret = get_bat(env, ctx, eaddr, rw, access_type);
  827 + /* No break here */
  828 +#if defined(TARGET_PPC64)
  829 + case PPC_FLAGS_MMU_64B:
  830 + case PPC_FLAGS_MMU_64BRIDGE:
  831 +#endif
818 832 if (ret < 0) {
819   - /* We didn't match any BAT entry */
  833 + /* We didn't match any BAT entry or don't have BATs */
820 834 ret = get_segment(env, ctx, eaddr, rw, access_type);
821 835 }
822 836 break;
823 837 case PPC_FLAGS_MMU_SOFT_4xx:
  838 + case PPC_FLAGS_MMU_403:
824 839 ret = mmu4xx_get_physical_address(env, ctx, eaddr,
825 840 rw, access_type);
826 841 break;
827   - default:
  842 + case PPC_FLAGS_MMU_601:
  843 + /* XXX: TODO */
  844 + cpu_abort(env, "601 MMU model not implemented\n");
  845 + return -1;
  846 + case PPC_FLAGS_MMU_BOOKE:
828 847 /* XXX: TODO */
829   - cpu_abort(env, "MMU model not implemented\n");
  848 + cpu_abort(env, "BookeE MMU model not implemented\n");
  849 + return -1;
  850 + case PPC_FLAGS_MMU_BOOKE_FSL:
  851 + /* XXX: TODO */
  852 + cpu_abort(env, "BookE FSL MMU model not implemented\n");
  853 + return -1;
  854 + default:
  855 + cpu_abort(env, "Unknown or invalid MMU model\n");
830 856 return -1;
831 857 }
832 858 }
833 859 #if 0
834 860 if (loglevel > 0) {
835   - fprintf(logfile, "%s address " ADDRX " => " ADDRX "\n",
836   - __func__, eaddr, ctx->raddr);
  861 + fprintf(logfile, "%s address " ADDRX " => %d " ADDRX "\n",
  862 + __func__, eaddr, ret, ctx->raddr);
837 863 }
838 864 #endif
839 865  
... ... @@ -885,19 +911,48 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
885 911 switch (ret) {
886 912 case -1:
887 913 /* No matches in page tables or TLB */
888   - if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
  914 + switch (PPC_MMU(env)) {
  915 + case PPC_FLAGS_MMU_SOFT_6xx:
889 916 exception = EXCP_I_TLBMISS;
890 917 env->spr[SPR_IMISS] = address;
891 918 env->spr[SPR_ICMP] = 0x80000000 | ctx.ptem;
892 919 error_code = 1 << 18;
893 920 goto tlb_miss;
894   - } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
  921 + case PPC_FLAGS_MMU_SOFT_4xx:
  922 + case PPC_FLAGS_MMU_403:
895 923 exception = EXCP_40x_ITLBMISS;
896 924 error_code = 0;
897 925 env->spr[SPR_40x_DEAR] = address;
898 926 env->spr[SPR_40x_ESR] = 0x00000000;
899   - } else {
  927 + break;
  928 + case PPC_FLAGS_MMU_32B:
900 929 error_code = 0x40000000;
  930 + break;
  931 +#if defined(TARGET_PPC64)
  932 + case PPC_FLAGS_MMU_64B:
  933 + /* XXX: TODO */
  934 + cpu_abort(env, "MMU model not implemented\n");
  935 + return -1;
  936 + case PPC_FLAGS_MMU_64BRIDGE:
  937 + /* XXX: TODO */
  938 + cpu_abort(env, "MMU model not implemented\n");
  939 + return -1;
  940 +#endif
  941 + case PPC_FLAGS_MMU_601:
  942 + /* XXX: TODO */
  943 + cpu_abort(env, "MMU model not implemented\n");
  944 + return -1;
  945 + case PPC_FLAGS_MMU_BOOKE:
  946 + /* XXX: TODO */
  947 + cpu_abort(env, "MMU model not implemented\n");
  948 + return -1;
  949 + case PPC_FLAGS_MMU_BOOKE_FSL:
  950 + /* XXX: TODO */
  951 + cpu_abort(env, "MMU model not implemented\n");
  952 + return -1;
  953 + default:
  954 + cpu_abort(env, "Unknown or invalid MMU model\n");
  955 + return -1;
901 956 }
902 957 break;
903 958 case -2:
... ... @@ -924,7 +979,8 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
924 979 switch (ret) {
925 980 case -1:
926 981 /* No matches in page tables or TLB */
927   - if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_6xx)) {
  982 + switch (PPC_MMU(env)) {
  983 + case PPC_FLAGS_MMU_SOFT_6xx:
928 984 if (rw == 1) {
929 985 exception = EXCP_DS_TLBMISS;
930 986 error_code = 1 << 16;
... ... @@ -940,7 +996,8 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
940 996 env->spr[SPR_HASH2] = ctx.pg_addr[1];
941 997 /* Do not alter DAR nor DSISR */
942 998 goto out;
943   - } else if (unlikely(PPC_MMU(env) == PPC_FLAGS_MMU_SOFT_4xx)) {
  999 + case PPC_FLAGS_MMU_SOFT_4xx:
  1000 + case PPC_FLAGS_MMU_403:
944 1001 exception = EXCP_40x_DTLBMISS;
945 1002 error_code = 0;
946 1003 env->spr[SPR_40x_DEAR] = address;
... ... @@ -948,8 +1005,35 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
948 1005 env->spr[SPR_40x_ESR] = 0x00800000;
949 1006 else
950 1007 env->spr[SPR_40x_ESR] = 0x00000000;
951   - } else {
  1008 + break;
  1009 + case PPC_FLAGS_MMU_32B:
952 1010 error_code = 0x40000000;
  1011 + break;
  1012 +#if defined(TARGET_PPC64)
  1013 + case PPC_FLAGS_MMU_64B:
  1014 + /* XXX: TODO */
  1015 + cpu_abort(env, "MMU model not implemented\n");
  1016 + return -1;
  1017 + case PPC_FLAGS_MMU_64BRIDGE:
  1018 + /* XXX: TODO */
  1019 + cpu_abort(env, "MMU model not implemented\n");
  1020 + return -1;
  1021 +#endif
  1022 + case PPC_FLAGS_MMU_601:
  1023 + /* XXX: TODO */
  1024 + cpu_abort(env, "MMU model not implemented\n");
  1025 + return -1;
  1026 + case PPC_FLAGS_MMU_BOOKE:
  1027 + /* XXX: TODO */
  1028 + cpu_abort(env, "MMU model not implemented\n");
  1029 + return -1;
  1030 + case PPC_FLAGS_MMU_BOOKE_FSL:
  1031 + /* XXX: TODO */
  1032 + cpu_abort(env, "MMU model not implemented\n");
  1033 + return -1;
  1034 + default:
  1035 + cpu_abort(env, "Unknown or invalid MMU model\n");
  1036 + return -1;
953 1037 }
954 1038 break;
955 1039 case -2:
... ...
target-ppc/op_helper.c
... ... @@ -2537,39 +2537,72 @@ void do_4xx_tlbsx_ (void)
2537 2537 env->crf[0] = tmp;
2538 2538 }
2539 2539  
2540   -void do_4xx_tlbwe_lo (void)
  2540 +void do_4xx_tlbwe_hi (void)
2541 2541 {
2542 2542 ppcemb_tlb_t *tlb;
2543 2543 target_ulong page, end;
2544 2544  
  2545 +#if defined (DEBUG_SOFTWARE_TLB)
  2546 + if (loglevel) {
  2547 + fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
  2548 + }
  2549 +#endif
2545 2550 T0 &= 0x3F;
2546 2551 tlb = &env->tlb[T0].tlbe;
2547 2552 /* Invalidate previous TLB (if it's valid) */
2548 2553 if (tlb->prot & PAGE_VALID) {
2549 2554 end = tlb->EPN + tlb->size;
  2555 +#if defined (DEBUG_SOFTWARE_TLB)
  2556 + if (loglevel) {
  2557 + fprintf(logfile, "%s: invalidate old TLB %d start " ADDRX
  2558 + " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
  2559 + }
  2560 +#endif
2550 2561 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2551 2562 tlb_flush_page(env, page);
2552 2563 }
2553 2564 tlb->size = booke_tlb_to_page_size((T1 >> 7) & 0x7);
2554 2565 tlb->EPN = (T1 & 0xFFFFFC00) & ~(tlb->size - 1);
2555   - if (T1 & 0x400)
  2566 + if (T1 & 0x40)
2556 2567 tlb->prot |= PAGE_VALID;
2557 2568 else
2558 2569 tlb->prot &= ~PAGE_VALID;
2559   - tlb->PID = env->spr[SPR_BOOKE_PID]; /* PID */
  2570 + tlb->PID = env->spr[SPR_40x_PID]; /* PID */
2560 2571 tlb->attr = T1 & 0xFF;
  2572 +#if defined (DEBUG_SOFTWARE_TLB)
  2573 + if (loglevel) {
  2574 + fprintf(logfile, "%s: set up TLB %d RPN " ADDRX " EPN " ADDRX
  2575 + " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
  2576 + (int)T0, tlb->RPN, tlb->EPN, tlb->size,
  2577 + tlb->prot & PAGE_READ ? 'r' : '-',
  2578 + tlb->prot & PAGE_WRITE ? 'w' : '-',
  2579 + tlb->prot & PAGE_EXEC ? 'x' : '-',
  2580 + tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
  2581 + }
  2582 +#endif
2561 2583 /* Invalidate new TLB (if valid) */
2562 2584 if (tlb->prot & PAGE_VALID) {
2563 2585 end = tlb->EPN + tlb->size;
  2586 +#if defined (DEBUG_SOFTWARE_TLB)
  2587 + if (loglevel) {
  2588 + fprintf(logfile, "%s: invalidate TLB %d start " ADDRX
  2589 + " end " ADDRX "\n", __func__, (int)T0, tlb->EPN, end);
  2590 + }
  2591 +#endif
2564 2592 for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE)
2565 2593 tlb_flush_page(env, page);
2566 2594 }
2567 2595 }
2568 2596  
2569   -void do_4xx_tlbwe_hi (void)
  2597 +void do_4xx_tlbwe_lo (void)
2570 2598 {
2571 2599 ppcemb_tlb_t *tlb;
2572 2600  
  2601 +#if defined (DEBUG_SOFTWARE_TLB)
  2602 + if (loglevel) {
  2603 + fprintf(logfile, "%s T0 " REGX " T1 " REGX "\n", __func__, T0, T1);
  2604 + }
  2605 +#endif
2573 2606 T0 &= 0x3F;
2574 2607 tlb = &env->tlb[T0].tlbe;
2575 2608 tlb->RPN = T1 & 0xFFFFFC00;
... ... @@ -2578,5 +2611,16 @@ void do_4xx_tlbwe_hi (void)
2578 2611 tlb->prot |= PAGE_EXEC;
2579 2612 if (T1 & 0x100)
2580 2613 tlb->prot |= PAGE_WRITE;
  2614 +#if defined (DEBUG_SOFTWARE_TLB)
  2615 + if (loglevel) {
  2616 + fprintf(logfile, "%s: set up TLB %d RPN " ADDRX " EPN " ADDRX
  2617 + " size " ADDRX " prot %c%c%c%c PID %d\n", __func__,
  2618 + (int)T0, tlb->RPN, tlb->EPN, tlb->size,
  2619 + tlb->prot & PAGE_READ ? 'r' : '-',
  2620 + tlb->prot & PAGE_WRITE ? 'w' : '-',
  2621 + tlb->prot & PAGE_EXEC ? 'x' : '-',
  2622 + tlb->prot & PAGE_VALID ? 'v' : '-', (int)tlb->PID);
  2623 + }
  2624 +#endif
2581 2625 }
2582 2626 #endif /* !CONFIG_USER_ONLY */
... ...