00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00036 #include <arch/pm.h>
00037 #include <arch/mm/page.h>
00038 #include <arch/types.h>
00039 #include <arch/interrupt.h>
00040 #include <arch/asm.h>
00041 #include <interrupt.h>
00042 #include <mm/as.h>
00043
00044 #include <config.h>
00045
00046 #include <memstr.h>
00047 #include <mm/slab.h>
00048 #include <debug.h>
00049
00050
00051
00052
00053
00054
00055
00056 descriptor_t gdt[GDT_ITEMS] = {
00057
00058 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
00059
00060 { .limit_0_15 = 0xffff,
00061 .base_0_15 = 0,
00062 .base_16_23 = 0,
00063 .access = AR_PRESENT | AR_CODE | DPL_KERNEL | AR_READABLE ,
00064 .limit_16_19 = 0xf,
00065 .available = 0,
00066 .longmode = 1,
00067 .special = 0,
00068 .granularity = 1,
00069 .base_24_31 = 0 },
00070
00071 { .limit_0_15 = 0xffff,
00072 .base_0_15 = 0,
00073 .base_16_23 = 0,
00074 .access = AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_KERNEL,
00075 .limit_16_19 = 0xf,
00076 .available = 0,
00077 .longmode = 0,
00078 .special = 0,
00079 .granularity = 1,
00080 .base_24_31 = 0 },
00081
00082 { .limit_0_15 = 0xffff,
00083 .base_0_15 = 0,
00084 .base_16_23 = 0,
00085 .access = AR_PRESENT | AR_DATA | AR_WRITABLE | DPL_USER,
00086 .limit_16_19 = 0xf,
00087 .available = 0,
00088 .longmode = 0,
00089 .special = 1,
00090 .granularity = 1,
00091 .base_24_31 = 0 },
00092
00093 { .limit_0_15 = 0xffff,
00094 .base_0_15 = 0,
00095 .base_16_23 = 0,
00096 .access = AR_PRESENT | AR_CODE | DPL_USER,
00097 .limit_16_19 = 0xf,
00098 .available = 0,
00099 .longmode = 1,
00100 .special = 0,
00101 .granularity = 1,
00102 .base_24_31 = 0 },
00103
00104 { .limit_0_15 = 0xffff,
00105 .base_0_15 = 0,
00106 .base_16_23 = 0,
00107 .access = AR_PRESENT | AR_CODE | DPL_KERNEL | AR_READABLE,
00108 .limit_16_19 = 0xf,
00109 .available = 0,
00110 .longmode = 0,
00111 .special = 1,
00112 .granularity = 1,
00113 .base_24_31 = 0 },
00114
00115
00116 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
00117 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
00118
00119 #ifdef CONFIG_FB
00120 { 0xffff, 0, VESA_INIT_SEGMENT>>12, AR_PRESENT | AR_CODE | DPL_KERNEL, 0xf, 0, 0, 0, 0, 0 }
00121 #endif
00122 };
00123
00124 idescriptor_t idt[IDT_ITEMS];
00125
00126 ptr_16_64_t gdtr = {.limit = sizeof(gdt), .base= (__u64) gdt };
00127 ptr_16_64_t idtr = {.limit = sizeof(idt), .base= (__u64) idt };
00128
00129 static tss_t tss;
00130 tss_t *tss_p = NULL;
00131
00132 void gdt_tss_setbase(descriptor_t *d, __address base)
00133 {
00134 tss_descriptor_t *td = (tss_descriptor_t *) d;
00135
00136 td->base_0_15 = base & 0xffff;
00137 td->base_16_23 = ((base) >> 16) & 0xff;
00138 td->base_24_31 = ((base) >> 24) & 0xff;
00139 td->base_32_63 = ((base) >> 32);
00140 }
00141
00142 void gdt_tss_setlimit(descriptor_t *d, __u32 limit)
00143 {
00144 struct tss_descriptor *td = (tss_descriptor_t *) d;
00145
00146 td->limit_0_15 = limit & 0xffff;
00147 td->limit_16_19 = (limit >> 16) & 0xf;
00148 }
00149
00150 void idt_setoffset(idescriptor_t *d, __address offset)
00151 {
00152
00153
00154
00155 d->offset_0_15 = offset & 0xffff;
00156 d->offset_16_31 = offset >> 16 & 0xffff;
00157 d->offset_32_63 = offset >> 32;
00158 }
00159
00160 void tss_initialize(tss_t *t)
00161 {
00162 memsetb((__address) t, sizeof(tss_t), 0);
00163 }
00164
00165
00166
00167
00168 void idt_init(void)
00169 {
00170 idescriptor_t *d;
00171 int i;
00172
00173 for (i = 0; i < IDT_ITEMS; i++) {
00174 d = &idt[i];
00175
00176 d->unused = 0;
00177 d->selector = gdtselector(KTEXT_DES);
00178
00179 d->present = 1;
00180 d->type = AR_INTERRUPT;
00181
00182 idt_setoffset(d, ((__address) interrupt_handlers) + i*interrupt_handler_size);
00183 exc_register(i, "undef", (iroutine)null_interrupt);
00184 }
00185
00186 exc_register( 7, "nm_fault", nm_fault);
00187 exc_register(12, "ss_fault", ss_fault);
00188 exc_register(13, "gp_fault", gp_fault);
00189 exc_register(14, "ident_mapper", ident_page_fault);
00190 }
00191
00195 void pm_init(void)
00196 {
00197 descriptor_t *gdt_p = (struct descriptor *) gdtr.base;
00198 tss_descriptor_t *tss_desc;
00199
00200
00201
00202
00203
00204
00205 if (config.cpu_active == 1) {
00206 idt_init();
00207
00208
00209
00210
00211 tss_p = &tss;
00212 }
00213 else {
00214
00215
00216
00217 write_cr3((__address) AS_KERNEL->page_table);
00218
00219 tss_p = (struct tss *) malloc(sizeof(tss_t), FRAME_ATOMIC);
00220 if (!tss_p)
00221 panic("could not allocate TSS\n");
00222 }
00223
00224 tss_initialize(tss_p);
00225
00226 tss_desc = (tss_descriptor_t *) (&gdt_p[TSS_DES]);
00227 tss_desc->present = 1;
00228 tss_desc->type = AR_TSS;
00229 tss_desc->dpl = PL_KERNEL;
00230
00231 gdt_tss_setbase(&gdt_p[TSS_DES], (__address) tss_p);
00232 gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE - 1);
00233
00234 gdtr_load(&gdtr);
00235 idtr_load(&idtr);
00236
00237
00238
00239
00240 tr_load(gdtselector(TSS_DES));
00241 }
00242