[RISC-V MCU 应用开发]

gd32vf103 PMP内存保护疑问

[复制链接]
327|5
手机看帖
扫描二维码
随时随地手机跟帖
lindahnu|  楼主 | 2024-7-1 09:27 | 显示全部楼层 |阅读模式
本帖最后由 lindahnu 于 2024-7-2 18:04 编辑

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

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

/* different trigger condition */
#define INSTRUCTION_FETCH_EXCEPTION    0
#define LOAD_EXCEPTION                 1
#define STORE_EXCEPTION                2
#define RUN_WITH_NO_PMP_CHECK          3

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

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

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

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

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

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

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

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

    switch (mcause & MCAUSE_CAUSE) {
        case InsAccFault_EXCn:
            printf("Instruction access fault occurs, cause: 0x%lx, epc: 0x%lx\r\n", exc_frame->cause, exc_frame->epc);
            break;
        case LdFault_EXCn:
            printf("Load access fault occurs, cause: 0x%lx, epc: 0x%lx\r\n", exc_frame->cause, exc_frame->epc);
            break;
        case StAccessFault_EXCn:
            printf("Store/AMO access fault occurs, cause: 0x%lx, epc: 0x%lx\r\n", exc_frame->cause, exc_frame->epc);
            break;
        default: break;
    }
    while(1);
}

typedef void(*__funcpt)(void);

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

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

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

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

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

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

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

    pmp_config_rw.protection = PMP_R | PMP_W ;
#endif

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

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

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

    /* register corresponding exception */
    Exception_Register_EXC(InsAccFault_EXCn, (unsigned long)pmp_violation_fault_handler);
    Exception_Register_EXC(LdFault_EXCn, (unsigned long)pmp_violation_fault_handler);
    Exception_Register_EXC(StAccessFault_EXCn, (unsigned long)pmp_violation_fault_handler);

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

    while(1);
    return 0;
}


使用特权

评论回复

相关帖子

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区域之外

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

25

帖子

0

粉丝