Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Jan 2019 19:49:46 +0000 (UTC)
From:      Olivier Houchard <cognet@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r343004 - in head/sys/arm64: arm64 conf include
Message-ID:  <201901131949.x0DJnkRL089992@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cognet
Date: Sun Jan 13 19:49:46 2019
New Revision: 343004
URL: https://svnweb.freebsd.org/changeset/base/343004

Log:
  Impleent COMPAT_FREEBSD32 for arm64.
  This is based on early work by andrew@.

Modified:
  head/sys/arm64/arm64/elf32_machdep.c
  head/sys/arm64/arm64/freebsd32_machdep.c
  head/sys/arm64/arm64/identcpu.c
  head/sys/arm64/arm64/locore.S
  head/sys/arm64/arm64/machdep.c
  head/sys/arm64/arm64/undefined.c
  head/sys/arm64/arm64/vm_machdep.c
  head/sys/arm64/conf/GENERIC
  head/sys/arm64/include/armreg.h
  head/sys/arm64/include/elf.h
  head/sys/arm64/include/frame.h
  head/sys/arm64/include/reg.h
  head/sys/arm64/include/ucontext.h
  head/sys/arm64/include/vfp.h

Modified: head/sys/arm64/arm64/elf32_machdep.c
==============================================================================
--- head/sys/arm64/arm64/elf32_machdep.c	Sun Jan 13 18:48:13 2019	(r343003)
+++ head/sys/arm64/arm64/elf32_machdep.c	Sun Jan 13 19:49:46 2019	(r343004)
@@ -1,6 +1,15 @@
 /*-
- * Copyright (c) 2017 Nuxi, https://nuxi.nl/
+ * Copyright (c) 2014, 2015 The FreeBSD Foundation.
+ * Copyright (c) 2014, 2017 Andrew Turner.
+ * Copyright (c) 2018 Olivier Houchard
+ * All rights reserved.
  *
+ * This software was developed by Andrew Turner under
+ * sponsorship from the FreeBSD Foundation.
+ *
+ * Portions of this software were developed by Konstantin Belousov
+ * under sponsorship from the FreeBSD Foundation.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -26,13 +35,225 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
-#include <sys/types.h>
-#define	__ELF_WORD_SIZE	32
+#define	__ELF_WORD_SIZE 32
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/exec.h>
+#include <sys/imgact.h>
+#include <sys/linker.h>
+#include <sys/proc.h>
+#include <sys/sysent.h>
 #include <sys/imgact_elf.h>
+#include <sys/syscall.h>
+#include <sys/signalvar.h>
+#include <sys/vnode.h>
 
-void
-elf32_dump_thread(struct thread *td __unused, void *dst __unused,
-    size_t *off __unused)
+#include <machine/elf.h>
+
+#include <compat/freebsd32/freebsd32_util.h>
+
+#define	FREEBSD32_MINUSER	0x00001000
+#define	FREEBSD32_MAXUSER	((1ul << 32) - PAGE_SIZE)
+#define	FREEBSD32_SHAREDPAGE	(FREEBSD32_MAXUSER - PAGE_SIZE)
+#define	FREEBSD32_USRSTACK	FREEBSD32_SHAREDPAGE
+
+extern const char *freebsd32_syscallnames[];
+
+extern char aarch32_sigcode[];
+extern int sz_aarch32_sigcode;
+
+static int freebsd32_fetch_syscall_args(struct thread *td);
+static void freebsd32_setregs(struct thread *td, struct image_params *imgp,
+   u_long stack);
+static void freebsd32_set_syscall_retval(struct thread *, int);
+
+static boolean_t elf32_arm_abi_supported(struct image_params *);
+
+extern void freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
+
+static struct sysentvec elf32_freebsd_sysvec = {
+	.sv_size	= SYS_MAXSYSCALL,
+	.sv_table	= freebsd32_sysent,
+	.sv_errsize	= 0,
+	.sv_errtbl	= NULL,
+	.sv_transtrap	= NULL,
+	.sv_fixup	= elf32_freebsd_fixup,
+	.sv_sendsig	= freebsd32_sendsig,
+	.sv_sigcode	= aarch32_sigcode,
+	.sv_szsigcode	= &sz_aarch32_sigcode,
+	.sv_name	= "FreeBSD ELF32",
+	.sv_coredump	= elf32_coredump,
+	.sv_imgact_try	= NULL,
+	.sv_minsigstksz	= MINSIGSTKSZ,
+	.sv_pagesize	= PAGE_SIZE,
+	.sv_minuser	= FREEBSD32_MINUSER,
+	.sv_maxuser	= FREEBSD32_MAXUSER,
+	.sv_usrstack	= FREEBSD32_USRSTACK,
+	.sv_psstrings	= FREEBSD32_PS_STRINGS,
+	.sv_stackprot	= VM_PROT_READ | VM_PROT_WRITE,
+	.sv_copyout_strings = freebsd32_copyout_strings,
+	.sv_setregs	= freebsd32_setregs,
+	.sv_fixlimit	= NULL, // XXX
+	.sv_maxssiz	= NULL,
+	.sv_flags	= SV_ABI_FREEBSD | SV_ILP32 | SV_SHP | SV_TIMEKEEP,
+	.sv_set_syscall_retval = freebsd32_set_syscall_retval,
+	.sv_fetch_syscall_args = freebsd32_fetch_syscall_args,
+	.sv_syscallnames = freebsd32_syscallnames,
+	.sv_shared_page_base = FREEBSD32_SHAREDPAGE,
+	.sv_shared_page_len = PAGE_SIZE,
+	.sv_schedtail	= NULL,
+	.sv_thread_detach = NULL,
+	.sv_trap	= NULL,
+};
+INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
+
+static Elf32_Brandinfo freebsd32_brand_info = {
+	.brand		= ELFOSABI_FREEBSD,
+	.machine	= EM_ARM,
+	.compat_3_brand	= "FreeBSD",
+	.emul_path	= NULL,
+	.interp_path	= "/libexec/ld-elf.so.1",
+	.sysvec		= &elf32_freebsd_sysvec,
+	.interp_newpath	= NULL,
+	.brand_note	= &elf32_freebsd_brandnote,
+	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE,
+	.header_supported= elf32_arm_abi_supported,
+};
+
+SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_FIRST,
+    (sysinit_cfunc_t)elf32_insert_brand_entry, &freebsd32_brand_info);
+
+static boolean_t
+elf32_arm_abi_supported(struct image_params *imgp)
 {
+	const Elf32_Ehdr *hdr;
 
+	/* Check if we support AArch32 */
+	if (ID_AA64PFR0_EL0(READ_SPECIALREG(id_aa64pfr0_el1)) !=
+	    ID_AA64PFR0_EL0_64_32)
+		return (FALSE);
+
+#define	EF_ARM_EABI_VERSION(x)	(((x) & EF_ARM_EABIMASK) >> 24)
+#define	EF_ARM_EABI_FREEBSD_MIN	4
+	hdr = (const Elf32_Ehdr *)imgp->image_header;
+	if (EF_ARM_EABI_VERSION(hdr->e_flags) < EF_ARM_EABI_FREEBSD_MIN) {
+		if (bootverbose)
+			uprintf("Attempting to execute non EABI binary "
+			    "(rev %d) image %s",
+			    EF_ARM_EABI_VERSION(hdr->e_flags),
+			    imgp->args->fname);
+		return (FALSE);
+        }
+
+	return (TRUE);
+}
+
+static int
+freebsd32_fetch_syscall_args(struct thread *td)
+{
+	struct proc *p;
+	register_t *ap;
+	struct syscall_args *sa;
+	int error, i, nap;
+	unsigned int args[4];
+
+	nap = 4;
+	p = td->td_proc;
+	ap = td->td_frame->tf_x;
+	sa = &td->td_sa;
+
+	/* r7 is the syscall id */
+	sa->code = td->td_frame->tf_x[7];
+
+	if (sa->code == SYS_syscall) {
+		sa->code = *ap++;
+		nap--;
+	} else if (sa->code == SYS___syscall) {
+		sa->code = ap[1];
+		nap -= 2;
+		ap += 2;
+	}
+
+	if (sa->code >= p->p_sysent->sv_size)
+		sa->callp = &p->p_sysent->sv_table[0];
+	else
+		sa->callp = &p->p_sysent->sv_table[sa->code];
+
+	sa->narg = sa->callp->sy_narg;
+	for (i = 0; i < nap; i++)
+		sa->args[i] = ap[i];
+	if (sa->narg > nap) {
+		if ((sa->narg - nap) > nitems(args))
+			panic("Too many system call arguiments");
+		error = copyin((void *)td->td_frame->tf_x[13], args,
+		    (sa->narg - nap) * sizeof(int));
+		for (i = 0; i < (sa->narg - nap); i++)
+			sa->args[i + nap] = args[i];
+	}
+
+	td->td_retval[0] = 0;
+	td->td_retval[1] = 0;
+
+	return (0);
+}
+
+static void
+freebsd32_set_syscall_retval(struct thread *td, int error)
+{
+	struct trapframe *frame;
+
+	frame = td->td_frame;
+	switch (error) {
+	case 0:
+		frame->tf_x[0] = td->td_retval[0];
+		frame->tf_x[1] = td->td_retval[1];
+		frame->tf_spsr &= ~PSR_C;
+		break;
+	case ERESTART:
+		/*
+		 * Reconstruct the pc to point at the swi.
+		 */
+		if ((frame->tf_spsr & PSR_T) != 0)
+			frame->tf_elr -= 2; //THUMB_INSN_SIZE;
+		else
+			frame->tf_elr -= 4; //INSN_SIZE;
+		break;
+	case EJUSTRETURN:
+		/* nothing to do */
+		break;
+	default:
+		frame->tf_x[0] = error;
+		frame->tf_spsr |= PSR_C;
+		break;
+	}
+}
+
+static void
+freebsd32_setregs(struct thread *td, struct image_params *imgp,
+   u_long stack)
+{
+	struct trapframe *tf = td->td_frame;
+
+	memset(tf, 0, sizeof(struct trapframe));
+
+	/*
+	 * We need to set x0 for init as it doesn't call
+	 * cpu_set_syscall_retval to copy the value. We also
+	 * need to set td_retval for the cases where we do.
+	 */
+	tf->tf_x[0] = stack;
+	/* SP_usr is mapped to x13 */
+	tf->tf_x[13] = stack;
+	/* LR_usr is mapped to x14 */
+	tf->tf_x[14] = imgp->entry_addr;
+	tf->tf_elr = imgp->entry_addr;
+	tf->tf_spsr = PSR_M_32;
+}
+
+void
+elf32_dump_thread(struct thread *td, void *dst, size_t *off)
+{
+	/* XXX: VFP */
 }

Modified: head/sys/arm64/arm64/freebsd32_machdep.c
==============================================================================
--- head/sys/arm64/arm64/freebsd32_machdep.c	Sun Jan 13 18:48:13 2019	(r343003)
+++ head/sys/arm64/arm64/freebsd32_machdep.c	Sun Jan 13 19:49:46 2019	(r343004)
@@ -1,4 +1,5 @@
 /*-
+ * Copyright (c) 2018 Olivier Houchard
  * Copyright (c) 2017 Nuxi, https://nuxi.nl/
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,44 +28,382 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
-
+#include <sys/proc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/syscallsubr.h>
+#include <sys/ktr.h>
+#include <sys/sysent.h>
+#include <machine/armreg.h>
+#ifdef VFP
+#include <machine/vfp.h>
+#endif
 #include <compat/freebsd32/freebsd32_proto.h>
+#include <compat/freebsd32/freebsd32_signal.h>
 
+extern void freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
+
 /*
+ * The first two fields of a ucontext_t are the signal mask and the machine
+ * context.  The next field is uc_link; we want to avoid destroying the link
+ * when copying out contexts.
+ */
+#define UC32_COPY_SIZE  offsetof(ucontext32_t, uc_link)
+
+#ifdef VFP
+static void get_fpcontext32(struct thread *td, mcontext32_vfp_t *);
+#endif
+
+/*
  * Stubs for machine dependent 32-bits system calls.
  */
 
 int
+freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
+{
+	int error;
+
+#define ARM_SYNC_ICACHE		0
+#define ARM_DRAIN_WRITEBUF	1
+#define ARM_SET_TP		2
+#define ARM_GET_TP		3
+#define ARM_GET_VFPSTATE	4
+
+	switch(uap->op) {
+	case ARM_SET_TP:
+		WRITE_SPECIALREG(TPIDR_EL0, uap->parms);
+		WRITE_SPECIALREG(TPIDRRO_EL0, uap->parms);
+		return 0;
+	case ARM_SYNC_ICACHE:
+		{
+			struct {
+				uint32_t addr;
+				uint32_t size;
+			} args;
+
+			if ((error = copyin(uap->parms, &args, sizeof(args))) != 0)
+				return (error);
+			if ((uint64_t)args.addr + (uint64_t)args.size > 0xffffffff)
+				return (EINVAL);
+			cpu_icache_sync_range(args.addr, args.size);
+			return 0;
+		}
+	case ARM_GET_VFPSTATE:
+		{
+			mcontext32_vfp_t mcontext_vfp;
+
+			struct {
+				uint32_t mc_vfp_size;
+				uint32_t mc_vfp;
+			} args;
+			if ((error = copyin(uap->parms, &args, sizeof(args))) != 0)
+				return (error);
+			if (args.mc_vfp_size != sizeof(mcontext_vfp))
+				return (EINVAL);
+#ifdef VFP
+			get_fpcontext32(td, &mcontext_vfp);
+#else
+			bzero(&mcontext_vfp, sizeof(mcontext_vfp));
+#endif
+			error = copyout(&mcontext_vfp,
+				(void *)(uintptr_t)args.mc_vfp,
+				sizeof(mcontext_vfp));
+			return error;
+		}
+	}
+
+	return (EINVAL);
+}
+
+
+
+#ifdef VFP
+static void
+get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
+{
+	struct pcb *curpcb;
+
+	critical_enter();
+	curpcb = curthread->td_pcb;
+
+	if ((curpcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
+		/*
+		 * If we have just been running VFP instructions we will
+		 * need to save the state to memcpy it below.
+		 */
+		vfp_save_state(td, curpcb);
+
+		KASSERT(curpcb->pcb_fpusaved == &curpcb->pcb_fpustate,
+				("Called get_fpcontext while the kernel is using the VFP"));
+		KASSERT((curpcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0,
+				("Non-userspace FPU flags set in get_fpcontext"));
+		memcpy(mcp->mcv_reg, curpcb->pcb_fpustate.vfp_regs,
+				sizeof(mcp->mcv_reg));
+		mcp->mcv_fpscr = VFP_FPSCR_FROM_SRCR(curpcb->pcb_fpustate.vfp_fpcr,
+				curpcb->pcb_fpustate.vfp_fpsr);
+	}
+ critical_exit();
+}
+
+static void
+set_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
+{
+	struct pcb *pcb;
+
+	critical_enter();
+	pcb = td->td_pcb;
+	if (td == curthread)
+		vfp_discard(td);
+	memcpy(pcb->pcb_fpustate.vfp_regs, mcp->mcv_reg,
+			sizeof(pcb->pcb_fpustate.vfp_regs));
+	pcb->pcb_fpustate.vfp_fpsr = VFP_FPSR_FROM_FPSCR(mcp->mcv_fpscr);
+	pcb->pcb_fpustate.vfp_fpcr = VFP_FPSR_FROM_FPSCR(mcp->mcv_fpscr);
+	critical_exit();
+}
+#endif
+static void
+get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
+{
+	struct pcb *pcb;
+	struct trapframe *tf;
+	int i;
+
+	pcb = td->td_pcb;
+	tf = td->td_frame;
+
+	if ((flags & GET_MC_CLEAR_RET) != 0) {
+		mcp->mc_gregset[0] = 0;
+		mcp->mc_gregset[16] = tf->tf_spsr & ~PSR_C;
+	} else {
+		mcp->mc_gregset[0] = tf->tf_x[0];
+		mcp->mc_gregset[16] = tf->tf_spsr;
+	}
+	for (i = 1; i < 15; i++)
+		mcp->mc_gregset[i] = tf->tf_x[i];
+	mcp->mc_gregset[15] = tf->tf_elr;
+
+	mcp->mc_vfp_size = 0;
+	mcp->mc_vfp_ptr = 0;
+
+	memset(mcp->mc_spare, 0, sizeof(mcp->mc_spare));
+}
+
+static int
+set_mcontext32(struct thread *td, mcontext32_t *mcp)
+{
+	struct trapframe *tf;
+	mcontext32_vfp_t mc_vfp;
+	int i;
+
+	tf = td->td_frame;
+
+	for (i = 0; i < 15; i++)
+		tf->tf_x[i] = mcp->mc_gregset[i];
+	tf->tf_elr = mcp->mc_gregset[15];
+	tf->tf_spsr = mcp->mc_gregset[16];
+#ifdef VFP
+	if (mcp->mc_vfp_size == sizeof(mc_vfp) && mcp->mc_vfp_ptr != 0) {
+		if (copyin((void *)(uintptr_t)mcp->mc_vfp_ptr, &mc_vfp,
+					sizeof(mc_vfp)) != 0)
+			return (EFAULT);
+		set_fpcontext32(td, &mc_vfp);
+	}
+#endif
+
+	return (0);
+}
+
+#define UC_COPY_SIZE	offsetof(ucontext32_t, uc_link)
+
+int
 freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
 {
+	ucontext32_t uc;
+	int ret;
 
-	return (ENOSYS);
+	if (uap->ucp == NULL)
+		ret = EINVAL;
+	else {
+		memset(&uc, 0, sizeof(uc));
+		get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
+		PROC_LOCK(td->td_proc);
+		uc.uc_sigmask = td->td_sigmask;
+		PROC_UNLOCK(td->td_proc);
+		ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);
+	}
+	return (ret);
 }
 
 int
 freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
 {
+	ucontext32_t uc;
+	int ret;
 
-	return (ENOSYS);
+	if (uap->ucp == NULL)
+		ret = EINVAL;
+	else {
+		ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
+		if (ret == 0) {
+			ret = set_mcontext32(td, &uc.uc_mcontext);
+			if (ret == 0)
+				kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask,
+						NULL, 0);
+		}
+	}
+	return (ret);
 }
 
 int
 freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap)
 {
+	ucontext32_t uc;
+	int error;
 
-	return (ENOSYS);
+	if (uap == NULL)
+		return (EFAULT);
+	if (copyin(uap->sigcntxp, &uc, sizeof(uc)))
+		return (EFAULT);
+	error = set_mcontext32(td, &uc.uc_mcontext);
+	if (error != 0)
+		return (0);
+
+	/* Restore signal mask. */
+	kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
+
+	return (EJUSTRETURN);
+
 }
 
 int
 freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
 {
+	ucontext32_t uc;
+	int ret;
 
-	return (ENOSYS);
+	if (uap->oucp == NULL || uap->ucp == NULL)
+		ret = EINVAL;
+	else {
+		get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
+		PROC_LOCK(td->td_proc);
+		uc.uc_sigmask = td->td_sigmask;
+		PROC_UNLOCK(td->td_proc);
+		ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE);
+		if (ret == 0) {
+			ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
+			if (ret == 0) {
+				ret = set_mcontext32(td, &uc.uc_mcontext);
+				kern_sigprocmask(td, SIG_SETMASK,
+						&uc.uc_sigmask, NULL, 0);
+			}
+		}
+	}
+	return (ret);
 }
 
