diff --git a/src/x86/interrupts.c b/src/x86/interrupts.c index 37fe8b6..4b02a3c 100644 --- a/src/x86/interrupts.c +++ b/src/x86/interrupts.c @@ -30,13 +30,39 @@ struct gdt_entry_t unsigned int available : 1; unsigned int long_mode : 1; unsigned int big : 1; - unsigned int gran : 1; + unsigned int granularity : 1; unsigned int base_high : 8; } __attribute__ ((packed)); -struct tss_t +struct tss_entry_t { - + uint32_t prev_tss; + uint32_t esp0; + uint32_t ss0; + uint32_t esp1; + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; + uint32_t cs; + uint32_t ss; + uint32_t ds; + uint32_t fs; + uint32_t gs; + uint32_t ldt; + uint16_t trap; + uint16_t iomap_base; }; struct interrupt_descriptor_t @@ -49,7 +75,7 @@ struct interrupt_descriptor_t uint16_t dpl : 2; uint16_t present : 1; uint16_t offset_2; -}; +} __attribute__ ((packed)); struct descriptor_table_info_t { @@ -57,8 +83,6 @@ struct descriptor_table_info_t void *location; } __attribute__ ((packed)); -struct tss_t tss; - void load_gdt(struct gdt_entry_t *gdt) { struct descriptor_table_info_t gdt_info; @@ -87,6 +111,15 @@ void load_idt(struct interrupt_descriptor_t *idt) : "r"(&idt_info)); } +void load_tr(uint16_t gdt_offset) +{ + gdt_offset |= 3; + asm("mov %0, %%ax; " + "ltr %%ax; " + : + : "r"(gdt_offset)); +} + void create_interrupt_descriptor(struct interrupt_descriptor_t *descriptor, void *isr, enum isr_type_t type, uint32_t privilage) { descriptor->offset_1 = (uint32_t) isr & 0xFFFF; @@ -118,7 +151,7 @@ void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size descriptor->available = 0; descriptor->long_mode = 0; descriptor->big = 1; - descriptor->gran = 1; + descriptor->granularity = 1; break; case SEGMENT_KERNEL_DATA: descriptor->accessed = 0; @@ -130,7 +163,7 @@ void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size descriptor->available = 0; descriptor->long_mode = 0; descriptor->big = 1; - descriptor->gran = 1; + descriptor->granularity = 1; break; case SEGMENT_USER_CODE: descriptor->accessed = 0; @@ -142,7 +175,7 @@ void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size descriptor->available = 0; descriptor->long_mode = 0; descriptor->big = 1; - descriptor->gran = 1; + descriptor->granularity = 1; break; case SEGMENT_USER_DATA: descriptor->accessed = 0; @@ -154,7 +187,7 @@ void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size descriptor->available = 0; descriptor->long_mode = 0; descriptor->big = 1; - descriptor->gran = 1; + descriptor->granularity = 1; break; case SEGMENT_TSS: descriptor->accessed = 1; @@ -166,20 +199,25 @@ void create_segment_descriptor(struct gdt_entry_t *descriptor, size_t base, size descriptor->available = 0; descriptor->long_mode = 0; descriptor->big = 0; - descriptor->gran = 0; + descriptor->granularity = 0; } } void initialize_gdt() { static struct gdt_entry_t gdt[gdt_size]; + static struct tss_entry_t tss; 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); + create_segment_descriptor(&gdt[5], (size_t)&tss, sizeof(struct tss_entry_t) - 1, SEGMENT_TSS); + memset(&tss, 0, sizeof(tss)); + tss.esp0 = 0xFF800000; + tss.ss0 = 0x10; load_gdt(gdt); + load_tr(5 * sizeof(struct gdt_entry_t)); } void initialize_idt() @@ -191,9 +229,10 @@ void initialize_idt() 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[EXCEPTION_GPF], (void*)isr_gp_fault, INTERRPUT_TRAP32, 0); + create_interrupt_descriptor(&idt[EXCEPTION_PAGE_FAULT], (void*)isr_page_fault, INTERRPUT_TRAP32, 0); + create_interrupt_descriptor(&idt[EXCEPTION_DOUBLE_FAULT], (void*)isr_double_fault, INTERRPUT_TRAP32, 0); + create_interrupt_descriptor(&idt[ISR_PREEMPT], (void*)isr_preempt, 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); diff --git a/src/x86/interrupts.h b/src/x86/interrupts.h index 13c01a8..3b78343 100644 --- a/src/x86/interrupts.h +++ b/src/x86/interrupts.h @@ -25,6 +25,7 @@ enum interrupt_code_t EXCEPTION_VIRTUALIZATION = 20, EXCEPTION_SECURITY = 30, ISR_APIC_TIMER = 64, + ISR_PREEMPT = 65, ISR_AP_START = 127, ISR_SYSCALL = 128 };