source: mainline/arch/ia32/src/pm.c@ a5556b4

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

Cleanup.
Cancel fake in pm.c and replace it with LONG(0xdeadbeaf) in linker script. Still need some to find out why it must be there.
Remove comment saying, that mips is little-endian.

  • Property mode set to 100644
File size: 5.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#include <arch/pm.h>
30#include <config.h>
31#include <arch/types.h>
32#include <typedefs.h>
33#include <arch/interrupt.h>
34#include <arch/asm.h>
35#include <arch/context.h>
36#include <panic.h>
37#include <arch/mm/page.h>
38#include <mm/heap.h>
39#include <memstr.h>
40#include <arch/boot/boot.h>
41
42/*
43 * Early ia32 configuration functions and data structures.
44 */
45
46/*
47 * We have no use for segmentation so we set up flat mode. In this
48 * mode, we use, for each privilege level, two segments spanning the
49 * whole memory. One is for code and one is for data.
50 */
51struct descriptor gdt[GDT_ITEMS] = {
52 /* NULL descriptor */
53 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
54 /* KTEXT descriptor */
55 { 0xffff, 0, 0, AR_PRESENT | AR_CODE | DPL_KERNEL, 0xf, 0, 0, 1, 1, 0 },
56 /* KDATA descriptor */
57 { 0xffff, 0, 0, AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_KERNEL, 0xf, 0, 0, 1, 1, 0 },
58 /* UTEXT descriptor */
59 { 0xffff, 0, 0, AR_PRESENT | AR_CODE | DPL_USER, 0xf, 0, 0, 1, 1, 0 },
60 /* UDATA descriptor */
61 { 0xffff, 0, 0, AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_USER, 0xf, 0, 0, 1, 1, 0 },
62 /* TSS descriptor - set up will be completed later */
63 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
64};
65
66static struct idescriptor idt[IDT_ITEMS];
67
68static struct tss tss;
69
70struct tss *tss_p = NULL;
71
72/* gdtr is changed by kmp before next CPU is initialized */
73struct ptr_16_32 protected_bootstrap_gdtr = { .limit = sizeof(gdt), .base = KA2PA((__address) gdt) };
74struct ptr_16_32 gdtr = { .limit = sizeof(gdt), .base = (__address) gdt };
75
76void gdt_setbase(struct descriptor *d, __address base)
77{
78 d->base_0_15 = base & 0xffff;
79 d->base_16_23 = ((base) >> 16) & 0xff;
80 d->base_24_31 = ((base) >> 24) & 0xff;
81}
82
83void gdt_setlimit(struct descriptor *d, __u32 limit)
84{
85 d->limit_0_15 = limit & 0xffff;
86 d->limit_16_19 = (limit >> 16) & 0xf;
87}
88
89void idt_setoffset(struct idescriptor *d, __address offset)
90{
91 /*
92 * Offset is a linear address.
93 */
94 d->offset_0_15 = offset & 0xffff;
95 d->offset_16_31 = offset >> 16;
96}
97
98void tss_initialize(struct tss *t)
99{
100 memsetb((__address) t, sizeof(struct tss), 0);
101}
102
103/*
104 * This function takes care of proper setup of IDT and IDTR.
105 */
106void idt_init(void)
107{
108 struct idescriptor *d;
109 int i;
110
111 for (i = 0; i < IDT_ITEMS; i++) {
112 d = &idt[i];
113
114 d->unused = 0;
115 d->selector = selector(KTEXT_DES);
116
117 d->access = AR_PRESENT | AR_INTERRUPT; /* masking interrupt */
118
119 if (i == VECTOR_SYSCALL) {
120 /*
121 * The syscall interrupt gate must be calleable from userland.
122 */
123 d->access |= DPL_USER;
124 }
125
126 idt_setoffset(d, ((__address) interrupt_handlers) + i*interrupt_handler_size);
127 trap_register(i, null_interrupt);
128 }
129 trap_register(13, gp_fault);
130 trap_register( 7, nm_fault);
131 trap_register(12, ss_fault);
132}
133
134
135/* Clean IOPL(12,13) and NT(14) flags in EFLAGS register */
136static void clean_IOPL_NT_flags(void)
137{
138 asm
139 (
140 "pushfl;"
141 "pop %%eax;"
142 "and $0xffff8fff,%%eax;"
143 "push %%eax;"
144 "popfl;"
145 :
146 :
147 :"%eax"
148 );
149}
150
151/* Clean AM(18) flag in CR0 register */
152static void clean_AM_flag(void)
153{
154 asm
155 (
156 "mov %%cr0,%%eax;"
157 "and $0xFFFBFFFF,%%eax;"
158 "mov %%eax,%%cr0;"
159 :
160 :
161 :"%eax"
162 );
163}
164
165void pm_init(void)
166{
167 struct descriptor *gdt_p = (struct descriptor *) gdtr.base;
168 struct ptr_16_32 idtr;
169
170 /*
171 * Update addresses in GDT and IDT to their virtual counterparts.
172 */
173 idtr.limit = sizeof(idt);
174 idtr.base = (__address) idt;
175 __asm__ volatile ("lgdt %0\n" : : "m" (gdtr));
176 __asm__ volatile ("lidt %0\n" : : "m" (idtr));
177
178 /*
179 * Each CPU has its private GDT and TSS.
180 * All CPUs share one IDT.
181 */
182
183 if (config.cpu_active == 1) {
184 idt_init();
185 /*
186 * NOTE: bootstrap CPU has statically allocated TSS, because
187 * the heap hasn't been initialized so far.
188 */
189 tss_p = &tss;
190 }
191 else {
192 tss_p = (struct tss *) malloc(sizeof(struct tss));
193 if (!tss_p)
194 panic("could not allocate TSS\n");
195 }
196
197 tss_initialize(tss_p);
198
199 gdt_p[TSS_DES].access = AR_PRESENT | AR_TSS | DPL_KERNEL;
200 gdt_p[TSS_DES].special = 1;
201 gdt_p[TSS_DES].granularity = 1;
202
203 gdt_setbase(&gdt_p[TSS_DES], (__address) tss_p);
204 gdt_setlimit(&gdt_p[TSS_DES], sizeof(struct tss) - 1);
205
206 /*
207 * As of this moment, the current CPU has its own GDT pointing
208 * to its own TSS. We just need to load the TR register.
209 */
210 __asm__ volatile ("ltr %0" : : "r" ((__u16) selector(TSS_DES)));
211
212 clean_IOPL_NT_flags(); /* Disable I/O on nonprivileged levels */
213 clean_AM_flag(); /* Disable alignment check */
214}
Note: See TracBrowser for help on using the repository browser.