diff --git a/Cargo.lock b/Cargo.lock index 4a1b1ded4..8b7544429 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,17 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "acpi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94476c7ef97af4c4d998b3f422c1b01d5211aad57c80ed200baf148d1f1efab6" +dependencies = [ + "bit_field", + "bitflags 2.9.4", + "log", +] + [[package]] name = "aes" version = "0.7.5" @@ -23,6 +34,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "align_ext" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1c330e503236d0b06386ae6cc42a513ef1ccc23c52b603c1b52f018564faf44" + [[package]] name = "aligned-vec" version = "0.6.4" @@ -153,7 +170,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn", + "syn 2.0.106", ] [[package]] @@ -179,7 +196,7 @@ checksum = "6115af052c7914c0cbb97195e5c72cb61c511527250074f5c041d1048b0d8b16" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -215,6 +232,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "buddy_system_allocator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7913f22349ffcfc6ca0ca9a656ec26cfbba538ed49c31a273dff2c5d1ea83d9" + [[package]] name = "buddy_system_allocator" version = "0.11.0" @@ -314,7 +337,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.1", ] [[package]] @@ -326,7 +349,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -389,6 +412,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -414,6 +443,41 @@ dependencies = [ "cipher", ] +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + [[package]] name = "defmt" version = "0.3.100" @@ -443,7 +507,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -463,7 +527,7 @@ checksum = "6178a82cf56c836a3ba61a7935cdb1c49bfaa6fa4327cd5bf554a503087de26b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -487,7 +551,7 @@ checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -534,6 +598,12 @@ dependencies = [ "elf", ] +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + [[package]] name = "encode_unicode" version = "1.0.0" @@ -557,7 +627,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -582,6 +652,12 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "fdt" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67" + [[package]] name = "find-msvc-tools" version = "0.1.4" @@ -594,6 +670,12 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe" +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "foldhash" version = "0.1.5" @@ -625,6 +707,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "getrandom" version = "0.3.4" @@ -637,6 +730,18 @@ dependencies = [ "wasip2", ] +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + [[package]] name = "glob" version = "0.3.3" @@ -685,6 +790,30 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "iced-x86" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c447cff8c7f384a7d4f741cfcff32f75f3ad02b406432e8d6c878d56b1edf6b" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "id-alloc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc00004fc6588985b504ef607cea3fe08f978681b71a0bdfb669f5cfeb12994" +dependencies = [ + "bitvec", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "indexmap" version = "2.11.4" @@ -695,6 +824,18 @@ dependencies = [ "hashbrown 0.16.0", ] +[[package]] +name = "inherit-methods-macro" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831739f8836b05db933f3a84783a5af48bd605915dcd10c7435bc74e7947a030" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "insta" version = "1.43.2" @@ -715,7 +856,36 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn", + "syn 2.0.106", +] + +[[package]] +name = "int-to-c-enum" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24dde2fe29de031a6fc24642ea1a62cb8e273b6c9e8799fa5c7cf0e2f03f220" +dependencies = [ + "int-to-c-enum-derive", +] + +[[package]] +name = "int-to-c-enum-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac1b8cfab94604ae1bcab8af8dd04cac15568a95cff50c562e6108457022f49" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "intrusive-collections" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "189d0897e4cbe8c75efedf3502c18c887b05046e59d28404d4d8e46cbc4d1e86" +dependencies = [ + "memoffset", ] [[package]] @@ -770,6 +940,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +[[package]] +name = "linux-boot-params" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46d2ae7b39cedc485d4e73d0e660ec23d6adecef9721c9ffab0805ce36ad3b5b" + [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -782,7 +958,7 @@ version = "0.1.0" dependencies = [ "arrayvec", "bitflags 2.9.4", - "buddy_system_allocator", + "buddy_system_allocator 0.11.0", "either", "hashbrown 0.15.5", "rangemap", @@ -833,7 +1009,7 @@ dependencies = [ "spin 0.9.8", "syscalls", "thiserror", - "x86_64", + "x86_64 0.15.2", ] [[package]] @@ -841,7 +1017,7 @@ name = "litebox_platform_linux_userland" version = "0.1.0" dependencies = [ "cfg-if", - "getrandom", + "getrandom 0.3.4", "libc", "litebox", "litebox_common_linux", @@ -859,7 +1035,7 @@ dependencies = [ "arrayvec", "authenticode", "bitflags 2.9.4", - "buddy_system_allocator", + "buddy_system_allocator 0.11.0", "cfg-if", "cms", "const-oid", @@ -875,7 +1051,7 @@ dependencies = [ "object", "once_cell", "rangemap", - "raw-cpuid", + "raw-cpuid 11.6.0", "rsa", "sha1", "sha2", @@ -883,7 +1059,7 @@ dependencies = [ "spin 0.10.0", "thiserror", "x509-cert", - "x86_64", + "x86_64 0.15.2", ] [[package]] @@ -897,13 +1073,14 @@ dependencies = [ "litebox_platform_lvbs", "litebox_platform_windows_userland", "once_cell", + "platform", ] [[package]] name = "litebox_platform_windows_userland" version = "0.1.0" dependencies = [ - "getrandom", + "getrandom 0.3.4", "litebox", "litebox_common_linux", "windows-sys 0.60.2", @@ -951,7 +1128,7 @@ dependencies = [ "litebox_platform_lvbs", "litebox_platform_multiplex", "litebox_shim_optee", - "x86_64", + "x86_64 0.15.2", ] [[package]] @@ -1058,6 +1235,16 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +[[package]] +name = "loongArch64" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c9f0d275c70310e2a9d2fc23250c5ac826a73fa828a5f256401f85c5c554283" +dependencies = [ + "bit_field", + "bitflags 2.9.4", +] + [[package]] name = "managed" version = "0.8.0" @@ -1079,6 +1266,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1103,7 +1299,31 @@ checksum = "f8eec4327f127d4d18c54c8bfbf7b05d74cc9a1befdcc6283a241238ffbc84c6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", +] + +[[package]] +name = "multiboot2" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2011496ba8bbd4e64dcfdd66a867e666a39b2ec49b57042afea2bd32e00962d6" +dependencies = [ + "bitflags 2.9.4", + "log", + "multiboot2-common", + "ptr_meta 0.3.1", + "thiserror", + "uefi-raw", +] + +[[package]] +name = "multiboot2-common" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6892f2795001adb0f6e4c124de90b68f9edc4bf52b8d81b14dac45cb361f1cca" +dependencies = [ + "ptr_meta 0.3.1", + "thiserror", ] [[package]] @@ -1181,7 +1401,7 @@ checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -1214,6 +1434,83 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "ostd" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99b561405c211e7c5944a5ed5a6bd174b21a9f91a9b9a7f5502e76b4bd22eaa1" +dependencies = [ + "acpi", + "align_ext", + "bit_field", + "bitflags 1.3.2", + "bitvec", + "buddy_system_allocator 0.10.0", + "cfg-if", + "fdt", + "gimli 0.28.1", + "iced-x86", + "id-alloc", + "inherit-methods-macro", + "int-to-c-enum", + "intrusive-collections", + "linux-boot-params", + "log", + "loongArch64", + "multiboot2", + "num-traits", + "ostd-macros", + "ostd-pod", + "ostd-test", + "riscv", + "sbi-rt", + "smallvec", + "spin 0.9.8", + "tdx-guest", + "unwinding", + "volatile 0.6.1", + "x86", + "x86_64 0.14.13", +] + +[[package]] +name = "ostd-macros" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67d0126b67a5af217d0b132d07f012cd9677498146966c3cec79978d12cde07f" +dependencies = [ + "proc-macro2", + "quote", + "rand", + "syn 2.0.106", +] + +[[package]] +name = "ostd-pod" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61b8517ab09a8a0c3efc2d140c56a272850b4bdbb79fe68fd84596ab3ecc9eb7" +dependencies = [ + "ostd-pod-derive", +] + +[[package]] +name = "ostd-pod-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e69b03ec42718a08c207e908fb6d95348c4b1552ef2f880d672b381d5dc002" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ostd-test" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13ab8ca5a2977a839dda0a1ff9076bfdd0fbf2eb4a84aa0b0a682c421fe312b2" + [[package]] name = "paste" version = "1.0.15" @@ -1250,6 +1547,16 @@ dependencies = [ "spki", ] +[[package]] +name = "platform" +version = "0.1.0" +dependencies = [ + "litebox", + "litebox_common_linux", + "ostd", + "spin 0.9.8", +] + [[package]] name = "portable-atomic" version = "1.11.1" @@ -1281,7 +1588,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn", + "syn 2.0.106", ] [[package]] @@ -1303,7 +1610,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -1323,10 +1630,50 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", "version_check", ] +[[package]] +name = "ptr_meta" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcada80daa06c42ed5f48c9a043865edea5dc44cbf9ac009fda3b89526e28607" +dependencies = [ + "ptr_meta_derive 0.2.0", +] + +[[package]] +name = "ptr_meta" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9a0cf95a1196af61d4f1cbdab967179516d9a4a4312af1f31948f8f6224a79" +dependencies = [ + "ptr_meta_derive 0.3.1", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bca9224df2e20e7c5548aeb5f110a0f3b77ef05f8585139b7148b59056168ed2" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "quote" version = "1.0.41" @@ -1354,6 +1701,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ + "libc", "rand_chacha", "rand_core", ] @@ -1373,6 +1721,9 @@ name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] [[package]] name = "rangemap" @@ -1380,6 +1731,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93e7e49bb0bf967717f7bd674458b3d6b0c5f48ec7e3038166026a69fc22223" +[[package]] +name = "raw-cpuid" +version = "10.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "raw-cpuid" version = "11.6.0" @@ -1428,6 +1788,16 @@ dependencies = [ "portable-atomic-util", ] +[[package]] +name = "riscv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f5c1b8bf41ea746266cdee443d1d1e9125c86ce1447e1a2615abd34330d33a9" +dependencies = [ + "critical-section", + "embedded-hal", +] + [[package]] name = "rsa" version = "0.9.8" @@ -1448,6 +1818,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "runner" +version = "0.1.0" +dependencies = [ + "litebox", + "litebox_common_linux", + "litebox_platform_multiplex", + "litebox_shim_linux", + "ostd", + "platform", +] + [[package]] name = "rustc-hash" version = "2.1.1" @@ -1488,6 +1870,21 @@ dependencies = [ "winapi-util", ] +[[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.2.0" @@ -1536,7 +1933,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -1662,6 +2059,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strsim" version = "0.11.1" @@ -1674,6 +2077,17 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.106" @@ -1708,6 +2122,18 @@ dependencies = [ "num-traits", ] +[[package]] +name = "tdx-guest" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3792a8dc443107e37c3804c655a4807605c8b275e986b0f08add336f01e49685" +dependencies = [ + "bitflags 1.3.2", + "iced-x86", + "raw-cpuid 10.7.0", + "x86_64 0.14.13", +] + [[package]] name = "tempfile" version = "3.23.0" @@ -1715,7 +2141,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ "fastrand", - "getrandom", + "getrandom 0.3.4", "once_cell", "rustix", "windows-sys 0.61.2", @@ -1738,7 +2164,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] @@ -1747,12 +2173,38 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +[[package]] +name = "uefi-raw" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b463030b802e1265a3800fab24df95d3229c202c2e408832a206f05b4d1496ca" +dependencies = [ + "bitflags 2.9.4", + "ptr_meta 0.2.0", + "uguid", +] + +[[package]] +name = "uguid" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8352f8c05e47892e7eaf13b34abd76a7f4aeaf817b716e88789381927f199c" + [[package]] name = "unicode-ident" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +[[package]] +name = "unwinding" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f06a05848f650946acef3bf525fe96612226b61f74ae23ffa4e98bfbb8ab3c" +dependencies = [ + "gimli 0.31.1", +] + [[package]] name = "utf8parse" version = "0.2.2" @@ -1771,6 +2223,12 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793" +[[package]] +name = "volatile" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af8ca9a5d4debca0633e697c88269395493cebf2e10db21ca2dbde37c1356452" + [[package]] name = "walkdir" version = "2.5.0" @@ -1781,6 +2239,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + [[package]] name = "wasip2" version = "1.0.1+wasi-0.2.4" @@ -1987,6 +2451,29 @@ dependencies = [ "spki", ] +[[package]] +name = "x86" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2781db97787217ad2a2845c396a5efe286f87467a5810836db6d74926e94a385" +dependencies = [ + "bit_field", + "bitflags 1.3.2", + "raw-cpuid 10.7.0", +] + +[[package]] +name = "x86_64" +version = "0.14.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c101112411baafbb4bf8d33e4c4a80ab5b02d74d2612331c61e8192fc9710491" +dependencies = [ + "bit_field", + "bitflags 2.9.4", + "rustversion", + "volatile 0.4.6", +] + [[package]] name = "x86_64" version = "0.15.2" @@ -1996,7 +2483,7 @@ dependencies = [ "bit_field", "bitflags 2.9.4", "rustversion", - "volatile", + "volatile 0.4.6", ] [[package]] @@ -2016,7 +2503,7 @@ checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.106", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index cc2d32948..7c61d702f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,9 @@ members = [ # The CI tests are not meant to be released (thus are not prefixed with # `litebox_`), but exist purely to better manage development on LiteBox. "dev_tests", + ######################################################## + "ostd-test/platform", + "ostd-test/runner", ] default-members = [ "litebox", @@ -35,6 +38,8 @@ default-members = [ "litebox_shim_optee", "litebox_syscall_rewriter", "dev_tests", + "ostd-test/platform", + "ostd-test/runner", ] # We exclude `litebox_runner_lvbs` from `default-members` because its interrupt handling # depends on the unstable `abi_x86_interrupt` feature, which requires a nightly toolchain. diff --git a/OSDK.toml b/OSDK.toml new file mode 100644 index 000000000..d38442fc5 --- /dev/null +++ b/OSDK.toml @@ -0,0 +1,19 @@ +[boot] +method = "grub-rescue-iso" + +[qemu] +args = """\ + -enable-kvm \ + -machine q35,kernel-irqchip=split \ + -cpu Icelake-Server,+x2apic \ + --no-reboot \ + -m 8G \ + -smp 1 \ + -nographic \ + -serial chardev:mux \ + -monitor chardev:mux \ + -chardev stdio,id=mux,mux=on,signal=off \ + -display none \ + -device isa-debug-exit,iobase=0xf4,iosize=0x04 \ + -boot d,menu=off \ +""" diff --git a/bacon.toml b/bacon.toml index 8c14be276..6bfa8feb6 100644 --- a/bacon.toml +++ b/bacon.toml @@ -91,6 +91,16 @@ need_stdout = false allow_warnings = true on_success = "job:doc" # so that we don't open the browser at each change +# osdk check +[jobs.osdk-check] +command = ["cargo", "osdk", "check"] +workdir = "ostd-test/runner" + +# osdk run +[jobs.osdk-run] +command = ["cargo", "osdk", "run"] +allow_warnings = true + # Project-specific keybindings, to make it easier to run the various jobs here. [keybindings] k = "job:check" @@ -104,3 +114,5 @@ alt-d = "job:doc" v = "job:buildchecks-lvbs" alt-s = "job:buildchecks-snp" w = "job:clippy-windows" +o = "job:osdk-check" +alt-o = "job:osdk-run" diff --git a/litebox/src/fs/tests.rs b/litebox/src/fs/tests.rs index 23985bb41..5c7156917 100644 --- a/litebox/src/fs/tests.rs +++ b/litebox/src/fs/tests.rs @@ -1167,10 +1167,14 @@ mod layered { let mut names: Vec<_> = entries.iter().map(|e| e.name.as_str()).collect(); names.sort_unstable(); - assert_eq!( - names, - vec![".", "..", "bar", "foo", "upperdir", "upperfile"] - ); + assert_eq!(names, vec![ + ".", + "..", + "bar", + "foo", + "upperdir", + "upperfile" + ]); // Check file types for entry in &entries { diff --git a/litebox/src/lib.rs b/litebox/src/lib.rs index 1b64a0344..9d6786eba 100644 --- a/litebox/src/lib.rs +++ b/litebox/src/lib.rs @@ -10,6 +10,10 @@ //! the modules in this crate. #![no_std] +#![feature(let_chains)] +#![feature(unsigned_is_multiple_of)] +#![feature(trait_upcasting)] +#![feature(result_flattening)] extern crate alloc; diff --git a/litebox/src/mm/exception_table.rs b/litebox/src/mm/exception_table.rs index 88db669f5..ec13bd861 100644 --- a/litebox/src/mm/exception_table.rs +++ b/litebox/src/mm/exception_table.rs @@ -11,7 +11,7 @@ //! 3. Signal/exception handlers use [`search_exception_tables`] to look up recovery points //! 4. If found, execution is redirected to allow graceful failure handling //! -//! New fallible functions should follow the pattern established by [`__memcpy_fallible`]. +//! New fallible functions should follow the pattern established by [`__lb_memcpy_fallible`]. use crate::utils::ReinterpretUnsignedExt; @@ -49,7 +49,7 @@ unsafe extern "C" { /// see [`crate::platform::common_providers::userspace_pointers`]. /// /// Returns number of bytes that failed to copy (0 on success). - pub fn __memcpy_fallible(dst: *mut u8, src: *const u8, size: usize) -> usize; + pub fn __lb_memcpy_fallible(dst: *mut u8, src: *const u8, size: usize) -> usize; static __ex_table_start: [ExceptionTableEntry; 0]; static __ex_table_end: [ExceptionTableEntry; 0]; diff --git a/litebox/src/mm/linux.rs b/litebox/src/mm/linux.rs index fa56b151e..2bab042b7 100644 --- a/litebox/src/mm/linux.rs +++ b/litebox/src/mm/linux.rs @@ -291,13 +291,10 @@ impl + 'static, const ALIGN: usize> Vmem each.start % ALIGN == 0 && each.end % ALIGN == 0, "Vmem: reserved range is not aligned to {ALIGN} bytes" ); - vmem.vmas.insert( - each.start..each.end, - VmArea { - flags: VmFlags::empty(), - is_file_backed: false, - }, - ); + vmem.vmas.insert(each.start..each.end, VmArea { + flags: VmFlags::empty(), + is_file_backed: false, + }); } vmem } @@ -720,13 +717,10 @@ impl + 'static, const ALIGN: usize> Vmem VmemProtectError::ProtectError(e) })?; - self.vmas.insert( - intersection, - VmArea { - flags: new_flags, - is_file_backed: vma.is_file_backed, - }, - ); + self.vmas.insert(intersection, VmArea { + flags: new_flags, + is_file_backed: vma.is_file_backed, + }); if !before.is_empty() { self.vmas.insert(before, vma); } diff --git a/litebox/src/mm/memcpy_fallible_32.S b/litebox/src/mm/memcpy_fallible_32.S index 6a9347e60..9d3aac662 100644 --- a/litebox/src/mm/memcpy_fallible_32.S +++ b/litebox/src/mm/memcpy_fallible_32.S @@ -8,9 +8,9 @@ // Output: // eax uncopied bytes or 0 if successful. .text -.global __memcpy_fallible +.global __lb_memcpy_fallible .code32 -__memcpy_fallible: # (dst: *mut u8, src: *const u8, size: usize) -> usize +__lb_memcpy_fallible: # (dst: *mut u8, src: *const u8, size: usize) -> usize push esi push edi push ecx @@ -35,4 +35,4 @@ __memcpy_fallible: # (dst: *mut u8, src: *const u8, size: usize) -> usize .align 4 .long .move - . .long .memcpy_exit - . -.popsection \ No newline at end of file +.popsection diff --git a/litebox/src/mm/memcpy_fallible_64.S b/litebox/src/mm/memcpy_fallible_64.S index 404712b1b..8318ab24b 100644 --- a/litebox/src/mm/memcpy_fallible_64.S +++ b/litebox/src/mm/memcpy_fallible_64.S @@ -8,9 +8,9 @@ // Output: // rcx uncopied bytes or 0 if successful. .text -.global __memcpy_fallible +.global __lb_memcpy_fallible .code64 -__memcpy_fallible: # (dst: *mut u8, src: *const u8, size: usize) -> usize +__lb_memcpy_fallible: # (dst: *mut u8, src: *const u8, size: usize) -> usize mov rcx, rdx .move: rep movsb @@ -23,4 +23,4 @@ __memcpy_fallible: # (dst: *mut u8, src: *const u8, size: usize) -> usize .align 4 .long .move - . .long .memcpy_exit - . -.popsection \ No newline at end of file +.popsection diff --git a/litebox/src/mm/tests.rs b/litebox/src/mm/tests.rs index 9809161c4..43854505e 100644 --- a/litebox/src/mm/tests.rs +++ b/litebox/src/mm/tests.rs @@ -101,10 +101,9 @@ fn test_vmm_mapping() { } .unwrap(); // [(0x1_0000, 0x1_c000)] - assert_eq!( - collect_mappings(&vmm), - vec![start_addr..start_addr + 12 * PAGE_SIZE] - ); + assert_eq!(collect_mappings(&vmm), vec![ + start_addr..start_addr + 12 * PAGE_SIZE + ]); unsafe { vmm.remove_mapping( @@ -113,13 +112,10 @@ fn test_vmm_mapping() { } .unwrap(); // [(0x1_0000, 0x1_2000), (0x1_4000, 0x1_c000)] - assert_eq!( - collect_mappings(&vmm), - vec![ - start_addr..start_addr + 2 * PAGE_SIZE, - start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE - ] - ); + assert_eq!(collect_mappings(&vmm), vec![ + start_addr..start_addr + 2 * PAGE_SIZE, + start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE + ]); assert!(matches!( unsafe { @@ -164,10 +160,9 @@ fn test_vmm_mapping() { .is_ok() ); // Grow and merge, [(0x1_0000, 0x1_c000)] - assert_eq!( - collect_mappings(&vmm), - vec![start_addr..start_addr + 12 * PAGE_SIZE] - ); + assert_eq!(collect_mappings(&vmm), vec![ + start_addr..start_addr + 12 * PAGE_SIZE + ]); assert!(matches!( unsafe { @@ -190,14 +185,11 @@ fn test_vmm_mapping() { .is_ok() ); // Change permission, [(0x1_0000, 0x1_2000), (0x1_2000, 0x1_4000), (0x1_4000, 0x1_c000)] - assert_eq!( - collect_mappings(&vmm), - vec![ - start_addr..start_addr + 2 * PAGE_SIZE, - start_addr + 2 * PAGE_SIZE..start_addr + 4 * PAGE_SIZE, - start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE - ] - ); + assert_eq!(collect_mappings(&vmm), vec![ + start_addr..start_addr + 2 * PAGE_SIZE, + start_addr + 2 * PAGE_SIZE..start_addr + 4 * PAGE_SIZE, + start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE + ]); // try to remap [0x1_2000, 0x1_4000) let r = PageRange::new(start_addr + 2 * PAGE_SIZE, start_addr + 4 * PAGE_SIZE).unwrap(); @@ -215,14 +207,11 @@ fn test_vmm_mapping() { } .is_ok_and(|v| v.as_usize() == start_addr + 12 * PAGE_SIZE) ); - assert_eq!( - collect_mappings(&vmm), - vec![ - start_addr..start_addr + 2 * PAGE_SIZE, - start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE, - start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE - ] - ); + assert_eq!(collect_mappings(&vmm), vec![ + start_addr..start_addr + 2 * PAGE_SIZE, + start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE, + start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE + ]); // create new mapping with no suggested address assert_eq!( @@ -238,15 +227,12 @@ fn test_vmm_mapping() { .as_usize(), DummyVmemBackend::TASK_ADDR_MAX - PAGE_SIZE, ); - assert_eq!( - collect_mappings(&vmm), - vec![ - start_addr..start_addr + 2 * PAGE_SIZE, - start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE, - start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE, - DummyVmemBackend::TASK_ADDR_MAX - PAGE_SIZE..DummyVmemBackend::TASK_ADDR_MAX, - ] - ); + assert_eq!(collect_mappings(&vmm), vec![ + start_addr..start_addr + 2 * PAGE_SIZE, + start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE, + start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE, + DummyVmemBackend::TASK_ADDR_MAX - PAGE_SIZE..DummyVmemBackend::TASK_ADDR_MAX, + ]); // create new mapping with fixed address that overlaps with other mapping assert_eq!( @@ -262,16 +248,13 @@ fn test_vmm_mapping() { .as_usize(), start_addr + PAGE_SIZE ); - assert_eq!( - collect_mappings(&vmm), - vec![ - start_addr..start_addr + PAGE_SIZE, - start_addr + PAGE_SIZE..start_addr + 2 * PAGE_SIZE, - start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE, - start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE, - DummyVmemBackend::TASK_ADDR_MAX - PAGE_SIZE..DummyVmemBackend::TASK_ADDR_MAX, - ] - ); + assert_eq!(collect_mappings(&vmm), vec![ + start_addr..start_addr + PAGE_SIZE, + start_addr + PAGE_SIZE..start_addr + 2 * PAGE_SIZE, + start_addr + 4 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE, + start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE, + DummyVmemBackend::TASK_ADDR_MAX - PAGE_SIZE..DummyVmemBackend::TASK_ADDR_MAX, + ]); // shrink mapping assert!( @@ -283,15 +266,12 @@ fn test_vmm_mapping() { } .is_ok() ); - assert_eq!( - collect_mappings(&vmm), - vec![ - start_addr..start_addr + PAGE_SIZE, - start_addr + PAGE_SIZE..start_addr + 2 * PAGE_SIZE, - start_addr + 4 * PAGE_SIZE..start_addr + 6 * PAGE_SIZE, - start_addr + 8 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE, - start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE, - DummyVmemBackend::TASK_ADDR_MAX - PAGE_SIZE..DummyVmemBackend::TASK_ADDR_MAX, - ] - ); + assert_eq!(collect_mappings(&vmm), vec![ + start_addr..start_addr + PAGE_SIZE, + start_addr + PAGE_SIZE..start_addr + 2 * PAGE_SIZE, + start_addr + 4 * PAGE_SIZE..start_addr + 6 * PAGE_SIZE, + start_addr + 8 * PAGE_SIZE..start_addr + 12 * PAGE_SIZE, + start_addr + 12 * PAGE_SIZE..start_addr + 16 * PAGE_SIZE, + DummyVmemBackend::TASK_ADDR_MAX - PAGE_SIZE..DummyVmemBackend::TASK_ADDR_MAX, + ]); } diff --git a/litebox/src/platform/common_providers/userspace_pointers.rs b/litebox/src/platform/common_providers/userspace_pointers.rs index 1d7c534a6..c79e9dc8a 100644 --- a/litebox/src/platform/common_providers/userspace_pointers.rs +++ b/litebox/src/platform/common_providers/userspace_pointers.rs @@ -1,7 +1,7 @@ //! Userspace Pointer Abstraction with Fallible Memory Access //! //! This module implements fallible userspace pointers that can safely handle invalid -//! memory accesses from userspace. The pointers use [`__memcpy_fallible`] internally, +//! memory accesses from userspace. The pointers use [`__lb_memcpy_fallible`] internally, //! which relies on an exception table mechanism to recover from memory faults. //! //! ## Exception Handling Mechanism @@ -27,7 +27,7 @@ //! accesses will still cause the program to crash (e.g., with SIGSEGV), but //! with the additional overhead of the fallible copy mechanism. -use crate::mm::exception_table::__memcpy_fallible; +use crate::mm::exception_table::__lb_memcpy_fallible; use crate::platform::{RawConstPointer, RawMutPointer}; /// Represent a user space pointer to a read-only object @@ -54,7 +54,7 @@ unsafe fn read_at_offset<'a, T: Clone>( let src = unsafe { ptr.add(usize::try_from(count).ok()?) }; let mut data = core::mem::MaybeUninit::::uninit(); let failed_bytes = unsafe { - __memcpy_fallible( + __lb_memcpy_fallible( data.as_mut_ptr().cast(), src.cast(), core::mem::size_of::(), @@ -77,7 +77,7 @@ unsafe fn to_cow_slice<'a, T: Clone>( } let mut data = alloc::vec::Vec::::with_capacity(len); let failed_bytes = unsafe { - __memcpy_fallible( + __lb_memcpy_fallible( data.as_mut_ptr().cast(), ptr.cast(), len * core::mem::size_of::(), @@ -148,7 +148,7 @@ impl RawMutPointer for UserMutPtr { unsafe fn write_at_offset(self, count: isize, value: T) -> Option<()> { let dst = unsafe { self.inner.add(usize::try_from(count).ok()?) }; let failed_bytes = unsafe { - __memcpy_fallible( + __lb_memcpy_fallible( dst.cast(), (&raw const value).cast(), core::mem::size_of::(), @@ -174,7 +174,7 @@ impl RawMutPointer for UserMutPtr { } let dst = unsafe { self.inner.add(start_offset) }; let failed_bytes = unsafe { - __memcpy_fallible(dst.cast(), buf.as_ptr().cast(), core::mem::size_of_val(buf)) + __lb_memcpy_fallible(dst.cast(), buf.as_ptr().cast(), core::mem::size_of_val(buf)) }; if failed_bytes == 0 { Some(()) } else { None } } diff --git a/litebox/src/sync/futex.rs b/litebox/src/sync/futex.rs index 5afae1572..7c556874e 100644 --- a/litebox/src/sync/futex.rs +++ b/litebox/src/sync/futex.rs @@ -107,15 +107,12 @@ impl let futex_addr = Self::futex_addr_as_atomic(futex_addr)?; let bucket = self.bucket(addr); - let mut entry = pin!(LoanListEntry::new( - self.platform, - FutexEntry { - addr, - waker: cx.waker().clone(), - bitset, - done: AtomicBool::new(false), - }, - )); + let mut entry = pin!(LoanListEntry::new(self.platform, FutexEntry { + addr, + waker: cx.waker().clone(), + bitset, + done: AtomicBool::new(false), + },)); // Insert into the bucket's list. It will be removed when woken or the // entry goes out of scope. diff --git a/litebox/src/utilities/array_index_map.rs b/litebox/src/utilities/array_index_map.rs index 80f2d18d3..e6078ab1a 100644 --- a/litebox/src/utilities/array_index_map.rs +++ b/litebox/src/utilities/array_index_map.rs @@ -111,14 +111,11 @@ impl ArrayIndexMap { let Slot::Filled { generation: _, data, - } = core::mem::replace( - &mut self.storage[idx.index()], - Slot::Unfilled { - // Since it is a filled slot, it could not have transitioned from a tombstone - // (u32::MAX), thus this addition should never overflow. - generation: idx.generation.checked_add(1).unwrap(), - }, - ) + } = core::mem::replace(&mut self.storage[idx.index()], Slot::Unfilled { + // Since it is a filled slot, it could not have transitioned from a tombstone + // (u32::MAX), thus this addition should never overflow. + generation: idx.generation.checked_add(1).unwrap(), + }) else { // We just confirmed that we are in a filled slot stage in the right generation, so it // is impossible for this to be reached. diff --git a/litebox/src/utilities/loan_list.rs b/litebox/src/utilities/loan_list.rs index e516eb022..1b42470bc 100644 --- a/litebox/src/utilities/loan_list.rs +++ b/litebox/src/utilities/loan_list.rs @@ -580,14 +580,11 @@ mod tests { let done = &done; let observed_removed = &observed_removed; move || { - let mut v = pin!(LoanListEntry::new( - platform, - Value { - key: i / entries_per_key, - str: String::from("one"), - removed: AtomicBool::new(false), - }, - )); + let mut v = pin!(LoanListEntry::new(platform, Value { + key: i / entries_per_key, + str: String::from("one"), + removed: AtomicBool::new(false), + },)); v.as_mut().insert(list); if i % 2 == 0 { v.remove(); diff --git a/litebox_platform_linux_kernel/src/host/snp/snp_impl.rs b/litebox_platform_linux_kernel/src/host/snp/snp_impl.rs index 42d30e4c3..cb0c4f5d1 100644 --- a/litebox_platform_linux_kernel/src/host/snp/snp_impl.rs +++ b/litebox_platform_linux_kernel/src/host/snp/snp_impl.rs @@ -326,21 +326,29 @@ impl HostSnpInterface { impl HostInterface for HostSnpInterface { fn send_ip_packet(packet: &[u8]) -> Result { - let mut req = bindings::SnpVmplRequestArgs::new_request( - bindings::SNP_VMPL_TUN_WRITE_REQ, - 3, - [packet.as_ptr() as u64, packet.len() as u64, 0, 0, 0, 0], - ); + let mut req = + bindings::SnpVmplRequestArgs::new_request(bindings::SNP_VMPL_TUN_WRITE_REQ, 3, [ + packet.as_ptr() as u64, + packet.len() as u64, + 0, + 0, + 0, + 0, + ]); Self::request(&mut req); Self::parse_result(req.ret) } fn receive_ip_packet(packet: &mut [u8]) -> Result { - let mut req = bindings::SnpVmplRequestArgs::new_request( - bindings::SNP_VMPL_TUN_READ_REQ, - 3, - [packet.as_ptr() as u64, packet.len() as u64, 0, 0, 0, 0], - ); + let mut req = + bindings::SnpVmplRequestArgs::new_request(bindings::SNP_VMPL_TUN_READ_REQ, 3, [ + packet.as_ptr() as u64, + packet.len() as u64, + 0, + 0, + 0, + 0, + ]); Self::request(&mut req); Self::parse_result(req.ret) } @@ -358,11 +366,14 @@ impl HostInterface for HostSnpInterface { ); assert!(size <= usize::try_from(PAGE_SIZE << bindings::SNP_VMPL_ALLOC_MAX_ORDER).unwrap()); - let mut req = bindings::SnpVmplRequestArgs::new_request( - bindings::SNP_VMPL_ALLOC_REQ, - 1, - [u64::from(bindings::SNP_VMPL_ALLOC_MAX_ORDER), 0, 0, 0, 0, 0], - ); + let mut req = bindings::SnpVmplRequestArgs::new_request(bindings::SNP_VMPL_ALLOC_REQ, 1, [ + u64::from(bindings::SNP_VMPL_ALLOC_MAX_ORDER), + 0, + 0, + 0, + 0, + 0, + ]); Self::request(&mut req); match Self::parse_alloc_result(bindings::SNP_VMPL_ALLOC_MAX_ORDER, req.ret) { Ok(addr) => Some(( @@ -385,11 +396,15 @@ impl HostInterface for HostSnpInterface { } fn terminate(reason_set: u64, reason_code: u64) -> ! { - let mut req = bindings::SnpVmplRequestArgs::new_request( - bindings::SNP_VMPL_TERMINATE_REQ, - 2, - [reason_set, reason_code, 0, 0, 0, 0], - ); + let mut req = + bindings::SnpVmplRequestArgs::new_request(bindings::SNP_VMPL_TERMINATE_REQ, 2, [ + reason_set, + reason_code, + 0, + 0, + 0, + 0, + ]); Self::request(&mut req); // In case hypervisor fails to terminate it or intentionally reschedules it, diff --git a/litebox_platform_linux_kernel/src/lib.rs b/litebox_platform_linux_kernel/src/lib.rs index 1ddec73e9..285ccdf5f 100644 --- a/litebox_platform_linux_kernel/src/lib.rs +++ b/litebox_platform_linux_kernel/src/lib.rs @@ -2,6 +2,7 @@ #![cfg(target_arch = "x86_64")] #![no_std] +#![feature(unsigned_is_multiple_of)] use core::sync::atomic::AtomicU64; use core::{arch::asm, sync::atomic::AtomicU32}; diff --git a/litebox_platform_linux_kernel/src/ptr.rs b/litebox_platform_linux_kernel/src/ptr.rs index b065c8b7f..5047c0abf 100644 --- a/litebox_platform_linux_kernel/src/ptr.rs +++ b/litebox_platform_linux_kernel/src/ptr.rs @@ -1,6 +1,6 @@ //! Userspace Pointer Abstraction -use litebox::mm::exception_table::__memcpy_fallible; +use litebox::mm::exception_table::__lb_memcpy_fallible; use litebox::platform::{RawConstPointer, RawMutPointer}; /// Represent a user space pointer to a read-only object @@ -23,7 +23,7 @@ unsafe fn read_at_offset<'a, T: Clone>( let src = unsafe { ptr.add(usize::try_from(count).ok()?) }; let mut data = core::mem::MaybeUninit::::uninit(); let failed_bytes = unsafe { - __memcpy_fallible( + __lb_memcpy_fallible( data.as_mut_ptr().cast(), src.cast(), core::mem::size_of::(), @@ -46,7 +46,7 @@ unsafe fn to_cow_slice<'a, T: Clone>( } let mut data = alloc::vec::Vec::::with_capacity(len); let failed_bytes = unsafe { - __memcpy_fallible( + __lb_memcpy_fallible( data.as_mut_ptr().cast(), ptr.cast(), len * core::mem::size_of::(), @@ -136,7 +136,7 @@ impl RawMutPointer for UserMutPtr { unsafe fn write_at_offset(self, count: isize, value: T) -> Option<()> { let dst = unsafe { self.inner.add(usize::try_from(count).ok()?) }; let failed_bytes = unsafe { - __memcpy_fallible( + __lb_memcpy_fallible( dst.cast(), (&raw const value).cast(), core::mem::size_of::(), @@ -162,7 +162,7 @@ impl RawMutPointer for UserMutPtr { } let dst = unsafe { self.inner.add(start_offset) }; let failed_bytes = unsafe { - __memcpy_fallible(dst.cast(), buf.as_ptr().cast(), core::mem::size_of_val(buf)) + __lb_memcpy_fallible(dst.cast(), buf.as_ptr().cast(), core::mem::size_of_val(buf)) }; if failed_bytes == 0 { Some(()) } else { None } } diff --git a/litebox_platform_linux_userland/src/lib.rs b/litebox_platform_linux_userland/src/lib.rs index b506636cf..8304cdd51 100644 --- a/litebox_platform_linux_userland/src/lib.rs +++ b/litebox_platform_linux_userland/src/lib.rs @@ -3,6 +3,10 @@ // Restrict this crate to only work on Linux. For now, we are restricting this to only x86/x86-64 // Linux, but we _may_ allow for more in the future, if we find it useful to do so. #![cfg(all(target_os = "linux", any(target_arch = "x86_64", target_arch = "x86")))] +#![feature(let_chains)] +#![feature(naked_functions)] +#![allow(named_asm_labels)] +#![allow(unsafe_op_in_unsafe_fn)] use std::cell::Cell; use std::os::fd::{AsRawFd as _, FromRawFd as _}; @@ -388,7 +392,7 @@ fn get_guest_fsbase() -> usize { /// When the guest thread terminates, this function returns after restoring /// non-volatile register state. #[cfg(target_arch = "x86_64")] -#[unsafe(naked)] +#[naked] unsafe extern "C-unwind" fn run_thread_inner(ctx: &mut litebox_common_linux::PtRegs) { core::arch::naked_asm!( " @@ -526,7 +530,7 @@ interrupt_callback: /// When the guest thread terminates, this function returns after restoring /// non-volatile register state. #[cfg(target_arch = "x86")] -#[unsafe(naked)] +#[naked] unsafe extern "fastcall-unwind" fn run_thread_inner(ctx: &mut litebox_common_linux::PtRegs) { core::arch::naked_asm!( " @@ -672,7 +676,7 @@ unsafe extern "fastcall-unwind" fn syscall_handler_fast(ctx: &mut litebox_common /// Do not call this at a point where the stack needs to be unwound to run /// destructors. #[cfg(target_arch = "x86_64")] -#[unsafe(naked)] +#[naked] unsafe extern "C" fn switch_to_guest(ctx: &litebox_common_linux::PtRegs) -> ! { core::arch::naked_asm!( "switch_to_guest_start:", @@ -740,7 +744,7 @@ interrupt: ); #[cfg(target_arch = "x86")] -#[unsafe(naked)] +#[naked] unsafe extern "fastcall" fn switch_to_guest(ctx: &litebox_common_linux::PtRegs) -> ! { core::arch::naked_asm!( "switch_to_guest_start:", diff --git a/litebox_platform_linux_userland/src/syscall_intercept/systrap.rs b/litebox_platform_linux_userland/src/syscall_intercept/systrap.rs index 673643362..b6822e970 100644 --- a/litebox_platform_linux_userland/src/syscall_intercept/systrap.rs +++ b/litebox_platform_linux_userland/src/syscall_intercept/systrap.rs @@ -88,45 +88,39 @@ fn register_seccomp_filter() { let rules = vec![ (libc::SYS_read, vec![backdoor_on_arg(3)]), (libc::SYS_write, vec![backdoor_on_arg(3)]), - ( - libc::SYS_mmap, - vec![ - // A backdoor to allow invoking mmap. - SeccompRule::new(vec![ - SeccompCondition::new( - 3, - SeccompCmpArgLen::Dword, - SeccompCmpOp::MaskedEq(u64::from(super::MMAP_FLAG_MAGIC)), - u64::from(super::MMAP_FLAG_MAGIC), - ) - .unwrap(), - ]) + (libc::SYS_mmap, vec![ + // A backdoor to allow invoking mmap. + SeccompRule::new(vec![ + SeccompCondition::new( + 3, + SeccompCmpArgLen::Dword, + SeccompCmpOp::MaskedEq(u64::from(super::MMAP_FLAG_MAGIC)), + u64::from(super::MMAP_FLAG_MAGIC), + ) .unwrap(), - ], - ), + ]) + .unwrap(), + ]), (libc::SYS_mprotect, vec![backdoor_on_arg(3)]), (libc::SYS_munmap, vec![backdoor_on_arg(2)]), - ( - libc::SYS_rt_sigaction, - vec![ - // Allow rt_sigaction for non-SIGSYS signals - SeccompRule::new(vec![ - SeccompCondition::new( - 0, - SeccompCmpArgLen::Dword, - SeccompCmpOp::Ne, - litebox_common_linux::Signal::SIGSYS as u64, - ) - .unwrap(), - ]) - .unwrap(), - SeccompRule::new(vec![ - // The second argument `act` is null, so it does not change the signal handler. - SeccompCondition::new(1, SeccompCmpArgLen::Qword, SeccompCmpOp::Eq, 0).unwrap(), - ]) + (libc::SYS_rt_sigaction, vec![ + // Allow rt_sigaction for non-SIGSYS signals + SeccompRule::new(vec![ + SeccompCondition::new( + 0, + SeccompCmpArgLen::Dword, + SeccompCmpOp::Ne, + litebox_common_linux::Signal::SIGSYS as u64, + ) .unwrap(), - ], - ), + ]) + .unwrap(), + SeccompRule::new(vec![ + // The second argument `act` is null, so it does not change the signal handler. + SeccompCondition::new(1, SeccompCmpArgLen::Qword, SeccompCmpOp::Eq, 0).unwrap(), + ]) + .unwrap(), + ]), ( // allow rt_sigprocmask that does not block SIGSYS libc::SYS_rt_sigprocmask, @@ -149,33 +143,30 @@ fn register_seccomp_filter() { (libc::SYS_mremap, vec![backdoor_on_arg(5)]), (libc::SYS_sigaltstack, vec![]), (libc::SYS_arch_prctl, vec![backdoor_on_arg(2)]), - ( - libc::SYS_futex, - vec![ - SeccompRule::new(vec![ - SeccompCondition::new( - 1, - SeccompCmpArgLen::Dword, - SeccompCmpOp::MaskedEq(0x7f), - libc::FUTEX_WAIT as u64, - ) - .unwrap(), - backdoor_cond_on_arg(5), - ]) + (libc::SYS_futex, vec![ + SeccompRule::new(vec![ + SeccompCondition::new( + 1, + SeccompCmpArgLen::Dword, + SeccompCmpOp::MaskedEq(0x7f), + libc::FUTEX_WAIT as u64, + ) .unwrap(), - SeccompRule::new(vec![ - SeccompCondition::new( - 1, - SeccompCmpArgLen::Dword, - SeccompCmpOp::MaskedEq(0x7f), - libc::FUTEX_WAKE as u64, - ) - .unwrap(), - backdoor_cond_on_arg(5), - ]) + backdoor_cond_on_arg(5), + ]) + .unwrap(), + SeccompRule::new(vec![ + SeccompCondition::new( + 1, + SeccompCmpArgLen::Dword, + SeccompCmpOp::MaskedEq(0x7f), + libc::FUTEX_WAKE as u64, + ) .unwrap(), - ], - ), + backdoor_cond_on_arg(5), + ]) + .unwrap(), + ]), (libc::SYS_exit, vec![backdoor_on_arg(1)]), (libc::SYS_exit_group, vec![backdoor_on_arg(1)]), (libc::SYS_tgkill, vec![]), diff --git a/litebox_platform_lvbs/src/lib.rs b/litebox_platform_lvbs/src/lib.rs index 592267240..5a2651207 100644 --- a/litebox_platform_lvbs/src/lib.rs +++ b/litebox_platform_lvbs/src/lib.rs @@ -3,6 +3,10 @@ #![cfg(target_arch = "x86_64")] #![no_std] #![cfg_attr(feature = "interrupt", feature(abi_x86_interrupt))] +#![feature(let_chains)] +#![feature(unsigned_is_multiple_of)] +#![feature(naked_functions)] +#![allow(unsafe_op_in_unsafe_fn)] use crate::{ mshv::{vsm::Vtl0KernelInfo, vtl1_mem_layout::PAGE_SIZE}, diff --git a/litebox_platform_lvbs/src/mshv/mem_integrity.rs b/litebox_platform_lvbs/src/mshv/mem_integrity.rs index db5afbcc1..474665897 100644 --- a/litebox_platform_lvbs/src/mshv/mem_integrity.rs +++ b/litebox_platform_lvbs/src/mshv/mem_integrity.rs @@ -356,7 +356,7 @@ pub fn parse_modinfo(original_elf_data: &[u8]) -> Result<(), KernelElfError> { let modinfo_data = &original_elf_data[start..end]; for entry in modinfo_data.split(|&b| b == 0) { - if let Ok(s) = str::from_utf8(entry) + if let Ok(s) = core::str::from_utf8(entry) && let Some((k, v)) = s.split_once('=') && k == "name" { diff --git a/litebox_platform_lvbs/src/mshv/vtl_switch.rs b/litebox_platform_lvbs/src/mshv/vtl_switch.rs index 2855160b4..31580b497 100644 --- a/litebox_platform_lvbs/src/mshv/vtl_switch.rs +++ b/litebox_platform_lvbs/src/mshv/vtl_switch.rs @@ -88,7 +88,7 @@ fn save_vtl_state_to_per_cpu_variables(vtl: u8, vtl_state: *const VtlState) { } // Save CPU registers to a global data structure through using a stack -#[unsafe(naked)] +#[naked] unsafe extern "C" fn save_vtl0_state() { naked_asm!( "push r15", @@ -124,7 +124,7 @@ unsafe extern "C" fn save_vtl0_state() { } const STACK_ALIGNMENT: isize = -16; -#[unsafe(naked)] +#[naked] unsafe extern "C" fn save_vtl1_state() { naked_asm!( "push r15", @@ -168,7 +168,7 @@ fn load_vtl_state_from_per_cpu_variables(vtl: u8, vtl_state: *mut VtlState) { } // Restore CPU registers from the global data structure through using a stack. -#[unsafe(naked)] +#[naked] unsafe extern "C" fn load_vtl_state(vtl: u8) { naked_asm!( "sub rsp, {register_space}", @@ -240,7 +240,7 @@ fn jump_to_vtl_switch_loop_with_stack_cleanup() -> ! { } /// expose `vtl_switch_loop` to the outside (e.g., the syscall handler) -#[unsafe(naked)] +#[naked] pub(crate) unsafe extern "C" fn jump_to_vtl_switch_loop() -> ! { naked_asm!( "call {loop}", diff --git a/litebox_platform_lvbs/src/syscall_entry.rs b/litebox_platform_lvbs/src/syscall_entry.rs index 2c0cfe81f..720be95d4 100644 --- a/litebox_platform_lvbs/src/syscall_entry.rs +++ b/litebox_platform_lvbs/src/syscall_entry.rs @@ -191,7 +191,7 @@ fn syscall_entry(sysnr: u64, ctx_raw: *const SyscallContextRaw) -> usize { unreachable!() } -#[unsafe(naked)] +#[naked] unsafe extern "C" fn syscall_entry_wrapper() { naked_asm!( "swapgs", diff --git a/litebox_platform_multiplex/Cargo.toml b/litebox_platform_multiplex/Cargo.toml index 53abe0148..27ecf995f 100644 --- a/litebox_platform_multiplex/Cargo.toml +++ b/litebox_platform_multiplex/Cargo.toml @@ -9,6 +9,7 @@ litebox_platform_linux_userland = { path = "../litebox_platform_linux_userland/" litebox_platform_linux_kernel = { path = "../litebox_platform_linux_kernel/", version = "0.1.0", default-features = false, optional = true } litebox_platform_windows_userland = { path = "../litebox_platform_windows_userland/", version = "0.1.0", default-features = false, optional = true } litebox_platform_lvbs = { path = "../litebox_platform_lvbs/", version = "0.1.0", default-features = false, optional = true } +platform = { path = "../ostd-test/platform/", optional = true } once_cell = { version = "1.20.2", default-features = false, features = ["alloc", "race"] } cfg-if = "1.0.0" @@ -18,6 +19,7 @@ platform_linux_userland = ["dep:litebox_platform_linux_userland"] platform_windows_userland = ["dep:litebox_platform_windows_userland"] platform_lvbs = ["dep:litebox_platform_lvbs"] platform_linux_snp = ["dep:litebox_platform_linux_kernel"] +platform_ostd = ["dep:platform"] systrap_backend = ["platform_linux_userland", "litebox_platform_linux_userland/systrap_backend"] platform_linux_userland_with_linux_syscall = ["platform_linux_userland", "litebox_platform_linux_userland/linux_syscall"] platform_linux_userland_with_optee_syscall = ["platform_linux_userland", "litebox_platform_linux_userland/optee_syscall"] diff --git a/litebox_platform_multiplex/src/lib.rs b/litebox_platform_multiplex/src/lib.rs index fdccec5ea..26d55d7bc 100644 --- a/litebox_platform_multiplex/src/lib.rs +++ b/litebox_platform_multiplex/src/lib.rs @@ -32,6 +32,8 @@ cfg_if::cfg_if! { pub type Platform = litebox_platform_lvbs::host::LvbsLinuxKernel; } else if #[cfg(feature = "platform_linux_snp")] { pub type Platform = litebox_platform_linux_kernel::host::snp::snp_impl::SnpLinuxKernel; + } else if #[cfg(feature = "platform_ostd")] { + pub type Platform = platform::OstdPlatform; } else { compile_error!( r##"Hint: you might have forgotten to mark 'default-features = false'."## diff --git a/litebox_platform_windows_userland/src/lib.rs b/litebox_platform_windows_userland/src/lib.rs index 02d21545b..4b06b4bcc 100644 --- a/litebox_platform_windows_userland/src/lib.rs +++ b/litebox_platform_windows_userland/src/lib.rs @@ -1898,23 +1898,20 @@ mod tests { .as_usize(); // Even though `fixed_address` is false, we should still get the requested address if it's free. assert_eq!(addr2, addr + 0x8000); - assert_eq!( - collect_regions(addr..addr + 0x1_0000), - vec![ - ( - addr..addr + 0x1000, - windows_sys::Win32::System::Memory::MEM_COMMIT - ), - ( - addr + 0x1000..addr + 0x8000, - windows_sys::Win32::System::Memory::MEM_RESERVE - ), - ( - addr + 0x8000..addr + 0x1_0000, - windows_sys::Win32::System::Memory::MEM_COMMIT - ), - ] - ); + assert_eq!(collect_regions(addr..addr + 0x1_0000), vec![ + ( + addr..addr + 0x1000, + windows_sys::Win32::System::Memory::MEM_COMMIT + ), + ( + addr + 0x1000..addr + 0x8000, + windows_sys::Win32::System::Memory::MEM_RESERVE + ), + ( + addr + 0x8000..addr + 0x1_0000, + windows_sys::Win32::System::Memory::MEM_COMMIT + ), + ]); // Try to allocate [addr + 0x4000, addr + 0x1_0000), which overlaps with existing committed pages. // OS should allocate a new region instead of the requested one (as `fixed_address` is false) diff --git a/litebox_runner_linux_userland/tests/loader.rs b/litebox_runner_linux_userland/tests/loader.rs index e4a543af6..eb068084f 100644 --- a/litebox_runner_linux_userland/tests/loader.rs +++ b/litebox_runner_linux_userland/tests/loader.rs @@ -233,16 +233,12 @@ fn test_syscall_rewriter() { // rewrite the hello_exec_nolibc let hooked_path = std::path::Path::new(dir_path.as_str()).join("hello_exec_nolibc.hooked"); let _ = std::fs::remove_file(hooked_path.clone()); - let rewrite_success = common::rewrite_with_cache( - &path, - &hooked_path, - &[ - "--trampoline-addr", - litebox_shim_linux::loader::REWRITER_MAGIC_NUMBER - .to_string() - .as_str(), - ], - ); + let rewrite_success = common::rewrite_with_cache(&path, &hooked_path, &[ + "--trampoline-addr", + litebox_shim_linux::loader::REWRITER_MAGIC_NUMBER + .to_string() + .as_str(), + ]); assert!(rewrite_success, "failed to run syscall rewriter"); let executable_path = "/hello_exec_nolibc.hooked"; diff --git a/litebox_runner_optee_on_linux_userland/src/lib.rs b/litebox_runner_optee_on_linux_userland/src/lib.rs index 74d288656..1e0059355 100644 --- a/litebox_runner_optee_on_linux_userland/src/lib.rs +++ b/litebox_runner_optee_on_linux_userland/src/lib.rs @@ -111,13 +111,10 @@ fn run_ta_with_default_commands(ta_info: &ElfLoadInfo) { // Each OP-TEE TA has its own UUID. // The client of a session can be a normal-world (VTL0) application or another TA (at VTL1). // The VTL0 kernel is expected to provide the client identity information. - let _litebox = litebox_shim_optee::init_session( - &TeeUuid::default(), - &TeeIdentity { - login: TeeLogin::User, - uuid: TeeUuid::default(), - }, - ); + let _litebox = litebox_shim_optee::init_session(&TeeUuid::default(), &TeeIdentity { + login: TeeLogin::User, + uuid: TeeUuid::default(), + }); } // In OP-TEE TA, each command invocation is like (re)starting the TA with a new stack with diff --git a/litebox_runner_optee_on_linux_userland/src/tests.rs b/litebox_runner_optee_on_linux_userland/src/tests.rs index 39f2fdeea..b35422a81 100644 --- a/litebox_runner_optee_on_linux_userland/src/tests.rs +++ b/litebox_runner_optee_on_linux_userland/src/tests.rs @@ -34,13 +34,10 @@ pub fn run_ta_with_test_commands(ta_info: &ElfLoadInfo, prog_name: &str, json_pa }; if func_id == UteeEntryFunc::OpenSession { - let _litebox = litebox_shim_optee::init_session( - &TeeUuid::default(), - &TeeIdentity { - login: TeeLogin::User, - uuid: TeeUuid::default(), - }, - ); + let _litebox = litebox_shim_optee::init_session(&TeeUuid::default(), &TeeIdentity { + login: TeeLogin::User, + uuid: TeeUuid::default(), + }); } // special handling for the KMPP TA whose `OpenSession` expects a session ID that we cannot determine in advance diff --git a/litebox_shim_linux/src/lib.rs b/litebox_shim_linux/src/lib.rs index e9bc994d7..00caf0d9a 100644 --- a/litebox_shim_linux/src/lib.rs +++ b/litebox_shim_linux/src/lib.rs @@ -8,6 +8,9 @@ clippy::unused_self, reason = "by convention, syscalls and related methods take &self even if unused" )] +#![feature(let_chains)] +#![feature(unsigned_is_multiple_of)] +#![feature(result_flattening)] extern crate alloc; diff --git a/litebox_shim_linux/src/syscalls/epoll.rs b/litebox_shim_linux/src/syscalls/epoll.rs index 00f81ab99..f48a42795 100644 --- a/litebox_shim_linux/src/syscalls/epoll.rs +++ b/litebox_shim_linux/src/syscalls/epoll.rs @@ -618,14 +618,10 @@ mod test { let consumer = Arc::new(consumer); let reader = super::EpollDescriptor::Pipe(Arc::clone(&consumer)); epoll - .add_interest( - 10, - &reader, - EpollEvent { - events: Events::IN.bits(), - data: 0, - }, - ) + .add_interest(10, &reader, EpollEvent { + events: Events::IN.bits(), + data: 0, + }) .unwrap(); // spawn a thread to write to the pipe diff --git a/litebox_shim_linux/src/syscalls/file.rs b/litebox_shim_linux/src/syscalls/file.rs index ccbccf6fc..6c21bf03a 100644 --- a/litebox_shim_linux/src/syscalls/file.rs +++ b/litebox_shim_linux/src/syscalls/file.rs @@ -1120,15 +1120,12 @@ impl Task { files .file_descriptors .write() - .insert( - self, - Descriptor::Eventfd { - file: alloc::sync::Arc::new(eventfd), - close_on_exec: core::sync::atomic::AtomicBool::new( - flags.contains(EfdFlags::CLOEXEC), - ), - }, - ) + .insert(self, Descriptor::Eventfd { + file: alloc::sync::Arc::new(eventfd), + close_on_exec: core::sync::atomic::AtomicBool::new( + flags.contains(EfdFlags::CLOEXEC), + ), + }) .map_err(|desc| self.do_close(desc).err().unwrap_or(Errno::EMFILE)) } @@ -1139,32 +1136,26 @@ impl Task { match arg { IoctlArg::TCGETS(termios) => { unsafe { - termios.write_at_offset( - 0, - litebox_common_linux::Termios { - c_iflag: 0, - c_oflag: 0, - c_cflag: 0, - c_lflag: 0, - c_line: 0, - c_cc: [0; 19], - }, - ) + termios.write_at_offset(0, litebox_common_linux::Termios { + c_iflag: 0, + c_oflag: 0, + c_cflag: 0, + c_lflag: 0, + c_line: 0, + c_cc: [0; 19], + }) } .ok_or(Errno::EFAULT)?; Ok(0) } IoctlArg::TCSETS(_) => Ok(0), // TODO: implement IoctlArg::TIOCGWINSZ(ws) => unsafe { - ws.write_at_offset( - 0, - litebox_common_linux::Winsize { - row: 20, - col: 20, - xpixel: 0, - ypixel: 0, - }, - ) + ws.write_at_offset(0, litebox_common_linux::Winsize { + row: 20, + col: 20, + xpixel: 0, + ypixel: 0, + }) .ok_or(Errno::EFAULT)?; Ok(0) }, @@ -1308,15 +1299,12 @@ impl Task { files .file_descriptors .write() - .insert( - self, - Descriptor::Epoll { - file: alloc::sync::Arc::new(epoll_file), - close_on_exec: core::sync::atomic::AtomicBool::new( - flags.contains(EpollCreateFlags::EPOLL_CLOEXEC), - ), - }, - ) + .insert(self, Descriptor::Epoll { + file: alloc::sync::Arc::new(epoll_file), + close_on_exec: core::sync::atomic::AtomicBool::new( + flags.contains(EpollCreateFlags::EPOLL_CLOEXEC), + ), + }) .map_err(|desc| self.do_close(desc).err().unwrap_or(Errno::EMFILE)) } diff --git a/litebox_shim_linux/src/syscalls/misc.rs b/litebox_shim_linux/src/syscalls/misc.rs index 7aac317ef..492e9b983 100644 --- a/litebox_shim_linux/src/syscalls/misc.rs +++ b/litebox_shim_linux/src/syscalls/misc.rs @@ -145,13 +145,10 @@ impl Task { } _ => { unsafe { - header.write_at_offset( - 0, - litebox_common_linux::CapHeader { - version: _LINUX_CAPABILITY_VERSION_3, - pid: hdr.pid, - }, - ) + header.write_at_offset(0, litebox_common_linux::CapHeader { + version: _LINUX_CAPABILITY_VERSION_3, + pid: hdr.pid, + }) } .ok_or(Errno::EFAULT)?; if data.is_none() { diff --git a/litebox_shim_linux/src/syscalls/net.rs b/litebox_shim_linux/src/syscalls/net.rs index 5b03d72a5..76d588161 100644 --- a/litebox_shim_linux/src/syscalls/net.rs +++ b/litebox_shim_linux/src/syscalls/net.rs @@ -251,19 +251,16 @@ fn setsockopt( let data = unsafe { optval.to_cow_slice(TCP_CONGESTION_NAME_MAX.min(optlen)) } .ok_or(Errno::EFAULT)?; let name = core::str::from_utf8(&data).map_err(|_| Errno::EINVAL)?; - litebox_net().lock().set_tcp_option( - fd, - match name { - "reno" | "cubic" => { - log_unsupported!("enable {} for smoltcp?", name); - return Err(Errno::EINVAL); - } - "none" => litebox::net::TcpOptionData::CONGESTION( - litebox::net::CongestionControl::None, - ), - _ => return Err(Errno::EINVAL), - }, - )?; + litebox_net().lock().set_tcp_option(fd, match name { + "reno" | "cubic" => { + log_unsupported!("enable {} for smoltcp?", name); + return Err(Errno::EINVAL); + } + "none" => litebox::net::TcpOptionData::CONGESTION( + litebox::net::CongestionControl::None, + ), + _ => return Err(Errno::EINVAL), + })?; Ok(()) } TcpOption::KEEPCNT | TcpOption::KEEPIDLE | TcpOption::INFO => { diff --git a/litebox_shim_linux/src/syscalls/tests.rs b/litebox_shim_linux/src/syscalls/tests.rs index cc41caa74..9fb3234c2 100644 --- a/litebox_shim_linux/src/syscalls/tests.rs +++ b/litebox_shim_linux/src/syscalls/tests.rs @@ -221,10 +221,14 @@ fn test_getdent64() { .map(|(name, _, _)| name.clone()) .collect(); entry_names.sort(); - assert_eq!( - entry_names, - alloc::vec![".", "..", "bar", "foo", "test_file1.txt", "test_file2.txt"] - ); + assert_eq!(entry_names, alloc::vec![ + ".", + "..", + "bar", + "foo", + "test_file1.txt", + "test_file2.txt" + ]); // Verify that our test files have the correct type (regular file) for (name, typ, _) in &found_entries { @@ -382,10 +386,14 @@ fn test_getdent64() { // Verify we still got our expected entries through chunked reading all_entries.sort(); - assert_eq!( - all_entries, - alloc::vec![".", "..", "bar", "foo", "test_file1.txt", "test_file2.txt"] - ); + assert_eq!(all_entries, alloc::vec![ + ".", + "..", + "bar", + "foo", + "test_file1.txt", + "test_file2.txt" + ]); } #[test] diff --git a/litebox_shim_optee/src/lib.rs b/litebox_shim_optee/src/lib.rs index 517526d0c..47c3f9a02 100644 --- a/litebox_shim_optee/src/lib.rs +++ b/litebox_shim_optee/src/lib.rs @@ -2,6 +2,9 @@ #![cfg(target_arch = "x86_64")] #![no_std] +#![feature(let_chains)] +#![feature(unsigned_is_multiple_of)] +#![feature(result_flattening)] extern crate alloc; diff --git a/litebox_syscall_rewriter/src/lib.rs b/litebox_syscall_rewriter/src/lib.rs index a8fb646a6..362d359e2 100644 --- a/litebox_syscall_rewriter/src/lib.rs +++ b/litebox_syscall_rewriter/src/lib.rs @@ -11,6 +11,9 @@ //! //! This crate currently only supports x86-64 (i.e., amd64) ELFs. +#![feature(let_chains)] +#![feature(unsigned_is_multiple_of)] + use capstone::arch::x86::X86InsnGroup::{X86_GRP_CALL, X86_GRP_JUMP, X86_GRP_RET}; use capstone::prelude::*; diff --git a/ostd-test/platform/.gitignore b/ostd-test/platform/.gitignore new file mode 100644 index 000000000..ea8c4bf7f --- /dev/null +++ b/ostd-test/platform/.gitignore @@ -0,0 +1 @@ +/target diff --git a/ostd-test/platform/Cargo.toml b/ostd-test/platform/Cargo.toml new file mode 100644 index 000000000..f48b5713a --- /dev/null +++ b/ostd-test/platform/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "platform" +version = "0.1.0" +edition = "2024" + +[dependencies] +ostd = "0.16.1" +spin = "0.9.8" +litebox = { path = "../../litebox" } +litebox_common_linux = { path = "../../litebox_common_linux" } diff --git a/ostd-test/platform/src/lib.rs b/ostd-test/platform/src/lib.rs new file mode 100644 index 000000000..2e5047dcf --- /dev/null +++ b/ostd-test/platform/src/lib.rs @@ -0,0 +1,665 @@ +#![no_std] + +use litebox::platform::common_providers::userspace_pointers::{UserConstPtr, UserMutPtr}; +use ostd::arch::cpu::context::UserContext; + +extern crate alloc; + +macro_rules! debug { + ($($arg:tt)*) => { + // ostd::console::early_print(format_args!($($arg)*)); + }; +} + +pub struct OstdPlatform { + vm_space: alloc::sync::Arc, +} + +static SHIM: spin::Once< + &'static dyn litebox::shim::EnterShim, +> = spin::Once::new(); + +impl core::fmt::Debug for OstdPlatform { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_struct("OstdPlatform").finish_non_exhaustive() + } +} + +impl OstdPlatform { + pub fn new() -> OstdPlatform { + OstdPlatform { + vm_space: alloc::sync::Arc::new(ostd::mm::VmSpace::new()), + } + } + + // XXX: We prob should not be exposing this directly like this, but this is a quick workaround. + pub fn activate_vm_space(&self) { + self.vm_space.activate(); + } + + pub fn register_shim( + &self, + shim: &'static dyn litebox::shim::EnterShim, + ) { + if SHIM.is_completed() { + panic!("should not register more than one shim"); + } + SHIM.call_once(|| shim); + } +} + +impl litebox::platform::Provider for OstdPlatform {} + +impl litebox::platform::RawPointerProvider for OstdPlatform { + type RawConstPointer = UserConstPtr; + type RawMutPointer = UserMutPtr; +} + +impl litebox::platform::DebugLogProvider for OstdPlatform { + fn debug_log_print(&self, msg: &str) { + ostd::console::early_print(format_args!("{}", msg)); + } +} + +pub struct PunchthroughToken { + punchthrough: litebox_common_linux::PunchthroughSyscall, +} + +impl litebox::platform::PunchthroughToken for PunchthroughToken { + type Punchthrough = litebox_common_linux::PunchthroughSyscall; + fn execute( + self, + ) -> Result< + ::ReturnSuccess, + litebox::platform::PunchthroughError< + ::ReturnFailure, + >, + > { + match self.punchthrough { + #[cfg(target_arch = "x86_64")] + litebox_common_linux::PunchthroughSyscall::SetFsBase { addr } => { + unsafe { litebox_common_linux::wrfsbase(addr) }; + Ok(0) + } + #[cfg(target_arch = "x86_64")] + litebox_common_linux::PunchthroughSyscall::GetFsBase { addr } => { + use litebox::platform::RawMutPointer as _; + let fs_base = unsafe { litebox_common_linux::rdfsbase() }; + unsafe { addr.write_at_offset(0, fs_base) } + .map(|()| 0) + .ok_or(litebox::platform::PunchthroughError::Failure( + litebox_common_linux::errno::Errno::EFAULT, + )) + } + _ => unimplemented!("{:?}", self.punchthrough), + } + } +} + +impl litebox::platform::PunchthroughProvider for OstdPlatform { + type PunchthroughToken = PunchthroughToken; + fn get_punchthrough_token_for( + &self, + punchthrough: ::Punchthrough, + ) -> Option { + Some(PunchthroughToken { punchthrough }) + } +} + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct Instant { + from_boot: core::time::Duration, +} +pub struct SystemTime { + // TODO: actual time somehow? + from_boot: core::time::Duration, +} +impl litebox::platform::Instant for Instant { + fn checked_duration_since(&self, earlier: &Self) -> Option { + self.from_boot.checked_sub(earlier.from_boot) + } + fn checked_add(&self, _duration: core::time::Duration) -> Option { + todo!() + } +} +impl litebox::platform::SystemTime for SystemTime { + const UNIX_EPOCH: Self = Self { + from_boot: core::time::Duration::new(0, 0), + }; + fn duration_since(&self, earlier: &Self) -> Result { + self.from_boot + .checked_sub(earlier.from_boot) + .ok_or_else(|| self.from_boot.abs_diff(earlier.from_boot)) + } +} + +impl litebox::platform::TimeProvider for OstdPlatform { + type Instant = Instant; + type SystemTime = SystemTime; + fn now(&self) -> Self::Instant { + Instant { + from_boot: ostd::timer::Jiffies::elapsed().as_duration(), + } + } + fn current_time(&self) -> Self::SystemTime { + SystemTime { + from_boot: ostd::timer::Jiffies::elapsed().as_duration(), + } + } +} + +impl litebox::platform::IPInterfaceProvider for OstdPlatform { + fn send_ip_packet(&self, _packet: &[u8]) -> Result<(), litebox::platform::SendError> { + todo!() + } + fn receive_ip_packet( + &self, + _packet: &mut [u8], + ) -> Result { + todo!() + } +} + +pub struct RawMutex { + atomic: core::sync::atomic::AtomicU32, + wait_queue: ostd::sync::WaitQueue, +} + +impl litebox::platform::RawMutex for RawMutex { + fn underlying_atomic(&self) -> &core::sync::atomic::AtomicU32 { + &self.atomic + } + + fn wake_many(&self, n: usize) -> usize { + assert!(n > 0); + if n == 1 { + if self.wait_queue.wake_one() { 1 } else { 0 } + } else { + self.wait_queue.wake_all() + } + } + + // XXX: Not 100% sure that these semantics match what we need, but they should be close enough + // to work for now. + fn block(&self, val: u32) -> Result<(), litebox::platform::ImmediatelyWokenUp> { + let mut first_check = true; + self.wait_queue.wait_until(|| { + let current = self.atomic.load(core::sync::atomic::Ordering::Acquire); + if current != val { + if first_check { + Some(Err(litebox::platform::ImmediatelyWokenUp)) + } else { + Some(Ok(())) + } + } else { + first_check = false; + None + } + }) + } + fn block_or_timeout( + &self, + val: u32, + time: core::time::Duration, + ) -> Result { + let start = ostd::timer::Jiffies::elapsed(); + let deadline = start.as_duration().as_nanos() + time.as_nanos(); + let mut first_check = true; + self.wait_queue.wait_until(|| { + let current = self.atomic.load(core::sync::atomic::Ordering::Acquire); + if current != val { + if first_check { + Some(Err(litebox::platform::ImmediatelyWokenUp)) + } else { + Some(Ok(litebox::platform::UnblockedOrTimedOut::Unblocked)) + } + } else { + first_check = false; + if ostd::timer::Jiffies::elapsed().as_duration().as_nanos() >= deadline { + Some(Ok(litebox::platform::UnblockedOrTimedOut::TimedOut)) + } else { + None + } + } + }) + } +} + +impl litebox::platform::RawMutexProvider for OstdPlatform { + type RawMutex = RawMutex; + fn new_raw_mutex(&self) -> Self::RawMutex { + RawMutex { + atomic: core::sync::atomic::AtomicU32::new(0), + wait_queue: ostd::sync::WaitQueue::new(), + } + } +} + +impl litebox::platform::StdioProvider for OstdPlatform { + fn read_from_stdin(&self, _buf: &mut [u8]) -> Result { + todo!() + } + fn write_to( + &self, + _stream: litebox::platform::StdioOutStream, + buf: &[u8], + ) -> Result { + debug!("[write] {_stream:?}\n"); + ostd::console::early_print(format_args!( + "{}", + alloc::string::String::from_utf8_lossy(buf), + )); + Ok(buf.len()) + } + fn is_a_tty(&self, _stream: litebox::platform::StdioStream) -> bool { + todo!() + } +} + +impl litebox::platform::PageManagementProvider<4096> for OstdPlatform { + const TASK_ADDR_MIN: usize = 0x1000; + const TASK_ADDR_MAX: usize = 0x8000_0000_0000; + + fn allocate_pages( + &self, + suggested_range: core::ops::Range, + initial_permissions: litebox::platform::page_mgmt::MemoryRegionPermissions, + _can_grow_down: bool, + populate_pages_immediately: bool, + _fixed_address_behavior: litebox::platform::page_mgmt::FixedAddressBehavior, + ) -> Result, litebox::platform::page_mgmt::AllocationError> { + use litebox::platform::page_mgmt::AllocationError; + use ostd::mm::{CachePolicy, FrameAllocOptions, PageProperty}; + + debug!( + "[allocate_pages] range={:#x}..{:#x}, populate={}\n", + suggested_range.start, suggested_range.end, populate_pages_immediately + ); + + let vm_space = &self.vm_space; + debug!("[allocate_pages] Got VmSpace\n"); + + let size = suggested_range.end.saturating_sub(suggested_range.start); + if size == 0 { + debug!("[allocate_pages] ERROR: Size is 0\n"); + return Err(AllocationError::InvalidRange); + } + let num_pages = (size + 4095) / 4096; + debug!( + "[allocate_pages] Allocating {} pages (size={:#x})\n", + num_pages, size + ); + + let segment = if populate_pages_immediately { + FrameAllocOptions::new() + .zeroed(true) + .alloc_segment(num_pages) + } else { + FrameAllocOptions::new().alloc_segment(num_pages) + } + .map_err(|_e| { + debug!( + "[allocate_pages] ERROR: Failed to allocate segment: {:?}\n", + _e + ); + AllocationError::OutOfMemory + })?; + debug!("[allocate_pages] Allocated segment\n"); + + let flags = convert_permissions_to_flags(initial_permissions); + let page_prop = PageProperty::new_user(flags, CachePolicy::Writeback); + + debug!("[allocate_pages] Creating cursor\n"); + let guard = ostd::task::disable_preempt(); + let mut cursor = vm_space + .cursor_mut(&guard, &suggested_range) + .map_err(|_e| { + debug!( + "[allocate_pages] ERROR: Failed to create cursor: {:?}\n", + _e + ); + AllocationError::OutOfMemory + })?; + debug!("[allocate_pages] Mapping frames\n"); + + for frame in segment.into_iter() { + cursor.map(frame.into(), page_prop); + } + debug!("[allocate_pages] All frames mapped\n"); + + debug!("[allocate_pages] Flushing TLB\n"); + cursor + .flusher() + .issue_tlb_flush(ostd::mm::tlb::TlbFlushOp::for_range( + suggested_range.clone(), + )); + + debug!("[allocate_pages] Success\n"); + use litebox::platform::RawConstPointer; + Ok(UserMutPtr::from_usize(suggested_range.start)) + } + + unsafe fn deallocate_pages( + &self, + range: core::ops::Range, + ) -> Result<(), litebox::platform::page_mgmt::DeallocationError> { + use litebox::platform::page_mgmt::DeallocationError; + + debug!( + "[deallocate_pages] range={:#x}..{:#x}\n", + range.start, range.end + ); + + let vm_space = &self.vm_space; + + let size = range.end.saturating_sub(range.start); + if size == 0 || size % 4096 != 0 { + debug!("[deallocate_pages] ERROR: Invalid size {:#x}\n", size); + return Err(DeallocationError::Unaligned); + } + let num_pages = size / 4096; + debug!("[deallocate_pages] Unmapping {} pages\n", num_pages); + + let guard = ostd::task::disable_preempt(); + let mut cursor = vm_space + .cursor_mut(&guard, &range) + .map_err(|_| DeallocationError::Unaligned)?; + + let unmapped = cursor.unmap(num_pages); + if unmapped != num_pages { + debug!( + "[deallocate_pages] ERROR: Only unmapped {} of {} pages\n", + unmapped, num_pages + ); + return Err(DeallocationError::AlreadyUnallocated); + } + + cursor + .flusher() + .issue_tlb_flush(ostd::mm::tlb::TlbFlushOp::for_range(range)); + + debug!("[deallocate_pages] Success\n"); + Ok(()) + } + + unsafe fn update_permissions( + &self, + range: core::ops::Range, + new_permissions: litebox::platform::page_mgmt::MemoryRegionPermissions, + ) -> Result<(), litebox::platform::page_mgmt::PermissionUpdateError> { + use litebox::platform::page_mgmt::PermissionUpdateError; + + debug!( + "[update_permissions] range={:#x}..{:#x}, perms={:?}\n", + range.start, range.end, new_permissions + ); + + let vm_space = &self.vm_space; + + let size = range.end.saturating_sub(range.start); + if size == 0 || size % 4096 != 0 { + debug!("[update_permissions] ERROR: Invalid size {:#x}\n", size); + return Err(PermissionUpdateError::Unaligned); + } + debug!("[update_permissions] Updating {} pages\n", size / 4096); + + let new_flags = convert_permissions_to_flags(new_permissions); + + let guard = ostd::task::disable_preempt(); + let mut cursor = vm_space + .cursor_mut(&guard, &range) + .map_err(|_| PermissionUpdateError::Unaligned)?; + + debug!("[update_permissions] Protecting pages with new flags\n"); + let mut remaining_size = size; + while remaining_size > 0 { + match cursor.protect_next(remaining_size, |flags, _cache_policy| { + *flags = new_flags; + }) { + Some(protected_range) => { + let protected_size = protected_range.end - protected_range.start; + remaining_size = remaining_size.saturating_sub(protected_size); + } + None => { + debug!("[update_permissions] ERROR: No more mapped pages to protect\n"); + return Err(PermissionUpdateError::Unallocated); + } + } + } + + debug!("[update_permissions] Flushing TLB\n"); + cursor + .flusher() + .issue_tlb_flush(ostd::mm::tlb::TlbFlushOp::for_range(range)); + + debug!("[update_permissions] Success\n"); + Ok(()) + } + + fn reserved_pages(&self) -> impl Iterator> { + // TODO: Query the VmSpace or system for reserved ranges + core::iter::empty() + } +} + +fn convert_permissions_to_flags( + perms: litebox::platform::page_mgmt::MemoryRegionPermissions, +) -> ostd::mm::PageFlags { + use litebox::platform::page_mgmt::MemoryRegionPermissions; + use ostd::mm::PageFlags; + + let mut flags = PageFlags::empty(); + if perms.contains(MemoryRegionPermissions::READ) { + flags |= PageFlags::R; + } + if perms.contains(MemoryRegionPermissions::WRITE) { + flags |= PageFlags::W; + } + if perms.contains(MemoryRegionPermissions::EXEC) { + flags |= PageFlags::X; + } + flags +} + +impl litebox::platform::SystemInfoProvider for OstdPlatform { + fn get_syscall_entry_point(&self) -> usize { + todo!() + } + + fn get_vdso_address(&self) -> Option { + None + } +} + +// XXX: Maybe should use current task instead? `Task::current` +ostd::cpu_local! { + static TLS_POINTER: core::sync::atomic::AtomicUsize = core::sync::atomic::AtomicUsize::new(0); +} + +unsafe impl litebox::platform::ThreadLocalStorageProvider for OstdPlatform { + fn get_thread_local_storage() -> *mut () { + use ostd::cpu::PinCurrentCpu as _; + let preempt_guard = ostd::task::disable_preempt(); + let cpu_id = preempt_guard.current_cpu(); + let tls_ref = TLS_POINTER.get_on_cpu(cpu_id); + tls_ref.load(core::sync::atomic::Ordering::Acquire) as *mut () + } + + unsafe fn replace_thread_local_storage(value: *mut ()) -> *mut () { + use ostd::cpu::PinCurrentCpu as _; + let preempt_guard = ostd::task::disable_preempt(); + let cpu_id = preempt_guard.current_cpu(); + let tls_ref = TLS_POINTER.get_on_cpu(cpu_id); + tls_ref.swap(value as usize, core::sync::atomic::Ordering::AcqRel) as *mut () + } +} + +impl litebox::platform::CrngProvider for OstdPlatform { + fn fill_bytes_crng(&self, buf: &mut [u8]) { + // FIXME: call into the trusted host to get random bytes. + static RANDOM: spin::mutex::SpinMutex = + spin::mutex::SpinMutex::new(litebox::utils::rng::FastRng::new_from_seed( + core::num::NonZeroU64::new(0x4d595df4d0f33173).unwrap(), + )); + let mut random = RANDOM.lock(); + for b in buf.chunks_mut(8) { + b.copy_from_slice(&random.next_u64().to_ne_bytes()[..b.len()]); + } + } +} + +impl litebox::platform::ThreadProvider for OstdPlatform { + type ExecutionContext = litebox_common_linux::PtRegs; + + type ThreadSpawnError = litebox_common_linux::errno::Errno; + + type ThreadHandle = ThreadHandle; + + unsafe fn spawn_thread( + &self, + ctx: &Self::ExecutionContext, + init_thread: alloc::boxed::Box, + ) -> Result<(), Self::ThreadSpawnError> { + let mut user_ctx = UserContext::default(); + + copy_pt_to_uc(&mut user_ctx, ctx); + + let task_result = ostd::task::TaskOptions::new(move || { + init_thread.init(); + }) + .spawn(); + + match task_result { + Ok(_task) => Ok(()), + Err(_) => Err(litebox_common_linux::errno::Errno::EAGAIN), + } + } + + fn current_thread(&self) -> Self::ThreadHandle { + let current_task = + ostd::task::Task::current().expect("current_thread called outside of a task context"); + ThreadHandle { + task: current_task.cloned(), + } + } + + fn interrupt_thread(&self, _thread: &Self::ThreadHandle) { + // TODO: Implement thread interruption + todo!() + } +} + +pub struct ThreadHandle { + #[expect(dead_code)] + task: alloc::sync::Arc, +} + +pub fn run_thread(pt_regs: &mut litebox_common_linux::PtRegs) { + let pt_regs = *pt_regs; + debug!("[run_thread] setting up task\n"); + let task = alloc::sync::Arc::new( + ostd::task::TaskOptions::new(move || { + unsafe { run_thread_inner(pt_regs) }; + }) + .build() + .unwrap(), + ); + debug!("[run_thread] running task\n"); + task.run(); + // XXX: Weird that we need this + ostd::task::Task::yield_now(); +} + +unsafe fn run_thread_inner(mut pt_regs: litebox_common_linux::PtRegs) { + debug!("[run_thread] begin\n"); + let pt_regs = &mut pt_regs; + let mut user_context = UserContext::default(); + + copy_pt_to_uc(&mut user_context, pt_regs); + + let mut user_mode = ostd::user::UserMode::new(user_context); + + loop { + debug!("[run_thread] switch to user mode\n"); + let return_reason = user_mode.execute(|| false); + + debug!("[run_thread] returned due to {return_reason:?}\n"); + match return_reason { + ostd::user::ReturnReason::UserSyscall => { + let user_context = user_mode.context_mut(); + copy_uc_to_pt(&user_context, pt_regs); + debug!( + "[run_thread] ... start with rax={} orig_rax={}\n", + pt_regs.rax, pt_regs.orig_rax + ); + match SHIM + .get() + .expect("shim must have been registered") + .syscall(pt_regs) + { + litebox::shim::ContinueOperation::ResumeGuest => { + debug!( + "[run_thread] ...resume with rax={} orig_rax={}\n", + pt_regs.rax, pt_regs.orig_rax + ); + copy_pt_to_uc(user_context, pt_regs); + } + litebox::shim::ContinueOperation::ExitThread => { + ostd::console::early_print(format_args!("Program exited\n")); + // XXX: Actually return from `run_thread` instead + ostd::arch::qemu::exit_qemu(ostd::arch::qemu::QemuExitCode::Success); + // break; + } + } + } + ostd::user::ReturnReason::UserException => { + let user_context = user_mode.context(); + + debug!("\n\n=== UserException ===\n"); + debug!("Trap Number: {:#x}\n", user_context.trap_number()); + debug!("Trap Error Code: {:#x}\n", user_context.trap_error_code()); + debug!("RIP: {:#x}\n", user_context.instruction_pointer()); + debug!("RSP: {:#x}\n", user_context.stack_pointer()); + debug!("======================\n\n\n"); + let _ = user_context; + + ostd::console::early_print(format_args!( + "TODO: Unhandled user exception: {:?}\n", + return_reason + )); + + ostd::arch::qemu::exit_qemu(ostd::arch::qemu::QemuExitCode::Failed); + } + ostd::user::ReturnReason::KernelEvent => { + ostd::console::early_print(format_args!( + "TODO: Unhandled return reason: {:?}\n", + return_reason + )); + break; + } + } + } +} + +fn copy_uc_to_pt(user_context: &UserContext, pt_regs: &mut litebox_common_linux::PtRegs) { + // Convert UserContext to PtRegs for the shim + macro_rules! cp { + ($($r:ident),*) => { $(pt_regs.$r = user_context.$r();)* }; + } + #[cfg(target_arch = "x86_64")] + cp!( + rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp, r8, r9, r10, r11, r12, r13, r14, r15, rip + ); + pt_regs.orig_rax = pt_regs.rax; +} + +fn copy_pt_to_uc(user_context: &mut UserContext, pt_regs: &litebox_common_linux::PtRegs) { + // Copy results back to user context + macro_rules! cp { + ($($r:ident),*) => { $(user_context.general_regs_mut().$r = pt_regs.$r;)* }; + } + #[cfg(target_arch = "x86_64")] + cp!( + rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp, r8, r9, r10, r11, r12, r13, r14, r15, rip + ); +} diff --git a/ostd-test/runner/.gitignore b/ostd-test/runner/.gitignore new file mode 100644 index 000000000..ea8c4bf7f --- /dev/null +++ b/ostd-test/runner/.gitignore @@ -0,0 +1 @@ +/target diff --git a/ostd-test/runner/Cargo.toml b/ostd-test/runner/Cargo.toml new file mode 100644 index 000000000..e0e8a9642 --- /dev/null +++ b/ostd-test/runner/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "runner" +version = "0.1.0" +edition = "2024" + +[dependencies] +ostd = "0.16.1" +platform = { path = "../platform/" } +litebox = { path = "../../litebox" } +litebox_common_linux = { path = "../../litebox_common_linux", default-features = false } +litebox_shim_linux = { path = "../../litebox_shim_linux", default-features = false } +litebox_platform_multiplex = { path = "../../litebox_platform_multiplex", default-features = false, features = ["platform_ostd"] } diff --git a/ostd-test/runner/src/lib.rs b/ostd-test/runner/src/lib.rs new file mode 100644 index 000000000..fa476d876 --- /dev/null +++ b/ostd-test/runner/src/lib.rs @@ -0,0 +1,103 @@ +#![no_std] +#![feature(let_chains)] + +extern crate alloc; + +use alloc::vec::Vec; +use litebox::fs::FileSystem as _; +use ostd::prelude::println; +use platform::OstdPlatform; + +#[ostd::main] +pub fn main() { + let program_binary = include_bytes!("../../test-bins/hello_world_static"); + + let platform = alloc::boxed::Box::leak(alloc::boxed::Box::new(OstdPlatform::new())); + + // Activate the VmSpace immediately so allocations during load_program can be accessed + println!("Activating VmSpace..."); + platform.activate_vm_space(); + + litebox_platform_multiplex::set_platform(platform); + + let mut shim = litebox_shim_linux::LinuxShim::new(); + let litebox = shim.litebox(); + + let initial_file_system = { + let mut in_mem = litebox::fs::in_mem::FileSystem::new(litebox); + + in_mem.with_root_privileges(|fs| { + fs.mkdir( + "/bin", + litebox::fs::Mode::RWXU + | litebox::fs::Mode::RGRP + | litebox::fs::Mode::XGRP + | litebox::fs::Mode::ROTH + | litebox::fs::Mode::XOTH, + ) + .unwrap(); + }); + + in_mem.with_root_privileges(|fs| { + let fd = fs + .open( + "/bin/hello_world_static", + litebox::fs::OFlags::WRONLY | litebox::fs::OFlags::CREAT, + litebox::fs::Mode::RWXU + | litebox::fs::Mode::RGRP + | litebox::fs::Mode::XGRP + | litebox::fs::Mode::ROTH + | litebox::fs::Mode::XOTH, + ) + .unwrap(); + let mut data = program_binary.as_slice(); + while !data.is_empty() { + let len = fs.write(&fd, data, None).unwrap(); + data = &data[len..]; + } + fs.close(&fd).unwrap(); + }); + + let tar_ro = litebox::fs::tar_ro::FileSystem::new( + litebox, + litebox::fs::tar_ro::EMPTY_TAR_FILE.into(), + ); + shim.default_fs(in_mem, tar_ro) + }; + + shim.set_fs(initial_file_system); + platform.register_shim(shim.entrypoints()); + + let argv: Vec = + alloc::vec![alloc::ffi::CString::new("/bin/hello_world_static").unwrap(),]; + let envp: Vec = alloc::vec![]; + + println!(r#" _ _ _ ____ "#); + println!(r#" | | (_) |_ ___| __ ) _____ __ "#); + println!(r#" | | | | __/ _ \ _ \ / _ \ \/ / "#); + println!(r#" | |___| | || __/ |_) | (_) > < "#); + println!(r#" |_____|_|\__\___|____/ \___/_/\_\ "#); + println!(r#" "#); + println!("Runner initialized with binary at /bin/hello_world_static"); + println!("Loading and executing program..."); + + let task_params = litebox_common_linux::TaskParams { + pid: 1, + ppid: 0, + uid: 1000, + euid: 1000, + gid: 1000, + egid: 1000, + }; + + let entrypoints = shim.entrypoints(); + + let mut pt_regs = shim + .load_program(task_params, "/bin/hello_world_static", argv, envp) + .expect("Failed to load program"); + + platform::run_thread(&mut pt_regs); + + println!("oO0OoO0OoO0OooO0OoO0OoO0OooO0OoO0OoO0Oo"); + ostd::arch::qemu::exit_qemu(ostd::arch::qemu::QemuExitCode::Success); +} diff --git a/ostd-test/rust-toolchain.toml b/ostd-test/rust-toolchain.toml new file mode 100644 index 000000000..2eb01586a --- /dev/null +++ b/ostd-test/rust-toolchain.toml @@ -0,0 +1,3 @@ +[toolchain] +channel = "nightly-2025-01-15" +components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/ostd-test/test-bins/hello_world_static b/ostd-test/test-bins/hello_world_static new file mode 120000 index 000000000..a105d6f1b --- /dev/null +++ b/ostd-test/test-bins/hello_world_static @@ -0,0 +1 @@ +../../litebox_runner_linux_on_windows_userland/tests/test-bins/hello_world_static \ No newline at end of file diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 292fe499e..0c52af1cc 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "stable" +channel = "nightly-2025-01-15"