Finished implementing paging init and long mode switch
This commit is contained in:
5
Makefile
5
Makefile
@@ -15,6 +15,11 @@ SRC_DIRS := core
|
||||
KERNEL_C_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c))
|
||||
KERNEL_OBJ := $(addprefix $(BUILDDIR)/,$(KERNEL_C_FILES:.c=.o))
|
||||
|
||||
BUILD_ID := $(shell tools/generate_build_id.py --arch $(ARCH))
|
||||
|
||||
CFLAGS := -DBUILD_ID=\"$(BUILD_ID)\"
|
||||
ASMFLAGS := -DBUILD_ID=\"$(BUILD_ID)\"
|
||||
|
||||
$(BUILDDIR)/$(KERNEL_EXEC): $(KERNEL_OBJ) $(ARCH_OBJ)
|
||||
@echo " \033[1;36mLINK\033[0m \033[1m$@\033[0m"
|
||||
@mkdir -p $(@D)
|
||||
|
||||
@@ -18,4 +18,6 @@ run: $(BUILDDIR)/$(KERNEL_EXEC) $(BUILDDIR)/$(KERNEL_EXEC).elf32
|
||||
debug: $(BUILDDIR)/$(KERNEL_EXEC) $(BUILDDIR)/$(KERNEL_EXEC).elf32
|
||||
@echo " \033[1;93mBOOT\033[0m $<"
|
||||
|
||||
@$(QEMU) -kernel $(BUILDDIR)/$(KERNEL_EXEC).elf32 -S -s
|
||||
@$(QEMU) \
|
||||
-kernel $(BUILDDIR)/$(KERNEL_EXEC).elf32 -S -s \
|
||||
-monitor stdio
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
.set CHECKSUM, -(MAGIC + FLAGS)
|
||||
|
||||
/* the amount of memory to allocate for bootstrap page directories. */
|
||||
/* with buffer size 0x1000 (enough for exactly one page directory)
|
||||
/* we can map 1 GiB of virtual memory */
|
||||
#define BOOTSTRAP_PDIR_SIZE 0x1000
|
||||
|
||||
.extern start_64 # defined in start_64.S
|
||||
@@ -13,12 +15,41 @@
|
||||
.code32
|
||||
|
||||
.section .boot.rodata, "a", @progbits
|
||||
|
||||
/*******
|
||||
ERROR MESSAGE STRINGS
|
||||
*******/
|
||||
no_long_mode_err:
|
||||
.asciz "This system is not 64-bit. Press any key to reboot."
|
||||
|
||||
unsupported_cpu_err:
|
||||
.asciz "Your CPU is not supported by Magenta. Press any key to reboot."
|
||||
|
||||
|
||||
/*******
|
||||
LONG MDOE BOOSTRAP GDT
|
||||
*******/
|
||||
bootstrap_gdt:
|
||||
/* 0x00: null descriptor */
|
||||
.long 0x0
|
||||
.long 0x0
|
||||
|
||||
/* 0x08: kernel code segment */
|
||||
.long 0x0000ffff
|
||||
.long 0x002f9a00
|
||||
|
||||
/* 0x10: kernel data segment */
|
||||
.long 0x0000ffff
|
||||
.long 0x002f9200
|
||||
|
||||
bootstrap_gdt_ptr:
|
||||
.word 24 /* 8 bytes for each entry in bootstrap_gdt */
|
||||
.long bootstrap_gdt
|
||||
|
||||
|
||||
/*******
|
||||
LONG MODE BOOTSTRAP PAGING STRUCTURES
|
||||
*******/
|
||||
.section .boot.bss, "aw", @nobits
|
||||
bootstrap_pml4t: # a single PML4T
|
||||
.skip 0x1000
|
||||
@@ -30,6 +61,9 @@ bootstrap_stack_bottom:
|
||||
.skip 0x1000
|
||||
bootstrap_stack_top:
|
||||
|
||||
/*******
|
||||
MULTIBOOT HEADER
|
||||
*******/
|
||||
.section .boot.text, "ax", @progbits
|
||||
.align 4
|
||||
.long MAGIC
|
||||
@@ -94,6 +128,8 @@ unsupported_cpu:
|
||||
cli
|
||||
hlt
|
||||
|
||||
.global init_page_tables
|
||||
.type init_page_tables, @function
|
||||
init_page_tables:
|
||||
/* STEP 1: add an entry in the PML4T pointing to the PDPT.
|
||||
NOTE that we actually add two entries in the PML4T that both point to the same PDPT.
|
||||
@@ -103,7 +139,7 @@ init_page_tables:
|
||||
mov $bootstrap_pdpt, %esi
|
||||
|
||||
# in %ESI, build a PML4T entry containing the base address of the PDPT
|
||||
xor $0xFFF, %esi
|
||||
and $0xFFFFF000, %esi
|
||||
or $0x3, %esi
|
||||
|
||||
# add the PML4T entries at PML4T[0] and PML4T[511]
|
||||
@@ -111,8 +147,7 @@ init_page_tables:
|
||||
add $0xFF8, %edi
|
||||
mov %esi, (%edi)
|
||||
|
||||
/* STEP 2: initialise the PDPT.
|
||||
We need to create an entry in the PDPT for every page directory we intend to use. */
|
||||
/* STEP 2: write the pgdir entries to the BEGINNING of the PDPT */
|
||||
|
||||
# BOOTSTRAP_PDIR_SIZE contains the total size of the page directory buffer.
|
||||
# use it to calculate the number of page directories we're using.
|
||||
@@ -129,22 +164,61 @@ init_page_tables:
|
||||
%EBX is where we build the PDPT entry. */
|
||||
1:
|
||||
mov %esi, %ebx
|
||||
xor $0xFFF, %ebx
|
||||
and $0xFFFFF000, %ebx
|
||||
or $0x3, %ebx
|
||||
|
||||
# skip the first 4 bytes of the 8-byte entry, leaving them zero.
|
||||
add $0x4, %edi
|
||||
mov %ebx, (%edi)
|
||||
|
||||
add $0x1000, %esi
|
||||
add $0x4, %edi
|
||||
add $0x8, %edi
|
||||
sub $0x1, %eax
|
||||
|
||||
cmp $0x0, %eax
|
||||
jne 1b
|
||||
|
||||
/* STEP 3: initialise the page directories.
|
||||
Each page directory can be used to map 2MiB of virtual memory.
|
||||
/* STEP 3: write the pgdir entries to the END of the PDPT */
|
||||
|
||||
# BOOTSTRAP_PDIR_SIZE contains the total size of the page directory buffer.
|
||||
# use it to calculate the number of page directories we're using.
|
||||
mov $0, %edx
|
||||
mov $BOOTSTRAP_PDIR_SIZE, %eax
|
||||
mov $0x1000, %ebx
|
||||
idiv %ebx
|
||||
|
||||
mov $bootstrap_pdpt, %edi
|
||||
mov $bootstrap_pdir_buf, %esi
|
||||
|
||||
/* with the number of page directories in %EAX, calculate the starting index into the PDPT.
|
||||
we need to duplicate the pgdir entries here to map the kernel at vaddr 0xffffffff80000000 and up */
|
||||
mov %eax, %ecx
|
||||
mov $0x8, %edx
|
||||
mul %edx
|
||||
xchg %eax, %ecx
|
||||
add $0x1000, %edi
|
||||
sub %ecx, %edi
|
||||
sub $0x08, %edi # subtract one from the index here, otherwise the mapping will be at 0xffffffffc0000000
|
||||
# (each entry in the array is 8 bytes long)
|
||||
|
||||
/* %ESI is a pointer into the pagedir buffer.
|
||||
%EDI is a pointer into the PDPT.
|
||||
%EAX is the total number of page directories.
|
||||
%EBX is where we build the PDPT entry. */
|
||||
2:
|
||||
mov %esi, %ebx
|
||||
and $0xFFFFF000, %ebx
|
||||
or $0x3, %ebx
|
||||
|
||||
mov %ebx, (%edi)
|
||||
|
||||
add $0x1000, %esi
|
||||
add $0x8, %edi
|
||||
sub $0x1, %eax
|
||||
|
||||
cmp $0x0, %eax
|
||||
jne 2b
|
||||
|
||||
/* STEP 4: initialise the page directories.
|
||||
Each page directory entry can be used to map 2MiB of virtual memory.
|
||||
The exact number of page directories in use is determined by BOOTSTRAP_PDIR_SIZE */
|
||||
|
||||
/* the total number of page directory entries is stored in %EAX */
|
||||
@@ -160,24 +234,55 @@ init_page_tables:
|
||||
%EAX is the total number of page directories.
|
||||
%EBX is where we build the pagedir entry. */
|
||||
|
||||
2:
|
||||
3:
|
||||
mov %esi, %ebx
|
||||
xor $0xFFF, %ebx
|
||||
or $0x3, %ebx
|
||||
and $0xFFFFF000, %ebx
|
||||
or $0x83, %ebx
|
||||
|
||||
# skip the first 4 bytes of the 8-byte entry, leaving them zero.
|
||||
add $0x4, %edi
|
||||
mov %ebx, (%edi)
|
||||
|
||||
add $0x200000, %esi
|
||||
add $0x4, %edi
|
||||
dec %eax
|
||||
jnz 2b
|
||||
add $0x8, %edi
|
||||
sub $0x1, %eax
|
||||
|
||||
cmp $0x0, %eax
|
||||
jne 3b
|
||||
|
||||
ret
|
||||
|
||||
.global long_mode_switch
|
||||
.type long_mode_switch, @function
|
||||
long_mode_switch:
|
||||
ret
|
||||
/* load %CR3 with the physical address of the PML4T */
|
||||
mov $bootstrap_pml4t, %eax
|
||||
mov %eax, %cr3
|
||||
|
||||
/* enable long mode and the syscall/sysret instructions */
|
||||
movl $0xC0000080, %ecx
|
||||
rdmsr
|
||||
orl $0x00000101, %eax
|
||||
wrmsr
|
||||
|
||||
lgdt (bootstrap_gdt_ptr)
|
||||
|
||||
mov %cr4, %ecx
|
||||
orl $0x00000020, %ecx
|
||||
mov %ecx, %cr4
|
||||
|
||||
mov %cr0, %ecx
|
||||
orl $0x8000002a, %ecx
|
||||
mov %ecx, %cr0
|
||||
|
||||
mov $0x10, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
|
||||
ljmpl $0x08, $start_64
|
||||
|
||||
cli
|
||||
hlt
|
||||
|
||||
.global _start
|
||||
.type _start, @function
|
||||
|
||||
@@ -1,10 +1,57 @@
|
||||
.code64
|
||||
|
||||
.section .boot.rodata, "a", @progbits
|
||||
|
||||
/*******
|
||||
ERROR MESSAGE STRINGS
|
||||
*******/
|
||||
kernel_identifier:
|
||||
.asciz " Socks kernel version " BUILD_ID " "
|
||||
|
||||
|
||||
.section .boot.text, "ax", @progbits
|
||||
|
||||
.code64
|
||||
print_kernel_identifier:
|
||||
/* line 1: empty padding line */
|
||||
mov $kernel_identifier, %rsi
|
||||
mov $0xb8000, %rdi
|
||||
|
||||
1:
|
||||
movw $0x7000, (%rdi) # black text on white background.
|
||||
add $0x02, %rdi
|
||||
inc %rsi
|
||||
cmpb $0, (%rsi)
|
||||
jne 1b
|
||||
|
||||
/* line 2: kernel identiifer */
|
||||
mov $kernel_identifier, %rsi
|
||||
mov $0xb80A0, %rdi
|
||||
|
||||
2:
|
||||
movsb
|
||||
movb $0x70, (%rdi) # black text on white background
|
||||
inc %rdi
|
||||
cmpb $0, (%rsi)
|
||||
jne 2b
|
||||
|
||||
|
||||
/* line 3: empty padding line */
|
||||
mov $kernel_identifier, %rsi
|
||||
mov $0xb8140, %rdi
|
||||
|
||||
1:
|
||||
movw $0x7000, (%rdi) # black text on white background.
|
||||
add $0x02, %rdi
|
||||
inc %rsi
|
||||
cmpb $0, (%rsi)
|
||||
jne 1b
|
||||
ret
|
||||
|
||||
|
||||
.global start_64
|
||||
.type start_64, @function
|
||||
start_64:
|
||||
mov $0xb8000, %rax
|
||||
movb $77, (%rax)
|
||||
inc %rax
|
||||
movb $0xF, (%rax)
|
||||
call print_kernel_identifier
|
||||
|
||||
cli
|
||||
hlt
|
||||
|
||||
36
tools/generate_build_id.py
Executable file
36
tools/generate_build_id.py
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python3
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def is_arg_set(name):
|
||||
for arg in sys.argv:
|
||||
if arg == '--{}'.format(name):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def get_arg(name):
|
||||
ret_next = False
|
||||
for arg in sys.argv:
|
||||
if ret_next:
|
||||
return arg
|
||||
|
||||
if arg == '--{}'.format(name):
|
||||
ret_next = True
|
||||
|
||||
return ''
|
||||
|
||||
|
||||
arch = get_arg('arch')
|
||||
|
||||
build_type = 'debug'
|
||||
if is_arg_set('release'):
|
||||
build_type = 'release'
|
||||
|
||||
current_tag = subprocess.check_output(['git', 'describe', '--tags', '--abbrev=0']).decode('utf-8').strip()
|
||||
current_tag = current_tag[1:]
|
||||
|
||||
build_id = '{}/{}_{}'.format(current_tag, build_type, arch)
|
||||
print('{}'.format(build_id.upper()))
|
||||
Reference in New Issue
Block a user