Enter longmode

This commit is contained in:
Victor Timofei 2022-05-02 17:26:07 +03:00
parent 7d2edd52f0
commit 32e1548fe0
Signed by: vtimofei
GPG Key ID: B790DCEBE281403A
6 changed files with 171 additions and 16 deletions

View File

@ -3,7 +3,7 @@ GCC_VERSION := 11.2.0
PREFIX := ${PWD}/cross PREFIX := ${PWD}/cross
CROSS_BIN := ${PREFIX}/bin CROSS_BIN := ${PREFIX}/bin
BUILD_DIR := ./build BUILD_DIR := ./build
TARGET := i686-elf TARGET := x86_64-elf
FONTS := default8x16.o FONTS := default8x16.o
BUILD_DIR_ABS := $(abspath $(BUILD_DIR)) BUILD_DIR_ABS := $(abspath $(BUILD_DIR))
@ -15,8 +15,8 @@ ISO_DIR := $(BUILD_DIR)/iso_dir
CROSS_AS := ${TARGET}-as CROSS_AS := ${TARGET}-as
CROSS_CC := ${TARGET}-gcc CROSS_CC := ${TARGET}-gcc
CROSS_LD := ${TARGET}-ld CROSS_LD := ${TARGET}-ld
CFLAGS := "-std=gnu99 -ffreestanding -O2 -Wall -Wextra -I$$PWD/kernel" CFLAGS := "-ggdb -std=gnu99 -ffreestanding -O2 -Wall -Wextra -I$$PWD/kernel -mno-red-zone"
LDFLAGS := "-ffreestanding -O2 -nostdlib -lgcc" LDFLAGS := "-ggdb -ffreestanding -O2 -nostdlib -lgcc"
export PATH := ${CROSS_BIN}:$(PATH) export PATH := ${CROSS_BIN}:$(PATH)

View File

@ -1,21 +1,24 @@
OBJECTS_GZ := $(patsubst %.o, /usr/share/kbd/consolefonts/%.psfu.gz, $(OBJECTS)) OBJECTS_GZ := $(patsubst %.o, /usr/share/kbd/consolefonts/%.psfu.gz, $(OBJECTS))
OBJECTS_PSF := $(patsubst %.o, $(BUILD_DIR)/%.psfu, $(OBJECTS)) OBJECTS_PSF := $(patsubst %.o, $(BUILD_DIR)/%.psfu, $(OBJECTS))
SYMS_PREFIX := consolefonts SYMS_PREFIX := consolefonts
OBJCOPY := x86_64-elf-objcopy
OBJTARGET := elf64-x86-64
BINARY_ARCH := i386:x86-64
.PHONY: all .PHONY: all
all: $(BUILD_DIR)/$(OBJECTS) all: $(BUILD_DIR)/$(OBJECTS)
$(BUILD_DIR)/%.o: $(OBJECTS_PSF) $(BUILD_DIR)/%.o: $(OBJECTS_PSF)
@objcopy \ @$(OBJCOPY) \
-O elf32-i386 \ -O $(OBJTARGET) \
-B i386 \ -B $(BINARY_ARCH) \
-I binary \ -I binary \
$< $@ $< $@
@./gen_srd_file.sh \ @./gen_srd_file.sh \
$<.srd \ $<.srd \
$< \ $< \
$(SYMS_PREFIX) $(SYMS_PREFIX)
@objcopy \ @$(OBJCOPY) \
--redefine-syms $<.srd \ --redefine-syms $<.srd \
$@ $@
@rm $<.srd @rm $<.srd

View File

@ -1,5 +1,5 @@
SOURCES_S := boot.s SOURCES_S := boot.s boot64.s
OBJECTS_S := $(patsubst %.s, $(BUILD_DIR)/kernel/%.o, $(SOURCES_S)) OBJECTS_S := $(patsubst %.s, $(BUILD_DIR)/kernel/%.o, $(SOURCES_S))
SOURCES_C := kernel.c SOURCES_C := kernel.c
@ -12,18 +12,21 @@ LINKER_LD := linker.ld
all: $(BUILD_DIR)/kernel.bin all: $(BUILD_DIR)/kernel.bin
$(BUILD_DIR)/kernel.bin: $(OBJECTS_S) $(OBJECTS_C) $(LINKER_LD) $(BUILD_DIR)/kernel.bin: $(OBJECTS_S) $(OBJECTS_C) $(LINKER_LD)
@$(CROSS_CC) \ @x86_64-elf-ld \
-n \
-T $(LINKER_LD) \ -T $(LINKER_LD) \
$(LDFLAGS) \
$(OBJECTS_C) \ $(OBJECTS_C) \
$(OBJECTS_S) \ $(OBJECTS_S) \
$(EXTRA_OBJS) \ $(EXTRA_OBJS) \
-o $@ -o $@
@echo "Built $@"
$(BUILD_DIR)/kernel/%.o: %.c $(SOURCES_C) $(BUILD_DIR)/kernel/%.o: %.c $(SOURCES_C)
@mkdir -p $(dir $@) @mkdir -p $(dir $@)
@$(CROSS_CC) -c $< -o $@ $(CFLAGS) @$(CROSS_CC) -c $< -o $@ $(CFLAGS)
@echo "Built $@"
$(BUILD_DIR)/kernel/%.o: %.s $(SOURCES_S) $(BUILD_DIR)/kernel/%.o: %.s $(SOURCES_S)
@mkdir -p $(dir $@) @mkdir -p $(dir $@)
@$(CROSS_AS) $< -o $@ @$(CROSS_AS) $< -o $@
@echo "Built $@"

View File

