Skip to content

Commit

Permalink
UPSTREAM: arm64: kasan: mte: move GCR_EL1 switch to task switch when …
Browse files Browse the repository at this point in the history
…KASAN disabled

It is not necessary to write to GCR_EL1 on every kernel entry and
exit when HW tag-based KASAN is disabled because the kernel will not
execute any IRG instructions in that mode. Since accessing GCR_EL1
can be expensive on some microarchitectures, avoid doing so by moving
the access to task switch when HW tag-based KASAN is disabled.

Signed-off-by: Peter Collingbourne <pcc@google.com>
Acked-by: Andrey Konovalov <andreyknvl@gmail.com>
Link: https://linux-review.googlesource.com/id/I78e90d60612a94c24344526f476ac4ff216e10d2
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Link: https://lore.kernel.org/r/20210924010655.2886918-1-pcc@google.com
Signed-off-by: Will Deacon <will@kernel.org>
(cherry picked from commit e5af50a)
Bug: 217222520
Change-Id: I0588695d88fa2a530d56ee190700802d3df46e40
Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
  • Loading branch information
pcc authored and xairy committed Feb 15, 2022
1 parent 600102b commit 9f94c4b
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 7 deletions.
10 changes: 5 additions & 5 deletions arch/arm64/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -193,20 +193,20 @@ alternative_else_nop_endif

.macro mte_set_kernel_gcr, tmp, tmp2
#ifdef CONFIG_KASAN_HW_TAGS
alternative_if_not ARM64_MTE
alternative_cb kasan_hw_tags_enable
b 1f
alternative_else_nop_endif
alternative_cb_end
mov \tmp, KERNEL_GCR_EL1
msr_s SYS_GCR_EL1, \tmp
1:
#endif
.endm

.macro mte_set_user_gcr, tsk, tmp, tmp2
#ifdef CONFIG_ARM64_MTE
alternative_if_not ARM64_MTE
#ifdef CONFIG_KASAN_HW_TAGS
alternative_cb kasan_hw_tags_enable
b 1f
alternative_else_nop_endif
alternative_cb_end
ldr \tmp, [\tsk, #THREAD_MTE_CTRL]

mte_set_gcr \tmp, \tmp2
Expand Down
26 changes: 26 additions & 0 deletions arch/arm64/kernel/mte.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,30 @@ static void mte_update_sctlr_user(struct task_struct *task)
task->thread.sctlr_user = sctlr;
}

static void mte_update_gcr_excl(struct task_struct *task)
{
/*
* SYS_GCR_EL1 will be set to current->thread.mte_ctrl value by
* mte_set_user_gcr() in kernel_exit, but only if KASAN is enabled.
*/
if (kasan_hw_tags_enabled())
return;

write_sysreg_s(
((task->thread.mte_ctrl >> MTE_CTRL_GCR_USER_EXCL_SHIFT) &
SYS_GCR_EL1_EXCL_MASK) | SYS_GCR_EL1_RRND,
SYS_GCR_EL1);
}

void __init kasan_hw_tags_enable(struct alt_instr *alt, __le32 *origptr,
__le32 *updptr, int nr_inst)
{
BUG_ON(nr_inst != 1); /* Branch -> NOP */

if (kasan_hw_tags_enabled())
*updptr = cpu_to_le32(aarch64_insn_gen_nop());
}

void mte_thread_init_user(void)
{
if (!system_supports_mte())
Expand All @@ -198,6 +222,7 @@ void mte_thread_switch(struct task_struct *next)
return;

mte_update_sctlr_user(next);
mte_update_gcr_excl(next);

/*
* Check if an async tag exception occurred at EL1.
Expand Down Expand Up @@ -243,6 +268,7 @@ long set_mte_ctrl(struct task_struct *task, unsigned long arg)
if (task == current) {
preempt_disable();
mte_update_sctlr_user(task);
mte_update_gcr_excl(task);
update_sctlr_el1(task->thread.sctlr_user);
preempt_enable();
}
Expand Down
9 changes: 7 additions & 2 deletions include/linux/kasan.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ static __always_inline bool kasan_enabled(void)
return static_branch_likely(&kasan_flag_enabled);
}

static inline bool kasan_has_integrated_init(void)
static inline bool kasan_hw_tags_enabled(void)
{
return kasan_enabled();
}
Expand All @@ -104,7 +104,7 @@ static inline bool kasan_enabled(void)
return IS_ENABLED(CONFIG_KASAN);
}

static inline bool kasan_has_integrated_init(void)
static inline bool kasan_hw_tags_enabled(void)
{
return false;
}
Expand All @@ -125,6 +125,11 @@ static __always_inline void kasan_free_pages(struct page *page,

#endif /* CONFIG_KASAN_HW_TAGS */

static inline bool kasan_has_integrated_init(void)
{
return kasan_hw_tags_enabled();
}

#ifdef CONFIG_KASAN

struct kasan_cache {
Expand Down

0 comments on commit 9f94c4b

Please sign in to comment.