OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Apr 19, 2024 7:00 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: 64 bit long mode cr0 issue
PostPosted: Tue Mar 21, 2017 12:04 pm 
Offline
Member
Member

Joined: Wed Mar 15, 2017 9:22 am
Posts: 40
Hi all

I'm using the code from the 'Setting Up Long Mode' tutorial on this website and all going well so far except when I reach the following code

Code:
   mov eax, cr0                   ; Set the A-register to control register 0.
   or eax, 1 << 31 | 1 << 0     ; Set the PG-bit, which is the 31nd bit, and the PM-bit, which is the 0th bit.
   mov cr0, eax                  ; Set control register 0 to the A-register.


When the code gets to the mov cr0,eax line, it faults the VM i am running it in with a 'Page Table Not Present' error. I've moved the address of the tables (1GB mode so two tables) into the CR3 register so not sure why it's faulting. Any ideas?

Bipman


Top
 Profile  
 
 Post subject: Re: 64 bit long mode cr0 issue
PostPosted: Tue Mar 21, 2017 1:28 pm 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1584
You have to enable big page feature for 1G pages. Run it in bochs, and use "page (address)" in debugger to see where the translation fails.


Top
 Profile  
 
 Post subject: Re: 64 bit long mode cr0 issue
PostPosted: Tue Mar 21, 2017 1:34 pm 
Offline
Member
Member

Joined: Wed Mar 15, 2017 9:22 am
Posts: 40
I'll give it a go thanks!


Top
 Profile  
 
 Post subject: Re: 64 bit long mode cr0 issue
PostPosted: Thu Mar 23, 2017 3:05 am 
Offline
Member
Member

Joined: Wed Mar 15, 2017 9:22 am
Posts: 40
OK, there was an issue with the flags in the PDPE table being wrong (thanks goodness for the Bochs debugger) but I've now sorted that. Trouble is, it triple faults still after I set paging active (no interrupts set up yet) :-

