I'm in long mode, and I use syscall/sysret for system calls from userland.
Some system calls can put the current thread to sleep (send and block, sleep until message, terminate this thread, etc.) therefore there are times when I'd want to return from the syscall in another thread. The problem is that sysret uses rcx/r11 for rip/rflags, and the thread that I'm switching to might have been preempted by the timer while using rcx/r11.
How do other people solve this problem? Could I return from the syscall with iret if I'm switching contexts?
syscall/iret context switching?
- AndrewAPrice
- Member
- Posts: 2300
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
syscall/iret context switching?
My OS is Perception.
Re: syscall/iret context switching?
It is a bit tricky, but you can. Here is how I do it, I jump to "8f" when task switch is needed, and "9f" when syscall returns to the same task. The trick is at the beginning of the syscall handler (line 102 and below) where I arrange the task struct to look like it was interrupted, and I switch to the same stack pointed by the IST.MessiahAndrw wrote:Could I return from the syscall with iret if I'm switching contexts?
Cheers,
bzt
Re: syscall/iret context switching?
You can definitely return from syscall with iret, this is what I do for the difficult cases. My OS uses one kernel stack (2 pages) per task, so if a syscall needs to sleep, it just calls schedule(), and that will switch stacks, so that is not one of the weird cases. The weird cases are if a signal is pending, if the task has timed out, if the return address is greater than 0x0000800000000000 (there was this Intel-sysret-bug that breaks things when sysret is run with a non-canonical address, so I let iret run and then the GPF handler will take care of things), and finally if on return from syscall RCX and R11 do not match their counterparts in the fake interrupt frame I've been maintaining. I don't know how that could have happened, (well timed ptrace() maybe?) but in that case I use iret for defined behavior.
Carpe diem!
- AndrewAPrice
- Member
- Posts: 2300
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
Re: syscall/iret context switching?
Thanks for the replies.
I tried this out and it worked.
It was actually super simple. My thread's registers are saved in a struct. I point rsp to the new thread's register struct, and pop my registers, then call 'iretq' which pops the remaining RIP, CS, RFLAGS, RSP, SS from the top of my struct.
I tried this out and it worked.
It was actually super simple. My thread's registers are saved in a struct. I point rsp to the new thread's register struct, and pop my registers, then call 'iretq' which pops the remaining RIP, CS, RFLAGS, RSP, SS from the top of my struct.
My OS is Perception.