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