使能中断后的一般保护故障。 OSDEV

时间:2021-04-14 21:15:26

标签: c x86-64 interrupt osdev general-protection-fault

我正在尝试开发自己的操作系统。我已经为 32 位编写了一些代码,直到我突然决定要使用 64 位时才进行分页。我启用了长模式,设置基本分页,启动内核,内核设置更好的分页(前 4 MiB 分页以及帧缓冲区的开始)。现在我想启用中断,我将我的 32 位 idt 代码重组为 64 位并尝试启用它,它确实奇迹般地工作。我启用它的那一刻,我收到了一般保护错误。这里有一些需要考虑的事情,我似乎已经准备好了所有 irq 和 isr 的处理程序,我知道这是因为当一般保护故障发生时,它会在屏幕上打印出来。我几乎可以肯定它是由计时器引起的,但我无法确认,因为我的计时器中断处理程序也存在。不,我没有忘记 iretq :D。这是我的 idt.c 并且喜欢它整个 github 存储库。


#include "IDT.h"

#define PUSHALL \
     ".intel_syntax noprefix\n\t" \
    "push    r15\n\t"\
    "push    r14\n\t"\
    "push    r13\n\t"\
    "push    r12\n\t"\
    "push    r11\n\t"\
    "push    r10\n\t"\
    "push    r9\n\t"\
    "push    r8\n\t"\
    "push    rax\n\t"\
    "push    rcx\n\t"\
    "push    rdx\n\t"\
    "push    rbx\n\t"\
    "push    rsp\n\t"\
    "push    rbp\n\t"\
    "push    rsi\n\t"\
    "push    rdi\n\t"\
     ".att_syntax\n\t" \

#define POPALL\
    ".intel_syntax noprefix\n\t" \
    "pop     rdi\n\t"\
    "pop     rsi\n\t"\
    "pop     rbp\n\t"\
    "add     rsp, 10\n\t"\
    "pop     rbx\n\t"\
    "pop     rdx\n\t"\
    "pop     rcx\n\t"\
    "pop     rax\n\t"\
    "pop     r8\n\t"\
    "pop     r9\n\t"\
    "pop     r10\n\t"\
    "pop     r11\n\t"\
    "pop     r12\n\t"\
    "pop     r13\n\t"\
    "pop     r14\n\t"\
    "pop     r15\n\t"\
    "add     rsp, 0x10\n\t"\
    ".att_syntax\n\t" \
    

/* Common body for interrupt handler */
#define MAKE_INTERRUPT_COMMON_STUB(intno, intfunc) \
            "push $"#intno"\n\t" \
            PUSHALL  \
            "cld\n\t" \
            "push %rsp\n\t" \
            "call " #intfunc "\n\t" \
            POPALL \
            "add $10, %rsp\n\t"       /* Skip int_num and err_code */ \
            "iretq \n\t" \
            "#.popsection\n\t"

/* Make interrupt for exception without error code. Push a dummy value for the
 * error code in it place. Push all the segment registers and the segment registers
 * so that they are available to interrupt function (intfun). Pushes a unique
 * interrupt number (intno) after the error code so that a handler can be multiplexed
 * if needed. Restore all the registers upon exit.
 *
 * intentry: Is the interrupt entry point that can be used in an Interrupt
 *           Descriptor Table (IDT) entry.
 * intfunc:  Is the C interrupt function that the stub calls to do processing
 * intno:    Interrupt number. Can be used to multiplex multiple interrupts to one
 *           intfunc handler.
 */
#define MAKE_INTERRUPT(intentry, intfunc, intno) \
    extern void intentry (void); \
    __asm__("#.pushsection .text\n\t" \
            ".global " #intentry "\n\t" \
            ".align 16\n\t" \
            #intentry ":\n\t" \
            "push $0\n\t"            /* Push dummy error code */ \
            MAKE_INTERRUPT_COMMON_STUB(intno, intfunc));

/* Make interrupt for exception with error code. Processor pushes the error code
 * after the return address automatically. Push all the segment registers and the
 * segment registers so that they are available to interrupt function (intfun).
 * Pushes a unique interrupt number (intno) after the error code so that a handler
 * can be multiplexed if needed. Restore all the registers upon exit.
 *
 * intentry: Is the interrupt entry point that can be used in an Interrupt
 *           Descriptor Table (IDT) entry.
 * intfunc:  Is the C interrupt function that the stub calls to do processing
 * intno:    Interrupt number. Can be used to multiplex multiple interrupts to one
 *           intfunc handler.
*/
#define MAKE_INTERRUPT_ERRCODE(intentry, intfunc, intno) \
    extern void intentry (void); \
    __asm__("#.pushsection .text\n\t" \
            ".global " #intentry "\n" \
            ".align 16\n\t" \
            #intentry ":\n\t" \
            MAKE_INTERRUPT_COMMON_STUB(intno, intfunc));

