Changeset b9e97fb in mainline for arch/amd64/src/pm.c
- Timestamp:
- 2005-08-31T10:53:34Z (20 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8f91729
- Parents:
- 9756131
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
arch/amd64/src/pm.c
r9756131 rb9e97fb 30 30 #include <arch/mm/page.h> 31 31 #include <arch/types.h> 32 32 #include <arch/interrupt.h> 33 #include <arch/asm.h> 34 35 #include <config.h> 36 37 #include <memstr.h> 38 #include <mm/heap.h> 39 #include <debug.h> 33 40 34 41 /* … … 72 79 .longmode = 1, 73 80 .special = 0, 74 .granularity = 0,81 .granularity = 1, 75 82 .base_24_31 = 0 }, 76 83 /* UDATA descriptor */ … … 96 103 .granularity = 1, 97 104 .base_24_31 = 0 }, 98 /* TSS descriptor - set up will be completed later */ 105 /* TSS descriptor - set up will be completed later, 106 * on AMD64 it is 64-bit - 2 items in table */ 107 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 99 108 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } 100 109 }; 101 110 111 struct ptr_16_64 gdtr = {.limit = sizeof(gdtr), .base= (__u64) &gdtr }; 112 102 113 struct idescriptor idt[IDT_ITEMS]; 103 114 104 115 static struct tss tss; 105 116 106 /* Does not compile correctly if it does not exist*/117 /* TODO: Does not compile correctly if it does not exist ???? */ 107 118 int __attribute__ ((section ("K_DATA_START"))) __fake; 119 120 void gdt_tss_setbase(struct descriptor *d, __address base) 121 { 122 struct tss_descriptor *td = (struct tss_descriptor *) d; 123 124 td->base_0_15 = base & 0xffff; 125 td->base_16_23 = ((base) >> 16) & 0xff; 126 td->base_24_31 = ((base) >> 24) & 0xff; 127 td->base_32_63 = ((base) >> 32); 128 } 129 130 void gdt_tss_setlimit(struct descriptor *d, __u32 limit) 131 { 132 struct tss_descriptor *td = (struct tss_descriptor *) d; 133 134 td->limit_0_15 = limit & 0xffff; 135 td->limit_16_19 = (limit >> 16) & 0xf; 136 } 137 138 void idt_setoffset(struct idescriptor *d, __address offset) 139 { 140 /* 141 * Offset is a linear address. 142 */ 143 d->offset_0_15 = offset & 0xffff; 144 d->offset_16_31 = offset >> 16 & 0xffff; 145 d->offset_32_63 = offset >> 32; 146 } 147 148 void tss_initialize(struct tss *t) 149 { 150 memsetb((__address) t, sizeof(struct tss), 0); 151 } 152 153 /* 154 * This function takes care of proper setup of IDT and IDTR. 155 */ 156 void idt_init(void) 157 { 158 struct idescriptor *d; 159 int i; 160 161 for (i = 0; i < IDT_ITEMS; i++) { 162 d = &idt[i]; 163 164 d->unused = 0; 165 d->selector = idtselector(KTEXT_DES); 166 167 d->present = 1; 168 d->type = AR_INTERRUPT; /* masking interrupt */ 169 170 if (i == VECTOR_SYSCALL) { 171 /* 172 * The syscall interrupt gate must be calleable from userland. 173 */ 174 d->dpl |= PL_USER; 175 } 176 177 idt_setoffset(d, ((__address) interrupt_handlers) + i*interrupt_handler_size); 178 trap_register(i, null_interrupt); 179 } 180 trap_register(13, gp_fault); 181 trap_register( 7, nm_fault); 182 trap_register(12, ss_fault); 183 } 184 185 186 /* Clean IOPL(12,13) and NT(14) flags in EFLAGS register */ 187 static void clean_IOPL_NT_flags(void) 188 { 189 asm 190 ( 191 "pushfq;" 192 "pop %%rax;" 193 "and $~(0x7000),%%rax;" 194 "pushq %%rax;" 195 "popfq;" 196 : 197 : 198 :"%rax" 199 ); 200 } 201 202 /* Clean AM(18) flag in CR0 register */ 203 static void clean_AM_flag(void) 204 { 205 asm 206 ( 207 "mov %%cr0,%%rax;" 208 "and $~(0x40000),%%rax;" 209 "mov %%rax,%%cr0;" 210 : 211 : 212 :"%rax" 213 ); 214 } 215 216 void pm_init(void) 217 { 218 struct descriptor *gdt_p = (struct descriptor *) PA2KA(gdtr.base); 219 struct tss_descriptor *tss_d; 220 221 /* 222 * Each CPU has its private GDT and TSS. 223 * All CPUs share one IDT. 224 */ 225 226 if (config.cpu_active == 1) { 227 idt_init(); 228 /* 229 * NOTE: bootstrap CPU has statically allocated TSS, because 230 * the heap hasn't been initialized so far. 231 */ 232 tss_p = &tss; 233 } 234 else { 235 tss_p = (struct tss *) malloc(sizeof(struct tss)); 236 if (!tss_p) 237 panic("could not allocate TSS\n"); 238 } 239 240 tss_initialize(tss_p); 241 242 tss_d = (struct tss_descriptor *) &gdt_p[TSS_DES]; 243 tss_d[TSS_DES].present = 1; 244 tss_d[TSS_DES].type = AR_TSS; 245 tss_d[TSS_DES].dpl = PL_KERNEL; 246 247 gdt_tss_setbase(&gdt_p[TSS_DES], (__address) tss_p); 248 gdt_tss_setlimit(&gdt_p[TSS_DES], sizeof(struct tss) - 1); 249 250 /* 251 * As of this moment, the current CPU has its own GDT pointing 252 * to its own TSS. We just need to load the TR register. 253 */ 254 __asm__("ltr %0" : : "r" ((__u16) gdtselector(TSS_DES))); 255 256 clean_IOPL_NT_flags(); /* Disable I/O on nonprivileged levels */ 257 clean_AM_flag(); /* Disable alignment check */ 258 }
Note:
See TracChangeset
for help on using the changeset viewer.