From f92a23a2fcee6cbb97af9c7681e6872374d3c789 Mon Sep 17 00:00:00 2001 From: Michal Idziorek Date: Sat, 16 May 2015 03:48:35 +0200 Subject: finally working ring 3 --- kernel/GDT.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/interrupts.c | 50 +++++++++++-------- kernel/kernel.c | 25 +++++++--- kernel/task.c | 11 +++-- kernel/usermode.c | 99 +++++++++++++++++++++++++++++--------- kernel/usermode.h | 1 - kernel/vmem.c | 6 +++ 7 files changed, 274 insertions(+), 54 deletions(-) create mode 100644 kernel/GDT.c (limited to 'kernel') diff --git a/kernel/GDT.c b/kernel/GDT.c new file mode 100644 index 0000000..4bc7ca2 --- /dev/null +++ b/kernel/GDT.c @@ -0,0 +1,136 @@ +// http://wiki.osdev.org/GDT_Tutorial +#include "lib/logger/log.h" +#include "usermode.h" +#define FOOLOS_MODULE_NAME "GDT" + +#include +#define GDT_SIZE 6 + +extern sys_tss; + +typedef struct GDT_struct +{ + uint32_t base; + uint32_t limit; + uint32_t type; + +}GDT; + +//alternative +struct gdt_entry_bits +{ + unsigned int limit_low:16; + unsigned int base_low : 24; + //attribute byte split into bitfields + unsigned int accessed :1; + unsigned int read_write :1; //readable for code, writable for data + unsigned int conforming_expand_down :1; //conforming for code, expand down for data + unsigned int code :1; //1 for code, 0 for data + unsigned int always_1 :1; //should be 1 for everything but TSS and LDT + unsigned int DPL :2; //priveledge level + unsigned int present :1; + //and now into granularity + unsigned int limit_high :4; + unsigned int available :1; + unsigned int always_0 :1; //should always be 0 + unsigned int big :1; //32bit opcodes for code, uint32_t stack for data + unsigned int gran :1; //1 to use 4k page addressing, 0 for byte addressing + unsigned int base_high :8; +} __packed; //or __attribute__((packed)) + + +static GDT myGDT[GDT_SIZE]; +static uint8_t gdt_struct[GDT_SIZE*8]; + +/** + * \param target A pointer to the 8-byte GDT entry + * \param source An arbitrary structure describing the GDT entry + */ +void encodeGdtEntry(uint8_t *target, GDT source) +{ + // Check the limit to make sure that it can be encoded + if ((source.limit > 65536) && (source.limit & 0xFFF) != 0xFFF) + { + panic(FOOLOS_MODULE_NAME,"trying to set an invalid GDT source.limit!"); + } + if (source.limit > 65536) { + // Adjust granularity if required + source.limit = source.limit >> 12; + target[6] = 0xC0; + } else { + target[6] = 0x40; + } + + // Encode the limit + target[0] = source.limit & 0xFF; + target[1] = (source.limit >> 8) & 0xFF; + + // Encode the base + target[2] = source.base & 0xFF; + target[3] = (source.base >> 8) & 0xFF; + target[4] = (source.base >> 16) & 0xFF; + target[7] = (source.base >> 24) & 0xFF; + + target[5] = source.type; + target[6] |= (source.limit >> 16) & 0xF; + + // And... Type + + /* + +0 1 dw 0xffff ;limit +2 3 dw 0x0 ;base +4 db 0x0 ;base +5 db 10011010b ;flags +6 db 11001111b ;flags & seg.limit +7 db 0x0 ;base + */ + + +} + +void gdt_setup() +{ + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"setting up Global Descriptor Table"); + //selector 0x0 + myGDT[0].base=0; + myGDT[0].limit=0; + myGDT[0].type=0; + + //selector 0x8 code + myGDT[1].base=0; + myGDT[1].limit=0xffffffff; + myGDT[1].type=0x9a; + + //selector 0x10 data + myGDT[2].base=0; + myGDT[2].limit=0xffffffff; + myGDT[2].type=0x92; + + //selector 0x18 code user + myGDT[3].base=0; + myGDT[3].limit=0xffffffff; + myGDT[3].type=0xFa; + + //selector 0x20 data user + myGDT[4].base=0; + myGDT[4].limit=0xffffffff; + myGDT[4].type=0xF2; + + //TSS 0x28 + myGDT[5].base=&sys_tss; //tss start? + myGDT[5].limit=sizeof(tss_struct); //tss end? + myGDT[5].type=0x89; + + + // transcript to format the processor wants + for(int i=0;i @@ -18,7 +17,6 @@ #include "interrupts.h" #include "multiboot.h" - #include "console.h" #include @@ -29,6 +27,7 @@ #include "video/vesa.h" #include "multiboot.h" + void kernel_main(uint32_t eax,uint32_t ebx) { @@ -37,21 +36,31 @@ void kernel_main(uint32_t eax,uint32_t ebx) // console_init(); + // // PR // log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"%s - compiled on %s at %s",KERNEL_VERSION,__DATE__,__TIME__); + // // Configuring the PIT timer. // timer_init(); + + // + // GDT + // + gdt_setup(); + + // // Process Multiboot Header // multiboot_information *info=get_multiboot(eax, ebx); + // // Memory Init // @@ -60,17 +69,20 @@ void kernel_main(uint32_t eax,uint32_t ebx) // uint32_t kernel_blocks=mem_init(info); + + // // Activate Virtual Memory (paging) // pdirectory *dir=vmem_init(kernel_blocks); + // // Setup Interrupts (code segment: 0x08) // - int_init(0x08); + // // Scan the PCI Bus // @@ -98,23 +110,22 @@ void kernel_main(uint32_t eax,uint32_t ebx) //smp_log_procdata(&procdata); //smp_start_aps(&procdata,0x80000); // starts at 0x80000 // but it will be copied over mbr + // // Mount Root EXT2 ramimage // - fs_mount(info); // // Initialize Multitasking // - task_init(dir); + // - // Abvoe should never return + // Abvoe should never returon // - panic(FOOLOS_MODULE_NAME,"reached end of kernel.c !!"); } diff --git a/kernel/task.c b/kernel/task.c index 1474a64..000dc74 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -82,6 +82,7 @@ volatile uint32_t my_scheduler(uint32_t oldesp) // this gets called by our clock interrupt regularly! volatile uint32_t task_switch_next(uint32_t oldesp) { + asm volatile("sti"); timer_tick(); @@ -146,12 +147,12 @@ volatile uint32_t task_fork(uint32_t oldesp) return pid; } -char *argv_init[]={"/bin/init",NULL}; -char *env_init[]={NULL}; // init task (root of all other tasks / processes) // volatile void task_init(pdirectory *dir) { + + // this is our main task on slot 0 task_list[0].parent=0; task_list[0].active=true; @@ -159,10 +160,12 @@ volatile void task_init(pdirectory *dir) task_list[0].vmem=dir; task_list[0].esp = 0; // will be set by next task_switch_next() call. current_task=0; + + + switch_to_user_mode(); - syscall_execve("/bin/init",argv_init,env_init); //syscall_execve("/bin/foolshell",argv_init,env_init); -// syscall_execve("/bin/tput",argv,env); + //syscall_execve("/bin/tput",argv,env); } diff --git a/kernel/usermode.c b/kernel/usermode.c index afad9df..339045d 100644 --- a/kernel/usermode.c +++ b/kernel/usermode.c @@ -1,32 +1,85 @@ #include "usermode.h" +#define FOOLOS_MODULE_NAME "usermode" +#include "lib/logger/log.h" +#include "syscalls.h" +tss_struct sys_tss; //Define the TSS as a global structure + + +// generic syscall interface! +int syscall(int call, int p1, int p2, int p3) +{ + int ebx; // will hold return value; + + asm("pusha"); + + // select syscall + asm("mov %0, %%eax"::"m"(call)); + + // pass params + asm("mov %0,%%edx"::"m"(p1)); + asm("mov %0,%%ecx"::"m"(p2)); + asm("mov %0,%%ebx"::"m"(p3)); + + // interrrupt + asm("int $0x80"); + + // get return value + asm("mov %%ebx, %0": "=b" (ebx)); + + asm("popa"); + + return ebx; +} +int write(int file, char *ptr, int len) +{ + return syscall(SYSCALL_WRITE,file,ptr,len); +} +int execve(char *name, char **argv, char **env) +{ + return syscall(SYSCALL_EXECVE,name,argv,env); +} + void install_tss(int cpu_no){ + // now fill each value // set values necessary - sys_tss.ss0 = 0x10; - // now set the IO bitmap (not necessary, so set above limit) - sys_tss.iomap = ( unsigned short ) sizeof( tss_struct ); + sys_tss.ss0 = 0x10; //kernel data + sys_tss.esp0 = 0x9000; //kernel stack + + // now set the IO bitmap (not necessary, so set above limit) + // sys_tss.iomap = ( unsigned short ) sizeof( tss_struct ); +} + + +void switch_to_user_mode() +{ + char text[]="internal"; + write(1,text,10); + asm_usermode(); + while(1); // will not be reached? } -void switch_to_user_mode() { - // Set up a stack structure for switching to user mode. - asm volatile(" \ - cli; \ - mov $0x23, %ax; \ - mov %ax, %ds; \ - mov %ax, %es; \ - mov %ax, %fs; \ - mov %ax, %gs; \ - \ - mov %esp, %eax; \ - pushl $0x23; \ - pushl %eax; \ - pushf; \ - mov $0x200, %eax; \ - push %eax; \ - pushl $0x1B; \ - push $1f; \ - iret; \ 1: \ - "); +char *argv_init[]={"/bin/init",NULL}; +char *env_init[]={NULL}; + +// THIS WILL BE RUN IN RING 3! +void userfunc() +{ + + execve("/bin/init",argv_init,env_init); + + for(int i=0;i<3;i++) + { + log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"we are usermode!"); + } + + + while(1) + { + + char text[]="syscalling!"; + write(1,text,10); + } } diff --git a/kernel/usermode.h b/kernel/usermode.h index e9195e1..fafad5b 100644 --- a/kernel/usermode.h +++ b/kernel/usermode.h @@ -43,4 +43,3 @@ typedef volatile struct strtss{ unsigned short iomap; }__attribute__((packed)) tss_struct; -tss_struct sys_tss; //Define the TSS as a global structure diff --git a/kernel/vmem.c b/kernel/vmem.c index a8e4008..f49689f 100644 --- a/kernel/vmem.c +++ b/kernel/vmem.c @@ -277,6 +277,7 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir) pt_entry page=0; pt_entry_add_attrib (&page, I86_PTE_PRESENT); pt_entry_add_attrib (&page, I86_PTE_WRITABLE); + pt_entry_add_attrib (&page, I86_PTE_USER); pt_entry_set_frame (&page, frame); //! ...and add it to the page table @@ -287,6 +288,7 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir) *entry=0; pd_entry_add_attrib (entry, I86_PDE_PRESENT); pd_entry_add_attrib (entry, I86_PDE_WRITABLE); + pt_entry_add_attrib (entry, I86_PTE_USER); pd_entry_set_frame (entry, (physical_addr)table); } @@ -344,6 +346,7 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir) pt_entry page=0; pt_entry_add_attrib (&page, I86_PTE_PRESENT); pt_entry_add_attrib (&page, I86_PTE_WRITABLE); + pt_entry_add_attrib (&page, I86_PTE_USER); pt_entry_set_frame (&page, frame); @@ -356,6 +359,7 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir) *entry=0; pd_entry_add_attrib (entry, I86_PDE_PRESENT); pd_entry_add_attrib (entry, I86_PDE_WRITABLE); + pt_entry_add_attrib (entry, I86_PTE_USER); pd_entry_set_frame (entry, (physical_addr)table); virt_addr+=1024*4096; @@ -401,6 +405,7 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir) pt_entry page=0; pt_entry_add_attrib (&page, I86_PTE_PRESENT); pt_entry_add_attrib (&page, I86_PTE_WRITABLE); + pt_entry_add_attrib (&page, I86_PTE_USER); pt_entry_set_frame (&page, frame); @@ -413,6 +418,7 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir) *entry=0; pd_entry_add_attrib (entry, I86_PDE_PRESENT); pd_entry_add_attrib (entry, I86_PDE_WRITABLE); + pt_entry_add_attrib (entry, I86_PTE_USER); pd_entry_set_frame (entry, (physical_addr)table); virt_addr+=1024*4096; -- cgit v1.2.3