Commit d4c6e4e1 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: fix POWER3 boot

From: Anton Blanchard <anton@samba.org>

Binutils uses the recent mtcrf optimisation when compiling for a POWER4
target.  Unfortunately this causes a program check on POWER3.  We required
compiling for POWER4 so the tlbiel instruction would be recognised.

For the moment we hardwire the tlbiel instruction, longer term we can use the
binutils -many flag.
parent 820880f3
......@@ -72,6 +72,14 @@ config PPC64
bool
default y
config POWER4_ONLY
bool "Optimize for POWER4"
default n
---help---
Cause the compiler to optimize for POWER4 processors. The resulting
binary will not work on POWER3 or RS64 processors when compiled with
binutils 2.15 or later.
config SMP
bool "Symmetric multi-processing support"
---help---
......
......@@ -28,8 +28,13 @@ endif
LDFLAGS := -m elf64ppc
LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD)
CFLAGS += -msoft-float -pipe -Wno-uninitialized -mminimal-toc \
-mcpu=power4
CFLAGS += -msoft-float -pipe -Wno-uninitialized -mminimal-toc
ifeq ($(CONFIG_POWER4_ONLY),y)
CFLAGS += -mcpu=power4
else
CFLAGS += -mtune=power4
endif
have_zero_bss := $(shell if $(CC) -fno-zero-initialized-in-bss -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
......
......@@ -219,10 +219,10 @@ static long pSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
/* Ensure it is out of the tlb too */
if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
_tlbiel(va);
tlbiel(va);
} else {
spin_lock_irqsave(&pSeries_tlbie_lock, flags);
_tlbie(va, large);
tlbie(va, large);
spin_unlock_irqrestore(&pSeries_tlbie_lock, flags);
}
......@@ -256,7 +256,7 @@ static void pSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea)
/* Ensure it is out of the tlb too */
spin_lock_irqsave(&pSeries_tlbie_lock, flags);
_tlbie(va, 0);
tlbie(va, 0);
spin_unlock_irqrestore(&pSeries_tlbie_lock, flags);
}
......@@ -285,10 +285,10 @@ static void pSeries_hpte_invalidate(unsigned long slot, unsigned long va,
/* Invalidate the tlb */
if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
_tlbiel(va);
tlbiel(va);
} else {
spin_lock_irqsave(&pSeries_tlbie_lock, flags);
_tlbie(va, large);
tlbie(va, large);
spin_unlock_irqrestore(&pSeries_tlbie_lock, flags);
}
}
......@@ -350,12 +350,8 @@ static void pSeries_flush_hash_range(unsigned long context,
if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
asm volatile("ptesync":::"memory");
for (i = 0; i < j; i++) {
asm volatile("\n\
clrldi %0,%0,16\n\
tlbiel %0"
: : "r" (batch->vaddr[i]) : "memory" );
}
for (i = 0; i < j; i++)
__tlbiel(batch->vaddr[i]);
asm volatile("ptesync":::"memory");
} else {
......@@ -364,12 +360,8 @@ static void pSeries_flush_hash_range(unsigned long context,
asm volatile("ptesync":::"memory");
for (i = 0; i < j; i++) {
asm volatile("\n\
clrldi %0,%0,16\n\
tlbie %0"
: : "r" (batch->vaddr[i]) : "memory" );
}
for (i = 0; i < j; i++)
__tlbie(batch->vaddr[i], 0);
asm volatile("eieio; tlbsync; ptesync":::"memory");
......
......@@ -202,26 +202,46 @@ static inline unsigned long hpt_hash(unsigned long vpn, int large)
return (vsid & 0x7fffffffff) ^ page;
}
static inline void _tlbie(unsigned long va, int large)
static inline void __tlbie(unsigned long va, int large)
{
asm volatile("ptesync": : :"memory");
/* clear top 16 bits, non SLS segment */
va &= ~(0xffffULL << 48);
if (large) {
asm volatile("clrldi %0,%0,16\n\
tlbie %0,1" : : "r"(va) : "memory");
} else {
asm volatile("clrldi %0,%0,16\n\
tlbie %0,0" : : "r"(va) : "memory");
}
if (large)
asm volatile("tlbie %0,1" : : "r"(va) : "memory");
else
asm volatile("tlbie %0,0" : : "r"(va) : "memory");
}
static inline void tlbie(unsigned long va, int large)
{
asm volatile("ptesync": : :"memory");
__tlbie(va, large);
asm volatile("eieio; tlbsync; ptesync": : :"memory");
}
static inline void _tlbiel(unsigned long va)
static inline void __tlbiel(unsigned long va)
{
/* clear top 16 bits, non SLS segment */
va &= ~(0xffffULL << 48);
/*
* Thanks to Alan Modra we are now able to use machine specific
* assembly instructions (like tlbiel) by using the gas -many flag.
* However we have to support older toolchains so for the moment
* we hardwire it.
*/
#if 0
asm volatile("tlbiel %0" : : "r"(va) : "memory");
#else
asm volatile(".long 0x7c000224 | (%0 << 11)" : : "r"(va) : "memory");
#endif
}
static inline void tlbiel(unsigned long va)
{
asm volatile("ptesync": : :"memory");
asm volatile("clrldi %0,%0,16\n\
tlbiel %0" : : "r"(va) : "memory");
__tlbiel(va);
asm volatile("ptesync": : :"memory");
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment