spufs: switchable spu contexts
PATCH 2/7 spufs: switchable spu contexts
Add some infrastructure for saving and restoring the context of an SPE. This patch creates a new structure that can hold the whole state of a physical SPE in memory. It also contains code that avoids races during the context switch and the binary code that is loaded to the SPU in order to access its registers.
The actual PPE- and SPE-side context switch code are two separate patches.
From: Mark Nutter <[email protected]>
Signed-off-by Arnd Bergmann <[email protected]>
--
arch/ppc64/kernel/spu_base.c | 27 ++ fs/spufs/Makefile | 4 fs/spufs/context.c | 18 + fs/spufs/spu_restore_dump.h_shipped | 342 ++++++++++++++++++++++++++++++++++++ fs/spufs/spu_save_dump.h_shipped | 290 ++++++++++++++++++++++++++++++ fs/spufs/spufs.h | 2 fs/spufs/switch.c | 174 ++++++++++++++++++ include/asm-ppc64/spu.h | 76 ++++++++ include/asm-ppc64/spu_csa.h | 256 ++++++++++++++++++++++++++ 9 files changed, 1185 insertions(+), 4 deletions(-)
arch/ppc64/kernel/spu_base.c +24 -3
@@ -62,7 +62,9 @@static void spu_restart_dma (struct spu *spu) {struct spu_priv2 __iomem *priv2 = spu->priv2; -out_be64 (&priv2->mfc_control_RW,MFC_CNTL_RESTART_DMA_COMMAND ); + +if (!test_bit (SPU_CONTEXT_SWITCH_PENDING_nr, &spu->flags)) +out_be64 (&priv2->mfc_control_RW,MFC_CNTL_RESTART_DMA_COMMAND ); }static int __spu_trap_data_seg (struct spu *spu,unsigned long ea)
@@ -72,6 +74,11 @@pr_debug ("%s\n" , __FUNCTION__); +if (test_bit (SPU_CONTEXT_SWITCH_ACTIVE_nr, &spu->flags)) { +printk ("%s: invalid access during switch!\n" , __func__); +return 1 ; + } +if (REGION_ID (ea) !=USER_REGION_ID ) {pr_debug ("invalid region access at %016lx\n" , ea);return 1 ;
@@ -98,6 +105,7 @@return 0 ; } +extern int hash_page (unsigned long ea,unsigned long access,unsigned long trap);//XXX static int __spu_trap_data_map (struct spu *spu,unsigned long ea) {unsigned long dsisr;
@@ -107,8 +115,21 @@ priv1 = spu->priv1; dsisr =in_be64 (&priv1->mfc_dsisr_RW); -wake_up (&spu->stop_wq); +/* Handle kernel space hash faults immediately. +User hash faults need to be deferred to process context. */ +if ((dsisr &MFC_DSISR_PTE_NOT_FOUND ) + &®ION_ID (ea) !=USER_REGION_ID + &&hash_page (ea, _PAGE_PRESENT,0x300 ) ==0 ) { +spu_restart_dma (spu); +return 0 ; + } + +if (test_bit (SPU_CONTEXT_SWITCH_ACTIVE_nr, &spu->flags)) { +printk ("%s: invalid access during switch!\n" , __func__); +return 1 ; + } +wake_up (&spu->stop_wq);return 0 ; }
@@ -378,7 +399,6 @@ }EXPORT_SYMBOL (spu_free); -extern int hash_page (unsigned long ea,unsigned long access,unsigned long trap);//XXX static int spu_handle_mm_fault (struct spu *spu) {struct spu_priv1 __iomem *priv1;
@@ -646,6 +666,7 @@ spu->slb_replace =0 ; spu->mm =NULL ; spu->class_0_pending =0 ; + spu->flags =0UL ;spin_lock_init (&spu->register_lock);out_be64 (&spu->priv1->mfc_sdr_RW,mfspr (SPRN_SDR1 ));
fs/spufs/Makefile +3 -1
@@ -1,3 +1,5 @@ obj-$(CONFIG_SPU_FS) += spufs.o -spufs-y += inode.o file.o context.o +spufs-y += inode.o file.o context.o switch.o + +$(obj)/switch.o: $(obj)/spu_save_dump.h $(obj)/spu_restore_dump.h
fs/spufs/context.c +18 -0
@@ -22,6 +22,7 @@#include <linux/slab.h> #include <asm/spu.h> +#include <asm/spu_csa.h> #include "spufs.h" struct spu_context *alloc_spu_context (void )
@@ -30,9 +31,25 @@ ctx =kmalloc (sizeof *ctx,GFP_KERNEL );if (!ctx) goto out; +/* Future enhancement: do not call spu_alloc() +* here. This step should be deferred until +* spu_run()!! +* +* More work needs to be done to read(), +* write(), mmap(), etc., so that operations +* are performed on CSA when the context is +* not currently being run. In this way we +* can support arbitrarily large number of +* entries in /spu, allow state queries, etc. +*/ ctx->spu =spu_alloc ();if (!ctx->spu) goto out_free; +spu_init_csa (&ctx->csa); +if (!ctx->csa.lscsa) { +spu_free (ctx->spu); + goto out_free; + }init_rwsem (&ctx->backing_sema);spin_lock_init (&ctx->mmio_lock);kref_init (&ctx->kref);
@@ -50,6 +67,7 @@ ctx = container_of(kref, struct spu_context, kref);if (ctx->spu)spu_free (ctx->spu); +spu_fini_csa (&ctx->csa);kfree (ctx); }
fs/spufs/spu_restore_dump.h_shipped +342 -0
342 lines not on this page · raw message
fs/spufs/spu_save_dump.h_shipped +290 -0
290 lines not on this page · raw message
fs/spufs/spufs.h +2 -0
@@ -28,6 +28,7 @@#include <linux/fs.h> #include <asm/spu.h> +#include <asm/spu_csa.h> /* The magic number for our file system */ enum {
@@ -36,6 +37,7 @@struct spu_context {struct spu *spu;/* pointer to a physical SPU */ +struct spu_state csa;/* SPU context save area. */ struct rw_semaphore backing_sema;/* protects the above */ spinlock_t mmio_lock;/* protects mmio access */
fs/spufs/switch.c +174 -0
174 lines not on this page · raw message
include/asm-ppc64/spu.h +76 -0
88 lines not on this page · raw message
include/asm-ppc64/spu_csa.h +256 -0
256 lines not on this page · raw message