mirror of
https://github.com/kenshineto/kern.git
synced 2025-04-10 12:37:26 +00:00
400 lines
7.9 KiB
C
400 lines
7.9 KiB
C
/**
|
|
** @file kernel.c
|
|
**
|
|
** @author CSCI-452 class of 20245
|
|
**
|
|
** @brief Kernel support routines
|
|
*/
|
|
|
|
#define KERNEL_SRC
|
|
|
|
#include <common.h>
|
|
#include <cio.h>
|
|
#include <clock.h>
|
|
#include <kmem.h>
|
|
#include <procs.h>
|
|
#include <sio.h>
|
|
#include <syscalls.h>
|
|
#include <user.h>
|
|
#include <userids.h>
|
|
#include <vm.h>
|
|
|
|
/*
|
|
** 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_putchar('\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, true);
|
|
pcb_queue_dump("W", waiting, true);
|
|
pcb_queue_dump("S", sleeping, true);
|
|
pcb_queue_dump("Z", zombie, true);
|
|
pcb_queue_dump("I", sioread, true);
|
|
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");
|
|
|
|
// report our configuration options
|
|
kreport(true);
|
|
cio_puts("-------------------------------\n");
|
|
|
|
delay(DELAY_2_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, true) == SUCCESS);
|
|
|
|
// send it on its merry way
|
|
schedule(init_pcb);
|
|
dispatch();
|
|
|
|
#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
|
|
|
|
/*
|
|
** 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);
|
|
|
|
#if 0
|
|
// produce a "system state" report
|
|
cio_puts( "System status: Queues " );
|
|
pcb_queue_dump( "R", ready, true );
|
|
pcb_queue_dump( "W", waiting, true );
|
|
pcb_queue_dump( "S", sleeping, true );
|
|
pcb_queue_dump( "Z", zombie, true );
|
|
pcb_queue_dump( "I", sioread, true );
|
|
ptable_dump_counts();
|
|
pcb_dump( "Current: ", current, true );
|
|
|
|
delay( DELAY_3_SEC );
|
|
|
|
vm_print( current->pdir, true, TwoLevel );
|
|
|
|
delay( DELAY_3_SEC );
|
|
#endif
|
|
|
|
return 0;
|
|
}
|