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);