github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/sentry/syscalls/linux/sys_membarrier.go (about)

     1  // Copyright 2020 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  package linux
    16  
    17  import (
    18  	"github.com/MerlinKodo/gvisor/pkg/abi/linux"
    19  	"github.com/MerlinKodo/gvisor/pkg/errors/linuxerr"
    20  	"github.com/MerlinKodo/gvisor/pkg/sentry/arch"
    21  	"github.com/MerlinKodo/gvisor/pkg/sentry/kernel"
    22  )
    23  
    24  // Membarrier implements syscall membarrier(2).
    25  func Membarrier(t *kernel.Task, sysno uintptr, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) {
    26  	cmd := args[0].Int()
    27  	flags := args[1].Uint()
    28  
    29  	switch cmd {
    30  	case linux.MEMBARRIER_CMD_QUERY:
    31  		if flags != 0 {
    32  			return 0, nil, linuxerr.EINVAL
    33  		}
    34  		var supportedCommands uintptr
    35  		if t.Kernel().Platform.HaveGlobalMemoryBarrier() {
    36  			supportedCommands |= linux.MEMBARRIER_CMD_GLOBAL |
    37  				linux.MEMBARRIER_CMD_GLOBAL_EXPEDITED |
    38  				linux.MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED |
    39  				linux.MEMBARRIER_CMD_PRIVATE_EXPEDITED |
    40  				linux.MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED
    41  		}
    42  		if t.RSeqAvailable() {
    43  			supportedCommands |= linux.MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ |
    44  				linux.MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ
    45  		}
    46  		return supportedCommands, nil, nil
    47  	case linux.MEMBARRIER_CMD_GLOBAL, linux.MEMBARRIER_CMD_GLOBAL_EXPEDITED, linux.MEMBARRIER_CMD_PRIVATE_EXPEDITED:
    48  		if flags != 0 {
    49  			return 0, nil, linuxerr.EINVAL
    50  		}
    51  		if !t.Kernel().Platform.HaveGlobalMemoryBarrier() {
    52  			return 0, nil, linuxerr.EINVAL
    53  		}
    54  		if cmd == linux.MEMBARRIER_CMD_PRIVATE_EXPEDITED && !t.MemoryManager().IsMembarrierPrivateEnabled() {
    55  			return 0, nil, linuxerr.EPERM
    56  		}
    57  		return 0, nil, t.Kernel().Platform.GlobalMemoryBarrier()
    58  	case linux.MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED:
    59  		if flags != 0 {
    60  			return 0, nil, linuxerr.EINVAL
    61  		}
    62  		if !t.Kernel().Platform.HaveGlobalMemoryBarrier() {
    63  			return 0, nil, linuxerr.EINVAL
    64  		}
    65  		// no-op
    66  		return 0, nil, nil
    67  	case linux.MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED:
    68  		if flags != 0 {
    69  			return 0, nil, linuxerr.EINVAL
    70  		}
    71  		if !t.Kernel().Platform.HaveGlobalMemoryBarrier() {
    72  			return 0, nil, linuxerr.EINVAL
    73  		}
    74  		t.MemoryManager().EnableMembarrierPrivate()
    75  		return 0, nil, nil
    76  	case linux.MEMBARRIER_CMD_PRIVATE_EXPEDITED_RSEQ:
    77  		if flags&^linux.MEMBARRIER_CMD_FLAG_CPU != 0 {
    78  			return 0, nil, linuxerr.EINVAL
    79  		}
    80  		if !t.RSeqAvailable() {
    81  			return 0, nil, linuxerr.EINVAL
    82  		}
    83  		if !t.MemoryManager().IsMembarrierRSeqEnabled() {
    84  			return 0, nil, linuxerr.EPERM
    85  		}
    86  		// MEMBARRIER_CMD_FLAG_CPU and cpu_id are ignored since we don't have
    87  		// the ability to preempt specific CPUs.
    88  		return 0, nil, t.Kernel().Platform.PreemptAllCPUs()
    89  	case linux.MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_RSEQ:
    90  		if flags != 0 {
    91  			return 0, nil, linuxerr.EINVAL
    92  		}
    93  		if !t.RSeqAvailable() {
    94  			return 0, nil, linuxerr.EINVAL
    95  		}
    96  		t.MemoryManager().EnableMembarrierRSeq()
    97  		return 0, nil, nil
    98  	default:
    99  		// Probably a command we don't implement.
   100  		t.Kernel().EmitUnimplementedEvent(t, sysno)
   101  		return 0, nil, linuxerr.EINVAL
   102  	}
   103  }