interrupts.cc (5647:b06b49498c79) interrupts.cc (5648:e8abda6e0980)
1/*
2 * Copyright (c) 2008 The Hewlett-Packard Development Company
3 * All rights reserved.
4 *
5 * Redistribution and use of this software in source and binary forms,
6 * with or without modification, are permitted provided that the
7 * following conditions are met:
8 *
9 * The software must be used only for Non-Commercial Use which means any
10 * use which is NOT directed to receiving any direct monetary
11 * compensation for, or commercial advantage from such use. Illustrative
12 * examples of non-commercial use are academic research, personal study,
13 * teaching, education and corporate research & development.
14 * Illustrative examples of commercial use are distributing products for
15 * commercial advantage and providing services using the software for
16 * commercial advantage.
17 *
18 * If you wish to use this software or functionality therein that may be
19 * covered by patents for commercial use, please contact:
20 * Director of Intellectual Property Licensing
21 * Office of Strategy and Technology
22 * Hewlett-Packard Company
23 * 1501 Page Mill Road
24 * Palo Alto, California 94304
25 *
26 * Redistributions of source code must retain the above copyright notice,
27 * this list of conditions and the following disclaimer. Redistributions
28 * in binary form must reproduce the above copyright notice, this list of
29 * conditions and the following disclaimer in the documentation and/or
30 * other materials provided with the distribution. Neither the name of
31 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
32 * contributors may be used to endorse or promote products derived from
33 * this software without specific prior written permission. No right of
34 * sublicense is granted herewith. Derivatives of the software and
35 * output created using the software may be prepared, but only for
36 * Non-Commercial Uses. Derivatives of the software may be shared with
37 * others provided: (i) the others agree to abide by the list of
38 * conditions herein which includes the Non-Commercial Use restrictions;
39 * and (ii) such Derivatives of the software include the above copyright
40 * notice to acknowledge the contribution from this software where
41 * applicable, this list of conditions and the disclaimer below.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 *
55 * Authors: Gabe Black
56 */
57
1/*
2 * Copyright (c) 2008 The Hewlett-Packard Development Company
3 * All rights reserved.
4 *
5 * Redistribution and use of this software in source and binary forms,
6 * with or without modification, are permitted provided that the
7 * following conditions are met:
8 *
9 * The software must be used only for Non-Commercial Use which means any
10 * use which is NOT directed to receiving any direct monetary
11 * compensation for, or commercial advantage from such use. Illustrative
12 * examples of non-commercial use are academic research, personal study,
13 * teaching, education and corporate research & development.
14 * Illustrative examples of commercial use are distributing products for
15 * commercial advantage and providing services using the software for
16 * commercial advantage.
17 *
18 * If you wish to use this software or functionality therein that may be
19 * covered by patents for commercial use, please contact:
20 * Director of Intellectual Property Licensing
21 * Office of Strategy and Technology
22 * Hewlett-Packard Company
23 * 1501 Page Mill Road
24 * Palo Alto, California 94304
25 *
26 * Redistributions of source code must retain the above copyright notice,
27 * this list of conditions and the following disclaimer. Redistributions
28 * in binary form must reproduce the above copyright notice, this list of
29 * conditions and the following disclaimer in the documentation and/or
30 * other materials provided with the distribution. Neither the name of
31 * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
32 * contributors may be used to endorse or promote products derived from
33 * this software without specific prior written permission. No right of
34 * sublicense is granted herewith. Derivatives of the software and
35 * output created using the software may be prepared, but only for
36 * Non-Commercial Uses. Derivatives of the software may be shared with
37 * others provided: (i) the others agree to abide by the list of
38 * conditions herein which includes the Non-Commercial Use restrictions;
39 * and (ii) such Derivatives of the software include the above copyright
40 * notice to acknowledge the contribution from this software where
41 * applicable, this list of conditions and the disclaimer below.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 *
55 * Authors: Gabe Black
56 */
57
58#include "arch/x86/apicregs.hh"
58#include "arch/x86/interrupts.hh"
59#include "cpu/base.hh"
60
59#include "arch/x86/interrupts.hh"
60#include "cpu/base.hh"
61
61int divideFromConf(uint32_t conf)
62int
63divideFromConf(uint32_t conf)
62{
63 // This figures out what division we want from the division configuration
64 // register in the local APIC. The encoding is a little odd but it can
65 // be deciphered fairly easily.
66 int shift = ((conf & 0x8) >> 1) | (conf & 0x3);
67 shift = (shift + 1) % 8;
68 return 1 << shift;
69}
70
64{
65 // This figures out what division we want from the division configuration
66 // register in the local APIC. The encoding is a little odd but it can
67 // be deciphered fairly easily.
68 int shift = ((conf & 0x8) >> 1) | (conf & 0x3);
69 shift = (shift + 1) % 8;
70 return 1 << shift;
71}
72
71uint32_t
72X86ISA::Interrupts::readRegNoEffect(ApicRegIndex reg)
73namespace X86ISA
73{
74{
74 return regs[reg];
75
76ApicRegIndex
77decodeAddr(Addr paddr)
78{
79 ApicRegIndex regNum;
80 paddr &= ~mask(3);
81 switch (paddr)
82 {
83 case 0x20:
84 regNum = APIC_ID;
85 break;
86 case 0x30:
87 regNum = APIC_VERSION;
88 break;
89 case 0x80:
90 regNum = APIC_TASK_PRIORITY;
91 break;
92 case 0x90:
93 regNum = APIC_ARBITRATION_PRIORITY;
94 break;
95 case 0xA0:
96 regNum = APIC_PROCESSOR_PRIORITY;
97 break;
98 case 0xB0:
99 regNum = APIC_EOI;
100 break;
101 case 0xD0:
102 regNum = APIC_LOGICAL_DESTINATION;
103 break;
104 case 0xE0:
105 regNum = APIC_DESTINATION_FORMAT;
106 break;
107 case 0xF0:
108 regNum = APIC_SPURIOUS_INTERRUPT_VECTOR;
109 break;
110 case 0x100:
111 case 0x108:
112 case 0x110:
113 case 0x118:
114 case 0x120:
115 case 0x128:
116 case 0x130:
117 case 0x138:
118 case 0x140:
119 case 0x148:
120 case 0x150:
121 case 0x158:
122 case 0x160:
123 case 0x168:
124 case 0x170:
125 case 0x178:
126 regNum = APIC_IN_SERVICE((paddr - 0x100) / 0x8);
127 break;
128 case 0x180:
129 case 0x188:
130 case 0x190:
131 case 0x198:
132 case 0x1A0:
133 case 0x1A8:
134 case 0x1B0:
135 case 0x1B8:
136 case 0x1C0:
137 case 0x1C8:
138 case 0x1D0:
139 case 0x1D8:
140 case 0x1E0:
141 case 0x1E8:
142 case 0x1F0:
143 case 0x1F8:
144 regNum = APIC_TRIGGER_MODE((paddr - 0x180) / 0x8);
145 break;
146 case 0x200:
147 case 0x208:
148 case 0x210:
149 case 0x218:
150 case 0x220:
151 case 0x228:
152 case 0x230:
153 case 0x238:
154 case 0x240:
155 case 0x248:
156 case 0x250:
157 case 0x258:
158 case 0x260:
159 case 0x268:
160 case 0x270:
161 case 0x278:
162 regNum = APIC_INTERRUPT_REQUEST((paddr - 0x200) / 0x8);
163 break;
164 case 0x280:
165 regNum = APIC_ERROR_STATUS;
166 break;
167 case 0x300:
168 regNum = APIC_INTERRUPT_COMMAND_LOW;
169 break;
170 case 0x310:
171 regNum = APIC_INTERRUPT_COMMAND_HIGH;
172 break;
173 case 0x320:
174 regNum = APIC_LVT_TIMER;
175 break;
176 case 0x330:
177 regNum = APIC_LVT_THERMAL_SENSOR;
178 break;
179 case 0x340:
180 regNum = APIC_LVT_PERFORMANCE_MONITORING_COUNTERS;
181 break;
182 case 0x350:
183 regNum = APIC_LVT_LINT0;
184 break;
185 case 0x360:
186 regNum = APIC_LVT_LINT1;
187 break;
188 case 0x370:
189 regNum = APIC_LVT_ERROR;
190 break;
191 case 0x380:
192 regNum = APIC_INITIAL_COUNT;
193 break;
194 case 0x390:
195 regNum = APIC_CURRENT_COUNT;
196 break;
197 case 0x3E0:
198 regNum = APIC_DIVIDE_CONFIGURATION;
199 break;
200 default:
201 // A reserved register field.
202 panic("Accessed reserved register field %#x.\n", paddr);
203 break;
204 }
205 return regNum;
75}
206}
207}
76
208
209Tick
210X86ISA::Interrupts::read(PacketPtr pkt)
211{
212 Addr offset = pkt->getAddr() - pioAddr;
213 //Make sure we're at least only accessing one register.
214 if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3)))
215 panic("Accessed more than one register at a time in the APIC!\n");
216 ApicRegIndex reg = decodeAddr(offset);
217 uint32_t val = htog(readReg(reg));
218 pkt->setData(((uint8_t *)&val) + (offset & mask(3)));
219 return latency;
220}
221
222Tick
223X86ISA::Interrupts::write(PacketPtr pkt)
224{
225 Addr offset = pkt->getAddr() - pioAddr;
226 //Make sure we're at least only accessing one register.
227 if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3)))
228 panic("Accessed more than one register at a time in the APIC!\n");
229 ApicRegIndex reg = decodeAddr(offset);
230 uint32_t val = regs[reg];
231 pkt->writeData(((uint8_t *)&val) + (offset & mask(3)));
232 setReg(reg, gtoh(val));
233 return latency;
234}
235
77uint32_t
236uint32_t
78X86ISA::Interrupts::readReg(ApicRegIndex reg, ThreadContext * tc)
237X86ISA::Interrupts::readReg(ApicRegIndex reg)
79{
80 if (reg >= APIC_TRIGGER_MODE(0) &&
81 reg <= APIC_TRIGGER_MODE(15)) {
82 panic("Local APIC Trigger Mode registers are unimplemented.\n");
83 }
84 switch (reg) {
85 case APIC_ARBITRATION_PRIORITY:
86 panic("Local APIC Arbitration Priority register unimplemented.\n");
87 break;
88 case APIC_PROCESSOR_PRIORITY:
89 panic("Local APIC Processor Priority register unimplemented.\n");
90 break;
91 case APIC_EOI:
92 panic("Local APIC EOI register unimplemented.\n");
93 break;
94 case APIC_ERROR_STATUS:
95 regs[APIC_INTERNAL_STATE] &= ~ULL(0x1);
96 break;
97 case APIC_INTERRUPT_COMMAND_LOW:
98 panic("Local APIC Interrupt Command low"
99 " register unimplemented.\n");
100 break;
101 case APIC_INTERRUPT_COMMAND_HIGH:
102 panic("Local APIC Interrupt Command high"
103 " register unimplemented.\n");
104 break;
105 case APIC_CURRENT_COUNT:
106 {
238{
239 if (reg >= APIC_TRIGGER_MODE(0) &&
240 reg <= APIC_TRIGGER_MODE(15)) {
241 panic("Local APIC Trigger Mode registers are unimplemented.\n");
242 }
243 switch (reg) {
244 case APIC_ARBITRATION_PRIORITY:
245 panic("Local APIC Arbitration Priority register unimplemented.\n");
246 break;
247 case APIC_PROCESSOR_PRIORITY:
248 panic("Local APIC Processor Priority register unimplemented.\n");
249 break;
250 case APIC_EOI:
251 panic("Local APIC EOI register unimplemented.\n");
252 break;
253 case APIC_ERROR_STATUS:
254 regs[APIC_INTERNAL_STATE] &= ~ULL(0x1);
255 break;
256 case APIC_INTERRUPT_COMMAND_LOW:
257 panic("Local APIC Interrupt Command low"
258 " register unimplemented.\n");
259 break;
260 case APIC_INTERRUPT_COMMAND_HIGH:
261 panic("Local APIC Interrupt Command high"
262 " register unimplemented.\n");
263 break;
264 case APIC_CURRENT_COUNT:
265 {
107 uint32_t val = regs[reg] - tc->getCpuPtr()->curCycle();
266 assert(clock);
267 uint32_t val = regs[reg] - curTick / clock;
108 val /= (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]));
109 return val;
110 }
111 default:
112 break;
113 }
268 val /= (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]));
269 return val;
270 }
271 default:
272 break;
273 }
114 return readRegNoEffect(reg);
274 return regs[reg];
115}
116
117void
275}
276
277void
118X86ISA::Interrupts::setRegNoEffect(ApicRegIndex reg, uint32_t val)
278X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
119{
279{
120 regs[reg] = val;
121}
122
123void
124X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val, ThreadContext *tc)
125{
126 uint32_t newVal = val;
127 if (reg >= APIC_IN_SERVICE(0) &&
128 reg <= APIC_IN_SERVICE(15)) {
129 panic("Local APIC In-Service registers are unimplemented.\n");
130 }
131 if (reg >= APIC_TRIGGER_MODE(0) &&
132 reg <= APIC_TRIGGER_MODE(15)) {
133 panic("Local APIC Trigger Mode registers are unimplemented.\n");
134 }
135 if (reg >= APIC_INTERRUPT_REQUEST(0) &&
136 reg <= APIC_INTERRUPT_REQUEST(15)) {
137 panic("Local APIC Interrupt Request registers "
138 "are unimplemented.\n");
139 }
140 switch (reg) {
141 case APIC_ID:
142 newVal = val & 0xFF;
143 break;
144 case APIC_VERSION:
145 // The Local APIC Version register is read only.
146 return;
147 case APIC_TASK_PRIORITY:
148 newVal = val & 0xFF;
149 break;
150 case APIC_ARBITRATION_PRIORITY:
151 panic("Local APIC Arbitration Priority register unimplemented.\n");
152 break;
153 case APIC_PROCESSOR_PRIORITY:
154 panic("Local APIC Processor Priority register unimplemented.\n");
155 break;
156 case APIC_EOI:
157 panic("Local APIC EOI register unimplemented.\n");
158 break;
159 case APIC_LOGICAL_DESTINATION:
160 newVal = val & 0xFF000000;
161 break;
162 case APIC_DESTINATION_FORMAT:
163 newVal = val | 0x0FFFFFFF;
164 break;
165 case APIC_SPURIOUS_INTERRUPT_VECTOR:
166 regs[APIC_INTERNAL_STATE] &= ~ULL(1 << 1);
167 regs[APIC_INTERNAL_STATE] |= val & (1 << 8);
168 if (val & (1 << 9))
169 warn("Focus processor checking not implemented.\n");
170 break;
171 case APIC_ERROR_STATUS:
172 {
173 if (regs[APIC_INTERNAL_STATE] & 0x1) {
174 regs[APIC_INTERNAL_STATE] &= ~ULL(0x1);
175 newVal = 0;
176 } else {
177 regs[APIC_INTERNAL_STATE] |= ULL(0x1);
178 return;
179 }
180
181 }
182 break;
183 case APIC_INTERRUPT_COMMAND_LOW:
184 panic("Local APIC Interrupt Command low"
185 " register unimplemented.\n");
186 break;
187 case APIC_INTERRUPT_COMMAND_HIGH:
188 panic("Local APIC Interrupt Command high"
189 " register unimplemented.\n");
190 break;
191 case APIC_LVT_TIMER:
192 case APIC_LVT_THERMAL_SENSOR:
193 case APIC_LVT_PERFORMANCE_MONITORING_COUNTERS:
194 case APIC_LVT_LINT0:
195 case APIC_LVT_LINT1:
196 case APIC_LVT_ERROR:
197 {
198 uint64_t readOnlyMask = (1 << 12) | (1 << 14);
199 newVal = (val & ~readOnlyMask) |
200 (regs[reg] & readOnlyMask);
201 }
202 break;
203 case APIC_INITIAL_COUNT:
280 uint32_t newVal = val;
281 if (reg >= APIC_IN_SERVICE(0) &&
282 reg <= APIC_IN_SERVICE(15)) {
283 panic("Local APIC In-Service registers are unimplemented.\n");
284 }
285 if (reg >= APIC_TRIGGER_MODE(0) &&
286 reg <= APIC_TRIGGER_MODE(15)) {
287 panic("Local APIC Trigger Mode registers are unimplemented.\n");
288 }
289 if (reg >= APIC_INTERRUPT_REQUEST(0) &&
290 reg <= APIC_INTERRUPT_REQUEST(15)) {
291 panic("Local APIC Interrupt Request registers "
292 "are unimplemented.\n");
293 }
294 switch (reg) {
295 case APIC_ID:
296 newVal = val & 0xFF;
297 break;
298 case APIC_VERSION:
299 // The Local APIC Version register is read only.
300 return;
301 case APIC_TASK_PRIORITY:
302 newVal = val & 0xFF;
303 break;
304 case APIC_ARBITRATION_PRIORITY:
305 panic("Local APIC Arbitration Priority register unimplemented.\n");
306 break;
307 case APIC_PROCESSOR_PRIORITY:
308 panic("Local APIC Processor Priority register unimplemented.\n");
309 break;
310 case APIC_EOI:
311 panic("Local APIC EOI register unimplemented.\n");
312 break;
313 case APIC_LOGICAL_DESTINATION:
314 newVal = val & 0xFF000000;
315 break;
316 case APIC_DESTINATION_FORMAT:
317 newVal = val | 0x0FFFFFFF;
318 break;
319 case APIC_SPURIOUS_INTERRUPT_VECTOR:
320 regs[APIC_INTERNAL_STATE] &= ~ULL(1 << 1);
321 regs[APIC_INTERNAL_STATE] |= val & (1 << 8);
322 if (val & (1 << 9))
323 warn("Focus processor checking not implemented.\n");
324 break;
325 case APIC_ERROR_STATUS:
326 {
327 if (regs[APIC_INTERNAL_STATE] & 0x1) {
328 regs[APIC_INTERNAL_STATE] &= ~ULL(0x1);
329 newVal = 0;
330 } else {
331 regs[APIC_INTERNAL_STATE] |= ULL(0x1);
332 return;
333 }
334
335 }
336 break;
337 case APIC_INTERRUPT_COMMAND_LOW:
338 panic("Local APIC Interrupt Command low"
339 " register unimplemented.\n");
340 break;
341 case APIC_INTERRUPT_COMMAND_HIGH:
342 panic("Local APIC Interrupt Command high"
343 " register unimplemented.\n");
344 break;
345 case APIC_LVT_TIMER:
346 case APIC_LVT_THERMAL_SENSOR:
347 case APIC_LVT_PERFORMANCE_MONITORING_COUNTERS:
348 case APIC_LVT_LINT0:
349 case APIC_LVT_LINT1:
350 case APIC_LVT_ERROR:
351 {
352 uint64_t readOnlyMask = (1 << 12) | (1 << 14);
353 newVal = (val & ~readOnlyMask) |
354 (regs[reg] & readOnlyMask);
355 }
356 break;
357 case APIC_INITIAL_COUNT:
204 newVal = bits(val, 31, 0);
205 regs[APIC_CURRENT_COUNT] =
206 tc->getCpuPtr()->curCycle() +
207 (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION])) * newVal;
208 //FIXME This should schedule the timer event.
358 {
359 assert(clock);
360 newVal = bits(val, 31, 0);
361 uint32_t newCount = newVal *
362 (divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]) * 16);
363 regs[APIC_CURRENT_COUNT] = newCount + curTick / clock;
364 // Find out how long a "tick" of the timer should take.
365 Tick timerTick = 16 * clock;
366 // Schedule on the edge of the next tick plus the new count.
367 Tick offset = curTick % timerTick;
368 if (offset) {
369 reschedule(apicTimerEvent,
370 curTick + (newCount + 1) * timerTick - offset, true);
371 } else {
372 reschedule(apicTimerEvent,
373 curTick + newCount * timerTick, true);
374 }
375 }
209 break;
210 case APIC_CURRENT_COUNT:
211 //Local APIC Current Count register is read only.
212 return;
213 case APIC_DIVIDE_CONFIGURATION:
214 newVal = val & 0xB;
215 break;
216 default:
217 break;
218 }
376 break;
377 case APIC_CURRENT_COUNT:
378 //Local APIC Current Count register is read only.
379 return;
380 case APIC_DIVIDE_CONFIGURATION:
381 newVal = val & 0xB;
382 break;
383 default:
384 break;
385 }
219 setRegNoEffect(reg, newVal);
386 regs[reg] = newVal;
220 return;
221}
222
223X86ISA::Interrupts *
224X86LocalApicParams::create()
225{
226 return new X86ISA::Interrupts(this);
227}
387 return;
388}
389
390X86ISA::Interrupts *
391X86LocalApicParams::create()
392{
393 return new X86ISA::Interrupts(this);
394}