From c4e3f86ebf282f2ce0ef5d67653e05312cf5776d Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Thu, 10 Jan 2019 12:59:17 +0100 Subject: [PATCH] Finish first draft of paging post and rename it --- .../index.md | 161 +++++++++++++++--- .../multilevel-page-table.svg | 0 .../multilevel-paging-motivation.svg | 0 .../paging-fragmentation.svg | 0 .../paging-page-tables.svg | 0 .../qemu-print-p4-entries-abstraction.png | Bin 0 -> 18345 bytes .../qemu-print-p4-entries.png | Bin 0 -> 10856 bytes .../segmentation-fragmentation-compacted.svg | 0 .../segmentation-fragmentation.svg | 0 .../segmentation-same-program-twice.svg | 0 .../single-level-page-table.svg | 0 ...86_64-page-table-translation-addresses.svg | 0 .../x86_64-page-table-translation-large.svg | 2 + .../x86_64-page-table-translation-steps.svg | 2 + .../x86_64-page-table-translation.svg | 0 .../x86_64-table-indices-from-address.svg | 0 16 files changed, 143 insertions(+), 22 deletions(-) rename blog/content/second-edition/posts/{09-paging => 09-paging-introduction}/index.md (65%) rename blog/content/second-edition/posts/{09-paging => 09-paging-introduction}/multilevel-page-table.svg (100%) rename blog/content/second-edition/posts/{09-paging => 09-paging-introduction}/multilevel-paging-motivation.svg (100%) rename blog/content/second-edition/posts/{09-paging => 09-paging-introduction}/paging-fragmentation.svg (100%) rename blog/content/second-edition/posts/{09-paging => 09-paging-introduction}/paging-page-tables.svg (100%) create mode 100644 blog/content/second-edition/posts/09-paging-introduction/qemu-print-p4-entries-abstraction.png create mode 100644 blog/content/second-edition/posts/09-paging-introduction/qemu-print-p4-entries.png rename blog/content/second-edition/posts/{09-paging => 09-paging-introduction}/segmentation-fragmentation-compacted.svg (100%) rename blog/content/second-edition/posts/{09-paging => 09-paging-introduction}/segmentation-fragmentation.svg (100%) rename blog/content/second-edition/posts/{09-paging => 09-paging-introduction}/segmentation-same-program-twice.svg (100%) rename blog/content/second-edition/posts/{09-paging => 09-paging-introduction}/single-level-page-table.svg (100%) rename blog/content/second-edition/posts/{09-paging => 09-paging-introduction}/x86_64-page-table-translation-addresses.svg (100%) create mode 100644 blog/content/second-edition/posts/09-paging-introduction/x86_64-page-table-translation-large.svg create mode 100644 blog/content/second-edition/posts/09-paging-introduction/x86_64-page-table-translation-steps.svg rename blog/content/second-edition/posts/{09-paging => 09-paging-introduction}/x86_64-page-table-translation.svg (100%) rename blog/content/second-edition/posts/{09-paging => 09-paging-introduction}/x86_64-table-indices-from-address.svg (100%) diff --git a/blog/content/second-edition/posts/09-paging/index.md b/blog/content/second-edition/posts/09-paging-introduction/index.md similarity index 65% rename from blog/content/second-edition/posts/09-paging/index.md rename to blog/content/second-edition/posts/09-paging-introduction/index.md index 727ab677..8be3384b 100644 --- a/blog/content/second-edition/posts/09-paging/index.md +++ b/blog/content/second-edition/posts/09-paging-introduction/index.md @@ -1,17 +1,15 @@ +++ -title = "Paging" +title = "Introduction to Paging" order = 9 -path = "paging" +path = "paging-introduction" date = 0000-01-01 template = "second-edition/page.html" +++ -This post introduces _paging_, a very common memory management scheme that we will also use for our operating system. It explains why memory isolation is needed, how _segmentation_ works, what _virtual memory_ is, and how paging solves memory fragmentation issues. It also explores (multilevel) page tables and explains how paging works on the x86_64 architecture. +This post introduces _paging_, a very common memory management scheme that we will also use for our operating system. It explains why memory isolation is needed, how _segmentation_ works, what _virtual memory_ is, and how paging solves memory fragmentation issues. It also explores the layout of multilevel page tables on the x86_64 architecture. -In contrast to the other posts on this blog, this post does not contain any code. The reason for this is that a working paging implementation already needs many advanced features, which might be overwhelming if introduced right at the beginning. By focusing on the fundamentals first we can explain the concepts step by step, before we introduce the advanced features and the implementation in the next post. - This blog is openly developed on [Github]. If you have any problems or questions, please open an issue there. You can also leave comments [at the bottom]. [Github]: https://github.com/phil-opp/blog_os @@ -96,13 +94,13 @@ Internal fragmentation is unfortunate, but often better than the external fragme ### How does it work? -We saw that each of the potentially thousands of pages is individually mapped to a frame. This mapping information needs to be stored somewhere. Segmentation uses an individual segment selector register for each active memory region, which is not possible for paging since there are way more pages than registers. Instead paging uses a table structure called _page table_ to store the mapping information. +We saw that each of the potentially millions of pages is individually mapped to a frame. This mapping information needs to be stored somewhere. Segmentation uses an individual segment selector register for each active memory region, which is not possible for paging since there are way more pages than registers. Instead paging uses a table structure called _page table_ to store the mapping information. For our above example the page tables would look like this: ![Three page tables, one for each program instance. For instance 1 the mapping is 0->100, 50->150, 100->200. For instance 2 it is 0->300, 50->350, 100->400. For instance 3 it is 0->250, 50->450, 100->500.](paging-page-tables.svg) -We see that each program instance has its own page table. A pointer to the currently active table is stored in a special CPU register. On `x86`, this register is called `CR3`. It is the job of the operating system to load this register with the correct value before running each program instance. +We see that each program instance has its own page table. A pointer to the currently active table is stored in a special CPU register. On `x86`, this register is called `CR3`. It is the job of the operating system to load this register with the pointer to the correct page table before running each program instance. On each memory access, the CPU reads the table pointer from the register and looks up the mapped frame for the accessed page in the table. This is entirely done in hardware and completely transparent to the running program. To speed up the translation process, many CPU architectures have a special cache that remembers the results of the last translations. @@ -110,23 +108,23 @@ Depending on the architecture, page table entries can also store attributes such ### Multilevel Page Tables -The simple page tables we just saw have a problem in larger address spaces: they waste memory. For example, imagine a program that uses the four virtual pages 0, 1 000 000, 1_000 050, and 1 000 100: +The simple page tables we just saw have a problem in larger address spaces: they waste memory. For example, imagine a program that uses the four virtual pages `0`, `1_000_000`, `1_000_050`, and `1_000_100` (we use `_` as a thousands separator): -![Page 0 mapped to frame 0 and pages 1 000 000–1 000 150 mapped to frames 100–250](single-level-page-table.svg) +![Page 0 mapped to frame 0 and pages `1_000_000`–`1_000_150` mapped to frames 100–250](single-level-page-table.svg) It only needs 4 physical frames, but the page table has over a million entries. We can't omit the empty entries because then the CPU would no longer be able to jump directly to the correct entry in the translation process (e.g. it is no longer guaranteed that the fourth page uses the fourth entry). To reduce the wasted memory, we can use a **two-level page table**. The idea is that we use different page tables for different address regions. An additional table called _level 2_ page table contains the mapping between address regions and (level 1) page tables. -This is best explained by an example. Let's define that each level 1 page table is responsible for a region of size 10 000. Then the following tables would exist for the above example mapping: +This is best explained by an example. Let's define that each level 1 page table is responsible for a region of size `10_000`. Then the following tables would exist for the above example mapping: -![Page 0 points to entry 0 of the level 2 page table, which points to the level 1 page table T1. The first entry of T1 points to frame 0, the other entries are empty. Pages 1 000 000–1 000 150 point to the 100th entry of the level 2 page table, which points to a different level 1 page table T2. The first three entries of T2 point to frames 100–250, the other entries are empty.](multilevel-page-table.svg) +![Page 0 points to entry 0 of the level 2 page table, which points to the level 1 page table T1. The first entry of T1 points to frame 0, the other entries are empty. Pages `1_000_000`–`1_000_150` point to the 100th entry of the level 2 page table, which points to a different level 1 page table T2. The first three entries of T2 point to frames 100–250, the other entries are empty.](multilevel-page-table.svg) -Page 0 falls into the first 10 000 byte region, so it uses the first entry of the level 2 page table. This entry points to level 1 page table T1, which specifies that page 0 points to frame 0. +Page 0 falls into the first `10_000` byte region, so it uses the first entry of the level 2 page table. This entry points to level 1 page table T1, which specifies that page `0` points to frame `0`. -The pages 1 000 000, 1 000 050, and 1 000 100 all fall into the 100th memory region (which goes from 1 000 000 to 1 010 000), so they use the 100th entry of the level 2 page table. This entry points at a different level 1 page table T2. The T2 table maps the three pages to frames 100, 150, and 200. Note that the page number does not include the region offset, so e.g. for page 1 000 050 we use the T2 entry for page 50 (= 1 000 050 - 1 000 000). +The pages `1_000_000`, `1_000_050`, and `1_000_100` all fall into the 100th `10_000` byte region, so they use the 100th entry of the level 2 page table. This entry points at a different level 1 page table T2, which maps the three pages to frames `100`, `150`, and `200`. Note that the page address in level 1 tables does not include the region offset, so e.g. the entry for page `1_000_050` is just `50`. -We still have 100 empty entries in the level 2 table, but much fewer than the million empty entries before. The reason for this savings is that we don't need to create level 1 page tables for the unmapped memory regions between 10 000 and 1 000 000. +We still have 100 empty entries in the level 2 table, but much fewer than the million empty entries before. The reason for this savings is that we don't need to create level 1 page tables for the unmapped memory regions between `10_000` and `1_000_000`. The principle of two-level page tables can be extended to three, four, or more levels. Then the page table register points at the highest level table, which points to the next lower level table, which points to the next lower level, and so on. The level 1 page table then points at the mapped frame. The principle in general is called a _multilevel_ or _hierarchical_ page table. @@ -140,7 +138,7 @@ The page table index for level is derived directly from the virtual address: ![Bits 0–12 are the page offset, bits 12–21 the level 1 index, bits 21–30 the level 2 index, bits 30–39 the level 3 index, and bits 39–48 the level 4 index](x86_64-table-indices-from-address.svg) -We see that each table index consists of 9 bits, which makes sense because each table has 2^9 = 512 entries. The lowest 12 bits are the offset in the 4KiB page (2^12 bytes = 4KiB). Bits 48 to 64 are discarded, which means that x86_64 is not really 64-bit and only supports 48-bit addresses. There are plans to extend the address size to 57 bits through a [5-level page table], but no processors that support this feature exist yet. +We see that each table index consists of 9 bits, which makes sense because each table has 2^9 = 512 entries. The lowest 12 bits are the offset in the 4KiB page (2^12 bytes = 4KiB). Bits 48 to 64 are discarded, which means that x86_64 is not really 64-bit since it only supports 48-bit addresses. There are plans to extend the address size to 57 bits through a [5-level page table], but no processor that supports this feature exists yet. [5-level page table]: https://en.wikipedia.org/wiki/Intel_5-level_paging @@ -156,19 +154,21 @@ Let's go through an example to understand how the translation process works in d The physical address of the currently active level 4 page table, which is the root of the 4-level page table, is stored in the `CR3` register. Each page table entry then points to the physical frame of the next level table. The entry of the level 1 table then points to the mapped frame. Note that all addresses in the page tables are physical instead of virtual, because otherwise the CPU would need to translate those addresses too (which could cause a never-ending recursion). -The above page table hierarchy maps two pages (in blue). The start addresses of these pages are `0x803FE7F000` and `0x803FE00000`. Let's see what happens when the program tries to read from address `0x803FE7F5CE`. First, we convert the address to binary and determine the page table indices and the page offset for the address: +The above page table hierarchy maps two pages (in blue). From the page table indices we can deduce that the virtual addresses of these two pages are `0x803FE7F000` and `0x803FE00000`. Let's see what happens when the program tries to read from address `0x803FE7F5CE`. First, we convert the address to binary and determine the page table indices and the page offset for the address: ![The sign extension bits are all 0, the level 4 index is 1, the level 3 index is 0, the level 2 index is 511, the level 1 index is 127, and the page offset is 0x5ce](x86_64-page-table-translation-addresses.svg) With these indices, we can now walk the page table hierarchy to determine the mapped frame for the address: - We start by reading the address of the level 4 table out of the `CR3` register. -- Then we look at the entry with index 1 of that table, which tells us that the level 3 table is stored at address 16KiB. -- We load the level 3 table from that address and look at the entry with index 0, which points us to the level 2 table at 14KiB. +- The level 4 index is 1, so we look at the entry with index 1 of that table, which tells us that the level 3 table is stored at address 16KiB. +- We load the level 3 table from that address and look at the entry with index 0, which points us to the level 2 table at 24KiB. - The level 2 index is 511, so we look at the last entry of that page to find out the address of the level 1 table. -- The entry with index 127 of the level 1 table we finally find that the page is mapped to frame 12KiB, or 0xc000 in hexadecimal. +- Through the entry with index 127 of the level 1 table we finally find out that the page is mapped to frame 12KiB, or 0xc000 in hexadecimal. - The final step is to add the page offset to the frame address to get the physical address 0xc000 + 0x5ce = 0xc5ce. +![The same example 4-level page hierarchy with 5 additional arrows: "Step 0" from the CR3 register to the level 4 table, "Step 1" from the level 4 entry to the level 3 table, "Step 2" from the level 3 entry to the level 2 table, "Step 3" from the level 2 entry to the level 1 table, and "Step 4" from the level 1 table to the mapped frames.](x86_64-page-table-translation-steps.svg) + The permissions for the page in the level 1 table are `r`, which means read-only. The hardware enforces this permissions and would throw an exception if we tried to write to that page. Permissions in higher level pages restrict the possible permissions in lower level, so if we set the level 3 entry to read-only, no pages that use this entry can be writable, even if lower levels specify read/write permissions. It's important to note that even through this example used only a single instance of each table, there are typically multiple instances of each level in each address space. At maximum, there are: @@ -233,22 +233,139 @@ The `x86_64` crate provides types for [page tables] and their [entries], so we d A 4-level page table makes the translation of virtual addresses expensive, because each translation requires 4 memory accesses. To improve performance, the x86_64 architecture caches the last few translations in the so-called _translation lookaside buffer_ (TLB). This allows to skip the translation when the translation is still cached. -Unlike the other CPU caches, the TLB is not fully transparent since it does not update or remove translations when a mapping in the page table changes. Instead it must be manually updated whenever a mapping in the page table changes. 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]. +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.3.4/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. +## Try it out + +One thing that we did not mention yet: **Our kernel already runs on paging**. The bootloader that we added in the ["A minimal Rust Kernel"] post already set up a 4-level paging hierarchy that maps every page of our kernel to a physical frame. The bootloader does this because paging is mandatory in 64-bit mode on x86_64. + +["A minimal Rust kernel"]: ./second-edition/posts/02-minimal-rust-kernel/index.md#creating-a-bootimage + +This means that every memory address that we used in our kernel was a virtual address. Accessing the VGA buffer at address `0xb8000` only worked because the bootloader _identity mapped_ that memory page, which means that the virtual page `0xb8000` is mapped to the physical frame `0xb8000`. + +Let's try to take a look at the page tables that our kernel runs on: + +```rust +// in src/main.rs + +#[cfg(not(test))] +#[no_mangle] +pub extern "C" fn _start() -> ! { + use x86_64::registers::control::Cr3; + + let (level_4_page_table, _) = Cr3::read(); + println!("Level 4 page table at: {:?}", level_4_page_table.start_address()); + + […] +} +``` + +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.3.4/x86_64/registers/control/struct.Cr3.html#method.read +[`PhysFrame`]: https://docs.rs/x86_64/0.3.4/x86_64/structures/paging/struct.PhysFrame.html +[`Cr3Flags`]: https://docs.rs/x86_64/0.3.4/x86_64/registers/control/struct.Cr3Flags.html + +When we run it, we see the following output: + +``` +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.3.4/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. + +Solutions to this problem are explained in detail in the next post. For now it suffices to know that the bootloader used a technique called _recursive page tables_ to map the last page of the virtual address space to the physical frame of the level 4 page table. The last page of the virtual address space is `0xffff_ffff_ffff_f000`, so let's use it to read some entries of that table: + +```rust +// in src/main.rs + +#[cfg(not(test))] +#[no_mangle] +pub extern "C" fn _start() -> ! { + let level_4_table_pointer = 0xffff_ffff_ffff_f000 as *const u64; + for i in 0..10 { + let entry = unsafe { *level_4_table_pointer.offset(i) }; + println!("Entry {}: {:#x}", i, entry); + } + + […] +} +``` + +We cast the address of the last virtual page to a pointer to an `u64`. As we saw in the [previous section][page table format], each page table entry is 8 bytes (64 bits), so an `u64` represents exactly one entry. We print the first 10 entries of the table using a `for` loop. Inside the loop, we use an unsafe block to read from the raw pointer and the [`offset` method] to perform pointer arithmetic. + +[page table format]: #page-table-format +[`offset` method]: https://doc.rust-lang.org/std/primitive.pointer.html#method.offset + +When we run it, we see the following output: + +![Entry 0: 0x2023, Entry 1: 0x6e2063, Entry 2-9: 0x0](qemu-print-p4-entries.png) + +When we look at the [format of page table entries][page table format], we see that the value `0x2023` of entry 0 means that the entry is `present`, `writable`, was `accessed` by the CPU, and is mapped to frame `0x2000`. Entry 1 is mapped to frame `0x6e2000` has the same flags as entry 0, with the addition of the `dirty` flag that indicates that the page was written. Entries 2–9 are not `present`, so this virtual address range is not mapped to any physical addresses. + +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.3.4/x86_64/structures/paging/struct.PageTable.html + +```rust +// in src/main.rs + +#[cfg(not(test))] +#[no_mangle] +pub extern "C" fn _start() -> ! { + use x86_64::structures::paging::PageTable; + + let level_4_table_ptr = 0xffff_ffff_ffff_f000 as *const PageTable; + let level_4_table = unsafe {&*level_4_table_ptr}; + for i in 0..10 { + println!("Entry {}: {:?}", i, level_4_table[i]); + } + + […] +} +``` + +Here we cast the `0xffff_ffff_ffff_f000` pointer first to a raw pointer and then transform it to a Rust reference. This operation still needs `unsafe`, because the compiler can't know that this accessing this address is valid. But after this conversion we have a safe `&PageTable` type, which allows us to access the individual entries through safe, bounds checked [indexing operations]. + +[indexing operations]: https://doc.rust-lang.org/core/ops/trait.Index.html + +The crate also provides some nice abstractions for the individual entries so that we directly see which flags are set when we print them: + +![ +Entry 0: PageTableEntry { addr: PhysAddr(0x2000), flags: PRESENT | WRITABLE | ACCCESSED } +Entry 1: PageTableEntry { addr: PhysAddr(0x6e5000), flags: PRESENT | WRITABLE | ACCESSED | DIRTY } +Entry 2: PageTableEntry { addr: PhysAddr(0x0), flags: (empty)} +Entry 3: PageTableEntry { addr: PhysAddr(0x0), flags: (empty)} +Entry 4: PageTableEntry { addr: PhysAddr(0x0), flags: (empty)} +Entry 5: PageTableEntry { addr: PhysAddr(0x0), flags: (empty)} +Entry 6: PageTableEntry { addr: PhysAddr(0x0), flags: (empty)} +Entry 7: PageTableEntry { addr: PhysAddr(0x0), flags: (empty)} +Entry 8: PageTableEntry { addr: PhysAddr(0x0), flags: (empty)} +Entry 9: PageTableEntry { addr: PhysAddr(0x0), flags: (empty)} +](qemu-print-p4-entries-abstraction.png) + +The next step would be to follow the pointers in entry 0 or entry 1 to a level 3 page table. But we now have the problem again that `0x2000` and `0x6e5000` are physical addresses, so we can't access them directly. We will solve this problem in the next post. + ## Summary -This post introduced two memory protection techniques: segmentation and paging. While the former uses a variable-sized memory regions and suffers from external fragmentation, the latter uses fixed-sized pages and allows much more fine-grained control over access permissions. +This post introduced two memory protection techniques: segmentation and paging. While the former uses variable-sized memory regions and suffers from external fragmentation, the latter uses fixed-sized pages and allows much more fine-grained control over access permissions. Paging stores the mapping information for pages in page tables with one or more levels. The x86_64 architecture uses 4-level page tables and a page size of 4KiB. The hardware automatically walks the page tables and caches the resulting translations in the translation lookaside buffer (TLB). This buffer is not updated transparently and needs to be flushed manually on page table changes. +We learned that our kernel already runs on top of paging and tried to access the page table that our kernel runs on. This was compilicated by the fact that page tables store physical addresses that we can't access directly from our kernel. We can only access them through virtual pages that are mapped to the physical frame. + ## What's next? -The next post will build upon the fundamentals we learned in this post. It will introduce an advanced technique called _recursive page tables_ and then use that feature to implement a software based translation function and mapping functions. +The next post builds upon the fundamentals we learned in this post. It introduces an advanced technique called _recursive page tables_ to solve the problem of accessing page tables from our kernel. This allows us to traverse the page table hierarchy and implement a software based translation function. The post also implements functions to allocate new stacks, that we can use to implement multithreading in the future. ------- diff --git a/blog/content/second-edition/posts/09-paging/multilevel-page-table.svg b/blog/content/second-edition/posts/09-paging-introduction/multilevel-page-table.svg similarity index 100% rename from blog/content/second-edition/posts/09-paging/multilevel-page-table.svg rename to blog/content/second-edition/posts/09-paging-introduction/multilevel-page-table.svg diff --git a/blog/content/second-edition/posts/09-paging/multilevel-paging-motivation.svg b/blog/content/second-edition/posts/09-paging-introduction/multilevel-paging-motivation.svg similarity index 100% rename from blog/content/second-edition/posts/09-paging/multilevel-paging-motivation.svg rename to blog/content/second-edition/posts/09-paging-introduction/multilevel-paging-motivation.svg diff --git a/blog/content/second-edition/posts/09-paging/paging-fragmentation.svg b/blog/content/second-edition/posts/09-paging-introduction/paging-fragmentation.svg similarity index 100% rename from blog/content/second-edition/posts/09-paging/paging-fragmentation.svg rename to blog/content/second-edition/posts/09-paging-introduction/paging-fragmentation.svg diff --git a/blog/content/second-edition/posts/09-paging/paging-page-tables.svg b/blog/content/second-edition/posts/09-paging-introduction/paging-page-tables.svg similarity index 100% rename from blog/content/second-edition/posts/09-paging/paging-page-tables.svg rename to blog/content/second-edition/posts/09-paging-introduction/paging-page-tables.svg diff --git a/blog/content/second-edition/posts/09-paging-introduction/qemu-print-p4-entries-abstraction.png b/blog/content/second-edition/posts/09-paging-introduction/qemu-print-p4-entries-abstraction.png new file mode 100644 index 0000000000000000000000000000000000000000..6a0777674409e8acda8c374a563b25191ddc6f04 GIT binary patch literal 18345 zcmeAS@N?(olHy`uVBq!ia0y~yV7kP>z_^x!je&u|`rBk>1_lO}VkgfK4h{~E8jh3> z1_lO+64!{5;QX|b^2DN4hTO!GRNdm_qSVy9;*9)~6VpC;F)%1Fc)B=-RLpsMH*a z@=?v@A?qfsT@e(P)Gc~?Q;NqX*V9Y}hi5Q_drmoX^o}Q|h^D}80f{qJ+l&3mC681%dfv*p5<|;c-Q>rFVkQDe_7`z@6Y+J?s@d#CD$1l7#i$;{ZO}ic{JYo z+aaX}yYGvvlitsn@_E~n)clFN|8MN|%ZttVKRI9G?fi*t)3-N%{8uJDd+L4do%JQ{ zkE=!Q+y6^{DAKnyF?80KR|fv4wX5E!^WAxNqJQaB<1L?pPfCOzTY6%i*Qf92?;PFG zs>8l<`oC#`QBS}5Yxti0Hbte?{r}>}|3giBU(}2FJU#MHGhb@S#Qmkm#1bz~YFGca zW&fm-h+n)5Z*O(Lb>EE-LqWX1S_qSU7F<5BZ{Z_tyVMu=0-i(`@gUhuI zF7e#HT=)M+8mG0yl8JjdKORXam~k`u$=m-&g#A6O4p(CcEPG+Vsy|3=9km zU#=COkG11kW}7MJGT*k^d+$;v1_p+x2cMp5gTv)#sW=M*14D-L`*-F0O!qvUW?VX* znSp^pSFCNJ&G}#f7Oq1M2X#VLJSfO4(l|N!x$eIAk2QHF@BhBJ!j|Xo;*$KlIdjjI zSQ%@reqa6R>1p|jPqp#;;{V+GG*vs?)J98zfq@}Gk;l0;aYdwn#*DKjGkrwQq_sPi zYTUQxiC|~$bz?sH`T6T^XIa*x-6b}aK@wU#%)V;I%_YxnSI<+o*IZ_+bKPWyCPyCI zpMCnge;e5jH~x9(z+4|-u|RIxYBP`zZw3n3@|w()$@u@kq5N*?^mltc&zbjq&-2&U zqR+qD`CRYy&Gh*fANSiY%&&PY9VOXsD#QCce9G1xn{4)Pk!f4F?DEQQ-}y`4-Lc&J z=c)eXo6-4KUj{EP`TMIhc3+Kazum7D`@XKtpX=ei(V@a@_R9wk9O_>_eg0*db^hhp zbpO}ig0riB{aUxL@aL?5A3l2jIv{Vq@Z+fnsk7fTg?y^Z_kUjd@a5&@UZD?i%r4)% zx38?M>}ln^YuCcIZrZfyVL^b_-Q+_K?7ORP-JG9g#I17vdV$HMTfbI?wRig)HJ0hc zU;TRW1OqL5AWKlkGZwEcdDYKYjhYH7;K9~T+XN6vY(M*BK7iK^}CC?+vi@*5z8>+ z7GVkg`7fZkas9yq*Oz)v|N5}M#%1zJm&X@heCYa8bJIaNH}34rzP|1}^UL7nW^1$y^7G@*$5r_yN@Q6`c-*tuAoqj$ zZq@6^wQG9TUbYkRDalQDzW@2%_ZNHX|C#<;XYF_Tezjlyx2OIuo8>D!=2t}RO7*?9 zch{=&zjy0b?EiLGT|42|(fXD0|8L%(9=7aO<<;L`yzM{komKN|`WO4Zf0jR;8_9Bc z;kR{FRd4(MGyh$?z3^}hFctq((XTVGzReYLxO-gDW% zv;EYidXH5dx4yTCzxKspsb8PBo^upJN zYyTHyo^Yvu|MvdMhrQmn?%zLa*C8El8Wnr}e*NLORrl5Rtvi^YaNnGJ;@bT=7BhWH zo}SuTDX@3fD*1m8S`yS|GU-w%aJqF%_sZqf7kx?^8d$sfBpM@cm4T)Pkw)WS&+N$@*B?D zC-Hx~>~`5-Nch;8WN_)&D~HXp{^|Lzfgz*&rp}cVvx{@f=UsmFYE@ZT z+17|ff-DCU8EooTwUz&Hbv*ysWTwy7ZQIrrm(RPreg3``9~0KxOj&0AZin-7Gc&%+ z6XhzOD9`d+-dTCS{62q%(M*}8#UCHJuH^|cnd`T;_IO*I#Jh~5pPN)(K04Pp@8;YW zQ_t_-$@Mt<{M#2-G8Pms4>P&FcbT={+^hBf76t$MKhJW;`b`D}5+35~ckJEE%$m63 z>Q&RfTjhTT?)@Zsf2p+jI`2twpI5!V*#GZD|BLuPr{gakOj&gIuI)`-`I%YzKlJW? zUnibj@ImzNv)}e>^85W?PHR+Yz4iak`q$I#|FQkm|GqEq``)+Lzq;?2zH5FVrGD8@ z*Ub3U>0wI)xR_p^(Ov%ZtlU-i`uf=N{mH@a_kEuHtNcEn$?oLf_qB&t$^GB!pY?ui z{^if-=S*u_?mtD#<`3u1$&6(`=eMzf0`ur}p7@e?uD9;qy_#cYU1Mvpt7}ie=d4dP zj=2IXR^{(pt3GwAn{qw(b~!h9w{vy%=Mu5q_sZ{opYQQ}qPyLylPN_%X6$j$-}iaW zyqZUzmD=-`ZJznA^5Cpx=IgX(oKrry{CnE3o&L7V=GXk~{&MQ}wXa)G@BZaJztZXd zU+MTo)?v?Y`{c)5-K!sQ`LO@{tQ?8+vT@t>QC&S zyKdgUeOWs0bJpKm1xr3=EV-GJHMKp>n00&I@^`zA27frK|B^erEy}Xic<#qjA@P3? zEw;rffKzh3`8|NHB8acQ>muNKySuzwvcAAivx=ITsi<;sVq zweOhaug`q{*YI!a+v_jN>pq^YI(lvIuGbH^e=V2)vFYBwY1>~~=Uc8#lsMugr)Aj_ zb}E~Jf#L3x${>j|C0WVN?CifM`K>F7&^fu|=P#dm&oj+tXC>Fx{(EYF_VUdeH!d7J zcyOahS$TQ?(#;0_`p@s5jkfnWK7D_23TO9U*-@cf5jMa2$>pk?je9KjELunQ6+mTcW5}z2sp0umVtrcub>y#p@2^%TUZW%w)uPSeXUXH{PI1I*Sd$V4i97J z;!EEBz#w3rkDB{SkK>Q8yr@6FKI;7cxJXN%u`{2yNcr@wTQ++`+$}??UX$5pP3E5avQxh<^8VjX z)3fU9|9?mb`+DE);H50#?L`h~pIlpDKY3`b8uJW=H=V05af6Bj}+1jtz z|7ZKVD=QzGf5{f#w`}G2`I+hApUlj*JZ#-1wg_>s<4G|L&a@$Mf)o<>lX= z-ImGQy?wj>`Pu)g9zHrL`BD2Kx1)fJ-8;Q2|Ni}}x!Ljl^yiw`+jp;@(g~1YbH82x z^!&UF`~RL2{rll|{A&I`$Ms*Xd%w^1e(~wE%THJCTmO1@^(UMA7W1rYT8bim-2e4! zmfPZmY|Q@u|NMP_J>CAh>)Q4C8MU>}^Z)*t{zbp;=X6tvA5#78QPI&GPdV>ffAH%1 z*V*FCKcB}fH{Y*u;at1I#2;R6x2oN4|N6`6{+Zu5%U@C!XP0Ubek6-Z#xwcPx(!bt#{F|#? z|El%9Z#BN_-oN_wHP$!3e)YYNpBfL%J^uA<`jW={!k#~m<^TUUZvXFNf4%O%=fC&O ztA4jBZL`DWmm!;PhFDu$gG#M;@78_$_O0(@ZzFexkiZhMdLk zT}4k{1zLTc|GTd)^W(GW5=#RvzkFk`-ywWmjP0M5`TorZ9qMax{TDK^ZtiTl=@P$t z&+7TVKc)UXD_^nsUiEPg`>kKg{!U&Wb8Y&(+m^S~c$jUgYU7(99{6y>Tjy;=boAw$ zo43DOxqRN03X@Cg|3Axrao_&O0ue9k-PTh5$GMsUw%@O7|MvZR$=6p`4^?{1J9hZ^ zmxZ6>uU@PF%=Py{|NrY%Z|47L`}g5dbmUSO)_rExlUS@jXVX!sZ z^OE!Ne*^d0{5q_2(Dm=Z{J-qAfvcmUreLr=FSEAf4lErTm3zLjeYHp%eSIG zK9!Zp`0wz^Z++(3$!w21|6M-3e|3J{`}&39|8LyCY+rXf{Oeh1>0jr<_xWsJFZ1H! z{eKJW#Cf)=O)FzyX!!TRCeuRZ)y(vLYkPZ5&!!ny#wpzAH<9?^9&fPc=V9H052rqH zIQ%d`TtDtghQSp5|1MUa)4jdxKd{$Nnen~EDo~)s{UuMka^=GHA2ZhU+gAIouWA&L z(=(5ZkG}r@gLvG+_m(?WoZLSD>S@3ESMT4enH{G0Z{?wv=WGrhjOe#9zFJZ8>c-SJ zI@i3d*Tw8ywRP*txZk&~XP1|UU%nag_~M^WKMp=|V6Ih59r)s= z9Q*Tw{>%CMzNmjSfA^E|@00U)*Je*&m$j>IbzZEz#-3lHe_zM{F#omcn7O{k@9i(A ze!sIi+)a4azm0PL=W_o#lo6Wk?EmnI1N%bt^YW+a-#Gs|`d|A>g3Yy43RmhX4E8J8 z#$BByuk|I&q~^``ulxTWUj1v~{-X8wzHADAUCkaGTl?$uFMjzy4RvoPs&Cztw!4Ov zfnmYiCWR{*CfAmFpMP0-zJ6cWF=bXqh4bG{X7KVcXUggcahP(aaW(%8edB#T_S)0u z^Dh7TrFn94+u_GAebN`k{r`16)8GUD^vW~!e+@XEg)c2HD}P!&FYnEp7dO-AUA^^d z*Aq|e)!M&4JeAFzKl8=WdFvCZ78GY2XFl&-YGLmAH_tTT6M5tFwEx(zD_;ZT zciLUJ86Cc5`|QteUOL|cb%HJA`af;=*|=}ty4(5to%O4Kp8oph`F@9e&tJb>KL66< z{(qf%aeG$GohyAU^S;Qdgz#Nouijt&`(54Mdw-6Fzv!Fl{p(Er|7mrP|EPam{#$u% z|Fhd~@87t5Pe+qCe)aOOEsxG_DSqoP`Jl&g^ER)4re9sHnAgsi%Px^v*uHt?w{Od5 zo#C6``Qo=!uX~j2Z}qULpss4;dw!GI=S;Yn_P$9imyK=g`&V&lqkQPcTGq`0{dT|9 zrFhz<`oo_5{yhKtJef1{>;GJu{?D><-!uO&9ZQs77OXt}N1RWz>esL9`}Iy=W?pM_aF4u`CqVP^*xXJ=PNJI%9%4!B+JUPuB`OR!GkGs z9{q0L8cU`&y$t#NdtThP@On4<&9$@j{vB`sI$Qov&%RGLjBm|k^NMKaV_;}d_^gC)MX)N_dc+TKe^dIA^oMm4pBGrEPY2e(vtV zty{MqHd(a&@7}}5pP&7*Hs5xg0>_qJyOhpGp+s zu~m8hJZ$|x)y6w2uqH0p``0$M?%k$&Rj)F6+nCq(9RI|ZeDh$zil0IP{);b01lOZQJq5Muzuk=7N(Yi*BY^#S7Q& zIFtN<-$a7fRIZOtKG^)e`M-`mKmU6tT3kMuvg&0@)s8vJ6Q2M4R2zTzp~K>j9{Zll zb02emJXJWAyD8xJ?`kWH8`pEJ{7--X`*YKzk6mG5VWx9sKwYhcXZEFNcwT;)Bj>@- zQ}4g0(us9*K;!ew7s4*g3=CIPubfpEK2EdhHodenm6wS%aly-!Wq+IhE{=E5Niv&#)BfK&O`H3d9p2ip zF)%dfMYtqi?$Q6Qd->cszokEUpZ|9k0F6b8B>t7jWME)ea6W4P7SIsXio+kyyxd&% z;!o?Y(~JxZ3|o$UyOwr}|2K$z!bO3Xfq@}HVFGB-Qb)i8q(O{h2}q8cBG}v>$D*pPT z(pF7S(=x;FWA%_=Q#vB?{Q!!3P(`Ct9I z$3t6FR=hYisQSjUr&Y7HZtc^3d~E5W@*Q0e={PMTneQ_$& zPDok1_S@#J+no7b>E)8#{6kmwOfWzHTz0;E{l(961!fn`9k(pA zHt#>3`}y1ZDEk~1OkbGL=$Zms>E0G@ z{9+r|nQTeE66SiMvdymBJB?l@yPjiJt6lV_a)Xy^66fT{MmN>6*KN)$pIl_JRQA)e z%E^{mrJ3%*e4BcfO!f;~&U5&;v}DaqudKt{wr1Zxbvry(+S+w}PUu0Cj<^k)yH9eS zQ_&Blo`|jOcI$mMwd7Ca zc8*8e1wS=4ui4@w;vm}MuihA! zt{_+XsH^19sS`$~3z?=Ze6c(&TJMt9EVrBfYnJ^iT`PagUuNC9lBIj&)pm5RE}Apz zN$9ucj+a*rE^D7m-PSoh_vWJG^QY!d_PZDA$(@nAW5({Bb$50pSh4vs-BCJNa;^RB zrpld9cJ)7rwOsdTN7tO`;w~Xa$r?>U1A1&8gZ9eVT_v>YqLbzc<_mrL8 ze>e14-O^t5@@uk|oX@jZ-D#`VzTWh8&i4Aa0})T2ggiCNeONSS*0-xxGh#wCg{JKG zTAqC>ZjaH~+Hd^_{pqkLm+(So_J z+tqx2XHD+6z4tul^vx@ewNE`YTBK%dxy?+je$SbejaybXuP!bSj}^X=<~z^j@{S1k z=SKP^@wYa$nSJS9vuW13(vPLvGhe#Syb@^xPGS?k#ffj-x!!H(oWr;EZk0cNUA_C- z`rQI9>1P9vZ@Yc(7LR<*kDNTGi!6^i(|xNlGgbCZ-?sncw@9DQI)|U_xRkdsZLUUl zPI8c5_*2bU;g`(RUcX#)d+S>HXH!q6-QV+V)7@oVhLc04ZP~MliEFZ5$P)YKtP3(z zSFM`o`+N6E!z1zLvdxv1y4kb${L&Q85zp*i^(^%A&h0wk$s1nC#69`DXV2w0Z?E%5 z|K!egyZ7^S$-3_R*#QW6W=f7QhW;3Dg#h=zgtt+DLuXEG+ z@^#1Tu5TIQw^rNVx^pd8&-z08?daJ*?FIJ*JZE@+S>^Kb?({>Xw_MJbTRQEPJc5?{H=la72+v0U) z+sE8Rk1|ti&sb$kPu}zB_L0jPN^4~p7#JL+;=Srb`cF>1skQ#zv!|{KJPZsCTB++M zn*B^&zDN7;N9|K;w`V+IWnf^qa`M&bwq@BfKG#JVflP_f4$=elgJy>+gf#HQQo;IU|*Xf_32MzY@ z5A;7A@vV5-W;xD?_C3$@W=~svVlm@sJGTw|e*;#%E9_SLY4Y%5zgqJ0bw#tj%wP4| zGF$I-)tVK)a@#URBu}fQmhJTwtzDt}`25mE$vaW12fJP^SoNT0SSz#9vnsQAneT3K zPxaht;ne4?$@V8U{m2g&t_=BPBx3(CLF%xbDrZ-Zdv&wmDBHD z*4oF}xNh~aj=DwuR{z%A*7A(hu9q|>`(HFFUn`&XwNuIG)p?cqdvd$3 z`HLp2@9NF1-YH{UdS!FwPM`Hh(paxwtpE63?Dvc>N4J#toZ8cqJ56_GUGCMweJiST zX6H;+tI|=cRrbEx7%}zW{MDcPwbz|`oV8|pZntpwlE>k0(^hiw?&5K^e|xKFV%SBK zQ+1b2&aTh?Yhd?q_b#WY-|A*Q&|7z^Fl$oyO@5_i;TwI{t4zPC7Pl?6TdqEA-$#cv zFRuRBqP;vcX5p&nD2MFBM`bdKpI&3VyfH`Uff(nq&30R+ojt93y;kM@sY21?p-=wo zyRq-goCmLVoZ9C4=u)4R-OR6zuUF4s$DSa{yw+pp%l6|}YsHsi)DinvJDg9gFZjy1 zO1n0s$oih|?;2Sjy>lX*r(&00Hci!Un)z(wg{9nyl}7WG?;brjWhv)&)#BIezD(&^( zZ@E6{QgNZ&24Cg(HW^mw$F}=w2VdNIbc=89ZEgLvN~g9Qg;ffytIw>yvVAoNcdhNa zWs7VThv+IQ`_F4YV3E#euzW~V6J{oc9Y{qg%ETby@ah2Lpq{ zbeY{sdpSxjF|En?Fh#86S*|eef{s5w0%=! zQP>CB{kvjHq$ltBrL$UY(=Vp491IKrpQrQsUN?BIn|tEcF%|vmpO}8Fa(#V#S&Zk` zm}ft_wn#HDI0Vm)P>xM4NZxejP|Dm7M)l2i-7Yh^h#!AfBwKpPs)~W3VVk9x$MO9; z!dsQRopa_N3RGFYF6-8+~ zn4>Rmz2dvG>h6|Lpbo^lBmA3EBL6tJU*peylAA1)qP|qn|9Fb@V?aYsU zay-oEvgRh=i8VhG7#J9CoddU3tm+rOD`H?^U|73x@7BookKcpp=50#2M>AR%ZkZF$ zyrtGU)(xNNer;;)p4jQX6GKA#8BIN8k+d$IdU?tJ zkl6E){YTGK$*k~|i+maKbH{~kU!JCB9eNxo9&={3Uf=T9xqW3HmQFsOUS{g>N=$ae z#m7-@KQF!7@NQSf^wnqn>1{uId%yQz1Fd`N(@(1WRhv`ebIecnY0Q)NkDOPo{xqBA zV(N4G%O$I3J$`ij&X#Vm(2OX7w@uyuE-xw8{iR)+=`PHc6Y1JK)yUrZo{Q)4d)vx# zqbq-}%1%CRQn7kcroi5W;BSjwhQ!+E&gPHl=~iRCxXv`QhH;xv{mp{H+iEYby?P|h zD!!@CS3i?UW0K#!Y**7nC#|B>B_Hd;YL_gXTG|u&GUaXfwtroEn_p(x>m1&)*T>HX zrGDuA*Om3>$L)~wnYG*B*~Ny4o(>gzfBVb)RWrXmfAKm~UL^M1>d5tsu|QJd%yq zr){mjS-Dm3;-_nO(=Xbquk$!=KT$6@w0XlT|08PZVd61MLQQ(ttS;93{5s0M$N!7o z`d8|ZuED32OmNx%(QL!cRrjw|^~u#w{dvm^+$Zqw`Z8Z@rcCr6z1<=OMOURuy<%l{qUN48OEKTVBfje|i|wUprdt-~r%b(C^0&CgH@8N9 zcIlPO_oacdf0t*-g`O)-{roEWzoU8O?daJLoB8Ma-d9K!^8012mCGAfb3rtAeniTF zRNjK?%-5go__Xf=T0wm)F86i&veZpC&DZbE*>1R2Ufk!?DXuu5UjY;U%@J={Hg)By zDzmrm)s9d2RyEP=q;~Plgq0qDLrkyFJlDSN>DKtD%1PH;XMZ`mWY45eCYt`&%1X~J zZQ#BgJ^Qo6uZ5q*U+H%Uuk%E`I}pZ^u8ZnvFcjFtS6USzAkW;j|@+R z3{2$w{$V}aX49pWpSn|WU!FdFWr_Z~oioBK|H$q-G`+9f;e7Rhn+z+XOBT5GXG=cy zUVV7iYo)k#M!$F8G0Xq2_x13Kiuo~WlfTR^_+%()T{@+B;{I;_rRz@R3%N|6Tkmsu zWmcbY<-Ni$fAzAk=lmb$+ivT`}0_*!J8{b+VZs%WGyYsm-}`vU+WA*BztSJ^7!xV;*9(pc&n_84~>ejI(b+1xxnVBW4@ALn%G2`Ro{9xPVU+?bvT@o0o6CSxI z|8o7Rv|IBRuU}ppP-3}0Z7*BN$xiJ{mD|rgI_O(-;pyFZ=cP}a-eAG`j5i~E`|Zu2 zPDQ5)?O!{~+;HmNt)VKs)3IXK~?=m3q(anRWGF>hr6+Tuw)q&v*SlXNQvPf0tc8 zp}dEFxXdU?&5Zncbmy9A@k~))<=3y~oc^=x8vkSAy{lJeWxk)z`R>swn@I48fX5!* zoOQ3ZZ=JXJczo)b7H=_%@vwn7IIhe_obh)kWBw* z-2tbGMwj{fS1;bXXjYv4vPTC~?p;kvpX8nx7SPWCRvOLVg{obR8|TK)3Z^B=Qr{jf88z2fq{ z*Nd!v`CqhIHRtuIXIHoXYtH+$ZM)fFc6qzm`y5ZH%=uCta!YE@j|JMh>^8n=IBoTE zM@n%_Wqig-uk&Aad^+`Xm5u9XuUl%_PI=Y#CYqDa?yG#8y1O^??~a5?;b9+=F12@k zdA^6iWUWu=)yM(6tt$44iTk~Ds(NPZ7SDK}Q`(yT zlRu^8hF_22+Oc8pR!jaR@}LTN)00=P)vxc9D-XUX_tvTU>guy!??2mgJL1~MZ)@c) z>cg90yhrS0vu|H81F2c>Tk2n5*l*=3Z(=lI-RoX*uQ zz3V%-+vXip__bnUW66E?xcmM4H8a}F7VZrQi~l`g_2YNhe;3|2lCNiHU|>*?gv?hY zYRt4RThn3mdd;-dnejCd(EPqUb7$8Yah=`UHspgkn;VPF`Zuofy6Ao_G}3SKzu;2a z+jjrXsr9cZS@lOLGWypiBh#1N)q2lDRV;~c+;ou<ySCYL=F9d1 z&D=<5>0fSPk-pdMk6*uX?EA(@_qpHV#IIhg?|K&aG$!0^{l2gAC6l-B-70DKDq&%?6DWWcCNcNZI|2*v*T00w@zF0#b=wL=JeH{M9ykw&R)a0Q~R&M zYFPj4w48pRT4gG$zFO@HkNR`m4wp}bgxb#jRz5k|qk6B$>?c!q`fLbUQnzZ>YoF)N z*FW9TUu)y}dXew1q@Xy@%2`v?vv==$7IdKX?b@@I3V$#B1;^VfojjU}<$ z&&^W!*ZbjU_KLXqzZ0b|#%U}*Uz}g#yJxlPl%V=o0)MZbaM<;pc|E-2rLlT_?TM>} z-?#p|kUz73KWMybLXQJ@Qqo|`8F}k4mzkwu>vSIP=z10!F8jpx_T?=xuGhGy#YW$_ zS|<^HRmx{_&8!V_TV5!?UZu0#^Z&|S^K#|u(TZ(te!b%#-?qCE9YCy+}3;cM(2CsTAe8J8uCUueod9(>@j!q z`kze(4f!vAv_15*+OkdCw{*4_Ppaq7Ui3Bi=#9?2c6MYtuF1Hw*8%5_dm-*SF3-W zB{Qela%}eFJALN%lOwO1y0>&Kn^;?~{6&=^me;4A zU7i1z{qB?8{MQFW;}&Vp{RhF}$QU=_2Fw(o2OWVQu)Ag-@rR4z28Z zHg${dwU#^I>N0}VX4ihcb-GOY@~^^!D(lxgIJ$&i^yT?V#*C<$t5&67{+Cz8leu0z zbMhXe>73KLuK0%*$A&(ivSZITZ*BieyD}#4n=vIkXr9{BlegBb+bL3zSe;!g=V4#+ z&*^UJ$*b4>*TIKWR)x=gz5i_L_Kj;Ezm2wC6u)h|+2s8>H%w}!I%;79E34vXznb^& zkz8q)T}FyR?De&q)jH~xYd%V?y8gWGhT9hLQ!hT>k&YM6ufEgc_$5%8`Q<+TJ^SSA zgD>#Cb*f&tX5Tl(@Z)!{|8m}+YWI&1G-PcA8CX6PU{wDmLNN7OxxQ`bIU_x*4y*=_jDrWXmZ&m7QN@aw)FZe8{3u@b-dZJpUCZ>(HAr~6NA zjYer`-DHJbZ~i3D@(V4VbMkZF;`il&mzy%gW4_E+o11+xexJNf%-kM8}CZ>zjbp6quoJ2&LXw3m-+XU9J{wQBjAl1<;VZ?n0| z_qy2IoW#;&w-eK?`;)us`Iddr<@5Dcbv@PU{+|2G|EkaL;xAvf@OSAwzq;mngB~cq zz26pTv!j!L*Ph#-E14@L#ncb(S-cnhACbem)(%0at zG2vG&RrS{Yy>x2w7QI_b^wpkDowD4sa?`fe*?O!oH}2h?*4%C$fB=bCuhg^ z?_QbFU$$`XtEgq{RX^;cgkS+#EdwzKSd$6O~jWn7B)wkbXgmx@>e14a#D3-qZnODND zGp@|{v{Oq~%-p@EEb<%qRr)HKme4va0?qfwS5($-l6QHOn@}9Of9+Qp+kaZ0w@wwi zaI3&@zQ{}aP$SE26|rTS51yG*tmc_5m?RfKNmeC35@Z6_$4iiDMOw&SXQK!%J zSatDOm6@jTUjetBhT7E}B8$*t>;^R#X) zj?GwKwRPve+c9O*r>*YoyQ=&vwL07Q=jk@z%gY;Yz~|0?ZC&~9rT)9XD8rmJ3Ou* zlNp8>EsasEPI__5@efwLHW!bA0>6eRU#@U|ReJb|*)I&=)-CC9WuGCcT z(v35#Bj3iC#jW-J6T=_!@`&imAL^GBt<>hJitxjQ&09FmLtcJ;;z+BM#(n$am5j?>_9GG<_4R{@<1Ff51WVphHWSbqA< zX_tGOZGBINrtD3)xwSR+U3*~Y+Jm5ZxYv%|cAM6nf-D2M`R!x5S!K%7;HTmzZ(W)` zeWhpoonpiFpMF@EwCc;gZ{9@7gV2 zKl_#C+V|J)F7IBIwDZ)X+S&htO)vkGskMFEyy$eL>1)#k-hMF?&+X0?=xnoc4oatfHe?3%+6;~G_v$sC~ zb)(i?*dRQQ(`;>zb)RFx{^^01!=UPKMC0eJdu z7)X@(tIYG>{@b$Wwi9*)OWd3PD^Bp@pG}`mRoyq4tF?30d^L@z?P_mX85l0G9$)9- z-aLQLforVc2g4>enN9zCnZ@;$S=F1^)$9xm4LcJ5seR1~n!v-rz@Q_+e(9rjPip?d z*)bb+Hhno9_Qhh;C+}10yLwOmGCaFFW9H;jlctB?`c`v*k%6H${ZFd%`RWHpF7?3_dBJYD;@qdc~*GM?H^{9nKPb=-nYw^p1jnNfq@}5@aHAI z@NkpgC8;K_C4Bd{%-ohQaj#y-VcS`528IRs6@OygkF0MvzTPbT?e-h<^f{Oq7-lF> zXuG(HZ}t`j28La0LKM!1p2=DFDn0V6jQ@341K;@!3=Fk}Iupz)`3i1{-}N~^OSOemEy85}Sb4q9e0A{jrCjbBd literal 0 HcmV?d00001 diff --git a/blog/content/second-edition/posts/09-paging-introduction/qemu-print-p4-entries.png b/blog/content/second-edition/posts/09-paging-introduction/qemu-print-p4-entries.png new file mode 100644 index 0000000000000000000000000000000000000000..69e2a6023946873fcfe3bade36900a4177bc4e4e GIT binary patch literal 10856 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
iKnT zchCM^`ui>a-k*QZ$z2rOxb}3(a#xS^t2;MuK7O^(EPF|NTy~&KpxDK%ZHqVFyYZ^Q zqOWZC+Yh0}I3 zObR0HrqsNPyIoiRyE3-gFns-d_w|KsXH8F8EI!A|aA51Fj_l^(X|)B{9kT)q=5INh z{c_*>zq|JBoss=p;_op@v+Ej?wuc9!*zcXm}mE^}4zFX`@}vVdW05`P%mOy)5-RWpQ|4`He5T+a14e3;$j# zGEbi2fXU5`N_X?WZmB-HIbQO>w-0x-k8Zwx>g9sU@250YpRL~NbUS}t;#1MR$6kKF zxnbuq$@F5LL}`YE66>ZfD$ZBFO5E6W_{)|xE~_W9F-XLpztrc+e#i5Sx$l03lIdID zn7Qyruazs6VPH6BTp<7Qb#7{rxxRFtwf}ni^8c~ECJYBkUP~|et`*>?HRqdAp6@4> zXI?jz@_!rq>|Ou%vCNb6Yzz-JoSrsa>~y=l?aluUjMnKrLGv!;_r%TrYF$6&G5gGE zZ90qJ+%ohlo)h>?%B-(Vhk@a7bX?RMmY42w*0mR|8%+sfWnfr#^wXtB52RjZD!MQ; z801#HyH$8$iZla*!P{j<9^7Xc7<_g+2i{_2V7TlCPKj4LE^hadc8|0(300MvT$Nb3 ze%r0r+iM@>ty_9OVsXsp4X*>Q^D)Haf9l9)_Ag&NA>{J4C&@wACtu1*y;4|a?Y955 z>iMBa&0(UX-8T+nYytu?nrhHA_;ako9*6a)nf8TOkYK|(- zUw5Od{qnp0{gW>BK7G524WoLGjUOD`XnZe>s z8OzJJ+DCuCtm28fT|e>0pSbmp&AxJNLww@o1_H@@~ry{AN5Cd>>5Z~0s^*%=soq`@_9 zi1M-9TDc*YFUeJ1`g(0~-h1z7h^{M$+*0mmvO5vAI zpR%suvBitOE8O4aa4;PBa(kna?V6?EzD?L`%fqiN{PKES&HnIcch1$-f!8)!USDwQ z&Aan$TO+q~@iG|9En|7&pf`Q`L0UY#Tm=u1$Lc| zYFj&jnZaN#+dJjj8>hLB@m`#)we&^kEk=d|4=r9`_mdIes@kw@y}S69a?K z`lm~e`c0^Nvhgx|t*&$AR91$BC>?!WzI7Ali8+}tFkD{te4Q+N?ghCs3=9Umxbn{5 zn`-NH9+mM3^VeOLi@m`y+1wIr>Xz8jDHnVZOX^M@EawtZQl?M z?Dmrub9osVX5?9iEotBS?4I1F?d=Z}QVE$`>-96Q&l?Wx5>M5=`}wO>{pZi` zl7Giu&I>!i$Z#VbRCa~Cs+(S4lC{Kr@3gbo8-#cn3M#(pyq!_9!8*&a=*HiY>05cM zzOAqo2PMD41H9X5;;TRY<=FX{?aE$_?3;7SFT~xrJD)dubKQl9@(d04;EDQe;}?a) zndLLKA%*ho^*;|={*+)~;C%1t;uylWswL^hkGrXA&3&R97#WsbKTx}5{q{{wo>PN- zPQS8XV0ih9?d4vsitFBU->>+3{_wVK(%bu_7#f-<>gwxG{|8P>to%m_o6o(AAVU7R&PE(fB)4A1_r)%aH(GAuIs_Kdw!gL`LZ5n zh64vBcl3Yx8Wv`-GN>zVsVoD7j2@&QZ(j3x?vp!f>LYs+alpJiGQ6mc6|&ft4YlN>^XEtm%t#|6IEl*^;ML=`b){ zPO8i-Ea?5RMPLyl!wfUq^0yWlll6`>Ff#mF$DtbNfIW(J03z2N@RD#7OO zJ$|~IEl!x-x$V12_Iq4zboy^=hK85Z++(CK?UHU?GHY30?Ov$`K1J)Mq;CX=YW=Ti zWiqXz7YetZz3r=hB(8XA%Y(gA>@5Bp#dpBpdgW5Tlvr#I>uvA8@731s@OEw0E zo@}k=Ef;tg4s5X&0mZaIF1R}y&?~Vgy(DXaJN z?HmPZ-ZZ3sp7+hVhcA1Z(MwPbXb)=C9O8Ph<6)(FtVDJ0#pyy#-?L;G7`}y{kF_>C zZS<@3sr1(Dha1Fh9zG_yRQo}qkzcwq1H-c0eWEWD*Y4cj{^o6BMZ`>x{ofuwf2 zi}=3k&*J;1%GOuQUQ4^H1!@}J5?rFbQ_Je)&Sj}rw_E%8pEhM=FxUr4$dhY03xwLv zUXHzH^df>$njxWz_m2CoDsAl(f)Z&>^G*xJQx z3=a~X2wFSe&TG!!FV0nc*7VIEPqvSD_vKiu`B!;m?b|DX%nUyJb1E}8)_`k4S!d2E z3=BTqPnRA&XnN_gQwJME!mTfNwmx3Kd#hQJfnnLf5Vp*Pk_-)*)syzp1gHy{OXT&jivghqINx(F0s9P{M+tjp4;5n84_$DmEia4 zb)MHf`je`6y#FW1z|igvZo=}ZGrpC<9W_sHhgZc z-6y^<@AI9ryPmz<|9#f-`-atDYux5$|K51JU()Q@isD@Rx(kMjr?4?H$cPH-zrC?q z^z7@*)RGIfeZPd#_7|W2v@n~g=v52@!*%J~_hkidhacF!-i+TW|8s>t2NOe&--NU! zoBF0~WMJsq6w8{qdPeixtDkSKf4-;o&R&ko|7J2UtP{V^@-pxn?=Hz*VnlCKo@9?^8~1a4(V<)GBC6s`*dlMC}^xx5i!;o kqHJX<$G~vl#lQN=y!(!L&z|{!fq{X+)78&qol`;+0FL5ly#N3J literal 0 HcmV?d00001 diff --git a/blog/content/second-edition/posts/09-paging/segmentation-fragmentation-compacted.svg b/blog/content/second-edition/posts/09-paging-introduction/segmentation-fragmentation-compacted.svg similarity index 100% rename from blog/content/second-edition/posts/09-paging/segmentation-fragmentation-compacted.svg rename to blog/content/second-edition/posts/09-paging-introduction/segmentation-fragmentation-compacted.svg diff --git a/blog/content/second-edition/posts/09-paging/segmentation-fragmentation.svg b/blog/content/second-edition/posts/09-paging-introduction/segmentation-fragmentation.svg similarity index 100% rename from blog/content/second-edition/posts/09-paging/segmentation-fragmentation.svg rename to blog/content/second-edition/posts/09-paging-introduction/segmentation-fragmentation.svg diff --git a/blog/content/second-edition/posts/09-paging/segmentation-same-program-twice.svg b/blog/content/second-edition/posts/09-paging-introduction/segmentation-same-program-twice.svg similarity index 100% rename from blog/content/second-edition/posts/09-paging/segmentation-same-program-twice.svg rename to blog/content/second-edition/posts/09-paging-introduction/segmentation-same-program-twice.svg diff --git a/blog/content/second-edition/posts/09-paging/single-level-page-table.svg b/blog/content/second-edition/posts/09-paging-introduction/single-level-page-table.svg similarity index 100% rename from blog/content/second-edition/posts/09-paging/single-level-page-table.svg rename to blog/content/second-edition/posts/09-paging-introduction/single-level-page-table.svg diff --git a/blog/content/second-edition/posts/09-paging/x86_64-page-table-translation-addresses.svg b/blog/content/second-edition/posts/09-paging-introduction/x86_64-page-table-translation-addresses.svg similarity index 100% rename from blog/content/second-edition/posts/09-paging/x86_64-page-table-translation-addresses.svg rename to blog/content/second-edition/posts/09-paging-introduction/x86_64-page-table-translation-addresses.svg diff --git a/blog/content/second-edition/posts/09-paging-introduction/x86_64-page-table-translation-large.svg b/blog/content/second-edition/posts/09-paging-introduction/x86_64-page-table-translation-large.svg new file mode 100644 index 00000000..719fa4aa --- /dev/null +++ b/blog/content/second-edition/posts/09-paging-introduction/x86_64-page-table-translation-large.svg @@ -0,0 +1,2 @@ + +
Physical Memory
Physical Memory
0KiB
[Not supported by viewer]
IndexFrameFlags
0-
-
116KiBr/w


