⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 001_arch_i386_mm_fault_.html

📁 重读linux 2.4.2o所写的笔记
💻 HTML
📖 第 1 页 / 共 3 页
字号:
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;goto bad_area; //没有这样的vma<br>
        &nbsp;&nbsp; &nbsp;if (vma-&gt;vm_start &lt;= address)<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;goto good_area; //异常地址在一个vma 中<br>
        <br>
        &nbsp;&nbsp;&nbsp; //运行到这里表示, 这个地址落到了一个vma 空洞中<br>
        &nbsp;&nbsp; &nbsp;if (!(vma-&gt;vm_flags &amp; VM_GROWSDOWN))<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;goto bad_area;&nbsp; //如果这个空洞上的vma
        不是堆栈, 肯定是越界<br>
        <br>
        &nbsp;&nbsp; &nbsp;if (error_code &amp; 4) {<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;/*<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; * accessing the stack below %esp
        is always a bug.<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; * The "+ 32" is there due to some
        instructions (like<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; * pusha) doing post-decrement on
        the stack and that<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; * doesn't show up until later..<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; */<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (address + 32 &lt;
        regs-&gt;esp)<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;goto
        bad_area;&nbsp; //异常点不在esp 附近时也是一种越界<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        //而不是正常的堆栈操作<br>
        &nbsp;&nbsp; &nbsp;}<br>
        &nbsp;&nbsp; &nbsp;//对于正常的堆栈操作越界,我们应该为用户扩展堆栈<br>
        &nbsp;&nbsp; &nbsp;if (expand_stack(vma, address))<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;goto bad_area; //扩展失败, 转到bad_area<br>
        &nbsp;&nbsp; &nbsp;<br>
        /*<br>
        &nbsp;* 堆栈扩展以后, vma 就正常了,因此流程自然进入good_area<br>
        &nbsp;*/<br>
        good_area:<br>
        &nbsp;&nbsp;&nbsp; //异常点在正确的vma 中<br>
        &nbsp;&nbsp;&nbsp; //还要根据vma(代表OS) 容许的权限, 对异常分类<br>
        &nbsp;&nbsp; &nbsp;info.si_code = SEGV_ACCERR;<br>
        &nbsp;&nbsp; &nbsp;write = 0;<br>
        &nbsp;&nbsp; &nbsp;switch (error_code &amp; 3) {<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;default:&nbsp;&nbsp; &nbsp;/* 3:
        write, present */<br>
        #ifdef TEST_VERIFY_AREA<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (regs-&gt;cs
        == KERNEL_CS)<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
        &nbsp;printk("WP fault at %08lx\n", regs-&gt;eip);<br>
        #endif<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;/* fall through
        */<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case 2:&nbsp;&nbsp;
        &nbsp;&nbsp;&nbsp; &nbsp;/* write, not present */<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if
        (!(vma-&gt;vm_flags &amp; VM_WRITE))<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
        &nbsp;goto bad_area; //vma 不容许写, 是一种非法操作<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;write++;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case 1:&nbsp;&nbsp;
        &nbsp;&nbsp;&nbsp; &nbsp;/* read, present */<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;goto bad_area;
        // 权限错误, 非法<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;case 0:&nbsp;&nbsp;
        &nbsp;&nbsp;&nbsp; &nbsp;/* read, not present */<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if
        (!(vma-&gt;vm_flags &amp; (VM_READ | VM_EXEC)))<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
        &nbsp;goto bad_area; //vma 不容许读的情况下非法<br>
        &nbsp;&nbsp; &nbsp;}<br>
        <br>
        &nbsp;&nbsp; &nbsp;/*<br>
        &nbsp;&nbsp; &nbsp; * 如果处理陷入时到了这里,<br>
        &nbsp;&nbsp; &nbsp; * 说明异常点在一个完好的vma 中,并且符合OS 赋予<br>
        &nbsp;&nbsp; &nbsp; * 用户的权限.<br>
        &nbsp;&nbsp; &nbsp; */<br>
        &nbsp;&nbsp; &nbsp;switch (handle_mm_fault(mm, vma, address, write)) {<br>
        &nbsp;&nbsp; &nbsp;case
        1:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        &nbsp;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;tsk-&gt;min_flt++;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br>
        &nbsp;&nbsp; &nbsp;case 2:<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;tsk-&gt;maj_flt++;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;break;<br>
        &nbsp;&nbsp; &nbsp;case 0:<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;goto do_sigbus;<br>
        &nbsp;&nbsp; &nbsp;default:<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;goto out_of_memory;<br>
        &nbsp;&nbsp; &nbsp;}<br>
        <br>
        &nbsp;&nbsp; &nbsp;/*<br>
        &nbsp;&nbsp; &nbsp; * Did it hit the DOS screen memory VA from vm86
        mode?<br>
        &nbsp;&nbsp; &nbsp; */<br>
        &nbsp;&nbsp; &nbsp;if (regs-&gt;eflags &amp; VM_MASK) {<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;unsigned long bit = (address -
        0xA0000) &gt;&gt; PAGE_SHIFT;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (bit &lt; 32)<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
        &nbsp;tsk-&gt;thread.screen_bitmap |= 1 &lt;&lt; bit;<br>
        &nbsp;&nbsp; &nbsp;}<br>
        &nbsp;&nbsp; &nbsp;up(&amp;mm-&gt;mmap_sem);<br>
        &nbsp;&nbsp; &nbsp;return;<br>
        <br>
        /*<br>
        &nbsp;* Something tried to access memory that isn't in our memory map..<br>
        &nbsp;* Fix it, but check if it's kernel or user first..<br>
        &nbsp;*/<br>
        bad_area:<br>
        &nbsp;&nbsp; &nbsp;up(&amp;mm-&gt;mmap_sem);<br>
        <br>
        bad_area_nosemaphore:<br>
        &nbsp;&nbsp; &nbsp;/* User mode accesses just cause a SIGSEGV */<br>
        &nbsp;&nbsp; &nbsp;if (error_code &amp; 4) {<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;tsk-&gt;thread.cr2 = address;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;tsk-&gt;thread.error_code =
        error_code;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;tsk-&gt;thread.trap_no = 14;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;info.si_signo = SIGSEGV;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;info.si_errno = 0;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;/* info.si_code has been set above
        */<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;info.si_addr = (void *)address;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;force_sig_info(SIGSEGV, &amp;info,
        tsk);<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return;<br>
        &nbsp;&nbsp; &nbsp;}<br>
        <br>
        &nbsp;&nbsp; &nbsp;/*<br>
        &nbsp;&nbsp; &nbsp; * Pentium F0 0F C7 C8 bug workaround.<br>
        &nbsp;&nbsp; &nbsp; */<br>
        &nbsp;&nbsp; &nbsp;if (boot_cpu_data.f00f_bug) {<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;unsigned long nr;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;nr = (address - idt) &gt;&gt; 3;<br>
        <br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (nr == 6) {<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
        &nbsp;do_invalid_op(regs, 0);<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br>
        &nbsp;&nbsp; &nbsp;}<br>
        <br>
        no_context:<br>
        &nbsp;&nbsp; &nbsp;/* Are we prepared to handle this kernel fault?&nbsp;
        */<br>
        &nbsp;&nbsp; &nbsp;if ((fixup = search_exception_table(regs-&gt;eip)) !=
        0) {<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;regs-&gt;eip = fixup;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return;<br>
        &nbsp;&nbsp; &nbsp;}<br>
        <br>
        /*<br>
        &nbsp;* Oops. The kernel tried to access some bad page. We'll have to<br>
        &nbsp;* terminate things with extreme prejudice.<br>
        &nbsp;*/<br>
        <br>
        &nbsp;&nbsp; &nbsp;bust_spinlocks();<br>
        <br>
        &nbsp;&nbsp; &nbsp;if (address &lt; PAGE_SIZE)<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(KERN_ALERT "Unable to
        handle kernel NULL pointer dereference");<br>
        &nbsp;&nbsp; &nbsp;else<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(KERN_ALERT "Unable to
        handle kernel paging request");<br>
        &nbsp;&nbsp; &nbsp;printk(" at virtual address %08lx\n",address);<br>
        &nbsp;&nbsp; &nbsp;printk(" printing eip:\n");<br>
        &nbsp;&nbsp; &nbsp;printk("%08lx\n", regs-&gt;eip);<br>
        &nbsp;&nbsp; &nbsp;asm("movl %%cr3,%0":"=r" (page));<br>
        &nbsp;&nbsp; &nbsp;page = ((unsigned long *) __va(page))[address
        &gt;&gt; 22];<br>
        &nbsp;&nbsp; &nbsp;printk(KERN_ALERT "*pde = %08lx\n", page);<br>
        &nbsp;&nbsp; &nbsp;if (page &amp; 1) {<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;page &amp;= PAGE_MASK;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;address &amp;= 0x003ff000;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;page = ((unsigned long *)
        __va(page))[address &gt;&gt; PAGE_SHIFT];<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;printk(KERN_ALERT "*pte =
        %08lx\n", page);<br>
        &nbsp;&nbsp; &nbsp;}<br>
        &nbsp;&nbsp; &nbsp;die("Oops", regs, error_code);<br>
        &nbsp;&nbsp; &nbsp;do_exit(SIGKILL);<br>
        <br>
        /*<br>
        &nbsp;* We ran out of memory, or some other thing happened to us that
        made<br>
        &nbsp;* us unable to handle the page fault gracefully.<br>
        &nbsp;*/<br>
        out_of_memory:<br>
        &nbsp;&nbsp; &nbsp;up(&amp;mm-&gt;mmap_sem);<br>
        &nbsp;&nbsp; &nbsp;printk("VM: killing process %s\n", tsk-&gt;comm);<br>
        &nbsp;&nbsp; &nbsp;if (error_code &amp; 4)<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;do_exit(SIGKILL);<br>
        &nbsp;&nbsp; &nbsp;goto no_context;<br>
        <br>
        do_sigbus:<br>
        &nbsp;&nbsp; &nbsp;up(&amp;mm-&gt;mmap_sem);<br>
        <br>
        &nbsp;&nbsp; &nbsp;/*<br>
        &nbsp;&nbsp; &nbsp; * Send a sigbus, regardless of whether we were in
        kernel<br>
        &nbsp;&nbsp; &nbsp; * or user mode.<br>
        &nbsp;&nbsp; &nbsp; */<br>
        &nbsp;&nbsp; &nbsp;tsk-&gt;thread.cr2 = address;<br>
        &nbsp;&nbsp; &nbsp;tsk-&gt;thread.error_code = error_code;<br>
        &nbsp;&nbsp; &nbsp;tsk-&gt;thread.trap_no = 14;<br>
        &nbsp;&nbsp; &nbsp;info.si_code = SIGBUS;<br>
        &nbsp;&nbsp; &nbsp;info.si_errno = 0;<br>
        &nbsp;&nbsp; &nbsp;info.si_code = BUS_ADRERR;<br>
        &nbsp;&nbsp; &nbsp;info.si_addr = (void *)address;<br>
        &nbsp;&nbsp; &nbsp;force_sig_info(SIGBUS, &amp;info, tsk);<br>
        <br>
        &nbsp;&nbsp; &nbsp;/* Kernel mode? Handle exceptions or die */<br>
        &nbsp;&nbsp; &nbsp;if (!(error_code &amp; 4))<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;goto no_context;<br>
        &nbsp;&nbsp; &nbsp;return;<br>
        <br>
        vmalloc_fault: /* 内核的vmalloc可能分配了一个页面但是task自己的页表之内核<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        部分还没有设置。注:每个task都有自己的“kernel 空间”,这里<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        进行同步,从内核自己的页表将kernel space 的映射同步到<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        task page table*/<br>
        &nbsp;&nbsp; &nbsp;{<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;/*<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; * Synchronize this task's top
        level page-table<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; * with the 'reference' page
        table.<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; */<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;int offset =
        __pgd_offset(address);<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pgd_t *pgd, *pgd_k;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pmd_t *pmd, *pmd_k;<br>
        <br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pgd = tsk-&gt;active_mm-&gt;pgd +
        offset;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pgd_k = init_mm.pgd + offset;<br>
        <br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (!pgd_present(*pgd)) {<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if
        (!pgd_present(*pgd_k))<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
        &nbsp;goto bad_area_nosemaphore;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;set_pgd(pgd,
        *pgd_k);<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br>
        <br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pmd = pmd_offset(pgd, address);<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;pmd_k = pmd_offset(pgd_k,
        address);<br>
        <br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (pmd_present(*pmd) ||
        !pmd_present(*pmd_k))<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;goto
        bad_area_nosemaphore;<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;set_pmd(pmd, *pmd_k);<br>
        &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return;<br>
        &nbsp;&nbsp; &nbsp;}<br>
        }<br>
        &nbsp;&nbsp;&nbsp; &nbsp;<br>
        &nbsp;<br>
        &nbsp;&nbsp;&nbsp;&nbsp; 英文说的比较明白的就不敢添足了。<br>
        <br>
        &nbsp;&nbsp;&nbsp;&nbsp;
        幸亏上个函数对handle_mm_fault评论了一番,do_page_fault到这里也该收手了.<br>
        <br>
        <br>
        <br>
        <br>
        <br>
      </td>
    </tr>
    </tbody>
  </table>
</div>
<br>
&nbsp;&nbsp;&nbsp;<br></body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -