Merge branch 'feature-paging' into develop

Completed paging feature.
This commit is contained in:
Hunter White 2021-02-24 11:02:41 -05:00
commit 60c857324f
5 changed files with 127 additions and 20 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@ bin/
dep/
build/
tmp/
.vscode/
# ---> C++
# Compiled Object files

View File

@ -30,7 +30,7 @@ CPPSOURCES := $(shell find $(SRCDIR) -type f -name "*.$(CPPSRCEXT)")
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(CSOURCES:.$(CSRCEXT)=.o)) $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(CPPSOURCES:.$(CPPSRCEXT)=.o))
#Get assembly source files and create objects from them
ASSOURCES := $(shell find $(SRCDIR) -type f -name "*.$(ASSRCEXT)")
ASSOURCES := $(shell find $(SRCDIR) -name global-$(ARCH) -prune -false -o -type f -name "*.$(ASSRCEXT)" -print)
ASOBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(ASSOURCES:.$(ASSRCEXT)=.o))
#Find dependencies from C and C++ source files
@ -48,7 +48,7 @@ FLAGS := -O2 -Wall -Wextra -g -D__is_kernel -ffreestanding -fstack-protector
#Specific flags
CFLAGS := $(FLAGS) -std=gnu99
CXXFLAGS := $(FLAGS) -std=c++17
ASFLAGS :=
ASFLAGS := -g --gstabs+ --gdwarf-5
#Make sure certain directories are made
$(shell mkdir -p $(BUILDDIR) $(DEPDIR) bin/)
@ -61,27 +61,28 @@ $(shell mkdir -p $(patsubst $(SRCDIR)/%, $(DEPDIR)/%, $(TREE)))
GLOBALARCHDIR := $(BUILDDIR)/arch/global-$(ARCH)
#Define/create the global constructor objects
CRTBEGINOBJ := $($(C) $(CFLAGS) -print-file-name=crtbegin.o)
CRTENDOBJ := $($(C) $(CFLAGS) -print-file-name=crtend.o)
CRTBEGINOBJ := $(shell $(C) $(CFLAGS) -print-file-name=crtbegin.o)
CRTENDOBJ := $(shell $(C) $(CFLAGS) -print-file-name=crtend.o)
CRTBEGIN := $(GLOBALARCHDIR)/crti.o $(CRTBEGINOBJ)
CRTEND := $(CRTENDOBJ) $(GLOBALARCHDIR)/crtn.o
MAKEOBJS := $(GLOBALARCHDIR)/crti.o $(GLOBALARCHDIR)/crtn.o $(SRCDIR)/linker.ld $(OBJECTS) $(ASOBJECTS)
#Order the objects to prevent weird gcc bugs with global constructors
MAINOBJS := $(CRTBEGIN) $(OBJECTS) $(ASOBJECTS) $(CRTEND)
#Compile Target
bin/ZoarialBareOS.iso: bin/ZoarialBareOS.bin bin/grub.cfg
grub2-file --is-x86-multiboot bin/ZoarialBareOS.bin
mkdir -p $(BUILDDIR)/isodir/boot/grub
cp bin/ZoarialBareOS.bin $(BUILDDIR)/isodir/boot/
cp $(SRCDIR)/grub.cfg $(BUILDDIR)/isodir/boot/grub/grub.cfg
grub2-mkrescue -o $@ $(BUILDDIR)/isodir
bin/ZoarialBareOS.bin: $(MAINOBJS)
bin/ZoarialBareOS.bin: $(MAKEOBJS)
@echo " Linking... $(MAINOBJS)"
$(C) -T $(SRCDIR)/linker.ld $^ -o $@ -ffreestanding -O2 -nostdlib -lgcc
grub2-file --is-x86-multiboot $@
mkdir -p $(BUILDDIR)/isodir/boot/grub
$(C) -T $(SRCDIR)/linker.ld $(MAINOBJS) -o $@ -ffreestanding -O2 -nostdlib -lgcc
bin/grub.cfg: $(SRCDIR)/grub.cfg
cp $(SRCDIR)/grub.cfg bin/grub.cfg

View File

