gem5  v22.1.0.0
interrupts.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, 2012-2013, 2016 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) 2006 The Regents of The University of Michigan
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 #ifndef __ARCH_ARM_INTERRUPT_HH__
42 #define __ARCH_ARM_INTERRUPT_HH__
43 
44 #include "arch/arm/faults.hh"
45 #include "arch/arm/regs/misc.hh"
46 #include "arch/arm/utility.hh"
48 #include "cpu/thread_context.hh"
49 #include "debug/Interrupt.hh"
50 #include "enums/ArmExtension.hh"
51 #include "params/ArmInterrupts.hh"
52 
53 namespace gem5
54 {
55 
56 namespace ArmISA
57 {
58 
60 {
65  INT_SEV, // Special interrupt for recieving SEV's
69 };
70 
71 class Interrupts : public BaseInterrupts
72 {
73  private:
75  uint64_t intStatus;
76 
77  public:
78  using Params = ArmInterruptsParams;
79 
81  {
82  clearAll();
83  }
84 
85 
86  void
87  post(int int_num, int index) override
88  {
89  DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index);
90 
91  if (int_num < 0 || int_num >= NumInterruptTypes)
92  panic("int_num out of bounds\n");
93 
94  if (index != 0)
95  panic("No support for other interrupt indexes\n");
96 
97  interrupts[int_num] = true;
98  intStatus |= 1ULL << int_num;
99  }
100 
101  void
102  clear(int int_num, int index) override
103  {
104  DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index);
105 
106  if (int_num < 0 || int_num >= NumInterruptTypes)
107  panic("int_num out of bounds\n");
108 
109  if (index != 0)
110  panic("No support for other interrupt indexes\n");
111 
112  interrupts[int_num] = false;
113  intStatus &= ~(1ULL << int_num);
114  }
115 
116  void
117  clearAll() override
118  {
119  DPRINTF(Interrupt, "Interrupts all cleared\n");
120  intStatus = 0;
121  memset(interrupts, 0, sizeof(interrupts));
122  }
123 
125  {
126  INT_MASK_M, // masked (subject to PSTATE.{A,I,F} mask bit
127  INT_MASK_T, // taken regardless of mask
128  INT_MASK_P // pending
129  };
130 
131  bool takeInt(InterruptTypes int_type) const;
132 
133  bool
134  checkInterrupts() const override
135  {
136  HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
137 
138  if (!(intStatus || hcr.va || hcr.vi || hcr.vf))
139  return false;
140 
141  CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
142 
143  bool no_vhe = !HaveExt(tc, ArmExtension::FEAT_VHE);
144  bool amo, fmo, imo;
145  if (hcr.tge == 1){
146  amo = (no_vhe || hcr.e2h == 0);
147  fmo = (no_vhe || hcr.e2h == 0);
148  imo = (no_vhe || hcr.e2h == 0);
149  } else {
150  amo = hcr.amo;
151  fmo = hcr.fmo;
152  imo = hcr.imo;
153  }
154 
155  bool isHypMode = currEL(tc) == EL2;
156  bool isSecure = ArmISA::isSecure(tc);
157  bool allowVIrq = !cpsr.i && imo && !isSecure && !isHypMode;
158  bool allowVFiq = !cpsr.f && fmo && !isSecure && !isHypMode;
159  bool allowVAbort = !cpsr.a && amo && !isSecure && !isHypMode;
160 
161  if ( !(intStatus || (hcr.vi && allowVIrq) || (hcr.vf && allowVFiq) ||
162  (hcr.va && allowVAbort)) )
163  return false;
164 
165  bool take_irq = takeInt(INT_IRQ);
166  bool take_fiq = takeInt(INT_FIQ);
167  bool take_ea = takeInt(INT_ABT);
168 
169  return ((interrupts[INT_IRQ] && take_irq) ||
170  (interrupts[INT_FIQ] && take_fiq) ||
171  (interrupts[INT_ABT] && take_ea) ||
172  ((interrupts[INT_VIRT_IRQ] || hcr.vi) && allowVIrq) ||
173  ((interrupts[INT_VIRT_FIQ] || hcr.vf) && allowVFiq) ||
174  (hcr.va && allowVAbort) ||
175  (interrupts[INT_RST]) ||
177  );
178  }
179 
185  bool
186  checkWfiWake(HCR hcr, CPSR cpsr, SCR scr) const
187  {
188  uint64_t maskedIntStatus;
189  bool virtWake;
190 
191  maskedIntStatus = intStatus & ~((1 << INT_VIRT_IRQ) |
192  (1 << INT_VIRT_FIQ));
193  virtWake = (hcr.vi || interrupts[INT_VIRT_IRQ]) && hcr.imo;
194  virtWake |= (hcr.vf || interrupts[INT_VIRT_FIQ]) && hcr.fmo;
195  virtWake |= hcr.va && hcr.amo;
196  virtWake &= (cpsr.mode != MODE_HYP) && !isSecure(tc);
197  return maskedIntStatus || virtWake;
198  }
199 
200  uint32_t
201  getISR(HCR hcr, CPSR cpsr, SCR scr)
202  {
203  bool useHcrMux;
204  CPSR isr = 0; // ARM ARM states ISR reg uses same bit possitions as CPSR
205 
206  useHcrMux = (cpsr.mode != MODE_HYP) && !isSecure(tc);
207  isr.i = (useHcrMux & hcr.imo) ? (interrupts[INT_VIRT_IRQ] || hcr.vi)
208  : interrupts[INT_IRQ];
209  isr.f = (useHcrMux & hcr.fmo) ? (interrupts[INT_VIRT_FIQ] || hcr.vf)
210  : interrupts[INT_FIQ];
211  isr.a = (useHcrMux & hcr.amo) ? hcr.va : interrupts[INT_ABT];
212  return isr;
213  }
214 
225  bool
226  checkRaw(InterruptTypes interrupt) const
227  {
228  if (interrupt >= NumInterruptTypes)
229  panic("Interrupt number out of range.\n");
230 
231  return interrupts[interrupt];
232  }
233 
234  Fault
235  getInterrupt() override
236  {
237  assert(checkInterrupts());
238 
239  HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
240  CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
241 
242  bool no_vhe = !HaveExt(tc, ArmExtension::FEAT_VHE);
243  bool amo, fmo, imo;
244  if (hcr.tge == 1){
245  amo = (no_vhe || hcr.e2h == 0);
246  fmo = (no_vhe || hcr.e2h == 0);
247  imo = (no_vhe || hcr.e2h == 0);
248  } else {
249  amo = hcr.amo;
250  fmo = hcr.fmo;
251  imo = hcr.imo;
252  }
253 
254  // Calculate a few temp vars so we can work out if there's a pending
255  // virtual interrupt, and if its allowed to happen
256  // ARM ARM Issue C section B1.9.9, B1.9.11, and B1.9.13
257  bool isHypMode = currEL(tc) == EL2;
258  bool isSecure = ArmISA::isSecure(tc);
259  bool allowVIrq = !cpsr.i && imo && !isSecure && !isHypMode;
260  bool allowVFiq = !cpsr.f && fmo && !isSecure && !isHypMode;
261  bool allowVAbort = !cpsr.a && amo && !isSecure && !isHypMode;
262 
263  bool take_irq = takeInt(INT_IRQ);
264  bool take_fiq = takeInt(INT_FIQ);
265  bool take_ea = takeInt(INT_ABT);
266 
267  if (interrupts[INT_IRQ] && take_irq)
268  return std::make_shared<Interrupt>();
269  if ((interrupts[INT_VIRT_IRQ] || hcr.vi) && allowVIrq)
270  return std::make_shared<VirtualInterrupt>();
271  if (interrupts[INT_FIQ] && take_fiq)
272  return std::make_shared<FastInterrupt>();
273  if ((interrupts[INT_VIRT_FIQ] || hcr.vf) && allowVFiq)
274  return std::make_shared<VirtualFastInterrupt>();
275  if (interrupts[INT_ABT] && take_ea)
276  return std::make_shared<SystemError>();
277  if (hcr.va && allowVAbort)
278  return std::make_shared<VirtualDataAbort>(
281  if (interrupts[INT_RST])
282  return std::make_shared<Reset>();
283  if (interrupts[INT_SEV])
284  return std::make_shared<ArmSev>();
285 
286  panic("intStatus and interrupts not in sync\n");
287  }
288 
289  void updateIntrInfo() override {} // nothing to do
290 
291  void
292  serialize(CheckpointOut &cp) const override
293  {
296  }
297 
298  void
299  unserialize(CheckpointIn &cp) override
300  {
303  }
304 };
305 
306 } // namespace ARM_ISA
307 } // namespace gem5
308 
309 #endif // __ARCH_ARM_INTERRUPT_HH__
#define DPRINTF(x,...)
Definition: trace.hh:186
void clearAll() override
Definition: interrupts.hh:117
bool checkInterrupts() const override
Definition: interrupts.hh:134
uint32_t getISR(HCR hcr, CPSR cpsr, SCR scr)
Definition: interrupts.hh:201
void updateIntrInfo() override
Definition: interrupts.hh:289
bool takeInt(InterruptTypes int_type) const
Definition: interrupts.cc:46
void clear(int int_num, int index) override
Definition: interrupts.hh:102
bool interrupts[NumInterruptTypes]
Definition: interrupts.hh:74
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: interrupts.hh:292
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: interrupts.hh:299
void post(int int_num, int index) override
Definition: interrupts.hh:87
bool checkRaw(InterruptTypes interrupt) const
Check the state of a particular interrupt, ignoring CPSR masks.
Definition: interrupts.hh:226
ArmInterruptsParams Params
Definition: interrupts.hh:78
bool checkWfiWake(HCR hcr, CPSR cpsr, SCR scr) const
This function is used to check if a wfi operation should sleep.
Definition: interrupts.hh:186
Fault getInterrupt() override
Definition: interrupts.hh:235
Interrupts(const Params &p)
Definition: interrupts.hh:80
ThreadContext * tc
Definition: interrupts.hh:44
virtual RegVal readMiscReg(RegIndex misc_reg)=0
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:618
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:610
ExceptionLevel currEL(const ThreadContext *tc)
Returns the current Exception Level (EL) of the provided ThreadContext.
Definition: utility.cc:124
bool isSecure(ThreadContext *tc)
Definition: utility.cc:74
Bitfield< 4 > imo
Definition: misc_types.hh:287
Bitfield< 3 > fmo
Definition: misc_types.hh:288
@ MISCREG_CPSR
Definition: misc.hh:65
@ MISCREG_HCR_EL2
Definition: misc.hh:591
Bitfield< 5 > amo
Definition: misc_types.hh:286
bool HaveExt(ThreadContext *tc, ArmExtension ext)
Returns true if the provided ThreadContext supports the ArmExtension passed as a second argument.
Definition: utility.cc:224
Bitfield< 30, 0 > index
Bitfield< 54 > p
Definition: pagetable.hh:70
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
std::shared_ptr< FaultBase > Fault
Definition: types.hh:248
std::ostream CheckpointOut
Definition: serialize.hh:66
int64 int_type
Definition: sc_nbdefs.hh:206
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:568

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