Creating new page directories, and page tables on demand
Posted: Tue Mar 03, 2015 5:58 pm
I've been working some more on paging, and I'm to the point where I have to start worrying about page frame allocations. What I'm needing to do is figure out how to create new page tables, at the proper indices so I can map virtual addresses to physical addresses when a page fault occurs. I understand that there are quite a number of opinions on how to do this, and was wondering if what I have in mind is a good approach to the issue.
Here's the source code I'm discussing.
Here's a screen shot of what I'm getting.
My memory is currently set up as follows:
0x0 - 0xF,FFFF = GRUB space
0x10,0000 - 0x10,9D90 = my kernel
0x10,A000 - 0x12,9FFC = a stack of page aligned physical memory addresses
0x12,A000 = the page I'm using for my page directory
0x12,B000 = the page I'm using for my page table.
What I've done is created a stack of the page aligned physical addresses available to the system after the kernel, a page directory, and a page table. I then identity mapped everything up to the page table, and enabled paging. What I'm having a problem with is the chicken and the egg issue that goes along with creating new page directories, and page tables, when a page fault happens. When a page fault happens I need to map the physical address of a page to a virtual address, but in order to do that I need to be able to zero out the contents of the page which requires the memory to be mapped so I can write to it. If I attempt to write to memory that's not mapped I'll cause a page fault which will create an infinite loop of page faults, and get me no where. What's the solution to this dilemma?
Here's what I'm thinking I'll do to create a new page table, and page, when a page fault happens:
* Get the physical address of a free page off the stack.
* Put that physical address on my existing page table to map it to a given virtual address so I can write to the page.
* Zero out that page so there's no garbage in it.
* Copy the physical address for that page table to the proper index in the page directory.
* Get another physical memory address from the stack.
* Put that physical address on my existing page table to map it to a given virtual address so I can write to the page.
* Zero out that page so there's no garbage in it.
* Copy the physical address of that page to the proper index on my previously created, and mapped, page table.
* Mark the newly created page table as being present in memory by updating the value in the page directory.
* Mark the newly created page as being present in memory by updating the value in the page table using the mapped address I created to write to it.
* Unmap the virtual addresses I used to write to the two pages.
I was wondering if this sounds sane to everybody else. I realize there are some steps that I've excluded, but I wasn't looking to lay out all of the details of the page fault handler. Are there any big "gotchas" I'm missing?
EDIT TO THE MODS: Please PM me if I'm creating too many discussions about similar topics. The feedback from the forum is proving to be very helpful to me, but I don't want to step on any toes. I figured this question was different enough from the thread I created yesterday to be worthy of its own post.
Here's the source code I'm discussing.
Here's a screen shot of what I'm getting.
My memory is currently set up as follows:
0x0 - 0xF,FFFF = GRUB space
0x10,0000 - 0x10,9D90 = my kernel
0x10,A000 - 0x12,9FFC = a stack of page aligned physical memory addresses
0x12,A000 = the page I'm using for my page directory
0x12,B000 = the page I'm using for my page table.
What I've done is created a stack of the page aligned physical addresses available to the system after the kernel, a page directory, and a page table. I then identity mapped everything up to the page table, and enabled paging. What I'm having a problem with is the chicken and the egg issue that goes along with creating new page directories, and page tables, when a page fault happens. When a page fault happens I need to map the physical address of a page to a virtual address, but in order to do that I need to be able to zero out the contents of the page which requires the memory to be mapped so I can write to it. If I attempt to write to memory that's not mapped I'll cause a page fault which will create an infinite loop of page faults, and get me no where. What's the solution to this dilemma?
Here's what I'm thinking I'll do to create a new page table, and page, when a page fault happens:
* Get the physical address of a free page off the stack.
* Put that physical address on my existing page table to map it to a given virtual address so I can write to the page.
* Zero out that page so there's no garbage in it.
* Copy the physical address for that page table to the proper index in the page directory.
* Get another physical memory address from the stack.
* Put that physical address on my existing page table to map it to a given virtual address so I can write to the page.
* Zero out that page so there's no garbage in it.
* Copy the physical address of that page to the proper index on my previously created, and mapped, page table.
* Mark the newly created page table as being present in memory by updating the value in the page directory.
* Mark the newly created page as being present in memory by updating the value in the page table using the mapped address I created to write to it.
* Unmap the virtual addresses I used to write to the two pages.
I was wondering if this sounds sane to everybody else. I realize there are some steps that I've excluded, but I wasn't looking to lay out all of the details of the page fault handler. Are there any big "gotchas" I'm missing?
EDIT TO THE MODS: Please PM me if I'm creating too many discussions about similar topics. The feedback from the forum is proving to be very helpful to me, but I don't want to step on any toes. I figured this question was different enough from the thread I created yesterday to be worthy of its own post.