by hand. Technically we need to emulate:
                         fdc,fdce,pdc,"fic,4f",prober,probeir,probew, probeiw
                */
+               if (code == 17 && handle_nadtlb_fault(regs))
+                       return;
                fault_address = regs->ior;
                fault_space = regs->isr;
                break;
 
        }
        pagefault_out_of_memory();
 }
+
+/* Handle non-access data TLB miss faults.
+ *
+ * For probe instructions, accesses to userspace are considered allowed
+ * if they lie in a valid VMA and the access type matches. We are not
+ * allowed to handle MM faults here so there may be situations where an
+ * actual access would fail even though a probe was successful.
+ */
+int
+handle_nadtlb_fault(struct pt_regs *regs)
+{
+       unsigned long insn = regs->iir;
+       int breg, treg, xreg, val = 0;
+       struct vm_area_struct *vma, *prev_vma;
+       struct task_struct *tsk;
+       struct mm_struct *mm;
+       unsigned long address;
+       unsigned long acc_type;
+
+       switch (insn & 0x380) {
+       case 0x280:
+               /* FDC instruction */
+               fallthrough;
+       case 0x380:
+               /* PDC and FIC instructions */
+               if (printk_ratelimit()) {
+                       pr_warn("BUG: nullifying cache flush/purge instruction\n");
+                       show_regs(regs);
+               }
+               if (insn & 0x20) {
+                       /* Base modification */
+                       breg = (insn >> 21) & 0x1f;
+                       xreg = (insn >> 16) & 0x1f;
+                       if (breg && xreg)
+                               regs->gr[breg] += regs->gr[xreg];
+               }
+               regs->gr[0] |= PSW_N;
+               return 1;
+
+       case 0x180:
+               /* PROBE instruction */
+               treg = insn & 0x1f;
+               if (regs->isr) {
+                       tsk = current;
+                       mm = tsk->mm;
+                       if (mm) {
+                               /* Search for VMA */
+                               address = regs->ior;
+                               mmap_read_lock(mm);
+                               vma = find_vma_prev(mm, address, &prev_vma);
+                               mmap_read_unlock(mm);
+
+                               /*
+                                * Check if access to the VMA is okay.
+                                * We don't allow for stack expansion.
+                                */
+                               acc_type = (insn & 0x40) ? VM_WRITE : VM_READ;
+                               if (vma
+                                   && address >= vma->vm_start
+                                   && (vma->vm_flags & acc_type) == acc_type)
+                                       val = 1;
+                       }
+               }
+               if (treg)
+                       regs->gr[treg] = val;
+               regs->gr[0] |= PSW_N;
+               return 1;
+
+       case 0x300:
+               /* LPA instruction */
+               if (insn & 0x20) {
+                       /* Base modification */
+                       breg = (insn >> 21) & 0x1f;
+                       xreg = (insn >> 16) & 0x1f;
+                       if (breg && xreg)
+                               regs->gr[breg] += regs->gr[xreg];
+               }
+               treg = insn & 0x1f;
+               if (treg)
+                       regs->gr[treg] = 0;
+               regs->gr[0] |= PSW_N;
+               return 1;
+
+       default:
+               break;
+       }
+
+       return 0;
+}