Skip to content

Instantly share code, notes, and snippets.

@stephematician
Last active February 14, 2026 12:00
Show Gist options
  • Select an option

  • Save stephematician/ef10bdf388cc803da68913dc2d54b2a5 to your computer and use it in GitHub Desktop.

Select an option

Save stephematician/ef10bdf388cc803da68913dc2d54b2a5 to your computer and use it in GitHub Desktop.
Patching nvidia-driver-550 for Ubuntu 24.04 and 6.17
diff -u -r a/common/inc/nv-linux.h b/common/inc/nv-linux.h
--- a/common/inc/nv-linux.h 2025-04-08 23:05:21.000000000 +1000
+++ b/common/inc/nv-linux.h 2026-02-14 14:53:46.824504148 +1100
@@ -58,10 +58,8 @@
#include <linux/version.h>
#include <linux/utsname.h>
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
-#error "This driver does not support kernels older than 2.6.32!"
-#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 7, 0)
-# define KERNEL_2_6
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 10)
+#error "This driver does not support kernels older than 3.10!"
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
# define KERNEL_3
#else
@@ -463,6 +461,11 @@
(size) = *(unsigned long *) (ptr); \
}
+/* del_timer_sync fully deprecated in 6.15 */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,15,0)
+#define del_timer_sync timer_delete_sync
+#endif
+
/* keep track of memory usage */
#include "nv-memdbg.h"
@@ -573,21 +576,27 @@
{ \
(ptr) = kmalloc(size, NV_GFP_KERNEL); \
if (ptr) \
+ { \
NV_MEMDBG_ADD(ptr, size); \
+ } \
}
#define NV_KZALLOC(ptr, size) \
{ \
(ptr) = kzalloc(size, NV_GFP_KERNEL); \
if (ptr) \
+ { \
NV_MEMDBG_ADD(ptr, size); \
+ } \
}
#define NV_KMALLOC_ATOMIC(ptr, size) \
{ \
(ptr) = kmalloc(size, NV_GFP_ATOMIC); \
if (ptr) \
+ { \
NV_MEMDBG_ADD(ptr, size); \
+ } \
}
#if defined(__GFP_RETRY_MAYFAIL)
@@ -602,7 +611,9 @@
{ \
(ptr) = kmalloc(size, NV_GFP_NO_OOM); \
if (ptr) \
+ { \
NV_MEMDBG_ADD(ptr, size); \
+ } \
}
#define NV_KFREE(ptr, size) \
diff -u -r a/common/inc/nv-mm.h b/common/inc/nv-mm.h
--- a/common/inc/nv-mm.h 2025-04-08 23:04:58.000000000 +1000
+++ b/common/inc/nv-mm.h 2026-02-14 20:37:30.809345552 +1100
@@ -295,9 +295,25 @@
#endif
}
+#if NV_IS_EXPORT_SYMBOL_GPL___vma_start_write
+#undef NV_CAN_CALL_VMA_START_WRITE
+#else
+#define NV_CAN_CALL_VMA_START_WRITE
+#endif
+
+#if !defined(NV_CAN_CALL_VMA_START_WRITE) && \
+ defined(NV_VM_AREA_STRUCT_HAS_VM_REFCNT)
+/* local non-GPL implementation of start VMA write */
+void nv_vma_start_write(struct vm_area_struct *);
+#endif
+
static inline void nv_vm_flags_set(struct vm_area_struct *vma, vm_flags_t flags)
{
-#if defined(NV_VM_AREA_STRUCT_HAS_CONST_VM_FLAGS)
+#if !defined(NV_CAN_CALL_VMA_START_WRITE) && \
+ defined(NV_VM_AREA_STRUCT_HAS_VM_REFCNT)
+ nv_vma_start_write(vma);
+ ACCESS_PRIVATE(vma, __vm_flags) |= flags;
+#elif defined(NV_VM_AREA_STRUCT_HAS_CONST_VM_FLAGS)
vm_flags_set(vma, flags);
#else
vma->vm_flags |= flags;
@@ -306,7 +322,11 @@
static inline void nv_vm_flags_clear(struct vm_area_struct *vma, vm_flags_t flags)
{
-#if defined(NV_VM_AREA_STRUCT_HAS_CONST_VM_FLAGS)
+#if !defined(NV_CAN_CALL_VMA_START_WRITE) && \
+ defined(NV_VM_AREA_STRUCT_HAS_VM_REFCNT)
+ nv_vma_start_write(vma);
+ ACCESS_PRIVATE(vma, __vm_flags) &= ~flags;
+#elif defined(NV_VM_AREA_STRUCT_HAS_CONST_VM_FLAGS)
vm_flags_clear(vma, flags);
#else
vma->vm_flags &= ~flags;
diff -u -r a/common/inc/nv-proto.h b/common/inc/nv-proto.h
--- a/common/inc/nv-proto.h 2025-04-08 23:05:21.000000000 +1000
+++ b/common/inc/nv-proto.h 2026-02-08 14:14:17.771473795 +1100
@@ -41,7 +41,7 @@
int nvidia_mmap (struct file *, struct vm_area_struct *);
int nvidia_mmap_helper (nv_state_t *, nv_linux_file_private_t *, nvidia_stack_t *, struct vm_area_struct *, void *);
-int nv_encode_caching (pgprot_t *, NvU32, NvU32);
+int nv_encode_caching (pgprot_t *, NvU32, nv_memory_type_t);
void nv_revoke_gpu_mappings_locked(nv_state_t *);
NvUPtr nv_vm_map_pages (struct page **, NvU32, NvBool, NvBool);
diff -u -r a/conftest.sh b/conftest.sh
--- a/conftest.sh 2025-04-08 21:43:04.000000000 +1000
+++ b/conftest.sh 2026-02-14 19:11:34.846647063 +1100
@@ -151,18 +151,18 @@
fi
# Add the mach-default includes (only found on x86/older kernels)
- MACH_CFLAGS="$MACH_CFLAGS -I$SOURCE_HEADERS/asm-$KERNEL_ARCH/mach-default"
MACH_CFLAGS="$MACH_CFLAGS -I$SOURCE_ARCH_HEADERS/asm/mach-default"
+ MACH_CFLAGS="$MACH_CFLAGS -I$SOURCE_HEADERS/asm-$KERNEL_ARCH/mach-default"
CFLAGS="$BASE_CFLAGS $MACH_CFLAGS $OUTPUT_CFLAGS -include $AUTOCONF_FILE"
- CFLAGS="$CFLAGS -I$SOURCE_HEADERS"
- CFLAGS="$CFLAGS -I$SOURCE_HEADERS/uapi"
- CFLAGS="$CFLAGS -I$SOURCE_HEADERS/xen"
- CFLAGS="$CFLAGS -I$OUTPUT_HEADERS/generated/uapi"
CFLAGS="$CFLAGS -I$SOURCE_ARCH_HEADERS"
CFLAGS="$CFLAGS -I$SOURCE_ARCH_HEADERS/uapi"
CFLAGS="$CFLAGS -I$OUTPUT_ARCH_HEADERS/generated"
CFLAGS="$CFLAGS -I$OUTPUT_ARCH_HEADERS/generated/uapi"
+ CFLAGS="$CFLAGS -I$SOURCE_HEADERS"
+ CFLAGS="$CFLAGS -I$SOURCE_HEADERS/uapi"
+ CFLAGS="$CFLAGS -I$SOURCE_HEADERS/xen"
+ CFLAGS="$CFLAGS -I$OUTPUT_HEADERS/generated/uapi"
if [ -n "$BUILD_PARAMS" ]; then
CFLAGS="$CFLAGS -D$BUILD_PARAMS"
@@ -2467,60 +2467,36 @@
compile_check_conftest "$CODE" "NV_PCI_STOP_AND_REMOVE_BUS_DEVICE_PRESENT" "" "functions"
;;
- drm_helper_mode_fill_fb_struct | drm_helper_mode_fill_fb_struct_has_const_mode_cmd_arg)
- #
- # Determine if the drm_helper_mode_fill_fb_struct function takes
- # 'dev' argument.
- #
- # The drm_helper_mode_fill_fb_struct() has been updated to
- # take 'dev' parameter by commit a3f913ca9892 ("drm: Pass 'dev'
- # to drm_helper_mode_fill_fb_struct()") in v4.11 (2016-12-14)
- #
+ drm_helper_mode_fill_fb_struct)
+ # stephematician patch: the definitions are not included in
+ # drm_crtc_helper since kernel 6.3, now they belong to
+ # drm_modeset_helper; therefore we drop all tests relevant to
+ # earlier kernels and just check to see if a
+ # `struct drm_format_info *` is passed into
+ # drm_helper_mode_fill_fb_struct(). If so, it will have 4 arguments.
+ # This parameter was added in commit a34cc7bf1034 ("drm:
+ # Allow the caller to pass in the format info to
+ # drm_helper_mode_fill_fb_struct()") in linux-next
+ # (2025-07-16)
echo "$CONFTEST_PREAMBLE
- #include <drm/drm_crtc_helper.h>
- void drm_helper_mode_fill_fb_struct(struct drm_device *dev,
- struct drm_framebuffer *fb,
- const struct drm_mode_fb_cmd2 *mode_cmd)
- {
- return;
- }" > conftest$$.c;
+ #include <stddef.h>
+ #include <drm/drm_modeset_helper.h>
+
+ void conftest_drm_fill_fb_struct_takes_format_info(void) {
+ drm_helper_mode_fill_fb_struct(NULL, NULL, NULL, NULL);
+ }" > conftest$$.c
$CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
rm -f conftest$$.c
if [ -f conftest$$.o ]; then
- echo "#define NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_DEV_ARG" | append_conftest "function"
- echo "#define NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_CONST_MODE_CMD_ARG" | append_conftest "function"
+ echo "#define NV_DRM_FILL_FB_STRUCT_TAKES_FORMAT_INFO" | append_conftest "types"
rm -f conftest$$.o
- else
- echo "#undef NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_DEV_ARG" | append_conftest "function"
-
- #
- # Determine if the drm_mode_fb_cmd2 pointer argument is const in
- # drm_mode_config_funcs::fb_create and drm_helper_mode_fill_fb_struct().
- #
- # The drm_mode_fb_cmd2 pointer through this call chain was made
- # const by commit 1eb83451ba55 ("drm: Pass the user drm_mode_fb_cmd2
- # as const to .fb_create()") in v4.5 (2015-11-11)
- #
- echo "$CONFTEST_PREAMBLE
- #include <drm/drm_crtc_helper.h>
- void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
- const struct drm_mode_fb_cmd2 *mode_cmd)
- {
- return;
- }" > conftest$$.c;
+ return
+ fi
- $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
- rm -f conftest$$.c
+ echo "#undef NV_DRM_FILL_FB_STRUCT_TAKES_FORMAT_INFO" | append_conftest "types"
- if [ -f conftest$$.o ]; then
- echo "#define NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_CONST_MODE_CMD_ARG" | append_conftest "function"
- rm -f conftest$$.o
- else
- echo "#undef NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_CONST_MODE_CMD_ARG" | append_conftest "function"
- fi
- fi
;;
file_operations_fop_unsigned_offset_present)
@@ -6132,7 +6108,7 @@
echo "#include <generated/utsrelease.h>
UTS_RELEASE" > conftest$$.c
- $CC $CFLAGS -E -P conftest$$.c
+ $CC $CFLAGS -E -P conftest$$.c | sed '/^$/d'
rm -f conftest$$.c
;;
@@ -6525,6 +6501,20 @@
compile_check_conftest "$CODE" "NV_VM_AREA_STRUCT_HAS_CONST_VM_FLAGS" "" "types"
;;
+ vm_area_struct_has_vm_refcnt)
+ #
+ # Determine if the 'vm_area_struct' structure has a 'vm_refcnt' field.
+ #
+ CODE="
+ #include <linux/mm_types.h>
+
+ int conftest_vm_area_struct_has_vm_refcnt(void) {
+ return offsetof(struct vm_area_struct, vm_refcnt);
+ }"
+
+ compile_check_conftest "$CODE" "NV_VM_AREA_STRUCT_HAS_VM_REFCNT" "" "types"
+ ;;
+
drm_driver_has_dumb_destroy)
#
# Determine if the 'drm_driver' structure has a 'dumb_destroy'
@@ -7441,7 +7431,7 @@
if [ -n "$VGX_BUILD" ]; then
if [ -f /proc/xen/capabilities ]; then
- if [ "`cat /proc/xen/capabilities`" == "control_d" ]; then
+ if [ "`cat /proc/xen/capabilities`" = "control_d" ]; then
exit 0
fi
else
diff -u -r a/header-presence-tests.mk b/header-presence-tests.mk
--- a/header-presence-tests.mk 2025-04-08 21:43:04.000000000 +1000
+++ b/header-presence-tests.mk 2026-02-14 15:11:34.174700792 +1100
@@ -30,6 +30,7 @@
drm/drm_device.h \
drm/drm_mode_config.h \
drm/drm_modeset_lock.h \
+ drm/clients/drm_client_setup.h \
dt-bindings/interconnect/tegra_icc_id.h \
generated/autoconf.h \
generated/compile.h \
diff -u -r a/Kbuild b/Kbuild
--- a/Kbuild 2025-04-08 23:05:17.000000000 +1000
+++ b/Kbuild 2026-02-14 18:27:09.842404069 +1100
@@ -75,21 +75,14 @@
$(eval include $(src)/$(_module)/$(_module).Kbuild))
-#
-# Define CFLAGS that apply to all the NVIDIA kernel modules. EXTRA_CFLAGS
-# is deprecated since 2.6.24 in favor of ccflags-y, but we need to support
-# older kernels which do not have ccflags-y. Newer kernels append
-# $(EXTRA_CFLAGS) to ccflags-y for compatibility.
-#
-
-EXTRA_CFLAGS += -I$(src)/common/inc
-EXTRA_CFLAGS += -I$(src)
-EXTRA_CFLAGS += -Wall $(DEFINES) $(INCLUDES) -Wno-cast-qual -Wno-format-extra-args
-EXTRA_CFLAGS += -D__KERNEL__ -DMODULE -DNVRM
-EXTRA_CFLAGS += -DNV_VERSION_STRING=\"550.163.01\"
+ccflags-y += -I$(src)/common/inc
+ccflags-y += -I$(src)
+ccflags-y += -Wall $(DEFINES) $(INCLUDES) -Wno-cast-qual -Wno-format-extra-args
+ccflags-y += -D__KERNEL__ -DMODULE -DNVRM
+ccflags-y += -DNV_VERSION_STRING=\"550.163.01\"
ifneq ($(SYSSRCHOST1X),)
- EXTRA_CFLAGS += -I$(SYSSRCHOST1X)
+ ccflags-y += -I$(SYSSRCHOST1X)
endif
# Some Android kernels prohibit driver use of filesystem functions like
@@ -99,57 +92,57 @@
PLATFORM_IS_ANDROID ?= 0
ifeq ($(PLATFORM_IS_ANDROID),1)
- EXTRA_CFLAGS += -DNV_FILESYSTEM_ACCESS_AVAILABLE=0
+ ccflags-y += -DNV_FILESYSTEM_ACCESS_AVAILABLE=0
else
- EXTRA_CFLAGS += -DNV_FILESYSTEM_ACCESS_AVAILABLE=1
+ ccflags-y += -DNV_FILESYSTEM_ACCESS_AVAILABLE=1
endif
-EXTRA_CFLAGS += -Wno-unused-function
+ccflags-y += -Wno-unused-function
ifneq ($(NV_BUILD_TYPE),debug)
- EXTRA_CFLAGS += -Wuninitialized
+ ccflags-y += -Wuninitialized
endif
-EXTRA_CFLAGS += -fno-strict-aliasing
+ccflags-y += -fno-strict-aliasing
ifeq ($(ARCH),arm64)
- EXTRA_CFLAGS += -mstrict-align
+ ccflags-y += -mstrict-align
endif
ifeq ($(NV_BUILD_TYPE),debug)
- EXTRA_CFLAGS += -g
+ ccflags-y += -g
endif
-EXTRA_CFLAGS += -ffreestanding
+ccflags-y += -ffreestanding
ifeq ($(ARCH),arm64)
- EXTRA_CFLAGS += -mgeneral-regs-only -march=armv8-a
- EXTRA_CFLAGS += $(call cc-option,-mno-outline-atomics,)
+ ccflags-y += -mgeneral-regs-only -march=armv8-a
+ ccflags-y += $(call cc-option,-mno-outline-atomics,)
endif
ifeq ($(ARCH),x86_64)
- EXTRA_CFLAGS += -mno-red-zone -mcmodel=kernel
+ ccflags-y += -mno-red-zone -mcmodel=kernel
endif
ifeq ($(ARCH),powerpc)
- EXTRA_CFLAGS += -mlittle-endian -mno-strict-align -mno-altivec
+ ccflags-y += -mlittle-endian -mno-strict-align
endif
-EXTRA_CFLAGS += -DNV_UVM_ENABLE
-EXTRA_CFLAGS += $(call cc-option,-Werror=undef,)
-EXTRA_CFLAGS += -DNV_SPECTRE_V2=$(NV_SPECTRE_V2)
-EXTRA_CFLAGS += -DNV_KERNEL_INTERFACE_LAYER
+ccflags-y += -DNV_UVM_ENABLE
+ccflags-y += $(call cc-option,-Werror=undef,)
+ccflags-y += -DNV_SPECTRE_V2=$(NV_SPECTRE_V2)
+ccflags-y += -DNV_KERNEL_INTERFACE_LAYER
#
# Detect SGI UV systems and apply system-specific optimizations.
#
ifneq ($(wildcard /proc/sgi_uv),)
- EXTRA_CFLAGS += -DNV_CONFIG_X86_UV
+ ccflags-y += -DNV_CONFIG_X86_UV
endif
ifdef VGX_FORCE_VFIO_PCI_CORE
- EXTRA_CFLAGS += -DNV_VGPU_FORCE_VFIO_PCI_CORE
+ ccflags-y += -DNV_VGPU_FORCE_VFIO_PCI_CORE
endif
WARNINGS_AS_ERRORS ?=
@@ -179,14 +172,16 @@
NV_CONFTEST_HEADER := $(obj)/conftest/headers.h
NV_CONFTEST_CMD := /bin/sh $(NV_CONFTEST_SCRIPT) \
- "$(CC)" $(ARCH) $(NV_KERNEL_SOURCES) $(NV_KERNEL_OUTPUT)
+ "$(strip $(CC))" $(ARCH) $(NV_KERNEL_SOURCES) $(NV_KERNEL_OUTPUT)
NV_CFLAGS_FROM_CONFTEST := $(shell $(NV_CONFTEST_CMD) build_cflags)
-NV_CONFTEST_CFLAGS = $(NV_CFLAGS_FROM_CONFTEST) $(EXTRA_CFLAGS) -fno-pie
+NV_CONFTEST_CFLAGS = $(NV_CFLAGS_FROM_CONFTEST) $(ccflags-y) -fno-pie
+NV_CONFTEST_CFLAGS += $(filter -std=%,$(KBUILD_CFLAGS))
NV_CONFTEST_CFLAGS += $(call cc-disable-warning,pointer-sign)
NV_CONFTEST_CFLAGS += $(call cc-option,-fshort-wchar,)
NV_CONFTEST_CFLAGS += $(call cc-option,-Werror=incompatible-pointer-types,)
+NV_CONFTEST_CFLAGS += $(call cc-option,-fms-extensions,)
NV_CONFTEST_CFLAGS += -Wno-error
NV_CONFTEST_COMPILE_TEST_HEADERS := $(obj)/conftest/macros.h
diff -u -r a/nvidia/libspdm_aead.c b/nvidia/libspdm_aead.c
--- a/nvidia/libspdm_aead.c 2025-04-08 23:04:54.000000000 +1000
+++ b/nvidia/libspdm_aead.c 2026-02-08 14:12:34.300268149 +1100
@@ -38,7 +38,7 @@
};
#endif
-int libspdm_aead_prealloc(void **context, char const *alg)
+static int libspdm_aead_prealloc(void **context, char const *alg)
{
#ifndef USE_LKCA
return -ENODEV;
@@ -175,14 +175,14 @@
}
#endif
-int libspdm_aead_prealloced(void *context,
- const uint8_t *key, size_t key_size,
- const uint8_t *iv, size_t iv_size,
- const uint8_t *a_data, size_t a_data_size,
- const uint8_t *data_in, size_t data_in_size,
- uint8_t *tag, size_t tag_size,
- uint8_t *data_out, size_t *data_out_size,
- bool enc)
+static int libspdm_aead_prealloced(void *context,
+ const uint8_t *key, size_t key_size,
+ const uint8_t *iv, size_t iv_size,
+ const uint8_t *a_data, size_t a_data_size,
+ const uint8_t *data_in, size_t data_in_size,
+ uint8_t *tag, size_t tag_size,
+ uint8_t *data_out, size_t *data_out_size,
+ bool enc)
{
#ifndef USE_LKCA
return -ENODEV;
diff -u -r a/nvidia/nvidia.Kbuild b/nvidia/nvidia.Kbuild
--- a/nvidia/nvidia.Kbuild 2025-04-08 23:04:54.000000000 +1000
+++ b/nvidia/nvidia.Kbuild 2026-02-14 20:21:23.995474658 +1100
@@ -235,6 +235,7 @@
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_present_follow_pfnmap_start
NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_gpl_pci_ats_supported
NV_CONFTEST_SYMBOL_COMPILE_TESTS += ecc_digits_from_bytes
+NV_CONFTEST_SYMBOL_COMPILE_TESTS += is_export_symbol_gpl___vma_start_write
NV_CONFTEST_TYPE_COMPILE_TESTS += dma_ops
NV_CONFTEST_TYPE_COMPILE_TESTS += swiotlb_dma_ops
@@ -256,6 +257,7 @@
NV_CONFTEST_TYPE_COMPILE_TESTS += num_registered_fb
NV_CONFTEST_TYPE_COMPILE_TESTS += pci_driver_has_driver_managed_dma
NV_CONFTEST_TYPE_COMPILE_TESTS += vm_area_struct_has_const_vm_flags
+NV_CONFTEST_TYPE_COMPILE_TESTS += vm_area_struct_has_vm_refcnt
NV_CONFTEST_TYPE_COMPILE_TESTS += memory_failure_has_trapno_arg
NV_CONFTEST_TYPE_COMPILE_TESTS += foll_longterm_present
NV_CONFTEST_TYPE_COMPILE_TESTS += bus_type_has_iommu_ops
diff -u -r a/nvidia/nv-mmap.c b/nvidia/nv-mmap.c
--- a/nvidia/nv-mmap.c 2025-04-08 23:05:18.000000000 +1000
+++ b/nvidia/nv-mmap.c 2026-02-14 20:50:44.189241194 +1100
@@ -837,3 +837,80 @@
nvl->safe_to_mmap = safe_to_mmap;
}
+
+#if !defined(NV_CAN_CALL_VMA_START_WRITE) && \
+ defined(NV_VM_AREA_STRUCT_HAS_VM_REFCNT)
+static NvBool nv_vma_enter_locked(struct vm_area_struct *vma, NvBool detaching)
+{
+ NvU32 tgt_refcnt = VMA_LOCK_OFFSET;
+ NvBool interrupted = NV_FALSE;
+ if (!detaching)
+ {
+ tgt_refcnt++;
+ }
+ // rmmap_assert_write_locked(vma->vm_mm);
+ if (!refcount_add_not_zero(VMA_LOCK_OFFSET, &vma->vm_refcnt))
+ {
+ return NV_FALSE;
+ }
+
+ rwsem_acquire(&vma->vmlock_dep_map, 0, 0, _RET_IP_);
+ prepare_to_rcuwait(&vma->vm_mm->vma_writer_wait);
+
+ for (;;)
+ {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ if (refcount_read(&vma->vm_refcnt) == tgt_refcnt)
+ break;
+
+ if (signal_pending_state(TASK_UNINTERRUPTIBLE, current))
+ {
+ interrupted = NV_TRUE;
+ break;
+ }
+
+ schedule();
+ }
+
+ // This is an open-coded version of finish_rcuwait().
+ rcu_assign_pointer(vma->vm_mm->vma_writer_wait.task, NULL);
+ __set_current_state(TASK_RUNNING);
+
+ if (interrupted)
+ {
+ // Clean up on error: release refcount and dep_map
+ refcount_sub_and_test(VMA_LOCK_OFFSET, &vma->vm_refcnt);
+ rwsem_release(&vma->vmlock_dep_map, _RET_IP_);
+ return NV_FALSE;
+ }
+
+ lock_acquired(&vma->vmlock_dep_map, _RET_IP_);
+ return NV_TRUE;
+}
+
+/*
+ * Helper function to handle VMA locking and refcount management.
+ * see mm/mmap_lock.c and mmap_lock.h for more general approach
+ */
+void nv_vma_start_write(struct vm_area_struct *vma)
+{
+ NvU32 mm_lock_seq;
+ NvBool locked;
+ if (__is_vma_write_locked(vma, &mm_lock_seq))
+ return;
+
+ locked = nv_vma_enter_locked(vma, NV_FALSE);
+ if (!locked)
+ return;
+
+ WRITE_ONCE(vma->vm_lock_seq, mm_lock_seq);
+ if (locked)
+ {
+ NvBool detached;
+ detached = refcount_sub_and_test(VMA_LOCK_OFFSET, &vma->vm_refcnt);
+ rwsem_release(&vma->vmlock_dep_map, _RET_IP_);
+ WARN_ON_ONCE(detached);
+ }
+}
+EXPORT_SYMBOL(nv_vma_start_write);
+#endif
diff -u -r a/nvidia-drm/nvidia-drm-drv.c b/nvidia-drm/nvidia-drm-drv.c
--- a/nvidia-drm/nvidia-drm-drv.c 2025-04-08 22:08:07.000000000 +1000
+++ b/nvidia-drm/nvidia-drm-drv.c 2026-02-14 19:36:14.502799698 +1100
@@ -78,6 +78,8 @@
#if defined(NV_DRM_DRM_CLIENT_SETUP_H_PRESENT)
#include <drm/drm_client_setup.h>
+#elif defined(NV_DRM_CLIENTS_DRM_CLIENT_SETUP_H_PRESENT)
+#include <drm/clients/drm_client_setup.h>
#endif
#if defined(NV_DRM_DRM_FBDEV_TTM_H_PRESENT)
@@ -186,11 +188,10 @@
static struct drm_framebuffer *nv_drm_framebuffer_create(
struct drm_device *dev,
struct drm_file *file,
- #if defined(NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_CONST_MODE_CMD_ARG)
- const struct drm_mode_fb_cmd2 *cmd
- #else
- struct drm_mode_fb_cmd2 *cmd
+ #if defined(NV_DRM_FILL_FB_STRUCT_TAKES_FORMAT_INFO)
+ const struct drm_format_info *info,
#endif
+ const struct drm_mode_fb_cmd2 *cmd
)
{
struct drm_mode_fb_cmd2 local_cmd;
@@ -201,12 +202,11 @@
fb = nv_drm_internal_framebuffer_create(
dev,
file,
+ #if defined(NV_DRM_FILL_FB_STRUCT_TAKES_FORMAT_INFO)
+ info,
+ #endif
&local_cmd);
- #if !defined(NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_CONST_MODE_CMD_ARG)
- *cmd = local_cmd;
- #endif
-
return fb;
}
@@ -1785,6 +1785,7 @@
struct nv_drm_device *nv_dev = NULL;
struct drm_device *dev = NULL;
struct device *device = gpu_info->os_device_ptr;
+ bool bus_is_pci;
DRM_DEBUG(
"Registering device for NVIDIA GPU ID 0x08%x",
@@ -1818,7 +1819,7 @@
dev->dev_private = nv_dev;
nv_dev->dev = dev;
- bool bus_is_pci =
+ bus_is_pci =
#if defined(NV_LINUX)
device->bus == &pci_bus_type;
#elif defined(NV_BSD)
diff -u -r a/nvidia-drm/nvidia-drm-fb.c b/nvidia-drm/nvidia-drm-fb.c
--- a/nvidia-drm/nvidia-drm-fb.c 2025-04-08 22:08:08.000000000 +1000
+++ b/nvidia-drm/nvidia-drm-fb.c 2026-02-09 21:39:07.071222041 +1100
@@ -84,7 +84,7 @@
static struct nv_drm_framebuffer *nv_drm_framebuffer_alloc(
struct drm_device *dev,
struct drm_file *file,
- struct drm_mode_fb_cmd2 *cmd)
+ const struct drm_mode_fb_cmd2 *cmd)
{
struct nv_drm_device *nv_dev = to_nv_device(dev);
struct nv_drm_framebuffer *nv_fb;
@@ -206,7 +206,10 @@
struct drm_framebuffer *nv_drm_internal_framebuffer_create(
struct drm_device *dev,
struct drm_file *file,
- struct drm_mode_fb_cmd2 *cmd)
+ #if defined(NV_DRM_FILL_FB_STRUCT_TAKES_FORMAT_INFO)
+ const struct drm_format_info *info,
+ #endif
+ const struct drm_mode_fb_cmd2 *cmd)
{
struct nv_drm_device *nv_dev = to_nv_device(dev);
struct nv_drm_framebuffer *nv_fb;
@@ -255,10 +258,11 @@
/* Fill out framebuffer metadata from the userspace fb creation request */
drm_helper_mode_fill_fb_struct(
- #if defined(NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_DEV_ARG)
dev,
- #endif
&nv_fb->base,
+ #if defined(NV_DRM_FILL_FB_STRUCT_TAKES_FORMAT_INFO)
+ info,
+ #endif
cmd);
/*
diff -u -r a/nvidia-drm/nvidia-drm-fb.h b/nvidia-drm/nvidia-drm-fb.h
--- a/nvidia-drm/nvidia-drm-fb.h 2025-04-08 22:08:06.000000000 +1000
+++ b/nvidia-drm/nvidia-drm-fb.h 2026-02-08 20:49:27.566704043 +1100
@@ -59,7 +59,10 @@
struct drm_framebuffer *nv_drm_internal_framebuffer_create(
struct drm_device *dev,
struct drm_file *file,
- struct drm_mode_fb_cmd2 *cmd);
+ #if defined(NV_DRM_FILL_FB_STRUCT_TAKES_FORMAT_INFO)
+ const struct drm_format_info *info,
+ #endif
+ const struct drm_mode_fb_cmd2 *cmd);
#endif /* NV_DRM_ATOMIC_MODESET_AVAILABLE */
diff -u -r a/nvidia-drm/nvidia-drm-os-interface.c b/nvidia-drm/nvidia-drm-os-interface.c
--- a/nvidia-drm/nvidia-drm-os-interface.c 2025-04-08 22:08:06.000000000 +1000
+++ b/nvidia-drm/nvidia-drm-os-interface.c 2026-02-08 21:56:27.469852153 +1100
@@ -31,12 +31,17 @@
#include <linux/sync_file.h>
#endif
+#include <linux/version.h>
#include <linux/vmalloc.h>
#include <linux/sched.h>
#include <linux/device.h>
#include "nv-mm.h"
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,15,0)
+#define del_timer_sync timer_delete_sync
+#endif
+
#if defined(NV_DRM_DRMP_H_PRESENT)
#include <drm/drmP.h>
#endif
diff -u -r a/nvidia-drm/nvidia-drm-sources.mk b/nvidia-drm/nvidia-drm-sources.mk
--- a/nvidia-drm/nvidia-drm-sources.mk 2025-04-08 22:05:11.000000000 +1000
+++ b/nvidia-drm/nvidia-drm-sources.mk 2026-02-14 19:10:55.227016220 +1100
@@ -37,6 +37,7 @@
NV_CONFTEST_GENERIC_COMPILE_TESTS += drm_alpha_blending_available
NV_CONFTEST_GENERIC_COMPILE_TESTS += is_export_symbol_present_drm_gem_prime_fd_to_handle
NV_CONFTEST_GENERIC_COMPILE_TESTS += is_export_symbol_present_drm_gem_prime_handle_to_fd
+NV_CONFTEST_GENERIC_COMPILE_TESTS += is_export_symbol_gpl___vma_start_write
NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_dev_unref
NV_CONFTEST_FUNCTION_COMPILE_TESTS += drm_reinit_primary_mode_group
@@ -128,6 +129,7 @@
NV_CONFTEST_TYPE_COMPILE_TESTS += drm_connector_lookup
NV_CONFTEST_TYPE_COMPILE_TESTS += drm_connector_put
NV_CONFTEST_TYPE_COMPILE_TESTS += vm_area_struct_has_const_vm_flags
+NV_CONFTEST_TYPE_COMPILE_TESTS += vm_area_struct_has_vm_refcnt
NV_CONFTEST_TYPE_COMPILE_TESTS += drm_driver_has_dumb_destroy
NV_CONFTEST_TYPE_COMPILE_TESTS += fence_ops_use_64bit_seqno
NV_CONFTEST_TYPE_COMPILE_TESTS += drm_aperture_remove_conflicting_pci_framebuffers_has_driver_arg
diff -u -r a/nvidia-modeset/nvidia-modeset-linux.c b/nvidia-modeset/nvidia-modeset-linux.c
--- a/nvidia-modeset/nvidia-modeset-linux.c 2025-04-08 22:09:38.000000000 +1000
+++ b/nvidia-modeset/nvidia-modeset-linux.c 2026-02-08 16:18:17.271789209 +1100
@@ -23,6 +23,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/version.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/delay.h>
@@ -107,6 +108,10 @@
module_param_named(config_file, nvkms_conf, charp, 0400);
#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,15,0)
+#define del_timer_sync timer_delete_sync
+#endif
+
static atomic_t nvkms_alloc_called_count;
NvBool nvkms_output_rounding_fix(void)
diff -u -r a/nvidia-uvm/nvidia-uvm.Kbuild b/nvidia-uvm/nvidia-uvm.Kbuild
--- a/nvidia-uvm/nvidia-uvm.Kbuild 2025-04-08 23:04:54.000000000 +1000
+++ b/nvidia-uvm/nvidia-uvm.Kbuild 2026-02-14 19:11:08.628891232 +1100
@@ -90,6 +90,7 @@
NV_CONFTEST_TYPE_COMPILE_TESTS += migrate_vma_added_flags
NV_CONFTEST_TYPE_COMPILE_TESTS += migrate_device_range
NV_CONFTEST_TYPE_COMPILE_TESTS += vm_area_struct_has_const_vm_flags
+NV_CONFTEST_TYPE_COMPILE_TESTS += vm_area_struct_has_vm_refcnt
NV_CONFTEST_TYPE_COMPILE_TESTS += handle_mm_fault_has_mm_arg
NV_CONFTEST_TYPE_COMPILE_TESTS += handle_mm_fault_has_pt_regs_arg
NV_CONFTEST_TYPE_COMPILE_TESTS += mempolicy_has_unified_nodes
diff -u -r a/nvidia-uvm/uvm_channel_test.c b/nvidia-uvm/uvm_channel_test.c
--- a/nvidia-uvm/uvm_channel_test.c 2025-04-08 23:05:16.000000000 +1000
+++ b/nvidia-uvm/uvm_channel_test.c 2026-02-08 14:31:07.545606195 +1100
@@ -723,7 +723,7 @@
// This test verifies that concurrent pushes using the same channel pool
// select different channels, when the Confidential Computing feature is
// enabled.
-NV_STATUS test_conf_computing_channel_selection(uvm_va_space_t *va_space)
+static NV_STATUS test_conf_computing_channel_selection(uvm_va_space_t *va_space)
{
NV_STATUS status = NV_OK;
uvm_push_t *pushes = NULL;
@@ -796,7 +796,7 @@
return status;
}
-NV_STATUS test_channel_iv_rotation(uvm_va_space_t *va_space)
+static NV_STATUS test_channel_iv_rotation(uvm_va_space_t *va_space)
{
uvm_gpu_t *gpu;
@@ -1203,7 +1203,7 @@
return NV_OK;
}
-NV_STATUS test_write_ctrl_gpfifo_noop(uvm_va_space_t *va_space)
+static NV_STATUS test_write_ctrl_gpfifo_noop(uvm_va_space_t *va_space)
{
uvm_gpu_t *gpu;
@@ -1242,7 +1242,7 @@
return NV_OK;
}
-NV_STATUS test_write_ctrl_gpfifo_and_pushes(uvm_va_space_t *va_space)
+static NV_STATUS test_write_ctrl_gpfifo_and_pushes(uvm_va_space_t *va_space)
{
uvm_gpu_t *gpu;
@@ -1290,7 +1290,7 @@
return NV_OK;
}
-NV_STATUS test_write_ctrl_gpfifo_tight(uvm_va_space_t *va_space)
+static NV_STATUS test_write_ctrl_gpfifo_tight(uvm_va_space_t *va_space)
{
NV_STATUS status = NV_OK;
uvm_gpu_t *gpu;
diff -u -r a/nvidia-uvm/uvm_gpu_semaphore.c b/nvidia-uvm/uvm_gpu_semaphore.c
--- a/nvidia-uvm/uvm_gpu_semaphore.c 2025-04-08 23:05:06.000000000 +1000
+++ b/nvidia-uvm/uvm_gpu_semaphore.c 2026-02-08 13:35:52.616292179 +1100
@@ -585,7 +585,7 @@
return true;
}
-bool tracking_semaphore_uses_mutex(uvm_gpu_tracking_semaphore_t *tracking_semaphore)
+static bool tracking_semaphore_uses_mutex(uvm_gpu_tracking_semaphore_t *tracking_semaphore)
{
UVM_ASSERT(tracking_semaphore_check_gpu(tracking_semaphore));
diff -u -r a/nvidia-uvm/uvm_hopper_fault_buffer.c b/nvidia-uvm/uvm_hopper_fault_buffer.c
--- a/nvidia-uvm/uvm_hopper_fault_buffer.c 2025-04-08 23:05:12.000000000 +1000
+++ b/nvidia-uvm/uvm_hopper_fault_buffer.c 2026-02-08 14:25:58.490970962 +1100
@@ -21,6 +21,7 @@
*******************************************************************************/
+#include "uvm_hal.h"
#include "uvm_hal_types.h"
#include "hwref/hopper/gh100/dev_fault.h"
diff -u -r a/nvidia-uvm/uvm_maxwell_mmu.c b/nvidia-uvm/uvm_maxwell_mmu.c
--- a/nvidia-uvm/uvm_maxwell_mmu.c 2025-04-08 23:05:10.000000000 +1000
+++ b/nvidia-uvm/uvm_maxwell_mmu.c 2026-02-08 14:23:24.056242563 +1100
@@ -38,6 +38,7 @@
#include "uvm_forward_decl.h"
#include "uvm_gpu.h"
#include "uvm_mmu.h"
+#include "uvm_hal.h"
#include "uvm_push_macros.h"
#include "hwref/maxwell/gm107/dev_mmu.h"
diff -u -r a/nvidia-uvm/uvm_migrate_pageable.c b/nvidia-uvm/uvm_migrate_pageable.c
--- a/nvidia-uvm/uvm_migrate_pageable.c 2025-04-08 23:05:14.000000000 +1000
+++ b/nvidia-uvm/uvm_migrate_pageable.c 2026-02-14 17:54:34.061620472 +1100
@@ -507,7 +507,7 @@
return NV_OK;
}
-void migrate_vma_cleanup_pages(unsigned long *dst, unsigned long npages)
+static void migrate_vma_cleanup_pages(unsigned long *dst, unsigned long npages)
{
unsigned long i;
@@ -553,12 +553,13 @@
migrate_vma_cleanup_pages(args->dst, state->num_pages);
}
+#if defined(CONFIG_MIGRATE_VMA_HELPER)
void uvm_migrate_vma_alloc_and_copy_helper(struct vm_area_struct *vma,
- const unsigned long *src,
- unsigned long *dst,
- unsigned long start,
- unsigned long end,
- void *private)
+ const unsigned long *src,
+ unsigned long *dst,
+ unsigned long start,
+ unsigned long end,
+ void *private)
{
struct migrate_vma args =
{
@@ -571,6 +572,7 @@
uvm_migrate_vma_alloc_and_copy(&args, (migrate_vma_state_t *) private);
}
+#endif
void uvm_migrate_vma_finalize_and_map(struct migrate_vma *args, migrate_vma_state_t *state)
{
@@ -642,6 +644,7 @@
UVM_ASSERT(!bitmap_intersects(state->populate_pages_mask, state->allocation_failed_mask, state->num_pages));
}
+#if defined(CONFIG_MIGRATE_VMA_HELPER)
void uvm_migrate_vma_finalize_and_map_helper(struct vm_area_struct *vma,
const unsigned long *src,
const unsigned long *dst,
@@ -660,6 +663,7 @@
uvm_migrate_vma_finalize_and_map(&args, (migrate_vma_state_t *) private);
}
+#endif
static NV_STATUS nv_migrate_vma(struct migrate_vma *args, migrate_vma_state_t *state)
{
diff -u -r a/nvidia-uvm/uvm_mmu.c b/nvidia-uvm/uvm_mmu.c
--- a/nvidia-uvm/uvm_mmu.c 2025-04-08 23:05:09.000000000 +1000
+++ b/nvidia-uvm/uvm_mmu.c 2026-02-08 13:37:17.855041962 +1100
@@ -2310,7 +2310,7 @@
return uvm_parent_gpu_is_virt_mode_sriov_heavy(parent_gpu);
}
-NV_STATUS create_static_vidmem_mapping(uvm_gpu_t *gpu)
+static NV_STATUS create_static_vidmem_mapping(uvm_gpu_t *gpu)
{
NvU32 page_size;
NvU64 size;
diff -u -r a/nvidia-uvm/uvm_page_tree_test.c b/nvidia-uvm/uvm_page_tree_test.c
--- a/nvidia-uvm/uvm_page_tree_test.c 2025-04-08 23:05:15.000000000 +1000
+++ b/nvidia-uvm/uvm_page_tree_test.c 2026-02-08 14:29:41.758701760 +1100
@@ -1511,7 +1511,7 @@
// Queries the supported page sizes of the GPU(uvm_gpu_t) and fills the
// page_sizes array up to MAX_NUM_PAGE_SIZE. Returns the number of elements in
// page_sizes;
-size_t get_page_sizes(uvm_gpu_t *gpu, NvU32 *page_sizes)
+static size_t get_page_sizes(uvm_gpu_t *gpu, NvU32 *page_sizes)
{
unsigned long page_size_log2;
unsigned long page_sizes_bitvec;
diff -u -r a/nvidia-uvm/uvm_pascal_fault_buffer.c b/nvidia-uvm/uvm_pascal_fault_buffer.c
--- a/nvidia-uvm/uvm_pascal_fault_buffer.c 2025-04-08 23:05:11.000000000 +1000
+++ b/nvidia-uvm/uvm_pascal_fault_buffer.c 2026-02-08 14:36:38.484603216 +1100
@@ -324,9 +324,9 @@
return NVB069_FAULT_BUF_SIZE;
}
-void uvm_hal_pascal_fault_buffer_parse_non_replayable_entry_unsupported(uvm_parent_gpu_t *parent_gpu,
- void *fault_packet,
- uvm_fault_buffer_entry_t *buffer_entry)
+static void uvm_hal_pascal_fault_buffer_parse_non_replayable_entry_unsupported(uvm_parent_gpu_t *parent_gpu,
+ void *fault_packet,
+ uvm_fault_buffer_entry_t *buffer_entry)
{
UVM_ASSERT_MSG(false, "fault_buffer_parse_non_replayable_entry called on Pascal GPU\n");
}
diff -u -r a/nvidia-uvm/uvm_pascal_mmu.c b/nvidia-uvm/uvm_pascal_mmu.c
--- a/nvidia-uvm/uvm_pascal_mmu.c 2025-04-08 23:05:11.000000000 +1000
+++ b/nvidia-uvm/uvm_pascal_mmu.c 2026-02-08 14:23:45.947437186 +1100
@@ -37,6 +37,7 @@
#include "uvm_global.h"
#include "uvm_gpu.h"
#include "uvm_mmu.h"
+#include "uvm_hal.h"
#include "uvm_push_macros.h"
#include "uvm_pascal_fault_buffer.h"
#include "hwref/pascal/gp100/dev_fault.h"
diff -u -r a/nvidia-uvm/uvm_pmm_sysmem_test.c b/nvidia-uvm/uvm_pmm_sysmem_test.c
--- a/nvidia-uvm/uvm_pmm_sysmem_test.c 2025-04-08 23:05:16.000000000 +1000
+++ b/nvidia-uvm/uvm_pmm_sysmem_test.c 2026-02-08 14:33:04.012971055 +1100
@@ -1072,7 +1072,7 @@
return status;
}
-NV_STATUS do_test_cpu_chunk_free(uvm_cpu_chunk_t *chunk, uvm_va_space_t *va_space, uvm_processor_mask_t *test_gpus)
+static NV_STATUS do_test_cpu_chunk_free(uvm_cpu_chunk_t *chunk, uvm_va_space_t *va_space, uvm_processor_mask_t *test_gpus)
{
NV_STATUS status = NV_OK;
uvm_cpu_chunk_t **split_chunks;
@@ -1168,7 +1168,7 @@
return status;
}
-NV_STATUS test_cpu_chunk_free(uvm_va_space_t *va_space, uvm_processor_mask_t *test_gpus)
+static NV_STATUS test_cpu_chunk_free(uvm_va_space_t *va_space, uvm_processor_mask_t *test_gpus)
{
uvm_cpu_chunk_t *chunk;
uvm_chunk_sizes_mask_t alloc_sizes = uvm_cpu_chunk_get_allocation_sizes();
diff -u -r a/nvidia-uvm/uvm_pmm_test.c b/nvidia-uvm/uvm_pmm_test.c
--- a/nvidia-uvm/uvm_pmm_test.c 2025-04-08 23:05:16.000000000 +1000
+++ b/nvidia-uvm/uvm_pmm_test.c 2026-02-08 14:31:49.033642048 +1100
@@ -898,11 +898,11 @@
return status;
}
-NV_STATUS __test_pmm_async_alloc_type(uvm_va_space_t *va_space,
- uvm_gpu_t *gpu,
- size_t num_chunks,
- uvm_pmm_gpu_memory_type_t mem_type,
- size_t work_iterations)
+static NV_STATUS __test_pmm_async_alloc_type(uvm_va_space_t *va_space,
+ uvm_gpu_t *gpu,
+ size_t num_chunks,
+ uvm_pmm_gpu_memory_type_t mem_type,
+ size_t work_iterations)
{
NV_STATUS status;
NV_STATUS tracker_status = NV_OK;
diff -u -r a/nvidia-uvm/uvm_populate_pageable.c b/nvidia-uvm/uvm_populate_pageable.c
--- a/nvidia-uvm/uvm_populate_pageable.c 2025-04-08 23:05:14.000000000 +1000
+++ b/nvidia-uvm/uvm_populate_pageable.c 2026-02-08 14:26:45.827525535 +1100
@@ -53,7 +53,7 @@
}
}
-NV_STATUS uvm_handle_fault(struct vm_area_struct *vma, unsigned long start, unsigned long vma_num_pages, bool write)
+static NV_STATUS uvm_handle_fault(struct vm_area_struct *vma, unsigned long start, unsigned long vma_num_pages, bool write)
{
NV_STATUS status = NV_OK;
diff -u -r a/nvidia-uvm/uvm_tools.c b/nvidia-uvm/uvm_tools.c
--- a/nvidia-uvm/uvm_tools.c 2025-04-08 23:05:05.000000000 +1000
+++ b/nvidia-uvm/uvm_tools.c 2026-02-08 13:29:33.674525316 +1100
@@ -26,6 +26,7 @@
#include "uvm_gpu.h"
#include "uvm_hal.h"
#include "uvm_tools.h"
+#include "uvm_tools_init.h"
#include "uvm_va_space.h"
#include "uvm_api.h"
#include "uvm_hal_types.h"
diff -u -r a/nvidia-uvm/uvm_tools.h b/nvidia-uvm/uvm_tools.h
--- a/nvidia-uvm/uvm_tools.h 2025-04-08 23:05:05.000000000 +1000
+++ b/nvidia-uvm/uvm_tools.h 2026-02-08 14:18:35.588267073 +1100
@@ -110,6 +110,11 @@
const uvm_access_counter_buffer_entry_t *buffer_entry,
bool on_managed_phys);
+void uvm_tools_record_access_counter(uvm_va_space_t *va_space,
+ uvm_gpu_id_t gpu_id,
+ const uvm_access_counter_buffer_entry_t *buffer_entry,
+ bool on_managed_phys);
+
void uvm_tools_test_hmm_split_invalidate(uvm_va_space_t *va_space);
// schedules completed events and then waits from the to be dispatched
#!/bin/bash
diff -u -r nvidia-550-kernel-source/ nvidia-550-kernel-source-stephematician/ | \
sed 's|nvidia-550-kernel-source/usr/src/nvidia-550.163.01|a|' | \
sed 's|nvidia-550-kernel-source-stephematician/usr/src/nvidia-550.163.01|b|' > \
buildfix_kernel_6.17_stephematician.patch

