diff mbox

[v2,4/9] target-mips: add RI and XI fields to TLB entry

Message ID 1404806257-28048-5-git-send-email-leon.alrae@imgtec.com
State New
Headers show

Commit Message

Leon Alrae July 8, 2014, 7:57 a.m. UTC
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 <leon.alrae@imgtec.com>
---
 target-mips/cpu.h       |   11 +++++++++++
 target-mips/helper.c    |   11 ++++++++++-
 target-mips/op_helper.c |    8 ++++++++
 3 files changed, 29 insertions(+), 1 deletions(-)

Comments

Yongbok Kim Oct. 15, 2014, 12:24 p.m. UTC | #1
On 08/07/2014 08:57, Leon Alrae wrote:
> 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 <leon.alrae@imgtec.com>
> ---
>   target-mips/cpu.h       |   11 +++++++++++
>   target-mips/helper.c    |   11 ++++++++++-
>   target-mips/op_helper.c |    8 ++++++++
>   3 files changed, 29 insertions(+), 1 deletions(-)
>
> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
> index 4f6aa5b..5afafd7 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 9871273..6aa8c8a 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;

PC relative loads are allowed where execute is allowed (even though RI 
is 1).
Rather than just return RI here have to check XI and its OP code.

> +            }
>               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 b8d384a..3f39305 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);
>   }
>   

Regards,
Yongbok
Leon Alrae Oct. 24, 2014, 2:16 p.m. UTC | #2
On 15/10/2014 13:24, Yongbok Kim wrote:
> 
> On 08/07/2014 08:57, Leon Alrae wrote:
>> 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 <leon.alrae@imgtec.com>
>> ---
>>   target-mips/cpu.h       |   11 +++++++++++
>>   target-mips/helper.c    |   11 ++++++++++-
>>   target-mips/op_helper.c |    8 ++++++++
>>   3 files changed, 29 insertions(+), 1 deletions(-)
>>
>> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
>> index 4f6aa5b..5afafd7 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 9871273..6aa8c8a 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;
> 
> PC relative loads are allowed where execute is allowed (even though RI
> is 1).
> Rather than just return RI here have to check XI and its OP code.

This is true only for MIPS16 PC-relative loads. New R6 PC-relative loads
do cause TLBRI exceptions. Thus in context of Release 6 current
implementation is correct. I agree this will need to be corrected for
MIPS16, but not necessarily in this patchset.

Regards,
Leon
Yongbok Kim Oct. 24, 2014, 2:27 p.m. UTC | #3
On 24/10/2014 15:16, Leon Alrae wrote:
> On 15/10/2014 13:24, Yongbok Kim wrote:
>> On 08/07/2014 08:57, Leon Alrae wrote:
>>> 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 <leon.alrae@imgtec.com>
>>> ---
>>>    target-mips/cpu.h       |   11 +++++++++++
>>>    target-mips/helper.c    |   11 ++++++++++-
>>>    target-mips/op_helper.c |    8 ++++++++
>>>    3 files changed, 29 insertions(+), 1 deletions(-)
>>>
>>> diff --git a/target-mips/cpu.h b/target-mips/cpu.h
>>> index 4f6aa5b..5afafd7 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 9871273..6aa8c8a 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;
>> PC relative loads are allowed where execute is allowed (even though RI
>> is 1).
>> Rather than just return RI here have to check XI and its OP code.
> This is true only for MIPS16 PC-relative loads. New R6 PC-relative loads
> do cause TLBRI exceptions. Thus in context of Release 6 current
> implementation is correct. I agree this will need to be corrected for
> MIPS16, but not necessarily in this patchset.
>
> Regards,
> Leon
>
Agreed.

Regards,
Yongbok
diff mbox

Patch

diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 4f6aa5b..5afafd7 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 9871273..6aa8c8a 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 b8d384a..3f39305 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);
 }