MM touchups
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 8 Feb 2010 20:02:00 +0000 (12:02 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 8 Feb 2010 20:02:00 +0000 (12:02 -0800)
Fixes mmap() for x86 - at least for what it's used for now.

Keeps the sys_ functions in syscall.c.  The general model I'd like is
for the sys_ to be a wrapper with basic checks and a callout to a more
complicated function that might get used elsewhere in system.  We don't
do it well yet, but that's the idea.

Also keeps the bits in mman.h in sync with Linux, which might make
things easier.  If we're going to change them back and forth, there
ought to be a reason at least.

Please keep the syscalls in order in syscall.h and syscall.c, and try to
group related calls together.

kern/include/mm.h
kern/include/ros/mman.h
kern/include/ros/syscall.h
kern/include/syscall.h
kern/src/mm.c
kern/src/syscall.c

index 4a9e75d..5634cbf 100644 (file)
@@ -70,7 +70,9 @@ struct mm {
 
 };
 // would rather this be a mm struct
-void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags, int fd, size_t offset);
-
+void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
+           int fd, size_t offset);
+int mprotect(struct proc* p, void* addr, size_t len, int prot);
+int munmap(struct proc* p, void* addr, size_t len);
 
 #endif // !ROS_KERN_MM_H
index 59edef5..8da4bb1 100644 (file)
@@ -3,33 +3,42 @@
  * Barret Rhoden <brho@cs.berkeley.edu>
  * See LICENSE for details.
  *
- * Memory management flags, currently used in mmap()
+ * Memory management flags, currently used in mmap().
+ * Try to keep these in sync with /usr/include/bits/mman.h so we have less
+ * issues with userspace.
  */
 
 #ifndef ROS_INCLUDE_MMAN_H
 #define ROS_INCLUDE_MMAN_H
 
 /* Memory protection states (what you're allowed to do */
-#define PROT_READ              0x4
+#define PROT_READ              0x1
 #define PROT_WRITE             0x2
-#define PROT_EXEC              0x1
+#define PROT_EXEC              0x4
 #define PROT_NONE              0x0
+#define PROT_GROWSDOWN 0x01000000
+#define PROT_GROWSUP   0x02000000
+// TODO NOT A REAL STATE
 #define PROT_UNMAP             0x100
 
 /* mmap flags, only anonymous is supported now, feel free to pass others */
-#define MAP_SHARED             0x010
-#define MAP_PRIVATE            0x000
-#define MAP_ANONYMOUS  0x002
-#define MAP_FIXED              0x100
-//#define MAP_GROWSDOWN        0x010
-//#define MAP_STACK            0x020
-//#define MAP_POPULATE 0x040
-//#define MAP_NONBLOCK 0x080
-//#define MAP_NORESERVE        0x100
+#define MAP_SHARED             0x01
+#define MAP_PRIVATE            0x02
+#define MAP_FIXED              0x10
+#define MAP_ANONYMOUS  0x20
+#define MAP_ANON MAP_ANONYMOUS
+
+#define MAP_GROWSDOWN  0x00100
+#define MAP_DENYWRITE  0x00800
+#define MAP_EXECUTABLE 0x01000
+#define MAP_LOCKED             0x02000
+#define MAP_NORESERVE  0x04000
+#define MAP_POPULATE   0x08000
+#define MAP_NONBLOCK   0x10000
+#define MAP_STACK              0x20000
 
 /* Other mmap flags, which we probably won't support
 #define MAP_32BIT
-#define MAP_LOCKED
 */
 
 #endif /* !ROS_INCLUDE_MMAN_H */
index 29bfbad..53f2009 100644 (file)
 #define SYS_exec                                       16
 #define SYS_trywait                                    17
 #define SYS_mmap                                       18
-#define SYS_brk                                                19
-#define SYS_shared_page_alloc          20
-#define SYS_shared_page_free           21
-/*
+#define SYS_munmap                                     19
+#define SYS_mprotect                           20
+/* // these are the other mmap related calls, some of which we'll implement
 #define SYS_mincore // can read page tables instead
 #define SYS_madvise
 #define SYS_mlock
 #define SYS_msync
 */
