[Skiboot] [PATCH] external/mambo: mce injection step over uninteresting states

Nicholas Piggin npiggin at gmail.com
Thu Jul 18 11:54:27 AEST 2019


The MCE injection/step test skips over MSR[RI]=0, as it's an
"uninteresting" state (leads to die/crash). MSR[ME]=0 is similarly
uninteresting. MSR[PR]=1 is not interesting to do fine grained
injection because all MSR[PR]=1 states are much the same, from
machine check point of view, so skip this too.

MSR[EE]=1 is often not very interesting, because the kernel is well
tested for interrupt re-entrancy by asynchronous interrupts in these
states. However it is possible for the machine check handler to have
bugs in MSR[EE]=1, so make it optional to disable this state.

This makes injection testing easier and faster.

This patch also adds a bit more output to exc_mce, including printing
the initial 0x200 instruction details which makes things much less
confusing when stepping through a machine check.

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 external/mambo/mambo_utils.tcl | 67 +++++++++++++++++++++++-----------
 1 file changed, 46 insertions(+), 21 deletions(-)

diff --git a/external/mambo/mambo_utils.tcl b/external/mambo/mambo_utils.tcl
index 1defe95ad..0518fe81c 100644
--- a/external/mambo/mambo_utils.tcl
+++ b/external/mambo/mambo_utils.tcl
@@ -562,6 +562,9 @@ proc exc_sreset { } {
     upvar #0 target_c c
     upvar #0 target_p p
 
+    set pc [mysim cpu $p:$c:$t display spr pc]
+    puts "\[$p:$c:$t\]: $pc injecting SRESET"
+
     # In case of recoverable MCE, idle wakeup always sets RI, others get
     # RI from current environment. For unrecoverable, RI would always be
     # clear by hardware.
@@ -601,6 +604,8 @@ proc exc_sreset { } {
     if { [expr [mysim cpu $p:$c:$t display spr pc] == 0x104 ] } {
 	sreset_trigger
     }
+
+    ipc $t $c $p
 }
 
 proc mce_trigger { args } {
@@ -642,7 +647,8 @@ proc exc_mce { { d_side 0 } { cause 0x5 } { recoverable 1 } } {
     upvar #0 target_c c
     upvar #0 target_p p
 
-#    puts "INJECTING MCE"
+    set pc [mysim cpu $p:$c:$t display spr pc]
+    puts "\[$p:$c:$t\]: $pc injecting MCE"
 
     # In case of recoverable MCE, idle wakeup always sets RI, others get
     # RI from current environment. For unrecoverable, RI would always be
@@ -698,6 +704,8 @@ proc exc_mce { { d_side 0 } { cause 0x5 } { recoverable 1 } } {
     if { [expr [mysim cpu $p:$c:$t display spr pc] == 0x204 ] } {
 	mce_trigger
     }
+
+    ipc $t $c $p
 }
 
 set R1 0
@@ -713,7 +721,7 @@ proc stop_stack_match { args } {
     set r1 [mysim cpu $p:$c:$t display gpr 1]
     if { $R1 == $r1 } {
         simstop
-        ipca
+        ipc $t $c $p
     }
 }
 
@@ -754,8 +762,16 @@ proc inject_mce_step { {nr 1} } {
     }
 }
 
-# inject if RI is set and step over one instruction, and repeat.
-proc inject_mce_step_ri { {nr 1} } {
+# inject if ME and RI is set and PR is clear, step over the MCE to the next
+# instruction, and repeat.
+# Optionally skip the MCE if EE is set, as it's less interesting and allows
+# faster test coverage (however some interesting cases can be missed here,
+# e.g., user copies that modify AMR).
+#
+# This also contains some logic to avoid always killing reservations and
+# halting progress, but it does not always work so sometimes you get caught
+# in a reservation loop and have to step out of it manually.
+proc inject_mce_step_skip { {nr 1} {skip_ee 0} } {
     upvar #0 target_t t
     upvar #0 target_c c
     upvar #0 target_p p
@@ -765,29 +781,38 @@ proc inject_mce_step_ri { {nr 1} } {
     set reserve_counter 0
 
     for { set i 0 } { $i < $nr } { incr i 1 } {
-        if { [expr [mysim cpu $p:$c:$t display spr msr] & 0x2] } {
-            # inject_mce
-            if { [mysim cpu $p:$c:$t display reservation] in { "none" } } {
+        # Skip the injection if MSR[RI]=0 or MSR[ME]=0 or MSR[PR]=1
+        if { [ expr {!([p msr] & 0x2) || !([p msr] & 0x1000) || ([p msr] & 0x4000) } ] } {
+            mysim step 1
+            continue
+        }
+
+        if { $skip_ee && ([p msr] & 0x8000)} {
+            mysim step 1
+            continue
+        }
+
+        # inject_mce
+        if { [mysim cpu $p:$c:$t display reservation] in { "none" } } {
+            inject_mce
+            mysim cpu $p:$c:$t set reservation none
+            if { $reserve_inject_skip } {
+                set reserve_inject 1
+                set reserve_inject_skip 0
+            }
+        } else {
+            if { $reserve_inject } {
                 inject_mce
                 mysim cpu $p:$c:$t set reservation none
-                if { $reserve_inject_skip } {
-                    set reserve_inject 1
-                    set reserve_inject_skip 0
-                }
+                set reserve_inject 0
             } else {
-                if { $reserve_inject } {
-                    inject_mce
+                set reserve_inject_skip 1
+                set reserve_counter [ expr $reserve_counter + 1 ]
+                if { $reserve_counter > 30 } {
                     mysim cpu $p:$c:$t set reservation none
-                    set reserve_inject 0
-                } else {
-                    set reserve_inject_skip 1
-                    set reserve_counter [ expr $reserve_counter + 1 ]
-                    if { $reserve_counter > 30 } {
-                        mysim cpu $p:$c:$t set reservation none
-                    }
                 }
             }
         }
-        s
+        mysim step 1
     }
 }
-- 
2.20.1



More information about the Skiboot mailing list