由于无效的堆栈指针,无法调用汇编页面故障处理程序

问题描述 投票:1回答:1

当我的页面错误处理程序中断被调用(应该使系统挂起)时,在调用之前有一些变量被压入堆栈。我启用了虚拟内存,当我设置了无效的堆栈指针(esp)并调用了int14处理程序时,它立即导致另一个页面错误,依此类推。我应该如何解决这种情况?

我的int14代码:

isr14:
    ; interrupt handler for isr14
    jmp $
    iretd

导致其中断的代码:

mov esp, 0x1000 ; 0x1000 is not mapped in the VM directory
push dword 'A'
jmp $

我的IDT表的部分:

irq14:
    dw isr14
    dw 0x0008
    db 0x00
    db 10101110b
    dw 0x0000

irq15:
........
assembly x86 kernel virtual-machine interrupt
1个回答
0
投票

我应该如何解决这种情况?

我将通过使用规避来解决这种情况-请勿让内核首先使用狡猾的堆栈指针(也不要让内核堆栈发送到交换空间,请勿将页面错误用于“不断增长的内核堆栈”等)。请注意,如果在用户空间中发生页面错误(在CPL = 3时),CPU将自动切换到内核堆栈,因此用户空间是否具有躲避堆栈指针并不重要。

替代品是:

  • 当内核代码(CPL = 0)导致页面错误时,强制执行内核堆栈切换。可以使用硬件任务切换(保护模式)或页面错误异常处理程序的IST机制(长模式)来完成此操作。这将是恢复的最佳选择(例如,可以更轻松地找出问题所在,解决问题然后返回)。

  • 当内核代码(CPL = 0)引起双重错误时,强制执行内核堆栈切换。可以使用硬件任务切换(保护模式)或双重故障异常处理程序的IST机制(长模式)来完成此操作。这将是提高性能的最佳选择(对于正常的页面错误,不会增加开销)。

注1:请注意,硬件任务切换/任务门或IST均不可重入。对于硬件任务切换,如果在处理第一个页面错误时发生第二个页面错误,则会收到一般性保护错误(因为“页面错误任务”很忙);对于IST,如果在处理第一个页面错误时发生第二个页面错误,则第二个页面错误将破坏/覆盖第一个页面错误的堆栈,并使它无法恢复。从理论上讲,您可以通过尽快切换到不同的任务或不同的堆栈来减轻这些问题,但这很复杂/杂乱无章,可能会导致更多问题。

注2:使用硬件任务开关或IST,您可能最终会避免和避免双重错误;双重故障处理程序将“冻结系统并转储信息/紧急情况”作为灾难性内核故障(应该避免但并非应该避免)的通用回退。

注3:如果要支持“自动增长的内核堆栈”;您可以改用“堆栈探针”-基本上,只需在将内存用于堆栈之前从“未来堆栈”中进行虚拟读/ s(在函数结语中),以便在页面上剩下足够的内核堆栈时发生页面错误故障处理程序。

© www.soinside.com 2019 - 2024. All rights reserved.