Project

General

Profile

Statistics
| Branch: | Revision:

scoutos / prex-0.9.0 / bsp / hal / x86 / arch / cpu.c @ 03e9c04a

History | View | Annotate | Download (5.63 KB)

1 03e9c04a Brad Neuman
/*-
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
}