Merge branch 'master' into translations

This commit is contained in:
Philipp Oppermann
2020-02-17 10:38:43 +01:00
41 changed files with 1555 additions and 149 deletions

View File

@@ -0,0 +1,29 @@
+++
title = "Disable the Red Zone"
weight = 1
path = "red-zone"
template = "second-edition/extra.html"
+++
The [red zone] is an optimization of the [System V ABI] that allows functions to temporarily use the 128 bytes below its stack frame without adjusting the stack pointer:
[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
<!-- more -->
![stack frame with red zone](red-zone.svg)
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 return address and the local variables.
The red zone is defined as the 128 bytes below the adjusted stack pointer. The function can use this area for temporary data that's not needed across function calls. Thus, the two instructions for adjusting the stack pointer can be avoided in some cases (e.g. in small leaf functions).
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:
![red zone overwritten by exception handler](red-zone-overwrite.svg)
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].
[take weeks to debug]: http://forum.osdev.org/viewtopic.php?t=21720
To avoid such bugs when we implement exception handling in the future, we disable the red zone right from the beginning. This is achieved by adding the `"disable-redzone": true` line to our target configuration file.

View 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

View 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

View File

@@ -0,0 +1,44 @@
+++
title = "Disable SIMD"
weight = 2
path = "disable-simd"
template = "second-edition/extra.html"
+++
[Single Instruction Multiple Data (SIMD)] instructions are able to perform an operation (e.g. addition) simultaneously on multiple data words, which can speed up programs significantly. The `x86_64` architecture supports various SIMD standards:
[Single Instruction Multiple Data (SIMD)]: https://en.wikipedia.org/wiki/SIMD
<!-- more -->
- [MMX]: The _Multi Media Extension_ instruction set was introduced in 1997 and defines eight 64 bit registers called `mm0` through `mm7`. These registers are just aliases for the registers of the [x87 floating point unit].
- [SSE]: The _Streaming SIMD Extensions_ instruction set was introduced in 1999. Instead of re-using the floating point registers, it adds a completely new register set. The sixteen new registers are called `xmm0` through `xmm15` and are 128 bits each.
- [AVX]: The _Advanced Vector Extensions_ are extensions that further increase the size of the multimedia registers. The new registers are called `ymm0` through `ymm15` and are 256 bits each. They extend the `xmm` registers, so e.g. `xmm0` is the lower half of `ymm0`.
[MMX]: https://en.wikipedia.org/wiki/MMX_(instruction_set)
[x87 floating point unit]: https://en.wikipedia.org/wiki/X87
[SSE]: https://en.wikipedia.org/wiki/Streaming_SIMD_Extensions
[AVX]: https://en.wikipedia.org/wiki/Advanced_Vector_Extensions
By using such SIMD standards, programs can often speed up significantly. Good compilers are able to transform normal loops into such SIMD code automatically through a process called [auto-vectorization].
[auto-vectorization]: https://en.wikipedia.org/wiki/Automatic_vectorization
However, the large SIMD registers lead to problems in OS kernels. The reason is that the kernel has to backup all registers that it uses to memory on each hardware interrupt, because they need to have their original values when the interrupted program continues. So if the kernel uses SIMD registers, it has to backup a lot more data (5121600 bytes), which noticeably decreases performance. To avoid this performance loss, we want to disable the `sse` and `mmx` features (the `avx` feature is disabled by default).
We can do that through the the `features` field in our target specification. To disable the `mmx` and `sse` features we add them prefixed with a minus:
```json
"features": "-mmx,-sse"
```
## Floating Point
Unfortunately for us, the `x86_64` architecture uses SSE registers for floating point operations. Thus, every use of floating point with disabled SSE causes an error in LLVM. The problem is that Rust's core library already uses floats (e.g., it implements traits for `f32` and `f64`), so avoiding floats in our kernel does not suffice.
Fortunately, LLVM has support for a `soft-float` feature, emulates all floating point operations through software functions based on normal integers. This makes it possible to use floats in our kernel without SSE, it will just be a bit slower.
To turn on the `soft-float` feature for our kernel, we add it to the `features` line in our target specification, prefixed with a plus:
```json
"features": "-mmx,-sse,+soft-float"
```

View File

@@ -4,6 +4,8 @@ weight = 2
path = "minimal-rust-kernel"
date = 2018-02-10
[extra]
chapter = "Bare Bones"
+++
In this post we create a minimal 64-bit Rust kernel for the x86 architecture. We build upon the [freestanding Rust binary] from the previous post to create a bootable disk image, that prints something to the screen.
@@ -169,7 +171,7 @@ This setting specifies that the target doesn't support [stack unwinding] on pani
We're writing a kernel, so we'll need to handle interrupts at some point. To do that safely, we have to disable a certain stack pointer optimization called the _“red zone”_, because it would cause stack corruptions otherwise. For more information, see our separate post about [disabling the red zone].
[disabling the red zone]: @/second-edition/extra/disable-red-zone/index.md
[disabling the red zone]: @/second-edition/posts/02-minimal-rust-kernel/disable-red-zone/index.md
```json
"features": "-mmx,-sse,+soft-float",
@@ -183,7 +185,7 @@ The `mmx` and `sse` features determine support for [Single Instruction Multiple
A problem with disabling SIMD is that floating point operations on `x86_64` require SIMD registers by default. To solve this problem, we add the `soft-float` feature, which emulates all floating point operations through software functions based on normal integers.
For more information, see our post on [disabling SIMD](@/second-edition/extra/disable-simd/index.md).
For more information, see our post on [disabling SIMD](@/second-edition/posts/02-minimal-rust-kernel/disable-simd/index.md).
#### Putting it Together
Our target specification file now looks like this: