From 2fb58b73746e2f99ac85e82160277b18b18279be Mon Sep 17 00:00:00 2001 From: Leon Alrae Date: Mon, 7 Jul 2014 11:23:58 +0100 Subject: [PATCH] target-mips: add RI and XI fields to TLB entry In Revision 3 of the architecture, the RI and XI bits were added to the TLB to enable more secure access of memory pages. These bits (along with the Dirty bit) allow the implementation of read-only, write-only, no-execute access policies for mapped pages. Signed-off-by: Leon Alrae Reviewed-by: Yongbok Kim --- target-mips/cpu.h | 11 +++++++++++ target-mips/helper.c | 11 ++++++++++- target-mips/op_helper.c | 8 ++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 91e781e26a..13f3a48198 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -30,6 +30,10 @@ struct r4k_tlb_t { uint_fast16_t V1:1; uint_fast16_t D0:1; uint_fast16_t D1:1; + uint_fast16_t XI0:1; + uint_fast16_t XI1:1; + uint_fast16_t RI0:1; + uint_fast16_t RI1:1; target_ulong PFN[2]; }; @@ -229,6 +233,13 @@ struct CPUMIPSState { #define CP0VPEOpt_DWX0 0 target_ulong CP0_EntryLo0; target_ulong CP0_EntryLo1; +#if defined(TARGET_MIPS64) +# define CP0EnLo_RI 63 +# define CP0EnLo_XI 62 +#else +# define CP0EnLo_RI 31 +# define CP0EnLo_XI 30 +#endif target_ulong CP0_Context; target_ulong CP0_KScratch[MIPS_KSCRATCH_NUM]; int32_t CP0_PageMask; diff --git a/target-mips/helper.c b/target-mips/helper.c index 1c9e69d8f4..49187a3d08 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -27,6 +27,8 @@ #include "sysemu/kvm.h" enum { + TLBRET_XI = -6, + TLBRET_RI = -5, TLBRET_DIRTY = -4, TLBRET_INVALID = -3, TLBRET_NOMATCH = -2, @@ -85,8 +87,15 @@ int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, /* TLB match */ int n = !!(address & mask & ~(mask >> 1)); /* Check access rights */ - if (!(n ? tlb->V1 : tlb->V0)) + if (!(n ? tlb->V1 : tlb->V0)) { return TLBRET_INVALID; + } + if (rw == MMU_INST_FETCH && (n ? tlb->XI1 : tlb->XI0)) { + return TLBRET_XI; + } + if (rw == MMU_DATA_LOAD && (n ? tlb->RI1 : tlb->RI0)) { + return TLBRET_RI; + } if (rw != MMU_DATA_STORE || (n ? tlb->D1 : tlb->D0)) { *physical = tlb->PFN[n] | (address & (mask >> 1)); *prot = PAGE_READ; diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 9ec548cc02..582c84e1a4 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1849,10 +1849,14 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx) tlb->V0 = (env->CP0_EntryLo0 & 2) != 0; tlb->D0 = (env->CP0_EntryLo0 & 4) != 0; tlb->C0 = (env->CP0_EntryLo0 >> 3) & 0x7; + tlb->XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1; + tlb->RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1; tlb->PFN[0] = (env->CP0_EntryLo0 >> 6) << 12; tlb->V1 = (env->CP0_EntryLo1 & 2) != 0; tlb->D1 = (env->CP0_EntryLo1 & 4) != 0; tlb->C1 = (env->CP0_EntryLo1 >> 3) & 0x7; + tlb->XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1; + tlb->RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1; tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12; } @@ -1964,8 +1968,12 @@ void r4k_helper_tlbr(CPUMIPSState *env) env->CP0_EntryHi = tlb->VPN | tlb->ASID; env->CP0_PageMask = tlb->PageMask; env->CP0_EntryLo0 = tlb->G | (tlb->V0 << 1) | (tlb->D0 << 2) | + ((target_ulong)tlb->RI0 << CP0EnLo_RI) | + ((target_ulong)tlb->XI0 << CP0EnLo_XI) | (tlb->C0 << 3) | (tlb->PFN[0] >> 6); env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | + ((target_ulong)tlb->RI1 << CP0EnLo_RI) | + ((target_ulong)tlb->XI1 << CP0EnLo_XI) | (tlb->C1 << 3) | (tlb->PFN[1] >> 6); }