Prex Home / Browse Source - Prex Version: 0.9.0

root/bsp/hal/x86/arch/cpu.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tss_set
  2. tss_get
  3. gdt_set
  4. idt_set
  5. gdt_init
  6. idt_init
  7. tss_init
  8. cpu_init

   1 /*-
   2  * Copyright (c) 2005-2007, Kohsuke Ohtani
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. Neither the name of the author nor the names of any co-contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 /*
  31  * cpu.c - cpu dependent routines for Intel x86
  32  */
  33 
  34 #include <machine/syspage.h>
  35 #include <kernel.h>
  36 #include <cpu.h>
  37 #include <locore.h>
  38 #include <cpufunc.h>
  39 
  40 typedef void (*trapfn_t)(void);
  41 
  42 /*
  43  * Descriptors
  44  */
  45 static struct seg_desc gdt[NGDTS];
  46 static struct gate_desc idt[NIDTS];
  47 static struct tss tss;
  48 
  49 /*
  50  * Interrupt table
  51  */
  52 static const trapfn_t intr_table[] = {
  53         intr_0, intr_1, intr_2, intr_3, intr_4, intr_5, intr_6,
  54         intr_7, intr_8, intr_9, intr_10, intr_11, intr_12, intr_13,
  55         intr_14, intr_15
  56 };
  57 
  58 /*
  59  * Trap table
  60  */
  61 static const trapfn_t trap_table[] = {
  62         trap_0, trap_1, trap_2, trap_3, trap_4, trap_5, trap_6,
  63         trap_7, trap_8, trap_9, trap_10, trap_11, trap_12, trap_13,
  64         trap_14, trap_15, trap_16, trap_17, trap_18
  65 };
  66 #define NTRAPS  (int)(sizeof(trap_table) / sizeof(void *))
  67 
  68 /*
  69  * Set kernel stack pointer in TSS (task state segment).
  70  * An actual value of the register is automatically set when
  71  * CPU enters kernel mode next time.
  72  */
  73 void
  74 tss_set(uint32_t kstack)
  75 {
  76 
  77         tss.esp0 = kstack;
  78 }
  79 
  80 /*
  81  * tss_get() returns current esp0 value for trap handler.
  82  */
  83 uint32_t
  84 tss_get(void)
  85 {
  86 
  87         return tss.esp0;
  88 }
  89 
  90 /*
  91  * Set GDT (global descriptor table) members into specified vector
  92  */
  93 static void
  94 gdt_set(int vec, void *base, size_t limit, int type, u_int size)
  95 {
  96         struct seg_desc *seg = &gdt[vec];
  97 
  98         if (limit > 0xfffff) {
  99                 limit >>= 12;
 100                 size |= SIZE_4K;
 101         }
 102         seg->limit_lo = limit;
 103         seg->base_lo = (u_int)base & 0xffff;
 104         seg->base_mid = ((u_int)base >> 16) & 0xff;
 105         seg->limit_hi = limit >> 16;
 106         seg->base_hi = (u_int)base >> 24;
 107         seg->type = (u_int)type | ST_PRESENT;
 108         seg->size = size;
 109 }
 110 
 111 /*
 112  * Set IDT (interrupt descriptor table) members into specified vector
 113  */
 114 static void
 115 idt_set(int vec, trapfn_t off, u_int sel, int type)
 116 {
 117         struct gate_desc *gate = &idt[vec];
 118 
 119         gate->offset_lo = (u_int)off & 0xffff;
 120         gate->selector = sel;
 121         gate->nr_copy = 0;
 122         gate->type = (u_int)type | ST_PRESENT;
 123         gate->offset_hi = (u_int)off >> 16;
 124 }
 125 
 126 /*
 127  * Setup the GDT and load it.
 128  */
 129 static void
 130 gdt_init(void)
 131 {
 132         struct desc_p gdt_p;
 133 
 134         /* Set system vectors */
 135         gdt_set(KERNEL_CS / 8, 0, 0xffffffff, ST_KERN | ST_CODE_R, SIZE_32);
 136         gdt_set(KERNEL_DS / 8, 0, 0xffffffff, ST_KERN | ST_DATA_W, SIZE_32);
 137         gdt_set(USER_CS / 8, 0, 0xffffffff, ST_USER | ST_CODE_R, SIZE_32);
 138         gdt_set(USER_DS / 8, 0, 0xffffffff, ST_USER | ST_DATA_W, SIZE_32);
 139 
 140         /* Clear TSS Busy */
 141         gdt[KERNEL_TSS / 8].type &= ~ST_TSS_BUSY;
 142 
 143         /* Load GDT */
 144         gdt_p.limit = (uint16_t)(sizeof(gdt) - 1);
 145         gdt_p.base = (uint32_t)&gdt;
 146         load_gdt(&gdt_p);
 147 }
 148 
 149 /*
 150  * Setup the interrupt descriptor table and load it.
 151  *
 152  * IDT layout:
 153  *  0x00 - 0x12 ... S/W trap
 154  *  0x13 - 0x1f ... Intel reserved
 155  *  0x20 - 0x3f ... H/W interrupt
 156  *  0x40        ... System call trap
 157  */
 158 static void
 159 idt_init(void)
 160 {
 161         struct desc_p idt_p;
 162         int i;
 163 
 164         /* Fill all vectors with default handler */
 165         for (i = 0; i < NIDTS; i++)
 166                 idt_set(i, trap_default, KERNEL_CS, ST_KERN | ST_TRAP_GATE);
 167 
 168         /* Setup trap handlers */
 169         for (i = 0; i < NTRAPS; i++)
 170                 idt_set(i, trap_table[i], KERNEL_CS, ST_KERN | ST_TRAP_GATE);
 171 
 172         /* Setup interrupt handlers */
 173         for (i = 0; i < 16; i++)
 174                 idt_set(0x20 + i, intr_table[i], KERNEL_CS,
 175                         ST_KERN | ST_INTR_GATE);
 176 
 177         /* Setup debug trap */
 178         idt_set(3, trap_3, KERNEL_CS, ST_USER | ST_TRAP_GATE);
 179 
 180         /* Setup system call handler */
 181         idt_set(SYSCALL_INT, syscall_entry, KERNEL_CS,
 182                 ST_USER | ST_TRAP_GATE);
 183 
 184         /* Load IDT */
 185         idt_p.limit = (uint16_t)(sizeof(idt) - 1);
 186         idt_p.base = (uint32_t)&idt;
 187         load_idt(&idt_p);
 188 }
 189 
 190 /*
 191  * Initialize the task state segment.
 192  * Only one static TSS is used for all contexts.
 193  */
 194 static void
 195 tss_init(void)
 196 {
 197 
 198         gdt_set(KERNEL_TSS / 8, &tss, sizeof(struct tss) - 1,
 199                 ST_KERN | ST_TSS, 0);
 200         /* Setup TSS */
 201         memset(&tss, 0, sizeof(struct tss));
 202         tss.ss0 = KERNEL_DS;
 203         tss.esp0 = (uint32_t)BOOTSTKTOP;
 204         tss.cs = (uint32_t)USER_CS | 3;
 205         tss.ds = tss.es = tss.ss = tss.fs = tss.gs = (uint32_t)USER_CS | 3;
 206         tss.io_bitmap_offset = INVALID_IO_BITMAP;
 207         load_tr(KERNEL_TSS);
 208 }
 209 
 210 /*
 211  * Initialize CPU state.
 212  * Setup segment and interrupt descriptor.
 213  */
 214 void
 215 cpu_init(void)
 216 {
 217 
 218         /*
 219          * Initialize descriptors.
 220          * Setup segment and interrupt descriptor.
 221          */
 222         gdt_init();
 223         idt_init();
 224         tss_init();
 225 }

/* [<][>][^][v][top][bottom][index][help] */