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 *);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to