@ -30,6 +30,7 @@ search for this signature in the first 8 KiB of the kernel file, aligned at a
forced to be within the first 8 KiB of the kernel file. forced to be within the first 8 KiB of the kernel file.
*/ */
.section .multiboot .section .multiboot
.code32
.align 4 .align 4
.long MAGIC .long MAGIC
.long FLAGS .long FLAGS
@ -73,19 +74,56 @@ 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 stack is properly aligned and failure to align the stack will result in
undefined behavior. undefined behavior.
*/ */
/* GDT varibles */
.set GDT_ZERO_ENTRY, 0x0
.set GDT_EXECUTABLE_FLAG, 1<<43
.set GDT_CODE_AND_DATA_FLAG, 1<<44
.set GDT_PRESENT_FLAG, 1<<47
.set GDT_64_BIT_FLAG, 1<<53
.set GDT_FLAGS, GDT_EXECUTABLE_FLAG | GDT_CODE_AND_DATA_FLAG | GDT_PRESENT_FLAG | GDT_64_BIT_FLAG
.section .bss .section .bss
.align 16 /* We will be using hugepages, so we will need only 3 page levels. */
.align 4096
page_table_l4:
.skip 4096
page_table_l3:
.skip 4096
page_table_l2:
.skip 4096
page_table_l3_framebuffer:
.skip 4096
page_table_l2_framebuffer:
.skip 4096
stack_bottom: stack_bottom:
.skip 16384 # 16 KiB .skip 4096 * 4
stack_top: stack_top:
.section .rodata
.align 4
gdt64:
.quad GDT_ZERO_ENTRY
.set gdt64_code_segment, . - gdt64
.quad GDT_FLAGS
/*
gdt64_data_entry:
.set gdt64_data_segment, gdt64_data_entry - gdt64
.quad (1<<44) | (1<<46) | (1<<41)
*/
gdt64_pointer:
.word . - gdt64 - 1
.quad gdt64
/* /*
The linker script specifies _start as the entry point to the kernel and the 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 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. doesn't make sense to return from this function as the bootloader is gone.
*/ */
.section .text .section .text
.code32
.global _start .global _start
.extern long_mode_start
.type _start, @function .type _start, @function
_start: _start:
/* /*
@ -126,8 +164,12 @@ _start:
since (pushed 0 bytes so far), so the alignment has thus been since (pushed 0 bytes so far), so the alignment has thus been
preserved and the call is well defined. preserved and the call is well defined.
*/ */
pushl %ebx /* pass the Multiboot Info struct addr to kernel_main */ call setup_page_tables
call kernel_main call setup_framebuffer_page_tables
call enable_paging
lgdt (gdt64_pointer)
ljmp $gdt64_code_segment, $long_mode_start
/* /*
If the system has nothing more to do, put the computer into an If the system has nothing more to do, put the computer into an
@ -150,3 +192,92 @@ 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. This is useful when debugging or when you implement call tracing.
*/ */
.size _start, . - _start .size _start, . - _start
setup_page_tables:
movl $page_table_l3, %eax
orl $0b11, %eax /* flags are present and writable */
movl %eax, page_table_l4 /* set page_table_l4 first entry to point to page_table_l3 */
/* Same for next level */
movl $page_table_l2, %eax
orl $0b11, %eax
movl %eax, page_table_l3
/* Huge pages of size 2 MiBs */
movl $0, %ecx
.loop:
movl $0x200000, %eax
mul %ecx
/* present, writable, hugepage */
orl $0b10000011, %eax
movl %eax, page_table_l2(, %ecx, 8)
inc %ecx
cmp $512, %ecx
jne .loop
ret
setup_framebuffer_page_tables:
/* Get the multiboot struct address */
movl %ebx, %edx
/*
Offset to the framebuffer member. framebuffer[31:0] bits
*/
add $88, %edx
movl (%edx), %edx
/* L4 */
movl %edx, %ecx
shr $30, %ecx
and $0b111111111, %ecx
and $0xC0000000, %edx /* We will start mapping from this address */
movl $page_table_l2_framebuffer, %eax
orl $0b11, %eax
movl %eax, page_table_l3(, %ecx, 8)
/* Huge pages of size 2 MiBs */
movl $0, %ecx
.loop2:
movl $0x200000, %eax
imul %ecx, %eax
orl %edx, %eax
/* present, writable, hugepage */
orl $0b10000011, %eax
movl %eax, page_table_l2_framebuffer(, %ecx, 8)
inc %ecx
cmp $512, %ecx
jne .loop2
ret
enable_paging:
/* pass page table location to CR3 */
movl $page_table_l4, %eax
movl %eax, %cr3
/* Enable Physical Address Extension */
movl %cr4, %eax
orl $(1<<5), %eax
mov %eax, %cr4
/* Enable long mode */
mov $0xC0000080, %ecx
rdmsr
orl $(1<<8), %eax
wrmsr
/* Enable paging */
movl %cr0, %eax
orl $(1<<31), %eax
mov %eax, %cr0
ret

18
kernel/boot64.s Normal file
View File

@ -0,0 +1,18 @@
.global long_mode_start
.extern kernel_main
.section .text
.code64
long_mode_start:
movw $0, %ax
movw %ax, %ss
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
/* We should keep the pointer to mb, debug needed */
push %rbx /* Multiboot struct pointer */
mov %rbx, %rdi
call kernel_main
hlt

View File

@ -6,8 +6,8 @@
#error "You are not using a cross-compiler, you will most certainly run into trouble" #error "You are not using a cross-compiler, you will most certainly run into trouble"
#endif #endif
#if !defined (__i386__) #if !defined (__x86_64__)
#error "The kernel needs to be compiled with a ix86-elf compiler" #error "The kernel needs to be compiled with a x86_64-elf compiler"
#endif #endif
/* graphics framebuffer */ /* graphics framebuffer */