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 ---