Add long mode IDT

This commit is contained in:
pjht 2019-04-27 09:51:32 -05:00
parent 5384ec3af0
commit c6bca7f177
14 changed files with 937 additions and 28 deletions

View File

@ -34,7 +34,7 @@ cpuid: aes=0, sha=0, xsave=0, xsaveopt=0, avx_f16c=0, avx_fma=0, bmi=0, xop=0, f
cpuid: tbm=0, x86_64=1, 1g_pages=0, pcid=0, fsgsbase=0, smep=0, smap=0, mwait=1, vmx=1
print_timestamps: enabled=0
debugger_log: -
magic_break: enabled=0
magic_break: enabled=1
port_e9_hack: enabled=0
private_colormap: enabled=0
clock: sync=none, time0=local, rtc_sync=0

View File

@ -37,7 +37,7 @@ static idt_register_t idt_reg;
void idt_set_gate(int n,uint32_t handler) {
idt[n].low_offset=low_16(handler);
idt[n].sel=KERNEL_CS;
idt[n].sel=0x08;
idt[n].always0=0;
idt[n].flags=0xEE;
idt[n].high_offset=high_16(handler);

15
cpu/x86_64/cpu_init.c Normal file
View File

@ -0,0 +1,15 @@
// #include "gdt.h"
// #include "paging.h"
#include "isr.h"
#include <grub/multiboot.h>
// #include "pmem.h"
// #include "../tasking.h"
void cpu_init(multiboot_info_t* mbd) {
// gdt_init();
isr_install();
asm volatile("sti");
// pmem_init(mbd);
// paging_init();
// tasking_init();
}

5
cpu/x86_64/halt.c Normal file
View File

@ -0,0 +1,5 @@
void halt() {
asm volatile("cli;\
hltlabel: hlt;\
jmp hltlabel");
}

55
cpu/x86_64/idt.c Normal file
View File

@ -0,0 +1,55 @@
#include "idt.h"
#include <stdint.h>
/* Segment selectors */
#define KERNEL_CS 0x08
/* How every interrupt gate (handler) is defined */
typedef struct {
uint16_t low_offset; /* Low 16 bits of handler function address */
uint16_t sel; /* Kernel segment selector */
uint8_t always0;
/* First byte
* Bit 7: "Interrupt is present"
* Bits 6-5: Privilege level of caller (0=kernel..3=user)
* Bit 4: Set to 0 for interrupt gates
* Bits 3-0: bits 1110 = decimal 14 = "32 bit interrupt gate" */
uint8_t flags;
uint16_t middle_offset; /* Middle 16 bits of handler function address */
uint32_t high_offset; /* High 32 bits of handler function address */
uint32_t also0;
} __attribute__((packed)) idt_gate_t ;
/* A pointer to the array of interrupt handlers.
* Assembly instruction 'lidt' will read it */
typedef struct {
uint16_t limit;
uint64_t base;
} __attribute__((packed)) idt_register_t;
#define IDT_ENTRIES 256
static idt_gate_t idt[IDT_ENTRIES];
static idt_register_t idt_reg;
#define low_16(address) (uint16_t)((address) & 0xFFFF)
#define middle_16(address) (uint16_t)(((address) >> 16) & 0xFFFF)
#define high_32(address) (uint32_t)(((address) >> 32) & 0xFFFFFFFF)
void idt_set_gate(int n,uint64_t handler) {
idt[n].low_offset=low_16(handler);
idt[n].sel=KERNEL_CS;
idt[n].always0=0;
idt[n].flags=0xEE;
idt[n].middle_offset=middle_16(handler);
idt[n].high_offset=high_32(handler);
idt[n].also0=0;
}
void load_idt() {
idt_reg.base=(uint64_t) &idt;
idt_reg.limit=IDT_ENTRIES * sizeof(idt_gate_t) - 1;
/* Don't make the mistake of loading &idt -- always load &idt_reg */
asm volatile("lidtq (%0)":: "r" (&idt_reg));
}

10
cpu/x86_64/idt.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef IDT_H
#define IDT_H
#include <stdint.h>
/* Functions implemented in idt.c */
void idt_set_gate(int n,uint64_t handler);
void load_idt();
#endif

469
cpu/x86_64/interrupt.asm Normal file
View File

@ -0,0 +1,469 @@
; Defined in isr.c
[extern isr_handler]
[extern irq_handler]
; Common ISR code
isr_common_stub:
; 1. Save CPU state
push rax
push rcx
push rdx
push rbx
push rsp
push rbp
push rsi
push rdi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
; 2. Call C handler
call isr_handler
; 3. Restore state
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rbp
pop rsp
pop rbx
pop rdx
pop rcx
pop rax
add esp, 16 ; Cleans up the pushed error code and pushed ISR number
sti
iretq ; pops 5 things at once: CS, EIP, RFLAGS, SS, and RSP
; Common IRQ code. Identical to ISR code except for the 'call'
; and the 'pop ebx'
irq_common_stub:
; 1. Save CPU state
push rax
push rcx
push rdx
push rbx
push rsp
push rbp
push rsi
push rdi
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
; 2. Call C handler
call irq_handler
; 3. Restore state
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rdi
pop rsi
pop rbp
pop rsp
pop rbx
pop rdx
pop rcx
pop rax
add esp, 16 ; Cleans up the pushed error code and pushed ISR number
sti
iretq ; pops 5 things at once: CS, EIP, RFLAGS, SS, and RSP
; We don't get information about which interrupt was caller
; when the handler is run, so we will need to have a different handler
; for every interrupt.
; Furthermore, some interrupts push an error code onto the stack but others
; don't, so we will push a dummy error code for those which don't, so that
; we have a consistent stack for all of them.
; First make the ISRs global
global isr0
global isr1
global isr2
global isr3
global isr4
global isr5
global isr6
global isr7
global isr8
global isr9
global isr10
global isr11
global isr12
global isr13
global isr14
global isr15
global isr16
global isr17
global isr18
global isr19
global isr20
global isr21
global isr22
global isr23
global isr24
global isr25
global isr26
global isr27
global isr28
global isr29
global isr30
global isr31
global isr80
; IRQs
global irq0
global irq1
global irq2
global irq3
global irq4
global irq5
global irq6
global irq7
global irq8
global irq9
global irq10
global irq11
global irq12
global irq13
global irq14
global irq15
; 0: Divide By Zero Exception
isr0:
cli
push qword 0
push qword 0
jmp isr_common_stub
; 1: Debug Exception
isr1:
cli
push qword 0
push qword 1
jmp isr_common_stub
; 2: Non Maskable Interrupt Exception
isr2:
cli
push qword 0
push qword 2
jmp isr_common_stub
; 3: Int 3 Exception
isr3:
cli
push qword 0
push qword 3
jmp isr_common_stub
; 4: INTO Exception
isr4:
cli
push qword 0
push qword 4
jmp isr_common_stub
; 5: Out of Bounds Exception
isr5:
cli
push qword 0
push qword 5
jmp isr_common_stub
; 6: Invalid Opcode Exception
isr6:
cli
push qword 0
push qword 6
jmp isr_common_stub
; 7: Coprocessor Not Available Exception
isr7:
cli
push qword 0
push qword 7
jmp isr_common_stub
; 8: Double Fault Exception (With Error Code!)
isr8:
cli
push qword 8
jmp isr_common_stub
; 9: Coprocessor Segment Overrun Exception
isr9:
cli
push qword 0
push qword 9
jmp isr_common_stub
; 10: Bad TSS Exception (With Error Code!)
isr10:
cli
push qword 10
jmp isr_common_stub
; 11: Segment Not Present Exception (With Error Code!)
isr11:
cli
push qword 11
jmp isr_common_stub
; 12: Stack Fault Exception (With Error Code!)
isr12:
cli
push qword 12
jmp isr_common_stub
; 13: General Protection Fault Exception (With Error Code!)
isr13:
cli
push qword 13
jmp isr_common_stub
; 14: Page Fault Exception (With Error Code!)
isr14:
cli
push qword 14
jmp isr_common_stub
; 15: Reserved Exception
isr15:
cli
push qword 0
push qword 15
jmp isr_common_stub
; 16: Floating Point Exception
isr16:
cli
push qword 0
push qword 16
jmp isr_common_stub
; 17: Alignment Check Exception
isr17:
cli
push qword 0
push qword 17
jmp isr_common_stub
; 18: Machine Check Exception
isr18:
cli
push qword 0
push qword 18
jmp isr_common_stub
; 19: Reserved
isr19:
cli
push qword 0
push qword 19
jmp isr_common_stub
; 20: Reserved
isr20:
cli
push qword 0
push qword 20
jmp isr_common_stub
; 21: Reserved
isr21:
cli
push qword 0
push qword 21
jmp isr_common_stub
; 22: Reserved
isr22:
cli
push qword 0
push qword 22
jmp isr_common_stub
; 23: Reserved
isr23:
cli
push qword 0
push qword 23
jmp isr_common_stub
; 24: Reserved
isr24:
cli
push qword 0
push qword 24
jmp isr_common_stub
; 25: Reserved
isr25:
cli
push qword 0
push qword 25
jmp isr_common_stub
; 26: Reserved
isr26:
cli
push qword 0
push qword 26
jmp isr_common_stub
; 27: Reserved
isr27:
cli
push qword 0
push qword 27
jmp isr_common_stub
; 28: Reserved
isr28:
cli
push qword 0
push qword 28
jmp isr_common_stub
; 29: Reserved
isr29:
cli
push qword 0
push qword 29
jmp isr_common_stub
; 30: Reserved
isr30:
cli
push qword 0
push qword 30
jmp isr_common_stub
; 31: Reserved
isr31:
cli
push qword 0
push qword 31
jmp isr_common_stub
; 80: Syscalls
isr80:
cli
push qword 0
push qword 80
jmp isr_common_stub
; IRQ handlers
irq0:
cli
push qword 0
push qword 32
jmp irq_common_stub
irq1:
cli
push qword 1
push qword 33
jmp irq_common_stub
irq2:
cli
push qword 2
push qword 34
jmp irq_common_stub
irq3:
cli
push qword 3
push qword 35
jmp irq_common_stub
irq4:
cli
push qword 4
push qword 36
jmp irq_common_stub
irq5:
cli
push qword 5
push qword 37
jmp irq_common_stub
irq6:
cli
push qword 6
push qword 38
jmp irq_common_stub
irq7:
cli
push qword 7
push qword 39
jmp irq_common_stub
irq8:
cli
push qword 8
push qword 40
jmp irq_common_stub
irq9:
cli
push qword 9
push qword 41
jmp irq_common_stub
irq10:
cli
push qword 10
push qword 42
jmp irq_common_stub
irq11:
cli
push qword 11
push qword 43
jmp irq_common_stub
irq12:
cli
push qword 12
push qword 44
jmp irq_common_stub
irq13:
cli
push qword 13
push qword 45
jmp irq_common_stub
irq14:
cli
push qword 14
push qword 46
jmp irq_common_stub
irq15:
cli
push qword 15
push qword 47
jmp irq_common_stub

56
cpu/x86_64/interrupt.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef INERRUPT_H
#define INTERRUPT_H
/* ISRs reserved for CPU exceptions */
void isr0();
void isr1();
void isr2();
void isr3();
void isr4();
void isr5();
void isr6();
void isr7();
void isr8();
void isr9();
void isr10();
void isr11();
void isr12();
void isr13();
void isr14();
void isr15();
void isr16();
void isr17();
void isr18();
void isr19();
void isr20();
void isr21();
void isr22();
void isr23();
void isr24();
void isr25();
void isr26();
void isr27();
void isr28();
void isr29();
void isr30();
void isr31();
void isr80();
/* IRQ definitions */
void irq0();
void irq1();
void irq2();
void irq3();
void irq4();
void irq5();
void irq6();
void irq7();
void irq8();
void irq9();
void irq10();
void irq11();
void irq12();
void irq13();
void irq14();
void irq15();
#endif

203
cpu/x86_64/isr.c Normal file
View File

@ -0,0 +1,203 @@
#include "isr.h"
#include "idt.h"
#include "ports.h"
// #include "paging.h"
#include "../halt.h"
#include "../../drivers/vga.h"
// #include "../tasking.h"
#include "interrupt.h"
#include <string.h>
#include <stdint.h>
void irq_handler(registers_t r);
static isr_t interrupt_handlers[256];
/* Can't do this with a loop because we need the address
* of the function names */
void isr_install() {
idt_set_gate(0,(uint64_t)isr0);
idt_set_gate(1,(uint64_t)isr1);
idt_set_gate(2,(uint64_t)isr2);
idt_set_gate(3,(uint64_t)isr3);
idt_set_gate(4,(uint64_t)isr4);
idt_set_gate(5,(uint64_t)isr5);
idt_set_gate(6,(uint64_t)isr6);
idt_set_gate(7,(uint64_t)isr7);
idt_set_gate(8,(uint64_t)isr8);
idt_set_gate(9,(uint64_t)isr9);
idt_set_gate(10,(uint64_t)isr10);
idt_set_gate(11,(uint64_t)isr11);
idt_set_gate(12,(uint64_t)isr12);
idt_set_gate(13,(uint64_t)isr13);
idt_set_gate(14,(uint64_t)isr14);
idt_set_gate(15,(uint64_t)isr15);
idt_set_gate(16,(uint64_t)isr16);
idt_set_gate(17,(uint64_t)isr17);
idt_set_gate(18,(uint64_t)isr18);
idt_set_gate(19,(uint64_t)isr19);
idt_set_gate(20,(uint64_t)isr20);
idt_set_gate(21,(uint64_t)isr21);
idt_set_gate(22,(uint64_t)isr22);
idt_set_gate(23,(uint64_t)isr23);
idt_set_gate(24,(uint64_t)isr24);
idt_set_gate(25,(uint64_t)isr25);
idt_set_gate(26,(uint64_t)isr26);
idt_set_gate(27,(uint64_t)isr27);
idt_set_gate(28,(uint64_t)isr28);
idt_set_gate(29,(uint64_t)isr29);
idt_set_gate(30,(uint64_t)isr30);
idt_set_gate(31,(uint64_t)isr31);
idt_set_gate(80,(uint64_t)isr80);
// Remap the PIC
port_byte_out(0x20,0x11);
port_byte_out(0xA0,0x11);
port_byte_out(0x21,0x20);
port_byte_out(0xA1,0x28);
port_byte_out(0x21,0x04);
port_byte_out(0xA1,0x02);
port_byte_out(0x21,0x01);
port_byte_out(0xA1,0x01);
port_byte_out(0x21,0x0);
port_byte_out(0xA1,0x0);
// Install the IRQs
idt_set_gate(32,(uint64_t)irq0);
idt_set_gate(33,(uint64_t)irq1);
idt_set_gate(34,(uint64_t)irq2);
idt_set_gate(35,(uint64_t)irq3);
idt_set_gate(36,(uint64_t)irq4);
idt_set_gate(37,(uint64_t)irq5);
idt_set_gate(38,(uint64_t)irq6);
idt_set_gate(39,(uint64_t)irq7);
idt_set_gate(40,(uint64_t)irq8);
idt_set_gate(41,(uint64_t)irq9);
idt_set_gate(42,(uint64_t)irq10);
idt_set_gate(43,(uint64_t)irq11);
idt_set_gate(44,(uint64_t)irq12);
idt_set_gate(45,(uint64_t)irq13);
idt_set_gate(46,(uint64_t)irq14);
idt_set_gate(47,(uint64_t)irq15);
load_idt();
}
/* To print the message which defines every exception */
static char *exception_messages[] = {
"Division By Zero",
"Debug",
"Non Maskable Interrupt",
"Breakpoint",
"Into Detected Overflow",
"Out of Bounds",
"Invalid Opcode",
"No Coprocessor",
"Double Fault",
"Coprocessor Segment Overrun",
"Bad TSS",
"Segment Not Present",
"Stack Fault",
"General Protection Fault",
"Page Fault",
"Unknown Interrupt",
"Coprocessor Fault",
"Alignment Check",
"Machine Check",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved"
};
void isr_handler(registers_t r) {
switch (r.int_no) {
case 14: {
uint64_t addr;
asm("movq %%cr2,%0": "=r"(addr));
if (r.err_code==0) {
vga_write_string("Kernel process tried to read a non-present page entry at address ");
} else if (r.err_code==1) {
vga_write_string("Kernel process tried to read a page and caused a protection fault at address ");
} else if (r.err_code==2) {
vga_write_string("Kernel process tried to write to a non-present page entry at address ");
} else if (r.err_code==3) {
vga_write_string("Kernel process tried to write a page and caused a protection fault at address ");
} else if (r.err_code==4) {
vga_write_string("User process tried to read a non-present page entry at address ");
} else if (r.err_code==5) {
vga_write_string("User process tried to read a page and caused a protection fault at address ");
} else if (r.err_code==6) {
vga_write_string("User process tried to write to a non-present page entry at address ");
} else if (r.err_code==7) {
vga_write_string("User process tried to write a page and caused a protection fault at address ");
}
char str[11];
str[0]='\0';
hex_to_ascii(addr,str);
vga_write_string(str);
vga_write_string("\n");
// if ((r.err_code&1)==0) {
// // int dir_entry=(addr&0xFFC00000)>>22;
// // int table_entry=(addr&0x3FF000)>12;
// // if (dir_entry_present(dir_entry)) {
// // set_table_entry(dir_entry,table_entry,((dir_entry*1024)+table_entry)*0x1000,1,1,1);
// // for(int page=0;page<1024;page++) {
// // asm volatile("invlpg (%0)"::"r"(((dir_entry*1024)+page)*0x1000):"memory");
// // }
// // } else {
// // for(int page=0;page<1024;page++) {
// // set_table_entry(dir_entry,page,0x0,1,1,0);
// // }
// // set_table_entry(dir_entry,table_entry,((dir_entry*1024)+table_entry)*0x1000,1,1,1);
// // set_directory_entry(dir_entry,dir_entry,1,1,1);
// // }
// // return;
// }
halt();
break;
case 80:
// if (r.eax==1) {
// tss_stack_reset();
// tasking_yield();
// } else if (r.eax==2) {
// tasking_createTask((void*)r.ebx);
// } else if (r.eax==3) {
// r.ebx=(uint64_t)alloc_pages(r.ebx);
// } else if (r.eax==4) {
// alloc_pages_virt(r.ebx,(void*)r.ecx);
// } else if (r.eax==5) {
// r.ebx=(uint64_t)tasking_get_errno_address();
// }
break;
}
}
asm volatile("xchgw %bx, %bx");
}
void isr_register_handler(uint8_t n,isr_t handler) {
interrupt_handlers[n] = handler;
}
void irq_handler(registers_t r) {
/* After every interrupt we need to send an EOI to the PICs
* or they will not send another interrupt again */
if (r.int_no >= 40) port_byte_out(0xA0,0x20); /* slave */
port_byte_out(0x20,0x20); /* master */
/* Handle the interrupt in a more modular way */
if (interrupt_handlers[r.int_no] != 0) {
isr_t handler = interrupt_handlers[r.int_no];
handler(r);
}
}

90
cpu/x86_64/isr.h Normal file
View File

@ -0,0 +1,90 @@
#ifndef ISR_H
#define ISR_H
#include <stdint.h>
/* ISRs reserved for CPU exceptions */
extern void isr0();
extern void isr1();
extern void isr2();
extern void isr3();
extern void isr4();
extern void isr5();
extern void isr6();
extern void isr7();
extern void isr8();
extern void isr9();
extern void isr10();
extern void isr11();
extern void isr12();
extern void isr13();
extern void isr14();
extern void isr15();
extern void isr16();
extern void isr17();
extern void isr18();
extern void isr19();
extern void isr20();
extern void isr21();
extern void isr22();
extern void isr23();
extern void isr24();
extern void isr25();
extern void isr26();
extern void isr27();
extern void isr28();
extern void isr29();
extern void isr30();
extern void isr31();
extern void isr80();
/* IRQ definitions */
extern void irq0();
extern void irq1();
extern void irq2();
extern void irq3();
extern void irq4();
extern void irq5();
extern void irq6();
extern void irq7();
extern void irq8();
extern void irq9();
extern void irq10();
extern void irq11();
extern void irq12();
extern void irq13();
extern void irq14();
extern void irq15();
/* Struct which aggregates many registers */
typedef struct {
uint64_t r15,r14,r13,r12,r11,r10,r9,r8,rdi,rsi,rbp,rsp,rbx,rdx,rcx,rax; /* Pushed by our code. */
uint64_t int_no,err_code; /* Interrupt number and error code (if applicable) */
uint64_t rip,cs,rflags,userrsp,ss; /* Pushed by the processor automatically */
} registers_t;
#define IRQ0 32
#define IRQ1 33
#define IRQ2 34
#define IRQ3 35
#define IRQ4 36
#define IRQ5 37
#define IRQ6 38
#define IRQ7 39
#define IRQ8 40
#define IRQ9 41
#define IRQ10 42
#define IRQ11 43
#define IRQ12 44
#define IRQ13 45
#define IRQ14 46
#define IRQ15 47
typedef void (*isr_t)(registers_t);
void isr_install();
void isr_handler(registers_t r);
void irq_handler(registers_t r);
void isr_register_handler(uint8_t n,isr_t handler);
#endif

View File

@ -4,6 +4,12 @@ extern kmain
section .boot.text
bits 64
long_mode_start:
mov ax, 0
mov ss, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov rax,kmain
call rax
loop: jmp loop

0
ext2.img.lock Normal file
View File

View File

@ -1,29 +1,29 @@
// #include "../cpu/cpu_init.h"
#include "../cpu/cpu_init.h"
#include "../drivers/vga.h"
// #include "../drivers/pci.h"
// #include "../drivers/serial.h"
#include "../drivers/pci.h"
#include "../drivers/serial.h"
// #include "../cpu/i386/ports.h"
// #include "vfs.h"
// #include "../fs/devfs.h"
// #include "../fs/initrd.h"
#include "vfs.h"
#include "../fs/devfs.h"
#include "../fs/initrd.h"
#include <grub/text_fb_info.h>
// #include <stdlib.h>
// #include <tasking.h>
// #include <string.h>
// #include <memory.h>
#include <stdlib.h>
#include <tasking.h>
#include <string.h>
#include <memory.h>
#include <grub/multiboot.h>
// #include "klog.h"
// #include "elf.h"
// #include <errno.h>
// #include "../drivers/ide.h"
// #include "parts.h"
// #include "../fs/ext2.h"
// #include <stdint.h>
//
// static long initrd_sz;
// static char* initrd;
// static multiboot_info_t* mbd;
// typedef int (*func_ptr)();
#include "klog.h"
#include "elf.h"
#include <errno.h>
#include "../drivers/ide.h"
#include "parts.h"
#include "../fs/ext2.h"
#include <stdint.h>
static long initrd_sz;
static char* initrd;
static multiboot_info_t* mbd;
typedef int (*func_ptr)();
//
// static int console_dev_drv(char* filename,int c,long pos,char wr) {
// if (wr) {
@ -76,7 +76,7 @@
// for(;;) {}
// }
// }
//
// static void init() {
// init_vfs();
// init_devfs();
@ -136,8 +136,8 @@
// }
void kmain(multiboot_info_t* header) {
// mbd=header;
// cpu_init(mbd);
mbd=header;
cpu_init(mbd);
text_fb_info info;
// if (header->flags&MULTIBOOT_INFO_FRAMEBUFFER_INFO&&header->framebuffer_type==2) {
// info.address=(char*)(((uint32_t)header->framebuffer_addr&0xFFFFFFFF)+0xC0000000);

View File

@ -1 +1 @@
/Users/peterterpstra/x86_64-elf/bin/x86_64-elf-gcc -mcmodel=large
/Users/peterterpstra/x86_64-elf/bin/x86_64-elf-gcc -mcmodel=large -mno-red-zone