-int
-freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
+void
+freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
 {
+	struct thread *td;
+	struct proc *p;
+	struct trapframe *tf;
+	struct sigframe32 *fp, frame;
+	struct sigacts *psp;
+	struct siginfo32 siginfo;
+	struct sysentvec *sysent;
+	int onstack;
+	int sig;
+	int code;
 
-	return (ENOSYS);
+	siginfo_to_siginfo32(&ksi->ksi_info, &siginfo);
+	td = curthread;
+	p = td->td_proc;
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	sig = ksi->ksi_signo;
+	code = ksi->ksi_code;
+	psp = p->p_sigacts;
+	mtx_assert(&psp->ps_mtx, MA_OWNED);
+	tf = td->td_frame;
+	onstack = sigonstack(tf->tf_x[13]);
+
+	CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
+	    catcher, sig);
+
+	/* Allocate and validate space for the signal handler context. */
+	if ((td->td_pflags & TDP_ALTSTACK) != 0 && !(onstack) &&
+	    SIGISMEMBER(psp->ps_sigonstack, sig)) {
+		fp = (struct sigframe32 *)((uintptr_t)td->td_sigstk.ss_sp +
+		    td->td_sigstk.ss_size);
+#if defined(COMPAT_43)
+		td->td_sigstk.ss_flags |= SS_ONSTACK;
+#endif
+	} else
+		fp = (struct sigframe32 *)td->td_frame->tf_x[13];
+
+	/* make room on the stack */
+	fp--;
+
+	/* make the stack aligned */
+	fp = (struct sigframe32 *)((unsigned long)(fp) &~ (8 - 1));
+	/* Populate the siginfo frame. */
+	get_mcontext32(td, &frame.sf_uc.uc_mcontext, 0);
+#ifdef VFP
+	get_fpcontext32(td, &frame.sf_vfp);
+	frame.sf_uc.uc_mcontext.mc_vfp_size = sizeof(fp->sf_vfp);
+	frame.sf_uc.uc_mcontext.mc_vfp_ptr = (uint32_t)(uintptr_t)&fp->sf_vfp;
+#else
+	frame.sf_uc.uc_mcontext.mc_vfp_size = 0;
+	frame.sf_uc.uc_mcontext.mc_vfp_ptr = (uint32_t)NULL;
+#endif
+	frame.sf_si = siginfo;
+	frame.sf_uc.uc_sigmask = *mask;
+	frame.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK )
+	    ? ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE;
+	frame.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
+	frame.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size;
+
+	mtx_unlock(&psp->ps_mtx);
+	PROC_UNLOCK(td->td_proc);
+
+	/* Copy the sigframe out to the user's stack. */
+	if (copyout(&frame, fp, sizeof(*fp)) != 0) {
+		/* Process has trashed its stack. Kill it. */
+		CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%p", td, fp);
+		PROC_LOCK(p);
+		sigexit(td, SIGILL);
+	}
+
+	/*
+	 * Build context to run handler in.  We invoke the handler
+	 * directly, only returning via the trampoline.  Note the
+	 * trampoline version numbers are coordinated with machine-
+	 * dependent code in libc.
+	 */
+
+	tf->tf_x[0] = sig;
+	tf->tf_x[1] = (register_t)&fp->sf_si;
+	tf->tf_x[2] = (register_t)&fp->sf_uc;
+
+	/* the trampoline uses r5 as the uc address */
+	tf->tf_x[5] = (register_t)&fp->sf_uc;
+	tf->tf_elr = (register_t)catcher;
+	tf->tf_x[13] = (register_t)fp;
+	sysent = p->p_sysent;
+	if (sysent->sv_sigcode_base != 0)
+		tf->tf_x[14] = (register_t)sysent->sv_sigcode_base;
+	else
+		tf->tf_x[14] = (register_t)(sysent->sv_psstrings -
+		    *(sysent->sv_szsigcode));
+	/* Set the mode to enter in the signal handler */
+	if ((register_t)catcher & 1)
+		tf->tf_spsr |= PSR_T;
+	else
+		tf->tf_spsr &= ~PSR_T;
+
+	CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_x[14],
+	    tf->tf_x[13]);
+
+	PROC_LOCK(p);
+	mtx_lock(&psp->ps_mtx);
+
 }

Modified: head/sys/arm64/arm64/identcpu.c
==============================================================================
--- head/sys/arm64/arm64/identcpu.c	Sun Jan 13 18:48:13 2019	(r343003)
+++ head/sys/arm64/arm64/identcpu.c	Sun Jan 13 19:49:46 2019	(r343004)
@@ -49,8 +49,28 @@ static int ident_lock;
 
 char machine[] = "arm64";
 
-SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0,
-    "Machine class");
+#ifdef SCTL_MASK32
+extern int adaptive_machine_arch;
+#endif
+
+static int
+sysctl_hw_machine(SYSCTL_HANDLER_ARGS)
+{
+#ifdef SCTL_MASK32
+	static const char machine32[] = "arm";
+#endif
+	int error;
+#ifdef SCTL_MASK32
+	if ((req->flags & SCTL_MASK32) != 0 && adaptive_machine_arch)
+		error = SYSCTL_OUT(req, machine32, sizeof(machine32));
+	else
+#endif
+		error = SYSCTL_OUT(req, machine, sizeof(machine));
+	return (error);
+}
+
+SYSCTL_PROC(_hw, HW_MACHINE, machine, CTLTYPE_STRING | CTLFLAG_RD |
+	CTLFLAG_MPSAFE, NULL, 0, sysctl_hw_machine, "A", "Machine class");
 
 /*
  * Per-CPU affinity as provided in MPIDR_EL1

Modified: head/sys/arm64/arm64/locore.S
==============================================================================
--- head/sys/arm64/arm64/locore.S	Sun Jan 13 18:48:13 2019	(r343003)
+++ head/sys/arm64/arm64/locore.S	Sun Jan 13 19:49:46 2019	(r343004)
@@ -699,3 +699,21 @@ esigcode:
 	.global	szsigcode
 szsigcode:
 	.quad	esigcode - sigcode
+
+ENTRY(aarch32_sigcode)
+	.word 0xe1a0000d	// mov r0, sp
+	.word 0xe2800040	// add r0, r0, #SIGF_UC
+	.word 0xe59f700c	// ldr r7, [pc, #12]
+	.word 0xef000000	// swi #0
+	.word 0xe59f7008	// ldr r7, [pc, #8]
+	.word 0xef000000	// swi #0
+	.word 0xeafffffa	// b . - 16
+END(aarch32_sigcode)
+	.word SYS_sigreturn
+	.word SYS_exit
+	.align	3
+aarch32_esigcode:
+	.data
+	.global sz_aarch32_sigcode
+sz_aarch32_sigcode:
+	.quad aarch32_esigcode - aarch32_sigcode

Modified: head/sys/arm64/arm64/machdep.c
==============================================================================
--- head/sys/arm64/arm64/machdep.c	Sun Jan 13 18:48:13 2019	(r343003)
+++ head/sys/arm64/arm64/machdep.c	Sun Jan 13 19:49:46 2019	(r343004)
@@ -276,17 +276,36 @@ set_dbregs(struct thread *td, struct dbreg *regs)
 int
 fill_regs32(struct thread *td, struct reg32 *regs)
 {
+	int i;
+	struct trapframe *tf;
 
-	printf("ARM64TODO: fill_regs32");
-	return (EDOOFUS);
+	tf = td->td_frame;
+	for (i = 0; i < 13; i++)
+		regs->r[i] = tf->tf_x[i];
+	regs->r_sp = tf->tf_sp;
+	regs->r_lr = tf->tf_lr;
+	regs->r_pc = tf->tf_elr;
+	regs->r_cpsr = tf->tf_spsr;
+
+	return (0);
 }
 
 int
 set_regs32(struct thread *td, struct reg32 *regs)
 {
+	int i;
+	struct trapframe *tf;
 
-	printf("ARM64TODO: set_regs32");
-	return (EDOOFUS);
+	tf = td->td_frame;
+	for (i = 0; i < 13; i++)
+		tf->tf_x[i] = regs->r[i];
+	tf->tf_sp = regs->r_sp;
+	tf->tf_lr = regs->r_lr;
+	tf->tf_elr = regs->r_pc;
+	tf->tf_spsr = regs->r_cpsr;
+
+
+	return (0);
 }
 
 int

Modified: head/sys/arm64/arm64/undefined.c
==============================================================================
--- head/sys/arm64/arm64/undefined.c	Sun Jan 13 18:48:13 2019	(r343003)
+++ head/sys/arm64/arm64/undefined.c	Sun Jan 13 19:49:46 2019	(r343004)
@@ -35,10 +35,15 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
+#include <sys/proc.h>
 #include <sys/queue.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
+#include <sys/sysent.h>
 
 #include <machine/frame.h>
 #include <machine/undefined.h>
+#include <machine/vmparam.h>
 
 MALLOC_DEFINE(M_UNDEF, "undefhandler", "Undefined instruction handler data");
 
@@ -83,6 +88,33 @@ id_aa64mmfr2_handler(vm_offset_t va, uint32_t insn, st
 	return (0);
 }
 
+#ifdef COMPAT_FREEBSD32
+/* arm32 GDB breakpoints */
+#define GDB_BREAKPOINT	0xe6000011
+#define GDB5_BREAKPOINT	0xe7ffdefe
+static int
+gdb_trapper(vm_offset_t va, uint32_t insn, struct trapframe *frame,
+		uint32_t esr)
+{
+	struct thread *td = curthread;
+
+	if (insn == GDB_BREAKPOINT || insn == GDB5_BREAKPOINT) {
+		if (SV_PROC_FLAG(td->td_proc, SV_ILP32) &&
+		    va < VM_MAXUSER_ADDRESS) {
+			ksiginfo_t ksi;
+
+			ksiginfo_init_trap(&ksi);
+			ksi.ksi_signo = SIGTRAP;
+			ksi.ksi_code = TRAP_TRACE;
+			ksi.ksi_addr = (void *)va;
+			trapsignal(td, &ksi);
+			return 1;
+		}
+	}
+	return 0;
+}
+#endif
+
 void
 undef_init(void)
 {
@@ -91,6 +123,9 @@ undef_init(void)
 	LIST_INIT(&undef_handlers[1]);
 
 	install_undef_handler(false, id_aa64mmfr2_handler);
+#ifdef COMPAT_FREEBSD32
+	install_undef_handler(true, gdb_trapper);
+#endif
 }
 
 void *

