gic_v3_redistributor.cc (13531:e6f1bf55d038) gic_v3_redistributor.cc (13690:284050bbec68)
1/*
2 * Copyright (c) 2018 Metempsy Technology Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Jairo Balart
29 */
30
31#include "dev/arm/gic_v3_redistributor.hh"
32
33#include "arch/arm/utility.hh"
34#include "debug/GIC.hh"
35#include "dev/arm/gic_v3_cpu_interface.hh"
36#include "dev/arm/gic_v3_distributor.hh"
1/*
2 * Copyright (c) 2018 Metempsy Technology Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Jairo Balart
29 */
30
31#include "dev/arm/gic_v3_redistributor.hh"
32
33#include "arch/arm/utility.hh"
34#include "debug/GIC.hh"
35#include "dev/arm/gic_v3_cpu_interface.hh"
36#include "dev/arm/gic_v3_distributor.hh"
37#include "mem/fs_translating_port_proxy.hh"
37
38const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
39 SGI_base + 0x041f);
40
41Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id)
42 : gic(gic),
43 distributor(nullptr),
44 cpuInterface(nullptr),
45 cpuId(cpu_id),
46 irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
47 irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
48 irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
49 irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
50 irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
51 irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
52 irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
53 irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX)
54{
55}
56
57Gicv3Redistributor::~Gicv3Redistributor()
58{
59}
60
61void
62Gicv3Redistributor::init()
63{
64 distributor = gic->getDistributor();
65 cpuInterface = gic->getCPUInterface(cpuId);
66}
67
68void
69Gicv3Redistributor::initState()
70{
71 reset();
72}
73
74void
75Gicv3Redistributor::reset()
76{
77 peInLowPowerState = true;
78 std::fill(irqGroup.begin(), irqGroup.end(), 0);
79 std::fill(irqEnabled.begin(), irqEnabled.end(), false);
80 std::fill(irqPending.begin(), irqPending.end(), false);
81 std::fill(irqActive.begin(), irqActive.end(), false);
82 std::fill(irqPriority.begin(), irqPriority.end(), 0);
83
84 // SGIs have edge-triggered behavior
85 for (uint32_t int_id = 0; int_id < Gicv3::SGI_MAX; int_id++) {
86 irqConfig[int_id] = Gicv3::INT_EDGE_TRIGGERED;
87 }
88
89 std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0);
90 std::fill(irqNsacr.begin(), irqNsacr.end(), 0);
91 DPG1S = false;
92 DPG1NS = false;
93 DPG0 = false;
38
39const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
40 SGI_base + 0x041f);
41
42Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id)
43 : gic(gic),
44 distributor(nullptr),
45 cpuInterface(nullptr),
46 cpuId(cpu_id),
47 irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
48 irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
49 irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
50 irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
51 irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
52 irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
53 irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
54 irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX)
55{
56}
57
58Gicv3Redistributor::~Gicv3Redistributor()
59{
60}
61
62void
63Gicv3Redistributor::init()
64{
65 distributor = gic->getDistributor();
66 cpuInterface = gic->getCPUInterface(cpuId);
67}
68
69void
70Gicv3Redistributor::initState()
71{
72 reset();
73}
74
75void
76Gicv3Redistributor::reset()
77{
78 peInLowPowerState = true;
79 std::fill(irqGroup.begin(), irqGroup.end(), 0);
80 std::fill(irqEnabled.begin(), irqEnabled.end(), false);
81 std::fill(irqPending.begin(), irqPending.end(), false);
82 std::fill(irqActive.begin(), irqActive.end(), false);
83 std::fill(irqPriority.begin(), irqPriority.end(), 0);
84
85 // SGIs have edge-triggered behavior
86 for (uint32_t int_id = 0; int_id < Gicv3::SGI_MAX; int_id++) {
87 irqConfig[int_id] = Gicv3::INT_EDGE_TRIGGERED;
88 }
89
90 std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0);
91 std::fill(irqNsacr.begin(), irqNsacr.end(), 0);
92 DPG1S = false;
93 DPG1NS = false;
94 DPG0 = false;
95 EnableLPIs = false;
96 lpiConfigurationTablePtr = 0;
97 lpiIDBits = 0;
98 lpiPendingTablePtr = 0;
94}
95
96uint64_t
97Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access)
98{
99 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
100 uint64_t value = 0;
101 int first_intid = addr - GICR_IPRIORITYR.start();
102
103 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
104 uint8_t prio = irqPriority[int_id];
105
106 if (!distributor->DS && !is_secure_access) {
107 if (getIntGroup(int_id) != Gicv3::G1NS) {
108 // RAZ/WI for non-secure accesses for secure interrupts
109 continue;
110 } else {
111 // NS view
112 prio = (prio << 1) & 0xff;
113 }
114 }
115
116 value |= prio << (i * 8);
117 }
118
119 return value;
120 }
121
122 switch (addr) {
123 case GICR_CTLR: { // Control Register
124 uint64_t value = 0;
125
126 if (DPG1S) {
127 value |= GICR_CTLR_DPG1S;
128 }
129
130 if (DPG1NS) {
131 value |= GICR_CTLR_DPG1NS;
132 }
133
134 if (DPG0) {
135 value |= GICR_CTLR_DPG0;
136 }
137
99}
100
101uint64_t
102Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access)
103{
104 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
105 uint64_t value = 0;
106 int first_intid = addr - GICR_IPRIORITYR.start();
107
108 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
109 uint8_t prio = irqPriority[int_id];
110
111 if (!distributor->DS && !is_secure_access) {
112 if (getIntGroup(int_id) != Gicv3::G1NS) {
113 // RAZ/WI for non-secure accesses for secure interrupts
114 continue;
115 } else {
116 // NS view
117 prio = (prio << 1) & 0xff;
118 }
119 }
120
121 value |= prio << (i * 8);
122 }
123
124 return value;
125 }
126
127 switch (addr) {
128 case GICR_CTLR: { // Control Register
129 uint64_t value = 0;
130
131 if (DPG1S) {
132 value |= GICR_CTLR_DPG1S;
133 }
134
135 if (DPG1NS) {
136 value |= GICR_CTLR_DPG1NS;
137 }
138
139 if (DPG0) {
140 value |= GICR_CTLR_DPG0;
141 }
142
143 if (EnableLPIs) {
144 value |= GICR_CTLR_ENABLE_LPIS;
145 }
146
138 return value;
139 }
140
141 case GICR_IIDR: // Implementer Identification Register
142 //return 0x43b; // r0p0 GIC-500
143 return 0;
144
145 case GICR_TYPER: { // Type Register
146 /*
147 * Affinity_Value [63:32] == X
148 * (The identity of the PE associated with this Redistributor)
149 * CommonLPIAff [25:24] == 01
150 * (All Redistributors with the same Aff3 value must share an
151 * LPI Configuration table)
152 * Processor_Number [23:8] == X
153 * (A unique identifier for the PE)
154 * DPGS [5] == 1
155 * (GICR_CTLR.DPG* bits are supported)
156 * Last [4] == X
157 * (This Redistributor is the highest-numbered Redistributor in
158 * a series of contiguous Redistributor pages)
147 return value;
148 }
149
150 case GICR_IIDR: // Implementer Identification Register
151 //return 0x43b; // r0p0 GIC-500
152 return 0;
153
154 case GICR_TYPER: { // Type Register
155 /*
156 * Affinity_Value [63:32] == X
157 * (The identity of the PE associated with this Redistributor)
158 * CommonLPIAff [25:24] == 01
159 * (All Redistributors with the same Aff3 value must share an
160 * LPI Configuration table)
161 * Processor_Number [23:8] == X
162 * (A unique identifier for the PE)
163 * DPGS [5] == 1
164 * (GICR_CTLR.DPG* bits are supported)
165 * Last [4] == X
166 * (This Redistributor is the highest-numbered Redistributor in
167 * a series of contiguous Redistributor pages)
159 * DirectLPI [3] == 0
160 * (direct injection of LPIs not supported)
168 * DirectLPI [3] == 1
169 * (direct injection of LPIs supported)
161 * VLPIS [1] == 0
162 * (virtual LPIs not supported)
170 * VLPIS [1] == 0
171 * (virtual LPIs not supported)
163 * PLPIS [0] == 0
164 * (physical LPIs not supported)
172 * PLPIS [0] == 1
173 * (physical LPIs supported)
165 */
166 uint64_t affinity = getAffinity();
167 int last = cpuId == (gic->getSystem()->numContexts() - 1);
168 return (affinity << 32) | (1 << 24) | (cpuId << 8) |
174 */
175 uint64_t affinity = getAffinity();
176 int last = cpuId == (gic->getSystem()->numContexts() - 1);
177 return (affinity << 32) | (1 << 24) | (cpuId << 8) |
169 (1 << 5) | (last << 4);
178 (1 << 5) | (last << 4) | (1 << 3) | (1 << 0);
170 }
171
172 case GICR_WAKER: // Wake Register
173 if (!distributor->DS && !is_secure_access) {
174 // RAZ/WI for non-secure accesses
175 return 0;
176 }
177
178 if (peInLowPowerState) {
179 return GICR_WAKER_ChildrenAsleep | GICR_WAKER_ProcessorSleep;
180 } else {
181 return 0;
182 }
183
184 case GICR_PIDR0: { // Peripheral ID0 Register
185 uint8_t part_0 = 0x92; // Part number, bits[7:0]
186 return part_0;
187 }
188
189 case GICR_PIDR1: { // Peripheral ID1 Register
190 uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0]
191 uint8_t part_1 = 0x4; // Part number, bits[11:8]
192 return (des_0 << 4) | (part_1 << 0);
193 }
194
195 case GICR_PIDR2: { // Peripheral ID2 Register
196 uint8_t arch_rev = 0x3; // 0x3 GICv3
197 uint8_t jedec = 0x1; // JEP code
198 uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4]
199 return (arch_rev << 4) | (jedec << 3) | (des_1 << 0);
200 }
201
202 case GICR_PIDR3: // Peripheral ID3 Register
203 return 0x0; // Implementation defined
204
205 case GICR_PIDR4: { // Peripheral ID4 Register
206 uint8_t size = 0x4; // 64 KB software visible page
207 uint8_t des_2 = 0x4; // ARM implementation
208 return (size << 4) | (des_2 << 0);
209 }
210
211 case GICR_PIDR5: // Peripheral ID5 Register
212 case GICR_PIDR6: // Peripheral ID6 Register
213 case GICR_PIDR7: // Peripheral ID7 Register
214 return 0; // RES0
215
216 case GICR_IGROUPR0: { // Interrupt Group Register 0
217 uint64_t value = 0;
218
219 if (!distributor->DS && !is_secure_access) {
220 // RAZ/WI for non-secure accesses
221 return 0;
222 }
223
224 for (int int_id = 0; int_id < 8 * size; int_id++) {
225 value |= (irqGroup[int_id] << int_id);
226 }
227
228 return value;
229 }
230
231 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
232 case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0
233 uint64_t value = 0;
234
235 for (int int_id = 0; int_id < 8 * size; int_id++) {
236 if (!distributor->DS && !is_secure_access) {
237 // RAZ/WI for non-secure accesses for secure interrupts
238 if (getIntGroup(int_id) != Gicv3::G1NS) {
239 continue;
240 }
241 }
242
243 if (irqEnabled[int_id]) {
244 value |= (1 << int_id);
245 }
246 }
247
248 return value;
249 }
250
251 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
252 case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0
253 uint64_t value = 0;
254
255 for (int int_id = 0; int_id < 8 * size; int_id++) {
256 if (!distributor->DS && !is_secure_access) {
257 // RAZ/WI for non-secure accesses for secure interrupts
258 if (getIntGroup(int_id) != Gicv3::G1NS) {
259 continue;
260 }
261 }
262
263 value |= (irqPending[int_id] << int_id);
264 }
265
266 return value;
267 }
268
269 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
270 case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0
271 uint64_t value = 0;
272
273 for (int int_id = 0; int_id < 8 * size; int_id++) {
274 if (!distributor->DS && !is_secure_access) {
275 // RAZ/WI for non-secure accesses for secure interrupts
276 if (getIntGroup(int_id) != Gicv3::G1NS) {
277 continue;
278 }
279 }
280
281 value |= irqActive[int_id] << int_id;
282 }
283
284 return value;
285 }
286
287 case GICR_ICFGR0: // SGI Configuration Register
288 case GICR_ICFGR1: { // PPI Configuration Register
289 uint64_t value = 0;
290 uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX;
291
292 for (int i = 0, int_id = first_int_id; i < 32;
293 i = i + 2, int_id++) {
294 if (!distributor->DS && !is_secure_access) {
295 // RAZ/WI for non-secure accesses for secure interrupts
296 if (getIntGroup(int_id) != Gicv3::G1NS) {
297 continue;
298 }
299 }
300
301 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
302 value |= (0x2) << i;
303 }
304 }
305
306 return value;
307 }
308
309 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
310 uint64_t value = 0;
311
312 if (distributor->DS) {
313 value = 0;
314 } else {
315 if (!is_secure_access) {
316 // RAZ/WI for non-secure accesses
317 value = 0;
318 } else {
319 for (int int_id = 0; int_id < 8 * size; int_id++) {
320 value |= irqGrpmod[int_id] << int_id;
321 }
322 }
323 }
324
325 return value;
326 }
327
328 case GICR_NSACR: { // Non-secure Access Control Register
329 uint64_t value = 0;
330
331 if (distributor->DS) {
332 // RAZ/WI
333 value = 0;
334 } else {
335 if (!is_secure_access) {
336 // RAZ/WI
337 value = 0;
338 } else {
339 for (int i = 0, int_id = 0; i < 8 * size;
340 i = i + 2, int_id++) {
341 value |= irqNsacr[int_id] << i;
342 }
343 }
344 }
345
346 return value;
347 }
348
179 }
180
181 case GICR_WAKER: // Wake Register
182 if (!distributor->DS && !is_secure_access) {
183 // RAZ/WI for non-secure accesses
184 return 0;
185 }
186
187 if (peInLowPowerState) {
188 return GICR_WAKER_ChildrenAsleep | GICR_WAKER_ProcessorSleep;
189 } else {
190 return 0;
191 }
192
193 case GICR_PIDR0: { // Peripheral ID0 Register
194 uint8_t part_0 = 0x92; // Part number, bits[7:0]
195 return part_0;
196 }
197
198 case GICR_PIDR1: { // Peripheral ID1 Register
199 uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0]
200 uint8_t part_1 = 0x4; // Part number, bits[11:8]
201 return (des_0 << 4) | (part_1 << 0);
202 }
203
204 case GICR_PIDR2: { // Peripheral ID2 Register
205 uint8_t arch_rev = 0x3; // 0x3 GICv3
206 uint8_t jedec = 0x1; // JEP code
207 uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4]
208 return (arch_rev << 4) | (jedec << 3) | (des_1 << 0);
209 }
210
211 case GICR_PIDR3: // Peripheral ID3 Register
212 return 0x0; // Implementation defined
213
214 case GICR_PIDR4: { // Peripheral ID4 Register
215 uint8_t size = 0x4; // 64 KB software visible page
216 uint8_t des_2 = 0x4; // ARM implementation
217 return (size << 4) | (des_2 << 0);
218 }
219
220 case GICR_PIDR5: // Peripheral ID5 Register
221 case GICR_PIDR6: // Peripheral ID6 Register
222 case GICR_PIDR7: // Peripheral ID7 Register
223 return 0; // RES0
224
225 case GICR_IGROUPR0: { // Interrupt Group Register 0
226 uint64_t value = 0;
227
228 if (!distributor->DS && !is_secure_access) {
229 // RAZ/WI for non-secure accesses
230 return 0;
231 }
232
233 for (int int_id = 0; int_id < 8 * size; int_id++) {
234 value |= (irqGroup[int_id] << int_id);
235 }
236
237 return value;
238 }
239
240 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
241 case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0
242 uint64_t value = 0;
243
244 for (int int_id = 0; int_id < 8 * size; int_id++) {
245 if (!distributor->DS && !is_secure_access) {
246 // RAZ/WI for non-secure accesses for secure interrupts
247 if (getIntGroup(int_id) != Gicv3::G1NS) {
248 continue;
249 }
250 }
251
252 if (irqEnabled[int_id]) {
253 value |= (1 << int_id);
254 }
255 }
256
257 return value;
258 }
259
260 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
261 case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0
262 uint64_t value = 0;
263
264 for (int int_id = 0; int_id < 8 * size; int_id++) {
265 if (!distributor->DS && !is_secure_access) {
266 // RAZ/WI for non-secure accesses for secure interrupts
267 if (getIntGroup(int_id) != Gicv3::G1NS) {
268 continue;
269 }
270 }
271
272 value |= (irqPending[int_id] << int_id);
273 }
274
275 return value;
276 }
277
278 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
279 case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0
280 uint64_t value = 0;
281
282 for (int int_id = 0; int_id < 8 * size; int_id++) {
283 if (!distributor->DS && !is_secure_access) {
284 // RAZ/WI for non-secure accesses for secure interrupts
285 if (getIntGroup(int_id) != Gicv3::G1NS) {
286 continue;
287 }
288 }
289
290 value |= irqActive[int_id] << int_id;
291 }
292
293 return value;
294 }
295
296 case GICR_ICFGR0: // SGI Configuration Register
297 case GICR_ICFGR1: { // PPI Configuration Register
298 uint64_t value = 0;
299 uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX;
300
301 for (int i = 0, int_id = first_int_id; i < 32;
302 i = i + 2, int_id++) {
303 if (!distributor->DS && !is_secure_access) {
304 // RAZ/WI for non-secure accesses for secure interrupts
305 if (getIntGroup(int_id) != Gicv3::G1NS) {
306 continue;
307 }
308 }
309
310 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
311 value |= (0x2) << i;
312 }
313 }
314
315 return value;
316 }
317
318 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
319 uint64_t value = 0;
320
321 if (distributor->DS) {
322 value = 0;
323 } else {
324 if (!is_secure_access) {
325 // RAZ/WI for non-secure accesses
326 value = 0;
327 } else {
328 for (int int_id = 0; int_id < 8 * size; int_id++) {
329 value |= irqGrpmod[int_id] << int_id;
330 }
331 }
332 }
333
334 return value;
335 }
336
337 case GICR_NSACR: { // Non-secure Access Control Register
338 uint64_t value = 0;
339
340 if (distributor->DS) {
341 // RAZ/WI
342 value = 0;
343 } else {
344 if (!is_secure_access) {
345 // RAZ/WI
346 value = 0;
347 } else {
348 for (int i = 0, int_id = 0; i < 8 * size;
349 i = i + 2, int_id++) {
350 value |= irqNsacr[int_id] << i;
351 }
352 }
353 }
354
355 return value;
356 }
357
358 case GICR_PROPBASER: // Redistributor Properties Base Address Register
359 // OuterCache, bits [58:56]
360 // 000 Memory type defined in InnerCache field
361 // Physical_Address, bits [51:12]
362 // Bits [51:12] of the physical address containing the LPI
363 // Configuration table
364 // Shareability, bits [11:10]
365 // 00 Non-shareable
366 // InnerCache, bits [9:7]
367 // 000 Device-nGnRnE
368 // IDbits, bits [4:0]
369 // limited by GICD_TYPER.IDbits
370 return lpiConfigurationTablePtr | lpiIDBits;
371
372 // Redistributor LPI Pending Table Base Address Register
373 case GICR_PENDBASER:
374 // PTZ, bit [62]
375 // Pending Table Zero
376 // OuterCache, bits [58:56]
377 // 000 Memory type defined in InnerCache field
378 // Physical_Address, bits [51:16]
379 // Bits [51:16] of the physical address containing the LPI Pending
380 // table
381 // Shareability, bits [11:10]
382 // 00 Non-shareable
383 // InnerCache, bits [9:7]
384 // 000 Device-nGnRnE
385 return lpiPendingTablePtr;
386
387 // Redistributor Synchronize Register
388 case GICR_SYNCR:
389 return 0;
390
349 default:
350 panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
351 break;
352 }
353}
354
355void
356Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
357 bool is_secure_access)
358{
359 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
360 int first_intid = addr - GICR_IPRIORITYR.start();
361
362 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
363 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
364
365 if (!distributor->DS && !is_secure_access) {
366 if (getIntGroup(int_id) != Gicv3::G1NS) {
367 // RAZ/WI for non-secure accesses for secure interrupts
368 continue;
369 } else {
370 // NS view
371 prio = 0x80 | (prio >> 1);
372 }
373 }
374
375 irqPriority[int_id] = prio;
376 DPRINTF(GIC, "Gicv3Redistributor::write(): "
377 "int_id %d priority %d\n", int_id, irqPriority[int_id]);
378 }
379
380 return;
381 }
382
383 switch (addr) {
384 case GICR_CTLR: {
391 default:
392 panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
393 break;
394 }
395}
396
397void
398Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
399 bool is_secure_access)
400{
401 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
402 int first_intid = addr - GICR_IPRIORITYR.start();
403
404 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
405 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
406
407 if (!distributor->DS && !is_secure_access) {
408 if (getIntGroup(int_id) != Gicv3::G1NS) {
409 // RAZ/WI for non-secure accesses for secure interrupts
410 continue;
411 } else {
412 // NS view
413 prio = 0x80 | (prio >> 1);
414 }
415 }
416
417 irqPriority[int_id] = prio;
418 DPRINTF(GIC, "Gicv3Redistributor::write(): "
419 "int_id %d priority %d\n", int_id, irqPriority[int_id]);
420 }
421
422 return;
423 }
424
425 switch (addr) {
426 case GICR_CTLR: {
385 // GICR_TYPER.LPIS is 0 so Enable_LPIs is RES0
427 // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0
428 EnableLPIs = data & GICR_CTLR_ENABLE_LPIS;
386 DPG1S = data & GICR_CTLR_DPG1S;
387 DPG1NS = data & GICR_CTLR_DPG1NS;
388 DPG0 = data & GICR_CTLR_DPG0;
389 break;
390 }
391
392 case GICR_WAKER: // Wake Register
393 if (!distributor->DS && !is_secure_access) {
394 // RAZ/WI for non-secure accesses
395 return;
396 }
397
398 if (not peInLowPowerState and
399 (data & GICR_WAKER_ProcessorSleep)) {
400 DPRINTF(GIC, "Gicv3Redistributor::write(): "
401 "PE entering in low power state\n");
402 } else if (peInLowPowerState and
403 not(data & GICR_WAKER_ProcessorSleep)) {
404 DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n");
405 }
406
407 peInLowPowerState = data & GICR_WAKER_ProcessorSleep;
408 break;
409
410 case GICR_IGROUPR0: // Interrupt Group Register 0
411 if (!distributor->DS && !is_secure_access) {
412 // RAZ/WI for non-secure accesses
413 return;
414 }
415
416 for (int int_id = 0; int_id < 8 * size; int_id++) {
417 irqGroup[int_id] = data & (1 << int_id) ? 1 : 0;
418 DPRINTF(GIC, "Gicv3Redistributor::write(): "
419 "int_id %d group %d\n", int_id, irqGroup[int_id]);
420 }
421
422 break;
423
424 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
425 for (int int_id = 0; int_id < 8 * size; int_id++) {
426 if (!distributor->DS && !is_secure_access) {
427 // RAZ/WI for non-secure accesses for secure interrupts
428 if (getIntGroup(int_id) != Gicv3::G1NS) {
429 continue;
430 }
431 }
432
433 bool enable = data & (1 << int_id) ? 1 : 0;
434
435 if (enable) {
436 irqEnabled[int_id] = true;
437 }
438
439 DPRINTF(GIC, "Gicv3Redistributor::write(): "
440 "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
441 }
442
443 break;
444
445 case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0
446 for (int int_id = 0; int_id < 8 * size; int_id++) {
447 if (!distributor->DS && !is_secure_access) {
448 // RAZ/WI for non-secure accesses for secure interrupts
449 if (getIntGroup(int_id) != Gicv3::G1NS) {
450 continue;
451 }
452 }
453
454 bool disable = data & (1 << int_id) ? 1 : 0;
455
456 if (disable) {
457 irqEnabled[int_id] = false;
458 }
459
460 DPRINTF(GIC, "Gicv3Redistributor::write(): "
461 "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
462 }
463
464 break;
465
466 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
467 for (int int_id = 0; int_id < 8 * size; int_id++) {
468 if (!distributor->DS && !is_secure_access) {
469 // RAZ/WI for non-secure accesses for secure interrupts
470 if (getIntGroup(int_id) != Gicv3::G1NS) {
471 continue;
472 }
473 }
474
475 bool pending = data & (1 << int_id) ? 1 : 0;
476
477 if (pending) {
478 DPRINTF(GIC, "Gicv3Redistributor::write() "
479 "(GICR_ISPENDR0): int_id %d (PPI) "
480 "pending bit set\n", int_id);
481 irqPending[int_id] = true;
482 }
483 }
484
485 updateAndInformCPUInterface();
486 break;
487
488 case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0
489 for (int int_id = 0; int_id < 8 * size; int_id++) {
490 if (!distributor->DS && !is_secure_access) {
491 // RAZ/WI for non-secure accesses for secure interrupts
492 if (getIntGroup(int_id) != Gicv3::G1NS) {
493 continue;
494 }
495 }
496
497 bool clear = data & (1 << int_id) ? 1 : 0;
498
499 if (clear) {
500 irqPending[int_id] = false;
501 }
502 }
503
504 break;
505
506 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
507 for (int int_id = 0; int_id < 8 * size; int_id++) {
508 if (!distributor->DS && !is_secure_access) {
509 // RAZ/WI for non-secure accesses for secure interrupts
510 if (getIntGroup(int_id) != Gicv3::G1NS) {
511 continue;
512 }
513 }
514
515 bool activate = data & (1 << int_id) ? 1 : 0;
516
517 if (activate) {
518 if (!irqActive[int_id]) {
519 DPRINTF(GIC, "Gicv3Redistributor::write(): "
520 "int_id %d active set\n", int_id);
521 }
522
523 irqActive[int_id] = true;
524 }
525 }
526
527 break;
528
529 case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0
530 for (int int_id = 0; int_id < 8 * size; int_id++) {
531 if (!distributor->DS && !is_secure_access) {
532 // RAZ/WI for non-secure accesses for secure interrupts
533 if (getIntGroup(int_id) != Gicv3::G1NS) {
534 continue;
535 }
536 }
537
538 bool clear = data & (1 << int_id) ? 1 : 0;
539
540 if (clear) {
541 if (irqActive[int_id]) {
542 DPRINTF(GIC, "Gicv3Redistributor::write(): "
543 "int_id %d active cleared\n", int_id);
544 }
545
546 irqActive[int_id] = false;
547 }
548 }
549
550 break;
551
552 case GICR_ICFGR1: { // PPI Configuration Register
553 int first_intid = Gicv3::SGI_MAX;
554
555 for (int i = 0, int_id = first_intid; i < 8 * size;
556 i = i + 2, int_id++) {
557 if (!distributor->DS && !is_secure_access) {
558 // RAZ/WI for non-secure accesses for secure interrupts
559 if (getIntGroup(int_id) != Gicv3::G1NS) {
560 continue;
561 }
562 }
563
564 irqConfig[int_id] = data & (0x2 << i)
565 ? Gicv3::INT_EDGE_TRIGGERED :
566 Gicv3::INT_LEVEL_SENSITIVE;
567 DPRINTF(GIC, "Gicv3Redistributor::write(): "
568 "int_id %d (PPI) config %d\n",
569 int_id, irqConfig[int_id]);
570 }
571
572 break;
573 }
574
575 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
576 if (distributor->DS) {
577 // RAZ/WI if secutiry disabled
578 } else {
579 for (int int_id = 0; int_id < 8 * size; int_id++) {
580 if (!is_secure_access) {
581 // RAZ/WI for non-secure accesses
582 continue;
583 }
584
585 irqGrpmod[int_id] = data & (1 << int_id);
586 }
587 }
588
589 break;
590 }
591
592 case GICR_NSACR: { // Non-secure Access Control Register
593 if (distributor->DS) {
594 // RAZ/WI
595 } else {
596 if (!is_secure_access) {
597 // RAZ/WI
598 } else {
599 for (int i = 0, int_id = 0; i < 8 * size;
600 i = i + 2, int_id++) {
601 irqNsacr[int_id] = (data >> i) & 0x3;
602 }
603 }
604 }
605
606 break;
607 }
608
429 DPG1S = data & GICR_CTLR_DPG1S;
430 DPG1NS = data & GICR_CTLR_DPG1NS;
431 DPG0 = data & GICR_CTLR_DPG0;
432 break;
433 }
434
435 case GICR_WAKER: // Wake Register
436 if (!distributor->DS && !is_secure_access) {
437 // RAZ/WI for non-secure accesses
438 return;
439 }
440
441 if (not peInLowPowerState and
442 (data & GICR_WAKER_ProcessorSleep)) {
443 DPRINTF(GIC, "Gicv3Redistributor::write(): "
444 "PE entering in low power state\n");
445 } else if (peInLowPowerState and
446 not(data & GICR_WAKER_ProcessorSleep)) {
447 DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n");
448 }
449
450 peInLowPowerState = data & GICR_WAKER_ProcessorSleep;
451 break;
452
453 case GICR_IGROUPR0: // Interrupt Group Register 0
454 if (!distributor->DS && !is_secure_access) {
455 // RAZ/WI for non-secure accesses
456 return;
457 }
458
459 for (int int_id = 0; int_id < 8 * size; int_id++) {
460 irqGroup[int_id] = data & (1 << int_id) ? 1 : 0;
461 DPRINTF(GIC, "Gicv3Redistributor::write(): "
462 "int_id %d group %d\n", int_id, irqGroup[int_id]);
463 }
464
465 break;
466
467 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
468 for (int int_id = 0; int_id < 8 * size; int_id++) {
469 if (!distributor->DS && !is_secure_access) {
470 // RAZ/WI for non-secure accesses for secure interrupts
471 if (getIntGroup(int_id) != Gicv3::G1NS) {
472 continue;
473 }
474 }
475
476 bool enable = data & (1 << int_id) ? 1 : 0;
477
478 if (enable) {
479 irqEnabled[int_id] = true;
480 }
481
482 DPRINTF(GIC, "Gicv3Redistributor::write(): "
483 "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
484 }
485
486 break;
487
488 case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0
489 for (int int_id = 0; int_id < 8 * size; int_id++) {
490 if (!distributor->DS && !is_secure_access) {
491 // RAZ/WI for non-secure accesses for secure interrupts
492 if (getIntGroup(int_id) != Gicv3::G1NS) {
493 continue;
494 }
495 }
496
497 bool disable = data & (1 << int_id) ? 1 : 0;
498
499 if (disable) {
500 irqEnabled[int_id] = false;
501 }
502
503 DPRINTF(GIC, "Gicv3Redistributor::write(): "
504 "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
505 }
506
507 break;
508
509 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
510 for (int int_id = 0; int_id < 8 * size; int_id++) {
511 if (!distributor->DS && !is_secure_access) {
512 // RAZ/WI for non-secure accesses for secure interrupts
513 if (getIntGroup(int_id) != Gicv3::G1NS) {
514 continue;
515 }
516 }
517
518 bool pending = data & (1 << int_id) ? 1 : 0;
519
520 if (pending) {
521 DPRINTF(GIC, "Gicv3Redistributor::write() "
522 "(GICR_ISPENDR0): int_id %d (PPI) "
523 "pending bit set\n", int_id);
524 irqPending[int_id] = true;
525 }
526 }
527
528 updateAndInformCPUInterface();
529 break;
530
531 case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0
532 for (int int_id = 0; int_id < 8 * size; int_id++) {
533 if (!distributor->DS && !is_secure_access) {
534 // RAZ/WI for non-secure accesses for secure interrupts
535 if (getIntGroup(int_id) != Gicv3::G1NS) {
536 continue;
537 }
538 }
539
540 bool clear = data & (1 << int_id) ? 1 : 0;
541
542 if (clear) {
543 irqPending[int_id] = false;
544 }
545 }
546
547 break;
548
549 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
550 for (int int_id = 0; int_id < 8 * size; int_id++) {
551 if (!distributor->DS && !is_secure_access) {
552 // RAZ/WI for non-secure accesses for secure interrupts
553 if (getIntGroup(int_id) != Gicv3::G1NS) {
554 continue;
555 }
556 }
557
558 bool activate = data & (1 << int_id) ? 1 : 0;
559
560 if (activate) {
561 if (!irqActive[int_id]) {
562 DPRINTF(GIC, "Gicv3Redistributor::write(): "
563 "int_id %d active set\n", int_id);
564 }
565
566 irqActive[int_id] = true;
567 }
568 }
569
570 break;
571
572 case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0
573 for (int int_id = 0; int_id < 8 * size; int_id++) {
574 if (!distributor->DS && !is_secure_access) {
575 // RAZ/WI for non-secure accesses for secure interrupts
576 if (getIntGroup(int_id) != Gicv3::G1NS) {
577 continue;
578 }
579 }
580
581 bool clear = data & (1 << int_id) ? 1 : 0;
582
583 if (clear) {
584 if (irqActive[int_id]) {
585 DPRINTF(GIC, "Gicv3Redistributor::write(): "
586 "int_id %d active cleared\n", int_id);
587 }
588
589 irqActive[int_id] = false;
590 }
591 }
592
593 break;
594
595 case GICR_ICFGR1: { // PPI Configuration Register
596 int first_intid = Gicv3::SGI_MAX;
597
598 for (int i = 0, int_id = first_intid; i < 8 * size;
599 i = i + 2, int_id++) {
600 if (!distributor->DS && !is_secure_access) {
601 // RAZ/WI for non-secure accesses for secure interrupts
602 if (getIntGroup(int_id) != Gicv3::G1NS) {
603 continue;
604 }
605 }
606
607 irqConfig[int_id] = data & (0x2 << i)
608 ? Gicv3::INT_EDGE_TRIGGERED :
609 Gicv3::INT_LEVEL_SENSITIVE;
610 DPRINTF(GIC, "Gicv3Redistributor::write(): "
611 "int_id %d (PPI) config %d\n",
612 int_id, irqConfig[int_id]);
613 }
614
615 break;
616 }
617
618 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
619 if (distributor->DS) {
620 // RAZ/WI if secutiry disabled
621 } else {
622 for (int int_id = 0; int_id < 8 * size; int_id++) {
623 if (!is_secure_access) {
624 // RAZ/WI for non-secure accesses
625 continue;
626 }
627
628 irqGrpmod[int_id] = data & (1 << int_id);
629 }
630 }
631
632 break;
633 }
634
635 case GICR_NSACR: { // Non-secure Access Control Register
636 if (distributor->DS) {
637 // RAZ/WI
638 } else {
639 if (!is_secure_access) {
640 // RAZ/WI
641 } else {
642 for (int i = 0, int_id = 0; i < 8 * size;
643 i = i + 2, int_id++) {
644 irqNsacr[int_id] = (data >> i) & 0x3;
645 }
646 }
647 }
648
649 break;
650 }
651
652 case GICR_SETLPIR: // Set LPI Pending Register
653 setClrLPI(data, true);
654 break;
655
656 case GICR_CLRLPIR: // Clear LPI Pending Register
657 setClrLPI(data, false);
658 break;
659
660 case GICR_PROPBASER: { // Redistributor Properties Base Address Register
661 // OuterCache, bits [58:56]
662 // 000 Memory type defined in InnerCache field
663 // Physical_Address, bits [51:12]
664 // Bits [51:12] of the physical address containing the LPI
665 // Configuration table
666 // Shareability, bits [11:10]
667 // 00 Non-shareable
668 // InnerCache, bits [9:7]
669 // 000 Device-nGnRnE
670 // IDbits, bits [4:0]
671 // limited by GICD_TYPER.IDbits (= 0xf)
672 lpiConfigurationTablePtr = data & 0xFFFFFFFFFF000;
673 lpiIDBits = data & 0x1f;
674
675 // 0xf here matches the value of GICD_TYPER.IDbits.
676 // TODO - make GICD_TYPER.IDbits a parameter instead of a hardcoded
677 // value
678 if (lpiIDBits > 0xf) {
679 lpiIDBits = 0xf;
680 }
681
682 uint32_t largest_lpi_id = 2 ^ (lpiIDBits + 1);
683 uint32_t number_lpis = largest_lpi_id - SMALLEST_LPI_ID + 1;
684 lpiConfigurationTable.resize(number_lpis);
685 break;
686 }
687
688 // Redistributor LPI Pending Table Base Address Register
689 case GICR_PENDBASER:
690 // PTZ, bit [62]
691 // Pending Table Zero
692 // OuterCache, bits [58:56]
693 // 000 Memory type defined in InnerCache field
694 // Physical_Address, bits [51:16]
695 // Bits [51:16] of the physical address containing the LPI Pending
696 // table
697 // Shareability, bits [11:10]
698 // 00 Non-shareable
699 // InnerCache, bits [9:7]
700 // 000 Device-nGnRnE
701 lpiPendingTablePtr = data & 0xFFFFFFFFF0000;
702 break;
703
704 case GICR_INVLPIR: { // Redistributor Invalidate LPI Register
705 uint32_t lpi_id = data & 0xffffffff;
706 uint32_t largest_lpi_id = 2 ^ (lpiIDBits + 1);
707
708 if (lpi_id > largest_lpi_id) {
709 return;
710 }
711
712 uint32_t lpi_table_entry_index = lpi_id - SMALLEST_LPI_ID;
713 invalLpiConfig(lpi_table_entry_index);
714 break;
715 }
716
717 case GICR_INVALLR: { // Redistributor Invalidate All Register
718 for (int lpi_table_entry_index = 0;
719 lpi_table_entry_index < lpiConfigurationTable.size();
720 lpi_table_entry_index++) {
721 invalLpiConfig(lpi_table_entry_index);
722 }
723
724 break;
725 }
726
609 default:
610 panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
611 break;
612 }
613}
614
615void
727 default:
728 panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
729 break;
730 }
731}
732
733void
734Gicv3Redistributor::invalLpiConfig(uint32_t lpi_entry_index)
735{
736 Addr lpi_table_entry_ptr = lpiConfigurationTablePtr +
737 lpi_entry_index * sizeof(LPIConfigurationTableEntry);
738 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
739 tc->getVirtProxy().readBlob(lpi_table_entry_ptr,
740 (uint8_t*) &lpiConfigurationTable[lpi_entry_index],
741 sizeof(LPIConfigurationTableEntry));
742}
743
744void
616Gicv3Redistributor::sendPPInt(uint32_t int_id)
617{
618 assert((int_id >= Gicv3::SGI_MAX) &&
619 (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
620 irqPending[int_id] = true;
621 DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
622 "int_id %d (PPI) pending bit set\n", int_id);
623 updateAndInformCPUInterface();
624}
625
626void
627Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
628{
629 assert(int_id < Gicv3::SGI_MAX);
630 Gicv3::GroupId int_group = getIntGroup(int_id);
631
632 // asked for secure group 1
633 // configured as group 0
634 // send group 0
635 if (int_group == Gicv3::G0S && group == Gicv3::G1S) {
636 group = Gicv3::G0S;
637 }
638
639 if (group == Gicv3::G0S and int_group != Gicv3::G0S) {
640 return;
641 }
642
643 if (ns && distributor->DS == 0) {
644 int nsaccess = irqNsacr[int_id];
645
646 if ((int_group == Gicv3::G0S && nsaccess < 1) ||
647 (int_group == Gicv3::G1S && nsaccess < 2)) {
648 return;
649 }
650 }
651
652 irqPending[int_id] = true;
653 DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
654 "int_id %d (SGI) pending bit set\n", int_id);
655 updateAndInformCPUInterface();
656}
657
658Gicv3::IntStatus
659Gicv3Redistributor::intStatus(uint32_t int_id)
660{
661 assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX);
662
663 if (irqPending[int_id]) {
664 if (irqActive[int_id]) {
665 return Gicv3::INT_ACTIVE_PENDING;
666 }
667
668 return Gicv3::INT_PENDING;
669 } else if (irqActive[int_id]) {
670 return Gicv3::INT_ACTIVE;
671 } else {
672 return Gicv3::INT_INACTIVE;
673 }
674}
675
676/*
677 * Recalculate the highest priority pending interrupt after a
678 * change to redistributor state.
679 */
680void
681Gicv3Redistributor::update()
682{
683 bool new_hppi = false;
684
685 for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) {
686 Gicv3::GroupId int_group = getIntGroup(int_id);
687 bool group_enabled = distributor->groupEnabled(int_group);
688
689 if (irqPending[int_id] && irqEnabled[int_id] &&
690 !irqActive[int_id] && group_enabled) {
691 if ((irqPriority[int_id] < cpuInterface->hppi.prio) ||
692 /*
693 * Multiple pending ints with same priority.
694 * Implementation choice which one to signal.
695 * Our implementation selects the one with the lower id.
696 */
697 (irqPriority[int_id] == cpuInterface->hppi.prio &&
698 int_id < cpuInterface->hppi.intid)) {
699 cpuInterface->hppi.intid = int_id;
700 cpuInterface->hppi.prio = irqPriority[int_id];
701 cpuInterface->hppi.group = int_group;
702 new_hppi = true;
703 }
704 }
705 }
706
745Gicv3Redistributor::sendPPInt(uint32_t int_id)
746{
747 assert((int_id >= Gicv3::SGI_MAX) &&
748 (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
749 irqPending[int_id] = true;
750 DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
751 "int_id %d (PPI) pending bit set\n", int_id);
752 updateAndInformCPUInterface();
753}
754
755void
756Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
757{
758 assert(int_id < Gicv3::SGI_MAX);
759 Gicv3::GroupId int_group = getIntGroup(int_id);
760
761 // asked for secure group 1
762 // configured as group 0
763 // send group 0
764 if (int_group == Gicv3::G0S && group == Gicv3::G1S) {
765 group = Gicv3::G0S;
766 }
767
768 if (group == Gicv3::G0S and int_group != Gicv3::G0S) {
769 return;
770 }
771
772 if (ns && distributor->DS == 0) {
773 int nsaccess = irqNsacr[int_id];
774
775 if ((int_group == Gicv3::G0S && nsaccess < 1) ||
776 (int_group == Gicv3::G1S && nsaccess < 2)) {
777 return;
778 }
779 }
780
781 irqPending[int_id] = true;
782 DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
783 "int_id %d (SGI) pending bit set\n", int_id);
784 updateAndInformCPUInterface();
785}
786
787Gicv3::IntStatus
788Gicv3Redistributor::intStatus(uint32_t int_id)
789{
790 assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX);
791
792 if (irqPending[int_id]) {
793 if (irqActive[int_id]) {
794 return Gicv3::INT_ACTIVE_PENDING;
795 }
796
797 return Gicv3::INT_PENDING;
798 } else if (irqActive[int_id]) {
799 return Gicv3::INT_ACTIVE;
800 } else {
801 return Gicv3::INT_INACTIVE;
802 }
803}
804
805/*
806 * Recalculate the highest priority pending interrupt after a
807 * change to redistributor state.
808 */
809void
810Gicv3Redistributor::update()
811{
812 bool new_hppi = false;
813
814 for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) {
815 Gicv3::GroupId int_group = getIntGroup(int_id);
816 bool group_enabled = distributor->groupEnabled(int_group);
817
818 if (irqPending[int_id] && irqEnabled[int_id] &&
819 !irqActive[int_id] && group_enabled) {
820 if ((irqPriority[int_id] < cpuInterface->hppi.prio) ||
821 /*
822 * Multiple pending ints with same priority.
823 * Implementation choice which one to signal.
824 * Our implementation selects the one with the lower id.
825 */
826 (irqPriority[int_id] == cpuInterface->hppi.prio &&
827 int_id < cpuInterface->hppi.intid)) {
828 cpuInterface->hppi.intid = int_id;
829 cpuInterface->hppi.prio = irqPriority[int_id];
830 cpuInterface->hppi.group = int_group;
831 new_hppi = true;
832 }
833 }
834 }
835
836 // Check LPIs
837 uint32_t largest_lpi_id = 2 ^ (lpiIDBits + 1);
838 char lpi_pending_table[largest_lpi_id / 8];
839 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
840 tc->getVirtProxy().readBlob(lpiPendingTablePtr,
841 (uint8_t *) lpi_pending_table,
842 sizeof(lpi_pending_table));
843 for (int lpi_id = SMALLEST_LPI_ID; lpi_id < largest_lpi_id;
844 largest_lpi_id++) {
845 uint32_t lpi_pending_entry_byte = lpi_id / 8;
846 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
847 bool lpi_is_pending = lpi_pending_table[lpi_pending_entry_byte] &
848 1 << lpi_pending_entry_bit_position;
849 uint32_t lpi_configuration_entry_index = lpi_id - SMALLEST_LPI_ID;
850 bool lpi_is_enable =
851 lpiConfigurationTable[lpi_configuration_entry_index].enable;
852 // LPIs are always Non-secure Group 1 interrupts,
853 // in a system where two Security states are enabled.
854 Gicv3::GroupId lpi_group = Gicv3::G1NS;
855 bool group_enabled = distributor->groupEnabled(lpi_group);
856
857 if (lpi_is_pending && lpi_is_enable && group_enabled) {
858 uint8_t lpi_priority =
859 lpiConfigurationTable[lpi_configuration_entry_index].priority;
860
861 if ((lpi_priority < cpuInterface->hppi.prio) ||
862 (lpi_priority == cpuInterface->hppi.prio &&
863 lpi_id < cpuInterface->hppi.intid)) {
864 cpuInterface->hppi.intid = lpi_id;
865 cpuInterface->hppi.prio = lpi_priority;
866 cpuInterface->hppi.group = lpi_group;
867 new_hppi = true;
868 }
869 }
870 }
871
707 if (!new_hppi && cpuInterface->hppi.prio != 0xff &&
708 cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
709 distributor->fullUpdate();
710 }
711}
712
713void
872 if (!new_hppi && cpuInterface->hppi.prio != 0xff &&
873 cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
874 distributor->fullUpdate();
875 }
876}
877
878void
879Gicv3Redistributor::setClrLPI(uint64_t data, bool set)
880{
881 if (!EnableLPIs) {
882 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
883 // GICR_CTLR.EnableLPIs == 0.
884 return;
885 }
886
887 uint32_t lpi_id = data & 0xffffffff;
888 uint32_t largest_lpi_id = 2 ^ (lpiIDBits + 1);
889
890 if (lpi_id > largest_lpi_id) {
891 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
892 // pINTID value specifies an unimplemented LPI.
893 return;
894 }
895
896 Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
897 uint8_t lpi_pending_entry;
898 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
899 tc->getVirtProxy().readBlob(lpi_pending_entry_ptr,
900 (uint8_t*) &lpi_pending_entry,
901 sizeof(lpi_pending_entry));
902 uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
903 bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
904
905 if (set) {
906 if (is_set) {
907 // Writes to GICR_SETLPIR have not effect if the pINTID field
908 // corresponds to an LPI that is already pending.
909 return;
910 }
911
912 lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position);
913 } else {
914 if (!is_set) {
915 // Writes to GICR_SETLPIR have not effect if the pINTID field
916 // corresponds to an LPI that is not pending.
917 return;
918 }
919
920 lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position));
921 }
922
923 tc->getVirtProxy().writeBlob(lpi_pending_entry_ptr,
924 (uint8_t*) &lpi_pending_entry,
925 sizeof(lpi_pending_entry));
926 updateAndInformCPUInterface();
927}
928
929void
714Gicv3Redistributor::updateAndInformCPUInterface()
715{
716 update();
717 cpuInterface->update();
718}
719
720Gicv3::GroupId
721Gicv3Redistributor::getIntGroup(int int_id)
722{
723 assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
724
725 if (distributor->DS) {
726 if (irqGroup[int_id] == 0) {
727 return Gicv3::G0S;
728 } else {
729 return Gicv3::G1NS;
730 }
731 } else {
732 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
733 return Gicv3::G0S;
734 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
735 return Gicv3::G1NS;
736 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
737 return Gicv3::G1S;
738 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
739 return Gicv3::G1NS;
740 }
741 }
742
743 M5_UNREACHABLE;
744}
745
746void
747Gicv3Redistributor::activateIRQ(uint32_t int_id)
748{
749 irqPending[int_id] = false;
750 irqActive[int_id] = true;
751}
752
753void
754Gicv3Redistributor::deactivateIRQ(uint32_t int_id)
755{
756 irqActive[int_id] = false;
757}
758
759uint32_t
760Gicv3Redistributor::getAffinity()
761{
762 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
763 uint64_t mpidr = getMPIDR(gic->getSystem(), tc);
764 /*
765 * Aff3 = MPIDR[39:32]
766 * (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
767 * Aff2 = MPIDR[23:16]
768 * Aff1 = MPIDR[15:8]
769 * Aff0 = MPIDR[7:0]
770 * affinity = Aff3.Aff2.Aff1.Aff0
771 */
772 uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff));
773 return affinity;
774}
775
776bool
777Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group)
778{
779 if (peInLowPowerState) {
780 return false;
781 }
782
783 if (!distributor->groupEnabled(group)) {
784 return false;
785 }
786
787 if ((group == Gicv3::G1S) && DPG1S) {
788 return false;
789 }
790
791 if ((group == Gicv3::G1NS) && DPG1NS) {
792 return false;
793 }
794
795 if ((group == Gicv3::G0S) && DPG0) {
796 return false;
797 }
798
799 return true;
800}
801
802void
803Gicv3Redistributor::serialize(CheckpointOut & cp) const
804{
805 SERIALIZE_SCALAR(peInLowPowerState);
806 SERIALIZE_CONTAINER(irqGroup);
807 SERIALIZE_CONTAINER(irqEnabled);
808 SERIALIZE_CONTAINER(irqPending);
809 SERIALIZE_CONTAINER(irqActive);
810 SERIALIZE_CONTAINER(irqPriority);
811 SERIALIZE_CONTAINER(irqConfig);
812 SERIALIZE_CONTAINER(irqGrpmod);
813 SERIALIZE_CONTAINER(irqNsacr);
814 SERIALIZE_SCALAR(DPG1S);
815 SERIALIZE_SCALAR(DPG1NS);
816 SERIALIZE_SCALAR(DPG0);
930Gicv3Redistributor::updateAndInformCPUInterface()
931{
932 update();
933 cpuInterface->update();
934}
935
936Gicv3::GroupId
937Gicv3Redistributor::getIntGroup(int int_id)
938{
939 assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
940
941 if (distributor->DS) {
942 if (irqGroup[int_id] == 0) {
943 return Gicv3::G0S;
944 } else {
945 return Gicv3::G1NS;
946 }
947 } else {
948 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
949 return Gicv3::G0S;
950 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
951 return Gicv3::G1NS;
952 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
953 return Gicv3::G1S;
954 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
955 return Gicv3::G1NS;
956 }
957 }
958
959 M5_UNREACHABLE;
960}
961
962void
963Gicv3Redistributor::activateIRQ(uint32_t int_id)
964{
965 irqPending[int_id] = false;
966 irqActive[int_id] = true;
967}
968
969void
970Gicv3Redistributor::deactivateIRQ(uint32_t int_id)
971{
972 irqActive[int_id] = false;
973}
974
975uint32_t
976Gicv3Redistributor::getAffinity()
977{
978 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
979 uint64_t mpidr = getMPIDR(gic->getSystem(), tc);
980 /*
981 * Aff3 = MPIDR[39:32]
982 * (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
983 * Aff2 = MPIDR[23:16]
984 * Aff1 = MPIDR[15:8]
985 * Aff0 = MPIDR[7:0]
986 * affinity = Aff3.Aff2.Aff1.Aff0
987 */
988 uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff));
989 return affinity;
990}
991
992bool
993Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group)
994{
995 if (peInLowPowerState) {
996 return false;
997 }
998
999 if (!distributor->groupEnabled(group)) {
1000 return false;
1001 }
1002
1003 if ((group == Gicv3::G1S) && DPG1S) {
1004 return false;
1005 }
1006
1007 if ((group == Gicv3::G1NS) && DPG1NS) {
1008 return false;
1009 }
1010
1011 if ((group == Gicv3::G0S) && DPG0) {
1012 return false;
1013 }
1014
1015 return true;
1016}
1017
1018void
1019Gicv3Redistributor::serialize(CheckpointOut & cp) const
1020{
1021 SERIALIZE_SCALAR(peInLowPowerState);
1022 SERIALIZE_CONTAINER(irqGroup);
1023 SERIALIZE_CONTAINER(irqEnabled);
1024 SERIALIZE_CONTAINER(irqPending);
1025 SERIALIZE_CONTAINER(irqActive);
1026 SERIALIZE_CONTAINER(irqPriority);
1027 SERIALIZE_CONTAINER(irqConfig);
1028 SERIALIZE_CONTAINER(irqGrpmod);
1029 SERIALIZE_CONTAINER(irqNsacr);
1030 SERIALIZE_SCALAR(DPG1S);
1031 SERIALIZE_SCALAR(DPG1NS);
1032 SERIALIZE_SCALAR(DPG0);
1033 SERIALIZE_SCALAR(EnableLPIs);
1034 SERIALIZE_SCALAR(lpiConfigurationTablePtr);
1035 SERIALIZE_SCALAR(lpiIDBits);
1036 SERIALIZE_SCALAR(lpiPendingTablePtr);
817}
818
819void
820Gicv3Redistributor::unserialize(CheckpointIn & cp)
821{
822 UNSERIALIZE_SCALAR(peInLowPowerState);
823 UNSERIALIZE_CONTAINER(irqGroup);
824 UNSERIALIZE_CONTAINER(irqEnabled);
825 UNSERIALIZE_CONTAINER(irqPending);
826 UNSERIALIZE_CONTAINER(irqActive);
827 UNSERIALIZE_CONTAINER(irqPriority);
828 UNSERIALIZE_CONTAINER(irqConfig);
829 UNSERIALIZE_CONTAINER(irqGrpmod);
830 UNSERIALIZE_CONTAINER(irqNsacr);
831 UNSERIALIZE_SCALAR(DPG1S);
832 UNSERIALIZE_SCALAR(DPG1NS);
833 UNSERIALIZE_SCALAR(DPG0);
1037}
1038
1039void
1040Gicv3Redistributor::unserialize(CheckpointIn & cp)
1041{
1042 UNSERIALIZE_SCALAR(peInLowPowerState);
1043 UNSERIALIZE_CONTAINER(irqGroup);
1044 UNSERIALIZE_CONTAINER(irqEnabled);
1045 UNSERIALIZE_CONTAINER(irqPending);
1046 UNSERIALIZE_CONTAINER(irqActive);
1047 UNSERIALIZE_CONTAINER(irqPriority);
1048 UNSERIALIZE_CONTAINER(irqConfig);
1049 UNSERIALIZE_CONTAINER(irqGrpmod);
1050 UNSERIALIZE_CONTAINER(irqNsacr);
1051 UNSERIALIZE_SCALAR(DPG1S);
1052 UNSERIALIZE_SCALAR(DPG1NS);
1053 UNSERIALIZE_SCALAR(DPG0);
1054 UNSERIALIZE_SCALAR(EnableLPIs);
1055 UNSERIALIZE_SCALAR(lpiConfigurationTablePtr);
1056 UNSERIALIZE_SCALAR(lpiIDBits);
1057 UNSERIALIZE_SCALAR(lpiPendingTablePtr);
834}
1058}