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