PMP导致异常问题分析
现象和确认异常原因
触发了异常中断
查看异常原因为7 store access-fault exception.
并查看异常访问的地址为0x28382ad0
gdb也确认这个地址确实只能读不能写
查看PMP寄存器确认根本原因
Pmpcfg0 对应地址pmp0cfg~pmp3cfg
Pmpcfg1 对应地址pmp4cfg~pmp7cfg
Pmpcfg2 对应地址pmp8cfg~pmp11cfg
Pmpcfg3 对应地址pmp12cfg~pmp15cfg
pmpcfg3为0x5100即对应pmp13cfg为0x51
8位的配置属性0x51如下 只读
A=10 即NA4表示4字节区域,即pmpaddrxx对应的4字节区域
L=1
A=10=2 NA4
R=1
X=0
W=0
对应pmp13cfg的pmpaddr13=0xa0e0ab4 是34位地址右移2位的值,所以左移两位恢复实际值是0x2C38 2AD0
表示的范围是[0x2C38 2AD0,0x2C38 2AD3] 4字节
我们的地址空间是0x28000000-0x2bffffff
写0x2C38 2AD0实际映射到了写0x2838 2AD0 64M绕回。
所以写0x2838 2AD0这个不具备写属性的地址触发了store access-fault
exception.异常
所以以上确认了原因是PMP设置了该地址不具备写属性,而代码中去写所以导致了异常。
代码
我们的空间最多只有128M,最多到0x2bff ffff,为什么写了个0x2C38 2AD0的地址进去,
先找到对应的代码
由于是用的所以13的配置,所以先找这个索引对应
#define PMP_FIXED_INDEX_TASK_STACK 13
然后再搜索这个索引
找到如下函数
这个函数在vTaskSwitchContext调用
if (prev != pxCurrentTCB) {
pmp_task_stack_set((uint32_t)pxCurrentTCB- >pxStack);
}
即任务有切换时,设置栈底4字节不可写,用于栈溢出检测。
加个死循环用于在设置该值时停住
所以要确认什么时候写了0x2838 2AD0这个地址,由于使能了PMP,所以watchpoint抓不到,先触发了pmp的异常。
所以先关闭pmp设置
if (prev != pxCurrentTCB) {
///pmp_task_stack_set((uint32_t)pxCurrentTCB- >pxStack);
}
然后设置数据断点
watch (unsigned int )0x28382ad0
运行
第一次停在栈初始化,第二次停在如下处
可以看到
任务栈的地址是 0x28382ad0开始但是 临时变量mem的地址是0x28382a60在栈前面去了,所以栈溢出了。
把栈改大即可
审核编辑:汤梓红
-
嵌入式
+关注
关注
5068文章
19013浏览量
303121 -
调试
+关注
关注
7文章
572浏览量
33893 -
PMP
+关注
关注
0文章
45浏览量
18137 -
RISC-V
+关注
关注
44文章
2228浏览量
46007
发布评论请先 登录
相关推荐
评论