system.cc (5627:31eac202dbd1) | system.cc (6220:d774fa547141) |
---|---|
1/* 2 * Copyright (c) 2007 The Hewlett-Packard Development Company 3 * All rights reserved. 4 * 5 * Redistribution and use of this software in source and binary forms, 6 * with or without modification, are permitted provided that the 7 * following conditions are met: 8 * --- 67 unchanged lines hidden (view full) --- 76 77X86System::X86System(Params *p) : 78 System(p), smbiosTable(p->smbios_table), 79 mpFloatingPointer(p->intel_mp_pointer), 80 mpConfigTable(p->intel_mp_table), 81 rsdp(p->acpi_description_table_pointer) 82{} 83 | 1/* 2 * Copyright (c) 2007 The Hewlett-Packard Development Company 3 * All rights reserved. 4 * 5 * Redistribution and use of this software in source and binary forms, 6 * with or without modification, are permitted provided that the 7 * following conditions are met: 8 * --- 67 unchanged lines hidden (view full) --- 76 77X86System::X86System(Params *p) : 78 System(p), smbiosTable(p->smbios_table), 79 mpFloatingPointer(p->intel_mp_pointer), 80 mpConfigTable(p->intel_mp_table), 81 rsdp(p->acpi_description_table_pointer) 82{} 83 |
84static void 85installSegDesc(ThreadContext *tc, SegmentRegIndex seg, 86 SegDescriptor desc, bool longmode) 87{ 88 uint64_t base = desc.baseLow + (desc.baseHigh << 24); 89 bool honorBase = !longmode || seg == SEGMENT_REG_FS || 90 seg == SEGMENT_REG_GS || 91 seg == SEGMENT_REG_TSL || 92 seg == SYS_SEGMENT_REG_TR; 93 uint64_t limit = desc.limitLow | (desc.limitHigh << 16); 94 95 SegAttr attr = 0; 96 if (desc.s) { 97 if (desc.type.codeOrData) { 98 // Code segment 99 attr.readable = desc.type.r; 100 } else { 101 // Data segment 102 attr.readable = 1; 103 attr.writable = desc.type.w; 104 attr.expandDown = desc.type.e; 105 } 106 } else { 107 attr.writable = 1; 108 attr.readable = 1; 109 attr.expandDown = 0; 110 } 111 attr.longMode = desc.l; 112 attr.dpl = desc.dpl; 113 attr.defaultSize = desc.d; 114 115 tc->setMiscReg(MISCREG_SEG_BASE(seg), base); 116 tc->setMiscReg(MISCREG_SEG_EFF_BASE(seg), honorBase ? base : 0); 117 tc->setMiscReg(MISCREG_SEG_LIMIT(seg), limit); 118 tc->setMiscReg(MISCREG_SEG_ATTR(seg), (MiscReg)attr); 119} 120 |
|
84void 85X86System::startup() 86{ 87 System::startup(); | 121void 122X86System::startup() 123{ 124 System::startup(); |
125 ThreadContext *tc = threadContexts[0]; |
|
88 // This is the boot strap processor (BSP). Initialize it to look like 89 // the boot loader has just turned control over to the 64 bit OS. We 90 // won't actually set up real mode or legacy protected mode descriptor 91 // tables because we aren't executing any code that would require 92 // them. We do, however toggle the control bits in the correct order 93 // while allowing consistency checks and the underlying mechansims 94 // just to be safe. 95 --- 5 unchanged lines hidden (view full) --- 101 {0x72000, 0x73000, 0x74000, 0x75000}; 102 const Addr GDTBase = 0x76000; 103 104 const int PML4Bits = 9; 105 const int PDPTBits = 9; 106 const int PDTBits = 9; 107 108 // Get a port to write the page tables and descriptor tables. | 126 // This is the boot strap processor (BSP). Initialize it to look like 127 // the boot loader has just turned control over to the 64 bit OS. We 128 // won't actually set up real mode or legacy protected mode descriptor 129 // tables because we aren't executing any code that would require 130 // them. We do, however toggle the control bits in the correct order 131 // while allowing consistency checks and the underlying mechansims 132 // just to be safe. 133 --- 5 unchanged lines hidden (view full) --- 139 {0x72000, 0x73000, 0x74000, 0x75000}; 140 const Addr GDTBase = 0x76000; 141 142 const int PML4Bits = 9; 143 const int PDPTBits = 9; 144 const int PDTBits = 9; 145 146 // Get a port to write the page tables and descriptor tables. |
109 FunctionalPort * physPort = threadContexts[0]->getPhysPort(); | 147 FunctionalPort * physPort = tc->getPhysPort(); |
110 111 /* 112 * Set up the gdt. 113 */ | 148 149 /* 150 * Set up the gdt. 151 */ |
152 uint8_t numGDTEntries = 0; |
|
114 // Place holder at selector 0 115 uint64_t nullDescriptor = 0; | 153 // Place holder at selector 0 154 uint64_t nullDescriptor = 0; |
116 physPort->writeBlob(GDTBase, (uint8_t *)(&nullDescriptor), 8); | 155 physPort->writeBlob(GDTBase + numGDTEntries * 8, 156 (uint8_t *)(&nullDescriptor), 8); 157 numGDTEntries++; |
117 118 //64 bit code segment 119 SegDescriptor csDesc = 0; | 158 159 //64 bit code segment 160 SegDescriptor csDesc = 0; |
161 csDesc.type.codeOrData = 1; |
|
120 csDesc.type.c = 0; // Not conforming | 162 csDesc.type.c = 0; // Not conforming |
163 csDesc.type.r = 1; // Readable |
|
121 csDesc.dpl = 0; // Privelege level 0 122 csDesc.p = 1; // Present 123 csDesc.l = 1; // 64 bit 124 csDesc.d = 0; // default operand size | 164 csDesc.dpl = 0; // Privelege level 0 165 csDesc.p = 1; // Present 166 csDesc.l = 1; // 64 bit 167 csDesc.d = 0; // default operand size |
168 csDesc.g = 1; // Page granularity 169 csDesc.s = 1; // Not a system segment 170 csDesc.limitHigh = 0xF; 171 csDesc.limitLow = 0xFF; |
|
125 //Because we're dealing with a pointer and I don't think it's 126 //guaranteed that there isn't anything in a nonvirtual class between 127 //it's beginning in memory and it's actual data, we'll use an 128 //intermediary. 129 uint64_t csDescVal = csDesc; | 172 //Because we're dealing with a pointer and I don't think it's 173 //guaranteed that there isn't anything in a nonvirtual class between 174 //it's beginning in memory and it's actual data, we'll use an 175 //intermediary. 176 uint64_t csDescVal = csDesc; |
130 physPort->writeBlob(GDTBase, (uint8_t *)(&csDescVal), 8); | 177 physPort->writeBlob(GDTBase + numGDTEntries * 8, 178 (uint8_t *)(&csDescVal), 8); |
131 | 179 |
132 threadContexts[0]->setMiscReg(MISCREG_TSG_BASE, GDTBase); 133 threadContexts[0]->setMiscReg(MISCREG_TSG_LIMIT, 0xF); | 180 numGDTEntries++; |
134 | 181 |
182 SegSelector cs = 0; 183 cs.si = numGDTEntries - 1; 184 185 tc->setMiscReg(MISCREG_CS, (MiscReg)cs); 186 187 //32 bit data segment 188 SegDescriptor dsDesc = 0; 189 dsDesc.type.codeOrData = 0; 190 dsDesc.type.e = 0; // Not expand down 191 dsDesc.type.w = 1; // Writable 192 dsDesc.dpl = 0; // Privelege level 0 193 dsDesc.p = 1; // Present 194 dsDesc.d = 1; // default operand size 195 dsDesc.g = 1; // Page granularity 196 dsDesc.s = 1; // Not a system segment 197 dsDesc.limitHigh = 0xF; 198 dsDesc.limitLow = 0xFF; 199 uint64_t dsDescVal = dsDesc; 200 physPort->writeBlob(GDTBase + numGDTEntries * 8, 201 (uint8_t *)(&dsDescVal), 8); 202 203 numGDTEntries++; 204 205 SegSelector ds; 206 ds.si = numGDTEntries - 1; 207 208 tc->setMiscReg(MISCREG_DS, (MiscReg)ds); 209 tc->setMiscReg(MISCREG_ES, (MiscReg)ds); 210 tc->setMiscReg(MISCREG_FS, (MiscReg)ds); 211 tc->setMiscReg(MISCREG_GS, (MiscReg)ds); 212 tc->setMiscReg(MISCREG_SS, (MiscReg)ds); 213 214 tc->setMiscReg(MISCREG_TSL, 0); 215 tc->setMiscReg(MISCREG_TSG_BASE, GDTBase); 216 tc->setMiscReg(MISCREG_TSG_LIMIT, 8 * numGDTEntries - 1); 217 218 SegDescriptor tssDesc = 0; 219 tssDesc.type = 0xB; 220 tssDesc.dpl = 0; // Privelege level 0 221 tssDesc.p = 1; // Present 222 tssDesc.d = 1; // default operand size 223 tssDesc.g = 1; // Page granularity 224 tssDesc.s = 1; // Not a system segment 225 tssDesc.limitHigh = 0xF; 226 tssDesc.limitLow = 0xFF; 227 uint64_t tssDescVal = tssDesc; 228 physPort->writeBlob(GDTBase + numGDTEntries * 8, 229 (uint8_t *)(&tssDescVal), 8); 230 231 numGDTEntries++; 232 233 SegSelector tss = 0; 234 tss.si = numGDTEntries - 1; 235 236 tc->setMiscReg(MISCREG_TR, (MiscReg)tss); 237 installSegDesc(tc, SYS_SEGMENT_REG_TR, tssDesc, true); 238 |
|
135 /* 136 * Identity map the first 4GB of memory. In order to map this region 137 * of memory in long mode, there needs to be one actual page map level 138 * 4 entry which points to one page directory pointer table which 139 * points to 4 different page directory tables which are full of two 140 * megabyte pages. All of the other entries in valid tables are set 141 * to indicate that they don't pertain to anything valid and will 142 * cause a fault if used. --- 41 unchanged lines hidden (view full) --- 184 (uint8_t *)(&pdte), 8); 185 base += pageSize; 186 } 187 } 188 189 /* 190 * Transition from real mode all the way up to Long mode 191 */ | 239 /* 240 * Identity map the first 4GB of memory. In order to map this region 241 * of memory in long mode, there needs to be one actual page map level 242 * 4 entry which points to one page directory pointer table which 243 * points to 4 different page directory tables which are full of two 244 * megabyte pages. All of the other entries in valid tables are set 245 * to indicate that they don't pertain to anything valid and will 246 * cause a fault if used. --- 41 unchanged lines hidden (view full) --- 288 (uint8_t *)(&pdte), 8); 289 base += pageSize; 290 } 291 } 292 293 /* 294 * Transition from real mode all the way up to Long mode 295 */ |
192 CR0 cr0 = threadContexts[0]->readMiscRegNoEffect(MISCREG_CR0); | 296 CR0 cr0 = tc->readMiscRegNoEffect(MISCREG_CR0); |
193 //Turn off paging. 194 cr0.pg = 0; | 297 //Turn off paging. 298 cr0.pg = 0; |
195 threadContexts[0]->setMiscReg(MISCREG_CR0, cr0); | 299 tc->setMiscReg(MISCREG_CR0, cr0); |
196 //Turn on protected mode. 197 cr0.pe = 1; | 300 //Turn on protected mode. 301 cr0.pe = 1; |
198 threadContexts[0]->setMiscReg(MISCREG_CR0, cr0); | 302 tc->setMiscReg(MISCREG_CR0, cr0); |
199 | 303 |
200 CR4 cr4 = threadContexts[0]->readMiscRegNoEffect(MISCREG_CR4); | 304 CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4); |
201 //Turn on pae. 202 cr4.pae = 1; | 305 //Turn on pae. 306 cr4.pae = 1; |
203 threadContexts[0]->setMiscReg(MISCREG_CR4, cr4); | 307 tc->setMiscReg(MISCREG_CR4, cr4); |
204 205 //Point to the page tables. | 308 309 //Point to the page tables. |
206 threadContexts[0]->setMiscReg(MISCREG_CR3, PageMapLevel4); | 310 tc->setMiscReg(MISCREG_CR3, PageMapLevel4); |
207 | 311 |
208 Efer efer = threadContexts[0]->readMiscRegNoEffect(MISCREG_EFER); | 312 Efer efer = tc->readMiscRegNoEffect(MISCREG_EFER); |
209 //Enable long mode. 210 efer.lme = 1; | 313 //Enable long mode. 314 efer.lme = 1; |
211 threadContexts[0]->setMiscReg(MISCREG_EFER, efer); | 315 tc->setMiscReg(MISCREG_EFER, efer); |
212 | 316 |
317 //Start using longmode segments. 318 installSegDesc(tc, SEGMENT_REG_CS, csDesc, true); 319 installSegDesc(tc, SEGMENT_REG_DS, dsDesc, true); 320 installSegDesc(tc, SEGMENT_REG_ES, dsDesc, true); 321 installSegDesc(tc, SEGMENT_REG_FS, dsDesc, true); 322 installSegDesc(tc, SEGMENT_REG_GS, dsDesc, true); 323 installSegDesc(tc, SEGMENT_REG_SS, dsDesc, true); 324 |
|
213 //Activate long mode. 214 cr0.pg = 1; | 325 //Activate long mode. 326 cr0.pg = 1; |
215 threadContexts[0]->setMiscReg(MISCREG_CR0, cr0); | 327 tc->setMiscReg(MISCREG_CR0, cr0); |
216 | 328 |
217 /* 218 * Far jump into 64 bit mode. 219 */ 220 // Set the selector 221 threadContexts[0]->setMiscReg(MISCREG_CS, 1); 222 // Manually set up the segment attributes. In the future when there's 223 // other existing functionality to do this, that could be used 224 // instead. 225 SegAttr csAttr = 0; 226 csAttr.writable = 0; 227 csAttr.readable = 1; 228 csAttr.expandDown = 0; 229 csAttr.dpl = 0; 230 csAttr.defaultSize = 0; 231 csAttr.longMode = 1; 232 threadContexts[0]->setMiscReg(MISCREG_CS_ATTR, csAttr); | 329 tc->setPC(tc->getSystemPtr()->kernelEntry); 330 tc->setNextPC(tc->readPC()); |
233 | 331 |
234 threadContexts[0]->setPC(threadContexts[0]->getSystemPtr()->kernelEntry); 235 threadContexts[0]->setNextPC(threadContexts[0]->readPC()); 236 | |
237 // We should now be in long mode. Yay! 238 239 Addr ebdaPos = 0xF0000; 240 Addr fixed, table; 241 242 //Write out the SMBios/DMI table 243 writeOutSMBiosTable(ebdaPos, fixed, table); 244 ebdaPos += (fixed + table); --- 81 unchanged lines hidden --- | 332 // We should now be in long mode. Yay! 333 334 Addr ebdaPos = 0xF0000; 335 Addr fixed, table; 336 337 //Write out the SMBios/DMI table 338 writeOutSMBiosTable(ebdaPos, fixed, table); 339 ebdaPos += (fixed + table); --- 81 unchanged lines hidden --- |