interrupts.cc revision 5222
15222Sksewell@umich.edu/* 25222Sksewell@umich.edu * Copyright .AN) 2007 MIPS Technologies, Inc. All Rights Reserved 35222Sksewell@umich.edu * 45222Sksewell@umich.edu * This software is part of the M5 simulator. 55222Sksewell@umich.edu * 65222Sksewell@umich.edu * THIS IS A LEGAL AGREEMENT. BY DOWNLOADING, USING, COPYING, CREATING 75222Sksewell@umich.edu * DERIVATIVE WORKS, AND/OR DISTRIBUTING THIS SOFTWARE YOU ARE AGREEING 85222Sksewell@umich.edu * TO THESE TERMS AND CONDITIONS. 95222Sksewell@umich.edu * 105222Sksewell@umich.edu * Permission is granted to use, copy, create derivative works and 115222Sksewell@umich.edu * distribute this software and such derivative works for any purpose, 125222Sksewell@umich.edu * so long as (1) the copyright notice above, this grant of permission, 135222Sksewell@umich.edu * and the disclaimer below appear in all copies and derivative works 145222Sksewell@umich.edu * made, (2) the copyright notice above is augmented as appropriate to 155222Sksewell@umich.edu * reflect the addition of any new copyrightable work in a derivative 165222Sksewell@umich.edu * work (e.g., Copyright .AN) <Publication Year> Copyright Owner), and (3) 175222Sksewell@umich.edu * the name of MIPS Technologies, Inc. ($B!H(BMIPS$B!I(B) is not used in any 185222Sksewell@umich.edu * advertising or publicity pertaining to the use or distribution of 195222Sksewell@umich.edu * this software without specific, written prior authorization. 205222Sksewell@umich.edu * 215222Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED $B!H(BAS IS.$B!I(B MIPS MAKES NO WARRANTIES AND 225222Sksewell@umich.edu * DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS, STATUTORY, IMPLIED OR 235222Sksewell@umich.edu * OTHERWISE, INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 245222Sksewell@umich.edu * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND 255222Sksewell@umich.edu * NON-INFRINGEMENT OF THIRD PARTY RIGHTS, REGARDING THIS SOFTWARE. 265222Sksewell@umich.edu * IN NO EVENT SHALL MIPS BE LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, 275222Sksewell@umich.edu * INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, OR PUNITIVE DAMAGES OF 285222Sksewell@umich.edu * ANY KIND OR NATURE, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT, 295222Sksewell@umich.edu * THIS SOFTWARE AND/OR THE USE OF THIS SOFTWARE, WHETHER SUCH LIABILITY 305222Sksewell@umich.edu * IS ASSERTED ON THE BASIS OF CONTRACT, TORT (INCLUDING NEGLIGENCE OR 315222Sksewell@umich.edu * STRICT LIABILITY), OR OTHERWISE, EVEN IF MIPS HAS BEEN WARNED OF THE 325222Sksewell@umich.edu * POSSIBILITY OF ANY SUCH LOSS OR DAMAGE IN ADVANCE. 335222Sksewell@umich.edu * 345222Sksewell@umich.edu * Authors: Richard Strong 355222Sksewell@umich.edu */ 365222Sksewell@umich.edu 375222Sksewell@umich.edu 385222Sksewell@umich.edu#include "arch/mips/pra_constants.hh" 395222Sksewell@umich.edu#include "arch/mips/isa_traits.hh" 405222Sksewell@umich.edu#include "cpu/thread_context.hh" 415222Sksewell@umich.edu#include "arch/mips/interrupts.hh" 425222Sksewell@umich.edu 435222Sksewell@umich.edunamespace MipsISA 445222Sksewell@umich.edu{ 455222Sksewell@umich.edustatic inline uint8_t getCauseIP_(ThreadContext *tc) { 465222Sksewell@umich.edu MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); 475222Sksewell@umich.edu uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0); 485222Sksewell@umich.edu return IP_; 495222Sksewell@umich.edu} 505222Sksewell@umich.edu 515222Sksewell@umich.edustatic inline void setCauseIP_(ThreadContext *tc, uint8_t val) { 525222Sksewell@umich.edu MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); 535222Sksewell@umich.edu replaceBits(cause,Cause_IP7,Cause_IP0,val); 545222Sksewell@umich.edu tc->setMiscRegNoEffect(MipsISA::Cause,cause); 555222Sksewell@umich.edu} 565222Sksewell@umich.edu 575222Sksewell@umich.edu/* 585222Sksewell@umich.edu void Interrupts::post(int int_num, int index) 595222Sksewell@umich.edu { 605222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupt %d posted\n", int_num); 615222Sksewell@umich.edu 625222Sksewell@umich.edu //index should not be used 635222Sksewell@umich.edu assert(index == 0); 645222Sksewell@umich.edu 655222Sksewell@umich.edu if (int_num < 0 || int_num >= NumInterruptLevels) 665222Sksewell@umich.edu panic("int_num out of bounds\n"); 675222Sksewell@umich.edu intstatus |= 1 << int_num; 685222Sksewell@umich.edu } 695222Sksewell@umich.edu 705222Sksewell@umich.edu void Interrupts::clear(int int_num, int index) 715222Sksewell@umich.edu { 725222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num); 735222Sksewell@umich.edu 745222Sksewell@umich.edu //index should not be used 755222Sksewell@umich.edu assert(index == 0); 765222Sksewell@umich.edu 775222Sksewell@umich.edu if (int_num < 0 || int_num >= NumInterruptLevels) 785222Sksewell@umich.edu panic("int_num out of bounds\n"); 795222Sksewell@umich.edu 805222Sksewell@umich.edu intstatus &= ~(1 << int_num); 815222Sksewell@umich.edu } 825222Sksewell@umich.edu 835222Sksewell@umich.edu void Interrupts::clear_all() 845222Sksewell@umich.edu { 855222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupts all cleared\n"); 865222Sksewell@umich.edu intstatus = 0; 875222Sksewell@umich.edu } 885222Sksewell@umich.edu 895222Sksewell@umich.edu 905222Sksewell@umich.edu 915222Sksewell@umich.edu Fault Interrupts::getInterrupt(ThreadContext * tc) 925222Sksewell@umich.edu { 935222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupts getInterrupt\n"); 945222Sksewell@umich.edu // If a timer interrupt has occured, check to see if a 955222Sksewell@umich.edu // mtc0 to Compare register caused this interrupt to 965222Sksewell@umich.edu // be cleared. If this is the case, clear intstatus 975222Sksewell@umich.edu // bit for timer interrupt 985222Sksewell@umich.edu if (oncputimerintr){ 995222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupts oncputimerintr==true\n"); 1005222Sksewell@umich.edu MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); 1015222Sksewell@umich.edu uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0); 1025222Sksewell@umich.edu MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl); 1035222Sksewell@umich.edu uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO); 1045222Sksewell@umich.edu //mtc0 to compare must have cleared bit in IP 1055222Sksewell@umich.edu if ( ((1 << IPTI) & IP_) == 0){ 1065222Sksewell@umich.edu clear(IPTI, 0); 1075222Sksewell@umich.edu oncputimerintr=false; 1085222Sksewell@umich.edu } 1095222Sksewell@umich.edu } 1105222Sksewell@umich.edu //if there is a on cpu timer interrupt (i.e. Compare == Count) 1115222Sksewell@umich.edu //update intstatus before proceeding to interrupt 1125222Sksewell@umich.edu if (onCpuTimerInterrupt(tc)){ 1135222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n"); 1145222Sksewell@umich.edu //determine timer interrupt IP # 1155222Sksewell@umich.edu MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl); 1165222Sksewell@umich.edu uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO); 1175222Sksewell@umich.edu //set intstatus to correspond 1185222Sksewell@umich.edu post(IPTI, 0); 1195222Sksewell@umich.edu oncputimerintr=true; 1205222Sksewell@umich.edu } 1215222Sksewell@umich.edu 1225222Sksewell@umich.edu //Check if there are any outstanding interrupts 1235222Sksewell@umich.edu MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status); 1245222Sksewell@umich.edu if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled 1255222Sksewell@umich.edu bits(status, Status_ERL) == 0 && //error level must be 0 or interrupts inhibited 1265222Sksewell@umich.edu bits(status, Status_EXL) == 0 ) //exception level must be 0 or interrupts inhibited 1275222Sksewell@umich.edu { 1285222Sksewell@umich.edu // Software interrupts & hardware interrupts are handled in software. 1295222Sksewell@umich.edu // So if any interrupt that isn't masked is detected, jump to interrupt 1305222Sksewell@umich.edu // handler 1315222Sksewell@umich.edu uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending 1325222Sksewell@umich.edu IM = bits(status,Status_IM7,Status_IM0); 1335222Sksewell@umich.edu IP = intstatus; 1345222Sksewell@umich.edu //IM and IP are already correctly aligned 1355222Sksewell@umich.edu if (IM & IP){ 1365222Sksewell@umich.edu DPRINTF(Flow, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n", 1375222Sksewell@umich.edu IM, IP); 1385222Sksewell@umich.edu return new InterruptFault; 1395222Sksewell@umich.edu } 1405222Sksewell@umich.edu } 1415222Sksewell@umich.edu 1425222Sksewell@umich.edu return NoFault; 1435222Sksewell@umich.edu 1445222Sksewell@umich.edu } 1455222Sksewell@umich.edu 1465222Sksewell@umich.edu void Interrupts::updateIntrInfo(ThreadContext *tc) const 1475222Sksewell@umich.edu { 1485222Sksewell@umich.edu //Merge Interrupts.intstatus with mips MipISA::Status 1495222Sksewell@umich.edu MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); 1505222Sksewell@umich.edu replaceBits(cause,Cause_IP7,Cause_IP0,intstatus); 1515222Sksewell@umich.edu tc->setMiscRegNoEffect(MipsISA::Cause,cause); 1525222Sksewell@umich.edu } 1535222Sksewell@umich.edu 1545222Sksewell@umich.edu bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const 1555222Sksewell@umich.edu { 1565222Sksewell@umich.edu MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare); 1575222Sksewell@umich.edu MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count); 1585222Sksewell@umich.edu if (compare == count) 1595222Sksewell@umich.edu return true; 1605222Sksewell@umich.edu return false; 1615222Sksewell@umich.edu } 1625222Sksewell@umich.edu 1635222Sksewell@umich.edu 1645222Sksewell@umich.edu uint64_t Interrupts::get_vec(int int_num) 1655222Sksewell@umich.edu { 1665222Sksewell@umich.edu panic("MipsISA::Interrupts::get_vec() is not implemented. \n"); 1675222Sksewell@umich.edu M5_DUMMY_RETURN 1685222Sksewell@umich.edu } 1695222Sksewell@umich.edu*/ 1705222Sksewell@umich.eduvoid Interrupts::post(int int_num, ThreadContext* tc) 1715222Sksewell@umich.edu{ 1725222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupt %d posted\n", int_num); 1735222Sksewell@umich.edu if (int_num < 0 || int_num >= NumInterruptLevels) 1745222Sksewell@umich.edu panic("int_num out of bounds\n"); 1755222Sksewell@umich.edu 1765222Sksewell@umich.edu uint8_t intstatus= getCauseIP_(tc); 1775222Sksewell@umich.edu intstatus |= 1 << int_num; 1785222Sksewell@umich.edu setCauseIP_(tc, intstatus); 1795222Sksewell@umich.edu} 1805222Sksewell@umich.edu 1815222Sksewell@umich.eduvoid Interrupts::post(int int_num, int index) 1825222Sksewell@umich.edu{ 1835222Sksewell@umich.edu fatal("Must use Thread COntext when posting MIPS Interrupts in M5"); 1845222Sksewell@umich.edu} 1855222Sksewell@umich.edu 1865222Sksewell@umich.eduvoid Interrupts::clear(int int_num, ThreadContext* tc) 1875222Sksewell@umich.edu{ 1885222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num); 1895222Sksewell@umich.edu if (int_num < 0 || int_num >= NumInterruptLevels) 1905222Sksewell@umich.edu panic("int_num out of bounds\n"); 1915222Sksewell@umich.edu 1925222Sksewell@umich.edu uint8_t intstatus = getCauseIP_(tc); 1935222Sksewell@umich.edu intstatus &= ~(1 << int_num); 1945222Sksewell@umich.edu setCauseIP_(tc, intstatus); 1955222Sksewell@umich.edu} 1965222Sksewell@umich.edu 1975222Sksewell@umich.eduvoid Interrupts::clear(int int_num, int index) 1985222Sksewell@umich.edu{ 1995222Sksewell@umich.edu fatal("Must use Thread COntext when clearing MIPS Interrupts in M5"); 2005222Sksewell@umich.edu} 2015222Sksewell@umich.edu 2025222Sksewell@umich.eduvoid Interrupts::clear_all(ThreadContext *tc) 2035222Sksewell@umich.edu{ 2045222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupts all cleared\n"); 2055222Sksewell@umich.edu uint8_t intstatus = 0; 2065222Sksewell@umich.edu setCauseIP_(tc, intstatus); 2075222Sksewell@umich.edu} 2085222Sksewell@umich.edu 2095222Sksewell@umich.eduvoid Interrupts::clear_all() 2105222Sksewell@umich.edu{ 2115222Sksewell@umich.edu fatal("Must use Thread COntext when clearing MIPS Interrupts in M5"); 2125222Sksewell@umich.edu} 2135222Sksewell@umich.edu 2145222Sksewell@umich.edu 2155222Sksewell@umich.edu 2165222Sksewell@umich.eduFault Interrupts::getInterrupt(ThreadContext * tc) 2175222Sksewell@umich.edu{ 2185222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupts getInterrupt\n"); 2195222Sksewell@umich.edu 2205222Sksewell@umich.edu 2215222Sksewell@umich.edu 2225222Sksewell@umich.edu //Check if there are any outstanding interrupts 2235222Sksewell@umich.edu MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status); 2245222Sksewell@umich.edu if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled 2255222Sksewell@umich.edu bits(status, Status_ERL_HI,Status_ERL_LO) == 0 && //error level must be 0 or interrupts inhibited 2265222Sksewell@umich.edu bits(status, Status_EXL_HI,Status_EXL_LO) == 0 ) //exception level must be 0 or interrupts inhibited 2275222Sksewell@umich.edu { 2285222Sksewell@umich.edu // Software interrupts & hardware interrupts are handled in software. 2295222Sksewell@umich.edu // So if any interrupt that isn't masked is detected, jump to interrupt 2305222Sksewell@umich.edu // handler 2315222Sksewell@umich.edu uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending 2325222Sksewell@umich.edu IM = bits(status,Status_IM7,Status_IM0); 2335222Sksewell@umich.edu IP = getCauseIP_(tc); 2345222Sksewell@umich.edu //IM and IP are already correctly aligned 2355222Sksewell@umich.edu if (IM & IP){ 2365222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n", 2375222Sksewell@umich.edu IM, IP); 2385222Sksewell@umich.edu return new InterruptFault; 2395222Sksewell@umich.edu } 2405222Sksewell@umich.edu } 2415222Sksewell@umich.edu 2425222Sksewell@umich.edu return NoFault; 2435222Sksewell@umich.edu 2445222Sksewell@umich.edu} 2455222Sksewell@umich.edubool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const 2465222Sksewell@umich.edu{ 2475222Sksewell@umich.edu MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare); 2485222Sksewell@umich.edu MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count); 2495222Sksewell@umich.edu if (compare == count && count != 0) 2505222Sksewell@umich.edu return true; 2515222Sksewell@umich.edu return false; 2525222Sksewell@umich.edu} 2535222Sksewell@umich.eduvoid Interrupts::updateIntrInfo(ThreadContext *tc) const 2545222Sksewell@umich.edu{ 2555222Sksewell@umich.edu //Nothing needs to be done. 2565222Sksewell@umich.edu ; 2575222Sksewell@umich.edu} 2585222Sksewell@umich.edu 2595222Sksewell@umich.eduuint64_t Interrupts::get_vec(int int_num) 2605222Sksewell@umich.edu{ 2615222Sksewell@umich.edu panic("MipsISA::Interrupts::get_vec() is not implemented. \n"); 2625222Sksewell@umich.edu M5_DUMMY_RETURN 2635222Sksewell@umich.edu } 2645222Sksewell@umich.edu 2655222Sksewell@umich.edubool Interrupts::interruptsPending(ThreadContext *tc) const 2665222Sksewell@umich.edu{ 2675222Sksewell@umich.edu //if there is a on cpu timer interrupt (i.e. Compare == Count) 2685222Sksewell@umich.edu //update CauseIP before proceeding to interrupt 2695222Sksewell@umich.edu if (onCpuTimerInterrupt(tc)){ 2705222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n"); 2715222Sksewell@umich.edu //determine timer interrupt IP # 2725222Sksewell@umich.edu MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl); 2735222Sksewell@umich.edu uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO); 2745222Sksewell@umich.edu //set intstatus to correspond 2755222Sksewell@umich.edu //post(IPTI, tc); 2765222Sksewell@umich.edu uint8_t intstatus= getCauseIP_(tc); 2775222Sksewell@umich.edu intstatus |= 1 << IPTI; 2785222Sksewell@umich.edu setCauseIP_(tc, intstatus); 2795222Sksewell@umich.edu } 2805222Sksewell@umich.edu 2815222Sksewell@umich.edu return (getCauseIP_(tc) != 0); 2825222Sksewell@umich.edu 2835222Sksewell@umich.edu} 2845222Sksewell@umich.edu 2855222Sksewell@umich.edu 2865222Sksewell@umich.edu 2875222Sksewell@umich.edu 2885222Sksewell@umich.edu 2895222Sksewell@umich.edu} 290