Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • redox-os/kernel
  • deepaksirone/kernel
  • microcolonel/kernel
  • jD91mZM2/kernel
  • liamnprg/kernel
  • ids1024/kernel
  • luojia/kernel
  • efikarl/kernel
  • jferard/kernel
  • rosehuds/kernel
  • xTibor/kernel
  • Ano-Nymus/kernel
  • carrot93/kernel
  • noam93k/kernel
  • corvus_corax/kernel
  • antares/kernel
  • nrdxp/kernel
  • SoyaOhnishi/kernel
  • potatogim/kernel
  • bsjung/kernel
  • batzor/kernel
  • retrocoder68/kernel
  • kal/kernel
  • jabedude/kernel
  • 4lDO2/kernel
  • cherusk/kernel
  • sudoamin/kernel
  • chetankhilosiya/kernel
  • t-nil/kernel
  • Majoneza/kernel
  • wiredtv/kernel
  • tijlleenders/kernel
  • Mottl/kernel
  • usapmz/kernel
  • kamirr/kernel
  • CodingRays/kernel
  • Ivan/kernel
  • zacklukem/kernel
  • devnexen/kernel
  • uuuvn/kernel
  • rw_van/kernel
  • freewilll/kernel
  • ebalalic/kernel
  • henritel/kernel
  • dahc/kernel
  • Forest0923/kernel
  • andrey.turkin/kernel
  • amidamaru/kernel
  • gmacd/kernel
  • jinb-park/kernel
  • bjorn3/kernel
  • neallred/kernel
  • hmcmillan/kernel
  • jmaine/kernel
  • wt/kernel
  • aaronjanse/kernel
  • Skallwar/kernel
  • NateDogg1232/kernel
  • maxtnuk/kernel
  • Vladimare/kernel
  • ylz0923/kernel
  • wheatfox/kernel
  • mjdr/kernel
  • adi-g15/kernel
  • heghe/kernel
  • enygmator/kernel
  • vincent/kernel
  • StaringAtEditor/redox-os-kernel
  • zhaozhao/kernel
  • arthurpaulino/kernel
  • andypython/kernel
  • LLeny/kernel
