Move images next to their corresponding posts
@@ -241,7 +241,7 @@ It is important that the function is [diverging], i.e. it must never return. The
|
||||
|
||||
[diverging]: https://doc.rust-lang.org/book/functions.html#diverging-functions
|
||||
|
||||

|
||||

|
||||
|
||||
If our handler function returned normally, it would try to pop the return address from the stack. But it might get some completely different value then. For example, the CPU pushes an error code for some exceptions. Bad things would happen if we interpreted this error code as return address and jumped to it. Therefore interrupt handler functions must diverge[^fn-must-diverge].
|
||||
|
||||
@@ -550,7 +550,7 @@ pub extern "C" fn rust_main(...) {
|
||||
|
||||
It works! We see a `EXCEPTION: DIVIDE BY ZERO` message at the bottom of our screen:
|
||||
|
||||

|
||||

|
||||
|
||||
## What's next?
|
||||
We've successfully caught our first exception! However, our `EXCEPTION: DIVIDE BY ZERO` message doesn't contain much information about the cause of the exception. The next post improves the situation by printing i.a. the current stack pointer and address of the causing instruction. We will also explore other exceptions such as page faults, for which the CPU pushes an _error code_ on the stack.
|
||||
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@@ -24,7 +24,7 @@ An exception signals that something is wrong with the currently-executed instruc
|
||||
|
||||
This routine involves reading the interrupt descriptor table and invoking the registered handler function. But first, the CPU pushes various information onto the stack, which describe the current state and provide information about the cause of the exception:
|
||||
|
||||

|
||||

|
||||
|
||||
The pushed information contain the instruction and stack pointer, the current CPU flags, and (for some exceptions) an error code, which contains further information about the cause of the exception. Let's look at the fields in detail:
|
||||
|
||||
@@ -86,7 +86,7 @@ So the inline assembly loads the stack pointer value to `stack_frame` at the ver
|
||||
### Testing it
|
||||
Let's try it by executing `make run`:
|
||||
|
||||

|
||||

|
||||
|
||||
Those `ExceptionStackFrame` values look very wrong. The instruction pointer definitely shouldn't be 1 and the code segment should be `0x8` instead of some big number. So what's going on here?
|
||||
|
||||
@@ -255,7 +255,7 @@ lazy_static! {
|
||||
|
||||
Now we see a correct exception stack frame when we execute `make run`:
|
||||
|
||||

|
||||

|
||||
|
||||
## Testing on real Hardware
|
||||
Virtual machines such as QEMU are very convenient to quickly test our kernel. However, they might behave a bit different than real hardware in some situations. So we should test our kernel on real hardware, too.
|
||||
@@ -602,7 +602,7 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) {
|
||||
|
||||
We get the following output:
|
||||
|
||||

|
||||

|
||||
|
||||
### The Page Fault Error Code
|
||||
“Error code 2” is not really an useful error message. Let's improve this by creating a `PageFaultErrorCode` type:
|
||||
@@ -647,7 +647,7 @@ The `from_bits` function tries to convert the `u64` into a `PageFaultErrorCode`.
|
||||
|
||||
Now we get a useful error message when a page fault occurs, which allows us to debug it more easily:
|
||||
|
||||

|
||||

|
||||
|
||||
As expected, the page fault was caused by write to `0xdeadbeaf`. The `PROTECTION_VIOLATION` flag is not set, so the accessed page was not present.
|
||||
|
||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.3 KiB |
@@ -101,20 +101,20 @@ pub extern "C" fn rust_main(...) {
|
||||
|
||||
When we execute `make run`, we see the following:
|
||||
|
||||

|
||||

|
||||
|
||||
It works! Now we “just” need to return from the breakpoint handler somehow so that we see the `It did not crash` message again.
|
||||
|
||||
## Returning from Exceptions
|
||||
So how do we return from exceptions? To make it easier, we look at a normal function return first:
|
||||
|
||||

|
||||

|
||||
|
||||
When calling a function, the `call` instruction pushes the return address on the stack. When the called function is finished, it can return to the parent function through the `ret` instruction, which pops the return address from the stack and then jumps to it.
|
||||
|
||||
The exception stack frame, in contrast, looks a bit different:
|
||||
|
||||

|
||||

|
||||
|
||||
Instead of pushing a return address, the CPU pushes the stack and instruction pointers (with their segment descriptors), the RFLAGS register, and an optional error code. It also aligns the stack pointer to a 16 byte boundary before pushing values.
|
||||
|
||||
@@ -204,7 +204,7 @@ Note that we also removed the `loop {}` at the end of our `breakpoint_handler` s
|
||||
### Testing
|
||||
Let's try our new `iretq` logic:
|
||||
|
||||

|
||||

|
||||
|
||||
Instead of the expected _“It did not crash”_ message after the breakpoint exception, we get a page fault. The strange thing is that our kernel tried to access address `0x1`, which should never happen. So it seems like we messed up something important.
|
||||
|
||||
@@ -414,7 +414,7 @@ Note that we no longer need to manually align the stack pointer, because we're p
|
||||
### Testing it again
|
||||
Let's test it again with our corrected `handler!` macro:
|
||||
|
||||

|
||||

|
||||
|
||||
The page fault is gone and we see the _“It did not crash”_ message again!
|
||||
|
||||
@@ -436,7 +436,7 @@ However, auto-vectorization causes a problem for us: Most of the multimedia regi
|
||||
|
||||
We don't use any multimedia registers explicitly, but the Rust compiler might auto-vectorize our code (including the exception handlers). Thus we could silently clobber the multimedia registers, which leads to the same problems as above:
|
||||
|
||||

|
||||

|
||||
|
||||
This example shows a program that is using the first three multimedia registers (`mm0` to `mm2`). At some point, an exception occurs and control is transfered to the exception handler. The exception handler uses `mm1` for its own data and thus overwrites the previous value. When the exception is resolved, the CPU continues the interrupted program again. However, the program is now corrupt since it relies on the original `mm1` value.
|
||||
|
||||
@@ -691,7 +691,7 @@ The [red zone] is an optimization of the [System V ABI] that allows functions to
|
||||
|
||||
[red zone]: http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64#the-red-zone
|
||||
|
||||

|
||||

|
||||
|
||||
The image shows the stack frame of a function with `n` local variables. On function entry, the stack pointer is adjusted to make room on the stack for the local variables.
|
||||
|
||||
@@ -699,7 +699,7 @@ The red zone is defined as the 128 bytes below the adjusted stack pointer. The f
|
||||
|
||||
However, this optimization leads to huge problems with exceptions. Let's assume that an exception occurs while a function uses the red zone:
|
||||
|
||||

|
||||

|
||||
|
||||
The CPU and the exception handler overwrite the data in red zone. But this data is still needed by the interrupted function. So the function won't work correctly anymore when we return from the exception handler. It might fail or cause another exception, but it could also lead to strange bugs that [take weeks to debug].
|
||||
|
||||
@@ -878,7 +878,7 @@ The error code should still be `CAUSED_BY_WRITE` and the exception stack frame v
|
||||
#### Returning from Page Faults
|
||||
Let's see what happens if we comment out the trailing `loop` in our page fault handler:
|
||||
|
||||

|
||||

|
||||
|
||||
We see that the same error message is printed over and over again. Here is what happens:
|
||||
|
||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
@@ -68,7 +68,7 @@ After connecting to QEMU, you can use various gdb commands to control execution
|
||||
- `print` or `p`: Prints the value of a variable. You can use Cs `*` and `&` operators. To print in hexadecimal, use `p/x`.
|
||||
- `tui enable`: Enables the text user interface, which provides a graphical interface (see below). To disable it again, run `tui disable`.
|
||||
|
||||

|
||||

|
||||
|
||||
Of course there are many more commands. Feel free to send a PR if you think this list is missing something important. For a more complete GDB overview, check out [Beej's Quick Guide][bggdb] or the [website for Harvard's CS161 course][CS161].
|
||||
|
||||
@@ -232,7 +232,7 @@ Now it's time to boot our OS. We will use [QEMU]:
|
||||
```
|
||||
qemu-system-x86_64 -cdrom os.iso
|
||||
```
|
||||

|
||||

|
||||
|
||||
Notice the green `OK` in the upper left corner. If it does not work for you, take a look at the comment section.
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
@@ -215,7 +215,7 @@ As I don't like these names, I will call them P4, P3, P2, and P1 from now on.
|
||||
|
||||
Each page table contains 512 entries and one entry is 8 bytes, so they fit exactly in one page (`512*8 = 4096`). To translate a virtual address to a physical address the CPU[^hardware_lookup] will do the following[^virtual_physical_translation_source]:
|
||||
|
||||

|
||||

|
||||
|
||||
1. Get the address of the P4 table from the CR3 register
|
||||
2. Use bits 39-47 (9 bits) as an index into P4 (`2^9 = 512 = number of entries`)
|
||||
|
||||
@@ -151,7 +151,7 @@ The [red zone] is an optimization of the [System V ABI] that allows functions to
|
||||
[red zone]: http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64#the-red-zone
|
||||
[System V ABI]: http://wiki.osdev.org/System_V_ABI
|
||||
|
||||

|
||||

|
||||
|
||||
The image shows the stack frame of a function with `n` local variables. On function entry, the stack pointer is adjusted to make room on the stack for the local variables.
|
||||
|
||||
@@ -159,7 +159,7 @@ The red zone is defined as the 128 bytes below the adjusted stack pointer. The f
|
||||
|
||||
However, this optimization leads to huge problems with exceptions or hardware interrupts. Let's assume that an exception occurs while a function uses the red zone:
|
||||
|
||||

|
||||

|
||||
|
||||
The CPU and the exception handler overwrite the data in red zone. But this data is still needed by the interrupted function. So the function won't work correctly anymore when we return from the exception handler. This might lead to strange bugs that [take weeks to debug].
|
||||
|
||||
|
||||
92
blog/content/posts/03-set-up-rust/red-zone-overwrite.svg
Normal file
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
|
||||
<svg width="17cm" height="11cm" viewBox="-60 -21 340 212" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="90" y="65.9389">
|
||||
<tspan x="90" y="65.9389"></tspan>
|
||||
</text>
|
||||
<g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="204" y1="70" x2="176.236" y2="70"/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="185.118,65 175.118,70 185.118,75 "/>
|
||||
</g>
|
||||
<text font-size="7.90222" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="208" y="72.75">
|
||||
<tspan x="208" y="72.75">Old Stack Pointer</tspan>
|
||||
</text>
|
||||
<text font-size="7.90222" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="75" y="230">
|
||||
<tspan x="75" y="230"></tspan>
|
||||
</text>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="-20" y1="70" x2="-4" y2="70"/>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="-20" y1="190" x2="-4" y2="190"/>
|
||||
<g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="-12" y1="72.2361" x2="-12" y2="187.764"/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="-7,81.118 -12,71.118 -17,81.118 "/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="-17,178.882 -12,188.882 -7,178.882 "/>
|
||||
</g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="0" y1="-20" x2="0" y2="0"/>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="170" y1="-20" x2="170" y2="0"/>
|
||||
<g>
|
||||
<rect style="fill: #00ff00" x="0" y="0" width="170" height="20"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="0" width="170" height="20"/>
|
||||
</g>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="85" y="13.125">
|
||||
<tspan x="85" y="13.125">Return Address</tspan>
|
||||
</text>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="84" y="4">
|
||||
<tspan x="84" y="4"></tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #dddddd" x="0" y="20" width="170" height="20"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="20" width="170" height="20"/>
|
||||
</g>
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="85" y="33.125">
|
||||
<tspan x="85" y="33.125">Local Variable 1</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #cccccc" x="0" y="40" width="170" height="32"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x="0" y="40" width="170" height="32"/>
|
||||
</g>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="85" y="59.125">
|
||||
<tspan x="85" y="59.125">Local Variables 2..n</tspan>
|
||||
</text>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="0" y1="40" x2="170" y2="40"/>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="0" y1="72" x2="120" y2="72"/>
|
||||
<g>
|
||||
<rect style="fill: #ff3333" x="0" y="70" width="170" height="120"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="70" width="170" height="120"/>
|
||||
</g>
|
||||
<text font-size="9.03111" style="fill: #ffffff;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="40" y="179.125">
|
||||
<tspan x="40" y="179.125">Red Zone</tspan>
|
||||
</text>
|
||||
<text font-size="7.9021" style="fill: #000000;text-anchor:end;font-family:sans-serif;font-style:normal;font-weight:normal" x="-20" y="132.75">
|
||||
<tspan x="-20" y="132.75">128 bytes</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #ffc200" x="30" y="70" width="140" height="30"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="30" y="70" width="140" height="30"/>
|
||||
</g>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="100" y="88.125">
|
||||
<tspan x="100" y="88.125">Exception Stack Frame</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #ffe000" x="30" y="100" width="140" height="30"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="30" y="100" width="140" height="30"/>
|
||||
</g>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="100" y="118.125">
|
||||
<tspan x="100" y="118.125">Register Backup</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #c6db97" x="30" y="130" width="140" height="30"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="30" y="130" width="140" height="30"/>
|
||||
</g>
|
||||
<text font-size="8.46654" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="100" y="147.925">
|
||||
<tspan x="100" y="147.925">Handler Function Stack Frame</tspan>
|
||||
</text>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #ff3333" x1="30" y1="70" x2="30" y2="160"/>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #ff3333" x1="30" y1="160" x2="170" y2="160"/>
|
||||
<g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="204" y1="160" x2="176.236" y2="160"/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="185.118,155 175.118,160 185.118,165 "/>
|
||||
</g>
|
||||
<text font-size="7.90222" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="208" y="162.635">
|
||||
<tspan x="208" y="162.635">New Stack Pointer</tspan>
|
||||
</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.2 KiB |
62
blog/content/posts/03-set-up-rust/red-zone.svg
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
|
||||
<svg width="14cm" height="9cm" viewBox="-60 -21 270 172" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="90" y="65.9389">
|
||||
<tspan x="90" y="65.9389"></tspan>
|
||||
</text>
|
||||
<g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="154" y1="70" x2="126.236" y2="70"/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="135.118,65 125.118,70 135.118,75 "/>
|
||||
</g>
|
||||
<text font-size="7.90222" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="158" y="72.75">
|
||||
<tspan x="158" y="72.75">Stack Pointer</tspan>
|
||||
</text>
|
||||
<text font-size="7.90222" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="75" y="230">
|
||||
<tspan x="75" y="230"></tspan>
|
||||
</text>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="-20" y1="70" x2="-4" y2="70"/>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="-20" y1="150" x2="-4" y2="150"/>
|
||||
<g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="-12" y1="72.2361" x2="-12" y2="147.764"/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="-7,81.118 -12,71.118 -17,81.118 "/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="-17,138.882 -12,148.882 -7,138.882 "/>
|
||||
</g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="0" y1="-20" x2="0" y2="0"/>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="120" y1="-20" x2="120" y2="0"/>
|
||||
<g>
|
||||
<rect style="fill: #00ff00" x="0" y="0" width="120" height="20"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="0" width="120" height="20"/>
|
||||
</g>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="60" y="13.125">
|
||||
<tspan x="60" y="13.125">Return Address</tspan>
|
||||
</text>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="84" y="4">
|
||||
<tspan x="84" y="4"></tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #dddddd" x="0" y="20" width="120" height="20"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="20" width="120" height="20"/>
|
||||
</g>
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="60" y="33.125">
|
||||
<tspan x="60" y="33.125">Local Variable 1</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #cccccc" x="0" y="40" width="120" height="32"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x="0" y="40" width="120" height="32"/>
|
||||
</g>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="60" y="59.125">
|
||||
<tspan x="60" y="59.125">Local Variables 2..n</tspan>
|
||||
</text>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="0" y1="40" x2="120" y2="40"/>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="0" y1="72" x2="120" y2="72"/>
|
||||
<g>
|
||||
<rect style="fill: #ff3333" x="0" y="70" width="120" height="80"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="70" width="120" height="80"/>
|
||||
</g>
|
||||
<text font-size="9.03111" style="fill: #ffffff;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="60" y="113.125">
|
||||
<tspan x="60" y="113.125">Red Zone</tspan>
|
||||
</text>
|
||||
<text font-size="7.9021" style="fill: #000000;text-anchor:end;font-family:sans-serif;font-style:normal;font-weight:normal" x="-20" y="112.75">
|
||||
<tspan x="-20" y="112.75">128 bytes</tspan>
|
||||
</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
@@ -259,7 +259,7 @@ It just creates a new Writer that points to the VGA buffer at `0xb8000`. Then it
|
||||
|
||||
[byte character]: https://doc.rust-lang.org/reference.html#characters-and-strings
|
||||
|
||||

|
||||

|
||||
|
||||
### Volatile
|
||||
We just saw that our `H` was printed correctly. However, it might not work with future Rust compilers that optimize more aggressively.
|
||||
@@ -583,7 +583,7 @@ Since we imported the macros at crate level, they are available in all modules a
|
||||
|
||||
As expected, we now see a _“Hello World!”_ on a cleared screen:
|
||||
|
||||

|
||||

|
||||
|
||||
### Deadlocks
|
||||
Whenever we use locks, we must be careful to not accidentally introduce _deadlocks_. A [deadlock] occurs when a thread/program waits for a lock that will never be released. Normally, this happens when multiple threads access multiple locks. For example, when thread A holds lock 1 and tries to acquire lock 2 and -- at the same time -- thread B holds lock 2 and tries to acquire lock 1.
|
||||
@@ -633,7 +633,7 @@ Now the macro only evaluates the arguments (through `format_args!`) and passes t
|
||||
|
||||
Thus, we fixed the deadlock:
|
||||
|
||||

|
||||

|
||||
|
||||
We see that both “inner” and “outer” are printed.
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.5 KiB |
@@ -177,7 +177,7 @@ These lines are taken from the default linker script of `ld`, which can be obtai
|
||||
|
||||
Now there are only 12 sections left and we get a much more useful output:
|
||||
|
||||

|
||||

|
||||
|
||||
If you like, you can compare this output to the `objdump -h build/kernel-x86_64.bin` output. You will see that the start addresses and sizes match exactly for each section. The sections with flags `0x0` are mostly debug sections, so they don't need to be loaded. And the last few sections of the QEMU output aren't in the `objdump` output because they are special sections such as string tables.
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
929
blog/content/posts/06-page-tables/X86_Paging_64bit.svg
Normal file
@@ -0,0 +1,929 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="7.2973523in"
|
||||
height="4.1279249in"
|
||||
viewBox="-2141 2141 8777.1352 4929.2808"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="X86_Paging_64bit.svg">
|
||||
<metadata
|
||||
id="metadata370">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs368" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1080"
|
||||
inkscape:window-height="1868"
|
||||
id="namedview366"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="1.4404005"
|
||||
inkscape:cx="383.13253"
|
||||
inkscape:cy="73.778068"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g4" />
|
||||
<g
|
||||
style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="g4"
|
||||
transform="translate(-2845,-286.64442)">
|
||||
<rect
|
||||
x="8503"
|
||||
y="4015"
|
||||
width="708"
|
||||
height="3307"
|
||||
rx="0"
|
||||
style="fill:#dfdfdf"
|
||||
id="rect8" />
|
||||
<polyline
|
||||
points="3365,2598 3365,3070"
|
||||
id="polyline10" />
|
||||
<polyline
|
||||
points="3189,2598 3189,3070"
|
||||
id="polyline12" />
|
||||
<polyline
|
||||
points="3012,2598 3012,3070"
|
||||
id="polyline14" />
|
||||
<polyline
|
||||
points="2834,2598 2834,3070"
|
||||
id="polyline16" />
|
||||
<polyline
|
||||
points="2657,2598 2657,3070"
|
||||
id="polyline18" />
|
||||
<polyline
|
||||
points="2480,2598 2480,3070"
|
||||
id="polyline20" />
|
||||
<polyline
|
||||
points="2303,2598 2303,3070"
|
||||
id="polyline22" />
|
||||
<polyline
|
||||
points="2125,2456 2125,3070"
|
||||
id="polyline24" />
|
||||
<polyline
|
||||
points="1948,2598 1948,3070"
|
||||
id="polyline26" />
|
||||
<polyline
|
||||
points="1772,2598 1772,3070"
|
||||
id="polyline28" />
|
||||
<polyline
|
||||
points="1594,2598 1594,3070"
|
||||
id="polyline30" />
|
||||
<polyline
|
||||
points="1417,2598 1417,3070"
|
||||
id="polyline32" />
|
||||
<polyline
|
||||
points="1239,2598 1239,3070"
|
||||
id="polyline34" />
|
||||
<polyline
|
||||
points="1063,2598 1063,3070"
|
||||
id="polyline36" />
|
||||
<polyline
|
||||
points="886,2598 886,3070"
|
||||
id="polyline38" />
|
||||
<polyline
|
||||
points="708,2456 708,3070"
|
||||
id="polyline40" />
|
||||
<polyline
|
||||
points="3543,2456 3543,3070"
|
||||
id="polyline74" />
|
||||
<polyline
|
||||
points="-2125,2598 3543,2598"
|
||||
id="polyline76"
|
||||
transform="matrix(0.49978943,0,0,1,1772.2461,0)" />
|
||||
<polyline
|
||||
points="3543,3070 -1948,3070 -2125,3070"
|
||||
id="polyline78"
|
||||
transform="matrix(0.49786923,0,0,1,1779.0493,0)" />
|
||||
<polyline
|
||||
points="9035,2598 9035,3070"
|
||||
id="polyline80" />
|
||||
<polyline
|
||||
points="8858,2598 8858,3070"
|
||||
id="polyline82" />
|
||||
<polyline
|
||||
points="8681,2598 8681,3070"
|
||||
id="polyline84" />
|
||||
<polyline
|
||||
points="8503,2598 8503,3070"
|
||||
id="polyline86" />
|
||||
<polyline
|
||||
points="8326,2598 8326,3070"
|
||||
id="polyline88" />
|
||||
<polyline
|
||||
points="8150,2598 8150,3070"
|
||||
id="polyline90" />
|
||||
<polyline
|
||||
points="7972,2598 7972,3070"
|
||||
id="polyline92" />
|
||||
<polyline
|
||||
points="7795,2456 7795,3070"
|
||||
id="polyline94" />
|
||||
<polyline
|
||||
points="7617,2598 7617,3070"
|
||||
id="polyline96" />
|
||||
<polyline
|
||||
points="7441,2598 7441,3070"
|
||||
id="polyline98" />
|
||||
<polyline
|
||||
points="7264,2598 7264,3070"
|
||||
id="polyline100" />
|
||||
<polyline
|
||||
points="7086,2598 7086,3070"
|
||||
id="polyline102" />
|
||||
<polyline
|
||||
points="6909,2598 6909,3070"
|
||||
id="polyline104" />
|
||||
<polyline
|
||||
points="6732,2598 6732,3070"
|
||||
id="polyline106" />
|
||||
<polyline
|
||||
points="6555,2598 6555,3070"
|
||||
id="polyline108" />
|
||||
<polyline
|
||||
points="6377,2456 6377,3070"
|
||||
id="polyline110" />
|
||||
<polyline
|
||||
points="6200,2598 6200,3070"
|
||||
id="polyline112" />
|
||||
<polyline
|
||||
points="6024,2598 6024,3070"
|
||||
id="polyline114" />
|
||||
<polyline
|
||||
points="5846,2598 5846,3070"
|
||||
id="polyline116" />
|
||||
<polyline
|
||||
points="5669,2598 5669,3070"
|
||||
id="polyline118" />
|
||||
<polyline
|
||||
points="5491,2598 5491,3070"
|
||||
id="polyline120" />
|
||||
<polyline
|
||||
points="5315,2598 5315,3070"
|
||||
id="polyline122" />
|
||||
<polyline
|
||||
points="5138,2598 5138,3070"
|
||||
id="polyline124" />
|
||||
<polyline
|
||||
points="4960,2409 4960,3070"
|
||||
id="polyline126" />
|
||||
<polyline
|
||||
points="4783,2598 4783,3070"
|
||||
id="polyline128" />
|
||||
<polyline
|
||||
points="4606,2598 4606,3070"
|
||||
id="polyline130" />
|
||||
<polyline
|
||||
points="4429,2598 4429,3070"
|
||||
id="polyline132" />
|
||||
<polyline
|
||||
points="4251,2598 4251,3070"
|
||||
id="polyline134" />
|
||||
<polyline
|
||||
points="4074,2598 4074,3070"
|
||||
id="polyline136" />
|
||||
<polyline
|
||||
points="3898,2598 3898,3070"
|
||||
id="polyline138" />
|
||||
<polyline
|
||||
points="3720,2598 3720,3070"
|
||||
id="polyline140" />
|
||||
<polyline
|
||||
points="9212,2456 9212,3070"
|
||||
id="polyline142" />
|
||||
<polyline
|
||||
points="3543,2598 9212,2598"
|
||||
id="polyline144" />
|
||||
<polyline
|
||||
points="9212,3070 3720,3070 0,3070"
|
||||
id="polyline146"
|
||||
transform="matrix(0.92335242,0,0,1,706.07747,0)" />
|
||||
<rect
|
||||
x="5102"
|
||||
y="4488"
|
||||
width="1181"
|
||||
height="2362"
|
||||
rx="0"
|
||||
style="fill:#dfdfdf"
|
||||
id="rect148" />
|
||||
<rect
|
||||
x="3307"
|
||||
y="4251"
|
||||
width="1181"
|
||||
height="2362"
|
||||
rx="0"
|
||||
style="fill:#dfdfdf"
|
||||
id="rect150" />
|
||||
<rect
|
||||
x="6897"
|
||||
y="4724"
|
||||
width="1181"
|
||||
height="2362"
|
||||
rx="0"
|
||||
style="fill:#dfdfdf"
|
||||
id="rect152" />
|
||||
<rect
|
||||
x="1511"
|
||||
y="4015"
|
||||
width="1181"
|
||||
height="2362"
|
||||
rx="0"
|
||||
style="fill:#dfdfdf"
|
||||
id="rect154" />
|
||||
<rect
|
||||
x="1417"
|
||||
y="6850"
|
||||
width="1417"
|
||||
height="472"
|
||||
rx="0"
|
||||
id="rect156" />
|
||||
<rect
|
||||
x="8503"
|
||||
y="5433"
|
||||
width="708"
|
||||
height="236"
|
||||
rx="0"
|
||||
style="fill:#dfdfdf"
|
||||
id="rect158" />
|
||||
<rect
|
||||
x="5102"
|
||||
y="5669"
|
||||
width="1181"
|
||||
height="472"
|
||||
rx="0"
|
||||
id="rect160" />
|
||||
<rect
|
||||
x="3307"
|
||||
y="5433"
|
||||
width="1181"
|
||||
height="472"
|
||||
rx="0"
|
||||
id="rect162" />
|
||||
<rect
|
||||
x="6897"
|
||||
y="5905"
|
||||
width="1181"
|
||||
height="472"
|
||||
rx="0"
|
||||
id="rect164" />
|
||||
<rect
|
||||
x="1511"
|
||||
y="5196"
|
||||
width="1181"
|
||||
height="472"
|
||||
rx="0"
|
||||
id="rect166" />
|
||||
<circle
|
||||
cx="6141"
|
||||
cy="5905"
|
||||
r="47"
|
||||
style="fill:#0000ff;stroke:#0000ff;stroke-width:32"
|
||||
id="circle170" />
|
||||
<circle
|
||||
cx="4346"
|
||||
cy="5669"
|
||||
r="47"
|
||||
style="fill:#0000ff;stroke:#0000ff;stroke-width:32"
|
||||
id="circle172" />
|
||||
<circle
|
||||
cx="7937"
|
||||
cy="6141"
|
||||
r="47"
|
||||
style="fill:#0000ff;stroke:#0000ff;stroke-width:32"
|
||||
id="circle174" />
|
||||
<circle
|
||||
cx="2551"
|
||||
cy="5433"
|
||||
r="47"
|
||||
style="fill:#0000ff;stroke:#0000ff;stroke-width:32"
|
||||
id="circle176" />
|
||||
<polyline
|
||||
points="3118,3590 2834,3779"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline178" />
|
||||
<polyline
|
||||
points="1322,3590 1039,3779"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline180" />
|
||||
<polyline
|
||||
points="4913,3590 4629,3779"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline184" />
|
||||
<polyline
|
||||
points="6519,3590 6236,3779"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline186" />
|
||||
<polyline
|
||||
points="8314,3590 8031,3779"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline188" />
|
||||
<circle
|
||||
cx="1653"
|
||||
cy="7086"
|
||||
r="47"
|
||||
style="fill:#0000ff;stroke:#0000ff;stroke-width:32"
|
||||
id="circle190" />
|
||||
<polyline
|
||||
points="1653,7086 1181,7086 1181,6377 1354,6377"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline192" />
|
||||
<polygon
|
||||
points="1512,6377 1355,6330 1355,6425 1355,6425 "
|
||||
style="fill:#0000ff;stroke:#0000ff"
|
||||
id="polygon194" />
|
||||
<polyline
|
||||
points="7937,6141 8173,6141 8173,7322 8346,7322"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline196" />
|
||||
<polygon
|
||||
points="8504,7322 8347,7275 8347,7370 8347,7370 "
|
||||
style="fill:#0000ff;stroke:#0000ff"
|
||||
id="polygon198" />
|
||||
<polyline
|
||||
points="8173,3543 8173,5669 8346,5669"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline200" />
|
||||
<polygon
|
||||
points="8504,5669 8347,5622 8347,5716 8347,5716 "
|
||||
style="fill:#0000ff;stroke:#0000ff"
|
||||
id="polygon202" />
|
||||
<polyline
|
||||
points="9212,3070 9070,3307 8314,3307 8173,3543 8031,3307 7228,3307 7086,3070"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline204" />
|
||||
<polyline
|
||||
points="3898,3070 4015,3307 4629,3307 4771,3543 4913,3307 5385,3307 5491,3070"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline206" />
|
||||
<polyline
|
||||
points="5491,3070 5622,3307 6236,3307 6377,3543 6519,3307 6909,3307 7086,3070"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline208" />
|
||||
<polyline
|
||||
points="2303,3070 2409,3307 2834,3307 2976,3543 3118,3307 3779,3307 3898,3070"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline210" />
|
||||
<polyline
|
||||
points="708,3070 850,3307 1039,3307 1181,3543 1322,3307 2173,3307 2303,3070"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline212" />
|
||||
<polyline
|
||||
points="4771,3543 4771,6141 4944,6141"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline214" />
|
||||
<polygon
|
||||
points="5103,6141 4945,6094 4945,6188 4945,6188 "
|
||||
style="fill:#0000ff;stroke:#0000ff"
|
||||
id="polygon216" />
|
||||
<polyline
|
||||
points="6377,3543 6377,4015 6519,4157 6519,6377 6740,6377"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline218" />
|
||||
<polygon
|
||||
points="6898,6377 6741,6330 6741,6425 6741,6425 "
|
||||
style="fill:#0000ff;stroke:#0000ff"
|
||||
id="polygon220" />
|
||||
<polyline
|
||||
points="6141,5905 6377,5905 6377,7086 6740,7086"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline222" />
|
||||
<polygon
|
||||
points="6898,7086 6741,7039 6741,7133 6741,7133 "
|
||||
style="fill:#0000ff;stroke:#0000ff"
|
||||
id="polygon224" />
|
||||
<polyline
|
||||
points="4346,5669 4629,5669 4629,6850 4944,6850"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline226" />
|
||||
<polygon
|
||||
points="5103,6850 4945,6803 4945,6897 4945,6897 "
|
||||
style="fill:#0000ff;stroke:#0000ff"
|
||||
id="polygon228" />
|
||||
<polyline
|
||||
points="2598,5433 2834,5433 2834,6614 3149,6614"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline230" />
|
||||
<polygon
|
||||
points="3308,6614 3150,6566 3150,6661 3150,6661 "
|
||||
style="fill:#0000ff;stroke:#0000ff"
|
||||
id="polygon232" />
|
||||
<polyline
|
||||
points="1181,3543 1181,5669 1401,5669"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline234" />
|
||||
<polygon
|
||||
points="1560,5669 1402,5622 1402,5716 1402,5716 "
|
||||
style="fill:#0000ff;stroke:#0000ff"
|
||||
id="polygon236" />
|
||||
<polyline
|
||||
points="2976,3543 2976,5905 3149,5905"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline238" />
|
||||
<polygon
|
||||
points="3308,5905 3150,5858 3150,5952 3150,5952 "
|
||||
style="fill:#0000ff;stroke:#0000ff"
|
||||
id="polygon240" />
|
||||
<g
|
||||
style="fill:#000000;stroke-width:0"
|
||||
id="g242">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2281.8145"
|
||||
y="7165"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text244"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle">CR3 register</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3507"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text246"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end">32</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2161"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text248"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start">39</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2090"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text250"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end">40</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="744"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text252"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start">47</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="672"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text254"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="-672"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text256"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="-744"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text258"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="-2090"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text260"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9176"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text262"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end">0</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7759"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text264"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end">8</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="6342"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text266"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end">16</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4924"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text268"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end">24</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3579"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text270"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start">31</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="6413"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text272"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start">15</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7830"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text274"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start">7</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4996"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text276"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start">23</text>
|
||||
<g
|
||||
transform="matrix(0,-1,1,0,8976,4724)"
|
||||
id="g278">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="0"
|
||||
y="0"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="404"
|
||||
id="text280"
|
||||
style="font-style:normal;font-weight:normal;font-size:404px;font-family:Helvetica;text-anchor:middle">...</text>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,-1,1,0,8976,6614)"
|
||||
id="g282">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="0"
|
||||
y="0"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="404"
|
||||
id="text284"
|
||||
style="font-style:normal;font-weight:normal;font-size:404px;font-family:Helvetica;text-anchor:middle">...</text>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,-1,1,0,9448,5622)"
|
||||
id="g286">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="0"
|
||||
y="0"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text288"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle"><tspan
|
||||
style="font-size:200.46390561px"
|
||||
id="tspan3509">4K memory page</tspan></text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="-2125"
|
||||
y="2314"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text290"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5622"
|
||||
y="5958.457"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text292"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle"><tspan
|
||||
style="font-size:200.46391296px"
|
||||
id="tspan3497">P2 entry</tspan></text>
|
||||
<g
|
||||
transform="matrix(0,-1,1,0,5723,6614)"
|
||||
id="g296">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="0"
|
||||
y="0"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="404"
|
||||
id="text298"
|
||||
style="font-style:normal;font-weight:normal;font-size:404px;font-family:Helvetica;text-anchor:middle">...</text>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,-1,1,0,5723,5196)"
|
||||
id="g300">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="0"
|
||||
y="0"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="404"
|
||||
id="text302"
|
||||
style="font-style:normal;font-weight:normal;font-size:404px;font-family:Helvetica;text-anchor:middle">...</text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5692"
|
||||
y="4393"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text304"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle"><tspan
|
||||
style="font-size:200.46390561px"
|
||||
id="tspan3505">P2 table</tspan></text>
|
||||
<g
|
||||
transform="matrix(0,-1,1,0,3928,6377)"
|
||||
id="g306">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="0"
|
||||
y="0"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="404"
|
||||
id="text308"
|
||||
style="font-style:normal;font-weight:normal;font-size:404px;font-family:Helvetica;text-anchor:middle">...</text>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,-1,1,0,3928,4960)"
|
||||
id="g310">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="0"
|
||||
y="0"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="404"
|
||||
id="text312"
|
||||
style="font-style:normal;font-weight:normal;font-size:404px;font-family:Helvetica;text-anchor:middle">...</text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3826"
|
||||
y="5722.457"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text314"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle"><tspan
|
||||
style="font-size:200.46391296px"
|
||||
id="tspan3495">P3 entry</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3874"
|
||||
y="3968"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text318"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3874"
|
||||
y="4157"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text320"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle"><tspan
|
||||
style="font-size:200.46390561px"
|
||||
id="tspan3503">P3 table</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7417"
|
||||
y="6194.457"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text322"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle"><tspan
|
||||
style="font-size:200.46391296px"
|
||||
id="tspan3499">P1 entry </tspan></text>
|
||||
<g
|
||||
transform="matrix(0,-1,1,0,7519,6850)"
|
||||
id="g326">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="0"
|
||||
y="0"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="404"
|
||||
id="text328"
|
||||
style="font-style:normal;font-weight:normal;font-size:404px;font-family:Helvetica;text-anchor:middle">...</text>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,-1,1,0,7519,5433)"
|
||||
id="g330">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="0"
|
||||
y="0"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="404"
|
||||
id="text332"
|
||||
style="font-style:normal;font-weight:normal;font-size:404px;font-family:Helvetica;text-anchor:middle">...</text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7487"
|
||||
y="4629"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text334"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle"><tspan
|
||||
style="font-size:200.46390561px"
|
||||
id="tspan3507">P1 table</tspan></text>
|
||||
<g
|
||||
transform="matrix(0,-1,1,0,2133,6141)"
|
||||
id="g336">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="0"
|
||||
y="0"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="404"
|
||||
id="text338"
|
||||
style="font-style:normal;font-weight:normal;font-size:404px;font-family:Helvetica;text-anchor:middle">...</text>
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0,-1,1,0,2133,4724)"
|
||||
id="g340">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="0"
|
||||
y="0"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="404"
|
||||
id="text342"
|
||||
style="font-style:normal;font-weight:normal;font-size:404px;font-family:Helvetica;text-anchor:middle">...</text>
|
||||
</g>
|
||||
<text
|
||||
x="2004.2715"
|
||||
y="5486.457"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text344"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle">
|
||||
<tspan
|
||||
style="font-size:200.46390561px"
|
||||
id="tspan3493">P4 entry</tspan>
|
||||
</text>
|
||||
<text
|
||||
x="2031"
|
||||
y="5622"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text346"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle" />
|
||||
<text
|
||||
x="2078"
|
||||
y="3941.2715"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text348"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle">
|
||||
<tspan
|
||||
style="font-size:200.46391296px"
|
||||
id="tspan3501">P4 table</tspan>
|
||||
</text>
|
||||
<text
|
||||
x="3165"
|
||||
y="3732"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text350"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start;fill:#0000ff">9</text>
|
||||
<text
|
||||
x="1370"
|
||||
y="3732"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text352"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start;fill:#0000ff">9</text>
|
||||
<text
|
||||
x="1370"
|
||||
y="6708"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text354"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start;fill:#0000ff" />
|
||||
<text
|
||||
x="4960"
|
||||
y="3732"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text356"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start;fill:#0000ff">9</text>
|
||||
<text
|
||||
x="6566"
|
||||
y="3732"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text358"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start;fill:#0000ff">9</text>
|
||||
<text
|
||||
x="8362"
|
||||
y="3732"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text360"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start;fill:#0000ff">12</text>
|
||||
<text
|
||||
x="1181"
|
||||
y="7532.2715"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text364"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 27 KiB |
@@ -21,7 +21,7 @@ _Paging_ is a memory management scheme that separates virtual and physical memor
|
||||
|
||||
The x86 architecture uses a 4-level page table in 64-bit mode. A virtual address has the following structure:
|
||||
|
||||

