changeset cb5390385d87 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=cb5390385d87
description:
        x86: Fix implicit stack addressing in 64-bit mode

        When in 64-bit mode, if the stack is accessed implicitly by an 
instruction
        the alternate address prefix should be ignored if present.

        This patch adds an extra flag to the ldstop which signifies when the
        address override should be ignored. Then, for all of the affected
        instructions, this patch adds two options to the ld and st opcode to use
        the current stack addressing mode for all addresses and to ignore the
        AddressSizeFlagBit.  Finally, this patch updates the x86 TLB to not
        truncate the address if it is in 64-bit mode and the 
IgnoreAddrSizeFlagBit
        is set.

        This fixes a problem when calling __libc_start_main with a binary that 
is
        linked with a recent version of ld. This version of ld uses the address
        override prefix (0x67) on the call instruction instead of a nop.

        Note: This has not been tested in compatibility mode and only the call
        instruction with the address override prefix has been tested.

        See [1] page 9 (pdf page 45)

        For instructions that are affected see [1] page 519 (pdf page 555).

        [1] http://support.amd.com/TechDocs/24594.pdf

        Signed-off-by: Jason Lowe-Power <[email protected]>

diffstat:

 src/arch/x86/isa/insts/general_purpose/control_transfer/call.py          |   4 
+-
 src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py |  18 
+-
 src/arch/x86/isa/microops/ldstop.isa                                     |  82 
+++++++--
 3 files changed, 69 insertions(+), 35 deletions(-)

diffs (truncated from 314 to 300 lines):

diff -r 36b064696175 -r cb5390385d87 
src/arch/x86/isa/insts/general_purpose/control_transfer/call.py
--- a/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py   Fri Feb 
10 10:00:18 2017 -0500
+++ b/src/arch/x86/isa/insts/general_purpose/control_transfer/call.py   Fri Feb 
10 11:19:34 2017 -0500
@@ -45,7 +45,7 @@
     limm t1, imm
     rdip t7
     # Check target of call
-    st t7, ss, [0, t0, rsp], "-env.dataSize"
+    stis t7, ss, [0, t0, rsp], "-env.dataSize"
     subi rsp, rsp, ssz
     wrip t7, t1
 };
@@ -58,7 +58,7 @@
 
     rdip t1
     # Check target of call
-    st t1, ss, [0, t0, rsp], "-env.dataSize"
+    stis t1, ss, [0, t0, rsp], "-env.dataSize"
     subi rsp, rsp, ssz
     wripi reg, 0
 };
diff -r 36b064696175 -r cb5390385d87 
src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py
--- a/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py  
Fri Feb 10 10:00:18 2017 -0500
+++ b/src/arch/x86/isa/insts/general_purpose/data_transfer/stack_operations.py  
Fri Feb 10 11:19:34 2017 -0500
@@ -40,7 +40,7 @@
     # Make the default data size of pops 64 bits in 64 bit mode
     .adjust_env oszIn64Override
 
-    ld t1, ss, [1, t0, rsp], dataSize=ssz
+    ldis t1, ss, [1, t0, rsp], dataSize=ssz
     addi rsp, rsp, ssz, dataSize=asz
     mov reg, reg, t1
 };
@@ -49,7 +49,7 @@
     # Make the default data size of pops 64 bits in 64 bit mode
     .adjust_env oszIn64Override
 
-    ld t1, ss, [1, t0, rsp], dataSize=ssz
+    ldis 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
@@ -70,7 +70,7 @@
     # Make the default data size of pops 64 bits in 64 bit mode
     .adjust_env oszIn64Override
 
-    st reg, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
+    stis reg, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
     subi rsp, rsp, ssz
 };
 
@@ -79,7 +79,7 @@
     .adjust_env oszIn64Override
 
     limm t1, imm
-    st t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
+    stis t1, ss, [1, t0, rsp], "-env.stackSize", dataSize=ssz
     subi rsp, rsp, ssz
 };
 
@@ -138,7 +138,7 @@
     .adjust_env oszIn64Override
 
     mov t1, t1, rbp, dataSize=ssz
-    ld rbp, ss, [1, t0, t1], dataSize=ssz
+    ldis rbp, ss, [1, t0, t1], dataSize=ssz
     mov rsp, rsp, t1, dataSize=ssz
     addi rsp, rsp, ssz, dataSize=ssz
 };
@@ -156,7 +156,7 @@
     # t1 is now the masked nesting level, and t2 is the amount of storage.
 
     # Push rbp.
-    st rbp, ss, [1, t0, rsp], "-env.dataSize"
+    stis rbp, ss, [1, t0, rsp], "-env.dataSize"
     subi rsp, rsp, ssz
 
     # Save the stack pointer for later
