* [RFC/PATCH] powerpc: Deal with 44x virtually tagged icache
@ 2007-10-30 5:16 Benjamin Herrenschmidt
2007-10-30 12:23 ` Josh Boyer
0 siblings, 1 reply; 4+ messages in thread
From: Benjamin Herrenschmidt @ 2007-10-30 5:16 UTC (permalink / raw)
To: linuxppc-dev
The 44x family has an interesting "feature" which is a virtually
tagged instruction cache (yuck !). So far, we haven't dealt with
it properly, which means we've been mostly lucky or people didn't
report the problems, unless people have been running custom patches
in their distro...
This is an attempt at fixing it properly. I chose to do it by
setting a global flag whenever we change a PTE that was previously
marked executable, and flush the entire instruction cache upon
return to user space when that happens.
This is a bit heavy handed, but it's hard to do more fine grained
flushes as the icbi instruction, on those processor, for some very
strange reasons (since the cache is virtually mapped) still requires
a valid TLB entry for reading in the target address space, which
isn't something I want to deal with.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Fortunately, we don't support SMP on these or this solution wouldn't
work.
It does mean we do a bit of over-flushing on swap but on the
other hand, the code is simple. Another option would have been
to do the iccci after any syscall that potentially unmaps or
changes a mapping, like sys_munmap, sys_mremap, sys_sbrk, but
also the shmem stuff etc... I decided there was just too many
and was worried I would miss one.
This not very tested as I don't have a test case at hand showing the
problem and didn't feel like writing one today :-) It boots though.
Careful eyes will notice I didn't do the flush on fast_exception_return,
which shouldn't be necessary.
arch/powerpc/kernel/entry_32.S | 25 +++++++++++++++++++++++++
arch/powerpc/kernel/misc_32.S | 9 +++++++++
arch/powerpc/mm/44x_mmu.c | 1 +
include/asm-powerpc/pgtable-ppc32.h | 13 +++++++++++++
4 files changed, 48 insertions(+)
Index: linux-work/arch/powerpc/kernel/entry_32.S
===================================================================
--- linux-work.orig/arch/powerpc/kernel/entry_32.S 2007-10-15 11:19:35.000000000 +1000
+++ linux-work/arch/powerpc/kernel/entry_32.S 2007-10-30 16:09:51.000000000 +1100
@@ -244,6 +244,13 @@ syscall_exit_cont:
andis. r10,r0,DBCR0_IC@h
bnel- load_dbcr0
#endif
+#ifdef CONFIG_44x
+ lis r4,icache_44x_need_flush@ha
+ lwz r5,icache_44x_need_flush@l(r4)
+ cmplwi cr0,r5,0
+ bne- 2f
+1:
+#endif /* CONFIG_44x */
stwcx. r0,0,r1 /* to clear the reservation */
lwz r4,_LINK(r1)
lwz r5,_CCR(r1)
@@ -259,6 +266,13 @@ syscall_exit_cont:
SYNC
RFI
+#ifdef CONFIG_44x
+2: li r7,0
+ iccci r0,r0
+ stw r7,icache_44x_need_flush@l(r4)
+ b 1b
+#endif /* CONFIG_44x */
+
66: li r3,-ENOSYS
b ret_from_syscall
@@ -683,6 +697,17 @@ resume_kernel:
/* interrupts are hard-disabled at this point */
restore:
+#ifdef CONFIG_44x
+ lis r4,icache_44x_need_flush@ha
+ lwz r5,icache_44x_need_flush@l(r4)
+ cmplwi cr0,r5,0
+ beq+ 1f
+ iccci r0,r0
+ li r6,0
+ iccci r0,r0
+ stw r6,icache_44x_need_flush@l(r4)
+1:
+#endif /* CONFIG_44x */
lwz r0,GPR0(r1)
lwz r2,GPR2(r1)
REST_4GPRS(3, r1)
Index: linux-work/arch/powerpc/mm/44x_mmu.c
===================================================================
--- linux-work.orig/arch/powerpc/mm/44x_mmu.c 2007-09-28 11:42:05.000000000 +1000
+++ linux-work/arch/powerpc/mm/44x_mmu.c 2007-10-30 15:30:50.000000000 +1100
@@ -35,6 +35,7 @@
*/
unsigned int tlb_44x_index; /* = 0 */
unsigned int tlb_44x_hwater = PPC44x_TLB_SIZE - 1 - PPC44x_EARLY_TLBS;
+int icache_44x_need_flush;
/*
* "Pins" a 256MB TLB entry in AS0 for kernel lowmem
Index: linux-work/include/asm-powerpc/pgtable-ppc32.h
===================================================================
--- linux-work.orig/include/asm-powerpc/pgtable-ppc32.h 2007-09-28 11:42:10.000000000 +1000
+++ linux-work/include/asm-powerpc/pgtable-ppc32.h 2007-10-30 15:30:50.000000000 +1100
@@ -11,6 +11,11 @@
extern unsigned long va_to_phys(unsigned long address);
extern pte_t *va_to_pte(unsigned long address);
extern unsigned long ioremap_bot, ioremap_base;
+
+#ifdef CONFIG_44x
+extern int icache_44x_need_flush;
+#endif
+
#endif /* __ASSEMBLY__ */
/*
@@ -562,6 +567,10 @@ static inline unsigned long pte_update(p
: "=&r" (old), "=&r" (tmp), "=m" (*p)
: "r" (p), "r" (clr), "r" (set), "m" (*p)
: "cc" );
+#ifdef CONFIG_44x
+ if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC))
+ icache_44x_need_flush = 1;
+#endif
return old;
}
#else
@@ -582,6 +591,10 @@ static inline unsigned long long pte_upd
: "=&r" (old), "=&r" (tmp), "=m" (*p)
: "r" (p), "r" ((unsigned long)(p) + 4), "r" (clr), "r" (set), "m" (*p)
: "cc" );
+#ifdef CONFIG_44x
+ if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC))
+ icache_44x_need_flush = 1;
+#endif
return old;
}
#endif
Index: linux-work/arch/powerpc/kernel/misc_32.S
===================================================================
--- linux-work.orig/arch/powerpc/kernel/misc_32.S 2007-10-30 15:15:03.000000000 +1100
+++ linux-work/arch/powerpc/kernel/misc_32.S 2007-10-30 15:30:50.000000000 +1100
@@ -543,12 +543,21 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_I
addi r3,r3,L1_CACHE_BYTES
bdnz 0b
sync
+#ifndef CONFIG_44x
+ /* We don't flush the icache on 44x. Those have a virtual icache
+ * and we don't have access to the virtual address here (it's
+ * not the page vaddr but where it's mapped in user space). The
+ * flushing of the icache on these is handled elsewhere, when
+ * a change in the address space occurs, before returning to
+ * user space
+ */
mtctr r4
1: icbi 0,r6
addi r6,r6,L1_CACHE_BYTES
bdnz 1b
sync
isync
+#endif /* CONFIG_44x */
blr
/*
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC/PATCH] powerpc: Deal with 44x virtually tagged icache
2007-10-30 5:16 [RFC/PATCH] powerpc: Deal with 44x virtually tagged icache Benjamin Herrenschmidt
@ 2007-10-30 12:23 ` Josh Boyer
2007-10-30 20:16 ` Benjamin Herrenschmidt
0 siblings, 1 reply; 4+ messages in thread
From: Josh Boyer @ 2007-10-30 12:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
On Tue, 30 Oct 2007 16:16:54 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> The 44x family has an interesting "feature" which is a virtually
> tagged instruction cache (yuck !). So far, we haven't dealt with
> it properly, which means we've been mostly lucky or people didn't
> report the problems, unless people have been running custom patches
> in their distro...
>
> This is an attempt at fixing it properly. I chose to do it by
> setting a global flag whenever we change a PTE that was previously
> marked executable, and flush the entire instruction cache upon
> return to user space when that happens.
>
> This is a bit heavy handed, but it's hard to do more fine grained
> flushes as the icbi instruction, on those processor, for some very
> strange reasons (since the cache is virtually mapped) still requires
> a valid TLB entry for reading in the target address space, which
> isn't something I want to deal with.
>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
>
> Fortunately, we don't support SMP on these or this solution wouldn't
> work.
We should mark 44x BROKEN on SMP in Kconfig.
>
> It does mean we do a bit of over-flushing on swap but on the
> other hand, the code is simple. Another option would have been
> to do the iccci after any syscall that potentially unmaps or
> changes a mapping, like sys_munmap, sys_mremap, sys_sbrk, but
> also the shmem stuff etc... I decided there was just too many
> and was worried I would miss one.
>
> This not very tested as I don't have a test case at hand showing the
> problem and didn't feel like writing one today :-) It boots though.
>
> Careful eyes will notice I didn't do the flush on fast_exception_return,
> which shouldn't be necessary.
>
> arch/powerpc/kernel/entry_32.S | 25 +++++++++++++++++++++++++
> arch/powerpc/kernel/misc_32.S | 9 +++++++++
> arch/powerpc/mm/44x_mmu.c | 1 +
> include/asm-powerpc/pgtable-ppc32.h | 13 +++++++++++++
> 4 files changed, 48 insertions(+)
No arch/ppc fix? I know we all want it to die as soon as possible, but
still... :)
> Index: linux-work/arch/powerpc/kernel/entry_32.S
> ===================================================================
> --- linux-work.orig/arch/powerpc/kernel/entry_32.S 2007-10-15 11:19:35.000000000 +1000
> +++ linux-work/arch/powerpc/kernel/entry_32.S 2007-10-30 16:09:51.000000000 +1100
> @@ -244,6 +244,13 @@ syscall_exit_cont:
> andis. r10,r0,DBCR0_IC@h
> bnel- load_dbcr0
> #endif
> +#ifdef CONFIG_44x
> + lis r4,icache_44x_need_flush@ha
> + lwz r5,icache_44x_need_flush@l(r4)
> + cmplwi cr0,r5,0
> + bne- 2f
> +1:
> +#endif /* CONFIG_44x */
> stwcx. r0,0,r1 /* to clear the reservation */
> lwz r4,_LINK(r1)
> lwz r5,_CCR(r1)
> @@ -259,6 +266,13 @@ syscall_exit_cont:
> SYNC
> RFI
>
> +#ifdef CONFIG_44x
> +2: li r7,0
> + iccci r0,r0
> + stw r7,icache_44x_need_flush@l(r4)
> + b 1b
> +#endif /* CONFIG_44x */
> +
> 66: li r3,-ENOSYS
> b ret_from_syscall
>
> @@ -683,6 +697,17 @@ resume_kernel:
>
> /* interrupts are hard-disabled at this point */
> restore:
> +#ifdef CONFIG_44x
> + lis r4,icache_44x_need_flush@ha
> + lwz r5,icache_44x_need_flush@l(r4)
> + cmplwi cr0,r5,0
> + beq+ 1f
> + iccci r0,r0
> + li r6,0
> + iccci r0,r0
> + stw r6,icache_44x_need_flush@l(r4)
> +1:
Why two iccci's here?
> +#endif /* CONFIG_44x */
> lwz r0,GPR0(r1)
> lwz r2,GPR2(r1)
> REST_4GPRS(3, r1)
> Index: linux-work/arch/powerpc/mm/44x_mmu.c
> ===================================================================
> --- linux-work.orig/arch/powerpc/mm/44x_mmu.c 2007-09-28 11:42:05.000000000 +1000
> +++ linux-work/arch/powerpc/mm/44x_mmu.c 2007-10-30 15:30:50.000000000 +1100
> @@ -35,6 +35,7 @@
> */
> unsigned int tlb_44x_index; /* = 0 */
> unsigned int tlb_44x_hwater = PPC44x_TLB_SIZE - 1 - PPC44x_EARLY_TLBS;
> +int icache_44x_need_flush;
>
> /*
> * "Pins" a 256MB TLB entry in AS0 for kernel lowmem
> Index: linux-work/include/asm-powerpc/pgtable-ppc32.h
> ===================================================================
> --- linux-work.orig/include/asm-powerpc/pgtable-ppc32.h 2007-09-28 11:42:10.000000000 +1000
> +++ linux-work/include/asm-powerpc/pgtable-ppc32.h 2007-10-30 15:30:50.000000000 +1100
> @@ -11,6 +11,11 @@
> extern unsigned long va_to_phys(unsigned long address);
> extern pte_t *va_to_pte(unsigned long address);
> extern unsigned long ioremap_bot, ioremap_base;
> +
> +#ifdef CONFIG_44x
> +extern int icache_44x_need_flush;
> +#endif
> +
> #endif /* __ASSEMBLY__ */
>
> /*
> @@ -562,6 +567,10 @@ static inline unsigned long pte_update(p
> : "=&r" (old), "=&r" (tmp), "=m" (*p)
> : "r" (p), "r" (clr), "r" (set), "m" (*p)
> : "cc" );
> +#ifdef CONFIG_44x
> + if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC))
> + icache_44x_need_flush = 1;
> +#endif
> return old;
> }
> #else
> @@ -582,6 +591,10 @@ static inline unsigned long long pte_upd
> : "=&r" (old), "=&r" (tmp), "=m" (*p)
> : "r" (p), "r" ((unsigned long)(p) + 4), "r" (clr), "r" (set), "m" (*p)
> : "cc" );
> +#ifdef CONFIG_44x
> + if ((old & _PAGE_USER) && (old & _PAGE_HWEXEC))
> + icache_44x_need_flush = 1;
> +#endif
> return old;
> }
> #endif
> Index: linux-work/arch/powerpc/kernel/misc_32.S
> ===================================================================
> --- linux-work.orig/arch/powerpc/kernel/misc_32.S 2007-10-30 15:15:03.000000000 +1100
> +++ linux-work/arch/powerpc/kernel/misc_32.S 2007-10-30 15:30:50.000000000 +1100
> @@ -543,12 +543,21 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_I
> addi r3,r3,L1_CACHE_BYTES
> bdnz 0b
> sync
> +#ifndef CONFIG_44x
> + /* We don't flush the icache on 44x. Those have a virtual icache
> + * and we don't have access to the virtual address here (it's
> + * not the page vaddr but where it's mapped in user space). The
> + * flushing of the icache on these is handled elsewhere, when
> + * a change in the address space occurs, before returning to
> + * user space
> + */
> mtctr r4
> 1: icbi 0,r6
> addi r6,r6,L1_CACHE_BYTES
> bdnz 1b
> sync
> isync
> +#endif /* CONFIG_44x */
> blr
>
> /*
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC/PATCH] powerpc: Deal with 44x virtually tagged icache
2007-10-30 12:23 ` Josh Boyer
@ 2007-10-30 20:16 ` Benjamin Herrenschmidt
2007-10-30 21:07 ` Josh Boyer
0 siblings, 1 reply; 4+ messages in thread
From: Benjamin Herrenschmidt @ 2007-10-30 20:16 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev
> > Fortunately, we don't support SMP on these or this solution wouldn't
> > work.
>
> We should mark 44x BROKEN on SMP in Kconfig.
Can we enable SMP on 44x at all currently ?
> No arch/ppc fix? I know we all want it to die as soon as possible, but
> still... :)
Yeah, I didn't do it yet, which is one reason this patch is marked
RFC :-)
> > /* interrupts are hard-disabled at this point */
> > restore:
> > +#ifdef CONFIG_44x
> > + lis r4,icache_44x_need_flush@ha
> > + lwz r5,icache_44x_need_flush@l(r4)
> > + cmplwi cr0,r5,0
> > + beq+ 1f
> > + iccci r0,r0
> > + li r6,0
> > + iccci r0,r0
> > + stw r6,icache_44x_need_flush@l(r4)
> > +1:
>
> Why two iccci's here?
No idea... thinko/typo.
Ben.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC/PATCH] powerpc: Deal with 44x virtually tagged icache
2007-10-30 20:16 ` Benjamin Herrenschmidt
@ 2007-10-30 21:07 ` Josh Boyer
0 siblings, 0 replies; 4+ messages in thread
From: Josh Boyer @ 2007-10-30 21:07 UTC (permalink / raw)
To: benh; +Cc: linuxppc-dev
On Wed, 31 Oct 2007 07:16:31 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
>
> > > Fortunately, we don't support SMP on these or this solution wouldn't
> > > work.
> >
> > We should mark 44x BROKEN on SMP in Kconfig.
>
> Can we enable SMP on 44x at all currently ?
Not without editing the Kconfig.cputypes file. I was thinking of being
a bit proactive so people didn't just add || 44x to it and think it
would work. But it's minor.
> > No arch/ppc fix? I know we all want it to die as soon as possible, but
> > still... :)
>
> Yeah, I didn't do it yet, which is one reason this patch is marked
> RFC :-)
Fair enough.
> > > /* interrupts are hard-disabled at this point */
> > > restore:
> > > +#ifdef CONFIG_44x
> > > + lis r4,icache_44x_need_flush@ha
> > > + lwz r5,icache_44x_need_flush@l(r4)
> > > + cmplwi cr0,r5,0
> > > + beq+ 1f
> > > + iccci r0,r0
> > > + li r6,0
> > > + iccci r0,r0
> > > + stw r6,icache_44x_need_flush@l(r4)
> > > +1:
> >
> > Why two iccci's here?
>
> No idea... thinko/typo.
And here I thought you were being extra careful ;)
josh
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-10-30 21:07 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-30 5:16 [RFC/PATCH] powerpc: Deal with 44x virtually tagged icache Benjamin Herrenschmidt
2007-10-30 12:23 ` Josh Boyer
2007-10-30 20:16 ` Benjamin Herrenschmidt
2007-10-30 21:07 ` Josh Boyer
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).