linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: arnd@arndb.de
To: paulus@samba.org
Cc: linuxppc-dev@ozlabs.org, Jeremy Kerr <jk@ozlabs.org>
Subject: [POWERPC 17/18] cell: handle SPE kernel mappings that cross segment boundaries
Date: Tue, 18 Dec 2007 18:49:09 +0100	[thread overview]
Message-ID: <20071218175106.932751000@arndb.de> (raw)
In-Reply-To: 20071218174852.112644000@arndb.de

Currently, we have a possibilty that the SLBs setup during context
switch don't cover the entirety of the necessary lscsa and code
regions, if these regions cross a segment boundary.

This change checks the start and end of each region, and inserts a SLB
entry for each, if unique. We also remove the assumption that the
spu_save_code and spu_restore_code reside in the same segment, by using
the specific code array for save and restore.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/powerpc/platforms/cell/spu_base.c     |   50 ++++++++++++++++++++++++----
 arch/powerpc/platforms/cell/spufs/switch.c |   11 ++++--
 include/asm-powerpc/spu.h                  |    4 +-
 3 files changed, 52 insertions(+), 13 deletions(-)

Index: linux-2.6-new/arch/powerpc/platforms/cell/spu_base.c
===================================================================
--- linux-2.6-new.orig/arch/powerpc/platforms/cell/spu_base.c
+++ linux-2.6-new/arch/powerpc/platforms/cell/spu_base.c
@@ -275,19 +275,55 @@ static void __spu_kernel_slb(void *addr,
 }
 
 /**
+ * Given an array of @nr_slbs SLB entries, @slbs, return non-zero if the
+ * address @new_addr is present.
+ */
+static inline int __slb_present(struct spu_slb *slbs, int nr_slbs,
+		void *new_addr)
+{
+	unsigned long ea = (unsigned long)new_addr;
+	int i;
+
+	for (i = 0; i < nr_slbs; i++)
+		if (!((slbs[i].esid ^ ea) & ESID_MASK))
+			return 1;
+
+	return 0;
+}
+
+/**
  * Setup the SPU kernel SLBs, in preparation for a context save/restore. We
  * need to map both the context save area, and the save/restore code.
+ *
+ * Because the lscsa and code may cross segment boundaires, we check to see
+ * if mappings are required for the start and end of each range. We currently
+ * assume that the mappings are smaller that one segment - if not, something
+ * is seriously wrong.
  */
-void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa, void *code)
+void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa,
+		void *code, int code_size)
 {
-	struct spu_slb code_slb, lscsa_slb;
+	struct spu_slb slbs[4];
+	int i, nr_slbs = 0;
+	/* start and end addresses of both mappings */
+	void *addrs[] = {
+		lscsa, (void *)lscsa + sizeof(*lscsa) - 1,
+		code, code + code_size - 1
+	};
 
-	__spu_kernel_slb(lscsa, &lscsa_slb);
-	__spu_kernel_slb(code, &code_slb);
+	/* check the set of addresses, and create a new entry in the slbs array
+	 * if there isn't already a SLB for that address */
+	for (i = 0; i < ARRAY_SIZE(addrs); i++) {
+		if (__slb_present(slbs, nr_slbs, addrs[i]))
+			continue;
+
+		__spu_kernel_slb(addrs[i], &slbs[nr_slbs]);
+		nr_slbs++;
+	}
 
-	spu_load_slb(spu, 0, &lscsa_slb);
-	if (lscsa_slb.esid != code_slb.esid)
-		spu_load_slb(spu, 1, &code_slb);
+	/* Add the set of SLBs */
+	for (i = 0; i < nr_slbs; i++)
+		spu_load_slb(spu, i, &slbs[i]);
 }
 EXPORT_SYMBOL_GPL(spu_setup_kernel_slbs);
 
Index: linux-2.6-new/arch/powerpc/platforms/cell/spufs/switch.c
===================================================================
--- linux-2.6-new.orig/arch/powerpc/platforms/cell/spufs/switch.c
+++ linux-2.6-new/arch/powerpc/platforms/cell/spufs/switch.c
@@ -691,7 +691,8 @@ static inline void resume_mfc_queue(stru
 	out_be64(&priv2->mfc_control_RW, MFC_CNTL_RESUME_DMA_QUEUE);
 }
 
-static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu)
+static inline void setup_mfc_slbs(struct spu_state *csa, struct spu *spu,
+		unsigned int *code, int code_size)
 {
 	/* Save, Step 47:
 	 * Restore, Step 30.
@@ -708,7 +709,7 @@ static inline void setup_mfc_slbs(struct
 	 *     translation is desired by OS environment).
 	 */
 	spu_invalidate_slbs(spu);
-	spu_setup_kernel_slbs(spu, csa->lscsa, &spu_save_code);
+	spu_setup_kernel_slbs(spu, csa->lscsa, code, code_size);
 }
 
 static inline void set_switch_active(struct spu_state *csa, struct spu *spu)
