Page 2 of 2

Re: Long jump in 64-bits: instruction not supported

Posted: Thu Aug 25, 2016 10:14 am
by chris13524
I tried your code:

Code: Select all

[GLOBAL gdt_flush]
gdt_flush:
   mov rax, [rsp+4]
   lgdt [rax]

   mov rax, 0x10
   mov ds, rax
   mov es, rax
   mov fs, rax
   mov gs, rax
   mov ss, rax

   lea rax, [rel .flush]
   push 0x08
   push rax
   retf
.flush:
   ret
But it's giving me this exception:

Code: Select all

!!!! X64 Exception Type - 000000000000000D     CPU Apic ID - 00000000 !!!!
RIP  - 000000000673F325, CS  - 0000000000000028, RFLAGS - 0000000000000246
ExceptionData - 0000000000000000
RAX  - 07F94B4000000000, RCX - 00000000000000E9, RDX - 0000000000000068
RBX  - 0000000006744860, RSP - 0000000007F94B18, RBP - 00000000067448C8
RSI  - 0000000000000000, RDI - 00000000067448C8
R8   - 0000000000000000, R9  - 0000000000000674, R10 - 00000000000003F8
R11  - 0000000000000040, R12 - 0000000000000000, R13 - 0000000000000000
R14  - 0000000000000000, R15 - 0000000000000000
DS   - 0000000000000008, ES  - 0000000000000008, FS  - 0000000000000008
GS   - 0000000000000008, SS  - 0000000000000008
CR0  - 0000000080000033, CR2 - 0000000000000000, CR3 - 0000000007F33000
CR4  - 0000000000000668, CR8 - 0000000000000000
DR0  - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
DR3  - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
GDTR - 0000000007F1CE98 000000000000003F, LDTR - 0000000000000000
IDTR - 0000000007C07018 0000000000000FFF,   TR - 0000000000000000
FXSAVE_STATE - 0000000007F94770
!!!! Find PE image (No PDB)  (ImageBase=000000000673A000, EntryPoint=000000000673F34C) !!!!

Re: Long jump in 64-bits: instruction not supported

Posted: Thu Aug 25, 2016 10:28 am
by jnc100
UEFI code shouldn't be a shared object. It should be in the PE DLL format so it is potentially relocatable (it usually won't have to be), but shouldn't require runtime linking.

edit: additionally, if this code is called from C then the first argument will not be in [rsp+4] but rather in rcx.

Regards,
John.

Re: Long jump in 64-bits: instruction not supported

Posted: Thu Aug 25, 2016 10:41 am
by ~
Your question could probably be expressed in an index entry that says:
Loading a 64-bit GDT

Looks like it needs a background before and after loading the GDT.

Before, to know which CPU state we are in (do we need to load the GDT outside any function, etc.?).

After, to know which mechanism to use to try to flush the CPU execution state. Among other things, paging must be fully set up before entering 64-bit mode.

I remember having written a test 64-bit kernel with base file name "kernel.asm" or "kernel64.asm" in pure assembly. I'll see if I can find it in my 5TB+ archives.

Re: Long jump in 64-bits: instruction not supported

Posted: Thu Aug 25, 2016 10:47 am
by chris13524
I'm already running fine in 64-bit mode, UEFI started me off in this. All I was trying to do is to get interrupts working. I can log messages, write to the screen, etc.

Re: Long jump in 64-bits: instruction not supported

Posted: Thu Aug 25, 2016 2:12 pm
by chris13524
edit: additionally, if this code is called from C then the first argument will not be in [rsp+4] but rather in rcx.
It's being called from C++, does this work the same? Use rcx?

Re: Long jump in 64-bits: instruction not supported

Posted: Fri Aug 26, 2016 12:55 am
by iansjack
In the 64-bit ABI paramaters are passed in rdi, rsi, rdx, rcx, r8, r9 (and then pushed to the stack if there are more parameters). So if your function has only one parameter it will be passed in rdi. You can always look at the generated code if you are unsure.

Edit I should have added - this is the ABI for UNIX-type object files, as would be generated by gcc. The Windows 64-bit ABI is different and uses rcx, rdx, r8, and r9. I was assuming, from the forward slashes in path names, that you are using a UNIX-like system.