MAKE_INTERRUPT        (isr0,  isr0_handler,  0x00)
MAKE_INTERRUPT        (isr1,  isr1_handler,  0x01)
MAKE_INTERRUPT        (isr2,  isr2_handler,  0x02)
MAKE_INTERRUPT        (isr3,  isr3_handler,  0x03)
MAKE_INTERRUPT        (isr4,  isr4_handler,  0x04)
MAKE_INTERRUPT        (isr5,  isr5_handler,  0x05)
MAKE_INTERRUPT        (isr6,  isr6_handler,  0x06)
MAKE_INTERRUPT        (isr7,  isr7_handler,  0x07)
MAKE_INTERRUPT_ERRCODE(isr8,  isr8_handler,  0x08)
MAKE_INTERRUPT        (isr9,  isr9_handler,  0x09)
MAKE_INTERRUPT_ERRCODE(isr10, isr10_handler, 0x0a)
MAKE_INTERRUPT_ERRCODE(isr11, isr11_handler, 0x0b)
MAKE_INTERRUPT_ERRCODE(isr12, isr12_handler, 0x0c)
MAKE_INTERRUPT_ERRCODE(isr13, isr13_handler, 0x0d)
MAKE_INTERRUPT_ERRCODE(isr14, isr14_handler, 0x0e)
/* Reserved 0x0f */
MAKE_INTERRUPT        (isr16, isr0_handler,  0x10)
MAKE_INTERRUPT_ERRCODE(isr17, isr0_handler,  0x11)
MAKE_INTERRUPT        (isr18, isr0_handler,  0x12)
MAKE_INTERRUPT        (isr19, isr0_handler,  0x13)
MAKE_INTERRUPT        (isr20, isr0_handler,  0x14)
/* Reserved 0x15 to 0x1d */
MAKE_INTERRUPT_ERRCODE(isr30, isr0_handler,  0x1e)
/* Reserved 0x1f */

/* IRQ handlers */
MAKE_INTERRUPT        (irq0,  irq0_handler,  0x00)
MAKE_INTERRUPT        (irq1,  irq1_handler,  0x01)
MAKE_INTERRUPT        (irq2,  irq2_handler,  0x02)
MAKE_INTERRUPT        (irq3,  irq3_handler,  0x03)
MAKE_INTERRUPT        (irq4,  irq4_handler,  0x04)
MAKE_INTERRUPT        (irq5,  irq5_handler,  0x05)
MAKE_INTERRUPT        (irq6,  irq6_handler,  0x06)
MAKE_INTERRUPT        (irq7,  irq7_handler,  0x07)
MAKE_INTERRUPT        (irq8,  irq8_handler,  0x08)
MAKE_INTERRUPT        (irq9,  irq9_handler,  0x09)
MAKE_INTERRUPT        (irq10, irq10_handler,  0x0A)
MAKE_INTERRUPT        (irq11, irq11_handler,  0x0B)
MAKE_INTERRUPT        (irq12, irq12_handler,  0x0C)
MAKE_INTERRUPT        (irq13, irq13_handler,  0x0D)
MAKE_INTERRUPT        (irq14, irq14_handler,  0x0E)
MAKE_INTERRUPT        (irq15, irq15_handler,  0x0F)

void init_idt_entry(int num, unsigned int offset, unsigned short select, 
    unsigned short flags)
    {
        
        _idt_entries[num].offset0 = (unsigned short)(offset & 0x000000000000FFFF);
        _idt_entries[num].offset1 = (unsigned short)((offset & 0x00000000FFFF0000) >> 16);
        _idt_entries[num].offset2 = (unsigned int)((offset & 0xFFFFFFFF00000000) >> 32);

        _idt_entries[num].selector = select;
        _idt_entries[num].flags = flags;
         return;
    }




///////////////////////////////////////
void idt_flush(struct idt *idtr)
{
    asm volatile("lidt %0" :: "m"(*idtr));
}