|
||||

|
||||
|
||||
The bits 48–63 are so-called _sign extension_ bits and must be copies of bit 47. The following 36 bits define the page table indexes (9 bits per table) and the last 12 bits specify the offset in the 4KiB page.
|
||||
|
||||
@@ -29,7 +29,7 @@ Each table has 2^9 = 512 entries and each entry is 8 byte. Thus a page table fit
|
||||
|
||||
To translate an address, the CPU reads the P4 address from the CR3 register. Then it uses the indexes to walk the tables:
|
||||
|
||||

|
||||

|
||||
|
||||
The P4 entry points to a P3 table, where the next 9 bits of the address are used to select an entry. The P3 entry then points to a P2 table and the P2 entry points to a P1 table. The P1 entry, which is specified through bits 12–20, finally points to the physical frame.
|
||||
|
||||
@@ -233,19 +233,19 @@ We will solve the problem in another way using a trick called _recursive mapping
|
||||
### Recursive Mapping
|
||||
The trick is to map the P4 table recursively: The last entry doesn't point to a P3 table, but to the P4 table itself. We can use this entry to remove a translation level so that we land on a page table instead. For example, we can “loop” once to access a P1 table:
|
||||
|
||||

|
||||

|
||||
|
||||
By selecting the 511th P4 entry, which points points to the P4 table itself, the P4 table is used as the P3 table. Similarly, the P3 table is used as a P2 table and the P2 table is treated like a P1 table. Thus the P1 table becomes the target page and can be accessed through the offset.
|
||||
|
||||
It's also possible to access P2 tables by looping twice. And if we select the 511th entry three times, we can access and modify P3 tables:
|
||||
|
||||

