Replace unsupported highlight syntax with normal code blocks

This commit is contained in:
Philipp Oppermann
2017-06-09 14:43:03 +02:00
parent 945a766f0c
commit 59594b8622
5 changed files with 66 additions and 65 deletions

View File

@@ -139,7 +139,7 @@ To create the ELF _executable_, we need to [link] the object files together. We
[link]: https://en.wikipedia.org/wiki/Linker_(computing)
[linker script]: https://sourceware.org/binutils/docs/ld/Scripts.html
```
```ld
ENTRY(start)
SECTIONS {

View File

@@ -214,10 +214,10 @@ To fix it, we can implement the [Copy] trait for the `ColorCode` type. The easie
[Copy]: https://doc.rust-lang.org/nightly/core/marker/trait.Copy.html
[derive macro]: http://rustbyexample.com/trait/derive.html
{{< highlight rust "hl_lines=1" >}}
```rust
#[derive(Debug, Clone, Copy)]
struct ColorCode(u8);
{{< / highlight >}}
```
We also derive the [Clone] trait, since it's a requirement for `Copy`, and the [Debug] trait, which allows us to print this field for debugging purposes.
@@ -230,7 +230,7 @@ However, the [documentation for Copy] says: _“if your type can implement Copy,
[documentation for Copy]: https://doc.rust-lang.org/core/marker/trait.Copy.html#when-should-my-type-be-copy
{{< highlight rust "hl_lines=2 6" >}}
```rust
#[allow(dead_code)]
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
@@ -239,7 +239,7 @@ pub enum Color {...}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
struct ScreenChar {...}
{{< / highlight >}}
```
### Try it out!
To write some characters to the screen, you can create a temporary function:
@@ -315,7 +315,7 @@ Instead of a `ScreenChar`, we're now using a `Volatile<ScreenChar>`. (The `Volat
This means that we have to update our `Writer::write_byte` method:
{{< highlight rust "hl_lines=8 11" >}}
```rust
impl Writer {
pub fn write_byte(&mut self, byte: u8) {
match byte {
@@ -333,7 +333,7 @@ impl Writer {
}
...
}
{{< / highlight >}}
```
Instead of a normal assignment using `=`, we're now using the `write` method. This guarantees that the compiler will never optimize away this write.
@@ -375,14 +375,14 @@ The `Ok(())` is just a `Ok` Result containing the `()` type. We can drop the `pu
Now we can use Rust's built-in `write!`/`writeln!` formatting macros:
{{< highlight rust "hl_lines=2 4 5 6" >}}
```rust
// in the `print_something` function
use core::fmt::Write;
let mut writer = Writer {...};
writer.write_byte(b'H');
writer.write_str("ello! ");
write!(writer, "The numbers are {} and {}", 42, 1.0/3.0);
{{< / highlight >}}
```
Now you should see a `Hello! The numbers are 42 and 0.3333333333333333` at the bottom of the screen.
@@ -563,7 +563,7 @@ pub fn clear_screen() {
### Hello World using `println`
To use `println` in `lib.rs`, we need to import the macros of the VGA buffer module first. Therefore we add a `#[macro_use]` attribute to the module declaration:
{{< highlight rust "hl_lines=3 9 10" >}}
```rust
// in src/lib.rs
#[macro_use]
@@ -577,7 +577,7 @@ pub extern fn rust_main() {
loop{}
}
{{< / highlight >}}
```
Since we imported the macros at crate level, they are available in all modules and thus provide an easy and safe interface to the VGA buffer.

View File

@@ -26,7 +26,7 @@ A double fault behaves like a normal exception. It has the vector number `8` and
### Triggering a Double Fault
Let's provoke a double fault by triggering an exception for that we didn't define a handler function:
{{< highlight rust "hl_lines=10" >}}
```rust
// in src/lib.rs
#[no_mangle]
@@ -43,7 +43,7 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) {
println!("It did not crash!");
loop {}
}
{{< / highlight >}}
```
We try to write to address `0xdeadbeaf`, but the corresponding page is not present in the page tables. Thus, a page fault occurs. We haven't registered a page fault handler in our [IDT], so a double fault occurs.
@@ -63,7 +63,7 @@ So in order to prevent this triple fault, we need to either provide a handler fu
### A Double Fault Handler
A double fault is a normal exception with an error code, so we can use our `handler_with_error_code` macro to create a wrapper function:
{{< highlight rust "hl_lines=8 14" >}}
```rust
// in src/interrupts.rs
lazy_static! {
@@ -84,7 +84,7 @@ extern "x86-interrupt" fn double_fault_handler(
println!("\nEXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
loop {}
}
{{< / highlight >}}<!--end_-->
```
Our handler prints a short error message and dumps the exception stack frame. The error code of the double fault handler is always zero, so there's no reason to print it.
@@ -160,7 +160,7 @@ So the CPU tries to call our _double fault handler_ now. However, on a double fa
Let's try it ourselves! We can easily provoke a kernel stack overflow by calling a function that recurses endlessly:
{{< highlight rust "hl_lines=9 10 11 14" >}}
```rust
// in src/lib.rs
#[no_mangle]
@@ -179,7 +179,7 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) {
println!("It did not crash!");
loop {}
}
{{< / highlight >}}
```
When we try this code in QEMU, we see that the system enters a boot-loop again.
@@ -402,7 +402,7 @@ impl Add<usize> for Page {
#### Allocating a Double Fault Stack
Now we can allocate a new double fault stack by passing the memory controller to our `interrupts::init` function:
{{< highlight rust "hl_lines=8 11 12 21 22 23" >}}
```rust
// in src/lib.rs
#[no_mangle]
@@ -429,7 +429,7 @@ pub fn init(memory_controller: &mut MemoryController) {
IDT.load();
}
{{< / highlight >}}
```
We allocate a 4096 bytes stack (one page) for our double fault handler. Now we just need some way to tell the CPU that it should use this stack for handling double faults.
@@ -470,7 +470,7 @@ use x86_64::structures::tss::TaskStateSegment;
Let's create a new TSS in our `interrupts::init` function:
{{< highlight rust "hl_lines=3 9 10" >}}
```rust
// in src/interrupts.rs
use x86_64::VirtualAddress;
@@ -487,7 +487,7 @@ pub fn init(memory_controller: &mut MemoryController) {
IDT.load();
}
{{< / highlight >}}
```
We define that the 0th IST entry is the double fault stack (any other IST index would work too). We create a new TSS through the `TaskStateSegment::new` function and load the top address (stacks grow downwards) of the double fault stack into the 0th entry.
@@ -737,7 +737,7 @@ We now have a double fault stack and are able to create and load a TSS (which co
We already created a new TSS in our `interrupts::init` function. Now we can load this TSS by creating a new GDT:
{{< highlight rust "hl_lines=10 11 12 13" >}}
```rust
// in src/interrupts/mod.rs
pub fn init(memory_controller: &mut MemoryController) {
@@ -755,7 +755,7 @@ pub fn init(memory_controller: &mut MemoryController) {
IDT.load();
}
{{< / highlight >}}
```
However, when we try to compile it, the following errors occur:
@@ -814,7 +814,7 @@ The `Once` type allows us to initialize a `static` at runtime. It is safe becaus
So let's rewrite our `interrupts::init` function to use the static `TSS` and `GDT`:
{{< highlight rust "hl_lines=5 9 10 12 17 18" >}}
```rust
pub fn init(memory_controller: &mut MemoryController) {
let double_fault_stack = memory_controller.alloc_stack(1)
.expect("could not allocate double fault stack");
@@ -837,7 +837,7 @@ pub fn init(memory_controller: &mut MemoryController) {
IDT.load();
}
{{< / highlight >}}
```
Now it should compile again!
@@ -850,7 +850,7 @@ We're almost done. We successfully loaded our new GDT, which contains a TSS desc
For the first two steps, we need access to the `code_selector` and `tss_selector` variables outside of the closure. We can achieve this by moving the `let` declarations out of the closure:
{{< highlight rust "hl_lines=3 4 5 8 9 12 13 20 22" >}}
```rust
// in src/interrupts/mod.rs
pub fn init(memory_controller: &mut MemoryController) {
use x86_64::structures::gdt::SegmentSelector;
@@ -877,7 +877,7 @@ pub fn init(memory_controller: &mut MemoryController) {
IDT.load();
}
{{< / highlight >}}
```
We first set the descriptors to `empty` and then update them from inside the closure (which implicitly borrows them as `&mut`). Now we're able to reload the code segment register using [`set_cs`] and to load the TSS using [`load_tss`].
@@ -886,7 +886,7 @@ We first set the descriptors to `empty` and then update them from inside the clo
Now that we loaded a valid TSS and interrupt stack table, we can set the stack index for our double fault handler in the IDT:
{{< highlight rust "hl_lines=7 9" >}}
```rust
// in src/interrupt/mod.rs
lazy_static! {
@@ -900,7 +900,7 @@ lazy_static! {
...
};
}
{{< / highlight >}}
```
The `set_stack_index` method is unsafe because the the caller must ensure that the used index is valid and not already used for another exception.