Modified: head/sys/arm64/arm64/vm_machdep.c
==============================================================================
--- head/sys/arm64/arm64/vm_machdep.c	Sun Jan 13 18:48:13 2019	(r343003)
+++ head/sys/arm64/arm64/vm_machdep.c	Sun Jan 13 19:49:46 2019	(r343004)
@@ -78,6 +78,7 @@ cpu_fork(struct thread *td1, struct proc *p2, struct t
 		 * this may not have happened.
 		 */
 		td1->td_pcb->pcb_tpidr_el0 = READ_SPECIALREG(tpidr_el0);
+		td1->td_pcb->pcb_tpidrro_el0 = READ_SPECIALREG(tpidrro_el0);
 #ifdef VFP
 		if ((td1->td_pcb->pcb_fpflags & PCB_FP_STARTED) != 0)
 			vfp_save_state(td1, td1->td_pcb);
@@ -97,7 +98,7 @@ cpu_fork(struct thread *td1, struct proc *p2, struct t
 	bcopy(td1->td_frame, tf, sizeof(*tf));
 	tf->tf_x[0] = 0;
 	tf->tf_x[1] = 0;
-	tf->tf_spsr = 0;
+	tf->tf_spsr = td1->td_frame->tf_spsr & PSR_M_32;
 
 	td2->td_frame = tf;
 
@@ -195,7 +196,11 @@ cpu_set_upcall(struct thread *td, void (*entry)(void *
 {
 	struct trapframe *tf = td->td_frame;
 
-	tf->tf_sp = STACKALIGN((uintptr_t)stack->ss_sp + stack->ss_size);
+	/* 32bits processes use r13 for sp */
+	if (td->td_frame->tf_spsr & PSR_M_32)
+		tf->tf_x[13] = STACKALIGN((uintptr_t)stack->ss_sp + stack->ss_size);
+	else
+		tf->tf_sp = STACKALIGN((uintptr_t)stack->ss_sp + stack->ss_size);
 	tf->tf_elr = (register_t)entry;
 	tf->tf_x[0] = (register_t)arg;
 }
@@ -209,9 +214,19 @@ cpu_set_user_tls(struct thread *td, void *tls_base)
 		return (EINVAL);
 
 	pcb = td->td_pcb;
-	pcb->pcb_tpidr_el0 = (register_t)tls_base;
-	if (td == curthread)
-		WRITE_SPECIALREG(tpidr_el0, tls_base);
+	if (td->td_frame->tf_spsr & PSR_M_32) {
+		/* 32bits arm stores the user TLS into tpidrro */
+		pcb->pcb_tpidrro_el0 = (register_t)tls_base;
+		pcb->pcb_tpidr_el0 = (register_t)tls_base;
+		if (td == curthread) {
+			WRITE_SPECIALREG(tpidrro_el0, tls_base);
+			WRITE_SPECIALREG(tpidr_el0, tls_base);
+		}
+	} else {
+		pcb->pcb_tpidr_el0 = (register_t)tls_base;
+		if (td == curthread)
+			WRITE_SPECIALREG(tpidr_el0, tls_base);
+	}
 
 	return (0);
 }

Modified: head/sys/arm64/conf/GENERIC
==============================================================================
--- head/sys/arm64/conf/GENERIC	Sun Jan 13 18:48:13 2019	(r343003)
+++ head/sys/arm64/conf/GENERIC	Sun Jan 13 19:49:46 2019	(r343004)
@@ -52,7 +52,7 @@ options 	PROCFS			# Process filesystem (requires PSEUD
 options 	PSEUDOFS		# Pseudo-filesystem framework
 options 	GEOM_RAID		# Soft RAID functionality.
 options 	GEOM_LABEL		# Provides labelization
-options 	COMPAT_FREEBSD32	# Incomplete, but used by cloudabi32.ko.
+options 	COMPAT_FREEBSD32	# Compatible with FreeBSD/arm
 options 	COMPAT_FREEBSD11	# Compatible with FreeBSD11
 options 	SCSI_DELAY=5000		# Delay (in ms) before probing SCSI
 options 	KTRACE			# ktrace(1) support

Modified: head/sys/arm64/include/armreg.h
==============================================================================
--- head/sys/arm64/include/armreg.h	Sun Jan 13 18:48:13 2019	(r343003)
+++ head/sys/arm64/include/armreg.h	Sun Jan 13 19:49:46 2019	(r343004)
@@ -575,7 +575,11 @@
 #define	PSR_M_EL1h	0x00000005
 #define	PSR_M_EL2t	0x00000008
 #define	PSR_M_EL2h	0x00000009
+#define	PSR_M_64	0x00000000
+#define	PSR_M_32	0x00000010
 #define	PSR_M_MASK	0x0000000f
+
+#define	PSR_T		0x00000020
 
 #define	PSR_AARCH32	0x00000010
 #define	PSR_F		0x00000040

Modified: head/sys/arm64/include/elf.h
==============================================================================
--- head/sys/arm64/include/elf.h	Sun Jan 13 18:48:13 2019	(r343003)
+++ head/sys/arm64/include/elf.h	Sun Jan 13 19:49:46 2019	(r343004)
@@ -81,6 +81,10 @@ __ElfType(Auxinfo);
 #define	ELF_TARG_VER	1
 #endif
 
+#if __ELF_WORD_SIZE == 32
+#define	ET_DYN_LOAD_ADDR 0x12000
+#else
 #define	ET_DYN_LOAD_ADDR 0x100000
+#endif
 
 #endif /* !_MACHINE_ELF_H_ */

Modified: head/sys/arm64/include/frame.h
==============================================================================
--- head/sys/arm64/include/frame.h	Sun Jan 13 18:48:13 2019	(r343003)
+++ head/sys/arm64/include/frame.h	Sun Jan 13 19:49:46 2019	(r343004)
@@ -70,6 +70,14 @@ struct frame {
 	int dummy;
 };
 
+#ifdef COMPAT_FREEBSD32
+struct sigframe32 {
+	struct siginfo32		sf_si;
+	ucontext32_t			sf_uc;
+	mcontext32_vfp_t		sf_vfp;
+};
+#endif /* COMPAT_FREEBSD32 */
+
 #endif /* !LOCORE */
 
 #endif /* !_MACHINE_FRAME_H_ */

Modified: head/sys/arm64/include/reg.h
==============================================================================
--- head/sys/arm64/include/reg.h	Sun Jan 13 18:48:13 2019	(r343003)
+++ head/sys/arm64/include/reg.h	Sun Jan 13 19:49:46 2019	(r343004)
@@ -42,7 +42,11 @@ struct reg {
 };
 
 struct reg32 {
-	int dummy;
+	unsigned int r[13];
+	unsigned int r_sp;
+	unsigned int r_lr;
+	unsigned int r_pc;
+	unsigned int r_cpsr;
 };
 
 struct fpreg {

Modified: head/sys/arm64/include/ucontext.h
==============================================================================
--- head/sys/arm64/include/ucontext.h	Sun Jan 13 18:48:13 2019	(r343003)
+++ head/sys/arm64/include/ucontext.h	Sun Jan 13 19:49:46 2019	(r343004)
@@ -61,4 +61,30 @@ struct __mcontext {
 
 typedef struct __mcontext mcontext_t;
 
+#ifdef COMPAT_FREEBSD32
+#include <compat/freebsd32/freebsd32_signal.h>
+typedef struct __mcontext32 {
+	uint32_t		mc_gregset[17];
+	uint32_t		mc_vfp_size;
+	uint32_t		mc_vfp_ptr;
+	uint32_t		mc_spare[33];
+} mcontext32_t;
+
+typedef struct __ucontext32 {
+	sigset_t		uc_sigmask;
+	mcontext32_t		uc_mcontext;
+	u_int32_t		uc_link;
+	struct sigaltstack32	uc_stack;
+	u_int32_t		uc_flags;
+	u_int32_t		__spare__[4];
+} ucontext32_t;
+
+typedef struct __mcontext32_vfp {
+	__uint64_t	mcv_reg[32];
+	__uint32_t	mcv_fpscr;
+} mcontext32_vfp_t;
+
+#endif /* COMPAT_FREEBSD32 */
+
+
 #endif	/* !_MACHINE_UCONTEXT_H_ */

Modified: head/sys/arm64/include/vfp.h
==============================================================================
--- head/sys/arm64/include/vfp.h	Sun Jan 13 18:48:13 2019	(r343003)
+++ head/sys/arm64/include/vfp.h	Sun Jan 13 19:49:46 2019	(r343004)
@@ -65,6 +65,11 @@ int fpu_kern_leave(struct thread *, struct fpu_kern_ct
 int fpu_kern_thread(u_int);
 int is_fpu_kern_thread(u_int);
 
+/* Convert to and from Aarch32 FPSCR to Aarch64 FPCR/FPSR */
+#define VFP_FPSCR_FROM_SRCR(vpsr, vpcr) ((vpsr) | ((vpcr) & 0x7c00000))
+#define VFP_FPSR_FROM_FPSCR(vpscr) ((vpscr) &~ 0x7c00000)
+#define VFP_FPCR_FROM_FPSCR(vpsrc) ((vpsrc) & 0x7c00000)
+
 #endif
 
 #endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201901131949.x0DJnkRL089992>