void init_pic()
{

    outb(0x20,0x11);
    outb(0xA0,0x11);

    outb(0x21, 0x20);
    outb(0xA1, 40);

    outb(0x21, 0x04);
    outb(0xA1, 0x02);

    outb(0x21, 0x01);
    outb(0xA1, 0x01);

    outb(0x21, 0x0);
    outb(0xA1, 0x0);

    
}


void init_idt()
{
    init_pic();
    
    _idt_entries = RequestPage();
    Tidt.limit = 16 * 256;
    Tidt.base  = _idt_entries;
    
    memset(_idt_entries, 0, 16*256);
    
    
    
    for(int i = 0; i < 256 ; i++){
        init_idt_entry(i,(int)&isr0,0x08, 0x8E); 
    }
    init_idt_entry(0,(int)&isr0,0x08, 0x8E);
    init_idt_entry(1,(int)&isr1,0x08, 0x8E);
    init_idt_entry(2,(int)&isr2,0x08, 0x8E);
    init_idt_entry(3,(int)&isr3,0x08, 0x8E);
    init_idt_entry(4,(int)&isr4,0x08, 0x8E);
    init_idt_entry(5,(int)&isr5,0x08, 0x8E);
    init_idt_entry(6,(int)&isr6,0x08, 0x8E);
    init_idt_entry(7,(int)&isr7,0x08, 0x8E);
    init_idt_entry(8,(int)&isr8,0x08, 0x8E);
    init_idt_entry(9,(int)&isr9,0x08, 0x8E);
    init_idt_entry(10,(int)&isr10,0x08, 0x8E);
    init_idt_entry(11,(int)&isr11,0x08, 0x8E);
    init_idt_entry(12,(int)&isr12,0x08, 0x8E);
    init_idt_entry(13,(int)&isr13,0x08, 0x8E);
    init_idt_entry(14,(int)&isr14,0x08, 0x8E);
    /* ISR15 is reserved */
    init_idt_entry(16,(int)&isr16,0x08, 0x8E);
    init_idt_entry(17,(int)&isr17,0x08, 0x8E);
    init_idt_entry(18,(int)&isr18,0x08, 0x8E);
    init_idt_entry(19,(int)&isr19,0x08, 0x8E);
    init_idt_entry(20,(int)&isr20,0x08, 0x8E);
    /* ISR21 to ISR2F are reserved */
    init_idt_entry(30,(int)&isr30,0x08, 0x8E);

    /* IRQ handlers */
    init_idt_entry(32,(int)&irq0,0x08, 0x8E);
    init_idt_entry(33,(int)&irq1,0x08, 0x8E);
    init_idt_entry(34,(int)&irq2,0x08, 0x8E);
    init_idt_entry(35,(int)&irq3,0x08, 0x8E);
    init_idt_entry(36,(int)&irq4,0x08, 0x8E);
    init_idt_entry(37,(int)&irq5,0x08, 0x8E);
    init_idt_entry(38,(int)&irq6,0x08, 0x8E);
    init_idt_entry(39,(int)&irq7,0x08, 0x8E);
    init_idt_entry(40,(int)&irq8,0x08, 0x8E);
    init_idt_entry(41,(int)&irq9,0x08, 0x8E);
    init_idt_entry(42,(int)&irq10,0x08, 0x8E);
    init_idt_entry(43,(int)&irq11,0x08, 0x8E);
    init_idt_entry(44,(int)&irq12,0x08, 0x8E);
    init_idt_entry(45,(int)&irq13,0x08, 0x8E);
    init_idt_entry(46,(int)&irq14,0x08, 0x8E);
    init_idt_entry(47,(int)&irq15,0x08, 0x8E);
    
    
    idt_flush(&Tidt);
    
    asm volatile("sti;");
    
    
}

这是我的 isr.c 和 irq.c

情监侦:

#include "isr.h"

