x86: Userspace code to restart ROS TFs
[akaros.git] / user / include / i686 / hart.h
1 #ifndef PARLIB_ARCH_HART_H
2 #define PARLIB_ARCH_HART_H
3
4 #include <ros/common.h>
5 #include <ros/arch/trapframe.h>
6
7 /* Pops an ROS kernel-provided TF, reanabling notifications at the same time.
8  * A Userspace scheduler can call this when transitioning off the transition
9  * stack.
10  *
11  * Basically, it sets up the future stack pointer to have extra stuff after it,
12  * and then it pops the registers, then pops the new context's stack
13  * pointer.  Then it uses the extra stuff (the new PC is on the stack, the
14  * location of notif_enabled, and a clobbered work register) to enable notifs,
15  * restore the work reg, and then "ret".
16  *
17  * The important thing is that it can a notification after it enables
18  * notifications, and when it gets resumed it can ultimately run the new
19  * context.  Enough state is saved in the running context and stack to continue
20  * running. */
21 static inline void pop_ros_tf(struct user_trapframe *tf, bool *notif_en_loc)
22 {
23         asm volatile ("movl %2,-4(%1);          " /* push the PC */
24                       "movl %3,-12(%1);         " /* leave room for eax, push loc */
25                       "movl %0,%%esp;           " /* pop the real tf */
26                       "popal;                   "
27                       "addl $0x24,%%esp;        " /* move to the %esp in the tf */
28                       "popl %%esp;              " /* change to the new %esp */
29                       "subl $0x4,%%esp;         " /* move esp to the slot for eax */
30                       "pushl %%eax;             " /* save eax, will clobber soon */
31                       "subl $0x4,%%esp;         " /* move to notif_en_loc slot */
32                       "popl %%eax;              "
33                       "movb $0x01,(%%eax);      " /* enable notifications */
34                       "popl %%eax;              " /* restore tf's %eax */
35                       "ret;                     " /* return to the new PC */
36                       :
37                       : "g"(tf), "r"(tf->tf_esp), "r"(tf->tf_eip), "r"(notif_en_loc)
38                       : "memory");
39 }
40
41 #endif /* PARLIB_ARCH_HART_H */