Reworked the user VM map and added sysevent queue
authorKevin Klues <klueska@eecs.berkeley.edu>
Tue, 11 Aug 2009 01:10:56 +0000 (18:10 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 12 Aug 2009 19:23:58 +0000 (12:23 -0700)
I cleaned up the virtual memory map exposed to user space and created
structs that define the contents of our new procdata and procinfo
structures that the user can use to share data with the kernel.  The
procinfo structures are read only and the procdata structures are
read-write.  Additionally, some of the cruft has now been removed from
the memlayout that was still in there from the ut austin labs we based
our original code on.

Some other changes needed to be made to the way ring buffers are
initialized as well, so that we can statically define their types to be
of a certain size, rather than relying on the open-ended buffers that
were there originally.

Also, just some general cleanup of where certain header files are
included was done as well.

Finally, I mirrored the directory structure created by andrew under
user/parlib into user/roslib.

45 files changed:
GNUmakefile
kern/arch/i386/apic.c
kern/arch/i386/console.c
kern/arch/i386/pmap.c
kern/arch/i386/smp_boot.c
kern/arch/i386/trap.c
kern/arch/sparc/trap.c
kern/include/assert.h
kern/include/env.h
kern/include/ros/memlayout.h
kern/include/ros/procdata.h [new file with mode: 0644]
kern/include/ros/ring_buffer.h
kern/include/ros/syscall.h
kern/include/ros/sysevent.h
kern/src/Makefrag
kern/src/env.c
kern/src/kmalloc.c
kern/src/manager.c
kern/src/pmap.c
kern/src/syscall.c
kern/src/testing.c
user/apps/roslib/Makefrag
user/apps/roslib/fptest.c
user/apps/roslib/hello.c
user/apps/roslib/proctests.c
user/apps/roslib/spawn.c
user/parlib/inc/parlib.h
user/parlib/src/i386/entry.S
user/parlib/src/parlibmain.c
user/parlib/src/sparc/entry.S
user/roslib/inc/assert.h
user/roslib/inc/lib.h
user/roslib/inc/stdio.h
user/roslib/src/Makefrag
user/roslib/src/entry_i386.S [deleted file]
user/roslib/src/entry_sparc.S [deleted file]
user/roslib/src/i386/entry.S [new file with mode: 0644]
user/roslib/src/i386/syscall.c [new file with mode: 0644]
user/roslib/src/libmain.c
user/roslib/src/panic.c
user/roslib/src/sparc/entry.S [new file with mode: 0644]
user/roslib/src/sparc/syscall.c [new file with mode: 0644]
user/roslib/src/syscall.c
user/roslib/src/syscall_i386.c [deleted file]
user/roslib/src/syscall_sparc.c [deleted file]

index 399da63..8404e86 100644 (file)
@@ -9,14 +9,14 @@
 
 OBJDIR := obj
 
+# Make sure that 'all' is the first target
+all: symlinks
+
 # User defined constants passed on the command line 
 TARGET_ARCH := i386
 
 -include Makelocal
 
-# Make sure that 'all' is the first target
-all: symlinks
-
 TOP_DIR := .
 ARCH_DIR := $(TOP_DIR)/kern/arch
 INCLUDE_DIR := $(TOP_DIR)/kern/include
index 8edc67e..6cc68f6 100644 (file)
@@ -10,6 +10,7 @@
 #include <arch/apic.h>
 #include <ros/timer.h>
 #include <assert.h>
+#include <stdio.h>
 
 system_timing_t system_timing = {0, 0, 0xffff, 0};
 
index 040ded2..7ba316e 100644 (file)
@@ -7,6 +7,7 @@
 #include <atomic.h>
 #include <string.h>
 #include <assert.h>
+#include <stdio.h>
 
 #include <ros/memlayout.h>
 
index df67a96..30d30e5 100644 (file)
@@ -16,6 +16,7 @@
 #include <pmap.h>
 #include <kclock.h>
 #include <env.h>
+#include <stdio.h>
 
 // These variables are set in i386_vm_init()
 pde_t* boot_pgdir;             // Virtual address of boot time page directory
@@ -362,25 +363,13 @@ vm_init(void)
        //////////////////////////////////////////////////////////////////////
        // Make 'pages' point to an array of size 'npage' of 'struct Page'.
        // The kernel uses this structure to keep track of physical pages;
-       // 'npage' equals the number of physical pages in memory.  User-level
-       // programs get read-only access to the array as well.
-       // You must allocate the array yourself.
-       // Map this array read-only by the user at linear address UPAGES
-       // (ie. perm = PTE_U | PTE_P)
-       // Permissions:
-       //    - pages -- kernel RW, user NONE
-       //    - the read-only version mapped at UPAGES -- kernel R, user R
-       // Your code goes here: 
+       // 'npage' equals the number of physical pages in memory.  
+       // No longer mapping UPAGES into the address space
        
        // round up to the nearest page
        size_t page_array_size = ROUNDUP(npage*sizeof(page_t), PGSIZE);
        pages = (page_t *)boot_alloc(page_array_size, PGSIZE);
        memset(pages, 0, page_array_size);
-       if (page_array_size > PTSIZE) {
-               warn("page_array_size bigger than PTSIZE, userland will not see all pages");
-               page_array_size = PTSIZE;
-       }
-       boot_map_segment(pgdir, UPAGES, page_array_size, PADDR(pages), PTE_U | PTE_G);
 
        //////////////////////////////////////////////////////////////////////
        // Make 'envs' point to an array of size 'NENV' of 'env_t'.
@@ -471,11 +460,6 @@ check_boot_pgdir(bool pse)
 
        pgdir = boot_pgdir;
 
-       // check pages array
-       n = ROUNDUP(naddrpage*sizeof(page_t), PGSIZE);
-       for (i = 0; i < n; i += PGSIZE)
-               assert(check_va2pa(pgdir, UPAGES + i) == PADDR(pages) + i);
-
        // check phys mem
        //for (i = 0; KERNBASE + i != 0; i += PGSIZE)
        // adjusted check to account for only mapping avail mem
@@ -496,7 +480,6 @@ check_boot_pgdir(bool pse)
                case PDX(VPT):
                case PDX(UVPT):
                case PDX(KSTACKTOP-1):
-               case PDX(UPAGES):
                case PDX(LAPIC_BASE): // LAPIC mapping.  TODO: remove when MTRRs are up
                        assert(pgdir[i]);
                        break;
index fd99737..5a7fd8f 100644 (file)
@@ -215,3 +215,4 @@ uint32_t smp_main(void)
 
        return my_stack_top; // will be loaded in smp_entry.S
 }
+
index c06c489..472c238 100644 (file)
@@ -13,6 +13,7 @@
 #include <trap.h>
 #include <monitor.h>
 #include <process.h>
+#include <stdio.h>
 
 #include <syscall.h>
 
index 80dcc44..92714f6 100644 (file)
@@ -6,6 +6,7 @@
 #include <syscall.h>
 #include <monitor.h>
 #include <manager.h>
+#include <stdio.h>
 #include <smp.h>
 
 #ifdef __DEPUTY__
index 0c63ec2..38cdadb 100644 (file)
@@ -3,8 +3,6 @@
 #ifndef ROS_INC_ASSERT_H
 #define ROS_INC_ASSERT_H
 
-#include <stdio.h>
-
 void _warn(const char* NTS, int, const char* NTS, ...);
 void _panic(const char* NTS, int, const char* NTS, ...) __attribute__((noreturn));
 
index 54ebf75..097ffd7 100644 (file)
@@ -8,6 +8,7 @@
 #include <ros/syscall.h>
 #include <ros/sysevent.h>
 #include <ros/error.h>
+#include <ros/procdata.h>
 #include <arch/trap.h>
 #include <arch/types.h>
 #include <arch/arch.h>
@@ -16,8 +17,6 @@
 struct Env;
 typedef struct Env env_t;
 
-typedef int32_t envid_t;
-
 // An environment ID 'envid_t' has three parts:
 //
 // +1+---------------21-----------------+--------10--------+
@@ -34,6 +33,8 @@ typedef int32_t envid_t;
 // envid_ts less than 0 signify errors.  The envid_t == 0 is special, and
 // stands for the current environment.
 
+typedef int32_t envid_t;
+
 #define LOG2NENV               10
 #define NENV                   (1 << LOG2NENV)
 #define ENVX(envid)            ((envid) & (NENV - 1))
@@ -52,27 +53,22 @@ struct Env {
        uint32_t env_runs;                      // Number of times environment has run
        uint32_t env_refcnt;            // Reference count of kernel contexts using this
        uint32_t env_flags;
-       // The backring for processing asynchronous system calls from the user
-       // Note this is the actual backring, not a pointer to it somewhere else
-       syscall_back_ring_t env_syscallbackring;
-       // The front ring for pushing asynchronous system events out to the user
-       // Note this is the actual frontring, not a pointer to it somewhere else
-       sysevent_front_ring_t env_syseventfrontring;
 
        // Address space
        pde_t *COUNT(NPDENTRIES) env_pgdir;                     // Kernel virtual address of page dir
        physaddr_t env_cr3;                     // Physical address of page dir
 
-       // TODO - give this a proper type (pointers to a struct)
-       // - not always going to be PGSIZE either!
-       void*COUNT(PGSIZE) env_procinfo;                // KVA of per-process shared info table (RO)
-       // TODO - do we really want to get rid of procdata?
-       //void*COUNT(PGSIZE) env_procdata;              // KVA of per-process shared data table (RW)
+       // Per process info and data pages
+       procinfo_t *SAFE env_procinfo;       // KVA of per-process shared info table (RO)
+       procdata_t *SAFE env_procdata;       // KVA of per-process shared data table (RW)
+       
+       // The backring pointers for processing asynchronous system calls from the user
+       // Note this is the actual backring, not a pointer to it somewhere else
+       syscall_back_ring_t syscallbackring;
        
-       // Do we need these and the above back/front rings?
-       // Ring buffers for communicating with user space
-       syscall_sring_t*SAFE env_syscallring;   // Per-process ring buffer for async syscalls
-       sysevent_sring_t*SAFE env_syseventring; // Per-process ring buffer for async sysevents
+       // The front ring pointers for pushing asynchronous system events out to the user
+       // Note this is the actual frontring, not a pointer to it somewhere else
+       sysevent_front_ring_t syseventfrontring;
 };
 
 /* Process Flags */
index 8e4e6e9..507abfd 100644 (file)
  *                     |      Invalid Memory (*)      | --/--             |
  *    ULIM      ----> +------------------------------+ 0xbf800000      --+
  *                     |  Cur. Page Table (User R-)   | R-/R-  PTSIZE
- *    UVPT      ---->  +------------------------------+ 0xbf400000
- *                     |          RO PAGES            | R-/R-  PTSIZE
- *    UPAGES    ---->  +------------------------------+ 0xbf000000      --+
- *                     |  Unmapped (future expansion) | --/--             |
- *                     +------------------------------+ 0xbec01000      PTSIZE
- *                     |     Per-Process R/O Info     | R-/R-  PGSIZE     |
- * UTOP, UINFO  ---->  +------------------------------+ 0xbec00000      --+
- *                     |     Async Syscall Ring       | RW/RW  PGSIZE     |
- *   USYSCALL   ---->  +------------------------------+ 0xbebff000        |
- *                     |     Async Sysevent Ring      | RW/RW  PGSIZE     |
- *   USYSEVENT  ---->  +------------------------------+ 0xbebfe000      PTSIZE
- *                     |      Global Shared Page      | RW/RW  PGSIZE     |
- *     UGDATA   ---->  +------------------------------+ 0xbebfd000        |
- *                     |  Unmapped (future expansion) | --/--             |
- *   UXSTACKTOP ---->  +------------------------------+ 0xbe800000      --+
+ *    UVPT      ---->  +------------------------------+ 0xbf400000      --+
+ *                     | Unmapped (expandable region) |                   |
+ *                     |                              | R-/R-            PTSIZE
+ *                     |     Per-Process R/O Info     |                   |
+ * UTOP, UINFO  ---->  +------------------------------+ 0xbf000000      --+
+ *                     | Unmapped (expandable region) |                   |
+ *                     |                              | RW/RW            PTSIZE
+ *                     |     Per-Process R/W Data     |                   |
+ *    UDATA     ---->  +------------------------------+ 0xbec00000      --+
+ *                     |    Global Shared R/W Data    | RW/RW  PGSIZE
+ * UXSTACKTOP,UGDATA ->+------------------------------+ 0xbebff000
  *                     |     User Exception Stack     | RW/RW  PGSIZE
- *                     +------------------------------+ 0xbe7ff000
+ *                     +------------------------------+ 0xbebfe000
  *                     |       Empty Memory (*)       | --/--  PGSIZE
- *    USTACKTOP  --->  +------------------------------+ 0xbe7fe000
+ *    USTACKTOP  --->  +------------------------------+ 0xbebfd000
  *                     |      Normal User Stack       | RW/RW  PGSIZE
- *                     +------------------------------+ 0xbe7fd000
+ *                     +------------------------------+ 0xbebfc000
  *                     |                              |
  *                     |                              |
  *                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 // Same as VPT but read-only for users
 #define UVPT           (ULIM - PTSIZE)
-// Read-only copies of the Page structures
-#define UPAGES         (UVPT - PTSIZE)
-// Read-only, per-process shared info structures
-#define UINFO          (UPAGES - PTSIZE)
-#define UINFO_PAGES 1
 
 /*
  * Top of user VM. User can manipulate VA from UTOP-1 and down!
  */
 
 // Top of user-accessible VM
-#define UTOP           UINFO
+#define UTOP           (UVPT - PTSIZE)
+// Read-only, per-process shared info structures
+#define UINFO          UTOP
 
 // Read-write, per-process shared page for sending asynchronous 
 // syscalls to the kernel
-#define USYSCALL    (UTOP - PGSIZE)
-
-// Read-write, per-process shared page for receiving asynchronous 
-// sysevents from the kernel
-#define USYSEVENT   (USYSCALL - PGSIZE)
+#define UDATA    (UTOP - PTSIZE)
 
 // Read-write, global page.  Shared by all processes.  Can't be trusted.
-#define UGDATA   (USYSEVENT - PGSIZE)
+#define UGDATA   (UDATA - PGSIZE)
 
 // Top of one-page user exception stack
-#define UXSTACKTOP     (UTOP - PTSIZE)
+#define UXSTACKTOP     UGDATA
 // Next page left invalid to guard against exception stack overflow; then:
 // Top of normal user stack
 #define USTACKTOP      (UXSTACKTOP - 2*PGSIZE)
