1/* 2 * Copyright (c) 2006 The Regents of The University of Michigan 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: Ali Saidi 29 * Lisa Hsu 30 */ 31 32#ifndef __ARCH_SPARC_INTERRUPT_HH__ 33#define __ARCH_SPARC_INTERRUPT_HH__ 34 35#include "arch/sparc/faults.hh" 36#include "arch/sparc/isa_traits.hh" 37#include "arch/sparc/registers.hh" 38#include "cpu/thread_context.hh" 39#include "debug/Interrupt.hh" 40#include "params/SparcInterrupts.hh" 41#include "sim/sim_object.hh" 42 43namespace SparcISA 44{ 45 46enum InterruptTypes 47{ 48 IT_TRAP_LEVEL_ZERO, 49 IT_HINTP, 50 IT_INT_VEC, 51 IT_CPU_MONDO, 52 IT_DEV_MONDO, 53 IT_RES_ERROR, 54 IT_SOFT_INT, 55 NumInterruptTypes 56}; 57 58class Interrupts : public SimObject 59{ 60 private: 61 BaseCPU * cpu; 62 63 uint64_t interrupts[NumInterruptTypes]; 64 uint64_t intStatus; 65 66 public: 67 68 void 69 setCPU(BaseCPU * _cpu) 70 { 71 cpu = _cpu; 72 } 73 74 typedef SparcInterruptsParams Params; 75 76 const Params * 77 params() const 78 { 79 return dynamic_cast<const Params *>(_params); 80 } 81 82 Interrupts(Params * p) : SimObject(p), cpu(NULL) 83 { 84 clearAll(); 85 } 86 87 int 88 InterruptLevel(uint64_t softint) 89 { 90 if (softint & 0x10000 || softint & 0x1) 91 return 14; 92 93 int level = 15; 94 while (level > 0 && !(1 << level & softint)) 95 level--; 96 if (1 << level & softint) 97 return level; 98 return 0; 99 } 100 101 void 102 post(int int_num, int index) 103 { 104 DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); 105 assert(int_num >= 0 && int_num < NumInterruptTypes); 106 assert(index >= 0 && index < 64); 107 108 interrupts[int_num] |= ULL(1) << index; 109 intStatus |= ULL(1) << int_num; 110 } 111 112 void 113 clear(int int_num, int index) 114 { 115 DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); 116 assert(int_num >= 0 && int_num < NumInterruptTypes); 117 assert(index >= 0 && index < 64); 118 119 interrupts[int_num] &= ~(ULL(1) << index); 120 if (!interrupts[int_num]) 121 intStatus &= ~(ULL(1) << int_num); 122 } 123 124 void 125 clearAll() 126 { 127 for (int i = 0; i < NumInterruptTypes; ++i) { 128 interrupts[i] = 0; 129 } 130 intStatus = 0; 131 } 132 133 bool 134 checkInterrupts(ThreadContext *tc) const 135 { 136 if (!intStatus) 137 return false; 138 139 HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE); 140 PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); 141 142 // THESE ARE IN ORDER OF PRIORITY 143 // since there are early returns, and the highest 144 // priority interrupts should get serviced, 145 // it is v. important that new interrupts are inserted 146 // in the right order of processing 147 if (hpstate.hpriv) { 148 if (pstate.ie) { 149 if (interrupts[IT_HINTP]) { 150 // This will be cleaned by a HINTP write 151 return true; 152 } 153 if (interrupts[IT_INT_VEC]) { 154 // this will be cleared by an ASI read (or write) 155 return true; 156 } 157 } 158 } else { 159 if (interrupts[IT_TRAP_LEVEL_ZERO]) { 160 // this is cleared by deasserting HPSTATE::tlz 161 return true; 162 } 163 // HStick matches always happen in priv mode (ie doesn't matter) 164 if (interrupts[IT_HINTP]) { 165 return true; 166 } 167 if (interrupts[IT_INT_VEC]) { 168 // this will be cleared by an ASI read (or write) 169 return true; 170 } 171 if (pstate.ie) { 172 if (interrupts[IT_CPU_MONDO]) { 173 return true; 174 } 175 if (interrupts[IT_DEV_MONDO]) { 176 return true; 177 } 178 if (interrupts[IT_SOFT_INT]) { 179 return true; 180 } 181 182 if (interrupts[IT_RES_ERROR]) { 183 return true; 184 } 185 } // !hpriv && pstate.ie 186 } // !hpriv 187 188 return false; 189 } 190 191 Fault 192 getInterrupt(ThreadContext *tc) 193 { 194 assert(checkInterrupts(tc)); 195 196 HPSTATE hpstate = tc->readMiscRegNoEffect(MISCREG_HPSTATE); 197 PSTATE pstate = tc->readMiscRegNoEffect(MISCREG_PSTATE); 198 199 // THESE ARE IN ORDER OF PRIORITY 200 // since there are early returns, and the highest 201 // priority interrupts should get serviced, 202 // it is v. important that new interrupts are inserted 203 // in the right order of processing 204 if (hpstate.hpriv) { 205 if (pstate.ie) { 206 if (interrupts[IT_HINTP]) { 207 // This will be cleaned by a HINTP write 208 return std::make_shared<HstickMatch>(); 209 } 210 if (interrupts[IT_INT_VEC]) { 211 // this will be cleared by an ASI read (or write) 212 return std::make_shared<InterruptVector>(); 213 } 214 } 215 } else { 216 if (interrupts[IT_TRAP_LEVEL_ZERO]) { 217 // this is cleared by deasserting HPSTATE::tlz 218 return std::make_shared<TrapLevelZero>(); 219 } 220 // HStick matches always happen in priv mode (ie doesn't matter) 221 if (interrupts[IT_HINTP]) { 222 return std::make_shared<HstickMatch>(); 223 } 224 if (interrupts[IT_INT_VEC]) { 225 // this will be cleared by an ASI read (or write) 226 return std::make_shared<InterruptVector>(); 227 } 228 if (pstate.ie) { 229 if (interrupts[IT_CPU_MONDO]) { 230 return std::make_shared<CpuMondo>(); 231 } 232 if (interrupts[IT_DEV_MONDO]) { 233 return std::make_shared<DevMondo>(); 234 } 235 if (interrupts[IT_SOFT_INT]) { 236 int level = InterruptLevel(interrupts[IT_SOFT_INT]); 237 return std::make_shared<InterruptLevelN>(level); 238 } 239 240 if (interrupts[IT_RES_ERROR]) { 241 return std::make_shared<ResumableError>(); 242 } 243 } // !hpriv && pstate.ie 244 } // !hpriv 245 return NoFault; 246 } 247 248 void 249 updateIntrInfo(ThreadContext *tc) 250 {} 251 252 uint64_t 253 get_vec(int int_num) 254 { 255 assert(int_num >= 0 && int_num < NumInterruptTypes); 256 return interrupts[int_num]; 257 } 258 259 void 260 serialize(CheckpointOut &cp) const override 261 { 262 SERIALIZE_ARRAY(interrupts,NumInterruptTypes); 263 SERIALIZE_SCALAR(intStatus); 264 } 265 266 void 267 unserialize(CheckpointIn &cp) override 268 { 269 UNSERIALIZE_ARRAY(interrupts,NumInterruptTypes); 270 UNSERIALIZE_SCALAR(intStatus); 271 } 272}; 273} // namespace SPARC_ISA 274 275#endif // __ARCH_SPARC_INTERRUPT_HH__ 276