github.com/sagernet/gvisor@v0.0.0-20240428053021-e691de28565f/pkg/safecopy/atomic_arm64.s (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include "textflag.h" 6 7 // handleSwapUint32Fault returns the value stored in R1. Control is transferred 8 // to it when swapUint32 below receives SIGSEGV or SIGBUS, with the signal 9 // number stored in R1. 10 // 11 // It must have the same frame configuration as swapUint32 so that it can undo 12 // any potential call frame set up by the assembler. 13 TEXT handleSwapUint32Fault(SB), NOSPLIT, $0-24 14 MOVW R1, sig+20(FP) 15 RET 16 17 // See the corresponding doc in safecopy_unsafe.go 18 // 19 // The code is derived from Go source runtime/internal/atomic.Xchg. 20 // 21 //func swapUint32(ptr unsafe.Pointer, new uint32) (old uint32, sig int32) 22 TEXT ·swapUint32(SB), NOSPLIT, $0-24 23 // Store 0 as the returned signal number. If we run to completion, 24 // this is the value the caller will see; if a signal is received, 25 // handleSwapUint32Fault will store a different value in this address. 26 MOVW $0, sig+20(FP) 27 again: 28 MOVD ptr+0(FP), R0 29 MOVW new+8(FP), R1 30 LDAXRW (R0), R2 31 STLXRW R1, (R0), R3 32 CBNZ R3, again 33 MOVW R2, old+16(FP) 34 RET 35 36 // func addrOfSwapUint32() uintptr 37 TEXT ·addrOfSwapUint32(SB), $0-8 38 MOVD $·swapUint32(SB), R0 39 MOVD R0, ret+0(FP) 40 RET 41 42 // handleSwapUint64Fault returns the value stored in R1. Control is transferred 43 // to it when swapUint64 below receives SIGSEGV or SIGBUS, with the signal 44 // number stored in R1. 45 // 46 // It must have the same frame configuration as swapUint64 so that it can undo 47 // any potential call frame set up by the assembler. 48 TEXT handleSwapUint64Fault(SB), NOSPLIT, $0-28 49 MOVW R1, sig+24(FP) 50 RET 51 52 // See the corresponding doc in safecopy_unsafe.go 53 // 54 // The code is derived from Go source runtime/internal/atomic.Xchg64. 55 // 56 //func swapUint64(ptr unsafe.Pointer, new uint64) (old uint64, sig int32) 57 TEXT ·swapUint64(SB), NOSPLIT, $0-28 58 // Store 0 as the returned signal number. If we run to completion, 59 // this is the value the caller will see; if a signal is received, 60 // handleSwapUint64Fault will store a different value in this address. 61 MOVW $0, sig+24(FP) 62 again: 63 MOVD ptr+0(FP), R0 64 MOVD new+8(FP), R1 65 LDAXR (R0), R2 66 STLXR R1, (R0), R3 67 CBNZ R3, again 68 MOVD R2, old+16(FP) 69 RET 70 71 // func addrOfSwapUint64() uintptr 72 TEXT ·addrOfSwapUint64(SB), $0-8 73 MOVD $·swapUint64(SB), R0 74 MOVD R0, ret+0(FP) 75 RET 76 77 // handleCompareAndSwapUint32Fault returns the value stored in R1. Control is 78 // transferred to it when compareAndSwapUint32 below receives SIGSEGV or SIGBUS, 79 // with the signal number stored in R1. 80 // 81 // It must have the same frame configuration as compareAndSwapUint32 so that it 82 // can undo any potential call frame set up by the assembler. 83 TEXT handleCompareAndSwapUint32Fault(SB), NOSPLIT, $0-24 84 MOVW R1, sig+20(FP) 85 RET 86 87 // See the corresponding doc in safecopy_unsafe.go 88 // 89 // The code is derived from Go source runtime/internal/atomic.Cas. 90 // 91 //func compareAndSwapUint32(ptr unsafe.Pointer, old, new uint32) (prev uint32, sig int32) 92 TEXT ·compareAndSwapUint32(SB), NOSPLIT, $0-24 93 // Store 0 as the returned signal number. If we run to completion, this is 94 // the value the caller will see; if a signal is received, 95 // handleCompareAndSwapUint32Fault will store a different value in this 96 // address. 97 MOVW $0, sig+20(FP) 98 99 MOVD ptr+0(FP), R0 100 MOVW old+8(FP), R1 101 MOVW new+12(FP), R2 102 again: 103 LDAXRW (R0), R3 104 CMPW R1, R3 105 BNE done 106 STLXRW R2, (R0), R4 107 CBNZ R4, again 108 done: 109 MOVW R3, prev+16(FP) 110 RET 111 112 // func addrOfCompareAndSwapUint32() uintptr 113 TEXT ·addrOfCompareAndSwapUint32(SB), $0-8 114 MOVD $·compareAndSwapUint32(SB), R0 115 MOVD R0, ret+0(FP) 116 RET 117 118 // handleLoadUint32Fault returns the value stored in DI. Control is transferred 119 // to it when LoadUint32 below receives SIGSEGV or SIGBUS, with the signal 120 // number stored in DI. 121 // 122 // It must have the same frame configuration as loadUint32 so that it can undo 123 // any potential call frame set up by the assembler. 124 TEXT handleLoadUint32Fault(SB), NOSPLIT, $0-16 125 MOVW R1, sig+12(FP) 126 RET 127 128 // loadUint32 atomically loads *ptr and returns it. If a SIGSEGV or SIGBUS 129 // signal is received, the value returned is unspecified, and sig is the number 130 // of the signal that was received. 131 // 132 // Preconditions: ptr must be aligned to a 4-byte boundary. 133 // 134 //func loadUint32(ptr unsafe.Pointer) (val uint32, sig int32) 135 TEXT ·loadUint32(SB), NOSPLIT, $0-16 136 // Store 0 as the returned signal number. If we run to completion, 137 // this is the value the caller will see; if a signal is received, 138 // handleLoadUint32Fault will store a different value in this address. 139 MOVW $0, sig+12(FP) 140 141 MOVD ptr+0(FP), R0 142 LDARW (R0), R1 143 MOVW R1, val+8(FP) 144 RET 145 146 // func addrOfLoadUint32() uintptr 147 TEXT ·addrOfLoadUint32(SB), $0-8 148 MOVD $·loadUint32(SB), R0 149 MOVD R0, ret+0(FP) 150 RET