|
||||

|
||||
|
||||
So we just need to specify the desired P3 table in the address through the P1 index. By choosing the 511th entry multiple times, we stay on the P4 table until the address's P1 index becomes the actual P4 index.
|
||||
|
||||
To access the P4 table itself, we loop once more and thus never leave the frame:
|
||||
|
||||

|
||||

|
||||
|
||||
So we can access and modify page tables of all levels by just setting one P4 entry once. Most work is done by the CPU, we just the recursive entry to remove one or more translation levels. It may seem a bit strange at first, but it's a clean and simple solution once you wrapped your head around it.
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
@@ -329,11 +329,11 @@ Recursive mapping works by mapping the last P4 entry to the P4 table itself. Thu
|
||||
|
||||
For example, accessing a P3 table requires lopping three times:
|
||||
|
||||

|
||||

|
||||
|
||||
We can use the same mechanism to access inactive tables. The trick is to change the recursive mapping of the active P4 table to point to the inactive P4 table:
|
||||
|
||||

|
||||

|
||||
|
||||
Now the inactive table can be accessed exactly as the active table, even the magic addresses are the same. This allows us to use the `ActivePageTable` interface and the existing mapping methods for inactive tables, too. Note that everything besides the recursive mapping continues to work exactly as before since we've never changed the active table in the CPU.
|
||||
|
||||
@@ -364,7 +364,7 @@ It overwrites the 511th P4 entry and points it to the inactive table frame. Then
|
||||
|
||||
Now that the recursive mapping points to the given inactive table, we execute the closure in the new context. The closure can call all active table methods such as `translate` or `map_to`. It could even call `with` again and chain another inactive table! Wait… that would not work:
|
||||
|
||||

