Search code examples
cassemblykernelx86-64interrupt

Keyboard interrupts in long mode. 64 bit os


I try to create my first os from 0 using different tutorials. Now I have a simple kernel with simple paging, GDT for 64 bit, and entering to long mode. But there is a problem with keyboard interrupts. I read lots of topics about that and I think its a double-fault when start typing. Please, help me to understand and fix this problem. Here is repository with my code https://github.com/alexanderian76/TestOS So, the problem is if I type anything, QEMU resets system instead showing symbols on display. Each interrupt resets it, as I understand. This is my gdt64 and enter to long-mode


gdt64:
    dq 0 ; zero entry
.code: equ $ - gdt64 ; new
    dq (1<<43) | (1<<44) | (1<<47) | (1<<53) ; code segment
.pointer:
    dw $ - gdt64 - 1
    dq gdt64

This is enter to long mode.

start:
    mov esp, stack_top

    call check_multiboot
    call check_cpuid
    call check_long_mode

    call set_up_page_tables ; new
    call enable_paging     ; new

    ; print `OK` to screen
    mov dword [0xb8000], 0x2f4b2f4f
    
    lgdt [gdt64.pointer]
    jmp gdt64.code:long_mode_start
    
    hlt



long_mode_start:
    ; print `OKAY` to screen
    mov ax, 0
    mov ss, ax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax

    
    mov rax, 0x2f592f412f4b2f4f
    mov qword [0xb8000], rax
    
   call main
   
    hlt

And this is IDT

#define PIC2_COMMAND 0xA0
#define PIC2_DATA 0xA1

#define ICW1_INIT 0x10
#define ICW1_ICW4 0x01
#define ICW4_8086 0x01



struct IDT_entry {
    unsigned short offset_lowerbits;
    unsigned short selector;
    unsigned char ist;
    unsigned short offset_mid;
    unsigned int zero;
    unsigned char type_attr;
    unsigned int offset_higherbits;
};
//*********************************


extern struct IDT_entry IDT[IDT_SIZE];

void load_idt_entry()
{
   for(unsigned long long int t = 0; t < 256; t++) {
    IDT[t].offset_lowerbits = (unsigned short)(((unsigned long long int)&isr1 & 0x000000000000ffff));
    IDT[t].offset_mid = (unsigned short)(((unsigned long long int)&isr1 & 0x00000000ffff0000) >> 16);
    IDT[t].offset_higherbits = (unsigned int)(((unsigned long long int)&isr1 & 0xffffffff00000000) >> 32);
    IDT[t].selector = 0x08;
    IDT[t].type_attr = 0x8e;
    IDT[t].zero = 0;
    IDT[t].ist = 0;
    
    

    RemapPic();

    outb(0x21, 0xfd);
    outb(0xa1, 0xff);
    
    
    LoadIDT();
   }
}

void outb(unsigned short port, unsigned char val){
  asm volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
}

unsigned char inb(unsigned short port){
  unsigned char returnVal;
  asm volatile ("inb %1, %0"
  : "=a"(returnVal)
  : "Nd"(port));
  return returnVal;
}

void RemapPic(){
  unsigned char a1, a2;

  a1 = inb(PIC1_DATA);
  a2 = inb(PIC2_DATA);
  outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4);
  outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4);
  outb(PIC1_DATA, 0);
  outb(PIC2_DATA, 8);
  outb(PIC1_DATA, 4);
  outb(PIC2_DATA, 2);
  outb(PIC1_DATA, ICW4_8086);
  outb(PIC2_DATA, ICW4_8086);

  outb(PIC1_DATA, a1);
  outb(PIC2_DATA, a2);

}

Sorry, this the first time I ask something here, but I cant solve this problem by myself. Thank you so much!


Solution

  • Your IDT_entry seems to have the fields in the wrong order. type_attr should be after the ist and the zero should be at the end. Also your POPALL macro actually has pushes not pops.

    diff --git a/long_mode_init.asm b/long_mode_init.asm
    index cd64e24..926afae 100644
    --- a/long_mode_init.asm
    +++ b/long_mode_init.asm
    @@ -19,13 +19,13 @@ extern IDT
     %endmacro
     
     %macro POPALL 0
    -    push r11
    -    push r10
    -    push r9
    -    push r8
    -    push rdx
    -    push rcx
    -    push rax
    +    pop r11
    +    pop r10
    +    pop r9
    +    pop r8
    +    pop rdx
    +    pop rcx
    +    pop rax
     %endmacro
         
     
    diff --git a/main.c b/main.c
    index b1bfa1c..22ef2fe 100644
    --- a/main.c
    +++ b/main.c
    @@ -41,10 +41,10 @@ struct IDT_entry {
        unsigned short offset_lowerbits;
        unsigned short selector;
         unsigned char ist;
    -    unsigned short offset_mid;
    -   unsigned int zero;
        unsigned char type_attr;
    +    unsigned short offset_mid;
        unsigned int offset_higherbits;
    +   unsigned int zero;
     };
     //*********************************
    

    With these changes it does no longer crash.