diff --git a/src/boot/boot.S b/src/boot/boot.S index ba25a84..0092567 100644 --- a/src/boot/boot.S +++ b/src/boot/boot.S @@ -4,6 +4,8 @@ .extern gdt_memcpy .extern mb_load_fb_tag +.set STACK_LOCATION, 0x50000 + .section .multiboot .set MB_MAGIC, 0xE85250D6 @@ -65,7 +67,7 @@ cs_new: # Update stack segment movw $0x18, %ax movw %ax, %ss -movl $0x50000,%esp +movl $STACK_LOCATION,%esp # Load mov $0x38, %eax diff --git a/src/bringelle.c b/src/bringelle.c index 5fd315b..8faaecc 100644 --- a/src/bringelle.c +++ b/src/bringelle.c @@ -2,10 +2,15 @@ #include "utils/pic.h" #include "boot/multiboot.h" #include "utils/mem.h" +#include "utils/gdt.h" char show_tics=0; +extern GDT_TSS TSS; + void utask(){ + char msg[]="Message from the task :D"; + asm("mov $0x1, %%eax;int $0x30"::"b"(msg)); while(1); } @@ -15,14 +20,33 @@ void bringelle(){ // Kernel boot sequence pic_enable_interrupt(); - print("Interrupts enabled!\n"); - + print("Interrupts enabled\n"); + print("Kernel started !\n"); // Utask - memcpy((void*)utask,(void*)0x300000, 100); // 100 bytes seems reasonable to load utask - - print("Kernel started "); + print("Launch user task "); show_tics=1; + memcpy((void*)utask,(void*)0x300000, 100); // 100 bytes seems reasonable to load utask + 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 $0x400000 \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 $0 \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) + ); + while(1); } diff --git a/src/utils/gdt.c b/src/utils/gdt.c index fd86f5f..c380283 100644 --- a/src/utils/gdt.c +++ b/src/utils/gdt.c @@ -5,7 +5,7 @@ struct GDT_REGISTER GDTR = { 0, 0 }; GDT_TSS TSS; void gdt_memcpy(){ - GDTR.limit=8*8; // Each entry is 8 bytes and 8 entries + GDTR.limit=8*GDT_MAX_ENTRIES; // Each entry is 8 bytes and 8 entries GDTR.base=0x800; gdt_write_entry((GDT_ENTRY){0,0,0,0},0); // First one must be null @@ -60,12 +60,10 @@ void gdt_memcpy(){ // Init TSS segment TSS.t_reserved=0; TSS.io_map=0; - TSS.ss0=0x18; - TSS.esp0=0x50000; GDT_ENTRY tss_desc; tss_desc.base=(u32)&TSS; // Not used in stack descriptor - tss_desc.limit=0x68; // Define how much entry it can contains + tss_desc.limit=0x68; // Define how much bytes it occupies tss_desc.flags=0; tss_desc.access=0x89 | GDT_PRVL_3; // Note that 0x89 is specific to TSS! gdt_write_entry(tss_desc, 7); @@ -89,3 +87,12 @@ void gdt_write_entry(GDT_ENTRY entry, u32 id){ // Copy descriptor into memory memcpy(descriptor,(void*)GDTR.base+8*id,8); // Each entry is 64 bits (8 bytes) } + +int gdt_user_ds_base(){ + char *addr=(char*)GDTR.base+48; + int *base0_15=(int*)addr+2; + int *base16_31=(int*)addr+7; + int base0_15_content=*base0_15 & 0xFFFF; + int base16_21_content=*base16_31 & 0xFFFF; + return(base16_21_content<<16 & base0_15_content); +} \ No newline at end of file diff --git a/src/utils/gdt.h b/src/utils/gdt.h index 01a01bf..f010891 100644 --- a/src/utils/gdt.h +++ b/src/utils/gdt.h @@ -3,6 +3,8 @@ #include "types.h" +#define GDT_MAX_ENTRIES 8 + // Access byte #define GDT_AC 1 // Access bit #define GDT_RW 1 << 1 // Read/Write bit @@ -70,4 +72,6 @@ void gdt_memcpy(); */ void gdt_write_entry(GDT_ENTRY entry, u32 id); +int gdt_user_ds_base(); + #endif diff --git a/src/utils/pic.c b/src/utils/pic.c index f811d04..7681a13 100644 --- a/src/utils/pic.c +++ b/src/utils/pic.c @@ -1,6 +1,7 @@ #include "pic.h" #include "asm.h" #include "mem.h" +#include "syscall.h" struct IDT_REGISTER IDTR={ 200*8, @@ -9,32 +10,65 @@ struct IDT_REGISTER IDTR={ /// Bridge between IDT and functions call asm ( -"PIC_IRQ_DEFAULT:" +".macro SAVE_REGS \n\t" + "pushal \n\t" + "push %ds \n\t" + "push %es \n\t" + "push %fs \n\t" + "push %gs \n\t" + "push %ebx \n\t" + "mov $0x10,%bx \n\t" + "mov %bx,%ds \n\t" + "pop %ebx \n\t" +".endm \n\t" +".macro RESTORE_REGS \n\t" + "pop %gs \n\t" + "pop %fs \n\t" + "pop %es \n\t" + "pop %ds \n\t" + "popal \n\t" +".endm \n\t" +"PIC_IRQ_DEFAULT: \n\t" + "SAVE_REGS \n\t" "movb $0x20, %al \n\t" "outb %al, $0x20 \n\t" + "RESTORE_REGS \n\t" "iret \n\t" "PIC_IRQ_PRINT: \n\t" + "SAVE_REGS \n\t" "call _8042_keypress \n\t" "movb $0x20, %al \n\t" "outb %al, $0x20 \n\t" + "RESTORE_REGS \n\t" "iret \n\t" "PIC_IRQ_CLOCK: \n\t" + "SAVE_REGS \n\t" "call clock \n\t" "movb $0x20, %al \n\t" "outb %al, $0x20 \n\t" + "RESTORE_REGS \n\t" + "iret \n\t" +"PIC_IRQ_SYSCALL: \n\t" + "SAVE_REGS \n\t" + "call syscall \n\t" + "movb $0x20, %al \n\t" + "outb %al, $0x20 \n\t" + "RESTORE_REGS \n\t" "iret \n\t" ); -extern u32 PIC_IRQ_DEFAULT,PIC_IRQ_PRINT,PIC_IRQ_CLOCK; +extern u32 PIC_IRQ_DEFAULT,PIC_IRQ_PRINT,PIC_IRQ_CLOCK, PIC_IRQ_SYSCALL; void pic_enable_interrupt(){ // Map first default 32 entries for(int i=0;i<200;i++){ - pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_DEFAULT,IDT_TYPE_1},i); + pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_DEFAULT,IDT_INT_GATE},i); if(i==32) - pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_CLOCK,IDT_TYPE_1},i); + pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_CLOCK,IDT_INT_GATE},i); if(i==33) - pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_PRINT,IDT_TYPE_1},i); + pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_PRINT,IDT_INT_GATE},i); + if(i==48) + pic_add_idt_entry((IDT_ENTRY){0x08,(u32)&PIC_IRQ_SYSCALL,IDT_TRAP_GATE},i); } // Now configure 8952A diff --git a/src/utils/pic.h b/src/utils/pic.h index 2734437..5ee1ab2 100644 --- a/src/utils/pic.h +++ b/src/utils/pic.h @@ -3,7 +3,8 @@ #include "types.h" -#define IDT_TYPE_1 0x8E00 +#define IDT_INT_GATE 0x8E00 +#define IDT_TRAP_GATE 0xEF00 typedef struct IDT_ENTRY { u16 segment;