|
||||

|
||||
|
||||
Here the closure called `with` again and thus changed the recursive mapping of the inactive table to point to a second inactive table. Now we want to modify the P1 of the _second_ inactive table, but instead we land on the P1 of the _first_ inactive table since we never follow the pointer to the second table. Only when modifying the P2, P3, or P4 table we really access the second inactive table. This inconsistency would break our mapping functions completely.
|
||||
|
||||
@@ -460,13 +460,13 @@ Why is it unsafe? Because reading the CR3 register leads to a CPU exception if t
|
||||
|
||||
Now that we have a backup of the original P4 frame, we need a way to restore it after the closure has run. So we need to somehow modify the 511th entry of the original P4 frame, which is still the active table in the CPU. But we can't access it because the recursive mapping now points to the inactive table:
|
||||
|
||||

|
||||

|
||||
|
||||
It's just not possible to access the active P4 entry in 4 steps, so we can't reach it through the 4-level page table.
|
||||
|
||||
We could try to overwrite the recursive mapping of the _inactive_ P4 table and point it back to the original P4 frame:
|
||||
|
||||

|
||||

|
||||
|
||||
Now we can reach the active P4 entry in 4 steps and could restore the original mapping in the active table. But this hack has a drawback: The inactive table is now invalid since it is no longer recursive mapped. We would need to fix it by using a temporary page again (as above).
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
@@ -0,0 +1,819 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="900.00409"
|
||||
height="530"
|
||||
viewBox="-2141 2141 12027.89 7032.1014"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="recursive_mapping_access_p3.svg">
|
||||
<metadata
|
||||
id="metadata370">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs368" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="998"
|
||||
id="namedview366"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="2.7755576e-17"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="236.56561"
|
||||
inkscape:cy="267.91265"
|
||||
inkscape:window-x="1080"
|
||||
inkscape:window-y="568"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g4"
|
||||
units="in" />
|
||||
<g
|
||||
style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="g4"
|
||||
transform="translate(-1087.0637,717.51407)">
|
||||
<polyline
|
||||
points="3365,2598 3365,3070"
|
||||
id="polyline10"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="3189,2598 3189,3070"
|
||||
id="polyline12"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="3012,2598 3012,3070"
|
||||
id="polyline14"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="2834,2598 2834,3070"
|
||||
id="polyline16"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="2657,2598 2657,3070"
|
||||
id="polyline18"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="2480,2598 2480,3070"
|
||||
id="polyline20"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="2303,2598 2303,3070"
|
||||
id="polyline22"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="2125,2456 2125,3070"
|
||||
id="polyline24"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="1948,2598 1948,3070"
|
||||
id="polyline26"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="1772,2598 1772,3070"
|
||||
id="polyline28"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="1594,2598 1594,3070"
|
||||
id="polyline30"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="1417,2598 1417,3070"
|
||||
id="polyline32"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="1239,2598 1239,3070"
|
||||
id="polyline34"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="1063,2598 1063,3070"
|
||||
id="polyline36"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="886,2598 886,3070"
|
||||
id="polyline38"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="708,2456 708,3070"
|
||||
id="polyline40"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="3543,2456 3543,3070"
|
||||
id="polyline74"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="-2125,2598 3543,2598"
|
||||
id="polyline76"
|
||||
transform="matrix(0.70622791,0,0,1.3955346,455.54989,-1956.6141)" />
|
||||
<polyline
|
||||
points="3543,3070 -1948,3070 -2125,3070"
|
||||
id="polyline78"
|
||||
transform="matrix(0.70351457,0,0,1.3955346,465.16321,-1956.6141)" />
|
||||
<polyline
|
||||
points="9035,2598 9035,3070"
|
||||
id="polyline80"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="8858,2598 8858,3070"
|
||||
id="polyline82"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="8681,2598 8681,3070"
|
||||
id="polyline84"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="8503,2598 8503,3070"
|
||||
id="polyline86"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="8326,2598 8326,3070"
|
||||
id="polyline88"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="8150,2598 8150,3070"
|
||||
id="polyline90"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="7972,2598 7972,3070"
|
||||
id="polyline92"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="7795,2456 7795,3070"
|
||||
id="polyline94"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="7617,2598 7617,3070"
|
||||
id="polyline96"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="7441,2598 7441,3070"
|
||||
id="polyline98"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="7264,2598 7264,3070"
|
||||
id="polyline100"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="7086,2598 7086,3070"
|
||||
id="polyline102"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="6909,2598 6909,3070"
|
||||
id="polyline104"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="6732,2598 6732,3070"
|
||||
id="polyline106"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="6555,2598 6555,3070"
|
||||
id="polyline108"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="6377,2456 6377,3070"
|
||||
id="polyline110"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="6200,2598 6200,3070"
|
||||
id="polyline112"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="6024,2598 6024,3070"
|
||||
id="polyline114"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="5846,2598 5846,3070"
|
||||
id="polyline116"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="5669,2598 5669,3070"
|
||||
id="polyline118"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="5491,2598 5491,3070"
|
||||
id="polyline120"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="5315,2598 5315,3070"
|
||||
id="polyline122"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="5138,2598 5138,3070"
|
||||
id="polyline124"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="4960,2409 4960,3070"
|
||||
id="polyline126"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="4783,2598 4783,3070"
|
||||
id="polyline128"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="4606,2598 4606,3070"
|
||||
id="polyline130"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="4429,2598 4429,3070"
|
||||
id="polyline132"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="4251,2598 4251,3070"
|
||||
id="polyline134"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="4074,2598 4074,3070"
|
||||
id="polyline136"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="3898,2598 3898,3070"
|
||||
id="polyline138"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="3720,2598 3720,3070"
|
||||
id="polyline140"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="9212,2456 9212,3070"
|
||||
id="polyline142"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="3543,2598 9212,2598"
|
||||
id="polyline144"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="9212,3070 3720,3070 0,3070"
|
||||
id="polyline146"
|
||||
transform="matrix(1.3047439,0,0,1.3955346,-1051.0007,-1956.6141)" />
|
||||
<rect
|
||||
x="4021.6787"
|
||||
y="4311.5088"
|
||||
width="1668.8131"
|
||||
height="3296.2527"
|
||||
rx="0"
|
||||
style="fill:#dfdfdf;stroke-width:11.23412323"
|
||||
id="rect150" />
|
||||
<polyline
|
||||
points="3118,3590 2834,3779"
|
||||
style="stroke:#008200;stroke-opacity:1"
|
||||
id="polyline178"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="1322,3590 1039,3779"
|
||||
style="stroke:#008200;stroke-opacity:1"
|
||||
id="polyline180"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="4913,3590 4629,3779"
|
||||
style="stroke:#008200;stroke-opacity:1"
|
||||
id="polyline184"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="6519,3590 6236,3779"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline186"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="8314,3590 8031,3779"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline188"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="9212,3070 9070,3307 8314,3307 8173,3543 8031,3307 7228,3307 7086,3070"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline204"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="3898,3070 4015,3307 4629,3307 4771,3543 4913,3307 5385,3307 5491,3070"
|
||||
style="stroke:#008200;stroke-opacity:1"
|
||||
id="polyline206"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="5491,3070 5622,3307 6236,3307 6377,3543 6519,3307 6909,3307 7086,3070"
|
||||
style="stroke:#0000ff"
|
||||
id="polyline208"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="2303,3070 2409,3307 2834,3307 2976,3543 3118,3307 3779,3307 3898,3070"
|
||||
style="stroke:#008200;stroke-opacity:1"
|
||||
id="polyline210"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<polyline
|
||||
points="708,3070 850,3307 1039,3307 1181,3543 1322,3307 2173,3307 2303,3070"
|
||||
style="stroke:#008200;stroke-opacity:1"
|
||||
id="polyline212"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)" />
|
||||
<g
|
||||
style="fill:#000000;stroke-width:0"
|
||||
id="g242"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-2048.7241,-1956.6141)">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5546.7881"
|
||||
y="6876.4409"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text320-2-1-5"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:130.85745239px;line-height:125%;font-family:Helvetica;-inkscape-font-specification:'Helvetica, Normal';text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#4d4d4d;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:130.85745239px;line-height:125%;font-family:Helvetica;-inkscape-font-specification:'Helvetica, Normal';text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#4d4d4d;stroke-width:0"
|
||||
id="tspan3503-48-5-5">0</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3507"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text246"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end">32</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2161"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text248"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start">39</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="2090"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text250"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end">40</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="744"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text252"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start">47</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="672"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text254"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="-672"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text256"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="-744"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text258"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="-2090"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text260"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="9176"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text262"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end">0</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7759"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text264"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end">8</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="6342"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text266"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end">16</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4924"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text268"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:end">24</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3579"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text270"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start">31</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="6413"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text272"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start">15</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="7830"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text274"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start">7</text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4996"
|
||||
y="2551"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text276"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:'Helvetica Narrow';text-anchor:start">23</text>
|
||||
<g
|
||||
transform="matrix(0,-1,1,0,8976,6614)"
|
||||
id="g282" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="-2125"
|
||||
y="2314"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text290"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start" />
|
||||
<g
|
||||
transform="matrix(0,-1,1,0,4916.9545,5254.403)"
|
||||
id="g306">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="0"
|
||||
y="0"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="404"
|
||||
id="text308"
|
||||
style="font-style:normal;font-weight:normal;font-size:404px;font-family:Helvetica;text-anchor:middle">...</text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3874"
|
||||
y="3968"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text318"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4862.9551"
|
||||
y="4397.5566"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text320"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle"><tspan
|
||||
style="font-size:200.46391296px"
|
||||
id="tspan3503">P4 table</tspan></text>
|
||||
<text
|
||||
x="2031"
|
||||
y="5622"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text346"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle" />
|
||||
<text
|
||||
x="3165"
|
||||
y="3732"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text350"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start;fill:#008200;fill-opacity:1;">9</text>
|
||||
<text
|
||||
x="1370"
|
||||
y="3732"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text352"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start;fill:#008200;fill-opacity:1;">9</text>
|
||||
<text
|
||||
x="1370"
|
||||
y="6708"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text354"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start;fill:#0000ff" />
|
||||
<text
|
||||
x="4960"
|
||||
y="3732"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text356"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start;fill:#008200;fill-opacity:1;">9</text>
|
||||
<text
|
||||
x="6566"
|
||||
y="3732"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text358"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start;fill:#0000ff">9</text>
|
||||
<text
|
||||
x="8362"
|
||||
y="3732"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text360"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start;fill:#0000ff">12</text>
|
||||
<text
|
||||
x="1181"
|
||||
y="7532.2715"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text364"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:start" />
|
||||
<text
|
||||
x="1946.0945"
|
||||
y="6998.52"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text344-8-6"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:183.75857544px;line-height:125%;font-family:Helvetica;-inkscape-font-specification:'Helvetica, Normal';text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#000000;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
sodipodi:linespacing="125%">
|
||||
<tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:217.16923523px;line-height:125%;font-family:Helvetica;-inkscape-font-specification:'Helvetica, Normal';text-align:center;writing-mode:lr-tb;text-anchor:middle;stroke-width:0"
|
||||
id="tspan3493-3-2" />
|
||||
</text>
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:7.99999952;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
x="4294.9473"
|
||||
y="4493.6152"
|
||||
width="1181"
|
||||
height="471.99994"
|
||||
rx="0"
|
||||
id="rect162-5" />
|
||||
<circle
|
||||
cx="5335.9546"
|
||||
cy="4720.2134"
|
||||
style="fill:#008200;stroke:#008200;stroke-width:31.99999809;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
|
||||
id="circle172-4"
|
||||
r="46.999996" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4815.9546"
|
||||
y="4773.6704"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text314-5"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle;fill:#000000;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter"><tspan
|
||||
style="font-size:200.46391296px;stroke-width:0"
|
||||
id="tspan3495-6">P4 entry</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4925.6357"
|
||||
y="7173.5298"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text314-5-0"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle;fill:#000000;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter"><tspan
|
||||
style="font-size:200.46391296px;stroke-width:0"
|
||||
id="tspan3495-6-4">Recursive</tspan></text>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4925.6357"
|
||||
y="7440.8149"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text314-5-0-9"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle;fill:#000000;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter"><tspan
|
||||
style="font-size:200.46391296px;stroke-width:0"
|
||||
id="tspan3495-6-4-4">Mapping</tspan></text>
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:6.53430033;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
x="4296.5396"
|
||||
y="5560.2471"
|
||||
width="1182.4656"
|
||||
height="314.50067"
|
||||
rx="0"
|
||||
id="rect162-5-1" />
|
||||
<g
|
||||
style="fill:#000000;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
transform="matrix(0,-0.99999994,0.99999994,0,4915.3734,6277.1653)"
|
||||
id="g306-2">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="0"
|
||||
y="0"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="404"
|
||||
id="text308-3"
|
||||
style="font-style:normal;font-weight:normal;font-size:404px;font-family:Helvetica;text-anchor:middle">...</text>
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="3097.1609"
|
||||
y="2954.5652"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text320-4"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:318.2364502px;line-height:125%;font-family:Helvetica;-inkscape-font-specification:'Helvetica, Normal';text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#000000;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
inkscape:transform-center-x="-789.14735"
|
||||
inkscape:transform-center-y="1300.106"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:318.2364502px;line-height:125%;font-family:Helvetica;-inkscape-font-specification:'Helvetica, Normal';text-align:center;writing-mode:lr-tb;text-anchor:middle;stroke-width:0"
|
||||
id="tspan3503-4">111111111111111111111111111</tspan></text>
|
||||
<rect
|
||||
x="8208.377"
|
||||
y="4073.4419"
|
||||
width="691.0863"
|
||||
height="3268.5144"
|
||||
rx="0"
|
||||
style="fill:#dfdfdf;stroke:#000000;stroke-width:7.85773897;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect8" />
|
||||
<rect
|
||||
x="8208.377"
|
||||
y="5474.9399"
|
||||
width="691.0863"
|
||||
height="233.25354"
|
||||
rx="0"
|
||||
style="fill:#dfdfdf;stroke:#000000;stroke-width:7.85773897;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="rect158" />
|
||||
<g
|
||||
style="fill:#000000;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
transform="matrix(0,-0.98836234,0.97611052,0,9106.1205,5822.055)"
|
||||
id="g286">
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="96.892052"
|
||||
y="38.756821"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text288"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle"><tspan
|
||||
style="font-size:200.46391296px"
|
||||
id="tspan3509">P3 table </tspan></text>
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:14.53380773;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 2308.9448,-2797.8507 -483.0169,0 0,-2544.6425 -1879.786585,0 0,339.1222"
|
||||
id="path8874"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="4809.9756"
|
||||
y="5774.4951"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text314-5-5"
|
||||
style="font-style:normal;font-weight:normal;font-size:152px;font-family:Helvetica;text-anchor:middle;fill:#000000;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter"><tspan
|
||||
style="font-size:200.46392822px;stroke-width:0"
|
||||
id="tspan3495-6-7">P4 entry</tspan></text>
|
||||
<ellipse
|
||||
ry="46.999996"
|
||||
rx="46.999992"
|
||||
cx="5336.855"
|
||||
cy="5714.1816"
|
||||
style="fill:#0000ff;stroke:#0000ff;stroke-width:31.99999809;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="circle172-4-4" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:9.55735683px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 5392.0276,5712.0004 1512.0496,0 0,1631.4957 1257.8109,0"
|
||||
id="path9464"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#0000ff;stroke-width:9.51690483px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 8173.2452,3542.5202 0,364.8071 -584.0141,0 0,1802.0952 528.0052,0"
|
||||
id="path9466"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
x="5610.3569"
|
||||
y="4990.1772"
|
||||
font-style="normal"
|
||||
font-weight="normal"
|
||||
font-size="152"
|
||||
id="text320-2-1"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:130.85745239px;line-height:125%;font-family:Helvetica;-inkscape-font-specification:'Helvetica, Normal';text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#4d4d4d;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:130.85745239px;line-height:125%;font-family:Helvetica;-inkscape-font-specification:'Helvetica, Normal';text-align:center;writing-mode:lr-tb;text-anchor:middle;fill:#4d4d4d;stroke-width:0"
|
||||
id="tspan3503-48-5">511</tspan></text>
|
||||
</g>
|
||||
<polygon
|
||||
points="3308,6614 3150,6566 3150,6661 3150,6661 "
|
||||
style="fill:#008200;stroke:#008200;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;fill-opacity:1;stroke-opacity:1"
|
||||
id="polygon232-2"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-646.4618,-1622.6914)" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#008200;stroke-width:18.76697159px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 5574.5569,4637.287 719.9709,0 0,3526.7653 -2765.702,0 0,-560.545 294.8212,0"
|
||||
id="path5354"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#008200;stroke-width:18.52740288px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 3843.9848,5007.8363 -4223.58417,0 0,-2024.2908"
|
||||
id="path5356"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#008200;stroke-width:18.65159035px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 2156.7076,2986.8221 0,1988.2634 1691.863,0"
|
||||
id="path5358"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:none;fill-rule:evenodd;stroke:#008200;stroke-width:18.78581619px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 4696.351,2980.052 0,497.5653 -1975.7645,0 0,1464.6642 1128.3337,0"
|
||||
id="path5360"
|
||||
inkscape:connector-curvature="0" />
|
||||
<polygon
|
||||
points="3150,6661 3308,6614 3150,6566 3150,6661 "
|
||||
style="fill:#0000ff;stroke:#0000ff;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="polygon232-2-7"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-625.83944,-2988.2046)" />
|
||||
<polygon
|
||||
points="3150,6661 3150,6661 3308,6614 3150,6566 "
|
||||
style="fill:#0000ff;stroke:#0000ff;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="polygon232-2-7-3"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,4891.7749,-3219.444)" />
|
||||
<polygon
|
||||
points="3150,6661 3150,6661 3308,6614 3150,6566 "
|
||||
style="fill:#0000ff;stroke:#0000ff;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter"
|
||||
id="polygon232-2-7-3-5"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,4896.989,-940.27671)" />
|
||||
<polygon
|
||||
points="3150,6566 3150,6661 3150,6661 3308,6614 "
|
||||
style="fill:#008200;stroke:#008200;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;fill-opacity:1;stroke-opacity:1"
|
||||
id="polygon232-2-7-7"
|
||||
transform="matrix(1.4130509,0,0,1.3955346,-628.09888,-4256.4264)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
@@ -622,25 +622,25 @@ We will choose another solution with different tradoffs. It's not clearly “bet
|
||||
|
||||
A freed memory block is not used anymore and no one needs the stored information. It is still mapped to a virtual address and backed by a physical page. So we just store the information about the freed block _in the block itself_. We keep a pointer to the first block and store a pointer to the next block in each block. Thus, we create a single linked list:
|
||||
|
||||

