diff --git a/MP4/MP4_Sources.zip b/MP4/MP4_Sources.zip new file mode 100644 index 0000000..4045541 Binary files /dev/null and b/MP4/MP4_Sources.zip differ diff --git a/MP4/MP4_Sources/.DS_Store b/MP4/MP4_Sources/.DS_Store new file mode 100644 index 0000000..bc74e04 Binary files /dev/null and b/MP4/MP4_Sources/.DS_Store differ diff --git a/MP4/MP4_Sources/BIOS-bochs-latest b/MP4/MP4_Sources/BIOS-bochs-latest new file mode 100755 index 0000000..2cb4488 Binary files /dev/null and b/MP4/MP4_Sources/BIOS-bochs-latest differ diff --git a/MP4/MP4_Sources/README.TXT b/MP4/MP4_Sources/README.TXT new file mode 100755 index 0000000..3e9d7dd --- /dev/null +++ b/MP4/MP4_Sources/README.TXT @@ -0,0 +1,107 @@ +CSCE 410/611/613: MP4 -- README.TXT + +This file describes the content of this directory. +A file marked with (*) may be of some interest to the +student, and he/she may want to have a look at it. +A file marked with (**) is important for this MP, and the +student is strongly encouraged to study the contents of this file. + +BOCH Environment: +================= + +FILE: DESCRIPTION: + +BIOS-bochs-latest BIOS file. +VGABIOS-lgpl-latest BIOS file for the graphics system. +dev_kernel_grub.img Image file of the boot floopy. +bochsrc.bxrc Description file for the system. + Type 'bochs -f bochsrc.bxrc' to + start emulation. + +COMPILATION: +=========== + +FILE: DESCRIPTION: + +makefile (**) Makefile for Linux 64-bit environment. + Works with the provided linux image. + Type "make" to create the kernel. +linker.ld The linker script. + +OS COMPONENTS: +============= + +FILE: DESCRIPTION: + +start.asm (*) The bootloader starts code in this file, which in turn + jumps to the main entry in File "kernel.C". + +kernel.C (**) Main file, where the OS components are set up, and the + system gets going. + Define or undefine macro _TEST_PAGE_TABLE_ to + test either the page table implementation or the + implementation of the virtual memory allocator. + +assert.H/C Implements the "assert()" utility. +utils.H/C Various utilities (e.g. memcpy, strlen, + port I/O, etc.) +console.H/C Routines to print to the screen. + +machine.H (*) Definitions of some system constants and low-level + machine operations. + (Primarily memory sizes, register set, and + enable/disable interrupts) +gdt.H/C Global Descriptor Table. +gdt_low.asm Low-level GDT code, included in "start.asm". +idt.H/C Interrupt Descriptor Table. +idt_low.asm Low-level IDT code, included in "start.asm". +irq.H/C mapping of IRQ's into the IDT. +irq_low.asm Low-level IRQ stuff. (Primarily the interrupt service + routines and the routine stub that branches out to the + interrupt dispatcher in "interrupts.C". Included in + "start.asm". + +exceptions.H/C (*) The exception dispatcher. +interrupts.H/C The interrupt dispatcher. + +console.H/C Routines to print to the screen. + +simple_timer.H/C (*) Routines to control the periodic interval + timer. This is an example of an interrupt + handler. + +simple_keyboard.H/C(*) Routines to access the keyboard. Primarily as + way to wait until user presses key. + +machine_low.H/asm Various low-level x86 specific stuff. + +paging_low.H/asm (**) Low-level code to control the registers needed for + memory paging. + +page_table.H/C (**) Definition and empty implementation of a + page table manager. In addition to interface, + the .H file defines a few private members that + should guide the implementation. + +cont_frame_pool.H/C(**) Definition and empty implementation of a + physical frame memory manager that + supports contiguous + allocation. NOTE that the comments in + the implementation file give a recipe + of how to implement such a frame pool. + +vm_pool.H/C(**) Definition and implementation of a virtual + memory pool. + +UTILITIES: +========== + +FILE: DESCRIPTION: + +copykernel.sh (**) Simple script to copy the kernel onto + the floppy image. + The script mounts the floppy image, copies the kernel + image onto it, and then unmounts the floppy image again. + In rare cases the paths in the file may need to be + edited to make them reflect the student's environment. + diff --git a/MP4/MP4_Sources/VGABIOS-lgpl-latest b/MP4/MP4_Sources/VGABIOS-lgpl-latest new file mode 100755 index 0000000..646216a Binary files /dev/null and b/MP4/MP4_Sources/VGABIOS-lgpl-latest differ diff --git a/MP4/MP4_Sources/assert.C b/MP4/MP4_Sources/assert.C new file mode 100755 index 0000000..e85ae1d --- /dev/null +++ b/MP4/MP4_Sources/assert.C @@ -0,0 +1,45 @@ +/* + File: assert.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + + Date : 05/01/23 + + Implementation of the assert() function. + +*/ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "assert.H" + +#include "utils.H" +#include "console.H" + +/*--------------------------------------------------------------------------*/ +/* _assert() FUNCTION: gets called when assert() macro fails. */ +/*--------------------------------------------------------------------------*/ + +void _assert (const char* _file, const int _line, const char* _message ) { + /* Prints current file, line number, and failed assertion. */ + char temp[15]; + Console::puts("Assertion failed at file: "); + Console::puts(_file); + Console::puts(" line: "); + int2str(_line, temp); + Console::puts(temp); + Console::puts(" assertion: "); + Console::puts(_message); + Console::puts("\n"); + abort(); +}/* end _assert */ diff --git a/MP4/MP4_Sources/assert.H b/MP4/MP4_Sources/assert.H new file mode 100755 index 0000000..33c7a16 --- /dev/null +++ b/MP4/MP4_Sources/assert.H @@ -0,0 +1,56 @@ +/* + File: assert.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + + Date : 05/01/23 + + Header file for the "assert" macro. + + +*/ + +#ifndef __assert_H__ +#define __assert_H__ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "utils.H" + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* CONSTANTS */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* "ASSERT" MACRO */ +/*--------------------------------------------------------------------------*/ + +/* NOTE: The "assert" macros can be turned off by giving the -DNDEBUG + argument when compiling. */ + +#ifdef assert +# undef assert +#endif + +void _assert ( const char* _file, const int _line, const char* _message ); + +#ifdef NDEBUG +# define assert( m ) ( ( void ) 0 ) +#else +# define assert( m ) \ + if ( !(m) ) _assert( __FILE__, __LINE__, #m ); +#endif + +#endif diff --git a/MP4/MP4_Sources/bochsrc.bxrc b/MP4/MP4_Sources/bochsrc.bxrc new file mode 100755 index 0000000..310979c --- /dev/null +++ b/MP4/MP4_Sources/bochsrc.bxrc @@ -0,0 +1,48 @@ +############################################################### +# bochsrc.txt file for DLX Linux disk image. +############################################################### + +# how much memory the emulated machine will have +megs: 32 + +# filename of ROM images +romimage: file=BIOS-bochs-latest +vgaromimage: file=VGABIOS-lgpl-latest + +# what disk images will be used +floppya: 1_44=dev_kernel_grub.img, status=inserted +#floppyb: 1_44=floppyb.img, status=inserted + +# hard disk +#ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 +#ata0-master: type=disk, path="c.img", cylinders=306, heads=4, spt=17 +# choose the boot disk. +boot: floppy + +# default config interface is textconfig. +#config_interface: textconfig +#config_interface: wx + +#display_library: x +# other choices: win32 sdl wx carbon amigaos beos macintosh nogui rfb term svga + +# where do we send log messages? +log: bochsout.txt + +# disable the mouse +mouse: enabled=0 + +# enable key mapping, using US layout as default. +# +# NOTE: In Bochs 1.4, keyboard mapping is only 100% implemented on X windows. +# However, the key mapping tables are used in the paste function, so +# in the DLX Linux example I'm enabling keyboard_mapping so that paste +# will work. Cut&Paste is currently implemented on win32 and X windows only. + +#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-us.map +#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-fr.map +#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-de.map +#keyboard_mapping: enabled=1, map=$BXSHARE/keymaps/x11-pc-es.map + + +clock: sync=realtime, time0=946681200 # Sat Jan 1 00:00:00 2000 \ No newline at end of file diff --git a/MP4/MP4_Sources/console.C b/MP4/MP4_Sources/console.C new file mode 100755 index 0000000..2fc0899 --- /dev/null +++ b/MP4/MP4_Sources/console.C @@ -0,0 +1,213 @@ +/* + File: Console.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/02/2009 + +*/ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +#define CONSOLE_START_ADDRESS (unsigned short *)0xB8000 + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "console.H" + +#include "utils.H" +#include "machine.H" + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* CONSTANTS */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* FORWARDS */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* METHODS FOR CLASS C o n s o l e */ +/*--------------------------------------------------------------------------*/ + +/* -- GLOBAL VARIABLES -- */ + + int Console::attrib; /* background and foreground color */ + int Console::csr_x; /* position of cursor */ + int Console::csr_y; + unsigned short * Console::textmemptr; /* text pointer */ + +/* -- CONSTRUCTOR -- */ + +void Console::init(unsigned char _fore_color, + unsigned char _back_color) { + set_TextColor(_fore_color, _back_color); + csr_x = 0; + csr_y = 0; + textmemptr = CONSOLE_START_ADDRESS; + cls(); +} + + +void Console::scroll() { + + /* A blank is defined as a space... we need to give it + * backcolor too */ + unsigned blank = 0x20 | (attrib << 8); + + /* Row 25 is the end, this means we need to scroll up */ + if(csr_y >= 25) + { + /* Move the current text chunk that makes up the screen + * back in the buffer by a line */ + unsigned temp = csr_y - 25 + 1; + memcpy ((char*)textmemptr, (char*)(textmemptr + temp * 80), (25 - temp) * 80 * 2); + + /* Finally, we set the chunk of memory that occupies + * the last line of text to our 'blank' character */ + memsetw (textmemptr + (25 - temp) * 80, blank, 80); + csr_y = 25 - 1; + } +} + + +void Console::move_cursor() { + + /* The equation for finding the index in a linear + * chunk of memory can be represented by: + * Index = [(y * width) + x] */ + unsigned temp = csr_y * 80 + csr_x; + + /* This sends a command to indicies 14 and 15 in the + * Console Control Register of the VGA controller. These + * are the high and low bytes of the index that show + * where the hardware cursor is to be 'blinking'. To + * learn more, you should look up some VGA specific + * programming documents. A great start to graphics: + * http://www.brackeen.com/home/vga */ + Machine::outportb(0x3D4, (char)14); + //outportb(0x3D5, temp >> 8); + Machine::outportb(0x3D4, 15); + //outportb(0x3D5, (char)temp); +} + +/* Clear the screen */ +void Console::cls() { + + /* Again, we need the 'short' that will be used to + * represent a space with color */ + unsigned blank = 0x20 | (attrib << 8); + + /* Sets the entire screen to spaces in our current + * color */ + for(int i = 0; i < 25; i++) + memsetw (textmemptr + i * 80, blank, 80); + + /* Update out virtual cursor, and then move the + * hardware cursor */ + csr_x = 0; + csr_y = 0; + move_cursor(); +} + +/* Puts a single character on the screen */ +void Console::putch(const char _c){ + + + /* Handle a backspace, by moving the cursor back one space */ + if(_c == 0x08) + { + if(csr_x != 0) csr_x--; + } + /* Handles a tab by incrementing the cursor's x, but only + * to a point that will make it divisible by 8 */ + else if(_c == 0x09) + { + csr_x = (csr_x + 8) & ~(8 - 1); + } + /* Handles a 'Carriage Return', which simply brings the + * cursor back to the margin */ + else if(_c == '\r') + { + csr_x = 0; + } + /* We handle our newlines the way DOS and the BIOS do: we + * treat it as if a 'CR' was also there, so we bring the + * cursor to the margin and we increment the 'y' value */ + else if(_c == '\n') + { + csr_x = 0; + csr_y++; + } + /* Any character greater than and including a space, is a + * printable character. The equation for finding the index + * in a linear chunk of memory can be represented by: + * Index = [(y * width) + x] */ + else if(_c >= ' ') + { + unsigned short * where = textmemptr + (csr_y * 80 + csr_x); + *where = _c | (attrib << 8); /* Character AND attributes: color */ + csr_x++; + } + + /* If the cursor has reached the edge of the screen's width, we + * insert a new line in there */ + if(csr_x >= 80) + { + csr_x = 0; + csr_y++; + } + + /* Scroll the screen if needed, and finally move the cursor */ + scroll(); + move_cursor(); +} + +/* Uses the above routine to output a string... */ +void Console::puts(const char * _s) { + + for (int i = 0; i < strlen(_s); i++) { + putch(_s[i]); + } +} + +void Console::puti(const int _n) { + char foostr[15]; + + int2str(_n, foostr); + puts(foostr); +} + +void Console::putui(const unsigned int _n) { + char foostr[15]; + + uint2str(_n, foostr); + putch('<'); + puts(foostr); + putch('>'); +} + + +/* -- COLOR CONTROL -- */ +void Console::set_TextColor(const unsigned char _forecolor, + const unsigned char _backcolor) { + /* Top 4 bytes are the background, bottom 4 bytes + * are the foreground color */ + attrib = (_backcolor << 4) | (_forecolor & 0x0F); +} + diff --git a/MP4/MP4_Sources/console.H b/MP4/MP4_Sources/console.H new file mode 100755 index 0000000..aa24fda --- /dev/null +++ b/MP4/MP4_Sources/console.H @@ -0,0 +1,113 @@ +/* + File: Console.H + + Author : R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/02/12 + + The class Console encapsulates the output operations ot the console + screen. Since the console is initialized at the very beginning of the + boot-up of the operating system, when no memory management is available + yet, all functions and storage for the console are static. + + The console is initialized with an "init" function instead of a + constructor. (We don't want to deal with constructors that are called + before the "main()" function.) + + By making all functions static, we can access them across all object + files without having to declare a global Console object or pass pointers + to a locally declared object. + +*/ + +#ifndef _Console_H_ // include file only once +#define _Console_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none -- */ + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + +typedef enum { + BLACK = 0, + BLUE = 1, + GREEN = 2, + CYAN = 3, + RED = 4, + MAGENTA = 5, + BROWN = 6, + LIGHT_GREY = 7, + DARK_GREY = 8, + LIGHT_BLUE = 9, + LIGHT_GREEN = 10, + LIGHT_CYAN = 11, + LIGHT_RED = 12, + LIGHT_MAGENTA = 13, + LIGHT_BROWN = 14, + WHITE = 15 +} COLOR_CODE; + + +/*--------------------------------------------------------------------------*/ +/* FORWARDS */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* CLASS C o n s o l e */ +/*--------------------------------------------------------------------------*/ + +class Console { +private: + static int attrib; /* background and foreground color */ + static int csr_x; /* position of cursor */ + static int csr_y; + static unsigned short * textmemptr; /* text pointer */ +public: + + /* -- INITIALIZER (we have no constructor, there is no memory mgmt yet.) */ + static void init(unsigned char _fore_color = WHITE, + unsigned char _back_color = BLACK); + + static void scroll(); + + static void move_cursor(); + /* Update the hardware cursor. */ + + static void cls(); + /* Clear the screen. */ + + static void putch(const char _c); + /* Put a single character on the screen. */ + + static void puts(const char * _s); + /* Display a NULL-terminated string on the screen.*/ + + static void puti(const int _i); + /* Display a integer on the screen.*/ + + static void putui(const unsigned int _u); + /* Display a unsigned integer on the screen.*/ + + static void set_TextColor(unsigned char _fore_color, unsigned char _back_color); + /* Set the color of the foreground and background. */ + +}; + + +#endif + + diff --git a/MP4/MP4_Sources/cont_frame_pool.C b/MP4/MP4_Sources/cont_frame_pool.C new file mode 100644 index 0000000..f12329a --- /dev/null +++ b/MP4/MP4_Sources/cont_frame_pool.C @@ -0,0 +1,162 @@ +/* + File: ContFramePool.C + + Author: + Date : + + */ + +/*--------------------------------------------------------------------------*/ +/* + POSSIBLE IMPLEMENTATION + ----------------------- + + The class SimpleFramePool in file "simple_frame_pool.H/C" describes an + incomplete vanilla implementation of a frame pool that allocates + *single* frames at a time. Because it does allocate one frame at a time, + it does not guarantee that a sequence of frames is allocated contiguously. + This can cause problems. + + The class ContFramePool has the ability to allocate either single frames, + or sequences of contiguous frames. This affects how we manage the + free frames. In SimpleFramePool it is sufficient to maintain the free + frames. + In ContFramePool we need to maintain free *sequences* of frames. + + This can be done in many ways, ranging from extensions to bitmaps to + free-lists of frames etc. + + IMPLEMENTATION: + + One simple way to manage sequences of free frames is to add a minor + extension to the bitmap idea of SimpleFramePool: Instead of maintaining + whether a frame is FREE or ALLOCATED, which requires one bit per frame, + we maintain whether the frame is FREE, or ALLOCATED, or HEAD-OF-SEQUENCE. + The meaning of FREE is the same as in SimpleFramePool. + If a frame is marked as HEAD-OF-SEQUENCE, this means that it is allocated + and that it is the first such frame in a sequence of frames. Allocated + frames that are not first in a sequence are marked as ALLOCATED. + + NOTE: If we use this scheme to allocate only single frames, then all + frames are marked as either FREE or HEAD-OF-SEQUENCE. + + NOTE: In SimpleFramePool we needed only one bit to store the state of + each frame. Now we need two bits. In a first implementation you can choose + to use one char per frame. This will allow you to check for a given status + without having to do bit manipulations. Once you get this to work, + revisit the implementation and change it to using two bits. You will get + an efficiency penalty if you use one char (i.e., 8 bits) per frame when + two bits do the trick. + + DETAILED IMPLEMENTATION: + + How can we use the HEAD-OF-SEQUENCE state to implement a contiguous + allocator? Let's look a the individual functions: + + Constructor: Initialize all frames to FREE, except for any frames that you + need for the management of the frame pool, if any. + + get_frames(_n_frames): Traverse the "bitmap" of states and look for a + sequence of at least _n_frames entries that are FREE. If you find one, + mark the first one as HEAD-OF-SEQUENCE and the remaining _n_frames-1 as + ALLOCATED. + + release_frames(_first_frame_no): Check whether the first frame is marked as + HEAD-OF-SEQUENCE. If not, something went wrong. If it is, mark it as FREE. + Traverse the subsequent frames until you reach one that is FREE or + HEAD-OF-SEQUENCE. Until then, mark the frames that you traverse as FREE. + + mark_inaccessible(_base_frame_no, _n_frames): This is no different than + get_frames, without having to search for the free sequence. You tell the + allocator exactly which frame to mark as HEAD-OF-SEQUENCE and how many + frames after that to mark as ALLOCATED. + + needed_info_frames(_n_frames): This depends on how many bits you need + to store the state of each frame. If you use a char to represent the state + of a frame, then you need one info frame for each FRAME_SIZE frames. + + A WORD ABOUT RELEASE_FRAMES(): + + When we releae a frame, we only know its frame number. At the time + of a frame's release, we don't know necessarily which pool it came + from. Therefore, the function "release_frame" is static, i.e., + not associated with a particular frame pool. + + This problem is related to the lack of a so-called "placement delete" in + C++. For a discussion of this see Stroustrup's FAQ: + http://www.stroustrup.com/bs_faq2.html#placement-delete + + */ +/*--------------------------------------------------------------------------*/ + + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "cont_frame_pool.H" +#include "console.H" +#include "utils.H" +#include "assert.H" + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* CONSTANTS */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* FORWARDS */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* METHODS FOR CLASS C o n t F r a m e P o o l */ +/*--------------------------------------------------------------------------*/ + +ContFramePool::ContFramePool(unsigned long _base_frame_no, + unsigned long _nframes, + unsigned long _info_frame_no, + unsigned long _n_info_frames) +{ + // TODO: IMPLEMENTATION NEEEDED! + assert(false); +} + +unsigned long ContFramePool::get_frames(unsigned int _n_frames) +{ + // TODO: IMPLEMENTATION NEEEDED! + assert(false); +} + +void ContFramePool::mark_inaccessible(unsigned long _base_frame_no, + unsigned long _n_frames) +{ + // TODO: IMPLEMENTATION NEEEDED! + assert(false); +} + +void ContFramePool::release_frames(unsigned long _first_frame_no) +{ + // TODO: IMPLEMENTATION NEEEDED! + assert(false); +} + +unsigned long ContFramePool::needed_info_frames(unsigned long _n_frames) +{ + // TODO: IMPLEMENTATION NEEEDED! + assert(false); +} diff --git a/MP4/MP4_Sources/cont_frame_pool.H b/MP4/MP4_Sources/cont_frame_pool.H new file mode 100755 index 0000000..687a66f --- /dev/null +++ b/MP4/MP4_Sources/cont_frame_pool.H @@ -0,0 +1,119 @@ +/* + File: cont_frame_pool.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 17/02/04 + + Description: Management of the CONTIGUOUS Free-Frame Pool. + + As opposed to a non-contiguous free-frame pool, here we can allocate + a sequence of CONTIGUOUS frames. + + */ + +#ifndef _CONT_FRAME_POOL_H_ // include file only once +#define _CONT_FRAME_POOL_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "machine.H" + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* C o n t F r a m e P o o l */ +/*--------------------------------------------------------------------------*/ + +class ContFramePool { + +private: + /* -- DEFINE YOUR CONT FRAME POOL DATA STRUCTURE(s) HERE. */ + +public: + + // The frame size is the same as the page size, duh... + static const unsigned int FRAME_SIZE = Machine::PAGE_SIZE; + + ContFramePool(unsigned long _base_frame_no, + unsigned long _n_frames, + unsigned long _info_frame_no, + unsigned long _n_info_frames); + /* + Initializes the data structures needed for the management of this + frame pool. + _base_frame_no: Number of first frame managed by this frame pool. + _n_frames: Size, in frames, of this frame pool. + EXAMPLE: If _base_frame_no is 16 and _nframes is 4, this frame pool manages + physical frames numbered 16, 17, 18 and 19. + _info_frame_no: Number of the first frame that should be used to store the + management information for the frame pool. + NOTE: If _info_frame_no is 0, the frame pool is free to + choose any frames from the pool to store management information. + _n_info_frames: If _info_frame_no is 0, this argument specifies the + number of consecutive frames needed to store the management information + for the frame pool. + EXAMPLE: If _info_frame_no is 699 and _n_info_frames is 3, + then Frames 699, 700, and 701 are used to store the management information + for the frame pool. + NOTE: This function must be called before the paging system + is initialized. + */ + + unsigned long get_frames(unsigned int _n_frames); + /* + Allocates a number of contiguous frames from the frame pool. + _n_frames: Size of contiguous physical memory to allocate, + in number of frames. + If successful, returns the frame number of the first frame. + If fails, returns 0. + */ + + void mark_inaccessible(unsigned long _base_frame_no, + unsigned long _n_frames); + /* + Marks a contiguous area of physical memory, i.e., a contiguous + sequence of frames, as inaccessible. + _base_frame_no: Number of first frame to mark as inaccessible. + _n_frames: Number of contiguous frames to mark as inaccessible. + */ + + static void release_frames(unsigned long _first_frame_no); + /* + Releases a previously allocated contiguous sequence of frames + back to its frame pool. + The frame sequence is identified by the number of the first frame. + NOTE: This function is static because there may be more than one frame pool + defined in the system, and it is unclear which one this frame belongs to. + This function must first identify the correct frame pool and then call the frame + pool's release_frame function. + */ + + static unsigned long needed_info_frames(unsigned long _n_frames); + /* + Returns the number of frames needed to manage a frame pool of size _n_frames. + The number returned here depends on the implementation of the frame pool and + on the frame size. + EXAMPLE: For FRAME_SIZE = 4096 and a bitmap with a single bit per frame + (not appropriate for contiguous allocation) one would need one frame to manage a + frame pool with up to 8 * 4096 = 32k frames = 128MB of memory! + This function would therefore return the following value: + _n_frames / 32k + (_n_frames % 32k > 0 ? 1 : 0) (always round up!) + Other implementations need a different number of info frames. + The exact number is computed in this function.. + */ +}; +#endif diff --git a/MP4/MP4_Sources/copykernel.sh b/MP4/MP4_Sources/copykernel.sh new file mode 100755 index 0000000..afd49c3 --- /dev/null +++ b/MP4/MP4_Sources/copykernel.sh @@ -0,0 +1,5 @@ +# Replace "/mnt/floppy" with the whatever directory is appropriate. +sudo mount -o loop dev_kernel_grub.img /mnt/floppy +sudo cp kernel.bin /mnt/floppy +sleep 1s +sudo umount /mnt/floppy diff --git a/MP4/MP4_Sources/dev_kernel_grub.img b/MP4/MP4_Sources/dev_kernel_grub.img new file mode 100755 index 0000000..4108c01 Binary files /dev/null and b/MP4/MP4_Sources/dev_kernel_grub.img differ diff --git a/MP4/MP4_Sources/exceptions.C b/MP4/MP4_Sources/exceptions.C new file mode 100755 index 0000000..6192cb2 --- /dev/null +++ b/MP4/MP4_Sources/exceptions.C @@ -0,0 +1,183 @@ +/* + File: exceptions.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 12/09/05 + +*/ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "assert.H" +#include "utils.H" +#include "console.H" +#include "idt.H" +#include "exceptions.H" + +/*--------------------------------------------------------------------------*/ +/* EXTERNS */ +/*--------------------------------------------------------------------------*/ + +/* The low-level functions (defined in file 'IDT::low.s') that handle the + 32 Intel-defined CPU exceptions. + These functions are actually merely stubs that put the error code and + the exception code on the stack and then call a low-level function, which + in turn calls the exception dispatcher (defined in 'exceptions.H'). + Yes, there are more efficient ways to handle exceptions, but they require more + code replication. +*/ +extern "C" void isr0(); +extern "C" void isr1(); +extern "C" void isr2(); +extern "C" void isr3(); +extern "C" void isr4(); +extern "C" void isr5(); +extern "C" void isr6(); +extern "C" void isr7(); +extern "C" void isr8(); +extern "C" void isr9(); +extern "C" void isr10(); +extern "C" void isr11(); +extern "C" void isr12(); +extern "C" void isr13(); +extern "C" void isr14(); +extern "C" void isr15(); +extern "C" void isr16(); +extern "C" void isr17(); +extern "C" void isr18(); +extern "C" void isr19(); +extern "C" void isr20(); +extern "C" void isr21(); +extern "C" void isr22(); +extern "C" void isr23(); +extern "C" void isr24(); +extern "C" void isr25(); +extern "C" void isr26(); +extern "C" void isr27(); +extern "C" void isr28(); +extern "C" void isr29(); +extern "C" void isr30(); +extern "C" void isr31(); + +extern "C" void lowlevel_dispatch_exception(REGS * _r) { + ExceptionHandler::dispatch_exception(_r); +} + +/*--------------------------------------------------------------------------*/ +/* STATIC VARIABLES */ +/*--------------------------------------------------------------------------*/ + +ExceptionHandler * ExceptionHandler::handler_table[ExceptionHandler::EXCEPTION_TABLE_SIZE]; + +/*--------------------------------------------------------------------------*/ +/* EXPORTED EXCEPTION DISPATCHER FUNCTIONS */ +/*--------------------------------------------------------------------------*/ + +void ExceptionHandler::init_dispatcher() { + + /* -- INITIALIZE LOW-LEVEL EXCEPTION HANDLERS */ + /* Add any new ISRs to the IDT here using IDT::set_gate */ + IDT::set_gate( 0, (unsigned) isr0, 0x08, 0x8E); + IDT::set_gate( 1, (unsigned) isr1, 0x08, 0x8E); + IDT::set_gate( 2, (unsigned) isr2, 0x08, 0x8E); + IDT::set_gate( 3, (unsigned) isr3, 0x08, 0x8E); + IDT::set_gate( 4, (unsigned) isr4, 0x08, 0x8E); + IDT::set_gate( 5, (unsigned) isr5, 0x08, 0x8E); + IDT::set_gate( 6, (unsigned) isr6, 0x08, 0x8E); + IDT::set_gate( 7, (unsigned) isr7, 0x08, 0x8E); + + IDT::set_gate( 8, (unsigned) isr8, 0x08, 0x8E); + IDT::set_gate( 9, (unsigned) isr9, 0x08, 0x8E); + IDT::set_gate(10, (unsigned)isr10, 0x08, 0x8E); + IDT::set_gate(11, (unsigned)isr11, 0x08, 0x8E); + IDT::set_gate(12, (unsigned)isr12, 0x08, 0x8E); + IDT::set_gate(13, (unsigned)isr13, 0x08, 0x8E); + IDT::set_gate(14, (unsigned)isr14, 0x08, 0x8E); + IDT::set_gate(15, (unsigned)isr15, 0x08, 0x8E); + + IDT::set_gate(16, (unsigned)isr16, 0x08, 0x8E); + IDT::set_gate(17, (unsigned)isr17, 0x08, 0x8E); + IDT::set_gate(18, (unsigned)isr18, 0x08, 0x8E); + IDT::set_gate(19, (unsigned)isr19, 0x08, 0x8E); + IDT::set_gate(20, (unsigned)isr20, 0x08, 0x8E); + IDT::set_gate(21, (unsigned)isr21, 0x08, 0x8E); + IDT::set_gate(22, (unsigned)isr22, 0x08, 0x8E); + IDT::set_gate(23, (unsigned)isr23, 0x08, 0x8E); + + IDT::set_gate(24, (unsigned)isr24, 0x08, 0x8E); + IDT::set_gate(25, (unsigned)isr25, 0x08, 0x8E); + IDT::set_gate(26, (unsigned)isr26, 0x08, 0x8E); + IDT::set_gate(27, (unsigned)isr27, 0x08, 0x8E); + IDT::set_gate(28, (unsigned)isr28, 0x08, 0x8E); + IDT::set_gate(29, (unsigned)isr29, 0x08, 0x8E); + IDT::set_gate(30, (unsigned)isr30, 0x08, 0x8E); + IDT::set_gate(31, (unsigned)isr31, 0x08, 0x8E); + + /* -- INITIALIZE THE HIGH-LEVEL EXCEPTION HANDLER */ + int i; + for(i = 0; i < EXCEPTION_TABLE_SIZE; i++) { + handler_table[i] = NULL; + } +} + +void ExceptionHandler::dispatch_exception(REGS * _r) { + + /* -- EXCEPTION NUMBER */ + unsigned int exc_no = _r->int_no; + + Console::puts("EXCEPTION DISPATCHER: exc_no = "); + Console::putui(exc_no); + Console::puts("\n"); + + assert((exc_no >= 0) && (exc_no < EXCEPTION_TABLE_SIZE)); + + /* -- HAS A HANDLER BEEN REGISTERED FOR THIS EXCEPTION NO? */ + ExceptionHandler * handler = handler_table[exc_no]; + + if (!handler) { + /* --- NO HANDLER HAS BEEN REGISTERED. SIMPLY RETURN AN ERROR. */ + Console::puts("NO DEFAULT EXCEPTION HANDLER REGISTERED\n"); + abort(); + } + else { + /* -- HANDLE THE EXCEPTION OR INTERRUPT */ + handler->handle_exception(_r); + } + +} + +void ExceptionHandler::register_handler(unsigned int _isr_code, + ExceptionHandler * _handler) { + + assert(_isr_code >= 0 && _isr_code < EXCEPTION_TABLE_SIZE); + + handler_table[_isr_code] = _handler; + + Console::puts("Installed exception handler at ISR "); + Console::putui(_isr_code); + Console::puts("\n"); + +} + +void ExceptionHandler::deregister_handler(unsigned int _isr_code) { + assert(_isr_code >= 0 && _isr_code < EXCEPTION_TABLE_SIZE); + + handler_table[_isr_code] = NULL; + + Console::puts("UNINSTALLED exception handler at ISR "); + Console::putui(_isr_code); + Console::puts("\n"); + +} + + diff --git a/MP4/MP4_Sources/exceptions.H b/MP4/MP4_Sources/exceptions.H new file mode 100755 index 0000000..88a683b --- /dev/null +++ b/MP4/MP4_Sources/exceptions.H @@ -0,0 +1,86 @@ +/* + File: exceptions.h + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 12/09/05 + + Description: High-level exception handling. + + CPU exceptions are caught by low-level exception and interrupt + handler stubs, which all eventually cause the high-level + exception dispatcher to be called (see 'dispatch_exception() below). + + The dispatcher then looks up the appropriate exception handler + for the given exception, and calls it. + Specific exception handlers are installed by registering an exception handler + object of a class appropriately derived from class 'ExceptionHandler'. The + functionality of the exception handler is then implemented in function + 'handle_exception(REGS * _regs)'. + + +*/ + +#ifndef _exceptions_H_ // include file only once +#define _exceptions_H_ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "assert.H" +#include "machine.H" + +/*--------------------------------------------------------------------------*/ +/* E x c e p t i o n H a n d l e r */ +/*--------------------------------------------------------------------------*/ + +class ExceptionHandler { + + private: + + /* The Exception Handler Table */ + const static int EXCEPTION_TABLE_SIZE = 32; + static ExceptionHandler * handler_table[EXCEPTION_TABLE_SIZE]; + + public: + + /* -- POPULATE DISPATCHER TABLE */ + + static void register_handler(unsigned int _isr_code, + ExceptionHandler * _handler); + /* This function allows to install an exception handler for the given + exception code. The handler is a function pointer defined above. + Interrupt handlers are installed as exception handlers as well. + The 'register_interrupt' function uses irq2isr to map the IRQ + number to the code. */ + + static void deregister_handler(unsigned int _isr_code); + + /* -- DISPATCHER */ + static void init_dispatcher(); + /* This function is called to initialize the high-level exception handling. + No high level exception handlers are installed yet. If an exception + occurs at this point, the system displays an error message and + terminates. */ + + static void dispatch_exception(REGS * _r); + /* This is the high-level exception dispatcher. It dispatches the exception + to the previously registered exception handler. + This function is called by the low-level function + "lowlevel_dispatch_exception(REGS * _r)".*/ + + /* -- MANAGE INSTANCES OF EXCEPTION HANDLERS */ + + virtual void handle_exception(REGS * _regs) { + assert(false); // sometimes pure virtual functions dont link correctly. + } + /* Different exception handlers are derived from the base class ExceptionHandler + and their functionality is implemented in this function.*/ + +}; + +#endif + + diff --git a/MP4/MP4_Sources/gdt.C b/MP4/MP4_Sources/gdt.C new file mode 100755 index 0000000..4e1cb55 --- /dev/null +++ b/MP4/MP4_Sources/gdt.C @@ -0,0 +1,124 @@ +/* + File: gdt.C + + Date : 09/03/02 + + Description: Management of the Global Descriptor Table (GDT) + + The GDT describes memory access priviledges for memory segments. + + While the table is initialized by GRUB already, it may be a good idea to + do this again in the kernel code. + + For details see Section 5 of Brandon Friesen's Tutorial + on OS Kernel Development. + URL: http://www.osdever.net/bkerndev/Docs/title.htm + +* bkerndev - Bran's Kernel Development Tutorial +* By: Brandon F. (friesenb@gmail.com) +* Desc: Interrupt Descriptor Table management +* +* Notes: No warranty expressed or implied. Use at own risk. +*/ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +//#include "assert.H" +#include "utils.H" +#include "gdt.H" + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + +/* Defines a GDT entry. We use the 'packed' directive to prevent the + compiler from optimizing by aligning structure elements at word + boundaries. */ +struct gdt_entry { + unsigned short limit_low; + unsigned short base_low; + unsigned char base_middle; + unsigned char access; + unsigned char granularity; + unsigned char base_high; +} __attribute__((packed)); + +/* Special pointer that includes the limit: The max bytes + taken up by the GDT, minus 1. Again, this NEEDS to be packed. */ +struct gdt_ptr { + unsigned short limit; + unsigned int base; +} __attribute__((packed)); + +/*--------------------------------------------------------------------------*/ +/* VARIABLES */ +/*--------------------------------------------------------------------------*/ + +static struct gdt_entry gdt[GDT::SIZE]; +struct gdt_ptr gp; + +/*--------------------------------------------------------------------------*/ +/* EXTERNS */ +/*--------------------------------------------------------------------------*/ + +/* This function is defined in 'gdt_low.asm', which in turn is included in + 'start.asm'. */ +extern "C" void gdt_flush(); + +/*--------------------------------------------------------------------------*/ +/* EXPORTED FUNCTIONS */ +/*--------------------------------------------------------------------------*/ + +/* Use this function to set up an entry in the GDT. */ +void GDT::set_gate(int num, + unsigned long base, unsigned long limit, + unsigned char access, unsigned char gran) { + + /* Setup the descriptor base address */ + gdt[num].base_low = (base & 0xFFFF); + gdt[num].base_middle = (base >> 16) & 0xFF; + gdt[num].base_high = (base >> 24) & 0xFF; + + /* Setup the descriptor limits */ + gdt[num].limit_low = (limit & 0xFFFF); + gdt[num].granularity = ((limit >> 16) & 0x0F); + + /* Finally, set up the granularity and access flags */ + gdt[num].granularity |= (gran & 0xF0); + gdt[num].access = access; +} + + +/* Installs the GDT */ +void GDT::init() { + + /* Sets up the special GDT pointer. */ + gp.limit = (sizeof (struct gdt_entry) * SIZE) - 1; + gp.base = (unsigned int)&gdt; + + /* Our NULL descriptor */ + set_gate(0, 0, 0, 0, 0); + + /* The second entry is our Code Segment. The base address + is 0, the limit is 4GByte, it uses 4kB granularity, + uses 32-bit opcodes, and is a Code Segment descriptor. + Please check the GDT section in Bran's Kernel Development + tutorial to see exactly what each value means. */ + set_gate(1, 0, 0xFFFFFFFF, 0x9a, 0xCF); + + /* The third entry is our Data Segment. It's EXACTLY the + same as the code segment, but the descriptor type in + this entry's access byte says it's a Data Segment. */ + set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); + + /* Flush out the old GDT, and install the new changes. */ + gdt_flush(); +} diff --git a/MP4/MP4_Sources/gdt.H b/MP4/MP4_Sources/gdt.H new file mode 100755 index 0000000..ae9eb95 --- /dev/null +++ b/MP4/MP4_Sources/gdt.H @@ -0,0 +1,48 @@ +/* + File: gdt.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/03/02 + + Description: Management of the Global Descriptor Table (GDT) + + The GDT describes memory access priviledges for memory segments. + + While the table is initialized by GRUB already, it may be a good idea to + do this again in the kernel code. + + For details see Section 5 of Brandon Friesen's Tutotial + on OS Kernel Development. + URL: http://www.osdever.net/bkerndev/Docs/title.htm + +*/ + +#ifndef _GDT_H_ // include file only once +#define _GDT_H_ + +/*--------------------------------------------------------------------------*/ +/* GDT */ +/*--------------------------------------------------------------------------*/ + +class GDT { + +private: + + /* Use this function to set up an entry in the GDT. */ + static void set_gate(int num, + unsigned long base, unsigned long limit, + unsigned char access, unsigned char gran); + +public: + + static const unsigned int SIZE = 3; + + static void init(); + /* Initialize the GDT to have a null segment, a code segment, + and one data segment. */ + +}; + +#endif diff --git a/MP4/MP4_Sources/gdt_low.asm b/MP4/MP4_Sources/gdt_low.asm new file mode 100755 index 0000000..0b15df0 --- /dev/null +++ b/MP4/MP4_Sources/gdt_low.asm @@ -0,0 +1,18 @@ +; This will set up our new segment registers. We need to do +; something special in order to set CS. We do what is called a +; far jump. A jump that includes a segment as well as an offset. +; This is declared in C as 'extern void gdt_flush();' +global _gdt_flush ; Allows the C code to link to this. +extern _gp ; Says that '_gp' is in another file + +_gdt_flush: + lgdt[_gp] ; Load the GDT with our '_gp', a special pointer + mov ax, 0x10 ; 0x10 is the offset in the GDT to our data segment + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax +; mov ss, ax + jmp 0x08:flush2 ; 0x08 is the offset to our code segment: FAR JUMP! +flush2: + ret ; Returns back to the C code! diff --git a/MP4/MP4_Sources/idt.C b/MP4/MP4_Sources/idt.C new file mode 100755 index 0000000..76d93ca --- /dev/null +++ b/MP4/MP4_Sources/idt.C @@ -0,0 +1,108 @@ +/* + File: idt.C + + Date : 09/03/02 + +*/ + +/* Based largely on +* bkerndev - Bran's Kernel Development Tutorial +* By: Brandon F. (friesenb@gmail.com) +* Desc: Interrupt Descriptor Table management +* +* Notes: No warranty expressed or implied. Use at own risk. */ + + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +//#include "assert.H" +#include "utils.H" +#include "idt.H" +#include "console.H" + +/*--------------------------------------------------------------------------*/ +/* EXTERNS */ +/*--------------------------------------------------------------------------*/ + +/* Used to load our IDT, defined in 'idt_low.s' */ +extern "C" void idt_load(); + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + +struct idt_entry +{ + unsigned short base_lo; + unsigned short sel; + unsigned char always0; + unsigned char flags; + unsigned short base_hi; +} __attribute__((packed)); + +struct idt_ptr +{ + unsigned short limit; + unsigned int base; +} __attribute__((packed)); + + +/*--------------------------------------------------------------------------*/ +/* VARIABLES */ +/*--------------------------------------------------------------------------*/ + + +/* Declare an IDT of IDT_SIZE entries. We use only the first 32 + entries. If any undefined IDT entry is hit, it normally + cause an "Unhandled Interrupt" exception. Any descriptor + for which the 'presence' bit is cleared will generate an + "Unhandled Interrupt" exception. */ +struct idt_entry idt[IDT::SIZE]; +struct idt_ptr idtp; + +/*--------------------------------------------------------------------------*/ +/* HOOKING UP THE LOW-LEVEL EXCEPTION HANDLER TO EXCEPTIONDISPATCHER. */ +/*--------------------------------------------------------------------------*/ + +/* Use this function to set an entry in the IDT. */ +void IDT::set_gate(unsigned char num, unsigned long base, + unsigned short sel, unsigned char flags) { + + Console::puts("Installing handler in IDT position "); + Console::puti((int)num); + Console::puts("\n"); + + /* The interrupt routine's base address */ + idt[num].base_lo = (base & 0xFFFF); + idt[num].base_hi = (base >> 16) & 0xFFFF; + + /* The segment or 'selector' that this IDT entry will use + * is set here, along with any access flags */ + idt[num].sel = sel; + idt[num].always0 = 0; + idt[num].flags = flags; + +} + +/* Installs the IDT */ +void IDT::init() { + + /* Sets the special IDT pointer up. */ + idtp.limit = (sizeof (struct idt_entry) * 256) - 1; + idtp.base = (unsigned int)&idt; + + /* Clear out the entire IDT, initializing it to zeros. */ + memset(&idt, 0, sizeof(struct idt_entry) * 256); + + + /* Points the processor's internal register to the new IDT */ + idt_load(); +} diff --git a/MP4/MP4_Sources/idt.H b/MP4/MP4_Sources/idt.H new file mode 100755 index 0000000..ee0bd54 --- /dev/null +++ b/MP4/MP4_Sources/idt.H @@ -0,0 +1,57 @@ +/* + File: idt.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/03/02 + + Description: the Interrupt Description Table (IDT) + + The IDT contains pointer to low-level exception and interrupt handlers. + The way the exception handling is set up, all low-level handlers route + the exception to a single exception dispatcher, which in turn + calls a high-level exception dispatcher (see file 'exceptions.H'). + + For details see Section 6 of Brandon Friesen's Tutorial + on OS Kernel Development. + URL: http://www.osdever.net/bkerndev/Docs/title.htm + +*/ + +#ifndef _IDT_H_ // include file only once +#define _IDT_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +//#define IDT_SIZE 256 + +/*--------------------------------------------------------------------------*/ +/* Class IDT */ +/*--------------------------------------------------------------------------*/ + +class IDT { + + public: + + static const int SIZE = 256; + + static void init(); + /* Initialize the IDT, and fill the 32 first entries with pointers to handle + the 32 Intel-defined exceptions. After initializing the IDT, these exceptions + are routed to the exception dispatcher (see 'exceptions.H'). At this point, + no exception handlers are installed yet. + */ + + static void set_gate(unsigned char num, unsigned long base, + unsigned short sel, unsigned char flags); + /* Used to install a low-level exception handler in the IDT. For high-level + exception handlers, use the exception management framework defined in + file 'exceptions.H'. + */ + +}; + +#endif diff --git a/MP4/MP4_Sources/idt_low.asm b/MP4/MP4_Sources/idt_low.asm new file mode 100755 index 0000000..9312d38 --- /dev/null +++ b/MP4/MP4_Sources/idt_low.asm @@ -0,0 +1,279 @@ +; This is the exception de-multiplexer code. +; All low-level exception handling routines do the following: +; 1. disable interrupts +; 2. push error code on the stack (if the exception did not already +; do so! (Some exceptions automatically push the error code onto the +; stack.) +; 3. push the number of the exception onto the stack. +; 4. call the common interrupt service routine function, which then +; branches back out based on the exception number on the stack. +; (We do this because we don't want to replicate again and again the code +; to save the processor state.) +; + +; Here come the interrupt service routines for the 32 exceptions. +global _isr0 +global _isr1 +global _isr2 +global _isr3 +global _isr4 +global _isr5 +global _isr6 +global _isr7 +global _isr8 +global _isr9 +global _isr10 +global _isr11 +global _isr12 +global _isr13 +global _isr14 +global _isr15 +global _isr16 +global _isr17 +global _isr18 +global _isr19 +global _isr20 +global _isr21 +global _isr22 +global _isr23 +global _isr24 +global _isr25 +global _isr26 +global _isr27 +global _isr28 +global _isr29 +global _isr30 +global _isr31 + + +extern _promptA +extern _promptB +extern _promptC + + +; 0: Divide By Zero Exception +_isr0: + push byte 0 + push byte 0 + jmp isr_common_stub + +; 1: Debug Exception +_isr1: + push byte 0 + push byte 1 + jmp isr_common_stub + +; 2: Non Maskable Interrupt Exception +_isr2: + push byte 0 + push byte 2 + jmp isr_common_stub + +; 3: Int 3 Exception +_isr3: + push byte 0 + push byte 3 + jmp isr_common_stub + +; 4: INTO Exception +_isr4: + push byte 0 + push byte 4 + jmp isr_common_stub + +; 5: Out of Bounds Exception +_isr5: + push byte 0 + push byte 5 + jmp isr_common_stub + +; 6: Invalid Opcode Exception +_isr6: + push byte 0 + push byte 6 + jmp isr_common_stub + +; 7: Coprocessor Not Available Exception +_isr7: + push byte 0 + push byte 7 + jmp isr_common_stub + +; 8: Double Fault Exception (With Error Code!) +_isr8: + push byte 8 + jmp isr_common_stub + +; 9: Coprocessor Segment Overrun Exception +_isr9: + push byte 0 + push byte 9 + jmp isr_common_stub + +; 10: Bad TSS Exception (With Error Code!) +_isr10: + push byte 10 + jmp isr_common_stub + +; 11: Segment Not Present Exception (With Error Code!) +_isr11: + push byte 11 + jmp isr_common_stub + +; 12: Stack Fault Exception (With Error Code!) +_isr12: + push byte 12 + jmp isr_common_stub + +; 13: General Protection Fault Exception (With Error Code!) +_isr13: + push byte 13 + jmp isr_common_stub + +; 14: Page Fault Exception (With Error Code!) +_isr14: + push byte 14 + jmp isr_common_stub + +; 15: Reserved Exception +_isr15: + push byte 0 + push byte 15 + jmp isr_common_stub + +; 16: Floating Point Exception +_isr16: + push byte 0 + push byte 16 + jmp isr_common_stub + +; 17: Alignment Check Exception +_isr17: + push byte 0 + push byte 17 + jmp isr_common_stub + +; 18: Machine Check Exception +_isr18: + push byte 0 + push byte 18 + jmp isr_common_stub + +; 19: Reserved +_isr19: + push byte 0 + push byte 19 + jmp isr_common_stub + +; 20: Reserved +_isr20: + push byte 0 + push byte 20 + jmp isr_common_stub + +; 21: Reserved +_isr21: + push byte 0 + push byte 21 + jmp isr_common_stub + +; 22: Reserved +_isr22: + push byte 0 + push byte 22 + jmp isr_common_stub + +; 23: Reserved +_isr23: + push byte 0 + push byte 23 + jmp isr_common_stub + +; 24: Reserved +_isr24: + push byte 0 + push byte 24 + jmp isr_common_stub + +; 25: Reserved +_isr25: + push byte 0 + push byte 25 + jmp isr_common_stub + +; 26: Reserved +_isr26: + push byte 0 + push byte 26 + jmp isr_common_stub + +; 27: Reserved +_isr27: + push byte 0 + push byte 27 + jmp isr_common_stub + +; 28: Reserved +_isr28: + push byte 0 + push byte 28 + jmp isr_common_stub + +; 29: Reserved +_isr29: + push byte 0 + push byte 29 + jmp isr_common_stub + +; 30: Reserved +_isr30: + push byte 0 + push byte 30 + jmp isr_common_stub + +; 31: Reserved +_isr31: + push byte 0 + push byte 31 + jmp isr_common_stub + + + +; The common stub below will pun out into C. Let the +; assembler know that the function is defined in 'exceptions.C'. +extern _lowlevel_dispatch_exception + +; This is the common low-level stub for the exception handler. +; It saves the processor state, sets up for kernel mode +; segments, calls the C-level exception handler, +; and finally restores the stack frame. +isr_common_stub: + pusha + push ds + push es + push fs + push gs + + mov eax, esp ; Push us the stack + push eax + mov eax, _lowlevel_dispatch_exception + call eax ; A special call, preserves the 'eip' register + pop eax + pop gs + pop fs + pop es + pop ds + popa + add esp, 8 ; Ceans up the pushed error code and pushed ISR number + iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP1 + + + +; load the IDT defined in '_idtp' into the processor. +; This is declared in C as 'extern void _idt_load();' +; In turn, the variable '_idtp' is defined in file 'idt.C'. +global _idt_load +extern _idtp +_idt_load: + lidt [_idtp] + ret diff --git a/MP4/MP4_Sources/interrupts.C b/MP4/MP4_Sources/interrupts.C new file mode 100755 index 0000000..c67fba5 --- /dev/null +++ b/MP4/MP4_Sources/interrupts.C @@ -0,0 +1,172 @@ +/* + File: interrupts.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 12/09/05 + +*/ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* (none) */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "assert.H" +#include "utils.H" +#include "console.H" +#include "idt.H" +#include "irq.H" +#include "exceptions.H" +#include "interrupts.H" + +/*--------------------------------------------------------------------------*/ +/* EXTERNS */ +/*--------------------------------------------------------------------------*/ + +/* The low-level functions (defined in file 'irq_low.s') that handle the + 16 PIC-generated interrupts. + These functions are actually merely stubs that put the error code and + the exception code on the stack and then call a low-level function, which + in turn calls the interrupt dispatcher. + Yes, there are more efficient ways to handle exceptions, but they require more + code replication. +*/ + +extern "C" void irq0(); +extern "C" void irq1(); +extern "C" void irq2(); +extern "C" void irq3(); +extern "C" void irq4(); +extern "C" void irq5(); +extern "C" void irq6(); +extern "C" void irq7(); +extern "C" void irq8(); +extern "C" void irq9(); +extern "C" void irq10(); +extern "C" void irq11(); +extern "C" void irq12(); +extern "C" void irq13(); +extern "C" void irq14(); +extern "C" void irq15(); + +extern "C" void lowlevel_dispatch_interrupt(REGS * _r) { + InterruptHandler::dispatch_interrupt(_r); +} + +/*--------------------------------------------------------------------------*/ +/* LOCAL VARIABLES */ +/*--------------------------------------------------------------------------*/ + +InterruptHandler * InterruptHandler::handler_table[InterruptHandler::IRQ_TABLE_SIZE]; + +/*--------------------------------------------------------------------------*/ +/* EXPORTED INTERRUPT DISPATCHER FUNCTIONS */ +/*--------------------------------------------------------------------------*/ + +void InterruptHandler::init_dispatcher() { + + /* -- INITIALIZE LOW-LEVEL INTERRUPT HANDLERS */ + /* Add any new ISRs to the IDT here using IDT::set_gate */ + IDT::set_gate( 0+ IRQ_BASE, (unsigned) irq0, 0x08, 0x8E); + IDT::set_gate( 1+ IRQ_BASE, (unsigned) irq1, 0x08, 0x8E); + IDT::set_gate( 2+ IRQ_BASE, (unsigned) irq2, 0x08, 0x8E); + IDT::set_gate( 3+ IRQ_BASE, (unsigned) irq3, 0x08, 0x8E); + IDT::set_gate( 4+ IRQ_BASE, (unsigned) irq4, 0x08, 0x8E); + IDT::set_gate( 5+ IRQ_BASE, (unsigned) irq5, 0x08, 0x8E); + IDT::set_gate( 6+ IRQ_BASE, (unsigned) irq6, 0x08, 0x8E); + IDT::set_gate( 7+ IRQ_BASE, (unsigned) irq7, 0x08, 0x8E); + + IDT::set_gate( 8+ IRQ_BASE, (unsigned) irq8, 0x08, 0x8E); + IDT::set_gate( 9+ IRQ_BASE, (unsigned) irq9, 0x08, 0x8E); + IDT::set_gate(10+ IRQ_BASE, (unsigned)irq10, 0x08, 0x8E); + IDT::set_gate(11+ IRQ_BASE, (unsigned)irq11, 0x08, 0x8E); + IDT::set_gate(12+ IRQ_BASE, (unsigned)irq12, 0x08, 0x8E); + IDT::set_gate(13+ IRQ_BASE, (unsigned)irq13, 0x08, 0x8E); + IDT::set_gate(14+ IRQ_BASE, (unsigned)irq14, 0x08, 0x8E); + IDT::set_gate(15+ IRQ_BASE, (unsigned)irq15, 0x08, 0x8E); + + /* -- INITIALIZE THE HIGH-LEVEL INTERRUPT HANDLER */ + int i; + for(i = 0; i < IRQ_TABLE_SIZE; i++) { + handler_table[i] = NULL; + } +} + +bool InterruptHandler::generated_by_slave_PIC(unsigned int int_no) { + return int_no > 7; +} + +void InterruptHandler::dispatch_interrupt(REGS * _r) { + + /* -- INTERRUPT NUMBER */ + unsigned int int_no = _r->int_no - IRQ_BASE; + + //Console::puts("INTERRUPT DISPATCHER: int_no = "); + //Console::putui(int_no); + //Console::puts("\n"); + + assert((int_no >= 0) && (int_no < IRQ_TABLE_SIZE)); + + /* -- HAS A HANDLER BEEN REGISTERED FOR THIS INTERRUPT NO? */ + + InterruptHandler * handler = handler_table[int_no]; + + if (!handler) { + /* --- NO DEFAULT HANDLER HAS BEEN REGISTERED. SIMPLY RETURN AN ERROR. */ + Console::puts("INTERRUPT NO: "); + Console::puti(int_no); + Console::puts("\n"); + Console::puts("NO DEFAULT INTERRUPT HANDLER REGISTERED\n"); + // abort(); + } + else { + /* -- HANDLE THE INTERRUPT */ + handler->handle_interrupt(_r); + } + + /* This is an interrupt that was raised by the interrupt controller. We need + to send and end-of-interrupt (EOI) signal to the controller after the + interrupt has been handled. */ + + /* Check if the interrupt was generated by the slave interrupt controller. + If so, send an End-of-Interrupt (EOI) message to the slave controller. */ + + if (generated_by_slave_PIC(int_no)) { + Machine::outportb(0xA0, 0x20); + } + + /* Send an EOI message to the master interrupt controller. */ + Machine::outportb(0x20, 0x20); + +} + +void InterruptHandler::register_handler(unsigned int _irq_code, + InterruptHandler * _handler) { + assert(_irq_code >= 0 && _irq_code < IRQ_TABLE_SIZE); + + handler_table[_irq_code] = _handler; + + Console::puts("Installed interrupt handler at IRQ "); + Console::putui(_irq_code); + Console::puts("\n"); + +} + +void InterruptHandler::deregister_handler(unsigned int _irq_code) { + + assert(_irq_code >= 0 && _irq_code < IRQ_TABLE_SIZE); + + handler_table[_irq_code] = NULL; + + Console::puts("UNINSTALLED interrupt handler at IRQ "); + Console::putui(_irq_code); + Console::puts("\n"); + +} diff --git a/MP4/MP4_Sources/interrupts.H b/MP4/MP4_Sources/interrupts.H new file mode 100755 index 0000000..fd35216 --- /dev/null +++ b/MP4/MP4_Sources/interrupts.H @@ -0,0 +1,90 @@ +/* + File: interrupts.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 11/11/10 + + Description: High-level interrupt handling. + + CPU exceptions are caught by low-level exception and interrupt + handler stubs, which all eventually cause the high-level + exception dispatcher to be called (see 'dispatch_exception() below). + + The dispatcher then looks up the appropriate exception handler + for the given exception, and calls it. + Specific exception handlers are installed by registering an exception handler + object of a class appropriately derived from class 'ExceptionHandler'. The + functionality of the exception handler is then implemented in function + 'handle_exception(REGS * _regs)'. +*/ + +#ifndef _interrupts_H_ // include file only once +#define _interrupts_H_ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "assert.H" +#include "machine.H" +#include "exceptions.H" + +/*--------------------------------------------------------------------------*/ +/* I n t e r r u p t H a n d l e r */ +/*--------------------------------------------------------------------------*/ + +class InterruptHandler { + + private: + + /* The Interrupt Handler Table */ + const static int IRQ_TABLE_SIZE = 16; + const static int IRQ_BASE = 32; + + static InterruptHandler * handler_table[IRQ_TABLE_SIZE]; + + static bool generated_by_slave_PIC(unsigned int int_no); + /* Has the particular interupt been generated by the Slave PIC? */ + + public: + + /* -- POPULATE INTERRUPT-DISPATCHER TABLE */ + static void register_handler(unsigned int _irq_code, + InterruptHandler * _handler); + /* This function allows to install an interrupt handler for the given + Interrupt code. The handler is a function pointer defined above. + Interrupt handlers are installed as Interrupt handlers as well. + The 'register_interrupt' function uses irq2isr to map the IRQ + number to the code. */ + + static void deregister_handler(unsigned int _irq_code); + + /* -- INITIALIZER */ + static void init_dispatcher(); + /* This function is called to initialize the high-level interrupt + handling. No high level interrupt handlers are installed yet. + If an interrupt occurs at this point, the system displays an error + message and terminates. */ + + static void dispatch_interrupt(REGS * _r); + /* This is the high-level interrupt dispatcher. It dispatches the interrupt + to the previously registered interrupt handler. + This function is called by the low-level function + "lowlevel_dispatch_interrupt(REGS * _r)".*/ + + /* -- MANAGE INSTANCES OF INTERRUPT HANDLERS */ + + virtual void handle_interrupt(REGS * _regs) { + assert(false); // sometimes pure virtual functions don't link correctly. + } + /* Different interrupt handlers are derived from the base class + InterruptHandler, and their functionality is implemented in + this function.*/ + +}; + +#endif + + diff --git a/MP4/MP4_Sources/irq.C b/MP4/MP4_Sources/irq.C new file mode 100755 index 0000000..44f27c0 --- /dev/null +++ b/MP4/MP4_Sources/irq.C @@ -0,0 +1,60 @@ +/* + File: irq.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/03/05 + + This code borrows heavily from Brandon Friesen's the code in Brandon + Friesen's OS Development Tutorial. +*/ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +#define IRQ_BASE 32 + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "machine.H" +#include "irq.H" + +/*--------------------------------------------------------------------------*/ +/* LOCAL FUNCTIONS . */ +/*--------------------------------------------------------------------------*/ + +/* Normally, IRQs 0 to 7 are mapped to IDT entries 8 to 15. + For a variety of reasons it is a good idea to re-map these + IRQs to different locations + We send a sequence of commands to the PICs - 8259's - in order + to have IRQ0 to IRQ15 be remapped to IDT entries 32 to 47. +*/ +static void irq_remap() +{ + Machine::outportb(0x20, 0x11); + Machine::outportb(0xA0, 0x11); + Machine::outportb(0x21, 0x20); + Machine::outportb(0xA1, 0x28); + Machine::outportb(0x21, 0x04); + Machine::outportb(0xA1, 0x02); + Machine::outportb(0x21, 0x01); + Machine::outportb(0xA1, 0x01); + Machine::outportb(0x21, 0x0); + Machine::outportb(0xA1, 0x0); +} + + +/*--------------------------------------------------------------------------*/ +/* EXPORTED FUNCTIONS . */ +/*--------------------------------------------------------------------------*/ + +void IRQ::init() { + + irq_remap(); + + +} diff --git a/MP4/MP4_Sources/irq.H b/MP4/MP4_Sources/irq.H new file mode 100755 index 0000000..0072f9b --- /dev/null +++ b/MP4/MP4_Sources/irq.H @@ -0,0 +1,38 @@ +/* + File: irq.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/03/02 + + Description: Interrupt Table (IRQ) + + For details see Section 7 of Brandon Friesen's Tutorial + on OS Kernel Development. + URL: http://www.osdever.net/bkerndev/Docs/title.htm + +*/ + +#ifndef _IRQ_H_ // include file only once +#define _IRQ_H_ + + +/*--------------------------------------------------------------------------*/ +/* */ +/*--------------------------------------------------------------------------*/ + +class IRQ { + +public: + + static void init(); + /* Initialize the IRQ handlers, i.e. fill 16 entries with pointers to handle + the PIC generated interrupts. These interrupts are routed to the exception + dispatcher (see 'exceptions.H'). At this point, no exception handlers are + installed yet. + */ + +}; + +#endif diff --git a/MP4/MP4_Sources/irq_low.asm b/MP4/MP4_Sources/irq_low.asm new file mode 100755 index 0000000..e94271c --- /dev/null +++ b/MP4/MP4_Sources/irq_low.asm @@ -0,0 +1,136 @@ +global _irq0 +global _irq1 +global _irq2 +global _irq3 +global _irq4 +global _irq5 +global _irq6 +global _irq7 +global _irq8 +global _irq9 +global _irq10 +global _irq11 +global _irq12 +global _irq13 +global _irq14 +global _irq15 + +; 32: IRQ0 +_irq0: + push byte 0 + push byte 32 + jmp irq_common_stub + +; 33: IRQ1 +_irq1: + push byte 0 + push byte 33 + jmp irq_common_stub + +; 34: IRQ2 +_irq2: + push byte 0 + push byte 34 + jmp irq_common_stub + +; 35: IRQ3 +_irq3: + push byte 0 + push byte 35 + jmp irq_common_stub + +; 36: IRQ4 +_irq4: + push byte 0 + push byte 36 + jmp irq_common_stub + +; 37: IRQ5 +_irq5: + push byte 0 + push byte 37 + jmp irq_common_stub + +; 38: IRQ6 +_irq6: + push byte 0 + push byte 38 + jmp irq_common_stub + +; 39: IRQ7 +_irq7: + push byte 0 + push byte 39 + jmp irq_common_stub + +; 40: IRQ8 +_irq8: + push byte 0 + push byte 40 + jmp irq_common_stub + +; 41: IRQ9 +_irq9: + push byte 0 + push byte 41 + jmp irq_common_stub + +; 42: IRQ10 +_irq10: + push byte 0 + push byte 42 + jmp irq_common_stub + +; 43: IRQ11 +_irq11: + push byte 0 + push byte 43 + jmp irq_common_stub + +; 44: IRQ12 +_irq12: + push byte 0 + push byte 44 + jmp irq_common_stub + +; 45: IRQ13 +_irq13: + push byte 0 + push byte 45 + jmp irq_common_stub + +; 46: IRQ14 +_irq14: + push byte 0 + push byte 46 + jmp irq_common_stub + +; 47: IRQ15 +_irq15: + push byte 0 + push byte 47 + jmp irq_common_stub + +extern _lowlevel_dispatch_interrupt + +irq_common_stub: + pusha + push ds + push es + push fs + push gs + + mov eax, esp + + push eax + mov eax, _lowlevel_dispatch_interrupt + call eax + pop eax + + pop gs + pop fs + pop es + pop ds + popa + add esp, 8 + iret diff --git a/MP4/MP4_Sources/kernel.C b/MP4/MP4_Sources/kernel.C new file mode 100755 index 0000000..d982ec9 --- /dev/null +++ b/MP4/MP4_Sources/kernel.C @@ -0,0 +1,299 @@ +/* + File: kernel.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 2017/06/20 + + + This file has the main entry point to the operating system. + +*/ + + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +#define GB * (0x1 << 30) +#define MB * (0x1 << 20) +#define KB * (0x1 << 10) +#define KERNEL_POOL_START_FRAME ((2 MB) / Machine::PAGE_SIZE) +#define KERNEL_POOL_SIZE ((2 MB) / Machine::PAGE_SIZE) +#define PROCESS_POOL_START_FRAME ((4 MB) / Machine::PAGE_SIZE) +#define PROCESS_POOL_SIZE ((28 MB) / Machine::PAGE_SIZE) +/* definition of the kernel and process memory pools */ + +#define MEM_HOLE_START_FRAME ((15 MB) / Machine::PAGE_SIZE) +#define MEM_HOLE_SIZE ((1 MB) / Machine::PAGE_SIZE) +/* we have a 1 MB hole in physical memory starting at address 15 MB */ + +#define FAULT_ADDR (4 MB) +/* used in the code later as address referenced to cause page faults. */ +#define NACCESS ((1 MB) / 4) +/* NACCESS integer access (i.e. 4 bytes in each access) are made starting at address FAULT_ADDR */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "machine.H" /* LOW-LEVEL STUFF */ +#include "console.H" +#include "gdt.H" +#include "idt.H" /* LOW-LEVEL EXCEPTION MGMT. */ +#include "irq.H" +#include "exceptions.H" +#include "interrupts.H" + +#include "simple_keyboard.H" /* SIMPLE KB DRIVER */ +#include "simple_timer.H" /* SIMPLE TIMER MANAGEMENT */ + +#include "page_table.H" +#include "paging_low.H" + +#include "vm_pool.H" + +/*--------------------------------------------------------------------------*/ +/* FORWARD REFERENCES FOR TEST CODE */ +/*--------------------------------------------------------------------------*/ + +void TestPassed(); +void TestFailed(); + +void GeneratePageTableMemoryReferences(unsigned long start_address, int n_references); +void GenerateVMPoolMemoryReferences(VMPool *pool, int size1, int size2); + +/*--------------------------------------------------------------------------*/ +/* MEMORY ALLOCATION */ +/*--------------------------------------------------------------------------*/ + +VMPool *current_pool; + +typedef unsigned int size_t; + +//replace the operator "new" +void * operator new (size_t size) { + unsigned long a = current_pool->allocate((unsigned long)size); + return (void *)a; +} + +//replace the operator "new[]" +void * operator new[] (size_t size) { + unsigned long a = current_pool->allocate((unsigned long)size); + return (void *)a; +} + +//replace the operator "delete" +void operator delete (void * p) { + current_pool->release((unsigned long)p); +} + +//replace the operator "delete[]" +void operator delete[] (void * p) { + current_pool->release((unsigned long)p); +} + +/*--------------------------------------------------------------------------*/ +/* EXCEPTION HANDLERS */ +/*--------------------------------------------------------------------------*/ + +/* -- EXAMPLE OF THE DIVISION-BY-ZERO HANDLER */ + +void dbz_handler(REGS * r) { + Console::puts("DIVISION BY ZERO\n"); + for(;;); +} + + +/*--------------------------------------------------------------------------*/ +/* MAIN ENTRY INTO THE OS */ +/*--------------------------------------------------------------------------*/ + +int main() { + + GDT::init(); + Console::init(); + IDT::init(); + ExceptionHandler::init_dispatcher(); + IRQ::init(); + InterruptHandler::init_dispatcher(); + + + /* -- EXAMPLE OF AN EXCEPTION HANDLER -- */ + + class DBZ_Handler : public ExceptionHandler { + /* We derive Division-by-Zero handler from ExceptionHandler + and overload the method handle_exception. */ + public: + virtual void handle_exception(REGS * _regs) { + Console::puts("DIVISION BY ZERO!\n"); + for(;;); + } + } dbz_handler; + + /* Register the DBZ handler for exception no.0 + with the exception dispatcher. */ + ExceptionHandler::register_handler(0, &dbz_handler); + + + /* -- INITIALIZE THE TIMER (we use a very simple timer).-- */ + + SimpleTimer timer(100); /* timer ticks every 10ms. */ + + /* ---- Register timer handler for interrupt no.0 + with the interrupt dispatcher. */ + InterruptHandler::register_handler(0, &timer); + + /* NOTE: The timer chip starts periodically firing as + soon as we enable interrupts. + It is important to install a timer handler, as we + would get a lot of uncaptured interrupts otherwise. */ + + /* -- INSTALL KEYBOARD HANDLER -- */ + SimpleKeyboard::init(); + + Console::puts("after installing keyboard handler\n"); + + /* -- ENABLE INTERRUPTS -- */ + + Machine::enable_interrupts(); + + /* -- INITIALIZE FRAME POOLS -- */ + + ContFramePool kernel_mem_pool(KERNEL_POOL_START_FRAME, + KERNEL_POOL_SIZE, + 0, + 0); + + unsigned long n_info_frames = + ContFramePool::needed_info_frames(PROCESS_POOL_SIZE); + + unsigned long process_mem_pool_info_frame = + kernel_mem_pool.get_frames(n_info_frames); + + ContFramePool process_mem_pool(PROCESS_POOL_START_FRAME, + PROCESS_POOL_SIZE, + process_mem_pool_info_frame, + n_info_frames); + + /* Take care of the hole in the memory. */ + process_mem_pool.mark_inaccessible(MEM_HOLE_START_FRAME, MEM_HOLE_SIZE); + + /* -- INITIALIZE MEMORY (PAGING) -- */ + + /* ---- INSTALL PAGE FAULT HANDLER -- */ + + class PageFault_Handler : public ExceptionHandler { + /* We derive the page fault handler from ExceptionHandler + and overload the method handle_exception. */ + public: + virtual void handle_exception(REGS * _regs) { + PageTable::handle_fault(_regs); + } + } pagefault_handler; + + /* ---- Register the page fault handler for exception no. 14 + with the exception dispatcher. */ + ExceptionHandler::register_handler(14, &pagefault_handler); + + /* ---- INITIALIZE THE PAGE TABLE -- */ + + PageTable::init_paging(&kernel_mem_pool, + &process_mem_pool, + 4 MB); + + PageTable pt1; + + pt1.load(); + + PageTable::enable_paging(); + + /* -- INITIALIZE THE TWO VIRTUAL MEMORY PAGE POOLS -- */ + + /* -- MOST OF WHAT WE NEED IS SETUP. THE KERNEL CAN START. */ + + Console::puts("Hello World!\n"); + + /* Comment out the following line to test the VM Pools */ +#define _TEST_PAGE_TABLE_ + +#ifdef _TEST_PAGE_TABLE_ + + /* WE TEST JUST THE PAGE TABLE */ + GeneratePageTableMemoryReferences(FAULT_ADDR, NACCESS); + +#else + + /* WE TEST JUST THE VM POOLS */ + + /* -- CREATE THE VM POOLS. */ + + VMPool code_pool(512 MB, 256 MB, &process_mem_pool, &pt1); + VMPool heap_pool(1 GB, 256 MB, &process_mem_pool, &pt1); + + /* -- NOW THE POOLS HAVE BEEN CREATED. */ + + Console::puts("VM Pools successfully created!\n"); + + /* -- GENERATE MEMORY REFERENCES TO THE VM POOLS */ + + Console::puts("I am starting with an extensive test\n"); + Console::puts("of the VM Pool memory allocator.\n"); + Console::puts("Please be patient...\n"); + Console::puts("Testing the memory allocation on code_pool...\n"); + GenerateVMPoolMemoryReferences(&code_pool, 50, 100); + Console::puts("Testing the memory allocation on heap_pool...\n"); + GenerateVMPoolMemoryReferences(&heap_pool, 50, 100); + +#endif + + TestPassed(); +} + +void GeneratePageTableMemoryReferences(unsigned long start_address, int n_references) { + int *foo = (int *) start_address; + + for (int i=0; iis_legitimate((unsigned long)arr) == false) { + TestFailed(); + } + for(int j=0; j=0; j--) { + if(arr[j] != j) { + TestFailed(); + } + } + delete arr; + } +} + +void TestFailed() { + Console::puts("Test Failed\n"); + Console::puts("YOU CAN TURN OFF THE MACHINE NOW.\n"); + for(;;); +} + +void TestPassed() { + Console::puts("Test Passed! Congratulations!\n"); + Console::puts("YOU CAN SAFELY TURN OFF THE MACHINE NOW.\n"); + for(;;); +} diff --git a/MP4/MP4_Sources/linker.ld b/MP4/MP4_Sources/linker.ld new file mode 100755 index 0000000..fbb9a12 --- /dev/null +++ b/MP4/MP4_Sources/linker.ld @@ -0,0 +1,36 @@ +OUTPUT_FORMAT("binary") +ENTRY(start) +phys = 0x00100000; +SECTIONS +{ + .text phys : AT(phys) { + code = .; + *(.text) + *(.gnu.linkonce.t.*) + *(.gnu.linkonce.r.*) + *(.rodata) + . = ALIGN(4096); + } + .data : AT(phys + (data - code)) + { + data = .; + *(.data) + start_ctors = .; + *(.ctor*) + end_ctors = .; + start_dtors = .; + *(.dtor*) + end_dtors = .; + *(.gnu.linkonce.d.*) + . = ALIGN(4096); + } + .bss : AT(phys + (bss - code)) + { + bss = .; + *(.bss) + *(.gnu.linkonce.b.*) + . = ALIGN(4096); + } + end = .; +} + diff --git a/MP4/MP4_Sources/machine.C b/MP4/MP4_Sources/machine.C new file mode 100755 index 0000000..2d756a7 --- /dev/null +++ b/MP4/MP4_Sources/machine.C @@ -0,0 +1,70 @@ +/* + File: machine.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 12/09/04 + + LOW-LEVEL MACHINE FUNCTIONS. + +*/ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "machine.H" +#include "machine_low.H" + +#include "assert.H" + +/*--------------------------------------------------------------------------*/ +/* INTERRUPTS */ +/*--------------------------------------------------------------------------*/ + +bool Machine::interrupts_enabled() { + /* We check the IF flag (INTERRUPT ENABLE) in the EFLAGS status register. */ + return get_EFLAGS() & (1 << 9); +} + +void Machine::enable_interrupts() { + assert(!interrupts_enabled()); + __asm__ __volatile__ ("sti"); +} + +void Machine::disable_interrupts() { + assert(interrupts_enabled()); + __asm__ __volatile__ ("cli"); +} + +/*--------------------------------------------------------------------------*/ +/* PORT I/O OPERATIONS */ +/*--------------------------------------------------------------------------*/ + +/* We will use this later on for reading from the I/O ports to get data +* from devices such as the keyboard. We are using what is called +* 'inline assembly' in these routines to actually do the work */ +char Machine::inportb (unsigned short _port) { + unsigned char rv; + __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port)); + return rv; +} + +unsigned short Machine::inportw (unsigned short _port) { + unsigned short rv; + __asm__ __volatile__ ("inw %1, %0" : "=a" (rv) : "dN" (_port)); + return rv; +} + +/* We will use this to write to I/O ports to send bytes to devices. This +* will be used in the next tutorial for changing the textmode cursor +* position. Again, we use some inline assembly for the stuff that simply +* cannot be done in C */ +void Machine::outportb (unsigned short _port, char _data) { + __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data)); +} + +void Machine::outportw (unsigned short _port, unsigned short _data) { + __asm__ __volatile__ ("outw %1, %0" : : "dN" (_port), "a" (_data)); +} diff --git a/MP4/MP4_Sources/machine.H b/MP4/MP4_Sources/machine.H new file mode 100755 index 0000000..68eb6df --- /dev/null +++ b/MP4/MP4_Sources/machine.H @@ -0,0 +1,123 @@ +/* + File: machine.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 12/09/05 + + Description: Low-level definitions for x86 architecture. + + - Register context + - Data and code segment for kernel. + - Interrupt enable/disable. + +*/ + +#ifndef _machine_H_ // include file only once +#define _machine_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + +/* REGISTER CONTEXT ON THE STACK WHEN EXCEPTION/INTERRUPT REACHES EXCEPTION + DISPATCHER OR INTERRUPT DISPATCHER. + THIS IS ALSO USED IN THREAD SCHEDULING (for context switching) */ +typedef struct regs { + + /* segment descriptors */ + unsigned int gs; + unsigned int fs; + unsigned int es; + unsigned int ds; + + /* General purpose registers, managed by pusha/popa in x86. */ + unsigned int edi; + unsigned int esi; + unsigned int ebp; + unsigned int esp; + unsigned int ebx; + unsigned int edx; + unsigned int ecx; + unsigned int eax; + + /* In the low-level handlers (i.e. before we call the + exception or interrupt dispatcher) we push number + of the interrupt and error code onto the stack. */ + unsigned int int_no; + unsigned int err_code; + + /* These registers are pushed on the stack when + the exception occurs. */ + unsigned int eip; + unsigned int cs; + unsigned int eflags; + + /* These registers are pushed on the stack only when + the exception occured in user mode. + As long as you are in kernel mode, the register context + is 68 bytes long, and not 76! */ + unsigned int useresp; + unsigned int ss; +} REGS; + + +/*--------------------------------------------------------------------------*/ +/* CLASS M a c h i n e */ +/*--------------------------------------------------------------------------*/ + +class Machine { + +public: + +/*---------------------------------------------------------------*/ +/* MEMORY MANAGEMENT */ +/*---------------------------------------------------------------*/ + + static const unsigned int PAGE_SIZE = 4096; + static const unsigned int PT_ENTRIES_PER_PAGE = 1024; + +/*---------------------------------------------------------------*/ +/* INTERRUPTS */ +/*---------------------------------------------------------------*/ + + /* + This is done by checking the Interrupt Enabled flag in the + EFLAG status register and by issuing STI/CLI instructions. + (NOTE: If we have multiple threads, each has its own status register.) + */ + + static bool interrupts_enabled(); + /* Returns whether interrupts are enabled. */ + + static void enable_interrupts(); + static void disable_interrupts(); + /* Issue CLI/STI instructions. */ + +/*---------------------------------------------------------------*/ +/* PORT I/O OPERATIONS */ +/*---------------------------------------------------------------*/ + + static char inportb (unsigned short _port); + static unsigned short inportw (unsigned short _port); + /* Read data from input port _port.*/ + + static void outportb (unsigned short _port, char _data); + static void outportw (unsigned short _port, unsigned short _data); + /* Write _data to output port _port.*/ + +}; +#endif diff --git a/MP4/MP4_Sources/machine_low.H b/MP4/MP4_Sources/machine_low.H new file mode 100755 index 0000000..ff58008 --- /dev/null +++ b/MP4/MP4_Sources/machine_low.H @@ -0,0 +1,31 @@ +/* + File: machine_low.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 12/09/03 + + + Low-level CPU operations. + +*/ + +#ifndef _machine_low_H_ // include file only once +#define _machine_low_H_ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + + /* (none) */ + +/*--------------------------------------------------------------------------*/ +/* LOW-LEVER CPU OPERATIONS */ +/*--------------------------------------------------------------------------*/ + +extern "C" unsigned long get_EFLAGS(); +/* Return value of the EFLAGS status register. */ + +#endif + diff --git a/MP4/MP4_Sources/machine_low.asm b/MP4/MP4_Sources/machine_low.asm new file mode 100755 index 0000000..1d0998e --- /dev/null +++ b/MP4/MP4_Sources/machine_low.asm @@ -0,0 +1,18 @@ +; File: machine_low.asm +; +; Low level CPU handling functions. +; +; September 3, 2012 + +; ---------------------------------------------------------------------- +; get_EFLAGS() +; +; Returns value of the EFLAGS status register. +; +; ---------------------------------------------------------------------- +global _get_EFLAGS +; this function is exported. +_get_EFLAGS: + pushfd ; push eflags + pop eax ; pop contents into eax + ret \ No newline at end of file diff --git a/MP4/MP4_Sources/makefile b/MP4/MP4_Sources/makefile new file mode 100755 index 0000000..ecf4f14 --- /dev/null +++ b/MP4/MP4_Sources/makefile @@ -0,0 +1,80 @@ +CPP = gcc +CPP_OPTIONS = -m32 -nostdlib -fno-builtin -nostartfiles -nodefaultlibs -fno-exceptions -fno-rtti -fno-stack-protector -fleading-underscore -fno-asynchronous-unwind-tables + +all: kernel.bin + +clean: + rm -f *.o *.bin + +start.o: start.asm gdt_low.asm idt_low.asm irq_low.asm + nasm -f aout -o start.o start.asm + +utils.o: utils.C utils.H + $(CPP) $(CPP_OPTIONS) -c -o utils.o utils.C + +assert.o: assert.C assert.H + $(CPP) $(CPP_OPTIONS) -c -o assert.o assert.C + + +# ==== VARIOUS LOW-LEVEL STUFF ===== + +gdt.o: gdt.C gdt.H + $(CPP) $(CPP_OPTIONS) -c -o gdt.o gdt.C + +machine.o: machine.C machine.H + $(CPP) $(CPP_OPTIONS) -c -o machine.o machine.C + +machine_low.o: machine_low.asm machine_low.H + nasm -f aout -o machine_low.o machine_low.asm + +# ==== EXCEPTIONS AND INTERRUPTS ===== + +idt.o: idt.C idt.H + $(CPP) $(CPP_OPTIONS) -c -o idt.o idt.C + +irq.o: irq.C irq.H + $(CPP) $(CPP_OPTIONS) -c -o irq.o irq.C + +exceptions.o: exceptions.C exceptions.H + $(CPP) $(CPP_OPTIONS) -c -o exceptions.o exceptions.C + +interrupts.o: interrupts.C interrupts.H + $(CPP) $(CPP_OPTIONS) -c -o interrupts.o interrupts.C + +# ==== DEVICES ===== + +console.o: console.C console.H + $(CPP) $(CPP_OPTIONS) -c -o console.o console.C + +simple_timer.o: simple_timer.C simple_timer.H + $(CPP) $(CPP_OPTIONS) -c -o simple_timer.o simple_timer.C + +simple_keyboard.o: simple_keyboard.C simple_keyboard.H + $(CPP) $(CPP_OPTIONS) -c -o simple_keyboard.o simple_keyboard.C + +# ==== MEMORY ===== + +paging_low.o: paging_low.asm paging_low.H + nasm -f aout -o paging_low.o paging_low.asm + +page_table.o: page_table.C page_table.H paging_low.H + $(CPP) $(CPP_OPTIONS) -c -o page_table.o page_table.C + +cont_frame_pool.o: cont_frame_pool.C cont_frame_pool.H + $(CPP) $(CPP_OPTIONS) -c -o cont_frame_pool.o cont_frame_pool.C + +vm_pool.o: vm_pool.C vm_pool.H + $(CPP) $(CPP_OPTIONS) -c -o vm_pool.o vm_pool.C + +# ==== KERNEL MAIN FILE ===== + +kernel.o: kernel.C console.H simple_timer.H page_table.H + $(CPP) $(CPP_OPTIONS) -c -o kernel.o kernel.C + +kernel.bin: start.o utils.o kernel.o assert.o console.o gdt.o idt.o irq.o exceptions.o \ + interrupts.o simple_timer.o simple_keyboard.o paging_low.o page_table.o cont_frame_pool.o vm_pool.o machine.o \ + machine_low.o + ld -melf_i386 -T linker.ld -o kernel.bin start.o utils.o kernel.o assert.o console.o \ + gdt.o idt.o irq.o exceptions.o \ + interrupts.o simple_timer.o simple_keyboard.o paging_low.o page_table.o cont_frame_pool.o vm_pool.o machine.o \ + machine_low.o diff --git a/MP4/MP4_Sources/page_table.C b/MP4/MP4_Sources/page_table.C new file mode 100644 index 0000000..5db0877 --- /dev/null +++ b/MP4/MP4_Sources/page_table.C @@ -0,0 +1,56 @@ +#include "assert.H" +#include "exceptions.H" +#include "console.H" +#include "paging_low.H" +#include "page_table.H" + +PageTable * PageTable::current_page_table = NULL; +unsigned int PageTable::paging_enabled = 0; +ContFramePool * PageTable::kernel_mem_pool = NULL; +ContFramePool * PageTable::process_mem_pool = NULL; +unsigned long PageTable::shared_size = 0; + + +void PageTable::init_paging(ContFramePool * _kernel_mem_pool, + ContFramePool * _process_mem_pool, + const unsigned long _shared_size) +{ + assert(false); + Console::puts("Initialized Paging System\n"); +} + +PageTable::PageTable() +{ + assert(false); + Console::puts("Constructed Page Table object\n"); +} + + +void PageTable::load() +{ + assert(false); + Console::puts("Loaded page table\n"); +} + +void PageTable::enable_paging() +{ + assert(false); + Console::puts("Enabled paging\n"); +} + +void PageTable::handle_fault(REGS * _r) +{ + assert(false); + Console::puts("handled page fault\n"); +} + +void PageTable::register_pool(VMPool * _vm_pool) +{ + assert(false); + Console::puts("registered VM pool\n"); +} + +void PageTable::free_page(unsigned long _page_no) { + assert(false); + Console::puts("freed page\n"); +} diff --git a/MP4/MP4_Sources/page_table.H b/MP4/MP4_Sources/page_table.H new file mode 100755 index 0000000..7d3fbd0 --- /dev/null +++ b/MP4/MP4_Sources/page_table.H @@ -0,0 +1,100 @@ +/* + File: page_table.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 16/12/07 + + Description: Basic Paging. + + */ + +#ifndef _page_table_H_ // include file only once +#define _page_table_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "machine.H" +#include "exceptions.H" +#include "cont_frame_pool.H" +#include "vm_pool.H" + +/*--------------------------------------------------------------------------*/ +/* FORWARDS */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* P A G E - T A B L E */ +/*--------------------------------------------------------------------------*/ + +class PageTable { + +private: + + /* THESE MEMBERS ARE COMMON TO ENTIRE PAGING SUBSYSTEM */ + static PageTable * current_page_table; /* pointer to currently loaded page table object */ + static unsigned int paging_enabled; /* is paging turned on (i.e. are addresses logical)? */ + static ContFramePool * kernel_mem_pool; /* Frame pool for the kernel memory */ + static ContFramePool * process_mem_pool; /* Frame pool for the process memory */ + static unsigned long shared_size; /* size of shared address space */ + + /* DATA FOR CURRENT PAGE TABLE */ + unsigned long * page_directory; /* where is page directory located? */ + +public: + static const unsigned int PAGE_SIZE = Machine::PAGE_SIZE; + /* in bytes */ + static const unsigned int ENTRIES_PER_PAGE = Machine::PT_ENTRIES_PER_PAGE; + /* in entries */ + + static void init_paging(ContFramePool * _kernel_mem_pool, + ContFramePool * _process_mem_pool, + const unsigned long _shared_size); + /* Set the global parameters for the paging subsystem. */ + + PageTable(); + /* Initializes a page table with a given location for the directory and the + page table proper. + NOTE: The PageTable object still needs to be stored somewhere! + Probably it is best to have it on the stack, as there is no + memory manager yet... + NOTE2: It may also be simpler to create the first page table *before* + paging has been enabled. + */ + + void load(); + /* Makes the given page table the current table. This must be done once during + system startup and whenever the address space is switched (e.g. during + process switching). */ + + static void enable_paging(); + /* Enable paging on the CPU. Typically, a CPU start with paging disabled, and + memory is accessed by addressing physical memory directly. After paging is + enabled, memory is addressed logically. */ + + static void handle_fault(REGS * _r); + /* The page fault handler. */ + + // -- NEW IN MP4 + + void register_pool(VMPool * _vm_pool); + /* Register a virtual memory pool with the page table. */ + + void free_page(unsigned long _page_no); + /* If page is valid, release frame and mark page invalid. */ + +}; + +#endif + diff --git a/MP4/MP4_Sources/paging_low.H b/MP4/MP4_Sources/paging_low.H new file mode 100755 index 0000000..f36603a --- /dev/null +++ b/MP4/MP4_Sources/paging_low.H @@ -0,0 +1,51 @@ +/* + File: paging_low.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/03/28 + + + Low-level register operations for x86 paging subsystem. + +*/ + +#ifndef _paging_low_H_ // include file only once +#define _paging_low_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* -- none -- */ + +/*--------------------------------------------------------------------------*/ +/* FORWARDS */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* LOW-LEVEL PAGING ROUTINES */ +/*--------------------------------------------------------------------------*/ + +/* The low-level functions (defined in file 'paging_low.asm') that handle the + low-level function to manage the page tables. */ + + +/* -- CR0 -- */ +extern "C" unsigned long read_cr0(); +extern "C" void write_cr0(unsigned long _val); + +/* -- CR2 -- */ +extern "C" unsigned long read_cr2(); + +/* -- CR3 -- */ +extern "C" unsigned long read_cr3(); +extern "C" void write_cr3(unsigned long _val); + + +#endif + + diff --git a/MP4/MP4_Sources/paging_low.asm b/MP4/MP4_Sources/paging_low.asm new file mode 100755 index 0000000..071a775 --- /dev/null +++ b/MP4/MP4_Sources/paging_low.asm @@ -0,0 +1,32 @@ +global _read_cr0 +_read_cr0: + mov eax, cr0 + retn + +global _write_cr0 +_write_cr0: + push ebp + mov ebp, esp + mov eax, [ebp+8] + mov cr0, eax + pop ebp + retn + +global _read_cr2 +_read_cr2: + mov eax, cr2 + retn + +global _read_cr3 +_read_cr3: + mov eax, cr3 + retn + +global _write_cr3 +_write_cr3: + push ebp + mov ebp, esp + mov eax, [ebp+8] + mov cr3, eax + pop ebp + retn \ No newline at end of file diff --git a/MP4/MP4_Sources/simple_keyboard.C b/MP4/MP4_Sources/simple_keyboard.C new file mode 100755 index 0000000..f821d80 --- /dev/null +++ b/MP4/MP4_Sources/simple_keyboard.C @@ -0,0 +1,79 @@ +/* + File: simple_keyboard.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 2017/06/30 + + Simple control of the keyboard. + */ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* (none) */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "assert.H" +#include "machine.H" +#include "console.H" +#include "interrupts.H" +#include "simple_keyboard.H" + +/*--------------------------------------------------------------------------*/ +/* CONSTRUCTOR */ +/*--------------------------------------------------------------------------*/ + +SimpleKeyboard::SimpleKeyboard() { + key_pressed = false; +} + +/*--------------------------------------------------------------------------*/ +/* METHODS FOR CLASS S i m p l e K e y b o a r d */ +/*--------------------------------------------------------------------------*/ + +void SimpleKeyboard::handle_interrupt(REGS *_r) { + /* What to do when keyboard interrupt occurs? In this case, we update + "key_pressed". */ + + unsigned char status = Machine::inportb(STATUS_PORT); + /* lowest bit of status will be set if buffer is not empty. */ + if (status & 0x01) { + char kc = Machine::inportb(DATA_PORT); + if (kc >= 0) { + key_pressed = true; + key_code = kc; + } + } +} + +void SimpleKeyboard::wait() { + /* Loop until the user presses a key. */ + + kb.key_pressed = false; + + while(kb.key_pressed == false); + +} + +char SimpleKeyboard::read() { + /* Loop until the user presses a key, and then return the keycode. */ + kb.key_pressed = false; + + while (kb.key_pressed == false); + + return kb.key_code; +} + +SimpleKeyboard SimpleKeyboard::kb; + +void SimpleKeyboard::init() { + InterruptHandler::register_handler(1, &kb); +} + + diff --git a/MP4/MP4_Sources/simple_keyboard.H b/MP4/MP4_Sources/simple_keyboard.H new file mode 100755 index 0000000..823c09c --- /dev/null +++ b/MP4/MP4_Sources/simple_keyboard.H @@ -0,0 +1,68 @@ +/* + File: simple_keyboard.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 2017/02/17 + + Implements an interrupt handler for the keyboard. + The function is implemented in 'handle_interrupt'. + +*/ + +#ifndef _SIMPLE_KEYBOARD_H_ +#define _SIMPLE_KEYBOARD_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "interrupts.H" + +/*--------------------------------------------------------------------------*/ +/* S I M P L E K E Y B O A R D */ +/*--------------------------------------------------------------------------*/ + +class SimpleKeyboard : public InterruptHandler { + +public : + + SimpleKeyboard(); + /* Initialize the simple keyboard. */ + + virtual void handle_interrupt(REGS *_r); + /* This must be installed as the interrupt handler for the keyboard + when the system gets initialized. (e.g. in "kernel.C") + */ + + static void init(); + + static void wait(); + /* Wait until keyboard is pressed. The implementation is based + on busy looping! */ + + static char read(); + /* Wait until keyboard is pressed and return the keycode. + Note: The keycode is not the same as the character! + Note2: This is a very "approximate" implementation. Not complete, + and likely not correct. Use only under duress! + The implementation is based on busy looping! */ + +private: + bool key_pressed; + char key_code; + static SimpleKeyboard kb; + + static const unsigned short STATUS_PORT = 0x64; + static const unsigned short DATA_PORT = 0x60; + +}; + +#endif diff --git a/MP4/MP4_Sources/simple_timer.C b/MP4/MP4_Sources/simple_timer.C new file mode 100755 index 0000000..61c9b1c --- /dev/null +++ b/MP4/MP4_Sources/simple_timer.C @@ -0,0 +1,100 @@ +/* + File: simple_timer.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/03/19 + + Simple control of the +*/ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "assert.H" +#include "utils.H" +#include "console.H" +#include "interrupts.H" +#include "simple_timer.H" + +/*--------------------------------------------------------------------------*/ +/* CONSTRUCTOR */ +/*--------------------------------------------------------------------------*/ + +SimpleTimer::SimpleTimer(int _hz) { + /* How long has the system been running? */ + seconds = 0; + ticks = 0; /* ticks since last "seconds" update. */ + + /* At what frequency do we update the ticks counter? */ + /* hz = 18; */ + /* Actually, by defaults it is 18.22Hz. + In this way, a 16-bit counter wraps + around every hour. */ + set_frequency(_hz); + +} + +/*--------------------------------------------------------------------------*/ +/* METHODS FOR CLASS S i m p l e T i m e r */ +/*--------------------------------------------------------------------------*/ + + +void SimpleTimer::handle_interrupt(REGS *_r) { +/* What to do when timer interrupt occurs? In this case, we update "ticks", + and maybe update "seconds". + This must be installed as the interrupt handler for the timer in the + when the system gets initialized. (e.g. in "kernel.C") */ + + /* Increment our "ticks" count */ + ticks++; + + /* Whenever a second is over, we update counter accordingly. */ + if (ticks >= hz ) + { + seconds++; + ticks = 0; + Console::puts("One second has passed\n"); + } +} + + +void SimpleTimer::set_frequency(int _hz) { +/* Set the interrupt frequency for the simple timer. + Preferably set this before installing the timer handler! */ + + hz = _hz; /* Remember the frequency. */ + int divisor = 1193180 / _hz; /* The input clock runs at 1.19MHz */ + Machine::outportb(0x43, 0x34); /* Set command byte to be 0x36. */ + Machine::outportb(0x40, divisor & 0xFF); /* Set low byte of divisor. */ + Machine::outportb(0x40, divisor >> 8); /* Set high byte of divisor. */ +} + +void SimpleTimer::current(unsigned long * _seconds, int * _ticks) { +/* Return the current "time" since the system started. */ + + *_seconds = seconds; + *_ticks = ticks; +} + +void SimpleTimer::wait(unsigned long _seconds) { +/* Wait for a particular time to be passed. This is based on busy looping! */ + + unsigned long now_seconds; + int now_ticks; + current(&now_seconds, &now_ticks); + + unsigned long then_seconds = now_seconds + _seconds; + + while((seconds <= then_seconds) && (ticks < now_ticks)); +} + + diff --git a/MP4/MP4_Sources/simple_timer.H b/MP4/MP4_Sources/simple_timer.H new file mode 100755 index 0000000..ca48a0a --- /dev/null +++ b/MP4/MP4_Sources/simple_timer.H @@ -0,0 +1,70 @@ +/* + File: simple_timer.H + + Author: R. Bettati + Department of Computer Science + Texas A&M University + Date : 09/03/19 + + This is a simple example of a hardware interrupt handler. + As an example, this implements a timer, which in turn + triggers a function to be called at the given frequency. + The function is implemented in 'handle_interrupt'. + +*/ + +#ifndef _SIMPLE_TIMER_H_ +#define _SIMPLE_TIMER_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "interrupts.H" + +/*--------------------------------------------------------------------------*/ +/* S I M P L E T I M E R */ +/*--------------------------------------------------------------------------*/ + +class SimpleTimer : public InterruptHandler { + +private: + + /* How long has the system been running? */ + unsigned long seconds; + int ticks; /* ticks since last "seconds" update. */ + + /* At what frequency do we update the ticks counter? */ + int hz; /* Actually, by defaults it is 18.22Hz. + In this way, a 16-bit counter wraps + around every hour. */ + + void set_frequency(int _hz); + /* Set the interrupt frequency for the simple timer. */ + +public : + + SimpleTimer(int _hz); + /* Initialize the simple timer, and set its frequency. */ + + virtual void handle_interrupt(REGS *_r); + /* This must be installed as the interrupt handler for the timer + when the system gets initialized. (e.g. in "kernel.C") + */ + + void current(unsigned long * _seconds, int * _ticks); + /* Return the current "time" since the system started. */ + + void wait(unsigned long _seconds); + /* Wait for a particular time to be passed. The implementation is based + on busy looping! */ + +}; + +#endif diff --git a/MP4/MP4_Sources/start.asm b/MP4/MP4_Sources/start.asm new file mode 100755 index 0000000..9bbc858 --- /dev/null +++ b/MP4/MP4_Sources/start.asm @@ -0,0 +1,110 @@ +; bkerndev - Bran's Kernel Development Tutorial +; By: Brandon F. (friesenb@gmail.com) +; Desc: Kernel entry point, stack, and Interrupt Service Routines. +; +; Notes: No warranty expressed or implied. Use at own risk. +; +; This is the kernel's entry point. We could either call main here, +; or we can use this to setup the stack or other nice stuff, like +; perhaps setting up the GDT and segments. Please note that interrupts +; are disabled at this point: More on interrupts later! +[BITS 32] +global start +start: + mov esp, _sys_stack ; This points the stack to our new stack area + jmp stublet + +; This part MUST be 4byte aligned, so we solve that issue using 'ALIGN 4' +ALIGN 4 +mboot: + ; Multiboot macros to make a few lines later more readable + MULTIBOOT_PAGE_ALIGN equ 1<<0 + MULTIBOOT_MEMORY_INFO equ 1<<1 + MULTIBOOT_AOUT_KLUDGE equ 1<<16 + MULTIBOOT_HEADER_MAGIC equ 0x1BADB002 + MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_AOUT_KLUDGE + MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) + EXTERN code, bss, end + + ; This is the GRUB Multiboot header. A boot signature + dd MULTIBOOT_HEADER_MAGIC + dd MULTIBOOT_HEADER_FLAGS + dd MULTIBOOT_CHECKSUM + + ; AOUT kludge - must be physical addresses. Make a note of these: + ; The linker script fills in the data for these ones! + dd mboot ; header_addr: + ; address corresponding to the multiboot header + dd code ; load_addr: + ; physical address of the beginning of the text segment + dd bss ; load_end_addr: + ; physical address of the end of the data segment + ; (load_end_addr - load_addr) specifies how much data to load. + dd end ; bss_end_addr: + ; pysical address of end of bss segment. + ; boot loader initializes this area to zero, + ; and reserves the memory + dd start ; entry_addr: + ; physical address to which the boot loader should jump + ; to start running the OS + +stublet: + +; Initilization of static global objects. This goes through each object +; in the ctors section of the object file, where the global constructors +; created by C++ are put, and calls it. Normally C++ compilers add some code +; to do this, but that code is in the standard library - which we do not +; include +; See linker.ld to see where we tell the linker to put them. + extern start_ctors, end_ctors, start_dtors, end_dtors + +static_ctors_loop: + mov ebx, start_ctors + jmp .test + .body: + call [ebx] + add ebx,4 + .test: + cmp ebx, end_ctors + jb .body + +; Entering the kernel proper. + extern _main + call _main + +; Deinitialization of static global objects. This goes through each object +; in the dtors section of the object file, where the global destructors +; created by C++ are put, and calls it. Normally C++ compilers add some code +; to do this, but that code is in the standard library - which we do not include. +; See linker.ld to see where we tell the linker to put them. + +static_dtors_loop: + mov ebx, start_dtors + jmp .test + .body: + call [ebx] + add ebx,4 + .test: + cmp ebx, end_dtors + jb .body + +; Enter an endless loop here in order to stop. + jmp $ + +; Set up Global Descriptor Table +%include "gdt_low.asm" + +; Set up Low-level Exception Handling +%include "idt_low.asm" + +; Set up Low-level Interrupt Handling +%include "irq_low.asm" + +; Here is the definition of our BSS section. Right now, we'll use +; it just to store the stack. Remember that a stack actually grows +; downwards, so we declare the size of the data before declaring +; the identifier '_sys_stack' +SECTION .bss + resb 8192 ; This reserves 8KBytes of memory here +_sys_stack: + diff --git a/MP4/MP4_Sources/utils.C b/MP4/MP4_Sources/utils.C new file mode 100755 index 0000000..15fd38a --- /dev/null +++ b/MP4/MP4_Sources/utils.C @@ -0,0 +1,167 @@ +/* + File: utils.C + + Author: R. Bettati + Department of Computer Science + Texas A&M University + + Date : 09/02/12 + +*/ + +/* Some of the code comes from Brandon Friesens OS Tutorial: +* bkerndev - Bran's Kernel Development Tutorial +* By: Brandon F. (friesenb@gmail.com) +* Desc: Interrupt Descriptor Table management +* +* Notes: No warranty expressed or implied. Use at own risk. */ + + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none ) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "utils.H" + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* CONSTANTS */ +/*--------------------------------------------------------------------------*/ + + /* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* ABORT (USED e.g. IN _ASSERT() */ +/*--------------------------------------------------------------------------*/ + +void abort() { + for(;;); +} + +/*--------------------------------------------------------------------------*/ +/* MEMORY OPERATIONS */ +/*--------------------------------------------------------------------------*/ + +void *memcpy(void *dest, const void *src, int count) +{ + const char *sp = (const char *)src; + char *dp = (char *)dest; + for(; count != 0; count--) *dp++ = *sp++; + return dest; +} + +void *memset(void *dest, char val, int count) +{ + char *temp = (char *)dest; + for( ; count != 0; count--) *temp++ = val; + return dest; +} + +unsigned short *memsetw(unsigned short *dest, unsigned short val, int count) +{ + unsigned short *temp = (unsigned short *)dest; + for( ; count != 0; count--) *temp++ = val; + return dest; +} + +/*--------------------------------------------------------------------------*/ +/* STRING OPERATIONS */ +/*--------------------------------------------------------------------------*/ + + +int strlen(const char *_str) { + /* This loops through character array 'str', returning how + * many characters it needs to check before it finds a 0. + * In simple words, it returns the length in bytes of a string */ + int len = 0; + while (*_str != 0) { + _str++; + len++; + } + return len; +} +void strcpy(char* _dst, char* _src) { + while (*_src != 0) { + *_dst = *_src; + _dst++; + _src++; + } + *_dst = 0; // put terminating 0 at end. +} + +void int2str(int _num, char * _str) { + /* -- THIS IMPLEMENTATION IS ONE PRETTY BAD HACK. */ + int i; + char temp[11]; + + temp[0] = '\0'; + for(i = 1; i <= 10; i++) { + temp[i] = _num % 10 + '0'; + _num /= 10; + } + for(i = 10; temp[i] == '0'; i--); + if( i == 0 ) + i++; + while( i >= 0 ) + *_str++ = temp[i--]; +} + + +void uint2str(unsigned int _num, char * _str) { + /* -- THIS IS A BAD HACK AS WELL. */ + int i; + char temp[11]; + + temp[0] = '\0'; + for(i = 1; i <= 10; i++) { + temp[i] = _num % 10 + '0'; + _num /= 10; + } + for(i = 10; temp[i] == '0'; i--); + if( i == 0 ) + i++; + while( i >= 0 ) + *_str++ = temp[i--]; +} + +/*--------------------------------------------------------------------------*/ +/* POERT I/O OPERATIONS */ +/*--------------------------------------------------------------------------*/ + +/* We will use this later on for reading from the I/O ports to get data +* from devices such as the keyboard. We are using what is called +* 'inline assembly' in these routines to actually do the work */ +char inportb (unsigned short _port) { + unsigned char rv; + __asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port)); + return rv; +} + +unsigned short inportw (unsigned short _port) { + unsigned short rv; + __asm__ __volatile__ ("inw %1, %0" : "=a" (rv) : "dN" (_port)); + return rv; +} + +/* We will use this to write to I/O ports to send bytes to devices. This +* will be used in the next tutorial for changing the textmode cursor +* position. Again, we use some inline assembly for the stuff that simply +* cannot be done in C */ +void outportb (unsigned short _port, char _data) { + __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data)); +} + +void outportw (unsigned short _port, unsigned short _data) { + __asm__ __volatile__ ("outw %1, %0" : : "dN" (_port), "a" (_data)); +} diff --git a/MP4/MP4_Sources/utils.H b/MP4/MP4_Sources/utils.H new file mode 100755 index 0000000..71c6c4c --- /dev/null +++ b/MP4/MP4_Sources/utils.H @@ -0,0 +1,62 @@ +/* + File : utils.H + + Author : Riccardo Bettati + Modified : 2017/05/02 + + Description : Various definitions (NULL) and + utility functions (e.g. abort, memory and + string functions). +*/ + +#ifndef _utils_h_ +#define _utils_h_ + +/*---------------------------------------------------------------*/ +/* GENERAL CONSTANTS */ +/*---------------------------------------------------------------*/ + +#ifndef NULL +# define NULL 0 +#endif + +/*---------------------------------------------------------------*/ +/* ABORT */ +/*---------------------------------------------------------------*/ + +void abort(); +/* Stop execution. */ + +/*---------------------------------------------------------------*/ +/* SIMPLE MEMORY OPERATIONS */ +/*---------------------------------------------------------------*/ + +void *memcpy(void *dest, const void *src, int count); +/* Copy _count bytes from _src to _dest. (No check for uverlapping) */ + +void *memset(void *dest, char val, int count); +/* Set _count bytes to value _val, starting from location _dest. */ + +unsigned short *memsetw(unsigned short *dest, unsigned short val, int count); +/* Same as above, but operations are 16-bit wide. */ + +/*---------------------------------------------------------------*/ +/* SIMPLE STRING OPERATIONS (STRINGS ARE NULL-TERMINATED) */ +/*---------------------------------------------------------------*/ + +int strlen(const char * _str); +/* Determine the length of null-terminated string. */ + +void strcpy(char * _dst, char * _src); +/* Copy null-terminated string from _src to _dst. */ + +void int2str(int _num, char * _str); +/* Convert int to null-terminated string. */ + +void uint2str(unsigned int _num, char * _str); +/* Convert unsigned int to null-terminated string. */ + +#endif + + + diff --git a/MP4/MP4_Sources/vm_pool.C b/MP4/MP4_Sources/vm_pool.C new file mode 100644 index 0000000..d1071c7 --- /dev/null +++ b/MP4/MP4_Sources/vm_pool.C @@ -0,0 +1,69 @@ +/* + File: vm_pool.C + + Author: + Date : + + */ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "vm_pool.H" +#include "console.H" +#include "utils.H" +#include "assert.H" +#include "simple_keyboard.H" + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* CONSTANTS */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* FORWARDS */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* METHODS FOR CLASS V M P o o l */ +/*--------------------------------------------------------------------------*/ + +VMPool::VMPool(unsigned long _base_address, + unsigned long _size, + ContFramePool *_frame_pool, + PageTable *_page_table) { + assert(false); + Console::puts("Constructed VMPool object.\n"); +} + +unsigned long VMPool::allocate(unsigned long _size) { + assert(false); + Console::puts("Allocated region of memory.\n"); +} + +void VMPool::release(unsigned long _start_address) { + assert(false); + Console::puts("Released region of memory.\n"); +} + +bool VMPool::is_legitimate(unsigned long _address) { + assert(false); + Console::puts("Checked whether address is part of an allocated region.\n"); +} + diff --git a/MP4/MP4_Sources/vm_pool.H b/MP4/MP4_Sources/vm_pool.H new file mode 100755 index 0000000..94d5369 --- /dev/null +++ b/MP4/MP4_Sources/vm_pool.H @@ -0,0 +1,76 @@ +/* + File: vm_pool.H + + Author: R. Bettati, Nikhil Gupta + Department of Computer Science + Texas A&M University + Date : 10/26/2010 + + Description: Management of the Virtual Memory Pool + + +*/ + +#ifndef _VM_POOL_H_ // include file only once +#define _VM_POOL_H_ + +/*--------------------------------------------------------------------------*/ +/* DEFINES */ +/*--------------------------------------------------------------------------*/ + +/* -- (none) -- */ + +/*--------------------------------------------------------------------------*/ +/* INCLUDES */ +/*--------------------------------------------------------------------------*/ + +#include "utils.H" +#include "cont_frame_pool.H" + +/*--------------------------------------------------------------------------*/ +/* DATA STRUCTURES */ +/*--------------------------------------------------------------------------*/ + +/* Forward declaration of class PageTable */ +/* We need this to break a circular include sequence. */ +class PageTable; + +/*--------------------------------------------------------------------------*/ +/* V M P o o l */ +/*--------------------------------------------------------------------------*/ + +class VMPool { /* Virtual Memory Pool */ +private: + /* -- DEFINE YOUR VIRTUAL MEMORY POOL DATA STRUCTURE(s) HERE. */ + +public: + VMPool(unsigned long _base_address, + unsigned long _size, + ContFramePool *_frame_pool, + PageTable *_page_table); + /* Initializes the data structures needed for the management of this + * virtual-memory pool. + * _base_address is the logical start address of the pool. + * _size is the size of the pool in bytes. + * _frame_pool points to the frame pool that provides the virtual + * memory pool with physical memory frames. + * _page_table points to the page table that maps the logical memory + * references to physical addresses. */ + + unsigned long allocate(unsigned long _size); + /* Allocates a region of _size bytes of memory from the virtual + * memory pool. If successful, returns the virtual address of the + * start of the allocated region of memory. If fails, returns 0. */ + + void release(unsigned long _start_address); + /* Releases a region of previously allocated memory. The region + * is identified by its start address, which was returned when the + * region was allocated. */ + + bool is_legitimate(unsigned long _address); + /* Returns false if the address is not valid. An address is not valid + * if it is not part of a region that is currently allocated. */ + + }; + +#endif diff --git a/MP4/__MACOSX/._MP4_Sources b/MP4/__MACOSX/._MP4_Sources new file mode 100644 index 0000000..e4a9392 Binary files /dev/null and b/MP4/__MACOSX/._MP4_Sources differ diff --git a/MP4/__MACOSX/MP4_Sources/._.DS_Store b/MP4/__MACOSX/MP4_Sources/._.DS_Store new file mode 100644 index 0000000..09fa6bd Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._.DS_Store differ diff --git a/MP4/__MACOSX/MP4_Sources/._BIOS-bochs-latest b/MP4/__MACOSX/MP4_Sources/._BIOS-bochs-latest new file mode 100644 index 0000000..03b74d7 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._BIOS-bochs-latest differ diff --git a/MP4/__MACOSX/MP4_Sources/._README.TXT b/MP4/__MACOSX/MP4_Sources/._README.TXT new file mode 100644 index 0000000..d90f011 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._README.TXT differ diff --git a/MP4/__MACOSX/MP4_Sources/._VGABIOS-lgpl-latest b/MP4/__MACOSX/MP4_Sources/._VGABIOS-lgpl-latest new file mode 100644 index 0000000..33c8993 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._VGABIOS-lgpl-latest differ diff --git a/MP4/__MACOSX/MP4_Sources/._assert.C b/MP4/__MACOSX/MP4_Sources/._assert.C new file mode 100644 index 0000000..d2e5bc6 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._assert.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._assert.H b/MP4/__MACOSX/MP4_Sources/._assert.H new file mode 100644 index 0000000..23336cc Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._assert.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._bochsout.txt b/MP4/__MACOSX/MP4_Sources/._bochsout.txt new file mode 100644 index 0000000..5644309 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._bochsout.txt differ diff --git a/MP4/__MACOSX/MP4_Sources/._bochsrc.bxrc b/MP4/__MACOSX/MP4_Sources/._bochsrc.bxrc new file mode 100644 index 0000000..40cc0d9 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._bochsrc.bxrc differ diff --git a/MP4/__MACOSX/MP4_Sources/._console.C b/MP4/__MACOSX/MP4_Sources/._console.C new file mode 100644 index 0000000..8a48271 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._console.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._console.H b/MP4/__MACOSX/MP4_Sources/._console.H new file mode 100644 index 0000000..27a84ad Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._console.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._cont_frame_pool.C b/MP4/__MACOSX/MP4_Sources/._cont_frame_pool.C new file mode 100644 index 0000000..2b3ee36 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._cont_frame_pool.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._cont_frame_pool.H b/MP4/__MACOSX/MP4_Sources/._cont_frame_pool.H new file mode 100644 index 0000000..9e1ace7 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._cont_frame_pool.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._copykernel.sh b/MP4/__MACOSX/MP4_Sources/._copykernel.sh new file mode 100644 index 0000000..cb873e8 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._copykernel.sh differ diff --git a/MP4/__MACOSX/MP4_Sources/._dev_kernel_grub.img b/MP4/__MACOSX/MP4_Sources/._dev_kernel_grub.img new file mode 100644 index 0000000..4ee2ecf Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._dev_kernel_grub.img differ diff --git a/MP4/__MACOSX/MP4_Sources/._exceptions.C b/MP4/__MACOSX/MP4_Sources/._exceptions.C new file mode 100644 index 0000000..b7113a6 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._exceptions.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._exceptions.H b/MP4/__MACOSX/MP4_Sources/._exceptions.H new file mode 100644 index 0000000..6e42521 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._exceptions.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._gdt.C b/MP4/__MACOSX/MP4_Sources/._gdt.C new file mode 100644 index 0000000..d71bdce Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._gdt.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._gdt.H b/MP4/__MACOSX/MP4_Sources/._gdt.H new file mode 100644 index 0000000..59fb8e0 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._gdt.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._gdt_low.asm b/MP4/__MACOSX/MP4_Sources/._gdt_low.asm new file mode 100644 index 0000000..0434894 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._gdt_low.asm differ diff --git a/MP4/__MACOSX/MP4_Sources/._idt.C b/MP4/__MACOSX/MP4_Sources/._idt.C new file mode 100644 index 0000000..e4d51f1 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._idt.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._idt.H b/MP4/__MACOSX/MP4_Sources/._idt.H new file mode 100644 index 0000000..9ff91b2 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._idt.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._idt_low.asm b/MP4/__MACOSX/MP4_Sources/._idt_low.asm new file mode 100644 index 0000000..56bbaa9 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._idt_low.asm differ diff --git a/MP4/__MACOSX/MP4_Sources/._interrupts.C b/MP4/__MACOSX/MP4_Sources/._interrupts.C new file mode 100644 index 0000000..1a4829a Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._interrupts.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._interrupts.H b/MP4/__MACOSX/MP4_Sources/._interrupts.H new file mode 100644 index 0000000..03932af Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._interrupts.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._irq.C b/MP4/__MACOSX/MP4_Sources/._irq.C new file mode 100644 index 0000000..bdee82e Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._irq.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._irq.H b/MP4/__MACOSX/MP4_Sources/._irq.H new file mode 100644 index 0000000..2101c52 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._irq.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._irq_low.asm b/MP4/__MACOSX/MP4_Sources/._irq_low.asm new file mode 100644 index 0000000..4179f83 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._irq_low.asm differ diff --git a/MP4/__MACOSX/MP4_Sources/._kernel.C b/MP4/__MACOSX/MP4_Sources/._kernel.C new file mode 100644 index 0000000..33dddb6 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._kernel.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._linker.ld b/MP4/__MACOSX/MP4_Sources/._linker.ld new file mode 100644 index 0000000..23adfb8 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._linker.ld differ diff --git a/MP4/__MACOSX/MP4_Sources/._machine.C b/MP4/__MACOSX/MP4_Sources/._machine.C new file mode 100644 index 0000000..f660621 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._machine.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._machine.H b/MP4/__MACOSX/MP4_Sources/._machine.H new file mode 100644 index 0000000..78e33ec Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._machine.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._machine_low.H b/MP4/__MACOSX/MP4_Sources/._machine_low.H new file mode 100644 index 0000000..8354a0b Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._machine_low.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._machine_low.asm b/MP4/__MACOSX/MP4_Sources/._machine_low.asm new file mode 100644 index 0000000..dc76943 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._machine_low.asm differ diff --git a/MP4/__MACOSX/MP4_Sources/._makefile b/MP4/__MACOSX/MP4_Sources/._makefile new file mode 100644 index 0000000..1a70f5c Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._makefile differ diff --git a/MP4/__MACOSX/MP4_Sources/._page_table.C b/MP4/__MACOSX/MP4_Sources/._page_table.C new file mode 100644 index 0000000..183571e Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._page_table.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._page_table.H b/MP4/__MACOSX/MP4_Sources/._page_table.H new file mode 100644 index 0000000..631f7d9 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._page_table.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._paging_low.H b/MP4/__MACOSX/MP4_Sources/._paging_low.H new file mode 100644 index 0000000..47cf7c7 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._paging_low.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._paging_low.asm b/MP4/__MACOSX/MP4_Sources/._paging_low.asm new file mode 100644 index 0000000..df73b5b Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._paging_low.asm differ diff --git a/MP4/__MACOSX/MP4_Sources/._simple_keyboard.C b/MP4/__MACOSX/MP4_Sources/._simple_keyboard.C new file mode 100644 index 0000000..fe5c8f7 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._simple_keyboard.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._simple_keyboard.H b/MP4/__MACOSX/MP4_Sources/._simple_keyboard.H new file mode 100644 index 0000000..feff2c1 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._simple_keyboard.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._simple_timer.C b/MP4/__MACOSX/MP4_Sources/._simple_timer.C new file mode 100644 index 0000000..ac22feb Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._simple_timer.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._simple_timer.H b/MP4/__MACOSX/MP4_Sources/._simple_timer.H new file mode 100644 index 0000000..6c7891e Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._simple_timer.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._start.asm b/MP4/__MACOSX/MP4_Sources/._start.asm new file mode 100644 index 0000000..8296795 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._start.asm differ diff --git a/MP4/__MACOSX/MP4_Sources/._utils.C b/MP4/__MACOSX/MP4_Sources/._utils.C new file mode 100644 index 0000000..98503d1 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._utils.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._utils.H b/MP4/__MACOSX/MP4_Sources/._utils.H new file mode 100644 index 0000000..4d19cdf Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._utils.H differ diff --git a/MP4/__MACOSX/MP4_Sources/._vm_pool.C b/MP4/__MACOSX/MP4_Sources/._vm_pool.C new file mode 100644 index 0000000..3ce75d7 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._vm_pool.C differ diff --git a/MP4/__MACOSX/MP4_Sources/._vm_pool.H b/MP4/__MACOSX/MP4_Sources/._vm_pool.H new file mode 100644 index 0000000..3886f55 Binary files /dev/null and b/MP4/__MACOSX/MP4_Sources/._vm_pool.H differ diff --git a/MP4/handout_mp4.pdf b/MP4/handout_mp4.pdf new file mode 100644 index 0000000..30dea26 Binary files /dev/null and b/MP4/handout_mp4.pdf differ