[RISC-V MCU 应用开发] gd32vf103 PMP内存保护疑问

[复制链接]
2057|7
 楼主| lindahnu 发表于 2024-7-1 09:27 | 显示全部楼层 |阅读模式
本帖最后由 lindahnu 于 2024-7-2 18:04 编辑

使用nuclei IDE建立的pmp的例程代码,选择测试INSTRUCTION_FETCH_EXCEPTION不开启执行权限“X”,但是并没有产生异常进入InsAccFault_EXCn中断,这是什么原因?没明白,有小伙伴用过吗?

  1. // See LICENSE for license details.
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include "nuclei_sdk_soc.h"

  5. /* different trigger condition */
  6. #define INSTRUCTION_FETCH_EXCEPTION    0
  7. #define LOAD_EXCEPTION                 1
  8. #define STORE_EXCEPTION                2
  9. #define RUN_WITH_NO_PMP_CHECK          3

  10. /* Just choose one from above defines to test PMP */
  11. #define TRIGGER_PMP_VIOLATION_MODE     INSTRUCTION_FETCH_EXCEPTION

  12. volatile uint8_t protected_data[0x2000] __attribute__((aligned(0x2000))) =    \
  13. {0xaa, 0x1, 0x02, 0x03, 0x04, 0x05, 0x06, 0xaa};

  14. #ifndef __ICCRISCV__
  15. #define __PMP_PROTECT   __attribute__((section (".text"), aligned(0x2000)))
  16. #else
  17. /* IAR CC currently don't support align function in section,
  18. * so we provide a workaround using a customized iar_evalsoc_ilm.icf in this demo
  19. * we define a block called PMPFUNC alignment set to 0x2000 */
  20. #define __PMP_PROTECT   __attribute__((section (".text.pmpfunc")))
  21. #endif

  22. static void __PMP_PROTECT protected_execute(void)
  23. {
  24.     printf("----protected_execute succeed!----\r\n");

  25.     printf("Attempting to read protected_data[0]\r\n");
  26.     printf("protected_data[0]: 0x%0X succeed\r\n", protected_data[0]);

  27.     printf("Attempting to write protected_data[0]\r\n");
  28.     protected_data[0] = 0xFF;

  29.     printf("Won't run here if violates L R\\W\\X permission check!\r\n");
  30. }

  31. static void pmp_violation_fault_handler(unsigned long mcause, unsigned long sp)
  32. {
  33.     EXC_Frame_Type *exc_frame = (EXC_Frame_Type *)sp;

  34.     switch (mcause & MCAUSE_CAUSE) {
  35.         case InsAccFault_EXCn:
  36.             printf("Instruction access fault occurs, cause: 0x%lx, epc: 0x%lx\r\n", exc_frame->cause, exc_frame->epc);
  37.             break;
  38.         case LdFault_EXCn:
  39.             printf("Load access fault occurs, cause: 0x%lx, epc: 0x%lx\r\n", exc_frame->cause, exc_frame->epc);
  40.             break;
  41.         case StAccessFault_EXCn:
  42.             printf("Store/AMO access fault occurs, cause: 0x%lx, epc: 0x%lx\r\n", exc_frame->cause, exc_frame->epc);
  43.             break;
  44.         default: break;
  45.     }
  46.     while(1);
  47. }

  48. typedef void(*__funcpt)(void);

  49. int main(void)
  50. {
  51.     /* Configuration of execution region*/
  52.     pmp_config pmp_config_x = {
  53.         /*
  54.          * Locked PMP entries remain locked until the hart is reset,
  55.          * the L bit also indicates whether the R/W/X permissions are enforced on M-mode accesses
  56.          */
  57.         .protection = PMP_L | PMP_R | PMP_W | PMP_X,
  58.         /* Initial protected excutable address range is 2^12 = 4K bytes*/
  59.         .order = 12,
  60.         /* initial base address is 0, change it to your memory assignment */
  61.         .base_addr = 0,
  62.     };

  63.     /* configuration of read/write region*/
  64.     pmp_config pmp_config_rw = {
  65.         /*
  66.          * Locked PMP entries remain locked until the hart is reset,
  67.          * the L bit also indicates whether the R/W/X permissions are enforced on M-mode accesses
  68.          */
  69.         .protection = PMP_L | PMP_R | PMP_W | PMP_X,
  70.         /* initial protected readable/writable address range is 2^12 = 4K bytes */
  71.         .order = 12,
  72.         /* initial base address is 0, change it to your memory assignment */
  73.         .base_addr = 0,
  74.     };

  75.     pmp_config_x.base_addr = (unsigned long)protected_execute;
  76.     pmp_config_rw.base_addr = (unsigned long)protected_data;

  77. #if (INSTRUCTION_FETCH_EXCEPTION == TRIGGER_PMP_VIOLATION_MODE)
  78.     /* Remove X permission of protected_execute region */
  79.     pmp_config_x.protection = PMP_L | PMP_R | PMP_W;

  80.     pmp_config_rw.protection = PMP_L | PMP_R | PMP_W;
  81. #elif (LOAD_EXCEPTION == TRIGGER_PMP_VIOLATION_MODE)
  82.     /* Retrive X permission of protected_execute region */
  83.     pmp_config_x.protection = PMP_L | PMP_R | PMP_W | PMP_X;

  84.     /* Remove R permission of protected_data region */
  85.     pmp_config_rw.protection = PMP_L | PMP_W;
  86. #elif (STORE_EXCEPTION == TRIGGER_PMP_VIOLATION_MODE)
  87.     /* Retrive X permission of protected_execute region */
  88.     pmp_config_x.protection = PMP_L | PMP_R | PMP_W | PMP_X;

  89.     /* Remove W permission of protected_data region */
  90.     pmp_config_rw.protection = PMP_L | PMP_R ;
  91. #elif (RUN_WITH_NO_PMP_CHECK == TRIGGER_PMP_VIOLATION_MODE)
  92.     /* Unset Locking bit, any M-mode access matching the PMP entry will succeed */
  93.     pmp_config_x.protection = PMP_R | PMP_W | PMP_X;

  94.     pmp_config_rw.protection = PMP_R | PMP_W ;
  95. #endif

  96.     printf("------PMP demo with trigger condition %d------\r\n", TRIGGER_PMP_VIOLATION_MODE);

  97.     __set_PMPENTRYx(0, &pmp_config_x);
  98.     /* Verify the configuration takes effect */
  99.     memset(&pmp_config_x, 0, sizeof(pmp_config));
  100.     __get_PMPENTRYx(0, &pmp_config_x);
  101.     printf("Get pmp entry: index %d, prot_out: 0x%x, addr_out: 0x%lx, order_out: %lu\r\n", \
  102.         0, pmp_config_x.protection, pmp_config_x.base_addr, pmp_config_x.order);

  103.     __set_PMPENTRYx(1, &pmp_config_rw);
  104.     /* Verify the configuration takes effect */
  105.     memset(&pmp_config_rw, 0, sizeof(pmp_config));
  106.     __get_PMPENTRYx(1, &pmp_config_rw);
  107.     printf("Get pmp entry: index %d, prot_out: 0x%x, addr_out: 0x%lx, order_out: %lu\r\n", \
  108.         1, pmp_config_rw.protection, pmp_config_rw.base_addr, pmp_config_rw.order);

  109.     /* register corresponding exception */
  110.     Exception_Register_EXC(InsAccFault_EXCn, (unsigned long)pmp_violation_fault_handler);
  111.     Exception_Register_EXC(LdFault_EXCn, (unsigned long)pmp_violation_fault_handler);
  112.     Exception_Register_EXC(StAccessFault_EXCn, (unsigned long)pmp_violation_fault_handler);

  113.     /* In case compiler use inline optimization of protected_execute */
  114.     __funcpt fncptr = ((__funcpt)protected_execute);
  115.     printf("Attempting to fetch instruction from protected address\n");
  116.     fncptr();

  117.     while(1);
  118.     return 0;
  119. }


 楼主| lindahnu 发表于 2024-7-1 09:42 | 显示全部楼层
是用IDE自动创建的工程,测试读写权限也是没有进异常中断。
jcky001 发表于 2024-7-2 11:31 | 显示全部楼层
PMP配置有误?
elephant00 发表于 2024-7-2 11:33 | 显示全部楼层
检查中断向量表是否正确设置,确保InsAccFault_EXCn中断处理函数的地址被正确放置在中断向量表中。
 楼主| lindahnu 发表于 2024-7-2 18:10 | 显示全部楼层
debug时PMP配置完成后回读的值__get_PMPENTRYx是不对的。查资料这款MCU用的是Bumblebee内核,芯来科技Bumblebee 处理器内核指令架构手册上说它并不支持 PMP 单元,可又提供示例工程,太奇怪了。
cr315 发表于 2024-7-3 11:00 | 显示全部楼层
代码执行在PMP区域之外
LOVEEVER 发表于 2024-7-15 14:41 | 显示全部楼层
这个楼主是根据案例程序进行的修改嘛?
szt1993 发表于 2024-7-17 19:28 | 显示全部楼层
选择测试INSTRUCTION_FETCH_EXCEPTION不开启执行权限“X”导致的无法进入
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

31

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部