All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: linuxppc-embedded@lists.linuxppc.org
Subject: Re: Another fix for xmon on non-standard MMU machines
Date: Tue, 11 Sep 2001 09:17:48 +1000	[thread overview]
Message-ID: <20010911091748.M4823@zax> (raw)
In-Reply-To: <20010910160600.21153@smtp.adsl.oleane.com>


On Mon, Sep 10, 2001 at 06:06:00PM +0200, Benjamin Herrenschmidt wrote:
> >This patch stops xmon from attempting to print the segment registers
> >on machines where CONFIG_PPC_STD_MMU is not set.  This prevents xmon
> >from causing an exception when the 'S' command is used on the 4xx (and
> >others).
>
> BTW, Did you figure out that userland stack problem ? Looks like we are
> both having the same issue, but I can't yet tell where it comes from...

Not entirely, but I've made progress.  Turns out the TLB miss handler
was broken in that:
    a) it set the TLB writable bit based only the _PAGE_DIRTY bit, but
a page can be dirty but still write-protected - in particular this
happens during the COW of the stack, so the two processes were sharing
their stack.
    b) it wasn't touching the _PAGE_ACCESSED bit.

The following patch is still buggy and needs a lot of cleaning up, but
it gets things slightly further:

diff -urN ../linuxppc_2_4_devel/arch/ppc/kernel/head_4xx.S linux-bungo/arch/ppc/kernel/head_4xx.S
--- ../linuxppc_2_4_devel/arch/ppc/kernel/head_4xx.S	Mon Sep 10 11:11:43 2001
+++ linux-bungo/arch/ppc/kernel/head_4xx.S	Mon Sep 10 19:27:13 2001
@@ -234,6 +234,8 @@
 	 */
 	andis.	r21, r20, 0x8000
 	beq	3f
+	li	r22, 0
+	mtspr	SPRN_PID, r22		/* TLB will have 0 TID */
 	lis	r21, swapper_pg_dir@h
 	ori	r21, r21, swapper_pg_dir@l
 	b	4f
@@ -270,11 +272,6 @@
 	 * Many of these bits are software only.  Bits we don't set
 	 * here we (properly should) assume have the appropriate value.
 	 */
-	andi.	r22, r21, _PAGE_SHARED
-	beq	5f
-	li	r22, 0
-	mtspr	SPRN_PID, r22		/* TLB will have 0 TID */
-5:
 	li	r22, 0x0c00
 	andc	r21, r21, r22		/* Make sure 20, 21 are zero */
 	ori	r21, r21, 0x02e0	/* TLB LO ready to go */
@@ -429,6 +426,7 @@
  * load TLB entries from the page table if they exist.
  */
 	START_EXCEPTION(0x1100,	DTLBMiss)
+	b	data_tlb_miss
 	mtspr	SPRG0, r20		/* Save some working registers */
 	mtspr	SPRG1, r21
 	mtspr	SPRG4, r22
@@ -444,6 +442,8 @@
 	 */
 	andis.	r21, r20, 0x8000
 	beq	3f
+	li	r22, 0
+	mtspr	SPRN_PID, r22		/* TLB will have 0 TID */
 	lis	r21, swapper_pg_dir@h
 	ori	r21, r21, swapper_pg_dir@l
 	b	4f
@@ -451,6 +451,13 @@
 	/* Get the PGD for the current thread.
 	 */
 3:
+	/* hack, hack, hack */
+	mfspr	r22, SPRN_PID
+	cmpwi	cr0,r22,0
+	bne	999f
+	/* Oh dear, we're attemping to access user addresses from the kernel when we oughtn't */
+	b	Trap_13
+999:
 	mfspr	r21,SPRG3
 	lwz	r21,PGDIR(r21)
 4:
@@ -474,11 +481,6 @@
 	 * Many of these bits are software only.  Bits we don't set
 	 * here we (properly should) assume have the appropriate value.
 	 */
-	andi.	r22, r21, _PAGE_SHARED
-	beq	5f
-	li	r22, 0
-	mtspr	SPRN_PID, r22		/* TLB will have 0 TID */
-5:
 	li	r22, 0x0c00
 	andc	r21, r21, r22		/* Make sure 20, 21 are zero */
 	ori	r21, r21, 0x02e0	/* TLB LO ready to go */
