shim_tcb.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. #ifndef _SHIM_TCB_H_
  2. #define _SHIM_TCB_H_
  3. #include <assert.h>
  4. #include <atomic.h>
  5. #include <pal.h>
  6. #define SHIM_TCB_CANARY 0xdeadbeef
  7. struct shim_regs {
  8. uint64_t orig_rax;
  9. uint64_t rsp;
  10. uint64_t r15;
  11. uint64_t r14;
  12. uint64_t r13;
  13. uint64_t r12;
  14. uint64_t r11;
  15. uint64_t r10;
  16. uint64_t r9;
  17. uint64_t r8;
  18. uint64_t rcx;
  19. uint64_t rdx;
  20. uint64_t rsi;
  21. uint64_t rdi;
  22. uint64_t rbx;
  23. uint64_t rbp;
  24. uint64_t rflags;
  25. uint64_t rip;
  26. };
  27. struct shim_context {
  28. struct shim_regs * regs;
  29. uint64_t fs_base;
  30. struct shim_context * next;
  31. uint64_t enter_time;
  32. struct atomic_int preempt;
  33. };
  34. struct debug_buf;
  35. typedef struct shim_tcb shim_tcb_t;
  36. struct shim_tcb {
  37. uint64_t canary;
  38. shim_tcb_t * self;
  39. struct shim_thread * tp;
  40. struct shim_context context;
  41. unsigned int tid;
  42. int pal_errno;
  43. struct debug_buf * debug_buf;
  44. /* This record is for testing the memory of user inputs.
  45. * If a segfault occurs with the range [start, end],
  46. * the code addr is set to cont_addr to alert the caller. */
  47. struct {
  48. void * start, * end;
  49. void * cont_addr;
  50. bool has_fault;
  51. } test_range;
  52. };
  53. #define SHIM_TCB_GET(member) \
  54. ({ \
  55. shim_tcb_t* tcb; \
  56. __typeof__(tcb->member) ret; \
  57. static_assert(sizeof(ret) == 8 || \
  58. sizeof(ret) == 4 || \
  59. sizeof(ret) == 2 || \
  60. sizeof(ret) == 1, \
  61. "SHIM_TCB_GET can be used only for " \
  62. "8, 4, 2, or 1-byte(s) members"); \
  63. switch (sizeof(ret)) { \
  64. case 8: \
  65. __asm__("movq %%gs:%c1, %0\n" \
  66. : "=r"(ret) \
  67. : "i" (offsetof(PAL_TCB, libos_tcb) + \
  68. offsetof(shim_tcb_t, member))); \
  69. break; \
  70. case 4: \
  71. __asm__("movl %%gs:%c1, %0\n" \
  72. : "=r"(ret) \
  73. : "i" (offsetof(PAL_TCB, libos_tcb) + \
  74. offsetof(shim_tcb_t, member))); \
  75. break; \
  76. case 2: \
  77. __asm__("movw %%gs:%c1, %0\n" \
  78. : "=r"(ret) \
  79. : "i" (offsetof(PAL_TCB, libos_tcb) + \
  80. offsetof(shim_tcb_t, member))); \
  81. break; \
  82. case 1: \
  83. __asm__("movb %%gs:%c1, %0\n" \
  84. : "=r"(ret) \
  85. : "i" (offsetof(PAL_TCB, libos_tcb) + \
  86. offsetof(shim_tcb_t, member))); \
  87. break; \
  88. default: \
  89. __abort(); \
  90. } \
  91. ret; \
  92. })
  93. #define SHIM_TCB_SET(member, value) \
  94. do { \
  95. shim_tcb_t* tcb; \
  96. static_assert(sizeof(tcb->member) == 8 || \
  97. sizeof(tcb->member) == 4 || \
  98. sizeof(tcb->member) == 2 || \
  99. sizeof(tcb->member) == 1, \
  100. "SHIM_TCB_SET can be used only for " \
  101. "8, 4, 2, or 1-byte(s) members"); \
  102. switch (sizeof(tcb->member)) { \
  103. case 8: \
  104. __asm__("movq %0, %%gs:%c1\n" \
  105. :: "ir"(value), \
  106. "i"(offsetof(PAL_TCB, libos_tcb) + \
  107. offsetof(shim_tcb_t, member))); \
  108. break; \
  109. case 4: \
  110. __asm__("movl %0, %%gs:%c1\n" \
  111. :: "ir"(value), \
  112. "i"(offsetof(PAL_TCB, libos_tcb) + \
  113. offsetof(shim_tcb_t, member))); \
  114. break; \
  115. case 2: \
  116. __asm__("movw %0, %%gs:%c1\n" \
  117. :: "ir"(value), \
  118. "i"(offsetof(PAL_TCB, libos_tcb) + \
  119. offsetof(shim_tcb_t, member))); \
  120. break; \
  121. case 1: \
  122. __asm__("movb %0, %%gs:%c1\n" \
  123. :: "ir"(value), \
  124. "i"(offsetof(PAL_TCB, libos_tcb) + \
  125. offsetof(shim_tcb_t, member))); \
  126. break; \
  127. default: \
  128. __abort(); \
  129. } \
  130. } while (0)
  131. static inline void __shim_tcb_init(shim_tcb_t* shim_tcb) {
  132. shim_tcb->canary = SHIM_TCB_CANARY;
  133. shim_tcb->self = shim_tcb;
  134. }
  135. /* Call this function at the beginning of thread execution. */
  136. static inline void shim_tcb_init(void) {
  137. PAL_TCB* tcb = pal_get_tcb();
  138. shim_tcb_t* shim_tcb = (shim_tcb_t*)tcb->libos_tcb;
  139. memset(shim_tcb, 0, sizeof(*shim_tcb));
  140. __shim_tcb_init(shim_tcb);
  141. }
  142. static inline shim_tcb_t* shim_get_tcb(void) {
  143. return SHIM_TCB_GET(self);
  144. }
  145. static inline bool shim_tcb_check_canary(void) {
  146. return SHIM_TCB_GET(canary) == SHIM_TCB_CANARY;
  147. }
  148. #endif /* _SHIM_H_ */