File paflib.elf_EBB_fixes.patch of Package paflib

commit 1073bf6b5984418ac86e60483d98e16b7d8672ad
Author: Adhemerval Zanella <azanella@linux.vnet.ibm.com>
Date:   Tue Jun 10 07:53:29 2014 -0500

    ebb: ELFv2 EBB fixes
    
    This patches fixes two issues with ELFv2 for EBB: one that the TOC
    is not correct materialized and other that EBB setups the wrongly
    internal handler.
    
    This patch also adds memory barriers on EBB setup to ensure it is
    correct before function returns in thread environments.
    
    	* common/paf-common.h: Add 'mb' memory barrier macro.
    	* ebb/ebb-callback-ppc64.S: Fix the TOC materialization for ELFv2.
    	* ebb/ebb-sysdep.h: Define ELFv2 entrypoint as null to avoid local
    	entries to be used (since EBB handler needs to save all the state
    	befora tamper r2).
    	* ebb/ebb.c: Fix ELFv2 handler setup and add memory barriers.

diff --git a/common/paf-common.h b/common/paf-common.h
index 2e3ef92..6b0af53 100644
--- a/common/paf-common.h
+++ b/common/paf-common.h
@@ -55,6 +55,9 @@ typedef unsigned long int spr_t;
 	       : : "r" (__spr));			\
   })
 
+#define mb()                                            \
+  asm volatile("sync" : : : "memory");
+
 
 #ifdef ENABLE_DEBUG
 # define DEBUG(fmt, args...) fprintf(stderr, "%s:%d: debug: " fmt "\n", \
diff --git a/ebb/ebb-callback-ppc64.S b/ebb/ebb-callback-ppc64.S
index 697dbb8..3ab6586 100644
--- a/ebb/ebb-callback-ppc64.S
+++ b/ebb/ebb-callback-ppc64.S
@@ -523,8 +523,7 @@
   lxvd2x   v30,0,r9;                                               \
   lxvd2x   v31,0,r10;
 
-/* The new PPC64 LE ABI the TOC is already synthesized in global calls
-   (the case for the callback calls).  */
+/* Restore our TOC pointer using our entry point */
 #if _CALL_ELF != 2
 # define SETUP_TOC(__func)                                         \
   lis      r2,(__func)@highest;                                    \
@@ -533,8 +532,15 @@
   oris     r2,r2,(__func)@h;                                       \
   ori      r2,r2,(__func)@l;                                       \
   ld       r2,8(r2);
-# else
-# define SETUP_TOC(__func)
+#else
+# define SETUP_TOC(__func)                                         \
+   lis     r12,(__func)@highest;                                   \
+   ori     r12,r12,(__func)@higher;                                \
+   rldicr  r12,r12,32,31;                                          \
+   oris    r12,r12,(__func)@high;                                  \
+   ori     r12,r12,(__func)@l;                                     \
+0: addis   r2,r12,(.TOC.-0b)@ha;                                   \
+   addi	   r2,r2,(.TOC.-0b)@l;
 #endif
 
 .hidden __paf_ebb_ebb_hook
diff --git a/ebb/ebb-sysdep.h b/ebb/ebb-sysdep.h
index 0581dde..9c9fe5c 100644
--- a/ebb/ebb-sysdep.h
+++ b/ebb/ebb-sysdep.h
@@ -180,10 +180,9 @@ name##: OPD_ENT (name);					\
 #define END_ABI(name)					\
 	.size name,.-name;
 
-#define LOCALENTRY(name)				\
-1:      addis   r2,r12,.TOC.-1b@ha;			\
-        addi    r2,r2,.TOC.-1b@l;			\
-        .localentry name,.-name;
+/* Although ELFv2 defines the localentry entrypoint, for EBB handlers we
+   need to save current status before materialize handler's TOC.  */
+#define LOCALENTRY(name)
 # endif
 
 /* Both PPC64 LE and BE defines  */
diff --git a/ebb/ebb.c b/ebb/ebb.c
index f8cffed..99209f7 100644
--- a/ebb/ebb.c
+++ b/ebb/ebb.c
@@ -81,6 +81,9 @@ paf_ebb_pmu_init (uint64_t raw_event, int group)
   if (fd == -1)
     return -1;
 
+  /* Ensure any SPR writes are ordered vs us */
+  mb ();
+
   if (ioctl (fd, PERF_EVENT_IOC_ENABLE, 0) != 0)
     {
       close (fd);
@@ -93,6 +96,8 @@ paf_ebb_pmu_init (uint64_t raw_event, int group)
       return -1;
     }
 
+  mb ();
+
   return fd;
 }
 
@@ -127,11 +132,16 @@ __ebb_callback_handler_addr (paf_ebb_callback_type_t type)
     callback = __paf_ebb_callback_handler_vsr;
 
 #ifdef __powerpc64__
-  struct odp_entry_t {
+# if defined(_CALL_ELF) && _CALL_ELF==2
+  return (uintptr_t) callback;
+# else
+  struct odp_entry_t
+  {
     uintptr_t addr;
     uintptr_t toc;
   } *odp_entry = (struct odp_entry_t*)(callback);
   return odp_entry->addr;
+# endif
 #else
   return (uintptr_t)callback;
 #endif
@@ -173,8 +183,12 @@ paf_ebb_register_handler (ebbhandler_t handler, void *context,
   __paf_ebb_set_thread_flags (flags);
    
   handlerfp = __ebb_callback_handler_addr (type);
+  /* Ensure the user handler is set before it set the internal one */
+  mb ();
   mtspr (EBBHR, handlerfp);
 
+  /* Make sure the handler is set before we return */
+  mb ();
   return handler;
 }
 
@@ -189,6 +203,8 @@ paf_ebb_enable_branches (void)
 
   /* Enable PMU Event-Based exception (PME - bit 31).  */
   mtspr (BESCRS, (1 << 31));
+  /* Make sure the handler is set before we return */
+  mb ();
   return 0;
 }
 
@@ -203,5 +219,7 @@ paf_ebb_disable_branches (void)
 
   /* Disable PMU Event-Based exception (PME - bit 31).  */
   mtspr (BESCRR, (1 << 31));
+  /* Make sure the handler is set before we return */
+  mb ();
   return 0;
 }
openSUSE Build Service is sponsored by