[PATCH 1/2] Add support for stopping spus from xmon

Luke Browning LukeBrowning at us.ibm.com
Fri Oct 13 13:18:23 EST 2006


linuxppc-dev-bounces+lukebrowning=us.ibm.com at ozlabs.org wrote on 
10/12/2006 09:03:08 AM:

> This patch adds support for stopping, and restarting, spus
> from xmon. We use the spu master runcntl bit to stop execution,
> this is apparently the "right" way to control spu execution and
> spufs will be changed in the future to use this bit.
> 
> Testing has shown that to restart execution we have to turn the
> master runcntl bit on and also rewrite the spu runcntl bit, even
> if it is already set to 1 (running).
> 
> Stopping spus is triggered by the xmon command 'ss' - "spus stop"
> perhaps. Restarting them is triggered via 'sr'. Restart doesn't
> start execution on spus unless they were running prior to being
> stopped by xmon.
> 
> Walking the spu->full_list in xmon after a panic, would mean
> corruption of any spu struct would make all the others
> inaccessible. To avoid this, and also to make the next patch
> easier, we cache pointers to all spus during boot.

The spe affinity code drop created an array of spu pointers that
is indexed by spu->number.  We have a couple of other fields in
there that are needed for multiple spu scheduling operations. 
Maybe, you can use this array.  The name of the arry is lspu[]
for logical spus.

