github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/safecopy/atomic_amd64.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  // handleSwapUint32Fault returns the value stored in DI. Control is transferred
    18  // to it when swapUint32 below receives SIGSEGV or SIGBUS, with the signal
    19  // number stored in DI.
    20  //
    21  // It must have the same frame configuration as swapUint32 so that it can undo
    22  // any potential call frame set up by the assembler.
    23  TEXT handleSwapUint32Fault(SB), NOSPLIT|NOFRAME, $0-24
    24    MOVL DI, sig+20(FP)
    25    RET
    26  
    27  // swapUint32 atomically stores new into *ptr and returns (the previous ptr*
    28  // value, 0). If a SIGSEGV or SIGBUS signal is received during the swap, the
    29  // value of old is unspecified, and sig is the number of the signal that was
    30  // received.
    31  //
    32  // Preconditions: ptr must be aligned to a 4-byte boundary.
    33  //
    34  //func swapUint32(ptr unsafe.Pointer, new uint32) (old uint32, sig int32)
    35  TEXT ·swapUint32(SB), NOSPLIT|NOFRAME, $0-24
    36    // Store 0 as the returned signal number. If we run to completion,
    37    // this is the value the caller will see; if a signal is received,
    38    // handleSwapUint32Fault will store a different value in this address.
    39    MOVL $0, sig+20(FP)
    40  
    41    MOVQ ptr+0(FP), DI
    42    MOVL new+8(FP), AX
    43    XCHGL AX, 0(DI)
    44    MOVL AX, old+16(FP)
    45    RET
    46  
    47  // func addrOfSwapUint32() uintptr
    48  TEXT ·addrOfSwapUint32(SB), $0-8
    49    MOVQ $·swapUint32(SB), AX
    50    MOVQ AX, ret+0(FP)
    51    RET
    52  
    53  // handleSwapUint64Fault returns the value stored in DI. Control is transferred
    54  // to it when swapUint64 below receives SIGSEGV or SIGBUS, with the signal
    55  // number stored in DI.
    56  //
    57  // It must have the same frame configuration as swapUint64 so that it can undo
    58  // any potential call frame set up by the assembler.
    59  TEXT handleSwapUint64Fault(SB), NOSPLIT|NOFRAME, $0-28
    60    MOVL DI, sig+24(FP)
    61    RET
    62  
    63  // swapUint64 atomically stores new into *ptr and returns (the previous *ptr
    64  // value, 0). If a SIGSEGV or SIGBUS signal is received during the swap, the
    65  // value of old is unspecified, and sig is the number of the signal that was
    66  // received.
    67  //
    68  // Preconditions: ptr must be aligned to a 8-byte boundary.
    69  //
    70  //func swapUint64(ptr unsafe.Pointer, new uint64) (old uint64, sig int32)
    71  TEXT ·swapUint64(SB), NOSPLIT|NOFRAME, $0-28
    72    // Store 0 as the returned signal number. If we run to completion,
    73    // this is the value the caller will see; if a signal is received,
    74    // handleSwapUint64Fault will store a different value in this address.
    75    MOVL $0, sig+24(FP)
    76  
    77    MOVQ ptr+0(FP), DI
    78    MOVQ new+8(FP), AX
    79    XCHGQ AX, 0(DI)
    80    MOVQ AX, old+16(FP)
    81    RET
    82  
    83  // func addrOfSwapUint64() uintptr
    84  TEXT ·addrOfSwapUint64(SB), NOSPLIT|NOFRAME, $0-8
    85    MOVQ $·swapUint64(SB), AX
    86    MOVQ AX, ret+0(FP)
    87    RET
    88  
    89  // handleCompareAndSwapUint32Fault returns the value stored in DI. Control is
    90  // transferred to it when swapUint64 below receives SIGSEGV or SIGBUS, with the
    91  // signal number stored in DI.
    92  //
    93  // It must have the same frame configuration as compareAndSwapUint32 so that it
    94  // can undo any potential call frame set up by the assembler.
    95  TEXT handleCompareAndSwapUint32Fault(SB), NOSPLIT|NOFRAME, $0-24
    96    MOVL DI, sig+20(FP)
    97    RET
    98  
    99  // compareAndSwapUint32 is like sync/atomic.CompareAndSwapUint32, but returns
   100  // (the value previously stored at ptr, 0). If a SIGSEGV or SIGBUS signal is
   101  // received during the operation, the value of prev is unspecified, and sig is
   102  // the number of the signal that was received.
   103  //
   104  // Preconditions: ptr must be aligned to a 4-byte boundary.
   105  //
   106  //func compareAndSwapUint32(ptr unsafe.Pointer, old, new uint32) (prev uint32, sig int32)
   107  TEXT ·compareAndSwapUint32(SB), NOSPLIT|NOFRAME, $0-24
   108    // Store 0 as the returned signal number. If we run to completion, this is
   109    // the value the caller will see; if a signal is received,
   110    // handleCompareAndSwapUint32Fault will store a different value in this
   111    // address.
   112    MOVL $0, sig+20(FP)
   113  
   114    MOVQ ptr+0(FP), DI
   115    MOVL old+8(FP), AX
   116    MOVL new+12(FP), DX
   117    LOCK
   118    CMPXCHGL DX, 0(DI)
   119    MOVL AX, prev+16(FP)
   120    RET
   121  
   122  // func addrOfCompareAndSwapUint32() uintptr
   123  TEXT ·addrOfCompareAndSwapUint32(SB), NOSPLIT|NOFRAME, $0-8
   124    MOVQ $·compareAndSwapUint32(SB), AX
   125    MOVQ AX, ret+0(FP)
   126    RET
   127  
   128  // handleLoadUint32Fault returns the value stored in DI. Control is transferred
   129  // to it when LoadUint32 below receives SIGSEGV or SIGBUS, with the signal
   130  // number stored in DI.
   131  //
   132  // It must have the same frame configuration as loadUint32 so that it can undo
   133  // any potential call frame set up by the assembler.
   134  TEXT handleLoadUint32Fault(SB), NOSPLIT|NOFRAME, $0-16
   135    MOVL DI, sig+12(FP)
   136    RET
   137  
   138  // loadUint32 atomically loads *ptr and returns it. If a SIGSEGV or SIGBUS
   139  // signal is received, the value returned is unspecified, and sig is the number
   140  // of the signal that was received.
   141  //
   142  // Preconditions: ptr must be aligned to a 4-byte boundary.
   143  //
   144  //func loadUint32(ptr unsafe.Pointer) (val uint32, sig int32)
   145  TEXT ·loadUint32(SB), NOSPLIT|NOFRAME, $0-16
   146    // Store 0 as the returned signal number. If we run to completion,
   147    // this is the value the caller will see; if a signal is received,
   148    // handleLoadUint32Fault will store a different value in this address.
   149    MOVL $0, sig+12(FP)
   150  
   151    MOVQ ptr+0(FP), AX
   152    MOVL (AX), BX
   153    MOVL BX, val+8(FP)
   154    RET
   155  
   156  // func addrOfLoadUint32() uintptr
   157  TEXT ·addrOfLoadUint32(SB), NOSPLIT|NOFRAME, $0-8
   158    MOVQ $·loadUint32(SB), AX
   159    MOVQ AX, ret+0(FP)
   160    RET