Turn Interrupts objects into SimObjects. Also, move local APIC state into x86's Inter...
authorGabe Black <gblack@eecs.umich.edu>
Sun, 12 Oct 2008 16:09:56 +0000 (09:09 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Sun, 12 Oct 2008 16:09:56 +0000 (09:09 -0700)
28 files changed:
src/arch/alpha/AlphaInterrupts.py [new file with mode: 0644]
src/arch/alpha/SConscript
src/arch/alpha/interrupts.cc [new file with mode: 0644]
src/arch/alpha/interrupts.hh
src/arch/mips/MipsInterrupts.py [new file with mode: 0644]
src/arch/mips/SConscript
src/arch/sparc/SConscript
src/arch/sparc/SparcInterrupts.py [new file with mode: 0644]
src/arch/sparc/interrupts.cc [new file with mode: 0644]
src/arch/sparc/interrupts.hh
src/arch/x86/SConscript
src/arch/x86/X86LocalApic.py [new file with mode: 0644]
src/arch/x86/apicregs.hh [new file with mode: 0644]
src/arch/x86/interrupts.cc [new file with mode: 0644]
src/arch/x86/interrupts.hh
src/arch/x86/miscregfile.cc
src/arch/x86/miscregfile.hh
src/arch/x86/miscregs.hh
src/arch/x86/mmaped_ipr.hh
src/arch/x86/regfile.cc
src/arch/x86/tlb.cc
src/arch/x86/utility.cc
src/cpu/BaseCPU.py
src/cpu/base.cc
src/cpu/base.hh
src/cpu/o3/cpu.cc
src/cpu/ozone/cpu_impl.hh
src/cpu/simple/base.cc

diff --git a/src/arch/alpha/AlphaInterrupts.py b/src/arch/alpha/AlphaInterrupts.py
new file mode 100644 (file)
index 0000000..ecfcf5c
--- /dev/null
@@ -0,0 +1,33 @@
+# Copyright (c) 2008 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Gabe Black
+
+from m5.SimObject import SimObject
+
+class AlphaInterrupts(SimObject):
+    type = 'AlphaInterrupts'
+    cxx_class = 'AlphaISA::Interrupts'
index 04bac399613773f76d13c353df3c081d8a7023b4..069db25510e9b1194ce118d6d03beb11c4acb83f 100644 (file)
@@ -47,9 +47,11 @@ if env['TARGET_ISA'] == 'alpha':
     SimObject('AlphaTLB.py')
 
     if env['FULL_SYSTEM']:
+        SimObject('AlphaInterrupts.py')
         SimObject('AlphaSystem.py')
 
         Source('idle_event.cc')
+        Source('interrupts.cc')
         Source('kernel_stats.cc')
         Source('osfpal.cc')
         Source('stacktrace.cc')
diff --git a/src/arch/alpha/interrupts.cc b/src/arch/alpha/interrupts.cc
new file mode 100644 (file)
index 0000000..4b5dc56
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2008 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include "arch/alpha/interrupts.hh"
+
+AlphaISA::Interrupts *
+AlphaInterruptsParams::create()
+{
+    return new AlphaISA::Interrupts(this);
+}
index 6ae4e4b1d1ff3e210dc51a3b92e749248821692b..e7a451d4d86b1feb2173a80870a07c046d017496 100644 (file)
 #include "arch/alpha/faults.hh"
 #include "arch/alpha/isa_traits.hh"
 #include "base/compiler.hh"
+#include "base/trace.hh"
 #include "cpu/thread_context.hh"
+#include "params/AlphaInterrupts.hh"
+#include "sim/sim_object.hh"
 
 namespace AlphaISA {
 
-class Interrupts
+class Interrupts : public SimObject
 {
   private:
     bool newInfoSet;
@@ -51,7 +54,15 @@ class Interrupts
     uint64_t intstatus;
 
   public:
-    Interrupts()
+    typedef AlphaInterruptsParams Params;
+
+    const Params *
+    params() const
+    {
+        return dynamic_cast<const Params *>(_params);
+    }
+
+    Interrupts(Params * p) : SimObject(p)
     {
         memset(interrupts, 0, sizeof(interrupts));
         intstatus = 0;
diff --git a/src/arch/mips/MipsInterrupts.py b/src/arch/mips/MipsInterrupts.py
new file mode 100644 (file)
index 0000000..06cd542
--- /dev/null
@@ -0,0 +1,33 @@
+# Copyright (c) 2008 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Gabe Black
+
+from m5.SimObject import SimObject
+
+class MipsInterrupts(SimObject):
+    type = 'MipsInterrupts'
+    cxx_class = 'MipsISA::Interrupts'
index 844e7ba156c2f1afc27ecd34275f35fdefefd138..0368e68bcf32edbeae15759a6defd658adcf4efb 100644 (file)
@@ -51,6 +51,7 @@ if env['TARGET_ISA'] == 'mips':
 
     if env['FULL_SYSTEM']:
        SimObject('MipsSystem.py')
+       SimObject('MipsInterrupts.py')
         Source('idle_event.cc')
         Source('mips_core_specific.cc')
         Source('vtophys.cc')
index d4d68a6bd1af7373320d1008e3a7820789fb3bd3..126587835944149431c850e4b052f2defc9b541e 100644 (file)
@@ -52,7 +52,9 @@ if env['TARGET_ISA'] == 'sparc':
 
     if env['FULL_SYSTEM']:
         SimObject('SparcSystem.py')
+        SimObject('SparcInterrupts.py')
 
+        Source('interrupts.cc')
         Source('stacktrace.cc')
         Source('system.cc')
         Source('ua2005.cc')
diff --git a/src/arch/sparc/SparcInterrupts.py b/src/arch/sparc/SparcInterrupts.py
new file mode 100644 (file)
index 0000000..2cc964c
--- /dev/null
@@ -0,0 +1,33 @@
+# Copyright (c) 2008 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Gabe Black
+
+from m5.SimObject import SimObject
+
+class SparcInterrupts(SimObject):
+    type = 'SparcInterrupts'
+    cxx_class = 'SparcISA::Interrupts'
diff --git a/src/arch/sparc/interrupts.cc b/src/arch/sparc/interrupts.cc
new file mode 100644 (file)
index 0000000..96d61e5
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2008 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include "arch/sparc/interrupts.hh"
+    
+SparcISA::Interrupts *
+SparcInterruptsParams::create()
+{
+    return new SparcISA::Interrupts(this);
+}
index 4ad3385fb47fb2f6d06994a0061e3393a85047cf..7d1496d8ec0d0efc8cb7535bf61b1efc314c8c2e 100644 (file)
 #include "arch/sparc/faults.hh"
 #include "arch/sparc/isa_traits.hh"
 #include "cpu/thread_context.hh"
+#include "params/SparcInterrupts.hh"
+#include "sim/sim_object.hh"
 
 namespace SparcISA
 {
 
-class Interrupts
+class Interrupts : public SimObject
 {
 
   private:
@@ -48,7 +50,15 @@ class Interrupts
     uint64_t intStatus;
 
   public:
-    Interrupts()
+    typedef SparcInterruptsParams Params;
+
+    const Params *
+    params() const
+    {
+        return dynamic_cast<const Params *>(_params);
+    }
+
+    Interrupts(Params * p) : SimObject(p)
     {
         clear_all();
     }
index 0d8760fdc381f5718bb3597673ad74a8a1d065a9..e019b77c94fb81cde3537808d7c8de65e38b28b2 100644 (file)
@@ -109,9 +109,11 @@ if env['TARGET_ISA'] == 'x86':
     TraceFlag('X86')
 
     if env['FULL_SYSTEM']:
+        SimObject('X86LocalApic.py')
         SimObject('X86System.py')
 
         # Full-system sources
+        Source('interrupts.cc')
         Source('linux/system.cc')
         Source('pagetable_walker.cc')
         Source('system.cc')
diff --git a/src/arch/x86/X86LocalApic.py b/src/arch/x86/X86LocalApic.py
new file mode 100644 (file)
index 0000000..94e32ae
--- /dev/null
@@ -0,0 +1,35 @@
+# Copyright (c) 2008 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Gabe Black
+
+from m5.params import *
+from Device import BasicPioDevice
+
+class X86LocalApic(BasicPioDevice):
+    type = 'X86LocalApic'
+    cxx_class = 'X86ISA::Interrupts'
+    pio_latency = Param.Latency('1ns', 'Programmed IO latency in simticks')
diff --git a/src/arch/x86/apicregs.hh b/src/arch/x86/apicregs.hh
new file mode 100644 (file)
index 0000000..464c3af
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2008 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#ifndef __ARCH_X86_APICREGS_HH__
+#define __ARCH_X86_APICREGS_HH__
+
+namespace X86ISA
+{
+    enum ApicRegIndex
+    {
+        APIC_ID,
+        APIC_VERSION,
+        APIC_TASK_PRIORITY,
+        APIC_ARBITRATION_PRIORITY,
+        APIC_PROCESSOR_PRIORITY,
+        APIC_EOI,
+        APIC_LOGICAL_DESTINATION,
+        APIC_DESTINATION_FORMAT,
+        APIC_SPURIOUS_INTERRUPT_VECTOR,
+
+        APIC_IN_SERVICE_BASE,
+
+        APIC_TRIGGER_MODE_BASE = APIC_IN_SERVICE_BASE + 16,
+
+        APIC_INTERRUPT_REQUEST_BASE = APIC_TRIGGER_MODE_BASE + 16,
+
+        APIC_ERROR_STATUS = APIC_INTERRUPT_REQUEST_BASE + 16,
+        APIC_INTERRUPT_COMMAND_LOW,
+        APIC_INTERRUPT_COMMAND_HIGH,
+        APIC_LVT_TIMER,
+        APIC_LVT_THERMAL_SENSOR,
+        APIC_LVT_PERFORMANCE_MONITORING_COUNTERS,
+        APIC_LVT_LINT0,
+        APIC_LVT_LINT1,
+        APIC_LVT_ERROR,
+        APIC_INITIAL_COUNT,
+        APIC_CURRENT_COUNT,
+        APIC_DIVIDE_CONFIGURATION,
+
+        APIC_INTERNAL_STATE,
+
+        NUM_APIC_REGS
+    };
+
+    static inline ApicRegIndex
+    APIC_IN_SERVICE(int index)
+    {
+        return (ApicRegIndex)(APIC_IN_SERVICE_BASE + index);
+    }
+
+    static inline ApicRegIndex
+    APIC_TRIGGER_MODE(int index)
+    {
+        return (ApicRegIndex)(APIC_TRIGGER_MODE_BASE + index);
+    }
+
+    static inline ApicRegIndex
+    APIC_INTERRUPT_REQUEST(int index)
+    {
+        return (ApicRegIndex)(APIC_INTERRUPT_REQUEST_BASE + index);
+    }
+}
+
+#endif
diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc
new file mode 100644 (file)
index 0000000..73536f2
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2008 The Hewlett-Packard Development Company
+ * All rights reserved.
+ *
+ * Redistribution and use of this software in source and binary forms,
+ * with or without modification, are permitted provided that the
+ * following conditions are met:
+ *
+ * The software must be used only for Non-Commercial Use which means any
+ * use which is NOT directed to receiving any direct monetary
+ * compensation for, or commercial advantage from such use.  Illustrative
+ * examples of non-commercial use are academic research, personal study,
+ * teaching, education and corporate research & development.
+ * Illustrative examples of commercial use are distributing products for
+ * commercial advantage and providing services using the software for
+ * commercial advantage.
+ *
+ * If you wish to use this software or functionality therein that may be
+ * covered by patents for commercial use, please contact:
+ *     Director of Intellectual Property Licensing
+ *     Office of Strategy and Technology
+ *     Hewlett-Packard Company
+ *     1501 Page Mill Road
+ *     Palo Alto, California  94304
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.  Redistributions
+ * in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.  Neither the name of
+ * the COPYRIGHT HOLDER(s), HEWLETT-PACKARD COMPANY, nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.  No right of
+ * sublicense is granted herewith.  Derivatives of the software and
+ * output created using the software may be prepared, but only for
+ * Non-Commercial Uses.  Derivatives of the software may be shared with
+ * others provided: (i) the others agree to abide by the list of
+ * conditions herein which includes the Non-Commercial Use restrictions;
+ * and (ii) such Derivatives of the software include the above copyright
+ * notice to acknowledge the contribution from this software where
+ * applicable, this list of conditions and the disclaimer below.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Gabe Black
+ */
+
+#include "arch/x86/interrupts.hh"
+#include "cpu/base.hh"
+
+int divideFromConf(uint32_t conf)
+{
+    // This figures out what division we want from the division configuration
+    // register in the local APIC. The encoding is a little odd but it can
+    // be deciphered fairly easily.
+    int shift = ((conf & 0x8) >> 1) | (conf & 0x3);
+    shift = (shift + 1) % 8;
+    return 1 << shift;
+}
+
+uint32_t
+X86ISA::Interrupts::readRegNoEffect(ApicRegIndex reg)
+{
+    return regs[reg];
+}
+
+uint32_t
+X86ISA::Interrupts::readReg(ApicRegIndex reg, ThreadContext * tc)
+{
+    if (reg >= APIC_TRIGGER_MODE(0) &&
+            reg <= APIC_TRIGGER_MODE(15)) {
+        panic("Local APIC Trigger Mode registers are unimplemented.\n");
+    }
+    switch (reg) {
+      case APIC_ARBITRATION_PRIORITY:
+        panic("Local APIC Arbitration Priority register unimplemented.\n");
+        break;
+      case APIC_PROCESSOR_PRIORITY:
+        panic("Local APIC Processor Priority register unimplemented.\n");
+        break;
+      case APIC_EOI:
+        panic("Local APIC EOI register unimplemented.\n");
+        break;
+      case APIC_ERROR_STATUS:
+        regs[APIC_INTERNAL_STATE] &= ~ULL(0x1);
+        break;
+      case APIC_INTERRUPT_COMMAND_LOW:
+        panic("Local APIC Interrupt Command low"
+                " register unimplemented.\n");
+        break;
+      case APIC_INTERRUPT_COMMAND_HIGH:
+        panic("Local APIC Interrupt Command high"
+                " register unimplemented.\n");
+        break;
+      case APIC_CURRENT_COUNT:
+        {
+            uint32_t val = regs[reg] - tc->getCpuPtr()->curCycle();
+            val /= (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]));
+            return val;
+        }
+      default:
+        break;
+    }
+    return readRegNoEffect(reg);
+}
+
+void
+X86ISA::Interrupts::setRegNoEffect(ApicRegIndex reg, uint32_t val)
+{
+    regs[reg] = val;
+}
+
+void
+X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val, ThreadContext *tc)
+{
+    uint32_t newVal = val;
+    if (reg >= APIC_IN_SERVICE(0) &&
+            reg <= APIC_IN_SERVICE(15)) {
+        panic("Local APIC In-Service registers are unimplemented.\n");
+    }
+    if (reg >= APIC_TRIGGER_MODE(0) &&
+            reg <= APIC_TRIGGER_MODE(15)) {
+        panic("Local APIC Trigger Mode registers are unimplemented.\n");
+    }
+    if (reg >= APIC_INTERRUPT_REQUEST(0) &&
+            reg <= APIC_INTERRUPT_REQUEST(15)) {
+        panic("Local APIC Interrupt Request registers "
+                "are unimplemented.\n");
+    }
+    switch (reg) {
+      case APIC_ID:
+        newVal = val & 0xFF;
+        break;
+      case APIC_VERSION:
+        // The Local APIC Version register is read only.
+        return;
+      case APIC_TASK_PRIORITY:
+        newVal = val & 0xFF;
+        break;
+      case APIC_ARBITRATION_PRIORITY:
+        panic("Local APIC Arbitration Priority register unimplemented.\n");
+        break;
+      case APIC_PROCESSOR_PRIORITY:
+        panic("Local APIC Processor Priority register unimplemented.\n");
+        break;
+      case APIC_EOI:
+        panic("Local APIC EOI register unimplemented.\n");
+        break;
+      case APIC_LOGICAL_DESTINATION:
+        newVal = val & 0xFF000000;
+        break;
+      case APIC_DESTINATION_FORMAT:
+        newVal = val | 0x0FFFFFFF;
+        break;
+      case APIC_SPURIOUS_INTERRUPT_VECTOR:
+        regs[APIC_INTERNAL_STATE] &= ~ULL(1 << 1);
+        regs[APIC_INTERNAL_STATE] |= val & (1 << 8);
+        if (val & (1 << 9))
+            warn("Focus processor checking not implemented.\n");
+        break;
+      case APIC_ERROR_STATUS:
+        {
+            if (regs[APIC_INTERNAL_STATE] & 0x1) {
+                regs[APIC_INTERNAL_STATE] &= ~ULL(0x1);
+                newVal = 0;
+            } else {
+                regs[APIC_INTERNAL_STATE] |= ULL(0x1);
+                return;
+            }
+
+        }
+        break;
+      case APIC_INTERRUPT_COMMAND_LOW:
+        panic("Local APIC Interrupt Command low"
+                " register unimplemented.\n");
+        break;
+      case APIC_INTERRUPT_COMMAND_HIGH:
+        panic("Local APIC Interrupt Command high"
+                " register unimplemented.\n");
+        break;
+      case APIC_LVT_TIMER:
+      case APIC_LVT_THERMAL_SENSOR:
+      case APIC_LVT_PERFORMANCE_MONITORING_COUNTERS:
+      case APIC_LVT_LINT0:
+      case APIC_LVT_LINT1:
+      case APIC_LVT_ERROR:
+        {
+            uint64_t readOnlyMask = (1 << 12) | (1 << 14);
+            newVal = (val & ~readOnlyMask) |
+                     (regs[reg] & readOnlyMask);
+        }
+        break;
+      case APIC_INITIAL_COUNT:
+        newVal = bits(val, 31, 0);
+        regs[APIC_CURRENT_COUNT] =
+            tc->getCpuPtr()->curCycle() +
+            (16 * divideFromConf(regs[APIC_DIVIDE_CONFIGURATION])) * newVal;
+        //FIXME This should schedule the timer event.
+        break;
+      case APIC_CURRENT_COUNT:
+        //Local APIC Current Count register is read only.
+        return;
+      case APIC_DIVIDE_CONFIGURATION:
+        newVal = val & 0xB;
+        break;
+      default:
+        break;
+    }
+    setRegNoEffect(reg, newVal);
+    return;
+}
+
+X86ISA::Interrupts *
+X86LocalApicParams::create()
+{
+    return new X86ISA::Interrupts(this);
+}
index 43675294e4d7da076112f40f60cf28806cfb2a8c..68bb2e07d49e7bcbd3e9d5da7c7aca569bf4bc15 100644 (file)
 #ifndef __ARCH_X86_INTERRUPTS_HH__
 #define __ARCH_X86_INTERRUPTS_HH__
 
+#include "arch/x86/apicregs.hh"
 #include "arch/x86/faults.hh"
 #include "cpu/thread_context.hh"
+#include "params/X86LocalApic.hh"
+#include "sim/eventq.hh"
+#include "sim/sim_object.hh"
+
+class ThreadContext;
 
 namespace X86ISA
 {
 
-class Interrupts
+class Interrupts : public SimObject
 {
+  protected:
+    uint32_t regs[NUM_APIC_REGS];
+
+    class ApicTimerEvent : public Event
+    {
+      public:
+        ApicTimerEvent() : Event()
+        {}
+
+        void process()
+        {
+            warn("Local APIC timer event doesn't do anything!\n");
+        }
+    };
+
+    ApicTimerEvent apicTimerEvent;
+
   public:
-    Interrupts()
+    typedef X86LocalApicParams Params;
+
+    const Params *
+    params() const
+    {
+        return dynamic_cast<const Params *>(_params);
+    }
+
+    uint32_t readRegNoEffect(ApicRegIndex reg);
+    uint32_t readReg(ApicRegIndex miscReg, ThreadContext *tc);
+
+    void setRegNoEffect(ApicRegIndex reg, uint32_t val);
+    void setReg(ApicRegIndex reg, uint32_t val, ThreadContext *tc);
+
+    Interrupts(Params * p) : SimObject(p)
     {
+        //Set the local apic DFR to the flat model.
+        regs[APIC_DESTINATION_FORMAT] = (uint32_t)(-1);
+        memset(regs, 0, sizeof(regs));
         clear_all();
     }
 
index f40b1adf523afdef475fc59b96a2ccb57ee11932..aba49861628fdafaa7d2c28516a87f0a7970d667 100644 (file)
@@ -106,21 +106,9 @@ void MiscRegFile::clear()
 {
     // Blank everything. 0 might not be an appropriate value for some things.
     memset(regVal, 0, NumMiscRegs * sizeof(MiscReg));
-    //Set the local apic DFR to the flat model.
-    regVal[MISCREG_APIC_DESTINATION_FORMAT] = (MiscReg)(-1);
 }
 
-int divideFromConf(MiscReg conf)
-{
-    // This figures out what division we want from the division configuration
-    // register in the local APIC. The encoding is a little odd but it can
-    // be deciphered fairly easily.
-    int shift = ((conf & 0x8) >> 1) | (conf & 0x3);
-    shift = (shift + 1) % 8;
-    return 1 << shift;
-};
-
-MiscReg MiscRegFile::readRegNoEffect(int miscReg)
+MiscReg MiscRegFile::readRegNoEffect(MiscRegIndex miscReg)
 {
     // Make sure we're not dealing with an illegal control register.
     // Instructions should filter out these indexes, and nothing else should
@@ -131,52 +119,30 @@ MiscReg MiscRegFile::readRegNoEffect(int miscReg)
             !(miscReg > MISCREG_CR8 &&
               miscReg <= MISCREG_CR15));
 
+    if (isApicReg(miscReg)) {
+        panic("Can't readRegNoEffect from the local APIC.\n");
+    }
     return regVal[miscReg];
 }
 
-MiscReg MiscRegFile::readReg(int miscReg, ThreadContext * tc)
+MiscReg MiscRegFile::readReg(MiscRegIndex miscReg, ThreadContext * tc)
 {
-    if (miscReg >= MISCREG_APIC_START && miscReg <= MISCREG_APIC_END) {
-        if (miscReg >= MISCREG_APIC_TRIGGER_MODE(0) &&
-                miscReg <= MISCREG_APIC_TRIGGER_MODE(15)) {
-            panic("Local APIC Trigger Mode registers are unimplemented.\n");
-        }
-        switch (miscReg) {
-          case MISCREG_APIC_ARBITRATION_PRIORITY:
-            panic("Local APIC Arbitration Priority register unimplemented.\n");
-            break;
-          case MISCREG_APIC_PROCESSOR_PRIORITY:
-            panic("Local APIC Processor Priority register unimplemented.\n");
-            break;
-          case MISCREG_APIC_EOI:
-            panic("Local APIC EOI register unimplemented.\n");
-            break;
-          case MISCREG_APIC_ERROR_STATUS:
-            regVal[MISCREG_APIC_INTERNAL_STATE] &= ~ULL(0x1);
-            break;
-          case MISCREG_APIC_INTERRUPT_COMMAND_LOW:
-            panic("Local APIC Interrupt Command low"
-                    " register unimplemented.\n");
-            break;
-          case MISCREG_APIC_INTERRUPT_COMMAND_HIGH:
-            panic("Local APIC Interrupt Command high"
-                    " register unimplemented.\n");
-            break;
-          case MISCREG_APIC_CURRENT_COUNT:
-            return (regVal[miscReg] - tc->getCpuPtr()->curCycle()) /
-                (16 * divideFromConf(
-                    regVal[MISCREG_APIC_DIVIDE_CONFIGURATION]));
-            break;
-        }
+#if FULL_SYSTEM
+    if (isApicReg(miscReg)) {
+        Interrupts * interrupts = dynamic_cast<Interrupts *>(
+                tc->getCpuPtr()->getInterruptController());
+        assert(interrupts);
+        return interrupts->readReg(
+                (ApicRegIndex)(miscReg - MISCREG_APIC_START), tc);
     }
-    switch (miscReg) {
-      case MISCREG_TSC:
+#endif
+    if (miscReg == MISCREG_TSC) {
         return regVal[MISCREG_TSC] + tc->getCpuPtr()->curCycle();
     }
     return readRegNoEffect(miscReg);
 }
 
-void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val)
+void MiscRegFile::setRegNoEffect(MiscRegIndex miscReg, const MiscReg &val)
 {
     // Make sure we're not dealing with an illegal control register.
     // Instructions should filter out these indexes, and nothing else should
@@ -186,108 +152,26 @@ void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val)
               miscReg < MISCREG_CR8) &&
             !(miscReg > MISCREG_CR8 &&
               miscReg <= MISCREG_CR15));
+    if (isApicReg(miscReg)) {
+        panic("Can't setRegNoEffect from the local APIC.\n");
+    }
     regVal[miscReg] = val;
 }
 
-void MiscRegFile::setReg(int miscReg,
+void MiscRegFile::setReg(MiscRegIndex miscReg,
         const MiscReg &val, ThreadContext * tc)
 {
     MiscReg newVal = val;
-    if (miscReg >= MISCREG_APIC_START && miscReg <= MISCREG_APIC_END) {
-        if (miscReg >= MISCREG_APIC_IN_SERVICE(0) &&
-                miscReg <= MISCREG_APIC_IN_SERVICE(15)) {
-            panic("Local APIC In-Service registers are unimplemented.\n");
-        }
-        if (miscReg >= MISCREG_APIC_TRIGGER_MODE(0) &&
-                miscReg <= MISCREG_APIC_TRIGGER_MODE(15)) {
-            panic("Local APIC Trigger Mode registers are unimplemented.\n");
-        }
-        if (miscReg >= MISCREG_APIC_INTERRUPT_REQUEST(0) &&
-                miscReg <= MISCREG_APIC_INTERRUPT_REQUEST(15)) {
-            panic("Local APIC Interrupt Request registers "
-                    "are unimplemented.\n");
-        }
-        switch (miscReg) {
-          case MISCREG_APIC_ID:
-            newVal = val & 0xFF;
-            break;
-          case MISCREG_APIC_VERSION:
-            // The Local APIC Version register is read only.
-            return;
-          case MISCREG_APIC_TASK_PRIORITY:
-            newVal = val & 0xFF;
-            break;
-          case MISCREG_APIC_ARBITRATION_PRIORITY:
-            panic("Local APIC Arbitration Priority register unimplemented.\n");
-            break;
-          case MISCREG_APIC_PROCESSOR_PRIORITY:
-            panic("Local APIC Processor Priority register unimplemented.\n");
-            break;
-          case MISCREG_APIC_EOI:
-            panic("Local APIC EOI register unimplemented.\n");
-            break;
-          case MISCREG_APIC_LOGICAL_DESTINATION:
-            newVal = val & 0xFF000000;
-            break;
-          case MISCREG_APIC_DESTINATION_FORMAT:
-            newVal = val | 0x0FFFFFFF;
-            break;
-          case MISCREG_APIC_SPURIOUS_INTERRUPT_VECTOR:
-            regVal[MISCREG_APIC_INTERNAL_STATE] &= ~ULL(1 << 1);
-            regVal[MISCREG_APIC_INTERNAL_STATE] |= val & (1 << 8);
-            if (val & (1 << 9))
-                warn("Focus processor checking not implemented.\n");
-            break;
-          case MISCREG_APIC_ERROR_STATUS:
-            {
-                if (regVal[MISCREG_APIC_INTERNAL_STATE] & 0x1) {
-                    regVal[MISCREG_APIC_INTERNAL_STATE] &= ~ULL(0x1);
-                    newVal = 0;
-                } else {
-                    regVal[MISCREG_APIC_INTERNAL_STATE] |= ULL(0x1);
-                    return;
-                }
-
-            }
-            break;
-          case MISCREG_APIC_INTERRUPT_COMMAND_LOW:
-            panic("Local APIC Interrupt Command low"
-                    " register unimplemented.\n");
-            break;
-          case MISCREG_APIC_INTERRUPT_COMMAND_HIGH:
-            panic("Local APIC Interrupt Command high"
-                    " register unimplemented.\n");
-            break;
-          case MISCREG_APIC_LVT_TIMER:
-          case MISCREG_APIC_LVT_THERMAL_SENSOR:
-          case MISCREG_APIC_LVT_PERFORMANCE_MONITORING_COUNTERS:
-          case MISCREG_APIC_LVT_LINT0:
-          case MISCREG_APIC_LVT_LINT1:
-          case MISCREG_APIC_LVT_ERROR:
-            {
-                uint64_t readOnlyMask = (1 << 12) | (1 << 14);
-                newVal = (val & ~readOnlyMask) |
-                         (regVal[miscReg] & readOnlyMask);
-            }
-            break;
-          case MISCREG_APIC_INITIAL_COUNT:
-            newVal = bits(val, 31, 0);
-            regVal[MISCREG_APIC_CURRENT_COUNT] =
-                tc->getCpuPtr()->curCycle() +
-                (16 * divideFromConf(
-                    regVal[MISCREG_APIC_DIVIDE_CONFIGURATION])) * newVal;
-            //FIXME This should schedule the timer event.
-            break;
-          case MISCREG_APIC_CURRENT_COUNT:
-            //Local APIC Current Count register is read only.
-            return;
-          case MISCREG_APIC_DIVIDE_CONFIGURATION:
-            newVal = val & 0xB;
-            break;
-        }
-        setRegNoEffect(miscReg, newVal);
+#if FULL_SYSTEM
+    if (isApicReg(miscReg)) {
+        Interrupts * interrupts = dynamic_cast<Interrupts *>(
+                tc->getCpuPtr()->getInterruptController());
+        assert(interrupts);
+        interrupts->setReg(
+                ApicRegIndex(miscReg - MISCREG_APIC_START), val, tc);
         return;
     }
+#endif
     switch(miscReg)
     {
       case MISCREG_CR0:
@@ -408,6 +292,8 @@ void MiscRegFile::setReg(int miscReg,
       case MISCREG_TSC:
         regVal[MISCREG_TSC] = val - tc->getCpuPtr()->curCycle();
         return;
+      default:
+        break;
     }
     setRegNoEffect(miscReg, newVal);
 }
index 21caf3aa1938ff625a2f960e70b91e83d734f25c..e59b8d3b15927f06601dfeeb0a7c5ea241b63a1b 100644 (file)
@@ -91,7 +91,6 @@
 #include "arch/x86/faults.hh"
 #include "arch/x86/miscregs.hh"
 #include "arch/x86/types.hh"
-#include "sim/eventq.hh"
 #include "sim/host.hh"
 
 #include <string>
@@ -112,18 +111,6 @@ namespace X86ISA
       protected:
         MiscReg regVal[NumMiscRegs];
 
-        class ApicTimerEvent : public Event
-        {
-          public:
-            void
-            process()
-            {
-                warn("Local APIC timer event doesn't do anything!\n");
-            }
-        };
-
-        ApicTimerEvent apicTimerEvent;
-
       public:
         void clear();
 
@@ -132,13 +119,13 @@ namespace X86ISA
             clear();
         }
 
-        MiscReg readRegNoEffect(int miscReg);
+        MiscReg readRegNoEffect(MiscRegIndex miscReg);
 
-        MiscReg readReg(int miscReg, ThreadContext *tc);
+        MiscReg readReg(MiscRegIndex miscReg, ThreadContext *tc);
 
-        void setRegNoEffect(int miscReg, const MiscReg &val);
+        void setRegNoEffect(MiscRegIndex miscReg, const MiscReg &val);
 
-        void setReg(int miscReg,
+        void setReg(MiscRegIndex miscReg,
                 const MiscReg &val, ThreadContext *tc);
 
         void serialize(std::ostream & os);
index 5a6ee752d233178f624cd621e30f24a96185a166..dbf08ec5d52dd82fc3fb469921c4090861633b29 100644 (file)
@@ -58,6 +58,7 @@
 #ifndef __ARCH_X86_MISCREGS_HH__
 #define __ARCH_X86_MISCREGS_HH__
 
+#include "arch/x86/apicregs.hh"
 #include "arch/x86/segmentregs.hh"
 #include "arch/x86/x86_traits.hh"
 #include "base/bitunion.hh"
@@ -368,39 +369,9 @@ namespace X86ISA
 
         MISCREG_APIC_BASE,
 
+        // Space for the APIC registers
         MISCREG_APIC_START,
-        MISCREG_APIC_ID = MISCREG_APIC_START,
-        MISCREG_APIC_VERSION,
-        MISCREG_APIC_TASK_PRIORITY,
-        MISCREG_APIC_ARBITRATION_PRIORITY,
-        MISCREG_APIC_PROCESSOR_PRIORITY,
-        MISCREG_APIC_EOI,
-        MISCREG_APIC_LOGICAL_DESTINATION,
-        MISCREG_APIC_DESTINATION_FORMAT,
-        MISCREG_APIC_SPURIOUS_INTERRUPT_VECTOR,
-
-        MISCREG_APIC_IN_SERVICE_BASE,
-
-        MISCREG_APIC_TRIGGER_MODE_BASE = MISCREG_APIC_IN_SERVICE_BASE + 16,
-
-        MISCREG_APIC_INTERRUPT_REQUEST_BASE =
-            MISCREG_APIC_TRIGGER_MODE_BASE + 16,
-
-        MISCREG_APIC_ERROR_STATUS = MISCREG_APIC_INTERRUPT_REQUEST_BASE + 16,
-        MISCREG_APIC_INTERRUPT_COMMAND_LOW,
-        MISCREG_APIC_INTERRUPT_COMMAND_HIGH,
-        MISCREG_APIC_LVT_TIMER,
-        MISCREG_APIC_LVT_THERMAL_SENSOR,
-        MISCREG_APIC_LVT_PERFORMANCE_MONITORING_COUNTERS,
-        MISCREG_APIC_LVT_LINT0,
-        MISCREG_APIC_LVT_LINT1,
-        MISCREG_APIC_LVT_ERROR,
-        MISCREG_APIC_INITIAL_COUNT,
-        MISCREG_APIC_CURRENT_COUNT,
-        MISCREG_APIC_DIVIDE_CONFIGURATION,
-        MISCREG_APIC_END = MISCREG_APIC_DIVIDE_CONFIGURATION,
-
-        MISCREG_APIC_INTERNAL_STATE,
+        MISCREG_APIC_END = MISCREG_APIC_START + NUM_APIC_REGS - 1,
 
         // "Fake" MSRs for internally implemented devices
         MISCREG_PCI_CONFIG_ADDRESS,
@@ -408,6 +379,12 @@ namespace X86ISA
         NUM_MISCREGS
     };
 
+    static inline bool
+    isApicReg(MiscRegIndex index)
+    {
+        return index >= MISCREG_APIC_START && index <= MISCREG_APIC_END;
+    }
+
     static inline MiscRegIndex
     MISCREG_CR(int index)
     {
@@ -510,24 +487,6 @@ namespace X86ISA
         return (MiscRegIndex)(MISCREG_SEG_ATTR_BASE + index);
     }
 
-    static inline MiscRegIndex
-    MISCREG_APIC_IN_SERVICE(int index)
-    {
-        return (MiscRegIndex)(MISCREG_APIC_IN_SERVICE_BASE + index);
-    }
-
-    static inline MiscRegIndex
-    MISCREG_APIC_TRIGGER_MODE(int index)
-    {
-        return (MiscRegIndex)(MISCREG_APIC_TRIGGER_MODE_BASE + index);
-    }
-
-    static inline MiscRegIndex
-    MISCREG_APIC_INTERRUPT_REQUEST(int index)
-    {
-        return (MiscRegIndex)(MISCREG_APIC_INTERRUPT_REQUEST_BASE + index);
-    }
-
     /**
      * A type to describe the condition code bits of the RFLAGS register,
      * plus two flags, EZF and ECF, which are only visible to microcode.
index cf3eba5e9960a27c18a8882a9ad90c11a0b4631d..67a0b239e37db2c3f44029edef8fe203fe1c4558 100644 (file)
@@ -96,7 +96,12 @@ namespace X86ISA
 #else
         Addr offset = pkt->getAddr() & mask(3);
         MiscRegIndex index = (MiscRegIndex)(pkt->getAddr() / sizeof(MiscReg));
-        MiscReg data = htog(xc->readMiscRegNoEffect(index));
+        MiscReg data;
+        if (isApicReg(index)) {
+            data = htog(xc->readMiscReg(index));
+        } else {
+            data = htog(xc->readMiscRegNoEffect(index));
+        }
         // Make sure we don't trot off the end of data.
         assert(offset + pkt->getSize() <= sizeof(MiscReg));
         pkt->writeData(((uint8_t *)&data) + offset);
index c8ec2a95776a5e286ff6ffc112c78b0a2cc6edd6..78fde7474f1a943c056a3a7409a059f06ed6f1c6 100644 (file)
@@ -135,23 +135,23 @@ void RegFile::clear()
 
 MiscReg RegFile::readMiscRegNoEffect(int miscReg)
 {
-    return miscRegFile.readRegNoEffect(miscReg);
+    return miscRegFile.readRegNoEffect((MiscRegIndex)miscReg);
 }
 
 MiscReg RegFile::readMiscReg(int miscReg, ThreadContext *tc)
 {
-    return miscRegFile.readReg(miscReg, tc);
+    return miscRegFile.readReg((MiscRegIndex)miscReg, tc);
 }
 
 void RegFile::setMiscRegNoEffect(int miscReg, const MiscReg &val)
 {
-    miscRegFile.setRegNoEffect(miscReg, val);
+    miscRegFile.setRegNoEffect((MiscRegIndex)miscReg, val);
 }
 
 void RegFile::setMiscReg(int miscReg, const MiscReg &val,
         ThreadContext * tc)
 {
-    miscRegFile.setReg(miscReg, val, tc);
+    miscRegFile.setReg((MiscRegIndex)miscReg, val, tc);
 }
 
 FloatReg RegFile::readFloatReg(int floatReg, int width)
index 692d6d02212c990b4c00220a7f73fa1e073ff616..616f026cf4ad9ed9821df640e31a3571cd054e0e 100644 (file)
@@ -663,31 +663,31 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
         switch (paddr - baseAddr)
         {
           case 0x20:
-            regNum = MISCREG_APIC_ID;
+            regNum = APIC_ID;
             break;
           case 0x30:
-            regNum = MISCREG_APIC_VERSION;
+            regNum = APIC_VERSION;
             break;
           case 0x80:
-            regNum = MISCREG_APIC_TASK_PRIORITY;
+            regNum = APIC_TASK_PRIORITY;
             break;
           case 0x90:
-            regNum = MISCREG_APIC_ARBITRATION_PRIORITY;
+            regNum = APIC_ARBITRATION_PRIORITY;
             break;
           case 0xA0:
-            regNum = MISCREG_APIC_PROCESSOR_PRIORITY;
+            regNum = APIC_PROCESSOR_PRIORITY;
             break;
           case 0xB0:
-            regNum = MISCREG_APIC_EOI;
+            regNum = APIC_EOI;
             break;
           case 0xD0:
-            regNum = MISCREG_APIC_LOGICAL_DESTINATION;
+            regNum = APIC_LOGICAL_DESTINATION;
             break;
           case 0xE0:
-            regNum = MISCREG_APIC_DESTINATION_FORMAT;
+            regNum = APIC_DESTINATION_FORMAT;
             break;
           case 0xF0:
-            regNum = MISCREG_APIC_SPURIOUS_INTERRUPT_VECTOR;
+            regNum = APIC_SPURIOUS_INTERRUPT_VECTOR;
             break;
           case 0x100:
           case 0x108:
@@ -705,8 +705,7 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
           case 0x168:
           case 0x170:
           case 0x178:
-            regNum = MISCREG_APIC_IN_SERVICE(
-                    (paddr - baseAddr - 0x100) / 0x8);
+            regNum = APIC_IN_SERVICE((paddr - baseAddr - 0x100) / 0x8);
             break;
           case 0x180:
           case 0x188:
@@ -724,8 +723,7 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
           case 0x1E8:
           case 0x1F0:
           case 0x1F8:
-            regNum = MISCREG_APIC_TRIGGER_MODE(
-                    (paddr - baseAddr - 0x180) / 0x8);
+            regNum = APIC_TRIGGER_MODE((paddr - baseAddr - 0x180) / 0x8);
             break;
           case 0x200:
           case 0x208:
@@ -743,50 +741,50 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
           case 0x268:
           case 0x270:
           case 0x278:
-            regNum = MISCREG_APIC_INTERRUPT_REQUEST(
-                    (paddr - baseAddr - 0x200) / 0x8);
+            regNum = APIC_INTERRUPT_REQUEST((paddr - baseAddr - 0x200) / 0x8);
             break;
           case 0x280:
-            regNum = MISCREG_APIC_ERROR_STATUS;
+            regNum = APIC_ERROR_STATUS;
             break;
           case 0x300:
-            regNum = MISCREG_APIC_INTERRUPT_COMMAND_LOW;
+            regNum = APIC_INTERRUPT_COMMAND_LOW;
             break;
           case 0x310:
-            regNum = MISCREG_APIC_INTERRUPT_COMMAND_HIGH;
+            regNum = APIC_INTERRUPT_COMMAND_HIGH;
             break;
           case 0x320:
-            regNum = MISCREG_APIC_LVT_TIMER;
+            regNum = APIC_LVT_TIMER;
             break;
           case 0x330:
-            regNum = MISCREG_APIC_LVT_THERMAL_SENSOR;
+            regNum = APIC_LVT_THERMAL_SENSOR;
             break;
           case 0x340:
-            regNum = MISCREG_APIC_LVT_PERFORMANCE_MONITORING_COUNTERS;
+            regNum = APIC_LVT_PERFORMANCE_MONITORING_COUNTERS;
             break;
           case 0x350:
-            regNum = MISCREG_APIC_LVT_LINT0;
+            regNum = APIC_LVT_LINT0;
             break;
           case 0x360:
-            regNum = MISCREG_APIC_LVT_LINT1;
+            regNum = APIC_LVT_LINT1;
             break;
           case 0x370:
-            regNum = MISCREG_APIC_LVT_ERROR;
+            regNum = APIC_LVT_ERROR;
             break;
           case 0x380:
-            regNum = MISCREG_APIC_INITIAL_COUNT;
+            regNum = APIC_INITIAL_COUNT;
             break;
           case 0x390:
-            regNum = MISCREG_APIC_CURRENT_COUNT;
+            regNum = APIC_CURRENT_COUNT;
             break;
           case 0x3E0:
-            regNum = MISCREG_APIC_DIVIDE_CONFIGURATION;
+            regNum = APIC_DIVIDE_CONFIGURATION;
             break;
           default:
             // A reserved register field.
             return new GeneralProtection(0);
             break;
         }
+        regNum += MISCREG_APIC_START;
         req->setPaddr(regNum * sizeof(MiscReg) + offset);
     }
 #endif
index 5fe5bf8c37983b72f742a88349b9695f942a7962..852d72a2e9b16f8d7b9c7ad59c97829c8de1537d 100644 (file)
  * Authors: Gabe Black
  */
 
+#include "config/full_system.hh"
+
+#if FULL_SYSTEM
+#include "arch/x86/interrupts.hh"
+#endif
 #include "arch/x86/intregs.hh"
 #include "arch/x86/miscregs.hh"
 #include "arch/x86/segmentregs.hh"
 #include "arch/x86/utility.hh"
 #include "arch/x86/x86_traits.hh"
+#include "cpu/base.hh"
 #include "sim/system.hh"
 
 namespace X86ISA {
@@ -254,9 +260,13 @@ void initCPU(ThreadContext *tc, int cpuId)
     lApicBase.bsp = (cpuId == 0);
     tc->setMiscReg(MISCREG_APIC_BASE, lApicBase);
 
-    tc->setMiscRegNoEffect(MISCREG_APIC_ID, cpuId << 24);
+    Interrupts * interrupts = dynamic_cast<Interrupts *>(
+            tc->getCpuPtr()->getInterruptController());
+    assert(interrupts);
+
+    interrupts->setRegNoEffect(APIC_ID, cpuId << 24);
 
-    tc->setMiscRegNoEffect(MISCREG_APIC_VERSION, (5 << 16) | 0x14);
+    interrupts->setRegNoEffect(APIC_VERSION, (5 << 16) | 0x14);
 
     // TODO Set the SMRAM base address (SMBASE) to 0x00030000
 
index 1e3f0dbbc2df16c1f4fc4fd9cf79b4eeb3215037..c2385f6d0bbe3ed920f3d2a0a3951b002a985ad2 100644 (file)
@@ -39,14 +39,24 @@ default_tracer = ExeTracer()
 
 if build_env['TARGET_ISA'] == 'alpha':
     from AlphaTLB import AlphaDTB, AlphaITB
+    if build_env['FULL_SYSTEM']:
+        from AlphaInterrupts import AlphaInterrupts
 elif build_env['TARGET_ISA'] == 'sparc':
     from SparcTLB import SparcDTB, SparcITB
+    if build_env['FULL_SYSTEM']:
+        from SparcInterrupts import SparcInterrupts
 elif build_env['TARGET_ISA'] == 'x86':
     from X86TLB import X86DTB, X86ITB
+    if build_env['FULL_SYSTEM']:
+        from X86LocalApic import X86LocalApic
 elif build_env['TARGET_ISA'] == 'mips':
     from MipsTLB import MipsTLB,MipsDTB, MipsITB, MipsUTB
+    if build_env['FULL_SYSTEM']:
+        from MipsInterrupts import MipsInterrupts
 elif build_env['TARGET_ISA'] == 'arm':
     from ArmTLB import ArmTLB, ArmDTB, ArmITB, ArmUTB
+    if build_env['FULL_SYSTEM']:
+        from ArmInterrupts import ArmInterrupts
 
 class BaseCPU(MemObject):
     type = 'BaseCPU'
@@ -74,22 +84,37 @@ class BaseCPU(MemObject):
     if build_env['TARGET_ISA'] == 'sparc':
         dtb = Param.SparcDTB(SparcDTB(), "Data TLB")
         itb = Param.SparcITB(SparcITB(), "Instruction TLB")
+        if build_env['FULL_SYSTEM']:
+            interrupts = Param.SparcInterrupts(
+                SparcInterrupts(), "Interrupt Controller")
     elif build_env['TARGET_ISA'] == 'alpha':
         dtb = Param.AlphaDTB(AlphaDTB(), "Data TLB")
         itb = Param.AlphaITB(AlphaITB(), "Instruction TLB")
+        if build_env['FULL_SYSTEM']:
+            interrupts = Param.AlphaInterrupts(
+                AlphaInterrupts(), "Interrupt Controller")
     elif build_env['TARGET_ISA'] == 'x86':
         dtb = Param.X86DTB(X86DTB(), "Data TLB")
         itb = Param.X86ITB(X86ITB(), "Instruction TLB")
+        if build_env['FULL_SYSTEM']:
+            interrupts = Param.X86LocalApic(
+                    X86LocalApic(), "Interrupt Controller")
     elif build_env['TARGET_ISA'] == 'mips':
         UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?")
         dtb = Param.MipsDTB(MipsDTB(), "Data TLB")
         itb = Param.MipsITB(MipsITB(), "Instruction TLB")
         tlb = Param.MipsUTB(MipsUTB(), "Unified TLB")
+        if build_env['FULL_SYSTEM']:
+            interrupts = Param.MipsInterrupts(
+                    MipsInterrupts(), "Interrupt Controller")
     elif build_env['TARGET_ISA'] == 'arm':
         UnifiedTLB = Param.Bool(True, "Is this a Unified TLB?")
         dtb = Param.ArmDTB(ArmDTB(), "Data TLB")
         itb = Param.ArmITB(ArmITB(), "Instruction TLB")
         tlb = Param.ArmUTB(ArmUTB(), "Unified TLB")
+        if build_env['FULL_SYSTEM']:
+            interrupts = Param.ArmInterrupts(
+                    ArmInterrupts(), "Interrupt Controller")
     else:
         print "Don't know what TLB to use for ISA %s" % \
             build_env['TARGET_ISA']
index 1ca0dc14b8f4d9b704302ea2d1878dc8b744a96f..def1e9920627e044eb4d80f539bf900f0c59fc1b 100644 (file)
@@ -94,7 +94,7 @@ CPUProgressEvent::description() const
 
 #if FULL_SYSTEM
 BaseCPU::BaseCPU(Params *p)
-    : MemObject(p), clock(p->clock), instCnt(0),
+    : MemObject(p), clock(p->clock), instCnt(0), interrupts(p->interrupts),
       number_of_threads(p->numThreads), system(p->system),
       phase(p->phase)
 #else
@@ -381,33 +381,33 @@ BaseCPU::ProfileEvent::process()
 void
 BaseCPU::post_interrupt(int int_num, int index)
 {
-    interrupts.post(int_num, index);
+    interrupts->post(int_num, index);
 }
 
 void
 BaseCPU::clear_interrupt(int int_num, int index)
 {
-    interrupts.clear(int_num, index);
+    interrupts->clear(int_num, index);
 }
 
 void
 BaseCPU::clear_interrupts()
 {
-    interrupts.clear_all();
+    interrupts->clear_all();
 }
 
 void
 BaseCPU::serialize(std::ostream &os)
 {
     SERIALIZE_SCALAR(instCnt);
-    interrupts.serialize(os);
+    interrupts->serialize(os);
 }
 
 void
 BaseCPU::unserialize(Checkpoint *cp, const std::string &section)
 {
     UNSERIALIZE_SCALAR(instCnt);
-    interrupts.unserialize(cp, section);
+    interrupts->unserialize(cp, section);
 }
 
 #endif // FULL_SYSTEM
index c99efa834aff4715816eb1dd2680f953a9958706..a12c98ab0f333c64d639f0000a2db42a385bb8d1 100644 (file)
@@ -107,13 +107,13 @@ class BaseCPU : public MemObject
   protected:
 //    uint64_t interrupts[TheISA::NumInterruptLevels];
 //    uint64_t intstatus;
-    TheISA::Interrupts interrupts;
+    TheISA::Interrupts interrupts;
 
   public:
     TheISA::Interrupts *
     getInterruptController()
     {
-        return &interrupts;
+        return interrupts;
     }
 
     virtual void post_interrupt(int int_num, int index);
@@ -121,7 +121,7 @@ class BaseCPU : public MemObject
     virtual void clear_interrupts();
 
     bool check_interrupts(ThreadContext * tc) const
-    { return interrupts.check_interrupts(tc); }
+    { return interrupts->check_interrupts(tc); }
 
     class ProfileEvent : public Event
     {
index ac816fc18555cfe45d906926eac88c1f7e6b03b8..c110bbd50b09d1953c78a03aeca373e051aaa283 100644 (file)
@@ -906,7 +906,7 @@ Fault
 FullO3CPU<Impl>::getInterrupts()
 {
     // Check if there are any outstanding interrupts
-    return this->interrupts.getInterrupt(this->threadContexts[0]);
+    return this->interrupts->getInterrupt(this->threadContexts[0]);
 }
 
 template <class Impl>
@@ -920,7 +920,7 @@ FullO3CPU<Impl>::processInterrupts(Fault interrupt)
     // @todo: Allow other threads to handle interrupts.
 
     assert(interrupt != NoFault);
-    this->interrupts.updateIntrInfo(this->threadContexts[0]);
+    this->interrupts->updateIntrInfo(this->threadContexts[0]);
 
     DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name());
     this->trap(interrupt, 0);
index 9c0b95a1a58886d21a690ffead01e56c67acdf92..94af07525eedc8b6b04e11f1f720038a0ab30229 100644 (file)
@@ -678,10 +678,10 @@ OzoneCPU<Impl>::processInterrupts()
 
     // Check if there are any outstanding interrupts
     //Handle the interrupts
-    Fault interrupt = this->interrupts.getInterrupt(thread.getTC());
+    Fault interrupt = this->interrupts->getInterrupt(thread.getTC());
 
     if (interrupt != NoFault) {
-        this->interrupts.updateIntrInfo(thread.getTC());
+        this->interrupts->updateIntrInfo(thread.getTC());
         interrupt->invoke(thread.getTC());
     }
 }
index 3fd699868b9f7113599c1c9d8546a9b0fdb5876b..48e5db347cca3018ecc538584840bbde4c3d1cc8 100644 (file)
@@ -319,10 +319,10 @@ BaseSimpleCPU::checkForInterrupts()
 {
 #if FULL_SYSTEM
     if (check_interrupts(tc)) {
-        Fault interrupt = interrupts.getInterrupt(tc);
+        Fault interrupt = interrupts->getInterrupt(tc);
 
         if (interrupt != NoFault) {
-            interrupts.updateIntrInfo(tc);
+            interrupts->updateIntrInfo(tc);
             interrupt->invoke(tc);
         }
     }