Patching the NVIDIA 550 driver in 24.04

So, upon the HWE kernel being updatedf from 6.14 to 6.17, I found that my previously trusty NVIDIA driver at 550.163.01 is now failing to build:

Error! Bad return status for module build on kernel: 6.17.0-14-generic (x86_64)
Consult /var/lib/dkms/nvidia/550.163.01/build/make.log for more information.

I am, for now, stuck on 550.163.01 because of a freeze that occurs with any later driver, see: forums.developer.nvidia.com - Downgrade 580 on Ubuntu? Wine freezes. For reference, I was only able to get the 550.160.01 driver installed via an archived package: for instructions see Ubuntu MATE Community - Hold your NVIDIA drivers if they are stable.

Now, fixing the compiler errors was going to be much too niche for there to be and off-the-shelfsolution. I knew I was on my own here. Luckily, I've had some experience developing kernel modules (see v4l2loopback).

Initial look

The output of the failed kernel package install said to look in /var/lib/dkms/nvidia/550.163.01/build/make.log. The first error was:

nvidia/nv-acpi.c:26:10: fatal error: os-interface.h: No such file or directory

In fact, there were a lot of errors like that. Seems odd that there are suddenly missing header files.

I needed to know where this header file is supposed to be, and it turns out, its sitting in the /usr/src/nvidia-550-163.01 folder as expected. This means compiler flag problems!

