As per PCuABI specific registers c0-c3 are initialised for purecap applications to make use of. This is set in start_thread(). The macro START_THREAD is specialised to allow returning the value of argc to be placed in x0.
Signed-off-by: Sherwin da Cruz sherwin.dacruz@arm.com --- arch/arm64/include/asm/elf.h | 3 +++ arch/arm64/include/asm/processor.h | 35 ++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index 9eb86b4cb691..07fb682aa4e6 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h @@ -164,6 +164,9 @@ typedef unsigned long elf_greg_t; typedef elf_greg_t elf_gregset_t[ELF_NGREG]; typedef struct user_fpsimd_state elf_fpregset_t;
+#define START_THREAD(elf_ex, regs, elf_entry, bprm) \ + start_thread(regs, elf_entry, bprm->p, bprm->argc, bprm->envc) + #define SET_PERSONALITY_AARCH64() \ ({ \ current->personality &= ~READ_IMPLIES_EXEC; \ diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index 5bdecb185f63..b190cfe816f5 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -238,6 +238,35 @@ void tls_preserve_current_state(void); .fpsimd_cpu = NR_CPUS, \ }
+static inline int init_gp_regs(struct pt_regs *regs, unsigned long sp, + int argc, int envc) +{ + int retval = 0; +#ifdef CONFIG_CHERI_PURECAP_UABI + unsigned long argv, envp, auxv; + /* + * TODO [PCuABI]: + * - When argv/envp/auxv is moved off the stack, update the registers x1-x3 + * with the new pointer values, and ensure c1-c3 contain appropriate + * capabilities (currently set to csp). + * - Restrict bounds/perms of c1-c3. + * + * In ret_to_user c regs are first loaded then merged with x regs if their values + * are different. Hence we load capabilities in c regs and the value in x regs. + */ + retval = argc; /* Placed in x0 */ + argv = sp + 1 * sizeof(user_uintptr_t); /* Increment past argc on stack */ + envp = argv + (argc + 1) * sizeof(user_uintptr_t); /* Go past arg vals + NULL */ + auxv = envp + (envc + 1) * sizeof(user_uintptr_t); /* Go past env vals + NULL */ + regs->cregs[1] = regs->cregs[2] = regs->cregs[3] = regs->csp; + regs->regs[1] = argv; + regs->regs[2] = envp; + regs->regs[3] = auxv; +#endif /* CONFIG_CHERI_PURECAP_UABI */ + + return retval; +} + static inline void start_thread_common(struct pt_regs *regs, unsigned long pc) { memset(regs, 0, sizeof(*regs)); @@ -248,8 +277,8 @@ static inline void start_thread_common(struct pt_regs *regs, unsigned long pc) regs->pmr_save = GIC_PRIO_IRQON; }
-static inline void start_thread(struct pt_regs *regs, unsigned long pc, - unsigned long sp) +static inline int start_thread(struct pt_regs *regs, unsigned long pc, + unsigned long sp, int argc, int envc) { start_thread_common(regs, pc); regs->pstate = PSR_MODE_EL0t; @@ -258,6 +287,8 @@ static inline void start_thread(struct pt_regs *regs, unsigned long pc,
if (system_supports_morello()) morello_thread_start(regs, pc); + + return init_gp_regs(regs, sp, argc, envc); }
#ifdef CONFIG_COMPAT