Revision c55e9aef target-ppc/helper.c
b/target-ppc/helper.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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: |
Also available in: Unified diff