Add //pkg/sentry/devices/nvproxy and //pkg/abi/nvgpu.

Currently, version 525.60.13 of the open-source driver is required; each driver
version needs to be individually qualified since the kernel driver's ABI is
unstable.

In conjunction with cl/529511919, on T4, A100, or L4 GPUs:

```
$ sudo docker run --gpus all --runtime=runsc nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda11.7.1-ubi8
[Vector addition of 50000 elements]
Copy input data from the host memory to the CUDA device
CUDA kernel launch with 196 blocks of 256 threads
Copy output data from the CUDA device to the host memory
Test PASSED
Done

$ sudo docker run --gpus all --runtime=runsc -it nvcr.io/nvidia/pytorch:23.04-py3
...
root@ca01b7709883:/workspace# cd examples/upstream/word_language_model/ # see https://github.com/pytorch/examples/tree/main/word_language_model
root@ca01b7709883:/workspace/examples/upstream/word_language_model# python main.py --cuda --epochs 6 --model Transformer --lr 5
| epoch   1 |   200/ 2983 batches | lr 5.00 | ms/batch 10.52 | loss  7.60 | ppl  2003.10
| epoch   1 |   400/ 2983 batches | lr 5.00 | ms/batch  5.66 | loss  6.80 | ppl   895.15
| epoch   1 |   600/ 2983 batches | lr 5.00 | ms/batch  5.66 | loss  6.50 | ppl   664.17
| epoch   1 |   800/ 2983 batches | lr 5.00 | ms/batch  5.66 | loss  6.36 | ppl   576.66
| epoch   1 |  1000/ 2983 batches | lr 5.00 | ms/batch  5.61 | loss  6.26 | ppl   522.67
| epoch   1 |  1200/ 2983 batches | lr 5.00 | ms/batch  5.66 | loss  6.22 | ppl   504.51
| epoch   1 |  1400/ 2983 batches | lr 5.00 | ms/batch  5.65 | loss  6.15 | ppl   466.58
| epoch   1 |  1600/ 2983 batches | lr 5.00 | ms/batch  5.65 | loss  6.15 | ppl   470.48
| epoch   1 |  1800/ 2983 batches | lr 5.00 | ms/batch  5.68 | loss  6.03 | ppl   415.41
| epoch   1 |  2000/ 2983 batches | lr 5.00 | ms/batch  5.72 | loss  6.02 | ppl   412.43
| epoch   1 |  2200/ 2983 batches | lr 5.00 | ms/batch  5.93 | loss  5.93 | ppl   374.53
| epoch   1 |  2400/ 2983 batches | lr 5.00 | ms/batch  5.80 | loss  5.93 | ppl   377.23
| epoch   1 |  2600/ 2983 batches | lr 5.00 | ms/batch  5.74 | loss  5.93 | ppl   375.84
| epoch   1 |  2800/ 2983 batches | lr 5.00 | ms/batch  5.65 | loss  5.84 | ppl   343.92
-----------------------------------------------------------------------------------------
| end of epoch   1 | time: 19.08s | valid loss  5.75 | valid ppl   313.70
-----------------------------------------------------------------------------------------
| epoch   2 |   200/ 2983 batches | lr 5.00 | ms/batch  5.61 | loss  5.80 | ppl   329.43
| epoch   2 |   400/ 2983 batches | lr 5.00 | ms/batch  5.67 | loss  5.77 | ppl   319.79
| epoch   2 |   600/ 2983 batches | lr 5.00 | ms/batch  5.62 | loss  5.62 | ppl   276.16
| epoch   2 |   800/ 2983 batches | lr 5.00 | ms/batch  5.72 | loss  5.63 | ppl   277.32
| epoch   2 |  1000/ 2983 batches | lr 5.00 | ms/batch  5.68 | loss  5.60 | ppl   270.96
| epoch   2 |  1200/ 2983 batches | lr 5.00 | ms/batch  5.68 | loss  5.61 | ppl   273.71
| epoch   2 |  1400/ 2983 batches | lr 5.00 | ms/batch  5.64 | loss  5.62 | ppl   275.38
| epoch   2 |  1600/ 2983 batches | lr 5.00 | ms/batch  5.70 | loss  5.66 | ppl   286.58
| epoch   2 |  1800/ 2983 batches | lr 5.00 | ms/batch  5.74 | loss  5.54 | ppl   255.62
| epoch   2 |  2000/ 2983 batches | lr 5.00 | ms/batch  5.66 | loss  5.58 | ppl   264.36
| epoch   2 |  2200/ 2983 batches | lr 5.00 | ms/batch  5.65 | loss  5.48 | ppl   240.27
| epoch   2 |  2400/ 2983 batches | lr 5.00 | ms/batch  5.64 | loss  5.52 | ppl   248.69
| epoch   2 |  2600/ 2983 batches | lr 5.00 | ms/batch  5.62 | loss  5.53 | ppl   251.46
| epoch   2 |  2800/ 2983 batches | lr 5.00 | ms/batch  5.78 | loss  5.45 | ppl   233.75
-----------------------------------------------------------------------------------------
| end of epoch   2 | time: 18.00s | valid loss  5.53 | valid ppl   252.16
-----------------------------------------------------------------------------------------
| epoch   3 |   200/ 2983 batches | lr 5.00 | ms/batch  5.72 | loss  5.46 | ppl   235.25
| epoch   3 |   400/ 2983 batches | lr 5.00 | ms/batch  5.69 | loss  5.46 | ppl   234.59
| epoch   3 |   600/ 2983 batches | lr 5.00 | ms/batch  5.68 | loss  5.29 | ppl   197.90
| epoch   3 |   800/ 2983 batches | lr 5.00 | ms/batch  5.68 | loss  5.32 | ppl   204.71
| epoch   3 |  1000/ 2983 batches | lr 5.00 | ms/batch  5.66 | loss  5.31 | ppl   201.70
| epoch   3 |  1200/ 2983 batches | lr 5.00 | ms/batch  5.70 | loss  5.33 | ppl   205.88
| epoch   3 |  1400/ 2983 batches | lr 5.00 | ms/batch  5.59 | loss  5.35 | ppl   211.48
| epoch   3 |  1600/ 2983 batches | lr 5.00 | ms/batch  5.68 | loss  5.40 | ppl   220.79
| epoch   3 |  1800/ 2983 batches | lr 5.00 | ms/batch  6.03 | loss  5.29 | ppl   198.28
| epoch   3 |  2000/ 2983 batches | lr 5.00 | ms/batch  5.63 | loss  5.33 | ppl   206.45
| epoch   3 |  2200/ 2983 batches | lr 5.00 | ms/batch  5.62 | loss  5.23 | ppl   186.28
| epoch   3 |  2400/ 2983 batches | lr 5.00 | ms/batch  5.77 | loss  5.27 | ppl   194.13
| epoch   3 |  2600/ 2983 batches | lr 5.00 | ms/batch  5.62 | loss  5.29 | ppl   199.08
| epoch   3 |  2800/ 2983 batches | lr 5.00 | ms/batch  5.75 | loss  5.22 | ppl   184.77
-----------------------------------------------------------------------------------------
| end of epoch   3 | time: 18.10s | valid loss  5.45 | valid ppl   232.50
-----------------------------------------------------------------------------------------
| epoch   4 |   200/ 2983 batches | lr 5.00 | ms/batch  5.71 | loss  5.24 | ppl   189.07
| epoch   4 |   400/ 2983 batches | lr 5.00 | ms/batch  5.65 | loss  5.25 | ppl   190.61
| epoch   4 |   600/ 2983 batches | lr 5.00 | ms/batch  5.67 | loss  5.07 | ppl   159.83
| epoch   4 |   800/ 2983 batches | lr 5.00 | ms/batch  5.62 | loss  5.13 | ppl   168.20
| epoch   4 |  1000/ 2983 batches | lr 5.00 | ms/batch  5.64 | loss  5.12 | ppl   166.87
| epoch   4 |  1200/ 2983 batches | lr 5.00 | ms/batch  5.61 | loss  5.13 | ppl   169.07
| epoch   4 |  1400/ 2983 batches | lr 5.00 | ms/batch  5.60 | loss  5.17 | ppl   175.87
| epoch   4 |  1600/ 2983 batches | lr 5.00 | ms/batch  5.70 | loss  5.22 | ppl   184.63
| epoch   4 |  1800/ 2983 batches | lr 5.00 | ms/batch  5.69 | loss  5.12 | ppl   166.77
| epoch   4 |  2000/ 2983 batches | lr 5.00 | ms/batch  5.65 | loss  5.16 | ppl   173.80
| epoch   4 |  2200/ 2983 batches | lr 5.00 | ms/batch  5.71 | loss  5.05 | ppl   155.82
| epoch   4 |  2400/ 2983 batches | lr 5.00 | ms/batch  5.76 | loss  5.10 | ppl   163.49
| epoch   4 |  2600/ 2983 batches | lr 5.00 | ms/batch  5.71 | loss  5.12 | ppl   167.32
| epoch   4 |  2800/ 2983 batches | lr 5.00 | ms/batch  5.67 | loss  5.05 | ppl   155.76
-----------------------------------------------------------------------------------------
| end of epoch   4 | time: 18.03s | valid loss  5.42 | valid ppl   225.19
-----------------------------------------------------------------------------------------
| epoch   5 |   200/ 2983 batches | lr 5.00 | ms/batch  5.83 | loss  5.08 | ppl   160.77
| epoch   5 |   400/ 2983 batches | lr 5.00 | ms/batch  5.70 | loss  5.09 | ppl   163.02
| epoch   5 |   600/ 2983 batches | lr 5.00 | ms/batch  5.60 | loss  4.92 | ppl   137.13
| epoch   5 |   800/ 2983 batches | lr 5.00 | ms/batch  5.58 | loss  4.97 | ppl   143.72
| epoch   5 |  1000/ 2983 batches | lr 5.00 | ms/batch  5.64 | loss  4.96 | ppl   142.78
| epoch   5 |  1200/ 2983 batches | lr 5.00 | ms/batch  5.76 | loss  4.98 | ppl   146.04
| epoch   5 |  1400/ 2983 batches | lr 5.00 | ms/batch  5.67 | loss  5.03 | ppl   153.23
| epoch   5 |  1600/ 2983 batches | lr 5.00 | ms/batch  5.67 | loss  5.08 | ppl   160.29
| epoch   5 |  1800/ 2983 batches | lr 5.00 | ms/batch  5.67 | loss  4.98 | ppl   145.06
| epoch   5 |  2000/ 2983 batches | lr 5.00 | ms/batch  5.66 | loss  5.02 | ppl   151.17
| epoch   5 |  2200/ 2983 batches | lr 5.00 | ms/batch  5.66 | loss  4.90 | ppl   134.86
| epoch   5 |  2400/ 2983 batches | lr 5.00 | ms/batch  5.61 | loss  4.96 | ppl   142.85
| epoch   5 |  2600/ 2983 batches | lr 5.00 | ms/batch  5.66 | loss  4.98 | ppl   145.94
| epoch   5 |  2800/ 2983 batches | lr 5.00 | ms/batch  5.64 | loss  4.92 | ppl   136.60
-----------------------------------------------------------------------------------------
| end of epoch   5 | time: 17.99s | valid loss  5.39 | valid ppl   218.33
-----------------------------------------------------------------------------------------
| epoch   6 |   200/ 2983 batches | lr 5.00 | ms/batch  5.60 | loss  4.95 | ppl   140.86
| epoch   6 |   400/ 2983 batches | lr 5.00 | ms/batch  5.64 | loss  4.97 | ppl   143.35
| epoch   6 |   600/ 2983 batches | lr 5.00 | ms/batch  5.64 | loss  4.79 | ppl   120.55
| epoch   6 |   800/ 2983 batches | lr 5.00 | ms/batch  5.65 | loss  4.85 | ppl   127.48
| epoch   6 |  1000/ 2983 batches | lr 5.00 | ms/batch  5.64 | loss  4.84 | ppl   126.87
| epoch   6 |  1200/ 2983 batches | lr 5.00 | ms/batch  5.60 | loss  4.86 | ppl   129.41
| epoch   6 |  1400/ 2983 batches | lr 5.00 | ms/batch  5.66 | loss  4.91 | ppl   135.84
| epoch   6 |  1600/ 2983 batches | lr 5.00 | ms/batch  5.82 | loss  4.96 | ppl   143.08
| epoch   6 |  1800/ 2983 batches | lr 5.00 | ms/batch  5.68 | loss  4.86 | ppl   129.64
| epoch   6 |  2000/ 2983 batches | lr 5.00 | ms/batch  5.57 | loss  4.91 | ppl   134.98
| epoch   6 |  2200/ 2983 batches | lr 5.00 | ms/batch  5.80 | loss  4.79 | ppl   120.01
| epoch   6 |  2400/ 2983 batches | lr 5.00 | ms/batch  5.89 | loss  4.84 | ppl   126.87
| epoch   6 |  2600/ 2983 batches | lr 5.00 | ms/batch  5.79 | loss  4.87 | ppl   130.53
| epoch   6 |  2800/ 2983 batches | lr 5.00 | ms/batch  5.62 | loss  4.81 | ppl   122.77
-----------------------------------------------------------------------------------------
| end of epoch   6 | time: 18.09s | valid loss  5.37 | valid ppl   214.45
-----------------------------------------------------------------------------------------
| End of training | test loss  5.28 | test ppl   195.78

root@ca01b7709883:/workspace/examples/upstream/word_language_model# python generate.py --cuda
| Generated 0/1000 words
| Generated 100/1000 words
| Generated 200/1000 words
| Generated 300/1000 words
| Generated 400/1000 words
| Generated 500/1000 words
| Generated 600/1000 words
| Generated 700/1000 words
| Generated 800/1000 words
| Generated 900/1000 words
```