@@ -1835,7 +1836,8 @@ static void save_lscsa(struct spu_state 
 	 */
 
 	resume_mfc_queue(prev, spu);	/* Step 46. */
-	setup_mfc_slbs(prev, spu);	/* Step 47. */
+	/* Step 47. */
+	setup_mfc_slbs(prev, spu, spu_save_code, sizeof(spu_save_code));
 	set_switch_active(prev, spu);	/* Step 48. */
 	enable_interrupts(prev, spu);	/* Step 49. */
 	save_ls_16kb(prev, spu);	/* Step 50. */
@@ -1940,7 +1942,8 @@ static void restore_lscsa(struct spu_sta
 	setup_spu_status_part1(next, spu);	/* Step 27. */
 	setup_spu_status_part2(next, spu);	/* Step 28. */
 	restore_mfc_rag(next, spu);	        /* Step 29. */
-	setup_mfc_slbs(next, spu);	        /* Step 30. */
+	/* Step 30. */
+	setup_mfc_slbs(next, spu, spu_restore_code, sizeof(spu_restore_code));
 	set_spu_npc(next, spu);	                /* Step 31. */
 	set_signot1(next, spu);	                /* Step 32. */
 	set_signot2(next, spu);	                /* Step 33. */
Index: linux-2.6-new/include/asm-powerpc/spu.h
===================================================================
--- linux-2.6-new.orig/include/asm-powerpc/spu.h
+++ linux-2.6-new/include/asm-powerpc/spu.h
@@ -201,8 +201,8 @@ int spu_irq_class_0_bottom(struct spu *s
 int spu_irq_class_1_bottom(struct spu *spu);
 void spu_irq_setaffinity(struct spu *spu, int cpu);
 
-void spu_setup_kernel_slbs(struct spu *spu,
-		struct spu_lscsa *lscsa, void *code);
+void spu_setup_kernel_slbs(struct spu *spu, struct spu_lscsa *lscsa,
+		void *code, int code_size);
 
 #ifdef CONFIG_KEXEC
 void crash_register_spus(struct list_head *list);

-- 

  parent reply	other threads:[~2007-12-18 17:49 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-12-18 17:48 [POWERPC 00/18] cell patches for 2.6.25 arnd
2007-12-18 17:48 ` [POWERPC 01/18] perfmon2: make pm_interval register read/write arnd
2007-12-18 17:48 ` [POWERPC 02/18] OProfile: fix cbe pm signal routing problem arnd
2007-12-18 17:48 ` [POWERPC 03/18] cell: add missing \n arnd
2007-12-18 17:48 ` [POWERPC 04/18] Set archdata.dma_data for direct DMA in cell_dma_dev_setup() arnd
2007-12-18 19:48   ` Benjamin Herrenschmidt
2007-12-18 17:48 ` [POWERPC 05/18] Add celleb_dma_dev_setup() arnd
2007-12-18 19:48   ` Benjamin Herrenschmidt
2007-12-18 17:48 ` [POWERPC 06/18] Use archdata.dma_data in dma_direct_ops arnd
2007-12-18 19:49   ` Benjamin Herrenschmidt
2007-12-18 17:48 ` [POWERPC 07/18] Have cell use its own dma_direct_offset variable arnd
2007-12-18 19:50   ` Benjamin Herrenschmidt
2007-12-18 17:49 ` [POWERPC 08/18] Have celleb " arnd
2007-12-18 19:50   ` Benjamin Herrenschmidt
2007-12-18 17:49 ` [POWERPC 09/18] Remove the global dma_direct_offset arnd
2007-12-18 19:52   ` Benjamin Herrenschmidt
2007-12-18 17:49 ` [POWERPC 10/18] Remove bogus comment in dma_direct_alloc_coherent() arnd
2007-12-18 19:52   ` Benjamin Herrenschmidt
2007-12-18 17:49 ` [POWERPC 11/18] cell: Convert #include of asm/of_{platform, device}.h into linux/of_{platform, device}.h arnd
2007-12-18 17:49 ` [POWERPC 12/18] cell: export force_sig_info() arnd
2007-12-18 17:49 ` [POWERPC 13/18] cell: safer of_has_vicinity routine arnd
2007-12-18 17:49 ` [POWERPC 14/18] cell: handle kernel SLB setup in spu_base.c arnd
2007-12-18 17:49 ` [POWERPC 15/18] cell: use spu_load_slb for SLB setup arnd
2007-12-18 17:49 ` [POWERPC 16/18] cell: add spu_64k_pages_available() check arnd
2007-12-18 17:49 ` arnd [this message]
2007-12-18 17:49 ` [POWERPC 18/18] cell: catch errors from sysfs_create_group() arnd
2007-12-18 20:24 ` [POWERPC 00/18] cell patches for 2.6.25 Arnd Bergmann
2007-12-19  0:11 ` Arnd Bergmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20071218175106.932751000@arndb.de \
    --to=arnd@arndb.de \
    --cc=jk@ozlabs.org \
    --cc=linuxppc-dev@ozlabs.org \
    --cc=paulus@samba.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).