diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 23538d63..00000000 --- a/.appveyor.yml +++ /dev/null @@ -1,10 +0,0 @@ -branches: - only: - - staging - - trying - - /post-.*/ - -build: false - -test_script: - - echo "Nothing to do for master branch" diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index cab13b7b..00000000 --- a/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: minimal - -branches: - only: - # This is where pull requests from "bors r+" are built. - - staging - # This is where pull requests from "bors try" are built. - - trying - # Build post braches - - /^post-.*$/ - -script: - - echo "Nothing to do for master branch" diff --git a/LICENSE-MIT b/LICENSE-MIT index 2286d30b..de62280d 100644 --- a/LICENSE-MIT +++ b/LICENSE-MIT @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 Philipp Oppermann +Copyright (c) 2019 Philipp Oppermann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index 08c6199a..cca40b6a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The code for each post lives in a separate git branch. This makes it possible to **The code for the latest post is available [here][latest-post].** -[latest-post]: https://github.com/phil-opp/blog_os/tree/post-10 +[latest-post]: https://github.com/phil-opp/blog_os/tree/post-11 You can find the branch for each post by following the `(source code)` link in the [post list](#posts) below. The branches are named `post-XX` where `XX` is the post number, for example `post-03` for the _VGA Text Mode_ post or `post-07` for the _Hardware Interrupts_ post. For build instructions, see the Readme of the respective branch. @@ -56,6 +56,8 @@ The goal of this project is to provide step-by-step tutorials in individual blog ([source code](https://github.com/phil-opp/blog_os/tree/post-09)) - [Heap Allocation](https://os.phil-opp.com/heap-allocation/) ([source code](https://github.com/phil-opp/blog_os/tree/post-10)) +- [Allocator Designs](https://os.phil-opp.com/allocator-designs/) + ([source code](https://github.com/phil-opp/blog_os/tree/post-11)) ## First Edition Posts @@ -104,4 +106,17 @@ The current version of the blog is already the second edition. The first edition ([source code](https://github.com/phil-opp/blog_os/tree/returning_from_exceptions)) ## License -The source code is dual-licensed under MIT or the Apache License (Version 2.0). This excludes the `blog` directory. + +This project, with exception of the `blog/content` folder, is licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +For licensing of the `blog/content` folder, see the [`blog/content/README.md`](blog/content/README.md). + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index 2098d3ca..00000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,48 +0,0 @@ -# Documentation: https://aka.ms/yaml - -trigger: - branches: - include: - - '*' - exclude: - - 'staging.tmp' - -pool: - vmImage: ubuntu-16.04 - -steps: -- bash: | - echo "Hello world from $AGENT_NAME running on $AGENT_OS" - echo "Reason: $BUILD_REASON" - echo "Requested for: $BUILD_REQUESTEDFOR" - displayName: 'Build Info' - continueOnError: true - -- bash: curl -sL https://github.com/getzola/zola/releases/download/v0.9.0/zola-v0.9.0-x86_64-unknown-linux-gnu.tar.gz | tar zxv - displayName: "Download Zola" - -- script: python -m pip install --upgrade pip setuptools wheel - displayName: 'Install Python Tools' - -- script: python -m pip install --user -r requirements.txt - displayName: 'Install Python Libraries' - workingDirectory: "blog" - -- script: python before_build.py - displayName: "Run before_build.py script" - workingDirectory: "blog" - -- script: ../zola build - displayName: "Build Site" - workingDirectory: "blog" - -- task: PublishPipelineArtifact@0 - inputs: - artifactName: 'generated_site' - targetPath: 'blog/public' - -- script: curl -L https://git.io/misspell | bash - displayName: "Install misspell" - -- script: bin/misspell -error blog/content - displayName: "Check for common typos" diff --git a/blog/before_build.py b/blog/before_build.py index b779889e..2f6e60e5 100644 --- a/blog/before_build.py +++ b/blog/before_build.py @@ -21,18 +21,22 @@ def format_number(number): with io.open("templates/auto/recent-updates.html", 'w', encoding='utf8') as recent_updates: recent_updates.truncate() - recent_updates.write(u"
\`\`\`) are additionally licensed under either of
+
+- Apache License, Version 2.0 ([LICENSE-APACHE](../../LICENSE-APACHE) or
+ http://www.apache.org/licenses/LICENSE-2.0)
+- MIT license ([LICENSE-MIT](../../LICENSE-MIT) or http://opensource.org/licenses/MIT)
+
+at your option.
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be licensed as above, without any additional terms or conditions.
diff --git a/blog/content/pages/contact.md b/blog/content/pages/contact.md
index fb0e007e..34c952f0 100644
--- a/blog/content/pages/contact.md
+++ b/blog/content/pages/contact.md
@@ -8,4 +8,4 @@ Philipp Oppermann
contact@phil-opp.com
-Dr.Gustav-Knodel-Str. 7b, 76344 Eggenstein, Germany
+Gerwigstraße 17, 76131 Karlsruhe, Germany
diff --git a/blog/content/second-edition/extra/building-on-android/index.md b/blog/content/second-edition/extra/building-on-android/index.md
index 7d0d362a..9bdf0ef5 100644
--- a/blog/content/second-edition/extra/building-on-android/index.md
+++ b/blog/content/second-edition/extra/building-on-android/index.md
@@ -6,6 +6,8 @@ weight = 3
I finally managed to get `blog_os` building on my Android phone using [termux](https://termux.com/). This post explains the necessary steps to set it up.
+
+
diff --git a/blog/content/second-edition/posts/01-freestanding-rust-binary/index.md b/blog/content/second-edition/posts/01-freestanding-rust-binary/index.md
index 5564e899..c704e57c 100644
--- a/blog/content/second-edition/posts/01-freestanding-rust-binary/index.md
+++ b/blog/content/second-edition/posts/01-freestanding-rust-binary/index.md
@@ -4,6 +4,8 @@ weight = 1
path = "freestanding-rust-binary"
date = 2018-02-10
+[extra]
+chapter = "Bare Bones"
+++
The first step in creating our own operating system kernel is to create a Rust executable that does not link the standard library. This makes it possible to run Rust code on the [bare metal] without an underlying operating system.
@@ -145,10 +147,11 @@ Language items are special functions and types that are required internally by t
[`Copy`]: https://doc.rust-lang.org/nightly/core/marker/trait.Copy.html
[copy code]: https://github.com/rust-lang/rust/blob/485397e49a02a3b7ff77c17e4a3f16c653925cb3/src/libcore/marker.rs#L296-L299
-Providing own implementations of language items would be possible, but this should only be done as a last resort. The reason is that language items are highly unstable implementation details and not even type checked (so the compiler doesn't even check if a function has the right argument types). Fortunately, there is a more stable way to fix the above language item error.
+While providing custom implementations of language items is possible, it should only be done as a last resort. The reason is that language items are highly unstable implementation details and not even type checked (so the compiler doesn't even check if a function has the right argument types). Fortunately, there is a more stable way to fix the above language item error.
-The `eh_personality` language item marks a function that is used for implementing [stack unwinding]. By default, Rust uses unwinding to run the destructors of all live stack variables in case of a [panic]. This ensures that all used memory is freed and allows the parent thread to catch the panic and continue execution. Unwinding, however, is a complicated process and requires some OS specific libraries (e.g. [libunwind] on Linux or [structured exception handling] on Windows), so we don't want to use it for our operating system.
+The [`eh_personality` language item] marks a function that is used for implementing [stack unwinding]. By default, Rust uses unwinding to run the destructors of all live stack variables in case of a [panic]. This ensures that all used memory is freed and allows the parent thread to catch the panic and continue execution. Unwinding, however, is a complicated process and requires some OS specific libraries (e.g. [libunwind] on Linux or [structured exception handling] on Windows), so we don't want to use it for our operating system.
+[`eh_personality` language item]: https://github.com/rust-lang/rust/blob/edb368491551a77d77a48446d4ee88b35490c565/src/libpanic_unwind/gcc.rs#L11-L45
[stack unwinding]: http://www.bogotobogo.com/cplusplus/stackunwinding.php
[libunwind]: http://www.nongnu.org/libunwind/
[structured exception handling]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680657(v=vs.85).aspx
@@ -507,7 +510,7 @@ cargo rustc -- -C link-args="/ENTRY:_start /SUBSYSTEM:console"
cargo rustc -- -C link-args="-e __start -static -nostartfiles"
```
-Note that this is just a minimal example of a freestanding Rust binary. This binary expects various things, for example that a stack is initialized when the `_start` function is called. **So it probably for any real use of such a binary, more steps are required**.
+Note that this is just a minimal example of a freestanding Rust binary. This binary expects various things, for example that a stack is initialized when the `_start` function is called. **So for any real use of such a binary, more steps are required**.
## What's next?
diff --git a/blog/content/second-edition/extra/disable-red-zone/index.md b/blog/content/second-edition/posts/02-minimal-rust-kernel/disable-red-zone/index.md
similarity index 96%
rename from blog/content/second-edition/extra/disable-red-zone/index.md
rename to blog/content/second-edition/posts/02-minimal-rust-kernel/disable-red-zone/index.md
index f8740dde..212ccb97 100644
--- a/blog/content/second-edition/extra/disable-red-zone/index.md
+++ b/blog/content/second-edition/posts/02-minimal-rust-kernel/disable-red-zone/index.md
@@ -2,7 +2,7 @@
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:
@@ -10,6 +10,8 @@ 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 return address and the local variables.
diff --git a/blog/content/second-edition/extra/disable-red-zone/red-zone-overwrite.svg b/blog/content/second-edition/posts/02-minimal-rust-kernel/disable-red-zone/red-zone-overwrite.svg
similarity index 100%
rename from blog/content/second-edition/extra/disable-red-zone/red-zone-overwrite.svg
rename to blog/content/second-edition/posts/02-minimal-rust-kernel/disable-red-zone/red-zone-overwrite.svg
diff --git a/blog/content/second-edition/extra/disable-red-zone/red-zone.svg b/blog/content/second-edition/posts/02-minimal-rust-kernel/disable-red-zone/red-zone.svg
similarity index 100%
rename from blog/content/second-edition/extra/disable-red-zone/red-zone.svg
rename to blog/content/second-edition/posts/02-minimal-rust-kernel/disable-red-zone/red-zone.svg
diff --git a/blog/content/second-edition/extra/disable-simd/index.md b/blog/content/second-edition/posts/02-minimal-rust-kernel/disable-simd/index.md
similarity index 98%
rename from blog/content/second-edition/extra/disable-simd/index.md
rename to blog/content/second-edition/posts/02-minimal-rust-kernel/disable-simd/index.md
index 6810ddf6..6fe2f8d8 100644
--- a/blog/content/second-edition/extra/disable-simd/index.md
+++ b/blog/content/second-edition/posts/02-minimal-rust-kernel/disable-simd/index.md
@@ -2,13 +2,15 @@
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
+
+
- [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`.
diff --git a/blog/content/second-edition/posts/02-minimal-rust-kernel/index.md b/blog/content/second-edition/posts/02-minimal-rust-kernel/index.md
index 1f77204c..26ce8b18 100644
--- a/blog/content/second-edition/posts/02-minimal-rust-kernel/index.md
+++ b/blog/content/second-edition/posts/02-minimal-rust-kernel/index.md
@@ -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:
diff --git a/blog/content/second-edition/posts/03-vga-text-buffer/index.md b/blog/content/second-edition/posts/03-vga-text-buffer/index.md
index 09b46610..94098765 100644
--- a/blog/content/second-edition/posts/03-vga-text-buffer/index.md
+++ b/blog/content/second-edition/posts/03-vga-text-buffer/index.md
@@ -4,6 +4,8 @@ weight = 3
path = "vga-text-mode"
date = 2018-02-26
+[extra]
+chapter = "Bare Bones"
+++
The [VGA text mode] is a simple way to print text to the screen. In this post, we create an interface that makes its usage safe and simple, by encapsulating all unsafety in a separate module. We also implement support for Rust's [formatting macros].
diff --git a/blog/content/second-edition/posts/04-testing/index.md b/blog/content/second-edition/posts/04-testing/index.md
index 6e66feab..c63e4ce7 100644
--- a/blog/content/second-edition/posts/04-testing/index.md
+++ b/blog/content/second-edition/posts/04-testing/index.md
@@ -4,6 +4,8 @@ weight = 4
path = "testing"
date = 2019-04-27
+[extra]
+chapter = "Bare Bones"
+++
This post explores unit and integration testing in `no_std` executables. We will use Rust's support for custom test frameworks to execute test functions inside our kernel. To report the results out of QEMU, we will use different features of QEMU and the `bootimage` tool.
@@ -166,18 +168,18 @@ The functionality of the `isa-debug-exit` device is very simple. When a `value`
Instead of manually invoking the `in` and `out` assembly instructions, we use the abstractions provided by the [`x86_64`] crate. To add a dependency on that crate, we add it to the `dependencies` section in our `Cargo.toml`:
-[`x86_64`]: https://docs.rs/x86_64/0.7.5/x86_64/
+[`x86_64`]: https://docs.rs/x86_64/0.8.1/x86_64/
```toml
# in Cargo.toml
[dependencies]
-x86_64 = "0.7.5"
+x86_64 = "0.8.1"
```
Now we can use the [`Port`] type provided by the crate to create an `exit_qemu` function:
-[`Port`]: https://docs.rs/x86_64/0.7.5/x86_64/instructions/port/struct.Port.html
+[`Port`]: https://docs.rs/x86_64/0.8.1/x86_64/instructions/port/struct.Port.html
```rust
// in src/main.rs
diff --git a/blog/content/second-edition/posts/05-cpu-exceptions/index.md b/blog/content/second-edition/posts/05-cpu-exceptions/index.md
index 0fa6862b..f318cfdb 100644
--- a/blog/content/second-edition/posts/05-cpu-exceptions/index.md
+++ b/blog/content/second-edition/posts/05-cpu-exceptions/index.md
@@ -4,6 +4,8 @@ weight = 5
path = "cpu-exceptions"
date = 2018-06-17
+[extra]
+chapter = "Interrupts"
+++
CPU exceptions occur in various erroneous situations, for example when accessing an invalid memory address or when dividing by zero. To react to them we have to set up an _interrupt descriptor table_ that provides handler functions. At the end of this post, our kernel will be able to catch [breakpoint exceptions] and to resume normal execution afterwards.
@@ -82,7 +84,7 @@ Don't worry about steps 4 and 5 for now, we will learn about the global descript
## An IDT Type
Instead of creating our own IDT type, we will use the [`InterruptDescriptorTable` struct] of the `x86_64` crate, which looks like this:
-[`InterruptDescriptorTable` struct]: https://docs.rs/x86_64/0.7.5/x86_64/structures/idt/struct.InterruptDescriptorTable.html
+[`InterruptDescriptorTable` struct]: https://docs.rs/x86_64/0.8.1/x86_64/structures/idt/struct.InterruptDescriptorTable.html
``` rust
#[repr(C)]
@@ -113,10 +115,10 @@ pub struct InterruptDescriptorTable {
The fields have the type [`idt::Entry{{ config.extra.subtitle | replace(from=" ", to=" ") | safe }}
{% block header %}{% endblock header %} @@ -39,7 +39,7 @@ diff --git a/blog/templates/second-edition/extra.html b/blog/templates/second-edition/extra.html index 0926bcd2..105ff0be 100644 --- a/blog/templates/second-edition/extra.html +++ b/blog/templates/second-edition/extra.html @@ -4,6 +4,10 @@ {% block title %}{{ page.title }} | {{ config.title }}{% endblock title %} +{% block description -%} +{{ page.summary | safe | striptags }} +{%- endblock description %} + {% block main %}This blog series creates a small operating system in the @@ -21,59 +23,37 @@