/
main.cpp
162 lines (133 loc) · 4.84 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/* Copyright (c) 2017-2018 ARM Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if !defined(COMPONENT_PSA_SRV_IPC)
#error [NOT_SUPPORTED] Test supported only on PSA targets
#endif
#if (defined( __CC_ARM ) || defined(__ARMCC_VERSION) || defined( __ICCARM__ ))
#error [NOT_SUPPORTED] this test is supported on GCC only
#endif
#if defined(TARGET_FUTURE_SEQUANA_PSA)
#error [NOT_SUPPORTED] Disable this Test until FUTURE_SEQUANA_PSA enables Memory protection
#endif
#if defined(__CORTEX_M33)
#error [NOT_SUPPORTED] Cannot run on M33 core as SecureFault is implemented in secure-side and cant be remapped
#endif
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "cmsis.h"
#include "spm_api.h"
#include <stdlib.h>
#include "fault_functions.h"
using namespace utest::v1;
#define HARDFAULT_IRQn ((IRQn_Type)-13)
#define EXC_RETURN_RETURN_STACK_MSK ((uint32_t)(0x00000004))
#define PC_INDEX_IN_STACK_FRAME 6
volatile uint32_t fault_occurred;
uint32_t real_hard_fault_handler;
__STATIC_FORCEINLINE uint32_t __get_LR(void)
{
uint32_t result;
__ASM volatile("MOV %0, lr" : "=r"(result));
return (result);
}
void do_nothing(void)
{
__NOP();
}
static void hard_fault_handler_test()
{
fault_occurred++;
// LR is set EXC_RETURN
// lowest bits identify PSP vs MSP stack used for stacking
uint32_t lr = __get_LR();
uint32_t sp;
if (lr & EXC_RETURN_RETURN_STACK_MSK) {
sp = __get_PSP();
} else {
sp = __get_MSP();
}
// Overwrite return address.
// Fake return to a our special function since current
// instruction under test will always fail due to memory protection
((uint32_t *)sp)[PC_INDEX_IN_STACK_FRAME] = (uint32_t)do_nothing;
}
__attribute__((naked)) void call_mem(uint32_t addr)
{
// Only first instruction will be executed in positive flow,
// since exception will be generated for invalid memory access.
// Other instructions are for calling do_nothing function according to AAPCS.
__ASM(
"LDR r3, [r0]\n"
"BX lr\n"
);
}
static void test_memory(uint32_t addr, uint32_t expected_fatal_count)
{
call_mem(addr);
// Although call_mem is a "naked" function, it is called using AAPCS.
// Thus we can assume LR will point to next instruction, and caller save registers are backed up
TEST_ASSERT_EQUAL(expected_fatal_count, fault_occurred);
}
static void secure_ram_fault_test(void)
{
test_memory(PSA_SECURE_RAM_START, 1);
}
static void secure_flash_fault_test(void)
{
test_memory(PSA_SECURE_ROM_START, 1);
}
static void non_secure_ram_fault_test(void)
{
test_memory(PSA_NON_SECURE_RAM_START, 0);
}
static void non_secure_flash_fault_test(void)
{
test_memory(PSA_NON_SECURE_ROM_START, 0);
}
utest::v1::status_t fault_override_setup(const Case *const source, const size_t index_of_case)
{
// Save old hard fault handler and replace it with a new one
// NOTE: only works when VTOR is set to RAM
real_hard_fault_handler = NVIC_GetVector(HARDFAULT_IRQn);
NVIC_SetVector(HARDFAULT_IRQn, (uint32_t)&hard_fault_handler_test);
fault_occurred = 0;
return greentea_case_setup_handler(source, index_of_case);
}
utest::v1::status_t fault_override_teardown(const Case *const source, const size_t passed, const size_t failed,
const failure_t reason)
{
// Restore real hard fault handler
NVIC_SetVector(HARDFAULT_IRQn, real_hard_fault_handler);
return greentea_case_teardown_handler(source, passed, failed, reason);
}
Case cases[] = {
Case("SPM - Access non-secure RAM", fault_override_setup, non_secure_ram_fault_test, fault_override_teardown),
Case("SPM - Access non-secure Flash", fault_override_setup, non_secure_flash_fault_test, fault_override_teardown),
Case("SPM - Access secure RAM", fault_override_setup, secure_ram_fault_test, fault_override_teardown),
Case("SPM - Access secure Flash", fault_override_setup, secure_flash_fault_test, fault_override_teardown)
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(20, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main()
{
Harness::run(specification);
}