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