/usr/src$ find -regex '.*os-interface.h'
./nvidia-550.163.01/nvidia-modeset/nvidia-modeset-os-interface.h
./nvidia-550.163.01/common/inc/os-interface.h
./nvidia-550.163.01/nvidia-drm/nvidia-drm-os-interface.h

How to fix the compiler flags

I downloaded nvidia-550-kernel-source (at 550.163.01) and nvidia-580-kernel-source so that I had a driver that builds on 6.17 for comparison.

I thought a good place to start would be the build instructions:

~/nvidia-dbg$ diff 550-kernel-source/usr/share/nvidia-550.163.01/Kbuild \
     580-kernel-source/usr/share/nvidia-580.126.09/Kbuild

With output:

--- a/Kbuild    2025-04-08 23:05:17.000000000 +1000
+++ b/Kbuild    2026-02-08 12:39:01.562770917 +1100
@@ -75,21 +75,14 @@                                                             
  $(eval include $(src)/$(_module)/$(_module).Kbuild)) 


-#                                                                              
-# Define CFLAGS that apply to all the NVIDIA kernel modules. EXTRA_CFLAGS
-# is deprecated since 2.6.24 in favor of ccflags-y, but we need to support
-# older kernels which do not have ccflags-y. Newer kernels append
-# $(EXTRA_CFLAGS) to ccflags-y for compatibility.
-#
-
-EXTRA_CFLAGS += -I$(src)/common/inc
-EXTRA_CFLAGS += -I$(src)
-EXTRA_CFLAGS += -Wall $(DEFINES) $(INCLUDES) -Wno-cast-qual -Wno-format-extra-args
-EXTRA_CFLAGS += -D__KERNEL__ -DMODULE -DNVRM
-EXTRA_CFLAGS += -DNV_VERSION_STRING=\"550.163.01\"                             
+ccflags-y += -I$(src)/common/inc
+ccflags-y += -I$(src)
+ccflags-y += -Wall $(DEFINES) $(INCLUDES) -Wno-cast-qual -Wno-format-extra-args
+ccflags-y += -D__KERNEL__ -DMODULE -DNVRM
+ccflags-y += -DNV_VERSION_STRING=\"580.126.09\"

