mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-06 10:57:46 +00:00
powerpc/32s: Convert switch_mmu_context() to C
switch_mmu_context() does things that can easily be done in C.
For updating user segments, we have update_user_segments().
As mentionned in commit b5efec00b6
("powerpc/32s: Move KUEP
locking/unlocking in C"), update_user_segments() has the loop
unrolled which is a significant performance gain.
Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/05c0875ad8220c03452c3a334946e207c6ca04d6.1622708530.git.christophe.leroy@csgroup.eu
This commit is contained in:
parent
7235bb3593
commit
863771a28e
4 changed files with 40 additions and 63 deletions
|
@ -7,6 +7,11 @@
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
static __always_inline bool kuap_is_disabled(void)
|
||||||
|
{
|
||||||
|
return !IS_ENABLED(CONFIG_PPC_KUAP);
|
||||||
|
}
|
||||||
|
|
||||||
static __always_inline bool kuep_is_disabled(void)
|
static __always_inline bool kuep_is_disabled(void)
|
||||||
{
|
{
|
||||||
return !IS_ENABLED(CONFIG_PPC_KUEP);
|
return !IS_ENABLED(CONFIG_PPC_KUEP);
|
||||||
|
|
|
@ -86,7 +86,6 @@ int main(void)
|
||||||
OFFSET(PACA_CANARY, paca_struct, canary);
|
OFFSET(PACA_CANARY, paca_struct, canary);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
OFFSET(MMCONTEXTID, mm_struct, context.id);
|
|
||||||
#ifdef CONFIG_PPC32
|
#ifdef CONFIG_PPC32
|
||||||
#ifdef CONFIG_PPC_RTAS
|
#ifdef CONFIG_PPC_RTAS
|
||||||
OFFSET(RTAS_SP, thread_struct, rtas_sp);
|
OFFSET(RTAS_SP, thread_struct, rtas_sp);
|
||||||
|
@ -323,10 +322,6 @@ int main(void)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_PPC64
|
|
||||||
OFFSET(MM_PGD, mm_struct, pgd);
|
|
||||||
#endif /* ! CONFIG_PPC64 */
|
|
||||||
|
|
||||||
/* About the CPU features table */
|
/* About the CPU features table */
|
||||||
OFFSET(CPU_SPEC_FEATURES, cpu_spec, cpu_features);
|
OFFSET(CPU_SPEC_FEATURES, cpu_spec, cpu_features);
|
||||||
OFFSET(CPU_SPEC_SETUP, cpu_spec, cpu_setup);
|
OFFSET(CPU_SPEC_SETUP, cpu_spec, cpu_setup);
|
||||||
|
|
|
@ -1033,58 +1033,6 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_HPTE_TABLE)
|
||||||
mtspr SPRN_SRR1,r4
|
mtspr SPRN_SRR1,r4
|
||||||
rfi
|
rfi
|
||||||
|
|
||||||
/*
|
|
||||||
* void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next);
|
|
||||||
*
|
|
||||||
* Set up the segment registers for a new context.
|
|
||||||
*/
|
|
||||||
_ENTRY(switch_mmu_context)
|
|
||||||
lwz r3,MMCONTEXTID(r4)
|
|
||||||
cmpwi cr0,r3,0
|
|
||||||
blt- 4f
|
|
||||||
mulli r3,r3,897 /* multiply context by skew factor */
|
|
||||||
rlwinm r3,r3,4,8,27 /* VSID = (context & 0xfffff) << 4 */
|
|
||||||
#ifdef CONFIG_PPC_KUEP
|
|
||||||
oris r3, r3, SR_NX@h /* Set Nx */
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_PPC_KUAP
|
|
||||||
oris r3, r3, SR_KS@h /* Set Ks */
|
|
||||||
#endif
|
|
||||||
li r0,NUM_USER_SEGMENTS
|
|
||||||
mtctr r0
|
|
||||||
|
|
||||||
#ifdef CONFIG_BDI_SWITCH
|
|
||||||
/* Context switch the PTE pointer for the Abatron BDI2000.
|
|
||||||
* The PGDIR is passed as second argument.
|
|
||||||
*/
|
|
||||||
lwz r4, MM_PGD(r4)
|
|
||||||
lis r5, abatron_pteptrs@ha
|
|
||||||
stw r4, abatron_pteptrs@l + 0x4(r5)
|
|
||||||
#endif
|
|
||||||
BEGIN_MMU_FTR_SECTION
|
|
||||||
#ifndef CONFIG_BDI_SWITCH
|
|
||||||
lwz r4, MM_PGD(r4)
|
|
||||||
#endif
|
|
||||||
tophys(r4, r4)
|
|
||||||
rlwinm r4, r4, 4, 0xffff01ff
|
|
||||||
mtspr SPRN_SDR1, r4
|
|
||||||
END_MMU_FTR_SECTION_IFCLR(MMU_FTR_HPTE_TABLE)
|
|
||||||
li r4,0
|
|
||||||
isync
|
|
||||||
3:
|
|
||||||
mtsrin r3,r4
|
|
||||||
addi r3,r3,0x111 /* next VSID */
|
|
||||||
rlwinm r3,r3,0,8,3 /* clear out any overflow from VSID field */
|
|
||||||
addis r4,r4,0x1000 /* address of next segment */
|
|
||||||
bdnz 3b
|
|
||||||
sync
|
|
||||||
isync
|
|
||||||
blr
|
|
||||||
4: trap
|
|
||||||
EMIT_BUG_ENTRY 4b,__FILE__,__LINE__,0
|
|
||||||
blr
|
|
||||||
EXPORT_SYMBOL(switch_mmu_context)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* An undocumented "feature" of 604e requires that the v bit
|
* An undocumented "feature" of 604e requires that the v bit
|
||||||
* be cleared before changing BAT values.
|
* be cleared before changing BAT values.
|
||||||
|
@ -1282,9 +1230,3 @@ EXPORT_SYMBOL(empty_zero_page)
|
||||||
.globl swapper_pg_dir
|
.globl swapper_pg_dir
|
||||||
swapper_pg_dir:
|
swapper_pg_dir:
|
||||||
.space PGD_TABLE_SIZE
|
.space PGD_TABLE_SIZE
|
||||||
|
|
||||||
/* Room for two PTE pointers, usually the kernel and current user pointers
|
|
||||||
* to their respective root page table.
|
|
||||||
*/
|
|
||||||
abatron_pteptrs:
|
|
||||||
.space 8
|
|
||||||
|
|
|
@ -23,6 +23,12 @@
|
||||||
|
|
||||||
#include <asm/mmu_context.h>
|
#include <asm/mmu_context.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Room for two PTE pointers, usually the kernel and current user pointers
|
||||||
|
* to their respective root page table.
|
||||||
|
*/
|
||||||
|
void *abatron_pteptrs[2];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs
|
* On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs
|
||||||
* (virtual segment identifiers) for each context. Although the
|
* (virtual segment identifiers) for each context. Although the
|
||||||
|
@ -98,3 +104,32 @@ void __init mmu_context_init(void)
|
||||||
context_map[0] = (1 << FIRST_CONTEXT) - 1;
|
context_map[0] = (1 << FIRST_CONTEXT) - 1;
|
||||||
next_mmu_context = FIRST_CONTEXT;
|
next_mmu_context = FIRST_CONTEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
|
||||||
|
{
|
||||||
|
long id = next->context.id;
|
||||||
|
unsigned long val;
|
||||||
|
|
||||||
|
if (id < 0)
|
||||||
|
panic("mm_struct %p has no context ID", next);
|
||||||
|
|
||||||
|
isync();
|
||||||
|
|
||||||
|
val = CTX_TO_VSID(id, 0);
|
||||||
|
if (!kuep_is_disabled())
|
||||||
|
val |= SR_NX;
|
||||||
|
if (!kuap_is_disabled())
|
||||||
|
val |= SR_KS;
|
||||||
|
|
||||||
|
update_user_segments(val);
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_BDI_SWITCH))
|
||||||
|
abatron_pteptrs[1] = next->pgd;
|
||||||
|
|
||||||
|
if (!mmu_has_feature(MMU_FTR_HPTE_TABLE))
|
||||||
|
mtspr(SPRN_SDR1, rol32(__pa(next->pgd), 4) & 0xffff01ff);
|
||||||
|
|
||||||
|
mb(); /* sync */
|
||||||
|
isync();
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(switch_mmu_context);
|
||||||
|
|
Loading…
Reference in a new issue