summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorMichal Idziorek <m.i@gmx.at>2015-05-16 03:48:35 +0200
committerMichal Idziorek <m.i@gmx.at>2015-05-16 03:48:35 +0200
commitf92a23a2fcee6cbb97af9c7681e6872374d3c789 (patch)
tree41669345c8a5a60548e8e07cf805df9ef01c1c26 /kernel
parentba10657752ba869b1c46c861cbda689b535e8214 (diff)
finally working ring 3
Diffstat (limited to 'kernel')
-rw-r--r--kernel/GDT.c136
-rw-r--r--kernel/interrupts.c50
-rw-r--r--kernel/kernel.c25
-rw-r--r--kernel/task.c11
-rw-r--r--kernel/usermode.c99
-rw-r--r--kernel/usermode.h1
-rw-r--r--kernel/vmem.c6
7 files changed, 274 insertions, 54 deletions
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 <stdint.h>
+#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<GDT_SIZE;i++)
+ encodeGdtEntry(&gdt_struct[8*i],myGDT[i]);
+
+
+ // updat
+ install_tss();
+ setup_gdt(&gdt_struct[0],8*GDT_SIZE);
+
+
+}
diff --git a/kernel/interrupts.c b/kernel/interrupts.c
index 51d8f8e..a7e021c 100644
--- a/kernel/interrupts.c
+++ b/kernel/interrupts.c
@@ -7,6 +7,18 @@
#include "console.h"
#include "x86.h"
+void errlog(uint32_t error_code)
+{
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"error_code: 0x%08X",error_code);
+}
+
+void deflog(uint32_t eip, uint16_t cs, uint32_t flags)
+{
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"eip: 0x%08X",eip);
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"segment: 0x%08X",cs);
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"eflags: 0x%08X",flags);
+}
+
void int_install_ir(int irq, uint16_t flags, uint16_t sel, void *addr);
//void mouse_handler();
@@ -36,17 +48,6 @@ void exception_handle()
panic(FOOLOS_MODULE_NAME,"exception interrupt");
}
-void exception_handle_14(uint32_t error_code)
-{
- log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"error_code: 0x%08X",error_code);
- log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"error_code_P: %d",error_code&1);
- log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"error_code_W/R: %d",error_code&2);
- log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"error_code_U/S: %d",error_code&4);
- log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"error_code_RSVD: %d",error_code&8);
- log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"error_code_I/D: %d",error_code&16);
- log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"at addr: 0x%08X",x86_get_cr2());
- panic(FOOLOS_MODULE_NAME,"page fault !");
-}
void int_default()
{
log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"default handler");
@@ -76,15 +77,26 @@ void exception_handle_10(){ panic(FOOLOS_MODULE_NAME,"Invalid TSS"); }
void exception_handle_11(){ panic(FOOLOS_MODULE_NAME,"Segment Not Present"); }
void exception_handle_12(){ panic(FOOLOS_MODULE_NAME,"Stack Segment Overrun"); }
-void exception_handle_13()
+void exception_handle_13(uint32_t error_code,uint32_t eip,uint16_t cs,uint16_t unused, uint32_t flags)
{
-
- uint32_t err;
- asm("pop %eax"); // get Error Code
- asm ("mov %%eax, %0":"=r"(err));
- show_error(err);
+ errlog(error_code);
+ deflog(eip,cs,flags);
+
+ panic(FOOLOS_MODULE_NAME,"Exception: Fault: General Protection Fault");
+}
- panic(FOOLOS_MODULE_NAME,"General Protection Fault");
+void exception_handle_14(uint32_t error_code,uint32_t eip,uint16_t cs,uint16_t unused, uint32_t flags)
+{
+ errlog(error_code);
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"error_code_P: %d",error_code&1?1:0);
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"error_code_W/R: %d",error_code&2?1:0);
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"error_code_U/S: %d",error_code&4?1:0);
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"error_code_RSVD: %d",error_code&8?1:0);
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"error_code_I/D: %d",error_code&16?1:0);
+ log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"at addr: 0x%08X",x86_get_cr2());
+
+ deflog(eip,cs,flags);
+ panic(FOOLOS_MODULE_NAME,"Exception: Fault: Page Fault");
}
void exception_handle_15(){ panic(FOOLOS_MODULE_NAME,"Unassigned"); }
@@ -158,7 +170,7 @@ void int_init(uint16_t sel)
// int_install_ir(44, 0b10001110, 0x08,&mouse_handler);
//system calls
- int_install_ir(0x80, 0b10001110, 0x08,&int_syscall_handler);
+ int_install_ir(0x80, 0b11101110, 0x08,&int_syscall_handler);
int_install();
diff --git a/kernel/kernel.c b/kernel/kernel.c
index 7b29730..2ce84fb 100644
--- a/kernel/kernel.c
+++ b/kernel/kernel.c
@@ -4,7 +4,6 @@
#error "Watchout! this is not Linux but FoolOS. Use a cross-compiler"
#endif
-
#include "kernel.h"
#include <stdint.h>
@@ -18,7 +17,6 @@
#include "interrupts.h"
#include "multiboot.h"
-
#include "console.h"
#include <stddef.h>
@@ -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;