| 
15 | 15 |  * limitations under the License.  | 
16 | 16 |  */  | 
17 | 17 | #include <uvisor.h>  | 
 | 18 | +#include <stdbool.h>  | 
18 | 19 | #include "context.h"  | 
19 |  | -#include "debug.h"  | 
20 |  | -#include "vmpu.h"  | 
 | 20 | +#include "halt.h"  | 
 | 21 | +#include "vmpu_mpu.h"  | 
21 | 22 | #include "vmpu_unpriv_access.h"  | 
22 |  | -#include <stdbool.h>  | 
23 |  | - | 
24 |  | -#define TT_RESP_IREGION_Pos     24U  | 
25 |  | -#define TT_RESP_IREGION_Msk     (0xFFUL << TT_RESP_IREGION_Pos)  | 
26 |  | - | 
27 |  | -#define TT_RESP_IRVALID_Pos     23U  | 
28 |  | -#define TT_RESP_IRVALID_Msk     (1UL << TT_RESP_IRVALID_Pos)  | 
29 |  | - | 
30 |  | -#define TT_RESP_S_Pos           22U  | 
31 |  | -#define TT_RESP_S_Msk           (1UL << TT_RESP_S_Pos)  | 
32 |  | - | 
33 |  | -#define TT_RESP_NSRW_Pos        21U  | 
34 |  | -#define TT_RESP_NSRW_Msk        (1UL << TT_RESP_NSRW_Pos)  | 
35 |  | - | 
36 |  | -#define TT_RESP_NSR_Pos         20U  | 
37 |  | -#define TT_RESP_NSR_Msk         (1UL << TT_RESP_NSR_Pos)  | 
38 |  | - | 
39 |  | -#define TT_RESP_RW_Pos          19U  | 
40 |  | -#define TT_RESP_RW_Msk          (1UL << TT_RESP_RW_Pos)  | 
41 |  | - | 
42 |  | -#define TT_RESP_R_Pos           18U  | 
43 |  | -#define TT_RESP_R_Msk           (1UL << TT_RESP_R_Pos)  | 
44 |  | - | 
45 |  | -#define TT_RESP_SRVALID_Pos     17U  | 
46 |  | -#define TT_RESP_SRVALID_Msk     (1UL << TT_RESP_SRVALID_Pos)  | 
47 |  | - | 
48 |  | -#define TT_RESP_MRVALID_Pos     16U  | 
49 |  | -#define TT_RESP_MRVALID_Msk     (1UL << TT_RESP_MRVALID_Pos)  | 
50 |  | - | 
51 |  | -#define TT_RESP_SREGION_Pos     8U  | 
52 |  | -#define TT_RESP_SREGION_Msk     (0xFFUL << TT_RESP_SREGION_Pos)  | 
53 |  | - | 
54 |  | -#define TT_RESP_MREGION_Pos     0U  | 
55 |  | -#define TT_RESP_MREGION_Msk     (0xFFUL << TT_RESP_MREGION_Pos)  | 
56 |  | - | 
57 |  | - | 
58 |  | -static uint32_t vmpu_unpriv_test_range(uint32_t addr, uint32_t size)  | 
59 |  | -{  | 
60 |  | -    if (!size) size = 1;  | 
61 |  | -    uint32_t response_lower, response_upper;  | 
62 |  | -    uint32_t test_addr_lower = addr & ~31UL;  | 
63 |  | -    uint32_t test_addr_upper = (addr + size - 1) & ~31UL;  | 
64 |  | - | 
65 |  | -    /* Test lower address. */  | 
66 |  | -    asm volatile (  | 
67 |  | -        "tta %[response], %[addr]"  | 
68 |  | -        : [response] "=r" (response_lower)  | 
69 |  | -        : [addr] "r" (test_addr_lower)  | 
70 |  | -    );  | 
71 |  | -    if (test_addr_lower != test_addr_upper) {  | 
72 |  | -        /* Test upper address. */  | 
73 |  | -        asm volatile (  | 
74 |  | -            "tta %[response], %[addr]"  | 
75 |  | -            : [response] "=r" (response_upper)  | 
76 |  | -            : [addr] "r" (test_addr_upper)  | 
77 |  | -        );  | 
78 |  | -        /* If lower and upper do not have the same S|SRVALID|SREGION, then it's definitely not the same region. */  | 
79 |  | -        if (((response_lower ^ response_upper) & (TT_RESP_S_Msk | TT_RESP_SRVALID_Msk | TT_RESP_SREGION_Msk))) {  | 
80 |  | -            /* Upper memory region has different SAU region than lower memory region! */  | 
81 |  | -            return 0;  | 
82 |  | -        }  | 
83 |  | -        /* Both memory locations have the same non-secure SAU region and therefore same properties.  | 
84 |  | -         * No Secure SAU region can be inbetween due to SAU region overlap rules. */  | 
85 |  | -        response_lower &= response_upper;  | 
86 |  | -    }  | 
87 |  | - | 
88 |  | -    return response_lower & (TT_RESP_NSRW_Msk | TT_RESP_NSR_Msk | TT_RESP_RW_Msk | TT_RESP_R_Msk |  | 
89 |  | -                             TT_RESP_S_Msk | TT_RESP_SRVALID_Msk | TT_RESP_SREGION_Msk);  | 
90 |  | -}  | 
91 |  | - | 
92 |  | -extern int vmpu_fault_recovery_mpu(uint32_t pc, uint32_t sp, uint32_t fault_addr, uint32_t fault_status);  | 
93 | 23 | 
 
  | 
