Changeset View
Changeset View
Standalone View
Standalone View
sys/arm64/arm64/trap.c
| Show First 20 Lines • Show All 474 Lines • ▼ Show 20 Lines | else if ((exception & ISS_FP_UFF) != 0) | ||||
| code = FPE_FLTUND; | code = FPE_FLTUND; | ||||
| else if ((exception & ISS_FP_IXF) != 0) | else if ((exception & ISS_FP_IXF) != 0) | ||||
| code = FPE_FLTRES; | code = FPE_FLTRES; | ||||
| } | } | ||||
| call_trapsignal(td, SIGFPE, code, addr, exception); | call_trapsignal(td, SIGFPE, code, addr, exception); | ||||
| } | } | ||||
| #endif | #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(). | * See the comment above data_abort(). | ||||
| */ | */ | ||||
| void NO_PERTHREAD_SSP | void NO_PERTHREAD_SSP | ||||
| do_el1h_sync(struct thread *td, struct trapframe *frame) | do_el1h_sync(struct thread *td, struct trapframe *frame) | ||||
| { | { | ||||
| uint32_t exception; | uint32_t exception; | ||||
| uint64_t esr, far; | uint64_t esr, far; | ||||
| int dfsc; | int dfsc; | ||||
| ▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | case EXCP_UNKNOWN: | ||||
| panic("Undefined instruction: %08x", | panic("Undefined instruction: %08x", | ||||
| *(uint32_t *)frame->tf_elr); | *(uint32_t *)frame->tf_elr); | ||||
| break; | break; | ||||
| case EXCP_BTI: | case EXCP_BTI: | ||||
| print_registers(frame); | print_registers(frame); | ||||
| print_gp_register("far", far); | print_gp_register("far", far); | ||||
| panic("Branch Target exception"); | panic("Branch Target exception"); | ||||
| break; | break; | ||||
| case EXCP_MOE: | |||||
| handle_moe(td, frame, esr); | |||||
| break; | |||||
| default: | default: | ||||
| print_registers(frame); | print_registers(frame); | ||||
| print_gp_register("far", far); | print_gp_register("far", far); | ||||
| panic("Unknown kernel exception 0x%x esr_el1 0x%lx", exception, | panic("Unknown kernel exception 0x%x esr_el1 0x%lx", exception, | ||||
| esr); | esr); | ||||
| } | } | ||||
| } | |||||
| 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 | void | ||||
| do_el0_sync(struct thread *td, struct trapframe *frame) | do_el0_sync(struct thread *td, struct trapframe *frame) | ||||
| { | { | ||||
| pcpu_bp_harden bp_harden; | pcpu_bp_harden bp_harden; | ||||
| uint32_t exception; | uint32_t exception; | ||||
| uint64_t esr, far; | uint64_t esr, far; | ||||
| ▲ Show 20 Lines • Show All 190 Lines • Show Last 20 Lines | |||||