OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Oct 22, 2019 8:34 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Wrote a tutorial covering long mode
PostPosted: Sun Feb 21, 2010 3:52 am 
Offline
Member
Member

Joined: Sat Sep 29, 2007 5:43 pm
Posts: 127
Location: Amsterdam, The Netherlands
Hi,

I wrote a new article on the wiki today which covers setting up long mode. Any suggestions are welcome as well as making it more conform to the wiki itself (If somebody likes to). You can find the article here. I hope it will be of any use.


Regards,
Stephan J.R. van Schaik.


Top
 Profile  
 
 Post subject: Re: Wrote a tutorial covering long mode
PostPosted: Sun Feb 21, 2010 6:03 am 
Offline
Member
Member
User avatar

Joined: Thu Aug 11, 2005 11:00 pm
Posts: 1089
Location: Tartu, Estonia
First of all, this is absolutely great work :) I guess it will help many people fiddling around with the transition to long mode.

Second, I have some small hints. At the very end of the article, you clear the screen using "rep movsq". I guess you should set RDI to the start of video ram before doing so. In the same piece of code, instead of the power-consuming endless loop at the end, I would recommend to halt the CPU, so beginners who just copy and paste the article into some assembler won't heat up their CPUs too much. Finally, the binary numbers in your code are really nice as one can simply count which bit is set / cleared, but I would add some comment like "set bit 23", just to make things clear.

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


Top
 Profile  
 
 Post subject: Re: Wrote a tutorial covering long mode
PostPosted: Sun Feb 21, 2010 8:36 am 
Offline
Member
Member
User avatar

Joined: Fri May 16, 2008 7:13 pm
Posts: 301
Location: Hanoi, Vietnam
I have an idea on the CPUID part. You don't have to worry weather the CPU is from AMD or Intel. An piece of code below with detect 64-bit capability. And 64-bit supported means PAE supported, so you don't have to check for PAE if the CPU is 64-ready
Code:
mov eax, 80000000h  ; Extended-function 8000000h.
cpuid              ; Is largest extended function
cmp eax, 80000000h  ; any function > 80000000h?
jbe no_long_mode     ; If not, no long mode.
mov eax, 80000001h ; Extended-function 8000001h.
cpuid               ; Now EDX = extended-features flags.
bt edx, 29      ; Test if long mode is supported.
jnc no_long_mode      ; Exit if not supported.


Just in case you want to know, this code is taken from AMD manual, Chapter 14 section 8 :wink:

_________________
"Programmers are tools for converting caffeine into code."


Top
 Profile  
 
 Post subject: Re: Wrote a tutorial covering long mode
PostPosted: Sun Feb 21, 2010 10:25 am 
Offline
Member
Member

Joined: Sat Sep 29, 2007 5:43 pm
Posts: 127
Location: Amsterdam, The Netherlands
XenOS wrote:
First of all, this is absolutely great work :) I guess it will help many people fiddling around with the transition to long mode.

Second, I have some small hints. At the very end of the article, you clear the screen using "rep movsq". I guess you should set RDI to the start of video ram before doing so. In the same piece of code, instead of the power-consuming endless loop at the end, I would recommend to halt the CPU, so beginners who just copy and paste the article into some assembler won't heat up their CPUs too much. Finally, the binary numbers in your code are really nice as one can simply count which bit is set / cleared, but I would add some comment like "set bit 23", just to make things clear.

Thanks a lot. Yes, I should have set rdi to 0xB8000 #-o, I forgot about that. Will update the article.

quanganht wrote:
I have an idea on the CPUID part. You don't have to worry weather the CPU is from AMD or Intel.

I was expecting other x86-like processors to have some other flags, if they even actually support those functions, but I guess not.

quanganht wrote:
An piece of code below with detect 64-bit capability.And 64-bit supported means PAE supported, so you don't have to check for PAE if the CPU is 64-ready
Code:
mov eax, 80000000h  ; Extended-function 8000000h.
cpuid              ; Is largest extended function
cmp eax, 80000000h  ; any function > 80000000h?
jbe no_long_mode     ; If not, no long mode.
mov eax, 80000001h ; Extended-function 8000001h.
cpuid               ; Now EDX = extended-features flags.
bt edx, 29      ; Test if long mode is supported.
jnc no_long_mode      ; Exit if not supported.


Just in case you want to know, this code is taken from AMD manual, Chapter 14 section 8 :wink:

I saw the code in the manual once, but generally derived it myself based on the ideas I had about enabling long mode. Thanks for the information.

Edit: updated it.


Regards,
Stephan J.R. van Schaik.


Top
 Profile  
 
 Post subject: Re: Wrote a tutorial covering long mode
PostPosted: Mon Feb 22, 2010 8:09 am 
Offline
Member
Member
User avatar