Re: Long jump in 64-bits: instruction not supported

Posted: Fri Aug 26, 2016 4:45 am
by chris13524
iansjack wrote:In the 64-bit ABI paramaters are passed in rdi, rsi, rdx, rcx, r8, r9 (and then pushed to the stack if there are more parameters). So if your function has only one parameter it will be passed in rdi. You can always look at the generated code if you are unsure.

Edit I should have added - this is the ABI for UNIX-type object files, as would be generated by gcc. The Windows 64-bit ABI is different and uses rcx, rdx, r8, and r9. I was assuming, from the forward slashes in path names, that you are using a UNIX-like system.
Alright, I changed my code to use rdi, however, it's doing that "find PE image error again":

Code: Select all

BITS 64
DEFAULT REL

[GLOBAL gdt_flush]
gdt_flush:
   mov rax, [rdi]
   lgdt [rax]

   mov rax, 0x10
   mov ds, rax
   mov es, rax
   mov fs, rax
   mov gs, rax
   mov ss, rax

   lea rax, [rel .flush]
   push 0x08
   push rax
   retf
.flush:
   ret

[GLOBAL tss_flush]    ; Allows our C code to call tss_flush().
tss_flush:
   mov rax, 0x2B      ; Load the index of our TSS structure - The index is
                     ; 0x28, as it is the 5th selector and each is 8 bytes
                     ; long, but we set the bottom two bits (making 0x2B)
                     ; so that it has an RPL of 3, not zero.
   ltr ax            ; Load 0x2B into the task state register.
   ret
This is happening during the gdt_flush section, figured that out using console output:

Code: Select all

!!!! X64 Exception Type - 000000000000000E     CPU Apic ID - 00000000 !!!!
RIP  - 000000000673E353, CS  - 0000000000000028, RFLAGS - 0000000000000206
ExceptionData - 0000000000000000
RAX  - 000006744940002F, RCX - 0000000007EA9980, RDX - 0000000000000002
RBX  - 00000000067448C0, RSP - 0000000007F94B18, RBP - 0000000006744928
RSI  - 0000000007DD0B10, RDI - 0000000006744928
R8   - 0000000007DC475A, R9  - 0000000007F948EC, R10 - 00000000000003F8
R11  - 0000000000000040, R12 - 0000000000000000, R13 - 0000000000000000
R14  - 0000000000000000, R15 - 0000000000000000
DS   - 0000000000000008, ES  - 0000000000000008, FS  - 0000000000000008
GS   - 0000000000000008, SS  - 0000000000000008
CR0  - 0000000080000033, CR2 - 000006744940002F, CR3 - 0000000007F33000
CR4  - 0000000000000668, CR8 - 0000000000000000
DR0  - 0000000000000000, DR1 - 0000000000000000, DR2 - 0000000000000000
DR3  - 0000000000000000, DR6 - 00000000FFFF0FF0, DR7 - 0000000000000400
GDTR - 0000000007F1CE98 000000000000003F, LDTR - 0000000000000000
IDTR - 0000000007C07018 0000000000000FFF,   TR - 0000000000000000
FXSAVE_STATE - 0000000007F94770
!!!! Find PE image (No PDB)  (ImageBase=0000000006739000, EntryPoint=000000000673E37C) !!!!

Re: Long jump in 64-bits: instruction not supported

Posted: Fri Aug 26, 2016 5:40 am
by Octocontrabass
chris13524 wrote:

Code: Select all

   mov rax, [rdi]
   lgdt [rax]
Are you sure about that? Without seeing your function prototype, I can't tell exactly what you were going for, but I suspect you really want something like this:

Code: Select all

    lgdt [rdi]
(If you compile with -mabi=ms, use the ms_abi attribute on this function, or use a build of GCC that targets Microsoft's ABI by default, you should use RCX instead of RDI.)

Re: Long jump in 64-bits: instruction not supported

Posted: Fri Aug 26, 2016 7:51 am
by Boris
Always remember that the only 64 bit instruction with 64bit immediate parameter is Mov.
So one should do:

Code: Select all

mov rax, .label
push 8
push rax
retf