X86: Ensure that the CPUID instruction always writes its outputs.
authorGabe Black <gblack@eecs.umich.edu>
Mon, 4 Jun 2012 17:43:09 +0000 (10:43 -0700)
committerGabe Black <gblack@eecs.umich.edu>
Mon, 4 Jun 2012 17:43:09 +0000 (10:43 -0700)
The CPUID instruction was implemented so that it would only write its results
if the instruction was successful. This works fine on the simple CPU where
unwritten registers retain their old values, but on a CPU like O3 with
renaming this is broken. The instruction needs to write the old values back
into the registers explicitly if they aren't being changed.

src/arch/x86/isa/decoder/two_byte_opcodes.isa
src/arch/x86/isa/formats/cpuid.isa

index 34b79a6a4c73d5bfd2a65b08d872ae39a36f4a3e..3b187d625d37b583539083d022e62ff9bb33edb8 100644 (file)
                 0x1: pop_fs();
                 0x2: CPUIDInst::CPUID({{
                     CpuidResult result;
-                    success = doCpuid(xc->tcBase(), bits(Rax, 31, 0),
+                    bool success = doCpuid(xc->tcBase(), bits(Rax, 31, 0),
                         bits(Rcx, 31, 0), result);
-                    Rax = result.rax;
-                    Rbx = result.rbx;
-                    Rcx = result.rcx;
-                    Rdx = result.rdx;
+                    if (success) {
+                        Rax = result.rax;
+                        Rbx = result.rbx;
+                        Rcx = result.rcx;
+                        Rdx = result.rdx;
+                    } else {
+                        Rax = Rax;
+                        Rbx = Rbx;
+                        Rcx = Rcx;
+                        Rdx = Rdx;
+                    }
                     }});
                 0x3: Inst::BT(Ev,Gv);
                 0x4: Inst::SHLD(Ev,Gv,Ib);
index cc3070dedf630d275ce9a4a2cc4c67404236b871..535f1e92515fa636135928fa410e101c6f78e66c 100644 (file)
@@ -73,13 +73,10 @@ def template CPUIDExecute {{
     {
         // 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;
-        }
+        %(op_wb)s;
         return NoFault;
     }
 }};