void isr0_handler(interrupt_frame_t *frame)
{
    panic("Divide by zero");
    while(1);
    //fillRect(0, 0, 1080, 1920, 0xff0000);
}
void isr1_handler(interrupt_frame_t *frame)
{
    panic("Debug");
    while(1);
    //fillRect(0, 0, 1080, 1920, 0xff0000);
}
void isr2_handler(interrupt_frame_t *frame)
{
    panic("NMI");
    while(1);
    //fillRect(0, 0, 1080, 1920, 0xff0000);
}
void isr3_handler(interrupt_frame_t *frame)
{
    panic("Breakpoint");
    while(1);
    //fillRect(0, 0, 1080, 1920, 0xff0000);
}
void isr4_handler(interrupt_frame_t *frame)
{
    panic("Overflow");
    while(1);
   //fillRect(0, 0, 1080, 1920, 0xff0000);
}
void isr5_handler(interrupt_frame_t *frame)
{
    panic("Bound range exceeded");
    while(1);
   //fillRect(0, 0, 1080, 1920, 0xff0000);
}
void isr6_handler(interrupt_frame_t *frame)
{
    panic("Invalid Opcode");
    while(1);
    //fillRect(0, 0, 1080, 1920, 0xff0000);
}
void isr7_handler(interrupt_frame_t *frame)
{
    panic("Device Not Available");
    while(1);
   //fillRect(0, 0, 1080, 1920, 0xff0000);
}
void isr8_handler(interrupt_frame_t *frame)
{
    panic("Double Fault");
    while(1);
    //fillRect(0, 0, 1080, 1920, 0xff0000);
}
void isr9_handler(interrupt_frame_t *frame)
{
    panic("COPRO SEGMENT OVERRUN");
    
    while(1);
   //fillRect(0, 0, 1080, 1920, 0xff0000);
}
void isr10_handler(interrupt_frame_t *frame)
{
    panic("Invalid TSS");
    
    while(1);
   //fillRect(0, 0, 1080, 1920, 0xff0000);
}
void isr11_handler(interrupt_frame_t *frame)
{
    panic("Segment Not present");
    
    while(1);
    //fillRect(0, 0, 1080, 1920, 0xff0000);
}
void isr12_handler(interrupt_frame_t *frame)
{
    panic("Stack Segment Fault");
    
    while(1);
    //fillRect(0, 0, 1080, 1920, 0xff0000);
}
void isr13_handler(interrupt_frame_t *frame)
{
    panic("General Protection Fault");
    while(1);
    //fillRect(0, 0, 1080, 1920, 0xff0000);
}
void isr14_handler(interrupt_frame_t *frame)
{
    panic("Page Fault");
    
    while(1);
   //fillRect(0, 0, 1080, 1920, 0xff0000);
}

中断请求:


#include "irq.h"
#include "../../PS2/ps2.h"
#include "../../PS2/keyboard/keyboard.h"
#include "../../PS2/mouse/mouse.h"
#include "../../video/video.h" 
#include "../../string/string.h"

void default_irq_handler(interrupt_frame_t *frame)
{
        /* If IRQ # on slave PIC send EOI to slave */
        if (frame->int_no >= 8)
            outb(0xA0,0x20);

        /* Send EOI to master PIC */
        outb(0x20,0x20);
}

/* -------------------------- Programable Interval Timer ------------------------- */
void irq0_handler(interrupt_frame_t* frame)
{
    EnvironmentTick++;
    default_irq_handler(frame);
}

void Sleep(int ticks)
{
    int now = EnvironmentTick;

    while (EnvironmentTick != now + ticks);

    return;

}
void SetPITSpeed(int hz)
{
    int divisor = 1193180 / hz;       /* Calculate our divisor */
    outb(0x43, 0x36);             /* Set our command byte 0x36 */
    outb(0x40, divisor & 0xFF);   /* Set low byte of divisor */
    outb(0x40, divisor >> 8);     /* Set high byte of divisor */
}
/*  ------------------------------------------------------------------------------ */


/* -------------------------- Keyboard Controller -------------------------------- */
unsigned char currentCharInScancode;
unsigned char currentCharInKeycode;
unsigned char currentCharInASCII;

int isE0 = 0;
int isE1 = 0;
int pause = 0;
int prntscrn = 0;   
int isKeyPressed = 0;
int ignore = 0;
int isShift = 0;
char kbd_buffer[100];
int bufferIterator = 0;
char buffer[8];

