Software APIs
pmp_smoketest_napot.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
7 #include "sw/device/lib/runtime/irq.h"
8 #include "sw/device/lib/runtime/pmp.h"
9 #include "sw/device/lib/testing/test_framework/check.h"
11 
12 // Usable PMP regions vary depending on different exectuion environments.
13 // PMP regions with small or large indices are usually reserved by ROM/ROM_EXT
14 // So use PMP region 7 for this test.
15 #define PMP_LOAD_REGION_ID 7
16 
17 #define PMP_LOAD_RANGE_BUFFER_SIZE 1024
18 #define PMP_LOAD_RANGE_SIZE 512
19 #define PMP_LOAD_RANGE_BOTTOM_OFFSET 0
20 #define PMP_LOAD_RANGE_TOP_OFFSET \
21  (PMP_LOAD_RANGE_BOTTOM_OFFSET + PMP_LOAD_RANGE_SIZE - 1)
22 
23 // These flags are used in the test routine to verify that a corresponding
24 // interrupt has elapsed, and has been serviced. These are declared as volatile
25 // since they are referenced in the ISR routine as well as in the main program
26 // flow.
27 static volatile bool pmp_load_exception;
28 
29 /**
30  * The buffer that is used for load/store access violation test.
31  */
32 __attribute__((aligned(PMP_LOAD_RANGE_SIZE))) //
33 static volatile char pmp_load_store_test_data[PMP_LOAD_RANGE_BUFFER_SIZE];
34 
35 /**
36  * This overrides the default OTTF load/store fault exception handler.
37  */
38 void ottf_load_store_fault_handler(uint32_t *exc_info) {
39  pmp_load_exception = true;
40 }
41 
42 static void pmp_configure_load_napot(void) {
43  uintptr_t load_range_start =
44  (uintptr_t)&pmp_load_store_test_data[PMP_LOAD_RANGE_BOTTOM_OFFSET];
45 
46  pmp_region_config_t config = {
47  .lock = kPmpRegionLockLocked,
48  .permissions = kPmpRegionPermissionsNone,
49  };
50 
51  pmp_region_configure_napot_result_t result = pmp_region_configure_napot(
52  PMP_LOAD_REGION_ID, config, load_range_start, PMP_LOAD_RANGE_SIZE);
53  CHECK(result == kPmpRegionConfigureNapotOk,
54  "Load configuration failed, error code = %d", result);
55 }
56 
57 OTTF_DEFINE_TEST_CONFIG();
58 
59 bool test_main(void) {
60  bool configured;
61  pmp_region_configure_result_t result =
62  pmp_region_is_configured(PMP_LOAD_REGION_ID, &configured);
63  CHECK(result == kPmpRegionConfigureOk,
64  "PMP region %d cfg read failed, error code = %d", PMP_LOAD_REGION_ID,
65  result);
66  CHECK(!configured, "PMP region %d is already configured", PMP_LOAD_REGION_ID);
67 
68  pmp_load_exception = false;
69  char load = pmp_load_store_test_data[PMP_LOAD_RANGE_BOTTOM_OFFSET];
70  CHECK(!pmp_load_exception, "Load access violation before PMP configuration");
71 
72  pmp_configure_load_napot();
73 
74  pmp_load_exception = false;
75  load = pmp_load_store_test_data[PMP_LOAD_RANGE_BOTTOM_OFFSET];
76  CHECK(pmp_load_exception,
77  "No load access violation on the bottom of the range load");
78 
79  pmp_load_exception = false;
80  load = pmp_load_store_test_data[PMP_LOAD_RANGE_TOP_OFFSET];
81  CHECK(pmp_load_exception,
82  "No load access violation on the top of the range load");
83 
84  pmp_load_exception = false;
85  load = pmp_load_store_test_data[PMP_LOAD_RANGE_TOP_OFFSET + 1];
86  CHECK(!pmp_load_exception, "Load access violation on top of the range + 1");
87 
88  (void)load;
89 
90  return true;
91 }