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_C_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c))
|
||||||
KERNEL_OBJ := $(addprefix $(BUILDDIR)/,$(KERNEL_C_FILES:.c=.o))
|
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)
|
$(BUILDDIR)/$(KERNEL_EXEC): $(KERNEL_OBJ) $(ARCH_OBJ)
|
||||||
@echo " \033[1;36mLINK\033[0m \033[1m$@\033[0m"
|
@echo " \033[1;36mLINK\033[0m \033[1m$@\033[0m"
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
|
|||||||
@@ -18,4 +18,6 @@ run: $(BUILDDIR)/$(KERNEL_EXEC) $(BUILDDIR)/$(KERNEL_EXEC).elf32
|
|||||||
debug: $(BUILDDIR)/$(KERNEL_EXEC) $(BUILDDIR)/$(KERNEL_EXEC).elf32
|
debug: $(BUILDDIR)/$(KERNEL_EXEC) $(BUILDDIR)/$(KERNEL_EXEC).elf32
|
||||||
@echo " \033[1;93mBOOT\033[0m $<"
|
@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)
|
.set CHECKSUM, -(MAGIC + FLAGS)
|
||||||
|
|
||||||
/* the amount of memory to allocate for bootstrap page directories. */
|
/* 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
|
#define BOOTSTRAP_PDIR_SIZE 0x1000
|
||||||
|
|
||||||
.extern start_64 # defined in start_64.S
|
.extern start_64 # defined in start_64.S
|
||||||
@@ -13,12 +15,41 @@
|
|||||||
.code32
|
.code32
|
||||||
|
|
||||||
.section .boot.rodata, "a", @progbits
|
.section .boot.rodata, "a", @progbits
|
||||||
|
|
||||||
|
/*******
|
||||||
|
ERROR MESSAGE STRINGS
|
||||||
|
*******/
|
||||||
no_long_mode_err:
|
no_long_mode_err:
|
||||||
.asciz "This system is not 64-bit. Press any key to reboot."
|
.asciz "This system is not 64-bit. Press any key to reboot."
|
||||||
|
|
||||||
unsupported_cpu_err:
|
unsupported_cpu_err:
|
||||||
.asciz "Your CPU is not supported by Magenta. Press any key to reboot."
|
.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
|
.section .boot.bss, "aw", @nobits
|
||||||
bootstrap_pml4t: # a single PML4T
|
bootstrap_pml4t: # a single PML4T
|
||||||
.skip 0x1000
|
.skip 0x1000
|
||||||
@@ -30,6 +61,9 @@ bootstrap_stack_bottom:
|
|||||||
.skip 0x1000
|
.skip 0x1000
|
||||||
bootstrap_stack_top:
|
bootstrap_stack_top:
|
||||||
|
|
||||||
|
/*******
|
||||||
|
MULTIBOOT HEADER
|
||||||
|
*******/
|
||||||
.section .boot.text, "ax", @progbits
|
.section .boot.text, "ax", @progbits
|
||||||
.align 4
|
.align 4
|
||||||
.long MAGIC
|
.long MAGIC
|
||||||
@@ -94,6 +128,8 @@ unsupported_cpu:
|
|||||||
cli
|
cli
|
||||||
hlt
|
hlt
|
||||||
|
|
||||||
|
.global init_page_tables
|
||||||
|
.type init_page_tables, @function
|
||||||
init_page_tables:
|
init_page_tables:
|
||||||
/* STEP 1: add an entry in the PML4T pointing to the PDPT.
|
/* 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.
|
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
|
mov $bootstrap_pdpt, %esi
|
||||||
|
|
||||||
# in %ESI, build a PML4T entry containing the base address of the PDPT
|
# in %ESI, build a PML4T entry containing the base address of the PDPT
|
||||||
xor $0xFFF, %esi
|
and $0xFFFFF000, %esi
|
||||||
or $0x3, %esi
|
or $0x3, %esi
|
||||||
|
|
||||||
# add the PML4T entries at PML4T[0] and PML4T[511]
|
# add the PML4T entries at PML4T[0] and PML4T[511]
|
||||||
@@ -111,8 +147,7 @@ init_page_tables:
|
|||||||
add $0xFF8, %edi
|
add $0xFF8, %edi
|
||||||
mov %esi, (%edi)
|
mov %esi, (%edi)
|
||||||
|
|
||||||
/* STEP 2: initialise the PDPT.
|
/* STEP 2: write the pgdir entries to the BEGINNING of the PDPT */
|
||||||
We need to create an entry in the PDPT for every page directory we intend to use. */
|
|
||||||
|
|
||||||
# BOOTSTRAP_PDIR_SIZE contains the total size of the page directory buffer.
|
# BOOTSTRAP_PDIR_SIZE contains the total size of the page directory buffer.
|
||||||
# use it to calculate the number of page directories we're using.
|
# 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. */
|
%EBX is where we build the PDPT entry. */
|
||||||
1:
|
1:
|
||||||
mov %esi, %ebx
|
mov %esi, %ebx
|
||||||
xor $0xFFF, %ebx
|
and $0xFFFFF000, %ebx
|
||||||
or $0x3, %ebx
|
or $0x3, %ebx
|
||||||
|
|
||||||
# skip the first 4 bytes of the 8-byte entry, leaving them zero.
|
|
||||||
add $0x4, %edi
|
|
||||||
mov %ebx, (%edi)
|
mov %ebx, (%edi)
|
||||||
|
|
||||||
add $0x1000, %esi
|
add $0x1000, %esi
|
||||||
add $0x4, %edi
|
add $0x8, %edi
|
||||||
sub $0x1, %eax
|
sub $0x1, %eax
|
||||||
|
|
||||||
cmp $0x0, %eax
|
cmp $0x0, %eax
|
||||||
jne 1b
|
jne 1b
|
||||||
|
|
||||||
/* STEP 3: initialise the page directories.
|
/* STEP 3: write the pgdir entries to the END of the PDPT */
|
||||||
Each page directory can be used to map 2MiB of virtual memory.
|
|
||||||
|
# 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 exact number of page directories in use is determined by BOOTSTRAP_PDIR_SIZE */
|
||||||
|
|
||||||
/* the total number of page directory entries is stored in %EAX */
|
/* 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.
|
%EAX is the total number of page directories.
|
||||||
%EBX is where we build the pagedir entry. */
|
%EBX is where we build the pagedir entry. */
|
||||||
|
|
||||||
2:
|
3:
|
||||||
mov %esi, %ebx
|
mov %esi, %ebx
|
||||||
xor $0xFFF, %ebx
|
and $0xFFFFF000, %ebx
|
||||||
or $0x3, %ebx
|
or $0x83, %ebx
|
||||||
|
|
||||||
# skip the first 4 bytes of the 8-byte entry, leaving them zero.
|
|
||||||
add $0x4, %edi
|
|
||||||
mov %ebx, (%edi)
|
mov %ebx, (%edi)
|
||||||
|
|
||||||
add $0x200000, %esi
|
add $0x200000, %esi
|
||||||
add $0x4, %edi
|
add $0x8, %edi
|
||||||
dec %eax
|
sub $0x1, %eax
|
||||||
jnz 2b
|
|
||||||
|
cmp $0x0, %eax
|
||||||
|
jne 3b
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
.global long_mode_switch
|
||||||
|
.type long_mode_switch, @function
|
||||||
long_mode_switch:
|
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
|
.global _start
|
||||||
.type _start, @function
|
.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
|
.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
|
.global start_64
|
||||||
.type start_64, @function
|
.type start_64, @function
|
||||||
start_64:
|
start_64:
|
||||||
mov $0xb8000, %rax
|
call print_kernel_identifier
|
||||||
movb $77, (%rax)
|
|
||||||
inc %rax
|
cli
|
||||||
movb $0xF, (%rax)
|
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