File it-revert-dyn_patching.patch of Package itrace
---
src/driver/Makefile | 2 -
src/driver/ppc64/pi_itrace.c | 65 +++++++++++++++++++++++++++++++++++++++++--
2 files changed, 64 insertions(+), 3 deletions(-)
--- a/src/driver/Makefile
+++ b/src/driver/Makefile
@@ -1,5 +1,5 @@
src := $(ITRACE_DIR)/obj/ppc64
-EXTRA_CFLAGS += -D_LINUX -D_ST_ITRACE_ONLY
+EXTRA_CFLAGS += -D_LINUX -D_ST_ITRACE_ONLY -D_NO_DYNAMIC_PATCHING
EXTRA_CFLAGS += -I$(src)/../../include
# for hooks.h
EXTRA_CFLAGS += -I$(src)
--- a/src/driver/ppc64/pi_itrace.c
+++ b/src/driver/ppc64/pi_itrace.c
@@ -52,6 +52,9 @@
* 06/03/08 Karthik Ganesan Changed the way in which the instructions that clear the
* MSRRI are handled. We switch to branch mode within such
* unsafe areas of code.
+ * 10/21/08 Maynard Johnson Reinstate skipping around reservations. Default behavior
+ * will still use dynamic patching, but a compile switch
+ * will control which method.
*/
/* TODO: summarize PMC usage */
@@ -223,7 +226,28 @@ int reservation_inst(unsigned int instr)
#endif
#endif // STAP_ITRACE BODY
+#ifdef _NO_DYNAMIC_PATCHING
+void skip_trace_section(struct pt_regs *regs)
+{
+ unsigned int mmcr0 = mfspr(SPRN_MMCR0);
+ mmcr0 |= MMCR0_PMXE;
+ mmcr0 |= 0x4000; /* set PMCjCE bit */
+ mtspr(SPRN_MMCR0, mmcr0);
+
+ if (__is_processor(PV_POWER5) || __is_processor(PV_POWER5p) ||
+ __is_processor(PV_POWER6)) {
+ unsigned int mmcr1 = mfspr(SPRN_MMCR1);
+ mmcr1 &= ~(0xff0000); /* clear out PMC2SEL */
+ mmcr1 |= 0x020000; /* set PMC2SEL to 00000010 bits */
+ mtspr(SPRN_MMCR1, mmcr1);
+
+ mtspr(SPRN_PMC2, 0x7fffff40); /* set up to overflow soon */
+ } else
+ mtspr(SPRN_PMC4, 0x7ffffff0); /* set up to overflow soon */
+ regs->msr |= MSR_PM;
+}
+#endif
//
// is_stepping_safe_ss()
@@ -240,6 +264,13 @@ int is_stepping_safe_ss(struct pt_regs *
if (clears_msrri(regs, instr, 1))
return 0;
+#ifdef _NO_DYNAMIC_PATCHING
+ if (reservation_inst(instr)) {
+ skip_trace_section(regs);
+ return 0;
+ }
+#endif
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
/* 2.6.20 and earlier kernels (which includes SLES 9 and RHEL 4 kernels)
* had a problem in ret_from_except where if you take an exception after
@@ -258,6 +289,23 @@ int is_stepping_safe_ss(struct pt_regs *
return 1;
}
+#ifdef _NO_DYNAMIC_PATCHING
+/* Returns 1 if it's safe to continue branch stepping, 0 otherwise. */
+int is_stepping_safe_br(struct pt_regs *regs)
+{
+ unsigned long current_addr;
+
+ for (current_addr = regs->nip - 0x20;
+ current_addr <= (regs->nip + 0x20); current_addr += 4)
+ if (reservation_inst(*((unsigned int *)current_addr))) {
+ skip_trace_section(regs);
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
//
// ITrace_branch_hook()
@@ -335,15 +383,22 @@ int ITrace_branch_hook(struct pt_regs *
}
if (pi_itrace_pids[current->pid] & PIDS_ITRACE_ENABLE) {
+#ifdef _NO_DYNAMIC_PATCHING
+ if (!is_stepping_safe_br(regs)) {
+ regs->msr &= ~MSR_BE;
+ goto out;
+ }
+#endif
regs->msr |= MSR_BE;
pi_itrace_pids[current->pid] |= PIDS_ITRACE_ACTIVE;
} else {
regs->msr &= ~MSR_BE;
}
+out:
/* Reset the counter. Counting will start when the msr is restored */
mtspr(SPRN_PMC1, 0);
-
+
put_cpu();
return 1;
}
@@ -474,8 +529,10 @@ int ITrace_branch_hook_ss(struct pt_regs
// Switch Single Stepping off
regs->msr &= ~MSR_SE;
+#ifndef _NO_DYNAMIC_PATCHING
// Switch Branch Stepping On
regs->msr |= MSR_BE;
+#endif
}
}
put_cpu();
@@ -799,7 +856,7 @@ int ITrace_install(uint32_t flag)
PDEBUG("Itrace already installed.\n");
return (PU_SUCCESS);
}
-
+#ifndef _NO_DYNAMIC_PATCHING
PDEBUG("ItraceInstall: start\n");
if (pi_install_stdcx_patch() != PU_SUCCESS) {
@@ -809,6 +866,7 @@ int ITrace_install(uint32_t flag)
if (pi_install_trapbrk_patch() != PU_SUCCESS) {
printk("WARNING: trapbrk_patch not installed, ignore unless on RHEL\n");
}
+#endif
if (flag & PI_ITRACE_FLAG_SS) {
printk(KERN_NOTICE "PI: ITrace installed - single step mode\n");
@@ -862,8 +920,11 @@ int ITrace_remove(void)
#else
release_pmc_hardware();
#endif
+
+#ifndef _NO_DYNAMIC_PATCHING
pi_remove_stdcx_patch();
pi_remove_trapbrk_patch();
+#endif
return (PU_SUCCESS);
}