Annotation of prex-old/sys/arch/i386/i386/cpu.c, Revision 1.1.1.1.2.1
1.1 nbrk 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 <kernel.h>
35: #include <page.h>
36: #include <cpu.h>
37: #include <locore.h>
38:
39: typedef void (*trapfn_t)(void);
40:
41: /*
42: * Descriptors
43: */
44: static struct seg_desc gdt[NGDTS];
45: static struct gate_desc idt[NIDTS];
46: static struct tss tss;
47:
48: /*
49: * Interrupt table
50: */
51: static const trapfn_t intr_table[] = {
52: intr_0, intr_1, intr_2, intr_3, intr_4, intr_5, intr_6,
53: intr_7, intr_8, intr_9, intr_10, intr_11, intr_12, intr_13,
54: intr_14, intr_15
55: };
56:
57: /*
58: * Trap table
59: */
60: static const trapfn_t trap_table[] = {
61: trap_0, trap_1, trap_2, trap_3, trap_4, trap_5, trap_6,
62: trap_7, trap_8, trap_9, trap_10, trap_11, trap_12, trap_13,
63: trap_14, trap_15, trap_16, trap_17, trap_18
64: };
65: #define NTRAPS (int)(sizeof(trap_table) / sizeof(void *))
66:
67: /*
68: * Set kernel stack pointer in TSS (task state segment).
69: * An actual value of the register is automatically set when
70: * CPU enters kernel mode next time.
71: */
72: void
1.1.1.1.2.1! nbrk 73: tss_set(uint32_t kstack)
1.1 nbrk 74: {
75:
76: tss.esp0 = kstack;
77: }
78:
79: /*
80: * tss_get() returns current esp0 value for trap handler.
81: */
1.1.1.1.2.1! nbrk 82: uint32_t
1.1 nbrk 83: tss_get(void)
84: {
85:
86: return tss.esp0;
87: }
88:
89: /*
90: * Set GDT (global descriptor table) members into specified vector
91: */
92: static void
1.1.1.1.2.1! nbrk 93: gdt_set(int vec, void *base, size_t limit, int type, u_int size)
1.1 nbrk 94: {
95: struct seg_desc *seg = &gdt[vec];
96:
97: if (limit > 0xfffff) {
98: limit >>= 12;
99: size |= SIZE_4K;
100: }
101: seg->limit_lo = limit;
1.1.1.1.2.1! nbrk 102: seg->base_lo = (u_int)base & 0xffff;
! 103: seg->base_mid = ((u_int)base >> 16) & 0xff;
1.1 nbrk 104: seg->limit_hi = limit >> 16;
1.1.1.1.2.1! nbrk 105: seg->base_hi = (u_int)base >> 24;
! 106: seg->type = (u_int)type | ST_PRESENT;
1.1 nbrk 107: seg->size = size;
108: }
109:
110: /*
111: * Set IDT (interrupt descriptor table) members into specified vector
112: */
113: static void
1.1.1.1.2.1! nbrk 114: idt_set(int vec, trapfn_t off, u_int sel, int type)
1.1 nbrk 115: {
116: struct gate_desc *gate = &idt[vec];
117:
1.1.1.1.2.1! nbrk 118: gate->offset_lo = (u_int)off & 0xffff;
1.1 nbrk 119: gate->selector = sel;
120: gate->nr_copy = 0;
1.1.1.1.2.1! nbrk 121: gate->type = (u_int)type | ST_PRESENT;
! 122: gate->offset_hi = (u_int)off >> 16;
1.1 nbrk 123: }
124:
125: /*
126: * Setup the GDT and load it.
127: */
128: static void
129: gdt_init(void)
130: {
131: struct desc_p gdt_p;
132:
133: /* Set system vectors */
134: gdt_set(KERNEL_CS / 8, 0, 0xffffffff, ST_KERN | ST_CODE_R, SIZE_32);
135: gdt_set(KERNEL_DS / 8, 0, 0xffffffff, ST_KERN | ST_DATA_W, SIZE_32);
136: gdt_set(USER_CS / 8, 0, 0xffffffff, ST_USER | ST_CODE_R, SIZE_32);
137: gdt_set(USER_DS / 8, 0, 0xffffffff, ST_USER | ST_DATA_W, SIZE_32);
138:
139: /* Clear TSS Busy */
140: gdt[KERNEL_TSS / 8].type &= ~ST_TSS_BUSY;
141:
142: /* Load GDT */
1.1.1.1.2.1! nbrk 143: gdt_p.limit = (uint16_t)(sizeof(gdt) - 1);
! 144: gdt_p.base = (uint32_t)&gdt;
1.1 nbrk 145: lgdt(&gdt_p);
146: }
147:
148: /*
149: * Setup the interrupt descriptor table and load it.
150: *
151: * IDT layout:
152: * 0x00 - 0x12 ... S/W trap
153: * 0x13 - 0x1f ... Intel reserved
154: * 0x20 - 0x3f ... H/W interrupt
155: * 0x40 ... System call trap
156: */
157: static void
158: idt_init(void)
159: {
160: struct desc_p idt_p;
161: int i;
162:
163: /* Fill all vectors with default handler */
164: for (i = 0; i < NIDTS; i++)
165: idt_set(i, trap_default, KERNEL_CS, ST_KERN | ST_TRAP_GATE);
166:
167: /* Setup trap handlers */
168: for (i = 0; i < NTRAPS; i++)
169: idt_set(i, trap_table[i], KERNEL_CS, ST_KERN | ST_TRAP_GATE);
170:
171: /* Setup interrupt handlers */
172: for (i = 0; i < 16; i++)
173: idt_set(0x20 + i, intr_table[i], KERNEL_CS,
174: ST_KERN | ST_INTR_GATE);
175:
176: /* Setup debug trap */
177: idt_set(3, trap_3, KERNEL_CS, ST_USER | ST_TRAP_GATE);
178:
179: /* Setup system call handler */
180: idt_set(SYSCALL_INT, syscall_entry, KERNEL_CS,
181: ST_USER | ST_TRAP_GATE);
182:
183: /* Load IDT */
1.1.1.1.2.1! nbrk 184: idt_p.limit = (uint16_t)(sizeof(idt) - 1);
! 185: idt_p.base = (uint32_t)&idt;
1.1 nbrk 186: lidt(&idt_p);
187: }
188:
189: /*
190: * Initialize the task state segment.
191: * Only one static TSS is used for all contexts.
192: */
193: static void
194: tss_init(void)
195: {
196:
197: gdt_set(KERNEL_TSS / 8, &tss, sizeof(struct tss) - 1,
198: ST_KERN | ST_TSS, 0);
199: /* Setup TSS */
200: memset(&tss, 0, sizeof(struct tss));
201: tss.ss0 = KERNEL_DS;
1.1.1.1.2.1! nbrk 202: tss.esp0 = (uint32_t)phys_to_virt(BOOT_STACK + 0x800 - 1);
! 203: tss.cs = (uint32_t)USER_CS | 3;
! 204: tss.ds = tss.es = tss.ss = tss.fs = tss.gs = (uint32_t)USER_CS | 3;
1.1 nbrk 205: tss.io_bitmap_offset = INVALID_IO_BITMAP;
206: ltr(KERNEL_TSS);
207: }
208:
209: /*
210: * Set trap handler for GDB
211: */
212: void
1.1.1.1.2.1! nbrk 213: trap_set(int vec, void (*handler)(void))
1.1 nbrk 214: {
215: struct desc_p idt_p;
216:
217: idt_set(vec, (trapfn_t)handler, KERNEL_CS, ST_KERN | ST_TRAP_GATE);
1.1.1.1.2.1! nbrk 218: idt_p.limit = (uint16_t)(sizeof(idt) - 1);
! 219: idt_p.base = (uint32_t)&idt;
1.1 nbrk 220: lidt(&idt_p);
221: }
222:
223: /*
224: * Initialize CPU state.
225: * Setup segment and interrupt descriptor.
226: */
227: void
228: cpu_init(void)
229: {
230:
231: /* Enable write protection from kernel code */
232: set_cr0(get_cr0() | CR0_WP);
233:
234: /*
235: * Setup flag register.
236: * Interrupt disable, clear direction, clear nested
237: * task, i/o privilege 0
238: */
239: set_eflags(get_eflags() & ~(EFL_IF | EFL_DF | EFL_NT | EFL_IOPL));
240:
241: /*
242: * Initialize descriptors.
243: * Setup segment and interrupt descriptor.
244: */
245: gdt_init();
246: idt_init();
247: tss_init();
248: }
CVSweb