abort 异常解读(Prefetch Abort & Data Abort)
instruction fetch memory abort
data access memory abort
在 内存访问流程中 , ARM处理器可能会发生异常
异常的原因是中止( 异常的访问) , 中止分为三种:
MMU faults ( 4 种)
MMU检测到限制并向处理器发送信号。
Debug abort
监视器调试模式已启用,并且检测到断点或监视点。
External abort ( 三种)
外部内存系统发出非法或错误的内存访问信号。
MMU faults
如果中止的内存请求是指令获取,则当处理器尝试执行与中止的访问对应的指令时,将引发预取中止异常。
如果中止的访问是数据访问或缓存维护操作,则会引发数据中止异常。
Debug event
当启用监视调试模式时 , 可以由于 指令访问上的breakpoint 而执行中止, 产生 预取中止异常
当启用监视调试模式时 , 可以由于 数据访问上的watchpoint 而执行中止, 产生 数据中止异常
External abort
指令获取时的外部中止 , 可能会产生 预取中止异常( 依据是否执行)
数据读/ 写时外部中止 , 会产生 数据中止异常
硬件页表遍历上的外部中止 , 会产生 数据中止异常
案例
本次案例是匿名缺页, 会产生
MMU faults 中的 下面哪一种? ( alignment fault/ translation fault/ domain fault/ permission fault)
因为 没有做映射, 所以应该是 translation fault ,
此时是访问数据, 从而导致 数据中止异常
# include <sys/mman.h>
# include <stdio.h>
# include <memory.h>
int main ( int argc, char * argv[ ] ) {
char * m;
size_t s = 256 * 1024 ;
m = mmap ( NULL , s, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS , - 1 , 0 ) ;
if ( m == MAP_FAILED) {
perror ( "map mem" ) ;
m = NULL ;
return 1 ;
}
printf ( "mmap alloc memory ok, press ENTER to acess memory!\n" ) ;
getchar ( ) ;
memset ( m, 0 , s) ;
printf ( "mmap acess memory ok, press ENTER to quit!\n" ) ;
getchar ( ) ;
munmap ( m, s) ;
return 0 ;
}
A mmap 系统调用及返回
file-> f_op-> mmap 没有申请物理内存, 没有做映射, 而是在 file-> f_op-> mmap 中设置了 vma-> ops = & my_file_mmap
B 访存
访存的动作 是 在用户空间做的
例如 * p 就是访存动作
这个动作做完之后, 就会产生一个 data abort 异常
C data abort 异常硬件流程
访存( 访问存储器) 时发生异常, armv6 会
1. 设置 FSR
2. 设置 FAR
R14_abt = address of the aborted instruction + 8
SPSR_abt = CPSR
CPSR[ 4 : 0 ] = 0 b10111
CPSR[ 5 ] = 0
CPSR[ 7 ] = 1
CPSR[ 8 ] = 1
CPSR[ 9 ] = CP15_reg1_EEbit
if high vectors configured then
PC = 0xFFFF0010
else
PC = 0x00000010
D linux-5.11 对 data abort 异常的处理
__vectors_start
vector_dabt
__dabt_usr/ __dabt_svc
dabt_helper
CPU_DABORT_HANDLER/ v7_early_abort
v7_early_abort
mrc c5
mrc c6
do_DataAbort
fsr_info[ 0. . .4 ]
do_translation_fault
do_translation_fault
do_page_fault
__do_page_fault
handle_mm_fault
__handle_mm_fault
handle_pte_fault
do_anonymous_page
__do_user_fault
__do_kernel_fault
A 针对 匿名页面缺页异常 do_anonymous_page
有虚拟地址, 没有映射, 没有物理地址
应用场景 : malloc
在访问地址时会导致内存访问异常, 流程中会调用 do_anonymous_page
do_anonymous_page ( mm= 0xee11e540 , vma= 0xeeb02738 , address= 3069333504 , page_table= 0xee13c494 , pmd= 0xedc0edb8 , flags= 85 )
page = alloc_zeroed_user_highpage_movable ( vma, address) ;
( struct page * ) 0xef019cc0
do_anonymous_page ( mm= 0xee11e540 , vma= 0xeeb02738 , address= 3069337600 , page_table= 0xee13c498 , pmd= 0xedc0edb8 , flags= 85 )
page = alloc_zeroed_user_highpage_movable ( vma, address) ;
( struct page * ) 0xef019ca0
do_anonymous_page ( mm= 0xee11e540 , vma= 0xeeb02738 , address= 3069341696 , page_table= 0xee13c49c , pmd= 0xedc0edb8 , flags= 85 )
page = alloc_zeroed_user_highpage_movable ( vma, address) ;
( struct page * ) 0xef019c80
硬件流程
关键字 “Sequence for checking faults”