Update x86_64 to version 0.5.2

This is required for the upcomping _Paging Implementation_ post.
This commit is contained in:
Philipp Oppermann
2019-03-12 17:47:58 +01:00
parent 0b6564895e
commit ddbe36c0dc
6 changed files with 40 additions and 40 deletions

View File

@@ -227,8 +227,8 @@ Let's take a closer look at the available flags:
The `x86_64` crate provides types for [page tables] and their [entries], so we don't need to create these structures ourselves.
[page tables]: https://docs.rs/x86_64/0.5.0/x86_64/structures/paging/struct.PageTable.html
[entries]: https://docs.rs/x86_64/0.5.0/x86_64/structures/paging/page_table/struct.PageTableEntry.html
[page tables]: https://docs.rs/x86_64/0.5.2/x86_64/structures/paging/struct.PageTable.html
[entries]: https://docs.rs/x86_64/0.5.2/x86_64/structures/paging/page_table/struct.PageTableEntry.html
### The Translation Lookaside Buffer
@@ -237,7 +237,7 @@ A 4-level page table makes the translation of virtual addresses expensive, becau
Unlike the other CPU caches, the TLB is not fully transparent and does not update or remove translations when the contents of page tables change. This means that the kernel must manually update the TLB whenever it modifies a page table. To do this, there is a special CPU instruction called [`invlpg`] (“invalidate page”) that removes the translation for the specified page from the TLB, so that it is loaded again from the page table on the next access. The TLB can also be flushed completely by reloading the `CR3` register, which simulates an address space switch. The `x86_64` crate provides Rust functions for both variants in the [`tlb` module].
[`invlpg`]: https://www.felixcloutier.com/x86/INVLPG.html
[`tlb` module]: https://docs.rs/x86_64/0.5.0/x86_64/instructions/tlb/index.html
[`tlb` module]: https://docs.rs/x86_64/0.5.2/x86_64/instructions/tlb/index.html
It is important to remember flushing the TLB on each page table modification because otherwise the CPU might keep using the old translation, which can lead to non-deterministic bugs that are very hard to debug.
@@ -291,8 +291,8 @@ extern "x86-interrupt" fn page_fault_handler(
The [`CR2`] register is automatically set by the CPU on a page fault and contains the accessed virtual address that caused the page fault. We use the [`Cr2::read`] function of the `x86_64` crate to read and print it. Normally the [`PageFaultErrorCode`] type would provide more information about the type of memory access that caused the page fault, but there is currently an [LLVM bug] that passes an invalid error code, so we ignore it for now. We can't continue execution without resolving the page fault, so we enter a [`hlt_loop`] at the end.
[`CR2`]: https://en.wikipedia.org/wiki/Control_register#CR2
[`Cr2::read`]: https://docs.rs/x86_64/0.5.0/x86_64/registers/control/struct.Cr2.html#method.read
[`PageFaultErrorCode`]: https://docs.rs/x86_64/0.5.0/x86_64/structures/idt/struct.PageFaultErrorCode.html
[`Cr2::read`]: https://docs.rs/x86_64/0.5.2/x86_64/registers/control/struct.Cr2.html#method.read
[`PageFaultErrorCode`]: https://docs.rs/x86_64/0.5.2/x86_64/structures/idt/struct.PageFaultErrorCode.html
[LLVM bug]: https://github.com/rust-lang/rust/issues/57270
[`hlt_loop`]: ./second-edition/posts/08-hardware-interrupts/index.md#the
@@ -368,9 +368,9 @@ pub extern "C" fn _start() -> ! {
The [`Cr3::read`] function of the `x86_64` returns the currently active level 4 page table from the `CR3` register. It returns a tuple of a [`PhysFrame`] and a [`Cr3Flags`] type. We are only interested in the frame, so we ignore the second element of the tuple.
[`Cr3::read`]: https://docs.rs/x86_64/0.5.0/x86_64/registers/control/struct.Cr3.html#method.read
[`PhysFrame`]: https://docs.rs/x86_64/0.5.0/x86_64/structures/paging/frame/struct.PhysFrame.html
[`Cr3Flags`]: https://docs.rs/x86_64/0.5.0/x86_64/registers/control/struct.Cr3Flags.html
[`Cr3::read`]: https://docs.rs/x86_64/0.5.2/x86_64/registers/control/struct.Cr3.html#method.read
[`PhysFrame`]: https://docs.rs/x86_64/0.5.2/x86_64/structures/paging/frame/struct.PhysFrame.html
[`Cr3Flags`]: https://docs.rs/x86_64/0.5.2/x86_64/registers/control/struct.Cr3Flags.html
When we run it, we see the following output:
@@ -380,7 +380,7 @@ Level 4 page table at: PhysAddr(0x1000)
So the currently active level 4 page table is stored at address `0x1000` in _physical_ memory, as indicated by the [`PhysAddr`] wrapper type. The question now is: how can we access this table from our kernel?
[`PhysAddr`]: https://docs.rs/x86_64/0.5.0/x86_64/struct.PhysAddr.html
[`PhysAddr`]: https://docs.rs/x86_64/0.5.2/x86_64/struct.PhysAddr.html
Accessing physical memory directly is not possible when paging is active, since programs could easily circumvent memory protection and access memory of other programs otherwise. So the only way to access the table is through some virtual page that is mapped to the physical frame at address `0x1000`. This problem of creating mappings for page table frames is a general problem, since the kernel needs to access the page tables regularly, for example when allocating a stack for a new thread.
@@ -418,7 +418,7 @@ When we look at the [format of page table entries][page table format], we see th
Instead of working with unsafe raw pointers we can use the [`PageTable`] type of the `x86_64` crate:
[`PageTable`]: https://docs.rs/x86_64/0.5.0/x86_64/structures/paging/page_table/struct.PageTable.html
[`PageTable`]: https://docs.rs/x86_64/0.5.2/x86_64/structures/paging/page_table/struct.PageTable.html
```rust
// in src/main.rs