diff --git a/CMakeLists.txt b/CMakeLists.txt index fbaf0cd1..b4fbd9b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,23 @@ cmake_minimum_required(VERSION 3.20) -project(dragonOS C) +set(CMAKE_VERBOSE_MAKEFILE on) + +set(DRAGONOS_ARCH "x86_64") + +mark_as_advanced(CMAKE_INSTALL_PREFIX) + +set(CROSS_COMPILE "${DRAGONOS_ARCH}-linux-gnu-") +set(CMAKE_C_COMPILER "${CROSS_COMPILE}gcc") +set(CMAKE_ASM_COMPILER "${CROSS_COMPILE}gcc") +enable_language(ASM ASM_NASM) + +set(CMAKE_C_FLAGS + "-Wall -fPIC -nostdlib -nostartfiles -ffreestanding ") + + +project(dragonOS C ASM) set(CMAKE_C_STANDARD 11) add_subdirectory(bootloader) +add_subdirectory(kernel) +include_directories(kernel) diff --git a/bootloader/loader.asm b/bootloader/loader.asm index 43d4e9d6..aeb0c1c8 100644 --- a/bootloader/loader.asm +++ b/bootloader/loader.asm @@ -619,7 +619,7 @@ GO_TO_TMP_Protect: mov cr3, eax ; ==== 启用长模式 === - ; 参见英特尔开发手册合集p4360 volume4, chapter2 2-60 Vol. 4 + ; 参见英特尔开发手册合集p4360 volume4, chapter2 页码2-60 Vol. 4 ; IA32_EFER寄存器的第8位是LME标志位,能启用IA-32e模式 mov ecx, 0xC0000080 rdmsr diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt new file mode 100644 index 00000000..8dea833c --- /dev/null +++ b/kernel/CMakeLists.txt @@ -0,0 +1,18 @@ + + +#修改输出的路径 +set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/kernel) +# 添加汇编包含目录(当前文件夹) +add_compile_options(-I ${CMAKE_CURRENT_SOURCE_DIR}/ ) + +add_library(${PROJECT_NAME}-arch + head.S + main.c) +add_executable(kernel.bin + head.S main.c) +set_property( + TARGET kernel.bin + PROPERTY + DEPENDS + "link.lds" +) \ No newline at end of file diff --git a/kernel/head.S b/kernel/head.S new file mode 100644 index 00000000..f8e2c07a --- /dev/null +++ b/kernel/head.S @@ -0,0 +1,142 @@ +// 这是内核执行头程序 +// Created by longjin. +// 2022/01/20 + +.section .text + +.global _start + +_start: + // 初始化寄存器 + mov $0x10, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %ss + + mov $0x7e00, %esp + +// === 加载GDTR ==== + lgdt GDT_POINTER(%rip) //这里我没搞明白rip相对寻址, 看了文档,大概是用来实现PIC的(position independent code) +// === 加载IDTR ==== + lidt IDT_POINTER(%rip) + mov $0x10, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %ss + mov %ax, %gs + + movq $0x7e00, %rsp + +// ==== 加载CR3寄存器 + movq $0x101000, %rax //设置页目录基地址 + movq %rax, %cr3 + movq switch_seg(%rip), %rax + + // 由于ljmp和lcall在GAS中不受支持,因此我们需要先伪造函数调用现场,通过lret的方式,给它跳转过去。才能更新cs寄存器 + // 实在是太妙了!Amazing! + pushq $0x08 //段选择子 + pushq %rax + lretq + +// 64位模式的代码 +switch_seg: + .quad entry64 + +entry64: + movq $0x10, %rax + movq %rax, %ds + movq %rax, %es + movq %rax, %gs + movq %rax, %ss + + movq $0xffff800000007e00, %rsp //rsp的地址 + + // 切换到内核主程序 + movq go_to_kernel(%rip), %rax + pushq $0x08 + pushq %rax + lretq + +go_to_kernel: + .quad Start_Kernel + + + +// 初始化页表 +.align 8 //设置为8byte对齐 +.org 0x1000 //设置页表位置为内核执行头程序的0x1000处 + +__PML4E: + .quad 0x102007 // 系统访问,可读写,已存在, 地址在31~12位 + .fill 255,8,0 + .quad 0x102007 + .fill 255,8,0 + +.org 0x2000 + +__PDPTE: + + .quad 0x103003 // 用户访问,可读写,已存在 + .fill 511,8,0 + +.org 0x3000 + +__PDE: + + .quad 0x000083 // 用户访问,可读写,已存在 + .quad 0x200083 + .quad 0x400083 + .quad 0x600083 + .quad 0x800083 + .quad 0xe0000083 /*0x a00000*/ + .quad 0xe0200083 + .quad 0xe0400083 + .quad 0xe0600083 /*0x1000000*/ + .quad 0xe0800083 + .quad 0xe0a00083 + .quad 0xe0c00083 + .quad 0xe0e00083 + .fill 499,8,0 + +// GDT表 +.section .data +.global GDT_Table // 使得GDT可以被外部程序引用或者访问 + +GDT_Table: + .quad 0x0000000000000000 // 0 空描述符 00 + .quad 0x0020980000000000 // 1 内核64位代码段描述符 08 + .quad 0x0000920000000000 // 2 内核64位数据段描述符 10 + .quad 0x0020f80000000000 // 3 用户64位代码段描述符 18 + .quad 0x0000f20000000000 // 4 用户64位数据段描述符 20 + .quad 0x00cf9a000000ffff // 5 内核32位代码段描述符 28 + .quad 0x00cf92000000ffff // 6 内核32位数据段描述符 30 + .fill 10, 8, 0 // 8~9 TSS(跳过了第七段) 重复十次填充8字节的空间,赋值为0 +GDT_END: + +GDT_POINTER: +GDT_LIMIT: .word GDT_END - GDT_Table - 1 // GDT的大小 +GDT_BASE: .quad GDT_Table + +// IDT 表 +.global IDT_Table + +IDT_Table: + .fill 512, 8, 0 // 设置512*8字节的IDT表的空间 +IDT_END: + +IDT_POINTER: +IDT_LIMIT: .word IDT_END - IDT_Table - 1 +IDT_BASE: .quad IDT_Table + +// 64位的TSS表 +.global TSS64_Table + +TSS64_Table: + .fill 13, 8, 0 +TSS64_END: + +TSS64_POINTER: +TSS64_LIMIT: .word TSS64_END - TSS64_Table - 1 +TSS64_BASE: .quad TSS64_Table diff --git a/kernel/main.c b/kernel/main.c new file mode 100644 index 00000000..04fdc1bc --- /dev/null +++ b/kernel/main.c @@ -0,0 +1,11 @@ +// +// Created by longjin on 2022/1/20. +// + +void Start_Kernel(void) +{ + while(1) + { + + }; +} diff --git a/run_in_qemu.sh b/run_in_qemu.sh index 4ba57f53..f7b8935c 100644 --- a/run_in_qemu.sh +++ b/run_in_qemu.sh @@ -43,7 +43,7 @@ fi # ========把loader.bin复制到boot.img========== cp bin/bootloader/loader.bin tmp/boot # ========把内核程序复制到boot.img====== - cp bin/bootloader/kernel.bin tmp/boot + cp bin/kernel/kernel.bin tmp/boot sync # 卸载磁盘 umount tmp/boot