diff --git a/kern/include/ros/procdata.h b/kern/include/ros/procdata.h
new file mode 100644 (file)
index 0000000..f5ece87
--- /dev/null
@@ -0,0 +1,25 @@
+/* See COPYRIGHT for copyright information. */
+
+#ifndef ROS_PROCDATA_H
+#define ROS_PROCDATA_H
+
+#include <ros/memlayout.h>
+#include <ros/syscall.h>
+#include <ros/sysevent.h>
+#include <ros/error.h>
+
+typedef int32_t pid_t;
+
+typedef struct procinfo {
+       pid_t id;
+} procinfo_t;
+#define PROCINFO_NUM_PAGES  ((sizeof(procinfo_t)-1)/PGSIZE + 1)        
+
+typedef struct procdata {
+       // The actual ring buffers for communicating with user space
+       syscall_sring_t  syscallring;  // Per-process ring buffer for async syscalls
+       sysevent_sring_t syseventring; // Per-process ring buffer for async sysevents
+} procdata_t;
+#define PROCDATA_NUM_PAGES  ((sizeof(procdata_t)-1)/PGSIZE + 1)
+
+#endif // !ROS_PROCDATA_H
index ca4a836..0cd2e62 100644 (file)
@@ -43,6 +43,13 @@ typedef unsigned int RING_IDX;
 #define __RD16(_x) (((_x) & 0x0000ff00UL) ? __RD8((_x)>>8)<<8    : __RD8(_x))
 #define __RD32(_x) (((_x) & 0xffff0000UL) ? __RD16((_x)>>16)<<16 : __RD16(_x))
 
+/* Statically assert that two values are in fact equal.
+ * It works by enducing a compil error from a duplicate case in a switch 
+ * statement if the assertion is false.
+ */
+#define __ASSERT_EQUAL(x, y) \
+       switch ((x) == (y)) case 0: case ((x) == (y)):
+
 /*
  * Calculate size of a shared ring, given the total available space for the
  * ring and indexes (_sz), and the name tag of the request/response structure.
@@ -51,7 +58,24 @@ typedef unsigned int RING_IDX;
  * This tells us how many elements the ring _s can contain, given _sz space.
  */
 #define __RING_SIZE(_s, _sz) \
