gem5 v24.0.0.0
Loading...
Searching...
No Matches
fs_workload.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2007 The Hewlett-Packard Development Company
3 * Copyright (c) 2018 TU Dresden
4 * All rights reserved.
5 *
6 * The license below extends only to copyright in the software and shall
7 * not be construed as granting a license to any other intellectual
8 * property including but not limited to intellectual property relating
9 * to a hardware implementation of the functionality of the software
10 * licensed hereunder. You may use the software subject to the license
11 * terms below provided that you ensure that this notice is replicated
12 * unmodified and in its entirety in all distributions of the software,
13 * modified or unmodified, in source code or in binary form.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions are
17 * met: redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer;
19 * redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution;
22 * neither the name of the copyright holders nor the names of its
23 * contributors may be used to endorse or promote products derived from
24 * this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
40
41#include "arch/x86/bios/acpi.hh"
44#include "arch/x86/faults.hh"
46#include "cpu/thread_context.hh"
47#include "debug/ACPI.hh"
48#include "params/X86FsWorkload.hh"
49#include "sim/system.hh"
50
51namespace gem5
52{
53
54namespace X86ISA
55{
56
58 smbiosTable(p.smbios_table),
59 mpFloatingPointer(p.intel_mp_pointer),
60 mpConfigTable(p.intel_mp_table),
61 rsdp(p.acpi_description_table_pointer),
62 enable_osxsave(p.enable_osxsave)
63{}
64
65void
66installSegDesc(ThreadContext *tc, int seg, SegDescriptor desc, bool longmode)
67{
68 bool honorBase = !longmode || seg == segment_idx::Fs ||
70
71 SegAttr attr = 0;
72
73 attr.dpl = desc.dpl;
74 attr.unusable = 0;
75 attr.defaultSize = desc.d;
76 attr.longMode = desc.l;
77 attr.avl = desc.avl;
78 attr.granularity = desc.g;
79 attr.present = desc.p;
80 attr.system = desc.s;
81 attr.type = desc.type;
82 if (desc.s) {
83 if (desc.type.codeOrData) {
84 // Code segment
85 attr.expandDown = 0;
86 attr.readable = desc.type.r;
87 attr.writable = 0;
88 } else {
89 // Data segment
90 attr.expandDown = desc.type.e;
91 attr.readable = 1;
92 attr.writable = desc.type.w;
93 }
94 } else {
95 attr.readable = 1;
96 attr.writable = 1;
97 attr.expandDown = 0;
98 }
99
100 tc->setMiscReg(misc_reg::segBase(seg), desc.base);
101 tc->setMiscReg(misc_reg::segEffBase(seg), honorBase ? desc.base : 0);
102 tc->setMiscReg(misc_reg::segLimit(seg), desc.limit);
104}
105
106void
108{
110
111 for (auto *tc: system->threads) {
113
114 if (tc->contextId() == 0) {
115 tc->activate();
116 } else {
117 // This is an application processor (AP). It should be initialized
118 // to look like only the BIOS POST has run on it and put then put
119 // it into a halted state.
120 tc->suspend();
121 }
122 }
123
124 fatal_if(!kernelObj, "No kernel to load.");
125
127 "Loading a 32 bit x86 kernel is not supported.");
128
129 ThreadContext *tc = system->threads[0];
130 auto phys_proxy = system->physProxy;
131
132 // This is the boot strap processor (BSP). Initialize it to look like
133 // the boot loader has just turned control over to the 64 bit OS. We
134 // won't actually set up real mode or legacy protected mode descriptor
135 // tables because we aren't executing any code that would require
136 // them. We do, however toggle the control bits in the correct order
137 // while allowing consistency checks and the underlying mechansims
138 // just to be safe.
139
140 const int NumPDTs = 4;
141
142 const Addr PageMapLevel4 = 0x70000;
143 const Addr PageDirPtrTable = 0x71000;
144 const Addr PageDirTable[NumPDTs] =
145 {0x72000, 0x73000, 0x74000, 0x75000};
146 const Addr GDTBase = 0x76000;
147
148 const int PML4Bits = 9;
149 const int PDPTBits = 9;
150 const int PDTBits = 9;
151
152 /*
153 * Set up the gdt.
154 */
155 uint8_t numGDTEntries = 0;
156 // Place holder at selector 0
157 uint64_t nullDescriptor = 0;
158 phys_proxy.writeBlob(GDTBase + numGDTEntries * 8, &nullDescriptor, 8);
159 numGDTEntries++;
160
161 SegDescriptor initDesc = 0;
162 initDesc.type.codeOrData = 0; // code or data type
163 initDesc.type.c = 0; // conforming
164 initDesc.type.r = 1; // readable
165 initDesc.dpl = 0; // privilege
166 initDesc.p = 1; // present
167 initDesc.l = 1; // longmode - 64 bit
168 initDesc.d = 0; // operand size
169 initDesc.g = 1; // granularity
170 initDesc.s = 1; // system segment
171 initDesc.limit = 0xFFFFFFFF;
172 initDesc.base = 0;
173
174 // 64 bit code segment
175 SegDescriptor csDesc = initDesc;
176 csDesc.type.codeOrData = 1;
177 csDesc.dpl = 0;
178 // Because we're dealing with a pointer and I don't think it's
179 // guaranteed that there isn't anything in a nonvirtual class between
180 // it's beginning in memory and it's actual data, we'll use an
181 // intermediary.
182 uint64_t csDescVal = csDesc;
183 phys_proxy.writeBlob(GDTBase + numGDTEntries * 8, (&csDescVal), 8);
184
185 numGDTEntries++;
186
187 SegSelector cs = 0;
188 cs.si = numGDTEntries - 1;
189
191
192 // 32 bit data segment
193 SegDescriptor dsDesc = initDesc;
194 dsDesc.type.e = 0;
195 dsDesc.type.w = 1;
196 dsDesc.d = 1;
197 dsDesc.baseHigh = 0;
198 dsDesc.baseLow = 0;
199
200 uint64_t dsDescVal = dsDesc;
201 phys_proxy.writeBlob(GDTBase + numGDTEntries * 8, (&dsDescVal), 8);
202
203 numGDTEntries++;
204
205 SegSelector ds = 0;
206 ds.si = numGDTEntries - 1;
207
213
215 SegAttr ldtAttr = 0;
216 ldtAttr.unusable = 1;
217 tc->setMiscReg(misc_reg::TslAttr, ldtAttr);
218 tc->setMiscReg(misc_reg::TsgBase, GDTBase);
219 tc->setMiscReg(misc_reg::TsgLimit, 8 * numGDTEntries - 1);
220
221 SegDescriptor tssDesc = initDesc;
222 tssDesc.type = 0xB;
223 tssDesc.s = 0;
224
225 uint64_t tssDescVal = tssDesc;
226 phys_proxy.writeBlob(GDTBase + numGDTEntries * 8, (&tssDescVal), 8);
227
228 numGDTEntries++;
229
230 SegSelector tss = 0;
231 tss.si = numGDTEntries - 1;
232
233 tc->setMiscReg(misc_reg::Tr, (RegVal)tss);
234 installSegDesc(tc, segment_idx::Tr, tssDesc, true);
235
236 /*
237 * Identity map the first 4GB of memory. In order to map this region
238 * of memory in long mode, there needs to be one actual page map level
239 * 4 entry which points to one page directory pointer table which
240 * points to 4 different page directory tables which are full of two
241 * megabyte pages. All of the other entries in valid tables are set
242 * to indicate that they don't pertain to anything valid and will
243 * cause a fault if used.
244 */
245
246 // Put valid values in all of the various table entries which indicate
247 // that those entries don't point to further tables or pages. Then
248 // set the values of those entries which are needed.
249
250 // Page Map Level 4
251
252 // read/write, user, not present
253 uint64_t pml4e = htole<uint64_t>(0x6);
254 for (int offset = 0; offset < (1 << PML4Bits) * 8; offset += 8)
255 phys_proxy.writeBlob(PageMapLevel4 + offset, (&pml4e), 8);
256 // Point to the only PDPT
257 pml4e = htole<uint64_t>(0x7 | PageDirPtrTable);
258 phys_proxy.writeBlob(PageMapLevel4, (&pml4e), 8);
259
260 // Page Directory Pointer Table
261
262 // read/write, user, not present
263 uint64_t pdpe = htole<uint64_t>(0x6);
264 for (int offset = 0; offset < (1 << PDPTBits) * 8; offset += 8)
265 phys_proxy.writeBlob(PageDirPtrTable + offset, &pdpe, 8);
266 // Point to the PDTs
267 for (int table = 0; table < NumPDTs; table++) {
268 pdpe = htole<uint64_t>(0x7 | PageDirTable[table]);
269 phys_proxy.writeBlob(PageDirPtrTable + table * 8, &pdpe, 8);
270 }
271
272 // Page Directory Tables
273
274 Addr base = 0;
275 const Addr pageSize = 2 << 20;
276 for (int table = 0; table < NumPDTs; table++) {
277 for (int offset = 0; offset < (1 << PDTBits) * 8; offset += 8) {
278 // read/write, user, present, 4MB
279 uint64_t pdte = htole(0x87 | base);
280 phys_proxy.writeBlob(PageDirTable[table] + offset, &pdte, 8);
281 base += pageSize;
282 }
283 }
284
285 /*
286 * Transition from real mode all the way up to Long mode
287 */
288 CR0 cr0 = tc->readMiscRegNoEffect(misc_reg::Cr0);
289 // Turn off paging.
290 cr0.pg = 0;
291 tc->setMiscReg(misc_reg::Cr0, cr0);
292 // Turn on protected mode.
293 cr0.pe = 1;
294 tc->setMiscReg(misc_reg::Cr0, cr0);
295
296 CR4 cr4 = tc->readMiscRegNoEffect(misc_reg::Cr4);
297 // Turn on pae.
298 cr4.pae = 1;
299 cr4.osxsave = enable_osxsave;
300 tc->setMiscReg(misc_reg::Cr4, cr4);
301
302 // Point to the page tables.
303 tc->setMiscReg(misc_reg::Cr3, PageMapLevel4);
304
305 // Only used if cr4.osxsave is set
306 XCR0 xcr0 = tc->readMiscRegNoEffect(misc_reg::Xcr0);
307 xcr0.x87 = 1; // Must be 1 according to x86 specification
308 tc->setMiscReg(misc_reg::Xcr0, xcr0);
309
310 Efer efer = tc->readMiscRegNoEffect(misc_reg::Efer);
311 // Enable long mode.
312 efer.lme = 1;
313 tc->setMiscReg(misc_reg::Efer, efer);
314
315 // Start using longmode segments.
316 installSegDesc(tc, segment_idx::Cs, csDesc, true);
317 installSegDesc(tc, segment_idx::Ds, dsDesc, true);
318 installSegDesc(tc, segment_idx::Es, dsDesc, true);
319 installSegDesc(tc, segment_idx::Fs, dsDesc, true);
320 installSegDesc(tc, segment_idx::Gs, dsDesc, true);
321 installSegDesc(tc, segment_idx::Ss, dsDesc, true);
322
323 // Activate long mode.
324 cr0.pg = 1;
325 tc->setMiscReg(misc_reg::Cr0, cr0);
326
328
329 // We should now be in long mode. Yay!
330
331 Addr ebdaPos = 0xF0000;
332 Addr fixed, table;
333
334 // Write out the SMBios/DMI table.
335 writeOutSMBiosTable(ebdaPos, fixed, table);
336 ebdaPos += (fixed + table);
337 ebdaPos = roundUp(ebdaPos, 16);
338
339 // Write out the Intel MP Specification configuration table.
340 writeOutMPTable(ebdaPos, fixed, table);
341 ebdaPos += (fixed + table);
342
343 // Write out ACPI tables
344 writeOutACPITables(ebdaPos, table);
345 ebdaPos += table;
346}
347
348void
350 Addr &headerSize, Addr &structSize, Addr table)
351{
352 // If the table location isn't specified, just put it after the header.
353 // The header size as of the 2.5 SMBios specification is 0x1F bytes.
354 if (!table)
355 table = header + 0x1F;
357
358 smbiosTable->writeOut(system->physProxy, header, headerSize, structSize);
359
360 // Do some bounds checking to make sure we at least didn't step on
361 // ourselves.
362 assert(header > table || header + headerSize <= table);
363 assert(table > header || table + structSize <= header);
364}
365
366void
367FsWorkload::writeOutMPTable(Addr fp, Addr &fpSize, Addr &tableSize, Addr table)
368{
369 // If the table location isn't specified and it exists, just put
370 // it after the floating pointer. The fp size as of the 1.4 Intel MP
371 // specification is 0x10 bytes.
372 if (mpConfigTable) {
373 if (!table)
374 table = fp + 0x10;
376 }
377
378 fpSize = mpFloatingPointer->writeOut(system->physProxy, fp);
379 if (mpConfigTable)
380 tableSize = mpConfigTable->writeOut(system->physProxy, table);
381 else
382 tableSize = 0;
383
384 // Do some bounds checking to make sure we at least didn't step on
385 // ourselves and the fp structure was the size we thought it was.
386 assert(fp > table || fp + fpSize <= table);
387 assert(table > fp || table + tableSize <= fp);
388 assert(fpSize == 0x10);
389}
390
391void
393{
394 fpSize = 0;
395 if (rsdp) {
396 ACPI::LinearAllocator alloc(fp, 0x000FFFFF);
397 rsdp->write(system->physProxy, alloc);
398 fpSize = alloc.alloc(0, 0) - fp;
399 DPRINTF(ACPI, "Wrote ACPI tables to memory at %llx with size %llx.\n",
400 fp, fpSize);
401 }
402}
403
404} // namespace X86ISA
405} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
loader::ObjectFile * kernelObj
SimObjectParams Params
ThreadContext is the external interface to all thread state for anything outside of the CPU.
virtual void setMiscReg(RegIndex misc_reg, RegVal val)=0
virtual const PCStateBase & pcState() const =0
virtual RegVal readMiscRegNoEffect(RegIndex misc_reg) const =0
System * system
Definition workload.hh:81
Addr write(PortProxy &phys_proxy, Allocator &alloc) const
Definition acpi.cc:111
void writeOutACPITables(Addr begin, Addr &size)
void writeOutSMBiosTable(Addr header, Addr &headerSize, Addr &tableSize, Addr table=0)
smbios::SMBiosTable * smbiosTable
void initState() override
initState() is called on each SimObject when not restoring from a checkpoint.
FsWorkload(const Params &p)
intelmp::FloatingPointer * mpFloatingPointer
intelmp::ConfigTable * mpConfigTable
void writeOutMPTable(Addr fp, Addr &fpSize, Addr &tableSize, Addr table=0)
void invoke(ThreadContext *tc, const StaticInstPtr &inst=nullStaticInstPtr) override
Definition faults.cc:183
Addr writeOut(PortProxy &proxy, Addr addr)
Definition intelmp.cc:186
Addr writeOut(PortProxy &proxy, Addr addr)
Definition intelmp.cc:109
void writeOut(PortProxy &proxy, Addr addr, Addr &headerSize, Addr &structSize)
Definition smbios.cc:217
static constexpr T roundUp(const T &val, const U &align)
This function is used to align addresses in memory.
Definition intmath.hh:260
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:236
Bitfield< 19, 16 > fp
Bitfield< 15, 13 > ds
static RegIndex segAttr(int index)
Definition misc.hh:543
static RegIndex segBase(int index)
Definition misc.hh:522
static RegIndex segLimit(int index)
Definition misc.hh:536
static RegIndex segEffBase(int index)
Definition misc.hh:529
Bitfield< 15 > system
Definition misc.hh:1032
Bitfield< 51, 12 > base
Definition pagetable.hh:141
Bitfield< 2, 0 > seg
Definition types.hh:87
void installSegDesc(ThreadContext *tc, int seg, SegDescriptor desc, bool longmode)
Bitfield< 0 > p
Definition pagetable.hh:151
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
uint64_t RegVal
Definition types.hh:173
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
T htole(T value)
Definition byteswap.hh:172
output header
Definition nop.cc:36
Addr alloc(std::size_t size, unsigned align) override
Definition acpi.cc:91

Generated on Tue Jun 18 2024 16:24:00 for gem5 by doxygen 1.11.0