Far jump in 64bit mode

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
sngskunk
Member
Member
Posts: 47
Joined: Mon Mar 31, 2008 1:00 pm
Location: Louisville, KY, USA

Far jump in 64bit mode

Post by sngskunk »

How come if I am using nasm in long mode and I change the GDT for example, and I want to set the cs, I cannot do a far jump.

Cannot do:

Code: Select all

[BITS 64]

jmp 0x08:next  ;<-- NASM complains

next:
   hlt
Currently Working On:
Bootloader (Stage 1) (Complete)
Bootloader (Stage 2) (Inprogress)
User avatar
suthers
Member
Member
Posts: 672
Joined: Tue Feb 20, 2007 3:00 pm
Location: London UK
Contact:

Re: Far jump in 64bit mode

Post by suthers »

What kind of complaining, is it the standard 'invalid combination of opcode and operand', or something else?
Jules
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: Far jump in 64bit mode

Post by jnc100 »

There's no 'jmp ptr16:64' instruction. The assumption is that you'd never want to change cs with a jmp in long mode as flat segments are expected anyway. You can encode the jmp ptr16:32 instruction from a [BITS 32] section to a [BITS 64] section in order to make the initial switch from compatibility mode to long mode.

An (untested) workaround is

Code: Select all

push 0x8
lea rax, [next]
push rax
retf
Regards,
John.
User avatar
sngskunk
Member
Member
Posts: 47
Joined: Mon Mar 31, 2008 1:00 pm
Location: Louisville, KY, USA

Re: Far jump in 64bit mode

Post by sngskunk »

okay, i will give that a try, thank you.
Currently Working On:
Bootloader (Stage 1) (Complete)
Bootloader (Stage 2) (Inprogress)
User avatar
sngskunk
Member
Member
Posts: 47
Joined: Mon Mar 31, 2008 1:00 pm
Location: Louisville, KY, USA

Re: Far jump in 64bit mode

Post by sngskunk »

Okay well it didn't work here is what bochs gave me:

Code: Select all

00009322702e[CPU0 ] LGDT64_Ms: loaded base64 address is not in canonical form!
00009322702e[CPU0 ] interrupt(long mode): IDT entry extended attributes DWORD4 TYPE != 0
My code:

Code: Select all

gdtInit:
   lgdt              [gdtP]

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

	push	  0x8
	lea      rax, [gdtInitNext]
	push	  rax
	retf  ;<-- Fails here

gdtInitNext:
	ret
Currently Working On:
Bootloader (Stage 1) (Complete)
Bootloader (Stage 2) (Inprogress)
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: Far jump in 64bit mode

Post by jnc100 »

I've just tried that technique (albeit assembled under yasm but it should produce the same code) in my bootloader and it seemed to work fine. Are you definitely in 64-bit long mode (not compatibility), cs.l = 1, cs.d = 0 and assembling in a section with the BITS 64 directive?

Regards,
John.

edit: I note you've just edited your post to change the error message that's produced. The new one seems to imply the error is with the lgdt instruction? If not, suggest you use bochs debugger and examine the value of rax after the lea instruction.
User avatar
sngskunk
Member
Member
Posts: 47
Joined: Mon Mar 31, 2008 1:00 pm
Location: Louisville, KY, USA

Re: Far jump in 64bit mode

Post by sngskunk »

Here is my GDT:

Code: Select all

gdt[0] = (u64bit)0x0;
gdt[1] = (u64bit)0x390400;
gdt[2] = (u64bit)0x10000;
gdt[3] = (u64bit)0x3F0400;
Is this correct?
Currently Working On:
Bootloader (Stage 1) (Complete)
Bootloader (Stage 2) (Inprogress)
HJED
Member
Member
Posts: 61
Joined: Tue Sep 04, 2007 4:18 am
Location: the world wide web
Contact:

Re: Far jump in 64bit mode

Post by HJED »

jnc100 wrote:I've just tried that technique (albeit assembled under yasm but it should produce the same code) in my bootloader and it seemed to work fine. Are you definitely in 64-bit long mode (not compatibility), cs.l = 1, cs.d = 0 and assembling in a section with the BITS 64 directive?

Regards,
John.

edit: I note you've just edited your post to change the error message that's produced. The new one seems to imply the error is with the lgdt instruction? If not, suggest you use bochs debugger and examine the value of rax after the lea instruction.
yasm implemnts 64-bit instructions and addresses difrently from NASM
.................................. um what should i put here .............................?..........................................
..... :D................
User avatar
sngskunk
Member
Member
Posts: 47
Joined: Mon Mar 31, 2008 1:00 pm
Location: Louisville, KY, USA

Re: Far jump in 64bit mode

Post by sngskunk »

okay well i can use yasm but I am have trouble with my make file

Here is what happens:

Code: Select all

build
 |
 |- Makefile
 |- kernel
 |- load.o   <-- is put in build directory when it should be in asm
kernel
 |
 |- asm
     |- load.s
     |- (load.o) <-- load.o should be here
 |- kMain.c
 |- kMain.o
Heres my make script:

Code: Select all

SOURCES=../kernel/asm/load.o ../kernel/kMain.o