@@ -505,6 +507,7 @@
  * registers and bailout to a different point.
  */
 	START_EXCEPTION(0x1200,	ITLBMiss)
+	b	instruction_tlb_miss
 	mtspr	SPRG0, r20		/* Save some working registers */
 	mtspr	SPRG1, r21
 	mtspr	SPRG4, r22
@@ -520,6 +523,8 @@
 	 */
 	andis.	r21, r20, 0x8000
 	beq	3f
+	li	r22, 0
+	mtspr	SPRN_PID, r22		/* TLB will have 0 TID */
 	lis	r21, swapper_pg_dir@h
 	ori	r21, r21, swapper_pg_dir@l
 	b	4f
@@ -550,11 +555,6 @@
 	 * Many of these bits are software only.  Bits we don't set
 	 * here we (properly should) assume have the appropriate value.
 	 */
-	andi.	r22, r21, _PAGE_SHARED
-	beq	5f
-	li	r22, 0
-	mtspr	SPRN_PID, r22		/* TLB will have 0 TID */
-5:
 	li	r22, 0x0c00
 	andc	r21, r21, r22		/* Make sure 20, 21 are zero */
 	ori	r21, r21, 0x02e0	/* TLB LO ready to go */
@@ -672,6 +672,238 @@
  * reserved.
  */

