xv6里面:
0-31 为software exceptions
32-63 为hardware interrupts
64 system call interrupt
如下则是JOS的表
// Trap numbers
// These are processor defined:
#define T_DIVIDE 0 // divide error
#define T_DEBUG 1 // debug exception
#define T_NMI 2 // non-maskable interrupt
#define T_BRKPT 3 // breakpoint
#define T_OFLOW 4 // overflow
#define T_BOUND 5 // bounds check
#define T_ILLOP 6 // illegal opcode
#define T_DEVICE 7 // device not available
#define T_DBLFLT 8 // double fault
/* #define T_COPROC 9 */ // reserved (not generated by recent processors)
#define T_TSS 10 // invalid task switch segment
#define T_SEGNP 11 // segment not present
#define T_STACK 12 // stack exception
#define T_GPFLT 13 // general protection fault
#define T_PGFLT 14 // page fault
/* #define T_RES 15 */ // reserved
#define T_FPERR 16 // floating point error
#define T_ALIGN 17 // aligment check
#define T_MCHK 18 // machine check
#define T_SIMDERR 19 // SIMD floating point error
// These are arbitrarily chosen, but with care not to overlap
// processor defined exceptions or interrupt vectors.
#define T_SYSCALL 48 // system call
#define T_DEFAULT 500 // catchall
各种寄存器的总结图:
Exercise 4
pusha #如果指令是pushal那么将压入8个32位寄存器。
popa # 依次弹出8个元素,并依序填入到DI, SI, BP, SP, BX, DX, CX, AX这8个寄存器中。
注意下这里上半部分的内容也就是到error code之前,在JOS里面都是processor自动push进去的,根据调用时在user mode还是kernel mode而定,参考课本中下面这一段。
When a trap occurs, the processor hardware does the following. If the processor was executing in user mode, it loads %esp and %ss from the task segment descriptor, pushes the old user %ss and %esp onto the new stack. If the processor was executingin kernel mode, none of the above happens.
extern变量:
在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。 1. extern修饰变量的声明。 举例来说,如果文件a.c需要引用b.c中变量int v,就可以在a.c中声明extern int v,然后就可以引用变量v。
trap gate = exception gate
#define GD_KT 0x08 // kernel text
#define GD_KD 0x10 // kernel data
#define GD_UT 0x18 // user text
#define GD_UD 0x20 // user data
#define GD_TSS0 0x28 // Task segment selector for CPU 0
这个链接解释了具体发生中断时DPL检查过程:
https://zhuanlan.zhihu.com/p/137859808
(1)门槛检查: 检查特权级别下限,即检查是否能够访问这个描述符,对于用户主动发生的中断(软中断、int3、into),需要满足CPL<=描述符DPL,其他的中断不需要检查门槛
**(2)门框检查:**检查特权级别上限, 即检查是否能够调用这个中断处理程序,对于所有的中断需要满足CPL>=目标代码段DPL,这个步骤的目的是检查特权级转换状况,如果执行了目标代码段的处理程序,CPL也会转变为目标代码段的值,这样就实现了特权级转换。(注意:目标代码段描述符不是中断描述符中段选择子的RPL,而是选择子索引得到的断描述符的DPL)
CPL>=目标代码段DPL的目的是保证中断是从低特权级向高特权级转变或者同级转变(比如内核态的中断触发),而不是向低特权级转变。
IDT和TSS合作从而提供保护机制:
总结下exercise 4 的内容就是
Questions
Answer the following questions in your answers-lab3.txt:
What is the purpose of having an individual handler function for each exception/interrupt? (i.e., if all exceptions/interrupts were delivered to the same handler, what feature that exists in the current implementation could not be provided?)
因为erro code不一样,trapno倒是可以统一的??。
Did you have to do anything to make the user/softint program behave correctly? The grade script expects it to produce a general protection fault (trap 13), but softint’s code says int $14. Why should this produce interrupt vector 13? What happens if the kernel actually allows softint’s int $14 instruction to invoke the kernel’s page fault handler (which is interrupt vector 14)?
这题参见上面一大段的中断发生过程的DPL检查机制就可以:
int $14是用户显式地调用中断,所以需要进行门槛检查,这里要求CPL(3)<=DPL(page fault的dpl是0,在我们写的程序里设置的),所以这里就不符合要求了,其实中断门/陷阱门描述符的dpl就是为了说明显式调用所需要的优先级。因此无法调用page fault handler,那就会触发general protection fault。