svn commit: r338961 - in head/sys/arm64: arm64 include
Andrew Turner
andrew at FreeBSD.org
Thu Sep 27 13:50:59 UTC 2018
Author: andrew
Date: Thu Sep 27 13:50:57 2018
New Revision: 338961
URL: https://svnweb.freebsd.org/changeset/base/338961
Log:
Move the undefined instruction handler to identcpu.c so we have access
to the registers from boot.
Approved by: re (kib)
Sponsored by: ABT Systems Ltd
Differential Revision: https://reviews.freebsd.org/D17301
Modified:
head/sys/arm64/arm64/identcpu.c
head/sys/arm64/arm64/undefined.c
head/sys/arm64/include/undefined.h
Modified: head/sys/arm64/arm64/identcpu.c
==============================================================================
--- head/sys/arm64/arm64/identcpu.c Thu Sep 27 12:20:32 2018 (r338960)
+++ head/sys/arm64/arm64/identcpu.c Thu Sep 27 13:50:57 2018 (r338961)
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <machine/atomic.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
+#include <machine/undefined.h>
static int ident_lock;
@@ -162,6 +163,98 @@ const struct cpu_implementers cpu_implementers[] = {
CPU_IMPLEMENTER_NONE,
};
+struct mrs_safe_value {
+ u_int CRm;
+ u_int Op2;
+ uint64_t value;
+};
+
+static struct mrs_safe_value safe_values[] = {
+ { /* id_aa64pfr0_el1 */
+ .CRm = 4,
+ .Op2 = 0,
+ .value = ID_AA64PFR0_ADV_SIMD_NONE | ID_AA64PFR0_FP_NONE |
+ ID_AA64PFR0_EL1_64 | ID_AA64PFR0_EL0_64,
+ },
+ { /* id_aa64dfr0_el1 */
+ .CRm = 5,
+ .Op2 = 0,
+ .value = ID_AA64DFR0_DEBUG_VER_8,
+ },
+};
+
+static int
+user_mrs_handler(vm_offset_t va, uint32_t insn, struct trapframe *frame,
+ uint32_t esr)
+{
+ uint64_t value;
+ int CRm, Op2, i, reg;
+
+ if ((insn & MRS_MASK) != MRS_VALUE)
+ return (0);
+
+ /*
+ * We only emulate Op0 == 3, Op1 == 0, CRn == 0, CRm == {0, 4-7}.
+ * These are in the EL1 CPU identification space.
+ * CRm == 0 holds MIDR_EL1, MPIDR_EL1, and REVID_EL1.
+ * CRm == {4-7} holds the ID_AA64 registers.
+ *
+ * For full details see the ARMv8 ARM (ARM DDI 0487C.a)
+ * Table D9-2 System instruction encodings for non-Debug System
+ * register accesses.
+ */
+ if (mrs_Op0(insn) != 3 || mrs_Op1(insn) != 0 || mrs_CRn(insn) != 0)
+ return (0);
+
+ CRm = mrs_CRm(insn);
+ if (CRm > 7 || (CRm < 4 && CRm != 0))
+ return (0);
+
+ Op2 = mrs_Op2(insn);
+ value = 0;
+
+ for (i = 0; i < nitems(safe_values); i++) {
+ if (safe_values[i].CRm == CRm && safe_values[i].Op2 == Op2) {
+ value = safe_values[i].value;
+ break;
+ }
+ }
+
+ if (CRm == 0) {
+ switch (Op2) {
+ case 0:
+ value = READ_SPECIALREG(midr_el1);
+ break;
+ case 5:
+ value = READ_SPECIALREG(mpidr_el1);
+ break;
+ case 6:
+ value = READ_SPECIALREG(revidr_el1);
+ break;
+ default:
+ return (0);
+ }
+ }
+
+ /*
+ * We will handle this instruction, move to the next so we
+ * don't trap here again.
+ */
+ frame->tf_elr += INSN_SIZE;
+
+ reg = MRS_REGISTER(insn);
+ /* If reg is 31 then write to xzr, i.e. do nothing */
+ if (reg == 31)
+ return (1);
+
+ if (reg < nitems(frame->tf_x))
+ frame->tf_x[reg] = value;
+ else if (reg == 30)
+ frame->tf_lr = value;
+
+ return (1);
+}
+
static void
identify_cpu_sysinit(void *dummy __unused)
{
@@ -170,6 +263,8 @@ identify_cpu_sysinit(void *dummy __unused)
CPU_FOREACH(cpu) {
print_cpu_features(cpu);
}
+
+ install_undef_handler(true, user_mrs_handler);
}
SYSINIT(idenrity_cpu, SI_SUB_SMP, SI_ORDER_ANY, identify_cpu_sysinit, NULL);
Modified: head/sys/arm64/arm64/undefined.c
==============================================================================
--- head/sys/arm64/arm64/undefined.c Thu Sep 27 12:20:32 2018 (r338960)
+++ head/sys/arm64/arm64/undefined.c Thu Sep 27 13:50:57 2018 (r338961)
@@ -53,135 +53,6 @@ struct undef_handler {
*/
LIST_HEAD(, undef_handler) undef_handlers[2];
-#define MRS_MASK 0xfff00000
-#define MRS_VALUE 0xd5300000
-#define MRS_SPECIAL(insn) ((insn) & 0x000fffe0)
-#define MRS_REGISTER(insn) ((insn) & 0x0000001f)
-#define MRS_Op0_SHIFT 19
-#define MRS_Op0_MASK 0x00080000
-#define MRS_Op1_SHIFT 16
-#define MRS_Op1_MASK 0x00070000
-#define MRS_CRn_SHIFT 12
-#define MRS_CRn_MASK 0x0000f000
-#define MRS_CRm_SHIFT 8
-#define MRS_CRm_MASK 0x00000f00
-#define MRS_Op2_SHIFT 5
-#define MRS_Op2_MASK 0x000000e0
-#define MRS_Rt_SHIFT 0
-#define MRS_Rt_MASK 0x0000001f
-
-static inline int
-mrs_Op0(uint32_t insn)
-{
-
- /* op0 is encoded without the top bit in a mrs instruction */
- return (2 | ((insn & MRS_Op0_MASK) >> MRS_Op0_SHIFT));
-}
-
-#define MRS_GET(op) \
-static inline int \
-mrs_##op(uint32_t insn) \
-{ \
- \
- return ((insn & MRS_##op##_MASK) >> MRS_##op##_SHIFT); \
-}
-MRS_GET(Op1)
-MRS_GET(CRn)
-MRS_GET(CRm)
-MRS_GET(Op2)
-
-struct mrs_safe_value {
- u_int CRm;
- u_int Op2;
- uint64_t value;
-};
-
-static struct mrs_safe_value safe_values[] = {
- { /* id_aa64pfr0_el1 */
- .CRm = 4,
- .Op2 = 0,
- .value = ID_AA64PFR0_ADV_SIMD_NONE | ID_AA64PFR0_FP_NONE |
- ID_AA64PFR0_EL1_64 | ID_AA64PFR0_EL0_64,
- },
- { /* id_aa64dfr0_el1 */
- .CRm = 5,
- .Op2 = 0,
- .value = ID_AA64DFR0_DEBUG_VER_8,
- },
-};
-
-static int
-user_mrs_handler(vm_offset_t va, uint32_t insn, struct trapframe *frame,
- uint32_t esr)
-{
- uint64_t value;
- int CRm, Op2, i, reg;
-
- if ((insn & MRS_MASK) != MRS_VALUE)
- return (0);
-
- /*
- * We only emulate Op0 == 3, Op1 == 0, CRn == 0, CRm == {0, 4-7}.
- * These are in the EL1 CPU identification space.
- * CRm == 0 holds MIDR_EL1, MPIDR_EL1, and REVID_EL1.
- * CRm == {4-7} holds the ID_AA64 registers.
- *
- * For full details see the ARMv8 ARM (ARM DDI 0487C.a)
- * Table D9-2 System instruction encodings for non-Debug System
- * register accesses.
- */
- if (mrs_Op0(insn) != 3 || mrs_Op1(insn) != 0 || mrs_CRn(insn) != 0)
- return (0);
-
- CRm = mrs_CRm(insn);
- if (CRm > 7 || (CRm < 4 && CRm != 0))
- return (0);
-
- Op2 = mrs_Op2(insn);
- value = 0;
-
- for (i = 0; i < nitems(safe_values); i++) {
- if (safe_values[i].CRm == CRm && safe_values[i].Op2 == Op2) {
- value = safe_values[i].value;
- break;
- }
- }
-
- if (CRm == 0) {
- switch (Op2) {
- case 0:
- value = READ_SPECIALREG(midr_el1);
- break;
- case 5:
- value = READ_SPECIALREG(mpidr_el1);
- break;
- case 6:
- value = READ_SPECIALREG(revidr_el1);
- break;
- default:
- return (0);
- }
- }
-
- /*
- * We will handle this instruction, move to the next so we
- * don't trap here again.
- */
- frame->tf_elr += INSN_SIZE;
-
- reg = MRS_REGISTER(insn);
- /* If reg is 31 then write to xzr, i.e. do nothing */
- if (reg == 31)
- return (1);
-
- if (reg < nitems(frame->tf_x))
- frame->tf_x[reg] = value;
- else if (reg == 30)
- frame->tf_lr = value;
-
- return (1);
-}
-
/*
* Work around a bug in QEMU prior to 2.5.1 where reading unknown ID
* registers would raise an exception when they should return 0.
@@ -219,7 +90,6 @@ undef_init(void)
LIST_INIT(&undef_handlers[0]);
LIST_INIT(&undef_handlers[1]);
- install_undef_handler(true, user_mrs_handler);
install_undef_handler(false, id_aa64mmfr2_handler);
}
Modified: head/sys/arm64/include/undefined.h
==============================================================================
--- head/sys/arm64/include/undefined.h Thu Sep 27 12:20:32 2018 (r338960)
+++ head/sys/arm64/include/undefined.h Thu Sep 27 13:50:57 2018 (r338961)
@@ -36,6 +36,43 @@
typedef int (*undef_handler_t)(vm_offset_t, uint32_t, struct trapframe *,
uint32_t);
+#define MRS_MASK 0xfff00000
+#define MRS_VALUE 0xd5300000
+#define MRS_SPECIAL(insn) ((insn) & 0x000fffe0)
+#define MRS_REGISTER(insn) ((insn) & 0x0000001f)
+#define MRS_Op0_SHIFT 19
+#define MRS_Op0_MASK 0x00080000
+#define MRS_Op1_SHIFT 16
+#define MRS_Op1_MASK 0x00070000
+#define MRS_CRn_SHIFT 12
+#define MRS_CRn_MASK 0x0000f000
+#define MRS_CRm_SHIFT 8
+#define MRS_CRm_MASK 0x00000f00
+#define MRS_Op2_SHIFT 5
+#define MRS_Op2_MASK 0x000000e0
+#define MRS_Rt_SHIFT 0
+#define MRS_Rt_MASK 0x0000001f
+
+static inline int
+mrs_Op0(uint32_t insn)
+{
+
+ /* op0 is encoded without the top bit in a mrs instruction */
+ return (2 | ((insn & MRS_Op0_MASK) >> MRS_Op0_SHIFT));
+}
+
+#define MRS_GET(op) \
+static inline int \
+mrs_##op(uint32_t insn) \
+{ \
+ \
+ return ((insn & MRS_##op##_MASK) >> MRS_##op##_SHIFT); \
+}
+MRS_GET(Op1)
+MRS_GET(CRn)
+MRS_GET(CRm)
+MRS_GET(Op2)
+
void undef_init(void);
void *install_undef_handler(bool, undef_handler_t);
void remove_undef_handler(void *);
More information about the svn-src-all
mailing list