+data_tlb_miss:
+	mtspr	SPRG0, r20		/* Save some working registers */
+	mtspr	SPRG1, r21
+	mtspr	SPRG4, r22
+	mtspr	SPRG5, r23
+	mfcr	r21
+	mfspr	r22, SPRN_PID
+	mtspr	SPRG7, r21
+	mtspr	SPRG6, r22
+
+	mfspr	r20, SPRN_DEAR		/* Get faulting address */
+	li	r23, _PAGE_PRESENT	/* permission mask */
+	mfspr	r22, SPRN_ESR		/* Is this a write access? */
+	rlwimi	r23, r22, 16, 24, 24	/* insert _PAGE_RW if necessary */
+
+	/* If we are faulting a kernel address, we have to use the
+	 * kernel page tables.
+	 */
+	andis.	r21, r20, 0x8000
+	beq	3f
+
+	/* kernel address */
+	li	r22, 0
+	mtspr	SPRN_PID, r22		/* TLB will have 0 TID */
+	lis	r21, swapper_pg_dir@h
+	ori	r21, r21, swapper_pg_dir@l
+	mfspr	r22, SPRN_SRR1		/* Get the MSR */
+	rlwimi	r23, r22, 22, 27, 27	/* _PAGE_USER if it's a userland access */
+	b	4f
+
+	/* Get the PGD for the current thread.
+	 */
+3:
+	ori	r23, r23, _PAGE_USER		/* always need _PAGE_USER for user addresses */
+	mfspr	r21,SPRG3
+	lwz	r21,PGDIR(r21)
+4:
+	tophys(r21, r21)
+	rlwimi	r21, r20, 12, 20, 29	/* Create L1 (pgdir/pmd) address */
+	lwz	r21, 0(r21)		/* Get L1 entry */
+	rlwinm.	r22, r21, 0, 0, 19	/* Extract L2 (pte) base address */
+	beq	2f			/* Bail if no table */
+
+	tophys(r22, r22)
+	rlwimi	r22, r20, 22, 20, 29	/* Compute PTE address */
+	lwz	r21, 0(r22)		/* Get Linux PTE */
+
+	andc.	r20, r23, r21		/* Do we have permission? */
+	bne	2f			/* If not, page fault */
+
+
+	rlwinm	r23, r23, 1, 23, 25	/* Make the mask to update the PTE */
+	or	r20, r21, r23		/* Update ACCESSED and maybe DIRTY */
+	stw	r20, 0(r22)		/* Write back to the PTE */
+
+	mfspr	r20, SPRN_DEAR		/* and restore the faulting address */
+
+	/* Most of the Linux PTE is ready to load into the TLB LO.
+	 * We set ZSEL, where only the LS-bit determines user access.
+	 * Many of these bits are software only.  Bits we don't set
+	 * here we (properly should) assume have the appropriate value.
+	 */
+	li	r22, 0x0c00
+	andc	r21, r21, r22		/* Make sure 20, 21 are zero */
+	ori	r21, r21, 0x00e0	/* TLB LO ready to go */
+
+	/* Since it has a unified TLB, and we can take data faults on
+	 * instruction pages by copying data, we have to check if the
+	 * EPN is already in the TLB.
+	 */
+	tlbsx.	r23, 0, r20
+	beq	6f
+
+	/* load the next available TLB index.
+	*/
+	lis	r22, tlb_4xx_index@h
+	ori	r22, r22, tlb_4xx_index@l
+	tophys(r22, r22)
+	lwz	r23, 0(r22)
+	addi	r23, r23, 1
+	andi.	r23, r23, (PPC4XX_TLB_SIZE-1)
+	stw	r23, 0(r22)
+
+6:
+	tlbwe	r21, r23, TLB_DATA		/* Load TLB LO */
+
+	/* Create EPN.  This is the faulting address plus a static
+	 * set of bits.  These are size, valid, E, U0, and ensure
+	 * bits 20 and 21 are zero.
+	 */
+	li	r22, 0x00c0
+	rlwimi	r20, r22, 0, 20, 31
+	tlbwe	r20, r23, TLB_TAG		/* Load TLB HI */
+
+	/* Done...restore registers and get out of here.
+	*/
+	mfspr	r22, SPRG6
+	mfspr	r21, SPRG7
+	mtspr	SPRN_PID, r22
+	mtcr	r21
+	mfspr	r23, SPRG5
+	mfspr	r22, SPRG4
+	mfspr	r21, SPRG1
+	mfspr	r20, SPRG0
+	rfi
+2:
+	/* The bailout.  Restore registers to pre-exception conditions
+	 * and call the heavyweights to help us out.
+	 */
+	mfspr	r22, SPRG6
+	mfspr	r21, SPRG7
+	mtspr	SPRN_PID, r22
+	mtcr	r21
+	mfspr	r23, SPRG5
+	mfspr	r22, SPRG4
+	mfspr	r21, SPRG1
+	mfspr	r20, SPRG0
+	b	DataAccess
+
+instruction_tlb_miss:
+	mtspr	SPRG0, r20		/* Save some working registers */
+	mtspr	SPRG1, r21
+	mtspr	SPRG4, r22
+	mtspr	SPRG5, r23
+	mfcr	r21
+	mfspr	r22, SPRN_PID
+	mtspr	SPRG7, r21
+	mtspr	SPRG6, r22
+
+	mfspr	r20, SPRN_SRR0		/* Get faulting address */
+	li	r23, _PAGE_PRESENT | _PAGE_EXEC	/* permission mask */
+
+	/* If we are faulting a kernel address, we have to use the
+	 * kernel page tables.
+	 */
+	andis.	r21, r20, 0x8000
+	beq	3f
+
+	/* kernel address */
+	li	r22, 0
+	mtspr	SPRN_PID, r22		/* TLB will have 0 TID */
+	lis	r21, swapper_pg_dir@h
+	ori	r21, r21, swapper_pg_dir@l
+	mfspr	r22, SPRN_SRR1		/* Get the MSR */
+	rlwimi	r23, r22, 22, 27, 27	/* _PAGE_USER if it's a userland access */
+	b	4f
+
+	/* Get the PGD for the current thread.
+	 */
+3:
+	ori	r23, r23, _PAGE_USER		/* always need _PAGE_USER for user addresses */
+	mfspr	r21,SPRG3
+	lwz	r21,PGDIR(r21)
+4:
+	tophys(r21, r21)
+	rlwimi	r21, r20, 12, 20, 29	/* Create L1 (pgdir/pmd) address */
+	lwz	r21, 0(r21)		/* Get L1 entry */
+	rlwinm.	r22, r21, 0, 0, 19	/* Extract L2 (pte) base address */
+	beq	2f			/* Bail if no table */
+
+	tophys(r22, r22)
+	rlwimi	r22, r20, 22, 20, 29	/* Compute PTE address */
+	lwz	r21, 0(r22)		/* Get Linux PTE */
+
+	andc.	r23, r23, r21		/* Do we have permission? */
+	bne	2f			/* If not, page fault */
+
+	ori	r23, r21, _PAGE_ACCESSED	/* Update ACCESSED and maybe DIRTY */
+	stw	r23, 0(r22)		/* Write back to the PTE */
+
+	/* Most of the Linux PTE is ready to load into the TLB LO.
+	 * We set ZSEL, where only the LS-bit determines user access.
+	 * Many of these bits are software only.  Bits we don't set
+	 * here we (properly should) assume have the appropriate value.
+	 */
+	li	r22, 0x0c00
+	andc	r21, r21, r22		/* Make sure 20, 21 are zero */
+	ori	r21, r21, 0x00e0	/* TLB LO ready to go */
+
+	/* Since it has a unified TLB, and we can take data faults on
+	 * instruction pages by copying data, we have to check if the
+	 * EPN is already in the TLB.
+	 */
+	tlbsx.	r23, 0, r20
+	beq	6f
+
+	/* load the next available TLB index.
+	*/
+	lis	r22, tlb_4xx_index@h
+	ori	r22, r22, tlb_4xx_index@l
+	tophys(r22, r22)
+	lwz	r23, 0(r22)
+	addi	r23, r23, 1
+	andi.	r23, r23, (PPC4XX_TLB_SIZE-1)
+	stw	r23, 0(r22)
+
+6:
+	tlbwe	r21, r23, TLB_DATA		/* Load TLB LO */
+
+	/* Create EPN.  This is the faulting address plus a static
+	 * set of bits.  These are size, valid, E, U0, and ensure
+	 * bits 20 and 21 are zero.
+	 */
+	li	r22, 0x00c0
+	rlwimi	r20, r22, 0, 20, 31
+	tlbwe	r20, r23, TLB_TAG		/* Load TLB HI */
+
+	/* Done...restore registers and get out of here.
+	*/
+	mfspr	r22, SPRG6
+	mfspr	r21, SPRG7
+	mtspr	SPRN_PID, r22
+	mtcr	r21
+	mfspr	r23, SPRG5
+	mfspr	r22, SPRG4
+	mfspr	r21, SPRG1
+	mfspr	r20, SPRG0
+	rfi
+2:
+	/* The bailout.  Restore registers to pre-exception conditions
+	 * and call the heavyweights to help us out.
+	 */
+	mfspr	r22, SPRG6
+	mfspr	r21, SPRG7
+	mtspr	SPRN_PID, r22
+	mtcr	r21
+	mfspr	r23, SPRG5
+	mfspr	r22, SPRG4
+	mfspr	r21, SPRG1
+	mfspr	r20, SPRG0
+	b	InstructionAccess
+
 	/* Damn, I came up one instruction too many to fit into the
 	 * exception space :-).  Both the instruction and data TLB
 	 * miss get to this point to load the TLB.
@@ -961,6 +1193,22 @@
 	stw	r4, 0x4(r5)
 #endif
 	mtspr	SPRN_PID,r3
+	blr
+
+_GLOBAL(tlb_lookup_x)
+	lwz	r10,0(r3)
+_GLOBAL(tlb_lookup)
+	tlbsx.	r11,0,r3
+	beq	31415f
+	li	r3,0	/* No valid tlb entry */
+	not	r3,r3
+	blr
+31415:
+	tlbre	r3,r11,TLB_DATA
+	blr
+
+_GLOBAL(pid_lookup)
+	mfspr	r3,SPRN_PID
 	blr

 /* We put a few things here that have to be page-aligned. This stuff
diff -urN ../linuxppc_2_4_devel/arch/ppc/mm/pgtable.c linux-bungo/arch/ppc/mm/pgtable.c
--- ../linuxppc_2_4_devel/arch/ppc/mm/pgtable.c	Tue Aug 28 15:06:37 2001
+++ linux-bungo/arch/ppc/mm/pgtable.c	Mon Sep 10 17:09:57 2001
@@ -204,7 +204,7 @@
 		/* On the MPC8xx, we want the page shared so we
 		 * don't get ASID compares on kernel space.
 		 */
