Enter longmode
This commit is contained in:
parent
7d2edd52f0
commit
32e1548fe0
6
Makefile
6
Makefile
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 $@"
|
||||||
|
|
139
kernel/boot.s
139
kernel/boot.s
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue