summaryrefslogtreecommitdiff
path: root/src/arch/x86
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86')
-rw-r--r--src/arch/x86/SConscript16
-rw-r--r--src/arch/x86/SConsopts45
-rw-r--r--src/arch/x86/X86LocalApic.py36
-rw-r--r--src/arch/x86/X86System.py19
-rw-r--r--src/arch/x86/X86TLB.py17
-rw-r--r--src/arch/x86/apicregs.hh91
-rw-r--r--src/arch/x86/bios/ACPI.py99
-rw-r--r--src/arch/x86/bios/E820.py71
-rw-r--r--src/arch/x86/bios/IntelMP.py242
-rw-r--r--src/arch/x86/bios/SConscript77
-rw-r--r--src/arch/x86/bios/SMBios.py140
-rw-r--r--src/arch/x86/bios/acpi.cc109
-rw-r--r--src/arch/x86/bios/acpi.hh147
-rw-r--r--src/arch/x86/bios/e820.cc103
-rw-r--r--src/arch/x86/bios/e820.hh (renamed from src/arch/x86/syscallreturn.hh)48
-rw-r--r--src/arch/x86/bios/intelmp.cc476
-rw-r--r--src/arch/x86/bios/intelmp.hh330
-rw-r--r--src/arch/x86/bios/smbios.cc (renamed from src/arch/x86/smbios.cc)154
-rw-r--r--src/arch/x86/bios/smbios.hh (renamed from src/arch/x86/smbios.hh)118
-rw-r--r--src/arch/x86/cpuid.cc160
-rw-r--r--src/arch/x86/cpuid.hh61
-rw-r--r--src/arch/x86/emulenv.cc12
-rw-r--r--src/arch/x86/emulenv.hh1
-rw-r--r--src/arch/x86/faults.cc112
-rw-r--r--src/arch/x86/faults.hh168
-rw-r--r--src/arch/x86/floatregfile.cc17
-rw-r--r--src/arch/x86/floatregfile.hh2
-rw-r--r--src/arch/x86/insts/macroop.hh121
-rw-r--r--src/arch/x86/insts/microldstop.cc29
-rw-r--r--src/arch/x86/insts/microldstop.hh33
-rw-r--r--src/arch/x86/insts/microop.cc4
-rw-r--r--src/arch/x86/insts/microregop.cc3
-rw-r--r--src/arch/x86/insts/static_inst.cc42
-rw-r--r--src/arch/x86/insts/static_inst.hh3
-rw-r--r--src/arch/x86/interrupts.cc569
-rw-r--r--src/arch/x86/interrupts.hh253
-rw-r--r--src/arch/x86/intmessage.hh110
-rw-r--r--src/arch/x86/intregfile.cc17
-rw-r--r--src/arch/x86/intregfile.hh3
-rw-r--r--src/arch/x86/isa/decoder/one_byte_opcodes.isa23
-rw-r--r--src/arch/x86/isa/decoder/two_byte_opcodes.isa187
-rw-r--r--src/arch/x86/isa/formats/basic.isa8
-rw-r--r--src/arch/x86/isa/formats/cpuid.isa110
-rw-r--r--src/arch/x86/isa/formats/formats.isa3
-rw-r--r--src/arch/x86/isa/includes.isa9
-rw-r--r--src/arch/x86/isa/insts/__init__.py3
-rw-r--r--src/arch/x86/isa/insts/general_purpose/__init__.py1
-rw-r--r--src/arch/x86/isa/insts/general_purpose/arithmetic/multiply_and_divide.py24
-rw-r--r--src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py40
-rw-r--r--src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py153
-rw-r--r--src/arch/x86/isa/insts/general_purpose/control_transfer/call.py2
-rw-r--r--src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py198
-rw-r--r--src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py23
-rw-r--r--src/arch/x86/isa/insts/general_purpose/data_conversion/ascii_adjust.py8
-rw-r--r--src/arch/x86/isa/insts/general_purpose/data_conversion/bcd_adjust.py4
-rw-r--r--src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py22
-rw-r--r--src/arch/x86/isa/insts/general_purpose/data_conversion/extract_sign_mask.py4
-rw-r--r--src/arch/x86/isa/insts/general_purpose/data_conversion/translate.py2
-rw-r--r--src/arch/x86/isa/insts/general_purpose/data_transfer/move.py148
-rw-r--r--src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py106
-rw-r--r--src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py14
-rw-r--r--src/arch/x86/isa/insts/general_purpose/flags/set_and_clear.py22
-rw-r--r--src/arch/x86/isa/insts/general_purpose/input_output/general_io.py18
-rw-r--r--src/arch/x86/isa/insts/general_purpose/input_output/string_io.py32
-rw-r--r--src/arch/x86/isa/insts/general_purpose/load_segment_registers.py14
-rw-r--r--src/arch/x86/isa/insts/general_purpose/processor_information.py405
-rw-r--r--src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py89
-rw-r--r--src/arch/x86/isa/insts/general_purpose/semaphores.py26
-rw-r--r--src/arch/x86/isa/insts/general_purpose/string/compare_strings.py16
-rw-r--r--src/arch/x86/isa/insts/general_purpose/string/load_string.py15
-rw-r--r--src/arch/x86/isa/insts/general_purpose/string/move_string.py7
-rw-r--r--src/arch/x86/isa/insts/general_purpose/string/scan_string.py16
-rw-r--r--src/arch/x86/isa/insts/general_purpose/string/store_string.py7
-rw-r--r--src/arch/x86/isa/insts/general_purpose/system_calls.py183
-rw-r--r--src/arch/x86/isa/insts/romutil.py212
-rw-r--r--src/arch/x86/isa/insts/system/__init__.py3
-rw-r--r--src/arch/x86/isa/insts/system/control_registers.py35
-rw-r--r--src/arch/x86/isa/insts/system/msrs.py16
-rw-r--r--src/arch/x86/isa/insts/system/segmentation.py131
-rw-r--r--src/arch/x86/isa/macroop.isa122
-rw-r--r--src/arch/x86/isa/microasm.isa49
-rw-r--r--src/arch/x86/isa/microops/base.isa31
-rw-r--r--src/arch/x86/isa/microops/debug.isa229
-rw-r--r--src/arch/x86/isa/microops/fpop.isa2
-rw-r--r--src/arch/x86/isa/microops/ldstop.isa145
-rw-r--r--src/arch/x86/isa/microops/limmop.isa2
-rw-r--r--src/arch/x86/isa/microops/microops.isa8
-rw-r--r--src/arch/x86/isa/microops/regop.isa323
-rw-r--r--src/arch/x86/isa/microops/seqop.isa251
-rw-r--r--src/arch/x86/isa/microops/specop.isa19
-rw-r--r--src/arch/x86/isa/operands.isa54
-rw-r--r--src/arch/x86/isa/rom.isa90
-rw-r--r--src/arch/x86/isa/specialize.isa46
-rw-r--r--src/arch/x86/isa_traits.hh12
-rw-r--r--src/arch/x86/linux/linux.cc39
-rw-r--r--src/arch/x86/linux/linux.hh81
-rw-r--r--src/arch/x86/linux/process.cc30
-rw-r--r--src/arch/x86/linux/process.hh22
-rw-r--r--src/arch/x86/linux/syscalls.cc444
-rw-r--r--src/arch/x86/linux/system.cc61
-rw-r--r--src/arch/x86/linux/system.hh4
-rw-r--r--src/arch/x86/microcode_rom.hh74
-rw-r--r--src/arch/x86/miscregfile.cc289
-rw-r--r--src/arch/x86/miscregfile.hh13
-rw-r--r--src/arch/x86/miscregs.hh117
-rw-r--r--src/arch/x86/mmaped_ipr.hh30
-rw-r--r--src/arch/x86/pagetable.hh6
-rw-r--r--src/arch/x86/pagetable_walker.cc249
-rw-r--r--src/arch/x86/pagetable_walker.hh31
-rw-r--r--src/arch/x86/predecoder.cc45
-rw-r--r--src/arch/x86/predecoder.hh2
-rw-r--r--src/arch/x86/predecoder_tables.cc6
-rw-r--r--src/arch/x86/process.cc324
-rw-r--r--src/arch/x86/process.hh72
-rw-r--r--src/arch/x86/regfile.cc21
-rw-r--r--src/arch/x86/regfile.hh10
-rw-r--r--src/arch/x86/remote_gdb.cc18
-rw-r--r--src/arch/x86/stacktrace.cc4
-rw-r--r--src/arch/x86/system.cc78
-rw-r--r--src/arch/x86/system.hh14
-rw-r--r--src/arch/x86/tlb.cc355
-rw-r--r--src/arch/x86/tlb.hh21
-rw-r--r--src/arch/x86/types.hh11
-rw-r--r--src/arch/x86/utility.cc16
-rw-r--r--src/arch/x86/utility.hh7
-rw-r--r--src/arch/x86/x86_traits.hh37
126 files changed, 8165 insertions, 2146 deletions
diff --git a/src/arch/x86/SConscript b/src/arch/x86/SConscript
index 674cd54c2..4c0460e28 100644
--- a/src/arch/x86/SConscript
+++ b/src/arch/x86/SConscript
@@ -86,6 +86,7 @@
Import('*')
if env['TARGET_ISA'] == 'x86':
+ Source('cpuid.cc')
Source('emulenv.cc')
Source('floatregfile.cc')
Source('faults.cc')
@@ -105,16 +106,22 @@ if env['TARGET_ISA'] == 'x86':
Source('utility.cc')
SimObject('X86TLB.py')
- TraceFlag('Predecoder')
- TraceFlag('X86')
+ TraceFlag('Predecoder', "Predecoder debug output")
+ TraceFlag('X86', "Generic X86 ISA debugging")
if env['FULL_SYSTEM']:
+ TraceFlag('LocalApic', "Local APIC debugging")
+ TraceFlag('PageTableWalker', \
+ "Page table walker state machine debugging")
+ TraceFlag('Faults', "Trace all faults/exceptions/traps")
+
+ SimObject('X86LocalApic.py')
SimObject('X86System.py')
# Full-system sources
+ Source('interrupts.cc')
Source('linux/system.cc')
Source('pagetable_walker.cc')
- Source('smbios.cc')
Source('system.cc')
Source('stacktrace.cc')
Source('vtophys.cc')
@@ -170,7 +177,6 @@ if env['TARGET_ISA'] == 'x86':
'general_purpose/load_segment_registers.py',
'general_purpose/logical.py',
'general_purpose/no_operation.py',
- 'general_purpose/processor_information.py',
'general_purpose/rotate_and_shift/__init__.py',
'general_purpose/rotate_and_shift/rotate.py',
'general_purpose/rotate_and_shift/shift.py',
@@ -182,7 +188,9 @@ if env['TARGET_ISA'] == 'x86':
'general_purpose/string/scan_string.py',
'general_purpose/string/store_string.py',
'general_purpose/system_calls.py',
+ 'romutil.py',
'system/__init__.py',
+ 'system/control_registers.py',
'system/halt.py',
'system/invlpg.py',
'system/undefined_operation.py',
diff --git a/src/arch/x86/SConsopts b/src/arch/x86/SConsopts
index d8b7cbed1..f8b700271 100644
--- a/src/arch/x86/SConsopts
+++ b/src/arch/x86/SConsopts
@@ -3,43 +3,16 @@
# Copyright (c) 2007 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
+# 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. 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 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
diff --git a/src/arch/x86/X86LocalApic.py b/src/arch/x86/X86LocalApic.py
new file mode 100644
index 000000000..483c65ef8
--- /dev/null
+++ b/src/arch/x86/X86LocalApic.py
@@ -0,0 +1,36 @@
+# 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')
+ int_port = Port("Port for sending and receiving interrupt messages")
diff --git a/src/arch/x86/X86System.py b/src/arch/x86/X86System.py
index f73764540..527831205 100644
--- a/src/arch/x86/X86System.py
+++ b/src/arch/x86/X86System.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2007 The Hewlett-Packard Development Company
+# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
@@ -54,10 +54,27 @@
# Authors: Gabe Black
from m5.params import *
+from E820 import X86E820Table, X86E820Entry
+from SMBios import X86SMBiosSMBiosTable
+from IntelMP import X86IntelMPFloatingPointer, X86IntelMPConfigTable
+from ACPI import X86ACPIRSDP
from System import System
class X86System(System):
type = 'X86System'
+ smbios_table = Param.X86SMBiosSMBiosTable(
+ X86SMBiosSMBiosTable(), 'table of smbios/dmi information')
+ intel_mp_pointer = Param.X86IntelMPFloatingPointer(
+ X86IntelMPFloatingPointer(),
+ 'intel mp spec floating pointer structure')
+ intel_mp_table = Param.X86IntelMPConfigTable(
+ X86IntelMPConfigTable(),
+ 'intel mp spec configuration table')
+ acpi_description_table_pointer = Param.X86ACPIRSDP(
+ X86ACPIRSDP(), 'ACPI root description pointer structure')
class LinuxX86System(X86System):
type = 'LinuxX86System'
+
+ e820_table = Param.X86E820Table(
+ X86E820Table(), 'E820 map of physical memory')
diff --git a/src/arch/x86/X86TLB.py b/src/arch/x86/X86TLB.py
index dc080f37e..d5ae95372 100644
--- a/src/arch/x86/X86TLB.py
+++ b/src/arch/x86/X86TLB.py
@@ -54,23 +54,20 @@
# Authors: Gabe Black
from MemObject import MemObject
-from m5.SimObject import SimObject
from m5.params import *
from m5.proxy import *
from m5 import build_env
+from BaseTLB import BaseTLB
if build_env['FULL_SYSTEM']:
class X86PagetableWalker(MemObject):
type = 'X86PagetableWalker'
- cxx_namespace = 'X86ISA'
- cxx_class = 'Walker'
+ cxx_class = 'X86ISA::Walker'
port = Port("Port for the hardware table walker")
system = Param.System(Parent.any, "system object")
-class X86TLB(SimObject):
+class X86TLB(BaseTLB):
type = 'X86TLB'
- cxx_namespace = 'X86ISA'
- cxx_class = 'TLB'
abstract = True
size = Param.Int("TLB size")
if build_env['FULL_SYSTEM']:
@@ -79,14 +76,10 @@ class X86TLB(SimObject):
class X86DTB(X86TLB):
type = 'X86DTB'
- cxx_namespace = 'X86ISA'
- cxx_class = 'DTB'
-
+ cxx_class = 'X86ISA::DTB'
size = 64
class X86ITB(X86TLB):
type = 'X86ITB'
- cxx_namespace = 'X86ISA'
- cxx_class = 'ITB'
-
+ cxx_class = 'X86ISA::ITB'
size = 64
diff --git a/src/arch/x86/apicregs.hh b/src/arch/x86/apicregs.hh
new file mode 100644
index 000000000..464c3af2d
--- /dev/null
+++ b/src/arch/x86/apicregs.hh
@@ -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/bios/ACPI.py b/src/arch/x86/bios/ACPI.py
new file mode 100644
index 000000000..6f7cae946
--- /dev/null
+++ b/src/arch/x86/bios/ACPI.py
@@ -0,0 +1,99 @@
+# 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
+
+from m5.params import *
+from m5.SimObject import SimObject
+
+# ACPI description table header. Subclasses contain and handle the actual
+# contents as appropriate for that type of table.
+class X86ACPISysDescTable(SimObject):
+ type = 'X86ACPISysDescTable'
+ cxx_class = 'X86ISA::ACPI::SysDescTable'
+ abstract = True
+
+ oem_id = Param.String('', 'string identifying the oem')
+ oem_table_id = Param.String('', 'oem table ID')
+ oem_revision = Param.UInt32(0, 'oem revision number for the table')
+
+ creator_id = Param.String('',
+ 'string identifying the generator of the table')
+ creator_revision = Param.UInt32(0,
+ 'revision number for the creator of the table')
+
+class X86ACPIRSDT(X86ACPISysDescTable):
+ type = 'X86ACPIRSDT'
+ cxx_class = 'X86ISA::ACPI::RSDT'
+
+ entries = VectorParam.X86ACPISysDescTable([], 'system description tables')
+
+class X86ACPIXSDT(X86ACPISysDescTable):
+ type = 'X86ACPIXSDT'
+ cxx_class = 'X86ISA::ACPI::XSDT'
+
+ entries = VectorParam.X86ACPISysDescTable([], 'system description tables')
+
+# Root System Description Pointer Structure
+class X86ACPIRSDP(SimObject):
+ type = 'X86ACPIRSDP'
+ cxx_class = 'X86ISA::ACPI::RSDP'
+
+ oem_id = Param.String('', 'string identifying the oem')
+ # Because 0 encodes ACPI 1.0, 2 encodes ACPI 3.0, the version implemented
+ # here.
+ revision = Param.UInt8(2, 'revision of ACPI being used, zero indexed')
+
+ rsdt = Param.X86ACPIRSDT(NULL, 'root system description table')
+ xsdt = Param.X86ACPIXSDT(X86ACPIXSDT(),
+ 'extended system description table')
diff --git a/src/arch/x86/bios/E820.py b/src/arch/x86/bios/E820.py
new file mode 100644
index 000000000..288c253fb
--- /dev/null
+++ b/src/arch/x86/bios/E820.py
@@ -0,0 +1,71 @@
+# 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
+
+from m5.params import *
+from m5.SimObject import SimObject
+
+class X86E820Entry(SimObject):
+ type = 'X86E820Entry'
+ cxx_class = 'X86ISA::E820Entry'
+
+ addr = Param.Addr(0, 'address of the beginning of the region')
+ size = Param.MemorySize('0B', 'size of the region')
+ range_type = Param.UInt64('type of the region')
+
+class X86E820Table(SimObject):
+ type = 'X86E820Table'
+ cxx_class = 'X86ISA::E820Table'
+
+ entries = VectorParam.X86E820Entry([], 'entries for the e820 table')
diff --git a/src/arch/x86/bios/IntelMP.py b/src/arch/x86/bios/IntelMP.py
new file mode 100644
index 000000000..04e79b6ac
--- /dev/null
+++ b/src/arch/x86/bios/IntelMP.py
@@ -0,0 +1,242 @@
+# 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
+
+from m5.params import *
+from m5.SimObject import SimObject
+
+class X86IntelMPFloatingPointer(SimObject):
+ type = 'X86IntelMPFloatingPointer'
+ cxx_class = 'X86ISA::IntelMP::FloatingPointer'
+
+ # The minor revision of the spec to support. The major version is assumed
+ # to be 1 in accordance with the spec.
+ spec_rev = Param.UInt8(4, 'minor revision of the MP spec supported')
+ # If no default configuration is used, set this to 0.
+ default_config = Param.UInt8(0, 'which default configuration to use')
+ imcr_present = Param.Bool(True,
+ 'whether the IMCR register is present in the APIC')
+
+class X86IntelMPConfigTable(SimObject):
+ type = 'X86IntelMPConfigTable'
+ cxx_class = 'X86ISA::IntelMP::ConfigTable'
+
+ spec_rev = Param.UInt8(4, 'minor revision of the MP spec supported')
+ oem_id = Param.String("", 'system manufacturer')
+ product_id = Param.String("", 'product family')
+ oem_table_addr = Param.UInt32(0,
+ 'pointer to the optional oem configuration table')
+ oem_table_size = Param.UInt16(0, 'size of the oem configuration table')
+ local_apic = Param.UInt32(0xFEE00000, 'address of the local APIC')
+
+ base_entries = VectorParam.X86IntelMPBaseConfigEntry([],
+ 'base configuration table entries')
+
+ ext_entries = VectorParam.X86IntelMPExtConfigEntry([],
+ 'extended configuration table entries')
+
+ def add_entry(self, entry):
+ if isinstance(entry, X86IntelMPBaseConfigEntry):
+ self.base_entries.append(entry)
+ elif isinstance(entry, X86IntelMPExtConfigEntry):
+ self.ext_entries.append(entry)
+ else:
+ panic("Don't know what type of Intel MP entry %s is." \
+ % entry.__class__.__name__)
+
+class X86IntelMPBaseConfigEntry(SimObject):
+ type = 'X86IntelMPBaseConfigEntry'
+ cxx_class = 'X86ISA::IntelMP::BaseConfigEntry'
+ abstract = True
+
+class X86IntelMPExtConfigEntry(SimObject):
+ type = 'X86IntelMPExtConfigEntry'
+ cxx_class = 'X86ISA::IntelMP::ExtConfigEntry'
+ abstract = True
+
+class X86IntelMPProcessor(X86IntelMPBaseConfigEntry):
+ type = 'X86IntelMPProcessor'
+ cxx_class = 'X86ISA::IntelMP::Processor'
+
+ local_apic_id = Param.UInt8(0, 'local APIC id')
+ local_apic_version = Param.UInt8(0,
+ 'bits 0-7 of the local APIC version register')
+ enable = Param.Bool(True, 'if this processor is usable')
+ bootstrap = Param.Bool(False, 'if this is the bootstrap processor')
+
+ stepping = Param.UInt8(0, 'Processor stepping')
+ model = Param.UInt8(0, 'Processor model')
+ family = Param.UInt8(0, 'Processor family')
+
+ feature_flags = Param.UInt32(0, 'flags returned by the CPUID instruction')
+
+class X86IntelMPBus(X86IntelMPBaseConfigEntry):
+ type = 'X86IntelMPBus'
+ cxx_class = 'X86ISA::IntelMP::Bus'
+
+ bus_id = Param.UInt8(0, 'bus id assigned by the bios')
+ bus_type = Param.String("", 'string that identify the bus type')
+ # Legal values for bus_type are:
+ #
+ # "CBUS", "CBUSII", "EISA", "FUTURE", "INTERN", "ISA", "MBI", "MBII",
+ # "MCA", "MPI", "MPSA", "NUBUS", "PCI", "PCMCIA", "TC", "VL", "VME",
+ # "XPRESS"
+
+class X86IntelMPIOAPIC(X86IntelMPBaseConfigEntry):
+ type = 'X86IntelMPIOAPIC'
+ cxx_class = 'X86ISA::IntelMP::IOAPIC'
+
+ id = Param.UInt8(0, 'id of this APIC')
+ version = Param.UInt8(0, 'bits 0-7 of the version register')
+
+ enable = Param.Bool(True, 'if this APIC is usable')
+
+ address = Param.UInt32(0xfec00000, 'address of this APIC')
+
+class X86IntelMPInterruptType(Enum):
+ map = {'INT' : 0,
+ 'NMI' : 1,
+ 'SMI' : 2,
+ 'ExtInt' : 3
+ }
+
+class X86IntelMPPolarity(Enum):
+ map = {'ConformPolarity' : 0,
+ 'ActiveHigh' : 1,
+ 'ActiveLow' : 3
+ }
+
+class X86IntelMPTriggerMode(Enum):
+ map = {'ConformTrigger' : 0,
+ 'EdgeTrigger' : 1,
+ 'LevelTrigger' : 3
+ }
+
+class X86IntelMPIOIntAssignment(X86IntelMPBaseConfigEntry):
+ type = 'X86IntelMPIOIntAssignment'
+ cxx_class = 'X86ISA::IntelMP::IOIntAssignment'
+
+ interrupt_type = Param.X86IntelMPInterruptType('INT', 'type of interrupt')
+
+ polarity = Param.X86IntelMPPolarity('ConformPolarity', 'polarity')
+ trigger = Param.X86IntelMPTriggerMode('ConformTrigger', 'trigger mode')
+
+ source_bus_id = Param.UInt8(0,
+ 'id of the bus from which the interrupt signal comes')
+ source_bus_irq = Param.UInt8(0,
+ 'which interrupt signal from the source bus')
+
+ dest_io_apic_id = Param.UInt8(0,
+ 'id of the IO APIC the interrupt is going to')
+ dest_io_apic_intin = Param.UInt8(0,
+ 'the INTIN pin on the IO APIC the interrupt is connected to')
+
+class X86IntelMPLocalIntAssignment(X86IntelMPBaseConfigEntry):
+ type = 'X86IntelMPLocalIntAssignment'
+ cxx_class = 'X86ISA::IntelMP::LocalIntAssignment'
+
+ interrupt_type = Param.X86IntelMPInterruptType('INT', 'type of interrupt')
+
+ polarity = Param.X86IntelMPPolarity('ConformPolarity', 'polarity')
+ trigger = Param.X86IntelMPTriggerMode('ConformTrigger', 'trigger mode')
+
+ source_bus_id = Param.UInt8(0,
+ 'id of the bus from which the interrupt signal comes')
+ source_bus_irq = Param.UInt8(0,
+ 'which interrupt signal from the source bus')
+
+ dest_local_apic_id = Param.UInt8(0,
+ 'id of the local APIC the interrupt is going to')
+ dest_local_apic_intin = Param.UInt8(0,
+ 'the INTIN pin on the local APIC the interrupt is connected to')
+
+class X86IntelMPAddressType(Enum):
+ map = {"IOAddress" : 0,
+ "MemoryAddress" : 1,
+ "PrefetchAddress" : 2
+ }
+
+class X86IntelMPAddrSpaceMapping(X86IntelMPExtConfigEntry):
+ type = 'X86IntelMPAddrSpaceMapping'
+ cxx_class = 'X86ISA::IntelMP::AddrSpaceMapping'
+
+ bus_id = Param.UInt8(0, 'id of the bus the address space is mapped to')
+ address_type = Param.X86IntelMPAddressType('IOAddress',
+ 'address type used to access bus')
+ address = Param.Addr(0, 'starting address of the mapping')
+ length = Param.UInt64(0, 'length of mapping in bytes')
+
+class X86IntelMPBusHierarchy(X86IntelMPExtConfigEntry):
+ type = 'X86IntelMPBusHierarchy'
+ cxx_class = 'X86ISA::IntelMP::BusHierarchy'
+
+ bus_id = Param.UInt8(0, 'id of the bus being described')
+ subtractive_decode = Param.Bool(False,
+ 'whether this bus contains all addresses not used by its children')
+ parent_bus = Param.UInt8(0, 'bus id of this busses parent')
+
+class X86IntelMPRangeList(Enum):
+ map = {"ISACompatible" : 0,
+ "VGACompatible" : 1
+ }
+
+class X86IntelMPCompatAddrSpaceMod(X86IntelMPExtConfigEntry):
+ type = 'X86IntelMPCompatAddrSpaceMod'
+ cxx_class = 'X86ISA::IntelMP::CompatAddrSpaceMod'
+
+ bus_id = Param.UInt8(0, 'id of the bus being described')
+ add = Param.Bool(False,
+ 'if the range should be added to the original mapping')
+ range_list = Param.X86IntelMPRangeList('ISACompatible',
+ 'which predefined range of addresses to use')
diff --git a/src/arch/x86/bios/SConscript b/src/arch/x86/bios/SConscript
new file mode 100644
index 000000000..912d6599c
--- /dev/null
+++ b/src/arch/x86/bios/SConscript
@@ -0,0 +1,77 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2007-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
+
+Import('*')
+
+if env['TARGET_ISA'] == 'x86':
+ if env['FULL_SYSTEM']:
+ # The table generated by the bootloader using the BIOS and passed to
+ # the operating system which maps out physical memory.
+ SimObject('E820.py')
+ Source('e820.cc')
+
+ # The DMI tables.
+ SimObject('SMBios.py')
+ Source('smbios.cc')
+
+ # Intel Multiprocessor Specification Configuration Table
+ SimObject('IntelMP.py')
+ Source('intelmp.cc')
+
+ # ACPI system description tables
+ SimObject('ACPI.py')
+ Source('acpi.cc')
diff --git a/src/arch/x86/bios/SMBios.py b/src/arch/x86/bios/SMBios.py
new file mode 100644
index 000000000..4947b2854
--- /dev/null
+++ b/src/arch/x86/bios/SMBios.py
@@ -0,0 +1,140 @@
+# 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
+
+from m5.params import *
+from m5.SimObject import SimObject
+
+class X86SMBiosSMBiosStructure(SimObject):
+ type = 'X86SMBiosSMBiosStructure'
+ cxx_class = 'X86ISA::SMBios::SMBiosStructure'
+ abstract = True
+
+class Characteristic(Enum):
+ map = {'Unknown' : 2,
+ 'Unsupported' : 3,
+ 'ISA' : 4,
+ 'MCA' : 5,
+ 'EISA' : 6,
+ 'PCI' : 7,
+ 'PCMCIA' : 8,
+ 'PnP' : 9,
+ 'APM' : 10,
+ 'Flash' : 11,
+ 'Shadow' : 12,
+ 'VL_Vesa' : 13,
+ 'ESCD' : 14,
+ 'CDBoot' : 15,
+ 'SelectBoot' : 16,
+ 'Socketed' : 17,
+ 'PCMCIABoot' : 18,
+ 'EDD' : 19,
+ 'NEC9800' : 20,
+ 'Toshiba' : 21,
+ 'Floppy_5_25_360KB' : 22,
+ 'Floppy_5_25_1_2MB' : 23,
+ 'Floppy_3_5_720KB' : 24,
+ 'Floppy_3_5_2_88MB' : 25,
+ 'PrintScreen' : 26,
+ 'Keyboard8024' : 27,
+ 'Serial' : 28,
+ 'Printer' : 29,
+ 'CGA_Mono' : 30,
+ 'NEC_PC_98' : 31
+ }
+
+class ExtCharacteristic(Enum):
+ map = {'ACPI' : 0,
+ 'USBLegacy' : 1,
+ 'AGP' : 2,
+ 'I20Boot' : 3,
+ 'LS_120Boot' : 4,
+ 'ZIPBoot' : 5,
+ 'FirewireBoot' : 6,
+ 'SmartBattery' : 7,
+ 'BootSpec' : 8,
+ 'NetServiceBoot' : 9,
+ 'TargetContent' : 10
+ }
+
+class X86SMBiosBiosInformation(X86SMBiosSMBiosStructure):
+ type = 'X86SMBiosBiosInformation'
+ cxx_class = 'X86ISA::SMBios::BiosInformation'
+
+ vendor = Param.String("", "vendor name string")
+ version = Param.String("", "version string")
+ starting_addr_segment = \
+ Param.UInt16(0, "segment location of bios starting address")
+ release_date = Param.String("06/08/2008", "release date")
+ rom_size = Param.UInt8(0, "rom size")
+ characteristics = VectorParam.Characteristic([],
+ "bios characteristic bit vector")
+ characteristic_ext_bytes = VectorParam.ExtCharacteristic([],
+ "extended bios characteristic bit vector")
+ major = Param.UInt8(0, "major version number")
+ minor = Param.UInt8(0, "minor version number")
+ emb_cont_firmware_major = Param.UInt8(0,
+ "embedded controller firmware major version number")
+
+ emb_cont_firmware_minor = Param.UInt8(0,
+ "embedded controller firmware minor version number")
+
+class X86SMBiosSMBiosTable(SimObject):
+ type = 'X86SMBiosSMBiosTable'
+ cxx_class = 'X86ISA::SMBios::SMBiosTable'
+
+ major_version = Param.UInt8(2, "major version number")
+ minor_version = Param.UInt8(5, "minor version number")
+
+ structures = VectorParam.X86SMBiosSMBiosStructure([], "smbios structures")
diff --git a/src/arch/x86/bios/acpi.cc b/src/arch/x86/bios/acpi.cc
new file mode 100644
index 000000000..15b3901eb
--- /dev/null
+++ b/src/arch/x86/bios/acpi.cc
@@ -0,0 +1,109 @@
+/*
+ * 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/bios/acpi.hh"
+#include "mem/port.hh"
+#include "sim/byteswap.hh"
+#include "sim/sim_object.hh"
+
+#include "params/X86ACPIRSDP.hh"
+
+#include "params/X86ACPISysDescTable.hh"
+#include "params/X86ACPIRSDT.hh"
+#include "params/X86ACPIXSDT.hh"
+
+using namespace std;
+
+const char X86ISA::ACPI::RSDP::signature[] = "RSD PTR ";
+
+X86ISA::ACPI::RSDP::RSDP(Params *p) : SimObject(p), oemID(p->oem_id),
+ revision(p->revision), rsdt(p->rsdt), xsdt(p->xsdt)
+{}
+
+X86ISA::ACPI::SysDescTable::SysDescTable(Params *p,
+ const char * _signature, uint8_t _revision) : SimObject(p),
+ signature(_signature), revision(_revision),
+ oemID(p->oem_id), oemTableID(p->oem_table_id),
+ oemRevision(p->oem_revision),
+ creatorID(p->creator_id), creatorRevision(p->creator_revision)
+{}
+
+X86ISA::ACPI::RSDT::RSDT(Params *p) :
+ SysDescTable(p, "RSDT", 1), entries(p->entries)
+{}
+
+X86ISA::ACPI::XSDT::XSDT(Params *p) :
+ SysDescTable(p, "XSDT", 1), entries(p->entries)
+{}
+
+X86ISA::ACPI::RSDP *
+X86ACPIRSDPParams::create()
+{
+ return new X86ISA::ACPI::RSDP(this);
+}
+
+X86ISA::ACPI::RSDT *
+X86ACPIRSDTParams::create()
+{
+ return new X86ISA::ACPI::RSDT(this);
+}
+
+X86ISA::ACPI::XSDT *
+X86ACPIXSDTParams::create()
+{
+ return new X86ISA::ACPI::XSDT(this);
+}
diff --git a/src/arch/x86/bios/acpi.hh b/src/arch/x86/bios/acpi.hh
new file mode 100644
index 000000000..7bca17790
--- /dev/null
+++ b/src/arch/x86/bios/acpi.hh
@@ -0,0 +1,147 @@
+/*
+ * 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
+ */
+
+#ifndef __ARCH_X86_BIOS_ACPI_HH__
+#define __ARCH_X86_BIOS_ACPI_HH__
+
+#include "sim/host.hh"
+#include "sim/sim_object.hh"
+
+#include <vector>
+#include <string>
+
+class Port;
+
+class X86ACPIRSDPParams;
+
+class X86ACPISysDescTableParams;
+class X86ACPIRSDTParams;
+class X86ACPIXSDTParams;
+
+namespace X86ISA
+{
+
+namespace ACPI
+{
+
+class RSDT;
+class XSDT;
+class SysDescTable;
+
+class RSDP : public SimObject
+{
+ protected:
+ typedef X86ACPIRSDPParams Params;
+
+ static const char signature[];
+
+ std::string oemID;
+ uint8_t revision;
+
+ RSDT * rsdt;
+ XSDT * xsdt;
+
+ public:
+ RSDP(Params *p);
+};
+
+class SysDescTable : public SimObject
+{
+ protected:
+ typedef X86ACPISysDescTableParams Params;
+
+ const char * signature;
+ uint8_t revision;
+
+ std::string oemID;
+ std::string oemTableID;
+ uint32_t oemRevision;
+
+ std::string creatorID;
+ uint32_t creatorRevision;
+
+ public:
+ SysDescTable(Params *p, const char * _signature, uint8_t _revision);
+};
+
+class RSDT : public SysDescTable
+{
+ protected:
+ typedef X86ACPIRSDTParams Params;
+
+ std::vector<SysDescTable *> entries;
+
+ public:
+ RSDT(Params *p);
+};
+
+class XSDT : public SysDescTable
+{
+ protected:
+ typedef X86ACPIXSDTParams Params;
+
+ std::vector<SysDescTable *> entries;
+
+ public:
+ XSDT(Params *p);
+};
+
+} // namespace ACPI
+
+} // namespace X86ISA
+
+#endif // __ARCH_X86_BIOS_E820_HH__
diff --git a/src/arch/x86/bios/e820.cc b/src/arch/x86/bios/e820.cc
new file mode 100644
index 000000000..47adb703a
--- /dev/null
+++ b/src/arch/x86/bios/e820.cc
@@ -0,0 +1,103 @@
+/*
+ * 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/bios/e820.hh"
+#include "arch/x86/isa_traits.hh"
+#include "mem/port.hh"
+#include "sim/byteswap.hh"
+
+using namespace std;
+using namespace X86ISA;
+
+template<class T>
+void writeVal(T val, Port * port, Addr &addr)
+{
+ T guestVal = htog(val);
+ port->writeBlob(addr, (uint8_t *)&guestVal, sizeof(T));
+ addr += sizeof(T);
+}
+
+void X86ISA::E820Table::writeTo(Port * port, Addr countAddr, Addr addr)
+{
+ uint8_t e820Nr = entries.size();
+
+ // Make sure the number of entries isn't bigger than what the kernel
+ // would be capable of handling.
+ assert(e820Nr <= 128);
+
+ uint8_t guestE820Nr = htog(e820Nr);
+
+ port->writeBlob(countAddr, (uint8_t *)&guestE820Nr, sizeof(guestE820Nr));
+
+ for (int i = 0; i < e820Nr; i++) {
+ writeVal(entries[i]->addr, port, addr);
+ writeVal(entries[i]->size, port, addr);
+ writeVal(entries[i]->type, port, addr);
+ }
+}
+
+E820Table *
+X86E820TableParams::create()
+{
+ return new E820Table(this);
+}
+
+E820Entry *
+X86E820EntryParams::create()
+{
+ return new E820Entry(this);
+}
diff --git a/src/arch/x86/syscallreturn.hh b/src/arch/x86/bios/e820.hh
index 6a7fdba58..da738343b 100644
--- a/src/arch/x86/syscallreturn.hh
+++ b/src/arch/x86/bios/e820.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms,
@@ -55,20 +55,46 @@
* Authors: Gabe Black
*/
-#ifndef __ARCH_X86_SYSCALLRETURN_HH__
-#define __ARCH_X86_SYSCALLRETURN_HH__
+#ifndef __ARCH_X86_BIOS_E820_HH__
+#define __ARCH_X86_BIOS_E820_HH__
-#include "base/misc.hh"
-#include "cpu/thread_context.hh"
-#include "sim/syscallreturn.hh"
+#include "params/X86E820Entry.hh"
+#include "params/X86E820Table.hh"
+#include "sim/host.hh"
+#include "sim/sim_object.hh"
+
+#include <vector>
+
+class Port;
namespace X86ISA
{
- static inline void setSyscallReturn(SyscallReturn return_value,
- ThreadContext * tc)
+ class E820Entry : public SimObject
{
- tc->setIntReg(INTREG_RAX, return_value.value());
- }
+ public:
+ Addr addr;
+ Addr size;
+ uint32_t type;
+
+ public:
+ typedef X86E820EntryParams Params;
+ E820Entry(Params *p) :
+ SimObject(p), addr(p->addr), size(p->size), type(p->range_type)
+ {}
+ };
+
+ class E820Table : public SimObject
+ {
+ public:
+ std::vector<E820Entry *> entries;
+
+ public:
+ typedef X86E820TableParams Params;
+ E820Table(Params *p) : SimObject(p), entries(p->entries)
+ {}
+
+ void writeTo(Port * port, Addr countAddr, Addr addr);
+ };
};
-#endif // __ARCH_X86_SYSCALLRETURN_HH__
+#endif // __ARCH_X86_BIOS_E820_HH__
diff --git a/src/arch/x86/bios/intelmp.cc b/src/arch/x86/bios/intelmp.cc
new file mode 100644
index 000000000..2332e7a5c
--- /dev/null
+++ b/src/arch/x86/bios/intelmp.cc
@@ -0,0 +1,476 @@
+/*
+ * 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/bios/intelmp.hh"
+#include "arch/x86/isa_traits.hh"
+#include "base/misc.hh"
+#include "mem/port.hh"
+#include "sim/byteswap.hh"
+#include "sim/host.hh"
+
+// Config entry types
+#include "params/X86IntelMPBaseConfigEntry.hh"
+#include "params/X86IntelMPExtConfigEntry.hh"
+
+// General table structures
+#include "params/X86IntelMPConfigTable.hh"
+#include "params/X86IntelMPFloatingPointer.hh"
+
+// Base entry types
+#include "params/X86IntelMPBus.hh"
+#include "params/X86IntelMPIOAPIC.hh"
+#include "params/X86IntelMPIOIntAssignment.hh"
+#include "params/X86IntelMPLocalIntAssignment.hh"
+#include "params/X86IntelMPProcessor.hh"
+
+// Extended entry types
+#include "params/X86IntelMPAddrSpaceMapping.hh"
+#include "params/X86IntelMPBusHierarchy.hh"
+#include "params/X86IntelMPCompatAddrSpaceMod.hh"
+
+using namespace std;
+
+const char X86ISA::IntelMP::FloatingPointer::signature[] = "_MP_";
+
+template<class T>
+uint8_t
+writeOutField(FunctionalPort * port, Addr addr, T val)
+{
+ T guestVal = X86ISA::htog(val);
+ port->writeBlob(addr, (uint8_t *)(&guestVal), sizeof(T));
+
+ uint8_t checkSum = 0;
+ while(guestVal) {
+ checkSum += guestVal;
+ guestVal >>= 8;
+ }
+ return checkSum;
+}
+
+uint8_t
+writeOutString(FunctionalPort * port, Addr addr, string str, int length)
+{
+ char cleanedString[length + 1];
+ cleanedString[length] = 0;
+
+ if (str.length() > length) {
+ memcpy(cleanedString, str.c_str(), length);
+ warn("Intel MP configuration table string \"%s\" "
+ "will be truncated to \"%s\".\n", str, cleanedString);
+ } else {
+ memcpy(cleanedString, str.c_str(), str.length());
+ memset(cleanedString + str.length(), 0, length - str.length());
+ }
+ port->writeBlob(addr, (uint8_t *)(&cleanedString), length);
+
+ uint8_t checkSum = 0;
+ for (int i = 0; i < length; i++)
+ checkSum += cleanedString[i];
+
+ return checkSum;
+}
+
+Addr
+X86ISA::IntelMP::FloatingPointer::writeOut(FunctionalPort * port, Addr addr)
+{
+ // Make sure that either a config table is present or a default
+ // configuration was found but not both.
+ if (!tableAddr && !defaultConfig)
+ fatal("Either an MP configuration table or a default configuration "
+ "must be used.");
+ if (tableAddr && defaultConfig)
+ fatal("Both an MP configuration table and a default configuration "
+ "were set.");
+
+ uint8_t checkSum = 0;
+
+ port->writeBlob(addr, (uint8_t *)signature, 4);
+ for (int i = 0; i < 4; i++)
+ checkSum += signature[i];
+
+ checkSum += writeOutField(port, addr + 4, tableAddr);
+
+ // The length of the structure in paragraphs, aka 16 byte chunks.
+ uint8_t length = 1;
+ port->writeBlob(addr + 8, &length, 1);
+ checkSum += length;
+
+ port->writeBlob(addr + 9, &specRev, 1);
+ checkSum += specRev;
+
+ port->writeBlob(addr + 11, &defaultConfig, 1);
+ checkSum += defaultConfig;
+
+ uint32_t features2_5 = imcrPresent ? (1 << 7) : 0;
+ checkSum += writeOutField(port, addr + 12, features2_5);
+
+ checkSum = -checkSum;
+ port->writeBlob(addr + 10, &checkSum, 1);
+
+ return 16;
+}
+
+X86ISA::IntelMP::FloatingPointer::FloatingPointer(Params * p) :
+ SimObject(p), tableAddr(0), specRev(p->spec_rev),
+ defaultConfig(p->default_config), imcrPresent(p->imcr_present)
+{}
+
+X86ISA::IntelMP::FloatingPointer *
+X86IntelMPFloatingPointerParams::create()
+{
+ return new X86ISA::IntelMP::FloatingPointer(this);
+}
+
+Addr
+X86ISA::IntelMP::BaseConfigEntry::writeOut(FunctionalPort * port,
+ Addr addr, uint8_t &checkSum)
+{
+ port->writeBlob(addr, &type, 1);
+ checkSum += type;
+ return 1;
+}
+
+X86ISA::IntelMP::BaseConfigEntry::BaseConfigEntry(Params * p, uint8_t _type) :
+ SimObject(p), type(_type)
+{}
+
+Addr
+X86ISA::IntelMP::ExtConfigEntry::writeOut(FunctionalPort * port,
+ Addr addr, uint8_t &checkSum)
+{
+ port->writeBlob(addr, &type, 1);
+ checkSum += type;
+ port->writeBlob(addr + 1, &length, 1);
+ checkSum += length;
+ return 1;
+}
+
+X86ISA::IntelMP::ExtConfigEntry::ExtConfigEntry(Params * p,
+ uint8_t _type, uint8_t _length) :
+ SimObject(p), type(_type), length(_length)
+{}
+
+const char X86ISA::IntelMP::ConfigTable::signature[] = "PCMP";
+
+Addr
+X86ISA::IntelMP::ConfigTable::writeOut(FunctionalPort * port, Addr addr)
+{
+ uint8_t checkSum = 0;
+
+ port->writeBlob(addr, (uint8_t *)signature, 4);
+ for (int i = 0; i < 4; i++)
+ checkSum += signature[i];
+
+ // Base table length goes here but will be calculated later.
+
+ port->writeBlob(addr + 6, (uint8_t *)(&specRev), 1);
+ checkSum += specRev;
+
+ // The checksum goes here but is still being calculated.
+
+ checkSum += writeOutString(port, addr + 8, oemID, 8);
+ checkSum += writeOutString(port, addr + 16, productID, 12);
+
+ checkSum += writeOutField(port, addr + 28, oemTableAddr);
+ checkSum += writeOutField(port, addr + 32, oemTableSize);
+ checkSum += writeOutField(port, addr + 34, (uint16_t)baseEntries.size());
+ checkSum += writeOutField(port, addr + 36, localApic);
+
+ uint8_t reserved = 0;
+ port->writeBlob(addr + 43, &reserved, 1);
+ checkSum += reserved;
+
+ vector<BaseConfigEntry *>::iterator baseEnt;
+ uint16_t offset = 44;
+ for (baseEnt = baseEntries.begin();
+ baseEnt != baseEntries.end(); baseEnt++) {
+ offset += (*baseEnt)->writeOut(port, addr + offset, checkSum);
+ }
+
+ // We've found the end of the base table this point.
+ checkSum += writeOutField(port, addr + 4, offset);
+
+ vector<ExtConfigEntry *>::iterator extEnt;
+ uint16_t extOffset = 0;
+ uint8_t extCheckSum = 0;
+ for (extEnt = extEntries.begin();
+ extEnt != extEntries.end(); extEnt++) {
+ extOffset += (*extEnt)->writeOut(port,
+ addr + offset + extOffset, extCheckSum);
+ }
+
+ checkSum += writeOutField(port, addr + 40, extOffset);
+ extCheckSum = -extCheckSum;
+ checkSum += writeOutField(port, addr + 42, extCheckSum);
+
+ // And now, we finally have the whole check sum completed.
+ checkSum = -checkSum;
+ writeOutField(port, addr + 7, checkSum);
+
+ return offset + extOffset;
+};
+
+X86ISA::IntelMP::ConfigTable::ConfigTable(Params * p) : SimObject(p),
+ specRev(p->spec_rev), oemID(p->oem_id), productID(p->product_id),
+ oemTableAddr(p->oem_table_addr), oemTableSize(p->oem_table_size),
+ localApic(p->local_apic),
+ baseEntries(p->base_entries), extEntries(p->ext_entries)
+{}
+
+X86ISA::IntelMP::ConfigTable *
+X86IntelMPConfigTableParams::create()
+{
+ return new X86ISA::IntelMP::ConfigTable(this);
+}
+
+Addr
+X86ISA::IntelMP::Processor::writeOut(
+ FunctionalPort * port, Addr addr, uint8_t &checkSum)
+{
+ BaseConfigEntry::writeOut(port, addr, checkSum);
+ checkSum += writeOutField(port, addr + 1, localApicID);
+ checkSum += writeOutField(port, addr + 2, localApicVersion);
+ checkSum += writeOutField(port, addr + 3, cpuFlags);
+ checkSum += writeOutField(port, addr + 4, cpuSignature);
+ checkSum += writeOutField(port, addr + 8, featureFlags);
+
+ uint32_t reserved = 0;
+ port->writeBlob(addr + 12, (uint8_t *)(&reserved), 4);
+ port->writeBlob(addr + 16, (uint8_t *)(&reserved), 4);
+ return 20;
+}
+
+X86ISA::IntelMP::Processor::Processor(Params * p) : BaseConfigEntry(p, 0),
+ localApicID(p->local_apic_id), localApicVersion(p->local_apic_version),
+ cpuFlags(0), cpuSignature(0), featureFlags(p->feature_flags)
+{
+ if (p->enable)
+ cpuFlags |= (1 << 0);
+ if (p->bootstrap)
+ cpuFlags |= (1 << 1);
+
+ replaceBits(cpuSignature, 0, 3, p->stepping);
+ replaceBits(cpuSignature, 4, 7, p->model);
+ replaceBits(cpuSignature, 8, 11, p->family);
+}
+
+X86ISA::IntelMP::Processor *
+X86IntelMPProcessorParams::create()
+{
+ return new X86ISA::IntelMP::Processor(this);
+}
+
+Addr
+X86ISA::IntelMP::Bus::writeOut(
+ FunctionalPort * port, Addr addr, uint8_t &checkSum)
+{
+ BaseConfigEntry::writeOut(port, addr, checkSum);
+ checkSum += writeOutField(port, addr + 1, busID);
+ checkSum += writeOutString(port, addr + 2, busType, 6);
+ return 8;
+}
+
+X86ISA::IntelMP::Bus::Bus(Params * p) : BaseConfigEntry(p, 1),
+ busID(p->bus_id), busType(p->bus_type)
+{}
+
+X86ISA::IntelMP::Bus *
+X86IntelMPBusParams::create()
+{
+ return new X86ISA::IntelMP::Bus(this);
+}
+
+Addr
+X86ISA::IntelMP::IOAPIC::writeOut(
+ FunctionalPort * port, Addr addr, uint8_t &checkSum)
+{
+ BaseConfigEntry::writeOut(port, addr, checkSum);
+ checkSum += writeOutField(port, addr + 1, id);
+ checkSum += writeOutField(port, addr + 2, version);
+ checkSum += writeOutField(port, addr + 3, flags);
+ checkSum += writeOutField(port, addr + 4, address);
+ return 8;
+}
+
+X86ISA::IntelMP::IOAPIC::IOAPIC(Params * p) : BaseConfigEntry(p, 2),
+ id(p->id), version(p->version), flags(0), address(p->address)
+{
+ if (p->enable)
+ flags |= 1;
+}
+
+X86ISA::IntelMP::IOAPIC *
+X86IntelMPIOAPICParams::create()
+{
+ return new X86ISA::IntelMP::IOAPIC(this);
+}
+
+Addr
+X86ISA::IntelMP::IntAssignment::writeOut(
+ FunctionalPort * port, Addr addr, uint8_t &checkSum)
+{
+ BaseConfigEntry::writeOut(port, addr, checkSum);
+ checkSum += writeOutField(port, addr + 1, interruptType);
+ checkSum += writeOutField(port, addr + 2, flags);
+ checkSum += writeOutField(port, addr + 4, sourceBusID);
+ checkSum += writeOutField(port, addr + 5, sourceBusIRQ);
+ checkSum += writeOutField(port, addr + 6, destApicID);
+ checkSum += writeOutField(port, addr + 7, destApicIntIn);
+ return 8;
+}
+
+X86ISA::IntelMP::IOIntAssignment::IOIntAssignment(Params * p) :
+ IntAssignment(p, p->interrupt_type, p->polarity, p->trigger, 3,
+ p->source_bus_id, p->source_bus_irq,
+ p->dest_io_apic_id, p->dest_io_apic_intin)
+{}
+
+X86ISA::IntelMP::IOIntAssignment *
+X86IntelMPIOIntAssignmentParams::create()
+{
+ return new X86ISA::IntelMP::IOIntAssignment(this);
+}
+
+X86ISA::IntelMP::LocalIntAssignment::LocalIntAssignment(Params * p) :
+ IntAssignment(p, p->interrupt_type, p->polarity, p->trigger, 4,
+ p->source_bus_id, p->source_bus_irq,
+ p->dest_local_apic_id, p->dest_local_apic_intin)
+{}
+
+X86ISA::IntelMP::LocalIntAssignment *
+X86IntelMPLocalIntAssignmentParams::create()
+{
+ return new X86ISA::IntelMP::LocalIntAssignment(this);
+}
+
+Addr
+X86ISA::IntelMP::AddrSpaceMapping::writeOut(
+ FunctionalPort * port, Addr addr, uint8_t &checkSum)
+{
+ ExtConfigEntry::writeOut(port, addr, checkSum);
+ checkSum += writeOutField(port, addr + 2, busID);
+ checkSum += writeOutField(port, addr + 3, addrType);
+ checkSum += writeOutField(port, addr + 4, addr);
+ checkSum += writeOutField(port, addr + 12, addrLength);
+ return length;
+}
+
+X86ISA::IntelMP::AddrSpaceMapping::AddrSpaceMapping(Params * p) :
+ ExtConfigEntry(p, 128, 20),
+ busID(p->bus_id), addrType(p->address_type),
+ addr(p->address), addrLength(p->length)
+{}
+
+X86ISA::IntelMP::AddrSpaceMapping *
+X86IntelMPAddrSpaceMappingParams::create()
+{
+ return new X86ISA::IntelMP::AddrSpaceMapping(this);
+}
+
+Addr
+X86ISA::IntelMP::BusHierarchy::writeOut(
+ FunctionalPort * port, Addr addr, uint8_t &checkSum)
+{
+ ExtConfigEntry::writeOut(port, addr, checkSum);
+ checkSum += writeOutField(port, addr + 2, busID);
+ checkSum += writeOutField(port, addr + 3, info);
+ checkSum += writeOutField(port, addr + 4, parentBus);
+
+ uint32_t reserved = 0;
+ port->writeBlob(addr + 5, (uint8_t *)(&reserved), 3);
+
+ return length;
+}
+
+X86ISA::IntelMP::BusHierarchy::BusHierarchy(Params * p) :
+ ExtConfigEntry(p, 129, 8),
+ busID(p->bus_id), info(0), parentBus(p->parent_bus)
+{
+ if (p->subtractive_decode)
+ info |= 1;
+}
+
+X86ISA::IntelMP::BusHierarchy *
+X86IntelMPBusHierarchyParams::create()
+{
+ return new X86ISA::IntelMP::BusHierarchy(this);
+}
+
+Addr
+X86ISA::IntelMP::CompatAddrSpaceMod::writeOut(
+ FunctionalPort * port, Addr addr, uint8_t &checkSum)
+{
+ ExtConfigEntry::writeOut(port, addr, checkSum);
+ checkSum += writeOutField(port, addr + 2, busID);
+ checkSum += writeOutField(port, addr + 3, mod);
+ checkSum += writeOutField(port, addr + 4, rangeList);
+ return length;
+}
+
+X86ISA::IntelMP::CompatAddrSpaceMod::CompatAddrSpaceMod(Params * p) :
+ ExtConfigEntry(p, 130, 8),
+ busID(p->bus_id), mod(0), rangeList(p->range_list)
+{
+ if (p->add)
+ mod |= 1;
+}
+
+X86ISA::IntelMP::CompatAddrSpaceMod *
+X86IntelMPCompatAddrSpaceModParams::create()
+{
+ return new X86ISA::IntelMP::CompatAddrSpaceMod(this);
+}
diff --git a/src/arch/x86/bios/intelmp.hh b/src/arch/x86/bios/intelmp.hh
new file mode 100644
index 000000000..e8d1d656e
--- /dev/null
+++ b/src/arch/x86/bios/intelmp.hh
@@ -0,0 +1,330 @@
+/*
+ * 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
+ */
+
+#ifndef __ARCH_X86_BIOS_INTELMP_HH__
+#define __ARCH_X86_BIOS_INTELMP_HH__
+
+#include <string>
+#include <vector>
+
+#include "base/bitfield.hh"
+#include "sim/sim_object.hh"
+
+#include "enums/X86IntelMPAddressType.hh"
+#include "enums/X86IntelMPInterruptType.hh"
+#include "enums/X86IntelMPPolarity.hh"
+#include "enums/X86IntelMPRangeList.hh"
+#include "enums/X86IntelMPTriggerMode.hh"
+
+class FunctionalPort;
+
+// Config entry types
+class X86IntelMPBaseConfigEntryParams;
+class X86IntelMPExtConfigEntryParams;
+
+// General table structures
+class X86IntelMPConfigTableParams;
+class X86IntelMPFloatingPointerParams;
+
+// Base entry types
+class X86IntelMPBusParams;
+class X86IntelMPIOAPICParams;
+class X86IntelMPIOIntAssignmentParams;
+class X86IntelMPLocalIntAssignmentParams;
+class X86IntelMPProcessorParams;
+
+// Extended entry types
+class X86IntelMPAddrSpaceMappingParams;
+class X86IntelMPBusHierarchyParams;
+class X86IntelMPCompatAddrSpaceModParams;
+
+namespace X86ISA
+{
+
+namespace IntelMP
+{
+
+class FloatingPointer : public SimObject
+{
+ protected:
+ typedef X86IntelMPFloatingPointerParams Params;
+
+ uint32_t tableAddr;
+ uint8_t specRev;
+ uint8_t defaultConfig;
+ bool imcrPresent;
+
+ static const char signature[];
+
+ public:
+
+ Addr writeOut(FunctionalPort * port, Addr addr);
+
+ Addr getTableAddr()
+ {
+ return tableAddr;
+ }
+
+ void setTableAddr(Addr addr)
+ {
+ tableAddr = addr;
+ }
+
+ FloatingPointer(Params * p);
+};
+
+class BaseConfigEntry : public SimObject
+{
+ protected:
+ typedef X86IntelMPBaseConfigEntryParams Params;
+
+ uint8_t type;
+
+ public:
+
+ virtual Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum);
+
+ BaseConfigEntry(Params * p, uint8_t _type);
+};
+
+class ExtConfigEntry : public SimObject
+{
+ protected:
+ typedef X86IntelMPExtConfigEntryParams Params;
+
+ uint8_t type;
+ uint8_t length;
+
+ public:
+
+ virtual Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum);
+
+ ExtConfigEntry(Params * p, uint8_t _type, uint8_t _length);
+};
+
+class ConfigTable : public SimObject
+{
+ protected:
+ typedef X86IntelMPConfigTableParams Params;
+
+ static const char signature[];
+
+ uint8_t specRev;
+ std::string oemID;
+ std::string productID;
+ uint32_t oemTableAddr;
+ uint16_t oemTableSize;
+ uint32_t localApic;
+
+ std::vector<BaseConfigEntry *> baseEntries;
+ std::vector<ExtConfigEntry *> extEntries;
+
+ public:
+ Addr writeOut(FunctionalPort * port, Addr addr);
+
+ ConfigTable(Params * p);
+};
+
+class Processor : public BaseConfigEntry
+{
+ protected:
+ typedef X86IntelMPProcessorParams Params;
+
+ uint8_t localApicID;
+ uint8_t localApicVersion;
+ uint8_t cpuFlags;
+ uint32_t cpuSignature;
+ uint32_t featureFlags;
+
+ public:
+ Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum);
+
+ Processor(Params * p);
+};
+
+class Bus : public BaseConfigEntry
+{
+ protected:
+ typedef X86IntelMPBusParams Params;
+
+ uint8_t busID;
+ std::string busType;
+
+ public:
+ Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum);
+
+ Bus(Params * p);
+};
+
+class IOAPIC : public BaseConfigEntry
+{
+ protected:
+ typedef X86IntelMPIOAPICParams Params;
+
+ uint8_t id;
+ uint8_t version;
+ uint8_t flags;
+ uint32_t address;
+
+ public:
+ Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum);
+
+ IOAPIC(Params * p);
+};
+
+class IntAssignment : public BaseConfigEntry
+{
+ protected:
+ uint8_t interruptType;
+
+ uint16_t flags;
+
+ uint8_t sourceBusID;
+ uint8_t sourceBusIRQ;
+
+ uint8_t destApicID;
+ uint8_t destApicIntIn;
+
+ public:
+ Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum);
+
+ IntAssignment(X86IntelMPBaseConfigEntryParams * p,
+ Enums::X86IntelMPInterruptType _interruptType,
+ Enums::X86IntelMPPolarity polarity,
+ Enums::X86IntelMPTriggerMode trigger,
+ uint8_t _type,
+ uint8_t _sourceBusID, uint8_t _sourceBusIRQ,
+ uint8_t _destApicID, uint8_t _destApicIntIn) :
+ BaseConfigEntry(p, _type),
+ interruptType(_interruptType), flags(0),
+ sourceBusID(_sourceBusID), sourceBusIRQ(_sourceBusIRQ),
+ destApicID(_destApicID), destApicIntIn(_destApicIntIn)
+ {
+ replaceBits(flags, 0, 1, polarity);
+ replaceBits(flags, 2, 3, trigger);
+ }
+};
+
+class IOIntAssignment : public IntAssignment
+{
+ protected:
+ typedef X86IntelMPIOIntAssignmentParams Params;
+
+ public:
+ IOIntAssignment(Params * p);
+};
+
+class LocalIntAssignment : public IntAssignment
+{
+ protected:
+ typedef X86IntelMPLocalIntAssignmentParams Params;
+
+ public:
+ LocalIntAssignment(Params * p);
+};
+
+class AddrSpaceMapping : public ExtConfigEntry
+{
+ protected:
+ typedef X86IntelMPAddrSpaceMappingParams Params;
+
+ uint8_t busID;
+ uint8_t addrType;
+ uint64_t addr;
+ uint64_t addrLength;
+
+ public:
+ Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum);
+
+ AddrSpaceMapping(Params * p);
+};
+
+class BusHierarchy : public ExtConfigEntry
+{
+ protected:
+ typedef X86IntelMPBusHierarchyParams Params;
+
+ uint8_t busID;
+ uint8_t info;
+ uint8_t parentBus;
+
+ public:
+ Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum);
+
+ BusHierarchy(Params * p);
+};
+
+class CompatAddrSpaceMod : public ExtConfigEntry
+{
+ protected:
+ typedef X86IntelMPCompatAddrSpaceModParams Params;
+
+ uint8_t busID;
+ uint8_t mod;
+ uint32_t rangeList;
+
+ public:
+ Addr writeOut(FunctionalPort * port, Addr addr, uint8_t &checkSum);
+
+ CompatAddrSpaceMod(Params * p);
+};
+
+} //IntelMP
+
+} //X86ISA
+
+#endif
diff --git a/src/arch/x86/smbios.cc b/src/arch/x86/bios/smbios.cc
index 319650c1f..95ade1e4d 100644
--- a/src/arch/x86/smbios.cc
+++ b/src/arch/x86/bios/smbios.cc
@@ -85,12 +85,17 @@
* Authors: Gabe Black
*/
-#include "arch/x86/smbios.hh"
+#include "arch/x86/bios/smbios.hh"
#include "arch/x86/isa_traits.hh"
#include "mem/port.hh"
+#include "params/X86SMBiosBiosInformation.hh"
+#include "params/X86SMBiosSMBiosStructure.hh"
+#include "params/X86SMBiosSMBiosTable.hh"
#include "sim/byteswap.hh"
#include "sim/host.hh"
+using namespace std;
+
const char X86ISA::SMBios::SMBiosTable::SMBiosHeader::anchorString[] = "_SM_";
const uint8_t X86ISA::SMBios::SMBiosTable::
SMBiosHeader::formattedArea[] = {0,0,0,0,0};
@@ -101,6 +106,116 @@ const uint8_t X86ISA::SMBios::SMBiosTable::
const char X86ISA::SMBios::SMBiosTable::
SMBiosHeader::IntermediateHeader::anchorString[] = "_DMI_";
+template <class T>
+uint64_t
+composeBitVector(T vec)
+{
+ uint64_t val = 0;
+ typename T::iterator vecIt;
+ for (vecIt = vec.begin(); vecIt != vec.end(); vecIt++) {
+ val |= (1 << (*vecIt));
+ }
+ return val;
+}
+
+uint16_t
+X86ISA::SMBios::SMBiosStructure::writeOut(FunctionalPort * port, Addr addr)
+{
+ port->writeBlob(addr, (uint8_t *)(&type), 1);
+
+ uint8_t length = getLength();
+ port->writeBlob(addr + 1, (uint8_t *)(&length), 1);
+
+ uint16_t handleGuest = X86ISA::htog(handle);
+ port->writeBlob(addr + 2, (uint8_t *)(&handleGuest), 2);
+
+ return length + getStringLength();
+}
+
+X86ISA::SMBios::SMBiosStructure::SMBiosStructure(Params * p, uint8_t _type) :
+ SimObject(p), type(_type), handle(0), stringFields(false)
+{}
+
+void
+X86ISA::SMBios::SMBiosStructure::writeOutStrings(
+ FunctionalPort * port, Addr addr)
+{
+ std::vector<std::string>::iterator it;
+ Addr offset = 0;
+
+ const uint8_t nullTerminator = 0;
+
+ // If there are string fields but none of them are used, that's a
+ // special case which is handled by this if.
+ if (strings.size() == 0 && stringFields) {
+ port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1);
+ offset++;
+ } else {
+ for (it = strings.begin(); it != strings.end(); it++) {
+ port->writeBlob(addr + offset,
+ (uint8_t *)it->c_str(), it->length() + 1);
+ offset += it->length() + 1;
+ }
+ }
+ port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1);
+}
+
+int
+X86ISA::SMBios::SMBiosStructure::getStringLength()
+{
+ int size = 0;
+ std::vector<std::string>::iterator it;
+
+ for (it = strings.begin(); it != strings.end(); it++) {
+ size += it->length() + 1;
+ }
+
+ return size + 1;
+}
+
+int
+X86ISA::SMBios::SMBiosStructure::addString(string & newString)
+{
+ stringFields = true;
+ // If a string is empty, treat it as not existing. The index for empty
+ // strings is 0.
+ if (newString.length() == 0)
+ return 0;
+ strings.push_back(newString);
+ return strings.size();
+}
+
+string
+X86ISA::SMBios::SMBiosStructure::readString(int n)
+{
+ assert(n > 0 && n <= strings.size());
+ return strings[n - 1];
+}
+
+void
+X86ISA::SMBios::SMBiosStructure::setString(int n, std::string & newString)
+{
+ assert(n > 0 && n <= strings.size());
+ strings[n - 1] = newString;
+}
+
+X86ISA::SMBios::BiosInformation::BiosInformation(Params * p) :
+ SMBiosStructure(p, Type),
+ startingAddrSegment(p->starting_addr_segment),
+ romSize(p->rom_size),
+ majorVer(p->major), minorVer(p->minor),
+ embContFirmwareMajor(p->emb_cont_firmware_major),
+ embContFirmwareMinor(p->emb_cont_firmware_minor)
+ {
+ vendor = addString(p->vendor);
+ version = addString(p->version);
+ releaseDate = addString(p->release_date);
+
+ characteristics = composeBitVector(p->characteristics);
+ characteristicExtBytes =
+ composeBitVector(p->characteristic_ext_bytes);
+ }
+
uint16_t
X86ISA::SMBios::BiosInformation::writeOut(FunctionalPort * port, Addr addr)
{
@@ -122,8 +237,8 @@ X86ISA::SMBios::BiosInformation::writeOut(FunctionalPort * port, Addr addr)
X86ISA::htog(characteristicExtBytes);
port->writeBlob(addr + 0x12, (uint8_t *)(&characteristicExtBytesGuest), 2);
- port->writeBlob(addr + 0x14, (uint8_t *)(&major), 1);
- port->writeBlob(addr + 0x15, (uint8_t *)(&minor), 1);
+ port->writeBlob(addr + 0x14, (uint8_t *)(&majorVer), 1);
+ port->writeBlob(addr + 0x15, (uint8_t *)(&minorVer), 1);
port->writeBlob(addr + 0x16, (uint8_t *)(&embContFirmwareMajor), 1);
port->writeBlob(addr + 0x17, (uint8_t *)(&embContFirmwareMinor), 1);
@@ -132,9 +247,22 @@ X86ISA::SMBios::BiosInformation::writeOut(FunctionalPort * port, Addr addr)
return size;
}
+X86ISA::SMBios::SMBiosTable::SMBiosTable(Params * p) :
+ SimObject(p), structures(p->structures)
+{
+ smbiosHeader.majorVersion = p->major_version;
+ smbiosHeader.minorVersion = p->minor_version;
+ assert(p->major_version <= 9);
+ assert(p->minor_version <= 9);
+ smbiosHeader.intermediateHeader.smbiosBCDRevision =
+ (p->major_version << 4) | p->minor_version;
+}
+
void
-X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr)
+X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr,
+ Addr &headerSize, Addr &structSize)
{
+ headerSize = 0x1F;
/*
* The main header
@@ -205,14 +333,16 @@ X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr)
Addr base = smbiosHeader.intermediateHeader.tableAddr;
Addr offset = 0;
uint16_t maxSize = 0;
- std::vector<SMBiosStructure>::iterator it;
+ std::vector<SMBiosStructure *>::iterator it;
for (it = structures.begin(); it != structures.end(); it++) {
- uint16_t size = it->writeOut(port, base + offset);
+ uint16_t size = (*it)->writeOut(port, base + offset);
if (size > maxSize)
maxSize = size;
offset += size;
}
+ structSize = offset;
+
/*
* Header
*/
@@ -243,3 +373,15 @@ X86ISA::SMBios::SMBiosTable::writeOut(FunctionalPort * port, Addr addr)
intChecksum = -intChecksum;
port->writeBlob(addr + 0x15, (uint8_t *)(&intChecksum), 1);
}
+
+X86ISA::SMBios::BiosInformation *
+X86SMBiosBiosInformationParams::create()
+{
+ return new X86ISA::SMBios::BiosInformation(this);
+}
+
+X86ISA::SMBios::SMBiosTable *
+X86SMBiosSMBiosTableParams::create()
+{
+ return new X86ISA::SMBios::SMBiosTable(this);
+}
diff --git a/src/arch/x86/smbios.hh b/src/arch/x86/bios/smbios.hh
index c126de220..1c50d0b48 100644
--- a/src/arch/x86/smbios.hh
+++ b/src/arch/x86/bios/smbios.hh
@@ -85,16 +85,21 @@
* Authors: Gabe Black
*/
-#ifndef __ARCH_X86_SMBIOS_HH__
-#define __ARCH_X86_SMBIOS_HH__
+#ifndef __ARCH_X86_BIOS_SMBIOS_HH__
+#define __ARCH_X86_BIOS_SMBIOS_HH__
#include <string>
#include <vector>
-#include "arch/x86/isa_traits.hh"
-#include "mem/port.hh"
-#include "sim/byteswap.hh"
+#include "enums/Characteristic.hh"
+#include "enums/ExtCharacteristic.hh"
#include "sim/host.hh"
+#include "sim/sim_object.hh"
+
+class FunctionalPort;
+class X86SMBiosBiosInformationParams;
+class X86SMBiosSMBiosStructureParams;
+class X86SMBiosSMBiosTableParams;
namespace X86ISA
{
@@ -102,8 +107,11 @@ namespace X86ISA
namespace SMBios
{
-class SMBiosStructure
+class SMBiosStructure : public SimObject
{
+ protected:
+ typedef X86SMBiosSMBiosStructureParams Params;
+
public:
virtual
@@ -126,73 +134,33 @@ class SMBiosStructure
return 4;
}
- virtual uint16_t
- writeOut(FunctionalPort * port, Addr addr)
- {
- port->writeBlob(addr, (uint8_t *)(&type), 1);
-
- uint8_t length = getLength();
- port->writeBlob(addr + 1, (uint8_t *)(&length), 1);
-
- uint16_t handleGuest = X86ISA::htog(handle);
- port->writeBlob(addr + 2, (uint8_t *)(&handleGuest), 2);
-
- return length + getStringLength();
- }
+ virtual uint16_t writeOut(FunctionalPort * port, Addr addr);
protected:
- std::vector<std::string> strings;
-
- void writeOutStrings(FunctionalPort * port, Addr addr)
- {
- std::vector<std::string>::iterator it;
- Addr offset = 0;
-
- for (it = strings.begin(); it != strings.end(); it++) {
- port->writeBlob(addr + offset,
- (uint8_t *)it->c_str(), it->length() + 1);
- offset += it->length() + 1;
- }
+ bool stringFields;
- const uint8_t nullTerminator = 0;
- port->writeBlob(addr + offset, (uint8_t *)(&nullTerminator), 1);
- }
+ SMBiosStructure(Params * p, uint8_t _type);
- int getStringLength()
- {
- int size = 0;
- std::vector<std::string>::iterator it;
+ std::vector<std::string> strings;
- for (it = strings.begin(); it != strings.end(); it++) {
- size += it->length() + 1;
- }
+ void writeOutStrings(FunctionalPort * port, Addr addr);
- return size + 1;
- }
+ int getStringLength();
public:
- int addString(std::string & newString)
- {
- strings.push_back(newString);
- return strings.size();
- }
-
- std::string readString(int n)
- {
- assert(n > 0 && n <= strings.size());
- return strings[n - 1];
- }
-
- void setString(int n, std::string & newString)
- {
- assert(n > 0 && n <= strings.size());
- strings[n - 1] = newString;
- }
+ int addString(std::string & newString);
+ std::string readString(int n);
+ void setString(int n, std::string & newString);
};
class BiosInformation : public SMBiosStructure
{
+ protected:
+ const static uint8_t Type = 0;
+
+ typedef X86SMBiosBiosInformationParams Params;
+
public:
// Offset 04h, 1 byte
uint8_t vendor;
@@ -211,21 +179,25 @@ class BiosInformation : public SMBiosStructure
// Offset 12h, 2 bytes
uint16_t characteristicExtBytes;
// Offset 14h, 1 byte
- uint8_t major;
+ uint8_t majorVer;
// Offset 15h, 1 byte
- uint8_t minor;
+ uint8_t minorVer;
// Offset 16h, 1 byte
uint8_t embContFirmwareMajor;
// Offset 17h, 1 byte
uint8_t embContFirmwareMinor;
+ BiosInformation(Params * p);
+
uint8_t getLength() { return 0x18; }
uint16_t writeOut(FunctionalPort * port, Addr addr);
};
-class SMBiosTable
+class SMBiosTable : public SimObject
{
- public:
+ protected:
+ typedef X86SMBiosSMBiosTableParams Params;
+
struct SMBiosHeader
{
SMBiosHeader()
@@ -281,9 +253,23 @@ class SMBiosTable
} intermediateHeader;
} smbiosHeader;
- void writeOut(FunctionalPort * port, Addr addr);
+ std::vector<SMBiosStructure *> structures;
+
+ public:
+ SMBiosTable(Params * p);
+
+ Addr getTableAddr()
+ {
+ return smbiosHeader.intermediateHeader.tableAddr;
+ }
+
+ void setTableAddr(Addr addr)
+ {
+ smbiosHeader.intermediateHeader.tableAddr = addr;
+ }
- std::vector<SMBiosStructure> structures;
+ void writeOut(FunctionalPort * port, Addr addr,
+ Addr &headerSize, Addr &structSize);
};
} //SMBios
diff --git a/src/arch/x86/cpuid.cc b/src/arch/x86/cpuid.cc
new file mode 100644
index 000000000..247965df4
--- /dev/null
+++ b/src/arch/x86/cpuid.cc
@@ -0,0 +1,160 @@
+/*
+ * 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/x86/cpuid.hh"
+#include "base/bitfield.hh"
+#include "cpu/thread_context.hh"
+
+namespace X86ISA {
+ enum StandardCpuidFunction {
+ VendorAndLargestStdFunc,
+ FamilyModelStepping,
+ NumStandardCpuidFuncs
+ };
+
+ enum ExtendedCpuidFunctions {
+ VendorAndLargestExtFunc,
+ FamilyModelSteppingBrandFeatures,
+ NameString1,
+ NameString2,
+ NameString3,
+ L1CacheAndTLB,
+ L2L3CacheAndL2TLB,
+ APMInfo,
+
+ /*
+ * The following are defined by the spec but not yet implemented
+ */
+/* LongModeAddressSize,
+ // Function 9 is reserved
+ SVMInfo = 10,
+ // Functions 11-24 are reserved
+ TLB1GBPageInfo = 25,
+ PerformanceInfo,*/
+
+ NumExtendedCpuidFuncs
+ };
+
+ static const int vendorStringSize = 13;
+ static const char vendorString[vendorStringSize] = "AuthenticAMD";
+ static const int nameStringSize = 48;
+ static const char nameString[nameStringSize] = "Fake M5 x86_64 CPU";
+
+ uint64_t
+ stringToRegister(const char *str)
+ {
+ uint64_t reg = 0;
+ for (int pos = 3; pos >=0; pos--) {
+ reg <<= 8;
+ reg |= str[pos];
+ }
+ return reg;
+ }
+
+ bool
+ doCpuid(ThreadContext * tc, uint32_t function, CpuidResult &result)
+ {
+ uint16_t family = bits(function, 31, 16);
+ uint16_t funcNum = bits(function, 15, 0);
+ if (family == 0x8000) {
+ // The extended functions
+ switch (funcNum) {
+ case VendorAndLargestExtFunc:
+ assert(vendorStringSize >= 12);
+ result = CpuidResult(
+ NumExtendedCpuidFuncs - 1,
+ stringToRegister(vendorString),
+ stringToRegister(vendorString + 4),
+ stringToRegister(vendorString + 8));
+ break;
+ case FamilyModelSteppingBrandFeatures:
+ result = CpuidResult(0x00020f51, 0x00000405,
+ 0xe3d3fbff, 0x00000001);
+ break;
+ case NameString1:
+ case NameString2:
+ case NameString3:
+ {
+ // Zero fill anything beyond the end of the string. This
+ // should go away once the string is a vetted parameter.
+ char cleanName[nameStringSize];
+ memset(cleanName, '\0', nameStringSize);
+ strncpy(cleanName, nameString, nameStringSize);
+
+ int offset = (funcNum - NameString1) * 16;
+ assert(nameStringSize >= offset + 16);
+ result = CpuidResult(
+ stringToRegister(cleanName + offset + 0),
+ stringToRegister(cleanName + offset + 4),
+ stringToRegister(cleanName + offset + 8),
+ stringToRegister(cleanName + offset + 12));
+ }
+ break;
+ case L1CacheAndTLB:
+ result = CpuidResult(0xff08ff08, 0xff20ff20,
+ 0x40020140, 0x40020140);
+ break;
+ case L2L3CacheAndL2TLB:
+ result = CpuidResult(0x00000000, 0x42004200,
+ 0x00000000, 0x04008140);
+ break;
+ case APMInfo:
+ result = CpuidResult(0x80000018, 0x68747541,
+ 0x69746e65, 0x444d4163);
+ break;
+/* case LongModeAddressSize:
+ case SVMInfo:
+ case TLB1GBPageInfo:
+ case PerformanceInfo:*/
+ default:
+ return false;
+ }
+ } else if(family == 0x0000) {
+ // The standard functions
+ switch (funcNum) {
+ case VendorAndLargestStdFunc:
+ assert(vendorStringSize >= 12);
+ result = CpuidResult(
+ NumStandardCpuidFuncs - 1,
+ stringToRegister(vendorString),
+ stringToRegister(vendorString + 4),
+ stringToRegister(vendorString + 8));
+ break;
+ case FamilyModelStepping:
+ result = CpuidResult(0x00020f51, 0000000405,
+ 0xe3d3fbff, 0x00000001);
+ break;
+ default:
+ return false;
+ }
+ }
+ return true;
+ }
+} //namespace X86ISA
diff --git a/src/arch/x86/cpuid.hh b/src/arch/x86/cpuid.hh
new file mode 100644
index 000000000..5cb4c7972
--- /dev/null
+++ b/src/arch/x86/cpuid.hh
@@ -0,0 +1,61 @@
+/*
+ * 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_CPUID_HH__
+#define __ARCH_X86_CPUID_HH__
+
+#include <inttypes.h>
+
+class ThreadContext;
+
+namespace X86ISA
+{
+ struct CpuidResult
+ {
+ uint64_t rax;
+ uint64_t rbx;
+ uint64_t rcx;
+ uint64_t rdx;
+
+ // These are not in alphebetical order on purpose. The order reflects
+ // how the CPUID orders the registers when it returns results.
+ CpuidResult(uint64_t _rax, uint64_t _rbx,
+ uint64_t _rdx, uint64_t _rcx) :
+ rax(_rax), rbx(_rbx), rcx(_rcx), rdx(_rdx)
+ {}
+
+ CpuidResult()
+ {}
+ };
+
+ bool doCpuid(ThreadContext * tc, uint32_t function, CpuidResult &result);
+} // namespace X86ISA
+
+#endif
diff --git a/src/arch/x86/emulenv.cc b/src/arch/x86/emulenv.cc
index 31b705d79..0d7b32130 100644
--- a/src/arch/x86/emulenv.cc
+++ b/src/arch/x86/emulenv.cc
@@ -55,6 +55,8 @@
* Authors: Gabe Black
*/
+#include <cassert>
+
#include "arch/x86/emulenv.hh"
#include "base/misc.hh"
@@ -91,7 +93,7 @@ void EmulEnv::doModRM(const ExtMachInst & machInst)
//Figure out what segment to use. This won't be entirely accurate since
//the presence of a displacement is supposed to make the instruction
//default to the data segment.
- if (base != INTREG_RBP && base != INTREG_RSP ||
+ if ((base != INTREG_RBP && base != INTREG_RSP) ||
0/*Has an immediate offset*/) {
seg = SEGMENT_REG_DS;
//Handle any segment override that might have been in the instruction
@@ -103,3 +105,11 @@ void EmulEnv::doModRM(const ExtMachInst & machInst)
}
}
+void EmulEnv::setSeg(const ExtMachInst & machInst)
+{
+ seg = SEGMENT_REG_DS;
+ //Handle any segment override that might have been in the instruction
+ int segFromInst = machInst.legacy.seg;
+ if (segFromInst)
+ seg = (SegmentRegIndex)(segFromInst - 1);
+}
diff --git a/src/arch/x86/emulenv.hh b/src/arch/x86/emulenv.hh
index 1044dbdf9..cdb1bf863 100644
--- a/src/arch/x86/emulenv.hh
+++ b/src/arch/x86/emulenv.hh
@@ -86,6 +86,7 @@ namespace X86ISA
{;}
void doModRM(const ExtMachInst & machInst);
+ void setSeg(const ExtMachInst & machInst);
};
};
diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc
index 1c94a1251..b81400cc3 100644
--- a/src/arch/x86/faults.cc
+++ b/src/arch/x86/faults.cc
@@ -85,6 +85,7 @@
* Authors: Gabe Black
*/
+#include "arch/x86/decoder.hh"
#include "arch/x86/faults.hh"
#include "base/trace.hh"
#include "config/full_system.hh"
@@ -100,71 +101,90 @@
namespace X86ISA
{
#if FULL_SYSTEM
- void X86Trap::invoke(ThreadContext * tc)
+ void X86FaultBase::invoke(ThreadContext * tc)
{
- panic("X86 faults are not implemented!");
+ Addr pc = tc->readPC();
+ DPRINTF(Faults, "RIP %#x: vector %d: %s\n", pc, vector, describe());
+ using namespace X86ISAInst::RomLabels;
+ HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
+ MicroPC entry;
+ if (m5reg.mode == LongMode) {
+ if (isSoft()) {
+ entry = extern_label_longModeSoftInterrupt;
+ } else {
+ entry = extern_label_longModeInterrupt;
+ }
+ } else {
+ entry = extern_label_legacyModeInterrupt;
+ }
+ tc->setIntReg(INTREG_MICRO(1), vector);
+ tc->setIntReg(INTREG_MICRO(7), pc);
+ if (errorCode != (uint64_t)(-1)) {
+ if (m5reg.mode == LongMode) {
+ entry = extern_label_longModeInterruptWithError;
+ } else {
+ panic("Legacy mode interrupts with error codes "
+ "aren't implementde.\n");
+ }
+ // Software interrupts shouldn't have error codes. If one does,
+ // there would need to be microcode to set it up.
+ assert(!isSoft());
+ tc->setIntReg(INTREG_MICRO(15), errorCode);
+ }
+ tc->setMicroPC(romMicroPC(entry));
+ tc->setNextMicroPC(romMicroPC(entry) + 1);
}
- void X86Abort::invoke(ThreadContext * tc)
+ std::string
+ X86FaultBase::describe() const
{
- panic("X86 faults are not implemented!");
- }
+ std::stringstream ss;
+ ccprintf(ss, "%s", mnemonic());
+ if (errorCode != (uint64_t)(-1)) {
+ ccprintf(ss, "(%#x)", errorCode);
+ }
- void X86Interrupt::invoke(ThreadContext * tc)
- {
- panic("X86 faults are not implemented!");
+ return ss.str();
}
-
- void FakeITLBFault::invoke(ThreadContext * tc)
+
+ void X86Trap::invoke(ThreadContext * tc)
{
- // Start the page table walker.
- tc->getITBPtr()->walk(tc, vaddr);
+ X86FaultBase::invoke(tc);
+ // This is the same as a fault, but it happens -after- the instruction.
+ tc->setPC(tc->readNextPC());
+ tc->setNextPC(tc->readNextNPC());
+ tc->setNextNPC(tc->readNextNPC() + sizeof(MachInst));
}
- void FakeDTLBFault::invoke(ThreadContext * tc)
+ void X86Abort::invoke(ThreadContext * tc)
{
- // Start the page table walker.
- tc->getDTBPtr()->walk(tc, vaddr);
+ panic("Abort exception!");
}
-#else // !FULL_SYSTEM
- void FakeITLBFault::invoke(ThreadContext * tc)
+ void PageFault::invoke(ThreadContext * tc)
{
- DPRINTF(TLB, "Invoking an ITLB fault for address %#x at pc %#x.\n",
- vaddr, tc->readPC());
- Process *p = tc->getProcessPtr();
- TlbEntry entry;
- bool success = p->pTable->lookup(vaddr, entry);
- if(!success) {
- panic("Tried to execute unmapped address %#x.\n", vaddr);
+ HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
+ X86FaultBase::invoke(tc);
+ /*
+ * If something bad happens while trying to enter the page fault
+ * handler, I'm pretty sure that's a double fault and then all bets are
+ * off. That means it should be safe to update this state now.
+ */
+ if (m5reg.mode == LongMode) {
+ tc->setMiscReg(MISCREG_CR2, addr);
} else {
- Addr alignedVaddr = p->pTable->pageAlign(vaddr);
- DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr,
- entry.pageStart());
- tc->getITBPtr()->insert(alignedVaddr, entry);
+ tc->setMiscReg(MISCREG_CR2, (uint32_t)addr);
}
}
- void FakeDTLBFault::invoke(ThreadContext * tc)
+ std::string
+ PageFault::describe() const
{
- DPRINTF(TLB, "Invoking an DTLB fault for address %#x at pc %#x.\n",
- vaddr, tc->readPC());
- Process *p = tc->getProcessPtr();
- TlbEntry entry;
- bool success = p->pTable->lookup(vaddr, entry);
- if(!success) {
- p->checkAndAllocNextPage(vaddr);
- success = p->pTable->lookup(vaddr, entry);
- }
- if(!success) {
- panic("Tried to access unmapped address %#x.\n", vaddr);
- } else {
- Addr alignedVaddr = p->pTable->pageAlign(vaddr);
- DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr,
- entry.pageStart());
- tc->getDTBPtr()->insert(alignedVaddr, entry);
- }
+ std::stringstream ss;
+ ccprintf(ss, "%s at %#x", X86FaultBase::describe(), addr);
+ return ss.str();
}
+
#endif
} // namespace X86ISA
diff --git a/src/arch/x86/faults.hh b/src/arch/x86/faults.hh
index 78a55d0e1..fe5132994 100644
--- a/src/arch/x86/faults.hh
+++ b/src/arch/x86/faults.hh
@@ -58,9 +58,12 @@
#ifndef __ARCH_X86_FAULTS_HH__
#define __ARCH_X86_FAULTS_HH__
+#include "base/bitunion.hh"
#include "base/misc.hh"
#include "sim/faults.hh"
+#include <string>
+
namespace X86ISA
{
// Base class for all x86 "faults" where faults is in the m5 sense
@@ -69,11 +72,13 @@ namespace X86ISA
protected:
const char * faultName;
const char * mnem;
+ uint8_t vector;
uint64_t errorCode;
X86FaultBase(const char * _faultName, const char * _mnem,
- uint64_t _errorCode = 0) :
- faultName(_faultName), mnem(_mnem), errorCode(_errorCode)
+ const uint8_t _vector, uint64_t _errorCode = (uint64_t)-1)
+ : faultName(_faultName), mnem(_mnem),
+ vector(_vector), errorCode(_errorCode)
{
}
@@ -91,6 +96,17 @@ namespace X86ISA
{
return mnem;
}
+
+ virtual bool isSoft()
+ {
+ return false;
+ }
+
+#if FULL_SYSTEM
+ void invoke(ThreadContext * tc);
+
+ virtual std::string describe() const;
+#endif
};
// Base class for x86 faults which behave as if the underlying instruction
@@ -99,8 +115,8 @@ namespace X86ISA
{
protected:
X86Fault(const char * name, const char * mnem,
- uint64_t _errorCode = 0) :
- X86FaultBase(name, mnem, _errorCode)
+ const uint8_t vector, uint64_t _errorCode = (uint64_t)-1)
+ : X86FaultBase(name, mnem, vector, _errorCode)
{}
};
@@ -110,8 +126,8 @@ namespace X86ISA
{
protected:
X86Trap(const char * name, const char * mnem,
- uint64_t _errorCode = 0) :
- X86FaultBase(name, mnem, _errorCode)
+ const uint8_t vector, uint64_t _errorCode = (uint64_t)-1)
+ : X86FaultBase(name, mnem, vector, _errorCode)
{}
#if FULL_SYSTEM
@@ -124,8 +140,8 @@ namespace X86ISA
{
protected:
X86Abort(const char * name, const char * mnem,
- uint64_t _errorCode = 0) :
- X86FaultBase(name, mnem, _errorCode)
+ const uint8_t vector, uint64_t _errorCode = (uint64_t)-1)
+ : X86FaultBase(name, mnem, vector, _errorCode)
{}
#if FULL_SYSTEM
@@ -138,13 +154,9 @@ namespace X86ISA
{
protected:
X86Interrupt(const char * name, const char * mnem,
- uint64_t _errorCode = 0) :
- X86FaultBase(name, mnem, _errorCode)
+ const uint8_t _vector, uint64_t _errorCode = (uint64_t)-1)
+ : X86FaultBase(name, mnem, _vector, _errorCode)
{}
-
-#if FULL_SYSTEM
- void invoke(ThreadContext * tc);
-#endif
};
class UnimpInstFault : public FaultBase
@@ -201,7 +213,7 @@ namespace X86ISA
{
public:
DivideByZero() :
- X86Fault("Divide-by-Zero-Error", "#DE")
+ X86Fault("Divide-by-Zero-Error", "#DE", 0)
{}
};
@@ -209,15 +221,15 @@ namespace X86ISA
{
public:
DebugException() :
- X86FaultBase("Debug", "#DB")
+ X86FaultBase("Debug", "#DB", 1)
{}
};
class NonMaskableInterrupt : public X86Interrupt
{
public:
- NonMaskableInterrupt() :
- X86Interrupt("Non-Maskable-Interrupt", "#NMI")
+ NonMaskableInterrupt(uint8_t _vector) :
+ X86Interrupt("Non Maskable Interrupt", "#NMI", 2, _vector)
{}
};
@@ -225,7 +237,7 @@ namespace X86ISA
{
public:
Breakpoint() :
- X86Trap("Breakpoint", "#BP")
+ X86Trap("Breakpoint", "#BP", 3)
{}
};
@@ -233,7 +245,7 @@ namespace X86ISA
{
public:
OverflowTrap() :
- X86Trap("Overflow", "#OF")
+ X86Trap("Overflow", "#OF", 4)
{}
};
@@ -241,7 +253,7 @@ namespace X86ISA
{
public:
BoundRange() :
- X86Fault("Bound-Range", "#BR")
+ X86Fault("Bound-Range", "#BR", 5)
{}
};
@@ -249,7 +261,7 @@ namespace X86ISA
{
public:
InvalidOpcode() :
- X86Fault("Invalid-Opcode", "#UD")
+ X86Fault("Invalid-Opcode", "#UD", 6)
{}
};
@@ -257,7 +269,7 @@ namespace X86ISA
{
public:
DeviceNotAvailable() :
- X86Fault("Device-Not-Available", "#NM")
+ X86Fault("Device-Not-Available", "#NM", 7)
{}
};
@@ -265,132 +277,156 @@ namespace X86ISA
{
public:
DoubleFault() :
- X86Abort("Double-Fault", "#DF")
+ X86Abort("Double-Fault", "#DF", 8, 0)
{}
};
class InvalidTSS : public X86Fault
{
public:
- InvalidTSS() :
- X86Fault("Invalid-TSS", "#TS")
+ InvalidTSS(uint32_t _errorCode) :
+ X86Fault("Invalid-TSS", "#TS", 10, _errorCode)
{}
};
class SegmentNotPresent : public X86Fault
{
public:
- SegmentNotPresent() :
- X86Fault("Segment-Not-Present", "#NP")
+ SegmentNotPresent(uint32_t _errorCode) :
+ X86Fault("Segment-Not-Present", "#NP", 11, _errorCode)
{}
};
class StackFault : public X86Fault
{
public:
- StackFault() :
- X86Fault("Stack", "#SS")
+ StackFault(uint32_t _errorCode) :
+ X86Fault("Stack", "#SS", 12, _errorCode)
{}
};
class GeneralProtection : public X86Fault
{
public:
- GeneralProtection(uint64_t _errorCode) :
- X86Fault("General-Protection", "#GP", _errorCode)
+ GeneralProtection(uint32_t _errorCode) :
+ X86Fault("General-Protection", "#GP", 13, _errorCode)
{}
};
class PageFault : public X86Fault
{
+ protected:
+ BitUnion32(PageFaultErrorCode)
+ Bitfield<0> present;
+ Bitfield<1> write;
+ Bitfield<2> user;
+ Bitfield<3> reserved;
+ Bitfield<4> fetch;
+ EndBitUnion(PageFaultErrorCode)
+
+ Addr addr;
+
public:
- PageFault() :
- X86Fault("Page-Fault", "#PF")
+ PageFault(Addr _addr, uint32_t _errorCode) :
+ X86Fault("Page-Fault", "#PF", 14, _errorCode), addr(_addr)
{}
+
+ PageFault(Addr _addr, bool present, bool write,
+ bool user, bool reserved, bool fetch) :
+ X86Fault("Page-Fault", "#PF", 14, 0), addr(_addr)
+ {
+ PageFaultErrorCode code = 0;
+ code.present = present;
+ code.write = write;
+ code.user = user;
+ code.reserved = reserved;
+ code.fetch = fetch;
+ errorCode = code;
+ }
+
+#if FULL_SYSTEM
+ void invoke(ThreadContext * tc);
+
+ virtual std::string describe() const;
+#endif
};
class X87FpExceptionPending : public X86Fault
{
public:
X87FpExceptionPending() :
- X86Fault("x87 Floating-Point Exception Pending", "#MF")
+ X86Fault("x87 Floating-Point Exception Pending", "#MF", 16)
{}
};
- class AlignmentCheck : X86Fault
+ class AlignmentCheck : public X86Fault
{
public:
AlignmentCheck() :
- X86Fault("Alignment-Check", "#AC")
+ X86Fault("Alignment-Check", "#AC", 17, 0)
{}
};
- class MachineCheck : X86Abort
+ class MachineCheck : public X86Abort
{
public:
MachineCheck() :
- X86Abort("Machine-Check", "#MC")
+ X86Abort("Machine-Check", "#MC", 18)
{}
};
- class SIMDFloatingPointFault : X86Fault
+ class SIMDFloatingPointFault : public X86Fault
{
public:
SIMDFloatingPointFault() :
- X86Fault("SIMD Floating-Point", "#XF")
+ X86Fault("SIMD Floating-Point", "#XF", 19)
{}
};
- class SecurityException : X86FaultBase
+ class SecurityException : public X86FaultBase
{
public:
SecurityException() :
- X86FaultBase("Security Exception", "#SX")
+ X86FaultBase("Security Exception", "#SX", 30)
{}
};
- class ExternalInterrupt : X86Interrupt
+ class ExternalInterrupt : public X86Interrupt
{
public:
- ExternalInterrupt() :
- X86Interrupt("External Interrupt", "#INTR")
+ ExternalInterrupt(uint8_t _vector) :
+ X86Interrupt("External Interrupt", "#INTR", _vector)
{}
};
- class SoftwareInterrupt : X86Interrupt
+ class SystemManagementInterrupt : public X86Interrupt
{
public:
- SoftwareInterrupt() :
- X86Interrupt("Software Interrupt", "INTn")
+ SystemManagementInterrupt() :
+ X86Interrupt("System Management Interrupt", "#SMI", 0)
{}
};
- // These faults aren't part of the ISA definition. They trigger filling
- // the tlb on a miss and are to take the place of a hardware table walker.
- class FakeITLBFault : public X86Fault
+ class InitInterrupt : public X86Interrupt
{
- protected:
- Addr vaddr;
+ uint8_t vector;
public:
- FakeITLBFault(Addr _vaddr) :
- X86Fault("fake instruction tlb fault", "itlb"),
- vaddr(_vaddr)
+ InitInterrupt(uint8_t _vector) :
+ X86Interrupt("INIT Interrupt", "#INIT", _vector)
{}
-
- void invoke(ThreadContext * tc);
};
- class FakeDTLBFault : public X86Fault
+ class SoftwareInterrupt : public X86Interrupt
{
- protected:
- Addr vaddr;
public:
- FakeDTLBFault(Addr _vaddr) :
- X86Fault("fake data tlb fault", "dtlb"),
- vaddr(_vaddr)
+ SoftwareInterrupt(uint8_t _vector) :
+ X86Interrupt("Software Interrupt", "#INTR", _vector)
{}
- void invoke(ThreadContext * tc);
+ bool isSoft()
+ {
+ return true;
+ }
};
};
diff --git a/src/arch/x86/floatregfile.cc b/src/arch/x86/floatregfile.cc
index 1c49ea9c6..fce7f4868 100644
--- a/src/arch/x86/floatregfile.cc
+++ b/src/arch/x86/floatregfile.cc
@@ -96,15 +96,6 @@ using namespace std;
class Checkpoint;
-string X86ISA::getFloatRegName(RegIndex index)
-{
- static std::string floatRegName[NumFloatRegs] =
- {"mmx0", "mmx1", "mmx2", "mmx3", "mmx4", "mmx5", "mmx6", "mmx7",
- "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
- "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"};
- return floatRegName[index];
-}
-
void FloatRegFile::clear()
{
memset(q, 0, sizeof(FloatReg) * NumFloatRegs);
@@ -113,27 +104,27 @@ void FloatRegFile::clear()
FloatReg FloatRegFile::readReg(int floatReg, int width)
{
FloatReg reg = d[floatReg];
- DPRINTF(X86, "Reading %f from register %d.\n", reg, floatReg);
+ DPRINTF(FloatRegs, "Reading %f from register %d.\n", reg, floatReg);
return reg;
}
FloatRegBits FloatRegFile::readRegBits(int floatReg, int width)
{
FloatRegBits reg = q[floatReg];
- DPRINTF(X86, "Reading %#x from register %d.\n", reg, floatReg);
+ DPRINTF(FloatRegs, "Reading %#x from register %d.\n", reg, floatReg);
return reg;
}
Fault FloatRegFile::setReg(int floatReg, const FloatReg &val, int width)
{
- DPRINTF(X86, "Writing %f to register %d.\n", val, floatReg);
+ DPRINTF(FloatRegs, "Writing %f to register %d.\n", val, floatReg);
d[floatReg] = val;
return NoFault;
}
Fault FloatRegFile::setRegBits(int floatReg, const FloatRegBits &val, int width)
{
- DPRINTF(X86, "Writing bits %#x to register %d.\n", val, floatReg);
+ DPRINTF(FloatRegs, "Writing bits %#x to register %d.\n", val, floatReg);
q[floatReg] = val;
return NoFault;
}
diff --git a/src/arch/x86/floatregfile.hh b/src/arch/x86/floatregfile.hh
index b77ddb0eb..ab239dd7d 100644
--- a/src/arch/x86/floatregfile.hh
+++ b/src/arch/x86/floatregfile.hh
@@ -98,8 +98,6 @@ class Checkpoint;
namespace X86ISA
{
- std::string getFloatRegName(RegIndex);
-
//Each 128 bit xmm register is broken into two effective 64 bit registers.
const int NumFloatRegs =
NumMMXRegs + 2 * NumXMMRegs + NumMicroFpRegs;
diff --git a/src/arch/x86/insts/macroop.hh b/src/arch/x86/insts/macroop.hh
new file mode 100644
index 000000000..d6925a1a5
--- /dev/null
+++ b/src/arch/x86/insts/macroop.hh
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2007 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
+ */
+
+#ifndef __ARCH_X86_INSTS_MACROOP_HH__
+#define __ARCH_X86_INSTS_MACROOP_HH__
+
+#include "arch/x86/emulenv.hh"
+#include "arch/x86/types.hh"
+#include "arch/x86/insts/static_inst.hh"
+
+namespace X86ISA
+{
+// Base class for combinationally generated macroops
+class MacroopBase : public X86StaticInst
+{
+ protected:
+ const char *macrocodeBlock;
+
+ const uint32_t numMicroops;
+ X86ISA::EmulEnv env;
+
+ //Constructor.
+ MacroopBase(const char *mnem, ExtMachInst _machInst,
+ uint32_t _numMicroops, X86ISA::EmulEnv _env) :
+ X86StaticInst(mnem, _machInst, No_OpClass),
+ numMicroops(_numMicroops), env(_env)
+ {
+ assert(numMicroops);
+ microops = new StaticInstPtr[numMicroops];
+ flags[IsMacroop] = true;
+ }
+
+ ~MacroopBase()
+ {
+ delete [] microops;
+ }
+
+ StaticInstPtr * microops;
+
+ StaticInstPtr fetchMicroop(MicroPC microPC)
+ {
+ assert(microPC < numMicroops);
+ return microops[microPC];
+ }
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const
+ {
+ return mnemonic;
+ }
+
+ public:
+ ExtMachInst
+ getExtMachInst()
+ {
+ return machInst;
+ }
+
+ X86ISA::EmulEnv
+ getEmulEnv()
+ {
+ return env;
+ }
+};
+}
+
+#endif //__ARCH_X86_INSTS_MACROOP_HH__
diff --git a/src/arch/x86/insts/microldstop.cc b/src/arch/x86/insts/microldstop.cc
index 9638a2ae3..7cc6a330f 100644
--- a/src/arch/x86/insts/microldstop.cc
+++ b/src/arch/x86/insts/microldstop.cc
@@ -64,7 +64,6 @@ namespace X86ISA
const SymbolTable *symtab) const
{
std::stringstream response;
- bool someAddr = false;
printMnemonic(response, instMnem, mnemonic);
if(flags[IsLoad])
@@ -72,32 +71,8 @@ namespace X86ISA
else
printSrcReg(response, 2, dataSize);
response << ", ";
- printSegment(response, segment);
- response << ":[";
- if(scale != 0 && _srcRegIdx[0] != ZeroReg)
- {
- if(scale != 1)
- ccprintf(response, "%d*", scale);
- printSrcReg(response, 0, addressSize);
- someAddr = true;
- }
- if(_srcRegIdx[1] != ZeroReg)
- {
- if(someAddr)
- response << " + ";
- printSrcReg(response, 1, addressSize);
- someAddr = true;
- }
- if(disp != 0)
- {
- if(someAddr)
- response << " + ";
- ccprintf(response, "%#x", disp);
- someAddr = true;
- }
- if(!someAddr)
- response << "0";
- response << "]";
+ printMem(response, segment, scale, index, base, disp,
+ addressSize, false);
return response.str();
}
}
diff --git a/src/arch/x86/insts/microldstop.hh b/src/arch/x86/insts/microldstop.hh
index 5b1210d69..1774454c3 100644
--- a/src/arch/x86/insts/microldstop.hh
+++ b/src/arch/x86/insts/microldstop.hh
@@ -59,9 +59,18 @@
#define __ARCH_X86_INSTS_MICROLDSTOP_HH__
#include "arch/x86/insts/microop.hh"
+#include "mem/packet.hh"
+#include "mem/request.hh"
namespace X86ISA
{
+ static const Request::FlagsType SegmentFlagMask = mask(4);
+ static const int FlagShift = 4;
+ enum FlagBit {
+ CPL0FlagBit = 1,
+ AddrSizeFlagBit = 2
+ };
+
/**
* Base class for load and store ops
*/
@@ -76,6 +85,7 @@ namespace X86ISA
const RegIndex data;
const uint8_t dataSize;
const uint8_t addressSize;
+ const Request::FlagsType memFlags;
RegIndex foldOBit, foldABit;
//Constructor
@@ -86,13 +96,15 @@ namespace X86ISA
uint64_t _disp, uint8_t _segment,
RegIndex _data,
uint8_t _dataSize, uint8_t _addressSize,
+ Request::FlagsType _memFlags,
OpClass __opClass) :
X86MicroopBase(machInst, mnem, _instMnem,
isMicro, isDelayed, isFirst, isLast, __opClass),
scale(_scale), index(_index), base(_base),
disp(_disp), segment(_segment),
data(_data),
- dataSize(_dataSize), addressSize(_addressSize)
+ dataSize(_dataSize), addressSize(_addressSize),
+ memFlags(_memFlags | _segment)
{
foldOBit = (dataSize == 1 && !_machInst.rex.present) ? 1 << 6 : 0;
foldABit =
@@ -149,6 +161,25 @@ namespace X86ISA
}
return fault;
}
+
+ uint64_t
+ get(PacketPtr pkt) const
+ {
+ switch(dataSize)
+ {
+ case 1:
+ return pkt->get<uint8_t>();
+ case 2:
+ return pkt->get<uint16_t>();
+ case 4:
+ return pkt->get<uint32_t>();
+ case 8:
+ return pkt->get<uint64_t>();
+ default:
+ panic("Bad operand size %d for read at %#x.\n",
+ dataSize, pkt->getAddr());
+ }
+ }
};
}
diff --git a/src/arch/x86/insts/microop.cc b/src/arch/x86/insts/microop.cc
index 494c0b303..c7bfc3703 100644
--- a/src/arch/x86/insts/microop.cc
+++ b/src/arch/x86/insts/microop.cc
@@ -98,7 +98,7 @@ namespace X86ISA
case ConditionTests::SxOF:
return ccflags.sf ^ ccflags.of;
case ConditionTests::SxOvZF:
- return ccflags.sf ^ ccflags.of | ccflags.zf;
+ return (ccflags.sf ^ ccflags.of) | ccflags.zf;
case ConditionTests::False:
return false;
case ConditionTests::NotECF:
@@ -131,7 +131,7 @@ namespace X86ISA
case ConditionTests::NotSxOF:
return !(ccflags.sf ^ ccflags.of);
case ConditionTests::NotSxOvZF:
- return !(ccflags.sf ^ ccflags.of | ccflags.zf);
+ return !((ccflags.sf ^ ccflags.of) | ccflags.zf);
}
panic("Unknown condition: %d\n", condition);
return true;
diff --git a/src/arch/x86/insts/microregop.cc b/src/arch/x86/insts/microregop.cc
index 080926627..2ea975746 100644
--- a/src/arch/x86/insts/microregop.cc
+++ b/src/arch/x86/insts/microregop.cc
@@ -67,6 +67,9 @@ namespace X86ISA
bool subtract) const
{
DPRINTF(X86, "flagMask = %#x\n", flagMask);
+ if (_destRegIdx[0] & (1 << 6)) {
+ _dest >>= 8;
+ }
uint64_t flags = oldFlags & ~flagMask;
if(flagMask & (ECFBit | CFBit))
{
diff --git a/src/arch/x86/insts/static_inst.cc b/src/arch/x86/insts/static_inst.cc
index 0c1508d5a..f4ed44603 100644
--- a/src/arch/x86/insts/static_inst.cc
+++ b/src/arch/x86/insts/static_inst.cc
@@ -63,13 +63,13 @@ namespace X86ISA
void X86StaticInst::printMnemonic(std::ostream &os,
const char * mnemonic) const
{
- ccprintf(os, "\t%s ", mnemonic);
+ ccprintf(os, " %s ", mnemonic);
}
void X86StaticInst::printMnemonic(std::ostream &os,
const char * instMnemonic, const char * mnemonic) const
{
- ccprintf(os, "\t%s : %s ", instMnemonic, mnemonic);
+ ccprintf(os, " %s : %s ", instMnemonic, mnemonic);
}
void X86StaticInst::printSegment(std::ostream &os, int segment) const
@@ -240,6 +240,44 @@ namespace X86ISA
}
}
+ void X86StaticInst::printMem(std::ostream &os, uint8_t segment,
+ uint8_t scale, RegIndex index, RegIndex base,
+ uint64_t disp, uint8_t addressSize, bool rip) const
+ {
+ bool someAddr = false;
+ printSegment(os, segment);
+ os << ":[";
+ if (rip) {
+ os << "rip";
+ someAddr = true;
+ } else {
+ if (scale != 0 && index != ZeroReg)
+ {
+ if(scale != 1)
+ ccprintf(os, "%d*", scale);
+ printReg(os, index, addressSize);
+ someAddr = true;
+ }
+ if (base != ZeroReg)
+ {
+ if(someAddr)
+ os << " + ";
+ printReg(os, base, addressSize);
+ someAddr = true;
+ }
+ }
+ if (disp != 0)
+ {
+ if(someAddr)
+ os << " + ";
+ ccprintf(os, "%#x", disp);
+ someAddr = true;
+ }
+ if (!someAddr)
+ os << "0";
+ os << "]";
+ }
+
std::string X86StaticInst::generateDisassembly(Addr pc,
const SymbolTable *symtab) const
{
diff --git a/src/arch/x86/insts/static_inst.hh b/src/arch/x86/insts/static_inst.hh
index e5c333e75..8480f2713 100644
--- a/src/arch/x86/insts/static_inst.hh
+++ b/src/arch/x86/insts/static_inst.hh
@@ -89,6 +89,9 @@ namespace X86ISA
void printReg(std::ostream &os, int reg, int size) const;
void printSrcReg(std::ostream &os, int reg, int size) const;
void printDestReg(std::ostream &os, int reg, int size) const;
+ void printMem(std::ostream &os, uint8_t segment,
+ uint8_t scale, RegIndex index, RegIndex base,
+ uint64_t disp, uint8_t addressSize, bool rip) const;
inline uint64_t merge(uint64_t into, uint64_t val, int size) const
{
diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc
new file mode 100644
index 000000000..30c532c2b
--- /dev/null
+++ b/src/arch/x86/interrupts.cc
@@ -0,0 +1,569 @@
+/*
+ * 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/apicregs.hh"
+#include "arch/x86/interrupts.hh"
+#include "arch/x86/intmessage.hh"
+#include "cpu/base.hh"
+#include "mem/packet_access.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;
+}
+
+namespace X86ISA
+{
+
+ApicRegIndex
+decodeAddr(Addr paddr)
+{
+ ApicRegIndex regNum;
+ paddr &= ~mask(3);
+ switch (paddr)
+ {
+ case 0x20:
+ regNum = APIC_ID;
+ break;
+ case 0x30:
+ regNum = APIC_VERSION;
+ break;
+ case 0x80:
+ regNum = APIC_TASK_PRIORITY;
+ break;
+ case 0x90:
+ regNum = APIC_ARBITRATION_PRIORITY;
+ break;
+ case 0xA0:
+ regNum = APIC_PROCESSOR_PRIORITY;
+ break;
+ case 0xB0:
+ regNum = APIC_EOI;
+ break;
+ case 0xD0:
+ regNum = APIC_LOGICAL_DESTINATION;
+ break;
+ case 0xE0:
+ regNum = APIC_DESTINATION_FORMAT;
+ break;
+ case 0xF0:
+ regNum = APIC_SPURIOUS_INTERRUPT_VECTOR;
+ break;
+ case 0x100:
+ case 0x108:
+ case 0x110:
+ case 0x118:
+ case 0x120:
+ case 0x128:
+ case 0x130:
+ case 0x138:
+ case 0x140:
+ case 0x148:
+ case 0x150:
+ case 0x158:
+ case 0x160:
+ case 0x168:
+ case 0x170:
+ case 0x178:
+ regNum = APIC_IN_SERVICE((paddr - 0x100) / 0x8);
+ break;
+ case 0x180:
+ case 0x188:
+ case 0x190:
+ case 0x198:
+ case 0x1A0:
+ case 0x1A8:
+ case 0x1B0:
+ case 0x1B8:
+ case 0x1C0:
+ case 0x1C8:
+ case 0x1D0:
+ case 0x1D8:
+ case 0x1E0:
+ case 0x1E8:
+ case 0x1F0:
+ case 0x1F8:
+ regNum = APIC_TRIGGER_MODE((paddr - 0x180) / 0x8);
+ break;
+ case 0x200:
+ case 0x208:
+ case 0x210:
+ case 0x218:
+ case 0x220:
+ case 0x228:
+ case 0x230:
+ case 0x238:
+ case 0x240:
+ case 0x248:
+ case 0x250:
+ case 0x258:
+ case 0x260:
+ case 0x268:
+ case 0x270:
+ case 0x278:
+ regNum = APIC_INTERRUPT_REQUEST((paddr - 0x200) / 0x8);
+ break;
+ case 0x280:
+ regNum = APIC_ERROR_STATUS;
+ break;
+ case 0x300:
+ regNum = APIC_INTERRUPT_COMMAND_LOW;
+ break;
+ case 0x310:
+ regNum = APIC_INTERRUPT_COMMAND_HIGH;
+ break;
+ case 0x320:
+ regNum = APIC_LVT_TIMER;
+ break;
+ case 0x330:
+ regNum = APIC_LVT_THERMAL_SENSOR;
+ break;
+ case 0x340:
+ regNum = APIC_LVT_PERFORMANCE_MONITORING_COUNTERS;
+ break;
+ case 0x350:
+ regNum = APIC_LVT_LINT0;
+ break;
+ case 0x360:
+ regNum = APIC_LVT_LINT1;
+ break;
+ case 0x370:
+ regNum = APIC_LVT_ERROR;
+ break;
+ case 0x380:
+ regNum = APIC_INITIAL_COUNT;
+ break;
+ case 0x390:
+ regNum = APIC_CURRENT_COUNT;
+ break;
+ case 0x3E0:
+ regNum = APIC_DIVIDE_CONFIGURATION;
+ break;
+ default:
+ // A reserved register field.
+ panic("Accessed reserved register field %#x.\n", paddr);
+ break;
+ }
+ return regNum;
+}
+}
+
+Tick
+X86ISA::Interrupts::read(PacketPtr pkt)
+{
+ Addr offset = pkt->getAddr() - pioAddr;
+ //Make sure we're at least only accessing one register.
+ if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3)))
+ panic("Accessed more than one register at a time in the APIC!\n");
+ ApicRegIndex reg = decodeAddr(offset);
+ uint32_t val = htog(readReg(reg));
+ DPRINTF(LocalApic,
+ "Reading Local APIC register %d at offset %#x as %#x.\n",
+ reg, offset, val);
+ pkt->setData(((uint8_t *)&val) + (offset & mask(3)));
+ pkt->makeAtomicResponse();
+ return latency;
+}
+
+Tick
+X86ISA::Interrupts::write(PacketPtr pkt)
+{
+ Addr offset = pkt->getAddr() - pioAddr;
+ //Make sure we're at least only accessing one register.
+ if ((offset & ~mask(3)) != ((offset + pkt->getSize()) & ~mask(3)))
+ panic("Accessed more than one register at a time in the APIC!\n");
+ ApicRegIndex reg = decodeAddr(offset);
+ uint32_t val = regs[reg];
+ pkt->writeData(((uint8_t *)&val) + (offset & mask(3)));
+ DPRINTF(LocalApic,
+ "Writing Local APIC register %d at offset %#x as %#x.\n",
+ reg, offset, gtoh(val));
+ setReg(reg, gtoh(val));
+ pkt->makeAtomicResponse();
+ return latency;
+}
+void
+X86ISA::Interrupts::requestInterrupt(uint8_t vector,
+ uint8_t deliveryMode, bool level)
+{
+ /*
+ * Fixed and lowest-priority delivery mode interrupts are handled
+ * using the IRR/ISR registers, checking against the TPR, etc.
+ * The SMI, NMI, ExtInt, INIT, etc interrupts go straight through.
+ */
+ if (deliveryMode == DeliveryMode::Fixed ||
+ deliveryMode == DeliveryMode::LowestPriority) {
+ DPRINTF(LocalApic, "Interrupt is an %s.\n",
+ DeliveryMode::names[deliveryMode]);
+ // Queue up the interrupt in the IRR.
+ if (vector > IRRV)
+ IRRV = vector;
+ if (!getRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector)) {
+ setRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, vector);
+ if (level) {
+ setRegArrayBit(APIC_TRIGGER_MODE_BASE, vector);
+ } else {
+ clearRegArrayBit(APIC_TRIGGER_MODE_BASE, vector);
+ }
+ }
+ } else if (!DeliveryMode::isReserved(deliveryMode)) {
+ DPRINTF(LocalApic, "Interrupt is an %s.\n",
+ DeliveryMode::names[deliveryMode]);
+ if (deliveryMode == DeliveryMode::SMI && !pendingSmi) {
+ pendingUnmaskableInt = pendingSmi = true;
+ smiVector = vector;
+ } else if (deliveryMode == DeliveryMode::NMI && !pendingNmi) {
+ pendingUnmaskableInt = pendingNmi = true;
+ nmiVector = vector;
+ } else if (deliveryMode == DeliveryMode::ExtInt && !pendingExtInt) {
+ pendingExtInt = true;
+ extIntVector = vector;
+ } else if (deliveryMode == DeliveryMode::INIT && !pendingInit) {
+ pendingUnmaskableInt = pendingInit = true;
+ initVector = vector;
+ }
+ }
+ cpu->wakeup();
+}
+
+Tick
+X86ISA::Interrupts::recvMessage(PacketPtr pkt)
+{
+ uint8_t id = 0;
+ Addr offset = pkt->getAddr() - x86InterruptAddress(id, 0);
+ assert(pkt->cmd == MemCmd::MessageReq);
+ switch(offset)
+ {
+ case 0:
+ {
+ TriggerIntMessage message = pkt->get<TriggerIntMessage>();
+ DPRINTF(LocalApic,
+ "Got Trigger Interrupt message with vector %#x.\n",
+ message.vector);
+ // Make sure we're really supposed to get this.
+ assert((message.destMode == 0 && message.destination == id) ||
+ (bits((int)message.destination, id)));
+
+ requestInterrupt(message.vector,
+ message.deliveryMode, message.trigger);
+ }
+ break;
+ default:
+ panic("Local apic got unknown interrupt message at offset %#x.\n",
+ offset);
+ break;
+ }
+ delete pkt->req;
+ delete pkt;
+ return latency;
+}
+
+
+uint32_t
+X86ISA::Interrupts::readReg(ApicRegIndex reg)
+{
+ 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_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:
+ {
+ if (apicTimerEvent.scheduled()) {
+ assert(clock);
+ // Compute how many m5 ticks happen per count.
+ uint64_t ticksPerCount = clock *
+ divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]);
+ // Compute how many m5 ticks are left.
+ uint64_t val = apicTimerEvent.when() - curTick;
+ // Turn that into a count.
+ val = (val + ticksPerCount - 1) / ticksPerCount;
+ return val;
+ } else {
+ return 0;
+ }
+ }
+ default:
+ break;
+ }
+ return regs[reg];
+}
+
+void
+X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val)
+{
+ 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:
+ // Remove the interrupt that just completed from the local apic state.
+ clearRegArrayBit(APIC_IN_SERVICE_BASE, ISRV);
+ updateISRV();
+ return;
+ 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:
+ {
+ assert(clock);
+ newVal = bits(val, 31, 0);
+ // Compute how many timer ticks we're being programmed for.
+ uint64_t newCount = newVal *
+ (divideFromConf(regs[APIC_DIVIDE_CONFIGURATION]));
+ // Schedule on the edge of the next tick plus the new count.
+ Tick offset = curTick % clock;
+ if (offset) {
+ reschedule(apicTimerEvent,
+ curTick + (newCount + 1) * clock - offset, true);
+ } else {
+ reschedule(apicTimerEvent,
+ curTick + newCount * clock, true);
+ }
+ }
+ break;
+ case APIC_CURRENT_COUNT:
+ //Local APIC Current Count register is read only.
+ return;
+ case APIC_DIVIDE_CONFIGURATION:
+ newVal = val & 0xB;
+ break;
+ default:
+ break;
+ }
+ regs[reg] = newVal;
+ return;
+}
+
+bool
+X86ISA::Interrupts::checkInterrupts(ThreadContext *tc) const
+{
+ RFLAGS rflags = tc->readMiscRegNoEffect(MISCREG_RFLAGS);
+ if (pendingUnmaskableInt) {
+ DPRINTF(LocalApic, "Reported pending unmaskable interrupt.\n");
+ return true;
+ }
+ if (rflags.intf) {
+ if (pendingExtInt) {
+ DPRINTF(LocalApic, "Reported pending external interrupt.\n");
+ return true;
+ }
+ if (IRRV > ISRV && bits(IRRV, 7, 4) >
+ bits(regs[APIC_TASK_PRIORITY], 7, 4)) {
+ DPRINTF(LocalApic, "Reported pending regular interrupt.\n");
+ return true;
+ }
+ }
+ return false;
+}
+
+Fault
+X86ISA::Interrupts::getInterrupt(ThreadContext *tc)
+{
+ assert(checkInterrupts(tc));
+ // These are all probably fairly uncommon, so we'll make them easier to
+ // check for.
+ if (pendingUnmaskableInt) {
+ if (pendingSmi) {
+ DPRINTF(LocalApic, "Generated SMI fault object.\n");
+ return new SystemManagementInterrupt();
+ } else if (pendingNmi) {
+ DPRINTF(LocalApic, "Generated NMI fault object.\n");
+ return new NonMaskableInterrupt(nmiVector);
+ } else if (pendingInit) {
+ DPRINTF(LocalApic, "Generated INIT fault object.\n");
+ return new InitInterrupt(initVector);
+ } else {
+ panic("pendingUnmaskableInt set, but no unmaskable "
+ "ints were pending.\n");
+ return NoFault;
+ }
+ } else if (pendingExtInt) {
+ DPRINTF(LocalApic, "Generated external interrupt fault object.\n");
+ return new ExternalInterrupt(extIntVector);
+ } else {
+ DPRINTF(LocalApic, "Generated regular interrupt fault object.\n");
+ // The only thing left are fixed and lowest priority interrupts.
+ return new ExternalInterrupt(IRRV);
+ }
+}
+
+void
+X86ISA::Interrupts::updateIntrInfo(ThreadContext *tc)
+{
+ assert(checkInterrupts(tc));
+ if (pendingUnmaskableInt) {
+ if (pendingSmi) {
+ DPRINTF(LocalApic, "SMI sent to core.\n");
+ pendingSmi = false;
+ } else if (pendingNmi) {
+ DPRINTF(LocalApic, "NMI sent to core.\n");
+ pendingNmi = false;
+ } else if (pendingInit) {
+ DPRINTF(LocalApic, "Init sent to core.\n");
+ pendingInit = false;
+ }
+ if (!(pendingSmi || pendingNmi || pendingInit))
+ pendingUnmaskableInt = false;
+ } else if (pendingExtInt) {
+ pendingExtInt = false;
+ } else {
+ DPRINTF(LocalApic, "Interrupt %d sent to core.\n", IRRV);
+ // Mark the interrupt as "in service".
+ ISRV = IRRV;
+ setRegArrayBit(APIC_IN_SERVICE_BASE, ISRV);
+ // Clear it out of the IRR.
+ clearRegArrayBit(APIC_INTERRUPT_REQUEST_BASE, IRRV);
+ updateIRRV();
+ }
+}
+
+X86ISA::Interrupts *
+X86LocalApicParams::create()
+{
+ return new X86ISA::Interrupts(this);
+}
diff --git a/src/arch/x86/interrupts.hh b/src/arch/x86/interrupts.hh
index cf9109e22..c5e3bde0d 100644
--- a/src/arch/x86/interrupts.hh
+++ b/src/arch/x86/interrupts.hh
@@ -58,73 +58,274 @@
#ifndef __ARCH_X86_INTERRUPTS_HH__
#define __ARCH_X86_INTERRUPTS_HH__
+#include "arch/x86/apicregs.hh"
#include "arch/x86/faults.hh"
+#include "arch/x86/intmessage.hh"
+#include "base/bitfield.hh"
#include "cpu/thread_context.hh"
+#include "dev/io_device.hh"
+#include "dev/x86/intdev.hh"
+#include "params/X86LocalApic.hh"
+#include "sim/eventq.hh"
-namespace X86ISA
-{
+class ThreadContext;
+class BaseCPU;
+
+namespace X86ISA {
-class Interrupts
+class Interrupts : public BasicPioDevice, IntDev
{
+ protected:
+ // Storage for the APIC registers
+ uint32_t regs[NUM_APIC_REGS];
+
+ BitUnion32(LVTEntry)
+ Bitfield<7, 0> vector;
+ Bitfield<10, 8> deliveryMode;
+ Bitfield<12> status;
+ Bitfield<13> polarity;
+ Bitfield<14> remoteIRR;
+ Bitfield<15> trigger;
+ Bitfield<16> masked;
+ Bitfield<17> periodic;
+ EndBitUnion(LVTEntry)
+
+ /*
+ * Timing related stuff.
+ */
+ Tick latency;
+ Tick clock;
+
+ class ApicTimerEvent : public Event
+ {
+ private:
+ Interrupts *localApic;
+ public:
+ ApicTimerEvent(Interrupts *_localApic) :
+ Event(), localApic(_localApic)
+ {}
+
+ void process()
+ {
+ assert(localApic);
+ if (localApic->triggerTimerInterrupt()) {
+ localApic->setReg(APIC_INITIAL_COUNT,
+ localApic->readReg(APIC_INITIAL_COUNT));
+ }
+ }
+ };
+
+ ApicTimerEvent apicTimerEvent;
+
+ /*
+ * A set of variables to keep track of interrupts that don't go through
+ * the IRR.
+ */
+ bool pendingSmi;
+ uint8_t smiVector;
+ bool pendingNmi;
+ uint8_t nmiVector;
+ bool pendingExtInt;
+ uint8_t extIntVector;
+ bool pendingInit;
+ uint8_t initVector;
+
+ // This is a quick check whether any of the above (except ExtInt) are set.
+ bool pendingUnmaskableInt;
+
+ /*
+ * IRR and ISR maintenance.
+ */
+ uint8_t IRRV;
+ uint8_t ISRV;
+
+ int
+ findRegArrayMSB(ApicRegIndex base)
+ {
+ int offset = 7;
+ do {
+ if (regs[base + offset] != 0) {
+ return offset * 32 + findMsbSet(regs[base + offset]);
+ }
+ } while (offset--);
+ return 0;
+ }
+
+ void
+ updateIRRV()
+ {
+ IRRV = findRegArrayMSB(APIC_INTERRUPT_REQUEST_BASE);
+ }
+
+ void
+ updateISRV()
+ {
+ ISRV = findRegArrayMSB(APIC_IN_SERVICE_BASE);
+ }
+
+ void
+ setRegArrayBit(ApicRegIndex base, uint8_t vector)
+ {
+ regs[base + (vector % 32)] |= (1 << (vector >> 5));
+ }
+
+ void
+ clearRegArrayBit(ApicRegIndex base, uint8_t vector)
+ {
+ regs[base + (vector % 32)] &= ~(1 << (vector >> 5));
+ }
+
+ bool
+ getRegArrayBit(ApicRegIndex base, uint8_t vector)
+ {
+ return bits(regs[base + (vector % 32)], vector >> 5);
+ }
+
+ void requestInterrupt(uint8_t vector, uint8_t deliveryMode, bool level);
+
+ BaseCPU *cpu;
+
public:
- Interrupts()
+ /*
+ * Params stuff.
+ */
+ typedef X86LocalApicParams Params;
+
+ void
+ setCPU(BaseCPU * newCPU)
{
- clear_all();
+ cpu = newCPU;
}
- int InterruptLevel(uint64_t softint)
+ void
+ setClock(Tick newClock)
{
- panic("Interrupts::InterruptLevel unimplemented!\n");
- return 0;
+ clock = newClock;
}
- void post(int int_num, int index)
+ const Params *
+ params() const
{
- panic("Interrupts::post unimplemented!\n");
+ return dynamic_cast<const Params *>(_params);
}
- void clear(int int_num, int index)
+ /*
+ * Functions to interact with the interrupt port from IntDev.
+ */
+ Tick read(PacketPtr pkt);
+ Tick write(PacketPtr pkt);
+ Tick recvMessage(PacketPtr pkt);
+
+ bool
+ triggerTimerInterrupt()
{
- warn("Interrupts::clear unimplemented!\n");
+ LVTEntry entry = regs[APIC_LVT_TIMER];
+ if (!entry.masked)
+ requestInterrupt(entry.vector, entry.deliveryMode, entry.trigger);
+ return entry.periodic;
}
- void clear_all()
+ void addressRanges(AddrRangeList &range_list)
{
- warn("Interrupts::clear_all unimplemented!\n");
+ range_list.clear();
+ range_list.push_back(RangeEx(x86LocalAPICAddress(0, 0),
+ x86LocalAPICAddress(0, 0) + PageBytes));
}
- bool check_interrupts(ThreadContext * tc) const
+ void getIntAddrRange(AddrRangeList &range_list)
{
- return false;
+ range_list.clear();
+ range_list.push_back(RangeEx(x86InterruptAddress(0, 0),
+ x86InterruptAddress(0, 0) + PhysAddrAPICRangeSize));
}
- Fault getInterrupt(ThreadContext * tc)
+ Port *getPort(const std::string &if_name, int idx = -1)
{
- return NoFault;
+ if (if_name == "int_port")
+ return intPort;
+ return BasicPioDevice::getPort(if_name, idx);
}
- void updateIntrInfo(ThreadContext * tc)
+ /*
+ * Functions to access and manipulate the APIC's registers.
+ */
+
+ uint32_t readReg(ApicRegIndex miscReg);
+ void setReg(ApicRegIndex reg, uint32_t val);
+ void
+ setRegNoEffect(ApicRegIndex reg, uint32_t val)
{
- panic("Interrupts::updateIntrInfo unimplemented!\n");
+ regs[reg] = val;
}
- uint64_t get_vec(int int_num)
+ /*
+ * Constructor.
+ */
+
+ Interrupts(Params * p)
+ : BasicPioDevice(p), IntDev(this), latency(p->pio_latency), clock(0),
+ apicTimerEvent(this),
+ pendingSmi(false), smiVector(0),
+ pendingNmi(false), nmiVector(0),
+ pendingExtInt(false), extIntVector(0),
+ pendingInit(false), initVector(0),
+ pendingUnmaskableInt(false)
{
- panic("Interrupts::get_vec unimplemented!\n");
- return 0;
+ pioSize = PageBytes;
+ memset(regs, 0, sizeof(regs));
+ //Set the local apic DFR to the flat model.
+ regs[APIC_DESTINATION_FORMAT] = (uint32_t)(-1);
+ ISRV = 0;
+ IRRV = 0;
}
- void serialize(std::ostream & os)
+ /*
+ * Functions for retrieving interrupts for the CPU to handle.
+ */
+
+ bool checkInterrupts(ThreadContext *tc) const;
+ Fault getInterrupt(ThreadContext *tc);
+ void updateIntrInfo(ThreadContext *tc);
+
+ /*
+ * Serialization.
+ */
+
+ void
+ serialize(std::ostream &os)
{
panic("Interrupts::serialize unimplemented!\n");
}
- void unserialize(Checkpoint * cp, const std::string & section)
+ void
+ unserialize(Checkpoint *cp, const std::string &section)
{
panic("Interrupts::unserialize unimplemented!\n");
}
-};
+ /*
+ * Old functions needed for compatability but which will be phased out
+ * eventually.
+ */
+ void
+ post(int int_num, int index)
+ {
+ panic("Interrupts::post unimplemented!\n");
+ }
+
+ void
+ clear(int int_num, int index)
+ {
+ panic("Interrupts::clear unimplemented!\n");
+ }
+
+ void
+ clearAll()
+ {
+ panic("Interrupts::clearAll unimplemented!\n");
+ }
};
+} // namespace X86ISA
+
#endif // __ARCH_X86_INTERRUPTS_HH__
diff --git a/src/arch/x86/intmessage.hh b/src/arch/x86/intmessage.hh
new file mode 100644
index 000000000..f5f8519e2
--- /dev/null
+++ b/src/arch/x86/intmessage.hh
@@ -0,0 +1,110 @@
+/*
+ * 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_INTMESSAGE_HH__
+#define __ARCH_X86_INTMESSAGE_HH__
+
+#include "arch/x86/x86_traits.hh"
+#include "base/bitunion.hh"
+#include "mem/packet.hh"
+#include "mem/request.hh"
+#include "sim/host.hh"
+
+namespace X86ISA
+{
+ BitUnion32(TriggerIntMessage)
+ Bitfield<7, 0> destination;
+ Bitfield<15, 8> vector;
+ Bitfield<18, 16> deliveryMode;
+ Bitfield<19> destMode;
+ Bitfield<20> level;
+ Bitfield<21> trigger;
+ EndBitUnion(TriggerIntMessage)
+
+ namespace DeliveryMode
+ {
+ enum IntDeliveryMode {
+ Fixed = 0,
+ LowestPriority = 1,
+ SMI = 2,
+ NMI = 4,
+ INIT = 5,
+ ExtInt = 7,
+ NumModes
+ };
+
+ static const char * const names[NumModes] = {
+ "Fixed", "LowestPriority", "SMI", "Reserved",
+ "NMI", "INIT", "Reserved", "ExtInt"
+ };
+
+ static inline bool
+ isReserved(int mode)
+ {
+ return mode == 3 || mode == 6;
+ }
+ }
+
+ static const Addr TriggerIntOffset = 0;
+
+ static inline PacketPtr
+ prepIntRequest(const uint8_t id, Addr offset, Addr size)
+ {
+ RequestPtr req = new Request(x86InterruptAddress(id, offset),
+ size, Request::UNCACHEABLE);
+ PacketPtr pkt = new Packet(req, MemCmd::MessageReq, Packet::Broadcast);
+ pkt->allocate();
+ return pkt;
+ }
+
+ template<class T>
+ PacketPtr
+ buildIntRequest(const uint8_t id, T payload, Addr offset, Addr size)
+ {
+ PacketPtr pkt = prepIntRequest(id, offset, size);
+ pkt->set<T>(payload);
+ return pkt;
+ }
+
+ static inline PacketPtr
+ buildIntRequest(const uint8_t id, TriggerIntMessage payload)
+ {
+ return buildIntRequest(id, payload, TriggerIntOffset,
+ sizeof(TriggerIntMessage));
+ }
+
+ static inline PacketPtr
+ buildIntResponse()
+ {
+ panic("buildIntResponse not implemented.\n");
+ }
+}
+
+#endif
diff --git a/src/arch/x86/intregfile.cc b/src/arch/x86/intregfile.cc
index 9c9ea134e..58a37cb9e 100644
--- a/src/arch/x86/intregfile.cc
+++ b/src/arch/x86/intregfile.cc
@@ -97,17 +97,6 @@ using namespace std;
class Checkpoint;
-string X86ISA::getIntRegName(RegIndex index)
-{
- //These might appear to be out of order, but they match
- //the encoding for the registers. Who knows why the indexes
- //are out of order
- static std::string intRegName[NumIntArchRegs] =
- {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"};
- return intRegName[index];
-}
-
int IntRegFile::flattenIndex(int reg)
{
return reg;
@@ -120,13 +109,15 @@ void IntRegFile::clear()
IntReg IntRegFile::readReg(int intReg)
{
- DPRINTF(X86, "Read int reg %d and got value %#x\n", intReg, regs[intReg]);
+ DPRINTF(IntRegs, "Read int reg %d and got value %#x\n",
+ intReg, regs[intReg]);
return regs[intReg];
}
void IntRegFile::setReg(int intReg, const IntReg &val)
{
- DPRINTF(X86, "Setting int reg %d to value %#x\n", intReg, val);
+ DPRINTF(IntRegs, "Setting int reg %d to value %#x\n",
+ intReg, val);
regs[intReg] = val;
}
diff --git a/src/arch/x86/intregfile.hh b/src/arch/x86/intregfile.hh
index b4d256a04..131245352 100644
--- a/src/arch/x86/intregfile.hh
+++ b/src/arch/x86/intregfile.hh
@@ -100,9 +100,6 @@ namespace X86ISA
{
class Regfile;
- //This function translates integer register file indices into names
- std::string getIntRegName(RegIndex);
-
const int NumIntArchRegs = NUM_INTREGS;
const int NumIntRegs =
NumIntArchRegs + NumMicroIntRegs +
diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
index 332ae1641..817986232 100644
--- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa
+++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa
@@ -1,4 +1,4 @@
-// Copyright (c) 2007 The Hewlett-Packard Development Company
+// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
// All rights reserved.
//
// Redistribution and use of this software in source and binary forms,
@@ -418,12 +418,27 @@
default: Inst::RET_FAR();
}
0x4: int3();
+#if FULL_SYSTEM
0x5: int_Ib();
+#else
+ // Really only the LSB matters, but the predecoder will sign
+ // extend it, and there's no easy way to specify only checking
+ // the first byte.
+ 0x5: decode IMMEDIATE {
+ 0xffffffffffffff80:
+ SyscallInst::int80('xc->syscall(Rax)', IsSyscall);
+ default: int_Ib();
+ }
+#endif
0x6: decode MODE_SUBMODE {
0x0: Inst::UD2();
default: into();
}
- 0x7: iret();
+ 0x7: decode MODE_SUBMODE {
+ 0x4: Inst::IRET_REAL();
+ 0x3: Inst::IRET_VIRT();
+ default: Inst::IRET_PROT();
+ }
}
}
0x1A: decode OPCODE_OP_BOTTOM3 {
@@ -549,8 +564,8 @@
0x1F: decode OPCODE_OP_BOTTOM3 {
0x0: CLC();
0x1: STC();
- 0x2: WarnUnimpl::cli();
- 0x3: WarnUnimpl::sti();
+ 0x2: CLI();
+ 0x3: STI();
0x4: CLD();
0x5: STD();
//0x6: group4();
diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa
index 8135a1fdb..1ee62142a 100644
--- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa
+++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa
@@ -93,8 +93,8 @@
0x00: decode MODRM_REG {
0x0: sldt_Mw_or_Rv();
0x1: str_Mw_or_Rv();
- 0x2: lldt_Mw_or_Rv();
- 0x3: ltr_Mw_or_Rv();
+ 0x2: Inst::LLDT(Ew);
+ 0x3: Inst::LTR(Ew);
0x4: verr_Mw_or_Rv();
0x5: verw_Mw_or_Rv();
//0x6: jmpe_Ev(); // IA-64
@@ -128,7 +128,7 @@
0x4: smsw_Rv();
0x6: lmsw_Rv();
0x7: decode MODRM_RM {
- 0x0: swapgs();
+ 0x0: Inst::SWAPGS();
0x1: rdtscp();
default: Inst::UD2();
}
@@ -163,17 +163,117 @@
}
0x02: lar_Gv_Ew();
0x03: lsl_Gv_Ew();
- //sandpile.org doesn't seem to know what this is... ?
- 0x04: loadall_or_reset_or_hang();
+ // sandpile.org doesn't seem to know what this is...? We'll
+ // use it for pseudo instructions. We've got 16 bits of space
+ // to play with so there can be quite a few pseudo
+ // instructions.
+ //0x04: loadall_or_reset_or_hang();
+ 0x4: decode IMMEDIATE {
+ format BasicOperate {
#if FULL_SYSTEM
- 0x05: syscall();
+ 0x00: m5arm({{
+ PseudoInst::arm(xc->tcBase());
+ }}, IsNonSpeculative);
+ 0x01: m5quiesce({{
+ PseudoInst::quiesce(xc->tcBase());
+ }}, IsNonSpeculative);
+ 0x02: m5quiesceNs({{
+ PseudoInst::quiesceNs(xc->tcBase(), Rdi);
+ }}, IsNonSpeculative);
+ 0x03: m5quiesceCycle({{
+ PseudoInst::quiesceCycles(xc->tcBase(), Rdi);
+ }}, IsNonSpeculative);
+ 0x04: m5quiesceTime({{
+ Rax = PseudoInst::quiesceTime(xc->tcBase());
+ }}, IsNonSpeculative);
+#endif
+ 0x07: m5rpns({{
+ Rax = PseudoInst::rpns(xc->tcBase());
+ }}, IsNonSpeculative);
+ 0x21: m5exit({{
+ PseudoInst::m5exit(xc->tcBase(), Rdi);
+ }}, IsNonSpeculative);
+#if FULL_SYSTEM
+ 0x30: m5initparam({{
+ Rax = xc->tcBase()->getCpuPtr()->
+ system->init_param;
+ }}, IsNonSpeculative);
+ 0x31: m5loadsymbol({{
+ PseudoInst::loadsymbol(xc->tcBase());
+ }}, IsNonSpeculative);
+#endif
+ 0x40: m5resetstats({{
+ PseudoInst::resetstats(xc->tcBase(), Rdi, Rsi);
+ }}, IsNonSpeculative);
+ 0x41: m5dumpstats({{
+ PseudoInst::dumpstats(xc->tcBase(), Rdi, Rsi);
+ }}, IsNonSpeculative);
+ 0x42: m5dumpresetstats({{
+ PseudoInst::dumpresetstats(xc->tcBase(), Rdi, Rsi);
+ }}, IsNonSpeculative);
+ 0x43: m5checkpoint({{
+ PseudoInst::m5checkpoint(xc->tcBase(), Rdi, Rsi);
+ }}, IsNonSpeculative);
+#if FULL_SYSTEM
+ 0x50: m5readfile({{
+ Rax = PseudoInst::readfile(
+ xc->tcBase(), Rdi, Rsi, Rdx);
+ }}, IsNonSpeculative);
+#endif
+ 0x51: m5debugbreak({{
+ PseudoInst::debugbreak(xc->tcBase());
+ }}, IsNonSpeculative);
+ 0x52: m5switchcpu({{
+ PseudoInst::switchcpu(xc->tcBase());
+ }}, IsNonSpeculative);
+#if FULL_SYSTEM
+ 0x53: m5addsymbol({{
+ PseudoInst::addsymbol(xc->tcBase(), Rdi, Rsi);
+ }}, IsNonSpeculative);
+#endif
+ 0x54: m5panic({{
+ panic("M5 panic instruction called at pc=%#x.\n",
+ xc->readPC());
+ }}, IsNonSpeculative);
+ 0x55: m5reserved1({{
+ warn("M5 reserved opcode 1 ignored.\n");
+ }}, IsNonSpeculative);
+ 0x56: m5reserved2({{
+ warn("M5 reserved opcode 2 ignored.\n");
+ }}, IsNonSpeculative);
+ 0x57: m5reserved3({{
+ warn("M5 reserved opcode 3 ignored.\n");
+ }}, IsNonSpeculative);
+ 0x58: m5reserved4({{
+ warn("M5 reserved opcode 4 ignored.\n");
+ }}, IsNonSpeculative);
+ 0x59: m5reserved5({{
+ warn("M5 reserved opcode 5 ignored.\n");
+ }}, IsNonSpeculative);
+ default: Inst::UD2();
+ }
+ }
+#if FULL_SYSTEM
+ 0x05: decode MODE_MODE {
+ 0x0: decode MODE_SUBMODE {
+ 0x0: Inst::SYSCALL_64();
+ 0x1: Inst::SYSCALL_COMPAT();
+ }
+ 0x1: Inst::SYSCALL_LEGACY();
+ }
#else
- 0x05: SyscallInst::syscall('xc->syscall(rax)', IsSyscall);
+ 0x05: SyscallInst::syscall('xc->syscall(Rax)', IsSyscall);
#endif
- 0x06: clts();
- //sandpile.org says (AMD) after sysret, so I might want to check
- //if that means amd64 or AMD machines
- 0x07: loadall_or_sysret();
+ 0x06: Inst::CLTS();
+ 0x07: decode MODE_SUBMODE {
+ 0x0: decode OPSIZE {
+ // Return to 64 bit mode.
+ 0x8: Inst::SYSRET_TO_64();
+ // Return to compatibility mode.
+ default: Inst::SYSRET_TO_COMPAT();
+ }
+ default: Inst::SYSRET_NON_64();
+ }
}
0x01: decode OPCODE_OP_BOTTOM3 {
0x0: invd();
@@ -181,9 +281,9 @@
0x2: Inst::UD2();
0x3: Inst::UD2();
0x4: Inst::UD2();
- 0x5: threednow();
- 0x6: threednow();
- 0x7: threednow();
+ 0x5: Inst::PREFETCH(Mb);
+ 0x6: FailUnimpl::femms();
+ 0x7: FailUnimpl::threednow();
}
0x02: decode LEGACY_DECODEVAL {
// no prefix
@@ -235,7 +335,7 @@
//group17();
0x0: decode MODRM_REG {
0x0: prefetch_nta();
- 0x1: prefetch_t0();
+ 0x1: Inst::PREFETCH_T0(Mb);
0x2: prefetch_t1();
0x3: prefetch_t2();
default: Inst::HINT_NOP();
@@ -252,9 +352,9 @@
// no prefix
0x0: decode OPCODE_OP_BOTTOM3 {
0x0: Inst::MOV(Rd,Cd);
- 0x1: mov_Rd_Dd();
+ 0x1: Inst::MOV(Rd,Dd);
0x2: Inst::MOV(Cd,Rd);
- 0x3: mov_Dd_Rd();
+ 0x3: Inst::MOV(Dd,Rd);
0x4: mov_Rd_Td();
0x6: mov_Td_Rd();
default: Inst::UD2();
@@ -317,10 +417,14 @@
}
0x06: decode OPCODE_OP_BOTTOM3 {
0x0: Inst::WRMSR();
- 0x1: rdtsc();
+ 0x1: Inst::RDTSC();
0x2: Inst::RDMSR();
0x3: rdpmc();
+#if FULL_SYSTEM
0x4: sysenter();
+#else
+ 0x4: SyscallInst::sysenter('xc->syscall(Rax)', IsSyscall);
+#endif
0x5: sysexit();
0x6: Inst::UD2();
0x7: getsec();
@@ -707,7 +811,14 @@
0x14: decode OPCODE_OP_BOTTOM3 {
0x0: push_fs();
0x1: pop_fs();
- 0x2: Inst::CPUID(rAd);
+ 0x2: CPUIDInst::CPUID({{
+ CpuidResult result;
+ success = doCpuid(xc->tcBase(), Rax, result);
+ Rax = result.rax;
+ Rbx = result.rbx;
+ Rcx = result.rcx;
+ Rdx = result.rdx;
+ }});
0x3: Inst::BT(Ev,Gv);
0x4: shld_Ev_Gv_Ib();
0x5: shld_Ev_Gv_rCl();
@@ -719,20 +830,28 @@
0x1: pop_gs();
0x2: rsm_smm();
0x3: Inst::BTS(Ev,Gv);
- 0x4: shrd_Ev_Gv_Ib();
+ 0x4: Inst::SHRD(Ev,Gv,Ib);
0x5: shrd_Ev_Gv_rCl();
//0x6: group16();
- 0x6: decode MODRM_MOD {
- 0x3: decode MODRM_REG {
- 0x5: lfence();
- 0x6: mfence();
- 0x7: sfence();
+ 0x6: decode MODRM_REG {
+ 0x0: fxsave();
+ 0x1: fxrstor();
+ 0x2: ldmxcsr();
+ 0x3: stmxcsr();
+ 0x4: Inst::UD2();
+ 0x5: decode MODRM_MOD {
+ 0x3: BasicOperate::LFENCE(
+ {{/*Nothing*/}}, IsReadBarrier);
default: Inst::UD2();
}
- default: decode MODRM_REG {
- 0x0: fxsave();
- 0x1: fxrstor();
- 0x7: clflush();
+ 0x6: decode MODRM_MOD {
+ 0x3: BasicOperate::MFENCE(
+ {{/*Nothing*/}}, IsMemBarrier);
+ default: Inst::UD2();
+ }
+ 0x7: decode MODRM_MOD {
+ 0x3: BasicOperate::SFENCE(
+ {{/*Nothing*/}}, IsWriteBarrier);
default: Inst::UD2();
}
}
@@ -775,8 +894,8 @@
0x7: Inst::MOVSX_W(Gv,Ev);
}
0x18: decode OPCODE_OP_BOTTOM3 {
- 0x0: xadd_Eb_Gb();
- 0x1: xadd_Ev_Gv();
+ 0x0: Inst::XADD(Eb,Gb);
+ 0x1: Inst::XADD(Ev,Gv);
//0x7: group9();
0x7: decode MODRM_REG {
0x1: cmpxchg_Mq();
@@ -820,7 +939,11 @@
default: Inst::UD2();
}
}
- 0x19: bswap_B();
+ 0x19: decode OPSIZE {
+ 4: Inst::BSWAP_D(Bd);
+ 8: Inst::BSWAP_Q(Bq);
+ default: Inst::UD2();
+ }
0x1A: decode LEGACY_DECODEVAL {
// no prefix
0x0: decode OPCODE_OP_BOTTOM3 {
diff --git a/src/arch/x86/isa/formats/basic.isa b/src/arch/x86/isa/formats/basic.isa
index 7aea7085f..b96bae238 100644
--- a/src/arch/x86/isa/formats/basic.isa
+++ b/src/arch/x86/isa/formats/basic.isa
@@ -147,3 +147,11 @@ def template BasicDecode {{
def template BasicDecodeWithMnemonic {{
return new %(class_name)s("%(mnemonic)s", machInst);
}};
+
+def format BasicOperate(code, *flags) {{
+ iop = InstObjParams(name, Name, 'X86ISA::X86StaticInst', code, flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = BasicExecute.subst(iop)
+}};
diff --git a/src/arch/x86/isa/formats/cpuid.isa b/src/arch/x86/isa/formats/cpuid.isa
new file mode 100644
index 000000000..204270556
--- /dev/null
+++ b/src/arch/x86/isa/formats/cpuid.isa
@@ -0,0 +1,110 @@
+// 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
+
+output header {{
+ class CPUIDInst : public X86ISA::X86StaticInst
+ {
+ public:
+ static const RegIndex foldOBit = 0;
+ /// Constructor
+ CPUIDInst(const char *_mnemonic, ExtMachInst _machInst,
+ OpClass __opClass) :
+ X86ISA::X86StaticInst(_mnemonic, _machInst, __opClass)
+ {
+ }
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+}};
+
+output decoder {{
+ std::string CPUIDInst::generateDisassembly(Addr PC,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+
+ printMnemonic(response, mnemonic);
+ ccprintf(response, " ");
+ printReg(response, _srcRegIdx[0], machInst.opSize);
+ return response.str();
+ }
+}};
+
+def template CPUIDExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ // If the CPUID instruction used a valid function number, this will
+ // be set to true. Otherwise, the instruction does nothing.
+ bool success;
+ %(op_decl)s;
+ %(op_rd)s;
+ %(code)s;
+ if (success) {
+ %(op_wb)s;
+ }
+ return NoFault;
+ }
+}};
+
+def format CPUIDInst(code, *opt_flags) {{
+ iop = InstObjParams(name, Name, 'CPUIDInst', code, opt_flags)
+ header_output = BasicDeclare.subst(iop)
+ decoder_output = BasicConstructor.subst(iop)
+ decode_block = BasicDecode.subst(iop)
+ exec_output = CPUIDExecute.subst(iop)
+}};
+
diff --git a/src/arch/x86/isa/formats/formats.isa b/src/arch/x86/isa/formats/formats.isa
index 6906413c0..81179ab45 100644
--- a/src/arch/x86/isa/formats/formats.isa
+++ b/src/arch/x86/isa/formats/formats.isa
@@ -85,6 +85,9 @@
//Templates from this format are used later
##include "basic.isa"
+//Include a format to generate a CPUID instruction.
+##include "cpuid.isa"
+
//Include the "unknown" format
##include "unknown.isa"
diff --git a/src/arch/x86/isa/includes.isa b/src/arch/x86/isa/includes.isa
index 6724ea9b0..8626f117a 100644
--- a/src/arch/x86/isa/includes.isa
+++ b/src/arch/x86/isa/includes.isa
@@ -26,7 +26,7 @@
//
// Authors: Gabe Black
-// Copyright (c) 2007 The Hewlett-Packard Development Company
+// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
// All rights reserved.
//
// Redistribution and use of this software in source and binary forms,
@@ -97,6 +97,7 @@ output header {{
#include <iostream>
#include "arch/x86/emulenv.hh"
+#include "arch/x86/insts/macroop.hh"
#include "arch/x86/insts/microfpop.hh"
#include "arch/x86/insts/microldstop.hh"
#include "arch/x86/insts/microregop.hh"
@@ -113,10 +114,13 @@ output header {{
output decoder {{
#include "arch/x86/faults.hh"
#include "arch/x86/floatregs.hh"
+#include "arch/x86/microcode_rom.hh"
#include "arch/x86/miscregs.hh"
#include "arch/x86/segmentregs.hh"
+#include "arch/x86/tlb.hh"
#include "base/cprintf.hh"
#include "base/loader/symtab.hh"
+#include "base/misc.hh"
#include "cpu/thread_context.hh" // for Jump::branchTarget()
#include "mem/packet.hh"
@@ -144,6 +148,7 @@ output exec {{
#include <limits>
#include <cmath>
+#include "arch/x86/cpuid.hh"
#include "arch/x86/miscregs.hh"
#include "arch/x86/tlb.hh"
#include "base/bigint.hh"
@@ -152,6 +157,8 @@ output exec {{
#include "sim/sim_exit.hh"
#include "mem/packet.hh"
#include "mem/packet_access.hh"
+#include "mem/request.hh"
+#include "sim/pseudo_inst.hh"
using namespace X86ISA;
using namespace std;
diff --git a/src/arch/x86/isa/insts/__init__.py b/src/arch/x86/isa/insts/__init__.py
index 0ef617a87..d7a8bde19 100644
--- a/src/arch/x86/isa/insts/__init__.py
+++ b/src/arch/x86/isa/insts/__init__.py
@@ -53,7 +53,8 @@
#
# Authors: Gabe Black
-categories = ["general_purpose",
+categories = ["romutil",
+ "general_purpose",
"simd128",
"simd64",
"system",
diff --git a/src/arch/x86/isa/insts/general_purpose/__init__.py b/src/arch/x86/isa/insts/general_purpose/__init__.py
index 4f77cb233..23f955f08 100644
--- a/src/arch/x86/isa/insts/general_purpose/__init__.py
+++ b/src/arch/x86/isa/insts/general_purpose/__init__.py
@@ -65,7 +65,6 @@ categories = ["arithmetic",
"load_segment_registers",
"logical",
"no_operation",
- "processor_information",
"rotate_and_shift",
"semaphores",
"string",
diff --git a/src/arch/x86/isa/insts/general_purpose/arithmetic/multiply_and_divide.py b/src/arch/x86/isa/insts/general_purpose/arithmetic/multiply_and_divide.py
index a9b53acac..19d1c7789 100644
--- a/src/arch/x86/isa/insts/general_purpose/arithmetic/multiply_and_divide.py
+++ b/src/arch/x86/isa/insts/general_purpose/arithmetic/multiply_and_divide.py
@@ -246,7 +246,7 @@ def macroop DIV_B_R
divLoopTop:
div2 t1, rax, t1, dataSize=1
div2 t1, rax, t1, flags=(EZF,), dataSize=1
- bri t0, label("divLoopTop"), flags=(nCEZF,)
+ br label("divLoopTop"), flags=(nCEZF,)
#Unload the answer
divq rax, dataSize=1
@@ -269,7 +269,7 @@ def macroop DIV_B_M
divLoopTop:
div2 t1, rax, t1, dataSize=1
div2 t1, rax, t1, flags=(EZF,), dataSize=1
- bri t0, label("divLoopTop"), flags=(nCEZF,)
+ br label("divLoopTop"), flags=(nCEZF,)
#Unload the answer
divq rax, dataSize=1
@@ -293,7 +293,7 @@ def macroop DIV_B_P
divLoopTop:
div2 t1, rax, t1, dataSize=1
div2 t1, rax, t1, flags=(EZF,), dataSize=1
- bri t0, label("divLoopTop"), flags=(nCEZF,)
+ br label("divLoopTop"), flags=(nCEZF,)
#Unload the answer
divq rax, dataSize=1
@@ -321,7 +321,7 @@ divLoopTop:
div2 t1, rax, t1
div2 t1, rax, t1
div2 t1, rax, t1, flags=(EZF,)
- bri t0, label("divLoopTop"), flags=(nCEZF,)
+ br label("divLoopTop"), flags=(nCEZF,)
#Unload the answer
divq rax
@@ -347,7 +347,7 @@ divLoopTop:
div2 t1, rax, t1
div2 t1, rax, t1
div2 t1, rax, t1, flags=(EZF,)
- bri t0, label("divLoopTop"), flags=(nCEZF,)
+ br label("divLoopTop"), flags=(nCEZF,)
#Unload the answer
divq rax
@@ -374,7 +374,7 @@ divLoopTop:
div2 t1, rax, t1
div2 t1, rax, t1
div2 t1, rax, t1, flags=(EZF,)
- bri t0, label("divLoopTop"), flags=(nCEZF,)
+ br label("divLoopTop"), flags=(nCEZF,)
#Unload the answer
divq rax
@@ -422,7 +422,7 @@ def macroop IDIV_B_R
divLoopTop:
div2 t4, t1, t4, dataSize=1
div2 t4, t1, t4, flags=(EZF,), dataSize=1
- bri t0, label("divLoopTop"), flags=(nCEZF,)
+ br label("divLoopTop"), flags=(nCEZF,)
#Unload the answer
divq t5, dataSize=1
@@ -495,7 +495,7 @@ def macroop IDIV_B_M
divLoopTop:
div2 t4, t1, t4, dataSize=1
div2 t4, t1, t4, flags=(EZF,), dataSize=1
- bri t0, label("divLoopTop"), flags=(nCEZF,)
+ br label("divLoopTop"), flags=(nCEZF,)
#Unload the answer
divq t5, dataSize=1
@@ -569,7 +569,7 @@ def macroop IDIV_B_P
divLoopTop:
div2 t4, t1, t4, dataSize=1
div2 t4, t1, t4, flags=(EZF,), dataSize=1
- bri t0, label("divLoopTop"), flags=(nCEZF,)
+ br label("divLoopTop"), flags=(nCEZF,)
#Unload the answer
divq t5, dataSize=1
@@ -646,7 +646,7 @@ divLoopTop:
div2 t4, t1, t4
div2 t4, t1, t4
div2 t4, t1, t4, flags=(EZF,)
- bri t0, label("divLoopTop"), flags=(nCEZF,)
+ br label("divLoopTop"), flags=(nCEZF,)
#Unload the answer
divq t5
@@ -721,7 +721,7 @@ divLoopTop:
div2 t4, t1, t4
div2 t4, t1, t4
div2 t4, t1, t4, flags=(EZF,)
- bri t0, label("divLoopTop"), flags=(nCEZF,)
+ br label("divLoopTop"), flags=(nCEZF,)
#Unload the answer
divq t5
@@ -797,7 +797,7 @@ divLoopTop:
div2 t4, t1, t4
div2 t4, t1, t4
div2 t4, t1, t4, flags=(EZF,)
- bri t0, label("divLoopTop"), flags=(nCEZF,)
+ br label("divLoopTop"), flags=(nCEZF,)
#Unload the answer
divq t5
diff --git a/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py b/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py
index b5fc43fcd..dbd2d8b84 100644
--- a/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py
+++ b/src/arch/x86/isa/insts/general_purpose/cache_and_memory_management.py
@@ -53,20 +53,42 @@
#
# Authors: Gabe Black
-microcode = ""
+microcode = '''
+def macroop PREFETCH_M
+{
+ ld t0, seg, sib, disp, dataSize=1, prefetch=True
+};
+
+def macroop PREFETCH_P
+{
+ rdip t7
+ ld t0, seg, riprel, disp, dataSize=1, prefetch=True
+};
+
+def macroop PREFETCH_T0_M
+{
+ ld t0, seg, sib, disp, dataSize=1, prefetch=True
+};
+
+def macroop PREFETCH_T0_P
+{
+ rdip t7
+ ld t0, seg, riprel, disp, dataSize=1, prefetch=True
+};
+
+'''
+
#let {{
# class LFENCE(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class SFENCE(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class MFENCE(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class PREFETCHlevel(Inst):
-# "GenFault ${new UnimpInstFault}"
-# class PREFETCH(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class PREFETCHW(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class CLFLUSH(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
#}};
diff --git a/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py b/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py
index 71059e80d..22364e038 100644
--- a/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py
+++ b/src/arch/x86/isa/insts/general_purpose/compare_and_test/bit_scan.py
@@ -82,11 +82,11 @@
# Authors: Gabe Black
microcode = '''
-def macroop BSF_R_R {
+def macroop BSR_R_R {
# Determine if the input was zero, and also move it to a temp reg.
movi t1, t1, t0, dataSize=8
and t1, regm, regm, flags=(ZF,)
- bri t0, label("end"), flags=(CZF,)
+ br label("end"), flags=(CZF,)
# Zero out the result register
movi reg, reg, 0x0
@@ -125,20 +125,19 @@ def macroop BSF_R_R {
srli t3, t1, 1, dataSize=8, flags=(EZF,)
ori t4, reg, 0x1
mov reg, reg, t4, flags=(nCEZF,)
- mov t1, t1, t3, flags=(nCEZF,)
end:
fault "NoFault"
};
-def macroop BSF_R_M {
+def macroop BSR_R_M {
movi t1, t1, t0, dataSize=8
ld t1, seg, sib, disp
# Determine if the input was zero, and also move it to a temp reg.
and t1, t1, t1, flags=(ZF,)
- bri t0, label("end"), flags=(CZF,)
+ br label("end"), flags=(CZF,)
# Zero out the result register
movi reg, reg, 0x0
@@ -177,13 +176,12 @@ def macroop BSF_R_M {
srli t3, t1, 1, dataSize=8, flags=(EZF,)
ori t4, reg, 0x1
mov reg, reg, t4, flags=(nCEZF,)
- mov t1, t1, t3, flags=(nCEZF,)
end:
fault "NoFault"
};
-def macroop BSF_R_P {
+def macroop BSR_R_P {
rdip t7
movi t1, t1, t0, dataSize=8
@@ -191,7 +189,7 @@ def macroop BSF_R_P {
# Determine if the input was zero, and also move it to a temp reg.
and t1, t1, t1, flags=(ZF,)
- bri t0, label("end"), flags=(CZF,)
+ br label("end"), flags=(CZF,)
# Zero out the result register
movi reg, reg, 0x0
@@ -230,17 +228,16 @@ def macroop BSF_R_P {
srli t3, t1, 1, dataSize=8, flags=(EZF,)
ori t4, reg, 0x1
mov reg, reg, t4, flags=(nCEZF,)
- mov t1, t1, t3, flags=(nCEZF,)
end:
fault "NoFault"
};
-def macroop BSR_R_R {
+def macroop BSF_R_R {
# Determine if the input was zero, and also move it to a temp reg.
mov t1, t1, t0, dataSize=8
and t1, regm, regm, flags=(ZF,)
- bri t0, label("end"), flags=(CZF,)
+ br label("end"), flags=(CZF,)
# Zero out the result register
movi reg, reg, 0
@@ -248,48 +245,54 @@ def macroop BSR_R_R {
subi t2, t1, 1
xor t1, t2, t1
+
# Bit 6
- srli t3, t1, 32, dataSize=8
- andi t3, t3, 32
- or reg, reg, t3
+ srli t3, t1, 32, dataSize=8, flags=(EZF,)
+ ori t4, reg, 32
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 5
- srli t3, t1, 16, dataSize=8
- andi t3, t3, 16
- or reg, reg, t3
+ srli t3, t1, 16, dataSize=8, flags=(EZF,)
+ ori t4, reg, 16
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 4
- srli t3, t1, 8, dataSize=8
- andi t3, t3, 8
- or reg, reg, t3
+ srli t3, t1, 8, dataSize=8, flags=(EZF,)
+ ori t4, reg, 8
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 3
- srli t3, t1, 4, dataSize=8
- andi t3, t3, 4
- or reg, reg, t3
+ srli t3, t1, 4, dataSize=8, flags=(EZF,)
+ ori t4, reg, 4
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 2
- srli t3, t1, 2, dataSize=8
- andi t3, t3, 2
- or reg, reg, t3
+ srli t3, t1, 2, dataSize=8, flags=(EZF,)
+ ori t4, reg, 2
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 1
- srli t3, t1, 1, dataSize=8
- andi t3, t3, 1
- or reg, reg, t3
+ srli t3, t1, 1, dataSize=8, flags=(EZF,)
+ ori t4, reg, 1
+ mov reg, reg, t4, flags=(nCEZF,)
end:
fault "NoFault"
};
-def macroop BSR_R_M {
+def macroop BSF_R_M {
mov t1, t1, t0, dataSize=8
ld t1, seg, sib, disp
# Determine if the input was zero, and also move it to a temp reg.
and t1, t1, t1, flags=(ZF,)
- bri t0, label("end"), flags=(CZF,)
+ br label("end"), flags=(CZF,)
# Zero out the result register
mov reg, reg, t0
@@ -298,40 +301,46 @@ def macroop BSR_R_M {
xor t1, t2, t1
# Bit 6
- srli t3, t1, 32, dataSize=8
- andi t3, t3, 32
- or reg, reg, t3
+ srli t3, t1, 32, dataSize=8, flags=(EZF,)
+ ori t4, reg, 32
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 5
- srli t3, t1, 16, dataSize=8
- andi t3, t3, 16
- or reg, reg, t3
+ srli t3, t1, 16, dataSize=8, flags=(EZF,)
+ ori t4, reg, 16
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 4
- srli t3, t1, 8, dataSize=8
- andi t3, t3, 8
- or reg, reg, t3
+ srli t3, t1, 8, dataSize=8, flags=(EZF,)
+ ori t4, reg, 8
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 3
- srli t3, t1, 4, dataSize=8
- andi t3, t3, 4
- or reg, reg, t3
+ srli t3, t1, 4, dataSize=8, flags=(EZF,)
+ ori t4, reg, 4
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 2
- srli t3, t1, 2, dataSize=8
- andi t3, t3, 2
- or reg, reg, t3
+ srli t3, t1, 2, dataSize=8, flags=(EZF,)
+ ori t4, reg, 2
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 1
- srli t3, t1, 1, dataSize=8
- andi t3, t3, 1
- or reg, reg, t3
+ srli t3, t1, 1, dataSize=8, flags=(EZF,)
+ ori t4, reg, 1
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
end:
fault "NoFault"
};
-def macroop BSR_R_P {
+def macroop BSF_R_P {
rdip t7
mov t1, t1, t0, dataSize=8
@@ -339,7 +348,7 @@ def macroop BSR_R_P {
# Determine if the input was zero, and also move it to a temp reg.
and t1, t1, t1, flags=(ZF,)
- bri t0, label("end"), flags=(CZF,)
+ br label("end"), flags=(CZF,)
# Zero out the result register
mov reg, reg, t0
@@ -348,34 +357,40 @@ def macroop BSR_R_P {
xor t1, t2, t1
# Bit 6
- srli t3, t1, 32, dataSize=8
- andi t3, t3, 32
- or reg, reg, t3
+ srli t3, t1, 32, dataSize=8, flags=(EZF,)
+ ori t4, reg, 32
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 5
- srli t3, t1, 16, dataSize=8
- andi t3, t3, 16
- or reg, reg, t3
+ srli t3, t1, 16, dataSize=8, flags=(EZF,)
+ ori t4, reg, 16
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 4
- srli t3, t1, 8, dataSize=8
- andi t3, t3, 8
- or reg, reg, t3
+ srli t3, t1, 8, dataSize=8, flags=(EZF,)
+ ori t4, reg, 8
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 3
- srli t3, t1, 4, dataSize=8
- andi t3, t3, 4
- or reg, reg, t3
+ srli t3, t1, 4, dataSize=8, flags=(EZF,)
+ ori t4, reg, 4
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 2
- srli t3, t1, 2, dataSize=8
- andi t3, t3, 2
- or reg, reg, t3
+ srli t3, t1, 2, dataSize=8, flags=(EZF,)
+ ori t4, reg, 2
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
# Bit 1
- srli t3, t1, 1, dataSize=8
- andi t3, t3, 1
- or reg, reg, t3
+ srli t3, t1, 1, dataSize=8, flags=(EZF,)
+ ori t4, reg, 1
+ mov reg, reg, t4, flags=(nCEZF,)
+ mov t1, t1, t3, flags=(nCEZF,)
end:
fault "NoFault"
diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py
index 45a7822fb..7abafe253 100644
--- a/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py
+++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py
@@ -103,5 +103,5 @@ def macroop CALL_NEAR_P
'''
#let {{
# class CALL(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
#}};
diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py
index 7039b4b5c..8203f7c2c 100644
--- a/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py
+++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/interrupts_and_exceptions.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2007 The Hewlett-Packard Development Company
+# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
@@ -53,16 +53,194 @@
#
# Authors: Gabe Black
-microcode = ""
+microcode = '''
+def macroop IRET_REAL {
+ panic "Real mode iret isn't implemented!"
+};
+
+def macroop IRET_PROT {
+ .adjust_env oszIn64Override
+
+ # Check for a nested task. This isn't supported at the moment.
+ rflag t1, NT
+ panic "Task switching with iret is unimplemented!", flags=(nCEZF,)
+
+ #t1 = temp_RIP
+ #t2 = temp_CS
+ #t3 = temp_RFLAGS
+ #t4 = handy m5 register
+
+ # Pop temp_RIP, temp_CS, and temp_RFLAGS
+ ld t1, ss, [1, t0, rsp], "0 * env.stackSize", dataSize=ssz
+ ld t2, ss, [1, t0, rsp], "1 * env.stackSize", dataSize=ssz
+ ld t3, ss, [1, t0, rsp], "2 * env.stackSize", dataSize=ssz
+
+ # Read the handy m5 register for use later
+ rdm5reg t4
+
+
+###
+### Handle if we're returning to virtual 8086 mode.
+###
+
+ #IF ((temp_RFLAGS.VM=1) && (CPL=0) && (LEGACY_MODE))
+ # IRET_FROM_PROTECTED_TO_VIRTUAL
+
+ #temp_RFLAGS.VM != 1
+ rcri t0, t3, 18, flags=(ECF,)
+ br label("protToVirtFallThrough"), flags=(nCECF,)
+
+ #CPL=0
+ andi t0, t4, 0x30, flags=(EZF,)
+ br label("protToVirtFallThrough"), flags=(nCEZF,)
+
+ #(LEGACY_MODE)
+ rcri t0, t4, 1, flags=(ECF,)
+ br label("protToVirtFallThrough"), flags=(nCECF,)
+
+ panic "iret to virtual mode not supported"
+
+protToVirtFallThrough:
+
+
+
+ #temp_CPL = temp_CS.rpl
+ andi t5, t2, 0x3
+
+
+###
+### Read in the info for the new CS segment.
+###
+
+ #CS = READ_DESCRIPTOR (temp_CS, iret_chk)
+ andi t0, t2, 0xFC, flags=(EZF,), dataSize=2
+ br label("processCSDescriptor"), flags=(CEZF,)
+ andi t6, t2, 0xF8, dataSize=8
+ andi t0, t2, 0x4, flags=(EZF,), dataSize=2
+ br label("globalCSDescriptor"), flags=(CEZF,)
+ ld t8, tsl, [1, t0, t6], dataSize=8
+ br label("processCSDescriptor")
+globalCSDescriptor:
+ ld t8, tsg, [1, t0, t6], dataSize=8
+processCSDescriptor:
+ chks t2, t6, dataSize=8
+
+
+###
+### Get the new stack pointer and stack segment off the old stack if necessary,
+### and piggyback on the logic to check the new RIP value.
+###
+ #IF ((64BIT_MODE) || (temp_CPL!=CPL))
+ #{
+
+ #(64BIT_MODE)
+ andi t0, t4, 0xE, flags=(EZF,)
+ # Since we just found out we're in 64 bit mode, take advantage and
+ # do the appropriate RIP checks.
+ br label("doPopStackStuffAndCheckRIP"), flags=(CEZF,)
+
+ # Here, we know we're -not- in 64 bit mode, so we should do the
+ # appropriate/other RIP checks.
+ # if temp_RIP > CS.limit throw #GP(0)
+ rdlimit t6, cs, dataSize=8
+ subi t0, t1, t6, flags=(ECF,)
+ fault "new GeneralProtection(0)", flags=(CECF,)
+
+ #(temp_CPL!=CPL)
+ srli t7, t4, 4
+ xor t7, t7, t5
+ andi t0, t7, 0x3, flags=(EZF,)
+ br label("doPopStackStuff"), flags=(nCEZF,)
+ # We can modify user visible state here because we're know
+ # we're done with things that can fault.
+ addi rsp, rsp, "3 * env.stackSize"
+ br label("fallThroughPopStackStuff")
+
+doPopStackStuffAndCheckRIP:
+ # Check if the RIP is canonical.
+ sra t7, t1, 47, flags=(EZF,), dataSize=ssz
+ # if t7 isn't 0 or -1, it wasn't canonical.
+ br label("doPopStackStuff"), flags=(CEZF,)
+ addi t0, t7, 1, flags=(EZF,), dataSize=ssz
+ fault "new GeneralProtection(0)", flags=(nCEZF,)
+
+doPopStackStuff:
+ # POP.v temp_RSP
+ ld t6, ss, [1, t0, rsp], "3 * env.dataSize", dataSize=ssz
+ # POP.v temp_SS
+ ld t9, ss, [1, t0, rsp], "4 * env.dataSize", dataSize=ssz
+ # SS = READ_DESCRIPTOR (temp_SS, ss_chk)
+ andi t0, t9, 0xFC, flags=(EZF,), dataSize=2
+ br label("processSSDescriptor"), flags=(CEZF,)
+ andi t7, t9, 0xF8, dataSize=8
+ andi t0, t9, 0x4, flags=(EZF,), dataSize=2
+ br label("globalSSDescriptor"), flags=(CEZF,)
+ ld t7, tsl, [1, t0, t7], dataSize=8
+ br label("processSSDescriptor")
+globalSSDescriptor:
+ ld t7, tsg, [1, t0, t7], dataSize=8
+processSSDescriptor:
+ chks t9, t7, dataSize=8
+
+ # This actually updates state which is wrong. It should wait until we know
+ # we're not going to fault. Unfortunately, that's hard to do.
+ wrdl ss, t7, t9
+ wrsel ss, t9
+
+###
+### From this point downwards, we can't fault. We can update user visible state.
+###
+ # RSP.s = temp_RSP
+ mov rsp, rsp, t6, dataSize=ssz
+
+ #}
+
+fallThroughPopStackStuff:
+
+ # Update CS
+ wrdl cs, t8, t2
+ wrsel cs, t2
+
+ #CPL = temp_CPL
+
+ #IF (changing CPL)
+ #{
+ srli t7, t4, 4
+ xor t7, t7, t5
+ andi t0, t7, 0x3, flags=(EZF,)
+ br label("skipSegmentSquashing"), flags=(CEZF,)
+
+ # The attribute register needs to keep track of more info before this will
+ # work the way it needs to.
+ # FOR (seg = ES, DS, FS, GS)
+ # IF ((seg.attr.dpl < cpl && ((seg.attr.type = 'data')
+ # || (seg.attr.type = 'non-conforming-code')))
+ # {
+ # seg = NULL
+ # }
+ #}
+
+skipSegmentSquashing:
+
+ # Ignore this for now.
+ #RFLAGS.v = temp_RFLAGS
+ wrflags t0, t3
+ # VIF,VIP,IOPL only changed if (old_CPL = 0)
+ # IF only changed if (old_CPL <= old_RFLAGS.IOPL)
+ # VM unchanged
+ # RF cleared
+
+ #RIP = temp_RIP
+ wrip t0, t1, dataSize=ssz
+};
+
+def macroop IRET_VIRT {
+ panic "Virtual mode iret isn't implemented!"
+};
+'''
#let {{
# class INT(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class INTO(Inst):
-# "GenFault ${new UnimpInstFault}"
-# class IRET(Inst):
-# "GenFault ${new UnimpInstFault}"
-# class IRETD(Inst):
-# "GenFault ${new UnimpInstFault}"
-# class IRETQ(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
#}};
diff --git a/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py b/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py
index 0b2e81cbd..57ec9da26 100644
--- a/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py
+++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/xreturn.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2007 The Hewlett-Packard Development Company
+# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
@@ -85,7 +85,7 @@ def macroop RET_FAR {
ld t1, ss, [1, t0, rsp]
# Get the return CS
- ld t2, ss, [1, t0, rsp], dsz
+ ld t2, ss, [1, t0, rsp], ssz
# Get the rpl
andi t3, t2, 0x3
@@ -96,14 +96,23 @@ def macroop RET_FAR {
# that doesn't happen yet.
# Do stuff if they're equal
- chks t4, t2, flags=(EZF,)
- fault "new GeneralProtection(0)", flags=(CEZF,)
- ld t3, flatseg, [1, t0, t4], addressSize=8, dataSize=8
- wrdl cs, t3, t2
+ andi t0, t2, 0xFC, flags=(EZF,), dataSize=2
+ br label("processDescriptor"), flags=(CEZF,)
+ andi t3, t2, 0xF8, dataSize=8
+ andi t0, t2, 0x4, flags=(EZF,), dataSize=2
+ br label("globalDescriptor"), flags=(CEZF,)
+ ld t3, tsl, [1, t0, t3], dataSize=8
+ br label("processDescriptor")
+globalDescriptor:
+ ld t3, tsg, [1, t0, t3], dataSize=8
+processDescriptor:
+ chks t2, t3, IretCheck, dataSize=8
# There should be validity checks on the RIP checks here, but I'll do
# that later.
+ wrdl cs, t3, t2
+ wrsel cs, t2
wrip t0, t1
- bri t0, label("end")
+ br label("end")
# Do other stuff if they're not.
end:
diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/ascii_adjust.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/ascii_adjust.py
index a1e322e56..2cbdd1ad8 100644
--- a/src/arch/x86/isa/insts/general_purpose/data_conversion/ascii_adjust.py
+++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/ascii_adjust.py
@@ -56,11 +56,11 @@
microcode = ""
#let {{
# class AAA(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class AAD(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class AAM(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class AAS(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
#}};
diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/bcd_adjust.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/bcd_adjust.py
index 213724768..d220fdeb6 100644
--- a/src/arch/x86/isa/insts/general_purpose/data_conversion/bcd_adjust.py
+++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/bcd_adjust.py
@@ -56,7 +56,7 @@
microcode = ""
#let {{
# class DAA(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class DAS(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
#}};
diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py
index b98d09816..ac2343462 100644
--- a/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py
+++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/endian_conversion.py
@@ -53,8 +53,26 @@
#
# Authors: Gabe Black
-microcode = ""
+microcode = '''
+def macroop BSWAP_D_R
+{
+ roli reg, reg, 8, dataSize=2
+ roli reg, reg, 16, dataSize=4
+ roli reg, reg, 8, dataSize=2
+};
+
+def macroop BSWAP_Q_R
+{
+ roli reg, reg, 8, dataSize=2
+ roli reg, reg, 16, dataSize=4
+ roli reg, reg, 8, dataSize=2
+ roli reg, reg, 32, dataSize=8
+ roli reg, reg, 8, dataSize=2
+ roli reg, reg, 16, dataSize=4
+ roli reg, reg, 8, dataSize=2
+};
+'''
#let {{
# class BSWAP(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
#}};
diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/extract_sign_mask.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/extract_sign_mask.py
index 1e0810594..01fa280fc 100644
--- a/src/arch/x86/isa/insts/general_purpose/data_conversion/extract_sign_mask.py
+++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/extract_sign_mask.py
@@ -56,7 +56,7 @@
microcode = ""
#let {{
# class MOVMSKPS(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class MOVMSKPD(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
#}};
diff --git a/src/arch/x86/isa/insts/general_purpose/data_conversion/translate.py b/src/arch/x86/isa/insts/general_purpose/data_conversion/translate.py
index d6ae7885a..c334693e5 100644
--- a/src/arch/x86/isa/insts/general_purpose/data_conversion/translate.py
+++ b/src/arch/x86/isa/insts/general_purpose/data_conversion/translate.py
@@ -55,7 +55,7 @@
microcode = '''
def macroop XLAT {
- zexti t1, rax, 7
+ zexti t1, rax, 7, dataSize=8
# Here, t1 can be used directly. The value of al is supposed to be treated
# as unsigned. Since we zero extended it from 8 bits above and the address
# size has to be at least 16 bits, t1 will not be sign extended.
diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py
index 3b8608c48..60c046d04 100644
--- a/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py
+++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/move.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2007 The Hewlett-Packard Development Company
+# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
@@ -126,18 +126,19 @@ def macroop MOVSXD_R_P {
};
def macroop MOVSX_B_R_R {
- sexti reg, regm, 7
+ mov t1, t1, regm, dataSize=1
+ sexti reg, t1, 7
};
def macroop MOVSX_B_R_M {
- ld reg, seg, sib, disp, dataSize=1
- sexti reg, reg, 7
+ ld t1, seg, sib, disp, dataSize=1
+ sexti reg, t1, 7
};
def macroop MOVSX_B_R_P {
rdip t7
- ld reg, seg, riprel, disp, dataSize=1
- sexti reg, reg, 7
+ ld t1, seg, riprel, disp, dataSize=1
+ sexti reg, t1, 7
};
def macroop MOVSX_W_R_R {
@@ -160,7 +161,8 @@ def macroop MOVSX_W_R_P {
#
def macroop MOVZX_B_R_R {
- zexti reg, regm, 7
+ mov t1, t1, regm, dataSize=1
+ zexti reg, t1, 7
};
def macroop MOVZX_B_R_M {
@@ -190,13 +192,25 @@ def macroop MOVZX_W_R_P {
};
def macroop MOV_C_R {
+ .adjust_env maxOsz
wrcr reg, regm
};
def macroop MOV_R_C {
+ .adjust_env maxOsz
rdcr reg, regm
};
+def macroop MOV_D_R {
+ .adjust_env maxOsz
+ wrdr reg, regm
+};
+
+def macroop MOV_R_D {
+ .adjust_env maxOsz
+ rddr reg, regm
+};
+
def macroop MOV_R_S {
rdsel reg, regm
};
@@ -213,7 +227,7 @@ def macroop MOV_P_S {
};
def macroop MOV_REAL_S_R {
- zext t2, regm, 15
+ zexti t2, regm, 15, dataSize=8
slli t3, t2, 2, dataSize=8
wrsel reg, regm
wrbase reg, t3
@@ -221,87 +235,121 @@ def macroop MOV_REAL_S_R {
def macroop MOV_REAL_S_M {
ld t1, seg, sib, disp, dataSize=2
- zext t2, t1, 15
+ zexti t2, t1, 15, dataSize=8
slli t3, t2, 2, dataSize=8
wrsel reg, t1
wrbase reg, t3
};
def macroop MOV_REAL_S_P {
- rdip t7
- ld t1, seg, riprel, disp, dataSize=2
- zext t2, t1, 15
- slli t3, t2, 2, dataSize=8
- wrsel reg, t1
- wrbase reg, t3
+ panic "RIP relative addressing shouldn't happen in real mode"
};
def macroop MOV_S_R {
- chks t1, regm, flags=(EZF,), dataSize=8
- bri t0, label("end"), flags=(CEZF,)
- ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
- wrdl reg, t2, regm
-end:
+ andi t0, regm, 0xFC, flags=(EZF,), dataSize=2
+ br label("processDescriptor"), flags=(CEZF,)
+ andi t2, regm, 0xF8, dataSize=8
+ andi t0, regm, 0x4, flags=(EZF,), dataSize=2
+ br label("globalDescriptor"), flags=(CEZF,)
+ ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8
+ br label("processDescriptor")
+globalDescriptor:
+ ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8
+processDescriptor:
+ chks regm, t3, dataSize=8
+ wrdl reg, t3, regm
wrsel reg, regm
};
def macroop MOV_S_M {
ld t1, seg, sib, disp, dataSize=2
- chks t2, t1, flags=(EZF,), dataSize=8
- bri t0, label("end"), flags=(CEZF,)
- ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
- wrdl reg, t2, t1
-end:
+ andi t0, t1, 0xFC, flags=(EZF,), dataSize=2
+ br label("processDescriptor"), flags=(CEZF,)
+ andi t2, t1, 0xF8, dataSize=8
+ andi t0, t1, 0x4, flags=(EZF,), dataSize=2
+ br label("globalDescriptor"), flags=(CEZF,)
+ ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8
+ br label("processDescriptor")
+globalDescriptor:
+ ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8
+processDescriptor:
+ chks t1, t3, dataSize=8
+ wrdl reg, t3, t1
wrsel reg, t1
};
def macroop MOV_S_P {
rdip t7
ld t1, seg, riprel, disp, dataSize=2
- chks t2, t1, flags=(EZF,), dataSize=8
- bri t0, label("end"), flags=(CEZF,)
- ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
- wrdl reg, t2, t1
-end:
+ andi t0, t1, 0xFC, flags=(EZF,), dataSize=2
+ br label("processDescriptor"), flags=(CEZF,)
+ andi t2, t1, 0xF8, dataSize=8
+ andi t0, t1, 0x4, flags=(EZF,), dataSize=2
+ br label("globalDescriptor"), flags=(CEZF,)
+ ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8
+ br label("processDescriptor")
+globalDescriptor:
+ ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8
+processDescriptor:
+ chks t1, t3, dataSize=8
+ wrdl reg, t3, t1
wrsel reg, t1
};
def macroop MOVSS_S_R {
- chks t1, regm, flags=(EZF,), dataSize=8
- # This actually needs to use the selector as the error code, but it would
- # be hard to get that information into the instruction at the moment.
- fault "new GeneralProtection(0)", flags=(CEZF,)
- ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
- wrdl reg, t2, regm
+ andi t0, regm, 0xFC, flags=(EZF,), dataSize=2
+ br label("processDescriptor"), flags=(CEZF,)
+ andi t2, regm, 0xF8, dataSize=8
+ andi t0, regm, 0x4, flags=(EZF,), dataSize=2
+ br label("globalDescriptor"), flags=(CEZF,)
+ ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8
+ br label("processDescriptor")
+globalDescriptor:
+ ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8
+processDescriptor:
+ chks regm, t3, SSCheck, dataSize=8
+ wrdl reg, t3, regm
wrsel reg, regm
};
def macroop MOVSS_S_M {
ld t1, seg, sib, disp, dataSize=2
- chks t2, t1, flags=(EZF,), dataSize=8
- # This actually needs to use the selector as the error code, but it would
- # be hard to get that information into the instruction at the moment.
- fault "new GeneralProtection(0)", flags=(CEZF,)
- ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
- wrdl reg, t2, t1
+ andi t0, t1, 0xFC, flags=(EZF,), dataSize=2
+ br label("processDescriptor"), flags=(CEZF,)
+ andi t2, t1, 0xF8, dataSize=8
+ andi t0, t1, 0x4, flags=(EZF,), dataSize=2
+ br label("globalDescriptor"), flags=(CEZF,)
+ ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8
+ br label("processDescriptor")
+globalDescriptor:
+ ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8
+processDescriptor:
+ chks t1, t3, SSCheck, dataSize=8
+ wrdl reg, t3, t1
wrsel reg, t1
};
def macroop MOVSS_S_P {
rdip t7
ld t1, seg, riprel, disp, dataSize=2
- chks t2, t1, flags=(EZF,), dataSize=8
- # This actually needs to use the selector as the error code, but it would
- # be hard to get that information into the instruction at the moment.
- fault "new GeneralProtection(0)", flags=(CEZF,)
- ld t2, flatseg, [1, t0, t1], addressSize=8, dataSize=8
- wrdl reg, t2, t1
+ andi t0, t1, 0xFC, flags=(EZF,), dataSize=2
+ br label("processDescriptor"), flags=(CEZF,)
+ andi t2, t1, 0xF8, dataSize=8
+ andi t0, t1, 0x4, flags=(EZF,), dataSize=2
+ br label("globalDescriptor"), flags=(CEZF,)
+ ld t3, tsl, [1, t0, t2], dataSize=8, addressSize=8
+ br label("processDescriptor")
+globalDescriptor:
+ ld t3, tsg, [1, t0, t2], dataSize=8, addressSize=8
+processDescriptor:
+ chks t1, t3, SSCheck, dataSize=8
+ wrdl reg, t3, t1
wrsel reg, t1
};
'''
#let {{
# class MOVD(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class MOVNTI(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
#}};
diff --git a/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py b/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py
index 6c51f3171..82fdffc63 100644
--- a/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py
+++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2007 The Hewlett-Packard Development Company
+# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
@@ -58,8 +58,8 @@ def macroop POP_R {
# Make the default data size of pops 64 bits in 64 bit mode
.adjust_env oszIn64Override
- ld t1, ss, [1, t0, rsp]
- addi rsp, rsp, dsz
+ ld t1, ss, [1, t0, rsp], dataSize=ssz
+ addi rsp, rsp, ssz, dataSize=asz
mov reg, reg, t1
};
@@ -67,10 +67,10 @@ def macroop POP_M {
# Make the default data size of pops 64 bits in 64 bit mode
.adjust_env oszIn64Override
- ld t1, ss, [1, t0, rsp]
- cda seg, sib, disp
- addi rsp, rsp, dsz
- st t1, seg, sib, disp
+ ld t1, ss, [1, t0, rsp], dataSize=ssz
+ cda seg, sib, disp, dataSize=ssz
+ addi rsp, rsp, ssz, dataSize=asz
+ st t1, seg, sib, disp, dataSize=ssz
};
def macroop POP_P {
@@ -78,17 +78,17 @@ def macroop POP_P {
.adjust_env oszIn64Override
rdip t7
- ld t1, ss, [1, t0, rsp]
- cda seg, sib, disp
- addi rsp, rsp, dsz
- st t1, seg, riprel, disp
+ ld t1, ss, [1, t0, rsp], dataSize=ssz
+ cda seg, sib, disp, dataSize=ssz
+ addi rsp, rsp, ssz, dataSize=asz
+ st t1, seg, riprel, disp, dataSize=ssz
};
def macroop PUSH_R {
# Make the default data size of pops 64 bits in 64 bit mode
.adjust_env oszIn64Override
- stupd reg, ss, [1, t0, rsp], "-env.dataSize"
+ stupd reg, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
};
def macroop PUSH_I {
@@ -96,15 +96,15 @@ def macroop PUSH_I {
.adjust_env oszIn64Override
limm t1, imm
- stupd t1, ss, [1, t0, rsp], "-env.dataSize"
+ stupd t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
};
def macroop PUSH_M {
# Make the default data size of pops 64 bits in 64 bit mode
.adjust_env oszIn64Override
- ld t1, seg, sib, disp
- stupd t1, ss, [1, t0, rsp], "-env.dataSize"
+ ld t1, seg, sib, disp, dataSize=ssz
+ stupd t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
};
def macroop PUSH_P {
@@ -112,48 +112,48 @@ def macroop PUSH_P {
.adjust_env oszIn64Override
rdip t7
- ld t1, seg, riprel, disp
- stupd t1, ss, [1, t0, rsp], "-env.dataSize"
+ ld t1, seg, riprel, disp, dataSize=ssz
+ stupd t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
};
def macroop PUSHA {
# Check all the stack addresses. We'll assume that if the beginning and
# end are ok, then the stuff in the middle should be as well.
- cda ss, [1, t0, rsp], "-env.dataSize"
- cda ss, [1, t0, rsp], "-8 * env.dataSize"
- stupd rax, ss, [1, t0, rsp], "-env.dataSize"
- stupd rcx, ss, [1, t0, rsp], "-env.dataSize"
- stupd rdx, ss, [1, t0, rsp], "-env.dataSize"
- stupd rbx, ss, [1, t0, rsp], "-env.dataSize"
- stupd rsp, ss, [1, t0, rsp], "-env.dataSize"
- stupd rbp, ss, [1, t0, rsp], "-env.dataSize"
- stupd rsi, ss, [1, t0, rsp], "-env.dataSize"
- stupd rdi, ss, [1, t0, rsp], "-env.dataSize"
+ cda ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
+ cda ss, [1, t0, rsp], "-8 * env.stackSize", dataSize=ssz
+ stupd rax, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
+ stupd rcx, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
+ stupd rdx, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
+ stupd rbx, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
+ stupd rsp, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
+ stupd rbp, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
+ stupd rsi, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
+ stupd rdi, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
};
def macroop POPA {
# Check all the stack addresses. We'll assume that if the beginning and
# end are ok, then the stuff in the middle should be as well.
- ld t1, ss, [1, t0, rsp], "0 * env.dataSize"
- ld t2, ss, [1, t0, rsp], "7 * env.dataSize"
- mov rdi, rdi, t1
- ld rsi, ss, [1, t0, rsp], "1 * env.dataSize"
- ld rbp, ss, [1, t0, rsp], "2 * env.dataSize"
- ld rbx, ss, [1, t0, rsp], "4 * env.dataSize"
- ld rdx, ss, [1, t0, rsp], "5 * env.dataSize"
- ld rcx, ss, [1, t0, rsp], "6 * env.dataSize"
- mov rax, rax, t2
- addi rsp, rsp, "8 * env.dataSize"
+ ld t1, ss, [1, t0, rsp], "0 * env.stackSize", dataSize=ssz
+ ld t2, ss, [1, t0, rsp], "7 * env.stackSize", dataSize=ssz
+ mov rdi, rdi, t1, dataSize=ssz
+ ld rsi, ss, [1, t0, rsp], "1 * env.stackSize", dataSize=ssz
+ ld rbp, ss, [1, t0, rsp], "2 * env.stackSize", dataSize=ssz
+ ld rbx, ss, [1, t0, rsp], "4 * env.stackSize", dataSize=ssz
+ ld rdx, ss, [1, t0, rsp], "5 * env.stackSize", dataSize=ssz
+ ld rcx, ss, [1, t0, rsp], "6 * env.stackSize", dataSize=ssz
+ mov rax, rax, t2, dataSize=ssz
+ addi rsp, rsp, "8 * env.stackSize", dataSize=asz
};
def macroop LEAVE {
# Make the default data size of pops 64 bits in 64 bit mode
.adjust_env oszIn64Override
- mov t1, t1, rbp
- ld rbp, ss, [1, t0, t1]
- mov rsp, rsp, t1
- addi rsp, rsp, dsz
+ mov t1, t1, rbp, dataSize=asz
+ ld rbp, ss, [1, t0, t1], dataSize=ssz
+ mov rsp, rsp, t1, dataSize=asz
+ addi rsp, rsp, ssz, dataSize=asz
};
def macroop ENTER_I_I {
@@ -162,41 +162,41 @@ def macroop ENTER_I_I {
# Pull the different components out of the immediate
limm t1, imm
- zexti t2, t1, 15, dataSize=2
+ zexti t2, t1, 15, dataSize=8
srl t1, t1, 16
- zexti t1, t1, 5
+ zexti t1, t1, 5, dataSize=8
# t1 is now the masked nesting level, and t2 is the amount of storage.
# Push rbp.
- stupd rbp, ss, [1, t0, rsp], "-env.dataSize"
+ stupd rbp, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
# Save the stack pointer for later
- mov t6, t6, rsp
+ mov t6, t6, rsp, dataSize=asz
# If the nesting level is zero, skip all this stuff.
subi t0, t1, t0, flags=(EZF,), dataSize=2
- bri t0, label("skipLoop"), flags=(CEZF,)
+ br label("skipLoop"), flags=(CEZF,)
# If the level was 1, only push the saved rbp
subi t0, t1, 1, flags=(EZF,)
- bri t0, label("bottomOfLoop"), flags=(CEZF,)
+ br label("bottomOfLoop"), flags=(CEZF,)
limm t4, "ULL(-1)", dataSize=8
topOfLoop:
- ld t5, ss, [dsz, t4, rbp]
- stupd t5, ss, [1, t0, rsp], "-env.dataSize"
+ ld t5, ss, [ssz, t4, rbp], dataSize=ssz
+ stupd t5, ss, [1, t0, rsp], "-env.stackSize"
# If we're not done yet, loop
subi t4, t4, 1, dataSize=8
add t0, t4, t1, flags=(EZF,)
- bri t0, label("topOfLoop"), flags=(nCEZF,)
+ br label("topOfLoop"), flags=(nCEZF,)
bottomOfLoop:
# Push the old rbp onto the stack
- stupd t6, ss, [1, t0, rsp], "-env.dataSize"
+ stupd t6, ss, [1, t0, rsp], "-env.stackSize"
skipLoop:
- sub rsp, rsp, t2
- mov rbp, rbp, t6
+ sub rsp, rsp, t2, dataSize=asz
+ mov rbp, rbp, t6, dataSize=asz
};
'''
diff --git a/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py b/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py
index fe60350c1..59f6aaec2 100644
--- a/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py
+++ b/src/arch/x86/isa/insts/general_purpose/flags/push_and_pop.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2007 The Hewlett-Packard Development Company
+# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
@@ -57,17 +57,15 @@ microcode = '''
def macroop PUSHF {
.adjust_env oszIn64Override
- # This should really read the whole flags register, not just user flags.
- ruflags t1
- stupd t1, ss, [1, t0, rsp], "-env.dataSize"
+ rflags t1
+ stupd t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
};
def macroop POPF {
.adjust_env oszIn64Override
- ld t1, ss, [1, t0, rsp]
- addi rsp, rsp, dsz
- # This should really write the whole flags register, not just user flags.
- wruflags t1, t0
+ ld t1, ss, [1, t0, rsp], dataSize=ssz
+ addi rsp, rsp, ssz
+ wrflags t1, t0
};
'''
diff --git a/src/arch/x86/isa/insts/general_purpose/flags/set_and_clear.py b/src/arch/x86/isa/insts/general_purpose/flags/set_and_clear.py
index 4c655e0b2..e151dc61d 100644
--- a/src/arch/x86/isa/insts/general_purpose/flags/set_and_clear.py
+++ b/src/arch/x86/isa/insts/general_purpose/flags/set_and_clear.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2007 The Hewlett-Packard Development Company
+# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
@@ -84,10 +84,18 @@ def macroop CMC {
ruflags t1
wruflagsi t1, "CFBit"
};
+
+def macroop STI {
+ rflags t1
+ limm t2, "IFBit"
+ or t1, t1, t2
+ wrflags t1, t0
+};
+
+def macroop CLI {
+ rflags t1
+ limm t2, "~IFBit"
+ and t1, t1, t2
+ wrflags t1, t0
+};
'''
-#let {{
-# class CLI(Inst):
-# "GenFault ${new UnimpInstFault}"
-# class STI(Inst):
-# "GenFault ${new UnimpInstFault}"
-#}};
diff --git a/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py b/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py
index 1986a322e..4e3c9b316 100644
--- a/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py
+++ b/src/arch/x86/isa/insts/general_purpose/input_output/general_io.py
@@ -84,25 +84,23 @@
microcode = '''
def macroop IN_R_I {
.adjust_imm trimImm(8)
- limm t1, "IntAddrPrefixIO", dataSize=8
- ld reg, intseg, [1, t1, t0], imm, addressSize=8
+ limm t1, imm, dataSize=asz
+ ld reg, intseg, [1, t1, t0], "IntAddrPrefixIO << 3", addressSize=8
};
def macroop IN_R_R {
- limm t1, "IntAddrPrefixIO", dataSize=8
- zexti t2, regm, 15, dataSize=2
- ld reg, intseg, [1, t1, t2], addressSize=8
+ zexti t2, regm, 15, dataSize=8
+ ld reg, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8
};
def macroop OUT_I_R {
.adjust_imm trimImm(8)
- limm t1, "IntAddrPrefixIO", dataSize=8
- st reg, intseg, [1, t1, t0], imm, addressSize=8
+ limm t1, imm, dataSize=8
+ st reg, intseg, [1, t1, t0], "IntAddrPrefixIO << 3", addressSize=8
};
def macroop OUT_R_R {
- limm t1, "IntAddrPrefixIO", dataSize=8
- zexti t2, reg, 15, dataSize=2
- st regm, intseg, [1, t1, t2], addressSize=8
+ zexti t2, reg, 15, dataSize=8
+ st regm, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8
};
'''
diff --git a/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py b/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py
index b44203d9c..b3bc5ab67 100644
--- a/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py
+++ b/src/arch/x86/isa/insts/general_purpose/input_output/string_io.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2007 The Hewlett-Packard Development Company
+# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
@@ -61,32 +61,33 @@ def macroop INS_M_R {
subi t4, t0, dsz, dataSize=asz
mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
- limm t1, "IntAddrPrefixIO"
- zexti t2, reg, 15, dataSize=2
+ zexti t2, reg, 15, dataSize=8
- ld t6, intseg, [1, t1, t2], addressSize=8
+ ld t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8
st t6, es, [1, t0, rdi]
add rdi, rdi, t3, dataSize=asz
};
def macroop INS_E_M_R {
+ and t0, rcx, rcx, flags=(EZF,), dataSize=asz
+ br label("end"), flags=(CEZF,)
# Find the constant we need to either add or subtract from rdi
ruflag t0, 10
movi t3, t3, dsz, flags=(CEZF,), dataSize=asz
subi t4, t0, dsz, dataSize=asz
mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
- limm t1, "IntAddrPrefixIO"
- zexti t2, reg, 15, dataSize=2
+ zexti t2, reg, 15, dataSize=8
topOfLoop:
- ld t6, intseg, [1, t1, t2], addressSize=8
+ ld t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8
st t6, es, [1, t0, rdi]
subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
add rdi, rdi, t3, dataSize=asz
- bri t0, label("topOfLoop"), flags=(nCEZF,)
+ br label("topOfLoop"), flags=(nCEZF,)
+end:
fault "NoFault"
};
@@ -97,32 +98,33 @@ def macroop OUTS_R_M {
subi t4, t0, dsz, dataSize=asz
mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
- limm t1, "IntAddrPrefixIO"
- zexti t2, reg, 15, dataSize=2
+ zexti t2, reg, 15, dataSize=8
ld t6, ds, [1, t0, rsi]
- st t6, intseg, [1, t1, t2], addressSize=8
+ st t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8
add rsi, rsi, t3, dataSize=asz
};
def macroop OUTS_E_R_M {
+ and t0, rcx, rcx, flags=(EZF,), dataSize=asz
+ br label("end"), flags=(CEZF,)
# Find the constant we need to either add or subtract from rdi
ruflag t0, 10
movi t3, t3, dsz, flags=(CEZF,), dataSize=asz
subi t4, t0, dsz, dataSize=asz
mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
- limm t1, "IntAddrPrefixIO"
- zexti t2, reg, 15, dataSize=2
+ zexti t2, reg, 15, dataSize=8
topOfLoop:
ld t6, ds, [1, t0, rsi]
- st t6, intseg, [1, t1, t2], addressSize=8
+ st t6, intseg, [1, t2, t0], "IntAddrPrefixIO << 3", addressSize=8
subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
add rsi, rsi, t3, dataSize=asz
- bri t0, label("topOfLoop"), flags=(nCEZF,)
+ br label("topOfLoop"), flags=(nCEZF,)
+end:
fault "NoFault"
};
'''
diff --git a/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py b/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py
index 8aec4b99e..e6633ee1a 100644
--- a/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py
+++ b/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py
@@ -56,17 +56,17 @@
microcode = ""
#let {{
# class LDS(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class LES(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class LFS(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class LGS(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class LSS(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class MOV_SEG(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class POP(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
#}};
diff --git a/src/arch/x86/isa/insts/general_purpose/processor_information.py b/src/arch/x86/isa/insts/general_purpose/processor_information.py
deleted file mode 100644
index 6070169ac..000000000
--- a/src/arch/x86/isa/insts/general_purpose/processor_information.py
+++ /dev/null
@@ -1,405 +0,0 @@
-# Copyright (c) 2007 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
-
-microcode = '''
-def macroop CPUID_R {
-
-#
-# Find which type of cpuid function it is by checking bit 31. Also clear that
-# bit to form an offset into the functions of that type.
-#
- limm t1, 0x80000000, dataSize=4
- and t2, t1, rax, flags=(EZF,)
- # clear the bit
- xor t1, t2, rax
-
-#
-# Do range checking on the offset
-#
- # If EZF is set, the function is standard and the max is 0x1.
- movi t2, t2, 0x1, flags=(CEZF,)
- # If EZF is cleared, the function is extended and the max is 0x18.
- movi t2, t2, 0x18, flags=(nCEZF,)
- subi t0, t1, t2, flags=(ECF,)
- # ECF will be set if the offset is too large.
- bri t0, label("end"), flags=(nCECF,)
-
-
-#
-# Jump to the right portion
-#
- movi t2, t2, label("standardStart"), flags=(CEZF,)
- movi t2, t2, label("extendedStart"), flags=(nCEZF,)
- # This gives each function 8 microops to use. It's wasteful because only
- # 5 will be needed, but a multiply would be expensive. In the system
- # described in the RISC86 patent, the fifth instruction would really be
- # the sequencing field on an op quad, so each function would be implemented
- # by -exactly- one op quad. Since we're approximating, this should be ok.
- slli t1, t1, 3
- br t2, t1
-
-#############################################################################
-#############################################################################
-
-#
-# Standard functions.
-#
-
-standardStart:
-
-# 0x00000000 -- Processor Vendor and Largest Standard Function Number
- limm rax, 0x00000001, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x00000001 -- Family, Model, Stepping Identifiers
- limm rax, 0x00020f51, dataSize=4
- limm rbx, 0x00000405, dataSize=4
- limm rdx, 0xe3d3fbff, dataSize=4
- limm rcx, 0x00000001, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-#
-# Extended functions.
-#
-
-extendedStart:
-
-# 0x80000000 -- Processor Vendor and Largest Extended Function Number
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000001 -- EAX: AMD Family, Model, Stepping
-# EBX: BrandId Identifier
-# ECX: Feature Identifiers
-# EDX: Feature Identifiers
- limm rax, 0x00020f51, dataSize=4
- limm rbx, 0x00000405, dataSize=4
- limm rdx, 0xe3d3fbff, dataSize=4
- limm rcx, 0x00000001, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000002 -- Processor Name String Identifier
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000003 -- Processor Name String Identifier
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000004 -- Processor Name String Identifier
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000005 -- L1 Cache and TLB Identifiers
- limm rax, 0xff08ff08, dataSize=4
- limm rbx, 0xff20ff20, dataSize=4
- limm rdx, 0x40020140, dataSize=4
- limm rcx, 0x40020140, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000006 -- L2/L3 Cache and L2 TLB Identifiers
- limm rax, 0x00000000, dataSize=4
- limm rbx, 0x42004200, dataSize=4
- limm rdx, 0x00000000, dataSize=4
- limm rcx, 0x04008140, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000007 -- Advanced Power Management Information
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000008 -- Long Mode Address Size Identification
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000009 -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x8000000A -- SVM Revision and Feature Identification
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x8000000B -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x8000000C -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x8000000D -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x8000000E -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x8000000F -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000010 -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000011 -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000012 -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000013 -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000014 -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000015 -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000016 -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000017 -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-# 0x80000018 -- Reserved
- # JUNK VALUES
- limm rax, 0x80000018, dataSize=4
- limm rbx, 0x68747541, dataSize=4
- limm rdx, 0x69746e65, dataSize=4
- limm rcx, 0x444d4163, dataSize=4
- bri t0, label("end")
- fault "NoFault"
- fault "NoFault"
- fault "NoFault"
-
-end:
- fault "NoFault"
-};
-'''
diff --git a/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py b/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py
index ed7d761b8..caaeca974 100644
--- a/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py
+++ b/src/arch/x86/isa/insts/general_purpose/rotate_and_shift/shift.py
@@ -56,13 +56,13 @@
microcode = '''
def macroop SAL_R_I
{
- slli reg, reg, imm, flags=(SF,ZF,PF)
+ slli reg, reg, imm, flags=(CF,OF,SF,ZF,PF)
};
def macroop SAL_M_I
{
ldst t1, seg, sib, disp
- slli t1, t1, imm, flags=(SF,ZF,PF)
+ slli t1, t1, imm, flags=(CF,OF,SF,ZF,PF)
st t1, seg, sib, disp
};
@@ -70,19 +70,19 @@ def macroop SAL_P_I
{
rdip t7
ldst t1, seg, riprel, disp
- slli t1, t1, imm, flags=(SF,ZF,PF)
+ slli t1, t1, imm, flags=(CF,OF,SF,ZF,PF)
st t1, seg, riprel, disp
};
def macroop SAL_1_R
{
- slli reg, reg, 1, flags=(SF,ZF,PF)
+ slli reg, reg, 1, flags=(CF,OF,SF,ZF,PF)
};
def macroop SAL_1_M
{
ldst t1, seg, sib, disp
- slli t1, t1, 1, flags=(SF,ZF,PF)
+ slli t1, t1, 1, flags=(CF,OF,SF,ZF,PF)
st t1, seg, sib, disp
};
@@ -90,19 +90,19 @@ def macroop SAL_1_P
{
rdip t7
ldst t1, seg, riprel, disp
- slli t1, t1, 1, flags=(SF,ZF,PF)
+ slli t1, t1, 1, flags=(CF,OF,SF,ZF,PF)
st t1, seg, riprel, disp
};
def macroop SAL_R_R
{
- sll reg, reg, regm, flags=(SF,ZF,PF)
+ sll reg, reg, regm, flags=(CF,OF,SF,ZF,PF)
};
def macroop SAL_M_R
{
ldst t1, seg, sib, disp
- sll t1, t1, reg, flags=(SF,ZF,PF)
+ sll t1, t1, reg, flags=(CF,OF,SF,ZF,PF)
st t1, seg, sib, disp
};
@@ -110,19 +110,19 @@ def macroop SAL_P_R
{
rdip t7
ldst t1, seg, riprel, disp
- sll t1, t1, reg, flags=(SF,ZF,PF)
+ sll t1, t1, reg, flags=(CF,OF,SF,ZF,PF)
st t1, seg, riprel, disp
};
def macroop SHR_R_I
{
- srli reg, reg, imm, flags=(SF,ZF,PF)
+ srli reg, reg, imm, flags=(CF,OF,SF,ZF,PF)
};
def macroop SHR_M_I
{
ldst t1, seg, sib, disp
- srli t1, t1, imm, flags=(SF,ZF,PF)
+ srli t1, t1, imm, flags=(CF,OF,SF,ZF,PF)
st t1, seg, sib, disp
};
@@ -130,19 +130,19 @@ def macroop SHR_P_I
{
rdip t7
ldst t1, seg, riprel, disp
- srli t1, t1, imm, flags=(SF,ZF,PF)
+ srli t1, t1, imm, flags=(CF,OF,SF,ZF,PF)
st t1, seg, riprel, disp
};
def macroop SHR_1_R
{
- srli reg, reg, 1, flags=(SF,ZF,PF)
+ srli reg, reg, 1, flags=(CF,OF,SF,ZF,PF)
};
def macroop SHR_1_M
{
ldst t1, seg, sib, disp
- srli t1, t1, 1, flags=(SF,ZF,PF)
+ srli t1, t1, 1, flags=(CF,OF,SF,ZF,PF)
st t1, seg, sib, disp
};
@@ -150,19 +150,19 @@ def macroop SHR_1_P
{
rdip t7
ldst t1, seg, riprel, disp
- srli t1, t1, 1, flags=(SF,ZF,PF)
+ srli t1, t1, 1, flags=(CF,OF,SF,ZF,PF)
st t1, seg, riprel, disp
};
def macroop SHR_R_R
{
- srl reg, reg, regm, flags=(SF,ZF,PF)
+ srl reg, reg, regm, flags=(CF,OF,SF,ZF,PF)
};
def macroop SHR_M_R
{
ldst t1, seg, sib, disp
- srl t1, t1, reg, flags=(SF,ZF,PF)
+ srl t1, t1, reg, flags=(CF,OF,SF,ZF,PF)
st t1, seg, sib, disp
};
@@ -170,19 +170,54 @@ def macroop SHR_P_R
{
rdip t7
ldst t1, seg, riprel, disp
- srl t1, t1, reg, flags=(SF,ZF,PF)
+ srl t1, t1, reg, flags=(CF,OF,SF,ZF,PF)
+ st t1, seg, riprel, disp
+};
+
+# SHRD will not set OF correctly when the shift count is 1.
+def macroop SHRD_R_R_I
+{
+ srli t1, reg, imm, flags=(CF,)
+ rori t2, regm, imm
+ srli t3, regm, imm
+ xor t2, t2, t3
+ or reg, t1, t2
+};
+
+# SHRD will not set OF correctly when the shift count is 1.
+def macroop SHRD_M_R_I
+{
+ ldst t1, seg, sib, disp
+ srli t1, t1, imm, flags=(CF,)
+ rori t2, reg, imm
+ srli t3, reg, imm
+ xor t2, t2, t3
+ or t1, t1, t2
+ st t1, seg, sib, disp
+};
+
+# SHRD will not set OF correctly when the shift count is 1.
+def macroop SHRD_P_R_I
+{
+ rdip t7
+ ldst t1, seg, riprel, disp
+ srli t1, t1, imm, flags=(CF,)
+ rori t2, reg, imm
+ srli t3, reg, imm
+ xor t2, t2, t3
+ or t1, t1, t2
st t1, seg, riprel, disp
};
def macroop SAR_R_I
{
- srai reg, reg, imm, flags=(SF,ZF,PF)
+ srai reg, reg, imm, flags=(CF,OF,SF,ZF,PF)
};
def macroop SAR_M_I
{
ldst t1, seg, sib, disp
- srai t1, t1, imm, flags=(SF,ZF,PF)
+ srai t1, t1, imm, flags=(CF,OF,SF,ZF,PF)
st t1, seg, sib, disp
};
@@ -190,19 +225,19 @@ def macroop SAR_P_I
{
rdip t7
ldst t1, seg, riprel, disp
- srai t1, t1, imm, flags=(SF,ZF,PF)
+ srai t1, t1, imm, flags=(CF,OF,SF,ZF,PF)
st t1, seg, riprel, disp
};
def macroop SAR_1_R
{
- srai reg, reg, 1, flags=(SF,ZF,PF)
+ srai reg, reg, 1, flags=(CF,OF,SF,ZF,PF)
};
def macroop SAR_1_M
{
ldst t1, seg, sib, disp
- srai t1, t1, 1, flags=(SF,ZF,PF)
+ srai t1, t1, 1, flags=(CF,OF,SF,ZF,PF)
st t1, seg, sib, disp
};
@@ -210,19 +245,19 @@ def macroop SAR_1_P
{
rdip t7
ldst t1, seg, riprel, disp
- srai t1, t1, 1, flags=(SF,ZF,PF)
+ srai t1, t1, 1, flags=(CF,OF,SF,ZF,PF)
st t1, seg, riprel, disp
};
def macroop SAR_R_R
{
- sra reg, reg, regm, flags=(SF,ZF,PF)
+ sra reg, reg, regm, flags=(CF,OF,SF,ZF,PF)
};
def macroop SAR_M_R
{
ldst t1, seg, sib, disp
- sra t1, t1, reg, flags=(SF,ZF,PF)
+ sra t1, t1, reg, flags=(CF,OF,SF,ZF,PF)
st t1, seg, sib, disp
};
@@ -230,7 +265,7 @@ def macroop SAR_P_R
{
rdip t7
ldst t1, seg, riprel, disp
- sra t1, t1, reg, flags=(SF,ZF,PF)
+ sra t1, t1, reg, flags=(CF,OF,SF,ZF,PF)
st t1, seg, riprel, disp
};
'''
diff --git a/src/arch/x86/isa/insts/general_purpose/semaphores.py b/src/arch/x86/isa/insts/general_purpose/semaphores.py
index 27a31dbd9..f23241863 100644
--- a/src/arch/x86/isa/insts/general_purpose/semaphores.py
+++ b/src/arch/x86/isa/insts/general_purpose/semaphores.py
@@ -78,10 +78,30 @@ def macroop CMPXCHG_P_R {
st t1, seg, riprel, disp
mov rax, rax, t1, flags=(nCZF,)
};
+
+def macroop XADD_M_R {
+ ldst t1, seg, sib, disp
+ add t2, t1, reg, flags=(OF,SF,ZF,AF,PF,CF)
+ st t2, seg, sib, disp
+ mov reg, reg, t1
+};
+
+def macroop XADD_P_R {
+ rdip t7
+ ldst t1, seg, riprel, disp
+ add t2, t1, reg, flags=(OF,SF,ZF,AF,PF,CF)
+ st t2, seg, riprel, disp
+ mov reg, reg, t1
+};
+
+def macroop XADD_R_R {
+ add t2, regm, reg, flags=(OF,SF,ZF,AF,PF,CF)
+ mov regm, regm, reg
+ mov reg, reg, t2
+};
+
'''
#let {{
-# class XADD(Inst):
-# "GenFault ${new UnimpInstFault}"
# class XCHG(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
#}};
diff --git a/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py b/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py
index 71b8511b4..561b8a415 100644
--- a/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py
+++ b/src/arch/x86/isa/insts/general_purpose/string/compare_strings.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2007 The Hewlett-Packard Development Company
+# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
@@ -75,12 +75,16 @@ def macroop CMPS_M_M {
#
def macroop CMPS_E_M_M {
+ and t0, rcx, rcx, flags=(EZF,), dataSize=asz
+ br label("end"), flags=(CEZF,)
+
# Find the constant we need to either add or subtract from rdi
ruflag t0, 10
movi t3, t3, dsz, flags=(CEZF,), dataSize=asz
subi t4, t0, dsz, dataSize=asz
mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
+topOfLoop:
ld t1, seg, [1, t0, rsi]
ld t2, es, [1, t0, rdi]
sub t0, t1, t2, flags=(OF, SF, ZF, AF, PF, CF)
@@ -88,17 +92,22 @@ def macroop CMPS_E_M_M {
subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
add rdi, rdi, t3, dataSize=asz
add rsi, rsi, t3, dataSize=asz
- bri t0, 4, flags=(CSTRZnEZF,)
+ br label("topOfLoop"), flags=(CSTRZnEZF,)
+end:
fault "NoFault"
};
def macroop CMPS_N_M_M {
+ and t0, rcx, rcx, flags=(EZF,), dataSize=asz
+ br label("end"), flags=(CEZF,)
+
# Find the constant we need to either add or subtract from rdi
ruflag t0, 10
movi t3, t3, dsz, flags=(CEZF,), dataSize=asz
subi t4, t0, dsz, dataSize=asz
mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
+topOfLoop:
ld t1, seg, [1, t0, rsi]
ld t2, es, [1, t0, rdi]
sub t0, t1, t2, flags=(OF, SF, ZF, AF, PF, CF)
@@ -106,7 +115,8 @@ def macroop CMPS_N_M_M {
subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
add rdi, rdi, t3, dataSize=asz
add rsi, rsi, t3, dataSize=asz
- bri t0, 4, flags=(CSTRnZnEZF,)
+ br label("topOfLoop"), flags=(CSTRnZnEZF,)
+end:
fault "NoFault"
};
'''
diff --git a/src/arch/x86/isa/insts/general_purpose/string/load_string.py b/src/arch/x86/isa/insts/general_purpose/string/load_string.py
index 61525c2f2..14198701a 100644
--- a/src/arch/x86/isa/insts/general_purpose/string/load_string.py
+++ b/src/arch/x86/isa/insts/general_purpose/string/load_string.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2007 The Hewlett-Packard Development Company
+# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
@@ -61,12 +61,14 @@ def macroop LODS_M {
subi t4, t0, dsz, dataSize=asz
mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
- ld rax, seg, [1, t0, rdi]
+ ld rax, seg, [1, t0, rsi]
- add rdi, rdi, t3, dataSize=asz
+ add rsi, rsi, t3, dataSize=asz
};
def macroop LODS_E_M {
+ and t0, rcx, rcx, flags=(EZF,), dataSize=asz
+ br label("end"), flags=(CEZF,)
# Find the constant we need to either add or subtract from rdi
ruflag t0, 10
movi t3, t3, dsz, flags=(CEZF,), dataSize=asz
@@ -74,11 +76,12 @@ def macroop LODS_E_M {
mov t3, t3, t4, flags=(nCEZF,), dataSize=asz
topOfLoop:
- ld rax, seg, [1, t0, rdi]
+ ld rax, seg, [1, t0, rsi]
subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
- add rdi, rdi, t3, dataSize=asz
- bri t0, label("topOfLoop"), flags=(nCEZF,)
+ add rsi, rsi, t3, dataSize=asz
+ br label("topOfLoop"), flags=(nCEZF,)
+end:
fault "NoFault"
};
'''
diff --git a/src/arch/x86/isa/insts/general_purpose/string/move_string.py b/src/arch/x86/isa/insts/general_purpose/string/move_string.py
index b64acfdc2..18faa38e2 100644
--- a/src/arch/x86/isa/insts/general_purpose/string/move_string.py
+++ b/src/arch/x86/isa/insts/general_purpose/string/move_string.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2007 The Hewlett-Packard Development Company
+# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
@@ -69,6 +69,8 @@ def macroop MOVS_M_M {
};
def macroop MOVS_E_M_M {
+ and t0, rcx, rcx, flags=(EZF,), dataSize=asz
+ br label("end"), flags=(CEZF,)
# Find the constant we need to either add or subtract from rdi
ruflag t0, 10
movi t3, t3, dsz, flags=(CEZF,), dataSize=asz
@@ -82,7 +84,8 @@ topOfLoop:
subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
add rdi, rdi, t3, dataSize=asz
add rsi, rsi, t3, dataSize=asz
- bri t0, label("topOfLoop"), flags=(nCEZF,)
+ br label("topOfLoop"), flags=(nCEZF,)
+end:
fault "NoFault"
};
'''
diff --git a/src/arch/x86/isa/insts/general_purpose/string/scan_string.py b/src/arch/x86/isa/insts/general_purpose/string/scan_string.py
index b038cc00a..5b0e74aad 100644
--- a/src/arch/x86/isa/insts/general_purpose/string/scan_string.py
+++ b/src/arch/x86/isa/insts/general_purpose/string/scan_string.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2007 The Hewlett-Packard Development Company
+# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
@@ -73,34 +73,44 @@ def macroop SCAS_M {
#
def macroop SCAS_E_M {
+ and t0, rcx, rcx, flags=(EZF,), dataSize=asz
+ br label("end"), flags=(CEZF,)
+
# Find the constant we need to either add or subtract from rdi
ruflag t0, 10
movi t2, t2, dsz, flags=(CEZF,), dataSize=asz
subi t3, t0, dsz, dataSize=asz
mov t2, t2, t3, flags=(nCEZF,), dataSize=asz
+topOfLoop:
ld t1, es, [1, t0, rdi]
sub t0, t1, rax, flags=(OF, SF, ZF, AF, PF, CF)
subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
add rdi, rdi, t2, dataSize=asz
- bri t0, 4, flags=(CSTRZnEZF,)
+ br label("topOfLoop"), flags=(CSTRZnEZF,)
+end:
fault "NoFault"
};
def macroop SCAS_N_M {
+ and t0, rcx, rcx, flags=(EZF,), dataSize=asz
+ br label("end"), flags=(CEZF,)
+
# Find the constant we need to either add or subtract from rdi
ruflag t0, 10
movi t2, t2, dsz, flags=(CEZF,), dataSize=asz
subi t3, t0, dsz, dataSize=asz
mov t2, t2, t3, flags=(nCEZF,), dataSize=asz
+topOfLoop:
ld t1, es, [1, t0, rdi]
sub t0, t1, rax, flags=(OF, SF, ZF, AF, PF, CF)
subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
add rdi, rdi, t2, dataSize=asz
- bri t0, 4, flags=(CSTRnZnEZF,)
+ br label("topOfLoop"), flags=(CSTRnZnEZF,)
+end:
fault "NoFault"
};
diff --git a/src/arch/x86/isa/insts/general_purpose/string/store_string.py b/src/arch/x86/isa/insts/general_purpose/string/store_string.py
index a8d558929..fe9917ce6 100644
--- a/src/arch/x86/isa/insts/general_purpose/string/store_string.py
+++ b/src/arch/x86/isa/insts/general_purpose/string/store_string.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2007 The Hewlett-Packard Development Company
+# Copyright (c) 2007-2008 The Hewlett-Packard Development Company
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms,
@@ -67,6 +67,8 @@ def macroop STOS_M {
};
def macroop STOS_E_M {
+ and t0, rcx, rcx, flags=(EZF,), dataSize=asz
+ br label("end"), flags=(CEZF,)
# Find the constant we need to either add or subtract from rdi
ruflag t0, 10
movi t3, t3, dsz, flags=(CEZF,), dataSize=asz
@@ -78,7 +80,8 @@ topOfLoop:
subi rcx, rcx, 1, flags=(EZF,), dataSize=asz
add rdi, rdi, t3, dataSize=asz
- bri t0, label("topOfLoop"), flags=(nCEZF,)
+ br label("topOfLoop"), flags=(nCEZF,)
+end:
fault "NoFault"
};
'''
diff --git a/src/arch/x86/isa/insts/general_purpose/system_calls.py b/src/arch/x86/isa/insts/general_purpose/system_calls.py
index e056bea84..67607d5f8 100644
--- a/src/arch/x86/isa/insts/general_purpose/system_calls.py
+++ b/src/arch/x86/isa/insts/general_purpose/system_calls.py
@@ -53,14 +53,183 @@
#
# Authors: Gabe Black
-microcode = ""
+microcode = '''
+def macroop SYSCALL_64
+{
+ # All 1s.
+ limm t1, "(uint64_t)(-1)"
+
+ # Save the next RIP.
+ rdip rcx
+
+ # Stick rflags with RF masked into r11.
+ rflags t2
+ limm t3, "~RFBit"
+ andi r11, t2, t3, dataSize=8
+
+ rdval t3, star
+ srli t3, t3, 32, dataSize=8
+ andi t3, t3, 0xFC, dataSize=1
+
+ # Set up CS.
+ wrsel cs, t3
+ wrbase cs, t0, dataSize=8
+ wrlimit cs, t1, dataSize=4
+ # Not writable, read/execute-able, not expandDown,
+ # dpl=0, defaultSize=0, long mode
+ limm t4, ((0 << 0) | (1 << 1) | (0 << 2) | \
+ (0 << 3) | (0 << 5) | (1 << 6))
+ wrattr cs, t4
+
+ # Set up SS.
+ addi t3, t3, 8
+ wrsel ss, t3
+ wrbase ss, t0, dataSize=8
+ wrlimit ss, t1, dataSize=4
+ # Writable, readable, not expandDown,
+ # dpl=0, defaultSize=0, not long mode
+ limm t4, ((1 << 0) | (1 << 1) | (0 << 2) | \
+ (0 << 3) | (0 << 5) | (0 << 6))
+ wrattr ss, t4
+
+ # Set the new rip.
+ rdval t7, lstar
+ wrip t0, t7
+
+ # Mask the flags against sf_mask and leave RF turned off.
+ rdval t3, sf_mask, dataSize=8
+ xor t3, t3, t1, dataSize=8
+ and t3, t3, r11, dataSize=8
+ wrflags t3, t0
+};
+
+def macroop SYSCALL_COMPAT
+{
+ # All 1s.
+ limm t1, "(uint64_t)(-1)"
+
+ # Save the next RIP.
+ rdip rcx
+
+ # Stick rflags with RF masked into r11.
+ rflags t2
+ limm t3, "~RFBit"
+ andi r11, t2, t3, dataSize=8
+
+ rdval t3, star
+ srli t3, t3, 32, dataSize=8
+ andi t3, t3, 0xFC, dataSize=1
+
+ # Set up CS.
+ wrsel cs, t3
+ wrbase cs, t0, dataSize=8
+ wrlimit cs, t1, dataSize=4
+ # Not writable, read/execute-able, not expandDown,
+ # dpl=0, defaultSize=0, long mode
+ limm t4, ((0 << 0) | (1 << 1) | (0 << 2) | \
+ (0 << 3) | (0 << 5) | (1 << 6))
+ wrattr cs, t4
+
+ # Set up SS.
+ addi t3, t3, 8
+ wrsel ss, t3
+ wrbase ss, t0, dataSize=8
+ wrlimit ss, t1, dataSize=4
+ # Writable, readable, not expandDown,
+ # dpl=0, defaultSize=0, not long mode
+ limm t4, ((1 << 0) | (1 << 1) | (0 << 2) | \
+ (0 << 3) | (0 << 5) | (0 << 6))
+ wrattr ss, t4
+
+ # Set the new rip.
+ rdval t7, cstar
+ wrip t0, t7
+
+ # Mask the flags against sf_mask and leave RF turned off.
+ rdval t3, sf_mask, dataSize=8
+ xor t3, t3, t1, dataSize=8
+ and t3, t3, r11, dataSize=8
+ wrflags t3, t0
+};
+
+def macroop SYSCALL_LEGACY
+{
+ panic "The syscall instruction isn't implemented in legacy mode."
+};
+
+def macroop SYSRET_TO_64
+{
+ # All 1s.
+ limm t1, "(uint64_t)(-1)"
+
+ rdval t3, star
+ srli t3, t3, 48, dataSize=8
+ ori t3, t3, 3, dataSize=1
+
+ # Set rflags to r11 with RF and VM cleared.
+ limm t4, "~(RFBit | VMBit)"
+ and t4, t4, r11, dataSize=8
+ wrflags t4, t0
+
+ # Set up CS.
+ addi t4, t3, 16, dataSize=8
+ wrsel cs, t4
+ wrbase cs, t0, dataSize=8
+ wrlimit cs, t1, dataSize=4
+ # Not writable, read/execute-able, not expandDown,
+ # dpl=3, defaultSize=0, long mode
+ limm t4, ((0 << 0) | (1 << 1) | (0 << 2) | \
+ (3 << 3) | (0 << 5) | (1 << 6))
+ wrattr cs, t4
+
+ # Only the selector is changed for SS.
+ addi t4, t3, 8, dataSize=8
+ wrsel ss, t4
+
+ # Set the RIP back.
+ wrip rcx, t0, dataSize=8
+};
+
+def macroop SYSRET_TO_COMPAT
+{
+ # All 1s.
+ limm t1, "(uint64_t)(-1)"
+
+ rdval t3, star
+ srli t3, t3, 48, dataSize=8
+ ori t3, t3, 3, dataSize=1
+
+ # Set rflags to r11 with RF and VM cleared.
+ limm t4, "~(RFBit | VMBit)"
+ and t4, t4, r11, dataSize=8
+ wrflags t4, t0
+
+ # Set up CS.
+ wrsel cs, t3
+ wrbase cs, t0, dataSize=8
+ wrlimit cs, t1, dataSize=4
+ # Not writable, read/execute-able, not expandDown,
+ # dpl=3, defaultSize=1, not long mode
+ limm t4, ((0 << 0) | (1 << 1) | (0 << 2) | \
+ (3 << 3) | (1 << 5) | (0 << 6))
+ wrattr cs, t4
+
+ # Only the selector is changed for SS.
+ addi t4, t3, 8, dataSize=8
+ wrsel ss, t4
+
+ # Set the RIP back.
+ wrip rcx, t0, dataSize=8
+};
+
+def macroop SYSRET_NON_64
+{
+ panic "The sysret instruction isn't implemented in legacy mode."
+};
+'''
#let {{
# class SYSENTER(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
# class SYSEXIT(Inst):
-# "GenFault ${new UnimpInstFault}"
-# class SYSCALL(Inst):
-# "GenFault ${new UnimpInstFault}"
-# class SYSRET(Inst):
-# "GenFault ${new UnimpInstFault}"
+# "GenFault ${new UnimpInstFault}"
#}};
diff --git a/src/arch/x86/isa/insts/romutil.py b/src/arch/x86/isa/insts/romutil.py
new file mode 100644
index 000000000..e47259eb3
--- /dev/null
+++ b/src/arch/x86/isa/insts/romutil.py
@@ -0,0 +1,212 @@
+# 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
+
+intCodeTemplate = '''
+def rom
+{
+ # This vectors the CPU into an interrupt handler in long mode.
+ # On entry, t1 is set to the vector of the interrupt and t7 is the current
+ # ip. We need that because rdip returns the next ip.
+ extern %(startLabel)s:
+
+ #
+ # Get the 64 bit interrupt or trap gate descriptor from the IDT
+ #
+
+ # Load the gate descriptor from the IDT
+ slli t4, t1, 4, dataSize=8
+ ld t2, idtr, [1, t0, t4], 8, dataSize=8, addressSize=8, atCPL0=True
+ ld t4, idtr, [1, t0, t4], dataSize=8, addressSize=8, atCPL0=True
+
+ # Make sure the descriptor is a legal gate.
+ chks t1, t4, %(gateCheckType)s
+
+ #
+ # Get the target CS descriptor using the selector in the gate
+ # descriptor.
+ #
+ srli t10, t4, 16, dataSize=8
+ andi t5, t10, 0xF8, dataSize=8
+ andi t0, t10, 0x4, flags=(EZF,), dataSize=2
+ br rom_local_label("%(startLabel)s_globalDescriptor"), flags=(CEZF,)
+ ld t3, tsl, [1, t0, t5], dataSize=8, addressSize=8, atCPL0=True
+ br rom_local_label("%(startLabel)s_processDescriptor")
+%(startLabel)s_globalDescriptor:
+ ld t3, tsg, [1, t0, t5], dataSize=8, addressSize=8, atCPL0=True
+%(startLabel)s_processDescriptor:
+ chks t10, t3, IntCSCheck, dataSize=8
+ wrdl hs, t3, t10, dataSize=8
+
+ # Stick the target offset in t9.
+ wrdh t9, t4, t2, dataSize=8
+
+
+ #
+ # Figure out where the stack should be
+ #
+
+ # Record what we might set the stack selector to.
+ rdsel t11, ss
+
+ # Check if we're changing privelege level. At this point we can assume
+ # we're going to a DPL that's less than or equal to the CPL.
+ rdattr t10, hs, dataSize=8
+ srli t10, t10, 3, dataSize=8
+ andi t10, t10, 3, dataSize=8
+ rdattr t5, cs, dataSize=8
+ srli t5, t5, 3, dataSize=8
+ andi t5, t5, 0x3, dataSize=8
+ sub t0, t5, t10, flags=(EZF,), dataSize=8
+ # We're going to change priviledge, so zero out the stack selector. We
+ # need to let the IST have priority so we don't branch yet.
+ wrsel t11, t0, flags=(nCEZF,)
+
+ # Check the IST field of the gate descriptor
+ srli t12, t4, 32, dataSize=8
+ andi t12, t12, 0x7, dataSize=8
+ subi t0, t12, 1, flags=(ECF,), dataSize=8
+ br rom_local_label("%(startLabel)s_istStackSwitch"), flags=(nCECF,)
+ br rom_local_label("%(startLabel)s_cplStackSwitch"), flags=(nCEZF,)
+
+ # If we're here, it's because the stack isn't being switched.
+ # Set t6 to the new aligned rsp.
+ mov t6, t6, rsp, dataSize=8
+ br rom_local_label("%(startLabel)s_stackSwitched")
+
+%(startLabel)s_istStackSwitch:
+ ld t6, tr, [8, t12, t0], 0x1c, dataSize=8, addressSize=8, atCPL0=True
+ br rom_local_label("%(startLabel)s_stackSwitched")
+
+%(startLabel)s_cplStackSwitch:
+ # Get the new rsp from the TSS
+ ld t6, tr, [8, t10, t0], 4, dataSize=8, addressSize=8, atCPL0=True
+
+%(startLabel)s_stackSwitched:
+
+ andi t6, t6, 0xF0, dataSize=1
+ subi t6, t6, 40 + %(errorCodeSize)d, dataSize=8
+
+ ##
+ ## Point of no return.
+ ## We're now going to irrevocably modify visible state.
+ ## Anything bad that's going to happen should have happened by now or will
+ ## happen right now.
+ ##
+ wrip t0, t9, dataSize=8
+
+ #
+ # Set up the target code segment. Do this now so we have the right
+ # permissions when setting up the stack frame.
+ #
+ srli t5, t4, 16, dataSize=8
+ andi t5, t5, 0xFF, dataSize=8
+ wrdl cs, t3, t5, dataSize=8
+ # Tuck away the old CS for use below
+ limm t10, 0, dataSize=8
+ rdsel t10, cs, dataSize=2
+ wrsel cs, t5, dataSize=2
+
+ # Check that we can access everything we need to on the stack
+ ldst t0, hs, [1, t0, t6], dataSize=8, addressSize=8
+ ldst t0, hs, [1, t0, t6], \
+ 32 + %(errorCodeSize)d, dataSize=8, addressSize=8
+
+
+ #
+ # Build up the interrupt stack frame
+ #
+
+
+ # Write out the contents of memory
+ %(errorCodeCode)s
+ st t7, hs, [1, t0, t6], %(errorCodeSize)d, dataSize=8, addressSize=8
+ st t10, hs, [1, t0, t6], 8 + %(errorCodeSize)d, dataSize=8, addressSize=8
+ rflags t10, dataSize=8
+ st t10, hs, [1, t0, t6], 16 + %(errorCodeSize)d, dataSize=8, addressSize=8
+ st rsp, hs, [1, t0, t6], 24 + %(errorCodeSize)d, dataSize=8, addressSize=8
+ rdsel t5, ss, dataSize=2
+ st t5, hs, [1, t0, t6], 32 + %(errorCodeSize)d, dataSize=8, addressSize=8
+
+ # Set the stack segment
+ mov rsp, rsp, t6, dataSize=8
+ wrsel ss, t11, dataSize=2
+
+ #
+ # Adjust rflags which is still in t10 from above
+ #
+
+ # Set IF to the lowest bit of the original gate type.
+ # The type field of the original gate starts at bit 40.
+
+ # Set the TF, NT, and RF bits. We'll flip them at the end.
+ limm t6, (1 << 8) | (1 << 14) | (1 << 16)
+ or t10, t10, t6
+ srli t5, t4, 40, dataSize=8
+ srli t7, t10, 9, dataSize=8
+ xor t5, t7, t5, dataSize=8
+ andi t5, t5, 1, dataSize=8
+ slli t5, t5, 9, dataSize=8
+ or t6, t5, t6, dataSize=8
+
+ # Put the results into rflags
+ wrflags t6, t10
+
+ eret
+};
+'''
+
+microcode = \
+intCodeTemplate % {\
+ "startLabel" : "longModeInterrupt",
+ "gateCheckType" : "IntGateCheck",
+ "errorCodeSize" : 0,
+ "errorCodeCode" : ""
+} + \
+intCodeTemplate % {\
+ "startLabel" : "longModeSoftInterrupt",
+ "gateCheckType" : "SoftIntGateCheck",
+ "errorCodeSize" : 0,
+ "errorCodeCode" : ""
+} + \
+intCodeTemplate % {\
+ "startLabel" : "longModeInterruptWithError",
+ "gateCheckType" : "IntGateCheck",
+ "errorCodeSize" : 8,
+ "errorCodeCode" : '''
+ st t15, hs, [1, t0, t6], dataSize=8, addressSize=8
+ '''
+} + \
+'''
+def rom
+{
+ # This vectors the CPU into an interrupt handler in legacy mode.
+ extern legacyModeInterrupt:
+ panic "Legacy mode interrupts not implemented (in microcode)"
+ eret
+};
+'''
diff --git a/src/arch/x86/isa/insts/system/__init__.py b/src/arch/x86/isa/insts/system/__init__.py
index 409a929f5..0dec9ebda 100644
--- a/src/arch/x86/isa/insts/system/__init__.py
+++ b/src/arch/x86/isa/insts/system/__init__.py
@@ -81,7 +81,8 @@
#
# Authors: Gabe Black
-categories = ["halt",
+categories = ["control_registers",
+ "halt",
"invlpg",
"undefined_operation",
"msrs",
diff --git a/src/arch/x86/isa/insts/system/control_registers.py b/src/arch/x86/isa/insts/system/control_registers.py
new file mode 100644
index 000000000..902c01abb
--- /dev/null
+++ b/src/arch/x86/isa/insts/system/control_registers.py
@@ -0,0 +1,35 @@
+# Copyright (c) 2009 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
+
+microcode = '''
+def macroop CLTS {
+ rdcr t1, 0, dataSize=8
+ andi t1, t1, 0xF7, dataSize=1
+ wrcr 0, t1, dataSize=8
+};
+'''
diff --git a/src/arch/x86/isa/insts/system/msrs.py b/src/arch/x86/isa/insts/system/msrs.py
index 1acb4c792..7f283c8c1 100644
--- a/src/arch/x86/isa/insts/system/msrs.py
+++ b/src/arch/x86/isa/insts/system/msrs.py
@@ -84,8 +84,8 @@
microcode = '''
def macroop RDMSR
{
- limm t1, "IntAddrPrefixMSR >> 3"
- ld t2, intseg, [8, t1, rcx], dataSize=8, addressSize=4
+ ld t2, intseg, [8, rcx, t0], "IntAddrPrefixMSR << 3", \
+ dataSize=8, addressSize=8
mov rax, rax, t2, dataSize=4
srli t2, t2, 32, dataSize=8
mov rdx, rdx, t2, dataSize=4
@@ -93,10 +93,18 @@ def macroop RDMSR
def macroop WRMSR
{
- limm t1, "IntAddrPrefixMSR >> 3"
mov t2, t2, rax, dataSize=4
slli t3, rdx, 32, dataSize=8
or t2, t2, t3, dataSize=8
- st t2, intseg, [8, t1, rcx], dataSize=8, addressSize=4
+ st t2, intseg, [8, rcx, t0], "IntAddrPrefixMSR << 3", \
+ dataSize=8, addressSize=8
+};
+
+def macroop RDTSC
+{
+ rdtsc t1
+ mov rax, rax, t1, dataSize=4
+ srli t1, t1, 32, dataSize=8
+ mov rdx, rdx, t1, dataSize=4
};
'''
diff --git a/src/arch/x86/isa/insts/system/segmentation.py b/src/arch/x86/isa/insts/system/segmentation.py
index 97846f79c..acbca9f6e 100644
--- a/src/arch/x86/isa/insts/system/segmentation.py
+++ b/src/arch/x86/isa/insts/system/segmentation.py
@@ -56,7 +56,7 @@
microcode = '''
def macroop LGDT_M
{
- .adjust_env oszForPseudoDesc
+ .adjust_env maxOsz
# Get the limit
ld t1, seg, sib, disp, dataSize=2
@@ -68,7 +68,7 @@ def macroop LGDT_M
def macroop LGDT_P
{
- .adjust_env oszForPseudoDesc
+ .adjust_env maxOsz
rdip t7
# Get the limit
@@ -86,34 +86,34 @@ def macroop LGDT_P
def macroop LGDT_16_M
{
- .adjust_env oszForPseudoDesc
+ .adjust_env maxOsz
# Get the limit
ld t1, seg, sib, disp, dataSize=2
# Get the base
ld t2, seg, sib, 'adjustedDisp + 2', dataSize=4
- zexti t2, t2, 23
+ zexti t2, t2, 23, dataSize=8
wrbase tsg, t2
wrlimit tsg, t1
};
def macroop LGDT_16_P
{
- .adjust_env oszForPseudoDesc
+ .adjust_env maxOsz
rdip t7
# Get the limit
ld t1, seg, riprel, disp, dataSize=2
# Get the base
ld t2, seg, riprel, 'adjustedDisp + 2', dataSize=4
- zexti t2, t2, 23
+ zexti t2, t2, 23, dataSize=8
wrbase tsg, t2
wrlimit tsg, t1
};
def macroop LIDT_M
{
- .adjust_env oszForPseudoDesc
+ .adjust_env maxOsz
# Get the limit
ld t1, seg, sib, disp, dataSize=2
@@ -125,7 +125,7 @@ def macroop LIDT_M
def macroop LIDT_P
{
- .adjust_env oszForPseudoDesc
+ .adjust_env maxOsz
rdip t7
# Get the limit
@@ -143,28 +143,135 @@ def macroop LIDT_P
def macroop LIDT_16_M
{
- .adjust_env oszForPseudoDesc
+ .adjust_env maxOsz
# Get the limit
ld t1, seg, sib, disp, dataSize=2
# Get the base
ld t2, seg, sib, 'adjustedDisp + 2', dataSize=4
- zexti t2, t2, 23
+ zexti t2, t2, 23, dataSize=8
wrbase idtr, t2
wrlimit idtr, t1
};
def macroop LIDT_16_P
{
- .adjust_env oszForPseudoDesc
+ .adjust_env maxOsz
rdip t7
# Get the limit
ld t1, seg, riprel, disp, dataSize=2
# Get the base
ld t2, seg, riprel, 'adjustedDisp + 2', dataSize=4
- zexti t2, t2, 23
+ zexti t2, t2, 23, dataSize=8
wrbase idtr, t2
wrlimit idtr, t1
};
+
+def macroop LTR_R
+{
+ chks reg, t0, TRCheck
+ limm t4, 0
+ srli t4, reg, 3, dataSize=2
+ ldst t1, tsg, [8, t4, t0], dataSize=8
+ ld t2, tsg, [8, t4, t0], 8, dataSize=8
+ chks reg, t1, TSSCheck
+ wrdh t3, t1, t2
+ wrdl tr, t1, reg
+ wrbase tr, t3, dataSize=8
+ ori t1, t1, (1 << 9)
+ st t1, tsg, [8, t4, t0], dataSize=8
+};
+
+def macroop LTR_M
+{
+ ld t5, seg, sib, disp, dataSize=2
+ chks t5, t0, TRCheck
+ limm t4, 0
+ srli t4, t5, 3, dataSize=2
+ ldst t1, tsg, [8, t4, t0], dataSize=8
+ ld t2, tsg, [8, t4, t0], 8, dataSize=8
+ chks t5, t1, TSSCheck
+ wrdh t3, t1, t2
+ wrdl tr, t1, t5
+ wrbase tr, t3, dataSize=8
+ ori t1, t1, (1 << 9)
+ st t1, tsg, [8, t4, t0], dataSize=8
+};
+
+def macroop LTR_P
+{
+ rdip t7
+ ld t5, seg, riprel, disp, dataSize=2
+ chks t5, t0, TRCheck
+ limm t4, 0
+ srli t4, t5, 3, dataSize=2
+ ldst t1, tsg, [8, t4, t0], dataSize=8
+ ld t2, tsg, [8, t4, t0], 8, dataSize=8
+ chks t5, t1, TSSCheck
+ wrdh t3, t1, t2
+ wrdl tr, t1, t5
+ wrbase tr, t3, dataSize=8
+ ori t1, t1, (1 << 9)
+ st t1, tsg, [8, t4, t0], dataSize=8
+};
+
+def macroop LLDT_R
+{
+ chks reg, t0, InGDTCheck, flags=(EZF,)
+ br label("end"), flags=(CEZF,)
+ limm t4, 0
+ srli t4, reg, 3, dataSize=2
+ ldst t1, tsg, [8, t4, t0], dataSize=8
+ ld t2, tsg, [8, t4, t0], 8, dataSize=8
+ chks reg, t1, LDTCheck
+ wrdh t3, t1, t2
+ wrdl tr, t1, reg
+ wrbase tr, t3, dataSize=8
+end:
+ fault "NoFault"
+};
+
+def macroop LLDT_M
+{
+ ld t5, seg, sib, disp, dataSize=2
+ chks t5, t0, InGDTCheck, flags=(EZF,)
+ br label("end"), flags=(CEZF,)
+ limm t4, 0
+ srli t4, t5, 3, dataSize=2
+ ldst t1, tsg, [8, t4, t0], dataSize=8
+ ld t2, tsg, [8, t4, t0], 8, dataSize=8
+ chks t5, t1, LDTCheck
+ wrdh t3, t1, t2
+ wrdl tr, t1, t5
+ wrbase tr, t3, dataSize=8
+end:
+ fault "NoFault"
+};
+
+def macroop LLDT_P
+{
+ rdip t7
+ ld t5, seg, riprel, disp, dataSize=2
+ chks t5, t0, InGDTCheck, flags=(EZF,)
+ br label("end"), flags=(CEZF,)
+ limm t4, 0
+ srli t4, t5, 3, dataSize=2
+ ldst t1, tsg, [8, t4, t0], dataSize=8
+ ld t2, tsg, [8, t4, t0], 8, dataSize=8
+ chks t5, t1, LDTCheck
+ wrdh t3, t1, t2
+ wrdl tr, t1, t5
+ wrbase tr, t3, dataSize=8
+end:
+ fault "NoFault"
+};
+
+def macroop SWAPGS
+{
+ rdval t1, kernel_gs_base, dataSize=8
+ rdbase t2, gs, dataSize=8
+ wrbase gs, t1, dataSize=8
+ wrval kernel_gs_base, t2, dataSize=8
+};
'''
diff --git a/src/arch/x86/isa/macroop.isa b/src/arch/x86/isa/macroop.isa
index 4818b926c..3a836ff68 100644
--- a/src/arch/x86/isa/macroop.isa
+++ b/src/arch/x86/isa/macroop.isa
@@ -72,41 +72,13 @@ def template MacroExecPanic {{
output header {{
// Base class for combinationally generated macroops
- class Macroop : public StaticInst
+ class Macroop : public X86ISA::MacroopBase
{
- protected:
- const uint32_t numMicroops;
-
- //Constructor.
+ public:
Macroop(const char *mnem, ExtMachInst _machInst,
- uint32_t _numMicroops)
- : StaticInst(mnem, _machInst, No_OpClass),
- numMicroops(_numMicroops)
- {
- assert(numMicroops);
- microops = new StaticInstPtr[numMicroops];
- flags[IsMacroop] = true;
- }
-
- ~Macroop()
- {
- delete [] microops;
- }
-
- StaticInstPtr * microops;
-
- StaticInstPtr fetchMicroop(MicroPC microPC)
- {
- assert(microPC < numMicroops);
- return microops[microPC];
- }
-
- std::string generateDisassembly(Addr pc,
- const SymbolTable *symtab) const
- {
- return mnemonic;
- }
-
+ uint32_t _numMicroops, X86ISA::EmulEnv _env)
+ : MacroopBase(mnem, _machInst, _numMicroops, _env)
+ {}
%(MacroExecPanic)s
};
}};
@@ -130,22 +102,42 @@ def template MacroDeclare {{
%(declareLabels)s
public:
// Constructor.
- %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv env);
+ %(class_name)s(ExtMachInst machInst, X86ISA::EmulEnv _env);
+
+ std::string
+ generateDisassembly(Addr pc, const SymbolTable *symtab) const;
};
};
}};
+def template MacroDisassembly {{
+ std::string
+ X86Macroop::%(class_name)s::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream out;
+ out << mnemonic << "\t";
+
+ int regSize = %(regSize)s;
+ %(disassembly)s
+ // Shut up gcc.
+ regSize = regSize;
+ return out.str();
+ }
+}};
+
// Basic instruction class constructor template.
def template MacroConstructor {{
inline X86Macroop::%(class_name)s::%(class_name)s(
- ExtMachInst machInst, EmulEnv env)
- : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s)
+ ExtMachInst machInst, EmulEnv _env)
+ : %(base_class)s("%(mnemonic)s", machInst, %(num_microops)s, _env)
{
%(adjust_env)s;
%(adjust_imm)s;
%(adjust_disp)s;
- %(do_modrm)s;
+ %(init_env)s;
%(constructor)s;
+ const char *macrocodeBlock = "%(class_name)s";
//alloc_microops is the code that sets up the microops
//array in the parent class.
%(alloc_microops)s;
@@ -174,7 +166,7 @@ let {{
}
self.declared = False
self.adjust_env = ""
- self.doModRM = ""
+ self.init_env = ""
self.adjust_imm = '''
uint64_t adjustedImm = IMMEDIATE;
//This is to pacify gcc in case the immediate isn't used.
@@ -186,7 +178,12 @@ let {{
adjustedDisp = adjustedDisp;
'''
def getAllocator(self, env):
- return "new X86Macroop::%s(machInst, %s)" % (self.name, env.getAllocator())
+ return "new X86Macroop::%s(machInst, %s)" % \
+ (self.name, env.getAllocator())
+ def getMnemonic(self):
+ mnemonic = self.name.lower()
+ mnemonic = re.match(r'[^_]*', mnemonic).group(0)
+ return mnemonic
def getDeclaration(self):
#FIXME This first parameter should be the mnemonic. I need to
#write some code which pulls that out
@@ -194,32 +191,46 @@ let {{
for (label, microop) in self.labels.items():
declareLabels += "const static uint64_t label_%s = %d;\n" \
% (label, microop.micropc)
- iop = InstObjParams(self.name, self.name, "Macroop",
+ iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
{"code" : "",
"declareLabels" : declareLabels
})
return MacroDeclare.subst(iop);
- def getDefinition(self):
+ def getDefinition(self, env):
#FIXME This first parameter should be the mnemonic. I need to
#write some code which pulls that out
numMicroops = len(self.microops)
allocMicroops = ''
micropc = 0
for op in self.microops:
+ isLast = (micropc == numMicroops - 1)
allocMicroops += \
"microops[%d] = %s;\n" % \
- (micropc, op.getAllocator(True, False,
- micropc == 0,
- micropc == numMicroops - 1))
+ (micropc, op.getAllocator(True, not isLast,
+ micropc == 0, isLast))
micropc += 1
- iop = InstObjParams(self.name, self.name, "Macroop",
+ if env.useStackSize:
+ useStackSize = "true"
+ else:
+ useStackSize = "false"
+ if env.memoryInst:
+ memoryInst = "true"
+ else:
+ memoryInst = "false"
+ regSize = '''(%s || (env.base == INTREG_RSP && %s) ?
+ env.stackSize :
+ env.dataSize)''' % (useStackSize, memoryInst)
+ iop = InstObjParams(self.getMnemonic(), self.name, "Macroop",
{"code" : "", "num_microops" : numMicroops,
"alloc_microops" : allocMicroops,
"adjust_env" : self.adjust_env,
"adjust_imm" : self.adjust_imm,
"adjust_disp" : self.adjust_disp,
- "do_modrm" : self.doModRM})
- return MacroConstructor.subst(iop);
+ "disassembly" : env.disassembly,
+ "regSize" : regSize,
+ "init_env" : self.initEnv})
+ return MacroConstructor.subst(iop) + \
+ MacroDisassembly.subst(iop);
}};
let {{
@@ -235,6 +246,16 @@ let {{
self.dataSize = "OPSIZE"
self.stackSize = "STACKSIZE"
self.doModRM = False
+ self.disassembly = ""
+ self.firstArgument = True
+ self.useStackSize = False
+ self.memoryInst = False
+
+ def addToDisassembly(self, code):
+ if not self.firstArgument:
+ self.disassembly += "out << \", \";\n"
+ self.firstArgument = False
+ self.disassembly += code
def getAllocator(self):
if self.size == 'b':
@@ -283,6 +304,7 @@ let {{
let {{
doModRMString = "env.doModRM(machInst);\n"
+ noModRMString = "env.setSeg(machInst);\n"
def genMacroop(Name, env):
blocks = OutputBlocks()
if not macroopDict.has_key(Name):
@@ -290,9 +312,11 @@ let {{
macroop = macroopDict[Name]
if not macroop.declared:
if env.doModRM:
- macroop.doModRM = doModRMString
+ macroop.initEnv = doModRMString
+ else:
+ macroop.initEnv = noModRMString
blocks.header_output = macroop.getDeclaration()
- blocks.decoder_output = macroop.getDefinition()
+ blocks.decoder_output = macroop.getDefinition(env)
macroop.declared = True
blocks.decode_block = "return %s;\n" % macroop.getAllocator(env)
return blocks
diff --git a/src/arch/x86/isa/microasm.isa b/src/arch/x86/isa/microasm.isa
index 78ae34f52..c7c6dae2e 100644
--- a/src/arch/x86/isa/microasm.isa
+++ b/src/arch/x86/isa/microasm.isa
@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
-// Copyright (c) 2007 The Hewlett-Packard Development Company
+// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
// All rights reserved.
//
// Redistribution and use of this software in source and binary forms,
@@ -64,23 +64,32 @@
//Include code to build macroops in both C++ and python.
##include "macroop.isa"
+//Include code to fill out the microcode ROM in both C++ and python.
+##include "rom.isa"
+
let {{
import sys
sys.path[0:0] = ["src/arch/x86/isa/"]
from insts import microcode
# print microcode
- from micro_asm import MicroAssembler, Rom_Macroop, Rom
- mainRom = Rom('main ROM')
+ from micro_asm import MicroAssembler, Rom_Macroop
+ mainRom = X86MicrocodeRom('main ROM')
assembler = MicroAssembler(X86Macroop, microopClasses, mainRom, Rom_Macroop)
# Add in symbols for the microcode registers
- for num in range(15):
+ for num in range(16):
assembler.symbols["t%d" % num] = "NUM_INTREGS+%d" % num
- for num in range(7):
+ for num in range(8):
assembler.symbols["ufp%d" % num] = "FLOATREG_MICROFP(%d)" % num
# Add in symbols for the segment descriptor registers
- for letter in ("C", "D", "E", "F", "G", "S"):
+ for letter in ("C", "D", "E", "F", "G", "H", "S"):
assembler.symbols["%ss" % letter.lower()] = "SEGMENT_REG_%sS" % letter
+ # Add in symbols for the various checks of segment selectors.
+ for check in ("NoCheck", "CSCheck", "CallGateCheck", "IntGateCheck",
+ "SoftIntGateCheck", "SSCheck", "IretCheck", "IntCSCheck",
+ "TRCheck", "TSSCheck", "InGDTCheck", "LDTCheck"):
+ assembler.symbols[check] = "Seg%s" % check
+
for reg in ("TR", "IDTR"):
assembler.symbols[reg.lower()] = "SYS_SEGMENT_REG_%s" % reg
@@ -129,13 +138,15 @@ let {{
# like the internal segment above
assembler.symbols["flatseg"] = "SEGMENT_REG_LS"
- for reg in ('ax', 'bx', 'cx', 'dx', 'sp', 'bp', 'si', 'di'):
+ for reg in ('ax', 'bx', 'cx', 'dx', 'sp', 'bp', 'si', 'di', \
+ '8', '9', '10', '11', '12', '13', '14', '15'):
assembler.symbols["r%s" % reg] = "INTREG_R%s" % reg.upper()
- for reg in range(15):
+ for reg in range(16):
assembler.symbols["cr%d" % reg] = "MISCREG_CR%d" % reg
- for flag in ('CF', 'PF', 'ECF', 'AF', 'EZF', 'ZF', 'SF', 'OF'):
+ for flag in ('CF', 'PF', 'ECF', 'AF', 'EZF', 'ZF', 'SF', 'OF', \
+ 'TF', 'IF', 'NT', 'RF', 'VM', 'AC', 'VIF', 'VIP', 'ID'):
assembler.symbols[flag] = flag + "Bit"
for cond in ('True', 'False', 'ECF', 'EZF', 'SZnZF',
@@ -150,6 +161,11 @@ let {{
assembler.symbols["CTrue"] = "ConditionTests::True"
assembler.symbols["CFalse"] = "ConditionTests::False"
+ for reg in ('sysenter_cs', 'sysenter_esp', 'sysenter_eip',
+ 'star', 'lstar', 'cstar', 'sf_mask',
+ 'kernel_gs_base'):
+ assembler.symbols[reg] = "MISCREG_%s" % reg.upper()
+
# Code literal which forces a default 64 bit operand size in 64 bit mode.
assembler.symbols["oszIn64Override"] = '''
if (machInst.mode.submode == SixtyFourBitMode &&
@@ -157,7 +173,7 @@ let {{
env.dataSize = 8;
'''
- assembler.symbols["oszForPseudoDesc"] = '''
+ assembler.symbols["maxOsz"] = '''
if (machInst.mode.submode == SixtyFourBitMode)
env.dataSize = 8;
else
@@ -174,10 +190,23 @@ let {{
assembler.symbols["label"] = labeler
+ def rom_labeler(labelStr):
+ return "romMicroPC(RomLabels::extern_label_%s)" % labelStr
+
+ assembler.symbols["rom_label"] = rom_labeler
+
+ def rom_local_labeler(labelStr):
+ return "romMicroPC(RomLabels::label_%s)" % labelStr
+
+ assembler.symbols["rom_local_label"] = rom_local_labeler
+
def stack_index(index):
return "(NUM_FLOATREGS + (((%s) + 8) %% 8))" % index
assembler.symbols["st"] = stack_index
macroopDict = assembler.assemble(microcode)
+
+ decoder_output += mainRom.getDefinition()
+ header_output += mainRom.getDeclaration()
}};
diff --git a/src/arch/x86/isa/microops/base.isa b/src/arch/x86/isa/microops/base.isa
index 75658a26c..f1007bf71 100644
--- a/src/arch/x86/isa/microops/base.isa
+++ b/src/arch/x86/isa/microops/base.isa
@@ -69,6 +69,29 @@ let {{
let {{
class X86Microop(object):
+
+ generatorNameTemplate = "generate_%s_%d"
+
+ generatorTemplate = '''
+ StaticInstPtr
+ ''' + generatorNameTemplate + '''(StaticInstPtr curMacroop)
+ {
+ static const char *macrocodeBlock = romMnemonic;
+ static const ExtMachInst dummyExtMachInst;
+ static const EmulEnv dummyEmulEnv(0, 0, 1, 1, 1);
+
+ Macroop * macroop = dynamic_cast<Macroop *>(curMacroop.get());
+ const ExtMachInst &machInst =
+ macroop ? macroop->getExtMachInst() : dummyExtMachInst;
+ const EmulEnv &env =
+ macroop ? macroop->getEmulEnv() : dummyEmulEnv;
+ // env may not be used in the microop's constructor.
+ RegIndex reg = env.reg;
+ reg = reg;
+ using namespace RomLabels;
+ return %s;
+ }
+ '''
def __init__(self, name):
self.name = name
@@ -91,4 +114,12 @@ let {{
def getAllocator(self, mnemonic, *microFlags):
return 'new %s(machInst, %s)' % \
(self.className, mnemonic, self.microFlagsText(microFlags))
+
+ def getGeneratorDef(self, micropc):
+ return self.generatorTemplate % \
+ (self.className, micropc, \
+ self.getAllocator(True, True, False, False))
+
+ def getGenerator(self, micropc):
+ return self.generatorNameTemplate % (self.className, micropc)
}};
diff --git a/src/arch/x86/isa/microops/debug.isa b/src/arch/x86/isa/microops/debug.isa
new file mode 100644
index 000000000..38fee59bb
--- /dev/null
+++ b/src/arch/x86/isa/microops/debug.isa
@@ -0,0 +1,229 @@
+// 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
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Debug Microops
+//
+//////////////////////////////////////////////////////////////////////////
+
+output header {{
+ class MicroDebugBase : public X86ISA::X86MicroopBase
+ {
+ protected:
+ std::string message;
+ uint8_t cc;
+
+ public:
+ MicroDebugBase(ExtMachInst _machInst, const char * mnem,
+ const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ std::string _message, uint8_t _cc);
+
+ MicroDebugBase(ExtMachInst _machInst, const char * mnem,
+ const char * instMnem, std::string _message, uint8_t _cc);
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+}};
+
+def template MicroDebugDeclare {{
+ class %(class_name)s : public %(base_class)s
+ {
+ private:
+ void buildMe();
+ public:
+ %(class_name)s(ExtMachInst _machInst, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ std::string _message, uint8_t _cc);
+
+ %(class_name)s(ExtMachInst _machInst, const char * instMnem,
+ std::string _message, uint8_t _cc);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+def template MicroDebugExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ %(op_decl)s
+ %(op_rd)s
+ if (%(cond_test)s) {
+ %(func)s("%s\n", message);
+ }
+ return NoFault;
+ }
+}};
+
+output decoder {{
+ inline MicroDebugBase::MicroDebugBase(
+ ExtMachInst machInst, const char * mnem, const char * instMnem,
+ std::string _message, uint8_t _cc) :
+ X86MicroopBase(machInst, mnem, instMnem,
+ false, false, false, false, No_OpClass),
+ message(_message), cc(_cc)
+ {
+ }
+
+ inline MicroDebugBase::MicroDebugBase(
+ ExtMachInst machInst, const char * mnem, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ std::string _message, uint8_t _cc) :
+ X86MicroopBase(machInst, mnem, instMnem,
+ isMicro, isDelayed, isFirst, isLast, No_OpClass),
+ message(_message), cc(_cc)
+ {
+ }
+}};
+
+def template MicroDebugConstructor {{
+
+ inline void %(class_name)s::buildMe()
+ {
+ %(constructor)s;
+ }
+
+ inline %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem,
+ std::string _message, uint8_t _cc) :
+ %(base_class)s(machInst, "%(func)s", instMnem, _message, _cc)
+ {
+ buildMe();
+ }
+
+ inline %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ std::string _message, uint8_t _cc) :
+ %(base_class)s(machInst, "%(func)s", instMnem,
+ isMicro, isDelayed, isFirst, isLast, _message, _cc)
+ {
+ buildMe();
+ }
+}};
+
+output decoder {{
+ std::string MicroDebugBase::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+
+ printMnemonic(response, instMnem, mnemonic);
+ response << "\"" << message << "\"";
+
+ return response.str();
+ }
+}};
+
+let {{
+ class MicroDebug(X86Microop):
+ def __init__(self, message, flags=None):
+ self.message = message
+ if flags:
+ if not isinstance(flags, (list, tuple)):
+ raise Exception, "flags must be a list or tuple of flags"
+ self.cond = " | ".join(flags)
+ self.className += "Flags"
+ else:
+ self.cond = "0"
+
+ def getAllocator(self, *microFlags):
+ allocator = '''new %(class_name)s(machInst, macrocodeBlock
+ %(flags)s, "%(message)s", %(cc)s)''' % {
+ "class_name" : self.className,
+ "flags" : self.microFlagsText(microFlags),
+ "message" : self.message,
+ "cc" : self.cond}
+ return allocator
+
+ exec_output = ""
+ header_output = ""
+ decoder_output = ""
+
+ def buildDebugMicro(func):
+ global exec_output, header_output, decoder_output
+
+ iop = InstObjParams(func, "Micro%sFlags" % func.capitalize(),
+ "MicroDebugBase",
+ {"code": "",
+ "func": func,
+ "cond_test": "checkCondition(ccFlagBits, cc)"})
+ exec_output += MicroDebugExecute.subst(iop)
+ header_output += MicroDebugDeclare.subst(iop)
+ decoder_output += MicroDebugConstructor.subst(iop)
+
+ iop = InstObjParams(func, "Micro%s" % func.capitalize(),
+ "MicroDebugBase",
+ {"code": "",
+ "func": func,
+ "cond_test": "true"})
+ exec_output += MicroDebugExecute.subst(iop)
+ header_output += MicroDebugDeclare.subst(iop)
+ decoder_output += MicroDebugConstructor.subst(iop)
+
+ class MicroDebugChild(MicroDebug):
+ className = "Micro%s" % func.capitalize()
+
+ global microopClasses
+ microopClasses[func] = MicroDebugChild
+
+ buildDebugMicro("panic")
+ buildDebugMicro("fatal")
+ buildDebugMicro("warn")
+ buildDebugMicro("warn_once")
+}};
diff --git a/src/arch/x86/isa/microops/fpop.isa b/src/arch/x86/isa/microops/fpop.isa
index 2919aa277..d4acfdbf4 100644
--- a/src/arch/x86/isa/microops/fpop.isa
+++ b/src/arch/x86/isa/microops/fpop.isa
@@ -245,7 +245,7 @@ let {{
self.className += "Top"
def getAllocator(self, *microFlags):
- return '''new %(class_name)s(machInst, mnemonic
+ return '''new %(class_name)s(machInst, macrocodeBlock
%(flags)s, %(src1)s, %(src2)s, %(dest)s,
%(dataSize)s, %(spm)d)''' % {
"class_name" : self.className,
diff --git a/src/arch/x86/isa/microops/ldstop.isa b/src/arch/x86/isa/microops/ldstop.isa
index cb63e7cd9..af94cf31e 100644
--- a/src/arch/x86/isa/microops/ldstop.isa
+++ b/src/arch/x86/isa/microops/ldstop.isa
@@ -124,14 +124,16 @@ def template MicroLeaDeclare {{
uint8_t _scale, RegIndex _index, RegIndex _base,
uint64_t _disp, uint8_t _segment,
RegIndex _data,
- uint8_t _dataSize, uint8_t _addressSize);
+ uint8_t _dataSize, uint8_t _addressSize,
+ Request::FlagsType _memFlags);
%(class_name)s(ExtMachInst _machInst,
const char * instMnem,
uint8_t _scale, RegIndex _index, RegIndex _base,
uint64_t _disp, uint8_t _segment,
RegIndex _data,
- uint8_t _dataSize, uint8_t _addressSize);
+ uint8_t _dataSize, uint8_t _addressSize,
+ Request::FlagsType _memFlags);
%(BasicExecDeclare)s
};
@@ -151,11 +153,13 @@ def template MicroLoadExecute {{
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
- fault = read(xc, EA, Mem, (%(mem_flags)s) | segment);
+ fault = read(xc, EA, Mem, memFlags);
- if(fault == NoFault)
- {
+ if (fault == NoFault) {
%(code)s;
+ } else if (memFlags & Request::PF_EXCLUSIVE) {
+ // For prefetches, ignore any faults/exceptions.
+ return NoFault;
}
if(fault == NoFault)
{
@@ -178,7 +182,7 @@ def template MicroLoadInitiateAcc {{
%(ea_code)s;
DPRINTF(X86, "%s : %s: The address is %#x\n", instMnem, mnemonic, EA);
- fault = read(xc, EA, Mem, (%(mem_flags)s) | segment);
+ fault = read(xc, EA, Mem, memFlags);
return fault;
}
@@ -194,7 +198,7 @@ def template MicroLoadCompleteAcc {{
%(op_decl)s;
%(op_rd)s;
- Mem = pkt->get<typeof(Mem)>();
+ Mem = get(pkt);
%(code)s;
@@ -225,9 +229,10 @@ def template MicroStoreExecute {{
if(fault == NoFault)
{
- fault = write(xc, Mem, EA, (%(mem_flags)s) | segment);
+ fault = write(xc, Mem, EA, memFlags);
if(fault == NoFault)
{
+ %(post_code)s;
%(op_wb)s;
}
}
@@ -252,20 +257,20 @@ def template MicroStoreInitiateAcc {{
if(fault == NoFault)
{
- fault = write(xc, Mem, EA, (%(mem_flags)s) | segment);
- if(fault == NoFault)
- {
- %(op_wb)s;
- }
+ write(xc, Mem, EA, memFlags);
}
return fault;
}
}};
def template MicroStoreCompleteAcc {{
- Fault %(class_name)s::completeAcc(PacketPtr, %(CPU_exec_context)s * xc,
- Trace::InstRecord * traceData) const
+ Fault %(class_name)s::completeAcc(PacketPtr pkt,
+ %(CPU_exec_context)s * xc, Trace::InstRecord * traceData) const
{
+ %(op_decl)s;
+ %(op_rd)s;
+ %(complete_code)s;
+ %(op_wb)s;
return NoFault;
}
}};
@@ -295,14 +300,16 @@ def template MicroLdStOpDeclare {{
uint8_t _scale, RegIndex _index, RegIndex _base,
uint64_t _disp, uint8_t _segment,
RegIndex _data,
- uint8_t _dataSize, uint8_t _addressSize);
+ uint8_t _dataSize, uint8_t _addressSize,
+ Request::FlagsType _memFlags);
%(class_name)s(ExtMachInst _machInst,
const char * instMnem,
uint8_t _scale, RegIndex _index, RegIndex _base,
uint64_t _disp, uint8_t _segment,
RegIndex _data,
- uint8_t _dataSize, uint8_t _addressSize);
+ uint8_t _dataSize, uint8_t _addressSize,
+ Request::FlagsType _memFlags);
%(BasicExecDeclare)s
@@ -324,12 +331,13 @@ def template MicroLdStOpConstructor {{
uint8_t _scale, RegIndex _index, RegIndex _base,
uint64_t _disp, uint8_t _segment,
RegIndex _data,
- uint8_t _dataSize, uint8_t _addressSize) :
+ uint8_t _dataSize, uint8_t _addressSize,
+ Request::FlagsType _memFlags) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
false, false, false, false,
_scale, _index, _base,
_disp, _segment, _data,
- _dataSize, _addressSize, %(op_class)s)
+ _dataSize, _addressSize, _memFlags, %(op_class)s)
{
buildMe();
}
@@ -340,12 +348,13 @@ def template MicroLdStOpConstructor {{
uint8_t _scale, RegIndex _index, RegIndex _base,
uint64_t _disp, uint8_t _segment,
RegIndex _data,
- uint8_t _dataSize, uint8_t _addressSize) :
+ uint8_t _dataSize, uint8_t _addressSize,
+ Request::FlagsType _memFlags) :
%(base_class)s(machInst, "%(mnemonic)s", instMnem,
isMicro, isDelayed, isFirst, isLast,
_scale, _index, _base,
_disp, _segment, _data,
- _dataSize, _addressSize, %(op_class)s)
+ _dataSize, _addressSize, _memFlags, %(op_class)s)
{
buildMe();
}
@@ -353,26 +362,35 @@ def template MicroLdStOpConstructor {{
let {{
class LdStOp(X86Microop):
- def __init__(self, data, segment, addr, disp, dataSize, addressSize):
+ def __init__(self, data, segment, addr, disp,
+ dataSize, addressSize, baseFlags, atCPL0, prefetch):
self.data = data
[self.scale, self.index, self.base] = addr
self.disp = disp
self.segment = segment
self.dataSize = dataSize
self.addressSize = addressSize
+ self.memFlags = baseFlags
+ if atCPL0:
+ self.memFlags += " | (CPL0FlagBit << FlagShift)"
+ if prefetch:
+ self.memFlags += " | Request::PF_EXCLUSIVE"
+ self.memFlags += " | (machInst.legacy.addr ? " + \
+ "(AddrSizeFlagBit << FlagShift) : 0)"
def getAllocator(self, *microFlags):
- allocator = '''new %(class_name)s(machInst, mnemonic
+ allocator = '''new %(class_name)s(machInst, macrocodeBlock
%(flags)s, %(scale)s, %(index)s, %(base)s,
%(disp)s, %(segment)s, %(data)s,
- %(dataSize)s, %(addressSize)s)''' % {
+ %(dataSize)s, %(addressSize)s, %(memFlags)s)''' % {
"class_name" : self.className,
"flags" : self.microFlagsText(microFlags),
"scale" : self.scale, "index" : self.index,
"base" : self.base,
"disp" : self.disp,
"segment" : self.segment, "data" : self.data,
- "dataSize" : self.dataSize, "addressSize" : self.addressSize}
+ "dataSize" : self.dataSize, "addressSize" : self.addressSize,
+ "memFlags" : self.memFlags}
return allocator
}};
@@ -384,9 +402,11 @@ let {{
decoder_output = ""
exec_output = ""
- calculateEA = "EA = SegBase + scale * Index + Base + disp;"
+ calculateEA = '''
+ EA = bits(SegBase + scale * Index + Base + disp, addressSize * 8 - 1, 0);
+ '''
- def defineMicroLoadOp(mnemonic, code, mem_flags=0):
+ def defineMicroLoadOp(mnemonic, code, mem_flags="0"):
global header_output
global decoder_output
global exec_output
@@ -397,8 +417,7 @@ let {{
# Build up the all register version of this micro op
iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
{"code": code,
- "ea_code": calculateEA,
- "mem_flags": mem_flags})
+ "ea_code": calculateEA})
header_output += MicroLdStOpDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroLoadExecute.subst(iop)
@@ -407,19 +426,24 @@ let {{
class LoadOp(LdStOp):
def __init__(self, data, segment, addr, disp = 0,
- dataSize="env.dataSize", addressSize="env.addressSize"):
- super(LoadOp, self).__init__(data, segment,
- addr, disp, dataSize, addressSize)
+ dataSize="env.dataSize",
+ addressSize="env.addressSize",
+ atCPL0=False, prefetch=False):
+ super(LoadOp, self).__init__(data, segment, addr,
+ disp, dataSize, addressSize, mem_flags,
+ atCPL0, prefetch)
self.className = Name
self.mnemonic = name
microopClasses[name] = LoadOp
defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);')
- defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);', 'StoreCheck')
+ defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);',
+ 'X86ISA::StoreCheck')
defineMicroLoadOp('Ldfp', 'FpData.uqw = Mem;')
- def defineMicroStoreOp(mnemonic, code, mem_flags=0):
+ def defineMicroStoreOp(mnemonic, code, \
+ postCode="", completeCode="", mem_flags="0"):
global header_output
global decoder_output
global exec_output
@@ -430,8 +454,9 @@ let {{
# Build up the all register version of this micro op
iop = InstObjParams(name, Name, 'X86ISA::LdStOp',
{"code": code,
- "ea_code": calculateEA,
- "mem_flags": mem_flags})
+ "post_code": postCode,
+ "complete_code": completeCode,
+ "ea_code": calculateEA})
header_output += MicroLdStOpDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroStoreExecute.subst(iop)
@@ -440,26 +465,26 @@ let {{
class StoreOp(LdStOp):
def __init__(self, data, segment, addr, disp = 0,
- dataSize="env.dataSize", addressSize="env.addressSize"):
- super(StoreOp, self).__init__(data, segment,
- addr, disp, dataSize, addressSize)
+ dataSize="env.dataSize",
+ addressSize="env.addressSize",
+ atCPL0=False):
+ super(StoreOp, self).__init__(data, segment, addr,
+ disp, dataSize, addressSize, mem_flags, atCPL0, False)
self.className = Name
self.mnemonic = name
microopClasses[name] = StoreOp
- defineMicroStoreOp('St', 'Mem = Data;')
+ defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);')
defineMicroStoreOp('Stfp', 'Mem = FpData.uqw;')
- defineMicroStoreOp('Stupd', '''
- Mem = Data;
- Base = merge(Base, EA - SegBase, addressSize);
- ''');
-
+ defineMicroStoreOp('Stupd', 'Mem = pick(Data, 2, dataSize);',
+ 'Base = merge(Base, EA - SegBase, addressSize);',
+ 'Base = merge(Base, pkt->req->getVaddr() - SegBase, addressSize);');
+ defineMicroStoreOp('Cda', 'Mem = 0;', mem_flags="Request::NO_ACCESS")
iop = InstObjParams("lea", "Lea", 'X86ISA::LdStOp',
{"code": "Data = merge(Data, EA, dataSize);",
- "ea_code": calculateEA,
- "mem_flags": 0})
+ "ea_code": calculateEA})
header_output += MicroLeaDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroLeaExecute.subst(iop)
@@ -468,7 +493,7 @@ let {{
def __init__(self, data, segment, addr, disp = 0,
dataSize="env.dataSize", addressSize="env.addressSize"):
super(LeaOp, self).__init__(data, segment,
- addr, disp, dataSize, addressSize)
+ addr, disp, dataSize, addressSize, "0", False, False)
self.className = "Lea"
self.mnemonic = "lea"
@@ -477,38 +502,28 @@ let {{
iop = InstObjParams("tia", "Tia", 'X86ISA::LdStOp',
{"code": "xc->demapPage(EA, 0);",
- "ea_code": calculateEA,
- "mem_flags": 0})
+ "ea_code": calculateEA})
header_output += MicroLeaDeclare.subst(iop)
decoder_output += MicroLdStOpConstructor.subst(iop)
exec_output += MicroLeaExecute.subst(iop)
class TiaOp(LdStOp):
def __init__(self, segment, addr, disp = 0,
- dataSize="env.dataSize", addressSize="env.addressSize"):
+ dataSize="env.dataSize",
+ addressSize="env.addressSize"):
super(TiaOp, self).__init__("NUM_INTREGS", segment,
- addr, disp, dataSize, addressSize)
+ addr, disp, dataSize, addressSize, "0", False, False)
self.className = "Tia"
self.mnemonic = "tia"
microopClasses["tia"] = TiaOp
- iop = InstObjParams("cda", "Cda", 'X86ISA::LdStOp',
- {"code": '''
- Addr paddr;
- fault = xc->translateDataWriteAddr(EA, paddr,
- dataSize, (1 << segment));
- ''',
- "ea_code": calculateEA})
- header_output += MicroLeaDeclare.subst(iop)
- decoder_output += MicroLdStOpConstructor.subst(iop)
- exec_output += MicroLeaExecute.subst(iop)
-
class CdaOp(LdStOp):
def __init__(self, segment, addr, disp = 0,
- dataSize="env.dataSize", addressSize="env.addressSize"):
+ dataSize="env.dataSize",
+ addressSize="env.addressSize", atCPL0=False):
super(CdaOp, self).__init__("NUM_INTREGS", segment,
- addr, disp, dataSize, addressSize)
+ addr, disp, dataSize, addressSize, "0", atCPL0, False)
self.className = "Cda"
self.mnemonic = "cda"
diff --git a/src/arch/x86/isa/microops/limmop.isa b/src/arch/x86/isa/microops/limmop.isa
index 6686444fd..4e75ab8b0 100644
--- a/src/arch/x86/isa/microops/limmop.isa
+++ b/src/arch/x86/isa/microops/limmop.isa
@@ -154,7 +154,7 @@ let {{
self.dataSize = dataSize
def getAllocator(self, *microFlags):
- allocator = '''new %(class_name)s(machInst, mnemonic
+ allocator = '''new %(class_name)s(machInst, macrocodeBlock
%(flags)s, %(dest)s, %(imm)s, %(dataSize)s)''' % {
"class_name" : self.className,
"mnemonic" : self.mnemonic,
diff --git a/src/arch/x86/isa/microops/microops.isa b/src/arch/x86/isa/microops/microops.isa
index 53f34d3f2..19266f6d6 100644
--- a/src/arch/x86/isa/microops/microops.isa
+++ b/src/arch/x86/isa/microops/microops.isa
@@ -1,4 +1,4 @@
-// Copyright (c) 2007 The Hewlett-Packard Development Company
+// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
// All rights reserved.
//
// Redistribution and use of this software in source and binary forms,
@@ -68,5 +68,11 @@
//Load/store microop definitions
##include "ldstop.isa"
+//Control flow microop definitions
+##include "seqop.isa"
+
//Miscellaneous microop definitions
##include "specop.isa"
+
+//Microops for printing out debug messages through M5
+##include "debug.isa"
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa
index e761f0034..f9bc82119 100644
--- a/src/arch/x86/isa/microops/regop.isa
+++ b/src/arch/x86/isa/microops/regop.isa
@@ -1,4 +1,4 @@
-// Copyright (c) 2007 The Hewlett-Packard Development Company
+// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
// All rights reserved.
//
// Redistribution and use of this software in source and binary forms,
@@ -231,6 +231,21 @@ output header {{
void
divide(uint64_t dividend, uint64_t divisor,
uint64_t &quotient, uint64_t &remainder);
+
+ enum SegmentSelectorCheck {
+ SegNoCheck, SegCSCheck, SegCallGateCheck, SegIntGateCheck,
+ SegSoftIntGateCheck, SegSSCheck, SegIretCheck, SegIntCSCheck,
+ SegTRCheck, SegTSSCheck, SegInGDTCheck, SegLDTCheck
+ };
+
+ enum LongModeDescriptorType {
+ LDT64 = 2,
+ AvailableTSS64 = 9,
+ BusyTSS64 = 0xb,
+ CallGate64 = 0xc,
+ IntGate64 = 0xe,
+ TrapGate64 = 0xf
+ };
}};
output decoder {{
@@ -424,7 +439,7 @@ let {{
className = self.className
if self.mnemonic == self.base_mnemonic + 'i':
className += "Imm"
- allocator = '''new %(class_name)s(machInst, mnemonic
+ allocator = '''new %(class_name)s(machInst, macrocodeBlock
%(flags)s, %(src1)s, %(op2)s, %(dest)s,
%(dataSize)s, %(ext)s)''' % {
"class_name" : className,
@@ -838,19 +853,28 @@ let {{
code = 'RIP = psrc1 + sop2 + CSBase'
else_code="RIP = RIP;"
- class Br(WrRegOp, CondRegOp):
- code = 'nuIP = psrc1 + op2;'
- else_code='nuIP = nuIP;'
-
class Wruflags(WrRegOp):
code = 'ccFlagBits = psrc1 ^ op2'
+ class Wrflags(WrRegOp):
+ code = '''
+ MiscReg newFlags = psrc1 ^ op2;
+ MiscReg userFlagMask = 0xDD5;
+ // Get only the user flags
+ ccFlagBits = newFlags & userFlagMask;
+ // Get everything else
+ nccFlagBits = newFlags & ~userFlagMask;
+ '''
+
class Rdip(RdRegOp):
code = 'DestReg = RIP - CSBase'
class Ruflags(RdRegOp):
code = 'DestReg = ccFlagBits'
+ class Rflags(RdRegOp):
+ code = 'DestReg = ccFlagBits | nccFlagBits'
+
class Ruflag(RegOp):
code = '''
int flag = bits(ccFlagBits, imm8);
@@ -863,6 +887,20 @@ let {{
super(Ruflag, self).__init__(dest, \
"NUM_INTREGS", imm, flags, dataSize)
+ class Rflag(RegOp):
+ code = '''
+ MiscReg flagMask = 0x3F7FDD5;
+ MiscReg flags = (nccFlagBits | ccFlagBits) & flagMask;
+ int flag = bits(flags, imm8);
+ DestReg = merge(DestReg, flag, dataSize);
+ ccFlagBits = (flag == 0) ? (ccFlagBits | EZFBit) :
+ (ccFlagBits & ~EZFBit);
+ '''
+ def __init__(self, dest, imm, flags=None, \
+ dataSize="env.dataSize"):
+ super(Rflag, self).__init__(dest, \
+ "NUM_INTREGS", imm, flags, dataSize)
+
class Sext(RegOp):
code = '''
IntReg val = psrc1;
@@ -883,17 +921,53 @@ let {{
'''
class Zext(RegOp):
- code = 'DestReg = bits(psrc1, op2, 0);'
+ code = 'DestReg = merge(DestReg, bits(psrc1, op2, 0), dataSize);'
+
+ class Rddr(RegOp):
+ def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
+ super(Rddr, self).__init__(dest, \
+ src1, "NUM_INTREGS", flags, dataSize)
+ code = '''
+ CR4 cr4 = CR4Op;
+ DR7 dr7 = DR7Op;
+ if ((cr4.de == 1 && (src1 == 4 || src1 == 5)) || src1 >= 8) {
+ fault = new InvalidOpcode();
+ } else if (dr7.gd) {
+ fault = new DebugException();
+ } else {
+ DestReg = merge(DestReg, DebugSrc1, dataSize);
+ }
+ '''
+
+ class Wrdr(RegOp):
+ def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
+ super(Wrdr, self).__init__(dest, \
+ src1, "NUM_INTREGS", flags, dataSize)
+ code = '''
+ CR4 cr4 = CR4Op;
+ DR7 dr7 = DR7Op;
+ if ((cr4.de == 1 && (dest == 4 || dest == 5)) || dest >= 8) {
+ fault = new InvalidOpcode();
+ } else if ((dest == 6 || dest == 7) &&
+ bits(psrc1, 63, 32) &&
+ machInst.mode.mode == LongMode) {
+ fault = new GeneralProtection(0);
+ } else if (dr7.gd) {
+ fault = new DebugException();
+ } else {
+ DebugDest = psrc1;
+ }
+ '''
class Rdcr(RegOp):
def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
super(Rdcr, self).__init__(dest, \
src1, "NUM_INTREGS", flags, dataSize)
code = '''
- if (dest == 1 || (dest > 4 && dest < 8) || (dest > 8)) {
+ if (src1 == 1 || (src1 > 4 && src1 < 8) || (src1 > 8)) {
fault = new InvalidOpcode();
} else {
- DestReg = ControlSrc1;
+ DestReg = merge(DestReg, ControlSrc1, dataSize);
}
'''
@@ -950,7 +1024,7 @@ let {{
'''
# Microops for manipulating segmentation registers
- class SegOp(RegOp):
+ class SegOp(CondRegOp):
abstract = True
def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
super(SegOp, self).__init__(dest, \
@@ -971,74 +1045,223 @@ let {{
SegSelDest = psrc1;
'''
+ class WrAttr(SegOp):
+ code = '''
+ SegAttrDest = psrc1;
+ '''
+
class Rdbase(SegOp):
code = '''
- DestReg = SegBaseDest;
+ DestReg = merge(DestReg, SegBaseSrc1, dataSize);
'''
class Rdlimit(SegOp):
code = '''
- DestReg = SegLimitSrc1;
+ DestReg = merge(DestReg, SegLimitSrc1, dataSize);
+ '''
+
+ class RdAttr(SegOp):
+ code = '''
+ DestReg = merge(DestReg, SegAttrSrc1, dataSize);
'''
class Rdsel(SegOp):
code = '''
- DestReg = SegSelSrc1;
+ DestReg = merge(DestReg, SegSelSrc1, dataSize);
'''
- class Chks(SegOp):
+ class Rdval(RegOp):
+ def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
+ super(Rdval, self).__init__(dest, \
+ src1, "NUM_INTREGS", flags, dataSize)
code = '''
- // The selector is in source 1.
- SegSelector selector = psrc1;
-
- // Compute the address of the descriptor and set DestReg to it.
- if (selector.ti) {
- // A descriptor in the LDT
- Addr target = (selector.esi << 3) + LDTRBase;
- if (!LDTRSel || (selector.esi << 3) + dataSize > LDTRLimit)
- fault = new GeneralProtection(selector & mask(16));
- DestReg = target;
- } else {
- // A descriptor in the GDT
- Addr target = (selector.esi << 3) + GDTRBase;
- if ((selector.esi << 3) + dataSize > GDTRLimit)
- fault = new GeneralProtection(selector & mask(16));
- DestReg = target;
+ DestReg = MiscRegSrc1;
+ '''
+
+ class Wrval(RegOp):
+ def __init__(self, dest, src1, flags=None, dataSize="env.dataSize"):
+ super(Wrval, self).__init__(dest, \
+ src1, "NUM_INTREGS", flags, dataSize)
+ code = '''
+ MiscRegDest = SrcReg1;
+ '''
+
+ class Chks(RegOp):
+ def __init__(self, dest, src1, src2=0,
+ flags=None, dataSize="env.dataSize"):
+ super(Chks, self).__init__(dest,
+ src1, src2, flags, dataSize)
+ code = '''
+ // The selector is in source 1 and can be at most 16 bits.
+ SegSelector selector = DestReg;
+ SegDescriptor desc = SrcReg1;
+ HandyM5Reg m5reg = M5Reg;
+
+ switch (imm8)
+ {
+ case SegNoCheck:
+ break;
+ case SegCSCheck:
+ panic("CS checks for far calls/jumps not implemented.\\n");
+ break;
+ case SegCallGateCheck:
+ panic("CS checks for far calls/jumps through call gates"
+ "not implemented.\\n");
+ break;
+ case SegSoftIntGateCheck:
+ // Check permissions.
+ if (desc.dpl < m5reg.cpl) {
+ fault = new GeneralProtection(selector);
+ }
+ // Fall through on purpose
+ case SegIntGateCheck:
+ // Make sure the gate's the right type.
+ if ((m5reg.mode == LongMode && (desc.type & 0xe) != 0xe) ||
+ ((desc.type & 0x6) != 0x6)) {
+ fault = new GeneralProtection(0);
+ }
+ break;
+ case SegSSCheck:
+ if (selector.si || selector.ti) {
+ if (!desc.p) {
+ fault = new StackFault(selector);
+ }
+ } else {
+ if ((m5reg.submode != SixtyFourBitMode ||
+ m5reg.cpl == 3) ||
+ !(desc.s == 1 &&
+ desc.type.codeOrData == 0 && desc.type.w) ||
+ (desc.dpl != m5reg.cpl) ||
+ (selector.rpl != m5reg.cpl)) {
+ fault = new GeneralProtection(selector);
+ }
+ }
+ break;
+ case SegIretCheck:
+ {
+ if ((!selector.si && !selector.ti) ||
+ (selector.rpl < m5reg.cpl) ||
+ !(desc.s == 1 && desc.type.codeOrData == 1) ||
+ (!desc.type.c && desc.dpl != selector.rpl) ||
+ (desc.type.c && desc.dpl > selector.rpl)) {
+ fault = new GeneralProtection(selector);
+ } else if (!desc.p) {
+ fault = new SegmentNotPresent(selector);
+ }
+ break;
+ }
+ case SegIntCSCheck:
+ if (m5reg.mode == LongMode) {
+ if (desc.l != 1 || desc.d != 0) {
+ fault = new GeneralProtection(selector);
+ }
+ } else {
+ panic("Interrupt CS checks not implemented "
+ "in legacy mode.\\n");
+ }
+ break;
+ case SegTRCheck:
+ if (!selector.si || selector.ti) {
+ fault = new GeneralProtection(selector);
+ }
+ break;
+ case SegTSSCheck:
+ if (!desc.p) {
+ fault = new SegmentNotPresent(selector);
+ } else if (!(desc.type == 0x9 ||
+ (desc.type == 1 &&
+ m5reg.mode != LongMode))) {
+ fault = new GeneralProtection(selector);
+ }
+ break;
+ case SegInGDTCheck:
+ if (selector.ti) {
+ fault = new GeneralProtection(selector);
+ }
+ break;
+ case SegLDTCheck:
+ if (!desc.p) {
+ fault = new SegmentNotPresent(selector);
+ } else if (desc.type != 0x2) {
+ fault = new GeneralProtection(selector);
+ }
+ break;
+ default:
+ panic("Undefined segment check type.\\n");
}
'''
flag_code = '''
// Check for a NULL selector and set ZF,EZF appropriately.
ccFlagBits = ccFlagBits & ~(ext & (ZFBit | EZFBit));
- if (!selector.esi && !selector.ti)
+ if (!selector.si && !selector.ti)
ccFlagBits = ccFlagBits | (ext & (ZFBit | EZFBit));
'''
class Wrdh(RegOp):
code = '''
+ SegDescriptor desc = SrcReg1;
+
+ uint64_t target = bits(SrcReg2, 31, 0) << 32;
+ switch(desc.type) {
+ case LDT64:
+ case AvailableTSS64:
+ case BusyTSS64:
+ replaceBits(target, 23, 0, desc.baseLow);
+ replaceBits(target, 31, 24, desc.baseHigh);
+ break;
+ case CallGate64:
+ case IntGate64:
+ case TrapGate64:
+ replaceBits(target, 15, 0, bits(desc, 15, 0));
+ replaceBits(target, 31, 16, bits(desc, 63, 48));
+ break;
+ default:
+ panic("Wrdh used with wrong descriptor type!\\n");
+ }
+ DestReg = target;
+ '''
+
+ class Wrtsc(WrRegOp):
+ code = '''
+ TscOp = psrc1;
+ '''
+
+ class Rdtsc(RdRegOp):
+ code = '''
+ DestReg = TscOp;
+ '''
+ class Rdm5reg(RdRegOp):
+ code = '''
+ DestReg = M5Reg;
'''
class Wrdl(RegOp):
code = '''
SegDescriptor desc = SrcReg1;
- SegAttr attr = 0;
- attr.dpl = desc.dpl;
- attr.defaultSize = desc.d;
- if (!desc.s) {
- SegBaseDest = SegBaseDest;
- SegLimitDest = SegLimitDest;
- SegAttrDest = SegAttrDest;
- panic("System segment encountered.\\n");
- } else {
- if (!desc.p)
- panic("Segment not present.\\n");
- if (desc.type.codeOrData) {
- attr.readable = desc.type.r;
- attr.longMode = desc.l;
- } else {
- attr.expandDown = desc.type.e;
+ SegSelector selector = SrcReg2;
+ if (selector.si || selector.ti) {
+ SegAttr attr = 0;
+ attr.dpl = desc.dpl;
+ attr.defaultSize = desc.d;
+ if (!desc.s) {
+ // The expand down bit happens to be set for gates.
+ if (desc.type.e) {
+ panic("Gate descriptor encountered.\\n");
+ }
attr.readable = 1;
- attr.writable = desc.type.w;
+ attr.writable = 1;
+ } else {
+ if (!desc.p)
+ panic("Segment not present.\\n");
+ if (desc.type.codeOrData) {
+ attr.readable = desc.type.r;
+ attr.longMode = desc.l;
+ } else {
+ attr.expandDown = desc.type.e;
+ attr.readable = 1;
+ attr.writable = desc.type.w;
+ }
}
Addr base = desc.baseLow | (desc.baseHigh << 24);
Addr limit = desc.limitLow | (desc.limitHigh << 16);
@@ -1047,6 +1270,10 @@ let {{
SegBaseDest = base;
SegLimitDest = limit;
SegAttrDest = attr;
+ } else {
+ SegBaseDest = SegBaseDest;
+ SegLimitDest = SegLimitDest;
+ SegAttrDest = SegAttrDest;
}
'''
}};
diff --git a/src/arch/x86/isa/microops/seqop.isa b/src/arch/x86/isa/microops/seqop.isa
new file mode 100644
index 000000000..332519b87
--- /dev/null
+++ b/src/arch/x86/isa/microops/seqop.isa
@@ -0,0 +1,251 @@
+// 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
+
+output header {{
+ class SeqOpBase : public X86ISA::X86MicroopBase
+ {
+ protected:
+ uint16_t target;
+ uint8_t cc;
+
+ public:
+ SeqOpBase(ExtMachInst _machInst, const char * instMnem,
+ const char * mnemonic,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ uint16_t _target, uint8_t _cc);
+
+ SeqOpBase(ExtMachInst _machInst, const char * instMnem,
+ const char * mnemonic,
+ uint16_t _target, uint8_t _cc);
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
+ };
+}};
+
+def template SeqOpDeclare {{
+ class %(class_name)s : public %(base_class)s
+ {
+ private:
+ void buildMe();
+ public:
+ %(class_name)s(ExtMachInst _machInst, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ uint16_t _target, uint8_t _cc);
+
+ %(class_name)s(ExtMachInst _machInst, const char * instMnem,
+ uint16_t _target, uint8_t _cc);
+
+ %(BasicExecDeclare)s
+ };
+}};
+
+def template SeqOpExecute {{
+ Fault %(class_name)s::execute(%(CPU_exec_context)s *xc,
+ Trace::InstRecord *traceData) const
+ {
+ %(op_decl)s;
+ %(op_rd)s;
+ if (%(cond_test)s) {
+ %(code)s;
+ } else {
+ %(else_code)s;
+ }
+ %(op_wb)s;
+ return NoFault;
+ }
+}};
+
+output decoder {{
+ inline SeqOpBase::SeqOpBase(
+ ExtMachInst machInst, const char * mnemonic, const char * instMnem,
+ uint16_t _target, uint8_t _cc) :
+ X86MicroopBase(machInst, mnemonic, instMnem,
+ false, false, false, false, No_OpClass),
+ target(_target), cc(_cc)
+ {
+ }
+
+ inline SeqOpBase::SeqOpBase(
+ ExtMachInst machInst, const char * mnemonic, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ uint16_t _target, uint8_t _cc) :
+ X86MicroopBase(machInst, mnemonic, instMnem,
+ isMicro, isDelayed, isFirst, isLast, No_OpClass),
+ target(_target), cc(_cc)
+ {
+ }
+}};
+
+def template SeqOpConstructor {{
+
+ inline void %(class_name)s::buildMe()
+ {
+ %(constructor)s;
+ }
+
+ inline %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem,
+ uint16_t _target, uint8_t _cc) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem, _target, _cc)
+ {
+ buildMe();
+ }
+
+ inline %(class_name)s::%(class_name)s(
+ ExtMachInst machInst, const char * instMnem,
+ bool isMicro, bool isDelayed, bool isFirst, bool isLast,
+ uint16_t _target, uint8_t _cc) :
+ %(base_class)s(machInst, "%(mnemonic)s", instMnem,
+ isMicro, isDelayed, isFirst, isLast, _target, _cc)
+ {
+ buildMe();
+ }
+}};
+
+output decoder {{
+ std::string SeqOpBase::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+
+ printMnemonic(response, instMnem, mnemonic);
+ ccprintf(response, "%#x", target);
+
+ return response.str();
+ }
+}};
+
+let {{
+ class SeqOp(X86Microop):
+ def __init__(self, target, flags=None):
+ self.target = target
+ if flags:
+ if not isinstance(flags, (list, tuple)):
+ raise Exception, "flags must be a list or tuple of flags"
+ self.cond = " | ".join(flags)
+ self.className += "Flags"
+ else:
+ self.cond = "0"
+
+ def getAllocator(self, *microFlags):
+ allocator = '''new %(class_name)s(machInst, macrocodeBlock
+ %(flags)s, %(target)s, %(cc)s)''' % {
+ "class_name" : self.className,
+ "flags" : self.microFlagsText(microFlags),
+ "target" : self.target,
+ "cc" : self.cond}
+ return allocator
+
+ class Br(SeqOp):
+ className = "MicroBranch"
+
+ def getAllocator(self, *microFlags):
+ (is_micro, is_delayed, is_first, is_last) = microFlags
+ is_last = False
+ is_delayed = True
+ microFlags = (is_micro, is_delayed, is_first, is_last)
+ return super(Br, self).getAllocator(*microFlags)
+
+ class Eret(SeqOp):
+ target = "normalMicroPC(0)"
+ className = "Eret"
+
+ def __init__(self, flags=None):
+ if flags:
+ if not isinstance(flags, (list, tuple)):
+ raise Exception, "flags must be a list or tuple of flags"
+ self.cond = " | ".join(flags)
+ self.className += "Flags"
+ else:
+ self.cond = "0"
+
+ def getAllocator(self, *microFlags):
+ (is_micro, is_delayed, is_first, is_last) = microFlags
+ is_last = True
+ is_delayed = False
+ microFlags = (is_micro, is_delayed, is_first, is_last)
+ return super(Eret, self).getAllocator(*microFlags)
+
+ iop = InstObjParams("br", "MicroBranchFlags", "SeqOpBase",
+ {"code": "nuIP = target",
+ "else_code": "nuIP = nuIP",
+ "cond_test": "checkCondition(ccFlagBits, cc)"})
+ exec_output += SeqOpExecute.subst(iop)
+ header_output += SeqOpDeclare.subst(iop)
+ decoder_output += SeqOpConstructor.subst(iop)
+ iop = InstObjParams("br", "MicroBranch", "SeqOpBase",
+ {"code": "nuIP = target",
+ "else_code": "nuIP = nuIP",
+ "cond_test": "true"})
+ exec_output += SeqOpExecute.subst(iop)
+ header_output += SeqOpDeclare.subst(iop)
+ decoder_output += SeqOpConstructor.subst(iop)
+ microopClasses["br"] = Br
+
+ iop = InstObjParams("eret", "EretFlags", "SeqOpBase",
+ {"code": "", "else_code": "",
+ "cond_test": "checkCondition(ccFlagBits, cc)"})
+ exec_output += SeqOpExecute.subst(iop)
+ header_output += SeqOpDeclare.subst(iop)
+ decoder_output += SeqOpConstructor.subst(iop)
+ iop = InstObjParams("eret", "Eret", "SeqOpBase",
+ {"code": "", "else_code": "",
+ "cond_test": "true"})
+ exec_output += SeqOpExecute.subst(iop)
+ header_output += SeqOpDeclare.subst(iop)
+ decoder_output += SeqOpConstructor.subst(iop)
+ microopClasses["eret"] = Eret
+}};
diff --git a/src/arch/x86/isa/microops/specop.isa b/src/arch/x86/isa/microops/specop.isa
index 6bcc7ff91..c6e172ef1 100644
--- a/src/arch/x86/isa/microops/specop.isa
+++ b/src/arch/x86/isa/microops/specop.isa
@@ -1,4 +1,4 @@
-// Copyright (c) 2007 The Hewlett-Packard Development Company
+// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
// All rights reserved.
//
// Redistribution and use of this software in source and binary forms,
@@ -95,6 +95,9 @@ output header {{
}
%(BasicExecDeclare)s
+
+ std::string generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const;
};
}};
@@ -201,6 +204,16 @@ output decoder {{
return response.str();
}
+
+ std::string MicroHalt::generateDisassembly(Addr pc,
+ const SymbolTable *symtab) const
+ {
+ std::stringstream response;
+
+ printMnemonic(response, instMnem, mnemonic);
+
+ return response.str();
+ }
}};
let {{
@@ -217,7 +230,7 @@ let {{
self.cond = "0"
def getAllocator(self, *microFlags):
- allocator = '''new %(class_name)s(machInst, mnemonic
+ allocator = '''new %(class_name)s(machInst, macrocodeBlock
%(flags)s, %(fault)s, %(cc)s)''' % {
"class_name" : self.className,
"flags" : self.microFlagsText(microFlags),
@@ -244,7 +257,7 @@ let {{
pass
def getAllocator(self, *microFlags):
- return "new MicroHalt(machInst, mnemonic %s)" % \
+ return "new MicroHalt(machInst, macrocodeBlock %s)" % \
self.microFlagsText(microFlags)
microopClasses["halt"] = Halt
diff --git a/src/arch/x86/isa/operands.isa b/src/arch/x86/isa/operands.isa
index 9345158e9..ab1e9a851 100644
--- a/src/arch/x86/isa/operands.isa
+++ b/src/arch/x86/isa/operands.isa
@@ -26,7 +26,7 @@
//
// Authors: Gabe Black
-// Copyright (c) 2007 The Hewlett-Packard Development Company
+// Copyright (c) 2007-2008 The Hewlett-Packard Development Company
// All rights reserved.
//
// Redistribution and use of this software in source and binary forms,
@@ -109,7 +109,14 @@ def operands {{
'Quotient': ('IntReg', 'uqw', 'INTREG_IMPLICIT(2)', 'IsInteger', 9),
'Remainder': ('IntReg', 'uqw', 'INTREG_IMPLICIT(3)', 'IsInteger', 10),
'Divisor': ('IntReg', 'uqw', 'INTREG_IMPLICIT(4)', 'IsInteger', 11),
- 'rax': ('IntReg', 'uqw', '(INTREG_RAX)', 'IsInteger', 12),
+ 'Rax': ('IntReg', 'uqw', '(INTREG_RAX)', 'IsInteger', 12),
+ 'Rbx': ('IntReg', 'uqw', '(INTREG_RBX)', 'IsInteger', 13),
+ 'Rcx': ('IntReg', 'uqw', '(INTREG_RCX)', 'IsInteger', 14),
+ 'Rdx': ('IntReg', 'uqw', '(INTREG_RDX)', 'IsInteger', 15),
+ 'Rsp': ('IntReg', 'uqw', '(INTREG_RSP)', 'IsInteger', 16),
+ 'Rbp': ('IntReg', 'uqw', '(INTREG_RBP)', 'IsInteger', 17),
+ 'Rsi': ('IntReg', 'uqw', '(INTREG_RSI)', 'IsInteger', 18),
+ 'Rdi': ('IntReg', 'uqw', '(INTREG_RDI)', 'IsInteger', 19),
'FpSrcReg1': ('FloatReg', 'df', 'src1', 'IsFloating', 20),
'FpSrcReg2': ('FloatReg', 'df', 'src2', 'IsFloating', 21),
'FpDestReg': ('FloatReg', 'df', 'dest', 'IsFloating', 22),
@@ -117,10 +124,13 @@ def operands {{
'RIP': ('NPC', 'uqw', None, (None, None, 'IsControl'), 50),
'uIP': ('UPC', 'uqw', None, (None, None, 'IsControl'), 51),
'nuIP': ('NUPC', 'uqw', None, (None, None, 'IsControl'), 52),
+ # This holds the condition code portion of the flag register. The
+ # nccFlagBits version holds the rest.
'ccFlagBits': ('IntReg', 'uqw', 'INTREG_PSEUDO(0)', None, 60),
- # The TOP register should needs to be more protected so that later
+ # These register should needs to be more protected so that later
# instructions don't map their indexes with an old value.
- 'TOP': ('ControlReg', 'ub', 'MISCREG_X87_TOP', None, 61),
+ 'nccFlagBits': ('ControlReg', 'uqw', 'MISCREG_RFLAGS', None, 61),
+ 'TOP': ('ControlReg', 'ub', 'MISCREG_X87_TOP', None, 62),
# The segment base as used by memory instructions.
'SegBase': ('ControlReg', 'uqw', 'MISCREG_SEG_EFF_BASE(segment)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 70),
@@ -128,23 +138,31 @@ def operands {{
# original instruction.
'ControlDest': ('ControlReg', 'uqw', 'MISCREG_CR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 100),
'ControlSrc1': ('ControlReg', 'uqw', 'MISCREG_CR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 101),
- 'SegBaseDest': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 102),
- 'SegBaseSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 103),
- 'SegLimitDest': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 104),
- 'SegLimitSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 105),
- 'SegSelDest': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 106),
- 'SegSelSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 107),
- 'SegAttrDest': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 108),
- 'SegAttrSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 109),
+ 'DebugDest': ('ControlReg', 'uqw', 'MISCREG_DR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 102),
+ 'DebugSrc1': ('ControlReg', 'uqw', 'MISCREG_DR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 103),
+ 'SegBaseDest': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 104),
+ 'SegBaseSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_BASE(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 105),
+ 'SegLimitDest': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 106),
+ 'SegLimitSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_LIMIT(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 107),
+ 'SegSelDest': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 108),
+ 'SegSelSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_SEL(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 109),
+ 'SegAttrDest': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(dest)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 110),
+ 'SegAttrSrc1': ('ControlReg', 'uqw', 'MISCREG_SEG_ATTR(src1)', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 111),
# Operands to access specific control registers directly.
'EferOp': ('ControlReg', 'uqw', 'MISCREG_EFER', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 200),
'CR4Op': ('ControlReg', 'uqw', 'MISCREG_CR4', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 201),
- 'LDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSL_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 202),
- 'LDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSL_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 203),
- 'LDTRSel': ('ControlReg', 'uqw', 'MISCREG_TSL', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 204),
- 'GDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSG_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 205),
- 'GDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSG_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 206),
- 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 207),
+ 'DR7Op': ('ControlReg', 'uqw', 'MISCREG_DR7', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 202),
+ 'LDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSL_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 203),
+ 'LDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSL_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 204),
+ 'LDTRSel': ('ControlReg', 'uqw', 'MISCREG_TSL', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 205),
+ 'GDTRBase': ('ControlReg', 'uqw', 'MISCREG_TSG_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 206),
+ 'GDTRLimit': ('ControlReg', 'uqw', 'MISCREG_TSG_LIMIT', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 207),
+ 'CSBase': ('ControlReg', 'udw', 'MISCREG_CS_EFF_BASE', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 208),
+ 'CSAttr': ('ControlReg', 'udw', 'MISCREG_CS_ATTR', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 209),
+ 'MiscRegDest': ('ControlReg', 'uqw', 'dest', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 210),
+ 'MiscRegSrc1': ('ControlReg', 'uqw', 'src1', (None, None, ['IsSerializeAfter','IsSerializing','IsNonSpeculative']), 211),
+ 'TscOp': ('ControlReg', 'uqw', 'MISCREG_TSC', (None, None, ['IsSerializeAfter', 'IsSerializing', 'IsNonSpeculative']), 212),
+ 'M5Reg': ('ControlReg', 'uqw', 'MISCREG_M5_REG', (None, None, None), 213),
'Mem': ('Mem', 'uqw', None, ('IsMemRef', 'IsLoad', 'IsStore'), 300)
}};
diff --git a/src/arch/x86/isa/rom.isa b/src/arch/x86/isa/rom.isa
new file mode 100644
index 000000000..7d3eb8670
--- /dev/null
+++ b/src/arch/x86/isa/rom.isa
@@ -0,0 +1,90 @@
+// 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
+
+def template MicroRomConstructor {{
+
+ %(define_generators)s
+ const MicroPC X86ISA::MicrocodeRom::numMicroops = %(num_microops)s;
+
+ X86ISA::MicrocodeRom::MicrocodeRom()
+ {
+ using namespace RomLabels;
+ genFuncs = new GenFunc[numMicroops];
+ %(alloc_generators)s;
+ }
+}};
+
+let {{
+ from micro_asm import Rom
+
+ class X86MicrocodeRom(Rom):
+ def __init__(self, name):
+ super(X86MicrocodeRom, self).__init__(name)
+ self.directives = {}
+
+ def add_microop(self, mnemonic, microop):
+ microop.mnemonic = mnemonic
+ microop.micropc = len(self.microops)
+ self.microops.append(microop)
+
+
+ def getDeclaration(self):
+ declareLabels = "namespace RomLabels {\n"
+ for (label, microop) in self.labels.items():
+ declareLabels += "const static uint64_t label_%s = %d;\n" \
+ % (label, microop.micropc)
+ for (label, microop) in self.externs.items():
+ declareLabels += \
+ "const static MicroPC extern_label_%s = %d;\n" \
+ % (label, microop.micropc)
+ declareLabels += "}\n"
+ return declareLabels;
+
+ def getDefinition(self):
+ numMicroops = len(self.microops)
+ allocGenerators = ''
+ micropc = 0
+ define_generators = '''
+ namespace
+ {
+ static const char romMnemonic[] = "Microcode_ROM";
+ '''
+ for op in self.microops:
+ define_generators += op.getGeneratorDef(micropc)
+ allocGenerators += "genFuncs[%d] = %s;\n" % \
+ (micropc, op.getGenerator(micropc))
+ micropc += 1
+ define_generators += "}\n"
+ iop = InstObjParams(self.name, self.name, "MicrocodeRom",
+ {"code" : "",
+ "define_generators" : define_generators,
+ "num_microops" : numMicroops,
+ "alloc_generators" : allocGenerators
+ })
+ return MicroRomConstructor.subst(iop);
+}};
diff --git a/src/arch/x86/isa/specialize.isa b/src/arch/x86/isa/specialize.isa
index abf734307..b74363470 100644
--- a/src/arch/x86/isa/specialize.isa
+++ b/src/arch/x86/isa/specialize.isa
@@ -86,8 +86,17 @@ let {{
let {{
def doRipRelativeDecode(Name, opTypes, env):
# print "RIPing %s with opTypes %s" % (Name, opTypes)
- normBlocks = specializeInst(Name + "_M", copy.copy(opTypes), copy.copy(env))
- ripBlocks = specializeInst(Name + "_P", copy.copy(opTypes), copy.copy(env))
+ env.memoryInst = True
+ normEnv = copy.copy(env)
+ normEnv.addToDisassembly(
+ '''printMem(out, env.seg, env.scale, env.index, env.base,
+ machInst.displacement, env.addressSize, false);''')
+ normBlocks = specializeInst(Name + "_M", copy.copy(opTypes), normEnv)
+ ripEnv = copy.copy(env)
+ ripEnv.addToDisassembly(
+ '''printMem(out, env.seg, 1, 0, 0,
+ machInst.displacement, env.addressSize, true);''')
+ ripBlocks = specializeInst(Name + "_P", copy.copy(opTypes), ripEnv)
blocks = OutputBlocks()
blocks.append(normBlocks)
@@ -138,12 +147,17 @@ let {{
#Figure out what to do with fixed register operands
#This is the index to use, so we should stick it some place.
if opType.reg in ("A", "B", "C", "D"):
- env.addReg("INTREG_R%sX" % opType.reg)
+ regString = "INTREG_R%sX" % opType.reg
else:
- env.addReg("INTREG_R%s" % opType.reg)
+ regString = "INTREG_R%s" % opType.reg
+ env.addReg(regString)
+ env.addToDisassembly(
+ "printReg(out, %s, regSize);\n" % regString)
Name += "_R"
elif opType.tag == "B":
# This refers to registers whose index is encoded as part of the opcode
+ env.addToDisassembly(
+ "printReg(out, %s, regSize);\n" % InstRegIndex)
Name += "_R"
env.addReg(InstRegIndex)
elif opType.tag == "M":
@@ -156,24 +170,34 @@ let {{
elif opType.tag == "C":
# A control register indexed by the "reg" field
env.addReg(ModRMRegIndex)
+ env.addToDisassembly(
+ "ccprintf(out, \"CR%%d\", %s);\n" % ModRMRegIndex)
Name += "_C"
elif opType.tag == "D":
# A debug register indexed by the "reg" field
env.addReg(ModRMRegIndex)
+ env.addToDisassembly(
+ "ccprintf(out, \"DR%%d\", %s);\n" % ModRMRegIndex)
Name += "_D"
elif opType.tag == "S":
# A segment selector register indexed by the "reg" field
env.addReg(ModRMRegIndex)
+ env.addToDisassembly(
+ "printSegment(out, %s);\n" % ModRMRegIndex)
Name += "_S"
elif opType.tag in ("G", "P", "T", "V"):
# Use the "reg" field of the ModRM byte to select the register
env.addReg(ModRMRegIndex)
+ env.addToDisassembly(
+ "printReg(out, %s, regSize);\n" % ModRMRegIndex)
Name += "_R"
elif opType.tag in ("E", "Q", "W"):
# This might refer to memory or to a register. We need to
# divide it up farther.
regEnv = copy.copy(env)
regEnv.addReg(ModRMRMIndex)
+ regEnv.addToDisassembly(
+ "printReg(out, %s, regSize);\n" % ModRMRMIndex)
# This refers to memory. The macroop constructor should set up
# modrm addressing.
memEnv = copy.copy(env)
@@ -183,6 +207,8 @@ let {{
(doRipRelativeDecode, Name, copy.copy(opTypes), memEnv))
elif opType.tag in ("I", "J"):
# Immediates
+ env.addToDisassembly(
+ "ccprintf(out, \"%#x\", machInst.immediate);\n")
Name += "_I"
elif opType.tag == "O":
# Immediate containing a memory offset
@@ -190,10 +216,22 @@ let {{
elif opType.tag in ("PR", "R", "VR"):
# Non register modrm settings should cause an error
env.addReg(ModRMRMIndex)
+ env.addToDisassembly(
+ "printReg(out, %s, regSize);\n" % ModRMRMIndex)
Name += "_R"
elif opType.tag in ("X", "Y"):
# This type of memory addressing is for string instructions.
# They'll use the right index and segment internally.
+ if opType.tag == "X":
+ env.addToDisassembly(
+ '''printMem(out, env.seg,
+ 1, X86ISA::ZeroReg, X86ISA::INTREG_RSI, 0,
+ env.addressSize, false);''')
+ else:
+ env.addToDisassembly(
+ '''printMem(out, SEGMENT_REG_ES,
+ 1, X86ISA::ZeroReg, X86ISA::INTREG_RDI, 0,
+ env.addressSize, false);''')
Name += "_M"
else:
raise Exception, "Unrecognized tag %s." % opType.tag
diff --git a/src/arch/x86/isa_traits.hh b/src/arch/x86/isa_traits.hh
index abb7694ed..d25e0eb70 100644
--- a/src/arch/x86/isa_traits.hh
+++ b/src/arch/x86/isa_traits.hh
@@ -106,19 +106,7 @@ namespace X86ISA
const int StackPointerReg = INTREG_RSP;
//X86 doesn't seem to have a link register
const int ReturnAddressReg = 0;
- const int ReturnValueReg = INTREG_RAX;
const int FramePointerReg = INTREG_RBP;
- const int ArgumentReg[] = {
- INTREG_RDI,
- INTREG_RSI,
- INTREG_RDX,
- //This argument register is r10 for syscalls and rcx for C.
- INTREG_R10W,
- //INTREG_RCX,
- INTREG_R8W,
- INTREG_R9W
- };
- const int NumArgumentRegs = sizeof(ArgumentReg) / sizeof(const int);
// Some OS syscalls use a second register (rdx) to return a second
// value
diff --git a/src/arch/x86/linux/linux.cc b/src/arch/x86/linux/linux.cc
index 5e8d2de16..41855da59 100644
--- a/src/arch/x86/linux/linux.cc
+++ b/src/arch/x86/linux/linux.cc
@@ -97,3 +97,42 @@ const int X86Linux64::NUM_OPEN_FLAGS =
sizeof(X86Linux64::openFlagTable) /
sizeof(X86Linux64::openFlagTable[0]);
+// open(2) flags translation table
+OpenFlagTransTable X86Linux32::openFlagTable[] = {
+#ifdef _MSC_VER
+ { TGT_O_RDONLY, _O_RDONLY },
+ { TGT_O_WRONLY, _O_WRONLY },
+ { TGT_O_RDWR, _O_RDWR },
+ { TGT_O_APPEND, _O_APPEND },
+ { TGT_O_CREAT, _O_CREAT },
+ { TGT_O_TRUNC, _O_TRUNC },
+ { TGT_O_EXCL, _O_EXCL },
+#ifdef _O_NONBLOCK
+ { TGT_O_NONBLOCK, _O_NONBLOCK },
+#endif
+#ifdef _O_NOCTTY
+ { TGT_O_NOCTTY, _O_NOCTTY },
+#endif
+#ifdef _O_SYNC
+ { TGT_O_SYNC, _O_SYNC },
+#endif
+#else /* !_MSC_VER */
+ { TGT_O_RDONLY, O_RDONLY },
+ { TGT_O_WRONLY, O_WRONLY },
+ { TGT_O_RDWR, O_RDWR },
+ { TGT_O_APPEND, O_APPEND },
+ { TGT_O_CREAT, O_CREAT },
+ { TGT_O_TRUNC, O_TRUNC },
+ { TGT_O_EXCL, O_EXCL },
+ { TGT_O_NONBLOCK, O_NONBLOCK },
+ { TGT_O_NOCTTY, O_NOCTTY },
+#ifdef O_SYNC
+ { TGT_O_SYNC, O_SYNC },
+#endif
+#endif /* _MSC_VER */
+};
+
+const int X86Linux32::NUM_OPEN_FLAGS =
+ sizeof(X86Linux32::openFlagTable) /
+ sizeof(X86Linux32::openFlagTable[0]);
+
diff --git a/src/arch/x86/linux/linux.hh b/src/arch/x86/linux/linux.hh
index 8a78d5320..c2941c769 100644
--- a/src/arch/x86/linux/linux.hh
+++ b/src/arch/x86/linux/linux.hh
@@ -82,26 +82,26 @@ class X86Linux64 : public Linux
uint64_t st_mtime_nsec;
uint64_t st_ctimeX;
uint64_t st_ctime_nsec;
- int64_t __unused[3];
+ int64_t unused0[3];
} tgt_stat64;
static OpenFlagTransTable openFlagTable[];
- static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY
- static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY
- static const int TGT_O_RDWR = 00000002; //!< O_RDWR
- static const int TGT_O_NONBLOCK = 00004000; //!< O_NONBLOCK
- static const int TGT_O_APPEND = 00002000; //!< O_APPEND
- static const int TGT_O_CREAT = 00000100; //!< O_CREAT
- static const int TGT_O_TRUNC = 00001000; //!< O_TRUNC
- static const int TGT_O_EXCL = 00000200; //!< O_EXCL
- static const int TGT_O_NOCTTY = 00000400; //!< O_NOCTTY
- static const int TGT_O_SYNC = 00010000; //!< O_SYNC
-// static const int TGT_O_DRD = 0x00010000; //!< O_DRD
-// static const int TGT_O_DIRECTIO = 0x00020000; //!< O_DIRECTIO
-// static const int TGT_O_CACHE = 0x00002000; //!< O_CACHE
-// static const int TGT_O_DSYNC = 0x00008000; //!< O_DSYNC
-// static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC
+ static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY
+ static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY
+ static const int TGT_O_RDWR = 00000002; //!< O_RDWR
+ static const int TGT_O_NONBLOCK = 00004000; //!< O_NONBLOCK
+ static const int TGT_O_APPEND = 00002000; //!< O_APPEND
+ static const int TGT_O_CREAT = 00000100; //!< O_CREAT
+ static const int TGT_O_TRUNC = 00001000; //!< O_TRUNC
+ static const int TGT_O_EXCL = 00000200; //!< O_EXCL
+ static const int TGT_O_NOCTTY = 00000400; //!< O_NOCTTY
+ static const int TGT_O_SYNC = 00010000; //!< O_SYNC
+// static const int TGT_O_DRD = 0x00010000; //!< O_DRD
+// static const int TGT_O_DIRECTIO = 0x00020000; //!< O_DIRECTIO
+// static const int TGT_O_CACHE = 0x00002000; //!< O_CACHE
+// static const int TGT_O_DSYNC = 0x00008000; //!< O_DSYNC
+// static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC
static const int NUM_OPEN_FLAGS;
@@ -113,4 +113,53 @@ class X86Linux64 : public Linux
} tgt_iovec;
};
+class X86Linux32 : public Linux
+{
+ public:
+
+ typedef struct {
+ uint64_t st_dev;
+ uint8_t __pad0[4];
+ uint32_t __st_ino;
+ uint32_t st_mode;
+ uint32_t st_nlink;
+ uint32_t st_uid;
+ uint32_t st_gid;
+ uint64_t st_rdev;
+ int64_t st_size;
+ uint8_t __pad3[4];
+ uint32_t st_blksize;
+ uint64_t st_blocks;
+ uint32_t st_atimeX;
+ uint32_t st_atime_nsec;
+ uint32_t st_mtimeX;
+ uint32_t st_mtime_nsec;
+ uint32_t st_ctimeX;
+ uint32_t st_ctime_nsec;
+ uint64_t st_ino;
+ } tgt_stat64;
+
+ static OpenFlagTransTable openFlagTable[];
+
+ static const int TGT_O_RDONLY = 00000000; //!< O_RDONLY
+ static const int TGT_O_WRONLY = 00000001; //!< O_WRONLY
+ static const int TGT_O_RDWR = 00000002; //!< O_RDWR
+ static const int TGT_O_NONBLOCK = 00004000; //!< O_NONBLOCK
+ static const int TGT_O_APPEND = 00002000; //!< O_APPEND
+ static const int TGT_O_CREAT = 00000100; //!< O_CREAT
+ static const int TGT_O_TRUNC = 00001000; //!< O_TRUNC
+ static const int TGT_O_EXCL = 00000200; //!< O_EXCL
+ static const int TGT_O_NOCTTY = 00000400; //!< O_NOCTTY
+ static const int TGT_O_SYNC = 00010000; //!< O_SYNC
+// static const int TGT_O_DRD = 0x00010000; //!< O_DRD
+// static const int TGT_O_DIRECTIO = 0x00020000; //!< O_DIRECTIO
+// static const int TGT_O_CACHE = 0x00002000; //!< O_CACHE
+// static const int TGT_O_DSYNC = 0x00008000; //!< O_DSYNC
+// static const int TGT_O_RSYNC = 0x00040000; //!< O_RSYNC
+
+ static const int NUM_OPEN_FLAGS;
+
+ static const unsigned TGT_MAP_ANONYMOUS = 0x20;
+};
+
#endif
diff --git a/src/arch/x86/linux/process.cc b/src/arch/x86/linux/process.cc
index 8beaf150b..da22d9851 100644
--- a/src/arch/x86/linux/process.cc
+++ b/src/arch/x86/linux/process.cc
@@ -64,34 +64,16 @@
#include "kern/linux/linux.hh"
#include "sim/process.hh"
-#include "sim/syscall_emul.hh"
using namespace std;
using namespace X86ISA;
-SyscallDesc*
-X86LinuxProcess::getDesc(int callnum)
-{
- if (callnum < 0 || callnum > Num_Syscall_Descs)
- return NULL;
- return &syscallDescs[callnum];
-}
-
-X86LinuxProcess::X86LinuxProcess(LiveProcessParams * params,
+X86_64LinuxProcess::X86_64LinuxProcess(LiveProcessParams * params,
ObjectFile *objFile)
- : X86LiveProcess(params, objFile),
- Num_Syscall_Descs(273)
+ : X86_64LiveProcess(params, objFile, syscallDescs, 273)
{}
-void X86LinuxProcess::handleTrap(int trapNum, ThreadContext *tc)
-{
- switch(trapNum)
- {
- //This implementation is from SPARC
- case 0x10: //Linux 32 bit syscall trap
- tc->syscall(tc->readIntReg(1));
- break;
- default:
- X86LiveProcess::handleTrap(trapNum, tc);
- }
-}
+I386LinuxProcess::I386LinuxProcess(LiveProcessParams * params,
+ ObjectFile *objFile)
+ : I386LiveProcess(params, objFile, syscallDescs, 324)
+{}
diff --git a/src/arch/x86/linux/process.hh b/src/arch/x86/linux/process.hh
index e224374d4..ca3606ef0 100644
--- a/src/arch/x86/linux/process.hh
+++ b/src/arch/x86/linux/process.hh
@@ -60,26 +60,30 @@
#include "sim/process.hh"
#include "arch/x86/linux/linux.hh"
-#include "arch/x86/syscallreturn.hh"
#include "arch/x86/process.hh"
namespace X86ISA {
-/// A process with emulated x86/Linux syscalls.
-class X86LinuxProcess : public X86LiveProcess
+class X86_64LinuxProcess : public X86_64LiveProcess
{
+ protected:
+ /// Array of syscall descriptors, indexed by call number.
+ static SyscallDesc syscallDescs[];
+
public:
/// Constructor.
- X86LinuxProcess(LiveProcessParams * params, ObjectFile *objFile);
+ X86_64LinuxProcess(LiveProcessParams * params, ObjectFile *objFile);
+};
+class I386LinuxProcess : public I386LiveProcess
+{
+ protected:
/// Array of syscall descriptors, indexed by call number.
static SyscallDesc syscallDescs[];
- SyscallDesc* getDesc(int callnum);
-
- const int Num_Syscall_Descs;
-
- void handleTrap(int trapNum, ThreadContext *tc);
+ public:
+ /// Constructor.
+ I386LinuxProcess(LiveProcessParams * params, ObjectFile *objFile);
};
} // namespace X86ISA
diff --git a/src/arch/x86/linux/syscalls.cc b/src/arch/x86/linux/syscalls.cc
index ae2ac243b..09235ec94 100644
--- a/src/arch/x86/linux/syscalls.cc
+++ b/src/arch/x86/linux/syscalls.cc
@@ -68,7 +68,7 @@ static SyscallReturn
unameFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
ThreadContext *tc)
{
- TypedBufferArg<Linux::utsname> name(tc->getSyscallArg(0));
+ TypedBufferArg<Linux::utsname> name(process->getSyscallArg(tc, 0));
strcpy(name->sysname, "Linux");
strcpy(name->nodename, "m5.eecs.umich.edu");
@@ -94,8 +94,8 @@ archPrctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
};
//First argument is the code, second is the address
- int code = tc->getSyscallArg(0);
- uint64_t addr = tc->getSyscallArg(1);
+ int code = process->getSyscallArg(tc, 0);
+ uint64_t addr = process->getSyscallArg(tc, 1);
uint64_t fsBase, gsBase;
TranslatingPort *p = tc->getMemPort();
switch(code)
@@ -122,7 +122,112 @@ archPrctlFunc(SyscallDesc *desc, int callnum, LiveProcess *process,
}
}
-SyscallDesc X86LinuxProcess::syscallDescs[] = {
+BitUnion32(UserDescFlags)
+ Bitfield<0> seg_32bit;
+ Bitfield<2, 1> contents;
+ Bitfield<3> read_exec_only;
+ Bitfield<4> limit_in_pages;
+ Bitfield<5> seg_not_present;
+ Bitfield<6> useable;
+EndBitUnion(UserDescFlags)
+
+struct UserDesc32 {
+ uint32_t entry_number;
+ uint32_t base_addr;
+ uint32_t limit;
+ uint32_t flags;
+};
+
+struct UserDesc64 {
+ uint32_t entry_number;
+ uint32_t __padding1;
+ uint64_t base_addr;
+ uint32_t limit;
+ uint32_t flags;
+};
+
+static SyscallReturn
+setThreadArea32Func(SyscallDesc *desc, int callnum,
+ LiveProcess *process, ThreadContext *tc)
+{
+ const int minTLSEntry = 6;
+ const int numTLSEntries = 3;
+ const int maxTLSEntry = minTLSEntry + numTLSEntries - 1;
+
+ X86LiveProcess *x86lp = dynamic_cast<X86LiveProcess *>(process);
+ assert(x86lp);
+
+ assert((maxTLSEntry + 1) * sizeof(uint64_t) <= x86lp->gdtSize());
+
+ TypedBufferArg<UserDesc32> userDesc(process->getSyscallArg(tc, 0));
+ TypedBufferArg<uint64_t>
+ gdt(x86lp->gdtStart() + minTLSEntry * sizeof(uint64_t),
+ numTLSEntries * sizeof(uint64_t));
+
+ if (!userDesc.copyIn(tc->getMemPort()))
+ return -EFAULT;
+
+ if (!gdt.copyIn(tc->getMemPort()))
+ panic("Failed to copy in GDT for %s.\n", desc->name);
+
+ if (userDesc->entry_number == (uint32_t)(-1)) {
+ // Find a free TLS entry.
+ for (int i = 0; i < numTLSEntries; i++) {
+ if (gdt[i] == 0) {
+ userDesc->entry_number = i + minTLSEntry;
+ break;
+ }
+ }
+ // We failed to find one.
+ if (userDesc->entry_number == (uint32_t)(-1))
+ return -ESRCH;
+ }
+
+ int index = userDesc->entry_number;
+
+ if (index < minTLSEntry || index > maxTLSEntry)
+ return -EINVAL;
+
+ index -= minTLSEntry;
+
+ // Build the entry we're going to add.
+ SegDescriptor segDesc = 0;
+ UserDescFlags flags = userDesc->flags;
+
+ segDesc.limitLow = bits(userDesc->limit, 15, 0);
+ segDesc.baseLow = bits(userDesc->base_addr, 23, 0);
+ segDesc.type.a = 1;
+ if (!flags.read_exec_only)
+ segDesc.type.w = 1;
+ if (bits((uint8_t)flags.contents, 0))
+ segDesc.type.e = 1;
+ if (bits((uint8_t)flags.contents, 1))
+ segDesc.type.codeOrData = 1;
+ segDesc.s = 1;
+ segDesc.dpl = 3;
+ if (!flags.seg_not_present)
+ segDesc.p = 1;
+ segDesc.limitHigh = bits(userDesc->limit, 19, 16);
+ if (flags.useable)
+ segDesc.avl = 1;
+ segDesc.l = 0;
+ if (flags.seg_32bit)
+ segDesc.d = 1;
+ if (flags.limit_in_pages)
+ segDesc.g = 1;
+ segDesc.baseHigh = bits(userDesc->base_addr, 31, 24);
+
+ gdt[index] = (uint64_t)segDesc;
+
+ if (!userDesc.copyOut(tc->getMemPort()))
+ return -EFAULT;
+ if (!gdt.copyOut(tc->getMemPort()))
+ panic("Failed to copy out GDT for %s.\n", desc->name);
+
+ return 0;
+}
+
+SyscallDesc X86_64LinuxProcess::syscallDescs[] = {
/* 0 */ SyscallDesc("read", readFunc),
/* 1 */ SyscallDesc("write", writeFunc),
/* 2 */ SyscallDesc("open", openFunc<X86Linux64>),
@@ -135,7 +240,7 @@ SyscallDesc X86LinuxProcess::syscallDescs[] = {
/* 9 */ SyscallDesc("mmap", mmapFunc<X86Linux64>),
/* 10 */ SyscallDesc("mprotect", unimplementedFunc),
/* 11 */ SyscallDesc("munmap", munmapFunc),
- /* 12 */ SyscallDesc("brk", obreakFunc),
+ /* 12 */ SyscallDesc("brk", brkFunc),
/* 13 */ SyscallDesc("rt_sigaction", unimplementedFunc),
/* 14 */ SyscallDesc("rt_sigprocmask", unimplementedFunc),
/* 15 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
@@ -148,7 +253,7 @@ SyscallDesc X86LinuxProcess::syscallDescs[] = {
/* 22 */ SyscallDesc("pipe", unimplementedFunc),
/* 23 */ SyscallDesc("select", unimplementedFunc),
/* 24 */ SyscallDesc("sched_yield", unimplementedFunc),
- /* 25 */ SyscallDesc("mremap", unimplementedFunc),
+ /* 25 */ SyscallDesc("mremap", mremapFunc<X86Linux64>),
/* 26 */ SyscallDesc("msync", unimplementedFunc),
/* 27 */ SyscallDesc("mincore", unimplementedFunc),
/* 28 */ SyscallDesc("madvise", unimplementedFunc),
@@ -397,3 +502,330 @@ SyscallDesc X86LinuxProcess::syscallDescs[] = {
/* 271 */ SyscallDesc("ppoll", unimplementedFunc),
/* 272 */ SyscallDesc("unshare", unimplementedFunc)
};
+
+SyscallDesc I386LinuxProcess::syscallDescs[] = {
+ /* 0 */ SyscallDesc("restart_syscall", unimplementedFunc),
+ /* 1 */ SyscallDesc("exit", unimplementedFunc),
+ /* 2 */ SyscallDesc("fork", unimplementedFunc),
+ /* 3 */ SyscallDesc("read", unimplementedFunc),
+ /* 4 */ SyscallDesc("write", writeFunc),
+ /* 5 */ SyscallDesc("open", openFunc<X86Linux64>),
+ /* 6 */ SyscallDesc("close", unimplementedFunc),
+ /* 7 */ SyscallDesc("waitpid", unimplementedFunc),
+ /* 8 */ SyscallDesc("creat", unimplementedFunc),
+ /* 9 */ SyscallDesc("link", unimplementedFunc),
+ /* 10 */ SyscallDesc("unlink", unimplementedFunc),
+ /* 11 */ SyscallDesc("execve", unimplementedFunc),
+ /* 12 */ SyscallDesc("chdir", unimplementedFunc),
+ /* 13 */ SyscallDesc("time", unimplementedFunc),
+ /* 14 */ SyscallDesc("mknod", unimplementedFunc),
+ /* 15 */ SyscallDesc("chmod", unimplementedFunc),
+ /* 16 */ SyscallDesc("lchown", unimplementedFunc),
+ /* 17 */ SyscallDesc("break", unimplementedFunc),
+ /* 18 */ SyscallDesc("oldstat", unimplementedFunc),
+ /* 19 */ SyscallDesc("lseek", unimplementedFunc),
+ /* 20 */ SyscallDesc("getpid", unimplementedFunc),
+ /* 21 */ SyscallDesc("mount", unimplementedFunc),
+ /* 22 */ SyscallDesc("umount", unimplementedFunc),
+ /* 23 */ SyscallDesc("setuid", unimplementedFunc),
+ /* 24 */ SyscallDesc("getuid", unimplementedFunc),
+ /* 25 */ SyscallDesc("stime", unimplementedFunc),
+ /* 26 */ SyscallDesc("ptrace", unimplementedFunc),
+ /* 27 */ SyscallDesc("alarm", unimplementedFunc),
+ /* 28 */ SyscallDesc("oldfstat", unimplementedFunc),
+ /* 29 */ SyscallDesc("pause", unimplementedFunc),
+ /* 30 */ SyscallDesc("utime", unimplementedFunc),
+ /* 31 */ SyscallDesc("stty", unimplementedFunc),
+ /* 32 */ SyscallDesc("gtty", unimplementedFunc),
+ /* 33 */ SyscallDesc("access", unimplementedFunc),
+ /* 34 */ SyscallDesc("nice", unimplementedFunc),
+ /* 35 */ SyscallDesc("ftime", unimplementedFunc),
+ /* 36 */ SyscallDesc("sync", unimplementedFunc),
+ /* 37 */ SyscallDesc("kill", unimplementedFunc),
+ /* 38 */ SyscallDesc("rename", unimplementedFunc),
+ /* 39 */ SyscallDesc("mkdir", unimplementedFunc),
+ /* 40 */ SyscallDesc("rmdir", unimplementedFunc),
+ /* 41 */ SyscallDesc("dup", unimplementedFunc),
+ /* 42 */ SyscallDesc("pipe", unimplementedFunc),
+ /* 43 */ SyscallDesc("times", unimplementedFunc),
+ /* 44 */ SyscallDesc("prof", unimplementedFunc),
+ /* 45 */ SyscallDesc("brk", brkFunc),
+ /* 46 */ SyscallDesc("setgid", unimplementedFunc),
+ /* 47 */ SyscallDesc("getgid", unimplementedFunc),
+ /* 48 */ SyscallDesc("signal", unimplementedFunc),
+ /* 49 */ SyscallDesc("geteuid", unimplementedFunc),
+ /* 50 */ SyscallDesc("getegid", unimplementedFunc),
+ /* 51 */ SyscallDesc("acct", unimplementedFunc),
+ /* 52 */ SyscallDesc("umount2", unimplementedFunc),
+ /* 53 */ SyscallDesc("lock", unimplementedFunc),
+ /* 54 */ SyscallDesc("ioctl", unimplementedFunc),
+ /* 55 */ SyscallDesc("fcntl", unimplementedFunc),
+ /* 56 */ SyscallDesc("mpx", unimplementedFunc),
+ /* 57 */ SyscallDesc("setpgid", unimplementedFunc),
+ /* 58 */ SyscallDesc("ulimit", unimplementedFunc),
+ /* 59 */ SyscallDesc("oldolduname", unimplementedFunc),
+ /* 60 */ SyscallDesc("umask", unimplementedFunc),
+ /* 61 */ SyscallDesc("chroot", unimplementedFunc),
+ /* 62 */ SyscallDesc("ustat", unimplementedFunc),
+ /* 63 */ SyscallDesc("dup2", unimplementedFunc),
+ /* 64 */ SyscallDesc("getppid", unimplementedFunc),
+ /* 65 */ SyscallDesc("getpgrp", unimplementedFunc),
+ /* 66 */ SyscallDesc("setsid", unimplementedFunc),
+ /* 67 */ SyscallDesc("sigaction", unimplementedFunc),
+ /* 68 */ SyscallDesc("sgetmask", unimplementedFunc),
+ /* 69 */ SyscallDesc("ssetmask", unimplementedFunc),
+ /* 70 */ SyscallDesc("setreuid", unimplementedFunc),
+ /* 71 */ SyscallDesc("setregid", unimplementedFunc),
+ /* 72 */ SyscallDesc("sigsuspend", unimplementedFunc),
+ /* 73 */ SyscallDesc("sigpending", unimplementedFunc),
+ /* 74 */ SyscallDesc("sethostname", unimplementedFunc),
+ /* 75 */ SyscallDesc("setrlimit", unimplementedFunc),
+ /* 76 */ SyscallDesc("getrlimit", unimplementedFunc),
+ /* 77 */ SyscallDesc("getrusage", unimplementedFunc),
+ /* 78 */ SyscallDesc("gettimeofday", unimplementedFunc),
+ /* 79 */ SyscallDesc("settimeofday", unimplementedFunc),
+ /* 80 */ SyscallDesc("getgroups", unimplementedFunc),
+ /* 81 */ SyscallDesc("setgroups", unimplementedFunc),
+ /* 82 */ SyscallDesc("select", unimplementedFunc),
+ /* 83 */ SyscallDesc("symlink", unimplementedFunc),
+ /* 84 */ SyscallDesc("oldlstat", unimplementedFunc),
+ /* 85 */ SyscallDesc("readlink", unimplementedFunc),
+ /* 86 */ SyscallDesc("uselib", unimplementedFunc),
+ /* 87 */ SyscallDesc("swapon", unimplementedFunc),
+ /* 88 */ SyscallDesc("reboot", unimplementedFunc),
+ /* 89 */ SyscallDesc("readdir", unimplementedFunc),
+ /* 90 */ SyscallDesc("mmap", unimplementedFunc),
+ /* 91 */ SyscallDesc("munmap", unimplementedFunc),
+ /* 92 */ SyscallDesc("truncate", unimplementedFunc),
+ /* 93 */ SyscallDesc("ftruncate", unimplementedFunc),
+ /* 94 */ SyscallDesc("fchmod", unimplementedFunc),
+ /* 95 */ SyscallDesc("fchown", unimplementedFunc),
+ /* 96 */ SyscallDesc("getpriority", unimplementedFunc),
+ /* 97 */ SyscallDesc("setpriority", unimplementedFunc),
+ /* 98 */ SyscallDesc("profil", unimplementedFunc),
+ /* 99 */ SyscallDesc("statfs", unimplementedFunc),
+ /* 100 */ SyscallDesc("fstatfs", unimplementedFunc),
+ /* 101 */ SyscallDesc("ioperm", unimplementedFunc),
+ /* 102 */ SyscallDesc("socketcall", unimplementedFunc),
+ /* 103 */ SyscallDesc("syslog", unimplementedFunc),
+ /* 104 */ SyscallDesc("setitimer", unimplementedFunc),
+ /* 105 */ SyscallDesc("getitimer", unimplementedFunc),
+ /* 106 */ SyscallDesc("stat", unimplementedFunc),
+ /* 107 */ SyscallDesc("lstat", unimplementedFunc),
+ /* 108 */ SyscallDesc("fstat", unimplementedFunc),
+ /* 109 */ SyscallDesc("olduname", unimplementedFunc),
+ /* 110 */ SyscallDesc("iopl", unimplementedFunc),
+ /* 111 */ SyscallDesc("vhangup", unimplementedFunc),
+ /* 112 */ SyscallDesc("idle", unimplementedFunc),
+ /* 113 */ SyscallDesc("vm86old", unimplementedFunc),
+ /* 114 */ SyscallDesc("wait4", unimplementedFunc),
+ /* 115 */ SyscallDesc("swapoff", unimplementedFunc),
+ /* 116 */ SyscallDesc("sysinfo", unimplementedFunc),
+ /* 117 */ SyscallDesc("ipc", unimplementedFunc),
+ /* 118 */ SyscallDesc("fsync", unimplementedFunc),
+ /* 119 */ SyscallDesc("sigreturn", unimplementedFunc),
+ /* 120 */ SyscallDesc("clone", unimplementedFunc),
+ /* 121 */ SyscallDesc("setdomainname", unimplementedFunc),
+ /* 122 */ SyscallDesc("uname", unameFunc),
+ /* 123 */ SyscallDesc("modify_ldt", unimplementedFunc),
+ /* 124 */ SyscallDesc("adjtimex", unimplementedFunc),
+ /* 125 */ SyscallDesc("mprotect", unimplementedFunc),
+ /* 126 */ SyscallDesc("sigprocmask", unimplementedFunc),
+ /* 127 */ SyscallDesc("create_module", unimplementedFunc),
+ /* 128 */ SyscallDesc("init_module", unimplementedFunc),
+ /* 129 */ SyscallDesc("delete_module", unimplementedFunc),
+ /* 130 */ SyscallDesc("get_kernel_syms", unimplementedFunc),
+ /* 131 */ SyscallDesc("quotactl", unimplementedFunc),
+ /* 132 */ SyscallDesc("getpgid", unimplementedFunc),
+ /* 133 */ SyscallDesc("fchdir", unimplementedFunc),
+ /* 134 */ SyscallDesc("bdflush", unimplementedFunc),
+ /* 135 */ SyscallDesc("sysfs", unimplementedFunc),
+ /* 136 */ SyscallDesc("personality", unimplementedFunc),
+ /* 137 */ SyscallDesc("afs_syscall", unimplementedFunc),
+ /* 138 */ SyscallDesc("setfsuid", unimplementedFunc),
+ /* 139 */ SyscallDesc("setfsgid", unimplementedFunc),
+ /* 140 */ SyscallDesc("_llseek", unimplementedFunc),
+ /* 141 */ SyscallDesc("getdents", unimplementedFunc),
+ /* 142 */ SyscallDesc("_newselect", unimplementedFunc),
+ /* 143 */ SyscallDesc("flock", unimplementedFunc),
+ /* 144 */ SyscallDesc("msync", unimplementedFunc),
+ /* 145 */ SyscallDesc("readv", unimplementedFunc),
+ /* 146 */ SyscallDesc("writev", writevFunc<X86Linux32>),
+ /* 147 */ SyscallDesc("getsid", unimplementedFunc),
+ /* 148 */ SyscallDesc("fdatasync", unimplementedFunc),
+ /* 149 */ SyscallDesc("_sysctl", unimplementedFunc),
+ /* 150 */ SyscallDesc("mlock", unimplementedFunc),
+ /* 151 */ SyscallDesc("munlock", unimplementedFunc),
+ /* 152 */ SyscallDesc("mlockall", unimplementedFunc),
+ /* 153 */ SyscallDesc("munlockall", unimplementedFunc),
+ /* 154 */ SyscallDesc("sched_setparam", unimplementedFunc),
+ /* 155 */ SyscallDesc("sched_getparam", unimplementedFunc),
+ /* 156 */ SyscallDesc("sched_setscheduler", unimplementedFunc),
+ /* 157 */ SyscallDesc("sched_getscheduler", unimplementedFunc),
+ /* 158 */ SyscallDesc("sched_yield", unimplementedFunc),
+ /* 159 */ SyscallDesc("sched_get_priority_max", unimplementedFunc),
+ /* 160 */ SyscallDesc("sched_get_priority_min", unimplementedFunc),
+ /* 161 */ SyscallDesc("sched_rr_get_interval", unimplementedFunc),
+ /* 162 */ SyscallDesc("nanosleep", unimplementedFunc),
+ /* 163 */ SyscallDesc("mremap", unimplementedFunc),
+ /* 164 */ SyscallDesc("setresuid", unimplementedFunc),
+ /* 165 */ SyscallDesc("getresuid", unimplementedFunc),
+ /* 166 */ SyscallDesc("vm86", unimplementedFunc),
+ /* 167 */ SyscallDesc("query_module", unimplementedFunc),
+ /* 168 */ SyscallDesc("poll", unimplementedFunc),
+ /* 169 */ SyscallDesc("nfsservctl", unimplementedFunc),
+ /* 170 */ SyscallDesc("setresgid", unimplementedFunc),
+ /* 171 */ SyscallDesc("getresgid", unimplementedFunc),
+ /* 172 */ SyscallDesc("prctl", unimplementedFunc),
+ /* 173 */ SyscallDesc("rt_sigreturn", unimplementedFunc),
+ /* 174 */ SyscallDesc("rt_sigaction", unimplementedFunc),
+ /* 175 */ SyscallDesc("rt_sigprocmask", unimplementedFunc),
+ /* 176 */ SyscallDesc("rt_sigpending", unimplementedFunc),
+ /* 177 */ SyscallDesc("rt_sigtimedwait", unimplementedFunc),
+ /* 178 */ SyscallDesc("rt_sigqueueinfo", unimplementedFunc),
+ /* 179 */ SyscallDesc("rt_sigsuspend", unimplementedFunc),
+ /* 180 */ SyscallDesc("pread64", unimplementedFunc),
+ /* 181 */ SyscallDesc("pwrite64", unimplementedFunc),
+ /* 182 */ SyscallDesc("chown", unimplementedFunc),
+ /* 183 */ SyscallDesc("getcwd", unimplementedFunc),
+ /* 184 */ SyscallDesc("capget", unimplementedFunc),
+ /* 185 */ SyscallDesc("capset", unimplementedFunc),
+ /* 186 */ SyscallDesc("sigaltstack", unimplementedFunc),
+ /* 187 */ SyscallDesc("sendfile", unimplementedFunc),
+ /* 188 */ SyscallDesc("getpmsg", unimplementedFunc),
+ /* 189 */ SyscallDesc("putpmsg", unimplementedFunc),
+ /* 190 */ SyscallDesc("vfork", unimplementedFunc),
+ /* 191 */ SyscallDesc("ugetrlimit", unimplementedFunc),
+ /* 192 */ SyscallDesc("mmap2", mmapFunc<X86Linux32>),
+ /* 193 */ SyscallDesc("truncate64", unimplementedFunc),
+ /* 194 */ SyscallDesc("ftruncate64", unimplementedFunc),
+ /* 195 */ SyscallDesc("stat64", unimplementedFunc),
+ /* 196 */ SyscallDesc("lstat64", unimplementedFunc),
+ /* 197 */ SyscallDesc("fstat64", fstat64Func<X86Linux32>),
+ /* 198 */ SyscallDesc("lchown32", unimplementedFunc),
+ /* 199 */ SyscallDesc("getuid32", unimplementedFunc),
+ /* 200 */ SyscallDesc("getgid32", unimplementedFunc),
+ /* 201 */ SyscallDesc("geteuid32", unimplementedFunc),
+ /* 202 */ SyscallDesc("getegid32", unimplementedFunc),
+ /* 203 */ SyscallDesc("setreuid32", unimplementedFunc),
+ /* 204 */ SyscallDesc("setregid32", unimplementedFunc),
+ /* 205 */ SyscallDesc("getgroups32", unimplementedFunc),
+ /* 206 */ SyscallDesc("setgroups32", unimplementedFunc),
+ /* 207 */ SyscallDesc("fchown32", unimplementedFunc),
+ /* 208 */ SyscallDesc("setresuid32", unimplementedFunc),
+ /* 209 */ SyscallDesc("getresuid32", unimplementedFunc),
+ /* 210 */ SyscallDesc("setresgid32", unimplementedFunc),
+ /* 211 */ SyscallDesc("getresgid32", unimplementedFunc),
+ /* 212 */ SyscallDesc("chown32", unimplementedFunc),
+ /* 213 */ SyscallDesc("setuid32", unimplementedFunc),
+ /* 214 */ SyscallDesc("setgid32", unimplementedFunc),
+ /* 215 */ SyscallDesc("setfsuid32", unimplementedFunc),
+ /* 216 */ SyscallDesc("setfsgid32", unimplementedFunc),
+ /* 217 */ SyscallDesc("pivot_root", unimplementedFunc),
+ /* 218 */ SyscallDesc("mincore", unimplementedFunc),
+ /* 219 */ SyscallDesc("madvise", unimplementedFunc),
+ /* 220 */ SyscallDesc("madvise1", unimplementedFunc),
+ /* 221 */ SyscallDesc("getdents64", unimplementedFunc),
+ /* 222 */ SyscallDesc("fcntl64", unimplementedFunc),
+ /* 223 */ SyscallDesc("unused", unimplementedFunc),
+ /* 224 */ SyscallDesc("gettid", unimplementedFunc),
+ /* 225 */ SyscallDesc("readahead", unimplementedFunc),
+ /* 226 */ SyscallDesc("setxattr", unimplementedFunc),
+ /* 227 */ SyscallDesc("lsetxattr", unimplementedFunc),
+ /* 228 */ SyscallDesc("fsetxattr", unimplementedFunc),
+ /* 229 */ SyscallDesc("getxattr", unimplementedFunc),
+ /* 230 */ SyscallDesc("lgetxattr", unimplementedFunc),
+ /* 231 */ SyscallDesc("fgetxattr", unimplementedFunc),
+ /* 232 */ SyscallDesc("listxattr", unimplementedFunc),
+ /* 233 */ SyscallDesc("llistxattr", unimplementedFunc),
+ /* 234 */ SyscallDesc("flistxattr", unimplementedFunc),
+ /* 235 */ SyscallDesc("removexattr", unimplementedFunc),
+ /* 236 */ SyscallDesc("lremovexattr", unimplementedFunc),
+ /* 237 */ SyscallDesc("fremovexattr", unimplementedFunc),
+ /* 238 */ SyscallDesc("tkill", unimplementedFunc),
+ /* 239 */ SyscallDesc("sendfile64", unimplementedFunc),
+ /* 240 */ SyscallDesc("futex", unimplementedFunc),
+ /* 241 */ SyscallDesc("sched_setaffinity", unimplementedFunc),
+ /* 242 */ SyscallDesc("sched_getaffinity", unimplementedFunc),
+ /* 243 */ SyscallDesc("set_thread_area", setThreadArea32Func),
+ /* 244 */ SyscallDesc("get_thread_area", unimplementedFunc),
+ /* 245 */ SyscallDesc("io_setup", unimplementedFunc),
+ /* 246 */ SyscallDesc("io_destroy", unimplementedFunc),
+ /* 247 */ SyscallDesc("io_getevents", unimplementedFunc),
+ /* 248 */ SyscallDesc("io_submit", unimplementedFunc),
+ /* 249 */ SyscallDesc("io_cancel", unimplementedFunc),
+ /* 250 */ SyscallDesc("fadvise64", unimplementedFunc),
+ /* 251 */ SyscallDesc("unused", unimplementedFunc),
+ /* 252 */ SyscallDesc("exit_group", exitFunc),
+ /* 253 */ SyscallDesc("lookup_dcookie", unimplementedFunc),
+ /* 254 */ SyscallDesc("epoll_create", unimplementedFunc),
+ /* 255 */ SyscallDesc("epoll_ctl", unimplementedFunc),
+ /* 256 */ SyscallDesc("epoll_wait", unimplementedFunc),
+ /* 257 */ SyscallDesc("remap_file_pages", unimplementedFunc),
+ /* 258 */ SyscallDesc("set_tid_address", unimplementedFunc),
+ /* 259 */ SyscallDesc("timer_create", unimplementedFunc),
+ /* 260 */ SyscallDesc("timer_settime", unimplementedFunc),
+ /* 261 */ SyscallDesc("timer_gettime", unimplementedFunc),
+ /* 262 */ SyscallDesc("timer_getoverrun", unimplementedFunc),
+ /* 263 */ SyscallDesc("timer_delete", unimplementedFunc),
+ /* 264 */ SyscallDesc("clock_settime", unimplementedFunc),
+ /* 265 */ SyscallDesc("clock_gettime", unimplementedFunc),
+ /* 266 */ SyscallDesc("clock_getres", unimplementedFunc),
+ /* 267 */ SyscallDesc("clock_nanosleep", unimplementedFunc),
+ /* 268 */ SyscallDesc("statfs64", unimplementedFunc),
+ /* 269 */ SyscallDesc("fstatfs64", unimplementedFunc),
+ /* 270 */ SyscallDesc("tgkill", unimplementedFunc),
+ /* 271 */ SyscallDesc("utimes", unimplementedFunc),
+ /* 272 */ SyscallDesc("fadvise64_64", unimplementedFunc),
+ /* 273 */ SyscallDesc("vserver", unimplementedFunc),
+ /* 274 */ SyscallDesc("mbind", unimplementedFunc),
+ /* 275 */ SyscallDesc("get_mempolicy", unimplementedFunc),
+ /* 276 */ SyscallDesc("set_mempolicy", unimplementedFunc),
+ /* 277 */ SyscallDesc("mq_open", unimplementedFunc),
+ /* 278 */ SyscallDesc("mq_unlink", unimplementedFunc),
+ /* 279 */ SyscallDesc("mq_timedsend", unimplementedFunc),
+ /* 280 */ SyscallDesc("mq_timedreceive", unimplementedFunc),
+ /* 281 */ SyscallDesc("mq_notify", unimplementedFunc),
+ /* 282 */ SyscallDesc("mq_getsetattr", unimplementedFunc),
+ /* 283 */ SyscallDesc("kexec_load", unimplementedFunc),
+ /* 284 */ SyscallDesc("waitid", unimplementedFunc),
+ /* 285 */ SyscallDesc("sys_setaltroot", unimplementedFunc),
+ /* 286 */ SyscallDesc("add_key", unimplementedFunc),
+ /* 287 */ SyscallDesc("request_key", unimplementedFunc),
+ /* 288 */ SyscallDesc("keyctl", unimplementedFunc),
+ /* 289 */ SyscallDesc("ioprio_set", unimplementedFunc),
+ /* 290 */ SyscallDesc("ioprio_get", unimplementedFunc),
+ /* 291 */ SyscallDesc("inotify_init", unimplementedFunc),
+ /* 292 */ SyscallDesc("inotify_add_watch", unimplementedFunc),
+ /* 293 */ SyscallDesc("inotify_rm_watch", unimplementedFunc),
+ /* 294 */ SyscallDesc("migrate_pages", unimplementedFunc),
+ /* 295 */ SyscallDesc("openat", unimplementedFunc),
+ /* 296 */ SyscallDesc("mkdirat", unimplementedFunc),
+ /* 297 */ SyscallDesc("mknodat", unimplementedFunc),
+ /* 298 */ SyscallDesc("fchownat", unimplementedFunc),
+ /* 299 */ SyscallDesc("futimesat", unimplementedFunc),
+ /* 300 */ SyscallDesc("fstatat64", unimplementedFunc),
+ /* 301 */ SyscallDesc("unlinkat", unimplementedFunc),
+ /* 302 */ SyscallDesc("renameat", unimplementedFunc),
+ /* 303 */ SyscallDesc("linkat", unimplementedFunc),
+ /* 304 */ SyscallDesc("symlinkat", unimplementedFunc),
+ /* 305 */ SyscallDesc("readlinkat", unimplementedFunc),
+ /* 306 */ SyscallDesc("fchmodat", unimplementedFunc),
+ /* 307 */ SyscallDesc("faccessat", unimplementedFunc),
+ /* 308 */ SyscallDesc("pselect6", unimplementedFunc),
+ /* 309 */ SyscallDesc("ppoll", unimplementedFunc),
+ /* 310 */ SyscallDesc("unshare", unimplementedFunc),
+ /* 311 */ SyscallDesc("set_robust_list", unimplementedFunc),
+ /* 312 */ SyscallDesc("get_robust_list", unimplementedFunc),
+ /* 313 */ SyscallDesc("splice", unimplementedFunc),
+ /* 314 */ SyscallDesc("sync_file_range", unimplementedFunc),
+ /* 315 */ SyscallDesc("tee", unimplementedFunc),
+ /* 316 */ SyscallDesc("vmsplice", unimplementedFunc),
+ /* 317 */ SyscallDesc("move_pages", unimplementedFunc),
+ /* 318 */ SyscallDesc("getcpu", unimplementedFunc),
+ /* 319 */ SyscallDesc("epoll_pwait", unimplementedFunc),
+ /* 320 */ SyscallDesc("utimensat", unimplementedFunc),
+ /* 321 */ SyscallDesc("signalfd", unimplementedFunc),
+ /* 322 */ SyscallDesc("timerfd", unimplementedFunc),
+ /* 323 */ SyscallDesc("eventfd", unimplementedFunc)
+};
diff --git a/src/arch/x86/linux/system.cc b/src/arch/x86/linux/system.cc
index 944bb2930..c2d9cb35c 100644
--- a/src/arch/x86/linux/system.cc
+++ b/src/arch/x86/linux/system.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms,
@@ -68,7 +68,7 @@ using namespace LittleEndianGuest;
using namespace X86ISA;
LinuxX86System::LinuxX86System(Params *p)
- : X86System(p), commandLine(p->boot_osflags)
+ : X86System(p), commandLine(p->boot_osflags), e820Table(p->e820_table)
{
}
@@ -144,62 +144,7 @@ LinuxX86System::startup()
// A pointer to the buffer for E820 entries.
const Addr e820MapPointer = realModeData + 0x2d0;
- struct e820Entry
- {
- Addr addr;
- Addr size;
- uint32_t type;
- };
-
- // The size is computed this way to ensure no padding sneaks in.
- int e820EntrySize =
- sizeof(e820Entry().addr) +
- sizeof(e820Entry().size) +
- sizeof(e820Entry().type);
-
- // I'm not sure what these should actually be. On a real machine they
- // would be generated by the BIOS, and they need to reflect the regions
- // which are actually available/reserved. These values are copied from
- // my development machine.
- e820Entry e820Map[] = {
- {ULL(0x0), ULL(0x9d400), 1},
- {ULL(0x9d400), ULL(0xa0000) - ULL(0x9d400), 2},
- {ULL(0xe8000), ULL(0x100000) - ULL(0xe8000), 2},
- {ULL(0x100000), ULL(0xcfff9300) - ULL(0x100000), 1},
- {ULL(0xcfff9300), ULL(0xd0000000) - ULL(0xcfff9300), 2},
- {ULL(0xfec00000), ULL(0x100000000) - ULL(0xfec00000), 2}
- };
-
- uint8_t e820Nr = sizeof(e820Map) / sizeof(e820Entry);
-
- // Make sure the number of entries isn't bigger than what the kernel
- // would be capable of providing.
- assert(e820Nr <= 128);
-
- uint8_t guestE820Nr = X86ISA::htog(e820Nr);
- physPort->writeBlob(e820MapNrPointer,
- (uint8_t *)&guestE820Nr, sizeof(guestE820Nr));
-
- for (int i = 0; i < e820Nr; i++) {
- e820Entry guestE820Entry;
- guestE820Entry.addr = X86ISA::htog(e820Map[i].addr);
- guestE820Entry.size = X86ISA::htog(e820Map[i].size);
- guestE820Entry.type = X86ISA::htog(e820Map[i].type);
- physPort->writeBlob(e820MapPointer + e820EntrySize * i,
- (uint8_t *)&guestE820Entry.addr,
- sizeof(guestE820Entry.addr));
- physPort->writeBlob(
- e820MapPointer + e820EntrySize * i +
- sizeof(guestE820Entry.addr),
- (uint8_t *)&guestE820Entry.size,
- sizeof(guestE820Entry.size));
- physPort->writeBlob(
- e820MapPointer + e820EntrySize * i +
- sizeof(guestE820Entry.addr) +
- sizeof(guestE820Entry.size),
- (uint8_t *)&guestE820Entry.type,
- sizeof(guestE820Entry.type));
- }
+ e820Table->writeTo(physPort, e820MapNrPointer, e820MapPointer);
/*
* Pass the location of the real mode data structure to the kernel
diff --git a/src/arch/x86/linux/system.hh b/src/arch/x86/linux/system.hh
index fc725ad45..a9c5f4ca9 100644
--- a/src/arch/x86/linux/system.hh
+++ b/src/arch/x86/linux/system.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms,
@@ -62,12 +62,14 @@
#include <vector>
#include "params/LinuxX86System.hh"
+#include "arch/x86/bios/e820.hh"
#include "arch/x86/system.hh"
class LinuxX86System : public X86System
{
protected:
std::string commandLine;
+ X86ISA::E820Table * e820Table;
public:
typedef LinuxX86SystemParams Params;
diff --git a/src/arch/x86/microcode_rom.hh b/src/arch/x86/microcode_rom.hh
new file mode 100644
index 000000000..f8ad410ce
--- /dev/null
+++ b/src/arch/x86/microcode_rom.hh
@@ -0,0 +1,74 @@
+/*
+ * 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_MICROCODE_ROM_HH__
+#define __ARCH_X86_MICROCODE_ROM_HH__
+
+#include "arch/x86/emulenv.hh"
+#include "cpu/static_inst.hh"
+
+namespace X86ISAInst
+{
+ class MicrocodeRom
+ {
+ protected:
+
+ typedef StaticInstPtr (*GenFunc)(StaticInstPtr);
+
+ static const MicroPC numMicroops;
+
+ GenFunc * genFuncs;
+
+ public:
+ //Constructor.
+ MicrocodeRom();
+
+ //Destructor.
+ ~MicrocodeRom()
+ {
+ delete [] genFuncs;
+ }
+
+ StaticInstPtr
+ fetchMicroop(MicroPC microPC, StaticInstPtr curMacroop)
+ {
+ microPC = normalMicroPC(microPC);
+ assert(microPC < numMicroops);
+ return genFuncs[microPC](curMacroop);
+ }
+ };
+}
+
+namespace X86ISA
+{
+ using X86ISAInst::MicrocodeRom;
+}
+
+#endif // __ARCH_X86_MICROCODE_ROM_HH__
diff --git a/src/arch/x86/miscregfile.cc b/src/arch/x86/miscregfile.cc
index 3b4dc3407..0316603e5 100644
--- a/src/arch/x86/miscregfile.cc
+++ b/src/arch/x86/miscregfile.cc
@@ -87,6 +87,7 @@
#include "arch/x86/miscregfile.hh"
#include "arch/x86/tlb.hh"
+#include "cpu/base.hh"
#include "cpu/thread_context.hh"
#include "sim/serialize.hh"
@@ -95,19 +96,16 @@ using namespace std;
class Checkpoint;
-//These functions map register indices to names
-string X86ISA::getMiscRegName(RegIndex index)
-{
- panic("No misc registers in x86 yet!\n");
-}
-
void MiscRegFile::clear()
{
- // Blank everything. 0 might not be an appropriate value for some things.
+ // Blank everything. 0 might not be an appropriate value for some things,
+ // but it is for most.
memset(regVal, 0, NumMiscRegs * sizeof(MiscReg));
+ regVal[MISCREG_DR6] = (mask(8) << 4) | (mask(16) << 16);
+ regVal[MISCREG_DR7] = 1 << 10;
}
-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
@@ -121,90 +119,15 @@ MiscReg MiscRegFile::readRegNoEffect(int miscReg)
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_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_TASK_PRIORITY:
- panic("Local APIC Task Priority register unimplemented.\n");
- 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:
- panic("Local APIC Logical Destination register unimplemented.\n");
- break;
- case MISCREG_APIC_DESTINATION_FORMAT:
- panic("Local APIC Destination Format register unimplemented.\n");
- break;
- case MISCREG_APIC_SPURIOUS_INTERRUPT_VECTOR:
- panic("Local APIC Spurious Interrupt Vector"
- " register unimplemented.\n");
- break;
- case MISCREG_APIC_ERROR_STATUS:
- panic("Local APIC Error Status register unimplemented.\n");
- 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:
- panic("Local APIC LVT Timer register unimplemented.\n");
- break;
- case MISCREG_APIC_LVT_THERMAL_SENSOR:
- panic("Local APIC LVT Thermal Sensor register unimplemented.\n");
- break;
- case MISCREG_APIC_LVT_PERFORMANCE_MONITORING_COUNTERS:
- panic("Local APIC LVT Performance Monitoring Counters"
- " register unimplemented.\n");
- break;
- case MISCREG_APIC_LVT_LINT0:
- panic("Local APIC LVT LINT0 register unimplemented.\n");
- break;
- case MISCREG_APIC_LVT_LINT1:
- panic("Local APIC LVT LINT1 register unimplemented.\n");
- break;
- case MISCREG_APIC_LVT_ERROR:
- panic("Local APIC LVT Error register unimplemented.\n");
- break;
- case MISCREG_APIC_INITIAL_COUNT:
- panic("Local APIC Initial Count register unimplemented.\n");
- break;
- case MISCREG_APIC_CURRENT_COUNT:
- panic("Local APIC Current Count register unimplemented.\n");
- break;
- case MISCREG_APIC_DIVIDE_COUNT:
- panic("Local APIC Divide Count register unimplemented.\n");
- break;
- }
+ 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
@@ -217,96 +140,10 @@ void MiscRegFile::setRegNoEffect(int miscReg, const MiscReg &val)
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:
- panic("Local APIC ID register unimplemented.\n");
- break;
- case MISCREG_APIC_VERSION:
- panic("Local APIC Version register is read only.\n");
- break;
- case MISCREG_APIC_TASK_PRIORITY:
- panic("Local APIC Task Priority register unimplemented.\n");
- 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:
- panic("Local APIC Logical Destination register unimplemented.\n");
- break;
- case MISCREG_APIC_DESTINATION_FORMAT:
- panic("Local APIC Destination Format register unimplemented.\n");
- break;
- case MISCREG_APIC_SPURIOUS_INTERRUPT_VECTOR:
- panic("Local APIC Spurious Interrupt Vector"
- " register unimplemented.\n");
- break;
- case MISCREG_APIC_ERROR_STATUS:
- panic("Local APIC Error Status register unimplemented.\n");
- 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:
- panic("Local APIC LVT Timer register unimplemented.\n");
- break;
- case MISCREG_APIC_LVT_THERMAL_SENSOR:
- panic("Local APIC LVT Thermal Sensor register unimplemented.\n");
- break;
- case MISCREG_APIC_LVT_PERFORMANCE_MONITORING_COUNTERS:
- panic("Local APIC LVT Performance Monitoring Counters"
- " register unimplemented.\n");
- break;
- case MISCREG_APIC_LVT_LINT0:
- panic("Local APIC LVT LINT0 register unimplemented.\n");
- break;
- case MISCREG_APIC_LVT_LINT1:
- panic("Local APIC LVT LINT1 register unimplemented.\n");
- break;
- case MISCREG_APIC_LVT_ERROR:
- panic("Local APIC LVT Error register unimplemented.\n");
- break;
- case MISCREG_APIC_INITIAL_COUNT:
- panic("Local APIC Initial Count register unimplemented.\n");
- break;
- case MISCREG_APIC_CURRENT_COUNT:
- panic("Local APIC Current Count register unimplemented.\n");
- break;
- case MISCREG_APIC_DIVIDE_COUNT:
- panic("Local APIC Divide Count register unimplemented.\n");
- break;
- }
- setRegNoEffect(miscReg, newVal);
- return;
- }
switch(miscReg)
{
case MISCREG_CR0:
@@ -314,17 +151,39 @@ void MiscRegFile::setReg(int miscReg,
CR0 toggled = regVal[miscReg] ^ val;
CR0 newCR0 = val;
Efer efer = regVal[MISCREG_EFER];
+ HandyM5Reg m5reg = regVal[MISCREG_M5_REG];
if (toggled.pg && efer.lme) {
if (newCR0.pg) {
//Turning on long mode
efer.lma = 1;
+ m5reg.mode = LongMode;
regVal[MISCREG_EFER] = efer;
} else {
//Turning off long mode
efer.lma = 0;
+ m5reg.mode = LegacyMode;
regVal[MISCREG_EFER] = efer;
}
}
+ // Figure out what submode we're in.
+ if (m5reg.mode == LongMode) {
+ SegAttr csAttr = regVal[MISCREG_CS_ATTR];
+ if (csAttr.longMode)
+ m5reg.submode = SixtyFourBitMode;
+ else
+ m5reg.submode = CompatabilityMode;
+ } else {
+ if (newCR0.pe) {
+ RFLAGS rflags = regVal[MISCREG_RFLAGS];
+ if (rflags.vm)
+ m5reg.submode = Virtual8086Mode;
+ else
+ m5reg.submode = ProtectedMode;
+ } else {
+ m5reg.submode = RealMode;
+ }
+ }
+ regVal[MISCREG_M5_REG] = m5reg;
if (toggled.pg) {
tc->getITBPtr()->invalidateAll();
tc->getDTBPtr()->invalidateAll();
@@ -355,20 +214,26 @@ void MiscRegFile::setReg(int miscReg,
{
SegAttr toggled = regVal[miscReg] ^ val;
SegAttr newCSAttr = val;
+ HandyM5Reg m5reg = regVal[MISCREG_M5_REG];
if (toggled.longMode) {
- SegAttr newCSAttr = val;
if (newCSAttr.longMode) {
+ if (m5reg.mode == LongMode)
+ m5reg.submode = SixtyFourBitMode;
regVal[MISCREG_ES_EFF_BASE] = 0;
regVal[MISCREG_CS_EFF_BASE] = 0;
regVal[MISCREG_SS_EFF_BASE] = 0;
regVal[MISCREG_DS_EFF_BASE] = 0;
} else {
+ if (m5reg.mode == LongMode)
+ m5reg.submode = CompatabilityMode;
regVal[MISCREG_ES_EFF_BASE] = regVal[MISCREG_ES_BASE];
regVal[MISCREG_CS_EFF_BASE] = regVal[MISCREG_CS_BASE];
regVal[MISCREG_SS_EFF_BASE] = regVal[MISCREG_SS_BASE];
regVal[MISCREG_DS_EFF_BASE] = regVal[MISCREG_DS_BASE];
}
}
+ m5reg.cpl = newCSAttr.dpl;
+ regVal[MISCREG_M5_REG] = m5reg;
}
break;
// These segments always actually use their bases, or in other words
@@ -396,6 +261,80 @@ void MiscRegFile::setReg(int miscReg,
MISCREG_SEG_BASE_BASE)] = val;
}
break;
+ case MISCREG_TSC:
+ regVal[MISCREG_TSC] = val - tc->getCpuPtr()->curCycle();
+ return;
+ case MISCREG_DR0:
+ case MISCREG_DR1:
+ case MISCREG_DR2:
+ case MISCREG_DR3:
+ /* These should eventually set up breakpoints. */
+ break;
+ case MISCREG_DR4:
+ miscReg = MISCREG_DR6;
+ /* Fall through to have the same effects as DR6. */
+ case MISCREG_DR6:
+ {
+ DR6 dr6 = regVal[MISCREG_DR6];
+ DR6 newDR6 = val;
+ dr6.b0 = newDR6.b0;
+ dr6.b1 = newDR6.b1;
+ dr6.b2 = newDR6.b2;
+ dr6.b3 = newDR6.b3;
+ dr6.bd = newDR6.bd;
+ dr6.bs = newDR6.bs;
+ dr6.bt = newDR6.bt;
+ newVal = dr6;
+ }
+ break;
+ case MISCREG_DR5:
+ miscReg = MISCREG_DR7;
+ /* Fall through to have the same effects as DR7. */
+ case MISCREG_DR7:
+ {
+ DR7 dr7 = regVal[MISCREG_DR7];
+ DR7 newDR7 = val;
+ dr7.l0 = newDR7.l0;
+ dr7.g0 = newDR7.g0;
+ if (dr7.l0 || dr7.g0) {
+ panic("Debug register breakpoints not implemented.\n");
+ } else {
+ /* Disable breakpoint 0. */
+ }
+ dr7.l1 = newDR7.l1;
+ dr7.g1 = newDR7.g1;
+ if (dr7.l1 || dr7.g1) {
+ panic("Debug register breakpoints not implemented.\n");
+ } else {
+ /* Disable breakpoint 1. */
+ }
+ dr7.l2 = newDR7.l2;
+ dr7.g2 = newDR7.g2;
+ if (dr7.l2 || dr7.g2) {
+ panic("Debug register breakpoints not implemented.\n");
+ } else {
+ /* Disable breakpoint 2. */
+ }
+ dr7.l3 = newDR7.l3;
+ dr7.g3 = newDR7.g3;
+ if (dr7.l3 || dr7.g3) {
+ panic("Debug register breakpoints not implemented.\n");
+ } else {
+ /* Disable breakpoint 3. */
+ }
+ dr7.gd = newDR7.gd;
+ dr7.rw0 = newDR7.rw0;
+ dr7.len0 = newDR7.len0;
+ dr7.rw1 = newDR7.rw1;
+ dr7.len1 = newDR7.len1;
+ dr7.rw2 = newDR7.rw2;
+ dr7.len2 = newDR7.len2;
+ dr7.rw3 = newDR7.rw3;
+ dr7.len3 = newDR7.len3;
+ }
+ break;
+ default:
+ break;
}
setRegNoEffect(miscReg, newVal);
}
diff --git a/src/arch/x86/miscregfile.hh b/src/arch/x86/miscregfile.hh
index e095e06e9..6d3ae4e92 100644
--- a/src/arch/x86/miscregfile.hh
+++ b/src/arch/x86/miscregfile.hh
@@ -29,7 +29,7 @@
*/
/*
- * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms,
@@ -91,6 +91,7 @@
#include "arch/x86/faults.hh"
#include "arch/x86/miscregs.hh"
#include "arch/x86/types.hh"
+#include "sim/host.hh"
#include <string>
@@ -98,8 +99,6 @@ class Checkpoint;
namespace X86ISA
{
- std::string getMiscRegName(RegIndex);
-
//These will have to be updated in the future.
const int NumMiscArchRegs = NUM_MISCREGS;
const int NumMiscRegs = NUM_MISCREGS;
@@ -117,13 +116,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);
diff --git a/src/arch/x86/miscregs.hh b/src/arch/x86/miscregs.hh
index d1016d2a9..af02e9422 100644
--- a/src/arch/x86/miscregs.hh
+++ b/src/arch/x86/miscregs.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms,
@@ -82,6 +82,18 @@ namespace X86ISA
OFBit = 1 << 11
};
+ enum RFLAGBit {
+ TFBit = 1 << 8,
+ IFBit = 1 << 9,
+ NTBit = 1 << 14,
+ RFBit = 1 << 16,
+ VMBit = 1 << 17,
+ ACBit = 1 << 18,
+ VIFBit = 1 << 19,
+ VIPBit = 1 << 20,
+ IDBit = 1 << 21
+ };
+
enum MiscRegIndex
{
// Control registers
@@ -118,6 +130,9 @@ namespace X86ISA
// Flags register
MISCREG_RFLAGS = MISCREG_DR_BASE + NumDRegs,
+ //Register to keep handy values like the CPU mode in.
+ MISCREG_M5_REG,
+
/*
* Model Specific Registers
*/
@@ -183,6 +198,9 @@ namespace X86ISA
MISCREG_MC2_CTL,
MISCREG_MC3_CTL,
MISCREG_MC4_CTL,
+ MISCREG_MC5_CTL,
+ MISCREG_MC6_CTL,
+ MISCREG_MC7_CTL,
MISCREG_MC_STATUS_BASE,
MISCREG_MC0_STATUS = MISCREG_MC_STATUS_BASE,
@@ -190,6 +208,9 @@ namespace X86ISA
MISCREG_MC2_STATUS,
MISCREG_MC3_STATUS,
MISCREG_MC4_STATUS,
+ MISCREG_MC5_STATUS,
+ MISCREG_MC6_STATUS,
+ MISCREG_MC7_STATUS,
MISCREG_MC_ADDR_BASE,
MISCREG_MC0_ADDR = MISCREG_MC_ADDR_BASE,
@@ -197,6 +218,9 @@ namespace X86ISA
MISCREG_MC2_ADDR,
MISCREG_MC3_ADDR,
MISCREG_MC4_ADDR,
+ MISCREG_MC5_ADDR,
+ MISCREG_MC6_ADDR,
+ MISCREG_MC7_ADDR,
MISCREG_MC_MISC_BASE,
MISCREG_MC0_MISC = MISCREG_MC_MISC_BASE,
@@ -204,6 +228,9 @@ namespace X86ISA
MISCREG_MC2_MISC,
MISCREG_MC3_MISC,
MISCREG_MC4_MISC,
+ MISCREG_MC5_MISC,
+ MISCREG_MC6_MISC,
+ MISCREG_MC7_MISC,
// Extended feature enable register
MISCREG_EFER,
@@ -341,38 +368,6 @@ namespace X86ISA
MISCREG_APIC_BASE,
- 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_COUNT,
- MISCREG_APIC_END = MISCREG_APIC_DIVIDE_COUNT,
-
// "Fake" MSRs for internally implemented devices
MISCREG_PCI_CONFIG_ADDRESS,
@@ -481,24 +476,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.
@@ -537,6 +514,12 @@ namespace X86ISA
Bitfield<0> cf; // Carry Flag
EndBitUnion(RFLAGS)
+ BitUnion64(HandyM5Reg)
+ Bitfield<0> mode;
+ Bitfield<3, 1> submode;
+ Bitfield<5, 4> cpl;
+ EndBitUnion(HandyM5Reg)
+
/**
* Control registers
*/
@@ -589,6 +572,38 @@ namespace X86ISA
Bitfield<3, 0> tpr; // Task Priority Register
EndBitUnion(CR8)
+ BitUnion64(DR6)
+ Bitfield<0> b0;
+ Bitfield<1> b1;
+ Bitfield<2> b2;
+ Bitfield<3> b3;
+ Bitfield<13> bd;
+ Bitfield<14> bs;
+ Bitfield<15> bt;
+ EndBitUnion(DR6)
+
+ BitUnion64(DR7)
+ Bitfield<0> l0;
+ Bitfield<1> g0;
+ Bitfield<2> l1;
+ Bitfield<3> g1;
+ Bitfield<4> l2;
+ Bitfield<5> g2;
+ Bitfield<6> l3;
+ Bitfield<7> g3;
+ Bitfield<8> le;
+ Bitfield<9> ge;
+ Bitfield<13> gd;
+ Bitfield<17, 16> rw0;
+ Bitfield<19, 18> len0;
+ Bitfield<21, 20> rw1;
+ Bitfield<23, 22> len1;
+ Bitfield<25, 24> rw2;
+ Bitfield<27, 26> len2;
+ Bitfield<29, 28> rw3;
+ Bitfield<31, 30> len3;
+ EndBitUnion(DR7)
+
// MTRR capabilities
BitUnion64(MTRRcap)
Bitfield<7, 0> vcnt; // Variable-Range Register Count
diff --git a/src/arch/x86/mmaped_ipr.hh b/src/arch/x86/mmaped_ipr.hh
index eda85c084..7056c0902 100644
--- a/src/arch/x86/mmaped_ipr.hh
+++ b/src/arch/x86/mmaped_ipr.hh
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms,
@@ -78,15 +78,12 @@ namespace X86ISA
#if !FULL_SYSTEM
panic("Shouldn't have a memory mapped register in SE\n");
#else
+ Addr offset = pkt->getAddr() & mask(3);
MiscRegIndex index = (MiscRegIndex)(pkt->getAddr() / sizeof(MiscReg));
- if (index == MISCREG_PCI_CONFIG_ADDRESS ||
- (index >= MISCREG_APIC_START &&
- index <= MISCREG_APIC_END)) {
- pkt->set((uint32_t)(xc->readMiscReg(pkt->getAddr() /
- sizeof(MiscReg))));
- } else {
- pkt->set(xc->readMiscReg(pkt->getAddr() / sizeof(MiscReg)));
- }
+ MiscReg data = htog(xc->readMiscReg(index));
+ // Make sure we don't trot off the end of data.
+ assert(offset + pkt->getSize() <= sizeof(MiscReg));
+ pkt->setData(((uint8_t *)&data) + offset);
#endif
return xc->getCpuPtr()->ticks(1);
}
@@ -97,15 +94,14 @@ namespace X86ISA
#if !FULL_SYSTEM
panic("Shouldn't have a memory mapped register in SE\n");
#else
+ Addr offset = pkt->getAddr() & mask(3);
MiscRegIndex index = (MiscRegIndex)(pkt->getAddr() / sizeof(MiscReg));
- if (index == MISCREG_PCI_CONFIG_ADDRESS ||
- (index >= MISCREG_APIC_START &&
- index <= MISCREG_APIC_END)) {
- xc->setMiscReg(index, gtoh(pkt->get<uint32_t>()));
- } else {
- xc->setMiscReg(pkt->getAddr() / sizeof(MiscReg),
- gtoh(pkt->get<uint64_t>()));
- }
+ MiscReg data;
+ 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);
+ xc->setMiscReg(index, gtoh(data));
#endif
return xc->getCpuPtr()->ticks(1);
}
diff --git a/src/arch/x86/pagetable.hh b/src/arch/x86/pagetable.hh
index e42693c03..1a7a945e4 100644
--- a/src/arch/x86/pagetable.hh
+++ b/src/arch/x86/pagetable.hh
@@ -113,6 +113,12 @@ namespace X86ISA
TlbEntry(Addr asn, Addr _vaddr, Addr _paddr);
TlbEntry() {}
+ void
+ updateVaddr(Addr new_vaddr)
+ {
+ vaddr = new_vaddr;
+ }
+
Addr pageStart()
{
return paddr;
diff --git a/src/arch/x86/pagetable_walker.cc b/src/arch/x86/pagetable_walker.cc
index e70c16b1d..f625cf4bd 100644
--- a/src/arch/x86/pagetable_walker.cc
+++ b/src/arch/x86/pagetable_walker.cc
@@ -84,8 +84,8 @@ BitUnion64(PageTableEntry)
Bitfield<0> p;
EndBitUnion(PageTableEntry)
-void
-Walker::doNext(PacketPtr &read, PacketPtr &write)
+Fault
+Walker::doNext(PacketPtr &write)
{
assert(state != Ready && state != Waiting);
write = NULL;
@@ -101,39 +101,45 @@ Walker::doNext(PacketPtr &read, PacketPtr &write)
bool badNX = pte.nx && (!tlb->allowNX() || !enableNX);
switch(state) {
case LongPML4:
+ DPRINTF(PageTableWalker,
+ "Got long mode PML4 entry %#016x.\n", (uint64_t)pte);
nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl3 * size;
doWrite = !pte.a;
pte.a = 1;
entry.writable = pte.w;
entry.user = pte.u;
- if (badNX)
- panic("NX violation!\n");
+ if (badNX || !pte.p) {
+ stop();
+ return pageFault(pte.p);
+ }
entry.noExec = pte.nx;
- if (!pte.p)
- panic("Page at %#x not present!\n", entry.vaddr);
nextState = LongPDP;
break;
case LongPDP:
+ DPRINTF(PageTableWalker,
+ "Got long mode PDP entry %#016x.\n", (uint64_t)pte);
nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.longl2 * size;
doWrite = !pte.a;
pte.a = 1;
entry.writable = entry.writable && pte.w;
entry.user = entry.user && pte.u;
- if (badNX)
- panic("NX violation!\n");
- if (!pte.p)
- panic("Page at %#x not present!\n", entry.vaddr);
+ if (badNX || !pte.p) {
+ stop();
+ return pageFault(pte.p);
+ }
nextState = LongPD;
break;
case LongPD:
+ DPRINTF(PageTableWalker,
+ "Got long mode PD entry %#016x.\n", (uint64_t)pte);
doWrite = !pte.a;
pte.a = 1;
entry.writable = entry.writable && pte.w;
entry.user = entry.user && pte.u;
- if (badNX)
- panic("NX violation!\n");
- if (!pte.p)
- panic("Page at %#x not present!\n", entry.vaddr);
+ if (badNX || !pte.p) {
+ stop();
+ return pageFault(pte.p);
+ }
if (!pte.ps) {
// 4 KB page
entry.size = 4 * (1 << 10);
@@ -150,47 +156,49 @@ Walker::doNext(PacketPtr &read, PacketPtr &write)
entry.patBit = bits(pte, 12);
entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1);
tlb->insert(entry.vaddr, entry);
- nextState = Ready;
- delete read->req;
- delete read;
- read = NULL;
- return;
+ stop();
+ return NoFault;
}
case LongPTE:
+ DPRINTF(PageTableWalker,
+ "Got long mode PTE entry %#016x.\n", (uint64_t)pte);
doWrite = !pte.a;
pte.a = 1;
entry.writable = entry.writable && pte.w;
entry.user = entry.user && pte.u;
- if (badNX)
- panic("NX violation!\n");
- if (!pte.p)
- panic("Page at %#x not present!\n", entry.vaddr);
+ if (badNX || !pte.p) {
+ stop();
+ return pageFault(pte.p);
+ }
entry.paddr = (uint64_t)pte & (mask(40) << 12);
entry.uncacheable = uncacheable;
entry.global = pte.g;
entry.patBit = bits(pte, 12);
entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
tlb->insert(entry.vaddr, entry);
- nextState = Ready;
- delete read->req;
- delete read;
- read = NULL;
- return;
+ stop();
+ return NoFault;
case PAEPDP:
+ DPRINTF(PageTableWalker,
+ "Got legacy mode PAE PDP entry %#08x.\n", (uint32_t)pte);
nextRead = ((uint64_t)pte & (mask(40) << 12)) + vaddr.pael2 * size;
- if (!pte.p)
- panic("Page at %#x not present!\n", entry.vaddr);
+ if (!pte.p) {
+ stop();
+ return pageFault(pte.p);
+ }
nextState = PAEPD;
break;
case PAEPD:
+ DPRINTF(PageTableWalker,
+ "Got legacy mode PAE PD entry %#08x.\n", (uint32_t)pte);
doWrite = !pte.a;
pte.a = 1;
entry.writable = pte.w;
entry.user = pte.u;
- if (badNX)
- panic("NX violation!\n");
- if (!pte.p)
- panic("Page at %#x not present!\n", entry.vaddr);
+ if (badNX || !pte.p) {
+ stop();
+ return pageFault(pte.p);
+ }
if (!pte.ps) {
// 4 KB page
entry.size = 4 * (1 << 10);
@@ -206,39 +214,39 @@ Walker::doNext(PacketPtr &read, PacketPtr &write)
entry.patBit = bits(pte, 12);
entry.vaddr = entry.vaddr & ~((2 * (1 << 20)) - 1);
tlb->insert(entry.vaddr, entry);
- nextState = Ready;
- delete read->req;
- delete read;
- read = NULL;
- return;
+ stop();
+ return NoFault;
}
case PAEPTE:
+ DPRINTF(PageTableWalker,
+ "Got legacy mode PAE PTE entry %#08x.\n", (uint32_t)pte);
doWrite = !pte.a;
pte.a = 1;
entry.writable = entry.writable && pte.w;
entry.user = entry.user && pte.u;
- if (badNX)
- panic("NX violation!\n");
- if (!pte.p)
- panic("Page at %#x not present!\n", entry.vaddr);
+ if (badNX || !pte.p) {
+ stop();
+ return pageFault(pte.p);
+ }
entry.paddr = (uint64_t)pte & (mask(40) << 12);
entry.uncacheable = uncacheable;
entry.global = pte.g;
entry.patBit = bits(pte, 7);
entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
tlb->insert(entry.vaddr, entry);
- nextState = Ready;
- delete read->req;
- delete read;
- read = NULL;
- return;
+ stop();
+ return NoFault;
case PSEPD:
+ DPRINTF(PageTableWalker,
+ "Got legacy mode PSE PD entry %#08x.\n", (uint32_t)pte);
doWrite = !pte.a;
pte.a = 1;
entry.writable = pte.w;
entry.user = pte.u;
- if (!pte.p)
- panic("Page at %#x not present!\n", entry.vaddr);
+ if (!pte.p) {
+ stop();
+ return pageFault(pte.p);
+ }
if (!pte.ps) {
// 4 KB page
entry.size = 4 * (1 << 10);
@@ -255,54 +263,51 @@ Walker::doNext(PacketPtr &read, PacketPtr &write)
entry.patBit = bits(pte, 12);
entry.vaddr = entry.vaddr & ~((4 * (1 << 20)) - 1);
tlb->insert(entry.vaddr, entry);
- nextState = Ready;
- delete read->req;
- delete read;
- read = NULL;
- return;
+ stop();
+ return NoFault;
}
case PD:
+ DPRINTF(PageTableWalker,
+ "Got legacy mode PD entry %#08x.\n", (uint32_t)pte);
doWrite = !pte.a;
pte.a = 1;
entry.writable = pte.w;
entry.user = pte.u;
- if (!pte.p)
- panic("Page at %#x not present!\n", entry.vaddr);
+ if (!pte.p) {
+ stop();
+ return pageFault(pte.p);
+ }
// 4 KB page
entry.size = 4 * (1 << 10);
nextRead = ((uint64_t)pte & (mask(20) << 12)) + vaddr.norml2 * size;
nextState = PTE;
break;
- nextState = PTE;
- break;
case PTE:
+ DPRINTF(PageTableWalker,
+ "Got legacy mode PTE entry %#08x.\n", (uint32_t)pte);
doWrite = !pte.a;
pte.a = 1;
entry.writable = pte.w;
entry.user = pte.u;
- if (!pte.p)
- panic("Page at %#x not present!\n", entry.vaddr);
+ if (!pte.p) {
+ stop();
+ return pageFault(pte.p);
+ }
entry.paddr = (uint64_t)pte & (mask(20) << 12);
entry.uncacheable = uncacheable;
entry.global = pte.g;
entry.patBit = bits(pte, 7);
entry.vaddr = entry.vaddr & ~((4 * (1 << 10)) - 1);
tlb->insert(entry.vaddr, entry);
- nextState = Ready;
- delete read->req;
- delete read;
- read = NULL;
- return;
+ stop();
+ return NoFault;
default:
panic("Unknown page table walker state %d!\n");
}
PacketPtr oldRead = read;
//If we didn't return, we're setting up another read.
- uint32_t flags = oldRead->req->getFlags();
- if (uncacheable)
- flags |= UNCACHEABLE;
- else
- flags &= ~UNCACHEABLE;
+ Request::Flags flags = oldRead->req->getFlags();
+ flags.set(Request::UNCACHEABLE, uncacheable);
RequestPtr request =
new Request(nextRead, oldRead->getSize(), flags);
read = new Packet(request, MemCmd::ReadExReq, Packet::Broadcast);
@@ -319,14 +324,20 @@ Walker::doNext(PacketPtr &read, PacketPtr &write)
delete oldRead->req;
delete oldRead;
}
+ return NoFault;
}
-void
-Walker::start(ThreadContext * _tc, Addr vaddr)
+Fault
+Walker::start(ThreadContext * _tc, BaseTLB::Translation *_translation,
+ RequestPtr _req, bool _write, bool _execute)
{
assert(state == Ready);
- assert(!tc);
tc = _tc;
+ req = _req;
+ Addr vaddr = req->getVaddr();
+ execute = _execute;
+ write = _write;
+ translation = _translation;
VAddr addr = vaddr;
@@ -340,6 +351,7 @@ Walker::start(ThreadContext * _tc, Addr vaddr)
// Do long mode.
state = LongPML4;
top = (cr3.longPdtb << 12) + addr.longl4 * size;
+ enableNX = efer.nxe;
} else {
// We're in some flavor of legacy mode.
CR4 cr4 = tc->readMiscRegNoEffect(MISCREG_CR4);
@@ -347,6 +359,7 @@ Walker::start(ThreadContext * _tc, Addr vaddr)
// Do legacy PAE.
state = PAEPDP;
top = (cr3.paePdtb << 5) + addr.pael3 * size;
+ enableNX = efer.nxe;
} else {
size = 4;
top = (cr3.pdtb << 12) + addr.norml2 * size;
@@ -357,38 +370,44 @@ Walker::start(ThreadContext * _tc, Addr vaddr)
// Do legacy non PSE.
state = PD;
}
+ enableNX = false;
}
}
nextState = Ready;
entry.vaddr = vaddr;
- enableNX = efer.nxe;
-
- RequestPtr request =
- new Request(top, size, PHYSICAL | cr3.pcd ? UNCACHEABLE : 0);
+ Request::Flags flags = Request::PHYSICAL;
+ if (cr3.pcd)
+ flags.set(Request::UNCACHEABLE);
+ RequestPtr request = new Request(top, size, flags);
read = new Packet(request, MemCmd::ReadExReq, Packet::Broadcast);
read->allocate();
Enums::MemoryMode memMode = sys->getMemoryMode();
if (memMode == Enums::timing) {
- tc->suspend();
- port.sendTiming(read);
+ nextState = state;
+ state = Waiting;
+ timingFault = NoFault;
+ sendPackets();
} else if (memMode == Enums::atomic) {
+ Fault fault;
do {
port.sendAtomic(read);
PacketPtr write = NULL;
- doNext(read, write);
+ fault = doNext(write);
+ assert(fault == NoFault || read == NULL);
state = nextState;
nextState = Ready;
if (write)
port.sendAtomic(write);
} while(read);
- tc = NULL;
state = Ready;
nextState = Waiting;
+ return fault;
} else {
panic("Unrecognized memory system mode.\n");
}
+ return NoFault;
}
bool
@@ -400,18 +419,19 @@ Walker::WalkerPort::recvTiming(PacketPtr pkt)
bool
Walker::recvTiming(PacketPtr pkt)
{
- inflight--;
if (pkt->isResponse() && !pkt->wasNacked()) {
+ assert(inflight);
+ assert(state == Waiting);
+ assert(!read);
+ inflight--;
if (pkt->isRead()) {
- assert(inflight);
- assert(state == Waiting);
- assert(!read);
state = nextState;
nextState = Ready;
PacketPtr write = NULL;
- doNext(pkt, write);
- state = Waiting;
read = pkt;
+ timingFault = doNext(write);
+ state = Waiting;
+ assert(timingFault == NoFault || read == NULL);
if (write) {
writes.push_back(write);
}
@@ -420,14 +440,31 @@ Walker::recvTiming(PacketPtr pkt)
sendPackets();
}
if (inflight == 0 && read == NULL && writes.size() == 0) {
- tc->activate(0);
- tc = NULL;
state = Ready;
nextState = Waiting;
+ if (timingFault == NoFault) {
+ /*
+ * Finish the translation. Now that we now the right entry is
+ * in the TLB, this should work with no memory accesses.
+ * There could be new faults unrelated to the table walk like
+ * permissions violations, so we'll need the return value as
+ * well.
+ */
+ bool delayedResponse;
+ Fault fault = tlb->translate(req, tc, NULL, write, execute,
+ delayedResponse, true);
+ assert(!delayedResponse);
+ // Let the CPU continue.
+ translation->finish(fault, req, tc, write);
+ } else {
+ // There was a fault during the walk. Let the CPU know.
+ translation->finish(timingFault, req, tc, write);
+ }
}
} else if (pkt->wasNacked()) {
pkt->reinitNacked();
if (!port.sendTiming(pkt)) {
+ inflight--;
retrying = true;
if (pkt->isWrite()) {
writes.push_back(pkt);
@@ -435,8 +472,6 @@ Walker::recvTiming(PacketPtr pkt)
assert(!read);
read = pkt;
}
- } else {
- inflight++;
}
}
return true;
@@ -490,27 +525,26 @@ Walker::sendPackets()
//Reads always have priority
if (read) {
- if (!port.sendTiming(read)) {
+ PacketPtr pkt = read;
+ read = NULL;
+ inflight++;
+ if (!port.sendTiming(pkt)) {
retrying = true;
+ read = pkt;
+ inflight--;
return;
- } else {
- inflight++;
- delete read->req;
- delete read;
- read = NULL;
}
}
//Send off as many of the writes as we can.
while (writes.size()) {
PacketPtr write = writes.back();
+ writes.pop_back();
+ inflight++;
if (!port.sendTiming(write)) {
retrying = true;
+ writes.push_back(write);
+ inflight--;
return;
- } else {
- inflight++;
- delete write->req;
- delete write;
- writes.pop_back();
}
}
}
@@ -524,6 +558,15 @@ Walker::getPort(const std::string &if_name, int idx)
panic("No page table walker port named %s!\n", if_name);
}
+Fault
+Walker::pageFault(bool present)
+{
+ DPRINTF(PageTableWalker, "Raising page fault.\n");
+ HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
+ return new PageFault(entry.vaddr, present, write,
+ m5reg.cpl == 3, false, execute && enableNX);
+}
+
}
X86ISA::Walker *
diff --git a/src/arch/x86/pagetable_walker.hh b/src/arch/x86/pagetable_walker.hh
index 324f16f3c..f73774a45 100644
--- a/src/arch/x86/pagetable_walker.hh
+++ b/src/arch/x86/pagetable_walker.hh
@@ -85,17 +85,28 @@ namespace X86ISA
PSEPD, PD, PTE
};
- // Act on the current state and determine what to do next. read
- // should be the packet that just came back from a read and write
+ // Act on the current state and determine what to do next. The global
+ // read should be the packet that just came back from a read and write
// should be NULL. When the function returns, read is either NULL
// if the machine is finished, or points to a packet to initiate
// the next read. If any write is required to update an "accessed"
// bit, write will point to a packet to do the write. Otherwise it
- // will be NULL.
- void doNext(PacketPtr &read, PacketPtr &write);
+ // will be NULL. The return value is whatever fault was incurred
+ // during this stage of the lookup.
+ Fault doNext(PacketPtr &write);
// Kick off the state machine.
- void start(ThreadContext * _tc, Addr vaddr);
+ Fault start(ThreadContext * _tc, BaseTLB::Translation *translation,
+ RequestPtr req, bool write, bool execute);
+ // Clean up after the state machine.
+ void
+ stop()
+ {
+ nextState = Ready;
+ delete read->req;
+ delete read;
+ read = NULL;
+ }
protected:
@@ -111,6 +122,11 @@ namespace X86ISA
bool retrying;
/*
+ * The fault, if any, that's waiting to be delivered in timing mode.
+ */
+ Fault timingFault;
+
+ /*
* Functions for dealing with packets.
*/
bool recvTiming(PacketPtr pkt);
@@ -156,16 +172,21 @@ namespace X86ISA
// The TLB we're supposed to load.
TLB * tlb;
System * sys;
+ BaseTLB::Translation * translation;
/*
* State machine state.
*/
ThreadContext * tc;
+ RequestPtr req;
State state;
State nextState;
int size;
bool enableNX;
+ bool write, execute, user;
TlbEntry entry;
+
+ Fault pageFault(bool present);
public:
diff --git a/src/arch/x86/predecoder.cc b/src/arch/x86/predecoder.cc
index 407a09ec0..620ab89ea 100644
--- a/src/arch/x86/predecoder.cc
+++ b/src/arch/x86/predecoder.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms,
@@ -55,9 +55,11 @@
* Authors: Gabe Black
*/
+#include "arch/x86/miscregs.hh"
#include "arch/x86/predecoder.hh"
#include "base/misc.hh"
#include "base/trace.hh"
+#include "cpu/thread_context.hh"
#include "sim/host.hh"
namespace X86ISA
@@ -78,7 +80,9 @@ namespace X86ISA
emi.modRM = 0;
emi.sib = 0;
- emi.mode = 0;
+ HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
+ emi.mode.mode = m5reg.mode;
+ emi.mode.submode = m5reg.submode;
}
void Predecoder::process()
@@ -132,7 +136,10 @@ namespace X86ISA
{
uint8_t prefix = Prefixes[nextByte];
State nextState = PrefixState;
- if(prefix)
+ // REX prefixes are only recognized in 64 bit mode.
+ if (prefix == RexPrefix && emi.mode.submode != SixtyFourBitMode)
+ prefix = 0;
+ if (prefix)
consumeByte();
switch(prefix)
{
@@ -209,10 +216,12 @@ namespace X86ISA
DPRINTF(Predecoder, "Found opcode %#x.\n", nextByte);
emi.opcode.op = nextByte;
+ SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
+
//Figure out the effective operand size. This can be overriden to
//a fixed value at the decoder level.
int logOpSize;
- if(/*FIXME long mode*/1)
+ if (emi.mode.submode == SixtyFourBitMode)
{
if(emi.rex.w)
logOpSize = 3; // 64 bit operand size
@@ -221,7 +230,7 @@ namespace X86ISA
else
logOpSize = 2; // 32 bit operand size
}
- else if(/*FIXME default 32*/1)
+ else if(csAttr.defaultSize)
{
if(emi.legacy.op)
logOpSize = 1; // 16 bit operand size
@@ -242,14 +251,14 @@ namespace X86ISA
//Figure out the effective address size. This can be overriden to
//a fixed value at the decoder level.
int logAddrSize;
- if(/*FIXME 64-bit mode*/1)
+ if(emi.mode.submode == SixtyFourBitMode)
{
if(emi.legacy.addr)
logAddrSize = 2; // 32 bit address size
else
logAddrSize = 3; // 64 bit address size
}
- else if(/*FIXME default 32*/1)
+ else if(csAttr.defaultSize)
{
if(emi.legacy.addr)
logAddrSize = 1; // 16 bit address size
@@ -264,6 +273,16 @@ namespace X86ISA
logAddrSize = 1; // 16 bit address size
}
+ SegAttr ssAttr = tc->readMiscRegNoEffect(MISCREG_SS_ATTR);
+ //Figure out the effective stack width. This can be overriden to
+ //a fixed value at the decoder level.
+ if(emi.mode.submode == SixtyFourBitMode)
+ emi.stackSize = 8; // 64 bit stack width
+ else if(ssAttr.defaultSize)
+ emi.stackSize = 4; // 32 bit stack width
+ else
+ emi.stackSize = 2; // 16 bit stack width
+
//Set the actual address size
emi.addrSize = 1 << logAddrSize;
@@ -299,19 +318,21 @@ namespace X86ISA
ModRM modRM;
modRM = nextByte;
DPRINTF(Predecoder, "Found modrm byte %#x.\n", nextByte);
- if (0) {//FIXME in 16 bit mode
+ SegAttr csAttr = tc->readMiscRegNoEffect(MISCREG_CS_ATTR);
+ if (emi.mode.submode != SixtyFourBitMode &&
+ !csAttr.defaultSize) {
//figure out 16 bit displacement size
- if(modRM.mod == 0 && modRM.rm == 6 || modRM.mod == 2)
+ if ((modRM.mod == 0 && modRM.rm == 6) || modRM.mod == 2)
displacementSize = 2;
- else if(modRM.mod == 1)
+ else if (modRM.mod == 1)
displacementSize = 1;
else
displacementSize = 0;
} else {
//figure out 32/64 bit displacement size
- if(modRM.mod == 0 && modRM.rm == 5 || modRM.mod == 2)
+ if ((modRM.mod == 0 && modRM.rm == 5) || modRM.mod == 2)
displacementSize = 4;
- else if(modRM.mod == 1)
+ else if (modRM.mod == 1)
displacementSize = 1;
else
displacementSize = 0;
diff --git a/src/arch/x86/predecoder.hh b/src/arch/x86/predecoder.hh
index 6e41e8134..a16ce6fb8 100644
--- a/src/arch/x86/predecoder.hh
+++ b/src/arch/x86/predecoder.hh
@@ -58,6 +58,8 @@
#ifndef __ARCH_X86_PREDECODER_HH__
#define __ARCH_X86_PREDECODER_HH__
+#include <cassert>
+
#include "arch/x86/types.hh"
#include "base/bitfield.hh"
#include "base/misc.hh"
diff --git a/src/arch/x86/predecoder_tables.cc b/src/arch/x86/predecoder_tables.cc
index a8c719054..5f2b5c421 100644
--- a/src/arch/x86/predecoder_tables.cc
+++ b/src/arch/x86/predecoder_tables.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms,
@@ -123,7 +123,7 @@ namespace X86ISA
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
/* 0 */ 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1,
-/* 1 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
+/* 1 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 2 */ 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
/* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,
/* 4 */ 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1,
@@ -201,7 +201,7 @@ namespace X86ISA
//For two byte instructions
{ //LSB
// MSB 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F
-/* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+/* 0 */ 0 , 0 , 0 , 0 , WO, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , BY ,
/* 0 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 2 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
/* 3 */ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc
index 76f0b5d04..4a61ed168 100644
--- a/src/arch/x86/process.cc
+++ b/src/arch/x86/process.cc
@@ -98,56 +98,115 @@
#include "mem/page_table.hh"
#include "mem/translating_port.hh"
#include "sim/process_impl.hh"
+#include "sim/syscall_emul.hh"
#include "sim/system.hh"
using namespace std;
using namespace X86ISA;
-M5_64_auxv_t::M5_64_auxv_t(int64_t type, int64_t val)
-{
- a_type = TheISA::htog(type);
- a_val = TheISA::htog(val);
-}
-
-X86LiveProcess::X86LiveProcess(LiveProcessParams * params,
- ObjectFile *objFile)
- : LiveProcess(params, objFile)
+static const int ReturnValueReg = INTREG_RAX;
+static const int ArgumentReg[] = {
+ INTREG_RDI,
+ INTREG_RSI,
+ INTREG_RDX,
+ //This argument register is r10 for syscalls and rcx for C.
+ INTREG_R10W,
+ //INTREG_RCX,
+ INTREG_R8W,
+ INTREG_R9W
+};
+static const int NumArgumentRegs = sizeof(ArgumentReg) / sizeof(const int);
+static const int ArgumentReg32[] = {
+ INTREG_EBX,
+ INTREG_ECX,
+ INTREG_EDX,
+ INTREG_ESI,
+ INTREG_EDI,
+};
+static const int NumArgumentRegs32 = sizeof(ArgumentReg) / sizeof(const int);
+
+X86LiveProcess::X86LiveProcess(LiveProcessParams * params, ObjectFile *objFile,
+ SyscallDesc *_syscallDescs, int _numSyscallDescs) :
+ LiveProcess(params, objFile), syscallDescs(_syscallDescs),
+ numSyscallDescs(_numSyscallDescs)
{
brk_point = objFile->dataBase() + objFile->dataSize() + objFile->bssSize();
brk_point = roundUp(brk_point, VMPageSize);
+}
- // Set pointer for next thread stack. Reserve 8M for main stack.
- next_thread_stack_base = stack_base - (8 * 1024 * 1024);
-
+X86_64LiveProcess::X86_64LiveProcess(LiveProcessParams *params,
+ ObjectFile *objFile, SyscallDesc *_syscallDescs,
+ int _numSyscallDescs) :
+ X86LiveProcess(params, objFile, _syscallDescs, _numSyscallDescs)
+{
// Set up stack. On X86_64 Linux, stack goes from the top of memory
// downward, less the hole for the kernel address space plus one page
// for undertermined purposes.
stack_base = (Addr)0x7FFFFFFFF000ULL;
+ // Set pointer for next thread stack. Reserve 8M for main stack.
+ next_thread_stack_base = stack_base - (8 * 1024 * 1024);
+
// Set up region for mmaps. This was determined empirically and may not
// always be correct.
mmap_start = mmap_end = (Addr)0x2aaaaaaab000ULL;
}
-void X86LiveProcess::handleTrap(int trapNum, ThreadContext *tc)
+void
+I386LiveProcess::syscall(int64_t callnum, ThreadContext *tc)
{
- switch(trapNum)
- {
- default:
- panic("Unimplemented trap to operating system: trap number %#x.\n", trapNum);
+ Addr eip = tc->readPC();
+ if (eip >= vsyscallPage.base &&
+ eip < vsyscallPage.base + vsyscallPage.size) {
+ tc->setNextPC(vsyscallPage.base + vsyscallPage.vsysexitOffset);
}
+ X86LiveProcess::syscall(callnum, tc);
+}
+
+
+I386LiveProcess::I386LiveProcess(LiveProcessParams *params,
+ ObjectFile *objFile, SyscallDesc *_syscallDescs,
+ int _numSyscallDescs) :
+ X86LiveProcess(params, objFile, _syscallDescs, _numSyscallDescs)
+{
+ _gdtStart = 0x100000000;
+ _gdtSize = VMPageSize;
+
+ vsyscallPage.base = 0xffffe000ULL;
+ vsyscallPage.size = VMPageSize;
+ vsyscallPage.vsyscallOffset = 0x400;
+ vsyscallPage.vsysexitOffset = 0x410;
+
+ stack_base = vsyscallPage.base;
+
+ // Set pointer for next thread stack. Reserve 8M for main stack.
+ next_thread_stack_base = stack_base - (8 * 1024 * 1024);
+
+ // Set up region for mmaps. This was determined empirically and may not
+ // always be correct.
+ mmap_start = mmap_end = (Addr)0xf7ffd000ULL;
+}
+
+SyscallDesc*
+X86LiveProcess::getDesc(int callnum)
+{
+ if (callnum < 0 || callnum >= numSyscallDescs)
+ return NULL;
+ return &syscallDescs[callnum];
}
void
-X86LiveProcess::startup()
+X86_64LiveProcess::startup()
{
+ LiveProcess::startup();
+
if (checkpointRestored)
return;
- argsInit(sizeof(IntReg), VMPageSize);
+ argsInit(sizeof(uint64_t), VMPageSize);
- for (int i = 0; i < threadContexts.size(); i++) {
- ThreadContext * tc = threadContexts[i];
+ for (int i = 0; i < contextIds.size(); i++) {
+ ThreadContext * tc = system->getThreadContext(contextIds[i]);
SegAttr dataAttr = 0;
dataAttr.writable = 1;
@@ -203,10 +262,122 @@ X86LiveProcess::startup()
}
void
-X86LiveProcess::argsInit(int intSize, int pageSize)
+I386LiveProcess::startup()
+{
+ LiveProcess::startup();
+
+ if (checkpointRestored)
+ return;
+
+ argsInit(sizeof(uint32_t), VMPageSize);
+
+ /*
+ * Set up a GDT for this process. The whole GDT wouldn't really be for
+ * this process, but the only parts we care about are.
+ */
+ pTable->allocate(_gdtStart, _gdtSize);
+ uint64_t zero = 0;
+ assert(_gdtSize % sizeof(zero) == 0);
+ for (Addr gdtCurrent = _gdtStart;
+ gdtCurrent < _gdtStart + _gdtSize; gdtCurrent += sizeof(zero)) {
+ initVirtMem->write(gdtCurrent, zero);
+ }
+
+ // Set up the vsyscall page for this process.
+ pTable->allocate(vsyscallPage.base, vsyscallPage.size);
+ uint8_t vsyscallBlob[] = {
+ 0x51, // push %ecx
+ 0x52, // push %edp
+ 0x55, // push %ebp
+ 0x89, 0xe5, // mov %esp, %ebp
+ 0x0f, 0x34 // sysenter
+ };
+ initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vsyscallOffset,
+ vsyscallBlob, sizeof(vsyscallBlob));
+
+ uint8_t vsysexitBlob[] = {
+ 0x5d, // pop %ebp
+ 0x5a, // pop %edx
+ 0x59, // pop %ecx
+ 0xc3 // ret
+ };
+ initVirtMem->writeBlob(vsyscallPage.base + vsyscallPage.vsysexitOffset,
+ vsysexitBlob, sizeof(vsysexitBlob));
+
+ for (int i = 0; i < contextIds.size(); i++) {
+ ThreadContext * tc = system->getThreadContext(contextIds[i]);
+
+ SegAttr dataAttr = 0;
+ dataAttr.writable = 1;
+ dataAttr.readable = 1;
+ dataAttr.expandDown = 0;
+ dataAttr.dpl = 3;
+ dataAttr.defaultSize = 1;
+ dataAttr.longMode = 0;
+
+ //Initialize the segment registers.
+ for(int seg = 0; seg < NUM_SEGMENTREGS; seg++) {
+ tc->setMiscRegNoEffect(MISCREG_SEG_BASE(seg), 0);
+ tc->setMiscRegNoEffect(MISCREG_SEG_EFF_BASE(seg), 0);
+ tc->setMiscRegNoEffect(MISCREG_SEG_ATTR(seg), dataAttr);
+ tc->setMiscRegNoEffect(MISCREG_SEG_SEL(seg), 0xB);
+ tc->setMiscRegNoEffect(MISCREG_SEG_LIMIT(seg), (uint32_t)(-1));
+ }
+
+ SegAttr csAttr = 0;
+ csAttr.writable = 0;
+ csAttr.readable = 1;
+ csAttr.expandDown = 0;
+ csAttr.dpl = 3;
+ csAttr.defaultSize = 1;
+ csAttr.longMode = 0;
+
+ tc->setMiscRegNoEffect(MISCREG_CS_ATTR, csAttr);
+
+ tc->setMiscRegNoEffect(MISCREG_TSG_BASE, _gdtStart);
+ tc->setMiscRegNoEffect(MISCREG_TSG_EFF_BASE, _gdtStart);
+ tc->setMiscRegNoEffect(MISCREG_TSG_LIMIT, _gdtStart + _gdtSize - 1);
+
+ // Set the LDT selector to 0 to deactivate it.
+ tc->setMiscRegNoEffect(MISCREG_TSL, 0);
+
+ //Set up the registers that describe the operating mode.
+ CR0 cr0 = 0;
+ cr0.pg = 1; // Turn on paging.
+ cr0.cd = 0; // Don't disable caching.
+ cr0.nw = 0; // This is bit is defined to be ignored.
+ cr0.am = 0; // No alignment checking
+ cr0.wp = 0; // Supervisor mode can write read only pages
+ cr0.ne = 1;
+ cr0.et = 1; // This should always be 1
+ cr0.ts = 0; // We don't do task switching, so causing fp exceptions
+ // would be pointless.
+ cr0.em = 0; // Allow x87 instructions to execute natively.
+ cr0.mp = 1; // This doesn't really matter, but the manual suggests
+ // setting it to one.
+ cr0.pe = 1; // We're definitely in protected mode.
+ tc->setMiscReg(MISCREG_CR0, cr0);
+
+ Efer efer = 0;
+ efer.sce = 1; // Enable system call extensions.
+ efer.lme = 1; // Enable long mode.
+ efer.lma = 0; // Deactivate long mode.
+ efer.nxe = 1; // Enable nx support.
+ efer.svme = 0; // Disable svm support for now. It isn't implemented.
+ efer.ffxsr = 1; // Turn on fast fxsave and fxrstor.
+ tc->setMiscReg(MISCREG_EFER, efer);
+ }
+}
+
+template<class IntType>
+void
+X86LiveProcess::argsInit(int pageSize,
+ std::vector<AuxVector<IntType> > extraAuxvs)
{
- typedef M5_64_auxv_t auxv_t;
- Process::startup();
+ int intSize = sizeof(IntType);
+
+ typedef AuxVector<IntType> auxv_t;
+ std::vector<auxv_t> auxv = extraAuxvs;
string filename;
if(argv.size() < 1)
@@ -399,35 +570,35 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
roundUp(stack_size, pageSize));
// map out initial stack contents
- Addr sentry_base = stack_base - sentry_size;
- Addr file_name_base = sentry_base - file_name_size;
- Addr env_data_base = file_name_base - env_data_size;
- Addr arg_data_base = env_data_base - arg_data_size;
- Addr aux_data_base = arg_data_base - info_block_padding - aux_data_size;
- Addr auxv_array_base = aux_data_base - aux_array_size - aux_padding;
- Addr envp_array_base = auxv_array_base - envp_array_size;
- Addr argv_array_base = envp_array_base - argv_array_size;
- Addr argc_base = argv_array_base - argc_size;
-
- DPRINTF(X86, "The addresses of items on the initial stack:\n");
- DPRINTF(X86, "0x%x - file name\n", file_name_base);
- DPRINTF(X86, "0x%x - env data\n", env_data_base);
- DPRINTF(X86, "0x%x - arg data\n", arg_data_base);
- DPRINTF(X86, "0x%x - aux data\n", aux_data_base);
- DPRINTF(X86, "0x%x - auxv array\n", auxv_array_base);
- DPRINTF(X86, "0x%x - envp array\n", envp_array_base);
- DPRINTF(X86, "0x%x - argv array\n", argv_array_base);
- DPRINTF(X86, "0x%x - argc \n", argc_base);
- DPRINTF(X86, "0x%x - stack min\n", stack_min);
+ IntType sentry_base = stack_base - sentry_size;
+ IntType file_name_base = sentry_base - file_name_size;
+ IntType env_data_base = file_name_base - env_data_size;
+ IntType arg_data_base = env_data_base - arg_data_size;
+ IntType aux_data_base = arg_data_base - info_block_padding - aux_data_size;
+ IntType auxv_array_base = aux_data_base - aux_array_size - aux_padding;
+ IntType envp_array_base = auxv_array_base - envp_array_size;
+ IntType argv_array_base = envp_array_base - argv_array_size;
+ IntType argc_base = argv_array_base - argc_size;
+
+ DPRINTF(Stack, "The addresses of items on the initial stack:\n");
+ DPRINTF(Stack, "0x%x - file name\n", file_name_base);
+ DPRINTF(Stack, "0x%x - env data\n", env_data_base);
+ DPRINTF(Stack, "0x%x - arg data\n", arg_data_base);
+ DPRINTF(Stack, "0x%x - aux data\n", aux_data_base);
+ DPRINTF(Stack, "0x%x - auxv array\n", auxv_array_base);
+ DPRINTF(Stack, "0x%x - envp array\n", envp_array_base);
+ DPRINTF(Stack, "0x%x - argv array\n", argv_array_base);
+ DPRINTF(Stack, "0x%x - argc \n", argc_base);
+ DPRINTF(Stack, "0x%x - stack min\n", stack_min);
// write contents to stack
// figure out argc
- uint64_t argc = argv.size();
- uint64_t guestArgc = TheISA::htog(argc);
+ IntType argc = argv.size();
+ IntType guestArgc = X86ISA::htog(argc);
//Write out the sentry void *
- uint64_t sentry_NULL = 0;
+ IntType sentry_NULL = 0;
initVirtMem->writeBlob(sentry_base,
(uint8_t*)&sentry_NULL, sentry_size);
@@ -458,17 +629,70 @@ X86LiveProcess::argsInit(int intSize, int pageSize)
initVirtMem->writeBlob(argc_base, (uint8_t*)&guestArgc, intSize);
+ ThreadContext *tc = system->getThreadContext(contextIds[0]);
//Set the stack pointer register
- threadContexts[0]->setIntReg(StackPointerReg, stack_min);
+ tc->setIntReg(StackPointerReg, stack_min);
Addr prog_entry = objFile->entryPoint();
// There doesn't need to be any segment base added in since we're dealing
// with the flat segmentation model.
- threadContexts[0]->setPC(prog_entry);
- threadContexts[0]->setNextPC(prog_entry + sizeof(MachInst));
+ tc->setPC(prog_entry);
+ tc->setNextPC(prog_entry + sizeof(MachInst));
//Align the "stack_min" to a page boundary.
stack_min = roundDown(stack_min, pageSize);
// num_processes++;
}
+
+void
+X86_64LiveProcess::argsInit(int intSize, int pageSize)
+{
+ std::vector<AuxVector<uint64_t> > extraAuxvs;
+ X86LiveProcess::argsInit<uint64_t>(pageSize, extraAuxvs);
+}
+
+void
+I386LiveProcess::argsInit(int intSize, int pageSize)
+{
+ std::vector<AuxVector<uint32_t> > extraAuxvs;
+ //Tell the binary where the vsyscall part of the vsyscall page is.
+ extraAuxvs.push_back(AuxVector<uint32_t>(0x20,
+ vsyscallPage.base + vsyscallPage.vsyscallOffset));
+ extraAuxvs.push_back(AuxVector<uint32_t>(0x21, vsyscallPage.base));
+ X86LiveProcess::argsInit<uint32_t>(pageSize, extraAuxvs);
+}
+
+void
+X86LiveProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn return_value)
+{
+ tc->setIntReg(INTREG_RAX, return_value.value());
+}
+
+X86ISA::IntReg
+X86_64LiveProcess::getSyscallArg(ThreadContext *tc, int i)
+{
+ assert(i < NumArgumentRegs);
+ return tc->readIntReg(ArgumentReg[i]);
+}
+
+void
+X86_64LiveProcess::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val)
+{
+ assert(i < NumArgumentRegs);
+ return tc->setIntReg(ArgumentReg[i], val);
+}
+
+X86ISA::IntReg
+I386LiveProcess::getSyscallArg(ThreadContext *tc, int i)
+{
+ assert(i < NumArgumentRegs32);
+ return tc->readIntReg(ArgumentReg32[i]);
+}
+
+void
+I386LiveProcess::setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val)
+{
+ assert(i < NumArgumentRegs);
+ return tc->setIntReg(ArgumentReg[i], val);
+}
diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh
index 5def9e13d..cd6d99e66 100644
--- a/src/arch/x86/process.hh
+++ b/src/arch/x86/process.hh
@@ -62,38 +62,76 @@
#include <vector>
#include "sim/process.hh"
+class SyscallDesc;
+
namespace X86ISA
{
- struct M5_64_auxv_t
+
+ class X86LiveProcess : public LiveProcess
{
- int64_t a_type;
- union {
- int64_t a_val;
- int64_t a_ptr;
- int64_t a_fcn;
- };
+ protected:
+ Addr _gdtStart;
+ Addr _gdtSize;
+
+ SyscallDesc *syscallDescs;
+ const int numSyscallDescs;
- M5_64_auxv_t()
- {}
+ X86LiveProcess(LiveProcessParams * params, ObjectFile *objFile,
+ SyscallDesc *_syscallDescs, int _numSyscallDescs);
- M5_64_auxv_t(int64_t type, int64_t val);
+ template<class IntType>
+ void argsInit(int pageSize,
+ std::vector<AuxVector<IntType> > extraAuxvs);
+
+ public:
+ Addr gdtStart()
+ { return _gdtStart; }
+
+ Addr gdtSize()
+ { return _gdtSize; }
+
+ SyscallDesc* getDesc(int callnum);
+
+ void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value);
};
- class X86LiveProcess : public LiveProcess
+ class X86_64LiveProcess : public X86LiveProcess
{
protected:
- std::vector<M5_64_auxv_t> auxv;
-
- X86LiveProcess(LiveProcessParams * params, ObjectFile *objFile);
+ X86_64LiveProcess(LiveProcessParams *params, ObjectFile *objFile,
+ SyscallDesc *_syscallDescs, int _numSyscallDescs);
+ public:
+ void argsInit(int intSize, int pageSize);
void startup();
- public:
+ X86ISA::IntReg getSyscallArg(ThreadContext *tc, int i);
+ void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val);
+ };
- //Handles traps which request services from the operating system
- virtual void handleTrap(int trapNum, ThreadContext *tc);
+ class I386LiveProcess : public X86LiveProcess
+ {
+ protected:
+ I386LiveProcess(LiveProcessParams *params, ObjectFile *objFile,
+ SyscallDesc *_syscallDescs, int _numSyscallDescs);
+ class VSyscallPage
+ {
+ public:
+ Addr base;
+ Addr size;
+ Addr vsyscallOffset;
+ Addr vsysexitOffset;
+ };
+ VSyscallPage vsyscallPage;
+
+ public:
void argsInit(int intSize, int pageSize);
+ void startup();
+
+ void syscall(int64_t callnum, ThreadContext *tc);
+ X86ISA::IntReg getSyscallArg(ThreadContext *tc, int i);
+ void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val);
};
}
diff --git a/src/arch/x86/regfile.cc b/src/arch/x86/regfile.cc
index c27ab08ba..7d01c4bb4 100644
--- a/src/arch/x86/regfile.cc
+++ b/src/arch/x86/regfile.cc
@@ -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)
@@ -214,7 +214,7 @@ int X86ISA::flattenIntIndex(ThreadContext * tc, int reg)
//If we need to fold over the index to match byte semantics, do that.
//Otherwise, just strip off any extra bits and pass it through.
if (reg & (1 << 6))
- return (reg & ~(1 << 6) - 0x4);
+ return (reg & (~(1 << 6) - 0x4));
else
return (reg & ~(1 << 6));
}
@@ -228,7 +228,8 @@ int X86ISA::flattenFloatIndex(ThreadContext * tc, int reg)
return reg;
}
-void RegFile::serialize(std::ostream &os)
+void
+RegFile::serialize(EventManager *em, std::ostream &os)
{
intRegFile.serialize(os);
floatRegFile.serialize(os);
@@ -237,7 +238,8 @@ void RegFile::serialize(std::ostream &os)
SERIALIZE_SCALAR(nextRip);
}
-void RegFile::unserialize(Checkpoint *cp, const std::string &section)
+void
+RegFile::unserialize(EventManager *em, Checkpoint *cp, const string &section)
{
intRegFile.unserialize(cp, section);
floatRegFile.unserialize(cp, section);
@@ -246,11 +248,6 @@ void RegFile::unserialize(Checkpoint *cp, const std::string &section)
UNSERIALIZE_SCALAR(nextRip);
}
-void RegFile::changeContext(RegContextParam param, RegContextVal val)
-{
- panic("changeContext not implemented for x86!\n");
-}
-
void X86ISA::copyMiscRegs(ThreadContext *src, ThreadContext *dest)
{
panic("copyMiscRegs not implemented for x86!\n");
diff --git a/src/arch/x86/regfile.hh b/src/arch/x86/regfile.hh
index 650181aca..8938ab0bc 100644
--- a/src/arch/x86/regfile.hh
+++ b/src/arch/x86/regfile.hh
@@ -68,6 +68,7 @@
#include <string>
class Checkpoint;
+class EventManager;
namespace X86ISA
{
@@ -96,8 +97,6 @@ namespace X86ISA
void clear();
- int FlattenIntIndex(int reg);
-
MiscReg readMiscRegNoEffect(int miscReg);
MiscReg readMiscReg(int miscReg, ThreadContext *tc);
@@ -139,12 +138,11 @@ namespace X86ISA
void setIntReg(int intReg, const IntReg &val);
- void serialize(std::ostream &os);
- void unserialize(Checkpoint *cp, const std::string &section);
+ void serialize(EventManager *em, std::ostream &os);
+ void unserialize(EventManager *em, Checkpoint *cp,
+ const std::string &section);
public:
-
- void changeContext(RegContextParam param, RegContextVal val);
};
int flattenIntIndex(ThreadContext * tc, int reg);
diff --git a/src/arch/x86/remote_gdb.cc b/src/arch/x86/remote_gdb.cc
index 5ab0ec3fb..c416042c8 100644
--- a/src/arch/x86/remote_gdb.cc
+++ b/src/arch/x86/remote_gdb.cc
@@ -57,7 +57,7 @@
/*
* Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
+ * The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
@@ -65,8 +65,8 @@
*
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Lawrence Berkeley Laboratories.
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratories.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -78,8 +78,8 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@@ -96,7 +96,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
+ * @(#)kgdb_stub.c 8.4 (Berkeley) 1/12/94
*/
/*-
@@ -116,8 +116,8 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
@@ -157,7 +157,7 @@
#include "cpu/thread_context.hh"
using namespace std;
-using namespace TheISA;
+using namespace X86ISA;
RemoteGDB::RemoteGDB(System *_system, ThreadContext *c)
: BaseRemoteGDB(_system, c, NumGDBRegs)
diff --git a/src/arch/x86/stacktrace.cc b/src/arch/x86/stacktrace.cc
index 300e8dcd0..87767583b 100644
--- a/src/arch/x86/stacktrace.cc
+++ b/src/arch/x86/stacktrace.cc
@@ -70,8 +70,6 @@ namespace X86ISA
if (!tc->getSystemPtr()->kernelSymtab->findAddress("task_struct_comm", addr))
panic("thread info not compiled into kernel\n");
name_off = vp->readGtoH<int32_t>(addr);
-
- tc->delVirtPort(vp);
}
Addr
@@ -87,7 +85,6 @@ namespace X86ISA
vp = tc->getVirtPort();
tsk = vp->readGtoH<Addr>(base + task_off);
- tc->delVirtPort(vp);
return tsk;
}
@@ -105,7 +102,6 @@ namespace X86ISA
vp = tc->getVirtPort();
pd = vp->readGtoH<uint16_t>(task + pid_off);
- tc->delVirtPort(vp);
return pd;
}
diff --git a/src/arch/x86/system.cc b/src/arch/x86/system.cc
index 947a7793e..ed3dae4e6 100644
--- a/src/arch/x86/system.cc
+++ b/src/arch/x86/system.cc
@@ -55,13 +55,15 @@
* Authors: Gabe Black
*/
+#include "arch/x86/bios/smbios.hh"
+#include "arch/x86/bios/intelmp.hh"
#include "arch/x86/miscregs.hh"
#include "arch/x86/system.hh"
-#include "arch/x86/smbios.hh"
#include "arch/vtophys.hh"
-#include "base/remote_gdb.hh"
+#include "base/intmath.hh"
#include "base/loader/object_file.hh"
#include "base/loader/symtab.hh"
+#include "base/remote_gdb.hh"
#include "base/trace.hh"
#include "cpu/thread_context.hh"
#include "mem/physical.hh"
@@ -72,14 +74,12 @@
using namespace LittleEndianGuest;
using namespace X86ISA;
-X86System::X86System(Params *p)
- : System(p)
-{
- smbiosTable = new X86ISA::SMBios::SMBiosTable;
- smbiosTable->smbiosHeader.majorVersion = 2;
- smbiosTable->smbiosHeader.minorVersion = 5;
- smbiosTable->smbiosHeader.intermediateHeader.smbiosBCDRevision = 0x25;
-}
+X86System::X86System(Params *p) :
+ System(p), smbiosTable(p->smbios_table),
+ mpFloatingPointer(p->intel_mp_pointer),
+ mpConfigTable(p->intel_mp_table),
+ rsdp(p->acpi_description_table_pointer)
+{}
void
X86System::startup()
@@ -236,27 +236,67 @@ X86System::startup()
// We should now be in long mode. Yay!
+ Addr ebdaPos = 0xF0000;
+ Addr fixed, table;
+
//Write out the SMBios/DMI table
- writeOutSMBiosTable(0xF0000);
+ writeOutSMBiosTable(ebdaPos, fixed, table);
+ ebdaPos += (fixed + table);
+ ebdaPos = roundUp(ebdaPos, 16);
+
+ //Write out the Intel MP Specification configuration table
+ writeOutMPTable(ebdaPos, fixed, table);
+ ebdaPos += (fixed + table);
}
void
-X86System::writeOutSMBiosTable(Addr header, Addr table)
+X86System::writeOutSMBiosTable(Addr header,
+ Addr &headerSize, Addr &structSize, Addr table)
{
// Get a port to write the table and header to memory.
FunctionalPort * physPort = threadContexts[0]->getPhysPort();
// If the table location isn't specified, just put it after the header.
// The header size as of the 2.5 SMBios specification is 0x1F bytes
- if (!table) {
- if (!smbiosTable->smbiosHeader.intermediateHeader.tableAddr)
- smbiosTable->smbiosHeader.
- intermediateHeader.tableAddr = header + 0x1F;
- } else {
- smbiosTable->smbiosHeader.intermediateHeader.tableAddr = table;
+ if (!table)
+ table = header + 0x1F;
+ smbiosTable->setTableAddr(table);
+
+ smbiosTable->writeOut(physPort, header, headerSize, structSize);
+
+ // Do some bounds checking to make sure we at least didn't step on
+ // ourselves.
+ assert(header > table || header + headerSize <= table);
+ assert(table > header || table + structSize <= header);
+}
+
+void
+X86System::writeOutMPTable(Addr fp,
+ Addr &fpSize, Addr &tableSize, Addr table)
+{
+ // Get a port to write the table and header to memory.
+ FunctionalPort * physPort = threadContexts[0]->getPhysPort();
+
+ // If the table location isn't specified and it exists, just put
+ // it after the floating pointer. The fp size as of the 1.4 Intel MP
+ // specification is 0x10 bytes.
+ if (mpConfigTable) {
+ if (!table)
+ table = fp + 0x10;
+ mpFloatingPointer->setTableAddr(table);
}
- smbiosTable->writeOut(physPort, header);
+ fpSize = mpFloatingPointer->writeOut(physPort, fp);
+ if (mpConfigTable)
+ tableSize = mpConfigTable->writeOut(physPort, table);
+ else
+ tableSize = 0;
+
+ // Do some bounds checking to make sure we at least didn't step on
+ // ourselves and the fp structure was the size we thought it was.
+ assert(fp > table || fp + fpSize <= table);
+ assert(table > fp || table + tableSize <= fp);
+ assert(fpSize == 0x10);
}
diff --git a/src/arch/x86/system.hh b/src/arch/x86/system.hh
index 8a5483ebf..12a471f6f 100644
--- a/src/arch/x86/system.hh
+++ b/src/arch/x86/system.hh
@@ -74,6 +74,11 @@ namespace X86ISA
{
class SMBiosTable;
}
+ namespace IntelMP
+ {
+ class FloatingPointer;
+ class ConfigTable;
+ }
}
class X86System : public System
@@ -95,8 +100,15 @@ class X86System : public System
protected:
X86ISA::SMBios::SMBiosTable * smbiosTable;
+ X86ISA::IntelMP::FloatingPointer * mpFloatingPointer;
+ X86ISA::IntelMP::ConfigTable * mpConfigTable;
+ X86ISA::ACPI::RSDP * rsdp;
+
+ void writeOutSMBiosTable(Addr header,
+ Addr &headerSize, Addr &tableSize, Addr table = 0);
- void writeOutSMBiosTable(Addr header, Addr table = 0);
+ void writeOutMPTable(Addr fp,
+ Addr &fpSize, Addr &tableSize, Addr table = 0);
const Params *params() const { return (const Params *)_params; }
diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc
index a87abf212..3fec4c7da 100644
--- a/src/arch/x86/tlb.cc
+++ b/src/arch/x86/tlb.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 The Hewlett-Packard Development Company
+ * Copyright (c) 2007-2008 The Hewlett-Packard Development Company
* All rights reserved.
*
* Redistribution and use of this software in source and binary forms,
@@ -59,6 +59,7 @@
#include "config/full_system.hh"
+#include "arch/x86/insts/microldstop.hh"
#include "arch/x86/pagetable.hh"
#include "arch/x86/tlb.hh"
#include "arch/x86/x86_traits.hh"
@@ -72,6 +73,9 @@
#if FULL_SYSTEM
#include "arch/x86/pagetable_walker.hh"
+#else
+#include "mem/page_table.hh"
+#include "sim/process.hh"
#endif
namespace X86ISA {
@@ -90,7 +94,7 @@ TLB::TLB(const Params *p) : BaseTLB(p), configAddress(0), size(p->size)
#endif
}
-void
+TlbEntry *
TLB::insert(Addr vpn, TlbEntry &entry)
{
//TODO Deal with conflicting entries
@@ -106,6 +110,7 @@ TLB::insert(Addr vpn, TlbEntry &entry)
*newEntry = entry;
newEntry->vaddr = vpn;
entryList.push_front(newEntry);
+ return newEntry;
}
TLB::EntryList::iterator
@@ -138,14 +143,6 @@ TLB::lookup(Addr va, bool update_lru)
return *entry;
}
-#if FULL_SYSTEM
-void
-TLB::walk(ThreadContext * _tc, Addr vaddr)
-{
- walker->start(_tc, vaddr);
-}
-#endif
-
void
TLB::invalidateAll()
{
@@ -188,16 +185,18 @@ TLB::demapPage(Addr va, uint64_t asn)
}
}
-template<class TlbFault>
Fault
-TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
+TLB::translate(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write, bool execute,
+ bool &delayedResponse, bool timing)
{
+ delayedResponse = false;
Addr vaddr = req->getVaddr();
DPRINTF(TLB, "Translating vaddr %#x.\n", vaddr);
uint32_t flags = req->getFlags();
bool storeCheck = flags & StoreCheck;
- int seg = flags & mask(4);
+ int seg = flags & SegmentFlagMask;
//XXX Junk code to surpress the warning
if (storeCheck);
@@ -206,10 +205,11 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
// value.
if (seg == SEGMENT_REG_MS) {
DPRINTF(TLB, "Addresses references internal memory.\n");
- Addr prefix = vaddr & IntAddrPrefixMask;
+ Addr prefix = (vaddr >> 3) & IntAddrPrefixMask;
if (prefix == IntAddrPrefixCPUID) {
panic("CPUID memory space not yet implemented!\n");
} else if (prefix == IntAddrPrefixMSR) {
+ vaddr = vaddr >> 3;
req->setMmapedIpr(true);
Addr regNum = 0;
switch (vaddr & ~IntAddrPrefixMask) {
@@ -357,6 +357,15 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
case 0x410:
regNum = MISCREG_MC4_CTL;
break;
+ case 0x414:
+ regNum = MISCREG_MC5_CTL;
+ break;
+ case 0x418:
+ regNum = MISCREG_MC6_CTL;
+ break;
+ case 0x41C:
+ regNum = MISCREG_MC7_CTL;
+ break;
case 0x401:
regNum = MISCREG_MC0_STATUS;
break;
@@ -372,6 +381,15 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
case 0x411:
regNum = MISCREG_MC4_STATUS;
break;
+ case 0x415:
+ regNum = MISCREG_MC5_STATUS;
+ break;
+ case 0x419:
+ regNum = MISCREG_MC6_STATUS;
+ break;
+ case 0x41D:
+ regNum = MISCREG_MC7_STATUS;
+ break;
case 0x402:
regNum = MISCREG_MC0_ADDR;
break;
@@ -387,6 +405,15 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
case 0x412:
regNum = MISCREG_MC4_ADDR;
break;
+ case 0x416:
+ regNum = MISCREG_MC5_ADDR;
+ break;
+ case 0x41A:
+ regNum = MISCREG_MC6_ADDR;
+ break;
+ case 0x41E:
+ regNum = MISCREG_MC7_ADDR;
+ break;
case 0x403:
regNum = MISCREG_MC0_MISC;
break;
@@ -402,6 +429,15 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
case 0x413:
regNum = MISCREG_MC4_MISC;
break;
+ case 0x417:
+ regNum = MISCREG_MC5_MISC;
+ break;
+ case 0x41B:
+ regNum = MISCREG_MC6_MISC;
+ break;
+ case 0x41F:
+ regNum = MISCREG_MC7_MISC;
+ break;
case 0xC0000080:
regNum = MISCREG_EFER;
break;
@@ -510,7 +546,8 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
tc->readMiscRegNoEffect(MISCREG_PCI_CONFIG_ADDRESS);
if (bits(configAddress, 31, 31)) {
req->setPaddr(PhysAddrPrefixPciConfig |
- bits(configAddress, 30, 0));
+ mbits(configAddress, 30, 2) |
+ (IOPort & mask(2)));
}
} else {
req->setPaddr(PhysAddrPrefixIO | IOPort);
@@ -534,35 +571,38 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
// If we're not in 64-bit mode, do protection/limit checks
if (!efer.lma || !csAttr.longMode) {
DPRINTF(TLB, "Not in long mode. Checking segment protection.\n");
- SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg));
- if (!attr.writable && write)
- return new GeneralProtection(0);
- if (!attr.readable && !write && !execute)
+ // Check for a NULL segment selector.
+ if (!tc->readMiscRegNoEffect(MISCREG_SEG_SEL(seg)))
return new GeneralProtection(0);
+ bool expandDown = false;
+ SegAttr attr = tc->readMiscRegNoEffect(MISCREG_SEG_ATTR(seg));
+ if (seg >= SEGMENT_REG_ES && seg <= SEGMENT_REG_HS) {
+ if (!attr.writable && write)
+ return new GeneralProtection(0);
+ if (!attr.readable && !write && !execute)
+ return new GeneralProtection(0);
+ expandDown = attr.expandDown;
+
+ }
Addr base = tc->readMiscRegNoEffect(MISCREG_SEG_BASE(seg));
Addr limit = tc->readMiscRegNoEffect(MISCREG_SEG_LIMIT(seg));
- if (!attr.expandDown) {
+ // This assumes we're not in 64 bit mode. If we were, the default
+ // address size is 64 bits, overridable to 32.
+ int size = 32;
+ bool sizeOverride = (flags & (AddrSizeFlagBit << FlagShift));
+ if ((csAttr.defaultSize && sizeOverride) ||
+ (!csAttr.defaultSize && !sizeOverride))
+ size = 16;
+ Addr offset = bits(vaddr - base, size-1, 0);
+ Addr endOffset = offset + req->getSize() - 1;
+ if (expandDown) {
DPRINTF(TLB, "Checking an expand down segment.\n");
- // We don't have to worry about the access going around the
- // end of memory because accesses will be broken up into
- // pieces at boundaries aligned on sizes smaller than an
- // entire address space. We do have to worry about the limit
- // being less than the base.
- if (limit < base) {
- if (limit < vaddr + req->getSize() && vaddr < base)
- return new GeneralProtection(0);
- } else {
- if (limit < vaddr + req->getSize())
- return new GeneralProtection(0);
- }
+ warn_once("Expand down segments are untested.\n");
+ if (offset <= limit || endOffset <= limit)
+ return new GeneralProtection(0);
} else {
- if (limit < base) {
- if (vaddr <= limit || vaddr + req->getSize() >= base)
- return new GeneralProtection(0);
- } else {
- if (vaddr <= limit && vaddr + req->getSize() >= base)
- return new GeneralProtection(0);
- }
+ if (offset > limit || endOffset > limit)
+ return new GeneralProtection(0);
}
}
// If paging is enabled, do the translation.
@@ -571,14 +611,57 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
// The vaddr already has the segment base applied.
TlbEntry *entry = lookup(vaddr);
if (!entry) {
- return new TlbFault(vaddr);
- } else {
- // Do paging protection checks.
- DPRINTF(TLB, "Entry found with paddr %#x, doing protection checks.\n", entry->paddr);
- Addr paddr = entry->paddr | (vaddr & (entry->size-1));
- DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, paddr);
- req->setPaddr(paddr);
+#if FULL_SYSTEM
+ Fault fault = walker->start(tc, translation, req,
+ write, execute);
+ if (timing || fault != NoFault) {
+ // This gets ignored in atomic mode.
+ delayedResponse = true;
+ return fault;
+ }
+ entry = lookup(vaddr);
+ assert(entry);
+#else
+ DPRINTF(TLB, "Handling a TLB miss for "
+ "address %#x at pc %#x.\n",
+ vaddr, tc->readPC());
+
+ Process *p = tc->getProcessPtr();
+ TlbEntry newEntry;
+ bool success = p->pTable->lookup(vaddr, newEntry);
+ if(!success && !execute) {
+ p->checkAndAllocNextPage(vaddr);
+ success = p->pTable->lookup(vaddr, newEntry);
+ }
+ if(!success) {
+ panic("Tried to execute unmapped address %#x.\n", vaddr);
+ } else {
+ Addr alignedVaddr = p->pTable->pageAlign(vaddr);
+ DPRINTF(TLB, "Mapping %#x to %#x\n", alignedVaddr,
+ newEntry.pageStart());
+ entry = insert(alignedVaddr, newEntry);
+ }
+ DPRINTF(TLB, "Miss was serviced.\n");
+#endif
}
+ // Do paging protection checks.
+ bool inUser = (csAttr.dpl == 3 &&
+ !(flags & (CPL0FlagBit << FlagShift)));
+ if ((inUser && !entry->user) ||
+ (write && !entry->writable)) {
+ // The page must have been present to get into the TLB in
+ // the first place. We'll assume the reserved bits are
+ // fine even though we're not checking them.
+ return new PageFault(vaddr, true, write,
+ inUser, false, execute);
+ }
+
+
+ DPRINTF(TLB, "Entry found with paddr %#x, "
+ "doing protection checks.\n", entry->paddr);
+ Addr paddr = entry->paddr | (vaddr & (entry->size-1));
+ DPRINTF(TLB, "Translated %#x -> %#x.\n", vaddr, paddr);
+ req->setPaddr(paddr);
} else {
//Use the address which already has segmentation applied.
DPRINTF(TLB, "Paging disabled.\n");
@@ -592,160 +675,68 @@ TLB::translate(RequestPtr &req, ThreadContext *tc, bool write, bool execute)
req->setPaddr(vaddr);
}
// Check for an access to the local APIC
+#if FULL_SYSTEM
LocalApicBase localApicBase = tc->readMiscRegNoEffect(MISCREG_APIC_BASE);
- Addr baseAddr = localApicBase.base << 12;
+ Addr baseAddr = localApicBase.base * PageBytes;
Addr paddr = req->getPaddr();
- if (baseAddr <= paddr && baseAddr + (1 << 12) > paddr) {
- req->setMmapedIpr(true);
+ if (baseAddr <= paddr && baseAddr + PageBytes > paddr) {
+ // The Intel developer's manuals say the below restrictions apply,
+ // but the linux kernel, because of a compiler optimization, breaks
+ // them.
+ /*
// Check alignment
if (paddr & ((32/8) - 1))
return new GeneralProtection(0);
// Check access size
if (req->getSize() != (32/8))
return new GeneralProtection(0);
- MiscReg regNum;
- switch (paddr - baseAddr)
- {
- case 0x20:
- regNum = MISCREG_APIC_ID;
- break;
- case 0x30:
- regNum = MISCREG_APIC_VERSION;
- break;
- case 0x80:
- regNum = MISCREG_APIC_TASK_PRIORITY;
- break;
- case 0x90:
- regNum = MISCREG_APIC_ARBITRATION_PRIORITY;
- break;
- case 0xA0:
- regNum = MISCREG_APIC_PROCESSOR_PRIORITY;
- break;
- case 0xB0:
- regNum = MISCREG_APIC_EOI;
- break;
- case 0xD0:
- regNum = MISCREG_APIC_LOGICAL_DESTINATION;
- break;
- case 0xE0:
- regNum = MISCREG_APIC_DESTINATION_FORMAT;
- break;
- case 0xF0:
- regNum = MISCREG_APIC_SPURIOUS_INTERRUPT_VECTOR;
- break;
- case 0x100:
- case 0x108:
- case 0x110:
- case 0x118:
- case 0x120:
- case 0x128:
- case 0x130:
- case 0x138:
- case 0x140:
- case 0x148:
- case 0x150:
- case 0x158:
- case 0x160:
- case 0x168:
- case 0x170:
- case 0x178:
- regNum = MISCREG_APIC_IN_SERVICE(
- (paddr - baseAddr - 0x100) / 0x8);
- break;
- case 0x180:
- case 0x188:
- case 0x190:
- case 0x198:
- case 0x1A0:
- case 0x1A8:
- case 0x1B0:
- case 0x1B8:
- case 0x1C0:
- case 0x1C8:
- case 0x1D0:
- case 0x1D8:
- case 0x1E0:
- case 0x1E8:
- case 0x1F0:
- case 0x1F8:
- regNum = MISCREG_APIC_TRIGGER_MODE(
- (paddr - baseAddr - 0x180) / 0x8);
- break;
- case 0x200:
- case 0x208:
- case 0x210:
- case 0x218:
- case 0x220:
- case 0x228:
- case 0x230:
- case 0x238:
- case 0x240:
- case 0x248:
- case 0x250:
- case 0x258:
- case 0x260:
- case 0x268:
- case 0x270:
- case 0x278:
- regNum = MISCREG_APIC_INTERRUPT_REQUEST(
- (paddr - baseAddr - 0x200) / 0x8);
- break;
- case 0x280:
- regNum = MISCREG_APIC_ERROR_STATUS;
- break;
- case 0x300:
- regNum = MISCREG_APIC_INTERRUPT_COMMAND_LOW;
- break;
- case 0x310:
- regNum = MISCREG_APIC_INTERRUPT_COMMAND_HIGH;
- break;
- case 0x320:
- regNum = MISCREG_APIC_LVT_TIMER;
- break;
- case 0x330:
- regNum = MISCREG_APIC_LVT_THERMAL_SENSOR;
- break;
- case 0x340:
- regNum = MISCREG_APIC_LVT_PERFORMANCE_MONITORING_COUNTERS;
- break;
- case 0x350:
- regNum = MISCREG_APIC_LVT_LINT0;
- break;
- case 0x360:
- regNum = MISCREG_APIC_LVT_LINT1;
- break;
- case 0x370:
- regNum = MISCREG_APIC_LVT_ERROR;
- break;
- case 0x380:
- regNum = MISCREG_APIC_INITIAL_COUNT;
- break;
- case 0x390:
- regNum = MISCREG_APIC_CURRENT_COUNT;
- break;
- case 0x3E0:
- regNum = MISCREG_APIC_DIVIDE_COUNT;
- break;
- default:
- // A reserved register field.
- return new GeneralProtection(0);
- break;
- }
- req->setPaddr(regNum * sizeof(MiscReg));
+ */
+ // Force the access to be uncacheable.
+ req->setFlags(Request::UNCACHEABLE);
+ req->setPaddr(x86LocalAPICAddress(tc->contextId(), paddr - baseAddr));
}
+#endif
return NoFault;
};
Fault
-DTB::translate(RequestPtr &req, ThreadContext *tc, bool write)
+DTB::translateAtomic(RequestPtr req, ThreadContext *tc, bool write)
+{
+ bool delayedResponse;
+ return TLB::translate(req, tc, NULL, write,
+ false, delayedResponse, false);
+}
+
+void
+DTB::translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write)
{
- return TLB::translate<FakeDTLBFault>(req, tc, write, false);
+ bool delayedResponse;
+ assert(translation);
+ Fault fault = TLB::translate(req, tc, translation,
+ write, false, delayedResponse, true);
+ if (!delayedResponse)
+ translation->finish(fault, req, tc, write);
}
Fault
-ITB::translate(RequestPtr &req, ThreadContext *tc)
+ITB::translateAtomic(RequestPtr req, ThreadContext *tc)
+{
+ bool delayedResponse;
+ return TLB::translate(req, tc, NULL, false,
+ true, delayedResponse, false);
+}
+
+void
+ITB::translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation)
{
- return TLB::translate<FakeITLBFault>(req, tc, false, true);
+ bool delayedResponse;
+ assert(translation);
+ Fault fault = TLB::translate(req, tc, translation,
+ false, true, delayedResponse, true);
+ if (!delayedResponse)
+ translation->finish(fault, req, tc, false);
}
#if FULL_SYSTEM
diff --git a/src/arch/x86/tlb.hh b/src/arch/x86/tlb.hh
index 89b965e97..2467bc472 100644
--- a/src/arch/x86/tlb.hh
+++ b/src/arch/x86/tlb.hh
@@ -87,8 +87,7 @@ namespace X86ISA
class TLB : public BaseTLB
{
protected:
- friend class FakeITLBFault;
- friend class FakeDTLBFault;
+ friend class Walker;
typedef std::list<TlbEntry *> EntryList;
@@ -118,8 +117,6 @@ namespace X86ISA
protected:
Walker * walker;
-
- void walk(ThreadContext * _tc, Addr vaddr);
#endif
public:
@@ -137,13 +134,13 @@ namespace X86ISA
EntryList freeList;
EntryList entryList;
- template<class TlbFault>
- Fault translate(RequestPtr &req, ThreadContext *tc,
- bool write, bool execute);
+ Fault translate(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write, bool execute,
+ bool &delayedResponse, bool timing);
public:
- void insert(Addr vpn, TlbEntry &entry);
+ TlbEntry * insert(Addr vpn, TlbEntry &entry);
// Checkpointing
virtual void serialize(std::ostream &os);
@@ -159,7 +156,9 @@ namespace X86ISA
_allowNX = false;
}
- Fault translate(RequestPtr &req, ThreadContext *tc);
+ Fault translateAtomic(RequestPtr req, ThreadContext *tc);
+ void translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation);
friend class DTB;
};
@@ -172,7 +171,9 @@ namespace X86ISA
{
_allowNX = true;
}
- Fault translate(RequestPtr &req, ThreadContext *tc, bool write);
+ Fault translateAtomic(RequestPtr req, ThreadContext *tc, bool write);
+ void translateTiming(RequestPtr req, ThreadContext *tc,
+ Translation *translation, bool write);
#if FULL_SYSTEM
Tick doMmuRegRead(ThreadContext *tc, Packet *pkt);
Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt);
diff --git a/src/arch/x86/types.hh b/src/arch/x86/types.hh
index 90df38d13..29420352b 100644
--- a/src/arch/x86/types.hh
+++ b/src/arch/x86/types.hh
@@ -246,17 +246,6 @@ namespace X86ISA
MiscReg ctrlReg;
} AnyReg;
- //XXX This is very hypothetical. X87 instructions would need to
- //change their "context" constantly. It's also not clear how
- //this would be handled as far as out of order execution.
- //Maybe x87 instructions are in order?
- enum RegContextParam
- {
- CONTEXT_X87_TOP
- };
-
- typedef int RegContextVal;
-
typedef uint16_t RegIndex;
struct CoreSpecific {
diff --git a/src/arch/x86/utility.cc b/src/arch/x86/utility.cc
index 5fe5bf8c3..43a5ca1a9 100644
--- a/src/arch/x86/utility.cc
+++ b/src/arch/x86/utility.cc
@@ -55,11 +55,17 @@
* 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,15 @@ 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);
+
+ interrupts->setClock(tc->getCpuPtr()->ticks(16));
// TODO Set the SMRAM base address (SMBASE) to 0x00030000
diff --git a/src/arch/x86/utility.hh b/src/arch/x86/utility.hh
index 477a76e0b..6f0812a6a 100644
--- a/src/arch/x86/utility.hh
+++ b/src/arch/x86/utility.hh
@@ -93,7 +93,12 @@ namespace X86ISA
static inline bool
inUserMode(ThreadContext *tc)
{
- return false;
+#if FULL_SYSTEM
+ HandyM5Reg m5reg = tc->readMiscRegNoEffect(MISCREG_M5_REG);
+ return m5reg.cpl == 3;
+#else
+ return true;
+#endif
}
inline bool isCallerSaveIntegerRegister(unsigned int reg) {
diff --git a/src/arch/x86/x86_traits.hh b/src/arch/x86/x86_traits.hh
index d605ce218..0347a7099 100644
--- a/src/arch/x86/x86_traits.hh
+++ b/src/arch/x86/x86_traits.hh
@@ -55,11 +55,13 @@
* Authors: Gabe Black
*/
-#include "sim/host.hh"
-
#ifndef __ARCH_X86_X86TRAITS_HH__
#define __ARCH_X86_X86TRAITS_HH__
+#include <assert.h>
+
+#include "sim/host.hh"
+
namespace X86ISA
{
const int NumMicroIntRegs = 16;
@@ -90,6 +92,37 @@ namespace X86ISA
const Addr PhysAddrPrefixIO = ULL(0x8000000000000000);
const Addr PhysAddrPrefixPciConfig = ULL(0xC000000000000000);
+ const Addr PhysAddrPrefixLocalAPIC = ULL(0x2000000000000000);
+ const Addr PhysAddrPrefixInterrupts = ULL(0xA000000000000000);
+ // Each APIC gets two pages. One page is used for local apics to field
+ // accesses from the CPU, and the other is for all APICs to communicate.
+ const Addr PhysAddrAPICRangeSize = 1 << 12;
+
+ static inline Addr
+ x86IOAddress(const uint32_t port)
+ {
+ return PhysAddrPrefixIO | port;
+ }
+
+ static inline Addr
+ x86PciConfigAddress(const uint32_t addr)
+ {
+ return PhysAddrPrefixPciConfig | addr;
+ }
+
+ static inline Addr
+ x86LocalAPICAddress(const uint8_t id, const uint16_t addr)
+ {
+ assert(addr < (1 << 12));
+ return PhysAddrPrefixLocalAPIC | (id * (1 << 12)) | addr;
+ }
+
+ static inline Addr
+ x86InterruptAddress(const uint8_t id, const uint16_t addr)
+ {
+ assert(addr < PhysAddrAPICRangeSize);
+ return PhysAddrPrefixInterrupts | (id * PhysAddrAPICRangeSize) | addr;
+ }
}
#endif //__ARCH_X86_X86TRAITS_HH__