Joined: Fri May 16, 2008 7:13 pm
Posts: 301
Location: Hanoi, Vietnam
What a great tutorial! Can you please continue with the IDT and interrupts ? (I won't be helpful as I found it a little confusing :( )

_________________
"Programmers are tools for converting caffeine into code."


Top
 Profile  
 
 Post subject: Re: Wrote a tutorial covering long mode
PostPosted: Mon Feb 22, 2010 11:26 am 
Offline
Member
Member

Joined: Sat Sep 29, 2007 5:43 pm
Posts: 127
Location: Amsterdam, The Netherlands
quanganht wrote:
What a great tutorial! Can you please continue with the IDT and interrupts ? (I won't be helpful as I found it a little confusing :( )

Sure, basically the IDT used for 64-bit is the same as the one used for 32-bit though with generally two exceptions: the entries have been extended with an additional eight bytes (where the first four bytes serve as part of the offset) and the pointer has been extended to 80-bit as well (16-bit size, 64-bit base).


Regards,
Stephan J.R. van Schaik.


Top
 Profile  
 
 Post subject: Re: Wrote a tutorial covering long mode
PostPosted: Sun Apr 18, 2010 7:45 am 
Offline

Joined: Thu Jul 09, 2009 4:43 am
Posts: 4
Thank for your work.

After entering long mode, U don't reload SS (mov ss,ax). It means that CPU continue using prot mode stack.
But when I try to set new LM stack, bochs fires SS exception, saying that bit P is not set.

I using GRUB2 -> 32bit stub in ELF64.

Should I setup 32bit gdt first, prior entering long mode?
Or this is some kind of bug in Bochs?

Any ideas?


Top
 Profile  
 
 Post subject: Re: Wrote a tutorial covering long mode
PostPosted: Sun Apr 18, 2010 8:33 am 
Offline
Member
Member

Joined: Sat Sep 29, 2007 5:43 pm
Posts: 127
Location: Amsterdam, The Netherlands
Hi,

The GDT used for entering long mode is actually temporary. You ought to set up another GDT afterwards. In my kernel the new GDT to be loaded looks like this:
Code:
GDT:
    .Null:                              equ $ - GDT
                                        dq 0
    .KCode:                             equ $ - GDT
                                        dw 0
                                        dw 0
                                        db 0
                                        db 0x98
                                        db 0x20
                                        db 0
    .KData:                             equ $ - GDT
                                        dw 0
                                        dw 0
                                        db 0
                                        db 0x92
                                        db 0x20
                                        db 0
    .UCode:                             equ $ - GDT
                                        dw 0
                                        dw 0
                                        db 0
                                        db 0xF8
                                        db 0x20
                                        db 0
    .UData:                             equ $ - GDT
                                        dw 0
                                        dw 0
                                        db 0
                                        db 0xF2
                                        db 0x20
                                        db 0
    .Pointer:                           dw $ - GDT - 1
                                        dq GDT


And the way I load the GDT and set up the segment registers looks like this:
Code:
    mov rsp, 0x90000
    lgdt [GDT.Pointer]
    push QWORD GDT.KData
    push QWORD 0x90000
    pushfq
    pushfq
    pop rax
    and rax, 1111111111111111111111111111111111111111111111101011111011111111b
    push rax
    popfq
    push QWORD GDT.KCode
    push QWORD .Flush
    iretq
   
.Flush:
    mov ax, GDT.KData
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax


You might want to look at the AMD64 Architecture Programmer's Manual, Volume 2 to be more specific, as this manual contains more information about how the GDT should be laid out, but also about the EFLAGS I modified before using the IRETQ-instruction to reload the segment registers, more specifically the CS and SS registers.


Regards,
Stephan J.R. van Schaik.


Top
 Profile  
 
 Post subject: Re: Wrote a tutorial covering long mode
PostPosted: Sun Apr 18, 2010 5:31 pm 
Offline
Member
Member

Joined: Thu Mar 25, 2010 11:26 pm
Posts: 1801
Location: Melbourne, Australia
Stephan,

Gotta congratulate you on your Long Mode tutorial. It is excellent. I have one possible correction, though I must admit I haven't actually tried your code.

Code:
    ; Set the A-register to 0x00004000.
    or eax, 0x00004000

    ; Set control register 3 to the A-register.
    mov cr3, eax

Shouldn't the 'or' be a 'mov' ?

- gerryg400

_________________
If a trainstation is where trains stop, what is a workstation ?


Top
 Profile  
 
 Post subject: Re: Wrote a tutorial covering long mode
PostPosted: Sun Apr 18, 2010 5:43 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 29, 2008 1:07 pm
Posts: 550
Location: Throw a dart at central Texas
Not if he only wants to set that one bit. OR will leave all of the other bits alone, and so will preserve the other flags (such as paging enabled and whatnot).

_________________
Owner of Fawkes Software.
Wierd Al wrote:
You think your Commodore 64 is really neato,
What kind of chip you got in there, a Dorito?


Top
 Profile  
 
 Post subject: Re: Wrote a tutorial covering long mode
PostPosted: Sun Apr 18, 2010 6:17 pm 
Offline
Member
Member

Joined: Thu Mar 25, 2010 11:26 pm
Posts: 1801
Location: Melbourne, Australia
CR3 holds an address (of pml4). Well it holds some bits in the lower 12 bits, but Stephan is not setting those. Fairly sure it sure be a 'mov'

- gerryg400

_________________
If a trainstation is where trains stop, what is a workstation ?


Top
 Profile  
 
 Post subject: Re: Wrote a tutorial covering long mode
PostPosted: Sun Apr 18, 2010 7:14 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 29, 2008 1:07 pm
Posts: 550
Location: Throw a dart at central Texas
Image

I was thinking CR4. My bad.

_________________
Owner of Fawkes Software.
Wierd Al wrote:
You think your Commodore 64 is really neato,
What kind of chip you got in there, a Dorito?


Top
 Profile  
 
 Post subject: Re: Wrote a tutorial covering long mode
PostPosted: Sun Apr 18, 2010 11:09 pm 
Offline
Member
Member

Joined: Thu Mar 25, 2010 11:26 pm
Posts: 1801
Location: Melbourne, Australia
Quote:
After entering long mode, U don't reload SS (mov ss,ax). It means that CPU continue using prot mode stack.
But when I try to set new LM stack, bochs fires SS exception, saying that bit P is not set.

GDTR,

These are my findings (mainly from trial and error because the manuals aren't always very descriptive.)

You don't need to load SS. It's difficult to understand (for me anyway) but in long mode there are no data/stack segments. It's just one big memory area.

If you want to load SS, load the NULL selector. Other values crash my machine. Not sure about yours.

Also you don't need to load DS or ES. If you do load them make sure the P bit in the selector is set. P not set crashes my machine. But the processor ignores every other part of a data descriptor. Even the DPL is ignored. You don't need to have separate RINGn data segments. You use the paging mechanism for protection.

As I said this information was gathered by trial and error. I would like to hear from anyone who has a different experience.

- gerryg400

_________________
If a trainstation is where trains stop, what is a workstation ?


Top
 Profile  
 
 Post subject: Re: Wrote a tutorial covering long mode
PostPosted: Sun Apr 18, 2010 11:24 pm 
Offline
Member
Member

Joined: Sat Sep 29, 2007 5:43 pm
Posts: 127
Location: Amsterdam, The Netherlands
gerryg400 wrote:
Stephan,

Gotta congratulate you on your Long Mode tutorial. It is excellent. I have one possible correction, though I must admit I haven't actually tried your code.

Code:
    ; Set the A-register to 0x00004000.
    or eax, 0x00004000

    ; Set control register 3 to the A-register.
    mov cr3, eax

Shouldn't the 'or' be a 'mov' ?

- gerryg400

Yes, most likely. I don't have that revision of my source code any more so I'm not sure whether this is just me being confused with the OR and MOV instructions all around, or if it was something I got directly out of my source. In a newer version of my source I handle it like this (when creating the 32-bit page table):
Code:
    mov edi, DWORD [FreeMemory]
    add edi, 0xFFF
    and edi, 11111111111111111111000000000000b
    mov cr3, edi


And in the 64-bit version I use:
Code:
    mov edi, cr3



Regards,
Stephan J.R. van Schaik.


Top
 Profile  
 
 Post subject: Re: Wrote a tutorial covering long mode
PostPosted: Mon Apr 19, 2010 6:51 am 
Offline

Joined: Thu Jul 09, 2009 4:43 am
Posts: 4
Hi there, few question about tutorial here
Code:
    mov di, 0x1000
    xor ax, ax
    mov cx, 16384
    rep stosb  ; Clear the memory.
After this part di points to 4096+16384, so we need to set it one more time: mov di, 0x1000
Code:
    ; Set the word at the destination index to 0x2003.
    mov WORD [di], 0x2003
     ; Add 0x1000 to the destination index.
    add di, 0x1000
     ; Set the word at the destination index to 0x3003.
    mov WORD [di], 0x3003
     ; Add 0x1000 to the destination index.
    add di, 0x1000
     ; Set the word at the destination index to 0x4003.
    mov WORD [di], 0x4003
     ; Add 0x1000 to the destination index.
    add di, 0x1000
...and we dont need last add di, 0x1000

Next, we need to set di to 0x4000, not add 0x4000 to current value: mov di,0x4000
Code:
    ; Set the destination index to 0x4000.
    add di, 0x4000

    ; Set the B-register to 0x00000003.
    mov ebx, 0x00000003

    ; Set the C-register to 512.
    mov cx, 512


Last note. We assume that ecx and edi (their high part) is zero, but it not always true.
mb use edi, ecx insted? (or zero them at begining)

UPD
AMD64 APM vol. 2, page 357
"- Data-segment descriptors for software running in compatibility mode. The DS, ES, and SS
segments are ignored in 64-bit mode.
See “Data-Segment Descriptors” on page 87 for more
information."

Best wishes,
Igor


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 24 posts ]  Go to page 1, 2  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 2 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