@@ -172,8 +172,8 @@
 
     limm t4, "ULL(-1)", dataSize=8
 topOfLoop:
-    ld t5, ss, [dsz, t4, rbp]
-    st t5, ss, [1, t0, rsp], "-env.dataSize"
+    ldis t5, ss, [dsz, t4, rbp]
+    stis t5, ss, [1, t0, rsp], "-env.dataSize"
     subi rsp, rsp, ssz
 
     # If we're not done yet, loop
@@ -183,7 +183,7 @@
 
 bottomOfLoop:
     # Push the old rbp onto the stack
-    st t6, ss, [1, t0, rsp], "-env.dataSize"
+    stis t6, ss, [1, t0, rsp], "-env.dataSize"
     subi rsp, rsp, ssz
 
 skipLoop:
diff -r 36b064696175 -r cb5390385d87 src/arch/x86/isa/microops/ldstop.isa
--- a/src/arch/x86/isa/microops/ldstop.isa      Fri Feb 10 10:00:18 2017 -0500
+++ b/src/arch/x86/isa/microops/ldstop.isa      Fri Feb 10 11:19:34 2017 -0500
@@ -315,7 +315,8 @@
 let {{
     class LdStOp(X86Microop):
         def __init__(self, data, segment, addr, disp,
-                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec):
+                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
+                implicitStack):
             self.data = data
             [self.scale, self.index, self.base] = addr
             self.disp = disp
@@ -331,8 +332,11 @@
                 self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)"
             if nonSpec:
                 self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)"
-            self.memFlags += " | (machInst.legacy.addr ? " + \
-                             "(AddrSizeFlagBit << FlagShift) : 0)"
+            # For implicit stack operations, we should use *not* use the
+            # alternative addressing mode for loads/stores if the prefix is set
+            if not implicitStack:
+                self.memFlags += " | (machInst.legacy.addr ? " + \
+                                 "(AddrSizeFlagBit << FlagShift) : 0)"
 
         def getAllocator(self, microFlags):
             allocator = '''new %(class_name)s(machInst, macrocodeBlock,
@@ -351,7 +355,8 @@
 
     class BigLdStOp(X86Microop):
         def __init__(self, data, segment, addr, disp,
-                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec):
+                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
+                implicitStack):
             self.data = data
             [self.scale, self.index, self.base] = addr
             self.disp = disp
@@ -367,8 +372,11 @@
                 self.instFlags += " | (1ULL << StaticInst::IsDataPrefetch)"
             if nonSpec:
                 self.instFlags += " | (1ULL << StaticInst::IsNonSpeculative)"
-            self.memFlags += " | (machInst.legacy.addr ? " + \
-                             "(AddrSizeFlagBit << FlagShift) : 0)"
+            # For implicit stack operations, we should use *not* use the
+            # alternative addressing mode for loads/stores if the prefix is set
+            if not implicitStack:
+                self.memFlags += " | (machInst.legacy.addr ? " + \
+                                 "(AddrSizeFlagBit << FlagShift) : 0)"
 
         def getAllocator(self, microFlags):
             allocString = '''
@@ -395,9 +403,11 @@
 
     class LdStSplitOp(LdStOp):
         def __init__(self, data, segment, addr, disp,
-                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec):
+                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
+                implicitStack):
             super(LdStSplitOp, self).__init__(0, segment, addr, disp,
-                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec)
+                dataSize, addressSize, baseFlags, atCPL0, prefetch, nonSpec,
+                implicitStack)
             (self.dataLow, self.dataHi) = data
 
         def getAllocator(self, microFlags):
@@ -435,7 +445,8 @@
     calculateEA = 'EA = SegBase + ' + segmentEAExpr
 
     def defineMicroLoadOp(mnemonic, code, bigCode='',
-                          mem_flags="0", big=True, nonSpec=False):
+                          mem_flags="0", big=True, nonSpec=False,
+                          implicitStack=False):
         global header_output
         global decoder_output
         global exec_output
@@ -460,17 +471,26 @@
             exec_output += MicroLoadInitiateAcc.subst(iop)
             exec_output += MicroLoadCompleteAcc.subst(iop)
 
+        if implicitStack:
+            # For instructions that implicitly access the stack, the address
+            # size is the same as the stack segment pointer size, not the
+            # address size if specified by the instruction prefix
+            addressSize = "env.stackSize"
+        else:
+            addressSize = "env.addressSize"
+
         base = LdStOp
         if big:
             base = BigLdStOp
         class LoadOp(base):
             def __init__(self, data, segment, addr, disp = 0,
                     dataSize="env.dataSize",
-                    addressSize="env.addressSize",
-                    atCPL0=False, prefetch=False, nonSpec=nonSpec):
+                    addressSize=addressSize,
+                    atCPL0=False, prefetch=False, nonSpec=nonSpec,
+                    implicitStack=implicitStack):
                 super(LoadOp, self).__init__(data, segment, addr,
                         disp, dataSize, addressSize, mem_flags,
-                        atCPL0, prefetch, nonSpec)
+                        atCPL0, prefetch, nonSpec, implicitStack)
                 self.className = Name
                 self.mnemonic = name
 