void irq1_handler(interrupt_frame_t* frame)
{
    
    currentCharInScancode = readKeyboard();
    
    if(ignore > 0)
    {
        ignore--;
        default_irq_handler(frame);
        return;
    }
    else if(currentCharInScancode == 0xE1 && pause == 0)
    {
        pause = 1;
        ignore = 5;
    }
    else if(currentCharInScancode == 0xE0)
    {
        isE0 = 1;
        default_irq_handler(frame);
        return;
    }
    else if(currentCharInScancode == 0xF0)
    {
        isKeyPressed = 2;
        default_irq_handler(frame);
        return;
    }
    else if(currentCharInScancode == 0x7C && isE0 == 1)
    {   
        prntscrn = 1;
        ignore = 2;
    }
    
    
    if(isKeyPressed == 0)
        isKeyPressed = 1;
    else if(isKeyPressed == 2)
        isKeyPressed = 0;
    
    currentCharInKeycode = ScancodeToKeyCode(currentCharInScancode, isE0, prntscrn, pause);
    if(isE0 == 1) isE0 = 0;
    if(pause == 1) pause = 0;
    if(prntscrn == 1) prntscrn = 0;
    
    //drawStringToCursor(itoa(isKeyPressed, buffer, 16), 0xffffff, 0x000000);
    
    KeyPressed[currentCharInKeycode] = isKeyPressed; 
    
    //drawStringToCursor(itoa(isKeyPressed, buffer, 16), 0xffffff, 0x000000);
    
    kbd_buffer[bufferIterator] = currentCharInKeycode;
    if(bufferIterator == 99) bufferIterator = 0;
    else bufferIterator++;
    
    /*
    if((KeyCodeToASCII(currentCharInKeycode, KeyPressed[LSHIFT] | KeyPressed[RSHIFT]) != 0) && isKeyPressed == 1) 
    {
        drawCharToCursor(KeyCodeToASCII(currentCharInKeycode, KeyPressed[LSHIFT] | KeyPressed[RSHIFT]), 0xffffff, 0x000000);
        incrementCursor();
    }*/
    default_irq_handler(frame);
}
/*  ------------------------------------------------------------------------------ */

 
void irq2_handler(interrupt_frame_t* frame)
{
    default_irq_handler(frame);
}
void irq3_handler(interrupt_frame_t* frame)
{
    default_irq_handler(frame);
}
void irq4_handler(interrupt_frame_t* frame)
{
    default_irq_handler(frame);
}
void irq5_handler(interrupt_frame_t* frame)
{
    default_irq_handler(frame);
}
void irq6_handler(interrupt_frame_t* frame)
{
    default_irq_handler(frame);
}
void irq7_handler(interrupt_frame_t* frame)
{
    default_irq_handler(frame);
}
void irq8_handler(interrupt_frame_t* frame)
{
    default_irq_handler(frame);
}
void irq9_handler(interrupt_frame_t* frame)
{
    default_irq_handler(frame);
}
void irq10_handler(interrupt_frame_t* frame)
{
    default_irq_handler(frame);
}
void irq11_handler(interrupt_frame_t* frame)
{
    default_irq_handler(frame);
}

// -------------------------------- Mouse Controller ------------------------

unsigned char mouse_cycle = 0;
signed char mouse_byte[3];    //signed char
signed char mouse_x = 0;         //signed char
signed char mouse_y = 0;         //signed char
signed char state = 0;
signed char d = 0;

int LeftButton = 0;
int MiddleButton = 0;
int RightButton = 0;

unsigned char buff[16];
void irq12_handler(interrupt_frame_t* frame)
{
    switch(mouse_cycle)
    {
        case 0:
            mouse_byte[0]=readMouse();
            mouse_cycle++;
            break;
        case 1:
            mouse_byte[1]=readMouse();
            mouse_cycle++;
            break;
        case 2:
            mouse_byte[2]=readMouse();
            
            
            state = mouse_byte[2];
            d = mouse_byte[0];
            mouse_x = d - ((state << 4) & 0x100);
            d = mouse_byte[1];      
            mouse_y = d - ((state << 3) & 0x100);
            
            MouseX = MouseX + mouse_x;
            MouseY = MouseY - mouse_y;
            
            putpixel(MouseX, MouseY, 0xffffff);
            
            if( (state & 0b00001100) == 0b00001100 ) MiddleButton = 1;
            else if( (state & 0b00001100) == 0b00001000 ) MiddleButton = 0;
            
            if( (state & 0b000010001) == 0b00001001 ) LeftButton = 1;
            else if( (state & 0b00001001) == 0b00001000 ) LeftButton = 0;
            
            if( (state & 0b00001010) == 0b00001010 ) RightButton = 1;
            else if( (state & 0b00001010) == 0b00001000 ) RightButton = 0;
            
            //drawStringToCursor(itoa(RightButton, buffer, 16), 0xffffff, 0x000000);
            //incrementCursor();
            mouse_cycle=0;
            break;
    }
    default_irq_handler(frame);
}
// --------------------------------------------------------------------------

