我正在写一个操作系统。我想使用__attribute__((interrupt))
来做一些中断支持(我从PonchoOS复制了一堆代码来开始)。但是,只有页面故障检测和双重故障检测是有效的,其他中断不起作用(如键盘和定时器)。
这是标题:
#ifndef _KERNEL_INTERRUPTS_H_
#define _KERNEL_INTERRUPTS_H_
#include <stdint.h>
#define GP_FAULT 0xD
#define PAGE_FAULT 0xE
#define TIME_INTR 0x20
#define KERYBOARD_INTR 0x21
#define MOUSE_INTR 0x2C
#define PI_INTR 0x20
#define SOFT_INTR 0x80
#define DOUBLE_PAGE_FAULT 0x08
#define IDT_InterruptGate 0x8e
#define IDT_CallGate 0x8c
#define IDT_TrapGate 0x8f
#define PIC1_COMMAND 0x20
#define PIC1_DATA 0x21
#define PIC2_COMMAND 0xA0
#define PIC2_DATA 0xA1
#define PIC_EOI 0x20
#define ICW1_INIT 0x10
#define ICW1_ICW4 0x01
#define ICW4_8086 0x01
typedef struct _idtr {
uint16_t limit;
uint64_t offset;
} __attribute__((packed)) IDTR;
typedef struct _idt {
uint16_t offset0;
uint16_t selector;
uint8_t zero;
uint8_t type;
uint16_t offset1;
uint32_t offset2;
uint32_t reserved;
} __attribute__((packed)) IDT;
void setIDTOffset(IDT* _idt, uint64_t offset);
uint64_t getIDTOffset(IDT* _idt);
void initializeInterrupts(void);
void setIRQ(uint8_t iqrn, void* handler, uint8_t typeAttributes, uint8_t selector);
void initializePIC(void);
void picEnd(void);
struct InterruptFrame;
__attribute__((interrupt)) void pageFaultHandler(struct InterruptFrame* Frame);
__attribute__((interrupt)) void timerHandler(struct InterruptFrame* Frame);
__attribute__((interrupt)) void doubleFaultHandler(struct InterruptFrame* Frame);
__attribute__((interrupt)) void gpFaultHandler(struct InterruptFrame* Frame);
__attribute__((interrupt)) void keyboardIntHandler(struct InterruptFrame* Frame);
__attribute__((interrupt)) void mouseIntHandler(struct InterruptFrame* Frame);
__attribute__((interrupt)) void pitIntHandler(struct InterruptFrame* Frame);
#endif /* _KERNEL_INTERRUPTS_H_ */
这是实现:
#include <interrupts.h>
#include <graphics.h>
#include <io.h>
IDT idt[256];
IDTR idtr;
void setIDTOffset(IDT* _idt, uint64_t offset) {
_idt->offset0 = (uint16_t)(offset & 0xffff);
_idt->offset1 = (uint16_t)((offset & 0xffff0000) >> 16);
_idt->offset2 = (uint32_t)((offset & 0xffffffff00000000) >> 32);
}
uint64_t getIDTOffset(IDT* _idt) {
uint64_t offset = 0;
offset |= (uint64_t)_idt->offset0;
offset |= (uint64_t)_idt->offset1 << 16;
offset |= (uint64_t)_idt->offset2 << 32;
return offset;
}
void initializeInterrupts(void) {
idtr.limit = sizeof(IDT) * 256 - 1;
idtr.offset = (uint64_t)idt;
asm volatile("cli");
setIRQ(PAGE_FAULT, (void*)pageFaultHandler, IDT_InterruptGate, 0x8);
setIRQ(TIME_INTR, (void*)timerHandler, IDT_InterruptGate, 0x8);
setIRQ(KERYBOARD_INTR, (void*)keyboardIntHandler, IDT_InterruptGate, 0x8);
setIRQ(DOUBLE_PAGE_FAULT, (void*)doubleFaultHandler, IDT_InterruptGate, 0x8);
setIRQ(GP_FAULT, (void*)gpFaultHandler, IDT_InterruptGate, 0x8);
setIRQ(MOUSE_INTR, (void*)mouseIntHandler, IDT_InterruptGate, 0x8);
setIRQ(PI_INTR, (void*)pitIntHandler, IDT_InterruptGate, 0x8);
asm ("lidt %0" : : "m" (idtr));
asm volatile("sti");
initializePIC();
}
void setIRQ(uint8_t iqrn, void* handler, uint8_t typeAttributes, uint8_t selector) {
setIDTOffset(&idt[iqrn], (uint64_t)handler);
idt[iqrn].type = typeAttributes;
idt[iqrn].selector = selector;
idt[iqrn].zero = 0;
idt[iqrn].reserved = 0;
}
void initializePIC(void) {
uint8_t a1, a2;
a1 = inb(PIC1_DATA);
ioWait();
a2 = inb(PIC2_DATA);
ioWait();
outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
ioWait();
outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
ioWait;
outb(PIC1_DATA, 0x20);
ioWait();
outb(PIC2_DATA, 0x28);
ioWait();
outb(PIC1_DATA, 4);
ioWait();
outb(PIC2_DATA, 2);
ioWait();
outb(PIC1_DATA, ICW4_8086);
ioWait();
outb(PIC2_DATA, ICW4_8086);
ioWait();
outb(PIC1_DATA, a1);
ioWait();
outb(PIC2_DATA, a2);
}
void picEnd(void){
outb(PIC2_COMMAND, PIC_EOI);
outb(PIC1_COMMAND, PIC_EOI);
}
__attribute__((interrupt)) void pageFaultHandler(struct InterruptFrame* Frame) {
clear();
debugPrint("Page Fault Detected");
while(1);
}
__attribute__((interrupt)) void timerHandler(struct InterruptFrame* Frame) {
debugPrint("timer\n");
picEnd();
}
__attribute__((interrupt)) void doubleFaultHandler(struct InterruptFrame* Frame) {
clear();
debugPrint("Double Fault Detected");
while(1);
}
__attribute__((interrupt)) void gpFaultHandler(struct InterruptFrame* Frame) {
clear();
debugPrint("General Protection Fault Detected");
while(1);
}
__attribute__((interrupt)) void keyboardIntHandler(struct InterruptFrame* Frame) {
clear();
debugPrint("Pressed");
uint8_t scanCode = inb(0x60);
picEnd();
}
__attribute__((interrupt)) void mouseIntHandler(struct InterruptFrame* Frame) {
}
__attribute__((interrupt)) void pitIntHandler(struct InterruptFrame* Frame) {
}
这是我的github。
我使用“asm(“int $0x21“)”手动触发键盘中断。数据可以通过端口0x 60读取。
我正在使用x86_64-elf-gcc来构建内核,使用QEMU来运行内核。如何解决这个问题?有什么建议吗?
1条答案
按热度按时间gab6jxml1#
谢谢你的回复。只要打开所有的中断。