Gabe Black has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/56326 )
Change subject: arch-x86: Implement legacy mode interrupts.
......................................................................
arch-x86: Implement legacy mode interrupts.
Change-Id: Ib20f1a45d67c610176101820451ea1662ce17507
---
M src/arch/x86/faults.cc
M src/arch/x86/isa/insts/romutil.py
2 files changed, 336 insertions(+), 6 deletions(-)
diff --git a/src/arch/x86/faults.cc b/src/arch/x86/faults.cc
index 6a567c7..65ec273 100644
--- a/src/arch/x86/faults.cc
+++ b/src/arch/x86/faults.cc
@@ -85,8 +85,7 @@
if (m5reg.mode == LongMode) {
entry = extern_label_longModeInterruptWithError;
} else {
- panic("Legacy mode interrupts with error codes "
- "aren't implemented.");
+ entry = extern_label_legacyModeInterruptWithError;
}
tc->setIntReg(INTREG_MICRO(15), errorCode);
}
diff --git a/src/arch/x86/isa/insts/romutil.py
b/src/arch/x86/isa/insts/romutil.py
index 847b9c4..6741a29 100644
--- a/src/arch/x86/isa/insts/romutil.py
+++ b/src/arch/x86/isa/insts/romutil.py
@@ -24,7 +24,7 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-intCodeTemplate = '''
+longIntCodeTemplate = '''
def rom
{
# This vectors the CPU into an interrupt handler in long mode.
@@ -176,20 +176,324 @@
};
'''
+intCodeTemplate = '''
+def rom
+{
+ # This vectors the CPU into an interrupt handler in legacy 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 interrupt, trap, or task gate descriptor from the IDT
+ #
+
+ # Load the gate descriptor from the IDT
+ slli t4, t1, 3, dataSize=8
+ 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, dataSize=8
+
+ # Stick the target offset in t9.
+ wrdh t9, t4, t0, dataSize=8
+
+ # Check the gate type.
+ srli t2, t4, 40, dataSize=8
+ andi t2, t2, 0xf, dataSize=8
+ xori t2, t2, 0x5, flags=(EZF,), dataSize=8
+
+ panic "Protected mode interrupt through a task gate not implemented.",
\
+ flags=(CEZF,)
+
+ #
+ # 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_globalCS"), flags=(CEZF,)
+ ld t3, tsl, [1, t0, t5], dataSize=8, addressSize=8, atCPL0=True
+ br rom_local_label("%(startLabel)s_processCS")
+%(startLabel)s_globalCS:
+ ld t3, tsg, [1, t0, t5], dataSize=8, addressSize=8, atCPL0=True
+%(startLabel)s_processCS:
+ andi t13, t10, 0xff, dataSize=8
+ chks t13, t3, IntCSCheck, dataSize=8
+ wrdl hs, t3, t13, dataSize=8
+
+ #
+ # Figure out stack stuff.
+ #
+
+ # Determine the operand size. ECF will be 1 if 32 bit, and 0 if 16 bit.
+ srli t0, t4, 44, flags=(ECF,), dataSize=8
+
+ rdsel t1, cs, dataSize=8
+
+ # 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, cs, dataSize=8
+ andi t10, t10, 0x3, dataSize=8
+ rdattr t5, hs, dataSize=8
+ andi t5, t5, 0x3, dataSize=8
+ sub t0, t5, t10, flags=(EZF,), dataSize=8
+
+ # We shouldn't modify CS here, but we need to so we have the right
+ # permissions for the stack accesses further down.
+ wrsel cs, t13, dataSize=8
+ wrdl cs, t3, t13, dataSize=8
+
+ br rom_local_label("%(startLabel)s_noStackSwitch"), flags=(CEZF,)
+
+ # Get the new ESP from the TSS
+ ld t6, tr, [8, t10, t0], 4, dataSize=4, addressSize=8, atCPL0=True
+ # Get the new SS from the TSS
+ ld t8, tr, [8, t10, t0], 8, dataSize=2, addressSize=8, atCPL0=True
+
+ # Go get the stack segment descriptor
+ # Check for a null selector.
+ andi t0, t8, 0xFC, flags=(EZF,), dataSize=8
+ fault "std::make_shared<GeneralProtection>(0)", flags=(CEZF,)
+ # Extract the index.
+ andi t11, t8, 0xF8, dataSize=8
+ # Check if this is a global or local descriptor.
+ andi t0, t8, 0x4, flags=(EZF,), dataSize=2
+ br rom_local_label("%(startLabel)s_globalSS"), flags=(CEZF,)
+ ld t12, tsl, [1, t0, t11], dataSize=8, addressSize=8, atCPL0=True
+ br rom_local_label("%(startLabel)s_processSS")
+%(startLabel)s_globalSS:
+ ld t12, tsg, [1, t0, t11], dataSize=8, addressSize=8, atCPL0=True
+%(startLabel)s_processSS:
+ chks t8, t12, SSCheck, dataSize=8
+ wrdl hs, t12, t8, dataSize=8
+
+ # Find the size of stack addresses based on this new descriptor.
+ rdattr t14, hs, dataSize=8
+ andi t0, t14, 0x8, flags=(EZF,), dataSize=8
+
+ br rom_local_label("%(startLabel)s_sszIs4Switched"), flags=(nCEZF,)
+ br rom_local_label("%(startLabel)s_sszIs2DszIs4Switched"),
flags=(CECF,)
+
+ # ssz = 2, dsz = 2
+
+ # Make sure the space on the stack is accessible.
+ cda hs, [1, t0, t6], -1, dataSize=1, addressSize=2
+ cda hs, [1, t0, t6], -10 - %(errorCodeSize)d / 2, \
+ dataSize=1, addressSize=2
+
+ # Point of no return.
+ rdsel t2, ss, dataSize=8
+ st t2, hs, [1, t0, t6], -2, dataSize=2, addressSize=2
+ st rsp, hs, [1, t0, t6], -4, dataSize=2, addressSize=2
+ rflags t10, dataSize=8
+ st t10, hs, [1, t0, t6], -6, dataSize=2, addressSize=2
+ st t1, hs, [1, t0, t6], -8, dataSize=2, addressSize=2
+ st t7, hs, [1, t0, t6], -10, dataSize=2, addressSize=2
+ mov rsp, rsp, t6, dataSize=4
+ subi rsp, rsp, 10 + %(errorCodeSize)d / 2, dataSize=2
+ wrdl ss, t12, t8, dataSize=8
+ wrsel ss, t8, dataSize=8
+ %(errorCodeCode)s, dataSize=2, addressSize=2
+
+ br rom_local_label("%(startLabel)s_doneWithStack")
+
+%(startLabel)s_sszIs2DszIs4Switched:
+
+ # ssz = 2, dsz = 4
+
+ # Make sure the space on the stack is accessible.
+ cda hs, [1, t0, t6], -1, dataSize=1, addressSize=2
+ cda hs, [1, t0, t6], -20 - %(errorCodeSize)d, \
+ dataSize=1, addressSize=2
+
+ # Point of no return.
+ rdsel t2, ss, dataSize=8
+ st t2, hs, [1, t0, t6], -4, dataSize=4, addressSize=2
+ st rsp, hs, [1, t0, t6], -8, dataSize=4, addressSize=2
+ rflags t10, dataSize=8
+ st t10, hs, [1, t0, t6], -12, dataSize=4, addressSize=2
+ st t1, hs, [1, t0, t6], -16, dataSize=4, addressSize=2
+ st t7, hs, [1, t0, t6], -20, dataSize=4, addressSize=2
+ mov rsp, rsp, t6, dataSize=4
+ subi rsp, rsp, 20 + %(errorCodeSize)d, dataSize=2
+ wrdl ss, t12, t8, dataSize=8
+ wrsel ss, t8, dataSize=8
+ %(errorCodeCode)s, dataSize=4, addressSize=2
+
+ br rom_local_label("%(startLabel)s_doneWithStack")
+
+%(startLabel)s_sszIs4Switched:
+ br rom_local_label("%(startLabel)s_sszIs4DszIs4Switched"),
flags=(CECF,)
+
+ # ssz = 4, dsz = 2
+
+ # Make sure the space on the stack is accessible.
+ cda hs, [1, t0, t6], -1, dataSize=1, addressSize=4
+ cda hs, [1, t0, t6], -10 - %(errorCodeSize)d / 2, \
+ dataSize=1, addressSize=4
+
+ # Point of no return.
+ rdsel t2, ss, dataSize=8
+ st t2, hs, [1, t0, t6], -2, dataSize=2, addressSize=4
+ st rsp, hs, [1, t0, t6], -4, dataSize=2, addressSize=4
+ rflags t10, dataSize=8
+ st t10, hs, [1, t0, t6], -6, dataSize=2, addressSize=4
+ st t12, hs, [1, t0, t6], -8, dataSize=2, addressSize=4
+ st t7, hs, [1, t0, t6], -10, dataSize=2, addressSize=4
+ subi rsp, t6, 10 + %(errorCodeSize)d / 2, dataSize=4
+ wrdl ss, t12, t8, dataSize=8
+ wrsel ss, t8, dataSize=8
+ %(errorCodeCode)s, dataSize=2, addressSize=4
+
+ br rom_local_label("%(startLabel)s_doneWithStack")
+
+%(startLabel)s_sszIs4DszIs4Switched:
+
+ # ssz = 4, dsz = 4
+
+ # Make sure the space on the stack is accessible.
+ cda hs, [1, t0, t6], -1, dataSize=1, addressSize=4
+ cda hs, [1, t0, t6], -20 - %(errorCodeSize)d, \
+ dataSize=1, addressSize=4
+
+ # Point of no return.
+ rdsel t2, ss, dataSize=8
+ st t2, hs, [1, t0, t6], -4, dataSize=4, addressSize=4
+ st rsp, hs, [1, t0, t6], -8, dataSize=4, addressSize=4
+ rflags t10, dataSize=8
+ st t10, hs, [1, t0, t6], -12, dataSize=4, addressSize=4
+ st t1, hs, [1, t0, t6], -16, dataSize=4, addressSize=4
+ st t7, hs, [1, t0, t6], -20, dataSize=4, addressSize=4
+ subi rsp, t6, 20 + %(errorCodeSize)d, dataSize=4
+ wrdl ss, t12, t8, dataSize=8
+ wrsel ss, t8, dataSize=8
+ %(errorCodeCode)s, dataSize=2, addressSize=4
+
+ br rom_local_label("%(startLabel)s_doneWithStack")
+
+
+%(startLabel)s_noStackSwitch:
+
+ # Find the size of stack addresses based on the stack descriptor.
+ rdattr t14, ss, dataSize=8
+ andi t0, t14, 0x8, flags=(EZF,), dataSize=8
+
+ br rom_local_label("%(startLabel)s_sszIs4"), flags=(nCEZF,)
+ br rom_local_label("%(startLabel)s_sszIs2DszIs4"), flags=(CECF,)
+
+ # Make sure the space on the stack is accessible.
+ cda ss, [1, t0, rsp], -1, dataSize=1, addressSize=2
+ cda ss, [1, t0, rsp], -6 - %(errorCodeSize)d / 2, \
+ dataSize=1, addressSize=2
+
+ # Point of no return.
+ rflags t10, dataSize=8
+ st t10, ss, [1, t0, t6], -2, dataSize=2, addressSize=2
+ st t1, ss, [1, t0, t6], -4, dataSize=2, addressSize=2
+ st t7, ss, [1, t0, t6], -6, dataSize=2, addressSize=2
+ subi rsp, rsp, 6 + %(errorCodeSize)d / 2, dataSize=2
+ %(errorCodeCode)s, dataSize=2, addressSize=2
+
+ br rom_local_label("%(startLabel)s_doneWithStack")
+
+%(startLabel)s_sszIs2DszIs4:
+
+ # ssz = 2, dsz = 4
+
+ # Make sure the space on the stack is accessible.
+ cda ss, [1, t0, rsp], -1, dataSize=1, addressSize=2
+ cda ss, [1, t0, rsp], -12 - %(errorCodeSize)d, \
+ dataSize=1, addressSize=2
+
+ # Point of no return.
+ rflags t10, dataSize=8
+ st t10, ss, [1, t0, rsp], -4, dataSize=4, addressSize=2
+ st t1, ss, [1, t0, rsp], -8, dataSize=4, addressSize=2
+ st t7, ss, [1, t0, rsp], -12, dataSize=4, addressSize=2
+ subi rsp, rsp, 12 + %(errorCodeSize)d, dataSize=2
+ %(errorCodeCode)s, dataSize=4, addressSize=2
+
+ br rom_local_label("%(startLabel)s_doneWithStack")
+
+%(startLabel)s_sszIs4:
+ br rom_local_label("%(startLabel)s_sszIs4DszIs4"), flags=(CECF,)
+
+ # ssz = 4, dsz = 2
+
+ # Make sure the space on the stack is accessible.
+ cda ss, [1, t0, rsp], -1, dataSize=1, addressSize=4
+ cda ss, [1, t0, rsp], -6 - %(errorCodeSize)d / 2, \
+ dataSize=1, addressSize=4
+
+ # Point of no return.
+ rflags t10, dataSize=8
+ st t10, ss, [1, t0, rsp], -2, dataSize=2, addressSize=4
+ st t1, ss, [1, t0, rsp], -4, dataSize=2, addressSize=4
+ st t7, ss, [1, t0, rsp], -6, dataSize=2, addressSize=4
+ subi rsp, rsp, 6 + %(errorCodeSize)d / 2, dataSize=4
+ %(errorCodeCode)s, dataSize=2, addressSize=4
+
+ br rom_local_label("%(startLabel)s_doneWithStack")
+
+%(startLabel)s_sszIs4DszIs4:
+
+ # ssz = 4, dsz = 4
+
+ # Make sure the space on the stack is accessible.
+ cda ss, [1, t0, rsp], -1, dataSize=1, addressSize=4
+ cda ss, [1, t0, rsp], -12 - %(errorCodeSize)d, \
+ dataSize=1, addressSize=4
+
+ # Point of no return.
+ rflags t10, dataSize=8
+ st t10, ss, [1, t0, rsp], -4, dataSize=4, addressSize=4
+ st t1, ss, [1, t0, rsp], -8, dataSize=4, addressSize=4
+ st t7, ss, [1, t0, rsp], -12, dataSize=4, addressSize=4
+ subi rsp, rsp, 12 + %(errorCodeSize)d, dataSize=4
+ %(errorCodeCode)s, dataSize=4, addressSize=4
+
+ br rom_local_label("%(startLabel)s_doneWithStack")
+
+%(startLabel)s_doneWithStack:
+
+ wrip t0, t9, dataSize=8
+
+ # 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, RF, and VM bits. We'll flip them at the end.
+ limm t6, "(TFBit | NTBit | RFBit | VMBit)", dataSize=8
+ or t10, t10, t6, dataSize=8
+ 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 % {\
+longIntCodeTemplate % {\
"startLabel" : "longModeInterrupt",
"gateCheckType" : "IntGateCheck",
"errorCodeSize" : 0,
"errorCodeCode" : ""
} + \
-intCodeTemplate % {\
+longIntCodeTemplate % {\
"startLabel" : "longModeSoftInterrupt",
"gateCheckType" : "SoftIntGateCheck",
"errorCodeSize" : 0,
"errorCodeCode" : ""
} + \
-intCodeTemplate % {\
+longIntCodeTemplate % {\
"startLabel" : "longModeInterruptWithError",
"gateCheckType" : "IntGateCheck",
"errorCodeSize" : 8,
@@ -197,6 +501,24 @@
st t15, hs, [1, t0, t6], dataSize=8, addressSize=8
'''
} + \
+intCodeTemplate % {\
+ "startLabel" : "legacyModeInterrupt",
+ "gateCheckType" : "IntGateCheck",
+ "errorCodeSize" : 0,
+ "errorCodeCode" : "#"
+} + \
+intCodeTemplate % {\
+ "startLabel" : "legacyModeSoftInterrupt",
+ "gateCheckType" : "SoftIntGateCheck",
+ "errorCodeSize" : 0,
+ "errorCodeCode" : "#"
+} + \
+intCodeTemplate % {\
+ "startLabel" : "legacyModeInterruptWithError",
+ "gateCheckType" : "IntGateCheck",
+ "errorCodeSize" : 4,
+ "errorCodeCode" : 'st t15, ss, [1, t0, rsp]'
+} + \
'''
def rom
{
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/56326
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: Ib20f1a45d67c610176101820451ea1662ce17507
Gerrit-Change-Number: 56326
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <gabe.bl...@gmail.com>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- gem5-dev@gem5.org
To unsubscribe send an email to gem5-dev-le...@gem5.org
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s