htif.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * SPDX-License-Identifier: BSD-3-Clause
  3. *
  4. * Copyright (c) 2010-2020, The Regents of the University of California
  5. * (Regents). All Rights Reserved.
  6. */
  7. #include <sbi/riscv_locks.h>
  8. #include <sbi/sbi_console.h>
  9. #include <sbi/sbi_system.h>
  10. #include <sbi_utils/sys/htif.h>
  11. #define HTIF_DATA_BITS 48
  12. #define HTIF_DATA_MASK ((1ULL << HTIF_DATA_BITS) - 1)
  13. #define HTIF_DATA_SHIFT 0
  14. #define HTIF_CMD_BITS 8
  15. #define HTIF_CMD_MASK ((1ULL << HTIF_CMD_BITS) - 1)
  16. #define HTIF_CMD_SHIFT 48
  17. #define HTIF_DEV_BITS 8
  18. #define HTIF_DEV_MASK ((1ULL << HTIF_DEV_BITS) - 1)
  19. #define HTIF_DEV_SHIFT 56
  20. #define HTIF_DEV_SYSTEM 0
  21. #define HTIF_DEV_CONSOLE 1
  22. #define HTIF_CONSOLE_CMD_GETC 0
  23. #define HTIF_CONSOLE_CMD_PUTC 1
  24. #if __riscv_xlen == 64
  25. # define TOHOST_CMD(dev, cmd, payload) \
  26. (((uint64_t)(dev) << HTIF_DEV_SHIFT) | \
  27. ((uint64_t)(cmd) << HTIF_CMD_SHIFT) | \
  28. (uint64_t)(payload))
  29. #else
  30. # define TOHOST_CMD(dev, cmd, payload) ({ \
  31. if ((dev) || (cmd)) __builtin_trap(); \
  32. (payload); })
  33. #endif
  34. #define FROMHOST_DEV(fromhost_value) \
  35. ((uint64_t)((fromhost_value) >> HTIF_DEV_SHIFT) & HTIF_DEV_MASK)
  36. #define FROMHOST_CMD(fromhost_value) \
  37. ((uint64_t)((fromhost_value) >> HTIF_CMD_SHIFT) & HTIF_CMD_MASK)
  38. #define FROMHOST_DATA(fromhost_value) \
  39. ((uint64_t)((fromhost_value) >> HTIF_DATA_SHIFT) & HTIF_DATA_MASK)
  40. #define PK_SYS_write 64
  41. volatile uint64_t tohost __attribute__((section(".htif")));
  42. volatile uint64_t fromhost __attribute__((section(".htif")));
  43. static int htif_console_buf;
  44. static spinlock_t htif_lock = SPIN_LOCK_INITIALIZER;
  45. static void __check_fromhost()
  46. {
  47. uint64_t fh = fromhost;
  48. if (!fh)
  49. return;
  50. fromhost = 0;
  51. /* this should be from the console */
  52. if (FROMHOST_DEV(fh) != HTIF_DEV_CONSOLE)
  53. __builtin_trap();
  54. switch (FROMHOST_CMD(fh)) {
  55. case HTIF_CONSOLE_CMD_GETC:
  56. htif_console_buf = 1 + (uint8_t)FROMHOST_DATA(fh);
  57. break;
  58. case HTIF_CONSOLE_CMD_PUTC:
  59. break;
  60. default:
  61. __builtin_trap();
  62. }
  63. }
  64. static void __set_tohost(uint64_t dev, uint64_t cmd, uint64_t data)
  65. {
  66. while (tohost)
  67. __check_fromhost();
  68. tohost = TOHOST_CMD(dev, cmd, data);
  69. }
  70. #if __riscv_xlen == 32
  71. static void do_tohost_fromhost(uint64_t dev, uint64_t cmd, uint64_t data)
  72. {
  73. spin_lock(&htif_lock);
  74. __set_tohost(HTIF_DEV_SYSTEM, cmd, data);
  75. while (1) {
  76. uint64_t fh = fromhost;
  77. if (fh) {
  78. if (FROMHOST_DEV(fh) == HTIF_DEV_SYSTEM &&
  79. FROMHOST_CMD(fh) == cmd) {
  80. fromhost = 0;
  81. break;
  82. }
  83. __check_fromhost();
  84. }
  85. }
  86. spin_unlock(&htif_lock);
  87. }
  88. static void htif_putc(char ch)
  89. {
  90. /* HTIF devices are not supported on RV32, so do a proxy write call */
  91. volatile uint64_t magic_mem[8];
  92. magic_mem[0] = PK_SYS_write;
  93. magic_mem[1] = HTIF_DEV_CONSOLE;
  94. magic_mem[2] = (uint64_t)(uintptr_t)&ch;
  95. magic_mem[3] = HTIF_CONSOLE_CMD_PUTC;
  96. do_tohost_fromhost(HTIF_DEV_SYSTEM, 0, (uint64_t)(uintptr_t)magic_mem);
  97. }
  98. #else
  99. static void htif_putc(char ch)
  100. {
  101. spin_lock(&htif_lock);
  102. __set_tohost(HTIF_DEV_CONSOLE, HTIF_CONSOLE_CMD_PUTC, ch);
  103. spin_unlock(&htif_lock);
  104. }
  105. #endif
  106. static int htif_getc(void)
  107. {
  108. int ch;
  109. #if __riscv_xlen == 32
  110. /* HTIF devices are not supported on RV32 */
  111. return -1;
  112. #endif
  113. spin_lock(&htif_lock);
  114. __check_fromhost();
  115. ch = htif_console_buf;
  116. if (ch >= 0) {
  117. htif_console_buf = -1;
  118. __set_tohost(HTIF_DEV_CONSOLE, HTIF_CONSOLE_CMD_GETC, 0);
  119. }
  120. spin_unlock(&htif_lock);
  121. return ch - 1;
  122. }
  123. static struct sbi_console_device htif_console = {
  124. .name = "htif",
  125. .console_putc = htif_putc,
  126. .console_getc = htif_getc
  127. };
  128. int htif_serial_init(void)
  129. {
  130. sbi_console_set_device(&htif_console);
  131. return 0;
  132. }
  133. static int htif_system_reset_check(u32 type, u32 reason)
  134. {
  135. return 1;
  136. }
  137. static void htif_system_reset(u32 type, u32 reason)
  138. {
  139. while (1) {
  140. fromhost = 0;
  141. tohost = 1;
  142. }
  143. }
  144. static struct sbi_system_reset_device htif_reset = {
  145. .name = "htif",
  146. .system_reset_check = htif_system_reset_check,
  147. .system_reset = htif_system_reset
  148. };
  149. int htif_system_reset_init(void)
  150. {
  151. sbi_system_reset_set_device(&htif_reset);
  152. return 0;
  153. }