@@ -57,7 +57,7 @@ static int mca_patcher_overwrite_apply_patch(mca_patcher_base_patch_t *patch)
57
57
return OPAL_SUCCESS ;
58
58
}
59
59
60
- /* end of #if defined(__i386__) || defined(__x86_64__) || defined(__ia64__) */
60
+ /* end of #if defined(__i386__) || defined(__x86_64__) */
61
61
// ------------------------------------------------- PPC equivalent:
62
62
#elif (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC32 ) || (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC64 )
63
63
@@ -214,6 +214,78 @@ static int mca_patcher_overwrite_apply_patch(mca_patcher_base_patch_t *patch)
214
214
215
215
#endif
216
216
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
+
217
289
static int mca_patcher_overwrite_patch_address (uintptr_t sys_addr , uintptr_t hook_addr )
218
290
{
219
291
mca_patcher_base_patch_t * patch ;
@@ -268,7 +340,13 @@ static int mca_patcher_overwrite_patch_symbol(const char *func_symbol_name, uint
268
340
* func_old_addr = 0 ;
269
341
}
270
342
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
+ }
272
350
}
273
351
274
352
mca_patcher_base_module_t mca_patcher_overwrite_module = {
0 commit comments