72 results
Show changes
Commits on Source (408)
[build]
rustflags = [
# Kernel should preserve floating-point registers
"-Csoft-float",
]
[unstable]
build-std = ["core", "alloc", "compiler_builtins"]
target
/config.toml
.gitlab-ci-local/
image: "redoxos/redoxer:latest"
variables:
GIT_SUBMODULE_STRATEGY: recursive
stages:
- host
- build
- test
# TODO: benchmarks and profiling (maybe manually enabled for relevant MRs)?
build:
stage: build
script:
- mkdir -p target/${ARCH}
- TARGET=${ARCH}-unknown-redox redoxer env make BUILD=target/${ARCH}
parallel:
matrix:
- ARCH: [x86_64, i686, aarch64, riscv64gc]
fmt:
stage: host
script:
- rustup component add rustfmt-preview
- cargo fmt -- --check
unit_test:
stage: test
script:
- TARGET=x86_64-unknown-redox redoxer test
[submodule "syscall"]
path = syscall
url = https://gitlab.redox-os.org/redox-os/syscall.git
branch = master
[submodule "slab_allocator"]
path = slab_allocator
url = https://gitlab.redox-os.org/redox-os/slab_allocator
......@@ -9,3 +5,7 @@
path = rmm
url = https://gitlab.redox-os.org/redox-os/rmm.git
branch = master
[submodule "redox-path"]
path = redox-path
url = https://gitlab.redox-os.org/redox-os/redox-path.git
branch = main
[[language]]
name = "rust"
[[language.config.cargo]]
[[language-server.rust-analyzer.config.cargo]]
extraEnv = ["RUST_TARGET_PATH=targets"]
# Select one of targets to make lsp work for your confguration
# Do not commit this change
# TODO: find a better way to do this
# target = "aarch64-unknown-kernel"
[[language.config.check]]
[[language-server.rust-analyzer.config.check]]
targets = ["x86_64-unknown-kernel", "i686-unknown-kernel", "aarch64-unknown-kernel"]
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]]
name = "autocfg"
version = "1.1.0"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "bit_field"
version = "0.10.1"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4"
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
[[package]]
name = "bitfield"
......@@ -26,17 +44,26 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
[[package]]
name = "byteorder"
version = "1.4.3"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.0.73"
version = "1.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
checksum = "c736e259eea577f443d5c86c304f9f4ae0295c43f3ba05c21f1d66b5f06001af"
dependencies = [
"shlex",
]
[[package]]
name = "cfg-if"
......@@ -46,17 +73,14 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "equivalent"
version = "1.0.1"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "fdt"
version = "0.1.0"
source = "git+https://gitlab.redox-os.org/thomhuds/fdt.git#7358607679114ccab5f97e14894ed3b59c5d42d6"
dependencies = [
"byteorder",
]
version = "0.2.0-alpha1"
source = "git+https://github.com/repnop/fdt.git?rev=2fb1409edd1877c714a0aa36b6a7c5351004be54#2fb1409edd1877c714a0aa36b6a7c5351004be54"
[[package]]
name = "goblin"
......@@ -70,41 +94,55 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.14.0"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
dependencies = [
"ahash",
]
[[package]]
name = "hashbrown"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
[[package]]
name = "indexmap"
version = "2.0.0"
version = "2.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
dependencies = [
"equivalent",
"hashbrown",
"hashbrown 0.15.2",
]
[[package]]
name = "kernel"
version = "0.4.1"
dependencies = [
"arrayvec",
"bitfield",
"bitflags",
"bitflags 2.8.0",
"byteorder",
"cc",
"fdt",
"goblin",
"hashbrown 0.14.5",
"indexmap",
"linked_list_allocator 0.9.1",
"log",
"memoffset",
"paste",
"raw-cpuid",
"redox-path",
"redox_syscall",
"rmm",
"rustc-cfg",
"rustc-demangle",
"sbi-rt",
"slab",
"slab_allocator",
"spin 0.9.0",
"spin 0.9.8",
"spinning_top 0.3.0",
"toml",
"x86",
]
......@@ -124,14 +162,14 @@ version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "549ce1740e46b291953c4340adcd74c59bcf4308f4cac050fd33ba91b7168f4a"
dependencies = [
"spinning_top",
"spinning_top 0.2.5",
]
[[package]]
name = "lock_api"
version = "0.4.8"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390"
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
......@@ -139,33 +177,21 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.17"
version = "0.4.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if",
]
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
[[package]]
name = "memchr"
version = "2.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
[[package]]
name = "memoffset"
version = "0.6.5"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "paste"
version = "1.0.9"
name = "once_cell"
version = "1.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
[[package]]
name = "plain"
......@@ -175,36 +201,43 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
[[package]]
name = "proc-macro2"
version = "1.0.66"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "raw-cpuid"
version = "10.5.0"
version = "10.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6aa2540135b6a94f74c7bc90ad4b794f822026a894f3d7bcd185c100d13d4ad6"
checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332"
dependencies = [
"bitflags",
"bitflags 1.3.2",
]
[[package]]
name = "redox-path"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64072665120942deff5fd5425d6c1811b854f4939e7f1c01ce755f64432bbea7"
[[package]]
name = "redox_syscall"
version = "0.4.1"
version = "0.5.9"
source = "git+https://gitlab.redox-os.org/redox-os/syscall.git#3117ea451c6224a6eb91283d8eb7c41d05fb7d9d"
dependencies = [
"bitflags",
"bitflags 2.8.0",
]
[[package]]
......@@ -213,21 +246,39 @@ version = "0.1.0"
[[package]]
name = "rustc-cfg"
version = "0.3.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56a596b5718bf5e059d59a30af12f7f462a152de147aa462b70892849ee18704"
checksum = "9ddf7a5e441e8003a5a88aab97f1c6113043ddde252d789ef9dea3871b78633a"
dependencies = [
"thiserror",
]
[[package]]
name = "rustc-demangle"
version = "0.1.21"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "sbi-rt"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fbaa69be1eedc61c426e6d489b2260482e928b465360576900d52d496a58bd0"
dependencies = [
"sbi-spec",
]
[[package]]
name = "sbi-spec"
version = "0.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e36312fb5ddc10d08ecdc65187402baba4ac34585cb9d1b78522ae2358d890"
[[package]]
name = "scopeguard"
version = "1.1.0"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "scroll"
......@@ -237,18 +288,18 @@ checksum = "fda28d4b4830b807a8b43f7b0e6b5df875311b3e7621d84577188c175b6ec1ec"
[[package]]
name = "serde"
version = "1.0.188"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.188"
version = "1.0.218"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b"
dependencies = [
"proc-macro2",
"quote",
......@@ -257,13 +308,28 @@ dependencies = [
[[package]]
name = "serde_spanned"
version = "0.6.3"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
dependencies = [
"serde",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
dependencies = [
"autocfg",
]
[[package]]
name = "slab_allocator"
version = "0.3.1"
......@@ -286,38 +352,67 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "spin"
version = "0.9.0"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
dependencies = [
"lock_api",
]
[[package]]
name = "spinning_top"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b87bbf98cb81332a56c1ee8929845836f85e8ddd693157c30d76660196014478"
checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0"
dependencies = [
"lock_api",
]
[[package]]
name = "spinning_top"
version = "0.2.4"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75adad84ee84b521fb2cca2d4fd0f1dab1d8d026bda3c5bea4ca63b5f9f9293c"
checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300"
dependencies = [
"lock_api",
]
[[package]]
name = "syn"
version = "2.0.32"
version = "2.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2"
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "toml"
version = "0.7.8"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257"
checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148"
dependencies = [
"serde",
"serde_spanned",
......@@ -327,18 +422,18 @@ dependencies = [
[[package]]
name = "toml_datetime"
version = "0.6.3"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.19.15"
version = "0.22.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
dependencies = [
"indexmap",
"serde",
......@@ -349,15 +444,21 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.11"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "winnow"
version = "0.5.15"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc"
checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1"
dependencies = [
"memchr",
]
......@@ -369,6 +470,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55b5be8cc34d017d8aabec95bc45a43d0f20e8b2a31a453cabc804fe996f8dca"
dependencies = [
"bit_field",
"bitflags",
"bitflags 1.3.2",
"raw-cpuid",
]
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
......@@ -4,27 +4,27 @@ version = "0.4.1"
build = "build.rs"
edition = "2021"
[lib]
name = "kernel"
path = "src/lib.rs"
crate-type = ["staticlib"]
[build-dependencies]
cc = "1.0.3"
rustc-cfg = "0.3.0"
toml = "0.7"
cc = "1.0"
rustc-cfg = "0.5"
toml = "0.8"
[dependencies]
bitflags = "1.2.1"
bitflags = "2"
bitfield = "0.13.2"
hashbrown = { version = "0.14.3", default-features = false, features = ["ahash", "inline-more"] }
linked_list_allocator = "0.9.0"
log = "0.4"
memoffset = { version = "0.6", features = ["unstable_const"] }
redox_syscall = { path = "syscall" }
redox-path = "0.2.0"
redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git", branch = "master", default-features = false }
slab_allocator = { path = "slab_allocator", optional = true }
# FIXME: There is some undefined behavior probably in the kernel, which forces us to use spin 0.9.0 and not 0.9.2.
spin = "=0.9.0"
spin = "0.9.8"
spinning_top = { version = "0.3", features = ["arc_lock"] }
rmm = { path = "rmm", default-features = false }
arrayvec = { version = "0.7.4", default-features = false }
slab = { version = "0.4", default-features = false }
# TODO: Remove
indexmap = { version = "2.5.0", default-features = false }
[dependencies.goblin]
version = "0.2.1"
......@@ -35,42 +35,57 @@ features = ["elf32", "elf64"]
version = "0.1.16"
default-features = false
[target.'cfg(target_arch = "aarch64")'.dependencies]
[target.'cfg(any(target_arch = "aarch64", target_arch = "riscv64"))'.dependencies]
byteorder = { version = "1", default-features = false }
fdt = { git = "https://gitlab.redox-os.org/thomhuds/fdt.git", default-features = false }
paste = "1.0.7"
fdt = { git = "https://github.com/repnop/fdt.git", rev = "2fb1409edd1877c714a0aa36b6a7c5351004be54" }
[target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies]
raw-cpuid = "10.2.0"
x86 = { version = "0.47.0", default-features = false }
[target.'cfg(any(target_arch = "riscv64", target_arch = "riscv32"))'.dependencies]
sbi-rt = "0.0.3"
[features]
default = ["acpi", "multi_core", "graphical_debug", "serial_debug", "self_modifying"]
default = [
"acpi",
"multi_core",
"graphical_debug",
"serial_debug",
"self_modifying",
"x86_kvm_pv",
]
# Activates some limited code-overwriting optimizations, based on CPU features.
self_modifying = []
acpi = []
doc = []
graphical_debug = []
lpss_debug = []
multi_core = ["acpi"]
profiling = []
#TODO: remove when threading issues are fixed
pti = []
qemu_debug = []
serial_debug = []
system76_ec_debug = []
slab = ["slab_allocator"]
sys_stat = []
x86_kvm_pv = []
debugger = ["syscall_debug"]
syscall_debug = []
sys_fdstat = []
[profile.dev]
# Avoids having to define the eh_personality lang item and reduces kernel size
panic = "abort"
# Kernel doesn't yet work great with debug mode :(
opt-level = 3
[profile.release]
# Avoids having to define the eh_personality lang item and reduces kernel size
panic = "abort"
lto = true
debug = "full"
SOURCE:=$(dir $(realpath $(lastword $(MAKEFILE_LIST))))
BUILD?=$(CURDIR)
export RUST_TARGET_PATH=$(SOURCE)/targets
ifeq ($(TARGET),)
ARCH?=$(shell uname -m)
else
ARCH?=$(shell echo "$(TARGET)" | cut -d - -f1)
endif
ifeq ($(ARCH),riscv64gc)
ARCH:=riscv64
endif
GNU_TARGET=$(ARCH)-unknown-redox
all: $(BUILD)/kernel $(BUILD)/kernel.sym
LD_SCRIPT=$(SOURCE)/linkers/$(ARCH).ld
TARGET_SPEC=$(RUST_TARGET_PATH)/$(ARCH)-unknown-kernel.json
$(BUILD)/kernel.all: $(LD_SCRIPT) $(TARGET_SPEC) $(shell find $(SOURCE) -name "*.rs" -type f)
cargo rustc \
--bin kernel \
--manifest-path "$(SOURCE)/Cargo.toml" \
--target "$(TARGET_SPEC)" \
--release \
-Z build-std=core,alloc \
-- \
-C link-arg=-T -Clink-arg="$(LD_SCRIPT)" \
-C link-arg=-z -Clink-arg=max-page-size=0x1000 \
--emit link="$(BUILD)/kernel.all"
$(BUILD)/kernel.sym: $(BUILD)/kernel.all
$(GNU_TARGET)-objcopy \
--only-keep-debug \
"$(BUILD)/kernel.all" \
"$(BUILD)/kernel.sym"
$(BUILD)/kernel: $(BUILD)/kernel.all
$(GNU_TARGET)-objcopy \
--strip-debug \
"$(BUILD)/kernel.all" \
"$(BUILD)/kernel"
# kernel
# Kernel
Redox OS Microkernel
[![docs](https://img.shields.io/badge/docs-master-blue.svg)](https://docs.rs/redox_syscall/latest/syscall/)
[![SLOCs counter](https://tokei.rs/b1/github/redox-os/kernel?category=code)](https://github.com/XAMPPRocky/tokei)
[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
[![docs](https://img.shields.io/badge/docs-master-blue.svg)](https://doc.redox-os.org/kernel/kernel/)
[![](https://tokei.rs/b1/github/redox-os/kernel?category=code)](https://github.com/Aaronepower/tokei)
## Building the documentation
## Requirements
Try `cargo doc --open --target x86_64-unknown-none`.
* [`nasm`](https://nasm.us/) needs to be available on the PATH at build time.
## Debugging the redox kernel
## Building The Documentation
Running [qemu] with the `-s` flag will set up [qemu] to listen on port 1234 for
a [gdb] client to connect to it. To debug the redox kernel run.
Use this command:
```sh
cargo doc --open --target x86_64-unknown-none
```
## Debugging
### QEMU
Running [QEMU](https://www.qemu.org) with the `-s` flag will set up QEMU to listen on port `1234` for a GDB client to connect to it. To debug the redox kernel run.
```sh
make qemu gdb=yes
```
This will start a VM with and listen on port 1234 for a [gdb] or [lldb] client.
This will start a virtual machine with and listen on port `1234` for a GDB or LLDB client.
## [gdb]
### GDB
If you are going to use [gdb], run the following to load debug symbols and connect
to your running kernel.
If you are going to use [GDB](https://www.gnu.org/software/gdb/), run these commands to load debug symbols and connect to your running kernel:
```
(gdb) symbol-file build/kernel.sym
(gdb) target remote localhost:1234
```
## [lldb]
### LLDB
If you are going to use [lldb], run the following to start debugging.
If you are going to use [LLDB](https://lldb.llvm.org/), run these commands to start debugging:
```
(lldb) target create -s build/kernel.sym build/kernel
(lldb) gdb-remote localhost:1234
```
## Debugging
After connecting to your kernel you can set some interesting breakpoints and `continue`
the process. See your debuggers man page for more information on useful commands to run.
[qemu]: https://www.qemu.org
[gdb]: https://www.gnu.org/software/gdb/
[lldb]: https://lldb.llvm.org/
## Notes
- When trying to access a slice, **always** use the `common::GetSlice` trait and the `.get_slice()` method to get a slice without causing the kernel to panic.
The problem with slicing in regular Rust, e.g. `foo[a..b]`, is that if someone tries to access with a range that is out of bounds of an array/string/slice, it will cause a panic at runtime, as a safety measure. Same thing when accessing an element.
- Always use `foo.get(n)` instead of `foo[n]` and try to cover for the possibility of `Option::None`. Doing the regular way may work fine for applications, but never in the kernel. No possible panics should ever exist in kernel space, because then the whole OS would just stop working.
- If you receive a kernel panic in QEMU, use `pkill qemu-system` to kill the frozen QEMU process.
## How To Contribute
To learn how to contribute to this system component you need to read the following document:
- [CONTRIBUTING.md](https://gitlab.redox-os.org/redox-os/redox/-/blob/master/CONTRIBUTING.md)
## Development
To learn how to do development with this system component inside the Redox build system you need to read the [Build System](https://doc.redox-os.org/book/build-system-reference.html) and [Coding and Building](https://doc.redox-os.org/book/coding-and-building.html) pages.
### How To Build
To build this system component you need to download the Redox build system, you can learn how to do it on the [Building Redox](https://doc.redox-os.org/book/podman-build.html) page.
This is necessary because they only work with cross-compilation to a Redox virtual machine, but you can do some testing from Linux.
use rustc_cfg::Cfg;
use std::{env, path::Path, process::Command};
use toml::Table;
use std::env;
use std::path::Path;
use std::process::Command;
fn parse_kconfig(arch: &str) -> Option<()> {
println!("cargo:rerun-if-changed=config.toml");
......@@ -14,14 +12,27 @@ fn parse_kconfig(arch: &str) -> Option<()> {
let config_str = std::fs::read_to_string("config.toml").unwrap();
let root: Table = toml::from_str(&config_str).unwrap();
let altfeatures = root.get("arch")?.as_table().unwrap()
.get(arch)?.as_table().unwrap()
.get("features")?.as_table().unwrap();
let altfeatures = root
.get("arch")?
.as_table()
.unwrap()
.get(arch)?
.as_table()
.unwrap()
.get("features")?
.as_table()
.unwrap();
let self_modifying = env::var("CARGO_FEATURE_SELF_MODIFYING").is_ok();
for (name, value) in altfeatures {
let choice = value.as_str().unwrap();
let mut choice = value.as_str().unwrap();
assert!(matches!(choice, "always" | "never" | "auto"));
if !self_modifying && choice == "auto" {
choice = "never";
}
println!("cargo:rustc-cfg=cpu_feature_{choice}=\"{name}\"");
}
......@@ -32,46 +43,46 @@ fn main() {
println!("cargo:rustc-env=TARGET={}", env::var("TARGET").unwrap());
let out_dir = env::var("OUT_DIR").unwrap();
let cfg = Cfg::new(env::var_os("TARGET").unwrap()).unwrap();
let cfg = Cfg::of(env::var("TARGET").unwrap().as_str()).unwrap();
let arch_str = cfg.target_arch.as_str();
match arch_str {
"aarch64" => {
// Build pre kstart init asm code for aarch64
/*TODO: do we need any of this?
println!("cargo:rerun-if-changed=src/arch/aarch64/init/pre_kstart/early_init.S");
cc::Build::new()
.file("src/arch/aarch64/init/pre_kstart/early_init.S")
.target("aarch64-unknown-redox")
.compile("early_init");
*/
},
println!("cargo:rustc-cfg=dtb");
}
"x86" => {
println!("cargo:rerun-if-changed=src/asm/x86/trampoline.asm");
let status = Command::new("nasm")
.arg("-f").arg("bin")
.arg("-o").arg(format!("{}/trampoline", out_dir))
.arg("-f")
.arg("bin")
.arg("-o")
.arg(format!("{}/trampoline", out_dir))
.arg("src/asm/x86/trampoline.asm")
.status()
.expect("failed to run nasm");
if ! status.success() {
if !status.success() {
panic!("nasm failed with exit status {}", status);
}
},
}
"x86_64" => {
println!("cargo:rerun-if-changed=src/asm/x86_64/trampoline.asm");
let status = Command::new("nasm")
.arg("-f").arg("bin")
.arg("-o").arg(format!("{}/trampoline", out_dir))
.arg("-f")
.arg("bin")
.arg("-o")
.arg(format!("{}/trampoline", out_dir))
.arg("src/asm/x86_64/trampoline.asm")
.status()
.expect("failed to run nasm");
if ! status.success() {
if !status.success() {
panic!("nasm failed with exit status {}", status);
}
}
"riscv64" => {
println!("cargo:rustc-cfg=dtb");
}
_ => (),
}
......
......@@ -7,12 +7,23 @@ SECTIONS {
. = KERNEL_OFFSET;
. += SIZEOF_HEADERS;
/* Force the zero page to be part of a segment by creating a
* dummy section in the zero page.
* Limine will map the segment with the lowest vaddr value at
* 0xFFFFFFFF80000000 even if the segment has a higher vaddr.
* As such without the zero page being part of a segment, the
* kernel would be loaded at an offset from the expected
* location. As the redox kernel is not currently relocatable,
* this would result in a crash. A similar issue likely exists
* with multiboot/multiboot2 and the paddr of the segment.
*/
.dummy ALIGN(8) : AT(ADDR(.dummy) - KERNEL_OFFSET) {}
. = ALIGN(4096);
.text : AT(ADDR(.text) - KERNEL_OFFSET) {
__text_start = .;
*(.early_init.text*)
. = ALIGN(4096);
*(.text*)
__usercopy_start = .;
*(.usercopy-fns)
......@@ -21,7 +32,7 @@ SECTIONS {
__text_end = .;
}
.rodata : AT(ADDR(.rodata) - KERNEL_OFFSET) {
.rodata : AT(ADDR(.rodata) - KERNEL_OFFSET) {
__rodata_start = .;
*(.rodata*)
. = ALIGN(4096);
......
......@@ -8,6 +8,18 @@ SECTIONS {
. += SIZEOF_HEADERS;
/* Force the zero page to be part of a segment by creating a
* dummy section in the zero page.
* Limine will map the segment with the lowest vaddr value at
* 0xFFFFFFFF80000000 even if the segment has a higher vaddr.
* As such without the zero page being part of a segment, the
* kernel would be loaded at an offset from the expected
* location. As the redox kernel is not currently relocatable,
* this would result in a crash. A similar issue likely exists
* with multiboot/multiboot2 and the paddr of the segment.
*/
.dummy : AT(ADDR(.dummy) - KERNEL_OFFSET) {}
.text ALIGN(4K) : AT(ADDR(.text) - KERNEL_OFFSET) {
__text_start = .;
*(.text*)
......
ENTRY(kstart)
OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv" )
KERNEL_OFFSET = 0xFFFFFF0000000000;
SECTIONS {
. = KERNEL_OFFSET;
. += SIZEOF_HEADERS;
/* Force the zero page to be part of a segment by creating a
* dummy section in the zero page.
* Linker will map the segment with the lowest vaddr value at
* 0xFFFFFF0000000000 even if the segment has a higher vaddr.
* As such without the zero page being part of a segment, the
* kernel would be loaded at an offset from the expected
* location. As the redox kernel is not currently relocatable,
* this would result in a crash. A similar issue likely exists
* with multiboot/multiboot2 and the paddr of the segment.
*/
.dummy ALIGN(8) : AT(ADDR(.dummy) - KERNEL_OFFSET) {}
. = ALIGN(4096);
.text : AT(ADDR(.text) - KERNEL_OFFSET) {
__text_start = .;
*(.early_init.text*)
. = ALIGN(4096);
*(.text*)
__usercopy_start = .;
*(.usercopy-fns)
__usercopy_end = .;
. = ALIGN(4096);
__text_end = .;
}
.rodata : AT(ADDR(.rodata) - KERNEL_OFFSET) {
__rodata_start = .;
*(.rodata*)
. = ALIGN(4096);
__rodata_end = .;
}
.data : AT(ADDR(.data) - KERNEL_OFFSET) {
__data_start = .;
*(.data*)
*(.sdata*)
. = ALIGN(4096);
__data_end = .;
*(.got*)
. = ALIGN(4096);
__bss_start = .;
*(.bss*)
*(.sbss*)
. = ALIGN(4096);
__bss_end = .;
}
__end = .;
/DISCARD/ : {
*(.comment*)
*(.eh_frame*)
*(.gcc_except_table*)
*(.note*)
*(.rel.eh_frame*)
}
}
......@@ -8,6 +8,18 @@ SECTIONS {
. += SIZEOF_HEADERS;
/* Force the zero page to be part of a segment by creating a
* dummy section in the zero page.
* Limine will map the segment with the lowest vaddr value at
* 0xFFFFFFFF80000000 even if the segment has a higher vaddr.
* As such without the zero page being part of a segment, the
* kernel would be loaded at an offset from the expected
* location. As the redox kernel is not currently relocatable,
* this would result in a crash. A similar issue likely exists
* with multiboot/multiboot2 and the paddr of the segment.
*/
.dummy : AT(ADDR(.dummy) - KERNEL_OFFSET) {}
.text ALIGN(4K) : AT(ADDR(.text) - KERNEL_OFFSET) {
__text_start = .;
*(.text*)
......@@ -23,6 +35,7 @@ SECTIONS {
__altcode_start = .;
KEEP(*(.altcode*))
__altcode_end = .;
. = ALIGN(8);
__altrelocs_start = .;
KEEP(*(.altrelocs*))
__altrelocs_end = .;
......
Subproject commit a992ae89ed63c10e17a9212274d66b6b3b5f8274
Subproject commit 63669069f4eb2e3bf04c0399d28fb2e3e3c58166
blank_lines_lower_bound = 0 # default
blank_lines_upper_bound = 1 # default
brace_style = "SameLineWhere" # default
disable_all_formatting = false # default
edition = "2021"
empty_item_single_line = true # default
fn_single_line = false # default
force_explicit_abi = true # default
format_strings = false # default
hard_tabs = false # default
show_parse_errors = true # default
imports_granularity = "Crate" # default = Preserve
imports_indent = "Block" # default
imports_layout = "Mixed" # default
indent_style = "Block" # default
max_width = 100 # default
newline_style = "Unix" # default = Auto
skip_children = false # default
tab_spaces = 4 # default
trailing_comma = "Vertical" # default
where_single_line = false # default
use alloc::boxed::Box;
use core::mem;
use super::{find_sdt, sdt::Sdt};
use crate::{
device::generic_timer::GenericTimer,
dtb::irqchip::{register_irq, IRQ_CHIP},
};
#[derive(Clone, Copy, Debug)]
#[repr(C, packed)]
pub struct Gtdt {
pub header: Sdt,
pub cnt_control_base: u64,
_reserved: u32,
pub secure_el1_timer_gsiv: u32,
pub secure_el1_timer_flags: u32,
pub non_secure_el1_timer_gsiv: u32,
pub non_secure_el1_timer_flags: u32,
pub virtual_el1_timer_gsiv: u32,
pub virtual_el1_timer_flags: u32,
pub el2_timer_gsiv: u32,
pub el2_timer_flags: u32,
pub cnt_read_base: u64,
pub platform_timer_count: u32,
pub platform_timer_offset: u32,
/*TODO: we don't need these yet, and they cause short tables to fail parsing
pub virtual_el2_timer_gsiv: u32,
pub virtual_el2_timer_flags: u32,
*/
//TODO: platform timer structure (at platform timer offset, with platform timer count)
}
impl Gtdt {
pub fn init() {
let gtdt_sdt = find_sdt("GTDT");
let gtdt = if gtdt_sdt.len() == 1 {
match Gtdt::new(gtdt_sdt[0]) {
Some(gtdt) => gtdt,
None => {
log::warn!("Failed to parse GTDT");
return;
}
}
} else {
log::warn!("Unable to find GTDT");
return;
};
let gsiv = gtdt.non_secure_el1_timer_gsiv;
log::info!("generic_timer gsiv = {}", gsiv);
let mut timer = GenericTimer {
clk_freq: 0,
reload_count: 0,
};
timer.init();
register_irq(gsiv, Box::new(timer));
unsafe { IRQ_CHIP.irq_enable(gsiv as u32) };
}
pub fn new(sdt: &'static Sdt) -> Option<&'static Gtdt> {
if &sdt.signature == b"GTDT" && sdt.length as usize >= mem::size_of::<Gtdt>() {
Some(unsafe { &*((sdt as *const Sdt) as *const Gtdt) })
} else {
None
}
}
}
......@@ -2,24 +2,11 @@ use core::{mem, ptr};
use core::ptr::{read_volatile, write_volatile};
use crate::memory::Frame;
use crate::paging::{KernelMapper, PhysicalAddress, PageFlags};
use crate::paging::entry::EntryFlags;
use super::sdt::Sdt;
use super::{ACPI_TABLE, find_sdt};
#[repr(packed)]
#[derive(Clone, Copy, Debug, Default)]
pub struct GenericAddressStructure {
_address_space: u8,
_bit_width: u8,
_bit_offset: u8,
_access_size: u8,
pub address: u64,
}
use crate::memory::{map_device_memory, PhysicalAddress, PAGE_SIZE};
use super::{find_sdt, sdt::Sdt, GenericAddressStructure, ACPI_TABLE};
#[repr(packed)]
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
pub struct Hpet {
pub header: Sdt,
......@@ -32,7 +19,7 @@ pub struct Hpet {
pub hpet_number: u8,
pub min_periodic_clk_tick: u16,
pub oem_attribute: u8
pub oem_attribute: u8,
}
impl Hpet {
......@@ -56,8 +43,16 @@ impl Hpet {
pub fn new(sdt: &'static Sdt) -> Option<Hpet> {
if &sdt.signature == b"HPET" && sdt.length as usize >= mem::size_of::<Hpet>() {
let s = unsafe { ptr::read((sdt as *const Sdt) as *const Hpet) };
unsafe { s.base_address.init(&mut KernelMapper::lock()) };
Some(s)
if s.base_address.address_space == 0 {
unsafe { s.map() };
Some(s)
} else {
log::warn!(
"HPET has unsupported address space {}",
s.base_address.address_space
);
None
}
} else {
None
}
......@@ -66,22 +61,34 @@ impl Hpet {
//TODO: x86 use assumes only one HPET and only one GenericAddressStructure
#[cfg(target_arch = "x86")]
impl GenericAddressStructure {
pub unsafe fn init(&self, mapper: &mut KernelMapper) {
use crate::paging::{Page, VirtualAddress};
impl Hpet {
pub unsafe fn map(&self) {
use crate::{
memory::{Frame, KernelMapper},
paging::{entry::EntryFlags, Page, VirtualAddress},
};
use rmm::PageFlags;
let frame = Frame::containing_address(PhysicalAddress::new(self.address as usize));
let frame = Frame::containing(PhysicalAddress::new(self.base_address.address as usize));
let page = Page::containing_address(VirtualAddress::new(crate::HPET_OFFSET));
mapper
KernelMapper::lock()
.get_mut()
.expect("KernelMapper locked re-entrant while mapping memory for GenericAddressStructure")
.map_phys(page.start_address(), frame.start_address(), PageFlags::new().write(true).custom_flag(EntryFlags::NO_CACHE.bits(), true))
.expect(
"KernelMapper locked re-entrant while mapping memory for GenericAddressStructure",
)
.map_phys(
page.start_address(),
frame.base(),
PageFlags::new()
.write(true)
.custom_flag(EntryFlags::NO_CACHE.bits(), true),
)
.expect("failed to map memory for GenericAddressStructure")
.flush();
}
pub unsafe fn read_u64(&self, offset: usize) -> u64{
pub unsafe fn read_u64(&self, offset: usize) -> u64 {
read_volatile((crate::HPET_OFFSET + offset) as *const u64)
}
......@@ -91,22 +98,24 @@ impl GenericAddressStructure {
}
#[cfg(not(target_arch = "x86"))]
impl GenericAddressStructure {
pub unsafe fn init(&self, mapper: &mut KernelMapper) {
let frame = Frame::containing_address(PhysicalAddress::new(self.address as usize));
let (_, result) = mapper
.get_mut()
.expect("KernelMapper locked re-entrant while mapping memory for GenericAddressStructure")
.map_linearly(frame.start_address(), PageFlags::new().write(true).custom_flag(EntryFlags::NO_CACHE.bits(), true))
.expect("failed to map memory for GenericAddressStructure");
result.flush();
impl Hpet {
pub unsafe fn map(&self) {
map_device_memory(
PhysicalAddress::new(self.base_address.address as usize),
PAGE_SIZE,
);
}
pub unsafe fn read_u64(&self, offset: usize) -> u64{
read_volatile((self.address as usize + offset + crate::PHYS_OFFSET) as *const u64)
pub unsafe fn read_u64(&self, offset: usize) -> u64 {
read_volatile(
(self.base_address.address as usize + offset + crate::PHYS_OFFSET) as *const u64,
)
}
pub unsafe fn write_u64(&mut self, offset: usize, value: u64) {
write_volatile((self.address as usize + offset + crate::PHYS_OFFSET) as *mut u64, value);
write_volatile(
(self.base_address.address as usize + offset + crate::PHYS_OFFSET) as *mut u64,
value,
);
}
}
use core::mem;
use crate::memory::{allocate_frames, Frame};
use crate::paging::{KernelMapper, Page, PageFlags, PhysicalAddress, RmmA, RmmArch, VirtualAddress};
use super::sdt::Sdt;
use super::find_sdt;
use core::sync::atomic::{AtomicU8, Ordering};
use crate::device::local_apic::LOCAL_APIC;
use crate::interrupt;
use crate::start::{kstart_ap, CPU_COUNT, AP_READY};
/// The Multiple APIC Descriptor Table
#[derive(Clone, Copy, Debug)]
pub struct Madt {
sdt: &'static Sdt,
pub local_address: u32,
pub flags: u32
}
const TRAMPOLINE: usize = 0x8000;
static TRAMPOLINE_DATA: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/trampoline"));
pub static mut MADT: Option<Madt> = None;
pub const FLAG_PCAT: u32 = 1;
impl Madt {
pub fn init() {
let madt_sdt = find_sdt("APIC");
let madt = if madt_sdt.len() == 1 {
Madt::new(madt_sdt[0])
} else {
println!("Unable to find MADT");
return;
};
if let Some(madt) = madt {
// safe because no APs have been started yet.
unsafe { MADT = Some(madt) };
println!(" APIC: {:>08X}: {}", madt.local_address, madt.flags);
let local_apic = unsafe { &mut LOCAL_APIC };
let me = local_apic.id() as u8;
if local_apic.x2 {
println!(" X2APIC {}", me);
} else {
println!(" XAPIC {}: {:>08X}", me, local_apic.address);
}
if cfg!(feature = "multi_core") {
// Map trampoline
let trampoline_frame = Frame::containing_address(PhysicalAddress::new(TRAMPOLINE));
let trampoline_page = Page::containing_address(VirtualAddress::new(TRAMPOLINE));
let (result, page_table_physaddr) = unsafe {
//TODO: do not have writable and executable!
let mut mapper = KernelMapper::lock();
let result = mapper
.get_mut()
.expect("expected kernel page table not to be recursively locked while initializing MADT")
.map_phys(trampoline_page.start_address(), trampoline_frame.start_address(), PageFlags::new().execute(true).write(true))
.expect("failed to map trampoline");
(result, mapper.table().phys().data())
};
result.flush();
// Write trampoline, make sure TRAMPOLINE page is free for use
for i in 0..TRAMPOLINE_DATA.len() {
unsafe {
(*((TRAMPOLINE as *mut u8).add(i) as *const AtomicU8))
.store(TRAMPOLINE_DATA[i], Ordering::SeqCst);
}
}
for madt_entry in madt.iter() {
println!(" {:?}", madt_entry);
match madt_entry {
MadtEntry::LocalApic(ap_local_apic) => if ap_local_apic.id == me {
println!(" This is my local APIC");
} else {
if ap_local_apic.flags & 1 == 1 {
// Increase CPU ID
CPU_COUNT.fetch_add(1, Ordering::SeqCst);
// Allocate a stack
let stack_start = allocate_frames(64).expect("no more frames in acpi stack_start").start_address().data() + crate::PHYS_OFFSET;
let stack_end = stack_start + 64 * 4096;
let ap_ready = (TRAMPOLINE + 8) as *mut u64;
let ap_cpu_id = unsafe { ap_ready.add(1) };
let ap_page_table = unsafe { ap_ready.add(2) };
let ap_stack_start = unsafe { ap_ready.add(3) };
let ap_stack_end = unsafe { ap_ready.add(4) };
let ap_code = unsafe { ap_ready.add(5) };
// Set the ap_ready to 0, volatile
unsafe {
ap_ready.write(0);
ap_cpu_id.write(ap_local_apic.id.into());
ap_page_table.write(page_table_physaddr as u64);
ap_stack_start.write(stack_start as u64);
ap_stack_end.write(stack_end as u64);
ap_code.write(kstart_ap as u64);
// TODO: Is this necessary (this fence)?
core::arch::asm!("");
};
AP_READY.store(false, Ordering::SeqCst);
print!(" AP {}:", ap_local_apic.id);
// Send INIT IPI
{
let mut icr = 0x4500;
if local_apic.x2 {
icr |= (ap_local_apic.id as u64) << 32;
} else {
icr |= (ap_local_apic.id as u64) << 56;
}
print!(" IPI...");
local_apic.set_icr(icr);
}
// Send START IPI
{
//Start at 0x0800:0000 => 0x8000. Hopefully the bootloader code is still there
let ap_segment = (TRAMPOLINE >> 12) & 0xFF;
let mut icr = 0x4600 | ap_segment as u64;
if local_apic.x2 {
icr |= (ap_local_apic.id as u64) << 32;
} else {
icr |= (ap_local_apic.id as u64) << 56;
}
print!(" SIPI...");
local_apic.set_icr(icr);
}
// Wait for trampoline ready
print!(" Wait...");
while unsafe { (*ap_ready.cast::<AtomicU8>()).load(Ordering::SeqCst) } == 0 {
interrupt::pause();
}
print!(" Trampoline...");
while ! AP_READY.load(Ordering::SeqCst) {
interrupt::pause();
}
println!(" Ready");
unsafe { RmmA::invalidate_all(); }
} else {
println!(" CPU Disabled");
}
},
_ => ()
}
}
// Unmap trampoline
let (_frame, _, flush) = unsafe {
KernelMapper::lock()
.get_mut()
.expect("expected kernel page table not to be recursively locked while initializing MADT")
.unmap_phys(trampoline_page.start_address(), true)
.expect("failed to unmap trampoline page")
};
flush.flush();
}
}
}
pub fn new(sdt: &'static Sdt) -> Option<Madt> {
if &sdt.signature == b"APIC" && sdt.data_len() >= 8 { //Not valid if no local address and flags
let local_address = unsafe { *(sdt.data_address() as *const u32) };
let flags = unsafe { *(sdt.data_address() as *const u32).offset(1) };
Some(Madt {
sdt,
local_address,
flags
})
} else {
None
}
}
pub fn iter(&self) -> MadtIter {
MadtIter {
sdt: self.sdt,
i: 8 // Skip local controller address and flags
}
}
}
/// MADT Local APIC
#[derive(Clone, Copy, Debug)]
#[repr(packed)]
pub struct MadtLocalApic {
/// Processor ID
pub processor: u8,
/// Local APIC ID
pub id: u8,
/// Flags. 1 means that the processor is enabled
pub flags: u32
}
/// MADT I/O APIC
#[derive(Clone, Copy, Debug)]
#[repr(packed)]
pub struct MadtIoApic {
/// I/O APIC ID
pub id: u8,
/// reserved
_reserved: u8,
/// I/O APIC address
pub address: u32,
/// Global system interrupt base
pub gsi_base: u32
}
/// MADT Interrupt Source Override
#[derive(Clone, Copy, Debug)]
#[repr(packed)]
pub struct MadtIntSrcOverride {
/// Bus Source
pub bus_source: u8,
/// IRQ Source
pub irq_source: u8,
/// Global system interrupt base
pub gsi_base: u32,
/// Flags
pub flags: u16
}
/// MADT Entries
#[derive(Debug)]
pub enum MadtEntry {
LocalApic(&'static MadtLocalApic),
InvalidLocalApic(usize),
IoApic(&'static MadtIoApic),
InvalidIoApic(usize),
IntSrcOverride(&'static MadtIntSrcOverride),
InvalidIntSrcOverride(usize),
Unknown(u8)
}
pub struct MadtIter {
sdt: &'static Sdt,
i: usize
}
impl Iterator for MadtIter {
type Item = MadtEntry;
fn next(&mut self) -> Option<Self::Item> {
if self.i + 1 < self.sdt.data_len() {
let entry_type = unsafe { *(self.sdt.data_address() as *const u8).add(self.i) };
let entry_len = unsafe { *(self.sdt.data_address() as *const u8).add(self.i + 1) } as usize;
if self.i + entry_len <= self.sdt.data_len() {
let item = match entry_type {
0 => if entry_len == mem::size_of::<MadtLocalApic>() + 2 {
MadtEntry::LocalApic(unsafe { &*((self.sdt.data_address() + self.i + 2) as *const MadtLocalApic) })
} else {
MadtEntry::InvalidLocalApic(entry_len)
},
1 => if entry_len == mem::size_of::<MadtIoApic>() + 2 {
MadtEntry::IoApic(unsafe { &*((self.sdt.data_address() + self.i + 2) as *const MadtIoApic) })
} else {
MadtEntry::InvalidIoApic(entry_len)
},
2 => if entry_len == mem::size_of::<MadtIntSrcOverride>() + 2 {
MadtEntry::IntSrcOverride(unsafe { &*((self.sdt.data_address() + self.i + 2) as *const MadtIntSrcOverride) })
} else {
MadtEntry::InvalidIntSrcOverride(entry_len)
},
_ => MadtEntry::Unknown(entry_type)
};
self.i += entry_len;
Some(item)
} else {
None
}
} else {
None
}
}
}
use alloc::{boxed::Box, vec::Vec};
use super::{Madt, MadtEntry};
use crate::{
device::irqchip::{
gic::{GenericInterruptController, GicCpuIf, GicDistIf},
gicv3::{GicV3, GicV3CpuIf},
},
dtb::irqchip::{IrqChipItem, IRQ_CHIP},
memory::{map_device_memory, PhysicalAddress, PAGE_SIZE},
};
pub(super) fn init(madt: Madt) {
let mut gicd_opt = None;
let mut giccs = Vec::new();
for madt_entry in madt.iter() {
println!(" {:#x?}", madt_entry);
match madt_entry {
MadtEntry::Gicc(gicc) => {
giccs.push(gicc);
}
MadtEntry::Gicd(gicd) => {
if gicd_opt.is_some() {
log::warn!("Only one GICD should be present on a system, ignoring this one");
} else {
gicd_opt = Some(gicd);
}
}
_ => {}
}
}
let Some(gicd) = gicd_opt else {
log::warn!("No GICD found");
return;
};
let mut gic_dist_if = GicDistIf::default();
unsafe {
let phys = PhysicalAddress::new(gicd.physical_base_address as usize);
let virt = map_device_memory(phys, PAGE_SIZE);
gic_dist_if.init(virt.data());
};
log::info!("{:#x?}", gic_dist_if);
match gicd.gic_version {
1 | 2 => {
for gicc in giccs {
let mut gic_cpu_if = GicCpuIf::default();
unsafe {
let phys = PhysicalAddress::new(gicc.physical_base_address as usize);
let virt = map_device_memory(phys, PAGE_SIZE);
gic_cpu_if.init(virt.data())
};
log::info!("{:#x?}", gic_cpu_if);
let gic = GenericInterruptController {
gic_dist_if,
gic_cpu_if,
irq_range: (0, 0),
};
let chip = IrqChipItem {
phandle: 0,
parents: Vec::new(),
children: Vec::new(),
ic: Box::new(gic),
};
unsafe { IRQ_CHIP.irq_chip_list.chips.push(chip) };
//TODO: support more GICCs
break;
}
}
3 => {
for gicc in giccs {
let mut gic_cpu_if = GicV3CpuIf;
unsafe { gic_cpu_if.init() };
log::info!("{:#x?}", gic_cpu_if);
let gic = GicV3 {
gic_dist_if,
gic_cpu_if,
//TODO: get GICRs
gicrs: Vec::new(),
irq_range: (0, 0),
};
let chip = IrqChipItem {
phandle: 0,
parents: Vec::new(),
children: Vec::new(),
ic: Box::new(gic),
};
unsafe { IRQ_CHIP.irq_chip_list.chips.push(chip) };
//TODO: support more GICCs
break;
}
}
_ => {
log::warn!("unsupported GIC version {}", gicd.gic_version);
}
}
unsafe { IRQ_CHIP.init(None) };
}