VFS rename
[akaros.git] / kern / src / umem.c
index e2a776d..c7ae3d1 100644 (file)
 #include <smp.h>
 
 /**
- * @brief Global variable used to store erroneous virtual addresses as the
- *        result of a failed user_mem_check().
- *
- * zra: What if two checks fail at the same time? Maybe this should be per-cpu?
- *
- */
-static void *DANGEROUS RACY user_mem_check_addr;
-
-/**
- * @brief Check that an environment is allowed to access the range of memory
- * [va, va+len) with permissions 'perm | PTE_P'.
- *
- * Normally 'perm' will contain PTE_U at least, but this is not required.  The
- * function get_va_perms only checks for PTE_U, PTE_W, and PTE_P.  It won't
- * check for things like PTE_PS, PTE_A, etc.
- * 'va' and 'len' need not be page-aligned;
- *
- * A user program can access a virtual address if:
- *     -# the address is below ULIM
- *     -# the page table gives it permission.  
- *
- * If there is an error, 'user_mem_check_addr' is set to the first
- * erroneous virtual address.
- *
- * @param p    the process associated with the user program trying to access
- *             the virtual address range
- * @param va   the first virtual address in the range
- * @param len  the length of the virtual address range
- * @param perm the permissions the user is trying to access the virtual address 
- *             range with
- *
- * @return VA a pointer of type COUNT(len) to the address range
- * @return NULL trying to access this range of virtual addresses is not allowed
- */
-void *user_mem_check(struct proc *p, const void *DANGEROUS va, size_t len,
-                     size_t align, int perm)
-{
-       align--;
-       if(((align+1) & align) || ((uintptr_t)va & align) || (len & align))
-               return NULL;
-
-       // TODO - will need to sort this out wrt page faulting / PTE_P
-       // also could be issues with sleeping and waking up to find pages
-       // are unmapped, though i think the lab ignores this since the 
-       // kernel is uninterruptible
-       void *DANGEROUS start, *DANGEROUS end;
-       size_t num_pages, i;
-       int page_perms = 0;
-
-       perm |= PTE_P;
-       start = ROUNDDOWN((void*DANGEROUS)va, PGSIZE);
-       end = ROUNDUP((void*DANGEROUS)va + len, PGSIZE);
-       if (start >= end) {
-               warn("Blimey!  Wrap around in VM range calculation!");  
-               return NULL;
-       }
-       num_pages = LA2PPN(end - start);
-       for (i = 0; i < num_pages; i++, start += PGSIZE) {
-               page_perms = get_va_perms(p->env_pgdir, start);
-               // ensures the bits we want on are turned on.  if not, error out
-               if ((page_perms & perm) != perm) {
-                       if (i == 0)
-                               user_mem_check_addr = (void*DANGEROUS)va;
-                       else
-                               user_mem_check_addr = start;
-                       return NULL;
-               }
-       }
-       // this should never be needed, since the perms should catch it
-       if ((uintptr_t)end > ULIM) {
-               warn ("I suck - Bug in user permission mappings!");
-               return NULL;
-       }
-       return (void *COUNT(len))TC(va);
-}
-
-/**
- * @brief Checks that process 'p' is allowed to access the range
- * of memory [va, va+len) with permissions 'perm | PTE_U'. Destroy 
- * process 'p' if the assertion fails.
- *
- * This function is identical to user_mem_assert() except that it has a side
- * affect of destroying the process 'p' if the memory check fails.
- *
- * @param p    the process associated with the user program trying to access
- *             the virtual address range
- * @param va   the first virtual address in the range
- * @param len  the length of the virtual address range
- * @param perm the permissions the user is trying to access the virtual address 
- *             range with
- *
- * @return VA a pointer of type COUNT(len) to the address range
- * @return NULL trying to access this range of virtual addresses is not allowed
- *              process 'p' is destroyed
- *
- * GIANT WARNING: this could fuck up your refcnting for p if p was an
- * edible/refcounted reference.  (fix is to return, or just not use this) */
-void *user_mem_assert(struct proc *p, const void *DANGEROUS va, size_t len,
-                      size_t align, int perm)
-{
-       void* res = user_mem_check(p, va, len, align, perm | PTE_USER_RO);
-       if (!res) {
-               cprintf("[%08x] user_mem_check assertion failure for "
-                       "va %08x\n", p->pid, user_mem_check_addr);
-               /* won't be freed til the caller decrefs */
-               proc_destroy(p);
-        return NULL;
-       }
-    return res;
-}
-
-/**
  * @brief Copies data from a user buffer to a kernel buffer.
  * 
  * @param p    the process associated with the user program
@@ -151,8 +39,8 @@ int memcpy_from_user(struct proc *p, void *dest, const void *DANGEROUS va,
 
        static_assert(ULIM % PGSIZE == 0 && ULIM != 0); // prevent wrap-around
 
-       start = ROUNDDOWN(va, PGSIZE);
-       end = ROUNDUP(va + len, PGSIZE);
+       start = (void*)ROUNDDOWN((uintptr_t)va, PGSIZE);
+       end = (void*)ROUNDUP((uintptr_t)va + len, PGSIZE);
 
        if (start >= (void*SNT)ULIM || end > (void*SNT)ULIM)
                return -EFAULT;
@@ -217,8 +105,8 @@ int memcpy_to_user(struct proc *p, void *va, const void *src, size_t len)
 
        static_assert(ULIM % PGSIZE == 0 && ULIM != 0); // prevent wrap-around
 
-       start = ROUNDDOWN(va, PGSIZE);
-       end = ROUNDUP(va + len, PGSIZE);
+       start = (void*)ROUNDDOWN((uintptr_t)va, PGSIZE);
+       end = (void*)ROUNDUP((uintptr_t)va + len, PGSIZE);
 
        if (start >= (void*SNT)ULIM || end > (void*SNT)ULIM)
                return -EFAULT;
@@ -252,7 +140,7 @@ int memcpy_to_user(struct proc *p, void *va, const void *src, size_t len)
 int memcpy_to_user_errno(struct proc *p, void *dst, const void *src, int len)
 {
        if (memcpy_to_user(p, dst, src, len)) {
-               set_errno(EINVAL);
+               set_errno(EFAULT);
                return -1;
        }
        return 0;
@@ -268,7 +156,7 @@ void *user_memdup(struct proc *p, const void *va, int len)
                return ERR_PTR(-ENOMEM);
        if (memcpy_from_user(p, kva, va, len)) {
                kfree(kva);
-               return ERR_PTR(-EINVAL);
+               return ERR_PTR(-EFAULT);
        }
        return kva;
 }