Ported process stuff to SPARC port
authorAndrew Waterman <waterman@r53.millennium.berkeley.edu>
Wed, 14 Oct 2009 01:00:00 +0000 (18:00 -0700)
committerKevin Klues <klueska@r53.millennium.berkeley.edu>
Wed, 21 Oct 2009 01:45:38 +0000 (18:45 -0700)
18 files changed:
kern/arch/i386/init.h
kern/arch/sparc/arch.h
kern/arch/sparc/console.c
kern/arch/sparc/frontend.c
kern/arch/sparc/frontend.h
kern/arch/sparc/process.c
kern/arch/sparc/sparc.h
kern/arch/sparc/timer.c
kern/arch/sparc/trap.c
kern/arch/sparc/trap_entry.S
kern/include/pmap.h
kern/src/manager.c
kern/src/pmap.c
kern/src/syscall.c
user/parlib/inc/debug.h
user/parlib/src/sparc/newlib_backend.c
user/roslib/src/sparc/Makefrag
user/roslib/src/sparc/libmain.c [new file with mode: 0644]

index 9db49ec..77c4361 100644 (file)
@@ -5,4 +5,5 @@
 
 void arch_init();
 
-#endif // !ROS_ARCH_INIT_H
\ No newline at end of file
+#endif // !ROS_ARCH_INIT_H
+
index 2049a81..b23bd0a 100644 (file)
@@ -12,7 +12,6 @@
 
 #include <ros/common.h>
 #include <arch/timer.h>
-#include <arch/frontend.h>
 
 static __inline void breakpoint(void) __attribute__((always_inline));
 static __inline void invlpg(void *addr) __attribute__((always_inline));
@@ -151,7 +150,6 @@ cache_flush(void)
 static __inline void
 reboot(void)
 {
-       frontend_syscall(RAMP_SYSCALL_exit,0,0,0);
        while(1);
 }
 
index 4b0c2af..6c06532 100644 (file)
@@ -1,4 +1,5 @@
 #include <arch/frontend.h>
+#include <pmap.h>
 
 void
 cons_init(void)
@@ -10,7 +11,7 @@ cons_init(void)
 void
 cputbuf(const char*COUNT(len) buf, int len)
 {
-       frontend_syscall(RAMP_SYSCALL_write,1,(uint32_t)buf,len);
+       frontend_syscall(RAMP_SYSCALL_write,1,(uint32_t)PADDR(buf),len);
 }
 
 // Low-level console I/O
index 09de8f8..0c45043 100644 (file)
@@ -1,5 +1,3 @@
-#include <atomic.h>
-
 #ifdef __SHARC__
 #pragma nosharc
 #endif
@@ -8,8 +6,59 @@
 #pragma nodeputy
 #endif
 
+#include <atomic.h>
+#include <pmap.h>
+#include <arch/frontend.h>
+
 volatile int magic_mem[8] __attribute__((aligned(32)));
 
