|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/bsp/hal/x86/arch/cpu.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.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] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |