#include <sys/cdefs.h>
__KERNEL_RCSID(1, "$NetBSD: exec_machdep.c,v 1.10 2021/09/23 15:19:03 ryo Exp $");
#include "opt_compat_netbsd.h"
#include "opt_compat_netbsd32.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/exec.h>
#include <sys/cprng.h>
#include <uvm/uvm_extern.h>
#include <compat/common/compat_util.h>
#include <sys/exec_elf.h>
#ifdef COMPAT_NETBSD32
#include <compat/netbsd32/netbsd32_exec.h>
#endif
#include <aarch64/armreg.h>
#include <aarch64/frame.h>
#include <aarch64/machdep.h>
#include <arm/cpufunc.h>
#if EXEC_ELF64
int
aarch64_netbsd_elf64_probe(struct lwp *l, struct exec_package *epp, void *eh0,
char *itp, vaddr_t *start_p)
{
return 0;
}
#endif
#if EXEC_ELF32
int
aarch64_netbsd_elf32_probe(struct lwp *l, struct exec_package *epp, void *eh0,
char *itp, vaddr_t *start_p)
{
const Elf32_Ehdr * const eh = eh0;
const bool elf_aapcs_p =
(eh->e_flags & EF_ARM_EABIMASK) >= EF_ARM_EABI_VER4;
if (!elf_aapcs_p)
return ENOEXEC;
#ifdef __AARCH64EB__
if ((eh->e_flags & EF_ARM_BE8) == 0)
return ENOEXEC;
#endif
if (__SHIFTOUT(l->l_cpu->ci_id.ac_aa64pfr0, ID_AA64PFR0_EL1_EL0) !=
ID_AA64PFR0_EL1_EL0_64_32)
return ENOEXEC;
CTASSERT(sizeof(l->l_proc->p_md.md_march32) ==
sizeof(epp->ep_machine_arch));
if (epp->ep_machine_arch[0] != 0)
strlcpy(l->l_proc->p_md.md_march32, epp->ep_machine_arch,
sizeof(l->l_proc->p_md.md_march32));
return 0;
}
#endif
void
aarch64_setregs_ptrauth(struct lwp *l, bool randomize)
{
#ifdef ARMV83_PAC
if (!aarch64_pac_enabled)
return;
if (randomize) {
cprng_strong(kern_cprng, l->l_md.md_ia_user,
sizeof(l->l_md.md_ia_user), 0);
cprng_strong(kern_cprng, l->l_md.md_ib_user,
sizeof(l->l_md.md_ib_user), 0);
cprng_strong(kern_cprng, l->l_md.md_da_user,
sizeof(l->l_md.md_da_user), 0);
cprng_strong(kern_cprng, l->l_md.md_db_user,
sizeof(l->l_md.md_db_user), 0);
cprng_strong(kern_cprng, l->l_md.md_ga_user,
sizeof(l->l_md.md_ga_user), 0);
} else {
memset(l->l_md.md_ia_user, 0,
sizeof(l->l_md.md_ia_user));
memset(l->l_md.md_ib_user, 0,
sizeof(l->l_md.md_ib_user));
memset(l->l_md.md_da_user, 0,
sizeof(l->l_md.md_da_user));
memset(l->l_md.md_db_user, 0,
sizeof(l->l_md.md_db_user));
memset(l->l_md.md_ga_user, 0,
sizeof(l->l_md.md_ga_user));
}
#endif
}
void
setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
{
struct proc * const p = l->l_proc;
struct trapframe * const tf = lwp_trapframe(l);
aarch64_setregs_ptrauth(l, true);
p->p_flag &= ~PK_32;
memset(tf, 0, sizeof(*tf));
tf->tf_reg[2] = p->p_psstrp;
tf->tf_pc = pack->ep_entry;
tf->tf_sp = stack & -16L;
tf->tf_spsr = SPSR_M_EL0T;
}