Realmode to 64bit long mode switch problems
Posted: Tue Mar 24, 2009 5:11 am
Hey all,
So after some discussions in other threads and looking at the long mode tutorial I've run into a few snags with the switch to long mode...
Now I wanted to jump straight to the kernel having paging set to the higher-half model with paging set to map 0xFFFF800000000000 to 0x100000 phys (1mb). But based on what I'm trying to do with the jmp to switch cs to 64bit code selector / linear addr. being limited to 32bit this would not seem possible... this makes the kernel linking an issue now... so how would I perform the switch from 16bit real straight to 64bit kernel at the higher half addr of 0xFFFF800000000000??
I tried to embedded the code (db's for opcodes) for the push/retf trick to do the jump straight to 0xFFFF800000000000 but that also didn't seem to get me anywhere.
I've checked that the kernel code is correct and is indeed loaded at 0x100000.
RDMSR/WRMSR I created macros for as follows... why?... for some reason I originally started the bootloader code in tasm.. no biggie, I've added the opcodes that aren't supported as macros..:
Upon reaching the jump code bochs/qemu and real h/w just reboot...
any ideas? the mode switch code is from the wiki tut as well as the basic temp paging setup stuff (for now until i get this higher half thing right and can setup the paging properly)
Also, I presume theres no point to setup IDT before being in long mode as you'd reload it immediately in long mode using the new 16byte IDT descriptors?
John
So after some discussions in other threads and looking at the long mode tutorial I've run into a few snags with the switch to long mode...
Code: Select all
; LOAD our 64bit GDT
mov edi,offset GDTReg
lgdt fword ptr ds:[edi] ; Load 64bit Kernel GDT.
;SETUP PML4/PDs
xor bx,bx
mov es,bx
cld
mov di,0a000h
mov ax,0b00fh
stosw
xor ax,ax
mov cx,07ffh
rep stosw
mov ax,0c00fh
stosw
xor ax,ax
mov cx,07ffh
rep stosw
mov ax,018fh
stosw
xor ax,ax
mov cx,07ffh
rep stosw
;SETUP LONG MODE and PAGING OPTIONS
mov eax,10100000b ; Set PAE and PGE.
mov cr4,eax
mov edx,0000a000h ; Point CR3 at PML4.
mov cr3,edx
mov ecx,0c0000080h ; Specify EFER MSR.
RDMSR ; Read MSR.
or eax,00000100h ; Enable Long Mode.
WRMSR ; Write MSR Back.
mov ebx,cr0
or ebx,80000001h ; Enable Long Mode By Enabling Paging and Protection.
mov cr0,ebx
; !!!ALL WORKS TILL HERE!!!!
dw 0ea66h
dd 0100000h
dw 08h
I tried to embedded the code (db's for opcodes) for the push/retf trick to do the jump straight to 0xFFFF800000000000 but that also didn't seem to get me anywhere.
I've checked that the kernel code is correct and is indeed loaded at 0x100000.
RDMSR/WRMSR I created macros for as follows... why?... for some reason I originally started the bootloader code in tasm.. no biggie, I've added the opcodes that aren't supported as macros..:
Code: Select all
;=======================================================================================
; Obtain CPU Information.
; Function in EAX.
;=======================================================================================
CPUID MACRO
db 0fh,0a2h
ENDM
;=======================================================================================
; Read Time Stamp Counter
; edx:eax returns counter.
;=======================================================================================
RDTSC MACRO
db 0fh,31h
ENDM
;=======================================================================================
; (Branch Not Taken) Branch Hint.
;=======================================================================================
BNT MACRO
db 2eh
ENDM
;=======================================================================================
; (Branch Taken) Branch Hint.
;=======================================================================================
BTK MACRO
db 3eh
ENDM
;=======================================================================================
; Read Model Specific Register.
;=======================================================================================
RDMSR MACRO
db 0fh,32h
ENDM
;=======================================================================================
; Write Model Specific Register.
;=======================================================================================
WRMSR MACRO
db 0fh,30h
ENDM
any ideas? the mode switch code is from the wiki tut as well as the basic temp paging setup stuff (for now until i get this higher half thing right and can setup the paging properly)
Also, I presume theres no point to setup IDT before being in long mode as you'd reload it immediately in long mode using the new 16byte IDT descriptors?
John