Merge remote branch 'origin/sparc-dev'
[akaros.git] / kern / src / pmap.c
index afcc0a9..cc12b7c 100644 (file)
@@ -289,7 +289,7 @@ void* user_mem_check(env_t *env, const void *DANGEROUS va, size_t len, int perm)
                warn("Blimey!  Wrap around in VM range calculation!");  
                return NULL;
        }
-       num_pages = PPN(end - start);
+       num_pages = LA2PPN(end - start);
        for (i = 0; i < num_pages; i++, start += PGSIZE) {
                page_perms = get_va_perms(env->env_pgdir, start);
                // ensures the bits we want on are turned on.  if not, error out
@@ -379,10 +379,10 @@ user_mem_assert(env_t *env, const void *DANGEROUS va, size_t len, int perm)
                return NULL;
        }
        
-    void *COUNT(len) res = user_mem_check(env,va,len,perm | PTE_USER_RO);
+       void *COUNT(len) res = user_mem_check(env,va,len,perm | PTE_USER_RO);
        if (!res) {
                cprintf("[%08x] user_mem_check assertion failure for "
-                       "va %08x\n", env->env_id, user_mem_check_addr);
+                       "va %08x\n", env->pid, user_mem_check_addr);
                proc_destroy(env);      // may not return
         return NULL;
        }
@@ -419,21 +419,76 @@ error_t memcpy_from_user(env_t* env, void* COUNT(len) dest,
        if(start >= (void*SNT)ULIM || end >= (void*SNT)ULIM)
                return -EFAULT;
 
-       num_pages = PPN(end - start);
+       num_pages = LA2PPN(end - start);
        for(i = 0; i < num_pages; i++)
        {
                pte = pgdir_walk(env->env_pgdir, start+i*PGSIZE, 0);
                if(!pte || (*pte & perm) != perm)
                        return -EFAULT;
 
-               void*COUNT(PGSIZE) kpage = KADDR(PTE_ADDR(pte));
-               void* src_start = i > 0 ? kpage : kpage+(va-start);
+               void*COUNT(PGSIZE) kpage = KADDR(PTE_ADDR(*pte));
+               const void* src_start = i > 0 ? kpage : kpage+(va-start);
                void* dst_start = dest+bytes_copied;
                size_t copy_len = PGSIZE;
                if(i == 0)
                        copy_len -= va-start;
                if(i == num_pages-1)
-                       copy_len -= end-(start+len);
+                       copy_len -= end-(va+len);
+
+               memcpy(dst_start,src_start,copy_len);
+               bytes_copied += copy_len;
+       }
+
+       assert(bytes_copied == len);
+
+       return ESUCCESS;
+}
+
+/**
+ * @brief Copies data to a user buffer from a kernel buffer.
+ * 
+ * @param env  the environment associated with the user program
+ *             to which the buffer is being copied
+ * @param dest the destination address of the user buffer
+ * @param va   the address of the kernel buffer from which we are copying
+ * @param len  the length of the user buffer
+ *
+ * @return ESUCCESS on success
+ * @return -EFAULT  the page assocaited with 'va' is not present, the user 
+ *                  lacks the proper permissions, or there was an invalid 'va'
+ */
+error_t memcpy_to_user(env_t* env, void*DANGEROUS va,
+                 const void *COUNT(len) src, size_t len)
+{
+       const void *DANGEROUS start, *DANGEROUS end;
+       size_t num_pages, i;
+       pte_t *pte;
+       uintptr_t perm = PTE_P | PTE_USER_RW;
+       size_t bytes_copied = 0;
+
+       static_assert(ULIM % PGSIZE == 0 && ULIM != 0); // prevent wrap-around
+
+       start = ROUNDDOWN(va, PGSIZE);
+       end = ROUNDUP(va + len, PGSIZE);
+
+       if(start >= (void*SNT)ULIM || end >= (void*SNT)ULIM)
+               return -EFAULT;
+
+       num_pages = LA2PPN(end - start);
+       for(i = 0; i < num_pages; i++)
+       {
+               pte = pgdir_walk(env->env_pgdir, start+i*PGSIZE, 0);
+               if(!pte || (*pte & perm) != perm)
+                       return -EFAULT;
+
+               void*COUNT(PGSIZE) kpage = KADDR(PTE_ADDR(*pte));
+               void* dst_start = i > 0 ? kpage : kpage+(va-start);
+               const void* src_start = src+bytes_copied;
+               size_t copy_len = PGSIZE;
+               if(i == 0)
+                       copy_len -= va-start;
+               if(i == num_pages-1)
+                       copy_len -= end-(va+len);
 
                memcpy(dst_start,src_start,copy_len);
                bytes_copied += copy_len;