OSDev.org

The Place to Start for Operating System Developers
It is currently Wed Apr 24, 2024 6:11 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Leaving long mode
PostPosted: Mon Sep 15, 2008 3:53 pm 
Offline
Member
Member

Joined: Fri Jul 11, 2008 5:15 am
Posts: 342
Location: Hungary
I am currently writing my boot loader. It successfully enters 32-bit protected mode, enables paging, and also provides a V86 monitor to the PE image attached to it as a payload. The image may specify either i386 or amd64 processor, and the loader will prepare the environment requested. If the image is a 64-bit image, the loader successfully enters long mode (I have used the AMD manual and also have taken a peek at BareMetal OS). My problem is, I can't exit long mode... I believe I am following the steps outlined in the manual (page 44 in the 134 page PDF), but get a triple fault in Bochs.

Here is the code I use for returning to legacy protected mode. The first few lines save the environment, so that the loader can re-enter long mode (for example after calling a BIOS interrupt or executing some v86 code).
Code:
LdrTransition64To32:
        xchg    rax, rcx                        ; swap regs (call destination -> rcx)
        mov     esi, offset LoaderData          ; load address of data structure
        pushfq                                  ;
        pop     [rsi + 1Ch]                     ; save flags
        mov     [rsi + 0Ch], esp                ; save rsp
        sidt    fword ptr [rsi + 3Ch]           ; save IDTR
        cli                                     ; disable interrupts
; this is based on the AMD manual
        mov     rax, cr0                        ;
        and     eax, 7FFFFFFFh                  ; disable paging
        mov     cr0, rax                        ;
        mov     eax, mrTaskLoaderx86PageDirStart; load cr3 with 32-bit page table
        mov     cr3, rax                        ;
        mov     ecx, 0C0000080h                 ; EFER MSR number
        rdmsr                                   ; read EFER
        and     eax, not 100h                   ;
        wrmsr                                   ; write EFER
        mov     rax, cr4                        ; disable PAE
        and     al, not 20h                     ;
        mov     cr4, rax                        ;
; below this line is speculation, this may be outright wrong.
        mov     rax, offset LdrTransition64To32$0 ; address to return to
        pushfq                                  ; fake an iretq
        push    Code32R0Sel                     ;
        push    rax                             ;
        iretq                                   ;

(I know that hard-coding offsets is bad practice, however I can't yet get the 64-bit MASM to accept a structure field name as an offset.)

What am I doing wrong? Bochs says
Code:
00055028596e[CPU0 ] SetCR0: attempt to leave 64 bit mode directly to legacy mode !
00055028596d[CPU0 ] exception(0x0d): error_code=0000
00055028596d[CPU0 ] interrupt(): vector = 13, INT = 0, EXT = 1
00055028596d[CPU0 ] interrupt(long mode): INTERRUPT TO SAME PRIVILEGE


If I first try to disable LME, then disable CR0.PG, I get
Code:
00055028597e[CPU0 ] WRMSR: attempt to change LME when CR0.PG=1
00055028597d[CPU0 ] exception(0x0d): error_code=0000
00055028597d[CPU0 ] interrupt(): vector = 13, INT = 0, EXT = 1
00055028597d[CPU0 ] interrupt(long mode): INTERRUPT TO SAME PRIVILEGE


And if I first try to disable PAE, I get
Code:
00055028594d[CPU0 ] MOV_RqCq: read of CR4
00055028596d[CPU0 ] MOV_CqRq: write to CR4 of 00000000:00000000
00055028596e[CPU0 ] SetCR4: attempt to change PAE when EFER.LMA=1
00055028596d[CPU0 ] exception(0x0d): error_code=0000
00055028596d[CPU0 ] interrupt(): vector = 13, INT = 0, EXT = 1
00055028596d[CPU0 ] interrupt(long mode): INTERRUPT TO SAME PRIVILEGE


Any suggestions?


Top
 Profile  
 
 Post subject: Re: Leaving long mode
PostPosted: Mon Sep 15, 2008 6:23 pm 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8561
Location: At his keyboard!
Hi,

From the top of my head, you'd probably need to:
    - load 32-bit "compatibility mode" segments (including CS)
    - disable paging (which should also turn off long mode)
    - load 16-bit protected mode segments
    - disable protected mode
    - load 16-bit real mode segments
I don't think you need to touch the EFER because you can't be in long mode with paging disabled; and you definitely won't need to disable PAE because the PAE enable/disable flag is ignored when paging is disabled.


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: Leaving long mode
PostPosted: Mon Sep 15, 2008 7:39 pm 
Offline
Member
Member
User avatar

Joined: Wed Feb 07, 2007 1:45 pm
Posts: 1401
Location: Eugene, OR, US
Except that he isn't trying to get all the way back to Real mode -- just to Pmode. So he only needs to do the first 2 steps -- especially the part about loading the hidden parts of the segment registers with 32bit pmode selectors.


Top
 Profile  
 
 Post subject: Re: Leaving long mode
PostPosted: Tue Sep 16, 2008 12:59 am 
Offline
Member
Member

Joined: Fri Jul 11, 2008 5:15 am
Posts: 342
Location: Hungary
Brendan wrote:
Hi,

From the top of my head, you'd probably need to:
    - load 32-bit "compatibility mode" segments (including CS)
    - disable paging (which should also turn off long mode)
    - load 16-bit protected mode segments
    - disable protected mode
    - load 16-bit real mode segments
I don't think you need to touch the EFER because you can't be in long mode with paging disabled; and you definitely won't need to disable PAE because the PAE enable/disable flag is ignored when paging is disabled.


Cheers,

Brendan


Thank you, I got it working. It is interesting, however, that the AMD manual does not mention loading CS with a 32-bit descriptor before disabling paging...


Top
 Profile  
 
 Post subject: Re: Leaving long mode
PostPosted: Fri Sep 27, 2013 1:58 am 
Offline
Member
Member
User avatar

Joined: Sun Feb 20, 2011 2:01 pm
Posts: 110
Long mode is enabled, and an attempt is made to enable paging while CS.L=1.

It does say this... it is obsucre though.
CS.L is 64 bit. Enable includes disable.
It is saying you need to be in compatibility mode.

_________________
Whoever said you can't do OS development on Windows?
https://github.com/ChaiSoft/ChaiOS


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: DotBot [Bot], Majestic-12 [Bot] and 208 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group