syscall/iret context switching?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
AndrewAPrice
Member
Member
Posts: 2300
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

syscall/iret context switching?

Post by AndrewAPrice »

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?
My OS is Perception.
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: syscall/iret context switching?

Post by bzt »

MessiahAndrw wrote:Could I return from the syscall with iret if I'm switching contexts?
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.

Cheers,
bzt
nullplan
Member
Member
Posts: 1792
Joined: Wed Aug 30, 2017 8:24 am

Re: syscall/iret context switching?

Post by nullplan »

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!
User avatar
AndrewAPrice
Member
Member
Posts: 2300
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

Re: syscall/iret context switching?

Post by AndrewAPrice »

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.
My OS is Perception.
Post Reply