Skip to content

Commit 25b9269

Browse files
mrutland-armctmarinas
authored andcommitted
arm64: mm: convert cpu_do_switch_mm() to C
There's no reason that cpu_do_switch_mm() needs to be written as an assembly function, and having it as a C function would make it easier to maintain. This patch converts cpu_do_switch_mm() to C, removing code that this change makes redundant (e.g. the mmid macro). Since the header comment was stale and the prototype now implies all the necessary information, this comment is removed. The 'pgd_phys' argument is made a phys_addr_t to match the return type of virt_to_phys(). At the same time, post_ttbr_update_workaround() is updated to use IS_ENABLED(), which allows the compiler to figure out it can elide calls for !CONFIG_CAVIUM_ERRATUM_27456 builds. There should be no functional change as a result of this patch. Signed-off-by: Mark Rutland <[email protected]> Cc: Will Deacon <[email protected]> [[email protected]: change comments from asm-style to C-style] Signed-off-by: Catalin Marinas <[email protected]>
1 parent 4399e6c commit 25b9269

File tree

5 files changed

+32
-38
lines changed

5 files changed

+32
-38
lines changed

arch/arm64/include/asm/assembler.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,12 +256,6 @@ alternative_endif
256256
ldr \rd, [\rn, #VMA_VM_MM]
257257
.endm
258258

259-
/*
260-
* mmid - get context id from mm pointer (mm->context.id)
261-
*/
262-
.macro mmid, rd, rn
263-
ldr \rd, [\rn, #MM_CONTEXT_ID]
264-
.endm
265259
/*
266260
* read_ctr - read CTR_EL0. If the system has mismatched register fields,
267261
* provide the system wide safe value from arm64_ftr_reg_ctrel0.sys_val

arch/arm64/include/asm/mmu_context.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ static inline void cpu_set_reserved_ttbr0(void)
4646
isb();
4747
}
4848

49+
void cpu_do_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm);
50+
4951
static inline void cpu_switch_mm(pgd_t *pgd, struct mm_struct *mm)
5052
{
5153
BUG_ON(pgd == swapper_pg_dir);

arch/arm64/include/asm/proc-fns.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@
1313

1414
#include <asm/page.h>
1515

16-
struct mm_struct;
1716
struct cpu_suspend_ctx;
1817

1918
extern void cpu_do_idle(void);
20-
extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
2119
extern void cpu_do_suspend(struct cpu_suspend_ctx *ptr);
2220
extern u64 cpu_do_resume(phys_addr_t ptr, u64 idmap_ttbr);
2321

arch/arm64/mm/context.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Copyright (C) 2012 ARM Ltd.
77
*/
88

9+
#include <linux/bitfield.h>
910
#include <linux/bitops.h>
1011
#include <linux/sched.h>
1112
#include <linux/slab.h>
@@ -254,10 +255,37 @@ void check_and_switch_context(struct mm_struct *mm, unsigned int cpu)
254255
/* Errata workaround post TTBRx_EL1 update. */
255256
asmlinkage void post_ttbr_update_workaround(void)
256257
{
258+
if (!IS_ENABLED(CONFIG_CAVIUM_ERRATUM_27456))
259+
return;
260+
257261
asm(ALTERNATIVE("nop; nop; nop",
258262
"ic iallu; dsb nsh; isb",
259-
ARM64_WORKAROUND_CAVIUM_27456,
260-
CONFIG_CAVIUM_ERRATUM_27456));
263+
ARM64_WORKAROUND_CAVIUM_27456));
264+
}
265+
266+
void cpu_do_switch_mm(phys_addr_t pgd_phys, struct mm_struct *mm)
267+
{
268+
unsigned long ttbr1 = read_sysreg(ttbr1_el1);
269+
unsigned long asid = ASID(mm);
270+
unsigned long ttbr0 = phys_to_ttbr(pgd_phys);
271+
272+
/* Skip CNP for the reserved ASID */
273+
if (system_supports_cnp() && asid)
274+
ttbr0 |= TTBR_CNP_BIT;
275+
276+
/* SW PAN needs a copy of the ASID in TTBR0 for entry */
277+
if (IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN))
278+
ttbr0 |= FIELD_PREP(TTBR_ASID_MASK, asid);
279+
280+
/* Set ASID in TTBR1 since TCR.A1 is set */
281+
ttbr1 &= ~TTBR_ASID_MASK;
282+
ttbr1 |= FIELD_PREP(TTBR_ASID_MASK, asid);
283+
284+
write_sysreg(ttbr1, ttbr1_el1);
285+
isb();
286+
write_sysreg(ttbr0, ttbr0_el1);
287+
isb();
288+
post_ttbr_update_workaround();
261289
}
262290

263291
static int asids_init(void)

arch/arm64/mm/proc.S

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -142,34 +142,6 @@ SYM_FUNC_END(cpu_do_resume)
142142
.popsection
143143
#endif
144144

145-
/*
146-
* cpu_do_switch_mm(pgd_phys, tsk)
147-
*
148-
* Set the translation table base pointer to be pgd_phys.
149-
*
150-
* - pgd_phys - physical address of new TTB
151-
*/
152-
SYM_FUNC_START(cpu_do_switch_mm)
153-
mrs x2, ttbr1_el1
154-
mmid x1, x1 // get mm->context.id
155-
phys_to_ttbr x3, x0
156-
157-
alternative_if ARM64_HAS_CNP
158-
cbz x1, 1f // skip CNP for reserved ASID
159-
orr x3, x3, #TTBR_CNP_BIT
160-
1:
161-
alternative_else_nop_endif
162-
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
163-
bfi x3, x1, #48, #16 // set the ASID field in TTBR0
164-
#endif
165-
bfi x2, x1, #48, #16 // set the ASID
166-
msr ttbr1_el1, x2 // in TTBR1 (since TCR.A1 is set)
167-
isb
168-
msr ttbr0_el1, x3 // now update TTBR0
169-
isb
170-
b post_ttbr_update_workaround // Back to C code...
171-
SYM_FUNC_END(cpu_do_switch_mm)
172-
173145
.pushsection ".idmap.text", "awx"
174146

175147
.macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2

0 commit comments

Comments
 (0)