Long mode basics

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
salil_bhagurkar
Member
Member
Posts: 261
Joined: Mon Feb 19, 2007 10:40 am
Location: India

Long mode basics

Post by salil_bhagurkar »

Hello.. I currently have my os in pmode. I need to also make it work in long mode. Is it possible that without changing much code other than paging, i can port it to long mode? Where can i get good examples for long mode?
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Post by Dex »

OK, here goes the shortest sample:

Code: Select all

        ORG     1600h

        USE16

        cli                             ; disable the interrupts, just in
                                        ; case they are not disabled yet

        lgdt    [cs:GDTR]               ; load GDT register

        mov     eax,cr0                 ; switch to protected mode
        or      al,1
        mov     cr0,eax

        jmp     CODE_SELECTOR:pm_start


NULL_SELECTOR = 0
DATA_SELECTOR = 1 shl 3                 ; flat data selector (ring 0)
CODE_SELECTOR = 2 shl 3                 ; 32-bit code selector (ring 0)
LONG_SELECTOR = 3 shl 3                 ; 64-bit code selector (ring 0)

GDTR:                                   ; Global Descriptors Table Register
  dw 4*8-1                              ; limit of GDT (size minus one)
  dq GDT                                ; linear address of GDT

GDT rw 4                                ; null desciptor
    dw 0FFFFh,0,9200h,08Fh              ; flat data desciptor
    dw 0FFFFh,0,9A00h,0CFh              ; 32-bit code desciptor
    dw 0FFFFh,0,9A00h,0AFh              ; 64-bit code desciptor

        USE32

pm_start:

        mov     eax,DATA_SELECTOR       ; load 4 GB data descriptor
        mov     ds,ax                   ; to all data segment registers
        mov     es,ax
        mov     fs,ax
        mov     gs,ax
        mov     ss,ax

        mov     eax,cr4
        or      eax,1 shl 5
        mov     cr4,eax                 ; enable physical-address extensions

        mov     edi,70000h
        mov     ecx,4000h shr 2
        xor     eax,eax
        rep     stosd                   ; clear the page tables

        mov     dword [70000h],71000h + 111b ; first PDP table
        mov     dword [71000h],72000h + 111b ; first page directory
        mov     dword [72000h],73000h + 111b ; first page table

        mov     edi,73000h              ; address of first page table
        mov     eax,0 + 111b
        mov     ecx,256                 ; number of pages to map (1 MB)
  make_page_entries:
        stosd
        add     edi,4
        add     eax,1000h
        loop    make_page_entries

        mov     eax,70000h
        mov     cr3,eax                 ; load page-map level-4 base

        mov     ecx,0C0000080h          ; EFER MSR
        rdmsr
        or      eax,1 shl 8             ; enable long mode
        wrmsr

        mov     eax,cr0
        or      eax,1 shl 31
        mov     cr0,eax                 ; enable paging

        jmp     LONG_SELECTOR:long_start

        USE64

long_start:

        mov     rax,'L O N G '
        mov     [0B8000h],rax

        jmp     long_start
You may need tto play with ORG for your loader etc.

PS: Code by Tomasz Grysztar, more examples here: http://board.flatassembler.net/topic.php?t=6206
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Long mode basics

Post by Brendan »

Hi,
salil_bhagurkar wrote:Hello.. I currently have my os in pmode. I need to also make it work in long mode. Is it possible that without changing much code other than paging, i can port it to long mode? Where can i get good examples for long mode?
You would need to change the paging code because long mode uses 4 levels of paging structures - PML4 (page-map level 4), PDP (page directory pointer table), PD (page directory) and PT (page table). Each of these tables is 4 KB and contains 512 entries that are 8 bytes each.

The task switch code needs to change (more registers to save/restore). There's also a few differences with interrupt handling. The code that starts processes may also need changing.

The rest of your code will mostly depend on what language it is. For high level languages you should be able to recompile the code and get it running if it was written as portable code to begin with.

For most assembly code you must change some things to suit (make any addressing 64-bit, remove "PUSHAD", "POPAD", "INC reg" and "DEC reg" instructions, etc) and you will probably want to rewrite everything to use the extra registers.

For the OS design, you may want to change some things depending how they're done now. For example, if you originally made some design decisions based on the amount of linear address space you had to work with, then you might want to redesign those parts now that the there's a huge amount of linear address space.

Also, if you've already got a 32-bit OS then you might want to add support for running 32-bit processes. This should be relatively easy (if applications never have direct access to kernel data structures and don't work with 32-bit physical addresses), but will mean having 2 different kernel APIs. The best way is to make the kernel APIs as similar as possible, so that the 32-bit kernel API is just a small layer over the 64-bit kernel functions.

@Dex: That's not the shortest "switch from real mode to long mode" code possible - you can switch directly from real mode to long mode without any intermediate 32-bit protected mode.


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.
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Re: Long mode basics

Post by Dex »

Brendan wrote: @Dex: That's not the shortest "switch from real mode to long mode" code possible - you can switch directly from real mode to long mode without any intermediate 32-bit protected mode.


Cheers,

Brendan
Thanks for the info Brendan, but the shortest is ment, as in the shortest of the two examples (There's another in the link).
Post Reply