#define PT_HAVE_ACCESSED_DIRTY(mmu) true
        #ifdef CONFIG_X86_64
        #define PT_MAX_FULL_LEVELS PT64_ROOT_MAX_LEVEL
-       #define CMPXCHG cmpxchg
+       #define CMPXCHG "cmpxchgq"
        #else
-       #define CMPXCHG cmpxchg64
        #define PT_MAX_FULL_LEVELS 2
        #endif
 #elif PTTYPE == 32
        #define PT_GUEST_DIRTY_SHIFT PT_DIRTY_SHIFT
        #define PT_GUEST_ACCESSED_SHIFT PT_ACCESSED_SHIFT
        #define PT_HAVE_ACCESSED_DIRTY(mmu) true
-       #define CMPXCHG cmpxchg
+       #define CMPXCHG "cmpxchgl"
 #elif PTTYPE == PTTYPE_EPT
        #define pt_element_t u64
        #define guest_walker guest_walkerEPT
        #define PT_GUEST_DIRTY_SHIFT 9
        #define PT_GUEST_ACCESSED_SHIFT 8
        #define PT_HAVE_ACCESSED_DIRTY(mmu) ((mmu)->ept_ad)
-       #define CMPXCHG cmpxchg64
+       #ifdef CONFIG_X86_64
+       #define CMPXCHG "cmpxchgq"
+       #endif
        #define PT_MAX_FULL_LEVELS PT64_ROOT_MAX_LEVEL
 #else
        #error Invalid PTTYPE value
                               pt_element_t __user *ptep_user, unsigned index,
                               pt_element_t orig_pte, pt_element_t new_pte)
 {
-       int npages;
-       pt_element_t ret;
-       pt_element_t *table;
-       struct page *page;
-
-       npages = get_user_pages_fast((unsigned long)ptep_user, 1, FOLL_WRITE, &page);
-       if (likely(npages == 1)) {
-               table = kmap_atomic(page);
-               ret = CMPXCHG(&table[index], orig_pte, new_pte);
-               kunmap_atomic(table);
-
-               kvm_release_page_dirty(page);
-       } else {
-               struct vm_area_struct *vma;
-               unsigned long vaddr = (unsigned long)ptep_user & PAGE_MASK;
-               unsigned long pfn;
-               unsigned long paddr;
-
-               mmap_read_lock(current->mm);
-               vma = find_vma_intersection(current->mm, vaddr, vaddr + PAGE_SIZE);
-               if (!vma || !(vma->vm_flags & VM_PFNMAP)) {
-                       mmap_read_unlock(current->mm);
-                       return -EFAULT;
-               }
-               pfn = ((vaddr - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
-               paddr = pfn << PAGE_SHIFT;
-               table = memremap(paddr, PAGE_SIZE, MEMREMAP_WB);
-               if (!table) {
-                       mmap_read_unlock(current->mm);
-                       return -EFAULT;
-               }
-               ret = CMPXCHG(&table[index], orig_pte, new_pte);
-               memunmap(table);
-               mmap_read_unlock(current->mm);
-       }
+       int r = -EFAULT;
+
+       if (!user_access_begin(ptep_user, sizeof(pt_element_t)))
+               return -EFAULT;
+
+#ifdef CMPXCHG
+       asm volatile("1:" LOCK_PREFIX CMPXCHG " %[new], %[ptr]\n"
+                    "mov $0, %[r]\n"
+                    "setnz %b[r]\n"
+                    "2:"
+                    _ASM_EXTABLE_UA(1b, 2b)
+                    : [ptr] "+m" (*ptep_user),
+                      [old] "+a" (orig_pte),
+                      [r] "+q" (r)
+                    : [new] "r" (new_pte)
+                    : "memory");
+#else
+       asm volatile("1:" LOCK_PREFIX "cmpxchg8b %[ptr]\n"
+                    "movl $0, %[r]\n"
+                    "jz 2f\n"
+                    "incl %[r]\n"
+                    "2:"
+                    _ASM_EXTABLE_UA(1b, 2b)
+                    : [ptr] "+m" (*ptep_user),
+                      [old] "+A" (orig_pte),
+                      [r] "+rm" (r)
+                    : [new_lo] "b" ((u32)new_pte),
+                      [new_hi] "c" ((u32)(new_pte >> 32))
+                    : "memory");
+#endif
 
-       return (ret != orig_pte);
+       user_access_end();
+       return r;
 }
 
 static bool FNAME(prefetch_invalid_gpte)(struct kvm_vcpu *vcpu,