-		f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED;
+		f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED | _PAGE_EXEC;
 #if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
 		/* Allows stub to set breakpoints everywhere */
 		f |= _PAGE_RW | _PAGE_DIRTY;
diff -urN ../linuxppc_2_4_devel/include/asm-ppc/pgtable.h linux-bungo/include/asm-ppc/pgtable.h
--- ../linuxppc_2_4_devel/include/asm-ppc/pgtable.h	Tue Aug 28 15:07:05 2001
+++ linux-bungo/include/asm-ppc/pgtable.h	Mon Sep 10 19:29:01 2001
@@ -217,16 +217,17 @@

 #if defined(CONFIG_4xx)
 /* Definitions for 4xx embedded chips. */
+/* Beware, there is deep magic in the ordering of these bits */
 #define	_PAGE_GUARDED	0x001	/* G: page is guarded from prefetch */
 #define	_PAGE_COHERENT	0x002	/* M: enforece memory coherence */
 #define	_PAGE_NO_CACHE	0x004	/* I: caching is inhibited */
 #define	_PAGE_WRITETHRU	0x008	/* W: caching is write-through */
 #define	_PAGE_USER	0x010	/* matches one of the zone permission bits */
-#define _PAGE_EXEC	0x020	/* software: i-cache coherency required */
-#define	_PAGE_PRESENT	0x040	/* software: PTE contains a translation */
-#define _PAGE_DIRTY	0x100	/* C: page changed */
-#define	_PAGE_RW	0x200	/* Writes permitted */
-#define _PAGE_ACCESSED	0x400	/* R: page referenced */
+#define	_PAGE_PRESENT	0x020	/* software: PTE contains a translation */
+#define _PAGE_ACCESSED	0x040	/* software: page referenced */
+#define _PAGE_RW	0x080	/* software: Writes permitted */
+#define _PAGE_DIRTY	0x100	/* WR: page changed */
+#define _PAGE_EXEC	0x200	/* EX: i-cache coherency required */

 #elif defined(CONFIG_8xx)
 /* Definitions for 8xx embedded chips. */
