From 6138766c49443c11b45a8d61fc3a741564e1145d Mon Sep 17 00:00:00 2001 From: ngiddings Date: Fri, 16 Apr 2021 01:45:40 -0500 Subject: [PATCH] Added sequence to remap PIC Wrote GDT code in C Added routines to initialize GDT and IDT --- src/x86/apic.c | 22 ++++++ src/x86/entry.S | 34 +-------- src/x86/interrupts.c | 178 ++++++++++++++++++++++++++++++++++++++++++- src/x86/interrupts.h | 16 +--- src/x86/isr.c | 14 +++- src/x86/isr.h | 3 + src/x86/quark_x86.c | 30 ++------ 7 files changed, 223 insertions(+), 74 deletions(-) diff --git a/src/x86/apic.c b/src/x86/apic.c index c725790..399ab41 100644 --- a/src/x86/apic.c +++ b/src/x86/apic.c @@ -1,12 +1,34 @@ #include "mmgr.h" #include "apic.h" #include "msr.h" +#include "stdio.h" #include extern int _kernel_end; void apic_enable(struct page_stact_t *page_stack) { + // Remap and mask 8259 PIC + asm volatile( + "mov $0x11, %%al;" + "outb %%al, $0x20;" + "outb %%al, $0xA0;" + "mov $0x20, %%al;" + "outb %%al, $0x21;" + "mov $0x28, %%al;" + "outb %%al, $0xA1;" + "mov $4, %%al;" + "outb %%al, $0x21;" + "mov $2, %%al;" + "outb %%al, $0xA1;" + "mov $0x01, %%al;" + "outb %%al, $0x21;" + "outb %%al, $0xA1;" + "mov $0xFF, %%al;" + "outb %%al, $0xA1;" + "outb %%al, $0x21;" + ::: "al" + ); struct msr_apic_base_t msr; read_msr(MSR_APIC_BASE, (uint64_t*)&msr); map_page(page_stack, &_kernel_end, msr.apic_base << 12, 0); diff --git a/src/x86/entry.S b/src/x86/entry.S index 6ec1c8b..bb4a2ed 100755 --- a/src/x86/entry.S +++ b/src/x86/entry.S @@ -93,23 +93,6 @@ _multibootInfoTagEnd: .long 8 _multibootHeaderEnd: - -.section .rodata - -gdt: -.long 0, 0 -.short 0xFFFF -.short 0x0000 -.short 0x9A00 -.short 0x00CF -.short 0xFFFF -.short 0x0000 -.short 0x9200 -.short 0x00CF - -gdt_info: -.short 23 -.long gdt .section .bss @@ -170,7 +153,7 @@ _start: push %eax # Load physical address of startPaging() - mov $startPaging, %eax + mov $start_paging, %eax sub $BASE_DIFF, %eax # Initialize paging @@ -180,8 +163,6 @@ _start: lea 1f, %eax jmp *%eax 1: - # Delete PDE corresponding to identity map. We shouldn't need it anymore. - movl $0, (_tempIdentityMap) # Flush TLB mov %cr3, %eax @@ -190,19 +171,6 @@ _start: # Initialize stack in virtual memory mov $stackTop, %esp - # Load GPT - lgdt gdt_info - - # Load segment registers - jmp $8, $.ldcs -.ldcs: - mov $16, %ax - mov %ax, %ds - mov %ax, %es - mov %ax, %gs - mov %ax, %fs - mov %ax, %ss - # Change EBX to point to the virtual address of the multiboot info # If the new pointer is out-of-bounds, error add $0xFF800000, %ebx diff --git a/src/x86/interrupts.c b/src/x86/interrupts.c index aadce4a..37fe8b6 100644 --- a/src/x86/interrupts.c +++ b/src/x86/interrupts.c @@ -1,14 +1,85 @@ #include "interrupts.h" +#include "isr.h" +#include "string.h" +#include -struct idt_info_t +#define idt_size 256 +#define gdt_size 6 + +enum segment_type_t +{ + SEGMENT_KERNEL_CODE, + SEGMENT_KERNEL_DATA, + SEGMENT_USER_CODE, + SEGMENT_USER_DATA, + SEGMENT_TSS +}; + +struct gdt_entry_t +{ + unsigned int limit_low : 16; + unsigned int base_low : 24; + unsigned int accessed : 1; + unsigned int read_write : 1; + unsigned int conforming_expand_down : 1; + unsigned int code : 1; + unsigned int code_data_segment : 1; + unsigned int dpl : 2; + unsigned int present : 1; + unsigned int limit_high : 4; + unsigned int available : 1; + unsigned int long_mode : 1; + unsigned int big : 1; + unsigned int gran : 1; + unsigned int base_high : 8; +} __attribute__ ((packed)); + +struct tss_t +{ + +}; + +struct interrupt_descriptor_t +{ + uint16_t offset_1; + uint16_t selector; + uint16_t zero : 8; + uint16_t type : 4; + uint16_t storage : 1; + uint16_t dpl : 2; + uint16_t present : 1; + uint16_t offset_2; +}; + +struct descriptor_table_info_t { uint16_t size; void *location; } __attribute__ ((packed)); -void lidt(struct interrupt_descriptor_t *idt) +struct tss_t tss; + +void load_gdt(struct gdt_entry_t *gdt) { - struct idt_info_t idt_info; + struct descriptor_table_info_t gdt_info; + gdt_info.size = sizeof(struct gdt_entry_t) * 6 - 1; + gdt_info.location = (void *)gdt; + asm("lgdt (%0);" + "jmp $8, $.ldcs;" + ".ldcs:;" + "mov $16, %%ax;" + "mov %%ax, %%ds;" + "mov %%ax, %%es;" + "mov %%ax, %%gs;" + "mov %%ax, %%fs;" + "mov %%ax, %%ss;" + : + : "r"(&gdt_info)); +} + +void load_idt(struct interrupt_descriptor_t *idt) +{ + struct descriptor_table_info_t idt_info; idt_info.size = sizeof(struct interrupt_descriptor_t) * 256 - 1; idt_info.location = (void *)idt; asm("lidt (%0)" @@ -27,3 +98,104 @@ void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void descriptor->dpl = privilage; descriptor->present = 1; } + +void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size_t limit, enum segment_type_t type) +{ + descriptor->limit_low = limit; + descriptor->limit_high = (limit & (0xf << 16)) >> 16; + descriptor->base_low = base; + descriptor->base_high = (base & (0xff << 24)) >> 24; + descriptor->present = 1; + switch(type) + { + case SEGMENT_KERNEL_CODE: + descriptor->accessed = 0; + descriptor->read_write = 1; + descriptor->conforming_expand_down = 0; + descriptor->code = 1; + descriptor->code_data_segment = 1; + descriptor->dpl = 0; + descriptor->available = 0; + descriptor->long_mode = 0; + descriptor->big = 1; + descriptor->gran = 1; + break; + case SEGMENT_KERNEL_DATA: + descriptor->accessed = 0; + descriptor->read_write = 1; + descriptor->conforming_expand_down = 0; + descriptor->code = 0; + descriptor->code_data_segment = 1; + descriptor->dpl = 0; + descriptor->available = 0; + descriptor->long_mode = 0; + descriptor->big = 1; + descriptor->gran = 1; + break; + case SEGMENT_USER_CODE: + descriptor->accessed = 0; + descriptor->read_write = 1; + descriptor->conforming_expand_down = 0; + descriptor->code = 1; + descriptor->code_data_segment = 1; + descriptor->dpl = 3; + descriptor->available = 0; + descriptor->long_mode = 0; + descriptor->big = 1; + descriptor->gran = 1; + break; + case SEGMENT_USER_DATA: + descriptor->accessed = 0; + descriptor->read_write = 1; + descriptor->conforming_expand_down = 0; + descriptor->code = 0; + descriptor->code_data_segment = 1; + descriptor->dpl = 3; + descriptor->available = 0; + descriptor->long_mode = 0; + descriptor->big = 1; + descriptor->gran = 1; + break; + case SEGMENT_TSS: + descriptor->accessed = 1; + descriptor->read_write = 0; + descriptor->conforming_expand_down = 0; + descriptor->code = 1; + descriptor->code_data_segment = 0; + descriptor->dpl = 3; + descriptor->available = 0; + descriptor->long_mode = 0; + descriptor->big = 0; + descriptor->gran = 0; + } +} + +void initialize_gdt() +{ + static struct gdt_entry_t gdt[gdt_size]; + memset(gdt, 0, sizeof(struct gdt_entry_t) * gdt_size); + create_segment_descriptor(&gdt[1], 0, 0xFFFFF, SEGMENT_KERNEL_CODE); + create_segment_descriptor(&gdt[2], 0, 0xFFFFF, SEGMENT_KERNEL_DATA); + create_segment_descriptor(&gdt[3], 0, 0xFFFFF, SEGMENT_USER_CODE); + create_segment_descriptor(&gdt[4], 0, 0xFFFFF, SEGMENT_USER_DATA); + //create_segment_descriptor(&gdt[5], (size_t)&tss, sizeof(struct tss_t), SEGMENT_TSS); + load_gdt(gdt); +} + +void initialize_idt() +{ + static struct interrupt_descriptor_t idt[idt_size]; + memset(idt, 0, sizeof(struct interrupt_descriptor_t) * idt_size); + for(int i = 0; i < idt_size; i++) + { + create_interrupt_descriptor(&idt[i], (void*)isr_generic, INTERRPUT_INT32, 0); + } + create_interrupt_descriptor(&idt[EXCEPTION_DIV_BY_0], (void*)isr_division_by_zero, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[EXCEPTION_GPF], (void*)isr_gp_fault, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], (void*)isr_double_fault, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[ISR_APIC_TIMER], (void*)isr_timer, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[ISR_AP_START], (void*)isr_ap_start, INTERRPUT_INT32, 0); + create_interrupt_descriptor(&idt[ISR_SYSCALL], (void*)isr_syscall, INTERRPUT_INT32, 0); + load_idt(idt); +} diff --git a/src/x86/interrupts.h b/src/x86/interrupts.h index 96db47c..13c01a8 100644 --- a/src/x86/interrupts.h +++ b/src/x86/interrupts.h @@ -38,18 +38,6 @@ enum isr_type_t INTERRPUT_INT16 = 6 }; -struct interrupt_descriptor_t -{ - uint16_t offset_1; - uint16_t selector; - uint16_t zero : 8; - uint16_t type : 4; - uint16_t storage : 1; - uint16_t dpl : 2; - uint16_t present : 1; - uint16_t offset_2; -}; +void initialize_gdt(); -void lidt(struct interrupt_descriptor_t *idt); - -void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage); +void initialize_idt(); diff --git a/src/x86/isr.c b/src/x86/isr.c index 339a1f8..80fd862 100644 --- a/src/x86/isr.c +++ b/src/x86/isr.c @@ -2,6 +2,12 @@ #include "stdio.h" #include "apic.h" +__attribute__ ((interrupt)) +void isr_generic(void* frame) +{ + printf("Generic interrupt.\n"); +} + __attribute__ ((interrupt)) void isr_division_by_zero(void* frame) { @@ -11,18 +17,22 @@ void isr_division_by_zero(void* frame) __attribute__ ((interrupt)) void isr_gp_fault(void* frame, unsigned int error) { - + asm("cli"); + printf("Exception: GP fault, code %08x\n", error); + asm("hlt"); } __attribute__ ((interrupt)) void isr_page_fault(void* frame, unsigned int error) { - + printf("Exception: Page fault\n"); } __attribute__ ((interrupt)) void isr_double_fault(void* frame, unsigned int error) { + asm("cli"); + printf("Exception: Double fault (!!), code %08x\n", error); asm("hlt"); } diff --git a/src/x86/isr.h b/src/x86/isr.h index 272e224..c5a3914 100644 --- a/src/x86/isr.h +++ b/src/x86/isr.h @@ -1,5 +1,8 @@ #pragma once +__attribute__ ((interrupt)) +void isr_generic(void* frame); + __attribute__ ((interrupt)) void isr_division_by_zero(void* frame); diff --git a/src/x86/quark_x86.c b/src/x86/quark_x86.c index 69c3618..474fa5e 100644 --- a/src/x86/quark_x86.c +++ b/src/x86/quark_x86.c @@ -17,7 +17,7 @@ extern int _kernel_end; struct apic_registers_t volatile *apic_registers; -int startPaging(uint32_t *directory, uint32_t *table, uint32_t *identityTable) +int start_paging(uint32_t *directory, uint32_t *table, uint32_t *identityTable) { for (int i = 0; i < 1024; i++) { @@ -42,8 +42,9 @@ int startPaging(uint32_t *directory, uint32_t *table, uint32_t *identityTable) int initialize(void *multiboot_info) { + initialize_gdt(); + initialize_idt(); printf("***%s***\n", PACKAGE_STRING); - static struct interrupt_descriptor_t idt[256]; static struct page_stack_t page_stack; static struct kernel_t kernel; struct memory_region_t map_array[16]; @@ -76,33 +77,18 @@ int initialize(void *multiboot_info) { load_module(&kernel, &boot_info.modules[i]); } - memset(idt, 0, sizeof(struct interrupt_descriptor_t) * 256); - create_interrupt_descriptor(&idt[EXCEPTION_DIV_BY_0], (void*)isr_division_by_zero, INTERRPUT_INT32, 0); - create_interrupt_descriptor(&idt[EXCEPTION_GPF], (void*)isr_gp_fault, INTERRPUT_INT32, 0); - create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_INT32, 0); - create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], (void*)isr_double_fault, INTERRPUT_INT32, 0); - create_interrupt_descriptor(&idt[ISR_APIC_TIMER], (void*)isr_timer, INTERRPUT_INT32, 0); - create_interrupt_descriptor(&idt[ISR_AP_START], (void*)isr_ap_start, INTERRPUT_INT32, 0); - create_interrupt_descriptor(&idt[ISR_SYSCALL], (void*)isr_syscall, INTERRPUT_INT32, 0); - lidt(idt); - asm volatile( - "mov $0xFF, %%al;" - "outb %%al, $0xA1;" - "outb %%al, $0x21;" - ::: "al" - ); apic_enable(page_stack); - printf("spurious_interrupt_vector: %08x\n", *((uint32_t*) &apic_registers->spurious_iv)); - printf("lvt_timer_vector: %08x\n", *((uint32_t*) &apic_registers->lvt_timer)); - apic_registers->divide_config.value = APIC_DIVIDE_128; apic_registers->lvt_timer.vector = ISR_APIC_TIMER; apic_registers->lvt_timer.timer_mode = APIC_TIMER_PERIODIC; - apic_registers->initial_count.value = 1024*1024*512; + apic_registers->initial_count.value = 1024*1024*1024; apic_registers->lvt_timer.mask = 0; printf("spurious_interrupt_vector: %08x\n", *((uint32_t*) &apic_registers->spurious_iv)); printf("lvt_timer_vector: %08x\n", *((uint32_t*) &apic_registers->lvt_timer)); asm("sti"); - while(1) asm("hlt"); + while(1) + { + asm("hlt"); + } // TODO: enter first process }