mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-12 10:06:47 +00:00
bugfix: 解决了ignore_int在运行时可能破坏进程执行上下文的问题。 (#61)
This commit is contained in:
parent
fbe1e23e97
commit
bf8f61b500
@ -344,7 +344,7 @@ void apic_local_apic_init()
|
||||
* @brief 初始化apic控制器
|
||||
*
|
||||
*/
|
||||
void apic_init()
|
||||
int apic_init()
|
||||
{
|
||||
// 初始化中断门, 中断使用rsp0防止在软中断时发生嵌套,然后处理器重新加载导致数据被抹掉
|
||||
for (int i = 32; i <= 55; ++i)
|
||||
@ -386,6 +386,7 @@ void apic_init()
|
||||
kwarn("Cannot get RCBA address. RCBA_phys=%#010lx", RCBA_phys);
|
||||
}
|
||||
sti();
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* @brief 中断服务程序
|
||||
|
@ -290,7 +290,7 @@ void apic_init_ap_core_local_apic();
|
||||
* @brief 初始化apic控制器
|
||||
*
|
||||
*/
|
||||
void apic_init();
|
||||
int apic_init();
|
||||
|
||||
/**
|
||||
* @brief 读取指定类型的 Interrupt Control Structure
|
||||
|
@ -351,4 +351,11 @@ ENTRY(syscall_int)
|
||||
xchgq %rax, (%rsp) // 把FUNC的地址换入栈中
|
||||
jmp Err_Code
|
||||
|
||||
// irq模块初始化后的ignore_int入点
|
||||
ENTRY(ignore_int)
|
||||
pushq $0
|
||||
pushq %rax
|
||||
leaq ignore_int_handler(%rip), %rax // 获取ignore处理程序的地址
|
||||
xchgq %rax, (%rsp) // 把FUNC的地址换入栈中
|
||||
jmp Err_Code
|
||||
|
||||
|
@ -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");
|
||||
}
|
@ -326,6 +326,7 @@ entry64:
|
||||
jnc start_smp
|
||||
|
||||
setup_IDT:
|
||||
// 该部分代码只在启动初期使用,后面的c文件中会重新设置IDT,
|
||||
leaq m_ignore_int(%rip), %rdx // 将ignore_int的地址暂时存到中段描述符的高8B
|
||||
movq $(0x08 << 16), %rax // 设置段选择子。由IDT结构和段选择子结构可知,本行设置段基地址为0x100000,TI=0,RPL=0
|
||||
movw %dx, %ax
|
||||
@ -460,6 +461,7 @@ go_to_smp_kernel:
|
||||
.quad smp_ap_start
|
||||
|
||||
// ==== 异常/中断处理模块 ignore int: 忽略中断
|
||||
// (该部分代码只在启动初期使用,后面的c文件中会重新设置IDT,从而重设ignore_int的中断入点)
|
||||
m_ignore_int:
|
||||
// 切换到c语言的ignore_int
|
||||
movq go_to_ignore_int(%rip), %rax
|
||||
@ -470,7 +472,7 @@ m_ignore_int:
|
||||
|
||||
|
||||
go_to_ignore_int:
|
||||
.quad ignore_int
|
||||
.quad ignore_int_handler
|
||||
|
||||
|
||||
ENTRY(head_stack_start)
|
||||
|
@ -209,10 +209,4 @@ void Start_Kernel(void)
|
||||
while (1)
|
||||
pause();
|
||||
}
|
||||
|
||||
void ignore_int()
|
||||
{
|
||||
kwarn("Unknown interrupt or fault at RIP.\n");
|
||||
sti();
|
||||
}
|
||||
#pragma GCC pop_options
|
Loading…
x
Reference in New Issue
Block a user