Another round at reorganization
authorKevin Klues <klueska@cs.berkeley.edu>
Tue, 26 May 2009 03:24:57 +0000 (20:24 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Tue, 26 May 2009 03:39:54 +0000 (20:39 -0700)
This time 'parlib' has become the wrapper around newlib stuff, and 'roslib' is our somehwat ghetto libc
implementation weve been using since the beginning.  We also have the notion of architecture specific
includes, as well as includes shared by user/kernel space in the same style as the 'linux' include
directory in a linux distribution.

206 files changed:
GNUmakefile
boot/Makefrag [deleted file]
boot/boot.S [deleted file]
boot/main.c [deleted file]
boot/sign.pl [deleted file]
include/arch/apic.h [new file with mode: 0644]
include/arch/console.h [new file with mode: 0644]
include/arch/elf.h [new file with mode: 0644]
include/arch/mmu.h [new file with mode: 0644]
include/arch/multiboot.h [new file with mode: 0644]
include/arch/smp.h [new file with mode: 0644]
include/arch/stab.h [new file with mode: 0644]
include/arch/timer.h [new file with mode: 0644]
include/arch/types.h [new file with mode: 0644]
include/arch/x86.h [new file with mode: 0644]
include/assert.h [new file with mode: 0644]
include/atomic.h [new file with mode: 0644]
include/env.h [new file with mode: 0644]
include/error.h [new file with mode: 0644]
include/kbdreg.h [new file with mode: 0644]
include/kclock.h [new file with mode: 0644]
include/kdebug.h [new file with mode: 0644]
include/monitor.h [new file with mode: 0644]
include/pmap.h [new file with mode: 0644]
include/pool.h [new file with mode: 0644]
include/ros/env.h [new file with mode: 0644]
include/ros/memlayout.h [new file with mode: 0644]
include/ros/queue.h [new file with mode: 0644]
include/ros/ring_buffer.h [new file with mode: 0644]
include/ros/syscall.h [new file with mode: 0644]
include/ros/trap.h [new file with mode: 0644]
include/sched.h [new file with mode: 0644]
include/stdarg.h [new file with mode: 0644]
include/stdio.h [new file with mode: 0644]
include/string.h [new file with mode: 0644]
include/syscall.h [new file with mode: 0644]
include/testing.h [new file with mode: 0644]
include/trap.h [new file with mode: 0644]
kern/Makefrag
kern/apic.h [deleted file]
kern/atomic.h [deleted file]
kern/boot/Makefrag [new file with mode: 0644]
kern/boot/boot.S [new file with mode: 0644]
kern/boot/main.c [new file with mode: 0644]
kern/boot/sign.pl [new file with mode: 0644]
kern/console.h [deleted file]
kern/env.h [deleted file]
kern/ivy/Makefrag [new file with mode: 0644]
kern/ivy/deputy.c [new file with mode: 0644]
kern/ivylib/Makefrag [deleted file]
kern/ivylib/deputy.c [deleted file]
kern/kclock.h [deleted file]
kern/kdebug.h [deleted file]
kern/monitor.h [deleted file]
kern/pmap.h [deleted file]
kern/sched.h [deleted file]
kern/smp.h [deleted file]
kern/src/Makefrag
kern/src/apic.c
kern/src/atomic.c
kern/src/console.c
kern/src/entry.S
kern/src/env.c
kern/src/init.c
kern/src/kclock.c
kern/src/kdebug.c
kern/src/monitor.c
kern/src/pmap.c
kern/src/printf.c
kern/src/printfmt.c [new file with mode: 0644]
kern/src/readline.c [new file with mode: 0644]
kern/src/smp.c
kern/src/smp_entry.S
kern/src/string.c [new file with mode: 0644]
kern/src/syscall.c
kern/src/testing.c
kern/src/timer.c [new file with mode: 0644]
kern/src/trap.c
kern/src/trapentry.S
kern/syscall.h [deleted file]
kern/testing.h [deleted file]
kern/trap.h [deleted file]
user/Makefrag
user/apps/Makefrag
user/apps/newlib/Makefrag [deleted file]
user/apps/newlib/apps.ld [deleted file]
user/apps/newlib/hello.c [deleted file]
user/apps/newlib/null.c [deleted file]
user/apps/parlib/Makefrag
user/apps/parlib/apps.ld
user/apps/parlib/badsegment.c [deleted file]
user/apps/parlib/breakpoint.c [deleted file]
user/apps/parlib/buggyhello.c [deleted file]
user/apps/parlib/divzero.c [deleted file]
user/apps/parlib/evilhello.c [deleted file]
user/apps/parlib/faultread.c [deleted file]
user/apps/parlib/faultreadkernel.c [deleted file]
user/apps/parlib/faultwrite.c [deleted file]
user/apps/parlib/faultwritekernel.c [deleted file]
user/apps/parlib/hello.c
user/apps/parlib/measurements.c [deleted file]
user/apps/parlib/null.c
user/apps/parlib/print_tests.c [deleted file]
user/apps/parlib/softint.c [deleted file]
user/apps/parlib/testbss.c [deleted file]
user/apps/parlib/testpmap.c [deleted file]
user/apps/roslib/Makefrag [new file with mode: 0644]
user/apps/roslib/apps.ld [new file with mode: 0644]
user/apps/roslib/badsegment.c [new file with mode: 0644]
user/apps/roslib/breakpoint.c [new file with mode: 0644]
user/apps/roslib/buggyhello.c [new file with mode: 0644]
user/apps/roslib/divzero.c [new file with mode: 0644]
user/apps/roslib/evilhello.c [new file with mode: 0644]
user/apps/roslib/faultread.c [new file with mode: 0644]
user/apps/roslib/faultreadkernel.c [new file with mode: 0644]
user/apps/roslib/faultwrite.c [new file with mode: 0644]
user/apps/roslib/faultwritekernel.c [new file with mode: 0644]
user/apps/roslib/hello.c [new file with mode: 0644]
user/apps/roslib/measurements.c [new file with mode: 0644]
user/apps/roslib/null.c [new file with mode: 0644]
user/apps/roslib/print_tests.c [new file with mode: 0644]
user/apps/roslib/softint.c [new file with mode: 0644]
user/apps/roslib/testbss.c [new file with mode: 0644]
user/apps/roslib/testpmap.c [new file with mode: 0644]
user/newlib/Makefrag [deleted file]
user/newlib/src/Makefrag [deleted file]
user/newlib/src/libc_wrappers.c [deleted file]
user/newlib/src/libc_wrappers.h [deleted file]
user/parlib/COPYRIGHT [deleted file]
user/parlib/Makefrag
user/parlib/inc/assert.h [deleted file]
user/parlib/inc/atomic.h [deleted file]
user/parlib/inc/elf.h [deleted file]
user/parlib/inc/env.h [deleted file]
user/parlib/inc/error.h [deleted file]
user/parlib/inc/kbdreg.h [deleted file]
user/parlib/inc/lib.h [deleted file]
user/parlib/inc/malloc.h [deleted file]
user/parlib/inc/measure.h [deleted file]
user/parlib/inc/memlayout.h [deleted file]
user/parlib/inc/mmu.h [deleted file]
user/parlib/inc/multiboot.h [deleted file]
user/parlib/inc/null.h [deleted file]
user/parlib/inc/pool.h [deleted file]
user/parlib/inc/queue.h [deleted file]
user/parlib/inc/ring_buffer.h [deleted file]
user/parlib/inc/stab.h [deleted file]
user/parlib/inc/stdarg.h [deleted file]
user/parlib/inc/stdio.h [deleted file]
user/parlib/inc/string.h [deleted file]
user/parlib/inc/syscall.h [deleted file]
user/parlib/inc/timer.h [deleted file]
user/parlib/inc/trap.h [deleted file]
user/parlib/inc/types.h [deleted file]
user/parlib/inc/x86.h [deleted file]
user/parlib/ivylib/Makefrag [deleted file]
user/parlib/ivylib/deputy.c [deleted file]
user/parlib/src/Makefrag
user/parlib/src/asynccall.c [deleted file]
user/parlib/src/console.c [deleted file]
user/parlib/src/entry.S [deleted file]
user/parlib/src/exit.c [deleted file]
user/parlib/src/libmain.c [deleted file]
user/parlib/src/null.c [deleted file]
user/parlib/src/panic.c [deleted file]
user/parlib/src/parlib.c [new file with mode: 0644]
user/parlib/src/parlib.h [new file with mode: 0644]
user/parlib/src/printf.c [deleted file]
user/parlib/src/printfmt.c [deleted file]
user/parlib/src/readline.c [deleted file]
user/parlib/src/string.c [deleted file]
user/parlib/src/syscall.c [deleted file]
user/parlib/src/timer.c [deleted file]
user/roslib/COPYRIGHT [new file with mode: 0644]
user/roslib/Makefrag [new file with mode: 0644]
user/roslib/inc/arch [new symlink]
user/roslib/inc/assert.h [new file with mode: 0644]
user/roslib/inc/atomic.h [new file with mode: 0644]
user/roslib/inc/error.h [new file with mode: 0644]
user/roslib/inc/lib.h [new file with mode: 0644]
user/roslib/inc/malloc.h [new file with mode: 0644]
user/roslib/inc/measure.h [new file with mode: 0644]
user/roslib/inc/null.h [new file with mode: 0644]
user/roslib/inc/pool.h [new file with mode: 0644]
user/roslib/inc/queue.h [new file with mode: 0644]
user/roslib/inc/ros [new symlink]
user/roslib/inc/stdarg.h [new file with mode: 0644]
user/roslib/inc/stdio.h [new file with mode: 0644]
user/roslib/inc/string.h [new file with mode: 0644]
user/roslib/inc/types.h [new file with mode: 0644]
user/roslib/ivy/Makefrag [new file with mode: 0644]
user/roslib/ivy/deputy.c [new file with mode: 0644]
user/roslib/src/Makefrag [new file with mode: 0644]
user/roslib/src/asynccall.c [new file with mode: 0644]
user/roslib/src/console.c [new file with mode: 0644]
user/roslib/src/entry.S [new file with mode: 0644]
user/roslib/src/exit.c [new file with mode: 0644]
user/roslib/src/libmain.c [new file with mode: 0644]
user/roslib/src/null.c [new file with mode: 0644]
user/roslib/src/panic.c [new file with mode: 0644]
user/roslib/src/printf.c [new file with mode: 0644]
user/roslib/src/printfmt.c [new file with mode: 0644]
user/roslib/src/readline.c [new file with mode: 0644]
user/roslib/src/string.c [new file with mode: 0644]
user/roslib/src/syscall.c [new file with mode: 0644]
user/roslib/src/timer.c [new file with mode: 0644]

index 20b4354..3de15e1 100644 (file)
@@ -7,7 +7,8 @@
 #
 OBJDIR := obj
 
-TOP = .
+TOP_DIR := .
+INCLUDE_DIR := $(TOP_DIR)/include
 UNAME=$(shell uname -m)
 V = @
 
@@ -54,19 +55,10 @@ ARCH ?= NONE
 CFLAGS := $(CFLAGS) -D$(ARCH) 
 CFLAGS += -O -pipe -MD -fno-builtin -fno-stack-protector -gstabs
 CFLAGS += -Wall -Wno-format -Wno-unused
-CFLAGS += -I$(TOP)
-
-# Kernel vs. user universal compiler flags
-KERN_CFLAGS := $(CFLAGS) -DROS_KERNEL -nostdinc
-USER_CFLAGS := $(CFLAGS) -DROS_USER
 
 # Universal loader flags
 LDFLAGS := -nostdlib
 
-# Kernel vs. user universal loader flags
-KERN_LDFLAGS := 
-USER_LDFLAGS :=
-
 # GCC Library path 
 GCC_LIB := $(shell $(CC) -print-libgcc-file-name)
 
@@ -85,10 +77,6 @@ all:
 
 # Include Makefrags for subdirectories
 include user/Makefrag
-# A hack until we get the story figured out with the kernel including files from 
-# parlib/inc
-KERN_CFLAGS += -I$(USER_PARLIB_DIR)
-include boot/Makefrag
 include kern/Makefrag
 -include Makelocal
 
@@ -98,15 +86,6 @@ include kern/Makefrag
 # Delete target files if there is an error (or make is interrupted)
 .DELETE_ON_ERROR:
 
-# make it so that no intermediate .o files are ever deleted
-.PRECIOUS: %.o                                    \
-           $(OBJDIR)/$(BOOT_DIR)/%.o              \
-           $(OBJDIR)/$(KERN_DIR)/%.o              \
-              $(OBJDIR)/$(USER_PARLIB_DIR)/%.o       \
-              $(OBJDIR)/$(USER_NEWLIB_DIR)/%.o       \
-           $(OBJDIR)/$(USER_APPS_NEWLIB_DIR)/%.o  \
-           $(OBJDIR)/$(USER_APPS_PARLIB_DIR)/%.o
-
 # This magic automatically generates makefile dependencies
 # for header files included from C source files we compile,
 # and keeps those dependencies up-to-date every time we recompile.
diff --git a/boot/Makefrag b/boot/Makefrag
deleted file mode 100644 (file)
index ced83d5..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Makefile fragment for the ROS kernel.
-# This is NOT a complete makefile;
-# you must run GNU make in the top-level directory
-# where the GNUmakefile is located.
-#
-
-BOOT_DIR = boot
-OBJDIRS += $(BOOT_DIR)
-
-BOOT_CFLAGS  := $(KERN_CFLAGS) -Os -I$(USER_PARLIB_DIR)
-BOOT_LDFLAGS := $(KERN_LDFLAGS) -N -e start -Ttext 0x7C00
-BOOT_OBJS    := $(OBJDIR)/$(BOOT_DIR)/boot.o $(OBJDIR)/$(BOOT_DIR)/main.o
-
-$(OBJDIR)/$(BOOT_DIR)/%.o: $(BOOT_DIR)/%.c
-       @echo + cc [BOOT] $<
-       @mkdir -p $(@D)
-       $(V)$(CC) $(BOOT_CFLAGS) -c -o $@ $<
-
-$(OBJDIR)/$(BOOT_DIR)/%.o: $(BOOT_DIR)/%.S
-       @echo + as [BOOT] $<
-       @mkdir -p $(@D)
-       $(V)$(CC) $(BOOT_CFLAGS) -c -o $@ $<
-
-$(OBJDIR)/$(BOOT_DIR)/boot: $(BOOT_OBJS)
-       @echo + ld [BOOT] $<
-       $(V)$(LD) $(BOOT_LDFLAGS) -o $@.out $^
-       $(V)$(OBJDUMP) -S $@.out >$@.asm
-       $(V)$(OBJCOPY) -S -O binary $@.out $@
-       $(V)perl boot/sign.pl $(OBJDIR)/$(BOOT_DIR)/boot
-
diff --git a/boot/boot.S b/boot/boot.S
deleted file mode 100644 (file)
index 5ad119d..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-#include <inc/mmu.h>
-       
-.set PROT_MODE_CSEG,0x8                # code segment selector
-.set PROT_MODE_DSEG,0x10        # data segment selector
-.set CR0_PE_ON,0x1             # protected mode enable flag
-       
-###############################################################################
-# ENTRY POINT  
-#   This code should be stored in the first sector of the hard disk.
-#   After the BIOS initializes the hardware on startup or system reset,
-#   it loads this code at physical address 0x7c00 - 0x7d00 (512 bytes).
-#   Then the BIOS jumps to the beginning of it, address 0x7c00,
-#   while running in 16-bit real-mode (8086 compatibility mode).
-#   The Code Segment register (CS) is initially zero on entry.
-#      
-# This code switches into 32-bit protected mode so that all of
-# memory can accessed, then calls into C.
-###############################################################################
-       
-.globl start                                   # Entry point   
-start:         .code16                         # This runs in real mode
-               cli                             # Disable interrupts
-               cld                             # String operations increment
-
-               # Set up the important data segment registers (DS, ES, SS).
-               xorw    %ax,%ax                 # Segment number zero
-               movw    %ax,%ds                 # -> Data Segment
-               movw    %ax,%es                 # -> Extra Segment
-               movw    %ax,%ss                 # -> Stack Segment
-
-               # Set up the stack pointer, growing downward from 0x7c00.
-               movw    $start,%sp              # Stack Pointer
-       
-# Enable A20:
-#   For fascinating historical reasons (related to the fact that
-#   the earliest 8086-based PCs could only address 1MB of physical memory
-#   and subsequent 80286-based PCs wanted to retain maximum compatibility),
-#   physical address line 20 is tied to low when the machine boots.
-#   Obviously this a bit of a drag for us, especially when trying to
-#   address memory above 1MB.  This code undoes this.
-       
-seta20.1:      inb     $0x64,%al               # Get status
-               testb   $0x2,%al                # Busy?
-               jnz     seta20.1                # Yes
-               movb    $0xd1,%al               # Command: Write
-               outb    %al,$0x64               #  output port
-seta20.2:      inb     $0x64,%al               # Get status
-               testb   $0x2,%al                # Busy?
-               jnz     seta20.2                # Yes
-               movb    $0xdf,%al               # Enable
-               outb    %al,$0x60               #  A20
-
-# Switch from real to protected mode:
-#   Up until now, there's been no protection, so we've gotten along perfectly
-#   well without explicitly telling the processor how to translate addresses.
-#   When we switch to protected mode, this is no longer true!
-#   We need at least to set up some "segments" that tell the processor it's
-#   OK to run code at any address, or write to any address.
-#   The 'gdt' and 'gdtdesc' tables below define these segments.
-#   This code loads them into the processor.
-#   We need this setup to ensure the transition to protected mode is smooth.
-
-real_to_prot:  cli                     # Don't allow interrupts: mandatory,
-                                       # since we didn't set up an interrupt
-                                       # descriptor table for handling them
-               lgdt    gdtdesc         # load GDT: mandatory in protected mode
-               movl    %cr0, %eax      # Turn on protected mode
-               orl     $CR0_PE_ON, %eax
-               movl    %eax, %cr0
-
-               # CPU magic: jump to relocation, flush prefetch queue, and
-               # reload %cs.  Has the effect of just jmp to the next
-               # instruction, but simultaneously loads CS with
-               # $PROT_MODE_CSEG.
-               ljmp    $PROT_MODE_CSEG, $protcseg
-       
-               # we've switched to 32-bit protected mode; tell the assembler
-               # to generate code for that mode
-protcseg:      .code32
-               # Set up the protected-mode data segment registers
-               movw    $PROT_MODE_DSEG, %ax    # Our data segment selector
-               movw    %ax, %ds                # -> DS: Data Segment
-               movw    %ax, %es                # -> ES: Extra Segment
-               movw    %ax, %fs                # -> FS
-               movw    %ax, %gs                # -> GS
-               movw    %ax, %ss                # -> SS: Stack Segment
-       
-               call cmain                      # finish the boot load from C.
-                                               # cmain() should not return
-spin:          jmp spin                        # ..but in case it does, spin
-       
-               .p2align 2                      # force 4 byte alignment
-gdt:           SEG_NULL                                # null seg
-               SEG(STA_X|STA_R, 0x0, 0xffffffff)       # code seg
-               SEG(STA_W, 0x0, 0xffffffff)             # data seg
-       
-gdtdesc:       .word   0x17                    # sizeof(gdt) - 1
-               .long   gdt                     # address gdt
diff --git a/boot/main.c b/boot/main.c
deleted file mode 100644 (file)
index a2b3f97..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifdef __DEPUTY__
-#pragma nodeputy
-#endif
-
-#include <inc/x86.h>
-#include <inc/elf.h>
-
-/**********************************************************************
- * This a dirt simple boot loader, whose sole job is to boot
- * an elf kernel image from the first IDE hard disk.
- *
- * DISK LAYOUT
- *  * This program(boot.S and main.c) is the bootloader.  It should
- *    be stored in the first sector of the disk.
- * 
- *  * The 2nd sector onward holds the kernel image.
- *     
- *  * The kernel image must be in ELF format.
- *
- * BOOT UP STEPS       
- *  * when the CPU boots it loads the BIOS into memory and executes it
- *
- *  * the BIOS intializes devices, sets of the interrupt routines, and
- *    reads the first sector of the boot device(e.g., hard-drive) 
- *    into memory and jumps to it.
- *
- *  * Assuming this boot loader is stored in the first sector of the
- *    hard-drive, this code takes over...
- *
- *  * control starts in bootloader.S -- which sets up protected mode,
- *    and a stack so C code then run, then calls cmain()
- *
- *  * cmain() in this file takes over, reads in the kernel and jumps to it.
- **********************************************************************/
-
-#define SECTSIZE       512
-#define ELFHDR         ((elf_t *) 0x10000) // scratch space
-
-void readsect(void*, uint32_t);
-void readseg(uint32_t, uint32_t, uint32_t);
-
-void
-cmain(void)
-{
-       proghdr_t *ph, *eph;
-
-       // read 1st page off disk
-       readseg((uint32_t) ELFHDR, SECTSIZE*8, 0);
-
-       // is this a valid ELF?
-       if (ELFHDR->e_magic != ELF_MAGIC)
-               goto bad;
-
-       // load each program segment (ignores ph flags)
-       ph = (proghdr_t *) ((uint8_t *) ELFHDR + ELFHDR->e_phoff);
-       eph = ph + ELFHDR->e_phnum;
-       for (; ph < eph; ph++)
-               readseg(ph->p_va, ph->p_memsz, ph->p_offset);
-
-       // call the entry point from the ELF header
-       // note: does not return!
-       ((void (*)(void)) (ELFHDR->e_entry & 0x0FFFFFFF))();
-
-bad:
-       outw(0x8A00, 0x8A00);
-       outw(0x8A00, 0x8E00);
-       while (1)
-               /* do nothing */;
-}
-
-// Read 'count' bytes at 'offset' from kernel into virtual address 'va'.
-// Might copy more than asked
-void
-readseg(uint32_t va, uint32_t count, uint32_t offset)
-{
-       uint32_t end_va;
-
-       va &= 0x0FFFFFFF;
-       end_va = va + count;
-       
-       // round down to sector boundary
-       va &= ~(SECTSIZE - 1);
-
-       // translate from bytes to sectors, and kernel starts at sector 1
-       offset = (offset / SECTSIZE) + 1;
-
-       // If this is too slow, we could read lots of sectors at a time.
-       // We'd write more to memory than asked, but it doesn't matter --
-       // we load in increasing order.
-       while (va < end_va) {
-               readsect((uint8_t*) va, offset);
-               va += SECTSIZE;
-               offset++;
-       }
-}
-
-void
-waitdisk(void)
-{
-       // wait for disk ready
-       while ((inb(0x1F7) & 0xC0) != 0x40)
-               /* do nothing */;
-}
-
-void
-readsect(void *dst, uint32_t offset)
-{
-       // wait for disk to be ready
-       waitdisk();
-
-       /* the ISA uses a specified block of memory, 
-          addresses 0x1F0-0x1F7, that can use the special 
-          instructions inb/outb, as demonstrated in the 
-          following code in order to access the disk
-          Offset is 28 bytes long
-       */
-
-       outb(0x1F2, 1);                         // number of sectors to read
-       outb(0x1F3, offset);                    // bits 0-7 (low bits) of 28-bit offset
-       outb(0x1F4, offset >> 8);               // bits 8-15 of 28-bit offset
-       outb(0x1F5, offset >> 16);              // bits 16-23 of 28-bit offset
-       outb(0x1F6, (offset >> 24) | 0xE0);     // bits 24-27 of 28-bit offset
-                                               // bit 28 (= 0) means Disk 0
-                                               // other bits (29-31) must be set to one
-       outb(0x1F7, 0x20);                      // cmd 0x20 - read sectors
-
-       // wait for disk to be ready
-       waitdisk();
-
-       // read a sector
-       insl(0x1F0, dst, SECTSIZE/4);
-}
-
diff --git a/boot/sign.pl b/boot/sign.pl
deleted file mode 100644 (file)
index 8a65e9f..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/perl
-
-open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!";
-
-$n = sysread(SIG, $buf, 1000);
-
-if($n > 510){
-       print STDERR "boot block too large: $n bytes (max 510)\n";
-       exit 1;
-}
-
-print STDERR "boot block is $n bytes (max 510)\n";
-
-$buf .= "\0" x (510-$n);
-$buf .= "\x55\xAA";
-
-open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!";
-print SIG $buf;
-close SIG;
diff --git a/include/arch/apic.h b/include/arch/apic.h
new file mode 100644 (file)
index 0000000..613f42e
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
+
+#ifndef ROS_KERN_APIC_H
+#define ROS_KERN_APIC_H
+
+/* 
+ * Functions and definitions for dealing with the APIC and PIC, specific to
+ * Intel.  Does not handle an x2APIC.
+ */
+
+#include <arch/mmu.h>
+#include <arch/x86.h>
+
+// PIC
+#define PIC1_CMD                                       0x20
+#define PIC1_DATA                                      0x21
+#define PIC2_CMD                                       0xA0
+#define PIC2_DATA                                      0xA1
+// These are also hardcoded into the IRQ_HANDLERs of kern/trapentry.S
+#define PIC1_OFFSET                                    0x20
+#define PIC2_OFFSET                                    0x28
+#define PIC_EOI                                                0x20
+
+// Local APIC
+#define LAPIC_BASE                                     0xfee00000 // this is the default, can be changed
+#define LAPIC_EOI                                      (LAPIC_BASE + 0x0b0)
+#define LAPIC_SPURIOUS                         (LAPIC_BASE + 0x0f0)
+#define LAPIC_VERSION                          (LAPIC_BASE + 0x030)
+#define LAPIC_ERROR                                    (LAPIC_BASE + 0x280)
+#define LAPIC_ID                                       (LAPIC_BASE + 0x020)
+#define LAPIC_LOGICAL_ID                       (LAPIC_BASE + 0x0d0)
+// LAPIC Local Vector Table
+#define LAPIC_LVT_TIMER                                (LAPIC_BASE + 0x320)
+#define LAPIC_LVT_LINT0                                (LAPIC_BASE + 0x350)
+#define LAPIC_LVT_LINT1                                (LAPIC_BASE + 0x360)
+#define LAPIC_LVT_ERROR                                (LAPIC_BASE + 0x370)
+#define LAPIC_LVT_PERFMON                      (LAPIC_BASE + 0x340)
+#define LAPIC_LVT_THERMAL                      (LAPIC_BASE + 0x330)
+#define LAPIC_LVT_MASK                         0x00010000
+// LAPIC Timer
+#define LAPIC_TIMER_INIT                       (LAPIC_BASE + 0x380)
+#define LAPIC_TIMER_CURRENT                    (LAPIC_BASE + 0x390)
+#define LAPIC_TIMER_DIVIDE                     (LAPIC_BASE + 0x3e0)
+#define LAPIC_TIMER_DEFAULT_VECTOR     0xeb
+#define LAPIC_TIMER_DEFAULT_DIVISOR    0xa // This is 128.  Ref SDM 3.a 9.6.4
+// IPI Interrupt Command Register
+#define LAPIC_IPI_ICR_LOWER                    (LAPIC_BASE + 0x300)
+#define LAPIC_IPI_ICR_UPPER                    (LAPIC_BASE + 0x310)
+
+// IOAPIC
+#define IOAPIC_BASE                                    0xfec00000 // this is the default, can be changed
+
+// PIT (Programmable Interval Timer)
+#define        TIMER_REG_CNTR0 0       /* timer 0 counter port */
+#define        TIMER_REG_CNTR1 1       /* timer 1 counter port */
+#define        TIMER_REG_CNTR2 2       /* timer 2 counter port */
+#define        TIMER_REG_MODE  3       /* timer mode port */
+#define        TIMER_SEL0      0x00    /* select counter 0 */
+#define        TIMER_SEL1      0x40    /* select counter 1 */
+#define        TIMER_SEL2      0x80    /* select counter 2 */
+#define        TIMER_INTTC     0x00    /* mode 0, intr on terminal cnt */
+#define        TIMER_ONESHOT   0x02    /* mode 1, one shot */
+#define        TIMER_RATEGEN   0x04    /* mode 2, rate generator */
+#define        TIMER_SQWAVE    0x06    /* mode 3, square wave */
+#define        TIMER_SWSTROBE  0x08    /* mode 4, s/w triggered strobe */
+#define        TIMER_HWSTROBE  0x0a    /* mode 5, h/w triggered strobe */
+#define        TIMER_LATCH     0x00    /* latch counter for reading */
+#define        TIMER_LSB       0x10    /* r/w counter LSB */
+#define        TIMER_MSB       0x20    /* r/w counter MSB */
+#define        TIMER_16BIT     0x30    /* r/w counter 16 bits, LSB first */
+#define        TIMER_BCD       0x01    /* count in BCD */
+
+#define PIT_FREQ                                       1193182
+
+#define IO_TIMER1   0x40        /* 8253 Timer #1 */
+#define TIMER_CNTR0 (IO_TIMER1 + TIMER_REG_CNTR0)
+#define TIMER_CNTR1 (IO_TIMER1 + TIMER_REG_CNTR1)
+#define TIMER_CNTR2 (IO_TIMER1 + TIMER_REG_CNTR2)
+#define TIMER_MODE  (IO_TIMER1 + TIMER_REG_MODE)
+
+typedef struct system_timing {
+       uint64_t tsc_freq;
+       uint64_t bus_freq;
+       uint16_t pit_divisor;
+       uint8_t pit_mode;
+} system_timing_t;
+
+extern system_timing_t system_timing;
+
+void pic_remap(void);
+void pic_mask_irq(uint8_t irq);
+void pic_unmask_irq(uint8_t irq);
+void __lapic_set_timer(uint32_t ticks, uint8_t vec, bool periodic, uint8_t div);
+void lapic_set_timer(uint32_t usec, bool periodic);
+uint32_t lapic_get_default_id(void);
+// PIT related
+void pit_set_timer(uint32_t freq, uint32_t mode);
+void timer_init(void);
+void udelay(uint64_t usec);
+void udelay_pit(uint64_t usec);
+// TODO: right now timer defaults to TSC
+uint64_t gettimer(void);
+uint64_t inline getfreq(void);
+
+static inline void pic_send_eoi(uint32_t irq);
+static inline void lapic_send_eoi(void);
+static inline uint32_t lapic_get_version(void);
+static inline uint32_t lapic_get_error(void);
+static inline uint32_t lapic_get_id(void);
+static inline uint8_t lapic_get_logid(void);
+static inline void lapic_set_logid(uint8_t id);
+static inline void lapic_disable(void);
+static inline void lapic_enable(void);
+static inline void lapic_wait_to_send(void);
+static inline void send_init_ipi(void);
+static inline void send_startup_ipi(uint8_t vector);
+static inline void send_self_ipi(uint8_t vector);
+static inline void send_broadcast_ipi(uint8_t vector);
+static inline void send_all_others_ipi(uint8_t vector);
+static inline void send_ipi(uint8_t dest, bool logical_mode, uint8_t vector);
+
+#define mask_lapic_lvt(entry) \
+       write_mmreg32(entry, read_mmreg32(entry) | LAPIC_LVT_MASK)
+#define unmask_lapic_lvt(entry) \
+       write_mmreg32(entry, read_mmreg32(entry) & ~LAPIC_LVT_MASK)
+
+static inline void pic_send_eoi(uint32_t irq)
+{
+       // all irqs beyond the first seven need to be chained to the slave
+       if (irq > 7)
+               outb(PIC2_CMD, PIC_EOI);
+       outb(PIC1_CMD, PIC_EOI);
+}
+
+static inline void lapic_send_eoi(void)
+{
+       write_mmreg32(LAPIC_EOI, 0);
+}
+
+static inline uint32_t lapic_get_version(void)
+{
+       return read_mmreg32(LAPIC_VERSION);     
+}
+
+static inline uint32_t lapic_get_error(void)
+{
+       write_mmreg32(LAPIC_ERROR, 0xdeadbeef);
+       return read_mmreg32(LAPIC_ERROR);
+}
+
+static inline uint32_t lapic_get_id(void)
+{
+       return read_mmreg32(LAPIC_ID) >> 24;
+}
+
+static inline uint8_t lapic_get_logid(void)
+{
+       return read_mmreg32(LAPIC_LOGICAL_ID) >> 24;
+}
+
+static inline void lapic_set_logid(uint8_t id)
+{
+       write_mmreg32(LAPIC_LOGICAL_ID, id << 24);
+}
+
+/* There are a couple ways to do it.  The MSR route doesn't seem to work
+ * in KVM.  It's also a somewhat permanent thing
+ */
+static inline void lapic_disable(void)
+{
+       write_mmreg32(LAPIC_SPURIOUS, read_mmreg32(LAPIC_SPURIOUS) & 0xffffefff);
+       //write_msr(IA32_APIC_BASE, read_msr(IA32_APIC_BASE) & ~MSR_APIC_ENABLE);
+}
+
+/* Spins until previous IPIs are delivered.  Not sure if we want it inlined
+ * Also not sure when we really need to do this. 
+ */
+static inline void lapic_wait_to_send(void)
+{
+       while(read_mmreg32(LAPIC_IPI_ICR_LOWER) & 0x1000)
+               cpu_relax();
+}
+
+static inline void lapic_enable(void)
+{
+       write_mmreg32(LAPIC_SPURIOUS, read_mmreg32(LAPIC_SPURIOUS) | 0x00000100);
+}
+
+static inline void send_init_ipi(void)
+{
+       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4500);
+}
+
+static inline void send_startup_ipi(uint8_t vector)
+{
+       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4600 | vector);
+}
+
+static inline void send_self_ipi(uint8_t vector)
+{
+       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00044000 | vector);
+}
+
+static inline void send_broadcast_ipi(uint8_t vector)
+{
+       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00084000 | vector);
+}
+
+static inline void send_all_others_ipi(uint8_t vector)
+{
+       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4000 | vector);
+}
+
+static inline void send_ipi(uint8_t dest, bool logical_mode, uint8_t vector)
+{
+       write_mmreg32(LAPIC_IPI_ICR_UPPER, dest << 24);
+       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00004000 | (logical_mode << 11) | vector);
+}
+
+/* To change the LAPIC Base (not recommended):
+       msr_val = read_msr(IA32_APIC_BASE);
+       msr_val = msr_val & ~MSR_APIC_BASE_ADDRESS | 0xfaa00000;
+       write_msr(IA32_APIC_BASE, msr_val);
+*/
+#endif /* ROS_KERN_APIC_H */
diff --git a/include/arch/console.h b/include/arch/console.h
new file mode 100644 (file)
index 0000000..e6528dc
--- /dev/null
@@ -0,0 +1,27 @@
+/* See COPYRIGHT for copyright information. */
+
+#ifndef _CONSOLE_H_
+#define _CONSOLE_H_
+#ifndef ROS_KERNEL
+# error "This is a ROS kernel header; user programs should not #include it"
+#endif
+
+#include <arch/types.h>
+
+#define MONO_BASE      0x3B4
+#define MONO_BUF       0xB0000
+#define CGA_BASE       0x3D4
+#define CGA_BUF                0xB8000
+
+#define CRT_ROWS       25
+#define CRT_COLS       80
+#define CRT_SIZE       (CRT_ROWS * CRT_COLS)
+
+void cons_init(void);
+void cons_putc(int c);
+int cons_getc(void);
+
+void kbd_intr(void); // irq 1
+void serial_intr(void); // irq 4
+
+#endif /* _CONSOLE_H_ */
diff --git a/include/arch/elf.h b/include/arch/elf.h
new file mode 100644 (file)
index 0000000..602f73a
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef ROS_INC_ELF_H
+#define ROS_INC_ELF_H
+
+#define ELF_MAGIC 0x464C457FU  /* "\x7FELF" in little endian */
+
+#include <arch/types.h>
+
+typedef struct Elf {
+       uint32_t e_magic;       // must equal ELF_MAGIC
+       uint8_t e_elf[12];
+       uint16_t e_type;
+       uint16_t e_machine;
+       uint32_t e_version;
+       uint32_t e_entry;
+       uint32_t e_phoff;
+       uint32_t e_shoff;
+       uint32_t e_flags;
+       uint16_t e_ehsize;
+       uint16_t e_phentsize;
+       uint16_t e_phnum;
+       uint16_t e_shentsize;
+       uint16_t e_shnum;
+       uint16_t e_shstrndx;
+} elf_t;
+
+typedef struct Proghdr {
+       uint32_t p_type;
+       uint32_t p_offset;
+       uint32_t p_va;
+       uint32_t p_pa;
+       uint32_t p_filesz;
+       uint32_t p_memsz;
+       uint32_t p_flags;
+       uint32_t p_align;
+} proghdr_t;
+
+typedef struct Secthdr {
+       uint32_t sh_name;
+       uint32_t sh_type;
+       uint32_t sh_flags;
+       uint32_t sh_addr;
+       uint32_t sh_offset;
+       uint32_t sh_size;
+       uint32_t sh_link;
+       uint32_t sh_info;
+       uint32_t sh_addralign;
+       uint32_t sh_entsize;
+} secthdr_t;
+
+// Values for Proghdr::p_type
+#define ELF_PROG_LOAD          1
+
+// Flag bits for Proghdr::p_flags
+#define ELF_PROG_FLAG_EXEC     1
+#define ELF_PROG_FLAG_WRITE    2
+#define ELF_PROG_FLAG_READ     4
+
+// Values for Secthdr::sh_type
+#define ELF_SHT_NULL           0
+#define ELF_SHT_PROGBITS       1
+#define ELF_SHT_SYMTAB         2
+#define ELF_SHT_STRTAB         3
+
+// Values for Secthdr::sh_name
+#define ELF_SHN_UNDEF          0
+
+#endif /* !ROS_INC_ELF_H */
diff --git a/include/arch/mmu.h b/include/arch/mmu.h
new file mode 100644 (file)
index 0000000..43d35d1
--- /dev/null
@@ -0,0 +1,336 @@
+#ifndef ROS_INC_MMU_H
+#define ROS_INC_MMU_H
+
+/*
+ * This file contains definitions for the x86 memory management unit (MMU),
+ * including paging- and segmentation-related data structures and constants,
+ * the %cr0, %cr4, and %eflags registers, and traps.
+ */
+
+/*
+ *
+ *     Part 1.  Paging data structures and constants.
+ *
+ */
+
+// A linear address 'la' has a three-part structure as follows:
+//
+// +--------10------+-------10-------+---------12----------+
+// | Page Directory |   Page Table   | Offset within Page  |
+// |      Index     |      Index     |                     |
+// +----------------+----------------+---------------------+
+//  \--- PDX(la) --/ \--- PTX(la) --/ \---- PGOFF(la) ----/
+//  \----------- PPN(la) -----------/
+//
+// The PDX, PTX, PGOFF, and PPN macros decompose linear addresses as shown.
+// To construct a linear address la from PDX(la), PTX(la), and PGOFF(la),
+// use PGADDR(PDX(la), PTX(la), PGOFF(la)).
+
+// page number field of address
+#define PPN(la)                (((uintptr_t) (la)) >> PTXSHIFT)
+#define VPN(la)                PPN(la)         // used to index into vpt[]
+
+// page directory index
+#define PDX(la)                ((((uintptr_t) (la)) >> PDXSHIFT) & 0x3FF)
+#define VPD(la)                PDX(la)         // used to index into vpd[]
+
+// page table index
+#define PTX(la)                ((((uintptr_t) (la)) >> PTXSHIFT) & 0x3FF)
+
+// offset in page
+#define PGOFF(la)      (((uintptr_t) (la)) & 0xFFF)
+
+// offset in jumbo page
+#define JPGOFF(la)     (((uintptr_t) (la)) & 0x003FFFFF)
+
+// construct linear address from indexes and offset
+#define PGADDR(d, t, o)        ((void*) ((d) << PDXSHIFT | (t) << PTXSHIFT | (o)))
+
+// Page directory and page table constants.
+#define NPDENTRIES     1024            // page directory entries per page directory
+#define NPTENTRIES     1024            // page table entries per page table
+
+#define PGSIZE         4096            // bytes mapped by a page
+#define JPGSIZE                4096*1024       // bytes mapped by a jumbo page (4MB)
+#define PGSHIFT                12              // log2(PGSIZE)
+
+#define PTSIZE         (PGSIZE*NPTENTRIES) // bytes mapped by a page directory entry
+#define PTSHIFT                22              // log2(PTSIZE)
+
+#define PTXSHIFT       12              // offset of PTX in a linear address
+#define PDXSHIFT       22              // offset of PDX in a linear address
+
+// Page table/directory entry flags.
+#define PTE_P          0x001   // Present
+#define PTE_W          0x002   // Writeable
+#define PTE_U          0x004   // User
+#define PTE_PWT                0x008   // Write-Through
+#define PTE_PCD                0x010   // Cache-Disable
+#define PTE_A          0x020   // Accessed
+#define PTE_D          0x040   // Dirty
+#define PTE_PS         0x080   // Page Size (only applies to PDEs)
+#define PTE_PAT                0x080   // PAT (only applies to second layer PTEs)
+#define PTE_G          0x100   // Global Page
+
+// The PTE_AVAIL bits aren't used by the kernel or interpreted by the
+// hardware, so user processes are allowed to set them arbitrarily.
+#define PTE_AVAIL      0xE00   // Available for software use
+
+// Only flags in PTE_USER may be used in system calls.
+#define PTE_USER       (PTE_AVAIL | PTE_P | PTE_W | PTE_U)
+
+// address in page table entry
+#define PTE_ADDR(pte)  ((physaddr_t) (pte) & ~0xFFF)
+
+// Control Register flags
+#define CR0_PE         0x00000001      // Protection Enable
+#define CR0_MP         0x00000002      // Monitor coProcessor
+#define CR0_EM         0x00000004      // Emulation
+#define CR0_TS         0x00000008      // Task Switched
+#define CR0_ET         0x00000010      // Extension Type
+#define CR0_NE         0x00000020      // Numeric Error
+#define CR0_WP         0x00010000      // Write Protect
+#define CR0_AM         0x00040000      // Alignment Mask
+#define CR0_NW         0x20000000      // Not Writethrough - more tricky than it sounds
+#define CR0_CD         0x40000000      // Cache Disable
+#define CR0_PG         0x80000000      // Paging
+
+// These two relate to the cacheability (L1, etc) of the page directory
+#define CR3_PWT                0x00000008      // Page directory caching write through
+#define CR3_PCD                0x00000010      // Page directory caching disabled
+
+#define CR4_VME                0x00000001      // V86 Mode Extensions
+#define CR4_PVI                0x00000002      // Protected-Mode Virtual Interrupts
+#define CR4_TSD                0x00000004      // Time Stamp Disable
+#define CR4_DE         0x00000008      // Debugging Extensions
+#define CR4_PSE                0x00000010      // Page Size Extensions
+#define CR4_PAE                0x00000020      // Physical Address Extensions
+#define CR4_MCE                0x00000040      // Machine Check Enable
+#define CR4_PGE                0x00000080      // Global Pages Enabled
+#define CR4_PCE                0x00000100      // Performance counter enable
+#define CR4_OSFXSR     0x00000200      // OS support for FXSAVE/FXRSTOR
+#define CR4_OSXMME     0x00000400      // OS support for unmasked SIMD FP exceptions
+#define CR4_VMXE       0x00002000      // VMX enable
+#define CR4_SMXE       0x00004000      // SMX enable
+#define CR4_OSXSAVE    0x00040000      // XSAVE and processor extended states-enabled
+
+// Eflags register
+#define FL_CF          0x00000001      // Carry Flag
+#define FL_PF          0x00000004      // Parity Flag
+#define FL_AF          0x00000010      // Auxiliary carry Flag
+#define FL_ZF          0x00000040      // Zero Flag
+#define FL_SF          0x00000080      // Sign Flag
+#define FL_TF          0x00000100      // Trap Flag
+#define FL_IF          0x00000200      // Interrupt Flag
+#define FL_DF          0x00000400      // Direction Flag
+#define FL_OF          0x00000800      // Overflow Flag
+#define FL_IOPL_MASK   0x00003000      // I/O Privilege Level bitmask
+#define FL_IOPL_0      0x00000000      //   IOPL == 0
+#define FL_IOPL_1      0x00001000      //   IOPL == 1
+#define FL_IOPL_2      0x00002000      //   IOPL == 2
+#define FL_IOPL_3      0x00003000      //   IOPL == 3
+#define FL_NT          0x00004000      // Nested Task
+#define FL_RF          0x00010000      // Resume Flag
+#define FL_VM          0x00020000      // Virtual 8086 mode
+#define FL_AC          0x00040000      // Alignment Check
+#define FL_VIF         0x00080000      // Virtual Interrupt Flag
+#define FL_VIP         0x00100000      // Virtual Interrupt Pending
+#define FL_ID          0x00200000      // ID flag
+
+// Page fault error codes
+#define FEC_PR         0x1     // Page fault caused by protection violation
+#define FEC_WR         0x2     // Page fault caused by a write
+#define FEC_U          0x4     // Page fault occured while in user mode
+
+
+/*
+ *
+ *     Part 2.  Segmentation data structures and constants.
+ *
+ */
+
+// Global descriptor numbers
+#define GD_KT     0x08     // kernel text
+#define GD_KD     0x10     // kernel data
+#define GD_UT     0x18     // user text
+#define GD_UD     0x20     // user data
+#define GD_TSS    0x28     // Task segment selector
+
+#ifdef __ASSEMBLER__
+
+/*
+ * Macros to build GDT entries in assembly.
+ */
+#define SEG_NULL                                               \
+       .word 0, 0;                                             \
+       .byte 0, 0, 0, 0
+#define SEG(type,base,lim)                                     \
+       .word (((lim) >> 12) & 0xffff), ((base) & 0xffff);      \
+       .byte (((base) >> 16) & 0xff), (0x90 | (type)),         \
+               (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
+
+#else  // not __ASSEMBLER__
+
+#include <arch/types.h>
+
+// Segment Descriptors
+typedef struct Segdesc {
+       unsigned sd_lim_15_0 : 16;  // Low bits of segment limit
+       unsigned sd_base_15_0 : 16; // Low bits of segment base address
+       unsigned sd_base_23_16 : 8; // Middle bits of segment base address
+       unsigned sd_type : 4;       // Segment type (see STS_ constants)
+       unsigned sd_s : 1;          // 0 = system, 1 = application
+       unsigned sd_dpl : 2;        // Descriptor Privilege Level
+       unsigned sd_p : 1;          // Present
+       unsigned sd_lim_19_16 : 4;  // High bits of segment limit
+       unsigned sd_avl : 1;        // Unused (available for software use)
+       unsigned sd_rsv1 : 1;       // Reserved
+       unsigned sd_db : 1;         // 0 = 16-bit segment, 1 = 32-bit segment
+       unsigned sd_g : 1;          // Granularity: limit scaled by 4K when set
+       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 }
+// 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 }
+// Normal segment
+#define SEG(type, base, lim, dpl) (segdesc_t)                                          \
+{ ((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)                                                \
+{ (lim) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff,                      \
+    type, 1, dpl, 1, (unsigned) (lim) >> 16, 0, 0, 1, 0,                       \
+    (unsigned) (base) >> 24 }
+
+#endif /* !__ASSEMBLER__ */
+
+// Application segment type bits
+#define STA_X          0x8         // Executable segment
+#define STA_E          0x4         // Expand down (non-executable segments)
+#define STA_C          0x4         // Conforming code segment (executable only)
+#define STA_W          0x2         // Writeable (non-executable segments)
+#define STA_R          0x2         // Readable (executable segments)
+#define STA_A          0x1         // Accessed
+
+// System segment type bits
+#define STS_T16A       0x1         // Available 16-bit TSS
+#define STS_LDT                0x2         // Local Descriptor Table
+#define STS_T16B       0x3         // Busy 16-bit TSS
+#define STS_CG16       0x4         // 16-bit Call Gate
+#define STS_TG         0x5         // Task Gate / Coum Transmitions
+#define STS_IG16       0x6         // 16-bit Interrupt Gate
+#define STS_TG16       0x7         // 16-bit Trap Gate
+#define STS_T32A       0x9         // Available 32-bit TSS
+#define STS_T32B       0xB         // Busy 32-bit TSS
+#define STS_CG32       0xC         // 32-bit Call Gate
+#define STS_IG32       0xE         // 32-bit Interrupt Gate
+#define STS_TG32       0xF         // 32-bit Trap Gate
+
+#define SEG_COUNT      6               // Number of segments in the steady state
+
+/*
+ *
+ *     Part 3.  Traps.
+ *
+ */
+
+#ifndef __ASSEMBLER__
+
+// Task state segment format (as described by the Pentium architecture book)
+typedef struct Taskstate {
+       uint32_t ts_link;       // Old ts selector
+       uintptr_t ts_esp0;      // Stack pointers and segment selectors
+       uint16_t ts_ss0;        //   after an increase in privilege level
+       uint16_t ts_padding1;
+       uintptr_t ts_esp1;
+       uint16_t ts_ss1;
+       uint16_t ts_padding2;
+       uintptr_t ts_esp2;
+       uint16_t ts_ss2;
+       uint16_t ts_padding3;
+       physaddr_t ts_cr3;      // Page directory base
+       uintptr_t ts_eip;       // Saved state from last task switch
+       uint32_t ts_eflags;
+       uint32_t ts_eax;        // More saved state (registers)
+       uint32_t ts_ecx;
+       uint32_t ts_edx;
+       uint32_t ts_ebx;
+       uintptr_t ts_esp;
+       uintptr_t ts_ebp;
+       uint32_t ts_esi;
+       uint32_t ts_edi;
+       uint16_t ts_es;         // Even more saved state (segment selectors)
+       uint16_t ts_padding4;
+       uint16_t ts_cs;
+       uint16_t ts_padding5;
+       uint16_t ts_ss;
+       uint16_t ts_padding6;
+       uint16_t ts_ds;
+       uint16_t ts_padding7;
+       uint16_t ts_fs;
+       uint16_t ts_padding8;
+       uint16_t ts_gs;
+       uint16_t ts_padding9;
+       uint16_t ts_ldt;
+       uint16_t ts_padding10;
+       uint16_t ts_t;          // Trap on task switch
+       uint16_t ts_iomb;       // I/O map base address
+} taskstate_t;
+
+// Gate descriptors for interrupts and traps
+typedef struct Gatedesc {
+       unsigned gd_off_15_0 : 16;   // low 16 bits of offset in segment
+       unsigned gd_ss : 16;         // segment selector
+       unsigned gd_args : 5;        // # args, 0 for interrupt/trap gates
+       unsigned gd_rsv1 : 3;        // reserved(should be zero I guess)
+       unsigned gd_type : 4;        // type(STS_{TG,IG32,TG32})
+       unsigned gd_s : 1;           // must be 0 (system)
+       unsigned gd_dpl : 2;         // DPL - highest ring allowed to use this
+       unsigned gd_p : 1;           // Present
+       unsigned gd_off_31_16 : 16;  // high bits of offset in segment
+} gatedesc_t;
+
+// Set up a normal interrupt/trap gate descriptor.
+// - istrap: 1 for a trap (= exception) gate, 0 for an interrupt gate.
+// - sel: Code segment selector for interrupt/trap handler
+// - off: Offset in code segment for interrupt/trap handler
+// - dpl: Descriptor Privilege Level -
+//       the privilege level required for software to invoke
+//       this interrupt/trap gate explicitly using an int instruction.
+#define SETGATE(gate, istrap, sel, off, dpl)                   \
+{                                                              \
+       (gate).gd_off_15_0 = (uint32_t) (off) & 0xffff;         \
+       (gate).gd_ss = (sel);                                   \
+       (gate).gd_args = 0;                                     \
+       (gate).gd_rsv1 = 0;                                     \
+       (gate).gd_type = (istrap) ? STS_TG32 : STS_IG32;        \
+       (gate).gd_s = 0;                                        \
+       (gate).gd_dpl = (dpl);                                  \
+       (gate).gd_p = 1;                                        \
+       (gate).gd_off_31_16 = (uint32_t) (off) >> 16;           \
+}
+
+// Set up a call gate descriptor.
+#define SETCALLGATE(gate, ss, off, dpl)                        \
+{                                                              \
+       (gate).gd_off_15_0 = (uint32_t) (off) & 0xffff;         \
+       (gate).gd_ss = (ss);                                    \
+       (gate).gd_args = 0;                                     \
+       (gate).gd_rsv1 = 0;                                     \
+       (gate).gd_type = STS_CG32;                              \
+       (gate).gd_s = 0;                                        \
+       (gate).gd_dpl = (dpl);                                  \
+       (gate).gd_p = 1;                                        \
+       (gate).gd_off_31_16 = (uint32_t) (off) >> 16;           \
+}
+
+// Pseudo-descriptors used for LGDT, LLDT and LIDT instructions.
+typedef struct Pseudodesc {
+       uint16_t pd_lim;                // Limit
+       uint32_t pd_base;               // Base address
+} __attribute__ ((packed)) pseudodesc_t;
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* !ROS_INC_MMU_H */
diff --git a/include/arch/multiboot.h b/include/arch/multiboot.h
new file mode 100644 (file)
index 0000000..b32982a
--- /dev/null
@@ -0,0 +1,119 @@
+     /* multiboot.h - the header for Multiboot */
+     /* Copyright (C) 1999, 2001  Free Software Foundation, Inc.
+     
+        This program is free software; you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation; either version 2 of the License, or
+        (at your option) any later version.
+     
+        This program is distributed in the hope that it will be useful,
+        but WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+        GNU General Public License for more details.
+     
+        You should have received a copy of the GNU General Public License
+        along with this program; if not, write to the Free Software
+        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+     
+     /* Macros. */
+     
+     /* The magic number for the Multiboot header. */
+     #define MULTIBOOT_HEADER_MAGIC          0x1BADB002
+     
+     /* The flags for the Multiboot header. */
+     #ifdef __ELF__
+     # define MULTIBOOT_HEADER_FLAGS         0x00000003
+     #else
+     # define MULTIBOOT_HEADER_FLAGS         0x00010003
+     #endif
+     
+     /* The magic number passed by a Multiboot-compliant boot loader. */
+     #define MULTIBOOT_BOOTLOADER_MAGIC      0x2BADB002
+     
+     /* The size of our stack (16KB). */
+     #define STACK_SIZE                      0x4000
+     
+     /* C symbol format. HAVE_ASM_USCORE is defined by configure. */
+     #ifdef HAVE_ASM_USCORE
+     # define EXT_C(sym)                     _ ## sym
+     #else
+     # define EXT_C(sym)                     sym
+     #endif
+     
+     #ifndef ASM
+     /* Do not include here in boot.S. */
+     
+     /* Types. */
+     
+     /* The Multiboot header. */
+     typedef struct multiboot_header
+     {
+       unsigned long magic;
+       unsigned long flags;
+       unsigned long checksum;
+       unsigned long header_addr;
+       unsigned long load_addr;
+       unsigned long load_end_addr;
+       unsigned long bss_end_addr;
+       unsigned long entry_addr;
+     } multiboot_header_t;
+     
+     /* The symbol table for a.out. */
+     typedef struct aout_symbol_table
+     {
+       unsigned long tabsize;
+       unsigned long strsize;
+       unsigned long addr;
+       unsigned long reserved;
+     } aout_symbol_table_t;
+     
+     /* The section header table for ELF. */
+     typedef struct elf_section_header_table
+     {
+       unsigned long num;
+       unsigned long size;
+       unsigned long addr;
+       unsigned long shndx;
+     } elf_section_header_table_t;
+     
+     /* The Multiboot information. */
+     typedef struct multiboot_info
+     {
+       unsigned long flags;
+       unsigned long mem_lower;
+       unsigned long mem_upper;
+       unsigned long boot_device;
+       unsigned long cmdline;
+       unsigned long mods_count;
+       unsigned long mods_addr;
+       union
+       {
+         aout_symbol_table_t aout_sym;
+         elf_section_header_table_t elf_sec;
+       } u;
+       unsigned long mmap_length;
+       unsigned long mmap_addr;
+     } multiboot_info_t;
+     
+     /* The module structure. */
+     typedef struct module
+     {
+       unsigned long mod_start;
+       unsigned long mod_end;
+       unsigned long string;
+       unsigned long reserved;
+     } module_t;
+     
+     /* The memory map. Be careful that the offset 0 is base_addr_low
+        but no size. */
+     typedef struct memory_map
+     {
+       unsigned long size;
+       unsigned long base_addr_low;
+       unsigned long base_addr_high;
+       unsigned long length_low;
+       unsigned long length_high;
+       unsigned long type;
+     } memory_map_t;
+     
+     #endif /* ! ASM */
diff --git a/include/arch/smp.h b/include/arch/smp.h
new file mode 100644 (file)
index 0000000..3599d0d
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef ROS_INC_SMP_H
+#define ROS_INC_SMP_H
+
+/* SMP related functions */
+
+#include <arch/types.h>
+#include <ros/queue.h>
+#include <atomic.h>
+#include <trap.h>
+
+#ifdef __BOCHS__
+#define SMP_CALL_FUNCTION_TIMEOUT    0x00ffffff
+#define SMP_BOOT_TIMEOUT             0x0000ffff
+#else
+#define SMP_CALL_FUNCTION_TIMEOUT    0x7ffffff0
+#define SMP_BOOT_TIMEOUT             0x002fffff
+#endif
+
+// be careful changing this, esp if you go over 16
+#define NUM_HANDLER_WRAPPERS           5
+
+typedef struct HandlerWrapper {
+       checklist_t* cpu_list;
+       uint8_t vector;
+} handler_wrapper_t;
+
+/* SMP bootup functions */
+void smp_boot(void);
+void smp_idle(void);
+
+/* SMP utility functions */
+int smp_call_function_self(isr_t handler, void* data,
+                           handler_wrapper_t** wait_wrapper);
+int smp_call_function_all(isr_t handler, void* data,
+                          handler_wrapper_t** wait_wrapper);
+int smp_call_function_single(uint8_t dest, isr_t handler, void* data,
+                             handler_wrapper_t** wait_wrapper);
+int smp_call_wait(handler_wrapper_t* wrapper);
+
+#endif /* !ROS_INC_SMP_H */
diff --git a/include/arch/stab.h b/include/arch/stab.h
new file mode 100644 (file)
index 0000000..9363d1f
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef ROS_STAB_H
+#define ROS_STAB_H
+#include <arch/types.h>
+
+// <inc/stab.h>
+// STABS debugging info
+
+// The ROS kernel debugger can understand some debugging information
+// in the STABS format.  For more information on this format, see
+// http://sources.redhat.com/gdb/onlinedocs/stabs_toc.html
+
+// The constants below define some symbol types used by various debuggers
+// and compilers.  ROS uses the N_SO, N_SOL, N_FUN, and N_SLINE types.
+
+#define        N_GSYM          0x20    // global symbol
+#define        N_FNAME         0x22    // F77 function name
+#define        N_FUN           0x24    // procedure name
+#define        N_STSYM         0x26    // data segment variable
+#define        N_LCSYM         0x28    // bss segment variable
+#define        N_MAIN          0x2a    // main function name
+#define        N_PC            0x30    // global Pascal symbol
+#define        N_RSYM          0x40    // register variable
+#define        N_SLINE         0x44    // text segment line number
+#define        N_DSLINE        0x46    // data segment line number
+#define        N_BSLINE        0x48    // bss segment line number
+#define        N_SSYM          0x60    // structure/union element
+#define        N_SO            0x64    // main source file name
+#define        N_LSYM          0x80    // stack variable
+#define        N_BINCL         0x82    // include file beginning
+#define        N_SOL           0x84    // included source file name
+#define        N_PSYM          0xa0    // parameter variable
+#define        N_EINCL         0xa2    // include file end
+#define        N_ENTRY         0xa4    // alternate entry point
+#define        N_LBRAC         0xc0    // left bracket
+#define        N_EXCL          0xc2    // deleted include file
+#define        N_RBRAC         0xe0    // right bracket
+#define        N_BCOMM         0xe2    // begin common
+#define        N_ECOMM         0xe4    // end common
+#define        N_ECOML         0xe8    // end common (local name)
+#define        N_LENG          0xfe    // length of preceding entry
+
+// Entries in the STABS table are formatted as follows.
+typedef struct Stab {
+       uint32_t n_strx;        // index into string table of name
+       uint8_t n_type;         // type of symbol
+       uint8_t n_other;        // misc info (usually empty)
+       uint16_t n_desc;        // description field
+       uintptr_t n_value;      // value of symbol
+} stab_t;
+
+#endif /* !ROS_STAB_H */
diff --git a/include/arch/timer.h b/include/arch/timer.h
new file mode 100644 (file)
index 0000000..6d5115a
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef ROS_INC_TIMER_H
+#define ROS_INC_TIMER_H
+
+#include <pool.h>
+#include <string.h>
+
+#define TIMER_TAG_SIZE 20
+#define MAX_TIMERS 20
+
+/* start_timing()
+ * This function simply reads the tsc in a serialized fashion and returns its
+ * 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));
+
+/* stop_timing()
+ * This function reads the tsc in a serialized fashion and subtracts the value
+ * it reads from the value passed in as a paramter in order to determine the 
+ * difference between the two values.  A global timing_overhead value is also 
+ * subtracted to compensate for the overhead associated with calling both
+ * start and stop timing and returning their values.
+ * 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));
+
+/* train_timing()
+ * This function is intended to train the timing_overhead variable for use by
+ * stop_timing().  It runs through a loop calling start/stop and averaging the 
+ * overhead of calling them without doing any useful work in between.
+ */
+void train_timing();
+
+/* timer_t
+ * This struct is used to keep track of counter values as they are spread
+ * throughput code and timing measurements are made calling TAGGED_TIMING_BEGIN
+ * and TAGGED_TIMING_END
+ */
+typedef struct Timer{
+       uint64_t curr_run;
+       uint64_t aggr_run;
+       char label[TIMER_TAG_SIZE];
+} timer_t;
+
+//TODO: ifdef measurement? error check when pool runs low
+#define TAGGED_TIMING_BEGIN(tag)                    \
+       static timer_t* _timer_##tag = NULL;            \
+       if (_timer_##tag == NULL) {                     \
+               _timer_##tag = POOL_GET(&timer_pool);       \
+               strcpy((_timer_##tag->label), #tag);        \
+               _timer_##tag->aggr_run = 0;                 \
+       }                                               \
+       _timer_##tag->curr_run = start_timing();
+#define TAGGED_TIMING_END(tag)                                              \
+({                                                                          \
+       _timer_##tag->curr_run = stop_timing(_timer_##tag->curr_run);           \
+       _timer_##tag->aggr_run += _timer_##tag->curr_run;                       \
+})
+
+#endif /* !ROS_INC_TIMER_H */
+
diff --git a/include/arch/types.h b/include/arch/types.h
new file mode 100644 (file)
index 0000000..d1f7a21
--- /dev/null
@@ -0,0 +1,142 @@
+#ifndef ROS_INC_TYPES_H
+#define ROS_INC_TYPES_H
+
+#ifndef NULL
+#define NULL ((void*) 0)
+#endif
+
+#ifndef TRUE
+#define TRUE   1
+#endif
+
+#ifndef FALSE
+#define FALSE  0
+#endif
+
+// Represents true-or-false values
+typedef int bool;
+
+// Explicitly-sized versions of integer types
+typedef __signed char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t;
+typedef unsigned short uint16_t;
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef long long int64_t;
+typedef unsigned long long uint64_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;
+
+// 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)); \
+})
+
+// Return the offset of 'member' relative to the beginning of a struct type
+#define offsetof(type, member)  ((size_t) (&((type*)0)->member))
+
+// 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 */
diff --git a/include/arch/x86.h b/include/arch/x86.h
new file mode 100644 (file)
index 0000000..fc21511
--- /dev/null
@@ -0,0 +1,421 @@
+#ifndef ROS_INC_X86_H
+#define ROS_INC_X86_H
+
+#include <arch/types.h>
+#include <arch/mmu.h>
+
+#define CHECK_FLAG(flags,bit)   ((flags) & (1 << (bit)))
+
+/* Model Specific Registers */
+#define IA32_APIC_BASE                         0x1b
+#define IA32_MTRR_DEF_TYPE                     0x2ff
+#define IA32_MTRR_PHYSBASE0                    0x200
+#define IA32_MTRR_PHYSMASK0                    0x201
+#define IA32_MTRR_PHYSBASE1                    0x202
+#define IA32_MTRR_PHYSMASK1                    0x203
+#define IA32_MTRR_PHYSBASE2                    0x204
+#define IA32_MTRR_PHYSMASK2                    0x205
+#define IA32_MTRR_PHYSBASE3                    0x206
+#define IA32_MTRR_PHYSMASK3                    0x207
+#define IA32_MTRR_PHYSBASE4                    0x208
+#define IA32_MTRR_PHYSMASK4                    0x209
+#define IA32_MTRR_PHYSBASE5                    0x20a
+#define IA32_MTRR_PHYSMASK5                    0x20b
+#define IA32_MTRR_PHYSBASE6                    0x20c
+#define IA32_MTRR_PHYSMASK6                    0x20d
+#define IA32_MTRR_PHYSBASE7                    0x20e
+#define IA32_MTRR_PHYSMASK7                    0x20f
+
+#define MSR_APIC_ENABLE                                0x00000800
+#define MSR_APIC_BASE_ADDRESS          0x0000000FFFFFF000
+
+/* CPUID */
+#define CPUID_PSE_SUPPORT                      0x00000008
+
+/* Arch Constants */
+#define MAX_NUM_CPUS                           255
+
+static __inline void breakpoint(void) __attribute__((always_inline));
+static __inline uint8_t inb(int port) __attribute__((always_inline));
+static __inline void insb(int port, void *addr, int cnt) __attribute__((always_inline));
+static __inline uint16_t inw(int port) __attribute__((always_inline));
+static __inline void insw(int port, void *addr, int cnt) __attribute__((always_inline));
+static __inline uint32_t inl(int port) __attribute__((always_inline));
+static __inline void insl(int port, void *addr, int cnt) __attribute__((always_inline));
+static __inline void outb(int port, uint8_t data) __attribute__((always_inline));
+static __inline void outsb(int port, const void *addr, int cnt) __attribute__((always_inline));
+static __inline void outw(int port, uint16_t data) __attribute__((always_inline));
+static __inline void outsw(int port, const void *addr, int cnt) __attribute__((always_inline));
+static __inline void outsl(int port, const void *addr, int cnt) __attribute__((always_inline));
+static __inline void outl(int port, uint32_t data) __attribute__((always_inline));
+static __inline void invlpg(void *addr) __attribute__((always_inline));
+static __inline void lidt(void *p) __attribute__((always_inline));
+static __inline void lldt(uint16_t sel) __attribute__((always_inline));
+static __inline void ltr(uint16_t sel) __attribute__((always_inline));
+static __inline void lcr0(uint32_t val) __attribute__((always_inline));
+static __inline uint32_t rcr0(void) __attribute__((always_inline));
+static __inline uint32_t rcr2(void) __attribute__((always_inline));
+static __inline void lcr3(uint32_t val) __attribute__((always_inline));
+static __inline uint32_t rcr3(void) __attribute__((always_inline));
+static __inline void lcr4(uint32_t val) __attribute__((always_inline));
+static __inline uint32_t rcr4(void) __attribute__((always_inline));
+static __inline void tlbflush(void) __attribute__((always_inline));
+static __inline uint32_t read_eflags(void) __attribute__((always_inline));
+static __inline void write_eflags(uint32_t eflags) __attribute__((always_inline));
+static __inline uint32_t read_ebp(void) __attribute__((always_inline));
+static __inline uint32_t read_esp(void) __attribute__((always_inline));
+static __inline void cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp);
+static __inline uint64_t read_tsc(void) __attribute__((always_inline));
+static __inline uint64_t read_tsc_serialized(void) __attribute__((always_inline));
+static __inline uint64_t read_msr(uint32_t reg) __attribute__((always_inline));
+static __inline void write_msr(uint32_t reg, uint64_t val) __attribute__((always_inline));
+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 enable_irq(void) __attribute__((always_inline));
+static __inline void disable_irq(void) __attribute__((always_inline));
+static __inline void enable_irqsave(int8_t* state) __attribute__((always_inline));
+static __inline void disable_irqsave(int8_t* state) __attribute__((always_inline));
+static __inline void cpu_relax(void) __attribute__((always_inline));
+static __inline void wbinvd(void) __attribute__((always_inline));
+static __inline void clflush(uintptr_t* addr) __attribute__((always_inline));
+
+static __inline void
+breakpoint(void)
+{
+       __asm __volatile("int3");
+}
+
+static __inline uint8_t
+inb(int port)
+{
+       uint8_t data;
+       __asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port));
+       return data;
+}
+
+static __inline void
+insb(int port, void *addr, int cnt)
+{
+       __asm __volatile("cld\n\trepne\n\tinsb"                 :
+                        "=D" (addr), "=c" (cnt)                :
+                        "d" (port), "0" (addr), "1" (cnt)      :
+                        "memory", "cc");
+}
+
+static __inline uint16_t
+inw(int port)
+{
+       uint16_t data;
+       __asm __volatile("inw %w1,%0" : "=a" (data) : "d" (port));
+       return data;
+}
+
+static __inline void
+insw(int port, void *addr, int cnt)
+{
+       __asm __volatile("cld\n\trepne\n\tinsw"                 :
+                        "=D" (addr), "=c" (cnt)                :
+                        "d" (port), "0" (addr), "1" (cnt)      :
+                        "memory", "cc");
+}
+
+static __inline uint32_t
+inl(int port)
+{
+       uint32_t data;
+       __asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port));
+       return data;
+}
+
+static __inline void
+insl(int port, void *addr, int cnt)
+{
+       __asm __volatile("cld\n\trepne\n\tinsl"                 :
+                        "=D" (addr), "=c" (cnt)                :
+                        "d" (port), "0" (addr), "1" (cnt)      :
+                        "memory", "cc");
+}
+
+static __inline void
+outb(int port, uint8_t data)
+{
+       __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port));
+}
+
+static __inline void
+outsb(int port, const void *addr, int cnt)
+{
+       __asm __volatile("cld\n\trepne\n\toutsb"                :
+                        "=S" (addr), "=c" (cnt)                :
+                        "d" (port), "0" (addr), "1" (cnt)      :
+                        "cc");
+}
+
+static __inline void
+outw(int port, uint16_t data)
+{
+       __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port));
+}
+
+static __inline void
+outsw(int port, const void *addr, int cnt)
+{
+       __asm __volatile("cld\n\trepne\n\toutsw"                :
+                        "=S" (addr), "=c" (cnt)                :
+                        "d" (port), "0" (addr), "1" (cnt)      :
+                        "cc");
+}
+
+static __inline void
+outsl(int port, const void *addr, int cnt)
+{
+       __asm __volatile("cld\n\trepne\n\toutsl"                :
+                        "=S" (addr), "=c" (cnt)                :
+                        "d" (port), "0" (addr), "1" (cnt)      :
+                        "cc");
+}
+
+static __inline void
+outl(int port, uint32_t data)
+{
+       __asm __volatile("outl %0,%w1" : : "a" (data), "d" (port));
+}
+
+static __inline void 
+invlpg(void *addr)
+{ 
+       __asm __volatile("invlpg (%0)" : : "r" (addr) : "memory");
+}  
+
+static __inline void
+lidt(void *p)
+{
+       __asm __volatile("lidt (%0)" : : "r" (p));
+}
+
+static __inline void
+lldt(uint16_t sel)
+{
+       __asm __volatile("lldt %0" : : "r" (sel));
+}
+
+static __inline void
+ltr(uint16_t sel)
+{
+       __asm __volatile("ltr %0" : : "r" (sel));
+}
+
+static __inline void
+lcr0(uint32_t val)
+{
+       __asm __volatile("movl %0,%%cr0" : : "r" (val));
+}
+
+static __inline uint32_t
+rcr0(void)
+{
+       uint32_t val;
+       __asm __volatile("movl %%cr0,%0" : "=r" (val));
+       return val;
+}
+
+static __inline uint32_t
+rcr2(void)
+{
+       uint32_t val;
+       __asm __volatile("movl %%cr2,%0" : "=r" (val));
+       return val;
+}
+
+static __inline void
+lcr3(uint32_t val)
+{
+       __asm __volatile("movl %0,%%cr3" : : "r" (val));
+}
+
+static __inline uint32_t
+rcr3(void)
+{
+       uint32_t val;
+       __asm __volatile("movl %%cr3,%0" : "=r" (val));
+       return val;
+}
+
+static __inline void
+lcr4(uint32_t val)
+{
+       __asm __volatile("movl %0,%%cr4" : : "r" (val));
+}
+
+static __inline uint32_t
+rcr4(void)
+{
+       uint32_t cr4;
+       __asm __volatile("movl %%cr4,%0" : "=r" (cr4));
+       return cr4;
+}
+
+static __inline void
+tlbflush(void)
+{
+       uint32_t cr3;
+       __asm __volatile("movl %%cr3,%0" : "=r" (cr3));
+       __asm __volatile("movl %0,%%cr3" : : "r" (cr3));
+}
+
+static __inline uint32_t
+read_eflags(void)
+{
+        uint32_t eflags;
+        __asm __volatile("pushfl; popl %0" : "=r" (eflags));
+        return eflags;
+}
+
+static __inline void
+write_eflags(uint32_t eflags)
+{
+        __asm __volatile("pushl %0; popfl" : : "r" (eflags));
+}
+
+static __inline uint32_t
+read_ebp(void)
+{
+        uint32_t ebp;
+        __asm __volatile("movl %%ebp,%0" : "=r" (ebp));
+        return ebp;
+}
+
+static __inline uint32_t
+read_esp(void)
+{
+        uint32_t esp;
+        __asm __volatile("movl %%esp,%0" : "=r" (esp));
+        return esp;
+}
+
+static __inline void
+cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
+{
+       uint32_t eax, ebx, ecx, edx;
+       asm volatile("cpuid" 
+               : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
+               : "a" (info));
+       if (eaxp)
+               *eaxp = eax;
+       if (ebxp)
+               *ebxp = ebx;
+       if (ecxp)
+               *ecxp = ecx;
+       if (edxp)
+               *edxp = edx;
+}
+
+static __inline uint64_t
+read_tsc(void)
+{
+       uint64_t tsc;
+       __asm __volatile("rdtsc" : "=A" (tsc));
+       return tsc;
+}
+
+static __inline uint64_t 
+read_tsc_serialized(void)
+{
+    uint64_t tsc;
+       cpuid(0, 0, 0, 0, 0);
+       tsc = read_tsc();
+       return tsc;
+}
+
+// Might need to mfence rdmsr.  supposedly wrmsr serializes, but not for x2APIC
+static __inline uint64_t
+read_msr(uint32_t reg)
+{
+       uint32_t edx, eax;
+       asm volatile("rdmsr; mfence" : "=d"(edx), "=a"(eax) : "c"(reg));
+       return (uint64_t)edx << 32 | eax;
+}
+
+static __inline void
+write_msr(uint32_t reg, uint64_t val)
+{
+       asm volatile("wrmsr" : : "d"((uint32_t)(val >> 32)),
+                                "a"((uint32_t)(val & 0xFFFFFFFF)), 
+                                "c"(reg));
+}
+
+static __inline void
+write_mmreg32(uint32_t reg, uint32_t val)
+{
+       {TRUSTEDBLOCK *((volatile uint32_t*)reg) = val; }
+       //the C ends up producing better asm than this:
+       //asm volatile("movl %0, (%1)" : : "r"(val), "r"(reg));
+}
+
+static __inline uint32_t
+read_mmreg32(uint32_t reg)
+{
+       {TRUSTEDBLOCK return *((volatile uint32_t*)reg); }
+}
+
+static __inline void
+enable_irq(void)
+{
+       asm volatile("sti");
+}
+
+static __inline void
+disable_irq(void)
+{
+       asm volatile("cli");
+}
+
+static __inline void
+enable_irqsave(int8_t* state)
+{
+       // *state tracks the number of nested enables and disables
+       // initial value of state: 0 = first run / no favorite
+       // > 0 means more enabled calls have been made
+       // < 0 means more disabled calls have been made
+       // Mostly doing this so we can call disable_irqsave first if we want
+
+       // one side or another "gets a point" if interrupts were already the
+       // way it wanted to go.  o/w, state stays at 0.  if the state was not 0
+       // then, enabling/disabling isn't even an option.  just increment/decrement
+
+       // if enabling is winning or tied, make sure it's enabled
+       if ((*state == 0) && (!(read_eflags() & FL_IF)))
+               enable_irq();
+       else
+               (*state)++;
+}
+
+static __inline void
+disable_irqsave(int8_t* state)
+{
+       if ((*state == 0) && (read_eflags() & FL_IF))
+               disable_irq();
+       else 
+               (*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");
+}
+
+static __inline void
+wbinvd(void) __attribute__((always_inline))
+{
+       asm volatile("wbinvd");
+}
+
+static __inline void
+clflush(uintptr_t* addr) __attribute__((always_inline))
+{
+       asm volatile("clflush %0" : : "m"(*addr));
+}
+#endif /* !ROS_INC_X86_H */
diff --git a/include/assert.h b/include/assert.h
new file mode 100644 (file)
index 0000000..0c63ec2
--- /dev/null
@@ -0,0 +1,20 @@
+/* See COPYRIGHT for copyright information. */
+
+#ifndef ROS_INC_ASSERT_H
+#define ROS_INC_ASSERT_H
+
+#include <stdio.h>
+
+void _warn(const char* NTS, int, const char* NTS, ...);
+void _panic(const char* NTS, int, const char* NTS, ...) __attribute__((noreturn));
+
+#define warn(...) _warn(__FILE__, __LINE__, __VA_ARGS__)
+#define panic(...) _panic(__FILE__, __LINE__, __VA_ARGS__)
+
+#define assert(x)              \
+       do { if (!(x)) panic("assertion failed: %s", #x); } while (0)
+
+// static_assert(x) will generate a compile-time error if 'x' is false.
+#define static_assert(x)       switch (x) case 0: case (x):
+
+#endif /* !ROS_INC_ASSERT_H */
diff --git a/include/atomic.h b/include/atomic.h
new file mode 100644 (file)
index 0000000..bc250b1
--- /dev/null
@@ -0,0 +1,140 @@
+#ifndef ROS_KERN_ATOMIC_H
+#define ROS_KERN_ATOMIC_H
+
+#include <arch/types.h>
+#include <arch/mmu.h>
+#include <arch/x86.h>
+
+#define mb() {rmb(); wmb();}
+#define rmb() ({ asm volatile("lfence"); })
+#define wmb() 
+
+/* //linux style atomic ops
+typedef struct {uint32_t real_num;} atomic_t;
+#define atomic_read(atom) ((atom)->real_num)
+#define atomic_set(atom, val) (((atom)->real_num) = (val))
+#define atomic_init(i) {(i)}
+//and the atomic incs, etc take an atomic_t ptr, deref inside
+*/
+
+static inline void spin_lock(volatile uint32_t* lock);
+static inline void spin_unlock(volatile uint32_t* lock);
+static inline void spin_lock_irqsave(volatile uint32_t* lock);
+static inline void spin_unlock_irqsave(volatile uint32_t* lock);
+static inline void atomic_inc(volatile uint32_t* number);
+static inline void atomic_dec(volatile uint32_t* number);
+static inline void atomic_andb(volatile uint8_t* number, uint8_t mask);
+
+/*********************** 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)[];
+} checklist_mask_t;
+
+// mask contains an unspecified array, so it needs to be at the bottom
+typedef struct checklist {
+       volatile uint32_t lock;
+       checklist_mask_t mask;
+} checklist_t;
+
+#define ZEROS_ARRAY(size) {[0 ... ((size)-1)] 0}
+
+#define DEFAULT_CHECKLIST_MASK(sz) {(sz), ZEROS_ARRAY(BYTES_FOR_BITMASK(sz))}
+#define DEFAULT_CHECKLIST(sz) {0, DEFAULT_CHECKLIST_MASK(sz)}
+#define INIT_CHECKLIST(nm, sz) \
+       checklist_t nm = DEFAULT_CHECKLIST(sz);
+#define INIT_CHECKLIST_MASK(nm, sz)    \
+       checklist_mask_t nm = DEFAULT_CHECKLIST_MASK(sz);
+
+int commit_checklist_wait(checklist_t* list, checklist_mask_t* mask);
+int commit_checklist_nowait(checklist_t* list, checklist_mask_t* mask);
+int waiton_checklist(checklist_t* list);
+int release_checklist(checklist_t* list);
+int checklist_is_locked(checklist_t* list);
+int checklist_is_clear(checklist_t* list);
+void reset_checklist(checklist_t* list);
+void down_checklist(checklist_t* list);
+// TODO - do we want to adjust the size?  (YES, don't want to check it all)
+// TODO - do we want to be able to call waiton without having called commit?
+//     - in the case of protected checklists
+// TODO - want a destroy checklist (when we have kmalloc, or whatever)
+// TODO - some sort of dynamic allocation of them in the future
+// TODO - think about deadlock issues with one core spinning on a lock for
+// something that it is the hold out for...
+//     - probably should have interrupts enabled, and never grab these locks
+//     from interrupt context (and not use irq_save)
+/**************************************************************/
+
+/* Barrier: currently made for everyone barriering.  Change to use checklist */
+typedef struct barrier {
+       volatile uint32_t lock;
+       uint32_t init_count;
+       uint32_t current_count;
+    volatile uint8_t ready;
+} barrier_t;
+
+void init_barrier(barrier_t* barrier, uint32_t count);
+void reset_barrier(barrier_t* barrier);
+void waiton_barrier(barrier_t* barrier);
+
+/* Inlined functions declared above */
+static inline void spin_lock(volatile uint32_t* lock)
+{
+       asm volatile(
+                       "1:                       "
+                       "       cmpb $0, %0;          "
+                       "       je 2f;                "
+                       "       pause;                "
+                       "       jmp 1b;               "
+                       "2:                       " 
+                       "       movb $1, %%al;        "
+                       "       xchgb %%al, %0;       "
+                       "       cmpb $0, %%al;        "
+                       "       jne 1b;               "
+               : : "m"(*lock) : "eax", "cc");
+}
+
+static inline void spin_unlock(volatile uint32_t* lock)
+{
+       *lock = 0;
+}
+
+// If ints are enabled, disable them and note it in the top bit of the lock
+// There is an assumption about releasing locks in order here...
+static inline void spin_lock_irqsave(volatile uint32_t* lock)
+{
+       uint32_t eflags;
+       eflags = read_eflags();
+       disable_irq();
+       spin_lock(lock);
+       if (eflags & FL_IF)
+               *lock |= 0x80000000;
+}
+
+// if the top bit of the lock is set, then re-enable interrupts
+static inline void spin_unlock_irqsave(volatile uint32_t* lock)
+{
+       if (*lock & 0x80000000) {
+               *lock = 0;
+               enable_irq();
+       } else
+               *lock = 0;
+}
+
+// need to do this with pointers and deref.  %0 needs to be the memory address
+static inline void atomic_inc(volatile uint32_t* number)
+{
+       asm volatile("lock incl %0" : "=m"(*number) : : "cc");
+}
+
+static inline void atomic_dec(volatile uint32_t* number)
+{
+       asm volatile("lock decl %0" : "=m"(*number) : : "cc");
+}
+
+static inline void atomic_andb(volatile uint8_t* number, uint8_t mask)
+{
+       asm volatile("lock andb %1,%0" : "=m"(*number) : "r"(mask) : "cc");
+}
+#endif /* !ROS_KERN_ATOMIC_H */
diff --git a/include/env.h b/include/env.h
new file mode 100644 (file)
index 0000000..067016d
--- /dev/null
@@ -0,0 +1,42 @@
+/* See COPYRIGHT for copyright information. */
+
+#ifndef ROS_KERN_ENV_H
+#define ROS_KERN_ENV_H
+
+#include <arch/x86.h>
+#include <ros/env.h>
+
+#ifndef ROS_MULTIENV
+#define ROS_MULTIENV 0
+#endif
+
+extern env_t *envs;            // All environments
+extern env_t* NORACE curenvs[MAX_NUM_CPUS];
+
+LIST_HEAD(env_list_t, env_t);          // Declares 'struct Env_list'
+
+void   env_init(void);
+int            env_alloc(env_t **e, envid_t parent_id);
+void   env_free(env_t *e);
+void   env_create(uint8_t *binary, size_t size);
+void   (IN_HANDLER env_destroy)(env_t *e);     // Does not return if e == curenv
+
+int    envid2env(envid_t envid, env_t **env_store, bool checkperm);
+// The following two functions do not return
+void   (IN_HANDLER env_run)(env_t *e) __attribute__((noreturn));
+void   env_pop_tf(trapframe_t *tf) __attribute__((noreturn));
+
+// For the grading script
+#define ENV_CREATE2(start, size)       {               \
+       extern uint8_t start[], size[];                 \
+       env_create(start, (int)size);                   \
+}
+
+#define ENV_CREATE(x)                  {               \
+       extern uint8_t _binary_obj_##x##_start[],       \
+               _binary_obj_##x##_size[];               \
+       env_create(_binary_obj_##x##_start,             \
+               (int)_binary_obj_##x##_size);           \
+}
+
+#endif // !ROS_KERN_ENV_H
diff --git a/include/error.h b/include/error.h
new file mode 100644 (file)
index 0000000..28fa1f9
--- /dev/null
@@ -0,0 +1,24 @@
+/* See COPYRIGHT for copyright information. */
+
+#ifndef ROS_INC_ERROR_H
+#define ROS_INC_ERROR_H
+
+typedef enum {
+       E_DEADLOCK      =       -3,
+       E_BUSY          =       -2,
+       E_FAIL          =       -1,
+       E_SUCCESS       =       0,
+} error_t;
+
+// Kernel error codes -- keep in sync with list in lib/printfmt.c.
+#define E_UNSPECIFIED  1       // Unspecified or unknown problem
+#define E_BAD_ENV              2       // Environment doesn't exist or otherwise
+                                                       // cannot be used in requested action
+#define E_INVAL                        3       // Invalid parameter
+#define E_NO_MEM               4       // Request failed due to memory shortage
+#define E_NO_FREE_ENV  5       // Attempt to create a new environment beyond
+                                                       // the maximum allowed
+#define E_FAULT                        6       // Memory fault
+#define        MAXERROR                6
+
+#endif // !ROS_INC_ERROR_H */
diff --git a/include/kbdreg.h b/include/kbdreg.h
new file mode 100644 (file)
index 0000000..0c7ffea
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef ROS_KBDREG_H
+#define ROS_KBDREG_H
+
+// Special keycodes
+#define KEY_HOME       0xE0
+#define KEY_END                0xE1
+#define KEY_UP         0xE2
+#define KEY_DN         0xE3
+#define KEY_LF         0xE4
+#define KEY_RT         0xE5
+#define KEY_PGUP       0xE6
+#define KEY_PGDN       0xE7
+#define KEY_INS                0xE8
+#define KEY_DEL                0xE9
+
+
+/* This is i8042reg.h + kbdreg.h from NetBSD. */
+
+#define        KBSTATP         0x64    /* kbd controller status port(I) */
+#define         KBS_DIB        0x01    /* kbd data in buffer */
+#define         KBS_IBF        0x02    /* kbd input buffer low */
+#define         KBS_WARM       0x04    /* kbd input buffer low */
+#define         KBS_OCMD       0x08    /* kbd output buffer has command */
+#define         KBS_NOSEC      0x10    /* kbd security lock not engaged */
+#define         KBS_TERR       0x20    /* kbd transmission error */
+#define         KBS_RERR       0x40    /* kbd receive error */
+#define         KBS_PERR       0x80    /* kbd parity error */
+
+#define        KBCMDP          0x64    /* kbd controller port(O) */
+#define         KBC_RAMREAD    0x20    /* read from RAM */
+#define         KBC_RAMWRITE   0x60    /* write to RAM */
+#define         KBC_AUXDISABLE 0xa7    /* disable auxiliary port */
+#define         KBC_AUXENABLE  0xa8    /* enable auxiliary port */
+#define         KBC_AUXTEST    0xa9    /* test auxiliary port */
+#define         KBC_KBDECHO    0xd2    /* echo to keyboard port */
+#define         KBC_AUXECHO    0xd3    /* echo to auxiliary port */
+#define         KBC_AUXWRITE   0xd4    /* write to auxiliary port */
+#define         KBC_SELFTEST   0xaa    /* start self-test */
+#define         KBC_KBDTEST    0xab    /* test keyboard port */
+#define         KBC_KBDDISABLE 0xad    /* disable keyboard port */
+#define         KBC_KBDENABLE  0xae    /* enable keyboard port */
+#define         KBC_PULSE0     0xfe    /* pulse output bit 0 */
+#define         KBC_PULSE1     0xfd    /* pulse output bit 1 */
+#define         KBC_PULSE2     0xfb    /* pulse output bit 2 */
+#define         KBC_PULSE3     0xf7    /* pulse output bit 3 */
+
+#define        KBDATAP         0x60    /* kbd data port(I) */
+#define        KBOUTP          0x60    /* kbd data port(O) */
+
+#define        K_RDCMDBYTE     0x20
+#define        K_LDCMDBYTE     0x60
+
+#define        KC8_TRANS       0x40    /* convert to old scan codes */
+#define        KC8_MDISABLE    0x20    /* disable mouse */
+#define        KC8_KDISABLE    0x10    /* disable keyboard */
+#define        KC8_IGNSEC      0x08    /* ignore security lock */
+#define        KC8_CPU         0x04    /* exit from protected mode reset */
+#define        KC8_MENABLE     0x02    /* enable mouse interrupt */
+#define        KC8_KENABLE     0x01    /* enable keyboard interrupt */
+#define        CMDBYTE         (KC8_TRANS|KC8_CPU|KC8_MENABLE|KC8_KENABLE)
+
+/* keyboard commands */
+#define        KBC_RESET       0xFF    /* reset the keyboard */
+#define        KBC_RESEND      0xFE    /* request the keyboard resend the last byte */
+#define        KBC_SETDEFAULT  0xF6    /* resets keyboard to its power-on defaults */
+#define        KBC_DISABLE     0xF5    /* as per KBC_SETDEFAULT, but also disable key scanning */
+#define        KBC_ENABLE      0xF4    /* enable key scanning */
+#define        KBC_TYPEMATIC   0xF3    /* set typematic rate and delay */
+#define        KBC_SETTABLE    0xF0    /* set scancode translation table */
+#define        KBC_MODEIND     0xED    /* set mode indicators(i.e. LEDs) */
+#define        KBC_ECHO        0xEE    /* request an echo from the keyboard */
+
+/* keyboard responses */
+#define        KBR_EXTENDED    0xE0    /* extended key sequence */
+#define        KBR_RESEND      0xFE    /* needs resend of command */
+#define        KBR_ACK         0xFA    /* received a valid command */
+#define        KBR_OVERRUN     0x00    /* flooded */
+#define        KBR_FAILURE     0xFD    /* diagnosic failure */
+#define        KBR_BREAK       0xF0    /* break code prefix - sent on key release */
+#define        KBR_RSTDONE     0xAA    /* reset complete */
+#define        KBR_ECHO        0xEE    /* echo response */
+
+#endif /* !ROS_KBDREG_H */
diff --git a/include/kclock.h b/include/kclock.h
new file mode 100644 (file)
index 0000000..813d3e8
--- /dev/null
@@ -0,0 +1,33 @@
+/* See COPYRIGHT for copyright information. */
+
+#ifndef ROS_KERN_KCLOCK_H
+#define ROS_KERN_KCLOCK_H
+#ifndef ROS_KERNEL
+# error "This is a ROS kernel header; user programs should not #include it"
+#endif
+
+#define        IO_RTC          0x070           /* RTC port */
+
+#define        MC_NVRAM_START  0xe     /* start of NVRAM: offset 14 */
+#define        MC_NVRAM_SIZE   50      /* 50 bytes of NVRAM */
+
+/* NVRAM bytes 7 & 8: base memory size */
+#define NVRAM_BASELO   (MC_NVRAM_START + 7)    /* low byte; RTC off. 0x15 */
+#define NVRAM_BASEHI   (MC_NVRAM_START + 8)    /* high byte; RTC off. 0x16 */
+
+/* NVRAM bytes 9 & 10: extended memory size */
+#define NVRAM_EXTLO    (MC_NVRAM_START + 9)    /* low byte; RTC off. 0x17 */
+#define NVRAM_EXTHI    (MC_NVRAM_START + 10)   /* high byte; RTC off. 0x18 */
+
+/* NVRAM bytes 34 and 35: extended memory POSTed size */
+#define NVRAM_PEXTLO   (MC_NVRAM_START + 34)   /* low byte; RTC off. 0x30 */
+#define NVRAM_PEXTHI   (MC_NVRAM_START + 35)   /* high byte; RTC off. 0x31 */
+
+/* NVRAM byte 36: current century.  (please increment in Dec99!) */
+#define NVRAM_CENTURY  (MC_NVRAM_START + 36)   /* RTC offset 0x32 */
+
+unsigned mc146818_read(unsigned reg);
+void mc146818_write(unsigned reg, unsigned datum);
+void kclock_init(void);
+
+#endif // !ROS_KERN_KCLOCK_H
diff --git a/include/kdebug.h b/include/kdebug.h
new file mode 100644 (file)
index 0000000..0db7fc8
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef ROS_KERN_KDEBUG_H
+#define ROS_KERN_KDEBUG_H
+
+#include <arch/types.h>
+
+// Debug information about a particular instruction pointer
+typedef struct Eipdebuginfo {
+       const char *eip_file;           // Source code filename for EIP
+       int eip_line;                           // Source code linenumber for EIP
+
+       const char *eip_fn_name;        // Name of function containing EIP
+                                                               //  - Note: not null terminated!
+       int eip_fn_namelen;                     // Length of function name
+       uintptr_t eip_fn_addr;          // Address of start of function
+       int eip_fn_narg;                        // Number of function arguments
+} eipdebuginfo_t;
+
+int debuginfo_eip(uintptr_t eip, eipdebuginfo_t *info);
+
+#endif
diff --git a/include/monitor.h b/include/monitor.h
new file mode 100644 (file)
index 0000000..2b26002
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef ROS_KERN_MONITOR_H
+#define ROS_KERN_MONITOR_H
+#ifndef ROS_KERNEL
+# error "This is a ROS kernel header; user programs should not #include it"
+#endif
+
+#include <ros/trap.h>
+
+// Activate the kernel monitor,
+// optionally providing a trap frame indicating the current state
+// (NULL if none).
+void (IN_HANDLER monitor)(trapframe_t *tf);
+
+// Functions implementing monitor commands.
+int mon_help(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
+int mon_kerninfo(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
+int mon_backtrace(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
+int mon_reboot(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
+int mon_showmapping(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
+int mon_setmapperm(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
+int mon_cpuinfo(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
+
+#endif // !ROS_KERN_MONITOR_H
diff --git a/include/pmap.h b/include/pmap.h
new file mode 100644 (file)
index 0000000..223be06
--- /dev/null
@@ -0,0 +1,135 @@
+/* See COPYRIGHT for copyright information. */
+
+#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 <arch/multiboot.h>
+#include <ros/memlayout.h>
+#include <atomic.h>
+#include <env.h>
+#include <assert.h>
+
+/* This macro takes a kernel virtual address -- an address that points above
+ * KERNBASE, where the machine's maximum 256MB of physical memory is mapped --
+ * and returns the corresponding physical address.  It panics if you pass it a
+ * non-kernel virtual address.
+ */
+#define PADDR(kva)                                             \
+({                                                             \
+       physaddr_t __m_kva = (physaddr_t) (kva);                \
+       if (__m_kva < KERNBASE)                                 \
+               panic("PADDR called with invalid kva %08lx", __m_kva);\
+       __m_kva - KERNBASE;                                     \
+})
+
+/* This macro takes a physical address and returns the corresponding kernel
+ * virtual address.  It warns if you pass an invalid physical address. */
+#define KADDR(pa)                                              \
+({                                                             \
+       physaddr_t __m_pa = (pa);                               \
+       uint32_t __m_ppn = PPN(__m_pa);                         \
+       if (__m_ppn >= npage)                                   \
+               warn("KADDR called with invalid pa %08lx", __m_pa);\
+       (void*) (__m_pa + KERNBASE);                            \
+})
+
+/*
+ * Page descriptor structures, mapped at UPAGES.
+ * Read/write to the kernel, read-only to user programs.
+ *
+ * Each Page describes one physical page.
+ * You can map a Page * to the corresponding physical address
+ * with page2pa() in kern/pmap.h.
+ */
+
+struct Page;
+typedef struct Page page_t;
+
+LIST_HEAD(page_list_t, page_t);
+typedef LIST_ENTRY(page_t) page_list_entry_t;
+
+struct Page {
+       page_list_entry_t pp_link;      /* free list link */
+
+       // pp_ref is the count of pointers (usually in page table entries)
+       // to this page, for pages allocated using page_alloc.
+       // Pages allocated at boot time using pmap.c's
+       // boot_alloc do not have valid reference count fields.
+
+       uint16_t pp_ref;
+};
+
+
+extern char bootstacktop[], bootstack[];
+
+extern page_t *pages;
+extern size_t npage;
+
+extern physaddr_t boot_cr3;
+extern pde_t *boot_pgdir;
+
+extern segdesc_t (COUNT(SEG_COUNT) gdt)[];
+extern pseudodesc_t gdt_pd;
+
+void   i386_detect_memory(multiboot_info_t *mbi);
+void   i386_print_memory_map(multiboot_info_t *mbi);
+bool   enable_pse(void);
+void   i386_vm_init(void);
+
+void   page_init(void);
+void   page_check(void);
+int    page_alloc(page_t **pp_store);
+void   page_free(page_t *pp);
+int    page_insert(pde_t *pgdir, page_t *pp, void *va, int perm);
+void   page_remove(pde_t *pgdir, void *va);
+page_t *page_lookup(pde_t *pgdir, void *va, pte_t **pte_store);
+void   page_decref(page_t *pp);
+
+void setup_default_mtrrs(barrier_t* smp_barrier);
+void   tlb_invalidate(pde_t *pgdir, void *va);
+void tlb_flush_global(void);
+
+void *COUNT(len)
+user_mem_check(env_t *env, const void *DANGEROUS va, size_t len, int perm);
+
+void *COUNT(len)
+user_mem_assert(env_t *env, const void *DANGEROUS va, size_t len, int perm);
+
+static inline void cache_flush(void)
+{
+       wbinvd();
+}
+
+static inline void cacheline_flush(void* addr)
+{
+       clflush((uintptr_t*)addr);
+}
+
+static inline ppn_t page2ppn(page_t *pp)
+{
+       return pp - pages;
+}
+
+static inline physaddr_t page2pa(page_t *pp)
+{
+       return page2ppn(pp) << PGSHIFT;
+}
+
+static inline page_t* pa2page(physaddr_t pa)
+{
+       if (PPN(pa) >= npage)
+               warn("pa2page called with pa larger than npage");
+       return &pages[PPN(pa)];
+}
+
+static inline void* page2kva(page_t *pp)
+{
+       return KADDR(page2pa(pp));
+}
+
+pte_t *pgdir_walk(pde_t *pgdir, const void *va, int create);
+
+#endif /* !ROS_KERN_PMAP_H */
diff --git a/include/pool.h b/include/pool.h
new file mode 100644 (file)
index 0000000..aa2d1ad
--- /dev/null
@@ -0,0 +1,76 @@
+/* See COPYRIGHT for copyright information. */
+/* Kevin Klues <klueska@cs.berkeley.edu>       */
+
+#ifndef ROS_INC_POOL_H
+#define ROS_INC_POOL_H
+
+#include <string.h>
+
+#define POOL_TYPE_DEFINE(_type, p, sz)                                                \
+typedef struct struct_##p {                                                             \
+       uint32_t size;                                                         \
+       uint32_t free;                                                         \
+       uint32_t index;                                                        \
+       _type* queue[(sz)];                                                       \
+       _type pool[(sz)];                                                         \
+} p##_t;
+
+#define POOL_INIT(p, sz)                                                       \
+({                                                                             \
+       (p)->size = (sz);                                                          \
+       (p)->free = (sz);                                                          \
+       (p)->index = 0;                                                            \
+       memset((p)->pool, 0, (sz) * sizeof((p)->pool[0]));                         \
+       for(int i=0; i<(p)->size; i++) {                                           \
+               (p)->queue[i] = &((p)->pool[i]);                                       \
+       }                                                                          \
+})
+
+#define POOL_GET(p)                                            \
+({                                                             \
+       void* rval = NULL;                                         \
+       if((p)->free) {                                            \
+               rval = (p)->queue[(p)->index];                         \
+               (p)->queue[(p)->index] = NULL;                         \
+               (p)->free--;                                           \
+               (p)->index++;                                          \
+               if((p)->index == (p)->size) {                          \
+               (p)->index = 0;                                    \
+       }                                                      \
+       }                                                          \
+       rval;                                                      \
+})
+
+// emptyIndex is also the first element that has been allocated, iterate thru to index-1
+
+#define POOL_FOR_EACH(p, func)                                                                 \
+({                                                                                                                             \
+       int emptyIndex = ((p)->index + (p)->free);                  \
+       if (emptyIndex >= (p)->size) {                                          \
+               emptyIndex -= (p)->size;                                        \
+       }                                                                   \
+       for(int _i = emptyIndex;  _i < (p)->index; _i++){                       \
+               func((p)->queue[_i]);                                                                   \
+       }                                                                                                                       \
+})                                                                                                                             \
+
+#define POOL_PUT(p, val)                                                       \
+({                                                                             \
+       int rval = -1;                                                            \
+       if((p)->free < (p)->size) {                                           \
+               int emptyIndex = ((p)->index + (p)->free);                     \
+               if (emptyIndex >= (p)->size) {                                 \
+                       emptyIndex -= (p)->size;                               \
+               }                                                              \
+               (p)->queue[emptyIndex] = val;                                  \
+               (p)->free++;                                                   \
+               rval = 1;                                                             \
+       }                                                                      \
+       rval;                                                                 \
+})
+
+#define POOL_EMPTY(p) ((p)->free == 0)
+#define POOL_SIZE(p) ((p)->free)
+#define POOL_MAX_SIZE(p) ((p)->size)
+
+#endif //ROS_INC_POOL_H
diff --git a/include/ros/env.h b/include/ros/env.h
new file mode 100644 (file)
index 0000000..98bf62f
--- /dev/null
@@ -0,0 +1,62 @@
+/* See COPYRIGHT for copyright information. */
+
+#ifndef ROS_INC_ENV_H
+#define ROS_INC_ENV_H
+
+#include <arch/types.h>
+#include <ros/queue.h>
+#include <ros/trap.h>
+#include <ros/memlayout.h>
+#include <ros/syscall.h>
+
+struct Env;
+typedef struct Env env_t;
+
+typedef int32_t envid_t;
+
+// An environment ID 'envid_t' has three parts:
+//
+// +1+---------------21-----------------+--------10--------+
+// |0|          Uniqueifier             |   Environment    |
+// | |                                  |      Index       |
+// +------------------------------------+------------------+
+//                                       \--- ENVX(eid) --/
+//
+// The environment index ENVX(eid) equals the environment's offset in the
+// 'envs[]' array.  The uniqueifier distinguishes environments that were
+// created at different times, but share the same environment index.
+//
+// All real environments are greater than 0 (so the sign bit is zero).
+// envid_ts less than 0 signify errors.  The envid_t == 0 is special, and
+// stands for the current environment.
+
+#define LOG2NENV               10
+#define NENV                   (1 << LOG2NENV)
+#define ENVX(envid)            ((envid) & (NENV - 1))
+
+// Values of env_status in struct Env
+#define ENV_FREE               0
+#define ENV_RUNNABLE           1
+#define ENV_NOT_RUNNABLE       2
+
+struct Env {
+       trapframe_t env_tf;                     // Saved registers
+       LIST_ENTRY(env_t) env_link;     // Free list link pointers
+       envid_t env_id;                         // Unique environment identifier
+       envid_t env_parent_id;          // env_id of this env's parent
+       unsigned env_status;            // Status of the environment
+       uint32_t env_runs;                      // Number of times environment has run
+       // Note this is the actual backring, not a pointer to it somewhere else
+       syscall_back_ring_t env_sysbackring;    // BackRing for generic syscalls
+
+       // Address space
+       pde_t *env_pgdir;                       // Kernel virtual address of page dir
+       physaddr_t env_cr3;                     // Physical address of page dir
+       // TODO - give these two proper types (pointers to structs)
+       void* env_procinfo;             // KVA of per-process shared info table (RO)
+       void* env_procdata;             // KVA of per-process shared data table (RW)
+       // Eventually want to move this to a per-system shared-info page
+       uint64_t env_tscfreq;           // Frequency of the TSC for measurements
+};
+
+#endif // !ROS_INC_ENV_H
diff --git a/include/ros/memlayout.h b/include/ros/memlayout.h
new file mode 100644 (file)
index 0000000..3aa65cb
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef ROS_INC_MEMLAYOUT_H
+#define ROS_INC_MEMLAYOUT_H
+
+#ifndef __ASSEMBLER__
+#include <arch/types.h>
+#include <arch/mmu.h>
+#include <ros/queue.h>
+#endif /* not __ASSEMBLER__ */
+
+/*
+ * This file contains definitions for memory management in our OS,
+ * which are relevant to both the kernel and user-mode software.
+ */
+
+/*
+ * Virtual memory map:                                Permissions
+ *                                                    kernel/user
+ *
+ *    4 Gig -------->  +------------------------------+
+ *                     |                              | RW/--
+ *                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *                     :              .               :
+ *                     :              .               :
+ *                     :              .               :
+ *                     |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| RW/--
+ *                     |                              | RW/--
+ *                     |   Remapped Physical Memory   | RW/--
+ *                     |                              | RW/--
+ *    KERNBASE ----->  +------------------------------+ 0xc0000000
+ *                     |  Cur. Page Table (Kern. RW)  | RW/--  PTSIZE
+ *    VPT,KSTACKTOP--> +------------------------------+ 0xbfc00000      --+
+ *                     |         Kernel Stack         | RW/--  KSTKSIZE   |
+ *                     | - - - - - - - - - - - - - - -|                 PTSIZE
+ *                     |      Invalid Memory (*)      | --/--             |
+ *    ULIM     ------> +------------------------------+ 0xbf800000      --+
+ *                     |  Cur. Page Table (User R-)   | R-/R-  PTSIZE
+ *    UVPT      ---->  +------------------------------+ 0xbf400000
+ *                     |          RO PAGES            | R-/R-  PTSIZE
+ *    UPAGES    ---->  +------------------------------+ 0xbf000000      --+
+ *                     |  Unmapped (future expansion) | --/--             |
+ *                     +------------------------------+ 0xbec01000      PTSIZE
+ *                     |     Per-Process R/O Info     | R-/R-  PGSIZE     |
+ * UTOP, UINFO  ---->  +------------------------------+ 0xbec00000      --+
+ *                     |  Unmapped (future expansion) | --/--             |
+ *                     +------------------------------+ 0xbe801000      PTSIZE
+ *                     |     Per-Process R/W Data     | RW/RW  PGSIZE     |
+ * UDATA,UXSTACKTOP--> +------------------------------+ 0xbe800000      --+
+ *                     |     User Exception Stack     | RW/RW  PGSIZE
+ *                     +------------------------------+ 0xbe7ff000
+ *                     |       Empty Memory (*)       | --/--  PGSIZE
+ *    USTACKTOP  --->  +------------------------------+ 0xbe7fe000
+ *                     |      Normal User Stack       | RW/RW  PGSIZE
+ *                     +------------------------------+ 0xbe7fd000
+ *                     |                              |
+ *                     |                              |
+ *                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *                     .                              .
+ *                     .                              .
+ *                     .                              .
+ *                     |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|
+ *                     |     Program Data & Heap      |
+ *    UTEXT -------->  +------------------------------+ 0x00800000
+ *    PFTEMP ------->  |       Empty Memory (*)       |        PTSIZE
+ *                     |                              |
+ *    UTEMP -------->  +------------------------------+ 0x00400000      --+
+ *                     |       Empty Memory (*)       |                   |
+ *                     | - - - - - - - - - - - - - - -|                   |
+ *                     |  User STAB Data (optional)   |                 PTSIZE
+ *    USTABDATA ---->  +------------------------------+ 0x00200000        |
+ *                     |       Empty Memory (*)       |                   |
+ *    0 ------------>  +------------------------------+                 --+
+ *
+ * (*) Note: The kernel ensures that "Invalid Memory" (ULIM) is *never*
+ *     mapped.  "Empty Memory" is normally unmapped, but user programs may
+ *     map pages there if desired.  ROS user programs map pages temporarily
+ *     at UTEMP.
+ */
+
+
+// All physical memory mapped at this address
+#define        KERNBASE        0xC0000000
+
+// At IOPHYSMEM (640K) there is a 384K hole for I/O.  From the kernel,
+// IOPHYSMEM can be addressed at KERNBASE + IOPHYSMEM.  The hole ends
+// at physical address EXTPHYSMEM.
+#define IOPHYSMEM      0x0A0000
+#define VGAPHYSMEM     0x0A0000
+#define DEVPHYSMEM     0x0C0000
+#define BIOSPHYSMEM    0x0F0000
+#define EXTPHYSMEM     0x100000
+
+// Virtual page table.  Entry PDX(VPT) in the PD contains a pointer to
+// the page directory itself, thereby turning the PD into a page table,
+// which maps all the PTEs containing the page mappings for the entire
+// virtual address space into that 4 Meg region starting at VPT.
+#define VPT                    (KERNBASE - PTSIZE)
+#define KSTACKTOP      VPT
+#define KSTKSIZE       (8*PGSIZE)              // size of a kernel stack
+#define ULIM           (KSTACKTOP - PTSIZE) 
+
+/*
+ * User read-only mappings! Anything below here til UTOP are readonly to user.
+ * They are global pages mapped in at env allocation time.
+ */
+
+// Same as VPT but read-only for users
+#define UVPT           (ULIM - PTSIZE)
+// Read-only copies of the Page structures
+#define UPAGES         (UVPT - PTSIZE)
+// Read-only, per-process shared info structures
+#define UINFO          (UPAGES - PTSIZE)
+#define UINFO_PAGES 1
+
+/*
+ * Top of user VM. User can manipulate VA from UTOP-1 and down!
+ */
+
+// Top of user-accessible VM
+#define UTOP           UINFO
+
+// Read-write, per-process shared data structures
+#define UDATA          (UTOP - PTSIZE)
+#define UDATA_PAGES 1
+
+// Top of one-page user exception stack
+#define UXSTACKTOP     UDATA
+// Next page left invalid to guard against exception stack overflow; then:
+// Top of normal user stack
+#define USTACKTOP      (UXSTACKTOP - 2*PGSIZE)
+
+// Where user programs generally begin
+#define UTEXT          (2*PTSIZE)
+
+// Used for temporary page mappings.  Typed 'void*' for convenience
+#define UTEMP          ((void*) PTSIZE)
+// Used for temporary page mappings for the user page-fault handler
+// (should not conflict with other temporary page mappings)
+#define PFTEMP         (UTEMP + PTSIZE - PGSIZE)
+// The location of the user-level STABS data structure
+#define USTABDATA      (PTSIZE / 2)    
+
+
+#ifndef __ASSEMBLER__
+
+/*
+ * The page directory entry corresponding to the virtual address range
+ * [VPT, VPT + PTSIZE) points to the page directory itself.  Thus, the page
+ * directory is treated as a page table as well as a page directory.
+ *
+ * One result of treating the page directory as a page table is that all PTEs
+ * can be accessed through a "virtual page table" at virtual address VPT (to
+ * which vpt is set in entry.S).  The PTE for page number N is stored in
+ * vpt[N].  (It's worth drawing a diagram of this!)
+ *
+ * A second consequence is that the contents of the current page directory
+ * will always be available at virtual address (VPT + (VPT >> PGSHIFT)), to
+ * which vpd is set in entry.S.
+ */
+typedef uint32_t pte_t;
+typedef uint32_t pde_t;
+
+extern volatile pte_t vpt[];     // VA of "virtual page table"
+extern volatile pde_t vpd[];     // VA of current page directory
+
+#endif /* !__ASSEMBLER__ */
+#endif /* !ROS_INC_MEMLAYOUT_H */
diff --git a/include/ros/queue.h b/include/ros/queue.h
new file mode 100644 (file)
index 0000000..1102ed4
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)queue.h     8.3 (Berkeley) 12/13/93
+ *
+ * For Jos, extra comments have been added to this file, and the original
+ * TAILQ and CIRCLEQ definitions have been removed.   - August 9, 2005
+ */
+
+#ifndef ROS_INC_QUEUE_H
+#define ROS_INC_QUEUE_H
+
+/*
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ */
+
+/*
+ * An example using the below functions.
+ */
+#if 0
+
+typedef struct Frob
+{
+       int frobozz;
+       LIST_ENTRY(frob_t) frob_link;   /* this contains the list element pointers */
+} frob_t;
+
+LIST_HEAD(frob_list_t, frob_t)         /* defines struct Frob_list as a list of Frob */
+
+frob_list_t flist;                     /* declare a Frob list */
+
+LIST_INIT(&flist);                     /* clear flist (globals are cleared anyway) */
+flist = LIST_HEAD_INITIALIZER(&flist); /* alternate way to clear flist */
+
+if(LIST_EMPTY(&flist))                 /* check whether list is empty */
+       printf("list is empty\n");
+
+frob_t *f = LIST_FIRST(&flist);        /* f is first element in list */
+f = LIST_NEXT(f, frob_link);           /* now f is next (second) element in list */
+f = LIST_NEXT(f, frob_link);           /* now f is next (third) element in list */
+
+for(f=LIST_FIRST(&flist); f != 0;      /* iterate over elements in flist */
+    f = LIST_NEXT(f, frob_link))
+       printf("f %d\n", f->frobozz);
+
+LIST_FOREACH(f, &flist, frob_link)     /* alternate way to say that */
+       printf("f %d\n", f->frobozz);
+
+f = LIST_NEXT(LIST_FIRST(&flist));     /* f is second element in list */
+LIST_INSERT_AFTER(f, g, frob_link);    /* add g right after f in list */
+LIST_REMOVE(g, frob_link);             /* remove g from list (can't insert twice!) */
+LIST_INSERT_BEFORE(f, g, frob_link);   /* add g right before f */
+LIST_REMOVE(g, frob_link);             /* remove g again */
+LIST_INSERT_HEAD(&flist, g, frob_link);        /* add g as first element in list */
+
+#endif
+
+/*
+ * List declarations.
+ */
+
+/*
+ * A list is headed by a structure defined by the LIST_HEAD macro.  This structure con‐
+ * tains a single pointer to the first element on the list.  The elements are doubly
+ * linked so that an arbitrary element can be removed without traversing the list.  New
+ * elements can be added to the list after an existing element or at the head of the list.
+ * A LIST_HEAD structure is declared as follows:
+ * 
+ *       LIST_HEAD(HEADNAME, TYPE) head;
+ * 
+ * where HEADNAME is the name of the structure to be defined, and TYPE is the type of the
+ * elements to be linked into the list.  A pointer to the head of the list can later be
+ * declared as:
+ * 
+ *       HEADNAME *headp;
+ * 
+ * (The names head and headp are user selectable.)
+ */
+#define        LIST_HEAD(name, type)                                   \
+typedef struct {                                                               \
+       type *lh_first; /* first element */                     \
+       type *lh_last;  /* last element */                      \
+} name;
+
+/*
+ * Set a list head variable to LIST_HEAD_INITIALIZER(head)
+ * to reset it to the empty list.
+ */
+#define        LIST_HEAD_INITIALIZER(head)                                     \
+       { NULL, NULL }
+
+/*
+ * Use this inside a structure "LIST_ENTRY(type) field" to use
+ * x as the list piece.
+ *
+ * The le_prev points at the pointer to the structure containing
+ * this very LIST_ENTRY, so that if we want to remove this list entry,
+ * we can do *le_prev = le_next to update the structure pointing at us.
+ */
+#define        LIST_ENTRY(type)                                                \
+struct {                                                               \
+       type *le_next;  /* next element */                      \
+       type **le_prev; /* ptr to ptr to this element */        \
+}
+
+/*
+ * List functions.
+ */
+
+/*
+ * Is the list named "head" empty?
+ */
+#define        LIST_EMPTY(head)        ((head)->lh_first == NULL)
+
+/*
+ * Return the first element in the list named "head".
+ */
+#define        LIST_FIRST(head)        ((head)->lh_first)
+
+/*
+ * Return the last element in the list named "head".
+ */
+#define        LIST_LAST(head) ((head)->lh_last)
+
+/*
+ * Return the element after "elm" in the list.
+ * The "field" name is the link element as above.
+ */
+#define        LIST_NEXT(elm, field)   ((elm)->field.le_next)
+
+/*
+ * Iterate over the elements in the list named "head".
+ * During the loop, assign the list elements to the variable "var"
+ * and use the LIST_ENTRY structure member "field" as the link field.
+ */
+#define        LIST_FOREACH(var, head, field)                                  \
+       for ((var) = LIST_FIRST((head));                                \
+           (var);                                                      \
+           (var) = LIST_NEXT((var), field))
+
+/*
+ * Reset the list named "head" to the empty list.
+ */
+#define        LIST_INIT(head) do {                                            \
+       LIST_FIRST((head)) = NULL;                                      \
+       LIST_LAST((head)) = NULL;                                       \
+} while (0)
+
+/*
+ * TODO : DON'T USE THIS because of tail pointer issues
+ * Insert the element "elm" *after* the element "listelm" which is
+ * already in the list.  The "field" name is the link element
+ * as above.
+#define        LIST_INSERT_AFTER(listelm, elm, field) do {                     \
+       if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+               LIST_NEXT((listelm), field)->field.le_prev =            \
+                   &LIST_NEXT((elm), field);                           \
+       LIST_NEXT((listelm), field) = (elm);                            \
+       (elm)->field.le_prev = &LIST_NEXT((listelm), field);            \
+} while (0)
+ */
+
+/*
+ * TODO : DON'T USE THIS because of tail pointer issues
+ * Insert the element "elm" *after* the element "listelm" which is
+ * Insert the element "elm" *before* the element "listelm" which is
+ * already in the list.  The "field" name is the link element
+ * as above.
+#define        LIST_INSERT_BEFORE(listelm, elm, field) do {                    \
+       (elm)->field.le_prev = (listelm)->field.le_prev;                \
+       LIST_NEXT((elm), field) = (listelm);                            \
+       *(listelm)->field.le_prev = (elm);                              \
+       (listelm)->field.le_prev = &LIST_NEXT((elm), field);            \
+} while (0)
+ */
+
+/*
+ * Insert the element "elm" at the head of the list named "head".
+ * The "field" name is the link element as above.
+ */
+#define        LIST_INSERT_HEAD(head, elm, field) do {                         \
+       if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)     \
+               LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+       else                                                       \
+               LIST_LAST((head)) = (elm);                                      \
+       LIST_FIRST((head)) = (elm);                                     \
+       (elm)->field.le_prev = &LIST_FIRST((head));                     \
+} while (0)
+
+/*
+ * TODO : DO NOT USE THIS AFTER YOU'VE REMOVED AN ITEM!!
+ * Insert the element "elm" at the tail of the list named "head".
+ * The "field" name is the link element as above.
+ * (you have been warned) ((sorry))
+ */
+#define        LIST_INSERT_TAIL(head, elm, field) do {                                            \
+       if (LIST_EMPTY((head)))                                                    \
+               LIST_INSERT_HEAD((head), (elm), field);                                \
+       else {                                                                     \
+               (elm)->field.le_prev = &(LIST_LAST((head))->field.le_next);            \
+               LIST_LAST((head))->field.le_next = (elm);                              \
+               LIST_LAST((head)) = (elm);                                             \
+               (elm)->field.le_next = NULL;                                           \
+       }                                                                          \
+} while (0)
+
+/*
+ * Remove the element "elm" from the list.
+ * The "field" name is the link element as above.
+ */
+#define        LIST_REMOVE(elm, field) do {                                    \
+       if (LIST_NEXT((elm), field) != NULL)                            \
+               LIST_NEXT((elm), field)->field.le_prev =                \
+                   (elm)->field.le_prev;                               \
+       *(elm)->field.le_prev = LIST_NEXT((elm), field);                \
+} while (0)
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/include/ros/ring_buffer.h b/include/ros/ring_buffer.h
new file mode 100644 (file)
index 0000000..08f1f7b
--- /dev/null
@@ -0,0 +1,306 @@
+/******************************************************************************
+ * ring.h
+ * 
+ * Shared producer-consumer ring macros.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Tim Deegan and Andrew Warfield November 2004.
+ */
+
+#ifndef ROS_INC_RING_BUFFER_H
+#define ROS_INC_RING_BUFFER_H
+
+#include <atomic.h>
+
+#define xen_mb()  mb()
+#define xen_rmb() rmb()
+#define xen_wmb() wmb()
+
+typedef unsigned int RING_IDX;
+
+/* Round a 32-bit unsigned constant down to the nearest power of two. */
+#define __RD2(_x)  (((_x) & 0x00000002) ? 0x2                  : ((_x) & 0x1))
+#define __RD4(_x)  (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2    : __RD2(_x))
+#define __RD8(_x)  (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4    : __RD4(_x))
+#define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8    : __RD8(_x))
+#define __RD32(_x) (((_x) & 0xffff0000) ? __RD16((_x)>>16)<<16 : __RD16(_x))
+
+/*
+ * Calculate size of a shared ring, given the total available space for the
+ * ring and indexes (_sz), and the name tag of the request/response structure.
+ * A ring contains as many entries as will fit, rounded down to the nearest 
+ * power of two (so we can mask with (size-1) to loop around).
+ * This tells us how many elements the ring _s can contain, given _sz space.
+ */
+#define __RING_SIZE(_s, _sz) \
+    (__RD32(((_sz) - (long)(_s)->ring + (long)(_s)) / sizeof((_s)->ring[0])))
+
+/*
+ * Macros to make the correct C datatypes for a new kind of ring.
+ * 
+ * To make a new ring datatype, you need to have two message structures,
+ * let's say request_t, and response_t already defined.
+ *
+ * In a header where you want the ring datatype declared, you then do:
+ *
+ *     DEFINE_RING_TYPES(mytag, request_t, response_t);
+ *
+ * These expand out to give you a set of types, as you can see below.
+ * The most important of these are:
+ * 
+ *     mytag_sring_t      - The shared ring.
+ *     mytag_front_ring_t - The 'front' half of the ring.
+ *     mytag_back_ring_t  - The 'back' half of the ring.
+ *
+ * To initialize a ring in your code you need to know the location and size
+ * of the shared memory area (PAGE_SIZE, for instance). To initialise
+ * the front half:
+ *
+ *     mytag_front_ring_t front_ring;
+ *     SHARED_RING_INIT((mytag_sring_t *)shared_page);
+ *     FRONT_RING_INIT(&front_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
+ *
+ * Initializing the back follows similarly (note that only the front
+ * initializes the shared ring):
+ *
+ *     mytag_back_ring_t back_ring;
+ *     BACK_RING_INIT(&back_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
+ */
+
+#define DEFINE_RING_TYPES(__name, __req_t, __rsp_t)                     \
+                                                                        \
+/* Shared ring entry */                                                 \
+union __name##_sring_entry {                                            \
+    __req_t req;                                                        \
+    __rsp_t rsp;                                                        \
+};                                                                      \
+                                                                        \
+/* Shared ring page */                                                  \
+struct __name##_sring {                                                 \
+    RING_IDX req_prod, req_event;                                       \
+    RING_IDX rsp_prod, rsp_event;                                       \
+    uint8_t  pad[48];                                                   \
+    union __name##_sring_entry ring[1]; /* variable-length */           \
+};                                                                      \
+                                                                        \
+/* "Front" end's private variables */                                   \
+struct __name##_front_ring {                                            \
+    RING_IDX req_prod_pvt;                                              \
+    RING_IDX rsp_cons;                                                  \
+    unsigned int nr_ents;                                               \
+    struct __name##_sring *sring;                                       \
+};                                                                      \
+                                                                        \
+/* "Back" end's private variables */                                    \
+struct __name##_back_ring {                                             \
+    RING_IDX rsp_prod_pvt;                                              \
+    RING_IDX req_cons;                                                  \
+    unsigned int nr_ents;                                               \
+    struct __name##_sring *sring;                                       \
+};                                                                      \
+                                                                        \
+/* Syntactic sugar */                                                   \
+typedef struct __name##_sring __name##_sring_t;                         \
+typedef struct __name##_front_ring __name##_front_ring_t;               \
+typedef struct __name##_back_ring __name##_back_ring_t
+
+/*
+ * Macros for manipulating rings.
+ * 
+ * FRONT_RING_whatever works on the "front end" of a ring: here 
+ * requests are pushed on to the ring and responses taken off it.
+ * 
+ * BACK_RING_whatever works on the "back end" of a ring: here 
+ * requests are taken off the ring and responses put on.
+ * 
+ * N.B. these macros do NO INTERLOCKS OR FLOW CONTROL. 
+ * This is OK in 1-for-1 request-response situations where the 
+ * requestor (front end) never has more than RING_SIZE()-1
+ * outstanding requests.
+ */
+
+/* Initialising empty rings */
+#define SHARED_RING_INIT(_s) do {                                       \
+    (_s)->req_prod  = (_s)->rsp_prod  = 0;                              \
+    (_s)->req_event = (_s)->rsp_event = 1;                              \
+    (void)memset((_s)->pad, 0, sizeof((_s)->pad));                      \
+} while(0)
+
+#define FRONT_RING_INIT(_r, _s, __size) do {                            \
+    (_r)->req_prod_pvt = 0;                                             \
+    (_r)->rsp_cons = 0;                                                 \
+    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
+    (_r)->sring = (_s);                                                 \
+} while (0)
+
+#define BACK_RING_INIT(_r, _s, __size) do {                             \
+    (_r)->rsp_prod_pvt = 0;                                             \
+    (_r)->req_cons = 0;                                                 \
+    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
+    (_r)->sring = (_s);                                                 \
+} while (0)
+
+/* Initialize to existing shared indexes -- for recovery */
+#define FRONT_RING_ATTACH(_r, _s, __size) do {                          \
+    (_r)->sring = (_s);                                                 \
+    (_r)->req_prod_pvt = (_s)->req_prod;                                \
+    (_r)->rsp_cons = (_s)->rsp_prod;                                    \
+    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
+} while (0)
+
+#define BACK_RING_ATTACH(_r, _s, __size) do {                           \
+    (_r)->sring = (_s);                                                 \
+    (_r)->rsp_prod_pvt = (_s)->rsp_prod;                                \
+    (_r)->req_cons = (_s)->req_prod;                                    \
+    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
+} while (0)
+
+/* How big is this ring? */
+#define RING_SIZE(_r)                                                   \
+    ((_r)->nr_ents)
+
+/* Number of free requests (for use on front side only). */
+#define RING_FREE_REQUESTS(_r)                                          \
+    (RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons))
+
+/* Test if there is an empty slot available on the front ring.
+ * (This is only meaningful from the front. )
+ */
+#define RING_FULL(_r)                                                   \
+    (RING_FREE_REQUESTS(_r) == 0)
+
+/* Test if there are outstanding messages to be processed on a ring. */
+#define RING_HAS_UNCONSUMED_RESPONSES(_r)                               \
+    ((_r)->sring->rsp_prod - (_r)->rsp_cons)
+
+#ifdef __GNUC__
+#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({                             \
+    unsigned int req = (_r)->sring->req_prod - (_r)->req_cons;          \
+    unsigned int rsp = RING_SIZE(_r) -                                  \
+        ((_r)->req_cons - (_r)->rsp_prod_pvt);                          \
+    req < rsp ? req : rsp;                                              \
+})
+#else
+/* Same as above, but without the nice GCC ({ ... }) syntax. */
+#define RING_HAS_UNCONSUMED_REQUESTS(_r)                                \
+    ((((_r)->sring->req_prod - (_r)->req_cons) <                        \
+      (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ?        \
+     ((_r)->sring->req_prod - (_r)->req_cons) :                         \
+     (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt)))
+#endif
+
+/* Direct access to individual ring elements, by index. */
+#define RING_GET_REQUEST(_r, _idx)                                      \
+    (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
+
+#define RING_GET_RESPONSE(_r, _idx)                                     \
+    (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
+
+/* Loop termination condition: Would the specified index overflow the ring? */
+#define RING_REQUEST_CONS_OVERFLOW(_r, _cons)                           \
+    (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
+
+#define RING_PUSH_REQUESTS(_r) do {                                     \
+    xen_wmb(); /* back sees requests /before/ updated producer index */ \
+    (_r)->sring->req_prod = (_r)->req_prod_pvt;                         \
+} while (0)
+
+#define RING_PUSH_RESPONSES(_r) do {                                    \
+    xen_wmb(); /* front sees resps /before/ updated producer index */   \
+    (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt;                         \
+} while (0)
+
+/*
+ * Notification hold-off (req_event and rsp_event):
+ * 
+ * When queueing requests or responses on a shared ring, it may not always be
+ * necessary to notify the remote end. For example, if requests are in flight
+ * in a backend, the front may be able to queue further requests without
+ * notifying the back (if the back checks for new requests when it queues
+ * responses).
+ * 
+ * When enqueuing requests or responses:
+ * 
+ *  Use RING_PUSH_{REQUESTS,RESPONSES}_AND_CHECK_NOTIFY(). The second argument
+ *  is a boolean return value. True indicates that the receiver requires an
+ *  asynchronous notification.
+ * 
+ * After dequeuing requests or responses (before sleeping the connection):
+ * 
+ *  Use RING_FINAL_CHECK_FOR_REQUESTS() or RING_FINAL_CHECK_FOR_RESPONSES().
+ *  The second argument is a boolean return value. True indicates that there
+ *  are pending messages on the ring (i.e., the connection should not be put
+ *  to sleep).
+ * 
+ *  These macros will set the req_event/rsp_event field to trigger a
+ *  notification on the very next message that is enqueued. If you want to
+ *  create batches of work (i.e., only receive a notification after several
+ *  messages have been enqueued) then you will need to create a customised
+ *  version of the FINAL_CHECK macro in your own code, which sets the event
+ *  field appropriately.
+ */
+
+#define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do {           \
+    RING_IDX __old = (_r)->sring->req_prod;                             \
+    RING_IDX __new = (_r)->req_prod_pvt;                                \
+    xen_wmb(); /* back sees requests /before/ updated producer index */ \
+    (_r)->sring->req_prod = __new;                                      \
+    xen_mb(); /* back sees new requests /before/ we check req_event */  \
+    (_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) <           \
+                 (RING_IDX)(__new - __old));                            \
+} while (0)
+
+#define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do {          \
+    RING_IDX __old = (_r)->sring->rsp_prod;                             \
+    RING_IDX __new = (_r)->rsp_prod_pvt;                                \
+    xen_wmb(); /* front sees resps /before/ updated producer index */   \
+    (_r)->sring->rsp_prod = __new;                                      \
+    xen_mb(); /* front sees new resps /before/ we check rsp_event */    \
+    (_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) <           \
+                 (RING_IDX)(__new - __old));                            \
+} while (0)
+
+#define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do {             \
+    (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r);                   \
+    if (_work_to_do) break;                                             \
+    (_r)->sring->req_event = (_r)->req_cons + 1;                        \
+    xen_mb();                                                           \
+    (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r);                   \
+} while (0)
+
+#define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do {            \
+    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);                  \
+    if (_work_to_do) break;                                             \
+    (_r)->sring->rsp_event = (_r)->rsp_cons + 1;                        \
+    xen_mb();                                                           \
+    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);                  \
+} while (0)
+
+#endif /* ROS_INC_RING_BUFFER_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/include/ros/syscall.h b/include/ros/syscall.h
new file mode 100644 (file)
index 0000000..aad2fe5
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef ROS_INC_SYSCALL_H
+#define ROS_INC_SYSCALL_H
+
+#include <arch/types.h>
+#include <ros/ring_buffer.h>
+#include <ros/queue.h>
+
+/* system call numbers */
+enum
+{
+       SYS_null = 1,
+       SYS_cache_buster,
+       SYS_cputs,
+       SYS_cgetc,
+       SYS_getenvid,
+       SYS_env_destroy,
+};
+#define NSYSCALLS (SYS_env_destroy)
+// syscall number starts at 1 and goes up to NSYSCALLS, without holes.
+#define INVALID_SYSCALL(syscallno) ((syscallno) > NSYSCALLS)
+
+#define NUM_SYS_ARGS 6
+typedef struct syscall_req {
+       uint32_t num;
+       uint32_t flags;
+       uint32_t args[NUM_SYS_ARGS];
+} syscall_req_t;
+
+typedef struct syscall_rsp {
+       int32_t retval;
+} syscall_rsp_t;
+
+// Generic Syscall Ring Buffer
+DEFINE_RING_TYPES(syscall, syscall_req_t, syscall_rsp_t);
+
+typedef struct syscall_desc syscall_desc_t;
+struct syscall_desc {
+       LIST_ENTRY(syscall_desc_t) next;
+       syscall_front_ring_t* sysfr;
+       uint32_t idx;
+       // cleanup
+       void (*cleanup)(void* data);
+       void* data;
+};
+LIST_HEAD(syscall_desc_list_t, syscall_desc_t);
+
+static uint32_t
+syscall_sysenter(int num, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5);
+
+#endif /* !ROS_INC_SYSCALL_H */
diff --git a/include/ros/trap.h b/include/ros/trap.h
new file mode 100644 (file)
index 0000000..5547fad
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef ROS_INC_TRAP_H
+#define ROS_INC_TRAP_H
+
+// Trap numbers
+// These are processor defined:
+#define T_DIVIDE     0         // divide error
+#define T_DEBUG      1         // debug exception
+#define T_NMI        2         // non-maskable interrupt
+#define T_BRKPT      3         // breakpoint
+#define T_OFLOW      4         // overflow
+#define T_BOUND      5         // bounds check
+#define T_ILLOP      6         // illegal opcode
+#define T_DEVICE     7         // device not available 
+#define T_DBLFLT     8         // double fault
+/* #define T_COPROC  9 */      // reserved (not generated by recent processors)
+#define T_TSS       10         // invalid task switch segment
+#define T_SEGNP     11         // segment not present
+#define T_STACK     12         // stack exception
+#define T_GPFLT     13         // genernal protection fault
+#define T_PGFLT     14         // page fault
+/* #define T_RES    15 */      // reserved
+#define T_FPERR     16         // floating point error
+#define T_ALIGN     17         // aligment check
+#define T_MCHK      18         // machine check
+#define T_SIMDERR   19         // SIMD floating point error
+
+// These are arbitrarily chosen, but with care not to overlap
+// processor defined exceptions or interrupt vectors.
+#define T_SYSCALL   0x80                       // system call
+#define T_DEFAULT   0xdeadbeef         // catchall
+
+#ifndef __ASSEMBLER__
+
+#include <arch/types.h>
+
+typedef struct PushRegs {
+       /* registers as pushed by pusha */
+       uint32_t reg_edi;
+       uint32_t reg_esi;
+       uint32_t reg_ebp;
+       uint32_t reg_oesp;              /* Useless */
+       uint32_t reg_ebx;
+       uint32_t reg_edx;
+       uint32_t reg_ecx;
+       uint32_t reg_eax;
+} push_regs_t;
+
+typedef struct Trapframe {
+       push_regs_t tf_regs;
+       uint16_t tf_es;
+       uint16_t tf_padding1;
+       uint16_t tf_ds;
+       uint16_t tf_padding2;
+       uint32_t tf_trapno;
+       /* below here defined by x86 hardware */
+       uint32_t tf_err;
+       uintptr_t tf_eip;
+       uint16_t tf_cs;
+       uint16_t tf_padding3;
+       uint32_t tf_eflags;
+       /* below here only when crossing rings, such as from user to kernel */
+       uintptr_t tf_esp;
+       uint16_t tf_ss;
+       uint16_t tf_padding4;
+} trapframe_t;
+
+
+#endif /* !__ASSEMBLER__ */
+
+// Must equal 'sizeof(trapframe_t)'.
+// A static_assert in kern/trap.c checks this.
+#define SIZEOF_STRUCT_TRAPFRAME        0x44
+
+#endif /* !ROS_INC_TRAP_H */
diff --git a/include/sched.h b/include/sched.h
new file mode 100644 (file)
index 0000000..d751fb5
--- /dev/null
@@ -0,0 +1,12 @@
+/* See COPYRIGHT for copyright information. */
+
+#ifndef ROS_KERN_SCHED_H
+#define ROS_KERN_SCHED_H
+#ifndef ROS_KERNEL
+# error "This is a ROS kernel header; user programs should not #include it"
+#endif
+
+// This function does not return.
+void sched_yield(void) __attribute__((noreturn));
+
+#endif // !ROS_KERN_SCHED_H
diff --git a/include/stdarg.h b/include/stdarg.h
new file mode 100644 (file)
index 0000000..8548ce6
--- /dev/null
@@ -0,0 +1,19 @@
+/*     $NetBSD: stdarg.h,v 1.12 1995/12/25 23:15:31 mycroft Exp $      */
+
+#ifndef ROS_INC_STDARG_H
+#define        ROS_INC_STDARG_H
+
+typedef void * TRUSTED va_list;
+
+#define        __va_size(type) \
+       (((sizeof(type) + sizeof(long) - 1) / sizeof(long)) * sizeof(long))
+
+#define        va_start(ap, last) \
+       ((ap) = (va_list)&(last) + __va_size(last))
+
+#define        va_arg(ap, type) \
+       (*(type *)((ap) += __va_size(type), (ap) - __va_size(type)))
+
+#define        va_end(ap)      ((void)0)
+
+#endif /* !ROS_INC_STDARG_H */
diff --git a/include/stdio.h b/include/stdio.h
new file mode 100644 (file)
index 0000000..2b96d6b
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef ROS_INC_STDIO_H
+#define ROS_INC_STDIO_H
+
+#include <stdarg.h>
+
+#ifndef NULL
+#define NULL   ((void *) 0)
+#endif /* !NULL */
+
+#ifdef DEBUG
+#define printd(args...) cprintf(args)
+#else
+#define printd(args...) {}
+#endif
+
+#define printk(args...) cprintf(args)
+
+// lib/stdio.c
+void   cputchar(int c);
+int    getchar(void);
+int    iscons(int fd);
+
+// lib/printfmt.c
+void   printfmt(void (*putch)(int, void**), void **putdat, const char *NTS fmt, ...);
+//void vprintfmt(void (*putch)(int, TV(t)), TV(t) putdat, const char *NTS fmt, va_list);
+void   vprintfmt(void (*putch)(int, void**), void **putdat, const char *NTS fmt, va_list);
+
+// lib/printf.c
+int    cprintf(const char * NTS fmt, ...);
+int    vcprintf(const char * NTS fmt, va_list);
+
+// lib/sprintf.c
+int    snprintf(char *str, int size, const char *fmt, ...);
+int    vsnprintf(char *COUNT(size) str, int size, const char *fmt, va_list);
+
+// lib/fprintf.c
+int    printf(const char *fmt, ...);
+int    fprintf(int fd, const char *fmt, ...);
+int    vfprintf(int fd, const char *fmt, va_list);
+
+// lib/readline.c
+char *NTS readline(const char *NTS prompt);
+
+#endif /* !ROS_INC_STDIO_H */
diff --git a/include/string.h b/include/string.h
new file mode 100644 (file)
index 0000000..1f3320c
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef ROS_INC_STRING_H
+#define ROS_INC_STRING_H
+
+#include <arch/types.h>
+
+int    strlen(const char *s);
+int    strnlen(const char *s, size_t size);
+char * strcpy(char *dst, const char *src);
+char * strncpy(char *dst, const char *src, size_t size);
+size_t strlcpy(char *dst, const char *src, size_t size);
+int    strcmp(const char *s1, const char *s2);
+int    strncmp(const char *s1, const char *s2, size_t size);
+char * strchr(const char *s, char c);
+char * strfind(const char *s, char c);
+
+void * memset(void *dst, int c, size_t len);
+void * memcpy(void *dst, const void *src, size_t len);
+void * memmove(void *dst, const void *src, size_t len);
+int    memcmp(const void *s1, const void *s2, size_t len);
+void * memfind(const void *s, int c, size_t len);
+
+long   strtol(const char *s, char **endptr, int base);
+
+#endif /* not ROS_INC_STRING_H */
diff --git a/include/syscall.h b/include/syscall.h
new file mode 100644 (file)
index 0000000..744def3
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef ROS_KERN_SYSCALL_H
+#define ROS_KERN_SYSCALL_H
+#ifndef ROS_KERNEL
+# error "This is ROS kernel header; user programs should not #include it"
+#endif
+
+#include <ros/syscall.h>
+#include <env.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);
+uint32_t process_generic_syscalls(env_t* e, uint32_t max);
+void syscall_wrapper(struct Trapframe *tf);
+#endif /* !ROS_KERN_SYSCALL_H */
diff --git a/include/testing.h b/include/testing.h
new file mode 100644 (file)
index 0000000..e49369b
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef ROS_INC_TESTING_H
+#define ROS_INC_TESTING_H
+
+/* This is just a dumping ground for old code used for testing.
+ * Someone should go through old commits and bring back other relevant tests.
+ * Someone else should actually make these useful on their own
+ */
+
+#include <arch/types.h>
+#include <trap.h>
+
+void test_ipi_sending(void);
+void test_pic_reception(void);
+void test_print_info(void);
+void test_barrier(void);
+void test_interrupts_irqsave(void);
+void test_bitmasks(void);
+void test_checklists(void);
+void test_pit(void);
+void test_smp_call_functions(void);
+void test_lapic_status_bit(void);
+
+void test_hello_world_handler(trapframe_t *tf, void* data);
+void test_print_info_handler(trapframe_t *tf, void* data);
+void test_barrier_handler(trapframe_t *tf, void* data);
+
+#endif /* !ROS_INC_TESTING_H */
diff --git a/include/trap.h b/include/trap.h
new file mode 100644 (file)
index 0000000..d2aa32e
--- /dev/null
@@ -0,0 +1,37 @@
+/* See COPYRIGHT for copyright information. */
+
+#ifndef ROS_KERN_TRAP_H
+#define ROS_KERN_TRAP_H
+#ifndef ROS_KERNEL
+# error "This is an ROS kernel header; user programs should not #include it"
+#endif
+
+#define MSR_IA32_SYSENTER_CS 0x174
+#define MSR_IA32_SYSENTER_ESP 0x175
+#define MSR_IA32_SYSENTER_EIP 0x176
+
+#include <arch/mmu.h>
+#include <ros/trap.h>
+
+// func ptr for interrupt service routines
+typedef void (*isr_t)(trapframe_t* tf, void* data);
+typedef struct InterruptHandler {
+       isr_t isr;
+       void* data;
+} handler_t;
+
+/* The kernel's interrupt descriptor table */
+extern gatedesc_t idt[];
+extern taskstate_t ts;
+
+void idt_init(void);
+void register_interrupt_handler(handler_t (COUNT(256)table)[], uint8_t int_num,
+                                isr_t handler, void* data);
+void (IN_HANDLER print_regs)(push_regs_t *regs);
+void (IN_HANDLER print_trapframe)(trapframe_t *tf);
+void (IN_HANDLER page_fault_handler)(trapframe_t *tf);
+void backtrace(trapframe_t *tf);
+
+void sysenter_init(void);
+extern void sysenter_handler();
+#endif /* ROS_KERN_TRAP_H */
index 8502400..f910bbf 100644 (file)
@@ -1,4 +1,11 @@
-
 KERN_DIR := kern
