Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 May 2015 19:20:31 +0000 (UTC)
From:      Andrew Turner <andrew@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r282779 - head/sys/arm/arm
Message-ID:  <201505111920.t4BJKVYk033104@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: andrew
Date: Mon May 11 19:20:30 2015
New Revision: 282779
URL: https://svnweb.freebsd.org/changeset/base/282779

Log:
  Add the kernel support for Thumb-2. It is only supported on ARMv7 as the
  main ARMv6 target, the Raspberry Pi, doesn't support Thumb-2.
  
  This as been tested with a Thumb-2 userland, however building one is
  currently unsupported as there are known toolchain issues breaking some
  binaries. Further work will also be needed to decide on the method of
  selecting which instruction set to build for, and to benchmark both to
  find how building everything as Thumb-2 will affect performance.
  
  Relnotes:	yes

Modified:
  head/sys/arm/arm/exception.S
  head/sys/arm/arm/machdep.c
  head/sys/arm/arm/syscall.c
  head/sys/arm/arm/undefined.c
  head/sys/arm/arm/vm_machdep.c

Modified: head/sys/arm/arm/exception.S
==============================================================================
--- head/sys/arm/arm/exception.S	Mon May 11 19:04:32 2015	(r282778)
+++ head/sys/arm/arm/exception.S	Mon May 11 19:20:30 2015	(r282779)
@@ -364,7 +364,6 @@ END(data_abort_entry)
  * on exit (without transitioning back through the undefined mode stack).
  */
 ASENTRY_NP(undefined_entry)
-	sub	lr, lr, #4		/* Adjust the lr. Transition to scv32 */
 	PUSHFRAMEINSVC			/* mode stack, build trapframe there. */
 	adr	lr, exception_exit      /* Return from handler via standard */
 	mov	r0, sp			/* exception exit routine.  Pass the */

Modified: head/sys/arm/arm/machdep.c
==============================================================================
--- head/sys/arm/arm/machdep.c	Mon May 11 19:04:32 2015	(r282778)
+++ head/sys/arm/arm/machdep.c	Mon May 11 19:20:30 2015	(r282779)
@@ -87,6 +87,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_page.h>
 #include <vm/vm_pager.h>
 
+#include <machine/acle-compat.h>
 #include <machine/armreg.h>
 #include <machine/atags.h>
 #include <machine/cpu.h>
@@ -337,6 +338,13 @@ sendsig(catcher, ksi, mask)
 	tf->tf_pc = (register_t)catcher;
 	tf->tf_usr_sp = (register_t)fp;
 	tf->tf_usr_lr = (register_t)(PS_STRINGS - *(p->p_sysent->sv_szsigcode));
+	/* Set the mode to enter in the signal handler */
+#if __ARM_ARCH >= 7
+	if ((register_t)catcher & 1)
+		tf->tf_spsr |= PSR_T;
+	else
+		tf->tf_spsr &= ~PSR_T;
+#endif
 
 	CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_usr_lr,
 	    tf->tf_usr_sp);
@@ -626,6 +634,10 @@ ptrace_single_step(struct thread *td)
 	struct proc *p;
 	int error;
 	
+	/* TODO: This needs to be updated for Thumb-2 */
+	if ((td->td_frame->tf_spsr & PSR_T) != 0)
+		return (EINVAL);
+
 	KASSERT(td->td_md.md_ptrace_instr == 0,
 	 ("Didn't clear single step"));
 	p = td->td_proc;
