gem5 v24.0.0.0
Loading...
Searching...
No Matches
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
54namespace gem5
55{
56
57void
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
67void
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
81void
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
97void
99 const ArmISA::Affinity &aff, Addr daddr)
100{
101 to->writeRedistributor(aff, daddr, 0xFFFFFFFF);
102}
103
104void
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
114void
117 Addr daddr, size_t size)
118{
119 for (auto a = daddr; a < daddr + size; a += 4)
120 copyDistRegister(from, to, a);
121}
122
123void
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
136void
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);
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
173}
174
175Tick
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
212Tick
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
249void
250Gicv3::sendInt(uint32_t int_id)
251{
252 DPRINTF(Interrupt, "Gicv3::sendInt(): received SPI %d\n", int_id);
253 distributor->sendInt(int_id);
254}
255
256void
257Gicv3::clearInt(uint32_t int_id)
258{
259 DPRINTF(Interrupt, "Gicv3::clearInt(): received SPI %d\n", int_id);
260 distributor->clearInt(int_id);
261}
262
263void
264Gicv3::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
272void
273Gicv3::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
281void
283{
284 auto tc = sys->threads[cpu];
285 tc->getCpuPtr()->postInterrupt(tc->threadId(), int_type, 0);
287}
288
289void
291{
293}
294
295bool
297{
298 return (version == GicVersion::GIC_V3) ||
299 (version == GicVersion::GIC_V4 && params().gicv4);
300}
301
302void
304{
305 auto tc = sys->threads[cpu];
306 tc->getCpuPtr()->clearInterrupt(tc->threadId(), int_type, 0);
307}
308
309void
311{
312 auto tc = sys->threads[cpu];
313 tc->getCpuPtr()->clearInterrupts(tc->threadId());
314}
315
316bool
317Gicv3::haveAsserted(uint32_t cpu) const
318{
319 auto tc = sys->threads[cpu];
320 return tc->getCpuPtr()->checkInterrupts(tc->threadId());
321}
322
324Gicv3::getCPUInterfaceByAffinity(const ArmISA::Affinity &aff) const
325{
327}
328
330Gicv3::getRedistributorByAffinity(const ArmISA::Affinity &aff) const
331{
332 for (auto & redistributor : redistributors) {
333 if (redistributor->getAffinity() == aff) {
334 return redistributor;
335 }
336 }
337
338 return nullptr;
339}
340
343{
345 "Address not pointing to a valid redistributor\n");
346
347 const Addr daddr = addr - redistRange.start();
348 const uint32_t redistributor_id = daddr / redistSize;
349
350 panic_if(redistributor_id >= redistributors.size(),
351 "Invalid redistributor_id!");
352 panic_if(!redistributors[redistributor_id], "Redistributor is null!");
353
354 return redistributors[redistributor_id];
355}
356
357uint32_t
359{
360 return distributor->read(daddr, 4, false);
361}
362
363uint32_t
364Gicv3::readRedistributor(const ArmISA::Affinity &aff, Addr daddr)
365{
366 auto redistributor = getRedistributorByAffinity(aff);
367 assert(redistributor);
368 return redistributor->read(daddr, 4, false);
369}
370
371RegVal
372Gicv3::readCpu(const ArmISA::Affinity &aff, ArmISA::MiscRegIndex misc_reg)
373{
374 auto cpu_interface = getCPUInterfaceByAffinity(aff);
375 assert(cpu_interface);
376 return cpu_interface->readMiscReg(misc_reg);
377}
378
379void
381{
382 distributor->write(daddr, data, sizeof(data), false);
383}
384
385void
386Gicv3::writeRedistributor(const ArmISA::Affinity &aff, Addr daddr, uint32_t data)
387{
388 auto redistributor = getRedistributorByAffinity(aff);
389 assert(redistributor);
390 redistributor->write(daddr, data, sizeof(data), false);
391}
392
393void
394Gicv3::writeCpu(const ArmISA::Affinity &aff, ArmISA::MiscRegIndex misc_reg,
395 RegVal data)
396{
397 auto cpu_interface = getCPUInterfaceByAffinity(aff);
398 assert(cpu_interface);
399 cpu_interface->setMiscReg(misc_reg, data);
400}
401
402void
404{
405 distributor->copy(from, to);
406 for (auto& redistributor : redistributors) {
407 redistributor->copy(from, to);
408 }
409 for (auto& cpu_interface : cpuInterfaces) {
410 cpu_interface->copy(from, to);
411 }
412}
413
414void
416{
417 distributor->serializeSection(cp, "distributor");
418
419 for (uint32_t redistributor_id = 0;
420 redistributor_id < redistributors.size(); redistributor_id++)
421 redistributors[redistributor_id]->serializeSection(cp,
422 csprintf("redistributors.%i", redistributor_id));
423
424 for (uint32_t cpu_interface_id = 0;
425 cpu_interface_id < cpuInterfaces.size(); cpu_interface_id++)
426 cpuInterfaces[cpu_interface_id]->serializeSection(cp,
427 csprintf("cpuInterface.%i", cpu_interface_id));
428}
429
430void
432{
433 getSystem()->setGIC(this);
434
435 distributor->unserializeSection(cp, "distributor");
436
437 for (uint32_t redistributor_id = 0;
438 redistributor_id < redistributors.size(); redistributor_id++)
439 redistributors[redistributor_id]->unserializeSection(cp,
440 csprintf("redistributors.%i", redistributor_id));
441
442 for (uint32_t cpu_interface_id = 0;
443 cpu_interface_id < cpuInterfaces.size(); cpu_interface_id++)
444 cpuInterfaces[cpu_interface_id]->unserializeSection(cp,
445 csprintf("cpuInterface.%i", cpu_interface_id));
446}
447
448} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
static void callClearStandByWfi(ThreadContext *tc)
Make a call to notify the power controller of STANDBYWFI deassertion.
Definition system.cc:207
void setGIC(BaseGic *gic)
Sets the pointer to the GIC.
Definition system.hh:168
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
ArmSystem * getSystem() const
Definition base_gic.hh:114
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)
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:386
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:431
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition gic_v3.cc:415
void deassertInt(uint32_t cpu, ArmISA::InterruptTypes int_type)
Definition gic_v3.cc:303
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:296
friend class Gicv3Distributor
Definition gic_v3.hh:100
uint32_t readRedistributor(const ArmISA::Affinity &aff, Addr daddr) override
Definition gic_v3.cc:364
void writeCpu(const ArmISA::Affinity &aff, ArmISA::MiscRegIndex misc_reg, RegVal data) override
Definition gic_v3.cc:394
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:317
friend class Gicv3CPUInterface
Definition gic_v3.hh:98
void deassertAll(uint32_t cpu)
Definition gic_v3.cc:310
Gicv3CPUInterface * getCPUInterfaceByAffinity(const ArmISA::Affinity &aff) const
Definition gic_v3.cc:324
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:330
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:342
uint32_t readDistributor(Addr daddr) override
Definition gic_v3.cc:358
Gicv3Its * its
Definition gic_v3.hh:105
void postInt(uint32_t cpu, ArmISA::InterruptTypes int_type)
Definition gic_v3.cc:282
void update()
Definition gic_v3.cc:290
std::vector< Gicv3Redistributor * > redistributors
Definition gic_v3.hh:103
void writeDistributor(Addr daddr, uint32_t data) override
Definition gic_v3.cc:380
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:372
void copyGicState(Gicv3Registers *from, Gicv3Registers *to)
Definition gic_v3.cc:403
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:295
bool isSecure() const
Definition packet.hh:836
Addr getAddr() const
Definition packet.hh:807
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:377
unsigned getSize() const
Definition packet.hh:817
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:1074
int size() const
Definition system.hh:210
Threads threads
Definition system.hh:310
AddrRange RangeSize(Addr start, Addr size)
bool contains(const Addr &a) const
Determine if the range contains an address.
Addr start() const
Get the start address of the range.
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:188
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:214
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
const char *const miscRegName[]
Definition misc.hh:1815
Bitfield< 0 > p
Bitfield< 25, 21 > to
Definition types.hh:96
Bitfield< 63 > val
Definition misc.hh:804
Bitfield< 3 > addr
Definition types.hh:84
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
uint64_t RegVal
Definition types.hh:173
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
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
Declaration of the Packet class.
Generic interface for platforms.

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