gem5  v22.1.0.0
gic_v3.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019-2022 Arm Limited
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  * Copyright (c) 2018 Metempsy Technology Consulting
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are
19  * met: redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer;
21  * redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in the
23  * documentation and/or other materials provided with the distribution;
24  * neither the name of the copyright holders nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  */
40 
41 #include "dev/arm/gic_v3.hh"
42 
43 #include "cpu/base.hh"
44 #include "debug/GIC.hh"
45 #include "debug/Interrupt.hh"
48 #include "dev/arm/gic_v3_its.hh"
50 #include "dev/platform.hh"
51 #include "mem/packet.hh"
52 #include "mem/packet_access.hh"
53 
54 namespace gem5
55 {
56 
57 void
60  Addr daddr)
61 {
62  auto val = from->readDistributor(daddr);
63  DPRINTF(GIC, "copy dist 0x%x 0x%08x\n", daddr, val);
64  to->writeDistributor(daddr, val);
65 }
66 
67 void
70  const ArmISA::Affinity &aff, Addr daddr)
71 {
72  auto val = from->readRedistributor(aff, daddr);
73  DPRINTF(GIC,
74  "copy redist (aff3: %d, aff2: %d, aff1: %d, aff0: %d) "
75  "0x%x 0x%08x\n",
76  aff.aff3, aff.aff2, aff.aff1, aff.aff0, daddr, val);
77 
78  to->writeRedistributor(aff, daddr, val);
79 }
80 
81 void
84  const ArmISA::Affinity &aff,
85  ArmISA::MiscRegIndex misc_reg)
86 {
87  auto val = from->readCpu(aff, misc_reg);
88  DPRINTF(GIC,
89  "copy cpu (aff3: %d, aff2: %d, aff1: %d, aff0: %d) "
90  "%s 0x%08x\n",
91  aff.aff3, aff.aff2, aff.aff1, aff.aff0,
92  ArmISA::miscRegName[misc_reg], val);
93 
94  to->writeCpu(aff, misc_reg, val);
95 }
96 
97 void
99  const ArmISA::Affinity &aff, Addr daddr)
100 {
101  to->writeRedistributor(aff, daddr, 0xFFFFFFFF);
102 }
103 
104 void
107  const ArmISA::Affinity &aff,
108  Addr daddr, size_t size)
109 {
110  for (auto a = daddr; a < daddr + size; a += 4)
111  copyRedistRegister(from, to, aff, a);
112 }
113 
114 void
117  Addr daddr, size_t size)
118 {
119  for (auto a = daddr; a < daddr + size; a += 4)
120  copyDistRegister(from, to, a);
121 }
122 
123 void
125 {
126  for (auto a = daddr; a < daddr + size; a += 4)
127  to->writeDistributor(a, 0xFFFFFFFF);
128 }
129 
130 
132  : BaseGic(p)
133 {
134 }
135 
136 void
138 {
139  distributor = new Gicv3Distributor(this, params().it_lines);
140  int threads = sys->threads.size();
141  redistributors.resize(threads, nullptr);
142  cpuInterfaces.resize(threads, nullptr);
143 
144  panic_if(threads > params().cpu_max,
145  "Exceeding maximum number of PEs supported by GICv3: "
146  "using %u while maximum is %u.", threads, params().cpu_max);
147 
148  for (int i = 0; i < threads; i++) {
149  redistributors[i] = new Gicv3Redistributor(this, i);
150  cpuInterfaces[i] = new Gicv3CPUInterface(this, sys->threads[i]);
151  }
152 
153  distRange = RangeSize(params().dist_addr,
155 
156  redistSize = redistributors[0]->addrRangeSize;
157  redistRange = RangeSize(params().redist_addr, redistSize * threads);
158 
160 
161  distributor->init();
162 
163  for (int i = 0; i < threads; i++) {
164  redistributors[i]->init();
165  cpuInterfaces[i]->init();
166  }
167 
168  Gicv3Its *its = params().its;
169  if (its)
170  its->setGIC(this);
171 
172  BaseGic::init();
173 }
174 
175 Tick
177 {
178  const Addr addr = pkt->getAddr();
179  const size_t size = pkt->getSize();
180  bool is_secure_access = pkt->isSecure();
181  uint64_t resp = 0;
182  Tick delay = 0;
183 
184  if (distRange.contains(addr)) {
185  const Addr daddr = addr - distRange.start();
186  panic_if(!distributor, "Distributor is null!");
187  resp = distributor->read(daddr, size, is_secure_access);
188  delay = params().dist_pio_delay;
189  DPRINTF(GIC, "Gicv3::read(): (distributor) context_id %d register %#x "
190  "size %d is_secure_access %d (value %#x)\n",
191  pkt->req->contextId(), daddr, size, is_secure_access, resp);
192  } else if (redistRange.contains(addr)) {
193  Addr daddr = (addr - redistRange.start()) % redistSize;
194 
196  resp = redist->read(daddr, size, is_secure_access);
197 
198  delay = params().redist_pio_delay;
199  DPRINTF(GIC, "Gicv3::read(): (redistributor %d) context_id %d "
200  "register %#x size %d is_secure_access %d (value %#x)\n",
201  redist->processorNumber(), pkt->req->contextId(), daddr, size,
202  is_secure_access, resp);
203  } else {
204  panic("Gicv3::read(): unknown address %#x\n", addr);
205  }
206 
207  pkt->setUintX(resp, ByteOrder::little);
208  pkt->makeAtomicResponse();
209  return delay;
210 }
211 
212 Tick
214 {
215  const size_t size = pkt->getSize();
216  uint64_t data = pkt->getUintX(ByteOrder::little);
217  const Addr addr = pkt->getAddr();
218  bool is_secure_access = pkt->isSecure();
219  Tick delay = 0;
220 
221  if (distRange.contains(addr)) {
222  const Addr daddr = addr - distRange.start();
223  panic_if(!distributor, "Distributor is null!");
224  DPRINTF(GIC, "Gicv3::write(): (distributor) context_id %d "
225  "register %#x size %d is_secure_access %d value %#x\n",
226  pkt->req->contextId(), daddr, size, is_secure_access, data);
227  distributor->write(daddr, data, size, is_secure_access);
228  delay = params().dist_pio_delay;
229  } else if (redistRange.contains(addr)) {
230  Addr daddr = (addr - redistRange.start()) % redistSize;
231 
233  DPRINTF(GIC, "Gicv3::write(): (redistributor %d) context_id %d "
234  "register %#x size %d is_secure_access %d value %#x\n",
235  redist->processorNumber(), pkt->req->contextId(), daddr, size,
236  is_secure_access, data);
237 
238  redist->write(daddr, data, size, is_secure_access);
239 
240  delay = params().redist_pio_delay;
241  } else {
242  panic("Gicv3::write(): unknown address %#x\n", addr);
243  }
244 
245  pkt->makeAtomicResponse();
246  return delay;
247 }
248 
249 void
250 Gicv3::sendInt(uint32_t int_id)
251 {
252  DPRINTF(Interrupt, "Gicv3::sendInt(): received SPI %d\n", int_id);
253  distributor->sendInt(int_id);
254 }
255 
256 void
257 Gicv3::clearInt(uint32_t int_id)
258 {
259  DPRINTF(Interrupt, "Gicv3::clearInt(): received SPI %d\n", int_id);
260  distributor->clearInt(int_id);
261 }
262 
263 void
264 Gicv3::sendPPInt(uint32_t int_id, uint32_t cpu)
265 {
266  panic_if(cpu >= redistributors.size(), "Invalid cpuID sending PPI!");
267  DPRINTF(Interrupt, "Gicv3::sendPPInt(): received PPI %d cpuTarget %#x\n",
268  int_id, cpu);
269  redistributors[cpu]->sendPPInt(int_id);
270 }
271 
272 void
273 Gicv3::clearPPInt(uint32_t int_id, uint32_t cpu)
274 {
275  panic_if(cpu >= redistributors.size(), "Invalid cpuID clearing PPI!");
276  DPRINTF(Interrupt, "Gicv3::clearPPInt(): received PPI %d cpuTarget %#x\n",
277  int_id, cpu);
278  redistributors[cpu]->clearPPInt(int_id);
279 }
280 
281 void
283 {
284  auto tc = sys->threads[cpu];
285  tc->getCpuPtr()->postInterrupt(tc->threadId(), int_type, 0);
287 }
288 
289 bool
291 {
292  return (version == GicVersion::GIC_V3) ||
293  (version == GicVersion::GIC_V4 && params().gicv4);
294 }
295 
296 void
298 {
299  auto tc = sys->threads[cpu];
300  tc->getCpuPtr()->clearInterrupt(tc->threadId(), int_type, 0);
301 }
302 
303 void
304 Gicv3::deassertAll(uint32_t cpu)
305 {
306  auto tc = sys->threads[cpu];
307  tc->getCpuPtr()->clearInterrupts(tc->threadId());
308 }
309 
310 bool
311 Gicv3::haveAsserted(uint32_t cpu) const
312 {
313  auto tc = sys->threads[cpu];
314  return tc->getCpuPtr()->checkInterrupts(tc->threadId());
315 }
316 
318 Gicv3::getCPUInterfaceByAffinity(const ArmISA::Affinity &aff) const
319 {
321 }
322 
324 Gicv3::getRedistributorByAffinity(const ArmISA::Affinity &aff) const
325 {
326  for (auto & redistributor : redistributors) {
327  if (redistributor->getAffinity() == aff) {
328  return redistributor;
329  }
330  }
331 
332  return nullptr;
333 }
334 
337 {
339  "Address not pointing to a valid redistributor\n");
340 
341  const Addr daddr = addr - redistRange.start();
342  const uint32_t redistributor_id = daddr / redistSize;
343 
344  panic_if(redistributor_id >= redistributors.size(),
345  "Invalid redistributor_id!");
346  panic_if(!redistributors[redistributor_id], "Redistributor is null!");
347 
348  return redistributors[redistributor_id];
349 }
350 
351 uint32_t
353 {
354  return distributor->read(daddr, 4, false);
355 }
356 
357 uint32_t
358 Gicv3::readRedistributor(const ArmISA::Affinity &aff, Addr daddr)
359 {
360  auto redistributor = getRedistributorByAffinity(aff);
361  assert(redistributor);
362  return redistributor->read(daddr, 4, false);
363 }
364 
365 RegVal
366 Gicv3::readCpu(const ArmISA::Affinity &aff, ArmISA::MiscRegIndex misc_reg)
367 {
368  auto cpu_interface = getCPUInterfaceByAffinity(aff);
369  assert(cpu_interface);
370  return cpu_interface->readMiscReg(misc_reg);
371 }
372 
373 void
375 {
376  distributor->write(daddr, data, sizeof(data), false);
377 }
378 
379 void
380 Gicv3::writeRedistributor(const ArmISA::Affinity &aff, Addr daddr, uint32_t data)
381 {
382  auto redistributor = getRedistributorByAffinity(aff);
383  assert(redistributor);
384  redistributor->write(daddr, data, sizeof(data), false);
385 }
386 
387 void
388 Gicv3::writeCpu(const ArmISA::Affinity &aff, ArmISA::MiscRegIndex misc_reg,
389  RegVal data)
390 {
391  auto cpu_interface = getCPUInterfaceByAffinity(aff);
392  assert(cpu_interface);
393  cpu_interface->setMiscReg(misc_reg, data);
394 }
395 
396 void
398 {
399  distributor->copy(from, to);
400  for (auto& redistributor : redistributors) {
401  redistributor->copy(from, to);
402  }
403  for (auto& cpu_interface : cpuInterfaces) {
404  cpu_interface->copy(from, to);
405  }
406 }
407 
408 void
410 {
411  distributor->serializeSection(cp, "distributor");
412 
413  for (uint32_t redistributor_id = 0;
414  redistributor_id < redistributors.size(); redistributor_id++)
415  redistributors[redistributor_id]->serializeSection(cp,
416  csprintf("redistributors.%i", redistributor_id));
417 
418  for (uint32_t cpu_interface_id = 0;
419  cpu_interface_id < cpuInterfaces.size(); cpu_interface_id++)
420  cpuInterfaces[cpu_interface_id]->serializeSection(cp,
421  csprintf("cpuInterface.%i", cpu_interface_id));
422 }
423 
424 void
426 {
427  getSystem()->setGIC(this);
428 
429  distributor->unserializeSection(cp, "distributor");
430 
431  for (uint32_t redistributor_id = 0;
432  redistributor_id < redistributors.size(); redistributor_id++)
433  redistributors[redistributor_id]->unserializeSection(cp,
434  csprintf("redistributors.%i", redistributor_id));
435 
436  for (uint32_t cpu_interface_id = 0;
437  cpu_interface_id < cpuInterfaces.size(); cpu_interface_id++)
438  cpuInterfaces[cpu_interface_id]->unserializeSection(cp,
439  csprintf("cpuInterface.%i", cpu_interface_id));
440 }
441 
442 } // namespace gem5
#define DPRINTF(x,...)
Definition: trace.hh:186
const char data[]
static void callClearStandByWfi(ThreadContext *tc)
Make a call to notify the power controller of STANDBYWFI deassertion.
Definition: system.cc:206
void setGIC(BaseGic *gic)
Sets the pointer to the GIC.
Definition: system.hh:165
ArmSystem * getSystem() const
Definition: base_gic.hh:114
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: base_gic.cc:71
const Params & params() const
Definition: base_gic.cc:78
BaseGicParams Params
Definition: base_gic.hh:75
void sendInt(uint32_t int_id)
void clearInt(uint32_t int_id)
void copy(Gicv3Registers *from, Gicv3Registers *to)
static const uint32_t ADDR_RANGE_SIZE
void write(Addr addr, uint64_t data, size_t size, bool is_secure_access)
uint64_t read(Addr addr, size_t size, bool is_secure_access)
GICv3 ITS module.
Definition: gic_v3_its.hh:84
void setGIC(Gicv3 *_gic)
Definition: gic_v3_its.cc:808
Gicv3CPUInterface * getCPUInterface() const
uint64_t read(Addr addr, size_t size, bool is_secure_access)
void write(Addr addr, uint64_t data, size_t size, bool is_secure_access)
static void clearRedistRegister(Gicv3Registers *to, const ArmISA::Affinity &aff, Addr daddr)
Definition: gic_v3.cc:98
static void clearDistRange(Gicv3Registers *to, Addr daddr, size_t size)
Definition: gic_v3.cc:124
static void copyRedistRange(Gicv3Registers *from, Gicv3Registers *to, const ArmISA::Affinity &aff, Addr daddr, size_t size)
Definition: gic_v3.cc:105
static void copyDistRegister(Gicv3Registers *from, Gicv3Registers *to, Addr daddr)
Definition: gic_v3.cc:58
virtual uint32_t readRedistributor(const ArmISA::Affinity &aff, Addr daddr)=0
static void copyCpuRegister(Gicv3Registers *from, Gicv3Registers *to, const ArmISA::Affinity &aff, ArmISA::MiscRegIndex misc_reg)
Definition: gic_v3.cc:82
static void copyRedistRegister(Gicv3Registers *from, Gicv3Registers *to, const ArmISA::Affinity &aff, Addr daddr)
Definition: gic_v3.cc:68
static void copyDistRange(Gicv3Registers *from, Gicv3Registers *to, Addr daddr, size_t size)
Definition: gic_v3.cc:115
virtual uint32_t readDistributor(Addr daddr)=0
virtual RegVal readCpu(const ArmISA::Affinity &aff, ArmISA::MiscRegIndex misc_reg)=0
void writeRedistributor(const ArmISA::Affinity &aff, Addr daddr, uint32_t data) override
Definition: gic_v3.cc:380
void init() override
init() is called after all C++ SimObjects have been created and all ports are connected.
Definition: gic_v3.cc:137
Gicv3(const Params &p)
Definition: gic_v3.cc:131
void clearPPInt(uint32_t int_id, uint32_t cpu) override
Definition: gic_v3.cc:273
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: gic_v3.cc:425
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: gic_v3.cc:409
void deassertInt(uint32_t cpu, ArmISA::InterruptTypes int_type)
Definition: gic_v3.cc:297
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: gic_v3.cc:176
bool supportsVersion(GicVersion version) override
Check if version supported.
Definition: gic_v3.cc:290
friend class Gicv3Distributor
Definition: gic_v3.hh:100
uint32_t readRedistributor(const ArmISA::Affinity &aff, Addr daddr) override
Definition: gic_v3.cc:358
void writeCpu(const ArmISA::Affinity &aff, ArmISA::MiscRegIndex misc_reg, RegVal data) override
Definition: gic_v3.cc:388
friend class Gicv3Redistributor
Definition: gic_v3.hh:99
AddrRangeList addrRanges
Definition: gic_v3.hh:108
bool haveAsserted(uint32_t cpu) const
Definition: gic_v3.cc:311
friend class Gicv3CPUInterface
Definition: gic_v3.hh:98
void deassertAll(uint32_t cpu)
Definition: gic_v3.cc:304
Gicv3CPUInterface * getCPUInterfaceByAffinity(const ArmISA::Affinity &aff) const
Definition: gic_v3.cc:318
std::vector< Gicv3CPUInterface * > cpuInterfaces
Definition: gic_v3.hh:104
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition: gic_v3.cc:213
Gicv3Redistributor * getRedistributorByAffinity(const ArmISA::Affinity &aff) const
Definition: gic_v3.cc:324
AddrRange redistRange
Definition: gic_v3.hh:107
void clearInt(uint32_t int_id) override
Clear an interrupt from a device that is connected to the GIC.
Definition: gic_v3.cc:257
Gicv3Redistributor * getRedistributorByAddr(Addr address) const
Definition: gic_v3.cc:336
uint32_t readDistributor(Addr daddr) override
Definition: gic_v3.cc:352
Gicv3Its * its
Definition: gic_v3.hh:105
void postInt(uint32_t cpu, ArmISA::InterruptTypes int_type)
Definition: gic_v3.cc:282
std::vector< Gicv3Redistributor * > redistributors
Definition: gic_v3.hh:103
void writeDistributor(Addr daddr, uint32_t data) override
Definition: gic_v3.cc:374
void sendInt(uint32_t int_id) override
Post an interrupt from a device that is connected to the GIC.
Definition: gic_v3.cc:250
RegVal readCpu(const ArmISA::Affinity &aff, ArmISA::MiscRegIndex misc_reg) override
Definition: gic_v3.cc:366
void copyGicState(Gicv3Registers *from, Gicv3Registers *to)
Definition: gic_v3.cc:397
Gicv3Distributor * distributor
Definition: gic_v3.hh:102
void sendPPInt(uint32_t int_id, uint32_t cpu) override
Interface call for private peripheral interrupts.
Definition: gic_v3.cc:264
AddrRange distRange
Definition: gic_v3.hh:106
uint64_t redistSize
Definition: gic_v3.hh:109
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
bool isSecure() const
Definition: packet.hh:834
Addr getAddr() const
Definition: packet.hh:805
void setUintX(uint64_t w, ByteOrder endian)
Set the value in the word w after truncating it to the length of the packet and then byteswapping it ...
Definition: packet.cc:361
RequestPtr req
A pointer to the original request.
Definition: packet.hh:376
unsigned getSize() const
Definition: packet.hh:815
uint64_t getUintX(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness and zero-extended to 64 bits.
Definition: packet.cc:352
void makeAtomicResponse()
Definition: packet.hh:1071
System * sys
Definition: io_device.hh:105
int size() const
Definition: system.hh:213
Threads threads
Definition: system.hh:313
AddrRange RangeSize(Addr start, Addr size)
Definition: addr_range.hh:815
bool contains(const Addr &a) const
Determine if the range contains an address.
Definition: addr_range.hh:471
Addr start() const
Get the start address of the range.
Definition: addr_range.hh:343
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:204
void serializeSection(CheckpointOut &cp, const char *name) const
Serialize an object into a new section.
Definition: serialize.cc:74
void unserializeSection(CheckpointIn &cp, const char *name)
Unserialize an a child object.
Definition: serialize.cc:81
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 8 > a
Definition: misc_types.hh:66
MiscRegIndex
Definition: misc.hh:64
const char *const miscRegName[]
Definition: misc.hh:1697
Bitfield< 25, 21 > to
Definition: types.hh:96
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 63 > val
Definition: misc.hh:776
Bitfield< 3 > addr
Definition: types.hh:84
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
std::ostream CheckpointOut
Definition: serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
uint64_t Tick
Tick count type.
Definition: types.hh:58
uint64_t RegVal
Definition: types.hh:173
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
int64 int_type
Definition: sc_nbdefs.hh:206
Declaration of the Packet class.
Generic interface for platforms.

Generated on Wed Dec 21 2022 10:22:32 for gem5 by doxygen 1.9.1