alternative.h 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. #ifndef __ASM_ALTERNATIVE_H
  2. #define __ASM_ALTERNATIVE_H
  3. #include <linux/types.h>
  4. #include <linux/stddef.h>
  5. #include <linux/stringify.h>
  6. struct alt_instr {
  7. s32 orig_offset; /* offset to original instruction */
  8. s32 alt_offset; /* offset to replacement instruction */
  9. u16 cpufeature; /* cpufeature bit set for replacement */
  10. u8 orig_len; /* size of original instruction(s) */
  11. u8 alt_len; /* size of new instruction(s), <= orig_len */
  12. };
  13. void apply_alternatives_all(void);
  14. void apply_alternatives(void *start, size_t length);
  15. void free_alternatives_memory(void);
  16. #define ALTINSTR_ENTRY(feature) \
  17. " .word 661b - .\n" /* label */ \
  18. " .word 663f - .\n" /* new instruction */ \
  19. " .hword " __stringify(feature) "\n" /* feature bit */ \
  20. " .byte 662b-661b\n" /* source len */ \
  21. " .byte 664f-663f\n" /* replacement len */
  22. /* alternative assembly primitive: */
  23. #define ALTERNATIVE(oldinstr, newinstr, feature) \
  24. "661:\n\t" \
  25. oldinstr "\n" \
  26. "662:\n" \
  27. ".pushsection .altinstructions,\"a\"\n" \
  28. ALTINSTR_ENTRY(feature) \
  29. ".popsection\n" \
  30. ".pushsection .altinstr_replacement, \"a\"\n" \
  31. "663:\n\t" \
  32. newinstr "\n" \
  33. "664:\n\t" \
  34. ".popsection\n\t" \
  35. ".if ((664b-663b) != (662b-661b))\n\t" \
  36. " .error \"Alternatives instruction length mismatch\"\n\t"\
  37. ".endif\n"
  38. #endif /* __ASM_ALTERNATIVE_H */