htif.c 3.6 KB

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