From 0e2c0cc0f4c8885e1e6848db53a440d404cc7621 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Thu, 4 Jul 2019 18:25:49 +0000 Subject: [PATCH] powerpc: skip poking CCR if it is unchanged * linux/powerpc/set_error.c (arch_set_r3_ccr): New function. (arch_set_error, arch_set_success): Use it. --- linux/powerpc/set_error.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/linux/powerpc/set_error.c b/linux/powerpc/set_error.c index 068d6b74..7585dd33 100644 --- a/linux/powerpc/set_error.c +++ b/linux/powerpc/set_error.c @@ -6,25 +6,30 @@ */ static int -arch_set_error(struct tcb *tcp) +arch_set_r3_ccr(struct tcb *tcp, const unsigned long r3, + const unsigned long ccr_set, const unsigned long ccr_clear) { if (ptrace_syscall_info_is_valid() && upeek(tcp, sizeof(long) * PT_CCR, &ppc_regs.ccr)) return -1; - ppc_regs.gpr[3] = tcp->u_error; - ppc_regs.ccr |= 0x10000000; - return upoke(tcp, sizeof(long) * PT_CCR, ppc_regs.ccr) || - upoke(tcp, sizeof(long) * (PT_R0 + 3), ppc_regs.gpr[3]); + const unsigned long old_ccr = ppc_regs.ccr; + ppc_regs.gpr[3] = r3; + ppc_regs.ccr |= ccr_set; + ppc_regs.ccr &= ~ccr_clear; + if (ppc_regs.ccr != old_ccr && + upoke(tcp, sizeof(long) * PT_CCR, ppc_regs.ccr)) + return -1; + return upoke(tcp, sizeof(long) * (PT_R0 + 3), ppc_regs.gpr[3]); +} + +static int +arch_set_error(struct tcb *tcp) +{ + return arch_set_r3_ccr(tcp, tcp->u_error, 0x10000000, 0); } static int arch_set_success(struct tcb *tcp) { - if (ptrace_syscall_info_is_valid() && - upeek(tcp, sizeof(long) * PT_CCR, &ppc_regs.ccr)) - return -1; - ppc_regs.gpr[3] = tcp->u_rval; - ppc_regs.ccr &= ~0x10000000; - return upoke(tcp, sizeof(long) * PT_CCR, ppc_regs.ccr) || - upoke(tcp, sizeof(long) * (PT_R0 + 3), ppc_regs.gpr[3]); + return arch_set_r3_ccr(tcp, tcp->u_rval, 0, 0x10000000); } -- 2.40.0