void irq13_handler(interrupt_frame_t* frame)
{
    default_irq_handler(frame);
}
void irq14_handler(interrupt_frame_t* frame)
{
    default_irq_handler(frame);
}
void irq15_handler(interrupt_frame_t* frame)
{
    default_irq_handler(frame);
}

以及整个 github 存储库: https://github.com/Danyy427/OSDEV5.git

您可以在 source/kernel/idt 中找到与 idt 相关的内容

你可以在 source/kernel/memory/paging 中找到与分页相关的内容

您可以在设置 64 位 gdt 的 source/bootloader/AfterBoot.asm 中找到与 gdt 相关的内容。

编辑:

新的 IDT.c 修复了一些问题(希望如此)

#include "IDT.h"

#define PUSHALL \
     ".intel_syntax noprefix\n\t" \
    "push    r15\n\t"\
    "push    r14\n\t"\
    "push    r13\n\t"\
    "push    r12\n\t"\
    "push    r11\n\t"\
    "push    r10\n\t"\
    "push    r9\n\t"\
    "push    r8\n\t"\
    "push    rax\n\t"\
    "push    rcx\n\t"\
    "push    rdx\n\t"\
    "push    rbx\n\t"\
    "push    rsp\n\t"\
    "push    rbp\n\t"\
    "push    rsi\n\t"\
    "push    rdi\n\t"\
     ".att_syntax\n\t" \

#define POPALL\
    ".intel_syntax noprefix\n\t" \
    "pop     rdi\n\t"\
    "pop     rsi\n\t"\
    "pop     rbp\n\t"\
    "add     rsp, 10\n\t"\
    "pop     rbx\n\t"\
    "pop     rdx\n\t"\
    "pop     rcx\n\t"\
    "pop     rax\n\t"\
    "pop     r8\n\t"\
    "pop     r9\n\t"\
    "pop     r10\n\t"\
    "pop     r11\n\t"\
    "pop     r12\n\t"\
    "pop     r13\n\t"\
    "pop     r14\n\t"\
    "pop     r15\n\t"\
    "add     rsp, 0x10\n\t"\
    ".att_syntax\n\t" \
    

/* Common body for interrupt handler */
#define MAKE_INTERRUPT_COMMON_STUB(intno, intfunc) \
            "push $"#intno"\n\t" \
            PUSHALL  \
            "mov %rsp, %rdi\n\t"\
            "sub $0x28, %rsp\n\t"\
            "cld\n\t" \
            "call " #intfunc "\n\t" \
            "add $28, %rsp\n\t"       /* Skip int_num and err_code */ \
            POPALL \
            "iretq \n\t" 

/* Make interrupt for exception without error code. Push a dummy value for the
 * error code in it place. Push all the segment registers and the segment registers
 * so that they are available to interrupt function (intfun). Pushes a unique
 * interrupt number (intno) after the error code so that a handler can be multiplexed
 * if needed. Restore all the registers upon exit.
 *
 * intentry: Is the interrupt entry point that can be used in an Interrupt
 *           Descriptor Table (IDT) entry.
 * intfunc:  Is the C interrupt function that the stub calls to do processing
 * intno:    Interrupt number. Can be used to multiplex multiple interrupts to one
 *           intfunc handler.
 */
#define MAKE_INTERRUPT(intentry, intfunc, intno) \
    extern void intentry (void); \
    __asm__(".global " #intentry "\n\t" \
            ".align 16\n\t" \
            #intentry ":\n\t" \
            "push $0\n\t"            /* Push dummy error code */ \
            MAKE_INTERRUPT_COMMON_STUB(intno, intfunc));

/* Make interrupt for exception with error code. Processor pushes the error code
 * after the return address automatically. Push all the segment registers and the
 * segment registers so that they are available to interrupt function (intfun).
 * Pushes a unique interrupt number (intno) after the error code so that a handler
 * can be multiplexed if needed. Restore all the registers upon exit.
 *
 * intentry: Is the interrupt entry point that can be used in an Interrupt
 *           Descriptor Table (IDT) entry.
 * intfunc:  Is the C interrupt function that the stub calls to do processing
 * intno:    Interrupt number. Can be used to multiplex multiple interrupts to one
 *           intfunc handler.
*/
#define MAKE_INTERRUPT_ERRCODE(intentry, intfunc, intno) \
    extern void intentry (void); \
    __asm__(".global " #intentry "\n" \
            ".align 16\n\t" \
            #intentry ":\n\t" \
            MAKE_INTERRUPT_COMMON_STUB(intno, intfunc));

