123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- #ifndef _SHIM_TCB_H_
- #define _SHIM_TCB_H_
- #include <assert.h>
- #include <atomic.h>
- #include <pal.h>
- #define SHIM_TCB_CANARY 0xdeadbeef
- struct shim_regs {
- uint64_t orig_rax;
- uint64_t rsp;
- uint64_t r15;
- uint64_t r14;
- uint64_t r13;
- uint64_t r12;
- uint64_t r11;
- uint64_t r10;
- uint64_t r9;
- uint64_t r8;
- uint64_t rcx;
- uint64_t rdx;
- uint64_t rsi;
- uint64_t rdi;
- uint64_t rbx;
- uint64_t rbp;
- uint64_t rflags;
- uint64_t rip;
- };
- struct shim_context {
- struct shim_regs * regs;
- uint64_t fs_base;
- struct shim_context * next;
- uint64_t enter_time;
- struct atomic_int preempt;
- };
- struct debug_buf;
- typedef struct shim_tcb shim_tcb_t;
- struct shim_tcb {
- uint64_t canary;
- shim_tcb_t * self;
- struct shim_thread * tp;
- struct shim_context context;
- unsigned int tid;
- int pal_errno;
- struct debug_buf * debug_buf;
- /* This record is for testing the memory of user inputs.
- * If a segfault occurs with the range [start, end],
- * the code addr is set to cont_addr to alert the caller. */
- struct {
- void * start, * end;
- void * cont_addr;
- bool has_fault;
- } test_range;
- };
- #define SHIM_TCB_GET(member) \
- ({ \
- shim_tcb_t* tcb; \
- __typeof__(tcb->member) ret; \
- static_assert(sizeof(ret) == 8 || \
- sizeof(ret) == 4 || \
- sizeof(ret) == 2 || \
- sizeof(ret) == 1, \
- "SHIM_TCB_GET can be used only for " \
- "8, 4, 2, or 1-byte(s) members"); \
- switch (sizeof(ret)) { \
- case 8: \
- __asm__("movq %%gs:%c1, %0\n" \
- : "=r"(ret) \
- : "i" (offsetof(PAL_TCB, libos_tcb) + \
- offsetof(shim_tcb_t, member))); \
- break; \
- case 4: \
- __asm__("movl %%gs:%c1, %0\n" \
- : "=r"(ret) \
- : "i" (offsetof(PAL_TCB, libos_tcb) + \
- offsetof(shim_tcb_t, member))); \
- break; \
- case 2: \
- __asm__("movw %%gs:%c1, %0\n" \
- : "=r"(ret) \
- : "i" (offsetof(PAL_TCB, libos_tcb) + \
- offsetof(shim_tcb_t, member))); \
- break; \
- case 1: \
- __asm__("movb %%gs:%c1, %0\n" \
- : "=r"(ret) \
- : "i" (offsetof(PAL_TCB, libos_tcb) + \
- offsetof(shim_tcb_t, member))); \
- break; \
- default: \
- __abort(); \
- } \
- ret; \
- })
- #define SHIM_TCB_SET(member, value) \
- do { \
- shim_tcb_t* tcb; \
- static_assert(sizeof(tcb->member) == 8 || \
- sizeof(tcb->member) == 4 || \
- sizeof(tcb->member) == 2 || \
- sizeof(tcb->member) == 1, \
- "SHIM_TCB_SET can be used only for " \
- "8, 4, 2, or 1-byte(s) members"); \
- switch (sizeof(tcb->member)) { \
- case 8: \
- __asm__("movq %0, %%gs:%c1\n" \
- :: "ir"(value), \
- "i"(offsetof(PAL_TCB, libos_tcb) + \
- offsetof(shim_tcb_t, member))); \
- break; \
- case 4: \
- __asm__("movl %0, %%gs:%c1\n" \
- :: "ir"(value), \
- "i"(offsetof(PAL_TCB, libos_tcb) + \
- offsetof(shim_tcb_t, member))); \
- break; \
- case 2: \
- __asm__("movw %0, %%gs:%c1\n" \
- :: "ir"(value), \
- "i"(offsetof(PAL_TCB, libos_tcb) + \
- offsetof(shim_tcb_t, member))); \
- break; \
- case 1: \
- __asm__("movb %0, %%gs:%c1\n" \
- :: "ir"(value), \
- "i"(offsetof(PAL_TCB, libos_tcb) + \
- offsetof(shim_tcb_t, member))); \
- break; \
- default: \
- __abort(); \
- } \
- } while (0)
- static inline void __shim_tcb_init(shim_tcb_t* shim_tcb) {
- shim_tcb->canary = SHIM_TCB_CANARY;
- shim_tcb->self = shim_tcb;
- }
- /* Call this function at the beginning of thread execution. */
- static inline void shim_tcb_init(void) {
- PAL_TCB* tcb = pal_get_tcb();
- shim_tcb_t* shim_tcb = (shim_tcb_t*)tcb->libos_tcb;
- memset(shim_tcb, 0, sizeof(*shim_tcb));
- __shim_tcb_init(shim_tcb);
- }
- static inline shim_tcb_t* shim_get_tcb(void) {
- return SHIM_TCB_GET(self);
- }
- static inline bool shim_tcb_check_canary(void) {
- return SHIM_TCB_GET(canary) == SHIM_TCB_CANARY;
- }
- #endif /* _SHIM_H_ */
|