-include $(KERN_DIR)/ivylib/Makefrag
+
+KERN_CFLAGS := $(CFLAGS) -DROS_KERNEL -nostdinc
+KERN_CFLAGS += -I$(INCLUDE_DIR)
+KERN_LDFLAGS := 
+
+include $(KERN_DIR)/boot/Makefrag
+include $(KERN_DIR)/ivy/Makefrag
 include $(KERN_DIR)/src/Makefrag
+
+.PRECIOUS: $(OBJDIR)/$(KERN_DIR)/%.o
diff --git a/kern/apic.h b/kern/apic.h
deleted file mode 100644 (file)
index fa66cd3..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (c) 2009 The Regents of the University of California
- * See LICENSE for details.
- */
-
-#ifndef ROS_KERN_APIC_H
-#define ROS_KERN_APIC_H
-
-/* 
- * Functions and definitions for dealing with the APIC and PIC, specific to
- * Intel.  Does not handle an x2APIC.
- */
-
-#include <inc/mmu.h>
-#include <inc/x86.h>
-
-// PIC
-#define PIC1_CMD                                       0x20
-#define PIC1_DATA                                      0x21
-#define PIC2_CMD                                       0xA0
-#define PIC2_DATA                                      0xA1
-// These are also hardcoded into the IRQ_HANDLERs of kern/trapentry.S
-#define PIC1_OFFSET                                    0x20
-#define PIC2_OFFSET                                    0x28
-#define PIC_EOI                                                0x20
-
-// Local APIC
-#define LAPIC_BASE                                     0xfee00000 // this is the default, can be changed
-#define LAPIC_EOI                                      (LAPIC_BASE + 0x0b0)
-#define LAPIC_SPURIOUS                         (LAPIC_BASE + 0x0f0)
-#define LAPIC_VERSION                          (LAPIC_BASE + 0x030)
-#define LAPIC_ERROR                                    (LAPIC_BASE + 0x280)
-#define LAPIC_ID                                       (LAPIC_BASE + 0x020)
-#define LAPIC_LOGICAL_ID                       (LAPIC_BASE + 0x0d0)
-// LAPIC Local Vector Table
-#define LAPIC_LVT_TIMER                                (LAPIC_BASE + 0x320)
-#define LAPIC_LVT_LINT0                                (LAPIC_BASE + 0x350)
-#define LAPIC_LVT_LINT1                                (LAPIC_BASE + 0x360)
-#define LAPIC_LVT_ERROR                                (LAPIC_BASE + 0x370)
-#define LAPIC_LVT_PERFMON                      (LAPIC_BASE + 0x340)
-#define LAPIC_LVT_THERMAL                      (LAPIC_BASE + 0x330)
-#define LAPIC_LVT_MASK                         0x00010000
-// LAPIC Timer
-#define LAPIC_TIMER_INIT                       (LAPIC_BASE + 0x380)
-#define LAPIC_TIMER_CURRENT                    (LAPIC_BASE + 0x390)
-#define LAPIC_TIMER_DIVIDE                     (LAPIC_BASE + 0x3e0)
-#define LAPIC_TIMER_DEFAULT_VECTOR     0xeb
-#define LAPIC_TIMER_DEFAULT_DIVISOR    0xa // This is 128.  Ref SDM 3.a 9.6.4
-// IPI Interrupt Command Register
-#define LAPIC_IPI_ICR_LOWER                    (LAPIC_BASE + 0x300)
-#define LAPIC_IPI_ICR_UPPER                    (LAPIC_BASE + 0x310)
-
-// IOAPIC
-#define IOAPIC_BASE                                    0xfec00000 // this is the default, can be changed
-
-// PIT (Programmable Interval Timer)
-#define        TIMER_REG_CNTR0 0       /* timer 0 counter port */
-#define        TIMER_REG_CNTR1 1       /* timer 1 counter port */
-#define        TIMER_REG_CNTR2 2       /* timer 2 counter port */
-#define        TIMER_REG_MODE  3       /* timer mode port */
-#define        TIMER_SEL0      0x00    /* select counter 0 */
-#define        TIMER_SEL1      0x40    /* select counter 1 */
-#define        TIMER_SEL2      0x80    /* select counter 2 */
-#define        TIMER_INTTC     0x00    /* mode 0, intr on terminal cnt */
-#define        TIMER_ONESHOT   0x02    /* mode 1, one shot */
-#define        TIMER_RATEGEN   0x04    /* mode 2, rate generator */
-#define        TIMER_SQWAVE    0x06    /* mode 3, square wave */
-#define        TIMER_SWSTROBE  0x08    /* mode 4, s/w triggered strobe */
-#define        TIMER_HWSTROBE  0x0a    /* mode 5, h/w triggered strobe */
-#define        TIMER_LATCH     0x00    /* latch counter for reading */
-#define        TIMER_LSB       0x10    /* r/w counter LSB */
-#define        TIMER_MSB       0x20    /* r/w counter MSB */
-#define        TIMER_16BIT     0x30    /* r/w counter 16 bits, LSB first */
-#define        TIMER_BCD       0x01    /* count in BCD */
-
-#define PIT_FREQ                                       1193182
-
-#define IO_TIMER1   0x40        /* 8253 Timer #1 */
-#define TIMER_CNTR0 (IO_TIMER1 + TIMER_REG_CNTR0)
-#define TIMER_CNTR1 (IO_TIMER1 + TIMER_REG_CNTR1)
-#define TIMER_CNTR2 (IO_TIMER1 + TIMER_REG_CNTR2)
-#define TIMER_MODE  (IO_TIMER1 + TIMER_REG_MODE)
-
-typedef struct system_timing {
-       uint64_t tsc_freq;
-       uint64_t bus_freq;
-       uint16_t pit_divisor;
-       uint8_t pit_mode;
-} system_timing_t;
-
-extern system_timing_t system_timing;
-
-void pic_remap(void);
-void pic_mask_irq(uint8_t irq);
-void pic_unmask_irq(uint8_t irq);
-void __lapic_set_timer(uint32_t ticks, uint8_t vec, bool periodic, uint8_t div);
-void lapic_set_timer(uint32_t usec, bool periodic);
-uint32_t lapic_get_default_id(void);
-// PIT related
-void pit_set_timer(uint32_t freq, uint32_t mode);
-void timer_init(void);
-void udelay(uint64_t usec);
-void udelay_pit(uint64_t usec);
-// TODO: right now timer defaults to TSC
-uint64_t gettimer(void);
-uint64_t inline getfreq(void);
-
-static inline void pic_send_eoi(uint32_t irq);
-static inline void lapic_send_eoi(void);
-static inline uint32_t lapic_get_version(void);
-static inline uint32_t lapic_get_error(void);
-static inline uint32_t lapic_get_id(void);
-static inline uint8_t lapic_get_logid(void);
-static inline void lapic_set_logid(uint8_t id);
-static inline void lapic_disable(void);
-static inline void lapic_enable(void);
-static inline void lapic_wait_to_send(void);
-static inline void send_init_ipi(void);
-static inline void send_startup_ipi(uint8_t vector);
-static inline void send_self_ipi(uint8_t vector);
-static inline void send_broadcast_ipi(uint8_t vector);
-static inline void send_all_others_ipi(uint8_t vector);
-static inline void send_ipi(uint8_t dest, bool logical_mode, uint8_t vector);
-
-#define mask_lapic_lvt(entry) \
-       write_mmreg32(entry, read_mmreg32(entry) | LAPIC_LVT_MASK)
-#define unmask_lapic_lvt(entry) \
-       write_mmreg32(entry, read_mmreg32(entry) & ~LAPIC_LVT_MASK)
-
-static inline void pic_send_eoi(uint32_t irq)
-{
-       // all irqs beyond the first seven need to be chained to the slave
-       if (irq > 7)
-               outb(PIC2_CMD, PIC_EOI);
-       outb(PIC1_CMD, PIC_EOI);
-}
-
-static inline void lapic_send_eoi(void)
-{
-       write_mmreg32(LAPIC_EOI, 0);
-}
-
-static inline uint32_t lapic_get_version(void)
-{
-       return read_mmreg32(LAPIC_VERSION);     
-}
-
-static inline uint32_t lapic_get_error(void)
-{
-       write_mmreg32(LAPIC_ERROR, 0xdeadbeef);
-       return read_mmreg32(LAPIC_ERROR);
-}
-
-static inline uint32_t lapic_get_id(void)
-{
-       return read_mmreg32(LAPIC_ID) >> 24;
-}
-
-static inline uint8_t lapic_get_logid(void)
-{
-       return read_mmreg32(LAPIC_LOGICAL_ID) >> 24;
-}
-
-static inline void lapic_set_logid(uint8_t id)
-{
-       write_mmreg32(LAPIC_LOGICAL_ID, id << 24);
-}
-
-/* There are a couple ways to do it.  The MSR route doesn't seem to work
- * in KVM.  It's also a somewhat permanent thing
- */
-static inline void lapic_disable(void)
-{
-       write_mmreg32(LAPIC_SPURIOUS, read_mmreg32(LAPIC_SPURIOUS) & 0xffffefff);
-       //write_msr(IA32_APIC_BASE, read_msr(IA32_APIC_BASE) & ~MSR_APIC_ENABLE);
-}
-
-/* Spins until previous IPIs are delivered.  Not sure if we want it inlined
- * Also not sure when we really need to do this. 
- */
-static inline void lapic_wait_to_send(void)
-{
-       while(read_mmreg32(LAPIC_IPI_ICR_LOWER) & 0x1000)
-               cpu_relax();
-}
-
-static inline void lapic_enable(void)
-{
-       write_mmreg32(LAPIC_SPURIOUS, read_mmreg32(LAPIC_SPURIOUS) | 0x00000100);
-}
-
-static inline void send_init_ipi(void)
-{
-       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4500);
-}
-
-static inline void send_startup_ipi(uint8_t vector)
-{
-       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4600 | vector);
-}
-
-static inline void send_self_ipi(uint8_t vector)
-{
-       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00044000 | vector);
-}
-
-static inline void send_broadcast_ipi(uint8_t vector)
-{
-       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00084000 | vector);
-}
-
-static inline void send_all_others_ipi(uint8_t vector)
-{
-       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4000 | vector);
-}
-
-static inline void send_ipi(uint8_t dest, bool logical_mode, uint8_t vector)
-{
-       write_mmreg32(LAPIC_IPI_ICR_UPPER, dest << 24);
-       write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00004000 | (logical_mode << 11) | vector);
-}
-
-/* To change the LAPIC Base (not recommended):
-       msr_val = read_msr(IA32_APIC_BASE);
-       msr_val = msr_val & ~MSR_APIC_BASE_ADDRESS | 0xfaa00000;
-       write_msr(IA32_APIC_BASE, msr_val);
-*/
-#endif /* ROS_KERN_APIC_H */
diff --git a/kern/atomic.h b/kern/atomic.h
deleted file mode 100644 (file)
index 3b93bf4..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-#ifndef ROS_KERN_ATOMIC_H
-#define ROS_KERN_ATOMIC_H
-
-#include <inc/types.h>
-#include <inc/mmu.h>
-#include <inc/x86.h>
-#include <inc/atomic.h>
-
-/* //linux style atomic ops
-typedef struct {uint32_t real_num;} atomic_t;
-#define atomic_read(atom) ((atom)->real_num)
-#define atomic_set(atom, val) (((atom)->real_num) = (val))
-#define atomic_init(i) {(i)}
-//and the atomic incs, etc take an atomic_t ptr, deref inside
-*/
-
-static inline void spin_lock(volatile uint32_t* lock);
-static inline void spin_unlock(volatile uint32_t* lock);
-static inline void spin_lock_irqsave(volatile uint32_t* lock);
-static inline void spin_unlock_irqsave(volatile uint32_t* lock);
-static inline void atomic_inc(volatile uint32_t* number);
-static inline void atomic_dec(volatile uint32_t* number);
-static inline void atomic_andb(volatile uint8_t* number, uint8_t mask);
-
-/*********************** 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)[];
-} checklist_mask_t;
-
-// mask contains an unspecified array, so it needs to be at the bottom
-typedef struct checklist {
-       volatile uint32_t lock;
-       checklist_mask_t mask;
-} checklist_t;
-
-#define ZEROS_ARRAY(size) {[0 ... ((size)-1)] 0}
-
-#define DEFAULT_CHECKLIST_MASK(sz) {(sz), ZEROS_ARRAY(BYTES_FOR_BITMASK(sz))}
-#define DEFAULT_CHECKLIST(sz) {0, DEFAULT_CHECKLIST_MASK(sz)}
-#define INIT_CHECKLIST(nm, sz) \
-       checklist_t nm = DEFAULT_CHECKLIST(sz);
-#define INIT_CHECKLIST_MASK(nm, sz)    \
-       checklist_mask_t nm = DEFAULT_CHECKLIST_MASK(sz);
-
-int commit_checklist_wait(checklist_t* list, checklist_mask_t* mask);
-int commit_checklist_nowait(checklist_t* list, checklist_mask_t* mask);
-int waiton_checklist(checklist_t* list);
-int release_checklist(checklist_t* list);
-int checklist_is_locked(checklist_t* list);
-int checklist_is_clear(checklist_t* list);
-void reset_checklist(checklist_t* list);
-void down_checklist(checklist_t* list);
-// TODO - do we want to adjust the size?  (YES, don't want to check it all)
-// TODO - do we want to be able to call waiton without having called commit?
-//     - in the case of protected checklists
-// TODO - want a destroy checklist (when we have kmalloc, or whatever)
-// TODO - some sort of dynamic allocation of them in the future
-// TODO - think about deadlock issues with one core spinning on a lock for
-// something that it is the hold out for...
-//     - probably should have interrupts enabled, and never grab these locks
-//     from interrupt context (and not use irq_save)
-/**************************************************************/
-
-/* Barrier: currently made for everyone barriering.  Change to use checklist */
-typedef struct barrier {
-       volatile uint32_t lock;
-       uint32_t init_count;
-       uint32_t current_count;
-    volatile uint8_t ready;
-} barrier_t;
-
-void init_barrier(barrier_t* barrier, uint32_t count);
-void reset_barrier(barrier_t* barrier);
-void waiton_barrier(barrier_t* barrier);
-
-/* Inlined functions declared above */
-static inline void spin_lock(volatile uint32_t* lock)
-{
-       asm volatile(
-                       "1:                       "
-                       "       cmpb $0, %0;          "
-                       "       je 2f;                "
-                       "       pause;                "
-                       "       jmp 1b;               "
-                       "2:                       " 
-                       "       movb $1, %%al;        "
-                       "       xchgb %%al, %0;       "
-                       "       cmpb $0, %%al;        "
-                       "       jne 1b;               "
-               : : "m"(*lock) : "eax", "cc");
-}
-
-static inline void spin_unlock(volatile uint32_t* lock)
-{
-       *lock = 0;
-}
-
-// If ints are enabled, disable them and note it in the top bit of the lock
-// There is an assumption about releasing locks in order here...
-static inline void spin_lock_irqsave(volatile uint32_t* lock)
-{
-       uint32_t eflags;
-       eflags = read_eflags();
-       disable_irq();
-       spin_lock(lock);
-       if (eflags & FL_IF)
-               *lock |= 0x80000000;
-}
-
-// if the top bit of the lock is set, then re-enable interrupts
-static inline void spin_unlock_irqsave(volatile uint32_t* lock)
-{
-       if (*lock & 0x80000000) {
-               *lock = 0;
-               enable_irq();
-       } else
-               *lock = 0;
-}
-
-// need to do this with pointers and deref.  %0 needs to be the memory address
-static inline void atomic_inc(volatile uint32_t* number)
-{
-       asm volatile("lock incl %0" : "=m"(*number) : : "cc");
-}
-
-static inline void atomic_dec(volatile uint32_t* number)
-{
-       asm volatile("lock decl %0" : "=m"(*number) : : "cc");
-}
-
-static inline void atomic_andb(volatile uint8_t* number, uint8_t mask)
-{
-       asm volatile("lock andb %1,%0" : "=m"(*number) : "r"(mask) : "cc");
-}
-#endif /* !ROS_KERN_ATOMIC_H */
diff --git a/kern/boot/Makefrag b/kern/boot/Makefrag
new file mode 100644 (file)
index 0000000..7a57309
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# Makefile fragment for the ROS kernel.
+# This is NOT a complete makefile;
+# you must run GNU make in the top-level directory
+# where the GNUmakefile is located.
+#
+
+KERN_BOOT_DIR := $(KERN_DIR)/boot
+OBJDIRS += $(KERN_BOOT_DIR)
+
+KERN_BOOT_CFLAGS  := $(KERN_CFLAGS) -Os
+KERN_BOOT_LDFLAGS := $(KERN_LDFLAGS) -N -e start -Ttext 0x7C00
+KERN_BOOT_OBJS    := $(OBJDIR)/$(KERN_DIR)/boot.o \
+                     $(OBJDIR)/$(KERN_DIR)/main.o
+
+$(OBJDIR)/$(KERN_DIR)/%.o: $(KERN_BOOT_DIR)/%.c
+       @echo + cc [BOOT] $<
+       @mkdir -p $(@D)
+       $(V)$(CC) $(KERN_BOOT_CFLAGS) -c -o $@ $<
+
+$(OBJDIR)/$(KERN_DIR)/%.o: $(KERN_BOOT_DIR)/%.S
+       @echo + as [BOOT] $<
+       @mkdir -p $(@D)
+       $(V)$(CC) $(KERN_BOOT_CFLAGS) -c -o $@ $<
+
+$(OBJDIR)/$(KERN_DIR)/boot: $(KERN_BOOT_OBJS)
+       @echo + ld [BOOT] $<
+       $(V)$(LD) $(KERN_BOOT_LDFLAGS) -o $@.out $^
+       $(V)$(OBJDUMP) -S $@.out >$@.asm
+       $(V)$(OBJCOPY) -S -O binary $@.out $@
+       $(V)perl $(KERN_BOOT_DIR)/sign.pl $(OBJDIR)/$(KERN_DIR)/boot
+
diff --git a/kern/boot/boot.S b/kern/boot/boot.S
new file mode 100644 (file)
index 0000000..22c2fef
--- /dev/null
@@ -0,0 +1,98 @@
+#include <arch/mmu.h>
+       
+.set PROT_MODE_CSEG,0x8                # code segment selector
+.set PROT_MODE_DSEG,0x10        # data segment selector
+.set CR0_PE_ON,0x1             # protected mode enable flag
+       
+###############################################################################
+# ENTRY POINT  
+#   This code should be stored in the first sector of the hard disk.
+#   After the BIOS initializes the hardware on startup or system reset,
+#   it loads this code at physical address 0x7c00 - 0x7d00 (512 bytes).
+#   Then the BIOS jumps to the beginning of it, address 0x7c00,
+#   while running in 16-bit real-mode (8086 compatibility mode).
+#   The Code Segment register (CS) is initially zero on entry.
+#      
+# This code switches into 32-bit protected mode so that all of
+# memory can accessed, then calls into C.
+###############################################################################
+       
+.globl start                                   # Entry point   
+start:         .code16                         # This runs in real mode
+               cli                             # Disable interrupts
+               cld                             # String operations increment
+
+               # Set up the important data segment registers (DS, ES, SS).
+               xorw    %ax,%ax                 # Segment number zero
+               movw    %ax,%ds                 # -> Data Segment
+               movw    %ax,%es                 # -> Extra Segment
+               movw    %ax,%ss                 # -> Stack Segment
+
+               # Set up the stack pointer, growing downward from 0x7c00.
+               movw    $start,%sp              # Stack Pointer
+       
+# Enable A20:
+#   For fascinating historical reasons (related to the fact that
+#   the earliest 8086-based PCs could only address 1MB of physical memory
+#   and subsequent 80286-based PCs wanted to retain maximum compatibility),
+#   physical address line 20 is tied to low when the machine boots.
+#   Obviously this a bit of a drag for us, especially when trying to
+#   address memory above 1MB.  This code undoes this.
+       
+seta20.1:      inb     $0x64,%al               # Get status
+               testb   $0x2,%al                # Busy?
+               jnz     seta20.1                # Yes
+               movb    $0xd1,%al               # Command: Write
+               outb    %al,$0x64               #  output port
+seta20.2:      inb     $0x64,%al               # Get status
+               testb   $0x2,%al                # Busy?
+               jnz     seta20.2                # Yes
+               movb    $0xdf,%al               # Enable
+               outb    %al,$0x60               #  A20
+
+# Switch from real to protected mode:
+#   Up until now, there's been no protection, so we've gotten along perfectly
+#   well without explicitly telling the processor how to translate addresses.
+#   When we switch to protected mode, this is no longer true!
+#   We need at least to set up some "segments" that tell the processor it's
+#   OK to run code at any address, or write to any address.
+#   The 'gdt' and 'gdtdesc' tables below define these segments.
+#   This code loads them into the processor.
+#   We need this setup to ensure the transition to protected mode is smooth.
+
+real_to_prot:  cli                     # Don't allow interrupts: mandatory,
+                                       # since we didn't set up an interrupt
+                                       # descriptor table for handling them
+               lgdt    gdtdesc         # load GDT: mandatory in protected mode
+               movl    %cr0, %eax      # Turn on protected mode
+               orl     $CR0_PE_ON, %eax
+               movl    %eax, %cr0
+
+               # CPU magic: jump to relocation, flush prefetch queue, and
+               # reload %cs.  Has the effect of just jmp to the next
+               # instruction, but simultaneously loads CS with
+               # $PROT_MODE_CSEG.
+               ljmp    $PROT_MODE_CSEG, $protcseg
+       
+               # we've switched to 32-bit protected mode; tell the assembler
+               # to generate code for that mode
+protcseg:      .code32
+               # Set up the protected-mode data segment registers
+               movw    $PROT_MODE_DSEG, %ax    # Our data segment selector
+               movw    %ax, %ds                # -> DS: Data Segment
+               movw    %ax, %es                # -> ES: Extra Segment
+               movw    %ax, %fs                # -> FS
+               movw    %ax, %gs                # -> GS
+               movw    %ax, %ss                # -> SS: Stack Segment
+       
+               call cmain                      # finish the boot load from C.
+                                               # cmain() should not return
+spin:          jmp spin                        # ..but in case it does, spin
+       
+               .p2align 2                      # force 4 byte alignment
+gdt:           SEG_NULL                                # null seg
+               SEG(STA_X|STA_R, 0x0, 0xffffffff)       # code seg
+               SEG(STA_W, 0x0, 0xffffffff)             # data seg
+       
+gdtdesc:       .word   0x17                    # sizeof(gdt) - 1
+               .long   gdt                     # address gdt
diff --git a/kern/boot/main.c b/kern/boot/main.c
new file mode 100644 (file)
index 0000000..64e9b46
--- /dev/null
@@ -0,0 +1,133 @@
+#ifdef __DEPUTY__
+#pragma nodeputy
+#endif
+
+#include <arch/x86.h>
+#include <arch/elf.h>
+
+/**********************************************************************
+ * This a dirt simple boot loader, whose sole job is to boot
+ * an elf kernel image from the first IDE hard disk.
+ *
+ * DISK LAYOUT
+ *  * This program(boot.S and main.c) is the bootloader.  It should
+ *    be stored in the first sector of the disk.
+ * 
+ *  * The 2nd sector onward holds the kernel image.
+ *     
+ *  * The kernel image must be in ELF format.
+ *
+ * BOOT UP STEPS       
+ *  * when the CPU boots it loads the BIOS into memory and executes it
+ *
+ *  * the BIOS intializes devices, sets of the interrupt routines, and
+ *    reads the first sector of the boot device(e.g., hard-drive) 
+ *    into memory and jumps to it.
+ *
+ *  * Assuming this boot loader is stored in the first sector of the
+ *    hard-drive, this code takes over...
+ *
+ *  * control starts in bootloader.S -- which sets up protected mode,
+ *    and a stack so C code then run, then calls cmain()
+ *
+ *  * cmain() in this file takes over, reads in the kernel and jumps to it.
+ **********************************************************************/
+
+#define SECTSIZE       512
+#define ELFHDR         ((elf_t *) 0x10000) // scratch space
+
+void readsect(void*, uint32_t);
+void readseg(uint32_t, uint32_t, uint32_t);
+
+void
+cmain(void)
+{
+       proghdr_t *ph, *eph;
+
+       // read 1st page off disk
+       readseg((uint32_t) ELFHDR, SECTSIZE*8, 0);
+
+       // is this a valid ELF?
+       if (ELFHDR->e_magic != ELF_MAGIC)
+               goto bad;
+
+       // load each program segment (ignores ph flags)
+       ph = (proghdr_t *) ((uint8_t *) ELFHDR + ELFHDR->e_phoff);
+       eph = ph + ELFHDR->e_phnum;
+       for (; ph < eph; ph++)
+               readseg(ph->p_va, ph->p_memsz, ph->p_offset);
+
+       // call the entry point from the ELF header
+       // note: does not return!
+       ((void (*)(void)) (ELFHDR->e_entry & 0x0FFFFFFF))();
+
+bad:
+       outw(0x8A00, 0x8A00);
+       outw(0x8A00, 0x8E00);
+       while (1)
+               /* do nothing */;
+}
+
+// Read 'count' bytes at 'offset' from kernel into virtual address 'va'.
+// Might copy more than asked
+void
+readseg(uint32_t va, uint32_t count, uint32_t offset)
+{
+       uint32_t end_va;
+
+       va &= 0x0FFFFFFF;
+       end_va = va + count;
+       
+       // round down to sector boundary
+       va &= ~(SECTSIZE - 1);
+
+       // translate from bytes to sectors, and kernel starts at sector 1
+       offset = (offset / SECTSIZE) + 1;
+
+       // If this is too slow, we could read lots of sectors at a time.
+       // We'd write more to memory than asked, but it doesn't matter --
+       // we load in increasing order.
+       while (va < end_va) {
+               readsect((uint8_t*) va, offset);
+               va += SECTSIZE;
+               offset++;
+       }
+}
+
+void
+waitdisk(void)
+{
+       // wait for disk ready
+       while ((inb(0x1F7) & 0xC0) != 0x40)
+               /* do nothing */;
+}
+
+void
+readsect(void *dst, uint32_t offset)
+{
+       // wait for disk to be ready
+       waitdisk();
+
+       /* the ISA uses a specified block of memory, 
+          addresses 0x1F0-0x1F7, that can use the special 
+          instructions inb/outb, as demonstrated in the 
+          following code in order to access the disk
+          Offset is 28 bytes long
+       */
+
+       outb(0x1F2, 1);                         // number of sectors to read
+       outb(0x1F3, offset);                    // bits 0-7 (low bits) of 28-bit offset
+       outb(0x1F4, offset >> 8);               // bits 8-15 of 28-bit offset
+       outb(0x1F5, offset >> 16);              // bits 16-23 of 28-bit offset
+       outb(0x1F6, (offset >> 24) | 0xE0);     // bits 24-27 of 28-bit offset
+                                               // bit 28 (= 0) means Disk 0
+                                               // other bits (29-31) must be set to one
+       outb(0x1F7, 0x20);                      // cmd 0x20 - read sectors
+
+       // wait for disk to be ready
+       waitdisk();
+
+       // read a sector
+       insl(0x1F0, dst, SECTSIZE/4);
+}
+
diff --git a/kern/boot/sign.pl b/kern/boot/sign.pl
new file mode 100644 (file)
index 0000000..8a65e9f
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/perl
+
+open(SIG, $ARGV[0]) || die "open $ARGV[0]: $!";
+
+$n = sysread(SIG, $buf, 1000);
+
+if($n > 510){
+       print STDERR "boot block too large: $n bytes (max 510)\n";
+       exit 1;
+}
+
+print STDERR "boot block is $n bytes (max 510)\n";
+
+$buf .= "\0" x (510-$n);
+$buf .= "\x55\xAA";
+
+open(SIG, ">$ARGV[0]") || die "open >$ARGV[0]: $!";
+print SIG $buf;
+close SIG;
diff --git a/kern/console.h b/kern/console.h
deleted file mode 100644 (file)
index 53fb81f..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/* See COPYRIGHT for copyright information. */
-
-#ifndef _CONSOLE_H_
-#define _CONSOLE_H_
-#ifndef ROS_KERNEL
-# error "This is a ROS kernel header; user programs should not #include it"
-#endif
-
-#include <inc/types.h>
-
-#define MONO_BASE      0x3B4
-#define MONO_BUF       0xB0000
-#define CGA_BASE       0x3D4
-#define CGA_BUF                0xB8000
-
-#define CRT_ROWS       25
-#define CRT_COLS       80
-#define CRT_SIZE       (CRT_ROWS * CRT_COLS)
-
-void cons_init(void);
-void cons_putc(int c);
-int cons_getc(void);
-
-void kbd_intr(void); // irq 1
-void serial_intr(void); // irq 4
-
-#endif /* _CONSOLE_H_ */
diff --git a/kern/env.h b/kern/env.h
deleted file mode 100644 (file)
index 4104edf..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* See COPYRIGHT for copyright information. */
-
-#ifndef ROS_KERN_ENV_H
-#define ROS_KERN_ENV_H
-
-#include <inc/x86.h>
-#include <inc/env.h>
-
-#ifndef ROS_MULTIENV
-// Change this value to 1 once you're allowing multiple environments
-// (for UCLA: Lab 3, Part 3; for MIT: Lab 4).
-#define ROS_MULTIENV 0
-#endif
-
-extern env_t *envs;            // All environments
-extern env_t* NORACE curenvs[MAX_NUM_CPUS];
-
-LIST_HEAD(env_list_t, env_t);          // Declares 'struct Env_list'
-
-void   env_init(void);
-int            env_alloc(env_t **e, envid_t parent_id);
-void   env_free(env_t *e);
-void   env_create(uint8_t *binary, size_t size);
-void   (IN_HANDLER env_destroy)(env_t *e);     // Does not return if e == curenv
-
-int    envid2env(envid_t envid, env_t **env_store, bool checkperm);
-// The following two functions do not return
-void   (IN_HANDLER env_run)(env_t *e) __attribute__((noreturn));
-void   env_pop_tf(trapframe_t *tf) __attribute__((noreturn));
-
-// For the grading script
-#define ENV_CREATE2(start, size)       {               \
-       extern uint8_t start[], size[];                 \
-       env_create(start, (int)size);                   \
-}
-
-#define ENV_CREATE(x)                  {               \
-       extern uint8_t _binary_obj_##x##_start[],       \
-               _binary_obj_##x##_size[];               \
-       env_create(_binary_obj_##x##_start,             \
-               (int)_binary_obj_##x##_size);           \
-}
-
-#endif // !ROS_KERN_ENV_H
diff --git a/kern/ivy/Makefrag b/kern/ivy/Makefrag
new file mode 100644 (file)
index 0000000..68839e1
--- /dev/null
@@ -0,0 +1,20 @@
+NATIVECC := ivycc
+
+KERN_IVY_DIR = $(KERN_DIR)/ivy
+OBJDIRS += $(KERN_IVY_DIR)
+
+KERN_IVY_CFLAGS   := $(KERN_CFLAGS)
+KERN_IVY_SRCFILES := $(KERN_IVY_DIR)/deputy.c
+KERN_IVY_OBJFILES := $(patsubst $(KERN_IVY_DIR)/%.c, \
+                                   $(OBJDIR)/$(KERN_DIR)/%.o, \
+                                   $(KERN_IVY_SRCFILES))
+
+$(OBJDIR)/$(KERN_DIR)/deputy.o: $(KERN_IVY_SRCFILES)
+       @echo + cc [KERN IVY] $<
+       @mkdir -p $(@D)
+       $(V)$(NATIVECC) $(KERN_IVY_CFLAGS) -c -o $@ $<
+
+$(OBJDIR)/$(KERN_DIR)/libivykern.a: $(KERN_IVY_OBJFILES)
+       @echo + ar [KERN IVY] $@
+       $(V)$(AR) r $@ $(KERN_IVY_OBJFILES) 2>/dev/null
+
diff --git a/kern/ivy/deputy.c b/kern/ivy/deputy.c
new file mode 100644 (file)
index 0000000..9747f1f
--- /dev/null
@@ -0,0 +1,111 @@
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#define IN_DEPUTY_LIBRARY
+
+// Use inline even when not optimizing for speed, since it prevents
+// warnings that would occur due to unused static functions.
+#ifdef DEPUTY_ALWAYS_STOP_ON_ERROR
+  #define INLINE inline __attribute__((always_inline))
+#else
+  #define INLINE inline
+#endif
+
+#define __LOCATION__        __FILE__, __LINE__, __FUNCTION__
+#define __LOCATION__FORMALS const char* file, int line, const char* func
+#define __LOCATION__ACTUALS file, line, func
+
+#ifndef asmlinkage
+#define asmlinkage __attribute__((regparm(0)))
+#endif
+
+#ifndef noreturn
+#define noreturn __attribute__((noreturn))
+#endif
+
+asmlinkage
+void deputy_fail_mayreturn(const char *check, const char *text,
+                           __LOCATION__FORMALS) {
+    cprintf("%s:%d: %s: Assertion failed in %s: %s\n",
+            __LOCATION__ACTUALS, check, text);
+/*
+    dump_stack();
+*/
+}
+
+asmlinkage noreturn
+void deputy_fail_noreturn_fast(void) {
+    panic("Deputy assertion failure\n");
+}
+
+int deputy_strlen(const char *str) {
+    return strlen(str);
+}
+
+char *deputy_strcpy(char *dest, const char *src) {
+    char *tmp = dest;
+    while ((*dest++ = *src++) != '\0') {
+        // do nothing
+    }
+    return tmp;
+}
+
+char *deputy_strncpy(char *dest, const char *src, size_t count) {
+    char *tmp = dest;
+    int c = count;
+    while (c >= 0) {
+        if ((*tmp = *src) != 0) src++;
+        tmp++;
+        c--;
+    }
+    return dest;
+}
+
+/* Search for a NULL starting at e and return its index */
+int deputy_findnull(const void *e, unsigned int bytes) {
+#define NULLCHECK(type) \
+    do { \
+        type *p = (type*) e; \
+        while (*p != 0) { \
+            p++; \
+        } \
+        length = (p - (type*) e); \
+    } while (0)
+
+    int length = 0;
+
+    switch (bytes) {
+        case 1:
+            NULLCHECK(char);
+            break;
+        case 2:
+            NULLCHECK(short);
+            break;
+        case 4:
+            NULLCHECK(long);
+            break;
+        default:
+            cprintf("Invalid byte size for nullcheck.\n");
+            break;
+    }
+
+    return length;
+#undef NULLCHECK
+}
+
+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;}
diff --git a/kern/ivylib/Makefrag b/kern/ivylib/Makefrag
deleted file mode 100644 (file)
index 7834bf9..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-NATIVECC := ivycc
-
-KERN_IVYLIB_DIR = $(KERN_DIR)/ivylib
-OBJDIRS += $(KERN_IVYLIB_DIR)
-
-KERN_IVYLIB_CFLAGS   := $(KERN_CFLAGS)
-KERN_IVYLIB_SRCFILES := $(KERN_IVYLIB_DIR)/deputy.c
-KERN_IVYLIB_OBJFILES := $(patsubst $(KERN_IVYLIB_DIR)/%.c, \
-                                   $(OBJDIR)/$(KERN_DIR)/%.o, \
-                                   $(KERN_IVYLIB_SRCFILES))
-
-$(OBJDIR)/$(KERN_DIR)/deputy.o: $(KERN_IVYLIB_SRCFILES)
-       @echo + cc [KERN IVYLIB] $<
-       @mkdir -p $(@D)
-       $(V)$(NATIVECC) $(KERN_IVYLIB_CFLAGS) -c -o $@ $<
-
-$(OBJDIR)/$(KERN_DIR)/libivykern.a: $(KERN_IVYLIB_OBJFILES)
-       @echo + ar [KERN IVYLIB] $@
-       $(V)$(AR) r $@ $(KERN_IVYLIB_OBJFILES) 2>/dev/null
-
diff --git a/kern/ivylib/deputy.c b/kern/ivylib/deputy.c
deleted file mode 100644 (file)
index 5596b16..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-#include <inc/stdio.h>
-#include <inc/assert.h>
-#include <inc/string.h>
-
-#define IN_DEPUTY_LIBRARY
-
-// Use inline even when not optimizing for speed, since it prevents
-// warnings that would occur due to unused static functions.
-#ifdef DEPUTY_ALWAYS_STOP_ON_ERROR
-  #define INLINE inline __attribute__((always_inline))
-#else
-  #define INLINE inline
-#endif
-
-#define __LOCATION__        __FILE__, __LINE__, __FUNCTION__
-#define __LOCATION__FORMALS const char* file, int line, const char* func
-#define __LOCATION__ACTUALS file, line, func
-
-#ifndef asmlinkage
-#define asmlinkage __attribute__((regparm(0)))
-#endif
-
-#ifndef noreturn
-#define noreturn __attribute__((noreturn))
-#endif
-
-asmlinkage
-void deputy_fail_mayreturn(const char *check, const char *text,
-                           __LOCATION__FORMALS) {
-    cprintf("%s:%d: %s: Assertion failed in %s: %s\n",
-            __LOCATION__ACTUALS, check, text);
-/*
-    dump_stack();
-*/
-}
-
-asmlinkage noreturn
-void deputy_fail_noreturn_fast(void) {
-    panic("Deputy assertion failure\n");
-}
-
-int deputy_strlen(const char *str) {
-    return strlen(str);
-}
-
-char *deputy_strcpy(char *dest, const char *src) {
-    char *tmp = dest;
-    while ((*dest++ = *src++) != '\0') {
-        // do nothing
-    }
-    return tmp;
-}
-
-char *deputy_strncpy(char *dest, const char *src, size_t count) {
-    char *tmp = dest;
-    int c = count;
-    while (c >= 0) {
-        if ((*tmp = *src) != 0) src++;
-        tmp++;
-        c--;
-    }
-    return dest;
-}
-
-/* Search for a NULL starting at e and return its index */
-int deputy_findnull(const void *e, unsigned int bytes) {
-#define NULLCHECK(type) \
-    do { \
-        type *p = (type*) e; \
-        while (*p != 0) { \
-            p++; \
-        } \
-        length = (p - (type*) e); \
-    } while (0)
-
-    int length = 0;
-
-    switch (bytes) {
-        case 1:
-            NULLCHECK(char);
-            break;
-        case 2:
-            NULLCHECK(short);
-            break;
-        case 4:
-            NULLCHECK(long);
-            break;
-        default:
-            cprintf("Invalid byte size for nullcheck.\n");
-            break;
-    }
-
-    return length;
-#undef NULLCHECK
-}
-
-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;}
diff --git a/kern/kclock.h b/kern/kclock.h
deleted file mode 100644 (file)
index 813d3e8..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/* See COPYRIGHT for copyright information. */
-
-#ifndef ROS_KERN_KCLOCK_H
-#define ROS_KERN_KCLOCK_H
-#ifndef ROS_KERNEL
-# error "This is a ROS kernel header; user programs should not #include it"
-#endif
-
-#define        IO_RTC          0x070           /* RTC port */
-
-#define        MC_NVRAM_START  0xe     /* start of NVRAM: offset 14 */
-#define        MC_NVRAM_SIZE   50      /* 50 bytes of NVRAM */
-
-/* NVRAM bytes 7 & 8: base memory size */
-#define NVRAM_BASELO   (MC_NVRAM_START + 7)    /* low byte; RTC off. 0x15 */
-#define NVRAM_BASEHI   (MC_NVRAM_START + 8)    /* high byte; RTC off. 0x16 */
-
-/* NVRAM bytes 9 & 10: extended memory size */
-#define NVRAM_EXTLO    (MC_NVRAM_START + 9)    /* low byte; RTC off. 0x17 */
-#define NVRAM_EXTHI    (MC_NVRAM_START + 10)   /* high byte; RTC off. 0x18 */
-
-/* NVRAM bytes 34 and 35: extended memory POSTed size */
-#define NVRAM_PEXTLO   (MC_NVRAM_START + 34)   /* low byte; RTC off. 0x30 */
-#define NVRAM_PEXTHI   (MC_NVRAM_START + 35)   /* high byte; RTC off. 0x31 */
-
-/* NVRAM byte 36: current century.  (please increment in Dec99!) */
-#define NVRAM_CENTURY  (MC_NVRAM_START + 36)   /* RTC offset 0x32 */
-
-unsigned mc146818_read(unsigned reg);
-void mc146818_write(unsigned reg, unsigned datum);
-void kclock_init(void);
-
-#endif // !ROS_KERN_KCLOCK_H
diff --git a/kern/kdebug.h b/kern/kdebug.h
deleted file mode 100644 (file)
index 2b7ea2e..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef ROS_KERN_KDEBUG_H
-#define ROS_KERN_KDEBUG_H
-
-#include <inc/types.h>
-
-// Debug information about a particular instruction pointer
-typedef struct Eipdebuginfo {
-       const char *eip_file;           // Source code filename for EIP
-       int eip_line;                           // Source code linenumber for EIP
-
-       const char *eip_fn_name;        // Name of function containing EIP
-                                                               //  - Note: not null terminated!
-       int eip_fn_namelen;                     // Length of function name
-       uintptr_t eip_fn_addr;          // Address of start of function
-       int eip_fn_narg;                        // Number of function arguments
-} eipdebuginfo_t;
-
-int debuginfo_eip(uintptr_t eip, eipdebuginfo_t *info);
-
-#endif
diff --git a/kern/monitor.h b/kern/monitor.h
deleted file mode 100644 (file)
index 85ab289..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef ROS_KERN_MONITOR_H
-#define ROS_KERN_MONITOR_H
-#ifndef ROS_KERNEL
-# error "This is a ROS kernel header; user programs should not #include it"
-#endif
-
-#include <kern/trap.h>
-
-// Activate the kernel monitor,
-// optionally providing a trap frame indicating the current state
-// (NULL if none).
-void (IN_HANDLER monitor)(trapframe_t *tf);
-
-// Functions implementing monitor commands.
-int mon_help(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
-int mon_kerninfo(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
-int mon_backtrace(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
-int mon_reboot(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
-int mon_showmapping(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
-int mon_setmapperm(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
-int mon_cpuinfo(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf);
-
-#endif // !ROS_KERN_MONITOR_H
diff --git a/kern/pmap.h b/kern/pmap.h
deleted file mode 100644 (file)
index 31a255f..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/* See COPYRIGHT for copyright information. */
-
-#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 <inc/memlayout.h>
-#include <inc/assert.h>
-#include <inc/multiboot.h>
-#include <kern/atomic.h>
-#include <kern/env.h>
-
-/* This macro takes a kernel virtual address -- an address that points above
- * KERNBASE, where the machine's maximum 256MB of physical memory is mapped --
- * and returns the corresponding physical address.  It panics if you pass it a
- * non-kernel virtual address.
- */
-#define PADDR(kva)                                             \
-({                                                             \
-       physaddr_t __m_kva = (physaddr_t) (kva);                \
-       if (__m_kva < KERNBASE)                                 \
-               panic("PADDR called with invalid kva %08lx", __m_kva);\
-       __m_kva - KERNBASE;                                     \
-})
-
-/* This macro takes a physical address and returns the corresponding kernel
- * virtual address.  It warns if you pass an invalid physical address. */
-#define KADDR(pa)                                              \
-({                                                             \
-       physaddr_t __m_pa = (pa);                               \
-       uint32_t __m_ppn = PPN(__m_pa);                         \
-       if (__m_ppn >= npage)                                   \
-               warn("KADDR called with invalid pa %08lx", __m_pa);\
-       (void*) (__m_pa + KERNBASE);                            \
-})
-
-
-
-extern char bootstacktop[], bootstack[];
-
-extern page_t *pages;
-extern size_t npage;
-
-extern physaddr_t boot_cr3;
-extern pde_t *boot_pgdir;
-
-extern segdesc_t (COUNT(SEG_COUNT) gdt)[];
-extern pseudodesc_t gdt_pd;
-
-void   i386_detect_memory(multiboot_info_t *mbi);
-void   i386_print_memory_map(multiboot_info_t *mbi);
-bool   enable_pse(void);
-void   i386_vm_init(void);
-
-void   page_init(void);
-void   page_check(void);
-int    page_alloc(page_t **pp_store);
-void   page_free(page_t *pp);
-int    page_insert(pde_t *pgdir, page_t *pp, void *va, int perm);
-void   page_remove(pde_t *pgdir, void *va);
-page_t *page_lookup(pde_t *pgdir, void *va, pte_t **pte_store);
-void   page_decref(page_t *pp);
-
-void setup_default_mtrrs(barrier_t* smp_barrier);
-void   tlb_invalidate(pde_t *pgdir, void *va);
-void tlb_flush_global(void);
-
-void *COUNT(len)
-user_mem_check(env_t *env, const void *DANGEROUS va, size_t len, int perm);
-
-void *COUNT(len)
-user_mem_assert(env_t *env, const void *DANGEROUS va, size_t len, int perm);
-
-static inline void cache_flush(void)
-{
-       wbinvd();
-}
-
-static inline void cacheline_flush(void* addr)
-{
-       clflush((uintptr_t*)addr);
-}
-
-static inline ppn_t page2ppn(page_t *pp)
-{
-       return pp - pages;
-}
-
-static inline physaddr_t page2pa(page_t *pp)
-{
-       return page2ppn(pp) << PGSHIFT;
-}
-
-static inline page_t* pa2page(physaddr_t pa)
-{
-       if (PPN(pa) >= npage)
-               warn("pa2page called with pa larger than npage");
-       return &pages[PPN(pa)];
-}
-
-static inline void* page2kva(page_t *pp)
-{
-       return KADDR(page2pa(pp));
-}
-
-pte_t *pgdir_walk(pde_t *pgdir, const void *va, int create);
-
-#endif /* !ROS_KERN_PMAP_H */
diff --git a/kern/sched.h b/kern/sched.h
deleted file mode 100644 (file)
index d751fb5..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/* See COPYRIGHT for copyright information. */
-
-#ifndef ROS_KERN_SCHED_H
-#define ROS_KERN_SCHED_H
-#ifndef ROS_KERNEL
-# error "This is a ROS kernel header; user programs should not #include it"
-#endif
-
-// This function does not return.
-void sched_yield(void) __attribute__((noreturn));
-
-#endif // !ROS_KERN_SCHED_H
diff --git a/kern/smp.h b/kern/smp.h
deleted file mode 100644 (file)
index 6e1d31a..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef ROS_INC_SMP_H
-#define ROS_INC_SMP_H
-
-/* SMP related functions */
-
-#include <inc/types.h>
-#include <inc/queue.h>
-
-#include <kern/trap.h>
-#include <kern/atomic.h>
-
-#ifdef __BOCHS__
-#define SMP_CALL_FUNCTION_TIMEOUT    0x00ffffff
-#define SMP_BOOT_TIMEOUT             0x0000ffff
-#else
-#define SMP_CALL_FUNCTION_TIMEOUT    0x7ffffff0
-#define SMP_BOOT_TIMEOUT             0x002fffff
-#endif
-
-// be careful changing this, esp if you go over 16
-#define NUM_HANDLER_WRAPPERS           5
-
-typedef struct HandlerWrapper {
-       checklist_t* cpu_list;
-       uint8_t vector;
-} handler_wrapper_t;
-
-/* SMP bootup functions */
-void smp_boot(void);
-void smp_idle(void);
-
-/* SMP utility functions */
-int smp_call_function_self(isr_t handler, void* data,
-                           handler_wrapper_t** wait_wrapper);
-int smp_call_function_all(isr_t handler, void* data,
-                          handler_wrapper_t** wait_wrapper);
-int smp_call_function_single(uint8_t dest, isr_t handler, void* data,
-                             handler_wrapper_t** wait_wrapper);
-int smp_call_wait(handler_wrapper_t* wrapper);
-
-#endif /* !ROS_INC_SMP_H */
index e22e42b..d6dba6b 100644 (file)
@@ -30,14 +30,14 @@ KERN_SRCFILES := $(KERN_SRC_DIR)/entry.S \
                  $(KERN_SRC_DIR)/testing.c \
                  $(KERN_SRC_DIR)/atomic.c \
                  $(KERN_SRC_DIR)/smp.c \
-                 $(USER_PARLIB_SRC_DIR)/printfmt.c \
-                 $(USER_PARLIB_SRC_DIR)/readline.c \
-                 $(USER_PARLIB_SRC_DIR)/string.c \
-                 $(USER_PARLIB_SRC_DIR)/timer.c
+                 $(KERN_SRC_DIR)/printfmt.c \
+                 $(KERN_SRC_DIR)/readline.c \
+                 $(KERN_SRC_DIR)/string.c \
+                 $(KERN_SRC_DIR)/timer.c
 # Only build files if they exist.
 KERN_SRCFILES := $(wildcard $(KERN_SRCFILES))
 
-KERN_APPFILES :=       $(USER_APPS_NEWLIB_DIR)/hello \
+KERN_APPFILES :=       $(USER_APPS_ROSLIB_DIR)/hello \
                     $(USER_APPS_PARLIB_DIR)/hello
 #                                      apps/null \
 #                                      apps/hello \
@@ -58,19 +58,21 @@ KERN_APPFILES :=    $(USER_APPS_NEWLIB_DIR)/hello \
 
 KERN_LDFLAGS   := $(KERN_LDFLAGS) -L$(OBJDIR)/$(KERN_DIR) \
                   -T $(KERN_DIR)/kernel.ld
+
 KERN_OBJFILES  := $(patsubst $(KERN_SRC_DIR)/%.c, \
                              $(OBJDIR)/$(KERN_DIR)/%.o, \
                              $(KERN_SRCFILES))
 KERN_OBJFILES  := $(patsubst $(KERN_SRC_DIR)/%.S, \
                              $(OBJDIR)/$(KERN_DIR)/%.o, \
                              $(KERN_OBJFILES))
-KERN_OBJFILES  := $(patsubst $(USER_PARLIB_SRC_DIR)/%.c, \
-                             $(OBJDIR)/$(KERN_DIR)/%.o, \
-                             $(KERN_OBJFILES))
+
 KERN_APPFILES  := $(patsubst %, $(OBJDIR)/%, $(KERN_APPFILES))
+
 KERN_LDDEPENDS := $(KERN_OBJFILES) $(KERN_APPFILES) $(KERN_DIR)/kernel.ld \
                   $(OBJDIR)/$(KERN_DIR)/libivykern.a
+
 KERN_LDLIBS    := -livykern
+
 KERN_GCC_LIB   := $(GCC_LIB)
 
 $(OBJDIR)/$(KERN_DIR)/%.o: $(KERN_SRC_DIR)/%.c
@@ -83,11 +85,6 @@ $(OBJDIR)/$(KERN_DIR)/%.o: $(KERN_SRC_DIR)/%.S
        @mkdir -p $(@D)
        $(V)$(CC) $(KERN_CFLAGS) -c -o $@ $<
 
-$(OBJDIR)/$(KERN_DIR)/%.o: $(USER_PARLIB_SRC_DIR)/%.c
-       @echo + cc [KERN] $<
-       @mkdir -p $(@D)
-       $(V)$(CC) $(KERN_CFLAGS) -c -o $@ $<
-
 $(OBJDIR)/$(KERN_DIR)/kernel: $(KERN_LDDEPENDS)
        @echo + ld [KERN] $@
        $(V)$(LD) -o $@ $(KERN_LDFLAGS) $(KERN_OBJFILES) $(KERN_LDLIBS) \
@@ -95,10 +92,10 @@ $(OBJDIR)/$(KERN_DIR)/kernel: $(KERN_LDDEPENDS)
        $(V)$(OBJDUMP) -S $@ > $@.asm
        $(V)$(NM) -n $@ > $@.sym
 
-$(OBJDIR)/$(KERN_DIR)/bochs.img: $(OBJDIR)/$(KERN_DIR)/kernel $(OBJDIR)/$(BOOT_DIR)/boot
+$(OBJDIR)/$(KERN_DIR)/bochs.img: $(OBJDIR)/$(KERN_DIR)/kernel $(OBJDIR)/$(KERN_DIR)/boot
        @echo + mk [KERN] $@
        $(V)dd if=/dev/zero of=$(OBJDIR)/$(KERN_DIR)/bochs.img~ count=10000 2>/dev/null
-       $(V)dd if=$(OBJDIR)/$(BOOT_DIR)/boot of=$(OBJDIR)/$(KERN_DIR)/bochs.img~ conv=notrunc 2>/dev/null
+       $(V)dd if=$(OBJDIR)/$(KERN_DIR)/boot of=$(OBJDIR)/$(KERN_DIR)/bochs.img~ conv=notrunc 2>/dev/null
        $(V)dd if=$(OBJDIR)/$(KERN_DIR)/kernel of=$(OBJDIR)/$(KERN_DIR)/bochs.img~ seek=1 conv=notrunc 2>/dev/null
        $(V)mv $(OBJDIR)/kern/bochs.img~ $(OBJDIR)/kern/bochs.img
 
index 28b56e3..90de4ec 100644 (file)
@@ -3,12 +3,11 @@
  * See LICENSE for details.
  */
 
-#include <inc/mmu.h>
-#include <inc/x86.h>
-#include <inc/assert.h>
-#include <inc/timer.h>
-
-#include <kern/apic.h>
+#include <arch/mmu.h>
+#include <arch/x86.h>
+#include <arch/apic.h>
+#include <arch/timer.h>
+#include <assert.h>
 
 system_timing_t system_timing = {0, 0, 0xffff, 0};
 
index f7d9e97..3a0eed7 100644 (file)
@@ -1,9 +1,8 @@
-#include <inc/string.h>
-#include <inc/assert.h>
-#include <inc/error.h>
-
-#include <kern/atomic.h>
-#include <kern/apic.h>
+#include <arch/apic.h>
+#include <string.h>
+#include <assert.h>
+#include <error.h>
+#include <atomic.h>
 
 // Must be called in a pair with waiton_checklist
 int commit_checklist_wait(checklist_t* list, checklist_mask_t* mask)
index ad94a80..4368dd2 100644 (file)
@@ -1,13 +1,12 @@
 /* See COPYRIGHT for copyright information. */
 
-#include <inc/x86.h>
-#include <inc/memlayout.h>
-#include <inc/kbdreg.h>
-#include <inc/string.h>
-#include <inc/assert.h>
-
-#include <kern/console.h>
+#include <arch/x86.h>
+#include <arch/console.h>
+#include <kbdreg.h>
+#include <string.h>
+#include <assert.h>
 
+#include <ros/memlayout.h>
 
 void cons_intr(int (*proc)(void));
 void scroll_screen(void);
index 3330be9..51df48e 100644 (file)
@@ -1,8 +1,8 @@
 /* See COPYRIGHT for copyright information. */
 
-#include <inc/mmu.h>
-#include <inc/memlayout.h>
-#include <inc/trap.h>
+#include <arch/mmu.h>
+#include <ros/trap.h>
+#include <ros/memlayout.h>
 
 # Shift Right Logical 
 #define SRL(val, shamt)                (((val) >> (shamt)) & ~(-1 << (32 - (shamt))))
index f6c6072..0ca5f94 100644 (file)
@@ -3,20 +3,21 @@
 #pragma nodeputy
 #endif
 
-#include <inc/x86.h>
-#include <inc/mmu.h>
-#include <inc/error.h>
-#include <inc/string.h>
-#include <inc/assert.h>
-#include <inc/elf.h>
-#include <inc/syscall.h>
-
-#include <kern/env.h>
-#include <kern/pmap.h>
-#include <kern/trap.h>
-#include <kern/monitor.h>
-#include <kern/apic.h>
-#include <kern/smp.h>
+#include <arch/x86.h>
+#include <arch/mmu.h>
+#include <arch/elf.h>
+#include <arch/apic.h>
+#include <arch/smp.h>
+
+#include <error.h>
+#include <string.h>
+#include <assert.h>
+#include <env.h>
+#include <pmap.h>
+#include <trap.h>
+#include <monitor.h>
+
+#include <ros/syscall.h>
 
 env_t *envs = NULL;            // All environments
 // TODO: make this a struct of info including the pointer and cacheline-align it
index a8853e5..fd0a753 100644 (file)
@@ -8,24 +8,24 @@
 #include Everything For Free -- It just works!!
 #else
 
-#include <inc/stdio.h>
-#include <inc/string.h>
-#include <inc/assert.h>
-#include <inc/multiboot.h>
-#include <inc/stab.h>
-#include <inc/x86.h>
-
-#include <kern/monitor.h>
-#include <kern/console.h>
-#include <kern/pmap.h>
-#include <kern/kclock.h>
-#include <kern/env.h>
-#include <kern/trap.h>
-#include <kern/apic.h>
-#include <kern/testing.h>
-#include <kern/atomic.h>
-#include <kern/smp.h>
-#include <kern/syscall.h>
+#include <arch/x86.h>
+#include <arch/apic.h>
+#include <arch/console.h>
+#include <arch/multiboot.h>
+#include <arch/stab.h>
+#include <arch/smp.h>
+
+#include <stdio.h>
+#include <atomic.h>
+#include <string.h>
+#include <assert.h>
+#include <monitor.h>
+#include <pmap.h>
+#include <env.h>
+#include <trap.h>
+#include <testing.h>
+#include <syscall.h>
+#include <kclock.h>
 
 static void print_cpuinfo(void);
 
@@ -83,7 +83,7 @@ void kernel_init(multiboot_info_t *mboot_info)
        //ENV_CREATE(user_evilhello);
        //ENV_CREATE(user_hello);
        ENV_CREATE(user_apps_parlib_hello);
-       ENV_CREATE(user_apps_newlib_hello);
+       ENV_CREATE(user_apps_roslib_hello);
        //ENV_CREATE(user_hello);
        //ENV_CREATE(user_hello);
        //ENV_CREATE(user_hello);
index d52f8f7..6f42dce 100644 (file)
@@ -5,9 +5,9 @@
  * generates interrupts on IRQ 0.
  */
 
-#include <inc/x86.h>
+#include <arch/x86.h>
 
-#include <kern/kclock.h>
+#include <kclock.h>
 
 
 unsigned
index 15c2d4b..dcc09d2 100644 (file)
@@ -2,14 +2,14 @@
 #pragma nodeputy
 #endif
 
-#include <inc/stab.h>
-#include <inc/string.h>
-#include <inc/memlayout.h>
-#include <inc/assert.h>
-
-#include <kern/kdebug.h>
-#include <kern/pmap.h>
-#include <kern/env.h>
+#include <arch/stab.h>
+#include <string.h>
+#include <assert.h>
+#include <kdebug.h>
+#include <pmap.h>
+#include <env.h>
+
+#include <ros/memlayout.h>
 
 extern const stab_t __STAB_BEGIN__[];  // Beginning of stabs table
 extern const stab_t __STAB_END__[];    // End of stabs table
index 3041662..a097d0e 100644 (file)
@@ -5,21 +5,22 @@
 #pragma nodeputy
 #endif
 
-#include <inc/stdio.h>
-#include <inc/string.h>
-#include <inc/memlayout.h>
-#include <inc/assert.h>
-#include <inc/x86.h>
-#include <inc/stab.h>
+#include <arch/x86.h>
+#include <arch/stab.h>
+#include <arch/apic.h>
+#include <arch/smp.h>
+#include <arch/console.h>
 
-#include <kern/console.h>
-#include <kern/monitor.h>
-#include <kern/trap.h>
-#include <kern/kdebug.h>
-#include <kern/pmap.h>
-#include <kern/apic.h>
-#include <kern/smp.h>
-#include <kern/testing.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <monitor.h>
+#include <trap.h>
+#include <pmap.h>
+#include <kdebug.h>
+#include <testing.h>
+
+#include <ros/memlayout.h>
 
 #define CMDBUF_SIZE    80      // enough for one VGA text line
 
index e9d3ac8..f73b75d 100644 (file)
@@ -3,17 +3,17 @@
 #pragma nodeputy
 #endif
 
-#include <inc/x86.h>
-#include <inc/mmu.h>
-#include <inc/error.h>
-#include <inc/string.h>
-#include <inc/assert.h>
-
-#include <kern/pmap.h>
-#include <kern/kclock.h>
-#include <kern/env.h>
-#include <kern/apic.h>
-#include <kern/atomic.h>
+#include <arch/x86.h>
+#include <arch/mmu.h>
+#include <arch/apic.h>
+
+#include <atomic.h>
+#include <error.h>
+#include <string.h>
+#include <assert.h>
+#include <pmap.h>
+#include <kclock.h>
+#include <env.h>
 
 // These variables are set by i386_detect_memory()
 static physaddr_t maxpa;       // Maximum physical address
index 8f65906..668e3c0 100644 (file)
@@ -5,11 +5,10 @@
 #pragma nodeputy
 #endif
 
-#include <inc/types.h>
-#include <inc/stdio.h>
-#include <inc/stdarg.h>
-
-#include <kern/atomic.h>
+#include <arch/types.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <atomic.h>
 
 uint32_t output_lock = 0;
 
diff --git a/kern/src/printfmt.c b/kern/src/printfmt.c
new file mode 100644 (file)
index 0000000..cdeab36
--- /dev/null
@@ -0,0 +1,297 @@
+// Stripped-down primitive printf-style formatting routines,
+// used in common by printf, sprintf, fprintf, etc.
+// This code is also used by both the kernel and user programs.
+
+#ifdef __DEPUTY__
+#pragma nodeputy
+#endif
+
+#include <arch/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <error.h>
+
+/*
+ * Space or zero padding and a field width are supported for the numeric
+ * formats only. 
+ * 
+ * The special format %e takes an integer error code
+ * and prints a string describing the error.
+ * The integer may be positive or negative,
+ * so that -E_NO_MEM and E_NO_MEM are equivalent.
+ */
+
+static const char * const error_string[MAXERROR + 1] =
+{
+       NULL,
+       "unspecified error",
+       "bad environment",
+       "invalid parameter",
+       "out of memory",
+       "out of environments",
+       "segmentation fault",
+};
+
+/*
+ * Print a number (base <= 16) in reverse order,
+ * using specified putch function and associated pointer putdat.
+ */
+static void printnum(void (*putch)(int, void**), void **putdat,
+                        unsigned long long num, unsigned base, int width, int padc)
+{
+       // first recursively print all preceding (more significant) digits
+       if (num >= base) {
+               printnum(putch, putdat, num / base, base, width - 1, padc);
+       } else {
+               // print any needed pad characters before first digit
+               while (--width > 0)
+                       putch(padc, putdat);
+       }
+
+       // then print this (the least significant) digit
+       putch("0123456789abcdef"[num % base], putdat);
+}
+
+// Get an unsigned int of various possible sizes from a varargs list,
+// depending on the lflag parameter.
+static unsigned long long getuint(va_list *ap, int lflag)
+{
+       if (lflag >= 2)
+               return va_arg(*ap, unsigned long long);
+       else if (lflag)
+               return va_arg(*ap, unsigned long);
+       else
+               return va_arg(*ap, unsigned int);
+}
+
+// Same as getuint but signed - can't use getuint
+// because of sign extension
+static long long getint(va_list *ap, int lflag)
+{
+       if (lflag >= 2)
+               return va_arg(*ap, long long);
+       else if (lflag)
+               return va_arg(*ap, long);
+       else
+               return va_arg(*ap, int);
+}
+
+
+// Main function to format and print a string.
+void printfmt(void (*putch)(int, void**), void **putdat, const char *fmt, ...);
+
+void vprintfmt(void (*putch)(int, void**), void **putdat, const char *fmt, va_list ap)
+{
+       register const char *p;
+       register int ch, err;
+       unsigned long long num;
+       int base, lflag, width, precision, altflag;
+       char padc;
+
+       while (1) {
+               while ((ch = *(unsigned char *) fmt++) != '%') {
+                       if (ch == '\0')
+                               return;
+                       putch(ch, putdat);
+               }
+
+               // Process a %-escape sequence
+               padc = ' ';
+               width = -1;
+               precision = -1;
+               lflag = 0;
+               altflag = 0;
+       reswitch:
+               switch (ch = *(unsigned char *) fmt++) {
+
+               // flag to pad on the right
+               case '-':
+                       padc = '-';
+                       goto reswitch;
+                       
+               // flag to pad with 0's instead of spaces
+               case '0':
+                       padc = '0';
+                       goto reswitch;
+
+               // width field
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+                       for (precision = 0; ; ++fmt) {
+                               precision = precision * 10 + ch - '0';
+                               ch = *fmt;
+                               if (ch < '0' || ch > '9')
+                                       break;
+                       }
+                       goto process_precision;
+
+               case '*':
+                       precision = va_arg(ap, int);
+                       goto process_precision;
+
+               case '.':
+                       if (width < 0)
+                               width = 0;
+                       goto reswitch;
+
+               case '#':
+                       altflag = 1;
+                       goto reswitch;
+
+               process_precision:
+                       if (width < 0)
+                               width = precision, precision = -1;
+                       goto reswitch;
+
+               // long flag (doubled for long long)
+               case 'l':
+                       lflag++;
+                       goto reswitch;
+
+               // character
+               case 'c':
+                       putch(va_arg(ap, int), putdat);
+                       break;
+
+               // error message
+               case 'e':
+                       err = va_arg(ap, int);
+                       if (err < 0)
+                               err = -err;
+                       if (err > MAXERROR || (p = error_string[err]) == NULL)
+                               printfmt(putch, putdat, "error %d", err);
+                       else
+                               printfmt(putch, putdat, "%s", p);
+                       break;
+
+               // string
+               case 's':
+                       if ((p = va_arg(ap, char *)) == NULL)
+                               p = "(null)";
+                       if (width > 0 && padc != '-')
+                               for (width -= strnlen(p, precision); width > 0; width--)
+                                       putch(padc, putdat);
+                       for (; (ch = *p++) != '\0' && (precision < 0 || --precision >= 0); width--)
+                               if (altflag && (ch < ' ' || ch > '~'))
+                                       putch('?', putdat);
+                               else
+                                       putch(ch, putdat);
+                       for (; width > 0; width--)
+                               putch(' ', putdat);
+                       break;
+
+               // (signed) decimal
+               case 'd':
+                       num = getint(&ap, lflag);
+                       if ((long long) num < 0) {
+                               putch('-', putdat);
+                               num = -(long long) num;
+                       }
+                       base = 10;
+                       goto number;
+
+               // unsigned decimal
+               case 'u':
+                       num = getuint(&ap, lflag);
+                       base = 10;
+                       goto number;
+
+               // (unsigned) octal
+               case 'o':
+                       // should do something with padding so it's always 3 octits
+                       num = getuint(&ap, lflag);
+                       base = 8;
+                       goto number;
+
+               // pointer
+               case 'p':
+                       putch('0', putdat);
+                       putch('x', putdat);
+                       num = (unsigned long long)
+                               (uintptr_t) va_arg(ap, void *);
+                       base = 16;
+                       goto number;
+
+               // (unsigned) hexadecimal
+               case 'x':
+                       num = getuint(&ap, lflag);
+                       base = 16;
+               number:
+                       printnum(putch, putdat, num, base, width, padc);
+                       break;
+
+               // escaped '%' character
+               case '%':
+                       putch(ch, putdat);
+                       break;
+                       
+               // unrecognized escape sequence - just print it literally
+               default:
+                       putch('%', putdat);
+                       for (fmt--; fmt[-1] != '%'; fmt--)
+                               /* do nothing */;
+                       break;
+               }
+       }
+}
+
+void printfmt(void (*putch)(int, void**), void **putdat, const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       vprintfmt(putch, putdat, fmt, ap);
+       va_end(ap);
+}
+
+typedef struct sprintbuf {
+       char *buf;
+       char *ebuf;
+       int cnt;
+} sprintbuf_t;
+
+static void sprintputch(int ch, sprintbuf_t **b)
+{
+       (*b)->cnt++;
+       if ((*b)->buf < (*b)->ebuf)
+               *((*b)->buf++) = ch;
+}
+
+int vsnprintf(char *buf, int n, const char *fmt, va_list ap)
+{
+       sprintbuf_t b = {buf, buf+n-1, 0};
+       sprintbuf_t *bp = &b;
+
+       if (buf == NULL || n < 1)
+               return -E_INVAL;
+
+       // print the string to the buffer
+       vprintfmt((void*)sprintputch, (void**)&bp, fmt, ap);
+
+       // null terminate the buffer
+       *b.buf = '\0';
+
+       return b.cnt;
+}
+
+int snprintf(char *buf, int n, const char *fmt, ...)
+{
+       va_list ap;
+       int rc;
+
+       va_start(ap, fmt);
+       rc = vsnprintf(buf, n, fmt, ap);
+       va_end(ap);
+
+       return rc;
+}
+
+
diff --git a/kern/src/readline.c b/kern/src/readline.c
new file mode 100644 (file)
index 0000000..96b00e8
--- /dev/null
@@ -0,0 +1,42 @@
+#ifdef __DEPUTY__
+#pragma nodeputy
+#endif
+
+#include <stdio.h>
+#include <error.h>
+
+#define BUFLEN 1024
+static char buf[BUFLEN];
+
+char *
+readline(const char *prompt)
+{
+       int i, c, echoing;
+
+       if (prompt != NULL)
+               cprintf("%s", prompt);
+
+       i = 0;
+       echoing = iscons(0);
+       while (1) {
+               c = getchar();
+               if (c < 0) {
+                       cprintf("read error: %e\n", c);
+                       return NULL;
+               } else if (c >= ' ' && i < BUFLEN-1) {
+                       if (echoing)
+                               cputchar(c);
+                       buf[i++] = c;
+               } else if (c == '\b' && i > 0) {
+                       if (echoing)
+                               cputchar(c);
+                       i--;
+               } else if (c == '\n' || c == '\r') {
+                       if (echoing)
+                               cputchar(c);
+                       buf[i] = 0;
+                       return buf;
+               }
+       }
+}
+
index 8c1881c..c9f9438 100644 (file)
@@ -2,19 +2,18 @@
 #pragma nodeputy
 #endif
 
-#include <inc/stdio.h>
-#include <inc/string.h>
-#include <inc/assert.h>
-#include <inc/error.h>
-#include <inc/x86.h>
-
-#include <kern/smp.h>
-#include <kern/console.h>
-#include <kern/pmap.h>
-#include <kern/env.h>
-#include <kern/apic.h>
-#include <kern/atomic.h>
-#include <kern/trap.h>
+#include <arch/x86.h>
+#include <arch/smp.h>
+#include <arch/console.h>
+#include <arch/apic.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <error.h>
+#include <pmap.h>
+#include <env.h>
+#include <atomic.h>
+#include <trap.h>
 
 volatile uint8_t num_cpus = 0xee;
 uintptr_t smp_stack_top;
index 434a1d9..95bcb9f 100644 (file)
@@ -1,6 +1,6 @@
-#include <inc/mmu.h>
-#include <inc/memlayout.h>
-#include <inc/trap.h>
+#include <arch/mmu.h>
+#include <ros/memlayout.h>
+#include <ros/trap.h>
 
 #define        RELOC(x) ((x) - KERNBASE)
 #define        CPUID_PSE_SUPPORT       0x00000008
diff --git a/kern/src/string.c b/kern/src/string.c
new file mode 100644 (file)
index 0000000..06622a9
--- /dev/null
@@ -0,0 +1,230 @@
+// Basic string routines.  Not hardware optimized, but not shabby.
+
+#ifdef __DEPUTY__
+#pragma nodeputy
+#endif
+
+#include <string.h>
+
+int
+strlen(const char *s)
+{
+       int n;
+
+       for (n = 0; *s != '\0'; s++)
+               n++;
+       return n;
+}
+
+int
+strnlen(const char *s, size_t size)
+{
+       int n;
+
+       for (n = 0; size > 0 && *s != '\0'; s++, size--)
+               n++;
+       return n;
+}
+
+char *
+strcpy(char *dst, const char *src)
+{
+       char *ret;
+
+       ret = dst;
+       while ((*dst++ = *src++) != '\0')
+               /* do nothing */;
+       return ret;
+}
+
+char *
+strncpy(char *dst, const char *src, size_t size) {
+       size_t i;
+       char *ret;
+
+       ret = dst;
+       for (i = 0; i < size; i++) {
+               *dst++ = *src;
+               // If strlen(src) < size, null-pad 'dst' out to 'size' chars
+               if (*src != '\0')
+                       src++;
+       }
+       return ret;
+}
+
+size_t
+strlcpy(char *dst, const char *src, size_t size)
+{
+       char *dst_in;
+
+       dst_in = dst;
+       if (size > 0) {
+               while (--size > 0 && *src != '\0')
+                       *dst++ = *src++;
+               *dst = '\0';
+       }
+       return dst - dst_in;
+}
+
+int
+strcmp(const char *p, const char *q)
+{
+       while (*p && *p == *q)
+               p++, q++;
+       return (int) ((unsigned char) *p - (unsigned char) *q);
+}
+
+int
+strncmp(const char *p, const char *q, size_t n)
+{
+       while (n > 0 && *p && *p == *q)
+               n--, p++, q++;
+       if (n == 0)
+               return 0;
+       else
+               return (int) ((unsigned char) *p - (unsigned char) *q);
+}
+
+// Return a pointer to the first occurrence of 'c' in 's',
+// or a null pointer if the string has no 'c'.
+char *
+strchr(const char *s, char c)
+{
+       for (; *s; s++)
+               if (*s == c)
+                       return (char *) s;
+       return 0;
+}
+
+// Return a pointer to the first occurrence of 'c' in 's',
+// or a pointer to the string-ending null character if the string has no 'c'.
+char *
+strfind(const char *s, char c)
+{
+       for (; *s; s++)
+               if (*s == c)
+                       break;
+       return (char *) s;
+}
+
+
+void *
+memset(void *v, int c, size_t n)
+{
+       char *p;
+       int m;
+
+       p = v;
+       m = n;
+       while (--m >= 0)
+               *p++ = c;
+
+       return v;
+}
+
+void *
+memcpy(void *dst, const void *src, size_t n)
+{
+       const char *s;
+       char *d;
+
+       s = src;
+       d = dst;
+       while (n-- > 0)
+               *d++ = *s++;
+
+       return dst;
+}
+
+void *
+memmove(void *dst, const void *src, size_t n)
+{
+       const char *s;
+       char *d;
+       
+       s = src;
+       d = dst;
+       if (s < d && s + n > d) {
+               s += n;
+               d += n;
+               while (n-- > 0)
+                       *--d = *--s;
+       } else
+               while (n-- > 0)
+                       *d++ = *s++;
+
+       return dst;
+}
+
+int
+memcmp(const void *v1, const void *v2, size_t n)
+{
+       const uint8_t *s1 = (const uint8_t *) v1;
+       const uint8_t *s2 = (const uint8_t *) v2;
+
+       while (n-- > 0) {
+               if (*s1 != *s2)
+                       return (int) *s1 - (int) *s2;
+               s1++, s2++;
+       }
+
+       return 0;
+}
+
+void *
+memfind(const void *s, int c, size_t n)
+{
+       const void *ends = (const char *) s + n;
+       for (; s < ends; s++)
+               if (*(const unsigned char *) s == (unsigned char) c)
+                       break;
+       return (void *) s;
+}
+
+long
+strtol(const char *s, char **endptr, int base)
+{
+       int neg = 0;
+       long val = 0;
+
+       // gobble initial whitespace
+       while (*s == ' ' || *s == '\t')
+               s++;
+
+       // plus/minus sign
+       if (*s == '+')
+               s++;
+       else if (*s == '-')
+               s++, neg = 1;
+
+       // hex or octal base prefix
+       if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x'))
+               s += 2, base = 16;
+       else if (base == 0 && s[0] == '0')
+               s++, base = 8;
+       else if (base == 0)
+               base = 10;
+
+       // digits
+       while (1) {
+               int dig;
+
+               if (*s >= '0' && *s <= '9')
+                       dig = *s - '0';
+               else if (*s >= 'a' && *s <= 'z')
+                       dig = *s - 'a' + 10;
+               else if (*s >= 'A' && *s <= 'Z')
+                       dig = *s - 'A' + 10;
+               else
+                       break;
+               if (dig >= base)
+                       break;
+               s++, val = (val * base) + dig;
+               // we don't properly detect overflow!
+       }
+
+       if (endptr)
+               *endptr = (char *) s;
+       return (neg ? -val : val);
+}
+
index 5f99bdf..bec0ade 100644 (file)
@@ -3,18 +3,16 @@
 #pragma nodeputy
 #endif
 
-#include <inc/x86.h>
-#include <inc/error.h>
-#include <inc/string.h>
-#include <inc/assert.h>
-
-#include <kern/env.h>
-#include <kern/pmap.h>
-#include <kern/trap.h>
-#include <kern/syscall.h>
-#include <kern/console.h>
-#include <kern/apic.h>
-
+#include <arch/x86.h>
+#include <arch/console.h>
+#include <arch/apic.h>
+#include <error.h>
+#include <string.h>
+#include <assert.h>
+#include <env.h>
+#include <pmap.h>
+#include <trap.h>
+#include <syscall.h>
 
 void syscall_wrapper(struct Trapframe *tf)
 {
index 7cda479..3ae3208 100644 (file)
@@ -2,17 +2,16 @@
 #pragma nodeputy
 #endif
 
-#include <inc/mmu.h>
-#include <inc/x86.h>
-#include <inc/stdio.h>
-#include <inc/assert.h>
-#include <inc/string.h>
-
-#include <kern/testing.h>
-#include <kern/trap.h>
-#include <kern/apic.h>
-#include <kern/atomic.h>
-#include <kern/smp.h>
+#include <arch/mmu.h>
+#include <arch/x86.h>
+#include <arch/smp.h>
+#include <arch/apic.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <testing.h>
+#include <trap.h>
+#include <atomic.h>
 
 #define test_vector 0xeb
 
diff --git a/kern/src/timer.c b/kern/src/timer.c
new file mode 100644 (file)
index 0000000..9c3f323
--- /dev/null
@@ -0,0 +1,66 @@
+#include <arch/x86.h>
+#include <arch/timer.h>
+
+/* timing_overhead
+ * Any user space process that links to this file will get its own copy.  
+ * This means it will manually have to call tune_timing itself before it 
+ * makes its first measurement.
+ */
+uint64_t timing_overhead = 0;
+
+/* start_timing()
+ * This function simply reads the tsc in a serialized fashion and returns its
+ * 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))
+{
+    return read_tsc_serialized();
+}
+
+/* stop_timing()
+ * This function reads the tsc in a serialized fashion and subtracts the value
+ * it reads from the value passed in as a paramter in order to determine the 
+ * difference between the two values.  A global timing_overhead value is also 
+ * subtracted to compensate for the overhead associated with calling both
+ * start and stop timing and returning their values.
+ * 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))
+{
+    return (read_tsc_serialized() - val - timing_overhead);
+}
+
+/* train_timing()
+ * This function is intended to train the timing_overhead variable for use by
+ * stop_timing().  It runs through a loop calling start/stop and averaging the 
+ * overhead of calling them without doing any useful work in between.
+ */
+void train_timing() 
+{
+       int i;
+       register uint64_t cum_overhead = 0;
+       register uint64_t time, diff;
+
+       //Do this 3 times outside the loop to warm up cpuid
+       time = start_timing();
+       diff = stop_timing(time);
+       time = start_timing();
+       diff = stop_timing(time);
+       time = start_timing();
+       diff = stop_timing(time);
+
+       for(i=0; i<10000; i++) {
+               time = start_timing();
+               diff = stop_timing(time);
+               
+               /* In case diff was negative, I want to add its absolute value
+                * to the cumulative error, otherwise, just diff itself
+                */
+               if((int64_t)diff < 0)
+                       diff = (uint64_t)(~0) - diff + 1; 
+               cum_overhead += diff;
+       }
+       timing_overhead = (cum_overhead/i);
+}
index 8186c8d..de62fcf 100644 (file)
@@ -2,18 +2,18 @@
 #pragma noasync
 #endif
 
-#include <inc/mmu.h>
-#include <inc/x86.h>
-#include <inc/assert.h>
-
-#include <kern/pmap.h>
-#include <kern/trap.h>
-#include <kern/console.h>
-#include <kern/monitor.h>
-#include <kern/env.h>
-#include <kern/syscall.h>
-#include <kern/apic.h>
-#include <kern/smp.h>
+#include <arch/mmu.h>
+#include <arch/x86.h>
+#include <arch/console.h>
+#include <arch/apic.h>
+#include <arch/smp.h>
+#include <assert.h>
+#include <pmap.h>
+#include <trap.h>
+#include <monitor.h>
+#include <env.h>
+
+#include <syscall.h>
 
 taskstate_t ts;
 
index ffefb58..8834166 100644 (file)
@@ -1,8 +1,8 @@
 /* See COPYRIGHT for copyright information. */
 
-#include <inc/mmu.h>
-#include <inc/memlayout.h>
-#include <inc/trap.h>
+#include <arch/mmu.h>
+#include <ros/trap.h>
+#include <ros/memlayout.h>
 
 
 
diff --git a/kern/syscall.h b/kern/syscall.h
deleted file mode 100644 (file)
index 68f237f..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef ROS_KERN_SYSCALL_H
-#define ROS_KERN_SYSCALL_H
-#ifndef ROS_KERNEL
-# error "This is ROS kernel header; user programs should not #include it"
-#endif
-
-#include <inc/syscall.h>
-#include <inc/env.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);
-uint32_t process_generic_syscalls(env_t* e, uint32_t max);
-void syscall_wrapper(struct Trapframe *tf);
-#endif /* !ROS_KERN_SYSCALL_H */
diff --git a/kern/testing.h b/kern/testing.h
deleted file mode 100644 (file)
index bc4407b..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef ROS_INC_TESTING_H
-#define ROS_INC_TESTING_H
-
-/* This is just a dumping ground for old code used for testing.
- * Someone should go through old commits and bring back other relevant tests.
- * Someone else should actually make these useful on their own
- */
-
-#include <inc/types.h>
-
-#include <kern/trap.h>
-
-void test_ipi_sending(void);
-void test_pic_reception(void);
-void test_print_info(void);
-void test_barrier(void);
-void test_interrupts_irqsave(void);
-void test_bitmasks(void);
-void test_checklists(void);
-void test_pit(void);
-void test_smp_call_functions(void);
-void test_lapic_status_bit(void);
-
-void test_hello_world_handler(trapframe_t *tf, void* data);
-void test_print_info_handler(trapframe_t *tf, void* data);
-void test_barrier_handler(trapframe_t *tf, void* data);
-
-#endif /* !ROS_INC_TESTING_H */
diff --git a/kern/trap.h b/kern/trap.h
deleted file mode 100644 (file)
index 0d68a5b..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* See COPYRIGHT for copyright information. */
-
-#ifndef ROS_KERN_TRAP_H
-#define ROS_KERN_TRAP_H
-#ifndef ROS_KERNEL
-# error "This is an ROS kernel header; user programs should not #include it"
-#endif
-
-#define MSR_IA32_SYSENTER_CS 0x174
-#define MSR_IA32_SYSENTER_ESP 0x175
-#define MSR_IA32_SYSENTER_EIP 0x176
-
-#include <inc/trap.h>
-#include <inc/mmu.h>
-
-// func ptr for interrupt service routines
-typedef void (*isr_t)(trapframe_t* tf, void* data);
-typedef struct InterruptHandler {
-       isr_t isr;
-       void* data;
-} handler_t;
-
-/* The kernel's interrupt descriptor table */
-extern gatedesc_t idt[];
-extern taskstate_t ts;
-
-void idt_init(void);
-void register_interrupt_handler(handler_t (COUNT(256)table)[], uint8_t int_num,
-                                isr_t handler, void* data);
-void (IN_HANDLER print_regs)(push_regs_t *regs);
-void (IN_HANDLER print_trapframe)(trapframe_t *tf);
-void (IN_HANDLER page_fault_handler)(trapframe_t *tf);
-void backtrace(trapframe_t *tf);
-
-void sysenter_init(void);
-extern void sysenter_handler();
-#endif /* ROS_KERN_TRAP_H */
index 273273e..4e6cf2f 100644 (file)
@@ -1,4 +1,15 @@
 USER_DIR = user
+
+USER_CFLAGS  := $(CFLAGS) -DROS_USER
+USER_LDFLAGS :=
+
+# This is defined here because it is need by both
+# roslib and parlib for compiling, but not by apps
+USER_ROSLIB_INCLUDE_DIR  := $(USER_DIR)/roslib/inc
+
+# This is defined here for use by the parlib library
+USER_NEWLIB_DIR := $(USER_DIR)/newlib
+
+include $(USER_DIR)/roslib/Makefrag
 include $(USER_DIR)/parlib/Makefrag
-include $(USER_DIR)/newlib/Makefrag
 include $(USER_DIR)/apps/Makefrag
index ac3e1b2..a064700 100644 (file)
@@ -1,3 +1,7 @@
 USER_APPS_DIR = $(USER_DIR)/apps
+
+include $(USER_APPS_DIR)/roslib/Makefrag
 include $(USER_APPS_DIR)/parlib/Makefrag
-include $(USER_APPS_DIR)/newlib/Makefrag
+
+.PRECIOUS: $(OBJDIR)/$(USER_APPS_DIR)/roslib/%.o \
+           $(OBJDIR)/$(USER_APPS_DIR)/parlib/%.o
diff --git a/user/apps/newlib/Makefrag b/user/apps/newlib/Makefrag
deleted file mode 100644 (file)
index 37e9623..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-USER_APPS_NEWLIB_DIR = $(USER_APPS_DIR)/newlib
-OBJDIRS += $(USER_APPS_NEWLIB_DIR)
-
-USER_APPS_NEWLIB_CFLAGS    := $(USER_CFLAGS) -I$(USER_NEWLIB_DIR)/include
-USER_APPS_NEWLIB_LDFLAGS   := $(USER_LDFLAGS) -static \
-                              -T $(USER_APPS_NEWLIB_DIR)/apps.ld
-USER_APPS_NEWLIB_LDDIRS    := -L$(OBJDIR)/$(USER_PARLIB_DIR) \
-                              -L$(USER_NEWLIB_DIR)/lib \
-                              -L$(OBJDIR)/$(USER_NEWLIB_DIR)
-USER_APPS_NEWLIB_LDLIBS    := -lc -lc_wrappers -lparlib
-USER_APPS_NEWLIB_LDOBJS    := $(OBJDIR)/$(USER_PARLIB_DIR)/entry.o \
-                              $(OBJDIR)/$(USER_PARLIB_DIR)/libmain.o
-USER_APPS_NEWLIB_LDDEPENDS := $(USER_APPS_NEWLIB_LDOBJS) \
-                              $(OBJDIR)/$(USER_PARLIB_DIR)/libparlib.a \
-                              $(OBJDIR)/$(USER_NEWLIB_DIR)/libc_wrappers.a \
-                              $(OBJDIR)/$(USER_APPS_NEWLIB_DIR)/%.o       
-USER_APPS_NEWLIB_GCC_LIB   := $(GCC_LIB)
-
-$(OBJDIR)/$(USER_APPS_NEWLIB_DIR)/%.o: $(USER_APPS_NEWLIB_DIR)/%.c
-       @echo + cc [APPS NEWLIB] $<
-       @mkdir -p $(@D)
-       $(V)$(CC) $(USER_APPS_NEWLIB_CFLAGS) -c -o $@ $<
-
-$(OBJDIR)/$(USER_APPS_NEWLIB_DIR)/%: $(USER_APPS_NEWLIB_LDDEPENDS)
-       @echo + ld [APPS NEWLIB] $@
-       $(V)$(LD) -o $@ $(USER_APPS_NEWLIB_LDFLAGS) $@.o \
-                    $(USER_APPS_NEWLIB_LDOBJS) $(USER_APPS_NEWLIB_LDDIRS) \
-                    $(USER_APPS_NEWLIB_LDLIBS) $(USER_APPS_NEWLIB_GCC_LIB)
-       $(V)$(OBJDUMP) -S $@ > $@.asm
-       $(V)$(NM) -n $@ > $@.sym
-
diff --git a/user/apps/newlib/apps.ld b/user/apps/newlib/apps.ld
deleted file mode 100644 (file)
index 3f64202..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* Simple linker script for ROS user-level programs.
-   See the GNU ld 'info' manual ("info ld") to learn the syntax. */
-
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH(i386)
-ENTRY(_start)
-
-SECTIONS
-{
-       /* Load programs at this address: "." means the current address */
-       . = 0x800020;
-
-       .text : {
-               *(.text .stub .text.* .gnu.linkonce.t.*)
-       }
-
-       PROVIDE(_etext = .);    /* Define the 'etext' symbol to this value */
-
-       .rodata : {
-               *(.rodata .rodata.* .gnu.linkonce.r.*)
-       }
-
-       /* Adjust the address for the data segment to the next page */
-       . = ALIGN(0x1000);
-
-       .data : {
-               *(.data)
-       }
-
-       PROVIDE(_edata = .);
-
-       .bss : {
-               *(.bss)
-       }
-
-       PROVIDE(_end = .);
-
-
-       /* Place debugging symbols so that they can be found by
-        * the kernel debugger.
-        * Specifically, the four words at 0x200000 mark the beginning of
-        * the stabs, the end of the stabs, the beginning of the stabs
-        * string table, and the end of the stabs string table, respectively.
-        */
-
-       .stab_info 0x200000 : {
-               LONG(__STAB_BEGIN__);
-               LONG(__STAB_END__);
-               LONG(__STABSTR_BEGIN__);
-               LONG(__STABSTR_END__);
-       }
-
-       .stab : {
-               __STAB_BEGIN__ = DEFINED(__STAB_BEGIN__) ? __STAB_BEGIN__ : .;
-               *(.stab);
-               __STAB_END__ = DEFINED(__STAB_END__) ? __STAB_END__ : .;
-               BYTE(0)         /* Force the linker to allocate space
-                                  for this section */
-       }
-
-       .stabstr : {
-               __STABSTR_BEGIN__ = DEFINED(__STABSTR_BEGIN__) ? __STABSTR_BEGIN__ : .;
-               *(.stabstr);
-               __STABSTR_END__ = DEFINED(__STABSTR_END__) ? __STABSTR_END__ : .;
-               BYTE(0)         /* Force the linker to allocate space
-                                  for this section */
-       }
-
-       /DISCARD/ : {
-               *(.eh_frame .note.GNU-stack)
-       }
-}
diff --git a/user/apps/newlib/hello.c b/user/apps/newlib/hello.c
deleted file mode 100644 (file)
index db008b1..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-
-int main(int argc, char** argv)
-{
-       printf("Hello world from newlib!!\n");
-       return 0;
-}
diff --git a/user/apps/newlib/null.c b/user/apps/newlib/null.c
deleted file mode 100644 (file)
index 64f1885..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <stdlib.h>
-
-int main(int argc, char** argv)
-{
-       return 0;
-}
index 6008575..3481438 100644 (file)
@@ -1,17 +1,25 @@
 USER_APPS_PARLIB_DIR = $(USER_APPS_DIR)/parlib
 OBJDIRS += $(USER_APPS_PARLIB_DIR)
 
-USER_APPS_PARLIB_CFLAGS    := $(USER_CFLAGS) -nostdinc \
-                              -I$(USER_PARLIB_DIR)
-USER_APPS_PARLIB_LDFLAGS   := $(USER_LDFLAGS) -nostdlib -static \
+USER_APPS_PARLIB_CFLAGS    := $(USER_CFLAGS) \
+                              -I$(USER_NEWLIB_DIR)/include
+
+USER_APPS_PARLIB_LDFLAGS   := $(USER_LDFLAGS) -static \
                               -T $(USER_APPS_PARLIB_DIR)/apps.ld
-USER_APPS_PARLIB_LDDIRS    := -L$(OBJDIR)/$(USER_PARLIB_DIR)
-USER_APPS_PARLIB_LDLIBS    := -lparlib -livyparlib 
-USER_APPS_PARLIB_LDOBJS    := $(OBJDIR)/$(USER_PARLIB_DIR)/libivyparlib.a \
-                              $(OBJDIR)/$(USER_PARLIB_DIR)/entry.o       
+
+USER_APPS_PARLIB_LDDIRS    := -L$(OBJDIR)/$(USER_PARLIB_DIR) \
+                              -L$(OBJDIR)/$(USER_ROSLIB_DIR) \
+                              -L$(USER_NEWLIB_DIR)/lib
+
+USER_APPS_PARLIB_LDLIBS    := -lc -lm -lg -lparlib -lroslib
+
+USER_APPS_PARLIB_LDOBJS    := $(OBJDIR)/$(USER_ROSLIB_DIR)/entry.o \
+                              $(OBJDIR)/$(USER_ROSLIB_DIR)/libmain.o
+
 USER_APPS_PARLIB_LDDEPENDS := $(USER_APPS_PARLIB_LDOBJS) \
                               $(OBJDIR)/$(USER_PARLIB_DIR)/libparlib.a \
                               $(OBJDIR)/$(USER_APPS_PARLIB_DIR)/%.o       
+
 USER_APPS_PARLIB_GCC_LIB   := $(GCC_LIB)
 
 $(OBJDIR)/$(USER_APPS_PARLIB_DIR)/%.o: $(USER_APPS_PARLIB_DIR)/%.c
@@ -19,7 +27,7 @@ $(OBJDIR)/$(USER_APPS_PARLIB_DIR)/%.o: $(USER_APPS_PARLIB_DIR)/%.c
        @mkdir -p $(@D)
        $(V)$(CC) $(USER_APPS_PARLIB_CFLAGS) -c -o $@ $<
 
-$(OBJDIR)/$(USER_APPS_PARLIB_DIR)/%: $(USER_APPS_PARLIB_LDDEPENDS)         
+$(OBJDIR)/$(USER_APPS_PARLIB_DIR)/%: $(USER_APPS_PARLIB_LDDEPENDS)
        @echo + ld [APPS PARLIB] $@
        $(V)$(LD) -o $@ $(USER_APPS_PARLIB_LDFLAGS) $@.o \
                     $(USER_APPS_PARLIB_LDOBJS) $(USER_APPS_PARLIB_LDDIRS) \
index e4e96b4..3f64202 100644 (file)
@@ -14,7 +14,7 @@ SECTIONS
                *(.text .stub .text.* .gnu.linkonce.t.*)
        }
 
-       PROVIDE(etext = .);     /* Define the 'etext' symbol to this value */
+       PROVIDE(_etext = .);    /* Define the 'etext' symbol to this value */
 
        .rodata : {
                *(.rodata .rodata.* .gnu.linkonce.r.*)
@@ -27,13 +27,13 @@ SECTIONS
                *(.data)
        }
 
-       PROVIDE(edata = .);
+       PROVIDE(_edata = .);
 
        .bss : {
                *(.bss)
        }
 
-       PROVIDE(end = .);
+       PROVIDE(_end = .);
 
 
        /* Place debugging symbols so that they can be found by
diff --git a/user/apps/parlib/badsegment.c b/user/apps/parlib/badsegment.c
deleted file mode 100644 (file)
index 78bc5f7..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// program to cause a general protection exception
-
-#include <inc/lib.h>
-
-int main(int argc, char** argv)
-{
-       // Try to load the kernel's TSS selector into the DS register.
-       //asm volatile("movw $28,%ax; movw %ax,%ds");
-  
-       // DP: 0x28 == 40
-       asm volatile("movw $40,%ax; movw %ax,%ds");
-       return 0;
-}
-
diff --git a/user/apps/parlib/breakpoint.c b/user/apps/parlib/breakpoint.c
deleted file mode 100644 (file)
index d43a19a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// program to cause a breakpoint trap
-
-#include <inc/lib.h>
-
-int main(int argc, char** argv)
-{
-       asm volatile("int $3");
-       return 0;
-}
-
diff --git a/user/apps/parlib/buggyhello.c b/user/apps/parlib/buggyhello.c
deleted file mode 100644 (file)
index dc1b82a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// buggy hello world -- unmapped pointer passed to kernel
-// kernel should destroy user environment in response
-
-#include <inc/lib.h>
-
-int main(int argc, char** argv)
-{
-       sys_cputs((char*SAFE)TC(1), 1);
-       return 0;
-}
-
diff --git a/user/apps/parlib/divzero.c b/user/apps/parlib/divzero.c
deleted file mode 100644 (file)
index 7e18661..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-// buggy program - causes a divide by zero exception
-
-#include <inc/lib.h>
-
-int zero;
-
-int main(int argc, char** argv)
-{
-       cprintf("1/0 is %08x!\n", 1/zero);
-       return 0;
-}
-
diff --git a/user/apps/parlib/evilhello.c b/user/apps/parlib/evilhello.c
deleted file mode 100644 (file)
index 19b30aa..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// evil hello world -- kernel pointer passed to kernel
-// kernel should destroy user environment in response
-
-#include <inc/lib.h>
-
-int main(int argc, char** argv)
-{
-       while(1);
-       // try to print the kernel entry point as a string!  mua ha ha!
-       sys_cputs((char*SAFE)TC(0xc0100020), 100);
-       return 0;
-}
-
diff --git a/user/apps/parlib/faultread.c b/user/apps/parlib/faultread.c
deleted file mode 100644 (file)
index e24f894..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// buggy program - faults with a read from location zero
-
-#include <inc/lib.h>
-
-int main(int argc, char** argv)
-{ TRUSTEDBLOCK
-       cprintf("I read %08x from location 0!\n", *(unsigned*)0);
-       return 0;
-}
-
diff --git a/user/apps/parlib/faultreadkernel.c b/user/apps/parlib/faultreadkernel.c
deleted file mode 100644 (file)
index 9aa3d06..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// buggy program - faults with a read from kernel space
-
-#include <inc/lib.h>
-
-int main(int argc, char** argv)
-{ TRUSTEDBLOCK
-       cprintf("I read %08x from location 0xf0100000!\n", *(unsigned*)0xf0100000);
-       return 0;
-}
-
diff --git a/user/apps/parlib/faultwrite.c b/user/apps/parlib/faultwrite.c
deleted file mode 100644 (file)
index d129245..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// buggy program - faults with a write to location zero
-
-#include <inc/lib.h>
-
-int main(int argc, char** argv)
-{ TRUSTEDBLOCK
-       *(unsigned*)0 = 0;
-       return 0;
-}
-
diff --git a/user/apps/parlib/faultwritekernel.c b/user/apps/parlib/faultwritekernel.c
deleted file mode 100644 (file)
index ddeafb8..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// buggy program - faults with a write to a kernel location
-
-#include <inc/lib.h>
-
-int main(int argc, char** argv)
-{ TRUSTEDBLOCK
-       *(unsigned*)0xf0100000 = 0;
-       return 0;
-}
-
index 17ca534..db008b1 100644 (file)
@@ -1,8 +1,8 @@
-#include <inc/lib.h>
-
+#include <stdlib.h>
+#include <stdio.h>
 
 int main(int argc, char** argv)
 {
-       cprintf("goodbye, world!\n");
+       printf("Hello world from newlib!!\n");
        return 0;
 }
diff --git a/user/apps/parlib/measurements.c b/user/apps/parlib/measurements.c
deleted file mode 100644 (file)
index 100b86d..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// null app
-#include <inc/lib.h>
-#include <inc/types.h>
-#include <inc/syscall.h>
-#include <inc/x86.h>
-#include <inc/measure.h>
-#include <inc/null.h>
-#include <inc/timer.h>
-
-#ifdef __DEPUTY__
-#pragma nodeputy
-#endif
-
-#define NUM_ITERATIONS 100000
-uint64_t times[NUM_ITERATIONS];
-
-uint64_t total(uint64_t (COUNT(length) array)[], int length)
-{
-       uint64_t sum = 0;
-       for(int i=0; i<length; i++) {
-               sum+=array[i];
-       }
-       return sum;
-       //return (length > 0) ? sum/((uint64_t)length) : 0;
-}
-
-int main(int argc, char** argv)
-{
-       TAGGED_TIMING_BEGIN(tst);
-       async_desc_t *desc1, *desc2;
-       async_rsp_t rsp1, rsp2;
-       cache_buster_async(&desc1, 20, 0xdeadbeef);
-       cache_buster_async(&desc2, 10, 0xcafebabe);
-       waiton_async_call(desc1, &rsp1);
-       waiton_async_call(desc2, &rsp2);
-       //measure_function(sys_null(), NUM_ITERATIONS, "sys_null");
-       //measure_function(asm volatile("nop;"), NUM_ITERATIONS, "nop");
-       //measure_function(cprintf("Reg Sync call  \n"), 10, "printf");
-       //measure_function_async(cprintf_async(&desc, "Cross-Core call\n"), desc, 10,\
-       //                       1, "Async Printf");
-       // Note this won't actually do 100 inner runs (first parameter).  will stop
-       // making calls beyond the ring size and won't wait on any extra calls.
-       measure_async_call(null_async(&desc), desc, 100, 100, "Async Null");
-       
-    TAGGED_TIMING_END(tst);
-       // Spin to make sure we don't have any resources deallocated before done
-       while(1);
-       return 0;
-}
index 190276e..64f1885 100644 (file)
@@ -1,4 +1,4 @@
-#include <lib.h>
+#include <stdlib.h>
 
 int main(int argc, char** argv)
 {
diff --git a/user/apps/parlib/print_tests.c b/user/apps/parlib/print_tests.c
deleted file mode 100644 (file)
index 80e6411..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <inc/lib.h>
-
-#ifdef __DEPUTY__
-#pragma nodeputy
-#endif
-
-int main(int argc, char** argv)
-{
-       cprintf("goodbye, world!\n");
-       cprintf("i am environment %08x\n", env->env_id);
-
-       cprintf("about to write to shared mem.  hope it gets printed.  blimey! \n");
-       async_desc_t *desc1, *desc2, *desc3;
-       async_rsp_t rsp1, rsp2, rsp3;
-       cprintf_async(&desc1, "Cross-Core call 1, coming from env %08x\n", env->env_id);
-       cprintf("Call 1 is sent!\n");
-       //cprintf_async(&desc2, "Cross-Core call 2, coming from env %08x\n", env->env_id);
-       cprintf_async(&desc2, "1111111111111111111111111111111122222222222222222222222222222222333333333333333333333333333333334444444444444444444444444444444455555555555555555555555555555555666666666666666666666666666666667777777777777777777777777777777788888888888888888888888888888888Cross-Core call 2, coming from env %08x\n", env->env_id);
-       cprintf("Call 2 is sent!\n");
-       cprintf("Waiting on Call 1 and 2\n");
-       waiton_async_call(desc1, &rsp1);
-       cprintf("Received 1\n");
-       waiton_async_call(desc2, &rsp2);
-       cprintf_async(&desc3, "Cross-Core call 3, coming from env %08x\n", env->env_id);
-       cprintf("Call 3 is sent!\n");
-       waiton_async_call(desc3, &rsp3);
-       // might as well spin, just to make sure nothing gets deallocated
-       // while we're waiting to test the async call
-       while (1);
-       return 0;
-}
diff --git a/user/apps/parlib/softint.c b/user/apps/parlib/softint.c
deleted file mode 100644 (file)
index d13cb79..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// buggy program - causes an illegal software interrupt
-
-#include <inc/lib.h>
-
-int main(int argc, char** argv)
-{
-       // this is a fake page fault.  it can only be used if the DPL is 3
-       // if the DPL = 0, this causes a general prot fault, not a PF
-       asm volatile("int $14");
-
-       // this is a real page fault.  volatile, so the compiler doesn't remove it
-       // this will cause a PF regardless of DPL, since it's a real PF.
-       //volatile int x = *((int*)0xc0000000);
-       return 0;
-}
-
diff --git a/user/apps/parlib/testbss.c b/user/apps/parlib/testbss.c
deleted file mode 100644 (file)
index f38d584..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// test reads and writes to a large bss
-
-#include <inc/lib.h>
-
-#define ARRAYSIZE (1024*1024)
-
-uint32_t bigarray[ARRAYSIZE];
-
-int main(int argc, char** argv)
-{
-       int i;
-
-       cprintf("Making sure bss works right...\n");
-       for (i = 0; i < ARRAYSIZE; i++)
-               if (bigarray[i] != 0)
-                       panic("bigarray[%d] isn't cleared!\n", i);
-       for (i = 0; i < ARRAYSIZE; i++)
-               bigarray[i] = i;
-       for (i = 0; i < ARRAYSIZE; i++)
-               if (bigarray[i] != i)
-                       panic("bigarray[%d] didn't hold its value!\n", i);
-
-       cprintf("Yes, good.  Now doing a wild write off the end...\n");
-       { TRUSTEDBLOCK
-       bigarray[ARRAYSIZE+1024] = 0;
-       }
-       panic("SHOULD HAVE TRAPPED!!!");
-       return 0;
-}
diff --git a/user/apps/parlib/testpmap.c b/user/apps/parlib/testpmap.c
deleted file mode 100644 (file)
index 0a9ecde..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-//#ifdef LAB >= 4
-
-#include <inc/lib.h>
-
-int sequence_length = 16;
-int sequence[] = { 0,  1,   1,   2,   3, 
-                  5,  8,  13,  21,  34, 
-                 55, 89, 144, 233, 377, 610};
-
-void
-mark_page(int* pg, int i) {
-  memset(pg, 0, PGSIZE);
-
-  // now dump a non-random sequence into the page
-  // offset by i
-  int j;
-  for (j = 0; j < sequence_length; j++)
-    pg[j] = i + sequence[j];
-}
-
-int
-test_page(int* pg, int i) {
-  int j;
-  for (j = 0; j < sequence_length; j++)
-    if (pg[j] != i + sequence[j])
-      return 1;
-
-  return 0;
-}
-
-void
-print_marked_page(int* pg) {
-  int j;
-  for (j = 0; j < (sequence_length-1); j++)
-    cprintf("%d, ", pg[j]);
-
-  cprintf("%d", pg[j]);
-}
-
-void
-print_expected_mark(int i) {
-  int j;
-  for (j = 0; j < (sequence_length-1); j++)
-    cprintf("%d, ", sequence[j]+i);
-  
-  cprintf("%d", sequence[j]+i);
-}
-
-int n, va, r, initva, maxpa, maxva, maxnum, failures;
-int *page_id;
-
-int
-alloc_range(int initaddr, int maxpa, int startn) {
-  n = startn;
-  maxnum = maxpa / PGSIZE;
-  initva = initaddr;
-  maxva = initva + maxpa;
-  
-  cprintf ("[%08x] trying to alloc pages in range [%08x, %08x]\n", env->env_id, initva, maxva);
-
-  // how many pages can I alloc? 
-  // - limit to 256 M worth of pages
-  for (va = initva; va < maxva; va += PGSIZE, n++) { 
-    // alloc a page 
-    if ((r = sys_mem_alloc(0, va, PTE_P | PTE_U | PTE_W | PTE_AVAIL)) < 0) { 
-      //cprintf("\nsys_mem_alloc failed: %e", r);
-      break;
-    }
-
-    //page_id = (int*)va;
-    //*page_id = n;              // mark this page...
-    //memset((int*)va, n, PGSIZE / sizeof(int));
-    mark_page((int*)va, n);
-
-    if ( (((va - initva) / PGSIZE) % 128) == 0) cprintf(".");
-  }
-  cprintf("\n");
-
-  cprintf("[%08x] able to allocate [%d] pages of requested [%d] pages\n", env->env_id, n, maxnum);
-
-  maxva = va;
-  return n;
-}
-
-int
-test_range(int startva, int endva, int startn) {
-  int c;
-  cprintf("[%08x] testing pages in [%08x, %08x] to see if they look okay\n", env->env_id, startva, endva);
-  n = startn;
-  failures = 0;  
-  for (va = startva, c = 0; va < endva; va += PGSIZE, n++, c++) { 
-    page_id = (int*)va;
-
-    if (test_page((int*)va, n)) {
-      cprintf("\n[%08x] unexpected value at [%08x]:\n  {", env->env_id, va);
-      print_marked_page((int*)va);
-      cprintf("} should be\n  {");
-      print_expected_mark(n);
-      cprintf("}");
-      
-      failures++;
-    } else {
-      Pte pte = vpt[VPN(va)];
-      int perm = (PTE_U | PTE_P | PTE_W | PTE_AVAIL);
-
-      if ((pte & perm) != perm) {
-       cprintf("\n[%08x] unexpected PTE permissions [04x] for address [%08x]\n {", env->env_id, pte & perm, va);
-       failures++;
-      }
-
-      //      cprintf("\n value at [%08x]: {", va);
-      //print_marked_page((int*)va);
-      //cprintf("} should be {");
-      //print_expected_mark(n);
-      //cprintf("}");
-    }
-
-    if ( (((va - startva) / PGSIZE) % 128) == 0) cprintf(".");
-    //if ((va % PDMAP) == 0) cprintf(".");
-  }
-  cprintf("\n");
-
-  cprintf("[%08x] tested %d pages: %d failed assertions.\n", env->env_id, c, failures);
-
-  return failures;
-}
-
-void
-unmap_range(int startva, int endva) {
-  cprintf("[%08x] unmapping range [%08x, %08x].\n", env->env_id, startva, endva);
-  int xva, z;
-  for (z=0, xva = startva; xva < endva; xva += PGSIZE, z++) { 
-    sys_mem_unmap(0, xva);
-  }
-  cprintf("[%08x] unmapped %d pages.\n", env->env_id, z);
-}
-
-int
-duplicate_range(int startva, int dupeva, int nbytes) {
-  cprintf("[%08x] duplicating range [%08x, %08x] at [%08x, %08x]\n", 
-        env->env_id, startva, startva+nbytes, dupeva, dupeva+nbytes);
-  int xva, r, k;
-  for (xva = 0, k = 0; xva < nbytes; xva += PGSIZE, k+=PGSIZE) { 
-    if ((r = sys_mem_map(0, startva+xva, 0, dupeva+xva, PTE_P | PTE_U | PTE_W | PTE_USER)) < 0) {
-      cprintf ("[%08x] duplicate_range FAILURE: %e\n", env->env_id, r);
-      return r;
-    }
-  }
-
-  return k;
-}
-
-// This tries to stress test the pmap code...
-// Not the most intelligent testing strategy, 
-// just hammer at it and see if it breaks.
-int main(int argc, char** argv)
-{  
-  int max, max2, k, j, i, dupesize, dupen;
-
-  for (i = 0; i < 2; i++) { // might as well do this multiple times to stress the system...
-    cprintf("PMAPTEST[%08x] starting ROUND %d.\n", env->env_id, i);
-
-    // Try to allocate as many pages as possible...
-    k = alloc_range(UTEXT+PDMAP, (256 * 1024 * 1024), 0);       // alloc as many as possible
-    max = maxva;                                                // save maximum memory size
-    test_range(UTEXT+PDMAP, max, 0);                            // test if all are unique pages
-
-    // If we've corrupted kernel memory, a yield might expose a problem.
-    cprintf("PMAPTEST[%08x] yielding...\n", env->env_id);
-    sys_yield();
-    cprintf("PMAPTEST[%08x] back.\n", env->env_id);
-
-    // Free a couple of pages for use by page tables and other envs...
-    unmap_range(max-16 * PGSIZE, max);                           // free some pages so we have wiggle room, if extra
-    max -= 16 * PGSIZE;                                          // pages are needed for page tables...
-    
-    // Unmap last 1024 pages and then try to reallocate them in the same place
-    unmap_range(max - PDMAP, max);                              // unmap last 1024 pages
-    j = alloc_range(max - PDMAP, PDMAP, 0);                     // try to realloc them (<1024 if other envs alloc'd)
-    max2 = maxva; // max2 <= max && max2 >= (max - PDMAP)
-    test_range(max - PDMAP, max2, 0);                           // test if new pages are unique
-  
-    // Create duplicate mappings of the last 1024
-    dupesize = duplicate_range(max2-PDMAP, max+PDMAP, j*PGSIZE); // create duplicate mappings
-    test_range(max2-PDMAP, max2-PDMAP+dupesize, 0);             // test lower mapping
-    test_range(max+PDMAP, max + PDMAP + dupesize, 0);           // test upper mapping
-    dupen = *((int*)(max+PDMAP));
-  
-    // Remove one of the duplicate mappings and then unmap and realloc the last 1024 pages
-    unmap_range(max2-PDMAP, max2-PDMAP+dupesize);           // unmap lower mapping
-    j = alloc_range(max2-PDMAP, PDMAP, 0);                  // try to alloc something, should be below 1024 (really? other envs?)
-    unmap_range(max2-2*PDMAP, max2 - PDMAP);                // free 1024 pages
-    j = alloc_range(max2-2*PDMAP, PDMAP, 0);                // alloc new pages for free'd 1024
-    //max2 = maxva; // max2 <= old_max2 - PDMAP
-    
-    // Test ranges...
-    test_range(UTEXT+PDMAP, max2-2*PDMAP, 0);              // test entire lower range of pages
-    test_range(max2-2*PDMAP, maxva, 0);                    // test entire lower range of pages
-    test_range(max+PDMAP, max + PDMAP + dupesize, dupen);  // test upper range
-
-    // Free everything
-    unmap_range(UTEXT+PDMAP, maxva);                        
-    unmap_range(max+PDMAP, max+PDMAP+dupesize);    
-    
-    //unmap_range(UTEXT+PDMAP, max);
-  }
-  return 0;
-}
-
-//#endif
-
-
-
-
diff --git a/user/apps/roslib/Makefrag b/user/apps/roslib/Makefrag
new file mode 100644 (file)
index 0000000..4a9477b
--- /dev/null
@@ -0,0 +1,30 @@
+USER_APPS_ROSLIB_DIR = $(USER_APPS_DIR)/roslib
+OBJDIRS += $(USER_APPS_ROSLIB_DIR)
+
+USER_APPS_ROSLIB_CFLAGS    := $(USER_CFLAGS) -nostdinc \
+                              -I$(USER_ROSLIB_DIR)/inc \
+                              -I$(USER_ROSLIB_DIR)/inc/arch
+USER_APPS_ROSLIB_LDFLAGS   := $(USER_LDFLAGS) -nostdlib -static \
+                              -T $(USER_APPS_ROSLIB_DIR)/apps.ld
+USER_APPS_ROSLIB_LDDIRS    := -L$(OBJDIR)/$(USER_ROSLIB_DIR)
+USER_APPS_ROSLIB_LDLIBS    := -lroslib -livyroslib 
+USER_APPS_ROSLIB_LDOBJS    := $(OBJDIR)/$(USER_ROSLIB_DIR)/libivyroslib.a \
+                              $(OBJDIR)/$(USER_ROSLIB_DIR)/entry.o       
+USER_APPS_ROSLIB_LDDEPENDS := $(USER_APPS_ROSLIB_LDOBJS) \
+                              $(OBJDIR)/$(USER_ROSLIB_DIR)/libroslib.a \
+                              $(OBJDIR)/$(USER_APPS_ROSLIB_DIR)/%.o       
+USER_APPS_ROSLIB_GCC_LIB   := $(GCC_LIB)
+
+$(OBJDIR)/$(USER_APPS_ROSLIB_DIR)/%.o: $(USER_APPS_ROSLIB_DIR)/%.c
+       @echo + cc [APPS ROSLIB] $<
+       @mkdir -p $(@D)
+       $(V)$(CC) $(USER_APPS_ROSLIB_CFLAGS) -c -o $@ $<
+
+$(OBJDIR)/$(USER_APPS_ROSLIB_DIR)/%: $(USER_APPS_ROSLIB_LDDEPENDS)         
+       @echo + ld [APPS ROSLIB] $@
+       $(V)$(LD) -o $@ $(USER_APPS_ROSLIB_LDFLAGS) $@.o \
+                    $(USER_APPS_ROSLIB_LDOBJS) $(USER_APPS_ROSLIB_LDDIRS) \
+                    $(USER_APPS_ROSLIB_LDLIBS) $(USER_APPS_ROSLIB_GCC_LIB)
+       $(V)$(OBJDUMP) -S $@ > $@.asm
+       $(V)$(NM) -n $@ > $@.sym
+
diff --git a/user/apps/roslib/apps.ld b/user/apps/roslib/apps.ld
new file mode 100644 (file)
index 0000000..e4e96b4
--- /dev/null
@@ -0,0 +1,72 @@
+/* Simple linker script for ROS user-level programs.
+   See the GNU ld 'info' manual ("info ld") to learn the syntax. */
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+SECTIONS
+{
+       /* Load programs at this address: "." means the current address */
+       . = 0x800020;
+
+       .text : {
+               *(.text .stub .text.* .gnu.linkonce.t.*)
+       }
+
+       PROVIDE(etext = .);     /* Define the 'etext' symbol to this value */
+
+       .rodata : {
+               *(.rodata .rodata.* .gnu.linkonce.r.*)
+       }
+
+       /* Adjust the address for the data segment to the next page */
+       . = ALIGN(0x1000);
+
+       .data : {
+               *(.data)
+       }
+
+       PROVIDE(edata = .);
+
+       .bss : {
+               *(.bss)
+       }
+
+       PROVIDE(end = .);
+
+
+       /* Place debugging symbols so that they can be found by
+        * the kernel debugger.
+        * Specifically, the four words at 0x200000 mark the beginning of
+        * the stabs, the end of the stabs, the beginning of the stabs
+        * string table, and the end of the stabs string table, respectively.
+        */
+
+       .stab_info 0x200000 : {
+               LONG(__STAB_BEGIN__);
+               LONG(__STAB_END__);
+               LONG(__STABSTR_BEGIN__);
+               LONG(__STABSTR_END__);
+       }
+
+       .stab : {
+               __STAB_BEGIN__ = DEFINED(__STAB_BEGIN__) ? __STAB_BEGIN__ : .;
+               *(.stab);
+               __STAB_END__ = DEFINED(__STAB_END__) ? __STAB_END__ : .;
+               BYTE(0)         /* Force the linker to allocate space
+                                  for this section */
+       }
+
+       .stabstr : {
+               __STABSTR_BEGIN__ = DEFINED(__STABSTR_BEGIN__) ? __STABSTR_BEGIN__ : .;
+               *(.stabstr);
+               __STABSTR_END__ = DEFINED(__STABSTR_END__) ? __STABSTR_END__ : .;
+               BYTE(0)         /* Force the linker to allocate space
+                                  for this section */
+       }
+
+       /DISCARD/ : {
+               *(.eh_frame .note.GNU-stack)
+       }
+}
diff --git a/user/apps/roslib/badsegment.c b/user/apps/roslib/badsegment.c
new file mode 100644 (file)
index 0000000..78bc5f7
--- /dev/null
@@ -0,0 +1,14 @@
+// program to cause a general protection exception
+
+#include <inc/lib.h>
+
+int main(int argc, char** argv)
+{
+       // Try to load the kernel's TSS selector into the DS register.
+       //asm volatile("movw $28,%ax; movw %ax,%ds");
+  
+       // DP: 0x28 == 40
+       asm volatile("movw $40,%ax; movw %ax,%ds");
+       return 0;
+}
+
diff --git a/user/apps/roslib/breakpoint.c b/user/apps/roslib/breakpoint.c
new file mode 100644 (file)
index 0000000..d43a19a
--- /dev/null
@@ -0,0 +1,10 @@
+// program to cause a breakpoint trap
+
+#include <inc/lib.h>
+
+int main(int argc, char** argv)
+{
+       asm volatile("int $3");
+       return 0;
+}
+
diff --git a/user/apps/roslib/buggyhello.c b/user/apps/roslib/buggyhello.c
new file mode 100644 (file)
index 0000000..dc1b82a
--- /dev/null
@@ -0,0 +1,11 @@
+// buggy hello world -- unmapped pointer passed to kernel
+// kernel should destroy user environment in response
+
+#include <inc/lib.h>
+
+int main(int argc, char** argv)
+{
+       sys_cputs((char*SAFE)TC(1), 1);
+       return 0;
+}
+
diff --git a/user/apps/roslib/divzero.c b/user/apps/roslib/divzero.c
new file mode 100644 (file)
index 0000000..7e18661
--- /dev/null
@@ -0,0 +1,12 @@
+// buggy program - causes a divide by zero exception
+
+#include <inc/lib.h>
+
+int zero;
+
+int main(int argc, char** argv)
+{
+       cprintf("1/0 is %08x!\n", 1/zero);
+       return 0;
+}
+
diff --git a/user/apps/roslib/evilhello.c b/user/apps/roslib/evilhello.c
new file mode 100644 (file)
index 0000000..19b30aa
--- /dev/null
@@ -0,0 +1,13 @@
+// evil hello world -- kernel pointer passed to kernel
+// kernel should destroy user environment in response
+
+#include <inc/lib.h>
+
+int main(int argc, char** argv)
+{
+       while(1);
+       // try to print the kernel entry point as a string!  mua ha ha!
+       sys_cputs((char*SAFE)TC(0xc0100020), 100);
+       return 0;
+}
+
diff --git a/user/apps/roslib/faultread.c b/user/apps/roslib/faultread.c
new file mode 100644 (file)
index 0000000..e24f894
--- /dev/null
@@ -0,0 +1,10 @@
+// buggy program - faults with a read from location zero
+
+#include <inc/lib.h>
+
+int main(int argc, char** argv)
+{ TRUSTEDBLOCK
+       cprintf("I read %08x from location 0!\n", *(unsigned*)0);
+       return 0;
+}
+
diff --git a/user/apps/roslib/faultreadkernel.c b/user/apps/roslib/faultreadkernel.c
new file mode 100644 (file)
index 0000000..9aa3d06
--- /dev/null
@@ -0,0 +1,10 @@
+// buggy program - faults with a read from kernel space
+
+#include <inc/lib.h>
+
+int main(int argc, char** argv)
+{ TRUSTEDBLOCK
+       cprintf("I read %08x from location&n