94 | 24 | uint32_t vmpu_unpriv_access(uint32_t addr, uint32_t size, uint32_t data)  | 
95 | 25 | {  | 
96 |  | -    unsigned int tries = 0;  | 
97 |  | -    while(1) {  | 
98 |  | -        if ((vmpu_unpriv_test_range(addr, UVISOR_UNPRIV_ACCESS_SIZE(size)) & (TT_RESP_NSRW_Msk | TT_RESP_SRVALID_Msk)) == (TT_RESP_NSRW_Msk | TT_RESP_SRVALID_Msk)) {  | 
99 |  | -            switch(size) {  | 
100 |  | -                case UVISOR_UNPRIV_ACCESS_READ(1):  | 
101 |  | -                    return *((uint8_t *) addr);  | 
102 |  | -                case UVISOR_UNPRIV_ACCESS_READ(2):  | 
103 |  | -                    return *((uint16_t *) addr);  | 
104 |  | -                case UVISOR_UNPRIV_ACCESS_READ(4):  | 
105 |  | -                    return *((uint32_t *) addr);  | 
106 |  | -                case UVISOR_UNPRIV_ACCESS_WRITE(1):  | 
107 |  | -                    *((uint8_t *) addr) = (uint8_t) data;  | 
108 |  | -                    return 0;  | 
109 |  | -                case UVISOR_UNPRIV_ACCESS_WRITE(2):  | 
110 |  | -                    *((uint16_t *) addr) = (uint16_t) data;  | 
111 |  | -                    return 0;  | 
112 |  | -                case UVISOR_UNPRIV_ACCESS_WRITE(4):  | 
113 |  | -                    *((uint32_t *) addr) = data;  | 
114 |  | -                    return 0;  | 
115 |  | -                default:  | 
116 |  | -                    break;  | 
117 |  | -            }  | 
118 |  | -            break;  | 
119 |  | -        }  | 
120 |  | -        if (++tries > 1 || !vmpu_fault_recovery_mpu(0, 0, addr, 0)) {  | 
121 |  | -            break;  | 
 | 26 | +    // This operation could be slow since we are scanning all the regions defined for the box  | 
 | 27 | +    // an implementation using the TTA command is faster but causes misses since it works with the MPU  | 
 | 28 | +    if (vmpu_buffer_access_is_ok(g_active_box, (const void *) addr, UVISOR_UNPRIV_ACCESS_SIZE(size))){  | 
 | 29 | +        switch(size) {  | 
 | 30 | +            case UVISOR_UNPRIV_ACCESS_READ(1):  | 
 | 31 | +                return *((uint8_t *) addr);  | 
 | 32 | +            case UVISOR_UNPRIV_ACCESS_READ(2):  | 
 | 33 | +                return *((uint16_t *) addr);  | 
 | 34 | +            case UVISOR_UNPRIV_ACCESS_READ(4):  | 
 | 35 | +                return *((uint32_t *) addr);  | 
 | 36 | +            case UVISOR_UNPRIV_ACCESS_WRITE(1):  | 
 | 37 | +                *((uint8_t *) addr) = (uint8_t) data;  | 
 | 38 | +                return 0;  | 
 | 39 | +            case UVISOR_UNPRIV_ACCESS_WRITE(2):  | 
 | 40 | +                *((uint16_t *) addr) = (uint16_t) data;  | 
 | 41 | +                return 0;  | 
 | 42 | +            case UVISOR_UNPRIV_ACCESS_WRITE(4):  | 
 | 43 | +                *((uint32_t *) addr) = data;  | 
 | 44 | +                return 0;  | 
 | 45 | +            default:  | 
 | 46 | +                break;  | 
122 | 47 |         }  | 
123 | 48 |     }  | 
 | 49 | +      | 
124 | 50 |     HALT_ERROR(PERMISSION_DENIED, "Access to restricted resource denied");  | 
125 | 51 |     return 0;  | 
126 | 52 | }  | 
0 commit comments