-#define SYS_resource_req                       22
+#define SYS_brk                                                21
+#define SYS_shared_page_alloc          22
+#define SYS_shared_page_free           23
+#define SYS_resource_req                       24
 /* Platform specific syscalls */
-#define SYS_serial_read                                23
-#define SYS_serial_write                       24
-#define SYS_eth_read                           25
-#define SYS_eth_write                          26
-#define SYS_frontend                           27
-#define SYS_mprotect                           28
-#define SYS_munmap                                     29
+#define SYS_serial_read                                25
+#define SYS_serial_write                       26
+#define SYS_eth_read                           27
+#define SYS_eth_write                          28
+#define SYS_frontend                           29
 
 #define SYS_read                               100
 #define SYS_write                              101
index 1b7c1e5..d54f55d 100644 (file)
@@ -36,7 +36,5 @@ intreg_t sys_unlink(struct proc* p, const char* path);
 intreg_t sys_chdir(struct proc* p, const char* path);
 intreg_t sys_getcwd(struct proc* p, char* pwd, int size);
 intreg_t sys_gettimeofday(struct proc* p, int* buf);
-intreg_t sys_mprotect(struct proc* p, void* addr, size_t len, int prot);
-intreg_t sys_munmap(struct proc* p, void* addr, size_t len);
 
 #endif /* !ROS_KERN_SYSCALL_H */
