@@ -152,8 +152,16 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long ra, rb, dar, insn;
#ifdef DEBUG_DCBX
const char *istr = NULL;
+ int ret;
+
+ insn = 0;
+ if (user_mode(regs)) {
+ if ((ret = get_user(insn, (unsigned long __user *)regs->nip)))
+ printk(KERN_CRIT "get_user:NIP:0x%08lx, err:%d\n",
+ regs->nip, ret);
+ } else
+ insn = *((unsigned long *)regs->nip);
- insn = *((unsigned long *)regs->nip);
if (((insn >> (31-5)) & 0x3f) == 31) {
if (((insn >> 1) & 0x3ff) == 1014) /* dcbz ? 0x3f6 */
istr = "dcbz";
@@ -178,20 +186,27 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
ra, rb, dar);
is_write = 0;
}
-
+#if 0
if (trap == 0x300 && address != dar) {
__asm__ ("mtdar %0" : : "r" (dar));
return 0;
}
+#endif
}
}
#endif
if (address == 0x00f0 && trap == 0x300) {
- pte_t *ptep;
-
+ int ret;
/* This is from a dcbX or icbi insn gone bad, these
* insn do not set DAR so we have to do it here instead */
- insn = *((unsigned long *)regs->nip);
+ if (user_mode(regs)) {
+ if ((ret = get_user(insn, (unsigned long __user *)regs->nip))) {
+ printk(KERN_CRIT "get_user:NIP:%lx, err:%d\n",
+ regs->nip, ret);
+ goto bad_area_nosemaphore;
+ }
+ } else
+ insn = *((unsigned long *)regs->nip);
ra = (insn >> (31-15)) & 0x1f; /* Reg RA */
rb = (insn >> (31-20)) & 0x1f; /* Reg RB */
@@ -206,18 +221,6 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
trap, address, dar, error_code, istr);
#endif
address = dar;
-#if 1
- if (is_write && get_pteptr(mm, dar, &ptep, NULL)) {
- pte_t my_pte = *ptep;
-
- if (pte_present(my_pte) && pte_write(my_pte)) {
- pte_val(my_pte) |= _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE;
- set_pte_at(mm, dar, ptep, my_pte);
- }
- }
-#else
- return 0;
-#endif
}
}
#endif