From 06011a6317b91b5c2c409a89f25b2145e4610ef3 Mon Sep 17 00:00:00 2001 From: Kenta Date: Mon, 13 Aug 2018 20:02:00 +0900 Subject: [PATCH 01/22] typo fix (#463) --- .../second-edition/posts/02-minimal-rust-kernel/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 200e1c74..997c1ec8 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 @@ -57,7 +57,7 @@ To avoid that every operating system implements its own bootloader, which is onl [Multiboot]: https://wiki.osdev.org/Multiboot [GNU GRUB]: https://en.wikipedia.org/wiki/GNU_GRUB -To make a kernel Multiboot compliant, one just needs to insert a so-called [Multiboot header] at the beginning of the kernel file. This makes it very easy to boot an OS in GRUB. However, GRUB and the the Multiboot standard have some problems too: +To make a kernel Multiboot compliant, one just needs to insert a so-called [Multiboot header] at the beginning of the kernel file. This makes it very easy to boot an OS in GRUB. However, GRUB and the Multiboot standard have some problems too: [Multiboot header]: https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#OS-image-format From 812c981f9b28f99407530a64d72a0180b8fbc3e1 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Mon, 13 Aug 2018 17:07:13 +0200 Subject: [PATCH 02/22] Self-host math picture --- .../03-returning-from-exceptions/index.md | 2 +- .../vector-addition.png | Bin 0 -> 2236 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 blog/content/first-edition/extra/naked-exceptions/03-returning-from-exceptions/vector-addition.png diff --git a/blog/content/first-edition/extra/naked-exceptions/03-returning-from-exceptions/index.md b/blog/content/first-edition/extra/naked-exceptions/03-returning-from-exceptions/index.md index be5421a1..d88f8f78 100644 --- a/blog/content/first-edition/extra/naked-exceptions/03-returning-from-exceptions/index.md +++ b/blog/content/first-edition/extra/naked-exceptions/03-returning-from-exceptions/index.md @@ -429,7 +429,7 @@ When we discussed calling conventions above, we assummed that a x86_64 CPU only However, modern CPUs also have a set of _special purpose registers_, which can be used to improve performance in several use cases. On x86_64, the most important set of special purpose registers are the _multimedia registers_. These registers are larger than the general purpose registers and can be used to speed up audio/video processing or matrix calculations. For example, we could use them to add two 4-dimensional vectors _in a single CPU instruction_: -![`(1,2,3,4) + (5,6,7,8) = (6,8,10,12)`](http://mathurl.com/jz3nvev.png) +![`(1,2,3,4) + (5,6,7,8) = (6,8,10,12)`](vector-addition.png) Such multimedia instructions are called [Single Instruction Multiple Data (SIMD)] instructions, because they simultaneously perform an operation (e.g. addition) on multiple data words. Good compilers are able to transform normal loops into such SIMD code automatically. This process is called [auto-vectorization] and can lead to huge performance improvements. diff --git a/blog/content/first-edition/extra/naked-exceptions/03-returning-from-exceptions/vector-addition.png b/blog/content/first-edition/extra/naked-exceptions/03-returning-from-exceptions/vector-addition.png new file mode 100644 index 0000000000000000000000000000000000000000..2036edfb1545637945e63f6c431eabcff2b4753e GIT binary patch literal 2236 zcmeAS@N?(olHy`uVBq!ia0y~yV3@_gz!1Q}%)r2KEojbn1_lP#0G|-o|Ns9pPz>Y} zm%n6SU=S+_@(X4tn;EkEu9A_!*|biV)$b2pzo_tXqd{!-@>&K42F?PH$YKTtz9S&a zI8~cZnt_4+x2KC^NCxZMsM}(z)dXC9udLWO{qnE>^KZ>;+}X%dbnaE~YiE~)_cx1V zkF^}QexP%M&!jhA9G{{SIG9A8&1Du}{5)%EntRiP*L$3GEqhiT z`t+zuw%kSTdg)yD2m2Y@1bQd+CQ59}So5I5$yxSs#j!_)?=MVQrBF1huT^e8V_U<8 z3fsO7F*n{7q{=+@*cm)&TO8A(Km7JBa~5q7*vHV+mLYP&{KeX-vkw<szMA$wn!k{j~d+TK~c+uDoTht|`dyXGST%HAuc_@GHe>-3|xcOpX%9M4^tr z1vLrVGuxf`mv=Ta8^pOqU5L@seILWlnKJd!nN7RS7H;L6;WYW`EHCwGyWgCDt-JPD zRn)TETNDl(^xS7~BPn>Dluzox3uLj6S9o%Ye67l4GsB+iHG%wj3z+0!?Z@wB@u+-| z*Lt+0qBp|-1^eShUtR8|Gc~`}1eR>PctcYE z%e}4pA23>8JDsX~E33VjPpSQHXv(wO+Z%2$oYUZ_JiA+t;{aDt%2v19xsN9uo)M~& z>6*5$mOH|WIXBW;;rN?vQ=eX8esSr}^NI%`@s8&lZO6o8+e^P(n~=P(ZgN?}SGTDL z?Y>Xf)STRPrslVpz|zRY31T<)9&VC({dISgY@yKS#o7;jip`&zI2_$>&bn-uZ<=Y+ zid2Dg=~YR*vW6S>9Po%q-MK||+VsoI?)?6?tl@Rq_ch0S>M`!(A$+Tj9wYFXD+J=e^?-muV>D*#IMWTM~h7XRnN@R|o zU_8(CBT%Y-twU`4j1x;88#%?q#8||AXBOFTd)(PC!zsVC(b|Q*RXy+Ca#@jM3`QO+ zjLyZoud4OEDH+6{9ohJ}gMS~JXY@-4J$Zo*ZR=f^uR8M7+lzT$&Bfp;`WlTtqbF}s z_IiA=O{OosLUR7esdpqkJmr7ab>{=`CFx#StBI$b-L+jrE*%iv=Do^if_2q-``NqV zKFeOaz94M&imP+B*sqrtt9g<5K0iJwJMflbdF|2*Ol=PqY`nUO&y}yZ$$`E6nsfN; zFNqT_+_Ld-DCM3ZAHCx0qw2nTJkH{d=z@ zW5H49r05fgSr2z@{XD5p%Rbt`qeJA+CX+uV9qBz46AO9m8`}5Hp5b9^x47By<>i zN(%q;EoeMtKl4s__mPhV$youJYA1PT-e>g`s_cKw(6l_M$Bq3??N$$&wk+d%(^oUn zn?PC=);+&udolhq$T%hM*F`L@9{Epmm!5}6?lP6~SQ4fj_A~3CjQadX2Q~_3imguC zG)2Mp&VFu==HA{nis;DH9Ju}9iQ=WUYgN7>nMZEys29I5S8M6jC#zcvbPC;P zZR~Wt)toNxwIY`D<)eSG4sQZG)4NT6W-XNQFG}AosP~Vb>%a2~HLa)aOL~8oGaXD7 zm!GxtWH|TXjVFDk*-z!2^ffTX<<^dRb%AeM8z(Gz8P0vWalZ6Rq0CP&pDZ?#INM@U z_&-j;xzXOsI9^xh_`GeW-xePI{9C1PV%wIED?94V1@`o3OgYac!mgZty!b{id)G$B zw)2mSQtSn0t$kEm!S|hCH{;Q?%L|KYL;o+?nio9vRHa!hgK$%@+P0KXVZNWd0%n(@ z&ucu7m@oB`bGL Date: Mon, 13 Aug 2018 17:09:00 +0200 Subject: [PATCH 03/22] Fix QEMU URLs in appveyor build --- .appveyor.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 5dc1cb53..5f40248e 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -60,10 +60,10 @@ install: - echo %cd% - mkdir "C:\Program Files\qemu" - cd "C:\Program Files\qemu" - - if %target%==i686-pc-windows-msvc appveyor DownloadFile "https://qemu.weilnetz.de/w32/qemu-w32-setup-20180519.exe" -FileName "qemu-setup.exe" - - if %target%==i686-pc-windows-gnu appveyor DownloadFile "https://qemu.weilnetz.de/w32/qemu-w32-setup-20180519.exe" -FileName "qemu-setup.exe" - - if %target%==x86_64-pc-windows-msvc appveyor DownloadFile "https://qemu.weilnetz.de/w64/qemu-w64-setup-20180519.exe" -FileName "qemu-setup.exe" - - if %target%==x86_64-pc-windows-gnu appveyor DownloadFile "https://qemu.weilnetz.de/w64/qemu-w64-setup-20180519.exe" -FileName "qemu-setup.exe" + - if %target%==i686-pc-windows-msvc appveyor DownloadFile "https://qemu.weilnetz.de/w32/2018/qemu-w32-setup-20180801.exe" -FileName "qemu-setup.exe" + - if %target%==i686-pc-windows-gnu appveyor DownloadFile "https://qemu.weilnetz.de/w32/2018/qemu-w32-setup-20180801.exe" -FileName "qemu-setup.exe" + - if %target%==x86_64-pc-windows-msvc appveyor DownloadFile "https://qemu.weilnetz.de/w64/2018/qemu-w64-setup-20180801.exe" -FileName "qemu-setup.exe" + - if %target%==x86_64-pc-windows-gnu appveyor DownloadFile "https://qemu.weilnetz.de/w64/2018/qemu-w64-setup-20180801.exe" -FileName "qemu-setup.exe" - 7z x qemu-setup.exe - set PATH=%PATH%;C:\Program Files\qemu - cd "C:\projects\blog-os" From 91001d915836b84258b630fb1062cf5bc1dd4cfd Mon Sep 17 00:00:00 2001 From: Kazushige Tominaga Date: Tue, 14 Aug 2018 19:57:18 +0900 Subject: [PATCH 04/22] Use `write_string` instead of `write_str` in example code (#462) --- blog/content/second-edition/posts/03-vga-text-buffer/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a1ba4d44..12761e75 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 @@ -347,7 +347,7 @@ pub fn print_something() { }; writer.write_byte(b'H'); - writer.write_str("ello! ").unwrap(); + writer.write_string("ello! "); write!(writer, "The numbers are {} and {}", 42, 1.0/3.0).unwrap(); } ``` From 0bd4fcd99e67135ec7c446225b7dea555a65b6af Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Tue, 14 Aug 2018 13:24:56 +0200 Subject: [PATCH 05/22] Run cargo update --- Cargo.lock | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 860a2f14..5e2f5281 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -22,11 +22,11 @@ version = "0.2.0" dependencies = [ "array-init 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "bootloader_precompiled 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "spin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "volatile 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "x86_64 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "x86_64 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -39,10 +39,11 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "spin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -57,7 +58,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "spin" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -66,7 +67,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "x86_64 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "x86_64 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -79,6 +80,11 @@ name = "ux" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "volatile" version = "0.2.4" @@ -86,7 +92,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "x86_64" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -101,12 +107,13 @@ dependencies = [ "checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" "checksum bootloader_precompiled 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "245362094f3e7e5c801e71646a672c1fa895c033ca47473278e3d99af6300be6" -"checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739" +"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "66481dbeb5e773e7bd85b63cd6042c30786f834338288c5ec4f3742673db360a" -"checksum spin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14db77c5b914df6d6173dda9a3b3f5937bd802934fa5edaf934df06a3491e56f" +"checksum spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "37b5646825922b96b5d7d676b5bb3458a54498e96ed7b0ce09dc43a07038fea4" "checksum uart_16550 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "269f953d8de3226f7c065c589c7b4a3e83d10a419c7c3b5e2e0f197e6acc966e" "checksum usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f70329e2cbe45d6c97a5112daad40c34cd9a4e18edb5a2a18fefeb584d8d25e5" "checksum ux 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53d8df5dd8d07fedccd202de1887d94481fadaea3db70479f459e8163a1fab41" +"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" "checksum volatile 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "54d4343a2df2d65144a874f95950754ee7b7e8594f6027aae8c7d0f4858a3fe8" -"checksum x86_64 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "51b347fd81faca2e19366605a2bb52aa2f0e1572835678e3355b66aab18650e6" +"checksum x86_64 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "466c2002e38edde7ebbaae6656793d4f71596634971c7e8cbf7afa4827968445" From 2a9075d64277579f4a101cb945fc6325bc6a1735 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 1 Oct 2018 16:38:48 +0800 Subject: [PATCH 06/22] Rfc 2070 panic implementation deprecated (#467) * Make changes to code examples. * Explain that panic_implementation has been deprecated * Update attributes in source code. --- .../posts/01-freestanding-rust-binary/index.md | 18 ++++++++---------- .../posts/02-minimal-rust-kernel/index.md | 3 +-- .../posts/03-vga-text-buffer/index.md | 2 +- .../posts/04-unit-testing/index.md | 4 ++-- .../posts/05-integration-tests/index.md | 12 ++++-------- src/bin/test-basic-boot.rs | 3 +-- src/bin/test-exception-breakpoint.rs | 3 +-- ...st-exception-double-fault-stack-overflow.rs | 3 +-- src/bin/test-panic.rs | 3 +-- src/main.rs | 3 +-- 10 files changed, 21 insertions(+), 33 deletions(-) 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 47a6b664..7dd231ff 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 @@ -134,17 +134,19 @@ This sets the panic strategy to `abort` for both the `dev` profile (used for `ca ### Panic Implementation -The `panic_impl` language item defines the function that the compiler should invoke when a [panic] occurs. Instead of providing the language item directly, we can use the [`panic_implementation`] attribute to create a `panic` function: +The `panic_impl` language item defines the function that the compiler should invoke when a [panic] occurs. Instead of providing the language item directly, we can use the [`panic_handler`] attribute to create a `panic` function. This used to take the for [`panic_implementation`], which has been deprecated and replaced by [`panic_handler`]. [`panic_implementation`]: https://github.com/rust-lang/rfcs/blob/master/text/2070-panic-implementation.md#panic_implementation +Note: [`panic_implementation`] has been deprecated, and we now use [`panic_handler`] instead + ```rust // in main.rs use core::panic::PanicInfo; /// This function is called on panic. -#[panic_implementation] +#[panic_handler] #[no_mangle] pub fn panic(_info: &PanicInfo) -> ! { loop {} @@ -157,11 +159,11 @@ The [`PanicInfo` parameter][PanicInfo] contains the file and line where the pani [diverging function]: https://doc.rust-lang.org/book/first-edition/functions.html#diverging-functions [“never” type]: https://doc.rust-lang.org/nightly/std/primitive.never.html -When we try `cargo build` now, we get an error that “#[panic_implementation] is an unstable feature”. +When we try `cargo build` now, we get an error that “#[panic_handler] is an unstable feature”. #### Enabling Unstable Features -The `panic_implementation` attribute was recently added and is thus still unstable and protected by a so-called _feature gate_. A feature gate is a special attribute that you have to specify at the top of your `main.rs` in order to use the corresponding feature. By doing this you basically say: “I know that this feature is unstable and that it might stop working without any warnings. I want to use it anyway.” +The `panic_handler` attribute was recently added and is thus still unstable and protected by a so-called _feature gate_. A feature gate is a special attribute that you have to specify at the top of your `main.rs` in order to use the corresponding feature. By doing this you basically say: “I know that this feature is unstable and that it might stop working without any warnings. I want to use it anyway.” Feature gates are not available in the stable or beta Rust compilers, only [nightly Rust] makes it possible to opt-in. This means that you have to use a nightly compiler for OS development for the near future (until all unstable features that we need are added are stabilized). @@ -171,8 +173,6 @@ To manage Rust installations I highly recommend [rustup]. It allows you to insta [rustup]: https://www.rustup.rs/ -After installing a nightly Rust compiler, you can enable the unstable `panic_implementation` feature by inserting `#![feature(panic_implementation)]` right at the top of `main.rs`. - Now we fixed both language item errors. However, if we try to compile it now, another language item is required: ``` @@ -196,14 +196,13 @@ Our freestanding executable does not have access to the Rust runtime and `crt0`, To tell the Rust compiler that we don't want to use the normal entry point chain, we add the `#![no_main]` attribute. ```rust -#![feature(panic_implementation)] #![no_std] #![no_main] use core::panic::PanicInfo; /// This function is called on panic. -#[panic_implementation] +#[panic_handler] #[no_mangle] pub fn panic(_info: &PanicInfo) -> ! { loop {} @@ -311,14 +310,13 @@ A minimal freestanding Rust binary looks like this: `src/main.rs`: ```rust -#![feature(panic_implementation)] // required for defining the panic handler #![no_std] // don't link the Rust standard library #![no_main] // disable all Rust-level entry points use core::panic::PanicInfo; /// This function is called on panic. -#[panic_implementation] +#[panic_handler] #[no_mangle] pub fn panic(_info: &PanicInfo) -> ! { loop {} 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 997c1ec8..1c43c698 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 @@ -199,14 +199,13 @@ Compiling for our new target will use Linux conventions (I'm not quite sure why, ```rust // src/main.rs -#![feature(panic_implementation)] // required for defining the panic handler #![no_std] // don't link the Rust standard library #![no_main] // disable all Rust-level entry points use core::panic::PanicInfo; /// This function is called on panic. -#[panic_implementation] +#[panic_handler] #[no_mangle] pub fn panic(_info: &PanicInfo) -> ! { loop {} 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 12761e75..c0bd5ddf 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 @@ -627,7 +627,7 @@ Now that we have a `println` macro, we can use it in our panic function to print // in main.rs /// This function is called on panic. -#[panic_implementation] +#[panic_handler] #[no_mangle] pub fn panic(info: &PanicInfo) -> ! { println!("{}", info); diff --git a/blog/content/second-edition/posts/04-unit-testing/index.md b/blog/content/second-edition/posts/04-unit-testing/index.md index cddd015d..14f34959 100644 --- a/blog/content/second-edition/posts/04-unit-testing/index.md +++ b/blog/content/second-edition/posts/04-unit-testing/index.md @@ -37,7 +37,7 @@ error[E0152]: duplicate lang item found: `panic_impl`. = note: first defined in crate `std`. ``` -The problem is that unit tests are built for the host machine, with the `std` library included. This makes sense because they should be able to run as a normal application on the host operating system. Since the standard library has it's own `panic_implementation` function, we get the above error. To fix it, we use [conditional compilation] to include our implementation of the panic handler only in non-test environments: +The problem is that unit tests are built for the host machine, with the `std` library included. This makes sense because they should be able to run as a normal application on the host operating system. Since the standard library has it's own `panic_handler` function, we get the above error. To fix it, we use [conditional compilation] to include our implementation of the panic handler only in non-test environments: [conditional compilation]: https://doc.rust-lang.org/reference/attributes.html#conditional-compilation @@ -48,7 +48,7 @@ The problem is that unit tests are built for the host machine, with the `std` li use core::panic::PanicInfo; #[cfg(not(test))] // only compile when the test flag is not set -#[panic_implementation] +#[panic_handler] #[no_mangle] pub fn panic(info: &PanicInfo) -> ! { println!("{}", info); diff --git a/blog/content/second-edition/posts/05-integration-tests/index.md b/blog/content/second-edition/posts/05-integration-tests/index.md index b75c69d0..87955717 100644 --- a/blog/content/second-edition/posts/05-integration-tests/index.md +++ b/blog/content/second-edition/posts/05-integration-tests/index.md @@ -329,7 +329,6 @@ Cargo allows to add [additional executables] to a project by putting them inside ```rust // src/bin/test-something.rs -#![feature(panic_implementation)] #![no_std] #![cfg_attr(not(test), no_main)] #![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] @@ -344,7 +343,7 @@ pub extern "C" fn _start() -> ! { } #[cfg(not(test))] -#[panic_implementation] +#[panic_handle] #[no_mangle] pub fn panic(_info: &PanicInfo) -> ! { loop {} @@ -402,7 +401,6 @@ pub unsafe fn exit_qemu() { ```rust // src/main.rs -#![feature(panic_implementation)] // required for defining the panic handler #![no_std] // don't link the Rust standard library #![cfg_attr(not(test), no_main)] // disable all Rust-level entry points #![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] @@ -425,7 +423,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] -#[panic_implementation] +#[panic_handler] #[no_mangle] pub fn panic(info: &PanicInfo) -> ! { println!("{}", info); @@ -464,7 +462,6 @@ We are finally able to create our first integration test executable. We start si ```rust // in src/bin/test-basic-boot.rs -#![feature(panic_implementation)] // required for defining the panic handler #![no_std] // don't link the Rust standard library #![cfg_attr(not(test), no_main)] // disable all Rust-level entry points #![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] @@ -490,7 +487,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] -#[panic_implementation] +#[panic_handler] #[no_mangle] pub fn panic(info: &PanicInfo) -> ! { serial_println!("failed"); @@ -531,7 +528,6 @@ To test that our panic handler is really invoked on a panic, we create a `test-p ```rust // in src/bin/test-panic.rs -#![feature(panic_implementation)] #![no_std] #![cfg_attr(not(test), no_main)] #![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] @@ -549,7 +545,7 @@ pub extern "C" fn _start() -> ! { } #[cfg(not(test))] -#[panic_implementation] +#[panic_handler] #[no_mangle] pub fn panic(_info: &PanicInfo) -> ! { serial_println!("ok"); diff --git a/src/bin/test-basic-boot.rs b/src/bin/test-basic-boot.rs index 54f26572..223ca6a4 100644 --- a/src/bin/test-basic-boot.rs +++ b/src/bin/test-basic-boot.rs @@ -1,4 +1,3 @@ -#![feature(panic_implementation)] // required for defining the panic handler #![no_std] // don't link the Rust standard library #![cfg_attr(not(test), no_main)] // disable all Rust-level entry points #![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] @@ -25,7 +24,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] -#[panic_implementation] +#[panic_handler] #[no_mangle] pub fn panic(info: &PanicInfo) -> ! { serial_println!("failed"); diff --git a/src/bin/test-exception-breakpoint.rs b/src/bin/test-exception-breakpoint.rs index 03906cbd..9e3ae7ec 100644 --- a/src/bin/test-exception-breakpoint.rs +++ b/src/bin/test-exception-breakpoint.rs @@ -1,4 +1,3 @@ -#![feature(panic_implementation)] #![feature(abi_x86_interrupt)] #![no_std] #![cfg_attr(not(test), no_main)] @@ -45,7 +44,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] -#[panic_implementation] +#[panic_handler] #[no_mangle] pub fn panic(info: &PanicInfo) -> ! { serial_println!("failed"); diff --git a/src/bin/test-exception-double-fault-stack-overflow.rs b/src/bin/test-exception-double-fault-stack-overflow.rs index 560f8f34..5ed15e41 100644 --- a/src/bin/test-exception-double-fault-stack-overflow.rs +++ b/src/bin/test-exception-double-fault-stack-overflow.rs @@ -1,4 +1,3 @@ -#![feature(panic_implementation)] #![feature(abi_x86_interrupt)] #![no_std] #![cfg_attr(not(test), no_main)] @@ -39,7 +38,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] -#[panic_implementation] +#[panic_handler] #[no_mangle] pub fn panic(info: &PanicInfo) -> ! { serial_println!("failed"); diff --git a/src/bin/test-panic.rs b/src/bin/test-panic.rs index 41b181a3..15075755 100644 --- a/src/bin/test-panic.rs +++ b/src/bin/test-panic.rs @@ -1,4 +1,3 @@ -#![feature(panic_implementation)] #![no_std] #![cfg_attr(not(test), no_main)] #![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] @@ -16,7 +15,7 @@ pub extern "C" fn _start() -> ! { } #[cfg(not(test))] -#[panic_implementation] +#[panic_handler] #[no_mangle] pub fn panic(_info: &PanicInfo) -> ! { serial_println!("ok"); diff --git a/src/main.rs b/src/main.rs index 9b56c433..52059a2a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ -#![feature(panic_implementation)] // required for defining the panic handler #![feature(abi_x86_interrupt)] #![no_std] // don't link the Rust standard library #![cfg_attr(not(test), no_main)] // disable all Rust-level entry points @@ -35,7 +34,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] -#[panic_implementation] +#[panic_handler] #[no_mangle] pub fn panic(info: &PanicInfo) -> ! { println!("{}", info); From 2dd925d34d5e9d36fc8abf21eb97a7500fbfddd3 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Mon, 1 Oct 2018 10:37:55 +0200 Subject: [PATCH 07/22] Don't mention the deprecated panic_implementation It existed only for a very short time, so I think that not many people will remember this attribute. --- .../posts/01-freestanding-rust-binary/index.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) 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 7dd231ff..35a6992c 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 @@ -134,11 +134,7 @@ This sets the panic strategy to `abort` for both the `dev` profile (used for `ca ### Panic Implementation -The `panic_impl` language item defines the function that the compiler should invoke when a [panic] occurs. Instead of providing the language item directly, we can use the [`panic_handler`] attribute to create a `panic` function. This used to take the for [`panic_implementation`], which has been deprecated and replaced by [`panic_handler`]. - -[`panic_implementation`]: https://github.com/rust-lang/rfcs/blob/master/text/2070-panic-implementation.md#panic_implementation - -Note: [`panic_implementation`] has been deprecated, and we now use [`panic_handler`] instead +The `panic_impl` language item defines the function that the compiler should invoke when a [panic] occurs. Instead of providing the language item directly, we can use the [`panic_handler`] attribute to create a `panic` function. ```rust // in main.rs From 6f48a17ba425ae341bd04671c36778e2a6d6f4b8 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Mon, 1 Oct 2018 13:11:39 +0200 Subject: [PATCH 08/22] Pub and no_mangle are no longer required for panic_handler (#468) --- .../01-freestanding-rust-binary/index.md | 23 ++------------- .../posts/02-minimal-rust-kernel/index.md | 29 +++++++++++++++---- .../posts/03-vga-text-buffer/index.md | 3 +- .../posts/04-unit-testing/index.md | 5 ++-- .../posts/05-integration-tests/index.md | 12 +++----- src/bin/test-basic-boot.rs | 3 +- src/bin/test-exception-breakpoint.rs | 3 +- ...t-exception-double-fault-stack-overflow.rs | 3 +- src/bin/test-panic.rs | 3 +- src/main.rs | 3 +- 10 files changed, 39 insertions(+), 48 deletions(-) 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 35a6992c..ce4eb86e 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 @@ -143,8 +143,7 @@ use core::panic::PanicInfo; /// This function is called on panic. #[panic_handler] -#[no_mangle] -pub fn panic(_info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { loop {} } ``` @@ -155,20 +154,6 @@ The [`PanicInfo` parameter][PanicInfo] contains the file and line where the pani [diverging function]: https://doc.rust-lang.org/book/first-edition/functions.html#diverging-functions [“never” type]: https://doc.rust-lang.org/nightly/std/primitive.never.html -When we try `cargo build` now, we get an error that “#[panic_handler] is an unstable feature”. - -#### Enabling Unstable Features - -The `panic_handler` attribute was recently added and is thus still unstable and protected by a so-called _feature gate_. A feature gate is a special attribute that you have to specify at the top of your `main.rs` in order to use the corresponding feature. By doing this you basically say: “I know that this feature is unstable and that it might stop working without any warnings. I want to use it anyway.” - -Feature gates are not available in the stable or beta Rust compilers, only [nightly Rust] makes it possible to opt-in. This means that you have to use a nightly compiler for OS development for the near future (until all unstable features that we need are added are stabilized). - -[nightly Rust]: https://doc.rust-lang.org/book/first-edition/release-channels.html - -To manage Rust installations I highly recommend [rustup]. It allows you to install nightly, beta, and stable compilers side-by-side and makes it easy to update them. To use a nightly compiler for the current directory, you can run `rustup override add nightly`. Alternatively, you can add a file called `rust-toolchain` with the content `nightly` to the project's root directory. - -[rustup]: https://www.rustup.rs/ - Now we fixed both language item errors. However, if we try to compile it now, another language item is required: ``` @@ -199,8 +184,7 @@ use core::panic::PanicInfo; /// This function is called on panic. #[panic_handler] -#[no_mangle] -pub fn panic(_info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { loop {} } ``` @@ -313,8 +297,7 @@ use core::panic::PanicInfo; /// This function is called on panic. #[panic_handler] -#[no_mangle] -pub fn panic(_info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { loop {} } 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 1c43c698..b61e1e39 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 @@ -206,8 +206,7 @@ use core::panic::PanicInfo; /// This function is called on panic. #[panic_handler] -#[no_mangle] -pub fn panic(_info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { loop {} } @@ -238,7 +237,7 @@ It fails! The error tells us that the Rust compiler no longer finds the `core` o The problem is that the core library is distributed together with the Rust compiler as a _precompiled_ library. So it is only valid for supported host triples (e.g., `x86_64-unknown-linux-gnu`) but not for our custom target. If we want to compile code for other targets, we need to recompile `core` for these targets first. #### Cargo xbuild -That's where [`cargo xbuild`] comes in. It is a wrapper for `cargo build` that automatically cross-compiles the built-in libraries. We can install it by executing: +That's where [`cargo xbuild`] comes in. It is a wrapper for `cargo build` that automatically cross-compiles `core` and other built-in libraries. We can install it by executing: [`cargo xbuild`]: https://github.com/rust-osdev/cargo-xbuild @@ -248,7 +247,27 @@ cargo install cargo-xbuild The command depends on the rust source code, which we can install with `rustup component add rust-src`. -We now can rerun the above command with `xbuild` instead of `build`: +Now we can rerun the above command with `xbuild` instead of `build`: + +``` +> cargo xbuild --target x86_64-blog_os.json +``` + +Depending on your version of the Rust compiler you might get the following error: + +``` +error: The sysroot can't be built for the Stable channel. Switch to nightly. +``` + +To understand this error, you need to know that the Rust compiler has three release channels: _stable_, _beta_, and _nightly_. The Rust Book explains the difference between these channels really well, so take a minute and [check it out](https://doc.rust-lang.org/book/second-edition/appendix-07-nightly-rust.html#choo-choo-release-channels-and-riding-the-trains). + +Some experimental features are only available on the nightly channel. Since Rust uses many of these features for the internal implementation of `core` and other built-in libraries, we need to use a nightly compiler when invoking `cargo xbuild` (since it rebuilds these libraries). + +To manage Rust installations I highly recommend [rustup]. It allows you to install nightly, beta, and stable compilers side-by-side and makes it easy to update them. With rustup you can use a nightly compiler for the current directory by running `rustup override add nightly`. Alternatively, you can add a file called `rust-toolchain` with the content `nightly` to the project's root directory. + +[rustup]: https://www.rustup.rs/ + +With a nightly compiler the build finally succeeds: ``` > cargo xbuild --target x86_64-blog_os.json @@ -260,7 +279,7 @@ We now can rerun the above command with `xbuild` instead of `build`: Finished dev [unoptimized + debuginfo] target(s) in 0.29 secs ``` -It worked! We see that `cargo xbuild` cross-compiled the `core`, `compiler_builtin`, and `alloc` libraries for our new custom target and then continued to compile our `blog_os` crate. +We see that `cargo xbuild` cross-compiled the `core`, `compiler_builtin`, and `alloc` libraries for our new custom target and then continued to compile our `blog_os` crate. Now we are able to build our kernel for a bare metal target. However, our `_start` entry point, which will be called by the boot loader, is still empty. So let's output something to screen from it. 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 c0bd5ddf..0c4e9bed 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 @@ -628,8 +628,7 @@ Now that we have a `println` macro, we can use it in our panic function to print /// This function is called on panic. #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { println!("{}", info); loop {} } diff --git a/blog/content/second-edition/posts/04-unit-testing/index.md b/blog/content/second-edition/posts/04-unit-testing/index.md index 14f34959..7d6f80cc 100644 --- a/blog/content/second-edition/posts/04-unit-testing/index.md +++ b/blog/content/second-edition/posts/04-unit-testing/index.md @@ -28,7 +28,7 @@ Unfortunately it's a bit more complicated for `no_std` applications such as our error[E0152]: duplicate lang item found: `panic_impl`. --> src/main.rs:35:1 | -35 | / pub fn panic(info: &PanicInfo) -> ! { +35 | / fn panic(info: &PanicInfo) -> ! { 36 | | println!("{}", info); 37 | | loop {} 38 | | } @@ -49,8 +49,7 @@ use core::panic::PanicInfo; #[cfg(not(test))] // only compile when the test flag is not set #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { println!("{}", info); loop {} } diff --git a/blog/content/second-edition/posts/05-integration-tests/index.md b/blog/content/second-edition/posts/05-integration-tests/index.md index 87955717..083d6c9a 100644 --- a/blog/content/second-edition/posts/05-integration-tests/index.md +++ b/blog/content/second-edition/posts/05-integration-tests/index.md @@ -344,8 +344,7 @@ pub extern "C" fn _start() -> ! { #[cfg(not(test))] #[panic_handle] -#[no_mangle] -pub fn panic(_info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { loop {} } ``` @@ -424,8 +423,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { println!("{}", info); loop {} } @@ -488,8 +486,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { serial_println!("failed"); serial_println!("{}", info); @@ -546,8 +543,7 @@ pub extern "C" fn _start() -> ! { #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(_info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { serial_println!("ok"); unsafe { exit_qemu(); } diff --git a/src/bin/test-basic-boot.rs b/src/bin/test-basic-boot.rs index 223ca6a4..9b891aad 100644 --- a/src/bin/test-basic-boot.rs +++ b/src/bin/test-basic-boot.rs @@ -25,8 +25,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { serial_println!("failed"); serial_println!("{}", info); diff --git a/src/bin/test-exception-breakpoint.rs b/src/bin/test-exception-breakpoint.rs index 9e3ae7ec..e6150acf 100644 --- a/src/bin/test-exception-breakpoint.rs +++ b/src/bin/test-exception-breakpoint.rs @@ -45,8 +45,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { serial_println!("failed"); serial_println!("{}", info); diff --git a/src/bin/test-exception-double-fault-stack-overflow.rs b/src/bin/test-exception-double-fault-stack-overflow.rs index 5ed15e41..876e4486 100644 --- a/src/bin/test-exception-double-fault-stack-overflow.rs +++ b/src/bin/test-exception-double-fault-stack-overflow.rs @@ -39,8 +39,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { serial_println!("failed"); serial_println!("{}", info); diff --git a/src/bin/test-panic.rs b/src/bin/test-panic.rs index 15075755..64131b86 100644 --- a/src/bin/test-panic.rs +++ b/src/bin/test-panic.rs @@ -16,8 +16,7 @@ pub extern "C" fn _start() -> ! { #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(_info: &PanicInfo) -> ! { +fn panic(_info: &PanicInfo) -> ! { serial_println!("ok"); unsafe { diff --git a/src/main.rs b/src/main.rs index 52059a2a..bb7e1a92 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,8 +35,7 @@ pub extern "C" fn _start() -> ! { /// This function is called on panic. #[cfg(not(test))] #[panic_handler] -#[no_mangle] -pub fn panic(info: &PanicInfo) -> ! { +fn panic(info: &PanicInfo) -> ! { println!("{}", info); loop {} } From 23e35b8d9b6f6f12b2673d0c4f0a11dfb8a7d1b7 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Sun, 7 Oct 2018 15:26:53 +0200 Subject: [PATCH 09/22] Fix typo in code example Closes #470 --- blog/content/second-edition/posts/05-integration-tests/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/content/second-edition/posts/05-integration-tests/index.md b/blog/content/second-edition/posts/05-integration-tests/index.md index 083d6c9a..04ac347b 100644 --- a/blog/content/second-edition/posts/05-integration-tests/index.md +++ b/blog/content/second-edition/posts/05-integration-tests/index.md @@ -343,7 +343,7 @@ pub extern "C" fn _start() -> ! { } #[cfg(not(test))] -#[panic_handle] +#[panic_handler] fn panic(_info: &PanicInfo) -> ! { loop {} } From 4538b2fb2189f22a7151337e656b635cbd784a12 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Tue, 9 Oct 2018 13:01:33 +0200 Subject: [PATCH 10/22] Add rel=canonical link to all pages --- blog/templates/second-edition/base.html | 1 + 1 file changed, 1 insertion(+) diff --git a/blog/templates/second-edition/base.html b/blog/templates/second-edition/base.html index fb587d6b..913377a7 100644 --- a/blog/templates/second-edition/base.html +++ b/blog/templates/second-edition/base.html @@ -9,6 +9,7 @@ + From 4e82b638168911d36e6191fb63e0f481eb745d1d Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Tue, 9 Oct 2018 15:40:28 +0200 Subject: [PATCH 11/22] Add fathom tracking script --- blog/templates/first-edition/base.html | 15 +++++++++++++++ blog/templates/second-edition/base.html | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/blog/templates/first-edition/base.html b/blog/templates/first-edition/base.html index a4012f0e..aed4c87c 100644 --- a/blog/templates/first-edition/base.html +++ b/blog/templates/first-edition/base.html @@ -54,6 +54,21 @@ })(); + + + + diff --git a/blog/templates/second-edition/base.html b/blog/templates/second-edition/base.html index 913377a7..e877cf94 100644 --- a/blog/templates/second-edition/base.html +++ b/blog/templates/second-edition/base.html @@ -55,6 +55,21 @@ })(); + + + + From b30c3f653e220849e4ceb1b69fd7afdb0709128e Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Sun, 14 Oct 2018 16:18:55 +0200 Subject: [PATCH 12/22] minimal-rust-kernel: typo (#472) --- .../second-edition/posts/02-minimal-rust-kernel/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 b61e1e39..2e2758f0 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 @@ -6,7 +6,7 @@ date = 2018-02-10 template = "second-edition/page.html" +++ -In this post we create a minimal 64-bit Rust kernel for the x86 architecture. We built upon the [freestanding Rust binary] from the previous post to create a bootable disk image, that prints something to the screen. +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. [freestanding Rust binary]: ./second-edition/posts/01-freestanding-rust-binary/index.md From 36d56438a21e54576523a8fbfcaeff118cfd48de Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Sun, 14 Oct 2018 16:19:25 +0200 Subject: [PATCH 13/22] freestanding-rust-binary: small improves (#471) --- .../second-edition/posts/01-freestanding-rust-binary/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 ce4eb86e..1765b450 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 @@ -194,7 +194,7 @@ You might notice that we removed the `main` function. The reason is that a `main The entry point convention depends on your operating system. I recommend you to read the Linux section even if you're on a different OS because we will use this convention for our kernel. #### Linux -On Linux, the default entry point is called `_start`. The linker just looks for a function with that name and sets this function as entry point the executable. So to overwrite the entry point, we define our own `_start` function: +On Linux, the default entry point is called `_start`. The linker just looks for a function with that name and sets this function as entry point to the executable. So, to overwrite the entry point, we define our own `_start` function: ```rust #[no_mangle] From a198de6d1f9c28082273f065f044d5385cc03d9f Mon Sep 17 00:00:00 2001 From: acheronfail Date: Wed, 17 Oct 2018 22:40:29 +1100 Subject: [PATCH 14/22] fix minor typo (#474) --- blog/content/news/2018-03-09-pure-rust.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/content/news/2018-03-09-pure-rust.md b/blog/content/news/2018-03-09-pure-rust.md index 4da4bed0..85798680 100644 --- a/blog/content/news/2018-03-09-pure-rust.md +++ b/blog/content/news/2018-03-09-pure-rust.md @@ -29,7 +29,7 @@ The [first edition] required several C-tools for building: [linker script]: http://www.scoberlin.de/content/media/http/informatik/gcc_docs/ld_3.html [`make`]: https://www.gnu.org/software/make/ -We got lots of feedback that this setup was difficult to get to run [under macOS] and Windows. As a workaround, we [added support for docker], but that still required users to install and understand an additional dependency. So when we decided to create a second edition of the blog, originally because the order of posts led to jumps in difficulty, we thought about how we could avoid these C-dependencies. +We got lots of feedback that this setup was difficult to get running [under macOS] and Windows. As a workaround, we [added support for docker], but that still required users to install and understand an additional dependency. So when we decided to create a second edition of the blog - originally because the order of posts led to jumps in difficulty - we thought about how we could avoid these C-dependencies. [under macOS]: https://github.com/phil-opp/blog_os/issues/55 [added support for docker]: https://github.com/phil-opp/blog_os/pull/373 From 206fb7cc8a82a86aff4ce0d699b4663d8c4a7add Mon Sep 17 00:00:00 2001 From: acheronfail Date: Thu, 18 Oct 2018 08:21:58 +1100 Subject: [PATCH 15/22] refactor exception code into interrupts.rs --- .../posts/06-cpu-exceptions/index.md | 49 ++++++++++++++----- .../posts/07-double-faults/index.md | 14 +++--- src/interrupts.rs | 32 ++++++++++++ src/lib.rs | 7 ++- src/main.rs | 35 +------------ 5 files changed, 84 insertions(+), 53 deletions(-) create mode 100644 src/interrupts.rs diff --git a/blog/content/second-edition/posts/06-cpu-exceptions/index.md b/blog/content/second-edition/posts/06-cpu-exceptions/index.md index 25c2891b..1b57b8c3 100644 --- a/blog/content/second-edition/posts/06-cpu-exceptions/index.md +++ b/blog/content/second-edition/posts/06-cpu-exceptions/index.md @@ -207,7 +207,11 @@ If you are interested in more details: We also have a series of posts that expla Now that we've understood the theory, it's time to handle CPU exceptions in our kernel. We start by creating an `init_idt` function that creates a new `InterruptDescriptorTable`: ``` rust -// in src/main.rs +// in src/lib.rs + +pub mod interrupts; + +// in src/interrupts.rs extern crate x86_64; use x86_64::structures::idt::InterruptDescriptorTable; @@ -228,7 +232,7 @@ The breakpoint exception is commonly used in debuggers: When the user sets a bre For our use case, we don't need to overwrite any instructions. Instead, we just want to print a message when the breakpoint instruction is executed and then continue the program. So let's create a simple `breakpoint_handler` function and add it to our IDT: ```rust -/// in src/main.rs +// in src/interrupts.rs use x86_64::structures::idt::{InterruptDescriptorTable, ExceptionStackFrame}; @@ -246,7 +250,7 @@ extern "x86-interrupt" fn breakpoint_handler( Our handler just outputs a message and pretty-prints the exception stack frame. -When we try to compile it, the following error occurs: +When we try to compile it, the following errors occur: ``` error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue #40180) @@ -260,7 +264,33 @@ error[E0658]: x86-interrupt ABI is experimental and subject to change (see issue = help: add #![feature(abi_x86_interrupt)] to the crate attributes to enable ``` -This error occurs because the `x86-interrupt` calling convention is still unstable. To use it anyway, we have to explicitly enable it by adding `#![feature(abi_x86_interrupt)]` on the top of our `main.rs`. +This error occurs because the `x86-interrupt` calling convention is still unstable. To use it anyway, we have to explicitly enable it by adding `#![feature(abi_x86_interrupt)]` on the top of our `lib.rs`. + +``` +error: cannot find macro `println!` in this scope + --> src/interrupts.rs:40:5 + | +40 | println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); + | ^^^^^^^ + | + = help: have you added the `#[macro_use]` on the module/import? +``` + +And this error occurs because the `print!` and `println!` macros we created in the `vga_buffer` _must be defined_ before we use them. This is one case where import order matters in Rust. We can easily fix this by ensuring the order of our imports places the macros first: + +```rust +// in src/lib.rs + +#[macro_use] +pub mod vga_buffer; // import this before other modules so its macros may be used +pub mod gdt; +pub mod interrupts; +pub mod serial; +``` + +Now we can use our `print!` and `println!` macros in `interrupts.rs`. If you'd like to know more about the ins and outs of macros and how they differ from functions [you can find more information here](in-depth-rust-macros). + +[in-depth-rust-macros]: https://doc.rust-lang.org/book/second-edition/appendix-04-macros.html ### Loading the IDT In order that the CPU uses our new interrupt descriptor table, we need to load it using the [`lidt`] instruction. The `InterruptDescriptorTable` struct of the `x86_64` provides a [`load`][InterruptDescriptorTable::load] method function for that. Let's try to use it: @@ -269,7 +299,7 @@ In order that the CPU uses our new interrupt descriptor table, we need to load i [InterruptDescriptorTable::load]: https://docs.rs/x86_64/0.2.8/x86_64/structures/idt/struct.InterruptDescriptorTable.html#method.load ```rust -// in src/main.rs +// in src/interrupts.rs pub fn init_idt() { let mut idt = InterruptDescriptorTable::new(); @@ -339,10 +369,7 @@ We already imported the `lazy_static` crate when we [created an abstraction for [vga text buffer lazy static]: ./second-edition/posts/03-vga-text-buffer/index.md#lazy-statics ```rust -// in src/main.rs - -#[macro_use] -extern crate lazy_static; +// in src/interrupts.rs lazy_static! { static ref IDT: InterruptDescriptorTable = { @@ -370,7 +397,7 @@ Now we should be able to handle breakpoint exceptions! Let's try it in our `_sta pub extern "C" fn _start() -> ! { println!("Hello World{}", "!"); - init_idt(); + blog_os::interrupts::init_idt(); // invoke a breakpoint exception x86_64::instructions::int3(); @@ -403,7 +430,7 @@ static BREAKPOINT_HANDLER_CALLED: AtomicUsize = AtomicUsize::new(0); #[cfg(not(test))] #[no_mangle] pub extern "C" fn _start() -> ! { - init_idt(); + blog_os::interrupts::init_idt(); // invoke a breakpoint exception x86_64::instructions::int3(); diff --git a/blog/content/second-edition/posts/07-double-faults/index.md b/blog/content/second-edition/posts/07-double-faults/index.md index 39466694..fc7ff6d5 100644 --- a/blog/content/second-edition/posts/07-double-faults/index.md +++ b/blog/content/second-edition/posts/07-double-faults/index.md @@ -33,7 +33,7 @@ Let's provoke a double fault by triggering an exception for that we didn't defin pub extern "C" fn _start() -> ! { println!("Hello World{}", "!"); - init_idt(); + blog_os::interrupts::init_idt(); // trigger a page fault unsafe { @@ -60,7 +60,7 @@ So in order to prevent this triple fault, we need to either provide a handler fu A double fault is a normal exception with an error code, so we can specify a handler function similar to our breakpoint handler: ```rust -// in src/main.rs +// in src/interrupts.rs lazy_static! { static ref IDT: InterruptDescriptorTable = { @@ -162,7 +162,7 @@ Let's try it ourselves! We can easily provoke a kernel stack overflow by calling pub extern "C" fn _start() -> ! { println!("Hello World{}", "!"); - init_idt(); + blog_os::interrupts::init_idt(); fn stack_overflow() { stack_overflow(); // for each recursion, the return address is pushed @@ -314,7 +314,7 @@ pub extern "C" fn _start() -> ! { println!("Hello World{}", "!"); blog_os::gdt::init(); - init_idt(); + blog_os::interrupts::init_idt(); […] } @@ -380,7 +380,9 @@ We reload the code segment register using [`set_cs`] and to load the TSS using [ 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: ```rust -// in src/main.rs +// in src/interrupts.rs + +use gdt; lazy_static! { static ref IDT: InterruptDescriptorTable = { @@ -388,7 +390,7 @@ lazy_static! { idt.breakpoint.set_handler_fn(breakpoint_handler); unsafe { idt.double_fault.set_handler_fn(double_fault_handler) - .set_stack_index(blog_os::gdt::DOUBLE_FAULT_IST_INDEX); // new + .set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX); // new } idt diff --git a/src/interrupts.rs b/src/interrupts.rs new file mode 100644 index 00000000..be035e4b --- /dev/null +++ b/src/interrupts.rs @@ -0,0 +1,32 @@ +use x86_64::structures::idt::{ExceptionStackFrame, InterruptDescriptorTable}; +use gdt; + +lazy_static! { + static ref IDT: InterruptDescriptorTable = { + let mut idt = InterruptDescriptorTable::new(); + idt.breakpoint.set_handler_fn(breakpoint_handler); + unsafe { + idt.double_fault + .set_handler_fn(double_fault_handler) + .set_stack_index(gdt::DOUBLE_FAULT_IST_INDEX); + } + + idt + }; +} + +pub fn init_idt() { + IDT.load(); +} + +extern "x86-interrupt" fn breakpoint_handler(stack_frame: &mut ExceptionStackFrame) { + println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); +} + +extern "x86-interrupt" fn double_fault_handler( + stack_frame: &mut ExceptionStackFrame, + _error_code: u64, +) { + println!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); + loop {} +} diff --git a/src/lib.rs b/src/lib.rs index 86ef1bc1..961ae1d9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ #![no_std] // don't link the Rust standard library +#![feature(abi_x86_interrupt)] extern crate bootloader_precompiled; extern crate spin; @@ -13,9 +14,11 @@ extern crate array_init; #[cfg(test)] extern crate std; -pub mod gdt; -pub mod serial; +#[macro_use] pub mod vga_buffer; +pub mod gdt; +pub mod interrupts; +pub mod serial; pub unsafe fn exit_qemu() { use x86_64::instructions::port::Port; diff --git a/src/main.rs b/src/main.rs index bb7e1a92..65154cfb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ -#![feature(abi_x86_interrupt)] #![no_std] // don't link the Rust standard library #![cfg_attr(not(test), no_main)] // disable all Rust-level entry points #![cfg_attr(test, allow(dead_code, unused_macros, unused_imports))] @@ -19,7 +18,7 @@ pub extern "C" fn _start() -> ! { println!("Hello World{}", "!"); blog_os::gdt::init(); - init_idt(); + blog_os::interrupts::init_idt(); fn stack_overflow() { stack_overflow(); // for each recursion, the return address is pushed @@ -39,35 +38,3 @@ fn panic(info: &PanicInfo) -> ! { println!("{}", info); loop {} } - -use x86_64::structures::idt::{ExceptionStackFrame, InterruptDescriptorTable}; - -lazy_static! { - static ref IDT: InterruptDescriptorTable = { - let mut idt = InterruptDescriptorTable::new(); - idt.breakpoint.set_handler_fn(breakpoint_handler); - unsafe { - idt.double_fault - .set_handler_fn(double_fault_handler) - .set_stack_index(blog_os::gdt::DOUBLE_FAULT_IST_INDEX); - } - - idt - }; -} - -pub fn init_idt() { - IDT.load(); -} - -extern "x86-interrupt" fn breakpoint_handler(stack_frame: &mut ExceptionStackFrame) { - println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame); -} - -extern "x86-interrupt" fn double_fault_handler( - stack_frame: &mut ExceptionStackFrame, - _error_code: u64, -) { - println!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); - loop {} -} From 61397dbb07e13386ac91fb1133325851fdfe019d Mon Sep 17 00:00:00 2001 From: acheronfail Date: Thu, 18 Oct 2018 08:59:30 +1100 Subject: [PATCH 16/22] feedback: mention creating a new interrupts module --- blog/content/second-edition/posts/06-cpu-exceptions/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blog/content/second-edition/posts/06-cpu-exceptions/index.md b/blog/content/second-edition/posts/06-cpu-exceptions/index.md index 1b57b8c3..0d76dc61 100644 --- a/blog/content/second-edition/posts/06-cpu-exceptions/index.md +++ b/blog/content/second-edition/posts/06-cpu-exceptions/index.md @@ -204,7 +204,7 @@ If you are interested in more details: We also have a series of posts that expla [too-much-magic]: #too-much-magic ## Implementation -Now that we've understood the theory, it's time to handle CPU exceptions in our kernel. We start by creating an `init_idt` function that creates a new `InterruptDescriptorTable`: +Now that we've understood the theory, it's time to handle CPU exceptions in our kernel. We'll start by creating a new interrupts module in `src/interrupts.rs`, that first creates an `init_idt` function that creates a new `InterruptDescriptorTable`: ``` rust // in src/lib.rs From e3d742c928cfdd2a36e5ffe0e36141eef56d053a Mon Sep 17 00:00:00 2001 From: acheronfail Date: Thu, 18 Oct 2018 14:16:17 +1100 Subject: [PATCH 17/22] remove unused crate from main.rs --- src/main.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 65154cfb..b34592c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,8 +5,6 @@ #[macro_use] extern crate blog_os; extern crate x86_64; -#[macro_use] -extern crate lazy_static; use core::panic::PanicInfo; From 168e2b3d89bca07d2b48115be84eee3d90db8547 Mon Sep 17 00:00:00 2001 From: acheronfail Date: Thu, 18 Oct 2018 18:46:36 +1100 Subject: [PATCH 18/22] feedback: add explanation for adding #[macro_use] before import --- .../posts/06-cpu-exceptions/index.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/blog/content/second-edition/posts/06-cpu-exceptions/index.md b/blog/content/second-edition/posts/06-cpu-exceptions/index.md index 0d76dc61..09df2803 100644 --- a/blog/content/second-edition/posts/06-cpu-exceptions/index.md +++ b/blog/content/second-edition/posts/06-cpu-exceptions/index.md @@ -276,7 +276,19 @@ error: cannot find macro `println!` in this scope = help: have you added the `#[macro_use]` on the module/import? ``` -And this error occurs because the `print!` and `println!` macros we created in the `vga_buffer` _must be defined_ before we use them. This is one case where import order matters in Rust. We can easily fix this by ensuring the order of our imports places the macros first: +This happened because we forgot to add `#[macro_use]` before our import of the `vga_buffer` module. + +```rust +// in src/lib.rs + +pub mod gdt; +pub mod interrupts; +pub mod serial; +#[macro_use] // new +pub mod vga_buffer; +``` + +However, after adding `#[macro_use]` before the module import, we still get the same error. Sometimes this can be confusing, but it's actually a quirk of how Rust's macro system works. Macros _must be defined_ before you can use them. This is one case where import order matters in Rust. We can easily fix this by ensuring the order of our imports places the macros first: ```rust // in src/lib.rs From da09ad33620c2a68f61d51be34868599e27d9492 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Thu, 18 Oct 2018 13:50:00 +0200 Subject: [PATCH 19/22] Clarify that the exceptions tests use their own IDT --- .../posts/06-cpu-exceptions/index.md | 26 ++++++++++++++----- src/bin/test-exception-breakpoint.rs | 8 +++--- ...t-exception-double-fault-stack-overflow.rs | 8 +++--- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/blog/content/second-edition/posts/06-cpu-exceptions/index.md b/blog/content/second-edition/posts/06-cpu-exceptions/index.md index 09df2803..3ba15a9c 100644 --- a/blog/content/second-edition/posts/06-cpu-exceptions/index.md +++ b/blog/content/second-edition/posts/06-cpu-exceptions/index.md @@ -434,15 +434,14 @@ Let's create an integration test that ensures that the above continues to work. ```rust // in src/bin/test-exception-breakpoint.rs -use blog_os::exit_qemu; +[…] use core::sync::atomic::{AtomicUsize, Ordering}; static BREAKPOINT_HANDLER_CALLED: AtomicUsize = AtomicUsize::new(0); -#[cfg(not(test))] #[no_mangle] pub extern "C" fn _start() -> ! { - blog_os::interrupts::init_idt(); + init_test_idt(); // invoke a breakpoint exception x86_64::instructions::int3(); @@ -463,16 +462,31 @@ pub extern "C" fn _start() -> ! { loop {} } -extern "x86-interrupt" fn breakpoint_handler(_: &mut ExceptionStackFrame) { + +lazy_static! { + static ref TEST_IDT: InterruptDescriptorTable = { + let mut idt = InterruptDescriptorTable::new(); + idt.breakpoint.set_handler_fn(breakpoint_handler); + idt + }; +} + +pub fn init_test_idt() { + TEST_IDT.load(); +} + +extern "x86-interrupt" fn breakpoint_handler( + _stack_frame: &mut ExceptionStackFrame) +{ BREAKPOINT_HANDLER_CALLED.fetch_add(1, Ordering::SeqCst); } -// […] +[…] ``` For space reasons we don't show the full content here. You can find the full file [on Github](https://github.com/phil-opp/blog_os/blob/master/src/bin/test-exception-breakpoint.rs). -It is basically a copy of our `main.rs` with some modifications to `_start` and `breakpoint_handler`. The most interesting part is the `BREAKPOINT_HANDLER_CALLER` static. It is an [`AtomicUsize`], an integer type that can be safely concurrently modifies because all of its operations are atomic. We increment it when the `breakpoint_handler` is called and verify in our `_start` function that the handler was called exactly once. +It is similar to our `main.rs`, but uses a custom IDT called `TEST_IDT` and different `_start` and `breakpoint_handler` functions. The most interesting part is the `BREAKPOINT_HANDLER_CALLER` static. It is an [`AtomicUsize`], an integer type that can be safely concurrently modifies because all of its operations are atomic. We increment it when the `breakpoint_handler` is called and verify in our `_start` function that the handler was called exactly once. [`AtomicUsize`]: https://doc.rust-lang.org/core/sync/atomic/struct.AtomicUsize.html diff --git a/src/bin/test-exception-breakpoint.rs b/src/bin/test-exception-breakpoint.rs index e6150acf..f9de1543 100644 --- a/src/bin/test-exception-breakpoint.rs +++ b/src/bin/test-exception-breakpoint.rs @@ -18,7 +18,7 @@ static BREAKPOINT_HANDLER_CALLED: AtomicUsize = AtomicUsize::new(0); #[cfg(not(test))] #[no_mangle] pub extern "C" fn _start() -> ! { - init_idt(); + init_test_idt(); // invoke a breakpoint exception x86_64::instructions::int3(); @@ -59,15 +59,15 @@ fn panic(info: &PanicInfo) -> ! { use x86_64::structures::idt::{ExceptionStackFrame, InterruptDescriptorTable}; lazy_static! { - static ref IDT: InterruptDescriptorTable = { + static ref TEST_IDT: InterruptDescriptorTable = { let mut idt = InterruptDescriptorTable::new(); idt.breakpoint.set_handler_fn(breakpoint_handler); idt }; } -pub fn init_idt() { - IDT.load(); +pub fn init_test_idt() { + TEST_IDT.load(); } extern "x86-interrupt" fn breakpoint_handler(_stack_frame: &mut ExceptionStackFrame) { diff --git a/src/bin/test-exception-double-fault-stack-overflow.rs b/src/bin/test-exception-double-fault-stack-overflow.rs index 876e4486..30125c86 100644 --- a/src/bin/test-exception-double-fault-stack-overflow.rs +++ b/src/bin/test-exception-double-fault-stack-overflow.rs @@ -17,7 +17,7 @@ use core::panic::PanicInfo; #[allow(unconditional_recursion)] pub extern "C" fn _start() -> ! { blog_os::gdt::init(); - init_idt(); + init_test_idt(); fn stack_overflow() { stack_overflow(); // for each recursion, the return address is pushed @@ -53,7 +53,7 @@ fn panic(info: &PanicInfo) -> ! { use x86_64::structures::idt::{ExceptionStackFrame, InterruptDescriptorTable}; lazy_static! { - static ref IDT: InterruptDescriptorTable = { + static ref TEST_IDT: InterruptDescriptorTable = { let mut idt = InterruptDescriptorTable::new(); unsafe { idt.double_fault @@ -65,8 +65,8 @@ lazy_static! { }; } -pub fn init_idt() { - IDT.load(); +pub fn init_test_idt() { + TEST_IDT.load(); } extern "x86-interrupt" fn double_fault_handler( From a80ae0d06a748874129b9af767e7ad82fb800023 Mon Sep 17 00:00:00 2001 From: acheronfail Date: Thu, 18 Oct 2018 22:57:37 +1100 Subject: [PATCH 20/22] feedback: fix some typos --- blog/content/second-edition/posts/06-cpu-exceptions/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blog/content/second-edition/posts/06-cpu-exceptions/index.md b/blog/content/second-edition/posts/06-cpu-exceptions/index.md index 09df2803..9fd6303a 100644 --- a/blog/content/second-edition/posts/06-cpu-exceptions/index.md +++ b/blog/content/second-edition/posts/06-cpu-exceptions/index.md @@ -300,7 +300,7 @@ pub mod interrupts; pub mod serial; ``` -Now we can use our `print!` and `println!` macros in `interrupts.rs`. If you'd like to know more about the ins and outs of macros and how they differ from functions [you can find more information here](in-depth-rust-macros). +Now we can use our `print!` and `println!` macros in `interrupts.rs`. If you'd like to know more about the ins and outs of macros and how they differ from functions [you can find more information here][in-depth-rust-macros]. [in-depth-rust-macros]: https://doc.rust-lang.org/book/second-edition/appendix-04-macros.html @@ -442,7 +442,7 @@ static BREAKPOINT_HANDLER_CALLED: AtomicUsize = AtomicUsize::new(0); #[cfg(not(test))] #[no_mangle] pub extern "C" fn _start() -> ! { - blog_os::interrupts::init_idt(); + init_idt(); // invoke a breakpoint exception x86_64::instructions::int3(); From 15c3925b1e1cbfde9b6c76c01e5d3ee62ecc23ee Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Wed, 17 Oct 2018 14:46:21 +0200 Subject: [PATCH 21/22] Enable Windows testing under travis --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 1cefdcb2..2f45b772 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,7 @@ rust: os: - linux - osx + - windows cache: cargo: true @@ -31,6 +32,7 @@ addons: install: - if [ $TRAVIS_OS_NAME = osx ]; then brew update; brew install qemu; fi + - if [ $TRAVIS_OS_NAME = windows ]; then wget https://qemu.weilnetz.de/w64/2018/qemu-w64-setup-20180801.exe; 7z x qemu-w64-setup-20180801.exe; fi before_script: - rustup component add rust-src From 00d869952d2c900a69b06eed8c75628a981e9f6a Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Thu, 18 Oct 2018 14:23:41 +0200 Subject: [PATCH 22/22] Only use travis for bors --- bors.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/bors.toml b/bors.toml index e9bb6c7c..574c5632 100644 --- a/bors.toml +++ b/bors.toml @@ -1,5 +1,4 @@ status = [ "continuous-integration/travis-ci/push", - "continuous-integration/appveyor/branch", ] delete_merged_branches = true