diff -urp NVIDIA-Linux-x86_64-361.16.orig/kernel/common/inc/nv-linux.h NVIDIA-Linux-x86_64-361.16/kernel/common/inc/nv-linux.h
--- NVIDIA-Linux-x86_64-361.16.orig/kernel/common/inc/nv-linux.h	2015-12-30 06:44:07.000000000 +0100
+++ NVIDIA-Linux-x86_64-361.16/kernel/common/inc/nv-linux.h	2016-01-11 02:58:02.265211586 +0100
@@ -1330,9 +1330,14 @@ extern void *nvidia_stack_t_cache;
 #if (NV_KMEM_CACHE_CREATE_ARGUMENT_COUNT == 5)
 #define NV_KMEM_CACHE_CREATE(name, type)    \
     kmem_cache_create(name, sizeof(type), 0, 0, NULL)
+#define NV_KMEM_CACHE_CREATE_USERCOPY(name, type)    \
+    kmem_cache_create(name, sizeof(type), 0, SLAB_USERCOPY, NULL)
 #else
 #define NV_KMEM_CACHE_CREATE(name, type)    \
     kmem_cache_create(name, sizeof(type), 0, 0, NULL, \
+                       NULL)
+#define NV_KMEM_CACHE_CREATE_USERCOPY(name, type)    \
+    kmem_cache_create(name, sizeof(type), 0, SLAB_USERCOPY, NULL, \
                       NULL)
 #endif
 #define NV_KMEM_CACHE_DESTROY(kmem_cache)   \
diff -urp NVIDIA-Linux-x86_64-361.16.orig/kernel/nvidia/nv.c NVIDIA-Linux-x86_64-361.16/kernel/nvidia/nv.c
--- NVIDIA-Linux-x86_64-361.16.orig/kernel/nvidia/nv.c	2015-12-30 06:44:07.000000000 +0100
+++ NVIDIA-Linux-x86_64-361.16/kernel/nvidia/nv.c	2016-01-11 02:55:27.394977588 +0100
@@ -704,7 +704,7 @@ int __init nvidia_init_module(void)
     NV_SPIN_LOCK_INIT(&km_lock);
 #endif
 
-    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 NVIDIA-Linux-x86_64-361.16.orig/kernel/nvidia/nv-mmap.c NVIDIA-Linux-x86_64-361.16/kernel/nvidia/nv-mmap.c
--- NVIDIA-Linux-x86_64-361.16.orig/kernel/nvidia/nv-mmap.c	2015-12-30 06:44:07.000000000 +0100
+++ NVIDIA-Linux-x86_64-361.16/kernel/nvidia/nv-mmap.c	2016-01-11 02:58:47.132718812 +0100
@@ -113,12 +113,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 NVIDIA-Linux-x86_64-361.16.orig/kernel/nvidia-uvm/uvm8_channel.c NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm8_channel.c
--- NVIDIA-Linux-x86_64-361.16.orig/kernel/nvidia-uvm/uvm8_channel.c	2015-12-30 06:45:09.000000000 +0100
+++ NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm8_channel.c	2016-01-11 03:14:44.774335695 +0100
@@ -233,7 +233,7 @@ void uvm_channel_end_push(uvm_push_t *pu
     mb();
 
     channel->cpu_put = new_cpu_put;
-    ACCESS_ONCE(*channel->channel_info.GPPut) = new_cpu_put;
+    ACCESS_ONCE_RW(*channel->channel_info.GPPut) = new_cpu_put;
 
     uvm_spin_unlock(&channel->pool->lock);
 
diff -urp NVIDIA-Linux-x86_64-361.16.orig/kernel/nvidia-uvm/uvm8_global.c NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm8_global.c
--- NVIDIA-Linux-x86_64-361.16.orig/kernel/nvidia-uvm/uvm8_global.c	2015-12-30 06:45:09.000000000 +0100
+++ NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm8_global.c	2016-01-11 03:12:05.846067699 +0100
@@ -30,16 +30,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 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));
     return status;
