Paging questions

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
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Paging questions

Post by XCHG »

I have started reading about paging and how I can implement it in my kernel. I have some questions though that I couldn’t find answers to in Intel Manuals. I’d really appreciate it if somebody could answer these for me.

1. Bits 12 to 31 of the Control Register 3 hold the base address of the page directory. Since this is a 20 bit field, does it mean that the page table address should be located somewhere between the beginning of the physical memory and up to the 1 megabyte boundary? Or is it possible to put the Page Directory Entries somewhere else in the memory?

2. Can paging be enabled once in protected mode or does it have to be enabled before setting the PE bit of the Control Register 0?

3. I don’t know if I am right about this or not but the Page Directory is 4 kilobytes long. Each Page Directory Entry is 32-bits long and thus we can have a total number of 128 Page Directory Entries in the Page Directory Table. Is that right? If yes, then why some tutorials mention that there are 1024 Page Directory Entries in the Page Directory?


Thanks in advance.
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
Andrew275
Member
Member
Posts: 30
Joined: Tue Feb 27, 2007 2:29 pm
Contact:

Post by Andrew275 »

1. The page directory must be 4KB aligned, so therefore those low bits of the address would always be 0. You can put it anywhere in physical memory.

2. You can enable paging once in protected mode.

3. Your math is off. 32 bits is 4 bytes, so 4 KB divided by 4 bytes gives you 1024.
My operating system: Desktop OS
Content management system/forum: Deluxe Portal
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Thank you so much. I appreciate it. And by the way, I am not bad in math I think I must have been sleepy or something. :D
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
User avatar
muisei
Member
Member
Posts: 79
Joined: Sat Sep 23, 2006 2:10 pm
Location: Bulgaria
Contact:

Post by muisei »

This is quite a common phenomenon.I'm studying math all my life and yesterday I had to use my scintific calculator to solve 7*8. :oops:
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Post by Candy »

muisei wrote:This is quite a common phenomenon.I'm studying math all my life and yesterday I had to use my scintific calculator to solve 7*8. :oops:
The amount of amazement that should cause depends on your age.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

I seem not to be able to enable paging. Well here is the situation. My kernel is located at the 1MB (0x00100000) and I tried putting the Page Directory Entries at the 6MB (0x00600000). I also put Page Directory Entries right after the Page Directory at 6MB + 4KB (0x00601000). I then put zero in all the 1024 entries for both the Page Directory and the Page Table. I then initialized only the first Page Directory Entry and just Page Table Entry but I get the below error message as soon as I modify the Control Register 0 (CR0):
Bochs wrote: 00003287942e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
Below is the code that I have written:

Code: Select all

; ------------------------------------
KERNELENTRY                     EQU       MEGABYTE(1)
PAGE_DIRECTORY_MEMLOCATION      EQU       MEGABYTE(6)
PAGE_TABLE_MEMLOCATION          EQU       MEGABYTE(6) + KILOBYTE(4)
PAGE_DIRECTORY_AND_TABLE_COUNT  EQU       KILOBYTE(4) / 4
PAGE_ENTRY_LEN                  EQU       0x00000004
; ------------------------------------
; 1) Clear all 1024 Page Directory Entires (PDEs) and Page Table Entries (PTEs)
MOV     EBX , PAGE_DIRECTORY_MEMLOCATION          ; *EBX = Pointer to Page Directory
MOV     EDX , PAGE_TABLE_MEMLOCATION              ; *EDX = Pointer to Page Table
MOV     ECX , PAGE_DIRECTORY_AND_TABLE_COUNT      ; *ECX = Number of entries to fill
XOR     EAX , EAX                                 ; *EAX = Put zero in entries
.ZeroDirectoryAndTable:                           ; The loop to fill PDEs and PTEs
  MOV     DWORD PTR [EBX] , EAX                   ; Put zero in the current PDE
  MOV     DWORD PTR [EDX] , EAX                   ; Put zero in the current PTE
  ADD     EBX , PAGE_ENTRY_LEN                    ; Move to the next PDE
  ADD     EDX , PAGE_ENTRY_LEN                    ; Move to the next PTE
  DEC     ECX                                     ; Decrement the counter
  JNZ     .ZeroDirectoryAndTable                  ; Keep doing this while ECX > 0
