Skip to content

Commit 863771a

Browse files
chleroympe
authored andcommitted
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 b5efec0 ("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 <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/05c0875ad8220c03452c3a334946e207c6ca04d6.1622708530.git.christophe.leroy@csgroup.eu
1 parent 7235bb3 commit 863771a

File tree

4 files changed

+40
-63
lines changed

4 files changed

+40
-63
lines changed

arch/powerpc/include/asm/book3s/32/kup.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77

88
#ifndef __ASSEMBLY__
99

10+
static __always_inline bool kuap_is_disabled(void)
11+
{
12+
return !IS_ENABLED(CONFIG_PPC_KUAP);
13+
}
14+
1015
static __always_inline bool kuep_is_disabled(void)
1116
{
1217
return !IS_ENABLED(CONFIG_PPC_KUEP);

arch/powerpc/kernel/asm-offsets.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ int main(void)
8686
OFFSET(PACA_CANARY, paca_struct, canary);
8787
#endif
8888
#endif
89-
OFFSET(MMCONTEXTID, mm_struct, context.id);
9089
#ifdef CONFIG_PPC32
9190
#ifdef CONFIG_PPC_RTAS
9291
OFFSET(RTAS_SP, thread_struct, rtas_sp);
@@ -323,10 +322,6 @@ int main(void)
323322
#endif
324323
#endif
325324

326-
#ifndef CONFIG_PPC64
327-
OFFSET(MM_PGD, mm_struct, pgd);
328-
#endif /* ! CONFIG_PPC64 */
329-
330325
/* About the CPU features table */
331326
OFFSET(CPU_SPEC_FEATURES, cpu_spec, cpu_features);
332327
OFFSET(CPU_SPEC_SETUP, cpu_spec, cpu_setup);

arch/powerpc/kernel/head_book3s_32.S

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,58 +1033,6 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_HPTE_TABLE)
10331033
mtspr SPRN_SRR1,r4
10341034
rfi
10351035

1036-
/*
1037-
* void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next);
1038-
*
1039-
* Set up the segment registers for a new context.
1040-
*/
1041-
_ENTRY(switch_mmu_context)
1042-
lwz r3,MMCONTEXTID(r4)
1043-
cmpwi cr0,r3,0
1044-
blt- 4f
1045-
mulli r3,r3,897 /* multiply context by skew factor */
1046-
rlwinm r3,r3,4,8,27 /* VSID = (context & 0xfffff) << 4 */
1047-
#ifdef CONFIG_PPC_KUEP
1048-
oris r3, r3, SR_NX@h /* Set Nx */
1049-
#endif
1050-
#ifdef CONFIG_PPC_KUAP
1051-
oris r3, r3, SR_KS@h /* Set Ks */
1052-
#endif
1053-
li r0,NUM_USER_SEGMENTS
1054-
mtctr r0
1055-
1056-
#ifdef CONFIG_BDI_SWITCH
1057-
/* Context switch the PTE pointer for the Abatron BDI2000.
1058-
* The PGDIR is passed as second argument.
1059-
*/
1060-
lwz r4, MM_PGD(r4)
1061-
lis r5, abatron_pteptrs@ha
1062-
stw r4, abatron_pteptrs@l + 0x4(r5)
1063-
#endif
1064-
BEGIN_MMU_FTR_SECTION
1065-
#ifndef CONFIG_BDI_SWITCH
1066-
lwz r4, MM_PGD(r4)
1067-
#endif
1068-
tophys(r4, r4)
1069-
rlwinm r4, r4, 4, 0xffff01ff
1070-
mtspr SPRN_SDR1, r4
1071-
END_MMU_FTR_SECTION_IFCLR(MMU_FTR_HPTE_TABLE)
1072-
li r4,0
1073-
isync
1074-
3:
1075-
mtsrin r3,r4
1076-
addi r3,r3,0x111 /* next VSID */
1077-
rlwinm r3,r3,0,8,3 /* clear out any overflow from VSID field */
1078-
addis r4,r4,0x1000 /* address of next segment */
1079-
bdnz 3b
1080-
sync
1081-
isync
1082-
blr
1083-
4: trap
1084-
EMIT_BUG_ENTRY 4b,__FILE__,__LINE__,0
1085-
blr
1086-
EXPORT_SYMBOL(switch_mmu_context)
1087-
10881036
/*
10891037
* An undocumented "feature" of 604e requires that the v bit
10901038
* be cleared before changing BAT values.
@@ -1282,9 +1230,3 @@ EXPORT_SYMBOL(empty_zero_page)
12821230
.globl swapper_pg_dir
12831231
swapper_pg_dir:
12841232
.space PGD_TABLE_SIZE
1285-
1286-
/* Room for two PTE pointers, usually the kernel and current user pointers
1287-
* to their respective root page table.
1288-
*/
1289-
abatron_pteptrs:
1290-
.space 8

arch/powerpc/mm/book3s32/mmu_context.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323

2424
#include <asm/mmu_context.h>
2525

26+
/*
27+
* Room for two PTE pointers, usually the kernel and current user pointers
28+
* to their respective root page table.
29+
*/
30+
void *abatron_pteptrs[2];
31+
2632
/*
2733
* On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs
2834
* (virtual segment identifiers) for each context. Although the
@@ -98,3 +104,32 @@ void __init mmu_context_init(void)
98104
context_map[0] = (1 << FIRST_CONTEXT) - 1;
99105
next_mmu_context = FIRST_CONTEXT;
100106
}
107+
108+
void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
109+
{
110+
long id = next->context.id;
111+
unsigned long val;
112+
113+
if (id < 0)
114+
panic("mm_struct %p has no context ID", next);
115+
116+
isync();
117+
118+
val = CTX_TO_VSID(id, 0);
119+
if (!kuep_is_disabled())
120+
val |= SR_NX;
121+
if (!kuap_is_disabled())
122+
val |= SR_KS;
123+
124+
update_user_segments(val);
125+
126+
if (IS_ENABLED(CONFIG_BDI_SWITCH))
127+
abatron_pteptrs[1] = next->pgd;
128+
129+
if (!mmu_has_feature(MMU_FTR_HPTE_TABLE))
130+
mtspr(SPRN_SDR1, rol32(__pa(next->pgd), 4) & 0xffff01ff);
131+
132+
mb(); /* sync */
133+
isync();
134+
}
135+
EXPORT_SYMBOL(switch_mmu_context);

0 commit comments

Comments
 (0)