@@ -649,6 +661,10 @@ ptrace_clear_single_step(struct thread *
 {
 	struct proc *p;
 
+	/* TODO: This needs to be updated for Thumb-2 */
+	if ((td->td_frame->tf_spsr & PSR_T) != 0)
+		return (EINVAL);
+
 	if (td->td_md.md_ptrace_instr) {
 		p = td->td_proc;
 		PROC_UNLOCK(p);

Modified: head/sys/arm/arm/syscall.c
==============================================================================
--- head/sys/arm/arm/syscall.c	Mon May 11 19:04:32 2015	(r282778)
+++ head/sys/arm/arm/syscall.c	Mon May 11 19:20:30 2015	(r282779)
@@ -171,16 +171,7 @@ swi_handler(struct trapframe *frame)
 	td->td_frame = frame;
 
 	td->td_pticks = 0;
-	/*
-	 * Make sure the program counter is correctly aligned so we
-	 * don't take an alignment fault trying to read the opcode.
-	 * XXX: Fix for Thumb mode
-	 */
-	if (__predict_false(((frame->tf_pc - INSN_SIZE) & 3) != 0)) {
-		call_trapsignal(td, SIGILL, 0);
-		userret(td, frame);
-		return;
-	}
+
 	/*
 	 * Enable interrupts if they were enabled before the exception.
 	 * Since all syscalls *should* come from user mode it will always

Modified: head/sys/arm/arm/undefined.c
==============================================================================
--- head/sys/arm/arm/undefined.c	Mon May 11 19:04:32 2015	(r282778)
+++ head/sys/arm/arm/undefined.c	Mon May 11 19:20:30 2015	(r282779)
@@ -86,6 +86,19 @@ __FBSDID("$FreeBSD$");
 #include <machine/db_machdep.h>
 #endif
 
+#define	ARM_COPROC_INSN(insn)	(((insn) & (1 << 27)) != 0)
+#define	ARM_VFP_INSN(insn)	((((insn) & 0xfe000000) == 0xf2000000) || \
+    (((insn) & 0xff100000) == 0xf4000000))
+#define	ARM_COPROC(insn)	(((insn) >> 8) & 0xf)
+
+#define	THUMB_32BIT_INSN(insn)	((insn) >= 0xe800)
+#define	THUMB_COPROC_INSN(insn)	(((insn) & (3 << 26)) == (3 << 26))
+#define	THUMB_COPROC_UNDEFINED(insn) (((insn) & 0x3e << 20) == 0)
+#define	THUMB_VFP_INSN(insn)	(((insn) & (3 << 24)) == (3 << 24))
+#define	THUMB_COPROC(insn)	(((insn) >> 8) & 0xf)
+
+#define	COPROC_VFP	10
+
 #ifdef KDTRACE_HOOKS
 int (*dtrace_invop_jump_addr)(struct trapframe *);
 #endif
@@ -179,6 +192,7 @@ undefinedinstruction(struct trapframe *f
 	int fault_code;
 	int coprocessor;
 	struct undefined_handler *uh;
+	int error;
 #ifdef VERBOSE_ARM32
 	int s;
 #endif
@@ -192,6 +206,12 @@ undefinedinstruction(struct trapframe *f
 
 	PCPU_INC(cnt.v_trap);
 
+#if __ARM_ARCH >= 7
+	if ((frame->tf_spsr & PSR_T) != 0)
+		frame->tf_pc -= THUMB_INSN_SIZE;
+	else
+#endif
+		frame->tf_pc -= INSN_SIZE;
 	fault_pc = frame->tf_pc;
 
 	/*
@@ -200,11 +220,72 @@ undefinedinstruction(struct trapframe *f
 	 */
 	td = curthread == NULL ? &thread0 : curthread;
 
-	/*
-	 * Make sure the program counter is correctly aligned so we
-	 * don't take an alignment fault trying to read the opcode.
-	 */
-	if (__predict_false((fault_pc & 3) != 0)) {
+	coprocessor = 0;
+	if ((frame->tf_spsr & PSR_T) == 0) {
+		/*
+		 * Make sure the program counter is correctly aligned so we
+		 * don't take an alignment fault trying to read the opcode.
+		 */
+		if (__predict_false((fault_pc & 3) != 0)) {
+			ksiginfo_init_trap(&ksi);
+			ksi.ksi_signo = SIGILL;
+			ksi.ksi_code = ILL_ILLADR;
+			ksi.ksi_addr = (u_int32_t *)(intptr_t) fault_pc;
+			trapsignal(td, &ksi);
+			userret(td, frame);
+			return;
+		}
+
+		/*
+		 * Should use fuword() here .. but in the interests of
+		 * squeezing every bit of speed we will just use ReadWord().
+		 * We know the instruction can be read as was just executed
+		 * so this will never fail unless the kernel is screwed up
+		 * in which case it does not really matter does it ?
+		 */
+
+		fault_instruction = *(u_int32_t *)fault_pc;
+
+		/* Check for coprocessor instruction */
+
+		/*
+		 * According to the datasheets you only need to look at bit
+		 * 27 of the instruction to tell the difference between and
+		 * undefined instruction and a coprocessor instruction
+		 * following an undefined instruction trap.
+		 */
+
+		if (ARM_COPROC_INSN(fault_instruction))
+			coprocessor = ARM_COPROC(fault_instruction);
+		else {          /* check for special instructions */
+			if (ARM_VFP_INSN(fault_instruction))
+				coprocessor = COPROC_VFP; /* vfp / simd */
+		}
+	} else {
+#if __ARM_ARCH >= 7
+		fault_instruction = *(uint16_t *)fault_pc;
+		if (THUMB_32BIT_INSN(fault_instruction)) {
+			fault_instruction <<= 16;
+			fault_instruction |= *(uint16_t *)(fault_pc + 2);
+
+			/*
+			 * Is it a Coprocessor, Advanced SIMD, or
+			 * Floating-point instruction.
+			 */
+			if (THUMB_COPROC_INSN(fault_instruction)) {
+				if (THUMB_COPROC_UNDEFINED(fault_instruction)) {
+					/* undefined insn */
+				} else if (THUMB_VFP_INSN(fault_instruction))
+					coprocessor = COPROC_VFP;
+				else
+					coprocessor =
+					    THUMB_COPROC(fault_instruction);
+			}
+		}
+#else
+		/*
+		 * No support for Thumb-2 on this cpu
+		 */
 		ksiginfo_init_trap(&ksi);
 		ksi.ksi_signo = SIGILL;
 		ksi.ksi_code = ILL_ILLADR;
@@ -212,41 +293,8 @@ undefinedinstruction(struct trapframe *f
 		trapsignal(td, &ksi);
 		userret(td, frame);
 		return;
-	}
-
-	/*
-	 * Should use fuword() here .. but in the interests of squeezing every
-	 * bit of speed we will just use ReadWord(). We know the instruction
-	 * can be read as was just executed so this will never fail unless the
-	 * kernel is screwed up in which case it does not really matter does
-	 * it ?
-	 */
-
-	fault_instruction = *(u_int32_t *)fault_pc;
-
-	/* Update vmmeter statistics */
-#if 0
-	uvmexp.traps++;
 #endif
-	/* Check for coprocessor instruction */
-
-	/*
-	 * According to the datasheets you only need to look at bit 27 of the
-	 * instruction to tell the difference between and undefined
-	 * instruction and a coprocessor instruction following an undefined
-	 * instruction trap.
-	 */
-
-	coprocessor = 0;
-	if ((fault_instruction & (1 << 27)) != 0)
-		coprocessor = (fault_instruction >> 8) & 0x0f;
-#ifdef VFP
-	else {          /* check for special instructions */
-		if (((fault_instruction & 0xfe000000) == 0xf2000000) ||
-		    ((fault_instruction & 0xff100000) == 0xf4000000))
-			coprocessor = 10;       /* vfp / simd */
 	}
-#endif	/* VFP */
 
 	if ((frame->tf_spsr & PSR_MODE) == PSR_USR32_MODE) {
 		/*
@@ -264,13 +312,24 @@ undefinedinstruction(struct trapframe *f
 			       fault_code) == 0)
 		    break;
 
-	if (fault_code & FAULT_USER && fault_instruction == PTRACE_BREAKPOINT) {
-		PROC_LOCK(td->td_proc);
-		_PHOLD(td->td_proc);
-		ptrace_clear_single_step(td);
-		_PRELE(td->td_proc);
-		PROC_UNLOCK(td->td_proc);
-		return;
+	if (fault_code & FAULT_USER) {
+		/* TODO: No support for ptrace from Thumb-2 */
+		if ((frame->tf_spsr & PSR_T) == 0 &&
+		    fault_instruction == PTRACE_BREAKPOINT) {
+			PROC_LOCK(td->td_proc);
+			_PHOLD(td->td_proc);
+			error = ptrace_clear_single_step(td);
+			_PRELE(td->td_proc);
+			PROC_UNLOCK(td->td_proc);
+			if (error != 0) {
+				ksiginfo_init_trap(&ksi);
+				ksi.ksi_signo = SIGILL;
+				ksi.ksi_code = ILL_ILLOPC;
+				ksi.ksi_addr = (u_int32_t *)(intptr_t) fault_pc;
+				trapsignal(td, &ksi);
+			}
+			return;
+		}
 	}
 
 	if (uh == NULL && (fault_code & FAULT_USER)) {

Modified: head/sys/arm/arm/vm_machdep.c
==============================================================================
--- head/sys/arm/arm/vm_machdep.c	Mon May 11 19:04:32 2015	(r282778)
+++ head/sys/arm/arm/vm_machdep.c	Mon May 11 19:20:30 2015	(r282779)
@@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/uma.h>
 #include <vm/uma_int.h>
 
+#include <machine/acle-compat.h>
 #include <machine/md_var.h>
 #include <machine/vfp.h>
 
@@ -204,7 +205,12 @@ cpu_set_syscall_retval(struct thread *td
 		/*
 		 * Reconstruct the pc to point at the swi.
 		 */
-		frame->tf_pc -= INSN_SIZE;
+#if __ARM_ARCH >= 7
+		if ((frame->tf_spsr & PSR_T) != 0)
+			frame->tf_pc -= THUMB_INSN_SIZE;
+		else
+#endif
+			frame->tf_pc -= INSN_SIZE;
 		break;
 	case EJUSTRETURN:
 		/* nothing to do */



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