Skip to content

Commit c0c6db1

Browse files
author
Oren Cohen
committed
Handle armv8m unpriv_access with SAU
Previously when we got to unpriv_access we verfied the operation with the TT assembly command, we now switch to using the SAU with uVisor vmpu functions. This could slow down the operation since we switch an assembly command with a C function which scans the virtual regions.
1 parent 391d080 commit c0c6db1

File tree

1 file changed

+23
-96
lines changed

1 file changed

+23
-96
lines changed

Diff for: core/vmpu/src/mpu_armv8m/vmpu_armv8m_unpriv_access.c

+23-96
Original file line numberDiff line numberDiff line change
@@ -18,109 +18,36 @@
1818
#include "context.h"
1919
#include "debug.h"
2020
#include "vmpu.h"
21+
#include "vmpu_mpu.h"
2122
#include "vmpu_unpriv_access.h"
2223
#include <stdbool.h>
2324

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-
9425
uint32_t vmpu_unpriv_access(uint32_t addr, uint32_t size, uint32_t data)
9526
{
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;
27+
// This operation could be slow since we are scanning all the regions defined for the box
28+
// an implementation using the TTA command is faster but causes misses since it works with the MPU
29+
if (vmpu_buffer_access_is_ok(g_active_box, (const void *) addr, UVISOR_UNPRIV_ACCESS_SIZE(size))){
30+
switch(size) {
31+
case UVISOR_UNPRIV_ACCESS_READ(1):
32+
return *((uint8_t *) addr);
33+
case UVISOR_UNPRIV_ACCESS_READ(2):
34+
return *((uint16_t *) addr);
35+
case UVISOR_UNPRIV_ACCESS_READ(4):
36+
return *((uint32_t *) addr);
37+
case UVISOR_UNPRIV_ACCESS_WRITE(1):
38+
*((uint8_t *) addr) = (uint8_t) data;
39+
return 0;
40+
case UVISOR_UNPRIV_ACCESS_WRITE(2):
41+
*((uint16_t *) addr) = (uint16_t) data;
42+
return 0;
43+
case UVISOR_UNPRIV_ACCESS_WRITE(4):
44+
*((uint32_t *) addr) = data;
45+
return 0;
46+
default:
47+
break;
12248
}
12349
}
50+
12451
HALT_ERROR(PERMISSION_DENIED, "Access to restricted resource denied");
12552
return 0;
12653
}

0 commit comments

Comments
 (0)