And a lot more. My hunch was correct! All the differences were down to the deprecation of EXTRA_CFLAGS.

First attempt at a patch

I created two folders, one called nvidia-550-kernel-source with the original code and another called nvidia-550-kernel-source-stephematician for the update.

I modified the EXTRA_CFLAGS lines in Kbuild to match those in the 580 driver.

From here, I needed to create a "patch" file, so I wrote a short script to help create them:

#!/bin/bash

diff -u -r nvidia-550-kernel-source/ nvidia-550-kernel-source-stephematician/ | \
    sed 's|nvidia-550-kernel-source/usr/src/nvidia-550.163.01|a|' | \
    sed 's|nvidia-550-kernel-source-stephematician/usr/src/nvidia-550.163.01|b|' > \
    buildfix_kernel_6.17_stephematician.patch

To test building the module with the patch, I'd copy it to /usr/src and use dkms:

sudo cp buildfix_kernel_6.17_stephematician.patch \
    /usr/src/nvidia-550.163.01/patches
sudo dkms build -m nvidia/550.163.01 -k 6.17.0-14-generic

Oops! I forgot one thing, I need to add the patch file to /usr/src/nvidia-550.163.01/dkms.conf. Add the line with sudoedit:

PATCH[1]="buildfix_kernel_6.17_stephematician.patch"