[Not supported by viewer]
Level 4 Page Table
Level 4 Page Table
4KiB
[Not supported by viewer]
IndexFrameFlags
024KiB
r/w



[Not supported by viewer]
Level 3 Page Table
Level 3 Page Table
16KiB
<div>16KiB</div>
24KiB
<div>24KiB</div>
8KiB
[Not supported by viewer]
IndexFrameFlags



511
24KiB
r/w
[Not supported by viewer]
Level 2 Page Table
Level 2 Page Table
Level 1 Page Table
Level 1 Page Table
32KiB
<div>32KiB</div>
IndexFrameFlags
036KiB
r/w



127
12KiBr


[Not supported by viewer]
4KiB
4KiB
CR3 Register
CR3 Register
\ No newline at end of file diff --git a/blog/content/second-edition/posts/09-paging-introduction/x86_64-page-table-translation-steps.svg b/blog/content/second-edition/posts/09-paging-introduction/x86_64-page-table-translation-steps.svg new file mode 100644 index 00000000..6c13b322 --- /dev/null +++ b/blog/content/second-edition/posts/09-paging-introduction/x86_64-page-table-translation-steps.svg @@ -0,0 +1,2 @@ + +
Physical Memory
Physical Memory
0KiB
[Not supported by viewer]
IndexFrameFlags
0-
-
116KiBr/w


