interrupts.cc revision 5648
15222Sksewell@umich.edu/* 25254Sksewell@umich.edu * Copyright (c) 2006 The Regents of The University of Michigan 35254Sksewell@umich.edu * Copyright (c) 2007 MIPS Technologies, Inc. 45254Sksewell@umich.edu * All rights reserved. 55222Sksewell@umich.edu * 65254Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without 75254Sksewell@umich.edu * modification, are permitted provided that the following conditions are 85254Sksewell@umich.edu * met: redistributions of source code must retain the above copyright 95254Sksewell@umich.edu * notice, this list of conditions and the following disclaimer; 105254Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright 115254Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the 125254Sksewell@umich.edu * documentation and/or other materials provided with the distribution; 135254Sksewell@umich.edu * neither the name of the copyright holders nor the names of its 145254Sksewell@umich.edu * contributors may be used to endorse or promote products derived from 155254Sksewell@umich.edu * this software without specific prior written permission. 165222Sksewell@umich.edu * 175254Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 185254Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 195254Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 205254Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 215254Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 225254Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 235254Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 245254Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 255254Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 265254Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 275254Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 285222Sksewell@umich.edu * 295254Sksewell@umich.edu * Authors: Steve Reinhardt 305254Sksewell@umich.edu * Kevin Lim 315254Sksewell@umich.edu * Korey Sewell 325222Sksewell@umich.edu */ 335222Sksewell@umich.edu 345222Sksewell@umich.edu#include "arch/mips/pra_constants.hh" 355222Sksewell@umich.edu#include "arch/mips/isa_traits.hh" 365222Sksewell@umich.edu#include "cpu/thread_context.hh" 375222Sksewell@umich.edu#include "arch/mips/interrupts.hh" 385222Sksewell@umich.edu 395222Sksewell@umich.edunamespace MipsISA 405222Sksewell@umich.edu{ 415222Sksewell@umich.edustatic inline uint8_t getCauseIP_(ThreadContext *tc) { 425222Sksewell@umich.edu MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); 435222Sksewell@umich.edu uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0); 445222Sksewell@umich.edu return IP_; 455222Sksewell@umich.edu} 465222Sksewell@umich.edu 475222Sksewell@umich.edustatic inline void setCauseIP_(ThreadContext *tc, uint8_t val) { 485222Sksewell@umich.edu MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); 495222Sksewell@umich.edu replaceBits(cause,Cause_IP7,Cause_IP0,val); 505222Sksewell@umich.edu tc->setMiscRegNoEffect(MipsISA::Cause,cause); 515222Sksewell@umich.edu} 525222Sksewell@umich.edu 535222Sksewell@umich.edu/* 545222Sksewell@umich.edu void Interrupts::post(int int_num, int index) 555222Sksewell@umich.edu { 565222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupt %d posted\n", int_num); 575222Sksewell@umich.edu 585222Sksewell@umich.edu //index should not be used 595222Sksewell@umich.edu assert(index == 0); 605222Sksewell@umich.edu 615222Sksewell@umich.edu if (int_num < 0 || int_num >= NumInterruptLevels) 625222Sksewell@umich.edu panic("int_num out of bounds\n"); 635222Sksewell@umich.edu intstatus |= 1 << int_num; 645222Sksewell@umich.edu } 655222Sksewell@umich.edu 665222Sksewell@umich.edu void Interrupts::clear(int int_num, int index) 675222Sksewell@umich.edu { 685222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num); 695222Sksewell@umich.edu 705222Sksewell@umich.edu //index should not be used 715222Sksewell@umich.edu assert(index == 0); 725222Sksewell@umich.edu 735222Sksewell@umich.edu if (int_num < 0 || int_num >= NumInterruptLevels) 745222Sksewell@umich.edu panic("int_num out of bounds\n"); 755222Sksewell@umich.edu 765222Sksewell@umich.edu intstatus &= ~(1 << int_num); 775222Sksewell@umich.edu } 785222Sksewell@umich.edu 795222Sksewell@umich.edu void Interrupts::clear_all() 805222Sksewell@umich.edu { 815222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupts all cleared\n"); 825222Sksewell@umich.edu intstatus = 0; 835222Sksewell@umich.edu } 845222Sksewell@umich.edu 855222Sksewell@umich.edu 865222Sksewell@umich.edu 875222Sksewell@umich.edu Fault Interrupts::getInterrupt(ThreadContext * tc) 885222Sksewell@umich.edu { 895222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupts getInterrupt\n"); 905222Sksewell@umich.edu // If a timer interrupt has occured, check to see if a 915222Sksewell@umich.edu // mtc0 to Compare register caused this interrupt to 925222Sksewell@umich.edu // be cleared. If this is the case, clear intstatus 935222Sksewell@umich.edu // bit for timer interrupt 945222Sksewell@umich.edu if (oncputimerintr){ 955222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupts oncputimerintr==true\n"); 965222Sksewell@umich.edu MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); 975222Sksewell@umich.edu uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0); 985222Sksewell@umich.edu MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl); 995222Sksewell@umich.edu uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO); 1005222Sksewell@umich.edu //mtc0 to compare must have cleared bit in IP 1015222Sksewell@umich.edu if ( ((1 << IPTI) & IP_) == 0){ 1025222Sksewell@umich.edu clear(IPTI, 0); 1035222Sksewell@umich.edu oncputimerintr=false; 1045222Sksewell@umich.edu } 1055222Sksewell@umich.edu } 1065222Sksewell@umich.edu //if there is a on cpu timer interrupt (i.e. Compare == Count) 1075222Sksewell@umich.edu //update intstatus before proceeding to interrupt 1085222Sksewell@umich.edu if (onCpuTimerInterrupt(tc)){ 1095222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n"); 1105222Sksewell@umich.edu //determine timer interrupt IP # 1115222Sksewell@umich.edu MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl); 1125222Sksewell@umich.edu uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO); 1135222Sksewell@umich.edu //set intstatus to correspond 1145222Sksewell@umich.edu post(IPTI, 0); 1155222Sksewell@umich.edu oncputimerintr=true; 1165222Sksewell@umich.edu } 1175222Sksewell@umich.edu 1185222Sksewell@umich.edu //Check if there are any outstanding interrupts 1195222Sksewell@umich.edu MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status); 1205222Sksewell@umich.edu if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled 1215222Sksewell@umich.edu bits(status, Status_ERL) == 0 && //error level must be 0 or interrupts inhibited 1225222Sksewell@umich.edu bits(status, Status_EXL) == 0 ) //exception level must be 0 or interrupts inhibited 1235222Sksewell@umich.edu { 1245222Sksewell@umich.edu // Software interrupts & hardware interrupts are handled in software. 1255222Sksewell@umich.edu // So if any interrupt that isn't masked is detected, jump to interrupt 1265222Sksewell@umich.edu // handler 1275222Sksewell@umich.edu uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending 1285222Sksewell@umich.edu IM = bits(status,Status_IM7,Status_IM0); 1295222Sksewell@umich.edu IP = intstatus; 1305222Sksewell@umich.edu //IM and IP are already correctly aligned 1315222Sksewell@umich.edu if (IM & IP){ 1325222Sksewell@umich.edu DPRINTF(Flow, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n", 1335222Sksewell@umich.edu IM, IP); 1345222Sksewell@umich.edu return new InterruptFault; 1355222Sksewell@umich.edu } 1365222Sksewell@umich.edu } 1375222Sksewell@umich.edu 1385222Sksewell@umich.edu return NoFault; 1395222Sksewell@umich.edu 1405222Sksewell@umich.edu } 1415222Sksewell@umich.edu 1425222Sksewell@umich.edu void Interrupts::updateIntrInfo(ThreadContext *tc) const 1435222Sksewell@umich.edu { 1445222Sksewell@umich.edu //Merge Interrupts.intstatus with mips MipISA::Status 1455222Sksewell@umich.edu MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); 1465222Sksewell@umich.edu replaceBits(cause,Cause_IP7,Cause_IP0,intstatus); 1475222Sksewell@umich.edu tc->setMiscRegNoEffect(MipsISA::Cause,cause); 1485222Sksewell@umich.edu } 1495222Sksewell@umich.edu 1505222Sksewell@umich.edu bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const 1515222Sksewell@umich.edu { 1525222Sksewell@umich.edu MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare); 1535222Sksewell@umich.edu MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count); 1545222Sksewell@umich.edu if (compare == count) 1555222Sksewell@umich.edu return true; 1565222Sksewell@umich.edu return false; 1575222Sksewell@umich.edu } 1585222Sksewell@umich.edu 1595222Sksewell@umich.edu*/ 1605222Sksewell@umich.eduvoid Interrupts::post(int int_num, ThreadContext* tc) 1615222Sksewell@umich.edu{ 1625222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupt %d posted\n", int_num); 1635222Sksewell@umich.edu if (int_num < 0 || int_num >= NumInterruptLevels) 1645222Sksewell@umich.edu panic("int_num out of bounds\n"); 1655222Sksewell@umich.edu 1665222Sksewell@umich.edu uint8_t intstatus= getCauseIP_(tc); 1675222Sksewell@umich.edu intstatus |= 1 << int_num; 1685222Sksewell@umich.edu setCauseIP_(tc, intstatus); 1695222Sksewell@umich.edu} 1705222Sksewell@umich.edu 1715222Sksewell@umich.eduvoid Interrupts::post(int int_num, int index) 1725222Sksewell@umich.edu{ 1735222Sksewell@umich.edu fatal("Must use Thread COntext when posting MIPS Interrupts in M5"); 1745222Sksewell@umich.edu} 1755222Sksewell@umich.edu 1765222Sksewell@umich.eduvoid Interrupts::clear(int int_num, ThreadContext* tc) 1775222Sksewell@umich.edu{ 1785222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num); 1795222Sksewell@umich.edu if (int_num < 0 || int_num >= NumInterruptLevels) 1805222Sksewell@umich.edu panic("int_num out of bounds\n"); 1815222Sksewell@umich.edu 1825222Sksewell@umich.edu uint8_t intstatus = getCauseIP_(tc); 1835222Sksewell@umich.edu intstatus &= ~(1 << int_num); 1845222Sksewell@umich.edu setCauseIP_(tc, intstatus); 1855222Sksewell@umich.edu} 1865222Sksewell@umich.edu 1875222Sksewell@umich.eduvoid Interrupts::clear(int int_num, int index) 1885222Sksewell@umich.edu{ 1895222Sksewell@umich.edu fatal("Must use Thread COntext when clearing MIPS Interrupts in M5"); 1905222Sksewell@umich.edu} 1915222Sksewell@umich.edu 1925222Sksewell@umich.eduvoid Interrupts::clear_all(ThreadContext *tc) 1935222Sksewell@umich.edu{ 1945222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupts all cleared\n"); 1955222Sksewell@umich.edu uint8_t intstatus = 0; 1965222Sksewell@umich.edu setCauseIP_(tc, intstatus); 1975222Sksewell@umich.edu} 1985222Sksewell@umich.edu 1995222Sksewell@umich.eduvoid Interrupts::clear_all() 2005222Sksewell@umich.edu{ 2015222Sksewell@umich.edu fatal("Must use Thread COntext when clearing MIPS Interrupts in M5"); 2025222Sksewell@umich.edu} 2035222Sksewell@umich.edu 2045222Sksewell@umich.edu 2055222Sksewell@umich.edu 2065222Sksewell@umich.eduFault Interrupts::getInterrupt(ThreadContext * tc) 2075222Sksewell@umich.edu{ 2085222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupts getInterrupt\n"); 2095222Sksewell@umich.edu 2105222Sksewell@umich.edu 2115222Sksewell@umich.edu 2125222Sksewell@umich.edu //Check if there are any outstanding interrupts 2135222Sksewell@umich.edu MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status); 2145222Sksewell@umich.edu if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled 2155222Sksewell@umich.edu bits(status, Status_ERL_HI,Status_ERL_LO) == 0 && //error level must be 0 or interrupts inhibited 2165222Sksewell@umich.edu bits(status, Status_EXL_HI,Status_EXL_LO) == 0 ) //exception level must be 0 or interrupts inhibited 2175222Sksewell@umich.edu { 2185222Sksewell@umich.edu // Software interrupts & hardware interrupts are handled in software. 2195222Sksewell@umich.edu // So if any interrupt that isn't masked is detected, jump to interrupt 2205222Sksewell@umich.edu // handler 2215222Sksewell@umich.edu uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending 2225222Sksewell@umich.edu IM = bits(status,Status_IM7,Status_IM0); 2235222Sksewell@umich.edu IP = getCauseIP_(tc); 2245222Sksewell@umich.edu //IM and IP are already correctly aligned 2255222Sksewell@umich.edu if (IM & IP){ 2265222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n", 2275222Sksewell@umich.edu IM, IP); 2285222Sksewell@umich.edu return new InterruptFault; 2295222Sksewell@umich.edu } 2305222Sksewell@umich.edu } 2315222Sksewell@umich.edu 2325222Sksewell@umich.edu return NoFault; 2335222Sksewell@umich.edu 2345222Sksewell@umich.edu} 2355222Sksewell@umich.edubool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const 2365222Sksewell@umich.edu{ 2375222Sksewell@umich.edu MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare); 2385222Sksewell@umich.edu MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count); 2395222Sksewell@umich.edu if (compare == count && count != 0) 2405222Sksewell@umich.edu return true; 2415222Sksewell@umich.edu return false; 2425222Sksewell@umich.edu} 2435222Sksewell@umich.eduvoid Interrupts::updateIntrInfo(ThreadContext *tc) const 2445222Sksewell@umich.edu{ 2455222Sksewell@umich.edu //Nothing needs to be done. 2465222Sksewell@umich.edu ; 2475222Sksewell@umich.edu} 2485222Sksewell@umich.edu 2495222Sksewell@umich.edubool Interrupts::interruptsPending(ThreadContext *tc) const 2505222Sksewell@umich.edu{ 2515222Sksewell@umich.edu //if there is a on cpu timer interrupt (i.e. Compare == Count) 2525222Sksewell@umich.edu //update CauseIP before proceeding to interrupt 2535222Sksewell@umich.edu if (onCpuTimerInterrupt(tc)){ 2545222Sksewell@umich.edu DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n"); 2555222Sksewell@umich.edu //determine timer interrupt IP # 2565222Sksewell@umich.edu MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl); 2575222Sksewell@umich.edu uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO); 2585222Sksewell@umich.edu //set intstatus to correspond 2595222Sksewell@umich.edu //post(IPTI, tc); 2605222Sksewell@umich.edu uint8_t intstatus= getCauseIP_(tc); 2615222Sksewell@umich.edu intstatus |= 1 << IPTI; 2625222Sksewell@umich.edu setCauseIP_(tc, intstatus); 2635222Sksewell@umich.edu } 2645222Sksewell@umich.edu 2655222Sksewell@umich.edu return (getCauseIP_(tc) != 0); 2665222Sksewell@umich.edu 2675222Sksewell@umich.edu} 2685222Sksewell@umich.edu 2695222Sksewell@umich.edu 2705222Sksewell@umich.edu 2715222Sksewell@umich.edu 2725222Sksewell@umich.edu 2735222Sksewell@umich.edu} 274