无法在我的 64 位、c 内核崩溃中处理中断 (IRQ)
Can't get Interrupts (IRQs) handled in my 64bit, c kernel crashes
标题说明了一切,我的图片遮罩有效。
如果我发送一个 IRQ (key-stroke),内核就会崩溃。
我正在使用 nasm。
我应该怎么做才能在发送中断时执行 exception_handler 函数?
idt.h
#pragma once
#include "../types.h"
#define IDT_MAX_DESCRIPTORS 256
#define GDT_OFFSET_KERNEL_CODE (0x01 * 0x08) //!!!! just to test
extern uint64_t isr_stub_table[];
typedef struct {
uint16_t isr_low; // The lower 16 bits of the ISR's address
uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR
uint8_t ist; // The IST in the TSS that the CPU will load into RSP; set to zero for now
uint8_t attributes; // Type and attributes; see the IDT page
uint16_t isr_mid; // The higher 16 bits of the lower 32 bits of the ISR's address
uint32_t isr_high; // The higher 32 bits of the ISR's address
uint32_t reserved; // Set to zero
} __attribute__((packed)) idt_desc_t;
typedef struct {
uint16_t limit;
uint64_t base;
} __attribute__((packed)) idtr_t;
static idtr_t idtr;
void idt_reload(idtr_t* idtr);
void idt_set_descriptor(uint8_t vector, uintptr_t isr, uint8_t flags, uint8_t ist);
void idt_init(void);
static bool vectors[IDT_MAX_DESCRIPTORS];
idt.c:
#include "idt.h"
#include "../types.h"
idt_desc_t idt[IDT_MAX_DESCRIPTORS]; // Create an array of IDT entries; aligned for performance
void idt_set_descriptor(uint8_t vector, uintptr_t isr, uint8_t flags, uint8_t ist) {
idt_desc_t* descriptor = &idt[vector];
descriptor->isr_low = isr & 0xFFFF;
descriptor->kernel_cs = GDT_OFFSET_KERNEL_CODE;
descriptor->ist = ist;
descriptor->attributes = flags;
descriptor->isr_mid = (isr >> 16) & 0xFFFF;
descriptor->isr_high = (isr >> 32) & 0xFFFFFFFF;
descriptor->reserved = 0;
}
void idt_init() {
idtr.base = (uintptr_t)&idt[0];
idtr.limit = (uint16_t)sizeof(idt_desc_t) * IDT_MAX_DESCRIPTORS - 1;
for (uint8_t vector = 0; vector < 32; vector++) {
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E, 1);
vectors[vector] = true;
}
__asm__ volatile("lidt %0" : : "memory"(idtr)); // load the new IDT
__asm__ volatile("sti"); // set the interrupt flag
}
void exception_handler() {
terminal_puts("Hello");
__asm__ volatile ("cli; hlt"); // Completely hangs the computer
}
如果我删除 __asm__ volatile("sti");
部分,它不会再崩溃,但仍然无法处理中断。
idt.asm:
extern exception_handler
%macro isr_err_stub 1
isr_stub_%+%1:
call exception_handler
iretq
%endmacro
%macro isr_no_err_stub 1
isr_stub_%+%1:
call exception_handler
iretq
%endmacro
isr_no_err_stub 0
isr_no_err_stub 1
isr_no_err_stub 2
isr_no_err_stub 3
isr_no_err_stub 4
isr_no_err_stub 5
isr_no_err_stub 6
isr_no_err_stub 7
isr_err_stub 8
isr_no_err_stub 9
isr_err_stub 10
isr_err_stub 11
isr_err_stub 12
isr_err_stub 13
isr_err_stub 14
isr_no_err_stub 15
isr_no_err_stub 16
isr_err_stub 17
isr_no_err_stub 18
isr_no_err_stub 19
isr_no_err_stub 20
isr_no_err_stub 21
isr_no_err_stub 22
isr_no_err_stub 23
isr_no_err_stub 24
isr_no_err_stub 25
isr_no_err_stub 26
isr_no_err_stub 27
isr_no_err_stub 28
isr_no_err_stub 29
isr_err_stub 30
isr_no_err_stub 31
global isr_stub_table
isr_stub_table:
%assign i 0
%rep 32
dq isr_stub_%+i
%assign i i+1
%endrep
我不知道要添加的详细信息,所以如果您需要,请询问更多。
我用过这个教程:https://wiki.osdev.org/Interrupts_tutorial
一切正常,但 gdt 未正确初始化
标题说明了一切,我的图片遮罩有效。 如果我发送一个 IRQ (key-stroke),内核就会崩溃。 我正在使用 nasm。 我应该怎么做才能在发送中断时执行 exception_handler 函数?
idt.h
#pragma once
#include "../types.h"
#define IDT_MAX_DESCRIPTORS 256
#define GDT_OFFSET_KERNEL_CODE (0x01 * 0x08) //!!!! just to test
extern uint64_t isr_stub_table[];
typedef struct {
uint16_t isr_low; // The lower 16 bits of the ISR's address
uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR
uint8_t ist; // The IST in the TSS that the CPU will load into RSP; set to zero for now
uint8_t attributes; // Type and attributes; see the IDT page
uint16_t isr_mid; // The higher 16 bits of the lower 32 bits of the ISR's address
uint32_t isr_high; // The higher 32 bits of the ISR's address
uint32_t reserved; // Set to zero
} __attribute__((packed)) idt_desc_t;
typedef struct {
uint16_t limit;
uint64_t base;
} __attribute__((packed)) idtr_t;
static idtr_t idtr;
void idt_reload(idtr_t* idtr);
void idt_set_descriptor(uint8_t vector, uintptr_t isr, uint8_t flags, uint8_t ist);
void idt_init(void);
static bool vectors[IDT_MAX_DESCRIPTORS];
idt.c:
#include "idt.h"
#include "../types.h"
idt_desc_t idt[IDT_MAX_DESCRIPTORS]; // Create an array of IDT entries; aligned for performance
void idt_set_descriptor(uint8_t vector, uintptr_t isr, uint8_t flags, uint8_t ist) {
idt_desc_t* descriptor = &idt[vector];
descriptor->isr_low = isr & 0xFFFF;
descriptor->kernel_cs = GDT_OFFSET_KERNEL_CODE;
descriptor->ist = ist;
descriptor->attributes = flags;
descriptor->isr_mid = (isr >> 16) & 0xFFFF;
descriptor->isr_high = (isr >> 32) & 0xFFFFFFFF;
descriptor->reserved = 0;
}
void idt_init() {
idtr.base = (uintptr_t)&idt[0];
idtr.limit = (uint16_t)sizeof(idt_desc_t) * IDT_MAX_DESCRIPTORS - 1;
for (uint8_t vector = 0; vector < 32; vector++) {
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E, 1);
vectors[vector] = true;
}
__asm__ volatile("lidt %0" : : "memory"(idtr)); // load the new IDT
__asm__ volatile("sti"); // set the interrupt flag
}
void exception_handler() {
terminal_puts("Hello");
__asm__ volatile ("cli; hlt"); // Completely hangs the computer
}
如果我删除 __asm__ volatile("sti");
部分,它不会再崩溃,但仍然无法处理中断。
idt.asm:
extern exception_handler
%macro isr_err_stub 1
isr_stub_%+%1:
call exception_handler
iretq
%endmacro
%macro isr_no_err_stub 1
isr_stub_%+%1:
call exception_handler
iretq
%endmacro
isr_no_err_stub 0
isr_no_err_stub 1
isr_no_err_stub 2
isr_no_err_stub 3
isr_no_err_stub 4
isr_no_err_stub 5
isr_no_err_stub 6
isr_no_err_stub 7
isr_err_stub 8
isr_no_err_stub 9
isr_err_stub 10
isr_err_stub 11
isr_err_stub 12
isr_err_stub 13
isr_err_stub 14
isr_no_err_stub 15
isr_no_err_stub 16
isr_err_stub 17
isr_no_err_stub 18
isr_no_err_stub 19
isr_no_err_stub 20
isr_no_err_stub 21
isr_no_err_stub 22
isr_no_err_stub 23
isr_no_err_stub 24
isr_no_err_stub 25
isr_no_err_stub 26
isr_no_err_stub 27
isr_no_err_stub 28
isr_no_err_stub 29
isr_err_stub 30
isr_no_err_stub 31
global isr_stub_table
isr_stub_table:
%assign i 0
%rep 32
dq isr_stub_%+i
%assign i i+1
%endrep
我不知道要添加的详细信息,所以如果您需要,请询问更多。 我用过这个教程:https://wiki.osdev.org/Interrupts_tutorial
一切正常,但 gdt 未正确初始化