From 1c0212238ab6427f6d8000c0002763ae4f273dfd Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Tue, 12 Mar 2024 13:46:24 +0200 Subject: [PATCH] refactor: implement generated ABI --- Cargo.lock | 1055 --------------------- Cargo.toml | 7 + build.rs | 32 +- driver/fs/memfs/src/lib.rs | 4 +- libk/libk-thread/Cargo.toml | 1 + libk/libk-thread/src/process.rs | 9 +- src/arch/aarch64/exception.rs | 2 +- src/arch/aarch64/mod.rs | 1 + src/arch/x86_64/syscall.rs | 3 +- src/main.rs | 3 +- src/syscall/arg.rs | 55 +- src/syscall/mod.rs | 1546 ++++++++++++++++--------------- 12 files changed, 847 insertions(+), 1871 deletions(-) delete mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 245875f0..00000000 --- a/Cargo.lock +++ /dev/null @@ -1,1055 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aarch64-cpu" -version = "9.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac42a04a61c19fc8196dd728022a784baecc5d63d7e256c01ad1b3fbfab26287" -dependencies = [ - "tock-registers", -] - -[[package]] -name = "accessor" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd8b2abd55bf1f9cffbf00fd594566c51a9d31402553284920c1309ca8351086" - -[[package]] -name = "acpi" -version = "4.1.1" -source = "git+https://github.com/alnyan/acpi.git?branch=acpi-system#5efda0f9c17bccb922cf2b6b5fd73088bb887965" -dependencies = [ - "bit_field", - "log", - "rsdp", -] - -[[package]] -name = "acpi-system" -version = "0.1.0" -source = "git+https://github.com/alnyan/acpi-system.git#17192e5f603fdc7d78c9b83885e8a9d9aac45af7" -dependencies = [ - "acpi", - "aml", - "bit_field", - "enum-map", - "log", -] - -[[package]] -name = "aml" -version = "0.16.4" -source = "git+https://github.com/alnyan/acpi.git?branch=acpi-system#5efda0f9c17bccb922cf2b6b5fd73088bb887965" -dependencies = [ - "bit_field", - "bitvec", - "byteorder", - "log", - "spinning_top", -] - -[[package]] -name = "atomic_enum" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6227a8d6fdb862bcb100c4314d0d9579e5cd73fa6df31a2e6f6e1acd3c5f1207" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bit_field" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "btree_monstrousity" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4d0977e9c15f276380f16f2e9594257c258172b23af39ffd2e4cf5971cb38c7" -dependencies = [ - "cfg-if", - "rustversion", -] - -[[package]] -name = "bytemuck" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "crossbeam-queue" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" - -[[package]] -name = "device-api" -version = "0.1.0" -dependencies = [ - "device-api-macros", - "yggdrasil-abi", -] - -[[package]] -name = "device-api-macros" -version = "0.1.0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "discrete_range_map" -version = "0.6.2" -source = "git+https://git.alnyan.me/yggdrasil/discrete_range_map.git#10fd79828d2918bd079a11c2b2c623eede170c3f" -dependencies = [ - "btree_monstrousity", - "either", - "itertools 0.12.0", - "serde", -] - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "elf" -version = "0.7.2" -source = "git+https://git.alnyan.me/yggdrasil/yggdrasil-elf.git#419cd311de2e9514b5033677cde9a33f7d0ba4a2" -dependencies = [ - "hashbrown", -] - -[[package]] -name = "endian-type-rs" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6419a5c75e40011b9fe0174db3fe24006ab122fbe1b7e9cc5974b338a755c76" - -[[package]] -name = "enum-map" -version = "2.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9" -dependencies = [ - "enum-map-derive", -] - -[[package]] -name = "enum-map-derive" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "fallible-iterator" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" - -[[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - -[[package]] -name = "fdt-rs" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99a40cabc11c8258822a593f5c51f2d9f4923e715ca9e2a0630cf77ae15f390b" -dependencies = [ - "endian-type-rs", - "fallible-iterator", - "memoffset 0.5.6", - "num-derive", - "num-traits", - "rustc_version", - "static_assertions", - "unsafe_unwrap", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "pin-utils", -] - -[[package]] -name = "getrandom" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "git-version" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad568aa3db0fcbc81f2f116137f263d7304f512a1209b35b85150d3ef88ad19" -dependencies = [ - "git-version-macro", -] - -[[package]] -name = "git-version-macro" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" - -[[package]] -name = "hosted-tests" -version = "0.1.0" -dependencies = [ - "yggdrasil-abi", -] - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" -dependencies = [ - "either", -] - -[[package]] -name = "kernel-fs" -version = "0.1.0" -dependencies = [ - "kernel-util", - "log", - "vfs", - "ygg_driver_block", - "yggdrasil-abi", -] - -[[package]] -name = "kernel-util" -version = "0.1.0" -dependencies = [ - "crossbeam-queue", - "device-api", - "futures-util", - "log", - "yggdrasil-abi", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.152" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "linked_list_allocator" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" -dependencies = [ - "spinning_top", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" - -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "memfs" -version = "0.1.0" -dependencies = [ - "kernel-util", - "log", - "static_assertions", - "vfs", - "yggdrasil-abi", -] - -[[package]] -name = "memoffset" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memtables" -version = "0.1.0" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro2" -version = "1.0.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proptest" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" -dependencies = [ - "bit-set", - "bit-vec", - "bitflags 2.4.1", - "lazy_static", - "num-traits", - "rand", - "rand_chacha", - "rand_xorshift", - "regex-syntax", - "rusty-fork", - "tempfile", - "unarray", -] - -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - -[[package]] -name = "quote" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "rsdp" -version = "2.0.0" -source = "git+https://github.com/alnyan/acpi.git?branch=acpi-system#5efda0f9c17bccb922cf2b6b5fd73088bb887965" -dependencies = [ - "log", -] - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.38.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" -dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - -[[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - -[[package]] -name = "rusty-fork" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" -dependencies = [ - "fnv", - "quick-error", - "tempfile", - "wait-timeout", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "serde" -version = "1.0.195" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.195" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "spinning_top" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0" -dependencies = [ - "lock_api", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[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.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall", - "rustix", - "windows-sys", -] - -[[package]] -name = "tock-registers" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "696941a0aee7e276a165a978b37918fd5d22c55c3d6bda197813070ca9c0f21c" - -[[package]] -name = "unarray" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unsafe_unwrap" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1230ec65f13e0f9b28d789da20d2d419511893ea9dac2c1f4ef67b8b14e5da80" - -[[package]] -name = "uuid" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "vfs" -version = "0.1.0" -dependencies = [ - "futures-util", - "hosted-tests", - "kernel-util", - "log", - "ygg_driver_block", - "yggdrasil-abi", -] - -[[package]] -name = "vmalloc" -version = "0.1.0" -dependencies = [ - "discrete_range_map", - "itertools 0.11.0", - "proptest", - "yggdrasil-abi", -] - -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "xhci" -version = "0.9.2" -source = "git+https://github.com/rust-osdev/xhci.git#6144829ff13c2499dc812cea09df4e5a1d0862cc" -dependencies = [ - "accessor", - "bit_field", - "num-derive", - "num-traits", - "paste", -] - -[[package]] -name = "yboot-proto" -version = "0.1.0" -source = "git+https://git.alnyan.me/yggdrasil/yboot-proto.git#edf5db1b1d5d5dcb9d737cd7ec23b2e124b3b027" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "ygg_driver_ahci" -version = "0.1.0" -dependencies = [ - "bytemuck", - "device-api", - "futures-util", - "kernel-fs", - "kernel-util", - "log", - "memoffset 0.9.0", - "static_assertions", - "tock-registers", - "vfs", - "ygg_driver_block", - "ygg_driver_pci", - "yggdrasil-abi", -] - -[[package]] -name = "ygg_driver_block" -version = "0.1.0" -dependencies = [ - "bytemuck", - "futures-util", - "kernel-util", - "log", - "static_assertions", - "uuid", - "yggdrasil-abi", -] - -[[package]] -name = "ygg_driver_nvme" -version = "0.1.0" -dependencies = [ - "bytemuck", - "device-api", - "futures-util", - "kernel-fs", - "kernel-util", - "log", - "static_assertions", - "tock-registers", - "vfs", - "ygg_driver_block", - "ygg_driver_pci", - "yggdrasil-abi", -] - -[[package]] -name = "ygg_driver_pci" -version = "0.1.0" -dependencies = [ - "acpi", - "bitflags 2.4.1", - "device-api", - "kernel-util", - "log", - "yggdrasil-abi", -] - -[[package]] -name = "ygg_driver_virtio_net" -version = "0.1.0" -dependencies = [ - "ygg_driver_pci", -] - -[[package]] -name = "yggdrasil-abi" -version = "0.1.0" -source = "git+https://git.alnyan.me/yggdrasil/yggdrasil-abi.git#d2173e1e9e92e668399cf83aeb32e09823826821" - -[[package]] -name = "yggdrasil-kernel" -version = "0.1.0" -dependencies = [ - "aarch64-cpu", - "acpi", - "acpi-system", - "aml", - "atomic_enum", - "bitflags 2.4.1", - "bytemuck", - "cfg-if", - "crossbeam-queue", - "device-api", - "device-api-macros", - "elf", - "fdt-rs", - "futures-util", - "git-version", - "kernel-fs", - "kernel-util", - "linked_list_allocator", - "log", - "memfs", - "memtables", - "spinning_top", - "static_assertions", - "tock-registers", - "vfs", - "vmalloc", - "xhci", - "yboot-proto", - "ygg_driver_ahci", - "ygg_driver_block", - "ygg_driver_nvme", - "ygg_driver_pci", - "ygg_driver_virtio_net", - "yggdrasil-abi", -] diff --git a/Cargo.toml b/Cargo.toml index 08935458..c4dcee1f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,8 @@ authors = ["Mark Poliakov "] opt-level = 3 [dependencies] +abi-lib = { git = "https://git.alnyan.me/yggdrasil/abi-generator.git" } + yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" } vfs = { path = "lib/vfs" } device-api = { path = "lib/device-api", features = ["derive"] } @@ -70,6 +72,11 @@ acpi-system = { git = "https://github.com/alnyan/acpi-system.git" } ygg_driver_nvme = { path = "driver/block/nvme" } kernel-arch-x86_64 = { path = "arch/x86_64" } +[build-dependencies] +prettyplease = "0.2.15" +yggdrasil-abi-def = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi-def.git" } +abi-generator = { git = "https://git.alnyan.me/yggdrasil/abi-generator.git" } + [features] default = ["fb_console"] fb_console = [] diff --git a/build.rs b/build.rs index c015254e..5307bb10 100644 --- a/build.rs +++ b/build.rs @@ -1,10 +1,16 @@ use std::{ - env, + env, fs, io::{self, Write}, - path::PathBuf, + path::{Path, PathBuf}, process::Command, }; +use abi_generator::{ + abi::{ty::TypeWidth, AbiBuilder}, + syntax::UnwrapFancy, + TargetEnv, +}; + fn build_x86_64() { const DEFAULT_8086_AS: &str = "nasm"; const AP_BOOTSTRAP_S: &str = "src/arch/x86_64/boot/ap_boot.S"; @@ -33,9 +39,31 @@ fn build_x86_64() { } } +fn generate_syscall_dispatcher>(out_dir: P) { + let abi: AbiBuilder = AbiBuilder::from_string( + yggdrasil_abi_def::ABI_FILE, + TargetEnv { + thin_pointer_width: TypeWidth::U64, + fat_pointer_width: TypeWidth::U128, + }, + ) + .unwrap_fancy(""); + + let generated_dispatcher = out_dir.as_ref().join("generated_dispatcher.rs"); + let file = prettyplease::unparse( + &abi.emit_syscall_dispatcher("handle_syscall", "impls") + .unwrap_fancy(""), + ); + + fs::write(generated_dispatcher, file.as_bytes()).unwrap(); +} + fn main() { + let out_dir = env::var("OUT_DIR").unwrap(); let arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap(); + generate_syscall_dispatcher(&out_dir); + println!("cargo:rerun-if-changed=build.rs"); match arch.as_str() { diff --git a/driver/fs/memfs/src/lib.rs b/driver/fs/memfs/src/lib.rs index cd16449f..54894160 100644 --- a/driver/fs/memfs/src/lib.rs +++ b/driver/fs/memfs/src/lib.rs @@ -148,8 +148,8 @@ impl MemoryFilesystem { let node = self.make_path(&root, path, FileType::Directory, false)?; assert_eq!(node.ty(), hdr.node_kind()); - let uid = UserId::from(usize::from(&hdr.uid) as u32); - let gid = GroupId::from(usize::from(&hdr.gid) as u32); + let uid = unsafe { UserId::from_raw(usize::from(&hdr.uid) as u32) }; + let gid = unsafe { GroupId::from_raw(usize::from(&hdr.gid) as u32) }; let mode = convert_mode(usize::from(&hdr.mode))?; let access = unsafe { AccessToken::authorized() }; diff --git a/libk/libk-thread/Cargo.toml b/libk/libk-thread/Cargo.toml index 03634422..984d0388 100644 --- a/libk/libk-thread/Cargo.toml +++ b/libk/libk-thread/Cargo.toml @@ -10,6 +10,7 @@ libk-util = { path = "../libk-util" } libk-mm = { path = "../libk-mm" } libk-device = { path = "../libk-device" } kernel-arch = { path = "../../arch" } +abi-lib = { git = "https://git.alnyan.me/yggdrasil/abi-generator.git" } yggdrasil-abi = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-abi.git" } diff --git a/libk/libk-thread/src/process.rs b/libk/libk-thread/src/process.rs index 1ef594b9..fab3a36f 100644 --- a/libk/libk-thread/src/process.rs +++ b/libk/libk-thread/src/process.rs @@ -1,5 +1,6 @@ use core::marker::PhantomData; +use abi_lib::SyscallRegister; use alloc::{ collections::BTreeMap, string::String, @@ -17,7 +18,7 @@ use libk_util::{ }, }; use yggdrasil_abi::{ - error::{Error, SyscallResult}, + error::Error, process::{ExitCode, Signal, ThreadSpawnOptions}, }; @@ -247,12 +248,12 @@ impl, IO: ProcessIo> ProcessImpl { let src_thread = Thread::current(); let src_process = src_thread.process::(); - let rax = src_process + let value = src_process .fork_inner(frame) .map(|ProcessId(p)| p as u32) - .into_syscall_result(); + .into_syscall_register(); - frame.set_return_value(rax as _); + frame.set_return_value(value as _); } /// Replaces the process address space with a new one, loaded from the specified program diff --git a/src/arch/aarch64/exception.rs b/src/arch/aarch64/exception.rs index 1c5c8ba6..5334489e 100644 --- a/src/arch/aarch64/exception.rs +++ b/src/arch/aarch64/exception.rs @@ -11,7 +11,7 @@ use aarch64_cpu::{ }; use abi::{ process::{Signal, SignalEntryData}, - syscall::SyscallFunction, + SyscallFunction, }; use kernel_arch::{task::TaskFrame, Architecture, ArchitectureImpl}; use kernel_arch_aarch64::context::ExceptionFrame; diff --git a/src/arch/aarch64/mod.rs b/src/arch/aarch64/mod.rs index 5144d879..e358a2fb 100644 --- a/src/arch/aarch64/mod.rs +++ b/src/arch/aarch64/mod.rs @@ -93,6 +93,7 @@ impl Platform for AArch64 { } unsafe fn reset(&self) -> ! { + loop {} if let Some(reset) = self.reset.try_get() { reset.reset() } else { diff --git a/src/arch/x86_64/syscall.rs b/src/arch/x86_64/syscall.rs index faff7bc4..7685e33e 100644 --- a/src/arch/x86_64/syscall.rs +++ b/src/arch/x86_64/syscall.rs @@ -2,7 +2,7 @@ use core::arch::global_asm; -use abi::{process::SignalEntryData, syscall::SyscallFunction}; +use abi::{process::SignalEntryData, SyscallFunction}; use kernel_arch::task::TaskFrame; use kernel_arch_x86_64::{ context::SyscallFrame, @@ -23,6 +23,7 @@ fn syscall_inner(frame: &mut SyscallFrame) { return; } } + // FIXME: Fork is temporarily disabled if frame.rax == usize::from(SyscallFunction::Fork) as u64 { unsafe { ProcessImpl::raw_fork(frame); diff --git a/src/main.rs b/src/main.rs index 23818470..df05203a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,7 +25,8 @@ inline_const, maybe_uninit_uninit_array, const_maybe_uninit_uninit_array, - never_type + never_type, + trace_macros )] #![allow( clippy::new_without_default, diff --git a/src/syscall/arg.rs b/src/syscall/arg.rs index f7049d8f..a7dcf4e8 100644 --- a/src/syscall/arg.rs +++ b/src/syscall/arg.rs @@ -1,26 +1,19 @@ -use abi::io::RawFd; -use libk_thread::{ - mem::{validate_user_region, ForeignPointer}, - thread::Thread, -}; +use libk_thread::{mem::ForeignPointer, thread::Thread}; use yggdrasil_abi::error::Error; -// XXX - -pub(super) fn arg_buffer_ref<'a>(base: usize, len: usize) -> Result<&'a [u8], Error> { +pub(super) fn ref_const<'a, T: Sized>(addr: usize) -> Result<&'a T, Error> { let proc = Thread::current(); - validate_user_region(proc.address_space(), base, len, false)?; - Ok(unsafe { core::slice::from_raw_parts(base as *const u8, len) }) + let ptr = addr as *const T; + unsafe { ptr.validate_user_ptr(proc.address_space()) } +} +pub(super) fn ref_mut<'a, T: Sized>(addr: usize) -> Result<&'a mut T, Error> { + let proc = Thread::current(); + let ptr = addr as *mut T; + unsafe { ptr.validate_user_mut(proc.address_space()) } } -pub(super) fn arg_buffer_mut<'a>(base: usize, len: usize) -> Result<&'a mut [u8], Error> { - let proc = Thread::current(); - validate_user_region(proc.address_space(), base, len, true)?; - Ok(unsafe { core::slice::from_raw_parts_mut(base as *mut u8, len) }) -} - -pub(super) fn arg_user_str<'a>(base: usize, len: usize) -> Result<&'a str, Error> { - let slice = arg_buffer_ref(base, len)?; +pub(super) fn str_ref<'a>(base: usize, len: usize) -> Result<&'a str, Error> { + let slice = slice_ref(base, len)?; if slice.contains(&0) { warnln!("User-supplied string contains NUL characters"); return Err(Error::InvalidArgument); @@ -28,31 +21,13 @@ pub(super) fn arg_user_str<'a>(base: usize, len: usize) -> Result<&'a str, Error Ok(core::str::from_utf8(slice).unwrap()) } -pub(super) fn arg_user_ref<'a, T: Sized>(addr: usize) -> Result<&'a T, Error> { +pub(super) fn slice_ref<'a, T: Sized>(base: usize, count: usize) -> Result<&'a [T], Error> { let proc = Thread::current(); - let ptr = addr as *const T; - unsafe { ptr.validate_user_ptr(proc.address_space()) } + let ptr = base as *const T; + unsafe { ptr.validate_user_slice(count, proc.address_space()) } } - -pub(super) fn arg_user_mut<'a, T: Sized>(addr: usize) -> Result<&'a mut T, Error> { - let proc = Thread::current(); - let ptr = addr as *mut T; - unsafe { ptr.validate_user_mut(proc.address_space()) } -} - -pub(super) fn arg_user_slice_mut<'a, T: Sized>( - base: usize, - count: usize, -) -> Result<&'a mut [T], Error> { +pub(super) fn slice_mut<'a, T: Sized>(base: usize, count: usize) -> Result<&'a mut [T], Error> { let proc = Thread::current(); let ptr = base as *mut T; unsafe { ptr.validate_user_slice_mut(count, proc.address_space()) } } - -pub(super) fn arg_option_fd(raw: u32) -> Option { - if raw == u32::MAX { - None - } else { - Some(RawFd(raw)) - } -} diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index f576e67d..592a0000 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -1,48 +1,12 @@ //! System function call handlers -use core::{mem::MaybeUninit, time::Duration}; -use abi::{ - error::Error, - io::{ - DeviceRequest, DirectoryEntry, FileAttr, FileMetadataUpdate, FileMode, MessageDestination, - OpenOptions, PollControl, RawFd, ReceivedMessageMetadata, SeekFrom, SentMessage, - TerminalOptions, TerminalSize, - }, - mem::MappingSource, - net::{SocketOption, SocketType}, - process::{ - ExecveOptions, ExitCode, MutexOperation, ProcessInfoElement, Signal, SpawnOption, - SpawnOptions, ThreadSpawnOptions, - }, - syscall::SyscallFunction, - system::SystemInfo, -}; -use alloc::{borrow::ToOwned, boxed::Box, sync::Arc, vec::Vec}; -use libk::{block, runtime}; -use libk_mm::{ - phys, - process::VirtualRangeBacking, - table::{EntryLevelExt, MapAttributes}, -}; -use libk_thread::{ - process::{Process, ProcessManager}, - thread::{CurrentThread, Thread}, -}; +use abi::{error::Error, io::RawFd, SyscallFunction}; use libk_util::sync::IrqSafeSpinlockGuard; -use vfs::{File, IoContext, MessagePayload, NodeRef, Read, Seek, Write}; -use ygg_driver_net_core::socket::{RawSocket, TcpListener, TcpSocket, UdpSocket}; -use yggdrasil_abi::{error::SyscallResult, io::MountOptions}; +use vfs::NodeRef; -use crate::{ - arch::L3, - debug::LogLevel, - fs, - proc::{self, io::ProcessIoImpl, random}, - task::process::{ProcessId, ProcessImpl, ProcessManagerImpl}, -}; +use crate::{proc::io::ProcessIoImpl, task::process::ProcessImpl}; mod arg; -use arg::*; fn run_with_io) -> T>( proc: &ProcessImpl, @@ -74,754 +38,812 @@ fn run_with_io_at< f(at, io) } -fn sys_execve(thread: CurrentThread, options: &ExecveOptions) -> Result { - let process = thread.process::(); +mod impls { + use abi::process::{ExecveOptions, SpawnOption}; + pub(crate) use abi::{ + error::Error, + io::{ + DeviceRequest, DirectoryEntry, FileAttr, FileMetadataUpdate, FileMode, + MessageDestination, MountOptions, OpenOptions, PollControl, RawFd, + ReceivedMessageMetadata, SeekFrom, SentMessage, TerminalOptions, TerminalSize, + UnmountOptions, + }, + mem::MappingSource, + net::{SocketOption, SocketType}, + process::{ExitCode, MutexOperation, Signal, SignalEntryData, SpawnOptions}, + system::SystemInfo, + }; + use alloc::{boxed::Box, sync::Arc}; + use libk::{block, runtime}; + use vfs::{File, IoContext, MessagePayload, Read, Seek, Write}; + use ygg_driver_net_core::socket::{RawSocket, TcpListener, TcpSocket, UdpSocket}; - // Clone the options into the kernel - let mut argv = Vec::new(); - let mut envp = Vec::new(); + use core::{ + mem::MaybeUninit, net::SocketAddr, num::NonZeroUsize, sync::atomic::AtomicU32, + time::Duration, + }; - for &arg in options.arguments { - argv.push(arg.to_owned()); - } - for &env in options.environment { - envp.push(env.to_owned()); + use libk_mm::{ + phys, + process::VirtualRangeBacking, + table::{EntryLevelExt, MapAttributes}, + }; + use libk_thread::{ + process::{Process, ProcessManager}, + thread::Thread, + types::ProcessId, + }; + + use crate::{ + arch::L3, + debug::LogLevel, + fs, + proc::{self, random}, + task::process::ProcessManagerImpl, + }; + + use super::{run_with_io, run_with_io_at}; + + // Misc + pub(crate) fn debug_trace(message: &str) { + let thread = Thread::current(); + let process = thread.process::(); + + log_print_raw!( + LogLevel::Debug, + "[{}:{}] TRACE: {}\n", + process.id(), + thread.id, + message + ); } - process.exec(options.program, argv, envp) -} + pub(crate) fn get_random(buffer: &mut [u8]) { + random::read(buffer); + } -fn syscall_handler(func: SyscallFunction, args: &[u64]) -> Result { - let thread = Thread::current(); - let process = thread.process::(); + pub(crate) fn mount(options: &MountOptions<'_>) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); - match func { - SyscallFunction::DebugTrace => { - let pid = process.id(); - let tid = thread.id; + run_with_io(&process, |mut io| { + let fs_root = fs::create_filesystem(options)?; + io.ioctx_mut().mount(options.target, fs_root)?; + Ok(()) + }) + } - let arg = arg_user_str(args[0] as usize, args[1] as usize)?; + pub(crate) fn unmount(_options: &UnmountOptions) -> Result<(), Error> { + todo!() + } - log_print_raw!(LogLevel::Debug, "[{}:{}] TRACE: {}\n", pid, tid, arg); + // Memory management + pub(crate) fn map_memory( + _hint: Option, + len: usize, + source: &MappingSource, + ) -> Result { + let thread = Thread::current(); + let process = thread.process::(); - Ok(0) - } - SyscallFunction::GetRandom => { - let buf = arg_buffer_mut(args[0] as _, args[1] as _)?; - random::read(buf); - Ok(0) - } - SyscallFunction::Nanosleep => { - let seconds = args[0]; - let nanos = args[1] as u32; - let duration = Duration::new(seconds, nanos); + let space = thread.address_space(); - block! { - runtime::sleep(duration).await - } - .map(|_| 0) - } - // Resource management - SyscallFunction::MapMemory => { - let mut len = args[1] as usize; - let source = arg_user_ref::(args[2] as usize)?; + let len = len.page_align_up::(); - let space = thread.address_space(); - - len = len.page_align_up::(); - - run_with_io(&process, |io| { - let backing = match source { - MappingSource::Anonymous => VirtualRangeBacking::anonymous(), - &MappingSource::File(fd, offset) => { - let file = io.files.file(fd)?; - VirtualRangeBacking::file(offset, file.clone())? - } - }; - - space.allocate( - None, - len, - backing, - MapAttributes::USER_WRITE - | MapAttributes::USER_READ - | MapAttributes::NON_GLOBAL, - ) - }) - } - SyscallFunction::UnmapMemory => { - let addr = args[0] as usize; - let len = args[1] as usize; - - let space = thread.address_space(); - - if len & 0xFFF != 0 { - todo!(); - } - - unsafe { - space.unmap(addr, len)?; - } - - Ok(0) - } - SyscallFunction::SetSignalEntry => { - let entry = args[0] as usize; - let sp = args[1] as usize; - - thread.set_signal_entry(entry, sp); - - Ok(0) - } - // I/O - SyscallFunction::Open => { - let at = arg_option_fd(args[0] as u32); - let path = arg_user_str(args[1] as usize, args[2] as usize)?; - let opts = OpenOptions::from(args[3] as u32); - let mode = FileMode::from(args[4] as u32); - - run_with_io_at(&process, at, |at, mut io| { - let file = io.ioctx_mut().open(Some(at), path, opts, mode)?; - - // TODO NO_CTTY? - if process.session_terminal().is_none() - && let Some(node) = file.node() - && node.is_terminal() - { - debugln!("Session terminal set for #{}: {}", process.id(), path); - process.set_session_terminal(node.clone()); + run_with_io(&process, |io| { + let backing = match source { + MappingSource::Anonymous => VirtualRangeBacking::anonymous(), + &MappingSource::File(fd, offset) => { + let file = io.files.file(fd)?; + VirtualRangeBacking::file(offset, file.clone())? } + }; - let fd = io.files.place_file(file, true)?; - Ok(fd.0 as usize) - }) - } - SyscallFunction::OpenDirectory => { - let at = arg_option_fd(args[0] as u32); - let path = arg_user_str(args[1] as usize, args[2] as usize)?; + space.allocate( + None, + len, + backing, + MapAttributes::USER_WRITE | MapAttributes::USER_READ | MapAttributes::NON_GLOBAL, + ) + }) + } - run_with_io_at(&process, at, |at, mut io| { - let node = io.ioctx_mut().find(Some(at), path, true, true)?; - let access = io.ioctx_mut().check_access(vfs::Action::Read, &node)?; - let file = node.open_directory(access)?; - let fd = io.files.place_file(file, true)?; + pub(crate) fn unmap_memory(address: usize, len: usize) -> Result<(), Error> { + let thread = Thread::current(); + let space = thread.address_space(); - Ok(fd.0 as usize) - }) - } - SyscallFunction::Read => { - let fd = RawFd(args[0] as u32); - let data = arg_buffer_mut(args[1] as _, args[2] as _)?; - - run_with_io(&process, |io| io.files.file(fd)?.read(data)) - } - SyscallFunction::Write => { - let fd = RawFd(args[0] as u32); - let data = arg_buffer_ref(args[1] as _, args[2] as _)?; - - run_with_io(&process, |io| io.files.file(fd)?.write(data)) - } - SyscallFunction::Seek => { - let fd = RawFd(args[0] as u32); - let pos = SeekFrom::from(args[1]); - - run_with_io(&process, |io| { - io.files.file(fd)?.seek(pos).map(|v| v as usize) - }) - } - SyscallFunction::ReadDirectory => { - let fd = RawFd(args[0] as u32); - let buffer = arg_user_slice_mut::>( - args[1] as usize, - args[2] as usize, - )?; - - run_with_io(&process, |io| io.files.file(fd)?.read_dir(buffer)) - } - SyscallFunction::Close => { - let fd = RawFd(args[0] as u32); - - run_with_io(&process, |mut io| { - let res = io.files.close_file(fd); - - if res == Err(Error::InvalidFile) { - warnln!("Double close of fd {:?} in process {}", fd, process.id()); - } - - res?; - - Ok(0) - }) - } - SyscallFunction::Mount => { - let options = arg_user_ref::(args[0] as usize)?; - - run_with_io(&process, |mut io| { - let fs_root = fs::create_filesystem(options)?; - io.ioctx_mut().mount(options.target, fs_root)?; - Ok(0) - }) - } - SyscallFunction::Unmount => { + if len & 0xFFF != 0 { todo!(); } - SyscallFunction::DeviceRequest => { - let fd = RawFd(args[0] as u32); - let req = arg_user_mut::(args[1] as usize)?; - run_with_io(&process, |io| { - let file = io.files.file(fd)?; - // let node = file.node().ok_or(Error::InvalidFile)?; - file.device_request(req)?; - Ok(0) - }) + unsafe { + space.unmap(address, len)?; } - SyscallFunction::GetMetadata => { - let at = arg_option_fd(args[0] as u32); - let path = arg_user_str(args[1] as usize, args[2] as usize)?; - let buffer = arg_user_mut::>(args[3] as usize)?; - let follow = args[4] != 0; - run_with_io_at(&process, at, |at, mut io| { - let node = if path.is_empty() { - at - // at.ok_or(Error::InvalidArgument)? + Ok(()) + } + + pub(crate) fn get_system_info(element: &mut SystemInfo) -> Result<(), Error> { + match element { + SystemInfo::MemoryStats(stats) => { + *stats = phys::stats(); + Ok(()) + } + } + } + + // Process/thread management + pub(crate) fn exit_process(code: ExitCode) -> ! { + let thread = Thread::current(); + thread.exit_process::(code) + } + + pub(crate) fn spawn_process(options: &SpawnOptions<'_>) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |mut io| { + // Setup a new process from the file + let (child_process, child_main) = proc::load_binary( + io.ioctx_mut(), + Some(Arc::downgrade(&process)), + options.program, + options.arguments, + options.environment, + )?; + let pid: u32 = child_process.id().into(); + + // Inherit group and session from the creator + child_process.inherit(&process)?; + + // Inherit root from the creator + // let child_ioctx = IoContext::new(io.ioctx().root().clone()); + let child_ioctx = IoContext::inherit(io.ioctx_mut()); + let mut child_io = child_process.io.lock(); + child_io.set_ioctx(child_ioctx); + + for opt in options.optional { + match opt { + &SpawnOption::InheritFile { source, child } => { + if let Ok(src_file) = io.files.file(source) { + child_io.files.set_file(child, src_file.clone())?; + } + } + &SpawnOption::SetProcessGroup(pgroup) => { + let pgroup = if pgroup == 0 { + child_process.id() + } else { + pgroup.into() + }; + child_process.set_group_id(pgroup); + } + _ => (), + } + } + + if let Some(fd) = options.optional.iter().find_map(|item| { + if let &SpawnOption::GainTerminal(fd) = item { + Some(fd) } else { - io.ioctx_mut().find(Some(at), path, follow, true)? - }; + None + } + }) { + debugln!("{} requested terminal {:?}", pid, fd); + let file = child_io.files.file(fd)?; + // let node = file.node().ok_or(Error::InvalidFile)?; + let mut req = DeviceRequest::SetTerminalGroup(child_process.group_id().into()); + file.device_request(&mut req)?; - let metadata = node.metadata()?; - let size = node.size()?; + if let Some(node) = file.node() { + child_process.set_session_terminal(node.clone()); + } + // node.device_request(&mut req)?; + } - buffer.write(FileAttr { - size, - ty: node.ty(), - mode: metadata.mode, - uid: metadata.uid, - gid: metadata.gid, - }); + drop(child_io); + child_main.enqueue(); - Ok(0) - }) + Ok(pid as _) + }) + } + + pub(crate) fn wait_process(pid: u32, status: &mut ExitCode) -> Result<(), Error> { + let pid = ProcessId::from(pid); + let target = ProcessManagerImpl::get(pid).ok_or(Error::DoesNotExist)?; + *status = block!(target.wait_for_exit().await)?; + Ok(()) + } + + pub(crate) fn get_pid() -> u32 { + let thread = Thread::current(); + let process = thread.process::(); + process.id().into() + } + + pub(crate) fn nanosleep(duration: &Duration) { + block! { + runtime::sleep(*duration).await } - SyscallFunction::UpdateMetadata => { - let at = arg_option_fd(args[0] as u32); - let _path = arg_user_str(args[1] as usize, args[2] as usize)?; - let _update = arg_user_ref::(args[3] as usize)?; - let _follow = args[4] != 0; + .unwrap(); + } - run_with_io_at(&process, at, |_at, _io| { - todo!(); - }) - } - SyscallFunction::CreateDirectory => { - let at = arg_option_fd(args[0] as u32); - let path = arg_user_str(args[1] as usize, args[2] as usize)?; - let mode = FileMode::from(args[3] as u32); + pub(crate) fn set_signal_entry(ip: usize, sp: usize) { + let thread = Thread::current(); + thread.set_signal_entry(ip, sp); + } - run_with_io_at(&process, at, |at, mut io| { - io.ioctx_mut().create_directory(Some(at), path, mode)?; - Ok(0) - }) - } - SyscallFunction::Remove => { - let at = arg_option_fd(args[0] as u32); - let path = arg_user_str(args[1] as usize, args[2] as usize)?; + pub(crate) fn send_signal(target: u32, signal: Signal) -> Result<(), Error> { + let pid = ProcessId(target as _); + let target = ProcessManagerImpl::get(pid).ok_or(Error::DoesNotExist)?; + target.raise_signal(signal); + Ok(()) + } - run_with_io_at(&process, at, |at, mut io| { - io.ioctx_mut().remove_file(Some(at), path)?; - Ok(0) - }) - } - SyscallFunction::RemoveDirectory => { - todo!() - } - SyscallFunction::CreatePipe => { - let ends: &mut [MaybeUninit; 2] = arg_user_mut(args[0] as usize)?; + pub(crate) fn mutex(mutex: &AtomicU32, op: &MutexOperation) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + let mutex = process.get_or_insert_mutex((mutex as *const AtomicU32).addr()); + + match op { + &MutexOperation::Wait(value, _timeout) => block! { mutex.wait(value).await }.unwrap(), + MutexOperation::Wake => mutex.wake(), + MutexOperation::WakeAll => mutex.wake_all(), + } + + Ok(()) + } + + pub(crate) fn start_session() -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + let session_terminal = process.clear_session_terminal(); + + if let Some(ctty) = session_terminal { + // Drop all FDs referring to the old session terminal run_with_io(&process, |mut io| { - let (read, write) = File::new_pipe_pair(256); - - let read_fd = io.files.place_file(read, true)?; - let write_fd = io.files.place_file(write, true)?; - - infoln!("Read end: {:?}", read_fd); - infoln!("Write end: {:?}", write_fd); - - ends[0].write(read_fd); - ends[1].write(write_fd); - - Ok(0) - }) + io.files.retain(|_, f| { + f.node() + .map(|node| !Arc::ptr_eq(node, &ctty)) + .unwrap_or(true) + }); + }); } - SyscallFunction::CreatePoll => run_with_io(&process, |mut io| { + + process.set_session_id(process.id()); + process.set_group_id(process.id()); + + Ok(()) + } + + // I/O + pub(crate) fn open( + at: Option, + path: &str, + opts: OpenOptions, + mode: FileMode, + ) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io_at(&process, at, |at, mut io| { + let file = io.ioctx_mut().open(Some(at), path, opts, mode)?; + + // TODO NO_CTTY? + if process.session_terminal().is_none() + && let Some(node) = file.node() + && node.is_terminal() + { + debugln!("Session terminal set for #{}: {}", process.id(), path); + process.set_session_terminal(node.clone()); + } + + let fd = io.files.place_file(file, true)?; + Ok(fd) + }) + } + + pub(crate) fn close(fd: RawFd) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |mut io| { + let res = io.files.close_file(fd); + + if res == Err(Error::InvalidFile) { + warnln!("Double close of fd {:?} in process {}", fd, process.id()); + } + + res + }) + } + + pub(crate) fn write(fd: RawFd, buffer: &[u8]) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |io| io.files.file(fd)?.write(buffer)) + } + + pub(crate) fn read(fd: RawFd, buffer: &mut [u8]) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |io| io.files.file(fd)?.read(buffer)) + } + + pub(crate) fn seek(fd: RawFd, pos: SeekFrom) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |io| io.files.file(fd)?.seek(pos)) + } + + pub(crate) fn open_directory(at: Option, path: &str) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io_at(&process, at, |at, mut io| { + let node = io.ioctx_mut().find(Some(at), path, true, true)?; + let access = io.ioctx_mut().check_access(vfs::Action::Read, &node)?; + let file = node.open_directory(access)?; + let fd = io.files.place_file(file, true)?; + + Ok(fd) + }) + } + + pub(crate) fn read_directory_entries( + fd: RawFd, + entries: &mut [MaybeUninit], + ) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |io| io.files.file(fd)?.read_dir(entries)) + } + + pub(crate) fn create_directory( + at: Option, + path: &str, + mode: FileMode, + ) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io_at(&process, at, |at, mut io| { + io.ioctx_mut().create_directory(Some(at), path, mode)?; + Ok(()) + }) + } + + pub(crate) fn remove_directory(_at: Option, _path: &str) -> Result<(), Error> { + todo!() + } + + pub(crate) fn remove(at: Option, path: &str) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io_at(&process, at, |at, mut io| { + io.ioctx_mut().remove_file(Some(at), path)?; + Ok(()) + }) + } + + pub(crate) fn clone_fd(source_fd: RawFd, target_fd: Option) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |mut io| { + let file = io.files.file(source_fd)?.clone(); + + let fd = match target_fd { + Some(target_fd) => { + io.files.set_file(target_fd, file)?; + target_fd + } + None => io.files.place_file(file, true)?, + }; + + Ok(fd) + }) + } + + pub(crate) fn update_metadata( + at: Option, + _path: &str, + _update: &FileMetadataUpdate, + ) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io_at(&process, at, |_at, _io| { + todo!(); + }) + } + + pub(crate) fn get_metadata( + at: Option, + path: &str, + buffer: &mut MaybeUninit, + follow: bool, + ) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io_at(&process, at, |at, mut io| { + let node = if path.is_empty() { + at + // at.ok_or(Error::InvalidArgument)? + } else { + io.ioctx_mut().find(Some(at), path, follow, true)? + }; + + let metadata = node.metadata()?; + let size = node.size()?; + + buffer.write(FileAttr { + size, + ty: node.ty(), + mode: metadata.mode, + uid: metadata.uid, + gid: metadata.gid, + }); + + Ok(()) + }) + } + + pub(crate) fn device_request(fd: RawFd, req: &mut DeviceRequest) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |io| io.files.file(fd)?.device_request(req)) + } + + // Misc I/O + pub(crate) fn open_channel(name: &str, subscribe: bool) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |mut io| { + let file = File::new_message_channel(name, subscribe); + let fd = io.files.place_file(file, true)?; + Ok(fd) + }) + } + + pub(crate) fn create_timer(repeat: bool) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |mut io| { + let file = File::new_timer(repeat); + let fd = io.files.place_file(file, true)?; + Ok(fd) + }) + } + + pub(crate) fn create_pty( + options: &TerminalOptions, + size: &TerminalSize, + output: &mut [MaybeUninit; 2], + ) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |mut io| { + let (master, slave) = File::new_pseudo_terminal(*options, *size)?; + let master_fd = io.files.place_file(master, true)?; + let slave_fd = io.files.place_file(slave, true)?; + + output[0].write(master_fd); + output[1].write(slave_fd); + + Ok(()) + }) + } + + pub(crate) fn create_shared_memory(size: usize) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |mut io| { + let file = File::new_shared_memory(size)?; + let fd = io.files.place_file(file, true)?; + Ok(fd) + }) + } + + pub(crate) fn create_poll_channel() -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |mut io| { let poll = File::new_poll_channel(); let fd = io.files.place_file(poll, true)?; - Ok(fd.0 as usize) - }), - SyscallFunction::PollControl => { - let poll_fd = RawFd::from(args[0] as u32); - let control = - PollControl::try_from(args[1] as u32).map_err(|_| Error::InvalidArgument)?; - let fd = RawFd::from(args[2] as u32); - - run_with_io(&process, |io| { - let poll_file = io.files.file(poll_fd)?; - let poll = poll_file.as_poll_channel()?; - - match control { - PollControl::AddFd => { - let polled_file = io.files.file(fd)?.clone(); - poll.add(fd, polled_file); - } - } - - Ok(0) - }) - } - SyscallFunction::PollWait => { - let poll_fd = RawFd::from(args[0] as u32); - let timeout = arg_user_ref::>(args[1] as usize)?; - let output = arg_user_mut::)>>(args[2] as usize)?; - - run_with_io(&process, |io| { - let poll_file = io.files.file(poll_fd)?; - let poll = poll_file.as_poll_channel()?; - - *output = block! { - poll.wait(*timeout).await - }?; - - Ok(0) - }) - } - SyscallFunction::OpenChannel => { - let name = arg_user_str(args[0] as usize, args[1] as usize)?; - let with_sub = args[2] != 0; - - debugln!("OpenChannel {:?}, with_sub={}", name, with_sub); - - run_with_io(&process, |mut io| { - let file = File::new_message_channel(name, with_sub); - let fd = io.files.place_file(file, true)?; - - Ok(fd.0 as usize) - }) - } - SyscallFunction::SendMessage => { - let fd = RawFd::from(args[0] as u32); - let message = arg_user_ref::(args[1] as usize)?; - let destination = MessageDestination::from(args[2]); - - run_with_io(&process, |io| { - let file = io.files.file(fd)?; - let channel = file.as_message_channel()?; - - match message { - &SentMessage::File(fd) => { - let sent_file = io.files.file(fd)?; - - channel - .send_message(MessagePayload::File(sent_file.clone()), destination)?; - } - &SentMessage::Data(data) => { - channel.send_message(MessagePayload::Data(Box::from(data)), destination)?; - } - } - - Ok(0) - }) - } - SyscallFunction::ReceiveMessage => { - let fd = RawFd::from(args[0] as u32); - let metadata = arg_user_mut::>(args[1] as usize)?; - let buf = arg_buffer_mut(args[2] as usize, args[3] as usize)?; - let from = arg_user_mut::>(args[4] as usize)?; - - run_with_io(&process, |mut io| { - let file = io.files.file(fd)?; - let channel = file.as_message_channel()?; - - let message = channel.receive_message()?; - - from.write(message.source); - - match &message.payload { - MessagePayload::Data(data) => { - // TODO allow truncated messages? - let len = data.len(); - if buf.len() < len { - return Err(Error::MissingData); - } - - metadata.write(ReceivedMessageMetadata::Data(len)); - buf[..len].copy_from_slice(data); - - Ok(len) - } - MessagePayload::File(file) => { - let fd = io.files.place_file(file.clone(), true)?; - - metadata.write(ReceivedMessageMetadata::File(fd)); - - Ok(0) - } - } - }) - } - SyscallFunction::CreateSharedMemory => { - let size = args[0] as usize; - let size = size.page_align_up::(); - - run_with_io(&process, |mut io| { - let file = File::new_shared_memory(size)?; - let fd = io.files.place_file(file, true)?; - Ok(fd.0 as usize) - }) - } - SyscallFunction::CreatePty => { - let options = arg_user_ref::(args[0] as usize)?; - let size = arg_user_ref::(args[1] as usize)?; - let output = arg_user_mut::>(args[2] as usize)?; - - run_with_io(&process, |mut io| { - let (master, slave) = File::new_pseudo_terminal(*options, *size)?; - let master_fd = io.files.place_file(master, true)?; - let slave_fd = io.files.place_file(slave, true)?; - - output.write((master_fd, slave_fd)); - - Ok(0) - }) - } - SyscallFunction::CloneFd => { - let source_fd = RawFd::from(args[0] as u32); - let target_fd = RawFd::from(args[1] as u32); - - run_with_io(&process, |mut io| { - let file = io.files.file(source_fd)?.clone(); - - let fd = if target_fd != RawFd::NONE { - io.files.set_file(target_fd, file)?; - target_fd - } else { - io.files.place_file(file, true)? - }; - - Ok(fd.0 as usize) - }) - } - SyscallFunction::CreateTimer => { - let repeat = args[0] != 0; - - run_with_io(&process, |mut io| { - let file = File::new_timer(repeat); - let fd = io.files.place_file(file, true)?; - Ok(fd.0 as _) - }) - } - // Process management - SyscallFunction::SpawnProcess => { - let options = arg_user_ref::(args[0] as usize)?; - - run_with_io(&process, |mut io| { - // Setup a new process from the file - let (child_process, child_main) = proc::load_binary( - io.ioctx_mut(), - Some(Arc::downgrade(&process)), - options.program, - options.arguments, - options.environment, - )?; - let pid: u32 = child_process.id().into(); - - // Inherit group and session from the creator - child_process.inherit(&process)?; - - // Inherit root from the creator - // let child_ioctx = IoContext::new(io.ioctx().root().clone()); - let child_ioctx = IoContext::inherit(io.ioctx_mut()); - let mut child_io = child_process.io.lock(); - child_io.set_ioctx(child_ioctx); - - for opt in options.optional { - match opt { - &SpawnOption::InheritFile { source, child } => { - if let Ok(src_file) = io.files.file(source) { - child_io.files.set_file(child, src_file.clone())?; - } - } - &SpawnOption::SetProcessGroup(pgroup) => { - let pgroup = if pgroup == 0 { - child_process.id() - } else { - pgroup.into() - }; - child_process.set_group_id(pgroup); - } - _ => (), - } - } - - if let Some(fd) = options.optional.iter().find_map(|item| { - if let &SpawnOption::GainTerminal(fd) = item { - Some(fd) - } else { - None - } - }) { - debugln!("{} requested terminal {:?}", pid, fd); - let file = child_io.files.file(fd)?; - // let node = file.node().ok_or(Error::InvalidFile)?; - let mut req = DeviceRequest::SetTerminalGroup(child_process.group_id().into()); - file.device_request(&mut req)?; - - if let Some(node) = file.node() { - child_process.set_session_terminal(node.clone()); - } - // node.device_request(&mut req)?; - } - - drop(child_io); - child_main.enqueue(); - - Ok(pid as _) - }) - } - SyscallFunction::Exec => { - let options = arg_user_ref::(args[0] as usize)?; - sys_execve(thread, options)?; - } - SyscallFunction::SpawnThread => { - let options = arg_user_ref::(args[0] as usize)?; - let id = process.spawn_thread(options)?; - Ok(id.as_user() as _) - } - SyscallFunction::Mutex => { - let address = args[0] as usize; - let op = arg_user_ref::(args[1] as usize)?; - - let mutex = process.get_or_insert_mutex(address); - - match op { - &MutexOperation::Wait(value, _timeout) => { - block! { mutex.wait(value).await }.unwrap() - } - MutexOperation::Wake => mutex.wake(), - MutexOperation::WakeAll => mutex.wake_all(), - } - - Ok(0) - } - SyscallFunction::ExitThread => { - let code = ExitCode::from(args[0] as i32); - thread.exit::(code) - } - SyscallFunction::ExitProcess => { - // A bit different from thread exit: wait for other threads to finish and exit only - // after that - let code = ExitCode::from(args[0] as i32); - - thread.exit_process::(code) - } - SyscallFunction::SendSignal => { - let pid = ProcessId::from(args[0] as u32); - let signal = Signal::try_from(args[1] as u32).map_err(|_| Error::InvalidArgument)?; - - let target = ProcessManagerImpl::get(pid).ok_or(Error::DoesNotExist)?; - target.raise_signal(signal); - - Ok(0) - } - SyscallFunction::ExitSignal => { - panic!("Handled elsewhere"); - // Process::current().exit_signal(); - } - SyscallFunction::GetPid => Ok(u32::from(process.id()) as usize), - SyscallFunction::GetSessionId => todo!(), - SyscallFunction::GetProcessGroupId => todo!(), - SyscallFunction::SetProcessGroupId => { - let pid = ProcessId::from(args[0] as u32); - let group_id = ProcessId::from(args[1] as u32); - - // Other syscall variants are not currently supported - assert_eq!(pid, group_id); - assert_eq!(process.id(), pid); - - process.set_group_id(group_id); - Ok(0) - } - SyscallFunction::GetProcessInfo => { - let element = arg_user_mut::(args[0] as _)?; - - run_with_io(&process, |mut io| match element { - ProcessInfoElement::Umask(mask) => { - *mask = io.ioctx_mut().umask(); - Ok(0) - } - }) - } - SyscallFunction::SetProcessInfo => { - let element = arg_user_ref::(args[0] as _)?; - - run_with_io(&process, |mut io| match element { - &ProcessInfoElement::Umask(mask) => { - io.ioctx_mut().set_umask(mask); - Ok(0) - } - }) - } - SyscallFunction::GetSystemInfo => { - let element = arg_user_mut::(args[0] as _)?; - - match element { - SystemInfo::MemoryStats(stats) => { - *stats = phys::stats(); - Ok(0) - } - } - } - SyscallFunction::StartSession => { - let session_terminal = process.clear_session_terminal(); - - if let Some(ctty) = session_terminal { - // Drop all FDs referring to the old session terminal - run_with_io(&process, |mut io| { - io.files.retain(|_, f| { - f.node() - .map(|node| !Arc::ptr_eq(node, &ctty)) - .unwrap_or(true) - }); - }); - } - - process.set_session_id(process.id()); - process.set_group_id(process.id()); - - Ok(0) - } - // Waiting and polling - SyscallFunction::WaitProcess => { - let pid = ProcessId::from(args[0] as u32); - debugln!("WaitProcess #{}", pid); - let status = arg_user_mut::(args[1] as _)?; - - let target = ProcessManagerImpl::get(pid).ok_or(Error::DoesNotExist)?; - - *status = block!(target.wait_for_exit().await)?; - - Ok(0) - } - - // Networking - SyscallFunction::BindSocket => { - let listen = arg_user_ref::(args[0] as usize)?; - let ty = SocketType::try_from(args[1] as u32).map_err(|_| Error::InvalidArgument)?; - - run_with_io(&process, |mut io| { - let file = match ty { - SocketType::UdpPacket => { - File::from_packet_socket(UdpSocket::bind((*listen).into())?) - } - SocketType::RawPacket => File::from_packet_socket(RawSocket::bind()?), - SocketType::TcpStream => { - File::from_listener_socket(TcpListener::bind((*listen).into())?) - } - }; - let fd = io.files.place_file(file, true)?; - Ok(fd.0 as usize) - }) - } - SyscallFunction::ConnectSocket => { - let socket_fd = RawFd::from(args[0] as u32); - let remote = arg_user_ref::(args[1] as usize)?; - let ty = SocketType::try_from(args[2] as u32).map_err(|_| Error::InvalidArgument)?; - let local_result = - arg_user_mut::>(args[3] as usize)?; - - // TODO connect on existing sockets? - assert_eq!(socket_fd, RawFd::NONE); - - run_with_io(&process, |mut io| { - let (local, file) = match ty { - SocketType::TcpStream => { - let (local, socket) = TcpSocket::connect((*remote).into())?; - (local, File::from_stream_socket(socket)) - } - _ => return Err(Error::InvalidArgument), - }; - let fd = io.files.place_file(file, true)?; - local_result.write(local.into()); - Ok(fd.0 as usize) - }) - } - SyscallFunction::SendTo => { - let socket_fd = RawFd::from(args[0] as u32); - let buffer = arg_buffer_ref(args[1] as usize, args[2] as usize)?; - let recepient = arg_user_ref::>(args[3] as usize)?; - - run_with_io(&process, |io| { - let file = io.files.file(socket_fd)?; - - file.send_to(buffer, recepient.map(Into::into)) - }) - } - SyscallFunction::ReceiveFrom => { - let socket_fd = RawFd::from(args[0] as u32); - let buffer = arg_buffer_mut(args[1] as usize, args[2] as usize)?; - let remote_result = - arg_user_mut::>(args[3] as usize)?; - - run_with_io(&process, |io| { - let file = io.files.file(socket_fd)?; - let mut remote = MaybeUninit::uninit(); - let len = file.receive_from(buffer, &mut remote)?; - remote_result.write(unsafe { remote.assume_init() }.into()); - Ok(len) - }) - } - SyscallFunction::GetSocketOption => { - let socket_fd = RawFd::from(args[0] as u32); - let option = arg_user_mut::(args[1] as usize)?; - - run_with_io(&process, |io| { - let file = io.files.file(socket_fd)?; - let socket = file.as_socket()?; - socket.get_option(option)?; - Ok(0) - }) - } - SyscallFunction::SetSocketOption => { - let socket_fd = RawFd::from(args[0] as u32); - let option = arg_user_ref::(args[1] as usize)?; - - run_with_io(&process, |io| { - let file = io.files.file(socket_fd)?; - let socket = file.as_socket()?; - socket.set_option(option)?; - Ok(0) - }) - } - SyscallFunction::Accept => { - let socket_fd = RawFd::from(args[0] as u32); - let remote_result = - arg_user_mut::>(args[1] as usize)?; - - run_with_io(&process, |mut io| { - let file = io.files.file(socket_fd)?; - let mut remote = MaybeUninit::uninit(); - let accepted_file = file.accept(&mut remote)?; - let accepted_fd = io.files.place_file(accepted_file, true)?; - unsafe { - remote_result.write(remote.assume_init().into()); - } - Ok(accepted_fd.0 as usize) - }) - } - - SyscallFunction::Fork => unreachable!(), + Ok(fd) + }) } + + pub(crate) fn create_pipe(ends: &mut [MaybeUninit; 2]) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |mut io| { + let (read, write) = File::new_pipe_pair(256); + + let read_fd = io.files.place_file(read, true)?; + let write_fd = io.files.place_file(write, true)?; + + ends[0].write(read_fd); + ends[1].write(write_fd); + + Ok(()) + }) + } + + pub(crate) fn poll_channel_wait( + poll_fd: RawFd, + timeout: &Option, + output: &mut Option<(RawFd, Result<(), Error>)>, + ) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |io| { + let poll_file = io.files.file(poll_fd)?; + let poll = poll_file.as_poll_channel()?; + + *output = block! { + poll.wait(*timeout).await + }?; + + Ok(()) + }) + } + + pub(crate) fn poll_channel_control( + poll_fd: RawFd, + control: PollControl, + fd: RawFd, + ) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |io| { + let poll_file = io.files.file(poll_fd)?; + let poll = poll_file.as_poll_channel()?; + + match control { + PollControl::AddFd => { + let polled_file = io.files.file(fd)?.clone(); + poll.add(fd, polled_file); + } + } + + Ok(()) + }) + } + + pub(crate) fn send_message( + fd: RawFd, + message: &SentMessage<'_>, + destination: MessageDestination, + ) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |io| { + let file = io.files.file(fd)?; + let channel = file.as_message_channel()?; + + match message { + &SentMessage::File(fd) => { + let sent_file = io.files.file(fd)?; + + channel.send_message(MessagePayload::File(sent_file.clone()), destination)?; + } + &SentMessage::Data(data) => { + channel.send_message(MessagePayload::Data(Box::from(data)), destination)?; + } + } + + Ok(()) + }) + } + + pub(crate) fn receive_message( + fd: RawFd, + metadata: &mut MaybeUninit, + buf: &mut [u8], + from: &mut MaybeUninit, + ) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |mut io| { + let file = io.files.file(fd)?; + let channel = file.as_message_channel()?; + + let message = channel.receive_message()?; + + from.write(message.source); + + match &message.payload { + MessagePayload::Data(data) => { + // TODO allow truncated messages? + let len = data.len(); + if buf.len() < len { + return Err(Error::MissingData); + } + + metadata.write(ReceivedMessageMetadata::Data(len)); + buf[..len].copy_from_slice(data); + + Ok(()) + } + MessagePayload::File(file) => { + let fd = io.files.place_file(file.clone(), true)?; + + metadata.write(ReceivedMessageMetadata::File(fd)); + + Ok(()) + } + } + }) + } + + // Network + pub(crate) fn connect_socket( + socket_fd: Option, + remote: &SocketAddr, + ty: SocketType, + local_result: &mut MaybeUninit, + ) -> Result { + assert!(socket_fd.is_none()); + + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |mut io| { + let (local, file) = match ty { + SocketType::TcpStream => { + let (local, socket) = TcpSocket::connect((*remote).into())?; + (local, File::from_stream_socket(socket)) + } + _ => return Err(Error::InvalidArgument), + }; + let fd = io.files.place_file(file, true)?; + local_result.write(local.into()); + Ok(fd) + }) + } + + pub(crate) fn bind_socket(listen: &SocketAddr, ty: SocketType) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |mut io| { + let file = match ty { + SocketType::UdpPacket => { + File::from_packet_socket(UdpSocket::bind((*listen).into())?) + } + SocketType::RawPacket => File::from_packet_socket(RawSocket::bind()?), + SocketType::TcpStream => { + File::from_listener_socket(TcpListener::bind((*listen).into())?) + } + }; + let fd = io.files.place_file(file, true)?; + Ok(fd) + }) + } + + pub(crate) fn accept( + socket_fd: RawFd, + remote_result: &mut MaybeUninit, + ) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |mut io| { + let file = io.files.file(socket_fd)?; + let mut remote = MaybeUninit::uninit(); + let accepted_file = file.accept(&mut remote)?; + let accepted_fd = io.files.place_file(accepted_file, true)?; + unsafe { + remote_result.write(remote.assume_init().into()); + } + Ok(accepted_fd) + }) + } + + pub(crate) fn send_to( + socket_fd: RawFd, + buffer: &[u8], + recepient: &Option, + ) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |io| { + let file = io.files.file(socket_fd)?; + + file.send_to(buffer, recepient.map(Into::into)) + }) + } + + pub(crate) fn receive_from( + socket_fd: RawFd, + buffer: &mut [u8], + remote_result: &mut MaybeUninit, + ) -> Result { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |io| { + let file = io.files.file(socket_fd)?; + let mut remote = MaybeUninit::uninit(); + let len = file.receive_from(buffer, &mut remote)?; + remote_result.write(unsafe { remote.assume_init() }.into()); + Ok(len) + }) + } + + pub(crate) fn set_socket_option(socket_fd: RawFd, option: &SocketOption) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |io| { + let file = io.files.file(socket_fd)?; + let socket = file.as_socket()?; + socket.set_option(option) + }) + } + + pub(crate) fn get_socket_option( + socket_fd: RawFd, + option: &mut SocketOption, + ) -> Result<(), Error> { + let thread = Thread::current(); + let process = thread.process::(); + + run_with_io(&process, |io| { + let file = io.files.file(socket_fd)?; + let socket = file.as_socket()?; + socket.get_option(option) + }) + } + + // Handled outside + pub(crate) fn exit_signal(_frame: &SignalEntryData) -> ! { + unreachable!() + } + + pub(crate) fn fork() -> Result { + unreachable!() + } + + pub(crate) fn execve(_options: &ExecveOptions<'_>) -> Result<(), Error> { + unreachable!() + } +} + +mod generated { + #![allow(unreachable_code)] + + use abi::SyscallFunction; + use abi_lib::SyscallRegister; + + use super::{ + arg, + impls::{self, *}, + }; + + include!(concat!(env!("OUT_DIR"), "/generated_dispatcher.rs")); } /// Entrypoint for system calls that takes raw argument values @@ -829,20 +851,14 @@ pub fn raw_syscall_handler(func: u64, args: &[u64]) -> u64 { let Ok(func) = SyscallFunction::try_from(func as usize) else { todo!("Undefined syscall: {}", func); }; + let args = unsafe { core::mem::transmute(args) }; - // let proc = Process::current(); - // debugln!( - // "{} {:?}: raw_syscall_handler {:?}, {:x?}", - // proc.id(), - // proc.name(), - // func, - // args - // ); - let result = syscall_handler(func, args); + let result = generated::handle_syscall(func, args); - if let &Err(error) = &result { - warnln!("{:?}: {:?}", func, error); - } + let value = match result { + Ok(value) => value, + Err(e) => (-(e as u32 as isize)) as usize, + }; - result.into_syscall_result() as u64 + value as _ }