From 396076eb750a865096d26d5552e8a52291391301 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Tue, 12 May 2020 16:51:22 -0400 Subject: [PATCH] Most of post-12 --- Cargo.lock | 218 +++++++++++++++++++++++++----------- Cargo.toml | 24 +++- src/allocator.rs | 2 +- src/interrupts.rs | 35 ++---- src/lib.rs | 5 +- src/main.rs | 15 +++ src/memory.rs | 116 +++++++++---------- src/task.rs | 35 ++++++ src/task/keyboard.rs | 81 ++++++++++++++ src/task/simple_executor.rs | 44 ++++++++ 10 files changed, 415 insertions(+), 160 deletions(-) create mode 100644 src/task.rs create mode 100644 src/task/keyboard.rs create mode 100644 src/task/simple_executor.rs diff --git a/Cargo.lock b/Cargo.lock index b5101f2..33eb1cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,12 +1,9 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "array-init" -version = "0.0.4" +name = "autocfg" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "bit_field" @@ -15,37 +12,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "blog_os" version = "0.1.0" dependencies = [ - "bootloader 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bootloader 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", + "conquer-once 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "linked_list_allocator 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "pc-keyboard 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "linked_list_allocator 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "pc-keyboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "pic8259_simple 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uart_16550 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "uart_16550 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "x86_64 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", + "x86_64 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bootloader" -version = "0.8.1" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "cast" -version = "0.2.2" +name = "cfg-if" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "cc" -version = "1.0.45" +name = "conquer-once" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "conquer-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "conquer-util" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -53,6 +61,45 @@ name = "cpuio" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crossbeam-queue" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-core" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-task" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-util" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -63,20 +110,23 @@ dependencies = [ [[package]] name = "linked_list_allocator" -version = "0.6.4" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "spinning_top 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "nodrop" -version = "0.1.13" +name = "lock_api" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "pc-keyboard" -version = "0.3.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -88,34 +138,47 @@ dependencies = [ ] [[package]] -name = "raw-cpuid" -version = "6.1.0" +name = "pin-project" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-internal 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rustc_version" -version = "0.2.3" +name = "pin-project-internal" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "semver" -version = "0.9.0" +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "semver-parser" -version = "0.7.0" +name = "quote" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -124,17 +187,35 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "uart_16550" -version = "0.2.0" +name = "spinning_top" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "x86_64 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "ux" -version = "0.1.3" +name = "syn" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "uart_16550" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "x86_64 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -144,49 +225,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "x86_64" -version = "0.5.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "array-init 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "x86_64" -version = "0.7.5" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "array-init 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] -"checksum array-init 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "23589ecb866b460d3a0f1278834750268c607e8e28a1b982c907219f3178cd72" +"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" "checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" -"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" -"checksum bootloader 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "45dd858bd74a742ec0fe887722952c263abd0825aa8d33a3704917a97d7bd41e" -"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum bootloader 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "152a28c753e229e037e910b4cd4cd16a90c53dd9a67fd751fa304b4b4a03970c" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum conquer-once 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7644600a548ecad74e4a918392af1798f7dd045be610be3203b9e129b4f98f" +"checksum conquer-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "654fb2472cc369d311c547103a1fa81d467bef370ae7a0680f65939895b1182a" "checksum cpuio 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22b8e308ccfc5acf3b82f79c0eac444cf6114cb2ac67a230ca6c177210068daa" +"checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" +"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +"checksum futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" +"checksum futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626" +"checksum futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum linked_list_allocator 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "47314ec1d29aa869ee7cb5a5be57be9b1055c56567d59c3fb6689926743e0bea" -"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum pc-keyboard 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fff50ab09ba31bcebc0669f4e64c0952fae1acdca9e6e0587e68e4e8443808ac" +"checksum linked_list_allocator 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e70e46c13c0e8374c26cec5752e3347ca1087d9711de8f45aa513a7700efd73d" +"checksum lock_api 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +"checksum pc-keyboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48392db76c4e9a69e0b3be356c5f97ebb7b14413c5e4fd0af4755dbf86e2fce" "checksum pic8259_simple 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc64b2fd10828da8521b6cdabe0679385d7d2a3a6d4c336b819d1fa31ba35c72" -"checksum raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "30a9d219c32c9132f7be513c18be77c9881c7107d2ab5569d205a6a0f0e6dc7d" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum pin-project 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)" = "81d480cb4e89522ccda96d0eed9af94180b7a5f93fb28f66e1fd7d68431663d1" +"checksum pin-project-internal 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)" = "a82996f11efccb19b685b14b5df818de31c1edcee3daa256ab5775dd98e72feb" +"checksum pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +"checksum proc-macro2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "8872cf6f48eee44265156c111456a700ab3483686b3f96df4cf5481c89157319" +"checksum quote 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4c1f4b0efa5fc5e8ceb705136bfee52cfdb6a4e3509f770b478cd6ed434232a7" +"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -"checksum uart_16550 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b9392f60931fe3bf8f24e0a15ee4f51528770f1d64c48768ab66571334d95b0" -"checksum ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dfeb711b61ce620c0cb6fd9f8e3e678622f0c971da2a63c4b3e25e88ed012f" +"checksum spinning_top 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32d801a3a53bcf5071f85fef8d5cab9e5f638fc5580a37e6eb7aba4b37438d24" +"checksum syn 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "dd1b5e337360b1fae433c59fcafa0c6b77c605e92540afa5221a7b81a9eca91d" +"checksum uart_16550 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2b5e5e7b79b55e1aa57b0ab994490d876d9c2f5b18c7716628155207e0e4b197" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6af0edf5b4faacc31fc51159244d78d65ec580f021afcef7bd53c04aeabc7f29" -"checksum x86_64 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bb8f09c32a991cc758ebcb9b7984f530095d32578a4e7b85db6ee1f0bbe4c9c6" -"checksum x86_64 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "997837f3913aac8f67164683258756d712376849906c8d609f844084bc03ef84" +"checksum x86_64 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "df453cbef6f9a3f703c1866338da79ae8e98a86f7ccd90bca92e6f1583720941" +"checksum x86_64 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4206b60c9f99766329b66962aa8ddc01df6c7edd02edc046b7a69d5df9fcdbcf" diff --git a/Cargo.toml b/Cargo.toml index 2076b13..6d472bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,17 +7,31 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bootloader = { version = "0.8.1", features = ["map_physical_memory"]} -linked_list_allocator = "0.6.4" -pc-keyboard = "0.3.1" +bootloader = { version = "0.8.0", features = ["map_physical_memory"]} +linked_list_allocator = "0.8.0" +pc-keyboard = "0.5.0" pic8259_simple = "0.1.1" spin = "0.5.2" uart_16550 = "0.2.0" volatile = "0.2.6" -x86_64 = "0.7.5" +x86_64 = "0.9.6" + +[dependencies.conquer-once] +version = "0.2.0" +default-features = false + +[dependencies.crossbeam-queue] +version = "0.2.1" +default-features = false +features = ["alloc"] + +[dependencies.futures-util] +version = "0.3.5" +default-features = false +features = ["alloc"] [dependencies.lazy_static] -version = "1.4.0" +version = "1.0" features = ["spin_no_std"] [profile.dev] diff --git a/src/allocator.rs b/src/allocator.rs index 5bc77fa..858c79c 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -38,7 +38,7 @@ unsafe impl GlobalAlloc for Dummy { pub fn init_heap( mapper: &mut impl Mapper, frame_allocator: &mut impl FrameAllocator, -) -> Result<(), MapToError> { +) -> Result<(), MapToError> { let page_range = { let heap_start = VirtAddr::new(HEAP_START as u64); let head_end = heap_start + HEAP_SIZE - 1u64; diff --git a/src/interrupts.rs b/src/interrupts.rs index fa3f25b..d6fd6a5 100644 --- a/src/interrupts.rs +++ b/src/interrupts.rs @@ -10,6 +10,12 @@ use crate::{print, println}; #[cfg(test)] use crate::{serial_print, serial_println}; +pub const PIC_1_OFFSET: u8 = 32; +pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8; + +pub static PICS: spin::Mutex = + spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) }); + lazy_static! { static ref IDT: InterruptDescriptorTable = { let mut idt = InterruptDescriptorTable::new(); @@ -39,9 +45,8 @@ extern "x86-interrupt" fn breakpoint_handler(stack_frame: &mut InterruptStackFra extern "x86-interrupt" fn double_fault_handler( stack_frame: &mut InterruptStackFrame, _error_code: u64, -) { - println!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); - hlt_loop(); +) -> ! { + panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); } extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: &mut InterruptStackFrame) { @@ -53,34 +58,12 @@ extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: &mut InterruptSt } } -pub const PIC_1_OFFSET: u8 = 32; -pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8; - -pub static PICS: spin::Mutex = - spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) }); - extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: &mut InterruptStackFrame) { - use pc_keyboard::{layouts, DecodedKey, Keyboard, ScancodeSet1}; - use spin::Mutex; use x86_64::instructions::port::Port; - lazy_static! { - static ref KEYBOARD: Mutex> = - Mutex::new(Keyboard::new(layouts::Us104Key, ScancodeSet1)); - } - - let mut keyboard = KEYBOARD.lock(); let mut port = Port::new(0x60); // PS/2 port - let scancode: u8 = unsafe { port.read() }; - if let Ok(Some(key_event)) = keyboard.add_byte(scancode) { - if let Some(key) = keyboard.process_keyevent(key_event) { - match key { - DecodedKey::Unicode(character) => print!("{}", character), - DecodedKey::RawKey(key) => print!("{:?}", key), - } - } - } + crate::task::keyboard::add_scancode(scancode); unsafe { PICS.lock() diff --git a/src/lib.rs b/src/lib.rs index ce47e4f..f93e5bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,7 +12,6 @@ extern crate alloc; use core::panic::PanicInfo; -use linked_list_allocator::LockedHeap; #[cfg(test)] use bootloader::{entry_point, BootInfo}; @@ -20,9 +19,6 @@ use bootloader::{entry_point, BootInfo}; #[cfg(test)] entry_point!(test_kernel_main); -// #[global_allocator] -// static ALLOCATOR: LockedHeap = LockedHeap::empty(); - #[alloc_error_handler] fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! { panic!("allocation error: {:?}", layout) @@ -34,6 +30,7 @@ pub mod interrupts; pub mod macros; pub mod memory; pub mod serial; +pub mod task; pub mod vga_buffer; pub fn test_runner(tests: &[&dyn Fn()]) { diff --git a/src/main.rs b/src/main.rs index 6d2ccac..a602d6f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ use alloc::{boxed::Box, rc::Rc, vec, vec::Vec}; use core::panic::PanicInfo; use blog_os::println; +use blog_os::task::{keyboard, Task, simple_executor::SimpleExecutor}; use bootloader::{entry_point, BootInfo}; /// This function is called on panic. @@ -65,9 +66,23 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { Rc::strong_count(&cloned_reference) ); + let mut executor = SimpleExecutor::new(); + executor.spawn(Task::new(example_task())); + executor.spawn(Task::new(keyboard::print_keypresses())); + executor.run(); + #[cfg(test)] test_main(); println!("It did not crash!"); blog_os::hlt_loop(); } + +async fn async_number() -> u32 { + 42 +} + +async fn example_task() { + let number = async_number().await; + println!("async number: {}", number); +} diff --git a/src/memory.rs b/src/memory.rs index 51b4d6e..e938020 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -2,63 +2,12 @@ use bootloader::bootinfo::{MemoryMap, MemoryRegionType}; use x86_64::{ structures::paging::{ FrameAllocator, Mapper, OffsetPageTable, Page, PageTable, PhysFrame, Size4KiB, + UnusedPhysFrame, }, PhysAddr, VirtAddr, }; -/// A FrameAllocator that always returns `None`. -pub struct EmptyFrameAllocator; - -unsafe impl FrameAllocator for EmptyFrameAllocator { - fn allocate_frame(&mut self) -> Option { - None - } -} - -pub struct BootInfoFrameAllocator { - memory_map: &'static MemoryMap, - next: usize, -} - -impl BootInfoFrameAllocator { - /// Create a FrameAllocator from the passed memory map. - /// - /// This function is unsafe because the caller must guarantee that the passed - /// meory map is valid. The main requirement is that all frame are marked - /// as `USABLE` in it are really unused. - pub unsafe fn init(memory_map: &'static MemoryMap) -> Self { - BootInfoFrameAllocator { - memory_map, - next: 0, - } - } - - /// Returns an iterator over the usable frames specified in the memory map. - fn usable_frames(&self) -> impl Iterator { - // get usable regions from memory map - let regions = self.memory_map.iter(); - let usable_regions = regions.filter(|r| r.region_type == MemoryRegionType::Usable); - - // map each region to its address range - let addr_ranges = usable_regions.map(|r| r.range.start_addr()..r.range.end_addr()); - - // transform to an iterator of frame start addresses - let frame_addresses = addr_ranges.flat_map(|r| r.step_by(4096)); - - // create `PhysFrame` types from the start addresses - frame_addresses.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr))) - } -} - -unsafe impl FrameAllocator for BootInfoFrameAllocator { - fn allocate_frame(&mut self) -> Option { - let frame = self.usable_frames().nth(self.next); - self.next += 1; - frame - } -} - -/// Initialize a new OffsetPageTable +/// Initialize a new OffsetPageTable. /// /// This function is unsafe because the caller must guarantee that the /// complete physical memory is mapped to virtual memory at the passed @@ -84,10 +33,10 @@ unsafe fn active_level_4_table(physical_memory_offset: VirtAddr) -> &'static mut let virt = physical_memory_offset + phys.as_u64(); let page_table_ptr: *mut PageTable = virt.as_mut_ptr(); - &mut *page_table_ptr + &mut *page_table_ptr // unsafe } -/// Creates an example maping for the given page to frame `0xb8000` +/// Creates an example mapping for the given page to frame `0xb8000`. pub fn create_example_mapping( page: Page, mapper: &mut OffsetPageTable, @@ -96,9 +45,62 @@ pub fn create_example_mapping( use x86_64::structures::paging::PageTableFlags as Flags; let frame = PhysFrame::containing_address(PhysAddr::new(0xb8000)); + // FIXME: ONLY FOR TEMPORARY TESTING + let unused_frame = unsafe { UnusedPhysFrame::new(frame) }; let flags = Flags::PRESENT | Flags::WRITABLE; - let map_to_result = unsafe { mapper.map_to(page, frame, flags, frame_allocator) }; - + let map_to_result = mapper.map_to(page, unused_frame, flags, frame_allocator); map_to_result.expect("map_to failed").flush(); } + +/// A FrameAllocator that always returns `None`. +pub struct EmptyFrameAllocator; + +unsafe impl FrameAllocator for EmptyFrameAllocator { + fn allocate_frame(&mut self) -> Option { + None + } +} + +/// A FrameAllocator that returns usable frames from the bootloader's memory map. +pub struct BootInfoFrameAllocator { + memory_map: &'static MemoryMap, + next: usize, +} + +impl BootInfoFrameAllocator { + /// Create a FrameAllocator from the passed memory map. + /// + /// This function is unsafe because the caller must guarantee that the passed + /// memory map is valid. The main requirement is that all frames that are marked + /// as `USABLE` in it are really unused. + pub unsafe fn init(memory_map: &'static MemoryMap) -> Self { + BootInfoFrameAllocator { + memory_map, + next: 0, + } + } + + /// Returns an iterator over the usable frames specified in the memory map. + fn usable_frames(&self) -> impl Iterator { + // get usable regions from memory map + let regions = self.memory_map.iter(); + let usable_regions = regions.filter(|r| r.region_type == MemoryRegionType::Usable); + // map each region to its address range + let addr_ranges = usable_regions.map(|r| r.range.start_addr()..r.range.end_addr()); + // transform to an iterator of frame start addresses + let frame_addresses = addr_ranges.flat_map(|r| r.step_by(4096)); + // create `PhysFrame` types from the start addresses + let frames = frame_addresses.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr))); + // we know that the frames are really unused + frames.map(|f| unsafe { UnusedPhysFrame::new(f) }) + } +} + +unsafe impl FrameAllocator for BootInfoFrameAllocator { + fn allocate_frame(&mut self) -> Option { + let frame = self.usable_frames().nth(self.next); + self.next += 1; + frame + } +} diff --git a/src/task.rs b/src/task.rs new file mode 100644 index 0000000..6adcd50 --- /dev/null +++ b/src/task.rs @@ -0,0 +1,35 @@ +use core::{future::Future, pin::Pin}; +use core::sync::atomic::{AtomicU64, Ordering}; +use core::task::{Context, Poll}; +use alloc::boxed::Box; + +pub mod keyboard; +pub mod simple_executor; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +struct TaskId(u64); + +impl TaskId { + fn new() -> Self { + static NEXT_ID: AtomicU64 = AtomicU64::new(0); + TaskId(NEXT_ID.fetch_add(1, Ordering::Relaxed)) + } +} + +pub struct Task { + id: TaskId, + future: Pin>>, +} + +impl Task { + pub fn new(future: impl Future + 'static) -> Task { + Task { + id: TaskId::new(), + future: Box::pin(future), + } + } + + fn poll(&mut self, context: &mut Context) -> Poll<()> { + self.future.as_mut().poll(context) + } +} \ No newline at end of file diff --git a/src/task/keyboard.rs b/src/task/keyboard.rs new file mode 100644 index 0000000..dc8bfab --- /dev/null +++ b/src/task/keyboard.rs @@ -0,0 +1,81 @@ +use conquer_once::spin::OnceCell; +use core::{pin::Pin, task::{Poll, Context}}; +use crossbeam_queue::ArrayQueue; +use futures_util::task::AtomicWaker; +use futures_util::stream::{Stream, StreamExt}; +use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1}; + +use crate::{print, println}; + +static SCANCODE_QUEUE: OnceCell> = OnceCell::uninit(); +static WAKER: AtomicWaker = AtomicWaker::new(); + +/// Called by the keyboard interrupt handler +/// +/// Must not block or allocate. +pub(crate) fn add_scancode(scancode: u8) { + if let Ok(queue) = SCANCODE_QUEUE.try_get() { + if let Err(_) = queue.push(scancode) { + println!("WARNING: scancode queue full; dropping keyboard input"); + } else { + WAKER.wake(); + } + } else { + println!("WARNING: scancode queue uninitialized"); + } +} + +pub async fn print_keypresses() { + let mut scancodes = ScancodeStream::new(); + let mut keyboard = Keyboard::new(layouts::Us104Key, ScancodeSet1, HandleControl::Ignore); + + while let Some(scancode) = scancodes.next().await { + if let Ok(Some(key_event)) = keyboard.add_byte(scancode) { + if let Some(key) = keyboard.process_keyevent(key_event) { + match key { + DecodedKey::Unicode(character) => print!("{}", character), + DecodedKey::RawKey(key) => print!("{:?}", key), + } + } + } + } +} + +pub struct ScancodeStream { + _private: (), +} + +impl ScancodeStream { + pub fn new() -> Self { + SCANCODE_QUEUE.try_init_once(|| ArrayQueue::new(100)) + .expect("ScancodeStream::new should only be called once"); + + ScancodeStream { + _private: () + } + } +} + +impl Stream for ScancodeStream { + type Item = u8; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + let queue = SCANCODE_QUEUE + .try_get() + .expect("not initialized"); + + // fast path + if let Ok(scancode) = queue.pop() { + return Poll::Ready(Some(scancode)); + } + + WAKER.register(&cx.waker()); + match queue.pop() { + Ok(scancode) => { + WAKER.take(); + Poll::Ready(Some(scancode)) + }, + Err(crossbeam_queue::PopError) => Poll::Pending, + } + } +} \ No newline at end of file diff --git a/src/task/simple_executor.rs b/src/task/simple_executor.rs new file mode 100644 index 0000000..a01e176 --- /dev/null +++ b/src/task/simple_executor.rs @@ -0,0 +1,44 @@ +use super::Task; +use alloc::collections::VecDeque; +use core::task::{Context, Poll, Waker, RawWaker, RawWakerVTable}; + +pub struct SimpleExecutor { + task_queue: VecDeque, +} + +impl SimpleExecutor { + pub fn new() -> SimpleExecutor { + SimpleExecutor { + task_queue: VecDeque::new(), + } + } + + pub fn spawn(&mut self, task: Task) { + self.task_queue.push_back(task) + } + + pub fn run(&mut self) { + while let Some(mut task) = self.task_queue.pop_front() { + let waker = dummy_waker(); + let mut context = Context::from_waker(&waker); + match task.poll(&mut context) { + Poll::Ready(()) => {} // task done + Poll::Pending => self.task_queue.push_back(task), + } + } + } +} + +fn dummy_raw_waker() -> RawWaker { + fn no_op(_: *const ()) {} + fn clone(_: *const ()) -> RawWaker { + dummy_raw_waker() + } + + let vtable = &RawWakerVTable::new(clone, no_op, no_op, no_op); + RawWaker::new(0 as *const (), vtable) +} + +fn dummy_waker() -> Waker { + unsafe { Waker::from_raw(dummy_raw_waker()) } +} \ No newline at end of file