CFLAGS=-I ../kernel/include -m64 -nostdlib -nostdinc -nodefaultlibs -fno-builtin -fno-stack-protector
LDFLAGS=-melf_x86_64 -Tlink.ld
ASFLAGS=-felf64

all: $(SOURCES) link 

clean:
	rm *.o ../kernel/asm/*.o ../kernel/*.o kernel

link:
	ld $(LDFLAGS) -o kernel $(SOURCES)

.s.o:
	yasm $(ASFLAGS) $<
Currently Working On:
Bootloader (Stage 1) (Complete)
Bootloader (Stage 2) (Inprogress)
jnc100
Member
Member
Posts: 775
Joined: Mon Apr 09, 2007 12:10 pm
Location: London, UK
Contact:

Re: Far jump in 64bit mode

Post by jnc100 »

HJED wrote:yasm implemnts 64-bit instructions and addresses difrently from NASM
Please provide a bit more information. In what sense?
sngskunk wrote:Here is my GDT:

Code: Select all

gdt[0] = (u64bit)0x0;
gdt[1] = (u64bit)0x390400;
gdt[2] = (u64bit)0x10000;
gdt[3] = (u64bit)0x3F0400;
Is this correct?
Er, no. I don't think so. How did you manage to generate those values? I suggest you break it down field by field and decide exactly what you want to put in each field.

Regards,
John.
User avatar
sngskunk
Member
Member
Posts: 47
Joined: Mon Mar 31, 2008 1:00 pm
Location: Louisville, KY, USA

Re: Far jump in 64bit mode

Post by sngskunk »

Okay so I decided to go back an redo my GDT code but I am getting an error like this below:

Code: Select all

00009340690e[CPU0 ] return_protected: CS selector null
00009340690e[CPU0 ] interrupt(long mode): IDT entry extended attributes DWORD4 TYPE != 0
My assembly code:

Code: Select all

[BITS 64]

%include "../kernel/include/asm/common.s"

[GLOBAL gdtInit]
[EXTERN gdtP]

gdtInit:
	lgdt	[gdtP]
	
	push	0x08
	lea		rax, [gdtInitFinish]
	push	rax
	retf    ;<--- Code stops here and returns error above

	gdtInitFinish:
		ret
Here is my gdt.c:

Code: Select all

/*
 * Global Descriptor Structure
 */
typedef struct {
	u16bit	limit;
	u16bit	baseLow;
	u08bit	baseMid;
	u08bit	type;
	u08bit	flags;
	u08bit	baseHigh;
} __attribute__((packed)) gdtEntry;

/*
 * Global Descriptor Pointer
 */
typedef struct {
	u16bit	limit;
	u64bit	base;
} __attribute__((packed)) gdtPointer;

/* Setup Table and Pointer */
gdtEntry gdt[4];
gdtPointer gdtP;

void gdtStart(void) {
	/* Create GDT entries */
	gdtSet(0, 0, 0);
	gdtSet(1, 0x9C, 0x20);
	gdtSet(2, 0x90, 0);
	gdtSet(3, 0xFC, 0x20);
	
	/* Create GDT Pointer */
	gdtP.limit = (sizeof(gdtEntry) * 4) - 1;
	gdtP.base = (u64bit)&gdt;
	
	gdtInit();
}

void gdtSet(u08bit number, u08bit type, u08bit flags) {
	/* Set Base and Limit Address */
	gdt[number].baseLow = 0;
	gdt[number].baseMid = 0;
	gdt[number].baseHigh = 0;
	gdt[number].limit = 0;
	
	/* Set Type and Flags */
	gdt[number].type = type;
	gdt[number].flags = flags;
}
Currently Working On:
Bootloader (Stage 1) (Complete)
Bootloader (Stage 2) (Inprogress)
User avatar
sngskunk
Member
Member
Posts: 47
Joined: Mon Mar 31, 2008 1:00 pm
Location: Louisville, KY, USA

Re: Far jump in 64bit mode

Post by sngskunk »

Am i creating my GDT correctly, or is in the gdtInit() function?

Any help would be great! Thanks!
Currently Working On:
Bootloader (Stage 1) (Complete)
Bootloader (Stage 2) (Inprogress)
HJED
Member
Member
Posts: 61
Joined: Tue Sep 04, 2007 4:18 am
Location: the world wide web
Contact:

Re: Far jump in 64bit mode

Post by HJED »

yasm is different then nasm2 for 64-bit instructions see http://www.tortall.net/projects/yasm/wiki/AMD64
.................................. um what should i put here .............................?..........................................
..... :D................
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Re: Far jump in 64bit mode

Post by AJ »

Hi,

Firstly, have you done a CLI? If not, do you have a valid 64 bit IDT loaded (which handles exceptions and IRQ's at minimum)? If so, check that your IDT entries are really all valid 64 bit versions (even if you are in compatibility mode).

Secondly, the original error you had:
00009322702e[CPU0 ] LGDT64_Ms: loaded base64 address is not in canonical form!
00009322702e[CPU0 ] interrupt(long mode): IDT entry extended attributes DWORD4 TYPE != 0
is because 64 bit modes require all pointers to be in canonical form. This means that the MSB's of the pointer must all be the same as the last valid MSB (this means bit 47 for the first long mode implementation).

Cheers,
Adam
Post Reply