please
This commit is contained in:
commit
a1cc1aa6ac
99 changed files with 4716 additions and 261 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,3 +2,4 @@ Abraham Silberschatz-Operating System Concepts (9th,2012.12).pdf
|
||||||
DevEnv/
|
DevEnv/
|
||||||
*.o
|
*.o
|
||||||
*.bin
|
*.bin
|
||||||
|
bochsout.txt
|
||||||
|
|
|
@ -1,213 +0,0 @@
|
||||||
00000000000i[ ] Bochs x86 Emulator 2.6.9
|
|
||||||
00000000000i[ ] Built from SVN snapshot on April 9, 2017
|
|
||||||
00000000000i[ ] Compiled on Apr 21 2017 at 23:41:40
|
|
||||||
00000000000i[ ] System configuration
|
|
||||||
00000000000i[ ] processors: 1 (cores=1, HT threads=1)
|
|
||||||
00000000000i[ ] A20 line support: yes
|
|
||||||
00000000000i[ ] IPS is set to 4000000
|
|
||||||
00000000000i[ ] CPU configuration
|
|
||||||
00000000000i[ ] SMP support: yes, quantum=16
|
|
||||||
00000000000i[ ] level: 6
|
|
||||||
00000000000i[ ] APIC support: xapic
|
|
||||||
00000000000i[ ] FPU support: yes
|
|
||||||
00000000000i[ ] MMX support: yes
|
|
||||||
00000000000i[ ] 3dnow! support: yes
|
|
||||||
00000000000i[ ] SEP support: yes
|
|
||||||
00000000000i[ ] SIMD support: sse2
|
|
||||||
00000000000i[ ] XSAVE support: no
|
|
||||||
00000000000i[ ] AES support: no
|
|
||||||
00000000000i[ ] SHA support: no
|
|
||||||
00000000000i[ ] MOVBE support: no
|
|
||||||
00000000000i[ ] ADX support: no
|
|
||||||
00000000000i[ ] x86-64 support: yes
|
|
||||||
00000000000i[ ] 1G paging support: no
|
|
||||||
00000000000i[ ] MWAIT support: yes
|
|
||||||
00000000000i[ ] Optimization configuration
|
|
||||||
00000000000i[ ] RepeatSpeedups support: no
|
|
||||||
00000000000i[ ] Fast function calls: no
|
|
||||||
00000000000i[ ] Handlers Chaining speedups: no
|
|
||||||
00000000000i[ ] Devices configuration
|
|
||||||
00000000000i[ ] PCI support: i440FX i430FX
|
|
||||||
00000000000i[ ] Networking: no
|
|
||||||
00000000000i[ ] Sound support: no
|
|
||||||
00000000000i[ ] USB support: UHCI
|
|
||||||
00000000000i[ ] VGA extension support: vbe
|
|
||||||
00000000000i[MEM0 ] allocated memory at 0x7f51d3416010. after alignment, vector=0x7f51d3417000
|
|
||||||
00000000000i[MEM0 ] 32.00MB
|
|
||||||
00000000000i[MEM0 ] mem block size = 0x00020000, blocks=256
|
|
||||||
00000000000i[MEM0 ] rom at 0xfffe0000/131072 ('BIOS-bochs-latest')
|
|
||||||
00000000000i[CPU0 ] WARNING: 3DNow! is not implemented yet !
|
|
||||||
00000000000i[PLUGIN] init_dev of 'pci' plugin device by virtual method
|
|
||||||
00000000000i[DEV ] i440FX PMC present at device 0, function 0
|
|
||||||
00000000000i[PLUGIN] init_dev of 'pci2isa' plugin device by virtual method
|
|
||||||
00000000000i[DEV ] PIIX3 PCI-to-ISA bridge present at device 1, function 0
|
|
||||||
00000000000i[PLUGIN] init_dev of 'cmos' plugin device by virtual method
|
|
||||||
00000000000i[CMOS ] Using local time for initial clock
|
|
||||||
00000000000i[CMOS ] Setting initial clock to: Tue May 30 20:29:08 2017 (time0=1496194148)
|
|
||||||
00000000000i[PLUGIN] init_dev of 'dma' plugin device by virtual method
|
|
||||||
00000000000i[DMA ] channel 4 used by cascade
|
|
||||||
00000000000i[PLUGIN] init_dev of 'pic' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] init_dev of 'pit' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] init_dev of 'vga' plugin device by virtual method
|
|
||||||
00000000000i[MEM0 ] Register memory access handlers: 0x0000000a0000 - 0x0000000bffff
|
|
||||||
00000000000i[VGA ] interval=200000, mode=realtime
|
|
||||||
00000000000i[MEM0 ] Register memory access handlers: 0x0000e0000000 - 0x0000e0ffffff
|
|
||||||
00000000000i[BXVGA ] VBE Bochs Display Extension Enabled
|
|
||||||
00000000000i[XGUI ] test_alloc_colors: 16 colors available out of 16 colors tried
|
|
||||||
00000000000i[XGUI ] font 8 wide x 16 high, display depth = 24
|
|
||||||
00000000000i[MEM0 ] rom at 0xc0000/38400 ('VGABIOS-lgpl-latest')
|
|
||||||
00000000000i[PLUGIN] init_dev of 'floppy' plugin device by virtual method
|
|
||||||
00000000000i[DMA ] channel 2 used by Floppy Drive
|
|
||||||
00000000000i[FLOPPY] fd0: 'dev_kernel_grub.img' ro=0, h=2,t=80,spt=18
|
|
||||||
00000000000i[FLOPPY] Using boot sequence floppy, none, none
|
|
||||||
00000000000i[FLOPPY] Floppy boot signature check is enabled
|
|
||||||
00000000000i[PLUGIN] init_dev of 'acpi' plugin device by virtual method
|
|
||||||
00000000000i[DEV ] ACPI Controller present at device 1, function 3
|
|
||||||
00000000000i[PLUGIN] init_dev of 'ioapic' plugin device by virtual method
|
|
||||||
00000000000i[IOAPIC] initializing I/O APIC
|
|
||||||
00000000000i[MEM0 ] Register memory access handlers: 0x0000fec00000 - 0x0000fec00fff
|
|
||||||
00000000000i[IOAPIC] IOAPIC enabled (base address = 0xfec00000)
|
|
||||||
00000000000i[PLUGIN] init_dev of 'keyboard' plugin device by virtual method
|
|
||||||
00000000000i[KBD ] will paste characters every 400 keyboard ticks
|
|
||||||
00000000000i[PLUGIN] init_dev of 'harddrv' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] init_dev of 'pci_ide' plugin device by virtual method
|
|
||||||
00000000000i[DEV ] PIIX3 PCI IDE controller present at device 1, function 1
|
|
||||||
00000000000i[PLUGIN] init_dev of 'unmapped' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] init_dev of 'biosdev' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] init_dev of 'speaker' plugin device by virtual method
|
|
||||||
00000000000i[PCSPK ] Using /dev/console for output
|
|
||||||
00000000000i[PLUGIN] init_dev of 'extfpuirq' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] init_dev of 'parallel' plugin device by virtual method
|
|
||||||
00000000000i[PAR ] parallel port 1 at 0x0378 irq 7
|
|
||||||
00000000000i[PLUGIN] init_dev of 'serial' plugin device by virtual method
|
|
||||||
00000000000i[SER ] com1 at 0x03f8 irq 4 (mode: null)
|
|
||||||
00000000000i[PLUGIN] init_dev of 'iodebug' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] init_dev of 'usb_uhci' plugin device by virtual method
|
|
||||||
00000000000i[DEV ] USB UHCI present at device 1, function 2
|
|
||||||
00000000000i[UHCI ] USB UHCI initialized
|
|
||||||
00000000000i[PLUGIN] register state of 'pci' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'pci2isa' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'cmos' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'dma' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'pic' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'pit' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'vga' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'floppy' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'unmapped' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'biosdev' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'speaker' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'extfpuirq' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'parallel' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'serial' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'iodebug' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'usb_uhci' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'acpi' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'ioapic' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'keyboard' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'harddrv' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] register state of 'pci_ide' plugin device by virtual method
|
|
||||||
00000000000i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
|
|
||||||
00000000000i[CPU0 ] cpu hardware reset
|
|
||||||
00000000000i[APIC0 ] allocate APIC id=0 (MMIO enabled) to 0x0000fee00000
|
|
||||||
00000000000i[CPU0 ] CPU[0] is the bootstrap processor
|
|
||||||
00000000000i[CPU0 ] CPUID[0x00000000]: 00000005 68747541 444d4163 69746e65
|
|
||||||
00000000000i[CPU0 ] CPUID[0x00000001]: 00000633 00010800 00002008 17cbfbff
|
|
||||||
00000000000i[CPU0 ] CPUID[0x00000002]: 00000000 00000000 00000000 00000000
|
|
||||||
00000000000i[CPU0 ] CPUID[0x00000003]: 00000000 00000000 00000000 00000000
|
|
||||||
00000000000i[CPU0 ] CPUID[0x00000004]: 00000000 00000000 00000000 00000000
|
|
||||||
00000000000i[CPU0 ] CPUID[0x00000005]: 00000040 00000040 00000003 00000020
|
|
||||||
00000000000i[CPU0 ] CPUID[0x80000000]: 80000008 68747541 444d4163 69746e65
|
|
||||||
00000000000i[CPU0 ] CPUID[0x80000001]: 00000633 00000000 00000101 ebd3f3ff
|
|
||||||
00000000000i[CPU0 ] CPUID[0x80000002]: 20444d41 6c687441 74286e6f 7020296d
|
|
||||||
00000000000i[CPU0 ] CPUID[0x80000003]: 65636f72 726f7373 00000000 00000000
|
|
||||||
00000000000i[CPU0 ] CPUID[0x80000004]: 00000000 00000000 00000000 00000000
|
|
||||||
00000000000i[CPU0 ] CPUID[0x80000005]: 01ff01ff 01ff01ff 40020140 40020140
|
|
||||||
00000000000i[CPU0 ] CPUID[0x80000006]: 00000000 42004200 02008140 00000000
|
|
||||||
00000000000i[CPU0 ] CPUID[0x80000007]: 00000000 00000000 00000000 00000000
|
|
||||||
00000000000i[CPU0 ] CPUID[0x80000008]: 00003028 00000000 00000000 00000000
|
|
||||||
00000000000i[PLUGIN] reset of 'pci' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'pci2isa' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'cmos' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'dma' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'pic' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'pit' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'vga' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'floppy' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'acpi' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'ioapic' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'keyboard' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'harddrv' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'pci_ide' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'unmapped' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'biosdev' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'speaker' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'extfpuirq' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'parallel' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'serial' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'iodebug' plugin device by virtual method
|
|
||||||
00000000000i[PLUGIN] reset of 'usb_uhci' plugin device by virtual method
|
|
||||||
00000000000i[ ] set SIGINT handler to bx_debug_ctrlc_handler
|
|
||||||
00000003302i[BIOS ] $Revision: 1.209 $ $Date: 2008/06/02 20:08:10 $
|
|
||||||
00000318057i[KBD ] reset-disable command received
|
|
||||||
00000438667i[VBIOS ] VGABios $Id: vgabios.c,v 1.67 2008/01/27 09:44:12 vruppert Exp $
|
|
||||||
00000438738i[BXVGA ] VBE known Display Interface b0c0
|
|
||||||
00000438770i[BXVGA ] VBE known Display Interface b0c4
|
|
||||||
00000441695i[VBIOS ] VBE Bios $Id: vbe.c,v 1.60 2008/03/02 07:47:21 vruppert Exp $
|
|
||||||
00000603836i[XGUI ] charmap update. Font is 9 x 16
|
|
||||||
00000764696i[BIOS ] Starting rombios32
|
|
||||||
00000765523i[BIOS ] ram_size=0x02000000
|
|
||||||
00000805868i[BIOS ] Found 1 cpu(s)
|
|
||||||
00000822169i[BIOS ] bios_table_addr: 0x000fb778 end=0x000fcc00
|
|
||||||
00001281043i[PCI ] i440FX PMC write to PAM register 59 (TLB Flush)
|
|
||||||
00001740530i[P2ISA ] PCI IRQ routing: PIRQA# set to 0x0b
|
|
||||||
00001740577i[P2ISA ] PCI IRQ routing: PIRQB# set to 0x09
|
|
||||||
00001740624i[P2ISA ] PCI IRQ routing: PIRQC# set to 0x0b
|
|
||||||
00001740671i[P2ISA ] PCI IRQ routing: PIRQD# set to 0x09
|
|
||||||
00001740687i[P2ISA ] write: ELCR2 = 0x0a
|
|
||||||
00001741624i[BIOS ] PIIX3 init: elcr=00 0a
|
|
||||||
00001761969i[BIOS ] PCI: bus=0 devfn=0x00: vendor_id=0x8086 device_id=0x1237
|
|
||||||
00001765206i[BIOS ] PCI: bus=0 devfn=0x08: vendor_id=0x8086 device_id=0x7000
|
|
||||||
00001767939i[BIOS ] PCI: bus=0 devfn=0x09: vendor_id=0x8086 device_id=0x7010
|
|
||||||
00001768400i[PIDE ] new BM-DMA address: 0xc000
|
|
||||||
00001769283i[BIOS ] region 4: 0x0000c000
|
|
||||||
00001771787i[BIOS ] PCI: bus=0 devfn=0x0a: vendor_id=0x8086 device_id=0x7020
|
|
||||||
00001772176i[UHCI ] new base address: 0xc020
|
|
||||||
00001773059i[BIOS ] region 4: 0x0000c020
|
|
||||||
00001773330i[UHCI ] new irq line = 9
|
|
||||||
00001775602i[BIOS ] PCI: bus=0 devfn=0x0b: vendor_id=0x8086 device_id=0x7113
|
|
||||||
00001776102i[ACPI ] new irq line = 11
|
|
||||||
00001776139i[ACPI ] new PM base address: 0xb000
|
|
||||||
00001776201i[ACPI ] new SM base address: 0xb100
|
|
||||||
00001776669i[CPU0 ] Enter to System Management Mode
|
|
||||||
00001776679i[CPU0 ] RSM: Resuming from System Management Mode
|
|
||||||
00001776713i[PCI ] setting SMRAM control register to 0x4a
|
|
||||||
00001776995i[PCI ] setting SMRAM control register to 0x0a
|
|
||||||
00001800276i[BIOS ] MP table addr=0x000fb850 MPC table addr=0x000fb780 size=0xd0
|
|
||||||
00001802479i[BIOS ] SMBIOS table addr=0x000fb860
|
|
||||||
00001805523i[BIOS ] ACPI tables: RSDP addr=0x000fb970 ACPI DATA addr=0x01ff0000 size=0x9d8
|
|
||||||
00001825056i[PCI ] i440FX PMC write to PAM register 59 (TLB Flush)
|
|
||||||
00001826068i[BIOS ] bios_table_cur_addr: 0x000fb994
|
|
||||||
00014040993i[BIOS ] Booting from 0000:7c00
|
|
||||||
00060731772i[XGUI ] charmap update. Font is 9 x 16
|
|
||||||
00300805704i[XGUI ] charmap update. Font is 9 x 16
|
|
||||||
00547344000p[XGUI ] >>PANIC<< POWER button turned off.
|
|
||||||
00547344000i[CPU0 ] CPU is in protected mode (active)
|
|
||||||
00547344000i[CPU0 ] CS.mode = 32 bit
|
|
||||||
00547344000i[CPU0 ] SS.mode = 32 bit
|
|
||||||
00547344000i[CPU0 ] EFER = 0x00000000
|
|
||||||
00547344000i[CPU0 ] | EAX=00000000 EBX=00101000 ECX=000b8000 EDX=000003d4
|
|
||||||
00547344000i[CPU0 ] | ESP=00102fe0 EBP=00102fe8 ESI=000263d3 EDI=000263df
|
|
||||||
00547344000i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df if tf sf zf af pf cf
|
|
||||||
00547344000i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
|
|
||||||
00547344000i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 ffffffff 1 1
|
|
||||||
00547344000i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
|
|
||||||
00547344000i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
|
|
||||||
00547344000i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 ffffffff 1 1
|
|
||||||
00547344000i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
|
|
||||||
00547344000i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
|
|
||||||
00547344000i[CPU0 ] | EIP=00100116 (00100116)
|
|
||||||
00547344000i[CPU0 ] | CR0=0x60000011 CR2=0x00000000
|
|
||||||
00547344000i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
|
|
||||||
00547344000i[CMOS ] Last time is 1496194284 (Tue May 30 20:31:24 2017)
|
|
||||||
00547344000i[XGUI ] Exit
|
|
||||||
00547344000i[SIM ] quit_sim called with exit code 1
|
|
|
@ -148,9 +148,6 @@ ContFramePool::ContFramePool(unsigned long _base_frame_no,
|
||||||
nFreeFrames = _n_frames;
|
nFreeFrames = _n_frames;
|
||||||
info_frame_no = _info_frame_no;
|
info_frame_no = _info_frame_no;
|
||||||
n_info_frames = _n_info_frames;
|
n_info_frames = _n_info_frames;
|
||||||
|
|
||||||
pools[nPools] = *this;
|
|
||||||
nPools += 1;
|
|
||||||
|
|
||||||
// If _info_frame_no is zero then we keep management info in the first
|
// If _info_frame_no is zero then we keep management info in the first
|
||||||
// frame(s), else we use the provided frame(s) to keep management info
|
// frame(s), else we use the provided frame(s) to keep management info
|
||||||
|
@ -186,23 +183,27 @@ ContFramePool::ContFramePool(unsigned long _base_frame_no,
|
||||||
{
|
{
|
||||||
unsigned int i = info_frame_no / 4;
|
unsigned int i = info_frame_no / 4;
|
||||||
unsigned int r = info_frame_no % 4;
|
unsigned int r = info_frame_no % 4;
|
||||||
unsigned char mask = 0xC0;
|
unsigned char mask = 0x80;
|
||||||
mask = mask >> r*2;
|
mask = mask >> r*2;
|
||||||
|
|
||||||
unsigned int c = 0;
|
unsigned int c = 0;
|
||||||
while(c < n_info_frames)
|
while(c < n_info_frames)
|
||||||
{
|
{
|
||||||
bitmap[i] = bitmap[i] ^ mask;
|
bitmap[i] = bitmap[i] ^ mask;
|
||||||
|
bitmap[i] = bitmap[i] ^ (mask >> 1);
|
||||||
if(mask == 0x02)
|
if(mask == 0x02)
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
mask = 0xC0;
|
mask = 0x80;
|
||||||
}
|
}
|
||||||
c++;
|
c++;
|
||||||
|
nFreeFrames--;
|
||||||
}
|
}
|
||||||
|
|
||||||
nFreeFrames--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pools[nPools] = *this;
|
||||||
|
nPools += 1;
|
||||||
|
|
||||||
Console::puts("Frame Pool initialized\n");
|
Console::puts("Frame Pool initialized\n");
|
||||||
}
|
}
|
||||||
|
@ -211,7 +212,7 @@ unsigned long ContFramePool::get_frames(unsigned int _n_frames)
|
||||||
{
|
{
|
||||||
// Are there enough frames left to allocate?
|
// Are there enough frames left to allocate?
|
||||||
assert(nFreeFrames > _n_frames);
|
assert(nFreeFrames > _n_frames);
|
||||||
|
|
||||||
// Find a frame that is not being used and return its frame index.
|
// Find a frame that is not being used and return its frame index.
|
||||||
// Mark that frame as being used in the bitmap.
|
// Mark that frame as being used in the bitmap.
|
||||||
// NOTE: Must be updated to find a sequence of contiguous frames
|
// NOTE: Must be updated to find a sequence of contiguous frames
|
||||||
|
@ -226,69 +227,60 @@ unsigned long ContFramePool::get_frames(unsigned int _n_frames)
|
||||||
unsigned int j = 0;
|
unsigned int j = 0;
|
||||||
unsigned int c = 0;
|
unsigned int c = 0;
|
||||||
|
|
||||||
// used as a simple way to check if we failed to find a free
|
|
||||||
// frame for an index i in the bitmap.
|
|
||||||
bool failed = false;
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
unsigned char mask = 0x80;
|
unsigned char mask = 0x80 >> (j*2);
|
||||||
// check every 2 bits for a free frame in the bitmap
|
// check every 2 bits for a free frame in the bitmap
|
||||||
while((mask & bitmap[i]) == 0 || ((mask >> 1) & bitmap[i]) == 0)
|
while((mask & bitmap[i]) == 0 || ((mask >> 1) & bitmap[i]) == 0)
|
||||||
{
|
{
|
||||||
if(mask != 0x02)
|
if(mask != 0x02)
|
||||||
{
|
{
|
||||||
j++;
|
j++;
|
||||||
mask >> 2;
|
mask = mask >> 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
failed = true;
|
|
||||||
i++;
|
i++;
|
||||||
j = 0;
|
j = 0;
|
||||||
break;
|
mask = 0x80;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if frame is found, start checking for sequence
|
// if frame is found, start checking for sequence
|
||||||
if(!failed)
|
unsigned int temp = i;
|
||||||
|
c++;
|
||||||
|
while(c < _n_frames)
|
||||||
{
|
{
|
||||||
unsigned int temp = i;
|
if(mask != 0x02)
|
||||||
c++;
|
|
||||||
while(c < _n_frames)
|
|
||||||
{
|
{
|
||||||
if(mask != 0x02)
|
mask = mask >> 2;
|
||||||
{
|
|
||||||
mask >> 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
temp++;
|
|
||||||
mask = 0x80;
|
|
||||||
}
|
|
||||||
if((mask & bitmap[temp]) != 0 && ((mask >> 1) & bitmap[temp]) != 0)
|
|
||||||
{
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(c == _n_frames)
|
else
|
||||||
{
|
{
|
||||||
nFreeFrames -= _n_frames;
|
temp++;
|
||||||
|
mask = 0x80;
|
||||||
|
}
|
||||||
|
if((mask & bitmap[temp]) != 0 && ((mask >> 1) & bitmap[temp]) != 0)
|
||||||
|
{
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
failed = false;
|
if(c == _n_frames)
|
||||||
|
{
|
||||||
|
nFreeFrames -= _n_frames;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
frame_no += i*4 + j;
|
frame_no += i*4 + j;
|
||||||
|
|
||||||
// Update bitmap
|
// Update bitmap
|
||||||
// First: clear most significant bit to mark head of sequence.
|
// First: clear most significant bit to mark head of sequence.
|
||||||
bitmap[i] = bitmap[i] ^ (0x80 >> j*2);
|
bitmap[i] = bitmap[i] ^ (0x80 >> (j*2));
|
||||||
// Second: clear both bits for all remaining frames in the sequence.
|
// Second: clear both bits for all remaining frames in the sequence.
|
||||||
c = 1;
|
c = 1;
|
||||||
unsigned char mask = 0x80 >> j*2;
|
unsigned char mask = 0x80 >> j*2;
|
||||||
|
@ -297,7 +289,7 @@ unsigned long ContFramePool::get_frames(unsigned int _n_frames)
|
||||||
{
|
{
|
||||||
if(mask != 0x02)
|
if(mask != 0x02)
|
||||||
{
|
{
|
||||||
mask >> 2;
|
mask = mask >> 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -346,7 +338,7 @@ void ContFramePool::release_frames(unsigned long _frame_no)
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
while(i < nPools)
|
while(i < nPools)
|
||||||
{
|
{
|
||||||
if(_frame_no < pools[i].base_frame_no || _frame_no > (pools[i].base_frame_no + pools[i].nframes))
|
if(_frame_no <= pools[i].base_frame_no || _frame_no > (pools[i].base_frame_no + pools[i].nframes))
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -364,19 +356,24 @@ void ContFramePool::release_frames_here(unsigned long _first_frame_no)
|
||||||
|
|
||||||
unsigned int bitmap_index = (_first_frame_no - base_frame_no) / 4;
|
unsigned int bitmap_index = (_first_frame_no - base_frame_no) / 4;
|
||||||
unsigned char mask = 0x80 >> ((_first_frame_no - base_frame_no) % 4) * 2;
|
unsigned char mask = 0x80 >> ((_first_frame_no - base_frame_no) % 4) * 2;
|
||||||
|
|
||||||
if((bitmap[bitmap_index] & mask) != 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0)
|
if(!((bitmap[bitmap_index] & mask) == 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0))
|
||||||
{
|
{
|
||||||
Console::puts("Error, Frame being released is not being used\n");
|
if((bitmap[bitmap_index] & mask) != 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0)
|
||||||
|
{
|
||||||
|
Console::puts("Error, Frame being released is not being used\n");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
Console::puts("Error, Frame being released is not head of sequence\n");
|
||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bitmap[bitmap_index] ^= mask;
|
bitmap[bitmap_index] ^= mask;
|
||||||
nFreeFrames++;
|
nFreeFrames++;
|
||||||
|
|
||||||
if(mask != 0x02)
|
if(mask != 0x02)
|
||||||
{
|
{
|
||||||
mask >> 2;
|
mask = mask >> 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -388,6 +385,15 @@ void ContFramePool::release_frames_here(unsigned long _first_frame_no)
|
||||||
{
|
{
|
||||||
bitmap[bitmap_index] ^= mask;
|
bitmap[bitmap_index] ^= mask;
|
||||||
bitmap[bitmap_index] ^= (mask >> 1);
|
bitmap[bitmap_index] ^= (mask >> 1);
|
||||||
|
if(mask != 0x02)
|
||||||
|
{
|
||||||
|
mask = mask >> 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mask = 0x80;
|
||||||
|
bitmap_index++;
|
||||||
|
}
|
||||||
nFreeFrames++;
|
nFreeFrames++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
136
MP2/MP2_Sources/kernel.C
Executable file
136
MP2/MP2_Sources/kernel.C
Executable file
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
File: kernel.C
|
||||||
|
|
||||||
|
Author: R. Bettati
|
||||||
|
Department of Computer Science
|
||||||
|
Texas A&M University
|
||||||
|
Date : 02/02/17
|
||||||
|
|
||||||
|
|
||||||
|
This file has the main entry point to the operating system.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* DEFINES */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define MB * (0x1 << 20)
|
||||||
|
#define KB * (0x1 << 10)
|
||||||
|
/* Makes things easy to read */
|
||||||
|
|
||||||
|
#define KERNEL_POOL_START_FRAME ((2 MB) / (4 KB))
|
||||||
|
#define KERNEL_POOL_SIZE ((2 MB) / (4 KB))
|
||||||
|
#define PROCESS_POOL_START_FRAME ((4 MB) / (4 KB))
|
||||||
|
#define PROCESS_POOL_SIZE ((28 MB) / (4 KB))
|
||||||
|
/* Definition of the kernel and process memory pools */
|
||||||
|
|
||||||
|
#define MEM_HOLE_START_FRAME ((15 MB) / (4 KB))
|
||||||
|
#define MEM_HOLE_SIZE ((1 MB) / (4 KB))
|
||||||
|
/* We have a 1 MB hole in physical memory starting at address 15 MB */
|
||||||
|
|
||||||
|
#define TEST_START_ADDR_PROC (4 MB)
|
||||||
|
#define TEST_START_ADDR_KERNEL (2 MB)
|
||||||
|
/* Used in the memory test below to generate sequences of memory references. */
|
||||||
|
/* One is for a sequence of memory references in the kernel space, and the */
|
||||||
|
/* other for memory references in the process space. */
|
||||||
|
|
||||||
|
#define N_TEST_ALLOCATIONS
|
||||||
|
/* Number of recursive allocations that we use to test. */
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* INCLUDES */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "machine.H" /* LOW-LEVEL STUFF */
|
||||||
|
#include "console.H"
|
||||||
|
|
||||||
|
#include "assert.H"
|
||||||
|
#include "cont_frame_pool.H" /* The physical memory manager */
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* FORWARDS */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void test_memory(ContFramePool * _pool, unsigned int _allocs_to_go);
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* MAIN ENTRY INTO THE OS */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
Console::init();
|
||||||
|
|
||||||
|
/* -- INITIALIZE FRAME POOLS -- */
|
||||||
|
|
||||||
|
/* ---- KERNEL POOL -- */
|
||||||
|
|
||||||
|
ContFramePool kernel_mem_pool(KERNEL_POOL_START_FRAME,
|
||||||
|
KERNEL_POOL_SIZE,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
|
||||||
|
|
||||||
|
/* ---- PROCESS POOL -- */
|
||||||
|
|
||||||
|
//
|
||||||
|
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);
|
||||||
|
|
||||||
|
process_mem_pool.mark_inaccessible(MEM_HOLE_START_FRAME, MEM_HOLE_SIZE);
|
||||||
|
//
|
||||||
|
/* -- MOST OF WHAT WE NEED IS SETUP. THE KERNEL CAN START. */
|
||||||
|
|
||||||
|
Console::puts("Hello World!\n");
|
||||||
|
|
||||||
|
/* -- TEST MEMORY ALLOCATOR */
|
||||||
|
|
||||||
|
test_memory(&kernel_mem_pool, 32);
|
||||||
|
|
||||||
|
/* ---- Add code here to test the frame pool implementation. */
|
||||||
|
|
||||||
|
/* -- NOW LOOP FOREVER */
|
||||||
|
Console::puts("Testing is DONE. We will do nothing forever\n");
|
||||||
|
Console::puts("Feel free to turn off the machine now.\n");
|
||||||
|
|
||||||
|
for(;;);
|
||||||
|
|
||||||
|
/* -- WE DO THE FOLLOWING TO KEEP THE COMPILER HAPPY. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_memory(ContFramePool * _pool, unsigned int _allocs_to_go) {
|
||||||
|
Console::puts("alloc_to_go = "); Console::puti(_allocs_to_go); Console::puts("\n");
|
||||||
|
if (_allocs_to_go > 0) {
|
||||||
|
int n_frames = _allocs_to_go % 4 + 1;
|
||||||
|
Console::puti(n_frames);
|
||||||
|
unsigned long frame = _pool->get_frames(n_frames);
|
||||||
|
Console::puts("testing.");
|
||||||
|
int * value_array = (int*)(frame * (4 KB));
|
||||||
|
Console::puts("testing.");
|
||||||
|
for (int i = 0; i < (1 KB) * n_frames; i++) {
|
||||||
|
value_array[i] = _allocs_to_go;
|
||||||
|
}
|
||||||
|
test_memory(_pool, _allocs_to_go - 1);
|
||||||
|
for (int i = 0; i < (1 KB) * n_frames; i++) {
|
||||||
|
if(value_array[i] != _allocs_to_go){
|
||||||
|
Console::puts("MEMORY TEST FAILED. ERROR IN FRAME POOL\n");
|
||||||
|
Console::puts("i ="); Console::puti(i);
|
||||||
|
Console::puts(" v = "); Console::puti(value_array[i]);
|
||||||
|
Console::puts(" n ="); Console::puti(_allocs_to_go);
|
||||||
|
Console::puts("\n");
|
||||||
|
for(;;);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ContFramePool::release_frames(frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
BIN
MP2/design.odt
Normal file
BIN
MP2/design.odt
Normal file
Binary file not shown.
BIN
MP2/design.pdf
Normal file
BIN
MP2/design.pdf
Normal file
Binary file not shown.
BIN
MP2/mp2.zip
Normal file
BIN
MP2/mp2.zip
Normal file
Binary file not shown.
404
MP2/mp2/cont_frame_pool.C
Normal file
404
MP2/mp2/cont_frame_pool.C
Normal file
|
@ -0,0 +1,404 @@
|
||||||
|
/*
|
||||||
|
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::pools = (ContFramePool *) FRAME_SIZE; // List of frame pools, managed by the class
|
||||||
|
unsigned int ContFramePool::nPools = 0; // Number of pools being managed
|
||||||
|
|
||||||
|
ContFramePool::ContFramePool(unsigned long _base_frame_no,
|
||||||
|
unsigned long _n_frames,
|
||||||
|
unsigned long _info_frame_no,
|
||||||
|
unsigned long _n_info_frames)
|
||||||
|
{
|
||||||
|
// Bitmap must fit in a single frame!
|
||||||
|
// NOTE: In theory, we don't need to make the bitmap any larger,
|
||||||
|
// since as stated in the instructions it is already big enough to
|
||||||
|
// hold for 128MB of memory with one bit per frame, so should still
|
||||||
|
// be enough for 64MB of memory with 2 bits per frame.
|
||||||
|
// Assertion changed to match max size of frames allowed.
|
||||||
|
assert(_n_frames <= FRAME_SIZE * 4);
|
||||||
|
|
||||||
|
base_frame_no = _base_frame_no;
|
||||||
|
nframes = _n_frames;
|
||||||
|
nFreeFrames = _n_frames;
|
||||||
|
info_frame_no = _info_frame_no;
|
||||||
|
n_info_frames = _n_info_frames;
|
||||||
|
|
||||||
|
// If _info_frame_no is zero then we keep management info in the first
|
||||||
|
// frame(s), else we use the provided frame(s) to keep management info
|
||||||
|
// NOTE: bitmap needs to be allocated with n_info_frames if specified.
|
||||||
|
if(info_frame_no == 0)
|
||||||
|
{
|
||||||
|
bitmap = (unsigned char *) (base_frame_no * FRAME_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bitmap = (unsigned char *) (info_frame_no * FRAME_SIZE * n_info_frames);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number of frames must "fill" the bitmap!
|
||||||
|
assert ((nframes % 8 ) == 0);
|
||||||
|
|
||||||
|
|
||||||
|
// Everything ok. Proceed to mark all bits in the bitmap
|
||||||
|
// NOTE: changed to reflect that I need 2 bits per frame now
|
||||||
|
for(int i=0; i*4 < _n_frames; i++)
|
||||||
|
{
|
||||||
|
bitmap[i] = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark the first frame as being used if it is being used
|
||||||
|
// NOTE: need to mark multiple frames if needed.
|
||||||
|
if(info_frame_no == 0)
|
||||||
|
{
|
||||||
|
bitmap[0] = 0x3F;
|
||||||
|
nFreeFrames--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int i = info_frame_no / 4;
|
||||||
|
unsigned int r = info_frame_no % 4;
|
||||||
|
unsigned char mask = 0x80;
|
||||||
|
mask = mask >> r*2;
|
||||||
|
|
||||||
|
unsigned int c = 0;
|
||||||
|
while(c < n_info_frames)
|
||||||
|
{
|
||||||
|
bitmap[i] = bitmap[i] ^ mask;
|
||||||
|
bitmap[i] = bitmap[i] ^ (mask >> 1);
|
||||||
|
if(mask == 0x02)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
mask = 0x80;
|
||||||
|
}
|
||||||
|
c++;
|
||||||
|
nFreeFrames--;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pools[nPools] = *this;
|
||||||
|
nPools += 1;
|
||||||
|
|
||||||
|
Console::puts("Frame Pool initialized\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long ContFramePool::get_frames(unsigned int _n_frames)
|
||||||
|
{
|
||||||
|
// Are there enough frames left to allocate?
|
||||||
|
assert(nFreeFrames > _n_frames);
|
||||||
|
|
||||||
|
// Find a frame that is not being used and return its frame index.
|
||||||
|
// Mark that frame as being used in the bitmap.
|
||||||
|
// NOTE: Must be updated to find a sequence of contiguous frames
|
||||||
|
// that are not being used and return the index of the head.
|
||||||
|
unsigned int frame_no = base_frame_no;
|
||||||
|
|
||||||
|
// i is being used as the frame_no / 4
|
||||||
|
// j is frame_no % 4
|
||||||
|
// together, they will give the actual frame_no.
|
||||||
|
// c is used as a counter to count a squence of free frames.
|
||||||
|
unsigned int i = 0;
|
||||||
|
unsigned int j = 0;
|
||||||
|
unsigned int c = 0;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
unsigned char mask = 0x80 >> (j*2);
|
||||||
|
// check every 2 bits for a free frame in the bitmap
|
||||||
|
while((mask & bitmap[i]) == 0 || ((mask >> 1) & bitmap[i]) == 0)
|
||||||
|
{
|
||||||
|
if(mask != 0x02)
|
||||||
|
{
|
||||||
|
j++;
|
||||||
|
mask = mask >> 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
j = 0;
|
||||||
|
mask = 0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if frame is found, start checking for sequence
|
||||||
|
unsigned int temp = i;
|
||||||
|
c++;
|
||||||
|
while(c < _n_frames)
|
||||||
|
{
|
||||||
|
if(mask != 0x02)
|
||||||
|
{
|
||||||
|
mask = mask >> 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp++;
|
||||||
|
mask = 0x80;
|
||||||
|
}
|
||||||
|
if((mask & bitmap[temp]) != 0 && ((mask >> 1) & bitmap[temp]) != 0)
|
||||||
|
{
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(c == _n_frames)
|
||||||
|
{
|
||||||
|
nFreeFrames -= _n_frames;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
frame_no += i*4 + j;
|
||||||
|
|
||||||
|
// Update bitmap
|
||||||
|
// First: clear most significant bit to mark head of sequence.
|
||||||
|
bitmap[i] = bitmap[i] ^ (0x80 >> (j*2));
|
||||||
|
// Second: clear both bits for all remaining frames in the sequence.
|
||||||
|
c = 1;
|
||||||
|
unsigned char mask = 0x80 >> j*2;
|
||||||
|
unsigned int temp = i;
|
||||||
|
while(c < _n_frames)
|
||||||
|
{
|
||||||
|
if(mask != 0x02)
|
||||||
|
{
|
||||||
|
mask = mask >> 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp++;
|
||||||
|
mask = 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap[temp] = bitmap[temp] ^ mask;
|
||||||
|
bitmap[temp] = bitmap[temp] ^ (mask >> 1);
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (frame_no);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContFramePool::mark_inaccessible(unsigned long _base_frame_no,
|
||||||
|
unsigned long _n_frames)
|
||||||
|
{
|
||||||
|
// Mark all frames in the range as being used.
|
||||||
|
int i ;
|
||||||
|
for(i = _base_frame_no; i < _base_frame_no + _n_frames; i++){
|
||||||
|
mark_inaccessible(i);
|
||||||
|
}
|
||||||
|
nFreeFrames -= _n_frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContFramePool::mark_inaccessible(unsigned long _frame_no)
|
||||||
|
{
|
||||||
|
// Let's first do a range check.
|
||||||
|
assert ((_frame_no >= base_frame_no) && (_frame_no < base_frame_no + nframes));
|
||||||
|
|
||||||
|
unsigned int bitmap_index = (_frame_no - base_frame_no) / 4;
|
||||||
|
unsigned char mask = 0x80 >> ((_frame_no - base_frame_no) % 4) * 2;
|
||||||
|
|
||||||
|
// Is the frame being used already?
|
||||||
|
assert(((bitmap[bitmap_index] & mask) != 0) && (bitmap[bitmap_index] & (mask >> 1)) != 0);
|
||||||
|
|
||||||
|
// Update bitmap
|
||||||
|
bitmap[bitmap_index] ^= mask;
|
||||||
|
bitmap[bitmap_index] ^= mask >> 1;
|
||||||
|
nFreeFrames--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContFramePool::release_frames(unsigned long _frame_no)
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
while(i < nPools)
|
||||||
|
{
|
||||||
|
if(_frame_no <= pools[i].base_frame_no || _frame_no > (pools[i].base_frame_no + pools[i].nframes))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pools[i].release_frames_here(_frame_no);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContFramePool::release_frames_here(unsigned long _first_frame_no)
|
||||||
|
{
|
||||||
|
unsigned char * bitmap = this->bitmap;
|
||||||
|
|
||||||
|
unsigned int bitmap_index = (_first_frame_no - base_frame_no) / 4;
|
||||||
|
unsigned char mask = 0x80 >> ((_first_frame_no - base_frame_no) % 4) * 2;
|
||||||
|
|
||||||
|
if(!((bitmap[bitmap_index] & mask) == 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0))
|
||||||
|
{
|
||||||
|
if((bitmap[bitmap_index] & mask) != 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0)
|
||||||
|
{
|
||||||
|
Console::puts("Error, Frame being released is not being used\n");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
Console::puts("Error, Frame being released is not head of sequence\n");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap[bitmap_index] ^= mask;
|
||||||
|
nFreeFrames++;
|
||||||
|
|
||||||
|
if(mask != 0x02)
|
||||||
|
{
|
||||||
|
mask = mask >> 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mask = 0x80;
|
||||||
|
bitmap_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(bitmap[bitmap_index] & mask == 0 && (bitmap[bitmap_index] & (mask >> 1)) == 0)
|
||||||
|
{
|
||||||
|
bitmap[bitmap_index] ^= mask;
|
||||||
|
bitmap[bitmap_index] ^= (mask >> 1);
|
||||||
|
if(mask != 0x02)
|
||||||
|
{
|
||||||
|
mask = mask >> 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mask = 0x80;
|
||||||
|
bitmap_index++;
|
||||||
|
}
|
||||||
|
nFreeFrames++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long ContFramePool::needed_info_frames(unsigned long _n_frames)
|
||||||
|
{
|
||||||
|
return (_n_frames / (FRAME_SIZE * 4)) + (_n_frames % (FRAME_SIZE * 4) > 0 ? 1 : 0);
|
||||||
|
}
|
132
MP2/mp2/cont_frame_pool.H
Executable file
132
MP2/mp2/cont_frame_pool.H
Executable file
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
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. */
|
||||||
|
|
||||||
|
unsigned char * bitmap; // Remember the bitmap here needs 2 bits per frame
|
||||||
|
unsigned int nFreeFrames; //
|
||||||
|
unsigned long base_frame_no; // Where does the frame pool start in phys mem?
|
||||||
|
unsigned long nframes; // Size of the frame pool
|
||||||
|
unsigned long info_frame_no; // Where do we store the management information?
|
||||||
|
unsigned long n_info_frames; // Number of frames needed to store management info
|
||||||
|
static ContFramePool* pools; // List of frame pools, managed by the class
|
||||||
|
static unsigned int nPools; // Number of pools being managed
|
||||||
|
|
||||||
|
void mark_inaccessible(unsigned long _frame_no); // Should be a frame marked as
|
||||||
|
// a head, otherwise fails
|
||||||
|
void release_frames_here(unsigned long _frame_no); // non-static member function
|
||||||
|
|
||||||
|
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 _n_frames 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 _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
|
BIN
MP2/mp2/design.pdf
Normal file
BIN
MP2/mp2/design.pdf
Normal file
Binary file not shown.
BIN
MP3/MP3_Sources.zip
Normal file
BIN
MP3/MP3_Sources.zip
Normal file
Binary file not shown.
BIN
MP3/MP3_Sources/BIOS-bochs-latest
Executable file
BIN
MP3/MP3_Sources/BIOS-bochs-latest
Executable file
Binary file not shown.
101
MP3/MP3_Sources/README.TXT
Executable file
101
MP3/MP3_Sources/README.TXT
Executable file
|
@ -0,0 +1,101 @@
|
||||||
|
CSCE 410/611/613: MP2 -- 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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
BIN
MP3/MP3_Sources/VGABIOS-lgpl-latest
Executable file
BIN
MP3/MP3_Sources/VGABIOS-lgpl-latest
Executable file
Binary file not shown.
45
MP3/MP3_Sources/assert.C
Executable file
45
MP3/MP3_Sources/assert.C
Executable file
|
@ -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 */
|
56
MP3/MP3_Sources/assert.H
Executable file
56
MP3/MP3_Sources/assert.H
Executable file
|
@ -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
|
48
MP3/MP3_Sources/bochsrc.bxrc
Executable file
48
MP3/MP3_Sources/bochsrc.bxrc
Executable file
|
@ -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
|
213
MP3/MP3_Sources/console.C
Executable file
213
MP3/MP3_Sources/console.C
Executable file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
113
MP3/MP3_Sources/console.H
Executable file
113
MP3/MP3_Sources/console.H
Executable file
|
@ -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
|
||||||
|
|
||||||
|
|
404
MP3/MP3_Sources/cont_frame_pool.C
Normal file
404
MP3/MP3_Sources/cont_frame_pool.C
Normal file
|
@ -0,0 +1,404 @@
|
||||||
|
/*
|
||||||
|
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::pools = (ContFramePool *) FRAME_SIZE; // List of frame pools, managed by the class
|
||||||
|
unsigned int ContFramePool::nPools = 0; // Number of pools being managed
|
||||||
|
|
||||||
|
ContFramePool::ContFramePool(unsigned long _base_frame_no,
|
||||||
|
unsigned long _n_frames,
|
||||||
|
unsigned long _info_frame_no,
|
||||||
|
unsigned long _n_info_frames)
|
||||||
|
{
|
||||||
|
// Bitmap must fit in a single frame!
|
||||||
|
// NOTE: In theory, we don't need to make the bitmap any larger,
|
||||||
|
// since as stated in the instructions it is already big enough to
|
||||||
|
// hold for 128MB of memory with one bit per frame, so should still
|
||||||
|
// be enough for 64MB of memory with 2 bits per frame.
|
||||||
|
// Assertion changed to match max size of frames allowed.
|
||||||
|
assert(_n_frames <= FRAME_SIZE * 4);
|
||||||
|
|
||||||
|
base_frame_no = _base_frame_no;
|
||||||
|
nframes = _n_frames;
|
||||||
|
nFreeFrames = _n_frames;
|
||||||
|
info_frame_no = _info_frame_no;
|
||||||
|
n_info_frames = _n_info_frames;
|
||||||
|
|
||||||
|
// If _info_frame_no is zero then we keep management info in the first
|
||||||
|
// frame(s), else we use the provided frame(s) to keep management info
|
||||||
|
// NOTE: bitmap needs to be allocated with n_info_frames if specified.
|
||||||
|
if(info_frame_no == 0)
|
||||||
|
{
|
||||||
|
bitmap = (unsigned char *) (base_frame_no * FRAME_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bitmap = (unsigned char *) (info_frame_no * FRAME_SIZE * n_info_frames);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number of frames must "fill" the bitmap!
|
||||||
|
assert ((nframes % 8 ) == 0);
|
||||||
|
|
||||||
|
|
||||||
|
// Everything ok. Proceed to mark all bits in the bitmap
|
||||||
|
// NOTE: changed to reflect that I need 2 bits per frame now
|
||||||
|
for(int i=0; i*4 < _n_frames; i++)
|
||||||
|
{
|
||||||
|
bitmap[i] = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark the first frame as being used if it is being used
|
||||||
|
// NOTE: need to mark multiple frames if needed.
|
||||||
|
if(info_frame_no == 0)
|
||||||
|
{
|
||||||
|
bitmap[0] = 0x3F;
|
||||||
|
nFreeFrames--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int i = info_frame_no / 4;
|
||||||
|
unsigned int r = info_frame_no % 4;
|
||||||
|
unsigned char mask = 0x80;
|
||||||
|
mask = mask >> r*2;
|
||||||
|
|
||||||
|
unsigned int c = 0;
|
||||||
|
while(c < n_info_frames)
|
||||||
|
{
|
||||||
|
bitmap[i] = bitmap[i] ^ mask;
|
||||||
|
bitmap[i] = bitmap[i] ^ (mask >> 1);
|
||||||
|
if(mask == 0x02)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
mask = 0x80;
|
||||||
|
}
|
||||||
|
c++;
|
||||||
|
nFreeFrames--;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pools[nPools] = *this;
|
||||||
|
nPools += 1;
|
||||||
|
|
||||||
|
Console::puts("Frame Pool initialized\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long ContFramePool::get_frames(unsigned int _n_frames)
|
||||||
|
{
|
||||||
|
// Are there enough frames left to allocate?
|
||||||
|
assert(nFreeFrames > _n_frames);
|
||||||
|
|
||||||
|
// Find a frame that is not being used and return its frame index.
|
||||||
|
// Mark that frame as being used in the bitmap.
|
||||||
|
// NOTE: Must be updated to find a sequence of contiguous frames
|
||||||
|
// that are not being used and return the index of the head.
|
||||||
|
unsigned int frame_no = base_frame_no;
|
||||||
|
|
||||||
|
// i is being used as the frame_no / 4
|
||||||
|
// j is frame_no % 4
|
||||||
|
// together, they will give the actual frame_no.
|
||||||
|
// c is used as a counter to count a squence of free frames.
|
||||||
|
unsigned int i = 0;
|
||||||
|
unsigned int j = 0;
|
||||||
|
unsigned int c = 0;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
unsigned char mask = 0x80 >> (j*2);
|
||||||
|
// check every 2 bits for a free frame in the bitmap
|
||||||
|
while((mask & bitmap[i]) == 0 || ((mask >> 1) & bitmap[i]) == 0)
|
||||||
|
{
|
||||||
|
if(mask != 0x02)
|
||||||
|
{
|
||||||
|
j++;
|
||||||
|
mask = mask >> 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
j = 0;
|
||||||
|
mask = 0x80;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if frame is found, start checking for sequence
|
||||||
|
unsigned int temp = i;
|
||||||
|
c++;
|
||||||
|
while(c < _n_frames)
|
||||||
|
{
|
||||||
|
if(mask != 0x02)
|
||||||
|
{
|
||||||
|
mask = mask >> 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp++;
|
||||||
|
mask = 0x80;
|
||||||
|
}
|
||||||
|
if((mask & bitmap[temp]) != 0 && ((mask >> 1) & bitmap[temp]) != 0)
|
||||||
|
{
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(c == _n_frames)
|
||||||
|
{
|
||||||
|
nFreeFrames -= _n_frames;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
frame_no += i*4 + j;
|
||||||
|
|
||||||
|
// Update bitmap
|
||||||
|
// First: clear most significant bit to mark head of sequence.
|
||||||
|
bitmap[i] = bitmap[i] ^ (0x80 >> (j*2));
|
||||||
|
// Second: clear both bits for all remaining frames in the sequence.
|
||||||
|
c = 1;
|
||||||
|
unsigned char mask = 0x80 >> j*2;
|
||||||
|
unsigned int temp = i;
|
||||||
|
while(c < _n_frames)
|
||||||
|
{
|
||||||
|
if(mask != 0x02)
|
||||||
|
{
|
||||||
|
mask = mask >> 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
temp++;
|
||||||
|
mask = 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap[temp] = bitmap[temp] ^ mask;
|
||||||
|
bitmap[temp] = bitmap[temp] ^ (mask >> 1);
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (frame_no);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContFramePool::mark_inaccessible(unsigned long _base_frame_no,
|
||||||
|
unsigned long _n_frames)
|
||||||
|
{
|
||||||
|
// Mark all frames in the range as being used.
|
||||||
|
int i ;
|
||||||
|
for(i = _base_frame_no; i < _base_frame_no + _n_frames; i++){
|
||||||
|
mark_inaccessible(i);
|
||||||
|
}
|
||||||
|
nFreeFrames -= _n_frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContFramePool::mark_inaccessible(unsigned long _frame_no)
|
||||||
|
{
|
||||||
|
// Let's first do a range check.
|
||||||
|
assert ((_frame_no >= base_frame_no) && (_frame_no < base_frame_no + nframes));
|
||||||
|
|
||||||
|
unsigned int bitmap_index = (_frame_no - base_frame_no) / 4;
|
||||||
|
unsigned char mask = 0x80 >> ((_frame_no - base_frame_no) % 4) * 2;
|
||||||
|
|
||||||
|
// Is the frame being used already?
|
||||||
|
assert(((bitmap[bitmap_index] & mask) != 0) && (bitmap[bitmap_index] & (mask >> 1)) != 0);
|
||||||
|
|
||||||
|
// Update bitmap
|
||||||
|
bitmap[bitmap_index] ^= mask;
|
||||||
|
bitmap[bitmap_index] ^= mask >> 1;
|
||||||
|
nFreeFrames--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContFramePool::release_frames(unsigned long _frame_no)
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
while(i < nPools)
|
||||||
|
{
|
||||||
|
if(_frame_no <= pools[i].base_frame_no || _frame_no > (pools[i].base_frame_no + pools[i].nframes))
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pools[i].release_frames_here(_frame_no);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContFramePool::release_frames_here(unsigned long _first_frame_no)
|
||||||
|
{
|
||||||
|
unsigned char * bitmap = this->bitmap;
|
||||||
|
|
||||||
|
unsigned int bitmap_index = (_first_frame_no - base_frame_no) / 4;
|
||||||
|
unsigned char mask = 0x80 >> ((_first_frame_no - base_frame_no) % 4) * 2;
|
||||||
|
|
||||||
|
if(!((bitmap[bitmap_index] & mask) == 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0))
|
||||||
|
{
|
||||||
|
if((bitmap[bitmap_index] & mask) != 0 && (bitmap[bitmap_index] & (mask >> 1)) != 0)
|
||||||
|
{
|
||||||
|
Console::puts("Error, Frame being released is not being used\n");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
Console::puts("Error, Frame being released is not head of sequence\n");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap[bitmap_index] ^= mask;
|
||||||
|
nFreeFrames++;
|
||||||
|
|
||||||
|
if(mask != 0x02)
|
||||||
|
{
|
||||||
|
mask = mask >> 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mask = 0x80;
|
||||||
|
bitmap_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(bitmap[bitmap_index] & mask == 0 && (bitmap[bitmap_index] & (mask >> 1)) == 0)
|
||||||
|
{
|
||||||
|
bitmap[bitmap_index] ^= mask;
|
||||||
|
bitmap[bitmap_index] ^= (mask >> 1);
|
||||||
|
if(mask != 0x02)
|
||||||
|
{
|
||||||
|
mask = mask >> 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mask = 0x80;
|
||||||
|
bitmap_index++;
|
||||||
|
}
|
||||||
|
nFreeFrames++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long ContFramePool::needed_info_frames(unsigned long _n_frames)
|
||||||
|
{
|
||||||
|
return (_n_frames / (FRAME_SIZE * 4)) + (_n_frames % (FRAME_SIZE * 4) > 0 ? 1 : 0);
|
||||||
|
}
|
132
MP3/MP3_Sources/cont_frame_pool.H
Executable file
132
MP3/MP3_Sources/cont_frame_pool.H
Executable file
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
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. */
|
||||||
|
|
||||||
|
unsigned char * bitmap; // Remember the bitmap here needs 2 bits per frame
|
||||||
|
unsigned int nFreeFrames; //
|
||||||
|
unsigned long base_frame_no; // Where does the frame pool start in phys mem?
|
||||||
|
unsigned long nframes; // Size of the frame pool
|
||||||
|
unsigned long info_frame_no; // Where do we store the management information?
|
||||||
|
unsigned long n_info_frames; // Number of frames needed to store management info
|
||||||
|
static ContFramePool* pools; // List of frame pools, managed by the class
|
||||||
|
static unsigned int nPools; // Number of pools being managed
|
||||||
|
|
||||||
|
void mark_inaccessible(unsigned long _frame_no); // Should be a frame marked as
|
||||||
|
// a head, otherwise fails
|
||||||
|
void release_frames_here(unsigned long _frame_no); // non-static member function
|
||||||
|
|
||||||
|
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 _n_frames 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 _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
|
5
MP3/MP3_Sources/copykernel.sh
Executable file
5
MP3/MP3_Sources/copykernel.sh
Executable file
|
@ -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
|
BIN
MP1/MP1_Sources/dev_kernel_grub.img → MP3/MP3_Sources/dev_kernel_grub.img
Normal file → Executable file
BIN
MP1/MP1_Sources/dev_kernel_grub.img → MP3/MP3_Sources/dev_kernel_grub.img
Normal file → Executable file
Binary file not shown.
183
MP3/MP3_Sources/exceptions.C
Executable file
183
MP3/MP3_Sources/exceptions.C
Executable file
|
@ -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");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
86
MP3/MP3_Sources/exceptions.H
Executable file
86
MP3/MP3_Sources/exceptions.H
Executable file
|
@ -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
|
||||||
|
|
||||||
|
|
124
MP3/MP3_Sources/gdt.C
Executable file
124
MP3/MP3_Sources/gdt.C
Executable file
|
@ -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();
|
||||||
|
}
|
48
MP3/MP3_Sources/gdt.H
Executable file
48
MP3/MP3_Sources/gdt.H
Executable file
|
@ -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
|
18
MP3/MP3_Sources/gdt_low.asm
Executable file
18
MP3/MP3_Sources/gdt_low.asm
Executable file
|
@ -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!
|
108
MP3/MP3_Sources/idt.C
Executable file
108
MP3/MP3_Sources/idt.C
Executable file
|
@ -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();
|
||||||
|
}
|
57
MP3/MP3_Sources/idt.H
Executable file
57
MP3/MP3_Sources/idt.H
Executable file
|
@ -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
|
279
MP3/MP3_Sources/idt_low.asm
Executable file
279
MP3/MP3_Sources/idt_low.asm
Executable file
|
@ -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
|
172
MP3/MP3_Sources/interrupts.C
Executable file
172
MP3/MP3_Sources/interrupts.C
Executable file
|
@ -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");
|
||||||
|
|
||||||
|
}
|
90
MP3/MP3_Sources/interrupts.H
Executable file
90
MP3/MP3_Sources/interrupts.H
Executable file
|
@ -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
|
||||||
|
|
||||||
|
|
60
MP3/MP3_Sources/irq.C
Executable file
60
MP3/MP3_Sources/irq.C
Executable file
|
@ -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();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
38
MP3/MP3_Sources/irq.H
Executable file
38
MP3/MP3_Sources/irq.H
Executable file
|
@ -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
|
136
MP3/MP3_Sources/irq_low.asm
Executable file
136
MP3/MP3_Sources/irq_low.asm
Executable file
|
@ -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
|
196
MP3/MP3_Sources/kernel.C
Executable file
196
MP3/MP3_Sources/kernel.C
Executable file
|
@ -0,0 +1,196 @@
|
||||||
|
/*
|
||||||
|
File: kernel.C
|
||||||
|
|
||||||
|
Author: R. Bettati
|
||||||
|
Department of Computer Science
|
||||||
|
Texas A&M University
|
||||||
|
Date : 12/09/03
|
||||||
|
|
||||||
|
|
||||||
|
This file has the main entry point to the operating system.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* 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" /* TIMER MANAGEMENT */
|
||||||
|
|
||||||
|
#include "page_table.H"
|
||||||
|
#include "paging_low.H"
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* DEFINES */
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* 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: Division-by-Zero -- */
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
/* -- EXAMPLE OF AN INTERRUPT HANDLER: 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 INTERRUPT HANDLER FOR SIMPLE KEYBOARD -- */
|
||||||
|
|
||||||
|
SimpleKeyboard::init();
|
||||||
|
|
||||||
|
/* NOTE: In the SimpleKeyboard::init() a private static object of
|
||||||
|
type SimpleKeyboard is created and its interrupt handler is
|
||||||
|
registered with the interrupt dispatcher. Subsequent calls to the
|
||||||
|
static function SimpleKeyboard::wait() look until a key is pressed.*/
|
||||||
|
|
||||||
|
/* -- 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); /* We share the first 4MB */
|
||||||
|
|
||||||
|
PageTable pt;
|
||||||
|
|
||||||
|
pt.load();
|
||||||
|
|
||||||
|
PageTable::enable_paging();
|
||||||
|
|
||||||
|
Console::puts("WE TURNED ON PAGING!\n");
|
||||||
|
Console::puts("If we see this message, the page tables have been\n");
|
||||||
|
Console::puts("set up mostly correctly.\n");
|
||||||
|
|
||||||
|
/* -- MOST OF WHAT WE NEED IS SETUP. THE KERNEL CAN START. */
|
||||||
|
|
||||||
|
Console::puts("Hello World!\n");
|
||||||
|
|
||||||
|
/* -- GENERATE MEMORY REFERENCES */
|
||||||
|
|
||||||
|
int *foo = (int *) FAULT_ADDR;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i<NACCESS; i++) {
|
||||||
|
foo[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console::puts("DONE WRITING TO MEMORY. Now testing...\n");
|
||||||
|
|
||||||
|
for (i=0; i<NACCESS; i++) {
|
||||||
|
if(foo[i] != i) {
|
||||||
|
Console::puts("TEST FAILED for access number:");
|
||||||
|
Console::putui(i);
|
||||||
|
Console::puts("\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(i == NACCESS) {
|
||||||
|
Console::puts("TEST PASSED\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- STOP HERE */
|
||||||
|
Console::puts("YOU CAN SAFELY TURN OFF THE MACHINE NOW.\n");
|
||||||
|
for(;;);
|
||||||
|
|
||||||
|
/* -- WE DO THE FOLLOWING TO KEEP THE COMPILER HAPPY. */
|
||||||
|
return 1;
|
||||||
|
}
|
36
MP3/MP3_Sources/linker.ld
Executable file
36
MP3/MP3_Sources/linker.ld
Executable file
|
@ -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 = .;
|
||||||
|
}
|
||||||
|
|
70
MP3/MP3_Sources/machine.C
Executable file
70
MP3/MP3_Sources/machine.C
Executable file
|
@ -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));
|
||||||
|
}
|
123
MP3/MP3_Sources/machine.H
Executable file
123
MP3/MP3_Sources/machine.H
Executable file
|
@ -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
|
31
MP3/MP3_Sources/machine_low.H
Executable file
31
MP3/MP3_Sources/machine_low.H
Executable file
|
@ -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
|
||||||
|
|
18
MP3/MP3_Sources/machine_low.asm
Executable file
18
MP3/MP3_Sources/machine_low.asm
Executable file
|
@ -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
|
78
MP3/MP3_Sources/makefile
Executable file
78
MP3/MP3_Sources/makefile
Executable file
|
@ -0,0 +1,78 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
# ==== 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 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 machine.o \
|
||||||
|
machine_low.o
|
91
MP3/MP3_Sources/page_table.C
Normal file
91
MP3/MP3_Sources/page_table.C
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
kernel_mem_pool = _kernel_mem_pool;
|
||||||
|
process_mem_pool = process_mem_pool;
|
||||||
|
shared_size = _shared_size;
|
||||||
|
|
||||||
|
Console::puts("\nInitialized Paging System\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
PageTable::PageTable()
|
||||||
|
{
|
||||||
|
//kernel_mem_pool->get_frames(1); // Need to take one frame for page directory.
|
||||||
|
|
||||||
|
//page_directory = (unsigned long *) 0x32000; // Should be the starting address after 1st 2MB
|
||||||
|
page_directory = (unsigned long *) kernel_mem_pool->get_frames(1); // Should I get the address like this???
|
||||||
|
|
||||||
|
//unsigned long * page_table = (unsigned long *) 0x33000; // Should be 4kb after the page directory.
|
||||||
|
unsigned long * page_table = page_directory + 0x1000; // Might be able to just do this.
|
||||||
|
|
||||||
|
unsigned long tempaddr; // Temporary address iterator.
|
||||||
|
|
||||||
|
// We need to map the first 4MB.
|
||||||
|
for(unsigned int i = 0; i < 1024; i++)
|
||||||
|
{
|
||||||
|
page_table[i] = tempaddr | 3; // set bits 0 and 1 to present and read/write respectively
|
||||||
|
tempaddr += 4096; // 4096 = 4kb
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Fill first entry of page directory.
|
||||||
|
page_directory[0] = *page_table;
|
||||||
|
page_directory[0] = page_directory[0] | 3;
|
||||||
|
|
||||||
|
for(unsigned int j = 1; j < 1024; j++)
|
||||||
|
{
|
||||||
|
page_directory[j] = 0 | 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_page_table = this;
|
||||||
|
|
||||||
|
Console::puts("\nConstructed Page Table object\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PageTable::load()
|
||||||
|
{
|
||||||
|
write_cr3(*page_directory);
|
||||||
|
current_page_table = this;
|
||||||
|
Console::puts("\nLoaded page table\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageTable::enable_paging()
|
||||||
|
{
|
||||||
|
write_cr3(*current_page_table->page_directory);
|
||||||
|
write_cr0(read_cr0() | 0x80000000);
|
||||||
|
paging_enabled = read_cr0();
|
||||||
|
Console::puts("\nEnabled paging\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PageTable::handle_fault(REGS * _r)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
unsigned long tempframe = process_mem_pool->get_frames(1);
|
||||||
|
Console::puts("\nerror code: ");
|
||||||
|
Console::puti(_r->err_code);
|
||||||
|
|
||||||
|
unsigned char mask = 0x00;
|
||||||
|
|
||||||
|
|
||||||
|
read_cr2();
|
||||||
|
*/
|
||||||
|
assert(false);
|
||||||
|
Console::puts("\nhandled page fault\n");
|
||||||
|
}
|
||||||
|
|
91
MP3/MP3_Sources/page_table.H
Executable file
91
MP3/MP3_Sources/page_table.H
Executable file
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
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"
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
/* 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, duh! */
|
||||||
|
|
||||||
|
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. */
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
51
MP3/MP3_Sources/paging_low.H
Executable file
51
MP3/MP3_Sources/paging_low.H
Executable file
|
@ -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
|
||||||
|
|
||||||
|
|
32
MP3/MP3_Sources/paging_low.asm
Executable file
32
MP3/MP3_Sources/paging_low.asm
Executable file
|
@ -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
|
79
MP3/MP3_Sources/simple_keyboard.C
Executable file
79
MP3/MP3_Sources/simple_keyboard.C
Executable file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
68
MP3/MP3_Sources/simple_keyboard.H
Executable file
68
MP3/MP3_Sources/simple_keyboard.H
Executable file
|
@ -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
|
100
MP3/MP3_Sources/simple_timer.C
Executable file
100
MP3/MP3_Sources/simple_timer.C
Executable file
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
70
MP3/MP3_Sources/simple_timer.H
Executable file
70
MP3/MP3_Sources/simple_timer.H
Executable file
|
@ -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
|
110
MP3/MP3_Sources/start.asm
Executable file
110
MP3/MP3_Sources/start.asm
Executable file
|
@ -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:
|
||||||
|
|
167
MP3/MP3_Sources/utils.C
Executable file
167
MP3/MP3_Sources/utils.C
Executable file
|
@ -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));
|
||||||
|
}
|
62
MP3/MP3_Sources/utils.H
Executable file
62
MP3/MP3_Sources/utils.H
Executable file
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
BIN
MP3/__MACOSX/._MP3_Sources
Normal file
BIN
MP3/__MACOSX/._MP3_Sources
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._BIOS-bochs-latest
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._BIOS-bochs-latest
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._README.TXT
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._README.TXT
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._VGABIOS-lgpl-latest
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._VGABIOS-lgpl-latest
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._assert.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._assert.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._assert.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._assert.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._bochsrc.bxrc
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._bochsrc.bxrc
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._console.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._console.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._console.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._console.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._cont_frame_pool.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._cont_frame_pool.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._cont_frame_pool.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._cont_frame_pool.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._copykernel.sh
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._copykernel.sh
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._dev_kernel_grub.img
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._dev_kernel_grub.img
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._exceptions.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._exceptions.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._exceptions.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._exceptions.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._gdt.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._gdt.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._gdt.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._gdt.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._gdt_low.asm
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._gdt_low.asm
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._idt.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._idt.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._idt.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._idt.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._idt_low.asm
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._idt_low.asm
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._interrupts.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._interrupts.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._interrupts.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._interrupts.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._irq.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._irq.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._irq.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._irq.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._irq_low.asm
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._irq_low.asm
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._kernel.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._kernel.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._linker.ld
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._linker.ld
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._machine.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._machine.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._machine.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._machine.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._machine_low.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._machine_low.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._machine_low.asm
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._machine_low.asm
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._makefile
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._makefile
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._page_table.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._page_table.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._page_table.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._page_table.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._paging_low.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._paging_low.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._paging_low.asm
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._paging_low.asm
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._simple_keyboard.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._simple_keyboard.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._simple_keyboard.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._simple_keyboard.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._simple_timer.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._simple_timer.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._simple_timer.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._simple_timer.H
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._start.asm
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._start.asm
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._utils.C
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._utils.C
Normal file
Binary file not shown.
BIN
MP3/__MACOSX/MP3_Sources/._utils.H
Normal file
BIN
MP3/__MACOSX/MP3_Sources/._utils.H
Normal file
Binary file not shown.
BIN
MP3/handout_mp3.pdf
Normal file
BIN
MP3/handout_mp3.pdf
Normal file
Binary file not shown.
Reference in a new issue