Merge branch 'net-dev'. See body of commit for details.
authorPaul Pearce <pearce@eecs.berkeley.edu>
Thu, 17 Sep 2009 00:42:04 +0000 (17:42 -0700)
committerPaul Pearce <pearce@eecs.berkeley.edu>
Thu, 17 Sep 2009 00:42:04 +0000 (17:42 -0700)
This is a merge of the mptable, ioapic, pci, ethernet, and ethernet based remote syscall code.

By default on x86, the mptable, ioapic, and pci code is enabled. Network code is not.

In order to enable the ethernet driver, you must define __NETWORK__
in your make local, and set USER_MAC_ADDRESS to the correct value
in order to communicate with your front end machine. The front end
server app now lives in tools/. Setting __NETWORK__ will cause the
driver to initialize on real hardware, or perform a series of interrupt
tests for simulation. This will also cause parlab_matrix to be the userspace
application booted, instead of the standard apps in manager.c. Network
support is x86 dependent.

Other things handled in this commit include:

Updated doxygen support. Doxygen will now strip out ivy annotations, and
be optimized for C code.

Rewritten newlib_backend. The code is now several orders of magnitude better
(no seriously, look at it).

Conflicts:
kern/arch/i386/Makefrag
kern/include/kfs.h
kern/include/ros/syscall.h
kern/src/Makefrag
kern/src/init.c
kern/src/kfs.c
kern/src/kmalloc.c
kern/src/manager.c
kern/src/syscall.c
kern/src/testing.c
user/roslib/inc/sys

154 files changed:
GNUmakefile
kern/Makefrag
kern/arch/i386/Makefrag
kern/arch/i386/apic.c
kern/arch/i386/apic.h
kern/arch/i386/arch.h
kern/arch/i386/atomic.h
kern/arch/i386/colored_caches.c
kern/arch/i386/console.c
kern/arch/i386/console.h
kern/arch/i386/cpuinfo.c
kern/arch/i386/env.c
kern/arch/i386/ioapic.c
kern/arch/i386/ioapic.h
kern/arch/i386/kclock.c
kern/arch/i386/kdebug.c
kern/arch/i386/mmu.h
kern/arch/i386/mptables.c
kern/arch/i386/mptables.h
kern/arch/i386/ne2k.c
kern/arch/i386/ne2k.h
kern/arch/i386/page_alloc.c
kern/arch/i386/pci.c
kern/arch/i386/pmap.c
kern/arch/i386/process.c [new file with mode: 0644]
kern/arch/i386/rl8168.c
kern/arch/i386/rl8168.h
kern/arch/i386/smp.c
kern/arch/i386/smp.h
kern/arch/i386/smp_boot.c
kern/arch/i386/trap.c
kern/arch/i386/trap.h
kern/arch/i386/trapentry.S
kern/arch/i386/types.h
kern/arch/i386/x86.h
kern/arch/sparc/atomic.h
kern/arch/sparc/boot.c
kern/arch/sparc/colored_caches.c
kern/arch/sparc/console.h
kern/arch/sparc/env.c
kern/arch/sparc/env.c.save [deleted file]
kern/arch/sparc/env.c.save.1 [deleted file]
kern/arch/sparc/frontend.h
kern/arch/sparc/pmap.c
kern/arch/sparc/smp.c
kern/arch/sparc/smp.h
kern/arch/sparc/sparc.h
kern/arch/sparc/timer.c
kern/arch/sparc/timer.h
kern/arch/sparc/trap.c
kern/arch/sparc/trap.h
kern/include/assert.h
kern/include/atomic.h
kern/include/colored_caches.h
kern/include/colored_page_alloc.h
kern/include/elf.h
kern/include/env.h
kern/include/ivy/sharc.h [new file with mode: 0644]
kern/include/kdebug.h
kern/include/kfs.h
kern/include/kmalloc.h
kern/include/listable.h
kern/include/manager.h
kern/include/monitor.h
kern/include/multiboot.h
kern/include/page_alloc.h
kern/include/pmap.h
kern/include/process.h
kern/include/ros/common.h [new file with mode: 0644]
kern/include/ros/error.h
kern/include/ros/memlayout.h
kern/include/ros/mman.h [new file with mode: 0644]
kern/include/ros/noivy.h [new file with mode: 0644]
kern/include/ros/procdata.h
kern/include/ros/ring_buffer.h
kern/include/ros/syscall.h
kern/include/smp.h
kern/include/stab.h
kern/include/stdint.h [new file with mode: 0644]
kern/include/stdio.h
kern/include/string.h
kern/include/sys/queue.h
kern/include/sys/types.h [new file with mode: 0644]
kern/include/syscall.h
kern/include/testing.h
kern/include/timing.h
kern/include/trap.h
kern/include/types.h [new file with mode: 0644]
kern/include/workqueue.h
kern/ivy/Makefrag
kern/ivy/deputy.c
kern/ivy/sharc.c [new file with mode: 0644]
kern/src/Makefrag
kern/src/atomic.c
kern/src/colored_caches.c
kern/src/env.c
kern/src/init.c
kern/src/kfs.c
kern/src/kmalloc.c
kern/src/manager.c
kern/src/monitor.c
kern/src/multiboot.c
kern/src/page_alloc.c
kern/src/pmap.c
kern/src/printf.c
kern/src/printfmt.c
kern/src/process.c
kern/src/readline.c
kern/src/schedule.c
kern/src/smp.c
kern/src/string.c
kern/src/syscall.c
kern/src/sysevent.c
kern/src/testing.c
kern/src/timer.c
kern/src/workqueue.c
user/Makefrag
user/apps/parlib/Makefrag
user/apps/parlib/file_error.c
user/apps/parlib/file_io.c
user/apps/parlib/matrix.c
user/apps/parlib/readline.c
user/apps/roslib/measurements.c
user/apps/roslib/mhello.c [new file with mode: 0644]
user/parlib/inc/channel.h
user/parlib/inc/libc_patch.h
user/parlib/inc/newlib_backend.h
user/parlib/inc/parlib.h
user/parlib/ivy/Makefrag
user/parlib/ivy/deputy.c
user/parlib/src/Makefrag
user/parlib/src/debug.c
user/parlib/src/debugfmt.c
user/parlib/src/i386/newlib_backend.c
user/parlib/src/i386/syscall.c
user/roslib/inc/lib.h
user/roslib/inc/measure.h
user/roslib/inc/stdint.h [new file with mode: 0644]
user/roslib/inc/string.h
user/roslib/inc/sys [new symlink]
user/roslib/inc/sys/queue.h [deleted symlink]
user/roslib/inc/sys~88b8671ba3a11748b50b03007ef263be90e0b490 [new symlink]
user/roslib/inc/types.h [deleted file]
user/roslib/ivy/Makefrag
user/roslib/ivy/deputy.c
user/roslib/src/asynccall.c
user/roslib/src/exit.c
user/roslib/src/i386/entry.S
user/roslib/src/i386/syscall.c
user/roslib/src/printf.c
user/roslib/src/printfmt.c
user/roslib/src/syscall.c
user/roslib/src/syswrapper.c
user/roslib/src/timer.c

index 0a1a680..2976206 100644 (file)
@@ -6,7 +6,6 @@
 #      http://aegis.sourceforge.net/auug97.pdf
 #
 
-
 OBJDIR := obj
 
 # Make sure that 'all' is the first target
@@ -14,12 +13,14 @@ all: symlinks
 
 # User defined constants passed on the command line 
 TARGET_ARCH := i386
+COMPILER := IVY
 
 -include Makelocal
 
 TOP_DIR := .
 ARCH_DIR := $(TOP_DIR)/kern/arch
 INCLUDE_DIR := $(TOP_DIR)/kern/include
+
 UNAME=$(shell uname -m)
 V = @
 
@@ -48,7 +49,19 @@ GCCPREFIX := $(shell if i386-ros-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/de
 endif
 
 # Default programs for compilation
-CC         := ivycc --deputy --gcc=$(GCCPREFIX)gcc --enable-error-db $(EXTRAARGS)
+ifeq ($(COMPILER),IVY)
+KERN_CFLAGS := --deputy\
+                  --enable-error-db\
+                  --no-rc-sharc\
+                  --sc-dynamic-is-error\
+                  --sc-ops=$(INCLUDE_DIR)/ivy/sharc.h\
+                  --sc-all-in-thread
+USER_CFLAGS := --deputy --enable-error-db
+CC         := ivycc --gcc=$(GCCPREFIX)gcc
+else
+CC         := $(GCCPREFIX)gcc -std=gnu99 -fgnu89-inline
+endif
+
 AS         := $(GCCPREFIX)as
 AR         := $(GCCPREFIX)ar
 LD         := $(GCCPREFIX)ld
@@ -60,7 +73,7 @@ PERL    := perl
 # Universal compiler flags
 # -fno-builtin is required to avoid refs to undefined functions in the kernel.
 # Only optimize to -O1 to discourage inlining, which complicates backtraces.
-CFLAGS := $(CFLAGS) -D$(TARGET_ARCH)
+CFLAGS := $(CFLAGS) -D$(TARGET_ARCH) $(EXTRAARGS)
 CFLAGS += -O2 -pipe -MD -fno-builtin -fno-stack-protector -gstabs
 CFLAGS += -Wall -Wno-format -Wno-unused -Wno-attributes
 CFLAGS += -nostdinc -Igccinclude/$(TARGET_ARCH)
index 3687d72..d0d60c9 100644 (file)
@@ -1,6 +1,6 @@
 KERN_DIR := kern
 
-KERN_CFLAGS := $(CFLAGS) -DROS_KERNEL
+KERN_CFLAGS += $(CFLAGS) -DROS_KERNEL
 KERN_CFLAGS += -I$(INCLUDE_DIR)
 KERN_LDFLAGS := $(LDFLAGS)
 
index 84aed02..ba6fc6f 100644 (file)
@@ -25,9 +25,10 @@ KERN_ARCH_SRCFILES := $(KERN_ARCH_SRC_DIR)/entry.S \
                       $(KERN_ARCH_SRC_DIR)/smp.c \
                       $(KERN_ARCH_SRC_DIR)/apic.c \
                       $(KERN_ARCH_SRC_DIR)/kdebug.c \
-                         $(KERN_ARCH_SRC_DIR)/mptables.c \
-                         $(KERN_ARCH_SRC_DIR)/pci.c \
-                         $(KERN_ARCH_SRC_DIR)/ioapic.c \
-                         $(KERN_ARCH_SRC_DIR)/rl8168.c \
-                         $(KERN_ARCH_SRC_DIR)/ne2k.c \
+                      $(KERN_ARCH_SRC_DIR)/process.c \
+                      $(KERN_ARCH_SRC_DIR)/mptables.c \
+                      $(KERN_ARCH_SRC_DIR)/pci.c \
+                      $(KERN_ARCH_SRC_DIR)/ioapic.c \
+                      $(KERN_ARCH_SRC_DIR)/rl8168.c \
+                      $(KERN_ARCH_SRC_DIR)/ne2k.c \
                       $(KERN_ARCH_SRC_DIR)/env.c
index 4a06ad2..35620ed 100644 (file)
@@ -4,6 +4,10 @@
  * See LICENSE for details.
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <arch/mmu.h>
 #include <arch/x86.h>
 #include <arch/arch.h>
@@ -145,7 +149,7 @@ static int getpit()
     return ((high << 8) | low);
 }
 
-// forces cpu to relax for usec miliseconds
+// forces cpu to relax for usec miliseconds.  declared in kern/include/timing.h
 void udelay(uint64_t usec)
 {
        #if !defined(__BOCHS__)
index 907ddd5..615950f 100644 (file)
@@ -101,7 +101,7 @@ void timer_init(void);
 void udelay_pit(uint64_t usec);
 // TODO: right now timer defaults to TSC
 uint64_t gettimer(void);
-uint64_t inline getfreq(void);
+uint64_t getfreq(void);
 
 static inline void pic_send_eoi(uint32_t irq);
 static inline void lapic_send_eoi(void);
@@ -184,9 +184,8 @@ static inline void lapic_disable(void)
  */
 static inline void lapic_wait_to_send(void)
 {
-       static inline void cpu_relax(void);
        while(read_mmreg32(LAPIC_IPI_ICR_LOWER) & 0x1000)
-               cpu_relax();
+               __cpu_relax();
 }
 
 static inline void lapic_enable(void)
index 135dedc..3ddb38f 100644 (file)
@@ -2,9 +2,9 @@
 #define ROS_INC_ARCH_H
 
 #include <arch/x86.h>
-#include <arch/types.h>
-#include <arch/apic.h>
+#include <ros/common.h>
 #include <arch/trap.h>
+#include <arch/apic.h>
 
 /* Arch Constants */
 #define MAX_NUM_CPUS                           255
@@ -111,9 +111,7 @@ disable_irqsave(int8_t* state)
 static __inline void
 cpu_relax(void)
 {
-       // in case the compiler doesn't serialize for pause, the "m" will make sure
-       // no memory is reordered around this instruction.
-       asm volatile("pause" : : : "memory");
+       __cpu_relax();
 }
 
 static __inline void
@@ -123,7 +121,7 @@ cpu_halt(void)
 }
 
 static __inline void
-clflush(uintptr_t* addr) __attribute__((always_inline))
+clflush(uintptr_t* addr)
 {
        asm volatile("clflush %0" : : "m"(*addr));
 }
@@ -143,7 +141,7 @@ core_id(void)
 static __inline void
 cache_flush(void)
 {
-        wbinvd();
+       wbinvd();
 }
 
 static __inline void
@@ -154,4 +152,4 @@ reboot(void)
        while(1);
 }
 
-#endif /* !ROS_INC_X86_H */
+#endif /* !ROS_INC_ARCH_H */
index 3dbfa75..ce675e9 100644 (file)
@@ -1,23 +1,26 @@
 #ifndef ROS_INCLUDE_ATOMIC_H
 #define ROS_INCLUDE_ATOMIC_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 #define mb() {rmb(); wmb();}
 #define rmb() ({ asm volatile("lfence"); })
 #define wmb() 
+/* Force a wmb, used in cases where an IPI could beat a write, even though
+ * write-orderings are respected. */
+#define wmb_f() ({ asm volatile("sfence"); })
 
-typedef void* atomic_t;
-typedef volatile uint32_t spinlock_t;
+typedef void * RACY atomic_t;
+typedef volatile uint32_t RACY spinlock_t;
 
 static inline void atomic_init(atomic_t *number, int32_t val);
 static inline int32_t atomic_read(atomic_t *number);
 static inline void atomic_set(atomic_t *number, int32_t val);
 static inline void atomic_inc(atomic_t *number);
 static inline void atomic_dec(atomic_t *number);
-static inline void atomic_andb(volatile uint8_t* number, uint8_t mask);
-static inline void spin_lock(volatile uint32_t*COUNT(1) lock);
-static inline void spin_unlock(volatile uint32_t* lock);
+static inline void atomic_andb(volatile uint8_t RACY* number, uint8_t mask);
+static inline void spin_lock(volatile uint32_t SRACY*COUNT(1) lock);
+static inline void spin_unlock(volatile uint32_t SRACY* lock);
 
 /* Inlined functions declared above */
 static inline void atomic_init(atomic_t *number, int32_t val)
@@ -48,7 +51,7 @@ static inline void atomic_dec(atomic_t *number)
        asm volatile("lock decl %0" : "=m"(*number) : : "cc");
 }
 
-static inline void atomic_andb(volatile uint8_t *number, uint8_t mask)
+static inline void atomic_andb(volatile uint8_t RACY*number, uint8_t mask)
 {
        asm volatile("lock andb %1,%0" : "=m"(*number) : "r"(mask) : "cc");
 }
index ec42145..f437954 100644 (file)
@@ -5,6 +5,10 @@
  * Kevin Klues <klueska@cs.berkeley.edu>    
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <colored_caches.h>
 
 // Global variables
@@ -23,4 +27,5 @@ void cache_init()
        available_caches.l1 = TRUE;
        available_caches.l2 = TRUE;
        available_caches.l3 = TRUE;
+       available_caches.llc = &l3;
 }
index 7ba316e..d4aa439 100644 (file)
@@ -37,7 +37,7 @@ void scroll_screen(void);
 #define COM_LSR_DATA   0x01    //   Data available
 #define COM_LSR_READY  0x20    //   Ready to send
 
-static bool serial_exists;
+static bool SREADONLY serial_exists;
 
 int
 serial_proc_data(void)
@@ -47,7 +47,8 @@ serial_proc_data(void)
        return inb(COM1+COM_RX);
 }
 
