@@ -57,7 +57,7 @@ static int mca_patcher_overwrite_apply_patch(mca_patcher_base_patch_t *patch)
5757 return OPAL_SUCCESS ;
5858}
5959
60- /* end of #if defined(__i386__) || defined(__x86_64__) || defined(__ia64__) */
60+ /* end of #if defined(__i386__) || defined(__x86_64__) */
6161// ------------------------------------------------- PPC equivalent:
6262#elif (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC32 ) || (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC64 )
6363
@@ -214,6 +214,78 @@ static int mca_patcher_overwrite_apply_patch(mca_patcher_base_patch_t *patch)
214214
215215#endif
216216
217+ /*
218+ * The logic in this function for each platform is based on code from
219+ * mca_patcher_overwrite_apply_patch(). There are 2 general approaches:
220+ * 1: Directly check constant instructions (ignoring addresses as parameters)
221+ * 2: Generate a bit mask by passing min and max values to underlying helper
222+ * functions and negate the XOR'ed results. These results can be used to
223+ * mask off transient values (like addresess) and non-instruction values
224+ * (like register contents). Once the masks are applied, the results are
225+ * compared against the min values directly to check for equality. If equal,
226+ * we consider the memory to be previously patched.
227+ */
228+ static bool mca_patcher_is_function_patched (unsigned char * target )
229+ {
230+
231+ #if (OPAL_ASSEMBLY_ARCH == OPAL_IA32 )
232+ return (* (unsigned char * )target == 0xe9 );
233+ #elif (OPAL_ASSEMBLY_ARCH == OPAL_X86_64 )
234+ return (
235+ (* (unsigned short * )(target + 0 ) == 0xbb49 ) &&
236+ (* (unsigned char * )(target + 10 ) == 0x41 ) &&
237+ (* (unsigned char * )(target + 11 ) == 0xff ) &&
238+ (* (unsigned char * )(target + 12 ) == 0xe3 )
239+ );
240+ #elif (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC32 ) || (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC64 )
241+ const unsigned int gr_max = 0xF ; //11 is used in our patching code, but is the max 4 or 5 bits?
242+ const unsigned int addr_max = 0xFFFF ;
243+ unsigned int addis_base = addis ( 0 , 0 , 0 );
244+ unsigned int addis_mask = ~(addis_base ^ addis ( gr_max , 0 , addr_max ));
245+ unsigned int ori_base = ori ( 0 , 0 , 0 );
246+ unsigned int ori_mask = ~( ori_base ^ ori ( gr_max , gr_max , addr_max ));
247+ unsigned int mtspr_base = mtspr ( 9 , 0 ); // 9 = CTR
248+ unsigned int mtspr_mask = ~(mtspr_base ^ mtspr ( 9 , gr_max ));
249+ unsigned int bcctr_base = bcctr (20 , 0 , 0 ); // 20 = always
250+ unsigned int bcctr_mask = ~(bcctr_base ^ bcctr (20 , 0 , 0 ));
251+ #if (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC32 )
252+
253+ return (
254+ ((* (unsigned int * ) (target + 0 )) & addis_mask ) == addis_base &&
255+ ((* (unsigned int * ) (target + 4 )) & ori_mask ) == ori_base &&
256+ ((* (unsigned int * ) (target + 8 )) & mtspr_mask ) == mtspr_base &&
257+ ((* (unsigned int * ) (target + 12 )) & bcctr_mask ) == bcctr_base
258+ );
259+ #else
260+ unsigned int rldicr_base = rldicr ( 0 , 0 , 32 , 31 );
261+ unsigned int rldicr_mask = ~(rldicr_base ^ rldicr ( gr_max , gr_max , 32 , 31 ));
262+ unsigned int oris_base = oris ( 0 , 0 , 0 );
263+ unsigned int oris_mask = ~(oris_base ^ oris ( gr_max , gr_max , addr_max ));
264+
265+ return (
266+ ((* (unsigned int * ) (target + 0 )) & addis_mask ) == addis_base &&
267+ ((* (unsigned int * ) (target + 4 )) & ori_mask ) == ori_base &&
268+ ((* (unsigned int * ) (target + 8 )) & rldicr_mask ) == rldicr_base &&
269+ ((* (unsigned int * ) (target + 12 )) & oris_mask ) == oris_base &&
270+ ((* (unsigned int * ) (target + 16 )) & ori_mask ) == ori_base &&
271+ ((* (unsigned int * ) (target + 20 )) & mtspr_mask ) == mtspr_base &&
272+ ((* (unsigned int * ) (target + 24 )) & bcctr_mask ) == bcctr_base
273+ );
274+ #endif
275+ #elif defined(__aarch64__ )
276+ uint32_t mov_mask = ~((0xFFFF << 5 ) | 0x1F );
277+ uint32_t br_mask = ~(0x1F << 5 );
278+
279+ return (
280+ ((* (uint32_t * ) (target + 0 )) & mov_mask ) == mov (0 , 3 , 0 ) &&
281+ ((* (uint32_t * ) (target + 4 )) & mov_mask ) == movk (0 , 2 , 0 ) &&
282+ ((* (uint32_t * ) (target + 8 )) & mov_mask ) == movk (0 , 1 , 0 ) &&
283+ ((* (uint32_t * ) (target + 12 )) & mov_mask ) == movk (0 , 0 , 0 ) &&
284+ ((* (uint32_t * ) (target + 16 )) & br_mask ) == br (0 )
285+ );
286+ #endif
287+ }
288+
217289static int mca_patcher_overwrite_patch_address (uintptr_t sys_addr , uintptr_t hook_addr )
218290{
219291 mca_patcher_base_patch_t * patch ;
@@ -268,7 +340,13 @@ static int mca_patcher_overwrite_patch_symbol(const char *func_symbol_name, uint
268340 * func_old_addr = 0 ;
269341 }
270342
271- return mca_patcher_overwrite_patch_address (old_addr , func_new_addr );
343+ if (mca_patcher_is_function_patched ((unsigned char * )old_addr )) {
344+ opal_output_verbose (10 , 0 , "function %s is already patched; stopping further patching\n" ,
345+ func_symbol_name );
346+ return OPAL_ERR_RESOURCE_BUSY ;
347+ } else {
348+ return mca_patcher_overwrite_patch_address (old_addr , func_new_addr );
349+ }
272350}
273351
274352mca_patcher_base_module_t mca_patcher_overwrite_module = {
0 commit comments