|
||||

|
||||
|
||||
In the following, we call a freed block a _hole_. Each hole stores its size and a pointer to the next hole. If a hole is larger than needed, we leave the remaining memory unused. By storing a pointer to the first hole, we are able to traverse the complete list.
|
||||
|
||||
#### Initialization
|
||||
When the heap is created, all of its memory is unused. Thus, it forms a single large hole:
|
||||
|
||||

|
||||

|
||||
|
||||
The optional pointer to the next hole is set to `None`.
|
||||
|
||||
#### Allocation
|
||||
In order to allocate a block of memory, we need to find a hole that satisfies the size and alignment requirements. If the found hole is larger than required, we split it into two smaller holes. For example, when we allocate a 24 byte block right after initialization, we split the single hole into a hole of size 24 and a hole with the remaining size:
|
||||
|
||||

|
||||

|
||||
|
||||
Then we use the new 24 byte hole to perform the allocation:
|
||||
|
||||

|
||||

|
||||
|
||||
To find a suitable hole, we can use several search strategies:
|
||||
|
||||
@@ -659,11 +659,11 @@ However, both best fit and worst fit have a significant problem: They need to sc
|
||||
#### Deallocation
|
||||
To deallocate a block of memory, we can just insert its corresponding hole somewhere into the list. However, we need to merge adjacent holes. Otherwise, we are unable to reuse the freed memory for larger allocations. For example:
|
||||
|
||||

