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 * --- 41 unchanged lines hidden (view full) --- 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 * --- 41 unchanged lines hidden (view full) --- 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"); --- 12 unchanged lines hidden (view full) --- 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"); --- 12 unchanged lines hidden (view full) --- 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"); --- 62 unchanged lines hidden (view full) --- 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"); --- 62 unchanged lines hidden (view full) --- 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} |