index f5c0fb3..52270c7 100644 (file)
 void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
            int fd, size_t offset)
 {
-       printd("mmap(addr %x, len %x, prot %x, flags %x, fd %x, off %x)\n",addr,len,prot,flags,fd,offset);
-       if (flags & MAP_SHARED) {
+       printd("mmap(addr %x, len %x, prot %x, flags %x, fd %x, off %x)\n", addr,
+              len, prot, flags, fd, offset);
+       #ifdef __i386__
+       if (fd || offset) {
+               printk("[kernel] mmap() does not support files yet.\n");
+               return (void*SAFE)TC(-1);
+       }
+       #endif
+       if (fd && (flags & MAP_SHARED)) {
                printk("[kernel] mmap() for files requires !MAP_SHARED.\n");
                return (void*)-1;
        }
 
-       /*if (fd || offset) {
-               printk("[kernel] mmap() does not support files yet.\n");
-               return (void*SAFE)TC(-1);
-       }*/
        /* TODO: make this work, instead of a ghetto hack
         * Find a valid range, make sure it doesn't run into the kernel
         * make sure there's enough memory (not exceeding quotas)
         * allocate and map the pages, update appropriate structures (vm_region)
         * return appropriate pointer
         * Right now, all we can do is give them the range they ask for.
-        */
+        * (or try to find one on sparc) */
+       // TODO: race here
        if (!(flags & MAP_FIXED))
        {
                addr = MIN(addr,UMMAP_START);
                addr = (uintptr_t)get_free_va_range(p->env_pgdir,UMMAP_START,len);
+               assert(!PGOFF(addr));
        }
        else if(PGOFF(addr)) { // MAP_FIXED with unaligned address
                printk("[kernel] mmap() page align your addr.\n");
@@ -48,11 +53,12 @@ void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
        // TODO: grab the appropriate mm_lock
        spin_lock_irqsave(&p->proc_lock);
        // make sure all pages are available, and in a reasonable range
-       // TODO: can probably do this better with vm_regions.
+       // TODO: can probably do this better with vm_regions, and not do it after
+       // getting the free va range
        // can also consider not mapping to 0x00000000
        for (int i = 0; i < num_pages; i++) {
                a_pte = pgdir_walk(p->env_pgdir, (void*SNT)(addr + i*PGSIZE), 0);
-               if (!(flags & MAP_FIXED) && a_pte && *a_pte & PTE_P)
+               if (a_pte && *a_pte & PTE_P)
                        goto mmap_abort;
                if (addr + i*PGSIZE >= USTACKBOT)
                        goto mmap_abort;
@@ -61,16 +67,20 @@ void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
        for (int i = 0; i < num_pages; i++) {
                if (upage_alloc(p, &a_page, 1))
                        goto mmap_abort;
-               // TODO: TLB shootdown if replacing an old mapping
+               // TODO: TLB shootdown if replacing an old mapping (depends on semantics
+               // of MAP_FIXED)
+               // TODO: handle all PROT flags
                if (page_insert(p->env_pgdir, a_page, (void*SNT)(addr + i*PGSIZE),
-                               1||(prot & PROT_WRITE) ? PTE_USER_RW : PTE_USER_RO)) {
+                               (prot & PROT_WRITE) ? PTE_USER_RW : PTE_USER_RO)) {
                        page_free(a_page);
                        goto mmap_abort;
                }
        }
 
+       #ifndef __i386__
        // This is dumb--should not read until faulted in.
        // This is just to get it correct at first
+       // TODO: use mmap2 semantics, offset is a PGSIZE
        if(fd >= 0)
        {
                char buf[PGSIZE];
@@ -78,6 +88,7 @@ void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
                if(ret == -1)
                        goto mmap_abort;
        }
+       #endif
 
        // TODO: release the appropriate mm_lock
        spin_unlock_irqsave(&p->proc_lock);
@@ -95,7 +106,7 @@ void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
                return (void*SAFE)TC(-1); // this is also ridiculous
 }
 
-intreg_t sys_mprotect(struct proc* p, void* addr, size_t len, int prot)
+int mprotect(struct proc* p, void* addr, size_t len, int prot)
 {
        printd("mprotect(addr %x, len %x, prot %x)\n",addr,len,prot);
        if((intptr_t)addr % PGSIZE || (len == 0 && (prot & PROT_UNMAP)))
@@ -104,6 +115,7 @@ intreg_t sys_mprotect(struct proc* p, void* addr, size_t len, int prot)
                return -1;
        }
 
+       // overflow of end is handled in the for loop's parameters
        char* end = ROUNDUP((char*)addr+len,PGSIZE);
        if(addr >= (void*)UTOP || end >= (char*)UTOP)
        {
@@ -119,6 +131,7 @@ intreg_t sys_mprotect(struct proc* p, void* addr, size_t len, int prot)
                pte_t* pte = pgdir_walk(p->env_pgdir,a,0);
                if(pte && *pte & PTE_P)
                {
+                       // TODO: do munmap() in munmap(), instead of mprotect()
                        if(prot & PROT_UNMAP)
                        {
                                page_t* page = ppn2page(PTE2PPN(*pte));
@@ -135,12 +148,12 @@ intreg_t sys_mprotect(struct proc* p, void* addr, size_t len, int prot)
                }
        }
 
-       //TODO: TLB shootdown
+       //TODO: TLB shootdown - needs to be process wide
        tlbflush();
        return 0;
 }
 
-intreg_t sys_munmap(struct proc* p, void* addr, size_t len)
+int munmap(struct proc* p, void* addr, size_t len)
 {
-       return sys_mprotect(p,addr,len,PROT_UNMAP);
+       return mprotect(p, addr, len, PROT_UNMAP);
 }
index dc68230..46663f4 100644 (file)
@@ -442,6 +442,16 @@ static void *sys_mmap(struct proc* p, uintreg_t a1, uintreg_t a2, uintreg_t a3,
        return mmap(p,a1,a2,a3,_a456[0],_a456[1],_a456[2]);
 }
 
+static intreg_t sys_mprotect(struct proc* p, void* addr, size_t len, int prot)
+{
+       return mprotect(p, addr, len, prot);
+}
+
+static intreg_t sys_munmap(struct proc* p, void* addr, size_t len)
+{
+       return munmap(p, addr, len);
+}
+
 static void* sys_brk(struct proc *p, void* addr) {
        size_t range;