Files
kunlun/dtest/dtest3/kl3_pmp_test/kl3_pmp_test.c
2024-09-28 14:24:04 +08:00

474 lines
18 KiB
C
Executable File

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
/* os shim includes */
#include "os_types.h"
#include "os_utils.h"
/* common includes */
#include "iot_io.h"
#include "iot_config.h"
/* driver includes */
#include "iot_clock.h"
#include "iot_uart.h"
#include "iot_system.h"
/* debug includes*/
#include "dbg_io.h"
#include "platform.h"
#include "encoding.h"
#include "hw_reg_api.h"
#include "ahb.h"
#include "cpu.h"
#include "dtest_printf.h"
#include "pmp.h"
#include "mmon.h"
typedef enum {
EXCEPTION_CAUSE_INSTRUCTION_ADDRESS_MISALIGNED = 0,
EXCEPTION_CAUSE_INSTRUCTION_ACCESS_FAULT = 1,
EXCEPTION_CAUSE_ILLEGAL_INSTRUCTION = 2,
EXCEPTION_CAUSE_BREAKPOINT = 3,
EXCEPTION_CAUSE_LOAD_ADDRESS_MISALIGNED = 4,
EXCEPTION_CAUSE_LOAD_ADDRESS_FAULT = 5,
EXCEPTION_CAUSE_STORE_AMO_ACCESS_MISALIGNED = 6,
EXCEPTION_CAUSE_STORE_AMO_ACCESS_FAULT = 7,
EXCEPTION_CAUSE_ENV_CALL_FROM_U_MODE = 8,
EXCEPTION_CAUSE_ENV_CALL_FROM_S_MODE = 9,
EXCEPTION_CAUSE_RESERVED_10 = 10,
EXCEPTION_CAUSE_ENV_CALL_FROM_M_MODE = 11,
EXCEPTION_CAUSE_INSTRUCTION_PAGE_FAULT = 12,
EXCEPTION_CAUSE_LOAD_PAGE_FAULT = 13,
EXCEPTION_CAUSE_RESERVED_14 = 14,
EXCEPTION_CAUSE_STORE_AMO_PAGE_FAULT = 15,
EXCEPTION_CAUSE_RESERVED = 16, // >= 16
} riscv_exception_cause_t;
#define DTEST_PMP_TEST_SIZE 32
#define DTEST_PMP_ALIGIN_SIZE 1024
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_00[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_01[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_02[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_03[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_04[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_05[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_06[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_07[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_08[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_09[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_10[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_11[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_12[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_13[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_14[DTEST_PMP_TEST_SIZE] = {0};
volatile __attribute__((aligned(DTEST_PMP_ALIGIN_SIZE))) uint32_t protected_mem_region_15[DTEST_PMP_TEST_SIZE] = {0};
/* the mcause code will be test */
volatile uintptr_t g_mcause_set = 0;
/* the mcause code get from exception handler */
volatile uintptr_t g_mcause_get = 0;
/* set 1 if exception occer */
volatile int g_exception_occer = 0;
uint32_t g_intc_trigger_cnt = 0;
extern void kl3_trap_entry();
extern int platform_init();
extern void intc_handler(uint32_t cpu);
extern uintptr_t kl3_handle_trap(uintptr_t mcause, uintptr_t epc, saved_registers *reg);
void kl3_exception_handler(uintptr_t mcause)
{
uint32_t mbadaddr = 0;
//disble global interrupt;
__asm volatile ( "csrc mstatus,8" );
__asm volatile ( "csrr %0, mbadaddr" : "=r"(mbadaddr));
switch(mcause) {
case EXCEPTION_CAUSE_INSTRUCTION_ADDRESS_MISALIGNED:
dprintf("mcause: 0x%02x[Instruction address misaligned]\n",
mcause);
break;
case 0x1:
dprintf("mcause: 0x%02x[Instruction access fault]\n",
mcause);
break;
case 0x2:
dprintf("mcause: 0x%02x[Illegal instruction]\n", mcause);
break;
case 0x3:
dprintf("mcause: 0x%02x[Breakpoint]\n", mcause);
break;
case 0x4:
dprintf("mcause: 0x%02x[Load address misaligned]\n",
mcause);
break;
case EXCEPTION_CAUSE_LOAD_ADDRESS_FAULT:
dprintf("mcause: 0x%02x[Load access fault]\n", mcause);
break;
case 0x6:
dprintf("mcause: 0x%02x[Store address misaligned]\n",
mcause);
break;
case 0x7:
dprintf("mcase: 0x%02x[Store access fault]\n", mcause);
break;
default:
dprintf("mcause: 0x%02x\n", mcause);
break;
}
}
uintptr_t kl3_handle_trap(uintptr_t mcause,
uintptr_t epc, saved_registers *reg)
{
if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT) {
intc_handler(cpu_get_mhartid());
g_intc_trigger_cnt++;
} else {
kl3_exception_handler(mcause);
//extern void exception_reg_dump(saved_registers *regs);
//exception_reg_dump(reg);
g_exception_occer = 1;
g_mcause_get = mcause;
void exception_test_loop(void);
void (*pgm_start)(void) = (void*)exception_test_loop;
pgm_start();
}
return epc;
}
uint32_t pmp_exec_test(uint32_t arg)
{
dprintf("%s running, arg:%d\n", __FUNCTION__, arg);
return arg;
}
static int32_t pmp_test(void)
{
static int test_case = -1;
static uint8_t pmp_idx = 0;
uint32_t addr;
uint32_t temp = 0x12345678;
test_case++;
iot_printf("\n");
dprintf("case index:%d\n", test_case);
switch (test_case) {
case 0:
/* mmon_disable_address_access() function test */
dprintf("mmon_disable_address_access api test, disable read, "
"write and execute \n");
addr = (uint32_t)protected_mem_region_00;
mmon_disable_address_access(pmp_idx, addr, 32*4);
dprintf("read option, should trigger load access fault\n");
g_mcause_set = EXCEPTION_CAUSE_LOAD_ADDRESS_FAULT;
dprintf("pmp test data:0x%08x\n", protected_mem_region_00[15]);
break;
case 1:
dprintf("write option, should trigger store access fault\n");
g_mcause_set = EXCEPTION_CAUSE_STORE_AMO_ACCESS_FAULT;
protected_mem_region_00[15] = 0x12345678;
break;
case 2:
dprintf("execute option, should trigger instruction access fault\n");
g_mcause_set = EXCEPTION_CAUSE_INSTRUCTION_ACCESS_FAULT;
void (*pgm_start_1)(void) = (void*)protected_mem_region_00;
pgm_start_1();
break;
case 3:
/* mmon_set_address_access() function test */
dprintf("mmon_disable_address_access api test, enable read, "
"write and execute \n");
addr = (uint32_t)protected_mem_region_00;
mmon_set_address_access(addr, 32*4,
MMON_PRV_READ | MMON_PRV_WRITE | MMON_PRV_EXEC);
dprintf("write option(0x%08x), should be normal\n", temp);
g_mcause_set = EXCEPTION_CAUSE_RESERVED;
protected_mem_region_00[15] = temp;
break;
case 4:
dprintf("read option, should be normal\n");
g_mcause_set = EXCEPTION_CAUSE_RESERVED;
dprintf("pmp test data:0x%08x\n", protected_mem_region_00[15]);
if (protected_mem_region_00[15] != temp) {
dprintf("!!!!! read value is not equal to write value !!!!!!\n");
while(1);
}
break;
case 5:
dprintf("execute option, should trigger illegal instruction\n");
protected_mem_region_00[0] = temp;
g_mcause_set = EXCEPTION_CAUSE_ILLEGAL_INSTRUCTION;
void (*pgm_start_2)(void) = (void*)((uint32_t)protected_mem_region_00 + 2);
pgm_start_2();
break;
case 6:
/* read option disable test */
dprintf("read option disable, should trigger load access fault\n");
addr = (uint32_t)protected_mem_region_00;
mmon_set_mode_address_access(pmp_idx, PMP_NA4, addr, 0, MMON_PRV_WRITE | MMON_PRV_EXEC);
g_mcause_set = EXCEPTION_CAUSE_LOAD_ADDRESS_FAULT;
dprintf("pmp test data:0x%08x\n", *(uint32_t *)addr);
break;
case 7:
/* write option disable test */
dprintf("write option disable, should trigger store access fault\n");
addr = (uint32_t)protected_mem_region_00;
mmon_set_mode_address_access(pmp_idx, PMP_NA4, addr, 0, MMON_PRV_READ | MMON_PRV_EXEC);
g_mcause_set = EXCEPTION_CAUSE_STORE_AMO_ACCESS_FAULT;
// protected_mem_region_00[0] = 0x12345678;
*(uint32_t *)addr = 0x12345678;
break;
case 8:
/* execute option disable test */
dprintf("execute option disable, should trigger instruction access fault\n");
addr = (uint32_t)pmp_exec_test;
mmon_set_mode_address_access(pmp_idx, PMP_NA4, addr, 0, MMON_PRV_READ | MMON_PRV_WRITE);
g_mcause_set = EXCEPTION_CAUSE_INSTRUCTION_ACCESS_FAULT;
pmp_exec_test(1);
break;
case 9:
/* read option enable test */
dprintf("read option enable, should be normal\n");
addr = (uint32_t)protected_mem_region_00;
mmon_set_mode_address_access(pmp_idx, PMP_NA4, addr, 0, MMON_PRV_READ);
g_mcause_set = EXCEPTION_CAUSE_RESERVED;
dprintf("pmp test data:0x%08x\n", *(uint32_t *)addr);
break;
case 10:
/* write option enable test */
dprintf("write option enable(read enable), should be normal\n");
addr = (uint32_t)protected_mem_region_00;
mmon_set_mode_address_access(pmp_idx, PMP_NA4, addr, 0, MMON_PRV_WRITE | MMON_PRV_READ);
g_mcause_set = EXCEPTION_CAUSE_RESERVED;
// protected_mem_region_00[0] = 0x12345678;
*(uint32_t *)addr = 0x12345678;
break;
case 11:
/* write option enable test */
dprintf("write option enable(read disable), should trigger store fault\n");
addr = (uint32_t)protected_mem_region_00;
mmon_set_mode_address_access(pmp_idx, PMP_NA4, addr, 0, MMON_PRV_WRITE);
g_mcause_set = EXCEPTION_CAUSE_STORE_AMO_ACCESS_FAULT;
// protected_mem_region_00[0] = 0x12345678;
*(uint32_t *)addr = 0x12345678;
break;
case 12:
/* execute option enable test */
dprintf("execute option enable, should be normal\n");
addr = (uint32_t)pmp_exec_test;
mmon_set_mode_address_access(pmp_idx, PMP_NA4, addr, 0, MMON_PRV_EXEC);
g_mcause_set = EXCEPTION_CAUSE_RESERVED;
pmp_exec_test(2);
break;
case 13:
/* address matching mode test - OFF */
dprintf("address matching OFF mode test, should be normal\n");
addr = (uint32_t)protected_mem_region_00;
mmon_set_mode_address_access(pmp_idx, PMP_OFF, addr, 0, 0);
g_mcause_set = EXCEPTION_CAUSE_RESERVED;
dprintf("pmp test data:0x%08x\n", *(uint32_t *)addr);
pmp_exec_test(3);
break;
case 14:
/* address matching mode test - PMP_TOR */
dprintf("address matching TOR mode test, should trigger load access fault\n");
addr = (uint32_t)protected_mem_region_00;
mmon_set_mode_address_access(pmp_idx, PMP_TOR, addr, addr + 128, 0);
g_mcause_set = EXCEPTION_CAUSE_LOAD_ADDRESS_FAULT;
dprintf("pmp test data:0x%08x\n", *(uint32_t *)addr);
break;
case 15:
/* address matching mode test - PMP_NA4 */
dprintf("address matching NA4 mode test\n");
dprintf("in the previous test items, PMP_NA4 mode is used\n");
g_mcause_set = EXCEPTION_CAUSE_RESERVED;
break;
case 16:
/* address matching mode test - PMP_NAPOT */
dprintf("address matching NA_TOR mode test, should trigger load access fault\n");
addr = (uint32_t)protected_mem_region_00;
mmon_set_mode_address_access(pmp_idx, PMP_NAPOT, addr, 8, 0);
g_mcause_set = EXCEPTION_CAUSE_LOAD_ADDRESS_FAULT;
dprintf("pmp test data:0x%08x\n", *(uint32_t *)addr);
break;
case 17:
/* pmp entry lock or unlock test */
/* However, when the l field is 1, the m, s, and u modes must follow
* the permission settings in the configuration register. When the
* l field is 0, any operation matching this PMP entry in the M mode
* will succeed, while the permission settings in the configuration
* register must be followed in the s and u modes.
*/
dprintf("pmp entry lock test\n");
dprintf("in the previous test items, lock is used.\n");
dprintf("driver code must be modified for manually test unlock function\n");
dprintf("expect that the exception will not be triggered "
"where the exception should be triggered\n");
break;
case 18:
/* priotity and matching logic test */
/* pmp entry have static priority. small numbers have higher priority */
dprintf("priotity and matching logic test, should be normal\n");
addr = (uint32_t)protected_mem_region_00;
mmon_set_mode_address_access(0, PMP_NAPOT, addr, 8, MMON_PRV_READ);
mmon_set_mode_address_access(1, PMP_NAPOT, addr, 8, 0);
g_mcause_set = EXCEPTION_CAUSE_RESERVED;
dprintf("pmp test data:0x%08x\n", *(uint32_t *)addr);
break;
case (19 + 0):
case (19 + 1):
case (19 + 2):
case (19 + 3):
case (19 + 4):
case (19 + 5):
case (19 + 6):
case (19 + 7):
case (19 + 8):
case (19 + 9):
case (19 + 10):
case (19 + 11):
case (19 + 12):
case (19 + 13):
case (19 + 14):
case (19 + 15):
/* pmp entry base function test, there are 16 pmp entrys */
/* close all of the pmp entry, prevent mutual influence */
if (pmp_idx == 0) {
dprintf("close all of the pmp entry\n");
for (uint8_t i = 0; i < 16; i++) {
mmon_set_mode_address_access(i, PMP_OFF, 0, 0, 0);
}
}
addr = (uint32_t)protected_mem_region_00 + (pmp_idx * DTEST_PMP_ALIGIN_SIZE);
dprintf("pmp entry base test, index:%d, protect addr:0x%08x\n", pmp_idx, addr);
dprintf("\tprotect off, write should be normal\n");
mmon_set_mode_address_access(pmp_idx, PMP_OFF, addr, 0, 0);
g_mcause_set = EXCEPTION_CAUSE_RESERVED;
*(uint32_t *)addr = temp;
dprintf("\tset %p value to 0x%08x, read 0x%08x\n", addr, temp, *(uint32_t *)addr);
dprintf("\tprotect on, write should trigger load access fault\n");
mmon_set_mode_address_access(pmp_idx, PMP_NAPOT, addr, 8, 0);
g_mcause_set = EXCEPTION_CAUSE_LOAD_ADDRESS_FAULT;
dprintf("\tpmp test data:0x%08x\n", *(uint32_t *)addr);
pmp_idx++;
break;
case (19 + 16):
/* test complete */
dprintf("all of the case have been completed\n");
return 2;
break;
}
return 0;
}
void exception_test_loop()
{
static uint32_t case_failed_cnt = 0;
/* if exception occer, need check exception code get is same as set */
if (g_exception_occer) {
g_exception_occer = 0;
if (g_mcause_get == g_mcause_set) {
dcase_success();
} else {
dcase_failed();
case_failed_cnt++;
}
}
for (;;) {
int32_t test_case_result = pmp_test();
if (0 == test_case_result) { //case succeed
dcase_success();
} else if (1 == test_case_result) { //case failed
/* when exception occer, it will not run here */
dcase_failed();
case_failed_cnt++;
} else if (2 == test_case_result) { //case run complete
dprintf("intc trigger cnt:%d\n", g_intc_trigger_cnt);
dprintf("case failed cnt:%d, pmp test %s\n", case_failed_cnt,
case_failed_cnt ? "failed" : "succeed");
dend();
for (;;) {
iot_delay_us(10000);
}
} else {
dprintf("!!!! logic exception !!!!!\n");
while(1);
}
iot_delay_us(10000);
}
}
static void cache_init()
{
cache_enable(AHB_CACHE_D0);
cache_set_buffer_mode(AHB_CACHE_D0, 1);
cache_enable(AHB_CACHE_D1);
cache_set_buffer_mode(AHB_CACHE_D1, 1);
}
int main(void)
{
cache_init();
/*install trap entry*/
write_csr(mtvec, &kl3_trap_entry);
dbg_uart_init();
dconfig();
dstart();
dversion();
/* Prevent being optimized */
dprintf("test memory 0 addr:%p\n", protected_mem_region_00);
dprintf("test memory 1 addr:%p\n", protected_mem_region_01);
dprintf("test memory 2 addr:%p\n", protected_mem_region_02);
dprintf("test memory 3 addr:%p\n", protected_mem_region_03);
dprintf("test memory 4 addr:%p\n", protected_mem_region_04);
dprintf("test memory 5 addr:%p\n", protected_mem_region_05);
dprintf("test memory 6 addr:%p\n", protected_mem_region_06);
dprintf("test memory 7 addr:%p\n", protected_mem_region_07);
dprintf("test memory 8 addr:%p\n", protected_mem_region_08);
dprintf("test memory 9 addr:%p\n", protected_mem_region_09);
dprintf("test memory 10 addr:%p\n", protected_mem_region_10);
dprintf("test memory 11 addr:%p\n", protected_mem_region_11);
dprintf("test memory 12 addr:%p\n", protected_mem_region_12);
dprintf("test memory 13 addr:%p\n", protected_mem_region_13);
dprintf("test memory 14 addr:%p\n", protected_mem_region_14);
dprintf("test memory 15 addr:%p\n", protected_mem_region_15);
exception_test_loop();
return 0;
}