@@ -478,6 +498,9 @@
 
     defineMicroLoadOp('Ld', 'Data = merge(Data, Mem, dataSize);',
                             'Data = Mem & mask(dataSize * 8);')
+    defineMicroLoadOp('Ldis', 'Data = merge(Data, Mem, dataSize);',
+                              'Data = Mem & mask(dataSize * 8);',
+                               implicitStack=True)
     defineMicroLoadOp('Ldst', 'Data = merge(Data, Mem, dataSize);',
                               'Data = Mem & mask(dataSize * 8);',
                       '(StoreCheck << FlagShift)')
@@ -544,10 +567,11 @@
             def __init__(self, data, segment, addr, disp = 0,
                     dataSize="env.dataSize",
                     addressSize="env.addressSize",
-                    atCPL0=False, prefetch=False, nonSpec=nonSpec):
+                    atCPL0=False, prefetch=False, nonSpec=nonSpec,
+                    implicitStack=False):
                 super(LoadOp, self).__init__(data, segment, addr,
                         disp, dataSize, addressSize, mem_flags,
-                        atCPL0, prefetch, nonSpec)
+                        atCPL0, prefetch, nonSpec, implicitStack)
                 self.className = Name
                 self.mnemonic = name
 
@@ -574,7 +598,8 @@
                            '(StoreCheck << FlagShift) | Request::LOCKED_RMW',
                            nonSpec=True)
 
-    def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0"):
+    def defineMicroStoreOp(mnemonic, code, completeCode="", mem_flags="0",
+                           implicitStack=False):
         global header_output
         global decoder_output
         global exec_output
@@ -594,20 +619,30 @@
         exec_output += MicroStoreInitiateAcc.subst(iop)
         exec_output += MicroStoreCompleteAcc.subst(iop)
 
+        if implicitStack:
+            # For instructions that implicitly access the stack, the address
+            # size is the same as the stack segment pointer size, not the
+            # address size if specified by the instruction prefix
+            addressSize = "env.stackSize"
+        else:
+            addressSize = "env.addressSize"
+
         class StoreOp(LdStOp):
             def __init__(self, data, segment, addr, disp = 0,
                     dataSize="env.dataSize",
-                    addressSize="env.addressSize",
-                    atCPL0=False, nonSpec=False):
+                    addressSize=addressSize,
+                    atCPL0=False, nonSpec=False, implicitStack=implicitStack):
                 super(StoreOp, self).__init__(data, segment, addr, disp,
                         dataSize, addressSize, mem_flags, atCPL0, False,
-                        nonSpec)
+                        nonSpec, implicitStack)
                 self.className = Name
                 self.mnemonic = name
 
         microopClasses[name] = StoreOp
 
     defineMicroStoreOp('St', 'Mem = pick(Data, 2, dataSize);')
+    defineMicroStoreOp('Stis', 'Mem = pick(Data, 2, dataSize);',
+                       implicitStack=True)
     defineMicroStoreOp('Stul', 'Mem = pick(Data, 2, dataSize);',
             mem_flags="Request::LOCKED_RMW")
 
@@ -655,10 +690,10 @@
             def __init__(self, data, segment, addr, disp = 0,
                     dataSize="env.dataSize",
                     addressSize="env.addressSize",
-                    atCPL0=False, nonSpec=False):
+                    atCPL0=False, nonSpec=False, implicitStack=False):
                 super(StoreOp, self).__init__(data, segment, addr, disp,
                         dataSize, addressSize, mem_flags, atCPL0, False,
-                        nonSpec)
+                        nonSpec, implicitStack)
                 self.className = Name
                 self.mnemonic = name
 
@@ -694,7 +729,7 @@
         def __init__(self, data, segment, addr, disp = 0,
                 dataSize="env.dataSize", addressSize="env.addressSize"):
             super(LeaOp, self).__init__(data, segment, addr, disp,
-                    dataSize, addressSize, "0", False, False, False)
+                    dataSize, addressSize, "0", False, False, False, False)
             self.className = "Lea"
             self.mnemonic = "lea"
 
@@ -715,7 +750,7 @@
                 addressSize="env.addressSize"):
             super(TiaOp, self).__init__("InstRegIndex(NUM_INTREGS)", segment,
                     addr, disp, dataSize, addressSize, "0", False, False,
-                    False)
+                    False, False)
             self.className = "Tia"
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to