|
||||

|
||||
|
||||
In order to use these adjacent holes for a large allocation, we need to merge them to a single large hole first:
|
||||
|
||||

|
||||

|
||||
|
||||
The easiest way to ensure that adjacent holes are always merged, is to keep the hole list sorted by address. Thus, we only need to check the predecessor and the successor in the list when we free a memory block. If they are adjacent to the freed block, we merge the corresponding holes. Else, we insert the freed block as a new hole at the correct position.
|
||||
|
||||
@@ -677,7 +677,7 @@ The detailed implementation would go beyond the scope of this post, since it con
|
||||
I created the [linked_list_allocator] crate to handle all of these cases. It consists of a [Heap struct] that provides an `allocate_first_fit` and a `deallocate` method. If you are interested in the implementation details, check out the [source code][linked_list_allocator source].
|
||||
|
||||
[linked_list_allocator]: https://crates.io/crates/linked_list_allocator
|
||||
[Heap struct]: http://phil-opp.github.io/linked-list-allocator/linked_list_allocator/struct.Heap.html
|
||||
[Heap struct]: http://phil-opp.github.io/linked_list_allocator/struct.Heap.html
|
||||
[linked_list_allocator source]: https://github.com/phil-opp/linked-list-allocator
|
||||
|
||||
So we just need to implement Rust's allocation modules and integrate it into our kernel. We start by creating a new `hole_list_allocator` crate inside the `libs` directory:
|
||||
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
@@ -160,7 +160,7 @@ Since we don't know when an exception occurs, we can't backup any registers befo
|
||||
### The Exception Stack Frame
|
||||
On a normal function call (using the `call` instruction), the CPU pushes the return address before jumping to the target function. On function return (using the `ret` instruction), the CPU pops this return address and jumps to it. So the stack frame of a normal function call looks like this:
|
||||
|
||||

