来自 x86 中断处理程序的意外跳转
Unexpected jump from an x86 interrupt handler
我正在制作我的自定义 8x86 64 位OS,但我遇到了一些中断处理程序问题。
当我为常见的异常和中断添加中断处理程序时,我通过 "sti" 指令启用了中断。
然后,"General Protection Fault"在启用中断后立即发生。
所以,我检查了 GDB。
堆栈是
(gdb) bt
#0 kISR::kISRGeneralProtection () at /home/xaliver/WorkSpace/kOdin/kernel64/./ISR.cpp:70
#1 0x000000000000fee8 in ?? ()
#2 0x0000000000202e30 in _kISRTimer ()
Backtrace stopped: frame did not save the PC
奇怪的部分是0xfee8。我使用 0x10000 以下的内存作为 32 位保护模式的堆栈。现在,系统处于 64 位模式,因此值为空,如“00 00”。
所以,我检查了第 2 帧,_kISRTimer。
0xfee8保存的rip为0x202e30。是_kISRTimer的"iretq"指令。
这里是汇编代码。
; #32, Timer ISR
_kISRTimer:
KSAVECONTEXT ; Store the context and change selector to
202dd3: 55 push %rbp
202dd4: 48 89 e5 mov %rsp,%rbp
202dd7: 50 push %rax
202dd8: 53 push %rbx
202dd9: 51 push %rcx
202dda: 52 push %rdx
202ddb: 57 push %rdi
202ddc: 56 push %rsi
202ddd: 41 50 push %r8
202ddf: 41 51 push %r9
202de1: 41 52 push %r10
202de3: 41 53 push %r11
202de5: 41 54 push %r12
202de7: 41 55 push %r13
202de9: 41 56 push %r14
202deb: 41 57 push %r15
202ded: 66 8c d8 mov %ds,%ax
202df0: 50 push %rax
202df1: 66 8c c0 mov %es,%ax
202df4: 50 push %rax
202df5: 0f a0 pushq %fs
202df7: 0f a8 pushq %gs
202df9: 66 b8 10 00 mov [=11=]x10,%ax
202dfd: 8e d8 mov %eax,%ds
202dff: 8e c0 mov %eax,%es
202e01: 8e e8 mov %eax,%gs
202e03: 8e e0 mov %eax,%fs
; kernel data descriptor
; Insert interrupt number to the hander and call the handler
mov rdi, 32
202e05: bf 20 00 00 00 mov [=11=]x20,%edi
call _kCommonInterruptHandler
202e0a: e8 75 e3 ff ff callq 201184 <_kCommonInterruptHandler>
KLOADCONTEXT ; Restore the context
202e0f: 0f a9 popq %gs
202e11: 0f a1 popq %fs
202e13: 58 pop %rax
202e14: 8e c0 mov %eax,%es
202e16: 58 pop %rax
202e17: 8e d8 mov %eax,%ds
202e19: 41 5f pop %r15
202e1b: 41 5e pop %r14
202e1d: 41 5d pop %r13
202e1f: 41 5c pop %r12
202e21: 41 5b pop %r11
202e23: 41 5a pop %r10
202e25: 41 59 pop %r9
202e27: 41 58 pop %r8
202e29: 5e pop %rsi
202e2a: 5f pop %rdi
202e2b: 5a pop %rdx
202e2c: 59 pop %rcx
202e2d: 5b pop %rbx
202e2e: 58 pop %rax
202e2f: 5d pop %rbp
iretq ; Return the event point after interrupt
202e30: 48 cf iretq
我认为跳0xfee8没有意义。
我还尝试删除定时器的中断处理程序。但是,"GPF" 出现在其他中断处理程序中。其他中断处理程序与_kISRTimer相同,只是调用函数不同
从代码中知道为什么会出现GPF吗?
或者,跳转不是来自代码?
请让我知道为什么会出现这个问题。
谢谢。
The iretq
instruction 或 return 从中断处理程序到 64 位地址,期望 return 地址和标志位于堆栈顶部,并产生一个如果 return 地址无效(例如,因为它指向一个不执行的内存页面),则一般保护错误。因此,当您的处理程序被调用时,您应该检查堆栈上的值、调用代码和 CS 选择器。如果其中任何一个发生了变化,您的堆栈可能包含垃圾。您对“0x10000 以下的内存作为 32 位保护模式的堆栈”的评论表明,其中一种或两种情况都可能是这种情况。
我正在制作我的自定义 8x86 64 位OS,但我遇到了一些中断处理程序问题。
当我为常见的异常和中断添加中断处理程序时,我通过 "sti" 指令启用了中断。
然后,"General Protection Fault"在启用中断后立即发生。
所以,我检查了 GDB。
堆栈是
(gdb) bt
#0 kISR::kISRGeneralProtection () at /home/xaliver/WorkSpace/kOdin/kernel64/./ISR.cpp:70
#1 0x000000000000fee8 in ?? ()
#2 0x0000000000202e30 in _kISRTimer ()
Backtrace stopped: frame did not save the PC
奇怪的部分是0xfee8。我使用 0x10000 以下的内存作为 32 位保护模式的堆栈。现在,系统处于 64 位模式,因此值为空,如“00 00”。
所以,我检查了第 2 帧,_kISRTimer。
0xfee8保存的rip为0x202e30。是_kISRTimer的"iretq"指令。
这里是汇编代码。
; #32, Timer ISR
_kISRTimer:
KSAVECONTEXT ; Store the context and change selector to
202dd3: 55 push %rbp
202dd4: 48 89 e5 mov %rsp,%rbp
202dd7: 50 push %rax
202dd8: 53 push %rbx
202dd9: 51 push %rcx
202dda: 52 push %rdx
202ddb: 57 push %rdi
202ddc: 56 push %rsi
202ddd: 41 50 push %r8
202ddf: 41 51 push %r9
202de1: 41 52 push %r10
202de3: 41 53 push %r11
202de5: 41 54 push %r12
202de7: 41 55 push %r13
202de9: 41 56 push %r14
202deb: 41 57 push %r15
202ded: 66 8c d8 mov %ds,%ax
202df0: 50 push %rax
202df1: 66 8c c0 mov %es,%ax
202df4: 50 push %rax
202df5: 0f a0 pushq %fs
202df7: 0f a8 pushq %gs
202df9: 66 b8 10 00 mov [=11=]x10,%ax
202dfd: 8e d8 mov %eax,%ds
202dff: 8e c0 mov %eax,%es
202e01: 8e e8 mov %eax,%gs
202e03: 8e e0 mov %eax,%fs
; kernel data descriptor
; Insert interrupt number to the hander and call the handler
mov rdi, 32
202e05: bf 20 00 00 00 mov [=11=]x20,%edi
call _kCommonInterruptHandler
202e0a: e8 75 e3 ff ff callq 201184 <_kCommonInterruptHandler>
KLOADCONTEXT ; Restore the context
202e0f: 0f a9 popq %gs
202e11: 0f a1 popq %fs
202e13: 58 pop %rax
202e14: 8e c0 mov %eax,%es
202e16: 58 pop %rax
202e17: 8e d8 mov %eax,%ds
202e19: 41 5f pop %r15
202e1b: 41 5e pop %r14
202e1d: 41 5d pop %r13
202e1f: 41 5c pop %r12
202e21: 41 5b pop %r11
202e23: 41 5a pop %r10
202e25: 41 59 pop %r9
202e27: 41 58 pop %r8
202e29: 5e pop %rsi
202e2a: 5f pop %rdi
202e2b: 5a pop %rdx
202e2c: 59 pop %rcx
202e2d: 5b pop %rbx
202e2e: 58 pop %rax
202e2f: 5d pop %rbp
iretq ; Return the event point after interrupt
202e30: 48 cf iretq
我认为跳0xfee8没有意义。
我还尝试删除定时器的中断处理程序。但是,"GPF" 出现在其他中断处理程序中。其他中断处理程序与_kISRTimer相同,只是调用函数不同
从代码中知道为什么会出现GPF吗? 或者,跳转不是来自代码? 请让我知道为什么会出现这个问题。 谢谢。
The iretq
instruction 或 return 从中断处理程序到 64 位地址,期望 return 地址和标志位于堆栈顶部,并产生一个如果 return 地址无效(例如,因为它指向一个不执行的内存页面),则一般保护错误。因此,当您的处理程序被调用时,您应该检查堆栈上的值、调用代码和 CS 选择器。如果其中任何一个发生了变化,您的堆栈可能包含垃圾。您对“0x10000 以下的内存作为 32 位保护模式的堆栈”的评论表明,其中一种或两种情况都可能是这种情况。