diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2007-10-31 01:42:19 -0400 |
---|---|---|
committer | Josh Boyer <jwboyer@linux.vnet.ibm.com> | 2007-11-01 08:15:30 -0400 |
commit | b98ac05d5e460301fbea24cceed0f2a601c82e22 (patch) | |
tree | 2e556ad28a007d13339300fbbd4942d0ec9f023c /arch/powerpc/kernel/entry_32.S | |
parent | e701d269aa28996f3502780951fe1b12d5d66b49 (diff) |
[POWERPC] 4xx: Deal with 44x virtually tagged icache
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>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Diffstat (limited to 'arch/powerpc/kernel/entry_32.S')
-rw-r--r-- | arch/powerpc/kernel/entry_32.S | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 21d889e63e87..a7572cf464bd 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -244,6 +244,13 @@ syscall_exit_cont: | |||
244 | andis. r10,r0,DBCR0_IC@h | 244 | andis. r10,r0,DBCR0_IC@h |
245 | bnel- load_dbcr0 | 245 | bnel- load_dbcr0 |
246 | #endif | 246 | #endif |
247 | #ifdef CONFIG_44x | ||
248 | lis r4,icache_44x_need_flush@ha | ||
249 | lwz r5,icache_44x_need_flush@l(r4) | ||
250 | cmplwi cr0,r5,0 | ||
251 | bne- 2f | ||
252 | 1: | ||
253 | #endif /* CONFIG_44x */ | ||
247 | stwcx. r0,0,r1 /* to clear the reservation */ | 254 | stwcx. r0,0,r1 /* to clear the reservation */ |
248 | lwz r4,_LINK(r1) | 255 | lwz r4,_LINK(r1) |
249 | lwz r5,_CCR(r1) | 256 | lwz r5,_CCR(r1) |
@@ -258,6 +265,12 @@ syscall_exit_cont: | |||
258 | mtspr SPRN_SRR1,r8 | 265 | mtspr SPRN_SRR1,r8 |
259 | SYNC | 266 | SYNC |
260 | RFI | 267 | RFI |
268 | #ifdef CONFIG_44x | ||
269 | 2: li r7,0 | ||
270 | iccci r0,r0 | ||
271 | stw r7,icache_44x_need_flush@l(r4) | ||
272 | b 1b | ||
273 | #endif /* CONFIG_44x */ | ||
261 | 274 | ||
262 | 66: li r3,-ENOSYS | 275 | 66: li r3,-ENOSYS |
263 | b ret_from_syscall | 276 | b ret_from_syscall |
@@ -683,6 +696,16 @@ resume_kernel: | |||
683 | 696 | ||
684 | /* interrupts are hard-disabled at this point */ | 697 | /* interrupts are hard-disabled at this point */ |
685 | restore: | 698 | restore: |
699 | #ifdef CONFIG_44x | ||
700 | lis r4,icache_44x_need_flush@ha | ||
701 | lwz r5,icache_44x_need_flush@l(r4) | ||
702 | cmplwi cr0,r5,0 | ||
703 | beq+ 1f | ||
704 | li r6,0 | ||
705 | iccci r0,r0 | ||
706 | stw r6,icache_44x_need_flush@l(r4) | ||
707 | 1: | ||
708 | #endif /* CONFIG_44x */ | ||
686 | lwz r0,GPR0(r1) | 709 | lwz r0,GPR0(r1) |
687 | lwz r2,GPR2(r1) | 710 | lwz r2,GPR2(r1) |
688 | REST_4GPRS(3, r1) | 711 | REST_4GPRS(3, r1) |