#include "libc/stdio.h" #include "gdt.h" #include "mem.h" #include "paging.h" char show_tics=0; void schedule(){ } void clock(){ static int tic=0; static int sec=0; tic++; if(tic>=20){ tic=0; sec++; if(show_tics) putchar('.'); } schedule(); } void run_task(int *page_dir, void *task, int task_size){ // Compute various addresses int*pt_addr=(int*)PADDR(page_dir[1]); void *entry_point=(void*)(PADDR(pt_addr[3])); void *ustack=(void*)((int)entry_point+0xFF); // Load the task into memory memcpy(task,entry_point, task_size); // Load page directory asm( "mov %0, %%eax \n\t" "mov %%eax,%%cr3 \n\t" :: "b"(page_dir) ); // Setup users adresses // Switch to user task asm ( "cli \n\t" // Ensure we do not get interrupted "movl %%ss, %%eax \n\t" "movl %%eax, %0 \n\t" // Save kernel ss segment into the TSS "movl %%esp, %1 \n\t" // Save kernel esp into the TSS BEFORE setting up the stack "pushl $0x33 \n\t" // Push task ss which is 0x30 along with prlv which is 0x3 "pushl %2 \n\t" // Push task esp "pushfl \n\t" // Retrieve flags "popl %%eax \n\t" "orl $0x200, %%eax \n\t" // Enable interrupt for the user task "and $0xffffbfff, %%eax \n\t" // Clear the NT flags "push %%eax \n\t" // Push task flags "push $0x23 \n\t" // Push task cs which is 0x20 along with prlv which is 0x3 "push %3 \n\t" // Push task entry point "mov $0x2B, %%eax \n\t" // GDT entry 0x28 along with prlv which is 0x3 "mov %%eax, %%ds \n\t" // Setting up user data segment "iret \n\t" // Launch user task : "=m" (TSS.ss0), "=m" (TSS.esp0) : "b" (ustack), "c" (entry_point) ); }