Per-CPU structure For storing request info:
1 2 3 4 5 6 7 8 9 10 struct shadow_stack { struct qspinlock *lock ; # indicate there is a request, write only by client # server iterates the array, checks this value, and process request bool active; bool completed; int cpu_id; void *ptr; uint64_t local_shadow_stack_ptr; }
Each CPU will have a shadow stack
1 DEFINE_PER_CPU_SHARED_ALIGNED(struct shadow_stack, local_shadow_stack);
And server thread will a shadow stack
1 struct shadow_stack *server_ptr ;
Question: server thread and some other threads might be on the same CPU. Will this be problematic?
Client 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 void main () { swilock_delegate(lock); # reuse spin_lock() ... # CS ... swilock_delegate_finish(); # reuse spin_unlock() } __swilock_delegate(struct qspinlock *lock) { struct shadow_stack *ptr = this_cpu_ptr(&local_shadow_stack); ptr->lock = lock; ptr->completed = false ; ptr->active = true ; while (ptr->completed == false ); return 0 ; } void swilock_delegate (struct qspinlock *lock) { ... ret_val = __swilock_delegate(lock); ... } void swilock_delegate_finish (struct qspinlock *lock) { ... return ; }
Can reuse TCLock code [Marked yellow]
Server Reuse parts marked green
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 void init () { ... ... ... } void execute_request (struct shadow_stack *ptr) { swi_lock(lock, TAS); ... ptr->active = false ; ptr->completed = true ; swi_unlock(lock, TAS) } void swi_delegate_thread () { while (!kthread_should_stop()){ for_each_possible_cpu (i) { if requests[i].active{ execute_request(requests[i]) } } } }