Commit ae08d237 authored by David Gibson's avatar David Gibson Committed by Linus Torvalds

[PATCH] POWER5 erratum workaround

Early POWER5 revisions (<DD2.1) have a problem requiring slbie
instructions to be repeated under some circumstances.  The patch below
adds a workaround (patch made by Anton Blanchard).
parent e3756200
...@@ -311,6 +311,7 @@ BEGIN_FTR_SECTION ...@@ -311,6 +311,7 @@ BEGIN_FTR_SECTION
beq 2f /* if yes, don't slbie it */ beq 2f /* if yes, don't slbie it */
oris r6,r6,0x0800 /* set C (class) bit */ oris r6,r6,0x0800 /* set C (class) bit */
slbie r6 slbie r6
slbie r6 /* Workaround POWER5 < DD2.1 issue */
2: 2:
END_FTR_SECTION_IFSET(CPU_FTR_SLB) END_FTR_SECTION_IFSET(CPU_FTR_SLB)
clrrdi r7,r8,THREAD_SHIFT /* base of new stack */ clrrdi r7,r8,THREAD_SHIFT /* base of new stack */
......
...@@ -474,14 +474,14 @@ static void preload_slb(struct task_struct *tsk, struct mm_struct *mm) ...@@ -474,14 +474,14 @@ static void preload_slb(struct task_struct *tsk, struct mm_struct *mm)
void flush_slb(struct task_struct *tsk, struct mm_struct *mm) void flush_slb(struct task_struct *tsk, struct mm_struct *mm)
{ {
unsigned long offset = __get_cpu_var(stab_cache_ptr); unsigned long offset = __get_cpu_var(stab_cache_ptr);
union {
unsigned long word0;
slb_dword0 data;
} esid_data;
if (offset <= NR_STAB_CACHE_ENTRIES) { if (offset <= NR_STAB_CACHE_ENTRIES) {
int i; int i;
union {
unsigned long word0;
slb_dword0 data;
} esid_data;
asm volatile("isync" : : : "memory"); asm volatile("isync" : : : "memory");
for (i = 0; i < offset; i++) { for (i = 0; i < offset; i++) {
esid_data.word0 = 0; esid_data.word0 = 0;
...@@ -493,6 +493,17 @@ void flush_slb(struct task_struct *tsk, struct mm_struct *mm) ...@@ -493,6 +493,17 @@ void flush_slb(struct task_struct *tsk, struct mm_struct *mm)
asm volatile("isync; slbia; isync" : : : "memory"); asm volatile("isync; slbia; isync" : : : "memory");
} }
/* Workaround POWER5 < DD2.1 issue */
if (offset == 1 || offset > NR_STAB_CACHE_ENTRIES) {
/*
* flush segment in EEH region, we dont normally access
* addresses in this region.
*/
esid_data.word0 = 0;
esid_data.data.esid = EEH_REGION_ID;
asm volatile("slbie %0" : : "r" (esid_data));
}
__get_cpu_var(stab_cache_ptr) = 0; __get_cpu_var(stab_cache_ptr) = 0;
preload_slb(tsk, mm); preload_slb(tsk, mm);
......
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