git: 18af5a180b29 - main - arm64: Enable MOPS usage in the kernel
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 10 Feb 2026 15:43:30 UTC
The branch main has been updated by andrew:
URL: https://cgit.FreeBSD.org/src/commit/?id=18af5a180b29f425b8427263be5517d3573ca220
commit 18af5a180b29f425b8427263be5517d3573ca220
Author: Sarah Walker <sarah.walker2@arm.com>
AuthorDate: 2026-02-09 20:39:53 +0000
Commit: Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2026-02-10 15:39:56 +0000
arm64: Enable MOPS usage in the kernel
Support handling kernel-side MOE exceptions.
Reported by: andrew
Sponsored by: Arm Ltd
Differential Revision: https://reviews.freebsd.org/D54943
---
sys/arm64/arm64/trap.c | 123 +++++++++++++++++++++++++------------------------
1 file changed, 63 insertions(+), 60 deletions(-)
diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c
index 3de56187657c..b3c68fa4826f 100644
--- a/sys/arm64/arm64/trap.c
+++ b/sys/arm64/arm64/trap.c
@@ -480,6 +480,66 @@ fpe_trap(struct thread *td, void *addr, uint32_t exception)
}
#endif
+static void
+handle_moe(struct thread *td, struct trapframe *frame, uint64_t esr)
+{
+ uint64_t src;
+ uint64_t dest;
+ uint64_t size;
+ int src_reg;
+ int dest_reg;
+ int size_reg;
+ int format_option;
+
+ format_option = esr & ISS_MOE_FORMAT_OPTION_MASK;
+ dest_reg = (esr & ISS_MOE_DESTREG_MASK) >> ISS_MOE_DESTREG_SHIFT;
+ size_reg = (esr & ISS_MOE_SIZEREG_MASK) >> ISS_MOE_SIZEREG_SHIFT;
+ dest = frame->tf_x[dest_reg];
+ size = frame->tf_x[size_reg];
+
+ /*
+ * Put the registers back in the original format suitable for a
+ * prologue instruction, using the generic return routine from the
+ * Arm ARM (DDI 0487I.a) rules CNTMJ and MWFQH.
+ */
+ if (esr & ISS_MOE_MEMINST) {
+ /* SET* instruction */
+ if (format_option == ISS_MOE_FORMAT_OPTION_A ||
+ format_option == ISS_MOE_FORMAT_OPTION_A2) {
+ /* Format is from Option A; forward set */
+ frame->tf_x[dest_reg] = dest + size;
+ frame->tf_x[size_reg] = -size;
+ }
+ } else {
+ /* CPY* instruction */
+ src_reg = (esr & ISS_MOE_SRCREG_MASK) >> ISS_MOE_SRCREG_SHIFT;
+ src = frame->tf_x[src_reg];
+
+ if (format_option == ISS_MOE_FORMAT_OPTION_B ||
+ format_option == ISS_MOE_FORMAT_OPTION_B2) {
+ /* Format is from Option B */
+ if (frame->tf_spsr & PSR_N) {
+ /* Backward copy */
+ frame->tf_x[dest_reg] = dest - size;
+ frame->tf_x[src_reg] = src + size;
+ }
+ } else {
+ /* Format is from Option A */
+ if (frame->tf_x[size_reg] & (1UL << 63)) {
+ /* Forward copy */
+ frame->tf_x[dest_reg] = dest + size;
+ frame->tf_x[src_reg] = src + size;
+ frame->tf_x[size_reg] = -size;
+ }
+ }
+ }
+
+ if (esr & ISS_MOE_FROM_EPILOGUE)
+ frame->tf_elr -= 8;
+ else
+ frame->tf_elr -= 4;
+}
+
/*
* See the comment above data_abort().
*/
@@ -589,6 +649,9 @@ do_el1h_sync(struct thread *td, struct trapframe *frame)
print_gp_register("far", far);
panic("Branch Target exception");
break;
+ case EXCP_MOE:
+ handle_moe(td, frame, esr);
+ break;
default:
print_registers(frame);
print_gp_register("far", far);
@@ -597,66 +660,6 @@ do_el1h_sync(struct thread *td, struct trapframe *frame)
}
}
-static void
-handle_moe(struct thread *td, struct trapframe *frame, uint64_t esr)
-{
- uint64_t src;
- uint64_t dest;
- uint64_t size;
- int src_reg;
- int dest_reg;
- int size_reg;
- int format_option;
-
- format_option = esr & ISS_MOE_FORMAT_OPTION_MASK;
- dest_reg = (esr & ISS_MOE_DESTREG_MASK) >> ISS_MOE_DESTREG_SHIFT;
- size_reg = (esr & ISS_MOE_SIZEREG_MASK) >> ISS_MOE_SIZEREG_SHIFT;
- dest = frame->tf_x[dest_reg];
- size = frame->tf_x[size_reg];
-
- /*
- * Put the registers back in the original format suitable for a
- * prologue instruction, using the generic return routine from the
- * Arm ARM (DDI 0487I.a) rules CNTMJ and MWFQH.
- */
- if (esr & ISS_MOE_MEMINST) {
- /* SET* instruction */
- if (format_option == ISS_MOE_FORMAT_OPTION_A ||
- format_option == ISS_MOE_FORMAT_OPTION_A2) {
- /* Format is from Option A; forward set */
- frame->tf_x[dest_reg] = dest + size;
- frame->tf_x[size_reg] = -size;
- }
- } else {
- /* CPY* instruction */
- src_reg = (esr & ISS_MOE_SRCREG_MASK) >> ISS_MOE_SRCREG_SHIFT;
- src = frame->tf_x[src_reg];
-
- if (format_option == ISS_MOE_FORMAT_OPTION_B ||
- format_option == ISS_MOE_FORMAT_OPTION_B2) {
- /* Format is from Option B */
- if (frame->tf_spsr & PSR_N) {
- /* Backward copy */
- frame->tf_x[dest_reg] = dest - size;
- frame->tf_x[src_reg] = src + size;
- }
- } else {
- /* Format is from Option A */
- if (frame->tf_x[size_reg] & (1UL << 63)) {
- /* Forward copy */
- frame->tf_x[dest_reg] = dest + size;
- frame->tf_x[src_reg] = src + size;
- frame->tf_x[size_reg] = -size;
- }
- }
- }
-
- if (esr & ISS_MOE_FROM_EPILOGUE)
- frame->tf_elr -= 8;
- else
- frame->tf_elr -= 4;
-}
-
void
do_el0_sync(struct thread *td, struct trapframe *frame)
{