[Not supported by viewer]
Level 4 Page Table
Level 4 Page Table
4KiB
[Not supported by viewer]
IndexFrameFlags
024KiB
r/w



[Not supported by viewer]
Level 3 Page Table
Level 3 Page Table
16KiB
<div>16KiB</div>
24KiB
<div>24KiB</div>
8KiB
[Not supported by viewer]
IndexFrameFlags



511
24KiB
r/w
[Not supported by viewer]
Level 2 Page Table
Level 2 Page Table
Level 1 Page Table
Level 1 Page Table
32KiB
<div>32KiB</div>
IndexFrameFlags
036KiB
r/w



127
12KiBr


[Not supported by viewer]
4KiB
4KiB
CR3 Register
CR3 Register
Step 1
Step 1
Step 0
Step 0
Step 2
Step 2
Step 3
Step 3
Step 4
Step 4
\ No newline at end of file diff --git a/blog/content/second-edition/posts/09-paging/x86_64-page-table-translation.svg b/blog/content/second-edition/posts/09-paging-introduction/x86_64-page-table-translation.svg similarity index 100% rename from blog/content/second-edition/posts/09-paging/x86_64-page-table-translation.svg rename to blog/content/second-edition/posts/09-paging-introduction/x86_64-page-table-translation.svg diff --git a/blog/content/second-edition/posts/09-paging/x86_64-table-indices-from-address.svg b/blog/content/second-edition/posts/09-paging-introduction/x86_64-table-indices-from-address.svg similarity index 100% rename from blog/content/second-edition/posts/09-paging/x86_64-table-indices-from-address.svg rename to blog/content/second-edition/posts/09-paging-introduction/x86_64-table-indices-from-address.svg