source: mainline/kernel/arch/ia32/src/pm.c@ 0f17bff

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0f17bff was 0f17bff, checked in by Jakub Jermar <jakub@…>, 9 years ago

Replace magic numbers with macros

  • Property mode set to 100644
File size: 8.7 KB
Line 
1/*
2 * Copyright (c) 2001-2004 Jakub Jermar
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 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup ia32
30 * @{
31 */
32/** @file
33 */
34
35#include <arch/pm.h>
36#include <config.h>
37#include <typedefs.h>
38#include <arch/interrupt.h>
39#include <arch/asm.h>
40#include <arch/context.h>
41#include <panic.h>
42#include <arch/mm/page.h>
43#include <mm/km.h>
44#include <mm/frame.h>
45#include <mm/slab.h>
46#include <memstr.h>
47#include <arch/boot/boot.h>
48#include <interrupt.h>
49#include <arch/cpu.h>
50
51/*
52 * Early ia32 configuration functions and data structures.
53 */
54
55/*
56 * We don't have much use for segmentation so we set up flat mode.
57 * In this mode, we use, for each privilege level, two segments spanning the
58 * whole memory. One is for code and one is for data.
59 *
60 * One special segment apart of that is for the GS register which holds
61 * a pointer to the VREG page in its base.
62 */
63descriptor_t gdt[GDT_ITEMS] = {
64 [NULL_DES] = {
65 0
66 },
67 [KTEXT_DES] = {
68 .limit_0_15 = 0xffff,
69 .limit_16_19 = 0xf,
70 .access = AR_PRESENT | AR_CODE | DPL_KERNEL,
71 .special = 1,
72 .granularity = 1
73 },
74 [KDATA_DES] = {
75 .limit_0_15 = 0xffff,
76 .limit_16_19 = 0xf,
77 .access = AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_KERNEL,
78 .special = 1,
79 .granularity = 1
80 },
81 [UTEXT_DES] = {
82 .limit_0_15 = 0xffff,
83 .limit_16_19 = 0xf,
84 .access = AR_PRESENT | AR_CODE | DPL_USER,
85 .special = 1,
86 .granularity = 1
87 },
88 [UDATA_DES] = {
89 .limit_0_15 = 0xffff,
90 .limit_16_19 = 0xf,
91 .access = AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_USER,
92 .special = 1,
93 .granularity = 1
94 },
95 [TSS_DES] = { /* set up will be completed later */
96 0,
97 },
98 [VREG_DES] = { /* will be reinitialized later */
99 .limit_0_15 = 0xffff,
100 .limit_16_19 = 0xf,
101 .access = AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_USER,
102 .special = 1,
103 .granularity = 1
104 },
105 /* VESA Init descriptor */
106#ifdef CONFIG_FB
107 [VESA_INIT_CODE_DES] = {
108 .limit_0_15 = 0xffff,
109 .limit_16_19 = 0xf,
110 .base_16_23 = VESA_INIT_SEGMENT >> 12,
111 .access = AR_PRESENT | AR_CODE | AR_READABLE | DPL_KERNEL
112 },
113 [VESA_INIT_DATA_DES] = {
114 .limit_0_15 = 0xffff,
115 .limit_16_19 = 0xf,
116 .base_16_23 = VESA_INIT_SEGMENT >> 12,
117 .access = AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_KERNEL
118 }
119#endif
120};
121
122static idescriptor_t idt[IDT_ITEMS];
123
124static tss_t tss0;
125
126tss_t *tss_p = NULL;
127
128/* gdtr is changed by kmp before next CPU is initialized */
129ptr_16_32_t gdtr = {
130 .limit = sizeof(gdt),
131 .base = (uintptr_t) gdt
132};
133
134void gdt_setbase(descriptor_t *d, uintptr_t base)
135{
136 d->base_0_15 = base & 0xffff;
137 d->base_16_23 = (base >> 16) & 0xff;
138 d->base_24_31 = (base >> 24) & 0xff;
139}
140
141void gdt_setlimit(descriptor_t *d, uint32_t limit)
142{
143 d->limit_0_15 = limit & 0xffff;
144 d->limit_16_19 = (limit >> 16) & 0xf;
145}
146
147void idt_setoffset(idescriptor_t *d, uintptr_t offset)
148{
149 /*
150 * Offset is a linear address.
151 */
152 d->offset_0_15 = offset & 0xffff;
153 d->offset_16_31 = offset >> 16;
154}
155
156void tss_initialize(tss_t *t)
157{
158 memsetb(t, sizeof(tss_t), 0);
159}
160
161/*
162 * This function takes care of proper setup of IDT and IDTR.
163 */
164void idt_init(void)
165{
166 idescriptor_t *d;
167 unsigned int i;
168
169 for (i = 0; i < IDT_ITEMS; i++) {
170 d = &idt[i];
171
172 d->unused = 0;
173 d->selector = GDT_SELECTOR(KTEXT_DES);
174
175 if (i == VECTOR_SYSCALL) {
176 /*
177 * The syscall trap gate must be callable from
178 * userland. Interrupts will remain enabled.
179 */
180 d->access = AR_PRESENT | AR_TRAP | DPL_USER;
181 } else {
182 /*
183 * Other interrupts use interrupt gates which
184 * disable interrupts.
185 */
186 d->access = AR_PRESENT | AR_INTERRUPT;
187 }
188 }
189
190 d = &idt[0];
191 idt_setoffset(d++, (uintptr_t) &int_0);
192 idt_setoffset(d++, (uintptr_t) &int_1);
193 idt_setoffset(d++, (uintptr_t) &int_2);
194 idt_setoffset(d++, (uintptr_t) &int_3);
195 idt_setoffset(d++, (uintptr_t) &int_4);
196 idt_setoffset(d++, (uintptr_t) &int_5);
197 idt_setoffset(d++, (uintptr_t) &int_6);
198 idt_setoffset(d++, (uintptr_t) &int_7);
199 idt_setoffset(d++, (uintptr_t) &int_8);
200 idt_setoffset(d++, (uintptr_t) &int_9);
201 idt_setoffset(d++, (uintptr_t) &int_10);
202 idt_setoffset(d++, (uintptr_t) &int_11);
203 idt_setoffset(d++, (uintptr_t) &int_12);
204 idt_setoffset(d++, (uintptr_t) &int_13);
205 idt_setoffset(d++, (uintptr_t) &int_14);
206 idt_setoffset(d++, (uintptr_t) &int_15);
207 idt_setoffset(d++, (uintptr_t) &int_16);
208 idt_setoffset(d++, (uintptr_t) &int_17);
209 idt_setoffset(d++, (uintptr_t) &int_18);
210 idt_setoffset(d++, (uintptr_t) &int_19);
211 idt_setoffset(d++, (uintptr_t) &int_20);
212 idt_setoffset(d++, (uintptr_t) &int_21);
213 idt_setoffset(d++, (uintptr_t) &int_22);
214 idt_setoffset(d++, (uintptr_t) &int_23);
215 idt_setoffset(d++, (uintptr_t) &int_24);
216 idt_setoffset(d++, (uintptr_t) &int_25);
217 idt_setoffset(d++, (uintptr_t) &int_26);
218 idt_setoffset(d++, (uintptr_t) &int_27);
219 idt_setoffset(d++, (uintptr_t) &int_28);
220 idt_setoffset(d++, (uintptr_t) &int_29);
221 idt_setoffset(d++, (uintptr_t) &int_30);
222 idt_setoffset(d++, (uintptr_t) &int_31);
223 idt_setoffset(d++, (uintptr_t) &int_32);
224 idt_setoffset(d++, (uintptr_t) &int_33);
225 idt_setoffset(d++, (uintptr_t) &int_34);
226 idt_setoffset(d++, (uintptr_t) &int_35);
227 idt_setoffset(d++, (uintptr_t) &int_36);
228 idt_setoffset(d++, (uintptr_t) &int_37);
229 idt_setoffset(d++, (uintptr_t) &int_38);
230 idt_setoffset(d++, (uintptr_t) &int_39);
231 idt_setoffset(d++, (uintptr_t) &int_40);
232 idt_setoffset(d++, (uintptr_t) &int_41);
233 idt_setoffset(d++, (uintptr_t) &int_42);
234 idt_setoffset(d++, (uintptr_t) &int_43);
235 idt_setoffset(d++, (uintptr_t) &int_44);
236 idt_setoffset(d++, (uintptr_t) &int_45);
237 idt_setoffset(d++, (uintptr_t) &int_46);
238 idt_setoffset(d++, (uintptr_t) &int_47);
239 idt_setoffset(d++, (uintptr_t) &int_48);
240 idt_setoffset(d++, (uintptr_t) &int_49);
241 idt_setoffset(d++, (uintptr_t) &int_50);
242 idt_setoffset(d++, (uintptr_t) &int_51);
243 idt_setoffset(d++, (uintptr_t) &int_52);
244 idt_setoffset(d++, (uintptr_t) &int_53);
245 idt_setoffset(d++, (uintptr_t) &int_54);
246 idt_setoffset(d++, (uintptr_t) &int_55);
247 idt_setoffset(d++, (uintptr_t) &int_56);
248 idt_setoffset(d++, (uintptr_t) &int_57);
249 idt_setoffset(d++, (uintptr_t) &int_58);
250 idt_setoffset(d++, (uintptr_t) &int_59);
251 idt_setoffset(d++, (uintptr_t) &int_60);
252 idt_setoffset(d++, (uintptr_t) &int_61);
253 idt_setoffset(d++, (uintptr_t) &int_62);
254 idt_setoffset(d++, (uintptr_t) &int_63);
255
256 idt_setoffset(&idt[VECTOR_SYSCALL], (uintptr_t) &int_syscall);
257}
258
259void pm_init(void)
260{
261 descriptor_t *gdt_p = (descriptor_t *) gdtr.base;
262 ptr_16_32_t idtr;
263
264 /*
265 * Update addresses in GDT and IDT to their virtual counterparts.
266 */
267 idtr.limit = sizeof(idt);
268 idtr.base = (uintptr_t) idt;
269 gdtr_load(&gdtr);
270 idtr_load(&idtr);
271
272 /*
273 * Each CPU has its private GDT and TSS.
274 * All CPUs share one IDT.
275 */
276
277 if (config.cpu_active == 1) {
278 idt_init();
279 /*
280 * NOTE: bootstrap CPU has statically allocated TSS, because
281 * the heap hasn't been initialized so far.
282 */
283 tss_p = &tss0;
284 } else {
285 tss_p = (tss_t *) malloc(sizeof(tss_t), FRAME_ATOMIC);
286 if (!tss_p)
287 panic("Cannot allocate TSS.");
288 }
289
290 tss_initialize(tss_p);
291
292 gdt_p[TSS_DES].access = AR_PRESENT | AR_TSS | DPL_KERNEL;
293 gdt_p[TSS_DES].special = 1;
294 gdt_p[TSS_DES].granularity = 0;
295
296 gdt_setbase(&gdt_p[TSS_DES], (uintptr_t) tss_p);
297 gdt_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE - 1);
298
299 /*
300 * As of this moment, the current CPU has its own GDT pointing
301 * to its own TSS. We just need to load the TR register.
302 */
303 tr_load(GDT_SELECTOR(TSS_DES));
304
305 /* Disable I/O on nonprivileged levels and clear NT flag. */
306 write_eflags(read_eflags() & ~(EFLAGS_IOPL | EFLAGS_NT));
307
308 /* Disable alignment check */
309 write_cr0(read_cr0() & ~CR0_AM);
310}
311
312/** @}
313 */
Note: See TracBrowser for help on using the repository browser.