From 506ada89629ec7059b96ecfb0dc7d33ece0103ca Mon Sep 17 00:00:00 2001 From: Eduard Zingerman Date: Fri, 4 Sep 2026 17:05:56 -0700 Subject: bpf: mark a NULL kfunc argument precise check_kfunc_arg() allows bpf_register_is_null() for nullable arguments w/o marking the underlying scalar register precise. Hence a checkpoint created on such a path would prune against arbitrary scalar value. Fixes: 3bda08b63670 ("bpf: Allow NULL buffers in bpf_dynptr_slice(_rw)") Signed-off-by: Eduard Zingerman Link: https://lore.kernel.org/r/20260904-register-is-null-precise-fixes-v1-5-0f5a360ff15d@gmail.com Signed-off-by: Alexei Starovoitov --- drivers/gpu/drm/nova/Kconfig | 17 +++++++++ drivers/gpu/drm/nova/Makefile | 4 ++ drivers/gpu/drm/nova/driver.rs | 84 ++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/nova/file.rs | 69 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/nova/gem.rs | 55 +++++++++++++++++++++++++++ drivers/gpu/drm/nova/nova.rs | 17 +++++++++ 6 files changed, 246 insertions(+) create mode 100644 drivers/gpu/drm/nova/Kconfig create mode 100644 drivers/gpu/drm/nova/Makefile create mode 100644 drivers/gpu/drm/nova/driver.rs create mode 100644 drivers/gpu/drm/nova/file.rs create mode 100644 drivers/gpu/drm/nova/gem.rs create mode 100644 drivers/gpu/drm/nova/nova.rs (limited to 'drivers/gpu/drm/nova') diff --git a/drivers/gpu/drm/nova/Kconfig b/drivers/gpu/drm/nova/Kconfig new file mode 100644 index 000000000..ba16c7440 --- /dev/null +++ b/drivers/gpu/drm/nova/Kconfig @@ -0,0 +1,17 @@ +config DRM_NOVA + tristate "Nova DRM driver" + depends on 64BIT + depends on DRM=y + depends on PCI + depends on RUST + depends on !CPU_BIG_ENDIAN + select AUXILIARY_BUS + select NOVA_CORE + default n + help + Choose this if you want to build the Nova DRM driver for Nvidia + GSP-based GPUs. + + This driver is work in progress and may not be functional. + + If M is selected, the module will be called nova-drm. diff --git a/drivers/gpu/drm/nova/Makefile b/drivers/gpu/drm/nova/Makefile new file mode 100644 index 000000000..f8527b2b7 --- /dev/null +++ b/drivers/gpu/drm/nova/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_DRM_NOVA) += nova-drm.o +nova-drm-y := nova.o diff --git a/drivers/gpu/drm/nova/driver.rs b/drivers/gpu/drm/nova/driver.rs new file mode 100644 index 000000000..43f15cdfe --- /dev/null +++ b/drivers/gpu/drm/nova/driver.rs @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0 + +use kernel::{ + auxiliary, + device::Core, + drm::{ + self, + gem, + ioctl, // + }, + prelude::*, + sync::aref::ARef, // +}; + +use crate::file::File; +use crate::gem::NovaObject; + +pub(crate) struct NovaDriver; + +pub(crate) struct Nova { + #[expect(unused)] + drm: ARef>, +} + +/// Convienence type alias for the DRM device type for this driver +pub(crate) type NovaDevice = drm::Device; + +#[pin_data] +pub(crate) struct NovaData { + pub(crate) adev: ARef, +} + +const INFO: drm::DriverInfo = drm::DriverInfo { + major: 0, + minor: 0, + patchlevel: 0, + name: c"nova-drm", + desc: c"NVIDIA Graphics and Compute", +}; + +const NOVA_CORE_MODULE_NAME: &CStr = c"nova-core"; +const AUXILIARY_NAME: &CStr = c"nova-drm"; + +kernel::auxiliary_device_table!( + AUX_TABLE, + ::IdInfo, + [( + auxiliary::DeviceId::new(NOVA_CORE_MODULE_NAME, AUXILIARY_NAME), + () + )] +); + +impl auxiliary::Driver for NovaDriver { + type IdInfo = (); + type Data<'bound> = Nova; + const ID_TABLE: auxiliary::IdTable = &AUX_TABLE; + + fn probe<'bound>( + adev: &'bound auxiliary::Device>, + _info: &'bound Self::IdInfo, + ) -> impl PinInit, Error> + 'bound { + let data = try_pin_init!(NovaData { adev: adev.into() }); + + let drm = drm::UnregisteredDevice::::new(adev.as_ref(), data)?; + let drm = drm::Registration::new_foreign_owned(drm, adev.as_ref(), 0)?; + + Ok(Nova { drm: drm.into() }) + } +} + +#[vtable] +impl drm::Driver for NovaDriver { + type Data = NovaData; + type File = File; + type Object = gem::Object; + + const INFO: drm::DriverInfo = INFO; + + kernel::declare_drm_ioctls! { + (NOVA_GETPARAM, drm_nova_getparam, ioctl::RENDER_ALLOW, File::get_param), + (NOVA_GEM_CREATE, drm_nova_gem_create, ioctl::AUTH | ioctl::RENDER_ALLOW, File::gem_create), + (NOVA_GEM_INFO, drm_nova_gem_info, ioctl::AUTH | ioctl::RENDER_ALLOW, File::gem_info), + } +} diff --git a/drivers/gpu/drm/nova/file.rs b/drivers/gpu/drm/nova/file.rs new file mode 100644 index 000000000..a3b7bd367 --- /dev/null +++ b/drivers/gpu/drm/nova/file.rs @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0 + +use crate::driver::{NovaDevice, NovaDriver}; +use crate::gem::NovaObject; +use kernel::{ + alloc::flags::*, + drm::{self, gem::BaseObject}, + pci, + prelude::*, + uapi, +}; + +pub(crate) struct File; + +impl drm::file::DriverFile for File { + type Driver = NovaDriver; + + fn open(_dev: &NovaDevice) -> Result>> { + Ok(KBox::new(Self, GFP_KERNEL)?.into()) + } +} + +impl File { + /// IOCTL: get_param: Query GPU / driver metadata. + pub(crate) fn get_param( + dev: &NovaDevice, + getparam: &mut uapi::drm_nova_getparam, + _file: &drm::File, + ) -> Result { + let adev = &dev.adev; + let parent = adev.parent(); + let pdev: &pci::Device = parent.try_into()?; + + let value = match getparam.param as u32 { + uapi::NOVA_GETPARAM_VRAM_BAR_SIZE => pdev.resource_len(1)?, + _ => return Err(EINVAL), + }; + + getparam.value = Into::::into(value); + + Ok(0) + } + + /// IOCTL: gem_create: Create a new DRM GEM object. + pub(crate) fn gem_create( + dev: &NovaDevice, + req: &mut uapi::drm_nova_gem_create, + file: &drm::File, + ) -> Result { + let obj = NovaObject::new(dev, req.size.try_into()?)?; + + req.handle = obj.create_handle(file)?; + + Ok(0) + } + + /// IOCTL: gem_info: Query GEM metadata. + pub(crate) fn gem_info( + _dev: &NovaDevice, + req: &mut uapi::drm_nova_gem_info, + file: &drm::File, + ) -> Result { + let bo = NovaObject::lookup_handle(file, req.handle)?; + + req.size = bo.size().try_into()?; + + Ok(0) + } +} diff --git a/drivers/gpu/drm/nova/gem.rs b/drivers/gpu/drm/nova/gem.rs new file mode 100644 index 000000000..9d8ff7de2 --- /dev/null +++ b/drivers/gpu/drm/nova/gem.rs @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0 + +use kernel::{ + drm, + drm::{gem, gem::BaseObject, DeviceContext}, + page, + prelude::*, + sync::aref::ARef, +}; + +use crate::{ + driver::{NovaDevice, NovaDriver}, + file::File, +}; + +/// GEM Object inner driver data +#[pin_data] +pub(crate) struct NovaObject {} + +impl gem::DriverObject for NovaObject { + type Driver = NovaDriver; + type Args = (); + + fn new( + _dev: &NovaDevice, + _size: usize, + _args: Self::Args, + ) -> impl PinInit { + try_pin_init!(NovaObject {}) + } +} + +impl NovaObject { + /// Create a new DRM GEM object. + pub(crate) fn new( + dev: &NovaDevice, + size: usize, + ) -> Result>> { + if size == 0 { + return Err(EINVAL); + } + let aligned_size = page::page_align(size).ok_or(EINVAL)?; + + gem::Object::::new(dev, aligned_size, ()) + } + + /// Look up a GEM object handle for a `File` and return an `ObjectRef` for it. + #[inline] + pub(crate) fn lookup_handle( + file: &drm::File, + handle: u32, + ) -> Result>> { + gem::Object::lookup_handle(file, handle) + } +} diff --git a/drivers/gpu/drm/nova/nova.rs b/drivers/gpu/drm/nova/nova.rs new file mode 100644 index 000000000..1fd454c7e --- /dev/null +++ b/drivers/gpu/drm/nova/nova.rs @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Nova DRM Driver + +mod driver; +mod file; +mod gem; + +use crate::driver::NovaDriver; + +kernel::module_auxiliary_driver! { + type: NovaDriver, + name: "nova-drm", + authors: ["Danilo Krummrich"], + description: "Nova GPU driver", + license: "GPL v2", +} -- cgit v1.3.1