Paging Implementation #1013
Replies: 99 comments 14 replies
-
|
The |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
|
This paging approach seems much clear and easy to understand |
Beta Was this translation helpful? Give feedback.
-
|
@DanGdl Great to hear that! |
Beta Was this translation helpful? Give feedback.
-
|
That's better than last time (I hope). Last time the code didn't compile. |
Beta Was this translation helpful? Give feedback.
-
|
@pitust Please open an issue when you have any problems with compiling the code. You can also find the complete code for the post in the |
Beta Was this translation helpful? Give feedback.
-
|
If I use the 'map_physical_memory' feature,and I want to create a new level_4_page_table to be switched to when I create a new process.Do I need to map the whole physical memory in the new page table manually just like what you did in 'bootloader' crate?Actually I found that snippet of code,but I am not really sure should I type it again in my code. |
Beta Was this translation helpful? Give feedback.
-
|
@songzhi If you want that your new process also has access to the physical memory then you need to add a mapping for it in its address space. As an optimization you can link the level 3 or level 2 page table from your current address space to the new address space instead of copying them, so that both address spaces share the same level 3/level 2 table. |
Beta Was this translation helpful? Give feedback.
-
|
For anyone who is updating |
Beta Was this translation helpful? Give feedback.
-
|
How to create global static frame_allocator so that I can move the page mapping inside the page fault handler. I have tried In lib.rspub static mut FRAME_ALLOCATOR: Option<BootInfoFrameAllocator<Iterator<Item = PhysFrame>> = None I keep getting an error "doesn't have a size known at compile-time" |
Beta Was this translation helpful? Give feedback.
-
Discussed in #593 |
Beta Was this translation helpful? Give feedback.
-
|
Just wanted to mention that the |
Beta Was this translation helpful? Give feedback.
-
|
@nrlsk Thanks for reporting! Fixed in 6db5ad7. |
Beta Was this translation helpful? Give feedback.
-
|
@tom7980 Seems like you deleted your comment. It was a valid question, so let me give you a short answer anyway. Yes, the frame allocator could be implemented this way. We used a similar implementation before. The problem is that it couldn't be stored in a
Could you open an issue for this with more specific information? |
Beta Was this translation helpful? Give feedback.
-
|
@phil-opp I can open an issue about it tomorrow as I'm on the wrong computer currently, I was only struggling on my windows environment, once I booted into Linux and tried the build steps I managed to sort it so it might just be my windows env is mis-configured. Regarding my question, I actually had a go at implementing it but I came up against the issue that the initialisation of the wrapper was expecting a type I where I: Iterator, but due to passing a memory map to the function and doing some transformations onto it I was getting a nested iterator and it wouldn't let me store it anyway! I'm going to take another look at it tomorrow but I think I understand what you meant about the |
Beta Was this translation helpful? Give feedback.
-
|
I'm having a lot of difficulty debugging this page fault (I got the triple fault to at least work). After using step for a bit of time and then returning to "next" the next command starts behaving just like step. Instead of (say) jumping over these lines of my code, for example: return MMAP
.get()
.unwrap()
.iter()
.map(|r| r.start..r.end)
.flat_map(|r| r.step_by(4096))
.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr)))
.nth(FPOS.load(Ordering::Relaxed));It does this instead:
And so on and so forth. This makes it incredibly difficult to get out of and the debugging noise makes it impossible to track where I'm trying to go. Does anyone know why GDB is behaving this way? |
Beta Was this translation helpful? Give feedback.
-
|
Okay, I think I've nailed it down. For some reason, this code, or thereabouts, is causing the page fault: fn create_next_table<'b, A>(
&self,
entry: &'b mut PageTableEntry,
insert_flags: PageTableFlags,
allocator: &mut A,
) -> Result<&'b mut PageTable, PageTableCreateError>
where
A: FrameAllocator<Size4KiB> + ?Sized,
{
let created;
if entry.is_unused() {
if let Some(frame) = allocator.allocate_frame() {
entry.set_frame(frame, insert_flags);
created = true;
} else {
return Err(PageTableCreateError::FrameAllocationFailed);
}
} else {
if !insert_flags.is_empty() && !entry.flags().contains(insert_flags) {
entry.set_flags(entry.flags() | insert_flags);
}
created = false;
}
let page_table = match self.next_table_mut(entry) {
Err(PageTableWalkError::MappedToHugePage) => {
return Err(PageTableCreateError::MappedToHugePage);
}
Err(PageTableWalkError::NotMapped) => panic!("entry should be mapped at this point"),
Ok(page_table) => page_table,
};
if created {
page_table.zero();
}
Ok(page_table)
}To be specific, this part: let page_table = match self.next_table_mut(entry) {
Err(PageTableWalkError::MappedToHugePage) => {
return Err(PageTableCreateError::MappedToHugePage);
}
Err(PageTableWalkError::NotMapped) => panic!("entry should be mapped at this point"),
Ok(page_table) => page_table,
};
if created {
page_table.zero();
}
Ok(page_table)I've no idea why this is causing the page fault in particular. But for some reason this is where my (15 plus) breakpoints lead me to. Thoughts? |
Beta Was this translation helpful? Give feedback.
-
|
sir, I follow this post step by step. But after the session "Accessing the Page Tables", when I build and run it, the qemu window displays panic information. The same as the source code cloned from your github repo. There is my develop enviroment: |
Beta Was this translation helpful? Give feedback.
-
|
hello, when i cargo run, i got a panic: |
Beta Was this translation helpful? Give feedback.
-
|
In "mapping the complete physical memory", can someone explain the 132KiB number? 32 GiB / 4 KiB = 8388608 pages Each level 2 page table has 2MiB / 8B = 262144 entries Therefore there are 8388608 / 262144 = 32 level 2 page tables, and 1 level 3 page table with 32 entries. Space occupied = |
Beta Was this translation helpful? Give feedback.
-
Before this post, we wrote bytes to 0xb8000 to print something on screen. Does that mean |
Beta Was this translation helpful? Give feedback.
-
|
I guess the bootloader is not necessary anymore once the kernel is properly loaded and starts executing, but the bootloader seems to identity-map the initial page tables and the bootloader itself's code and data sections as seen here at the 3rd stage and never unload or unmap them even until the control is transferred to the kernel. Is the bootloader code and data used to communicate with the kernel or for any other reasons after the kernel is loaded? |
Beta Was this translation helpful? Give feedback.
-
|
When I use cargo run to compile the kernel, why is it always stuck?I have to try it again and agian. |
Beta Was this translation helpful? Give feedback.
-
|
Hello, I have trouble understanding the code for the After playing a bit in Rust Playground, I think I understood. Are |
Beta Was this translation helpful? Give feedback.
-
|
Hello, In the technique Map the Complete Physical Memory, how can I create a new PageTable for another process. Since OffsetPageTable requires the that complete physical memory to be mapped, how do I achieve that? Thank you. |
Beta Was this translation helpful? Give feedback.
-
|
Did you mean virtual address on the paragraph before Using OffsetTable? Because if you add the physical offset you get the virtual address not the physical address |
Beta Was this translation helpful? Give feedback.
-
shouldn't it be |
Beta Was this translation helpful? Give feedback.
-
|
Really good blog/post, thank you. I think the "Address Calculation" in "Recursive Page Tables" can be simplified while making the code easier to read/review. The current code snippet has a lot of magic numbers in it: // Untested code, level must be 0..=4
fn virtual2rpt_addr(mut addr: u64, level: usize) -> u64 {
// Shift right until everything is in the right place.
addr >>= (9*level);
// Set sign extension and recursive index bits (assuming r=0o777 for simplicity)
addr |= u64::MAX << (48-9*level);
// Set the last 3 bit to 0, since we want the address to the entry.
addr &= !7u64;
addr
}Most of this is constant and only depends on level, so if level is hard coded all of this likely gets compiled to a By using i64 (so shifting extends with 1) and setting the sign-extend bits to 1 before doing the shifting it could even be faster, esp. when all levels are needed: let addr = (addr | u64::MAX << 48) as i64;
let lvl1 = (addr >> 9) as u64 & !7;
let lvl2 = (addr >> 18) as u64 & !7;
let lvl3 = (addr >> 27) as u64 & !7;
let lvl4 = (addr >> 36) as u64 & !7;
// Or by shifting back (they generate identical assembly)
let lvl1 =( (addr >> 12) << 3) as u64It's not as intuitive to get to, but should still be easy enough to understand with the explanation above it. => You can get the address for all 4 levels with just 8 shifts (or 4 shits and 4 AND) and an OR (while being pipelining friendly given enough ALUs and needing only a minimal amount of registers). |
Beta Was this translation helpful? Give feedback.
-
Hello, In the section Accessing Page Tables, subsection Mapping at Fixed Offset, it is written that this method does not allow us to access other address spaces. I am unable to understand why this would be the case. If the OS makes a new process, the OS should be able to add a mapping for the page table frame of the newly created process, and as all the processes that are currently running should have their page tables set up by the OS, the OS should have mappings for the address spaces for all the currently running processes, right? |
Beta Was this translation helpful? Give feedback.
-
Very basic question, but if we reserve 1000 KiB memory region starting at 1008 KiB, shouldn't we not be able to use physical address between 1008 KiB (vs. 1000 KiB) and 2008 KiB? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
This is a general purpose comment thread for the Paging Implementation post.
Beta Was this translation helpful? Give feedback.
All reactions