Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removing CR3 check from RecursivePageTable? #157

Open
CWood1 opened this issue May 23, 2020 · 3 comments
Open

Removing CR3 check from RecursivePageTable? #157

CWood1 opened this issue May 23, 2020 · 3 comments

Comments

@CWood1
Copy link

CWood1 commented May 23, 2020

This issue is mostly for discussion purposes, to clarify my understanding.

RecursivePageTable::new() requires the passed page table to be active, checked through CR3. However, I'm not entirely sure I grok why that is. Nothing else in RecursivePageTable references CR3 in any way, other than that one particular check.

The reason I'm looking to remove this, is because I'd like to be able to have my kernel map in new page tables, for processes/drivers/etc, by mapping in the new page table at some address within the kernel space, and calling that "recursive" - the algorithms would all be the same, it would simply be a different P4 being referenced. In this way, I don't need to have every page table mapped into the kernel constantly for no reason, I don't need to manually manage pages when there's a perfectly good implementation already written, and generally it would simplify the setup.

However, I don't consider myself familiar enough with the implementation to know why the CR3 check is in place, and whether or not it is safe to remove. Could somebody with this knowledge advise please?

@phil-opp
Copy link
Member

See https://os.phil-opp.com/paging-implementation/#recursive-page-tables for an overview how recursive page tables work. The reason for the CR3 check is that the addresses derived from the recursive index only work if the given level 4 table is the active page table in the CPU. You can't just reference a different level 4 table because then the calculated addresses for the level 3, 2, and 1 tables are invalid (because the CPU always uses the level 4 table referenced by the CR3 register for the translation).

It is possible to access the page table hierachy of an inactive level 4 table, but it is a bit more complicated. The idea is to point the recursive entry of the active level 4 table to the inactive level 4 table, which is recursively mapped too. This way, you now access the tables of the inactive page table through recursive addresses. The challenge of this approach is to make the original level 4 table recursive again after you're done modifying the inactive page table hierarchy. The problem is that the original level 4 table is no longer accessible through recursive addresses, so you have to create some kind of temporary mapping for it in the new page table hierarchy in order to access it. See the (outdated) https://os.phil-opp.com/remap-the-kernel/#overview for more details.

Since the RecursivePageTable type can easily lead to undefined behavior if the passed page table is not active, we check that in the new method. In case you're really sure that the using a specific inactive level 4 table is fine in your case (e.g. when using the approach described above), you can use the unsafe RecursivePageTable::new_unchecked method to skip the CR3 check.

I hope this answers your question!

@josephlr
Copy link
Contributor

@phil-opp Do you think we should update the Safety section of RecursivePageTable::new_unchecked to reflect the above? Right now the docs are unclear here.

@phil-opp
Copy link
Member

Yes, I agree that the current docs are a bit vague.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants