interrupts.cc revision 6378
1/* 2 * Copyright (c) 2006 The Regents of The University of Michigan 3 * Copyright (c) 2007 MIPS Technologies, Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * Authors: Steve Reinhardt 30 * Kevin Lim 31 * Korey Sewell 32 */ 33 34#include "arch/mips/pra_constants.hh" 35#include "arch/mips/isa_traits.hh" 36#include "cpu/thread_context.hh" 37#include "arch/mips/interrupts.hh" 38 39namespace MipsISA 40{ 41 42static inline uint8_t 43getCauseIP(ThreadContext *tc) { 44 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); 45 return bits(cause, Cause_IP7, Cause_IP0); 46} 47 48static inline void 49setCauseIP_(ThreadContext *tc, uint8_t val) { 50 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause); 51 replaceBits(cause, Cause_IP7, Cause_IP0, val); 52 tc->setMiscRegNoEffect(MipsISA::Cause, cause); 53} 54 55void 56Interrupts::post(int int_num, ThreadContext* tc) 57{ 58 DPRINTF(Interrupt, "Interrupt %d posted\n", int_num); 59 if (int_num < 0 || int_num >= NumInterruptLevels) 60 panic("int_num out of bounds\n"); 61 62 uint8_t intstatus = getCauseIP(tc); 63 intstatus |= 1 << int_num; 64 setCauseIP(tc, intstatus); 65} 66 67void 68Interrupts::post(int int_num, int index) 69{ 70 fatal("Must use Thread Context when posting MIPS Interrupts in M5"); 71} 72 73void 74Interrupts::clear(int int_num, ThreadContext* tc) 75{ 76 DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num); 77 if (int_num < 0 || int_num >= NumInterruptLevels) 78 panic("int_num out of bounds\n"); 79 80 uint8_t intstatus = getCauseIP(tc); 81 intstatus &= ~(1 << int_num); 82 setCauseIP(tc, intstatus); 83} 84 85void 86Interrupts::clear(int int_num, int index) 87{ 88 fatal("Must use Thread Context when clearing MIPS Interrupts in M5"); 89} 90 91void 92Interrupts::clearAll(ThreadContext *tc) 93{ 94 DPRINTF(Interrupt, "Interrupts all cleared\n"); 95 uint8_t intstatus = 0; 96 setCauseIP(tc, intstatus); 97} 98 99void 100Interrupts::clearAll() 101{ 102 fatal("Must use Thread Context when clearing MIPS Interrupts in M5"); 103} 104 105 106 107Fault 108Interrupts::getInterrupt(ThreadContext * tc) 109{ 110 DPRINTF(Interrupt, "Interrupts getInterrupt\n"); 111 112 //Check if there are any outstanding interrupts 113 MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status); 114 // Interrupts must be enabled, error level must be 0 or interrupts 115 // inhibited, and exception level must be 0 or interrupts inhibited 116 if (bits(status, Status_IE_LO) == 1 && 117 bits(status, Status_ERL_HI, Status_ERL_LO) == 0 && 118 bits(status, Status_EXL_HI, Status_EXL_LO) == 0) { 119 // Software interrupts & hardware interrupts are handled in software. 120 // So if any interrupt that isn't masked is detected, jump to interrupt 121 // handler 122 uint8_t InterruptMask = bits(status, Status_IM7, Status_IM0); 123 uint8_t InterruptPending = getCauseIP(tc); 124 // InterruptMask and InterruptPending are already correctly aligned 125 if (InterruptMask && InterruptPending){ 126 DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n", 127 InterruptMask, InterruptPending); 128 return new InterruptFault; 129 } 130 } 131 132 return NoFault; 133} 134 135bool 136Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const 137{ 138 MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare); 139 MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count); 140 if (compare == count && count != 0) 141 return true; 142 return false; 143} 144 145void 146Interrupts::updateIntrInfo(ThreadContext *tc) const 147{ 148 //Nothing needs to be done. 149} 150 151bool 152Interrupts::interruptsPending(ThreadContext *tc) const 153{ 154 //if there is a on cpu timer interrupt (i.e. Compare == Count) 155 //update CauseIP before proceeding to interrupt 156 if (onCpuTimerInterrupt(tc)) { 157 DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc) == true\n"); 158 //determine timer interrupt IP # 159 MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl); 160 uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO); 161 //set intstatus to correspond 162 //post(IPTI, tc); 163 uint8_t intstatus = getCauseIP(tc); 164 intstatus |= 1 << IPTI; 165 setCauseIP(tc, intstatus); 166 } 167 168 return (getCauseIP(tc) != 0); 169 170} 171 172} 173