Search code examples
cargumentsvoidxv6

value not ignored "(argaddr(0, &fva)"


I am looking to add xv6 page table functionality. However, for some reason I am getting errors with argaddr and argint. Why?

Lab reference: xv6 page table

int sys_pgaccess(void){
  uint64 fva;
  int pnum;
  uint64 abits;
  int res = 0;
  pte_t* pte_addr;
  pte_t pte;


  if(argaddr(0, &fva) < 0) {
    return -1;
  }
  if(argint(1, &pnum) < 0) {
    return -1;
  }
kernel/sysproc.c: In function 'sys_pgaccess':
kernel/sysproc.c:105:6: error: void value not ignored as it ought to be
  105 |   if(argaddr(0, &fva) < 0) {
      |      ^~~~~~~~~~~~~~~~
kernel/sysproc.c:108:6: error: void value not ignored as it ought to be
  108 |   if(argint(1, &pnum) < 0) {
      |      ^~~~~~~~~~~~~~~~

I am a beginner so I looked at the code for argaddr, etc., but could not understand it.


Solution

  • The compiler is telling you that argaddr and argint are void functions, and do not return a value.

    You cannot compare nothing with an integer.

    Looking at kernel/syscall.c from mit-pdos/xv6-riscv, we can see the RISC-V function definitions:

    // Fetch the nth 32-bit system call argument.
    void
    argint(int n, int *ip)
    {
      *ip = argraw(n);
    }
    
    // Retrieve an argument as a pointer.
    // Doesn't check for legality, since
    // copyin/copyout will do that.
    void
    argaddr(int n, uint64 *ip)
    {
      *ip = argraw(n);
    }
    

    The contents of the lab linked deal with RISC-V.

    It appears you should simply remove the conditionals:

    int sys_pgaccess(void)
    {
      uint64 fva;
      int pnum;
      /* ... */
     
      argaddr(0, &fva);
      argint(1, &pnum);
      /* ... */
    }
    

    For completeness, the x86 versions of these functions do return values, so you may have read the wrong documentation.

    syscall.c from the no longer maintained mit-pdos/xv6-public contains the x86 definitions:

    // Fetch the int at addr from the current process.
    int
    fetchint(uint addr, int *ip)
    {
      struct proc *curproc = myproc();
    
      if(addr >= curproc->sz || addr+4 > curproc->sz)
        return -1;
      *ip = *(int*)(addr);
      return 0;
    }
    
    // Fetch the nth 32-bit system call argument.
    int
    argint(int n, int *ip)
    {
      return fetchint((myproc()->tf->esp) + 4 + 4*n, ip);
    }
    
    // Fetch the nth word-sized system call argument as a pointer
    // to a block of memory of size bytes.  Check that the pointer
    // lies within the process address space.
    int
    argptr(int n, char **pp, int size)
    {
      int i;
      struct proc *curproc = myproc();
     
      if(argint(n, &i) < 0)
        return -1;
      if(size < 0 || (uint)i >= curproc->sz || (uint)i+size > curproc->sz)
        return -1;
      *pp = (char*)i;
      return 0;
    }