The inconveniences of sysenter/sysexit
Posted: Mon Jan 12, 2009 8:35 pm
Recently when trying to implement sysenter and sysexit calls I found that they are quite restrictive and inconveniently written entirely for optimization. When you use sysenter, the cpu doesn't read or write anything to the stack. I guess this is an optimization so that the system doesn't do extra memory accesses..
As a result, returning to the original calling area becomes more difficult. Basically, sysexit returns to the address based on information written in registers ecx and edx... Unfortunately the kernel handler that answers the "sysenter" doesn't know where to return to, so it cannot place anything into ecx or edx without some external information. The CPU automatically changes SS and ESP so pushing anything into the stack before hand won't work.
The most efficient solution I can think of is setting the registers to the required values before hand. So:
Unfortunately with this method, even if you change the initial registers to something less popular, you will still be using up more registers than if using conventional software interrupts.
If you don't change the initial registers and you are careful with assembly you can get away without pushing and popping the ecx and edx.... I suggest not doing this however.
...A less optimized solution would be to store the registers in memory, and pass one register containing the memory location, and have the kernel read the registers from memory. ...but once again, we are trying not to use memory.
I have heard that the Linux people have figured out how to preserve their compatibility and still allow to use up all the registers as before.. I read it as being called something like an "ugly hack".... I couldn't find how they did it though. ...maybe their "ugly hack" had more to do with reverse compatibility rather than extending the amount of usable registers.
Does anybody know a better method of getting around this inconvenience?
Veniamin
Edit: I am not sure if this is the correct place to post. If it is not, can you please move it to the correct place?
As a result, returning to the original calling area becomes more difficult. Basically, sysexit returns to the address based on information written in registers ecx and edx... Unfortunately the kernel handler that answers the "sysenter" doesn't know where to return to, so it cannot place anything into ecx or edx without some external information. The CPU automatically changes SS and ESP so pushing anything into the stack before hand won't work.
The most efficient solution I can think of is setting the registers to the required values before hand. So:
Code: Select all
mov edx, next ;Where to return to.
mov ecx, esp ;Stack to set when we return.
sysenter
next:
...
sysenterHandler:
push edx
push ecx
; Handle system functions here...
pop ecx
pop edx
sysexit
If you don't change the initial registers and you are careful with assembly you can get away without pushing and popping the ecx and edx.... I suggest not doing this however.
...A less optimized solution would be to store the registers in memory, and pass one register containing the memory location, and have the kernel read the registers from memory. ...but once again, we are trying not to use memory.
I have heard that the Linux people have figured out how to preserve their compatibility and still allow to use up all the registers as before.. I read it as being called something like an "ugly hack".... I couldn't find how they did it though. ...maybe their "ugly hack" had more to do with reverse compatibility rather than extending the amount of usable registers.
Does anybody know a better method of getting around this inconvenience?
Veniamin
Edit: I am not sure if this is the correct place to post. If it is not, can you please move it to the correct place?