From ae5b1ad448e4a86f7a667d966368ef8e61c3a061 Mon Sep 17 00:00:00 2001 From: pjht Date: Sat, 20 Oct 2018 11:32:14 -0500 Subject: [PATCH] Work, but TSS loading broken. --- 32bit-gdt.asm | 34 +++++++ Makefile | 2 +- bochsout.txt | 249 +++++++++++++++++++++++++++++++++++++++++++++ bochsrc.txt | 2 +- boot/32bit-gdt.asm | 40 ++------ boot/boot.asm | 2 +- drivers/gdt.c | 69 +++++++++++++ drivers/gdt.h | 61 +++++++++++ kernel/kernel.c | 40 ++++---- libc/memory.c | 5 + libc/memory.h | 1 + new-gdt.asm | 35 +++++++ old-gdt.asm | 57 +++++++++++ 13 files changed, 546 insertions(+), 51 deletions(-) create mode 100644 32bit-gdt.asm create mode 100644 bochsout.txt create mode 100644 drivers/gdt.c create mode 100644 drivers/gdt.h create mode 100644 new-gdt.asm create mode 100644 old-gdt.asm diff --git a/32bit-gdt.asm b/32bit-gdt.asm new file mode 100644 index 0000000..71b9329 --- /dev/null +++ b/32bit-gdt.asm @@ -0,0 +1,34 @@ +gdt_start: ; don't remove the labels, they're needed to compute sizes and jumps + ; the GDT starts with a null 8-byte + dd 0x0 ; 4 byte + dd 0x0 ; 4 byte + +; GDT for code segment. base = 0x00000000, length = 0xfffff +; for flags, refer to os-dev.pdf document, page 36 +gdt_code: + dw 0x0000 ; segment length, bits 0-15 + dw 0x0 ; segment base, bits 0-15 + db 0x0 ; segment base, bits 16-23 + db 10011010b ; flags (8 bits) + db 11000001b ; flags (4 bits) + segment length, bits 16-19 + db 0x0 ; segment base, bits 24-31 + +; GDT for data segment. base and length identical to code segment +; some flags changed, again, refer to os-dev.pdf +gdt_data: + dw 0x0000 + dw 0x0 + db 0x0 + db 10010010b + db 11000001b + +gdt_end: + +; GDT descriptor +gdt_descriptor: + dw gdt_end - gdt_start - 1 ; size (16 bit), always one less of its true size + dd gdt_start ; address (32 bit) + +; define some constants for later use +CODE_SEG equ gdt_code - gdt_start +DATA_SEG equ gdt_data - gdt_start diff --git a/Makefile b/Makefile index c18da3a..f1670c5 100644 --- a/Makefile +++ b/Makefile @@ -39,5 +39,5 @@ debug: os-image.bin kernel.elf nasm $< -f bin -o $@ clean: - rm -rf *.bin *.dis *.o os-image.bin *.elf + rm -rf *.bin *.dis *.o os-image.bin *.elf boot/boot.bin rm -rf */*.o diff --git a/bochsout.txt b/bochsout.txt new file mode 100644 index 0000000..8915961 --- /dev/null +++ b/bochsout.txt @@ -0,0 +1,249 @@ +00000000000i[ ] Bochs x86 Emulator 2.6.9 +00000000000i[ ] Built from SVN snapshot on April 9, 2017 +00000000000i[ ] Compiled on May 2 2018 at 13:26:32 +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: no +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[ ] VMX support: 1 +00000000000i[ ] Optimization configuration +00000000000i[ ] RepeatSpeedups support: yes +00000000000i[ ] Fast function calls: yes +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 cirrus +00000000000i[MEM0 ] allocated memory at 0x10a780000. after alignment, vector=0x10a780000 +00000000000i[MEM0 ] 32.00MB +00000000000i[MEM0 ] mem block size = 0x00020000, blocks=256 +00000000000i[MEM0 ] rom at 0xfffe0000/131072 ('/usr/local/Cellar/bochs/2.6.9_2/share/bochs/BIOS-bochs-latest') +00000000000i[ ] lt_dlhandle is 0x7fa5fec76d60 +00000000000i[PLUGIN] loaded plugin libbx_hdimage.so +00000000000i[ ] lt_dlhandle is 0x7fa5fef32320 +00000000000i[PLUGIN] loaded plugin libbx_pci.so +00000000000i[ ] lt_dlhandle is 0x7fa5fec77050 +00000000000i[PLUGIN] loaded plugin libbx_pci2isa.so +00000000000i[ ] lt_dlhandle is 0x7fa5fec77450 +00000000000i[PLUGIN] loaded plugin libbx_usb_uhci.so +00000000000i[ ] lt_dlhandle is 0x7fa5fef33ad0 +00000000000i[PLUGIN] loaded plugin libbx_acpi.so +00000000000i[ ] lt_dlhandle is 0x7fa60106e670 +00000000000i[PLUGIN] loaded plugin libbx_cmos.so +00000000000i[ ] lt_dlhandle is 0x7fa5fec77dc0 +00000000000i[PLUGIN] loaded plugin libbx_dma.so +00000000000i[ ] lt_dlhandle is 0x7fa5fec78370 +00000000000i[PLUGIN] loaded plugin libbx_pic.so +00000000000i[ ] lt_dlhandle is 0x7fa5fec78530 +00000000000i[PLUGIN] loaded plugin libbx_pit.so +00000000000i[ ] lt_dlhandle is 0x7fa5fec78920 +00000000000i[PLUGIN] loaded plugin libbx_vga.so +00000000000i[ ] lt_dlhandle is 0x7fa5fed37690 +00000000000i[PLUGIN] loaded plugin libbx_floppy.so +00000000000i[ ] lt_dlhandle is 0x7fa5fed37c80 +00000000000i[PLUGIN] loaded plugin libbx_ioapic.so +00000000000i[ ] lt_dlhandle is 0x7fa5fec78db0 +00000000000i[PLUGIN] loaded plugin libbx_keyboard.so +00000000000i[ ] lt_dlhandle is 0x7fa60106ef50 +00000000000i[PLUGIN] loaded plugin libbx_harddrv.so +00000000000i[ ] lt_dlhandle is 0x7fa5fec79570 +00000000000i[PLUGIN] loaded plugin libbx_pci_ide.so +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: Sat Oct 20 11:17:35 2018 (time0=1540052255) +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[MEM0 ] rom at 0xc0000/41472 ('/usr/local/Cellar/bochs/2.6.9_2/share/bochs/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: 'os-image.bin' 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 ] Forwarding beep to gui +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 756e6547 6c65746e 49656e69 +00000000000i[CPU0 ] CPUID[0x00000001]: 00000633 00010800 00002028 1fcbfbff +00000000000i[CPU0 ] CPUID[0x00000002]: 00410601 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 00000000 00000000 00000000 +00000000000i[CPU0 ] CPUID[0x80000001]: 00000000 00000000 00000101 2a100000 +00000000000i[CPU0 ] CPUID[0x80000002]: 20202020 20202020 20202020 6e492020 +00000000000i[CPU0 ] CPUID[0x80000003]: 286c6574 50202952 69746e65 52286d75 +00000000000i[CPU0 ] CPUID[0x80000004]: 20342029 20555043 20202020 00202020 +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 +00000004662i[BIOS ] $Revision: 13073 $ $Date: 2017-02-16 22:43:52 +0100 (Do, 16. Feb 2017) $ +00000318050i[KBD ] reset-disable command received +00000320819i[BIOS ] Starting rombios32 +00000321257i[BIOS ] Shutdown flag 0 +00000321840i[BIOS ] ram_size=0x02000000 +00000322261i[BIOS ] ram_end=32MB +00000362829i[BIOS ] Found 1 cpu(s) +00000376413i[BIOS ] bios_table_addr: 0x000f9cd8 end=0x000fcc00 +00000704208i[PCI ] i440FX PMC write to PAM register 59 (TLB Flush) +00001032137i[P2ISA ] PCI IRQ routing: PIRQA# set to 0x0b +00001032156i[P2ISA ] PCI IRQ routing: PIRQB# set to 0x09 +00001032175i[P2ISA ] PCI IRQ routing: PIRQC# set to 0x0b +00001032194i[P2ISA ] PCI IRQ routing: PIRQD# set to 0x09 +00001032204i[P2ISA ] write: ELCR2 = 0x0a +00001032974i[BIOS ] PIIX3/PIIX4 init: elcr=00 0a +00001040697i[BIOS ] PCI: bus=0 devfn=0x00: vendor_id=0x8086 device_id=0x1237 class=0x0600 +00001042976i[BIOS ] PCI: bus=0 devfn=0x08: vendor_id=0x8086 device_id=0x7000 class=0x0601 +00001045094i[BIOS ] PCI: bus=0 devfn=0x09: vendor_id=0x8086 device_id=0x7010 class=0x0101 +00001045323i[PIDE ] new BM-DMA address: 0xc000 +00001045939i[BIOS ] region 4: 0x0000c000 +00001047953i[BIOS ] PCI: bus=0 devfn=0x0a: vendor_id=0x8086 device_id=0x7020 class=0x0c03 +00001048157i[UHCI ] new base address: 0xc020 +00001048773i[BIOS ] region 4: 0x0000c020 +00001048901i[UHCI ] new irq line = 9 +00001050796i[BIOS ] PCI: bus=0 devfn=0x0b: vendor_id=0x8086 device_id=0x7113 class=0x0680 +00001051028i[ACPI ] new irq line = 11 +00001051040i[ACPI ] new irq line = 9 +00001051065i[ACPI ] new PM base address: 0xb000 +00001051079i[ACPI ] new SM base address: 0xb100 +00001051107i[PCI ] setting SMRAM control register to 0x4a +00001215200i[CPU0 ] Enter to System Management Mode +00001215200i[CPU0 ] enter_system_management_mode: temporary disable VMX while in SMM mode +00001215210i[CPU0 ] RSM: Resuming from System Management Mode +00001379231i[PCI ] setting SMRAM control register to 0x0a +00001394138i[BIOS ] MP table addr=0x000f9db0 MPC table addr=0x000f9ce0 size=0xc8 +00001395960i[BIOS ] SMBIOS table addr=0x000f9dc0 +00001398141i[BIOS ] ACPI tables: RSDP addr=0x000f9ee0 ACPI DATA addr=0x01ff0000 size=0xf72 +00001401353i[BIOS ] Firmware waking vector 0x1ff00cc +00001403148i[PCI ] i440FX PMC write to PAM register 59 (TLB Flush) +00001403871i[BIOS ] bios_table_cur_addr: 0x000f9f04 +00001531488i[VBIOS ] VGABios $Id: vgabios.c,v 1.76 2013/02/10 08:07:03 vruppert Exp $ +00001531559i[BXVGA ] VBE known Display Interface b0c0 +00001531591i[BXVGA ] VBE known Display Interface b0c5 +00001534516i[VBIOS ] VBE Bios $Id: vbe.c,v 1.65 2014/07/08 18:02:25 vruppert Exp $ +00014040189i[BIOS ] Booting from 0000:7c00 +00014771579i[FLOPPY] partial read() on floppy image returns 128/512 +00014816023i[FLOPPY] read() on floppy image returns 0 +00014860467i[FLOPPY] read() on floppy image returns 0 +00014904911i[FLOPPY] read() on floppy image returns 0 +00015045640e[CPU0 ] fetch_raw_descriptor: GDT: index (2f) 5 > limit (27) +00015051260i[CPU0 ] WARNING: HLT instruction with IF=0! +00482728000i[ ] Ctrl-C detected in signal handler. +00482728001i[ ] dbg: Quit +00482728001i[CPU0 ] CPU is in protected mode (halted) +00482728001i[CPU0 ] CS.mode = 32 bit +00482728001i[CPU0 ] SS.mode = 32 bit +00482728001i[CPU0 ] EFER = 0x00000000 +00482728001i[CPU0 ] | EAX=00002000 EBX=00001000 ECX=00000000 EDX=000000a0 +00482728001i[CPU0 ] | ESP=0008ff78 EBP=0008ff90 ESI=000e0000 EDI=0000ffac +00482728001i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df if tf sf zf af PF cf +00482728001i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D +00482728001i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 ffffffff 1 1 +00482728001i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 ffffffff 1 1 +00482728001i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 ffffffff 1 1 +00482728001i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 ffffffff 1 1 +00482728001i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 ffffffff 1 1 +00482728001i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 ffffffff 1 1 +00482728001i[CPU0 ] | EIP=000019d4 (000019d4) +00482728001i[CPU0 ] | CR0=0x60000011 CR2=0x00000000 +00482728001i[CPU0 ] | CR3=0x00000000 CR4=0x00000000 +00482728001i[CMOS ] Last time is 1540052375 (Sat Oct 20 11:19:35 2018) +00482728001i[SIM ] quit_sim called with exit code 0 diff --git a/bochsrc.txt b/bochsrc.txt index fa14b2d..eb19aef 100644 --- a/bochsrc.txt +++ b/bochsrc.txt @@ -40,7 +40,7 @@ private_colormap: enabled=0 clock: sync=none, time0=local, rtc_sync=0 # no cmosimage # no loader -log: - +log: bochsout.txt logprefix: %t%e%d debug: action=ignore info: action=report diff --git a/boot/32bit-gdt.asm b/boot/32bit-gdt.asm index e5b1ef1..f9d692d 100644 --- a/boot/32bit-gdt.asm +++ b/boot/32bit-gdt.asm @@ -3,43 +3,23 @@ gdt_start: ; don't remove the labels, they're needed to compute sizes and jumps dd 0x0 ; 4 byte dd 0x0 ; 4 byte -; GDT for kernel code segment. base = 0x00000000, length = 0xfffff +; GDT for code segment. base = 0x00000000, length = 0xfffff ; for flags, refer to os-dev.pdf document, page 36 -gdt_kern_code: - dw 0x0000 ; segment length, bits 0-15 +gdt_code: + dw 0xffff ; segment length, bits 0-15 dw 0x0 ; segment base, bits 0-15 db 0x0 ; segment base, bits 16-23 db 10011010b ; flags (8 bits) - db 11000001b ; flags (4 bits) + segment length, bits 16-19 + db 11001111b ; flags (4 bits) + segment length, bits 16-19 db 0x0 ; segment base, bits 24-31 -; GDT for kernel data segment. base and length identical to code segment +; GDT for data segment. base and length identical to code segment ; some flags changed, again, refer to os-dev.pdf -gdt_kern_data: - dw 0x0000 - dw 0x0 - db 0x0 - db 10010010b - db 11000001b - db 0x0 - -; GDT for user code segment. base = 0x01000000, length = 0xfffff -; for flags, refer to os-dev.pdf document, page 36 -gdt_usr_code: - dw 0xffff ; segment length, bits 0-15 - dw 0x0 ; segment base, bits 0-15 - db 0x0 ; segment base, bits 16-23 - db 11111010b ; flags (8 bits) - db 11001111b ; flags (4 bits) + segment length, bits 16-19 - db 0x0 ; segment base, bits 24-31 - -; GDT for user data segment. base and length identical to code segment -; some flags changed, again, refer to os-dev.pdf -gdt_usr_data: +gdt_data: dw 0xffff dw 0x0 db 0x0 - db 11110010b + db 10010010b db 11001111b db 0x0 @@ -51,7 +31,5 @@ gdt_descriptor: dd gdt_start ; address (32 bit) ; define some constants for later use -CODE_SEG equ gdt_kern_code - gdt_start -DATA_SEG equ gdt_kern_data - gdt_start -USR_CODE_SEG equ gdt_usr_code - gdt_start -USR_DATA_SEG equ gdt_usr_data - gdt_start +CODE_SEG equ gdt_code - gdt_start +DATA_SEG equ gdt_data - gdt_start diff --git a/boot/boot.asm b/boot/boot.asm index 0e29984..c3da8c8 100644 --- a/boot/boot.asm +++ b/boot/boot.asm @@ -30,7 +30,7 @@ load_kernel: [bits 32] BEGIN_PM: call KERNEL_OFFSET ; Give control to the kernel - jmp $ ; Stay here when the kernel returns control to us (if ever) + jmp $ BOOT_DRIVE db 0 ; It is a good idea to store it in memory because 'dl' may get overwritten diff --git a/drivers/gdt.c b/drivers/gdt.c new file mode 100644 index 0000000..62d9139 --- /dev/null +++ b/drivers/gdt.c @@ -0,0 +1,69 @@ +// +// descriptor_tables.c - Initialises the GDT and IDT, and defines the +// default ISR and IRQ handler. +// Based on code from Bran's kernel development tutorials. +// Rewritten for JamesM's kernel development tutorials. +// + +#include "gdt.h" +#include + +static void gdt_set_gate(int32_t num,uint32_t base,uint32_t limit,uint8_t access,uint8_t gran); +static void write_tss(int32_t num, uint16_t ss0, uint32_t esp0); + +gdt_entry_t gdt_entries[6]; +gdt_ptr_t gdt_ptr; +tss_entry_t tss_entry; + +void init_gdt() { + gdt_ptr.limit=(sizeof(gdt_entry_t)*5)-1; + gdt_ptr.base =(uint32_t)&gdt_entries; + + gdt_set_gate(0, 0, 0, 0, 0); // Null segment + gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // Code segment + gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment + gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); // User mode code segment + gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); // User mode data segment + write_tss(5, 0x10, 0x80000); + asm volatile("lgdt (%%eax)"::"a"((uint32_t)&gdt_ptr)); + asm volatile("mov $0x2B, %ax; \ + ltr %ax; \ + "); +} + +static void gdt_set_gate(int32_t num,uint32_t base,uint32_t limit,uint8_t access,uint8_t gran) { + gdt_entries[num].base_low=(base&0xFFFF); + gdt_entries[num].base_middle=(base>>16)&0xFF; + gdt_entries[num].base_high=(base>>24)&0xFF; + gdt_entries[num].limit_low =(limit&0xFFFF); + gdt_entries[num].granularity=(limit>>16)&0x0F; + gdt_entries[num].granularity|=gran & 0xF0; + gdt_entries[num].access=access; +} + +static void write_tss(int32_t num, uint16_t ss0, uint32_t esp0) { + // Firstly, let's compute the base and limit of our entry into the GDT. + uint32_t base = (uint32_t) &tss_entry; + uint32_t limit = base + sizeof(tss_entry); + + // Now, add our TSS descriptor's address to the GDT. + gdt_set_gate(num, base, limit, 0xE9, 0x00); + + // Ensure the descriptor is initially zero. + memory_set(&tss_entry, 0, sizeof(tss_entry)); + tss_entry.ss0 = ss0; // Set the kernel stack segment. + tss_entry.esp0 = esp0; // Set the kernel stack pointer. + + // Here we set the cs, ss, ds, es, fs and gs entries in the TSS. These specify what + // segments should be loaded when the processor switches to kernel mode. Therefore + // they are just our normal kernel code/data segments - 0x08 and 0x10 respectively, + // but with the last two bits set, making 0x0b and 0x13. The setting of these bits + // sets the RPL (requested privilege level) to 3, meaning that this TSS can be used + // to switch to kernel mode from ring 3. + tss_entry.cs = 0x0b; + tss_entry.ss = tss_entry.ds = tss_entry.es = tss_entry.fs = tss_entry.gs = 0x13; +} + +void set_kernel_stack(uint32_t stack) { + tss_entry.esp0 = stack; +} diff --git a/drivers/gdt.h b/drivers/gdt.h new file mode 100644 index 0000000..2a9b103 --- /dev/null +++ b/drivers/gdt.h @@ -0,0 +1,61 @@ +#ifndef GDT_H +#define GDT_H + +#include + +struct gdt_entry_struct +{ + uint16_t limit_low; + uint16_t base_low; + uint8_t base_middle; + uint8_t access; + uint8_t granularity; + uint8_t base_high; + +} __attribute__((packed)); +typedef struct gdt_entry_struct gdt_entry_t; + +struct gdt_ptr_struct { + uint16_t limit; + uint32_t base; +} __attribute__((packed)); +typedef struct gdt_ptr_struct gdt_ptr_t; + +// A struct describing a Task State Segment. +struct tss_entry_struct { + uint32_t prev_tss; // The previous TSS - if we used hardware task switching this would form a linked list. + uint32_t esp0; // The stack pointer to load when we change to kernel mode. + uint32_t ss0; // The stack segment to load when we change to kernel mode. + uint32_t esp1; // Unused... + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; // The value to load into ES when we change to kernel mode. + uint32_t cs; // The value to load into CS when we change to kernel mode. + uint32_t ss; // The value to load into SS when we change to kernel mode. + uint32_t ds; // The value to load into DS when we change to kernel mode. + uint32_t fs; // The value to load into FS when we change to kernel mode. + uint32_t gs; // The value to load into GS when we change to kernel mode. + uint32_t ldt; // Unused... + uint16_t trap; + uint16_t iomap_base; +} __attribute__((packed)); + +typedef struct tss_entry_struct tss_entry_t; + + +void init_gdt(); +void set_kernel_stack(uint32_t stack); + +#endif diff --git a/kernel/kernel.c b/kernel/kernel.c index 2b109bf..1fc8ac4 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -1,29 +1,32 @@ #include "../drivers/vga.h" #include "../drivers/isr.h" #include "../drivers/idt.h" +#include "../drivers/gdt.h" /* pop %eax; \ or $0x200,%eax; \ push %eax; \ */ void switch_to_user_mode() { - // Set up a stack structure for switching to user mode. - asm volatile(" \ - cli; \ - mov $0x23, %ax; \ - mov %ax, %ds; \ - mov %ax, %es; \ - mov %ax, %fs; \ - mov %ax, %gs; \ - mov %esp, %eax; \ - pushl $0x23; \ - pushl %eax; \ - pushf; \ - pushl $0x1B; \ - push $1f; \ - iret; \ - 1: \ - "); + // set_kernel_stack(0x80000); + // Set up a stack structure for switching to user mode. + asm volatile(" \ + cli; \ + mov $0x23, %ax; \ + mov %ax, %ds; \ + mov %ax, %es; \ + mov %ax, %fs; \ + mov %ax, %gs; \ + \ + mov %esp, %eax; \ + pushl $0x23; \ + pushl %eax; \ + pushf; \ + pushl $0x1B; \ + push $1f; \ + iret; \ + 1: \ + "); } @@ -33,5 +36,8 @@ void main() { isr_install(); asm volatile("sti"); write_string("Setup interrupts\n"); + init_gdt(); + write_string("Setup new GDT\n"); switch_to_user_mode(); + write_string("User mode!\n"); } diff --git a/libc/memory.c b/libc/memory.c index e6d668b..ef34670 100644 --- a/libc/memory.c +++ b/libc/memory.c @@ -4,3 +4,8 @@ void memory_copy(char *source,char *dest,int nbytes) { *(dest+i)=*(source+i); } } + +void memory_set(char *dest, char val, int len) { + char *temp = (char *)dest; + for ( ; len != 0; len--) *temp++ = val; +} diff --git a/libc/memory.h b/libc/memory.h index e90f615..ca3b700 100644 --- a/libc/memory.h +++ b/libc/memory.h @@ -2,5 +2,6 @@ #define MEMORY_H void memory_copy(char *source,char *dest,int nbytes); +void memory_set(char *dest,char val,int len); #endif diff --git a/new-gdt.asm b/new-gdt.asm new file mode 100644 index 0000000..f9d692d --- /dev/null +++ b/new-gdt.asm @@ -0,0 +1,35 @@ +gdt_start: ; don't remove the labels, they're needed to compute sizes and jumps + ; the GDT starts with a null 8-byte + dd 0x0 ; 4 byte + dd 0x0 ; 4 byte + +; GDT for code segment. base = 0x00000000, length = 0xfffff +; for flags, refer to os-dev.pdf document, page 36 +gdt_code: + dw 0xffff ; segment length, bits 0-15 + dw 0x0 ; segment base, bits 0-15 + db 0x0 ; segment base, bits 16-23 + db 10011010b ; flags (8 bits) + db 11001111b ; flags (4 bits) + segment length, bits 16-19 + db 0x0 ; segment base, bits 24-31 + +; GDT for data segment. base and length identical to code segment +; some flags changed, again, refer to os-dev.pdf +gdt_data: + dw 0xffff + dw 0x0 + db 0x0 + db 10010010b + db 11001111b + db 0x0 + +gdt_end: + +; GDT descriptor +gdt_descriptor: + dw gdt_end - gdt_start - 1 ; size (16 bit), always one less of its true size + dd gdt_start ; address (32 bit) + +; define some constants for later use +CODE_SEG equ gdt_code - gdt_start +DATA_SEG equ gdt_data - gdt_start diff --git a/old-gdt.asm b/old-gdt.asm new file mode 100644 index 0000000..e5b1ef1 --- /dev/null +++ b/old-gdt.asm @@ -0,0 +1,57 @@ +gdt_start: ; don't remove the labels, they're needed to compute sizes and jumps + ; the GDT starts with a null 8-byte + dd 0x0 ; 4 byte + dd 0x0 ; 4 byte + +; GDT for kernel code segment. base = 0x00000000, length = 0xfffff +; for flags, refer to os-dev.pdf document, page 36 +gdt_kern_code: + dw 0x0000 ; segment length, bits 0-15 + dw 0x0 ; segment base, bits 0-15 + db 0x0 ; segment base, bits 16-23 + db 10011010b ; flags (8 bits) + db 11000001b ; flags (4 bits) + segment length, bits 16-19 + db 0x0 ; segment base, bits 24-31 + +; GDT for kernel data segment. base and length identical to code segment +; some flags changed, again, refer to os-dev.pdf +gdt_kern_data: + dw 0x0000 + dw 0x0 + db 0x0 + db 10010010b + db 11000001b + db 0x0 + +; GDT for user code segment. base = 0x01000000, length = 0xfffff +; for flags, refer to os-dev.pdf document, page 36 +gdt_usr_code: + dw 0xffff ; segment length, bits 0-15 + dw 0x0 ; segment base, bits 0-15 + db 0x0 ; segment base, bits 16-23 + db 11111010b ; flags (8 bits) + db 11001111b ; flags (4 bits) + segment length, bits 16-19 + db 0x0 ; segment base, bits 24-31 + +; GDT for user data segment. base and length identical to code segment +; some flags changed, again, refer to os-dev.pdf +gdt_usr_data: + dw 0xffff + dw 0x0 + db 0x0 + db 11110010b + db 11001111b + db 0x0 + +gdt_end: + +; GDT descriptor +gdt_descriptor: + dw gdt_end - gdt_start - 1 ; size (16 bit), always one less of its true size + dd gdt_start ; address (32 bit) + +; define some constants for later use +CODE_SEG equ gdt_kern_code - gdt_start +DATA_SEG equ gdt_kern_data - gdt_start +USR_CODE_SEG equ gdt_usr_code - gdt_start +USR_DATA_SEG equ gdt_usr_data - gdt_start