Encountering General Protection Fault on SYSRET
Posted: Tue Mar 19, 2024 9:48 pm
I am currently working on my os code, and trying to switch to the user mode.
This is how I set my gdts:
And this is how I try to switch to usermode:
This is how the system looks before "usermode()":
And after executing "SYSRET", it encountered a General Protect Fault, followed by a Stack-Segment Fault:
Then the system crashed.
I have also set the page table to user-mode:
This is how I set my gdts:
Code: Select all
uint64 gdt[6];
gdt[0] = 0UL; // dummy
gdt[1] = 0x00a0980000000000UL; // kernel code
gdt[2] = 0x00c0920000000000UL; // kernel data
gdt[3] = 0UL; // reserved
gdt[4] = 0x00c0f20000000000UL; // user data
gdt[5] = 0x00a0f80000000000UL; // user code
struct gdtp {
uint16 size;
uint64 addr;
} __attribute__((packed)) _gdtp;
_gdtp.size = 8 * 6 - 1;
_gdtp.addr = (uint64)&gdt[0];
cli();
__asm__ __volatile__ ("lgdt 0x1031d0"); // addr for _gdtp
Code: Select all
global jump_usermode
extern user_test
jump_usermode:
;enable system call extensions that enables sysret and syscall
mov rcx, 0xc0000082
wrmsr
mov rcx, 0xc0000080
rdmsr
or eax, 1
wrmsr ;enable syscall/sysret
mov rcx, 0xc0000081
rdmsr
mov edx, 0x00180008
wrmsr ; CS/SS selectors
mov rcx, user_test ; to be loaded into RIP
;mov rcx, user_test
mov r11, 0x202 ; to be loaded into EFLAGS
o64 sysret
Code: Select all
Servicing hardware INT=0x20
192: v=20 e=0000 i=0 cpl=0 IP=0008:0000000000101852 pc=0000000000101852 SP=0000:0000000000110ef0 env->regs[R_EAX]=0000000000000010
RAX=0000000000000010 RBX=0000000000000000 RCX=0000000000000008 RDX=00000000000003f8
RSI=0000000000000030 RDI=00000000000003f8 RBP=0000000000110fe0 RSP=0000000000110ef0
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000000
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=0000000000101852 RFL=00000212 [----A--] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0000 0000000000000000 00000000 00000000
CS =0008 0000000000000000 00000000 00209800 DPL=0 CS64 [---]
SS =0000 0000000000000000 ffffffff 00c09300 DPL=0 DS [-WA]
DS =0000 0000000000000000 00000000 00000000
FS =0000 0000000000000000 00000000 00000000
GS =0000 0000000000000000 00000000 00000000
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT= 0000000000100284 0000000f
IDT= 00000000001031e0 00000fff
CR0=80000011 CR2=0000000000000000 CR3=0000000000105000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000010 CCD=0000000000000001 CCO=EFLAGS
EFER=0000000000000500
Code: Select all
check_exception old: 0xffffffff new 0xd
193: v=0d e=0000 i=0 cpl=3 IP=002b:00000000001013bd pc=00000000001013bd SP=0023:0000000000110e90 env->regs[R_EAX]=00000000000003fd
RAX=00000000000003fd RBX=0000000000000000 RCX=00000000001019ee RDX=00000000000003fd
RSI=0000000000000030 RDI=00000000000003fd RBP=0000000000110e90 RSP=0000000000110e90
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000202
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=00000000001013bd RFL=00000202 [-------] CPL=3 II=0 A20=1 SMM=0 HLT=0
ES =0000 0000000000000000 00000000 00000000
CS =002b 0000000000000000 ffffffff 00a0fb00 DPL=3 CS64 [-RA]
SS =0023 0000000000000000 ffffffff 00c0f300 DPL=3 DS [-WA]
DS =0000 0000000000000000 00000000 00000000
FS =0000 0000000000000000 00000000 00000000
GS =0000 0000000000000000 00000000 00000000
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT= 00000000001031a0 0000002f
IDT= 00000000001031e0 00000fff
CR0=80000011 CR2=0000000000000000 CR3=0000000000105000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000005 CCD=00000000000003fd CCO=ADDL
EFER=0000000000000501
check_exception old: 0xd new 0xc
194: v=08 e=0000 i=0 cpl=3 IP=002b:00000000001013bd pc=00000000001013bd SP=0023:0000000000110e90 env->regs[R_EAX]=00000000000003fd
RAX=00000000000003fd RBX=0000000000000000 RCX=00000000001019ee RDX=00000000000003fd
RSI=0000000000000030 RDI=00000000000003fd RBP=0000000000110e90 RSP=0000000000110e90
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000202
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=00000000001013bd RFL=00000202 [-------] CPL=3 II=0 A20=1 SMM=0 HLT=0
ES =0000 0000000000000000 00000000 00000000
CS =002b 0000000000000000 ffffffff 00a0fb00 DPL=3 CS64 [-RA]
SS =0023 0000000000000000 ffffffff 00c0f300 DPL=3 DS [-WA]
DS =0000 0000000000000000 00000000 00000000
FS =0000 0000000000000000 00000000 00000000
GS =0000 0000000000000000 00000000 00000000
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT= 00000000001031a0 0000002f
IDT= 00000000001031e0 00000fff
CR0=80000011 CR2=0000000000000000 CR3=0000000000105000 CR4=00000020
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000005 CCD=00000000000003fd CCO=ADDL
EFER=0000000000000501
check_exception old: 0x8 new 0xc
I have also set the page table to user-mode:
Code: Select all
setup_page_tables:
mov eax, page_table_l3
or eax, 0b111 ; present, writable, usermode.
mov [page_table_l4], eax
mov eax, page_table_l2
or eax, 0b111 ; present, writable, usermode.
mov [page_table_l3], eax
mov ecx, 0 ; counter
.loop:
mov eax, 0x200000 ; 2MiB
mul ecx
or eax, 0b10000111 ; present, writable, huge page, usermode.
mov [page_table_l2 + ecx * 8], eax ; 1G does this indicates that, the whole memory is merely copy of 2MiB?
inc ecx ; increment counter
cmp ecx, 512 ; checks if the whole table is mapped
jne .loop
ret