interrupts.cc revision 5647
15647Sgblack@eecs.umich.edu/* 25647Sgblack@eecs.umich.edu * Copyright (c) 2008 The Hewlett-Packard Development Company 35647Sgblack@eecs.umich.edu * All rights reserved. 45647Sgblack@eecs.umich.edu * 55647Sgblack@eecs.umich.edu * Redistribution and use of this software in source and binary forms, 65647Sgblack@eecs.umich.edu * with or without modification, are permitted provided that the 75647Sgblack@eecs.umich.edu * following conditions are met: 85647Sgblack@eecs.umich.edu * 95647Sgblack@eecs.umich.edu * The software must be used only for Non-Commercial Use which means any 105647Sgblack@eecs.umich.edu * use which is NOT directed to receiving any direct monetary 115647Sgblack@eecs.umich.edu * compensation for, or commercial advantage from such use. Illustrative 125647Sgblack@eecs.umich.edu * examples of non-commercial use are academic research, personal study, 135647Sgblack@eecs.umich.edu * teaching, education and corporate research & development. 145647Sgblack@eecs.umich.edu * Illustrative examples of commercial use are distributing products for 155647Sgblack@eecs.umich.edu * commercial advantage and providing services using the software for 165647Sgblack@eecs.umich.edu * commercial advantage. 175647Sgblack@eecs.umich.edu * 185647Sgblack@eecs.umich.edu * If you wish to use this software or functionality therein that may be 195647Sgblack@eecs.umich.edu * covered by patents for commercial use, please contact: 205647Sgblack@eecs.umich.edu * Director of Intellectual Property Licensing 215647Sgblack@eecs.umich.edu * Office of Strategy and Technology 225647Sgblack@eecs.umich.edu * Hewlett-Packard Company 235647Sgblack@eecs.umich.edu * 1501 Page Mill Road 245647Sgblack@eecs.umich.edu * Palo Alto, California 94304 255647Sgblack@eecs.umich.edu * 265647Sgblack@eecs.umich.edu * Redistributions of source code must retain the above copyright notice, 275647Sgblack@eecs.umich.edu * this list of conditions and the following disclaimer. Redistributions 285647Sgblack@eecs.umich.edu * in binary form must reproduce the above copyright notice, this list of 295647Sgblack@eecs.umich.edu * conditions and the following disclaimer in the documentation and/or 305647Sgblack@eecs.umich.edu * other materials provided with the distribution. Neither the name of 315647Sgblack@eecs.umich.edu * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its 325647Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 335647Sgblack@eecs.umich.edu * this software without specific prior written permission. No right of 345647Sgblack@eecs.umich.edu * sublicense is granted herewith. Derivatives of the software and 355647Sgblack@eecs.umich.edu * output created using the software may be prepared, but only for 365647Sgblack@eecs.umich.edu * Non-Commercial Uses. Derivatives of the software may be shared with 375647Sgblack@eecs.umich.edu * others provided: (i) the others agree to abide by the list of 385647Sgblack@eecs.umich.edu * conditions herein which includes the Non-Commercial Use restrictions; 395647Sgblack@eecs.umich.edu * and (ii) such Derivatives of the software include the above copyright 405647Sgblack@eecs.umich.edu * notice to acknowledge the contribution from this software where 415647Sgblack@eecs.umich.edu * applicable, this list of conditions and the disclaimer below. 425647Sgblack@eecs.umich.edu * 435647Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 445647Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 455647Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 465647Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 475647Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 485647Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 495647Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 505647Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 515647Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 525647Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 535647Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 545647Sgblack@eecs.umich.edu * 555647Sgblack@eecs.umich.edu * Authors: Gabe Black 565647Sgblack@eecs.umich.edu */ 575647Sgblack@eecs.umich.edu 585647Sgblack@eecs.umich.edu#include "arch/x86/interrupts.hh" 595647Sgblack@eecs.umich.edu#include "cpu/base.hh" 605647Sgblack@eecs.umich.edu 615647Sgblack@eecs.umich.eduint divideFromConf(uint32_t conf) 625647Sgblack@eecs.umich.edu{ 635647Sgblack@eecs.umich.edu // This figures out what division we want from the division configuration 645647Sgblack@eecs.umich.edu // register in the local APIC. The encoding is a little odd but it can 655647Sgblack@eecs.umich.edu // be deciphered fairly easily. 665647Sgblack@eecs.umich.edu int shift = ((conf & 0x8) >> 1) | (conf & 0x3); 675647Sgblack@eecs.umich.edu shift = (shift + 1) % 8; 685647Sgblack@eecs.umich.edu return 1 << shift; 695647Sgblack@eecs.umich.edu} 705647Sgblack@eecs.umich.edu 715647Sgblack@eecs.umich.eduuint32_t 725647Sgblack@eecs.umich.eduX86ISA::Interrupts::readRegNoEffect(ApicRegIndex reg) 735647Sgblack@eecs.umich.edu{ 745647Sgblack@eecs.umich.edu return regs[reg]; 755647Sgblack@eecs.umich.edu} 765647Sgblack@eecs.umich.edu 775647Sgblack@eecs.umich.eduuint32_t 785647Sgblack@eecs.umich.eduX86ISA::Interrupts::readReg(ApicRegIndex reg, ThreadContext * tc) 795647Sgblack@eecs.umich.edu{ 805647Sgblack@eecs.umich.edu if (reg >= APIC_TRIGGER_MODE(0) && 815647Sgblack@eecs.umich.edu reg <= APIC_TRIGGER_MODE(15)) { 825647Sgblack@eecs.umich.edu panic("Local APIC Trigger Mode registers are unimplemented.\n"); 835647Sgblack@eecs.umich.edu } 845647Sgblack@eecs.umich.edu switch (reg) { 855647Sgblack@eecs.umich.edu case APIC_ARBITRATION_PRIORITY: 865647Sgblack@eecs.umich.edu panic("Local APIC Arbitration Priority register unimplemented.\n"); 875647Sgblack@eecs.umich.edu break; 885647Sgblack@eecs.umich.edu case APIC_PROCESSOR_PRIORITY: 895647Sgblack@eecs.umich.edu panic("Local APIC Processor Priority register unimplemented.\n"); 905647Sgblack@eecs.umich.edu break; 915647Sgblack@eecs.umich.edu case APIC_EOI: 925647Sgblack@eecs.umich.edu panic("Local APIC EOI register unimplemented.\n"); 935647Sgblack@eecs.umich.edu break; 945647Sgblack@eecs.umich.edu case APIC_ERROR_STATUS: 955647Sgblack@eecs.umich.edu regs[APIC_INTERNAL_STATE] &= ~ULL(0x1); 965647Sgblack@eecs.umich.edu break; 975647Sgblack@eecs.umich.edu case APIC_INTERRUPT_COMMAND_LOW: 985647Sgblack@eecs.umich.edu panic("Local APIC Interrupt Command low" 995647Sgblack@eecs.umich.edu " register unimplemented.\n"); 1005647Sgblack@eecs.umich.edu break; 1015647Sgblack@eecs.umich.edu case APIC_INTERRUPT_COMMAND_HIGH: 1025647Sgblack@eecs.umich.edu panic("Local APIC Interrupt Command high" 1035647Sgblack@eecs.umich.edu " register unimplemented.\n"); 1045647Sgblack@eecs.umich.edu break; 1055647Sgblack@eecs.umich.edu case APIC_CURRENT_COUNT: 1065647Sgblack@eecs.umich.edu { 1075647Sgblack@eecs.umich.edu uint32_t val = regs[reg] - tc->getCpuPtr()->curCycle(); 1085647Sgblack@eecs.umich.edu val /= (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION])); 1095647Sgblack@eecs.umich.edu return val; 1105647Sgblack@eecs.umich.edu } 1115647Sgblack@eecs.umich.edu default: 1125647Sgblack@eecs.umich.edu break; 1135647Sgblack@eecs.umich.edu } 1145647Sgblack@eecs.umich.edu return readRegNoEffect(reg); 1155647Sgblack@eecs.umich.edu} 1165647Sgblack@eecs.umich.edu 1175647Sgblack@eecs.umich.eduvoid 1185647Sgblack@eecs.umich.eduX86ISA::Interrupts::setRegNoEffect(ApicRegIndex reg, uint32_t val) 1195647Sgblack@eecs.umich.edu{ 1205647Sgblack@eecs.umich.edu regs[reg] = val; 1215647Sgblack@eecs.umich.edu} 1225647Sgblack@eecs.umich.edu 1235647Sgblack@eecs.umich.eduvoid 1245647Sgblack@eecs.umich.eduX86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val, ThreadContext *tc) 1255647Sgblack@eecs.umich.edu{ 1265647Sgblack@eecs.umich.edu uint32_t newVal = val; 1275647Sgblack@eecs.umich.edu if (reg >= APIC_IN_SERVICE(0) && 1285647Sgblack@eecs.umich.edu reg <= APIC_IN_SERVICE(15)) { 1295647Sgblack@eecs.umich.edu panic("Local APIC In-Service registers are unimplemented.\n"); 1305647Sgblack@eecs.umich.edu } 1315647Sgblack@eecs.umich.edu if (reg >= APIC_TRIGGER_MODE(0) && 1325647Sgblack@eecs.umich.edu reg <= APIC_TRIGGER_MODE(15)) { 1335647Sgblack@eecs.umich.edu panic("Local APIC Trigger Mode registers are unimplemented.\n"); 1345647Sgblack@eecs.umich.edu } 1355647Sgblack@eecs.umich.edu if (reg >= APIC_INTERRUPT_REQUEST(0) && 1365647Sgblack@eecs.umich.edu reg <= APIC_INTERRUPT_REQUEST(15)) { 1375647Sgblack@eecs.umich.edu panic("Local APIC Interrupt Request registers " 1385647Sgblack@eecs.umich.edu "are unimplemented.\n"); 1395647Sgblack@eecs.umich.edu } 1405647Sgblack@eecs.umich.edu switch (reg) { 1415647Sgblack@eecs.umich.edu case APIC_ID: 1425647Sgblack@eecs.umich.edu newVal = val & 0xFF; 1435647Sgblack@eecs.umich.edu break; 1445647Sgblack@eecs.umich.edu case APIC_VERSION: 1455647Sgblack@eecs.umich.edu // The Local APIC Version register is read only. 1465647Sgblack@eecs.umich.edu return; 1475647Sgblack@eecs.umich.edu case APIC_TASK_PRIORITY: 1485647Sgblack@eecs.umich.edu newVal = val & 0xFF; 1495647Sgblack@eecs.umich.edu break; 1505647Sgblack@eecs.umich.edu case APIC_ARBITRATION_PRIORITY: 1515647Sgblack@eecs.umich.edu panic("Local APIC Arbitration Priority register unimplemented.\n"); 1525647Sgblack@eecs.umich.edu break; 1535647Sgblack@eecs.umich.edu case APIC_PROCESSOR_PRIORITY: 1545647Sgblack@eecs.umich.edu panic("Local APIC Processor Priority register unimplemented.\n"); 1555647Sgblack@eecs.umich.edu break; 1565647Sgblack@eecs.umich.edu case APIC_EOI: 1575647Sgblack@eecs.umich.edu panic("Local APIC EOI register unimplemented.\n"); 1585647Sgblack@eecs.umich.edu break; 1595647Sgblack@eecs.umich.edu case APIC_LOGICAL_DESTINATION: 1605647Sgblack@eecs.umich.edu newVal = val & 0xFF000000; 1615647Sgblack@eecs.umich.edu break; 1625647Sgblack@eecs.umich.edu case APIC_DESTINATION_FORMAT: 1635647Sgblack@eecs.umich.edu newVal = val | 0x0FFFFFFF; 1645647Sgblack@eecs.umich.edu break; 1655647Sgblack@eecs.umich.edu case APIC_SPURIOUS_INTERRUPT_VECTOR: 1665647Sgblack@eecs.umich.edu regs[APIC_INTERNAL_STATE] &= ~ULL(1 << 1); 1675647Sgblack@eecs.umich.edu regs[APIC_INTERNAL_STATE] |= val & (1 << 8); 1685647Sgblack@eecs.umich.edu if (val & (1 << 9)) 1695647Sgblack@eecs.umich.edu warn("Focus processor checking not implemented.\n"); 1705647Sgblack@eecs.umich.edu break; 1715647Sgblack@eecs.umich.edu case APIC_ERROR_STATUS: 1725647Sgblack@eecs.umich.edu { 1735647Sgblack@eecs.umich.edu if (regs[APIC_INTERNAL_STATE] & 0x1) { 1745647Sgblack@eecs.umich.edu regs[APIC_INTERNAL_STATE] &= ~ULL(0x1); 1755647Sgblack@eecs.umich.edu newVal = 0; 1765647Sgblack@eecs.umich.edu } else { 1775647Sgblack@eecs.umich.edu regs[APIC_INTERNAL_STATE] |= ULL(0x1); 1785647Sgblack@eecs.umich.edu return; 1795647Sgblack@eecs.umich.edu } 1805647Sgblack@eecs.umich.edu 1815647Sgblack@eecs.umich.edu } 1825647Sgblack@eecs.umich.edu break; 1835647Sgblack@eecs.umich.edu case APIC_INTERRUPT_COMMAND_LOW: 1845647Sgblack@eecs.umich.edu panic("Local APIC Interrupt Command low" 1855647Sgblack@eecs.umich.edu " register unimplemented.\n"); 1865647Sgblack@eecs.umich.edu break; 1875647Sgblack@eecs.umich.edu case APIC_INTERRUPT_COMMAND_HIGH: 1885647Sgblack@eecs.umich.edu panic("Local APIC Interrupt Command high" 1895647Sgblack@eecs.umich.edu " register unimplemented.\n"); 1905647Sgblack@eecs.umich.edu break; 1915647Sgblack@eecs.umich.edu case APIC_LVT_TIMER: 1925647Sgblack@eecs.umich.edu case APIC_LVT_THERMAL_SENSOR: 1935647Sgblack@eecs.umich.edu case APIC_LVT_PERFORMANCE_MONITORING_COUNTERS: 1945647Sgblack@eecs.umich.edu case APIC_LVT_LINT0: 1955647Sgblack@eecs.umich.edu case APIC_LVT_LINT1: 1965647Sgblack@eecs.umich.edu case APIC_LVT_ERROR: 1975647Sgblack@eecs.umich.edu { 1985647Sgblack@eecs.umich.edu uint64_t readOnlyMask = (1 << 12) | (1 << 14); 1995647Sgblack@eecs.umich.edu newVal = (val & ~readOnlyMask) | 2005647Sgblack@eecs.umich.edu (regs[reg] & readOnlyMask); 2015647Sgblack@eecs.umich.edu } 2025647Sgblack@eecs.umich.edu break; 2035647Sgblack@eecs.umich.edu case APIC_INITIAL_COUNT: 2045647Sgblack@eecs.umich.edu newVal = bits(val, 31, 0); 2055647Sgblack@eecs.umich.edu regs[APIC_CURRENT_COUNT] = 2065647Sgblack@eecs.umich.edu tc->getCpuPtr()->curCycle() + 2075647Sgblack@eecs.umich.edu (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION])) * newVal; 2085647Sgblack@eecs.umich.edu //FIXME This should schedule the timer event. 2095647Sgblack@eecs.umich.edu break; 2105647Sgblack@eecs.umich.edu case APIC_CURRENT_COUNT: 2115647Sgblack@eecs.umich.edu //Local APIC Current Count register is read only. 2125647Sgblack@eecs.umich.edu return; 2135647Sgblack@eecs.umich.edu case APIC_DIVIDE_CONFIGURATION: 2145647Sgblack@eecs.umich.edu newVal = val & 0xB; 2155647Sgblack@eecs.umich.edu break; 2165647Sgblack@eecs.umich.edu default: 2175647Sgblack@eecs.umich.edu break; 2185647Sgblack@eecs.umich.edu } 2195647Sgblack@eecs.umich.edu setRegNoEffect(reg, newVal); 2205647Sgblack@eecs.umich.edu return; 2215647Sgblack@eecs.umich.edu} 2225647Sgblack@eecs.umich.edu 2235647Sgblack@eecs.umich.eduX86ISA::Interrupts * 2245647Sgblack@eecs.umich.eduX86LocalApicParams::create() 2255647Sgblack@eecs.umich.edu{ 2265647Sgblack@eecs.umich.edu return new X86ISA::Interrupts(this); 2275647Sgblack@eecs.umich.edu} 228