interrupts.cc (5704:98224505352a) interrupts.cc (6378:4a2ff62c3b4f)
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

--- 24 unchanged lines hidden (view full) ---

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{
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

--- 24 unchanged lines hidden (view full) ---

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{
41static inline uint8_t getCauseIP_(ThreadContext *tc) {
41
42static inline uint8_t
43getCauseIP(ThreadContext *tc) {
42 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
44 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
43 uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0);
44 return IP_;
45 return bits(cause, Cause_IP7, Cause_IP0);
45}
46
46}
47
47static inline void setCauseIP_(ThreadContext *tc, uint8_t val) {
48static inline void
49setCauseIP_(ThreadContext *tc, uint8_t val) {
48 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
50 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
49 replaceBits(cause,Cause_IP7,Cause_IP0,val);
50 tc->setMiscRegNoEffect(MipsISA::Cause,cause);
51 replaceBits(cause, Cause_IP7, Cause_IP0, val);
52 tc->setMiscRegNoEffect(MipsISA::Cause, cause);
51}
52
53}
54
53/*
54 void Interrupts::post(int int_num, int index)
55 {
56 DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
57
58 //index should not be used
59 assert(index == 0);
60
61 if (int_num < 0 || int_num >= NumInterruptLevels)
62 panic("int_num out of bounds\n");
63 intstatus |= 1 << int_num;
64 }
65
66 void Interrupts::clear(int int_num, int index)
67 {
68 DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
69
70 //index should not be used
71 assert(index == 0);
72
73 if (int_num < 0 || int_num >= NumInterruptLevels)
74 panic("int_num out of bounds\n");
75
76 intstatus &= ~(1 << int_num);
77 }
78
79 void Interrupts::clearAll()
80 {
81 DPRINTF(Interrupt, "Interrupts all cleared\n");
82 intstatus = 0;
83 }
84
85
86
87 Fault Interrupts::getInterrupt(ThreadContext * tc)
88 {
89 DPRINTF(Interrupt, "Interrupts getInterrupt\n");
90 // If a timer interrupt has occured, check to see if a
91 // mtc0 to Compare register caused this interrupt to
92 // be cleared. If this is the case, clear intstatus
93 // bit for timer interrupt
94 if (oncputimerintr){
95 DPRINTF(Interrupt, "Interrupts oncputimerintr==true\n");
96 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
97 uint8_t IP_ = bits(cause,Cause_IP7, Cause_IP0);
98 MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
99 uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
100 //mtc0 to compare must have cleared bit in IP
101 if ( ((1 << IPTI) & IP_) == 0){
102 clear(IPTI, 0);
103 oncputimerintr=false;
104 }
105 }
106 //if there is a on cpu timer interrupt (i.e. Compare == Count)
107 //update intstatus before proceeding to interrupt
108 if (onCpuTimerInterrupt(tc)){
109 DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n");
110 //determine timer interrupt IP #
111 MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
112 uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
113 //set intstatus to correspond
114 post(IPTI, 0);
115 oncputimerintr=true;
116 }
117
118 //Check if there are any outstanding interrupts
119 MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
120 if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled
121 bits(status, Status_ERL) == 0 && //error level must be 0 or interrupts inhibited
122 bits(status, Status_EXL) == 0 ) //exception level must be 0 or interrupts inhibited
123 {
124 // Software interrupts & hardware interrupts are handled in software.
125 // So if any interrupt that isn't masked is detected, jump to interrupt
126 // handler
127 uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending
128 IM = bits(status,Status_IM7,Status_IM0);
129 IP = intstatus;
130 //IM and IP are already correctly aligned
131 if (IM & IP){
132 DPRINTF(Flow, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
133 IM, IP);
134 return new InterruptFault;
135 }
136 }
137
138 return NoFault;
139
140 }
141
142 void Interrupts::updateIntrInfo(ThreadContext *tc) const
143 {
144 //Merge Interrupts.intstatus with mips MipISA::Status
145 MiscReg cause = tc->readMiscRegNoEffect(MipsISA::Cause);
146 replaceBits(cause,Cause_IP7,Cause_IP0,intstatus);
147 tc->setMiscRegNoEffect(MipsISA::Cause,cause);
148 }
149
150 bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
151 {
152 MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
153 MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
154 if (compare == count)
155 return true;
156 return false;
157 }
158
159*/
160void Interrupts::post(int int_num, ThreadContext* tc)
55void
56Interrupts::post(int int_num, ThreadContext* tc)
161{
162 DPRINTF(Interrupt, "Interrupt %d posted\n", int_num);
163 if (int_num < 0 || int_num >= NumInterruptLevels)
164 panic("int_num out of bounds\n");
165
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
166 uint8_t intstatus= getCauseIP_(tc);
62 uint8_t intstatus = getCauseIP(tc);
167 intstatus |= 1 << int_num;
63 intstatus |= 1 << int_num;
168 setCauseIP_(tc, intstatus);
64 setCauseIP(tc, intstatus);
169}
170
65}
66
171void Interrupts::post(int int_num, int index)
67void
68Interrupts::post(int int_num, int index)
172{
69{
173 fatal("Must use Thread COntext when posting MIPS Interrupts in M5");
70 fatal("Must use Thread Context when posting MIPS Interrupts in M5");
174}
175
71}
72
176void Interrupts::clear(int int_num, ThreadContext* tc)
73void
74Interrupts::clear(int int_num, ThreadContext* tc)
177{
178 DPRINTF(Interrupt, "Interrupt %d cleared\n", int_num);
179 if (int_num < 0 || int_num >= NumInterruptLevels)
180 panic("int_num out of bounds\n");
181
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
182 uint8_t intstatus = getCauseIP_(tc);
80 uint8_t intstatus = getCauseIP(tc);
183 intstatus &= ~(1 << int_num);
81 intstatus &= ~(1 << int_num);
184 setCauseIP_(tc, intstatus);
82 setCauseIP(tc, intstatus);
185}
186
83}
84
187void Interrupts::clear(int int_num, int index)
85void
86Interrupts::clear(int int_num, int index)
188{
87{
189 fatal("Must use Thread COntext when clearing MIPS Interrupts in M5");
88 fatal("Must use Thread Context when clearing MIPS Interrupts in M5");
190}
191
89}
90
192void Interrupts::clearAll(ThreadContext *tc)
91void
92Interrupts::clearAll(ThreadContext *tc)
193{
194 DPRINTF(Interrupt, "Interrupts all cleared\n");
195 uint8_t intstatus = 0;
93{
94 DPRINTF(Interrupt, "Interrupts all cleared\n");
95 uint8_t intstatus = 0;
196 setCauseIP_(tc, intstatus);
96 setCauseIP(tc, intstatus);
197}
198
97}
98
199void Interrupts::clearAll()
99void
100Interrupts::clearAll()
200{
101{
201 fatal("Must use Thread COntext when clearing MIPS Interrupts in M5");
102 fatal("Must use Thread Context when clearing MIPS Interrupts in M5");
202}
203
204
205
103}
104
105
106
206Fault Interrupts::getInterrupt(ThreadContext * tc)
107Fault
108Interrupts::getInterrupt(ThreadContext * tc)
207{
208 DPRINTF(Interrupt, "Interrupts getInterrupt\n");
209
109{
110 DPRINTF(Interrupt, "Interrupts getInterrupt\n");
111
210
211
212 //Check if there are any outstanding interrupts
213 MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
112 //Check if there are any outstanding interrupts
113 MiscReg status = tc->readMiscRegNoEffect(MipsISA::Status);
214 if (bits(status, Status_IE_LO) == 1 && //interrupts must be enabled
215 bits(status, Status_ERL_HI,Status_ERL_LO) == 0 && //error level must be 0 or interrupts inhibited
216 bits(status, Status_EXL_HI,Status_EXL_LO) == 0 ) //exception level must be 0 or interrupts inhibited
217 {
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) {
218 // Software interrupts & hardware interrupts are handled in software.
219 // So if any interrupt that isn't masked is detected, jump to interrupt
220 // handler
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
221 uint8_t IM, IP; //IM=interrupt mask, IP=interrupt pending
222 IM = bits(status,Status_IM7,Status_IM0);
223 IP = getCauseIP_(tc);
224 //IM and IP are already correctly aligned
225 if (IM & IP){
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){
226 DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
126 DPRINTF(Interrupt, "Interrupt! IM[7:0]=%d IP[7:0]=%d \n",
227 IM, IP);
127 InterruptMask, InterruptPending);
228 return new InterruptFault;
229 }
230 }
231
232 return NoFault;
128 return new InterruptFault;
129 }
130 }
131
132 return NoFault;
233
234}
133}
235bool Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
134
135bool
136Interrupts::onCpuTimerInterrupt(ThreadContext * tc) const
236{
237 MiscReg compare = tc->readMiscRegNoEffect(MipsISA::Compare);
238 MiscReg count = tc->readMiscRegNoEffect(MipsISA::Count);
239 if (compare == count && count != 0)
240 return true;
241 return false;
242}
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}
243void Interrupts::updateIntrInfo(ThreadContext *tc) const
144
145void
146Interrupts::updateIntrInfo(ThreadContext *tc) const
244{
245 //Nothing needs to be done.
147{
148 //Nothing needs to be done.
246 ;
247}
248
149}
150
249bool Interrupts::interruptsPending(ThreadContext *tc) const
151bool
152Interrupts::interruptsPending(ThreadContext *tc) const
250{
251 //if there is a on cpu timer interrupt (i.e. Compare == Count)
252 //update CauseIP before proceeding to interrupt
153{
154 //if there is a on cpu timer interrupt (i.e. Compare == Count)
155 //update CauseIP before proceeding to interrupt
253 if (onCpuTimerInterrupt(tc)){
254 DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc)==true\n");
156 if (onCpuTimerInterrupt(tc)) {
157 DPRINTF(Interrupt, "Interrupts OnCpuTimerINterrupt(tc) == true\n");
255 //determine timer interrupt IP #
256 MiscReg intctl = tc->readMiscRegNoEffect(MipsISA::IntCtl);
257 uint8_t IPTI = bits(intctl, IntCtl_IPTI_HI, IntCtl_IPTI_LO);
258 //set intstatus to correspond
259 //post(IPTI, tc);
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);
260 uint8_t intstatus= getCauseIP_(tc);
163 uint8_t intstatus = getCauseIP(tc);
261 intstatus |= 1 << IPTI;
164 intstatus |= 1 << IPTI;
262 setCauseIP_(tc, intstatus);
165 setCauseIP(tc, intstatus);
263 }
264
166 }
167
265 return (getCauseIP_(tc) != 0);
168 return (getCauseIP(tc) != 0);
266
267}
268
169
170}
171
269
270
271
272
273}
172}