#include <sys/segments.h>
#include <sys/controlregs.h>
#define DATASZ .byte 0x66;
.globl _start
_start:
movq %rbp, save_rbp
movq %rsp, save_rsp
movq %rbx, save_rbx
movq %rsi, save_rsi
movq %r12, save_r12
movq %r13, save_r13
movq %r14, save_r14
movq %r15, save_r15
movq $_start, %rsp
movq %rdi, %rbx
subq $18, %rsp
movq %rsp, %rdi
cld
movl $18, %ecx
rep
movsb
sidt save_idt
sgdt save_gdt
str save_tr
movw %cs, save_cs
movw %ds, save_ds
movw %ss, save_ss
movw %es, save_es
movw %fs, save_fs
movw %gs, save_gs
movq %cr4, %rax
movq %rax, save_cr4
movq %cr3, %rax
movq %rax, save_cr3
movq %cr0, %rax
movq %rax, save_cr0
movl $MSR_AMD_FSBASE, %ecx
rdmsr
movl %eax, save_fsbase
movl %edx, save_fsbase + 4
xorl %eax, %eax
xorl %edx, %edx
wrmsr
movl $MSR_AMD_GSBASE, %ecx
rdmsr
movl %eax, save_gsbase
movl %edx, save_gsbase + 4
xorl %eax, %eax
xorl %edx, %edx
wrmsr
movl $MSR_AMD_KGSBASE, %ecx
rdmsr
movl %eax, save_kgsbase
movl %edx, save_kgsbase + 4
xorl %eax, %eax
xorl %edx, %edx
wrmsr
movq %cr8, %rax
movq %rax, save_cr8
leaq enter_real, %rax
movw %ax, enter_real_ljmp
leaq enter_protected, %rax
movw %ax, enter_protected_ljmp
leaq gdt_info, %rax
movw %ax, gdt_info_load
movb %bl, int_instr+1
jmp 1f
1:
xorq %r8, %r8
xorq %r9, %r9
xorq %r10, %r10
xorq %r11, %r11
xorq %r12, %r12
xorq %r13, %r13
xorq %r14, %r14
xorq %r15, %r15
xorl %eax, %eax
xorl %ebx, %ebx
xorl %ecx, %ecx
xorl %edx, %edx
xorl %ebp, %ebp
xorl %esi, %esi
xorl %edi, %edi
lgdt gdt_info
lidt idt_info
movq %rsp, %rax
pushq $B32DATA_SEL
pushq %rax
pushf
pushq $B32CODE_SEL
pushq $1f
iretq
1:
.code32
movl %cr0, %eax
btcl $31, %eax
movl %eax, %cr0
ljmp $B32CODE_SEL, $1f
1:
xorl %eax, %eax
movl %eax, %cr3
movl $MSR_AMD_EFER, %ecx
rdmsr
btcl $8, %eax
wrmsr
ljmp $B16CODE_SEL, $enter_16_bit
enter_16_bit:
DATASZ movl $B16DATA_SEL, %eax
movw %ax, %ss
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
DATASZ movl $0x0, %eax
DATASZ movl %eax, %cr0
.byte 0xea
enter_real_ljmp:
.value 0
.value 0x0
enter_real:
DATASZ xorl %eax, %eax
movw %ax, %ss
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
popl %eax
popl %ebx
popl %ecx
popl %edx
popl %esi
popl %edi
popl %ebp
pop %es
pop %ds
sti
int_instr:
int $0x10
cli
pushf
push %ds
push %es
pushl %ebp
pushl %edi
pushl %esi
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
push $0
pop %ds
.byte 0x0f, 0x01, 0x16
gdt_info_load:
.value 0
DATASZ movl $0x1, %eax
DATASZ movl %eax, %cr0
.byte 0xea
enter_protected_ljmp:
.value 0
.value B32CODE_SEL
enter_protected:
.code32
movw $B32DATA_SEL, %ax
movw %ax, %ds
movw %ax, %ss
movl save_cr4, %eax
movl %eax, %cr4
movl save_cr3, %eax
movl %eax, %cr3
movl $MSR_AMD_EFER, %ecx
rdmsr
btsl $8, %eax
wrmsr
movl save_cr0, %eax
movl %eax, %cr0
jmp enter_paging
enter_paging:
pushl $B64CODE_SEL
pushl $longmode
lret
longmode:
.code64
lgdt save_gdt
lidt save_idt
movzwq save_tr, %rax
addq save_gdt+2, %rax
btcl $1, 5(%rax)
ltr save_tr
movw save_ds, %ds
movw save_ss, %ss
movw save_es, %es
movw save_fs, %fs
movw save_gs, %gs
pushq save_cs
pushq $.newcs
lretq
.newcs:
movl save_fsbase, %eax
movl save_fsbase + 4, %edx
movl $MSR_AMD_FSBASE, %ecx
wrmsr
movl save_gsbase, %eax
movl save_gsbase + 4, %edx
movl $MSR_AMD_GSBASE, %ecx
wrmsr
movl save_kgsbase, %eax
movl save_kgsbase + 4, %edx
movl $MSR_AMD_KGSBASE, %ecx
wrmsr
movq save_cr8, %rax
cmpq $0, %rax
je 1f
movq %rax, %cr8
1:
movq save_rsi, %rdi
movq %rsp, %rsi
movq $18, %rcx
rep
movsb
movw 18(%rsp), %ax
andq $0xffff, %rax
movq save_r12, %r12
movq save_r13, %r13
movq save_r14, %r14
movq save_r15, %r15
movq save_rbx, %rbx
movq save_rbp, %rbp
movq save_rsp, %rsp
ret
.align 4
save_esi:
.long 0
save_edi:
.long 0
save_ebx:
.long 0
save_ebp:
.long 0
save_esp:
.long 0
.align 8
save_rsi:
.quad 0
save_rbx:
.quad 0
save_rbp:
.quad 0
save_rsp:
.quad 0
save_r12:
.quad 0
save_r13:
.quad 0
save_r14:
.quad 0
save_r15:
.quad 0
save_kgsbase:
.quad 0
save_gsbase:
.quad 0
save_fsbase:
.quad 0
save_cr8:
.quad 0
save_idt:
.quad 0
.quad 0
save_gdt:
.quad 0
.quad 0
save_cr0:
.quad 0
save_cr3:
.quad 0
save_cr4:
.quad 0
save_cs:
.quad 0
save_ss:
.value 0
save_ds:
.value 0
save_es:
.value 0
save_fs:
.value 0
save_gs:
.value 0
save_tr:
.value 0
idt_info:
.value 0x3ff
.quad 0
#include "../boot/boot_gdt.s"