mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-07 11:28:32 +00:00
powerpc/64s/hash: Use POWER6 SLBIA IH=1 variant in switch_slb
The SLBIA IH=1 hint will remove all non-zero SLBEs, but only invalidate ERAT entries associated with a class value of 1, for processors that support the hint (e.g., POWER6 and newer), which Linux assigns to user addresses. This prevents kernel ERAT entries from being invalidated when context switchig (if the thread faulted in more than 8 user SLBEs). Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
85376e2a17
commit
5141c182d7
1 changed files with 23 additions and 15 deletions
|
@ -128,13 +128,21 @@ void slb_flush_all_realmode(void)
|
||||||
asm volatile("slbmte %0,%0; slbia" : : "r" (0));
|
asm volatile("slbmte %0,%0; slbia" : : "r" (0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __slb_flush_and_rebolt(void)
|
void slb_flush_and_rebolt(void)
|
||||||
{
|
{
|
||||||
/* If you change this make sure you change SLB_NUM_BOLTED
|
/* If you change this make sure you change SLB_NUM_BOLTED
|
||||||
* and PR KVM appropriately too. */
|
* and PR KVM appropriately too. */
|
||||||
unsigned long linear_llp, lflags;
|
unsigned long linear_llp, lflags;
|
||||||
unsigned long ksp_esid_data, ksp_vsid_data;
|
unsigned long ksp_esid_data, ksp_vsid_data;
|
||||||
|
|
||||||
|
WARN_ON(!irqs_disabled());
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can't take a PMU exception in the following code, so hard
|
||||||
|
* disable interrupts.
|
||||||
|
*/
|
||||||
|
hard_irq_disable();
|
||||||
|
|
||||||
linear_llp = mmu_psize_defs[mmu_linear_psize].sllp;
|
linear_llp = mmu_psize_defs[mmu_linear_psize].sllp;
|
||||||
lflags = SLB_VSID_KERNEL | linear_llp;
|
lflags = SLB_VSID_KERNEL | linear_llp;
|
||||||
|
|
||||||
|
@ -160,20 +168,7 @@ static void __slb_flush_and_rebolt(void)
|
||||||
:: "r"(ksp_vsid_data),
|
:: "r"(ksp_vsid_data),
|
||||||
"r"(ksp_esid_data)
|
"r"(ksp_esid_data)
|
||||||
: "memory");
|
: "memory");
|
||||||
}
|
|
||||||
|
|
||||||
void slb_flush_and_rebolt(void)
|
|
||||||
{
|
|
||||||
|
|
||||||
WARN_ON(!irqs_disabled());
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We can't take a PMU exception in the following code, so hard
|
|
||||||
* disable interrupts.
|
|
||||||
*/
|
|
||||||
hard_irq_disable();
|
|
||||||
|
|
||||||
__slb_flush_and_rebolt();
|
|
||||||
get_paca()->slb_cache_ptr = 0;
|
get_paca()->slb_cache_ptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,7 +313,20 @@ void switch_slb(struct task_struct *tsk, struct mm_struct *mm)
|
||||||
|
|
||||||
asm volatile("isync" : : : "memory");
|
asm volatile("isync" : : : "memory");
|
||||||
} else {
|
} else {
|
||||||
__slb_flush_and_rebolt();
|
struct slb_shadow *p = get_slb_shadow();
|
||||||
|
unsigned long ksp_esid_data =
|
||||||
|
be64_to_cpu(p->save_area[KSTACK_INDEX].esid);
|
||||||
|
unsigned long ksp_vsid_data =
|
||||||
|
be64_to_cpu(p->save_area[KSTACK_INDEX].vsid);
|
||||||
|
|
||||||
|
asm volatile("isync\n"
|
||||||
|
PPC_SLBIA(1) "\n"
|
||||||
|
"slbmte %0,%1\n"
|
||||||
|
"isync"
|
||||||
|
:: "r"(ksp_vsid_data),
|
||||||
|
"r"(ksp_esid_data));
|
||||||
|
|
||||||
|
asm volatile("isync" : : : "memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
get_paca()->slb_cache_ptr = 0;
|
get_paca()->slb_cache_ptr = 0;
|
||||||
|
|
Loading…
Reference in a new issue