mirror of
https://github.com/mbilker/vgpu_unlock-rs.git
synced 2026-01-17 11:57:00 +01:00
nvidia: refactor everything out of the main class and use official naming and structs where possible
This commit is contained in:
@@ -19,6 +19,6 @@ pub const fn _IOC(a: c_ulong, b: c_ulong, c: c_ulong, d: c_ulong) -> c_ulong {
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[inline]
|
||||
pub const fn _IOCWR<T>(b: c_ulong, c: c_ulong) -> c_ulong {
|
||||
pub const fn _IOWR<T>(b: c_ulong, c: c_ulong) -> c_ulong {
|
||||
_IOC(_IOC_READ | _IOC_WRITE, b, c, mem::size_of::<T>() as c_ulong)
|
||||
}
|
||||
|
||||
495
src/lib.rs
495
src/lib.rs
@@ -12,7 +12,6 @@ use std::borrow::Cow;
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::fmt;
|
||||
use std::fs;
|
||||
use std::io::{ErrorKind, Write};
|
||||
use std::mem;
|
||||
@@ -33,11 +32,37 @@ mod format;
|
||||
mod human_number;
|
||||
mod ioctl;
|
||||
mod log;
|
||||
mod nvidia;
|
||||
mod utils;
|
||||
mod uuid;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::format::{CStrFormat, HexFormat, HexFormatSlice, StraightFormat, WideCharFormat};
|
||||
use crate::ioctl::_IOCWR;
|
||||
use crate::format::WideCharFormat;
|
||||
use crate::log::{error, info};
|
||||
use crate::nvidia::ctrl0000vgpu::{
|
||||
Nv0000CtrlVgpuGetStartDataParams, NV0000_CTRL_CMD_VGPU_GET_START_DATA,
|
||||
};
|
||||
use crate::nvidia::ctrl0080gpu::{
|
||||
Nv0080CtrlGpuGetVirtualizationModeParams, NV0080_CTRL_CMD_GPU_GET_VIRTUALIZATION_MODE,
|
||||
NV0080_CTRL_GPU_VIRTUALIZATION_MODE_HOST,
|
||||
};
|
||||
use crate::nvidia::ctrl2080bus::{Nv2080CtrlBusGetPciInfoParams, NV2080_CTRL_CMD_BUS_GET_PCI_INFO};
|
||||
use crate::nvidia::ctrl2080gpu::NV2080_CTRL_CMD_GPU_GET_INFOROM_OBJECT_VERSION;
|
||||
use crate::nvidia::ctrl9096::NV9096_CTRL_CMD_GET_ZBC_CLEAR_TABLE;
|
||||
use crate::nvidia::ctrla081::{
|
||||
NvA081CtrlCmdVgpuConfigGetMigrationCapParams, NvA081CtrlVgpuConfigGetVgpuTypeInfoParams,
|
||||
NvA081CtrlVgpuInfo, NVA081_CTRL_CMD_VGPU_CONFIG_GET_MIGRATION_CAP,
|
||||
NVA081_CTRL_CMD_VGPU_CONFIG_GET_VGPU_TYPE_INFO,
|
||||
};
|
||||
use crate::nvidia::ctrla082::{
|
||||
NvA082CtrlCmdHostVgpuDeviceGetVgpuTypeInfoParams,
|
||||
NVA082_CTRL_CMD_HOST_VGPU_DEVICE_GET_VGPU_TYPE_INFO,
|
||||
};
|
||||
use crate::nvidia::error::{
|
||||
NV_ERR_BUSY_RETRY, NV_ERR_NOT_SUPPORTED, NV_ERR_OBJECT_NOT_FOUND, NV_OK,
|
||||
};
|
||||
use crate::nvidia::nvos::{Nvos54Parameters, NV_ESC_RM_CONTROL};
|
||||
use crate::uuid::Uuid;
|
||||
|
||||
static LAST_MDEV_UUID: Mutex<Option<Uuid>> = parking_lot::const_mutex(None);
|
||||
|
||||
@@ -65,187 +90,6 @@ static CONFIG: Config = {
|
||||
const DEFAULT_CONFIG_PATH: &str = "/etc/vgpu_unlock/config.toml";
|
||||
const DEFAULT_PROFILE_OVERRIDE_CONFIG_PATH: &str = "/etc/vgpu_unlock/profile_override.toml";
|
||||
|
||||
/// Pulled from https://github.com/NVIDIA/open-gpu-kernel-modules/blob/d8f3bcff924776518f1e63286537c3cf365289ac/kernel-open/common/inc/nv-ioctl-numbers.h
|
||||
const NV_IOCTL_MAGIC: c_ulong = b'F' as _;
|
||||
|
||||
/// Value of the "request" argument used by `nvidia-vgpud` and `nvidia-vgpu-mgr` when calling
|
||||
/// ioctl to read the PCI device ID, type, and many other things from the driver.
|
||||
///
|
||||
/// Pulled from https://github.com/NVIDIA/open-gpu-kernel-modules/blob/d8f3bcff924776518f1e63286537c3cf365289ac/src/nvidia/arch/nvalloc/unix/include/nv_escape.h
|
||||
/// and [`nvidia_ioctl`](https://github.com/NVIDIA/open-gpu-kernel-modules/blob/98553501593ef05bddcc438689ed1136f732d40a/kernel-open/nvidia/nv.c)
|
||||
/// and [`__NV_IOWR`](https://github.com/NVIDIA/open-gpu-kernel-modules/blob/98553501593ef05bddcc438689ed1136f732d40a/kernel-open/common/inc/nv.h)
|
||||
/// showing that `_IOCWR` is used to derive the I/O control request codes.
|
||||
const NV_ESC_RM_CONTROL: c_ulong = _IOCWR::<Nvos54Parameters>(NV_IOCTL_MAGIC, 0x2a);
|
||||
|
||||
/// `result` is a pointer to `VgpuStart`.
|
||||
const OP_READ_START_CALL: u32 = 0xc01;
|
||||
|
||||
/// `result` is a pointer to `uint32_t`.
|
||||
const NV0080_CTRL_CMD_GPU_GET_VIRTUALIZATION_MODE: u32 = 0x800289;
|
||||
|
||||
/// `result` is a pointer to `uint32_t[4]`, the second element (index 1) is the device ID, the
|
||||
/// forth element (index 3) is the subsystem ID.
|
||||
///
|
||||
/// Pulled from https://github.com/NVIDIA/open-gpu-kernel-modules/blob/d8f3bcff924776518f1e63286537c3cf365289ac/src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080bus.h
|
||||
const NV2080_CTRL_CMD_BUS_GET_PCI_INFO: u32 = 0x20801801;
|
||||
|
||||
/// `result` is a pointer to `VgpuConfig`.
|
||||
const OP_READ_VGPU_CFG: u32 = 0xa0820102;
|
||||
|
||||
/// `result` is a pointer to `VgpuConfig`.
|
||||
///
|
||||
/// This RM control command is used starting in vGPU version 15.0 (525.60.12).
|
||||
const OP_READ_VGPU_CFG2: u32 = 0xA0810103;
|
||||
|
||||
/// `result` is a pointer to `bool`.
|
||||
const OP_READ_VGPU_MIGRATION_CAP: u32 = 0xa0810112;
|
||||
|
||||
/// `nvidia-vgpu-mgr` expects this value for a vGPU capable GPU.
|
||||
///
|
||||
/// Pulled from https://github.com/NVIDIA/open-gpu-kernel-modules/blob/d8f3bcff924776518f1e63286537c3cf365289ac/src/common/sdk/nvidia/inc/ctrl/ctrl0080/ctrl0080gpu.h
|
||||
const NV0080_CTRL_GPU_VIRTUALIZATION_MODE_HOST: u32 = 3;
|
||||
|
||||
/// When ioctl returns success (retval >= 0) but sets the status value of the arg structure to 3
|
||||
/// then `nvidia-vgpud` will sleep for a bit (first 0.1s then 1s then 10s) then issue the same
|
||||
/// ioctl call again until the status differs from 3. It will attempt this for up to 24h before
|
||||
/// giving up.
|
||||
///
|
||||
/// See https://github.com/NVIDIA/open-gpu-kernel-modules/blob/d8f3bcff924776518f1e63286537c3cf365289ac/kernel-open/common/inc/nvstatuscodes.h
|
||||
const NV_OK: u32 = 0x0;
|
||||
const NV_ERR_BUSY_RETRY: u32 = 0x3;
|
||||
const NV_ERR_NOT_SUPPORTED: u32 = 0x56;
|
||||
const NV_ERR_OBJECT_NOT_FOUND: u32 = 0x57;
|
||||
|
||||
/// When issuing ioctl with `NV_ESC_RM_CONTROL` then the `argp` argument is a pointer to a
|
||||
/// `NVOS54_PARAMETERS` structure like this.
|
||||
///
|
||||
/// See [`NVOS54_PARAMETERS`](https://github.com/NVIDIA/open-gpu-kernel-modules/blob/d8f3bcff924776518f1e63286537c3cf365289ac/src/common/sdk/nvidia/inc/nvos.h)
|
||||
//#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
struct Nvos54Parameters {
|
||||
/// Initialized prior to call.
|
||||
h_client: u32,
|
||||
/// Initialized prior to call.
|
||||
h_object: u32,
|
||||
/// Operation type, see comment below.
|
||||
cmd: u32,
|
||||
/// Pointer initialized prior to call.
|
||||
/// Pointee initialized to 0 prior to call.
|
||||
/// Pointee is written by ioctl call.
|
||||
params: *mut c_void,
|
||||
/// Size in bytes of the object referenced in `params`.
|
||||
params_size: u32,
|
||||
/// Written by ioctl call. See comment below.
|
||||
status: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
struct Uuid(u32, u16, u16, [u8; 8]);
|
||||
|
||||
impl fmt::Display for Uuid {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{:08x}-{:04x}-{:04x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
|
||||
self.0,
|
||||
self.1,
|
||||
self.2,
|
||||
self.3[0],
|
||||
self.3[1],
|
||||
self.3[2],
|
||||
self.3[3],
|
||||
self.3[4],
|
||||
self.3[5],
|
||||
self.3[6],
|
||||
self.3[7]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct VgpuStart {
|
||||
uuid: Uuid,
|
||||
config_params: [u8; 1024],
|
||||
qemu_pid: u32,
|
||||
unknown_414: [u8; 12],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct VgpuConfig {
|
||||
vgpu_type: u32,
|
||||
vgpu_name: [u8; 32],
|
||||
vgpu_class: [u8; 32],
|
||||
vgpu_signature: [u8; 128],
|
||||
features: [u8; 128],
|
||||
max_instances: u32,
|
||||
num_heads: u32,
|
||||
max_resolution_x: u32,
|
||||
max_resolution_y: u32,
|
||||
max_pixels: u32,
|
||||
frl_config: u32,
|
||||
cuda_enabled: u32,
|
||||
ecc_supported: u32,
|
||||
mig_instance_size: u32,
|
||||
multi_vgpu_supported: u32,
|
||||
vdev_id: u64,
|
||||
pdev_id: u64,
|
||||
fb_length: u64,
|
||||
mappable_video_size: u64,
|
||||
fb_reservation: u64,
|
||||
encoder_capacity: u32,
|
||||
bar1_length: u64,
|
||||
frl_enable: u32,
|
||||
adapter_name: [u8; 64],
|
||||
adapter_name_unicode: [u16; 64],
|
||||
short_gpu_name_string: [u8; 64],
|
||||
licensed_product_name: [u8; 128],
|
||||
vgpu_extra_params: [u8; 1024],
|
||||
unknown_end: [u8; 8],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct VgpuConfig2 {
|
||||
vgpu_type: u32,
|
||||
vgpu_name: [u8; 32],
|
||||
vgpu_class: [u8; 32],
|
||||
vgpu_signature: [u8; 128],
|
||||
features: [u8; 128],
|
||||
max_instances: u32,
|
||||
num_heads: u32,
|
||||
max_resolution_x: u32,
|
||||
max_resolution_y: u32,
|
||||
max_pixels: u32,
|
||||
frl_config: u32,
|
||||
cuda_enabled: u32,
|
||||
ecc_supported: u32,
|
||||
mig_instance_size: u32,
|
||||
multi_vgpu_supported: u32,
|
||||
vdev_id: u64,
|
||||
pdev_id: u64,
|
||||
profile_size: u64,
|
||||
fb_length: u64,
|
||||
unknown: u64,
|
||||
fb_reservation: u64,
|
||||
mappable_video_size: u64,
|
||||
encoder_capacity: u32,
|
||||
bar1_length: u64,
|
||||
frl_enable: u32,
|
||||
adapter_name: [u8; 64],
|
||||
adapter_name_unicode: [u16; 64],
|
||||
short_gpu_name_string: [u8; 64],
|
||||
licensed_product_name: [u8; 128],
|
||||
vgpu_extra_params: [u8; 1024],
|
||||
unknown_end: [u8; 0xc1c],
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
struct LoadVgpuConfig2 {
|
||||
vgpu_type: u32,
|
||||
config: VgpuConfig2,
|
||||
}
|
||||
|
||||
trait VgpuConfigLike {
|
||||
fn vgpu_type(&mut self) -> &mut u32;
|
||||
fn vgpu_name(&mut self) -> &mut [u8; 32];
|
||||
@@ -279,14 +123,26 @@ trait VgpuConfigLike {
|
||||
}
|
||||
|
||||
macro_rules! impl_trait_fn {
|
||||
($name:ident, $t:ty) => {
|
||||
fn $name(&mut self) -> &mut $t {
|
||||
&mut self.$name
|
||||
($field:ident, $t:ty) => {
|
||||
fn $field(&mut self) -> &mut $t {
|
||||
&mut self.$field
|
||||
}
|
||||
};
|
||||
($source_field:ident => $target_field:ident, $t:ty) => {
|
||||
fn $target_field(&mut self) -> &mut $t {
|
||||
&mut self.$source_field
|
||||
}
|
||||
};
|
||||
}
|
||||
macro_rules! impl_trait_fn_aligned {
|
||||
($field:ident, $t:ty) => {
|
||||
fn $field(&mut self) -> &mut $t {
|
||||
&mut self.$field.0
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl VgpuConfigLike for VgpuConfig {
|
||||
impl VgpuConfigLike for NvA082CtrlCmdHostVgpuDeviceGetVgpuTypeInfoParams {
|
||||
impl_trait_fn!(vgpu_type, u32);
|
||||
impl_trait_fn!(vgpu_name, [u8; 32]);
|
||||
impl_trait_fn!(vgpu_class, [u8; 32]);
|
||||
@@ -322,13 +178,13 @@ impl VgpuConfigLike for VgpuConfig {
|
||||
impl_trait_fn!(vgpu_extra_params, [u8; 1024]);
|
||||
}
|
||||
|
||||
impl VgpuConfigLike for VgpuConfig2 {
|
||||
impl VgpuConfigLike for NvA081CtrlVgpuInfo {
|
||||
impl_trait_fn!(vgpu_type, u32);
|
||||
impl_trait_fn!(vgpu_name, [u8; 32]);
|
||||
impl_trait_fn!(vgpu_class, [u8; 32]);
|
||||
impl_trait_fn!(vgpu_signature, [u8; 128]);
|
||||
impl_trait_fn!(features, [u8; 128]);
|
||||
impl_trait_fn!(max_instances, u32);
|
||||
impl_trait_fn!(license => features, [u8; 128]);
|
||||
impl_trait_fn!(max_instance => max_instances, u32);
|
||||
impl_trait_fn!(num_heads, u32);
|
||||
impl_trait_fn!(max_resolution_x, u32);
|
||||
impl_trait_fn!(max_resolution_y, u32);
|
||||
@@ -336,20 +192,20 @@ impl VgpuConfigLike for VgpuConfig2 {
|
||||
impl_trait_fn!(frl_config, u32);
|
||||
impl_trait_fn!(cuda_enabled, u32);
|
||||
impl_trait_fn!(ecc_supported, u32);
|
||||
impl_trait_fn!(mig_instance_size, u32);
|
||||
impl_trait_fn!(gpu_instance_size => mig_instance_size, u32);
|
||||
impl_trait_fn!(multi_vgpu_supported, u32);
|
||||
impl_trait_fn!(vdev_id, u64);
|
||||
impl_trait_fn!(pdev_id, u64);
|
||||
impl_trait_fn_aligned!(vdev_id, u64);
|
||||
impl_trait_fn_aligned!(pdev_id, u64);
|
||||
|
||||
fn profile_size(&mut self) -> Option<&mut u64> {
|
||||
Some(&mut self.profile_size)
|
||||
Some(&mut self.profile_size.0)
|
||||
}
|
||||
|
||||
impl_trait_fn!(fb_length, u64);
|
||||
impl_trait_fn!(mappable_video_size, u64);
|
||||
impl_trait_fn!(fb_reservation, u64);
|
||||
impl_trait_fn_aligned!(fb_length, u64);
|
||||
impl_trait_fn_aligned!(mappable_video_size, u64);
|
||||
impl_trait_fn_aligned!(fb_reservation, u64);
|
||||
impl_trait_fn!(encoder_capacity, u32);
|
||||
impl_trait_fn!(bar1_length, u64);
|
||||
impl_trait_fn_aligned!(bar1_length, u64);
|
||||
impl_trait_fn!(frl_enable, u32);
|
||||
impl_trait_fn!(adapter_name, [u8; 64]);
|
||||
impl_trait_fn!(adapter_name_unicode, [u16; 64]);
|
||||
@@ -398,125 +254,6 @@ struct VgpuProfileOverride<'a> {
|
||||
license_type: Option<&'a str>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for VgpuStart {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("VgpuStart")
|
||||
.field("uuid", &format_args!("{{{}}}", self.uuid))
|
||||
.field("config_params", &CStrFormat(&self.config_params))
|
||||
.field("qemu_pid", &self.qemu_pid)
|
||||
.field("unknown_414", &StraightFormat(&self.unknown_414))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for VgpuConfig {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let vgpu_signature = self.vgpu_signature[..]
|
||||
.split(|&x| x == 0)
|
||||
.next()
|
||||
.unwrap_or(&[]);
|
||||
let vgpu_extra_params = self.vgpu_extra_params[..]
|
||||
.split(|&x| x == 0)
|
||||
.next()
|
||||
.unwrap_or(&[]);
|
||||
|
||||
f.debug_struct("VgpuConfig")
|
||||
.field("vgpu_type", &self.vgpu_type)
|
||||
.field("vgpu_name", &CStrFormat(&self.vgpu_name))
|
||||
.field("vgpu_class", &CStrFormat(&self.vgpu_class))
|
||||
.field("vgpu_signature", &HexFormatSlice(vgpu_signature))
|
||||
.field("features", &CStrFormat(&self.features))
|
||||
.field("max_instances", &self.max_instances)
|
||||
.field("num_heads", &self.num_heads)
|
||||
.field("max_resolution_x", &self.max_resolution_x)
|
||||
.field("max_resolution_y", &self.max_resolution_y)
|
||||
.field("max_pixels", &self.max_pixels)
|
||||
.field("frl_config", &self.frl_config)
|
||||
.field("cuda_enabled", &self.cuda_enabled)
|
||||
.field("ecc_supported", &self.ecc_supported)
|
||||
.field("mig_instance_size", &self.mig_instance_size)
|
||||
.field("multi_vgpu_supported", &self.multi_vgpu_supported)
|
||||
.field("vdev_id", &HexFormat(self.vdev_id))
|
||||
.field("pdev_id", &HexFormat(self.pdev_id))
|
||||
.field("fb_length", &HexFormat(self.fb_length))
|
||||
.field("mappable_video_size", &HexFormat(self.mappable_video_size))
|
||||
.field("fb_reservation", &HexFormat(self.fb_reservation))
|
||||
.field("encoder_capacity", &HexFormat(self.encoder_capacity))
|
||||
.field("bar1_length", &HexFormat(self.bar1_length))
|
||||
.field("frl_enable", &self.frl_enable)
|
||||
.field("adapter_name", &CStrFormat(&self.adapter_name))
|
||||
.field(
|
||||
"adapter_name_unicode",
|
||||
&WideCharFormat(&self.adapter_name_unicode),
|
||||
)
|
||||
.field(
|
||||
"short_gpu_name_string",
|
||||
&CStrFormat(&self.short_gpu_name_string),
|
||||
)
|
||||
.field(
|
||||
"licensed_product_name",
|
||||
&CStrFormat(&self.licensed_product_name),
|
||||
)
|
||||
.field("vgpu_extra_params", &HexFormatSlice(vgpu_extra_params))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for VgpuConfig2 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let vgpu_signature = self.vgpu_signature[..]
|
||||
.split(|&x| x == 0)
|
||||
.next()
|
||||
.unwrap_or(&[]);
|
||||
let vgpu_extra_params = self.vgpu_extra_params[..]
|
||||
.split(|&x| x == 0)
|
||||
.next()
|
||||
.unwrap_or(&[]);
|
||||
|
||||
f.debug_struct("VgpuConfig2")
|
||||
.field("vgpu_type", &self.vgpu_type)
|
||||
.field("vgpu_name", &CStrFormat(&self.vgpu_name))
|
||||
.field("vgpu_class", &CStrFormat(&self.vgpu_class))
|
||||
.field("vgpu_signature", &HexFormatSlice(vgpu_signature))
|
||||
.field("features", &CStrFormat(&self.features))
|
||||
.field("max_instances", &self.max_instances)
|
||||
.field("num_heads", &self.num_heads)
|
||||
.field("max_resolution_x", &self.max_resolution_x)
|
||||
.field("max_resolution_y", &self.max_resolution_y)
|
||||
.field("max_pixels", &self.max_pixels)
|
||||
.field("frl_config", &self.frl_config)
|
||||
.field("cuda_enabled", &self.cuda_enabled)
|
||||
.field("ecc_supported", &self.ecc_supported)
|
||||
.field("mig_instance_size", &self.mig_instance_size)
|
||||
.field("multi_vgpu_supported", &self.multi_vgpu_supported)
|
||||
.field("vdev_id", &HexFormat(self.vdev_id))
|
||||
.field("pdev_id", &HexFormat(self.pdev_id))
|
||||
.field("profile_size", &HexFormat(self.profile_size))
|
||||
.field("fb_length", &HexFormat(self.fb_length))
|
||||
.field("unknown", &HexFormat(self.unknown))
|
||||
.field("fb_reservation", &HexFormat(self.fb_reservation))
|
||||
.field("mappable_video_size", &HexFormat(self.mappable_video_size))
|
||||
.field("encoder_capacity", &HexFormat(self.encoder_capacity))
|
||||
.field("bar1_length", &HexFormat(self.bar1_length))
|
||||
.field("frl_enable", &self.frl_enable)
|
||||
.field("adapter_name", &CStrFormat(&self.adapter_name))
|
||||
.field(
|
||||
"adapter_name_unicode",
|
||||
&WideCharFormat(&self.adapter_name_unicode),
|
||||
)
|
||||
.field(
|
||||
"short_gpu_name_string",
|
||||
&CStrFormat(&self.short_gpu_name_string),
|
||||
)
|
||||
.field(
|
||||
"licensed_product_name",
|
||||
&CStrFormat(&self.licensed_product_name),
|
||||
)
|
||||
.field("vgpu_extra_params", &CStrFormat(vgpu_extra_params))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
fn check_size(name: &str, actual_size: usize, expected_size: usize) -> bool {
|
||||
if actual_size != expected_size {
|
||||
error!(
|
||||
@@ -565,7 +302,7 @@ pub unsafe extern "C" fn ioctl(fd: RawFd, request: c_ulong, argp: *mut c_void) -
|
||||
|
||||
// Safety: NVIDIA's driver itself uses `sizeof` when calculating the ioctl number and so does
|
||||
// this hook so the structure passed in should be of the correct size.
|
||||
let io_data = &mut *(argp as *mut Nvos54Parameters);
|
||||
let io_data: &mut Nvos54Parameters = &mut *argp.cast();
|
||||
|
||||
if io_data.status == NV_ERR_BUSY_RETRY {
|
||||
// Driver will try again.
|
||||
@@ -593,19 +330,20 @@ pub unsafe extern "C" fn ioctl(fd: RawFd, request: c_ulong, argp: *mut c_void) -
|
||||
|
||||
match io_data.cmd {
|
||||
NV2080_CTRL_CMD_BUS_GET_PCI_INFO
|
||||
if check_size!(NV2080_CTRL_CMD_BUS_GET_PCI_INFO, size: 16) && CONFIG.unlock =>
|
||||
if check_size!(
|
||||
NV2080_CTRL_CMD_BUS_GET_PCI_INFO,
|
||||
Nv2080CtrlBusGetPciInfoParams
|
||||
) && CONFIG.unlock =>
|
||||
{
|
||||
// Lookup address of the device and subsystem IDs.
|
||||
let devid_ptr: *mut u32 = io_data.params.add(0).cast();
|
||||
let subsysid_ptr: *mut u32 = io_data.params.add(4).cast();
|
||||
let params: &mut Nv2080CtrlBusGetPciInfoParams = &mut *io_data.params.cast();
|
||||
|
||||
let orig_devid = *devid_ptr;
|
||||
let orig_subsysid = *subsysid_ptr;
|
||||
let orig_device_id = params.pci_device_id;
|
||||
let orig_sub_system_id = params.pci_sub_system_id;
|
||||
|
||||
let actual_devid = (orig_devid & 0xffff0000) >> 16;
|
||||
let actual_subsysid = (orig_subsysid & 0xffff0000) >> 16;
|
||||
let actual_device_id = (orig_device_id & 0xffff0000) >> 16;
|
||||
let actual_sub_system_id = (orig_sub_system_id & 0xffff0000) >> 16;
|
||||
|
||||
let (spoofed_devid, spoofed_subsysid) = match actual_devid {
|
||||
let (spoofed_devid, spoofed_subsysid) = match actual_device_id {
|
||||
// Maxwell
|
||||
0x1340..=0x13bd | 0x174d..=0x179c => {
|
||||
// Tesla M10
|
||||
@@ -614,12 +352,12 @@ pub unsafe extern "C" fn ioctl(fd: RawFd, request: c_ulong, argp: *mut c_void) -
|
||||
// Maxwell 2.0
|
||||
0x13c0..=0x1436 | 0x1617..=0x1667 | 0x17c2..=0x17fd => {
|
||||
// Tesla M60
|
||||
(0x13f2, actual_subsysid)
|
||||
(0x13f2, actual_sub_system_id)
|
||||
}
|
||||
// Pascal
|
||||
0x15f0 | 0x15f1 | 0x1b00..=0x1d56 | 0x1725..=0x172f => {
|
||||
// Tesla P40
|
||||
(0x1b38, actual_subsysid)
|
||||
(0x1b38, actual_sub_system_id)
|
||||
}
|
||||
// GV100 Volta
|
||||
//
|
||||
@@ -627,7 +365,7 @@ pub unsafe extern "C" fn ioctl(fd: RawFd, request: c_ulong, argp: *mut c_void) -
|
||||
// 0x1dba = Quadro GV100 32GB
|
||||
0x1d81 | 0x1dba => {
|
||||
// Tesla V100 32GB PCIE
|
||||
(0x1db6, actual_subsysid)
|
||||
(0x1db6, actual_sub_system_id)
|
||||
}
|
||||
// Turing
|
||||
0x1e02..=0x1ff9 | 0x2182..=0x21d1 => {
|
||||
@@ -637,58 +375,82 @@ pub unsafe extern "C" fn ioctl(fd: RawFd, request: c_ulong, argp: *mut c_void) -
|
||||
// Ampere
|
||||
0x2200..=0x2600 => {
|
||||
// RTX A6000
|
||||
(0x2230, actual_subsysid)
|
||||
(0x2230, actual_sub_system_id)
|
||||
}
|
||||
_ => (actual_devid, actual_subsysid),
|
||||
_ => (actual_device_id, actual_sub_system_id),
|
||||
};
|
||||
|
||||
*devid_ptr = (orig_devid & 0xffff) | (spoofed_devid << 16);
|
||||
*subsysid_ptr = (orig_subsysid & 0xffff) | (spoofed_subsysid << 16);
|
||||
params.pci_device_id = (orig_device_id & 0xffff) | (spoofed_devid << 16);
|
||||
params.pci_sub_system_id = (orig_sub_system_id & 0xffff) | (spoofed_subsysid << 16);
|
||||
}
|
||||
NV0080_CTRL_CMD_GPU_GET_VIRTUALIZATION_MODE
|
||||
if check_size!(NV0080_CTRL_CMD_GPU_GET_VIRTUALIZATION_MODE, u32) && CONFIG.unlock =>
|
||||
if check_size!(
|
||||
NV0080_CTRL_CMD_GPU_GET_VIRTUALIZATION_MODE,
|
||||
Nv0080CtrlGpuGetVirtualizationModeParams
|
||||
) && CONFIG.unlock =>
|
||||
{
|
||||
let dev_type_ptr: *mut u32 = io_data.params.cast();
|
||||
let params: &mut Nv0080CtrlGpuGetVirtualizationModeParams = &mut *io_data.params.cast();
|
||||
|
||||
// Set device type to vGPU capable.
|
||||
*dev_type_ptr = NV0080_CTRL_GPU_VIRTUALIZATION_MODE_HOST;
|
||||
params.virtualization_mode = NV0080_CTRL_GPU_VIRTUALIZATION_MODE_HOST;
|
||||
}
|
||||
OP_READ_VGPU_MIGRATION_CAP
|
||||
if check_size!(OP_READ_VGPU_MIGRATION_CAP, u8) && CONFIG.unlock_migration =>
|
||||
NVA081_CTRL_CMD_VGPU_CONFIG_GET_MIGRATION_CAP
|
||||
if check_size!(
|
||||
NVA081_CTRL_CMD_VGPU_CONFIG_GET_MIGRATION_CAP,
|
||||
NvA081CtrlCmdVgpuConfigGetMigrationCapParams
|
||||
) && CONFIG.unlock_migration =>
|
||||
{
|
||||
let migration_enabled: *mut u8 = io_data.params.cast();
|
||||
let params: &mut NvA081CtrlCmdVgpuConfigGetMigrationCapParams =
|
||||
&mut *io_data.params.cast();
|
||||
|
||||
*migration_enabled = 1;
|
||||
params.migration_cap = 1;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if io_data.status == NV_OK {
|
||||
match io_data.cmd {
|
||||
OP_READ_VGPU_CFG if check_size!(OP_READ_VGPU_CFG, VgpuConfig) => {
|
||||
let config = &mut *(io_data.params as *mut VgpuConfig);
|
||||
NV0000_CTRL_CMD_VGPU_GET_START_DATA
|
||||
if check_size!(
|
||||
NV0000_CTRL_CMD_VGPU_GET_START_DATA,
|
||||
Nv0000CtrlVgpuGetStartDataParams
|
||||
) =>
|
||||
{
|
||||
let config: &Nv0000CtrlVgpuGetStartDataParams = &*io_data.params.cast();
|
||||
info!("{:#?}", config);
|
||||
|
||||
if !handle_profile_override(config) {
|
||||
*LAST_MDEV_UUID.lock() = Some(config.mdev_uuid);
|
||||
}
|
||||
NVA081_CTRL_CMD_VGPU_CONFIG_GET_VGPU_TYPE_INFO
|
||||
if check_size!(
|
||||
NVA081_CTRL_CMD_VGPU_CONFIG_GET_VGPU_TYPE_INFO,
|
||||
NvA081CtrlVgpuConfigGetVgpuTypeInfoParams
|
||||
) =>
|
||||
{
|
||||
let params: &mut NvA081CtrlVgpuConfigGetVgpuTypeInfoParams =
|
||||
&mut *io_data.params.cast();
|
||||
info!("{:#?}", params);
|
||||
|
||||
if !handle_profile_override(&mut params.vgpu_type_info) {
|
||||
error!("Failed to apply profile override");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
OP_READ_VGPU_CFG2 if check_size!(OP_READ_VGPU_CFG2, LoadVgpuConfig2) => {
|
||||
let config = &mut *io_data.params.cast::<LoadVgpuConfig2>();
|
||||
info!("{:#?}", config);
|
||||
NVA082_CTRL_CMD_HOST_VGPU_DEVICE_GET_VGPU_TYPE_INFO
|
||||
if check_size!(
|
||||
NVA082_CTRL_CMD_HOST_VGPU_DEVICE_GET_VGPU_TYPE_INFO,
|
||||
NvA082CtrlCmdHostVgpuDeviceGetVgpuTypeInfoParams
|
||||
) =>
|
||||
{
|
||||
let params: &mut NvA082CtrlCmdHostVgpuDeviceGetVgpuTypeInfoParams =
|
||||
&mut *io_data.params.cast();
|
||||
info!("{:#?}", params);
|
||||
|
||||
if !handle_profile_override(&mut config.config) {
|
||||
if !handle_profile_override(params) {
|
||||
error!("Failed to apply profile override");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
OP_READ_START_CALL if check_size!(OP_READ_START_CALL, VgpuStart) => {
|
||||
let config = &*(io_data.params as *const VgpuStart);
|
||||
info!("{:#?}", config);
|
||||
|
||||
*LAST_MDEV_UUID.lock() = Some(config.uuid);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -697,15 +459,17 @@ pub unsafe extern "C" fn ioctl(fd: RawFd, request: c_ulong, argp: *mut c_void) -
|
||||
// Things seems to work fine even if some operations that fail result in failed assertions.
|
||||
// So here we change the status value for these cases to cleanup the logs for
|
||||
// `nvidia-vgpu-mgr`.
|
||||
if io_data.cmd == 0xa0820104 || io_data.cmd == 0x90960103 {
|
||||
if io_data.cmd == 0xa0820104 || io_data.cmd == NV9096_CTRL_CMD_GET_ZBC_CLEAR_TABLE {
|
||||
io_data.status = NV_OK;
|
||||
} else {
|
||||
error!("cmd: 0x{:x} failed.", io_data.cmd);
|
||||
error!("cmd: {:#x} failed.", io_data.cmd);
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for some Maxwell cards not supporting reading inforom.
|
||||
if io_data.cmd == 0x2080014b && io_data.status == NV_ERR_NOT_SUPPORTED {
|
||||
if io_data.cmd == NV2080_CTRL_CMD_GPU_GET_INFOROM_OBJECT_VERSION
|
||||
&& io_data.status == NV_ERR_NOT_SUPPORTED
|
||||
{
|
||||
io_data.status = NV_ERR_OBJECT_NOT_FOUND;
|
||||
}
|
||||
|
||||
@@ -995,18 +759,3 @@ fn apply_profile_override<C: VgpuConfigLike>(
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::mem;
|
||||
|
||||
use super::{LoadVgpuConfig2, VgpuConfig, VgpuConfig2, VgpuStart};
|
||||
|
||||
#[test]
|
||||
fn verify_sizes() {
|
||||
assert_eq!(mem::size_of::<VgpuStart>(), 0x420);
|
||||
assert_eq!(mem::size_of::<VgpuConfig>(), 0x738);
|
||||
assert_eq!(mem::size_of::<VgpuConfig2>(), 0x1358);
|
||||
assert_eq!(mem::size_of::<LoadVgpuConfig2>(), 0x1360);
|
||||
}
|
||||
}
|
||||
|
||||
44
src/nvidia/ctrl0000vgpu.rs
Normal file
44
src/nvidia/ctrl0000vgpu.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
///! Sourced from https://github.com/NVIDIA/open-gpu-kernel-modules/blob/758b4ee8189c5198504cb1c3c5bc29027a9118a3/src/common/sdk/nvidia/inc/ctrl/ctrl0000/ctrl0000vgpu.h
|
||||
use std::fmt;
|
||||
|
||||
use crate::format::{CStrFormat, HexFormat};
|
||||
use crate::uuid::Uuid;
|
||||
|
||||
pub const NV0000_CTRL_CMD_VGPU_GET_START_DATA: u32 = 0xc01;
|
||||
|
||||
/// See `NV0000_CTRL_VGPU_GET_START_DATA_PARAMS`
|
||||
#[repr(C)]
|
||||
pub struct Nv0000CtrlVgpuGetStartDataParams {
|
||||
// [u8; VM_UUID_SIZE]
|
||||
pub mdev_uuid: Uuid,
|
||||
pub config_params: [u8; 1024],
|
||||
pub qemu_pid: u32,
|
||||
pub gpu_pci_id: u32,
|
||||
pub vgpu_id: u16,
|
||||
pub gpu_pci_bdf: u32,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Nv0000CtrlVgpuGetStartDataParams {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Nv0000CtrlVgpuGetStartDataParams")
|
||||
.field("mdev_uuid", &format_args!("{{{}}}", self.mdev_uuid))
|
||||
.field("config_params", &CStrFormat(&self.config_params))
|
||||
.field("qemu_pid", &self.qemu_pid)
|
||||
.field("gpu_pci_id", &HexFormat(&self.gpu_pci_id))
|
||||
.field("vgpu_id", &self.vgpu_id)
|
||||
.field("gpu_pci_bdf", &self.gpu_pci_bdf)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::mem;
|
||||
|
||||
use super::Nv0000CtrlVgpuGetStartDataParams;
|
||||
|
||||
#[test]
|
||||
fn verify_sizes() {
|
||||
assert_eq!(mem::size_of::<Nv0000CtrlVgpuGetStartDataParams>(), 0x420);
|
||||
}
|
||||
}
|
||||
11
src/nvidia/ctrl0080gpu.rs
Normal file
11
src/nvidia/ctrl0080gpu.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
///! Sourced from https://github.com/NVIDIA/open-gpu-kernel-modules/blob/758b4ee8189c5198504cb1c3c5bc29027a9118a3/src/common/sdk/nvidia/inc/ctrl/ctrl0080/ctrl0080gpu.h
|
||||
|
||||
pub const NV0080_CTRL_CMD_GPU_GET_VIRTUALIZATION_MODE: u32 = 0x800289;
|
||||
|
||||
/// `nvidia-vgpu-mgr` expects this value for a vGPU capable GPU.
|
||||
pub const NV0080_CTRL_GPU_VIRTUALIZATION_MODE_HOST: u32 = 0x00000003;
|
||||
|
||||
/// See `NV0080_CTRL_GPU_GET_VIRTUALIZATION_MODE_PARAMS`
|
||||
pub struct Nv0080CtrlGpuGetVirtualizationModeParams {
|
||||
pub virtualization_mode: u32,
|
||||
}
|
||||
13
src/nvidia/ctrl2080bus.rs
Normal file
13
src/nvidia/ctrl2080bus.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
///! Sourced from https://github.com/NVIDIA/open-gpu-kernel-modules/blob/5f40a5aee5ef9c92085836bf5b5a9056174f07f1/src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080bus.h
|
||||
|
||||
pub const NV2080_CTRL_CMD_BUS_GET_PCI_INFO: u32 = 0x20801801;
|
||||
|
||||
/// See `NV2080_CTRL_BUS_GET_PCI_INFO_PARAMS`
|
||||
//#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct Nv2080CtrlBusGetPciInfoParams {
|
||||
pub pci_device_id: u32,
|
||||
pub pci_sub_system_id: u32,
|
||||
pub pci_revision_id: u32,
|
||||
pub pci_ext_device_id: u32,
|
||||
}
|
||||
7
src/nvidia/ctrl2080gpu.rs
Normal file
7
src/nvidia/ctrl2080gpu.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
///! Sourced from https://github.com/NVIDIA/open-gpu-kernel-modules/blob/5f40a5aee5ef9c92085836bf5b5a9056174f07f1/src/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080gpu.h
|
||||
|
||||
pub const NV_GRID_LICENSE_INFO_MAX_LENGTH: usize = 128;
|
||||
|
||||
pub const NV2080_GPU_MAX_NAME_STRING_LENGTH: usize = 0x0000040;
|
||||
|
||||
pub const NV2080_CTRL_CMD_GPU_GET_INFOROM_OBJECT_VERSION: u32 = 0x2080014b;
|
||||
3
src/nvidia/ctrl9096.rs
Normal file
3
src/nvidia/ctrl9096.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
///! Sourced from https://github.com/NVIDIA/open-gpu-kernel-modules/blob/90eb10774f1c53d2364eacf9fa8f0c7a92b1b824/src/common/sdk/nvidia/inc/ctrl/ctrl9096.h
|
||||
|
||||
pub const NV9096_CTRL_CMD_GET_ZBC_CLEAR_TABLE: u32 = 0x90960103;
|
||||
153
src/nvidia/ctrla081.rs
Normal file
153
src/nvidia/ctrla081.rs
Normal file
@@ -0,0 +1,153 @@
|
||||
///! Sourced from https://github.com/NVIDIA/open-gpu-kernel-modules/blob/758b4ee8189c5198504cb1c3c5bc29027a9118a3/src/common/sdk/nvidia/inc/ctrl/ctrla081.h
|
||||
use std::fmt;
|
||||
|
||||
use super::ctrl2080gpu::{NV2080_GPU_MAX_NAME_STRING_LENGTH, NV_GRID_LICENSE_INFO_MAX_LENGTH};
|
||||
use crate::format::{CStrFormat, HexFormat, HexFormatSlice, WideCharFormat};
|
||||
use crate::utils::AlignedU64;
|
||||
|
||||
pub const NVA081_VGPU_STRING_BUFFER_SIZE: usize = 32;
|
||||
pub const NVA081_VGPU_SIGNATURE_SIZE: usize = 128;
|
||||
|
||||
pub const NVA081_EXTRA_PARAMETERS_SIZE: usize = 1024;
|
||||
|
||||
/// See `NVA081_CTRL_VGPU_CONFIG_INFO`
|
||||
// Set `align(8)` for `NVA081_CTRL_VGPU_CONFIG_GET_VGPU_TYPE_INFO_PARAMS`
|
||||
#[repr(C, align(8))]
|
||||
pub struct NvA081CtrlVgpuInfo {
|
||||
pub vgpu_type: u32,
|
||||
pub vgpu_name: [u8; NVA081_VGPU_STRING_BUFFER_SIZE],
|
||||
pub vgpu_class: [u8; NVA081_VGPU_STRING_BUFFER_SIZE],
|
||||
pub vgpu_signature: [u8; NVA081_VGPU_SIGNATURE_SIZE],
|
||||
pub license: [u8; NV_GRID_LICENSE_INFO_MAX_LENGTH],
|
||||
pub max_instance: u32,
|
||||
pub num_heads: u32,
|
||||
pub max_resolution_x: u32,
|
||||
pub max_resolution_y: u32,
|
||||
pub max_pixels: u32,
|
||||
pub frl_config: u32,
|
||||
pub cuda_enabled: u32,
|
||||
pub ecc_supported: u32,
|
||||
pub gpu_instance_size: u32,
|
||||
pub multi_vgpu_supported: u32,
|
||||
pub vdev_id: AlignedU64,
|
||||
pub pdev_id: AlignedU64,
|
||||
pub profile_size: AlignedU64,
|
||||
pub fb_length: AlignedU64,
|
||||
pub gsp_heap_size: AlignedU64,
|
||||
pub fb_reservation: AlignedU64,
|
||||
pub mappable_video_size: AlignedU64,
|
||||
pub encoder_capacity: u32,
|
||||
pub bar1_length: AlignedU64,
|
||||
pub frl_enable: u32,
|
||||
pub adapter_name: [u8; NV2080_GPU_MAX_NAME_STRING_LENGTH],
|
||||
pub adapter_name_unicode: [u16; NV2080_GPU_MAX_NAME_STRING_LENGTH],
|
||||
pub short_gpu_name_string: [u8; NV2080_GPU_MAX_NAME_STRING_LENGTH],
|
||||
pub licensed_product_name: [u8; NV_GRID_LICENSE_INFO_MAX_LENGTH],
|
||||
pub vgpu_extra_params: [u8; NVA081_EXTRA_PARAMETERS_SIZE],
|
||||
pub ftrace_enable: u32,
|
||||
pub gpu_direct_supported: u32,
|
||||
pub nvlink_p2p_supported: u32,
|
||||
pub multi_vgpu_exclusive: u32,
|
||||
pub exclusive_type: u32,
|
||||
pub exclusive_size: u32,
|
||||
pub gpu_instance_profile_id: u32,
|
||||
unknown_end: [u8; 0xc00],
|
||||
}
|
||||
|
||||
pub const NVA081_CTRL_CMD_VGPU_CONFIG_GET_VGPU_TYPE_INFO: u32 = 0xa0810103;
|
||||
|
||||
/// This RM control command is used starting in vGPU version 15.0 (525.60.12).
|
||||
///
|
||||
/// See `NVA081_CTRL_VGPU_CONFIG_GET_VGPU_TYPE_INFO_PARAMS`
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct NvA081CtrlVgpuConfigGetVgpuTypeInfoParams {
|
||||
pub vgpu_type: u32,
|
||||
pub vgpu_type_info: NvA081CtrlVgpuInfo,
|
||||
}
|
||||
|
||||
pub const NVA081_CTRL_CMD_VGPU_CONFIG_GET_MIGRATION_CAP: u32 = 0xa0810112;
|
||||
|
||||
/// See `NVA081_CTRL_CMD_VGPU_CONFIG_GET_MIGRATION_CAP_PARAMS`
|
||||
#[repr(C)]
|
||||
pub struct NvA081CtrlCmdVgpuConfigGetMigrationCapParams {
|
||||
pub migration_cap: u8,
|
||||
}
|
||||
|
||||
impl fmt::Debug for NvA081CtrlVgpuInfo {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let vgpu_signature = self.vgpu_signature[..]
|
||||
.split(|&x| x == 0)
|
||||
.next()
|
||||
.unwrap_or(&[]);
|
||||
let vgpu_extra_params = self.vgpu_extra_params[..]
|
||||
.split(|&x| x == 0)
|
||||
.next()
|
||||
.unwrap_or(&[]);
|
||||
|
||||
f.debug_struct("NvA081CtrlVgpuInfo")
|
||||
.field("vgpu_type", &self.vgpu_type)
|
||||
.field("vgpu_name", &CStrFormat(&self.vgpu_name))
|
||||
.field("vgpu_class", &CStrFormat(&self.vgpu_class))
|
||||
.field("vgpu_signature", &HexFormatSlice(vgpu_signature))
|
||||
.field("license", &CStrFormat(&self.license))
|
||||
.field("max_instance", &self.max_instance)
|
||||
.field("num_heads", &self.num_heads)
|
||||
.field("max_resolution_x", &self.max_resolution_x)
|
||||
.field("max_resolution_y", &self.max_resolution_y)
|
||||
.field("max_pixels", &self.max_pixels)
|
||||
.field("frl_config", &self.frl_config)
|
||||
.field("cuda_enabled", &self.cuda_enabled)
|
||||
.field("ecc_supported", &self.ecc_supported)
|
||||
.field("gpu_instance_size", &self.gpu_instance_size)
|
||||
.field("multi_vgpu_supported", &self.multi_vgpu_supported)
|
||||
.field("vdev_id", &HexFormat(self.vdev_id))
|
||||
.field("pdev_id", &HexFormat(self.pdev_id))
|
||||
.field("profile_size", &HexFormat(self.profile_size))
|
||||
.field("fb_length", &HexFormat(self.fb_length))
|
||||
.field("gsp_heap_size", &HexFormat(self.gsp_heap_size))
|
||||
.field("fb_reservation", &HexFormat(self.fb_reservation))
|
||||
.field("mappable_video_size", &HexFormat(self.mappable_video_size))
|
||||
.field("encoder_capacity", &HexFormat(self.encoder_capacity))
|
||||
.field("bar1_length", &HexFormat(self.bar1_length))
|
||||
.field("frl_enable", &self.frl_enable)
|
||||
.field("adapter_name", &CStrFormat(&self.adapter_name))
|
||||
.field(
|
||||
"adapter_name_unicode",
|
||||
&WideCharFormat(&self.adapter_name_unicode),
|
||||
)
|
||||
.field(
|
||||
"short_gpu_name_string",
|
||||
&CStrFormat(&self.short_gpu_name_string),
|
||||
)
|
||||
.field(
|
||||
"licensed_product_name",
|
||||
&CStrFormat(&self.licensed_product_name),
|
||||
)
|
||||
.field("vgpu_extra_params", &CStrFormat(vgpu_extra_params))
|
||||
.field("ftrace_enable", &self.ftrace_enable)
|
||||
.field("gpu_direct_supported", &self.gpu_direct_supported)
|
||||
.field("nvlink_p2p_supported", &self.nvlink_p2p_supported)
|
||||
.field("multi_vgpu_exclusive", &self.multi_vgpu_exclusive)
|
||||
.field("exclusive_type", &self.exclusive_type)
|
||||
.field("exclusive_size", &self.exclusive_size)
|
||||
.field("gpu_instance_profile_id", &self.gpu_instance_profile_id)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::mem;
|
||||
|
||||
use super::{NvA081CtrlVgpuConfigGetVgpuTypeInfoParams, NvA081CtrlVgpuInfo};
|
||||
|
||||
#[test]
|
||||
fn verify_sizes() {
|
||||
assert_eq!(mem::size_of::<NvA081CtrlVgpuInfo>(), 0x1358);
|
||||
assert_eq!(
|
||||
mem::size_of::<NvA081CtrlVgpuConfigGetVgpuTypeInfoParams>(),
|
||||
0x1360
|
||||
);
|
||||
}
|
||||
}
|
||||
108
src/nvidia/ctrla082.rs
Normal file
108
src/nvidia/ctrla082.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
use std::fmt;
|
||||
|
||||
use crate::format::{CStrFormat, HexFormat, HexFormatSlice, WideCharFormat};
|
||||
|
||||
/// Inferred based on `NVA082_CTRL_CMD_HOST_VGPU_DEVICE_GET_VGPU_TYPE_INFO_PARAMS`
|
||||
pub const NVA082_CTRL_CMD_HOST_VGPU_DEVICE_GET_VGPU_TYPE_INFO: u32 = 0xa0820102;
|
||||
|
||||
/// Pulled from a comment in [`NVA081_CTRL_VGPU_INFO`](https://github.com/NVIDIA/open-gpu-kernel-modules/blob/758b4ee8189c5198504cb1c3c5bc29027a9118a3/src/common/sdk/nvidia/inc/ctrl/ctrla081.h#L82)
|
||||
#[repr(C)]
|
||||
pub struct NvA082CtrlCmdHostVgpuDeviceGetVgpuTypeInfoParams {
|
||||
pub vgpu_type: u32,
|
||||
pub vgpu_name: [u8; 32],
|
||||
pub vgpu_class: [u8; 32],
|
||||
pub vgpu_signature: [u8; 128],
|
||||
pub features: [u8; 128],
|
||||
pub max_instances: u32,
|
||||
pub num_heads: u32,
|
||||
pub max_resolution_x: u32,
|
||||
pub max_resolution_y: u32,
|
||||
pub max_pixels: u32,
|
||||
pub frl_config: u32,
|
||||
pub cuda_enabled: u32,
|
||||
pub ecc_supported: u32,
|
||||
pub mig_instance_size: u32,
|
||||
pub multi_vgpu_supported: u32,
|
||||
pub vdev_id: u64,
|
||||
pub pdev_id: u64,
|
||||
pub fb_length: u64,
|
||||
pub mappable_video_size: u64,
|
||||
pub fb_reservation: u64,
|
||||
pub encoder_capacity: u32,
|
||||
pub bar1_length: u64,
|
||||
pub frl_enable: u32,
|
||||
pub adapter_name: [u8; 64],
|
||||
pub adapter_name_unicode: [u16; 64],
|
||||
pub short_gpu_name_string: [u8; 64],
|
||||
pub licensed_product_name: [u8; 128],
|
||||
pub vgpu_extra_params: [u8; 1024],
|
||||
unknown_end: [u8; 8],
|
||||
}
|
||||
|
||||
impl fmt::Debug for NvA082CtrlCmdHostVgpuDeviceGetVgpuTypeInfoParams {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let vgpu_signature = self.vgpu_signature[..]
|
||||
.split(|&x| x == 0)
|
||||
.next()
|
||||
.unwrap_or(&[]);
|
||||
let vgpu_extra_params = self.vgpu_extra_params[..]
|
||||
.split(|&x| x == 0)
|
||||
.next()
|
||||
.unwrap_or(&[]);
|
||||
|
||||
f.debug_struct("NvA082CtrlCmdHostVgpuDeviceGetVgpuTypeInfoParams")
|
||||
.field("vgpu_type", &self.vgpu_type)
|
||||
.field("vgpu_name", &CStrFormat(&self.vgpu_name))
|
||||
.field("vgpu_class", &CStrFormat(&self.vgpu_class))
|
||||
.field("vgpu_signature", &HexFormatSlice(vgpu_signature))
|
||||
.field("features", &CStrFormat(&self.features))
|
||||
.field("max_instances", &self.max_instances)
|
||||
.field("num_heads", &self.num_heads)
|
||||
.field("max_resolution_x", &self.max_resolution_x)
|
||||
.field("max_resolution_y", &self.max_resolution_y)
|
||||
.field("max_pixels", &self.max_pixels)
|
||||
.field("frl_config", &self.frl_config)
|
||||
.field("cuda_enabled", &self.cuda_enabled)
|
||||
.field("ecc_supported", &self.ecc_supported)
|
||||
.field("mig_instance_size", &self.mig_instance_size)
|
||||
.field("multi_vgpu_supported", &self.multi_vgpu_supported)
|
||||
.field("vdev_id", &HexFormat(self.vdev_id))
|
||||
.field("pdev_id", &HexFormat(self.pdev_id))
|
||||
.field("fb_length", &HexFormat(self.fb_length))
|
||||
.field("mappable_video_size", &HexFormat(self.mappable_video_size))
|
||||
.field("fb_reservation", &HexFormat(self.fb_reservation))
|
||||
.field("encoder_capacity", &HexFormat(self.encoder_capacity))
|
||||
.field("bar1_length", &HexFormat(self.bar1_length))
|
||||
.field("frl_enable", &self.frl_enable)
|
||||
.field("adapter_name", &CStrFormat(&self.adapter_name))
|
||||
.field(
|
||||
"adapter_name_unicode",
|
||||
&WideCharFormat(&self.adapter_name_unicode),
|
||||
)
|
||||
.field(
|
||||
"short_gpu_name_string",
|
||||
&CStrFormat(&self.short_gpu_name_string),
|
||||
)
|
||||
.field(
|
||||
"licensed_product_name",
|
||||
&CStrFormat(&self.licensed_product_name),
|
||||
)
|
||||
.field("vgpu_extra_params", &HexFormatSlice(vgpu_extra_params))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::mem;
|
||||
|
||||
use super::NvA082CtrlCmdHostVgpuDeviceGetVgpuTypeInfoParams;
|
||||
|
||||
#[test]
|
||||
fn verify_sizes() {
|
||||
assert_eq!(
|
||||
mem::size_of::<NvA082CtrlCmdHostVgpuDeviceGetVgpuTypeInfoParams>(),
|
||||
0x738
|
||||
);
|
||||
}
|
||||
}
|
||||
141
src/nvidia/error.rs
Normal file
141
src/nvidia/error.rs
Normal file
@@ -0,0 +1,141 @@
|
||||
#![allow(unused)]
|
||||
|
||||
///! When ioctl returns success (retval >= 0) but sets the status value of the arg structure to 3
|
||||
///! then `nvidia-vgpud` will sleep for a bit (first 0.1s then 1s then 10s) then issue the same
|
||||
///! ioctl call again until the status differs from 3. It will attempt this for up to 24h before
|
||||
///! giving up.
|
||||
///!
|
||||
///! Sourced from https://github.com/NVIDIA/open-gpu-kernel-modules/blob/5f40a5aee5ef9c92085836bf5b5a9056174f07f1/kernel-open/common/inc/nvstatuscodes.h
|
||||
|
||||
pub const NV_OK: u32 = 0x00000000;
|
||||
pub const NV_ERR_GENERIC: u32 = 0x0000ffff;
|
||||
pub const NV_ERR_BROKEN_FB: u32 = 0x00000001;
|
||||
pub const NV_ERR_BUFFER_TOO_SMALL: u32 = 0x00000002;
|
||||
pub const NV_ERR_BUSY_RETRY: u32 = 0x00000003;
|
||||
pub const NV_ERR_CALLBACK_NOT_SCHEDULED: u32 = 0x00000004;
|
||||
pub const NV_ERR_CARD_NOT_PRESENT: u32 = 0x00000005;
|
||||
pub const NV_ERR_CYCLE_DETECTED: u32 = 0x00000006;
|
||||
pub const NV_ERR_DMA_IN_USE: u32 = 0x00000007;
|
||||
pub const NV_ERR_DMA_MEM_NOT_LOCKED: u32 = 0x00000008;
|
||||
pub const NV_ERR_DMA_MEM_NOT_UNLOCKED: u32 = 0x00000009;
|
||||
pub const NV_ERR_DUAL_LINK_INUSE: u32 = 0x0000000a;
|
||||
pub const NV_ERR_ECC_ERROR: u32 = 0x0000000b;
|
||||
pub const NV_ERR_FIFO_BAD_ACCESS: u32 = 0x0000000c;
|
||||
pub const NV_ERR_FREQ_NOT_SUPPORTED: u32 = 0x0000000d;
|
||||
pub const NV_ERR_GPU_DMA_NOT_INITIALIZED: u32 = 0x0000000e;
|
||||
pub const NV_ERR_GPU_IS_LOST: u32 = 0x0000000f;
|
||||
pub const NV_ERR_GPU_IN_FULLCHIP_RESET: u32 = 0x00000010;
|
||||
pub const NV_ERR_GPU_NOT_FULL_POWER: u32 = 0x00000011;
|
||||
pub const NV_ERR_GPU_UUID_NOT_FOUND: u32 = 0x00000012;
|
||||
pub const NV_ERR_HOT_SWITCH: u32 = 0x00000013;
|
||||
pub const NV_ERR_I2C_ERROR: u32 = 0x00000014;
|
||||
pub const NV_ERR_I2C_SPEED_TOO_HIGH: u32 = 0x00000015;
|
||||
pub const NV_ERR_ILLEGAL_ACTION: u32 = 0x00000016;
|
||||
pub const NV_ERR_IN_USE: u32 = 0x00000017;
|
||||
pub const NV_ERR_INFLATE_COMPRESSED_DATA_FAILED: u32 = 0x00000018;
|
||||
pub const NV_ERR_INSERT_DUPLICATE_NAME: u32 = 0x00000019;
|
||||
pub const NV_ERR_INSUFFICIENT_RESOURCES: u32 = 0x0000001a;
|
||||
pub const NV_ERR_INSUFFICIENT_PERMISSIONS: u32 = 0x0000001b;
|
||||
pub const NV_ERR_INSUFFICIENT_POWER: u32 = 0x0000001c;
|
||||
pub const NV_ERR_INVALID_ACCESS_TYPE: u32 = 0x0000001d;
|
||||
pub const NV_ERR_INVALID_ADDRESS: u32 = 0x0000001e;
|
||||
pub const NV_ERR_INVALID_ARGUMENT: u32 = 0x0000001f;
|
||||
pub const NV_ERR_INVALID_BASE: u32 = 0x00000020;
|
||||
pub const NV_ERR_INVALID_CHANNEL: u32 = 0x00000021;
|
||||
pub const NV_ERR_INVALID_CLASS: u32 = 0x00000022;
|
||||
pub const NV_ERR_INVALID_CLIENT: u32 = 0x00000023;
|
||||
pub const NV_ERR_INVALID_COMMAND: u32 = 0x00000024;
|
||||
pub const NV_ERR_INVALID_DATA: u32 = 0x00000025;
|
||||
pub const NV_ERR_INVALID_DEVICE: u32 = 0x00000026;
|
||||
pub const NV_ERR_INVALID_DMA_SPECIFIER: u32 = 0x00000027;
|
||||
pub const NV_ERR_INVALID_EVENT: u32 = 0x00000028;
|
||||
pub const NV_ERR_INVALID_FLAGS: u32 = 0x00000029;
|
||||
pub const NV_ERR_INVALID_FUNCTION: u32 = 0x0000002a;
|
||||
pub const NV_ERR_INVALID_HEAP: u32 = 0x0000002b;
|
||||
pub const NV_ERR_INVALID_INDEX: u32 = 0x0000002c;
|
||||
pub const NV_ERR_INVALID_IRQ_LEVEL: u32 = 0x0000002d;
|
||||
pub const NV_ERR_INVALID_LIMIT: u32 = 0x0000002e;
|
||||
pub const NV_ERR_INVALID_LOCK_STATE: u32 = 0x0000002f;
|
||||
pub const NV_ERR_INVALID_METHOD: u32 = 0x00000030;
|
||||
pub const NV_ERR_INVALID_OBJECT: u32 = 0x00000031;
|
||||
pub const NV_ERR_INVALID_OBJECT_BUFFER: u32 = 0x00000032;
|
||||
pub const NV_ERR_INVALID_OBJECT_HANDLE: u32 = 0x00000033;
|
||||
pub const NV_ERR_INVALID_OBJECT_NEW: u32 = 0x00000034;
|
||||
pub const NV_ERR_INVALID_OBJECT_OLD: u32 = 0x00000035;
|
||||
pub const NV_ERR_INVALID_OBJECT_PARENT: u32 = 0x00000036;
|
||||
pub const NV_ERR_INVALID_OFFSET: u32 = 0x00000037;
|
||||
pub const NV_ERR_INVALID_OPERATION: u32 = 0x00000038;
|
||||
pub const NV_ERR_INVALID_OWNER: u32 = 0x00000039;
|
||||
pub const NV_ERR_INVALID_PARAM_STRUCT: u32 = 0x0000003a;
|
||||
pub const NV_ERR_INVALID_PARAMETER: u32 = 0x0000003b;
|
||||
pub const NV_ERR_INVALID_PATH: u32 = 0x0000003c;
|
||||
pub const NV_ERR_INVALID_POINTER: u32 = 0x0000003d;
|
||||
pub const NV_ERR_INVALID_REGISTRY_KEY: u32 = 0x0000003e;
|
||||
pub const NV_ERR_INVALID_REQUEST: u32 = 0x0000003f;
|
||||
pub const NV_ERR_INVALID_STATE: u32 = 0x00000040;
|
||||
pub const NV_ERR_INVALID_STRING_LENGTH: u32 = 0x00000041;
|
||||
pub const NV_ERR_INVALID_READ: u32 = 0x00000042;
|
||||
pub const NV_ERR_INVALID_WRITE: u32 = 0x00000043;
|
||||
pub const NV_ERR_INVALID_XLATE: u32 = 0x00000044;
|
||||
pub const NV_ERR_IRQ_NOT_FIRING: u32 = 0x00000045;
|
||||
pub const NV_ERR_IRQ_EDGE_TRIGGERED: u32 = 0x00000046;
|
||||
pub const NV_ERR_MEMORY_TRAINING_FAILED: u32 = 0x00000047;
|
||||
pub const NV_ERR_MISMATCHED_SLAVE: u32 = 0x00000048;
|
||||
pub const NV_ERR_MISMATCHED_TARGET: u32 = 0x00000049;
|
||||
pub const NV_ERR_MISSING_TABLE_ENTRY: u32 = 0x0000004a;
|
||||
pub const NV_ERR_MODULE_LOAD_FAILED: u32 = 0x0000004b;
|
||||
pub const NV_ERR_MORE_DATA_AVAILABLE: u32 = 0x0000004c;
|
||||
pub const NV_ERR_MORE_PROCESSING_REQUIRED: u32 = 0x0000004d;
|
||||
pub const NV_ERR_MULTIPLE_MEMORY_TYPES: u32 = 0x0000004e;
|
||||
pub const NV_ERR_NO_FREE_FIFOS: u32 = 0x0000004f;
|
||||
pub const NV_ERR_NO_INTR_PENDING: u32 = 0x00000050;
|
||||
pub const NV_ERR_NO_MEMORY: u32 = 0x00000051;
|
||||
pub const NV_ERR_NO_SUCH_DOMAIN: u32 = 0x00000052;
|
||||
pub const NV_ERR_NO_VALID_PATH: u32 = 0x00000053;
|
||||
pub const NV_ERR_NOT_COMPATIBLE: u32 = 0x00000054;
|
||||
pub const NV_ERR_NOT_READY: u32 = 0x00000055;
|
||||
pub const NV_ERR_NOT_SUPPORTED: u32 = 0x00000056;
|
||||
pub const NV_ERR_OBJECT_NOT_FOUND: u32 = 0x00000057;
|
||||
pub const NV_ERR_OBJECT_TYPE_MISMATCH: u32 = 0x00000058;
|
||||
pub const NV_ERR_OPERATING_SYSTEM: u32 = 0x00000059;
|
||||
pub const NV_ERR_OTHER_DEVICE_FOUND: u32 = 0x0000005a;
|
||||
pub const NV_ERR_OUT_OF_RANGE: u32 = 0x0000005b;
|
||||
pub const NV_ERR_OVERLAPPING_UVM_COMMIT: u32 = 0x0000005c;
|
||||
pub const NV_ERR_PAGE_TABLE_NOT_AVAIL: u32 = 0x0000005d;
|
||||
pub const NV_ERR_PID_NOT_FOUND: u32 = 0x0000005e;
|
||||
pub const NV_ERR_PROTECTION_FAULT: u32 = 0x0000005f;
|
||||
pub const NV_ERR_RC_ERROR: u32 = 0x00000060;
|
||||
pub const NV_ERR_REJECTED_VBIOS: u32 = 0x00000061;
|
||||
pub const NV_ERR_RESET_REQUIRED: u32 = 0x00000062;
|
||||
pub const NV_ERR_STATE_IN_USE: u32 = 0x00000063;
|
||||
pub const NV_ERR_SIGNAL_PENDING: u32 = 0x00000064;
|
||||
pub const NV_ERR_TIMEOUT: u32 = 0x00000065;
|
||||
pub const NV_ERR_TIMEOUT_RETRY: u32 = 0x00000066;
|
||||
pub const NV_ERR_TOO_MANY_PRIMARIES: u32 = 0x00000067;
|
||||
pub const NV_ERR_UVM_ADDRESS_IN_USE: u32 = 0x00000068;
|
||||
pub const NV_ERR_MAX_SESSION_LIMIT_REACHED: u32 = 0x00000069;
|
||||
pub const NV_ERR_LIB_RM_VERSION_MISMATCH: u32 = 0x0000006a;
|
||||
pub const NV_ERR_PRIV_SEC_VIOLATION: u32 = 0x0000006b;
|
||||
pub const NV_ERR_GPU_IN_DEBUG_MODE: u32 = 0x0000006c;
|
||||
pub const NV_ERR_FEATURE_NOT_ENABLED: u32 = 0x0000006d;
|
||||
pub const NV_ERR_RESOURCE_LOST: u32 = 0x0000006e;
|
||||
pub const NV_ERR_PMU_NOT_READY: u32 = 0x0000006f;
|
||||
pub const NV_ERR_FLCN_ERROR: u32 = 0x00000070;
|
||||
pub const NV_ERR_FATAL_ERROR: u32 = 0x00000071;
|
||||
pub const NV_ERR_MEMORY_ERROR: u32 = 0x00000072;
|
||||
pub const NV_ERR_INVALID_LICENSE: u32 = 0x00000073;
|
||||
pub const NV_ERR_NVLINK_INIT_ERROR: u32 = 0x00000074;
|
||||
pub const NV_ERR_NVLINK_MINION_ERROR: u32 = 0x00000075;
|
||||
pub const NV_ERR_NVLINK_CLOCK_ERROR: u32 = 0x00000076;
|
||||
pub const NV_ERR_NVLINK_TRAINING_ERROR: u32 = 0x00000077;
|
||||
pub const NV_ERR_NVLINK_CONFIGURATION_ERROR: u32 = 0x00000078;
|
||||
pub const NV_ERR_RISCV_ERROR: u32 = 0x00000079;
|
||||
pub const NV_ERR_FABRIC_MANAGER_NOT_PRESENT: u32 = 0x0000007a;
|
||||
pub const NV_WARN_HOT_SWITCH: u32 = 0x00010001;
|
||||
pub const NV_WARN_INCORRECT_PERFMON_DATA: u32 = 0x00010002;
|
||||
pub const NV_WARN_MISMATCHED_SLAVE: u32 = 0x00010003;
|
||||
pub const NV_WARN_MISMATCHED_TARGET: u32 = 0x00010004;
|
||||
pub const NV_WARN_MORE_PROCESSING_REQUIRED: u32 = 0x00010005;
|
||||
pub const NV_WARN_NOTHING_TO_DO: u32 = 0x00010006;
|
||||
pub const NV_WARN_NULL_OBJECT: u32 = 0x00010007;
|
||||
pub const NV_WARN_OUT_OF_RANGE: u32 = 0x00010008;
|
||||
4
src/nvidia/ioctl.rs
Normal file
4
src/nvidia/ioctl.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
use std::os::raw::c_ulong;
|
||||
|
||||
/// Pulled from https://github.com/NVIDIA/open-gpu-kernel-modules/blob/d8f3bcff924776518f1e63286537c3cf365289ac/kernel-open/common/inc/nv-ioctl-numbers.h
|
||||
pub const NV_IOCTL_MAGIC: c_ulong = b'F' as _;
|
||||
11
src/nvidia/mod.rs
Normal file
11
src/nvidia/mod.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
pub mod ctrl0000vgpu;
|
||||
pub mod ctrl0080gpu;
|
||||
pub mod ctrl2080bus;
|
||||
pub mod ctrl2080gpu;
|
||||
pub mod ctrl9096;
|
||||
pub mod ctrla081;
|
||||
pub mod ctrla082;
|
||||
pub mod error;
|
||||
pub mod ioctl;
|
||||
pub mod nvos;
|
||||
pub mod nvtypes;
|
||||
40
src/nvidia/nvos.rs
Normal file
40
src/nvidia/nvos.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
///! Sourced from https://github.com/NVIDIA/open-gpu-kernel-modules/blob/d8f3bcff924776518f1e63286537c3cf365289ac/src/common/sdk/nvidia/inc/nvos.h
|
||||
use std::os::raw::{c_ulong, c_void};
|
||||
|
||||
use super::ioctl::NV_IOCTL_MAGIC;
|
||||
use super::nvtypes::NvHandle;
|
||||
use crate::ioctl::_IOWR;
|
||||
|
||||
/// Value of the "request" argument used by `nvidia-vgpud` and `nvidia-vgpu-mgr` when calling
|
||||
/// ioctl to read the PCI device ID, type, and many other things from the driver.
|
||||
///
|
||||
/// Pulled from https://github.com/NVIDIA/open-gpu-kernel-modules/blob/d8f3bcff924776518f1e63286537c3cf365289ac/src/nvidia/arch/nvalloc/unix/include/nv_escape.h
|
||||
/// and [`nvidia_ioctl`](https://github.com/NVIDIA/open-gpu-kernel-modules/blob/98553501593ef05bddcc438689ed1136f732d40a/kernel-open/nvidia/nv.c)
|
||||
/// and [`__NV_IOWR`](https://github.com/NVIDIA/open-gpu-kernel-modules/blob/98553501593ef05bddcc438689ed1136f732d40a/kernel-open/common/inc/nv.h)
|
||||
/// showing that `_IOWR` is used to derive the I/O control request codes.
|
||||
pub const NV_ESC_RM_CONTROL: c_ulong = _IOWR::<Nvos54Parameters>(NV_IOCTL_MAGIC, 0x2a);
|
||||
|
||||
/// When issuing ioctl with `NV_ESC_RM_CONTROL` then the `argp` argument is a pointer to a
|
||||
/// `NVOS54_PARAMETERS` structure like this.
|
||||
///
|
||||
/// See [`NVOS54_PARAMETERS`](https://github.com/NVIDIA/open-gpu-kernel-modules/blob/d8f3bcff924776518f1e63286537c3cf365289ac/src/common/sdk/nvidia/inc/nvos.h)
|
||||
//#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
pub struct Nvos54Parameters {
|
||||
/// Initialized prior to call.
|
||||
pub h_client: NvHandle,
|
||||
/// Initialized prior to call.
|
||||
pub h_object: NvHandle,
|
||||
/// Operation type, see comment below.
|
||||
pub cmd: u32,
|
||||
/// Set of flags for call.
|
||||
pub flags: u32,
|
||||
/// Pointer initialized prior to call.
|
||||
/// Pointee initialized to 0 prior to call.
|
||||
/// Pointee is written by ioctl call.
|
||||
pub params: *mut c_void,
|
||||
/// Size in bytes of the object referenced in `params`.
|
||||
pub params_size: u32,
|
||||
/// Written by ioctl call. See comment below.
|
||||
pub status: u32,
|
||||
}
|
||||
1
src/nvidia/nvtypes.rs
Normal file
1
src/nvidia/nvtypes.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub type NvHandle = u32;
|
||||
19
src/utils.rs
Normal file
19
src/utils.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C, align(8))]
|
||||
pub struct AlignedU64(pub u64);
|
||||
|
||||
impl fmt::Debug for AlignedU64 {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::LowerHex for AlignedU64 {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::LowerHex::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
25
src/uuid.rs
Normal file
25
src/uuid.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Uuid(pub u32, pub u16, pub u16, pub [u8; 8]);
|
||||
|
||||
impl fmt::Display for Uuid {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{:08x}-{:04x}-{:04x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
|
||||
self.0,
|
||||
self.1,
|
||||
self.2,
|
||||
self.3[0],
|
||||
self.3[1],
|
||||
self.3[2],
|
||||
self.3[3],
|
||||
self.3[4],
|
||||
self.3[5],
|
||||
self.3[6],
|
||||
self.3[7]
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user