diff -urp NVIDIA-Linux-x86_64-361.16.orig/kernel/nvidia-uvm/uvm8_gpu_semaphore.c NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm8_gpu_semaphore.c
--- NVIDIA-Linux-x86_64-361.16.orig/kernel/nvidia-uvm/uvm8_gpu_semaphore.c	2015-12-30 06:45:09.000000000 +0100
+++ NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm8_gpu_semaphore.c	2016-01-11 03:14:22.011553125 +0100
@@ -303,7 +303,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;
 }
 
 NV_STATUS uvm_gpu_tracking_semaphore_alloc(uvm_gpu_semaphore_pool_t *pool, uvm_gpu_tracking_semaphore_t *tracking_sem)
diff -urp NVIDIA-Linux-x86_64-361.16.orig/kernel/nvidia-uvm/uvm_common.c NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm_common.c
--- NVIDIA-Linux-x86_64-361.16.orig/kernel/nvidia-uvm/uvm_common.c	2015-12-30 06:45:09.000000000 +0100
+++ NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm_common.c	2016-01-11 03:06:02.062940434 +0100
@@ -74,7 +74,6 @@ static int uvmnext_activated(void)
 #endif
 
 static dev_t g_uvmBaseDev;
-struct UvmOpsUvmEvents g_exportedUvmOps;
 
 static char* uvm_driver_mode = "lite";
 
@@ -185,12 +184,17 @@ static NV_STATUS uvmSetupGpuProvider(voi
 {
     NV_STATUS status = NV_OK;
 
-    g_exportedUvmOps.startDevice = uvm_gpu_event_start_device;
-    g_exportedUvmOps.stopDevice  = uvm_gpu_event_stop_device;
+    static struct UvmOpsUvmEvents g_exportedUvmOps = {
+        .startDevice = uvm_gpu_event_start_device,
+        .stopDevice  = uvm_gpu_event_stop_device,
+        .isrTopHalf  = NULL,
+    };
+    pax_open_kernel();
     if (uvmnext_activated())
-        g_exportedUvmOps.isrTopHalf = uvmnext_isr_top_half;
+        *(void **)&g_exportedUvmOps.isrTopHalf = uvmnext_isr_top_half;
     else if (uvmfull_activated())
-        g_exportedUvmOps.isrTopHalf = uvmfull_isr_top_half;
+        *(void **)&g_exportedUvmOps.isrTopHalf = uvmfull_isr_top_half;
+    pax_close_kernel();
 
     // call RM to exchange the function pointers.
     status = nvUvmInterfaceRegisterUvmCallbacks(&g_exportedUvmOps);
diff -urp NVIDIA-Linux-x86_64-361.16.orig/kernel/nvidia-uvm/uvm_full_fault_buffer.h NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm_full_fault_buffer.h
--- NVIDIA-Linux-x86_64-361.16.orig/kernel/nvidia-uvm/uvm_full_fault_buffer.h	2015-12-30 06:45:09.000000000 +0100
+++ NVIDIA-Linux-x86_64-361.16/kernel/nvidia-uvm/uvm_full_fault_buffer.h	2016-01-11 03:10:29.874565713 +0100
@@ -31,6 +31,7 @@
 #define _UVM_FULL_FAULT_BUFFER_H_
 
 #include "uvmtypes.h"
+#include "linux/compiler.h"
 
 #define MAXWELL_FAULT_BUFFER_A (0xb069)
 #define MEM_RD32(a) (*(const volatile NvU32 *)(a)) 
@@ -303,7 +304,7 @@ typedef struct
     NvUvmControlPrefetch_t              controlPrefetch;
     NvUvmTestFaultBufferOverflow_t      testFaultBufferOverflow;
     NvUvmClearFaultBufferOverflow_t     clearFaultBufferOverflow;
-} UvmFaultBufferOps;
+} UvmFaultBufferOps __no_const;
 
 /******************************************************************************
     uvmfull_fault_buffer_init