Second attempt

I was still seeing warnings, and warnings are treated as errors. There were two main types:

  • An "undeclared prototype"; which meant I had to fix a couple of missing headers and declare some functions that were not used outside of the unit as static; e.g.

    diff -u -r a/nvidia/libspdm_aead.c b/nvidia/libspdm_aead.c
    --- a/nvidia/libspdm_aead.c	2025-04-08 23:04:54.000000000 +1000
    +++ b/nvidia/libspdm_aead.c	2026-02-08 14:12:34.300268149 +1100
    @@ -38,7 +38,7 @@
     };
     #endif
     
    -int libspdm_aead_prealloc(void **context, char const *alg)
    +static int libspdm_aead_prealloc(void **context, char const *alg)
     {
     #ifndef USE_LKCA
         return -ENODEV;
  • A warning about parentheses for an empty body in an if statement, e.g. the following change:

    diff -u -r a/common/inc/nv-linux.h b/common/inc/nv-linux.h
    --- a/common/inc/nv-linux.h	2025-04-08 23:05:21.000000000 +1000
    +++ b/common/inc/nv-linux.h	2026-02-08 13:59:20.225684435 +1100
    @@ -601,8 +609,9 @@
     #define NV_KMALLOC_NO_OOM(ptr, size) \
         { \
             (ptr) = kmalloc(size, NV_GFP_NO_OOM); \
    -        if (ptr) \
    +        if (ptr) { \
                 NV_MEMDBG_ADD(ptr, size); \
    +        } \
         }
     
     #define NV_KFREE(ptr, size) \

And lastly, there was an actual error due to the use of del_timer_sync which has been fully deprected in kernel 6.15.0. To get around this, I used a really brute-force approach in nv-linux.h and one other header:

diff -u -r a/common/inc/nv-linux.h b/common/inc/nv-linux.h
--- a/common/inc/nv-linux.h	2025-04-08 23:05:21.000000000 +1000
+++ b/common/inc/nv-linux.h	2026-02-08 13:59:20.225684435 +1100
@@ -463,6 +463,11 @@
         (size) = *(unsigned long *) (ptr);              \
     }
 
