void gdt_install(void) { gdt_ptr.limit = sizeof(gdt) - 1; gdt_ptr.base = (unsigned int)&gdt; memset(gdt, 0, sizeof(gdt)); // Kernel space gdt_set_gate(&gdt[GDT_KERNEL_CS].memseg, 0, 0xFFFFF, 0, 1); gdt_set_gate(&gdt[GDT_KERNEL_DS].memseg, 0, 0xFFFFF, 0, 0); // User space gdt_set_gate(&gdt[GDT_USER_CS].memseg, 0, 0xFFFFF, 3, 1); gdt_set_gate(&gdt[GDT_USER_DS].memseg, 0, 0xFFFFF, 3, 0); // IRQ, faults, thread gdt_set_tss(&gdt[GDT_HW_INT_TSS].tss, &kernel_tasks.tss_for_hw_int); gdt_set_tss(&gdt[GDT_PAGE_FAULT_TSS].tss, &kernel_tasks.tss_for_page_fault); gdt_set_tss(&gdt[GDT_DOUBLE_FAULT_TSS].tss, &kernel_tasks.tss_for_double_fault); gdt_set_tss(&gdt[GDT_ACTIVE_THREAD_TSS].tss, &kernel_tasks.tss_for_active_thread); asm_gdt_flush(&gdt_ptr); asm_set_tr(8 * GDT_ACTIVE_THREAD_TSS); }
/* This one get's called from the architecture-specific interrupt * handlers, which do fiddling like EOIs (i386). */ isf_t* __attribute__((fastcall)) interrupts_callback(uint32_t intr, isf_t* regs) { struct interrupt_reg reg = interrupt_handlers[intr]; task_t* task = scheduler_get_current(); #ifdef INTERRUPTS_DEBUG debug("state before:\n"); dump_isf(LOG_DEBUG, regs); #endif if(reg.handler) { if(reg.can_reent) { interrupts_enable(); } reg.handler(regs); } #ifdef ENABLE_PICOTCP if(intr == IRQ(0)) { net_tick(); } #endif // Run scheduler every 100th tick, or when task yields if((intr == IRQ(0) && !(timer_get_tick() % 100)) || (task && task->interrupt_yield)) { if((task && task->interrupt_yield)) { task->interrupt_yield = false; } task_t* new_task = scheduler_select(regs); if(new_task && new_task->state) { #ifdef INTERRUPTS_DEBUG debug("state after (task selection):\n"); dump_isf(LOG_DEBUG, new_task->state); #endif gdt_set_tss(new_task->kernel_stack + PAGE_SIZE); return new_task->state; } } #ifdef INTERRUPTS_DEBUG debug("state after:\n"); dump_isf(LOG_DEBUG, regs); #endif return regs; }
void gdt_init() { memset(&gdt_entries, 0, sizeof(gdt_entries)); gdt_set_gate(0, 0, 0, 0, 0); // 0x0 Null segment gdt_set_gate(1, 0, 0xFFFF, 0x98, 0x20); // 0x8 Kernel Code segment gdt_set_gate(2, 0, 0xFFFF, 0x90, 0x00); // 0x10 Kernel Data segment gdt_set_gate(3, 0, 0xFFFF, 0xF8, 0x20); // 0x18 User mode code segment gdt_set_gate(4, 0, 0xFFFF, 0xF0, 0x00); // 0x20 User mode data segment gdt_set_tss(); // 0x28 TSS64 gdt_ptr.limit = sizeof(gdt_entries) - 1; gdt_ptr.base = (u64)&gdt_entries; gdt_flush(&gdt_ptr); tss_flush(); }