+int32_t frontend_syscall_from_user(env_t* p, int32_t syscall_num, uint32_t arg0, uint32_t arg1, uint32_t arg2)
+{
+       int32_t ret;
+       #define KBUFSIZE 1024
+       char buf[KBUFSIZE];
+
+       switch(syscall_num)
+       {
+               case RAMP_SYSCALL_write:
+                       arg2 = arg2 > KBUFSIZE ? KBUFSIZE : arg2;
+                       if(memcpy_from_user(p,buf,(void*)arg1,arg2))
+                               return -1;
+                       arg1 = PADDR((uint32_t)buf);
+                       ret = frontend_syscall(syscall_num,arg0,arg1,arg2);
+                       break;
+
+               case RAMP_SYSCALL_open:
+                       if(memcpy_from_user(p,buf,(void*)arg0,KBUFSIZE))
+                               return -1;
+                       arg0 = PADDR((uint32_t)buf);
+                       ret = frontend_syscall(syscall_num,arg0,arg1,arg2);
+                       break;
+
+               case RAMP_SYSCALL_fstat:
+                       ret = frontend_syscall(syscall_num,arg0,PADDR((uint32_t)buf),arg2);
+                       if(memcpy_to_user(p,(void*)arg1,buf,64))
+                               return -1;
+                       break;
+
+               case RAMP_SYSCALL_read:
+                       arg2 = arg2 > KBUFSIZE ? KBUFSIZE : arg2;
+                       ret = frontend_syscall(syscall_num,arg0,PADDR((uint32_t)buf),arg2);
+                       if(memcpy_to_user(p,(void*)arg1,buf,arg2))
+                               return -1;
+                       break;
+
+               case RAMP_SYSCALL_getch:
+                       return frontend_syscall(RAMP_SYSCALL_getch,0,0,0);
+
+               default:
+                       ret = -1;
+                       break;
+       }
+
+       return ret;
+}
+
 int32_t frontend_syscall(int32_t syscall_num, uint32_t arg0, uint32_t arg1, uint32_t arg2)
 {
        static spinlock_t lock = 0;
index 36d5d4b..5b0e0fe 100644 (file)
@@ -3,8 +3,14 @@
 
 #include <ros/common.h>
 
+#ifdef ROS_KERNEL
+
+#include <env.h>
+int32_t frontend_syscall_from_user(env_t* p, int32_t syscall_num, uint32_t arg0, uint32_t arg1, uint32_t arg2);
 int32_t frontend_syscall(int32_t syscall_num, uint32_t arg0, uint32_t arg1, uint32_t arg2);
 
+#endif
+
 #define RAMP_SYSCALL_exit              1
 #define RAMP_SYSCALL_read              3
 #define RAMP_SYSCALL_write             4
index 8729a0f..18fcc15 100644 (file)
@@ -33,5 +33,13 @@ proc_init_trapframe(trapframe_t *tf)
 
 void proc_set_tfcoreid(trapframe_t *tf, uint32_t id)
 {
-       tf->gpr[8] = id;
+       tf->gpr[10] = id;
+}
+
+/* For cases that we won't return from a syscall via the normal path, and need
+ * to set the syscall return value in the registers manually.  Like in a syscall
+ * moving to RUNNING_M */
+void proc_set_syscall_retval(trapframe_t *SAFE tf, intreg_t value)
+{
+       tf->gpr[8] = value;
 }
index b246f30..a108e2c 100644 (file)
@@ -23,7 +23,6 @@
 #define XSTR(arg) STR(arg)
 
 #include <ros/common.h>
-#include <arch/frontend.h>
 
 static __inline uint32_t read_psr(void) __attribute__((always_inline));
 static __inline uint32_t read_wim(void) __attribute__((always_inline));
index 557b58d..01ceef2 100644 (file)
@@ -29,7 +29,8 @@ asm (
 
 void
 timer_init(void)
-{
+{      
+#if 0
        uint32_t ticks = timer_ticks;
        uint64_t tsc_ticks;
 
@@ -41,6 +42,8 @@ timer_init(void)
        while(ticks == timer_ticks) ;
 
        system_timing.tsc_freq = (read_tsc() - tsc_ticks)*INTERRUPT_TIMER_HZ;
+#endif
+       system_timing.tsc_freq = 1000000;
 
        cprintf("TSC Frequency: %llu\n", system_timing.tsc_freq);
 }
index c9bcbfd..88d0a43 100644 (file)
@@ -227,7 +227,7 @@ handle_syscall(trapframe_t* state)
 
        env_push_ancillary_state(current);
 
-       state->gpr[8] = syscall(current,num,a1,a2,a3,a4,a5);
+       state->gpr[8] = syscall(current,state,num,a1,a2,a3,a4,a5);
 
        trap_handled();
 }
index c0df71a..80b55c4 100644 (file)
@@ -28,17 +28,12 @@ handle_trap:
        bne,a   1f
         sub    %fp,64+SIZEOF_TRAPFRAME_T+SIZEOF_ACTIVE_MESSAGE_T,%l6
 
-1:     # back up what might be an active message (%asr8-12)
-       mov     %asr8,%l3
-       st      %l3,[%l6+64+SIZEOF_TRAPFRAME_T+0]
-       mov     %asr9,%l3
+1:     # back up what might be an active message
+       st      %l0,[%l6+64+SIZEOF_TRAPFRAME_T+0]
        st      %l3,[%l6+64+SIZEOF_TRAPFRAME_T+4]
-       mov     %asr10,%l3
-       st      %l3,[%l6+64+SIZEOF_TRAPFRAME_T+8]
-       mov     %asr11,%l3
-       st      %l3,[%l6+64+SIZEOF_TRAPFRAME_T+12]
-       mov     %asr12,%l3
-       st      %l3,[%l6+64+SIZEOF_TRAPFRAME_T+16]
+       st      %l4,[%l6+64+SIZEOF_TRAPFRAME_T+8]
+       st      %l5,[%l6+64+SIZEOF_TRAPFRAME_T+12]
+       st      %g0,[%l6+64+SIZEOF_TRAPFRAME_T+16]
 
        mov     %l7,%l0
        # At this point we may use %l3/4/5/7 as temporary regs
index 7cbaed2..0f6d8c2 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (c) 2009 The Regents of the University of California
  * Barret Rhoden <brho@cs.berkeley.edu>
  * Kevin Klues <klueska@cs.berkeley.edu> (multiboot functions)
- * Ander Waterman <waterman@cs.berkeley.edu> (memcpy_from_user)
+ * Andrew Waterman <waterman@cs.berkeley.edu> (memcpy_to/from_user)
  * Zach Anderson (zra@cs.berkeley.edu> (user_mem_strlcpy)
  * See LICENSE for details.
  *
@@ -92,6 +92,10 @@ size_t user_mem_strlcpy(env_t *env, char *NT COUNT(len - 1),
 error_t
 memcpy_from_user(env_t* env, void* COUNT(len) dest,
                  const void *DANGEROUS va, size_t len);
+
+error_t
+memcpy_to_user(env_t* env, void*DANGEROUS va,
+                 const void *COUNT(len) src, size_t len);
                  
 /* Arch specific implementations for these */
 pte_t *pgdir_walk(pde_t *COUNT(NPDENTRIES) pgdir, const void *SNT va, int create);
index c16ccb8..d35dbdf 100644 (file)
@@ -40,14 +40,12 @@ void manager(void)
        // This is a bypass of the standard manager structure, for network use
        // If enabled, this spawns parlib_matrix, and allows the execution
        // of a remote binary to function correctly (schedule() call below)
-       #ifdef __NETWORK__      
        if (progress++ == 0) {
                envs[0] = kfs_proc_create(kfs_lookup_path("parlib_matrix"));
                proc_set_state(envs[0], PROC_RUNNABLE_S);
                proc_run(envs[0]);
        }
        schedule();
-       #endif 
 
        switch (progress++) {
                case 0:
index afcc0a9..16bdae3 100644 (file)
@@ -426,14 +426,69 @@ error_t memcpy_from_user(env_t* env, void* COUNT(len) dest,
                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 = PPN(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;
index cfa98bc..56a7058 100644 (file)
 #include <resource.h>
 #include <kfs.h> // eventually replace this with vfs.h
 
+#ifdef __sparc_v8__
+#include <arch/frontend.h>
+#endif 
+
 #ifdef __NETWORK__
 #include <arch/nic_common.h>
 extern char *CT(PACKET_HEADER_SIZE + len) (*packet_wrap)(const char *CT(len) data, size_t len);
@@ -491,10 +495,10 @@ intreg_t syscall(struct proc *p, trapframe_t *tf, uintreg_t syscallno,
                        return sys_serial_write(p, (char *DANGEROUS)a1, (size_t)a2);
                case SYS_serial_read:
                        return sys_serial_read(p, (char *DANGEROUS)a1, (size_t)a2);
+       #endif
                case SYS_run_binary:
                        return sys_run_binary(p, (char *DANGEROUS)a1,
                                              (char* DANGEROUS)a2, (size_t)a3);
-       #endif
        #ifdef __NETWORK__
                case SYS_eth_write:
                        return sys_eth_write(p, (char *DANGEROUS)a1, (size_t)a2);
@@ -503,7 +507,7 @@ intreg_t syscall(struct proc *p, trapframe_t *tf, uintreg_t syscallno,
        #endif
        #ifdef __sparc_v8__
                case SYS_frontend:
-                       return frontend_syscall(a1,a2,a3,a4);
+                       return frontend_syscall_from_user(p,a1,a2,a3,a4);
        #endif
 
                default:
index c967525..eec8b35 100644 (file)
@@ -1,18 +1,11 @@
 #ifndef PARLIB_INC_DEBUG_H
 #define PARLIB_INC_DEBUG_H
 
-typedef void * TRUSTED va_list;
+typedef __builtin_va_list va_list;
 
-#define __va_size(type) \
-    (((sizeof(type) + sizeof(long) - 1) / sizeof(long)) * sizeof(long))
-
-#define va_start(ap, last) \
-    ((ap) = (va_list)&(last) + __va_size(last))
-
-#define va_arg(ap, type) \
-    (*(type *COUNT(1))((ap) += __va_size(type), (ap) - __va_size(type)))
-
-#define va_end(ap)  ((void)0)
+#define va_start(v,l)   __builtin_va_start(v,l)
+#define va_end(v)      __builtin_va_end(v)
+#define va_arg(v,l)     __builtin_va_arg(v,l)
 
 size_t strnlen(const char *NTS s, size_t size);
 #ifdef __DEPUTY__
index 1eed4b4..2e931dd 100644 (file)
@@ -7,6 +7,7 @@
 #include <sys/unistd.h>
 #include <sys/times.h>
 #include <sys/time.h>
+#include <debug.h>
 
 char *__env[1] = { 0 };
 char **environ = __env;
@@ -128,22 +129,28 @@ gettimeofday(struct timeval* tp, void* tzp)
        return -1;
 }
 
-void*SNT
-sbrk(ptrdiff_t incr)
+/* sbrk()
+ * Increase program data space. 
+ * As malloc and related functions depend on this, it is 
+ * useful to have a working implementation. 
+ * The following suffices for a standalone system; it exploits the 
+ * symbol _end automatically defined by the GNU linker.
+ */
+void* sbrk(ptrdiff_t incr) 
 {
-       #define HEAP_SIZE 8192
+       #define HEAP_SIZE (1<<23)
        static uint8_t array[HEAP_SIZE];
-       static uint8_t*SNT heap_end = array;
-       static uint8_t*SNT stack_ptr = &(array[HEAP_SIZE-1]);
+       static uint8_t *BND(array, array + HEAP_SIZE) heap_end = array;
+       static uint8_t *stack_ptr = &(array[HEAP_SIZE-1]);
 
-       uint8_t*SNT prev_heap_end;
+       uint8_t* prev_heap_end; 
 
        prev_heap_end = heap_end;
        if (heap_end + incr > stack_ptr) {
                errno = ENOMEM;
-               return (void*SNT)-1;
+               return (void*CT(1))TC(-1);
        }
 
        heap_end += incr;
-       return (caddr_t SNT) prev_heap_end;
+       return (caddr_t) prev_heap_end;
 }
index e7baf20..2cb0db2 100644 (file)
@@ -10,5 +10,6 @@ OBJDIRS += $(USER_ROSLIB_ARCH_SRC_DIR)
 # We also snatch the use of a couple handy source files
 # from the lib directory, to avoid gratuitous code duplication.
 USER_ROSLIB_ARCH_SRCFILES := $(USER_ROSLIB_ARCH_SRC_DIR)/syscall.c \
-                             $(USER_ROSLIB_ARCH_SRC_DIR)/entry.S
+                             $(USER_ROSLIB_ARCH_SRC_DIR)/entry.S \
+                             $(USER_ROSLIB_ARCH_SRC_DIR)/libmain.c
 
diff --git a/user/roslib/src/sparc/libmain.c b/user/roslib/src/sparc/libmain.c
new file mode 100644 (file)
index 0000000..d3107c6
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * Arch specific implementations of lib.h functions.
+ */
+
+#include <lib.h>
+
+/* Return the vcoreid, which is set in entry.S right before calling libmain.
+ * This should only be used in libmain() and main(), before any code that might
+ * use a register.  It just returns eax. */
+uint32_t newcore(void)
+{
+       uint32_t ret;
+       asm volatile("mov %%o2,%0" : "=r"(ret));
+       return ret;
+}
+
+/* This should only be used in libmain(), to reset eax before calling main from
+ * vcore0 (which is the only one calling libmain). */
+void setvcore0(void)
+{
+       asm volatile ("mov 0,%o2");
+}