1

I need to write a system call in XV6 that gets a few integers and a few integer pointers as arguments, and I don't understand how to do it.
I read about argint and argptr, but I don't understand how to use them. For example, I don't understand if they are used both for passing the arguments (within the user space) to the system call, and for retrieving them in sys_name (the name of the function in sysproc.c.

In addition, I need the function to return a value, and I don't know how to return to value back to the user space, where the function was called.

Dani
  • 719
  • 1
  • 7
  • 14

1 Answers1

2

tldr:

If you called your syscall like this some_syscall(42), all you have to do to access 42 is call: argint(0, &local_var). This stores the 0th int parameter, 42, into local_var.

With argptr, you need to give it the address of a pointer and the number of bytes of memory you want to fetch. However, since a pointer in 32-bit architecture is 4-bytes, argint will also do the job.

Here's a high-level understanding of how it works:

argint accesses the parameters with some pointer math. It accesses the trapframe struct of the process, containing the user-space registers of the syscall. The trapframe saved the function's parameters starting at the esp register. It adds 4 to skip an empty word on the stack from some conversion that I believe is xv6 specific. The 4*n is so you can access the nth 4-byte parameter after the starting address.

fetchint does some error checking and actually stores the address at the address specified by that *ip pointer.

// Fetch the nth 32-bit system call argument.
int
argint(int n, int *ip)
{
  return fetchint((myproc()->tf->esp) + 4 + 4*n, ip);
}

In syscall.c, syscall() manages passing the return value of your kernel-space function to the user. It accesses that user-space stack to set the process's return-value register eax to whatever your syscall returned. Here's that line for reference:

      curproc->tf->eax = syscalls[num]();

This github is pretty helpful for understanding xv6 sometimes: https://github.com/YehudaShapira/xv6-explained/blob/master/Explanations.md#getting-arguments-in-system-calls

cam
  • 4,409
  • 2
  • 24
  • 34
  • So when I call to `some_syscall(42)`, the `42` (and others parameters that I pass, such as integer pointers) are "automatically" enter to registers, and the only thing that I need to do is to extract then using `argint` (both for the intetgers and for the integer pointers)? – Dani Jun 21 '20 at 08:02
  • Correct. Those are set by xv6 and you just need to use `argint`. I think you understand this but since xv6 is 32-bit, pointers and int variables are just 4-bytes so you can just use `argint` for both. – cam Jun 21 '20 at 16:43
  • @Dani did that answer your question? I'll revise the answer to include the clarification – cam Jun 22 '20 at 05:34