ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

11. 缺页中断处理概述

2021-07-18 16:34:22  阅读:278  来源: 互联网

标签:11 do info fault bad fsr abort 概述 缺页


在之前介绍malloc()和mmap()两个用户API函数的内核实现时,我们发现它们只建立了进程地址空间,在用户空间可以看到虚拟内存,但没有建立虚拟内存和物理内存之间的映射关系。当进程访问这些还没有建立映射关系的虚拟内存时,处理器自动触发一个缺页异常(也称为"缺页中断"),linux内核必须处理此异常。缺页异常是内存管理当中最复杂和重要的一部分,需要考虑很多的细节,包括匿名页面、KSM页面、page cache页面、写时复制、私有映射和共享映射等。

    缺页异常处理依赖于处理器的体系结构,因此缺页异常底层的处理流程在内核代码中特定体系结构的部分。下面以ARMv7为例来介绍底层缺页异常处理的过程。

    当在数据访问周期里进行存储访问时发生异常,基于ARMv7-A架构的处理器会跳转到异常向量表的Data abort向量中。Data abort的底层汇编处理和irq中断类似。汇编处理流程为__vectors_start->vector_dabt->__dabt_usr/__dabt_svc->dabt_helper->v7_early_abort,我们从ENTRY(v7_early_abort)开始介绍。

[arch/arm/mm/abort-ev7.S]

ENTRY(v7_early_abort)
    mrc p15, 0, r1, c5, c0, 0       @ get FSR
    mrc p15, 0, r0, c6, c0, 0       @ get FAR

    /*
     * V6 code adjusts the returned DFSR.
     * New designs should not need to patch up faults.
     */

#if defined(CONFIG_VERIFY_PERMISSION_FAULT)
    /*
     * Detect erroneous permission failures and fix
     */
    ldr r3, =0x40d          @ On permission fault
    and r3, r1, r3
    cmp r3, #0x0d
    bne do_DataAbort

    mcr p15, 0, r0, c7, c8, 0       @ Retranslate FAR
    isb
    mrc p15, 0, ip, c7, c4, 0       @ Read the PAR
    and r3, ip, #0x7b           @ On translation fault
    cmp r3, #0x0b
    bne do_DataAbort
    bic r1, r1, #0xf            @ Fix up FSR FS[5:0]
    and ip, ip, #0x7e
    orr r1, r1, ip, LSR #1
#endif

    b   do_DataAbort

ARM的MMU中有如下两个与存储访问失效相关的寄存器。

  • 失效状态寄存器(Data Fault Status Register, FSR).

  • 失效地址寄存器(Data Fault Address Register, FAR).

当发生存储访问失效时,失效状态寄存器FSR会反映所发生的存储失效的相关信息,包括存储访问所属域和存储访问的类型等,同时失效地址寄存器会记录访问失效的虚拟地址。汇编函数v7_early_abort通过协处理器的寄存器c5和c6读取出FSR和FAR寄存器后,直接调用C语言的do_DataAbort()函数。

/*
 * Dispatch a data abort to the relevant handler.
 */
asmlinkage void __exception
do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
    /*struct fsr_info数据结构用于描述一条失效状态对应的处理方案,下面给出,请立即查看*/
    const struct fsr_info *inf = fsr_info + fsr_fs(fsr);
    struct siginfo info;

    if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs))
        return;

    pr_alert("Unhandled fault: %s (0x%03x) at 0x%08lx\n",
        inf->name, fsr, addr);
    show_pte(current->mm, addr);

    info.si_signo = inf->sig;
    info.si_errno = 0;
    info.si_code  = inf->code;
    info.si_addr  = (void __user *)addr;
    arm_notify_die("", regs, &info, fsr, 0);
}
static inline int fsr_fs(unsigned int fsr)
{
    return (fsr & FSR_FS3_0) | (fsr & FSR_FS4) >> 6;
}
struct fsr_info {
    int (*fn)(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
    int sig;
    int code;
    const char *name;
};
@fn: 表示修复这条失效状态的函数指针.
@sig:表示处理失败时linux内核要发送的信号类型.
@name: 表示这条失效状态的名称.

[arch/arm/mm/fsr-2level.c]

tatic struct fsr_info fsr_info[] = {
    /*
     * The following are the standard ARMv3 and ARMv4 aborts.  ARMv5
     * defines these to be "precise" aborts.
     */
    { do_bad,       SIGSEGV, 0,     "vector exception"         },
    { do_bad,       SIGBUS,  BUS_ADRALN,    "alignment exception"          },
    { do_bad,       SIGKILL, 0,     "terminal exception"           },
    { do_bad,       SIGBUS,  BUS_ADRALN,    "alignment exception"          },
    { do_bad,       SIGBUS,  0,     "external abort on linefetch"      },
    { do_translation_fault, SIGSEGV, SEGV_MAPERR,   "section translation fault"    },
    { do_bad,       SIGBUS,  0,     "external abort on linefetch"      },
    { do_page_fault,    SIGSEGV, SEGV_MAPERR,   "page translation fault"       },
    { do_bad,       SIGBUS,  0,     "external abort on non-linefetch"  },
    { do_bad,       SIGSEGV, SEGV_ACCERR,   "section domain fault"         },
    { do_bad,       SIGBUS,  0,     "external abort on non-linefetch"  },
    { do_bad,       SIGSEGV, SEGV_ACCERR,   "page domain fault"        },
    { do_bad,       SIGBUS,  0,     "external abort on translation"    },
    { do_sect_fault,    SIGSEGV, SEGV_ACCERR,   "section permission fault"     },
    { do_bad,       SIGBUS,  0,     "external abort on translation"    },
   { do_page_fault,    SIGSEGV, SEGV_ACCERR,   "page permission fault"        },
    ......
};

fsr_info[]数组列出了常见的地址失效处理方案,以页面转换失效(page translation fault)和页面访问权限失效为例,它们最终的解决方案是调用do_page_fault()来修复。

标签:11,do,info,fault,bad,fsr,abort,概述,缺页
来源: https://blog.csdn.net/dai_xiangjun/article/details/118863387

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有