OK6410A 开发板 (八) 54 linux-5.11 OK6410A 缺页异常实例分析

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 ,// TODO
此时是访问数据,从而导致 数据中止异常
  • 应用程序
// mmap (因为mmap比malloc简单)
// A1. 私有匿名映射	: 用于 分配大块内存(128KB及以上)
// fd = -1 flags=MAP_ANONYMOUS|MAP_PRIVATE

#include <sys/mman.h>
#include <stdio.h>
#include <memory.h>

int main(int argc, char *argv[]) {
        char *m;
        size_t s = 256 * 1024;
		
		// 此时会进入 系统调用 mmap
		// 做 虚拟内存的申请
        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();
        
        // 此时会 进入异常 data abort
        // 每访问一页,就会进入一次异常
        // 进入的时候 , 会调用 do_anonymous_page  为 4KB 虚拟地址
        // 1. 做 物理页的申请				alloc_zeroed_user_highpage_movable
        // 2. 做 虚拟内存与物理内存的映射 	set_pte_at
        
        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 // Fault Status Register	存储失效的相关信息(包括存储访问所属区域和访问类型)
	2.设置 FAR // Fault Address Register 存储访问失效的虚拟地址

	R14_abt = address of the aborted instruction + 8
	SPSR_abt = CPSR
	CPSR[4:0] = 0b10111 		/* Enter Abort mode */
	CPSR[5] = 0 				/* Execute in ARM state */
								/* CPSR[6] is unchanged */
	CPSR[7] = 1 				/* Disable normal interrupts */
	CPSR[8] = 1 				/* Disable Imprecise Data Aborts (v6 only) */
	CPSR[9] = CP15_reg1_EEbit 	/* Endianness on exception entry */
	if high vectors configured then
	PC = 0xFFFF0010
	else
	PC = 0x00000010

D linux-5.11 对 data abort 异常的处理
  • level 1

__vectors_start
	vector_dabt
		__dabt_usr/__dabt_svc
			dabt_helper
				CPU_DABORT_HANDLER/v7_early_abort

  • level 2
v7_early_abort
	mrc c5 // 读 c5
	mrc c6 // 读 c6
	do_DataAbort
		fsr_info[0...4] // exceptions_init 注册了 do_translation_fault // hook_fault_code(4, do_translation_fault, SIGSEGV, SEGV_MAPERR, "I-cache maintenance fault");
			do_translation_fault
  • level 2
do_translation_fault
	do_page_fault // 缺页异常 的 核心函数
		__do_page_fault
			handle_mm_fault
				__handle_mm_fault
					handle_pte_fault
						do_anonymous_page
		__do_user_fault		// 用户空间访问 0地址时会出现这种情况
		__do_kernel_fault  	// 内核空间访问 0地址是会出现这种情况
	A 针对 匿名页面缺页异常 do_anonymous_page
		有虚拟地址,没有映射,没有物理地址
		应用场景 : malloc // 匿名页面(没有关联到文件映射的页面)

在访问地址时会导致内存访问异常, 流程中会调用 do_anonymous_page
  • level 3
// 每一次进入do_anonymous_page  做 一页的映射
// 多次 进入之后,发现
// 同一个进程,同一个vma,虚拟地址地址越来越高,page地址越来越低(物理地址越来越低) 
// 此时无法用 page_to_phys(page) 打印物理地址,但是 struct page 的地址 都是间隔 0x20,说明 物理地址是连续的
// pmd 是一样的,pmd 中是 页表基址寄存器 的值
// page_table 是 一级页表的地址

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
	// 物理地址 : TODO

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”
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值