; ------------------------------------
; Make the first Page Directory Entry
MOV     EBX , PAGE_DIRECTORY_MEMLOCATION          ; *EBX = Pointer to Page Directory
MOV     EAX , 0x00000003 | PAGE_TABLE_MEMLOCATION ; Set the access bits and Memory Location
MOV     DWORD PTR [EBX] , EAX                     ; Set the first Page Directory Entry
; ------------------------------------
; Make the first Page Table Entry
MOV     EBX , PAGE_TABLE_MEMLOCATION              ; *EBX = Pointer to Page Table
MOV     EAX , 0x00000003 | KERNELENTRY            ; Set access bits and etc
MOV     DWORD PTR [EBX] , EAX                     ; Set the first Page Table Entry
; ------------------------------------
MOV     EAX , CR3                                 ; Read the Control Register 3
OR      EAX , PAGE_DIRECTORY_MEMLOCATION          ; Set the Page Directory Base
MOV     CR3 , EAX                                 ; Modify the Control Register 3
; ------------------------------------
MOV     EAX , CR0                                 ; Read the Control Register 0
OR      EAX , CR0_PG                              ; Set the Paging Bit (BIT#31)
MOV     CR0 , EAX                                 ; Enable Paging (BAM-ERROR!)
JMP     $                                         ; Don't go any further
; ------------------------------------
I'd appreciate it if somebody could tell me what I am doing wrong.
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

the problem lies here:

Code: Select all

; Make the first Page Table Entry
MOV     EBX , PAGE_TABLE_MEMLOCATION              ; *EBX = Pointer to Page Table
MOV     EAX , 0x00000003 | KERNELENTRY            ; Set access bits and etc
MOV     DWORD PTR [EBX] , EAX 
as you see you fill only entry #1 of the page table. This covers
0x000000-0x001000 (4KB)
instead of
0x100000-0x10???? (your kernel at the 1MB mark)
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

The first thing that I do when my kernel is loaded into the memory is that I set the Page Table Entries and Page Directory Entries. So these codes that I pasted here are the only codes that run when my kernel runs so shouldn't it work? I mean these codes when assembled don't cross a 4KB boundary.
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
User avatar
Kevin McGuire
Member
Member
Posts: 843
Joined: Tue Nov 09, 2004 12:00 am
Location: United States
Contact:

Post by Kevin McGuire »

This is equivalent to what the CPU does when it wants to find out what physical address maps to what virtual address.

Code: Select all

KERNELENTRY                     EQU       MEGABYTE(1)
PAGE_DIRECTORY_MEMLOCATION      EQU       MEGABYTE(6)
PAGE_TABLE_MEMLOCATION          EQU       MEGABYTE(6) + KILOBYTE(4)
PAGE_DIRECTORY_AND_TABLE_COUNT  EQU       KILOBYTE(4) / 4
PAGE_ENTRY_LEN                  EQU       0x00000004 

ADDRESS_WANTED 

mov ebp, PAGE_DIRECTORY_MEMLOCATION
mov  eax, ADDRESS_WANTED
shr eax, 22
mov ebp, dword [ebp+eax*4]
and ebp, 0xFFFFF000
mov eax, ADDRESS_WANTED
shl eax, 10
shr eax, 22
mov ebp, dword[ebp+eax*4]
and ebp, 0xFFFFF000
mov eax, ADDRESS_WANTED
and eax, 0xFFF
or ebp, eax
; EBP holds the physical address for the virtual address ADDRESS_WANTED..
The CPU also checks the flags in each entry which I do not do.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

your kernel is located from the 1MB mark. When you enable paging, the page table must contain entries that map the kernel area to physical memory. You do not provide any entries for that, so that when paging is enabled the processor looks up bogus values and crashes.

your reasoning goes wrong about here:
- you fill in entry 0 of page table 0. The processor looks this up when accessing memory from 0x00000000-0x00000fff, not where your code is located (which would be around the 256th entry)
- you make the page table entry point at 0x00000000. The real mode IVT is located here, not your kernel code.

You'll need to fix both problems before anything will work.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Oh so I must have gotten it wrong. This means that you can not map a linear address to a physical address beginning at a random place in the memory using the first or the second entry of the page table? So I have to find divide my kernel's entry point by 4KB and that will be entry in the page table that I have to fill. Is that close on being on the money?

How about the page directory? should I fill all the PDEs too? Thank you guys.


P.S: Oh now I get it. 1024 Page Directory Entires * 1024 Page Table Entries * Number of bytes that a Page Table covers (4096) = 1024*1024*4096 = 4294967296 which is the whole addressable memory. I'm a dingus!
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
User avatar
XCHG
Member
Member
Posts: 416
Joined: Sat Nov 25, 2006 3:55 am
Location: Wisconsin
Contact:

Post by XCHG »

Okay I enabled paging, finally! I filled the first PTE and filled its corresponding 1024 PTEs. This allowed me to address the first 4 MBs of memory. Thank you everyone. Combuster, thank you so much. I appreciate your help.

Here is the code. It might help someone, someday:

Code: Select all

  ; ------------------------------------
  PAGE_DIRECTORY_MEMLOCATION      EQU       MEGABYTE(6)
  PAGE_TABLE_MEMLOCATION          EQU       MEGABYTE(6) + KILOBYTE(4)
  PAGE_DIRECTORY_AND_TABLE_COUNT  EQU       KILOBYTE(4) / 4
  PAGE_ENTRY_LEN                  EQU       0x00000004
  ; ------------------------------------
  INVOKE  __ZeroMemory, PAGE_DIRECTORY_MEMLOCATION, KILOBYTE(4)
  INVOKE  __ZeroMemory, PAGE_TABLE_MEMLOCATION, KILOBYTE(4)
  ; ------------------------------------
  ; Fill in the first Page Directory Entry
  MOV     EBX , PAGE_DIRECTORY_MEMLOCATION
  MOV     EAX , 0x00000003 | PAGE_TABLE_MEMLOCATION
  MOV     DWORD PTR [EBX] , EAX
  ; ------------------------------------
  ; Fill in all 1024 PTEs of the first PDE
  MOV     EBX , PAGE_TABLE_MEMLOCATION
  MOV     ECX , PAGE_DIRECTORY_AND_TABLE_COUNT
  XOR     EDX , EDX
  .FillPageTableEntries:
    MOV     EAX , EDX
    OR      EAX , 0x00000003
    MOV     DWORD PTR [EBX] , EAX
    ADD     EDX , KILOBYTE(4)
    ADD     EBX , 0x00000004
    DEC     ECX
    JNZ     .FillPageTableEntries  
  ; ------------------------------------
  MOV     EAX , CR3
  OR      EAX , PAGE_DIRECTORY_MEMLOCATION
  MOV     CR3 , EAX
  ; ------------------------------------
  MOV     EAX , CR0
  OR      EAX , CR0_PG
  MOV     CR0 , EAX
  ; ------------------------------------
On the field with sword and shield amidst the din of dying of men's wails. War is waged and the battle will rage until only the righteous prevails.
Post Reply