github.com/sagernet/gvisor@v0.0.0-20240428053021-e691de28565f/pkg/safecopy/sighandler_arm64.s (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "textflag.h" 16 17 // The signals handled by sigHandler. 18 #define SIGBUS 7 19 #define SIGSEGV 11 20 21 // Offsets to the registers in context->uc_mcontext.gregs[]. 22 #define REG_R0 0xB8 23 #define REG_R1 0xC0 24 #define REG_PC 0x1B8 25 26 // Offset to the si_addr field of siginfo. 27 #define SI_CODE 0x08 28 #define SI_ADDR 0x10 29 30 // signalHandler is the signal handler for SIGSEGV and SIGBUS signals. It must 31 // not be set up as a handler to any other signals. 32 // 33 // If the instruction causing the signal is within a safecopy-protected 34 // function, the signal is handled such that execution resumes in the 35 // appropriate fault handling stub with R0 containing the faulting address and 36 // R1 containing the signal number. Otherwise control is transferred to the 37 // previously configured signal handler (savedSigSegvHandler or 38 // savedSigBusHandler). 39 // 40 // This function cannot be written in go because it runs whenever a signal is 41 // received by the thread (preempting whatever was running), which includes when 42 // garbage collector has stopped or isn't expecting any interactions (like 43 // barriers). 44 // 45 // The arguments are the following: 46 // R0 - The signal number. 47 // R1 - Pointer to siginfo_t structure. 48 // R2 - Pointer to ucontext structure. 49 TEXT ·signalHandler(SB),NOSPLIT,$0 50 // Check if the signal is from the kernel, si_code > 0 means a kernel signal. 51 MOVD SI_CODE(R1), R7 52 CMPW $0x0, R7 53 BLE original_handler 54 55 // Check if PC is within the area we care about. 56 MOVD REG_PC(R2), R7 57 MOVD ·memcpyBegin(SB), R8 58 CMP R8, R7 59 BLO not_memcpy 60 MOVD ·memcpyEnd(SB), R8 61 CMP R8, R7 62 BHS not_memcpy 63 64 // Modify the context such that execution will resume in the fault handler. 65 MOVD $handleMemcpyFault(SB), R7 66 B handle_fault 67 68 not_memcpy: 69 MOVD ·memclrBegin(SB), R8 70 CMP R8, R7 71 BLO not_memclr 72 MOVD ·memclrEnd(SB), R8 73 CMP R8, R7 74 BHS not_memclr 75 76 MOVD $handleMemclrFault(SB), R7 77 B handle_fault 78 79 not_memclr: 80 MOVD ·swapUint32Begin(SB), R8 81 CMP R8, R7 82 BLO not_swapuint32 83 MOVD ·swapUint32End(SB), R8 84 CMP R8, R7 85 BHS not_swapuint32 86 87 MOVD $handleSwapUint32Fault(SB), R7 88 B handle_fault 89 90 not_swapuint32: 91 MOVD ·swapUint64Begin(SB), R8 92 CMP R8, R7 93 BLO not_swapuint64 94 MOVD ·swapUint64End(SB), R8 95 CMP R8, R7 96 BHS not_swapuint64 97 98 MOVD $handleSwapUint64Fault(SB), R7 99 B handle_fault 100 101 not_swapuint64: 102 MOVD ·compareAndSwapUint32Begin(SB), R8 103 CMP R8, R7 104 BLO not_casuint32 105 MOVD ·compareAndSwapUint32End(SB), R8 106 CMP R8, R7 107 BHS not_casuint32 108 109 MOVD $handleCompareAndSwapUint32Fault(SB), R7 110 B handle_fault 111 112 not_casuint32: 113 MOVD ·loadUint32Begin(SB), R8 114 CMP R8, R7 115 BLO not_loaduint32 116 MOVD ·loadUint32End(SB), R8 117 CMP R8, R7 118 BHS not_loaduint32 119 120 MOVD $handleLoadUint32Fault(SB), R7 121 B handle_fault 122 123 not_loaduint32: 124 original_handler: 125 // Jump to the previous signal handler, which is likely the golang one. 126 MOVD ·savedSigBusHandler(SB), R7 127 MOVD ·savedSigSegVHandler(SB), R8 128 CMPW $SIGSEGV, R0 129 CSEL EQ, R8, R7, R7 130 B (R7) 131 132 handle_fault: 133 // Entered with the address of the fault handler in R7; store it in PC. 134 MOVD R7, REG_PC(R2) 135 136 // Store the faulting address in R0. 137 MOVD SI_ADDR(R1), R7 138 MOVD R7, REG_R0(R2) 139 140 // Store the signal number in R1. 141 MOVW R0, REG_R1(R2) 142 143 RET 144 145 // func addrOfSignalHandler() uintptr 146 TEXT ·addrOfSignalHandler(SB), $0-8 147 MOVD $·signalHandler(SB), R0 148 MOVD R0, ret+0(FP) 149 RET