interrupts.hh revision 13640
13537SN/A/* 211581SDylan.Johnson@ARM.com * Copyright (c) 2010, 2012-2013, 2016 ARM Limited 37400SAli.Saidi@ARM.com * All rights reserved 47400SAli.Saidi@ARM.com * 57400SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall 67400SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual 77400SAli.Saidi@ARM.com * property including but not limited to intellectual property relating 87400SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software 97400SAli.Saidi@ARM.com * licensed hereunder. You may use the software subject to the license 107400SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated 117400SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software, 127400SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form. 137400SAli.Saidi@ARM.com * 143537SN/A * Copyright (c) 2006 The Regents of The University of Michigan 153537SN/A * All rights reserved. 163537SN/A * 173537SN/A * Redistribution and use in source and binary forms, with or without 183537SN/A * modification, are permitted provided that the following conditions are 193537SN/A * met: redistributions of source code must retain the above copyright 203537SN/A * notice, this list of conditions and the following disclaimer; 213537SN/A * redistributions in binary form must reproduce the above copyright 223537SN/A * notice, this list of conditions and the following disclaimer in the 233537SN/A * documentation and/or other materials provided with the distribution; 243537SN/A * neither the name of the copyright holders nor the names of its 253537SN/A * contributors may be used to endorse or promote products derived from 263537SN/A * this software without specific prior written permission. 273537SN/A * 283537SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 293537SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 303537SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 313537SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323537SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 333537SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 343537SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 353537SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 363537SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 373537SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 383537SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 394103SN/A * 404103SN/A * Authors: Ali Saidi 413537SN/A */ 423537SN/A 436757SAli.Saidi@ARM.com#ifndef __ARCH_ARM_INTERRUPT_HH__ 446757SAli.Saidi@ARM.com#define __ARCH_ARM_INTERRUPT_HH__ 453537SN/A 466757SAli.Saidi@ARM.com#include "arch/arm/faults.hh" 476757SAli.Saidi@ARM.com#include "arch/arm/isa_traits.hh" 487400SAli.Saidi@ARM.com#include "arch/arm/miscregs.hh" 496757SAli.Saidi@ARM.com#include "arch/arm/registers.hh" 5010037SARM gem5 Developers#include "arch/arm/utility.hh" 513827SN/A#include "cpu/thread_context.hh" 528245Snate@binkert.org#include "debug/Interrupt.hh" 536757SAli.Saidi@ARM.com#include "params/ArmInterrupts.hh" 545647SN/A#include "sim/sim_object.hh" 553827SN/A 566757SAli.Saidi@ARM.comnamespace ArmISA 573537SN/A{ 583894SN/A 595647SN/Aclass Interrupts : public SimObject 604009SN/A{ 615810SN/A private: 625810SN/A BaseCPU * cpu; 634009SN/A 647400SAli.Saidi@ARM.com bool interrupts[NumInterruptTypes]; 654103SN/A uint64_t intStatus; 664009SN/A 674009SN/A public: 685810SN/A 695810SN/A void 705810SN/A setCPU(BaseCPU * _cpu) 715810SN/A { 725810SN/A cpu = _cpu; 735810SN/A } 745810SN/A 756757SAli.Saidi@ARM.com typedef ArmInterruptsParams Params; 765647SN/A 775647SN/A const Params * 785647SN/A params() const 795647SN/A { 805647SN/A return dynamic_cast<const Params *>(_params); 815647SN/A } 825647SN/A 835810SN/A Interrupts(Params * p) : SimObject(p), cpu(NULL) 844009SN/A { 855704SN/A clearAll(); 864009SN/A } 874009SN/A 884009SN/A 895704SN/A void 905704SN/A post(int int_num, int index) 913537SN/A { 927400SAli.Saidi@ARM.com DPRINTF(Interrupt, "Interrupt %d:%d posted\n", int_num, index); 937400SAli.Saidi@ARM.com 947400SAli.Saidi@ARM.com if (int_num < 0 || int_num >= NumInterruptTypes) 957400SAli.Saidi@ARM.com panic("int_num out of bounds\n"); 967400SAli.Saidi@ARM.com 977400SAli.Saidi@ARM.com if (index != 0) 987400SAli.Saidi@ARM.com panic("No support for other interrupt indexes\n"); 997400SAli.Saidi@ARM.com 1007400SAli.Saidi@ARM.com interrupts[int_num] = true; 1017400SAli.Saidi@ARM.com intStatus |= ULL(1) << int_num; 1024009SN/A } 1033894SN/A 1045704SN/A void 1055704SN/A clear(int int_num, int index) 1064009SN/A { 1077847Sminkyu.jeong@arm.com DPRINTF(Interrupt, "Interrupt %d:%d cleared\n", int_num, index); 1087400SAli.Saidi@ARM.com 1097400SAli.Saidi@ARM.com if (int_num < 0 || int_num >= NumInterruptTypes) 1107400SAli.Saidi@ARM.com panic("int_num out of bounds\n"); 1117400SAli.Saidi@ARM.com 1127400SAli.Saidi@ARM.com if (index != 0) 1137400SAli.Saidi@ARM.com panic("No support for other interrupt indexes\n"); 1147400SAli.Saidi@ARM.com 1157400SAli.Saidi@ARM.com interrupts[int_num] = false; 1167400SAli.Saidi@ARM.com intStatus &= ~(ULL(1) << int_num); 1174009SN/A } 1183827SN/A 1195704SN/A void 1205704SN/A clearAll() 1214009SN/A { 1227400SAli.Saidi@ARM.com DPRINTF(Interrupt, "Interrupts all cleared\n"); 1234103SN/A intStatus = 0; 1247400SAli.Saidi@ARM.com memset(interrupts, 0, sizeof(interrupts)); 1254009SN/A } 1263537SN/A 12710037SARM gem5 Developers enum InterruptMask { 12810037SARM gem5 Developers INT_MASK_M, // masked (subject to PSTATE.{A,I,F} mask bit 12910037SARM gem5 Developers INT_MASK_T, // taken regardless of mask 13010037SARM gem5 Developers INT_MASK_P // pending 13110037SARM gem5 Developers }; 13210037SARM gem5 Developers 13310037SARM gem5 Developers bool takeInt(ThreadContext *tc, InterruptTypes int_type) const; 13410037SARM gem5 Developers 1355704SN/A bool 1365704SN/A checkInterrupts(ThreadContext *tc) const 1374009SN/A { 13810037SARM gem5 Developers HCR hcr = tc->readMiscReg(MISCREG_HCR); 13910037SARM gem5 Developers 14010037SARM gem5 Developers if (!(intStatus || hcr.va || hcr.vi || hcr.vf)) 1417400SAli.Saidi@ARM.com return false; 1427400SAli.Saidi@ARM.com 1437400SAli.Saidi@ARM.com CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 1447400SAli.Saidi@ARM.com 14513640Sgiacomo.travaglini@arm.com bool isHypMode = currEL(tc) == EL2; 14611581SDylan.Johnson@ARM.com bool isSecure = inSecureState(tc); 14710037SARM gem5 Developers bool allowVIrq = !cpsr.i && hcr.imo && !isSecure && !isHypMode; 14810037SARM gem5 Developers bool allowVFiq = !cpsr.f && hcr.fmo && !isSecure && !isHypMode; 14910037SARM gem5 Developers bool allowVAbort = !cpsr.a && hcr.amo && !isSecure && !isHypMode; 15010037SARM gem5 Developers 15111566Smitch.hayenga@arm.com if ( !(intStatus || (hcr.vi && allowVIrq) || (hcr.vf && allowVFiq) || 15211566Smitch.hayenga@arm.com (hcr.va && allowVAbort)) ) 15311566Smitch.hayenga@arm.com return false; 15411566Smitch.hayenga@arm.com 15510037SARM gem5 Developers bool take_irq = takeInt(tc, INT_IRQ); 15610037SARM gem5 Developers bool take_fiq = takeInt(tc, INT_FIQ); 15710037SARM gem5 Developers bool take_ea = takeInt(tc, INT_ABT); 15810037SARM gem5 Developers 15910037SARM gem5 Developers return ((interrupts[INT_IRQ] && take_irq) || 16010037SARM gem5 Developers (interrupts[INT_FIQ] && take_fiq) || 16110037SARM gem5 Developers (interrupts[INT_ABT] && take_ea) || 16210037SARM gem5 Developers ((interrupts[INT_VIRT_IRQ] || hcr.vi) && allowVIrq) || 16310037SARM gem5 Developers ((interrupts[INT_VIRT_FIQ] || hcr.vf) && allowVFiq) || 16410037SARM gem5 Developers (hcr.va && allowVAbort) || 16510037SARM gem5 Developers (interrupts[INT_RST]) || 16610037SARM gem5 Developers (interrupts[INT_SEV]) 16710037SARM gem5 Developers ); 1684009SN/A } 1693537SN/A 1708285SPrakash.Ramrakhyani@arm.com /** 1718285SPrakash.Ramrakhyani@arm.com * This function is used to check if a wfi operation should sleep. If there 1728285SPrakash.Ramrakhyani@arm.com * is an interrupt pending, even if it's masked, wfi doesn't sleep. 1738285SPrakash.Ramrakhyani@arm.com * @return any interrupts pending 1748285SPrakash.Ramrakhyani@arm.com */ 1758285SPrakash.Ramrakhyani@arm.com bool 17610037SARM gem5 Developers checkWfiWake(HCR hcr, CPSR cpsr, SCR scr) const 1778285SPrakash.Ramrakhyani@arm.com { 17810037SARM gem5 Developers uint64_t maskedIntStatus; 17910037SARM gem5 Developers bool virtWake; 18010037SARM gem5 Developers 18110037SARM gem5 Developers maskedIntStatus = intStatus & ~((1 << INT_VIRT_IRQ) | 18210037SARM gem5 Developers (1 << INT_VIRT_FIQ)); 18310037SARM gem5 Developers virtWake = (hcr.vi || interrupts[INT_VIRT_IRQ]) && hcr.imo; 18410037SARM gem5 Developers virtWake |= (hcr.vf || interrupts[INT_VIRT_FIQ]) && hcr.fmo; 18510037SARM gem5 Developers virtWake |= hcr.va && hcr.amo; 18610037SARM gem5 Developers virtWake &= (cpsr.mode != MODE_HYP) && !inSecureState(scr, cpsr); 18710037SARM gem5 Developers return maskedIntStatus || virtWake; 18810037SARM gem5 Developers } 18910037SARM gem5 Developers 19010037SARM gem5 Developers uint32_t 19110037SARM gem5 Developers getISR(HCR hcr, CPSR cpsr, SCR scr) 19210037SARM gem5 Developers { 19310037SARM gem5 Developers bool useHcrMux; 19410037SARM gem5 Developers CPSR isr = 0; // ARM ARM states ISR reg uses same bit possitions as CPSR 19510037SARM gem5 Developers 19610037SARM gem5 Developers useHcrMux = (cpsr.mode != MODE_HYP) && !inSecureState(scr, cpsr); 19710037SARM gem5 Developers isr.i = (useHcrMux & hcr.imo) ? (interrupts[INT_VIRT_IRQ] || hcr.vi) 19810037SARM gem5 Developers : interrupts[INT_IRQ]; 19910037SARM gem5 Developers isr.f = (useHcrMux & hcr.fmo) ? (interrupts[INT_VIRT_FIQ] || hcr.vf) 20010037SARM gem5 Developers : interrupts[INT_FIQ]; 20110037SARM gem5 Developers isr.a = (useHcrMux & hcr.amo) ? hcr.va : interrupts[INT_ABT]; 20210037SARM gem5 Developers return isr; 2038285SPrakash.Ramrakhyani@arm.com } 2048285SPrakash.Ramrakhyani@arm.com 2059656Sandreas.sandberg@arm.com /** 2069656Sandreas.sandberg@arm.com * Check the state of a particular interrupt, ignoring CPSR masks. 2079656Sandreas.sandberg@arm.com * 2089656Sandreas.sandberg@arm.com * This method is primarily used when running the target CPU in a 2099656Sandreas.sandberg@arm.com * hardware VM (e.g., KVM) to check if interrupts should be 2109656Sandreas.sandberg@arm.com * delivered upon guest entry. 2119656Sandreas.sandberg@arm.com * 2129656Sandreas.sandberg@arm.com * @param interrupt Interrupt type to check the state of. 2139656Sandreas.sandberg@arm.com * @return true if the interrupt is asserted, false otherwise. 2149656Sandreas.sandberg@arm.com */ 2159656Sandreas.sandberg@arm.com bool 2169656Sandreas.sandberg@arm.com checkRaw(InterruptTypes interrupt) const 2179656Sandreas.sandberg@arm.com { 2189656Sandreas.sandberg@arm.com if (interrupt >= NumInterruptTypes) 2199656Sandreas.sandberg@arm.com panic("Interrupt number out of range.\n"); 2209656Sandreas.sandberg@arm.com 2219656Sandreas.sandberg@arm.com return interrupts[interrupt]; 2229656Sandreas.sandberg@arm.com } 2238285SPrakash.Ramrakhyani@arm.com 2245704SN/A Fault 2255704SN/A getInterrupt(ThreadContext *tc) 2264009SN/A { 22711566Smitch.hayenga@arm.com assert(checkInterrupts(tc)); 22811566Smitch.hayenga@arm.com 22910037SARM gem5 Developers HCR hcr = tc->readMiscReg(MISCREG_HCR); 23010037SARM gem5 Developers CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); 23110037SARM gem5 Developers 23210037SARM gem5 Developers // Calculate a few temp vars so we can work out if there's a pending 23310037SARM gem5 Developers // virtual interrupt, and if its allowed to happen 23410037SARM gem5 Developers // ARM ARM Issue C section B1.9.9, B1.9.11, and B1.9.13 23513640Sgiacomo.travaglini@arm.com bool isHypMode = currEL(tc) == EL2; 23611581SDylan.Johnson@ARM.com bool isSecure = inSecureState(tc); 23710037SARM gem5 Developers bool allowVIrq = !cpsr.i && hcr.imo && !isSecure && !isHypMode; 23810037SARM gem5 Developers bool allowVFiq = !cpsr.f && hcr.fmo && !isSecure && !isHypMode; 23910037SARM gem5 Developers bool allowVAbort = !cpsr.a && hcr.amo && !isSecure && !isHypMode; 24010037SARM gem5 Developers 24110037SARM gem5 Developers bool take_irq = takeInt(tc, INT_IRQ); 24210037SARM gem5 Developers bool take_fiq = takeInt(tc, INT_FIQ); 24310037SARM gem5 Developers bool take_ea = takeInt(tc, INT_ABT); 2447400SAli.Saidi@ARM.com 24510037SARM gem5 Developers if (interrupts[INT_IRQ] && take_irq) 24610474Sandreas.hansson@arm.com return std::make_shared<Interrupt>(); 24710037SARM gem5 Developers if ((interrupts[INT_VIRT_IRQ] || hcr.vi) && allowVIrq) 24810474Sandreas.hansson@arm.com return std::make_shared<VirtualInterrupt>(); 24910037SARM gem5 Developers if (interrupts[INT_FIQ] && take_fiq) 25010474Sandreas.hansson@arm.com return std::make_shared<FastInterrupt>(); 25110037SARM gem5 Developers if ((interrupts[INT_VIRT_FIQ] || hcr.vf) && allowVFiq) 25210474Sandreas.hansson@arm.com return std::make_shared<VirtualFastInterrupt>(); 25310037SARM gem5 Developers if (interrupts[INT_ABT] && take_ea) 25410474Sandreas.hansson@arm.com return std::make_shared<SystemError>(); 25510037SARM gem5 Developers if (hcr.va && allowVAbort) 25610474Sandreas.hansson@arm.com return std::make_shared<VirtualDataAbort>( 25710474Sandreas.hansson@arm.com 0, TlbEntry::DomainType::NoAccess, false, 25810474Sandreas.hansson@arm.com ArmFault::AsynchronousExternalAbort); 2597400SAli.Saidi@ARM.com if (interrupts[INT_RST]) 26010474Sandreas.hansson@arm.com return std::make_shared<Reset>(); 2618518Sgeoffrey.blake@arm.com if (interrupts[INT_SEV]) 26210474Sandreas.hansson@arm.com return std::make_shared<ArmSev>(); 2637400SAli.Saidi@ARM.com 2647400SAli.Saidi@ARM.com panic("intStatus and interrupts not in sync\n"); 2654009SN/A } 2663537SN/A 2675704SN/A void 2685704SN/A updateIntrInfo(ThreadContext *tc) 2694009SN/A { 2707400SAli.Saidi@ARM.com ; // nothing to do 2714009SN/A } 2723654SN/A 2735704SN/A void 27410905Sandreas.sandberg@arm.com serialize(CheckpointOut &cp) const 2754009SN/A { 2767400SAli.Saidi@ARM.com SERIALIZE_ARRAY(interrupts, NumInterruptTypes); 2777400SAli.Saidi@ARM.com SERIALIZE_SCALAR(intStatus); 2784009SN/A } 2793537SN/A 2805704SN/A void 28110905Sandreas.sandberg@arm.com unserialize(CheckpointIn &cp) 2824009SN/A { 2837400SAli.Saidi@ARM.com UNSERIALIZE_ARRAY(interrupts, NumInterruptTypes); 2847400SAli.Saidi@ARM.com UNSERIALIZE_SCALAR(intStatus); 2854009SN/A } 2864009SN/A}; 2876757SAli.Saidi@ARM.com} // namespace ARM_ISA 2883537SN/A 2896757SAli.Saidi@ARM.com#endif // __ARCH_ARM_INTERRUPT_HH__ 290