-    (__RD32(((_sz) - (long)(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
+    __RING_SIZE_BYTES(_s, _sz) / sizeof((_s)->ring[0])
+
+/*
+ * This is the same as above, except in terms of bytes instead of elements
+ */
+#define __RING_SIZE_BYTES(_s, _sz) \
+    (__RD32((_sz) - (long)(_s)->ring + (long)(_s)))
+
+/*
+ * These two are the same as above except that they rely on type information
+ * to determine the sizes statically, rather than the runtime instantiation
+ * of the ring buffer variable
+ */
+#define __RING_SIZE_STATIC(__name, _sz) \
+    (__RING_SIZE_BYTES_STATIC(_sz) / sizeof(union __name##_sring_entry))
+
+#define __RING_SIZE_BYTES_STATIC(_sz) \
+    (__RD32((_sz) - __RING_HEADER_SIZE()))
 
 /*
  * Macros to make the correct C datatypes for a new kind of ring.
@@ -62,14 +86,25 @@ typedef unsigned int RING_IDX;
  * In a header where you want the ring datatype declared, you then do:
  *
  *     DEFINE_RING_TYPES(mytag, request_t, response_t);
+ * or
+ *     DEFINE_RING_TYPES_WITH_SIZE(mytag, request_t, response_t, size);
  *
- * These expand out to give you a set of types, as you can see below.
+ * Both macros expand out to give you a set of types, as you can see below.
  * The most important of these are:
  * 
  *     mytag_sring_t      - The shared ring.
  *     mytag_front_ring_t - The 'front' half of the ring.
  *     mytag_back_ring_t  - The 'back' half of the ring.
  *
+ * The first of these macros will only declare a single element array to 
+ * represent the ring buffer in the shared ring struct that is ultimately
+ * created.  
+ *
+ * The second macro actually statically declares space of size (size) inside
+ * the shared ring struct. This size is rounded down to the nearest power of 2
+ * and space is subtracted off to account for holding any necessary ring 
+ * buffer headers.
+ *
  * To initialize a ring in your code you need to know the location and size
  * of the shared memory area (PAGE_SIZE, for instance). To initialise
  * the front half:
@@ -83,9 +118,26 @@ typedef unsigned int RING_IDX;
  *
  *     mytag_back_ring_t back_ring;
  *     BACK_RING_INIT(&back_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
+ *
+ * If you use the second of the two macros when first defining your ring 
+ * structures, then the size you use when initializing your front and back 
+ * rings *should* match the size you passed into this macro (e.g. PAGE_SIZE
+ * in this example).
  */
 
+#define __RING_HEADER()                                                 \
+    RING_IDX req_prod, req_event;                                       \
+    RING_IDX rsp_prod, rsp_event;                                       \
+    uint8_t  pad[48];
+    
+#define __RING_HEADER_SIZE() \
+    (sizeof(struct {__RING_HEADER()} ))
+
 #define DEFINE_RING_TYPES(__name, __req_t, __rsp_t)                     \
+       DEFINE_RING_TYPES_WITH_SIZE(__name, __req_t, __rsp_t,               \
+                                   __RING_HEADER_SIZE() + 1)
+
+#define DEFINE_RING_TYPES_WITH_SIZE(__name, __req_t, __rsp_t, __size)   \
                                                                         \
 /* Shared ring entry */                                                 \
 union __name##_sring_entry {                                            \
@@ -95,10 +147,8 @@ union __name##_sring_entry {                                            \
                                                                         \
 /* Shared ring page */                                                  \
 struct __name##_sring {                                                 \
-    RING_IDX req_prod, req_event;                                       \
-    RING_IDX rsp_prod, rsp_event;                                       \
-    uint8_t  pad[48];                                                   \
-    union __name##_sring_entry ring[1]; /* variable-length */           \
+       __RING_HEADER()                                                     \
+    union __name##_sring_entry ring[__RING_SIZE_STATIC(__name, __size)];\
 };                                                                      \
                                                                         \
 /* "Front" end's private variables */                                   \
@@ -120,7 +170,20 @@ struct __name##_back_ring {                                             \
 /* Syntactic sugar */                                                   \
 typedef struct __name##_sring __name##_sring_t;                         \
 typedef struct __name##_front_ring __name##_front_ring_t;               \
-typedef struct __name##_back_ring __name##_back_ring_t
+typedef struct __name##_back_ring __name##_back_ring_t;                 \
+                                                                        \
+/* This is a dummy function just used to statically assert that         \
+ * there are no weird padding issues associated with our sring structs  \
+ */                                                                     \
+static void __name##_assert_sring_size() __attribute__((used)) {        \
+       __ASSERT_EQUAL( sizeof(__name##_sring_t),                           \
+                       ( __RING_HEADER_SIZE()  +                           \
+                         ( __RING_SIZE_STATIC(__name, __size) *            \
+                           sizeof(union __name##_sring_entry)              \
+                         )                                                 \
+                       )                                                   \
+                     );                                                    \
+}              
 
 /*
  * Macros for manipulating rings.
@@ -305,3 +368,4 @@ typedef struct __name##_back_ring __name##_back_ring_t
  * indent-tabs-mode: nil
  * End:
  */
\ No newline at end of file
index 732d39b..72b30e3 100644 (file)
@@ -51,6 +51,7 @@ typedef struct syscall_rsp {
 } syscall_rsp_t;
 
 // Generic Syscall Ring Buffer
-DEFINE_RING_TYPES(syscall, syscall_req_t, syscall_rsp_t);
+#define SYSCALLRINGSIZE    PGSIZE
+DEFINE_RING_TYPES_WITH_SIZE(syscall, syscall_req_t, syscall_rsp_t, SYSCALLRINGSIZE);
 
 #endif /* !ROS_INCLUDE_SYSCALL_H */
index dc9d06a..6874fd3 100644 (file)
@@ -30,7 +30,8 @@ typedef struct sysevent_rsp {
        error_t rsp;
 } sysevent_rsp_t;
 
-// Generic Syscall Ring Buffer
-DEFINE_RING_TYPES(sysevent, sysevent_t, sysevent_rsp_t);
+// Generic Sysevent Ring Buffer
+#define SYSEVENTRINGSIZE    PGSIZE
+DEFINE_RING_TYPES_WITH_SIZE(sysevent, sysevent_t, sysevent_rsp_t, SYSEVENTRINGSIZE);
 
 #endif //ROS_SYSEVENT_H
\ No newline at end of file
index 9cd4637..9723732 100644 (file)
@@ -45,7 +45,7 @@ KERN_APPFILES := \
                  $(USER_APPS_PARLIB_DIR)/channel_test_server \
                  $(USER_APPS_ROSLIB_DIR)/measurements \
                  $(USER_APPS_PARLIB_DIR)/hello \
-                 $(USER_APPS_PARLIB_DIR)/matrix \
+                 $(USER_APPS_PARLIB_DIR)/matrix
 #                 $(USER_APPS_PARLIB_DIR)/open_read
 
 KERN_LDFLAGS   := $(KERN_LDFLAGS) -L$(OBJDIR)/$(KERN_DIR) \
index fa5fd05..2e9cf85 100644 (file)
@@ -17,6 +17,7 @@
 #include <trap.h>
 #include <monitor.h>
 #include <manager.h>
+#include <stdio.h>
 
 #include <ros/syscall.h>
 #include <ros/error.h>
@@ -112,79 +113,36 @@ env_init(void)
 //
 static int
 env_setup_vm(env_t *e)
-WRITES(e->env_pgdir, e->env_cr3, e->env_procinfo, e->env_syscallring,
-       e->env_syseventring, e->env_syscallbackring, e->env_syseventfrontring)
+WRITES(e->env_pgdir, e->env_cr3, e->env_procinfo, e->env_procdata)
 {
        int i, r;
        page_t *pgdir = NULL;
-       page_t *pginfo = NULL
-       page_t *pgsyscallring = NULL;
-       page_t *pgsyseventring = NULL;
+       page_t *pginfo[PROCINFO_NUM_PAGES] = {NULL}
+       page_t *pgdata[PROCDATA_NUM_PAGES] = {NULL};
+       static page_t* shared_page = 0;
 
        /* 
-        * Allocate pages for the page directory, shared info, shared data, 
-        * and kernel message pages
+        * First, allocate a page for the pgdir of this process and up 
+        * its reference count since this will never be done elsewhere
         */
        r = page_alloc(&pgdir);
        if(r < 0) return r;
-       r = page_alloc(&pginfo);
-       if (r < 0) {
-               page_free(pgdir);
-               return r;
-       }       
-       r = page_alloc(&pgsyscallring);
-       if (r < 0) {
-               page_free(pgdir);
-               page_free(pginfo);
-               return r;
-       }
-       r = page_alloc(&pgsyseventring);
-       if (r < 0) {
-               page_free(pgdir);
-               page_free(pginfo);
-               page_free(pgsyscallring);
-               return r;
-       }
-
-       // Now, set e->env_pgdir and e->env_cr3,
-       // and initialize the page directory.
-       //
-       // Hint:
-       //    - The VA space of all envs is identical above UTOP
-       //      (except at VPT and UVPT, which we've set below).
-       //      (and not for UINFO either)
-       //      See inc/memlayout.h for permissions and layout.
-       //      Can you use boot_pgdir as a template?  Hint: Yes.
-       //      (Make sure you got the permissions right in Lab 2.)
-       //    - The initial VA below UTOP is empty.
-       //    - You do not need to make any more calls to page_alloc.
-       //    - Note: pp_ref is not maintained for most physical pages
-       //      mapped above UTOP -- but you do need to increment
-       //      env_pgdir's pp_ref!
-
-       // need to up pgdir's reference, since it will never be done elsewhere
        pgdir->pp_ref++;
-       e->env_pgdir = page2kva(pgdir);
-       e->env_cr3 = page2pa(pgdir);
-       e->env_procinfo = page2kva(pginfo);
-       e->env_syscallring = page2kva(pgsyscallring);
-       e->env_syseventring = page2kva(pgsyseventring);
 
+       /* 
+        * Next, set up the e->env_pgdir and e->env_cr3 pointers to point
+        * to this newly allocated page and clear its contents
+        */
        memset(page2kva(pgdir), 0, PGSIZE);
-       memset(e->env_procinfo, 0, PGSIZE);
-       memset((void*COUNT(PGSIZE)) TC(e->env_syscallring), 0, PGSIZE);
-       memset((void*COUNT(PGSIZE)) TC(e->env_syseventring), 0, PGSIZE);
+       e->env_pgdir = (pde_t *COUNT(NPDENTRIES)) TC(page2kva(pgdir));
+       e->env_cr3 =   (physaddr_t) TC(page2pa(pgdir));
 
-       // Initialize the generic syscall ring buffer
-       SHARED_RING_INIT(e->env_syscallring);
-       // Initialize the backend of the syscall ring buffer
-       BACK_RING_INIT(&e->env_syscallbackring, e->env_syscallring, PGSIZE);
-                      
-       // Initialize the generic sysevent ring buffer
-       SHARED_RING_INIT(e->env_syseventring);
-       // Initialize the frontend of the sysevent ring buffer
-       FRONT_RING_INIT(&e->env_syseventfrontring, e->env_syseventring, PGSIZE);
+       /* 
+        * Now start filling in the pgdir with mappings required by all newly
+        * created address spaces
+        */
 
+       // Map in the kernel to the top of every address space
        // should be able to do this so long as boot_pgdir never has
        // anything put below UTOP
        // TODO check on this!  had a nasty bug because of it
@@ -192,57 +150,74 @@ WRITES(e->env_pgdir, e->env_cr3, e->env_procinfo, e->env_syscallring,
        // screwed up...
        memcpy(e->env_pgdir, boot_pgdir, NPDENTRIES*sizeof(pde_t));
 
-       // something like this.  TODO, if you want
-       //memcpy(&e->env_pgdir[PDX(UTOP)], &boot_pgdir[PDX(UTOP)], PGSIZE - PDX(UTOP));
-       // check with
-       // assert(memcmp(e->env_pgdir, boot_pgdir, PGSIZE) == 0);
-
        // VPT and UVPT map the env's own page table, with
        // different permissions.
        e->env_pgdir[PDX(VPT)]  = PTE(PPN(e->env_cr3), PTE_P | PTE_KERN_RW);
        e->env_pgdir[PDX(UVPT)] = PTE(PPN(e->env_cr3), PTE_P | PTE_USER_RO);
 
-       // Insert the per-process info and ring buffer pages into this process's 
-       // pgdir.  I don't want to do these two pages later (like with the stack), 
-       // since the kernel wants to keep pointers to it easily.
-       // Could place all of this with a function that maps a shared memory page
-       // that can work between any two address spaces or something.
-       r = page_insert(e->env_pgdir, pginfo, (void*SNT)UINFO, PTE_USER_RO);
-       if (r < 0) {
-               page_free(pgdir);
-               page_free(pginfo);
-               page_free(pgsyscallring);
-               page_free(pgsyseventring);
-               return r;
+       /*
+        * Now allocate and insert all pages required for the shared 
+        * procinfo structure into the page table
+        */
+       for(int i=0; i<PROCINFO_NUM_PAGES; i++) {
+               if(page_alloc(&pginfo[i]) < 0) 
+                       goto env_setup_vm_error;
+               if(page_insert(e->env_pgdir, pginfo[i], (void*SNT)(UINFO + i*PGSIZE), PTE_USER_RO) < 0)
+                       goto env_setup_vm_error;
        }
-       r = page_insert(e->env_pgdir, pgsyscallring, (void*SNT)USYSCALL, PTE_USER_RW);
-       if (r < 0) {
-               // note that we can't currently deallocate the pages created by
-               // pgdir_walk (inside insert).  should be able to gather them up when
-               // we destroy environments and their page tables.
-               page_free(pgdir);
-               page_free(pginfo);
-               page_free(pgsyscallring);
-               page_free(pgsyseventring);
-               return r;
+       
+       /*
+        * Now allocate and insert all pages required for the shared 
+        * procdata structure into the page table
+        */
+       for(int i=0; i<PROCDATA_NUM_PAGES; i++) {
+               if(page_alloc(&pgdata[i]) < 0)
+                       goto env_setup_vm_error;
+               if(page_insert(e->env_pgdir, pgdata[i], (void*SNT)(UDATA + i*PGSIZE), PTE_USER_RW) < 0)
+                       goto env_setup_vm_error;
        }
 
-       /* Shared page for all processes.  Can't be trusted, but still very useful
-        * at this stage for us.  Consider removing when we have real processes.
+       /* 
+        * Now, set e->env_procinfo, and e->env_procdata to point to 
+        * the proper pages just allocated and clear them out.
+        */
+       e->env_procinfo = (procinfo_t *SAFE) TC(page2kva(pginfo[0]));
+       e->env_procdata = (procdata_t *SAFE) TC(page2kva(pgdata[0]));
+       
+       memset(e->env_procinfo, 0, sizeof(procinfo_t));
+       memset(e->env_procdata, 0, sizeof(procdata_t));
+       
+       /* Finally, set up the Global Shared Data page for all processes.  
+        * Can't be trusted, but still very useful at this stage for us.  
+        * Consider removing when we have real processes.
         * (TODO).  Note the page is alloced only the first time through
         */
-       static page_t* shared_page = 0;
-       if (!shared_page)
-               page_alloc(&shared_page);
+       if (!shared_page) {
+               if(page_alloc(&shared_page) < 0)
+                       goto env_setup_vm_error;
        // Up it, so it never goes away.  One per user, plus one from page_alloc
        // This is necessary, since it's in the per-process range of memory that
        // gets freed during page_free.
        shared_page->pp_ref++;
+       }
 
        // Inserted into every process's address space at UGDATA
-       page_insert(e->env_pgdir, shared_page, (void*SNT)UGDATA, PTE_USER_RW);
+       if(page_insert(e->env_pgdir, shared_page, (void*SNT)UGDATA, PTE_USER_RW) < 0)
+               goto env_setup_vm_error;
 
        return 0;
+
+env_setup_vm_error:    
+       page_free(shared_page);
+       for(int i=0; i< PROCDATA_NUM_PAGES; i++) {
+               page_free(pgdata[i]);
+       }
+       for(int i=0; i< PROCINFO_NUM_PAGES; i++) {
+               page_free(pginfo[i]);
+       }
+       env_user_mem_free(e);
+       page_free(pgdir);
+       return -ENOMEM;
 }
 
 //
@@ -283,10 +258,33 @@ env_alloc(env_t **newenv_store, envid_t parent_id)
        e->env_refcnt = 1;
        e->env_flags = 0;
 
+
        memset(&e->env_ancillary_state, 0, sizeof(e->env_ancillary_state));
        memset(&e->env_tf, 0, sizeof(e->env_tf));
        env_init_trapframe(e);
 
+       /* 
+        * Initialize the contents of the e->env_procinfo structure
+        */
+        e->env_procinfo->id = (e->env_id & 0x3FF);
+        
+       /* 
+        * Initialize the contents of the e->env_procdata structure
+        */
+       // Initialize the generic syscall ring buffer
+       SHARED_RING_INIT(&e->env_procdata->syscallring);
+       // Initialize the backend of the syscall ring buffer
+       BACK_RING_INIT(&e->syscallbackring, 
+                      &e->env_procdata->syscallring, 
+                      SYSCALLRINGSIZE);
+                      
+       // Initialize the generic sysevent ring buffer
+       SHARED_RING_INIT(&e->env_procdata->syseventring);
+       // Initialize the frontend of the sysevent ring buffer
+       FRONT_RING_INIT(&e->syseventfrontring, 
+                       &e->env_procdata->syseventring, 
+                       SYSEVENTRINGSIZE);
+
        // commit the allocation
        LIST_REMOVE(e, env_link);
        *newenv_store = e;
index f832c31..df337a3 100644 (file)
@@ -9,6 +9,7 @@
 #include <ros/error.h>
 #include <pmap.h>
 #include <kmalloc.h>
+#include <stdio.h>
 
 #define kmallocdebug(args...)  printk(args)
 
index be5306e..0bcef2e 100644 (file)
@@ -18,6 +18,7 @@
 #include <syscall.h>
 #include <testing.h>
 #include <kfs.h>
+#include <stdio.h>
 
 /*
  * Currently, if you leave this function by way of env_run (process_workqueue
index 595209c..d886fb2 100644 (file)
@@ -14,6 +14,7 @@
 #include <pmap.h>
 #include <kclock.h>
 #include <process.h>
+#include <stdio.h>
 
 //
 // Allocate n bytes of physical memory aligned on an 
index 92a5efc..9e861e0 100644 (file)
@@ -16,6 +16,7 @@
 #include <pmap.h>
 #include <trap.h>
 #include <syscall.h>
+#include <stdio.h>
 #include <kfs.h> // eventually replace this with vfs.h
 
 //Do absolutely nothing.  Used for profiling.
@@ -378,7 +379,7 @@ intreg_t syscall_async(env_t* e, syscall_req_t *call)
 intreg_t process_generic_syscalls(env_t* e, size_t max)
 {
        size_t count = 0;
-       syscall_back_ring_t* sysbr = &e->env_syscallbackring;
+       syscall_back_ring_t* sysbr = &e->syscallbackring;
 
        // make sure the env is still alive.  
        // incref will return ESUCCESS on success.
index af9a83c..d436e32 100644 (file)
@@ -421,8 +421,6 @@ static void wait_for_all_envs_to_die(void)
                cpu_relax();
 }
 
-#if 0
-
 // this never returns.
 static void sync_tests(int start_core, int num_threads, int job_num)
 {
@@ -430,6 +428,7 @@ static void sync_tests(int start_core, int num_threads, int job_num)
        wait_for_all_envs_to_die();
        for (int i = start_core; i < start_core + num_threads; i++)
                env_batch[i] = ENV_CREATE(roslib_measurements);
+       lcr3(env_batch[start_core]->env_cr3);
        init_barrier(bar, num_threads);
        *job_to_run = job_num;
        for (int i = start_core; i < start_core + num_threads; i++)
@@ -450,7 +449,10 @@ static void async_tests(int start_core, int num_threads, int job_num)
        wait_for_all_envs_to_die();
        for (int i = start_core; i < start_core + num_threads; i++)
                env_batch[i] = ENV_CREATE(roslib_measurements);
+       printk("async_tests: checkpoint 0\n");
+       lcr3(env_batch[start_core]->env_cr3);
        init_barrier(bar, num_threads);
+       printk("async_tests: checkpoint 1\n");
        *job_to_run = job_num;
        for (int i = start_core; i < start_core + num_threads; i++)
                smp_call_function_single(i, run_env_handler, env_batch[i], 0);
@@ -539,8 +541,6 @@ void test_run_measurements(uint32_t job_num)
        panic("Error in test setup!!");
 }
 
-#endif // __i386__
-
 /************************************************************/
 /* ISR Handler Functions */
 
index 3d8e15e..c2a63ae 100644 (file)
@@ -7,7 +7,7 @@ USER_APPS_ROSLIB_LDFLAGS   := $(USER_LDFLAGS) -static \
                               -T $(USER_APPS_ROSLIB_DIR)/apps_$(TARGET_ARCH).ld
 USER_APPS_ROSLIB_LDDIRS    := -L$(OBJDIR)/$(USER_ROSLIB_DIR)
 USER_APPS_ROSLIB_LDLIBS    := --start-group -livyroslib -lroslib --end-group
-USER_APPS_ROSLIB_LDOBJS    := $(OBJDIR)/$(USER_ROSLIB_DIR)/entry_$(TARGET_ARCH).o 
+USER_APPS_ROSLIB_LDOBJS    := $(OBJDIR)/$(USER_ROSLIB_DIR)/$(TARGET_ARCH)/entry.o 
 USER_APPS_ROSLIB_LDDEPENDS := $(USER_APPS_ROSLIB_LDOBJS) \
                               $(OBJDIR)/$(USER_ROSLIB_DIR)/libivyroslib.a \
                               $(OBJDIR)/$(USER_ROSLIB_DIR)/libroslib.a \
index b8c4f08..7fea4e4 100644 (file)
@@ -1,4 +1,5 @@
 #include <lib.h>
+#include <stdio.h>
 #include <syswrapper.h>
 #include <arch/arch.h>
 #include <ros/syscall.h>
index fadc6a6..af30db3 100644 (file)
@@ -1,4 +1,5 @@
 #include <lib.h>
+#include <stdio.h>
 
 int main(int argc, char** argv)
 {
index 787423e..fe12755 100644 (file)
@@ -1,4 +1,5 @@
 #include <lib.h>
+#include <stdio.h>
 #include <syswrapper.h>
 #include <arch/arch.h>
 
index f5658f5..3905de2 100644 (file)
@@ -1,4 +1,6 @@
+
 #include <lib.h>
+#include <stdio.h>
 #include <syswrapper.h>
 
 int main(int argc, char** argv)
index b02cfa5..a2e8ddb 100644 (file)
@@ -11,6 +11,7 @@
 #include <ros/memlayout.h>
 #include <ros/syscall.h>
 #include <ros/error.h>
+#include <ros/procdata.h>
 #include <newlib_backend.h>
 
 enum {
@@ -18,10 +19,8 @@ enum {
        PG_RDWR   = 6,
 };
 
-// will need to change these types when we have real structs
-// seems like they need to be either arrays [] or functions () for it to work
-extern volatile uint8_t (COUNT(PGSIZE * UINFO_PAGES) procinfo)[];
-extern volatile uint8_t (COUNT(PGSIZE * UDATA_PAGES) procdata)[];
+extern procinfo_t* procinfo;
+extern procdata_t* procdata;
 
 intreg_t syscall(uint16_t num, intreg_t a1,
                 intreg_t a2, intreg_t a3,
index aa6e18e..4734b02 100644 (file)
@@ -9,7 +9,7 @@
        .globl procinfo
        .set procinfo, UINFO
        .globl procdata
-       .set procdata, USYSCALL
+       .set procdata, UDATA
        .globl pages
        .set pages, UPAGES
        .globl vpt
index e8a1718..c28a593 100644 (file)
@@ -12,10 +12,6 @@ extern int main(int argc, char **argv);
 
 void parlibmain(int argc, char **argv)
 {
-       /* This is a good time to connect a global var to the procinfo structure
-        * like we used to do with env_t */
-       //env = (env_t*)procinfo;       
-
        debug("Hello from process %d!\n", getpid());
        // call user main routine
        int r = main(argc, argv);
index f55b083..2a61b56 100644 (file)
@@ -10,7 +10,7 @@
        .globl procinfo
        .set procinfo, UINFO
        .globl procdata
-       .set procdata, USYSCALL
+       .set procdata, UDATA
        .globl pages
        .set pages, UPAGES
        .globl vpt
index 0c63ec2..38cdadb 100644 (file)
@@ -3,8 +3,6 @@
 #ifndef ROS_INC_ASSERT_H
 #define ROS_INC_ASSERT_H
 
-#include <stdio.h>
-
 void _warn(const char* NTS, int, const char* NTS, ...);
 void _panic(const char* NTS, int, const char* NTS, ...) __attribute__((noreturn));
 
index 712ede5..a758e15 100644 (file)
 #include <ros/timer.h>
 #include <ros/error.h>
 #include <ros/memlayout.h>
-#include <ros/syscall.h>
+#include <ros/procdata.h>
 
 #include <stdarg.h>
 #include <string.h>
 #include <pool.h>
+#include <assert.h>
 #include <sys/queue.h>
 
 #define USED(x)                (void)(x)
 
 // libos.c or entry.S
 extern char *binaryname;
-// will need to change these types when we have real structs
-// seems like they need to be either arrays [] or functions () for it to work
-extern volatile uint8_t (COUNT(PGSIZE * UINFO_PAGES) procinfo)[];
-extern volatile uint8_t (COUNT(PGSIZE * UDATA_PAGES) procdata)[];
-extern syscall_front_ring_t sysfrontring;
+extern procinfo_t* procinfo;
+extern procdata_t* procdata;
+extern syscall_front_ring_t syscallfrontring;
+extern sysevent_back_ring_t syseventbackring;
 void exit(void) __attribute__((noreturn));
 
 /*
@@ -71,6 +71,7 @@ error_t     waiton_syscall(syscall_desc_t* desc, syscall_rsp_t* rsp);
 // async callback
 #define MAX_SYSCALLS 100
 #define MAX_ASYNCCALLS 100
+
 // The high-level object a process waits on, with multiple syscalls within.
 typedef struct async_desc {
        syscall_desc_list_t syslist;
@@ -87,9 +88,6 @@ typedef struct async_rsp_t {
 // This is per-thread, and used when entering a async library call to properly
 // group syscall_desc_t used during the processing of that async call
 extern async_desc_t* current_async_desc;
-// stdio.h needs to be included after async_desc_t.  assert.h includes stdio.h.
-#include <stdio.h>
-#include <assert.h>
 
 // This pooltype contains syscall_desc_t, which is how you wait on one syscall.
 POOL_TYPE_DEFINE(syscall_desc_t, syscall_desc_pool, MAX_SYSCALLS);
index 75bab8b..d82ecaa 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef ROS_INC_STDIO_H
 #define ROS_INC_STDIO_H
 
+#include <lib.h>
 #include <stdarg.h>
 
 #ifndef NULL
@@ -39,8 +40,6 @@ int   vfprintf(int fd, const char *fmt, va_list);
 // lib/readline.c
 char *NTS readline(const char *NTS prompt);
 
-#include <lib.h>
-
 int    cprintf_async(async_desc_t** desc, const char * NTS fmt, ...);
 
 #endif /* !ROS_INC_STDIO_H */
index 11c4739..8e18fef 100644 (file)
@@ -14,7 +14,8 @@ USER_ROSLIB_SRC_SRCFILES := $(USER_ROSLIB_SRC_DIR)/console.c \
                             $(USER_ROSLIB_SRC_DIR)/readline.c \
                             $(USER_ROSLIB_SRC_DIR)/string.c \
                             $(USER_ROSLIB_SRC_DIR)/syscall.c \
-                            $(USER_ROSLIB_SRC_DIR)/syscall_$(TARGET_ARCH).c \
+                            $(USER_ROSLIB_SRC_DIR)/$(TARGET_ARCH)/syscall.c \
+                            $(USER_ROSLIB_SRC_DIR)/$(TARGET_ARCH)/entry.S \
                             $(USER_ROSLIB_SRC_DIR)/asynccall.c \
                             $(USER_ROSLIB_SRC_DIR)/atomic.c \
                             $(USER_ROSLIB_SRC_DIR)/timer.c 
diff --git a/user/roslib/src/entry_i386.S b/user/roslib/src/entry_i386.S
deleted file mode 100644 (file)
index 02cb4f3..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <arch/mmu.h>
-#include <ros/memlayout.h>
-
-.data
-
-
-// Define the global symbols 'procinfo', 'procdata', 'pages', 'vpt', and 'vpd'
-// so that they can be used in C as if they were ordinary global arrays.
-       .globl procinfo
-       .set procinfo, UINFO
-       .globl procdata
-       .set procdata, USYSCALL
-       .globl pages
-       .set pages, UPAGES
-       .globl vpt
-       .set vpt, UVPT
-       .globl vpd
-       .set vpd, (UVPT+(UVPT>>12)*4)
-
-
-// Entrypoint - this is where the kernel (or our parent process)
-// starts us running when we are initially created and run
-.text
-.globl _start
-_start:
-       // See if we were started with arguments on the stack
-       cmpl $USTACKTOP, %esp
-       jne args_exist
-
-       // If not, push dummy argc/argv arguments.
-       // This happens when we are loaded by the kernel,
-       // because the kernel does not know about passing arguments.
-       pushl $0
-       pushl $0
-
-args_exist:
-       call libmain
-1:      jmp 1b
-
diff --git a/user/roslib/src/entry_sparc.S b/user/roslib/src/entry_sparc.S
deleted file mode 100644 (file)
index ae19a6c..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#include <arch/mmu.h>
-#include <ros/memlayout.h>
-
-.data
-
-
-// Define the global symbols 'procinfo', 'procdata', 'pages', 'vpt', and 'vpd'
-// so that they can be used in C as if they were ordinary global arrays.
-       .globl procinfo
-       .set procinfo, UINFO
-       .globl procdata
-       .set procdata, USYSCALL
-       .globl pages
-       .set pages, UPAGES
-       .globl vpt
-       .set vpt, UVPT
-       .globl vpd
-       .set vpd, (UVPT+(UVPT>>12)*4)
-
-
-// Entrypoint - this is where the kernel (or our parent process)
-// starts us running when we are initially created and run
-.text
-.globl _start
-_start:
-       // See if we were started with arguments on the stack
-       tst     %o0
-       bne     args_exist
-        nop
-
-       // If not, push dummy argc/argv arguments.
-       // This happens when we are loaded by the kernel,
-       // because the kernel does not know about passing arguments.
-       mov     0,%o0
-       mov     0,%o1
-
-args_exist:
-       call    libmain
-        nop
-
-1:     ba      1b
-        nop
-
diff --git a/user/roslib/src/i386/entry.S b/user/roslib/src/i386/entry.S
new file mode 100644 (file)
index 0000000..2b94c7e
--- /dev/null
@@ -0,0 +1,39 @@
+#include <arch/mmu.h>
+#include <ros/memlayout.h>
+
+.data
+
+
+// Define the global symbols 'procinfo', 'procdata', 'pages', 'vpt', and 'vpd'
+// so that they can be used in C as if they were ordinary global arrays.
+       .globl procinfo
+       .set procinfo, UINFO
+       .globl procdata
+       .set procdata, UDATA
+       .globl pages
+       .set pages, UPAGES
+       .globl vpt
+       .set vpt, UVPT
+       .globl vpd
+       .set vpd, (UVPT+(UVPT>>12)*4)
+
+
+// Entrypoint - this is where the kernel (or our parent process)
+// starts us running when we are initially created and run
+.text
+.globl _start
+_start:
+       // See if we were started with arguments on the stack
+       cmpl $USTACKTOP, %esp
+       jne args_exist
+
+       // If not, push dummy argc/argv arguments.
+       // This happens when we are loaded by the kernel,
+       // because the kernel does not know about passing arguments.
+       pushl $0
+       pushl $0
+
+args_exist:
+       call libmain
+1:      jmp 1b
+
diff --git a/user/roslib/src/i386/syscall.c b/user/roslib/src/i386/syscall.c
new file mode 100644 (file)
index 0000000..d4ef7ab
--- /dev/null
@@ -0,0 +1,73 @@
+// System call stubs.
+#ifdef __DEPUTY__
+#pragma nodeputy
+#endif
+
+#include <arch/types.h>
+#include <arch/arch.h>
+
+// TODO: fix sysenter to take all 5 params
+static inline intreg_t syscall_sysenter(uint16_t num, intreg_t a1,
+                                 intreg_t a2, intreg_t a3,
+                                 intreg_t a4, intreg_t a5)
+{
+       intreg_t ret;
+       asm volatile ("  pushl %%ebp;        "
+                     "  pushl %%esi;        "
+                     "  movl %%esp, %%ebp;  "
+                     "  leal 1f, %%esi;     "
+                     "  sysenter;           "
+                     "1:                    "
+                     "  popl %%esi;         "
+                     "  popl %%ebp;         "
+                     : "=a" (ret)
+                     : "a" (num),
+                       "d" (a1),
+                       "c" (a2),
+                       "b" (a3),
+                       "D" (a4)
+                     : "cc", "memory");
+       return ret;
+}
+
+static inline intreg_t syscall_trap(uint16_t num, intreg_t a1,
+                             intreg_t a2, intreg_t a3,
+                             intreg_t a4, intreg_t a5)
+{
+       uint32_t ret;
+
+       // Generic system call: pass system call number in AX,
+       // up to five parameters in DX, CX, BX, DI, SI.
+       // Interrupt kernel with T_SYSCALL.
+       //
+       // The "volatile" tells the assembler not to optimize
+       // this instruction away just because we don't use the
+       // return value.
+       //
+       // The last clause tells the assembler that this can
+       // potentially change the condition codes and arbitrary
+       // memory locations.
+
+       asm volatile("int %1"
+                    : "=a" (ret)
+                    : "i" (T_SYSCALL),
+                      "a" (num),
+                      "d" (a1),
+                      "c" (a2),
+                      "b" (a3),
+                      "D" (a4),
+                      "S" (a5)
+                    : "cc", "memory");
+       return ret;
+}
+
+intreg_t syscall(uint16_t num, intreg_t a1,
+                intreg_t a2, intreg_t a3,
+                intreg_t a4, intreg_t a5)
+{
+       #ifndef SYSCALL_TRAP
+               return syscall_sysenter(num, a1, a2, a3, a4, a5);
+       #else
+               return syscall_trap(num, a1, a2, a3, a4, a5);
+       #endif
+}
index de138b8..4b6c704 100644 (file)
@@ -9,7 +9,8 @@
 extern int main(int argc, char **argv);
 
 char *binaryname = "(PROGRAM NAME UNKNOWN)";
-syscall_front_ring_t sysfrontring;
+syscall_front_ring_t syscallfrontring;
+sysevent_back_ring_t syseventbackring;
 syscall_desc_pool_t syscall_desc_pool;
 async_desc_pool_t async_desc_pool;
 timer_pool_t timer_pool;
@@ -17,16 +18,13 @@ timer_pool_t timer_pool;
 // This is meant to be PER USER THREAD!!! (TODO (benh))
 async_desc_t* current_async_desc;
 
-void
-libmain(int argc, char **argv)
+void libmain(int argc, char **argv)
 {
-       /* This is a good time to connect a global var to the procinfo structure
-        * like we used to do with env_t */
-       //env = (env_t*)procinfo;       
-
        // Set up the front ring for the general syscall ring
+       // and the back ring for the general sysevent ring
        // TODO: Reorganize these global variables
-       FRONT_RING_INIT(&sysfrontring, (syscall_sring_t*)procdata, PGSIZE);
+       FRONT_RING_INIT(&syscallfrontring, &(procdata->syscallring), SYSCALLRINGSIZE);
+       BACK_RING_INIT(&syseventbackring, &(procdata->syseventring), SYSEVENTRINGSIZE);
        POOL_INIT(&syscall_desc_pool, MAX_SYSCALLS);
        POOL_INIT(&async_desc_pool, MAX_ASYNCCALLS);
 
index 2a8bf2f..c3411dc 100644 (file)
@@ -1,6 +1,7 @@
 
 #include <lib.h>
 #include <arch/arch.h>
+#include <stdio.h>
 
 char *argv0;
 
diff --git a/user/roslib/src/sparc/entry.S b/user/roslib/src/sparc/entry.S
new file mode 100644 (file)
index 0000000..6ce88ec
--- /dev/null
@@ -0,0 +1,43 @@
+#include <arch/mmu.h>
+#include <ros/memlayout.h>
+
+.data
+
+
+// Define the global symbols 'procinfo', 'procdata', 'pages', 'vpt', and 'vpd'
+// so that they can be used in C as if they were ordinary global arrays.
+       .globl procinfo
+       .set procinfo, UINFO
+       .globl procdata
+       .set procdata, UDATA
+       .globl pages
+       .set pages, UPAGES
+       .globl vpt
+       .set vpt, UVPT
+       .globl vpd
+       .set vpd, (UVPT+(UVPT>>12)*4)
+
+
+// Entrypoint - this is where the kernel (or our parent process)
+// starts us running when we are initially created and run
+.text
+.globl _start
+_start:
+       // See if we were started with arguments on the stack
+       tst     %o0
+       bne     args_exist
+        nop
+
+       // If not, push dummy argc/argv arguments.
+       // This happens when we are loaded by the kernel,
+       // because the kernel does not know about passing arguments.
+       mov     0,%o0
+       mov     0,%o1
+
+args_exist:
+       call    libmain
+        nop
+
+1:     ba      1b
+        nop
+
diff --git a/user/roslib/src/sparc/syscall.c b/user/roslib/src/sparc/syscall.c
new file mode 100644 (file)
index 0000000..2528869
--- /dev/null
@@ -0,0 +1,10 @@
+__asm__ (".global syscall              \n\t"
+         "syscall:                     \n\t"
+         "mov %o0,%g1          \n\t"
+         "mov %o1,%o0          \n\t"
+         "mov %o2,%o1          \n\t"
+         "mov %o3,%o2          \n\t"
+         "mov %o4,%o3          \n\t"
+         "mov %o5,%o4          \n\t"
+         "retl                 \n\t"
+         "ta 8                 \n\t");
index 2254cb2..f5beaff 100644 (file)
@@ -18,19 +18,19 @@ static error_t async_syscall(syscall_req_t* req, syscall_desc_t* desc)
        // abort if there is no room for our request.  ring size is currently 64.
        // we could spin til it's free, but that could deadlock if this same thread
        // is supposed to consume the requests it is waiting on later.
-       if (RING_FULL(&sysfrontring))
+       if (RING_FULL(&syscallfrontring))
                return -EBUSY;
        // req_prod_pvt comes in as the previously produced item.  need to
        // increment to the next available spot, which is the one we'll work on.
        // at some point, we need to listen for the responses.
-       desc->idx = ++(sysfrontring.req_prod_pvt);
-       desc->sysfr = &sysfrontring;
-       syscall_req_t* r = RING_GET_REQUEST(&sysfrontring, desc->idx);
+       desc->idx = ++(syscallfrontring.req_prod_pvt);
+       desc->sysfr = &syscallfrontring;
+       syscall_req_t* r = RING_GET_REQUEST(&syscallfrontring, desc->idx);
        memcpy(r, req, sizeof(syscall_req_t));
-       // push our updates to sysfrontring.req_prod_pvt
-       RING_PUSH_REQUESTS(&sysfrontring);
+       // push our updates to syscallfrontring.req_prod_pvt
+       RING_PUSH_REQUESTS(&syscallfrontring);
        //cprintf("DEBUG: sring->req_prod: %d, sring->rsp_prod: %d\n", \
-               sysfrontring.sring->req_prod, sysfrontring.sring->rsp_prod);
+               syscallfrontring.sring->req_prod, syscallfrontring.sring->rsp_prod);
        return 0;
 }
 
diff --git a/user/roslib/src/syscall_i386.c b/user/roslib/src/syscall_i386.c
deleted file mode 100644 (file)
index d4ef7ab..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-// System call stubs.
-#ifdef __DEPUTY__
-#pragma nodeputy
-#endif
-
-#include <arch/types.h>
-#include <arch/arch.h>
-
-// TODO: fix sysenter to take all 5 params
-static inline intreg_t syscall_sysenter(uint16_t num, intreg_t a1,
-                                 intreg_t a2, intreg_t a3,
-                                 intreg_t a4, intreg_t a5)
-{
-       intreg_t ret;
-       asm volatile ("  pushl %%ebp;        "
-                     "  pushl %%esi;        "
-                     "  movl %%esp, %%ebp;  "
-                     "  leal 1f, %%esi;     "
-                     "  sysenter;           "
-                     "1:                    "
-                     "  popl %%esi;         "
-                     "  popl %%ebp;         "
-                     : "=a" (ret)
-                     : "a" (num),
-                       "d" (a1),
-                       "c" (a2),
-                       "b" (a3),
-                       "D" (a4)
-                     : "cc", "memory");
-       return ret;
-}
-
-static inline intreg_t syscall_trap(uint16_t num, intreg_t a1,
-                             intreg_t a2, intreg_t a3,
-                             intreg_t a4, intreg_t a5)
-{
-       uint32_t ret;
-
-       // Generic system call: pass system call number in AX,
-       // up to five parameters in DX, CX, BX, DI, SI.
-       // Interrupt kernel with T_SYSCALL.
-       //
-       // The "volatile" tells the assembler not to optimize
-       // this instruction away just because we don't use the
-       // return value.
-       //
-       // The last clause tells the assembler that this can
-       // potentially change the condition codes and arbitrary
-       // memory locations.
-
-       asm volatile("int %1"
-                    : "=a" (ret)
-                    : "i" (T_SYSCALL),
-                      "a" (num),
-                      "d" (a1),
-                      "c" (a2),
-                      "b" (a3),
-                      "D" (a4),
-                      "S" (a5)
-                    : "cc", "memory");
-       return ret;
-}
-
-intreg_t syscall(uint16_t num, intreg_t a1,
-                intreg_t a2, intreg_t a3,
-                intreg_t a4, intreg_t a5)
-{
-       #ifndef SYSCALL_TRAP
-               return syscall_sysenter(num, a1, a2, a3, a4, a5);
-       #else
-               return syscall_trap(num, a1, a2, a3, a4, a5);
-       #endif
-}
diff --git a/user/roslib/src/syscall_sparc.c b/user/roslib/src/syscall_sparc.c
deleted file mode 100644 (file)
index 2528869..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-__asm__ (".global syscall              \n\t"
-         "syscall:                     \n\t"
-         "mov %o0,%g1          \n\t"
-         "mov %o1,%o0          \n\t"
-         "mov %o2,%o1          \n\t"
-         "mov %o3,%o2          \n\t"
-         "mov %o4,%o3          \n\t"
-         "mov %o5,%o4          \n\t"
-         "retl                 \n\t"
-         "ta 8                 \n\t");