static DEFINE_PER_CPU(struct uprobe_ctlblk, ucb) = { 0, NULL };
+static void save_current_flags(struct pt_regs *regs)
+{
+ __get_cpu_var(ucb).flags = regs->EREG(flags);
+}
+
+static void restore_current_flags(struct pt_regs *regs)
+{
+ regs->EREG(flags) &= ~IF_MASK;
+ regs->EREG(flags) |= __get_cpu_var(ucb).flags & IF_MASK;
+}
+
int arch_prepare_uprobe(struct uprobe *up, struct hlist_head *page_list)
{
int ret = 0;
switch (insns[0]) {
case 0x9c: /* pushfl */
*tos &= ~(TF_MASK | IF_MASK);
- *tos |= flags;
+ *tos |= flags & (TF_MASK | IF_MASK);
break;
case 0xc2: /* iret/ret/lret */
case 0xc3:
struct task_struct *task = current;
pid_t tgid = task->tgid;
+ save_current_flags(regs);
+
addr = (kprobe_opcode_t *)(regs->EREG(ip) - sizeof(kprobe_opcode_t));
p = get_ukprobe(addr, tgid);
}
__get_cpu_var(ucb).p = p;
- __get_cpu_var(ucb).flags = (regs->EREG(flags) & (TF_MASK | IF_MASK));
return 1;
}
unsigned long flags = __get_cpu_var(ucb).flags;
resume_execution(p, regs, flags);
+ restore_current_flags(regs);
return 1;
}