Entering the 64-bit Submode from Long 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
teodori
Member
Member
Posts: 103
Joined: Wed Nov 14, 2012 4:55 pm

Entering the 64-bit Submode from Long Mode

Post by teodori »

Hello everyone, I managed to go into Long Mode with Compatibility SubMode, but what I wanted is Long Mode with 64-Bit SubMode. I created a 64 bit GDT an loaded it, but bochs tells me that I am in:

Code: Select all

00014090084i[BIOS ] Booting from 0000:7c00
00014173256i[CPU0 ] WARNING: HLT instruction with IF=0!
00243956000p[SDL  ] >>PANIC<< User requested shutdown.
00243956000i[CPU0 ] CPU is in compatibility mode (halted)
00243956000i[CPU0 ] CS.d_b = 32 bit
00243956000i[CPU0 ] SS.d_b = 32 bit
00243956000i[CPU0 ] EFER   = 0x00000500
00243956000i[CPU0 ] | RAX=000000003f224f22  RBX=0000000000200003
00243956000i[CPU0 ] | RCX=00000000c0000080  RDX=0000000000000000
00243956000i[CPU0 ] | RSP=0000000000000200  RBP=0000000000000099
00243956000i[CPU0 ] | RSI=00000000000e00bb  RDI=0000000000005000
00243956000i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00243956000i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00243956000i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00243956000i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00243956000i[CPU0 ] | IOPL=0 id vip vif ac vm rf nt of df if tf sf zf af PF cf
00243956000i[CPU0 ] | SEG selector     base    limit G D
00243956000i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00243956000i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 ffffffff 1 1
00243956000i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00243956000i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00243956000i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00243956000i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00243956000i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
00243956000i[CPU0 ] |  MSR_FS_BASE:0000000000000000
00243956000i[CPU0 ] |  MSR_GS_BASE:0000000000000000
00243956000i[CPU0 ] | RIP=00000000000060ca (00000000000060ca)
00243956000i[CPU0 ] | CR0=0xe0000011 CR2=0x0000000000000000
00243956000i[CPU0 ] | CR3=0x00001000 CR4=0x000000b0
00243956000i[CPU0 ] 0x00000000000060ca>> jmp .-3 (0x000060c9) : EBFD
00243956000i[CMOS ] Last time is 1379024977 (Fri Sep 13 00:29:37 2013)
00243956000i[     ] restoring default signal behavior
00243956000i[CTRL ] quit_sim called with exit code 1
What am I doing wrong?
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Entering the 64-bit Submode from Long Mode

Post by xenos »

Did you make a far jump to a 64 bit code segment?
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
teodori
Member
Member
Posts: 103
Joined: Wed Nov 14, 2012 4:55 pm

Re: Entering the 64-bit Submode from Long Mode

Post by teodori »

Hm yeah I did one... but when I am in Compatibility Mode I can't use far jumps anymore. I know how to get to Long Mode, but I don't know how to get to 64-Bit Mode. Do I have to load the 64-Bit GDT before doing the far jump, like when I switch from 16-Bit to 32-Bit?

I looked up in http://wiki.osdev.org/User:Stephanvansc ... it_Submode

Code: Select all

# Load Control Register CR4
# Enable Page Size Extension (Bit 4 in CR4)
# Enable Physical Address Extension (Bit 5 in CR4)
# Enable Page Global Enabled (Bit 7 in CR4)
# Store Control Register CR4
movl %cr4, %eax
orl $(1<<4), %eax
orl $(1<<5), %eax
orl $(1<<7), %eax
movl %eax, %cr4

# Use Model Specific Register 0xC0000080
# Read from MSR
# Enable Long Mode (Bit 8 in MSR)
# Write to MSR
movl $0xc0000080, %ecx
rdmsr
orl $(1<<8), %eax
wrmsr

# Load Control Register CR0
# Enable Paging (Bit 31 in CR0)
# Store Control Register CR0
movl %cr0, %eax
orl $(1<<31), %eax
movl %eax, %cr0

# Setup all Segment Registers
# and reload Code Segment, Instruction Pointer
movw $0x0010, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss
ljmp $0x0008, $(INITSEG * 0x10 + JumpToLM)
JumpToLM:

.code64

# Load Global Descriptor Table
lgdt gdt64ptr
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Entering the 64-bit Submode from Long Mode

Post by xenos »

teodori wrote:Hm yeah I did one... but when I am in Compatibility Mode I can't use far jumps anymore.
Of course you can. That's also what the code you quoted is doing - it enters Long Mode, reloads the segment registers and does a far jump.
Do I have to load the 64-Bit GDT before doing the far jump, like when I switch from 16-Bit to 32-Bit?
Yes - you need a 64-bit code segment to which you can do the far jump, and that should be in your 64-bit GDT.
Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Entering the 64-bit Submode from Long Mode

Post by sortie »

For comparison, here is how I enter 64-bit long mode: https://gitorious.org/sortix/sortix/sou ... oot.s#L115
User avatar
xenos
Member
Member
Posts: 1121
Joined: Thu Aug 11, 2005 11:00 pm
Libera.chat IRC: xenos1984
Location: Tartu, Estonia
Contact:

Re: Entering the 64-bit Submode from Long Mode

Post by xenos »

Programmers' Hardware Database // GitHub user: xenos1984; OS project: NOS
Post Reply