OSDev.org
https://forum.osdev.org/

GP Excpetion when doing retf in Long Mode
https://forum.osdev.org/viewtopic.php?f=13&t=33718
Page 1 of 1

Author:  Freggar [ Tue May 28, 2019 5:02 am ]
Post subject:  GP Excpetion when doing retf in Long Mode

Emulator: QEMU
Compiler: x86_64-w64-mingw32-gcc (and as)

I'm trying to simulate a far jump via retf. For testing purposes I try to jump to the same segment I'm already in. The following code is executed after ExitBootServices():

Code:
.intel_syntax noprefix
.global test_retf

test_retf:
   push rbp
   mov rbp, rsp

   mov ax, cs
   push ax # push cs
   push jump_target # push target
   retf

jump_target:
   nop # do something after far jump
   pop rbp # Return
   ret

.att_syntax noprefix


Executing this code produces a GP Exception:

Code:
!!!! X64 Exception Type - 0D(#GP - General Protection)  CPU Apic ID - 00000000 !!!!
ExceptionData - 0000000000009090
RIP  - 00000000066FB010, CS  - 0000000000000038, RFLAGS - 0000000000000046
RAX  - 0000000000000038, RCX - 0000000000000000, RDX - 0000000000000000
RBX  - 0000000000000000, RSP - 0000000007F1F986, RBP - 0000000007F1F990
RSI  - 0000000000000009, RDI - 0000000006E92118
R8   - 0000000007F1F93C, R9  - 0000000000000078, R10 - 0000000007BC4840
R11  - 0000000036E11C9A, R12 - 0000000000000000, R13 - 0000000006BDA018
R14  - 0000000000000000, R15 - 0000000007650000
DS   - 0000000000000030, ES  - 0000000000000030, FS  - 0000000000000030
GS   - 0000000000000030, SS  - 0000000000000030
CR0  - 0000000080010033, CR2 - 0000000000000000, CR3 - 0000000007C01000
CR4  - 0000000000000668, CR8 - 0000000000000000
DR0  - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
DR3  - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
GDTR - 0000000007BEEA98 0000000000000047, LDTR - 0000000000000000
IDTR - 000000000765A018 0000000000000FFF,   TR - 0000000000000000
FXSAVE_STATE - 0000000007F1F5E0
!!!! Find image based on IP(0x66FB010) (No PDB)  (ImageBase=00000000066FA000, EntryPoint=00000000066FB020) !!!!

Can someone point me to what I'm doing wrong? I've read the RETF section from the AMD Programmer’s Manual Volume 3 and cannot find out what I'm doing wrong.

Author:  Octocontrabass [ Tue May 28, 2019 5:52 am ]
Post subject:  Re: GP Excpetion when doing retf in Long Mode

In long mode, "push ax" still only pushes two bytes onto the stack. You need an instruction that will push eight bytes, such as "push rax".

(This might not be the only problem, but it's the only one I can spot right now.)

Author:  Freggar [ Tue May 28, 2019 7:03 am ]
Post subject:  Re: GP Excpetion when doing retf in Long Mode

Thanks for the pointer, doing
Code:
mov rax, cs
push rax

instead, will yield the same error. Are you sure that I need to push 8 bytes?
Quote:
All stack pops are determined by the operand size. If necessary, the target rIP is zero-extended to 64
bits before assuming program control.

AMD Programmer’s Manual Volume 3 -- RET (far)

This leads me to believe that I need to push 2 bytes since the CS register is 2 bytes.

Author:  Octocontrabass [ Tue May 28, 2019 7:44 am ]
Post subject:  Re: GP Excpetion when doing retf in Long Mode

Freggar wrote:
Are you sure that I need to push 8 bytes?

Yes, assuming you're using a far return with a 64-bit operand size. I'm not familiar with GAS for x86 assembly, but I know NASM and YASM disagree on whether "retf" should be encoded with a 32-bit operand size or a 64-bit operand size. You might need to write something else to get the right operand size.

It's not made clear in the section of the manual you quote, but CS is popped using the operand size, discarding the unused high-order bits if the operand size is 32-bit or 64-bit.

Author:  Freggar [ Wed May 29, 2019 3:10 am ]
Post subject:  Re: GP Excpetion when doing retf in Long Mode

Yes, seems like it was an issue with operand size. I got it working by using the code from this stackoverflow post
Code:
sub $16, %rsp
movq $8, 8(%rsp)
movabsq $fun, %rax
mov %rax, (%rsp)
lretq

The "lretq" translates to "rex.W retf" in objdump, so you probably need to specify 64-bit operand size.

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/