bl30: rtos_sdk add pmp protection [2/2]
PD#SWPL-140705
Problem:
bl30: add pmp protection (for rtos_sdk)
Solution:
.text/rodata permission: R/X
.data/stack/heap permission: R/W
back ground all 4G region: R/W
application to both M and U mode.
Verify:
a5_av409, s5_ax201, t5m_ay301, t3x_bc302, s1a_bg201
Change-Id: I281e647c0baf33c23655f2eae0f0d51c18371362
Signed-off-by: bangzheng.liu <bangzheng.liu@amlogic.com>
diff --git a/n200_func.c b/n200_func.c
index 492b624..e7532e9 100644
--- a/n200_func.c
+++ b/n200_func.c
@@ -15,18 +15,122 @@
#include "n200_timer.h"
#include "gcc_compiler_attributes.h"
#include "riscv_encoding.h"
+#include "lscript.h"
-// Configure PMP to make all the address space accesable and executable
+#define PMP_PRINT(...) printf(__VA_ARGS__)
+#define PMP_PRINT_DEBUG(...) //printf(__VA_ARGS__)
+
+/*
+ * -- Configure PMP --
+ * For User mode only.
+ * To make all the address space accessible and executable
+ */
void pmp_open_all_space(void)
{
// Config entry0 addr to all 1s to make the range cover all space
- asm volatile("li x6, 0xffffffff" ::: "x6");
- asm volatile("csrw pmpaddr0, x6" :::);
+ asm volatile ("li x6, 0xffffffff":::"x6");
+ asm volatile ("csrw pmpaddr0, x6":::);
// Config entry0 cfg to make it NAPOT address mode, and R/W/X okay
- asm volatile("li x6, 0x7f" ::: "x6");
- asm volatile("csrw pmpcfg0, x6" :::);
+ asm volatile ("li x6, 0x7f":::"x6");
+ asm volatile ("csrw pmpcfg0, x6":::);
}
+#ifndef CONFIG_N200_REVA
+/*
+ * -- Configure PMP --
+ * For both Machine and User mode.
+ * To make aocpu text/ro data space readable and executable.
+ * To make aocpu data space readable and writable.
+ * To make 4G space readable and writable.
+ * Note:
+ * If config_pmp is called, pmp_open_all_space is invalid.
+ */
+uint32_t config_pmp(void)
+{
+ uint32_t start_text_addr = (uint32_t)&_text;
+ uint32_t end_text_addr = (uint32_t)&_etext;
+ uint32_t text_len_left = end_text_addr - start_text_addr;
+ uint32_t next_seg_len;
+ uint32_t pmp_cfg[8] = {0};
+ int pmp_entry_used = 0;
+ uint32_t pmp_region_base = start_text_addr;
+ uint32_t ao_ram_end = configMEM_START + configMEM_LEN;
+ uint32_t all_region_size = 0x1fffffff;
+
+ PMP_PRINT("AOCPU: configure PMP for memory 0x%lx ~ 0x%lx\n",
+ start_text_addr, end_text_addr);
+
+ while (text_len_left > 0) {
+ for (next_seg_len = 1024; next_seg_len*2 <= text_len_left; next_seg_len *= 2)
+ ;
+
+ text_len_left -= next_seg_len;
+ PMP_PRINT_DEBUG("segment length: %lx\n", next_seg_len);
+ PMP_PRINT_DEBUG("length left : %lx\n", text_len_left);
+
+ /* Configure text/ro data space access privilege */
+ switch (pmp_entry_used) {
+ case 0:
+ write_csr(pmpaddr0, (pmp_region_base >> 2) | NAPOT_SIZE(next_seg_len));
+ pmp_cfg[0] = (PMP_CFG_R_EN | PMP_CFG_X_EN | PMP_CFG_A_NAPOT | PMP_CFG_L_EN);
+ break;
+ case 1:
+ write_csr(pmpaddr1, (pmp_region_base >> 2) | NAPOT_SIZE(next_seg_len));
+ pmp_cfg[1] = (PMP_CFG_R_EN | PMP_CFG_X_EN | PMP_CFG_A_NAPOT | PMP_CFG_L_EN);
+ break;
+ case 2:
+ write_csr(pmpaddr2, (pmp_region_base >> 2) | NAPOT_SIZE(next_seg_len));
+ pmp_cfg[2] = (PMP_CFG_R_EN | PMP_CFG_X_EN | PMP_CFG_A_NAPOT | PMP_CFG_L_EN);
+ break;
+ case 3:
+ write_csr(pmpaddr3, (pmp_region_base >> 2) | NAPOT_SIZE(next_seg_len));
+ pmp_cfg[3] = (PMP_CFG_R_EN | PMP_CFG_X_EN | PMP_CFG_A_NAPOT | PMP_CFG_L_EN);
+ break;
+ case 4:
+ write_csr(pmpaddr4, (pmp_region_base >> 2) | NAPOT_SIZE(next_seg_len));
+ pmp_cfg[4] = (PMP_CFG_R_EN | PMP_CFG_X_EN | PMP_CFG_A_NAPOT | PMP_CFG_L_EN);
+ break;
+ case 5:
+ write_csr(pmpaddr5, (pmp_region_base >> 2) | NAPOT_SIZE(next_seg_len));
+ pmp_cfg[5] = (PMP_CFG_R_EN | PMP_CFG_X_EN | PMP_CFG_A_NAPOT | PMP_CFG_L_EN);
+ break;
+ default:
+ break;
+ }
+ pmp_entry_used++;
+ pmp_region_base += next_seg_len;
+ PMP_PRINT_DEBUG("pmp_entry_used : %d\n", pmp_entry_used);
+ PMP_PRINT_DEBUG("pmp_region_base: %lx\n", pmp_region_base);
+ }
+
+ /* Configure data space access privilege */
+ write_csr(pmpaddr6, (pmp_region_base >> 2) | NAPOT_SIZE(ao_ram_end - pmp_region_base));
+ pmp_cfg[6] = (PMP_CFG_R_EN | PMP_CFG_W_EN | PMP_CFG_A_NAPOT | PMP_CFG_L_EN);
+ /* Configure all 32-bit (4G) address space access privilege */
+ write_csr(pmpaddr7, (0x0) | all_region_size);
+ pmp_cfg[7] = (PMP_CFG_R_EN | PMP_CFG_W_EN | PMP_CFG_A_NAPOT | PMP_CFG_L_EN);
+ /* Set Configuration for text/ro data/data/4G space */
+ write_csr(pmpcfg0, (pmp_cfg[3] << 24) | (pmp_cfg[2] << 16) |
+ (pmp_cfg[1] << 8) | (pmp_cfg[0] << 0));
+ write_csr(pmpcfg1, (pmp_cfg[7] << 24) | (pmp_cfg[6] << 16) |
+ (pmp_cfg[5] << 8) | (pmp_cfg[4] << 0));
+
+ PMP_PRINT_DEBUG("pmpaddr0 : %lx\n", read_csr(pmpaddr0));
+ PMP_PRINT_DEBUG("pmpaddr1 : %lx\n", read_csr(pmpaddr1));
+ PMP_PRINT_DEBUG("pmpaddr2 : %lx\n", read_csr(pmpaddr2));
+ PMP_PRINT_DEBUG("pmpaddr3 : %lx\n", read_csr(pmpaddr3));
+ PMP_PRINT_DEBUG("pmpaddr4 : %lx\n", read_csr(pmpaddr4));
+ PMP_PRINT_DEBUG("pmpaddr5 : %lx\n", read_csr(pmpaddr5));
+ PMP_PRINT_DEBUG("pmpaddr6 : %lx\n", read_csr(pmpaddr6));
+ PMP_PRINT_DEBUG("pmpaddr7 : %lx\n", read_csr(pmpaddr7));
+ PMP_PRINT_DEBUG("pmpcfg0 : %lx\n", read_csr(pmpcfg0));
+ PMP_PRINT_DEBUG("pmpcfg1 : %lx\n", read_csr(pmpcfg1));
+ PMP_PRINT("AOCPU: configure PMP end\n");
+
+ return 0;
+}
+#endif
+
void switch_m2u_mode(void)
{
clear_csr(mstatus, MSTATUS_MPP);