-int serial_read_byte() {
+int serial_read_byte()
+{
        return serial_proc_data();
 }
 
@@ -80,7 +81,10 @@ serial_init(void)
 
        // Clear any preexisting overrun indications and interrupts
        // Serial port doesn't exist if COM_LSR returns 0xFF
-       serial_exists = (inb(COM1+COM_LSR) != 0xFF);
+       {
+               bool lbool = ((inb(COM1+COM_LSR) != 0xFF));
+               serial_exists = SINIT(lbool);
+       }
        (void) inb(COM1+COM_IIR);
        (void) inb(COM1+COM_RX);
 
@@ -148,18 +152,20 @@ lpt_putc(int c)
 #define MAX_SCROLL_LENGTH      20
 #define SCROLLING_CRT_SIZE     (MAX_SCROLL_LENGTH * CRT_SIZE)
 
-static unsigned addr_6845;
-static uint16_t *COUNT(CRT_SIZE) crt_buf;
-static uint16_t crt_pos;
+static volatile uint32_t SRACY lock = 0;
 
-static uint16_t scrolling_crt_buf[SCROLLING_CRT_SIZE];
-static uint16_t scrolling_crt_pos;
-static uint8_t current_crt_buf;
+static unsigned SREADONLY addr_6845;
+static uint16_t *SLOCKED(&lock) COUNT(CRT_SIZE) crt_buf;
+static uint16_t SLOCKED(&lock) crt_pos;
+
+static uint16_t (SLOCKED(&lock) scrolling_crt_buf)[SCROLLING_CRT_SIZE];
+static uint16_t SLOCKED(&lock) scrolling_crt_pos;
+static uint8_t SLOCKED(&lock) current_crt_buf;
 
 void
 cga_init(void)
 {
-       volatile uint16_t *COUNT(CRT_SIZE) cp;
+       volatile uint16_t SLOCKED(&lock)*COUNT(CRT_SIZE) cp;
        uint16_t was;
        unsigned pos;
 
@@ -168,10 +174,10 @@ cga_init(void)
        *cp = (uint16_t) 0xA55A;
        if (*cp != 0xA55A) {
                cp = (uint16_t *COUNT(CRT_SIZE)) TC(KERNBASE + MONO_BUF);
-               addr_6845 = MONO_BASE;
+               addr_6845 = SINIT(MONO_BASE);
        } else {
                *cp = was;
-               addr_6845 = CGA_BASE;
+               addr_6845 = SINIT(CGA_BASE);
        }
        
        /* Extract cursor location */
@@ -180,13 +186,15 @@ cga_init(void)
        outb(addr_6845, 15);
        pos |= inb(addr_6845 + 1);
 
-       crt_buf = (uint16_t *COUNT(CRT_SIZE)) cp;
+       crt_buf = (uint16_t SLOCKED(&lock)*COUNT(CRT_SIZE)) cp;
        crt_pos = pos;
        scrolling_crt_pos = 0;
        current_crt_buf = 0;
+
 }
 
-static void set_screen(uint8_t screen_num) {
+static void set_screen(uint8_t screen_num)
+{
        uint16_t leftovers = (scrolling_crt_pos % CRT_COLS);
        leftovers = (leftovers) ? CRT_COLS - leftovers : 0;
        
@@ -196,19 +204,22 @@ static void set_screen(uint8_t screen_num) {
        memcpy(crt_buf, scrolling_crt_buf + offset, CRT_SIZE * sizeof(uint16_t));
 }
 
-static void scroll_screen_up(void) {
+static void scroll_screen_up(void)
+{
        if(current_crt_buf <  (scrolling_crt_pos / CRT_SIZE))
                current_crt_buf++;
        set_screen(current_crt_buf);
 }
 
-static void scroll_screen_down(void) {
+static void scroll_screen_down(void)
+{
        if(current_crt_buf > 0) 
                current_crt_buf--;
        set_screen(current_crt_buf);
 }
 
-static void reset_screen(void) {
+static void reset_screen(void)
+{
        current_crt_buf = 0;
        set_screen(current_crt_buf);
 }
@@ -296,7 +307,7 @@ cga_putc(int c)
 
 #define E0ESC          (1<<6)
 
-static uint8_t shiftcode[256] = 
+static uint8_t (SREADONLY shiftcode)[256] = 
 {
        [0x1D] CTL,
        [0x2A] SHIFT,
@@ -306,7 +317,7 @@ static uint8_t shiftcode[256] =
        [0xB8] ALT
 };
 
-static uint8_t togglecode[256] = 
+static uint8_t (SREADONLY togglecode)[256] = 
 {
        [0x3A] CAPSLOCK,
        [0x45] NUMLOCK,
@@ -374,7 +385,7 @@ static uint8_t ctlmap[256] =
        [0xD2] KEY_INS,         [0xD3] KEY_DEL
 };
 
-static uint8_t * COUNT(256) charcode[4] = {
+static uint8_t * COUNT(256) (SREADONLY charcode)[4] = {
        normalmap,
        shiftmap,
        ctlmap,
@@ -385,13 +396,15 @@ static uint8_t * COUNT(256) charcode[4] = {
  * Get data from the keyboard.  If we finish a character, return it.  Else 0.
  * Return -1 if no data.
  */
+static uint32_t SLOCKED(&lock) shift;
+static bool SLOCKED(&lock) crt_scrolled = FALSE;
+
 static int
 kbd_proc_data(void)
 {
        int c;
        uint8_t data;
-       static uint32_t shift;
-       static bool crt_scrolled = FALSE;
+
 
        if ((inb(KBSTATP) & KBS_DIB) == 0)
                return -1;
@@ -478,12 +491,13 @@ kbd_init(void)
 // whenever the corresponding interrupt occurs.
 
 #define CONSBUFSIZE    512
-
-static struct {
+struct cons {
        uint8_t buf[CONSBUFSIZE];
        uint32_t rpos;
        uint32_t wpos;
-} cons;
+};
+
+static struct cons SLOCKED(&lock) cons;
 
 // called by device interrupt routines to feed input characters
 // into the circular console input buffer.
@@ -507,6 +521,8 @@ cons_getc(void)
 {
        int c;
 
+       spin_lock_irqsave(&lock);
+
        // poll for any pending input characters,
        // so that this function works even when interrupts are disabled
        // (e.g., when called from the kernel monitor).
@@ -520,8 +536,10 @@ cons_getc(void)
                c = cons.buf[cons.rpos++];
                if (cons.rpos == CONSBUFSIZE)
                        cons.rpos = 0;
+               spin_unlock_irqsave(&lock);
                return c;
        }
+       spin_unlock_irqsave(&lock);
        return 0;
 }
 
@@ -529,7 +547,7 @@ cons_getc(void)
 void
 cons_putc(int c)
 {
-       static uint32_t lock;
+       //static uint32_t lock; zra: moving up for sharC annotations
        spin_lock_irqsave(&lock);
        #ifndef SERIAL_IO
                serial_putc(c);
index c00fa58..205581a 100644 (file)
@@ -6,7 +6,7 @@
 # error "This is a ROS kernel header; user programs should not #include it"
 #endif
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 #define MONO_BASE      0x3B4
 #define MONO_BUF       0xB0000
index 4322a98..9330f5d 100644 (file)
@@ -4,6 +4,10 @@
  * See LICENSE for details.
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <arch/arch.h>
 #include <arch/x86.h>
 #include <arch/mmu.h>
@@ -20,7 +24,7 @@ void print_cpuinfo(void)
        uint32_t model, family;
        uint64_t msr_val;
        char vendor_id[13];
-       extern char (SNT _start)[];
+       extern char (SNT SREADONLY _start)[];
 
        asm volatile ("cpuid;"
                  "movl    %%ebx, (%2);"
@@ -68,7 +72,7 @@ void print_cpuinfo(void)
        if (ecx & 0x00000060) {
                msr_val = read_msr(IA32_FEATURE_CONTROL);
                printd("64 Bit Feature Control: 0x%08x\n", msr_val);
-               if (msr_val & 0x5 == 0x5)
+               if ((msr_val & 0x5) == 0x5)
                        printk("Hardware virtualization supported\n");
                else
                        printk("Hardware virtualization not supported\n");
@@ -97,9 +101,11 @@ void print_cpuinfo(void)
 
 void show_mapping(uintptr_t start, size_t size)
 {
-       pde_t *COUNT(PTSIZE) pgdir = (pde_t *COUNT(PTSIZE))vpd;
-       pte_t *pte, *pde;
-       page_t* page;
+       pde_t SLOCKED(&vpd_lock) *COUNT(PTSIZE) pgdir =
+           (pde_t SLOCKED(&vpd_lock) *COUNT(PTSIZE))vpd;
+       pte_t *pte;
+       pte_t SLOCKED(&vpd_lock) *pde;
+       page_t *page;
        uintptr_t i;
 
        cprintf("   Virtual    Physical  Ps Dr Ac CD WT U W\n");
@@ -121,6 +127,7 @@ void show_mapping(uintptr_t start, size_t size)
 
 void backtrace(void)
 { TRUSTEDBLOCK
+       extern char (SNT SREADONLY _start)[];
        uint32_t *ebp, eip;
        eipdebuginfo_t debuginfo;
        char buf[256];
index 986b96a..45132c0 100644 (file)
@@ -1,6 +1,6 @@
 /* See COPYRIGHT for copyright information. */
-#ifdef __DEPUTY__
-#pragma noasync
+#ifdef __SHARC__
+#pragma nosharc
 #endif
 
 #include <arch/trap.h>
@@ -51,30 +51,6 @@ void env_pop_tf(trapframe_t *tf)
        }
 }
 
-void
-env_set_program_counter(env_t* e, uintptr_t pc)
-{
-       e->env_tf.tf_eip = pc;
-}
-
-void
-env_init_trapframe(env_t* e)
-{
-       // Set up appropriate initial values for the segment registers.
-       // GD_UD is the user data segment selector in the GDT, and
-       // GD_UT is the user text segment selector (see inc/memlayout.h).
-       // The low 2 bits of each segment register contains the
-       // Requestor Privilege Level (RPL); 3 means user mode.
-       e->env_tf.tf_ds = GD_UD | 3;
-       e->env_tf.tf_es = GD_UD | 3;
-       e->env_tf.tf_ss = GD_UD | 3;
-       e->env_tf.tf_esp = USTACKTOP;
-       e->env_tf.tf_cs = GD_UT | 3;
-       // You will set e->env_tf.tf_eip later.
-       // set the env's EFLAGSs to have interrupts enabled
-       e->env_tf.tf_eflags |= 0x00000200; // bit 9 is the interrupts-enabled
-}
-
 // Flush all mapped pages in the user portion of the address space
 void
 env_user_mem_free(env_t* e)
index 4dc20fe..483f32b 100644 (file)
@@ -3,6 +3,11 @@
  * See LICENSE for details.
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+// Not currently sharc complient.
+
 /** @file
  * @brief Basic IOAPIC Driver.
  *
@@ -19,7 +24,6 @@
  * @todo Some notion of a 'initalized' flag we can check to ensure bootup call order.
  */
 
-
 #include <arch/mmu.h>
 #include <arch/x86.h>
 #include <arch/apic.h>
@@ -147,6 +151,7 @@ void ioapic_init() {
   * There is no notion of success besides invalid data, which casues a panic.
   *
   * @todo Logical partition support
+  * @todo Decide on a synchronization mechinism
   *
   * @param[in] irq     The IRQ we are trying to route. This is non-kernal-offseted. EX: Pit is IRQ 0, not 32.
   * @param[in] dest    The core id we want to route irq to
@@ -159,6 +164,7 @@ void ioapic_route_irq(uint8_t irq, uint8_t dest) {
        }
 
        // THIS IS A TEMP CHECK. IF WE USE LOGICAL PARTITIONS THIS MUST BE REMOVED
+        extern uint8_t num_cpus;
        if (dest >= num_cpus)
                panic("TRYING TO REROUTE TO AN INVALID DESTINATION!");
        
@@ -186,6 +192,8 @@ void ioapic_route_irq(uint8_t irq, uint8_t dest) {
   * This function must be called after ioapic_init() is called, but need not be called after a matching ioapic_route_irq()
   *
   * There is no notion of success besides invalid data, which casues a panic.
+  *
+  * @todo Decide on a synchronization mechinism
   * 
   * @param[in] irq     The IRQ we are trying to unroute. This is non-kernal-offseted. EX: Pit is IRQ 0, not 32.
   */
@@ -202,4 +210,4 @@ void ioapic_unroute_irq(uint8_t irq) {
        write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , IOAPIC_REDIRECT_OFFSET + 2*ioapic_redirects[irq].ioapic_int + 1);
        write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + IOAPIC_WRITE_WINDOW_OFFSET, IOAPIC_UNROUTE_HIGH);
 
-}
\ No newline at end of file
+}
index 88ba7c2..157407f 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef ROS_KERN_IOAPIC_H
 #define ROS_KERN_IOAPIC_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 /* IOAPIC_BASE really go away. This is NOT required by the spec as far as I know.
  * This was originally in apic.h, but Paul moved it here. This is NOT used by
index 6f42dce..da4e187 100644 (file)
@@ -5,6 +5,10 @@
  * generates interrupts on IRQ 0.
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <arch/x86.h>
 
 #include <kclock.h>
index 2b8f098..a2cf1a5 100644 (file)
@@ -1,3 +1,7 @@
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <stab.h>
 #include <string.h>
 #include <assert.h>
index 115b810..9b3a67c 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef ROS_INC_MMU_H
 #define ROS_INC_MMU_H
 
+#ifndef __ASSEMBLER__
+#include <ros/common.h>
+#endif
+
 /*
  * This file contains definitions for the x86 memory management unit (MMU),
  * including paging- and segmentation-related data structures and constants,
 
 #else  // not __ASSEMBLER__
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 // Segment Descriptors
 typedef struct Segdesc {
@@ -199,19 +203,37 @@ typedef struct Segdesc {
        unsigned sd_base_31_24 : 8; // High bits of segment base address
 } segdesc_t;
 // Null segment
-#define SEG_NULL       (segdesc_t){ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+#define SEG_NULL       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 // Segment that is loadable but faults when used
-#define SEG_FAULT      (segdesc_t){ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 }
+#define SEG_FAULT      { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 }
 // Normal segment
-#define SEG(type, base, lim, dpl) (segdesc_t)                                          \
+#define SEG(type, base, lim, dpl)                                                                      \
 { ((lim) >> 12) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,      \
     type, 1, dpl, 1, (unsigned) (lim) >> 28, 0, 0, 1, 1,                       \
     (unsigned) (base) >> 24 }
-#define SEG16(type, base, lim, dpl) (segdesc_t)                                                \
+
+#define SEG16(type, base, lim, dpl)                                                            \
 { (lim) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,                      \
     type, 1, dpl, 1, (unsigned) (lim) >> 16, 0, 0, 1, 0,                       \
     (unsigned) (base) >> 24 }
 
+#define SEG16ROINIT(seg,type,base,lim,dpl) \
+       {\
+               (seg).sd_lim_15_0 = SINIT((lim) & 0xffff);\
+               (seg).sd_base_15_0 = SINIT((base)&0xffff);\
+               (seg).sd_base_23_16 = SINIT(((base)>>16)&0xff);\
+               (seg).sd_type = SINIT(type);\
+               (seg).sd_s = SINIT(1);\
+               (seg).sd_dpl = SINIT(dpl);\
+               (seg).sd_p = SINIT(1);\
+               (seg).sd_lim_19_16 = SINIT((unsigned)(lim)>>16);\
+               (seg).sd_avl = SINIT(0);\
+               (seg).sd_rsv1 = SINIT(0);\
+               (seg).sd_db = SINIT(1);\
+               (seg).sd_g = SINIT(0);\
+               (seg).sd_base_31_24 = SINIT((unsigned)(base)>> 24);\
+       }
+
 #endif /* !__ASSEMBLER__ */
 
 // Application segment type bits
@@ -321,6 +343,19 @@ typedef struct Gatedesc {
        (gate).gd_off_31_16 = (uint32_t) (off) >> 16;           \
 }
 
+#define ROSETGATE(gate, istrap, sel, off, dpl)                 \
+{                                                              \
+       (gate).gd_off_15_0 = SINIT((uint32_t) (off) & 0xffff);          \
+       (gate).gd_ss = SINIT(sel);                                      \
+       (gate).gd_args = SINIT(0);                                      \
+       (gate).gd_rsv1 = SINIT(0);                                      \
+       (gate).gd_type = SINIT((istrap) ? STS_TG32 : STS_IG32); \
+       (gate).gd_s = SINIT(0);                                 \
+       (gate).gd_dpl = SINIT(dpl);                                     \
+       (gate).gd_p = SINIT(1);                                 \
+       (gate).gd_off_31_16 = SINIT((uint32_t) (off) >> 16);            \
+}
+
 // Set up a call gate descriptor.
 #define SETCALLGATE(gate, ss, off, dpl)                        \
 {                                                              \
@@ -341,7 +376,7 @@ typedef struct Pseudodesc {
        uint32_t pd_base;               // Base address
 } __attribute__ ((packed)) pseudodesc_t;
 
-extern segdesc_t (COUNT(SEG_COUNT) gdt)[];
+extern segdesc_t (COUNT(SEG_COUNT) RO gdt)[];
 extern pseudodesc_t gdt_pd;
 
 #endif /* !__ASSEMBLER__ */
index 518516c..4cc6a62 100644 (file)
@@ -3,10 +3,17 @@
  * See LICENSE for details.
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+// Not currently sharc complient. However
+// we should never be modifying these structures post smp_boot().
+
 #include <arch/ioapic.h>
 #include <arch/pci.h>
 #include <arch/mptables.h>
 
+#include <ros/common.h>
 #include <stdio.h>
 #include <string.h>
 #include <kmalloc.h>
@@ -539,4 +546,4 @@ void lint_parse() {
                mptables_dump("-->dst Apic INT: %p\n", mp_lint_entries[i].dst_apic_int);
                
        }
-}
\ No newline at end of file
+}
index 4fb7f0f..afee595 100644 (file)
@@ -6,7 +6,7 @@
 #ifndef ROS_INC_MPTABLES_H
 #define ROS_INC_MPTABLES_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 #include <pmap.h>
 
 /* 
index b204ada..911c30f 100644 (file)
@@ -1,7 +1,16 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
+
 #ifdef __DEPUTY__
 #pragma nodeputy
 #endif
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <arch/mmu.h>
 #include <arch/x86.h>
 #include <arch/smp.h>
 #include <pmap.h>
 #include <timing.h>
 
-/* NE2000 NIC Driver Sketch
+/** @file
+ * @brief NE2K Driver Sketch
+ *
+ * EXPERIMENTAL. DO NOT USE IF YOU DONT KNOW WHAT YOU ARE DOING
+ *
+ * This driver will attempt to detect a ne2k device and run some interrupt
+ * tests. This is used for ioapic debugging in simulation
  *
- * Written by Paul Pearce.
+ * @author Paul Pearce <pearce@eecs.berkeley.edu>
  *
+ * @todo Everything
  */
 
 extern uint32_t eth_up; // Fix this                               
index f64f1c7..8a4b9e5 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef ROS_INC_NE2K_H
 #define ROS_INC_NE2K_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 #include <trap.h>
 #include <pmap.h>
 
index 3e6d66f..abaf22c 100644 (file)
@@ -4,9 +4,9 @@
  * 
  * Kevin Klues <klueska@cs.berkeley.edu>    
  */
-#ifdef __DEPUTY__
-#pragma nodeputy
+
+#ifdef __SHARC__
+#pragma nosharc
 #endif
 
 #include <sys/queue.h>
 #include <pmap.h>
 #include <kmalloc.h>
 
-page_list_t page_free_list;    // Free list of physical pages
-DECLARE_CACHE_COLORED_PAGE_FREE_LISTS(); // Free list of pages filed by color
+// llc stands for last-level-cache
+uint16_t llc_num_colors;
+page_list_t *COUNT(llc_num_colors) colored_page_free_list = NULL;
+spinlock_t colored_page_free_list_lock;
+
+void page_alloc_bootstrap(cache_t* llc) {
+       // Initialize the properties of the last level cache used by this allocator
+       llc_num_colors = get_cache_num_page_colors(llc);
+
+       // Allocate space for the array required to manage the free lists
+       size_t list_size = llc_num_colors*sizeof(page_list_t);
+       colored_page_free_list = (page_list_t*) boot_alloc(list_size, PGSIZE);
+}
 
 /*
  * Initialize the memory free lists.
@@ -25,11 +36,21 @@ DECLARE_CACHE_COLORED_PAGE_FREE_LISTS(); // Free list of pages filed by color
  */
 void page_alloc_init() 
 {
-       // Now, initialize the lists required to manage the page free lists
-       LIST_INIT(&page_free_list);
-       INIT_CACHE_COLORED_PAGE_FREE_LISTS();
-       
-       //  Finally, mark the pages already in use by the kernel. 
+       cache_t* llc = available_caches.llc;
+
+       // First Bootstrap the page alloc process
+       static bool bootstrapped = FALSE;
+       if(!bootstrapped) {
+               bootstrapped = TRUE;
+               page_alloc_bootstrap(llc);
+       }
+
+       // Then, initialize the array required to manage the colored page free list
+       for(int i=0; i<llc_num_colors; i++) {
+               LIST_INIT(&(colored_page_free_list[i]));
+       }
+
+       //  Then, mark the pages already in use by the kernel. 
        //  1) Mark page 0 as in use.
        //     This way we preserve the real-mode IDT and BIOS structures
        //     in case we ever need them.  (Currently we don't, but...)
@@ -39,7 +60,8 @@ void page_alloc_init()
        //  4) Then extended memory [EXTPHYSMEM, ...).
        //     Some of it is in use, some is free.
        int i;
-       physaddr_t physaddr_after_kernel = PADDR(ROUNDUP(boot_freemem, PGSIZE));
+       extern char (SNT end)[];
+       physaddr_t physaddr_after_kernel = PADDR(PTRROUNDUP(boot_freemem, PGSIZE));
 
        pages[0].page_ref = 1;
        // alloc the second page, since we will need it later to init the other cores
@@ -47,8 +69,11 @@ void page_alloc_init()
        pages[1].page_ref = 1;
        for (i = 2; i < PPN(IOPHYSMEM); i++) {
                pages[i].page_ref = 0;
-               LIST_INSERT_HEAD(&page_free_list, &pages[i], global_link);
-               INSERT_CACHE_COLORING_PAGE_ONTO_FREE_LISTS(&pages[i]);
+               LIST_INSERT_HEAD(
+                  &(colored_page_free_list[get_page_color(page2ppn(&pages[i]), llc)]),
+                  &pages[i],
+                  page_link
+               );
        }
        for (i = PPN(IOPHYSMEM); i < PPN(EXTPHYSMEM); i++) {
                pages[i].page_ref = 1;
@@ -58,8 +83,11 @@ void page_alloc_init()
        }
        for (i = PPN(physaddr_after_kernel); i < PPN(maxaddrpa); i++) {
                pages[i].page_ref = 0;
-               LIST_INSERT_HEAD(&page_free_list, &pages[i], global_link);
-               INSERT_CACHE_COLORING_PAGE_ONTO_FREE_LISTS(&pages[i]);
+               LIST_INSERT_HEAD(
+                  &(colored_page_free_list[get_page_color(page2ppn(&pages[i]), llc)]),
+                  &pages[i],
+                  page_link
+               );
        }
        // this block out all memory above maxaddrpa.  will need another mechanism
        // to allocate and map these into the kernel address space
index c6767fc..7276444 100644 (file)
@@ -3,6 +3,11 @@
  * See LICENSE for details.
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+// Not currently sharc complient. 
+
 /** @file
  * @brief Basic PCI Driver.
  *
@@ -140,4 +145,4 @@ void pci_init() {
                                
                                pci_debug("\n");
                        }               
-}
\ No newline at end of file
+}
index d2db7f8..1539060 100644 (file)
@@ -1,3 +1,7 @@
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 /* See COPYRIGHT for copyright information. */
 #include <arch/x86.h>
 #include <arch/arch.h>
 
 // These variables are set in i386_vm_init()
 pde_t* boot_pgdir;             // Virtual address of boot time page directory
-physaddr_t boot_cr3;           // Physical address of boot time page directory
+physaddr_t RO boot_cr3;                // Physical address of boot time page directory
 
 // Global variables
+volatile uint32_t pages_lock = 0;
 page_t *pages = NULL;          // Virtual address of physical page array
 
 // Global descriptor table.
@@ -435,7 +440,6 @@ vm_init(void)
 // but it is a pretty good sanity check. 
 //
 static physaddr_t check_va2pa(pde_t *COUNT(NPDENTRIES) pgdir, uintptr_t va);
-static pte_t get_vaperms(pde_t *COUNT(NPDENTRIES) pgdir, uintptr_t va);
 
 static void
 check_boot_pgdir(bool pse)
@@ -481,13 +485,21 @@ check_boot_pgdir(bool pse)
                }
        }
 
-       // check permissions
-       // user read-only.  check for user and write, should be only user
-       // eagle-eyed viewers should be able to explain the extra cases
+       /* check permissions
+        * user read-only.  check for user and write, should be only user
+        * eagle-eyed viewers should be able to explain the extra cases.
+        * for the mongoose-eyed, remember that weird shit happens when you loop
+        * through UVPT.  Specifically, you can't loop once, then look at a jumbo
+        * page that is kernel only.  That's the end of the page table for you, so
+        * having a U on the entry doesn't make sense.  Thus we check for a jumbo
+        * page, and special case it.  This will happen at 0xbf701000.  Why is this
+        * magical?  Get your eagle glasses and figure it out. */
        for (i = UTOP; i < ULIM; i+=PGSIZE) {
-               pte = get_vaperms(pgdir, i);
-               if ((pte & PTE_P) && (i != UVPT+(VPT>>10))) {
-                       if (pte & PTE_PS) {
+               pte = get_va_perms(pgdir, (void*SAFE)TC(i));
+               if (pte & PTE_P) {
+                       if (i == UVPT+(VPT >> 10))
+                               continue;
+                       if (*pgdir_walk(pgdir, (void*SAFE)TC(i), 0) & PTE_PS) {
                                assert((pte & PTE_U) != PTE_U);
                                assert((pte & PTE_W) != PTE_W);
                        } else {
@@ -498,20 +510,20 @@ check_boot_pgdir(bool pse)
        }
        // kernel read-write.
        for (i = ULIM; i <= KERNBASE + maxaddrpa - PGSIZE; i+=PGSIZE) {
-               pte = get_vaperms(pgdir, i);
+               pte = get_va_perms(pgdir, (void*SAFE)TC(i));
                if ((pte & PTE_P) && (i != VPT+(UVPT>>10))) {
                        assert((pte & PTE_U) != PTE_U);
                        assert((pte & PTE_W) == PTE_W);
                }
        }
        // special mappings
-       pte = get_vaperms(pgdir, UVPT+(VPT>>10));
+       pte = get_va_perms(pgdir, (void*SAFE)TC(UVPT+(VPT>>10)));
        assert((pte & PTE_U) != PTE_U);
        assert((pte & PTE_W) != PTE_W);
 
        // note this means the kernel cannot directly manipulate this virtual address
        // convince yourself this isn't a big deal, eagle-eyes!
-       pte = get_vaperms(pgdir, VPT+(UVPT>>10));
+       pte = get_va_perms(pgdir, (void*SAFE)TC(VPT+(UVPT>>10)));
        assert((pte & PTE_U) != PTE_U);
        assert((pte & PTE_W) != PTE_W);
 
@@ -541,23 +553,6 @@ check_va2pa(pde_t *COUNT(NPDENTRIES) _pgdir, uintptr_t va)
 }
 
 /* 
- * This function returns a PTE with the aggregate permissions equivalent
- * to walking the two levels of paging.  PPN = 0.  Somewhat fragile, in that
- * it returns PTE_PS if either entry has PTE_PS (which should only happen
- * for some of the recusive walks)
- */
-
-static pte_t
-get_vaperms(pde_t *COUNT(NPDENTRIES) pgdir, uintptr_t va)
-{
-       pde_t* pde = &pgdir[PDX(va)];
-       pte_t* pte = pgdir_walk(pgdir, (void*SNT)va, 0);
-       if (!pte || !(*pte & PTE_P))
-               return 0;
-       return PGOFF(*pde & *pte) + PTE_PS & (*pde | *pte);
-}
-
-/* 
  * Remove the second level page table associated with virtual address va.
  * Will 0 out the PDE for that page table.
  * Panics if the page table has any present entries.
@@ -623,6 +618,54 @@ pgdir_walk(pde_t *pgdir, const void *SNT va, int create)
        return &((pde_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(*the_pde)))[PTX(va)];
 }
 
+/* Returns the effective permissions for PTE_U, PTE_W, and PTE_P on a given
+ * virtual address.  Note we need to consider the composition of every PTE in
+ * the page table walk. */
+int get_va_perms(pde_t *pgdir, const void *SNT va)
+{
+       pde_t the_pde = pgdir[PDX(va)];
+       pte_t the_pte;
+
+       if (!(the_pde & PTE_P))
+               return 0;
+       if (the_pde & PTE_PS)
+               return the_pde & (PTE_U | PTE_W | PTE_P);
+       the_pte = ((pde_t*COUNT(NPTENTRIES))KADDR(PTE_ADDR(the_pde)))[PTX(va)];
+       if (!(the_pte & PTE_P))
+               return 0;
+       return the_pte & the_pde & (PTE_U | PTE_W | PTE_P);
+}
+
+void *get_free_va_range(pde_t *pgdir, uintptr_t addr, size_t len)
+{
+{TRUSTEDBLOCK
+       // want to make sure there aren't mappings already.  will need to do this
+       // later with zones, for when we lazily allocate memory
+
+       uintptr_t startaddr;
+
+       int npages = ROUNDUP(len, PGSIZE) / PGSIZE;
+
+       addr &= ~0xfff;
+       if (!addr)
+               // some sensible default.  can cache the previous value somewhere
+               addr = USTACKTOP - PGSIZE; // TODO: not looking down
+       startaddr = addr;       
+       pte_t *pte = pgdir_walk(pgdir, (void*)addr, 0);
+       // what about jumbo pages?
+       // consider looping around, esp if we start from a cached spot
+       // don't map at pg 0, or below brk
+       // consider local memory ranges...
+
+       /*
+       first fit?
+       what if we have a sorted structure of what mem ranges are already in use?
+       */
+
+       return (void*)0xdeadbeef;
+}
+}
+
 /* Flushes a TLB, including global pages.  We should always have the CR4_PGE
  * flag set, but just in case, we'll check.  Toggling this bit flushes the TLB.
  */
@@ -640,7 +683,7 @@ void
 page_check(void)
 {
        page_t *pp, *pp0, *pp1, *pp2;
-       page_list_t fl;
+       page_list_t fl[1024];
        pte_t *ptep;
 
        // should be able to allocate three pages
@@ -654,8 +697,10 @@ page_check(void)
        assert(pp2 && pp2 != pp1 && pp2 != pp0);
 
        // temporarily steal the rest of the free pages
-       fl = page_free_list;
-       LIST_INIT(&page_free_list);
+       for(int i=0; i<llc_num_colors; i++) {
+               fl[i] = colored_page_free_list[i];
+               LIST_INIT(&colored_page_free_list[i]);
+       }
 
        // should be no free memory
        assert(page_alloc(&pp) == -ENOMEM);
@@ -771,7 +816,8 @@ page_check(void)
        }
 
        // give free list back
-       page_free_list = fl;
+       for(int i=0; i<llc_num_colors; i++)
+               colored_page_free_list[i] = fl[i];
 
        // free the pages we took
        page_free(pp0);
diff --git a/kern/arch/i386/process.c b/kern/arch/i386/process.c
new file mode 100644 (file)
index 0000000..ca63f82
--- /dev/null
@@ -0,0 +1,37 @@
+#include <arch/arch.h>
+#include <arch/trap.h>
+#include <process.h>
+#include <pmap.h>
+#include <smp.h>
+
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+
+void proc_set_program_counter(trapframe_t *tf, uintptr_t pc)
+{
+       tf->tf_eip = pc;
+}
+
+void proc_init_trapframe(trapframe_t *tf)
+{
+       /* Set up appropriate initial values for the segment registers.
+        * GD_UD is the user data segment selector in the GDT, and
+        * GD_UT is the user text segment selector (see inc/memlayout.h).
+        * The low 2 bits of each segment register contains the
+        * Requestor Privilege Level (RPL); 3 means user mode. */
+       tf->tf_ds = GD_UD | 3;
+       tf->tf_es = GD_UD | 3;
+       tf->tf_ss = GD_UD | 3;
+       tf->tf_esp = USTACKTOP;
+       tf->tf_cs = GD_UT | 3;
+       /* set the env's EFLAGSs to have interrupts enabled */
+       tf->tf_eflags |= 0x00000200; // bit 9 is the interrupts-enabled
+}
+
+/* Coupled closely with userland's entry.S.  id is the vcoreid, which entry.S
+ * uses to determine what to do.  vcoreid == 0 is the main core/context. */
+void proc_set_tfcoreid(trapframe_t *tf, uint32_t id)
+{
+       tf->tf_regs.reg_eax = id;
+}
index 69cd044..4ffc499 100644 (file)
@@ -1,3 +1,20 @@
+/** @file
+ * @brief NE2K Driver Sketch       
+ *
+ * EXPERIMENTAL. DO NOT USE IF YOU DONT KNOW WHAT YOU ARE DOING
+ *
+ * This driver will attempt to detect a ne2k device and run some interrupt
+ * tests. This is used for ioapic debugging in simulation
+ *
+ * @author Paul Pearce <pearce@eecs.berkeley.edu>
+ *
+ * @todo Everything                   
+ */
+
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #ifdef __DEPUTY__
 #pragma nodeputy
 #endif
 
 #include <pmap.h>
 
+/** @file
+ * @brief Realtek RL8168 Driver
+ *
+ * EXPERIMENTAL. DO NOT USE IF YOU DONT KNOW WHAT YOU ARE DOING
+ *
+ * This is a function rl8168 driver, that uses some really ugly hacks to achieve
+ * UDP communication with a remote syscall server, without a network stack.
+ *
+ * To enable use, define __NETWORK__ in your Makelocal
+ *
+ * @author Paul Pearce <pearce@eecs.berkeley.edu>
+ *
+ * @todo Move documention below into doxygen format.
+ * @todo See list in code
+ */
+
+
 /* RealTek 8168d (8111d) NIC Driver
  *
  * Written by Paul Pearce.
  * TODO: CONCURRENCY!
  */
 
+#ifndef USER_MAC_ADDRESS
+#define USER_MAC_ADDRESS {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+#endif
+
 struct Descriptor
 {
     unsigned int command,  /* command/status dword */
@@ -623,7 +661,7 @@ int rl8168_send_frame(const char *data, size_t len) {
 
 // This function is a complete hack for syscalls until we get a stack.
 // the day I delete this monstrosity of code I will be a happy man --Paul
-const char *rl8168_packet_wrap(const char* data, size_t len) {
+char *rl8168_packet_wrap(const char* data, size_t len) {
        
        #define htons(A) ((((uint16_t)(A) & 0xff00) >> 8) | \
                            (((uint16_t)(A) & 0x00ff) << 8))
index a0447ac..03b2365 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef ROS_INC_REALTEK_H
 #define ROS_INC_REALTEK_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 #include <trap.h>
 #include <pmap.h>
 
 #define MAX_PACKET_DATA                MAX_FRAME_SIZE - PACKET_HEADER_SIZE
 // This number needs verification! Also, this is a huge hack, as the driver shouldnt care about UDP/IP etc.
 
-const char *rl8168_packet_wrap(const char* data, size_t len);
+char *rl8168_packet_wrap(const char* data, size_t len);
 
 
 // ^----- Evil line ------^
index 508317b..aed6af9 100644 (file)
@@ -4,6 +4,10 @@
  * See LICENSE for details.
  */
 
+#ifdef __SHARC__
+//#pragma nosharc
+#endif
+
 #include <arch/arch.h>
 #include <smp.h>
 
 /*************************** IPI Wrapper Stuff ********************************/
 // checklists to protect the global interrupt_handlers for 0xf0, f1, f2, f3, f4
 // need to be global, since there is no function that will always exist for them
-handler_wrapper_t             handler_wrappers[NUM_HANDLER_WRAPPERS];
+handler_wrapper_t (RO handler_wrappers)[NUM_HANDLER_WRAPPERS];
 
-static int smp_call_function(uint8_t type, uint8_t dest, poly_isr_t handler, TV(t) data,
+static int smp_call_function(uint8_t type, uint32_t dest, poly_isr_t handler, TV(t) data,
                              handler_wrapper_t** wait_wrapper)
 {
-       extern handler_t interrupt_handlers[NUM_INTERRUPT_HANDLERS];
        int8_t state = 0;
        uint32_t wrapper_num;
        handler_wrapper_t* wrapper;
@@ -38,7 +41,7 @@ static int smp_call_function(uint8_t type, uint8_t dest, poly_isr_t handler, TV(
                atomic_dec(&outstanding_calls);
                return -EBUSY;
        }
-       
+
        // assumes our cores are numbered in order
        if ((type == 4) && (dest >= num_cpus))
                panic("Destination CPU does not exist!");
@@ -150,7 +153,7 @@ int smp_call_function_all(poly_isr_t handler, TV(t) data,
        return smp_call_function(2, 0, handler, data, wait_wrapper);
 }
 
-int smp_call_function_single(uint8_t dest, poly_isr_t handler, TV(t) data,
+int smp_call_function_single(uint32_t dest, poly_isr_t handler, TV(t) data,
                              handler_wrapper_t** wait_wrapper)
 {
        return smp_call_function(4, dest, handler, data, wait_wrapper);
index 3f33c6e..6a7194d 100644 (file)
 
 #define NUM_INTERRUPT_HANDLERS 256
 
-typedef struct HandlerWrapper {
+struct HandlerWrapper {
        checklist_t* cpu_list;
        uint8_t vector;
-} handler_wrapper_t;
+};
 
-#endif
+typedef struct HandlerWrapper LCKD(&cpu_list->lock) handler_wrapper_t;
+
+#endif /* !ROS_ARCH_SMP_H */
index dc94c7f..f5163be 100644 (file)
@@ -4,6 +4,10 @@
  * See LICENSE for details.
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <arch/x86.h>
 #include <arch/arch.h>
 #include <smp.h>
@@ -52,25 +56,32 @@ static void init_smp_call_function(void)
 
 /******************************************************************************/
 
+#ifdef __IVY__
 static void smp_mtrr_handler(trapframe_t *tf, barrier_t *data)
+#else
+static void smp_mtrr_handler(trapframe_t *tf, void *data)
+#endif
 {
        setup_default_mtrrs(data);
 }
 
 // this needs to be set in smp_entry too...
 #define trampoline_pg 0x00001000
-extern smp_entry(), smp_entry_end(), smp_boot_lock(), smp_semaphore();
+extern char (SNT SREADONLY smp_entry)[];
+extern char (SNT SREADONLY smp_entry_end)[];
+extern char (SNT SREADONLY smp_boot_lock)[];
+extern char (SNT SREADONLY smp_semaphore)[];
 
 static inline volatile uint32_t *COUNT(1)
 get_smp_semaphore()
 {
-       return (volatile uint32_t *COUNT(1))TC(&smp_semaphore - &smp_entry + trampoline_pg);
+       return (volatile uint32_t *COUNT(1))TC(smp_semaphore - smp_entry + trampoline_pg);
 }
 
 static inline uint32_t *COUNT(1)
 get_smp_bootlock()
 {
-       return (uint32_t *COUNT(1))TC(&smp_boot_lock - &smp_entry + trampoline_pg);
+       return (uint32_t *COUNT(1))TC(smp_boot_lock - smp_entry + trampoline_pg);
 }
 
 void smp_boot(void)
@@ -79,8 +90,8 @@ void smp_boot(void)
        // NEED TO GRAB A LOWMEM FREE PAGE FOR AP BOOTUP CODE
        // page1 (2nd page) is reserved, hardcoded in pmap.c
        memset(KADDR(trampoline_pg), 0, PGSIZE);
-       memcpy(KADDR(trampoline_pg), (void *COUNT(PGSIZE))TC(&smp_entry),
-           &smp_entry_end - &smp_entry);
+       memcpy(KADDR(trampoline_pg), (void *COUNT(PGSIZE))TC(smp_entry),
+           smp_entry_end - smp_entry);
 
        // This mapping allows access to the trampoline with paging on and off
        // via trampoline_pg
@@ -223,7 +234,8 @@ uint32_t smp_main(void)
        my_ts->ts_esp0 = my_stack_top;
        my_ts->ts_ss0 = GD_KD;
        // Initialize the TSS field of my_gdt.
-       my_gdt[GD_TSS >> 3] = SEG16(STS_T32A, (uint32_t) (my_ts), sizeof(taskstate_t), 0);
+       my_gdt[GD_TSS >> 3] = (segdesc_t)SEG16(STS_T32A, (uint32_t) (my_ts),
+                             sizeof(taskstate_t), 0);
        my_gdt[GD_TSS >> 3].sd_s = 0;
        // Load the TSS
        ltr(GD_TSS);
index 99cb0c3..899b479 100644 (file)
@@ -1,9 +1,13 @@
+#ifdef __SHARC__
+//#pragma nosharc
+#endif
 
 #include <arch/mmu.h>
 #include <arch/x86.h>
 #include <arch/arch.h>
 #include <arch/console.h>
 #include <arch/apic.h>
+#include <ros/common.h>
 #include <smp.h>
 #include <assert.h>
 #include <pmap.h>
 
 #include <syscall.h>
 
-taskstate_t ts;
+taskstate_t RO ts;
 
 /* Interrupt descriptor table.  (Must be built at run time because
  * shifted function addresses can't be represented in relocation records.)
  */
 // Aligned on an 8 byte boundary (SDM V3A 5-13)
-gatedesc_t __attribute__ ((aligned (8))) idt[256] = { { 0 } };
-pseudodesc_t idt_pd = {
+gatedesc_t __attribute__ ((aligned (8))) (RO idt)[256] = { { 0 } };
+pseudodesc_t RO idt_pd = {
        sizeof(idt) - 1, (uint32_t) idt
 };
 
@@ -29,12 +33,16 @@ pseudodesc_t idt_pd = {
  * of functions to be called when servicing an interrupt.  other cores
  * can set up their own later.
  */
-handler_t TP(void *) interrupt_handlers[NUM_INTERRUPT_HANDLERS];
+#ifdef __IVY__
+#pragma cilnoremove("iht_lock")
+#endif
+spinlock_t iht_lock;
+handler_t TP(TV(t)) LCKD(&iht_lock) (RO interrupt_handlers)[NUM_INTERRUPT_HANDLERS];
 
-static const char *NTS (IN_HANDLER trapname)(int trapno)
+static const char *NTS trapname(int trapno)
 {
-    // zra: excnames is NORACE because Ivy doesn't trust const
-       static const char *NT const (NORACE excnames)[] = {
+    // zra: excnames is SREADONLY because Ivy doesn't trust const
+       static const char *NT const (RO excnames)[] = {
                "Divide error",
                "Debug",
                "Non-Maskable Interrupt",
@@ -68,20 +76,20 @@ static const char *NTS (IN_HANDLER trapname)(int trapno)
 void
 idt_init(void)
 {
-       extern segdesc_t gdt[];
+       extern segdesc_t (RO gdt)[];
 
        // This table is made in trapentry.S by each macro in that file.
        // It is layed out such that the ith entry is the ith's traphandler's
        // (uint32_t) trap addr, then (uint32_t) trap number
        struct trapinfo { uint32_t trapaddr; uint32_t trapnumber; };
-       extern struct trapinfo (BND(__this,trap_tbl_end) trap_tbl)[];
-       extern struct trapinfo (SNT trap_tbl_end)[];
+       extern struct trapinfo (BND(__this,trap_tbl_end) RO trap_tbl)[];
+       extern struct trapinfo (SNT RO trap_tbl_end)[];
        int i, trap_tbl_size = trap_tbl_end - trap_tbl;
        extern void ISR_default(void);
 
        // set all to default, to catch everything
        for(i = 0; i < 256; i++)
-               SETGATE(idt[i], 0, GD_KT, &ISR_default, 0);
+               ROSETGATE(idt[i], 0, GD_KT, &ISR_default, 0);
 
        // set all entries that have real trap handlers
        // we need to stop short of the last one, since the last is the default
@@ -90,24 +98,25 @@ idt_init(void)
        // if we set these to trap gates, be sure to handle the IRQs separately
        // and we might need to break our pretty tables
        for(i = 0; i < trap_tbl_size - 1; i++)
-               SETGATE(idt[trap_tbl[i].trapnumber], 0, GD_KT, trap_tbl[i].trapaddr, 0);
+               ROSETGATE(idt[trap_tbl[i].trapnumber], 0, GD_KT, trap_tbl[i].trapaddr, 0);
 
        // turn on syscall handling and other user-accessible ints
        // DPL 3 means this can be triggered by the int instruction
        // STS_TG32 sets the IDT type to a Trap Gate (interrupts enabled)
-       idt[T_SYSCALL].gd_dpl = 3;
-       idt[T_SYSCALL].gd_type = STS_TG32;
-       idt[T_BRKPT].gd_dpl = 3;
+       idt[T_SYSCALL].gd_dpl = SINIT(3);
+       idt[T_SYSCALL].gd_type = SINIT(STS_TG32);
+       idt[T_BRKPT].gd_dpl = SINIT(3);
 
        // Setup a TSS so that we get the right stack
        // when we trap to the kernel.
-       ts.ts_esp0 = KSTACKTOP;
-       ts.ts_ss0 = GD_KD;
+       ts.ts_esp0 = SINIT(KSTACKTOP);
+       ts.ts_ss0 = SINIT(GD_KD);
 
        // Initialize the TSS field of the gdt.
-       gdt[GD_TSS >> 3] = SEG16(STS_T32A, (uint32_t) (&ts),
-                                       sizeof(taskstate_t), 0);
-       gdt[GD_TSS >> 3].sd_s = 0;
+       SEG16ROINIT(gdt[GD_TSS >> 3],STS_T32A, (uint32_t)(&ts),sizeof(taskstate_t),0);
+       //gdt[GD_TSS >> 3] = (segdesc_t)SEG16(STS_T32A, (uint32_t) (&ts),
+       //                                 sizeof(taskstate_t), 0);
+       gdt[GD_TSS >> 3].sd_s = SINIT(0);
 
        // Load the TSS
        ltr(GD_TSS);
@@ -126,7 +135,7 @@ idt_init(void)
 }
 
 void
-(IN_HANDLER print_regs)(push_regs_t *regs)
+print_regs(push_regs_t *regs)
 {
        cprintf("  edi  0x%08x\n", regs->reg_edi);
        cprintf("  esi  0x%08x\n", regs->reg_esi);
@@ -139,7 +148,7 @@ void
 }
 
 void
-(IN_HANDLER print_trapframe)(trapframe_t *tf)
+print_trapframe(trapframe_t *tf)
 {
        cprintf("TRAP frame at %p on core %d\n", tf, core_id());
        print_regs(&tf->tf_regs);
@@ -155,7 +164,7 @@ void
 }
 
 static void
-(IN_HANDLER trap_dispatch)(trapframe_t *tf)
+trap_dispatch(trapframe_t *tf)
 {
        // Handle processor exceptions.
        switch(tf->tf_trapno) {
@@ -191,24 +200,24 @@ static void
 }
 
 void
-(IN_HANDLER env_push_ancillary_state)(env_t* e)
+env_push_ancillary_state(env_t* e)
 {
        // Here's where you'll save FP/MMX/XMM regs
 }
 
 void
-(IN_HANDLER env_pop_ancillary_state)(env_t* e)
+env_pop_ancillary_state(env_t* e)
 {
        // Here's where you'll restore FP/MMX/XMM regs
 }
 
 void
-(IN_HANDLER trap)(trapframe_t *tf)
+trap(trapframe_t *tf)
 {
        //cprintf("Incoming TRAP frame at %p\n", tf);
 
        // TODO: do this once we know we are are not returning to the current
-       // context.  doing it now is safe.
+       // context.  doing it now is safe. (HSS)
        env_push_ancillary_state(current);
 
        if ((tf->tf_cs & ~3) != GD_UT && (tf->tf_cs & ~3) != GD_KT) {
@@ -239,21 +248,25 @@ void
 }
 
 void
-(IN_HANDLER irq_handler)(trapframe_t *tf)
+irq_handler(trapframe_t *tf)
 {
        //if (core_id())
        //      cprintf("Incoming IRQ, ISR: %d on core %d\n", tf->tf_trapno, core_id());
        // merge this with alltraps?  other than the EOI... or do the same in all traps
 
-       extern handler_wrapper_t handler_wrappers[NUM_HANDLER_WRAPPERS];
+       // TODO: do this once we know we are are not returning to the current
+       // context.  doing it now is safe. (HSS)
+       env_push_ancillary_state(current);
+
+       extern handler_wrapper_t (RO handler_wrappers)[NUM_HANDLER_WRAPPERS];
 
        // determine the interrupt handler table to use.  for now, pick the global
-       handler_t TP(void *) * handler_tbl = interrupt_handlers;
+       handler_t TP(TV(t)) LCKD(&iht_lock) * handler_tbl = interrupt_handlers;
 
        if (handler_tbl[tf->tf_trapno].isr != 0)
                handler_tbl[tf->tf_trapno].isr(tf, handler_tbl[tf->tf_trapno].data);
        // if we're a general purpose IPI function call, down the cpu_list
-       if ((0xf0 <= tf->tf_trapno) && (tf->tf_trapno < 0xf0 +NUM_HANDLER_WRAPPERS))
+       if ((I_SMP_CALL0 <= tf->tf_trapno) && (tf->tf_trapno <= I_SMP_CALL_LAST))
                down_checklist(handler_wrappers[tf->tf_trapno & 0x0f].cpu_list);
 
        // Send EOI.  might want to do this in assembly, and possibly earlier
@@ -276,8 +289,8 @@ void
 }
 
 void
-register_interrupt_handler(handler_t TP(TV(t)) table[], uint8_t int_num, poly_isr_t handler,
-                           void* data)
+register_interrupt_handler(handler_t TP(TV(t)) table[],
+                           uint8_t int_num, poly_isr_t handler, TV(t) data)
 {
        table[int_num].isr = handler;
        table[int_num].data = data;
@@ -347,7 +360,7 @@ void sysenter_init(void)
 void sysenter_callwrapper(struct Trapframe *tf)
 {
        current->env_tf = *tf;
-       
+
        // The trapframe on the stack should be ignored from here on.
        tf = &current->env_tf;
        tf->tf_regs.reg_eax = (intreg_t) syscall(current,
@@ -365,3 +378,68 @@ void sysenter_callwrapper(struct Trapframe *tf)
         */
        proc_startcore(current, tf);
 }
+
+uint32_t send_active_message(uint32_t dst, amr_t pc,
+                             TV(a0t) arg0, TV(a1t) arg1, TV(a2t) arg2)
+{
+       error_t retval = -EBUSY;
+       spin_lock_irqsave(&per_cpu_info[dst].amsg_lock);
+       size_t current_amsg = per_cpu_info[dst].amsg_current;
+       // If there's a PC there, then that means it's an outstanding message
+       FOR_CIRC_BUFFER(current_amsg, NUM_ACTIVE_MESSAGES, i) {
+               if (per_cpu_info[dst].active_msgs[i].pc)
+                       continue;
+               per_cpu_info[dst].active_msgs[i].pc = pc;
+               per_cpu_info[dst].active_msgs[i].arg0 = arg0;
+               per_cpu_info[dst].active_msgs[i].arg1 = arg1;
+               per_cpu_info[dst].active_msgs[i].arg2 = arg2;
+               per_cpu_info[dst].active_msgs[i].srcid = core_id();
+               retval = 0;
+               break;
+       }
+       spin_unlock_irqsave(&per_cpu_info[dst].amsg_lock);
+       // since we touched memory the other core will touch (the lock), we don't
+       // need an wmb_f()
+       if (!retval)
+               send_ipi(dst, 0, I_ACTIVE_MSG);
+       return retval;
+}
+
+/* Active message handler.  We don't want to block other AMs from coming in, so
+ * we'll copy out the message and let go of the lock.  This won't return until
+ * all pending AMs are executed.  If the PC is 0, then this was an extra IPI and
+ * we already handled the message (or someone is sending IPIs without loading
+ * the active message...)
+ * Note that all of this happens from interrupt context, and interrupts are
+ * currently disabled for this gate. */
+void __active_message(trapframe_t *tf)
+{
+       per_cpu_info_t RO*myinfo = &per_cpu_info[core_id()];
+       active_message_t amsg;
+
+       lapic_send_eoi();
+       while (1) { // will break out when we find an empty amsg
+               /* Get the message */
+               spin_lock_irqsave(&myinfo->amsg_lock);
+               if (myinfo->active_msgs[myinfo->amsg_current].pc) {
+                       amsg = myinfo->active_msgs[myinfo->amsg_current];
+                       myinfo->active_msgs[myinfo->amsg_current].pc = 0;
+                       myinfo->amsg_current = (myinfo->amsg_current + 1) %
+                                              NUM_ACTIVE_MESSAGES;
+               } else { // was no PC in the current active message, meaning we do nothing
+                       spin_unlock_irqsave(&myinfo->amsg_lock);
+                       return;
+               }
+               /* In case the function doesn't return (which is common: __startcore,
+                * __death, etc), there is a chance we could lose an amsg.  We can only
+                * have up to two interrupts outstanding, and if we never return, we
+                * never deal with any other amsgs.  This extra IPI hurts performance
+                * but is only necessary if there is another outstanding message in the
+                * buffer, but makes sure we never miss out on an amsg. */
+               if (myinfo->active_msgs[myinfo->amsg_current].pc)
+                       send_ipi(core_id(), 0, I_ACTIVE_MSG);
+               spin_unlock_irqsave(&myinfo->amsg_lock);
+               /* Execute the active message */
+               amsg.pc(tf, amsg.srcid, amsg.arg0, amsg.arg1, amsg.arg2);
+       }
+}
index 00767cb..049172f 100644 (file)
 #define T_SYSCALL   0x80                       // system call
 #define T_DEFAULT   0xdeadbeef         // catchall
 
+/* IPIs */
+/* Testing IPI (used in testing.c) */
+#define I_TESTING              230
+/* smp_call_function IPIs, keep in sync with NUM_HANDLER_WRAPPERS (and < 16)
+ * it's important that this begins with 0xf0.  check i386/trap.c for details. */
+#define I_SMP_CALL0    0xf0 // 240
+#define I_SMP_CALL1    0xf1
+#define I_SMP_CALL2    0xf2
+#define I_SMP_CALL3    0xf3
+#define I_SMP_CALL4    0xf4
+#define I_SMP_CALL_LAST I_SMP_CALL4
+/* Direct/Hardwired IPIs.  Hardwired in trapentry.S */
+#define I_ACTIVE_MSG   255
+
+/* Number of active messages available per core (arbitrary) */
+#define NUM_ACTIVE_MESSAGES 5
+
+
 #ifndef __ASSEMBLER__
 
-#include <arch/types.h>
+#include <ros/common.h>
 #include <arch/mmu.h>
 
 /* The kernel's interrupt descriptor table */
index 3087851..2cac166 100644 (file)
@@ -1,11 +1,14 @@
-/* See COPYRIGHT for copyright information. */
-
+/* See COPYRIGHT for copyright information.
+ * The two TRAP* macros (minus the .data parts) are from the JOS project.
+ * Everything else:
+ * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ */
 #include <arch/mmu.h>
 #include <arch/trap.h>
 #include <ros/memlayout.h>
 
-
-
 ###################################################################
 # exceptions/interrupts
 ###################################################################
@@ -14,7 +17,7 @@
  * a trap.  It pushes a trap number onto the stack, then jumps to _alltraps.
  * It also builds this traps portion of the trap_tbl.
  * Use TRAPHANDLER for traps where the CPU automatically pushes an error code.
- */ 
+ */
 #define TRAPHANDLER(name, num)                                                                 \
        .text;                                                                                                          \
        .globl name;            /* define global symbol for 'name' */   \
        .long name;                                                     \
        .long num
 
+/* Same as above, but takes a specific function to jump to.  See comments
+ * below from _allirqs for details.
+ */
+#define IRQ_HANDLER_SPEC(name, num, func)                                      \
+       .text;                                                                                                 \
+       .globl name;                                                                                   \
+       .type name, @function;                                                                 \
+       .align 2;                                                                                              \
+       name:                                                                                                  \
+       pushl $0;                                                                  \
+       pushl $(num);                                                              \
+       cld;                                                                       \
+       pushl %ds;                                                                 \
+       pushl %es;                                                                 \
+       pushal;                                                                    \
+       movw $GD_KD, %ax;                                                          \
+       movw %ax, %ds;                                                             \
+       movw %ax, %es;                                                             \
+       pushl %esp;                                                                \
+       movl $0, %ebp;                                                             \
+       call (func);                                                               \
+       popl %esp;                                                                 \
+       popal;                                                                     \
+       popl %es;                                                                  \
+       popl %ds;                                                                  \
+       addl $0x8, %esp;                                                           \
+       iret;                                                                      \
+       .data;                                                                     \
+       .long name;                                                                \
+       .long num
+
 .data
 .globl trap_tbl
 trap_tbl:
 
 /*
- * Lab 3: Your code here for generating entry points for the different traps.
+ * Generate entry points for the different traps.
  */
 TRAPHANDLER_NOEC(ISR_divide_error, T_DIVIDE)
 TRAPHANDLER_NOEC(ISR_debug_exceptions, T_DEBUG)
@@ -106,17 +140,23 @@ IRQ_HANDLER(IRQ12, 44)
 IRQ_HANDLER(IRQ13, 45)
 IRQ_HANDLER(IRQ14, 46)
 IRQ_HANDLER(IRQ15, 47)
-/* 20 general purpose vectors, for use by the LAPIC.  Can expand later. */
+/* 25 general purpose vectors, for use by the LAPIC.  Can expand later. */
+IRQ_HANDLER(IRQ198, I_TESTING) # used in testing.c
+IRQ_HANDLER(IRQ199, 231)
+IRQ_HANDLER(IRQ200, 232)
+IRQ_HANDLER(IRQ201, 233)
+IRQ_HANDLER(IRQ202, 234)
 IRQ_HANDLER(IRQ203, 235)
 IRQ_HANDLER(IRQ204, 236)
 IRQ_HANDLER(IRQ205, 237)
 IRQ_HANDLER(IRQ206, 238)
 IRQ_HANDLER(IRQ207, 239)
-IRQ_HANDLER(IRQ208, 240)
-IRQ_HANDLER(IRQ209, 241)
-IRQ_HANDLER(IRQ210, 242)
-IRQ_HANDLER(IRQ211, 243)
-IRQ_HANDLER(IRQ212, 244)
+/* 0xf0 - start of the SMP_CALL IPIS */
+IRQ_HANDLER(IRQ208, I_SMP_CALL0)
+IRQ_HANDLER(IRQ209, I_SMP_CALL1)
+IRQ_HANDLER(IRQ210, I_SMP_CALL2)
+IRQ_HANDLER(IRQ211, I_SMP_CALL3)
+IRQ_HANDLER(IRQ212, I_SMP_CALL4)
 IRQ_HANDLER(IRQ213, 245)
 IRQ_HANDLER(IRQ214, 246)
 IRQ_HANDLER(IRQ215, 247)
@@ -127,10 +167,11 @@ IRQ_HANDLER(IRQ219, 251)
 IRQ_HANDLER(IRQ220, 252)
 IRQ_HANDLER(IRQ221, 253)
 IRQ_HANDLER(IRQ222, 254)
-IRQ_HANDLER(IRQ223, 255)
+IRQ_HANDLER_SPEC(IRQ223, I_ACTIVE_MSG, __active_message)
 
+/* Technically, these HANDLER entries do not need to be in numeric order */
 TRAPHANDLER_NOEC(ISR_syscall, T_SYSCALL)
-/* Make sure default is last!! */
+/* But make sure default is last!! */
 TRAPHANDLER_NOEC(ISR_default, T_DEFAULT)
 
 .data
@@ -160,7 +201,7 @@ _alltraps:
        iret
 
 /* will need to think about when we reenable interrupts.  right now, iret does it,
- * if the previous EFLAGS had interrupts enabled 
+ * if the previous EFLAGS had interrupts enabled
  */
 _allirqs:
        cld
@@ -186,7 +227,7 @@ sysenter_handler:
        sti                                             # enable interrupts (things are sane here)
        cld
        pushfl                                  # save the eflags
-       pushl $0                                # these zeros keep the trapframe looking the same 
+       pushl $0                                # these zeros keep the trapframe looking the same
        pushl $0                                # as when we receive a trap or interrupt
        pushl $0                                # and CS == 0 lets the kernel know it was a sysenter
        pushl $T_SYSCALL                # helps with print_trapframe
index 28bc462..dc8ea85 100644 (file)
@@ -1,24 +1,11 @@
 #ifndef ROS_INC_TYPES_H
 #define ROS_INC_TYPES_H
 
-#define LITTLE_ENDIAN
-
-#ifndef NULL
-#define NULL ((void*) 0)
-#endif
-
-#ifndef TRUE
-#define TRUE   1
-#endif
+#include <stddef.h>
 
-#ifndef FALSE
-#define FALSE  0
-#endif
-
-#define CHECK_FLAG(flags,bit)   ((flags) & (1 << (bit)))
+#define LITTLE_ENDIAN
 
 // Represents true-or-false values
-typedef int bool;
 
 #define NUM_ADDR_BITS 32
 #define MAX_VADDR     ((uint64_t)(~0) >> (64-NUM_ADDR_BITS))
@@ -38,144 +25,14 @@ typedef unsigned int uint32_t;
 typedef long long int64_t;
 typedef unsigned long long uint64_t;
 
+typedef long ssize_t;
+typedef int pid_t;
+
 // Pointers and addresses are 32 bits long.
 // We use pointer types to represent virtual addresses,
 // uintptr_t to represent the numerical values of virtual addresses,
 // and physaddr_t to represent physical addresses.
 typedef int32_t intptr_t;
 typedef uint32_t uintptr_t;
-typedef uint32_t physaddr_t;
-
-// Registers are 32 bits long
-typedef int32_t intreg_t;
-typedef uint32_t uintreg_t;
-
-// Page numbers are 32 bits long.
-typedef uint32_t ppn_t;
-
-// size_t is used for memory object sizes.
-typedef uint32_t size_t;
-// ssize_t is a signed version of ssize_t, used in case there might be an
-// error return.
-typedef int32_t ssize_t;
-
-// off_t is used for file offsets and lengths.
-typedef int32_t off_t;
-
-// Efficient min and max operations
-#define MIN(_a, _b)                                            \
-({                                                             \
-       typeof(_a) __a = (_a);                                  \
-       typeof(_b) __b = (_b);                                  \
-       __a <= __b ? __a : __b;                                 \
-})
-#define MAX(_a, _b)                                            \
-({                                                             \
-       typeof(_a) __a = (_a);                                  \
-       typeof(_b) __b = (_b);                                  \
-       __a >= __b ? __a : __b;                                 \
-})
-
-// Rounding operations (efficient when n is a power of 2)
-// Round down to the nearest multiple of n
-#define ROUNDDOWN(a, n)                                                \
-({                                                             \
-       uint32_t __a = (uint32_t) (a);                          \
-       (typeof(a)) (__a - __a % (n));                          \
-})
-// Round up to the nearest multiple of n
-#define ROUNDUP(a, n)                                          \
-({                                                             \
-       uint32_t __n = (uint32_t) (n);                          \
-       (typeof(a)) (ROUNDDOWN((uint32_t) (a) + __n - 1, __n)); \
-})
-
-// Round down to the nearest multiple of n
-#define PTRROUNDDOWN(a, n)                                             \
-({                                                             \
-       char * __a = (char *) (a);                              \
-       (typeof(a)) (__a - (uint32_t)__a % (n));                                \
-})
-// Round pointer up to the nearest multiple of n
-#define PTRROUNDUP(a, n)                                               \
-({                                                             \
-       uint32_t __n = (uint32_t) (n);                          \
-       (typeof(a)) (PTRROUNDDOWN((char *) (a) + __n - 1, __n));        \
-})
-
-// Return the integer logarithm of the value provided rounded up
-static inline uint32_t LOG2(uint32_t value)
-{
-    uint32_t l = 0;
-    while( (value >> l) > 1 ) ++l;
-    return l;
-}
-
-// Return the offset of 'member' relative to the beginning of a struct type
-#ifndef offsetof
-#define offsetof(type, member)  ((size_t) (&((type*)0)->member))
-#endif
-
-// Ivy currently can only handle 63 bits (OCaml thing), so use this to make
-// a uint64_t programatically
-#define UINT64(upper, lower) ( (((uint64_t)(upper)) << 32) | (lower) )
-
-/*********************** Bitmask stuff **********************/
-#define BYTES_FOR_BITMASK(size) (((size) - 1) / 8 + 1)
-#define BYTES_FOR_BITMASK_WITH_CHECK(size) ((size) ? ((size) - (1)) / (8) + (1) : (0))
-#define DECL_BITMASK(name, size) uint8_t (name)[BYTES_FOR_BITMASK((size))]
-
-#define GET_BITMASK_BIT(name, bit) (((name)[(bit)/8] & (1 << ((bit) % 8))) ? 1 : 0)
-#define SET_BITMASK_BIT(name, bit) ((name)[(bit)/8] |= (1 << ((bit) % 8)))
-#define CLR_BITMASK_BIT(name, bit) ((name)[(bit)/8] &= ~(1 << ((bit) % 8)))
-#define SET_BITMASK_BIT_ATOMIC(name, bit) (atomic_orb(&(name)[(bit)/8], (1 << ((bit) % 8))))
-#define CLR_BITMASK_BIT_ATOMIC(name, bit) (atomic_andb(&(name)[(bit)/8], ~(1 << ((bit) % 8))))
-
-#define CLR_BITMASK(name, size) \
-({ \
-       {TRUSTEDBLOCK \
-       memset((void*)((uintptr_t)(name)), 0, BYTES_FOR_BITMASK((size))); \
-       } \
-})
-
-#define FILL_BITMASK(name, size) \
-({ \
-       {TRUSTEDBLOCK \
-       memset((void*)((uintptr_t)(name)), 255, BYTES_FOR_BITMASK((size))); \
-       } \
-       (name)[BYTES_FOR_BITMASK((size))-1] >>= (((size) % 8) ? (8 - ((size) % 8)) : 0 ); \
-}) 
-
-#define COPY_BITMASK(newmask, oldmask, size) \
-({ \
-       {TRUSTEDBLOCK \
-       memcpy((void*)((uintptr_t)(newmask)), \
-           (void*)((uintptr_t)(oldmask)), \
-           BYTES_FOR_BITMASK((size))); \
-       } \
-})
-
-// this checks the entire last byte, so keep it 0 in the other macros
-#define BITMASK_IS_CLEAR(name, size) ({ \
-       uint32_t __n = BYTES_FOR_BITMASK((size)); \
-       bool clear = 1; \
-       while (__n-- > 0) { \
-               if ((name)[__n]) { \
-                       clear = 0; \
-                       break;\
-               }\
-       } \
-       clear; })
-
-#define PRINT_BITMASK(name, size) { \
-       int i;  \
-       for (i = 0; i < BYTES_FOR_BITMASK(size); i++) { \
-               int j;  \
-               for (j = 0; j < 8; j++) \
-                       printk("%x", ((name)[i] >> j) & 1);     \
-       } \
-       printk("\n"); \
-}
-/**************************************************************/
 
 #endif /* !ROS_INC_TYPES_H */
index ac192b2..82a70eb 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef ROS_INC_X86_H
 #define ROS_INC_X86_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 #include <arch/mmu.h>
 
 /* Model Specific Registers */
@@ -66,6 +66,7 @@ static __inline void write_msr(uint32_t reg, uint64_t val) __attribute__((always
 static __inline uint32_t read_mmreg32(uint32_t reg) __attribute__((always_inline));
 static __inline void write_mmreg32(uint32_t reg, uint32_t val) __attribute__((always_inline));
 static __inline void wbinvd(void) __attribute__((always_inline));
+static __inline void __cpu_relax(void) __attribute__((always_inline));
 
 static __inline uint8_t
 inb(int port)
@@ -310,9 +311,19 @@ read_mmreg32(uint32_t reg)
 }
 
 static __inline void
-wbinvd(void) __attribute__((always_inline))
+wbinvd(void)
 {
        asm volatile("wbinvd");
 }
 
+/* this version of cpu_relax is needed to resolve some circular dependencies
+ * with arch/arch.h and arch/apic.h */
+static __inline void
+__cpu_relax(void)
+{
+       // in case the compiler doesn't serialize for pause, the "m" will make sure
+       // no memory is reordered around this instruction.
+       asm volatile("pause" : : : "memory");
+}
+
 #endif /* !ROS_INC_X86_H */
index fb8275c..73d370f 100644 (file)
@@ -6,6 +6,9 @@
 #define mb() {rmb(); wmb();}
 #define rmb()
 #define wmb() ({ asm volatile("stbar"); })
+/* Force a wmb, used in cases where an IPI could beat a write, even though
+ * write-orderings are respected.  (Used by x86) */
+#define wmb_f() wmb()
 
 typedef volatile uint32_t spinlock_t;
 
index 61f0258..ea397fc 100644 (file)
@@ -1,7 +1,7 @@
 #include <multiboot.h>
 #include <arch/mmu.h>
 #include <arch/arch.h>
-#include <arch/types.h>
+#include <ros/common.h>
 #include <ros/memlayout.h>
 #include <string.h>
 
index ba7a01d..679c4e2 100644 (file)
@@ -18,9 +18,8 @@ void cache_init()
        // TODO: Should call out to something reading the acpi tables from 
        // memory, or something similar.  For now, just initialize them inline
        init_cache_properties(&l1,   32,  8, 64);
-       init_cache_properties(&l2,  256,  8, 64);
-       init_cache_properties(&l3, 8192, 16, 64);
        available_caches.l1 = TRUE;
        available_caches.l2 = FALSE;
        available_caches.l3 = FALSE;
+       available_caches.llc = &l1;
 }
index 856f146..c12e8fc 100644 (file)
@@ -6,7 +6,7 @@
 # error "This is a ROS kernel header; user programs should not #include it"
 #endif
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 #define CRT_ROWS       25
 #define CRT_COLS       80
index c98510f..905e786 100644 (file)
@@ -10,7 +10,7 @@
 #include <pmap.h>
 
 void
-(IN_HANDLER env_push_ancillary_state)(env_t* e)
+( env_push_ancillary_state)(env_t* e)
 {
        static_assert(offsetof(ancillary_state_t,fpr) % 8 == 0);
 
@@ -46,7 +46,7 @@ void
 }
 
 void
-(IN_HANDLER env_pop_ancillary_state)(env_t* e)
+( env_pop_ancillary_state)(env_t* e)
 { 
 
        #define pop_two_fp_regs(pdest,n) \
@@ -81,21 +81,21 @@ void
 }
 
 void
-env_set_program_counter(env_t* e, uintptr_t pc)
+proc_set_program_counter(trapframe_t *tf, uintptr_t pc)
 {
-       e->env_tf.pc = pc;
-       e->env_tf.npc = pc+4;
+       tf->pc = pc;
+       tf->npc = pc+4;
 }
 
 void
-env_init_trapframe(env_t* e)
+proc_init_trapframe(trapframe_t *tf)
 {
        extern char trap_table;
 
-       e->env_tf.gpr[14] = USTACKTOP-64;
-       e->env_tf.psr = PSR_S; // but PS = 0
-       e->env_tf.wim = 0;
-       e->env_tf.tbr = (uint32_t)&trap_table;
+       tf->gpr[14] = USTACKTOP-64;
+       tf->psr = PSR_S; // but PS = 0
+       tf->wim = 0;
+       tf->tbr = (uint32_t)&trap_table;
 }
 
 // Flush all mapped pages in the user portion of the address space
diff --git a/kern/arch/sparc/env.c.save b/kern/arch/sparc/env.c.save
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/kern/arch/sparc/env.c.save.1 b/kern/arch/sparc/env.c.save.1
deleted file mode 100644 (file)
index 62228f1..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/* See COPYRIGHT for copyright information. */
-#ifdef __DEPUTY__
-#pragma noasync
-#endif
-
-#include <arch/trap.h>
-#include <env.h>
-#include <assert.h>
-#include <arch/arch.h>
-#include <pmap.h>
-
-void
-(IN_HANDLER env_push_ancillary_state)(env_t* e)
-{
-       static_assert(offsetof(ancillary_state_t,fpr) % 8 == 0);
-
-       #define push_two_fp_regs(pdest,n) \
-           __asm__ __volatile__ ("std  %%f" XSTR(n) ",[%0+4*" XSTR(n) "]" \
-                             : : "r"(pdest) : "memory");
-
-       // do I need to save FP regs?
-       if(e->env_tf.psr & PSR_EF)
-       {
-               // temporarily turn on FP in the kernel
-               write_psr(read_psr() | PSR_EF);
-
-               e->env_ancillary_state.fsr = read_fsr();
-
-               push_two_fp_regs(e->env_ancillary_state.fpr,0);
-               push_two_fp_regs(e->env_ancillary_state.fpr,2);
-               push_two_fp_regs(e->env_ancillary_state.fpr,4);
-               push_two_fp_regs(e->env_ancillary_state.fpr,6);
-               push_two_fp_regs(e->env_ancillary_state.fpr,8);
-               push_two_fp_regs(e->env_ancillary_state.fpr,10);
-               push_two_fp_regs(e->env_ancillary_state.fpr,12);
-               push_two_fp_regs(e->env_ancillary_state.fpr,14);
-               push_two_fp_regs(e->env_ancillary_state.fpr,16);
-               push_two_fp_regs(e->env_ancillary_state.fpr,18);
-               push_two_fp_regs(e->env_ancillary_state.fpr,20);
-               push_two_fp_regs(e->env_ancillary_state.fpr,22);
-               push_two_fp_regs(e->env_ancillary_state.fpr,24);
-               push_two_fp_regs(e->env_ancillary_state.fpr,26);
-               push_two_fp_regs(e->env_ancillary_state.fpr,28);
-               push_two_fp_regs(e->env_ancillary_state.fpr,30);
-
-               write_psr(read_psr() & ~PSR_EF);
-       }
-}
-
-void
-(IN_HANDLER env_pop_ancillary_state)(env_t* e)
-{ 
-
-       #define pop_two_fp_regs(pdest,n) \
-           __asm__ __volatile__ ("ldd  [%0+4*" XSTR(n) "], %%f" XSTR(n) \
-                             : : "r"(pdest) : "memory");
-
-       if(e->env_tf.psr & PSR_EF)
-       {
-               write_psr(read_psr() | PSR_EF);
-
-               pop_two_fp_regs(e->env_ancillary_state.fpr,0);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,2);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,4);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,6);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,8);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,10);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,12);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,14);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,16);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,18);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,20);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,22);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,24);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,26);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,28);
-               pop_two_fp_regs(e->env_ancillary_state.fpr,30);
-
-               write_fsr(e->env_ancillary_state.fsr);
-
-               write_psr(read_psr() & ~PSR_EF);
-       }
-}
-
-void
-env_set_program_counter(env_t* e, uintptr_t pc)
-{
-       e->env_tf.pc = pc;
-       e->env_tf.npc = pc+4;
-}
-
-void
-env_init_trapframe(env_t* e)
-{
-       extern char trap_table;
-
-       e->env_tf.gpr[14] = USTACKTOP-64;
-       e->env_tf.psr = PSR_S; // but PS = 0
-       e->env_tf.wim = 0;
-       e->env_tf.tbr = (uint32_t)&trap_table;
-}
-
-// Flush all mapped pages in the user portion of the address space
-// TODO: only supports L3 user pages
-void
-env_user_mem_free(env_t* e)
-{
-       pte_t *l1pt = e->env_pgdir, *l2pt, *l3pt;
-       uint32_t l1x,l2x,l3x;
-       physaddr_t l2ptpa,l3ptpa,page_pa;
-       uint32_t l2_tables_per_page,l3_tables_per_page;
-
-       l2_tables_per_page = PGSIZE/(sizeof(pte_t)*NL2ENTRIES);
-       l3_tables_per_page = PGSIZE/(sizeof(pte_t)*NL3ENTRIES);
-
-       static_assert(L2X(UTOP) == 0 && L3X(UTOP) == 0);
-       for(l1x = 0; l1x < L1X(UTOP); l1x++)
-       {
-               if(!(l1pt[l1x] & PTE_PTD))
-                       continue;
-
-               l2ptpa = PTD_ADDR(l1pt[l1x]);
-               l2pt = (pte_t*COUNT(NL2ENTRIES)) KADDR(l2ptpa);
-
-               for(l2x = 0; l2x < NL2ENTRIES; l2x++)
-               {
-                       if(!(l2pt[l2x] & PTE_PTD))
-                               continue;
-
-                       l3ptpa = PTD_ADDR(l2pt[l2x]);
-                       l3pt = (pte_t*COUNT(NL3ENTRIES)) KADDR(l3ptpa);
-
-                       for(l3x = 0; l3x < NL3ENTRIES; l3x++)
-                       {
-                               if(l3pt[l3x] & PTE_PTE)
-                               {
-                                       page_pa = PTE_ADDR(l3pt[l3x]);
-                                       l3pt[l3x] = 0;
-                                       page_decref(pa2page(page_pa));
-                               }
-                       }
-
-                       l2pt[l2x] = 0;
-
-                       // free the L3 PT itself
-                       page_decref(pa2page(l2ptpa));
-               }
-
-               l1pt[l1x] = 0;
-
-               // free the L2 PT itself
-               page_decref(pa2page(l2ptpa));
-       }
-
-       tlbflush();
-}
index fbabfab..36d5d4b 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef ROS_ARCH_FRONTEND_H
 #define ROS_ARCH_FRONTEND_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 int32_t frontend_syscall(int32_t syscall_num, uint32_t arg0, uint32_t arg1, uint32_t arg2);
 
index 0dd7574..8a76031 100644 (file)
@@ -24,8 +24,8 @@ vm_init(void)
        boot_cr3 = PADDR(boot_pgdir);
 
        size_t env_array_size = ROUNDUP(NENV*sizeof(env_t), PGSIZE);
-       envs = (env_t *)boot_alloc(env_array_size, PGSIZE);
-       memset(envs, 0, env_array_size);
+       envs = /*(env_t *)*/boot_calloc(env_array_size, PGSIZE);
+       //memset(envs, 0, env_array_size);
 }
 
 error_t
@@ -114,6 +114,14 @@ pgdir_walk(pde_t* l1pt, const void*SNT va, int create)
        l3pte = &l3pt[L3X(va)];
        return l3pte;
 }
+
+/* TODO: this is probably wrong, since it only returns the pte as if it were the
+ * perms. */
+int get_va_perms(pde_t *pgdir, const void *SNT va)
+{
+       return (int)pgdir_walk(pgdir, va, 0);
+}
+
 void
 page_check(void)
 {
index 942bc40..b5e1783 100644 (file)
@@ -107,7 +107,7 @@ int smp_call_function_all(isr_t handler, void* data,
        return 0;
 }
 
-int smp_call_function_single(uint8_t dest, isr_t handler, void* data,
+int smp_call_function_single(uint32_t dest, isr_t handler, void* data,
                              handler_wrapper_t** wait_wrapper)
 {
        int8_t state = 0;
index 604c7e9..b71f0de 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef ROS_ARCH_SMP_H
 #define ROS_ARCH_SMP_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 #include <arch/arch.h>
 #include <atomic.h>
 
@@ -13,4 +13,4 @@ typedef struct
        spinlock_t lock;
 } handler_wrapper_t;
 
-#endif
+#endif /* !ROS_ARCH_SMP_H */
index 0df458c..0e53aa2 100644 (file)
@@ -22,8 +22,8 @@
 #define STR(arg) #arg
 #define XSTR(arg) STR(arg)
 
-#include <arch/types.h>
-#include <arch/trap.h>
+#include <ros/common.h>
+#include <trap.h>
 #include <arch/frontend.h>
 
 static __inline uint32_t read_psr(void) __attribute__((always_inline));
@@ -42,7 +42,6 @@ static __inline void write_fsr(uint32_t val) __attribute__((always_inline));
 static __inline uint32_t memsize_mb(void) __attribute__((always_inline));
 static __inline uint32_t mmu_probe(uint32_t va) __attribute__((always_inline));
 
-uint32_t send_active_message(uint32_t dst, amr_t pc, uint32_t arg0, uint32_t arg1, uint32_t arg2);
 void flush_windows();
 
 #define store_alternate(addr,asi,data) ({ uint32_t __my_addr = (addr); uint32_t __my_data = (data); __asm__ __volatile__ ("sta %0,[%1] %2" : : "r"(__my_data),"r"(__my_addr),"i"(asi)); })
index f170dd6..f3d5725 100644 (file)
@@ -1,5 +1,5 @@
 #include <arch/timer.h>
-#include <arch/types.h>
+#include <ros/common.h>
 #include <arch/trap.h>
 #include <arch/arch.h>
 #include <stdio.h>
index 2e1a221..37264b4 100644 (file)
@@ -3,7 +3,7 @@
 
 #define INTERRUPT_TIMER_HZ     100
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 typedef struct system_timing {
        uint64_t tsc_freq;
index 704ef11..db372af 100644 (file)
@@ -35,7 +35,7 @@ trap_handled(void)
 }
 
 void
-(IN_HANDLER print_trapframe)(trapframe_t *tf)
+( print_trapframe)(trapframe_t *tf)
 {
        int i, len;
        char buf[1024];
index 1e6b700..ab57870 100644 (file)
@@ -6,7 +6,7 @@
 
 #ifndef __ASSEMBLER__
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 typedef struct
 {
@@ -22,18 +22,6 @@ typedef struct
        uint64_t timestamp;
 } trapframe_t;
 
-typedef void (*amr_t)(trapframe_t* tf, uint32_t srcid, uint32_t a0, uint32_t a1, uint32_t a2);
-
-typedef struct
-{
-       uint32_t srcid;
-       amr_t pc;
-       uint32_t arg0;
-       uint32_t arg1;
-       uint32_t arg2;
-       uint32_t pad;
-} active_message_t;
-
 typedef struct
 {
        uint32_t fpr[32];
index 38cdadb..de94831 100644 (file)
@@ -3,8 +3,9 @@
 #ifndef ROS_INC_ASSERT_H
 #define ROS_INC_ASSERT_H
 
-void _warn(const char* NTS, int, const char* NTS, ...);
-void _panic(const char* NTS, int, const char* NTS, ...) __attribute__((noreturn));
+void ( _warn)(const char* NTS, int, const char* NTS, ...);
+void ( _panic)(const char* NTS, int, const char* NTS, ...)
+    __attribute__((noreturn));
 
 #define warn(...) _warn(__FILE__, __LINE__, __VA_ARGS__)
 #define panic(...) _panic(__FILE__, __LINE__, __VA_ARGS__)
index 975cd1c..aab58ae 100644 (file)
@@ -1,26 +1,31 @@
 #ifndef ROS_KERN_ATOMIC_H
 #define ROS_KERN_ATOMIC_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 #include <arch/mmu.h>
 #include <arch/atomic.h>
 #include <arch/arch.h>
 
-static inline void spin_lock_irqsave(volatile uint32_t*SAFE lock);
-static inline void spin_unlock_irqsave(volatile uint32_t*SAFE lock);
+static inline void
+(SLOCK(0) spin_lock_irqsave)(volatile uint32_t SRACY*SAFE lock);
+static inline void
+(SUNLOCK(0) spin_unlock_irqsave)(volatile uint32_t SRACY*SAFE lock);
 
 /*********************** Checklist stuff **********************/
 typedef struct checklist_mask {
        // only need an uint8_t, but we need the bits[] to be word aligned
        uint32_t size;
-       volatile uint8_t (COUNT(BYTES_FOR_BITMASK(size)) bits)[];
+       volatile uint8_t (COUNT(BYTES_FOR_BITMASK(size)) bits)[MAX_NUM_CPUS];
 } checklist_mask_t;
 
 // mask contains an unspecified array, so it needs to be at the bottom
-typedef struct checklist {
+struct checklist {
        volatile uint32_t lock;
        checklist_mask_t mask;
-} checklist_t;
+       // eagle-eyed readers may know why this might have been needed. 2009-09-04
+       //volatile uint8_t (COUNT(BYTES_FOR_BITMASK(size)) bits)[];
+};
+typedef struct checklist RACY checklist_t;
 
 #define ZEROS_ARRAY(size) {[0 ... ((size)-1)] 0}
 
index d66d9e4..14cc093 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef ROS_KERN_COLORED_CACHES_H
 #define ROS_KERN_COLORED_CACHES_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 /****************** Cache Structures ********************/
 typedef struct Cache {
@@ -24,6 +24,9 @@ typedef struct AvailableCaches {
        uint8_t l1 : 1;
        uint8_t l2 : 1;
        uint8_t l3 : 1;
+
+       // Pointer to the last level cache
+       cache_t*   llc;
 } available_caches_t;
 
 /******** Externally visible global variables ************/
@@ -38,24 +41,24 @@ size_t get_offset_in_cache_line(uintptr_t addr, cache_t *c);
 void print_cache_properties(char *NT lstring, cache_t *c);
 
 /****************** Cache Properties *********************/
-size_t get_cache_ways_associative(cache_t *c);
-size_t get_cache_line_size_bytes(cache_t *c);
-size_t get_cache_size_bytes(cache_t *c);
-size_t get_cache_size_kilobytes(cache_t *c);
-size_t get_cache_size_megabytes(cache_t *c);
-size_t get_cache_num_offset_bits(cache_t *c);
-size_t get_cache_num_index_bits(cache_t *c);
-size_t get_cache_num_tag_bits(cache_t *c);
-size_t get_cache_num_page_color_bits(cache_t *c);
-size_t get_cache_bytes_per_line(cache_t *c);
-size_t get_cache_num_lines(cache_t *c);
-size_t get_cache_num_sets(cache_t *c);
-size_t get_cache_lines_per_set(cache_t *c);
-size_t get_cache_lines_per_page(cache_t *c);
-size_t get_cache_bytes_per_way(cache_t *c);
-size_t get_cache_lines_per_way(cache_t *c);
-size_t get_cache_pages_per_way(cache_t *c);
-size_t get_cache_num_page_colors(cache_t *c);
+inline size_t get_cache_ways_associative(cache_t *c);
+inline size_t get_cache_line_size_bytes(cache_t *c);
+inline size_t get_cache_size_bytes(cache_t *c);
+inline size_t get_cache_size_kilobytes(cache_t *c);
+inline size_t get_cache_size_megabytes(cache_t *c);
+inline size_t get_cache_num_offset_bits(cache_t *c);
+inline size_t get_cache_num_index_bits(cache_t *c);
+inline size_t get_cache_num_tag_bits(cache_t *c);
+inline size_t get_cache_num_page_color_bits(cache_t *c);
+inline size_t get_cache_bytes_per_line(cache_t *c);
+inline size_t get_cache_num_lines(cache_t *c);
+inline size_t get_cache_num_sets(cache_t *c);
+inline size_t get_cache_lines_per_set(cache_t *c);
+inline size_t get_cache_lines_per_page(cache_t *c);
+inline size_t get_cache_bytes_per_way(cache_t *c);
+inline size_t get_cache_lines_per_way(cache_t *c);
+inline size_t get_cache_pages_per_way(cache_t *c);
+inline size_t get_cache_num_page_colors(cache_t *c);
 
 #endif // ROS_KERN_COLORED_CACHES_H
 
index 4fce9d1..865c405 100644 (file)
        page_list_entry_t _cache##_cache_colored_page_link;
        
 #define DECLARE_CACHE_COLORED_PAGE_FREE_LIST(_cache)                          \
-       page_list_t *COUNT(npages) _cache##_cache_colored_page_list = NULL;
+       uint8_t _cache##_num_colors = 0;                                          \
+       page_list_t *COUNT(_cache##_num_colors) _cache##_cache_colored_page_list = NULL;
        
 #define DECLARE_EXTERN_CACHE_COLORED_PAGE_FREE_LIST(_cache)                   \
-       extern page_list_t *COUNT(npages) _cache##_cache_colored_page_list;
+    extern uint8_t _cache##_num_colors;                                       \
+       extern page_list_t *COUNT(_cache##_num_colors) _cache##_cache_colored_page_list;
        
 #define DECLARE_CACHE_COLORED_PAGE_ALLOC_FUNCTION(_cache)                     \
 error_t _cache##_page_alloc(page_t** page, size_t color)                      \
@@ -40,11 +42,11 @@ error_t _cache##_page_alloc(page_t** page, size_t color)                      \
 #define INIT_CACHE_COLORED_PAGE_FREE_LIST(_cache)                             \
 {                                                                             \
        if(available_caches._cache == TRUE) {                                     \
-           uint8_t num_colors = get_cache_num_page_colors(&(_cache));            \
-           size_t list_size = num_colors*sizeof(page_list_t);                    \
+           _cache##_num_colors = get_cache_num_page_colors(&(_cache));           \
+           size_t list_size = _cache##_num_colors*sizeof(page_list_t);            \
            _cache##_cache_colored_page_list                                      \
               = (page_list_t*) boot_alloc(list_size, PGSIZE);                    \
-               for(int i=0; i<num_colors; i++) {                                     \
+               for(int i=0; i<_cache##_num_colors; i++) {                            \
                        LIST_INIT(&(_cache##_cache_colored_page_list[i]));                \
                }                                                                     \
        }                                                                         \
index 21919ee..d2ac247 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef ROS_INC_ELF_H
 #define ROS_INC_ELF_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 #if defined(LITTLE_ENDIAN)
 #  define ELF_MAGIC 0x464C457FU        /* "\x7FELF" in little endian */
index 1bc9822..969f203 100644 (file)
@@ -10,7 +10,7 @@
 #include <ros/error.h>
 #include <ros/procdata.h>
 #include <arch/trap.h>
-#include <arch/types.h>
+#include <ros/common.h>
 #include <arch/arch.h>
 #include <sys/queue.h>
 
@@ -40,6 +40,9 @@ typedef int32_t envid_t;
 #define ENVX(envid)            ((envid) & (NENV - 1))
 
 // TODO: clean this up.
+#ifdef __SHARC__
+typedef sharC_env_t;
+#endif
 struct Env {
        TAILQ_ENTRY(Env) proc_link NOINIT;      // Free list link pointers
        spinlock_t proc_lock;
@@ -53,10 +56,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;
+       uint32_t env_entry;
+       /* Virtual coremap: each index is the virtual core id, the contents at that
+        * index is the physical core_id() corresponding to the vcore. */
+       uint32_t vcoremap[MAX_NUM_CPUS];
+       uint32_t num_vcores;
+
+#ifdef __SHARC__
+       // held spin-locks
+       // zra: Used by Ivy. Let me know if this should go elsewhere.
+       sharC_env_t sharC_env;
+#endif
 
        // Address space
        pde_t *COUNT(NPDENTRIES) env_pgdir;                     // Kernel virtual address of page dir
        physaddr_t env_cr3;                     // Physical address of page dir
+//     struct memregion_list memregions;
 
        // Per process info and data pages
        procinfo_t *SAFE env_procinfo;       // KVA of per-process shared info table (RO)
@@ -76,12 +91,23 @@ struct Env {
 
 extern env_t *COUNT(NENV) envs;                // All environments
 extern atomic_t num_envs;              // Number of envs
-extern env_t* NORACE curenvs[MAX_NUM_CPUS];
+// TODO: consider moving this to struct per_cpu_info
+extern env_t * (RO curenvs)[MAX_NUM_CPUS];
+
+static inline env_t *
+get_cpu_curenv() TRUSTED
+{
+       return curenvs[core_id()];
+}
+
+static inline void
+set_cpu_curenv(env_t *p) TRUSTED
+{
+       curenvs[core_id()] = p;
+}
 
 void   env_init(void);
 int            env_alloc(env_t *SAFE*SAFE e, envid_t parent_id);
-void   env_init_trapframe(env_t* e);
-void   env_set_program_counter(env_t* e, uintptr_t pc);
 void   env_push_ancillary_state(env_t* e);
 void   env_pop_ancillary_state(env_t* e);
 void   env_free(env_t *SAFE e);
@@ -92,7 +118,8 @@ env_t*       env_create(uint8_t *COUNT(size) binary, size_t size);
  * Allows the kernel to figure out what process is running on its core.
  * Can be used just like a pointer to a struct process.
  */
-#define current (curenvs[core_id()])
+#define current (get_cpu_curenv())
+//#define current (curenvs[core_id()])
 
 int    envid2env(envid_t envid, env_t **env_store, bool checkperm);
 // The following three functions do not return
@@ -100,6 +127,10 @@ void       env_pop_tf(trapframe_t *tf) __attribute__((noreturn));
 
 
 /* Helper handler for smp_call to dispatch jobs to other cores */
-void run_env_handler(trapframe_t *tf, env_t* data);
+#ifdef __IVY__
+void run_env_handler(trapframe_t *tf, env_t * data);
+#else
+void run_env_handler(trapframe_t *tf, void * data);
+#endif
 
 #endif // !ROS_KERN_ENV_H
diff --git a/kern/include/ivy/sharc.h b/kern/include/ivy/sharc.h
new file mode 100644 (file)
index 0000000..2b4274b
--- /dev/null
@@ -0,0 +1,171 @@
+#include <assert.h>
+#include <string.h>
+
+#define SINLINE inline
+#define SUNUSED __attribute__((unused))
+
+typedef struct __ivy_sharC_thread {
+#define SHARC_MAX_LOCKS 16
+    void *held_locks[SHARC_MAX_LOCKS];
+    unsigned int max_lock;
+} sharC_env_t;
+
+#include <env.h>
+
+extern int __ivy_checking_on;
+
+#pragma cilnoremove("sharC_env_init")
+static SINLINE void sharC_env_init(sharC_env_t *sharC_env) TRUSTED;
+static SINLINE void sharC_env_init(sharC_env_t *sharC_env)
+WRITES(sharC_env->max_lock,sharC_env->held_locks)
+{
+       sharC_env->max_lock = 0;
+       memset(sharC_env->held_locks,0,SHARC_MAX_LOCKS);
+       return;
+}
+
+#pragma cilnoremove("__sharc_single_threaded")
+static SINLINE void __sharc_single_threaded(void *msg) TRUSTED;
+static SINLINE void __sharc_single_threaded(void *msg)
+{
+       // TODO: how do I know how many threads/cores are running?
+    //assert(1);
+    return;
+}
+
+
+#define GET_SHARC_THREAD() current->sharC_env
+
+#define THREAD_LOCKS(thread,i) (thread.held_locks[(i)])
+#define THREAD_MAX_LOCK(thread) (thread.max_lock)
+
+#define THIS_LOCKS(i)        (THREAD_LOCKS(GET_SHARC_THREAD(),(i)))
+#define THIS_MAX_LOCK        (THREAD_MAX_LOCK(GET_SHARC_THREAD()))
+
+/*
+ * Locks
+ */
+
+extern void
+__sharc_lock_error(const void *lck, const void *what,
+                   unsigned int sz, char *msg);
+
+extern void
+__sharc_lock_coerce_error(void *dstlck, void *srclck, char *msg);
+
+/* assumes no double-locking */
+#pragma cilnoremove("__sharc_add_lock")
+static SINLINE void __sharc_add_lock(void *lck) TRUSTED;
+static SINLINE void __sharc_add_lock(void *lck)
+{
+    unsigned int i;
+
+       if (!__ivy_checking_on || !current) return;
+
+    for (i = 0; i <= THIS_MAX_LOCK; i++)
+        if (!THIS_LOCKS(i))
+            break;
+
+    if (i > THIS_MAX_LOCK && THIS_MAX_LOCK < SHARC_MAX_LOCKS)
+            THIS_MAX_LOCK++;
+
+    THIS_LOCKS(i) = lck;
+    return;
+}
+
+/* this will be very inefficient if the lock isn't actually held */
+#pragma cilnoremove("__sharc_rm_lock")
+static SINLINE void __sharc_rm_lock(void *lck) TRUSTED;
+static SINLINE void __sharc_rm_lock(void *lck)
+{
+    unsigned int i;
+
+       if (!__ivy_checking_on || !current) return;
+
+    for (i = 0; i <= THIS_MAX_LOCK; i++)
+        if (THIS_LOCKS(i) == lck)
+            break;
+
+    if (i == THIS_MAX_LOCK && THIS_MAX_LOCK > 0)
+            THIS_MAX_LOCK--;
+
+    THIS_LOCKS(i) = (void *)0;
+    return;
+}
+
+#pragma cilnoremove("__sharc_chk_lock")
+static SINLINE void
+__sharc_chk_lock(void *lck, void *what, unsigned int sz, char *msg) TRUSTED;
+static SINLINE void
+__sharc_chk_lock(void *lck, void *what, unsigned int sz, char *msg)
+{
+    unsigned int i;
+
+       // TODO: how do I find how many threads are running?
+    //if (__sharc_num_threads == 1) return;
+
+       if (!__ivy_checking_on || !current) return;
+
+    for (i = 0; i <= THIS_MAX_LOCK; i++)
+        if (THIS_LOCKS(i) == lck)
+            break;
+
+    if (i > THIS_MAX_LOCK) {
+            __sharc_lock_error(lck,what,sz,msg);
+    }
+}
+
+#pragma cilnoremove("__sharc_coerce_lock")
+static SINLINE void
+__sharc_coerce_lock(void *dstlck, void *srclck, char *msg) TRUSTED;
+static SINLINE void
+__sharc_coerce_lock(void *dstlck, void *srclck, char *msg)
+{
+       if (!__ivy_checking_on) return;
+
+    if (dstlck != srclck)
+        __sharc_lock_coerce_error(dstlck,srclck,msg);
+}
+
+/*
+ * The sharing cast.
+ *
+ */
+
+extern void __sharc_group_cast_error(int, void *, void *, char *);
+
+#pragma cilnoremove("__sharc_check_group_cast")
+static inline void
+__sharc_check_group_cast(int hassame, void *srcg, void *src, char *msg) TRUSTED;
+static inline void
+__sharc_check_group_cast(int hassame, void *srcg, void *src, char *msg)
+{
+       int old;
+       if (!__ivy_checking_on) return;
+       old = __ivy_checking_on;
+       __ivy_checking_on = 0;
+       panic("sharc group cast unimplemented");
+       __ivy_checking_on = old;
+}
+
+
+extern void __sharc_cast_error(void *addr, unsigned long sz, char *msg);
+
+#pragma cilnoremove("__sharc_sharing_cast")
+static SINLINE void *
+__sharc_sharing_cast(void *addr,void **slot, unsigned int localslot SUNUSED,
+                     unsigned long lo, unsigned long hi,
+                     char *msg) TRUSTED;
+static SINLINE void *
+__sharc_sharing_cast(void *addr,void **slot, unsigned int localslot SUNUSED,
+                     unsigned long lo, unsigned long hi,
+                     char *msg)
+{
+       int old;
+       if (!__ivy_checking_on) return NULL;
+       old = __ivy_checking_on;
+       __ivy_checking_on = 0;
+       panic("sharc sharing cast unimplemented");
+       __ivy_checking_on = old;
+       return NULL;
+}
index 9fbf3fd..4127814 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef ROS_KERN_KDEBUG_H
 #define ROS_KERN_KDEBUG_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 // Debug information about a particular instruction pointer
 typedef struct Eipdebuginfo {
index d3f12fd..b6d76e6 100644 (file)
 #ifndef ROS_KERN_KFS_H
 #define ROS_KERN_KFS_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 #include <process.h>
 
-// zra : putting nodeputy in header files makes life difficult.
-//#pragma nodeputy
-
 struct kfs_entry {
        char (NT name)[256];
        uint8_t *COUNT(size) start;
        size_t size;
 };
 
-#define MAX_KFS_FILES 11
+#define MAX_KFS_FILES 20
 extern struct kfs_entry kfs[MAX_KFS_FILES];
 
 ssize_t kfs_lookup_path(char*NTS path);
index 33df609..90b3edd 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef ROS_KERN_KMALLOC_H
 #define ROS_KERN_KMALLOC_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 void  kmalloc_init();
 
index ece51ea..3056e21 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef ROS_LISTABLE_H
 #define ROS_LISTABLE_H
  
-#include <arch/types.h>
+#include <ros/common.h>
 #include <sys/queue.h>
 
 #define DECLARE_LISTABLE_ITEM(name, link, item)   \
index b333893..f8804e7 100644 (file)
  * The manager is the "asymmetric control unit", that runs on core 0 for now
  * and controls the actions of the whole system.
  */
-
 void manager(void);
 
+/* Returns if the calling core is a management core or not. */
+static inline bool management_core(void);
+
+static inline bool management_core(void)
+{
+       // currently returns true for only core 0
+       return !core_id();
+}
+
 #endif /* ROS_KERN_MANAGER_H */
index 8d7af4c..4013aa8 100644 (file)
@@ -7,7 +7,7 @@
 // Activate the kernel monitor,
 // optionally providing a trap frame indicating the current state
 // (NULL if none).
-void (IN_HANDLER monitor)(trapframe_t *tf);
+void ( monitor)(trapframe_t *tf);
 
 // Functions implementing monitor commands.
 int mon_help(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
@@ -21,5 +21,6 @@ int mon_nanwan(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_kfs_ls(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_kfs_run(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 int mon_manager(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
+int mon_procinfo(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
 
 #endif // !ROS_KERN_MONITOR_H
index b34a5b4..ac57d17 100644 (file)
@@ -3,7 +3,7 @@
 
 #ifndef __ASSEMBLER__
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 extern physaddr_t maxpa;        // Maximum physical address in the system
 extern physaddr_t maxaddrpa;    // Maximum addressable physical address
index 8be20ce..ed0d141 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef PAGE_ALLOC_H
 #define PAGE_ALLOC_H
 
+#include <atomic.h>
 #include <sys/queue.h>
 #include <ros/error.h>
 #include <arch/mmu.h>
@@ -21,16 +22,17 @@ typedef LIST_HEAD(PageList, Page) page_list_t;
 typedef LIST_ENTRY(Page) page_list_entry_t;
 
 struct Page {
-       page_list_entry_t global_link;
-       DECLARE_CACHE_COLORED_PAGE_LINKS();
+       page_list_entry_t page_link;
        
        size_t num_cons_links;
     size_t page_ref;
 };
 
+
 /******** Externally visible global variables ************/
-extern page_list_t page_free_list;
-DECLARE_EXTERN_CACHE_COLORED_PAGE_FREE_LISTS();
+extern uint16_t llc_num_colors;
+extern page_list_t *COUNT(llc_num_colors) colored_page_free_list;
+extern spinlock_t colored_page_free_list_lock;
 
 /*************** Functional Interface *******************/
 void page_alloc_init(void);
index c6d4569..3eed160 100644 (file)
@@ -2,11 +2,9 @@
 
 #ifndef ROS_KERN_PMAP_H
 #define ROS_KERN_PMAP_H
-#ifndef ROS_KERNEL
-# error "This is a ROS kernel header; user programs should not #include it"
-#endif
 
 #include <ros/memlayout.h>
+#include <ros/mman.h>
 #include <sys/queue.h>
 #include <multiboot.h>
 #include <atomic.h>
 
 extern char (SNT bootstacktop)[], (SNT bootstack)[];
 
-extern page_t *COUNT(npages) pages; // List of pysical pages
+// List of physical pages
+extern volatile uint32_t pages_lock;
+extern page_t SLOCKED(&pages_lock) * SREADONLY COUNT(npages) pages;
 
-extern physaddr_t boot_cr3;
+extern physaddr_t RO boot_cr3;
 extern pde_t *COUNT(NPDENTRIES) boot_pgdir;
 
 extern char*BND(end, maxaddrpa_ptr + IVY_KERNBASE) boot_freemem;
@@ -59,7 +59,7 @@ int       page_insert(pde_t *COUNT(NPDENTRIES) pgdir, page_t *pp, void *SNT va, in
 void*COUNT(PGSIZE) page_insert_in_range(pde_t *COUNT(NPDENTRIES) pgdir, page_t *pp, 
                              void *SNT vab, void *SNT vae, int perm);
 void   page_remove(pde_t *COUNT(NPDENTRIES) pgdir, void *SNT va);
-page_t*COUNT(1) page_lookup(pde_t *COUNT(NPDENTRIES) pgdir, void *SNT va, pte_t **pte_store);
+page_t*COUNT(1) page_lookup(pde_t SSOMELOCK*COUNT(NPDENTRIES) pgdir, void *SNT va, pte_t **pte_store);
 error_t        pagetable_remove(pde_t *COUNT(NPDENTRIES) pgdir, void *SNT va);
 void   page_decref(page_t *COUNT(1) pp);
 
@@ -80,7 +80,10 @@ error_t
 memcpy_from_user(env_t* env, void* COUNT(len) dest,
                  const void *DANGEROUS va, size_t len);
                  
-pte_t *pgdir_walk(pde_t *COUNT(NPDENTRIES) pgdir, const void *SNT va, int create);                 
+/* Arch specific implementations for these */
+pte_t *pgdir_walk(pde_t *COUNT(NPDENTRIES) pgdir, const void *SNT va, int create);
+int get_va_perms(pde_t *COUNT(NPDENTRIES) pgdir, const void *SNT va);
+void *get_free_va_range(pde_t *pgdir, uintptr_t addr, size_t len);
 
 static inline page_t *SAFE ppn2page(size_t ppn)
 {
@@ -121,4 +124,23 @@ static inline page_t* kva2page(void* addr)
        return pa2page(PADDR(addr));
 }
 
+/*
+ * Memory management for processes: syscall related functions, virtual memory
+ * regions, etc.
+ */
+void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags, int fd, size_t offset);
+
+/* Memory region for a process, consisting of linear(virtual) addresses.  This
+ * is what the kernel allocates a process, and the physical mapping can be done
+ * lazily (or not).  This way, if a page is swapped out, and the PTE says it
+ * isn't present, we still have a way to account for how the whole region ought
+ * to be dealt with. */
+struct memregion {
+       LIST_ENTRY(memregion) link; // actually, i'd like a sorted tree of these
+       uintptr_t base;
+       size_t len;
+       int perm;
+};
+TAILQ_HEAD(memregion_list, memregion); // Declares 'struct memregion_list'
+
 #endif /* !ROS_KERN_PMAP_H */
index 5f7868a..755d9c4 100644 (file)
@@ -10,7 +10,8 @@
 #ifndef ROS_KERN_PROCESS_H
 #define ROS_KERN_PROCESS_H
 
-#include <arch/types.h>
+#include <ros/common.h>
+#include <trap.h>
 #include <atomic.h>
 
 /* Process States.  Not 100% on the names yet. */
@@ -35,14 +36,41 @@ extern spinlock_t freelist_lock;
 extern struct proc_list proc_runnablelist;
 extern spinlock_t runnablelist_lock;
 
+extern spinlock_t idle_lock;
+extern uint32_t idlecoremap[MAX_NUM_CPUS];
+extern uint32_t num_idlecores;
+
 int proc_set_state(struct proc *p, uint32_t state) WRITES(p->state);
 struct proc *get_proc(unsigned pid);
-bool proc_controls(struct proc *actor, struct proc *target);
-void proc_run(struct proc *p);
-void proc_startcore(struct proc *p, trapframe_t *tf) __attribute__((noreturn));
+bool proc_controls(struct proc *SAFE actor, struct proc *SAFE target);
+void proc_run(struct proc *SAFE p);
+// TODO: why do we need these parentheses?
+void (proc_startcore)(struct proc *SAFE p, trapframe_t *SAFE tf)
+     __attribute__((noreturn));
+void (proc_destroy)(struct proc *SAFE p);
 void proc_destroy(struct proc *SAFE p);
+void proc_init_trapframe(trapframe_t *SAFE tf);
+void proc_set_program_counter(trapframe_t *SAFE tf, uintptr_t pc);
+void proc_set_tfcoreid(trapframe_t *SAFE tf, uint32_t id);
 
 /* The reference counts are mostly to track how many cores loaded the cr3 */
 error_t proc_incref(struct proc *SAFE p);
 void proc_decref(struct proc *SAFE p);
+
+/* Active message handlers for process management */
+#ifdef __IVY__
+void __startcore(trapframe_t *tf, uint32_t srcid, struct proc *CT(1) a0,
+                 trapframe_t *CT(1) a1, void *SNT a2);
+void __death(trapframe_t *tf, uint32_t srcid, void *SNT a0, void *SNT a1,
+             void *SNT a2);
+#else
+void __startcore(trapframe_t *tf, uint32_t srcid, void * a0, void * a1,
+                 void * a2);
+void __death(trapframe_t *tf, uint32_t srcid, void * a0, void * a1,
+             void * a2);
+#endif
+
+/* Degubbing */
+void print_idlecoremap(void);
+
 #endif // !ROS_KERN_PROCESS_H
diff --git a/kern/include/ros/common.h b/kern/include/ros/common.h
new file mode 100644 (file)
index 0000000..331a14f
--- /dev/null
@@ -0,0 +1,150 @@
+#ifndef ROS_COMMON_H
+#define ROS_COMMON_H
+
+#ifndef __IVY__
+#include <ros/noivy.h>
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+typedef uintptr_t physaddr_t;
+typedef ssize_t intreg_t;
+typedef size_t uintreg_t;
+typedef int bool;
+
+#ifndef NULL
+#define NULL ((void*) 0)
+#endif
+
+#ifndef TRUE
+#define TRUE   1
+#endif
+
+#ifndef FALSE
+#define FALSE  0
+#endif
+
+#define CHECK_FLAG(flags,bit)   ((flags) & (1 << (bit)))
+
+#define FOR_CIRC_BUFFER(next, size, var) \
+       for (int _var = 0, var = (next); _var < (size); _var++, var = (var + 1) % (size))
+
+// Efficient min and max operations
+#define MIN(_a, _b)                                            \
+({                                                             \
+       typeof(_a) __a = (_a);                                  \
+       typeof(_b) __b = (_b);                                  \
+       __a <= __b ? __a : __b;                                 \
+})
+#define MAX(_a, _b)                                            \
+({                                                             \
+       typeof(_a) __a = (_a);                                  \
+       typeof(_b) __b = (_b);                                  \
+       __a >= __b ? __a : __b;                                 \
+})
+
+// Rounding operations (efficient when n is a power of 2)
+// Round down to the nearest multiple of n
+#define ROUNDDOWN(a, n)                                                \
+({                                                             \
+       uint32_t __a = (uint32_t) (a);                          \
+       (typeof(a)) (__a - __a % (n));                          \
+})
+// Round up to the nearest multiple of n
+#define ROUNDUP(a, n)                                          \
+({                                                             \
+       uint32_t __n = (uint32_t) (n);                          \
+       (typeof(a)) (ROUNDDOWN((uint32_t) (a) + __n - 1, __n)); \
+})
+
+// Round down to the nearest multiple of n
+#define PTRROUNDDOWN(a, n)                                             \
+({                                                             \
+       char * __a = (char *) (a);                              \
+       (typeof(a)) (__a - (uint32_t)__a % (n));                                \
+})
+// Round pointer up to the nearest multiple of n
+#define PTRROUNDUP(a, n)                                               \
+({                                                             \
+       uint32_t __n = (uint32_t) (n);                          \
+       (typeof(a)) (PTRROUNDDOWN((char *) (a) + __n - 1, __n));        \
+})
+
+// Return the integer logarithm of the value provided rounded up
+static inline uint32_t LOG2(uint32_t value)
+{
+    uint32_t l = 0;
+    while( (value >> l) > 1 ) ++l;
+    return l;
+}
+
+// Return the offset of 'member' relative to the beginning of a struct type
+#ifndef offsetof
+#define offsetof(type, member)  ((size_t) (&((type*)0)->member))
+#endif
+
+// Ivy currently can only handle 63 bits (OCaml thing), so use this to make
+// a uint64_t programatically
+#define UINT64(upper, lower) ( (((uint64_t)(upper)) << 32) | (lower) )
+
+
+/*********************** Bitmask stuff **********************/
+#define BYTES_FOR_BITMASK(size) (((size) - 1) / 8 + 1)
+#define BYTES_FOR_BITMASK_WITH_CHECK(size) ((size) ? ((size) - (1)) / (8) + (1) : (0))
+#define DECL_BITMASK(name, size) uint8_t (name)[BYTES_FOR_BITMASK((size))]
+
+#define GET_BITMASK_BIT(name, bit) (((name)[(bit)/8] & (1 << ((bit) % 8))) ? 1 : 0)
+#define SET_BITMASK_BIT(name, bit) ((name)[(bit)/8] |= (1 << ((bit) % 8)))
+#define CLR_BITMASK_BIT(name, bit) ((name)[(bit)/8] &= ~(1 << ((bit) % 8)))
+#define SET_BITMASK_BIT_ATOMIC(name, bit) (atomic_orb(&(name)[(bit)/8], (1 << ((bit) % 8))))
+#define CLR_BITMASK_BIT_ATOMIC(name, bit) (atomic_andb(&(name)[(bit)/8], ~(1 << ((bit) % 8))))
+
+#define CLR_BITMASK(name, size) \
+({ \
+       {TRUSTEDBLOCK \
+       memset((void*)((uintptr_t)(name)), 0, BYTES_FOR_BITMASK((size))); \
+       } \
+})
+
+#define FILL_BITMASK(name, size) \
+({ \
+       {TRUSTEDBLOCK \
+       memset((void*)((uintptr_t)(name)), 255, BYTES_FOR_BITMASK((size))); \
+       } \
+       (name)[BYTES_FOR_BITMASK((size))-1] >>= (((size) % 8) ? (8 - ((size) % 8)) : 0 ); \
+}) 
+
+#define COPY_BITMASK(newmask, oldmask, size) \
+({ \
+       {TRUSTEDBLOCK \
+       memcpy((void*)((uintptr_t)(newmask)), \
+           (void*)((uintptr_t)(oldmask)), \
+           BYTES_FOR_BITMASK((size))); \
+       } \
+})
+
+// this checks the entire last byte, so keep it 0 in the other macros
+#define BITMASK_IS_CLEAR(name, size) ({ \
+       uint32_t __n = BYTES_FOR_BITMASK((size)); \
+       bool clear = 1; \
+       while (__n-- > 0) { \
+               if ((name)[__n]) { \
+                       clear = 0; \
+                       break;\
+               }\
+       } \
+       clear; })
+
+#define PRINT_BITMASK(name, size) { \
+       int i;  \
+       for (i = 0; i < BYTES_FOR_BITMASK(size); i++) { \
+               int j;  \
+               for (j = 0; j < 8; j++) \
+                       printk("%x", ((name)[i] >> j) & 1);     \
+       } \
+       printk("\n"); \
+}
+/**************************************************************/
+#endif /* ROS_COMMON_H */
index 6885ed8..318a954 100644 (file)
@@ -3,8 +3,12 @@
 #ifndef ROS_INC_ERROR_H
 #define ROS_INC_ERROR_H
 
+#include <ros/common.h>
+
 #define DECLARE_ERROR_CODE(e, s)
 
+// define this to prevent conflicts with newlib's errno.h
+#define __error_t_defined
 typedef enum {
        ESUCCESS = 0,            // Success
        EFAIL,                   // Generic Failure
@@ -12,6 +16,7 @@ typedef enum {
        EDEADLOCK,               // Would cause deadlock
        EBUSY,                   // Currently busy, try again later
        ENOMEM,                  // No memory available
+       ENOCACHE,                // No cache available
        EINVAL,                  // Invalid arguments
        EFAULT,                  // Segmentation fault
        EBADENV,                 // Bad environment 
@@ -36,6 +41,7 @@ static const char *NTS const error_string[NUMERRORS] =
        "Would cause deadlock",
        "Currently busy, try again later",
        "No memory available",
+       "No cache available",
        "Invalid arguments",
        "Segmentation fault",
        "Bad environment",
index d40ab7e..f19154b 100644 (file)
@@ -2,7 +2,7 @@
 #define ROS_INC_MEMLAYOUT_H
 
 #ifndef __ASSEMBLER__
-#include <arch/types.h>
+#include <ros/common.h>
 #include <arch/mmu.h>
 #endif /* not __ASSEMBLER__ */
 
@@ -31,7 +31,7 @@
  *                     |         Kernel Stack         | RW/--  KSTKSIZE   |
  *                     | - - - - - - - - - - - - - - -|                 PTSIZE
  *                     |      Invalid Memory (*)      | --/--             |
- *    ULIM      ----> +------------------------------+ 0xbf800000      --+
+ *    ULIM      ---->  +------------------------------+ 0xbf800000      --+
  *                     |  Cur. Page Table (User R-)   | R-/R-  PTSIZE
  *    UVPT      ---->  +------------------------------+ 0xbf400000      --+
  *                     | Unmapped (expandable region) |                   |
 typedef uint32_t pte_t;
 typedef uint32_t pde_t;
 
-extern volatile pte_t (COUNT(PTSIZE) vpt)[];     // VA of "virtual page table"
-extern volatile pde_t (COUNT(PTSIZE) vpd)[];     // VA of current page directory
+#ifdef __IVY__
+#pragma cilnoremove("vpt_lock", "vpd_lock")
+#endif
+extern volatile uint32_t vpt_lock;
+extern volatile uint32_t vpd_lock;
+
+extern volatile pte_t SLOCKED(&vpt_lock) (COUNT(PTSIZE) SREADONLY vpt)[]; // VA of "virtual page table"
+extern volatile pde_t SLOCKED(&vpd_lock) (COUNT(PTSIZE) SREADONLY vpd)[]; // VA of current page directory
 
 #endif /* !__ASSEMBLER__ */
 #endif /* !ROS_INC_MEMLAYOUT_H */
diff --git a/kern/include/ros/mman.h b/kern/include/ros/mman.h
new file mode 100644 (file)
index 0000000..4bc9130
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * Barret Rhoden <brho@cs.berkeley.edu>
+ * See LICENSE for details.
+ *
+ * Memory management flags, currently used in mmap()
+ */
+
+#ifndef ROS_INCLUDE_MMAN_H
+#define ROS_INCLUDE_MMAN_H
+
+/* Memory protection states (what you're allowed to do */
+#define PROT_NONE              0x1
+#define PROT_EXEC              0x2
+#define PROT_READ              0x4
+#define PROT_WRITE             0x8
+
+/* mmap flags, only anonymous is supported now, feel free to pass others */
+#define MAP_SHARED             0x001
+#define MAP_PRIVATE            0x002
+#define MAP_ANONYMOUS  0x004
+#define MAP_FIXED              0x008
+#define MAP_GROWSDOWN  0x010
+#define MAP_STACK              0x020
+#define MAP_POPULATE   0x040
+#define MAP_NONBLOCK   0x080
+#define MAP_NORESERVE  0x100
+
+/* Other mmap flags, which we probably won't support
+#define MAP_32BIT
+#define MAP_LOCKED
+*/
+
+#endif /* !ROS_INCLUDE_MMAN_H */
diff --git a/kern/include/ros/noivy.h b/kern/include/ros/noivy.h
new file mode 100644 (file)
index 0000000..83d4d41
--- /dev/null
@@ -0,0 +1,164 @@
+#ifndef NOIVY_H
+#define NOIVY_H
+
+#define BOUND(lo, hi)   
+#define COUNT(n)        
+#define SIZE(n)         
+#define SAFE            
+#define SNT             
+#define DANGEROUS       
+
+/* Begin Experimental attributes */
+#define META(p)            
+#define HANDLER_ATOMIC              
+#define LOCK_HANDLER_ATOMIC(...)   
+#define IN_HANDLER_ATOMIC  
+#define IN_HANDLER         
+#define ASYNC              
+#define NORACE             
+#define SYNCHRONOUS        
+#define REGION(r)          
+#define NOREGION           
+#define SOMEREGION         
+#define SAMEREGION         
+#define DELETES_REGION(r)  
+#define GROUP(g)           
+#define NOGROUP            
+#define SOMEGROUP          
+#define SAMEGROUP          
+#define UNIQUE             
+#define NOALIAS            
+#define PAIRED_WITH(c)     
+#define PAIRED(c1,c2)      
+#define ARGPAIRED(c1,c2,arg) 
+#define FNPTRCALLER(fn)    
+#define INITSTRUCT(s)      
+#define NOINIT             
+#define WRITES(...)        
+#define RPROTECT           
+#define WPROTECT           
+#define RWPROTECT          
+#define R_PERMITTED(...) 
+#define W_PERMITTED(...) 
+#define RW_PERMITTED(...) 
+/* End Experimental attributes */
+
+#define BND(lo, hi)     
+#define CT(n)           
+#define SZ(n)           
+
+#define EFAT            
+#define FAT             
+
+#define NULLTERM        
+#define NT              
+#define NTS             
+#define NTC(n)          
+
+#define NTDROPATTR      
+#define NTEXPANDATTR    
+
+#define NULLABLE
+#define OPT             
+#define NONNULL         
+
+#define TRUSTED         
+#define TRUSTEDBLOCK    
+
+#define POLY           
+
+#define COPYTYPE        
+
+//specifies that Deputy's typechecker (but not optimizer) should assume
+//that this lvalue is constant. (unsound)
+#define ASSUMECONST     
+
+#define WHEN(e)         
+
+#define DMEMCPY(x, y, z) 
+#define DMEMSET(x, y, z) 
+#define DMEMCMP(x, y, z)
+
+#define DALLOC(x)       
+#define DREALLOC(x, y)  
+#define DFREE(x)        
+
+#define DVARARG(x)      
+#define DPRINTF(x)      
+
+#define NTDROP(x)       (x)
+#define NTEXPAND(x)     (x)
+#define TC(x)           (x)
+
+#define TVATTR(x)       
+#define TPATTR(x)       
+
+#define TV(x)           void *
+#define TP(x)           
+#define NTP(n,x)
+#define NTPTV(n)
+
+/* Sharc Stuff */
+
+#define SINTHREAD
+#define SFNPTR
+#define SHASDEF
+#define SPURE
+#define STCREATE(fn,arg)
+#define SBARRIER(n)
+#define SBARRIERFN
+
+#define SLOCK(x)
+#define SUNLOCK(x)
+#define SLOCKED(l)
+#define SSOMELOCK
+#define SREADONLY
+#define SRACY
+#define SREADS(n)
+#define SWRITES(n)
+#define SREADSNT
+#define SWRITESNT
+#define SCTX
+#define SPRIVATE
+#define SDYNAMIC
+#define SINDYNAMIC
+#define SOUTDYNAMIC
+#define SDYNBAR(b)
+
+#define RO
+#define LCKD(x)
+#define RACY
+#define PRIVATE
+
+#define BASE(p)
+
+#define SGROUP(g)
+#define SNOGROUP
+#define SRETGROUP
+#define SARGGROUP
+
+#define SSAME
+
+#define SUNIQUE
+#define SNOALIAS
+
+#define SMAYCAST
+#define SINMAYCAST
+#define SOUTMAYCAST
+#define SCONDMCRET
+
+#define TRUSTEDBLOCK
+
+#define SCAST(x) (x)
+#define SINIT(x) (x)
+#define SINIT_DOUBLE(x) (x)
+#define SINIT_FLOAT(x) (x)
+
+#define hs_nofree
+
+#define DALLOC(x)
+#define DFREE(x)
+
+
+#endif // NOIVY_H
+
index f5ece87..ee7e22f 100644 (file)
@@ -7,8 +7,7 @@
 #include <ros/syscall.h>
 #include <ros/sysevent.h>
 #include <ros/error.h>
-
-typedef int32_t pid_t;
+#include <ros/common.h>
 
 typedef struct procinfo {
        pid_t id;
index aa0d389..3fac1ec 100644 (file)
@@ -36,6 +36,9 @@
 
 typedef unsigned int RING_IDX;
 
+// zra: smp.c is v. slow to build because these RDn() things cause expressions
+//      to grow exponentially.
+
 /* Round a 32-bit unsigned constant down to the nearest power of two. */
 #define __RD2(_x)  (((_x) & 0x00000002UL) ? 0x2                  : ((_x) & 0x1))
 #define __RD4(_x)  (((_x) & 0x0000000cUL) ? __RD2((_x)>>2)<<2    : __RD2(_x))
@@ -130,8 +133,12 @@ typedef unsigned int RING_IDX;
     RING_IDX rsp_prod, rsp_event;                                       \
     uint8_t  pad[48];
     
+struct rhs_struct {
+       __RING_HEADER()
+};
+
 #define __RING_HEADER_SIZE() \
-    (sizeof(struct {__RING_HEADER()} ))
+    (sizeof(struct rhs_struct))
 
 #define DEFINE_RING_TYPES(__name, __req_t, __rsp_t)                     \
        DEFINE_RING_TYPES_WITH_SIZE(__name, __req_t, __rsp_t,               \
@@ -171,11 +178,11 @@ struct __name##_back_ring {                                             \
 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;                 \
-                                                                        \
 /* 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)) {        \
+static void __name##_assert_sring_size() __attribute__((used));         \
+static void __name##_assert_sring_size() {                              \
        __ASSERT_EQUAL( sizeof(__name##_sring_t),                           \
                        ( __RING_HEADER_SIZE()  +                           \
                          ( __RING_SIZE_STATIC(__name, __size) *            \
@@ -185,6 +192,7 @@ static void __name##_assert_sring_size() __attribute__((used)) {        \
                      );                                                    \
 }              
 
+
 /*
  * Macros for manipulating rings.
  * 
index 217a4e1..1b40e25 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef ROS_INCLUDE_SYSCALL_H
 #define ROS_INCLUDE_SYSCALL_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 #include <ros/ring_buffer.h>
 
 /* system call numbers */
@@ -15,11 +15,17 @@ enum
        SYS_cputs,
        SYS_cgetc,
        SYS_getcpuid,
-       SYS_serial_write,
-       SYS_serial_read,
+
+       // The next 3 syscalls go with the experimental network
+       // driver. These syscalls are used by newlib_backend /
+       // our remote binary loader to pull data from / put data
+       // into a buffer managed by the network driver.
+       // These should go away as things mature. 
        SYS_eth_read,
        SYS_eth_write,
        SYS_run_binary,
+       // End of extra network syscalls
+
        SYS_getpid,
        SYS_proc_destroy,
        SYS_shared_page_alloc,
@@ -27,6 +33,20 @@ enum
        SYS_yield,
        SYS_proc_create,
        SYS_proc_run,
+
+       SYS_mmap,
+       SYS_brk,
+       /*
+       SYS_mprotect,
+       SYS_mremap,
+       SYS_mincore, // can read page tables instead
+       SYS_madvise,
+       SYS_mlock,
+       SYS_msync,
+       */
+
+       SYS_serial_write,
+       SYS_serial_read,
        SYS_frontend,           // forward a syscall to front-end machine
 
        SYS_endofcalls //Should always be last
@@ -55,6 +75,7 @@ typedef struct syscall_rsp {
 
 // Generic Syscall Ring Buffer
 #define SYSCALLRINGSIZE    PGSIZE
-DEFINE_RING_TYPES_WITH_SIZE(syscall, syscall_req_t, syscall_rsp_t, SYSCALLRINGSIZE);
+//DEFINE_RING_TYPES_WITH_SIZE(syscall, syscall_req_t, syscall_rsp_t, SYSCALLRINGSIZE);
+DEFINE_RING_TYPES(syscall, syscall_req_t, syscall_rsp_t);
 
 #endif /* !ROS_INCLUDE_SYSCALL_H */
index e911da9..5d46162 100644 (file)
 /* SMP related functions */
 
 #include <arch/smp.h>
-#include <arch/types.h>
+#include <ros/common.h>
 #include <trap.h>
 #include <atomic.h>
+#include <process.h>
 #include <workqueue.h>
 #include <env.h>
 
 // will want this padded out to cacheline alignment
 struct per_cpu_info {
-       uint32_t lock;
+       spinlock_t lock;
        bool preempt_pending;
-       struct workqueue workqueue;
+       struct workqueue NTPTV(t) workqueue;
+#ifdef __i386__
+       spinlock_t amsg_lock;
+       unsigned LCKD(&amsg_lock) amsg_current;
+       active_message_t LCKD(&amsg_lock) (RO active_msgs)[NUM_ACTIVE_MESSAGES];
+#endif
 };
-extern struct per_cpu_info  per_cpu_info[MAX_NUM_CPUS];
-extern volatile uint8_t num_cpus;
+
+typedef struct per_cpu_info NTPTV(t) NTPTV(a0t) NTPTV(a1t) NTPTV(a2t) per_cpu_info_t;
+
+extern per_cpu_info_t (RO per_cpu_info)[MAX_NUM_CPUS];
+extern volatile uint8_t RO num_cpus;
 
 /* SMP bootup functions */
 void smp_boot(void);
@@ -34,7 +43,7 @@ int smp_call_function_self(poly_isr_t handler, TV(t) data,
                            handler_wrapper_t** wait_wrapper);
 int smp_call_function_all(poly_isr_t handler, TV(t) data,
                           handler_wrapper_t** wait_wrapper);
-int smp_call_function_single(uint8_t dest, poly_isr_t handler, TV(t) data,
+int smp_call_function_single(uint32_t dest, poly_isr_t handler, TV(t) data,
                              handler_wrapper_t** wait_wrapper);
 int smp_call_wait(handler_wrapper_t*SAFE wrapper);
 
index 9363d1f..eed75ba 100644 (file)
@@ -1,6 +1,6 @@
 #ifndef ROS_STAB_H
 #define ROS_STAB_H
-#include <arch/types.h>
+#include <ros/common.h>
 
 // <inc/stab.h>
 // STABS debugging info
diff --git a/kern/include/stdint.h b/kern/include/stdint.h
new file mode 100644 (file)
index 0000000..44fd3db
--- /dev/null
@@ -0,0 +1,5 @@
+/* GHETTO: To our grandchildren, we are sorry for this
+ * We do this since newlib has it's own stdint that conflicts with the kernel
+ * and roslib's types. */
+
+#include <arch/types.h>
index 8d2e6ae..8212951 100644 (file)
@@ -31,7 +31,7 @@ void  vprintfmt(void (*putch)(int, void**), void **putdat, const char *NTS fmt, v
 #endif
 
 // lib/printf.c
-int    cprintf(const char * NTS fmt, ...);
+int    ( cprintf)(const char * NTS fmt, ...);
 int    vcprintf(const char * NTS fmt, va_list);
 
 // lib/sprintf.c
index dd42c41..265cf1f 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef ROS_INC_STRING_H
 #define ROS_INC_STRING_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 #define STRING char *NTS
 #define STRBUF(n) char *NT COUNT(n)
index 3dfa6ca..fd2c60f 100644 (file)
@@ -40,7 +40,7 @@
 #define ROS_INCLUDE_SYS_QUEUE_H
 
 //#include <machine/ansi.h>    /* for __offsetof */
-#include <arch/types.h>        /* for __offsetof */
+#include <ros/common.h>        /* for __offsetof */
 
 /*
  * This file defines four types of data structures: singly-linked lists,
diff --git a/kern/include/sys/types.h b/kern/include/sys/types.h
new file mode 100644 (file)
index 0000000..44fd3db
--- /dev/null
@@ -0,0 +1,5 @@
+/* GHETTO: To our grandchildren, we are sorry for this
+ * We do this since newlib has it's own stdint that conflicts with the kernel
+ * and roslib's types. */
+
+#include <arch/types.h>
index 5677a99..80ba8bc 100644 (file)
@@ -7,8 +7,8 @@
 #include <ros/syscall.h>
 #include <process.h>
 
-int32_t (SYNCHRONOUS syscall)(env_t* e, uint32_t num, uint32_t a1, uint32_t a2,
-                              uint32_t a3, uint32_t a4, uint32_t a5);
-int32_t syscall_async(env_t* e, syscall_req_t *syscall);
-int32_t process_generic_syscalls(env_t* e, uint32_t max);
+intreg_t (syscall)(env_t* e, uintreg_t num, uintreg_t a1, uintreg_t a2,
+                   uintreg_t a3, uintreg_t a4, uintreg_t a5);
+intreg_t syscall_async(env_t* e, syscall_req_t *syscall);
+intreg_t process_generic_syscalls(env_t* e, size_t max);
 #endif /* !ROS_KERN_SYSCALL_H */
index c3c5bbc..7b83224 100644 (file)
@@ -6,7 +6,7 @@
  * Someone else should actually make these useful on their own
  */
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 void test_ipi_sending(void);
 void test_pic_reception(void);
@@ -21,6 +21,8 @@ void test_pit(void);
 void test_smp_call_functions(void);
 void test_lapic_status_bit(void);
 void test_run_measurements(uint32_t job_num);
+void test_circ_buffer(void);
+void test_active_messages(void);
 
 struct trapframe_t;
 
index eaa6c63..0edd068 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef ROS_INC_TIMING_H
 #define ROS_INC_TIMING_H
 
-#include <arch/types.h>
+#include <ros/common.h>
 
 void udelay(uint64_t usec);
 
index 455bbb8..eec4b27 100644 (file)
@@ -6,23 +6,74 @@
 # error "This is an ROS kernel header; user programs should not #include it"
 #endif
 
+#include <arch/arch.h>
 #include <arch/mmu.h>
 #include <arch/trap.h>
 
 // func ptr for interrupt service routines
-typedef void (*poly_isr_t)(trapframe_t* tf, TV(t) data);
+typedef void ( *poly_isr_t)(trapframe_t* tf, TV(t) data);
 typedef void (*isr_t)(trapframe_t* tf, void * data);
 typedef struct InterruptHandler {
        poly_isr_t isr;
        TV(t) data;
 } handler_t;
 
+#ifdef __IVY__
+#pragma cilnoremove("iht_lock")
+extern spinlock_t iht_lock;
+#endif
+extern handler_t LCKD(&iht_lock) (CT(NUM_INTERRUPT_HANDLERS) RO interrupt_handlers)[];
+
 void idt_init(void);
-void register_interrupt_handler(handler_t (COUNT(256)table)[], uint8_t int_num,
-                                poly_isr_t handler, TV(t) data);
-void (IN_HANDLER print_trapframe)(trapframe_t *tf);
-void (IN_HANDLER page_fault_handler)(trapframe_t *tf);
+void
+register_interrupt_handler(handler_t SSOMELOCK (CT(NUM_INTERRUPT_HANDLERS)table)[],
+                           uint8_t int_num,
+                           poly_isr_t handler, TV(t) data);
+void ( print_trapframe)(trapframe_t *tf);
+void ( page_fault_handler)(trapframe_t *tf);
 
 void sysenter_init(void);
 extern void sysenter_handler();
+
+/* Active messages.  Each arch implements them in their own way.  Both should be
+ * guaranteeing in-order delivery.  Kept here in trap.h, since sparc is using
+ * trap.h for AMs
+ *
+ * These are different (for now) than the smp_calls in smp.h, since
+ * they will be executed immediately, and in the order in which they are sent.
+ * smp_calls are currently not run in order, and if they put things on the
+ * workqueue, they don't get run until smp_idle (for now).
+ *
+ * Also, a big difference is that smp_calls can use the same message (registered
+ * in the interrupt_handlers[] for x86) for every recipient, but the active
+ * messages require a unique message.  Also for now, but it might be like that
+ * for a while on x86. */
+
+typedef void (*amr_t)(trapframe_t* tf, uint32_t srcid,
+                      TV(a0t) a0, TV(a1t) a1, TV(a2t) a2);
+
+struct active_message
+{
+       uint32_t srcid;
+       amr_t pc;
+       TV(a0t) arg0;
+       TV(a1t) arg1;
+       TV(a2t) arg2;
+       uint32_t pad;
+};
+typedef struct active_message NTPTV(a0t) NTPTV(a1t) NTPTV(a2t) active_message_t;
+
+uint32_t send_active_message(uint32_t dst, amr_t pc,
+                             TV(a0t) arg0, TV(a1t) arg1, TV(a2t) arg2);
+
+/* Spins til the active message is sent.  Could block in the future. */
+static inline void
+send_active_msg_sync(uint32_t dst, amr_t pc,
+                     TV(a0t) arg0, TV(a1t) arg1, TV(a2t) arg2)
+{
+       while (send_active_message(dst, pc, arg0, arg1, arg2))
+               cpu_relax();
+       return;
+}
+
 #endif /* ROS_KERN_TRAP_H */
diff --git a/kern/include/types.h b/kern/include/types.h
new file mode 100644 (file)
index 0000000..fb343eb
--- /dev/null
@@ -0,0 +1 @@
+#include <
index 27ce98e..ebff971 100644 (file)
@@ -12,7 +12,7 @@
 #define ROS_KERN_WORKQUEUE_H
 
 #include <sys/queue.h>
-#include <arch/types.h>
+#include <ros/common.h>
 #include <env.h>
 
 typedef void (*func_t)(TV(t) data);
@@ -25,11 +25,11 @@ struct work {
 // TODO make these dynamic and hold more than 1.  might want better list macros.
 #define WORKQUEUE_ELEMENTS 1
 struct workqueue {
-       struct work TP(env_t *) statics[WORKQUEUE_ELEMENTS];
+       struct work TP(TV(t)) statics[WORKQUEUE_ELEMENTS];
 };
 
 void process_workqueue(void);
 // For now, the caller should free their struct work after this call
-int enqueue_work(struct workqueue *queue, struct work TP(env_t *) *job);
+int enqueue_work(struct workqueue TP(TV(t)) *queue, struct work TP(TV(t)) *job);
 
 #endif /* ROS_KERN_WORKQUEUE_H */
index fa62c72..46451d2 100644 (file)
@@ -1,8 +1,12 @@
 KERN_IVY_DIR = $(KERN_DIR)/ivy\r
 OBJDIRS += $(KERN_IVY_DIR)\r
 \r
-KERN_IVY_CFLAGS   := $(KERN_CFLAGS) --nodeputy\r
-KERN_IVY_SRCFILES := $(KERN_IVY_DIR)/deputy.c\r
+KERN_IVY_CFLAGS   := $(KERN_CFLAGS)\r
+ifeq ($(COMPILER),IVY)\r
+KERN_IVY_CFLAGS   += --nodeputy --nosharc\r
+endif\r
+\r
+KERN_IVY_SRCFILES := $(KERN_IVY_DIR)/deputy.c $(KERN_IVY_DIR)/sharc.c\r
 KERN_IVY_OBJFILES := $(patsubst $(KERN_IVY_DIR)/%.c, \\r
                                    $(OBJDIR)/$(KERN_IVY_DIR)/%.o, \\r
                                    $(KERN_IVY_SRCFILES))\r
index 9747f1f..6f09777 100644 (file)
@@ -1,3 +1,4 @@
+#ifdef __IVY__
 #include <stdio.h>
 #include <assert.h>
 #include <string.h>
 #define noreturn __attribute__((noreturn))
 #endif
 
+extern int __ivy_checking_on;
+
 asmlinkage
 void deputy_fail_mayreturn(const char *check, const char *text,
                            __LOCATION__FORMALS) {
+       int old;
+       if (!__ivy_checking_on) return;
+       old = __ivy_checking_on;
+       __ivy_checking_on = 0;
     cprintf("%s:%d: %s: Assertion failed in %s: %s\n",
             __LOCATION__ACTUALS, check, text);
+       __ivy_checking_on = old;
 /*
     dump_stack();
 */
@@ -36,7 +44,9 @@ void deputy_fail_mayreturn(const char *check, const char *text,
 
 asmlinkage noreturn
 void deputy_fail_noreturn_fast(void) {
+       __ivy_checking_on = 0;
     panic("Deputy assertion failure\n");
+       __ivy_checking_on = 1;
 }
 
 int deputy_strlen(const char *str) {
@@ -86,7 +96,10 @@ int deputy_findnull(const void *e, unsigned int bytes) {
             NULLCHECK(long);
             break;
         default:
+                       if (!__ivy_checking_on) return length;
+                       __ivy_checking_on = 0;
             cprintf("Invalid byte size for nullcheck.\n");
+                       __ivy_checking_on = 1;
             break;
     }
 
@@ -98,14 +111,4 @@ void *__deputy_memset(void *s, int c, unsigned int n) {
   return memset(s, c, n);
 }
 
-void __ivy_handler_atomic_entry() __attribute__((weak));
-void __ivy_handler_atomic_entry() {return;}
-
-void __ivy_handler_atomic_exit() __attribute__((weak));
-void __ivy_handler_atomic_exit() {return;}
-
-void __ivy_handler_atomic_locks_entry(unsigned int n, ...) __attribute__((weak));
-void __ivy_handler_atomic_locks_entry(unsigned int n, ...) {return;}
-
-void __ivy_handler_atomic_locks_exit(unsigned int n, ...) __attribute__((weak));
-void __ivy_handler_atomic_locks_exit(unsigned int n, ...) {return;}
+#endif // __IVY__
diff --git a/kern/ivy/sharc.c b/kern/ivy/sharc.c
new file mode 100644 (file)
index 0000000..4f707ef
--- /dev/null
@@ -0,0 +1,28 @@
+#ifdef __IVY__
+#include <assert.h>
+
+int __ivy_checking_on = 1;
+
+void __sharc_lock_error(const void *lck, const void *what,
+                        unsigned int sz, char *msg)
+{
+       int old;
+       if (!__ivy_checking_on) return;
+       old = __ivy_checking_on;
+       __ivy_checking_on = 0;
+       warn("Ivy: The lock %p was not held for (%p,%d): %s\n",
+          lck, what, sz, msg);
+       __ivy_checking_on = old;
+}
+
+void __sharc_lock_coerce_error(void *dstlck, void *srclck, char *msg)
+{
+       int old;
+       if (!__ivy_checking_on) return;
+       old = __ivy_checking_on;
+       __ivy_checking_on = 0;
+       warn("Ivy: The locks in the coercion at %s must be the same\n", msg);
+       __ivy_checking_on = old;
+}
+
+#endif // __IVY__
index a556e52..48ca3e4 100644 (file)
@@ -49,6 +49,7 @@ KERN_APPFILES := \
                  $(USER_APPS_ROSLIB_DIR)/null \
                  $(USER_APPS_ROSLIB_DIR)/spawn \
                  $(USER_APPS_ROSLIB_DIR)/hello \
+                 $(USER_APPS_ROSLIB_DIR)/mhello \
                  $(USER_APPS_ROSLIB_DIR)/measurements \
                  $(USER_APPS_PARLIB_DIR)/draw_nanwan_standalone \
                  $(USER_APPS_PARLIB_DIR)/channel_test_client \
index b1d705e..a88b7ba 100644 (file)
@@ -1,3 +1,7 @@
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <arch/arch.h>
 
 #include <atomic.h>
@@ -33,7 +37,7 @@ int commit_checklist_wait(checklist_t* list, checklist_mask_t* mask)
 int commit_checklist_nowait(checklist_t* list, checklist_mask_t* mask)
 {
        int e = 0;
-       if (e = commit_checklist_wait(list, mask))
+       if ((e = commit_checklist_wait(list, mask)))
                return e;
        // give up the lock, since we won't wait for completion
        spin_unlock_irqsave(&list->lock);
index 107271e..5eb1161 100644 (file)
@@ -5,7 +5,11 @@
  * Kevin Klues <klueska@cs.berkeley.edu>    
  */
 
-#include <arch/types.h>
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
+#include <ros/common.h>
 #include <arch/mmu.h>
 #include <colored_caches.h>
 #include <stdio.h>
index 4413a65..d37d1a1 100644 (file)
@@ -1,5 +1,9 @@
 /* See COPYRIGHT for copyright information. */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <arch/arch.h>
 #include <arch/mmu.h>
 #include <elf.h>
@@ -25,7 +29,7 @@ atomic_t num_envs;
 // This lets the kernel know what process is running on the core it traps into.
 // A lot of the Env business, including this and its usage, will change when we
 // redesign the env as a multi-process.
-env_t* curenvs[MAX_NUM_CPUS] = {[0 ... (MAX_NUM_CPUS-1)] NULL};
+env_t* (RO curenvs)[MAX_NUM_CPUS] = {[0 ... (MAX_NUM_CPUS-1)] NULL};
 
 #define ENVGENSHIFT    12              // >= LOGNENV
 
@@ -87,15 +91,22 @@ env_init(void)
        int i;
 
        schedule_init();
+       // core 0 is not idle, all others are (for now)
+       spin_lock(&idle_lock);
+       num_idlecores = num_cpus - 1;
+       for (i = 0; i < num_idlecores; i++)
+               idlecoremap[i] = i + 1;
+       spin_unlock(&idle_lock);
        atomic_init(&num_envs, 0);
        TAILQ_INIT(&proc_freelist);
        assert(envs != NULL);
-       for (i = NENV-1; i >= 0; i--) { TRUSTEDBLOCK // asw ivy workaround
+       for (i = NENV-1; i >= 0; i--) {
                // these should already be set from when i memset'd the array to 0
                envs[i].state = ENV_FREE;
                envs[i].env_id = 0;
                TAILQ_INSERT_HEAD(&proc_freelist, &envs[i], proc_link);
        }
+
 }
 
 //
@@ -159,7 +170,8 @@ WRITES(e->env_pgdir, e->env_cr3, e->env_procinfo, e->env_procdata)
        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)
+               if(page_insert(e->env_pgdir, pginfo[i], (void*SNT)(UINFO + i*PGSIZE),
+                              PTE_USER_RO) < 0)
                        goto env_setup_vm_error;
        }
 
@@ -170,7 +182,8 @@ WRITES(e->env_pgdir, e->env_cr3, e->env_procinfo, e->env_procdata)
        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)
+               if(page_insert(e->env_pgdir, pgdata[i], (void*SNT)(UDATA + i*PGSIZE),
+                              PTE_USER_RW) < 0)
                        goto env_setup_vm_error;
        }
 
@@ -265,11 +278,17 @@ env_alloc(env_t **newenv_store, envid_t parent_id)
        e->env_runs = 0;
        e->env_refcnt = 1;
        e->env_flags = 0;
-
+       e->env_entry = 0; // cheating.  this really gets set in load_icode
+#ifdef __SHARC__
+       /* init SharC state */
+       sharC_env_init(&e->sharC_env);
+#endif
+       e->num_vcores = 0;
+       memset(&e->vcoremap, 0, sizeof(e->vcoremap));
 
        memset(&e->env_ancillary_state, 0, sizeof(e->env_ancillary_state));
        memset(&e->env_tf, 0, sizeof(e->env_tf));
-       env_init_trapframe(e);
+       proc_init_trapframe(&e->env_tf);
 
        /*
         * Initialize the contents of the e->env_procinfo structure
@@ -401,7 +420,8 @@ load_icode(env_t *SAFE e, uint8_t *COUNT(size) binary, size_t size)
                memset((void*)phdr.p_va + phdr.p_filesz, 0, phdr.p_memsz - phdr.p_filesz);
        }}
 
-       env_set_program_counter(e, elfhdr.e_entry);
+       proc_set_program_counter(&e->env_tf, elfhdr.e_entry);
+       e->env_entry = elfhdr.e_entry;
 
        // Now map one page for the program's initial stack
        // at virtual address USTACKTOP - PGSIZE.
@@ -455,21 +475,43 @@ env_free(env_t *e)
        TAILQ_INSERT_HEAD(&proc_freelist, e, proc_link);
 }
 
+
+#define PER_CPU_THING(type,name)\
+type SLOCKED(name##_lock) * RWPROTECT name;\
+type SLOCKED(name##_lock) *\
+(get_per_cpu_##name)()\
+{\
+       { R_PERMITTED(global(name))\
+               return &name[core_id()];\
+       }\
+}
+
+
 /* This is the top-half of an interrupt handler, where the bottom half is
  * proc_run (which never returns).  Just add it to the delayed work queue,
  * which (incidentally) can only hold one item at this point.
  *
  * Note this is rather old, and meant to run a RUNNABLE_S on a worker core.
  */
-void run_env_handler(trapframe_t *tf, env_t *data)
+#ifdef __IVY__
+void run_env_handler(trapframe_t *tf, env_t * data)
+#else
+void run_env_handler(trapframe_t *tf, void * data)
+#endif
 {
        assert(data);
        struct work TP(env_t *) job;
-       struct workqueue *workqueue = &per_cpu_info[core_id()].workqueue;
-       { //TRUSTEDBLOCK TODO: how do we make this func_t cast work?
+       struct workqueue TP(env_t *) *CT(1) workqueue =
+           TC(&per_cpu_info[core_id()].workqueue);
+       // this doesn't work, and making it a TP(env_t) is wrong
+       // zra: When you want to use other types, let me know, and I can help
+    // make something that Ivy is happy with. 
+#ifdef __IVY__
        job.func = proc_run;
+#else
+       job.func = (func_t)proc_run;
+#endif
        job.data = data;
-       }
        if (enqueue_work(workqueue, &job))
                panic("Failed to enqueue work!");
 }
index 5aff619..04b009d 100644 (file)
@@ -1,5 +1,9 @@
 /* See COPYRIGHT for copyright information. */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #ifdef __BSD_ON_CORE_0__
 #include Everything For Free -- It just works!!
 #else
@@ -21,6 +25,7 @@
 #include <syscall.h>
 #include <kclock.h>
 #include <manager.h>
+#include <testing.h>
 
 #include <arch/rl8168.h>
 #include <arch/ne2k.h>
@@ -43,11 +48,15 @@ void kernel_init(multiboot_info_t *mboot_info)
 
        print_cpuinfo();
 
-       // zra: using KADDR macro gives a runtime warning, but it is possibly more
-    //      clear what's going on this way?
+       // Old way, pre Zach's Ivy annotations
        //multiboot_detect_memory((multiboot_info_t*)((uint32_t)mboot_info + KERNBASE));
        //multiboot_print_memory_map((multiboot_info_t*)((uint32_t)mboot_info + KERNBASE));
-       multiboot_detect_memory((multiboot_info_t*COUNT(1))KADDR((physaddr_t)mboot_info));
+       
+       // Paul: Can't use KADDR as arg to multiboot_detect_memory
+       //  since multiboot_detect_memory is what sets npages. 
+       //  Must simulate KADDR macro (ugly).
+       multiboot_detect_memory((multiboot_info_t*SAFE)(void*TRUSTED)((physaddr_t)mboot_info + KERNBASE));
+       
        multiboot_print_memory_map((multiboot_info_t*COUNT(1))KADDR((physaddr_t)mboot_info));
 
        vm_init();
@@ -55,27 +64,39 @@ void kernel_init(multiboot_info_t *mboot_info)
        cache_init();
        page_init();
        page_check();
-
-       env_init();
+       //test_page_coloring();
 
        idt_init();
        sysenter_init();
        timer_init();
        
+       // @todo: Add an arch specific init? This is ugly
        #ifdef __i386__
        mptables_parse();
        pci_init();
        ioapic_init(); // MUST BE AFTER PCI/ISA INIT!
        #endif // __i386__
-       
-       
+               
        // this returns when all other cores are done and ready to receive IPIs
        smp_boot();
+       env_init();
        
-       #ifdef __i386__
+
+       /* EXPERIMENTAL NETWORK FUNCTIONALITY
+        * To enable, define __NETWORK__ in your Makelocal
+        * If enabled, will load the rl8168 driver (if device exists)
+        * and will a boot into userland matrix, so remote syscalls can be performed.
+        * If in simulation, will do some debugging information with the ne2k device
+        *
+        * Note: If you use this, you should also define the mac address of the 
+        * teathered machine via USER_MAC_ADDRESS in Makelocal.
+        *
+        * Additionally, you should have a look at the syscall server in the tools directory
+        */
+       #ifdef __NETWORK__
        rl8168_init();          
        ne2k_init();
-       #endif // __i386__
+       #endif // __NETWORK__
 
        manager();
 }
index b177b25..16629b7 100644 (file)
@@ -4,6 +4,10 @@
  * See LICENSE for details.
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <kfs.h>
 #include <string.h>
 #include <assert.h>
@@ -25,6 +29,7 @@ DECL_PROG(roslib_fptest);
 DECL_PROG(roslib_null);
 DECL_PROG(roslib_spawn);
 DECL_PROG(roslib_hello);
+DECL_PROG(roslib_mhello);
 DECL_PROG(roslib_measurements);
 DECL_PROG(parlib_draw_nanwan_standalone);
 DECL_PROG(parlib_channel_test_client);
@@ -38,7 +43,8 @@ struct kfs_entry kfs[MAX_KFS_FILES] = {
        KFS_ENTRY(roslib_null)
        KFS_ENTRY(roslib_spawn)
        KFS_ENTRY(roslib_hello)
-        KFS_ENTRY(roslib_measurements)
+       KFS_ENTRY(roslib_mhello)
+       KFS_ENTRY(roslib_measurements)
        KFS_ENTRY(parlib_draw_nanwan_standalone)
        KFS_ENTRY(parlib_channel_test_client)
        KFS_ENTRY(parlib_channel_test_server)
@@ -60,7 +66,7 @@ ssize_t kfs_lookup_path(char* path)
  * This should take a real inode or something to point to the real location,
  * and env_create shouldn't assume everything is contiguous
  */
-struct proc *kfs_proc_create(size_t kfs_inode)
+struct proc *kfs_proc_create(int kfs_inode)
 {
        if (kfs_inode < 0 || kfs_inode >= MAX_KFS_FILES)
                panic("Invalid kfs_inode.  Check you error codes!");
index d5ce980..ccb6227 100644 (file)
@@ -5,7 +5,11 @@
  * Kevin Klues <klueska@cs.berkeley.edu>    
  */
 
-#include <arch/types.h>
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
+#include <ros/common.h>
 #include <ros/error.h>
 #include <pmap.h>
 #include <kmalloc.h>
@@ -90,7 +94,6 @@ void kmalloc_init()
 
 void* kmalloc(size_t size, int flags) 
 {
-       // ****** NEXT CONDITION MUST BE MERGED INTO MASTER!!! -PAUL *******
        if (size == 0)
                return NULL;
 
@@ -119,10 +122,10 @@ void* kmalloc(size_t size, int flags)
        for(int i=0; i<npages; i++) {
                page_t* page;
                page_alloc_specific(&page, first+i);
-               // NEXT LINE MUST BE MERGED INTO MASTER (Also, Kevin doesn't like.)
+               // Kevin doesn't like this next line 
                page_incref(page); 
                page->num_cons_links = npages-i;
-               LIST_INSERT_HEAD(&pages_list, page, global_link);
+               LIST_INSERT_HEAD(&pages_list, page, page_link);
                kmallocdebug("mallocing page: %u\n", first+i);
                kmallocdebug("at addr: %p\n", ppn2kva(first+i));
        }
@@ -138,7 +141,7 @@ void kfree(void *addr)
        kmallocdebug("getting page: %u\n", page2ppn(page));
        for(int i=0; i<num_links; i++) {
                page_t* p = ppn2page((page2ppn(page) + i));
-               LIST_REMOVE(p, global_link);
+               LIST_REMOVE(p, page_link);
                page_free(p);
                kmallocdebug("freeing page: %d\n", page2ppn(p));
        }
index 5ca0940..2c89a9e 100644 (file)
@@ -4,7 +4,11 @@
  * See LICENSE for details.
  */
 
-#include <arch/types.h>
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
+#include <ros/common.h>
 #include <smp.h>
 
 #include <assert.h>
@@ -16,6 +20,7 @@
 #include <testing.h>
 #include <kfs.h>
 #include <stdio.h>
+#include <timing.h>
 
 /*
  * Currently, if you leave this function by way of proc_run (process_workqueue
 void manager(void)
 {
        static uint8_t progress = 0;
-       env_t *envs[256];
-       
+
+       struct proc *envs[256];
+       struct proc *p ;
+
+       // 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:
+                       // Here's how to do a multicored/parallel process:
+                       p = kfs_proc_create(kfs_lookup_path("roslib_mhello"));
+                       // being proper and all:
+                       proc_set_state(p, PROC_RUNNABLE_S);
+                       proc_set_state(p, PROC_RUNNING_S);
+                       proc_set_state(p, PROC_RUNNABLE_M);
+       
+                       // set vcoremap with dispatch plan.  usually done by schedule()
+                       spin_lock_irqsave(&p->proc_lock);
+                       p->num_vcores = 5; // assuming 5 are free, this is just an example
+                       spin_lock(&idle_lock); // need to grab the cores
+                       for (int i = 0; i < 5; i++) {
+                               // grab the last one on the list
+                               p->vcoremap[i] = idlecoremap[num_idlecores-1];
+                               num_idlecores--;
+                       }
+                       spin_unlock(&idle_lock);
+                       spin_unlock_irqsave(&p->proc_lock);
+                       proc_run(p);
+                       udelay(5000000);
+                       printk("Killing p\n");
+                       proc_destroy(p);
+                       printk("Killed p\n");
+                       udelay(1000000);
+                       panic("This is okay");
+                       break;
+               case 1:
                        envs[0] = kfs_proc_create(kfs_lookup_path("roslib_hello"));
                        proc_set_state(envs[0], PROC_RUNNABLE_S);
                        proc_run(envs[0]);
                        break;
        #ifdef __i386__
-               case 1:
+               case 2:
                        panic("Do not panic");
                        envs[0] = kfs_proc_create(kfs_lookup_path("parlib_channel_test_client"));
                        envs[1] = kfs_proc_create(kfs_lookup_path("parlib_channel_test_server"));
                        smp_call_function_single(1, run_env_handler, envs[0], 0);
                        smp_call_function_single(2, run_env_handler, envs[1], 0);
                        break;
-               case 2:
                case 3:
        #else // sparc
-               case 1:
+               case 2:
                        panic("Do not panic");
                        envs[0] = kfs_proc_create(kfs_lookup_path("roslib_proctests"));
                        envs[1] = kfs_proc_create(kfs_lookup_path("roslib_proctests"));
@@ -63,7 +101,7 @@ void manager(void)
                        envs[6] = kfs_proc_create(kfs_lookup_path("roslib_null"));
                        proc_run(envs[0]);
                        break;
-               case 2:
+               case 3:
                        #if 0
                        // reminder of how to spawn remotely
                        for (int i = 0; i < 8; i++) {
@@ -73,7 +111,6 @@ void manager(void)
                        }
                        process_workqueue();
                        #endif
-               case 3:
        #endif
 
                #if 0
@@ -124,4 +161,3 @@ void manager(void)
        */
        return;
 }
-
index 3937440..b1edbcd 100644 (file)
@@ -1,6 +1,10 @@
 // Simple command-line kernel monitor useful for
 // controlling the kernel and exploring the system interactively.
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <arch/arch.h>
 #include <stab.h>
 #include <smp.h>
@@ -41,6 +45,7 @@ static command_t commands[] = {
        { "kfs_ls", "List files in KFS", mon_kfs_ls},
        { "kfs_run", "Create and run a program from KFS", mon_kfs_run},
        { "manager", "Run the manager", mon_manager},
+       { "procinfo", "Show information about processes", mon_procinfo},
 };
 #define NCOMMANDS (sizeof(commands)/sizeof(commands[0]))
 
@@ -174,8 +179,6 @@ int mon_setmapperm(int argc, char **argv, trapframe_t *tf)
 
 int mon_cpuinfo(int argc, char **argv, trapframe_t *tf)
 {
-       extern uint8_t num_cpus;
-
        cprintf("Number of CPUs detected: %d\n", num_cpus);
        cprintf("Calling CPU's ID: 0x%08x\n", core_id());
 
@@ -261,6 +264,23 @@ int mon_kfs_run(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
        return 0;
 }
 
+int mon_procinfo(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
+{
+       if (argc != 2) {
+               printk("Usage: procinfo OPTION\n");
+               printk("\tidle_cores: show idle core map\n");
+               printk("\trunnable: show proc_runnablelist\n");
+               return 1;
+       }
+       if (!strcmp(argv[1], "idle_cores"))
+               print_idlecoremap();
+       else if (!strcmp(argv[1], "runnable"))
+               dump_proclist(&proc_runnablelist);
+       else
+               printk("Bad option\n");
+       return 0;
+}
+
 /***** Kernel monitor command interpreter *****/
 
 #define WHITESPACE "\t\r\n "
index f6e937f..65a2034 100644 (file)
@@ -1,5 +1,9 @@
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <multiboot.h>
-#include <arch/types.h>
+#include <ros/common.h>
 #include <arch/mmu.h>
 #include <arch/arch.h>
 #include <ros/memlayout.h>
index 93cd9c8..0eb6da4 100644 (file)
@@ -5,6 +5,10 @@
  * Kevin Klues <klueska@cs.berkeley.edu>    
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <sys/queue.h>
 #include <page_alloc.h>
 #include <pmap.h>
@@ -21,6 +25,30 @@ static void page_clear(page_t *SAFE page)
        memset(page, 0, sizeof(page_t));
 }
 
+error_t page_alloc_from_color_range(page_t** page,  
+                                    uint16_t base_color,
+                                    uint16_t range) {
+
+       // Find first available color with pages available
+    //  in the proper range
+       int i = base_color;
+       spin_lock_irqsave(&colored_page_free_list_lock);
+       for(i; i<(base_color+range); i++) {
+               if(!LIST_EMPTY(&colored_page_free_list[i]))
+                       break;
+       }
+       // Alocate a page from that color
+       if(i < (base_color+range)) {
+               *page = LIST_FIRST(&colored_page_free_list[i]);
+               LIST_REMOVE(*page, page_link);
+               page_clear(*page);
+               spin_unlock_irqsave(&colored_page_free_list_lock);
+               return ESUCCESS;
+       }
+       spin_unlock_irqsave(&colored_page_free_list_lock);
+       return -ENOMEM;
+}
+
 /**
  * @brief Allocates a physical page from a pool of unused physical memory
  *
@@ -35,15 +63,7 @@ static void page_clear(page_t *SAFE page)
  */
 error_t page_alloc(page_t** page) 
 {
-       //TODO: Put a lock around this
-       if(!LIST_EMPTY(&page_free_list)) {
-               *page = LIST_FIRST(&page_free_list);
-               LIST_REMOVE(*page, global_link);
-               REMOVE_CACHE_COLORING_PAGE_FROM_FREE_LISTS(page);
-               page_clear(*page);
-               return ESUCCESS;
-       }
-       return -ENOMEM;
+       return page_alloc_from_color_range(page, 0, llc_num_colors);
 }
 
 /*
@@ -78,7 +98,38 @@ error_t page_alloc(page_t** page)
  *      return -ENOMEM;
  * }
  */
-DECLARE_CACHE_COLORED_PAGE_ALLOC_FUNCTIONS();
+error_t l1_page_alloc(page_t** page, size_t color)
+{
+       if(available_caches.l1)
+       {
+               uint16_t range = llc_num_colors / get_cache_num_page_colors(&l1);
+               uint16_t base_color = color*range;
+               return page_alloc_from_color_range(page, base_color, range);
+       }
+       return -ENOCACHE;
+}
+
+error_t l2_page_alloc(page_t** page, size_t color)
+{
+       if(available_caches.l2)
+       {
+               uint16_t range = llc_num_colors / get_cache_num_page_colors(&l2);
+               uint16_t base_color = color*range;
+               return page_alloc_from_color_range(page, base_color, range);
+       }
+       return -ENOCACHE;
+}
+
+error_t l3_page_alloc(page_t** page, size_t color)
+{
+       if(available_caches.l3)
+       {
+               uint16_t range = llc_num_colors / get_cache_num_page_colors(&l3);
+               uint16_t base_color = color*range;
+               return page_alloc_from_color_range(page, base_color, range);
+       }
+       return -ENOCACHE;
+}
 
 /*
  * Allocates a specific physical page.
@@ -95,13 +146,14 @@ DECLARE_CACHE_COLORED_PAGE_ALLOC_FUNCTIONS();
  */
 error_t page_alloc_specific(page_t** page, size_t ppn)
 {
-       //TODO: Put a lock around this
+       spin_lock_irqsave(&colored_page_free_list_lock);
        page_t* sp_page = ppn2page(ppn);
        if( sp_page->page_ref != 0 )
                return -ENOMEM;
        *page = sp_page;
-       LIST_REMOVE(*page, global_link);
-       REMOVE_CACHE_COLORING_PAGE_FROM_FREE_LISTS(page);
+       LIST_REMOVE(*page, page_link);
+       spin_unlock_irqsave(&colored_page_free_list_lock);
+
        page_clear(*page);
        return 0;
 }
@@ -114,8 +166,16 @@ error_t page_free(page_t* page)
 {
        //TODO: Put a lock around this
        page_clear(page);
-       LIST_INSERT_HEAD(&page_free_list, page, global_link);
-       INSERT_CACHE_COLORING_PAGE_ONTO_FREE_LISTS(page);       
+       cache_t* llc = available_caches.llc;
+
+       spin_lock_irqsave(&colored_page_free_list_lock);
+       LIST_INSERT_HEAD(
+          &(colored_page_free_list[get_page_color(page2ppn(page), llc)]),
+          page,
+          page_link
+       );
+       spin_unlock_irqsave(&colored_page_free_list_lock);
+
        return ESUCCESS;
 }
 
@@ -123,7 +183,6 @@ error_t page_free(page_t* page)
  * Check if a page with the given pyhysical page # is free
  */
 int page_is_free(size_t ppn) {
-       //TODO: Put a lock around this
        page_t* page = ppn2page(ppn);
        if( page->page_ref == 0 )
                return TRUE;
index bada5d0..5cb5939 100644 (file)
  * @author Barret Rhoden <brho@cs.berkeley.edu>
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <arch/arch.h>
 #include <arch/mmu.h>
 
@@ -31,6 +35,9 @@
  */
 static void *DANGEROUS user_mem_check_addr;
 
+volatile uint32_t vpt_lock = 0;
+volatile uint32_t vpd_lock = 0;
+
 /**
  * @brief Initialize the array of physical pages and memory free list.
  *
@@ -46,8 +53,7 @@ void page_init(void)
         * 'npages' equals the number of physical pages in memory.
         * round up to the nearest page
         */
-       size_t page_array_size = ROUNDUP(npages*sizeof(page_t), PGSIZE);
-       pages = (page_t*)boot_alloc(page_array_size, PGSIZE);
+       pages = (page_t*)boot_alloc(npages*sizeof(page_t), PGSIZE);
        memset(pages, 0, npages*sizeof(page_t));
 
        /*
@@ -232,7 +238,9 @@ void tlb_invalidate(pde_t *pgdir, void *va)
  * @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.
+ * 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:
@@ -260,7 +268,7 @@ void* user_mem_check(env_t *env, const void *DANGEROUS va, size_t len, int perm)
        // kernel is uninterruptible
        void *DANGEROUS start, *DANGEROUS end;
        size_t num_pages, i;
-       pte_t *pte;
+       int page_perms = 0;
 
        perm |= PTE_P;
        start = ROUNDDOWN((void*DANGEROUS)va, PGSIZE);
@@ -271,9 +279,9 @@ void* user_mem_check(env_t *env, const void *DANGEROUS va, size_t len, int perm)
        }
        num_pages = PPN(end - start);
        for (i = 0; i < num_pages; i++, start += PGSIZE) {
-               pte = pgdir_walk(env->env_pgdir, start, 0);
+               page_perms = get_va_perms(env->env_pgdir, start);
                // ensures the bits we want on are turned on.  if not, error out
-               if ( !pte || ((*pte & perm) != perm) ) {
+               if ((page_perms & perm) != perm) {
                        if (i == 0)
                                user_mem_check_addr = (void*DANGEROUS)va;
                        else
@@ -306,20 +314,23 @@ void* user_mem_check(env_t *env, const void *DANGEROUS va, size_t len, int perm)
  * @return LEN the length of the new buffer copied into 'dst'
  */
 size_t
-user_mem_strlcpy(env_t *env, char *dst, const char *DANGEROUS va,
+user_mem_strlcpy(env_t *env, char *_dst, const char *DANGEROUS va,
                  size_t _len, int perm)
 {
        const char *DANGEROUS src = va;
        size_t len = _len;
-       char *NT COUNT(_len-1) dst_in = dst;
+       char *NT COUNT(_len-1) dst_in = _dst;
+       char *NT BND(_dst,_dst + _len - 1) dst = _dst;
 
        if (len > 0) {
                while (1) {
                        char *c;
+                       // what if len was 1?
                        if (--len <= 0) break;
                        c = user_mem_check(env, src, 1, perm);
                        if (!c) break;
                        if (*c == '\0') break;
+                       // TODO: ivy bitches about this
                        *dst++ = *c;
                        src++;
                }
@@ -416,3 +427,15 @@ error_t memcpy_from_user(env_t* env, void* COUNT(len) dest,
        return ESUCCESS;
 }
 
+/* mmap2() semantics on the offset */
+void *mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags, int fd,
+           size_t offset)
+{
+       if (fd || offset) {
+               printk("[kernel] mmap() does not support files yet.\n");
+               return (void*SAFE)TC(-1);
+       }
+       void *tmp = get_free_va_range(p->env_pgdir, addr, len);
+       printk("tmp = 0x%08x\n", tmp);
+       return 0;
+}
index e870dca..4f4730a 100644 (file)
@@ -1,8 +1,12 @@
 // Simple implementation of cprintf console output for the kernel,
 // based on printfmt() and the kernel console's cputchar().
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <arch/arch.h>
-#include <arch/types.h>
+#include <ros/common.h>
 
 #include <atomic.h>
 #include <stdio.h>
@@ -48,7 +52,11 @@ int vcprintf(const char *fmt, va_list ap)
        spin_lock_irqsave(&output_lock);
 
        // do the buffered printf
+       #ifdef __DEPUTY__
        vprintfmt(buffered_putch, &cntp, fmt, ap);
+       #else
+       vprintfmt((void*)buffered_putch, (void*)&cntp, fmt, ap);
+       #endif
 
        // write out remaining chars in the buffer
        buffered_putch(-1,&cntp);
index 5d4fc83..030df80 100644 (file)
@@ -2,7 +2,11 @@
 // used in common by printf, sprintf, fprintf, etc.
 // This code is also used by both the kernel and user programs.
 
-#include <arch/types.h>
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
+#include <ros/common.h>
 #include <ros/error.h>
 #include <stdio.h>
 #include <string.h>
@@ -279,7 +283,11 @@ int vsnprintf(char *buf, int n, const char *fmt, va_list ap)
        b.buf = buf;
 
        // print the string to the buffer
-       vprintfmt(sprintputch, (sprintbuf_t *NONNULL*NONNULL)&bp, fmt, ap);
+       #ifdef __DEPUTY__
+       vprintfmt((void*)sprintputch, (sprintbuf_t *NONNULL*NONNULL)&bp, fmt, ap);
+       #else
+       vprintfmt((void*)sprintputch, (void*)&bp, fmt, ap);
+       #endif
 
        // null terminate the buffer
        *b.buf = '\0';
index 616aa64..b7071f8 100644 (file)
@@ -4,6 +4,11 @@
  * See LICENSE for details.
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
+#include <arch/arch.h>
 #include <process.h>
 #include <atomic.h>
 #include <smp.h>
 #include <manager.h>
 #include <stdio.h>
 #include <assert.h>
+#include <timing.h>
 #include <sys/queue.h>
 
+/* Process Lists */
 struct proc_list proc_freelist = TAILQ_HEAD_INITIALIZER(proc_freelist);
 spinlock_t freelist_lock = 0;
 struct proc_list proc_runnablelist = TAILQ_HEAD_INITIALIZER(proc_runnablelist);
 spinlock_t runnablelist_lock = 0;
 
+/* Tracks which cores are idle, similar to the vcoremap.  Each value is the
+ * physical coreid of an unallocated core. */
+spinlock_t idle_lock = 0;
+uint32_t LCKD(&idle_lock) (RO idlecoremap)[MAX_NUM_CPUS];
+uint32_t LCKD(&idle_lock) num_idlecores = 0;
+
 /*
  * While this could be done with just an assignment, this gives us the
  * opportunity to check for bad transitions.  Might compile these out later, so
@@ -112,37 +125,63 @@ void proc_run(struct proc *p)
                        // There should be no core cleanup to do (like decref).
                        assert(current != p);
                        // if we're a worker core, smp_idle, o/w return
-                       // TODO considering encapsulating this block (core_id too)
-                       if (core_id())
+                       if (!management_core())
                                smp_idle(); // this never returns
                        return;
                case (PROC_RUNNABLE_S):
                        proc_set_state(p, PROC_RUNNING_S);
+                       // We will want to know where this process is running, even if it is
+                       // only in RUNNING_S.  can use the vcoremap, which makes death easy.
+                       // we may need the pcoremap entry to mark it as a RUNNING_S core, or
+                       // else update it here. (TODO) (PCORE)
+                       p->num_vcores = 0;
+                       p->vcoremap[0] = core_id();
                        spin_unlock_irqsave(&p->proc_lock);
                        // This normally doesn't return, but might error out in the future.
                        proc_startcore(p, &p->env_tf);
                        break;
                case (PROC_RUNNABLE_M):
-                       // BIG TODO: do this.
-                       // Check for how we're supposed to dispatch this
-                       // Update core map or whatever with what we're about to do
-
+                       proc_set_state(p, PROC_RUNNING_M);
+                       /* vcoremap[i] holds the coreid of the physical core allocated to
+                        * this process.  It is set outside proc_run.  For the active
+                        * message, a0 = struct proc*, a1 = struct trapframe*.   */
+                       if (p->num_vcores) {
+                               // TODO: handle silly state (HSS)
+                               // set virtual core 0 to run the main context
+#ifdef __IVY__
+                               send_active_msg_sync(p->vcoremap[0], __startcore, p,
+                                                    &p->env_tf, (void *SNT)0);
+#else
+                               send_active_msg_sync(p->vcoremap[0], (void *)__startcore,
+                                                    (void *)p, (void *)&p->env_tf, 0);
+#endif
+                               /* handle the others.  note the sync message will spin until
+                                * there is a free active message slot, which could lock up the
+                                * system.  think about this. (TODO) */
+                               for (int i = 1; i < p->num_vcores; i++)
+#ifdef __IVY__
+                                       send_active_msg_sync(p->vcoremap[i], __startcore,
+                                                            p, (trapframe_t *CT(1))NULL, (void *SNT)i);
+#else
+                                       send_active_msg_sync(p->vcoremap[i], (void *)__startcore,
+                                                            (void *)p, (void *)0, (void *)i);
+#endif
+                       }
                        /* There a subtle (attempted) race avoidance here.  proc_startcore
-                        * can handle a death IPI, but we can't have the startcore come
-                        * after the death IPI.  Otherwise, it would look like a new
-                        * process.  So we hold the lock to make sure our IPI went out
-                        * before a possible death IPI.  We don't IPI ourselves, since we
-                        * need to let go of the lock.  This could change if we
-                        * process_workqueue in the interrupt handler path and do something
-                        * like light kernel threading, which ties into state bundling.
-                        * Also, we may never allow proc_run to run on a target/worker core.
-                        */
-                       // Send IPIs to everyone else involved
+                        * can handle a death message, but we can't have the startcore come
+                        * after the death message.  Otherwise, it would look like a new
+                        * process.  So we hold the lock to make sure our message went out
+                        * before a possible death message.
+                        * - Likewise, we need interrupts to be disabled, in case one of the
+                        *   messages was for us, and reenable them after letting go of the
+                        *   lock.  This is done by spin_lock_irqsave, so be careful if you
+                        *   change this.
+                        * - This can also be done far more intelligently / efficiently,
+                        *   like skipping in case it's busy and coming back later.
+                        * - Note there is no guarantee this core's interrupts were on, so
+                        *   it may not get the message for a while... */
                        spin_unlock_irqsave(&p->proc_lock);
-                       // if (am_involved)
-                       //      proc_startcore(p, &appropriate_trapframe);
-                       // if not, need to make sure we don't return to the process's core 0
-                       panic("Unimplemented");
+                       break;
                default:
                        spin_unlock_irqsave(&p->proc_lock);
                        panic("Invalid process state in proc_run()!!");
@@ -182,8 +221,10 @@ void proc_run(struct proc *p)
  * some "bundling" code.
  */
 void proc_startcore(struct proc *p, trapframe_t *tf) {
-       // TODO it's possible to be DYING, but it's a rare race.  remove this soon.
-       assert(p->state & (PROC_RUNNING_S | PROC_RUNNING_M));
+       // it's possible to be DYING, but it's a rare race.
+       //if (p->state & (PROC_RUNNING_S | PROC_RUNNING_M))
+       //      printk("dying before (re)startcore on core %d\n", core_id());
+
        // sucks to have ints disabled when doing env_decref and possibly freeing
        disable_irq();
        if (per_cpu_info[core_id()].preempt_pending) {
@@ -193,31 +234,32 @@ void proc_startcore(struct proc *p, trapframe_t *tf) {
        }
        /* If the process wasn't here, then we need to load its address space. */
        if (p != current) {
-               if (proc_incref(p))
+               if (proc_incref(p)) {
                        // getting here would mean someone tried killing this while we tried
                        // to start one of it's contexts (from scratch, o/w we had it's CR3
                        // loaded already)
-                       // if this happens, the death-IPI ought to be on its way...  we can
-                       // either wait, or just cleanup_core() and smp_idle.
-                       panic("Proc is dying, handle me!"); // TODO
+                       // if this happens, a no-op death-IPI ought to be on its way...  we can
+                       // just smp_idle()
+                       smp_idle();
+               }
                lcr3(p->env_cr3);
                // we unloaded the old cr3, so decref it (if it exists)
                // TODO: Consider moving this to wherever we really "mean to leave the
                // process's context".
                if (current)
                        proc_decref(current);
-               current = p;
+               set_cpu_curenv(p);
        }
        /* need to load our silly state, preferably somewhere other than here so we
         * can avoid the case where the context was just running here.  it's not
         * sufficient to do it in the "new process" if-block above (could be things
         * like page faults that cause us to keep the same process, but want a
         * different context.
-        * for now, we load this silly state here. (TODO)
+        * for now, we load this silly state here. (TODO) (HSS)
         * We also need this to be per trapframe, and not per process...
         */
        env_pop_ancillary_state(p);
-       env_pop_tf(&p->env_tf);
+       env_pop_tf(tf);
 }
 
 /*
@@ -240,60 +282,83 @@ void proc_startcore(struct proc *p, trapframe_t *tf) {
  */
 void proc_destroy(struct proc *p)
 {
+       // Note this code relies on this lock disabling interrupts, similar to
+       // proc_run.
        spin_lock_irqsave(&p->proc_lock);
-       // Could save the state and do this outside the lock
        switch (p->state) {
                case PROC_DYING:
                        return; // someone else killed this already.
                case PROC_RUNNABLE_S:
                case PROC_RUNNABLE_M:
+                       // Think about other lists, like WAITING, or better ways to do this
                        deschedule_proc(p);
                        break;
+               case PROC_RUNNING_S:
+                       #if 0
+                       // here's how to do it manually
+                       if (current == p) {
+                               lcr3(boot_cr3);
+                               proc_decref(p); // this decref is for the cr3
+                               current = NULL;
+                       }
+                       #endif
+                       send_active_msg_sync(p->vcoremap[0], __death, (void *SNT)0,
+                                            (void *SNT)0, (void *SNT)0);
+                       #if 0
+                       /* right now, RUNNING_S only runs on a mgmt core (0), not cores
+                        * managed by the idlecoremap.  so don't do this yet. */
+                       spin_lock(&idle_lock);
+                       idlecoremap[num_idlecores++] = p->vcoremap[0];
+                       spin_unlock(&idle_lock);
+                       #endif
+                       break;
+               case PROC_RUNNING_M:
+                       /* Send the DEATH message to every core running this process, and
+                        * deallocate the cores.
+                        * The rule is that the vcoremap is set before proc_run, and reset
+                        * within proc_destroy */
+                       spin_lock(&idle_lock);
+                       for (int i = 0; i < p->num_vcores; i++) {
+                               send_active_msg_sync(p->vcoremap[i], __death, (void *SNT)0,
+                                                    (void *SNT)0, (void *SNT)0);
+                               // give the pcore back to the idlecoremap
+                               assert(num_idlecores < num_cpus); // sanity
+                               idlecoremap[num_idlecores++] = p->vcoremap[i];
+                               p->vcoremap[i] = 0; // TODO: might need a better signal
+                       }
+                       spin_unlock(&idle_lock);
+                       break;
                default:
-                       // Think about other lists, or better ways to do this
+                       // TODO: getting here if it's already dead and free (ENV_FREE).
+                       // Need to sort reusing process structures and having pointers to
+                       // them floating around the system.
+                       panic("Weird state(0x%08x) in proc_destroy", p->state);
        }
        proc_set_state(p, PROC_DYING);
-       // BIG TODO: check the coremap to find out who needs to die
-       // send the death IPI to everyone else involved
-       spin_unlock_irqsave(&p->proc_lock);
 
-       proc_decref(p); // this decref is for the process in general
        atomic_dec(&num_envs);
+       /* TODO: (REF) dirty hack.  decref currently uses a lock, but needs to use
+        * CAS instead (another lock would be slightly less ghetto).  but we need to
+        * decref before releasing the lock, since that could enable interrupts,
+        * which would have us receive the DEATH IPI if this was called locally by
+        * the target process. */
+       //proc_decref(p); // this decref is for the process in general
+       p->env_refcnt--;
+       size_t refcnt = p->env_refcnt; // need to copy this in so it's not reloaded
 
-       /*
-        * If we are currently running this address space on our core, we need a
-        * known good pgdir before releasing the old one.  This is currently the
-        * major practical implication of the kernel caring about a processes
-        * existence (the inc and decref).  This decref corresponds to the incref in
-        * proc_startcore (though it's not the only one).
-        */
-       // TODO - probably make this a function, which the death IPI calls
-       if (current == p) {
-               lcr3(boot_cr3);
-               proc_decref(p); // this decref is for the cr3
-               current = NULL;
-       } else {
-               return;
-       }
-
-       // for old envs that die on user cores.  since env run never returns, cores
-       // never get back to their old hlt/relaxed/spin state, so we need to force
-       // them back to an idle function.
+       /* After unlocking, we can receive a DEATH IPI and clean up */
+       spin_unlock_irqsave(&p->proc_lock);
 
-       if (core_id()) {
-               smp_idle();
-               panic("should never see me");
-       }
-       // else we're core 0 and can do the usual
+       // coupled with the refcnt-- above, from decref.  if this happened,
+       // proc_destroy was called "remotely", and with no one else refcnting
+       if (!refcnt)
+               env_free(p);
 
-       /* Instead of picking a new environment to run, or defaulting to the monitor
-        * like before, for now we'll hop into the manager() function, which
-        * dispatches jobs.  Note that for now we start the manager from the top,
-        * and not from where we left off the last time we called manager.  That
-        * would require us to save some context (and a stack to work on) here.
-        */
-       manager();
-       assert(0); // never get here
+       /* If we were running the process, we should have received an IPI by now.
+        * If not, odds are interrupts are disabled, which shouldn't happen while
+        * servicing syscalls. */
+       assert(current != p);
+       return;
 }
 
 /*
@@ -320,6 +385,8 @@ void proc_destroy(struct proc *p)
  *
  * Also, no one should ever update the refcnt outside of these functions.
  * Eventually, we'll have Ivy support for this. (TODO)
+ *
+ * TODO: (REF) change to use CAS.
  */
 error_t proc_incref(struct proc *p)
 {
@@ -339,13 +406,74 @@ error_t proc_incref(struct proc *p)
  * "Last one out" actually finalizes the death of the process.  This is tightly
  * coupled with the previous function (incref)
  * Be sure to load a different cr3 before calling this!
+ *
+ * TODO: (REF) change to use CAS.  Note that when we do so, we may be holding
+ * the process lock when calling env_free().
  */
 void proc_decref(struct proc *p)
 {
        spin_lock_irqsave(&p->proc_lock);
        p->env_refcnt--;
+       size_t refcnt = p->env_refcnt; // need to copy this in so it's not reloaded
        spin_unlock_irqsave(&p->proc_lock);
        // if we hit 0, no one else will increment and we can check outside the lock
-       if (p->env_refcnt == 0)
+       if (!refcnt)
                env_free(p);
 }
+
+/* Active message handler to start a process's context on this core.  Tightly
+ * coupled with proc_run() */
+#ifdef __IVY__
+void __startcore(trapframe_t *tf, uint32_t srcid, struct proc *CT(1) a0,
+                 trapframe_t *CT(1) a1, void *SNT a2)
+#else
+void __startcore(trapframe_t *tf, uint32_t srcid, void * a0, void * a1,
+                 void * a2)
+#endif
+{
+       uint32_t coreid = core_id();
+       struct proc *p_to_run = (struct proc *CT(1))a0;
+       trapframe_t local_tf;
+       trapframe_t *tf_to_pop = (trapframe_t *CT(1))a1;
+
+       printk("Startcore on core %d\n", coreid);
+       assert(p_to_run);
+       // TODO: handle silly state (HSS)
+       if (!tf_to_pop) {
+               tf_to_pop = &local_tf;
+               memset(tf_to_pop, 0, sizeof(*tf_to_pop));
+               proc_init_trapframe(tf_to_pop);
+               // Note the init_tf sets tf_to_pop->tf_esp = USTACKTOP;
+               proc_set_tfcoreid(tf_to_pop, (uint32_t)a2);
+               proc_set_program_counter(tf_to_pop, p_to_run->env_entry);
+       }
+       proc_startcore(p_to_run, tf_to_pop);
+}
+
+/* Active message handler to stop running whatever context is on this core and
+ * to idle.  Note this leaves no trace of what was running.
+ * It's okay if death comes to a core that's already idling and has no current.
+ * It could happen if a process decref'd before proc_startcore could incref. */
+void __death(trapframe_t *tf, uint32_t srcid, void *SNT a0, void *SNT a1,
+             void *SNT a2)
+{
+       /* If we are currently running an address space on our core, we need a known
+        * good pgdir before releasing the old one.  This is currently the major
+        * practical implication of the kernel caring about a processes existence
+        * (the inc and decref).  This decref corresponds to the incref in
+        * proc_startcore (though it's not the only one). */
+       if (current) {
+               lcr3(boot_cr3);
+               proc_decref(current);
+               set_cpu_curenv(NULL);
+       }
+       smp_idle();
+}
+
+void print_idlecoremap(void)
+{
+       spin_lock(&idle_lock);
+       for (int i = 0; i < num_idlecores; i++)
+               printk("idlecoremap[%d] = %d\n", i, idlecoremap[i]);
+       spin_unlock(&idle_lock);
+}
index 71a46c6..fc26f46 100644 (file)
@@ -1,4 +1,8 @@
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <ros/error.h>
 #include <stdio.h>
 
index a4ff0c7..7ab2d9e 100644 (file)
@@ -6,6 +6,10 @@
  * Scheduling and dispatching.
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <schedule.h>
 #include <process.h>
 #include <monitor.h>
 #include <atomic.h>
 #include <sys/queue.h>
 
+// This could be useful for making scheduling decisions.  
+/* Physical coremap: each index is a physical core id, with a proc ptr for
+ * whoever *should be or is* running.  Very similar to current / curenvs[],
+ * which is what process is *really* running there. */
+struct proc *pcoremap[MAX_NUM_CPUS];
+
 void schedule_init(void)
 {
        TAILQ_INIT(&proc_runnablelist);
index c1cdc0e..8c6c924 100644 (file)
@@ -4,6 +4,10 @@
  * See LICENSE for details.
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <arch/arch.h>
 #include <atomic.h>
 #include <smp.h>
@@ -13,6 +17,7 @@
 #include <assert.h>
 #include <pmap.h>
 #include <process.h>
+#include <manager.h>
 #include <trap.h>
 
 struct per_cpu_info per_cpu_info[MAX_NUM_CPUS];
@@ -20,17 +25,30 @@ struct per_cpu_info per_cpu_info[MAX_NUM_CPUS];
 // tracks number of global waits on smp_calls, must be <= NUM_HANDLER_WRAPPERS
 atomic_t outstanding_calls = 0;
 
-/* All non-zero cores call this at the end of their boot process.  They halt,
- * and wake up when interrupted, do any work on their work queue, then halt
- * when there is nothing to do.  
- * TODO: think about resetting the stack pointer at the beginning.
+/* All cores end up calling this whenever there is nothing left to do.  Non-zero
+ * cores call it when they are done booting.  Other cases include after getting
+ * a DEATH IPI.
+ * - Management cores (core 0 for now) call manager, which should never return.
+ * - Worker cores halt and wake up when interrupted, do any work on their work
+ *   queue, then halt again.
+ *
+ * TODO: think about resetting the stack pointer at the beginning for worker
+ * cores. (keeps the stack from growing if we never go back to userspace).
+ * TODO: think about unifying the manager into a workqueue function, so we don't
+ * need to check mgmt_core in here.  it gets a little ugly, since there are
+ * other places where we check for mgmt and might not smp_idle / call manager.
  */
 void smp_idle(void)
 {
-       enable_irq();
-       while (1) {
-               process_workqueue();
-               // consider races with work added after we started leaving the last func
-               cpu_halt();
+       if (!management_core()) {
+               enable_irq();
+               while (1) {
+                       process_workqueue();
+                       // consider races with work added after we started leaving the last func
+                       cpu_halt();
+               }
+       } else {
+               manager();
        }
+       assert(0);
 }
index e73f98f..5c2e53b 100644 (file)
@@ -1,5 +1,9 @@
 // Basic string routines.  Not hardware optimized, but not shabby.
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <string.h>
 
 int
@@ -49,6 +53,7 @@ strncpy(char *dst, const char *src, size_t size) {
 
        ret = dst;
        for (i = 0; i < size; i++) {
+               // TODO: ivy bitches about this
                *dst++ = *src;
                // If strlen(src) < size, null-pad 'dst' out to 'size' chars
                if (*src != '\0')
index 569bd71..e5b270d 100644 (file)
@@ -1,10 +1,14 @@
 /* See COPYRIGHT for copyright information. */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #ifdef __DEPUTY__
 #pragma nodeputy
 #endif
 
-
+#include <ros/common.h>
 #include <arch/types.h>
 #include <arch/arch.h>
 #include <arch/mmu.h>
@@ -62,6 +66,10 @@ static ssize_t sys_serial_read(env_t* e, char *DANGEROUS _buf, size_t len)
        #endif
 }
 
+//
+/* START OF REMOTE SYSTEMCALL SUPPORT SYSCALLS. THESE WILL GO AWAY AS THINGS MATURE */
+//
+
 static ssize_t sys_run_binary(env_t* e, void *binary_buf, void* arg, size_t len) {
        uint8_t* new_binary = kmalloc(len, 0);
        if(new_binary == NULL)
@@ -77,7 +85,8 @@ static ssize_t sys_run_binary(env_t* e, void *binary_buf, void* arg, size_t len)
        return 0;
 }
 
-// This is probably not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
+
+// This is not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
 static ssize_t sys_eth_write(env_t* e, const char *DANGEROUS buf, size_t len) 
 { 
        extern int eth_up;
@@ -108,23 +117,8 @@ static ssize_t sys_eth_write(env_t* e, const char *DANGEROUS buf, size_t len)
        else
                return -EINVAL;
 }
-/*
-static ssize_t sys_eth_write(env_t* e, const char *DANGEROUS buf, size_t len) 
-{ 
-       extern int eth_up;
-       
-       if (eth_up) {
-               
-               char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_U);
-               
-               return(send_frame(buf, len));
-       }
-       return -EINVAL;
-}
-*/
 
-
-// This is probably not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
+// This is not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
 static ssize_t sys_eth_read(env_t* e, char *DANGEROUS buf, size_t len) 
 {
        extern int eth_up;
@@ -156,6 +150,10 @@ static ssize_t sys_eth_read(env_t* e, char *DANGEROUS buf, size_t len)
                return -EINVAL;
 }
 
+//
+/* END OF REMOTE SYSTEMCALL SUPPORT SYSCALLS. */
+//
+
 static ssize_t sys_shared_page_alloc(env_t* p1,
                                      void**DANGEROUS _addr, envid_t p2_id,
                                      int p1_flags, int p2_flags
@@ -415,8 +413,8 @@ static error_t sys_proc_run(struct proc *p, unsigned pid)
 
 // TODO: Build a dispatch table instead of switching on the syscallno
 // Dispatches to the correct kernel function, passing the arguments.
-intreg_t syscall(env_t* e, uint32_t syscallno, uint32_t a1, uint32_t a2,
-                 uint32_t a3, uint32_t a4, uint32_t a5)
+intreg_t syscall(env_t* e, uintreg_t syscallno, uintreg_t a1, uintreg_t a2,
+                 uintreg_t a3, uintreg_t a4, uintreg_t a5)
 {
        // Call the function corresponding to the 'syscallno' parameter.
        // Return any appropriate return value.
@@ -425,6 +423,9 @@ intreg_t syscall(env_t* e, uint32_t syscallno, uint32_t a1, uint32_t a2,
        //        " a2: %x\n    a3: %x\n    a4: %x\n    a5: %x\n",
        //        syscallno, a1, a2, a3, a4, a5);
 
+       // used if we need more args, like in mmap
+       int32_t _a4, _a5, _a6, *COUNT(3) args;
+
        assert(e); // should always have an env for every syscall
        //printk("Running syscall: %d\n", syscallno);
        if (INVALID_SYSCALL(syscallno))
@@ -434,13 +435,6 @@ intreg_t syscall(env_t* e, uint32_t syscallno, uint32_t a1, uint32_t a2,
                case SYS_null:
                        sys_null();
                        return ESUCCESS;
-               case SYS_run_binary:
-                       return sys_run_binary(e, (char *DANGEROUS)a1, 
-                                             (char* DANGEROUS)a2, (size_t)a3);
-               case SYS_eth_write:
-                       return sys_eth_write(e, (char *DANGEROUS)a1, (size_t)a2);
-               case SYS_eth_read:
-                       return sys_eth_read(e, (char *DANGEROUS)a1, (size_t)a2);        
                case SYS_cache_buster:
                        sys_cache_buster(e, a1, a2, a3);
                        return 0;
@@ -470,12 +464,32 @@ intreg_t syscall(env_t* e, uint32_t syscallno, uint32_t a1, uint32_t a2,
                        return sys_proc_create(e, (char *DANGEROUS)a1);
                case SYS_proc_run:
                        return sys_proc_run(e, (size_t)a1);
+               case SYS_mmap:
+                       // we only have 4 parameters from sysenter currently, need to copy
+                       // in the others.  if we stick with this, we can make a func for it.
+               args = user_mem_assert(e, (void*DANGEROUS)a4,
+                                              3*sizeof(_a4), PTE_USER_RW);
+                       _a4 = args[0];
+                       _a5 = args[1];
+                       _a6 = args[2];
+                       return (intreg_t) mmap(e, a1, a2, a3, _a4, _a5, _a6);
+               case SYS_brk:
+                       printk("brk not implemented yet\n");
+                       return -EINVAL;
 
        #ifdef __i386__
                case SYS_serial_write:
                        return sys_serial_write(e, (char *DANGEROUS)a1, (size_t)a2);
                case SYS_serial_read:
                        return sys_serial_read(e, (char *DANGEROUS)a1, (size_t)a2);
+                case SYS_run_binary:
+                        return sys_run_binary(e, (char *DANGEROUS)a1,
+                                              (char* DANGEROUS)a2, (size_t)a3);
+                case SYS_eth_write:
+                        return sys_eth_write(e, (char *DANGEROUS)a1, (size_t)a2);
+                case SYS_eth_read:
+                        return sys_eth_read(e, (char *DANGEROUS)a1, (size_t)a2);
+
        #endif
 
        #ifdef __sparc_v8__
@@ -516,8 +530,8 @@ intreg_t process_generic_syscalls(env_t* e, size_t max)
                        lcr3(e->env_cr3);
                }
                count++;
-               //printk("DEBUG PRE: sring->req_prod: %d, sring->rsp_prod: %d\n",\
-                          sysbr->sring->req_prod, sysbr->sring->rsp_prod);
+               //printk("DEBUG PRE: sring->req_prod: %d, sring->rsp_prod: %d\n",
+               //         sysbr->sring->req_prod, sysbr->sring->rsp_prod);
                // might want to think about 0-ing this out, if we aren't
                // going to explicitly fill in all fields
                syscall_rsp_t rsp;
@@ -529,8 +543,8 @@ intreg_t process_generic_syscalls(env_t* e, size_t max)
                // update our counter for what we've produced (assumes we went in order!)
                (sysbr->rsp_prod_pvt)++;
                RING_PUSH_RESPONSES(sysbr);
-               //printk("DEBUG POST: sring->req_prod: %d, sring->rsp_prod: %d\n",\
-                          sysbr->sring->req_prod, sysbr->sring->rsp_prod);
+               //printk("DEBUG POST: sring->req_prod: %d, sring->rsp_prod: %d\n",
+               //         sysbr->sring->req_prod, sysbr->sring->rsp_prod);
        }
        // load sane page tables (and don't rely on decref to do it for you).
        lcr3(boot_cr3);
index f67e3ce..a6ce6fb 100644 (file)
@@ -4,4 +4,7 @@
  * 
  * Kevin Klues <klueska@cs.berkeley.edu>    
  */
+
+#ifdef __SHARC__
+#pragma nosharc
+#endif
index e6a1740..55bf00d 100644 (file)
@@ -1,9 +1,14 @@
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <arch/mmu.h>
 #include <arch/arch.h>
 #include <smp.h>
 
 #include <ros/memlayout.h>
+#include <ros/common.h>
 
 #include <atomic.h>
 #include <stdio.h>
@@ -11,6 +16,7 @@
 #include <string.h>
 #include <testing.h>
 #include <trap.h>
+#include <arch/trap.h>
 #include <process.h>
 #include <syscall.h>
 #include <timing.h>
 #include <multiboot.h>
 #include <pmap.h>
 #include <page_alloc.h>
-
 #include <pmap.h>
 
-#define test_vector 0xeb
-
 #ifdef __i386__
 
 void test_ipi_sending(void)
 {
-       extern handler_t (COUNT(NUM_INTERRUPT_HANDLERS) interrupt_handlers)[];
+       extern handler_t (CT(NUM_INTERRUPT_HANDLERS) RO interrupt_handlers)[];
        int8_t state = 0;
 
-       register_interrupt_handler(interrupt_handlers, test_vector,
+       register_interrupt_handler(interrupt_handlers, I_TESTING,
                                   test_hello_world_handler, NULL);
        enable_irqsave(&state);
        cprintf("\nCORE 0 sending broadcast\n");
-       send_broadcast_ipi(test_vector);
+       send_broadcast_ipi(I_TESTING);
        udelay(3000000);
        cprintf("\nCORE 0 sending all others\n");
-       send_all_others_ipi(test_vector);
+       send_all_others_ipi(I_TESTING);
        udelay(3000000);
        cprintf("\nCORE 0 sending self\n");
-       send_self_ipi(test_vector);
+       send_self_ipi(I_TESTING);
        udelay(3000000);
        cprintf("\nCORE 0 sending ipi to physical 1\n");
-       send_ipi(0x01, 0, test_vector);
+       send_ipi(0x01, 0, I_TESTING);
        udelay(3000000);
        cprintf("\nCORE 0 sending ipi to physical 2\n");
-       send_ipi(0x02, 0, test_vector);
+       send_ipi(0x02, 0, I_TESTING);
        udelay(3000000);
        cprintf("\nCORE 0 sending ipi to physical 3\n");
-       send_ipi(0x03, 0, test_vector);
+       send_ipi(0x03, 0, I_TESTING);
        udelay(3000000);
        cprintf("\nCORE 0 sending ipi to physical 15\n");
-       send_ipi(0x0f, 0, test_vector);
+       send_ipi(0x0f, 0, I_TESTING);
        udelay(3000000);
        cprintf("\nCORE 0 sending ipi to logical 2\n");
-       send_ipi(0x02, 1, test_vector);
+       send_ipi(0x02, 1, I_TESTING);
        udelay(3000000);
        cprintf("\nCORE 0 sending ipi to logical 1\n");
-       send_ipi(0x01, 1, test_vector);
+       send_ipi(0x01, 1, I_TESTING);
        udelay(3000000);
        cprintf("\nDone!\n");
        disable_irqsave(&state);
@@ -121,6 +124,14 @@ void test_page_coloring(void)
        //Declare a local variable for allocating pages 
        page_t* page;
 
+       cprintf("Contents of the page free list:\n");
+       for(int i=0; i<llc_num_colors; i++) {
+               cprintf("  COLOR %d:\n", i);
+               LIST_FOREACH(page, &colored_page_free_list[i], page_link) {
+                       cprintf("    Page: %d\n", page2ppn(page));
+               }
+       }
+
        //Run through and allocate all pages through l1_page_alloc
        cprintf("Allocating from L1 page colors:\n");
        for(int i=0; i<get_cache_num_page_colors(&l1); i++) {
@@ -175,7 +186,6 @@ void test_page_coloring(void)
                cprintf("Page: %d\n", page2ppn(page));  
 }
 
-extern uint8_t num_cpus;
 barrier_t test_cpu_array;
 
 void test_barrier(void)
@@ -324,8 +334,6 @@ void test_checklist_handler(trapframe_t *tf, void* data)
        down_checklist(the_global_list);
 }
 
-extern uint8_t num_cpus;
-
 void test_checklists(void)
 {
        INIT_CHECKLIST(a_list, MAX_NUM_CPUS);
@@ -361,7 +369,11 @@ void test_checklists(void)
 
 atomic_t a, b, c;
 
-void test_incrementer_handler(trapframe_t *tf, atomic_t* data)
+#ifdef __IVY__
+void test_incrementer_handler(trapframe_t *tf, atomic_t *data)
+#else
+void test_incrementer_handler(trapframe_t *tf, void *data)
+#endif
 {
        assert(data);
        atomic_inc(data);
@@ -481,13 +493,13 @@ void test_smp_call_functions(void)
 #ifdef __i386__
 void test_lapic_status_bit(void)
 {
-       register_interrupt_handler(interrupt_handlers, test_vector,
+       register_interrupt_handler(interrupt_handlers, I_TESTING,
                                   test_incrementer_handler, &a);
        #define NUM_IPI 100000
        atomic_set(&a,0);
        printk("IPIs received (should be 0): %d\n", a);
        for(int i = 0; i < NUM_IPI; i++) {
-               send_ipi(7, 0, test_vector);
+               send_ipi(7, 0, I_TESTING);
                lapic_wait_to_send();
        }
        // need to wait a bit to let those IPIs get there
@@ -695,9 +707,13 @@ void test_barrier_handler(trapframe_t *tf, void* data)
        //cprintf("Round 4: Core %d\n", core_id());
 }
 
-static void test_waiting_handler(trapframe_t *tf, atomic_t * data)
+#ifdef __IVY__
+static void test_waiting_handler(trapframe_t *tf, atomic_t *data)
+#else
+static void test_waiting_handler(trapframe_t *tf, void *data)
+#endif
 {
-       {HANDLER_ATOMIC atomic_dec(data);}
+       atomic_dec(data);
 }
 
 #ifdef __i386__
@@ -716,10 +732,63 @@ void test_pit(void)
 
        atomic_t waiting;
        atomic_init(&waiting, 1);
-       register_interrupt_handler(interrupt_handlers, test_vector,
+       register_interrupt_handler(interrupt_handlers, I_TESTING,
                                   test_waiting_handler, &waiting);
        while(atomic_read(&waiting))
                cpu_relax();
        cprintf("End now\n");
 }
+
+void test_circ_buffer(void)
+{
+       int arr[5] = {0, 1, 2, 3, 4};
+
+       for (int i = 0; i < 5; i++) {
+               FOR_CIRC_BUFFER(i, 5, j)
+                       printk("Starting with current = %d, each value = %d\n", i, j);
+       }
+       return;
+}
+
+#ifdef __IVY__
+void test_am_handler(trapframe_t* tf, uint32_t srcid, uint32_t a0, uint32_t a1,
+                     uint32_t a2)
+#else
+void test_am_handler(trapframe_t* tf, uint32_t srcid, void * a0, void * a1,
+                     void * a2)
+#endif
+{
+       printk("Received AM on core %d from core %d: arg0= 0x%08x, arg1 = "
+              "0x%08x, arg2 = 0x%08x\n", core_id(), srcid, a0, a1, a2);
+       return;
+}
+
+void test_active_messages(void)
+{
+       // basic tests, make sure we can handle a wraparound and that the error
+       // messages work.
+       printk("sending NUM_ACTIVE_MESSAGES to core 1, sending (#,deadbeef,0)\n");
+       for (int i = 0; i < NUM_ACTIVE_MESSAGES; i++)
+#ifdef __IVY__
+               while (send_active_message(1, test_am_handler, i, 0xdeadbeef, 0))
+                       cpu_relax();
+#else
+               while (send_active_message(1, test_am_handler, (void *)i,
+                                          (void *)0xdeadbeef, (void *)0))
+                       cpu_relax();
+#endif
+       udelay(5000000);
+       printk("sending 2*NUM_ACTIVE_MESSAGES to core 1, sending (#,cafebabe,0)\n");
+       for (int i = 0; i < 2*NUM_ACTIVE_MESSAGES; i++)
+#ifdef __IVY__
+               while (send_active_message(1, test_am_handler, i, 0xdeadbeef, 0))
+                       cpu_relax();
+#else
+               while (send_active_message(1, test_am_handler, (void *)i,
+                                          (void *)0xdeadbeef, (void *)0))
+                       cpu_relax();
+#endif
+       udelay(5000000);
+       return;
+}
 #endif // __i386__
index 48fdec4..cc089ae 100644 (file)
@@ -1,3 +1,8 @@
+
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <arch/arch.h>
 #include <ros/timer.h>
 
@@ -13,7 +18,7 @@ uint64_t timing_overhead = 0;
  * value.  It is pusposefully annotated with a noinline so that the overheads 
  * assocaited with calling it are as deterministic as possible.
  */
-uint64_t start_timing() __attribute__((noinline))
+uint64_t start_timing()
 {
     return read_tsc_serialized();
 }
@@ -27,7 +32,7 @@ uint64_t start_timing() __attribute__((noinline))
  * This function is purposefully annotated with a noinline so that 
  * the overheads assocaited with calling it are as deterministic as possible.
  */
-uint64_t stop_timing(uint64_t val) __attribute__((noinline))
+uint64_t stop_timing(uint64_t val)
 {
     uint64_t diff = (read_tsc_serialized() - val - timing_overhead);
        if ((int64_t) diff < 0) 
index 5e2de2f..e7027c5 100644 (file)
@@ -4,6 +4,10 @@
  * See LICENSE for details.
  */
 
+#ifdef __SHARC__
+#pragma nosharc
+#endif
+
 #include <atomic.h>
 #include <smp.h>
 
@@ -18,8 +22,8 @@
  */
 void process_workqueue()
 {
-       struct work TP(env_t *) work;
-       struct per_cpu_info *cpuinfo = &per_cpu_info[core_id()];
+       struct work TP(TV(t)) work;
+       per_cpu_info_t *cpuinfo = &per_cpu_info[core_id()];
 
        // copy the work in, since we may never return to this stack frame
        spin_lock_irqsave(&cpuinfo->lock);
@@ -35,10 +39,10 @@ void process_workqueue()
        }
 }
 
-int enqueue_work(struct workqueue *queue, struct work *job)
+int enqueue_work(struct workqueue TP(TV(t)) *queue, struct work TP(TV(t)) *job)
 {
        error_t retval = 0;
-       struct per_cpu_info *cpuinfo = &per_cpu_info[core_id()];
+       per_cpu_info_t *cpuinfo = &per_cpu_info[core_id()];
 
        spin_lock_irqsave(&cpuinfo->lock);
        printd("Enqueuing func 0x%08x and data 0x%08x on core %d.\n",
index 0596f5e..4d746aa 100644 (file)
@@ -1,6 +1,6 @@
 USER_DIR = user
 
-USER_CFLAGS  := $(CFLAGS) -DROS_USER 
+USER_CFLAGS  += $(CFLAGS) -DROS_USER 
 USER_LDFLAGS := $(LDFLAGS)
 
 include $(USER_DIR)/roslib/Makefrag
index 380664a..a8d20a4 100644 (file)
@@ -1,9 +1,14 @@
 USER_APPS_PARLIB_DIR = $(USER_APPS_DIR)/parlib
 OBJDIRS += $(USER_APPS_PARLIB_DIR)
 
-USER_APPS_PARLIB_CFLAGS    := $(USER_CFLAGS) --nodeputy --nopatch \
+PATCHFILE = $(OBJDIR)/$(USER_PARLIB_DIR)/libc_patch.i
+
+USER_APPS_PARLIB_CFLAGS    := $(USER_CFLAGS)  \
                               -I$(USER_PARLIB_NEWLIB_DIR)/include \
                               -I$(USER_PARLIB_DIR)/inc
+ifeq ($(COMPILER),IVY)
+       USER_APPS_PARLIB_CFLAGS    += --nodeputy --nopatch #--patch=$(PATCHFILE) 
+endif
 
 USER_APPS_PARLIB_LDFLAGS   := $(USER_LDFLAGS) -static \
                               -T $(USER_APPS_PARLIB_DIR)/apps_$(TARGET_ARCH).ld
@@ -30,7 +35,7 @@ USER_APPS_PARLIB_LDDEPENDS := $(USER_APPS_PARLIB_LDOBJS) \
 
 USER_APPS_PARLIB_GCC_LIB   := $(GCC_LIB)
 
-$(OBJDIR)/$(USER_APPS_PARLIB_DIR)/%.o: $(USER_APPS_PARLIB_DIR)/%.c
+$(OBJDIR)/$(USER_APPS_PARLIB_DIR)/%.o: $(USER_APPS_PARLIB_DIR)/%.c $(PATCHFILE)
        @echo + cc [APPS PARLIB] $<
        @mkdir -p $(@D)
        $(V)$(CC) $(USER_APPS_PARLIB_CFLAGS) -c -o $@ $<
index 83ecdcf..90df8ec 100644 (file)
@@ -35,7 +35,7 @@ void file_error()
 
        errno = 0;
        printf("\n");
-       int result = read(bad_fd, buf, IN_BUF_SIZE - 1);
+       result = read(bad_fd, buf, IN_BUF_SIZE - 1);
        printf("Read:         %d bytes\n", result);
        printf("ERRNO:        %s\n", strerror(errno));
 
index 058bd33..63b3486 100644 (file)
@@ -1,5 +1,5 @@
-#include <string.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
index 07b56a0..1aa741f 100644 (file)
@@ -2,7 +2,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <unistd.h>
-#include <arch/types.h>
+#include <ros/common.h>
 
 extern char * readline(const char *prompt);
 extern void draw_nanwan();
index 7c53082..73370af 100644 (file)
@@ -3,7 +3,7 @@
 #include <fcntl.h>
 #include <arch/kbdreg.h>
 
-char* readline(const char *prompt)
+char* readline(const char * prompt)
 {
        int i, read_amt;
        char c;
index af17789..0b77a3b 100644 (file)
@@ -1,4 +1,4 @@
-#include <arch/types.h>
+#include <ros/common.h>
 #include <arch/arch.h>
 #include <ros/timer.h>
 #include <ros/syscall.h>
diff --git a/user/apps/roslib/mhello.c b/user/apps/roslib/mhello.c
new file mode 100644 (file)
index 0000000..417c805
--- /dev/null
@@ -0,0 +1,28 @@
+#include <lib.h>
+#include <stdio.h>
+
+// ghetto udelay, put in a lib somewhere and export the tsc freq
+#include <arch/arch.h>
+void udelay(uint64_t usec, uint64_t tsc_freq)
+{
+       uint64_t start, end, now;
+
+       start = read_tsc();
+    end = start + (tsc_freq * usec) / 1000000;
+       if (end == 0) cprintf("This is terribly wrong \n");
+       do {
+        cpu_relax();
+        now = read_tsc();
+       } while (now < end || (now > start && end < start));
+       return;
+}
+
+int main(int argc, char** argv)
+{
+       cprintf("Multi-Goodbye, world, from PID: %d!\n", sys_getpid());
+       sys_mmap((void*SNT)1, 2, 3, 4, 0, 0);
+       while(1);
+       udelay(5000000, 1995014570); // KVM's freq.  Whatever.
+
+       return 0;
+}
index f49dfbb..8ad97ec 100644 (file)
@@ -9,7 +9,7 @@
 #define ROS_CHANNEL_H
  
 #include <stdint.h>
-#include <arch/types.h>
+#include <ros/common.h>
 #include <ros/error.h>
 #include <ros/ring_buffer.h>
 
index 8760158..cf92096 100644 (file)
@@ -434,7 +434,7 @@ OPTSTRING getcwd (STRINGBUF(__size) __buf, size_t __size);
 
 // reent.h
 
-#ifdef __CYGWIN__
+//#ifdef __CYGWIN__
 // Take care of the union in reent.h (on cygwin)
 // This union is not actually used, so we can use WHEN 
 // clauses to enable only the used field.
@@ -444,7 +444,7 @@ struct _reent {
         void _unused WHEN(0);
     } _new;
 };
-#endif
+//#endif
 
 // siginfo.h
 
index 0dea51e..2ee9e4d 100644 (file)
@@ -1,7 +1,7 @@
 /* See COPYRIGHT for copyright information. */
 /* Kevin Klues <klueska@cs.berkeley.edu>       */
 
-#ifndef _NEWLIB_LIBC_WRAPPERS_H
+#ifndef _NEWLIB_LIBC_WRAPPERS_H_
 #define _NEWLIB_LIBC_WRAPPERS_H_
 
 #include <errno.h>
@@ -150,7 +150,7 @@ response_t *send_message(msg_t *msg, int len);
 /* write_to_channel()
  * Send a message out over the channel, defined by msg, of length len
  */
-int write_to_channel(char *msg, int len);
+int write_to_channel(msg_t *msg, int len);
 
 #endif //_NEWLIB_LIBC_WRAPPERS_H_