From f8529d09bf1555c2dda61f5841b7ad4f42ce9715 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Thu, 17 Apr 2025 13:44:55 -0400 Subject: elf sym loading --- kernel/old/Make.mk | 76 --- kernel/old/cio.c | 796 ---------------------------- kernel/old/clock.c | 163 ------ kernel/old/include/.vm.h.swp | Bin 24576 -> 0 bytes kernel/old/include/bootstrap.h | 120 ----- kernel/old/include/cio.h | 287 ---------- kernel/old/include/clock.h | 55 -- kernel/old/include/common.h | 31 -- kernel/old/include/compat.h | 131 ----- kernel/old/include/debug.h | 327 ------------ kernel/old/include/defs.h | 129 ----- kernel/old/include/elf.h | 235 --------- kernel/old/include/kdefs.h | 152 ------ kernel/old/include/klib.h | 57 -- kernel/old/include/kmem.h | 138 ----- kernel/old/include/lib.h | 314 ----------- kernel/old/include/list.h | 68 --- kernel/old/include/params.h | 31 -- kernel/old/include/procs.h | 452 ---------------- kernel/old/include/sio.h | 168 ------ kernel/old/include/support.h | 87 --- kernel/old/include/syscalls.h | 80 --- kernel/old/include/types.h | 58 -- kernel/old/include/udefs.h | 113 ---- kernel/old/include/ulib.h | 315 ----------- kernel/old/include/user.h | 138 ----- kernel/old/include/userids.h | 33 -- kernel/old/include/vm.h | 443 ---------------- kernel/old/include/vmtables.h | 43 -- kernel/old/include/x86/arch.h | 303 ----------- kernel/old/include/x86/bios.h | 73 --- kernel/old/include/x86/ops.h | 443 ---------------- kernel/old/include/x86/pic.h | 139 ----- kernel/old/include/x86/pit.h | 82 --- kernel/old/include/x86/uart.h | 349 ------------ kernel/old/isrs.S | 374 ------------- kernel/old/kernel.c | 384 -------------- kernel/old/kernel.ld | 71 --- kernel/old/kmem.c | 699 ------------------------ kernel/old/list.c | 64 --- kernel/old/procs.c | 1136 ---------------------------------------- kernel/old/sio.c | 694 ------------------------ kernel/old/startup.S | 153 ------ kernel/old/support.c | 279 ---------- kernel/old/syscalls.c | 829 ----------------------------- kernel/old/user.c | 783 --------------------------- kernel/old/vm.c | 625 ---------------------- kernel/old/vmtables.c | 338 ------------ 48 files changed, 12858 deletions(-) delete mode 100644 kernel/old/Make.mk delete mode 100644 kernel/old/cio.c delete mode 100644 kernel/old/clock.c delete mode 100644 kernel/old/include/.vm.h.swp delete mode 100644 kernel/old/include/bootstrap.h delete mode 100644 kernel/old/include/cio.h delete mode 100644 kernel/old/include/clock.h delete mode 100644 kernel/old/include/common.h delete mode 100644 kernel/old/include/compat.h delete mode 100644 kernel/old/include/debug.h delete mode 100644 kernel/old/include/defs.h delete mode 100644 kernel/old/include/elf.h delete mode 100644 kernel/old/include/kdefs.h delete mode 100644 kernel/old/include/klib.h delete mode 100644 kernel/old/include/kmem.h delete mode 100644 kernel/old/include/lib.h delete mode 100644 kernel/old/include/list.h delete mode 100644 kernel/old/include/params.h delete mode 100644 kernel/old/include/procs.h delete mode 100644 kernel/old/include/sio.h delete mode 100644 kernel/old/include/support.h delete mode 100644 kernel/old/include/syscalls.h delete mode 100644 kernel/old/include/types.h delete mode 100644 kernel/old/include/udefs.h delete mode 100644 kernel/old/include/ulib.h delete mode 100644 kernel/old/include/user.h delete mode 100644 kernel/old/include/userids.h delete mode 100644 kernel/old/include/vm.h delete mode 100644 kernel/old/include/vmtables.h delete mode 100644 kernel/old/include/x86/arch.h delete mode 100644 kernel/old/include/x86/bios.h delete mode 100644 kernel/old/include/x86/ops.h delete mode 100644 kernel/old/include/x86/pic.h delete mode 100644 kernel/old/include/x86/pit.h delete mode 100644 kernel/old/include/x86/uart.h delete mode 100644 kernel/old/isrs.S delete mode 100644 kernel/old/kernel.c delete mode 100644 kernel/old/kernel.ld delete mode 100644 kernel/old/kmem.c delete mode 100644 kernel/old/list.c delete mode 100644 kernel/old/procs.c delete mode 100644 kernel/old/sio.c delete mode 100644 kernel/old/startup.S delete mode 100644 kernel/old/support.c delete mode 100644 kernel/old/syscalls.c delete mode 100644 kernel/old/user.c delete mode 100644 kernel/old/vm.c delete mode 100644 kernel/old/vmtables.c (limited to 'kernel/old') diff --git a/kernel/old/Make.mk b/kernel/old/Make.mk deleted file mode 100644 index ac8928d..0000000 --- a/kernel/old/Make.mk +++ /dev/null @@ -1,76 +0,0 @@ -# -# Makefile fragment for the kernel components of the system. -# -# Makefile fragment for the kernel component of the system. -# -# THIS IS NOT A COMPLETE Makefile - run GNU make in the top-level -# directory, and this will be pulled in automatically. -# - -SUBDIRS += kernel - -################### -# FILES SECTION # -################### - -BOOT_OBJ := $(patsubst %.c, $(BUILDDIR)/%.o, $(BOOT_SRC)) - -KERN_SRC := kernel/startup.S kernel/isrs.S \ - kernel/cio.c kernel/clock.c kernel/kernel.c kernel/kmem.c \ - kernel/list.c kernel/procs.c kernel/sio.c kernel/support.c \ - kernel/syscalls.c kernel/user.c kernel/vm.c kernel/vmtables.c - -KERN_OBJ := $(patsubst %.c, $(BUILDDIR)/%.o, $(KERN_SRC)) -KERN_OBJ := $(patsubst %.S, $(BUILDDIR)/%.o, $(KERN_OBJ)) - -KCFLAGS := -ggdb -KLDFLAGS := -T kernel/kernel.ld -KLIBS := -lkernel -lcommon - -################### -# RULES SECTION # -################### - -kernel: $(BUILDDIR)/kernel/kernel.b - -$(BUILDDIR)/kernel/%.o: kernel/%.c $(BUILDDIR)/.vars.CFLAGS - @mkdir -p $(@D) - $(CC) $(CFLAGS) $(KCFLAGS) -c -o $@ $< - -#$(BUILDDIR)/kernel/%.o: kernel/%.S $(BUILDDIR)/.vars.CFLAGS -# @mkdir -p $(@D) -# $(CPP) $(CPPFLAGS) -o $(@D)/$*.s $< -# $(AS) $(ASFLAGS) $(KCFLAGS) -o $@ $(@D)/$*.s -a=$(@D)/$*.lst -# $(RM) -f $(@D)/$*.s - -$(BUILDDIR)/kernel/%.o: kernel/%.S $(BUILDDIR)/.vars.CFLAGS - @mkdir -p $(@D) - $(CC) $(CFLAGS) $(KCFLAGS) -c -o $@ $< - $(OBJDUMP) -S $@ > $(@D)/$*.asm - -$(BUILDDIR)/kernel/kernel: $(KERN_OBJ) - @mkdir -p $(@D) - $(LD) $(KLDFLAGS) $(LDFLAGS) -o $@ $(KERN_OBJ) $(KLIBS) - $(OBJDUMP) -S $@ > $@.asm - $(NM) -n $@ > $@.sym - $(READELF) -a $@ > $@.info - -$(BUILDDIR)/kernel/kernel.b: $(BUILDDIR)/kernel/kernel - $(LD) $(LDFLAGS) -o $(BUILDDIR)/kernel/kernel.b -s \ - --oformat binary -Ttext 0x10000 $(BUILDDIR)/kernel/kernel - -# some debugging assist rules -$(BUILDDIR)/kernel/%.i: kernel/%.c $(BUILDDIR)/.vars.CFLAGS - @mkdir -p $(@D) - $(CC) $(CFLAGS) $(KCFLAGS) -E -c $< > $(@D)/$*.i - -$(BUILDDIR)/kernel/%.dat: $(BUILDDIR)/kernel/%.o - @mkdir -p $(@D) - $(OBJCOPY) -S -O binary -j .data $< $@ - hexdump -C $@ > $(@D)/$*.hex - -$(BUILDDIR)/kernel/%.rodat: $(BUILDDIR)/kernel/%.o - @mkdir -p $(@D) - $(OBJCOPY) -S -O binary -j .rodata $< $@ - hexdump -C $@ > $(@D)/$*.hex - diff --git a/kernel/old/cio.c b/kernel/old/cio.c deleted file mode 100644 index cfff543..0000000 --- a/kernel/old/cio.c +++ /dev/null @@ -1,796 +0,0 @@ -/* -** SCCS ID: @(#)cio.c 2.10 1/22/25 -** -** @file cio.c -** -** @author Warren R. Carithers -** -** Based on: c_io.c 1.13 (Ken Reek, Jon Coles, Warren R. Carithers) -** -** Console I/O routines -** -** This module implements a simple set of input and output routines -** for the console screen and keyboard on the machines in the DSL. -** Refer to the header file comments for complete details. -** -** Naming conventions: -** -** Externally-visible functions have names beginning with the -** characters "cio_". -** -*/ - -#include -#include -#include -#include -#include -#include - -/* -** Bit masks for the lower five and eight bits of a value -*/ -#define BMASK5 0x1f -#define BMASK8 0xff - -/* -** Video parameters -*/ -#define SCREEN_MIN_X 0 -#define SCREEN_MIN_Y 0 -#define SCREEN_X_SIZE 80 -#define SCREEN_Y_SIZE 25 -#define SCREEN_MAX_X ( SCREEN_X_SIZE - 1 ) -#define SCREEN_MAX_Y ( SCREEN_Y_SIZE - 1 ) - -/* -** Video state -*/ -static unsigned int scroll_min_x, scroll_min_y; -static unsigned int scroll_max_x, scroll_max_y; -static unsigned int curr_x, curr_y; -static unsigned int min_x, min_y; -static unsigned int max_x, max_y; - -// pointer to input notification function -static void (*notify)(int); - -#ifdef SA_DEBUG -#include -#define cio_putchar putchar -#define cio_puts(x) fputs( x, stdout ) -#endif - - -/* -** VGA definitions. -*/ - -// calculate the memory address of a specific character position -// within VGA memory -#define VIDEO_ADDR(x,y) ( unsigned short * ) \ - ( VID_BASE_ADDR + 2 * ( (y) * SCREEN_X_SIZE + (x) ) ) - -// port addresses -#define VGA_CTRL_IX_ADDR 0x3d4 -# define VGA_CTRL_CUR_HIGH 0x0e // cursor location, high byte -# define VGA_CTRL_CUR_LOW 0x0f // cursor location, low byte -#define VGA_CTRL_IX_DATA 0x3d5 - -// attribute bits -#define VGA_ATT_BBI 0x80 // blink, or background intensity -#define VGA_ATT_BGC 0x70 // background color -#define VGA_ATT_FICS 0x80 // foreground intensity or char font select -#define VGA_ATT_FGC 0x70 // foreground color - -// color selections -#define VGA_BG_BLACK 0x0000 // background colors -#define VGA_BG_BLUE 0x1000 -#define VGA_BG_GREEN 0x2000 -#define VGA_BG_CYAN 0x3000 -#define VGA_BG_RED 0x4000 -#define VGA_BG_MAGENTA 0x5000 -#define VGA_BG_BROWN 0x6000 -#define VGA_BG_WHITE 0x7000 - -#define VGA_FG_BLACK 0x0000 // foreground colors -#define VGA_FG_BLUE 0x0100 -#define VGA_FG_GREEN 0x0200 -#define VGA_FG_CYAN 0x0300 -#define VGA_FG_RED 0x0400 -#define VGA_FG_MAGENTA 0x0500 -#define VGA_FG_BROWN 0x0600 -#define VGA_FG_WHITE 0x0700 - -// color combinations -#define VGA_WHITE_ON_BLACK (VGA_FG_WHITE | VGA_BG_BLACK) -#define VGA_BLACK_ON_WHITE (VGA_FG_BLACK | VGA_BG_WHITE) - -/* -** Internal support routines. -*/ - -/* -** setcursor: set the cursor location (screen coordinates) -*/ -static void setcursor( void ) { - unsigned addr; - unsigned int y = curr_y; - - if( y > scroll_max_y ) { - y = scroll_max_y; - } - - addr = (unsigned)( y * SCREEN_X_SIZE + curr_x ); - - outb( VGA_CTRL_IX_ADDR, VGA_CTRL_CUR_HIGH ); - outb( VGA_CTRL_IX_DATA, ( addr >> 8 ) & BMASK8 ); - outb( VGA_CTRL_IX_ADDR, VGA_CTRL_CUR_LOW ); - outb( VGA_CTRL_IX_DATA, addr & BMASK8 ); -} - -/* -** putchar_at: physical output to the video memory -*/ -static void putchar_at( unsigned int x, unsigned int y, unsigned int c ) { - /* - ** If x or y is too big or small, don't do any output. - */ - if( x <= max_x && y <= max_y ) { - unsigned short *addr = VIDEO_ADDR( x, y ); - - /* - ** The character may have attributes associated with it; if - ** so, use those, otherwise use white on black. - */ - c &= 0xffff; // keep only the lower bytes - if( c > BMASK8 ) { - *addr = (unsigned short)c; - } else { - *addr = (unsigned short)c | VGA_WHITE_ON_BLACK; - } - } -} - -/* -** Globally-visible support routines. -*/ - -/* -** Set the scrolling region -*/ -void cio_setscroll( unsigned int s_min_x, unsigned int s_min_y, - unsigned int s_max_x, unsigned int s_max_y ) { - scroll_min_x = bound( min_x, s_min_x, max_x ); - scroll_min_y = bound( min_y, s_min_y, max_y ); - scroll_max_x = bound( scroll_min_x, s_max_x, max_x ); - scroll_max_y = bound( scroll_min_y, s_max_y, max_y ); - curr_x = scroll_min_x; - curr_y = scroll_min_y; - setcursor(); -} - -/* -** Cursor movement in the scroll region -*/ -void cio_moveto( unsigned int x, unsigned int y ) { - curr_x = bound( scroll_min_x, x + scroll_min_x, scroll_max_x ); - curr_y = bound( scroll_min_y, y + scroll_min_y, scroll_max_y ); - setcursor(); -} - -/* -** The putchar family -*/ -void cio_putchar_at( unsigned int x, unsigned int y, unsigned int c ) { - if( ( c & 0x7f ) == '\n' ) { - unsigned int limit; - - /* - ** If we're in the scroll region, don't let this loop - ** leave it. If we're not in the scroll region, don't - ** let this loop enter it. - */ - if( x > scroll_max_x ) { - limit = max_x; - } - else if( x >= scroll_min_x ) { - limit = scroll_max_x; - } - else { - limit = scroll_min_x - 1; - } - while( x <= limit ) { - putchar_at( x, y, ' ' ); - x += 1; - } - } - else { - putchar_at( x, y, c ); - } -} - -#ifndef SA_DEBUG -void cio_putchar( unsigned int c ) { - /* - ** If we're off the bottom of the screen, scroll the window. - */ - if( curr_y > scroll_max_y ) { - cio_scroll( curr_y - scroll_max_y ); - curr_y = scroll_max_y; - } - - switch( c & BMASK8 ) { - case '\n': - /* - ** Erase to the end of the line, then move to new line - ** (actual scroll is delayed until next output appears). - */ - while( curr_x <= scroll_max_x ) { - putchar_at( curr_x, curr_y, ' ' ); - curr_x += 1; - } - curr_x = scroll_min_x; - curr_y += 1; - break; - - case '\r': - curr_x = scroll_min_x; - break; - - default: - putchar_at( curr_x, curr_y, c ); - curr_x += 1; - if( curr_x > scroll_max_x ) { - curr_x = scroll_min_x; - curr_y += 1; - } - break; - } - setcursor(); -} -#endif - -/* -** The puts family -*/ -void cio_puts_at( unsigned int x, unsigned int y, const char *str ) { - unsigned int ch; - - while( (ch = *str++) != '\0' && x <= max_x ) { - cio_putchar_at( x, y, ch ); - x += 1; - } -} - -#ifndef SA_DEBUG -void cio_puts( const char *str ) { - unsigned int ch; - - while( (ch = *str++) != '\0' ) { - cio_putchar( ch ); - } -} -#endif - -/* -** Write a "sized" buffer (like cio_puts(), but no NUL) -*/ -void cio_write( const char *buf, int length ) { - for( int i = 0; i < length; ++i ) { - cio_putchar( buf[i] ); - } -} - -void cio_clearscroll( void ) { - unsigned int nchars = scroll_max_x - scroll_min_x + 1; - unsigned int l; - unsigned int c; - - for( l = scroll_min_y; l <= scroll_max_y; l += 1 ) { - unsigned short *to = VIDEO_ADDR( scroll_min_x, l ); - - for( c = 0; c < nchars; c += 1 ) { - *to++ = ' ' | 0x0700; - } - } -} - -void cio_clearscreen( void ) { - unsigned short *to = VIDEO_ADDR( min_x, min_y ); - unsigned int nchars = ( max_y - min_y + 1 ) * ( max_x - min_x + 1 ); - - while( nchars > 0 ) { - *to++ = ' ' | 0x0700; - nchars -= 1; - } -} - - -void cio_scroll( unsigned int lines ) { - unsigned short *from; - unsigned short *to; - int nchars = scroll_max_x - scroll_min_x + 1; - int line, c; - - /* - ** If # of lines is the whole scrolling region or more, just clear. - */ - if( lines > scroll_max_y - scroll_min_y ) { - cio_clearscroll(); - curr_x = scroll_min_x; - curr_y = scroll_min_y; - setcursor(); - return; - } - - /* - ** Must copy it line by line. - */ - for( line = scroll_min_y; line <= scroll_max_y - lines; line += 1 ) { - from = VIDEO_ADDR( scroll_min_x, line + lines ); - to = VIDEO_ADDR( scroll_min_x, line ); - for( c = 0; c < nchars; c += 1 ) { - *to++ = *from++; - } - } - - for( ; line <= scroll_max_y; line += 1 ) { - to = VIDEO_ADDR( scroll_min_x, line ); - for( c = 0; c < nchars; c += 1 ) { - *to++ = ' ' | 0x0700; - } - } -} - -static int mypad( int x, int y, int extra, int padchar ) { - while( extra > 0 ) { - if( x != -1 || y != -1 ) { - cio_putchar_at( x, y, padchar ); - x += 1; - } - else { - cio_putchar( padchar ); - } - extra -= 1; - } - return x; -} - -static int mypadstr( int x, int y, char *str, int len, int width, - int leftadjust, int padchar ) { - int extra; - - if( len < 0 ) { - len = strlen( str ); - } - extra = width - len; - if( extra > 0 && !leftadjust ) { - x = mypad( x, y, extra, padchar ); - } - if( x != -1 || y != -1 ) { - cio_puts_at( x, y, str ); - x += len; - } - else { - cio_puts( str ); - } - if( extra > 0 && leftadjust ) { - x = mypad( x, y, extra, padchar ); - } - return x; -} - -static void do_printf( int x, int y, char **f ) { - char *fmt = *f; - int *ap; - char buf[ 12 ]; - char ch; - char *str; - int leftadjust; - int width; - int len; - int padchar; - - /* - ** Get characters from the format string and process them - */ - - ap = (int *)( f + 1 ); - - while( (ch = *fmt++) != '\0' ) { - - /* - ** Is it the start of a format code? - */ - - if( ch == '%' ) { - - /* - ** Yes, get the padding and width options (if there). - ** Alignment must come at the beginning, then fill, - ** then width. - */ - - leftadjust = 0; - padchar = ' '; - width = 0; - - ch = *fmt++; - - if( ch == '-' ) { - leftadjust = 1; - ch = *fmt++; - } - - if( ch == '0' ) { - padchar = '0'; - ch = *fmt++; - } - - while( ch >= '0' && ch <= '9' ) { - width *= 10; - width += ch - '0'; - ch = *fmt++; - } - - /* - ** What data type do we have? - */ - switch( ch ) { - - case 'c': - // ch = *( (int *)ap )++; - ch = *ap++; - buf[ 0 ] = ch; - buf[ 1 ] = '\0'; - x = mypadstr( x, y, buf, 1, width, leftadjust, padchar ); - break; - - case 'd': - // len = cvtdec( buf, *( (int *)ap )++ ); - len = cvtdec( buf, *ap++ ); - x = mypadstr( x, y, buf, len, width, leftadjust, padchar ); - break; - - case 's': - // str = *( (char **)ap )++; - str = (char *) (*ap++); - x = mypadstr( x, y, str, -1, width, leftadjust, padchar ); - break; - - case 'x': - // len = cvthex( buf, *( (int *)ap )++ ); - len = cvthex( buf, *ap++ ); - x = mypadstr( x, y, buf, len, width, leftadjust, padchar ); - break; - - case 'o': - // len = cvtoct( buf, *( (int *)ap )++ ); - len = cvtoct( buf, *ap++ ); - x = mypadstr( x, y, buf, len, width, leftadjust, padchar ); - break; - - case 'u': - len = cvtuns( buf, *ap++ ); - x = mypadstr( x, y, buf, len, width, leftadjust, padchar ); - break; - - } - } else { - - /* - ** No - just print it normally. - */ - - if( x != -1 || y != -1 ) { - cio_putchar_at( x, y, ch ); - switch( ch ) { - case '\n': - y += 1; - /* FALL THRU */ - - case '\r': - x = scroll_min_x; - break; - - default: - x += 1; - } - } - else { - cio_putchar( ch ); - } - } - } -} - -void cio_printf_at( unsigned int x, unsigned int y, char *fmt, ... ) { - do_printf( x, y, &fmt ); -} - -void cio_printf( char *fmt, ... ) { - do_printf( -1, -1, &fmt ); -} - -/* -** These are the "standard" IBM AT "Set 1" keycodes. -*/ - -static unsigned char scan_code[ 2 ][ 128 ] = { - { // unshifted characters -/* 00-07 */ '\377', '\033', '1', '2', '3', '4', '5', '6', -/* 08-0f */ '7', '8', '9', '0', '-', '=', '\b', '\t', -/* 10-17 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', -/* 18-1f */ 'o', 'p', '[', ']', '\n', '\377', 'a', 's', -/* 20-27 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', -/* 28-2f */ '\'', '`', '\377', '\\', 'z', 'x', 'c', 'v', -/* 30-37 */ 'b', 'n', 'm', ',', '.', '/', '\377', '*', -/* 38-3f */ '\377', ' ', '\377', '\377', '\377', '\377', '\377', '\377', -/* 40-47 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '7', -/* 48-4f */ '8', '9', '-', '4', '5', '6', '+', '1', -/* 50-57 */ '2', '3', '0', '.', '\377', '\377', '\377', '\377', -/* 58-5f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 60-67 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 68-6f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 70-77 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 78-7f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377' - }, - - { // shifted characters -/* 00-07 */ '\377', '\033', '!', '@', '#', '$', '%', '^', -/* 08-0f */ '&', '*', '(', ')', '_', '+', '\b', '\t', -/* 10-17 */ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', -/* 18-1f */ 'O', 'P', '{', '}', '\n', '\377', 'A', 'S', -/* 20-27 */ 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', -/* 28-2f */ '"', '~', '\377', '|', 'Z', 'X', 'C', 'V', -/* 30-37 */ 'B', 'N', 'M', '<', '>', '?', '\377', '*', -/* 38-3f */ '\377', ' ', '\377', '\377', '\377', '\377', '\377', '\377', -/* 40-47 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '7', -/* 48-4f */ '8', '9', '-', '4', '5', '6', '+', '1', -/* 50-57 */ '2', '3', '0', '.', '\377', '\377', '\377', '\377', -/* 58-5f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 60-67 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 68-6f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 70-77 */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377', -/* 78-7f */ '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377' - } -}; - -/* -** Scan code masks -*/ - -// 'release' bit -#define REL_BIT 0x80 -#define CODE_BITS 0x7f - -#define IS_PRESS(c) (((c) & REL_BIT) == 0) -#define IS_RELEASE(c) (((c) & REL_BIT) != 0) - -/* -** Scan codes for some special characters -*/ - -// escape code - followed by another code byte -#define SCAN_ESC 0xe0 - -// shift keys: press, release -#define L_SHIFT_DN 0x2a -#define R_SHIFT_DN 0x36 -#define L_SHIFT_UP 0xaa -#define R_SHIFT_UP 0xb6 - -// control keys -#define L_CTRL_DN 0x1d -#define L_CTRL_UP 0x9d - -/* -** I/O communication constants -*/ -#define KBD_DATA 0x60 -#define KBD_STATUS 0x64 -#define READY 0x1 - -/* -** Circular buffer for input characters. Characters are inserted at -** next_space, and are removed at next_char. Buffer is empty if -** these are equal. -*/ -#define C_BUFSIZE 200 - -static char input_buffer[ C_BUFSIZE ]; -static volatile char *next_char = input_buffer; -static volatile char *next_space = input_buffer; - -static volatile char *increment( volatile char *pointer ) { - if( ++pointer >= input_buffer + C_BUFSIZE ) { - pointer = input_buffer; - } - return pointer; -} - -static int input_scan_code( int code ) { - static int shift = 0; - static int ctrl_mask = BMASK8; - int rval = -1; - - /* - ** Do the shift processing - */ - code &= BMASK8; - switch( code ) { - case L_SHIFT_DN: - case R_SHIFT_DN: - shift = 1; - break; - - case L_SHIFT_UP: - case R_SHIFT_UP: - shift = 0; - break; - - case L_CTRL_DN: - ctrl_mask = BMASK5; - break; - - case L_CTRL_UP: - ctrl_mask = BMASK8; - break; - - default: - /* - ** Process ordinary characters only on the press (to handle - ** autorepeat). Ignore undefined scan codes. - */ - if( IS_PRESS(code) ) { - code = scan_code[ shift ][ (int)code ]; - if( code != '\377' ) { - volatile char *next = increment( next_space ); - - /* - ** Store character only if there's room - */ - rval = code & ctrl_mask; - if( next != next_char ) { - *next_space = code & ctrl_mask; - next_space = next; - } - } - } - } - return( rval ); -} - -static void keyboard_isr( int vector, int code ) { - - int data = inb( KBD_DATA ); - int val = input_scan_code( data ); - - // if there is a notification function, call it - if( val != -1 && notify ) - notify( val ); - - outb( PIC1_CMD, PIC_EOI ); -} - -int cio_getchar( void ) { - char c; - int interrupts_enabled = r_eflags() & EFL_IF; - - while( next_char == next_space ) { - if( !interrupts_enabled ) { - /* - ** Must read the next keystroke ourselves. - */ - while( ( inb( KBD_STATUS ) & READY ) == 0 ) { - ; - } - (void) input_scan_code( inb( KBD_DATA ) ); - } - } - - c = *next_char & BMASK8; - next_char = increment( next_char ); - if( c != EOT ) { - cio_putchar( c ); - } - return c; -} - -int cio_gets( char *buffer, unsigned int size ) { - char ch; - int count = 0; - - while( size > 1 ) { - ch = cio_getchar(); - if( ch == EOT ) { - break; - } - *buffer++ = ch; - count += 1; - size -= 1; - if( ch == '\n' ) { - break; - } - } - *buffer = '\0'; - return count; -} - -int cio_input_queue( void ) { - int n_chars = next_space - next_char; - - if( n_chars < 0 ) { - n_chars += C_BUFSIZE; - } - return n_chars; -} - -/* -** Initialization routines -*/ -void cio_init( void (*fcn)(int) ) { - /* - ** Screen dimensions - */ - min_x = SCREEN_MIN_X; - min_y = SCREEN_MIN_Y; - max_x = SCREEN_MAX_X; - max_y = SCREEN_MAX_Y; - - /* - ** Scrolling region - */ - scroll_min_x = SCREEN_MIN_X; - scroll_min_y = SCREEN_MIN_Y; - scroll_max_x = SCREEN_MAX_X; - scroll_max_y = SCREEN_MAX_Y; - - /* - ** Initial cursor location - */ - curr_y = min_y; - curr_x = min_x; - setcursor(); - - /* - ** Notification function (or NULL) - */ - notify = fcn; - - /* - ** Set up the interrupt handler for the keyboard - */ - install_isr( VEC_KBD, keyboard_isr ); -} - -#ifdef SA_DEBUG -int main() { - cio_printf( "%d\n", 123 ); - cio_printf( "%d\n", -123 ); - cio_printf( "%d\n", 0x7fffffff ); - cio_printf( "%d\n", 0x80000001 ); - cio_printf( "%d\n", 0x80000000 ); - cio_printf( "x%14dy\n", 0x80000000 ); - cio_printf( "x%-14dy\n", 0x80000000 ); - cio_printf( "x%014dy\n", 0x80000000 ); - cio_printf( "x%-014dy\n", 0x80000000 ); - cio_printf( "%s\n", "xyz" ); - cio_printf( "|%10s|\n", "xyz" ); - cio_printf( "|%-10s|\n", "xyz" ); - cio_printf( "%c\n", 'x' ); - cio_printf( "|%4c|\n", 'y' ); - cio_printf( "|%-4c|\n", 'y' ); - cio_printf( "|%04c|\n", 'y' ); - cio_printf( "|%-04c|\n", 'y' ); - cio_printf( "|%3d|\n", 5 ); - cio_printf( "|%3d|\n", 54321 ); - cio_printf( "%x\n", 0x123abc ); - cio_printf( "|%04x|\n", 20 ); - cio_printf( "|%012x|\n", 0xfedcba98 ); - cio_printf( "|%-012x|\n", 0x76543210 ); -} - -int curr_x, curr_y, max_x, max_y; -#endif diff --git a/kernel/old/clock.c b/kernel/old/clock.c deleted file mode 100644 index 96f71c4..0000000 --- a/kernel/old/clock.c +++ /dev/null @@ -1,163 +0,0 @@ -/** -** @file clock.c -** -** @author CSCI-452 class of 20245 -** -** @brief Clock module implementation -*/ - -#define KERNEL_SRC - -#include - -#include -#include - -#include -#include -#include - -/* -** PRIVATE DEFINITIONS -*/ - -/* -** PRIVATE DATA TYPES -*/ - -/* -** PRIVATE GLOBAL VARIABLES -*/ - -// pinwheel control variables -static uint32_t pinwheel; // pinwheel counter -static uint32_t pindex; // index into pinwheel string - -/* -** PUBLIC GLOBAL VARIABLES -*/ - -// current system time -uint32_t system_time; - -/* -** PRIVATE FUNCTIONS -*/ - -/** -** Name: clk_isr -** -** The ISR for the clock -** -** @param vector Vector number for the clock interrupt -** @param code Error code (0 for this interrupt) -*/ -static void clk_isr( int vector, int code ) { - - // spin the pinwheel - - ++pinwheel; - if( pinwheel == (CLOCK_FREQ / 10) ) { - pinwheel = 0; - ++pindex; - cio_putchar_at( 0, 0, "|/-\\"[ pindex & 3 ] ); - } - -#if defined(SYSTEM_STATUS) - // Periodically, dump the queue lengths and the SIO status (along - // with the SIO buffers, if non-empty). - // - // Define the symbol SYSTEM_STATUS with a value equal to the desired - // reporting frequency, in seconds. - - if( (system_time % SEC_TO_TICKS(SYSTEM_STATUS)) == 0 ) { - cio_printf_at( 1, 0, " queues: R[%u] W[%u] S[%u] Z[%u] I[%u] ", - pcb_queue_length(ready), - pcb_queue_length(waiting), - pcb_queue_length(sleeping), - pcb_queue_length(zombie), - pcb_queue_length(sioread) - ); - } -#endif - - // time marches on! - ++system_time; - - // wake up any sleeping processes whose time has come - // - // we give them preference over the current process when - // it is scheduled again - - do { - // if there isn't anyone in the sleep queue, we're done - if( pcb_queue_empty(sleeping) ) { - break; - } - - // peek at the first member of the queue - pcb_t *tmp = pcb_queue_peek( sleeping ); - assert( tmp != NULL ); - - // the sleep queue is sorted in ascending order by wakeup - // time, so we know that the retrieved PCB's wakeup time is - // the earliest of any process on the sleep queue; if that - // time hasn't arrived yet, there's nobody left to awaken - - if( tmp->wakeup > system_time ) { - break; - } - - // OK, we need to wake this process up - assert( pcb_queue_remove(sleeping,&tmp) == SUCCESS ); - schedule( tmp ); - } while( 1 ); - - // next, we decrement the current process' remaining time - current->ticks -= 1; - - // has it expired? - if( current->ticks < 1 ) { - // yes! reschedule it - schedule( current ); - current = NULL; - // and pick a new process - dispatch(); - } - - // tell the PIC we're done - outb( PIC1_CMD, PIC_EOI ); -} - -/* -** PUBLIC FUNCTIONS -*/ - -/** -** Name: clk_init -** -** Initializes the clock module -** -*/ -void clk_init( void ) { - -#if TRACING_INIT - cio_puts( " Clock" ); -#endif - - // start the pinwheel - pinwheel = (CLOCK_FREQ / 10) - 1; - pindex = 0; - - // return to the dawn of time - system_time = 0; - - // configure the clock - uint32_t divisor = PIT_FREQ / CLOCK_FREQ; - outb( PIT_CONTROL_PORT, PIT_0_LOAD | PIT_0_SQUARE ); - outb( PIT_0_PORT, divisor & 0xff ); // LSB of divisor - outb( PIT_0_PORT, (divisor >> 8) & 0xff ); // MSB of divisor - - // register the second-stage ISR - install_isr( VEC_TIMER, clk_isr ); -} diff --git a/kernel/old/include/.vm.h.swp b/kernel/old/include/.vm.h.swp deleted file mode 100644 index eb334b9..0000000 Binary files a/kernel/old/include/.vm.h.swp and /dev/null differ diff --git a/kernel/old/include/bootstrap.h b/kernel/old/include/bootstrap.h deleted file mode 100644 index ade778a..0000000 --- a/kernel/old/include/bootstrap.h +++ /dev/null @@ -1,120 +0,0 @@ -/* -** SCCS ID: @(#)bootstrap.h 2.4 1/22/25 -** -** @file bootstrap.h -** -** @author K. Reek -** @author Warren R. Carithers, Garrett C. Smith -** -** Addresses where various stuff goes in memory. -*/ - -#ifndef BOOTSTRAP_H_ -#define BOOTSTRAP_H_ - -/* -** The boot device -*/ -#define BDEV_FLOPPY 0x00 -#define BDEV_USB 0x80 /* hard drive */ - -#define BDEV BDEV_USB /* default */ - -/* -** Bootstrap definitions -*/ -#define BOOT_SEG 0x07c0 /* 07c0:0000 */ -#define BOOT_DISP 0x0000 -#define BOOT_ADDR ((BOOT_SEG << 4) + BOOT_DISP) - -#define PART2_DISP 0x0200 /* 07c0:0200 */ -#define PART2_ADDR ((BOOT_SEG << 4) + PART2_DISP) - -#define SECTOR_SIZE 0x200 /* 512 bytes */ - -/* Note: this assumes the bootstrap is two sectors long! */ -#define BOOT_SIZE (SECTOR_SIZE + SECTOR_SIZE) - -#define OFFSET_LIMIT (0x10000 - SECTOR_SIZE) - -#define BOOT_SP_DISP 0x4000 /* stack pointer 07c0:4000, or 0xbc00 */ -#define BOOT_SP_ADDR ((BOOT_SEG << 4) + BOOT_SP_DISP) - -#define SECTOR1_END (BOOT_ADDR + SECTOR_SIZE) -#define SECTOR2_END (BOOT_ADDR + BOOT_SIZE) - -// location of the user blob data -// (three halfwords of data) -#define USER_BLOB_DATA (SECTOR2_END - 12) - -/* -** The target program itself -*/ -#define TARGET_SEG 0x00001000 /* 1000:0000 */ -#define TARGET_ADDR 0x00010000 /* and upward */ -#define TARGET_STACK 0x00010000 /* and downward */ - -/* -** The Global Descriptor Table (0000:0500 - 0000:2500) -*/ -#define GDT_SEG 0x00000050 -#define GDT_ADDR 0x00000500 - - /* segment register values */ -#define GDT_LINEAR 0x0008 /* All of memory, R/W */ -#define GDT_CODE 0x0010 /* All of memory, R/E */ -#define GDT_DATA 0x0018 /* All of memory, R/W */ -#define GDT_STACK 0x0020 /* All of memory, R/W */ - -/* -** The Interrupt Descriptor Table (0000:2500 - 0000:2D00) -*/ -#define IDT_SEG 0x00000250 -#define IDT_ADDR 0x00002500 - -/* -** Additional I/O ports used by the bootstrap code -*/ - -// keyboard controller -#define KBD_DATA 0x60 -#define KBD_CMD 0x64 -#define KBD_STAT 0x64 - -// status register bits -#define KBD_OBSTAT 0x01 -#define KBD_IBSTAT 0x02 -#define KBD_SYSFLAG 0x04 -#define KBD_CMDDAT 0x08 - -// commands -#define KBD_P1_DISABLE 0xad -#define KBD_P1_ENABLE 0xae -#define KBD_RD_OPORT 0xd0 -#define KBD_WT_OPORT 0xd1 - -#ifdef ASM_SRC - -// segment descriptor macros for use in assembly source files -// layout: -// .word lower 16 bits of limit -// .word lower 16 bits of base -// .byte middle 8 bits of base -// .byte type byte -// .byte granularity byte -// .byte upper 8 bits of base -// we use 4K units, so we ignore the lower 12 bits of the limit -#define SEGNULL \ - .word 0, 0, 0, 0 - -#define SEGMENT(base,limit,dpl,type) \ - .word (((limit) >> 12) & 0xffff); \ - .word ((base) & 0xffff) ; \ - .byte (((base) >> 16) & 0xff) ; \ - .byte (SEG_PRESENT | (dpl) | SEG_NON_SYSTEM | (type)) ; \ - .byte (SEG_GRAN_4KBYTE | SEG_DB_32BIT | (((limit) >> 28) & 0xf)) ; \ - .byte (((base) >> 24) & 0xff) - -#endif /* ASM_SRC */ - -#endif diff --git a/kernel/old/include/cio.h b/kernel/old/include/cio.h deleted file mode 100644 index 1854f6e..0000000 --- a/kernel/old/include/cio.h +++ /dev/null @@ -1,287 +0,0 @@ -/** -** SCCS ID: @(#)cio.h 2.7 1/22/25 -** -** @file cio.h -** -** @author Warren R. Carithers -** @authors K. Reek, Jon Coles -** -** Based on: c_io.c 1.13 (Ken Reek, Jon Coles, Warren R. Carithers) -** -** Declarations and descriptions of console I/O routines -** -** These routines provide a rudimentary capability for printing to -** the screen and reading from the keyboard. -** -** Screen output: -** There are two families of functions. The first provides a window -** that behaves in the usual manner: writes extending beyond the right -** edge of the window wrap around to the next line, the top line -** scrolls off the window to make room for new lines at the bottom. -** However, you may choose what part of the screen contains this -** scrolling window. This allows you to print some text at fixed -** locations on the screen while the rest of the screen scrolls. -** -** The second family allows for printing at fixed locations on the -** screen. No scrolling or line wrapping are done for these functions. -** It is not intended that these functions be used to write in the -** scrolling area of the screen. -** -** In both sets of functions, the (x,y) coordinates are interpreted -** as (column,row), with the upper left corner of the screen being -** (0,0) and the lower right corner being (79,24). -** -** The printf provided in both sets of functions has the same -** conversion capabilities. Format codes are of the form: -** -** %-0WC -** -** where "-", "0", and "W" are all optional: -** "-" is the left-adjust flag (default is right-adjust) -** "0" is the zero-fill flag (default is space-fill) -** "W" is a number specifying the minimum field width (default: 1 ) -** and "C" is the conversion type, which must be one of these: -** "c" print a single character -** "s" print a null-terminated string -** "d" print an integer as a decimal value -** "x" print an integer as a hexadecimal value -** "o" print an integer as a octal value -** -** Keyboard input: -** Two functions are provided: getting a single character and getting -** a newline-terminated line. A third function returns a count of -** the number of characters available for immediate reading. -** No conversions are provided (yet). -*/ - -#ifndef CIO_H_ -#define CIO_H_ - -#ifndef ASM_SRC - -// EOT indicator (control-D) -#define EOT '\04' - -/***************************************************************************** -** -** INITIALIZATION ROUTINES -** -** Initializes the I/O system. -*/ - -/** -** cio_init -** -** Initializes the I/O routines. Must be called before -** any CIO functions can be used. -** -** @param notify pointer to an input notification function, or NULL -*/ -void cio_init( void (*notify)(int) ); - -/***************************************************************************** -** -** SCROLLING OUTPUT ROUTINES -** -** Each operation begins at the current cursor position and advances -** it. If a newline is output, the reminder of that line is cleared. -** Output extending past the end of the line is wrapped. If the -** cursor is moved below the scrolling region's bottom edge, scrolling -** is delayed until the next output is produced. -*/ - -/** -** cio_setscroll -** -** This sets the scrolling region to be the area defined by the arguments. -** The remainder of the screen does not scroll and may be used to display -** data you do not want to move. By default, the scrolling region is the -** entire screen. X and Y coordinates begin at 0 in the upper left corner -** of the screen. -** -** @param min_x,min_y upper-left corner of the region -** @param max_x,max_y lower-right corner of the region -*/ -void cio_setscroll( unsigned int min_x, unsigned int min_y, - unsigned int max_x, unsigned int max_y ); - -/** -** cio_moveto -** -** Moves the cursor to the specified position. (0,0) indicates -** the upper left corner of the scrolling region. Subsequent -** output will begin at the cursor position. -** -** @param x,y desired coordinate position -*/ -void cio_moveto( unsigned int x, unsigned int y ); - -/** -** cio_putchar -** -** Prints a single character. -** -** @param c the character to be printed -*/ -void cio_putchar( unsigned int c ); - -/** -** cio_puts -** -** Prints the characters in the string up to but not including -** the terminating null byte. -** -** @param str pointer to a NUL-terminated string to be printed -*/ -void cio_puts( const char *str ); - -/** -** cio_write -** -** Prints "length" characters from the buffer. -** -** @param buf the buffer of characters -** @param length the number of characters to print -*/ -void cio_write( const char *buf, int length ); - -/** -** cio_printf -** -** Limited form of printf (see the beginning of this file for -** a list of what is implemented). -** -** @param fmt a printf-style format control string -** @param ... optional additional values to be printed -*/ -void cio_printf( char *fmt, ... ); - -/** -** cio_scroll -** -** Scroll the scrolling region up by the given number of lines. -** The output routines scroll automatically so normally you -** do not need to call this routine yourself. -** -** @param lines the number of lines to scroll -*/ -void cio_scroll( unsigned int lines ); - -/** -** cio_clearscroll -** -** Clears the entire scrolling region to blank spaces, and -** moves the cursor to (0,0). -*/ -void cio_clearscroll( void ); - -/***************************************************************************** -** -** NON-SCROLLING OUTPUT ROUTINES -** -** Coordinates are relative to the entire screen: (0,0) is the upper -** left corner. There is no line wrap or scrolling. -*/ - -/** -** cio_putchar_at -** -** Prints the given character. If a newline is printed, -** the rest of the line is cleared. If this happens to the -** left of the scrolling region, the clearing stops when the -** region is reached. If this happens inside the scrolling -** region, the clearing stops when the edge of the region -** is reached. -** -** @param x,y desired coordinate position -** @param c the character to be printed -*/ -void cio_putchar_at( unsigned int x, unsigned int y, unsigned int c ); - -/** -** cio_puts_at -** -** Prints the given string. cio_putchar_at is used to print -** the individual characters; see that description for details. -** -** @param x,y desired coordinate position -** @param str pointer to a NUL-terminated string to be printed -*/ -void cio_puts_at( unsigned int x, unsigned int y, const char *str ); - -/** -** cio_printf_at -** -** Limited form of printf (see the beginning of this file for -** a list of what is implemented). -** -** @param x,y desired coordinate position -** @param fmt a printf-style format control string -** @param ... optional additional values to be printed -*/ -void cio_printf_at( unsigned int x, unsigned int y, char *fmt, ... ); - -/** -** cio_clearscreen -** -** This function clears the entire screen, including the scrolling region. -*/ -void cio_clearscreen( void ); - -/***************************************************************************** -** -** INPUT ROUTINES -** -** When interrupts are enabled, a keyboard ISR collects keystrokes -** and saves them until the program calls for them. If the input -** queue fills, additional characters are silently discarded. -** When interrupts are not enabled, keystrokes made when no input -** routines have been ** called are lost. This can cause errors in -** the input translation because the states of the Shift and Ctrl keys -** may not be tracked accurately. If interrupts are disabled, the user -** is advised to refrain from typing anything except when the program is -** waiting for input. -*/ - -/** -** cio_getchar -** -** If the character is not immediately available, the function -** waits until the character arrives. -** -** @return the next character from the keyboard input buffer -*/ -int cio_getchar( void ); - -/** -** cio_gets -** -** This function reads a newline-terminated line from the -** keyboard. cio_getchar is used to obtain the characters; -** see that description for more details. The function -** returns when: -** a newline is entered (this is stored in the buffer) -** ctrl-D is entered (not stored in the buffer) -** the buffer becomes full. -** The buffer is null-terminated in all cases. -** -** @param buffer destination buffer for the input character sequence -** @param size the buffer length -** -** @return count of the number of characters read into the buffer -*/ -int cio_gets( char *buffer, unsigned int size ); - -/** -** cio_input_queue -** -** This function lets the program determine whether there is input -** available. This indicates whether or not a call to cio_getchar() -** would block. -** -** @return number of characters in the input queue -*/ -int cio_input_queue( void ); -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/clock.h b/kernel/old/include/clock.h deleted file mode 100644 index 6eae41f..0000000 --- a/kernel/old/include/clock.h +++ /dev/null @@ -1,55 +0,0 @@ -/** -** @file clock.h -** -** @author CSCI-452 class of 20245 -** -** @brief Clock module declarations -*/ - -#ifndef CLOCK_H_ -#define CLOCK_H_ - -#include - -/* -** General (C and/or assembly) definitions -*/ - -// conversion functions for seconds, ms, and ticks -// (SEC_TO_MS is defined in defs.h) -#define MS_TO_TICKS(n) ((n)) -#define SEC_TO_TICKS(n) (MS_TO_TICKS(SEC_TO_MS(n))) -#define TICKS_TO_SEC(n) ((n) / CLOCK_FREQ) -#define TICKS_TO_SEC_ROUNDED(n) (((n)+(CLOCK_FREQ-1)) / CLOCK_FREQ) - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -*/ - -/* -** Types -*/ - -/* -** Globals -*/ - -// current system time -extern uint32_t system_time; - -/* -** Prototypes -*/ - -/** -** Name: clk_init -** -** Clock module initialization -*/ -void clk_init( void ); - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/common.h b/kernel/old/include/common.h deleted file mode 100644 index 599c492..0000000 --- a/kernel/old/include/common.h +++ /dev/null @@ -1,31 +0,0 @@ -/** -** @file common.h -** -** @author Warren R. Carithers -** -** @brief Common definitions for the baseline system. -** -** This header file pulls in the standard header information needed -** by all parts of the system. It is purely for our convenience. -*/ - -#ifndef COMMON_H_ -#define COMMON_H_ - -// everything needs these; they also pull in -// the kernel- or user-level defs and lib headers -#include -#include -#include -#include - -#ifdef KERNEL_SRC - -// only kernel code needs these headers -#include -#include -#include - -#endif /* KERNEL_SRC */ - -#endif diff --git a/kernel/old/include/compat.h b/kernel/old/include/compat.h deleted file mode 100644 index ee62090..0000000 --- a/kernel/old/include/compat.h +++ /dev/null @@ -1,131 +0,0 @@ -/** -** @file compat.h -** -** @author Warren R. Carithers -** -** @brief Compatibility definitions for standard modules. -** -** These definitions are here to simplify the integration -** of some pre-written modules into the 452 baseline system. -** This is used primarily for the 'kmem' and 'sio' modules. -** -** We use CPP symbols and not actual data types for things here, -** as this means we don't need to include any other header files -** into this file. This helps get around "include loops" (e.g., -** a.h includes b.h, which includes c.h, which includes a.h) when -** there are many interdependencies between source files. -*/ - -#ifndef COMPAT_H_ -#define COMPAT_H_ - -#include -#include - -/* -** Section 1: sized integer types -** -** Internally, we use standard names for "sized" integer types for -** simplicity. If those disagree with the names used in the rest of -** the system, we take the opportunity to define our names here. -** -** To enable these, uncomment them, and place the apropriate -** existing type names in place of the '?' characters. -*/ - -// standard "sized integer" types -// #define int8_t ? -// #define uint8_t ? -// #define int16_t ? -// #define uint16_t ? -// #define int32_t ? -// #define uint32_t ? -// #define int64_t ? -// #define uint64_t ? -// #define bool_t ? - -/* -** Section 2: other types -** -** Add type definitions here as needed. -** -** Note: we do not include the PCB and Queue declarations -** here because we don't actually need them in this header -** file - we're only defining CPP macros. Whatever file -** uses these macros, however, must include the appropriate -** headers if it uses these macros. -** -** To enable these, uncomment them, and place the apropriate -** existing type names in place of the '?' characters. -*/ - -// type name for the PCB -#define PCBTYPE pcb_t - -// type name for our queue -#define QTYPE pcb_queue_t - -/* -** Section 3: interface and behavior -** -** Include #define statements here as needed to define -** the names of functions and globals used in these modules -** in terms of the names used in the rest of the baseline. -** -** To enable these, uncomment them, and place the apropriate -** existing variable or function names in place of the '?' characters. -*/ - -// string functions -#define SLENGTH strlen - -// scheduler -#define SCHED schedule - -// dispatcher -#define DISPATCH dispatch - -/* -** blocked queue for reading processes -** -** Define this if we are blocking processes which try to -** read from the SIO when no characters are available. -** Its value should be the name of the globally-visible -** queue to be used. -*/ -#define QNAME sioread - -#ifdef QNAME - -// Only define these macros if we need to be able to create and -// manage a queue of things. It is expected that these will need -// to be customized based on the names and calling sequences of -// the appropriate functions. - -// invoke the queue creation function -// examples: -// -// #define QCREATE(q) do { -// _que_create( &(q), NULL ); -// } while(0) -// -// #define QCREATE(q) // do nothing - -#define QCREATE(q) // handled elsewhere for us - -// check to see if the queue is empty -// examples: -// -// #define QEMPTY(q) queue_is_empty(q) -// #define QEMPTY(q) (quene_length(q) > 0) -#define QEMPTY(q) pcb_queue_empty(q) - -// this macro expands into code that removes a value from -// 'q' and places it into 'd' -#define QDEQUE(q,d) do { \ - assert(pcb_queue_remove( (q), (pcb_t **) &(d) ) == SUCCESS ); \ - } while(0) - -#endif /* QNAME */ - -#endif diff --git a/kernel/old/include/debug.h b/kernel/old/include/debug.h deleted file mode 100644 index 487a592..0000000 --- a/kernel/old/include/debug.h +++ /dev/null @@ -1,327 +0,0 @@ -/** -** @file debug.h -** -** @author Numerous CSCI-452 classes -** -** Debugging macros and constants. -** -*/ - -#ifndef DEBUG_H_ -#define DEBUG_H_ - -// Standard system headers - -#include -#include - -// Kernel library - -#include - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -*/ - -/* -** General function entry/exit announcements -*/ - -#ifdef ANNOUNCE_ENTRY -// Announce that we have entered a kernel function -// usage: ENTERING( "name" ), EXITING( "name" ) -// currently, these do not use the macro parameter, but could be -// modified to do so; instead, we use the __func__ CPP pseudo-macro -// to get the function name -#define ENTERING(n) do { cio_puts( " enter " __func__ ); } while(0) -#define EXITING(n) do { cio_puts( " exit " __func__ ); } while(0) -#else -#define ENTERING(m) // do nothing -#define EXITING(m) // do nothing -#endif - -/* -** Console messages when error conditions are noted. -*/ - -// Warning messages to the console -// m: message (condition, etc.) -#define WARNING(m) do { \ - cio_printf( "\n** %s (%s @ %d): ", __func__, __FILE__, __LINE__ ); \ - cio_puts( m ); \ - cio_putchar( '\n' ); \ - } while(0) - -// Panic messages to the console -// n: severity level -// m: message (condition, etc.) -#define PANIC(n,m) do { \ - sprint( b512, "%s (%s @ %d), %d: %s\n", \ - __func__, __FILE__, __LINE__, n, # m ); \ - kpanic( b512 ); \ - } while(0) - -/* -** Assertions are categorized by the "sanity level" being used in this -** compilation; each only triggers a fault if the sanity level is at or -** above a specific value. This allows selective enabling/disabling of -** debugging checks. -** -** The sanity level is set during compilation with the CPP macro -** "SANITY". A sanity level of 0 disables conditional assertions, -** but not the basic assert() version. -*/ - -#ifndef SANITY -// default sanity check level: check everything! -#define SANITY 9999 -#endif - -// Always-active assertions -#define assert(x) if( !(x) ) { PANIC(0,x); } - -// only provide these macros if the sanity check level is positive - -#if SANITY > 0 - -#define assert1(x) if( SANITY >= 1 && !(x) ) { PANIC(1,x); } -#define assert2(x) if( SANITY >= 2 && !(x) ) { PANIC(2,x); } -#define assert3(x) if( SANITY >= 3 && !(x) ) { PANIC(3,x); } -#define assert4(x) if( SANITY >= 4 && !(x) ) { PANIC(4,x); } -// arbitrary sanity level -#define assertN(n,x) if( SANITY >= (n) && !(x) ) { PANIC(n,x); } - -#else - -#define assert1(x) // do nothing -#define assert2(x) // do nothing -#define assert3(x) // do nothing -#define assert4(x) // do nothing -#define assertN(n,x) // do nothing - -#endif /* SANITY > 0 */ - -/* -** Tracing options are enabled by defining one or more of the T_ -** macros described in the Makefile. -** -** To add a tracing option: -** -** 1) Pick a short name for it (e.g., "PCB", "VM", ...) -** 2) At the end of this list, add code like this, with "name" -** replaced by your short name, and "nnnnnnnn" replaced by a -** unique bit that will designate this tracing option: -** -** #ifdef T_name -** #define TRname 0xnnnnnnnn -** #else -** #define TRname 0 -** #endif -** -** Use the next bit position following the one in last list entry. -** 3) Add this to the end of the "TRACE" macro definition: -** -** | TRname -** -** 4) In the list of "TRACING_*" macros, add one for your option -** (using a name that might be more descriptive) in the 'then' clause: -** -** #define TRACING_bettername ((TRACE & TRname) != 0) -** -** 5) Also add a "null" version in the 'else' clause: -** -** #define TRACING_bettername 0 -** -** 6) Maybe add your T_name choice to the Makefile with an explanation -** on the off chance you want anyone else to be able to understand -** what it's used for. :-) -** -** We're making CPP work for its pay with this file. -*/ - -// 2^0 bit -#ifdef T_PCB -#define TRPCB 0x00000001 -#else -#define TRPCB 0 -#endif - -#ifdef T_VM -#define TRVM 0x00000002 -#else -#define TRVM 0 -#endif - -#ifdef T_QUE -#define TRQUEUE 0x00000004 -#else -#define TRQUEUE 0 -#endif - -#ifdef T_SCH -#define TRSCHED 0x00000008 -#else -#define TRSCHED 0 -#endif - -// 2^4 bit -#ifdef T_DSP -#define TRDISP 0x00000010 -#else -#define TRDISP 0 -#endif - -#ifdef T_SCALL -#define TRSYSCALLS 0x00000020 -#else -#define TRSYSCALLS 0 -#endif - -#ifdef T_SRET -#define TRSYSRETS 0x00000040 -#else -#define TRSYSRETS 0 -#endif - -#ifdef T_EXIT -#define TREXIT 0x00000080 -#else -#define TREXIT 0 -#endif - -// 2^8 bit -#ifdef T_INIT -#define TRINIT 0x00000100 -#else -#define TRINIT 0 -#endif - -#ifdef T_KM -#define TRKMEM 0x00000200 -#else -#define TRKMEM 0 -#endif - -#ifdef T_KMFR -#define TRKMEM_F 0x00000400 -#else -#define TRKMEM_F 0 -#endif - -#ifdef T_KMIN -#define TRKMEM_I 0x00000800 -#else -#define TRKMEM_I 0 -#endif - -// 2^12 bit -#ifdef T_FORK -#define TRFORK 0x00001000 -#else -#define TRFORK 0 -#endif - -#ifdef T_EXEC -#define TREXEC 0x00002000 -#else -#define TREXEC 0 -#endif - -#ifdef T_SIO -#define TRSIO_STAT 0x00004000 -#else -#define TRSIO_STAT 0 -#endif - -#ifdef T_SIOR -#define TRSIO_RD 0x00008000 -#else -#define TRSIO_RD 0 -#endif - -// 2^16 bit -#ifdef T_SIOW -#define TRSIO_WR 0x00010000 -#else -#define TRSIO_WR 0 -#endif - -#ifdef T_USER -#define TRUSER 0x00020000 -#else -#define TRUSER 0 -#endif - -#ifdef T_ELF -#define TRELF 0x00040000 -#else -#define TRELF 0 -#endif - -// 13 bits remaining for tracing options -// next available bit: 0x00080000 - -#define TRACE (TRDISP | TREXIT | TRINIT | TRKMEM | TRKMEM_F | TRKMEM_I | TRPCB | TRQUEUE | TRSCHED | TREXEC | TRSIO_RD | TRSIO_STAT | TRSIO_WR | TRFORK | TRVM | TRSYSCALLS | TRSYSRETS | TRUSER | TRELF) - -#if TRACE > 0 - -// compile-time expressions for testing trace options -// usage: #if TRACING_thing -#define TRACING_PCB ((TRACE & TRPCB) != 0) -#define TRACING_VM ((TRACE & TRVM) != 0) -#define TRACING_QUEUE ((TRACE & TRQUEUE) != 0) -#define TRACING_SCHED ((TRACE & TRSCHED) != 0) -#define TRACING_DISPATCH ((TRACE & TRDISPATCH) != 0) -#define TRACING_SYSCALLS ((TRACE & TRSYSCALLS) != 0) -#define TRACING_SYSRETS ((TRACE & TRSYSRETS) != 0) -#define TRACING_EXIT ((TRACE & TREXIT) != 0) -#define TRACING_INIT ((TRACE & TRINIT) != 0) -#define TRACING_KMEM ((TRACE & TRKMEM) != 0) -#define TRACING_KMEM_FREELIST ((TRACE & TRKMEM_F) != 0) -#define TRACING_KMEM_INIT ((TRACE & TRKMEM_I) != 0) -#define TRACING_FORK ((TRACE & TRFORK) != 0) -#define TRACING_EXEC ((TRACE & TREXEC) != 0) -#define TRACING_SIO_STAT ((TRACE & TRSIO_STAT) != 0) -#define TRACING_SIO_ISR ((TRACE & TRSIO_ISR) != 0) -#define TRACING_SIO_RD ((TRACE & TRSIO_RD) != 0) -#define TRACING_SIO_WR ((TRACE & TRSIO_WR) != 0) -#define TRACING_USER ((TRACE & TRUSER) != 0) -#define TRACING_ELF ((TRACE & TRELF) != 0) - -// more generic tests -#define TRACING_SOMETHING (TRACE != 0) - -#else - -// TRACE == 0, so just define these all as "false" - -#define TRACING_PCB 0 -#define TRACING_STACK 0 -#define TRACING_QUEUE 0 -#define TRACING_SCHED 0 -#define TRACING_DISPATCH 0 -#define TRACING_SYSCALLS 0 -#define TRACING_SYSRET 0 -#define TRACING_EXIT 0 -#define TRACING_INIT 0 -#define TRACING_KMEM 0 -#define TRACING_KMEM_FREELIST 0 -#define TRACING_KMEM_INIT 0 -#define TRACING_FORK 0 -#define TRACING_EXEC 0 -#define TRACING_SI_STAT 0 -#define TRACING_SIO_ISR 0 -#define TRACING_SIO_RD 0 -#define TRACING_SIO_WR 0 -#define TRACING_USER 0 -#define TRACING_ELF 0 - -#define TRACING_SOMETHING 0 - -#endif /* TRACE */ - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/defs.h b/kernel/old/include/defs.h deleted file mode 100644 index 0280c47..0000000 --- a/kernel/old/include/defs.h +++ /dev/null @@ -1,129 +0,0 @@ -/** -** @file defs.h -** -** @author Warren R. Carithers -** -** @brief Common definitions. -** -** This header file defines things which are neede by all -** parts of the system (OS and user levels). -** -** Things which are kernel-specific go in the kdefs.h file; -** things which are user-specific go in the udefs.h file. -** The correct one of these will be automatically included -** at the end of this file. -*/ - -#ifndef DEFS_H_ -#define DEFS_H_ - -/* -** General (C and/or assembly) definitions -** -** This section of the header file contains definitions that can be -** used in either C or assembly-language source code. -*/ - -// NULL pointer value -// -// we define this the traditional way so that -// it's usable from both C and assembly - -#define NULL 0 - -// predefined i/o channels - -#define CHAN_CIO 0 -#define CHAN_SIO 1 - -// maximum allowable number of command-line arguments -#define MAX_ARGS 10 - -// sizes of various things -#define NUM_1KB 0x00000400 // 2^10 -#define NUM_4KB 0x00001000 // 2^12 -#define NUM_1MB 0x00100000 // 2^20 -#define NUM_4MB 0x00400000 // 2^22 -#define NUM_1GB 0x40000000 // 2^30 -#define NUM_2GB 0x80000000 // 2^31 -#define NUM_3GB 0xc0000000 - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -** -** Anything that should not be visible to something other than -** the C compiler should be put here. -*/ - -/* -** System error codes -** -** These can be returned to both system functions -** and to user system calls. -*/ - // success! -#define SUCCESS (0) -# define E_SUCCESS SUCCESS - // generic "something went wrong" -#define E_FAILURE (-1) - // specific failure reasons -#define E_BAD_PARAM (-2) -#define E_BAD_CHAN (-3) -#define E_NO_CHILDREN (-4) -#define E_NO_MEMORY (-5) -#define E_NOT_FOUND (-6) -#define E_NO_PROCS (-7) - -/* -** These error codes are internal to the OS. -*/ -#define E_EMPTY_QUEUE (-100) -#define E_NO_PCBS (-101) -#define E_NO_PTE (-102) -#define E_LOAD_LIMIT (-103) - -// exit status values -#define EXIT_SUCCESS (0) -#define EXIT_FAILURE (-1) -#define EXIT_KILLED (-101) -#define EXIT_BAD_SYSCALL (-102) - -/* -** Process priority values -*/ -enum priority_e { - PRIO_HIGH, PRIO_STD, PRIO_LOW, PRIO_DEFERRED - // sentinel - , N_PRIOS -}; - -// halves of various data sizes - -#define UI16_UPPER 0xff00 -#define UI16_LOWER 0x00ff - -#define UI32_UPPER 0xffff0000 -#define UI32_LOWER 0x0000ffff - -#define UI64_UPPER 0xffffffff00000000LL -#define UI64_LOWER 0x00000000ffffffffLL - -// Simple conversion pseudo-functions usable by everyone - -// convert seconds to ms -#define SEC_TO_MS(n) ((n) * 1000) - -#endif /* !ASM_SRC */ - -/* -** Level-specific definitions -*/ -#ifdef KERNEL_SRC -#include -#else -#include -#endif /* KERNEL_SRC */ - -#endif diff --git a/kernel/old/include/elf.h b/kernel/old/include/elf.h deleted file mode 100644 index a43e5c3..0000000 --- a/kernel/old/include/elf.h +++ /dev/null @@ -1,235 +0,0 @@ -/** -** @file elf.h -** -** @author Warren R. Carithers -** -** @brief ELF format declarations -*/ - -#ifndef ELF_H_ -#define ELF_H_ - -#include - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -*/ - -// ELF data types (TIS ELF Spec v1.2, May 1995 -typedef uint32_t e32_a; // 32-bit unsigned address -typedef uint16_t e32_h; // 16-bit unsigned "medium" integer -typedef uint32_t e32_o; // 32-bit unsigned offset -typedef int32_t e32_sw; // 32-bit signed "large" integer -typedef uint32_t e32_w; // 32-bit unsigned "large" integer -typedef uint8_t e32_si; // 8-bit unsigned "small" integer - -// ELF magic number - first four bytes -#define ELF_MAGIC 0x464C457FU // "\x7FELF" in little-endian order -#define EI_NIDENT 16 - -union elfident_u { - uint8_t bytes[EI_NIDENT]; // array of 16 bytes - struct { - uint32_t magic; // magic number - uint8_t class; // file class - uint8_t data; // data encoding - uint8_t version; // file version - uint8_t osabi; // OS ABI identification - uint8_t abivers; // ABI version - uint8_t pad[7]; // padding to 16 bytes - } f; -}; - -// indices for byte fields in the ident array -#define EI_MAGIC 0 -# define EI_MAG0 EI_MAGIC -# define EI_MAG1 1 -# define EI_MAG2 2 -# define EI_MAG3 3 -#define EI_CLASS 4 -#define EI_DATA 5 -#define EI_VERSION 6 -#define EI_OSABI 7 -#define EI_ABIVERSION 8 - -// ELF classes -#define ELF_CLASS_NONE 0 -#define ELF_CLASS_32 1 // 32-bit objects -#define ELF_CLASS_64 2 // 64-bit objects - -// ELF data encoding -#define ELF_DATA_NONE 0 // invalid data encoding -#define ELF_DATA_2LSB 1 // two's complement little-endian -#define ELF_DATA_2MSB 2 // two's complement big-endian - -// ELF versions -#define ELF_VERSION__NONE 0 // invalid version -# define EV_NONE ELF_VERSION_NONE -#define ELF_VERSION__CURRENT 1 // current version -# define EV_CURRENT ELF_VERSION_CURRENT - -// ELF header -// -// field names are from the TIS ELF Spec v1.2, May 1995 -typedef struct elfhdr_s { - union elfident_u e_ident; // file identification - e32_h e_type; // file type - e32_h e_machine; // required architecture - e32_w e_version; // object file version - e32_a e_entry; // entry point (VA) - e32_o e_phoff; // offset to program header table (PHT) - e32_o e_shoff; // offset to section header table (SHT) - e32_w e_flags; // processor-specific flags - e32_h e_ehsize; // ELF header size (bytes) - e32_h e_phentsize; // size of one PHT entry (bytes) - e32_h e_phnum; // number of PHT entries - e32_h e_shentsize; // size of one SHT entry (bytes) - e32_h e_shnum; // number of SHT entries - e32_h e_shstrndx; // SHT index of the sect. name string table -} elfhdr_t; - -#define SZ_ELFHDR sizeof(elfhdr_t) - -// field values -// e_type -#define ET_NONE 0 // no file type -#define ET_REL 1 // relocatable file -#define ET_EXEC 2 // executable file -#define ET_DYN 3 // shared object file -#define ET_CORE 4 // core file -#define ET_LO_OS 0xfe00 // processor-specific -#define ET_HI_OS 0xfeff // processor-specific -#define ET_LO_CP 0xff00 // processor-specific -#define ET_HI_CP 0xffff // processor-specific - -// e_machine -#define EM_NONE 0x00 // no machine type -#define EM_M32 0x01 // AT&T WE 32100 -#define EM_SPARC 0x02 // SUN SPARC -#define EM_386 0x03 // Intel Architecture -#define EM_68K 0x04 // Motorola 68000 -#define EM_88K 0x05 // Motorola 88000 -#define EM_IAMCU 0x06 // Intel MCU -#define EM_860 0x07 // Intel 80860 -#define EM_MIPS 0x08 // MIPS RS3000 Big-Endian -#define EM_S370 0x09 // IBM System/370 -#define EM_MIPS_RS3_LE 0x0a // MIPS RS3000 Big-Endian -#define EM_SPARC32PLLUS 0x12 // Sun "v8plus" -#define EM_PPC 0x14 // IBM PowerPC -#define EM_PPC64 0x15 // IBM PowerPC 64-bit -#define EM_S390 0x16 // IBM System/390 -#define EM_ARM 0x28 // ARM up to V7/AArch32 -#define EM_SPARCV9 0x2b // SPARC V9 64-bit -#define EM_IA_64 0x32 // Intel Itanium (Merced) -#define EM_MIPS_X 0x32 // Stanford MIPS-X -#define EM_X86_64 0x3E // AMD x86-64 (Intel64) -#define EM_PDP11 0x40 // DEC PDP-11 -#define EM_VAX 0x4b // DEC VAX -#define EM_AARCH64 0xb7 // ARM AArch64 -#define EM_Z80 0xec // Zilog Z-80 -#define EM_AMDGPU 0xf0 // AMD GPU -#define EM_RISCV 0xf3 // RISC-V -#define EM_BPF 0xf7 // Berkeley Packet Filter - -// ELF section header -// -// field names are from the TIS ELF Spec v1.2, May 1995 -typedef struct shdr_s { - e32_w sh_name; // section name (index into string table) - e32_w sh_type; // section contents/semantics - e32_w sh_flags; // attribute flag bits - e32_a sh_addr; // 0, or load point of this section in memory - e32_o sh_offset; // byte offset within the file - e32_w sh_size; // section size in bytes - e32_w sh_link; // section header index table link - e32_w sh_info; // "extra information" - e32_w sh_addralign; // required alignment - e32_w sh_entsize; // 0, or size of each entry in the section -} elfsecthdr_t; - -#define SZ_ELFSECTHDR sizeof(elfsecthdr_t) - -// sh_name -#define SHN_UNDEF 0 - -// sh_type -#define SHT_NULL 0x00 -#define SHT_PROGBITS 0x01 -#define SHT_SYMTAB 0x02 -#define SHT_STRTAB 0x03 -#define SHT_RELA 0x04 -#define SHT_HASH 0x05 -#define SHT_DYNAMIC 0x06 -#define SHT_NOTE 0x07 -#define SHT_NOBITS 0x08 -#define SHT_REL 0x09 -#define SHT_SHLIB 0x0a -#define SHT_DYNSYM 0x0b -#define SHT_LO_CP 0x70000000 -#define SHT_HI_CP 0x7fffffff -#define SHT_LO_US 0x80000000 -#define SHT_HI_US 0x8fffffff - -// sh_flags -#define SHF_WRITE 0x001 -#define SHF_ALLOC 0x002 -#define SHF_EXECINSTR 0x004 -#define SHF_MERGE 0x010 -#define SHF_STRINGS 0x020 -#define SHF_INFO_LINK 0x040 -#define SHF_LINK_ORDER 0x080 -#define SHF_OS_NONCON 0x100 -#define SHF_GROUP 0x200 -#define SHF_TLS 0x400 -#define SHF_MASKOS 0x0ff00000 -#define SHF_MASKPROC 0xf0000000 - -// ELF program header -// -// field names are from the TIS ELF Spec v1.2, May 1995 -typedef struct phdr_s { - e32_w p_type; // type of segment - e32_o p_offset; // byte offset in file - e32_a p_va; // load point in memory (virtual address) - e32_a p_pa; // load point in memory (physical address) - e32_w p_filesz; // number of bytes in this file - e32_w p_memsz; // number of bytes in memory - e32_w p_flags; // attribute flag bits - e32_w p_align; // required alignment -} elfproghdr_t; - -#define SZ_ELFPROGHDR sizeof(elfproghdr_t) - -// p_type -#define PT_NULL 0 -#define PT_LOAD 1 -#define PT_DYNAMIC 2 -#define PT_INTERP 3 -#define PT_NOTE 4 -#define PT_SHLIB 5 -#define PT_PHDR 6 -#define PT_TLS 7 -#define PT_LO_OS 0x70000000 -#define PT_HI_OS 0x7fffffff -#define PT_LO_CP 0x70000000 -#define PT_HI_CP 0x7fffffff - -// p_flags -#define PF_E 0x1 -#define PF_W 0x2 -#define PF_R 0x4 -#define PF_MASKPROC 0xf0000000 - -/* -** Globals -*/ - -/* -** Prototypes -*/ - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/kdefs.h b/kernel/old/include/kdefs.h deleted file mode 100644 index 794516b..0000000 --- a/kernel/old/include/kdefs.h +++ /dev/null @@ -1,152 +0,0 @@ -/** -** @file kdefs.h -** -** @author CSCI-452 class of 20245 -** -** @brief Kernel-only declarations. -*/ - -#ifndef KDEFS_H_ -#define KDEFS_H_ - -// debugging macros -#include - -/* -** General (C and/or assembly) definitions -*/ - -// page sizes -#define SZ_PAGE NUM_4KB -#define SZ_BIGPAGE NUM_4MB - -// kernel stack size (bytes) -#define N_KSTKPAGES 1 -#define SZ_KSTACK (N_KSTKPAGES * SZ_PAGE) - -// user stack size -#define N_USTKPAGES 2 -#define SZ_USTACK (N_USTKPAGES * SZ_PAGE) - -// declarations for modulus checking of (e.g.) sizes and addresses - -#define MOD4_BITS 0x00000003 -#define MOD4_MASK 0xfffffffc -#define MOD4_INC 0x00000004 -#define MOD4_SHIFT 2 - -#define MOD16_BITS 0x0000000f -#define MOD16_MASK 0xfffffff0 -#define MOD16_INC 0x00000010 -#define MOD16_SHIFT 4 - -#define MOD1K_BITS 0x000003ff -#define MOD1K_MASK 0xfffffc00 -#define MOD1K_INC 0x00000400 -#define MOD1K_SHIFT 10 - -#define MOD4K_BITS 0x00000fff -#define MOD4K_MASK 0xfffff000 -#define MOD4K_INC 0x00001000 -#define MOD4K_SHIFT 12 - -#define MOD1M_BITS 0x000fffff -#define MOD1M_MASK 0xfff00000 -#define MOD1M_INC 0x00100000 -#define MOD1M_SHIFT 20 - -#define MOD4M_BITS 0x003fffff -#define MOD4M_MASK 0xffc00000 -#define MOD4M_INC 0x00400000 -#define MOD4M_SHIFT 22 - -#define MOD1G_BITS 0x3fffffff -#define MOD1G_MASK 0xc0000000 -#define MOD1G_INC 0x40000000 -#define MOD1G_SHIFT 30 - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -*/ - -// unit conversion macros -#define B_TO_KB(x) (((uint_t)(x))>>10) -#define B_TO_MB(x) (((uint_t)(x))>>20) -#define B_TO_GB(x) (((uint_t)(x))>>30) - -#define KB_TO_B(x) (((uint_t)(x))<<10) -#define KB_TO_MB(x) (((uint_t)(x))>>10) -#define KB_TO_GB(x) (((uint_t)(x))>>20) - -#define MB_TO_B(x) (((uint_t)(x))<<20) -#define MB_TO_KB(x) (((uint_t)(x))<<10) -#define MB_TO_GB(x) (((uint_t)(x))>>10) - -#define GB_TO_B(x) (((uint_t)(x))<<30) -#define GB_TO_KB(x) (((uint_t)(x))<<20) -#define GB_TO_MB(x) (((uint_t)(x))<<10) - -// potetially useful compiler attributes -#define ATTR_ALIGNED(x) __attribute__((__aligned__(x))) -#define ATTR_PACKED __attribute__((__packed__)) -#define ATTR_UNUSED __attribute__((__unused__)) - -/* -** Utility macros -*/ - -// -// macros to clear data structures -// -// these are usable for clearing single-valued data items (e.g., -// a PCB, etc.) -#define CLEAR(v) memclr( &v, sizeof(v) ) -#define CLEAR_PTR(p) memclr( p, sizeof(*p) ) - -// -// macros for access registers and system call arguments -// - -// REG(pcb,x) -- access a specific register in a process context -#define REG(pcb,x) ((pcb)->context->x) - -// RET(pcb) -- access return value register in a process context -#define RET(pcb) ((pcb)->context->eax) - -// ARG(pcb,n) -- access argument #n from the indicated process -// -// ARG(pcb,0) --> return address -// ARG(pcb,1) --> first parameter -// ARG(pcb,2) --> second parameter -// etc. -// -// ASSUMES THE STANDARD 32-BIT ABI, WITH PARAMETERS PUSHED ONTO THE -// STACK. IF THE PARAMETER PASSING MECHANISM CHANGES, SO MUST THIS! -#define ARG(pcb,n) ( ( (uint32_t *) (((pcb)->context) + 1) ) [(n)] ) - -/* -** Types -*/ - -/* -** Globals -*/ - -// general-purpose character buffer -extern char b256[256]; - -// buffer for use by PANIC() macro -extern char b512[512]; - -// kernel stack -extern uint8_t kstack[SZ_KSTACK]; - -/* -** Prototypes -*/ - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/klib.h b/kernel/old/include/klib.h deleted file mode 100644 index c1d270c..0000000 --- a/kernel/old/include/klib.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -** @file klib.h -** -** @author Warren R. Carithers -** -** Additional support functions for the kernel. -*/ - -#ifndef KLIB_H_ -#define KLIB_H_ - -#include - -#ifndef ASM_SRC - -#include - -/** -** Name: put_char_or_code( ch ) -** -** Description: Prints a character on the console, unless it -** is a non-printing character, in which case its hex code -** is printed -** -** @param ch The character to be printed -*/ -void put_char_or_code( int ch ); - -/** -** Name: backtrace -** -** Perform a simple stack backtrace. Could be augmented to use the -** symbol table to print function/variable names, etc., if so desired. -** -** @param ebp Initial EBP to use -** @param args Number of function argument values to print -*/ -void backtrace( uint32_t *ebp, uint_t args ); - -/** -** Name: kpanic -** -** Kernel-level panic routine -** -** usage: kpanic( msg ) -** -** Prefix routine for panic() - can be expanded to do other things -** (e.g., printing a stack traceback) -** -** @param msg[in] String containing a relevant message to be printed, -** or NULL -*/ -void kpanic( const char *msg ); - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/kmem.h b/kernel/old/include/kmem.h deleted file mode 100644 index 5a98765..0000000 --- a/kernel/old/include/kmem.h +++ /dev/null @@ -1,138 +0,0 @@ -/** -** @file kmem.h -** -** @author Warren R. Carithers -** @author Kenneth Reek -** @author 4003-506 class of 20013 -** -** @brief Support for dynamic memory allocation within the OS. -** -** This is a basic page allocator. Each allocation request returns -** a pointer to a single 4096-byte page of memory. -** -** The module also supports subddivision of pages into "slices", -** each of which is 1KB (i.e., 1/4 of a page). -*/ - -#ifndef KMEM_H_ -#define KMEM_H_ - -#define KERNEL_SRC - -// standard types etc. -#include - -/* -** General (C and/or assembly) definitions -*/ - -// Slab and slice sizes, in bytes - -#define SZ_SLAB SZ_PAGE -#define SZ_SLICE (SZ_SLAB >> 2) - -// memory limits -// -// these determine the range of memory addresses the kmem -// module will manage -// -// we won't map any memory below 1MB or above 1GB -#define KM_LOW_CUTOFF NUM_1MB -#define KM_HIGH_CUTOFF NUM_1GB - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -*/ - -/* -** Types -*/ - -/* -** Globals -*/ - -/* -** Prototypes -*/ - -/** -** Name: km_init -** -** Find what memory is present on the system and -** construct the list of free memory blocks. -** -** Dependencies: -** Must be called before any other init routine that uses -** dynamic storage is called. -*/ -void km_init( void ); - -/** -** Name: km_dump -** -** Dump information about the free lists to the console. By default, -** prints only the list sizes; if 'addrs' is true, also dumps the list -** of page addresses; if 'all' is also true, dumps page addresses and -** slice addresses. -** -** @param addrs Also dump page addresses -** @param both Also dump slice addresses -*/ -void km_dump( bool_t addrs, bool_t both ); - -/* -** Functions that manipulate free memory blocks. -*/ - -/** -** Name: km_page_alloc -** -** Allocate a page of memory from the free list. -** -** @return a pointer to the beginning of the allocated page, -** or NULL if no memory is available -*/ -void *km_page_alloc( void ); - -/** -** Name: km_page_free -** -** Returns a memory block to the list of available blocks, -** combining it with adjacent blocks if they're present. -** -** CRITICAL ASSUMPTION: multi-page blocks will be freed one page -** at a time! -** -** @param[in] block Pointer to the page to be returned to the free list -*/ -void km_page_free( void *block ); - -/** -** Name: km_slice_alloc -** -** Dynamically allocates a slice (1/4 of a page). If no -** memory is available, we return NULL (unless ALLOC_FAIL_PANIC -** was defined, in which case we panic). -** -** @return a pointer to the allocated slice -*/ -void *km_slice_alloc( void ); - -/** -** Name: km_slice_free -** -** Returns a slice to the list of available slices. -** -** We make no attempt to merge slices, as they are independent -** blocks of memory (unlike pages). -** -** @param[in] block Pointer to the slice (1/4 page) to be freed -*/ -void km_slice_free( void *block ); - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/lib.h b/kernel/old/include/lib.h deleted file mode 100644 index bde0554..0000000 --- a/kernel/old/include/lib.h +++ /dev/null @@ -1,314 +0,0 @@ -/** -** @file lib.h -** -** @author Numerous CSCI-452 classes -** -** @brief C declarations of common library functions -** -** These are callable from either kernel or user code. Care should be taken -** that user code is linked against these separately from kernel code, to -** ensure separation of the address spaces. -*/ - -#ifndef LIB_H_ -#define LIB_H_ - -#ifndef ASM_SRC - -#include - -/* -********************************************** -** MEMORY MANIPULATION FUNCTIONS -********************************************** -*/ - -/** -** blkmov(dst,src,len) -** -** Copy a word-aligned block from src to dst. Deals with overlapping -** buffers. -** -** If the buffer addresses aren't word-aligned or the length is not a -** multiple of four, calls memmove(). -** -** @param dst Destination buffer -** @param src Source buffer -** @param len Buffer size (in bytes) -*/ -void blkmov( void *dst, const void *src, register uint32_t len ); - -/** -** memset(buf,len,value) -** -** initialize all bytes of a block of memory to a specific value -** -** @param buf The buffer to initialize -** @param len Buffer size (in bytes) -** @param value Initialization value -*/ -void memset( void *buf, register uint32_t len, register uint32_t value ); - -/** -** memclr(buf,len) -** -** Initialize all bytes of a block of memory to zero -** -** @param buf The buffer to initialize -** @param len Buffer size (in bytes) -*/ -void memclr( void *buf, register uint32_t len ); - -/** -** memcpy(dst,src,len) -** -** Copy a block from one place to another -** -** May not correctly deal with overlapping buffers -** -** @param dst Destination buffer -** @param src Source buffer -** @param len Buffer size (in bytes) -*/ -void memcpy( void *dst, register const void *src, register uint32_t len ); - -/** -** memmove(dst,src,len) -** -** Copy a block from one place to another. Deals with overlapping -** buffers -** -** @param dst Destination buffer -** @param src Source buffer -** @param len Buffer size (in bytes) -*/ -void memmove( void *dst, register const void *src, register uint32_t len ); - -/* -********************************************** -** STRING MANIPULATION FUNCTIONS -********************************************** -*/ - -/** -** str2int(str,base) - convert a string to a number in the specified base -** -** @param str The string to examine -** @param base The radix to use in the conversion -** -** @return The converted integer -*/ -int str2int( register const char *str, register int base ); - -/** -** strlen(str) - return length of a NUL-terminated string -** -** @param str The string to examine -** -** @return The length of the string, or 0 -*/ -uint32_t strlen( register const char *str ); - -/** -** strcmp(s1,s2) - compare two NUL-terminated strings -** -** @param s1 The first source string -** @param s2 The second source string -** -** @return negative if s1 < s2, zero if equal, and positive if s1 > s2 -*/ -int strcmp( register const char *s1, register const char *s2 ); - -/** -** strcpy(dst,src) - copy a NUL-terminated string -** -** @param dst The destination buffer -** @param src The source buffer -** -** @return The dst parameter -** -** NOTE: assumes dst is large enough to hold the copied string -*/ -char *strcpy( register char *dst, register const char *src ); - -/** -** strcat(dst,src) - append one string to another -** -** @param dst The destination buffer -** @param src The source buffer -** -** @return The dst parameter -** -** NOTE: assumes dst is large enough to hold the resulting string -*/ -char *strcat( register char *dst, register const char *src ); - -/** -** pad(dst,extra,padchar) - generate a padding string -** -** @param dst Pointer to where the padding should begin -** @param extra How many padding bytes to add -** @param padchar What character to pad with -** -** @return Pointer to the first byte after the padding -** -** NOTE: does NOT NUL-terminate the buffer -*/ -char *pad( char *dst, int extra, int padchar ); - -/** -** padstr(dst,str,len,width,leftadjust,padchar - add padding characters -** to a string -** -** @param dst The destination buffer -** @param str The string to be padded -** @param len The string length, or -1 -** @param width The desired final length of the string -** @param leftadjust Should the string be left-justified? -** @param padchar What character to pad with -** -** @return Pointer to the first byte after the padded string -** -** NOTE: does NOT NUL-terminate the buffer -*/ -char *padstr( char *dst, char *str, int len, int width, - int leftadjust, int padchar ); - -/** -** sprint(dst,fmt,...) - formatted output into a string buffer -** -** @param dst The string buffer -** @param fmt Format string -** -** The format string parameter is followed by zero or more additional -** parameters which are interpreted according to the format string. -** -** NOTE: assumes the buffer is large enough to hold the result string -** -** NOTE: relies heavily on the x86 parameter passing convention -** (parameters are pushed onto the stack in reverse order as -** 32-bit values). -*/ -void sprint( char *dst, char *fmt, ... ); - -/* -********************************************** -** CONVERSION FUNCTIONS -********************************************** -*/ - -/** -** cvtuns0(buf,value) - local support routine for cvtuns() -** -** Convert a 32-bit unsigned value into a NUL-terminated character string -** -** @param buf Result buffer -** @param value Value to be converted -** -** @return Pointer to the first unused byte in the buffer -** -** NOTE: assumes buf is large enough to hold the resulting string -*/ -char *cvtuns0( char *buf, uint32_t value ); - -/** -** cvtuns(buf,value) -** -** Convert a 32-bit unsigned value into a NUL-terminated character string -** -** @param buf Result buffer -** @param value Value to be converted -** -** @return Length of the resulting buffer -** -** NOTE: assumes buf is large enough to hold the resulting string -*/ -int cvtuns( char *buf, uint32_t value ); - -/** -** cvtdec0(buf,value) - local support routine for cvtdec() -** -** convert a 32-bit unsigned integer into a NUL-terminated character string -** -** @param buf Destination buffer -** @param value Value to convert -** -** @return The number of characters placed into the buffer -** (not including the NUL) -** -** NOTE: assumes buf is large enough to hold the resulting string -*/ -char *cvtdec0( char *buf, int value ); - -/** -** cvtdec(buf,value) -** -** convert a 32-bit signed value into a NUL-terminated character string -** -** @param buf Destination buffer -** @param value Value to convert -** -** @return The number of characters placed into the buffer -** (not including the NUL) -** -** NOTE: assumes buf is large enough to hold the resulting string -*/ -int cvtdec( char *buf, int32_t value ); - -/** -** cvthex(buf,value) -** -** convert a 32-bit unsigned value into a mininal-length (up to -** 8-character) NUL-terminated character string -** -** @param buf Destination buffer -** @param value Value to convert -** -** @return The number of characters placed into the buffer -** (not including the NUL) -** -** NOTE: assumes buf is large enough to hold the resulting string -*/ -int cvthex( char *buf, uint32_t value ); - -/** -** cvtoct(buf,value) -** -** convert a 32-bit unsigned value into a mininal-length (up to -** 11-character) NUL-terminated character string -** -** @param buf Destination buffer -** @param value Value to convert -** -** @return The number of characters placed into the buffer -** (not including the NUL) -** -** NOTE: assumes buf is large enough to hold the resulting string -*/ -int cvtoct( char *buf, uint32_t value ); - -/** -** bound(min,value,max) -** -** This function confines an argument within specified bounds. -** -** @param min Lower bound -** @param value Value to be constrained -** @param max Upper bound -** -** @return The constrained value -*/ -uint32_t bound( uint32_t min, uint32_t value, uint32_t max ); - -#endif /* !ASM_SRC */ - -/* -** Finally, pull in the level-specific library headers -*/ -#ifdef KERNEL_SRC -#include -#else -#include -#endif /* KERNEL_SRC */ - -#endif diff --git a/kernel/old/include/list.h b/kernel/old/include/list.h deleted file mode 100644 index 28c2377..0000000 --- a/kernel/old/include/list.h +++ /dev/null @@ -1,68 +0,0 @@ -/** -** @file list.h -** -** @author Warren R. Carithers -** -** @brief Support for a basic linked list data type. -** -** This module provides a very basic linked list data structure. -** A list can contain anything that has a pointer field in the first -** four bytes; these routines assume those bytes contain a pointer to -** the following entry in the list, whatever that may be. -*/ - -#ifndef LIST_H_ -#define LIST_H_ - -#define KERNEL_SRC - -// standard types etc. -#include - -/* -** General (C and/or assembly) definitions -*/ - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -*/ - -/* -** Data types -*/ - -// The list structure -typedef struct list_s { - struct list_s *next; // link to the successor -} list_t; - -/* -** Prototypes -*/ - -/** -** Name: list_add -** -** Add the supplied data to the beginning of the specified list. -** -** @param[in,out] list The address of a list_t variable -** @param[in] data The data to prepend to the list -*/ -void list_add( list_t *list, void *data ); - -/** -** Name: list_remove -** -** Remove the first entry from a linked list. -** -** @param[in,out] list The address of a list_t variable -** -** @return a pointer to the removed data, or NULL if the list was empty -*/ -void *list_remove( list_t *list ); - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/params.h b/kernel/old/include/params.h deleted file mode 100644 index 52eb81d..0000000 --- a/kernel/old/include/params.h +++ /dev/null @@ -1,31 +0,0 @@ -/** -** @file params.h -** -** @author CSCI-452 class of 20245 -** -** @brief System configuration settings -** -** This header file contains many of the "easily tunable" system -** settings, such as clock rate, number of simultaneous user -** processes, etc. This provides a sort of "one-stop shop" for -** things that might be tweaked frequently. -*/ - -#ifndef PARAMS_H_ -#define PARAMS_H_ - -/* -** General (C and/or assembly) definitions -*/ - -// Upper bound on the number of simultaneous user-level -// processes in the system (completely arbitrary) - -#define N_PROCS 25 - -// Clock frequency (Hz) - -#define CLOCK_FREQ 1000 -#define TICKS_PER_MS 1 - -#endif diff --git a/kernel/old/include/procs.h b/kernel/old/include/procs.h deleted file mode 100644 index 9db4ac8..0000000 --- a/kernel/old/include/procs.h +++ /dev/null @@ -1,452 +0,0 @@ -/* -** @file procs.h -** -** @author CSCI-452 class of 20245 -** -** @brief Process-related declarations -*/ - -#ifndef PROCS_H_ -#define PROCS_H_ - -#include - -/* -** General (C and/or assembly) definitions -*/ - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -*/ - -/* -** Types -*/ - -/* -** Process states -*/ -enum state_e { - // pre-viable - STATE_UNUSED = 0, STATE_NEW, - // runnable - STATE_READY, STATE_RUNNING, - // runnable, but waiting for some event - STATE_SLEEPING, STATE_BLOCKED, STATE_WAITING, - // no longer runnable - STATE_KILLED, STATE_ZOMBIE - // sentinel value - , N_STATES -}; - -// these may be handy for checking general conditions of processes -// they depend on the order of the state names in the enum! -#define FIRST_VIABLE STATE_READY -#define FIRST_BLOCKED STATE_SLEEPING -#define LAST_VIABLE STATE_WAITING - -/* -** Process priorities are defined in -*/ - -/* -** Quantum lengths - values are number of clock ticks -*/ -enum quantum_e { - QUANTUM_SHORT = 1, - QUANTUM_STANDARD = 3, - QUANTUM_LONG = 5 -}; - -/* -** PID-related definitions -*/ -#define PID_INIT 1 -#define FIRST_USER_PID 2 - -/* -** Process context structure -** -** NOTE: the order of data members here depends on the -** register save code in isr_stubs.S!!!! -** -** This will be at the top of the user stack when we enter -** an ISR. In the case of a system call, it will be followed -** by the return address and the system call parameters. -*/ - -typedef struct context_s { - uint32_t ss; // pushed by isr_save - uint32_t gs; - uint32_t fs; - uint32_t es; - uint32_t ds; - uint32_t edi; - uint32_t esi; - uint32_t ebp; - uint32_t esp; - uint32_t ebx; - uint32_t edx; - uint32_t ecx; - uint32_t eax; - uint32_t vector; - uint32_t code; // pushed by isr_save or the hardware - uint32_t eip; // pushed by the hardware - uint32_t cs; - uint32_t eflags; -} context_t; - -#define SZ_CONTEXT sizeof(context_t) - -/* -** program section information for user processes -*/ - -typedef struct section_s { - uint_t length; // length, in some units - uint_t addr; // location, in some units -} section_t; - -// note: these correspond to the PT_LOAD sections found in -// an ELF file, not necessarily to text/data/bss -#define SECT_L1 0 -#define SECT_L2 1 -#define SECT_L3 2 -#define SECT_STACK 3 - -// total number of section table entries in our PCB -#define N_SECTS 4 -// number of those that can be loaded from an ELF module -#define N_LOADABLE 3 - -/* -** The process control block -** -** Fields are ordered by size to avoid padding -** -** Currently, this is 72 bytes long. It could be reduced to 64 (2^6) -** bytes by making the last four fields uint16_t types; that would -** divide nicely into 1024 bytes, giving 16 PCBs per 1/4 page of memory. -*/ - -typedef struct pcb_s { - - // four-byte fields - // start with these four bytes, for easy access in assembly - context_t *context; // pointer to context save area on stack - - // VM information - pde_t *pdir; // page directory for this process - section_t sects[N_SECTS]; // per-section memory information - - // queue linkage - struct pcb_s *next; // next PCB in queue - - // process state information - struct pcb_s *parent; // pointer to PCB of our parent process - uint32_t wakeup; // wakeup time, for sleeping processes - int32_t exit_status; // termination status, for parent's use - - // these things may not need to be four bytes - uint_t pid; // PID of this process - enum state_e state; // process' current state - enum priority_e priority; // process priority level - uint_t ticks; // remaining ticks in this time slice - -} pcb_t; - -#define SZ_PCB sizeof(pcb_t) - -/* -** PCB queue structure (opaque to the rest of the kernel) -*/ -typedef struct pcb_queue_s *pcb_queue_t; - -/* -** Queue ordering methods -*/ -enum pcb_queue_order_e { - O_FIFO, O_PRIO, O_PID, O_WAKEUP - // sentinel - , N_ORDERINGS -}; -#define O_FIRST_STYLE O_FIFO -#define O_LAST_STYLE O_WAKEUP - -/* -** Globals -*/ - -// public-facing queue handles -extern pcb_queue_t pcb_freelist; -extern pcb_queue_t ready; -extern pcb_queue_t waiting; -extern pcb_queue_t sleeping; -extern pcb_queue_t zombie; -extern pcb_queue_t sioread; - -// pointer to the currently-running process -extern pcb_t *current; - -// the process table -extern pcb_t ptable[N_PROCS]; - -// next available PID -extern uint_t next_pid; - -// pointer to the PCB for the 'init' process -extern pcb_t *init_pcb; - -// table of state name strings -extern const char *state_str[N_STATES]; - -// table of priority name strings -extern const char *prio_str[N_PRIOS]; - -// table of queue ordering name strings -extern const char *ord_str[N_ORDERINGS]; - -/* -** Prototypes -*/ - -/** -** Name: pcb_init -** -** Initialization for the Process module. -*/ -void pcb_init( void ); - -/** -** Name: pcb_alloc -** -** Allocate a PCB from the list of free PCBs. -** -** @param pcb Pointer to a pcb_t * where the PCB pointer will be returned. -** -** @return status of the allocation attempt -*/ -int pcb_alloc( pcb_t **pcb ); - -/** -** Name: pcb_free -** -** Return a PCB to the list of free PCBs. -** -** @param pcb Pointer to the PCB to be deallocated. -*/ -void pcb_free( pcb_t *pcb ); - -/** -** Name: pcb_zombify -** -** Turn the indicated process into a Zombie. This function -** does most of the real work for exit() and kill() calls. -** Is also called from the scheduler and dispatcher. -** -** @param pcb Pointer to the newly-undead PCB -*/ -void pcb_zombify( register pcb_t *victim ); - -/** -** Name: pcb_cleanup -** -** Reclaim a process' data structures -** -** @param pcb The PCB to reclaim -*/ -void pcb_cleanup( pcb_t *pcb ); - -/** -** Name: pcb_find_pid -** -** Locate the PCB for the process with the specified PID -** -** @param pid The PID to be located -** -** @return Pointer to the PCB, or NULL -*/ -pcb_t *pcb_find_pid( uint_t pid ); - -/** -** Name: pcb_find_ppid -** -** Locate the PCB for the process with the specified parent -** -** @param pid The PID to be located -** -** @return Pointer to the PCB, or NULL -*/ -pcb_t *pcb_find_ppid( uint_t pid ); - -/** -** Name: pcb_queue_reset -** -** Initialize a PCB queue. -** -** @param queue[out] The queue to be initialized -** @param order[in] The desired ordering for the queue -** -** @return status of the init request -*/ -int pcb_queue_reset( pcb_queue_t queue, enum pcb_queue_order_e style ); - -/** -** Name: pcb_queue_empty -** -** Determine whether a queue is empty. Essentially just a wrapper -** for the PCB_QUEUE_EMPTY() macro, for use outside this module. -** -** @param[in] queue The queue to check -** -** @return true if the queue is empty, else false -*/ -bool_t pcb_queue_empty( pcb_queue_t queue ); - -/** -** Name: pcb_queue_length -** -** Return the count of elements in the specified queue. -** -** @param[in] queue The queue to check -** -** @return the count (0 if the queue is empty) -*/ -uint_t pcb_queue_length( const pcb_queue_t queue ); - -/** -** Name: pcb_queue_insert -** -** Inserts a PCB into the indicated queue. -** -** @param queue[in,out] The queue to be used -** @param pcb[in] The PCB to be inserted -** -** @return status of the insertion request -*/ -int pcb_queue_insert( pcb_queue_t queue, pcb_t *pcb ); - -/** -** Name: pcb_queue_peek -** -** Return the first PCB from the indicated queue, but don't -** remove it from the queue -** -** @param queue[in] The queue to be used -** -** @return the PCB pointer, or NULL if the queue is empty -*/ -pcb_t *pcb_queue_peek( const pcb_queue_t queue ); - -/** -** Name: pcb_queue_remove -** -** Remove the first PCB from the indicated queue. -** -** @param queue[in,out] The queue to be used -** @param pcb[out] Pointer to where the PCB pointer will be saved -** -** @return status of the removal request -*/ -int pcb_queue_remove( pcb_queue_t queue, pcb_t **pcb ); - -/** -** Name: pcb_queue_remove_this -** -** Remove the specified PCB from the indicated queue. -** -** @param queue[in,out] The queue to be used -** @param pcb[in] Pointer to the PCB to be removed -** -** @return status of the removal request -*/ -int pcb_queue_remove_this( pcb_queue_t queue, pcb_t *pcb ); - -/* -** Scheduler routines -*/ - -/** -** schedule(pcb) -** -** Schedule the supplied process -** -** @param pcb Pointer to the PCB of the process to be scheduled -*/ -void schedule( pcb_t *pcb ); - -/** -** dispatch() -** -** Select the next process to receive the CPU -*/ -void dispatch( void ); - -/* -** Debugging/tracing routines -*/ - -/** -** Name: ctx_dump -** -** Dumps the contents of this process context to the console -** -** @param msg[in] An optional message to print before the dump -** @param c[in] The context to dump out -*/ -void ctx_dump( const char *msg, register context_t *c ); - -/** -** Name: ctx_dump_all -** -** dump the process context for all active processes -** -** @param msg[in] Optional message to print -*/ -void ctx_dump_all( const char *msg ); - -/** -** Name: pcb_dump -** -** Dumps the contents of this PCB to the console -** -** @param msg[in] An optional message to print before the dump -** @param p[in] The PCB to dump -** @param all[in] Dump all the contents? -*/ -void pcb_dump( const char *msg, register pcb_t *p, bool_t all ); - -/** -** Name: pcb_queue_dump -** -** Dump the contents of the specified queue to the console -** -** @param msg[in] An optional message to print before the dump -** @param queue[in] The queue to dump -** @param contents[in] Also dump (some) contents? -*/ -void pcb_queue_dump( const char *msg, pcb_queue_t queue, bool_t contents ); - -/** -** Name: ptable_dump -** -** dump the contents of the "active processes" table -** -** @param msg[in] Optional message to print -** @param all[in] Dump all or only part of the relevant data -*/ -void ptable_dump( const char *msg, bool_t all ); - -/** -** Name: ptable_dump_counts -** -** Prints basic information about the process table (number of -** entries, number with each process state, etc.). -*/ -void ptable_dump_counts( void ); - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/sio.h b/kernel/old/include/sio.h deleted file mode 100644 index dca80ed..0000000 --- a/kernel/old/include/sio.h +++ /dev/null @@ -1,168 +0,0 @@ -/** -** @file sio.h -** -** @author Warren R. Carithers -** -** @brief SIO definitions -*/ - -#ifndef SIO_H_ -#define SIO_H_ - -// compatibility definitions -#include - -/* -** General (C and/or assembly) definitions -*/ - -// sio interrupt settings - -#define SIO_TX 0x01 -#define SIO_RX 0x02 -#define SIO_BOTH (SIO_TX | SIO_RX) - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -*/ - -#include - -#include - -/* -** PUBLIC GLOBAL VARIABLES -*/ - -// queue for read-blocked processes -extern QTYPE QNAME; - -/* -** PUBLIC FUNCTIONS -*/ - -/** -** sio_init() -** -** Initialize the UART chip. -*/ -void sio_init( void ); - -/** -** sio_enable() -** -** Enable SIO interrupts -** -** usage: uint8_t old = sio_enable( uint8_t which ) -** -** @param which Bit mask indicating which interrupt(s) to enable -** -** @return the prior IER setting -*/ -uint8_t sio_enable( uint8_t which ); - -/** -** sio_disable() -** -** Disable SIO interrupts -** -** usage: uint8_t old = sio_disable( uint8_t which ) -** -** @param which Bit mask indicating which interrupt(s) to disable -** -** @return the prior IER setting -*/ -uint8_t sio_disable( uint8_t which ); - -/** -** sio_inq_length() -** -** Get the input queue length -** -** usage: int num = sio_inq_length() -** -** @return the count of characters still in the input queue -*/ -int sio_inq_length( void ); - -/** -** sio_readc() -** -** Get the next input character -** -** usage: int ch = sio_readc() -** -** @return the next character, or -1 if no character is available -*/ -int sio_readc( void ); - -/** -** sio_read() -** -** Read the entire input buffer into a user buffer of a specified size -** -** usage: int num = sio_read( char *buffer, int length ) -** -** @param buf The destination buffer -** @param length Length of the buffer -** -** @return the number of bytes copied, or 0 if no characters were available -*/ -int sio_read( char *buffer, int length ); - -/** -** sio_writec( ch ) -** -** Write a character to the serial output -** -** usage: sio_writec( int ch ) -** -** @param ch Character to be written (in the low-order 8 bits) -*/ -void sio_writec( int ch ); - -/** -** sio_write( ch ) -** -** Write a buffer of characters to the serial output -** -** usage: int num = sio_write( const char *buffer, int length ) -** -** @param buffer Buffer containing characters to write -** @param length Number of characters to write -** -** @return the number of characters copied into the SIO output buffer -*/ -int sio_write( const char *buffer, int length ); - -/** -** sio_puts( buf ) -** -** Write a NUL-terminated buffer of characters to the serial output -** -** usage: n = sio_puts( const char *buffer ); -** -** @param buffer The buffer containing a NUL-terminated string -** -** @return the count of bytes transferred -*/ -int sio_puts( const char *buffer ); - -/** -** sio_dump( full ) -** -** Dump the contents of the SIO buffers to the console -** -** usage: sio_dump(true) or sio_dump(false) -** -** @param full Boolean indicating whether or not a "full" dump -** is being requested (which includes the contents -** of the queues) -*/ -void sio_dump( bool_t full ); - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/support.h b/kernel/old/include/support.h deleted file mode 100644 index bdc5dc6..0000000 --- a/kernel/old/include/support.h +++ /dev/null @@ -1,87 +0,0 @@ -/** -** SCCS ID: @(#)support.h 2.3 1/22/25 -** -** @file support.h -** -** @author K. Reek -** @author Warren R. Carithers -** -** Declarations for functions provided in support.c, and -** some hardware characteristics needed in the initialization. -** -*/ - -#ifndef SUPPORT_H -#define SUPPORT_H - -/* -** Delay values -** -** Notes: The parameter to the delay() function is ambiguous; it -** purports to indicate a delay length, but that isn't really tied -** to any real-world time measurement. -** -** On the original systems we used (dual 500MHz Intel P3 CPUs), each -** "unit" was approximately one tenth of a second, so delay(10) would -** delay for about one second. -** -** On the current machines (Intel Core i5-7500), delay(100) is about -** 2.5 seconds, so each "unit" is roughly 0.025 seconds. -** -** Ultimately, just remember that THESE VALUES ARE APPROXIMATE AT BEST. -*/ -#define DELAY_1_SEC 40 -#define DELAY_1_25_SEC 50 -#define DELAY_2_SEC 80 -#define DELAY_2_5_SEC 100 -#define DELAY_3_SEC 120 -#define DELAY_5_SEC 200 -#define DELAY_7_SEC 280 -#define DELAY_10_SEC 400 - -#ifndef ASM_SRC -/** -** panic -** -** Called when we find an unrecoverable error, this routine disables -** interrupts, prints a description of the error and then goes into a -** hard loop to prevent any further processing. -** -** @param reason NUL-terminated message to be printed. -*/ -void panic( char *reason ); - -/** -** init_interrupts -** -** (Re)initilizes the interrupt system. This includes initializing the -** IDT and the PIC. It is up to the user to enable processor interrupts -** when they're ready. -*/ -void init_interrupts( void ); - -/* -** install_isr -** -** Installs a second-level handler for a specific interrupt. Returns the -** previously-installed handler for reinstallation (if desired). -** -** @param vector the interrupt vector number -** @param handler the second-stage ISR function to be called by the stub -** -** @return a pointer to the previously-registered ISR -*/ -void (*install_isr( int vector, - void ( *handler )(int,int) ) )( int, int ); - -/* -** Name: delay -** -** See the comment above about the relative accuracy of the 'length' -** parameter. -*/ -void delay( int length ); - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/syscalls.h b/kernel/old/include/syscalls.h deleted file mode 100644 index e66f6c0..0000000 --- a/kernel/old/include/syscalls.h +++ /dev/null @@ -1,80 +0,0 @@ -/** -** @file syscalls.h -** -** @author CSCI-452 class of 20245 -** -** @brief System call declarations -*/ - -#ifndef SYSCALLS_H_ -#define SYSCALLS_H_ - -#include - -/* -** General (C and/or assembly) definitions -*/ - -/* -** system call codes -** -** these are used in the user-level C library stub functions, -** and are defined here as CPP macros instead of as an enum -** so that they can be used from assembly -*/ - -#define SYS_exit 0 -#define SYS_waitpid 1 -#define SYS_fork 2 -#define SYS_exec 3 -#define SYS_read 4 -#define SYS_write 5 -#define SYS_getpid 6 -#define SYS_getppid 7 -#define SYS_gettime 8 -#define SYS_getprio 9 -#define SYS_setprio 10 -#define SYS_kill 11 -#define SYS_sleep 12 - -// UPDATE THIS DEFINITION IF MORE SYSCALLS ARE ADDED! -#define N_SYSCALLS 13 - -// dummy system call code for testing our ISR -#define SYS_bogus 0xbad - -// interrupt vector entry for system calls -#define VEC_SYSCALL 0x80 - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -*/ - -/* -** Types -*/ - -/* -** Globals -*/ - -/* -** Prototypes -*/ - -#ifdef KERNEL_SRC - -/** -** Name: sys_init -** -** Syscall module initialization routine -*/ -void sys_init( void ); - -#endif /* KERNEL_SRC */ - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/types.h b/kernel/old/include/types.h deleted file mode 100644 index 2f934f1..0000000 --- a/kernel/old/include/types.h +++ /dev/null @@ -1,58 +0,0 @@ -/** -** @file types.h -** -** @author Warren R. Carithers -** -** @brief Common type declarations. -** -** This header file contains type declarations used throughout -** the kernel and user code. -*/ - -#ifndef TYPES_H_ -#define TYPES_H_ - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -** -** Anything that should not be visible to something other than -** the C compiler should be put here. -*/ - -/* -** Types -*/ - -// standard integer sized types -typedef 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 int int64_t; -typedef unsigned long long int uint64_t; - -// other integer types -typedef unsigned char uchar_t; -typedef unsigned int uint_t; -typedef unsigned long int ulong_t; - -// Boolean values -typedef uint8_t bool_t; - -#define true 1 -#define false 0 - -#ifdef KERNEL_SRC -// we define these here instead of in vm.h in order to get around a -// nasty chick/egg dependency between procs.h and vm.h -typedef uint32_t pde_t; // page directory entry -typedef uint32_t pte_t; // page table entry -#endif /* KERNEL_SRC */ - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/udefs.h b/kernel/old/include/udefs.h deleted file mode 100644 index 50b6952..0000000 --- a/kernel/old/include/udefs.h +++ /dev/null @@ -1,113 +0,0 @@ -/** -** @file udefs.h -** -** @author CSCI-452 class of 20245 -** -** @brief "Userland" configuration information -*/ - -#ifndef UDEFS_H_ -#define UDEFS_H_ - -#include - -/* -** General (C and/or assembly) definitions -** -** This section of the header file contains definitions that can be -** used in either C or assembly-language source code. -*/ - -// delay loop counts - -#define DELAY_LONG 100000000 -#define DELAY_MED 4500000 -#define DELAY_SHORT 2500000 - -#define DELAY_STD DELAY_SHORT - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -*/ - -// convenience macros - -// a delay loop - kind of ugly, but it works - -#define DELAY(n) do { \ - for(int _dlc = 0; _dlc < (DELAY_##n); ++_dlc) continue; \ - } while(0) - -/* -** We need the list of program IDs so that we can request -** their execution -*/ - -#include - -/* -** All user main() functions have the following prototype: -** -** int name( int argc, char *argv[] ); -** -** To simplify declaring them, we define a macro that expands into -** that header. This can be used both in the implementation (followed -** by the function body) and in places where we just need the prototype -** (following it with a semicolon). -*/ - -#define USERMAIN(f) int f( int argc, char *argv[] ) - -/* -** User process controls. -** -** To enable a specific test, define the symbol SPAWN_name here, and -** guard the places in other code that use or refer to that test. For -** example, test 'A' is enabled by definining SPAWN_A here, and all -** places that refer to test 'A' are guarded with: -** -** #ifdef SPAWN_A -** ... conditionally-compiled code -** #endif -** -** Generally, most of these will exit with a status of 0. If a process -** returns from its main function when it shouldn't (e.g., if it had -** called exit() but continued to run), it will usually return a status -** of ?. -*/ - -/* -** The standard set of test programs, start by the shell (which is started -** automatically from the initial user process) -** -** There is no user 'O' program, and programs 'W' through 'Z' are spawned -** from other processes and are never spawned directly. -*/ - -#define SPAWN_A -#define SPAWN_B -#define SPAWN_C -#define SPAWN_D -#define SPAWN_E -#define SPAWN_F -#define SPAWN_G -#define SPAWN_H -#define SPAWN_I -#define SPAWN_J -#define SPAWN_K -#define SPAWN_L -#define SPAWN_M -#define SPAWN_N -#define SPAWN_P -#define SPAWN_Q -#define SPAWN_R -#define SPAWN_S -#define SPAWN_T -#define SPAWN_U -#define SPAWN_V - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/ulib.h b/kernel/old/include/ulib.h deleted file mode 100644 index d254d6a..0000000 --- a/kernel/old/include/ulib.h +++ /dev/null @@ -1,315 +0,0 @@ -/** -** @file ulib.h -** -** @author CSCI-452 class of 20245 -** -** @brief Declarations for user-level library functions -** -** This module implements a simple collection of support functions -** similar to the standard C library. -*/ - -#ifndef ULIB_H_ -#define ULIB_H_ - -#include - -/* -** General (C and/or assembly) definitions -*/ - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -*/ - -/* -** Types -*/ - -/* -** Globals -*/ - -/* -** Prototypes -*/ - -/* -************************************************* -** SYSTEM CALLS ********************************* -************************************************* -*/ - -/** -** exit - terminate the calling process -** -** usage: exit(status); -** -** @param status Termination status of this process -** -** Does not return. -*/ -void exit( int32_t status ); - -/** -** waitpid - wait for a child process to terminate -** -** usage: pid = waitpid(pid,&status); -** -** @param pid PID of the desired child, or 0 for any child -** @param status Pointer to int32_t into which the child's status is placed, -** or NULL -** -** @return The PID of the terminated child, or an error code -** -** If there are no children in the system, returns an error code (*status -** is unchanged). -** -** If there are one or more children in the system and at least one has -** terminated but hasn't yet been cleaned up, cleans up that process and -** returns its information; otherwise, blocks until a child terminates. -*/ -int waitpid( uint_t pid, int32_t *status ); - -/** -** fork - create a duplicate of the calling process -** -** usage: pid = fork(); -** -** @return parent - the pid of the new child, or an error code -** child - 0 -*/ -int fork( void ); - -/** -** exec - replace the memory image of the calling process -** -** usage: exec( what, args ) -** -** @param what program table index of the program to exec -** @param args the command-line argument vector -** -** Does not return if it succeeds; if it returns, something has -** gone wrong. -*/ -void exec( uint_t what, char **args ); - -/** -** read - read into a buffer from a stream -** -** usage: n = read(channel,buf,length) -** -** @param chan I/O stream to read from -** @param buf Buffer to read into -** @param length Maximum capacity of the buffer -** -** @return The count of bytes transferred, or an error code -*/ -int read( uint_t chan, void *buffer, uint_t length ); - -/** -** write - write from a buffer to a stream -** -** usage: n = write(channel,buf,length) -** -** @param chan I/O stream to write to -** @param buf Buffer to write from -** @param length Maximum capacity of the buffer -** -** @return The count of bytes transferred, or an error code -*/ -int write( uint_t chan, const void *buffer, uint_t length ); - -/** -** getpid - get the PID of the calling process -** -** usage: pid = getpid() -** -** @return the PID of this process -*/ -uint_t getpid( void ); - -/** -** getppid - get the PID of the calling process' parent -** -** usage: pid = getppid() -** -** @return the PID of this process' parent -*/ -uint_t getppid( void ); - -/** -** gettime - get the current system time -** -** usage: pid = gettime() -** -** @return the system time -*/ -uint32_t gettime( void ); - -/** -** getprio - get the scheduling priority of the calling process -** -** usage: prio = getprio() -** -** @return the process' priority -*/ -int getprio( void ); - -/** -** setprio - set the scheduling priority of the calling process -** -** usage: oldprio = setprio(newprio) -** -** @param new the desired new priority -** -** @return the old priority value -*/ -int setprio( int new ); - -/** -** kill - terminate a process with extreme prejudice -** -** usage: n = kill( pid ) -** -** @param pid the intended victim -** -** @return 0 on success, else an error code -*/ -int32_t kill( uint_t pid ); - -/** -** sleep - put the current process to sleep for some length of time -** -** usage: sleep(n); -** -** @param ms Desired sleep time (in ms), or 0 to yield the CPU -** -** @return the time the process spent sleeping (in ms) -*/ -int sleep( uint32_t ms ); - -/** -** bogus - a nonexistent system call, to test our syscall ISR -** -** usage: bogus() -** -** Does not return. -*/ -void bogus( void ); - -/* -************************************************* -** CONVENIENT "SHORTHAND" VERSIONS OF SYSCALLS ** -************************************************* -** -** These are library functions that perform specific common -** variants of system calls. This helps reduce the total number -** of system calls, keeping our baseline OS as lean and mean -** as we can make it. :-) -*/ - -/** -** wait - wait for any child to exit -** -** usage: pid = wait(&status) -** -** Calls waitpid(0,status) -** -** @param status Pointer to int32_t into which the child's status is placed, -** or NULL -** -** @return The PID of the terminated child, or an error code -*/ -int wait( int32_t *status ); - -/** -** spawn - create a new process running a different program -** -** usage: n = spawn(what,args) -** -** Creates a new process and then execs 'what' -** -** @param what Program table index of the program to spawn -** @param args The command-line argument vector for the process -** -** @return The PID of the child, or an error code -*/ -int spawn( uint_t what, char **args ); - -/** -** cwritech(ch) - write a single character to the console -** -** @param ch The character to write -** -** @return The return value from calling write() -*/ -int cwritech( char ch ); - -/** -** cwrites(str) - write a NUL-terminated string to the console -** -** @param str The string to write -** -*/ -int cwrites( const char *str ); - -/** -** cwrite(buf,leng) - write a sized buffer to the console -** -** @param buf The buffer to write -** @param leng The number of bytes to write -** -** @return The return value from calling write() -*/ -int cwrite( const char *buf, uint32_t leng ); - -/** -** swritech(ch) - write a single character to the SIO -** -** @param ch The character to write -** -** @return The return value from calling write() -*/ -int swritech( char ch ); - -/** -** swrites(str) - write a NUL-terminated string to the SIO -** -** @param str The string to write -** -** @return The return value from calling write() -*/ -int swrites( const char *str ); - -/** -** swrite(buf,leng) - write a sized buffer to the SIO -** -** @param buf The buffer to write -** @param leng The number of bytes to write -** -** @return The return value from calling write() -*/ -int swrite( const char *buf, uint32_t leng ); - -/* -************************************************* -** MISCELLANEOUS USEFUL SUPPORT FUNCTIONS ******* -************************************************* -*/ - -/** -** fake_exit() -** -** dummy "startup" function -** -** calls exit(%eax) - serves as the "return to" code for -** main() functions, in case they don't call exit() themselves -*/ -void fake_exit( void ); - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/user.h b/kernel/old/include/user.h deleted file mode 100644 index 4d9402f..0000000 --- a/kernel/old/include/user.h +++ /dev/null @@ -1,138 +0,0 @@ -/** -** @file user.h -** -** @author CSCI-452 class of 20245 -** -** @brief Declarations of user-level code management routines -*/ - -#ifndef USER_H_ -#define USER_H_ - -#include - -#include -#include - -// default value for EFLAGS in new processes -#define DEFAULT_EFLAGS (EFL_MB1 | EFL_IF) - -/* -** General (C and/or assembly) definitions -*/ - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -*/ - -/* -** Types -*/ - -/* -** Blob file organization -** -** The file begins with a four-byte magic number and a four-byte integer -** indicating the number of ELF files contained in the blob. This is -** followed by an array of 32-byte file table entries, and then the contents -** of the ELF files in the order they appear in the program file table. -** -** Bytes Contents -** ----- ---------------------------- -** 0 - 3 File magic number ("BLB\0") -** 4 - 7 Number of ELF files in blob ("n") -** 8 - n*32+8 Program file table -** n*32+9 - ? ELF file contents -** -** Each program file table entry contains the following information: -** -** name File name (up to 19 characters long) -** offset Byte offset to the ELF header for this file -** size Size of this ELF file, in bytes -** flags Flags related to this file -*/ - -// user program blob header -typedef struct header_s { - char magic[4]; - uint32_t num; -} header_t; - -// length of the file name field -#define NAMELEN 20 - -// program descriptor -typedef struct prog_s { - char name[NAMELEN]; // truncated name (15 chars) - uint32_t offset; // offset from the beginning of the blob - uint32_t size; // size of this ELF module - uint32_t flags; // miscellaneous flags -} prog_t; - -/* -** Globals -*/ - -/* -** Prototypes -*/ - -/** -** Name: user_init -** -** Initializes the user support module. -*/ -void user_init( void ); - -/** -** Name: user_locate -** -** Locates a user program in the user code archive. -** -** @param what The ID of the user program to find -** -** @return pointer to the program table entry in the code archive, or NULL -*/ -prog_t *user_locate( uint_t what ); - -/** -** Name: user_duplicate -** -** Duplicates the memory setup for an existing process. -** -** @param new The PCB for the new copy of the program -** @param old The PCB for the existing the program -** -** @return the status of the duplicate attempt -*/ -int user_duplicate( pcb_t *new, pcb_t *old ); - -/** -** Name: user_load -** -** Loads a user program from the user code archive into memory. -** Allocates all needed frames and sets up the VM tables. -** -** @param prog A pointer to the program table entry to be loaded -** @param pcb The PCB for the program being loaded -** @param args The argument vector for the program -** -** @return the status of the load attempt -*/ -int user_load( prog_t *prog, pcb_t *pcb, const char **args ); - -/** -** Name: user_cleanup -** -** "Unloads" a user program. Deallocates all memory frames and -** cleans up the VM structures. -** -** @param pcb The PCB of the program to be cleaned up -*/ -void user_cleanup( pcb_t *pcb ); - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/userids.h b/kernel/old/include/userids.h deleted file mode 100644 index 284f3ee..0000000 --- a/kernel/old/include/userids.h +++ /dev/null @@ -1,33 +0,0 @@ -/** -** @file userids.h -** -** @author Warren R. Carithers -** -** @brief IDs for user-level programs -** -** NOTE: this file is automatically generated when the user.img file -** is created. Do not edit this manually! -*/ - -#ifndef USERIDS_H_ -#define USERIDS_H_ - -#ifndef ASM_SRC -/* -** These IDs are used to identify the various user programs. -** Each call to exec() will provide one of these as the first -** argument. -** -** This list should be updated if/when the collection of -** user processes changes. -*/ -enum users_e { - Init, Idle, Shell, ProgABC, ProgDE, ProgFG, ProgH, ProgI, - ProgJ, ProgKL, ProgMN, ProgP, ProgQ, ProgR, ProgS, ProgTUV, - ProgW, ProgX, ProgY, ProgZ - // sentinel - , N_USERS -}; -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/vm.h b/kernel/old/include/vm.h deleted file mode 100644 index 6e3935e..0000000 --- a/kernel/old/include/vm.h +++ /dev/null @@ -1,443 +0,0 @@ -/** -** @file vm.h -** -** @author CSCI-452 class of 20245 -** -** @brief Virtual memory-related declarations. -*/ - -#ifndef VM_H_ -#define VM_H_ - -#include -#include - -#include - -/* -** VM layout of the system -** -** User processes use the first 4MB of the 32-bit address space; see the -** next comment for details. -** -** Kernel virtual addresses are in the "higher half" range, beginning -** at 0x80000000. We define our mapping such that virtual address -** 0x8nnnnnnn maps to physical address 0x0nnnnnnn, so converting between -** the two is trivial. -*/ - -/* -** VM layout of process' address space -** -** Processes are limited to the first 4MB of the 32-bit address space: -** -** Address Range Contents -** ======================= ================================ -** 0x00000000 - 0x00000fff page 0 is inaccessible -** 0x00001000 - 0x000..fff text occupies pages 1 - N -** 0x000..000 - 0x000..fff data occupies pages N+1 - N+d -** 0x000..000 - 0x000..fff bss occupies pages N+d+1 - N+d+b -** 0x000..000 - 0x003fdfff unusable -** 0x003fe000 - 0x003fffff stack occupies last two pages -** -** This gives us the following page table structure: -** -** Page directory: -** Entries Contents -** ======== ============================== -** 0 point to PMT for address space -** 1 - 1023 invalid -** -** Page map table: -** Entries Contents -** ======== ============================== -** 0 invalid -** 1 - N text frames -** N+1 - N+d data frames -** N+d+1 - N+d+b bss frames -** N+d+b+1 - 1021 invalid -** 1022 - 1023 stack frames -*/ - -/* -** General (C and/or assembly) definitions -*/ - -// user virtual addresses -#define USER_TEXT 0x00001000 -#define USER_STACK 0x003fe000 -#define USER_STK_END 0x00400000 - -// how to find the addresses of the stack pages in the VM hierarchy -// user address space is the first 4MB of virtual memory -#define USER_PDE 0 -// the stack occupies the last two pages of the address space -#define USER_STK_PTE1 1022 -#define USER_STK_PTE2 1023 - -// some important memory addresses -#define KERN_BASE 0x80000000 // start of "kernel" memory -#define EXT_BASE 0x00100000 // start of "extended" memory (1MB) -#define DEV_BASE 0xfe000000 // "device" memory -#define PHYS_TOP 0x3fffffff // last usable physical address (1GB - 1) - -// where the kernel actually lives -#define KERN_PLINK 0x00010000 -#define KERN_VLINK (KERN_BASE + KERN_PLINK) - -// number of entries in a page directory or page table -#define N_PDE 1024 -#define N_PTE 1024 - -// index field shift counts and masks -#define PDIX_SHIFT 22 -#define PTIX_SHIFT 12 -#define PIX2I_MASK 0x3ff - -// physical/virtual converters that don't use casting -// (usable from anywhere) -#define V2PNC(a) ((a) - KERN_BASE) -#define P2VNC(a) ((a) + KERN_BASE) - -// page-size address rounding macros -#define SZ_PG_M1 MOD4K_BITS -#define SZ_PG_MASK MOD4K_MASK -#define PGUP(a) (((a)+SZ_PG_M1) & SZ_PG_MASK) -#define PGDOWN(a) ((a) & SZ_PG_MASK) - -// page directory entry bit fields -#define PDE_P 0x00000001 // 1 = present -#define PDE_RW 0x00000002 // 1 = writable -#define PDE_US 0x00000004 // 1 = user and system usable -#define PDE_PWT 0x00000008 // cache: 1 = write-through -#define PDE_PCD 0x00000010 // cache: 1 = disabled -#define PDE_A 0x00000020 // accessed -#define PDE_D 0x00000040 // dirty (4MB pages) -#define PDE_AVL1 0x00000040 // ignored (4KB pages) -#define PDE_PS 0x00000080 // 1 = 4MB page size -#define PDE_G 0x00000100 // global -#define PDE_AVL2 0x00000e00 // ignored -#define PDE_PAT 0x00001000 // (4MB pages) use page attribute table -#define PDE_PTA 0xfffff000 // page table address field (4KB pages) -#define PDE_FA 0xffc00000 // frame address field (4MB pages) - -// page table entry bit fields -#define PTE_P 0x00000001 // present -#define PTE_RW 0x00000002 // 1 = writable -#define PTE_US 0x00000004 // 1 = user and system usable -#define PTE_PWT 0x00000008 // cache: 1 = write-through -#define PTE_PCD 0x00000010 // cache: 1 = disabled -#define PTE_A 0x00000020 // accessed -#define PTE_D 0x00000040 // dirty -#define PTE_PAT 0x00000080 // use page attribute table -#define PTE_G 0x00000100 // global -#define PTE_AVL2 0x00000e00 // ignored -#define PTE_FA 0xfffff000 // frame address field - -// error code bit assignments for page faults -#define PFLT_P 0x00000001 -#define PFLT_W 0x00000002 -#define PFLT_US 0x00000004 -#define PFLT_RSVD 0x00000008 -#define PFLT_ID 0x00000010 -#define PFLT_PK 0x00000020 -#define PFLT_SS 0x00000040 -#define PFLT_HLAT 0x00000080 -#define PFLT_SGX 0x00008000 -#define PFLT_UNUSED 0xffff7f00 - -#ifndef ASM_SRC - -/* -** Start of C-only definitions -*/ - -// physical/virtual converters that do use casting -// (not usable from assembly) -#define V2P(a) (((uint32_t)(a)) - KERN_BASE) -#define P2V(a) (((uint32_t)(a)) + KERN_BASE) - -// create a pde/pte from an integer frame number and permission bits -#define MKPDE(f,p) ((pde_t)( TO_FRAME((f)) | (p) )) -#define MKPTE(f,p) ((pte_t)( TO_FRAME((f)) | (p) )) - -// is a PDE/PTE present? -// (P bit is in the same place in both) -#define IS_PRESENT(entry) (((entry) & PDE_P) != 0 ) - -// is a PDE a 4MB page entry? -#define IS_LARGE(pde) (((pde) & PDE_PS) != 0 ) - -// is this entry "system only" or "system and user"? -#define IS_SYSTEM(entry) (((entry) & PDE_US) == 0 ) -#define IS_USER(entry) (((entry) & PDE_US) != 0 ) - -// low-order nine bits of PDEs and PTEs hold "permission" flag bits -#define PERMS_MASK MOD4K_MASK - -// 4KB frame numbers are 20 bits wide -#define FRAME_4K_SHIFT 12 -#define FRAME2I_4K_MASK 0x000fffff -#define TO_4KFRAME(n) (((n)&FRAME2I_4K_MASK) << FRAME_4K_SHIFT) -#define GET_4KFRAME(n) (((n) >> FRAME_4K_SHIFT)&F2I_4K_MASK) -#define PDE_4K_ADDR(n) ((n) & MOD4K_MASK) -#define PTE_4K_ADDR(n) ((n) & MOD4K_MASK) - -// 4MB frame numbers are 10 bits wide -#define FRAME_4M_SHIFT 22 -#define FRAME2I_4M_MASK 0x000003ff -#define TO_4MFRAME(n) (((n)&FRAME2I_4M_MASK) << FRAME_4M_SHIFT) -#define GET_4MFRAME(n) (((n) >> FRAME_4M_SHIFT)&F2I_4M_MASK) -#define PDE_4M_ADDR(n) ((n) & MOD4M_MASK) -#define PTE_4M_ADDR(n) ((n) & MOD4M_MASK) - -// extract the PMT address or frame address from a table entry -// PDEs could point to 4MB pages, or 4KB PMTs -#define PDE_ADDR(p) (IS_LARGE(p)?(((uint32_t)p)&PDE_FA):(((uint32_t)p)&PDE_PTA)) -// PTEs always point to 4KB pages -#define PTE_ADDR(p) (((uint32_t)(p))&PTE_FA) -// everything has nine bits of permission flags -#define PERMS(p) (((uint32_t)(p))&PERMS_MASK) - -// extract the table indices from a 32-bit address -#define PDIX(v) ((((uint32_t)(v)) >> PDIX_SHIFT) & PIX2I_MASK) -#define PTIX(v) ((((uint32_t)(v)) >> PTIX_SHIFT) & PIX2I_MASK) - -/* -** Types -*/ - -// page directory entries - -// as a 32-bit word, in types.h -// typedef uint32_t pde_t; - -// PDE for 4KB pages -typedef struct pdek_s { - uint_t p :1; // present - uint_t rw :1; // writable - uint_t us :1; // user/supervisor - uint_t pwt :1; // cache write-through - uint_t pcd :1; // cache disable - uint_t a :1; // accessed - uint_t avl1 :1; // ignored (available) - uint_t ps :1; // page size (must be 0) - uint_t avl2 :4; // ignored (available) - uint_t fa :20; // frame address -} pdek_f_t; - -// PDE for 4MB pages -typedef struct pdem_s { - uint_t p :1; // present - uint_t rw :1; // writable - uint_t us :1; // user/supervisor - uint_t pwt :1; // cache write-through - uint_t pcd :1; // cache disable - uint_t a :1; // accessed - uint_t d :1; // dirty - uint_t ps :1; // page size (must be 1) - uint_t g :1; // global - uint_t avl :3; // ignored (available) - uint_t fa :20; // frame address -} pdem_f_t; - -// page table entries - -// as a 32-bit word, in types.h -// typedef uint32_t pte_t; - -// broken out into fields -typedef struct pte_s { - uint_t p :1; // present - uint_t rw :1; // writable - uint_t us :1; // user/supervisor - uint_t pwt :1; // cache write-through - uint_t pcd :1; // cache disable - uint_t a :1; // accessed - uint_t d :1; // dirty - uint_t pat :1; // page attribute table in use - uint_t g :1; // global - uint_t avl :3; // ignored (available) - uint_t fa :20; // frame address -} ptef_t; - -// page fault error code bits -// comment: meaning when 1 / meaning when 0 -struct pfec_s { - uint_t p :1; // page-level protection violation / !present - uint_t w :1; // write / read - uint_t us :1; // user-mode access / supervisor-mode access - uint_t rsvd :1; // reserved bit violation / not - uint_t id :1; // instruction fetch / data fetch - uint_t pk :1; // protection-key violation / !pk - uint_t ss :1; // shadow stack access / !ss - uint_t hlat :1; // HLAT paging / ordinary paging or access rights - uint_t xtr1 :7; // unused - uint_t sgz :1; // SGX-specific access control violation / !SGX - uint_t xtr2 :16; // more unused -}; - -typedef union pfec_u { - uint32_t u; - struct pfec_s s; -} pfec_t; - -// Mapping descriptor for VA::PA mappings -typedef struct mapping_t { - uint32_t va_start; // starting virtual address for this range - uint32_t pa_start; // first physical address in the range - uint32_t pa_end; // last physical address in the range - uint32_t perm; // access control -} mapping_t; - -/* -** Globals -*/ - -// created page directory for the kernel -extern pde_t *kpdir; - -/* -** Prototypes -*/ - -/** -** Name: vm_init -** -** Initialize the VM module -** -** Note: should not be called until after the memory free list has -** been set up. -*/ -void vm_init( void ); - -/** -** Name: vm_pagedup -** -** Duplicate a page of memory -** -** @param old Pointer to the first byte of a page -** -** @return a pointer to the new, duplicate page, or NULL -*/ -void *vm_pagedup( void *old ); - -/** -** Name: vm_ptdup -** -** Duplicate a page directory entry -** -** @param dst Pointer to where the duplicate should go -** @param curr Pointer to the entry to be duplicated -** -** @return true on success, else false -*/ -bool_t vm_ptdup( pde_t *dst, pde_t *curr ); - -/** -** Name: vm_getpte -** -** Return the address of the PTE corresponding to the virtual address -** 'va' within the address space controlled by 'pgdir'. If there is no -** page table for that VA and 'alloc' is true, create the necessary -** page table entries. -** -** @param pdir Pointer to the page directory to be searched -** @param va The virtual address we're looking for -** @param alloc Should we allocate a page table if there isn't one? -** -** @return A pointer to the page table entry for this VA, or NULL -*/ -pte_t *vm_getpte( pde_t *pdir, const void *va, bool_t alloc ); - -/** -** Name: vm_mkkvm -** -** Create the kernel's page table hierarchy -*/ -pde_t *vm_mkkvm( void ); - -/** -** Name: vm_mkuvm -** -** Create the page table hierarchy for a user process -*/ -pde_t *vm_mkuvm( void ); - -/** -** Name: vm_set_kvm -** -** Switch the page table register to the kernel's page directory -*/ -void vm_set_kvm( void ); - -/** -** Name: vm_set_uvm -** -** Switch the page table register to the page directory for a user process. -** -** @param p The PCB of the user process -*/ -void vm_set_uvm( pcb_t *p ); - -/** -** Name: vm_add -** -** Add pages to the page hierarchy for a process, copying data into -** them if necessary. -** -** @param pdir Pointer to the page directory to modify -** @param wr "Writable" flag for the PTE -** @param sys "System" flag for the PTE -** @param va Starting VA of the range -** @param size Amount of physical memory to allocate -** @param data Pointer to data to copy, or NULL -** @param bytes Number of bytes to copy -** -** @return status of the allocation attempt -*/ -int vm_add( pde_t *pdir, bool_t wr, bool_t sys, - void *va, uint32_t size, char *data, uint32_t bytes ); - -/** -** Name: vm_free -** -** Deallocate a page table hierarchy and all physical memory frames -** in the user portion. -** -** @param pdir Pointer to the page directory -*/ -void vm_free( pde_t *pdir ); - -/* -** Name: vm_map -** -** Create PTEs for virtual addresses starting at 'va' that refer to -** physical addresses in the range [pa, pa+size-1]. We aren't guaranteed -** that va is page-aligned. -** -** @param pdir Page directory for this address space -** @param va The starting virtual address -** @param size Length of the range to be mapped -** @param pa The starting physical address -** @param perm Permission bits for the PTEs -*/ -int vm_map( pde_t *pdir, void *va, uint_t size, uint_t pa, int perm ); - -/** -** Name: vm_uvmdup -** -** Create a duplicate of the user portio of an existing page table -** hierarchy. We assume that the "new" page directory exists and -** the system portions of it should not be touched. -** -** @param old Existing page directory -** @param new New page directory -** -** @return status of the duplication attempt -*/ -int vm_uvmdup( pde_t *old, pde_t *new ); - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/vmtables.h b/kernel/old/include/vmtables.h deleted file mode 100644 index 17f6e0a..0000000 --- a/kernel/old/include/vmtables.h +++ /dev/null @@ -1,43 +0,0 @@ -/** -** @file vmtables.h -** -** @author CSCI-452 class of 20245 -** -** @brief Predefined VM tables -*/ - -#ifndef VMTABLES_H_ -#define VMTABLES_H_ - -#include -#include -#include - -#ifndef ASM_SRC - -/* -** Initial page directory, for when the kernel is starting up -** -** we use large (4MB) pages here to allow us to use a one-level -** paging hierarchy; the kernel will create a new page table -** hierarchy once memory is initialized -*/ -extern pde_t firstpdir[]; - -/* -** "Identity" page map table. -** -** This just maps the first 4MB of physical memory. It is initialized -** in vm_init(). -*/ -extern pte_t id_map[]; - -/* -** Kernel address mappings, present in every page table -*/ -extern mapping_t kmap[]; -extern const uint32_t n_kmap; - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/x86/arch.h b/kernel/old/include/x86/arch.h deleted file mode 100644 index 113c76b..0000000 --- a/kernel/old/include/x86/arch.h +++ /dev/null @@ -1,303 +0,0 @@ -/* -** @file arch.h -** -** @author Warren R. Carithers -** @author K. Reek -** -** Definitions of constants and macros for use -** with the x86 architecture and registers. -** -*/ - -#ifndef X86ARCH_H_ -#define X86ARCH_H_ - -/* -** Video stuff -*/ -#define VID_BASE_ADDR 0xB8000 - -/* -** Memory management -*/ -#define SEG_PRESENT 0x80 -#define SEG_PL_0 0x00 -#define SEG_PL_1 0x20 -#define SEG_PL_2 0x40 -#define SEG_PL_3 0x50 -#define SEG_SYSTEM 0x00 -#define SEG_NON_SYSTEM 0x10 -#define SEG_32BIT 0x04 -#define DESC_IGATE 0x06 - -/* -** Exceptions -*/ -#define N_EXCEPTIONS 256 - -/* -** Bit definitions in registers -** -** See IA-32 Intel Architecture SW Dev. Manual, Volume 3: System -** Programming Guide, page 2-8. -*/ - -/* -** EFLAGS -*/ -#define EFL_RSVD 0xffc00000 /* reserved */ -#define EFL_MB0 0x00008020 /* must be zero */ -#define EFL_MB1 0x00000002 /* must be 1 */ - -#define EFL_ID 0x00200000 -#define EFL_VIP 0x00100000 -#define EFL_VIF 0x00080000 -#define EFL_AC 0x00040000 -#define EFL_VM 0x00020000 -#define EFL_RF 0x00010000 -#define EFL_NT 0x00004000 -#define EFL_IOPL 0x00003000 -#define EFL_OF 0x00000800 -#define EFL_DF 0x00000400 -#define EFL_IF 0x00000200 -#define EFL_TF 0x00000100 -#define EFL_SF 0x00000080 -#define EFL_ZF 0x00000040 -#define EFL_AF 0x00000010 -#define EFL_PF 0x00000004 -#define EFL_CF 0x00000001 - -/* -** CR0, CR1, CR2, CR3, CR4 -** -** IA-32 V3, page 2-12. -*/ -#define CR0_RSVD 0x1ffaffc0 -#define CR0_PG 0x80000000 -#define CR0_CD 0x40000000 -#define CR0_NW 0x20000000 -#define CR0_AM 0x00040000 -#define CR0_WP 0x00010000 -#define CR0_NE 0x00000020 -#define CR0_ET 0x00000010 -#define CR0_TS 0x00000008 -#define CR0_EM 0x00000004 -#define CR0_MP 0x00000002 -#define CR0_PE 0x00000001 - -#define CR1_RSVD 0xffffffff - -#define CR2_RSVD 0x00000000 -#define CR2_PF_LIN_ADDR 0xffffffff - -#define CR3_RSVD 0x00000fe7 -#define CR3_PD_BASE 0xfffff000 -#define CR3_PCD 0x00000010 -#define CR3_PWT 0x00000008 - -#define CR4_RSVD 0xfd001000 -#define CR4_UINT 0x02000000 -#define CR4_PKS 0x01000000 -#define CR4_CET 0x00800000 -#define CR4_PKE 0x00400000 -#define CR4_SMAP 0x00200000 -#define CR4_SMEP 0x00100000 -#define CR4_KL 0x00080000 -#define CR4_OSXS 0x00040000 -#define CR4_PCID 0x00020000 -#define CR4_FSGS 0x00010000 -#define CR4_SMXE 0x00004000 -#define CR4_VMXE 0x00002000 -#define CR4_LA57 0x00001000 -#define CR4_UMIP 0x00000800 -#define CR4_OSXMMEXCPT 0x00000400 -#define CR4_OSFXSR 0x00000200 -#define CR4_PCE 0x00000100 -#define CR4_PGE 0x00000080 -#define CR4_MCE 0x00000040 -#define CR4_PAE 0x00000020 -#define CR4_PSE 0x00000010 -#define CR4_DE 0x00000008 -#define CR4_TSD 0x00000004 -#define CR4_PVI 0x00000002 -#define CR4_VME 0x00000001 - -/* -** PMode segment selector field masks -** -** IA-32 V3, page 3-8. -*/ -#define SEG_SEL_IX_MASK 0xfff8 -#define SEG_SEL_TI_MASK 0x0004 -#define SEG_SEL_RPL_MASK 0x0003 - -/* -** Segment descriptor bytes -** -** IA-32 V3, page 3-10. -** -** Bytes: -** 0, 1: segment limit 15:0 -** 2, 3: base address 15:0 -** 4: base address 23:16 -** 7: base address 31:24 -*/ - -/* -** Byte 5: access control bits -** 7: present -** 6-5: DPL -** 4: system/user -** 3-0: type -*/ -#define SEG_ACCESS_P_MASK 0x80 -# define SEG_PRESENT 0x80 -# define SEG_NOT_PRESENT 0x00 - -#define SEG_ACCESS_DPL_MASK 0x60 -# define SEG_DPL_0 0x00 -# define SEG_DPL_1 0x20 -# define SEG_DPL_2 0x40 -# define SEG_DPL_3 0x60 - -#define SEG_ACCESS_S_MASK 0x10 -# define SEG_SYSTEM 0x00 -# define SEG_NON_SYSTEM 0x10 - -#define SEG_TYPE_MASK 0x0f -# define SEG_DATA_A_BIT 0x1 -# define SEG_DATA_W_BIT 0x2 -# define SEG_DATA_E_BIT 0x4 -# define SEG_CODE_A_BIT 0x1 -# define SEG_CODE_R_BIT 0x2 -# define SEG_CODE_C_BIT 0x4 -# define SEG_DATA_RO 0x0 -# define SEG_DATA_ROA 0x1 -# define SEG_DATA_RW 0x2 -# define SEG_DATA_RWA 0x3 -# define SEG_DATA_RO_XD 0x4 -# define SEG_DATA_RO_XDA 0x5 -# define SEG_DATA_RW_XW 0x6 -# define SEG_DATA_RW_XWA 0x7 -# define SEG_CODE_XO 0x8 -# define SEG_CODE_XOA 0x9 -# define SEG_CODE_XR 0xa -# define SEG_CODE_XRA 0xb -# define SEG_CODE_XO_C 0xc -# define SEG_CODE_XO_CA 0xd -# define SEG_CODE_XR_C 0xe -# define SEG_CODE_XR_CA 0xf - -/* -** Byte 6: sizes -** 7: granularity -** 6: d/b -** 5: long mode -** 4: available! -** 3-0: upper 4 bits of limit -** 7: base address 31:24 -*/ -#define SEG_SIZE_G_MASK 0x80 -# define SEG_GRAN_BYTE 0x00 -# define SEG_GRAN_4KBYTE 0x80 - -#define SEG_SIZE_D_B_MASK 0x40 -# define SEG_DB_16BIT 0x00 -# define SEG_DB_32BIT 0x40 - -#define SEG_SIZE_L_MASK 0x20 -# define SEG_L_64BIT 0x20 -# define SEG_L_32BIT 0x00 - -#define SEG_SIZE_AVL_MASK 0x10 - -#define SEG_SIZE_LIM_19_16_MASK 0x0f - - -/* -** System-segment and gate-descriptor types -** -** IA-32 V3, page 3-15. -*/ - // type 0: reserved -#define SEG_SYS_16BIT_TSS_AVAIL 0x1 -#define SEG_SYS_LDT 0x2 -#define SEG_SYS_16BIT_TSS_BUSY 0x3 -#define SEG_SYS_16BIT_CALL_GATE 0x4 -#define SEG_SYS_TASK_GATE 0x5 -#define SEG_SYS_16BIT_INT_GATE 0x6 -#define SEG_SYS_16BIT_TRAP_GATE 0x7 - // type 8: reserved -#define SEG_SYS_32BIT_TSS_AVAIL 0x9 - // type A: reserved -#define SEG_SYS_32BIT_TSS_BUSY 0xb -#define SEG_SYS_32BIT_CALL_GATE 0xc - // type D: reserved -#define SEG_SYS_32BIT_INT_GATE 0xe -#define SEG_SYS_32BIT_TRAP_GATE 0xf - -/* -** IDT Descriptors -** -** IA-32 V3, page 5-13. -** -** All have a segment selector in bytes 2 and 3; Task Gate descriptors -** have bytes 0, 1, 4, 6, and 7 reserved; others have bytes 0, 1, 6, -** and 7 devoted to the 16 bits of the Offset, with the low nybble of -** byte 4 reserved. -*/ -#define IDT_PRESENT 0x8000 -#define IDT_DPL_MASK 0x6000 -# define IDT_DPL_0 0x0000 -# define IDT_DPL_1 0x2000 -# define IDT_DPL_2 0x4000 -# define IDT_DPL_3 0x6000 -#define IDT_GATE_TYPE 0x0f00 -# define IDT_TASK_GATE 0x0500 -# define IDT_INT16_GATE 0x0600 -# define IDT_INT32_GATE 0x0e00 -# define IDT_TRAP16_GATE 0x0700 -# define IDT_TRAP32_GATE 0x0f00 - -/* -** Interrupt vectors -*/ - -// predefined by the architecture -#define VEC_DIVIDE_ERROR 0x00 -#define VEC_DEBUG_EXCEPTION 0x01 -#define VEC_NMI_INTERRUPT 0x02 -#define VEC_BREAKPOINT 0x03 -#define VEC_OVERFLOW 0x04 -#define VEC_BOUND_RANGE_EXCEEDED 0x05 -#define VEC_INVALID_OPCODE 0x06 -#define VEC_DEVICE_NOT_AVAILABLE 0x07 -#define VEC_DOUBLE_FAULT 0x08 -#define VEC_COPROCESSOR_OVERRUN 0x09 -#define VEC_INVALID_TSS 0x0a -#define VEC_SEGMENT_NOT_PRESENT 0x0b -#define VEC_STACK_FAULT 0x0c -#define VEC_GENERAL_PROTECTION 0x0d -#define VEC_PAGE_FAULT 0x0e -// 0x0f is reserved - unused -#define VEC_FPU_ERROR 0x10 -#define VEC_ALIGNMENT_CHECK 0x11 -#define VEC_MACHINE_CHECK 0x12 -#define VEC_SIMD_FP_EXCEPTION 0x13 -#define VEC_VIRT_EXCEPTION 0x14 -#define VEC_CTRL_PROT_EXCEPTION 0x15 -// 0x16 through 0x1f are reserved - -// 0x20 through 0xff are user-defined, non-reserved - -// IRQ0 through IRQ15 will use vectors 0x20 through 0x2f -#define VEC_TIMER 0x20 -#define VEC_KBD 0x21 -#define VEC_COM2 0x23 -#define VEC_COM1 0x24 -#define VEC_PARALLEL 0x25 -#define VEC_FLOPPY 0x26 -#define VEC_MYSTERY 0x27 -#define VEC_MOUSE 0x2c - -#endif diff --git a/kernel/old/include/x86/bios.h b/kernel/old/include/x86/bios.h deleted file mode 100644 index a19e570..0000000 --- a/kernel/old/include/x86/bios.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -** @file bios.h -** -** @author Warren R. Carithers -** -** BIOS-related declarations -*/ - -#ifndef BIOS_H_ -#define BIOS_H_ - -/* -** BIOS-related memory addresses -*/ - -#define BIOS_BDA 0x0400 - -/* -** Selected BIOS interrupt numbers -*/ - -#define BIOS_TIMER 0x08 -#define BIOS_KBD 0x09 -#define BIOS_VIDEO 0x10 -#define BIOS_EQUIP 0x11 -#define BIOS_MSIZ 0x12 -#define BIOS_DISK 0x13 -#define BIOS_SERIAL 0x14 -#define BIOS_MISC 0x15 -#define BIOS_KBDSVC 0x16 -#define BIOS_PRTSVC 0x17 -#define BIOS_BOOT 0x19 -#define BIOS_RTCPCI 0x1a - -// BIOS video commands (AH) -#define BV_W_ADV 0x0e - -// BIOS disk commands (AH) -#define BD_RESET 0x00 -#define BD_CHECK 0x01 -#define BD_RDSECT 0x02 -#define BD_WRSECT 0x03 -#define BD_PARAMS 0x08 - -// BIOS disk commands with parameters (AX) -#define BD_READ(n) ((BD_RDSECT << 8) | (n)) -#define BD_READ1 0x0201 - -// CMOS ports (used for masking NMIs) -#define CMOS_ADDR 0x70 -#define CMOS_DATA 0x71 - -// important related commands -#define NMI_ENABLE 0x00 -#define NMI_DISABLE 0x80 - -/* -** Physical Memory Map Table (0000:2D00 - 0000:7c00) -** -** Primarily used with the BIOS_MISC interrupt -*/ -#define MMAP_SEG 0x02D0 -#define MMAP_DISP 0x0000 -#define MMAP_ADDR ((MMAP_SEG << 4) + MMAP_DISP) -#define MMAP_SECTORS 0x0a - -#define MMAP_ENT 24 /* bytes per entry */ -#define MMAP_MAX_ENTS (BOOT_ADDR - MMAP_ADDR - 4) / 24 - -#define MMAP_CODE 0xE820 /* int 0x15 code */ -#define MMAP_MAGIC_NUM 0x534D4150 /* for 0xE820 interrupt */ - -#endif diff --git a/kernel/old/include/x86/ops.h b/kernel/old/include/x86/ops.h deleted file mode 100644 index ad795b9..0000000 --- a/kernel/old/include/x86/ops.h +++ /dev/null @@ -1,443 +0,0 @@ -/** -** @file ops.h -** -** @author Warren R. Carithers -** -** @brief Inline escapes to assembly for efficiency -** -** Inspiration from: -** Martins Mozeiko, https://gist.github.com/mmozeiko/f68ad2546bd6ab953315 -** MIT's xv6, https://github.com/mit-pdos/xv6-public -** -** Note: normally, GCC doesn't inline unless the optimization level is -** over 1. This can be forced by adding -** -** __attribute__((always_inline)) -** -** after the parameter list on each declaration. This is enabled by -** defining the compile-time CPP symbol FORCE_INLINING. -*/ - -#ifndef OPS_H_ -#define OPS_H_ - -#include - -#ifndef ASM_SRC - -// control "forced" inlining -#ifdef FORCE_INLINING -#define OPSINLINED __attribute__((always_inline)) -#else -#define OPSINLINED /* no-op */ -#endif /* FORCE_INLINING */ - -/**************************** -** Data movement -****************************/ - -/** -** Block move functions -** -** Variations: movsb(), movsl(), movsq() -** -** Description: Copy from source buffer to destination buffer -** -** @param dst Destination buffer -** @param src Source buffer -** @param len Byte count -*/ -static inline void -movsb( void* dst, const void* src, uint32_t len ) OPSINLINED -{ - __asm__ __volatile__( "cld; rep movsb" - : "+D"(dst), "+S"(src), "+c"(len) - : : "memory" ); -} - -static inline void -movsw( void* dst, const void* src, uint32_t len ) OPSINLINED -{ - __asm__ __volatile__( "cld; rep movsw" - : "+D"(dst), "+S"(src), "+c"(len) - : : "memory" ); -} - -static inline void -movsl( void* dst, const void* src, uint32_t len ) OPSINLINED -{ - __asm__ __volatile__( "cld; rep movsl" - : "+D"(dst), "+S"(src), "+c"(len) - : : "memory" ); -} - -static inline void -movsq( void* dst, const void* src, uint32_t len ) OPSINLINED -{ - __asm__ __volatile__( "cld; rep movsq" - : "+D"(dst), "+S"(src), "+c"(len) - : : "memory" ); -} - -/** -** Block store functions -** -** Variations: stosb(), stosw(), stosl() -** -** Description: Store a specific value into destination buffer -** -** @param dst Destination buffer -** @param val Data to copy -** @param len Byte count -*/ -static inline void -stosb( void *dst, uint8_t val, uint32_t len ) OPSINLINED -{ - __asm__ __volatile__( "cld; rep stosb" - : "=D" (dst), "=c" (len) - : "0" (dst), "1" (len), "a" (val) - : "memory", "cc" ); -} - -static inline void -stosw( void *dst, uint16_t val, uint32_t len ) OPSINLINED -{ - __asm__ __volatile__( "cld; rep stos2" - : "=D" (dst), "=c" (len) - : "0" (dst), "1" (len), "a" (val) - : "memory", "cc" ); -} - -static inline void -stosl( void *dst, uint32_t val, uint32_t len ) OPSINLINED -{ - __asm__ __volatile__( "cld; rep stosl" - : "=D" (dst), "=c" (len) - : "0" (dst), "1" (len), "a" (val) - : "memory", "cc" ); -} - -/**************************** -** Special register access -****************************/ - -/** -** Register read functions -** -** Variations: r_cr0(), r_cr2(), r_cr3(), r_cr4(), r_eflags(), -** r_ebp(), r_esp() -** -** Description: Reads the register indicated by its name -** -** @return Contents of the register -*/ -static inline uint32_t -r_cr0( void ) OPSINLINED -{ - uint32_t val; - __asm__ __volatile__( "movl %%cr0,%0" : "=r" (val) ); - return val; -} - -static inline uint32_t -r_cr2( void ) OPSINLINED -{ - uint32_t val; - __asm__ __volatile__( "movl %%cr2,%0" : "=r" (val) ); - return val; -} - -static inline uint32_t -r_cr3( void ) OPSINLINED -{ - uint32_t val; - __asm__ __volatile__( "movl %%cr3,%0" : "=r" (val) ); - return val; -} - -static inline uint32_t -r_cr4( void ) OPSINLINED -{ - uint32_t val; - __asm__ __volatile__( "movl %%cr4,%0" : "=r" (val) ); - return val; -} - -static inline uint32_t -r_eflags(void) OPSINLINED -{ - uint32_t val; - __asm__ __volatile__( "pushfl; popl %0" : "=r" (val) ); - return val; -} - -static inline uint32_t -r_ebp(void) OPSINLINED -{ - uint32_t val; - __asm__ __volatile__( "movl %%ebp,%0" : "=r" (val) ); - return val; -} - -static inline uint32_t -r_esp(void) OPSINLINED -{ - uint32_t val; - __asm__ __volatile__( "movl %%esp,%0" : "=r" (val) ); - return val; -} - -/** -** Register write functions -** -** Variations: w_cr0(), w_cr2(), w_cr3(), w_cr4(), w_eflags() -** -** Description: Writes a value into the CR indicated by its name -*/ -static inline void -w_cr0( uint32_t val ) OPSINLINED -{ - __asm__ __volatile__( "movl %0,%%cr0" : : "r" (val) ); -} - -static inline void -w_cr2( uint32_t val ) OPSINLINED -{ - __asm__ __volatile__( "movl %0,%%cr2" : : "r" (val) ); -} - -static inline void -w_cr3( uint32_t val ) OPSINLINED -{ - __asm__ __volatile__( "movl %0,%%cr3" : : "r" (val) ); -} - -static inline void -w_cr4( uint32_t val ) OPSINLINED -{ - __asm__ __volatile__( "movl %0,%%cr4" : : "r" (val) ); -} - -static inline void -w_eflags(uint32_t eflags) OPSINLINED -{ - __asm__ __volatile__( "pushl %0; popfl" : : "r" (eflags) ); -} - -/** -** Descriptor table load functions -** -** Variations: w_gdt(), w_idt() -** -** Description: Load an address into the specified processor register -** -** @param addr The value to be loaded into the register -*/ -static inline void -w_gdt( void *addr ) OPSINLINED -{ - __asm__ __volatile__( "lgdt (%0)" : : "r" (addr) ); -} - -static inline void -w_idt( void *addr ) OPSINLINED -{ - __asm__ __volatile__( "lidt (%0)" : : "r" (addr) ); -} - -/** -** CPU ID access -** -** Description: Retrieve CPUID information -** -** @param op Value to be placed into %eax for the operation -** @param ap Pointer to where %eax contents should be saved, or NULL -** @param bp Pointer to where %ebx contents should be saved, or NULL -** @param cp Pointer to where %ecx contents should be saved, or NULL -** @param dp Pointer to where %edx contents should be saved, or NULL -*/ -static inline void -cpuid( uint32_t op, uint32_t *ap, uint32_t *bp, - uint32_t *cp, uint32_t *dp ) OPSINLINED -{ - uint32_t eax, ebx, ecx, edx; - __asm__ __volatile__( "cpuid" - : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) - : "a" (op) ); - - if( ap ) *ap = eax; - if( bp ) *bp = ebx; - if( cp ) *cp = ecx; - if( dp ) *dp = edx; -} - -/**************************** -** TLB management -****************************/ - -/** -** TLB invalidation for one page -** -** Description: Invalidate the TLB entry for an address -** -** @param addr An address within the page to be flushed -*/ -static inline void -invlpg( uint32_t addr ) OPSINLINED -{ - __asm__ __volatile__( "invlpg (%0)" : : "r" (addr) : "memory" ); -} - -/** -** TLB invalidation for all pages -** -** Description: Flush all entries from the TLB -** -** We do this by changing CR3. -*/ -static inline void -flushtlb( void ) OPSINLINED -{ - uint32_t cr3; - __asm__ __volatile__( "movl %%cr3,%0" : "=r" (cr3) ); - __asm__ __volatile__( "movl %0,%%cr2" : : "r" (cr3) ); -} - -/**************************** -** I/O instructions -****************************/ - -/** -** Name: inN -** -** Variations: inb(), inw(), inl() -** -** Description: Read some amount of data from the supplied I/O port -** -** @param port The i/o port to read from -** -** @return The data read from the specified port -*/ -static inline uint8_t -inb( int port ) OPSINLINED -{ - uint8_t data; - __asm__ __volatile__( "inb %w1,%0" : "=a" (data) : "d" (port) ); - return data; -} - -static inline uint16_t -inw( int port ) OPSINLINED -{ - uint16_t data; - __asm__ __volatile__( "inw %w1,%0" : "=a" (data) : "d" (port) ); - return data; -} - -static inline uint32_t -inl( int port ) OPSINLINED -{ - uint32_t data; - __asm__ __volatile__( "inl %w1,%0" : "=a" (data) : "d" (port) ); - return data; -} - -/** -** Name: outN -** -** Variations: outb(), outw(), outl() -** -** Description: Write some data to the specified I/O port -** -** @param port The i/o port to write to -** @param data The data to be written to the port -** -** @return The data read from the specified port -*/ -static inline void -outb( int port, uint8_t data ) OPSINLINED -{ - __asm__ __volatile__( "outb %0,%w1" : : "a" (data), "d" (port) ); -} - -static inline void -outw( int port, uint16_t data ) OPSINLINED -{ - __asm__ __volatile__( "outw %0,%w1" : : "a" (data), "d" (port) ); -} - -static inline void -outl( int port, uint32_t data ) OPSINLINED -{ - __asm__ __volatile__( "outl %0,%w1" : : "a" (data), "d" (port) ); -} - -/**************************** -** Miscellaneous instructions -****************************/ - -/** -** Name: breakpoint -** -** Description: Cause a breakpoint interrupt for debugging purposes -*/ -static inline void -breakpoint( void ) OPSINLINED -{ - __asm__ __volatile__( "int3" ); -} - -/** -** Name: get_ra -** -** Description: Get the return address for the calling function -** (i.e., where whoever called us will go back to) -** -** @return The address the calling routine will return to as a uint32_t -*/ -static inline uint32_t -get_ra( void ) OPSINLINED -{ - uint32_t val; - __asm__ __volatile__( "movl 4(%%ebp),%0" : "=r" (val) ); - return val; -} - -/** -** Name: ev_wait -** -** Description: Pause until something happens -*/ -static inline void -ev_wait( void ) OPSINLINED -{ - __asm__ __volatile__( "sti ; hlt" ); -} - - -/** -** Name: xchgl -** -** Description: Perform an atomic exchange with memory -** -** @param addr Memory location to be modified -** @param data Data to exchange -** -** @return The old contents of the memory location -*/ -static inline uint32_t -xchgl( volatile uint32_t *addr, uint32_t data ) OPSINLINED -{ - uint32_t old; - - // + indicates a read-modify-write operand - __asm__ __volatile__( "lock; xchgl %0, %1" - : "+m" (*addr), "=a" (old) - : "1" (data) - : "cc"); - return old; -} - -#endif /* !ASM_SRC */ - -#endif diff --git a/kernel/old/include/x86/pic.h b/kernel/old/include/x86/pic.h deleted file mode 100644 index d4fa93b..0000000 --- a/kernel/old/include/x86/pic.h +++ /dev/null @@ -1,139 +0,0 @@ -/** -** @file pic.h -** -** @author Warren R. Carithers -** @author K. Reek -** -** Definitions of constants and macros for the Intel 8259 Programmable -** Interrupt Controller. -** -*/ - -#ifndef X86PIC_H_ -#define X86PIC_H_ - -/* -** Our expected configuration is two PICs, with the secondary connected -** through the IRQ2 pin of the primary. -*/ - -/* -** Port addresses for the command port and interrupt mask register port -** for both the primary and secondary PICs. -*/ -#define PIC1_CMD 0x20 // primary command -#define PIC1_DATA (PIC1_CMD + 1) // primary data / int mask register -#define PIC2_CMD 0xA0 // secondary command -#define PIC2_DATA (PIC2_CMD + 1) // secondary data / int mask register - -/* -** Initialization Command Word (ICW) definitions -** -** Initialization sequence: -** ICW1 Init command is sent to each command port. -** ICW2 vector commands are sent to the data ports. -** If "cascade mode" was selected, send ICW3 commands to the data ports. -** If "need ICW4" was selected, send ICW4 commands to the data ports. -** -** Following that sequence, the PIC is ready to accept interrupts; -** it will also accept Output Command Words (OCWs) to the data ports. -** -** PIC1_* defines are intended for the primary PIC -** PIC2_* defines are intended for the secondary PIC -** PIC_* defines are sent to both PICs -*/ - -/* -** ICW1: initialization, send to command port -*/ -#define PIC_CW1_INIT 0x10 // start initialization sequence -#define PIC_CW1_NEED4 0x01 // ICW4 will also be set -#define PIC_CW1_SINGLE 0x02 // select single (vs. cascade) mode -#define PIC_CW1_INTVAL 0x04 // set call interval to 4 (vs. 8) -#define PIC_CW1_LEVEL 0x08 // use level-triggered mode (vs. edge) - -/* -** ICW2: interrupt vector base offsets, send to data port -*/ -#define PIC1_CW2_VECBASE 0x20 // IRQ0 int vector number -#define PIC2_CW2_VECBASE 0x28 // IRQ8 int vector number - -/* -** ICW3: secondary::primary attachment, send to data port -*/ -#define PIC1_CW3_SEC_IRQ2 0x04 // bit mask: secondary is on pin 2 -#define PIC2_CW3_SEC_ID 0x02 // integer: secondary id - -/* -** ICW4: operating mode, send to data port -*/ -#define PIC_CW4_PM86 0x01 // 8086 mode (vs. 8080/8085) -#define PIC_CW4_AUTOEOI 0x02 // do auto eoi's -#define PIC_CW4_UNBUF 0x00 // unbuffered mode -#define PIC_CW4_SEC_BUF 0x08 // put secondary in buffered mode -#define PIC_CW4_PRI_BUF 0x0C // put primary in buffered mode -#define PIC_CW4_SFNMODE 0x10 // "special fully nested" mode - -/* -** Operation Control Words (OCWs) -** -** After the init sequence, can send these -*/ - -/* -** OCW1: interrupt mask; send to data port -*/ -#define PIC_MASK_NONE 0x00 // allow all interrupts -#define PIC_MASK_NO_IRQ0 0x01 // prevent IRQ0 interrupts -#define PIC_MASK_NO_IRQ1 0x02 // prevent IRQ1 interrupts -#define PIC_MASK_NO_IRQ2 0x04 // prevent IRQ2 interrupts -#define PIC_MASK_NO_IRQ3 0x08 // prevent IRQ3 interrupts -#define PIC_MASK_NO_IRQ4 0x10 // prevent IRQ4 interrupts -#define PIC_MASK_NO_IRQ5 0x20 // prevent IRQ5 interrupts -#define PIC_MASK_NO_IRQ6 0x40 // prevent IRQ6 interrupts -#define PIC_MASK_NO_IRQ7 0x80 // prevent IRQ7 interrupts -#define PIC_MASK_ALL 0xff // prevent all interrupts - -/* -** OCW2: EOI control, interrupt level; send to command port -*/ -#define PIC_LVL_0 0x00 // act on IRQ level 0 -#define PIC_LVL_1 0x01 // act on IRQ level 1 -#define PIC_LVL_2 0x02 // act on IRQ level 2 -#define PIC_LVL_3 0x03 // act on IRQ level 3 -#define PIC_LVL_4 0x04 // act on IRQ level 4 -#define PIC_LVL_5 0x05 // act on IRQ level 5 -#define PIC_LVL_6 0x06 // act on IRQ level 6 -#define PIC_LVL_7 0x07 // act on IRQ level 7 - -#define PIC_EOI_NON_SPEC 0x20 // non-specific EOI command -# define PIC_EOI PIC_EOI_NON_SPEC - -#define PIC_EOI_SPEC 0x60 // specific EOI command -# define PIC_SEOI PIC_EOI_SPEC -# define PIC_SEOI_LVL0 (PIC_EOI_SPEC | PIC_LVL_0) -# define PIC_SEOI_LVL1 (PIC_EOI_SPEC | PIC_LVL_1) -# define PIC_SEOI_LVL2 (PIC_EOI_SPEC | PIC_LVL_2) -# define PIC_SEOI_LVL3 (PIC_EOI_SPEC | PIC_LVL_3) -# define PIC_SEOI_LVL4 (PIC_EOI_SPEC | PIC_LVL_4) -# define PIC_SEOI_LVL5 (PIC_EOI_SPEC | PIC_LVL_5) -# define PIC_SEOI_LVL6 (PIC_EOI_SPEC | PIC_LVL_6) -# define PIC_SEOI_LVL7 (PIC_EOI_SPEC | PIC_LVL_7) - -#define PIC_EOI_ROT_NONSP 0xa0 // rotate on non-spec EOI cmd -#define PIC_EOI_SET_ROT_AUTO 0x80 // set "rotate in auto EOI mode" -#define PIC_EOI_CLR_ROT_AUTO 0x00 // clear "rotate in auto EOI mode" -#define PIC_EOI_ROT_SPEC 0xe0 // rotate on spec EOI cmd (+ level) -#define PIC_EOI_SET_PRIO 0xc0 // set priority (+ level) -#define PIC_EOI_NOP 0x40 // no operation - -/* -** OCW3: read requests, special mask mode; send to command port -*/ -#define PIC_READIRR 0x0a // read the IR register -#define PIC_READISR 0x0b // read the IS register -#define PIC_POLL 0x0c // poll -#define PIC_MASK_RESET 0x48 // reset special mask mode -#define PIC_MASK_SET 0x68 // set special mask mode - -#endif diff --git a/kernel/old/include/x86/pit.h b/kernel/old/include/x86/pit.h deleted file mode 100644 index 269fcec..0000000 --- a/kernel/old/include/x86/pit.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -** @file pit.h -** -** @author Warren R. Carithers -** @author K. Reek -** -** Definitions of constants and macros for the -** Intel 8254 Programmable Interval Timer -** -*/ - -#ifndef X86PIT_H_ -#define X86PIT_H_ - - -/* -** Hardware timer (Intel 8254 Programmable Interval Timer) -** -** Control word layout: -** -** Bit 7 6 | 5 4 | 3 2 1 | 0 -** Field SC1 SC0|RW1 RW0|M2 M1 M0 |BCD -** -** SC - select counter -** RW - read/write -** M - mode -** BCD - binary or BCD counter -*/ - -/* Frequency settings */ -#define PIT_DEFAULT_TICKS_PER_SECOND 18 // actually 18.2065Hz -#define PIT_DEFAULT_MS_PER_TICK (1000/PIT_DEFAULT_TICKS_PER_SECOND) -#define PIT_FREQ 1193182 // clock cycles/sec - -/* Port assignments */ -#define PIT_BASE_PORT 0x40 // I/O port for the timer -# define PIT_0_PORT (PIT_BASE_PORT) -# define PIT_1_PORT (PIT_BASE_PORT+1) -# define PIT_2_PORT (PIT_BASE_PORT+2) -# define PIT_CONTROL_PORT (PIT_BASE_PORT+3) - -/* BCD field */ -#define PIT_USE_DECIMAL 0x00 // 16-bit binary counter (default) -#define PIT_USE_BCD 0x01 // BCD counter - -/* Timer modes */ -#define PIT_MODE_0 0x00 // int on terminal count -#define PIT_MODE_1 0x02 // one-shot -#define PIT_MODE_2 0x04 // divide-by-N -#define PIT_MODE_3 0x06 // square-wave -#define PIT_MODE_4 0x08 // software strobe -#define PIT_MODE_5 0x0a // hardware strobe - -/* Timer 0 settings */ -#define PIT_0_SELECT 0x00 // select timer 0 -#define PIT_0_LOAD 0x30 // load LSB, then MSB -#define PIT_0_NDIV PIT_MODE_2 // divide-by-N counter -#define PIT_0_SQUARE PIT_MODE_3 // square-wave mode -#define PIT_0_ENDSIGNAL 0x00 // assert OUT at end of count - -/* Timer 1 settings */ -#define PIT_1_SELECT 0x40 // select timer 1 -#define PIT_1_READ 0x30 // read/load LSB then MSB -#define PIT_1_RATE 0x06 // square-wave, for USART - -/* Timer 2 settings */ -#define PIT_2_SELECT 0x80 // select timer 1 -#define PIT_2_READ 0x30 // read/load LSB then MSB -#define PIT_2_RATE 0x06 // square-wave, for USART - -/* Timer read-back */ -#define PIT_READBACK 0xc0 // perform a read-back -#define PIT_RB_NOT_COUNT 0x20 // don't latch the count -#define PIT_RB_NOT_STATUS 0x10 // don't latch the status -#define PIT_RB_CHAN_2 0x08 // read back channel 2 -#define PIT_RB_CHAN_1 0x04 // read back channel 1 -#define PIT_RB_CHAN_0 0x02 // read back channel 0 -#define PIT_RB_ACCESS_MASK 0x30 // access mode field -#define PIT_RB_OP_MASK 0x0e // oper mode field -#define PIT_RB_BCD_MASK 0x01 // BCD mode field - -#endif diff --git a/kernel/old/include/x86/uart.h b/kernel/old/include/x86/uart.h deleted file mode 100644 index 0c6194b..0000000 --- a/kernel/old/include/x86/uart.h +++ /dev/null @@ -1,349 +0,0 @@ -/* -** @file uart.h -** -** @author M. Reek -** @authors K. Reek, Warren R. Carithers -** -** Definitions for a 16540/16550 compatible UART. Definitions are taken -** from datasheets for the National Semiconductor INS8250, NS16450, and -** NS16550 UART chips, and the PC87309 Super I/O legacy peripheral chip. -** -** The naming convention is UAx_yyy_zzzzz. "x" is either 4 or 5 (see below), -** "yyy" is the name of the register to which this value applies, and -** "zzzzz" is the name of the value or field. -** -** The UA4 prefix denotes 16540 compatible functions, available in both -** chips. The UA5 prefix denotes 16550-only functions (primarily the FIFOs). -** -** For many items there are two names: one short one that matches the name -** in the chip manual, and another that is more readable. -*/ - -#ifndef UART_H -#define UART_H - -/********************************************************************* -***************************** I/O PORTS ****************************** -*********************************************************************/ - -/* -** Base port number assigned to the device -*/ -#define UA4_COM1_PORT 0x3f8 -#define UA4_COM2_PORT 0x2f8 -#define UA4_COM3_PORT 0x3e8 -#define UA4_COM4_PORT 0x2e8 - -// short name for the one we'll use -#define UA4_PORT UA4_COM1_PORT -#define UA5_PORT UA4_COM1_PORT - -/* -** Registers -** -** The 164x0 chips have the following registers. The (RO) and (WO) -** suffixes indicate read-only and write-only access. -** -** Index Register(s) -** ===== ========================================= -** 0 Receiver Data (RO), Transmitter Data (WO) -** 1 Interrupt Enable -** 2 Interrupt ID (RO), FIFO Control (WO) -** 3 Line Control, Divisor Latch -** 4 Modem Control -** 5 Line Status -** 6 Modem Status -** 7 Scratch -** -** Registers indices are relative to the base I/O port for the -** specific UART port being used (e.g., for COM1, the port addresses -** are 0x3f8 through 0x3ff). When two registers share a port and have -** different access methods (RO vs. WO), a read from the port accesses -** the RO register and a write to the port access the WO register. -** -** The Line Control and Divisor Latch registers are accessed by writing -** a byte to the port; the high-order bit determines which register is -** accessed (0 selects Line Control, 1 selects Divisor Latch), with the -** remaining bits selecting fields within the indicated register. -*/ - -/* -** Receiver Data Register (read-only) -*/ -#define UA4_RXD (UA4_PORT+0) -# define UA4_RX_DATA UA4_RXD - -/* -** Transmitter Data Register (write-only) -*/ -#define UA4_TXD (UA4_PORT+0) -# define UA4_TX_DATA UA4_TXD - -/* -** Interrupt Enable Register -*/ -#define UA4_IER (UA4_PORT+1) -# define UA4_INT_ENABLE_REG UA4_IER - -// fields -#define UA4_IER_RX_IE 0x01 // Rcvr High-Data-Level Int Enable -#define UA4_IER_TX_IE 0x02 // Xmitter Low-data-level Int Enable -#define UA4_IER_LS_IE 0x04 // Line Status Int Enable -#define UA4_IER_MS_IE 0x08 // Modem Status Int Enable - -// aliases -#define UA4_IER_RX_INT_ENABLE UA4_IER_RX_IE -#define UA4_IER_TX_INT_ENABLE UA4_IER_TX_IE -#define UA4_IER_LINE_STATUS_INT_ENABLE UA4_IER_LS_IE -#define UA4_IER_MODEM_STATUS_INT_ENABLE UA4_IER_MS_IE - -/* -** Interrupt Identification Register (read-only) -** -** a.k.a. Event Identification Register -*/ -#define UA4_IIR (UA4_PORT+2) -# define UA4_EVENT_ID UA4_IIR - -// fields -#define UA4_IIR_IPF 0x01 // Interrupt Pending flag - -#define UA4_IIR_IPR_MASK 0x06 // Interrupt Priority mask -# define UA4_IIR_IPR0_MASK 0x02 // IPR bit 0 mask -# define UA4_IIR_IPR1_MASK 0x04 // IPR bit 1 mask - -#define UA5_IIR_RXFT 0x08 // RX_FIFO Timeout -#define UA5_IIR_FEN0 0x40 // FIFOs Enabled -#define UA5_IIR_FEN1 0x80 // FIFOs Enabled - -// aliases -#define UA4_IIR_INT_PENDING UA4_IIR_IPF -#define UA4_IIR_INT_PRIORITY UA4_IIR_IPR -#define UA5_IIR_RX_FIFO_TIMEOUT UA5_IIR_RXFT -#define UA5_IIR_FIFO_ENABLED_0 UA5_IIR_FEN0 -#define UA5_IIR_FIFO_ENABLED_1 UA5_IIR_FEN1 - -// IIR interrupt priorities (four-bit values) -#define UA4_IIR_INT_PRI_MASK 0x0f // Mask for extracting int priority -# define UA4_IIR_NO_INT 0x01 // no interrupt -# define UA4_IIR_LINE_STATUS 0x06 // line status interrupt -# define UA4_IIR_RX 0x04 // Receiver High Data Level -# define UA5_IIR_RX_FIFO 0x0c // Receiver FIFO timeout (16550) -# define UA4_IIR_TX 0x02 // Transmitter Low Data level -# define UA4_IIR_MODEM_STATUS 0x00 // Modem Status - -// aliases -#define UA4_IIR_NO_INT_PENDING UA4_IIR_NO_INT -#define UA4_IIR_LINE_STATUS_INT_PENDING UA4_IIR_LINE_STATUS -#define UA4_IIR_RX_INT_PENDING UA4_IIR_RX -#define UA5_IIR_RX_FIFO_TIMEOUT_INT_PENDING UA5_IIR_RX_FIFO -#define UA4_IIR_TX_INT_PENDING UA4_IIR_TX -#define UA4_IIR_MODEM_STATUS_INT_PENDING UA4_IIR_MODEM_STATUS - -/* -** FIFO Control Register (16550 only, write-only) -*/ -#define UA5_FCR (UA5_PORT+2) -# define UA5_FIFO_CTL UA5_FCR - -#define UA5_FCR_FIFO_RESET 0x00 // Reset the FIFO -#define UA5_FCR_FIFO_EN 0x01 // FIFO Enable -#define UA5_FCR_RXSR 0x02 // Receiver Soft Reset -#define UA5_FCR_TXSR 0x04 // Transmitter Soft Reset - -#define UA5_FCR_TXFT_MASK 0x30 // TX_FIFO threshold level mask -# define UA5_FCR_TXFT0_MASK 0x10 // TXFT bit 0 mask -# define UA5_FCR_TXFT1_MASK 0x20 // TXFT bit 1 mask -# define UA5_FCR_TX_FIFO_1 0x00 // 1 char -# define UA5_FCR_TX_FIFO_3 0x10 // 3 char -# define UA5_FCR_TX_FIFO_9 0x20 // 9 char -# define UA5_FCR_TX_FIFO_13 0x30 // 13 char - -#define UA5_FCR_RXFT_MASK 0xc0 // RX_FIFO threshold level mask -# define UA5_FCR_RXFT0_MASK 0x40 // RXFT bit 0 mask -# define UA5_FCR_RXFT1_MASK 0x80 // RXFT bit 1 mask -# define UA5_FCR_RX_FIFO_1 0x00 // 1 char -# define UA5_FCR_RX_FIFO_4 0x40 // 4 char -# define UA5_FCR_RX_FIFO_8 0x80 // 8 char -# define UA5_FCR_RX_FIFO_14 0xc0 // 14 char - -// aliases -#define UA5_FCR_FIFO_ENABLED UA5_FCR_FIFO_EN -#define UA5_FCR_RX_SOFT_RESET UA5_FCR_RXSR -#define UA5_FCR_TX_SOFT_RESET UA5_FCR_TXSR -#define UA5_FCR_TX_FIFO_1_CHAR UA5_FCR_TX_FIFO_1 -#define UA5_FCR_TX_FIFO_3_CHAR UA5_FCR_TX_FIFO_3 -#define UA5_FCR_TX_FIFO_9_CHAR UA5_FCR_TX_FIFO_9 -#define UA5_FCR_TX_FIFO_13_CHAR UA5_FCR_TX_FIFO_13 -#define UA5_FCR_RX_FIFO_1_CHAR UA5_FCR_RX_FIFO_1 -#define UA5_FCR_RX_FIFO_4_CHAR UA5_FCR_RX_FIFO_4 -#define UA5_FCR_RX_FIFO_8_CHAR UA5_FCR_RX_FIFO_8 -#define UA5_FCR_RX_FIFO_14_CHAR UA5_FCR_RX_FIFO_14 - -/* -** Line Control Register (available in all banks) -** -** Selected when bit 7 of the value written to the port is a 0. -*/ -#define UA4_LCR (UA4_PORT+3) -# define UA4_LINE_CTL UA4_LCR - -#define UA4_LCR_WLS_MASK 0x03 // Word Length Select mask -# define UA4_LCR_WLS0_MASK 0x01 // WLS bit 0 mask -# define UA4_LCR_WLS1_MASK 0x02 // WLS bit 1 mask -# define UA4_LCR_WLS_5 0x00 // 5 bits per char -# define UA4_LCR_WLS_6 0x01 // 6 bits per char -# define UA4_LCR_WLS_7 0x02 // 7 bits per char -# define UA4_LCR_WLS_8 0x03 // 8 bits per char - -#define UA4_LCR_STB 0x04 // Stop Bits -# define UA4_LCR_1_STOP_BIT 0x00 -# define UA4_LCR_2_STOP_BIT 0x04 - -#define UA4_LCR_PEN 0x08 // Parity Enable -#define UA4_LCR_EPS 0x10 // Even Parity Select -#define UA4_LCR_STKP 0x20 // Sticky Parity -# define UA4_LCR_NO_PARITY 0x00 -# define UA4_LCR_ODD_PARITY UA4_LCR_PEN -# define UA4_LCR_EVEN_PARITY (UA4_LCR_PEN|UA4_LCR_EPS) -# define UA4_LCR_PARITY_LOGIC_1 (UA4_LCR_PEN|UA4_LCR_STKP) -# define UA4_LCR_PARITY_LOGIC_0 (UA4_LCR_PEN|UA4_LCR_EPS|UA4_LCR_STKP) - -#define UA4_LCR_SBRK 0x40 // Set Break -#define UA4_LCR_DLAB 0x80 // Divisor Latch select bit - -// aliases -# define UA4_LCR_STOP_BITS UA4_LCR_STB -# define UA4_LCR_PARITY_ENABLE UA4_LCR_PEN -# define UA4_LCR_SET_BREAK UA4_LCR_SBRK -# define UA4_LCR_BANK_SELECT_ENABLE UA4_LCR_BKSE - -/* -** Divisor Latch Registers -** Divisor Latch Least Significant (DLL) -** Divisor Latch Most Significant (DLM) -** -** These contain the lower and upper halves of the 16-bit divisor for -** baud rate generation. -** -** Accessing them requires sending a command to LCR with the most -** significant bit (0x80, the DLAB field) set. This "unlocks" the -** Divisor Latch registers, which are accessed at UA4_PORT+0 and -** UA4_PORT+1 (i.e., in place of the RXD/TXD and IE registers). To -** "re-lock" the Divisor Latch registers, write a command byte to -** LCR with 0 in the DLAB bit. -*/ -#define UA4_DLL (UA4_PORT+0) // Divisor Latch (least sig.) -#define UA4_DLM (UA4_PORT+1) // Divisor Latch (most sig.) - -// aliases -#define UA4_DIVISOR_LATCH_LS UA4_DLL -#define UA4_DIVISOR_LATCH_MS UA4_DLM - -// Baud rate divisor high and low bytes -#define BAUD_HIGH_BYTE(x) (((x) >> 8) & 0xff) -#define BAUD_LOW_BYTE(x) ((x) & 0xff) - -// Baud rate divisors -#define DL_BAUD_50 2304 -#define DL_BAUD_75 1536 -#define DL_BAUD_110 1047 -#define DL_BAUD_150 768 -#define DL_BAUD_300 384 -#define DL_BAUD_600 192 -#define DL_BAUD_1200 96 -#define DL_BAUD_1800 64 -#define DL_BAUD_2000 58 -#define DL_BAUD_2400 48 -#define DL_BAUD_3600 32 -#define DL_BAUD_4800 24 -#define DL_BAUD_7200 16 -#define DL_BAUD_9600 12 -#define DL_BAUD_14400 8 -#define DL_BAUD_19200 6 -#define DL_BAUD_28800 4 -#define DL_BAUD_38400 3 -#define DL_BAUD_57600 2 -#define DL_BAUD_115200 1 - -/* -** Modem Control Register -*/ -#define UA4_MCR (UA4_PORT+4) -# define UA4_MODEM_CTL UA4_MCR - -#define UA4_MCR_DTR 0x01 // Data Terminal Ready -#define UA4_MCR_RTS 0x02 // Ready to Send -#define UA4_MCR_RILP 0x04 // Loopback Interrupt Request -#define UA4_MCR_ISEN 0x08 // Interrupt Signal Enable -#define UA4_MCR_DCDLP 0x08 // DCD Loopback -#define UA4_MCR_LOOP 0x10 // Loopback Enable - -// aliases -#define UA4_MCR_DATA_TERMINAL_READY UA4_MCR_DTR -#define UA4_MCR_READY_TO_SEND UA4_MCR_RTS -#define UA4_MCR_LOOPBACK_INT_REQ UA4_MCR_RILP -#define UA4_MCR_INT_SIGNAL_ENABLE UA4_MCR_ISEN -#define UA4_MCR_LOOPBACK_DCD UA4_MCR_DCDLP -#define UA4_MCR_LOOPBACK_ENABLE UA4_MCR_LOOP - -/* -** Line Status Register -*/ -#define UA4_LSR (UA4_PORT+5) -# define UA4_LINE_STATUS UA4_LSR - -#define UA4_LSR_RXDA 0x01 // Receiver Data Available -#define UA4_LSR_OE 0x02 // Overrun Error -#define UA4_LSR_PE 0x04 // Parity Error -#define UA4_LSR_FE 0x08 // Framing Error -#define UA4_LSR_BRK 0x10 // Break Event Detected -#define UA4_LSR_TXRDY 0x20 // Transmitter Ready -#define UA4_LSR_TXEMP 0x40 // Transmitter Empty -#define UA4_LSR_ER_INF 0x80 // Error in RX_FIFO - -// aliases -#define UA4_LSR_RX_DATA_AVAILABLE UA4_LSR_RXDA -#define UA4_LSR_OVERRUN_ERROR UA4_LSR_OE -#define UA4_LSR_PARITY_ERROR UA4_LSR_PE -#define UA4_LSR_FRAMING_ERROR UA4_LSR_FE -#define UA4_LSR_BREAK_DETECTED UA4_LSR_BRK -#define UA4_LSR_TX_READY UA4_LSR_TXRDY -#define UA4_LSR_TX_EMPTY UA4_LSR_TXEMP -#define UA4_LSR_RX_FIFO_ERROR UA4_LSR_ER_INF - -/* -** Modem Status Register -*/ -#define UA4_MSR (UA4_PORT+6) -# define UA4_MODEM_STATUS UA4_MSR - -#define UA4_MSR_DCTS 0x01 // Delta Clear to Send -#define UA4_MSR_DDSR 0x02 // Delta Data Set Ready -#define UA4_MSR_TERI 0x04 // Trailing Edge Ring Indicate -#define UA4_MSR_DDCD 0x08 // Delta Data Carrier Detect -#define UA4_MSR_CTS 0x10 // Clear to Send -#define UA4_MSR_DSR 0x20 // Data Set Ready -#define UA4_MSR_RI 0x40 // Ring Indicate -#define UA4_MSR_DCD 0x80 // Data Carrier Detect - -// aliases -#define UA4_MSR_DELTA_CLEAR_TO_SEND UA4_MSR_DCTS -#define UA4_MSR_DELTA_DATA_SET_READY UA4_MSR_DDSR -#define UA4_MSR_TRAILING_EDGE_RING UA4_MSR_TERI -#define UA4_MSR_DELTA_DATA_CARRIER_DETECT UA4_MSR_DDCD -#define UA4_MSR_CLEAR_TO_SEND UA4_MSR_CTS -#define UA4_MSR_DATA_SET_READY UA4_MSR_DSR -#define UA4_MSR_RING_INDICATE UA4_MSR_RI -#define UA4_MSR_DATA_CARRIER_DETECT UA4_MSR_DCD - -/* -** Scratch Register -** -** Not used by the UART; usable as a "scratchpad" register for -** temporary storage. -*/ -#define UA4_SCR (UA4_PORT+7) -# define UA4_SCRATCH UA4_UA5_SCR - -#endif /* uart.h */ diff --git a/kernel/old/isrs.S b/kernel/old/isrs.S deleted file mode 100644 index f6bd662..0000000 --- a/kernel/old/isrs.S +++ /dev/null @@ -1,374 +0,0 @@ -/* -** @file isrs.S -** -** @author K. Reek -** @authors Jon Coles, Warren R. Carithers, Margaret Reek -** @author numerous Systems Programming classes -** -** Stubs for ISRs. -** -** This module provides the stubs needed for interrupts to save -** the machine state before calling the ISR. All interrupts have -** their own stub which pushes the interrupt number on the stack. -** This makes it possible for a common ISR to determine which -** interrupted occurred. -*/ - -#define ASM_SRC - -# .arch i386 - -#include - -/* -** Configuration options - define in Makefile -** -** TRACE_CX include context restore debugging code -*/ - - .text - -/* -** Macros for the isr stubs. Some interrupts push an error code on -** the stack and others don't; for those that don't we simply push -** a zero so that cleaning up from either type is identical. -** -** Note: these are not marked as global symbols, as they are never -** accessed directly outside of this file. This could be changed -** if need be by adding this line to each macro definition right -** after the #define line: -** -** .global isr_##vector -*/ - -#define ISR(vector) \ -isr_##vector: ; \ - pushl $0 ; \ - pushl $vector ; \ - jmp isr_save - -#define ERR_ISR(vector) \ -isr_##vector: ; \ - pushl $vector ; \ - jmp isr_save - - .globl isr_table - .globl isr_restore - -/* -** This routine saves the machine state, calls the ISR, and then -** restores the machine state and returns from the interrupt. -** -******************************************************************** -******************************************************************** -** NOTE: this code is highly application-specific, and will most ** -** probably require modification to tailor it. ** -** ** -** Examples of mods: switch to/from user stack, context switch ** -** changes, etc. ** -******************************************************************** -******************************************************************** -*/ - -isr_save: - -/* -** Begin by saving the CPU state (except for the FP context information). -** -** At this point, the stack looks like this: -** -** esp -> vector # saved by the entry macro -** error code, or 0 saved by the hardware, or the entry macro -** saved EIP saved by the hardware -** saved CS saved by the hardware -** saved EFLAGS saved by the hardware -*/ - pusha // save E*X, ESP, EBP, ESI, EDI - pushl %ds // save segment registers - pushl %es - pushl %fs - pushl %gs - pushl %ss - -/* -** Stack contents (all 32-bit longwords) and offsets from ESP: -** -** SS GS FS ES DS EDI ESI EBP ESP EBX EDX ECX EAX vec cod EIP CS EFL -** 0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 -** -** Note that the saved ESP is the contents before the PUSHA. -** -** Set up parameters for the ISR call. -*/ - movl 52(%esp),%eax // get vector number and error code - movl 56(%esp),%ebx - -/* -*********************** -** MOD FOR 20245 ** -*********************** -*/ - -/* -** We need to switch to the system stack. This requires that we save -** the user context pointer into the current PCB, then load ESP with -** the initial system stack pointer. -*/ - - .globl current - .globl kernel_esp - - // save the context pointer - movl current, %edx - movl %esp, (%edx) - - // also save the page directory pointer - movl %cr3, %ecx - movl %ecx, 4(%edx) - - // switch to the system stack - // - // NOTE: this is inherently non-reentrant! If/when the OS - // is converted from monolithic to something that supports - // reentrant or interruptable ISRs, this code will need to - // be changed to support that! - - movl kernel_esp, %esp - - // we don't change CR3 because all the user PDIRs are - // set up with mappings for the OS in the upper half - -/* -*********************** -** END MOD FOR 20245 ** -*********************** -*/ - - pushl %ebx // put them on the top of the stack ... - pushl %eax // ... as parameters for the ISR - -/* -** Call the ISR -*/ - movl isr_table(,%eax,4),%ebx - call *%ebx - addl $8,%esp // pop the two parameters - -/* -** Context restore begins here -*/ - -isr_restore: - -/* -*********************** -** MOD FOR 20245 ** -*********************** -*/ - movl current, %ebx // return to the user stack - movl (%ebx), %esp // ESP --> context save area - movl 4(%ebx), %ecx // page directory pointer - movl %ecx, %cr3 - - // now we're operating with the user process' - // page directory and stack - -/* -*********************** -** END MOD FOR 20245 ** -*********************** -*/ - -#ifdef TRACE_CX -/* -** DEBUGGING CODE PART 1 -** -** This code will execute during each context restore, and -** should be modified to print out whatever debugging information -** is desired. -** -** By default, it prints out the CPU context being restored; it -** relies on the standard save sequence (see above). -*/ - .globl cio_printf_at - - pushl $fmt - pushl $1 - pushl $0 - call cio_printf_at - addl $12,%esp -/* -** END OF DEBUGGING CODE PART 1 -*/ -#endif - -/* -** Restore the context. -*/ - popl %ss // restore the segment registers - popl %gs - popl %fs - popl %es - popl %ds - popa // restore others - addl $8, %esp // discard the error code and vector - iret // and return - -#ifdef TRACE_CX -/* -** DEBUGGING CODE PART 2 -** -** This format string is arranged according to the ordering of values -** in the context save area on the stack. -*/ -fmt: .ascii " ss=%08x gs=%08x fs=%08x es=%08x ds=%08x\n" - .ascii "edi=%08x esi=%08x ebp=%08x esp=%08x ebx=%08x\n" - .ascii "edx=%08x ecx=%08x eax=%08x vec=%08x cod=%08x\n" - .string "eip=%08x cs=%08x efl=%08x\n" - -/* -** END OF DEBUGGING CODE PART 2 -*/ -#endif - -/* -** Here we generate the individual stubs for each interrupt. -*/ -ISR(0x00); ISR(0x01); ISR(0x02); ISR(0x03); -ISR(0x04); ISR(0x05); ISR(0x06); ISR(0x07); -ERR_ISR(0x08); ISR(0x09); ERR_ISR(0x0a); ERR_ISR(0x0b); -ERR_ISR(0x0c); ERR_ISR(0x0d); ERR_ISR(0x0e); ISR(0x0f); -ISR(0x10); ERR_ISR(0x11); ISR(0x12); ISR(0x13); -ISR(0x14); ERR_ISR(0x15); ISR(0x16); ISR(0x17); -ISR(0x18); ISR(0x19); ISR(0x1a); ISR(0x1b); -ISR(0x1c); ISR(0x1d); ISR(0x1e); ISR(0x1f); -ISR(0x20); ISR(0x21); ISR(0x22); ISR(0x23); -ISR(0x24); ISR(0x25); ISR(0x26); ISR(0x27); -ISR(0x28); ISR(0x29); ISR(0x2a); ISR(0x2b); -ISR(0x2c); ISR(0x2d); ISR(0x2e); ISR(0x2f); -ISR(0x30); ISR(0x31); ISR(0x32); ISR(0x33); -ISR(0x34); ISR(0x35); ISR(0x36); ISR(0x37); -ISR(0x38); ISR(0x39); ISR(0x3a); ISR(0x3b); -ISR(0x3c); ISR(0x3d); ISR(0x3e); ISR(0x3f); -ISR(0x40); ISR(0x41); ISR(0x42); ISR(0x43); -ISR(0x44); ISR(0x45); ISR(0x46); ISR(0x47); -ISR(0x48); ISR(0x49); ISR(0x4a); ISR(0x4b); -ISR(0x4c); ISR(0x4d); ISR(0x4e); ISR(0x4f); -ISR(0x50); ISR(0x51); ISR(0x52); ISR(0x53); -ISR(0x54); ISR(0x55); ISR(0x56); ISR(0x57); -ISR(0x58); ISR(0x59); ISR(0x5a); ISR(0x5b); -ISR(0x5c); ISR(0x5d); ISR(0x5e); ISR(0x5f); -ISR(0x60); ISR(0x61); ISR(0x62); ISR(0x63); -ISR(0x64); ISR(0x65); ISR(0x66); ISR(0x67); -ISR(0x68); ISR(0x69); ISR(0x6a); ISR(0x6b); -ISR(0x6c); ISR(0x6d); ISR(0x6e); ISR(0x6f); -ISR(0x70); ISR(0x71); ISR(0x72); ISR(0x73); -ISR(0x74); ISR(0x75); ISR(0x76); ISR(0x77); -ISR(0x78); ISR(0x79); ISR(0x7a); ISR(0x7b); -ISR(0x7c); ISR(0x7d); ISR(0x7e); ISR(0x7f); -ISR(0x80); ISR(0x81); ISR(0x82); ISR(0x83); -ISR(0x84); ISR(0x85); ISR(0x86); ISR(0x87); -ISR(0x88); ISR(0x89); ISR(0x8a); ISR(0x8b); -ISR(0x8c); ISR(0x8d); ISR(0x8e); ISR(0x8f); -ISR(0x90); ISR(0x91); ISR(0x92); ISR(0x93); -ISR(0x94); ISR(0x95); ISR(0x96); ISR(0x97); -ISR(0x98); ISR(0x99); ISR(0x9a); ISR(0x9b); -ISR(0x9c); ISR(0x9d); ISR(0x9e); ISR(0x9f); -ISR(0xa0); ISR(0xa1); ISR(0xa2); ISR(0xa3); -ISR(0xa4); ISR(0xa5); ISR(0xa6); ISR(0xa7); -ISR(0xa8); ISR(0xa9); ISR(0xaa); ISR(0xab); -ISR(0xac); ISR(0xad); ISR(0xae); ISR(0xaf); -ISR(0xb0); ISR(0xb1); ISR(0xb2); ISR(0xb3); -ISR(0xb4); ISR(0xb5); ISR(0xb6); ISR(0xb7); -ISR(0xb8); ISR(0xb9); ISR(0xba); ISR(0xbb); -ISR(0xbc); ISR(0xbd); ISR(0xbe); ISR(0xbf); -ISR(0xc0); ISR(0xc1); ISR(0xc2); ISR(0xc3); -ISR(0xc4); ISR(0xc5); ISR(0xc6); ISR(0xc7); -ISR(0xc8); ISR(0xc9); ISR(0xca); ISR(0xcb); -ISR(0xcc); ISR(0xcd); ISR(0xce); ISR(0xcf); -ISR(0xd0); ISR(0xd1); ISR(0xd2); ISR(0xd3); -ISR(0xd4); ISR(0xd5); ISR(0xd6); ISR(0xd7); -ISR(0xd8); ISR(0xd9); ISR(0xda); ISR(0xdb); -ISR(0xdc); ISR(0xdd); ISR(0xde); ISR(0xdf); -ISR(0xe0); ISR(0xe1); ISR(0xe2); ISR(0xe3); -ISR(0xe4); ISR(0xe5); ISR(0xe6); ISR(0xe7); -ISR(0xe8); ISR(0xe9); ISR(0xea); ISR(0xeb); -ISR(0xec); ISR(0xed); ISR(0xee); ISR(0xef); -ISR(0xf0); ISR(0xf1); ISR(0xf2); ISR(0xf3); -ISR(0xf4); ISR(0xf5); ISR(0xf6); ISR(0xf7); -ISR(0xf8); ISR(0xf9); ISR(0xfa); ISR(0xfb); -ISR(0xfc); ISR(0xfd); ISR(0xfe); ISR(0xff); - - .data - -/* -** This table contains the addresses where each of the preceding -** stubs begins. This information is needed to initialize the -** Interrupt Descriptor Table in support.c -*/ - .globl isr_stub_table -isr_stub_table: - .long isr_0x00, isr_0x01, isr_0x02, isr_0x03 - .long isr_0x04, isr_0x05, isr_0x06, isr_0x07 - .long isr_0x08, isr_0x09, isr_0x0a, isr_0x0b - .long isr_0x0c, isr_0x0d, isr_0x0e, isr_0x0f - .long isr_0x10, isr_0x11, isr_0x12, isr_0x13 - .long isr_0x14, isr_0x15, isr_0x16, isr_0x17 - .long isr_0x18, isr_0x19, isr_0x1a, isr_0x1b - .long isr_0x1c, isr_0x1d, isr_0x1e, isr_0x1f - .long isr_0x20, isr_0x21, isr_0x22, isr_0x23 - .long isr_0x24, isr_0x25, isr_0x26, isr_0x27 - .long isr_0x28, isr_0x29, isr_0x2a, isr_0x2b - .long isr_0x2c, isr_0x2d, isr_0x2e, isr_0x2f - .long isr_0x30, isr_0x31, isr_0x32, isr_0x33 - .long isr_0x34, isr_0x35, isr_0x36, isr_0x37 - .long isr_0x38, isr_0x39, isr_0x3a, isr_0x3b - .long isr_0x3c, isr_0x3d, isr_0x3e, isr_0x3f - .long isr_0x40, isr_0x41, isr_0x42, isr_0x43 - .long isr_0x44, isr_0x45, isr_0x46, isr_0x47 - .long isr_0x48, isr_0x49, isr_0x4a, isr_0x4b - .long isr_0x4c, isr_0x4d, isr_0x4e, isr_0x4f - .long isr_0x50, isr_0x51, isr_0x52, isr_0x53 - .long isr_0x54, isr_0x55, isr_0x56, isr_0x57 - .long isr_0x58, isr_0x59, isr_0x5a, isr_0x5b - .long isr_0x5c, isr_0x5d, isr_0x5e, isr_0x5f - .long isr_0x60, isr_0x61, isr_0x62, isr_0x63 - .long isr_0x64, isr_0x65, isr_0x66, isr_0x67 - .long isr_0x68, isr_0x69, isr_0x6a, isr_0x6b - .long isr_0x6c, isr_0x6d, isr_0x6e, isr_0x6f - .long isr_0x70, isr_0x71, isr_0x72, isr_0x73 - .long isr_0x74, isr_0x75, isr_0x76, isr_0x77 - .long isr_0x78, isr_0x79, isr_0x7a, isr_0x7b - .long isr_0x7c, isr_0x7d, isr_0x7e, isr_0x7f - .long isr_0x80, isr_0x81, isr_0x82, isr_0x83 - .long isr_0x84, isr_0x85, isr_0x86, isr_0x87 - .long isr_0x88, isr_0x89, isr_0x8a, isr_0x8b - .long isr_0x8c, isr_0x8d, isr_0x8e, isr_0x8f - .long isr_0x90, isr_0x91, isr_0x92, isr_0x93 - .long isr_0x94, isr_0x95, isr_0x96, isr_0x97 - .long isr_0x98, isr_0x99, isr_0x9a, isr_0x9b - .long isr_0x9c, isr_0x9d, isr_0x9e, isr_0x9f - .long isr_0xa0, isr_0xa1, isr_0xa2, isr_0xa3 - .long isr_0xa4, isr_0xa5, isr_0xa6, isr_0xa7 - .long isr_0xa8, isr_0xa9, isr_0xaa, isr_0xab - .long isr_0xac, isr_0xad, isr_0xae, isr_0xaf - .long isr_0xb0, isr_0xb1, isr_0xb2, isr_0xb3 - .long isr_0xb4, isr_0xb5, isr_0xb6, isr_0xb7 - .long isr_0xb8, isr_0xb9, isr_0xba, isr_0xbb - .long isr_0xbc, isr_0xbd, isr_0xbe, isr_0xbf - .long isr_0xc0, isr_0xc1, isr_0xc2, isr_0xc3 - .long isr_0xc4, isr_0xc5, isr_0xc6, isr_0xc7 - .long isr_0xc8, isr_0xc9, isr_0xca, isr_0xcb - .long isr_0xcc, isr_0xcd, isr_0xce, isr_0xcf - .long isr_0xd0, isr_0xd1, isr_0xd2, isr_0xd3 - .long isr_0xd4, isr_0xd5, isr_0xd6, isr_0xd7 - .long isr_0xd8, isr_0xd9, isr_0xda, isr_0xdb - .long isr_0xdc, isr_0xdd, isr_0xde, isr_0xdf - .long isr_0xe0, isr_0xe1, isr_0xe2, isr_0xe3 - .long isr_0xe4, isr_0xe5, isr_0xe6, isr_0xe7 - .long isr_0xe8, isr_0xe9, isr_0xea, isr_0xeb - .long isr_0xec, isr_0xed, isr_0xee, isr_0xef - .long isr_0xf0, isr_0xf1, isr_0xf2, isr_0xf3 - .long isr_0xf4, isr_0xf5, isr_0xf6, isr_0xf7 - .long isr_0xf8, isr_0xf9, isr_0xfa, isr_0xfb - .long isr_0xfc, isr_0xfd, isr_0xfe, isr_0xff diff --git a/kernel/old/kernel.c b/kernel/old/kernel.c deleted file mode 100644 index 14e8b02..0000000 --- a/kernel/old/kernel.c +++ /dev/null @@ -1,384 +0,0 @@ -/** -** @file kernel.c -** -** @author CSCI-452 class of 20245 -** -** @brief Kernel support routines -*/ - -#define KERNEL_SRC - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* -** PRIVATE DEFINITIONS -*/ - -/* -** PRIVATE DATA TYPES -*/ - -/* -** PRIVATE GLOBAL VARIABLES -*/ - -/* -** PUBLIC GLOBAL VARIABLES -*/ - -// character buffers, usable throughout the OS -// nto guaranteed to retain their contents across an exception return -char b256[256]; // primarily used for message creation -char b512[512]; // used by PANIC macro - -/* -** PRIVATE FUNCTIONS -*/ - -/* -** PRIVATE FUNCTIONS -*/ - -/** -** report - report the system configuration -** -** Prints configuration information about the OS on the console monitor. -** -** @param dtrace Decode the TRACE options -*/ -static void kreport( bool_t dtrace ) { - - cio_puts( "\n-------------------------------\n" ); - cio_printf( "Config: N_PROCS = %d", N_PROCS ); - cio_printf( " N_PRIOS = %d", N_PRIOS ); - cio_printf( " N_STATES = %d", N_STATES ); - cio_printf( " CLOCK = %dHz\n", CLOCK_FREQ ); - - // This code is ugly, but it's the simplest way to - // print out the values of compile-time options - // without spending a lot of execution time at it. - - cio_puts( "Options: " -#ifdef RPT_INT_UNEXP - " R-uint" -#endif -#ifdef RPT_INT_MYSTERY - " R-mint" -#endif -#ifdef TRACE_CX - " CX" -#endif -#ifdef CONSOLE_STATS - " Cstats" -#endif - ); // end of cio_puts() call - -#ifdef SANITY - cio_printf( " SANITY = %d", SANITY ); -#endif -#ifdef STATUS - cio_printf( " STATUS = %d", STATUS ); -#endif - -#if TRACE > 0 - cio_printf( " TRACE = 0x%04x\n", TRACE ); - - // decode the trace settings if that was requested - if( TRACING_SOMETHING && dtrace ) { - - // this one is simpler - we rely on string literal - // concatenation in the C compiler to create one - // long string to print out - - cio_puts( "Tracing:" -#if TRACING_PCB - " PCB" -#endif -#if TRACING_VM - " VM" -#endif -#if TRACING_QUEUE - " QUE" -#endif -#if TRACING_SCHED - " SCHED" -#endif -#if TRACING_DISPATCH - " DISPATCH" -#endif -#if TRACING_SYSCALLS - " SCALL" -#endif -#if TRACING_SYSRETS - " SRET" -#endif -#if TRACING_EXIT - " EXIT" -#endif -#if TRACING_INIT - " INIT" -#endif -#if TRACING_KMEM - " KM" -#endif -#if TRACING_KMEM_FREELIST - " KMFL" -#endif -#if TRACING_KMEM_INIT - " KMIN" -#endif -#if TRACING_FORK - " FORK" -#endif -#if TRACING_EXEC - " EXEC" -#endif -#if TRACING_SIO_STAT - " S_STAT" -#endif -#if TRACING_SIO_ISR - " S_ISR" -#endif -#if TRACING_SIO_RD - " S_RD" -#endif -#if TRACING_SIO_WR - " S_WR" -#endif -#if TRACING_USER - " USER" -#endif -#if TRACING_ELF - " ELF" -#endif - ); // end of cio_puts() call - } -#endif /* TRACE > 0 */ - - cio_puts( "\n-------------------------------\n" ); -} - - -#if defined(CONSOLE_STATS) -/** -** stats - callback routine for console statistics -** -** Called by the CIO module when a key is pressed on the -** console keyboard. Depending on the key, it will print -** statistics on the console display, or will cause the -** user shell process to be dispatched. -** -** This code runs as part of the CIO ISR. -*/ -static void stats( int code ) { - - switch( code ) { - - case 'a': // dump the active table - ptable_dump( "\nActive processes", false ); - break; - - case 'c': // dump context info for all active PCBs - ctx_dump_all( "\nContext dump" ); - break; - - case 'p': // dump the active table and all PCBs - ptable_dump( "\nActive processes", true ); - break; - - case 'q': // dump the queues - // code to dump out any/all queues - pcb_queue_dump( "R", ready ); - pcb_queue_dump( "W", waiting ); - pcb_queue_dump( "S", sleeping ); - pcb_queue_dump( "Z", zombie ); - pcb_queue_dump( "I", sioread ); - break; - - case 'r': // print system configuration information - report( true ); - break; - - // ignore CR and LF - case '\r': // FALL THROUGH - case '\n': - break; - - default: - cio_printf( "console: unknown request '0x%02x'\n", code ); - // FALL THROUGH - - case 'h': // help message - cio_puts( "\nCommands:\n" - " a -- dump the active table\n" - " c -- dump contexts for active processes\n" - " h -- this message\n" - " p -- dump the active table and all PCBs\n" - " q -- dump the queues\n" - " r -- print system configuration\n" - ); - break; - } -} -#endif - -/* -** PUBLIC FUNCTIONS -*/ - -/** -** main - system initialization routine -** -** Called by the startup code immediately before returning into the -** first user process. -** -** Making this type 'int' keeps the compiler happy. -*/ -int main( void ) { - - /* - ** BOILERPLATE CODE - taken from basic framework - ** - ** Initialize interrupt stuff. - */ - - init_interrupts(); // IDT and PIC initialization - - /* - ** Console I/O system. - ** - ** Does not depend on the other kernel modules, so we can - ** initialize it before we initialize the kernel memory - ** and queue modules. - */ - -#if defined(CONSOLE_STATS) - cio_init( stats ); -#else - cio_init( NULL ); // no console callback routine -#endif - - cio_clearscreen(); // wipe out whatever is there - - /* - ** TERM-SPECIFIC CODE STARTS HERE - */ - - /* - ** Initialize various OS modules - ** - ** Other modules (clock, SIO, syscall, etc.) are expected to - ** install their own ISRs in their initialization routines. - */ - - cio_puts( "System initialization starting.\n" ); - cio_puts( "-------------------------------\n" ); - - cio_puts( "Modules:" ); - - // call the module initialization functions, being - // careful to follow any module precedence requirements - - km_init(); // MUST BE FIRST -#if TRACING_KMEM || TRACING_KMEM_FREE - delay( DELAY_2_SEC ); // approximately -#endif - - // other module initialization calls here - clk_init(); // clock - pcb_init(); // process (PCBs, queues, scheduler) -#if TRACING_PCB - delay( DELAY_2_SEC ); -#endif - sio_init(); // serial i/o - sys_init(); // system call -#if TRACING_SYSCALLS || TRACING_SYSRETS - delay( DELAY_2_SEC ); -#endif - vm_init(); // virtual memory - user_init(); // user code handling - - cio_puts( "\nModule initialization complete.\n" ); - cio_puts( "-------------------------------\n" ); - - // report our configuration options - kreport( true ); - - delay( DELAY_3_SEC ); - - /* - ** Other tasks typically performed here: - ** - ** Enabling any I/O devices (e.g., SIO xmit/rcv) - */ - - /* - ** Create the initial user process - ** - ** This code is largely stolen from the fork() and exec() - ** implementations in syscalls.c; if those change, this must - ** also change. - */ - - // if we can't get a PCB, there's no use continuing! - assert( pcb_alloc(&init_pcb) == SUCCESS ); - - // fill in the necessary details - init_pcb->pid = PID_INIT; - init_pcb->state = STATE_NEW; - init_pcb->priority = PRIO_HIGH; - - // find the 'init' program - prog_t *prog = user_locate( Init ); - assert( prog != NULL ); - - // command-line arguments for 'init' - const char *args[2] = { "init", NULL }; - - // load it - assert( user_load(prog,init_pcb,args) == SUCCESS ); - - // send it on its merry way - schedule( init_pcb ); - -#ifdef TRACE_CX - // if we're using a scrolling region, wait a bit more and then set it up - delay( DELAY_7_SEC ); - - // define a scrolling region in the top 7 lines of the screen - cio_setscroll( 0, 7, 99, 99 ); - - // clear it - cio_clearscroll(); - - // clear the top line - cio_puts_at( 0, 0, "* " ); - // separator - cio_puts_at( 0, 6, "================================================================================" ); -#endif - - // switch to the "real" kernel page directory - vm_set_kvm(); - - /* - ** END OF TERM-SPECIFIC CODE - ** - ** Finally, report that we're all done. - */ - - cio_puts( "System initialization complete.\n" ); - cio_puts( "-------------------------------\n" ); - - sio_enable( SIO_RX ); - - return 0; -} diff --git a/kernel/old/kernel.ld b/kernel/old/kernel.ld deleted file mode 100644 index 1534aad..0000000 --- a/kernel/old/kernel.ld +++ /dev/null @@ -1,71 +0,0 @@ -/* -** Simple linker script for the 20245 kernel. -*/ - -OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") -OUTPUT_ARCH(i386) -ENTRY(_start) - -SECTIONS -{ - /* Link the kernel at this address. */ - /* Must match what is defined in vm.h! */ - . = 0x80010000; - - .text : AT(0x10000) { - *(.text .stub .text.* .gnu.linkonce.t.*) - } - - /* standard symbols */ - PROVIDE(etext = .); - PROVIDE(_etext = .); - - /* put read-only data next */ - .rodata : { - *(.rodata .rodata.* .gnu.linkonce.r.*) - } - - /* Could put STABs here */ - .stab : { - PROVIDE(__STAB_BEGIN__ = .); - *(.stab); - PROVIDE(__STAB_END__ = .); - } - .stabstr : { - PROVIDE(__STABSTR_BEGIN__ = .); - *(.stabstr); - PROVIDE(__STABSTR_END__ = .); - } - - /* Align the data segment at the next page boundary */ - . = ALIGN(0x1000); - - PROVIDE(data = .); - PROVIDE(_data = .); - - /* The data segment */ - .data : { - *(.data .data.*) - } - - PROVIDE(edata = .); - PROVIDE(_edata = .); - - /* page-align the BSS */ - . = ALIGN(0x1000); - - PROVIDE(__bss_start = .); - - .bss : { - *(.bss .bss.*) - *(COMMON) - } - - PROVIDE(end = .); - PROVIDE(_end = .); - - /DISCARD/ : { - /* *(.stab .stab_info .stabstr) */ - *(.eh_frame .note.GNU-stack .note.gnu.property .comment) - } -} diff --git a/kernel/old/kmem.c b/kernel/old/kmem.c deleted file mode 100644 index febc6b9..0000000 --- a/kernel/old/kmem.c +++ /dev/null @@ -1,699 +0,0 @@ -/** -** @file kmem.c -** -** @author Warren R. Carithers -** @author Kenneth Reek -** @author 4003-506 class of 20013 -** -** @brief Functions to perform dynamic memory allocation in the OS. -** -** NOTE: these should NOT be called by user processes! -** -** This allocator functions as a simple "slab" allocator; it allows -** allocation of either 4096-byte ("page") or 1024-byte ("slice") -** chunks of memory from the free pool. The free pool is initialized -** using the memory map provided by the BIOS during the boot sequence, -** and contains a series of blocks which are each one page of memory -** (4KB, and aligned at 4KB boundaries); they are held in the free list -** in LIFO order, as all pages are created equal. -** -** By default, the addresses used are virtual addresses rather than -** physical addresses. Define the symbol USE_PADDRS when compiling to -** change this. -** -** Each allocator ("page" and "slice") allocates the first block from -** the appropriate free list. On deallocation, the block is added back -** to the free list. -** -** The "slice" allocator operates by taking blocks from the "page" -** allocator and splitting them into four 1K slices, which it then -** manages. Requests are made for slices one at a time. If the free -** list contains an available slice, it is unlinked and returned; -** otherwise, a page is requested from the page allocator, split into -** slices, and the slices are added to the free list, after which the -** first one is returned. The slice free list is a simple linked list -** of these 1K blocks; because they are all the same size, no ordering -** is done on the free list, and no coalescing is performed. -** -** This could be converted into a bitmap-based allocator pretty easily. -** A 4GB address space contains 2^20 (1,048,576) pages; at one bit per -** page frame, that's 131,072 (2^17) bytes to cover all of the address -** space, and that could be reduced by restricting allocatable space -** to a subset of the 4GB space. -** -** Compilation options: -** -** ALLOC_FAIL_PANIC if an internal slice allocation fails, panic -** USE_PADDRS build the free list using physical, not -** virtual, addresses -*/ - -#define KERNEL_SRC - -#include - -// all other framework includes are next -#include - -#include - -#include -#include -#include -#include -#include -#include - -/* -** PRIVATE DEFINITIONS -*/ - -// combination tracing tests -#define ANY_KMEM (TRACING_KMEM|TRACING_KMEM_INIT|TRACING_KMEM_FREELIST) -#define KMEM_OR_INIT (TRACING_KMEM|TRACING_KMEM_INIT) - -// parameters related to word and block sizes - -#define WORD_SIZE sizeof(int) -#define LOG2_OF_WORD_SIZE 2 - -#define LOG2_OF_PAGE_SIZE 12 - -#define LOG2_OF_SLICE_SIZE 10 - -// converters: pages to bytes, bytes to pages - -#define P2B(x) ((x) << LOG2_OF_PAGE_SIZE) -#define B2P(x) ((x) >> LOG2_OF_PAGE_SIZE) - -/* -** Name: adjacent -** -** Arguments: addresses of two blocks -** -** Description: Determines whether the second block immediately -** follows the first one. -*/ -#define adjacent(first,second) \ - ( (void *) (first) + P2B((first)->pages) == (void *) (second) ) - -/* -** PRIVATE DATA TYPES -*/ - -/* -** Memory region information returned by the BIOS -** -** This data consists of a 32-bit integer followed -** by an array of region descriptor structures. -*/ - -// a handy union for playing with 64-bit addresses -typedef union b64_u { - uint32_t part[2]; - uint64_t all; -} b64_t; - -// the halves of a 64-bit address -#define LOW part[0] -#define HIGH part[1] - -// memory region descriptor -typedef struct memregion_s { - b64_t base; // base address - b64_t length; // region length - uint32_t type; // type of region - uint32_t acpi; // ACPI 3.0 info -} ATTR_PACKED region_t; - -/* -** Region types -*/ - -#define REGION_USABLE 1 -#define REGION_RESERVED 2 -#define REGION_ACPI_RECL 3 -#define REGION_ACPI_NVS 4 -#define REGION_BAD 5 - -/* -** ACPI 3.0 bit fields -*/ - -#define REGION_IGNORE 0x01 -#define REGION_NONVOL 0x02 - -/* -** 32-bit and 64-bit address values as 64-bit literals -*/ - -#define ADDR_BIT_32 0x0000000100000000LL -#define ADDR_LOW_HALF 0x00000000ffffffffLL -#define ADDR_HIGH_HALR 0xffffffff00000000LL - -#define ADDR_32_MAX ADDR_LOW_HALF -#define ADDR_64_FIRST ADDR_BIT_32 - -/* -** PRIVATE GLOBAL VARIABLES -*/ - -// freespace pools -static list_t free_pages; -static list_t free_slices; - -// block counts -static uint32_t n_pages; -static uint32_t n_slices; - -// initialization status -static int km_initialized; - -/* -** IMPORTED GLOBAL VARIABLES -*/ - -// this is no longer used; for simple situations, it can be used as -// the KM_LOW_CUTOFF value -// -// extern int _end; // end of the BSS section - provided by the linker - -/* -** FUNCTIONS -*/ - -/* -** FREE LIST MANAGEMENT -*/ - -/** -** Name: add_block -** -** Add a block to the free list. The block will be split into separate -** page-sized fragments which will each be added to the free_pages -** list; each of these will also be modified. -** -** @param[in] base Base physical address of the block -** @param[in] length Block length, in bytes -*/ -static void add_block( uint32_t base, uint32_t length ) { - - // don't add it if it isn't at least 4K - if( length < SZ_PAGE ) { - return; - } - -#if ANY_KMEM - cio_printf( " add(%08x,%08x): ", base, length ); -#endif - - // verify that the base address is a 4K boundary - if( (base & MOD4K_BITS) != 0 ) { - // nope - how many bytes will we lose from the beginning - uint_t loss = base & MOD4K_BITS; - // adjust the starting address: (n + 4K - 1) / 4K - base = (base + MOD4K_BITS) & MOD4K_MASK; - // adjust the length - length -= loss; - } - - // only want to add multiples of 4K; check the lower bits - if( (length & MOD4K_BITS) != 0 ) { - // round it down to 4K - length &= MOD4K_MASK; - } - - // determine the starting and ending addresses for the block -#ifndef USE_PADDRS - // starting and ending addresses as virtual addresses - base = P2V(base); -#endif - // endpoint of the block - uint32_t blend = base + length; - - // page count for this block - int npages = 0; - -#if ANY_KMEM - cio_printf( "-> base %08x len %08x: ", base, length ); -#endif - - // iterate through the block page by page - while( base < blend ) { - list_add( &free_pages, (void *) base ); - ++npages; - base += SZ_PAGE; - } - - // add the count to our running total - n_pages += npages; - -#if ANY_KMEM - cio_printf( " -> %d pages\n", npages ); -#endif -} - -/** -** Name: km_init -** -** Find what memory is present on the system and -** construct the list of free memory blocks. -** -** Dependencies: -** Must be called before any other init routine that uses -** dynamic storage is called. -*/ -void km_init( void ) { - int32_t entries; - region_t *region; - -#if TRACING_INIT - // announce that we're starting initialization - cio_puts( " Kmem" ); -#endif - - // initially, nothing in the free lists - free_slices.next = NULL; - free_pages.next = NULL; - n_pages = n_slices = 0; - km_initialized = 0; - - // get the list length - entries = *((int32_t *) MMAP_ADDR); - -#if KMEM_OR_INIT - cio_printf( "\nKmem: %d regions\n", entries ); -#endif - - // if there are no entries, we have nothing to do! - if( entries < 1 ) { // note: entries == -1 could occur! - return; - } - - // iterate through the entries, adding things to the freelist - - region = ((region_t *) (MMAP_ADDR + 4)); - - for( int i = 0; i < entries; ++i, ++region ) { - -#if KMEM_OR_INIT - // report this region - cio_printf( "%3d: ", i ); - cio_printf( " B %08x%08x", - region->base.HIGH, region->base.LOW ); - cio_printf( " L %08x%08x", - region->length.HIGH, region->length.LOW ); - cio_printf( " T %08x A %08x", - region->type, region->acpi ); -#endif - - /* - ** Determine whether or not we should ignore this region. - ** - ** We ignore regions for several reasons: - ** - ** ACPI indicates it should be ignored - ** ACPI indicates it's non-volatile memory - ** Region type isn't "usable" - ** Region is above our address limit - ** - ** Currently, only "normal" (type 1) regions are considered - ** "usable" for our purposes. We could potentially expand - ** this to include ACPI "reclaimable" memory. - */ - - // first, check the ACPI one-bit flags - - if( ((region->acpi) & REGION_IGNORE) == 0 ) { -#if KMEM_OR_INIT - cio_puts( " IGN\n" ); -#endif - continue; - } - - if( ((region->acpi) & REGION_NONVOL) != 0 ) { -#if KMEM_OR_INIT - cio_puts( " NVOL\n" ); -#endif - continue; // we'll ignore this, too - } - - // next, the region type - - if( (region->type) != REGION_USABLE ) { -#if KMEM_OR_INIT - cio_puts( " RCLM\n" ); -#endif - continue; // we won't attempt to reclaim ACPI memory (yet) - } - - /* - ** We have a "normal" memory region. We need to verify - ** that it's within our constraints. - ** - ** We ignore anything below our KM_LOW_CUTOFF address. (In theory, - ** we should be able to re-use much of that space; in practice, - ** this is safer.) We won't add anything to the free list if it is: - ** - ** * below our KM_LOW_CUTOFF value - ** * above out KM_HIGH_CUTOFF value. - ** - ** For blocks which straddle one of those limits, we will - ** split it, and only use the portion that's within those - ** bounds. - */ - - // grab the two 64-bit values to simplify things - uint64_t base = region->base.all; - uint64_t length = region->length.all; - uint64_t endpt = base + length; - - // ignore it if it's above our high cutoff point - if( base >= KM_HIGH_CUTOFF || endpt >= KM_HIGH_CUTOFF ) { - - // is the whole thing too high, or just part? - if( base >= KM_HIGH_CUTOFF ) { - // it's all too high! -#if KMEM_OR_INIT - cio_puts( " HIGH\n" ); -#endif - continue; - } - - // some of it is usable - fix the end point - endpt = KM_HIGH_CUTOFF; - } - - // see if it's below our low cutoff point - if( base < KM_LOW_CUTOFF || endpt < KM_LOW_CUTOFF ) { - - // is the whole thing too low, or just part? - if( endpt < KM_LOW_CUTOFF ) { - // it's all below the cutoff! -#if KMEM_OR_INIT - cio_puts( " LOW\n" ); -#endif - continue; - } - - // some of it is usable - reset the base address - base = KM_LOW_CUTOFF; - - // recalculate the length - length = endpt - base; - } - - // we survived the gauntlet - add the new block - // - // we may have changed the base or endpoint, so - // we should recalculate the length - length = endpt - base; - -#if KMEM_OR_INIT - cio_puts( " OK\n" ); -#endif - - uint32_t b32 = base & ADDR_LOW_HALF; - uint32_t l32 = length & ADDR_LOW_HALF; - - add_block( b32, l32 ); - } - - // record the initialization - km_initialized = 1; - -#if KMEM_OR_INIT - delay( DELAY_3_SEC ); -#endif -} - -/** -** Name: km_dump -** -** Dump information about the free lists to the console. By default, -** prints only the list sizes; if 'addrs' is true, also dumps the list -** of page addresses; if 'all' is also true, dumps page addresses and -** slice addresses. -** -** @param addrs Also dump page addresses -** @param both Also dump slice addresses -*/ -void km_dump( bool_t addrs, bool_t both ) { - - // report the sizes - cio_printf( "&free_pages %08x, &free_slices %08x, %u pages, %u slices\n", - (uint32_t) &free_pages, (uint32_t) &free_slices, - n_pages, n_slices ); - - // was that all? - if( !addrs ) { - return; - } - - // dump the addresses of the pages in the free list - uint32_t n = 0; - list_t *block = free_pages.next; - while( block != NULL ) { - if( n && !(n & MOD4_BITS) ) { - // four per line - cio_putchar( '\n' ); - } - cio_printf( " page @ 0x%08x", (uint32_t) block ); - block = block->next; - ++n; - } - - // sanity check - verify that the counts match - if( n != n_pages ) { - sprint( b256, "km_dump: n_pages %u, counted %u!!!\n", - n_pages, n ); - WARNING( b256); - } - - if( !both ) { - return; - } - - // but wait - there's more! - - // also dump the addresses of slices in the slice free list - n = 0; - block = free_slices.next; - while( block != NULL ) { - if( n && !(n & MOD4_BITS) ) { - // four per line - cio_putchar( '\n' ); - } - cio_printf( " slc @ 0x%08x", (uint32_t) block ); - block = block->next; - ++n; - } - - // sanity check - verify that the counts match - if( n != n_slices ) { - sprint( b256, "km_dump: n_slices %u, counted %u!!!\n", - n_slices, n ); - WARNING( b256); - } -} - -/* -** PAGE MANAGEMENT -*/ - -/** -** Name: km_page_alloc -** -** Allocate a page of memory from the free list. -** -** @return a pointer to the beginning of the allocated page, -** or NULL if no memory is available -*/ -void *km_page_alloc( void ) { - - // if km_init() wasn't called first, stop us in our tracks - assert( km_initialized ); - -#if TRACING_KMEM_FREELIST - cio_puts( "KM: pg_alloc()" ); -#endif - - // pointer to the first block - void *page = list_remove( &free_pages ); - - // was a page available? - if( page == NULL ){ - // nope! -#if TRACING_KMEM_FREELIST - cio_puts( " FAIL\n" ); -#endif -#if ALLOC_FAIL_PANIC - PANIC( 0, "page alloc failed" ); -#else - return NULL; -#endif - } - - // fix the count of available pages - --n_pages; - -#if TRACING_KMEM_FREELIST - cio_printf( " -> %08x\n", (uint32_t) page ); -#endif - - return( page ); -} - -/** -** Name: km_page_free -** -** Returns a page to the list of available pages. -** -** @param[in] page Pointer to the page to be returned to the free list -*/ -void km_page_free( void *page ){ - - // verify that km_init() was called first - assert( km_initialized ); - -#if TRACING_KMEM_FREELIST - cio_printf( "KM: pg_free(%08x)\n", (uint32_t) page ); -#endif - - /* - ** Don't do anything if the address is NULL. - */ - if( page == NULL ){ - return; - } - - - /* - ** CRITICAL ASSUMPTION - ** - ** We assume that the block pointer given to us points to a single - ** page-sized block of memory. We make this assumption because we - ** don't track allocation sizes. We can't use the simple "allocate - ** four extra bytes before the returned pointer" scheme to do this - ** because we're managing pages, and the pointers we return must point - ** to page boundaries, so we would wind up allocating an extra page - ** for each allocation. - ** - ** Alternatively, we could keep an array of addresses and block - ** sizes ourselves, but that feels clunky, and would risk running out - ** of table entries if there are lots of allocations (assuming we use - ** a 4KB page to hold the table, at eight bytes per entry we would have - ** 512 entries per page). - ** - ** IF THIS ASSUMPTION CHANGES, THIS CODE MUST BE FIXED!!! - */ - - // link this into the free list - list_add( &free_pages, page ); - - // one more in the pool - ++n_pages; -} - -/* -** SLICE MANAGEMENT -*/ - -/* -** Slices are 1024-byte fragments from pages. We maintain a free list of -** slices for those parts of the OS which don't need full 4096-byte chunks -** of space. -*/ - -/** -** Name: carve_slices -** -** Split an allocated page into four slices and add -** them to the "free slices" list. -** -** @param page Pointer to the page to be carved up -*/ -static void carve_slices( void *page ) { - - // sanity check - assert1( page != NULL ); - -#if TRACING_KMEM_FREELIST - cio_printf( "KM: carve_slices(%08x)\n", (uint32_t) page ); -#endif - - // create the four slices from it - uint8_t *ptr = (uint8_t *) page; - for( int i = 0; i < 4; ++i ) { - km_slice_free( (void *) ptr ); - ptr += SZ_SLICE; - ++n_slices; - } -} - -/** -** Name: km_slice_alloc -** -** Dynamically allocates a slice (1/4 of a page). If no -** memory is available, we return NULL (unless ALLOC_FAIL_PANIC -** was defined, in which case we panic). -** -** @return a pointer to the allocated slice -*/ -void *km_slice_alloc( void ) { - - // verify that km_init() was called first - assert( km_initialized ); - -#if TRACING_KMEM_FREELIST - cio_printf( "KM: sl_alloc()\n" ); -#endif - - // if we are out of slices, create a few more - if( free_slices.next == NULL ) { - void *new = km_page_alloc(); - if( new == NULL ) { - // can't get any more space -#if ALLOC_FAIL_PANIC - PANIC( 0, "slice new alloc failed" ); -#else - return NULL; -#endif - } - carve_slices( new ); - } - - // take the first one from the free list - void *slice = list_remove( &free_slices ); - assert( slice != NULL ); - --n_slices; - - // make it nice and shiny for the caller - memclr( (void *) slice, SZ_SLICE ); - - return( slice ); -} - -/** -** Name: km_slice_free -** -** Returns a slice to the list of available slices. -** -** We make no attempt to merge slices, as we treat them as -** independent blocks of memory (like pages). -** -** @param[in] block Pointer to the slice (1/4 page) to be freed -*/ -void km_slice_free( void *block ) { - - // verify that km_init() was called first - assert( km_initialized ); - -#if TRACING_KMEM_FREELIST - cio_printf( "KM: sl_free(%08x)\n", (uint32_t) block ); -#endif - - // just add it to the front of the free list - list_add( &free_slices, block ); - --n_slices; -} diff --git a/kernel/old/list.c b/kernel/old/list.c deleted file mode 100644 index 084000a..0000000 --- a/kernel/old/list.c +++ /dev/null @@ -1,64 +0,0 @@ -/** -** @file list.c -** -** @author Warren R. Carithers -** -** @brief Support for a basic linked list data type. -** -** This module provides a very basic linked list data structure. -** A list can contain anything that has a pointer field in the first -** four bytes; these routines assume those bytes contain a pointer to -** the following entry in the list, whatever that may be. -*/ - -#define KERNEL_SRC - -#include - -#include - -/* -** FUNCTIONS -*/ - -/** -** Name: list_add -** -** Add the supplied data to the beginning of the specified list. -** -** @param[in,out] list The address of a list_t variable -** @param[in] data The data to prepend to the list -*/ -void list_add( list_t *list, void *data ) { - - // sanity checks - assert1( list != NULL ); - assert1( data != NULL ); - - list_t *tmp = (list_t *)data; - tmp->next = list->next; - list->next = tmp; -} - -/** -** Name: list_remove -** -** Remove the first entry from a linked list. -** -** @param[in,out] list The address of a list_t variable -** -** @return a pointer to the removed data, or NULL if the list was empty -*/ -void *list_remove( list_t *list ) { - - assert1( list != NULL ); - - list_t *data = list->next; - if( data != NULL ) { - list->next = data->next; - data->next = NULL; - } - - return (void *)data; -} - diff --git a/kernel/old/procs.c b/kernel/old/procs.c deleted file mode 100644 index 96bb3fd..0000000 --- a/kernel/old/procs.c +++ /dev/null @@ -1,1136 +0,0 @@ -/* -** @file procs.c -** -** @author CSCI-452 class of 20245 -** -** @brief Process-related implementations -*/ - -#define KERNEL_SRC - -#include - -#include -#include - -/* -** PRIVATE DEFINITIONS -*/ - -// determine if a queue is empty; assumes 'q' is a valid pointer -#define PCB_QUEUE_EMPTY(q) ((q)->head == NULL) - -/* -** PRIVATE DATA TYPES -*/ - -/* -** PCB Queue structure -** -** Opaque to the rest of the kernel -** -** Typedef'd in the header: typedef struct pcb_queue_s *pcb_queue_t; -*/ -struct pcb_queue_s { - pcb_t *head; - pcb_t *tail; - enum pcb_queue_order_e order; -}; - -/* -** PRIVATE GLOBAL VARIABLES -*/ - -// collection of queues -static struct pcb_queue_s pcb_freelist_queue; -static struct pcb_queue_s ready_queue; -static struct pcb_queue_s waiting_queue; -static struct pcb_queue_s sleeping_queue; -static struct pcb_queue_s zombie_queue; -static struct pcb_queue_s sioread_queue; - -/* -** PUBLIC GLOBAL VARIABLES -*/ - -// public-facing queue handles -pcb_queue_t pcb_freelist; -pcb_queue_t ready; -pcb_queue_t waiting; -pcb_queue_t sleeping; -pcb_queue_t zombie; -pcb_queue_t sioread; - -// pointer to the currently-running process -pcb_t *current; - -// the process table -pcb_t ptable[N_PROCS]; - -// next available PID -uint_t next_pid; - -// pointer to the PCB for the 'init' process -pcb_t *init_pcb; - -// table of state name strings -const char *state_str[N_STATES] = { - [ STATE_UNUSED ] = "Unu", // "Unused" - [ STATE_NEW ] = "New", - [ STATE_READY ] = "Rdy", // "Ready" - [ STATE_RUNNING ] = "Run", // "Running" - [ STATE_SLEEPING ] = "Slp", // "Sleeping" - [ STATE_BLOCKED ] = "Blk", // "Blocked" - [ STATE_WAITING ] = "Wat", // "Waiting" - [ STATE_KILLED ] = "Kil", // "Killed" - [ STATE_ZOMBIE ] = "Zom" // "Zombie" -}; - -// table of priority name strings -const char *prio_str[N_PRIOS] = { - [ PRIO_HIGH ] = "High", - [ PRIO_STD ] = "User", - [ PRIO_LOW ] = "Low ", - [ PRIO_DEFERRED ] = "Def " -}; - -// table of queue ordering name strings -const char *ord_str[N_PRIOS] = { - [ O_FIFO ] = "FIFO", - [ O_PRIO ] = "PRIO", - [ O_PID ] = "PID ", - [ O_WAKEUP ] = "WAKE" -}; - -/* -** PRIVATE FUNCTIONS -*/ - -/** -** Priority search functions. These are used to traverse a supplied -** queue looking for the queue entry that would precede the supplied -** PCB when that PCB is inserted into the queue. -** -** Variations: -** find_prev_wakeup() compares wakeup times -** find_prev_priority() compares process priorities -** find_prev_pid() compares PIDs -** -** Each assumes the queue should be in ascending order by the specified -** comparison value. -** -** @param[in] queue The queue to search -** @param[in] pcb The PCB to look for -** -** @return a pointer to the predecessor in the queue, or NULL if -** this PCB would be at the beginning of the queue. -*/ -static pcb_t *find_prev_wakeup( pcb_queue_t queue, pcb_t *pcb ) { - - // sanity checks! - assert1( queue != NULL ); - assert1( pcb != NULL ); - - pcb_t *prev = NULL; - pcb_t *curr = queue->head; - - while( curr != NULL && curr->wakeup <= pcb->wakeup ) { - prev = curr; - curr = curr->next; - } - - return prev; -} - -static pcb_t *find_prev_priority( pcb_queue_t queue, pcb_t *pcb ) { - - // sanity checks! - assert1( queue != NULL ); - assert1( pcb != NULL ); - - pcb_t *prev = NULL; - pcb_t *curr = queue->head; - - while( curr != NULL && curr->priority <= pcb->priority ) { - prev = curr; - curr = curr->next; - } - - return prev; -} - -static pcb_t *find_prev_pid( pcb_queue_t queue, pcb_t *pcb ) { - - // sanity checks! - assert1( queue != NULL ); - assert1( pcb != NULL ); - - pcb_t *prev = NULL; - pcb_t *curr = queue->head; - - while( curr != NULL && curr->pid <= pcb->pid ) { - prev = curr; - curr = curr->next; - } - - return prev; -} - -/* -** PUBLIC FUNCTIONS -*/ - -// a macro to simplify queue setup -#define QINIT(q,s) \ - q = &q##_queue; \ - if( pcb_queue_reset(q,s) != SUCCESS ) { \ - PANIC( 0, "pcb_init can't reset " # q ); \ - } - -/** -** Name: pcb_init -** -** Initialization for the Process module. -*/ -void pcb_init( void ) { - -#if TRACING_INIT - cio_puts( " Procs" ); -#endif - - // there is no current process - current = NULL; - - // set up the external links to the queues - QINIT( pcb_freelist, O_FIFO ); - QINIT( ready, O_PRIO ); - QINIT( waiting, O_PID ); - QINIT( sleeping, O_WAKEUP ); - QINIT( zombie, O_PID ); - QINIT( sioread, O_FIFO ); - - /* - ** We statically allocate our PCBs, so we need to add them - ** to the freelist before we can use them. If this changes - ** so that we dynamicallyl allocate PCBs, this step either - ** won't be required, or could be used to pre-allocate some - ** number of PCB structures for future use. - */ - - pcb_t *ptr = ptable; - for( int i = 0; i < N_PROCS; ++i ) { - pcb_free( ptr ); - ++ptr; - } -} - -/** -** Name: pcb_alloc -** -** Allocate a PCB from the list of free PCBs. -** -** @param pcb Pointer to a pcb_t * where the PCB pointer will be returned. -** -** @return status of the allocation attempt -*/ -int pcb_alloc( pcb_t **pcb ) { - - // sanity check! - assert1( pcb != NULL ); - - // remove the first PCB from the free list - pcb_t *tmp; - if( pcb_queue_remove(pcb_freelist,&tmp) != SUCCESS ) { - return E_NO_PCBS; - } - - *pcb = tmp; - return SUCCESS; -} - -/** -** Name: pcb_free -** -** Return a PCB to the list of free PCBs. -** -** @param pcb Pointer to the PCB to be deallocated. -*/ -void pcb_free( pcb_t *pcb ) { - - if( pcb != NULL ) { - // mark the PCB as available - pcb->state = STATE_UNUSED; - - // add it to the free list - int status = pcb_queue_insert( pcb_freelist, pcb ); - - // if that failed, we're in trouble - if( status != SUCCESS ) { - sprint( b256, "pcb_free(0x%08x) status %d", (uint32_t) pcb, - status ); - PANIC( 0, b256 ); - } - } -} - -/** -** Name: pcb_zombify -** -** Turn the indicated process into a Zombie. This function -** does most of the real work for exit() and kill() calls. -** Is also called from the scheduler and dispatcher. -** -** @param pcb Pointer to the newly-undead PCB -*/ -void pcb_zombify( register pcb_t *victim ) { - - // should this be an error? - if( victim == NULL ) { - return; - } - - // every process must have a parent, even if it's 'init' - assert( victim->parent != NULL ); - - /* - ** We need to locate the parent of this process. We also need - ** to reparent any children of this process. We do these in - ** a single loop. - */ - pcb_t *parent = victim->parent; - pcb_t *zchild = NULL; - - // two PIDs we will look for - uint_t vicpid = victim->pid; - - // speed up access to the process table entries - register pcb_t *curr = ptable; - - for( int i = 0; i < N_PROCS; ++i, ++curr ) { - - // make sure this is a valid entry - if( curr->state == STATE_UNUSED ) { - continue; - } - - // if this is our parent, just keep going - we continue - // iterating to find all the children of this process. - if( curr == parent ) { - continue; - } - - if( curr->parent == victim ) { - - // found a child - reparent it - curr->parent = init_pcb; - - // see if this child is already undead - if( curr->state == STATE_ZOMBIE ) { - // if it's already a zombie, remember it, so we - // can pass it on to 'init'; also, if there are - // two or more zombie children, it doesn't matter - // which one we pick here, as the others will be - // collected when 'init' loops - zchild = curr; - } - - } - } - - /* - ** If we found a child that was already terminated, we need to - ** wake up the init process if it's already waiting. - ** - ** Note: we only need to do this for one Zombie child process - - ** init will loop and collect the others after it finishes with - ** this one. - ** - ** Also note: it's possible that the exiting process' parent is - ** also init, which means we're letting one of zombie children - ** of the exiting process be cleaned up by init before the - ** existing process itself is cleaned up by init. This will work, - ** because after init cleans up the zombie, it will loop and - ** call waitpid() again, by which time this exiting process will - ** be marked as a zombie. - */ - if( zchild != NULL && init_pcb->state == STATE_WAITING ) { - - // dequeue the zombie - assert( pcb_queue_remove_this(zombie,zchild) == SUCCESS ); - - assert( pcb_queue_remove_this(waiting,init_pcb) == SUCCESS ); - - // intrinsic return value is the PID - RET(init_pcb) = zchild->pid; - - // may also want to return the exit status - int32_t *ptr = (int32_t *) ARG(init_pcb,2); - - if( ptr != NULL ) { - // ******************************************************** - // ** Potential VM issue here! This code assigns the exit - // ** status into a variable in the parent's address space. - // ** This works in the baseline because we aren't using - // ** any type of memory protection. If address space - // ** separation is implemented, this code will very likely - // ** STOP WORKING, and will need to be fixed. - // ******************************************************** - *ptr = zchild->exit_status; - } - - // all done - schedule 'init', and clean up the zombie - schedule( init_pcb ); - pcb_cleanup( zchild ); - } - - /* - ** Now, deal with the parent of this process. If the parent is - ** already waiting, just wake it up and clean up this process. - ** Otherwise, this process becomes a zombie. - ** - ** Note: if the exiting process' parent is init and we just woke - ** init up to deal with a zombie child of the exiting process, - ** init's status won't be Waiting any more, so we don't have to - ** worry about it being scheduled twice. - */ - - if( parent->state == STATE_WAITING ) { - - // verify that the parent is either waiting for this process - // or is waiting for any of its children - uint32_t target = ARG(parent,1); - - if( target == 0 || target == vicpid ) { - - // the parent is waiting for this child or is waiting - // for any of its children, so we can wake it up. - - // intrinsic return value is the PID - RET(parent) = vicpid; - - // may also want to return the exit status - int32_t *ptr = (int32_t *) ARG(parent,2); - - if( ptr != NULL ) { - // ******************************************************** - // ** Potential VM issue here! This code assigns the exit - // ** status into a variable in the parent's address space. - // ** This works in the baseline because we aren't using - // ** any type of memory protection. If address space - // ** separation is implemented, this code will very likely - // ** STOP WORKING, and will need to be fixed. - // ******************************************************** - *ptr = victim->exit_status; - } - - // all done - schedule the parent, and clean up the zombie - schedule( parent ); - pcb_cleanup( victim ); - - return; - } - } - - /* - ** The parent isn't waiting OR is waiting for a specific child - ** that isn't this exiting process, so we become a Zombie. - ** - ** This code assumes that Zombie processes are *not* in - ** a queue, but instead are just in the process table with - ** a state of 'Zombie'. This simplifies life immensely, - ** because we won't need to dequeue it when it is collected - ** by its parent. - */ - - victim->state = STATE_ZOMBIE; - assert( pcb_queue_insert(zombie,victim) == SUCCESS ); - - /* - ** Note: we don't call _dispatch() here - we leave that for - ** the calling routine, as it's possible we don't need to - ** choose a new current process. - */ -} - -/** -** Name: pcb_cleanup -** -** Reclaim a process' data structures -** -** @param pcb The PCB to reclaim -*/ -void pcb_cleanup( pcb_t *pcb ) { - -#if TRACING_PCB - cio_printf( "** pcb_cleanup(0x%08x)\n", (uint32_t) pcb ); -#endif - - // avoid deallocating a NULL pointer - if( pcb == NULL ) { - // should this be an error? - return; - } - - // we need to release all the VM data structures and frames - user_cleanup( pcb ); - - // release the PCB itself - pcb_free( pcb ); -} - -/** -** Name: pcb_find_pid -** -** Locate the PCB for the process with the specified PID -** -** @param pid The PID to be located -** -** @return Pointer to the PCB, or NULL -*/ -pcb_t *pcb_find_pid( uint_t pid ) { - - // must be a valid PID - if( pid < 1 ) { - return NULL; - } - - // scan the process table - pcb_t *p = ptable; - - for( int i = 0; i < N_PROCS; ++i, ++p ) { - if( p->pid == pid && p->state != STATE_UNUSED ) { - return p; - } - } - - // didn't find it! - return NULL; -} - -/** -** Name: pcb_find_ppid -** -** Locate the PCB for the process with the specified parent -** -** @param pid The PID to be located -** -** @return Pointer to the PCB, or NULL -*/ -pcb_t *pcb_find_ppid( uint_t pid ) { - - // must be a valid PID - if( pid < 1 ) { - return NULL; - } - - // scan the process table - pcb_t *p = ptable; - - for( int i = 0; i < N_PROCS; ++i, ++p ) { - assert1( p->parent != NULL ); - if( p->parent->pid == pid && p->parent->state != STATE_UNUSED ) { - return p; - } - } - - // didn't find it! - return NULL; -} - -/** -** Name: pcb_queue_reset -** -** Initialize a PCB queue. We assume that whatever data may be -** in the queue structure can be overwritten. -** -** @param queue[out] The queue to be initialized -** @param order[in] The desired ordering for the queue -** -** @return status of the init request -*/ -int pcb_queue_reset( pcb_queue_t queue, enum pcb_queue_order_e style ) { - - // sanity check - assert1( queue != NULL ); - - // make sure the style is valid - if( style < O_FIRST_STYLE || style > O_LAST_STYLE ) { - return E_BAD_PARAM; - } - - // reset the queue - queue->head = queue->tail = NULL; - queue->order = style; - - return SUCCESS; -} - -/** -** Name: pcb_queue_empty -** -** Determine whether a queue is empty. Essentially just a wrapper -** for the PCB_QUEUE_EMPTY() macro, for use outside this module. -** -** @param[in] queue The queue to check -** -** @return true if the queue is empty, else false -*/ -bool_t pcb_queue_empty( pcb_queue_t queue ) { - - // if there is no queue, blow up - assert1( queue != NULL ); - - return PCB_QUEUE_EMPTY(queue); -} - -/** -** Name: pcb_queue_length -** -** Return the count of elements in the specified queue. -** -** @param[in] queue The queue to check -** -** @return the count (0 if the queue is empty) -*/ -uint_t pcb_queue_length( const pcb_queue_t queue ) { - - // sanity check - assert1( queue != NULL ); - - // this is pretty simple - register pcb_t *tmp = queue->head; - register int num = 0; - - while( tmp != NULL ) { - ++num; - tmp = tmp->next; - } - - return num; -} - -/** -** Name: pcb_queue_insert -** -** Inserts a PCB into the indicated queue. -** -** @param queue[in,out] The queue to be used -** @param pcb[in] The PCB to be inserted -** -** @return status of the insertion request -*/ -int pcb_queue_insert( pcb_queue_t queue, pcb_t *pcb ) { - - // sanity checks - assert1( queue != NULL ); - assert1( pcb != NULL ); - - // if this PCB is already in a queue, we won't touch it - if( pcb->next != NULL ) { - // what to do? we let the caller decide - return E_BAD_PARAM; - } - - // is the queue empty? - if( queue->head == NULL ) { - queue->head = queue->tail = pcb; - return SUCCESS; - } - assert1( queue->tail != NULL ); - - // no, so we need to search it - pcb_t *prev = NULL; - - // find the predecessor node - switch( queue->order ) { - case O_FIFO: - prev = queue->tail; - break; - case O_PRIO: - prev = find_prev_priority(queue,pcb); - break; - case O_PID: - prev = find_prev_pid(queue,pcb); - break; - case O_WAKEUP: - prev = find_prev_wakeup(queue,pcb); - break; - default: - // do we need something more specific here? - return E_BAD_PARAM; - } - - // OK, we found the predecessor node; time to do the insertion - - if( prev == NULL ) { - - // there is no predecessor, so we're - // inserting at the front of the queue - pcb->next = queue->head; - if( queue->head == NULL ) { - // empty queue!?! - should we panic? - queue->tail = pcb; - } - queue->head = pcb; - - } else if( prev->next == NULL ) { - - // append at end - prev->next = pcb; - queue->tail = pcb; - - } else { - - // insert between prev & prev->next - pcb->next = prev->next; - prev->next = pcb; - - } - - return SUCCESS; -} - -/** -** Name: pcb_queue_remove -** -** Remove the first PCB from the indicated queue. -** -** @param queue[in,out] The queue to be used -** @param pcb[out] Pointer to where the PCB pointer will be saved -** -** @return status of the removal request -*/ -int pcb_queue_remove( pcb_queue_t queue, pcb_t **pcb ) { - - //sanity checks - assert1( queue != NULL ); - assert1( pcb != NULL ); - - // can't get anything if there's nothing to get! - if( PCB_QUEUE_EMPTY(queue) ) { - return E_EMPTY_QUEUE; - } - - // take the first entry from the queue - pcb_t *tmp = queue->head; - queue->head = tmp->next; - - // disconnect it completely - tmp->next = NULL; - - // was this the last thing in the queue? - if( queue->head == NULL ) { - // yes, so clear the tail pointer for consistency - queue->tail = NULL; - } - - // save the pointer - *pcb = tmp; - - return SUCCESS; -} - -/** -** Name: pcb_queue_remove_this -** -** Remove the specified PCB from the indicated queue. -** -** We don't return the removed pointer, because the calling -** routine must already have it (because it was supplied -** to us in the call). -** -** @param queue[in,out] The queue to be used -** @param pcb[in] Pointer to the PCB to be removed -** -** @return status of the removal request -*/ -int pcb_queue_remove_this( pcb_queue_t queue, pcb_t *pcb ) { - - //sanity checks - assert1( queue != NULL ); - assert1( pcb != NULL ); - - // can't get anything if there's nothing to get! - if( PCB_QUEUE_EMPTY(queue) ) { - return E_EMPTY_QUEUE; - } - - // iterate through the queue until we find the desired PCB - pcb_t *prev = NULL; - pcb_t *curr = queue->head; - - while( curr != NULL && curr != pcb ) { - prev = curr; - curr = curr->next; - } - - // case prev curr next interpretation - // ==== ==== ==== ==== ============================ - // 1. 0 0 -- *** CANNOT HAPPEN *** - // 2. 0 !0 0 removing only element - // 3. 0 !0 !0 removing first element - // 4. !0 0 -- *** NOT FOUND *** - // 5. !0 !0 0 removing from end - // 6. !0 !0 !0 removing from middle - - if( curr == NULL ) { - // case 1 - assert( prev != NULL ); - // case 4 - return E_NOT_FOUND; - } - - // connect predecessor to successor - if( prev != NULL ) { - // not the first element - // cases 5 and 6 - prev->next = curr->next; - } else { - // removing first element - // cases 2 and 3 - queue->head = curr->next; - } - - // if this was the last node (cases 2 and 5), - // also need to reset the tail pointer - if( curr->next == NULL ) { - // if this was the only entry (2), prev is NULL, - // so this works for that case, too - queue->tail = prev; - } - - // unlink current from queue - curr->next = NULL; - - // there's a possible consistancy problem here if somehow - // one of the queue pointers is NULL and the other one - // is not NULL - - assert1( - (queue->head == NULL && queue->tail == NULL) || - (queue->head != NULL && queue->tail != NULL) - ); - - return SUCCESS; -} - -/** -** Name: pcb_queue_peek -** -** Return the first PCB from the indicated queue, but don't -** remove it from the queue. -** -** @param queue[in] The queue to be used -** -** @return the PCB poiner, or NULL if the queue is empty -*/ -pcb_t *pcb_queue_peek( const pcb_queue_t queue ) { - - //sanity check - assert1( queue != NULL ); - - // can't get anything if there's nothing to get! - if( PCB_QUEUE_EMPTY(queue) ) { - return NULL; - } - - // just return the first entry from the queue - return queue->head; -} - -/* -** Scheduler routines -*/ - -/** -** schedule(pcb) -** -** Schedule the supplied process -** -** @param pcb Pointer to the PCB of the process to be scheduled -*/ -void schedule( pcb_t *pcb ) { - - // sanity check - assert1( pcb != NULL ); - - // check for a killed process - if( pcb->state == STATE_KILLED ) { - // TODO figure out what to do now - return; - } - - // mark it as ready - pcb->state = STATE_READY; - - // add it to the ready queue - if( pcb_queue_insert(ready,pcb) != SUCCESS ) { - PANIC( 0, "schedule insert fail" ); - } -} - -/** -** dispatch() -** -** Select the next process to receive the CPU -*/ -void dispatch( void ) { - - // verify that there is no current process - assert( current == NULL ); - - // grab whoever is at the head of the queue - int status = pcb_queue_remove( ready, ¤t ); - if( status != SUCCESS ) { - sprint( b256, "dispatch queue remove failed, code %d", status ); - PANIC( 0, b256 ); - } - - // set the process up for success - current->state = STATE_RUNNING; - current->ticks = QUANTUM_STANDARD; -} - - -/* -** Debugging/tracing routines -*/ - -/** -** ctx_dump(msg,context) -** -** Dumps the contents of this process context to the console -** -** @param msg[in] An optional message to print before the dump -** @param c[in] The context to dump out -*/ -void ctx_dump( const char *msg, register context_t *c ) { - - // first, the message (if there is one) - if( msg ) { - cio_puts( msg ); - } - - // the pointer - cio_printf( " @ %08x: ", (uint32_t) c ); - - // if it's NULL, why did you bother calling me? - if( c == NULL ) { - cio_puts( " NULL???\n" ); - return; - } - - // now, the contents - cio_printf( "ss %04x gs %04x fs %04x es %04x ds %04x cs %04x\n", - c->ss & 0xff, c->gs & 0xff, c->fs & 0xff, - c->es & 0xff, c->ds & 0xff, c->cs & 0xff ); - cio_printf( " edi %08x esi %08x ebp %08x esp %08x\n", - c->edi, c->esi, c->ebp, c->esp ); - cio_printf( " ebx %08x edx %08x ecx %08x eax %08x\n", - c->ebx, c->edx, c->ecx, c->eax ); - cio_printf( " vec %08x cod %08x eip %08x eflags %08x\n", - c->vector, c->code, c->eip, c->eflags ); -} - -/** -** ctx_dump_all(msg) -** -** dump the process context for all active processes -** -** @param msg[in] Optional message to print -*/ -void ctx_dump_all( const char *msg ) { - - if( msg != NULL ) { - cio_puts( msg ); - } - - int n = 0; - register pcb_t *pcb = ptable; - for( int i = 0; i < N_PROCS; ++i, ++pcb ) { - if( pcb->state != STATE_UNUSED ) { - ++n; - cio_printf( "%2d(%d): ", n, pcb->pid ); - ctx_dump( NULL, pcb->context ); - } - } -} - -/** -** _pcb_dump(msg,pcb) -** -** Dumps the contents of this PCB to the console -** -** @param msg[in] An optional message to print before the dump -** @param pcb[in] The PCB to dump -** @param all[in] Dump all the contents? -*/ -void pcb_dump( const char *msg, register pcb_t *pcb, bool_t all ) { - - // first, the message (if there is one) - if( msg ) { - cio_puts( msg ); - } - - // the pointer - cio_printf( " @ %08x:", (uint32_t) pcb ); - - // if it's NULL, why did you bother calling me? - if( pcb == NULL ) { - cio_puts( " NULL???\n" ); - return; - } - - cio_printf( " %d", pcb->pid ); - cio_printf( " %s", - pcb->state >= N_STATES ? "???" : state_str[pcb->state] ); - - if( !all ) { - // just printing IDs and states on one line - return; - } - - // now, the rest of the contents - cio_printf( " %s", - pcb->priority >= N_PRIOS ? "???" : prio_str[pcb->priority] ); - - cio_printf( " ticks %u xit %d wake %08x\n", - pcb->ticks, pcb->exit_status, pcb->wakeup ); - - cio_printf( " parent %08x", (uint32_t)pcb->parent ); - if( pcb->parent != NULL ) { - cio_printf( " (%u)", pcb->parent->pid ); - } - - cio_printf( " next %08x context %08x pde %08x", (uint32_t) pcb->next, - (uint32_t) pcb->context, (uint32_t) pcb->pdir ); - - cio_putchar( '\n' ); -} - -/** -** pcb_queue_dump(msg,queue,contents) -** -** Dump the contents of the specified queue to the console -** -** @param msg[in] Optional message to print -** @param queue[in] The queue to dump -** @param contents[in] Also dump (some) contents? -*/ -void pcb_queue_dump( const char *msg, pcb_queue_t queue, bool_t contents ) { - - // report on this queue - cio_printf( "%s: ", msg ); - if( queue == NULL ) { - cio_puts( "NULL???\n" ); - return; - } - - // first, the basic data - cio_printf( "head %08x tail %08x", - (uint32_t) queue->head, (uint32_t) queue->tail ); - - // next, how the queue is ordered - cio_printf( " order %s\n", - queue->order >= N_ORDERINGS ? "????" : ord_str[queue->order] ); - - // if there are members in the queue, dump the first few PIDs - if( contents && queue->head != NULL ) { - cio_puts( " PIDs: " ); - pcb_t *tmp = queue->head; - for( int i = 0; i < 5 && tmp != NULL; ++i, tmp = tmp->next ) { - cio_printf( " [%u]", tmp->pid ); - } - - if( tmp != NULL ) { - cio_puts( " ..." ); - } - - cio_putchar( '\n' ); - } -} - -/** -** ptable_dump(msg,all) -** -** dump the contents of the "active processes" table -** -** @param msg[in] Optional message to print -** @param all[in] Dump all or only part of the relevant data -*/ -void ptable_dump( const char *msg, bool_t all ) { - - if( msg ) { - cio_puts( msg ); - } - cio_putchar( ' ' ); - - int used = 0; - int empty = 0; - - register pcb_t *pcb = ptable; - for( int i = 0; i < N_PROCS; ++i ) { - if( pcb->state == STATE_UNUSED ) { - - // an empty slot - ++empty; - - } else { - - // a non-empty slot - ++used; - - // if not dumping everything, add commas if needed - if( !all && used ) { - cio_putchar( ',' ); - } - - // report the table slot # - cio_printf( " #%d:", i ); - - // and dump the contents - pcb_dump( NULL, pcb, all ); - } - } - - // only need this if we're doing one-line output - if( !all ) { - cio_putchar( '\n' ); - } - - // sanity check - make sure we saw the correct number of table slots - if( (used + empty) != N_PROCS ) { - cio_printf( "Table size %d, used %d + empty %d = %d???\n", - N_PROCS, used, empty, used + empty ); - } -} - -/** -** Name: ptable_dump_counts -** -** Prints basic information about the process table (number of -** entries, number with each process state, etc.). -*/ -void ptable_dump_counts( void ) { - uint_t nstate[N_STATES] = { 0 }; - uint_t unknown = 0; - - int n = 0; - pcb_t *ptr = ptable; - while( n < N_PROCS ) { - if( ptr->state < 0 || ptr->state >= N_STATES ) { - ++unknown; - } else { - ++nstate[ptr->state]; - } - ++n; - ++ptr; - } - - cio_printf( "Ptable: %u ***", unknown ); - for( n = 0; n < N_STATES; ++n ) { - cio_printf( " %u %s", nstate[n], - state_str[n] != NULL ? state_str[n] : "???" ); - } - cio_putchar( '\n' ); -} diff --git a/kernel/old/sio.c b/kernel/old/sio.c deleted file mode 100644 index a5c7b75..0000000 --- a/kernel/old/sio.c +++ /dev/null @@ -1,694 +0,0 @@ -/** -** @file sio.c -** -** @author Warren R. Carithers -** -** @brief SIO module -** -** For maximum compatibility from semester to semester, this code uses -** several "stand-in" type names and macros which should be defined -** in the accompanying "compat.h" header file if they're not part of -** the baseline system: -** -** standard-sized integer types: intN_t, uintN_t -** other types: PCBTYPE, QTYPE -** scheduler functions: SCHED, DISPATCH -** queue functions: QCREATE, QLENGTH, QDEQUE -** other functions: SLENGTH -** sio read queue: QNAME -** -** Our SIO scheme is very simple: -** -** Input: We maintain a buffer of incoming characters that haven't -** yet been read by processes. When a character comes in, if -** there is no process waiting for it, it goes in the buffer; -** otherwise, the first waiting process is awakeneda and it -** gets the character. -** -** When a process invokes readch(), if there is a character in -** the input buffer, the process gets it; otherwise, it is -** blocked until input appears -** -** Communication with system calls is via two routines. -** sio_readc() returns the first available character (if -** there is one), resetting the input variables if this was -** the last character in the buffer. If there are no -** characters in the buffer, sio_read() returns a -1 -** (presumably so the requesting process can be blocked). -** -** sio_read() copies the contents of the input buffer into -** a user-supplied buffer. It returns the number of characters -** copied. If there are no characters available, return a -1. -** -** Output: We maintain a buffer of outgoing characters that haven't -** yet been sent to the device, and an indication of whether -** or not we are in the middle of a transmit sequence. When -** an interrupt comes in, if there is another character to -** send we copy it to the transmitter buffer; otherwise, we -** end the transmit sequence. -** -** Communication with user processes is via three functions. -** sio_writec() writes a single character; sio_write() -** writes a sized buffer full of characters; sio_puts() -** prints a NUL-terminated string. If we are in the middle -** of a transmit sequence, all characters will be added -** to the output buffer (from where they will be sent -** automatically); otherwise, we send the first character -** directly, add the rest of the characters (if there are -** any) to the output buffer, and set the "sending" flag -** to indicate that we're expecting a transmitter interrupt. -*/ - -#define KERNEL_SRC - -// this should do all includes required for this OS -#include - -// all other framework includes are next -#include -#include -#include - -#include -#include - -/* -** PRIVATE DEFINITIONS -*/ - -#define BUF_SIZE 2048 - -/* -** PRIVATE GLOBALS -*/ - - // input character buffer -static char inbuffer[ BUF_SIZE ]; -static char *inlast; -static char *innext; -static uint32_t incount; - - // output character buffer -static char outbuffer[ BUF_SIZE ]; -static char *outlast; -static char *outnext; -static uint32_t outcount; - - // output control flag -static int sending; - - // interrupt register status -static uint8_t ier; - -/* -** PUBLIC GLOBAL VARIABLES -*/ - -// queue for read-blocked processes -#ifdef QNAME -QTYPE QNAME; -#endif - -/* -** PRIVATE FUNCTIONS -*/ - -/** -** sio_isr(vector,ecode) -** -** Interrupt handler for the SIO module. Handles all pending -** events (as described by the SIO controller). -** -** @param vector The interrupt vector number for this interrupt -** @param ecode The error code associated with this interrupt -*/ -static void sio_isr( int vector, int ecode ) { - int ch; - -#if TRACING_SIO_ISR - cio_puts( "SIO: int:" ); -#endif - // - // Must process all pending events; loop until the IRR - // says there's nothing else to do. - // - - for(;;) { - - // get the "pending event" indicator - int iir = inb( UA4_IIR ) & UA4_IIR_INT_PRI_MASK; - - // process this event - switch( iir ) { - - case UA4_IIR_LINE_STATUS: - // shouldn't happen, but just in case.... - cio_printf( "** SIO int, LSR = %02x\n", inb(UA4_LSR) ); - break; - - case UA4_IIR_RX: -#if TRACING_SIO_ISR - cio_puts( " RX" ); -#endif - // get the character - ch = inb( UA4_RXD ); - if( ch == '\r' ) { // map CR to LF - ch = '\n'; - } -#if TRACING_SIO_ISR - cio_printf( " ch %02x", ch ); -#endif - -#ifdef QNAME - // - // If there is a waiting process, this must be - // the first input character; give it to that - // process and awaken the process. - // - - if( !QEMPTY(QNAME) ) { - PCBTYPE *pcb; - - QDEQUE( QNAME, pcb ); - // make sure we got a non-NULL result - assert( pcb ); - - // return char via arg #2 and count in EAX - char *buf = (char *) ARG(pcb,2); - *buf = ch & 0xff; - RET(pcb) = 1; - SCHED( pcb ); - - } else { -#endif /* QNAME */ - - // - // Nobody waiting - add to the input buffer - // if there is room, otherwise just ignore it. - // - - if( incount < BUF_SIZE ) { - *inlast++ = ch; - ++incount; - } - -#ifdef QNAME - } -#endif /* QNAME */ - break; - - case UA5_IIR_RX_FIFO: - // shouldn't happen, but just in case.... - ch = inb( UA4_RXD ); - cio_printf( "** SIO FIFO timeout, RXD = %02x\n", ch ); - break; - - case UA4_IIR_TX: -#if TRACING_SIO_ISR - cio_puts( " TX" ); -#endif - // if there is another character, send it - if( sending && outcount > 0 ) { -#if TRACING_SIO_ISR - cio_printf( " ch %02x", *outnext ); -#endif - outb( UA4_TXD, *outnext ); - ++outnext; - // wrap around if necessary - if( outnext >= (outbuffer + BUF_SIZE) ) { - outnext = outbuffer; - } - --outcount; -#if TRACING_SIO_ISR - cio_printf( " (outcount %d)", outcount ); -#endif - } else { -#if TRACING_SIO_ISR - cio_puts( " EOS" ); -#endif - // no more data - reset the output vars - outcount = 0; - outlast = outnext = outbuffer; - sending = 0; - // disable TX interrupts - sio_disable( SIO_TX ); - } - break; - - case UA4_IIR_NO_INT: -#if TRACING_SIO_ISR - cio_puts( " EOI\n" ); -#endif - // nothing to do - tell the PIC we're done - outb( PIC1_CMD, PIC_EOI ); - return; - - case UA4_IIR_MODEM_STATUS: - // shouldn't happen, but just in case.... - cio_printf( "** SIO int, MSR = %02x\n", inb(UA4_MSR) ); - break; - - default: - // uh-oh.... - sprint( b256, "sio isr: IIR %02x\n", ((uint32_t) iir) & 0xff ); - PANIC( 0, b256 ); - } - - } - - // should never reach this point! - assert( false ); -} - -/* -** PUBLIC FUNCTIONS -*/ - -/** -** sio_init() -** -** Initialize the UART chip. -*/ -void sio_init( void ) { - -#if TRACING_INIT - cio_puts( " Sio" ); -#endif - - /* - ** Initialize SIO variables. - */ - - memclr( (void *) inbuffer, sizeof(inbuffer) ); - inlast = innext = inbuffer; - incount = 0; - - memclr( (void *) outbuffer, sizeof(outbuffer) ); - outlast = outnext = outbuffer; - outcount = 0; - sending = 0; - - // queue of read-blocked processes - QCREATE( QNAME ); - - /* - ** Next, initialize the UART. - ** - ** Initialize the FIFOs - ** - ** this is a bizarre little sequence of operations - */ - - outb( UA5_FCR, 0x20 ); - outb( UA5_FCR, UA5_FCR_FIFO_RESET ); // 0x00 - outb( UA5_FCR, UA5_FCR_FIFO_EN ); // 0x01 - outb( UA5_FCR, UA5_FCR_FIFO_EN | UA5_FCR_RXSR ); // 0x03 - outb( UA5_FCR, UA5_FCR_FIFO_EN | UA5_FCR_RXSR | UA5_FCR_TXSR ); // 0x07 - - /* - ** disable interrupts - ** - ** note that we leave them disabled; sio_enable() must be - ** called to switch them back on - */ - - outb( UA4_IER, 0 ); - ier = 0; - - /* - ** select the divisor latch registers and set the data rate - */ - - outb( UA4_LCR, UA4_LCR_DLAB ); - outb( UA4_DLL, BAUD_LOW_BYTE( DL_BAUD_9600 ) ); - outb( UA4_DLM, BAUD_HIGH_BYTE( DL_BAUD_9600 ) ); - - /* - ** deselect the latch registers, by setting the data - ** characteristics in the LCR - */ - - outb( UA4_LCR, UA4_LCR_WLS_8 | UA4_LCR_1_STOP_BIT | UA4_LCR_NO_PARITY ); - - /* - ** Set the ISEN bit to enable the interrupt request signal, - ** and the DTR and RTS bits to enable two-way communication. - */ - - outb( UA4_MCR, UA4_MCR_ISEN | UA4_MCR_DTR | UA4_MCR_RTS ); - - /* - ** Install our ISR - */ - - install_isr( VEC_COM1, sio_isr ); -} - -/** -** sio_enable() -** -** Enable SIO interrupts -** -** usage: uint8_t old = sio_enable( uint8_t which ) -** -** @param which Bit mask indicating which interrupt(s) to enable -** -** @return the prior IER setting -*/ -uint8_t sio_enable( uint8_t which ) { - uint8_t old; - - // remember the current status - - old = ier; - - // figure out what to enable - - if( which & SIO_TX ) { - ier |= UA4_IER_TX_IE; - } - - if( which & SIO_RX ) { - ier |= UA4_IER_RX_IE; - } - - // if there was a change, make it - - if( old != ier ) { - outb( UA4_IER, ier ); - } - - // return the prior settings - - return( old ); -} - -/** -** sio_disable() -** -** Disable SIO interrupts -** -** usage: uint8_t old = sio_disable( uint8_t which ) -** -** @param which Bit mask indicating which interrupt(s) to disable -** -** @return the prior IER setting -*/ -uint8_t sio_disable( uint8_t which ) { - uint8_t old; - - // remember the current status - - old = ier; - - // figure out what to disable - - if( which & SIO_TX ) { - ier &= ~UA4_IER_TX_IE; - } - - if( which & SIO_RX ) { - ier &= ~UA4_IER_RX_IE; - } - - // if there was a change, make it - - if( old != ier ) { - outb( UA4_IER, ier ); - } - - // return the prior settings - - return( old ); -} - -/** -** sio_inq_length() -** -** Get the input queue length -** -** usage: int num = sio_inq_length() -** -** @return the count of characters still in the input queue -*/ -int sio_inq_length( void ) { - return( incount ); -} - -/** -** sio_readc() -** -** Get the next input character -** -** usage: int ch = sio_readc() -** -** @return the next character, or -1 if no character is available -*/ -int sio_readc( void ) { - int ch; - - // assume there is no character available - ch = -1; - - // - // If there is a character, return it - // - - if( incount > 0 ) { - - // take it out of the input buffer - ch = ((int)(*innext++)) & 0xff; - --incount; - - // reset the buffer variables if this was the last one - if( incount < 1 ) { - inlast = innext = inbuffer; - } - - } - - return( ch ); - -} - -/** -** sio_read(buf,length) -** -** Read the entire input buffer into a user buffer of a specified size -** -** usage: int num = sio_read( char *buffer, int length ) -** -** @param buf The destination buffer -** @param length Length of the buffer -** -** @return the number of bytes copied, or 0 if no characters were available -*/ - -int sio_read( char *buf, int length ) { - char *ptr = buf; - int copied = 0; - - // if there are no characters, just return 0 - - if( incount < 1 ) { - return( 0 ); - } - - // - // We have characters. Copy as many of them into the user - // buffer as will fit. - // - - while( incount > 0 && copied < length ) { - *ptr++ = *innext++ & 0xff; - if( innext > (inbuffer + BUF_SIZE) ) { - innext = inbuffer; - } - --incount; - ++copied; - } - - // reset the input buffer if necessary - - if( incount < 1 ) { - inlast = innext = inbuffer; - } - - // return the copy count - - return( copied ); -} - - -/** -** sio_writec( ch ) -** -** Write a character to the serial output -** -** usage: sio_writec( int ch ) -** -** @param ch Character to be written (in the low-order 8 bits) -*/ -void sio_writec( int ch ){ - - - // - // Must do LF -> CRLF mapping - // - - if( ch == '\n' ) { - sio_writec( '\r' ); - } - - // - // If we're currently transmitting, just add this to the buffer - // - - if( sending ) { - *outlast++ = ch; - ++outcount; - return; - } - - // - // Not sending - must prime the pump - // - - sending = 1; - outb( UA4_TXD, ch ); - - // Also must enable transmitter interrupts - - sio_enable( SIO_TX ); - -} - -/** -** sio_write( buffer, length ) -** -** Write a buffer of characters to the serial output -** -** usage: int num = sio_write( const char *buffer, int length ) -** -** @param buffer Buffer containing characters to write -** @param length Number of characters to write -** -** @return the number of characters copied into the SIO output buffer -*/ -int sio_write( const char *buffer, int length ) { - int first = *buffer; - const char *ptr = buffer; - int copied = 0; - - // - // If we are currently sending, we want to append all - // the characters to the output buffer; else, we want - // to append all but the first character, and then use - // sio_writec() to send the first one out. - // - - if( !sending ) { - ptr += 1; - copied++; - } - - while( copied < length && outcount < BUF_SIZE ) { - *outlast++ = *ptr++; - // wrap around if necessary - if( outlast >= (outbuffer + BUF_SIZE) ) { - outlast = outbuffer; - } - ++outcount; - ++copied; - } - - // - // We use sio_writec() to send out the first character, - // as it will correctly set all the other necessary - // variables for us. - // - - if( !sending ) { - sio_writec( first ); - } - - // Return the transfer count - - - return( copied ); - -} - -/** -** sio_puts( buf ) -** -** Write a NUL-terminated buffer of characters to the serial output -** -** usage: int num = sio_puts( const char *buffer ) -** -** @param buffer The buffer containing a NUL-terminated string -** -** @return the count of bytes transferred -*/ -int sio_puts( const char *buffer ) { - int n; // must be outside the loop so we can return it - - n = SLENGTH( buffer ); - sio_write( buffer, n ); - - return( n ); -} - -/** -** sio_dump( full ) -** -** dump the contents of the SIO buffers to the console -** -** usage: sio_dump(true) or sio_dump(false) -** -** @param full Boolean indicating whether or not a "full" dump -** is being requested (which includes the contents -** of the queues) -*/ - -void sio_dump( bool_t full ) { - int n; - char *ptr; - - // dump basic info into the status region - - cio_printf_at( 48, 0, - "SIO: IER %02x (%c%c%c) in %d ot %d", - ((uint32_t)ier) & 0xff, sending ? '*' : '.', - (ier & UA4_IER_TX_IE) ? 'T' : 't', - (ier & UA4_IER_RX_IE) ? 'R' : 'r', - incount, outcount ); - - // if we're not doing a full dump, stop now - - if( !full ) { - return; - } - - // also want the queue contents, but we'll - // dump them into the scrolling region - - if( incount ) { - cio_puts( "SIO input queue: \"" ); - ptr = innext; - for( n = 0; n < incount; ++n ) { - put_char_or_code( *ptr++ ); - } - cio_puts( "\"\n" ); - } - - if( outcount ) { - cio_puts( "SIO output queue: \"" ); - cio_puts( " ot: \"" ); - ptr = outnext; - for( n = 0; n < outcount; ++n ) { - put_char_or_code( *ptr++ ); - } - cio_puts( "\"\n" ); - } -} diff --git a/kernel/old/startup.S b/kernel/old/startup.S deleted file mode 100644 index 73a081e..0000000 --- a/kernel/old/startup.S +++ /dev/null @@ -1,153 +0,0 @@ -/* -** @file startup.S -** -** @author Jon Coles -** @authors Warren R. Carithers, K. Reek -** -** SP startup code. -** -** This code prepares the various registers for execution of -** the program. It sets up all the segment registers and the -** runtime stack. By the time this code is running, we're in -** protected mode already. -*/ - -#define KERNEL_SRC -#define ASM_SRC - -# .arch i386 - -#include -#include -#include -#include -#include - -/* -** Configuration options - define in Makefile -** -** CLEAR_BSS include code to clear all BSS space -** OS_CONFIG OS-related (vs. just standalone) variations -*/ - -/* -** A symbol for locating the beginning of the code. -*/ - .globl begtext - - .text -begtext: - -/* -** The entry point. When we get here, we have just entered protected -** mode, so all the segment registers are incorrect except for CS. -*/ - .globl _start - -_start: - cli /* seems to be reset on entry to p. mode */ - movb $NMI_ENABLE, %al /* re-enable NMIs (bootstrap */ - outb $CMOS_ADDR /* turned them off) */ - -/* -** Set the data and stack segment registers (code segment register -** was set by the long jump that switched us into protected mode). -*/ - xorl %eax, %eax /* clear EAX */ - movw $GDT_DATA, %ax /* GDT entry #3 - data segment */ - movw %ax, %ds /* for all four data segment registers */ - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - - movw $GDT_STACK, %ax /* entry #4 is the stack segment */ - movw %ax, %ss - - movl $TARGET_STACK, %esp /* set up the system stack pointer */ - -#ifdef CLEAR_BSS -/* -** Zero the BSS segment -** -** These symbols are defined automatically by the linker, but they're -** defined at their virtual addresses rather than their physical addresses, -** and we haven't enabled paging yet. -*/ - .globl __bss_start, _end - - movl $V2PNC(__bss_start), %edi -clearbss: - movl $0, (%edi) - addl $4, %edi - cmpl $V2PNC(_end), %edi - jb clearbss -#endif /* CLEAR_BSS */ - -/* -** Enable paging. We use "large" pages for the initial page directory -** so that a one-level hierarchy will work for us. Once we have set -** up our memory freelist, we'll create a two-level hierarchy using -** "normal" 4KB pages. -*/ - # enable large pages - movl %cr4, %eax - orl $(CR4_PSE), %eax - movl %eax, %cr4 - - # set the page directory - .globl firstpdir - movl $(V2PNC(firstpdir)), %eax - movl %eax, %cr3 - - # turn on paging - movl %cr0, %eax - orl $(CR0_PG), %eax - movl %eax, %cr0 - - # reset our stack pointer - movl $(kstack + SZ_KSTACK), %esp - - # set the initial frame pointer - xorl %ebp, %ebp - -/* -** Call the system initialization routine, and switch to -** executing at high addresses. We use an indirect jump -** here to avoid getting a PC-relative 'jmp' instruction. -** -** Alternate idea: push the address of isr_restore -** and just do an indirect jump? -*/ - .globl main - - movl $main, %eax - call *%eax - -/* -** At this point, main() must have created the first user -** process, and we're ready to shift into user mode. The user -** stack for that process must have the initial context in it; -** we treat this as a "return from interrupt" event, and just -** transfer to the code that restores the user context. -*/ - - .globl isr_restore - jmp isr_restore - - .data - -/* -** Define the kernel stack here, at a multiple-of-16 address -*/ - .p2align 4 - .globl kstack -kstack: .space SZ_KSTACK, 0 - -/* -** Define the initial kernel ESP here, as well. It should point -** to the first byte after the stack. -*/ - - .globl kernel_esp -kernel_esp: - .long kstack + SZ_KSTACK diff --git a/kernel/old/support.c b/kernel/old/support.c deleted file mode 100644 index d48ce59..0000000 --- a/kernel/old/support.c +++ /dev/null @@ -1,279 +0,0 @@ -/* -** SCCS ID: @(#)support.c 2.6 1/22/25 -** -** @file support.c -** -** @author 4003-506 class of 20003 -** @authors K. Reek, Warren R. Carithers -** -** Miscellaneous system initialization functions, interrupt -** support routines, and data structures. -*/ - -#include - -#include -#include -#include -#include -#include -#include -#include - -/* -** Global variables and local data types. -*/ - -/* -** This is the table that contains pointers to the C-language ISR for -** each interrupt. These functions are called from the isr stub based -** on the interrupt number. -*/ -void ( *isr_table[ 256 ] )( int vector, int code ); - -/* -** Format of an IDT entry. -*/ -typedef struct { - short offset_15_0; - short segment_selector; - short flags; - short offset_31_16; -} IDT_Gate; - -/* -** LOCAL ROUTINES - not intended to be used outside this module. -*/ - -/** -** unexpected_handler -** -** This routine catches interrupts that we do not expect to ever occur. -** It handles them by (optionally) reporting them and then calling panic(). -** -** @param vector vector number for the interrupt that occurred -** @param code error code, or a dummy value -** -** Does not return. -*/ -#ifdef RPT_INT_UNEXP -/* add any header includes you need here */ -#endif -static void unexpected_handler( int vector, int code ) { -#ifdef RPT_INT_UNEXP - cio_printf( "\n** UNEXPECTED vector %d code %d\n", vector, code ); -#endif - panic( "Unexpected interrupt" ); -} - -/** -** default_handler -** -** Default handler for interrupts we expect may occur but are not -** handling (yet). We just reset the PIC and return. -** -** @param vector vector number for the interrupt that occurred -** @param code error code, or a dummy value -*/ -static void default_handler( int vector, int code ) { -#ifdef RPT_INT_UNEXP - cio_printf( "\n** vector %d code %d\n", vector, code ); -#endif - if( vector >= 0x20 && vector < 0x30 ) { - if( vector > 0x27 ) { - // must also ACK the secondary PIC - outb( PIC2_CMD, PIC_EOI ); - } - outb( PIC1_CMD, PIC_EOI ); - } else { - /* - ** All the "expected" interrupts will be handled by the - ** code above. If we get down here, the isr table may - ** have been corrupted. Print a message and don't return. - */ - panic( "Unexpected \"expected\" interrupt!" ); - } -} - -/** -** mystery_handler -** -** Default handler for the "mystery" interrupt that comes through vector -** 0x27. This is a non-repeatable interrupt whose source has not been -** identified, but it appears to be the famous "spurious level 7 interrupt" -** source. -** -** @param vector vector number for the interrupt that occurred -** @param code error code, or a dummy value -*/ -static void mystery_handler( int vector, int code ) { -#if defined(RPT_INT_MYSTERY) || defined(RPT_INT_UNEXP) - cio_printf( "\nMystery interrupt!\nVector=0x%02x, code=%d\n", - vector, code ); -#endif - outb( PIC1_CMD, PIC_EOI ); -} - -/** -** init_pic -** -** Initialize the 8259 Programmable Interrupt Controller. -*/ -static void init_pic( void ) { - /* - ** ICW1: start the init sequence, update ICW4 - */ - outb( PIC1_CMD, PIC_CW1_INIT | PIC_CW1_NEED4 ); - outb( PIC2_CMD, PIC_CW1_INIT | PIC_CW1_NEED4 ); - - /* - ** ICW2: primary offset of 0x20 in the IDT, secondary offset of 0x28 - */ - outb( PIC1_DATA, PIC1_CW2_VECBASE ); - outb( PIC2_DATA, PIC2_CW2_VECBASE ); - - /* - ** ICW3: secondary attached to line 2 of primary, bit mask is 00000100 - ** secondary id is 2 - */ - outb( PIC1_DATA, PIC1_CW3_SEC_IRQ2 ); - outb( PIC2_DATA, PIC2_CW3_SEC_ID ); - - /* - ** ICW4: want 8086 mode, not 8080/8085 mode - */ - outb( PIC1_DATA, PIC_CW4_PM86 ); - outb( PIC2_DATA, PIC_CW4_PM86 ); - - /* - ** OCW1: allow interrupts on all lines - */ - outb( PIC1_DATA, PIC_MASK_NONE ); - outb( PIC2_DATA, PIC_MASK_NONE ); -} - -/** -** set_idt_entry -** -** Construct an entry in the IDT -** -** @param entry the vector number of the interrupt -** @param handler ISR address to be put into the IDT entry -** -** Note: generally, the handler invoked from the IDT will be a "stub" -** that calls the second-level C handler via the isr_table array. -*/ -static void set_idt_entry( int entry, void ( *handler )( void ) ) { - IDT_Gate *g = (IDT_Gate *)IDT_ADDR + entry; - - g->offset_15_0 = (int)handler & 0xffff; - g->segment_selector = 0x0010; - g->flags = IDT_PRESENT | IDT_DPL_0 | IDT_INT32_GATE; - g->offset_31_16 = (int)handler >> 16 & 0xffff; -} - -/** -** Name: init_idt -** -** Initialize the Interrupt Descriptor Table (IDT). This makes each of -** the entries in the IDT point to the isr stub for that entry, and -** installs a default handler in the handler table. Temporary handlers -** are then installed for those interrupts we may get before a real -** handler is set up. -*/ -static void init_idt( void ) { - int i; - extern void ( *isr_stub_table[ 256 ] )( void ); - - /* - ** Make each IDT entry point to the stub for that vector. Also - ** make each entry in the ISR table point to the default handler. - */ - for ( i=0; i < 256; i++ ) { - set_idt_entry( i, isr_stub_table[ i ] ); - install_isr( i, unexpected_handler ); - } - - /* - ** Install the handlers for interrupts that have (or will have) a - ** specific handler. Comments indicate which module init function - ** will eventually install the "real" handler. - */ - - install_isr( VEC_KBD, default_handler ); // cio_init() - install_isr( VEC_COM1, default_handler ); // sio_init() - install_isr( VEC_TIMER, default_handler ); // clk_init() - install_isr( VEC_SYSCALL, default_handler ); // sys_init() - install_isr( VEC_PAGE_FAULT, default_handler ); // vm_init() - - install_isr( VEC_MYSTERY, mystery_handler ); -} - -/* -** END OF LOCAL ROUTINES. -** -** Full documentation for globally-visible routines is in the corresponding -** header file. -*/ - -/* -** panic -** -** Called when we find an unrecoverable error. -*/ -void panic( char *reason ) { - __asm__( "cli" ); - cio_printf( "\nPANIC: %s\nHalting...", reason ); - for(;;) { - ; - } -} - -/* -** init_interrupts -** -** (Re)initilizes the interrupt system. -*/ -void init_interrupts( void ) { - init_idt(); - init_pic(); -} - -/* -** install_isr -** -** Installs a second-level handler for a specific interrupt. -*/ -void (*install_isr( int vector, - void (*handler)(int,int) ) ) ( int, int ) { - - void ( *old_handler )( int vector, int code ); - - old_handler = isr_table[ vector ]; - isr_table[ vector ] = handler; - return old_handler; -} - -/* -** Name: delay -** -** Notes: The parameter to the delay() function is ambiguous; it -** purports to indicate a delay length, but that isn't really tied -** to any real-world time measurement. -** -** On the original systems we used (dual 500MHz Intel P3 CPUs), each -** "unit" was approximately one tenth of a second, so delay(10) would -** delay for about one second. -** -** On the current machines (Intel Core i5-7500), delay(100) is about -** 2.5 seconds, so each "unit" is roughly 0.025 seconds. -** -** Ultimately, just remember that DELAY VALUES ARE APPROXIMATE AT BEST. -*/ -void delay( int length ) { - - while( --length >= 0 ) { - for( int i = 0; i < 10000000; ++i ) - ; - } -} diff --git a/kernel/old/syscalls.c b/kernel/old/syscalls.c deleted file mode 100644 index 7176cda..0000000 --- a/kernel/old/syscalls.c +++ /dev/null @@ -1,829 +0,0 @@ -/** -** @file syscalls.c -** -** @author CSCI-452 class of 20245 -** -** @brief System call implementations -*/ - -#define KERNEL_SRC - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/* -** PRIVATE DEFINITIONS -*/ - -/* -** Macros to simplify tracing a bit -** -** TRACING_SYSCALLS and TRACING_SYSRETS are defined in debug.h, -** controlled by the TRACE ** macro. If not tracing these, SYSCALL_ENTER -** is a no-op, and SYSCALL_EXIT just does a return. -*/ - -#if TRACING_SYSCALLS - -#define SYSCALL_ENTER(x) do { \ - cio_printf( "--> %s, pid %08x", __func__, (uint32_t) (x) ); \ - } while(0) - -#else - -#define SYSCALL_ENTER(x) /* */ - -#endif /* TRACING_SYSCALLS */ - -#if TRACING_SYSRETS - -#define SYSCALL_EXIT(x) do { \ - cio_printf( "<-- %s %08x\n", __func__, (uint32_t) (x) ); \ - return; \ - } while(0) - -#else - -#define SYSCALL_EXIT(x) return - -#endif /* TRACING_SYSRETS */ - -/* -** PRIVATE DATA TYPES -*/ - -/* -** PUBLIC GLOBAL VARIABLES -*/ - -/* -** IMPLEMENTATION FUNCTIONS -*/ - -// a macro to simplify syscall entry point specification -// we don't declare these static because we may want to call -// some of them from other parts of the kernel -#define SYSIMPL(x) void sys_##x( pcb_t * pcb ) - -/* -** Second-level syscall handlers -** -** All have this prototype: -** -** static void sys_NAME( pcb_t *pcb ); -** -** where the parameter 'pcb' is a pointer to the PCB of the process -** making the system call. -** -** Values being returned to the user are placed into the EAX -** field in the context save area for that process. -*/ - -/** -** sys_exit - terminate the calling process -** -** Implements: -** void exit( int32_t status ); -** -** Does not return -*/ -SYSIMPL(exit) { - - // sanity check - assert( pcb != NULL ); - - SYSCALL_ENTER( pcb->pid ); - - // retrieve the exit status of this process - pcb->exit_status = (int32_t) ARG(pcb,1); - - // now, we need to do the following: - // reparent any children of this process and wake up init if need be - // find this process' parent and wake it up if it's waiting - - pcb_zombify( pcb ); - - // pick a new winner - dispatch(); - - SYSCALL_EXIT( 0 ); -} - -/** -** sys_waitpid - wait for a child process to terminate -** -** Implements: -** int waitpid( uint_t pid, int32_t *status ); -** -** Blocks the calling process until the specified child (or any child) -** of the caller terminates. Intrinsic return is the PID of the child that -** terminated, or an error code; on success, returns the child's termination -** status via 'status' if that pointer is non-NULL. -*/ -SYSIMPL(waitpid) { - - // sanity check - assert( pcb != NULL ); - - SYSCALL_ENTER( pcb->pid ); - - /* - ** We need to do two things here: (1) find out whether or - ** not this process has any children in the system, and (2) - ** find out whether the desired child (or any child, if the - ** target PID is 0) has terminated. - ** - ** To do this, we loop until we find a the requested PID or - ** a Zombie child process, or have gone through all of the - ** slots in the process table. - ** - ** If the target PID is 0, we don't care which child process - ** we reap here; there could be several, but we only need to - ** find one. - */ - - // verify that we aren't looking for ourselves! - uint_t target = ARG(pcb,1); - - if( target == pcb->pid ) { - RET(pcb) = E_BAD_PARAM; - SYSCALL_EXIT( E_BAD_PARAM ); - } - - // Good. Now, figure out what we're looking for. - - pcb_t *child = NULL; - - if( target != 0 ) { - - // we're looking for a specific child - child = pcb_find_pid( target ); - - if( child != NULL ) { - - // found the process; is it one of our children: - if( child->parent != pcb ) { - // NO, so we can't wait for it - RET(pcb) = E_BAD_PARAM; - SYSCALL_EXIT( E_BAD_PARAM ); - } - - // yes! is this one ready to be collected? - if( child->state != STATE_ZOMBIE ) { - // no, so we'll have to block for now - child = NULL; - } - - } else { - - // no such child - RET(pcb) = E_BAD_PARAM; - SYSCALL_EXIT( E_BAD_PARAM ); - - } - - } else { - - // looking for any child - - // we need to find a process that is our child - // and has already exited - - child = NULL; - bool_t found = false; - - // unfortunately, we can't stop at the first child, - // so we need to do the iteration ourselves - register pcb_t *curr = ptable; - - for( int i = 0; i < N_PROCS; ++i, ++curr ) { - - if( curr->parent == pcb ) { - - // found one! - found = true; - - // has it already exited? - if( curr->state == STATE_ZOMBIE ) { - // yes, so we're done here - child = curr; - break; - } - } - } - - if( !found ) { - // got through the loop without finding a child! - RET(pcb) = E_NO_CHILDREN; - SYSCALL_EXIT( E_NO_CHILDREN ); - } - - } - - /* - ** At this point, one of these situations is true: - ** - ** * we are looking for a specific child and found it - ** * we are looking for any child and found one - ** - ** Either way, 'child' will be non-NULL if the selected - ** process has already become a Zombie. If that's the - ** case, we collect its status and clean it up; otherwise, - ** we block this process. - */ - - // did we find one to collect? - if( child == NULL ) { - - // no - mark the parent as "Waiting" - pcb->state = STATE_WAITING; - assert( pcb_queue_insert(waiting,pcb) == SUCCESS ); - - // select a new current process - dispatch(); - SYSCALL_EXIT( (uint32_t) current ); - } - - // found a Zombie; collect its information and clean it up - RET(pcb) = child->pid; - - // get "status" pointer from parent - int32_t *stat = (int32_t *) ARG(pcb,2); - - // if stat is NULL, the parent doesn't want the status - if( stat != NULL ) { - // ******************************************************** - // ** Potential VM issue here! This code assigns the exit - // ** status into a variable in the parent's address space. - // ** This works in the baseline because we aren't using - // ** any type of memory protection. If address space - // ** separation is implemented, this code will very likely - // ** STOP WORKING, and will need to be fixed. - // ******************************************************** - *stat = child->exit_status; - } - - // clean up the child - pcb_cleanup( child ); - - SYSCALL_EXIT( RET(pcb) ); -} - -/** -** sys_fork - create a new process -** -** Implements: -** int fork( void ); -** -** Creates a new process that is a duplicate of the calling process. -** Returns the child's PID to the parent, and 0 to the child, on success; -** else, returns an error code to the parent. -*/ -SYSIMPL(fork) { - - // sanity check - assert( pcb != NULL ); - - SYSCALL_ENTER( pcb->pid ); - - // Make sure there's room for another process! - pcb_t *new; - if( pcb_alloc(&new) != SUCCESS || new == NULL ) { - RET(pcb) = E_NO_PROCS; - SYSCALL_EXIT( RET(pcb) ); - } - - // duplicate the memory image of the parent - int status = user_duplicate( new, pcb ); - if( status != SUCCESS ) { - pcb_free( new ); - RET(pcb) = status; - SYSCALL_EXIT( status ); - } - - // Set the child's identity. - new->pid = next_pid++; - new->parent = pcb; - new->state = STATE_NEW; - - // replicate other things inherited from the parent - new->priority = pcb->priority; - - // Set the return values for the two processes. - RET(pcb) = new->pid; - RET(new) = 0; - - // Schedule the child, and let the parent continue. - schedule( new ); - - SYSCALL_EXIT( new->pid ); -} - -/** -** sys_exec - replace the memory image of a process -** -** Implements: -** void exec( uint_t what, char **args ); -** -** Replaces the memory image of the calling process with that of the -** indicated program. -** -** Returns only on failure. -*/ -SYSIMPL(exec) -{ - // sanity check - assert( pcb != NULL ); - - uint_t what = ARG(pcb,1); - const char **args = (const char **) ARG(pcb,2); - - SYSCALL_ENTER( pcb->pid ); - - // locate the requested program - prog_t *prog = user_locate( what ); - if( prog == NULL ) { - RET(pcb) = E_NOT_FOUND; - SYSCALL_EXIT( E_NOT_FOUND ); - } - - // we have located the program, but before we can load it, - // we need to clean up the existing VM hierarchy - vm_free( pcb->pdir ); - pcb->pdir = NULL; - - // "load" it and set up the VM tables for this process - int status = user_load( prog, pcb, args ); - if( status != SUCCESS ) { - RET(pcb) = status; - SYSCALL_EXIT( status ); - } - - /* - ** Decision: - ** (A) schedule this process and dispatch another, - ** (B) let this one continue in its current time slice - ** (C) reset this one's time slice and let it continue - ** - ** We choose option A. - ** - ** If scheduling the process fails, the exec() has failed. However, - ** all trace of the old process is gone by now, so we can't return - ** an error status to it. - */ - - schedule( pcb ); - - dispatch(); -} - -/** -** sys_read - read into a buffer from an input channel -** -** Implements: -** int read( uint_t chan, void *buffer, uint_t length ); -** -** Reads up to 'length' bytes from 'chan' into 'buffer'. Returns the -** count of bytes actually transferred. -*/ -SYSIMPL(read) { - - // sanity check - assert( pcb != NULL ); - - SYSCALL_ENTER( pcb->pid ); - - // grab the arguments - uint_t chan = ARG(pcb,1); - char *buf = (char *) ARG(pcb,2); - uint_t len = ARG(pcb,3); - - // if the buffer is of length 0, we're done! - if( len == 0 ) { - RET(pcb) = 0; - SYSCALL_EXIT( 0 ); - } - - // try to get the next character(s) - int n = 0; - - if( chan == CHAN_CIO ) { - - // console input is non-blocking - if( cio_input_queue() < 1 ) { - RET(pcb) = 0; - SYSCALL_EXIT( 0 ); - } - // at least one character - n = cio_gets( buf, len ); - RET(pcb) = n; - SYSCALL_EXIT( n ); - - } else if( chan == CHAN_SIO ) { - - // SIO input is blocking, so if there are no characters - // available, we'll block this process - n = sio_read( buf, len ); - RET(pcb) = n; - SYSCALL_EXIT( n ); - - } - - // bad channel code - RET(pcb) = E_BAD_PARAM; - SYSCALL_EXIT( E_BAD_PARAM ); -} - -/** -** sys_write - write from a buffer to an output channel -** -** Implements: -** int write( uint_t chan, const void *buffer, uint_t length ); -** -** Writes 'length' bytes from 'buffer' to 'chan'. Returns the -** count of bytes actually transferred. -*/ -SYSIMPL(write) { - - // sanity check - assert( pcb != NULL ); - - SYSCALL_ENTER( pcb->pid ); - - // grab the parameters - uint_t chan = ARG(pcb,1); - char *buf = (char *) ARG(pcb,2); - uint_t length = ARG(pcb,3); - - // this is almost insanely simple, but it does separate the - // low-level device access fromm the higher-level syscall implementation - - // assume we write the indicated amount - int rval = length; - - // simplest case - if( length >= 0 ) { - - if( chan == CHAN_CIO ) { - - cio_write( buf, length ); - - } else if( chan == CHAN_SIO ) { - - sio_write( buf, length ); - - } else { - - rval = E_BAD_CHAN; - - } - - } - - RET(pcb) = rval; - - SYSCALL_EXIT( rval ); -} - -/** -** sys_getpid - returns the PID of the calling process -** -** Implements: -** uint_t getpid( void ); -*/ -SYSIMPL(getpid) { - - // sanity check! - assert( pcb != NULL ); - - SYSCALL_ENTER( pcb->pid ); - - // return the time - RET(pcb) = pcb->pid; -} - -/** -** sys_getppid - returns the PID of the parent of the calling process -** -** Implements: -** uint_t getppid( void ); -*/ -SYSIMPL(getppid) { - - // sanity check! - assert( pcb != NULL ); - assert( pcb->parent != NULL ); - - SYSCALL_ENTER( pcb->pid ); - - // return the time - RET(pcb) = pcb->parent->pid; -} - -/** -** sys_gettime - returns the current system time -** -** Implements: -** uint32_t gettime( void ); -*/ -SYSIMPL(gettime) { - - // sanity check! - assert( pcb != NULL ); - - SYSCALL_ENTER( pcb->pid ); - - // return the time - RET(pcb) = system_time; -} - -/** -** sys_getprio - the scheduling priority of the calling process -** -** Implements: -** int getprio( void ); -*/ -SYSIMPL(getprio) { - - // sanity check! - assert( pcb != NULL ); - - SYSCALL_ENTER( pcb->pid ); - - // return the time - RET(pcb) = pcb->priority; -} - -/** -** sys_setprio - sets the scheduling priority of the calling process -** -** Implements: -** int setprio( int new ); -*/ -SYSIMPL(setprio) { - - // sanity check! - assert( pcb != NULL ); - - SYSCALL_ENTER( pcb->pid ); - - // remember the old priority - int old = pcb->priority; - - // set the priority - pcb->priority = ARG(pcb,1); - - // return the old value - RET(pcb) = old; -} - -/** -** sys_kill - terminate a process with extreme prejudice -** -** Implements: -** int32_t kill( uint_t pid ); -** -** Marks the specified process (or the calling process, if PID is 0) -** as "killed". Returns 0 on success, else an error code. -*/ -SYSIMPL(kill) { - - // sanity check - assert( pcb != NULL ); - - SYSCALL_ENTER( pcb->pid ); - - // who is the victim? - uint_t pid = ARG(pcb,1); - - // if it's this process, convert this into a call to exit() - if( pid == pcb->pid ) { - pcb->exit_status = EXIT_KILLED; - pcb_zombify( pcb ); - dispatch(); - SYSCALL_EXIT( EXIT_KILLED ); - } - - // must be a valid "ordinary user" PID - // QUESTION: what if it's the idle process? - if( pid < FIRST_USER_PID ) { - RET(pcb) = E_FAILURE; - SYSCALL_EXIT( E_FAILURE ); - } - - // OK, this is an acceptable victim; see if it exists - pcb_t *victim = pcb_find_pid( pid ); - if( victim == NULL ) { - // nope! - RET(pcb) = E_NOT_FOUND; - SYSCALL_EXIT( E_NOT_FOUND ); - } - - // must have a state that is possible - assert( victim->state >= FIRST_VIABLE && victim->state < N_STATES ); - - // how we perform the kill depends on the victim's state - int32_t status = SUCCESS; - - switch( victim->state ) { - - case STATE_KILLED: // FALL THROUGH - case STATE_ZOMBIE: - // you can't kill it if it's already dead - RET(pcb) = SUCCESS; - break; - - case STATE_READY: // FALL THROUGH - case STATE_SLEEPING: // FALL THROUGH - case STATE_BLOCKED: // FALL THROUGH - // here, the process is on a queue somewhere; mark - // it as "killed", and let the scheduler deal with it - victim->state = STATE_KILLED; - RET(pcb) = SUCCESS; - break; - - case STATE_RUNNING: - // we have met the enemy, and it is us! - pcb->exit_status = EXIT_KILLED; - pcb_zombify( pcb ); - status = EXIT_KILLED; - // we need a new current process - dispatch(); - break; - - case STATE_WAITING: - // similar to the 'running' state, but we don't need - // to dispatch a new process - victim->exit_status = EXIT_KILLED; - status = pcb_queue_remove_this( waiting, victim ); - pcb_zombify( victim ); - RET(pcb) = status; - break; - - default: - // this is a really bad potential problem - we have an - // unexpected or bogus process state, but we didn't - // catch that earlier. - sprint( b256, "*** kill(): victim %d, odd state %d\n", - victim->pid, victim->state ); - PANIC( 0, b256 ); - } - - SYSCALL_EXIT( status ); -} - - -/** -** sys_sleep - put the calling process to sleep for some length of time -** -** Implements: -** uint_t sleep( uint_t ms ); -** -** Puts the calling process to sleep for 'ms' milliseconds (or just yields -** the CPU if 'ms' is 0). ** Returns the time the process spent sleeping. -*/ -SYSIMPL(sleep) { - - // sanity check - assert( pcb != NULL ); - - SYSCALL_ENTER( pcb->pid ); - - // get the desired duration - uint_t length = ARG( pcb, 1 ); - - if( length == 0 ) { - - // just yield the CPU - // sleep duration is 0 - RET(pcb) = 0; - - // back on the ready queue - schedule( pcb ); - - } else { - - // sleep for a while - pcb->wakeup = system_time + length; - - if( pcb_queue_insert(sleeping,pcb) != SUCCESS ) { - // something strange is happening - WARNING( "sleep pcb insert failed" ); - // if this is the current process, report an error - if( current == pcb ) { - RET(pcb) = -1; - } - // return without dispatching a new process - return; - } - } - - // only dispatch if the current process called us - if( pcb == current ) { - current = NULL; - dispatch(); - } -} - -/* -** PRIVATE FUNCTIONS GLOBAL VARIABLES -*/ - -/* -** The system call jump table -** -** Initialized using designated initializers to ensure the entries -** are correct even if the syscall code values should happen to change. -** This also makes it easy to add new system call entries, as their -** position in the initialization list is irrelevant. -*/ - -static void (* const syscalls[N_SYSCALLS])( pcb_t * ) = { - [ SYS_exit ] = sys_exit, - [ SYS_waitpid ] = sys_waitpid, - [ SYS_fork ] = sys_fork, - [ SYS_exec ] = sys_exec, - [ SYS_read ] = sys_read, - [ SYS_write ] = sys_write, - [ SYS_getpid ] = sys_getpid, - [ SYS_getppid ] = sys_getppid, - [ SYS_gettime ] = sys_gettime, - [ SYS_getprio ] = sys_getprio, - [ SYS_setprio ] = sys_setprio, - [ SYS_kill ] = sys_kill, - [ SYS_sleep ] = sys_sleep -}; - -/** -** Name: sys_isr -** -** System call ISR -** -** @param vector Vector number for this interrupt -** @param code Error code (0 for this interrupt) -*/ -static void sys_isr( int vector, int code ) { - - // keep the compiler happy - (void) vector; - (void) code; - - // sanity check! - assert( current != NULL ); - assert( current->context != NULL ); - - // retrieve the syscall code - int num = REG( current, eax ); - -#if TRACING_SYSCALLS - cio_printf( "** --> SYS pid %u code %u\n", current->pid, num ); -#endif - - // validate it - if( num < 0 || num >= N_SYSCALLS ) { - // bad syscall number - // could kill it, but we'll just force it to exit - num = SYS_exit; - ARG(current,1) = EXIT_BAD_SYSCALL; - } - - // call the handler - syscalls[num]( current ); - -#if TRACING_SYSCALLS - cio_printf( "** <-- SYS pid %u ret %u\n", current->pid, RET(current) ); -#endif - - // tell the PIC we're done - outb( PIC1_CMD, PIC_EOI ); -} - -/* -** PUBLIC FUNCTIONS -*/ - -/** -** Name: sys_init -** -** Syscall module initialization routine -** -** Dependencies: -** Must be called after cio_init() -*/ -void sys_init( void ) { - -#if TRACING_INIT - cio_puts( " Sys" ); -#endif - - // install the second-stage ISR - install_isr( VEC_SYSCALL, sys_isr ); -} diff --git a/kernel/old/user.c b/kernel/old/user.c deleted file mode 100644 index c41867e..0000000 --- a/kernel/old/user.c +++ /dev/null @@ -1,783 +0,0 @@ -/** -** @file user.c -** -** @author CSCI-452 class of 20245 -** -** @brief User-level code manipulation routines -*/ - -#define KERNEL_SRC - -#include - -#include -#include -#include -#include - -/* -** PRIVATE DEFINITIONS -*/ - -/* -** PRIVATE DATA TYPES -*/ - -/* -** PRIVATE GLOBAL VARIABLES -*/ - -/* -** PUBLIC GLOBAL VARIABLES -*/ - -/* -** Location of the "user blob" in memory. -** -** These variables are filled in by the code in startup.S using values -** passed to it from the bootstrap. -** -** These are visible so that the startup code can find them. -*/ -uint16_t user_offset; // byte offset from the segment base -uint16_t user_segment; // segment base address -uint16_t user_sectors; // number of 512-byte sectors it occupies - -header_t *user_header; // filled in by the user_init routine -prog_t *prog_table; // filled in by the user_init routine - -/* -** PRIVATE FUNCTIONS -*/ - -#if TRACING_ELF - -/* -** This is debugging support code; if not debugging the ELF -** handling code, it won't be compiled into the kernel. -*/ - -// buffer used by some of these functions -static char ebuf[16]; - -/* -** File header functions -*/ - -// interpret the file class -static const char *fh_eclass( e32_si class ) { - switch( class ) { - case ELF_CLASS_NONE: return( "None" ); break; - case ELF_CLASS_32: return( "EC32" ); break; - case ELF_CLASS_64: return( "EC64" ); break; - } - return( "????" ); -} - -// interpret the data encoding -static const char *fh_edata( e32_si data ) { - switch( data ) { - case ELF_DATA_NONE: return( "Invd" ); break; - case ELF_DATA_2LSB: return( "2CLE" ); break; - case ELF_DATA_2MSB: return( "2CBE" ); break; - } - return( "????" ); -} - -// interpret the file type -static const char *fh_htype( e32_h type ) { - switch( type ) { - case ET_NONE: return( "none" ); break; - case ET_REL: return( "rel" ); break; - case ET_EXEC: return( "exec" ); break; - case ET_DYN: return( "dyn" ); break; - case ET_CORE: return( "core" ); break; - default: - if( type >= ET_LO_OS && type <= ET_HI_OS ) - return( "OSsp" ); - else if( type >= ET_LO_CP && type <= ET_HI_CP ) - return( "CPsp" ); - } - sprint( ebuf, "0x%04x", type ); - return( (const char *) ebuf ); -} - -// interpret the machine type -static const char *fh_mtype( e32_h machine ) { - switch( machine ) { - case EM_NONE: return( "None" ); break; - case EM_386: return( "386" ); break; - case EM_ARM: return( "ARM" ); break; - case EM_X86_64: return( "AMD64" ); break; - case EM_AARCH64: return( "AARCH64" ); break; - case EM_RISCV: return( "RISC-V" ); break; - } - return( "Other" ); -} - -// dump the program header -static void dump_fhdr( elfhdr_t *hdr ) { - cio_puts( "File header: magic " ); - for( int i = EI_MAG0; i <= EI_MAG3; ++i ) - put_char_or_code( hdr->e_ident.bytes[i] ); - cio_printf( " class %s", fh_eclass(hdr->e_ident.f.class) ); - cio_printf( " enc %s", fh_edata(hdr->e_ident.f.data) ); - cio_printf( " ver %u\n", hdr->e_ident.f.version ); - cio_printf( " type %s", fh_htype(hdr->e_type) ); - cio_printf( " mach %s", fh_mtype(hdr->e_machine) ); - cio_printf( " vers %d", hdr->e_version ); - cio_printf( " entr %08x\n", hdr->e_entry ); - - cio_printf( " phoff %08x", hdr->e_phoff ); - cio_printf( " shoff %08x", hdr->e_shoff ); - cio_printf( " flags %08x", (uint32_t) hdr->e_flags ); - cio_printf( " ehsize %u\n", hdr->e_ehsize ); - cio_printf( " phentsize %u", hdr->e_phentsize ); - cio_printf( " phnum %u", hdr->e_phnum ); - cio_printf( " shentsize %u", hdr->e_shentsize ); - cio_printf( " shnum %u", hdr->e_shnum ); - cio_printf( " shstrndx %u\n", hdr->e_shstrndx ); -} - -/* -** Program header functions -*/ - -// categorize the header type -static const char *ph_type( e32_w type ) { - switch( type ) { - case PT_NULL: return( "Unused" ); break; - case PT_LOAD: return( "Load" ); break; - case PT_DYNAMIC: return( "DLI" ); break; - case PT_INTERP: return( "Interp" ); break; - case PT_NOTE: return( "Aux" ); break; - case PT_SHLIB: return( "RSVD" ); break; - case PT_PHDR: return( "PTentry" ); break; - case PT_TLS: return( "TLS" ); break; - default: - if( type >= PT_LO_OS && type <= PT_HI_OS ) - return( "OSsp" ); - else if( type >= PT_LO_CP && type <= PT_HI_CP ) - return( "CPsp" ); - } - sprint( ebuf, "0x%08x", type ); - return( (const char *) ebuf ); -} - -// report the individual flags -static void ph_flags( e32_w flags ) { - if( (flags & PF_R) != 0 ) cio_putchar( 'R' ); - if( (flags & PF_W) != 0 ) cio_putchar( 'W' ); - if( (flags & PF_E) != 0 ) cio_putchar( 'X' ); -} - -// dump a program header -static void dump_phdr( elfproghdr_t *hdr, int n ) { - cio_printf( "Prog header %d, type %s\n", n, ph_type(hdr->p_type) ); - cio_printf( " offset %08x", hdr->p_offset ); - cio_printf( " va %08x", hdr->p_va ); - cio_printf( " pa %08x\n", hdr->p_pa ); - cio_printf( " filesz %08x", hdr->p_filesz ); - cio_printf( " memsz %08x", hdr->p_memsz ); - cio_puts( " flags " ); - ph_flags( hdr->p_flags ); - cio_printf( " align %08x", hdr->p_align ); - cio_putchar( '\n' ); -} - -/* -** Section header functions -*/ - -// interpret the header type -static const char *sh_type( e32_w type ) { - switch( type ) { - case SHT_NULL: return( "Unused" ); break; - case SHT_PROGBITS: return( "Progbits" ); break; - case SHT_SYMTAB: return( "Symtab" ); break; - case SHT_STRTAB: return( "Strtab" ); break; - case SHT_RELA: return( "Rela" ); break; - case SHT_HASH: return( "Hash" ); break; - case SHT_DYNAMIC: return( "Dynamic" ); break; - case SHT_NOTE: return( "Note" ); break; - case SHT_NOBITS: return( "Nobits" ); break; - case SHT_REL: return( "Rel" ); break; - case SHT_SHLIB: return( "Shlib" ); break; - case SHT_DYNSYM: return( "Dynsym" ); break; - default: - if( type >= SHT_LO_CP && type <= SHT_HI_CP ) - return( "CCsp" ); - else if( type >= SHT_LO_US && type <= SHT_HI_US ) - return( "User" ); - } - sprint( ebuf, "0x%08x", type ); - return( (const char *) ebuf ); -} - -// report the various flags -static void sh_flags( unsigned int flags ) { - if( (flags & SHF_WRITE) != 0 ) cio_putchar( 'W' ); - if( (flags & SHF_ALLOC) != 0 ) cio_putchar( 'A' ); - if( (flags & SHF_EXECINSTR) != 0 ) cio_putchar( 'X' ); - if( (flags & SHF_MERGE) != 0 ) cio_putchar( 'M' ); - if( (flags & SHF_STRINGS) != 0 ) cio_putchar( 'S' ); - if( (flags & SHF_INFO_LINK) != 0 ) cio_putchar( 'L' ); - if( (flags & SHF_LINK_ORDER) != 0 ) cio_putchar( 'o' ); - if( (flags & SHF_OS_NONCON) != 0 ) cio_putchar( 'n' ); - if( (flags & SHF_GROUP) != 0 ) cio_putchar( 'g' ); - if( (flags & SHF_TLS) != 0 ) cio_putchar( 't' ); -} - -// dump a section header -ATTR_UNUSED -static void dump_shdr( elfsecthdr_t *hdr, int n ) { - cio_printf( "Sect header %d, type %d (%s), name %s\n", - n, hdr->sh_type, sh_type(hdr->sh_type) ); - cio_printf( " flags %08x ", (uint32_t) hdr->sh_flags ); - sh_flags( hdr->sh_flags ); - cio_printf( " addr %08x", hdr->sh_addr ); - cio_printf( " offset %08x", hdr->sh_offset ); - cio_printf( " size %08x\n", hdr->sh_size ); - cio_printf( " link %08x", hdr->sh_link ); - cio_printf( " info %08x", hdr->sh_info ); - cio_printf( " align %08x", hdr->sh_addralign ); - cio_printf( " entsz %08x\n", hdr->sh_entsize ); -} -#endif - -/** -** read_phdrs(addr,phoff,phentsize,phnum) -** -** Parses the ELF program headers and each segment described into memory. -** -** @param hdr Pointer to the program header -** @param pcb Pointer to the PCB (and its PDE) -** -** @return status of the attempt: -** SUCCESS everything loaded correctly -** E_LOAD_LIMIT more than N_LOADABLE PT_LOAD sections -** other status returned from vm_add() -*/ -static int read_phdrs( elfhdr_t *hdr, pcb_t *pcb ) { - - // sanity check - assert1( hdr != NULL ); - assert2( pcb != NULL ); - -#if TRACING_USER - cio_printf( "read_phdrs(%08x,%08x)\n", (uint32_t) hdr, (uint32_t) pcb ); -#endif - - // iterate through the program headers - uint_t nhdrs = hdr->e_phnum; - - // pointer to the first header table entry - elfproghdr_t *curr = (elfproghdr_t *) ((uint32_t) hdr + hdr->e_phoff); - - // process them all - int loaded = 0; - for( uint_t i = 0; i < nhdrs; ++i, ++curr ) { - -#if TRACING_ELF - dump_phdr( curr, i ); -#endif - if( curr->p_type != PT_LOAD ) { - // not loadable --> we'll skip it - continue; - } - - if( loaded >= N_LOADABLE ) { -#if TRACING_USER - cio_puts( " LIMIT\n" ); -#endif - return E_LOAD_LIMIT; - } - - // set a pointer to the bytes within the object file - char *data = (char *) (((uint32_t)hdr) + curr->p_offset); -#if TRACING_USER - cio_printf( " data @ %08x", (uint32_t) data ); -#endif - - // copy the pages into memory - int stat = vm_add( pcb->pdir, curr->p_flags & PF_W, false, - (char *) curr->p_va, curr->p_memsz, data, curr->p_filesz ); - if( stat != SUCCESS ) { - // TODO what else should we do here? check for memory leak? - return stat; - } - - // set the section table entry in the PCB - pcb->sects[loaded].length = curr->p_memsz; - pcb->sects[loaded].addr = curr->p_va; -#if TRACING_USER - cio_printf( " loaded %u @ %08x\n", - pcb->sects[loaded].length, pcb->sects[loaded].addr ); -#endif - ++loaded; - } - - return SUCCESS; -} - -/** -** Name: stack_setup -** -** Set up the stack for a new process -** -** @param pcb Pointer to the PCB for the process -** @param entry Entry point for the new process -** @param args Argument vector to be put in place -** -** @return A pointer to the context_t on the stack, or NULL -*/ -static context_t *stack_setup( pcb_t *pcb, uint32_t entry, const char **args ) { - - /* - ** First, we need to count the space we'll need for the argument - ** vector and strings. - */ - - int argbytes = 0; - int argc = 0; - - while( args[argc] != NULL ) { - int n = strlen( args[argc] ) + 1; - // can't go over one page in size - if( (argbytes + n) > SZ_PAGE ) { - // oops - ignore this and any others - break; - } - argbytes += n; - ++argc; - } - - // Round up the byte count to the next multiple of four. - argbytes = (argbytes + 3) & MOD4_MASK; - - /* - ** Allocate the arrays. We are safe using dynamic arrays here - ** because we're using the OS stack, not the user stack. - ** - ** We want the argstrings and argv arrays to contain all zeroes. - ** The C standard states, in section 6.7.8, that - ** - ** "21 If there are fewer initializers in a brace-enclosed list - ** than there are elements or members of an aggregate, or - ** fewer characters in a string literal used to initialize an - ** array of known size than there are elements in the array, - ** the remainder of the aggregate shall be initialized - ** implicitly the same as objects that have static storage - ** duration." - ** - ** Sadly, because we're using variable-sized arrays, we can't - ** rely on this, so we have to call memclr() instead. :-( In - ** truth, it doesn't really cost us much more time, but it's an - ** annoyance. - */ - - char argstrings[ argbytes ]; - char *argv[ argc + 1 ]; - - CLEAR( argstrings ); - CLEAR( argv ); - - // Next, duplicate the argument strings, and create pointers to - // each one in our argv. - char *tmp = argstrings; - for( int i = 0; i < argc; ++i ) { - int nb = strlen(args[i]) + 1; // bytes (incl. NUL) in this string - strcpy( tmp, args[i] ); // add to our buffer - argv[i] = tmp; // remember where it was - tmp += nb; // move on - } - - // trailing NULL pointer - argv[argc] = NULL; - - /* - ** The pages for the stack were cleared when they were allocated, - ** so we don't need to remember to do that. - ** - ** We reserve one longword at the bottom of the stack to hold a - ** pointer to where argv is on the stack. - ** - ** The user code was linked with a startup function that defines - ** the entry point (_start), calls main(), and then calls exit() - ** if main() returns. We need to set up the stack this way: - ** - ** esp -> context <- context save area - ** ... <- context save area - ** context <- context save area - ** entry_pt <- return address for the ISR - ** argc <- argument count for main() - ** /-> argv <- argv pointer for main() - ** | ... <- argv array w/trailing NULL - ** | ... <- argv character strings - ** \--- ptr <- last word in stack - ** - ** Stack alignment rules for the SysV ABI i386 supplement dictate that - ** the 'argc' parameter must be at an address that is a multiple of 16; - ** see below for more information. - */ - - // Pointer to the last word in stack. We get this from the - // VM hierarchy. Get the PDE entry for the user address space. - pde_t stack_pde = pcb->pdir[USER_PDE]; - - // The PDE entry points to the PT, which is an array of PTE. The last - // two entries are for the stack; pull out the last one. - pte_t stack_pte = ((pte_t *)(stack_pde & MOD4K_MASK))[USER_STK_PTE2]; - - // OK, now we have the PTE. The frame address of the last page is - // in this PTE. Find the address immediately after that. - uint32_t *ptr = (uint32_t *) - ((uint32_t)(stack_pte & MOD4K_MASK) + SZ_PAGE); - - // Pointer to where the arg strings should be filled in. - char *strings = (char *) ( (uint32_t) ptr - argbytes ); - - // back the pointer up to the nearest word boundary; because we're - // moving toward location 0, the nearest word boundary is just the - // next smaller address whose low-order two bits are zeroes - strings = (char *) ((uint32_t) strings & MOD4_MASK); - - // Copy over the argv strings. - memcpy( (void *)strings, argstrings, argbytes ); - - /* - ** Next, we need to copy over the argv pointers. Start by - ** determining where 'argc' should go. - ** - ** Stack alignment is controlled by the SysV ABI i386 supplement, - ** version 1.2 (June 23, 2016), which states in section 2.2.2: - ** - ** "The end of the input argument area shall be aligned on a 16 - ** (32 or 64, if __m256 or __m512 is passed on stack) byte boundary. - ** In other words, the value (%esp + 4) is always a multiple of 16 - ** (32 or 64) when control is transferred to the function entry - ** point. The stack pointer, %esp, always points to the end of the - ** latest allocated stack frame." - ** - ** Isn't technical documentation fun? Ultimately, this means that - ** the first parameter to main() should be on the stack at an address - ** that is a multiple of 16. - ** - ** The space needed for argc, argv, and the argv array itself is - ** argc + 3 words (argc+1 for the argv entries, plus one word each - ** for argc and argv). We back up that much from 'strings'. - */ - - int nwords = argc + 3; - uint32_t *acptr = ((uint32_t *) strings) - nwords; - - /* - ** Next, back up until we're at a multiple-of-16 address. Because we - ** are moving to a lower address, its upper 28 bits are identical to - ** the address we currently have, so we can do this with a bitwise - ** AND to just turn off the lower four bits. - */ - - acptr = (uint32_t *) ( ((uint32_t)acptr) & MOD16_MASK ); - - // copy in 'argc' - *acptr = argc; - - // next, 'argv', which follows 'argc'; 'argv' points to the - // word that follows it in the stack - uint32_t *avptr = acptr + 2; - *(acptr+1) = (uint32_t) avptr; - - /* - ** Next, we copy in all argc+1 pointers. - */ - - // Adjust and copy the string pointers. - for( int i = 0; i <= argc; ++i ) { - if( argv[i] != NULL ) { - // an actual pointer - adjust it and copy it in - *avptr = (uint32_t) strings; - // skip to the next entry in the array - strings += strlen(argv[i]) + 1; - } else { - // end of the line! - *avptr = NULL; - } - ++avptr; - } - - /* - ** Now, we need to set up the initial context for the executing - ** process. - ** - ** When this process is dispatched, the context restore code will - ** pop all the saved context information off the stack, including - ** the saved EIP, CS, and EFLAGS. We set those fields up so that - ** the interrupt "returns" to the entry point of the process. - */ - - // Locate the context save area on the stack. - context_t *ctx = ((context_t *) avptr) - 1; - - /* - ** We cleared the entire stack earlier, so all the context - ** fields currently contain zeroes. We now need to fill in - ** all the important fields. - */ - - ctx->eflags = DEFAULT_EFLAGS; // IE enabled, PPL 0 - ctx->eip = entry; // initial EIP - ctx->cs = GDT_CODE; // segment registers - ctx->ss = GDT_STACK; - ctx->ds = ctx->es = ctx->fs = ctx->gs = GDT_DATA; - - /* - ** Return the new context pointer to the caller. It will be our - ** caller's responsibility to schedule this process. - */ - - return( ctx ); -} - -/* -** PUBLIC FUNCTIONS -*/ - -/** -** Name: user_init -** -** Initializes the user support module. -*/ -void user_init( void ) { - -#if TRACING_INIT - cio_puts( " User" ); -#endif - - // This is gross, but we need to get this information somehow. - // Access the "user blob" data in the second bootstrap sector - uint16_t *blobdata = (uint16_t *) USER_BLOB_DATA; - user_offset = *blobdata++; - user_segment = *blobdata++; - user_sectors = *blobdata++; - -#if TRACING_USER - cio_printf( "\nUser blob: %u sectors @ %04x:%04x", user_sectors, - user_segment, user_offset ); -#endif - - // calculate the location of the user blob - if( user_sectors > 0 ) { - - // calculate the address of the header - user_header = (header_t *) - ( KERN_BASE + - ( (((uint_t)user_segment) << 4) + ((uint_t)user_offset) ) - ); - - // the program table immediate follows the blob header - prog_table = (prog_t *) (user_header + 1); - -#if TRACING_USER - cio_printf( ", hdr %08x, %u progs, tbl %08x\n", (uint32_t) user_header, - user_header->num, (uint32_t) prog_table ); -#endif - - } else { - // too bad, so sad! - user_header = NULL; - prog_table = NULL; -#if TRACING_USER - cio_putchar( '\n' ); -#endif - } -} - -/** -** Name: user_locate -** -** Locates a user program in the user code archive. -** -** @param what The ID of the user program to find -** -** @return pointer to the program table entry in the code archive, or NULL -*/ -prog_t *user_locate( uint_t what ) { - - // no programs if there is no blob! - if( user_header == NULL ) { - return NULL; - } - - // make sure this is a reasonable program to request - if( what >= user_header->num ) { - // no such program! - return NULL; - } - - // find the entry in the program table - prog_t *prog = &prog_table[what]; - - // if there are no bytes, it's useless - if( prog->size < 1 ) { - return NULL; - } - - // return the program table pointer - return prog; -} - -/** -** Name: user_duplicate -** -** Duplicates the memory setup for an existing process. -** -** @param new The PCB for the new copy of the program -** @param old The PCB for the existing the program -** -** @return the status of the duplicate attempt -*/ -int user_duplicate( pcb_t *new, pcb_t *old ) { - - // We need to do a recursive duplication of the process address - // space of the current process. First, we create a new user - // page directory. Next, we'll duplicate the USER_PDE page - // table. Finally, we'll go through that table and duplicate - // all the frames. - - // create the initial VM hierarchy - pde_t *pdir = vm_mkuvm(); - if( pdir == NULL ) { - return E_NO_MEMORY; - } - new->pdir = pdir; - - // Next, add a USER_PDE page table that's a duplicate of the - // current process' page table - if( !vm_uvmdup(old->pdir,new->pdir) ) { - // check for memory leak? - return E_NO_MEMORY; - } - - // We don't do copy-on-write, so we must duplicate all the - // individual page frames. Iterate through all the user-level - // PDE entries, and replace the existing frames with duplicates. - // - // NOTE: we only deal with pdir[0] here, as we are limiting - // the user address space to the first 4MB. If the size of - // the address space goes up, this code will need to be - // modified to loop over the larger space. - - // pointer to the PMT for the user - pte_t *pt = (pte_t *) (pdir[USER_PDE]); - assert( pt != NULL ); - - for( int i = 0; i < N_PTE; ++i ) { - // get the current entry from the PMT - pte_t entry = *pt; - - // if this entry is present, - if( IS_PRESENT(entry) ) { - - // duplicate the frame pointed to by this PTE - void *tmp = vm_pagedup( (void *) PTE_ADDR(entry) ); - - // replace the old frame number with the new one - *pt = (pte_t) (((uint32_t)tmp) | PERMS(entry) ); - - } else { - - *pt = 0; - - } - ++pt; - } - - return SUCCESS; -} - -/** -** Name: user_load -** -** Loads a user program from the user code archive into memory. -** Allocates all needed frames and sets up the VM tables. -** -** @param ptab A pointer to the program table entry to be loaded -** @param pcb The PCB for the program being loaded -** @param args The argument vector for the program -** -** @return the status of the load attempt -*/ -int user_load( prog_t *ptab, pcb_t *pcb, const char **args ) { - - // NULL pointers are bad! - assert1( ptab != NULL ); - assert1( pcb != NULL ); - assert1( args != NULL ); - - // locate the ELF binary - elfhdr_t *hdr = (elfhdr_t *) ((uint32_t)user_header + ptab->offset); - -#if TRACING_ELF - cio_printf( "Load: ptab %08x: '%s', off %08x, size %08x, flags %08x\n", - (uint32_t) ptab, ptab->name, ptab->offset, ptab->size, - ptab->flags ); - cio_printf( " args %08x:", (uint32_t) args ); - for( int i = 0; args[i] != NULL; ++i ) { - cio_printf( " [%d] %s", i, args[i] ); - } - cio_printf( "\n pcb %08x (pid %u)\n", (uint32_t) pcb, pcb->pid ); - dump_fhdr( hdr ); -#endif - - // verify the ELF header - if( hdr->e_ident.f.magic != ELF_MAGIC ) { - return E_BAD_PARAM; - } - - // allocate a page directory - pcb->pdir = vm_mkuvm(); - if( pcb->pdir == NULL ) { - return E_NO_MEMORY; - } - - // read all the program headers - int stat = read_phdrs( hdr, pcb ); - if( stat != SUCCESS ) { - // TODO figure out a better way to deal with this - PANIC( 0, "user_load: phdr read failed" ); - } - - // next, set up the runtime stack - just like setting up loadable - // sections, except nothing to copy - stat = vm_add( pcb->pdir, true, false, (void *) USER_STACK, - SZ_USTACK, NULL, 0 ); - if( stat != SUCCESS ) { - // TODO yadda yadda... - PANIC( 0, "user_load: vm_add failed" ); - } - - // set up the command-line arguments - pcb->context = stack_setup( pcb, hdr->e_entry, args ); - - return SUCCESS; -} - -/** -** Name: user_cleanup -** -** "Unloads" a user program. Deallocates all memory frames and -** cleans up the VM structures. -** -** @param pcb The PCB of the program to be unloaded -*/ -void user_cleanup( pcb_t *pcb ) { - - if( pcb == NULL ) { - // should this be an error? - return; - } - - vm_free( pcb->pdir ); - pcb->pdir = NULL; -} diff --git a/kernel/old/vm.c b/kernel/old/vm.c deleted file mode 100644 index 749bed3..0000000 --- a/kernel/old/vm.c +++ /dev/null @@ -1,625 +0,0 @@ -/** -** @file vm.c -** -** @author CSCI-452 class of 20245 -** -** @brief Kernel VM support -*/ - -#define KERNEL_SRC - -#include - -#include -#include - -#include -#include -#include -#include - -/* -** PUBLIC GLOBAL VARIABLES -*/ - -// created page directory for the kernel -pde_t *kpdir; - -/* -** PRIVATE FUNCTIONS -*/ - -/** -** Name: vm_isr -** -** Description: Page fault handler -** -** @param vector Interrupt vector number -** @param code Error code pushed onto the stack -*/ -static void vm_isr( int vector, int code ) { - - // get whatever information we can from the fault - pfec_t fault; - fault.u = (uint32_t) code; - uint32_t addr = r_cr2(); - - // report what we found - sprint( b256, - "** page fault @ 0x%08x %cP %c %cM %cRSV %c %cPK %cSS %cHLAT %cSGZ", - addr, - fault.s.p ? ' ' : '!', - fault.s.w ? 'W' : 'R', - fault.s.us ? 'U' : 'S', - fault.s.rsvd ? ' ' : '!', - fault.s.id ? 'I' : 'D', - fault.s.pk ? ' ' : '!', - fault.s.ss ? ' ' : '!', - fault.s.hlat ? ' ' : '!', - fault.s.sgz ? ' ' : '!' - ); - - // and give up - PANIC( 0, b256 ); -} - -/** -** Name: uva2kva -** -** Convert a user VA into a kernel address. Works for all addresses - -** if the address is a page address, the PERMS(va) value will be 0; -** otherwise, it is the offset into the page. -** -** @param pdir Pointer to the page directory to examine -** @param va Virtual address to check -*/ -ATTR_UNUSED -static void *uva2kva( pde_t *pdir, void *va ) { - - // find the PMT entry for this address - pte_t *pte = vm_getpte( pdir, va, false ); - if( pte == NULL ) { - return NULL; - } - - // get the entry - pte_t entry = *pte; - - // is this a valid address for the user? - if( IS_PRESENT(entry) ) { - return NULL; - } - - // is this a system-only page? - if( IS_SYSTEM(entry) ) { - return NULL; - } - - // get the physical address - uint32_t frame = PTE_ADDR(*pte) | PERMS(va); - - return (void *) P2V(frame); -} - - -/* -** PUBLIC FUNCTIONS -*/ - -/** -** Name: vm_init -** -** Description: Initialize the VM module -*/ -void vm_init( void ) { - -#if TRACING_INIT - cio_puts( " VM" ); -#endif - - // set up the kernel's 4K-page directory - kpdir = vm_mkkvm(); - assert( kpdir != NULL ); - - // switch to it - vm_set_kvm(); - - // install the page fault handler - install_isr( VEC_PAGE_FAULT, vm_isr ); -} - -/** -** Name: vm_pagedup -** -** Duplicate a page of memory -** -** @param old Pointer to the first byte of a page -** -** @return a pointer to the new, duplicate page, or NULL -*/ -void *vm_pagedup( void *old ) { - void *new = (void *) km_page_alloc(); - if( new != NULL ) { - blkmov( new, old, SZ_PAGE ); - } - return new; -} - -/** -** Name: vm_pdedup -** -** Duplicate a page directory entry -** -** @param dst Pointer to where the duplicate should go -** @param curr Pointer to the entry to be duplicated -** -** @return true on success, else false -*/ -bool_t vm_pdedup( pde_t *dst, pde_t *curr ) { - - assert1( curr != NULL ); - assert1( dst != NULL ); - -#if TRACING_VM - cio_printf( "vm_pdedup dst %08x curr %08x\n", - (uint32_t) dst, (uint32_t) curr ); -#endif - pde_t entry = *curr; - - // simplest case - if( !IS_PRESENT(entry) ) { - *dst = 0; - return true; - } - - // OK, we have an entry; allocate a page table for it - pte_t *newtbl = (pte_t *) km_page_alloc(); - if( newtbl == NULL ) { - return false; - } - - // we could clear the new table, but we'll be assigning to - // each entry anyway, so we'll save the execution time - - // address of the page table for this directory entry - pte_t *old = (pte_t *) PDE_ADDR(entry); - - // pointer to the first PTE in the new table - pte_t *new = newtbl; - - for( int i = 0 ; i < N_PTE; ++i ) { - if( !IS_PRESENT(*old) ) { - *new = 0; - } else { - *new = *old; - } - ++old; - ++new; - } - - // replace the page table address - // upper 22 bits from 'newtbl', lower 12 from '*curr' - *dst = (pde_t) ( PTE_ADDR(newtbl) | PERMS(entry) ); - - return true; -} - -/** -** Name: vm_getpte -** -** Return the address of the PTE corresponding to the virtual address -** 'va' within the address space controlled by 'pgdir'. If there is no -** page table for that VA and 'alloc' is true, create the necessary -** page table entries. -** -** @param pdir Pointer to the page directory to be searched -** @param va The virtual address we're looking for -** @param alloc Should we allocate a page table if there isn't one? -** -** @return A pointer to the page table entry for this VA, or NULL if -** there isn't one and we're not allocating -*/ -pte_t *vm_getpte( pde_t *pdir, const void *va, bool_t alloc ) { - pte_t *ptab; - - // sanity check - assert1( pdir != NULL ); - - // get the PDIR entry for this virtual address - pde_t *pde = &pdir[ PDIX(va) ]; - - // is it already set up? - if( IS_PRESENT(*pde) ) { - - // yes! - ptab = (pte_t*)P2V(PTE_ADDR(*pde)); - - } else { - - // no - should we create it? - if( !alloc ) { - // nope, so just return - return NULL; - } - - // yes - try to allocate a page table - ptab = (pte_t *) km_page_alloc(); - if( ptab == NULL ) { - WARNING( "can't allocate page table" ); - return NULL; - } - - // who knows what was left in this page.... - memclr( ptab, SZ_PAGE ); - - // add this to the page directory - // - // we set this up to allow general access; this could be - // controlled by setting access control in the page table - // entries, if necessary. - // - // NOTE: the allocator is serving us virtual page addresses, - // so we must convert them to physical addresses - *pde = ((uint32_t) V2P(ptab)) | PDE_P | PDE_RW; - } - - // finally, return a pointer to the entry in the - // page table for this VA - return &ptab[ PTIX(va) ]; -} - -// Set up kernel part of a page table. -pde_t *vm_mkkvm( void ) -{ - mapping_t *k; - - // allocate the page directory - pde_t *pdir = km_page_alloc(); - if( pdir == NULL ) { - return NULL; - } - - // clear it out to disable all the entries - memclr( pdir, SZ_PAGE ); - - if( P2V(PHYS_TOP) > DEV_BASE ) { - cio_printf( "PHYS_TOP (%08x -> %08x) > DEV_BASE(%08x)\n", - PHYS_TOP, P2V(PHYS_TOP), DEV_BASE ); - PANIC( 0, "PHYS_TOP too large" ); - } - - // map in all the page ranges - k = kmap; - for( int i = 0; i < n_kmap; ++i, ++k ) { - int stat = vm_map( pdir, ((void *)k->va_start), - k->pa_end - k->pa_start, - k->pa_start, k->perm ); - if( stat != SUCCESS ) { - vm_free( pdir ); - return 0; - } - } - - return pdir; -} - -/* -** Creates an initial user VM table hierarchy by copying the -** system entries into a new page directory. -** -** @return a pointer to the new page directory, or NULL -*/ -pde_t *vm_mkuvm( void ) { - - // allocate the directory - pde_t *new = (pde_t *) km_page_alloc(); - if( new == NULL ) { - return NULL; - } - - // iterate through the kernel page directory - pde_t *curr = kpdir; - pde_t *dst = new; - for( int i = 0; i < N_PDE; ++i ) { - - if( *curr != 0 ) { - // found an active one - duplicate it - if( !vm_pdedup(dst,curr) ) { - return NULL; - } - } - - ++curr; - ++dst; - } - - return new; - -} - -/** -** Name: vm_set_kvm -** -** Switch the page table register to the kernel's page directory. -*/ -void vm_set_kvm( void ) { - w_cr3( V2P(kpdir) ); // switch to the kernel page table -} - -/** -** Name: vm_set_uvm -** -** Switch the page table register to the page directory for a user process. -** -** @param p PCB of the process we're switching to -*/ -void vm_set_uvm( pcb_t *p ) { - assert( p != NULL ); - assert( p->pdir != NULL ); - - w_cr3( V2P(p->pdir) ); // switch to process's address space -} - -/** -** Name: vm_add -** -** Add pages to the page hierarchy for a process, copying data into -** them if necessary. -** -** @param pdir Pointer to the page directory to modify -** @param wr "Writable" flag for the PTE -** @param sys "System" flag for the PTE -** @param va Starting VA of the range -** @param size Amount of physical memory to allocate (bytes) -** @param data Pointer to data to copy, or NULL -** @param bytes Number of bytes to copy -** -** @return status of the allocation attempt -*/ -int vm_add( pde_t *pdir, bool_t wr, bool_t sys, - void *va, uint32_t size, char *data, uint32_t bytes ) { - - // how many pages do we need? - uint_t npages = ((size & MOD4K_BITS) ? PGUP(size) : size) >> MOD4K_SHIFT; - - // permission set for the PTEs - uint_t entrybase = PTE_P; - if( wr ) { - entrybase |= PTE_RW; - } - if( sys ) { - entrybase |= PTE_US; - } - -#if TRACING_VM - cio_printf( "vm_add: pdir %08x, %s, va %08x (%u, %u pgs)\n", - (uint32_t) pdir, wr ? "W" : "!W", (uint32_t) va, size ); - cio_printf( " from %08x, %u bytes, perms %08x\n", - (uint32_t) data, bytes, entrybase ); -#endif - - // iterate through the pages - - for( int i = 0; i < npages; ++i ) { - - // figure out where this page will go in the hierarchy - pte_t *pte = vm_getpte( pdir, va, true ); - if( pte == NULL ) { - // TODO if i > 0, this isn't the first frame - is - // there anything to do about other frames? - // POSSIBLE MEMORY LEAK? - return E_NO_MEMORY; - } - - // allocate the frame - void *page = km_page_alloc(); - if( page == NULL ) { - // TODO same question here - return E_NO_MEMORY; - } - - // clear it all out - memclr( page, SZ_PAGE ); - - // create the PTE for this frame - uint32_t entry = (uint32_t) (PTE_ADDR(page) | entrybase); - *pte = entry; - - // copy data if we need to - if( data != NULL && bytes > 0 ) { - // how much to copy - uint_t num = bytes > SZ_PAGE ? SZ_PAGE : bytes; - // do it! - memcpy( (void *)page, (void *)data, num ); - // adjust all the pointers - data += num; // where to continue - bytes -= num; // what's left to copy - } - - // bump the virtual address - va += SZ_PAGE; - } - - return SUCCESS; - -} - -/** -** Name: vm_free -** -** Deallocate a page table hierarchy and all physical memory frames -** in the user portion. -** -** Works only for 4KB pages. -** -** @param pdir Pointer to the page directory -*/ -void vm_free( pde_t *pdir ) { - - // do we have anything to do? - if( pdir == NULL ) { - return; - } - - // iterate through the page directory entries, freeing the - // PMTS and the frames they point to - pde_t *curr = pdir; - for( int i = 0; i < N_PDE; ++i ) { - - // the entry itself - pde_t entry = *curr; - - // does this entry point to anything useful? - if( IS_PRESENT(entry) ) { - - // yes - large pages make us unhappy - assert( !IS_LARGE(entry) ); - - // get the PMT pointer - pte_t *pmt = (pte_t *) PTE_ADDR(entry); - - // walk the PMT - for( int j = 0; j < N_PTE; ++j ) { - // does this entry point to a frame? - if( IS_PRESENT(*pmt) ) { - // yes - free the frame - km_page_free( (void *) PTE_ADDR(*pmt) ); - // mark it so we don't get surprised - *pmt = 0; - } - // move on - ++pmt; - } - // now, free the PMT itself - km_page_free( (void *) PDE_ADDR(entry) ); - *curr = 0; - } - - // move to the next entry - ++curr; - } - - // finally, free the PDIR itself - km_page_free( (void *) pdir ); -} - -/* -** Name: vm_map -** -** Create PTEs for virtual addresses starting at 'va' that refer to -** physical addresses in the range [pa, pa+size-1]. We aren't guaranteed -** that va is page-aligned. -** -** @param pdir Page directory for this address space -** @param va The starting virtual address -** @param size Length of the range to be mapped -** @param pa The starting physical address -** @param perm Permission bits for the PTEs -** -** @return the status of the mapping attempt -*/ -int vm_map( pde_t *pdir, void *va, uint_t size, uint_t pa, int perm ) { - - // round the VA down to its page boundary - char *addr = (char*)PGDOWN((uint_t)va); - - // round the end of the range down to its page boundary - char *last = (char*)PGDOWN(((uint_t)va) + size - 1); - - while( addr < last ) { - - // get a pointer to the PTE for the current VA - pte_t *pte = vm_getpte( pdir, addr, true ); - if( pte == NULL ) { - // couldn't find it - return E_NO_PTE; - } - - // if this entry has already been mapped, we're in trouble - if( IS_PRESENT(*pte) ) { - cio_printf( "vm_map(%08x,%08x,%u,%08x,%03x)\n", - (uint32_t) pdir, (uint32_t) va, size, pa, perm ); - cio_printf( " addr %08x last %08x pte %08x *pte %08x\n", - (uint32_t) addr, (uint32_t) last, - (uint32_t) pte, *pte ); - - PANIC( 0, "mapping an already-mapped address" ); - } - - // ok, set the PTE as requested - *pte = pa | perm | PTE_P; - - // nope - move to the next page - addr += SZ_PAGE; - pa += SZ_PAGE; - - } - return SUCCESS; -} - -/** -** Name: vm_uvmdup -** -** Create a duplicate of the user portio of an existing page table -** hierarchy. We assume that the "new" page directory exists and -** the system portions of it should not be touched. -** -** Note: we do not duplicate the frames in the hierarchy - we just -** create a duplicate of the hierarchy itself. This means that we -** now have two sets of page tables that refer to the same physical -** frames in memory. -** -** @param old Existing page directory -** @param new New page directory -** -** @return status of the duplication attempt -*/ -int vm_uvmdup( pde_t *old, pde_t *new ) { - - if( old == NULL || new == NULL ) { - return E_BAD_PARAM; - } - - // we only want to deal with the "user" half of the address space - for( int i = 0; i < (N_PDE >> 1); ++i ) { - - // the entry to copy - pde_t entry = *old; - - // is this entry in use? - if( IS_PRESENT(entry) ) { - - // yes. if it points to a 4MB page, we just copy it; - // otherwise, we must duplicate the next level PMT - - if( !IS_LARGE(entry) ) { - - // it's a 4KB page, so we need to duplicate the PMT - pte_t *newpt = (pte_t *) vm_pagedup( (void *)PTE_ADDR(entry) ); - if( newpt == NULL ) { - return E_NO_MEMORY; - } - - uint32_t perms = PERMS(entry); - - // create the new PDE entry by replacing the frame # - entry = ((uint32_t) newpt) | perms; - } - - } else { - - // not present, so create an empty entry - entry = 0; - - } - - // send it on its way - *new = entry; - - // move on down the line - ++old; - ++new; - } - - return SUCCESS; -} diff --git a/kernel/old/vmtables.c b/kernel/old/vmtables.c deleted file mode 100644 index a50315d..0000000 --- a/kernel/old/vmtables.c +++ /dev/null @@ -1,338 +0,0 @@ -/** -** @file vmtables.c -** -** @author CSCI-452 class of 20245 -** -** @brief Kernel VM tables -** -** Compilation options: -** -** MAKE_IDENTITY_MAP Creates a page table that identity-maps the first -** 4MB of main memory. -*/ - -#define KERNEL_SRC - -#include - -#include -#include -#include -#include - -// defined for us by the linker -extern char _data[]; - -/* -** Initial page directory, for when the kernel is starting up -** -** we use large (4MB) pages here to allow us to use a one-level -** paging hierarchy; the kernel will create a new page table -** hierarchy once memory is initialized -** -** We only map the first 2GB of memory, plus a 4MB portion of -** the upper half, which we map to cover the first 4MB of -** memory. -*/ - -// identity-map 4MB virtual address #n to physical 4MB address #n -// used for addresses 0 to 2GB -#define L(n) [n] = (pde_t) ( (TO_4MFRAME((n))) | (PDE_P|PDE_RW|PDE_PS) ) - -// ditto, but adds 512 (0x200) to the index -// used for addresses 2GB to 4GB -#define M(n) [n|0x200] = (pde_t) ( (TO_4MFRAME((n))) | (PDE_P|PDE_RW|PDE_PS) ) - -ATTR_ALIGNED(SZ_PAGE) -const pde_t firstpdir[N_PDE] = { - - // Map VA range [0, 2GB] to PA range [0, 2GB] -L(0x000), L(0x001), L(0x002), L(0x003), L(0x004), L(0x005), L(0x006), L(0x007), -L(0x008), L(0x009), L(0x00a), L(0x00b), L(0x00c), L(0x00d), L(0x00e), L(0x00f), -L(0x010), L(0x011), L(0x012), L(0x013), L(0x014), L(0x015), L(0x016), L(0x017), -L(0x018), L(0x019), L(0x01a), L(0x01b), L(0x01c), L(0x01d), L(0x01e), L(0x01f), -L(0x020), L(0x021), L(0x022), L(0x023), L(0x024), L(0x025), L(0x026), L(0x027), -L(0x028), L(0x029), L(0x02a), L(0x02b), L(0x02c), L(0x02d), L(0x02e), L(0x02f), -L(0x030), L(0x031), L(0x032), L(0x033), L(0x034), L(0x035), L(0x036), L(0x037), -L(0x038), L(0x039), L(0x03a), L(0x03b), L(0x03c), L(0x03d), L(0x03e), L(0x03f), -L(0x040), L(0x041), L(0x042), L(0x043), L(0x044), L(0x045), L(0x046), L(0x047), -L(0x048), L(0x049), L(0x04a), L(0x04b), L(0x04c), L(0x04d), L(0x04e), L(0x04f), -L(0x050), L(0x051), L(0x052), L(0x053), L(0x054), L(0x055), L(0x056), L(0x057), -L(0x058), L(0x059), L(0x05a), L(0x05b), L(0x05c), L(0x05d), L(0x05e), L(0x05f), -L(0x060), L(0x061), L(0x062), L(0x063), L(0x064), L(0x065), L(0x066), L(0x067), -L(0x068), L(0x069), L(0x06a), L(0x06b), L(0x06c), L(0x06d), L(0x06e), L(0x06f), -L(0x070), L(0x071), L(0x072), L(0x073), L(0x074), L(0x075), L(0x076), L(0x077), -L(0x078), L(0x079), L(0x07a), L(0x07b), L(0x07c), L(0x07d), L(0x07e), L(0x07f), -L(0x080), L(0x081), L(0x082), L(0x083), L(0x084), L(0x085), L(0x086), L(0x087), -L(0x088), L(0x089), L(0x08a), L(0x08b), L(0x08c), L(0x08d), L(0x08e), L(0x08f), -L(0x090), L(0x091), L(0x092), L(0x093), L(0x094), L(0x095), L(0x096), L(0x097), -L(0x098), L(0x099), L(0x09a), L(0x09b), L(0x09c), L(0x09d), L(0x09e), L(0x09f), -L(0x0a0), L(0x0a1), L(0x0a2), L(0x0a3), L(0x0a4), L(0x0a5), L(0x0a6), L(0x0a7), -L(0x0a8), L(0x0a9), L(0x0aa), L(0x0ab), L(0x0ac), L(0x0ad), L(0x0ae), L(0x0af), -L(0x0b0), L(0x0b1), L(0x0b2), L(0x0b3), L(0x0b4), L(0x0b5), L(0x0b6), L(0x0b7), -L(0x0b8), L(0x0b9), L(0x0ba), L(0x0bb), L(0x0bc), L(0x0bd), L(0x0be), L(0x0bf), -L(0x0c0), L(0x0c1), L(0x0c2), L(0x0c3), L(0x0c4), L(0x0c5), L(0x0c6), L(0x0c7), -L(0x0c8), L(0x0c9), L(0x0ca), L(0x0cb), L(0x0cc), L(0x0cd), L(0x0ce), L(0x0cf), -L(0x0d0), L(0x0d1), L(0x0d2), L(0x0d3), L(0x0d4), L(0x0d5), L(0x0d6), L(0x0d7), -L(0x0d8), L(0x0d9), L(0x0da), L(0x0db), L(0x0dc), L(0x0dd), L(0x0de), L(0x0df), -L(0x0e0), L(0x0e1), L(0x0e2), L(0x0e3), L(0x0e4), L(0x0e5), L(0x0e6), L(0x0e7), -L(0x0e8), L(0x0e9), L(0x0ea), L(0x0eb), L(0x0ec), L(0x0ed), L(0x0ee), L(0x0ef), -L(0x0f0), L(0x0f1), L(0x0f2), L(0x0f3), L(0x0f4), L(0x0f5), L(0x0f6), L(0x0f7), -L(0x0f8), L(0x0f9), L(0x0fa), L(0x0fb), L(0x0fc), L(0x0fd), L(0x0fe), L(0x0ff), -L(0x100), L(0x101), L(0x102), L(0x103), L(0x104), L(0x105), L(0x106), L(0x107), -L(0x108), L(0x109), L(0x10a), L(0x10b), L(0x10c), L(0x10d), L(0x10e), L(0x10f), -L(0x110), L(0x111), L(0x112), L(0x113), L(0x114), L(0x115), L(0x116), L(0x117), -L(0x118), L(0x119), L(0x11a), L(0x11b), L(0x11c), L(0x11d), L(0x11e), L(0x11f), -L(0x120), L(0x121), L(0x122), L(0x123), L(0x124), L(0x125), L(0x126), L(0x127), -L(0x128), L(0x129), L(0x12a), L(0x12b), L(0x12c), L(0x12d), L(0x12e), L(0x12f), -L(0x130), L(0x131), L(0x132), L(0x133), L(0x134), L(0x135), L(0x136), L(0x137), -L(0x138), L(0x139), L(0x13a), L(0x13b), L(0x13c), L(0x13d), L(0x13e), L(0x13f), -L(0x140), L(0x141), L(0x142), L(0x143), L(0x144), L(0x145), L(0x146), L(0x147), -L(0x148), L(0x149), L(0x14a), L(0x14b), L(0x14c), L(0x14d), L(0x14e), L(0x14f), -L(0x150), L(0x151), L(0x152), L(0x153), L(0x154), L(0x155), L(0x156), L(0x157), -L(0x158), L(0x159), L(0x15a), L(0x15b), L(0x15c), L(0x15d), L(0x15e), L(0x15f), -L(0x160), L(0x161), L(0x162), L(0x163), L(0x164), L(0x165), L(0x166), L(0x167), -L(0x168), L(0x169), L(0x16a), L(0x16b), L(0x16c), L(0x16d), L(0x16e), L(0x16f), -L(0x170), L(0x171), L(0x172), L(0x173), L(0x174), L(0x175), L(0x176), L(0x177), -L(0x178), L(0x179), L(0x17a), L(0x17b), L(0x17c), L(0x17d), L(0x17e), L(0x17f), -L(0x180), L(0x181), L(0x182), L(0x183), L(0x184), L(0x185), L(0x186), L(0x187), -L(0x188), L(0x189), L(0x18a), L(0x18b), L(0x18c), L(0x18d), L(0x18e), L(0x18f), -L(0x190), L(0x191), L(0x192), L(0x193), L(0x194), L(0x195), L(0x196), L(0x197), -L(0x198), L(0x199), L(0x19a), L(0x19b), L(0x19c), L(0x19d), L(0x19e), L(0x19f), -L(0x1a0), L(0x1a1), L(0x1a2), L(0x1a3), L(0x1a4), L(0x1a5), L(0x1a6), L(0x1a7), -L(0x1a8), L(0x1a9), L(0x1aa), L(0x1ab), L(0x1ac), L(0x1ad), L(0x1ae), L(0x1af), -L(0x1b0), L(0x1b1), L(0x1b2), L(0x1b3), L(0x1b4), L(0x1b5), L(0x1b6), L(0x1b7), -L(0x1b8), L(0x1b9), L(0x1ba), L(0x1bb), L(0x1bc), L(0x1bd), L(0x1be), L(0x1bf), -L(0x1c0), L(0x1c1), L(0x1c2), L(0x1c3), L(0x1c4), L(0x1c5), L(0x1c6), L(0x1c7), -L(0x1c8), L(0x1c9), L(0x1ca), L(0x1cb), L(0x1cc), L(0x1cd), L(0x1ce), L(0x1cf), -L(0x1d0), L(0x1d1), L(0x1d2), L(0x1d3), L(0x1d4), L(0x1d5), L(0x1d6), L(0x1d7), -L(0x1d8), L(0x1d9), L(0x1da), L(0x1db), L(0x1dc), L(0x1dd), L(0x1de), L(0x1df), -L(0x1e0), L(0x1e1), L(0x1e2), L(0x1e3), L(0x1e4), L(0x1e5), L(0x1e6), L(0x1e7), -L(0x1e8), L(0x1e9), L(0x1ea), L(0x1eb), L(0x1ec), L(0x1ed), L(0x1ee), L(0x1ef), -L(0x1f0), L(0x1f1), L(0x1f2), L(0x1f3), L(0x1f4), L(0x1f5), L(0x1f6), L(0x1f7), -L(0x1f8), L(0x1f9), L(0x1fa), L(0x1fb), L(0x1fc), L(0x1fd), L(0x1fe), L(0x1ff), - - // Map VA range [2GB, 4GB] to PA range [0, 2MB] -M(0x000), M(0x001), M(0x002), M(0x003), M(0x004), M(0x005), M(0x006), M(0x007), -M(0x008), M(0x009), M(0x00a), M(0x00b), M(0x00c), M(0x00d), M(0x00e), M(0x00f), -M(0x010), M(0x011), M(0x012), M(0x013), M(0x014), M(0x015), M(0x016), M(0x017), -M(0x018), M(0x019), M(0x01a), M(0x01b), M(0x01c), M(0x01d), M(0x01e), M(0x01f), -M(0x020), M(0x021), M(0x022), M(0x023), M(0x024), M(0x025), M(0x026), M(0x027), -M(0x028), M(0x029), M(0x02a), M(0x02b), M(0x02c), M(0x02d), M(0x02e), M(0x02f), -M(0x030), M(0x031), M(0x032), M(0x033), M(0x034), M(0x035), M(0x036), M(0x037), -M(0x038), M(0x039), M(0x03a), M(0x03b), M(0x03c), M(0x03d), M(0x03e), M(0x03f), -M(0x040), M(0x041), M(0x042), M(0x043), M(0x044), M(0x045), M(0x046), M(0x047), -M(0x048), M(0x049), M(0x04a), M(0x04b), M(0x04c), M(0x04d), M(0x04e), M(0x04f), -M(0x050), M(0x051), M(0x052), M(0x053), M(0x054), M(0x055), M(0x056), M(0x057), -M(0x058), M(0x059), M(0x05a), M(0x05b), M(0x05c), M(0x05d), M(0x05e), M(0x05f), -M(0x060), M(0x061), M(0x062), M(0x063), M(0x064), M(0x065), M(0x066), M(0x067), -M(0x068), M(0x069), M(0x06a), M(0x06b), M(0x06c), M(0x06d), M(0x06e), M(0x06f), -M(0x070), M(0x071), M(0x072), M(0x073), M(0x074), M(0x075), M(0x076), M(0x077), -M(0x078), M(0x079), M(0x07a), M(0x07b), M(0x07c), M(0x07d), M(0x07e), M(0x07f), -M(0x080), M(0x081), M(0x082), M(0x083), M(0x084), M(0x085), M(0x086), M(0x087), -M(0x088), M(0x089), M(0x08a), M(0x08b), M(0x08c), M(0x08d), M(0x08e), M(0x08f), -M(0x090), M(0x091), M(0x092), M(0x093), M(0x094), M(0x095), M(0x096), M(0x097), -M(0x098), M(0x099), M(0x09a), M(0x09b), M(0x09c), M(0x09d), M(0x09e), M(0x09f), -M(0x0a0), M(0x0a1), M(0x0a2), M(0x0a3), M(0x0a4), M(0x0a5), M(0x0a6), M(0x0a7), -M(0x0a8), M(0x0a9), M(0x0aa), M(0x0ab), M(0x0ac), M(0x0ad), M(0x0ae), M(0x0af), -M(0x0b0), M(0x0b1), M(0x0b2), M(0x0b3), M(0x0b4), M(0x0b5), M(0x0b6), M(0x0b7), -M(0x0b8), M(0x0b9), M(0x0ba), M(0x0bb), M(0x0bc), M(0x0bd), M(0x0be), M(0x0bf), -M(0x0c0), M(0x0c1), M(0x0c2), M(0x0c3), M(0x0c4), M(0x0c5), M(0x0c6), M(0x0c7), -M(0x0c8), M(0x0c9), M(0x0ca), M(0x0cb), M(0x0cc), M(0x0cd), M(0x0ce), M(0x0cf), -M(0x0d0), M(0x0d1), M(0x0d2), M(0x0d3), M(0x0d4), M(0x0d5), M(0x0d6), M(0x0d7), -M(0x0d8), M(0x0d9), M(0x0da), M(0x0db), M(0x0dc), M(0x0dd), M(0x0de), M(0x0df), -M(0x0e0), M(0x0e1), M(0x0e2), M(0x0e3), M(0x0e4), M(0x0e5), M(0x0e6), M(0x0e7), -M(0x0e8), M(0x0e9), M(0x0ea), M(0x0eb), M(0x0ec), M(0x0ed), M(0x0ee), M(0x0ef), -M(0x0f0), M(0x0f1), M(0x0f2), M(0x0f3), M(0x0f4), M(0x0f5), M(0x0f6), M(0x0f7), -M(0x0f8), M(0x0f9), M(0x0fa), M(0x0fb), M(0x0fc), M(0x0fd), M(0x0fe), M(0x0ff), -M(0x100), M(0x101), M(0x102), M(0x103), M(0x104), M(0x105), M(0x106), M(0x107), -M(0x108), M(0x109), M(0x10a), M(0x10b), M(0x10c), M(0x10d), M(0x10e), M(0x10f), -M(0x110), M(0x111), M(0x112), M(0x113), M(0x114), M(0x115), M(0x116), M(0x117), -M(0x118), M(0x119), M(0x11a), M(0x11b), M(0x11c), M(0x11d), M(0x11e), M(0x11f), -M(0x120), M(0x121), M(0x122), M(0x123), M(0x124), M(0x125), M(0x126), M(0x127), -M(0x128), M(0x129), M(0x12a), M(0x12b), M(0x12c), M(0x12d), M(0x12e), M(0x12f), -M(0x130), M(0x131), M(0x132), M(0x133), M(0x134), M(0x135), M(0x136), M(0x137), -M(0x138), M(0x139), M(0x13a), M(0x13b), M(0x13c), M(0x13d), M(0x13e), M(0x13f), -M(0x140), M(0x141), M(0x142), M(0x143), M(0x144), M(0x145), M(0x146), M(0x147), -M(0x148), M(0x149), M(0x14a), M(0x14b), M(0x14c), M(0x14d), M(0x14e), M(0x14f), -M(0x150), M(0x151), M(0x152), M(0x153), M(0x154), M(0x155), M(0x156), M(0x157), -M(0x158), M(0x159), M(0x15a), M(0x15b), M(0x15c), M(0x15d), M(0x15e), M(0x15f), -M(0x160), M(0x161), M(0x162), M(0x163), M(0x164), M(0x165), M(0x166), M(0x167), -M(0x168), M(0x169), M(0x16a), M(0x16b), M(0x16c), M(0x16d), M(0x16e), M(0x16f), -M(0x170), M(0x171), M(0x172), M(0x173), M(0x174), M(0x175), M(0x176), M(0x177), -M(0x178), M(0x179), M(0x17a), M(0x17b), M(0x17c), M(0x17d), M(0x17e), M(0x17f), -M(0x180), M(0x181), M(0x182), M(0x183), M(0x184), M(0x185), M(0x186), M(0x187), -M(0x188), M(0x189), M(0x18a), M(0x18b), M(0x18c), M(0x18d), M(0x18e), M(0x18f), -M(0x190), M(0x191), M(0x192), M(0x193), M(0x194), M(0x195), M(0x196), M(0x197), -M(0x198), M(0x199), M(0x19a), M(0x19b), M(0x19c), M(0x19d), M(0x19e), M(0x19f), -M(0x1a0), M(0x1a1), M(0x1a2), M(0x1a3), M(0x1a4), M(0x1a5), M(0x1a6), M(0x1a7), -M(0x1a8), M(0x1a9), M(0x1aa), M(0x1ab), M(0x1ac), M(0x1ad), M(0x1ae), M(0x1af), -M(0x1b0), M(0x1b1), M(0x1b2), M(0x1b3), M(0x1b4), M(0x1b5), M(0x1b6), M(0x1b7), -M(0x1b8), M(0x1b9), M(0x1ba), M(0x1bb), M(0x1bc), M(0x1bd), M(0x1be), M(0x1bf), -M(0x1c0), M(0x1c1), M(0x1c2), M(0x1c3), M(0x1c4), M(0x1c5), M(0x1c6), M(0x1c7), -M(0x1c8), M(0x1c9), M(0x1ca), M(0x1cb), M(0x1cc), M(0x1cd), M(0x1ce), M(0x1cf), -M(0x1d0), M(0x1d1), M(0x1d2), M(0x1d3), M(0x1d4), M(0x1d5), M(0x1d6), M(0x1d7), -M(0x1d8), M(0x1d9), M(0x1da), M(0x1db), M(0x1dc), M(0x1dd), M(0x1de), M(0x1df), -M(0x1e0), M(0x1e1), M(0x1e2), M(0x1e3), M(0x1e4), M(0x1e5), M(0x1e6), M(0x1e7), -M(0x1e8), M(0x1e9), M(0x1ea), M(0x1eb), M(0x1ec), M(0x1ed), M(0x1ee), M(0x1ef), -M(0x1f0), M(0x1f1), M(0x1f2), M(0x1f3), M(0x1f4), M(0x1f5), M(0x1f6), M(0x1f7), -M(0x1f8), M(0x1f9), M(0x1fa), M(0x1fb), M(0x1fc), M(0x1fd), M(0x1fe), M(0x1ff) -}; - -#ifdef MAKE_IDENTITY_MAP -/* -** "Identity" page map table. -** -** This just maps the first 4MB of physical memory. It is initialized -** in vm_init(). -** -** This could be converted into a 4GB map of 4MB pages by turning on -** the PDE_PS bit in each entry. -*/ - -// identity-map 4KB page #n -#define S(n) [n] = (pte_t) ( (TO_4KFRAME((n))) | (PTE_P|PTE_RW) ) - -const pte_t id_map[N_PTE] = { -S(0x000), S(0x001), S(0x002), S(0x003), S(0x004), S(0x005), S(0x006), S(0x007), -S(0x008), S(0x009), S(0x00a), S(0x00b), S(0x00c), S(0x00d), S(0x00e), S(0x00f), -S(0x010), S(0x011), S(0x012), S(0x013), S(0x014), S(0x015), S(0x016), S(0x017), -S(0x018), S(0x019), S(0x01a), S(0x01b), S(0x01c), S(0x01d), S(0x01e), S(0x01f), -S(0x020), S(0x021), S(0x022), S(0x023), S(0x024), S(0x025), S(0x026), S(0x027), -S(0x028), S(0x029), S(0x02a), S(0x02b), S(0x02c), S(0x02d), S(0x02e), S(0x02f), -S(0x030), S(0x031), S(0x032), S(0x033), S(0x034), S(0x035), S(0x036), S(0x037), -S(0x038), S(0x039), S(0x03a), S(0x03b), S(0x03c), S(0x03d), S(0x03e), S(0x03f), -S(0x040), S(0x041), S(0x042), S(0x043), S(0x044), S(0x045), S(0x046), S(0x047), -S(0x048), S(0x049), S(0x04a), S(0x04b), S(0x04c), S(0x04d), S(0x04e), S(0x04f), -S(0x050), S(0x051), S(0x052), S(0x053), S(0x054), S(0x055), S(0x056), S(0x057), -S(0x058), S(0x059), S(0x05a), S(0x05b), S(0x05c), S(0x05d), S(0x05e), S(0x05f), -S(0x060), S(0x061), S(0x062), S(0x063), S(0x064), S(0x065), S(0x066), S(0x067), -S(0x068), S(0x069), S(0x06a), S(0x06b), S(0x06c), S(0x06d), S(0x06e), S(0x06f), -S(0x070), S(0x071), S(0x072), S(0x073), S(0x074), S(0x075), S(0x076), S(0x077), -S(0x078), S(0x079), S(0x07a), S(0x07b), S(0x07c), S(0x07d), S(0x07e), S(0x07f), -S(0x080), S(0x081), S(0x082), S(0x083), S(0x084), S(0x085), S(0x086), S(0x087), -S(0x088), S(0x089), S(0x08a), S(0x08b), S(0x08c), S(0x08d), S(0x08e), S(0x08f), -S(0x090), S(0x091), S(0x092), S(0x093), S(0x094), S(0x095), S(0x096), S(0x097), -S(0x098), S(0x099), S(0x09a), S(0x09b), S(0x09c), S(0x09d), S(0x09e), S(0x09f), -S(0x0a0), S(0x0a1), S(0x0a2), S(0x0a3), S(0x0a4), S(0x0a5), S(0x0a6), S(0x0a7), -S(0x0a8), S(0x0a9), S(0x0aa), S(0x0ab), S(0x0ac), S(0x0ad), S(0x0ae), S(0x0af), -S(0x0b0), S(0x0b1), S(0x0b2), S(0x0b3), S(0x0b4), S(0x0b5), S(0x0b6), S(0x0b7), -S(0x0b8), S(0x0b9), S(0x0ba), S(0x0bb), S(0x0bc), S(0x0bd), S(0x0be), S(0x0bf), -S(0x0c0), S(0x0c1), S(0x0c2), S(0x0c3), S(0x0c4), S(0x0c5), S(0x0c6), S(0x0c7), -S(0x0c8), S(0x0c9), S(0x0ca), S(0x0cb), S(0x0cc), S(0x0cd), S(0x0ce), S(0x0cf), -S(0x0d0), S(0x0d1), S(0x0d2), S(0x0d3), S(0x0d4), S(0x0d5), S(0x0d6), S(0x0d7), -S(0x0d8), S(0x0d9), S(0x0da), S(0x0db), S(0x0dc), S(0x0dd), S(0x0de), S(0x0df), -S(0x0e0), S(0x0e1), S(0x0e2), S(0x0e3), S(0x0e4), S(0x0e5), S(0x0e6), S(0x0e7), -S(0x0e8), S(0x0e9), S(0x0ea), S(0x0eb), S(0x0ec), S(0x0ed), S(0x0ee), S(0x0ef), -S(0x0f0), S(0x0f1), S(0x0f2), S(0x0f3), S(0x0f4), S(0x0f5), S(0x0f6), S(0x0f7), -S(0x0f8), S(0x0f9), S(0x0fa), S(0x0fb), S(0x0fc), S(0x0fd), S(0x0fe), S(0x0ff), -S(0x100), S(0x101), S(0x102), S(0x103), S(0x104), S(0x105), S(0x106), S(0x107), -S(0x108), S(0x109), S(0x10a), S(0x10b), S(0x10c), S(0x10d), S(0x10e), S(0x10f), -S(0x110), S(0x111), S(0x112), S(0x113), S(0x114), S(0x115), S(0x116), S(0x117), -S(0x118), S(0x119), S(0x11a), S(0x11b), S(0x11c), S(0x11d), S(0x11e), S(0x11f), -S(0x120), S(0x121), S(0x122), S(0x123), S(0x124), S(0x125), S(0x126), S(0x127), -S(0x128), S(0x129), S(0x12a), S(0x12b), S(0x12c), S(0x12d), S(0x12e), S(0x12f), -S(0x130), S(0x131), S(0x132), S(0x133), S(0x134), S(0x135), S(0x136), S(0x137), -S(0x138), S(0x139), S(0x13a), S(0x13b), S(0x13c), S(0x13d), S(0x13e), S(0x13f), -S(0x140), S(0x141), S(0x142), S(0x143), S(0x144), S(0x145), S(0x146), S(0x147), -S(0x148), S(0x149), S(0x14a), S(0x14b), S(0x14c), S(0x14d), S(0x14e), S(0x14f), -S(0x150), S(0x151), S(0x152), S(0x153), S(0x154), S(0x155), S(0x156), S(0x157), -S(0x158), S(0x159), S(0x15a), S(0x15b), S(0x15c), S(0x15d), S(0x15e), S(0x15f), -S(0x160), S(0x161), S(0x162), S(0x163), S(0x164), S(0x165), S(0x166), S(0x167), -S(0x168), S(0x169), S(0x16a), S(0x16b), S(0x16c), S(0x16d), S(0x16e), S(0x16f), -S(0x170), S(0x171), S(0x172), S(0x173), S(0x174), S(0x175), S(0x176), S(0x177), -S(0x178), S(0x179), S(0x17a), S(0x17b), S(0x17c), S(0x17d), S(0x17e), S(0x17f), -S(0x180), S(0x181), S(0x182), S(0x183), S(0x184), S(0x185), S(0x186), S(0x187), -S(0x188), S(0x189), S(0x18a), S(0x18b), S(0x18c), S(0x18d), S(0x18e), S(0x18f), -S(0x190), S(0x191), S(0x192), S(0x193), S(0x194), S(0x195), S(0x196), S(0x197), -S(0x198), S(0x199), S(0x19a), S(0x19b), S(0x19c), S(0x19d), S(0x19e), S(0x19f), -S(0x1a0), S(0x1a1), S(0x1a2), S(0x1a3), S(0x1a4), S(0x1a5), S(0x1a6), S(0x1a7), -S(0x1a8), S(0x1a9), S(0x1aa), S(0x1ab), S(0x1ac), S(0x1ad), S(0x1ae), S(0x1af), -S(0x1b0), S(0x1b1), S(0x1b2), S(0x1b3), S(0x1b4), S(0x1b5), S(0x1b6), S(0x1b7), -S(0x1b8), S(0x1b9), S(0x1ba), S(0x1bb), S(0x1bc), S(0x1bd), S(0x1be), S(0x1bf), -S(0x1c0), S(0x1c1), S(0x1c2), S(0x1c3), S(0x1c4), S(0x1c5), S(0x1c6), S(0x1c7), -S(0x1c8), S(0x1c9), S(0x1ca), S(0x1cb), S(0x1cc), S(0x1cd), S(0x1ce), S(0x1cf), -S(0x1d0), S(0x1d1), S(0x1d2), S(0x1d3), S(0x1d4), S(0x1d5), S(0x1d6), S(0x1d7), -S(0x1d8), S(0x1d9), S(0x1da), S(0x1db), S(0x1dc), S(0x1dd), S(0x1de), S(0x1df), -S(0x1e0), S(0x1e1), S(0x1e2), S(0x1e3), S(0x1e4), S(0x1e5), S(0x1e6), S(0x1e7), -S(0x1e8), S(0x1e9), S(0x1ea), S(0x1eb), S(0x1ec), S(0x1ed), S(0x1ee), S(0x1ef), -S(0x1f0), S(0x1f1), S(0x1f2), S(0x1f3), S(0x1f4), S(0x1f5), S(0x1f6), S(0x1f7), -S(0x1f8), S(0x1f9), S(0x1fa), S(0x1fb), S(0x1fc), S(0x1fd), S(0x1fe), S(0x1ff), -S(0x200), S(0x201), S(0x202), S(0x203), S(0x204), S(0x205), S(0x206), S(0x207), -S(0x208), S(0x209), S(0x20a), S(0x20b), S(0x20c), S(0x20d), S(0x20e), S(0x20f), -S(0x210), S(0x211), S(0x212), S(0x213), S(0x214), S(0x215), S(0x216), S(0x217), -S(0x218), S(0x219), S(0x21a), S(0x21b), S(0x21c), S(0x21d), S(0x21e), S(0x21f), -S(0x220), S(0x221), S(0x222), S(0x223), S(0x224), S(0x225), S(0x226), S(0x227), -S(0x228), S(0x229), S(0x22a), S(0x22b), S(0x22c), S(0x22d), S(0x22e), S(0x22f), -S(0x230), S(0x231), S(0x232), S(0x233), S(0x234), S(0x235), S(0x236), S(0x237), -S(0x238), S(0x239), S(0x23a), S(0x23b), S(0x23c), S(0x23d), S(0x23e), S(0x23f), -S(0x240), S(0x241), S(0x242), S(0x243), S(0x244), S(0x245), S(0x246), S(0x247), -S(0x248), S(0x249), S(0x24a), S(0x24b), S(0x24c), S(0x24d), S(0x24e), S(0x24f), -S(0x250), S(0x251), S(0x252), S(0x253), S(0x254), S(0x255), S(0x256), S(0x257), -S(0x258), S(0x259), S(0x25a), S(0x25b), S(0x25c), S(0x25d), S(0x25e), S(0x25f), -S(0x260), S(0x261), S(0x262), S(0x263), S(0x264), S(0x265), S(0x266), S(0x267), -S(0x268), S(0x269), S(0x26a), S(0x26b), S(0x26c), S(0x26d), S(0x26e), S(0x26f), -S(0x270), S(0x271), S(0x272), S(0x273), S(0x274), S(0x275), S(0x276), S(0x277), -S(0x278), S(0x279), S(0x27a), S(0x27b), S(0x27c), S(0x27d), S(0x27e), S(0x27f), -S(0x280), S(0x281), S(0x282), S(0x283), S(0x284), S(0x285), S(0x286), S(0x287), -S(0x288), S(0x289), S(0x28a), S(0x28b), S(0x28c), S(0x28d), S(0x28e), S(0x28f), -S(0x290), S(0x291), S(0x292), S(0x293), S(0x294), S(0x295), S(0x296), S(0x297), -S(0x298), S(0x299), S(0x29a), S(0x29b), S(0x29c), S(0x29d), S(0x29e), S(0x29f), -S(0x2a0), S(0x2a1), S(0x2a2), S(0x2a3), S(0x2a4), S(0x2a5), S(0x2a6), S(0x2a7), -S(0x2a8), S(0x2a9), S(0x2aa), S(0x2ab), S(0x2ac), S(0x2ad), S(0x2ae), S(0x2af), -S(0x2b0), S(0x2b1), S(0x2b2), S(0x2b3), S(0x2b4), S(0x2b5), S(0x2b6), S(0x2b7), -S(0x2b8), S(0x2b9), S(0x2ba), S(0x2bb), S(0x2bc), S(0x2bd), S(0x2be), S(0x2bf), -S(0x2c0), S(0x2c1), S(0x2c2), S(0x2c3), S(0x2c4), S(0x2c5), S(0x2c6), S(0x2c7), -S(0x2c8), S(0x2c9), S(0x2ca), S(0x2cb), S(0x2cc), S(0x2cd), S(0x2ce), S(0x2cf), -S(0x2d0), S(0x2d1), S(0x2d2), S(0x2d3), S(0x2d4), S(0x2d5), S(0x2d6), S(0x2d7), -S(0x2d8), S(0x2d9), S(0x2da), S(0x2db), S(0x2dc), S(0x2dd), S(0x2de), S(0x2df), -S(0x2e0), S(0x2e1), S(0x2e2), S(0x2e3), S(0x2e4), S(0x2e5), S(0x2e6), S(0x2e7), -S(0x2e8), S(0x2e9), S(0x2ea), S(0x2eb), S(0x2ec), S(0x2ed), S(0x2ee), S(0x2ef), -S(0x2f0), S(0x2f1), S(0x2f2), S(0x2f3), S(0x2f4), S(0x2f5), S(0x2f6), S(0x2f7), -S(0x2f8), S(0x2f9), S(0x2fa), S(0x2fb), S(0x2fc), S(0x2fd), S(0x2fe), S(0x2ff), -S(0x300), S(0x301), S(0x302), S(0x303), S(0x304), S(0x305), S(0x306), S(0x307), -S(0x308), S(0x309), S(0x30a), S(0x30b), S(0x30c), S(0x30d), S(0x30e), S(0x30f), -S(0x310), S(0x311), S(0x312), S(0x313), S(0x314), S(0x315), S(0x316), S(0x317), -S(0x318), S(0x319), S(0x31a), S(0x31b), S(0x31c), S(0x31d), S(0x31e), S(0x31f), -S(0x320), S(0x321), S(0x322), S(0x323), S(0x324), S(0x325), S(0x326), S(0x327), -S(0x328), S(0x329), S(0x32a), S(0x32b), S(0x32c), S(0x32d), S(0x32e), S(0x32f), -S(0x330), S(0x331), S(0x332), S(0x333), S(0x334), S(0x335), S(0x336), S(0x337), -S(0x338), S(0x339), S(0x33a), S(0x33b), S(0x33c), S(0x33d), S(0x33e), S(0x33f), -S(0x340), S(0x341), S(0x342), S(0x343), S(0x344), S(0x345), S(0x346), S(0x347), -S(0x348), S(0x349), S(0x34a), S(0x34b), S(0x34c), S(0x34d), S(0x34e), S(0x34f), -S(0x350), S(0x351), S(0x352), S(0x353), S(0x354), S(0x355), S(0x356), S(0x357), -S(0x358), S(0x359), S(0x35a), S(0x35b), S(0x35c), S(0x35d), S(0x35e), S(0x35f), -S(0x360), S(0x361), S(0x362), S(0x363), S(0x364), S(0x365), S(0x366), S(0x367), -S(0x368), S(0x369), S(0x36a), S(0x36b), S(0x36c), S(0x36d), S(0x36e), S(0x36f), -S(0x370), S(0x371), S(0x372), S(0x373), S(0x374), S(0x375), S(0x376), S(0x377), -S(0x378), S(0x379), S(0x37a), S(0x37b), S(0x37c), S(0x37d), S(0x37e), S(0x37f), -S(0x380), S(0x381), S(0x382), S(0x383), S(0x384), S(0x385), S(0x386), S(0x387), -S(0x388), S(0x389), S(0x38a), S(0x38b), S(0x38c), S(0x38d), S(0x38e), S(0x38f), -S(0x390), S(0x391), S(0x392), S(0x393), S(0x394), S(0x395), S(0x396), S(0x397), -S(0x398), S(0x399), S(0x39a), S(0x39b), S(0x39c), S(0x39d), S(0x39e), S(0x39f), -S(0x3a0), S(0x3a1), S(0x3a2), S(0x3a3), S(0x3a4), S(0x3a5), S(0x3a6), S(0x3a7), -S(0x3a8), S(0x3a9), S(0x3aa), S(0x3ab), S(0x3ac), S(0x3ad), S(0x3ae), S(0x3af), -S(0x3b0), S(0x3b1), S(0x3b2), S(0x3b3), S(0x3b4), S(0x3b5), S(0x3b6), S(0x3b7), -S(0x3b8), S(0x3b9), S(0x3ba), S(0x3bb), S(0x3bc), S(0x3bd), S(0x3be), S(0x3bf), -S(0x3c0), S(0x3c1), S(0x3c2), S(0x3c3), S(0x3c4), S(0x3c5), S(0x3c6), S(0x3c7), -S(0x3c8), S(0x3c9), S(0x3ca), S(0x3cb), S(0x3cc), S(0x3cd), S(0x3ce), S(0x3cf), -S(0x3d0), S(0x3d1), S(0x3d2), S(0x3d3), S(0x3d4), S(0x3d5), S(0x3d6), S(0x3d7), -S(0x3d8), S(0x3d9), S(0x3da), S(0x3db), S(0x3dc), S(0x3dd), S(0x3de), S(0x3df), -S(0x3e0), S(0x3e1), S(0x3e2), S(0x3e3), S(0x3e4), S(0x3e5), S(0x3e6), S(0x3e7), -S(0x3e8), S(0x3e9), S(0x3ea), S(0x3eb), S(0x3ec), S(0x3ed), S(0x3ee), S(0x3ef), -S(0x3f0), S(0x3f1), S(0x3f2), S(0x3f3), S(0x3f4), S(0x3f5), S(0x3f6), S(0x3f7), -S(0x3f8), S(0x3f9), S(0x3fa), S(0x3fb), S(0x3fc), S(0x3fd), S(0x3fe), S(0x3ff) -}; -#endif /* MAKE_IDENTITY_MAP */ - -/* -** Kernel address mappings, present in every page table -*/ -const mapping_t kmap[] = { - // va pa_start pa_end perms - { KERN_BASE, 0, EXT_BASE, PDE_RW }, - { KERN_VLINK, KERN_PLINK, V2P(_data), 0 }, - { (uint32_t) _data, V2P(_data), KERN_BASE, PDE_RW }, - { DEV_BASE, DEV_BASE, 0, PDE_RW } -}; -const uint_t n_kmap = sizeof(kmap) / sizeof(kmap[0]); -- cgit v1.2.3-freya