This patch translates the following Morello helpers, which are currently written in assembly in arch/arm64/lib/morello.S, to C functions which are now defined in arch/arm64/kernel/morello.c:
- morello_cap_get_val_tag - morello_build_any_user_cap - morello_task_{save, restore}_user_tls
As these were all the remaining assembly functions in morello.S, this file has now been removed and the Makefile edited accordingly.
Signed-off-by: Akram Ahmad Akram.Ahmad@arm.com --- arch/arm64/kernel/morello.c | 58 ++++++++++++++ arch/arm64/lib/Makefile | 3 +- arch/arm64/lib/morello.S | 147 ------------------------------------ 3 files changed, 59 insertions(+), 149 deletions(-) delete mode 100644 arch/arm64/lib/morello.S
diff --git a/arch/arm64/kernel/morello.c b/arch/arm64/kernel/morello.c index a32780f9af4d..d4be535c8057 100644 --- a/arch/arm64/kernel/morello.c +++ b/arch/arm64/kernel/morello.c @@ -75,6 +75,21 @@ static uintcap_t morello_sentry_unsealcap __ro_after_init;
#define CAP_OTYPE_FIELD_BITS 15
+void morello_cap_get_val_tag(uintcap_t cap, __uint128_t *val, u8 *tag) +{ + *tag = cheri_tag_get((void __capability *)&cap); + *val = (__uint128_t)__builtin_cheri_copy_from_high((void __capability *)cap) << 64; + *val = *val | (__uint128_t)cheri_address_get((void __capability *)cap); +} + +uintcap_t morello_build_any_user_cap(const __uint128_t *val, u8 tag) +{ + if (!tag) + return (uintcap_t)cheri_tag_clear(uaddr_to_user_ptr((u64)*val)); + + return (uintcap_t)__builtin_cheri_copy_to_high(uaddr_to_user_ptr((u64)*val), *val >> 64); +} + static bool is_pure_task(void) { return IS_ENABLED(CONFIG_CHERI_PURECAP_UABI) && !is_compat_task(); @@ -112,6 +127,49 @@ void morello_thread_start(struct pt_regs *regs, unsigned long pc) /* CSP is null-derived in hybrid */ } } +void morello_thread_save_user_state(struct task_struct *tsk) +{ + /* (R)CTPIDR is handled by task_save_user_tls */ + tsk->thread.morello_user_state.ddc = read_sysreg_c(DDC_EL0); + tsk->thread.morello_user_state.rddc = read_sysreg_c(RDDC_EL0); + tsk->thread.morello_user_state.cid = read_sysreg_c(CID_EL0); + tsk->thread.morello_user_state.cctlr = read_sysreg(CCTLR_EL0); +} + +void morello_thread_restore_user_state(struct task_struct *tsk) +{ + /* (R)CTPIDR is handled by task_restore_user_tls */ + write_sysreg_c(tsk->thread.morello_user_state.ddc, DDC_EL0); + write_sysreg_c(tsk->thread.morello_user_state.rddc, RDDC_EL0); + write_sysreg_c(tsk->thread.morello_user_state.cid, CID_EL0); + write_sysreg(tsk->thread.morello_user_state.cctlr, CCTLR_EL0); +} + +void morello_task_save_user_tls(struct task_struct *tsk, user_uintptr_t *tp_ptr) +{ + tsk->thread.morello_user_state.ctpidr = read_sysreg_c(CTPIDR_EL0); + tsk->thread.morello_user_state.rctpidr = read_sysreg_c(RCTPIDR_EL0); + + if (!__morello_cap_has_executive(task_pt_regs(tsk)->pcc)) + *tp_ptr = read_sysreg_c(RCTPIDR_EL0); + else + *tp_ptr = read_sysreg_c(CTPIDR_EL0); +} + +void morello_task_restore_user_tls(struct task_struct *tsk, + const user_uintptr_t *tp_ptr) +{ + uintcap_t *ctpidr = &tsk->thread.morello_user_state.ctpidr; + uintcap_t *rctpidr = &tsk->thread.morello_user_state.rctpidr; + + if (!__morello_cap_has_executive(task_pt_regs(tsk)->pcc)) + *rctpidr = *tp_ptr; + else + *ctpidr = *tp_ptr; + + write_sysreg_c(*rctpidr, RCTPIDR_EL0); + write_sysreg_c(*ctpidr, CTPIDR_EL0); +}
void morello_thread_init_user(void) { diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile index 5fa6f0645edc..2e46ed437b69 100644 --- a/arch/arm64/lib/Makefile +++ b/arch/arm64/lib/Makefile @@ -27,8 +27,7 @@ obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
obj-$(CONFIG_ARM64_MTE) += mte.o
-obj-$(CONFIG_ARM64_MORELLO) += morello.o \ - copy_from_user_with_captags.o \ +obj-$(CONFIG_ARM64_MORELLO) += copy_from_user_with_captags.o \ copy_to_user_with_captags.o
obj-$(CONFIG_KASAN_SW_TAGS) += kasan_sw_tags.o diff --git a/arch/arm64/lib/morello.S b/arch/arm64/lib/morello.S deleted file mode 100644 index 5a4a39badfe2..000000000000 --- a/arch/arm64/lib/morello.S +++ /dev/null @@ -1,147 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) 2020 Arm Ltd. - * - * TODO: most of the functions in this file should be reimplemented in C to - * improve readability. - */ - -#include <linux/linkage.h> - -#include <asm/asm-uaccess.h> -#include <asm/assembler.h> -#include <asm/morello.h> -#include <asm/sysreg.h> - -SYM_FUNC_START(morello_cap_get_val_tag) - gctag x3, c0 - clrtag c0, c0 // Store the 128-bit value without the tag - str c0, [x1] - strb w3, [x2] - - ret -SYM_FUNC_END(morello_cap_get_val_tag) - -SYM_FUNC_START(morello_build_any_user_cap) - ldr c0, [x0] - cbz w1, 1f - /* - * The tag should be set, build a valid capability from the root - * capability. - * In case c0 is sealed (non-zero object type), we need to extract the - * object type first to be able to reseal it after BUILD. The CSEAL - * instruction is used to cover the case where c0 was not sealed. - */ - adr_l x3, cheri_user_root_allperms_cap - ldr c3, [x3] - - cpytype c4, c3, c0 - build c0, c0, c3 - cseal c0, c0, c4 - b 2f -1: - /* The tag should be cleared, make sure it is. */ - clrtag c0, c0 -2: - ret -SYM_FUNC_END(morello_build_any_user_cap) - -SYM_FUNC_START(morello_thread_save_user_state) - mov x9, #THREAD_MORELLO_USER_STATE - add x0, x0, x9 // x0 = tsk->thread.morello_user_state - - /* (R)CTPIDR is handled by task_save_user_tls */ - mrs c1, ddc_el0 - mrs c2, rddc_el0 - stp c1, c2, [x0, #MORELLO_STATE_DDC] - mrs c1, cid_el0 - str c1, [x0, #MORELLO_STATE_CID] - mrs x1, cctlr_el0 - str x1, [x0, #MORELLO_STATE_CCTLR] - - ret -SYM_FUNC_END(morello_thread_save_user_state) - -SYM_FUNC_START(morello_thread_restore_user_state) - mov x9, #THREAD_MORELLO_USER_STATE - add x0, x0, x9 // x0 = tsk->thread.morello_user_state - - /* (R)CTPIDR is handled by task_restore_user_tls */ - ldp c1, c2, [x0, #MORELLO_STATE_DDC] - msr ddc_el0, c1 - msr rddc_el0, c2 - ldr c1, [x0, #MORELLO_STATE_CID] - msr cid_el0, c1 - ldr x1, [x0, #MORELLO_STATE_CCTLR] - msr cctlr_el0, x1 - - ret -SYM_FUNC_END(morello_thread_restore_user_state) - -SYM_FUNC_START(morello_task_save_user_tls) - get_task_pt_regs x8, x0 - mov x9, #THREAD_MORELLO_USER_STATE - add x0, x0, x9 // x0 = tsk->thread.morello_user_state - - mrs c2, ctpidr_el0 - mrs c3, rctpidr_el0 - /* Save CTPIDR and RCTPIDR */ - stp c2, c3, [x0, #MORELLO_STATE_CTPIDR] - - ldr c5, [x8, #S_PCC] - /* - * If the task is currently running in Restricted, save the lower 64 bits - * of RCTPIDR (RTPIDR) in tsk->thread instead of TPIDR. - */ - morello_tst_cap_has_executive c5, x6 // Task running in Executive? -#ifdef CONFIG_CHERI_PURECAP_UABI - csel c2, c2, c3, ne // If not, save RTPIDR - str c2, [x1] -#else - csel x2, x2, x3, ne // If not, save RTPIDR - str x2, [x1] -#endif - ret -SYM_FUNC_END(morello_task_save_user_tls) - -SYM_FUNC_START(morello_task_restore_user_tls) - get_task_pt_regs x8, x0 - mov x9, #THREAD_MORELLO_USER_STATE - add x0, x0, x9 // x0 = tsk->thread.morello_user_state - - /* Load CTPIDR, RCTPIDR and the 64-bit TLS pointer */ - ldp c2, c3, [x0, #MORELLO_STATE_CTPIDR] -#ifdef CONFIG_CHERI_PURECAP_UABI - ldr c4, [x1] -#else - ldr x4, [x1] -#endif - - /* - * The 64-bit TLS pointer may have been modified from within the kernel - * (e.g. through ptrace) since morello_task_save_user_tls was called. - * Merge it back into the active capability TLS pointer, that is RCTPIDR - * if the task is running in Restricted and CTPIDR otherwise. - */ - ldr c5, [x8, #S_PCC] - morello_tst_cap_has_executive c5, x6 // Task running in Executive? - b.eq 1f // If not, merge into RCTPIDR -#ifdef CONFIG_CHERI_PURECAP_UABI - mov c2, c4 // Save the TLS pointer into CTPIDR -#else - morello_merge_c_x 2, x4 // Merge the TLS pointer into CTPIDR -#endif - b 2f -1: -#ifdef CONFIG_CHERI_PURECAP_UABI - mov c3, c4 // Save the TLS pointer into RCTPIDR -#else - morello_merge_c_x 3, x4 // Merge the TLS pointer into RCTPIDR -#endif -2: - msr ctpidr_el0, c2 - msr rctpidr_el0, c3 - - ret -SYM_FUNC_END(morello_task_restore_user_tls) -