+/* del_timer_sync fully deprecated in 6.15 */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,15,0)
+#define del_timer_sync timer_delete_sync
+#endif
+
 /* keep track of memory usage */
 #include "nv-memdbg.h"

Non-trivial changes

The last problem was less trivial. There was a change to the interface for drm_helper_mode_fill_fb_struct.

nvidia-drm/nvidia-drm-drv.c:214:18: error: initialization of ‘struct drm_framebuffer * (*)(struct drm_device *, struct drm_file *, const struct drm_format_info *, const struct drm_mode_fb_cmd2 *)’ from incompatible pointer type ‘struct drm_framebuffer * (*)(struct drm_device *, struct drm_file *, const struct drm_mode_fb_cmd2 *)’ [-Werror=incompatible-pointer-types]

Looking at the code, this interface has changed before. NVIDIA has had to work around this by checking the argument types using its conftest.sh script. Here's an excerpt from that script:

# ...
    echo "$CONFTEST_PREAMBLE
    #include <drm/drm_crtc_helper.h>
    void drm_helper_mode_fill_fb_struct(struct drm_device *dev,
                                        struct drm_framebuffer *fb,
                                        const struct drm_mode_fb_cmd2 *mode_cmd)
    {
        return;
    }" > conftest$$.c;

    $CC $CFLAGS -c conftest$$.c > /dev/null 2>&1
    rm -f conftest$$.c

    if [ -f conftest$$.o ]; then
        echo "#define NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_DEV_ARG" | append_conftest "function"
        rm -f conftest$$.o
    else
