system.cc (5132:ad5e94876bfc) system.cc (5299:e61b9f2a9732)
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 *

--- 41 unchanged lines hidden (view full) ---

50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 *
55 * Authors: Gabe Black
56 */
57
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 *

--- 41 unchanged lines hidden (view full) ---

50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 *
55 * Authors: Gabe Black
56 */
57
58#include "arch/x86/miscregs.hh"
58#include "arch/x86/system.hh"
59#include "arch/vtophys.hh"
60#include "base/remote_gdb.hh"
61#include "base/loader/object_file.hh"
62#include "base/loader/symtab.hh"
63#include "base/trace.hh"
59#include "arch/x86/system.hh"
60#include "arch/vtophys.hh"
61#include "base/remote_gdb.hh"
62#include "base/loader/object_file.hh"
63#include "base/loader/symtab.hh"
64#include "base/trace.hh"
65#include "cpu/thread_context.hh"
64#include "mem/physical.hh"
65#include "params/X86System.hh"
66#include "sim/byteswap.hh"
67
68
66#include "mem/physical.hh"
67#include "params/X86System.hh"
68#include "sim/byteswap.hh"
69
70
69using namespace BigEndianGuest;
71using namespace LittleEndianGuest;
72using namespace X86ISA;
70
71X86System::X86System(Params *p)
72 : System(p)
73{
74}
75
73
74X86System::X86System(Params *p)
75 : System(p)
76{
77}
78
79void
80X86System::startup()
81{
82 System::startup();
83 // This is the boot strap processor (BSP). Initialize it to look like
84 // the boot loader has just turned control over to the 64 bit OS. We
85 // won't actually set up real mode or legacy protected mode descriptor
86 // tables because we aren't executing any code that would require
87 // them. We do, however toggle the control bits in the correct order
88 // while allowing consistency checks and the underlying mechansims
89 // just to be safe.
90
91 const int NumPDTs = 4;
92
93 const Addr PageMapLevel4 = 0x70000;
94 const Addr PageDirPtrTable = 0x71000;
95 const Addr PageDirTable[NumPDTs] =
96 {0x72000, 0x73000, 0x74000, 0x75000};
97 const Addr GDTBase = 0x76000;
98
99 const int PML4Bits = 9;
100 const int PDPTBits = 9;
101 const int PDTBits = 9;
102
103 // Get a port to write the page tables and descriptor tables.
104 FunctionalPort * physPort = threadContexts[0]->getPhysPort();
105
106 /*
107 * Set up the gdt.
108 */
109 // Place holder at selector 0
110 uint64_t nullDescriptor = 0;
111 physPort->writeBlob(GDTBase, (uint8_t *)(&nullDescriptor), 8);
112
113 //64 bit code segment
114 SegDescriptor csDesc = 0;
115 csDesc.type.c = 0; // Not conforming
116 csDesc.dpl = 0; // Privelege level 0
117 csDesc.p = 1; // Present
118 csDesc.l = 1; // 64 bit
119 csDesc.d = 0; // default operand size
120 //Because we're dealing with a pointer and I don't think it's
121 //guaranteed that there isn't anything in a nonvirtual class between
122 //it's beginning in memory and it's actual data, we'll use an
123 //intermediary.
124 uint64_t csDescVal = csDesc;
125 physPort->writeBlob(GDTBase, (uint8_t *)(&csDescVal), 8);
126
127 threadContexts[0]->setMiscReg(MISCREG_TSG_BASE, GDTBase);
128 threadContexts[0]->setMiscReg(MISCREG_TSG_LIMIT, 0xF);
129
130 /*
131 * Identity map the first 4GB of memory. In order to map this region
132 * of memory in long mode, there needs to be one actual page map level
133 * 4 entry which points to one page directory pointer table which
134 * points to 4 different page directory tables which are full of two
135 * megabyte pages. All of the other entries in valid tables are set
136 * to indicate that they don't pertain to anything valid and will
137 * cause a fault if used.
138 */
139
140 // Put valid values in all of the various table entries which indicate
141 // that those entries don't point to further tables or pages. Then
142 // set the values of those entries which are needed.
143
144 // Page Map Level 4
145
146 // read/write, user, not present
147 uint64_t pml4e = X86ISA::htog(0x6);
148 for (int offset = 0; offset < (1 << PML4Bits) * 8; offset += 8) {
149 physPort->writeBlob(PageMapLevel4 + offset, (uint8_t *)(&pml4e), 8);
150 }
151 // Point to the only PDPT
152 pml4e = X86ISA::htog(0x7 | PageDirPtrTable);
153 physPort->writeBlob(PageMapLevel4, (uint8_t *)(&pml4e), 8);
154
155 // Page Directory Pointer Table
156
157 // read/write, user, not present
158 uint64_t pdpe = X86ISA::htog(0x6);
159 for (int offset = 0; offset < (1 << PDPTBits) * 8; offset += 8) {
160 physPort->writeBlob(PageDirPtrTable + offset,
161 (uint8_t *)(&pdpe), 8);
162 }
163 // Point to the PDTs
164 for (int table = 0; table < NumPDTs; table++) {
165 pdpe = X86ISA::htog(0x7 | PageDirTable[table]);
166 physPort->writeBlob(PageDirPtrTable + table * 8,
167 (uint8_t *)(&pdpe), 8);
168 }
169
170 // Page Directory Tables
171
172 Addr base = 0;
173 const Addr pageSize = 2 << 20;
174 for (int table = 0; table < NumPDTs; table++) {
175 for (int offset = 0; offset < (1 << PDTBits) * 8; offset += 8) {
176 // read/write, user, present, 4MB
177 uint64_t pdte = X86ISA::htog(0x87 | base);
178 physPort->writeBlob(PageDirTable[table] + offset,
179 (uint8_t *)(&pdte), 8);
180 base += pageSize;
181 }
182 }
183
184 /*
185 * Transition from real mode all the way up to Long mode
186 */
187 CR0 cr0 = threadContexts[0]->readMiscRegNoEffect(MISCREG_CR0);
188 //Turn off paging.
189 cr0.pg = 0;
190 threadContexts[0]->setMiscReg(MISCREG_CR0, cr0);
191 //Turn on protected mode.
192 cr0.pe = 1;
193 threadContexts[0]->setMiscReg(MISCREG_CR0, cr0);
194
195 CR4 cr4 = threadContexts[0]->readMiscRegNoEffect(MISCREG_CR4);
196 //Turn on pae.
197 cr4.pae = 1;
198 threadContexts[0]->setMiscReg(MISCREG_CR4, cr4);
199
200 //Point to the page tables.
201 threadContexts[0]->setMiscReg(MISCREG_CR3, PageMapLevel4);
202
203 Efer efer = threadContexts[0]->readMiscRegNoEffect(MISCREG_EFER);
204 //Enable long mode.
205 efer.lme = 1;
206 threadContexts[0]->setMiscReg(MISCREG_EFER, efer);
207
208 //Activate long mode.
209 cr0.pg = 1;
210 threadContexts[0]->setMiscReg(MISCREG_CR0, cr0);
211
212 /*
213 * Far jump into 64 bit mode.
214 */
215 // Set the selector
216 threadContexts[0]->setMiscReg(MISCREG_CS, 1);
217 // Manually set up the segment attributes. In the future when there's
218 // other existing functionality to do this, that could be used
219 // instead.
220 SegAttr csAttr = 0;
221 csAttr.writable = 0;
222 csAttr.readable = 1;
223 csAttr.expandDown = 0;
224 csAttr.dpl = 0;
225 csAttr.defaultSize = 0;
226 csAttr.longMode = 1;
227 threadContexts[0]->setMiscReg(MISCREG_CS_ATTR, csAttr);
228
229 threadContexts[0]->setPC(threadContexts[0]->getSystemPtr()->kernelEntry);
230 threadContexts[0]->setNextPC(threadContexts[0]->readPC());
231
232 // We should now be in long mode. Yay!
233}
234
76X86System::~X86System()
77{
78}
79
80void
81X86System::serialize(std::ostream &os)
82{
83 System::serialize(os);

--- 14 unchanged lines hidden ---
235X86System::~X86System()
236{
237}
238
239void
240X86System::serialize(std::ostream &os)
241{
242 System::serialize(os);

--- 14 unchanged lines hidden ---