gem5 v24.0.0.0
Loading...
Searching...
No Matches
acpi.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008 The Hewlett-Packard Development Company
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include "arch/x86/bios/acpi.hh"
39
40#include <algorithm>
41#include <cassert>
42#include <cstring>
43
44#include "base/trace.hh"
45#include "mem/port.hh"
46#include "mem/port_proxy.hh"
47#include "sim/byteswap.hh"
48#include "sim/sim_object.hh"
49
50namespace gem5
51{
52
53namespace X86ISA
54{
55
56namespace ACPI
57{
58
59static void
60fillCopy(void *dest, size_t dest_size, const void *src, size_t src_size)
61{
62 src_size = std::min(src_size, dest_size);
63 const size_t zero_size = dest_size - src_size;
64
65 uint8_t *pos = (uint8_t *)dest;
66
67 std::memcpy(pos, src, src_size);
68 pos += src_size;
69
70 std::memset(pos, 0, zero_size);
71}
72
73static void
74fillCopy(void *dest, size_t dest_size, const std::string &src)
75{
76 fillCopy(dest, dest_size, src.c_str(), src.length());
77}
78
79const char RSDP::signature[] = "RSD PTR ";
80
81static uint8_t
82apic_checksum(uint8_t* ptr, std::size_t size)
83{
84 uint8_t sum = 0;
85 for (unsigned i = 0; i < size; ++i)
86 sum += ptr[i];
87 return 0x100 - sum;
88}
89
90Addr
91LinearAllocator::alloc(std::size_t size, unsigned align)
92{
93 if (align) {
94 unsigned offset = next % align;
95 if (offset)
96 next += (align - offset);
97 }
98 Addr chunk = next;
99 next += size;
100 assert(0 == end || next <= end);
101 return chunk;
102}
103
105 SimObject(p),
106 rsdt(p.rsdt),
107 xsdt(p.xsdt)
108{}
109
110Addr
111RSDP::write(PortProxy& phys_proxy, Allocator& alloc) const
112{
114 Addr addr = alloc.alloc(mem.size(), 16);
115
116 Mem* data = (Mem*)mem.data();
117 static_assert(sizeof(signature) - 1 == sizeof(data->signature),
118 "signature length mismatch");
119 std::memcpy(data->signature, signature, sizeof(data->signature));
120 fillCopy(data->oemID, sizeof(data->oemID), params().oem_id);
121 data->revision = params().revision;
122 data->length = mem.size();
123
124 if (rsdt) {
125 data->rsdtAddress = rsdt->write(phys_proxy, alloc);
126 DPRINTF(ACPI, "Allocated RSDT @ %llx\n", data->rsdtAddress);
127 }
128 if (xsdt) {
129 data->xsdtAddress = xsdt->write(phys_proxy, alloc);
130 DPRINTF(ACPI, "Allocated XSDT @ %llx\n", data->xsdtAddress);
131 }
132
133 // checksum calculation
134 data->checksum = apic_checksum(mem.data(), sizeof(MemR0));
135 data->extendedChecksum = apic_checksum(mem.data(), mem.size());
136
137 // write the whole thing
138 phys_proxy.writeBlob(addr, mem.data(), mem.size());
139
140 return addr;
141}
142
143Addr
146{
147 // An empty SysDescTable doesn't make any sense, so assert that somebody
148 // else allocated a large enough blob.
149 assert(mem.size() >= sizeof(Mem));
150
151 // Allocate a place to write this blob.
152 Addr addr = alloc.alloc(mem.size());
153
154 DPRINTF(ACPI, "Writing system description table [%llx - %llx]\n", addr,
155 addr + mem.size());
156
157 // Fill in the header.
158 auto& p = params();
159 Mem* header = (Mem*)mem.data();
160 fillCopy(header->signature, sizeof(header->signature), signature);
161 header->length = mem.size();
162 header->revision = revision;
163 fillCopy(header->oemID, sizeof(header->oemID), p.oem_id);
164 fillCopy(header->oemTableID, sizeof(header->oemTableID), p.oem_table_id);
165 header->oemRevision = p.oem_revision;
166 header->creatorID = p.creator_id;
167 header->creatorRevision = p.creator_revision;
168
169 // Update checksum.
170 header->checksum = apic_checksum(mem.data(), mem.size());
171
172 // Write to memory.
173 phys_proxy.writeBlob(addr, mem.data(), mem.size());
174
175 return addr;
176}
177
179template<class T>
180RXSDT<T>::RXSDT(const Params& p, const char *_signature, uint8_t _revision) :
181 SysDescTable(p, _signature, _revision)
182{}
183
184template<class T>
188{
189 // Since this table ends with a variably sized array, it can't be extended
190 // by another table type.
191 assert(mem.empty());
192 mem.resize(sizeof(Mem));
193
194 auto base_size = mem.size();
195 mem.resize(base_size + sizeof(Ptr) * entries.size());
196
197 Ptr* ptr_array = reinterpret_cast<Ptr*>(mem.data() + base_size);
198 DPRINTF(ACPI, "RXSDT: Writing %d entries (ptr size: %d)\n", entries.size(),
199 sizeof(Ptr));
200 for (const auto *entry : entries) {
201 Addr entry_addr = entry->write(phys_proxy, alloc);
202 fatal_if((entry_addr & mask(sizeof(Ptr) * 8)) != entry_addr,
203 "RXSDT: Entry address doesn't fit in pointer type.");
204 DPRINTF(ACPI, "RXSDT: wrote entry @ %llx\n", entry_addr);
205 *ptr_array++ = entry_addr;
206 }
207
208 return SysDescTable::writeBuf(phys_proxy, alloc, mem);
209}
210
211RSDT::RSDT(const Params& p) : RXSDT(p, "RSDT", 1)
212{
213 entries = p.entries;
214}
215
216XSDT::XSDT(const Params& p) : RXSDT(p, "XSDT", 1)
217{
218 entries = p.entries;
219}
220
221
224 SysDescTable(p, "APIC", 4),
225 records(p.records)
226{}
227
228Addr
231{
232 // Since this table ends with a variably sized array, it can't be extended
233 // by another table type.
234 assert(mem.empty());
235 mem.resize(sizeof(Mem));
236
237 Mem* header = reinterpret_cast<Mem*>(mem.data());
238 header->localAPICAddress = params().local_apic_address;
239 header->flags = params().flags;
240
241 for (const auto& record : records) {
242 auto entry = record->prepare();
243 mem.insert(mem.end(), entry.begin(), entry.end());
244 }
245
246 DPRINTF(ACPI, "MADT: writing %d records (size: %d)\n",
247 records.size(), mem.size());
248
249 return SysDescTable::writeBuf(phys_proxy, alloc, mem);
250}
251
252void
254{
255 assert(mem.size() >= sizeof(Mem));
256 DPRINTF(ACPI, "MADT: writing record type %d (size: %d)\n",
257 type, mem.size());
258
259 Mem* header = reinterpret_cast<Mem*>(mem.data());
260 header->type = type;
261 header->length = mem.size();
262}
263
264void
266{
267 assert(mem.empty());
268 mem.resize(sizeof(Mem));
269
270 Mem* data = reinterpret_cast<Mem*>(mem.data());
271 data->acpiProcessorId = params().acpi_processor_id;
272 data->apicId = params().apic_id;
273 data->flags = params().flags;
274
276}
277
278void
280{
281 assert(mem.empty());
282 mem.resize(sizeof(Mem));
283
284 Mem* data = reinterpret_cast<Mem*>(mem.data());
285 data->ioApicId = params().id;
286 data->ioApicAddress = params().address;
287 data->intBase = params().int_base;
288
290}
291
292void
294{
295 assert(mem.empty());
296 mem.resize(sizeof(Mem));
297
298 Mem* data = reinterpret_cast<Mem*>(mem.data());
299 data->busSource = params().bus_source;
300 data->irqSource = params().irq_source;
301 data->globalSystemInterrupt = params().sys_int;
302 data->flags = params().flags;
303
305}
306
307void
309{
310 assert(mem.empty());
311 mem.resize(sizeof(Mem));
312
313 Mem* data = reinterpret_cast<Mem*>(mem.data());
314 data->acpiProcessorId = params().acpi_processor_id;
315 // The "flags" field is not properly aligned.
316 memcpy(&data->flags, &params().flags, sizeof(data->flags));
317 data->lintNo = params().lint_no;
318
320}
321
322void
324{
325 assert(mem.empty());
326 mem.resize(sizeof(Mem));
327
328 Mem* data = reinterpret_cast<Mem*>(mem.data());
329 data->localAPICAddress = params().address;
330
332}
333
334} // namespace ACPI
335
336} // namespace X86ISA
337} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
This object is a proxy for a port or other object which implements the functional response protocol,...
Definition port_proxy.hh:87
void writeBlob(Addr addr, const void *p, uint64_t size) const
Same as tryWriteBlob, but insists on success.
Abstract superclass for simulation objects.
SimObjectParams Params
void prepareBuf(std::vector< uint8_t > &mem) const override
Definition acpi.cc:279
void prepareBuf(std::vector< uint8_t > &mem) const override
Definition acpi.cc:293
void prepareBuf(std::vector< uint8_t > &mem) const override
Definition acpi.cc:323
void prepareBuf(std::vector< uint8_t > &mem) const override
Definition acpi.cc:265
MADT(const Params &p)
Definition acpi.cc:223
Addr writeBuf(PortProxy &phys_proxy, Allocator &alloc, std::vector< uint8_t > &mem) const override
Definition acpi.cc:229
void prepareBuf(std::vector< uint8_t > &mem) const override
Definition acpi.cc:308
virtual void prepareBuf(std::vector< uint8_t > &mem) const =0
Definition acpi.cc:253
static const char signature[]
Definition acpi.hh:99
RSDP(const Params &p)
Definition acpi.cc:104
Addr write(PortProxy &phys_proxy, Allocator &alloc) const
Definition acpi.cc:111
RSDT(const Params &p)
Definition acpi.cc:211
std::vector< SysDescTable * > entries
Definition acpi.hh:179
Addr writeBuf(PortProxy &phys_proxy, Allocator &alloc, std::vector< uint8_t > &mem) const override
Definition acpi.cc:186
RXSDT(const Params &p, const char *_signature, uint8_t _revision)
Definition acpi.cc:180
virtual Addr writeBuf(PortProxy &phys_proxy, Allocator &alloc, std::vector< uint8_t > &mem) const =0
Definition acpi.cc:144
Addr write(PortProxy &phys_proxy, Allocator &alloc) const
Definition acpi.hh:166
XSDT(const Params &p)
Definition acpi.cc:216
STL vector class.
Definition stl.hh:37
#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
const Params & params() const
uint8_t flags
Definition helpers.cc:87
Port Object Declaration.
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 18 > sum
Definition misc.hh:1198
static uint8_t apic_checksum(uint8_t *ptr, std::size_t size)
Definition acpi.cc:82
static void fillCopy(void *dest, size_t dest_size, const void *src, size_t src_size)
Definition acpi.cc:60
Bitfield< 3 > addr
Definition types.hh:84
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 Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
output header
Definition nop.cc:36
PortProxy Object Declaration.
virtual Addr alloc(std::size_t size, unsigned align=1)=0
Addr alloc(std::size_t size, unsigned align) override
Definition acpi.cc:91
bool_vector8 mem[]
Definition reset_stim.h:43

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