gem5  v22.1.0.0
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 
50 namespace gem5
51 {
52 
53 namespace X86ISA
54 {
55 
56 namespace ACPI
57 {
58 
59 static void
60 fillCopy(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 
73 static void
74 fillCopy(void *dest, size_t dest_size, const std::string &src)
75 {
76  fillCopy(dest, dest_size, src.c_str(), src.length());
77 }
78 
79 const char RSDP::signature[] = "RSD PTR ";
80 
81 static uint8_t
82 apic_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 
90 Addr
91 LinearAllocator::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 
104 RSDP::RSDP(const Params &p) :
105  SimObject(p),
106  rsdt(p.rsdt),
107  xsdt(p.xsdt)
108 {}
109 
110 Addr
111 RSDP::write(PortProxy& phys_proxy, Allocator& alloc) const
112 {
113  std::vector<uint8_t> mem(sizeof(Mem));
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 
143 Addr
145  std::vector<uint8_t> &mem) const
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 
179 template<class T>
180 RXSDT<T>::RXSDT(const Params& p, const char *_signature, uint8_t _revision) :
181  SysDescTable(p, _signature, _revision)
182 {}
183 
184 template<class T>
187  std::vector<uint8_t>& mem) const
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 
211 RSDT::RSDT(const Params& p) : RXSDT(p, "RSDT", 1)
212 {
213  entries = p.entries;
214 }
215 
216 XSDT::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 
228 Addr
230  std::vector<uint8_t>& mem) const
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 
252 void
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 
264 void
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 
278 void
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 
292 void
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 
307 void
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 
322 void
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:186
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, int size) const
Same as tryWriteBlob, but insists on success.
Definition: port_proxy.hh:192
Abstract superclass for simulation objects.
Definition: sim_object.hh:148
SimObjectParams Params
Definition: sim_object.hh:170
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
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition: logging.hh:226
const Params & params() const
Definition: sim_object.hh:176
uint8_t flags
Definition: helpers.cc:66
Port Object Declaration.
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 18 > sum
Definition: misc.hh:560
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
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
void align(const scfx_rep &lhs, const scfx_rep &rhs, int &new_wp, int &len_mant, scfx_mant_ref &lhs_mant, scfx_mant_ref &rhs_mant)
Definition: scfx_rep.cc:2051
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 Wed Dec 21 2022 10:22:28 for gem5 by doxygen 1.9.1