lkmc.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /* https://cirosantilli.com/linux-kernel-module-cheat#lkmc-c */
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <lkmc.h>
  7. #define LKMC_ASSERT_EQ_DEFINE(bits) \
  8. LKMC_ASSERT_EQ_DECLARE(bits) \
  9. { \
  10. if (val1 != val2) { \
  11. printf("%s failed\n", __func__); \
  12. printf("val1 0x%" PRIX ## bits "\n", val1); \
  13. printf("val2 0x%" PRIX ## bits "\n", val2); \
  14. lkmc_assert_fail(line); \
  15. } \
  16. }
  17. LKMC_ASSERT_EQ_DEFINE(32)
  18. LKMC_ASSERT_EQ_DEFINE(64)
  19. #undef ASSERT_EQ_DEFINE
  20. void lkmc_assert_fail(uint32_t line) {
  21. printf("error: assertion failed at line: %" PRIu32 "\n", line);
  22. fflush(stdout);
  23. abort();
  24. }
  25. void lkmc_assert_memcmp(
  26. const void *s1,
  27. const void *s2,
  28. size_t n,
  29. uint32_t line
  30. ) {
  31. size_t i;
  32. uint8_t *s1b, *s2b;
  33. uint8_t b1, b2;
  34. s1b = (uint8_t *)s1;
  35. s2b = (uint8_t *)s2;
  36. for (i = 0; i < n; ++i) {
  37. b1 = s1b[i];
  38. b2 = s2b[i];
  39. if (b1 != b2) {
  40. printf(
  41. "%s failed: "
  42. "byte1, byte2, index: "
  43. "0x%02" PRIX8 " 0x%02" PRIX8 " 0x%zX\n",
  44. __func__,
  45. b1,
  46. b2,
  47. i
  48. );
  49. lkmc_assert_fail(line);
  50. }
  51. }
  52. }
  53. void lkmc_print_hex_32(uint32_t x) {
  54. printf("0x%08" PRIX32, x);
  55. }
  56. void lkmc_print_hex_64(uint64_t x) {
  57. printf("0x%016" PRIX64, x);
  58. }
  59. void lkmc_print_newline() {
  60. printf("\n");
  61. }
  62. #if defined(__arm__)
  63. void lkmc_arm_psci_cpu_on(
  64. uint32_t target_cpu,
  65. uint32_t entry_point_address,
  66. uint32_t context_id
  67. ) {
  68. register int r0 __asm__ ("r0") = 0x84000003;
  69. register int r1 __asm__ ("r1") = target_cpu;
  70. register int r2 __asm__ ("r2") = entry_point_address;
  71. register int r3 __asm__ ("r3") = context_id;
  72. __asm__ __volatile__(
  73. "hvc 0\n"
  74. :
  75. : "r" (r0),
  76. "r" (r1),
  77. "r" (r2),
  78. "r" (r3)
  79. :
  80. );
  81. }
  82. #elif defined(__aarch64__)
  83. #define LKMC_SYSREG_READ_WRITE(nbits, name) \
  84. LKMC_CONCAT(LKMC_CONCAT(uint, nbits), _t) LKMC_CONCAT(LKMC_CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, read_), name)(void) { \
  85. LKMC_CONCAT(LKMC_CONCAT(uint, nbits), _t) name; \
  86. __asm__ __volatile__("mrs %0, " #name : "=r" (name) : : ); \
  87. return name; \
  88. } \
  89. void LKMC_CONCAT(LKMC_CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, write_), name)(LKMC_CONCAT(LKMC_CONCAT(uint, nbits), _t) name) { \
  90. __asm__ __volatile__("msr " #name ", %0" : : "r" (name) : ); \
  91. } \
  92. void LKMC_CONCAT(LKMC_CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, print_), name)(void) { \
  93. printf(#name " 0x%" PRIX ## nbits "\n", LKMC_CONCAT(LKMC_CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, read_), name)()); \
  94. }
  95. LKMC_SYSREG_OPS
  96. #undef LKMC_SYSREG_READ_WRITE
  97. uint64_t lkmc_aarch64_cpu_id() {
  98. /* TODO: cores beyond 4th?
  99. * Mnemonic: Main Processor ID Register
  100. */
  101. return lkmc_sysreg_read_mpidr_el1() & 3;
  102. }
  103. void lkmc_aarch64_psci_cpu_on(
  104. uint64_t target_cpu,
  105. uint64_t entry_point_address,
  106. uint64_t context_id
  107. ) {
  108. register int w0 __asm__ ("w0") = 0xc4000003;
  109. register int x1 __asm__ ("x1") = target_cpu;
  110. register int x2 __asm__ ("x2") = entry_point_address;
  111. register int x3 __asm__ ("x3") = context_id;
  112. __asm__ __volatile__(
  113. "hvc 0\n"
  114. :
  115. : "r" (w0),
  116. "r" (x1),
  117. "r" (x2),
  118. "r" (x3)
  119. :
  120. );
  121. }
  122. #endif