@@ -279,7 +280,7 @@
 #define _PAGE_BASE	_PAGE_PRESENT | _PAGE_ACCESSED
 #define _PAGE_WRENABLE	_PAGE_RW | _PAGE_DIRTY

-#define _PAGE_KERNEL	_PAGE_BASE | _PAGE_WRENABLE | _PAGE_SHARED
+#define _PAGE_KERNEL	_PAGE_BASE | _PAGE_WRENABLE | _PAGE_SHARED | _PAGE_EXEC
 #define _PAGE_IO	_PAGE_KERNEL | _PAGE_NO_CACHE | _PAGE_GUARDED

 #define PAGE_NONE	__pgprot(_PAGE_BASE)
@@ -291,7 +292,7 @@
 #define PAGE_COPY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)

 #define PAGE_KERNEL	__pgprot(_PAGE_KERNEL)
-#define PAGE_KERNEL_RO	__pgprot(_PAGE_BASE | _PAGE_SHARED)
+#define PAGE_KERNEL_RO	__pgprot(_PAGE_BASE | _PAGE_SHARED | _PAGE_EXEC)
 #define PAGE_KERNEL_CI	__pgprot(_PAGE_IO)

 /*


--
David Gibson			| For every complex problem there is a
david@gibson.dropbear.id.au	| solution which is simple, neat and
				| wrong.  -- H.L. Mencken
http://www.ozlabs.org/people/dgibson


** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

  parent reply	other threads:[~2001-09-10 23:17 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-09-10  9:47 Another fix for xmon on non-standard MMU machines David Gibson
     [not found] ` <20010910160600.21153@smtp.adsl.oleane.com>
2001-09-10 23:17   ` David Gibson [this message]
2001-09-11  0:16     ` Dan Malek
2001-09-11  1:04       ` David Gibson

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=20010911091748.M4823@zax \
    --to=david@gibson.dropbear.id.au \
    --cc=benh@kernel.crashing.org \
    --cc=linuxppc-embedded@lists.linuxppc.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.