Files
Ayush RanjanandgVisor bot ac9dac82f8 nvproxy: Clean up struct field tags.
Before this change, there were 2 places in which the driver struct names were
defined for nvproxy structs:
1. As struct field tags. The first field of structs had a tag `nvproxy:*`. This
   was kind of awkward. Such metadata is usually a struct comment.
2. In version.go while registering the struct with a name. Not all structs are
   defined in nvproxy (for example simple structs). In such cases, the driver
   struct name is directly assigned while registering struct info.

This change gets rid of (1). Most of the struct tags were `nvproxy:"same"`. Now
driverStructs() always infers the driver struct name using the nvproxy struct
name itself. The few cases where the nvproxy tag was needed, because driver
struct name was lower cased, were handled by defining driverStructWithName()
which allows specifying a different name. Now all driver struct names
definitions are in one place.

Along the way, also made the following fixes:
- For some reason, many structs defined in pkg/abi/nvgpu/frontend.go had
  camel-cased naming, while all other structs in pkg/abi/nvgpu/ctrl.go and
  pkg/abi/nvgpu/classes.go were named the same as their driver structs. The
  convention in the abi/* packages is to follow the kernel source naming.
  This is against Go sytle guide, but is more readable for gVisor purposes and
  has been a long accepted convention. This also makes the task of removing (1)
  easier. So renamed all such structs as per their driver names.
- A lot of code in pkg/sentry/devices/nvproxy/version.go was still referring to
  driver struct info as "struct names", even though it was representing more
  than just struct names. It also contains the reflect.Type of the struct which
  is used to compare the nvproxy struct layout to the driver struct layout.

PiperOrigin-RevId: 710648105
2024-12-30 01:32:41 -08:00

157 lines
5.5 KiB
Go

// Copyright 2024 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/abi/nvgpu"
"gvisor.dev/gvisor/pkg/sentry/devices/nvproxy/nvconf"
)
// errHandler is an error returned by an ioctl handler function.
type errHandler struct {
Err string
}
// Error implements the error interface.
func (e *errHandler) Error() string {
return e.Err
}
// ioctl handler errors.
var (
errUndefinedHandler = errHandler{"handler is undefined"}
errMissingCapability = errHandler{"missing capability"}
)
type frontendIoctlHandler struct {
// handler is the function to call if a capability in capSet is enabled.
handler func(*frontendIoctlState) (uintptr, error)
// capSet is a bitmask of capabilities that this handler is available for.
capSet nvconf.DriverCaps
}
// feHandler returns a frontendIoctlHandler that wraps the given function.
// The handler will be called if any of the given capabilities are enabled.
func feHandler(handler func(*frontendIoctlState) (uintptr, error), caps nvconf.DriverCaps) frontendIoctlHandler {
return frontendIoctlHandler{
handler: handler,
capSet: caps,
}
}
// handle calls the handler if the capability is enabled.
// Returns errMissingCapability if the caller is missing the required
// capabilities for this handler.
// Returns errUndefinedHandler if the handler does not exist.
func (h frontendIoctlHandler) handle(fi *frontendIoctlState) (uintptr, error) {
if h.handler == nil {
return 0, &errUndefinedHandler
}
if h.capSet&fi.fd.dev.nvp.capsEnabled == 0 {
return 0, &errMissingCapability
}
return h.handler(fi)
}
type controlCmdHandler struct {
// handler is the function to call if a capability in capSet is enabled.
handler func(*frontendIoctlState, *nvgpu.NVOS54_PARAMETERS) (uintptr, error)
// capSet is a bitmask of capabilities that this handler is available for.
capSet nvconf.DriverCaps
}
// ctrlHandler returns a controlCmdHandler that wraps the given function.
// The handler will be called if any of the given capabilities are enabled.
func ctrlHandler(handler func(*frontendIoctlState, *nvgpu.NVOS54_PARAMETERS) (uintptr, error), caps nvconf.DriverCaps) controlCmdHandler {
return controlCmdHandler{
handler: handler,
capSet: caps,
}
}
// handle calls the handler if the capability is enabled.
// Returns errMissingCapability if the caller is missing the required
// capabilities for this handler.
// Returns errUndefinedHandler if the handler does not exist.
func (h controlCmdHandler) handle(fi *frontendIoctlState, params *nvgpu.NVOS54_PARAMETERS) (uintptr, error) {
if h.handler == nil {
return 0, &errUndefinedHandler
}
if h.capSet&fi.fd.dev.nvp.capsEnabled == 0 {
return 0, &errMissingCapability
}
return h.handler(fi, params)
}
type allocationClassHandler struct {
// handler is the function to call if a capability in capSet is enabled.
handler func(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS64_PARAMETERS, isNVOS64 bool) (uintptr, error)
// capSet is a bitmask of capabilities that this handler is available for.
capSet nvconf.DriverCaps
}
// allocHandler returns a allocationClassHandler that wraps the given function.
// The handler will be called if any of the given capabilities are enabled.
func allocHandler(handler func(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS64_PARAMETERS, isNVOS64 bool) (uintptr, error), caps nvconf.DriverCaps) allocationClassHandler {
return allocationClassHandler{
handler: handler,
capSet: caps,
}
}
// handle calls the handler if the capability is enabled.
// Returns errMissingCapability if the caller is missing the required
// capabilities for this handler.
// Returns errUndefinedHandler if the handler does not exist.
func (h allocationClassHandler) handle(fi *frontendIoctlState, ioctlParams *nvgpu.NVOS64_PARAMETERS, isNVOS64 bool) (uintptr, error) {
if h.handler == nil {
return 0, &errUndefinedHandler
}
if h.capSet&fi.fd.dev.nvp.capsEnabled == 0 {
return 0, &errMissingCapability
}
return h.handler(fi, ioctlParams, isNVOS64)
}
type uvmIoctlHandler struct {
// handler is the function to call if a capability in capSet is enabled.
handler func(*uvmIoctlState) (uintptr, error)
// capSet is a bitmask of capabilities that this handler is available for.
capSet nvconf.DriverCaps
}
// uvmHandler returns a uvmIoctlHandler that wraps the given function.
// The handler will be called if any of the given capabilities are enabled.
func uvmHandler(handler func(*uvmIoctlState) (uintptr, error), caps nvconf.DriverCaps) uvmIoctlHandler {
return uvmIoctlHandler{
handler: handler,
capSet: caps,
}
}
// handle calls the handler if the capability is enabled.
// Returns errMissingCapability if the caller is missing the required
// capabilities for this handler.
// Returns errUndefinedHandler if the handler does not exist.
func (h uvmIoctlHandler) handle(ui *uvmIoctlState) (uintptr, error) {
if h.handler == nil {
return 0, &errUndefinedHandler
}
if h.capSet&ui.fd.dev.nvp.capsEnabled == 0 {
return 0, &errMissingCapability
}
return h.handler(ui)
}