Re: x86_64 system call entry points

Andi Kleen
2006-06-06T05:25:13Z

Martin Bisson <bissonm@discreet.com> writes:

> - sysenter/32 bits, executed on a 32 bit machine: I get a segfault on
> the sysenter instruction. I use the following code to enter the
> system call:
> pid_t getpid32()
> {
> pid_t resultvar;
>
> asm volatile (
> "push %%ebp\n\t"
> "push %%ecx\n\t"
> "push %%edx\n\t"
> "mov %%esp,%%ebp\n\t"
> "sysenter\n\t"

You can't use your own SYSENTER. Since sysenter doesn't pass the original
address and the kernel always returns to a fixed address - which is in the vsyscall
page. The fixed address is used because there are not enough registers to pass
both syscall arguments and return address.

The instruction has a few other quirks and isn't exactly the best one Intel
ever designed.

> - int $0x80/64 bits: All system calls return -1 (EINTR). Is there
> something wrong in the way I call it:

Hmm, it should do an 32bit syscall even from 64bit. I can take a look.

> pid_t getpid64()
> {
> pid_t resultvar;
>
> asm volatile (
> "int $0x80\n\t"
> : "=a" (resultvar) : "0" (__NR_getpid)
> : "memory");
>
> return resultvar;
> }
>
>
> - sysenter/64 bits: I get an illegal instruction. I've read that it's
> not implemented on AMD-64 (which is what I have). Is there ANY x86_64
> machine on which this instruction is implemented? Does this mean that
> the code that handles this case in entry.S has never been run?

Intel machines have it, but they don't have SYSCALL from compat mode. That
is why both are implemented. It should end at the code in ia32entry.S

Again you can't use your own - so likely it is returning to the vsyscall page
and then jumping to a bogus address on the stack. You can verify that by
single stepping through it with a debugger.

> - syscall/64 bits: works fine
> - int $0x80/32 bits: works fine
> - syscall/32 bits: illegal instruction, but I guess that's all right
> because of the machine I use.

On AMD it should work. The kernel vsyscall page uses it.

-Andi