summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nova
diff options
context:
space:
mode:
authorEduard Zingerman <eddyz87@gmail.com>2026-09-04 17:05:56 -0700
committerAlexei Starovoitov <ast@kernel.org>2026-09-04 18:17:30 -0700
commit506ada89629ec7059b96ecfb0dc7d33ece0103ca (patch)
tree0b07297409b68d2333fb4f0eae7f3b072eb68d4c /drivers/gpu/drm/nova
downloadlinux-stable-506ada89629ec7059b96ecfb0dc7d33ece0103ca.tar.gz
linux-stable-506ada89629ec7059b96ecfb0dc7d33ece0103ca.zip
bpf: mark a NULL kfunc argument precisegrafted
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 <eddyz87@gmail.com> Link: https://lore.kernel.org/r/20260904-register-is-null-precise-fixes-v1-5-0f5a360ff15d@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'drivers/gpu/drm/nova')
-rw-r--r--drivers/gpu/drm/nova/Kconfig17
-rw-r--r--drivers/gpu/drm/nova/Makefile4
-rw-r--r--drivers/gpu/drm/nova/driver.rs84
-rw-r--r--drivers/gpu/drm/nova/file.rs69
-rw-r--r--drivers/gpu/drm/nova/gem.rs55
-rw-r--r--drivers/gpu/drm/nova/nova.rs17
6 files changed, 246 insertions, 0 deletions
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<drm::Device<NovaDriver>>,
+}
+
+/// Convienence type alias for the DRM device type for this driver
+pub(crate) type NovaDevice<Ctx = drm::Registered> = drm::Device<NovaDriver, Ctx>;
+
+#[pin_data]
+pub(crate) struct NovaData {
+ pub(crate) adev: ARef<auxiliary::Device>,
+}
+
+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,
+ <NovaDriver as auxiliary::Driver>::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<Self::IdInfo> = &AUX_TABLE;
+
+ fn probe<'bound>(
+ adev: &'bound auxiliary::Device<Core<'_>>,
+ _info: &'bound Self::IdInfo,
+ ) -> impl PinInit<Self::Data<'bound>, Error> + 'bound {
+ let data = try_pin_init!(NovaData { adev: adev.into() });
+
+ let drm = drm::UnregisteredDevice::<Self>::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<Ctx: drm::DeviceContext> = gem::Object<NovaObject, Ctx>;
+
+ 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<Pin<KBox<Self>>> {
+ 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<File>,
+ ) -> Result<u32> {
+ 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::<u64>::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<File>,
+ ) -> Result<u32> {
+ 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<File>,
+ ) -> Result<u32> {
+ 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<Ctx: DeviceContext>(
+ _dev: &NovaDevice<Ctx>,
+ _size: usize,
+ _args: Self::Args,
+ ) -> impl PinInit<Self, Error> {
+ try_pin_init!(NovaObject {})
+ }
+}
+
+impl NovaObject {
+ /// Create a new DRM GEM object.
+ pub(crate) fn new<Ctx: DeviceContext>(
+ dev: &NovaDevice<Ctx>,
+ size: usize,
+ ) -> Result<ARef<gem::Object<Self, Ctx>>> {
+ if size == 0 {
+ return Err(EINVAL);
+ }
+ let aligned_size = page::page_align(size).ok_or(EINVAL)?;
+
+ gem::Object::<Self, Ctx>::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<File>,
+ handle: u32,
+ ) -> Result<ARef<gem::Object<Self>>> {
+ 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",
+}