> 
> We attempt to catch and recover from errors while stopping and
> restarting the spus, but as with most xmon functionality there are
> no guarantees that performing these operations won't crash xmon
> itself.
> 
> Signed-off-by: Michael Ellerman <michael at ellerman.id.au>
> ---
> 
>  arch/powerpc/platforms/cell/spu_base.c |    4 
>  arch/powerpc/xmon/xmon.c               |  142 
> ++++++++++++++++++++++++++++++++-
>  include/asm-powerpc/xmon.h             |    2 
>  3 files changed, 146 insertions(+), 2 deletions(-)
> 
> Index: to-merge/arch/powerpc/platforms/cell/spu_base.c
> ===================================================================
> --- to-merge.orig/arch/powerpc/platforms/cell/spu_base.c
> +++ to-merge/arch/powerpc/platforms/cell/spu_base.c
> @@ -38,6 +38,7 @@
>  #include <asm/spu.h>
>  #include <asm/spu_priv1.h>
>  #include <asm/mmu_context.h>
> +#include <asm/xmon.h>
> 
>  #include "interrupt.h"
> 
> @@ -914,6 +915,9 @@ static int __init init_spu_base(void)
>           break;
>        }
>     }
> +
> +   xmon_register_spus(&spu_full_list);
> +
>     return ret;
>  }
>  module_init(init_spu_base);
> Index: to-merge/arch/powerpc/xmon/xmon.c
> ===================================================================
> --- to-merge.orig/arch/powerpc/xmon/xmon.c
> +++ to-merge/arch/powerpc/xmon/xmon.c
> @@ -35,6 +35,8 @@
>  #include <asm/rtas.h>
>  #include <asm/sstep.h>
>  #include <asm/bug.h>
> +#include <asm/spu.h>
> +#include <asm/spu_priv1.h>
> 
>  #ifdef CONFIG_PPC64
>  #include <asm/hvcall.h>
> @@ -145,6 +147,8 @@ static void xmon_print_symbol(unsigned l
>                 const char *after);
>  static const char *getvecname(unsigned long vec);
> 
> +static int do_spu_cmd(void);
> +
>  int xmon_no_auto_backtrace;
> 
>  extern int print_insn_powerpc(unsigned long, unsigned long, int);
> @@ -207,8 +211,12 @@ Commands:\n\
>    mi   show information about memory allocation\n\
>    p    call a procedure\n\
>    r   print registers\n\
> -  s   single step\n\
> -  S   print special registers\n\
> +  s   single step\n"
> +#ifdef CONFIG_PPC_CELL
> +"  ss   stop execution on all spus\n\
> +  sr   restore execution on stopped spus\n"
> +#endif
> +"  S   print special registers\n\
>    t   print backtrace\n\
>    x   exit monitor and recover\n\
>    X   exit monitor and dont recover\n"
> @@ -516,6 +524,7 @@ int xmon(struct pt_regs *excp)
>        xmon_save_regs(&regs);
>        excp = &regs;
>     }
> +
>     return xmon_core(excp, 0);
>  }
>  EXPORT_SYMBOL(xmon);
> @@ -808,6 +817,8 @@ cmds(struct pt_regs *excp)
>           cacheflush();
>           break;
>        case 's':
> +         if (do_spu_cmd() == 0)
> +            break;
>           if (do_step(excp))
>              return cmd;
>           break;
> @@ -2630,3 +2641,130 @@ void __init xmon_setup(void)
>     if (xmon_early)
>        debugger(NULL);
>  }
> +
> +#ifdef CONFIG_PPC_CELL
> +
> +struct spu_info {
> +   struct spu *spu;
> +   u64 saved_mfc_sr1_RW;
> +   u32 saved_spu_runcntl_RW;
> +   u8 stopped_ok;
> +};
> +
> +#define XMON_NUM_SPUS   16   /* Enough for current hardware */
> +
> +static struct spu_info spu_info[XMON_NUM_SPUS];
> +
> +void xmon_register_spus(struct list_head *list)
> +{
> +   struct spu *spu;
> +
> +   list_for_each_entry(spu, list, full_list) {
> +      if (spu->number >= XMON_NUM_SPUS) {
> +         WARN_ON(1);
> +         continue;
> +      }
> +
> +      spu_info[spu->number].spu = spu;
> +      spu_info[spu->number].stopped_ok = 0;
> +   }
> +}
> +
> +static void stop_spus(void)
> +{
> +   struct spu *spu;
> +   int i;
> +   u64 tmp;
> +
> +   for (i = 0; i < XMON_NUM_SPUS; i++) {
> +      if (!spu_info[i].spu)
> +         continue;
> +
> +      if (setjmp(bus_error_jmp) == 0) {
> +         catch_memory_errors = 1;
> +         sync();
> +
> +         spu = spu_info[i].spu;
> +
> +         spu_info[i].saved_spu_runcntl_RW =
> +            in_be32(&spu->problem->spu_runcntl_RW);
> +
> +         tmp = spu_mfc_sr1_get(spu);
> +         spu_info[i].saved_mfc_sr1_RW = tmp;
> +
> +         tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
> +         spu_mfc_sr1_set(spu, tmp);
> +
> +         sync();
> +         __delay(200);
> +
> +         spu_info[i].stopped_ok = 1;
> +         printf("Stopped spu %.2d\n", i);
> +      } else {
> +         catch_memory_errors = 0;
> +         printf("*** Error stopping spu %.2d\n", i);
> +      }
> +      catch_memory_errors = 0;
> +   }
> +}
> +
> +static void restart_spus(void)
> +{
> +   struct spu *spu;
> +   int i;
> +
> +   for (i = 0; i < XMON_NUM_SPUS; i++) {
> +      if (!spu_info[i].spu)
> +         continue;
> +
> +      if (!spu_info[i].stopped_ok) {
> +         printf("*** Error, spu %d was not successfully stopped"
> +               ", not restarting\n", i);
> +         continue;
> +      }
> +
> +      if (setjmp(bus_error_jmp) == 0) {
> +         catch_memory_errors = 1;
> +         sync();
> +
> +         spu = spu_info[i].spu;
> +         spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
> +         out_be32(&spu->problem->spu_runcntl_RW,
> +               spu_info[i].saved_spu_runcntl_RW);
> +
> +         sync();
> +         __delay(200);
> +
> +         printf("Restarted spu %.2d\n", i);
> +      } else {
> +         catch_memory_errors = 0;
> +         printf("*** Error restarting spu %.2d\n", i);
> +      }
> +      catch_memory_errors = 0;
> +   }
> +}
> +
> +static int do_spu_cmd(void)
> +{
> +   int cmd;
> +
> +   cmd = inchar();
> +   switch (cmd) {
> +   case 's':
> +      stop_spus();
> +      break;
> +   case 'r':
> +      restart_spus();
> +      break;
> +   default:
> +      return -1;
> +   }
> +
> +   return 0;
> +}
> +#else /* ! CONFIG_PPC_CELL */
> +static int do_spu_cmd(void)
> +{
> +   return -1;
> +}
> +#endif
> Index: to-merge/include/asm-powerpc/xmon.h
> ===================================================================
> --- to-merge.orig/include/asm-powerpc/xmon.h
> +++ to-merge/include/asm-powerpc/xmon.h
> @@ -14,8 +14,10 @@
> 
>  #ifdef CONFIG_XMON
>  extern void xmon_setup(void);
> +extern void xmon_register_spus(struct list_head *list);
>  #else
>  static inline void xmon_setup(void) { };
> +static inline void xmon_register_spus(struct list_head *list) { };
>  #endif
> 
>  #endif /* __KERNEL __ */
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ozlabs.org/pipermail/linuxppc-dev/attachments/20061013/720cd753/attachment.htm>


More information about the Linuxppc-dev mailing list