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-07-20 16:38:08.234048340 +0200
+++ work/kernel/common/inc/nv-linux.h	2017-07-20 16:36:18.747868610 +0200
@@ -1194,7 +1194,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)
@@ -1203,6 +1204,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-07-20 16:38:08.234048340 +0200
+++ work/kernel/common/inc/nv-modeset-interface.h	2017-07-20 16:36:18.747868610 +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-07-20 16:38:08.234048340 +0200
+++ work/kernel/common/inc/nv-register-module.h	2017-07-20 16:36:18.747868610 +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-07-20 16:38:08.234048340 +0200
+++ work/kernel/nvidia/nv.c	2017-07-20 16:36:18.751886392 +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-07-20 16:38:08.262081731 +0200
+++ work/kernel/nvidia/nv-chrdev.c	2017-07-20 16:36:18.751886392 +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-07-20 16:38:08.262081731 +0200
+++ work/kernel/nvidia/nv-instance.c	2017-07-20 16:36:18.751886392 +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-07-20 16:38:08.262081731 +0200
+++ work/kernel/nvidia/nv-mmap.c	2017-07-20 16:36:18.751886392 +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-07-20 16:38:08.262081731 +0200
+++ work/kernel/nvidia/nv-modeset-interface.c	2017-07-20 16:43:36.601711519 +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-07-20 16:38:08.262081731 +0200
+++ work/kernel/nvidia-drm/nvidia-drm-drv.c	2017-07-20 16:36:18.751886392 +0200
@@ -716,6 +716,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;
@@ -726,6 +727,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-07-20 16:38:08.262081731 +0200
+++ work/kernel/nvidia-modeset/nvidia-modeset-linux.c	2017-07-20 16:36:18.751886392 +0200
@@ -335,29 +335,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 = {
-    nvkms_suspend,
-    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;
@@ -368,20 +367,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);
 }
 
 /*************************************************************************
@@ -705,13 +704,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;
 }
@@ -720,23 +719,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-07-20 16:38:08.262081731 +0200
+++ work/kernel/nvidia-uvm/uvm8_global.c	2017-07-20 16:36:18.751886392 +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-07-20 16:38:08.262081731 +0200
+++ work/kernel/nvidia-uvm/uvm8_gpu_semaphore.c	2017-07-20 16:36:18.751886392 +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-07-20 16:38:08.262081731 +0200
+++ work/kernel/nvidia-uvm/uvm8_hal.h	2017-07-20 16:36:18.755904175 +0200
@@ -437,7 +437,7 @@ typedef struct
         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-07-20 16:38:08.266086502 +0200
+++ work/kernel/nvidia-uvm/uvm8_mmu.h	2017-07-20 16:36:18.755904175 +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-07-20 16:38:08.266086502 +0200
+++ work/kernel/nvidia-uvm/uvm_common.c	2017-07-20 16:36:18.755904175 +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-07-20 16:38:08.266086502 +0200
+++ work/kernel/nvidia-uvm/uvm_linux.h	2017-07-20 16:36:18.755904175 +0200
@@ -438,7 +438,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
