|
@@ -2,47 +2,47 @@
|
|
|
#include "irq.h"
|
|
|
#include <common/errno.h>
|
|
|
|
|
|
-
|
|
|
#if _INTR_8259A_
|
|
|
#include <driver/interrupt/8259A/8259A.h>
|
|
|
#else
|
|
|
#include <driver/interrupt/apic/apic.h>
|
|
|
#endif
|
|
|
|
|
|
+#include "gate.h"
|
|
|
#include <common/asm.h>
|
|
|
#include <common/printk.h>
|
|
|
#include <common/string.h>
|
|
|
-#include "gate.h"
|
|
|
#include <mm/slab.h>
|
|
|
+extern void ignore_int();
|
|
|
|
|
|
#pragma GCC push_options
|
|
|
#pragma GCC optimize("O0")
|
|
|
// 保存函数调用现场的寄存器
|
|
|
-#define SAVE_ALL_REGS \
|
|
|
- "cld; \n\t" \
|
|
|
- "pushq %rax; \n\t" \
|
|
|
- "pushq %rax; \n\t" \
|
|
|
- "movq %es, %rax; \n\t" \
|
|
|
- "pushq %rax; \n\t" \
|
|
|
- "movq %ds, %rax; \n\t" \
|
|
|
- "pushq %rax; \n\t" \
|
|
|
- "xorq %rax, %rax;\n\t" \
|
|
|
- "pushq %rbp; \n\t" \
|
|
|
- "pushq %rdi; \n\t" \
|
|
|
- "pushq %rsi; \n\t" \
|
|
|
- "pushq %rdx; \n\t" \
|
|
|
- "pushq %rcx; \n\t" \
|
|
|
- "pushq %rbx; \n\t" \
|
|
|
- "pushq %r8 ; \n\t" \
|
|
|
- "pushq %r9 ; \n\t" \
|
|
|
- "pushq %r10; \n\t" \
|
|
|
- "pushq %r11; \n\t" \
|
|
|
- "pushq %r12; \n\t" \
|
|
|
- "pushq %r13; \n\t" \
|
|
|
- "pushq %r14; \n\t" \
|
|
|
- "pushq %r15; \n\t" \
|
|
|
- "movq $0x10, %rdx;\n\t" \
|
|
|
- "movq %rdx, %ds; \n\t" \
|
|
|
+#define SAVE_ALL_REGS \
|
|
|
+ "cld; \n\t" \
|
|
|
+ "pushq %rax; \n\t" \
|
|
|
+ "pushq %rax; \n\t" \
|
|
|
+ "movq %es, %rax; \n\t" \
|
|
|
+ "pushq %rax; \n\t" \
|
|
|
+ "movq %ds, %rax; \n\t" \
|
|
|
+ "pushq %rax; \n\t" \
|
|
|
+ "xorq %rax, %rax;\n\t" \
|
|
|
+ "pushq %rbp; \n\t" \
|
|
|
+ "pushq %rdi; \n\t" \
|
|
|
+ "pushq %rsi; \n\t" \
|
|
|
+ "pushq %rdx; \n\t" \
|
|
|
+ "pushq %rcx; \n\t" \
|
|
|
+ "pushq %rbx; \n\t" \
|
|
|
+ "pushq %r8 ; \n\t" \
|
|
|
+ "pushq %r9 ; \n\t" \
|
|
|
+ "pushq %r10; \n\t" \
|
|
|
+ "pushq %r11; \n\t" \
|
|
|
+ "pushq %r12; \n\t" \
|
|
|
+ "pushq %r13; \n\t" \
|
|
|
+ "pushq %r14; \n\t" \
|
|
|
+ "pushq %r15; \n\t" \
|
|
|
+ "movq $0x10, %rdx;\n\t" \
|
|
|
+ "movq %rdx, %ds; \n\t" \
|
|
|
"movq %rdx, %es; \n\t"
|
|
|
|
|
|
// 定义IRQ处理函数的名字格式:IRQ+中断号+interrupt
|
|
@@ -52,14 +52,13 @@
|
|
|
// 构造中断entry
|
|
|
// 为了复用返回函数的代码,需要压入一个错误码0
|
|
|
// todo: 将这里改为volatile,也许能解决编译选项为O1时,系统崩溃的问题
|
|
|
-#define Build_IRQ(number) \
|
|
|
- void IRQ_NAME(number); \
|
|
|
- __asm__(SYMBOL_NAME_STR(IRQ) #number "interrupt: \n\t" \
|
|
|
- "pushq $0x00 \n\t" SAVE_ALL_REGS \
|
|
|
- "movq %rsp, %rdi \n\t" \
|
|
|
- "leaq ret_from_intr(%rip), %rax \n\t" \
|
|
|
- "pushq %rax \n\t" \
|
|
|
- "movq $" #number ", %rsi \n\t" \
|
|
|
+#define Build_IRQ(number) \
|
|
|
+ void IRQ_NAME(number); \
|
|
|
+ __asm__(SYMBOL_NAME_STR(IRQ) #number "interrupt: \n\t" \
|
|
|
+ "pushq $0x00 \n\t" SAVE_ALL_REGS "movq %rsp, %rdi \n\t" \
|
|
|
+ "leaq ret_from_intr(%rip), %rax \n\t" \
|
|
|
+ "pushq %rax \n\t" \
|
|
|
+ "movq $" #number ", %rsi \n\t" \
|
|
|
"jmp do_IRQ \n\t");
|
|
|
|
|
|
// 构造中断入口
|
|
@@ -89,32 +88,11 @@ Build_IRQ(0x36);
|
|
|
Build_IRQ(0x37);
|
|
|
|
|
|
// 初始化中断数组
|
|
|
-void (*interrupt_table[24])(void) =
|
|
|
- {
|
|
|
- IRQ0x20interrupt,
|
|
|
- IRQ0x21interrupt,
|
|
|
- IRQ0x22interrupt,
|
|
|
- IRQ0x23interrupt,
|
|
|
- IRQ0x24interrupt,
|
|
|
- IRQ0x25interrupt,
|
|
|
- IRQ0x26interrupt,
|
|
|
- IRQ0x27interrupt,
|
|
|
- IRQ0x28interrupt,
|
|
|
- IRQ0x29interrupt,
|
|
|
- IRQ0x2ainterrupt,
|
|
|
- IRQ0x2binterrupt,
|
|
|
- IRQ0x2cinterrupt,
|
|
|
- IRQ0x2dinterrupt,
|
|
|
- IRQ0x2einterrupt,
|
|
|
- IRQ0x2finterrupt,
|
|
|
- IRQ0x30interrupt,
|
|
|
- IRQ0x31interrupt,
|
|
|
- IRQ0x32interrupt,
|
|
|
- IRQ0x33interrupt,
|
|
|
- IRQ0x34interrupt,
|
|
|
- IRQ0x35interrupt,
|
|
|
- IRQ0x36interrupt,
|
|
|
- IRQ0x37interrupt,
|
|
|
+void (*interrupt_table[24])(void) = {
|
|
|
+ IRQ0x20interrupt, IRQ0x21interrupt, IRQ0x22interrupt, IRQ0x23interrupt, IRQ0x24interrupt, IRQ0x25interrupt,
|
|
|
+ IRQ0x26interrupt, IRQ0x27interrupt, IRQ0x28interrupt, IRQ0x29interrupt, IRQ0x2ainterrupt, IRQ0x2binterrupt,
|
|
|
+ IRQ0x2cinterrupt, IRQ0x2dinterrupt, IRQ0x2einterrupt, IRQ0x2finterrupt, IRQ0x30interrupt, IRQ0x31interrupt,
|
|
|
+ IRQ0x32interrupt, IRQ0x33interrupt, IRQ0x34interrupt, IRQ0x35interrupt, IRQ0x36interrupt, IRQ0x37interrupt,
|
|
|
};
|
|
|
|
|
|
/**
|
|
@@ -139,18 +117,9 @@ Build_IRQ(0x80); // 系统调用入口
|
|
|
void (*syscall_intr_table[1])(void) = {IRQ0x80interrupt};
|
|
|
|
|
|
// 初始化IPI中断服务程序数组
|
|
|
-void (*SMP_interrupt_table[SMP_IRQ_NUM])(void) =
|
|
|
- {
|
|
|
- IRQ0xc8interrupt,
|
|
|
- IRQ0xc9interrupt,
|
|
|
- IRQ0xcainterrupt,
|
|
|
- IRQ0xcbinterrupt,
|
|
|
- IRQ0xccinterrupt,
|
|
|
- IRQ0xcdinterrupt,
|
|
|
- IRQ0xceinterrupt,
|
|
|
- IRQ0xcfinterrupt,
|
|
|
- IRQ0xd0interrupt,
|
|
|
- IRQ0xd1interrupt,
|
|
|
+void (*SMP_interrupt_table[SMP_IRQ_NUM])(void) = {
|
|
|
+ IRQ0xc8interrupt, IRQ0xc9interrupt, IRQ0xcainterrupt, IRQ0xcbinterrupt, IRQ0xccinterrupt,
|
|
|
+ IRQ0xcdinterrupt, IRQ0xceinterrupt, IRQ0xcfinterrupt, IRQ0xd0interrupt, IRQ0xd1interrupt,
|
|
|
};
|
|
|
|
|
|
// 初始化local apic中断服务程序数组
|
|
@@ -164,18 +133,9 @@ Build_IRQ(0x9c);
|
|
|
Build_IRQ(0x9d);
|
|
|
Build_IRQ(0x9e);
|
|
|
Build_IRQ(0x9f);
|
|
|
-void (*local_apic_interrupt_table[LOCAL_APIC_IRQ_NUM])(void) =
|
|
|
- {
|
|
|
- IRQ0x96interrupt,
|
|
|
- IRQ0x97interrupt,
|
|
|
- IRQ0x98interrupt,
|
|
|
- IRQ0x99interrupt,
|
|
|
- IRQ0x9ainterrupt,
|
|
|
- IRQ0x9binterrupt,
|
|
|
- IRQ0x9cinterrupt,
|
|
|
- IRQ0x9dinterrupt,
|
|
|
- IRQ0x9einterrupt,
|
|
|
- IRQ0x9finterrupt,
|
|
|
+void (*local_apic_interrupt_table[LOCAL_APIC_IRQ_NUM])(void) = {
|
|
|
+ IRQ0x96interrupt, IRQ0x97interrupt, IRQ0x98interrupt, IRQ0x99interrupt, IRQ0x9ainterrupt,
|
|
|
+ IRQ0x9binterrupt, IRQ0x9cinterrupt, IRQ0x9dinterrupt, IRQ0x9einterrupt, IRQ0x9finterrupt,
|
|
|
};
|
|
|
|
|
|
/**
|
|
@@ -189,7 +149,8 @@ void (*local_apic_interrupt_table[LOCAL_APIC_IRQ_NUM])(void) =
|
|
|
* @param irq_name 中断名
|
|
|
* @return int
|
|
|
*/
|
|
|
-int irq_register(ul irq_num, void *arg, void (*handler)(ul irq_num, ul parameter, struct pt_regs *regs), ul paramater, hardware_intr_controller *controller, char *irq_name)
|
|
|
+int irq_register(ul irq_num, void *arg, void (*handler)(ul irq_num, ul parameter, struct pt_regs *regs), ul paramater,
|
|
|
+ hardware_intr_controller *controller, char *irq_name)
|
|
|
{
|
|
|
// 由于为I/O APIC分配的中断向量号是从32开始的,因此要减去32才是对应的interrupt_desc的元素
|
|
|
irq_desc_t *p = NULL;
|
|
@@ -252,6 +213,10 @@ int irq_unregister(ul irq_num)
|
|
|
*/
|
|
|
void irq_init()
|
|
|
{
|
|
|
+ // 将idt重置为新的ignore_int入点(此前在head.S中有设置,
|
|
|
+ // 但是那个不完整,某些版本的编译器的输出,在真机运行时会破坏进程执行环境,从而导致#GP
|
|
|
+ for (int i = 0; i < 256; ++i)
|
|
|
+ set_intr_gate(i, 0, ignore_int);
|
|
|
#if _INTR_8259A_
|
|
|
init_8259A();
|
|
|
#else
|
|
@@ -261,4 +226,15 @@ void irq_init()
|
|
|
|
|
|
#endif
|
|
|
}
|
|
|
-#pragma GCC optimize("O0")
|
|
|
+#pragma GCC optimize("O0")
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 当系统收到未知的中断时,执行此处理函数
|
|
|
+ *
|
|
|
+ * @param regs
|
|
|
+ * @param error_code
|
|
|
+ */
|
|
|
+void ignore_int_handler(struct pt_regs *regs, unsigned long error_code)
|
|
|
+{
|
|
|
+ kwarn("Unknown interrupt or fault at RIP.\n");
|
|
|
+}
|