DragonOS/kernel/head.S
2022-07-09 17:03:47 +08:00

665 lines
15 KiB
ArmAsm
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by longjin.
// 2022/01/20
#include "common/asm.h"
// 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
// -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
.section .multiboot_header
.align MULTIBOOT_HEADER_ALIGN
//
multiboot_header:
//
.long MULTIBOOT2_HEADER_MAGIC
//
.long MULTIBOOT_ARCHITECTURE_I386
//
.long HEADER_LENGTH
//
.long CHECKSUM
// Multiboot2 Specification version 2.0.pdf
//
.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
.short MULTIBOOT_HEADER_TAG_END
//
.short 0
.long 8
multiboot_header_end:
.section .bootstrap
.global _start
.type _start, @function
# multiboot2.cpp
.extern _start64
.extern boot_info_addr
.extern multiboot2_magic
ENTRY(_start)
//
cli
// multiboot2_info
mov %ebx, mb2_info
//mov %ebx, %e8
//
mov %eax, mb2_magic
//mov %eax, %e9
/
// 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
.global enter_head_from_ap_boot
enter_head_from_ap_boot:
// 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)
jmp $0x8, $ready_to_start_64
hlt
ret
.code64
.global ready_to_start_64
ready_to_start_64:
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %ss
mov $0x7e00, %esp
//6. start64
movq switch_to_start64(%rip), %rax
pushq $0x08 //
pushq %rax
lretq
switch_to_start64:
.quad _start64
.code64
is_from_ap:
hlt
.global _start64
.type _start64, @function
.extern Start_Kernel
ENTRY(_start64)
//
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %ss
mov $0x7e00, %esp
// === GDTR ====
lgdt GDT_POINTER(%rip) //rip, PICposition independent code
//lgdt $GDT_POINTER
// === IDTR ====
lidt IDT_POINTER(%rip)
//lidt $IDT_POINTER
movq GDT_POINTER(%rip), %r12
movq head_stack_start(%rip), %rsp
// apu
movq $0x1b, %rcx // IA32_APIC_BASE.BSP[8]apu
rdmsr
bt $8, %rax
jnc load_cr3
// 2.
//
mov $__PML4E, %eax
mov $__PDPTE, %ebx
or $0x3, %ebx
mov %ebx, 0(%eax)
mov %ebx, 256(%eax)
//
mov $__PDPTE, %eax
mov $__PDE, %ebx
or $0x3, %ebx
mov %ebx, 0(%eax)
// ==== CR3
load_cr3:
// apu
movq $__PML4E, %rax //
movq %rax, %cr3
movq switch_seg(%rip), %rax
// ljmplcallGASlretcs
// 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 head_stack_start(%rip), %rsp //rsp
// GDTIDT
leaq GDT_Table(%rip), %r8
leaq GDT_END(%rip), %r9
subq %r8, %r9
movq %r9, %r13 // GDT size
leaq IDT_Table(%rip), %r8
leaq IDT_END(%rip), %r9
subq %r8, %r9
movq %r9, %r12 // IDT size
lgdt GDT_POINTER64(%rip)
lidt IDT_POINTER64(%rip)
// apu
movq $0x1b, %rcx // IA32_APIC_BASE.BSP[8]apu
rdmsr
bt $8, %rax
jnc start_smp
setup_IDT:
leaq m_ignore_int(%rip), %rdx // ignore_int8B
movq $(0x08 << 16), %rax // IDT0x100000TI=0,RPL=0
movw %dx, %ax
movq $ (0x8e00 << 32), %rcx // Type=1110 P=1 DPL=00 0=0
addq %rcx, %rax
// ignore_int, rax8B rdx8B
movl %edx, %ecx
shrl $16, %ecx // 16
shlq $48, %rcx
addq %rcx, %rax // 31:16
shrq $32, %rdx // 3232
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 ===
//rdx8B rax8B
leaq TSS64_Table(%rip), %rdx // process.cinitial_tss[0]
movq $0xffff800000000000, %r8
addq %r8, %rdx
xorq %rax, %rax
xorq %rcx, %rcx
// TSS47401000 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 // ecx8
shlq $16, %rcx
addq %rcx, %rax
addq $103, %rax //
leaq GDT_Table(%rip), %rdi
movq %rax, 80(%rdi) // BGDT10
shrq $32, %rdx
movq %rdx, 88(%rdi) // 8BGDT11
// (main.c使load_TR)
// mov $0x50, %ax // 80
// ltr %ax
//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
movq go_to_kernel(%rip), %rax /* movq address */
pushq $0x08
pushq %rax
movq mb2_info, %r15
movq mb2_magic, %r14
lretq
go_to_kernel:
.quad Start_Kernel
start_smp:
//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
movq go_to_smp_kernel(%rip), %rax /* movq address */
pushq $0x08
pushq %rax
/*
// GDTIDT
leaq GDT_Table(%rip), %r8
leaq GDT_END(%rip), %r9
subq %r8, %r9
movq %r9, %r13 // GDT size
leaq IDT_Table(%rip), %r8
leaq IDT_END(%rip), %r9
subq %r8, %r9
movq %r9, %r12 // IDT size
lgdt GDT_POINTER64(%rip)
lidt IDT_POINTER64(%rip)
*/
lretq
go_to_smp_kernel:
.quad smp_ap_start
// ==== / ignore int
m_ignore_int:
// cignore_int
movq go_to_ignore_int(%rip), %rax
pushq $0x08
pushq %rax
lretq
lretq
go_to_ignore_int:
.quad ignore_int
ENTRY(head_stack_start)
.quad initial_proc_union + 32768
//
.align 0x1000 //4k
//.org 0x1000 //0x1000
__PML4E:
.quad 0x103007 // 访 31~12
.fill 255,8,0
.quad 0x103003
.fill 255,8,0
.org 0x2000
__PDPTE:
.quad 0x104003 // 访
.fill 511,8,0
.org 0x3000
__PDE:
.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
.quad 0x3000083
.quad 0x3200083
.quad 0x3400083
.quad 0x3600083
.quad 0xe0000083 /*虚拟地址0x 3000000 初始情况下,帧缓冲区映射到这里*/
.quad 0xe0200083
.quad 0xe0400083
.quad 0xe0600083 /*0x1000000*/
.quad 0xe0800083
.quad 0xe0a00083
.quad 0xe0c00083
.quad 0xe0e00083
.quad 0xe1000083
.quad 0xe1200083
.quad 0xe1400083
.quad 0xe1600083
.quad 0xe1800083
.quad 0xe1a00083
.quad 0xe1c00083
.quad 0xe1e00083
.fill 468,8,0
// GDT
.align 16
.global GDT_Table // 使GDT访
GDT_Table:
.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 100, 8, 0 // 10-11 TSS(9) 80 TSS128bit
GDT_END:
.global GDT_POINTER
GDT_POINTER:
GDT_LIMIT: .word GDT_END - GDT_Table - 1 // GDT
GDT_BASE: .quad GDT_Table
.global GDT_POINTER64
GDT_POINTER64:
GDT_LIMIT64: .word GDT_END - GDT_Table - 1 // GDT
GDT_BASE64: .quad GDT_Table + 0xffff800000000000
// IDT
.global IDT_Table
IDT_Table:
.fill 512, 8, 0 // 512*8IDT
IDT_END:
.global IDT_POINTER
IDT_POINTER:
IDT_LIMIT: .word IDT_END - IDT_Table - 1
IDT_BASE: .quad IDT_Table
.global IDT_POINTER64
IDT_POINTER64:
IDT_LIMIT64: .word IDT_END - IDT_Table - 1
IDT_BASE64: .quad IDT_Table + 0xffff800000000000
// 64TSS
.global TSS64_Table
TSS64_Table:
.fill 13, 8, 0
TSS64_END:
.section .bootstrap.data
mb2_magic: .quad 0
mb2_info: .quad 0
.code32
// 4KB/
.align 0x1000
.global pml4
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