<br><tt><font size=2>linuxppc-dev-bounces+lukebrowning=us.ibm.com@ozlabs.org
wrote on 10/12/2006 09:03:08 AM:<br>
<br>
&gt; This patch adds support for stopping, and restarting, spus<br>
&gt; from xmon. We use the spu master runcntl bit to stop execution,<br>
&gt; this is apparently the &quot;right&quot; way to control spu execution
and<br>
&gt; spufs will be changed in the future to use this bit.<br>
&gt; <br>
&gt; Testing has shown that to restart execution we have to turn the<br>
&gt; master runcntl bit on and also rewrite the spu runcntl bit, even<br>
&gt; if it is already set to 1 (running).<br>
&gt; <br>
&gt; Stopping spus is triggered by the xmon command 'ss' - &quot;spus stop&quot;<br>
&gt; perhaps. Restarting them is triggered via 'sr'. Restart doesn't<br>
&gt; start execution on spus unless they were running prior to being<br>
&gt; stopped by xmon.<br>
&gt; <br>
&gt; Walking the spu-&gt;full_list in xmon after a panic, would mean<br>
&gt; corruption of any spu struct would make all the others<br>
&gt; inaccessible. To avoid this, and also to make the next patch<br>
&gt; easier, we cache pointers to all spus during boot.<br>
</font></tt>
<br><tt><font size=2>The spe affinity code drop created an array of spu
pointers that</font></tt>
<br><tt><font size=2>is indexed by spu-&gt;number. &nbsp;We have a couple
of other fields in</font></tt>
<br><tt><font size=2>there that are needed for multiple spu scheduling
operations. &nbsp;</font></tt>
<br><tt><font size=2>Maybe, you can use this array. &nbsp;The name of the
arry is lspu[]</font></tt>
<br><tt><font size=2>for logical spus.</font></tt>
<br>
<br><tt><font size=2>&gt; <br>
&gt; We attempt to catch and recover from errors while stopping and<br>
&gt; restarting the spus, but as with most xmon functionality there are<br>
&gt; no guarantees that performing these operations won't crash xmon<br>
&gt; itself.<br>
&gt; <br>
&gt; Signed-off-by: Michael Ellerman &lt;michael@ellerman.id.au&gt;<br>
&gt; ---<br>
&gt; <br>
&gt; &nbsp;arch/powerpc/platforms/cell/spu_base.c | &nbsp; &nbsp;4 <br>
&gt; &nbsp;arch/powerpc/xmon/xmon.c &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; &nbsp; | &nbsp;142 <br>
&gt; ++++++++++++++++++++++++++++++++-<br>
&gt; &nbsp;include/asm-powerpc/xmon.h &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
&nbsp; | &nbsp; &nbsp;2 <br>
&gt; &nbsp;3 files changed, 146 insertions(+), 2 deletions(-)<br>
&gt; <br>
&gt; Index: to-merge/arch/powerpc/platforms/cell/spu_base.c<br>
&gt; ===================================================================<br>
&gt; --- to-merge.orig/arch/powerpc/platforms/cell/spu_base.c<br>
&gt; +++ to-merge/arch/powerpc/platforms/cell/spu_base.c<br>
&gt; @@ -38,6 +38,7 @@<br>
&gt; &nbsp;#include &lt;asm/spu.h&gt;<br>
&gt; &nbsp;#include &lt;asm/spu_priv1.h&gt;<br>
&gt; &nbsp;#include &lt;asm/mmu_context.h&gt;<br>
&gt; +#include &lt;asm/xmon.h&gt;<br>
&gt; &nbsp;<br>
&gt; &nbsp;#include &quot;interrupt.h&quot;<br>
&gt; &nbsp;<br>
&gt; @@ -914,6 +915,9 @@ static int __init init_spu_base(void)<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp;}<br>
&gt; &nbsp; &nbsp; }<br>
&gt; +<br>
&gt; + &nbsp; xmon_register_spus(&amp;spu_full_list);<br>
&gt; +<br>
&gt; &nbsp; &nbsp; return ret;<br>
&gt; &nbsp;}<br>
&gt; &nbsp;module_init(init_spu_base);<br>
&gt; Index: to-merge/arch/powerpc/xmon/xmon.c<br>
&gt; ===================================================================<br>
&gt; --- to-merge.orig/arch/powerpc/xmon/xmon.c<br>
&gt; +++ to-merge/arch/powerpc/xmon/xmon.c<br>
&gt; @@ -35,6 +35,8 @@<br>
&gt; &nbsp;#include &lt;asm/rtas.h&gt;<br>
&gt; &nbsp;#include &lt;asm/sstep.h&gt;<br>
&gt; &nbsp;#include &lt;asm/bug.h&gt;<br>
&gt; +#include &lt;asm/spu.h&gt;<br>
&gt; +#include &lt;asm/spu_priv1.h&gt;<br>
&gt; &nbsp;<br>
&gt; &nbsp;#ifdef CONFIG_PPC64<br>
&gt; &nbsp;#include &lt;asm/hvcall.h&gt;<br>
&gt; @@ -145,6 +147,8 @@ static void xmon_print_symbol(unsigned l<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const char
*after);<br>
&gt; &nbsp;static const char *getvecname(unsigned long vec);<br>
&gt; &nbsp;<br>
&gt; +static int do_spu_cmd(void);<br>
&gt; +<br>
&gt; &nbsp;int xmon_no_auto_backtrace;<br>
&gt; &nbsp;<br>
&gt; &nbsp;extern int print_insn_powerpc(unsigned long, unsigned long,
int);<br>
&gt; @@ -207,8 +211,12 @@ Commands:\n\<br>
&gt; &nbsp; &nbsp;mi &nbsp; show information about memory allocation\n\<br>
&gt; &nbsp; &nbsp;p &nbsp; &nbsp;call a procedure\n\<br>
&gt; &nbsp; &nbsp;r &nbsp; print registers\n\<br>
&gt; - &nbsp;s &nbsp; single step\n\<br>
&gt; - &nbsp;S &nbsp; print special registers\n\<br>
&gt; + &nbsp;s &nbsp; single step\n&quot;<br>
&gt; +#ifdef CONFIG_PPC_CELL<br>
&gt; +&quot; &nbsp;ss &nbsp; stop execution on all spus\n\<br>
&gt; + &nbsp;sr &nbsp; restore execution on stopped spus\n&quot;<br>
&gt; +#endif<br>
&gt; +&quot; &nbsp;S &nbsp; print special registers\n\<br>
&gt; &nbsp; &nbsp;t &nbsp; print backtrace\n\<br>
&gt; &nbsp; &nbsp;x &nbsp; exit monitor and recover\n\<br>
&gt; &nbsp; &nbsp;X &nbsp; exit monitor and dont recover\n&quot;<br>
&gt; @@ -516,6 +524,7 @@ int xmon(struct pt_regs *excp)<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp;xmon_save_regs(&amp;regs);<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp;excp = &amp;regs;<br>
&gt; &nbsp; &nbsp; }<br>
&gt; +<br>
&gt; &nbsp; &nbsp; return xmon_core(excp, 0);<br>
&gt; &nbsp;}<br>
&gt; &nbsp;EXPORT_SYMBOL(xmon);<br>
&gt; @@ -808,6 +817,8 @@ cmds(struct pt_regs *excp)<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cacheflush();<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp;case 's':<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; if (do_spu_cmd() == 0)<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (do_step(excp))<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return cmd;<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>
&gt; @@ -2630,3 +2641,130 @@ void __init xmon_setup(void)<br>
&gt; &nbsp; &nbsp; if (xmon_early)<br>
&gt; &nbsp; &nbsp; &nbsp; &nbsp;debugger(NULL);<br>
&gt; &nbsp;}<br>
&gt; +<br>
&gt; +#ifdef CONFIG_PPC_CELL<br>
&gt; +<br>
&gt; +struct spu_info {<br>
&gt; + &nbsp; struct spu *spu;<br>
&gt; + &nbsp; u64 saved_mfc_sr1_RW;<br>
&gt; + &nbsp; u32 saved_spu_runcntl_RW;<br>
&gt; + &nbsp; u8 stopped_ok;<br>
&gt; +};<br>
&gt; +<br>
&gt; +#define XMON_NUM_SPUS &nbsp; 16 &nbsp; /* Enough for current hardware
*/<br>
&gt; +<br>
&gt; +static struct spu_info spu_info[XMON_NUM_SPUS];<br>
&gt; +<br>
&gt; +void xmon_register_spus(struct list_head *list)<br>
&gt; +{<br>
&gt; + &nbsp; struct spu *spu;<br>
&gt; +<br>
&gt; + &nbsp; list_for_each_entry(spu, list, full_list) {<br>
&gt; + &nbsp; &nbsp; &nbsp;if (spu-&gt;number &gt;= XMON_NUM_SPUS) {<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; WARN_ON(1);<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; continue;<br>
&gt; + &nbsp; &nbsp; &nbsp;}<br>
&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp;spu_info[spu-&gt;number].spu = spu;<br>
&gt; + &nbsp; &nbsp; &nbsp;spu_info[spu-&gt;number].stopped_ok = 0;<br>
&gt; + &nbsp; }<br>
&gt; +}<br>
&gt; +<br>
&gt; +static void stop_spus(void)<br>
&gt; +{<br>
&gt; + &nbsp; struct spu *spu;<br>
&gt; + &nbsp; int i;<br>
&gt; + &nbsp; u64 tmp;<br>
&gt; +<br>
&gt; + &nbsp; for (i = 0; i &lt; XMON_NUM_SPUS; i++) {<br>
&gt; + &nbsp; &nbsp; &nbsp;if (!spu_info[i].spu)<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; continue;<br>
&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp;if (setjmp(bus_error_jmp) == 0) {<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; catch_memory_errors = 1;<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; sync();<br>
&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; spu = spu_info[i].spu;<br>
&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; spu_info[i].saved_spu_runcntl_RW =<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;in_be32(&amp;spu-&gt;problem-&gt;spu_runcntl_RW);<br>
&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; tmp = spu_mfc_sr1_get(spu);<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; spu_info[i].saved_mfc_sr1_RW = tmp;<br>
&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; tmp &amp;= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; spu_mfc_sr1_set(spu, tmp);<br>
&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; sync();<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; __delay(200);<br>
&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; spu_info[i].stopped_ok = 1;<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; printf(&quot;Stopped spu %.2d\n&quot;,
i);<br>
&gt; + &nbsp; &nbsp; &nbsp;} else {<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; catch_memory_errors = 0;<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; printf(&quot;*** Error stopping spu
%.2d\n&quot;, i);<br>
&gt; + &nbsp; &nbsp; &nbsp;}<br>
&gt; + &nbsp; &nbsp; &nbsp;catch_memory_errors = 0;<br>
&gt; + &nbsp; }<br>
&gt; +}<br>
&gt; +<br>
&gt; +static void restart_spus(void)<br>
&gt; +{<br>
&gt; + &nbsp; struct spu *spu;<br>
&gt; + &nbsp; int i;<br>
&gt; +<br>
&gt; + &nbsp; for (i = 0; i &lt; XMON_NUM_SPUS; i++) {<br>
&gt; + &nbsp; &nbsp; &nbsp;if (!spu_info[i].spu)<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; continue;<br>
&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp;if (!spu_info[i].stopped_ok) {<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; printf(&quot;*** Error, spu %d was not
successfully stopped&quot;<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;, not restarting\n&quot;,
i);<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; continue;<br>
&gt; + &nbsp; &nbsp; &nbsp;}<br>
&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp;if (setjmp(bus_error_jmp) == 0) {<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; catch_memory_errors = 1;<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; sync();<br>
&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; spu = spu_info[i].spu;<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; out_be32(&amp;spu-&gt;problem-&gt;spu_runcntl_RW,<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; spu_info[i].saved_spu_runcntl_RW);<br>
&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; sync();<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; __delay(200);<br>
&gt; +<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; printf(&quot;Restarted spu %.2d\n&quot;,
i);<br>
&gt; + &nbsp; &nbsp; &nbsp;} else {<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; catch_memory_errors = 0;<br>
&gt; + &nbsp; &nbsp; &nbsp; &nbsp; printf(&quot;*** Error restarting spu
%.2d\n&quot;, i);<br>
&gt; + &nbsp; &nbsp; &nbsp;}<br>
&gt; + &nbsp; &nbsp; &nbsp;catch_memory_errors = 0;<br>
&gt; + &nbsp; }<br>
&gt; +}<br>
&gt; +<br>
&gt; +static int do_spu_cmd(void)<br>
&gt; +{<br>
&gt; + &nbsp; int cmd;<br>
&gt; +<br>
&gt; + &nbsp; cmd = inchar();<br>
&gt; + &nbsp; switch (cmd) {<br>
&gt; + &nbsp; case 's':<br>
&gt; + &nbsp; &nbsp; &nbsp;stop_spus();<br>
&gt; + &nbsp; &nbsp; &nbsp;break;<br>
&gt; + &nbsp; case 'r':<br>
&gt; + &nbsp; &nbsp; &nbsp;restart_spus();<br>
&gt; + &nbsp; &nbsp; &nbsp;break;<br>
&gt; + &nbsp; default:<br>
&gt; + &nbsp; &nbsp; &nbsp;return -1;<br>
&gt; + &nbsp; }<br>
&gt; +<br>
&gt; + &nbsp; return 0;<br>
&gt; +}<br>
&gt; +#else /* ! CONFIG_PPC_CELL */<br>
&gt; +static int do_spu_cmd(void)<br>
&gt; +{<br>
&gt; + &nbsp; return -1;<br>
&gt; +}<br>
&gt; +#endif<br>
&gt; Index: to-merge/include/asm-powerpc/xmon.h<br>
&gt; ===================================================================<br>
&gt; --- to-merge.orig/include/asm-powerpc/xmon.h<br>
&gt; +++ to-merge/include/asm-powerpc/xmon.h<br>
&gt; @@ -14,8 +14,10 @@<br>
&gt; &nbsp;<br>
&gt; &nbsp;#ifdef CONFIG_XMON<br>
&gt; &nbsp;extern void xmon_setup(void);<br>
&gt; +extern void xmon_register_spus(struct list_head *list);<br>
&gt; &nbsp;#else<br>
&gt; &nbsp;static inline void xmon_setup(void) { };<br>
&gt; +static inline void xmon_register_spus(struct list_head *list) { };<br>
&gt; &nbsp;#endif<br>
&gt; &nbsp;<br>
&gt; &nbsp;#endif /* __KERNEL __ */<br>
&gt; _______________________________________________<br>
&gt; Linuxppc-dev mailing list<br>
&gt; Linuxppc-dev@ozlabs.org<br>
&gt; https://ozlabs.org/mailman/listinfo/linuxppc-dev<br>
</font></tt>