Updates #14

PiperOrigin-RevId: 534515559
This commit is contained in:
Jamie Liu
2023-05-23 12:23:14 -07:00
committed by gVisor bot
parent 158636229e
commit 8c789fee2d
18 changed files with 3185 additions and 0 deletions
+2
View File
@@ -250,6 +250,8 @@ analyzers:
- generated.gen.pb.go
ST1021: # Doc should start with type name.
internal:
exclude:
- "pkg/abi/nvgpu/.*.go"
suppress:
- "comment on exported type Translation" # Intentional.
- "comment on exported type PinnedRange" # Intentional.
+19
View File
@@ -0,0 +1,19 @@
load("//tools:defs.bzl", "go_library")
package(default_applicable_licenses = ["//:license"])
licenses(["notice"])
go_library(
name = "nvgpu",
srcs = [
"classes.go",
"ctrl.go",
"frontend.go",
"nvgpu.go",
"status.go",
"uvm.go",
],
marshal = True,
visibility = ["//pkg/sentry:internal"],
)
+199
View File
@@ -0,0 +1,199 @@
// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package nvgpu
// Class handles, from src/nvidia/generated/g_allclasses.h.
const (
NV01_ROOT = 0x00000000
NV01_ROOT_NON_PRIV = 0x00000001
NV01_MEMORY_SYSTEM = 0x0000003e
NV01_ROOT_CLIENT = 0x00000041
NV01_MEMORY_SYSTEM_OS_DESCRIPTOR = 0x00000071
NV01_EVENT_OS_EVENT = 0x00000079
NV01_DEVICE_0 = 0x00000080
NV20_SUBDEVICE_0 = 0x00002080
NV50_THIRD_PARTY_P2P = 0x0000503c
GT200_DEBUGGER = 0x000083de
GF100_SUBDEVICE_MASTER = 0x000090e6
FERMI_CONTEXT_SHARE_A = 0x00009067
FERMI_VASPACE_A = 0x000090f1
KEPLER_CHANNEL_GROUP_A = 0x0000a06c
TURING_USERMODE_A = 0x0000c461
TURING_CHANNEL_GPFIFO_A = 0x0000c46f
AMPERE_CHANNEL_GPFIFO_A = 0x0000c56f
TURING_DMA_COPY_A = 0x0000c5b5
AMPERE_DMA_COPY_A = 0x0000c6b5
AMPERE_DMA_COPY_B = 0x0000c7b5
TURING_COMPUTE_A = 0x0000c5c0
AMPERE_COMPUTE_A = 0x0000c6c0
ADA_COMPUTE_A = 0x0000c9c0
)
// NV0005_ALLOC_PARAMETERS is the alloc params type for NV01_EVENT_OS_EVENT,
// from src/common/sdk/nvidia/inc/class/cl0005.h.
//
// +marshal
type NV0005_ALLOC_PARAMETERS struct {
HParentClient Handle
HSrcResource Handle
HClass uint32
NotifyIndex uint32
Data P64 // actually FD for NV01_EVENT_OS_EVENT, see src/nvidia/src/kernel/rmapi/event.c:eventConstruct_IMPL() => src/nvidia/arch/nvalloc/unix/src/os.c:osUserHandleToKernelPtr()
}
// NV0080_ALLOC_PARAMETERS is the alloc params type for NV01_DEVICE_0, from
// src/common/sdk/nvidia/inc/class/cl0080.h.
//
// +marshal
type NV0080_ALLOC_PARAMETERS struct {
DeviceID uint32
HClientShare Handle
HTargetClient Handle
HTargetDevice Handle
Flags uint32
Pad0 [4]byte
VASpaceSize uint64
VAStartInternal uint64
VALimitInternal uint64
VAMode uint32
Pad1 [4]byte
}
// NV2080_ALLOC_PARAMETERS is the alloc params type for NV20_SUBDEVICE_0, from
// src/common/sdk/nvidia/inc/class/cl2080.h.
//
// +marshal
type NV2080_ALLOC_PARAMETERS struct {
SubDeviceID uint32
}
// NV503C_ALLOC_PARAMETERS is the alloc params type for NV50_THIRD_PARTY_P2P,
// from src/common/sdk/nvidia/inc/class/cl503c.h.
//
// +marshal
type NV503C_ALLOC_PARAMETERS struct {
Flags uint32
}
// NV83DE_ALLOC_PARAMETERS is the alloc params type for GT200_DEBUGGER,
// from src/common/sdk/nvidia/inc/class/cl83de.h.
//
// +marshal
type NV83DE_ALLOC_PARAMETERS struct {
HDebuggerClient_Obsolete Handle
HAppClient Handle
HClass3DObject Handle
}
// NV_CTXSHARE_ALLOCATION_PARAMETERS is the alloc params type for
// FERMI_CONTEXT_SHARE_A, from src/common/sdk/nvidia/inc/nvos.h.
//
// +marshal
type NV_CTXSHARE_ALLOCATION_PARAMETERS struct {
HVASpace Handle
Flags uint32
SubctxID uint32
}
// NV_VASPACE_ALLOCATION_PARAMETERS is the alloc params type for
// FERMI_VASPACE_A, from src/common/sdk/nvidia/inc/nvos.h.
//
// +marshal
type NV_VASPACE_ALLOCATION_PARAMETERS struct {
Index uint32
Flags uint32
VASize uint64
VAStartInternal uint64
VALimitInternal uint64
BigPageSize uint32
Pad0 [4]byte
VABase uint64
}
// NV_CHANNEL_GROUP_ALLOCATION_PARAMETERS is the alloc params type for
// KEPLER_CHANNEL_GROUP_A, from src/common/sdk/nvidia/inc/nvos.h.
//
// +marshal
type NV_CHANNEL_GROUP_ALLOCATION_PARAMETERS struct {
HObjectError Handle
HObjectECCError Handle
HVASpace Handle
EngineType uint32
BIsCallingContextVgpuPlugin uint8
Pad0 [3]byte
}
// NV_MEMORY_DESC_PARAMS is from
// src/common/sdk/nvidia/inc/alloc/alloc_channel.h.
//
// +marshal
type NV_MEMORY_DESC_PARAMS struct {
Base uint64
Size uint64
AddressSpace uint32
CacheAttrib uint32
}
// NV_CHANNEL_ALLOC_PARAMS is the alloc params type for TURING_CHANNEL_GPFIFO_A
// and AMPERE_CHANNEL_GPFIFO_A, from
// src/common/sdk/nvidia/inc/alloc/alloc_channel.h.
//
// +marshal
type NV_CHANNEL_ALLOC_PARAMS struct {
HObjectError Handle
HObjectBuffer Handle
GPFIFOOffset uint64
GPFIFOEntries uint32
Flags uint32
HContextShare Handle
HVASpace Handle
HUserdMemory [NV_MAX_SUBDEVICES]Handle
UserdOffset [NV_MAX_SUBDEVICES]uint64
EngineType uint32
CID uint32
SubDeviceID uint32
HObjectECCError Handle
InstanceMem NV_MEMORY_DESC_PARAMS
UserdMem NV_MEMORY_DESC_PARAMS
RamfcMem NV_MEMORY_DESC_PARAMS
MthdbufMem NV_MEMORY_DESC_PARAMS
HPhysChannelGroup Handle
InternalFlags uint32
ErrorNotifierMem NV_MEMORY_DESC_PARAMS
ECCErrorNotifierMem NV_MEMORY_DESC_PARAMS
ProcessID uint32
SubProcessID uint32
}
// NVB0B5_ALLOCATION_PARAMETERS is the alloc param type for TURING_DMA_COPY_A,
// AMPERE_DMA_COPY_A, and AMPERE_DMA_COPY_B from
// src/common/sdk/nvidia/inc/class/clb0b5sw.h.
//
// +marshal
type NVB0B5_ALLOCATION_PARAMETERS struct {
Version uint32
EngineType uint32
}
// NV_GR_ALLOCATION_PARAMETERS is the alloc param type for TURING_COMPUTE_A,
// AMPERE_COMPUTE_A, and ADA_COMPUTE_A, from src/common/sdk/nvidia/inc/nvos.h.
//
// +marshal
type NV_GR_ALLOCATION_PARAMETERS struct {
Version uint32
Flags uint32
Size uint32
Caps uint32
}
+251
View File
@@ -0,0 +1,251 @@
// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package nvgpu
// From src/nvidia/interface/deprecated/rmapi_deprecated.h:
const (
RM_GSS_LEGACY_MASK = 0x00008000
)
// From src/common/sdk/nvidia/inc/ctrl/ctrlxxxx.h:
// +marshal
type NVXXXX_CTRL_XXX_INFO struct {
Index uint32
Data uint32
}
// From src/common/sdk/nvidia/inc/ctrl/ctrl0000/ctrl0000client.h:
const (
NV0000_CTRL_CMD_CLIENT_GET_ADDR_SPACE_TYPE = 0xd01
NV0000_CTRL_CMD_CLIENT_SET_INHERITED_SHARE_POLICY = 0xd04
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl0000/ctrl0000gpu.h:
const (
NV0000_CTRL_CMD_GPU_GET_ATTACHED_IDS = 0x201
NV0000_CTRL_CMD_GPU_GET_ID_INFO = 0x202
NV0000_CTRL_CMD_GPU_GET_ID_INFO_V2 = 0x205
NV0000_CTRL_CMD_GPU_GET_PROBED_IDS = 0x214
NV0000_CTRL_CMD_GPU_ATTACH_IDS = 0x215
NV0000_CTRL_CMD_GPU_DETACH_IDS = 0x216
NV0000_CTRL_CMD_GPU_GET_PCI_INFO = 0x21b
NV0000_CTRL_CMD_GPU_QUERY_DRAIN_STATE = 0x279
NV0000_CTRL_CMD_GPU_GET_MEMOP_ENABLE = 0x27b
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl0000/ctrl0000syncgpuboost.h:
const (
NV0000_CTRL_CMD_SYNC_GPU_BOOST_GROUP_INFO = 0xa04
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl0000/ctrl0000system.h:
const (
NV0000_CTRL_CMD_SYSTEM_GET_BUILD_VERSION = 0x101
NV0000_CTRL_CMD_SYSTEM_GET_FABRIC_STATUS = 0x136
)
// +marshal
type NV0000_CTRL_SYSTEM_GET_BUILD_VERSION_PARAMS struct {
SizeOfStrings uint32
Pad [4]byte
PDriverVersionBuffer P64
PVersionBuffer P64
PTitleBuffer P64
ChangelistNumber uint32
OfficialChangelistNumber uint32
}
// From src/common/sdk/nvidia/inc/ctrl/ctrl0080/ctrl0080fb.h:
const (
NV0080_CTRL_CMD_FB_GET_CAPS_V2 = 0x801307
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl0080/ctrl0080fifo.h:
const (
NV0080_CTRL_CMD_FIFO_GET_CHANNELLIST = 0x80170d
)
// +marshal
type NV0080_CTRL_FIFO_GET_CHANNELLIST_PARAMS struct {
NumChannels uint32
Pad [4]byte
PChannelHandleList P64
PChannelList P64
}
// From src/common/sdk/nvidia/inc/ctrl/ctrl0080/ctrl0080gpu.h:
const (
NV0080_CTRL_CMD_GPU_GET_NUM_SUBDEVICES = 0x800280
NV0080_CTRL_CMD_GPU_QUERY_SW_STATE_PERSISTENCE = 0x800288
NV0080_CTRL_CMD_GPU_GET_VIRTUALIZATION_MODE = 0x800289
NV0080_CTRL_CMD_GPU_GET_CLASSLIST_V2 = 0x800292
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl0080/ctrl0080gr.h:
// +marshal
type NV0080_CTRL_GR_ROUTE_INFO struct {
Flags uint32
Pad [4]byte
Route uint64
}
// From src/common/sdk/nvidia/inc/ctrl/ctrl0080/ctrl0080host.h:
const (
NV0080_CTRL_CMD_HOST_GET_CAPS_V2 = 0x801402
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080bus.h:
const (
NV2080_CTRL_CMD_BUS_GET_PCI_INFO = 0x20801801
NV2080_CTRL_CMD_BUS_GET_PCI_BAR_INFO = 0x20801803
NV2080_CTRL_CMD_BUS_GET_INFO_V2 = 0x20801823
NV2080_CTRL_CMD_BUS_GET_PCIE_SUPPORTED_GPU_ATOMICS = 0x2080182a
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080ce.h:
const (
NV2080_CTRL_CMD_CE_GET_ALL_CAPS = 0x20802a0a
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080fb.h:
const (
NV2080_CTRL_CMD_FB_GET_INFO_V2 = 0x20801303
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080fifo.h:
const (
NV2080_CTRL_CMD_FIFO_DISABLE_CHANNELS = 0x2080110b
NV2080_CTRL_FIFO_DISABLE_CHANNELS_MAX_ENTRIES = 64
)
// +marshal
type NV2080_CTRL_FIFO_DISABLE_CHANNELS_PARAMS struct {
BDisable uint8
Pad1 [3]byte
NumChannels uint32
BOnlyDisableScheduling uint8
BRewindGpPut uint8
Pad2 [6]byte
PRunlistPreemptEvent P64
HClientList [NV2080_CTRL_FIFO_DISABLE_CHANNELS_MAX_ENTRIES]Handle
HChannelList [NV2080_CTRL_FIFO_DISABLE_CHANNELS_MAX_ENTRIES]Handle
}
// From src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080gpu.h:
const (
NV2080_CTRL_CMD_GPU_GET_INFO_V2 = 0x20800102
NV2080_CTRL_CMD_GPU_GET_NAME_STRING = 0x20800110
NV2080_CTRL_CMD_GPU_GET_SHORT_NAME_STRING = 0x20800111
NV2080_CTRL_CMD_GPU_GET_SIMULATION_INFO = 0x20800119
NV2080_CTRL_CMD_GPU_QUERY_ECC_STATUS = 0x2080012f
NV2080_CTRL_CMD_GPU_QUERY_COMPUTE_MODE_RULES = 0x20800131
NV2080_CTRL_CMD_GPU_ACQUIRE_COMPUTE_MODE_RESERVATION = 0x20800145 // undocumented; paramSize == 0
NV2080_CTRL_CMD_GPU_RELEASE_COMPUTE_MODE_RESERVATION = 0x20800146 // undocumented; paramSize == 0
NV2080_CTRL_CMD_GPU_GET_GID_INFO = 0x2080014a
NV2080_CTRL_CMD_GPU_GET_ENGINES_V2 = 0x20800170
NV2080_CTRL_CMD_GPU_GET_ACTIVE_PARTITION_IDS = 0x2080018b
NV2080_CTRL_CMD_GPU_GET_COMPUTE_POLICY_CONFIG = 0x20800195
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080gr.h:
const (
NV2080_CTRL_CMD_GR_GET_INFO = 0x20801201
NV2080_CTRL_CMD_GR_SET_CTXSW_PREEMPTION_MODE = 0x20801210
NV2080_CTRL_CMD_GR_GET_CTX_BUFFER_SIZE = 0x20801218
NV2080_CTRL_CMD_GR_GET_GLOBAL_SM_ORDER = 0x2080121b
NV2080_CTRL_CMD_GR_GET_CAPS_V2 = 0x20801227
NV2080_CTRL_CMD_GR_GET_GPC_MASK = 0x2080122a
NV2080_CTRL_CMD_GR_GET_TPC_MASK = 0x2080122b
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080gsp.h:
const (
NV2080_CTRL_CMD_GSP_GET_FEATURES = 0x20803601
)
// +marshal
type NV2080_CTRL_GR_GET_INFO_PARAMS struct {
GRInfoListSize uint32 // in elements
Pad [4]byte
GRInfoList P64
GRRouteInfo NV0080_CTRL_GR_ROUTE_INFO
}
// From src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080mc.h:
const (
NV2080_CTRL_CMD_MC_GET_ARCH_INFO = 0x20801701
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080nvlink.h:
const (
NV2080_CTRL_CMD_NVLINK_GET_NVLINK_STATUS = 0x20803002
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080perf.h:
const (
NV2080_CTRL_CMD_PERF_BOOST = 0x2080200a
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080rc.h:
const (
NV2080_CTRL_CMD_RC_GET_WATCHDOG_INFO = 0x20802209
NV2080_CTRL_CMD_RC_RELEASE_WATCHDOG_REQUESTS = 0x2080220c
NV2080_CTRL_CMD_RC_SOFT_DISABLE_WATCHDOG = 0x20802210
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080tmr.h:
const (
NV2080_CTRL_CMD_TIMER_GET_GPU_CPU_TIME_CORRELATION_INFO = 0x20800406
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl503c.h:
const (
NV503C_CTRL_CMD_REGISTER_VA_SPACE = 0x503c0102
NV503C_CTRL_CMD_REGISTER_VIDMEM = 0x503c0104
NV503C_CTRL_CMD_UNREGISTER_VIDMEM = 0x503c0105
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl83de/ctrl83dedebug.h:
const (
NV83DE_CTRL_CMD_DEBUG_SET_EXCEPTION_MASK = 0x83de0309
NV83DE_CTRL_CMD_DEBUG_READ_ALL_SM_ERROR_STATES = 0x83de030c
NV83DE_CTRL_CMD_DEBUG_CLEAR_ALL_SM_ERROR_STATES = 0x83de0310
)
// From src/common/sdk/nvidia/inc/ctrl/ctrlc36f.h:
const (
NVC36F_CTRL_GET_CLASS_ENGINEID = 0xc36f0101
NVC36F_CTRL_CMD_GPFIFO_GET_WORK_SUBMIT_TOKEN = 0xc36f0108
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl906f.h:
const (
NV906F_CTRL_CMD_RESET_CHANNEL = 0x906f0102
)
// From src/common/sdk/nvidia/inc/ctrl/ctrl90e6.h:
const (
NV90E6_CTRL_CMD_MASTER_GET_VIRTUAL_FUNCTION_ERROR_CONT_INTR_MASK = 0x90e60102
)
// From src/common/sdk/nvidia/inc/ctrl/ctrla06c.h:
const (
NVA06C_CTRL_CMD_GPFIFO_SCHEDULE = 0xa06c0101
NVA06C_CTRL_CMD_SET_TIMESLICE = 0xa06c0103
NVA06C_CTRL_CMD_PREEMPT = 0xa06c0105
)
+322
View File
@@ -0,0 +1,322 @@
// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package nvgpu
// NV_IOCTL_MAGIC is the "canonical" IOC_TYPE for frontend ioctls.
// The driver ignores IOC_TYPE, allowing any value to be passed.
const NV_IOCTL_MAGIC = uint32('F')
// Frontend ioctl numbers.
// Note that these are only the IOC_NR part of the ioctl command.
const (
// From kernel-open/common/inc/nv-ioctl-numbers.h:
NV_IOCTL_BASE = 200
NV_ESC_CARD_INFO = NV_IOCTL_BASE + 0
NV_ESC_REGISTER_FD = NV_IOCTL_BASE + 1
NV_ESC_ALLOC_OS_EVENT = NV_IOCTL_BASE + 6
NV_ESC_FREE_OS_EVENT = NV_IOCTL_BASE + 7
NV_ESC_CHECK_VERSION_STR = NV_IOCTL_BASE + 10
NV_ESC_SYS_PARAMS = NV_IOCTL_BASE + 14
// From kernel-open/common/inc/nv-ioctl-numa.h:
NV_ESC_NUMA_INFO = NV_IOCTL_BASE + 15
// From src/nvidia/arch/nvalloc/unix/include/nv_escape.h:
NV_ESC_RM_ALLOC_MEMORY = 0x27
NV_ESC_RM_FREE = 0x29
NV_ESC_RM_CONTROL = 0x2a
NV_ESC_RM_ALLOC = 0x2b
NV_ESC_RM_DUP_OBJECT = 0x34
NV_ESC_RM_SHARE = 0x35
NV_ESC_RM_VID_HEAP_CONTROL = 0x4a
NV_ESC_RM_MAP_MEMORY = 0x4e
NV_ESC_RM_UNMAP_MEMORY = 0x4f
NV_ESC_RM_UPDATE_DEVICE_MAPPING_INFO = 0x5e
)
// Frontend ioctl parameter structs, from src/common/sdk/nvidia/inc/nvos.h or
// kernel-open/common/inc/nv-ioctl.h.
// IoctlRegisterFD is nv_ioctl_register_fd_t, the parameter type for
// NV_ESC_REGISTER_FD.
//
// +marshal
type IoctlRegisterFD struct {
CtlFD int32
}
// IoctlAllocOSEvent is nv_ioctl_alloc_os_event_t, the parameter type for
// NV_ESC_ALLOC_OS_EVENT.
//
// +marshal
type IoctlAllocOSEvent struct {
HClient Handle
HDevice Handle
FD uint32
Status uint32
}
// IoctlFreeOSEvent is nv_ioctl_free_os_event_t, the parameter type for
// NV_ESC_FREE_OS_EVENT.
//
// +marshal
type IoctlFreeOSEvent struct {
HClient Handle
HDevice Handle
FD uint32
Status uint32
}
// RMAPIVersion is nv_rm_api_version_t, the parameter type for
// NV_ESC_CHECK_VERSION_STR.
//
// +marshal
type RMAPIVersion struct {
Cmd uint32
Reply uint32
VersionString [64]byte
}
// IoctlSysParams is nv_ioctl_sys_params_t, the parameter type for
// NV_ESC_SYS_PARAMS.
//
// +marshal
type IoctlSysParams struct {
MemblockSize uint64
}
// IoctlNVOS02ParametersWithFD is nv_ioctl_nvos2_parameters_with_fd, the
// parameter type for NV_ESC_RM_ALLOC_MEMORY.
//
// +marshal
type IoctlNVOS02ParametersWithFD struct {
Params NVOS02Parameters
FD int32
Pad0 [4]byte
}
// +marshal
type NVOS02Parameters struct {
HRoot Handle
HObjectParent Handle
HObjectNew Handle
HClass uint32
Flags uint32
Pad0 [4]byte
PMemory P64 // address of application mapping, without indirection
Limit uint64
Status uint32
Pad1 [4]byte
}
// NVOS00Parameters is NVOS00_PARAMETERS, the parameter type for
// NV_ESC_RM_FREE.
//
// +marshal
type NVOS00Parameters struct {
HRoot Handle
HObjectParent Handle
HObjectOld Handle
Status uint32
}
// NVOS21Parameters is NVOS21_PARAMETERS, one possible parameter type for
// NV_ESC_RM_ALLOC.
//
// +marshal
type NVOS21Parameters struct {
HRoot Handle
HObjectParent Handle
HObjectNew Handle
HClass uint32
PAllocParms P64
Status uint32
Pad0 [4]byte
}
// NVOS55Parameters is NVOS55_PARAMETERS, the parameter type for
// NV_ESC_RM_DUP_OBJECT.
//
// +marshal
type NVOS55Parameters struct {
HClient Handle
HParent Handle
HObject Handle
HClientSrc Handle
HObjectSrc Handle
Flags uint32
Status uint32
}
// NVOS57Parameters is NVOS57_PARAMETERS, the parameter type for
// NV_ESC_RM_SHARE.
//
// +marshal
type NVOS57Parameters struct {
HClient Handle
HObject Handle
SharePolicy RS_SHARE_POLICY
Status uint32
}
// NVOS32Parameters is NVOS32_PARAMETERS, the parameter type for
// NV_ESC_RM_VID_HEAP_CONTROL.
//
// +marshal
type NVOS32Parameters struct {
HRoot Handle
HObjectParent Handle
Function uint32
HVASpace Handle
IVCHeapNumber int16
Pad [2]byte
Status uint32
Total uint64
Free uint64
Data [144]byte // union
}
// Possible values for NVOS32Parameters.Function:
const (
NVOS32_FUNCTION_ALLOC_SIZE = 2
)
// NVOS32AllocSize is the type of NVOS32Parameters.Data for
// NVOS32_FUNCTION_ALLOC_SIZE.
type NVOS32AllocSize struct {
Owner uint32
HMemory Handle
Type uint32
Flags uint32
Attr uint32
Format uint32
ComprCovg uint32
ZcullCovg uint32
PartitionStride uint32
Width uint32
Height uint32
Pad0 [4]byte
Size uint64
Alignment uint64
Offset uint64
Limit uint64
Address P64
RangeBegin uint64
RangeEnd uint64
Attr2 uint32
CtagOffset uint32
}
// IoctlNVOS33ParametersWithFD is nv_ioctl_nvos33_parameters_with_fd, the
// parameter type for NV_ESC_RM_MAP_MEMORY, from
// src/nvidia/arch/nvalloc/unix/include/nv-unix-nvos-params-wrappers.h.
//
// +marshal
type IoctlNVOS33ParametersWithFD struct {
Params NVOS33Parameters
FD int32
Pad0 [4]byte
}
// +marshal
type NVOS33Parameters struct {
HClient Handle
HDevice Handle
HMemory Handle
Pad0 [4]byte
Offset uint64
Length uint64
PLinearAddress P64 // address of application mapping, without indirection
Status uint32
Flags uint32
}
// NVOS34Parameters is NVOS34_PARAMETERS, the parameter type for
// NV_ESC_RM_UNMAP_MEMORY.
//
// +marshal
type NVOS34Parameters struct {
HClient Handle
HDevice Handle
HMemory Handle
Pad0 [4]byte
PLinearAddress P64 // address of application mapping, without indirection
Status uint32
Flags uint32
}
// NVOS54Parameters is NVOS54_PARAMETERS, the parameter type for
// NV_ESC_RM_CONTROL.
//
// +marshal
type NVOS54Parameters struct {
HClient Handle
HObject Handle
Cmd uint32
Flags uint32
Params P64
ParamsSize uint32
Status uint32
}
// NVOS56Parameters is NVOS56_PARAMETERS, the parameter type for
// NV_ESC_RM_UPDATE_DEVICE_MAPPING_INFO.
//
// +marshal
type NVOS56Parameters struct {
HClient Handle
HDevice Handle
HMemory Handle
Pad0 [4]byte
POldCPUAddress P64
PNewCPUAddress P64
Status uint32
Pad1 [4]byte
}
// NVOS64Parameters is NVOS64_PARAMETERS, one possible parameter type for
// NV_ESC_RM_ALLOC.
//
// +marshal
type NVOS64Parameters struct {
HRoot Handle
HObjectParent Handle
HObjectNew Handle
HClass uint32
PAllocParms P64
PRightsRequested P64
Flags uint32
Status uint32
}
// Frontend ioctl parameter struct sizes.
var (
SizeofIoctlRegisterFD = uint32((*IoctlRegisterFD)(nil).SizeBytes())
SizeofIoctlAllocOSEvent = uint32((*IoctlAllocOSEvent)(nil).SizeBytes())
SizeofIoctlFreeOSEvent = uint32((*IoctlFreeOSEvent)(nil).SizeBytes())
SizeofRMAPIVersion = uint32((*RMAPIVersion)(nil).SizeBytes())
SizeofIoctlSysParams = uint32((*IoctlSysParams)(nil).SizeBytes())
SizeofIoctlNVOS02ParametersWithFD = uint32((*IoctlNVOS02ParametersWithFD)(nil).SizeBytes())
SizeofNVOS00Parameters = uint32((*NVOS00Parameters)(nil).SizeBytes())
SizeofNVOS21Parameters = uint32((*NVOS21Parameters)(nil).SizeBytes())
SizeofIoctlNVOS33ParametersWithFD = uint32((*IoctlNVOS33ParametersWithFD)(nil).SizeBytes())
SizeofNVOS55Parameters = uint32((*NVOS55Parameters)(nil).SizeBytes())
SizeofNVOS57Parameters = uint32((*NVOS57Parameters)(nil).SizeBytes())
SizeofNVOS32Parameters = uint32((*NVOS32Parameters)(nil).SizeBytes())
SizeofNVOS34Parameters = uint32((*NVOS34Parameters)(nil).SizeBytes())
SizeofNVOS54Parameters = uint32((*NVOS54Parameters)(nil).SizeBytes())
SizeofNVOS56Parameters = uint32((*NVOS56Parameters)(nil).SizeBytes())
SizeofNVOS64Parameters = uint32((*NVOS64Parameters)(nil).SizeBytes())
)
+64
View File
@@ -0,0 +1,64 @@
// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package nvgpu tracks the ABI of the Nvidia GPU Linux kernel driver:
// https://github.com/NVIDIA/open-gpu-kernel-modules
package nvgpu
// Device numbers.
const (
NV_MAJOR_DEVICE_NUMBER = 195 // from kernel-open/common/inc/nv.h
NV_CONTROL_DEVICE_MINOR = 255 // from kernel-open/common/inc/nv-linux.h
NVIDIA_UVM_PRIMARY_MINOR_NUMBER = 0 // from kernel-open/nvidia-uvm/uvm_common.h
)
// Handle is NvHandle, from src/common/sdk/nvidia/inc/nvtypes.h.
//
// +marshal
type Handle struct {
Val uint32
}
// P64 is NvP64, from src/common/sdk/nvidia/inc/nvtypes.h.
//
// +marshal
type P64 uint64
// From src/common/sdk/nvidia/inc/nvlimits.h:
const (
NV_MAX_DEVICES = 32
NV_MAX_SUBDEVICES = 8
)
// RS_ACCESS_MASK is RS_ACCESS_MASK, from
// src/common/sdk/nvidia/inc/rs_access.h.
//
// +marshal
type RS_ACCESS_MASK struct {
Limbs [SDK_RS_ACCESS_MAX_LIMBS]uint32 // RsAccessLimb
}
const SDK_RS_ACCESS_MAX_LIMBS = 1
// RS_SHARE_POLICY is RS_SHARE_POLICY, from
// src/common/sdk/nvidia/inc/rs_access.h.
//
// +marshal
type RS_SHARE_POLICY struct {
Target uint32
AccessMask RS_ACCESS_MASK
Type uint16
Action uint8
Pad [1]byte
}
+22
View File
@@ -0,0 +1,22 @@
// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package nvgpu
// Status codes, from src/common/sdk/nvidia/inc/nvstatuscodes.h.
const (
NV_ERR_INVALID_ADDRESS = 0x0000001e
NV_ERR_INVALID_LIMIT = 0x0000002e
NV_ERR_NOT_SUPPORTED = 0x00000056
)
+236
View File
@@ -0,0 +1,236 @@
// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package nvgpu
// HasRMCtrlFD is a type constraint for UVM parameter structs containing a
// RMCtrlFD field. This is necessary because, as of this writing (Go 1.20),
// there is no way to enable field access using a Go type constraint.
type HasRMCtrlFD interface {
GetRMCtrlFD() int32
SetRMCtrlFD(int32)
}
// UVM ioctl commands.
const (
// From kernel-open/nvidia-uvm/uvm_linux_ioctl.h:
UVM_INITIALIZE = 0x30000001
UVM_DEINITIALIZE = 0x30000002
// From kernel-open/nvidia-uvm/uvm_ioctl.h:
UVM_CREATE_RANGE_GROUP = 23
UVM_DESTROY_RANGE_GROUP = 24
UVM_REGISTER_GPU_VASPACE = 25
UVM_UNREGISTER_GPU_VASPACE = 26
UVM_REGISTER_CHANNEL = 27
UVM_UNREGISTER_CHANNEL = 28
UVM_MAP_EXTERNAL_ALLOCATION = 33
UVM_FREE = 34
UVM_REGISTER_GPU = 37
UVM_UNREGISTER_GPU = 38
UVM_PAGEABLE_MEM_ACCESS = 39
UVM_MAP_DYNAMIC_PARALLELISM_REGION = 65
UVM_ALLOC_SEMAPHORE_POOL = 68
UVM_VALIDATE_VA_RANGE = 72
UVM_CREATE_EXTERNAL_RANGE = 73
)
// +marshal
type UVM_INITIALIZE_PARAMS struct {
Flags uint64
RMStatus uint32
Pad0 [4]byte
}
// UVM_INITIALIZE_PARAMS flags, from kernel-open/nvidia-uvm/uvm_types.h.
const (
UVM_INIT_FLAGS_MULTI_PROCESS_SHARING_MODE = 0x2
)
// +marshal
type UVM_CREATE_RANGE_GROUP_PARAMS struct {
RangeGroupID uint64
RMStatus uint32
Pad0 [4]byte
}
// +marshal
type UVM_DESTROY_RANGE_GROUP_PARAMS struct {
RangeGroupID uint64
RMStatus uint32
Pad0 [4]byte
}
// +marshal
type UVM_REGISTER_GPU_VASPACE_PARAMS struct {
GPUUUID [16]uint8
RMCtrlFD int32
HClient Handle
HVASpace Handle
RMStatus uint32
}
func (p *UVM_REGISTER_GPU_VASPACE_PARAMS) GetRMCtrlFD() int32 {
return p.RMCtrlFD
}
func (p *UVM_REGISTER_GPU_VASPACE_PARAMS) SetRMCtrlFD(fd int32) {
p.RMCtrlFD = fd
}
// +marshal
type UVM_UNREGISTER_GPU_VASPACE_PARAMS struct {
GPUUUID [16]uint8
RMStatus uint32
}
// +marshal
type UVM_REGISTER_CHANNEL_PARAMS struct {
GPUUUID [16]uint8
RMCtrlFD int32
HClient Handle
HChannel Handle
Pad [4]byte
Base uint64
Length uint64
RMStatus uint32
Pad0 [4]byte
}
func (p *UVM_REGISTER_CHANNEL_PARAMS) GetRMCtrlFD() int32 {
return p.RMCtrlFD
}
func (p *UVM_REGISTER_CHANNEL_PARAMS) SetRMCtrlFD(fd int32) {
p.RMCtrlFD = fd
}
// +marshal
type UVM_UNREGISTER_CHANNEL_PARAMS struct {
GPUUUID [16]uint8
HClient Handle
HChannel Handle
RMStatus uint32
}
// +marshal
type UVM_MAP_EXTERNAL_ALLOCATION_PARAMS struct {
Base uint64
Length uint64
Offset uint64
PerGPUAttributes [UVM_MAX_GPUS]UvmGpuMappingAttributes
GPUAttributesCount uint64
RMCtrlFD int32
HClient Handle
HMemory Handle
RMStatus uint32
}
func (p *UVM_MAP_EXTERNAL_ALLOCATION_PARAMS) GetRMCtrlFD() int32 {
return p.RMCtrlFD
}
func (p *UVM_MAP_EXTERNAL_ALLOCATION_PARAMS) SetRMCtrlFD(fd int32) {
p.RMCtrlFD = fd
}
// +marshal
type UVM_FREE_PARAMS struct {
Base uint64
Length uint64
RMStatus uint32
Pad0 [4]byte
}
// +marshal
type UVM_REGISTER_GPU_PARAMS struct {
GPUUUID [16]uint8
NumaEnabled uint8
Pad [3]byte
NumaNodeID int32
RMCtrlFD int32
HClient Handle
HSMCPartRef Handle
RMStatus uint32
}
func (p *UVM_REGISTER_GPU_PARAMS) GetRMCtrlFD() int32 {
return p.RMCtrlFD
}
func (p *UVM_REGISTER_GPU_PARAMS) SetRMCtrlFD(fd int32) {
p.RMCtrlFD = fd
}
// +marshal
type UVM_UNREGISTER_GPU_PARAMS struct {
GPUUUID [16]uint8
RMStatus uint32
}
// +marshal
type UVM_PAGEABLE_MEM_ACCESS_PARAMS struct {
PageableMemAccess uint8
Pad [3]byte
RMStatus uint32
}
// +marshal
type UVM_MAP_DYNAMIC_PARALLELISM_REGION_PARAMS struct {
Base uint64
Length uint64
GPUUUID [16]uint8
RMStatus uint32
Pad0 [4]byte
}
// +marshal
type UVM_ALLOC_SEMAPHORE_POOL_PARAMS struct {
Base uint64
Length uint64
PerGPUAttributes [UVM_MAX_GPUS]UvmGpuMappingAttributes
GPUAttributesCount uint64
RMStatus uint32
Pad0 [4]byte
}
// +marshal
type UVM_VALIDATE_VA_RANGE_PARAMS struct {
Base uint64
Length uint64
RMStatus uint32
Pad0 [4]byte
}
// +marshal
type UVM_CREATE_EXTERNAL_RANGE_PARAMS struct {
Base uint64
Length uint64
RMStatus uint32
Pad0 [4]byte
}
// From kernel-open/nvidia-uvm/uvm_types.h:
const UVM_MAX_GPUS = NV_MAX_DEVICES
// +marshal
type UvmGpuMappingAttributes struct {
GPUUUID [16]byte
GPUMappingType uint32
GPUCachingType uint32
GPUFormatType uint32
GPUElementBits uint32
GPUCompressionType uint32
}
+55
View File
@@ -0,0 +1,55 @@
load("//tools:defs.bzl", "go_library")
load("//pkg/sync/locking:locking.bzl", "declare_mutex")
package(default_applicable_licenses = ["//:license"])
licenses(["notice"])
declare_mutex(
name = "objs_mutex",
out = "objs_mutex.go",
package = "nvproxy",
prefix = "objs",
)
go_library(
name = "nvproxy",
srcs = [
"frontend.go",
"frontend_mmap.go",
"frontend_unsafe.go",
"nvproxy.go",
"nvproxy_unsafe.go",
"objs_mutex.go",
"seccomp_filters.go",
"uvm.go",
"uvm_mmap.go",
"uvm_unsafe.go",
],
visibility = ["//pkg/sentry:internal"],
deps = [
"//pkg/abi/linux",
"//pkg/abi/nvgpu",
"//pkg/cleanup",
"//pkg/context",
"//pkg/errors/linuxerr",
"//pkg/fdnotifier",
"//pkg/hostarch",
"//pkg/log",
"//pkg/marshal",
"//pkg/marshal/primitive",
"//pkg/safemem",
"//pkg/seccomp",
"//pkg/sentry/arch",
"//pkg/sentry/fsimpl/devtmpfs",
"//pkg/sentry/kernel",
"//pkg/sentry/memmap",
"//pkg/sentry/mm",
"//pkg/sentry/vfs",
"//pkg/sync",
"//pkg/sync/locking",
"//pkg/usermem",
"//pkg/waiter",
"@org_golang_x_sys//unix:go_default_library",
],
)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,85 @@
// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package nvproxy
import (
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sentry/vfs"
)
// ConfigureMMap implements vfs.FileDescriptionImpl.ConfigureMMap.
func (fd *frontendFD) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) error {
return vfs.GenericConfigureMMap(&fd.vfsfd, fd, opts)
}
// AddMapping implements memmap.Mappable.AddMapping.
func (fd *frontendFD) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar hostarch.AddrRange, offset uint64, writable bool) error {
return nil
}
// RemoveMapping implements memmap.Mappable.RemoveMapping.
func (fd *frontendFD) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar hostarch.AddrRange, offset uint64, writable bool) {
}
// CopyMapping implements memmap.Mappable.CopyMapping.
func (fd *frontendFD) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR hostarch.AddrRange, offset uint64, writable bool) error {
return nil
}
// Translate implements memmap.Mappable.Translate.
func (fd *frontendFD) Translate(ctx context.Context, required, optional memmap.MappableRange, at hostarch.AccessType) ([]memmap.Translation, error) {
return []memmap.Translation{
{
Source: optional,
File: &fd.memmapFile,
Offset: optional.Start,
Perms: at,
},
}, nil
}
// InvalidateUnsavable implements memmap.Mappable.InvalidateUnsavable.
func (fd *frontendFD) InvalidateUnsavable(ctx context.Context) error {
return nil
}
type frontendFDMemmapFile struct {
fd *frontendFD
}
// IncRef implements memmap.File.IncRef.
func (mf *frontendFDMemmapFile) IncRef(fr memmap.FileRange) {
}
// DecRef implements memmap.File.DecRef.
func (mf *frontendFDMemmapFile) DecRef(fr memmap.FileRange) {
}
// MapInternal implements memmap.File.MapInternal.
func (mf *frontendFDMemmapFile) MapInternal(fr memmap.FileRange, at hostarch.AccessType) (safemem.BlockSeq, error) {
// FIXME(jamieliu): determine if this is safe
log.Traceback("nvproxy: rejecting frontendFDMemmapFile.MapInternal")
return safemem.BlockSeq{}, linuxerr.EINVAL
}
// FD implements memmap.File.FD.
func (mf *frontendFDMemmapFile) FD() int {
return int(mf.fd.hostFD)
}
@@ -0,0 +1,241 @@
// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package nvproxy
import (
"runtime"
"unsafe"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/nvgpu"
"gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/marshal/primitive"
)
func frontendIoctlInvoke[Params any](fi *frontendIoctlState, sentryParams *Params) (uintptr, error) {
n, _, errno := unix.RawSyscall(unix.SYS_IOCTL, uintptr(fi.fd.hostFD), frontendIoctlCmd(fi.nr, fi.ioctlParamsSize), uintptr(unsafe.Pointer(sentryParams)))
if errno != 0 {
return n, errno
}
return n, nil
}
func rmControlInvoke[Params any](fi *frontendIoctlState, ioctlParams *nvgpu.NVOS54Parameters, ctrlParams *Params) (uintptr, error) {
defer runtime.KeepAlive(ctrlParams) // since we convert to non-pointer-typed P64
sentryIoctlParams := *ioctlParams
sentryIoctlParams.Params = p64FromPtr(unsafe.Pointer(ctrlParams))
n, err := frontendIoctlInvoke(fi, &sentryIoctlParams)
if err != nil {
return n, err
}
outIoctlParams := sentryIoctlParams
outIoctlParams.Params = ioctlParams.Params
if _, err := outIoctlParams.CopyOut(fi.t, fi.ioctlParamsAddr); err != nil {
return n, err
}
return n, nil
}
func ctrlClientSystemGetBuildVersionInvoke(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS54Parameters, ctrlParams *nvgpu.NV0000_CTRL_SYSTEM_GET_BUILD_VERSION_PARAMS, driverVersionBuf, versionBuf, titleBuf *byte) (uintptr, error) {
sentryCtrlParams := *ctrlParams
sentryCtrlParams.PDriverVersionBuffer = p64FromPtr(unsafe.Pointer(driverVersionBuf))
sentryCtrlParams.PVersionBuffer = p64FromPtr(unsafe.Pointer(versionBuf))
sentryCtrlParams.PTitleBuffer = p64FromPtr(unsafe.Pointer(titleBuf))
n, err := rmControlInvoke(fi, ioctlParams, &sentryCtrlParams)
if err != nil {
return n, err
}
outCtrlParams := sentryCtrlParams
outCtrlParams.PDriverVersionBuffer = ctrlParams.PDriverVersionBuffer
outCtrlParams.PVersionBuffer = ctrlParams.PVersionBuffer
outCtrlParams.PTitleBuffer = ctrlParams.PTitleBuffer
if _, err := outCtrlParams.CopyOut(fi.t, addrFromP64(ioctlParams.Params)); err != nil {
return n, err
}
return n, nil
}
func ctrlDevFIFOGetChannelList(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS54Parameters) (uintptr, error) {
var ctrlParams nvgpu.NV0080_CTRL_FIFO_GET_CHANNELLIST_PARAMS
if ctrlParams.SizeBytes() != int(ioctlParams.ParamsSize) {
return 0, linuxerr.EINVAL
}
if _, err := ctrlParams.CopyIn(fi.t, addrFromP64(ioctlParams.Params)); err != nil {
return 0, err
}
if ctrlParams.NumChannels == 0 {
// Compare
// src/nvidia/src/kernel/gpu/fifo/kernel_fifo_ctrl.c:deviceCtrlCmdFifoGetChannelList_IMPL().
return 0, linuxerr.EINVAL
}
channelHandleList := make([]uint32, ctrlParams.NumChannels)
if _, err := primitive.CopyUint32SliceIn(fi.t, addrFromP64(ctrlParams.PChannelHandleList), channelHandleList); err != nil {
return 0, err
}
channelList := make([]uint32, ctrlParams.NumChannels)
if _, err := primitive.CopyUint32SliceIn(fi.t, addrFromP64(ctrlParams.PChannelList), channelList); err != nil {
return 0, err
}
sentryCtrlParams := ctrlParams
sentryCtrlParams.PChannelHandleList = p64FromPtr(unsafe.Pointer(&channelHandleList[0]))
sentryCtrlParams.PChannelList = p64FromPtr(unsafe.Pointer(&channelList[0]))
n, err := rmControlInvoke(fi, ioctlParams, &sentryCtrlParams)
if err != nil {
return n, err
}
if _, err := primitive.CopyUint32SliceOut(fi.t, addrFromP64(ctrlParams.PChannelHandleList), channelHandleList); err != nil {
return 0, err
}
if _, err := primitive.CopyUint32SliceOut(fi.t, addrFromP64(ctrlParams.PChannelList), channelList); err != nil {
return 0, err
}
outCtrlParams := sentryCtrlParams
outCtrlParams.PChannelHandleList = ctrlParams.PChannelHandleList
outCtrlParams.PChannelList = ctrlParams.PChannelList
if _, err := outCtrlParams.CopyOut(fi.t, addrFromP64(ioctlParams.Params)); err != nil {
return n, err
}
return n, nil
}
func ctrlSubdevGRGetInfo(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS54Parameters) (uintptr, error) {
var ctrlParams nvgpu.NV2080_CTRL_GR_GET_INFO_PARAMS
if ctrlParams.SizeBytes() != int(ioctlParams.ParamsSize) {
return 0, linuxerr.EINVAL
}
if _, err := ctrlParams.CopyIn(fi.t, addrFromP64(ioctlParams.Params)); err != nil {
return 0, err
}
if ctrlParams.GRInfoListSize == 0 {
// Compare
// src/nvidia/src/kernel/gpu/gr/kernel_graphics.c:_kgraphicsCtrlCmdGrGetInfoV2().
return 0, linuxerr.EINVAL
}
infoList := make([]byte, int(ctrlParams.GRInfoListSize)*(*nvgpu.NVXXXX_CTRL_XXX_INFO)(nil).SizeBytes())
if _, err := fi.t.CopyInBytes(addrFromP64(ctrlParams.GRInfoList), infoList); err != nil {
return 0, err
}
sentryCtrlParams := ctrlParams
sentryCtrlParams.GRInfoList = p64FromPtr(unsafe.Pointer(&infoList[0]))
n, err := rmControlInvoke(fi, ioctlParams, &sentryCtrlParams)
if err != nil {
return n, err
}
if _, err := fi.t.CopyOutBytes(addrFromP64(ctrlParams.GRInfoList), infoList); err != nil {
return n, err
}
outCtrlParams := sentryCtrlParams
outCtrlParams.GRInfoList = ctrlParams.GRInfoList
if _, err := outCtrlParams.CopyOut(fi.t, addrFromP64(ioctlParams.Params)); err != nil {
return n, err
}
return n, nil
}
func rmAllocInvoke[Params any](fi *frontendIoctlState, ioctlParams *nvgpu.NVOS64Parameters, allocParams *Params, isNVOS64 bool) (uintptr, error) {
defer runtime.KeepAlive(allocParams) // since we convert to non-pointer-typed P64
if isNVOS64 {
sentryIoctlParams := *ioctlParams
sentryIoctlParams.PAllocParms = p64FromPtr(unsafe.Pointer(allocParams))
var rightsRequested nvgpu.RS_ACCESS_MASK
if ioctlParams.PRightsRequested != 0 {
if _, err := rightsRequested.CopyIn(fi.t, addrFromP64(ioctlParams.PRightsRequested)); err != nil {
return 0, err
}
sentryIoctlParams.PRightsRequested = p64FromPtr(unsafe.Pointer(&rightsRequested))
}
n, err := frontendIoctlInvoke(fi, &sentryIoctlParams)
if err != nil {
return n, err
}
if ioctlParams.PRightsRequested != 0 {
if _, err := rightsRequested.CopyOut(fi.t, addrFromP64(ioctlParams.PRightsRequested)); err != nil {
return n, err
}
}
outIoctlParams := sentryIoctlParams
outIoctlParams.PAllocParms = ioctlParams.PAllocParms
outIoctlParams.PRightsRequested = ioctlParams.PRightsRequested
if _, err := outIoctlParams.CopyOut(fi.t, fi.ioctlParamsAddr); err != nil {
return n, err
}
return n, nil
}
sentryIoctlParams := nvgpu.NVOS21Parameters{
HRoot: ioctlParams.HRoot,
HObjectParent: ioctlParams.HObjectParent,
HObjectNew: ioctlParams.HObjectNew,
HClass: ioctlParams.HClass,
PAllocParms: p64FromPtr(unsafe.Pointer(allocParams)),
Status: ioctlParams.Status,
}
n, err := frontendIoctlInvoke(fi, &sentryIoctlParams)
if err != nil {
return n, err
}
outIoctlParams := nvgpu.NVOS21Parameters{
HRoot: sentryIoctlParams.HRoot,
HObjectParent: sentryIoctlParams.HObjectParent,
HObjectNew: sentryIoctlParams.HObjectNew,
HClass: sentryIoctlParams.HClass,
PAllocParms: ioctlParams.PAllocParms,
Status: sentryIoctlParams.Status,
}
if _, err := outIoctlParams.CopyOut(fi.t, fi.ioctlParamsAddr); err != nil {
return n, err
}
return n, nil
}
func rmVidHeapControlAllocSize(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS32Parameters) (uintptr, error) {
allocSizeParams := (*nvgpu.NVOS32AllocSize)(unsafe.Pointer(&ioctlParams.Data))
sentryIoctlParams := *ioctlParams
sentryAllocSizeParams := (*nvgpu.NVOS32AllocSize)(unsafe.Pointer(&sentryIoctlParams.Data))
var addr uint64
if allocSizeParams.Address != 0 {
if _, err := primitive.CopyUint64In(fi.t, addrFromP64(allocSizeParams.Address), &addr); err != nil {
return 0, err
}
sentryAllocSizeParams.Address = p64FromPtr(unsafe.Pointer(&addr))
}
n, err := frontendIoctlInvoke(fi, &sentryIoctlParams)
if err != nil {
return n, err
}
outIoctlParams := sentryIoctlParams
outAllocSizeParams := (*nvgpu.NVOS32AllocSize)(unsafe.Pointer(&outIoctlParams.Data))
if allocSizeParams.Address != 0 {
if _, err := primitive.CopyUint64Out(fi.t, addrFromP64(allocSizeParams.Address), addr); err != nil {
return n, err
}
outAllocSizeParams.Address = allocSizeParams.Address
}
if _, err := outIoctlParams.CopyOut(fi.t, fi.ioctlParamsAddr); err != nil {
return n, err
}
return n, nil
}
+136
View File
@@ -0,0 +1,136 @@
// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package nvproxy implements proxying for the Nvidia GPU Linux kernel driver:
// https://github.com/NVIDIA/open-gpu-kernel-modules
package nvproxy
import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/nvgpu"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/sentry/fsimpl/devtmpfs"
"gvisor.dev/gvisor/pkg/sentry/mm"
"gvisor.dev/gvisor/pkg/sentry/vfs"
)
// Register registers all devices implemented by this package in vfsObj.
func Register(vfsObj *vfs.VirtualFilesystem, uvmDevMajor uint32) error {
// The kernel driver's interface is unstable, so only allow versions of the
// driver that are known to be supported.
version, err := hostDriverVersion()
if err != nil {
return fmt.Errorf("failed to get Nvidia driver version: %w", err)
}
switch version {
case "525.60.13":
log.Infof("Nvidia driver version: %s", version)
default:
return fmt.Errorf("unknown Nvidia driver version: %s", version)
}
nvp := &nvproxy{
objsLive: make(map[nvgpu.Handle]*object),
}
for minor := uint32(0); minor <= nvgpu.NV_CONTROL_DEVICE_MINOR; minor++ {
if err := vfsObj.RegisterDevice(vfs.CharDevice, nvgpu.NV_MAJOR_DEVICE_NUMBER, minor, &frontendDevice{
nvp: nvp,
minor: minor,
}, &vfs.RegisterDeviceOptions{
GroupName: "nvidia-frontend",
}); err != nil {
return err
}
}
if err := vfsObj.RegisterDevice(vfs.CharDevice, uvmDevMajor, nvgpu.NVIDIA_UVM_PRIMARY_MINOR_NUMBER, &uvmDevice{
nvp: nvp,
}, &vfs.RegisterDeviceOptions{
GroupName: "nvidia-uvm",
}); err != nil {
return err
}
return nil
}
// CreateDriverDevtmpfsFiles creates device special files in dev that should
// always exist when this package is enabled. It does not create per-device
// files in dev; see CreateIndexDevtmpfsFile.
func CreateDriverDevtmpfsFiles(ctx context.Context, dev *devtmpfs.Accessor, uvmDevMajor uint32) error {
if err := dev.CreateDeviceFile(ctx, "nvidiactl", vfs.CharDevice, nvgpu.NV_MAJOR_DEVICE_NUMBER, nvgpu.NV_CONTROL_DEVICE_MINOR, 0666); err != nil {
return err
}
if err := dev.CreateDeviceFile(ctx, "nvidia-uvm", vfs.CharDevice, uvmDevMajor, nvgpu.NVIDIA_UVM_PRIMARY_MINOR_NUMBER, 0666); err != nil {
return err
}
return nil
}
// CreateIndexDevtmpfsFile creates the device special file in dev for the
// device with the given index.
func CreateIndexDevtmpfsFile(ctx context.Context, dev *devtmpfs.Accessor, index uint32) error {
return dev.CreateDeviceFile(ctx, fmt.Sprintf("nvidia%d", index), vfs.CharDevice, nvgpu.NV_MAJOR_DEVICE_NUMBER, index, 0666)
}
// +stateify savable
type nvproxy struct {
objsMu objsMutex
objsLive map[nvgpu.Handle]*object
}
// object tracks an object allocated through the driver.
//
// +stateify savable
type object struct {
impl objectImpl
}
func (o *object) init(impl objectImpl) {
o.impl = impl
}
// Release is called after the represented object is freed.
func (o *object) Release(ctx context.Context) {
o.impl.Release(ctx)
}
type objectImpl interface {
Release(ctx context.Context)
}
// osDescMem is an objectImpl tracking an OS descriptor.
//
// +stateify savable
type osDescMem struct {
object
pinnedRanges []mm.PinnedRange
}
// Release implements objectImpl.Release.
func (o *osDescMem) Release(ctx context.Context) {
ctx.Infof("nvproxy: unpinning pages for released OS descriptor")
mm.Unpin(o.pinnedRanges)
}
type marshalPtr[T any] interface {
*T
marshal.Marshallable
}
func addrFromP64(p nvgpu.P64) hostarch.Addr {
return hostarch.Addr(uintptr(uint64(p)))
}
@@ -0,0 +1,74 @@
// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package nvproxy
import (
"bytes"
"fmt"
"unsafe"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/nvgpu"
)
func hostDriverVersion() (string, error) {
ctlFD, err := unix.Openat(-1, "/dev/nvidiactl", unix.O_RDONLY|unix.O_NOFOLLOW, 0)
if err != nil {
return "", fmt.Errorf("failed to open /dev/nvidiactl: %w", err)
}
defer unix.Close(ctlFD)
// From src/nvidia/arch/nvalloc/unix/include/nv-ioctl.h:
const NV_RM_API_VERSION_REPLY_RECOGNIZED = 1
// 530.30.02 and later versions of the host driver `#define
// NV_RM_API_VERSION_CMD_QUERY '2'`, which causes this ioctl to return the
// driver version without performing a check. Earlier versions of the
// driver `#define NV_RM_API_VERSION_CMD_OVERRIDE '2'`, which causes the
// ioctl to no-op. Try with Cmd '2' first, hoping that the driver
// interprets it as _QUERY; if the returned string is empty, then it was
// interpreted as _OVERRIDE and we need to perform an actual check (Cmd 0),
// which has the downside of logging an error message.
ioctlParams := nvgpu.RMAPIVersion{
Cmd: '2',
}
if _, _, errno := unix.RawSyscall(unix.SYS_IOCTL, uintptr(ctlFD), frontendIoctlCmd(nvgpu.NV_ESC_CHECK_VERSION_STR, uint32(unsafe.Sizeof(ioctlParams))), uintptr(unsafe.Pointer(&ioctlParams))); errno != 0 {
return "", fmt.Errorf("NV_ESC_CHECK_VERSION_STR ioctl error: %w", errno)
}
if ioctlParams.Reply != NV_RM_API_VERSION_REPLY_RECOGNIZED {
return "", fmt.Errorf("unknown NV_ESC_CHECK_VERSION_STR reply: %d", ioctlParams.Reply)
}
if ioctlParams.VersionString[0] == '\x00' {
ioctlParams.Cmd = 0
ioctlParams.Reply = 0
// We expect the check to fail on our empty version string, so tolerate
// EINVAL.
if _, _, errno := unix.RawSyscall(unix.SYS_IOCTL, uintptr(ctlFD), frontendIoctlCmd(nvgpu.NV_ESC_CHECK_VERSION_STR, uint32(unsafe.Sizeof(ioctlParams))), uintptr(unsafe.Pointer(&ioctlParams))); errno != 0 && errno != unix.EINVAL {
return "", fmt.Errorf("fallback NV_ESC_CHECK_VERSION_STR ioctl error: %w", errno)
}
if ioctlParams.Reply != NV_RM_API_VERSION_REPLY_RECOGNIZED {
return "", fmt.Errorf("unknown fallback NV_ESC_CHECK_VERSION_STR reply: %d", ioctlParams.Reply)
}
}
if i := bytes.IndexByte(ioctlParams.VersionString[:], '\x00'); i >= 0 {
return string(ioctlParams.VersionString[:i]), nil
}
return string(ioctlParams.VersionString[:]), nil
}
func p64FromPtr(ptr unsafe.Pointer) nvgpu.P64 {
return nvgpu.P64(uint64(uintptr(ptr)))
}
@@ -0,0 +1,190 @@
// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package nvproxy
import (
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/abi/nvgpu"
"gvisor.dev/gvisor/pkg/seccomp"
)
// Filters returns seccomp-bpf filters for this package.
func Filters() seccomp.SyscallRules {
nonNegativeFD := seccomp.LessThanOrEqual(0x7fff_ffff /* max int32 */)
notIocSizeMask := ^(((uintptr(1) << linux.IOC_SIZEBITS) - 1) << linux.IOC_SIZESHIFT) // for ioctls taking arbitrary size
return seccomp.SyscallRules{
unix.SYS_OPENAT: []seccomp.Rule{
{
// All paths that we openat() are absolute, so we pass a dirfd
// of -1 (which is invalid for relative paths, but ignored for
// absolute paths) to hedge against bugs involving AT_FDCWD or
// real dirfds.
seccomp.EqualTo(^uintptr(0)),
seccomp.MatchAny{},
seccomp.MaskedEqual(unix.O_NOFOLLOW|unix.O_CREAT, unix.O_NOFOLLOW),
seccomp.MatchAny{},
},
},
unix.SYS_IOCTL: []seccomp.Rule{
{
nonNegativeFD,
seccomp.MaskedEqual(notIocSizeMask, frontendIoctlCmd(nvgpu.NV_ESC_CARD_INFO, 0)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_CHECK_VERSION_STR, nvgpu.SizeofRMAPIVersion)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_REGISTER_FD, nvgpu.SizeofIoctlRegisterFD)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_ALLOC_OS_EVENT, nvgpu.SizeofIoctlAllocOSEvent)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_FREE_OS_EVENT, nvgpu.SizeofIoctlFreeOSEvent)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_SYS_PARAMS, nvgpu.SizeofIoctlSysParams)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_ALLOC_MEMORY, nvgpu.SizeofIoctlNVOS02ParametersWithFD)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_FREE, nvgpu.SizeofNVOS00Parameters)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_CONTROL, nvgpu.SizeofNVOS54Parameters)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_ALLOC, nvgpu.SizeofNVOS21Parameters)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_ALLOC, nvgpu.SizeofNVOS64Parameters)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_DUP_OBJECT, nvgpu.SizeofNVOS55Parameters)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_SHARE, nvgpu.SizeofNVOS57Parameters)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_VID_HEAP_CONTROL, nvgpu.SizeofNVOS32Parameters)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_MAP_MEMORY, nvgpu.SizeofIoctlNVOS33ParametersWithFD)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_UNMAP_MEMORY, nvgpu.SizeofNVOS34Parameters)),
},
{
nonNegativeFD,
seccomp.EqualTo(frontendIoctlCmd(nvgpu.NV_ESC_RM_UPDATE_DEVICE_MAPPING_INFO, nvgpu.SizeofNVOS56Parameters)),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_INITIALIZE),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_DEINITIALIZE),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_CREATE_RANGE_GROUP),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_DESTROY_RANGE_GROUP),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_REGISTER_GPU_VASPACE),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_UNREGISTER_GPU_VASPACE),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_REGISTER_CHANNEL),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_UNREGISTER_CHANNEL),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_MAP_EXTERNAL_ALLOCATION),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_FREE),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_REGISTER_GPU),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_UNREGISTER_GPU),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_PAGEABLE_MEM_ACCESS),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_MAP_DYNAMIC_PARALLELISM_REGION),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_ALLOC_SEMAPHORE_POOL),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_VALIDATE_VA_RANGE),
},
{
nonNegativeFD,
seccomp.EqualTo(nvgpu.UVM_CREATE_EXTERNAL_RANGE),
},
},
unix.SYS_MREMAP: []seccomp.Rule{
{
seccomp.MatchAny{},
seccomp.EqualTo(0), /* old_size */
seccomp.MatchAny{},
seccomp.EqualTo(linux.MREMAP_MAYMOVE | linux.MREMAP_FIXED),
seccomp.MatchAny{},
seccomp.EqualTo(0),
},
},
}
}
+271
View File
@@ -0,0 +1,271 @@
// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package nvproxy
import (
"fmt"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/abi/nvgpu"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/fdnotifier"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/marshal"
"gvisor.dev/gvisor/pkg/sentry/arch"
"gvisor.dev/gvisor/pkg/sentry/kernel"
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/usermem"
"gvisor.dev/gvisor/pkg/waiter"
)
// uvmDevice implements vfs.Device for /dev/nvidia-uvm.
//
// +stateify savable
type uvmDevice struct {
nvp *nvproxy
}
// Open implements vfs.Device.Open.
func (dev *uvmDevice) Open(ctx context.Context, mnt *vfs.Mount, vfsd *vfs.Dentry, opts vfs.OpenOptions) (*vfs.FileDescription, error) {
hostFD, err := unix.Openat(-1, "/dev/nvidia-uvm", int((opts.Flags&unix.O_ACCMODE)|unix.O_NOFOLLOW), 0)
if err != nil {
ctx.Warningf("nvproxy: failed to open host /dev/nvidia-uvm: %v", err)
return nil, err
}
fd := &uvmFD{
nvp: dev.nvp,
hostFD: int32(hostFD),
}
if err := fd.vfsfd.Init(fd, opts.Flags, mnt, vfsd, &vfs.FileDescriptionOptions{
UseDentryMetadata: true,
}); err != nil {
unix.Close(hostFD)
return nil, err
}
if err := fdnotifier.AddFD(int32(hostFD), &fd.queue); err != nil {
unix.Close(hostFD)
return nil, err
}
fd.memmapFile.fd = fd
return &fd.vfsfd, nil
}
// uvmFD implements vfs.FileDescriptionImpl for /dev/nvidia-uvm.
//
// uvmFD is not savable; we do not implement save/restore of host GPU state.
type uvmFD struct {
vfsfd vfs.FileDescription
vfs.FileDescriptionDefaultImpl
vfs.DentryMetadataFileDescriptionImpl
vfs.NoLockFD
nvp *nvproxy
hostFD int32
memmapFile uvmFDMemmapFile
queue waiter.Queue
}
// Release implements vfs.FileDescriptionImpl.Release.
func (fd *uvmFD) Release(context.Context) {
fdnotifier.RemoveFD(fd.hostFD)
fd.queue.Notify(waiter.EventHUp)
unix.Close(int(fd.hostFD))
}
// EventRegister implements waiter.Waitable.EventRegister.
func (fd *uvmFD) EventRegister(e *waiter.Entry) error {
fd.queue.EventRegister(e)
if err := fdnotifier.UpdateFD(fd.hostFD); err != nil {
fd.queue.EventUnregister(e)
return err
}
return nil
}
// EventUnregister implements waiter.Waitable.EventUnregister.
func (fd *uvmFD) EventUnregister(e *waiter.Entry) {
fd.queue.EventUnregister(e)
if err := fdnotifier.UpdateFD(fd.hostFD); err != nil {
panic(fmt.Sprint("UpdateFD:", err))
}
}
// Readiness implements waiter.Waitable.Readiness.
func (fd *uvmFD) Readiness(mask waiter.EventMask) waiter.EventMask {
return fdnotifier.NonBlockingPoll(fd.hostFD, mask)
}
// Epollable implements vfs.FileDescriptionImpl.Epollable.
func (fd *uvmFD) Epollable() bool {
return true
}
// Ioctl implements vfs.FileDescriptionImpl.Ioctl.
func (fd *uvmFD) Ioctl(ctx context.Context, uio usermem.IO, sysno uintptr, args arch.SyscallArguments) (uintptr, error) {
cmd := args[1].Uint()
argPtr := args[2].Pointer()
t := kernel.TaskFromContext(ctx)
if t == nil {
panic("Ioctl should be called from a task context")
}
ui := uvmIoctlState{
fd: fd,
ctx: ctx,
t: t,
cmd: cmd,
ioctlParamsAddr: argPtr,
}
switch cmd {
case nvgpu.UVM_INITIALIZE:
return uvmInitialize(&ui)
case nvgpu.UVM_DEINITIALIZE:
return uvmIoctlInvoke[byte](&ui, nil)
case nvgpu.UVM_CREATE_RANGE_GROUP:
return uvmIoctlSimple[nvgpu.UVM_CREATE_RANGE_GROUP_PARAMS](&ui)
case nvgpu.UVM_DESTROY_RANGE_GROUP:
return uvmIoctlSimple[nvgpu.UVM_DESTROY_RANGE_GROUP_PARAMS](&ui)
case nvgpu.UVM_REGISTER_GPU_VASPACE:
return uvmIoctlHasRMCtrlFD[nvgpu.UVM_REGISTER_GPU_VASPACE_PARAMS](&ui)
case nvgpu.UVM_UNREGISTER_GPU_VASPACE:
return uvmIoctlSimple[nvgpu.UVM_UNREGISTER_GPU_VASPACE_PARAMS](&ui)
case nvgpu.UVM_REGISTER_CHANNEL:
return uvmIoctlHasRMCtrlFD[nvgpu.UVM_REGISTER_CHANNEL_PARAMS](&ui)
case nvgpu.UVM_UNREGISTER_CHANNEL:
return uvmIoctlSimple[nvgpu.UVM_UNREGISTER_CHANNEL_PARAMS](&ui)
case nvgpu.UVM_MAP_EXTERNAL_ALLOCATION:
return uvmIoctlHasRMCtrlFD[nvgpu.UVM_MAP_EXTERNAL_ALLOCATION_PARAMS](&ui)
case nvgpu.UVM_FREE:
return uvmIoctlSimple[nvgpu.UVM_FREE_PARAMS](&ui)
case nvgpu.UVM_REGISTER_GPU:
return uvmIoctlHasRMCtrlFD[nvgpu.UVM_REGISTER_GPU_PARAMS](&ui)
case nvgpu.UVM_UNREGISTER_GPU:
return uvmIoctlSimple[nvgpu.UVM_UNREGISTER_GPU_PARAMS](&ui)
case nvgpu.UVM_PAGEABLE_MEM_ACCESS:
return uvmIoctlSimple[nvgpu.UVM_PAGEABLE_MEM_ACCESS_PARAMS](&ui)
case nvgpu.UVM_MAP_DYNAMIC_PARALLELISM_REGION:
return uvmIoctlSimple[nvgpu.UVM_MAP_DYNAMIC_PARALLELISM_REGION_PARAMS](&ui)
case nvgpu.UVM_ALLOC_SEMAPHORE_POOL:
return uvmIoctlSimple[nvgpu.UVM_ALLOC_SEMAPHORE_POOL_PARAMS](&ui)
case nvgpu.UVM_VALIDATE_VA_RANGE:
return uvmIoctlSimple[nvgpu.UVM_VALIDATE_VA_RANGE_PARAMS](&ui)
case nvgpu.UVM_CREATE_EXTERNAL_RANGE:
return uvmIoctlSimple[nvgpu.UVM_CREATE_EXTERNAL_RANGE_PARAMS](&ui)
default:
ctx.Warningf("nvproxy: unknown uvm ioctl %d", cmd)
return 0, linuxerr.EINVAL
}
}
// uvmIoctlState holds the state of a call to uvmFD.Ioctl().
type uvmIoctlState struct {
fd *uvmFD
ctx context.Context
t *kernel.Task
cmd uint32
ioctlParamsAddr hostarch.Addr
}
func uvmIoctlSimple[Params any, PParams marshalPtr[Params]](ui *uvmIoctlState) (uintptr, error) {
var ioctlParams Params
if _, err := (PParams)(&ioctlParams).CopyIn(ui.t, ui.ioctlParamsAddr); err != nil {
return 0, err
}
n, err := uvmIoctlInvoke(ui, &ioctlParams)
if err != nil {
return n, err
}
if _, err := (PParams)(&ioctlParams).CopyOut(ui.t, ui.ioctlParamsAddr); err != nil {
return n, err
}
return n, nil
}
func uvmInitialize(ui *uvmIoctlState) (uintptr, error) {
var ioctlParams nvgpu.UVM_INITIALIZE_PARAMS
if _, err := ioctlParams.CopyIn(ui.t, ui.ioctlParamsAddr); err != nil {
return 0, err
}
sentryIoctlParams := ioctlParams
// This is necessary to share the host UVM FD between sentry and
// application processes.
sentryIoctlParams.Flags = ioctlParams.Flags | nvgpu.UVM_INIT_FLAGS_MULTI_PROCESS_SHARING_MODE
n, err := uvmIoctlInvoke(ui, &sentryIoctlParams)
if err != nil {
return n, err
}
outIoctlParams := sentryIoctlParams
// Only expose the MULTI_PROCESS_SHARING_MODE flag if it was present in
// ioctlParams.
outIoctlParams.Flags &^= ^ioctlParams.Flags & nvgpu.UVM_INIT_FLAGS_MULTI_PROCESS_SHARING_MODE
if _, err := outIoctlParams.CopyOut(ui.t, ui.ioctlParamsAddr); err != nil {
return n, err
}
return n, nil
}
type hasRMCtrlFDPtr[T any] interface {
*T
marshal.Marshallable
nvgpu.HasRMCtrlFD
}
func uvmIoctlHasRMCtrlFD[Params any, PParams hasRMCtrlFDPtr[Params]](ui *uvmIoctlState) (uintptr, error) {
var ioctlParams Params
if _, err := (PParams)(&ioctlParams).CopyIn(ui.t, ui.ioctlParamsAddr); err != nil {
return 0, err
}
rmCtrlFD := (PParams)(&ioctlParams).GetRMCtrlFD()
if rmCtrlFD < 0 {
n, err := uvmIoctlInvoke(ui, &ioctlParams)
if err != nil {
return n, err
}
if _, err := (PParams)(&ioctlParams).CopyOut(ui.t, ui.ioctlParamsAddr); err != nil {
return n, err
}
return n, nil
}
ctlFileGeneric, _ := ui.t.FDTable().Get(rmCtrlFD)
if ctlFileGeneric == nil {
return 0, linuxerr.EINVAL
}
defer ctlFileGeneric.DecRef(ui.ctx)
ctlFile, ok := ctlFileGeneric.Impl().(*frontendFD)
if !ok {
return 0, linuxerr.EINVAL
}
sentryIoctlParams := ioctlParams
(PParams)(&sentryIoctlParams).SetRMCtrlFD(ctlFile.hostFD)
n, err := uvmIoctlInvoke(ui, &sentryIoctlParams)
if err != nil {
return n, err
}
outIoctlParams := sentryIoctlParams
(PParams)(&outIoctlParams).SetRMCtrlFD(rmCtrlFD)
if _, err := (PParams)(&outIoctlParams).CopyOut(ui.t, ui.ioctlParamsAddr); err != nil {
return n, err
}
return n, nil
}
+87
View File
@@ -0,0 +1,87 @@
// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package nvproxy
import (
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/errors/linuxerr"
"gvisor.dev/gvisor/pkg/hostarch"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/safemem"
"gvisor.dev/gvisor/pkg/sentry/memmap"
"gvisor.dev/gvisor/pkg/sentry/vfs"
)
// ConfigureMMap implements vfs.FileDescriptionImpl.ConfigureMMap.
func (fd *uvmFD) ConfigureMMap(ctx context.Context, opts *memmap.MMapOpts) error {
return vfs.GenericConfigureMMap(&fd.vfsfd, fd, opts)
}
// AddMapping implements memmap.Mappable.AddMapping.
func (fd *uvmFD) AddMapping(ctx context.Context, ms memmap.MappingSpace, ar hostarch.AddrRange, offset uint64, writable bool) error {
return nil
}
// RemoveMapping implements memmap.Mappable.RemoveMapping.
func (fd *uvmFD) RemoveMapping(ctx context.Context, ms memmap.MappingSpace, ar hostarch.AddrRange, offset uint64, writable bool) {
}
// CopyMapping implements memmap.Mappable.CopyMapping.
func (fd *uvmFD) CopyMapping(ctx context.Context, ms memmap.MappingSpace, srcAR, dstAR hostarch.AddrRange, offset uint64, writable bool) error {
return nil
}
// Translate implements memmap.Mappable.Translate.
func (fd *uvmFD) Translate(ctx context.Context, required, optional memmap.MappableRange, at hostarch.AccessType) ([]memmap.Translation, error) {
return []memmap.Translation{
{
Source: optional,
File: &fd.memmapFile,
Offset: optional.Start,
// kernel-open/nvidia-uvm/uvm.c:uvm_mmap() requires mappings to be
// PROT_READ|PROT_WRITE.
Perms: hostarch.ReadWrite,
},
}, nil
}
// InvalidateUnsavable implements memmap.Mappable.InvalidateUnsavable.
func (fd *uvmFD) InvalidateUnsavable(ctx context.Context) error {
return nil
}
type uvmFDMemmapFile struct {
fd *uvmFD
}
// IncRef implements memmap.File.IncRef.
func (mf *uvmFDMemmapFile) IncRef(fr memmap.FileRange) {
}
// DecRef implements memmap.File.DecRef.
func (mf *uvmFDMemmapFile) DecRef(fr memmap.FileRange) {
}
// MapInternal implements memmap.File.MapInternal.
func (mf *uvmFDMemmapFile) MapInternal(fr memmap.FileRange, at hostarch.AccessType) (safemem.BlockSeq, error) {
// TODO(jamieliu): make an attempt with MAP_FIXED_NOREPLACE?
log.Traceback("nvproxy: rejecting uvmFDMemmapFile.MapInternal")
return safemem.BlockSeq{}, linuxerr.EINVAL
}
// FD implements memmap.File.FD.
func (mf *uvmFDMemmapFile) FD() int {
return int(mf.fd.hostFD)
}
+29
View File
@@ -0,0 +1,29 @@
// Copyright 2023 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package nvproxy
import (
"unsafe"
"golang.org/x/sys/unix"
)
func uvmIoctlInvoke[Params any](ui *uvmIoctlState, ioctlParams *Params) (uintptr, error) {
n, _, errno := unix.RawSyscall(unix.SYS_IOCTL, uintptr(ui.fd.hostFD), uintptr(ui.cmd), uintptr(unsafe.Pointer(ioctlParams)))
if errno != 0 {
return n, errno
}
return n, nil
}