POK(kernelpart)
/home/jaouen/pok_official/pok/trunk/kernel/arch/x86/space.c
Go to the documentation of this file.
00001 /*
00002  *                               POK header
00003  * 
00004  * The following file is a part of the POK project. Any modification should
00005  * made according to the POK licence. You CANNOT use this file or a part of
00006  * this file is this part of a file for your own project
00007  *
00008  * For more information on the POK licence, please see our LICENCE FILE
00009  *
00010  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
00011  *
00012  *                                      Copyright (c) 2007-2009 POK team 
00013  *
00014  * Created by julien on Thu Jan 15 23:34:13 2009 
00015  */
00016 
00017 
00024 #include <types.h>
00025 #include <errno.h>
00026 #include <libc.h>
00027 #include <bsp.h>
00028 
00029 #include <arch.h>
00030 
00031 #include <arch/x86/interrupt.h>
00032 
00033 #include "gdt.h"
00034 #include "tss.h"
00035 
00036 #include "space.h"
00037 
00038 #define KERNEL_STACK_SIZE 8192
00039 
00040 pok_ret_t pok_create_space (uint8_t partition_id,
00041                             uint32_t addr,
00042                             uint32_t size)
00043 {
00044    gdt_set_segment (GDT_PARTITION_CODE_SEGMENT (partition_id),
00045          addr, size, GDTE_CODE, 3);
00046 
00047    gdt_set_segment (GDT_PARTITION_DATA_SEGMENT (partition_id),
00048          addr, size, GDTE_DATA, 3);
00049 
00050    return (POK_ERRNO_OK);
00051 }
00052 
00053 pok_ret_t pok_space_switch (uint8_t old_partition_id,
00054                             uint8_t new_partition_id)
00055 {
00056    gdt_disable (GDT_PARTITION_CODE_SEGMENT(old_partition_id));
00057    gdt_disable (GDT_PARTITION_DATA_SEGMENT(old_partition_id));
00058    gdt_enable (GDT_PARTITION_CODE_SEGMENT(new_partition_id));
00059    gdt_enable (GDT_PARTITION_DATA_SEGMENT(new_partition_id));
00060 
00061    return (POK_ERRNO_OK);
00062 }
00063 
00064 uint32_t        pok_space_base_vaddr (uint32_t addr)
00065 {
00066    (void) addr;
00067    return (0);
00068 }
00069 
00070 uint32_t        pok_space_context_create (uint8_t  partition_id,
00071                                    uint32_t entry_rel,
00072                                    uint32_t stack_rel,
00073                                    uint32_t arg1,
00074                                    uint32_t arg2)
00075 {
00076    char*             stack_addr;
00077    space_context_t*  sp;
00078    
00079    stack_addr = pok_bsp_mem_alloc (KERNEL_STACK_SIZE);
00080 
00081    sp = (space_context_t *)
00082       (stack_addr + KERNEL_STACK_SIZE - 4 - sizeof (space_context_t));
00083 
00084    memset (sp, 0, sizeof (space_context_t));
00085 
00086    sp->ctx.__esp  = (uint32_t)(&sp->ctx.eip); /* for pusha */
00087    sp->ctx.eip    = (uint32_t)pok_dispatch_space;
00088    sp->ctx.cs     = GDT_CORE_CODE_SEGMENT << 3;
00089    sp->ctx.eflags = 1 << 9;
00090 
00091    sp->arg1          = arg1;
00092    sp->arg2          = arg2;
00093    sp->kernel_sp     = (uint32_t)sp;
00094    sp->user_sp       = stack_rel;
00095    sp->user_pc       = entry_rel;
00096    sp->partition_id  = partition_id;
00097 
00098    return ((uint32_t) sp);
00099 }
00100 
00101 #ifdef POK_NEEDS_ERROR_HANDLING
00102 void pok_space_context_restart (uint32_t sp, uint32_t entry, uint32_t user_stack)
00103 {
00104    space_context_t* ct;
00105 
00106    ct = (space_context_t*) sp;
00107    ct->ctx.__esp  = (uint32_t)(&ct->ctx.eip); /* for pusha */
00108    ct->ctx.eip    = (uint32_t)pok_dispatch_space;
00109    ct->user_pc = entry;
00110    ct->user_sp = user_stack;
00111 }
00112 #endif
00113 
00114 void pok_dispatch_space (uint8_t partition_id,
00115                          uint32_t user_pc,
00116                          uint32_t user_sp,
00117                          uint32_t kernel_sp,
00118                          uint32_t arg1,
00119                          uint32_t arg2)
00120 {
00121    interrupt_frame   ctx;
00122    uint32_t          code_sel;
00123    uint32_t          data_sel;
00124    uint32_t          sp;
00125 
00126    code_sel = GDT_BUILD_SELECTOR (GDT_PARTITION_CODE_SEGMENT (partition_id), 0, 3);
00127    data_sel = GDT_BUILD_SELECTOR (GDT_PARTITION_DATA_SEGMENT (partition_id), 0, 3);
00128 
00129    sp = (uint32_t) &ctx;
00130 
00131    memset (&ctx, 0, sizeof (interrupt_frame));
00132 
00133    pok_arch_preempt_disable ();
00134 
00135    ctx.es = ctx.ds = ctx.ss = data_sel;
00136 
00137    ctx.__esp   = (uint32_t) (&ctx.error); /* for pusha */
00138    ctx.eip     = user_pc;
00139    ctx.eax     = arg1;
00140    ctx.ebx     = arg2;
00141    ctx.cs      = code_sel;
00142    ctx.eflags  = 1 << 9;
00143    ctx.esp     = user_sp;
00144 
00145    tss_set_esp0 (kernel_sp);
00146 
00147    asm ("mov %0, %%esp          \n"
00148         "pop %%es               \n"
00149         "pop %%ds               \n"
00150         "popa                   \n"
00151         "addl $4, %%esp         \n"
00152         "iret                   \n"
00153         :
00154         : "m" (sp)
00155        );
00156 }