세그먼트 레지스터 로드 질문

Meiy@Google의 이미지

안녕하세요 현재 기본도 모르면서 하이퍼바이저를 만들고 있는데요.

질문의 목적은 세그먼트 레지스터 초기화 및 로드 질문입니다.

구조는 UEFI 앱 - return 주소 저장 후 vmm.bin으로 jmp

현재 GDTR, 페이지 테이블은 교체를 완료한 상태입니다.

GDT 내용은
gdt[0] = X86_NULL_DESCRIPTOR;

gdt[1] = X86_KERNEL_CODE_SEGMENT;

gdt[2] = X86_KERNEL_DATA_SEGMENT;

gdt[3] = X86_USER_CODE_SEGMENT;

gdt[4] = X86_USER_DATA_SEGMENT;

gdt[5] = 0;

gdt[6] = X64_NULL_DESCRIPTOR;

gdt[7] = X64_KERNEL_CODE_SEGMENT;

gdt[8] = X64_KERNEL_DATA_SEGMENT;

gdt[9] = X64_USER_CODE_SEGMENT;

gdt[10] = X64_USER_DATA_SEGMENT;

gdt[11] = 0;

이 상태로 로드를 하였구요.
이 코드를 작성할 당시엔 UEFI 환경입니다. (사실 이후에도 그렇지만요)
QEMU 환경입니다.

아래는 제가 작성한
nasm 어셈블리이고 세그먼트 로드와 함께 vmm entry로 far 점프하는 코드입니다.

 
chg_gdtr_pg:
	lgdt [r9]
 
	mov rax, r10
        mov cr3, rax
	;mov rbx, [rcx + 0x08]
	;mov rsp, rbx
 
	jmp short .reload_cs
 
.reload_cs:
	push 0x38 ; problem
	lea rbx, [rel .reload_segments]
	push rbx
	retfq
 
.reload_segments:
	mov bx, 0x40
	mov ds, bx
	mov es, bx
	mov fs, bx
	mov gs, bx
	mov ss, bx
 
        mov rax, vmm_entry_addr
	jmp far rax

당연 여기서 mov cs, ax 를 해버리면 크래시가 발생합니다.

그리고 모든 세그먼트 레지스터에 값이 제대로 입력 되었습니다.
현재 크래시 지점은 push 0x30 부터 발생합니다.
아래는 GDT 관련 출력 로그 입니다.

GDT[0] = 0x0, addr = 0x7DB50000
GDT[1] = 0xCF9A000FFFFF, addr = 0x7DB50008
GDT[2] = 0xCF92000FFFFF, addr = 0x7DB50010
GDT[3] = 0xCFFA000FFFFF, addr = 0x7DB50018
GDT[4] = 0xCFF2000FFFFF, addr = 0x7DB50020
GDT[5] = 0x7F0089754178006B, addr = 0x7DB50028
GDT[6] = 0x0, addr = 0x7DB50030
GDT[7] = 0xAF9A000FFFFF, addr = 0x7DB50038
GDT[8] = 0xCF92000FFFFF, addr = 0x7DB50040
GDT[9] = 0xAFFA000FFFFF, addr = 0x7DB50048
GDT[10] = 0xCFF2000FFFFF, addr = 0x7DB50050
GDT[11] = 0x7F00897541E80077, addr = 0x7DB50058
new_gdt_offset = 40B000
gdt_address = 7DB50000
gdtr addr = 0x7DB50070
gdtr->offset = 0x40B000
gdtr->limit = 0x6F

아래는 QEMU 환경 Triple Fault 로그 입니다.
Triple fault
CPU Reset (CPU 0)
RAX=000000007db51000 RBX=000000007dedd000 RCX=000000007f754118 RDX=000000007df0c018
RSI=000000007df0c018 RDI=000000007df0ca20 RBP=000000007fdf55a0 RSP=000000007fdf5578
R8 =0000000000000000 R9 =000000007db50070 R10=000000007db51000 R11=000000007fdf5410
R12=000000007dedd50c R13=000000007dedd6e4 R14=000000007df0da98 R15=000000007dedd5f0
RIP=00000000003ff069 RFL=00000002 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
CS =0038 0000000000000000 ffffffff 00af9a00 DPL=0 CS64 [-R-]
SS =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
DS =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
FS =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
GS =0030 0000000000000000 ffffffff 00cf9300 DPL=0 DS [-WA]
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0048 000000007f7e3058 00000067 00008900 DPL=0 TSS64-avl
GDT= 000000000040b000 0000006f
IDT= 000000007f26b018 00000fff
CR0=80010033 CR2=000000007f26b098 CR3=000000007db51000 CR4=00000668

IDT 같은 경우 VMM 내부에서 로드를 진행 합니다.

일단 Triple Fault 지점은 push 0x38 지점입니다.
그렇다면 스택에 관련된 문제라는 건데...
원래 이런식으로 로드를 하면 안되는 것일까요?
어떠한 빌드업이 필요해 보이는데 헛다리를 짚고 있는건가요?

조언좀 부탁드립니다.