Page 1 of 1

x86-64 syscall bad return value

Posted: Wed Jan 06, 2016 4:42 pm
by AnnikaBlair
im having a strange problem with getting return value from syscalls. other interrupts work fine (as far as i can tell) even syscalls work if no return value needed.
anytime try to get return value its wrong.
most of this is based on a tutorial for the same in 32bit (im using 64bit) dont remember where i found it but it worked fine when i was working with 32 bits

this is the function called from user app to use syscall:

Code: Select all

#define DEFN_SYSCALL1(fn, num, P1) \
uint64_t fn(P1 p1) \
{ \
  uint64_t a; \
  asm volatile("int $0x80" : "=a" (a) : "D" (num), "S" ((uint64_t)p1)); \
  return a; \
}
this is called from interrupt handler. (again those work correctly although never needed return before now) syscalls[] is alist of pinters to functions

Code: Select all

void syscall_handler(registers_t reg)
{	
	if (reg.rdi >= num_syscalls)
		return;
	void *location = syscalls[reg.rdi];
	asm volatile (" \
		mov %1, %%r8; \
		mov %2, %%rcx; \
		mov %3, %%rdx; \
		mov %4, %%rsi; \
		mov %5, %%rdi; \
		call *%6; \
	" : "=a" (reg.rax) : "r" (reg.r9), "r" (reg.r8), "r" (reg.rcx), "r" (reg.rdx), "r" (reg.rsi), "r" (location));
}
that then calls get_pages() which when run directly(not from a syscall) returns correct address

this just creates a syscall with desired function name
DEFN_SYSCALL1(sys_get_pages, 11, const char*);

then this should get a pointer to a block of memory but always gets 0xB (should be around 0x600000)
void *mem = sys_get_pages(16);

sorry if its really obvious but iv been fighting with this for months
and if you need any other code ill be glad to post it
also not sure if this matters but using qemu for testing

Re: x86-64 syscall bad return value

Posted: Wed Jan 06, 2016 8:28 pm
by gerryg400
Hi, you are passing the 'reg' parameter to syscall_handler by value. This means that the structure that you pass will not be modified by the called function. You will need to pass a pointer instead.

gerry

Re: x86-64 syscall bad return value

Posted: Wed Jan 06, 2016 10:48 pm
by AnnikaBlair
Thank you so much Gerry. That fixed it. I guess I need to reread everything thingi thought I knew about pointers #-o

Re: x86-64 syscall bad return value

Posted: Thu Jan 07, 2016 3:58 am
by Combuster
On another note,

Code: Select all

void *location = syscalls[reg.rdi];
   asm volatile (" \
      mov %1, %%r8; \
      mov %2, %%rcx; \
      mov %3, %%rdx; \
      mov %4, %%rsi; \
      mov %5, %%rdi; \
      call *%6; \
   " : "=a" (reg.rax) : "r" (reg.r9), "r" (reg.r8), "r" (reg.rcx), "r" (reg.rdx), "r" (reg.rsi), "r" (location));
or...

Code: Select all

reg->rax = (syscalls[reg->rdi])(reg->r9, reg->r8, reg->rcx, reg->rdx, reg->rsi);
You can do this in pure C and gain the benefits of it being more compact, portable, and probably most importantly, type-safe. You just need to learn how to use function pointers. :wink:

Re: x86-64 syscall bad return value

Posted: Thu Jan 07, 2016 4:24 am
by iansjack
I would strongly recommend that you consider using the "syscall" instruction rather than interrupts to implement system calls. As you may guess from its name, that's what it was designed for.