Code:
   Next at t=0
   (0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b          ; ea5be000f0
   <bochs:1> c
   (0).[92902891] ??? (physical address not available)
   Next at t=92902892
   (0).[92902892] ??? (physical address not available)
   <bochs:2> r
   rax: 00000000_e0000011 rcx: 00000000_c0000080
   rdx: 00000000_00000000 rbx: 00000000_0000933d
   rsp: 00000000_0009ffff rbp: 00000000_00008000
   rsi: 00000000_000e0000 rdi: 00000000_00021020
   r8 : 00000000_00000000 r9 : 00000000_00000000
   r10: 00000000_00000000 r11: 00000000_00000000
   r12: 00000000_00000000 r13: 00000000_00000000
   r14: 00000000_00000000 r15: 00000000_00000000
   rip: 00000000_00009436
   eflags 0x00010012: id vip vif ac vm RF nt IOPL=0 of df if tf sf zf AF pf cf
   <bochs:3> page 1
   PML4: 0x000000000002100b    ps         a pcd PWT S W P
   PDPE: 0x0000000000000081    PS g pat d a pcd pwt S R P
   physical address not available for linear 0x0000000000000000
   <bochs:4> quit
   (0).[92902892] ??? (physical address not available)


The (messy) code for the tables is :-

Code:
mov ax,ds         ;start of 64 bit page translation tables
   mov es,ax         ;
   mov edi,PML4E      ;
   xor ax,ax            ;mov 0 to al for storing in tables
   mov ecx,0x2000         ;8k for both tables
   rep stosb             ;store al 8k times
   
   mov eax,PDPE
   add eax,0xb            ;flags for the first entry in PM4LE
   mov  [PML4E],eax         ;
   
   mov edi,PDPE            ;Next the three entries for the 3 gigs of code and memory
   mov eax,0x81            ;Flags 0b00000010000001
   mov [edi],eax         ;store flags+0 base address
                     ;next part of address will be 0 too
   mov [edi+4],dword 0      ;store 0 for the next part of the address + 0 in NX bit
   add edi,dword 8         ;Next table
   
   mov eax,dword 0x81      ;
   bts eax,30            ;set 2GB start
   mov [edi],eax         ;
   xor eax,eax
   bts eax,31            ;set 'no eecute' bit as it's data
   mov [edi+4],eax
   add edi,dword 8         ;next table

   mov eax,dword 0x81      ;
   bts eax,31            ;3GB
   mov [edi],eax
   xor eax,eax
   bts eax,31            ;no execute bit set as this is data
   mov [edi+4],eax
   add edi,dword  8
   
   mov eax,0xc0000000      ;4GB
   add eax,dword 0x81      ;
   mov [edi],eax
   xor eax,eax
   bts eax,31            ;no execute bit set as this is data
   mov [edi+4],eax
   add edi,dword 8
   
   
   mov eax, PML4E          ; Pointer to PML4 table (<4GB).
   mov cr3, eax          ; Initialize CR3 with PML4 base.


It must be an issue with my paging table, I wanted the first 1GB from 0:0 up to 1GB to be a code page and I've set it R/W for now. Can I not use 0:0 as the first address in the table? I'm basically wanting to set the first 1GB to code and the rest to data as there will only be one process running.

Bipman


Top
 Profile  
 
 Post subject: Re: 64 bit long mode cr0 issue
PostPosted: Fri Mar 24, 2017 2:57 am 
Offline
Member
Member

Joined: Wed Mar 15, 2017 9:22 am
Posts: 40
I'm now running in Virtualbox under a 64 bit OS as I discovered the 'other' OS i was using was not 64 bit. Anyway, the same still occurs and a view of the tables shows:-

Code:
VBoxDbg> dptg 0x21000
%%0000000000021000 (index 0x0):
000 %0000000000000000: 0000000000000081 big phys=0000000000000000 p  r s na nd avl=00             
001 %0000000000200000: 8000000040000081 big phys=0000000040000000 p  r s na nd avl=00            NX
002 %0000000000400000: 8000000080000081 big phys=0000000080000000 p  r s na nd avl=00            NX
003 %0000000000600000: 80000000c0000081 big phys=00000000c0000000 p  r s na nd avl=00            NX


Which looks OK to me. But when I run the following code:-

Code:
   mov eax, cr0 ; Read CR0.
   bts eax, 31 ; Set PG=1.
   mov cr0, eax ; Write CR0.


I get a triple fault with

Code:
eax=80000011 ebx=00000000 ecx=c0000080 edx=00000000 esi=000094d8 edi=00021018
eip=000094b2 esp=0009ffff ebp=00008000 iopl=0 rf nv up di pl zr na po nc
cs=0008 ds=0010 es=0010 fs=0010 gs=0010 ss=0010               eflags=00010046
u: error: DBGCCmdHlpVarToDbgfAddr failed on '0008:000094b2 L 0': VERR_PAGE_TABLE_NOT_PRESENT


If I try and display the tables I get

Code:
dptg 0
%%0000ff53f000f000 (base %0000000000000000 / index 0x0):
error: VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS:  Reading PTE memory at %%0000ff53f000f000.


I'm so nearly there but cannot work out what the issue is, any ideas?

Bipman


Top
 Profile  
 
 Post subject: Re: 64 bit long mode cr0 issue
PostPosted: Fri Mar 24, 2017 3:49 am 
Offline
Member
Member

Joined: Sat Nov 10, 2012 1:16 pm
Posts: 62
Honestly, it'd help if you'd dump CR0~CR4 after the triple fault also.


Top
 Profile  
 
 Post subject: Re: 64 bit long mode cr0 issue
PostPosted: Fri Mar 24, 2017 5:29 am 
Offline
Member
Member

Joined: Wed Mar 15, 2017 9:22 am
Posts: 40
OK, here they are

Code:
cr0=0000000080000011
cr2=0000000000000080
cr3=0000000000020000
cr4=0000000000000020
cr8=0000000000000000


Bipman


Top
 Profile  
 
 Post subject: Re: 64 bit long mode cr0 issue
PostPosted: Fri Mar 24, 2017 11:18 am 
Offline
Member
Member

Joined: Wed Mar 15, 2017 9:22 am
Posts: 40
Before the Page Fault the table looks OK

Code:
VBoxDbg> dpd
%%0000000000021000 (index 0x0):
000 %0000000000000000: 0000000000000083 big phys=0000000000000000 p  w s na nd avl=00             
001 %0000000000200000: 8000000040000083 big phys=0000000040000000 p  w s na nd avl=00            NX
002 %0000000000400000: 8000000080000083 big phys=0000000080000000 p  w s na nd avl=00            NX
003 %0000000000600000: 80000000c0000083 big phys=00000000c0000000 p  w s na nd avl=00            NX
004 %0000000000800000: 0000000000000000 4kb phys=0000000000000000 np r s na    avl=00           
005 %0000000000a00000: 0000000000000000 4kb phys=0000000000000000 np r s na    avl=00           
006 %0000000000c00000: 0000000000000000 4kb phys=0000000000000000 np r s na    avl=00           
007 %0000000000e00000: 0000000000000000 4kb phys=0000000000000000 np r s na    avl=00           
008 %0000000001000000: 0000000000000000 4kb phys=0000000000000000 np r s na    avl=00           
009 %0000000001200000: 0000000000000000 4kb phys=0000000000000000 np r s na    avl=00           
00a %0000000001400000: 0000000000000000 4kb phys=0000000000000000 np r s na    avl=00 


Although I'm not sure where items 4+ come from as the table is 0's past 3. Once I set the cr0 register for PG=1 this table is just full of rubbish.
CR registers before the fault are

Code:
cr0=00000011 cr2=00000000
cr3=00020000 cr4=00000020


Does it look OK?

Bipman


Top
 Profile  
 
 Post subject: Re: 64 bit long mode cr0 issue
PostPosted: Fri Mar 24, 2017 9:40 pm 
Offline
Member
Member

Joined: Sat Nov 10, 2012 1:16 pm
Posts: 62
The CR registers all look okay for the most part; on the other hand, I'm not sure why in that last one you're doing "dptg 0" instead of "dptg 0x21000" to see the current tables. (See a couple of lines down about where your IDT currently is for why that'd give entirely wrong information for debugging - IDT entries have basically no resemblance to page-table entries.)

Well, let's narrow down what could still be going wrong here.

Do you have an IDT set up yet? (It looks like the answer is "yes", but the entries appear to be trash or at least of the wrong size, leading to the page fault at 00000080 as CR2 says, which would be where the double-fault IDT entry is if the IDT base is 00000000.)

Do you have the timer interrupt disabled or remapped at this point? (If you don't, that's going to immediately make the CPU think you've double-faulted.)


Top
 Profile  
 
 Post subject: Re: 64 bit long mode cr0 issue
PostPosted: Sat Mar 25, 2017 3:03 am 
Offline
Member
Member

Joined: Wed Mar 15, 2017 9:22 am
Posts: 40
Hi

Interrupts are cleared and so there is no IDT table for now. I was going to do this once I had managed to get into 64 bit long mode. The dptg 0x2100 shows (although I'm not sure what the 0,200000,400000,600000 are) :-

Code:
  VBoxDbg> dptg 0x21000
  %%0000000000021000 (index 0x0):
  000 %0000000000000000: 0000000000000083 big phys=0000000000000000 p  w s na nd avl=00             
  001 %0000000000200000: 8000000040000083 big phys=0000000040000000 p  w s na nd avl=00            NX
  002 %0000000000400000: 8000000080000083 big phys=0000000080000000 p  w s na nd avl=00            NX
  003 %0000000000600000: 80000000c0000083 big phys=00000000c0000000 p  w s na nd avl=00            NX
  VBoxDbg>


Unless you have to have an IDT even if interrupots are disabled I can't see the problem. I must be missing something really simple.

Bipman


Top
 Profile  
 
 Post subject: Re: 64 bit long mode cr0 issue
PostPosted: Sat Mar 25, 2017 5:14 am 
Offline
Member
Member

Joined: Thu Aug 13, 2015 4:57 pm
Posts: 384
In the last piece of code you've posted you only enable paging, not protected mode? Have you changed your code from the original so that those are now done separately? It's a bit difficult to follow when there's only bits and pieces. Also debug info from Bochs might be a bit more descriptive.

If you can show the relevant code, Bochs error message and dump relevant registers and memory regions + paging info it might be more useful. I'd suggest always including the relevant pieces as none of us can know what changes from post to post: you might have changed some code, some of the registers might now be different.. It's really difficult trying to guess which posts of yours are "in sync"..


Top
 Profile  
 
 Post subject: Re: 64 bit long mode cr0 issue
PostPosted: Sat Mar 25, 2017 6:11 am 
Offline
Member
Member

Joined: Wed Mar 15, 2017 9:22 am
Posts: 40
OK, here goes. It goes into 32 bit protected mode first, and then tried to go to the 64 bit mode. To save using up space with the code the link to the asm file is here:-

https://www.dropbox.com/s/rnhhraab0efvc88/SOSOS.asm?dl=0

Below is the debug output from Virtualbox as I am using that now due to memory usage of over 2GB :-

Code:
eax=80000011 ebx=00000000 ecx=c0000080 edx=00000000 esi=0000f4a0 edi=00021018
eip=0000949b esp=0009ffff ebp=00008000 iopl=0 rf nv up di pl zr na po nc
cs={0008 base=00000000 limit=ffffffff flags=c09b} dr0=00000000 dr1=00000000
ds={0010 base=00000000 limit=ffffffff flags=c093} dr2=00000000 dr3=00000000
es={0010 base=00000000 limit=ffffffff flags=c093} dr6=ffff0ff0 dr7=00000400
fs={0010 base=00000000 limit=ffffffff flags=c093} cr0=80000011 cr2=00000080
gs={0010 base=00000000 limit=ffffffff flags=c093} cr3=00020000 cr4=00000020
ss={0010 base=00000000 limit=ffffffff flags=c093} cr8=00000000
gdtr=000094b9:0017  idtr=00000000:ffff  eflags=00010046
ldtr={0000 base=00000000 limit=0000ffff flags=0082}
tr  ={0000 base=00000000 limit=0000ffff flags=008b}
sysenter={cs=0000 eip=00000000 esp=00000000}
fcw=0000 fsw=042b ftw=ffff mxcsr=ffffffff mxcsr_mask=ffffffff
u: error: DBGCCmdHlpVarToDbgfAddr failed on '0008:0000949b L 0': VERR_PAGE_TABLE_NOT_PRESENT


The memory areas and tables don't print as the below error shows :-

Code:
dptg 0x21000
%%0000ff53f000f108 (base %0000000000021000 / index 0x21):
error: VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS:  Reading PTE memory at %%0000ff53f000f108.


The tables before the fault are shown in a reply above. Let me know if you need anything else

Bipman


Top
 Profile  
 
 Post subject: Re: 64 bit long mode cr0 issue
PostPosted: Sat Mar 25, 2017 9:59 am 
Offline
Member
Member

Joined: Thu Aug 13, 2015 4:57 pm
Posts: 384
Is there a reason you don't want to/can't use Bochs? It might be able to provide more useful information.

How do you know at which instruction your code breaks? Single-stepping, using loops, etc?

Is the first "debug output from virtualbox" in your latest post after what? Right after enabling paging?

In your code:
Code:
   mov edi,40000000
   mov [edi],byte 0xeb
   mov [edi+1],byte 0xfe
   jmp $
   mov eax, cr0 ; Read CR0.
   bts eax, 31 ; Set PG=1.
   mov cr0, eax ; Write CR0.

What's the first part until the CR0 part intended to do? Is the 40000000 supposed to be hex?

Then:
Code:
   db 066h
   db 0eah
   dd 0x80000000
   dw CODE_SEG64


What's that intended to be? There's no comment for those _lines_, though there's a comment above.. That's supposed to be a far jump? You are using CODE_SEG64, though it's not yet loaded (with lgdt), since it seems you have two GDT's. Note, I didn't check, but the GDT64 might coincide with GDT32 in descriptor numbers so in that case you would still be using the CODE32 descriptor, however your code changes to 64-bit...


Top
 Profile  
 
 Post subject: Re: 64 bit long mode cr0 issue
PostPosted: Sat Mar 25, 2017 10:32 am 
Offline
Member
Member

Joined: Wed Mar 15, 2017 9:22 am
Posts: 40
Hi

Apologies but that version was an older one which I have now replaced with the current one. I'm not using bochs because it can't use more than 2GB memory and the virtualbox has it's own debugger and trace output which can be found in the link https://www.dropbox.com/s/qv1d9h3qcz7cl1w/VBox_Out.txt?dl=0 .

1.) The program halts at the mov cr0, eax and know this as I have paused it before and after and this is the line that faults. It does the same if I singe step.

2.) The debug output from VirtualBox was right after the paging enable i.e. mov cr0, eax

3.) Ignore that bit of code as it has been removed.

4.) I see what you mean about the CODE_SEG64; my mistake ! It was indeed a long jump to go into long mode. Be nice to get ths far though!

5.) There are two GDT tables, one for 32 bit and the simple 64 bit one.

Hope that helps and apologies again for sharing the wrong asm file.

Bipman


Top
 Profile  
 
 Post subject: Re: 64 bit long mode cr0 issue
PostPosted: Sat Mar 25, 2017 11:10 am 
Offline
Member
Member

Joined: Thu Aug 13, 2015 4:57 pm
Posts: 384
Can you elaborate on the issues with Bochs, I'm not an expert on it but I would think you can use more Guest than Host memory, or is there some other limitation your experiencing?

The trace you provided is not available, size 0 bytes.

Can you dump from virtual box the guest's _physical_ address for the paging stuff, I think it was 0x20000 and 0x21000. You should be able to do that before and after the offending instruction, since it shouldn't be dependent on the translation on the guest.

If you want to use VBox and there's no clear error, then you probably should implement IDT and see what exception gets raised and what's on the stack at that point, if anything relevant.

I usually use Qemu and gdb to debug it, being able to single step thru it all and check relevant registers, etc is pretty almost enough. Though I think Bochs might be a bit friendlier at generating useful error messages.


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

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot] and 90 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