aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-powerpc/system.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asm-powerpc/system.h')
-rw-r--r--include/asm-powerpc/system.h50
1 files changed, 49 insertions, 1 deletions
diff --git a/include/asm-powerpc/system.h b/include/asm-powerpc/system.h
index 5b2ecbc47907..3536a5cd7a2d 100644
--- a/include/asm-powerpc/system.h
+++ b/include/asm-powerpc/system.h
@@ -289,7 +289,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned long old, unsigned long new)
289 289
290#ifdef CONFIG_PPC64 290#ifdef CONFIG_PPC64
291static __inline__ unsigned long 291static __inline__ unsigned long
292__cmpxchg_u64(volatile long *p, unsigned long old, unsigned long new) 292__cmpxchg_u64(volatile unsigned long *p, unsigned long old, unsigned long new)
293{ 293{
294 unsigned long prev; 294 unsigned long prev;
295 295
@@ -359,5 +359,53 @@ extern void reloc_got2(unsigned long);
359 359
360#define PTRRELOC(x) ((typeof(x)) add_reloc_offset((unsigned long)(x))) 360#define PTRRELOC(x) ((typeof(x)) add_reloc_offset((unsigned long)(x)))
361 361
362static inline void create_instruction(unsigned long addr, unsigned int instr)
363{
364 unsigned int *p;
365 p = (unsigned int *)addr;
366 *p = instr;
367 asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (p));
368}
369
370/* Flags for create_branch:
371 * "b" == create_branch(addr, target, 0);
372 * "ba" == create_branch(addr, target, BRANCH_ABSOLUTE);
373 * "bl" == create_branch(addr, target, BRANCH_SET_LINK);
374 * "bla" == create_branch(addr, target, BRANCH_ABSOLUTE | BRANCH_SET_LINK);
375 */
376#define BRANCH_SET_LINK 0x1
377#define BRANCH_ABSOLUTE 0x2
378
379static inline void create_branch(unsigned long addr,
380 unsigned long target, int flags)
381{
382 unsigned int instruction;
383
384 if (! (flags & BRANCH_ABSOLUTE))
385 target = target - addr;
386
387 /* Mask out the flags and target, so they don't step on each other. */
388 instruction = 0x48000000 | (flags & 0x3) | (target & 0x03FFFFFC);
389
390 create_instruction(addr, instruction);
391}
392
393static inline void create_function_call(unsigned long addr, void * func)
394{
395 unsigned long func_addr;
396
397#ifdef CONFIG_PPC64
398 /*
399 * On PPC64 the function pointer actually points to the function's
400 * descriptor. The first entry in the descriptor is the address
401 * of the function text.
402 */
403 func_addr = *(unsigned long *)func;
404#else
405 func_addr = (unsigned long)func;
406#endif
407 create_branch(addr, func_addr, BRANCH_SET_LINK);
408}
409
362#endif /* __KERNEL__ */ 410#endif /* __KERNEL__ */
363#endif /* _ASM_POWERPC_SYSTEM_H */ 411#endif /* _ASM_POWERPC_SYSTEM_H */