@ -12,11 +12,17 @@ search for this signature in the first 8 KiB of the kernel file, aligned at a
32-bit boundary. The signature is in its own section so the header can be
forced to be within the first 8 KiB of the kernel file.
*/
.section .multiboot
.section .multiboot.data, "aw", @progbits
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
.long 0
.long 0
.long 0
.long 0
.long 0
/*
The multiboot standard does not define the value of the stack pointer register
@ -30,18 +36,29 @@ System V ABI standard and de-facto extensions. The compiler will assume the
stack is properly aligned and failure to align the stack will result in
undefined behavior.
*/
.section .bss
.section .bootstrap_stack, "aw", @nobits
.align 16
stack_bottom:
.skip 16384 # 16 KiB
stack_top:
# Preallocate pages used for paging. Don't hard-code addresses and assume they
# are available, as the bootloader might have loaded its multiboot structures or
# modules there. This lets the bootloader know it must avoid the addresses.
.section .bss, "aw", @nobits
.align 4096
boot_page_directory:
.skip 4096
boot_page_table1:
.skip 4096
# Further page tables may be required if the kernel grows beyond 3 MiB.
/*
The linker script specifies _start as the entry point to the kernel and the
bootloader will jump to this position once the kernel has been loaded. It
doesn't make sense to return from this function as the bootloader is gone.
*/
.section .text
.section .paging.setup.text, "ax", @progbits
.global _start
.type _start, @function
_start:
@ -57,7 +74,80 @@ _start:
itself. It has absolute and complete power over the
machine.
*/
# Physical address of boot_page_table1.
# TODO: I recall seeing some assembly that used a macro to do the
# conversions to and from physical. Maybe this should be done in this
# code as well?
movl $(boot_page_table1 - 0xC0000000), %edi
# First address to map is address 0.
# TODO: Start at the first kernel page instead. Alternatively map the first
# 1 MiB as it can be generally useful, and there's no need to
# specially map the VGA buffer.
movl $0, %esi
# Map 1023 pages. The 1024th will be the VGA text buffer.
movl $1023, %ecx
1:
# Only map the kernel.
cmpl $(_kernel_start), %esi
jl 2f
cmpl $(_kernel_end - 0xC0000000), %esi
jge 3f
# Map physical address as "present, writable". Note that this maps
# .text and .rodata as writable. Mind security and map them as non-writable.
movl %esi, %edx
orl $0x003, %edx
movl %edx, (%edi)
2:
# Size of page is 4096 bytes.
addl $4096, %esi
# Size of entries in boot_page_table1 is 4 bytes.
addl $4, %edi
# Loop to the next entry if we haven't finished.
loop 1b
3:
# Map VGA video memory to 0xC03FF000 as "present, writable".
movl $(0x000B8000 | 0x003), boot_page_table1 - 0xC0000000 + 1023 * 4
# The page table is used at both page directory entry 0 (virtually from 0x0
# to 0x3FFFFF) (thus identity mapping the kernel) and page directory entry
# 768 (virtually from 0xC0000000 to 0xC03FFFFF) (thus mapping it in the
# higher half). The kernel is identity mapped because enabling paging does
# not change the next instruction, which continues to be physical. The CPU
# would instead page fault if there was no identity mapping.
# Map the page table to both virtual addresses 0x00000000 and 0xC0000000.
movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 0
movl $(boot_page_table1 - 0xC0000000 + 0x003), boot_page_directory - 0xC0000000 + 768 * 4
# Set cr3 to the address of the boot_page_directory.
movl $(boot_page_directory - 0xC0000000), %ecx
movl %ecx, %cr3
# Enable paging and the write-protect bit.
movl %cr0, %ecx
orl $0x80010000, %ecx
movl %ecx, %cr0
# Jump to higher half with an absolute jump.
lea 4f, %ecx
jmp *%ecx
.section .text
4:
# At this point, paging is fully set up and enabled.
# Unmap the identity mapping as it is now unnecessary.
movl $0, boot_page_directory + 0
# Reload crc3 to force a TLB flush so the changes to take effect.
movl %cr3, %ecx
movl %ecx, %cr3
/*
To set up a stack, we set the esp register to point to the top of the
stack (as it grows downwards on x86 systems). This is necessarily done
@ -107,4 +197,4 @@ _start:
Set the size of the _start symbol to the current location '.' minus its start.
This is useful when debugging or when you implement call tracing.
*/
.size _start, . - _start
# .size _start, . - _start

View File

@ -37,7 +37,7 @@ void terminal_initialize(void)
terminal_row = 0;
terminal_column = 0;
terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK);
terminal_buffer = (uint16_t*) 0xB8000;
terminal_buffer = (uint16_t*) 0xC03FF000;
for (size_t y = 0; y < VGA_HEIGHT; y++) {
for (size_t x = 0; x < VGA_WIDTH; x++) {
const size_t index = y * VGA_WIDTH + x;

View File

@ -13,31 +13,46 @@ SECTIONS
/* First put the multiboot header, as it is required to be put very early
early in the image or the bootloader won't recognize the file format.
Next we'll put the .text section. */
.text BLOCK(4K) : ALIGN(4K)
_kernel_start = .;
.multiboot.data ALIGN(4K) :
{
*(.multiboot.data)
}
.paging.setup.text :
{
*(.paging.setup.text)
}
. += 0xC0000000;
.text ALIGN(4K) : AT (ADDR (.text) - 0xC0000000)
{
*(.multiboot)
*(.text)
}
/* Read-only data. */
.rodata BLOCK(4K) : ALIGN(4K)
.rodata ALIGN(4K) : AT (ADDR (.rodata) - 0xC0000000)
{
*(.rodata)
}
/* Read-write data (initialized) */
.data BLOCK(4K) : ALIGN(4K)
.data ALIGN(4K) : AT (ADDR (.data) - 0xC0000000)
{
*(.data)
}
/* Read-write data (uninitialized) and stack */
.bss BLOCK(4K) : ALIGN(4K)
.bss ALIGN(4K) : AT (ADDR (.bss) - 0xC0000000)
{
*(COMMON)
*(.bss)
*(.bootstrap_stack)
}
/* The compiler may produce other sections, by default it will put them in
a segment with the same name. Simply add stuff here as needed. */
_kernel_end = .;
}