Revision 999fa40e target-ppc/op_helper.c
b/target-ppc/op_helper.c | ||
---|---|---|
3929 | 3929 |
} |
3930 | 3930 |
|
3931 | 3931 |
/* Helpers for 4xx TLB management */ |
3932 |
target_ulong helper_4xx_tlbre_lo (target_ulong entry) |
|
3932 |
#define PPC4XX_TLB_ENTRY_MASK 0x0000003f /* Mask for 64 TLB entries */ |
|
3933 |
|
|
3934 |
#define PPC4XX_TLBHI_V 0x00000040 |
|
3935 |
#define PPC4XX_TLBHI_E 0x00000020 |
|
3936 |
#define PPC4XX_TLBHI_SIZE_MIN 0 |
|
3937 |
#define PPC4XX_TLBHI_SIZE_MAX 7 |
|
3938 |
#define PPC4XX_TLBHI_SIZE_DEFAULT 1 |
|
3939 |
#define PPC4XX_TLBHI_SIZE_SHIFT 7 |
|
3940 |
#define PPC4XX_TLBHI_SIZE_MASK 0x00000007 |
|
3941 |
|
|
3942 |
#define PPC4XX_TLBLO_EX 0x00000200 |
|
3943 |
#define PPC4XX_TLBLO_WR 0x00000100 |
|
3944 |
#define PPC4XX_TLBLO_ATTR_MASK 0x000000FF |
|
3945 |
#define PPC4XX_TLBLO_RPN_MASK 0xFFFFFC00 |
|
3946 |
|
|
3947 |
target_ulong helper_4xx_tlbre_hi (target_ulong entry) |
|
3933 | 3948 |
{ |
3934 | 3949 |
ppcemb_tlb_t *tlb; |
3935 | 3950 |
target_ulong ret; |
3936 | 3951 |
int size; |
3937 | 3952 |
|
3938 |
entry &= 0x3F;
|
|
3953 |
entry &= PPC4XX_TLB_ENTRY_MASK;
|
|
3939 | 3954 |
tlb = &env->tlb[entry].tlbe; |
3940 | 3955 |
ret = tlb->EPN; |
3941 |
if (tlb->prot & PAGE_VALID) |
|
3942 |
ret |= 0x400; |
|
3956 |
if (tlb->prot & PAGE_VALID) { |
|
3957 |
ret |= PPC4XX_TLBHI_V; |
|
3958 |
} |
|
3943 | 3959 |
size = booke_page_size_to_tlb(tlb->size); |
3944 |
if (size < 0 || size > 0x7) |
|
3945 |
size = 1; |
|
3946 |
ret |= size << 7; |
|
3960 |
if (size < PPC4XX_TLBHI_SIZE_MIN || size > PPC4XX_TLBHI_SIZE_MAX) { |
|
3961 |
size = PPC4XX_TLBHI_SIZE_DEFAULT; |
|
3962 |
} |
|
3963 |
ret |= size << PPC4XX_TLBHI_SIZE_SHIFT; |
|
3947 | 3964 |
env->spr[SPR_40x_PID] = tlb->PID; |
3948 | 3965 |
return ret; |
3949 | 3966 |
} |
3950 | 3967 |
|
3951 |
target_ulong helper_4xx_tlbre_hi (target_ulong entry)
|
|
3968 |
target_ulong helper_4xx_tlbre_lo (target_ulong entry)
|
|
3952 | 3969 |
{ |
3953 | 3970 |
ppcemb_tlb_t *tlb; |
3954 | 3971 |
target_ulong ret; |
3955 | 3972 |
|
3956 |
entry &= 0x3F;
|
|
3973 |
entry &= PPC4XX_TLB_ENTRY_MASK;
|
|
3957 | 3974 |
tlb = &env->tlb[entry].tlbe; |
3958 | 3975 |
ret = tlb->RPN; |
3959 |
if (tlb->prot & PAGE_EXEC) |
|
3960 |
ret |= 0x200; |
|
3961 |
if (tlb->prot & PAGE_WRITE) |
|
3962 |
ret |= 0x100; |
|
3976 |
if (tlb->prot & PAGE_EXEC) { |
|
3977 |
ret |= PPC4XX_TLBLO_EX; |
|
3978 |
} |
|
3979 |
if (tlb->prot & PAGE_WRITE) { |
|
3980 |
ret |= PPC4XX_TLBLO_WR; |
|
3981 |
} |
|
3963 | 3982 |
return ret; |
3964 | 3983 |
} |
3965 | 3984 |
|
... | ... | |
3970 | 3989 |
|
3971 | 3990 |
LOG_SWTLB("%s entry %d val " TARGET_FMT_lx "\n", __func__, (int)entry, |
3972 | 3991 |
val); |
3973 |
entry &= 0x3F;
|
|
3992 |
entry &= PPC4XX_TLB_ENTRY_MASK;
|
|
3974 | 3993 |
tlb = &env->tlb[entry].tlbe; |
3975 | 3994 |
/* Invalidate previous TLB (if it's valid) */ |
3976 | 3995 |
if (tlb->prot & PAGE_VALID) { |
3977 | 3996 |
end = tlb->EPN + tlb->size; |
3978 | 3997 |
LOG_SWTLB("%s: invalidate old TLB %d start " TARGET_FMT_lx " end " |
3979 | 3998 |
TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end); |
3980 |
for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) |
|
3999 |
for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
|
|
3981 | 4000 |
tlb_flush_page(env, page); |
4001 |
} |
|
3982 | 4002 |
} |
3983 |
tlb->size = booke_tlb_to_page_size((val >> 7) & 0x7); |
|
4003 |
tlb->size = booke_tlb_to_page_size((val >> PPC4XX_TLBHI_SIZE_SHIFT) |
|
4004 |
& PPC4XX_TLBHI_SIZE_MASK); |
|
3984 | 4005 |
/* We cannot handle TLB size < TARGET_PAGE_SIZE. |
3985 | 4006 |
* If this ever occurs, one should use the ppcemb target instead |
3986 | 4007 |
* of the ppc or ppc64 one |
3987 | 4008 |
*/ |
3988 |
if ((val & 0x40) && tlb->size < TARGET_PAGE_SIZE) {
|
|
4009 |
if ((val & PPC4XX_TLBHI_V) && tlb->size < TARGET_PAGE_SIZE) {
|
|
3989 | 4010 |
cpu_abort(env, "TLB size " TARGET_FMT_lu " < %u " |
3990 | 4011 |
"are not supported (%d)\n", |
3991 | 4012 |
tlb->size, TARGET_PAGE_SIZE, (int)((val >> 7) & 0x7)); |
3992 | 4013 |
} |
3993 | 4014 |
tlb->EPN = val & ~(tlb->size - 1); |
3994 |
if (val & 0x40) {
|
|
4015 |
if (val & PPC4XX_TLBHI_V) {
|
|
3995 | 4016 |
tlb->prot |= PAGE_VALID; |
3996 |
if (val & 0x20) {
|
|
4017 |
if (val & PPC4XX_TLBHI_E) {
|
|
3997 | 4018 |
/* XXX: TO BE FIXED */ |
3998 | 4019 |
cpu_abort(env, |
3999 | 4020 |
"Little-endian TLB entries are not supported by now\n"); |
... | ... | |
4014 | 4035 |
end = tlb->EPN + tlb->size; |
4015 | 4036 |
LOG_SWTLB("%s: invalidate TLB %d start " TARGET_FMT_lx " end " |
4016 | 4037 |
TARGET_FMT_lx "\n", __func__, (int)entry, tlb->EPN, end); |
4017 |
for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) |
|
4038 |
for (page = tlb->EPN; page < end; page += TARGET_PAGE_SIZE) {
|
|
4018 | 4039 |
tlb_flush_page(env, page); |
4040 |
} |
|
4019 | 4041 |
} |
4020 | 4042 |
} |
4021 | 4043 |
|
... | ... | |
4025 | 4047 |
|
4026 | 4048 |
LOG_SWTLB("%s entry %i val " TARGET_FMT_lx "\n", __func__, (int)entry, |
4027 | 4049 |
val); |
4028 |
entry &= 0x3F;
|
|
4050 |
entry &= PPC4XX_TLB_ENTRY_MASK;
|
|
4029 | 4051 |
tlb = &env->tlb[entry].tlbe; |
4030 |
tlb->attr = val & 0xFF;
|
|
4031 |
tlb->RPN = val & 0xFFFFFC00;
|
|
4052 |
tlb->attr = val & PPC4XX_TLBLO_ATTR_MASK;
|
|
4053 |
tlb->RPN = val & PPC4XX_TLBLO_RPN_MASK;
|
|
4032 | 4054 |
tlb->prot = PAGE_READ; |
4033 |
if (val & 0x200)
|
|
4055 |
if (val & PPC4XX_TLBLO_EX) {
|
|
4034 | 4056 |
tlb->prot |= PAGE_EXEC; |
4035 |
if (val & 0x100) |
|
4057 |
} |
|
4058 |
if (val & PPC4XX_TLBLO_WR) { |
|
4036 | 4059 |
tlb->prot |= PAGE_WRITE; |
4060 |
} |
|
4037 | 4061 |
LOG_SWTLB("%s: set up TLB %d RPN " TARGET_FMT_plx " EPN " TARGET_FMT_lx |
4038 | 4062 |
" size " TARGET_FMT_lx " prot %c%c%c%c PID %d\n", __func__, |
4039 | 4063 |
(int)entry, tlb->RPN, tlb->EPN, tlb->size, |
Also available in: Unified diff