# ...

And then the calls in the C source code look like this:

    drm_helper_mode_fill_fb_struct(
        #if defined(NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_DEV_ARG)
        dev,
        #endif
        &nv_fb->base,
        cmd);

So I need to do two things:

  1. Update the conftest.sh to check if the helper has 4 arguments and then define an appropriate macro.
  2. Modify the calls within the C source when the macro is defined.

Ultimately, the calls look a little like this:

    drm_helper_mode_fill_fb_struct(
        #if defined(NV_DRM_HELPER_MODE_FILL_FB_STRUCT_HAS_DEV_ARG)
        dev,
        #endif
        &nv_fb->base,
        #if defined(NV_DRM_FILL_FB_STRUCT_TAKES_FORMAT_INFO)
        info,
        #endif
        cmd);

With that out of the way, the driver builds ... almost.

Inlined something with GPL license

Somehow, changes within the kernel have led to the driver linking to __vma_start_write which is a GPL'd, i.e. it is exported via the EXPORT_SYMBOL_GPL macro in the kernel. This causes the following problem:

ERROR: modpost: GPL-incompatible module nvidia.ko uses GPL-only symbol '__vma_start_write'
ERROR: modpost: GPL-incompatible module nvidia-drm.ko uses GPL-only symbol '__vma_start_write'

I have amended the patch using selected (and modified) patches from here:

https://salsa.debian.org/nvidia-team/nvidia-graphics-drivers/-/tree/debian/550.163.01-4_bpo13+1?ref_type=tags

More details to come when I get time to put this all together. But at least the patched driver builds on 6.14 and 6.17 now 😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment