diff -urp work.orig/kernel/common/inc/nv-linux.h work/kernel/common/inc/nv-linux.h --- work.orig/kernel/common/inc/nv-linux.h 2017-09-29 06:17:46.000000000 +0200 +++ work/kernel/common/inc/nv-linux.h 2017-10-08 00:52:42.721523788 +0200 @@ -1189,7 +1189,8 @@ extern void *nvidia_stack_t_cache; #if (NV_KMEM_CACHE_CREATE_ARGUMENT_COUNT == 5) #define NV_KMEM_CACHE_CREATE_FULL(name, size, align, flags, ctor) \ kmem_cache_create(name, size, align, flags, ctor) - +#define NV_KMEM_CACHE_CREATE_FULL_USERCOPY(name, size, align, flags, useroffset, usersize, ctor) \ + kmem_cache_create_usercopy(name, size, align, flags, useroffset, usersize, ctor) #else #define NV_KMEM_CACHE_CREATE_FULL(name, size, align, flags, ctor) \ kmem_cache_create(name, size, align, flags, ctor, NULL) @@ -1198,6 +1199,14 @@ extern void *nvidia_stack_t_cache; #define NV_KMEM_CACHE_CREATE(name, type) \ NV_KMEM_CACHE_CREATE_FULL(name, sizeof(type), 0, 0, NULL) +#ifdef SLAB_USERCOPY +#define NV_KMEM_CACHE_CREATE_USERCOPY(name, type) \ + NV_KMEM_CACHE_CREATE_FULL(name, sizeof(type), 0, SLAB_USERCOPY, NULL) +#else +#define NV_KMEM_CACHE_CREATE_USERCOPY(name, type) \ + NV_KMEM_CACHE_CREATE_FULL_USERCOPY(name, sizeof(type), 0, 0, 0, sizeof(type), NULL) +#endif + #define NV_KMEM_CACHE_DESTROY(kmem_cache) \ kmem_cache_destroy(kmem_cache) diff -urp work.orig/kernel/common/inc/nv-modeset-interface.h work/kernel/common/inc/nv-modeset-interface.h --- work.orig/kernel/common/inc/nv-modeset-interface.h 2017-09-29 06:17:46.000000000 +0200 +++ work/kernel/common/inc/nv-modeset-interface.h 2017-10-08 00:52:42.721523788 +0200 @@ -72,7 +72,7 @@ typedef struct { * mix nvidia and nvidia-modeset kernel modules from different * releases. */ - const char *version_string; +// const char *version_string; /* * Return system information. @@ -115,8 +115,8 @@ typedef struct { int (*set_callbacks)(const nvidia_modeset_callbacks_t *cb); -} nvidia_modeset_rm_ops_t; +} __do_const nvidia_modeset_rm_ops_t; -NV_STATUS nvidia_get_rm_ops(nvidia_modeset_rm_ops_t *rm_ops); +NV_STATUS nvidia_get_rm_ops(const nvidia_modeset_rm_ops_t **rm_ops, const char **version_string); #endif /* _NV_MODESET_INTERFACE_H_ */ diff -urp work.orig/kernel/common/inc/nv-register-module.h work/kernel/common/inc/nv-register-module.h --- work.orig/kernel/common/inc/nv-register-module.h 2017-09-29 06:17:46.000000000 +0200 +++ work/kernel/common/inc/nv-register-module.h 2017-10-08 00:52:42.721523788 +0200 @@ -34,7 +34,7 @@ typedef struct nvidia_module_s { int (*ioctl)(struct inode *, struct file * file, unsigned int cmd, unsigned long arg); unsigned int (*poll)(struct file * file, poll_table *wait); -} nvidia_module_t; +} __do_const nvidia_module_t; int nvidia_register_module(nvidia_module_t *); int nvidia_unregister_module(nvidia_module_t *); diff -urp work.orig/kernel/nvidia/nv.c work/kernel/nvidia/nv.c --- work.orig/kernel/nvidia/nv.c 2017-09-29 06:17:45.000000000 +0200 +++ work/kernel/nvidia/nv.c 2017-10-08 00:52:42.721523788 +0200 @@ -682,7 +682,7 @@ int __init nvidia_init_module(void) nv_memdbg_init(); - nvidia_stack_t_cache = NV_KMEM_CACHE_CREATE(nvidia_stack_cache_name, + nvidia_stack_t_cache = NV_KMEM_CACHE_CREATE_USERCOPY(nvidia_stack_cache_name, nvidia_stack_t); if (nvidia_stack_t_cache == NULL) { diff -urp work.orig/kernel/nvidia/nv-chrdev.c work/kernel/nvidia/nv-chrdev.c --- work.orig/kernel/nvidia/nv-chrdev.c 2017-09-29 06:17:45.000000000 +0200 +++ work/kernel/nvidia/nv-chrdev.c 2017-10-08 00:52:42.721523788 +0200 @@ -20,8 +20,6 @@ int nv_register_chrdev(void *param) { nvidia_module_t *module = (nvidia_module_t *)param; - module->instance = nv_module_instance; - return (nvidia_register_module(module)); } diff -urp work.orig/kernel/nvidia/nv-instance.c work/kernel/nvidia/nv-instance.c --- work.orig/kernel/nvidia/nv-instance.c 2017-09-29 06:17:46.000000000 +0200 +++ work/kernel/nvidia/nv-instance.c 2017-10-08 00:52:42.721523788 +0200 @@ -51,6 +51,7 @@ struct pci_driver nv_pci_driver = { nvidia_module_t nv_fops = { .owner = THIS_MODULE, .module_name = MODULE_NAME, + .instance = MODULE_INSTANCE_NUMBER, .open = nvidia_open, .close = nvidia_close, .ioctl = nvidia_ioctl, diff -urp work.orig/kernel/nvidia/nv-mmap.c work/kernel/nvidia/nv-mmap.c --- work.orig/kernel/nvidia/nv-mmap.c 2017-09-29 06:17:45.000000000 +0200 +++ work/kernel/nvidia/nv-mmap.c 2017-10-08 00:52:42.721523788 +0200 @@ -102,12 +102,12 @@ nvidia_vma_release(struct vm_area_struct } #if defined(NV_VM_OPERATIONS_STRUCT_HAS_ACCESS) -static int +static ssize_t nvidia_vma_access( struct vm_area_struct *vma, unsigned long addr, void *buffer, - int length, + size_t length, int write ) { diff -urp work.orig/kernel/nvidia/nv-modeset-interface.c work/kernel/nvidia/nv-modeset-interface.c --- work.orig/kernel/nvidia/nv-modeset-interface.c 2017-09-29 06:17:45.000000000 +0200 +++ work/kernel/nvidia/nv-modeset-interface.c 2017-10-08 00:52:42.721523788 +0200 @@ -8,14 +8,14 @@ * _NVRM_COPYRIGHT_END_ */ -#include "nv-modeset-interface.h" - #include "nv-misc.h" #include "os-interface.h" #include "nv-linux.h" #include "nvstatus.h" #include "nv.h" +#include "nv-modeset-interface.h" + static const nvidia_modeset_callbacks_t *nv_modeset_callbacks; static int nvidia_modeset_rm_ops_alloc_stack(nvidia_stack_t **sp) @@ -100,10 +100,9 @@ static NvU32 nvidia_modeset_enumerate_gp return count; } -NV_STATUS nvidia_get_rm_ops(nvidia_modeset_rm_ops_t *rm_ops) +NV_STATUS nvidia_get_rm_ops(const nvidia_modeset_rm_ops_t **rm_ops, const char **version_string) { - const nvidia_modeset_rm_ops_t local_rm_ops = { - .version_string = NV_VERSION_STRING, + static const nvidia_modeset_rm_ops_t local_rm_ops = { .system_info = { .allow_write_combining = NV_FALSE, }, @@ -116,17 +115,26 @@ NV_STATUS nvidia_get_rm_ops(nvidia_modes .set_callbacks = nvidia_modeset_set_callbacks, }; - if (strcmp(rm_ops->version_string, NV_VERSION_STRING) != 0) + static const nvidia_modeset_rm_ops_t local_rm_ops_wc = { + .system_info = { + .allow_write_combining = NV_TRUE, + }, + .alloc_stack = nvidia_modeset_rm_ops_alloc_stack, + .free_stack = nvidia_modeset_rm_ops_free_stack, + .enumerate_gpus = nvidia_modeset_enumerate_gpus, + .open_gpu = nvidia_dev_get, + .close_gpu = nvidia_dev_put, + .op = rm_kernel_rmapi_op, /* provided by nv-kernel.o */ + .set_callbacks = nvidia_modeset_set_callbacks, + }; + + if (strcmp(*version_string, NV_VERSION_STRING) != 0) { - rm_ops->version_string = NV_VERSION_STRING; + *version_string = NV_VERSION_STRING; return NV_ERR_GENERIC; } - *rm_ops = local_rm_ops; - - if (NV_ALLOW_WRITE_COMBINING(NV_MEMORY_TYPE_FRAMEBUFFER)) { - rm_ops->system_info.allow_write_combining = NV_TRUE; - } + *rm_ops = NV_ALLOW_WRITE_COMBINING(NV_MEMORY_TYPE_FRAMEBUFFER) ? &local_rm_ops_wc : &local_rm_ops; return NV_OK; } diff -urp work.orig/kernel/nvidia-drm/nvidia-drm-drv.c work/kernel/nvidia-drm/nvidia-drm-drv.c --- work.orig/kernel/nvidia-drm/nvidia-drm-drv.c 2017-09-29 06:17:53.000000000 +0200 +++ work/kernel/nvidia-drm/nvidia-drm-drv.c 2017-10-08 00:52:42.721523788 +0200 @@ -771,6 +771,7 @@ static void nvidia_update_drm_driver_fea return; } + pax_open_kernel(); nv_drm_driver.driver_features |= DRIVER_MODESET | DRIVER_ATOMIC; nv_drm_driver.master_set = nvidia_drm_master_set; @@ -781,6 +782,7 @@ static void nvidia_update_drm_driver_fea nv_drm_driver.dumb_destroy = drm_gem_dumb_destroy; nv_drm_driver.gem_vm_ops = &nv_drm_gem_vma_ops; + pax_close_kernel(); #endif /* NV_DRM_ATOMIC_MODESET_AVAILABLE */ } diff -urp work.orig/kernel/nvidia-modeset/nvidia-modeset-linux.c work/kernel/nvidia-modeset/nvidia-modeset-linux.c --- work.orig/kernel/nvidia-modeset/nvidia-modeset-linux.c 2017-09-29 06:17:52.000000000 +0200 +++ work/kernel/nvidia-modeset/nvidia-modeset-linux.c 2017-10-08 00:52:42.725569791 +0200 @@ -341,29 +341,28 @@ static void nvkms_resume(NvU32 gpuId) * Interface with resman. *************************************************************************/ -static nvidia_modeset_rm_ops_t __rm_ops = { 0 }; +static const nvidia_modeset_rm_ops_t *__rm_ops; static nvidia_modeset_callbacks_t nvkms_rm_callbacks = { - .suspend = nvkms_suspend, - .resume = nvkms_resume + .suspend = nvkms_suspend, + .resume = nvkms_resume }; static int nvkms_alloc_rm(void) { NV_STATUS nvstatus; int ret; + const char *version_string = NV_VERSION_STRING; - __rm_ops.version_string = NV_VERSION_STRING; - - nvstatus = nvidia_get_rm_ops(&__rm_ops); + nvstatus = nvidia_get_rm_ops(&__rm_ops, &version_string); if (nvstatus != NV_OK) { printk(KERN_ERR NVKMS_LOG_PREFIX "Version mismatch: " "nvidia.ko(%s) nvidia-modeset.ko(%s)\n", - __rm_ops.version_string, NV_VERSION_STRING); + version_string, NV_VERSION_STRING); return -EINVAL; } - ret = __rm_ops.set_callbacks(&nvkms_rm_callbacks); + ret = __rm_ops->set_callbacks(&nvkms_rm_callbacks); if (ret < 0) { printk(KERN_ERR NVKMS_LOG_PREFIX "Failed to register callbacks\n"); return ret; @@ -374,20 +373,20 @@ static int nvkms_alloc_rm(void) static void nvkms_free_rm(void) { - __rm_ops.set_callbacks(NULL); + __rm_ops->set_callbacks(NULL); } void NVKMS_API_CALL nvkms_call_rm(void *ops) { nvidia_modeset_stack_ptr stack = NULL; - if (__rm_ops.alloc_stack(&stack) != 0) { + if (__rm_ops->alloc_stack(&stack) != 0) { return; } - __rm_ops.op(stack, ops); + __rm_ops->op(stack, ops); - __rm_ops.free_stack(stack); + __rm_ops->free_stack(stack); } /************************************************************************* @@ -723,13 +722,13 @@ NvBool NVKMS_API_CALL nvkms_open_gpu(NvU nvidia_modeset_stack_ptr stack = NULL; NvBool ret; - if (__rm_ops.alloc_stack(&stack) != 0) { + if (__rm_ops->alloc_stack(&stack) != 0) { return NV_FALSE; } - ret = __rm_ops.open_gpu(gpuId, stack) == 0; + ret = __rm_ops->open_gpu(gpuId, stack) == 0; - __rm_ops.free_stack(stack); + __rm_ops->free_stack(stack); return ret; } @@ -738,23 +737,23 @@ void NVKMS_API_CALL nvkms_close_gpu(NvU3 { nvidia_modeset_stack_ptr stack = NULL; - if (__rm_ops.alloc_stack(&stack) != 0) { + if (__rm_ops->alloc_stack(&stack) != 0) { return; } - __rm_ops.close_gpu(gpuId, stack); + __rm_ops->close_gpu(gpuId, stack); - __rm_ops.free_stack(stack); + __rm_ops->free_stack(stack); } NvU32 NVKMS_API_CALL nvkms_enumerate_gpus(nv_gpu_info_t *gpu_info) { - return __rm_ops.enumerate_gpus(gpu_info); + return __rm_ops->enumerate_gpus(gpu_info); } NvBool NVKMS_API_CALL nvkms_allow_write_combining(void) { - return __rm_ops.system_info.allow_write_combining; + return __rm_ops->system_info.allow_write_combining; } /************************************************************************* diff -urp work.orig/kernel/nvidia-uvm/uvm8_global.c work/kernel/nvidia-uvm/uvm8_global.c --- work.orig/kernel/nvidia-uvm/uvm8_global.c 2017-09-29 06:17:48.000000000 +0200 +++ work/kernel/nvidia-uvm/uvm8_global.c 2017-10-08 00:52:42.725569791 +0200 @@ -35,17 +35,17 @@ #include "nv_uvm_interface.h" uvm_global_t g_uvm_global; -static struct UvmOpsUvmEvents g_exported_uvm8_ops; +static struct UvmOpsUvmEvents g_exported_uvm8_ops = { + .startDevice = NULL, + .stopDevice = NULL, + .isrTopHalf = uvm8_isr_top_half, +}; static bool g_ops_registered = false; static NV_STATUS uvm8_register_callbacks(void) { NV_STATUS status = NV_OK; - g_exported_uvm8_ops.startDevice = NULL; - g_exported_uvm8_ops.stopDevice = NULL; - g_exported_uvm8_ops.isrTopHalf = uvm8_isr_top_half; - // Register the UVM callbacks with the main GPU driver: status = uvm_rm_locked_call(nvUvmInterfaceRegisterUvmCallbacks(&g_exported_uvm8_ops)); if (status != NV_OK) diff -urp work.orig/kernel/nvidia-uvm/uvm8_gpu_semaphore.c work/kernel/nvidia-uvm/uvm8_gpu_semaphore.c --- work.orig/kernel/nvidia-uvm/uvm8_gpu_semaphore.c 2017-09-29 06:17:49.000000000 +0200 +++ work/kernel/nvidia-uvm/uvm8_gpu_semaphore.c 2017-10-08 00:52:42.725569791 +0200 @@ -368,7 +368,7 @@ void uvm_gpu_semaphore_set_payload(uvm_g // being optimized out on non-SMP configs (we need them for interacting with // the GPU correctly even on non-SMP). mb(); - ACCESS_ONCE(*semaphore->payload) = payload; + ACCESS_ONCE_RW(*semaphore->payload) = payload; } // This function is intended to catch channels which have been left dangling in diff -urp work.orig/kernel/nvidia-uvm/uvm8_hal.h work/kernel/nvidia-uvm/uvm8_hal.h --- work.orig/kernel/nvidia-uvm/uvm8_hal.h 2017-09-29 06:17:49.000000000 +0200 +++ work/kernel/nvidia-uvm/uvm8_hal.h 2017-10-08 00:53:08.239361649 +0200 @@ -429,7 +429,7 @@ typedef struct // access_counter_buffer_ops: id is a hardware class uvm_access_counter_buffer_hal_t access_counter_buffer_ops; } u; -} uvm_hal_class_ops_t; +} __do_const uvm_hal_class_ops_t; NV_STATUS uvm_hal_init_table(void); NV_STATUS uvm_hal_init_gpu(uvm_gpu_t *gpu); diff -urp work.orig/kernel/nvidia-uvm/uvm8_mmu.h work/kernel/nvidia-uvm/uvm8_mmu.h --- work.orig/kernel/nvidia-uvm/uvm8_mmu.h 2017-09-29 06:17:50.000000000 +0200 +++ work/kernel/nvidia-uvm/uvm8_mmu.h 2017-10-08 00:52:42.725569791 +0200 @@ -24,7 +24,6 @@ #ifndef __UVM8_MMU_H__ #define __UVM8_MMU_H__ -#include "uvm8_forward_decl.h" #include "uvm8_hal_types.h" #include "uvm8_pmm_gpu.h" #include "uvmtypes.h" diff -urp work.orig/kernel/nvidia-uvm/uvm_common.c work/kernel/nvidia-uvm/uvm_common.c --- work.orig/kernel/nvidia-uvm/uvm_common.c 2017-09-29 06:17:47.000000000 +0200 +++ work/kernel/nvidia-uvm/uvm_common.c 2017-10-08 00:52:42.725569791 +0200 @@ -40,7 +40,6 @@ #define UVM_SPIN_LOOP_PRINT_TIMEOUT_SEC 30ULL static dev_t g_uvmBaseDev; -struct UvmOpsUvmEvents g_exportedUvmOps; static char* uvm_driver_mode = "8"; diff -urp work.orig/kernel/nvidia-uvm/uvm_linux.h work/kernel/nvidia-uvm/uvm_linux.h --- work.orig/kernel/nvidia-uvm/uvm_linux.h 2017-09-29 06:17:47.000000000 +0200 +++ work/kernel/nvidia-uvm/uvm_linux.h 2017-10-08 00:52:42.725569791 +0200 @@ -436,7 +436,7 @@ static inline NvU64 NV_GETTIME(void) // WRITE_ONCE/READ_ONCE have incompatible definitions across versions, which produces warnings. // Therefore, we define our own macros -#define UVM_WRITE_ONCE(x, val) (ACCESS_ONCE(x) = (val)) +#define UVM_WRITE_ONCE(x, val) (ACCESS_ONCE_RW(x) = (val)) #define UVM_READ_ONCE(x) ACCESS_ONCE(x) // Added in 3.11