MAKE_INTERRUPT        (isr0,  isr0_handler,  0x00)
MAKE_INTERRUPT        (isr1,  isr1_handler,  0x01)
MAKE_INTERRUPT        (isr2,  isr2_handler,  0x02)
MAKE_INTERRUPT        (isr3,  isr3_handler,  0x03)
MAKE_INTERRUPT        (isr4,  isr4_handler,  0x04)
MAKE_INTERRUPT        (isr5,  isr5_handler,  0x05)
MAKE_INTERRUPT        (isr6,  isr6_handler,  0x06)
MAKE_INTERRUPT        (isr7,  isr7_handler,  0x07)
MAKE_INTERRUPT_ERRCODE(isr8,  isr8_handler,  0x08)
MAKE_INTERRUPT        (isr9,  isr9_handler,  0x09)
MAKE_INTERRUPT_ERRCODE(isr10, isr10_handler, 0x0a)
MAKE_INTERRUPT_ERRCODE(isr11, isr11_handler, 0x0b)
MAKE_INTERRUPT_ERRCODE(isr12, isr12_handler, 0x0c)
MAKE_INTERRUPT_ERRCODE(isr13, isr13_handler, 0x0d)
MAKE_INTERRUPT_ERRCODE(isr14, isr14_handler, 0x0e)
/* Reserved 0x0f */
MAKE_INTERRUPT        (isr16, isr0_handler,  0x10)
MAKE_INTERRUPT_ERRCODE(isr17, isr0_handler,  0x11)
MAKE_INTERRUPT        (isr18, isr0_handler,  0x12)
MAKE_INTERRUPT        (isr19, isr0_handler,  0x13)
MAKE_INTERRUPT        (isr20, isr0_handler,  0x14)
/* Reserved 0x15 to 0x1d */
MAKE_INTERRUPT_ERRCODE(isr30, isr0_handler,  0x1e)
/* Reserved 0x1f */

/* IRQ handlers */
MAKE_INTERRUPT        (irq0,  irq0_handler,  0)
MAKE_INTERRUPT        (irq1,  irq1_handler,  1)
MAKE_INTERRUPT        (irq2,  irq2_handler,  2)
MAKE_INTERRUPT        (irq3,  irq3_handler,  3)
MAKE_INTERRUPT        (irq4,  irq4_handler,  4)
MAKE_INTERRUPT        (irq5,  irq5_handler,  5)
MAKE_INTERRUPT        (irq6,  irq6_handler,  6)
MAKE_INTERRUPT        (irq7,  irq7_handler,  7)
MAKE_INTERRUPT        (irq8,  irq8_handler,  8)
MAKE_INTERRUPT        (irq9,  irq9_handler,  9)
MAKE_INTERRUPT        (irq10, irq10_handler,  10)
MAKE_INTERRUPT        (irq11, irq11_handler,  11)
MAKE_INTERRUPT        (irq12, irq12_handler,  12)
MAKE_INTERRUPT        (irq13, irq13_handler,  13)
MAKE_INTERRUPT        (irq14, irq14_handler,  14)
MAKE_INTERRUPT        (irq15, irq15_handler,  15)

void init_idt_entry(int num, unsigned int offset, unsigned short select, 
    unsigned short flags)
    {
        
        _idt_entries[num].offset0 = (unsigned short)(offset & 0x000000000000FFFF);
        _idt_entries[num].offset1 = (unsigned short)((offset & 0x00000000FFFF0000) >> 16);
        _idt_entries[num].offset2 = (unsigned int)((offset & 0xFFFFFFFF00000000) >> 32);

        _idt_entries[num].selector = select;
        _idt_entries[num].flags = flags;
         return;
    }




///////////////////////////////////////
void idt_flush(struct idt *idtr)
{
    asm volatile("lidt %0" :: "m"(*idtr));
}

void init_pic()
{

    outb(0x20,0x11);
    outb(0xA0,0x11);

    outb(0x21, 0x20);
    outb(0xA1, 40);

    outb(0x21, 0x04);
    outb(0xA1, 0x02);

    outb(0x21, 0x01);
    outb(0xA1, 0x01);

    outb(0x21, 0x0);
    outb(0xA1, 0x0);

    
}


