diff mbox series

external/mambo: improve helper for machine checks

Message ID 20180417062819.27106-1-npiggin@gmail.com
State Accepted
Headers show
Series external/mambo: improve helper for machine checks | expand

Commit Message

Nicholas Piggin April 17, 2018, 6:28 a.m. UTC
Improve workarounds for stop injection, because mambo often will
trigger on 0x104/204 when injecting sreset/mces.

This also adds a workaround to skip injecting on reservations to
avoid infinite loops when doing inject_mce_step.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 external/mambo/mambo_utils.tcl | 62 +++++++++++++++++++++++++++++-----
 1 file changed, 53 insertions(+), 9 deletions(-)

Comments

Balbir Singh April 17, 2018, 10:06 p.m. UTC | #1
On Tue, 17 Apr 2018 16:28:19 +1000
Nicholas Piggin <npiggin@gmail.com> wrote:

> Improve workarounds for stop injection, because mambo often will
> trigger on 0x104/204 when injecting sreset/mces.
> 
> This also adds a workaround to skip injecting on reservations to
> avoid infinite loops when doing inject_mce_step.
> 
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
>  external/mambo/mambo_utils.tcl | 62 +++++++++++++++++++++++++++++-----
>  1 file changed, 53 insertions(+), 9 deletions(-)
> 
> diff --git a/external/mambo/mambo_utils.tcl b/external/mambo/mambo_utils.tcl
> index 7a27f0f4..6cbb222a 100644
> --- a/external/mambo/mambo_utils.tcl
> +++ b/external/mambo/mambo_utils.tcl
> @@ -378,6 +378,7 @@ proc sreset_trigger { args } {
>      variable SRR1
>  
>      mysim trigger clear pc 0x100
> +    mysim trigger clear pc 0x104
>      set s [expr [mysim cpu 0 display spr srr1] & ~0x00000000003c0002]
>      set SRR1 [expr $SRR1 | $s]
>      mysim cpu 0 set spr srr1 $SRR1
> @@ -410,14 +411,23 @@ proc exc_sreset { } {
>  
>      if { [current_insn] in { "stop" "nap" "sleep" "winkle" } } {
>          # mambo has a quirk that interrupts from idle wake immediately
> +        # and go over current instruction.
>          mysim trigger set pc 0x100 "sreset_trigger"
> -        mysim cpu 0 interrupt MachineCheck
> -	# XXX: only trigger if pc is 0x100
> -	sreset_trigger
> +        mysim trigger set pc 0x104 "sreset_trigger"
> +        mysim cpu 0 interrupt SystemReset
>      } else {
>          mysim trigger set pc 0x100 "sreset_trigger"
> +        mysim trigger set pc 0x104 "sreset_trigger"
>          mysim cpu 0 interrupt SystemReset
>      }
> +
> +    # sleep and sometimes other types of interrupts do not trigger 0x100
> +    if { [expr [mysim cpu 0 display spr pc] == 0x100 ] } {
> +	sreset_trigger
> +    }
> +    if { [expr [mysim cpu 0 display spr pc] == 0x104 ] } {
> +	sreset_trigger
> +    }
>  }
>  
>  proc mce_trigger { args } {
> @@ -426,12 +436,13 @@ proc mce_trigger { args } {
>      variable DAR
>  
>      mysim trigger clear pc 0x200
> +    mysim trigger clear pc 0x204
>  
>      set s [expr [mysim cpu 0 display spr srr1] & ~0x00000000801f0002]
>      set SRR1 [expr $SRR1 | $s]
>      mysim cpu 0 set spr srr1 $SRR1
>      mysim cpu 0 set spr dsisr $DSISR
> -    mysim cpu 0 set spr dar $DAR
> +    mysim cpu 0 set spr dar $DAR ; list
>  }
>  
>  #
> @@ -451,6 +462,8 @@ proc exc_mce { { d_side 0 } { cause 0x5 } { recoverable 1 } } {
>      variable DSISR
>      variable DAR
>  
> +#    puts "INJECTING MCE"
> +
>      # 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.
> @@ -466,7 +479,6 @@ proc exc_mce { { d_side 0 } { cause 0x5 } { recoverable 1 } } {
>          set msr_ri 0x0
>      }
>  
> -    # recoverable d-side SLB multihit
>      if { $d_side } {
>          set is_dside 1
>          set SRR1_mc_cause 0x0
> @@ -489,14 +501,23 @@ proc exc_mce { { d_side 0 } { cause 0x5 } { recoverable 1 } } {
>  
>      if { [current_insn] in { "stop" "nap" "sleep" "winkle" } } {
>          # mambo has a quirk that interrupts from idle wake immediately
> +        # and go over current instruction.
>          mysim trigger set pc 0x200 "mce_trigger"
> +        mysim trigger set pc 0x204 "mce_trigger"
>          mysim cpu 0 interrupt MachineCheck
> -	# XXX: only trigger if pc is 0x200
> -	mce_trigger
>      } else {
>          mysim trigger set pc 0x200 "mce_trigger"
> +        mysim trigger set pc 0x204 "mce_trigger"
>          mysim cpu 0 interrupt MachineCheck
>      }
> +
> +    # sleep and sometimes other types of interrupts do not trigger 0x200
> +    if { [expr [mysim cpu 0 display spr pc] == 0x200 ] } {
> +	mce_trigger
> +    }
> +    if { [expr [mysim cpu 0 display spr pc] == 0x204 ] } {
> +	mce_trigger
> +    }
>  }
>  

Thesse bits look fine to me

Acked-by: Balbir Singh <bsingharora@gmail.com>
Stewart Smith April 20, 2018, 7:22 a.m. UTC | #2
Nicholas Piggin <npiggin@gmail.com> writes:
> Improve workarounds for stop injection, because mambo often will
> trigger on 0x104/204 when injecting sreset/mces.
>
> This also adds a workaround to skip injecting on reservations to
> avoid infinite loops when doing inject_mce_step.
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> ---
>  external/mambo/mambo_utils.tcl | 62 +++++++++++++++++++++++++++++-----
>  1 file changed, 53 insertions(+), 9 deletions(-)

Merged to master as of e148cb32cc2669b82f3cf4922ce3bf8caad88b60
diff mbox series

Patch

diff --git a/external/mambo/mambo_utils.tcl b/external/mambo/mambo_utils.tcl
index 7a27f0f4..6cbb222a 100644
--- a/external/mambo/mambo_utils.tcl
+++ b/external/mambo/mambo_utils.tcl
@@ -378,6 +378,7 @@  proc sreset_trigger { args } {
     variable SRR1
 
     mysim trigger clear pc 0x100
+    mysim trigger clear pc 0x104
     set s [expr [mysim cpu 0 display spr srr1] & ~0x00000000003c0002]
     set SRR1 [expr $SRR1 | $s]
     mysim cpu 0 set spr srr1 $SRR1
@@ -410,14 +411,23 @@  proc exc_sreset { } {
 
     if { [current_insn] in { "stop" "nap" "sleep" "winkle" } } {
         # mambo has a quirk that interrupts from idle wake immediately
+        # and go over current instruction.
         mysim trigger set pc 0x100 "sreset_trigger"
-        mysim cpu 0 interrupt MachineCheck
-	# XXX: only trigger if pc is 0x100
-	sreset_trigger
+        mysim trigger set pc 0x104 "sreset_trigger"
+        mysim cpu 0 interrupt SystemReset
     } else {
         mysim trigger set pc 0x100 "sreset_trigger"
+        mysim trigger set pc 0x104 "sreset_trigger"
         mysim cpu 0 interrupt SystemReset
     }
+
+    # sleep and sometimes other types of interrupts do not trigger 0x100
+    if { [expr [mysim cpu 0 display spr pc] == 0x100 ] } {
+	sreset_trigger
+    }
+    if { [expr [mysim cpu 0 display spr pc] == 0x104 ] } {
+	sreset_trigger
+    }
 }
 
 proc mce_trigger { args } {
@@ -426,12 +436,13 @@  proc mce_trigger { args } {
     variable DAR
 
     mysim trigger clear pc 0x200
+    mysim trigger clear pc 0x204
 
     set s [expr [mysim cpu 0 display spr srr1] & ~0x00000000801f0002]
     set SRR1 [expr $SRR1 | $s]
     mysim cpu 0 set spr srr1 $SRR1
     mysim cpu 0 set spr dsisr $DSISR
-    mysim cpu 0 set spr dar $DAR
+    mysim cpu 0 set spr dar $DAR ; list
 }
 
 #
@@ -451,6 +462,8 @@  proc exc_mce { { d_side 0 } { cause 0x5 } { recoverable 1 } } {
     variable DSISR
     variable DAR
 
+#    puts "INJECTING MCE"
+
     # 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.
@@ -466,7 +479,6 @@  proc exc_mce { { d_side 0 } { cause 0x5 } { recoverable 1 } } {
         set msr_ri 0x0
     }
 
-    # recoverable d-side SLB multihit
     if { $d_side } {
         set is_dside 1
         set SRR1_mc_cause 0x0
@@ -489,14 +501,23 @@  proc exc_mce { { d_side 0 } { cause 0x5 } { recoverable 1 } } {
 
     if { [current_insn] in { "stop" "nap" "sleep" "winkle" } } {
         # mambo has a quirk that interrupts from idle wake immediately
+        # and go over current instruction.
         mysim trigger set pc 0x200 "mce_trigger"
+        mysim trigger set pc 0x204 "mce_trigger"
         mysim cpu 0 interrupt MachineCheck
-	# XXX: only trigger if pc is 0x200
-	mce_trigger
     } else {
         mysim trigger set pc 0x200 "mce_trigger"
+        mysim trigger set pc 0x204 "mce_trigger"
         mysim cpu 0 interrupt MachineCheck
     }
+
+    # sleep and sometimes other types of interrupts do not trigger 0x200
+    if { [expr [mysim cpu 0 display spr pc] == 0x200 ] } {
+	mce_trigger
+    }
+    if { [expr [mysim cpu 0 display spr pc] == 0x204 ] } {
+	mce_trigger
+    }
 }
 
 global R1
@@ -536,11 +557,34 @@  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} } {
+    set reserve_inject 1
+    set reserve_inject_skip 0
+    set reserve_counter 0
+
     for { set i 0 } { $i < $nr } { incr i 1 } {
         if { [expr [mysim cpu 0 display spr msr] & 0x2] } {
-            inject_mce
+            # inject_mce
+            if { [mysim cpu 0 display reservation] in { "none" } } {
+                inject_mce
+                mysim cpu 0 set reservation none
+                if { $reserve_inject_skip } {
+                    set reserve_inject 1
+                    set reserve_inject_skip 0
+                }
+            } else {
+                if { $reserve_inject } {
+                    inject_mce
+                    mysim cpu 0 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 0 set reservation none
+                    }
+                }
+            }
         }
         s
     }
 }
-