source: mainline/kernel/arch/ia32/src/pm.c@ 1433ecda

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1433ecda was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 8.7 KB
RevLine 
[f761f1eb]1/*
[df4ed85]2 * Copyright (c) 2001-2004 Jakub Jermar
[f761f1eb]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
[add04f7]29/** @addtogroup ia32
[b45c443]30 * @{
31 */
32/** @file
33 */
34
[f761f1eb]35#include <arch/pm.h>
36#include <config.h>
[d99c1d2]37#include <typedefs.h>
[f761f1eb]38#include <arch/interrupt.h>
39#include <arch/asm.h>
40#include <arch/context.h>
41#include <panic.h>
[b07769b6]42#include <arch/mm/page.h>
[d6f9fff]43#include <mm/km.h>
44#include <mm/frame.h>
[085d973]45#include <mm/slab.h>
[44a7ee5]46#include <mem.h>
[375237d1]47#include <arch/boot/boot.h>
[fcfac420]48#include <interrupt.h>
[0f17bff]49#include <arch/cpu.h>
[f761f1eb]50
51/*
[397c77f]52 * Early ia32 configuration functions and data structures.
[f761f1eb]53 */
54
55/*
[d6f9fff]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
[f761f1eb]58 * whole memory. One is for code and one is for data.
[281b607]59 *
[d6f9fff]60 * One special segment apart of that is for the GS register which holds
61 * a pointer to the VREG page in its base.
[f761f1eb]62 */
[39cea6a]63descriptor_t gdt[GDT_ITEMS] = {
[650cd22]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 },
[22cf454d]105 /* VESA Init descriptor */
[e8194664]106#ifdef CONFIG_FB
[650cd22]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 }
[ff586e06]119#endif
[f761f1eb]120};
121
[39cea6a]122static idescriptor_t idt[IDT_ITEMS];
[f761f1eb]123
[d6f9fff]124static tss_t tss0;
[f761f1eb]125
[39cea6a]126tss_t *tss_p = NULL;
[f761f1eb]127
[cb4b61d]128/* gdtr is changed by kmp before next CPU is initialized */
[ff586e06]129ptr_16_32_t gdtr = {
130 .limit = sizeof(gdt),
131 .base = (uintptr_t) gdt
132};
[f761f1eb]133
[7f1c620]134void gdt_setbase(descriptor_t *d, uintptr_t base)
[f761f1eb]135{
[76cec1e]136 d->base_0_15 = base & 0xffff;
[d6f9fff]137 d->base_16_23 = (base >> 16) & 0xff;
138 d->base_24_31 = (base >> 24) & 0xff;
[f761f1eb]139}
140
[7f1c620]141void gdt_setlimit(descriptor_t *d, uint32_t limit)
[f761f1eb]142{
[76cec1e]143 d->limit_0_15 = limit & 0xffff;
144 d->limit_16_19 = (limit >> 16) & 0xf;
[f761f1eb]145}
146
[7f1c620]147void idt_setoffset(idescriptor_t *d, uintptr_t offset)
[f761f1eb]148{
[b0bf501]149 /*
150 * Offset is a linear address.
151 */
152 d->offset_0_15 = offset & 0xffff;
153 d->offset_16_31 = offset >> 16;
[f761f1eb]154}
155
[39cea6a]156void tss_initialize(tss_t *t)
[f761f1eb]157{
[99d6fd0]158 memsetb(t, sizeof(tss_t), 0);
[f761f1eb]159}
160
161/*
162 * This function takes care of proper setup of IDT and IDTR.
163 */
164void idt_init(void)
165{
[39cea6a]166 idescriptor_t *d;
[f74bbaf]167 unsigned int i;
[76cec1e]168
[f761f1eb]169 for (i = 0; i < IDT_ITEMS; i++) {
170 d = &idt[i];
171
172 d->unused = 0;
[1d3d2cf]173 d->selector = GDT_SELECTOR(KTEXT_DES);
[f761f1eb]174
175 if (i == VECTOR_SYSCALL) {
176 /*
[f4946de]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.
[f761f1eb]185 */
[f4946de]186 d->access = AR_PRESENT | AR_INTERRUPT;
[f761f1eb]187 }
188 }
189
[b808660]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);
[44c69b66]255
256 idt_setoffset(&idt[VECTOR_SYSCALL], (uintptr_t) &int_syscall);
[b808660]257}
[f761f1eb]258
259void pm_init(void)
260{
[39cea6a]261 descriptor_t *gdt_p = (descriptor_t *) gdtr.base;
262 ptr_16_32_t idtr;
[69bd642]263
264 /*
265 * Update addresses in GDT and IDT to their virtual counterparts.
266 */
[4533601]267 idtr.limit = sizeof(idt);
[7f1c620]268 idtr.base = (uintptr_t) idt;
[897ad60]269 gdtr_load(&gdtr);
270 idtr_load(&idtr);
[a35b458]271
[f761f1eb]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 */
[d6f9fff]283 tss_p = &tss0;
284 } else {
[39cea6a]285 tss_p = (tss_t *) malloc(sizeof(tss_t), FRAME_ATOMIC);
[f761f1eb]286 if (!tss_p)
[f651e80]287 panic("Cannot allocate TSS.");
[f761f1eb]288 }
289
290 tss_initialize(tss_p);
[a35b458]291
[f761f1eb]292 gdt_p[TSS_DES].access = AR_PRESENT | AR_TSS | DPL_KERNEL;
293 gdt_p[TSS_DES].special = 1;
[11928d5]294 gdt_p[TSS_DES].granularity = 0;
[a35b458]295
[7f1c620]296 gdt_setbase(&gdt_p[TSS_DES], (uintptr_t) tss_p);
[11928d5]297 gdt_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE - 1);
[f761f1eb]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 */
[1d3d2cf]303 tr_load(GDT_SELECTOR(TSS_DES));
[a35b458]304
[0f17bff]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);
[f761f1eb]310}
[281b607]311
[06e1e95]312/** @}
[b45c443]313 */
Note: See TracBrowser for help on using the repository browser.