POK(kernelpart)
/home/jaouen/pok_official/pok/trunk/kernel/arch/x86/gdt.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 
00018 #include <libc.h>
00019 
00020 #include <types.h>
00021 #include <errno.h>
00022 
00023 #include "gdt.h"
00024 #include "sysdesc.h"
00025 #include "tss.h"
00026 
00027 #ifndef POK_NEEDS_THREADS
00028 #define POK_CONFIG_NB_THREADS 0
00029 #endif
00030 
00031 #ifndef POK_NEEDS_PARTITIONS
00032 #define POK_CONFIG_NB_PARTITIONS 0
00033 #endif
00034 
00035 #define GDT_SIZE 256
00036 
00037 gdt_entry_t     pok_gdt[GDT_SIZE];
00038 
00039 tss_t           pok_tss;
00040 
00041 pok_ret_t pok_gdt_init()
00042 {
00043    sysdesc_t sysdesc;
00044 
00045    /* Set null descriptor and clear table */
00046    memset(pok_gdt, 0, sizeof (gdt_entry_t) * GDT_SIZE);
00047 
00048    /* Set kernel descriptors */
00049    gdt_set_segment(GDT_CORE_CODE_SEGMENT, 0, ~0UL, GDTE_CODE, 0);
00050    gdt_set_segment(GDT_CORE_DATA_SEGMENT, 0, ~0UL, GDTE_DATA, 0);
00051 
00052    /* Load GDT */
00053    sysdesc.limit = sizeof (pok_gdt);
00054    sysdesc.base = (uint32_t)pok_gdt;
00055 
00056    asm ("lgdt %0"
00057          :
00058          : "m" (sysdesc));
00059 
00060    /* Reload Segments */
00061    asm ("ljmp %0, $1f   \n"
00062          "1:            \n"
00063          "mov %1, %%ax  \n"
00064          "mov %%ax, %%ds        \n"
00065          "mov %%ax, %%es        \n"
00066          "mov %%ax, %%fs        \n"
00067          "mov %%ax, %%gs        \n"
00068          "mov %%ax, %%ss        \n"
00069          :
00070          : "i" (GDT_CORE_CODE_SEGMENT << 3),
00071          "i" (GDT_CORE_DATA_SEGMENT << 3)
00072          : "eax");
00073 
00074    pok_tss_init();
00075 
00076    return (POK_ERRNO_OK);
00077 }
00078 
00079 int pok_tss_init()
00080 {
00081    uint16_t sel = GDT_BUILD_SELECTOR(GDT_TSS_SEGMENT, 0, 0);
00082 
00083    memset(&pok_tss, 0, sizeof (tss_t));
00084 
00085    pok_tss.ss0 = GDT_BUILD_SELECTOR(GDT_CORE_DATA_SEGMENT, 0, 0);
00086 
00087    gdt_set_system(GDT_TSS_SEGMENT, (uint32_t)&pok_tss,
00088          sizeof (tss_t), GDTE_TSS, 0);
00089 
00090    asm ("ltr %0" : :"m"(sel));
00091    return (POK_ERRNO_OK);
00092 }
00093 
00094 void tss_set_esp0(uint32_t esp0)
00095 {
00096    pok_tss.esp0 = esp0;
00097 }
00098 
00099 void gdt_set_segment(uint16_t index,
00100       uint32_t base_address,
00101       uint32_t limit,
00102       e_gdte_type t,
00103       int dpl)
00104 {
00105    if (limit > (1 << 20)) /* 4K granularity */
00106    {
00107       pok_gdt[index].limit_low = (limit >> 12) & 0xFFFF;
00108       pok_gdt[index].limit_high = (limit >> 28) & 0xF;
00109       pok_gdt[index].granularity = 1;
00110    }
00111    else /* 1B granularity */
00112    {
00113       pok_gdt[index].limit_low = limit & 0xFFFF;
00114       pok_gdt[index].limit_high = (limit >> 16) & 0xFF;
00115       pok_gdt[index].granularity = 0;
00116    }
00117 
00118    pok_gdt[index].base_low = base_address & 0xFFFFFF;
00119    pok_gdt[index].base_high = (base_address >> 24) & 0xFF;
00120 
00121    pok_gdt[index].type = t & 0xF;
00122    pok_gdt[index].dpl = dpl & 0x3;
00123 
00124    pok_gdt[index].s = 1;                      /* Segment is data/code type */
00125    pok_gdt[index].present = 1;
00126    pok_gdt[index].available = 0;
00127    pok_gdt[index].op_size = 1;        /* We work on 32 bits segments */
00128 }
00129 
00130 void gdt_set_system(uint16_t index,
00131       uint32_t base_address,
00132       uint32_t limit,
00133       e_gdte_type t,
00134       int dpl)
00135 {
00136    pok_gdt[index].limit_low = limit & 0xFFFF;
00137    pok_gdt[index].limit_high = (limit >> 16) & 0xFF;
00138    pok_gdt[index].base_low = base_address & 0xFFFFFF;
00139    pok_gdt[index].base_high = (base_address >> 24) & 0xFF;
00140 
00141    pok_gdt[index].type = t & 0xF;
00142    pok_gdt[index].dpl = dpl & 0x3;
00143 
00144    pok_gdt[index].s = 0;                      /* Segment is system type */
00145    pok_gdt[index].present = 1;
00146    pok_gdt[index].available = 0;
00147    pok_gdt[index].op_size = 0;
00148 }
00149 
00150 void gdt_enable(uint16_t index)
00151 {
00152    pok_gdt[index].present = 1;
00153 }
00154 
00155 void gdt_disable(uint16_t index)
00156 {
00157    pok_gdt[index].present = 0;
00158 }
00159 
00160 /*
00161  * DEPRECATED
00162  *
00163 uint32_t        gdt_segment_base(uint16_t idx)
00164 {
00165    uint32_t base;
00166 
00167    base = pok_gdt[idx].base_low | (pok_gdt[idx].base_high << 24);
00168 
00169    return base;
00170 }
00171 */
00172