|
||||

|
||||
|
||||
For exception and interrupt handlers, however, pushing a return address would not suffice, since interrupt handlers often run in a different context (stack pointer, CPU flags, etc.). Instead, the CPU performs the following steps when an interrupt occurs:
|
||||
|
||||
@@ -176,7 +176,7 @@ For exception and interrupt handlers, however, pushing a return address would no
|
||||
|
||||
So the _exception stack frame_ looks like this:
|
||||
|
||||

|
||||

|
||||
|
||||
In the `x86_64` crate, the exception stack frame is represented by the [`ExceptionStackFrame`] struct. It is passed to interrupt handlers as `&mut` and can be used to retrieve additional information about the exception's cause. The struct contains no error code field, since only some few exceptions push an error code. These exceptions use the separate [`HandlerFuncWithErrCode`] function type, which has an additional `error_code` argument.
|
||||
|
||||
@@ -406,7 +406,7 @@ pub extern "C" fn rust_main(...) {
|
||||
|
||||
When we run it in QEMU now (using `make run`), we see the following:
|
||||
|
||||

|
||||

|
||||
|
||||
It works! The CPU successfully invokes our breakpoint handler, which prints the message, and then returns back to the `rust_main` function, where the `It did not crash!` message is printed.
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
@@ -49,7 +49,7 @@ We try to write to address `0xdeadbeaf`, but the corresponding page is not prese
|
||||
|
||||
When we start our kernel now, we see that it enters an endless boot loop:
|
||||
|
||||

|
||||

|
||||
|
||||
The reason for the boot loop is the following:
|
||||
|
||||
@@ -90,7 +90,7 @@ Our handler prints a short error message and dumps the exception stack frame. Th
|
||||
|
||||
When we start our kernel now, we should see that the double fault handler is invoked:
|
||||
|
||||

|
||||

|
||||
|
||||
It worked! Here is what happens this time:
|
||||
|
||||
@@ -906,7 +906,7 @@ The `set_stack_index` method is unsafe because the the caller must ensure that t
|
||||
|
||||
That's it! Now the CPU should switch to the double fault stack whenever a double fault occurs. Thus, we are able to catch _all_ double faults, including kernel stack overflows:
|
||||
|
||||

|
||||

|
||||
|
||||
From now on we should never see a triple fault again!
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 17 KiB |