@@ -75,20 +75,33 @@ static int PatchLoadImm (uintptr_t addr, unsigned int reg, size_t value)
7575
7676#endif
7777
78- #if defined(__i386__ ) || defined(__x86_64__ ) || defined(__ia64__ )
79-
80- static void flush_and_invalidate_cache (unsigned long a )
78+ static void flush_and_invalidate_cache (unsigned long a )
8179{
82- #if defined(__i386__ )
83- /* does not work with AMD processors */
84- __asm__ volatile ("mfence;clflush %0;mfence" : :"m" (* (char * )a ));
85- #elif defined(__x86_64__ )
80+ #if OPAL_ASSEMBLY_ARCH == OPAL_IA32
81+ static int have_clflush = -1 ;
82+
83+ if (OPAL_UNLIKELY (-1 == have_clflush )) {
84+ int32_t cpuid1 , cpuid2 ;
85+ const int32_t level = 1 ;
86+
87+ __asm__ volatile ("cpuid" :
88+ "=a" (cpuid1 ), "=d" (cpuid2 ) :
89+ "a" (level ) :
90+ "ecx" , "ebx" );
91+ /* clflush is in edx bit 19 */
92+ have_clflush = !!(cpuid2 & (1 << 19 ));
93+ }
94+
95+ if (have_clflush ) {
96+ /* does not work with AMD processors */
97+ __asm__ volatile ("mfence;clflush %0;mfence" : :"m" (* (char * )a ));
98+ }
99+ #elif OPAL_ASSEMBLY_ARCH == OPAL_AMD64
86100 __asm__ volatile ("mfence;clflush %0;mfence" : :"m" (* (char * )a ));
87- #elif defined( __ia64__ )
101+ #elif OPAL_ASSEMBLY_ARCH == OPAL_IA64
88102 __asm__ volatile ("fc %0;; sync.i;; srlz.i;;" : : "r" (a ) : "memory" );
89103#endif
90104}
91- #endif
92105
93106// modify protection of memory range
94107static void ModifyMemoryProtection (uintptr_t addr , size_t length , int prot )
@@ -117,11 +130,9 @@ static inline void apply_patch (unsigned char *patch_data, uintptr_t address, si
117130{
118131 ModifyMemoryProtection (address , data_size , PROT_EXEC |PROT_READ |PROT_WRITE );
119132 memcpy ((void * ) address , patch_data , data_size );
120- #if defined(__i386__ ) || defined(__x86_64__ ) || defined(__ia64__ )
121133 for (size_t i = 0 ; i < data_size ; i += 16 ) {
122134 flush_and_invalidate_cache (address + i );
123135 }
124- #endif
125136
126137 ModifyMemoryProtection (address , data_size , PROT_EXEC |PROT_READ );
127138}
0 commit comments