void init_idt()
{
    init_pic();
    
    _idt_entries = RequestPage();
    Tidt.limit = 16 * 256;
    Tidt.base  = _idt_entries;
    
    memset(_idt_entries, 0, 16*256);
    
    
    
    for(int i = 0; i < 256 ; i++){
        init_idt_entry(i,(int)&isr0,0x08, 0x8E); 
    }
    init_idt_entry(0,(int)&isr0,0x08, 0x8E);
    init_idt_entry(1,(int)&isr1,0x08, 0x8E);
    init_idt_entry(2,(int)&isr2,0x08, 0x8E);
    init_idt_entry(3,(int)&isr3,0x08, 0x8E);
    init_idt_entry(4,(int)&isr4,0x08, 0x8E);
    init_idt_entry(5,(int)&isr5,0x08, 0x8E);
    init_idt_entry(6,(int)&isr6,0x08, 0x8E);
    init_idt_entry(7,(int)&isr7,0x08, 0x8E);
    init_idt_entry(8,(int)&isr8,0x08, 0x8E);
    init_idt_entry(9,(int)&isr9,0x08, 0x8E);
    init_idt_entry(10,(int)&isr10,0x08, 0x8E);
    init_idt_entry(11,(int)&isr11,0x08, 0x8E);
    init_idt_entry(12,(int)&isr12,0x08, 0x8E);
    init_idt_entry(13,(int)&isr13,0x08, 0x8E);
    init_idt_entry(14,(int)&isr14,0x08, 0x8E);
    /* ISR15 is reserved */
    init_idt_entry(16,(int)&isr16,0x08, 0x8E);
    init_idt_entry(17,(int)&isr17,0x08, 0x8E);
    init_idt_entry(18,(int)&isr18,0x08, 0x8E);
    init_idt_entry(19,(int)&isr19,0x08, 0x8E);
    init_idt_entry(20,(int)&isr20,0x08, 0x8E);
    /* ISR21 to ISR2F are reserved */
    init_idt_entry(30,(int)&isr30,0x08, 0x8E);

    /* IRQ handlers */
    init_idt_entry(32,(int)&irq0,0x08, 0x8E);
    init_idt_entry(33,(int)&irq1,0x08, 0x8E);
    init_idt_entry(34,(int)&irq2,0x08, 0x8E);
    init_idt_entry(35,(int)&irq3,0x08, 0x8E);
    init_idt_entry(36,(int)&irq4,0x08, 0x8E);
    init_idt_entry(37,(int)&irq5,0x08, 0x8E);
    init_idt_entry(38,(int)&irq6,0x08, 0x8E);
    init_idt_entry(39,(int)&irq7,0x08, 0x8E);
    init_idt_entry(40,(int)&irq8,0x08, 0x8E);
    init_idt_entry(41,(int)&irq9,0x08, 0x8E);
    init_idt_entry(42,(int)&irq10,0x08, 0x8E);
    init_idt_entry(43,(int)&irq11,0x08, 0x8E);
    init_idt_entry(44,(int)&irq12,0x08, 0x8E);
    init_idt_entry(45,(int)&irq13,0x08, 0x8E);
    init_idt_entry(46,(int)&irq14,0x08, 0x8E);
    init_idt_entry(47,(int)&irq15,0x08, 0x8E);
    
    
    
    SetPITSpeed(100);
    drawStringToCursor("Set PIT speed\n",0xffffff, 0x000000);       
    
    idt_flush(&Tidt);
    
    //int d = 5 / 0;
    //asm volatile("sti;");
    //while(1);
    
}

当我正常评论 sti 和 isr 的火时,一般保护错误消失了,我尝试用除以零错误,但是现在 irq 不火,我不知道发生了什么。

编辑:我解决了这个问题,问题是我没有正确设置堆栈

"sub $0x28, %rsp\n\t"\
            "cld\n\t" \
            "call " #intfunc "\n\t" \
            "add $28, %rsp\n\t"  

我忘记了最后一条指令中 28 前面的 0x。真难为情。另外我在这里写了 10 而不是 8

#define POPALL\
    ".intel_syntax noprefix\n\t" \
    "pop     rdi\n\t"\
    "pop     rsi\n\t"\
    "pop     rbp\n\t"\
    "add     rsp, 10\n\t"\
    "pop     rbx\n\t"\
    "pop     rdx\n\t"\


0 个答案:

没有答案