2022-01-21 03:43:13 +00:00
|
|
|
|
// 这是内核执行头程序
|
|
|
|
|
|
// Created by longjin.
|
|
|
|
|
|
// 2022/01/20
|
|
|
|
|
|
|
2022-02-10 05:45:38 +00:00
|
|
|
|
#include "common/asm.h"
|
|
|
|
|
|
|
2022-01-21 03:43:13 +00:00
|
|
|
|
|
2022-02-21 06:39:48 +00:00
|
|
|
|
// 以下是来自 multiboot2 规范的定义
|
|
|
|
|
|
// How many bytes from the start of the file we search for the header.
|
|
|
|
|
|
#define MULTIBOOT_SEARCH 32768
|
|
|
|
|
|
#define MULTIBOOT_HEADER_ALIGN 8
|
|
|
|
|
|
|
|
|
|
|
|
// The magic field should contain this.
|
|
|
|
|
|
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
|
|
|
|
|
|
|
|
|
|
|
|
// This should be in %eax.
|
|
|
|
|
|
#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
|
|
|
|
|
|
|
|
|
|
|
|
// Alignment of multiboot modules.
|
|
|
|
|
|
#define MULTIBOOT_MOD_ALIGN 0x00001000
|
|
|
|
|
|
|
|
|
|
|
|
// Alignment of the multiboot info structure.
|
|
|
|
|
|
#define MULTIBOOT_INFO_ALIGN 0x00000008
|
|
|
|
|
|
|
|
|
|
|
|
// Flags set in the 'flags' member of the multiboot header.
|
|
|
|
|
|
|
|
|
|
|
|
#define MULTIBOOT_TAG_ALIGN 8
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_END 0
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_MODULE 3
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_MMAP 6
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_VBE 7
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_APM 10
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_EFI32 11
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_EFI64 12
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_SMBIOS 13
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_NETWORK 16
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
|
|
|
|
|
|
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_END 0
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_EFI_BS 7
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
|
|
|
|
|
|
|
|
|
|
|
|
#define MULTIBOOT_ARCHITECTURE_I386 0
|
|
|
|
|
|
#define MULTIBOOT_ARCHITECTURE_MIPS32 4
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
|
|
|
|
|
|
|
|
|
|
|
|
#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
|
|
|
|
|
|
#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
|
|
|
|
|
|
#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
|
|
|
|
|
|
|
|
|
|
|
|
#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
|
|
|
|
|
|
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-02-21 14:59:57 +00:00
|
|
|
|
// 以下是来自 multiboot2 规范的定义
|
|
|
|
|
|
// How many bytes from the start of the file we search for the header.
|
|
|
|
|
|
#define MULTIBOOT_SEARCH 32768
|
|
|
|
|
|
#define MULTIBOOT_HEADER_ALIGN 8
|
|
|
|
|
|
|
|
|
|
|
|
// The magic field should contain this.
|
|
|
|
|
|
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
|
|
|
|
|
|
|
|
|
|
|
|
// This should be in %eax.
|
|
|
|
|
|
#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
|
|
|
|
|
|
|
|
|
|
|
|
// Alignment of multiboot modules.
|
|
|
|
|
|
#define MULTIBOOT_MOD_ALIGN 0x00001000
|
|
|
|
|
|
|
|
|
|
|
|
// Alignment of the multiboot info structure.
|
|
|
|
|
|
#define MULTIBOOT_INFO_ALIGN 0x00000008
|
|
|
|
|
|
|
|
|
|
|
|
// Flags set in the 'flags' member of the multiboot header.
|
|
|
|
|
|
|
|
|
|
|
|
#define MULTIBOOT_TAG_ALIGN 8
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_END 0
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_MODULE 3
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_MMAP 6
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_VBE 7
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_APM 10
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_EFI32 11
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_EFI64 12
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_SMBIOS 13
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_NETWORK 16
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
|
|
|
|
|
|
#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
|
|
|
|
|
|
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_END 0
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_EFI_BS 7
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
|
|
|
|
|
|
|
|
|
|
|
|
#define MULTIBOOT_ARCHITECTURE_I386 0
|
|
|
|
|
|
#define MULTIBOOT_ARCHITECTURE_MIPS32 4
|
|
|
|
|
|
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
|
|
|
|
|
|
|
|
|
|
|
|
#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
|
|
|
|
|
|
#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
|
|
|
|
|
|
#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
|
|
|
|
|
|
|
|
|
|
|
|
#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
|
|
|
|
|
|
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-02-21 06:39:48 +00:00
|
|
|
|
// 直接用 -m64 编译出来的是 64 位代码,
|
|
|
|
|
|
// 但是启动后的机器是 32 位的,相当于在 32 位机器上跑 64 位程序。
|
|
|
|
|
|
// 得加一层跳转到 64 位的 -m32 代码,开启 long 模式后再跳转到以 -m64 编译的代码中
|
|
|
|
|
|
// 对于 x86_64,需要在启动阶段进入长模式(IA32E),这意味着需要一个临时页表
|
|
|
|
|
|
// See https://wiki.osdev.org/Creating_a_64-bit_kernel:
|
|
|
|
|
|
// With a 32-bit bootstrap in your kernel
|
|
|
|
|
|
|
|
|
|
|
|
// 这部分是从保护模式启动 long 模式的代码
|
|
|
|
|
|
// 工作在 32bit
|
|
|
|
|
|
// 声明这一段代码以 32 位模式编译
|
|
|
|
|
|
.code32
|
|
|
|
|
|
|
|
|
|
|
|
// multiboot2 文件头
|
|
|
|
|
|
// 计算头长度
|
|
|
|
|
|
.SET HEADER_LENGTH, multiboot_header_end - multiboot_header
|
|
|
|
|
|
// 计算校验和
|
|
|
|
|
|
.SET CHECKSUM, -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + HEADER_LENGTH)
|
|
|
|
|
|
// 8 字节对齐
|
|
|
|
|
|
.align MULTIBOOT_HEADER_ALIGN
|
|
|
|
|
|
// 声明所属段
|
|
|
|
|
|
.section .multiboot_header
|
|
|
|
|
|
multiboot_header:
|
|
|
|
|
|
// 魔数
|
|
|
|
|
|
.long MULTIBOOT2_HEADER_MAGIC
|
|
|
|
|
|
// 架构
|
|
|
|
|
|
.long MULTIBOOT_ARCHITECTURE_I386
|
|
|
|
|
|
// 头长度
|
|
|
|
|
|
.long HEADER_LENGTH
|
|
|
|
|
|
// 校验和
|
|
|
|
|
|
.long CHECKSUM
|
|
|
|
|
|
// 添加其它内容在此,详细信息见 Multiboot2 Specification version 2.0.pdf
|
2022-02-21 14:59:57 +00:00
|
|
|
|
|
|
|
|
|
|
// 设置帧缓冲区
|
|
|
|
|
|
.align 8
|
|
|
|
|
|
framebuffer_tag_start:
|
|
|
|
|
|
.short MULTIBOOT_HEADER_TAG_FRAMEBUFFER
|
|
|
|
|
|
.short MULTIBOOT_HEADER_TAG_OPTIONAL
|
|
|
|
|
|
.long framebuffer_tag_end - framebuffer_tag_start
|
|
|
|
|
|
.long 1440
|
|
|
|
|
|
.long 900
|
|
|
|
|
|
.long 32
|
|
|
|
|
|
framebuffer_tag_end:
|
|
|
|
|
|
.align 8
|
2022-02-21 06:39:48 +00:00
|
|
|
|
.short MULTIBOOT_HEADER_TAG_END
|
|
|
|
|
|
// 结束标记
|
|
|
|
|
|
.short 0
|
|
|
|
|
|
.long 8
|
|
|
|
|
|
multiboot_header_end:
|
|
|
|
|
|
|
2022-02-21 14:59:57 +00:00
|
|
|
|
|
2022-02-21 06:39:48 +00:00
|
|
|
|
// 临时页表 4KB/页
|
|
|
|
|
|
.section .data
|
|
|
|
|
|
.align 0x1000
|
|
|
|
|
|
pml4:
|
|
|
|
|
|
.skip 0x1000
|
|
|
|
|
|
pdpt:
|
|
|
|
|
|
.skip 0x1000
|
|
|
|
|
|
pd:
|
|
|
|
|
|
.skip 0x1000
|
|
|
|
|
|
pt:
|
|
|
|
|
|
.skip 0x1000
|
|
|
|
|
|
|
|
|
|
|
|
// 临时 GDT
|
|
|
|
|
|
.align 16
|
|
|
|
|
|
gdt64:
|
|
|
|
|
|
null_desc:
|
|
|
|
|
|
.short 0xFFFF
|
|
|
|
|
|
.short 0
|
|
|
|
|
|
.byte 0
|
|
|
|
|
|
.byte 0
|
|
|
|
|
|
.byte 0
|
|
|
|
|
|
.byte 0
|
|
|
|
|
|
code_desc:
|
|
|
|
|
|
.short 0
|
|
|
|
|
|
.short 0
|
|
|
|
|
|
.byte 0
|
|
|
|
|
|
.byte 0x9A
|
|
|
|
|
|
.byte 0x20
|
|
|
|
|
|
.byte 0
|
|
|
|
|
|
data_desc:
|
|
|
|
|
|
.short 0
|
|
|
|
|
|
.short 0
|
|
|
|
|
|
.byte 0
|
|
|
|
|
|
.byte 0x92
|
|
|
|
|
|
.byte 0
|
|
|
|
|
|
.byte 0
|
|
|
|
|
|
user_code_desc:
|
|
|
|
|
|
.short 0
|
|
|
|
|
|
.short 0
|
|
|
|
|
|
.byte 0
|
|
|
|
|
|
.byte 0xFA
|
|
|
|
|
|
.byte 0x20
|
|
|
|
|
|
.byte 0
|
|
|
|
|
|
user_data_desc:
|
|
|
|
|
|
.short 0
|
|
|
|
|
|
.short 0
|
|
|
|
|
|
.byte 0
|
|
|
|
|
|
.byte 0xF2
|
|
|
|
|
|
.byte 0
|
|
|
|
|
|
.byte 0
|
|
|
|
|
|
gdt64_pointer:
|
|
|
|
|
|
.short gdt64_pointer-gdt64-1
|
|
|
|
|
|
.quad gdt64
|
|
|
|
|
|
gdt64_pointer64:
|
|
|
|
|
|
.short gdt64_pointer-gdt64-1
|
|
|
|
|
|
.quad gdt64
|
2022-01-21 03:43:13 +00:00
|
|
|
|
|
2022-02-21 06:39:48 +00:00
|
|
|
|
.section .text
|
|
|
|
|
|
.global _start
|
|
|
|
|
|
.type _start, @function
|
|
|
|
|
|
# 在 multiboot2.cpp 中定义
|
|
|
|
|
|
.extern boot_info_addr
|
|
|
|
|
|
.extern multiboot2_magic
|
2022-02-21 14:59:57 +00:00
|
|
|
|
.extern _start64
|
2022-01-21 03:43:13 +00:00
|
|
|
|
_start:
|
2022-02-21 06:39:48 +00:00
|
|
|
|
// 关中断
|
|
|
|
|
|
cli
|
|
|
|
|
|
// multiboot2_info 结构体指针
|
2022-02-21 14:59:57 +00:00
|
|
|
|
mov %ebx, boot_info_addr
|
2022-02-21 06:39:48 +00:00
|
|
|
|
// 魔数
|
2022-02-21 14:59:57 +00:00
|
|
|
|
mov %eax, multiboot2_magic
|
2022-02-21 06:39:48 +00:00
|
|
|
|
/ 从保护模式跳转到长模式
|
|
|
|
|
|
// 1. 允许 PAE
|
|
|
|
|
|
mov %cr4, %eax
|
|
|
|
|
|
or $(1<<5), %eax
|
|
|
|
|
|
mov %eax, %cr4
|
|
|
|
|
|
// 2. 设置临时页表
|
|
|
|
|
|
// 最高级
|
|
|
|
|
|
mov $pml4, %eax
|
|
|
|
|
|
mov $pdpt, %ebx
|
|
|
|
|
|
or $0x3, %ebx
|
|
|
|
|
|
mov %ebx, 0(%eax)
|
|
|
|
|
|
|
|
|
|
|
|
// 次级
|
|
|
|
|
|
mov $pdpt, %eax
|
|
|
|
|
|
mov $pd, %ebx
|
|
|
|
|
|
or $0x3, %ebx
|
|
|
|
|
|
mov %ebx, 0(%eax)
|
|
|
|
|
|
|
|
|
|
|
|
// 次低级
|
|
|
|
|
|
mov $pd, %eax
|
|
|
|
|
|
mov $pt, %ebx
|
|
|
|
|
|
or $0x3, %ebx
|
|
|
|
|
|
mov %ebx, 0(%eax)
|
|
|
|
|
|
|
|
|
|
|
|
// 最低级
|
|
|
|
|
|
// 循环 512 次,填满一页
|
|
|
|
|
|
mov $512, %ecx
|
|
|
|
|
|
mov $pt, %eax
|
|
|
|
|
|
mov $0x3, %ebx
|
|
|
|
|
|
.fill_pt:
|
|
|
|
|
|
mov %ebx, 0(%eax)
|
|
|
|
|
|
add $0x1000, %ebx
|
|
|
|
|
|
add $8, %eax
|
|
|
|
|
|
loop .fill_pt
|
|
|
|
|
|
|
|
|
|
|
|
// 填写 CR3
|
|
|
|
|
|
mov $pml4, %eax
|
|
|
|
|
|
mov %eax, %cr3
|
|
|
|
|
|
|
|
|
|
|
|
// 3. 切换到 long 模式
|
|
|
|
|
|
mov $0xC0000080, %ecx
|
|
|
|
|
|
rdmsr
|
|
|
|
|
|
or $(1<<8), %eax
|
|
|
|
|
|
wrmsr
|
|
|
|
|
|
|
|
|
|
|
|
// 4. 开启分页
|
|
|
|
|
|
mov %cr0, %eax
|
|
|
|
|
|
or $(1<<31), %eax
|
|
|
|
|
|
mov %eax, %cr0
|
|
|
|
|
|
|
|
|
|
|
|
// 5. 重新设置 GDT
|
|
|
|
|
|
mov $gdt64_pointer, %eax
|
|
|
|
|
|
lgdt 0(%eax)
|
|
|
|
|
|
|
|
|
|
|
|
// 6. 跳转到 64 位代码执行
|
|
|
|
|
|
jmp $0x8, $_start64
|
|
|
|
|
|
hlt
|
|
|
|
|
|
ret
|
|
|
|
|
|
|
2022-02-21 14:59:57 +00:00
|
|
|
|
|
2022-02-21 06:39:48 +00:00
|
|
|
|
.section .text
|
|
|
|
|
|
|
|
|
|
|
|
.code64
|
|
|
|
|
|
.global _start64
|
|
|
|
|
|
.type _start64, @function
|
|
|
|
|
|
.extern Start_Kernel
|
|
|
|
|
|
ENTRY(_start64)
|
2022-01-21 03:43:13 +00:00
|
|
|
|
// 初始化寄存器
|
|
|
|
|
|
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
|
2022-02-21 06:39:48 +00:00
|
|
|
|
|
2022-01-21 03:43:13 +00:00
|
|
|
|
movq $0x7e00, %rsp
|
2022-02-21 06:39:48 +00:00
|
|
|
|
|
|
|
|
|
|
// 2. 设置临时页表
|
|
|
|
|
|
// 最高级
|
|
|
|
|
|
mov $__PML4E, %eax
|
|
|
|
|
|
mov $__PDPTE, %ebx
|
2022-03-01 12:21:32 +00:00
|
|
|
|
or $0x3, %ebx
|
2022-02-21 06:39:48 +00:00
|
|
|
|
mov %ebx, 0(%eax)
|
|
|
|
|
|
|
|
|
|
|
|
// 次级
|
|
|
|
|
|
mov $__PDPTE, %eax
|
|
|
|
|
|
mov $__PDE, %ebx
|
2022-03-01 12:21:32 +00:00
|
|
|
|
or $0x3, %ebx
|
2022-02-21 06:39:48 +00:00
|
|
|
|
mov %ebx, 0(%eax)
|
2022-02-21 14:59:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
2022-01-21 03:43:13 +00:00
|
|
|
|
// ==== 加载CR3寄存器
|
2022-02-21 06:39:48 +00:00
|
|
|
|
movq $__PML4E, %rax //设置页目录基地址
|
2022-01-21 03:43:13 +00:00
|
|
|
|
movq %rax, %cr3
|
|
|
|
|
|
|
2022-02-21 06:39:48 +00:00
|
|
|
|
movq switch_seg(%rip), %rax
|
2022-01-21 03:43:13 +00:00
|
|
|
|
// 由于ljmp和lcall在GAS中不受支持,因此我们需要先伪造函数调用现场,通过lret的方式,给它跳转过去。才能更新cs寄存器
|
|
|
|
|
|
// 实在是太妙了!Amazing!
|
|
|
|
|
|
pushq $0x08 //段选择子
|
|
|
|
|
|
pushq %rax
|
|
|
|
|
|
lretq
|
|
|
|
|
|
|
|
|
|
|
|
// 64位模式的代码
|
|
|
|
|
|
switch_seg:
|
2022-02-21 06:39:48 +00:00
|
|
|
|
|
2022-01-21 03:43:13 +00:00
|
|
|
|
.quad entry64
|
|
|
|
|
|
|
|
|
|
|
|
entry64:
|
2022-02-21 06:39:48 +00:00
|
|
|
|
|
2022-01-21 03:43:13 +00:00
|
|
|
|
movq $0x10, %rax
|
|
|
|
|
|
movq %rax, %ds
|
|
|
|
|
|
movq %rax, %es
|
|
|
|
|
|
movq %rax, %gs
|
|
|
|
|
|
movq %rax, %ss
|
|
|
|
|
|
|
2022-02-12 14:14:51 +00:00
|
|
|
|
movq _stack_start(%rip), %rsp //rsp的地址
|
2022-01-21 03:43:13 +00:00
|
|
|
|
|
2022-01-24 12:56:59 +00:00
|
|
|
|
setup_IDT:
|
|
|
|
|
|
leaq m_ignore_int(%rip), %rdx // 将ignore_int的地址暂时存到中段描述符的高8B
|
|
|
|
|
|
movq $(0x08 << 16), %rax // 设置段选择子。由IDT结构和段选择子结构可知,本行设置段基地址为0x100000,TI=0,RPL=0
|
|
|
|
|
|
movw %dx, %ax
|
|
|
|
|
|
|
|
|
|
|
|
movq $ (0x8e00 << 32), %rcx // 设置Type=1110 P=1 DPL=00 0=0
|
|
|
|
|
|
addq %rcx, %rax
|
|
|
|
|
|
|
|
|
|
|
|
// 把ignore_int的地址填写到正确位置, rax存低8B, rdx存高8B
|
|
|
|
|
|
movl %edx, %ecx
|
|
|
|
|
|
shrl $16, %ecx // 去除低16位
|
|
|
|
|
|
shlq $48, %rcx
|
|
|
|
|
|
addq %rcx, %rax // 填写段内偏移31:16
|
|
|
|
|
|
|
|
|
|
|
|
shrq $32, %rdx // (已经填写了32位,故右移32)
|
|
|
|
|
|
|
|
|
|
|
|
leaq IDT_Table(%rip), %rdi // 获取中断描述符表的首地址,存储到rdi
|
|
|
|
|
|
mov $256, %rcx // 初始化每个中断描述符
|
|
|
|
|
|
|
|
|
|
|
|
repeat_set_idt:
|
|
|
|
|
|
// ====== 循环,初始化总共256个中断描述符 ===
|
|
|
|
|
|
movq %rax, (%rdi) // 保存低8B
|
|
|
|
|
|
movq %rdx, 8(%rdi) // 保存高8B
|
|
|
|
|
|
|
|
|
|
|
|
addq $0x10, %rdi // 转到下一个IDT表项
|
|
|
|
|
|
dec %rcx
|
|
|
|
|
|
jne repeat_set_idt
|
|
|
|
|
|
|
|
|
|
|
|
SetUp_TSS64:
|
|
|
|
|
|
// == 设置64位的任务状态段表 ===
|
|
|
|
|
|
//rdx保存高8B, rax保存低8B
|
|
|
|
|
|
leaq TSS64_Table(%rip), %rdx
|
|
|
|
|
|
xorq %rax, %rax
|
|
|
|
|
|
xorq %rcx, %rcx
|
|
|
|
|
|
|
|
|
|
|
|
// 设置TSS描述符的47:40位为1000 1001
|
|
|
|
|
|
movq $0x89, %rax
|
|
|
|
|
|
shlq $40, %rax
|
|
|
|
|
|
|
|
|
|
|
|
// 设置段基地址31:24
|
|
|
|
|
|
movl %edx, %ecx
|
|
|
|
|
|
shrl $24, %ecx
|
|
|
|
|
|
shlq $56, %rcx
|
|
|
|
|
|
addq %rcx, %rax
|
|
|
|
|
|
|
|
|
|
|
|
xorq %rcx, %rcx
|
|
|
|
|
|
|
|
|
|
|
|
// 设置段基地址23:00
|
|
|
|
|
|
movl %edx, %ecx
|
|
|
|
|
|
andl $0xffffff, %ecx // 清空ecx的中有效值的高8位(也就是上面已经赋值了的)
|
|
|
|
|
|
shlq $16, %rcx
|
|
|
|
|
|
addq %rcx, %rax
|
|
|
|
|
|
|
|
|
|
|
|
addq $103, %rax // 设置段长度
|
|
|
|
|
|
|
|
|
|
|
|
leaq GDT_Table(%rip), %rdi
|
2022-02-13 14:41:35 +00:00
|
|
|
|
movq %rax, 80(%rdi) // 把低八B存储到GDT第10项
|
2022-01-24 12:56:59 +00:00
|
|
|
|
shrq $32, %rdx
|
2022-02-13 14:41:35 +00:00
|
|
|
|
movq %rdx, 88(%rdi) // 高8B存到GDT第11项
|
2022-01-24 12:56:59 +00:00
|
|
|
|
|
2022-01-25 10:04:18 +00:00
|
|
|
|
// 装载任务状态段寄存器(已改为在main.c中使用load_TR宏进行装载)
|
2022-02-13 14:41:35 +00:00
|
|
|
|
// mov $0x50, %ax // 设置起始地址为80
|
2022-01-25 10:04:18 +00:00
|
|
|
|
// ltr %ax
|
2022-02-21 15:24:51 +00:00
|
|
|
|
|
|
|
|
|
|
//now enable SSE and the like
|
|
|
|
|
|
movq %cr0, %rax
|
|
|
|
|
|
and $0xFFFB, %ax //clear coprocessor emulation CR0.EM
|
|
|
|
|
|
or $0x2, %ax //set coprocessor monitoring CR0.MP
|
|
|
|
|
|
movq %rax, %cr0
|
|
|
|
|
|
movq %cr4, %rax
|
|
|
|
|
|
or $(3 << 9), %ax //set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
|
|
|
|
|
|
movq %rax, %cr4
|
2022-02-21 06:39:48 +00:00
|
|
|
|
|
|
|
|
|
|
call Start_Kernel
|
2022-01-21 03:43:13 +00:00
|
|
|
|
|
|
|
|
|
|
go_to_kernel:
|
|
|
|
|
|
.quad Start_Kernel
|
|
|
|
|
|
|
2022-01-24 12:56:59 +00:00
|
|
|
|
// ==== 异常/中断处理模块 ignore int: 忽略中断
|
|
|
|
|
|
m_ignore_int:
|
|
|
|
|
|
// 切换到c语言的ignore_int
|
|
|
|
|
|
movq go_to_ignore_int(%rip), %rax
|
|
|
|
|
|
pushq $0x08
|
|
|
|
|
|
pushq %rax
|
|
|
|
|
|
lretq
|
|
|
|
|
|
|
2022-01-25 10:04:18 +00:00
|
|
|
|
lretq
|
|
|
|
|
|
|
2022-01-21 03:43:13 +00:00
|
|
|
|
|
2022-01-24 12:56:59 +00:00
|
|
|
|
go_to_ignore_int:
|
|
|
|
|
|
.quad ignore_int
|
2022-01-21 03:43:13 +00:00
|
|
|
|
|
2022-02-10 05:45:38 +00:00
|
|
|
|
|
|
|
|
|
|
ENTRY(_stack_start)
|
|
|
|
|
|
.quad initial_proc_union + 32768
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-01-21 03:43:13 +00:00
|
|
|
|
// 初始化页表
|
2022-02-21 06:39:48 +00:00
|
|
|
|
|
2022-02-28 15:38:50 +00:00
|
|
|
|
.align 0x1000 //设置为4k对齐
|
2022-01-21 03:43:13 +00:00
|
|
|
|
.org 0x1000 //设置页表位置为内核执行头程序的0x1000处
|
|
|
|
|
|
|
|
|
|
|
|
__PML4E:
|
2022-03-01 12:21:32 +00:00
|
|
|
|
.quad 0x103003 // 用户访问,可读写,已存在, 地址在31~12位
|
2022-01-21 03:43:13 +00:00
|
|
|
|
.fill 255,8,0
|
2022-03-01 12:21:32 +00:00
|
|
|
|
.quad 0x103003
|
2022-01-21 03:43:13 +00:00
|
|
|
|
.fill 255,8,0
|
|
|
|
|
|
|
|
|
|
|
|
.org 0x2000
|
|
|
|
|
|
|
|
|
|
|
|
__PDPTE:
|
|
|
|
|
|
|
2022-03-01 12:21:32 +00:00
|
|
|
|
.quad 0x104003 // 用户访问,可读写,已存在
|
2022-01-21 03:43:13 +00:00
|
|
|
|
.fill 511,8,0
|
|
|
|
|
|
|
|
|
|
|
|
.org 0x3000
|
|
|
|
|
|
|
|
|
|
|
|
__PDE:
|
|
|
|
|
|
|
2022-03-01 12:21:32 +00:00
|
|
|
|
.quad 0x000083 // 用户访问,可读写,已存在
|
|
|
|
|
|
.quad 0x200083
|
|
|
|
|
|
.quad 0x400083
|
|
|
|
|
|
.quad 0x600083
|
|
|
|
|
|
.quad 0x800083
|
|
|
|
|
|
.quad 0xa00083
|
|
|
|
|
|
.quad 0xc00083
|
|
|
|
|
|
.quad 0xe00083
|
|
|
|
|
|
.quad 0x1000083
|
|
|
|
|
|
.quad 0x1200083
|
|
|
|
|
|
.quad 0x1400083
|
|
|
|
|
|
.quad 0x1600083
|
|
|
|
|
|
.quad 0x1800083
|
|
|
|
|
|
.quad 0x1a00083
|
|
|
|
|
|
.quad 0x1c00083
|
|
|
|
|
|
.quad 0x1e00083
|
|
|
|
|
|
.quad 0x2000083
|
|
|
|
|
|
.quad 0x2200083
|
|
|
|
|
|
.quad 0x2400083
|
|
|
|
|
|
.quad 0x2600083
|
|
|
|
|
|
.quad 0x2800083
|
|
|
|
|
|
.quad 0x2a00083
|
|
|
|
|
|
.quad 0x2c00083
|
|
|
|
|
|
.quad 0x2e00083
|
2022-03-02 05:07:13 +00:00
|
|
|
|
.quad 0x3000083
|
|
|
|
|
|
.quad 0x3200083
|
|
|
|
|
|
.quad 0x3400083
|
|
|
|
|
|
.quad 0x3600083
|
2022-03-01 12:21:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.quad 0xe0000083 /*虚拟地址0x 3000000 初始情况下,帧缓冲区映射到这里*/
|
|
|
|
|
|
.quad 0xe0200083
|
|
|
|
|
|
.quad 0xe0400083
|
|
|
|
|
|
.quad 0xe0600083 /*0x1000000*/
|
|
|
|
|
|
.quad 0xe0800083
|
|
|
|
|
|
.quad 0xe0a00083
|
|
|
|
|
|
.quad 0xe0c00083
|
|
|
|
|
|
.quad 0xe0e00083
|
2022-03-02 05:07:13 +00:00
|
|
|
|
.quad 0xe1000083
|
|
|
|
|
|
.quad 0xe1200083
|
|
|
|
|
|
.quad 0xe1400083
|
|
|
|
|
|
.quad 0xe1600083
|
|
|
|
|
|
.quad 0xe1800083
|
|
|
|
|
|
.quad 0xe1a00083
|
|
|
|
|
|
.quad 0xe1c00083
|
|
|
|
|
|
.quad 0xe1e00083
|
|
|
|
|
|
.fill 468,8,0
|
2022-01-21 03:43:13 +00:00
|
|
|
|
|
|
|
|
|
|
// GDT表
|
|
|
|
|
|
.section .data
|
2022-02-21 06:39:48 +00:00
|
|
|
|
.align 16
|
2022-01-21 03:43:13 +00:00
|
|
|
|
.global GDT_Table // 使得GDT可以被外部程序引用或者访问
|
|
|
|
|
|
|
|
|
|
|
|
GDT_Table:
|
2022-02-13 14:41:35 +00:00
|
|
|
|
.quad 0x0000000000000000 // 0 空描述符 0x00
|
|
|
|
|
|
.quad 0x0020980000000000 // 1 内核64位代码段描述符 0x08
|
|
|
|
|
|
.quad 0x0000920000000000 // 2 内核64位数据段描述符 0x10
|
|
|
|
|
|
.quad 0x0000000000000000 // 3 用户32位代码段描述符 0x18
|
|
|
|
|
|
.quad 0x0000000000000000 // 4 用户32位数据段描述符 0x20
|
|
|
|
|
|
.quad 0x0020f80000000000 // 5 用户64位代码段描述符 0x28
|
|
|
|
|
|
.quad 0x0000f20000000000 // 6 用户64位数据段描述符 0x30
|
|
|
|
|
|
.quad 0x00cf9a000000ffff // 7 内核32位代码段描述符 0x38
|
|
|
|
|
|
.quad 0x00cf92000000ffff // 8 内核32位数据段描述符 0x40
|
|
|
|
|
|
.fill 10, 8, 0 // 10-11 TSS(跳过了第9段) 重复十次填充8字节的空间,赋值为0
|
2022-01-21 03:43:13 +00:00
|
|
|
|
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
|
2022-02-28 15:38:50 +00:00
|
|
|
|
TSS64_BASE: .quad TSS64_Table
|