From 373ee5c2de0964c62dcafa987198e58831a8b530 Mon Sep 17 00:00:00 2001 From: AuYang261 <459461160@qq.com> Date: Tue, 26 Mar 2024 14:48:19 +0800 Subject: [PATCH 01/13] add random-hw feature in ruxmusl --- apps/c/cpp/features.txt | 2 ++ apps/c/cpp/main.cpp | 8 ++++++++ ulib/ruxmusl/Cargo.toml | 1 + 3 files changed, 11 insertions(+) diff --git a/apps/c/cpp/features.txt b/apps/c/cpp/features.txt index 9812e2a76..662a64968 100644 --- a/apps/c/cpp/features.txt +++ b/apps/c/cpp/features.txt @@ -2,3 +2,5 @@ alloc paging irq multitask +fs +random-hw diff --git a/apps/c/cpp/main.cpp b/apps/c/cpp/main.cpp index 0a77600ab..f970043fe 100644 --- a/apps/c/cpp/main.cpp +++ b/apps/c/cpp/main.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include extern "C" { @@ -65,5 +66,12 @@ int main() } std::cout << std::endl; + // random test + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(1, 100); + for (int i = 0; i < 10; i++) { + std::cout << "Random number: " << dis(gen) << std::endl; + } return 0; } diff --git a/ulib/ruxmusl/Cargo.toml b/ulib/ruxmusl/Cargo.toml index b8242a496..ca56428b1 100644 --- a/ulib/ruxmusl/Cargo.toml +++ b/ulib/ruxmusl/Cargo.toml @@ -41,6 +41,7 @@ epoll = ["ruxos_posix_api/epoll"] poll = ["ruxos_posix_api/poll"] rtc = ["ruxfeat/rtc"] signal = ["ruxos_posix_api/signal"] +random-hw = ["ruxos_posix_api/random-hw"] musl = ["ruxos_posix_api/musl", "tls"] From 5b48a0edeaffbf95b7045f291d37269fbe6fb53b Mon Sep 17 00:00:00 2001 From: AuYang261 <459461160@qq.com> Date: Tue, 26 Mar 2024 14:48:41 +0800 Subject: [PATCH 02/13] add c++ benchmark --- apps/c/cpp/.gitignore | 1 + apps/c/cpp/axbuild.mk | 56 +++++++++++++---- apps/c/cpp/main.cpp | 77 ----------------------- apps/c/cpp/std_benchmark.patch | 109 +++++++++++++++++++++++++++++++++ modules/ruxfs/src/mounts.rs | 2 + 5 files changed, 156 insertions(+), 89 deletions(-) create mode 100644 apps/c/cpp/.gitignore delete mode 100644 apps/c/cpp/main.cpp create mode 100644 apps/c/cpp/std_benchmark.patch diff --git a/apps/c/cpp/.gitignore b/apps/c/cpp/.gitignore new file mode 100644 index 000000000..bebd92107 --- /dev/null +++ b/apps/c/cpp/.gitignore @@ -0,0 +1 @@ +std-benchmark/ diff --git a/apps/c/cpp/axbuild.mk b/apps/c/cpp/axbuild.mk index 94d073e32..37e8ea604 100644 --- a/apps/c/cpp/axbuild.mk +++ b/apps/c/cpp/axbuild.mk @@ -1,21 +1,53 @@ +CMAKE = cmake + ARCH ?= x86_64 C_COMPILER := $(shell which $(CC)) +CXX_COMPILER := $(shell which $(CC)) +AR := $(shell which $(AR)) +RANLIB := $(shell which $(RANLIB)) CROSS_COMPILE_PATH := $(shell dirname $(C_COMPILER))/.. -CXX_STD := c++20 +CXX_STD ?= 20 + +app-objs := std_benchmark.o +std_benchmark_dir := $(APP)/std-benchmark +std_benchmark_build = $(std_benchmark_dir)/build + +bench ?= all +benches_available := $(wildcard $(std_benchmark_dir)/cxx/*.bench.cpp) +benches_available := $(patsubst $(std_benchmark_dir)/cxx/%.bench.cpp,%,$(benches_available)) -main-obj := main.o -app-objs := cpp.o +$(std_benchmark_dir): + @echo "Download std-benchmark source code" + cd $(APP)/ && git clone --recursive https://github.com/hiraditya/std-benchmark + patch -p1 -N -d $(std_benchmark_dir) --no-backup-if-mismatch -r - < $(APP)/std_benchmark.patch -$(APP)/$(app-objs): build_cpp -build_cpp: $(APP)/axbuild.mk $(APP)/main.cpp - $(C_COMPILER) -o $(APP)/$(main-obj) -nostdlib -static -no-pie -c -std=$(CXX_STD) \ - $(APP)/main.cpp -I$(CROSS_COMPILE_PATH)/*-linux-musl/include/c++/* - $(LD) -o $(app-objs) $(APP)/$(main-obj) -nostdlib -static -no-pie -r -e main \ +$(APP)/$(app-objs): build_std-benchmark +build_std-benchmark: $(std_benchmark_dir) $(APP)/axbuild.mk + cd $(std_benchmark_dir) && mkdir -p build && cd build && \ + $(CMAKE) .. -DCMAKE_CXX_STANDARD=$(CXX_STD) -DCMAKE_C_COMPILER=$(C_COMPILER) -DCMAKE_CXX_COMPILER=$(CXX_COMPILER) -DCMAKE_AR=$(AR) -DCMAKE_RANLIB=$(RANLIB) \ + -DENABLE_C_BENCHMARKS=OFF -DENABLE_C_VS_CXX_BENCHMARKS=OFF -DENABLE_COMPILER_VS_PROGRAMMER=OFF -DBENCHMARK_ENABLE_TESTING=OFF && \ + $(MAKE) -j + mkdir -p $(std_benchmark_build)/libgcc && cd $(std_benchmark_build)/libgcc && \ + ln -s -f $(CROSS_COMPILE_PATH)/lib/gcc/*-linux-musl/*/libgcc.a ./ && \ + $(AR) x libgcc.a _clrsbsi2.o +ifeq ($(bench), all) + $(error "Running all benches automatically is not supported, please add 'bench=' arg. \ + Available benches: $(benches_available)") +endif +ifneq ($(filter $(bench),$(benches_available)),) + $(LD) -o $(app-objs) -nostdlib -static -no-pie -r -e main \ + $(std_benchmark_build)/cxx/lib$(bench).bench.cpp.out.a \ + $(std_benchmark_build)/benchmark/src/libbenchmark.a \ $(CROSS_COMPILE_PATH)/*-linux-musl/lib/libstdc++.a \ - $(CROSS_COMPILE_PATH)/lib/gcc/*-linux-musl/*/libgcc_eh.a + $(CROSS_COMPILE_PATH)/lib/gcc/*-linux-musl/*/libgcc_eh.a \ + $(std_benchmark_build)/libgcc/_clrsbsi2.o +else + $(error "Available benches: $(benches_available)") +endif clean_c:: - rm -rf $(app-objs) - rm -rf $(APP)/$(main-obj) + rm -rf $(std_benchmark_build)/ + +.PHONY: build_std-benchmark clean_c + -.PHONY: build_cpp clean_c diff --git a/apps/c/cpp/main.cpp b/apps/c/cpp/main.cpp deleted file mode 100644 index f970043fe..000000000 --- a/apps/c/cpp/main.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include -#include -#include -#include -#include - -extern "C" { -__attribute__((weak)) void *__dso_handle; -} - -int main() -{ - - // cpp version - std::cout << "C++ version: " << __cplusplus << std::endl; - - // Create a list of integers - std::list myList = {5, 2, 8, 3, 1}; - - // Print the original list - std::cout << "Original list: "; - for (const auto &num : myList) { - std::cout << num << " "; - } - std::cout << std::endl; - - // Sort the list in ascending order - myList.sort(); - - // Print the sorted list - std::cout << "Sorted list: "; - for (const auto &num : myList) { - std::cout << num << " "; - } - std::cout << std::endl; - - // Create a vector of integers - std::vector myVector = {5, 2, 8, 3, 1}; - - // Print the original vector - std::cout << "Original vector: "; - for (const auto &num : myVector) { - std::cout << num << " "; - } - std::cout << std::endl; - - // Sort the vector in ascending order - std::sort(myVector.begin(), myVector.end()); - - // Print the sorted vector - std::cout << "Sorted vector: "; - for (const auto &num : myVector) { - std::cout << num << " "; - } - std::cout << std::endl; - - // Create a map of strings to integers - std::map myMap = { - {"apple", 5}, {"banana", 2}, {"orange", 8}, {"grape", 3}, {"kiwi", 1}}; - - // Print the map - std::cout << "Map: "; - for (const auto &pair : myMap) { - std::cout << pair.first << ":" << pair.second << " "; - } - std::cout << std::endl; - - // random test - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(1, 100); - for (int i = 0; i < 10; i++) { - std::cout << "Random number: " << dis(gen) << std::endl; - } - return 0; -} diff --git a/apps/c/cpp/std_benchmark.patch b/apps/c/cpp/std_benchmark.patch new file mode 100644 index 000000000..55e03db0b --- /dev/null +++ b/apps/c/cpp/std_benchmark.patch @@ -0,0 +1,109 @@ +--- /cxx/CMakeLists.txt ++++ /cxx/CMakeLists.txt +@@ -3,7 +3,7 @@ foreach(test_path ${BENCHMARK_TESTS}) + get_filename_component(test_file "${test_path}" NAME) + set(target ${test_file}.out) + #EXCLUDE_FROM_ALL +- add_executable(${target} ${test_file}) ++ add_library(${target} ${test_file}) + # shlwapi for MSVC + #target_link_libraries(${target} benchmark -pthread shlwapi) + target_link_libraries(${target} benchmark -pthread) +--- /cxx/mutators.bench.cpp ++++ /cxx/mutators.bench.cpp +@@ -26,8 +27,8 @@ void BM_write_seq(benchmark::State& state) { + template + void BM_push_back(benchmark::State& state) { + int N = state.range(0); +- V v; + while (state.KeepRunning()) { ++ V v; + for (int i = 0; i < N; ++i) + v.push_back(i); + } +@@ -37,8 +38,8 @@ void BM_push_back(benchmark::State& state) { + template + void BM_push_back_resize(benchmark::State& state) { + int N = state.range(0); +- V v(N); + while (state.KeepRunning()) { ++ V v(N); + for (int i = 0; i < N; ++i) + v.push_back(i); + } +@@ -48,9 +49,9 @@ void BM_push_back_resize(benchmark::State& state) { + template + void BM_push_back_vector_reserve(benchmark::State& state) { + int N = state.range(0); +- V v; +- v.reserve(N); + while (state.KeepRunning()) { ++ V v; ++ v.reserve(N); + for (int i = 0; i < N; ++i) + v.push_back(i); + } +@@ -60,9 +61,9 @@ void BM_push_back_vector_reserve(benchmark::State& state) { + template + void BM_insert_begin(benchmark::State& state) { + int N = state.range(0); +- V v(N, 1); +- auto val = *v.begin(); + while (state.KeepRunning()) { ++ V v(N, 1); ++ auto val = *v.begin(); + v.insert(v.begin(), val); + } + state.SetComplexityN(N); +@@ -94,14 +95,15 @@ void BM_assoc_insert_random(benchmark::State& state) { + int N = state.range(0); + using CVT = typename V::value_type; + using VT = typename remove_const::type; +- std::vector temp(N*1000); ++ // TODO: It will panic if *100 or *1000 ++ std::vector temp(N*10); + fill_random(temp); + V v; + auto it = temp.begin(); + while (state.KeepRunning()) { + v.insert(*it++); + if (it == temp.end()) // FIXME: After temp.end insert will just return. +- assert(0);//it = temp.begin(); ++ it = temp.begin(); + } + state.SetComplexityN(N); + } +--- /include/test_configs.h ++++ /include/test_configs.h +@@ -1,6 +1,8 @@ + #ifndef TEST_CONFIGS_H + #define TEST_CONFIGS_H + ++void *__dso_handle = 0; ++ + #define KB << 10 + #define MB << 20 + #define GB << 30 +@@ -12,9 +12,9 @@ + #ifdef i7_4770 + // To benchmark data residing completely in L1 cache. + #ifndef ENABLE_TRAVIS_BUILD +-#define L1 (32 KB) ++#define L1 (16) + // To benchmark data residing in L2 cache. +-#define L2 (256 KB) ++#define L2 (L1 << 7) + #else + // For the Travis CI to run the entire test. + #define L1 (16 KB) +--- /benchmark/CMakeLists.txt ++++ /benchmark/CMakeLists.txt +@@ -177,6 +177,8 @@ endif(BENCHMARK_USE_LIBCXX) + cxx_feature_check(STD_REGEX) + cxx_feature_check(GNU_POSIX_REGEX) + cxx_feature_check(POSIX_REGEX) ++add_compile_definitions(HAVE_STD_REGEX) ++set(HAVE_STD_REGEX 1) + if(NOT HAVE_STD_REGEX AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX) + message(FATAL_ERROR "Failed to determine the source files for the regular expression backend") + endif() diff --git a/modules/ruxfs/src/mounts.rs b/modules/ruxfs/src/mounts.rs index a32978eb7..b6dbf224f 100644 --- a/modules/ruxfs/src/mounts.rs +++ b/modules/ruxfs/src/mounts.rs @@ -20,11 +20,13 @@ pub(crate) fn devfs() -> Arc { let zero = fs::devfs::ZeroDev; let bar = fs::devfs::ZeroDev; let random = fs::devfs::RandomDev; + let urandom = fs::devfs::RandomDev; let devfs = fs::devfs::DeviceFileSystem::new(); let foo_dir = devfs.mkdir("foo"); devfs.add("null", Arc::new(null)); devfs.add("zero", Arc::new(zero)); devfs.add("random", Arc::new(random)); + devfs.add("urandom", Arc::new(urandom)); foo_dir.add("bar", Arc::new(bar)); Arc::new(devfs) } From 71b813db329d23424b1a762f17bb65da5458f9fd Mon Sep 17 00:00:00 2001 From: wuzheng Date: Wed, 27 Mar 2024 15:43:29 +0800 Subject: [PATCH 03/13] fix bugs in pl011 --- modules/ruxhal/src/arch/aarch64/trap.rs | 4 ++++ .../src/platform/aarch64_common/pl011.rs | 23 ++++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/modules/ruxhal/src/arch/aarch64/trap.rs b/modules/ruxhal/src/arch/aarch64/trap.rs index b9a19ed5b..5a863e6b7 100644 --- a/modules/ruxhal/src/arch/aarch64/trap.rs +++ b/modules/ruxhal/src/arch/aarch64/trap.rs @@ -9,6 +9,8 @@ use core::arch::global_asm; +#[cfg(feature = "irq")] +use crate::arch::enable_irqs; use aarch64_cpu::registers::{ESR_EL1, FAR_EL1}; use tock_registers::interfaces::Readable; @@ -56,6 +58,8 @@ fn handle_sync_exception(tf: &mut TrapFrame) { #[cfg(feature = "musl")] Some(ESR_EL1::EC::Value::SVC64) => { debug!("Handle supervisor call {}", tf.r[8]); + #[cfg(feature = "irq")] + enable_irqs(); let result = crate::trap::handle_syscall( tf.r[8] as usize, [ diff --git a/modules/ruxhal/src/platform/aarch64_common/pl011.rs b/modules/ruxhal/src/platform/aarch64_common/pl011.rs index 2ce048ac8..577371850 100644 --- a/modules/ruxhal/src/platform/aarch64_common/pl011.rs +++ b/modules/ruxhal/src/platform/aarch64_common/pl011.rs @@ -24,6 +24,7 @@ struct RxRingBuffer { buffer: [u8; BUFFER_SIZE], head: usize, tail: usize, + empty: bool, } #[cfg(feature = "irq")] @@ -33,22 +34,27 @@ impl RxRingBuffer { buffer: [0_u8; BUFFER_SIZE], head: 0_usize, tail: 0_usize, + empty: true, } } fn push(&mut self, n: u8) { - if self.tail != self.head { + if self.tail != self.head || self.empty { self.buffer[self.tail] = n; self.tail = (self.tail + 1) % BUFFER_SIZE; + self.empty = false; } } fn pop(&mut self) -> Option { - if self.head == self.tail { + if self.empty { None } else { let ret = self.buffer[self.head]; - self.head += (self.head + 1) % BUFFER_SIZE; + self.head = (self.head + 1) % BUFFER_SIZE; + if self.head == self.tail { + self.empty = true; + } Some(ret) } } @@ -98,18 +104,19 @@ pub fn init_early() { pub fn init() { #[cfg(feature = "irq")] { - crate::irq::register_handler(crate::platform::irq::UART_IRQ_NUM, handle); + crate::irq::register_handler(crate::platform::irq::UART_IRQ_NUM, irq_handler); crate::irq::set_enable(crate::platform::irq::UART_IRQ_NUM, true); } } /// UART IRQ Handler #[cfg(feature = "irq")] -pub fn handle() { - let is_receive_interrupt = UART.inner.lock().is_receive_interrupt(); +pub fn irq_handler() { + let mut dev = UART.inner.lock(); + let is_receive_interrupt = dev.is_receive_interrupt(); if is_receive_interrupt { - UART.inner.lock().ack_interrupts(); - while let Some(c) = UART.inner.lock().getchar() { + dev.ack_interrupts(); + while let Some(c) = dev.getchar() { UART.buffer.lock().push(c); } } From 4aaffd14ed66cad0f18c0d001b6beca8c794ca27 Mon Sep 17 00:00:00 2001 From: wuzheng Date: Wed, 27 Mar 2024 21:08:27 +0800 Subject: [PATCH 04/13] Implement logic to open symlink in 9pfs --- modules/rux9p/src/fs.rs | 54 ++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/modules/rux9p/src/fs.rs b/modules/rux9p/src/fs.rs index 72843870e..2cc87c4b4 100644 --- a/modules/rux9p/src/fs.rs +++ b/modules/rux9p/src/fs.rs @@ -121,6 +121,7 @@ impl CommonNode { const O_RDWR: u8 = 0x02; const O_RDONLY: u8 = 0x00; const EISDIR: u8 = 21; + const ELOOP: u8 = 40; let result = if *protocol == "9P2000.L" { dev.write().l_topen(fid, O_RDWR as u32) @@ -131,23 +132,36 @@ impl CommonNode { Ok(()) }; - if let Err(EISDIR) = result { - if *protocol == "9P2000.L" { - handle_result!( - dev.write().l_topen(fid, O_RDONLY as u32), - "9pfs l_topen failed! error code: {}" - ); - } else if *protocol == "9P2000.u" { - handle_result!( - dev.write().topen(fid, O_RDONLY), - "9pfs topen failed! error code: {}" - ); - } else { - error!("9pfs open failed! Unsupported protocol version"); + match result { + Err(EISDIR) if *protocol == "9P2000.L" => handle_result!( + dev.write().l_topen(fid, O_RDONLY as u32), + "9pfs l_topen failed! error code: {}" + ), + Err(EISDIR) if *protocol == "9P2000.u" => handle_result!( + dev.write().topen(fid, O_RDONLY), + "9pfs topen failed! error code: {}" + ), + Err(ELOOP) if *protocol == "9P2000.L" => { + let try_readlink = dev.write().treadlink(fid); + if let Ok(path) = try_readlink { + debug!("read link path ==> {:}", path); + let mut splited: Vec<&str> = path + .split('/') + .filter(|&x| !x.is_empty() && (x != ".")) + .collect(); + splited.insert(0, ".."); + let try_walk = dev.write().twalk(fid, fid, splited.len() as u16, &splited); + match try_walk { + Ok(_) => return Self::new(fid, parent, dev, protocol), + Err(ecode) => error!("9pfs twalk failed! error code: {}", ecode), + } + } else { + error!("9pfs treadlink failed! error code: {:?}", try_readlink); + } } - } else if let Err(ecode) = result { - error!("9pfs topen failed! error code: {}", ecode); - } + Err(ecode) => error!("9pfs topen failed! error code: {}", ecode), + _ => {} + }; Arc::new_cyclic(|this| Self { inner: dev, @@ -224,7 +238,13 @@ impl CommonNode { fn try_get(&self, path: &str) -> VfsResult { let (name, rest) = split_path(path); if name == ".." { - return self.parent().unwrap().lookup(rest.unwrap_or("")); + match self.parent() { + Some(parent) => return parent.lookup(rest.unwrap_or("")), + None => { + error!("9pfs: try_get a directory out of 9pfs boundary"); + return Err(VfsError::BadState); + } + } } else if name == "." { return self.try_get(rest.unwrap_or("")); } From 20da344d19ba8b43ac287306a29a6f0f8b7a5ad9 Mon Sep 17 00:00:00 2001 From: thesayol Date: Sun, 31 Mar 2024 20:21:03 +0800 Subject: [PATCH 05/13] add some syscalls for x86_64 and aarch64. --- api/ruxos_posix_api/Cargo.toml | 2 +- api/ruxos_posix_api/src/imp/cap.rs | 42 +++++ api/ruxos_posix_api/src/imp/execve/auxv.rs | 41 +++++ .../src/imp/execve/load_elf.rs | 120 ++++++++++++++ api/ruxos_posix_api/src/imp/execve/mod.rs | 153 ++++++++++++++++++ api/ruxos_posix_api/src/imp/execve/stack.rs | 55 +++++++ api/ruxos_posix_api/src/imp/fs.rs | 44 ++++- api/ruxos_posix_api/src/imp/io_mpx/poll.rs | 8 +- api/ruxos_posix_api/src/imp/mmap.rs | 32 +++- api/ruxos_posix_api/src/imp/mod.rs | 3 + api/ruxos_posix_api/src/imp/rt_sig.rs | 64 +++++++- api/ruxos_posix_api/src/imp/signal.rs | 8 +- api/ruxos_posix_api/src/imp/stat.rs | 37 ++++- api/ruxos_posix_api/src/imp/task.rs | 14 +- api/ruxos_posix_api/src/imp/time.rs | 5 + api/ruxos_posix_api/src/lib.rs | 24 ++- apps/c/envtest/expect_info.out | 2 +- apps/c/filetest/expect_info.out | 2 +- apps/c/helloworld/expect_info.out | 2 +- apps/c/helloworld/expect_info_smp4.out | 2 +- apps/c/httpclient/expect_info.out | 2 +- apps/c/memtest/expect_trace.out | 2 +- .../c/pthread/basic/expect_info_smp4_fifo.out | 2 +- .../parallel/expect_info_smp4_fifo.out | 2 +- .../pthread/parallel/expect_info_smp4_rr.out | 2 +- apps/c/pthread/pipe/expect_info_smp4_fifo.out | 2 +- .../c/pthread/sleep/expect_info_smp4_fifo.out | 2 +- apps/c/pthread/sleep/main.c | 5 +- apps/c/sqlite3/expect_info.out | 2 +- apps/c/sqlite3/expect_info_again.out | 2 +- apps/c/sqlite3/expect_info_ramdisk.out | 2 +- modules/ruxhal/src/mem.rs | 5 +- ulib/ruxlibc/src/unistd.rs | 8 +- ulib/ruxmusl/src/aarch64/mod.rs | 32 +++- ulib/ruxmusl/src/aarch64/syscall_id.rs | 18 +++ ulib/ruxmusl/src/x86_64/mod.rs | 43 ++++- ulib/ruxmusl/src/x86_64/syscall_id.rs | 31 ++++ 37 files changed, 772 insertions(+), 50 deletions(-) create mode 100644 api/ruxos_posix_api/src/imp/cap.rs create mode 100644 api/ruxos_posix_api/src/imp/execve/auxv.rs create mode 100644 api/ruxos_posix_api/src/imp/execve/load_elf.rs create mode 100644 api/ruxos_posix_api/src/imp/execve/mod.rs create mode 100644 api/ruxos_posix_api/src/imp/execve/stack.rs diff --git a/api/ruxos_posix_api/Cargo.toml b/api/ruxos_posix_api/Cargo.toml index 4d4dda594..1f9f1b60c 100644 --- a/api/ruxos_posix_api/Cargo.toml +++ b/api/ruxos_posix_api/Cargo.toml @@ -56,7 +56,7 @@ static_assertions = "1.1.0" spin = { version = "0.9" } lazy_static = { version = "1.4", features = ["spin_no_std"] } flatten_objects = { path = "../../crates/flatten_objects" } - +elf = { version = "0.7", default-features = false } bitflags = "2.2" [build-dependencies] diff --git a/api/ruxos_posix_api/src/imp/cap.rs b/api/ruxos_posix_api/src/imp/cap.rs new file mode 100644 index 000000000..4e4d28697 --- /dev/null +++ b/api/ruxos_posix_api/src/imp/cap.rs @@ -0,0 +1,42 @@ +use core::ffi::c_int; + +#[derive(Debug, Clone, Copy)] +struct UserCapHeader { + /// Linux Cap Version: + /// Version1 = 0x19980330, + /// Version2 = 0x20071026, + /// Version3 = 0x20080522, + version: u32, + pid: i32, +} + +/// The effective, permitted, and inheritable fields are bit masks of the capabilities. +/// Note that the CAP_* values are bit indexes and need to be bit-shifted before ORing into the bit fields. +#[derive(Debug, Clone, Copy)] +struct UserCapData { + effective: u32, + permitted: u32, + inheritable: u32, +} + +/// get thread capabilities. specific to Linux. +pub fn sys_cap_get(cap_user_header: usize, cap_user_data: usize) -> c_int { + let hdrp = cap_user_header as *const UserCapHeader; + let datap = cap_user_data as *mut UserCapData; + unsafe { + debug!( + "sys_cap_get <= pid {:?}, version {:x?} ", + (*hdrp).pid, + (*hdrp).version + ); + } + syscall_body!(sys_cap_get, { + unsafe { + // allow all + (*datap).effective = u32::MAX; + (*datap).inheritable = u32::MAX; + (*datap).permitted = u32::MAX; + }; + Ok(0) + }) +} diff --git a/api/ruxos_posix_api/src/imp/execve/auxv.rs b/api/ruxos_posix_api/src/imp/execve/auxv.rs new file mode 100644 index 000000000..169bed630 --- /dev/null +++ b/api/ruxos_posix_api/src/imp/execve/auxv.rs @@ -0,0 +1,41 @@ +#![allow(unused)] + +pub const AT_NULL: usize = 0; +pub const AT_IGNORE: usize = 1; + +pub const AT_EXECFD: usize = 2; + +/// The address of the program headers of the executable. +pub const AT_PHDR: usize = 3; + +pub const AT_PHENT: usize = 4; +pub const AT_PHNUM: usize = 5; +pub const AT_PAGESZ: usize = 6; + +/// The base address of the program interpreter (usually, the dynamic linker). +pub const AT_BASE: usize = 7; + +pub const AT_FLAGS: usize = 8; +pub const AT_ENTRY: usize = 9; +pub const AT_NOTELF: usize = 10; +pub const AT_UID: usize = 11; +pub const AT_EUID: usize = 12; +pub const AT_GID: usize = 13; +pub const AT_EGID: usize = 14; +pub const AT_PLATFORM: usize = 15; +pub const AT_HWCAP: usize = 16; +pub const AT_CLKTCK: usize = 17; +pub const AT_DCACHEBSIZE: usize = 19; +pub const AT_ICACHEBSIZE: usize = 20; +pub const AT_UCACHEBSIZE: usize = 21; +pub const AT_SECURE: usize = 23; +pub const AT_RANDOM: usize = 25; + +/// A pointer to a string containing the pathname used to execute the program. +pub const AT_EXECFN: usize = 31; + +/// The address of a page containing the vDSO that the kernel creates +pub const AT_SYSINFO_EHDR: usize = 33; + +/// The entry point to the system call function in the vDSO. Not present/needed on all architectures (e.g., absent on x86-64). +pub const AT_SYSINFO: usize = 32; diff --git a/api/ruxos_posix_api/src/imp/execve/load_elf.rs b/api/ruxos_posix_api/src/imp/execve/load_elf.rs new file mode 100644 index 000000000..e8730cf39 --- /dev/null +++ b/api/ruxos_posix_api/src/imp/execve/load_elf.rs @@ -0,0 +1,120 @@ +use crate::{ctypes::kstat, utils::char_ptr_to_str, *}; +use alloc::{vec, vec::Vec}; +use core::{ + ffi::c_char, + ptr::{null, null_mut}, +}; + +#[derive(Debug)] +pub struct ElfProg { + pub name: Vec, + pub path: Vec, + pub platform: Vec, + pub rand: Vec, + pub base: usize, + pub entry: usize, + pub interp_path: *const c_char, + pub phent: usize, + pub phnum: usize, + pub phdr: usize, +} + +impl ElfProg { + /// read elf from `path`, and copy LOAD segments to a alloacated memory + /// + /// and load interp, if needed. + pub fn new(filepath: *const c_char) -> Self { + let name = char_ptr_to_str(filepath).unwrap().as_bytes().to_vec(); + let path = name.clone(); + debug!("sys_execve: new elf prog: {:?}", char_ptr_to_str(filepath)); + + // open file + let fd = sys_open(filepath, ctypes::O_RDWR as i32, 0); + + // get file size + let mut buf = ctypes::kstat { + ..Default::default() + }; + sys_fstat(fd, &mut buf as *const kstat as *mut _); + let filesize = buf.st_size as usize; + + // read file + let mut file = vec![0u8; filesize]; + sys_read(fd, file.as_mut_ptr() as *mut _, filesize); + debug!("sys_execve: read file size 0x{filesize:x}"); + sys_close(fd); + + // parse elf + let file = elf::ElfBytes::::minimal_parse(&file) + .expect("parse ELF failed"); + + // get program's LOAD mem size + let mut msize = 0; + let segs = file.segments().unwrap(); + for seg in segs { + if seg.p_type == elf::abi::PT_LOAD { + msize += seg.p_memsz; + } + } + + // copy LOAD segments + let base = crate::sys_mmap(null_mut(), msize as usize, 0, 0, 0, 0) as usize; + for seg in segs { + if seg.p_type == elf::abi::PT_LOAD { + let data = file.segment_data(&seg).unwrap(); + let dst = (seg.p_vaddr as usize + base) as *mut u8; + unsafe { dst.copy_from_nonoverlapping(data.as_ptr(), data.len()) }; + } + } + + // phdr + let phdr = base + file.ehdr.e_phoff as usize; + + // get entry + let entry = file.ehdr.e_entry as usize + base; + + // parse interpreter + let mut interp_path = null::(); + for seg in file.segments().unwrap() { + if seg.p_type == elf::abi::PT_INTERP { + let data = file.segment_data(&seg).unwrap(); + interp_path = data.as_ptr() as *const c_char; + break; + } + } + + // platform + #[cfg(target_arch = "aarch64")] + let platform = b"aarch64".to_vec(); + #[cfg(target_arch = "x86_64")] + let platform = b"x86_64".to_vec(); + #[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))] + let platform = b"unknown".to_vec(); + + // get address of .text for debugging + let text_section_addr = base + + file + .section_header_by_name(".text") + .unwrap() + .unwrap() + .sh_offset as usize; + debug!( + "sys_execve: loaded ELF in 0x{:x}, .text is 0x{:x}", + base, text_section_addr + ); + + // create retval + Self { + base, + entry, + name, + path, + platform, + rand: alloc::vec![1, 2], + interp_path, + phent: file.ehdr.e_phentsize as usize, + phnum: file.ehdr.e_phnum as usize, + phdr, + } + } +} diff --git a/api/ruxos_posix_api/src/imp/execve/mod.rs b/api/ruxos_posix_api/src/imp/execve/mod.rs new file mode 100644 index 000000000..93886d94a --- /dev/null +++ b/api/ruxos_posix_api/src/imp/execve/mod.rs @@ -0,0 +1,153 @@ +use core::ffi::c_char; + +mod auxv; +mod load_elf; +mod stack; + +use alloc::vec; + +use crate::{ + imp::stat::{sys_getgid, sys_getuid}, + sys_getegid, sys_geteuid, +}; + +/// int execve(const char *pathname, char *const argv[], char *const envp[] ); +pub fn sys_execve(pathname: *const c_char, argv: usize, envp: usize) -> ! { + use auxv::*; + + let prog = load_elf::ElfProg::new(pathname); + + // get entry + let mut entry = prog.entry; + + // if interp is needed + let mut at_base = 0; + if !prog.interp_path.is_null() { + let interp_prog = load_elf::ElfProg::new(prog.interp_path); + entry = interp_prog.entry; + at_base = interp_prog.base; + debug!("sys_execve: INTERP base is {:x}", at_base); + }; + + // create stack + let mut stack = stack::Stack::new(); + + let name = prog.name; + let platform = prog.platform; + + // non 8B info + stack.push(vec![0u8; 32], 16); + let p_progname = stack.push(name, 16); + let _p_plat = stack.push(platform, 16); // platform + let p_rand = stack.push(prog.rand, 16); // rand + + // auxv + // TODO: vdso and rand + // TODO: a way to get pagesz instead of a constant + let auxv = vec![ + AT_PHDR, + prog.phdr, + AT_PHNUM, + prog.phnum, + AT_PHENT, + prog.phent, + AT_BASE, + at_base, + AT_PAGESZ, + 0x1000, + AT_HWCAP, + 0, + AT_CLKTCK, + 100, + AT_FLAGS, + 0, + AT_ENTRY, + prog.entry, + AT_UID, + sys_getuid() as usize, + AT_EUID, + sys_geteuid() as usize, + AT_EGID, + sys_getegid() as usize, + AT_GID, + sys_getgid() as usize, + AT_SECURE, + 0, + AT_EXECFN, + p_progname, + AT_RANDOM, + p_rand, + AT_SYSINFO_EHDR, + 0, + AT_IGNORE, + 0, + AT_NULL, + 0, + ]; + + // handle envs and args + let mut env_vec = vec![]; + let mut arg_vec = vec![]; + let mut argc = 0; + + let envp = envp as *const usize; + unsafe { + let mut i = 0; + while *envp.add(i) != 0 { + env_vec.push(*envp.add(i)); + i += 1; + } + env_vec.push(0); + } + + let argv = argv as *const usize; + unsafe { + let mut i = 0; + loop { + let p = *argv.add(i); + if p == 0 { + break; + } + arg_vec.push(p); + argc += 1; + i += 1; + } + + arg_vec.push(0); + } + + // push + stack.push(auxv, 16); + stack.push(env_vec, 8); + stack.push(arg_vec, 8); + let _sp = stack.push(vec![argc as usize], 8); + + // try run + debug!( + "sys_execve: run at entry 0x{entry:x}, then it will jump to 0x{:x} ", + prog.entry + ); + + #[cfg(target_arch = "aarch64")] + unsafe { + core::arch::asm!(" + mov sp, {} + blr {} + ", + in(reg)_sp, + in(reg)entry, + ); + } + #[cfg(target_arch = "x86_64")] + unsafe { + core::arch::asm!(" + mov rsp, {} + jmp {} + ", + in(reg)_sp, + in(reg)entry, + ); + } + + unreachable!("sys_execve: unknown arch"); +} diff --git a/api/ruxos_posix_api/src/imp/execve/stack.rs b/api/ruxos_posix_api/src/imp/execve/stack.rs new file mode 100644 index 000000000..a741263e7 --- /dev/null +++ b/api/ruxos_posix_api/src/imp/execve/stack.rs @@ -0,0 +1,55 @@ +use core::{mem::size_of, ptr::null_mut}; + +use crate::*; + +#[derive(Debug)] +pub struct Stack { + sp: usize, + start: usize, + end: usize, +} + +impl Stack { + // alloc a stack + pub fn new() -> Self { + let size = 0xa00000; // 10M + let p = sys_mmap(null_mut(), size, 0, 0, 0, 0); + + let start = p as usize; + let sp = start + size; + let end = sp; + + Self { sp, start, end } + } + + pub fn align(&mut self, align: usize) -> usize { + self.sp -= self.sp % align; + self.sp + } + + pub fn push(&mut self, thing: alloc::vec::Vec, align: usize) -> usize { + let size = thing.len() * size_of::(); + self.sp -= size; + self.sp = self.align(align); // align 16B + + if self.sp < self.start { + panic!("stack overflow"); + } + + let mut pt = self.sp as *mut T; + unsafe { + for t in thing { + *pt = t; + pt = pt.add(1); + } + } + + self.sp + } +} + +impl Drop for Stack { + fn drop(&mut self) { + sys_munmap(self.start as *mut _, self.end - self.start); + } +} diff --git a/api/ruxos_posix_api/src/imp/fs.rs b/api/ruxos_posix_api/src/imp/fs.rs index 65a539467..cb70b1004 100644 --- a/api/ruxos_posix_api/src/imp/fs.rs +++ b/api/ruxos_posix_api/src/imp/fs.rs @@ -13,7 +13,10 @@ use core::ffi::{c_char, c_int, c_long, c_void}; use axerrno::{LinuxError, LinuxResult}; use axio::{PollState, SeekFrom}; use axsync::Mutex; -use ruxfs::fops::{DirEntry, OpenOptions}; +use ruxfs::{ + api::set_current_dir, + fops::{DirEntry, OpenOptions}, +}; use super::fd_ops::{get_file_like, FileLike}; use crate::{ctypes, utils::char_ptr_to_str}; @@ -56,8 +59,14 @@ impl FileLike for File { let ty = metadata.file_type() as u8; let perm = metadata.perm().bits() as u32; let st_mode = ((ty as u32) << 12) | perm; + + // Inode of files, for musl dynamic linker. + // WARN: there will be collision for files with the same size. + // TODO: implement real inode. + let st_ino = metadata.size() + st_mode as u64; + Ok(ctypes::stat { - st_ino: 1, + st_ino, st_nlink: 1, st_mode, st_uid: 1000, @@ -298,7 +307,7 @@ pub unsafe fn sys_stat(path: *const c_char, buf: *mut core::ffi::c_void) -> c_in } /// retrieve information about the file pointed by `fd` -pub unsafe fn sys_fstat(fd: c_int, kst: *mut core::ffi::c_void) -> c_int { +pub fn sys_fstat(fd: c_int, kst: *mut core::ffi::c_void) -> c_int { debug!("sys_fstat <= {} {:#x}", fd, kst as usize); syscall_body!(sys_fstat, { if kst.is_null() { @@ -364,7 +373,6 @@ pub unsafe fn sys_newfstatat( "sys_newfstatat <= fd: {}, path: {:?}, flag: {:x}", _fd, path, flag ); - assert_eq!(_fd, ctypes::AT_FDCWD as c_int); syscall_body!(sys_newfstatat, { if kst.is_null() { return Err(LinuxError::EFAULT); @@ -648,3 +656,31 @@ pub unsafe fn sys_preadv( Ok(ret) }) } + +/// checks accessibility to the file `pathname`. +/// If pathname is a symbolic link, it is dereferenced. +/// The mode is either the value F_OK, for the existence of the file, +/// or a mask consisting of the bitwise OR of one or more of R_OK, W_OK, and X_OK, for the read, write, execute permissions. +pub fn sys_faccessat(dirfd: c_int, pathname: *const c_char, mode: c_int, flags: c_int) -> c_int { + let path = char_ptr_to_str(pathname).unwrap(); + debug!( + "sys_faccessat <= dirfd {} path {} mode {} flags {}", + dirfd, path, mode, flags + ); + syscall_body!(sys_faccessat, { + let mut options = OpenOptions::new(); + options.read(true); + let _file = ruxfs::fops::File::open(path, &options)?; + Ok(0) + }) +} + +/// changes the current working directory to the directory specified in path. +pub fn sys_chdir(path: *const c_char) -> c_int { + let p = char_ptr_to_str(path).unwrap(); + debug!("sys_chdir <= path: {}", p); + syscall_body!(sys_chdir, { + set_current_dir(p)?; + Ok(0) + }) +} diff --git a/api/ruxos_posix_api/src/imp/io_mpx/poll.rs b/api/ruxos_posix_api/src/imp/io_mpx/poll.rs index 56bb41c56..2daad9428 100644 --- a/api/ruxos_posix_api/src/imp/io_mpx/poll.rs +++ b/api/ruxos_posix_api/src/imp/io_mpx/poll.rs @@ -49,8 +49,12 @@ pub unsafe fn sys_ppoll( _sig_mask: *const ctypes::sigset_t, _sig_num: ctypes::size_t, ) -> c_int { - debug!("sys_ppoll <= nfds: {} timeout: {:?}", nfds, *timeout); - let to = Duration::from(*timeout).as_millis() as c_int; + let to = if timeout.is_null() { + -1 + } else { + Duration::from(*timeout).as_millis() as c_int + }; + debug!("sys_ppoll <= nfds: {} timeout: {:?}", nfds, to); sys_poll(fds, nfds, to) } diff --git a/api/ruxos_posix_api/src/imp/mmap.rs b/api/ruxos_posix_api/src/imp/mmap.rs index b706b21ca..43edd5b0f 100644 --- a/api/ruxos_posix_api/src/imp/mmap.rs +++ b/api/ruxos_posix_api/src/imp/mmap.rs @@ -20,27 +20,45 @@ use axerrno::LinuxError; /// ing process. /// /// TODO: Only support `start` equals to NULL, ignore fd, prot, flags +/// add something for musl interpreter, need improvement. pub fn sys_mmap( start: *mut c_void, len: ctypes::size_t, _prot: c_int, _flags: c_int, - _fd: c_int, + fd: c_int, _off: ctypes::off_t, ) -> *mut c_void { - debug!("sys_mmap <= start: {:p}, len: {}, fd: {}", start, len, _fd); + debug!("sys_mmap <= start: {:p}, len: {}, fd: {}", start, len, fd); syscall_body!(sys_mmap, { - if !start.is_null() { - debug!("Do not support explicitly specifying start addr"); - return Ok(core::ptr::null_mut()); + #[cfg(feature = "fs")] + if !start.is_null() && fd > 0 { + let ptr = start; + use crate::imp::fd_ops::get_file_like; + let dst = unsafe { core::slice::from_raw_parts_mut(ptr as *mut u8, len) }; + crate::sys_lseek(fd, _off, 0); + get_file_like(fd)?.read(dst)?; + return Ok(ptr); } + let layout = Layout::from_size_align(len, 8).unwrap(); - unsafe { + + let ptr = unsafe { let ptr = alloc(layout).cast::(); (ptr as *mut u8).write_bytes(0, len); assert!(!ptr.is_null(), "sys_mmap failed"); - Ok(ptr) + ptr + }; + + #[cfg(feature = "fs")] + if fd > 0 { + use crate::imp::fd_ops::get_file_like; + let dst = unsafe { core::slice::from_raw_parts_mut(ptr as *mut u8, len) }; + crate::sys_lseek(fd, _off, 0); + get_file_like(fd)?.read(dst)?; } + + Ok(ptr) }) } diff --git a/api/ruxos_posix_api/src/imp/mod.rs b/api/ruxos_posix_api/src/imp/mod.rs index 0198abf50..7b7880d35 100644 --- a/api/ruxos_posix_api/src/imp/mod.rs +++ b/api/ruxos_posix_api/src/imp/mod.rs @@ -9,6 +9,7 @@ mod stdio; +pub mod cap; pub mod getrandom; pub mod io; pub mod prctl; @@ -19,6 +20,8 @@ pub mod sys; pub mod task; pub mod time; +#[cfg(feature = "fs")] +pub mod execve; #[cfg(feature = "fd")] pub mod fd_ops; #[cfg(feature = "fs")] diff --git a/api/ruxos_posix_api/src/imp/rt_sig.rs b/api/ruxos_posix_api/src/imp/rt_sig.rs index e26066679..aa7a4ba7f 100644 --- a/api/ruxos_posix_api/src/imp/rt_sig.rs +++ b/api/ruxos_posix_api/src/imp/rt_sig.rs @@ -9,22 +9,78 @@ //! Signal implementation, used by musl -use core::ffi::c_int; +use axerrno::LinuxError; use crate::ctypes; +use core::{ + ffi::c_int, + sync::atomic::{AtomicUsize, Ordering}, +}; + +enum RTSigprocmaskHow { + Block = 0, + UnBlock = 1, + SetMask = 2, +} + +impl TryFrom for RTSigprocmaskHow { + type Error = (); + fn try_from(value: c_int) -> Result { + match value { + x if x == Self::Block as c_int => Ok(Self::Block), + x if x == Self::UnBlock as c_int => Ok(Self::UnBlock), + x if x == Self::SetMask as c_int => Ok(Self::SetMask), + _ => Err(()), + } + } +} + +static mut MASK_TMP: AtomicUsize = AtomicUsize::new(0); + +fn set_mask(old: *mut usize, new: usize) { + unsafe { + *old = new; + } +} + +fn get_mask(mask: *const usize) -> usize { + unsafe { *mask } +} /// Set mask for given thread pub fn sys_rt_sigprocmask( - flag: c_int, + how: c_int, _new_mask: *const usize, _old_mask: *mut usize, sigsetsize: usize, ) -> c_int { debug!( "sys_rt_sigprocmask <= flag: {}, sigsetsize: {}", - flag, sigsetsize + how, sigsetsize ); - syscall_body!(sys_rt_sigprocmask, Ok(0)) + + syscall_body!(sys_rt_sigprocmask, { + if !_old_mask.is_null() { + unsafe { + let new = MASK_TMP.load(Ordering::Relaxed); + set_mask(_old_mask, new); + } + } + + if !_new_mask.is_null() { + unsafe { + let set = get_mask(_new_mask); + match how.try_into() { + Ok(RTSigprocmaskHow::Block) => MASK_TMP.fetch_or(set, Ordering::Relaxed), + Ok(RTSigprocmaskHow::UnBlock) => MASK_TMP.fetch_and(!set, Ordering::Relaxed), + Ok(RTSigprocmaskHow::SetMask) => MASK_TMP.swap(set, Ordering::Relaxed), + _ => return Err(LinuxError::EINVAL), + }; + } + } + + Ok(0) + }) } /// sigaction syscall for A64 musl diff --git a/api/ruxos_posix_api/src/imp/signal.rs b/api/ruxos_posix_api/src/imp/signal.rs index 6def81518..971408dc1 100644 --- a/api/ruxos_posix_api/src/imp/signal.rs +++ b/api/ruxos_posix_api/src/imp/signal.rs @@ -10,8 +10,8 @@ use core::ffi::c_int; use core::time::Duration; -use crate::ctypes; use crate::ctypes::k_sigaction; +use crate::ctypes::{self, pid_t}; use axerrno::LinuxError; use ruxruntime::{rx_sigaction, Signal}; @@ -85,3 +85,9 @@ pub unsafe fn sys_sigaltstack( debug!("sys_sigaltstack <= ss: {:p}, old_ss: {:p}", _ss, _old_ss); syscall_body!(sys_sigaltstack, Ok(0)) } + +/// TODO: send a signal to a process +pub unsafe fn sys_kill(pid: pid_t, sig: c_int) -> c_int { + debug!("sys_kill <= pid {} sig {}", pid, sig); + syscall_body!(sys_kill, Ok(0)) +} diff --git a/api/ruxos_posix_api/src/imp/stat.rs b/api/ruxos_posix_api/src/imp/stat.rs index 3f65ec009..ecb25edf2 100644 --- a/api/ruxos_posix_api/src/imp/stat.rs +++ b/api/ruxos_posix_api/src/imp/stat.rs @@ -7,7 +7,8 @@ * See the Mulan PSL v2 for more details. */ -use crate::ctypes; +use crate::ctypes::{self, gid_t, pid_t, uid_t}; +use core::ffi::c_int; /// Set file mode creation mask /// @@ -26,3 +27,37 @@ pub fn sys_geteuid() -> core::ffi::c_uint { pub fn sys_getegid() -> core::ffi::c_uint { syscall_body!(sys_getegid, Ok(1000)) } + +/// Get current real user ID. +pub fn sys_getuid() -> c_int { + syscall_body!(sys_getuid, Ok(1000)) +} + +/// Get current real group ID. +pub fn sys_getgid() -> c_int { + syscall_body!(sys_getgid, Ok(1000)) +} + +/// set current user id +pub fn sys_setuid(uid: uid_t) -> c_int { + debug!("sys_setuid: uid {}", uid); + syscall_body!(sys_setuid, Ok(0)) +} + +/// set current group id +pub fn sys_setgid(gid: gid_t) -> c_int { + debug!("sys_setgid: gid {}", gid); + syscall_body!(sys_setgid, Ok(0)) +} + +/// get process gid +pub fn sys_getpgid(pid: pid_t) -> c_int { + debug!("sys_getpgid: getting pgid of pid {} ", pid); + syscall_body!(sys_getpgid, Ok(1000)) +} + +/// set process gid +pub fn sys_setpgid(pid: pid_t, pgid: pid_t) -> c_int { + debug!("sys_setpgid: pid {}, pgid {} ", pid, pgid); + syscall_body!(sys_setpgid, Ok(0)) +} diff --git a/api/ruxos_posix_api/src/imp/task.rs b/api/ruxos_posix_api/src/imp/task.rs index 4c295f86a..2ad8ff009 100644 --- a/api/ruxos_posix_api/src/imp/task.rs +++ b/api/ruxos_posix_api/src/imp/task.rs @@ -26,8 +26,8 @@ pub fn sys_sched_yield() -> c_int { } /// Get current thread ID. -pub fn sys_getpid() -> c_int { - syscall_body!(sys_getpid, +pub fn sys_gettid() -> c_int { + syscall_body!(sys_gettid, #[cfg(feature = "multitask")] { Ok(ruxtask::current().id().as_u64() as c_int) @@ -39,6 +39,16 @@ pub fn sys_getpid() -> c_int { ) } +/// Get current process ID. +pub fn sys_getpid() -> c_int { + syscall_body!(sys_getpid, Ok(2)) +} + +/// Get parent process's ID. +pub fn sys_getppid() -> c_int { + syscall_body!(sys_getppid, Ok(1)) +} + /// Exit current task pub fn sys_exit(exit_code: c_int) -> ! { debug!("sys_exit <= {}", exit_code); diff --git a/api/ruxos_posix_api/src/imp/time.rs b/api/ruxos_posix_api/src/imp/time.rs index 271087baa..2fa61c80e 100644 --- a/api/ruxos_posix_api/src/imp/time.rs +++ b/api/ruxos_posix_api/src/imp/time.rs @@ -115,3 +115,8 @@ pub unsafe fn sys_gettimeofday(ts: *mut ctypes::timespec, flags: c_int) -> c_int debug!("sys_gettimeofday <= flags: {}", flags); unsafe { sys_clock_gettime(0, ts) } } + +/// TODO: get process and waited-for child process times +pub unsafe fn sys_times(_buf: *mut usize) -> c_int { + syscall_body!(sys_times, Ok(0)) +} diff --git a/api/ruxos_posix_api/src/lib.rs b/api/ruxos_posix_api/src/lib.rs index 6cac87f24..b3854200e 100644 --- a/api/ruxos_posix_api/src/lib.rs +++ b/api/ruxos_posix_api/src/lib.rs @@ -45,16 +45,22 @@ pub mod config { #[allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals, clippy::upper_case_acronyms, missing_docs)] pub mod ctypes; +pub use imp::cap::sys_cap_get; pub use imp::getrandom::{sys_getrandom, sys_rand, sys_random, sys_srand}; pub use imp::io::{sys_read, sys_readv, sys_write, sys_writev}; pub use imp::prctl::{sys_arch_prctl, sys_prctl}; pub use imp::resources::{sys_getrlimit, sys_prlimit64, sys_setrlimit}; pub use imp::rt_sig::{sys_rt_sigaction, sys_rt_sigprocmask}; -pub use imp::stat::{sys_getegid, sys_geteuid, sys_umask}; +pub use imp::stat::{ + sys_getegid, sys_geteuid, sys_getgid, sys_getpgid, sys_getuid, sys_setgid, sys_setpgid, + sys_setuid, sys_umask, +}; pub use imp::sys::{sys_sysinfo, sys_uname}; pub use imp::sys_invalid; -pub use imp::task::{sys_exit, sys_getpid, sys_sched_yield}; -pub use imp::time::{sys_clock_gettime, sys_clock_settime, sys_gettimeofday, sys_nanosleep}; +pub use imp::task::{sys_exit, sys_getpid, sys_getppid, sys_gettid, sys_sched_yield}; +pub use imp::time::{ + sys_clock_gettime, sys_clock_settime, sys_gettimeofday, sys_nanosleep, sys_times, +}; #[cfg(all(feature = "fd", feature = "musl"))] pub use imp::fd_ops::sys_dup3; @@ -62,9 +68,10 @@ pub use imp::fd_ops::sys_dup3; pub use imp::fd_ops::{sys_close, sys_dup, sys_dup2, sys_fcntl}; #[cfg(feature = "fs")] pub use imp::fs::{ - sys_fchownat, sys_fdatasync, sys_fstat, sys_fsync, sys_getcwd, sys_getdents64, sys_lseek, - sys_lstat, sys_mkdir, sys_mkdirat, sys_newfstatat, sys_open, sys_openat, sys_pread, sys_preadv, - sys_readlinkat, sys_rename, sys_renameat, sys_rmdir, sys_stat, sys_unlink, sys_unlinkat, + sys_chdir, sys_faccessat, sys_fchownat, sys_fdatasync, sys_fstat, sys_fsync, sys_getcwd, + sys_getdents64, sys_lseek, sys_lstat, sys_mkdir, sys_mkdirat, sys_newfstatat, sys_open, + sys_openat, sys_pread, sys_preadv, sys_readlinkat, sys_rename, sys_renameat, sys_rmdir, + sys_stat, sys_unlink, sys_unlinkat, }; #[cfg(feature = "epoll")] pub use imp::io_mpx::{sys_epoll_create, sys_epoll_ctl, sys_epoll_pwait, sys_epoll_wait}; @@ -100,7 +107,7 @@ pub use imp::pthread::{ sys_pthread_setspecific, }; #[cfg(feature = "signal")] -pub use imp::signal::{sys_getitimer, sys_setitimer, sys_sigaction, sys_sigaltstack}; +pub use imp::signal::{sys_getitimer, sys_kill, sys_setitimer, sys_sigaction, sys_sigaltstack}; #[cfg(feature = "multitask")] pub use imp::pthread::futex::sys_futex; @@ -114,3 +121,6 @@ pub use imp::pthread::sys_clone; pub use imp::pthread::sys_set_tid_address; #[cfg(feature = "multitask")] pub use imp::pthread::{sys_pthread_create, sys_pthread_exit, sys_pthread_join, sys_pthread_self}; + +#[cfg(feature = "fs")] +pub use imp::execve::sys_execve; diff --git a/apps/c/envtest/expect_info.out b/apps/c/envtest/expect_info.out index a6cf5d914..cd1e5927d 100644 --- a/apps/c/envtest/expect_info.out +++ b/apps/c/envtest/expect_info.out @@ -9,7 +9,7 @@ Found physcial memory regions: .data .tdata .tbss .percpu (READ | WRITE | RESERVED) boot stack (READ | WRITE | RESERVED) .bss (READ | WRITE | RESERVED) - free memory (READ | WRITE | FREE) + free memory (READ | WRITE | EXECUTE | FREE) Initialize global memory allocator... use TLSF allocator. Initialize kernel page table... diff --git a/apps/c/filetest/expect_info.out b/apps/c/filetest/expect_info.out index 0cdc8153e..f2be3bec4 100644 --- a/apps/c/filetest/expect_info.out +++ b/apps/c/filetest/expect_info.out @@ -10,7 +10,7 @@ Found physcial memory regions: .percpu (READ | WRITE | RESERVED) boot stack (READ | WRITE | RESERVED) .bss (READ | WRITE | RESERVED) - free memory (READ | WRITE | FREE) + free memory (READ | WRITE | EXECUTE | FREE) Initialize global memory allocator... Initialize kernel page table... Initialize platform devices... diff --git a/apps/c/helloworld/expect_info.out b/apps/c/helloworld/expect_info.out index 61423d90e..21795aba7 100644 --- a/apps/c/helloworld/expect_info.out +++ b/apps/c/helloworld/expect_info.out @@ -10,7 +10,7 @@ Found physcial memory regions: .percpu (READ | WRITE | RESERVED) boot stack (READ | WRITE | RESERVED) .bss (READ | WRITE | RESERVED) - free memory (READ | WRITE | FREE) + free memory (READ | WRITE | EXECUTE | FREE) Initialize platform devices... Primary CPU 0 init OK. Hello, C app! diff --git a/apps/c/helloworld/expect_info_smp4.out b/apps/c/helloworld/expect_info_smp4.out index fcf956349..f2a0e25a2 100644 --- a/apps/c/helloworld/expect_info_smp4.out +++ b/apps/c/helloworld/expect_info_smp4.out @@ -10,7 +10,7 @@ Found physcial memory regions: .percpu (READ | WRITE | RESERVED) boot stack (READ | WRITE | RESERVED) .bss (READ | WRITE | RESERVED) - free memory (READ | WRITE | FREE) + free memory (READ | WRITE | EXECUTE | FREE) Initialize platform devices... CPU 0 init OK CPU 1 started diff --git a/apps/c/httpclient/expect_info.out b/apps/c/httpclient/expect_info.out index 2e78dfb73..19688d533 100644 --- a/apps/c/httpclient/expect_info.out +++ b/apps/c/httpclient/expect_info.out @@ -10,7 +10,7 @@ Found physcial memory regions: .percpu (READ | WRITE | RESERVED) boot stack (READ | WRITE | RESERVED) .bss (READ | WRITE | RESERVED) - free memory (READ | WRITE | FREE) + free memory (READ | WRITE | EXECUTE | FREE) Initialize global memory allocator... Initialize kernel page table... Initialize platform devices... diff --git a/apps/c/memtest/expect_trace.out b/apps/c/memtest/expect_trace.out index 41dca8b3f..3bdabf61c 100644 --- a/apps/c/memtest/expect_trace.out +++ b/apps/c/memtest/expect_trace.out @@ -10,7 +10,7 @@ Found physcial memory regions: .percpu (READ | WRITE | RESERVED) boot stack (READ | WRITE | RESERVED) .bss (READ | WRITE | RESERVED) - free memory (READ | WRITE | FREE) + free memory (READ | WRITE | EXECUTE | FREE) Initialize global memory allocator... use TLSF allocator. initialize global allocator at: \[0x[0-9a-f]\+, 0x[0-9a-f]\+) diff --git a/apps/c/pthread/basic/expect_info_smp4_fifo.out b/apps/c/pthread/basic/expect_info_smp4_fifo.out index 1d7b73b73..3b75dedc8 100644 --- a/apps/c/pthread/basic/expect_info_smp4_fifo.out +++ b/apps/c/pthread/basic/expect_info_smp4_fifo.out @@ -10,7 +10,7 @@ Found physcial memory regions: .percpu (READ | WRITE | RESERVED) boot stack (READ | WRITE | RESERVED) .bss (READ | WRITE | RESERVED) - free memory (READ | WRITE | FREE) + free memory (READ | WRITE | EXECUTE | FREE) Initialize global memory allocator... Initialize kernel page table... Initialize platform devices... diff --git a/apps/c/pthread/parallel/expect_info_smp4_fifo.out b/apps/c/pthread/parallel/expect_info_smp4_fifo.out index 2861e291b..b11eb07ca 100644 --- a/apps/c/pthread/parallel/expect_info_smp4_fifo.out +++ b/apps/c/pthread/parallel/expect_info_smp4_fifo.out @@ -10,7 +10,7 @@ Found physcial memory regions: .percpu (READ | WRITE | RESERVED) boot stack (READ | WRITE | RESERVED) .bss (READ | WRITE | RESERVED) - free memory (READ | WRITE | FREE) + free memory (READ | WRITE | EXECUTE | FREE) Initialize global memory allocator... Initialize kernel page table... Initialize platform devices... diff --git a/apps/c/pthread/parallel/expect_info_smp4_rr.out b/apps/c/pthread/parallel/expect_info_smp4_rr.out index 2e016df97..12efc08ad 100644 --- a/apps/c/pthread/parallel/expect_info_smp4_rr.out +++ b/apps/c/pthread/parallel/expect_info_smp4_rr.out @@ -10,7 +10,7 @@ Found physcial memory regions: .percpu (READ | WRITE | RESERVED) boot stack (READ | WRITE | RESERVED) .bss (READ | WRITE | RESERVED) - free memory (READ | WRITE | FREE) + free memory (READ | WRITE | EXECUTE | FREE) Initialize global memory allocator... Initialize kernel page table... Initialize platform devices... diff --git a/apps/c/pthread/pipe/expect_info_smp4_fifo.out b/apps/c/pthread/pipe/expect_info_smp4_fifo.out index a1e328dd2..fefc8cc0c 100644 --- a/apps/c/pthread/pipe/expect_info_smp4_fifo.out +++ b/apps/c/pthread/pipe/expect_info_smp4_fifo.out @@ -10,7 +10,7 @@ Found physcial memory regions: .percpu (READ | WRITE | RESERVED) boot stack (READ | WRITE | RESERVED) .bss (READ | WRITE | RESERVED) - free memory (READ | WRITE | FREE) + free memory (READ | WRITE | EXECUTE | FREE) Initialize global memory allocator... Initialize kernel page table... Initialize platform devices... diff --git a/apps/c/pthread/sleep/expect_info_smp4_fifo.out b/apps/c/pthread/sleep/expect_info_smp4_fifo.out index 35227b22d..6446cd725 100644 --- a/apps/c/pthread/sleep/expect_info_smp4_fifo.out +++ b/apps/c/pthread/sleep/expect_info_smp4_fifo.out @@ -10,7 +10,7 @@ Found physcial memory regions: .percpu (READ | WRITE | RESERVED) boot stack (READ | WRITE | RESERVED) .bss (READ | WRITE | RESERVED) - free memory (READ | WRITE | FREE) + free memory (READ | WRITE | EXECUTE | FREE) Initialize global memory allocator... Initialize kernel page table... Initialize platform devices... diff --git a/apps/c/pthread/sleep/main.c b/apps/c/pthread/sleep/main.c index b1ddf8e5a..a03f33beb 100644 --- a/apps/c/pthread/sleep/main.c +++ b/apps/c/pthread/sleep/main.c @@ -7,12 +7,15 @@ * See the Mulan PSL v2 for more details. */ +#define _GNU_SOURCE #include #include #include #include #include #include +#include +#include const int NUM_TASKS = 5; @@ -42,7 +45,7 @@ void *tickfunc(void *arg) void *tickfunc2(void *arg) { - pid_t task_id = getpid(); + pid_t task_id = gettid(); char buf0[128]; char buf1[128]; diff --git a/apps/c/sqlite3/expect_info.out b/apps/c/sqlite3/expect_info.out index 66815dbf7..53dd51c3f 100644 --- a/apps/c/sqlite3/expect_info.out +++ b/apps/c/sqlite3/expect_info.out @@ -10,7 +10,7 @@ Found physcial memory regions: .percpu (READ | WRITE | RESERVED) boot stack (READ | WRITE | RESERVED) .bss (READ | WRITE | RESERVED) - free memory (READ | WRITE | FREE) + free memory (READ | WRITE | EXECUTE | FREE) Initialize global memory allocator... Initialize kernel page table... Initialize platform devices... diff --git a/apps/c/sqlite3/expect_info_again.out b/apps/c/sqlite3/expect_info_again.out index 7532d63ef..846dde836 100644 --- a/apps/c/sqlite3/expect_info_again.out +++ b/apps/c/sqlite3/expect_info_again.out @@ -10,7 +10,7 @@ Found physcial memory regions: .percpu (READ | WRITE | RESERVED) boot stack (READ | WRITE | RESERVED) .bss (READ | WRITE | RESERVED) - free memory (READ | WRITE | FREE) + free memory (READ | WRITE | EXECUTE | FREE) Initialize global memory allocator... Initialize kernel page table... Initialize platform devices... diff --git a/apps/c/sqlite3/expect_info_ramdisk.out b/apps/c/sqlite3/expect_info_ramdisk.out index 02b206367..512530daa 100644 --- a/apps/c/sqlite3/expect_info_ramdisk.out +++ b/apps/c/sqlite3/expect_info_ramdisk.out @@ -10,7 +10,7 @@ Found physcial memory regions: .percpu (READ | WRITE | RESERVED) boot stack (READ | WRITE | RESERVED) .bss (READ | WRITE | RESERVED) - free memory (READ | WRITE | FREE) + free memory (READ | WRITE | EXECUTE | FREE) Initialize global memory allocator... Initialize kernel page table... Initialize platform devices... diff --git a/modules/ruxhal/src/mem.rs b/modules/ruxhal/src/mem.rs index f98c6ad2e..4f12a108e 100644 --- a/modules/ruxhal/src/mem.rs +++ b/modules/ruxhal/src/mem.rs @@ -143,7 +143,10 @@ pub(crate) fn default_free_regions() -> impl Iterator { core::iter::once(MemRegion { paddr: start, size: end.as_usize() - start.as_usize(), - flags: MemRegionFlags::FREE | MemRegionFlags::READ | MemRegionFlags::WRITE, + flags: MemRegionFlags::FREE + | MemRegionFlags::READ + | MemRegionFlags::WRITE + | MemRegionFlags::EXECUTE, name: "free memory", }) } diff --git a/ulib/ruxlibc/src/unistd.rs b/ulib/ruxlibc/src/unistd.rs index deaf75bbe..51d53625f 100644 --- a/ulib/ruxlibc/src/unistd.rs +++ b/ulib/ruxlibc/src/unistd.rs @@ -8,7 +8,7 @@ */ use core::ffi::c_int; -use ruxos_posix_api::{sys_exit, sys_getpid}; +use ruxos_posix_api::{sys_exit, sys_getpid, sys_gettid}; #[cfg(feature = "signal")] use { crate::getitimer, @@ -23,6 +23,12 @@ pub unsafe extern "C" fn getpid() -> c_int { sys_getpid() } +/// Get current thread ID. +#[no_mangle] +pub unsafe extern "C" fn gettid() -> c_int { + sys_gettid() +} + /// Abort the current process. #[no_mangle] pub unsafe extern "C" fn abort() -> ! { diff --git a/ulib/ruxmusl/src/aarch64/mod.rs b/ulib/ruxmusl/src/aarch64/mod.rs index d6d03dee9..9fc21c937 100644 --- a/ulib/ruxmusl/src/aarch64/mod.rs +++ b/ulib/ruxmusl/src/aarch64/mod.rs @@ -1,7 +1,7 @@ pub mod syscall_id; -use core::ffi::c_int; -use ruxos_posix_api::ctypes; +use core::ffi::{c_char, c_int}; +use ruxos_posix_api::ctypes::{self, gid_t, pid_t, uid_t}; use syscall_id::SyscallId; pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { @@ -72,6 +72,15 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { args[3] as *const core::ffi::c_char, ) as _, #[cfg(feature = "fs")] + SyscallId::FACCESSAT => ruxos_posix_api::sys_faccessat( + args[0] as c_int, + args[1] as *const c_char, + args[2] as c_int, + args[3] as c_int, + ) as _, + #[cfg(feature = "fs")] + SyscallId::CHDIR => ruxos_posix_api::sys_chdir(args[0] as *const c_char) as _, + #[cfg(feature = "fs")] SyscallId::OPENAT => ruxos_posix_api::sys_openat( args[0], args[1] as *const core::ffi::c_char, @@ -172,8 +181,11 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { SyscallId::FSYNC => ruxos_posix_api::sys_fsync(args[0] as c_int) as _, SyscallId::GETEUID => ruxos_posix_api::sys_geteuid() as _, SyscallId::GETEGID => ruxos_posix_api::sys_getegid() as _, + SyscallId::GETGID => ruxos_posix_api::sys_getgid() as _, + SyscallId::GETTID => ruxos_posix_api::sys_gettid() as _, #[cfg(feature = "fs")] SyscallId::FDATASYNC => ruxos_posix_api::sys_fdatasync(args[0] as c_int) as _, + SyscallId::CAP_GET => ruxos_posix_api::sys_cap_get(args[0], args[1]) as _, #[allow(unreachable_code)] #[cfg(not(feature = "multitask"))] SyscallId::EXIT => ruxos_posix_api::sys_exit(args[0] as c_int) as _, @@ -207,6 +219,8 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { ) as _, SyscallId::SCHED_YIELD => ruxos_posix_api::sys_sched_yield() as _, #[cfg(feature = "signal")] + SyscallId::KILL => ruxos_posix_api::sys_kill(args[0] as pid_t, args[1] as c_int) as _, + #[cfg(feature = "signal")] SyscallId::SIGALTSTACK => ruxos_posix_api::sys_sigaltstack( args[0] as *const core::ffi::c_void, args[1] as *mut core::ffi::c_void, @@ -225,6 +239,13 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { args[2] as *mut usize, args[3], ) as _, + SyscallId::SETGID => ruxos_posix_api::sys_setgid(args[0] as gid_t) as _, + SyscallId::SETUID => ruxos_posix_api::sys_setuid(args[0] as uid_t) as _, + SyscallId::TIMES => ruxos_posix_api::sys_times(args[0] as *mut usize) as _, + SyscallId::SETPGID => { + ruxos_posix_api::sys_setpgid(args[0] as pid_t, args[1] as pid_t) as _ + } + SyscallId::GETPGID => ruxos_posix_api::sys_getpgid(args[0] as pid_t) as _, SyscallId::UNAME => ruxos_posix_api::sys_uname(args[0] as *mut core::ffi::c_void) as _, SyscallId::GETRLIMIT => { ruxos_posix_api::sys_getrlimit(args[0] as c_int, args[1] as *mut ctypes::rlimit) @@ -237,6 +258,8 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { SyscallId::UMASK => ruxos_posix_api::sys_umask(args[0] as ctypes::mode_t) as _, #[cfg(feature = "multitask")] SyscallId::GETPID => ruxos_posix_api::sys_getpid() as _, + SyscallId::GETPPID => ruxos_posix_api::sys_getppid() as _, + SyscallId::GETUID => ruxos_posix_api::sys_getuid() as _, SyscallId::SYSINFO => { ruxos_posix_api::sys_sysinfo(args[0] as *mut ctypes::sysinfo) as _ } @@ -336,6 +359,11 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { args[3] as *mut core::ffi::c_void, args[4] as *mut ctypes::pid_t, ) as _, + #[cfg(feature = "fs")] + #[allow(unreachable_code)] + SyscallId::EXECVE => { + ruxos_posix_api::sys_execve(args[0] as *const c_char, args[1], args[2]) as _ + } #[cfg(feature = "alloc")] SyscallId::MMAP => ruxos_posix_api::sys_mmap( args[0] as *mut core::ffi::c_void, diff --git a/ulib/ruxmusl/src/aarch64/syscall_id.rs b/ulib/ruxmusl/src/aarch64/syscall_id.rs index efbf20336..6c2b38665 100644 --- a/ulib/ruxmusl/src/aarch64/syscall_id.rs +++ b/ulib/ruxmusl/src/aarch64/syscall_id.rs @@ -30,6 +30,10 @@ pub enum SyscallId { #[cfg(feature = "fs")] RENAMEAT = 38, #[cfg(feature = "fs")] + FACCESSAT = 48, + #[cfg(feature = "fs")] + CHDIR = 49, + #[cfg(feature = "fs")] FCHOWNAT = 54, #[cfg(feature = "fs")] OPENAT = 56, @@ -65,6 +69,7 @@ pub enum SyscallId { FSYNC = 82, #[cfg(feature = "fs")] FDATASYNC = 83, + CAP_GET = 90, EXIT = 93, #[cfg(feature = "multitask")] SET_TID_ADDRESS = 96, @@ -75,19 +80,30 @@ pub enum SyscallId { CLOCK_GETTIME = 113, SCHED_YIELD = 124, #[cfg(feature = "signal")] + KILL = 129, + #[cfg(feature = "signal")] SIGALTSTACK = 132, #[cfg(feature = "signal")] RT_SIGACTION = 134, #[cfg(feature = "signal")] RT_SIGPROCMASK = 135, + SETGID = 144, + SETUID = 146, + TIMES = 153, + SETPGID = 154, + GETPGID = 155, UNAME = 160, GETRLIMIT = 163, SETRLIMIT = 164, UMASK = 166, #[cfg(feature = "multitask")] GETPID = 172, + GETPPID = 173, + GETUID = 174, GETEUID = 175, + GETGID = 176, GETEGID = 177, + GETTID = 178, SYSINFO = 179, #[cfg(feature = "net")] SOCKET = 198, @@ -119,6 +135,8 @@ pub enum SyscallId { MREMAP = 216, #[cfg(feature = "multitask")] CLONE = 220, + #[cfg(feature = "fs")] + EXECVE = 221, #[cfg(feature = "alloc")] MMAP = 222, #[cfg(feature = "alloc")] diff --git a/ulib/ruxmusl/src/x86_64/mod.rs b/ulib/ruxmusl/src/x86_64/mod.rs index 19792017a..9d5ed0089 100644 --- a/ulib/ruxmusl/src/x86_64/mod.rs +++ b/ulib/ruxmusl/src/x86_64/mod.rs @@ -1,7 +1,7 @@ pub mod syscall_id; -use core::ffi::{c_int, c_ulong, c_void}; -use ruxos_posix_api::ctypes; +use core::ffi::{c_char, c_int, c_ulong, c_void}; +use ruxos_posix_api::ctypes::{self, gid_t, pid_t, uid_t}; use syscall_id::SyscallId; pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { @@ -267,6 +267,12 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { args[5] as *mut c_void, ) as _, + #[cfg(feature = "fs")] + #[allow(unreachable_code)] + SyscallId::EXECVE => { + ruxos_posix_api::sys_execve(args[0] as *const c_char, args[1], args[2]) as _ + } + #[cfg(not(feature = "multitask"))] SyscallId::EXIT => ruxos_posix_api::sys_exit(args[0] as c_int) as _, @@ -274,6 +280,9 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { #[cfg(feature = "multitask")] SyscallId::EXIT => ruxos_posix_api::sys_pthread_exit(args[0] as *mut c_void) as _, + #[cfg(feature = "signal")] + SyscallId::KILL => ruxos_posix_api::sys_kill(args[0] as pid_t, args[1] as c_int) as _, + SyscallId::UNAME => ruxos_posix_api::sys_uname(args[0] as *mut c_void) as _, #[cfg(feature = "fd")] @@ -299,6 +308,9 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { ruxos_posix_api::sys_getcwd(args[0] as *mut core::ffi::c_char, args[1]) as _ } + #[cfg(feature = "fs")] + SyscallId::CHDIR => ruxos_posix_api::sys_chdir(args[0] as *const c_char) as _, + #[cfg(feature = "fs")] SyscallId::RENAME => ruxos_posix_api::sys_rename( args[0] as *const core::ffi::c_char, @@ -345,6 +357,22 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { ruxos_posix_api::sys_sysinfo(args[0] as *mut ctypes::sysinfo) as _ } + SyscallId::TIMES => ruxos_posix_api::sys_times(args[0] as *mut usize) as _, + + SyscallId::GETUID => ruxos_posix_api::sys_getuid() as _, + + SyscallId::GETGID => ruxos_posix_api::sys_getgid() as _, + + SyscallId::SETUID => ruxos_posix_api::sys_setuid(args[0] as uid_t) as _, + + SyscallId::SETGID => ruxos_posix_api::sys_setgid(args[0] as gid_t) as _, + + SyscallId::GETPPID => ruxos_posix_api::sys_getppid() as _, + + SyscallId::GETPGID => ruxos_posix_api::sys_getpgid(args[0] as pid_t) as _, + + SyscallId::CAPGET => ruxos_posix_api::sys_cap_get(args[0], args[1]) as _, + #[cfg(feature = "signal")] SyscallId::SIGALTSTACK => { ruxos_posix_api::sys_sigaltstack(args[0] as *const c_void, args[1] as *mut c_void) @@ -363,6 +391,9 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { ruxos_posix_api::sys_arch_prctl(args[0] as c_int, args[1] as c_ulong) as _ } + #[cfg(feature = "multitask")] + SyscallId::GETTID => ruxos_posix_api::sys_gettid() as _, + #[cfg(feature = "multitask")] SyscallId::FUTEX => ruxos_posix_api::sys_futex( args[0], @@ -458,6 +489,14 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { args[3], ) as _, + #[cfg(feature = "fs")] + SyscallId::FACCESSAT => ruxos_posix_api::sys_faccessat( + args[0] as c_int, + args[1] as *const c_char, + args[2] as c_int, + args[3] as c_int, + ) as _, + #[cfg(feature = "select")] SyscallId::PSELECT6 => ruxos_posix_api::sys_pselect6( args[0] as c_int, diff --git a/ulib/ruxmusl/src/x86_64/syscall_id.rs b/ulib/ruxmusl/src/x86_64/syscall_id.rs index 7992518ad..d0493c156 100644 --- a/ulib/ruxmusl/src/x86_64/syscall_id.rs +++ b/ulib/ruxmusl/src/x86_64/syscall_id.rs @@ -124,8 +124,14 @@ pub enum SyscallId { #[cfg(feature = "multitask")] CLONE = 56, + #[cfg(feature = "fs")] + EXECVE = 59, + EXIT = 60, + #[cfg(feature = "signal")] + KILL = 62, + UNAME = 63, #[cfg(feature = "fd")] @@ -143,6 +149,9 @@ pub enum SyscallId { #[cfg(feature = "fs")] GETCWD = 79, + #[cfg(feature = "fs")] + CHDIR = 80, + #[cfg(feature = "fs")] RENAME = 82, @@ -166,6 +175,22 @@ pub enum SyscallId { SYSINFO = 99, + TIMES = 100, + + GETUID = 102, + + GETGID = 104, + + SETUID = 105, + + SETGID = 106, + + GETPPID = 110, + + GETPGID = 121, + + CAPGET = 125, + #[cfg(feature = "signal")] SIGALTSTACK = 131, @@ -173,6 +198,9 @@ pub enum SyscallId { ARCH_PRCTL = 158, + #[cfg(feature = "multitask")] + GETTID = 186, + #[cfg(feature = "multitask")] FUTEX = 202, @@ -213,6 +241,9 @@ pub enum SyscallId { #[cfg(feature = "fs")] READLINKAT = 267, + #[cfg(feature = "fs")] + FACCESSAT = 269, + #[cfg(feature = "select")] PSELECT6 = 270, From f178b6ff755cfb58be627bb94616cd32996d6fbf Mon Sep 17 00:00:00 2001 From: wuzheng Date: Wed, 10 Apr 2024 14:01:33 +0800 Subject: [PATCH 06/13] implement `mmap` with basic flags for aarch64 --- Cargo.lock | 12 + api/arceos_api/Cargo.toml | 1 + api/ruxfeat/Cargo.toml | 6 +- api/ruxos_posix_api/Cargo.toml | 6 + api/ruxos_posix_api/build.rs | 5 +- api/ruxos_posix_api/src/imp/fs.rs | 73 +-- api/ruxos_posix_api/src/imp/mmap/api.rs | 503 ++++++++++++++++++ .../src/imp/{mmap.rs => mmap/legacy.rs} | 11 + api/ruxos_posix_api/src/imp/mmap/mod.rs | 21 + api/ruxos_posix_api/src/imp/mmap/trap.rs | 150 ++++++ api/ruxos_posix_api/src/imp/mmap/utils.rs | 359 +++++++++++++ api/ruxos_posix_api/src/imp/stdio.rs | 37 +- api/ruxos_posix_api/src/lib.rs | 7 +- apps/c/libc-bench/features.txt | 1 + crates/page_table_entry/Cargo.toml | 1 + modules/ruxdriver/src/ixgbe.rs | 6 +- modules/ruxdriver/src/virtio.rs | 4 +- modules/ruxhal/src/arch/aarch64/mod.rs | 3 +- modules/ruxhal/src/arch/aarch64/trap.S | 40 ++ modules/ruxhal/src/arch/aarch64/trap.rs | 24 + modules/ruxhal/src/mem.rs | 31 +- modules/ruxhal/src/paging.rs | 123 ++++- .../src/platform/aarch64_qemu_virt/mp.rs | 4 +- .../ruxhal/src/platform/aarch64_raspi/mp.rs | 5 +- .../src/platform/riscv64_qemu_virt/mp.rs | 4 +- modules/ruxhal/src/trap.rs | 33 +- modules/ruxruntime/src/lib.rs | 25 +- modules/ruxruntime/src/mp.rs | 4 +- platforms/aarch64-qemu-virt.toml | 4 + platforms/aarch64-raspi4.toml | 4 + platforms/riscv64-qemu-virt.toml | 4 + platforms/x86_64-qemu-q35.toml | 4 + scripts/make/build_musl.mk | 2 +- scripts/make/features.mk | 2 +- ulib/ruxlibc/Cargo.toml | 1 + ulib/ruxlibc/c/mmap.c | 55 -- ulib/ruxlibc/include/sys/mman.h | 2 + ulib/ruxlibc/src/lib.rs | 4 + ulib/ruxlibc/src/mmap.rs | 64 +++ ulib/ruxmusl/Cargo.toml | 1 + ulib/ruxmusl/src/aarch64/mod.rs | 15 +- ulib/ruxmusl/src/aarch64/syscall_id.rs | 8 +- ulib/ruxmusl/src/x86_64/mod.rs | 17 +- ulib/ruxmusl/src/x86_64/syscall_id.rs | 6 + 44 files changed, 1533 insertions(+), 159 deletions(-) create mode 100644 api/ruxos_posix_api/src/imp/mmap/api.rs rename api/ruxos_posix_api/src/imp/{mmap.rs => mmap/legacy.rs} (90%) create mode 100644 api/ruxos_posix_api/src/imp/mmap/mod.rs create mode 100644 api/ruxos_posix_api/src/imp/mmap/trap.rs create mode 100644 api/ruxos_posix_api/src/imp/mmap/utils.rs delete mode 100644 ulib/ruxlibc/c/mmap.c create mode 100644 ulib/ruxlibc/src/mmap.rs diff --git a/Cargo.lock b/Cargo.lock index cfc692349..b53869d52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -703,6 +703,12 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "elf" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" + [[package]] name = "embedded-graphics" version = "0.8.1" @@ -1174,6 +1180,7 @@ version = "0.1.0" dependencies = [ "aarch64-cpu", "bitflags 2.4.0", + "log", "memory_addr", "x86_64", ] @@ -1661,9 +1668,13 @@ dependencies = [ "axsync", "bindgen", "bitflags 2.4.0", + "cfg-if", + "crate_interface", + "elf", "flatten_objects", "lazy_static", "memory_addr", + "page_table", "ruxconfig", "ruxfeat", "ruxfs", @@ -1672,6 +1683,7 @@ dependencies = [ "ruxruntime", "ruxtask", "spin 0.9.8", + "spinlock", "static_assertions", ] diff --git a/api/arceos_api/Cargo.toml b/api/arceos_api/Cargo.toml index 4e405c1df..9be613762 100644 --- a/api/arceos_api/Cargo.toml +++ b/api/arceos_api/Cargo.toml @@ -15,6 +15,7 @@ default = [] irq = ["ruxfeat/irq"] rtc = ["ruxfeat/rtc"] alloc = ["dep:axalloc", "ruxfeat/alloc"] +paging = ["alloc", "ruxfeat/paging"] multitask = ["ruxtask/multitask", "ruxfeat/multitask"] fs = ["dep:ruxfs", "ruxfeat/fs"] net = ["dep:axnet", "ruxfeat/net"] diff --git a/api/ruxfeat/Cargo.toml b/api/ruxfeat/Cargo.toml index f9f4b90c8..f4aaf4d56 100644 --- a/api/ruxfeat/Cargo.toml +++ b/api/ruxfeat/Cargo.toml @@ -41,16 +41,16 @@ sched_rr = ["ruxtask/sched_rr", "irq"] sched_cfs = ["ruxtask/sched_cfs", "irq"] # File system -fs = ["alloc", "paging", "dep:ruxfs", "ruxruntime/fs"] # TODO: try to remove "paging" +fs = ["alloc", "dep:ruxfs", "ruxruntime/fs"] blkfs = ["ruxdriver/virtio-blk", "ruxruntime/blkfs"] myfs = ["ruxfs?/myfs"] 9pfs = [] # Networking -net = ["alloc", "paging", "ruxdriver/virtio-net", "dep:axnet", "ruxruntime/net"] +net = ["alloc", "ruxdriver/virtio-net", "dep:axnet", "ruxruntime/net"] # Display -display = ["alloc", "paging", "ruxdriver/virtio-gpu", "dep:ruxdisplay", "ruxruntime/display"] +display = ["alloc", "ruxdriver/virtio-gpu", "dep:ruxdisplay", "ruxruntime/display"] # 9P virtio-9p = ["9pfs", "ruxdriver/virtio-9p", "rux9p/virtio-9p", "ruxruntime/virtio-9p"] diff --git a/api/ruxos_posix_api/Cargo.toml b/api/ruxos_posix_api/Cargo.toml index 1f9f1b60c..b767b2d72 100644 --- a/api/ruxos_posix_api/Cargo.toml +++ b/api/ruxos_posix_api/Cargo.toml @@ -19,6 +19,7 @@ default = [] smp = ["ruxfeat/smp"] alloc = ["dep:axalloc", "ruxfeat/alloc"] +paging = ["alloc", "ruxfeat/paging"] multitask = ["ruxfeat/multitask", "ruxtask/multitask", "dep:ruxfutex"] fd = ["alloc"] fs = ["dep:ruxfs", "ruxfeat/fs", "fd"] @@ -54,8 +55,13 @@ axerrno = { path = "../../crates/axerrno" } memory_addr = { path = "../../crates/memory_addr" } static_assertions = "1.1.0" spin = { version = "0.9" } +spinlock = { path = "../../crates/spinlock" } lazy_static = { version = "1.4", features = ["spin_no_std"] } flatten_objects = { path = "../../crates/flatten_objects" } +page_table = { path = "../../crates/page_table" } +crate_interface = { path = "../../crates/crate_interface" } + +cfg-if = "1.0" elf = { version = "0.7", default-features = false } bitflags = "2.2" diff --git a/api/ruxos_posix_api/build.rs b/api/ruxos_posix_api/build.rs index 5da21eb3c..fe71136be 100644 --- a/api/ruxos_posix_api/build.rs +++ b/api/ruxos_posix_api/build.rs @@ -125,7 +125,10 @@ typedef struct {{ "EINVAL", "CLONE_.*", "AT_.*", - "MAP_FAILED", + "MAP_.+", + "PROT_.+", + "MS_.+", + "MREMAP_.+", ]; #[derive(Debug)] diff --git a/api/ruxos_posix_api/src/imp/fs.rs b/api/ruxos_posix_api/src/imp/fs.rs index cb70b1004..46338c10a 100644 --- a/api/ruxos_posix_api/src/imp/fs.rs +++ b/api/ruxos_posix_api/src/imp/fs.rs @@ -232,6 +232,46 @@ pub fn sys_openat(fd: usize, path: *const c_char, flags: c_int, mode: ctypes::mo }) } +/// Set the position of the file indicated by `fd`. +/// +/// Read data from a file at a specific offset. +pub fn sys_pread64( + fd: c_int, + buf: *mut c_void, + count: usize, + pos: ctypes::off_t, +) -> ctypes::ssize_t { + debug!("sys_pread64 <= {} {} {}", fd, count, pos); + syscall_body!(sys_pread64, { + if buf.is_null() { + return Err(LinuxError::EFAULT); + } + let dst = unsafe { core::slice::from_raw_parts_mut(buf as *mut u8, count) }; + let size = File::from_fd(fd)?.inner.lock().read_at(pos as u64, dst)?; + Ok(size as ctypes::ssize_t) + }) +} + +/// Set the position of the file indicated by `fd`. +/// +/// Write data from a file at a specific offset. +pub fn sys_pwrite64( + fd: c_int, + buf: *const c_void, + count: usize, + pos: ctypes::off_t, +) -> ctypes::ssize_t { + debug!("sys_pwrite64 <= {} {} {}", fd, count, pos); + syscall_body!(sys_pwrite64, { + if buf.is_null() { + return Err(LinuxError::EFAULT); + } + let src = unsafe { core::slice::from_raw_parts_mut(buf as *mut u8, count) }; + let size = File::from_fd(fd)?.inner.lock().write_at(pos as u64, src)?; + Ok(size as ctypes::ssize_t) + }) +} + /// Set the position of the file indicated by `fd`. /// /// Return its position after seek. @@ -597,37 +637,6 @@ pub unsafe fn sys_getdents64( }) } -/// Read data from the file indicated by `fd`, starting at the position given by `offset`. -/// -/// Return the read size if success. -pub fn sys_pread( - fd: c_int, - buf: *mut c_void, - count: usize, - offset: ctypes::off_t, -) -> ctypes::ssize_t { - debug!( - "sys_pread <= fd: {} buf: {:#x} count: {} offset: {}", - fd, buf as usize, count, offset - ); - syscall_body!(sys_pread, { - if buf.is_null() { - return Err(LinuxError::EFAULT); - } - let dst = unsafe { core::slice::from_raw_parts_mut(buf as *mut u8, count) }; - #[cfg(feature = "fd")] - { - Ok(File::from_fd(fd)?.inner.lock().read_at(offset as _, dst)?) - } - #[cfg(not(feature = "fd"))] - match fd { - 0 => Ok(super::stdio::stdin().read(dst)? as ctypes::ssize_t), - 1 | 2 => Err(LinuxError::EPERM), - _ => Err(LinuxError::EBADF), - } - }) -} - /// Reads `iocnt` buffers from the file associated with the file descriptor `fd` into the /// buffers described by `iov`, starting at the position given by `offset` pub unsafe fn sys_preadv( @@ -651,7 +660,7 @@ pub unsafe fn sys_preadv( if iov.iov_base.is_null() { continue; } - ret += sys_pread(fd, iov.iov_base, iov.iov_len, offset); + ret += sys_pread64(fd, iov.iov_base, iov.iov_len, offset); } Ok(ret) }) diff --git a/api/ruxos_posix_api/src/imp/mmap/api.rs b/api/ruxos_posix_api/src/imp/mmap/api.rs new file mode 100644 index 000000000..ba5c8bee4 --- /dev/null +++ b/api/ruxos_posix_api/src/imp/mmap/api.rs @@ -0,0 +1,503 @@ +/* Copyright (c) [2023] [Syswonder Community] + * [Ruxos] is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +use crate::ctypes; +use alloc::vec::Vec; +use axerrno::LinuxError; +use core::{ + ffi::{c_int, c_void}, + ops::Bound, +}; +use memory_addr::PAGE_SIZE_4K; +use ruxhal::{mem::VirtAddr, paging::pte_update_page}; + +use super::utils::{ + find_free_region, get_mflags_from_usize, get_overlap, release_pages_mapped, shift_mapped_page, + Vma, MEM_MAP, VMA_END, VMA_MAP, +}; + +#[cfg(feature = "fs")] +use super::utils::release_pages_swaped; +#[cfg(feature = "fs")] +use crate::imp::fs::sys_pwrite64; + +/// Creates a new mapping in the virtual address space of the calling process. +/// +/// Note: support flags `MAP_PRIVATE`, `MAP_SHARED`, `MAP_ANONYMOUS`, `MAP_FILE`, `MAP_FIXED`. +pub fn sys_mmap( + start: *mut c_void, + len: ctypes::size_t, + prot: c_int, + flags: c_int, + fd: c_int, + off: ctypes::off_t, +) -> *mut c_void { + debug!( + "sys_mmap <= start: {:p}, len: {:x}, prot:{:x?}, flags:{:x?}, fd: {}", + start, len, prot, flags, fd + ); + syscall_body!(sys_mmap, { + // transform C-type into rust-type + let start = start as usize; + let len = VirtAddr::from(len).align_up_4k().as_usize(); + if !VirtAddr::from(start).is_aligned(PAGE_SIZE_4K) || len == 0 { + error!( + "mmap failed because start:{:x} is not aligned or len:{:x} == 0", + start, len + ); + return Err(LinuxError::EINVAL); + } + let prot = prot as u32; + let flags = flags as u32; + let fid = fd; + let offset = off as usize; + + // check if `MAP_SHARED` or `MAP_PRIVATE` within flags. + if (flags & ctypes::MAP_PRIVATE == 0) && (flags & ctypes::MAP_SHARED == 0) { + error!("mmap failed because none of `MAP_PRIVATE` and `MAP_SHARED` exsit"); + return Err(LinuxError::EINVAL); + } + + // check if `MAP_ANOYMOUS` within flags. + let fid = if flags & ctypes::MAP_ANONYMOUS != 0 { + -1 + } else if fid < 0 { + error!("fd in mmap without `MAP_ANONYMOUS` must larger than 0"); + return Err(LinuxError::EBADF); + } else { + fid + }; + + let mut new = Vma::new(fid, offset, prot, flags); + let mut vma_map = VMA_MAP.lock(); + let addr_condition = if start == 0 { None } else { Some(start) }; + let try_addr = find_free_region(&vma_map, addr_condition, len); + match try_addr { + Some(vaddr) if vaddr == start || flags & ctypes::MAP_FIXED == 0 => { + new.start_addr = vaddr; + new.end_addr = vaddr + len; + vma_map.insert(vaddr, new); + Ok(vaddr as *mut c_void) + } + _ => Err(LinuxError::ENOMEM), + } + }) +} + +/// Deletes the mappings for the specified address range +pub fn sys_munmap(start: *mut c_void, len: ctypes::size_t) -> c_int { + debug!("sys_munmap <= start: {:p}, len: {:x}", start, len); + syscall_body!(sys_munmap, { + // transform C-type into rust-type + let start = start as usize; + let end = VirtAddr::from(start + len).align_up_4k().as_usize(); + + if !VirtAddr::from(start).is_aligned(PAGE_SIZE_4K) || len == 0 { + error!( + "sys_munmap start_address={:x}, len {:x?} not aligned", + start, len + ); + return Err(LinuxError::EINVAL); + } + + let mut vma_map = VMA_MAP.lock(); + let mut post_append: Vec<(usize, Vma)> = Vec::new(); // vma should be insert. + let mut post_remove: Vec = Vec::new(); // vma should be removed. + let mut node = vma_map.upper_bound_mut(Bound::Included(&start)); + let mut counter = 0; // counter to check if all address in [start, start+len) is mapped. + while let Some(vma) = node.value_mut() { + if vma.start_addr >= end { + break; + } + if let Some((overlapped_start, overlapped_end)) = + get_overlap((start, end), (vma.start_addr, vma.end_addr)) + { + // Accumulate the size of the mapping area to be released + counter += overlapped_end - overlapped_start; + + // add node for overlapped vma_ptr + if vma.end_addr > overlapped_end { + let right_vma = Vma::clone_from(vma, overlapped_end, vma.end_addr); + post_append.push((overlapped_end, right_vma)); + } + if overlapped_start > vma.start_addr { + vma.end_addr = overlapped_start; + } else { + post_remove.push(vma.start_addr); + } + } + node.move_next(); + } + + // check if any address in [start, end) not mayed. + if counter != end - start { + error!( + "munmap {:x?} but only {:x?} Byte inside", + end - start, + counter + ); + return Err(LinuxError::EINVAL); + } + + // do post action if success. + for key in post_remove { + vma_map.remove(&key).expect("there should be no empty"); + } + for (key, value) in post_append { + vma_map.insert(key, value); + } + + // delete the mapped and swapped page. + release_pages_mapped(start, end); + #[cfg(feature = "fs")] + release_pages_swaped(start, end); + + Ok(0) + }) +} + +/// Changes the access protections for the calling process's memory pages +/// containing any part of the address range in the interval [addr, addr+len). +/// addr must be aligned to a page boundary. +pub fn sys_mprotect(start: *mut c_void, len: ctypes::size_t, prot: c_int) -> c_int { + debug!( + "sys_mprotect <= addr: {:p}, len: {:x}, prot: {}", + start, len, prot + ); + + syscall_body!(sys_mprotect, { + // transform C-type into rust-type + let start = start as usize; + let end = VirtAddr::from(start + len).align_up_4k().as_usize(); + if !VirtAddr::from(start).is_aligned(PAGE_SIZE_4K) || len == 0 { + return Err(LinuxError::EINVAL); + } + let syncing_interval = (start, end); + + let mut post_append: Vec<(usize, Vma)> = Vec::new(); + + let mut vma_map = VMA_MAP.lock(); + let mut node = vma_map.upper_bound_mut(Bound::Included(&start)); + let mut counter = 0; // counter to check if all address in [start, start+len) is mapped. + while let Some(vma) = node.value_mut() { + if vma.start_addr >= end { + break; + } + if let Some((overlapped_start, overlapped_end)) = + get_overlap(syncing_interval, (vma.start_addr, vma.end_addr)) + { + // Accumulate the size of the mapping area to be released + counter += overlapped_end - overlapped_start; + + // add node for overlapped vma_ptr + if vma.end_addr > overlapped_end { + let right_vma = Vma::clone_from(vma, overlapped_end, vma.end_addr); + post_append.push((overlapped_end, right_vma)); + } + if overlapped_start > vma.start_addr { + vma.end_addr = overlapped_start; + let mut overlapped_vma = Vma::clone_from(vma, overlapped_start, overlapped_end); + overlapped_vma.prot = prot as u32; + post_append.push((overlapped_start, overlapped_vma)) + } else { + vma.end_addr = overlapped_end; + vma.prot = prot as u32; + } + } + node.move_next(); + } + // check if any address in [start, end) not mayed. + if counter != end - start { + error!( + "munmap {:x?} but only {:x?} Byte inside", + end - start, + counter + ); + return Err(LinuxError::EFAULT); + } + + // upate PTEs if mprotect is successful. + for (&vaddr, _) in MEM_MAP.lock().range(start..end) { + if pte_update_page( + VirtAddr::from(vaddr), + None, + Some(get_mflags_from_usize(prot as u32)), + ) + .is_err() + { + error!( + "Update page prot failed when mprotecting the page: vaddr={:x?}, prot={:?}", + vaddr, prot + ); + } + } + // do post action if success. + for (key, value) in post_append { + vma_map.insert(key, value); + } + Ok(0) + }) +} + +/// Synchronizes the calling process's memory pages in the interval [addr, addr+len-1] +/// with the corresponding physical storage device, ensuring that any modifications +/// are flushed to the storage. +/// +/// Note: support flags `MS_SYNC` only. +pub fn sys_msync(start: *mut c_void, len: ctypes::size_t, flags: c_int) -> c_int { + debug!( + "sys_msync <= addr: {:p}, len: {}, flags: {}", + start, len, flags + ); + syscall_body!(sys_msync, { + #[cfg(feature = "fs")] + { + let start = start as usize; + let end = VirtAddr::from(start + len).align_up_4k().as_usize(); + if !VirtAddr::from(start).is_aligned(PAGE_SIZE_4K) || len == 0 { + return Err(LinuxError::EINVAL); + } + for (&vaddr, &page_info) in MEM_MAP.lock().range(start..end) { + if let Some((fid, offset, size)) = page_info { + let src = vaddr as *mut c_void; + let ret_size = sys_pwrite64(fid, src, size, offset as i64) as usize; + if size != ret_size { + error!( + "sys_msync: try to pwrite(fid={:x?}, size={:x?}, offset={:x?}) but get ret = {:x?}", + fid, size, offset, ret_size + ); + return Err(LinuxError::EFAULT); + } + } + } + } + Ok(0) + }) +} + +/// Remap a virtual memory address +pub fn sys_mremap( + old_addr: *mut c_void, + old_size: ctypes::size_t, + new_size: ctypes::size_t, + flags: c_int, + new_addr: *mut c_void, +) -> *mut c_void { + debug!( + "sys_mremap <= old_addr: {:p}, old_size: {}, new_size: {}, flags: {}, new_addr: {:p}", + old_addr, old_size, new_size, flags, new_addr + ); + syscall_body!(sys_mremap, { + let old_vaddr = VirtAddr::from(old_addr as usize); + let flags = flags as u32; + + // check if the parameters is legal. + if (!old_vaddr.is_aligned(PAGE_SIZE_4K)) + || new_size == 0 + || (old_size == 0 && flags & ctypes::MREMAP_MAYMOVE == 0) + || (old_size != new_size && flags & ctypes::MREMAP_DONTUNMAP != 0) + || flags & !(ctypes::MREMAP_MAYMOVE | ctypes::MREMAP_FIXED | ctypes::MREMAP_DONTUNMAP) + != 0 + || ((flags & ctypes::MREMAP_FIXED != 0 || flags & ctypes::MREMAP_DONTUNMAP != 0) + && (flags & ctypes::MREMAP_MAYMOVE == 0)) + { + return Err(LinuxError::EINVAL); + } + + let old_start = old_vaddr.as_usize(); + let old_end = old_start + old_size; + + let mut consistent_vma: Option = None; // structure to verify the consistent in the range of [old_start, old_end) + let mut post_remove: Vec = Vec::new(); // vma should be removed if success. + + let mut vma_map = VMA_MAP.lock(); + // collect and check vma alongside the range of [old_start, old_end). + let mut node = vma_map.upper_bound_mut(Bound::Included(&old_start)); + while let Some(vma) = node.value_mut() { + if vma.start_addr > old_end { + break; + } + // make sure of consistent_vma is continuous and consistent in both flags and prots. + if let Some(ref mut inner_vma) = consistent_vma { + let end_offset = inner_vma.offset + (inner_vma.end_addr - inner_vma.start_addr); + if inner_vma.end_addr == vma.start_addr + && inner_vma.flags == vma.flags + && inner_vma.prot == vma.prot + && inner_vma.fid == vma.fid + && (end_offset == vma.offset || inner_vma.fid < 0) + { + inner_vma.end_addr = vma.end_addr; + } else { + return Err(LinuxError::EFAULT); + } + } else { + consistent_vma.replace(Vma::clone_from(vma, vma.start_addr, vma.end_addr)); + } + + post_remove.push(vma.start_addr); + node.move_next(); + } + + // check if consistent_vma full match the remapping memory. + if consistent_vma.is_none() { + return Err(LinuxError::EFAULT); + } + let mut old_vma = consistent_vma.unwrap(); + if old_vma.end_addr < old_end { + return Err(LinuxError::EFAULT); + } + + let opt_address = if flags & ctypes::MREMAP_FIXED != 0 || !new_addr.is_null() { + Some(new_addr as usize) + } else { + None + }; + + if flags & ctypes::MREMAP_DONTUNMAP != 0 { + // find a new region for new_start + if let Some(new_start) = find_free_region(&vma_map, opt_address, new_size) { + if flags & ctypes::MREMAP_FIXED != 0 && new_addr as usize != new_start { + return Err(LinuxError::ENOMEM); + } + + // copy the dirty page. + shift_mapped_page( + old_vma.start_addr, + old_vma.end_addr, + new_start - old_vma.start_addr, + true, + ); + + // copy the old to the new. + vma_map.insert( + new_start, + Vma::clone_from(&old_vma, new_start, new_start + new_size), + ); + + // Remove the mapping debris and combine them into a large one.(for performance) + for key in post_remove { + vma_map.remove(&key); + } + vma_map.insert(old_vma.start_addr, old_vma); + + return Ok(new_start as *mut c_void); + } else { + return Err(LinuxError::ENOMEM); + } + } + + // shrinking the original address does not require changing the mapped page. + if old_size > new_size && (flags & ctypes::MREMAP_FIXED == 0 || new_addr == old_addr) { + let ret = old_vma.start_addr; + let new_end = old_start + new_size; + if old_vma.end_addr > old_end { + vma_map.insert( + old_end, + Vma::clone_from(&old_vma, old_end, old_vma.end_addr), + ); + } + old_vma.end_addr = new_end; + + // delete the mapped and swapped page outside of new vma. + release_pages_mapped(new_end, old_end); + #[cfg(feature = "fs")] + release_pages_swaped(new_end, old_end); + + // vma_map.insert(old_vma.start_addr, old_vma); + return Ok(ret as *mut c_void); + } + // expanding the original address does not require changing the mapped page. + else if old_size < new_size && (flags & ctypes::MREMAP_FIXED == 0 || new_addr == old_addr) + { + if old_vma.end_addr != old_end && flags & ctypes::MREMAP_MAYMOVE == 0 { + return Err(LinuxError::ENOMEM); + } + // find the right region to expand them in orignal addr. + let upper = vma_map + .lower_bound(Bound::Included(&old_end)) + .key() + .unwrap_or(&VMA_END); + if upper - old_end >= new_size - old_size { + let ret = old_vma.start_addr; + let new_end = old_start + new_size; + old_vma.end_addr = new_end; + vma_map.insert(old_vma.start_addr, old_vma); + return Ok(ret as *mut c_void); + } + } + + // try to move pages according to `new_addr`. + if flags & ctypes::MREMAP_MAYMOVE != 0 { + match find_free_region(&vma_map, opt_address, new_size) { + Some(vaddr) if vaddr == new_addr as usize || flags & ctypes::MREMAP_FIXED == 0 => { + // Reserve excess memory before and after + if old_vma.start_addr < old_start { + vma_map.insert( + old_vma.start_addr, + Vma::clone_from(&old_vma, old_vma.start_addr, old_start), + ); + } + if old_vma.end_addr > old_end { + vma_map.insert( + old_end, + Vma::clone_from(&old_vma, old_end, old_vma.end_addr), + ); + } + + // Shift mapped memory in both `MEM_MAP` and `SWAP_MAP`. + shift_mapped_page( + old_vma.start_addr, + old_vma.end_addr, + vaddr - old_vma.start_addr, + false, + ); + + // Insert the new vma. + vma_map.insert(vaddr, Vma::clone_from(&old_vma, vaddr, vaddr + new_size)); + + // remove the old vma deris. + for key in post_remove { + vma_map.remove(&key); + } + if old_vma.start_addr < old_start { + vma_map.insert( + old_end, + Vma::clone_from(&old_vma, old_vma.start_addr, old_start), + ); + } + if old_vma.end_addr > old_end { + vma_map.insert( + old_end, + Vma::clone_from(&old_vma, old_end, old_vma.end_addr), + ); + } + + return Ok(vaddr as *mut c_void); + } + _ => { + return Err(LinuxError::ENOMEM); + } + }; + } + + Err(LinuxError::ENOMEM) + }) +} + +/// give advice about use of memory +/// if success return 0, if error return -1 +/// +/// TODO: implement this to improve performance. +pub fn sys_madvise(addr: *mut c_void, len: ctypes::size_t, advice: c_int) -> c_int { + debug!( + "sys_madvise <= addr: {:p}, len: {}, advice: {}", + addr, len, advice + ); + syscall_body!(sys_madvise, Ok(0)) +} diff --git a/api/ruxos_posix_api/src/imp/mmap.rs b/api/ruxos_posix_api/src/imp/mmap/legacy.rs similarity index 90% rename from api/ruxos_posix_api/src/imp/mmap.rs rename to api/ruxos_posix_api/src/imp/mmap/legacy.rs index 43edd5b0f..682e7bb5e 100644 --- a/api/ruxos_posix_api/src/imp/mmap.rs +++ b/api/ruxos_posix_api/src/imp/mmap/legacy.rs @@ -105,6 +105,17 @@ pub fn sys_mremap( syscall_body!(sys_mremap, Ok::<*mut c_void, LinuxError>(-1 as _)) } +/// Synchronizes the calling process's memory pages in the interval [addr, addr+len-1] +/// with the corresponding physical storage device, ensuring that any modifications +/// are flushed to the storage. +pub fn sys_msync(start: *mut c_void, len: ctypes::size_t, flags: c_int) -> c_int { + debug!( + "sys_msync <= addr: {:p}, len: {}, flags: {}", + start, len, flags + ); + syscall_body!(sys_msync, Ok(0)) +} + /// give advice about use of memory /// if success return 0, if error return -1 /// diff --git a/api/ruxos_posix_api/src/imp/mmap/mod.rs b/api/ruxos_posix_api/src/imp/mmap/mod.rs new file mode 100644 index 000000000..b18d2c8e4 --- /dev/null +++ b/api/ruxos_posix_api/src/imp/mmap/mod.rs @@ -0,0 +1,21 @@ +/* Copyright (c) [2023] [Syswonder Community] + * [Ruxos] is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +cfg_if::cfg_if! { + if #[cfg(all(feature = "paging", target_arch = "aarch64"))] { + #[macro_use] + mod utils; + mod api; + mod trap; + pub use self::api::{sys_madvise, sys_mmap, sys_mprotect, sys_mremap, sys_msync, sys_munmap}; + }else { + mod legacy; + pub use self::legacy::{sys_madvise, sys_mmap, sys_mprotect, sys_mremap, sys_msync, sys_munmap}; + } +} diff --git a/api/ruxos_posix_api/src/imp/mmap/trap.rs b/api/ruxos_posix_api/src/imp/mmap/trap.rs new file mode 100644 index 000000000..32ee03d5c --- /dev/null +++ b/api/ruxos_posix_api/src/imp/mmap/trap.rs @@ -0,0 +1,150 @@ +/* Copyright (c) [2023] [Syswonder Community] + * [Ruxos] is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +use crate::ctypes; + +#[cfg(not(feature = "fs"))] +use ruxhal::paging::alloc_page_preload; +#[cfg(feature = "fs")] +use { + crate::imp::fs::sys_pread64, + crate::imp::mmap::utils::{preload_page_with_swap, BITMAP_FREE, SWAPED_MAP, SWAP_FID}, +}; + +use crate::imp::mmap::utils::{get_mflags_from_usize, MEM_MAP, VMA_MAP}; +use core::{cmp::min, ffi::c_void, ops::Bound}; +use memory_addr::PAGE_SIZE_4K; +use page_table::MappingFlags; +use ruxhal::{ + mem::VirtAddr, + paging::{do_pte_map, pte_query}, + trap::PageFaultCause, +}; + +struct TrapHandlerImpl; + +#[crate_interface::impl_interface] +impl ruxhal::trap::TrapHandler for TrapHandlerImpl { + fn handle_page_fault(vaddr: usize, cause: PageFaultCause) -> bool { + let vma_map = VMA_MAP.lock(); + if let Some(vma) = vma_map.upper_bound(Bound::Included(&vaddr)).value() { + // Check if page existing in the vma, go to panic if not. + if vma.end_addr <= vaddr { + return false; + } + + let vaddr = VirtAddr::from(vaddr).align_down_4k().as_usize(); + let size = min(PAGE_SIZE_4K, vma.end_addr - vaddr); + let map_flag = get_mflags_from_usize(vma.prot); + + trace!( + "Page Fault Happening, vaddr:{:x?}, casue:{:?}, map_flags:{:x?}", + vaddr, + cause, + map_flag + ); + + // Check if the access meet the prot + match cause { + PageFaultCause::INSTRUCTION if !map_flag.contains(MappingFlags::EXECUTE) => { + return false + } + PageFaultCause::READ if !map_flag.contains(MappingFlags::READ) => return false, + PageFaultCause::WRITE if !map_flag.contains(MappingFlags::WRITE) => return false, + _ => {} + } + + // In a multi-threaded situation, it is possible that multiple threads + // simultaneously trigger a page miss interrupt on the same page, + // resulting in the page being actually mapped and causing an `AlreadyMap` + // error + if pte_query(VirtAddr::from(vaddr)).is_ok() { + return true; + } + + let mut memory_map = MEM_MAP.lock(); + used_fs! { + let mut swaped_map = SWAPED_MAP.lock(); + let mut off_pool = BITMAP_FREE.lock(); + } + + // Due to the existence of only one page table in ruxos, in + // order to prevent data competition in multi-threaded environ- + // -ments caused by adding the current virtual address to the + // page table, it is necessary to first map the physical address + // that needs to be mapped to another virtual address, and then + // perform operations such as filling the corresponding memory + // data. After completing all operations involving memory read + // and write, map the actual virtual addresses that need to be mapped. + // + // fake_vaddr = preload() => do_pte_map(vaddr... fake_vaddr ...) + #[cfg(not(feature = "fs"))] + let fake_vaddr = alloc_page_preload().expect("alloc memory for new page failed"); + #[cfg(feature = "fs")] + let fake_vaddr = + preload_page_with_swap(&mut memory_map, &mut swaped_map, &mut off_pool); + + // Fill target data to assigned physical addresses, from file or zero according to mapping type + let dst = fake_vaddr.as_mut_ptr() as *mut c_void; + #[cfg(feature = "fs")] + { + if let Some(off) = swaped_map.remove(&vaddr) { + off_pool.push(off); + sys_pread64(*SWAP_FID, dst, size, off as i64); + } else if vma.fid > 0 && !map_flag.is_empty() { + let off = (vma.offset + (vaddr - vma.start_addr)) as i64; + sys_pread64(vma.fid, dst, size, off); + } else { + // Set page to 0 for anonymous mapping + // + // Safe because the page memory is allocated here + // and the page fault exception has not exited. + unsafe { + dst.write_bytes(0, size); + } + } + } + + // Set page to 0 for anonymous mapping + // + // Safe because the page memory is allocated here + // and the page fault exception has not exited. + #[cfg(not(feature = "fs"))] + unsafe { + dst.write_bytes(0, size); + } + + // Insert the record into `MEM_MAP` with write-back information(`None` if no need to write-back). + if (vma.prot & ctypes::PROT_WRITE != 0) + && (vma.flags & ctypes::MAP_PRIVATE == 0) + && (vma.fid > 0) + { + let map_length = min(PAGE_SIZE_4K, vma.end_addr - vaddr); + let offset = vma.offset + (vaddr - vma.start_addr); + memory_map.insert(vaddr, Some((vma.fid, offset, map_length))); + } else { + memory_map.insert(vaddr, None); + } + + // Do actual mmapping for target vaddr + // + // Note: other threads can access this page of memory after this code. + match do_pte_map(VirtAddr::from(vaddr), fake_vaddr, map_flag) { + Ok(()) => true, + Err(_) => false, + } + } else { + for mapped in vma_map.iter() { + warn!("{:x?}", mapped); + } + warn!("vaddr={:x?},cause={:x?}", vaddr, cause); + false + } + } +} diff --git a/api/ruxos_posix_api/src/imp/mmap/utils.rs b/api/ruxos_posix_api/src/imp/mmap/utils.rs new file mode 100644 index 000000000..b7e589767 --- /dev/null +++ b/api/ruxos_posix_api/src/imp/mmap/utils.rs @@ -0,0 +1,359 @@ +/* Copyright (c) [2023] [Syswonder Community] + * [Ruxos] is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +use crate::ctypes; + +#[cfg(feature = "fs")] +use { + crate::imp::fs::{sys_open, sys_pread64, sys_pwrite64}, + core::ffi::{c_char, c_void}, + page_table::PagingError, +}; + +use alloc::{collections::BTreeMap, vec::Vec}; +use axsync::Mutex; +use core::{ + cmp::{max, min}, + ops::Bound, +}; +use memory_addr::PAGE_SIZE_4K; +use page_table::MappingFlags; +use ruxhal::{ + mem::VirtAddr, + paging::{alloc_page_preload, do_pte_map, pte_query, pte_swap_preload, pte_unmap_page}, +}; + +// use `used_fs` instead of `#[cfg(feature = "fs")]{}` to cancel the scope of code. +#[cfg(feature = "fs")] +macro_rules! used_fs { + ($($code:tt)*) => {$($code)*}; +} + +#[cfg(not(feature = "fs"))] +macro_rules! used_fs { + ($($code:tt)*) => {}; +} + +pub(crate) const VMA_START: usize = ruxconfig::MMAP_START_VADDR; +pub(crate) const VMA_END: usize = ruxconfig::MMAP_END_VADDR; + +// TODO: move defination of `SWAP_MAX` and `SWAP_PATH` from const numbers to `ruxconfig`. +used_fs! { + pub(crate) const SWAP_MAX: usize = 1024 * 1024 * 1024; + pub(crate) const SWAP_PATH: &str = "swap.raw\0"; + pub(crate) static SWAPED_MAP: Mutex> = Mutex::new(BTreeMap::new()); // Vaddr => (page_size, offset_at_swaped) + lazy_static::lazy_static! { + pub(crate) static ref SWAP_FID: i32 = sys_open(SWAP_PATH.as_ptr() as *const c_char, (ctypes::O_RDWR| ctypes::O_TRUNC| ctypes::O_SYNC) as i32, 0); + pub(crate) static ref BITMAP_FREE: Mutex> = Mutex::new((0..SWAP_MAX).step_by(PAGE_SIZE_4K).collect()); + } +} + +pub(crate) static VMA_MAP: Mutex> = Mutex::new(BTreeMap::new()); // start_addr +pub(crate) static MEM_MAP: Mutex> = Mutex::new(BTreeMap::new()); // Vaddr => (fid, offset, page_size) + +type PageInfo = Option<(Fid, Offset, Len)>; // (fid, offset, page_size) +type Offset = usize; +type Fid = i32; +type Len = usize; + +/// Data structure for mapping [start_addr, end_addr) with meta data. +#[derive(Debug)] +pub(crate) struct Vma { + pub start_addr: usize, + pub end_addr: usize, + pub fid: i32, + pub offset: usize, + pub prot: u32, + pub flags: u32, +} + +/// Impl for Vma. +impl Vma { + pub fn new(fid: i32, offset: usize, prot: u32, flags: u32) -> Self { + Vma { + start_addr: 0, + end_addr: 0, + fid, + offset, + flags, + prot, + } + } + + pub fn clone_from(vma: &Vma, start_addr: usize, end_addr: usize) -> Self { + Vma { + start_addr, + end_addr, + fid: vma.fid, + offset: vma.offset, + prot: vma.prot, + flags: vma.prot, + } + } +} + +/// transform usize-like mmap flags to MappingFlags +pub(crate) fn get_mflags_from_usize(prot: u32) -> MappingFlags { + let mut mmap_prot = MappingFlags::empty(); + + if prot & ctypes::PROT_WRITE != 0 { + mmap_prot |= MappingFlags::WRITE; + } + if prot & ctypes::PROT_EXEC != 0 { + mmap_prot |= MappingFlags::EXECUTE; + } + + // always readable at least + mmap_prot | MappingFlags::READ +} + +/// lock overlap region between two intervals [start1, end1) and [start2,end2)。 +pub(crate) fn get_overlap( + interval1: (usize, usize), + interval2: (usize, usize), +) -> Option<(usize, usize)> { + let (start1, end1) = interval1; + let (start2, end2) = interval2; + + let overlap_start = max(start1, start2); + let overlap_end = min(end1, end2); + + if overlap_end > overlap_start { + Some((overlap_start, overlap_end)) + } else { + None + } +} + +/// search a free region in `VMA_LIST` meet the condition. +/// take care of AA-deadlock, this function should not be used after `MEM_MAP` is used. +pub(crate) fn find_free_region( + vma_map: &BTreeMap, + addr: Option, + len: usize, +) -> Option { + // Search free region in select region if start!=NULL, return error if `MAP_FIXED` flags exist. + if let Some(start) = addr { + let end_addr = if let Some(lower_vma) = vma_map.upper_bound(Bound::Included(&start)).value() + { + lower_vma.end_addr + } else { + VMA_START + }; + let upper = vma_map + .lower_bound(Bound::Included(&start)) + .key() + .unwrap_or(&VMA_END); + if upper - start >= len && end_addr <= start { + return Some(start); + } + } + + // Search free region on the top of VMA_LISTS first. + if let Some((_, last_vma)) = vma_map.last_key_value() { + if VMA_END - last_vma.end_addr >= len { + return Some(last_vma.end_addr); + } + } else if VMA_END >= VMA_START + len { + return Some(VMA_START); + } + + // Search free region among the VMA_LISTS. + let mut left = VMA_START; + for vma in vma_map.values() { + let right = vma.start_addr; + let free_size = right - left; + if free_size >= len { + return Some(left); + } + left = vma.end_addr; + } + + None +} + +/// release the range of [start, end) in mem_map +/// take care of AA-deadlock, this function should not be used after `MEM_MAP` is used. +pub(crate) fn release_pages_mapped(start: usize, end: usize) { + let mut memory_map = MEM_MAP.lock(); + let mut removing_vaddr = Vec::new(); + for (&vaddr, &_page_info) in memory_map.range(start..end) { + #[cfg(feature = "fs")] + if let Some((fid, offset, size)) = _page_info { + let src = vaddr as *mut c_void; + let offset = offset as i64; + sys_pwrite64(fid, src, size, offset); + } + if pte_unmap_page(VirtAddr::from(vaddr)).is_err() { + panic!("Release page failed when munmapping!"); + } + removing_vaddr.push(vaddr); + } + for vaddr in removing_vaddr { + memory_map.remove(&vaddr); + } +} + +/// release the range of [start, end) in swaped-file, swaped-file should not contain file-mapping. +/// take care of AA-deadlock, this function should not be used after `SWAPED_MAP` and `BITMAP_FREE` is used. +#[cfg(feature = "fs")] +pub(crate) fn release_pages_swaped(start: usize, end: usize) { + let mut swap_map = SWAPED_MAP.lock(); + let mut off_pool = BITMAP_FREE.lock(); + + let mut removing_vaddr = Vec::new(); + for (&vaddr, &off) in swap_map.range(start..end) { + removing_vaddr.push(vaddr); + off_pool.push(off); + } + for vaddr in removing_vaddr { + swap_map.remove(&vaddr); + } +} + +/// shift mapped the page in both MEM_MAP and SWAPED_MAP. +/// No page fault here should be guaranteed +pub(crate) fn shift_mapped_page(start: usize, end: usize, vma_offset: usize, copy: bool) { + let mut memory_map = MEM_MAP.lock(); + used_fs! { + let mut swaped_map = SWAPED_MAP.lock(); + let mut off_pool = BITMAP_FREE.lock(); + } + + let mut opt_buffer = Vec::new(); + for (&start, &page_info) in memory_map.range(start..end) { + opt_buffer.push((start, page_info)); + } + for (start, page_info) in opt_buffer { + // opt for the PTE. + let (fake_vaddr, flags) = if !copy { + memory_map.remove(&start); + // only shift virtual address and keep the physic address to free from data-copy. + let (_, flags, _) = pte_query(VirtAddr::from(start)).unwrap(); + let fake_vaddr = pte_swap_preload(VirtAddr::from(start)).unwrap(); + (fake_vaddr, flags) + } else { + let (_, flags, _) = pte_query(VirtAddr::from(start)).unwrap(); + + #[cfg(not(feature = "fs"))] + let fake_vaddr = alloc_page_preload().expect("alloc memory for new page failed"); + #[cfg(feature = "fs")] + let fake_vaddr = + preload_page_with_swap(&mut memory_map, &mut swaped_map, &mut off_pool); + + let dst = unsafe { + core::slice::from_raw_parts_mut(fake_vaddr.as_usize() as *mut u8, PAGE_SIZE_4K) + }; + if memory_map.contains_key(&start) { + // copy the memory directly + let src = + unsafe { core::slice::from_raw_parts_mut(start as *mut u8, PAGE_SIZE_4K) }; + dst.clone_from_slice(src); + } else if page_info.is_none() + /* has been swapped from memory */ + { + used_fs! { + let offset = swaped_map.get(&start).unwrap(); + sys_pread64( + *SWAP_FID, + dst.as_mut_ptr() as *mut c_void, + PAGE_SIZE_4K, + *offset as i64, + ); + } + } + (fake_vaddr, flags) + }; + do_pte_map(VirtAddr::from(start + vma_offset), fake_vaddr, flags).unwrap(); + memory_map.insert(start + vma_offset, page_info); + } + + used_fs! { + let mut opt_buffer = Vec::new(); + for (&start, &off_in_swap) in swaped_map.range(start..end) { + opt_buffer.push((start, off_in_swap)); + } + for (start, off_in_swap) in opt_buffer { + // opt for the swapped file, should copy swaped page for the new page. + if !copy { + swaped_map.remove(&start); + } else { + let off_ptr = off_pool + .pop() + .expect("There are no free space in swap-file!"); + let mut rw_buffer: [u8; PAGE_SIZE_4K] = [0_u8; PAGE_SIZE_4K]; + sys_pread64( + *SWAP_FID, + rw_buffer.as_mut_ptr() as *mut c_void, + PAGE_SIZE_4K, + off_in_swap as i64, + ); + sys_pwrite64( + *SWAP_FID, + rw_buffer.as_mut_ptr() as *mut c_void, + PAGE_SIZE_4K, + off_ptr as i64, + ); + } + swaped_map.insert(start + vma_offset, off_in_swap); + } + } +} + +/// Allocate a section of physical memory for faulty pages +/// Since there is only one page table in RuxOS, the return value is the starting value +/// of a virtual address that is also mapped to the allocated physical address. +#[cfg(feature = "fs")] +pub(crate) fn preload_page_with_swap( + memory_map: &mut BTreeMap, + swaped_map: &mut BTreeMap, + off_pool: &mut Vec, +) -> VirtAddr { + match alloc_page_preload() { + Ok(vaddr) => vaddr, + // Try to swap the mapped memory into Disk and use this segment of physical memory + #[cfg(feature = "fs")] + Err(PagingError::NoMemory) => match memory_map.pop_first() { + // For file mapping, the mapped content will be written directly to the original file. + Some((vaddr_swapped, Some((fid, offset, size)))) => { + let offset = offset.try_into().unwrap(); + sys_pwrite64(fid, vaddr_swapped as *mut c_void, size, offset); + pte_swap_preload(VirtAddr::from(vaddr_swapped)).unwrap() + } + // For anonymous mapping, you need to save the mapped memory to the prepared swap file, + // and record the memory address and its offset in the swap file. + Some((vaddr_swapped, None)) => { + let offset_get = off_pool.pop(); + if SWAP_FID.is_negative() || offset_get.is_none() { + panic!( + "No free memory for mmap or swap fid, swap fid={}", + *SWAP_FID + ); + } + let offset = offset_get.unwrap(); + swaped_map.insert(vaddr_swapped, offset); + + sys_pwrite64( + *SWAP_FID, + vaddr_swapped as *mut c_void, + PAGE_SIZE_4K, + offset as i64, + ); + + pte_swap_preload(VirtAddr::from(vaddr_swapped)).unwrap() + } + _ => panic!("No memory for mmap, check if huge memory leaky exists"), + }, + + Err(ecode) => panic!( + "Unexpected error {:x?} happening when page fault occurs!", + ecode + ), + } +} diff --git a/api/ruxos_posix_api/src/imp/stdio.rs b/api/ruxos_posix_api/src/imp/stdio.rs index 5d29c7a66..ecd85f44a 100644 --- a/api/ruxos_posix_api/src/imp/stdio.rs +++ b/api/ruxos_posix_api/src/imp/stdio.rs @@ -10,9 +10,15 @@ use axerrno::AxResult; use axio::{prelude::*, BufReader}; use axsync::Mutex; - #[cfg(feature = "fd")] -use {alloc::sync::Arc, axerrno::LinuxError, axerrno::LinuxResult, axio::PollState}; +use { + alloc::sync::Arc, + axerrno::AxError, + axerrno::LinuxError, + axerrno::LinuxResult, + axio::PollState, + core::sync::atomic::{AtomicBool, Ordering}, +}; fn console_read_bytes() -> Option { let ret = ruxhal::console::getchar().map(|c| if c == b'\r' { b'\n' } else { c }); @@ -58,6 +64,8 @@ impl Write for StdoutRaw { pub struct Stdin { inner: &'static Mutex>, + #[cfg(feature = "fd")] + nonblocking: AtomicBool, } impl Stdin { @@ -76,6 +84,17 @@ impl Stdin { crate::sys_sched_yield(); } } + + // Attempt a non-blocking read operation. + #[cfg(feature = "fd")] + fn read_nonblocked(&self, buf: &mut [u8]) -> AxResult { + if let Some(mut inner) = self.inner.try_lock() { + let read_len = inner.read(buf)?; + Ok(read_len) + } else { + Err(AxError::WouldBlock) + } + } } impl Read for Stdin { @@ -101,7 +120,11 @@ impl Write for Stdout { /// Constructs a new handle to the standard input of the current process. pub fn stdin() -> Stdin { static INSTANCE: Mutex> = Mutex::new(BufReader::new(StdinRaw)); - Stdin { inner: &INSTANCE } + Stdin { + inner: &INSTANCE, + #[cfg(feature = "fd")] + nonblocking: AtomicBool::from(false), + } } /// Constructs a new handle to the standard output of the current process. @@ -113,7 +136,10 @@ pub fn stdout() -> Stdout { #[cfg(feature = "fd")] impl super::fd_ops::FileLike for Stdin { fn read(&self, buf: &mut [u8]) -> LinuxResult { - Ok(self.read_blocked(buf)?) + match self.nonblocking.load(Ordering::Relaxed) { + true => Ok(self.read_nonblocked(buf)?), + false => Ok(self.read_blocked(buf)?), + } } fn write(&self, _buf: &[u8]) -> LinuxResult { @@ -141,7 +167,8 @@ impl super::fd_ops::FileLike for Stdin { }) } - fn set_nonblocking(&self, _nonblocking: bool) -> LinuxResult { + fn set_nonblocking(&self, nonblocking: bool) -> LinuxResult { + self.nonblocking.store(nonblocking, Ordering::Relaxed); Ok(()) } } diff --git a/api/ruxos_posix_api/src/lib.rs b/api/ruxos_posix_api/src/lib.rs index b3854200e..0a0a8debd 100644 --- a/api/ruxos_posix_api/src/lib.rs +++ b/api/ruxos_posix_api/src/lib.rs @@ -17,6 +17,7 @@ #![feature(doc_cfg)] #![feature(doc_auto_cfg)] #![allow(clippy::missing_safety_doc)] +#![cfg_attr(feature = "alloc", feature(btree_cursors))] #[macro_use] extern crate axlog; @@ -70,8 +71,8 @@ pub use imp::fd_ops::{sys_close, sys_dup, sys_dup2, sys_fcntl}; pub use imp::fs::{ sys_chdir, sys_faccessat, sys_fchownat, sys_fdatasync, sys_fstat, sys_fsync, sys_getcwd, sys_getdents64, sys_lseek, sys_lstat, sys_mkdir, sys_mkdirat, sys_newfstatat, sys_open, - sys_openat, sys_pread, sys_preadv, sys_readlinkat, sys_rename, sys_renameat, sys_rmdir, - sys_stat, sys_unlink, sys_unlinkat, + sys_openat, sys_pread64, sys_preadv, sys_pwrite64, sys_readlinkat, sys_rename, sys_renameat, + sys_rmdir, sys_stat, sys_unlink, sys_unlinkat, }; #[cfg(feature = "epoll")] pub use imp::io_mpx::{sys_epoll_create, sys_epoll_ctl, sys_epoll_pwait, sys_epoll_wait}; @@ -82,7 +83,7 @@ pub use imp::io_mpx::{sys_pselect6, sys_select}; #[cfg(feature = "fd")] pub use imp::ioctl::sys_ioctl; #[cfg(feature = "alloc")] -pub use imp::mmap::{sys_madvise, sys_mmap, sys_mprotect, sys_mremap, sys_munmap}; +pub use imp::mmap::{sys_madvise, sys_mmap, sys_mprotect, sys_mremap, sys_msync, sys_munmap}; #[cfg(feature = "net")] pub use imp::net::{ sys_accept, sys_bind, sys_connect, sys_freeaddrinfo, sys_getaddrinfo, sys_getpeername, diff --git a/apps/c/libc-bench/features.txt b/apps/c/libc-bench/features.txt index deb0a71d3..9dcdef8bc 100644 --- a/apps/c/libc-bench/features.txt +++ b/apps/c/libc-bench/features.txt @@ -1,3 +1,4 @@ alloc multitask fs +paging diff --git a/crates/page_table_entry/Cargo.toml b/crates/page_table_entry/Cargo.toml index a5a35dff2..2a86e6b7a 100644 --- a/crates/page_table_entry/Cargo.toml +++ b/crates/page_table_entry/Cargo.toml @@ -10,6 +10,7 @@ repository = "https://github.com/rcore-os/arceos/tree/main/crates/page_table_ent documentation = "https://rcore-os.github.io/arceos/page_table_entry/index.html" [dependencies] +log = "0.4" bitflags = "2.2" memory_addr = { path = "../memory_addr" } aarch64-cpu = "9.3" # TODO: put it in [target.'cfg(target_arch = "aarch64")'.dependencies] diff --git a/modules/ruxdriver/src/ixgbe.rs b/modules/ruxdriver/src/ixgbe.rs index e42b76fcb..2979065a9 100644 --- a/modules/ruxdriver/src/ixgbe.rs +++ b/modules/ruxdriver/src/ixgbe.rs @@ -10,7 +10,7 @@ use axalloc::global_allocator; use core::{alloc::Layout, ptr::NonNull}; use driver_net::ixgbe::{IxgbeHal, PhysAddr as IxgbePhysAddr}; -use ruxhal::mem::{phys_to_virt, virt_to_phys}; +use ruxhal::mem::{direct_virt_to_phys, phys_to_virt}; pub struct IxgbeHalImpl; @@ -22,7 +22,7 @@ unsafe impl IxgbeHal for IxgbeHalImpl { } else { return (0, NonNull::dangling()); }; - let paddr = virt_to_phys((vaddr.as_ptr() as usize).into()); + let paddr = direct_virt_to_phys((vaddr.as_ptr() as usize).into()); (paddr.as_usize(), vaddr) } @@ -37,7 +37,7 @@ unsafe impl IxgbeHal for IxgbeHalImpl { } unsafe fn mmio_virt_to_phys(vaddr: NonNull, _size: usize) -> IxgbePhysAddr { - virt_to_phys((vaddr.as_ptr() as usize).into()).into() + direct_virt_to_phys((vaddr.as_ptr() as usize).into()).into() } fn wait_until(duration: core::time::Duration) -> Result<(), &'static str> { diff --git a/modules/ruxdriver/src/virtio.rs b/modules/ruxdriver/src/virtio.rs index cf30b49e4..ec97412b5 100644 --- a/modules/ruxdriver/src/virtio.rs +++ b/modules/ruxdriver/src/virtio.rs @@ -14,7 +14,7 @@ use axalloc::global_allocator; use cfg_if::cfg_if; use driver_common::{BaseDriverOps, DevResult, DeviceType}; use driver_virtio::{BufferDirection, PhysAddr, VirtIoHal}; -use ruxhal::mem::{phys_to_virt, virt_to_phys}; +use ruxhal::mem::{direct_virt_to_phys, phys_to_virt, virt_to_phys}; use crate::{drivers::DriverProbe, AxDeviceEnum}; @@ -171,7 +171,7 @@ unsafe impl VirtIoHal for VirtIoHalImpl { } else { return (0, NonNull::dangling()); }; - let paddr = virt_to_phys(vaddr.into()); + let paddr = direct_virt_to_phys(vaddr.into()); let ptr = NonNull::new(vaddr as _).unwrap(); (paddr.as_usize(), ptr) } diff --git a/modules/ruxhal/src/arch/aarch64/mod.rs b/modules/ruxhal/src/arch/aarch64/mod.rs index 090ad3387..17afdc585 100644 --- a/modules/ruxhal/src/arch/aarch64/mod.rs +++ b/modules/ruxhal/src/arch/aarch64/mod.rs @@ -12,6 +12,7 @@ pub(crate) mod trap; use core::arch::asm; +use crate::mem::PAGE_SIZE_4K; use aarch64_cpu::registers::{DAIF, TPIDR_EL0, TTBR0_EL1, TTBR1_EL1, VBAR_EL1}; use memory_addr::{PhysAddr, VirtAddr}; use tock_registers::interfaces::{Readable, Writeable}; @@ -99,7 +100,7 @@ pub unsafe fn write_page_table_root0(root_paddr: PhysAddr) { pub fn flush_tlb(vaddr: Option) { unsafe { if let Some(vaddr) = vaddr { - asm!("tlbi vaae1is, {}; dsb sy; isb", in(reg) vaddr.as_usize()) + asm!("tlbi vaae1is, {}; dsb sy; isb", in(reg) vaddr.as_usize()/PAGE_SIZE_4K) } else { // flush the entire TLB asm!("tlbi vmalle1; dsb sy; isb") diff --git a/modules/ruxhal/src/arch/aarch64/trap.S b/modules/ruxhal/src/arch/aarch64/trap.S index 7167610ac..f06468287 100644 --- a/modules/ruxhal/src/arch/aarch64/trap.S +++ b/modules/ruxhal/src/arch/aarch64/trap.S @@ -48,6 +48,44 @@ add sp, sp, 34 * 8 .endm +save_neno_registers: + sub sp, sp, 50 * 8 + stp q0, q1, [sp, 0 * 16] + stp q2, q3, [sp, 2 * 16] + stp q4, q5, [sp, 4 * 16] + stp q6, q7, [sp, 6 * 16] + stp q16, q17, [sp, 8 * 16] + stp q18, q19, [sp, 10 * 16] + stp q20, q21, [sp, 12 * 16] + stp q22, q23, [sp, 14 * 16] + stp q24, q25, [sp, 16 * 16] + stp q26, q27, [sp, 18 * 16] + stp q28, q29, [sp, 20 * 16] + stp q30, q31, [sp, 22 * 16] + mrs x9, fpcr + mrs x10, fpsr + stp x9,x10, [sp, 48 * 8] + ret + +restore_neno_registers: + ldp q0, q1, [sp, 0 * 16] + ldp q2, q3, [sp, 2 * 16] + ldp q4, q5, [sp, 4 * 16] + ldp q6, q7, [sp, 6 * 16] + ldp q16, q17, [sp, 8 * 16] + ldp q18, q19, [sp, 10 * 16] + ldp q20, q21, [sp, 12 * 16] + ldp q22, q23, [sp, 14 * 16] + ldp q24, q25, [sp, 16 * 16] + ldp q26, q27, [sp, 18 * 16] + ldp q28, q29, [sp, 20 * 16] + ldp q30, q31, [sp, 22 * 16] + ldp x9,x10, [sp, 48 * 8] + msr fpcr, x9 + msr fpsr, x10 + add sp, sp, 50 * 8 + ret + .macro INVALID_EXCP, kind, source .p2align 7 SAVE_REGS @@ -62,7 +100,9 @@ .p2align 7 SAVE_REGS mov x0, sp + bl save_neno_registers bl handle_sync_exception + bl restore_neno_registers b .Lexception_return .endm diff --git a/modules/ruxhal/src/arch/aarch64/trap.rs b/modules/ruxhal/src/arch/aarch64/trap.rs index 5a863e6b7..431434f3a 100644 --- a/modules/ruxhal/src/arch/aarch64/trap.rs +++ b/modules/ruxhal/src/arch/aarch64/trap.rs @@ -11,6 +11,8 @@ use core::arch::global_asm; #[cfg(feature = "irq")] use crate::arch::enable_irqs; +#[cfg(feature = "paging")] +use crate::trap::PageFaultCause; use aarch64_cpu::registers::{ESR_EL1, FAR_EL1}; use tock_registers::interfaces::Readable; @@ -86,6 +88,28 @@ fn handle_sync_exception(tf: &mut TrapFrame) { Some(ESR_EL1::EC::Value::DataAbortCurrentEL) | Some(ESR_EL1::EC::Value::InstrAbortCurrentEL) => { let iss = esr.read(ESR_EL1::ISS); + #[cfg(feature = "paging")] + { + let vaddr = FAR_EL1.get() as usize; + + // this cause is coded like linux. + let cause: PageFaultCause = match esr.read_as_enum(ESR_EL1::EC) { + Some(ESR_EL1::EC::Value::DataAbortCurrentEL) => { + if iss & 0x40 != 0 { + PageFaultCause::WRITE // = store + } else { + PageFaultCause::READ // = load + } + } + _ => { + PageFaultCause::INSTRUCTION // = instruction fetch + } + }; + debug!("mapped vaddr in Page Fault: {:X} {:?}", vaddr, cause); + if crate::trap::handle_page_fault(vaddr, cause) { + return; + } + } panic!( "EL1 Page Fault @ {:#x}, FAR={:#x}, ISS={:#x}:\n{:#x?}", tf.elr, diff --git a/modules/ruxhal/src/mem.rs b/modules/ruxhal/src/mem.rs index 4f12a108e..b05409a6b 100644 --- a/modules/ruxhal/src/mem.rs +++ b/modules/ruxhal/src/mem.rs @@ -11,6 +11,8 @@ use core::fmt; +#[cfg(feature = "paging")] +use crate::paging::pte_query; #[doc(no_inline)] pub use memory_addr::{PhysAddr, VirtAddr, PAGE_SIZE_4K}; @@ -59,13 +61,28 @@ pub struct MemRegion { /// [`PHYS_VIRT_OFFSET`], that maps all the physical memory to the virtual /// space at the address plus the offset. So we have /// `paddr = vaddr - PHYS_VIRT_OFFSET`. +/// Usually only used when the page table is not enabled or linear mapping /// /// [`PHYS_VIRT_OFFSET`]: ruxconfig::PHYS_VIRT_OFFSET #[inline] -pub const fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr { +pub const fn direct_virt_to_phys(vaddr: VirtAddr) -> PhysAddr { PhysAddr::from(vaddr.as_usize() - ruxconfig::PHYS_VIRT_OFFSET) } +/// Converts a virtual address to a physical address. +/// +/// When paging is enabled, query physical address from the page table +#[inline] +pub fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr { + #[cfg(feature = "paging")] + match pte_query(vaddr) { + Ok((paddr, _, _)) => paddr, + Err(_) => PhysAddr::from(0_usize), // for address unmapped + } + #[cfg(not(feature = "paging"))] + direct_virt_to_phys(vaddr) +} + /// Converts a physical address to a virtual address. /// /// It assumes that there is a linear mapping with the offset @@ -88,31 +105,31 @@ pub fn memory_regions() -> impl Iterator { fn kernel_image_regions() -> impl Iterator { [ MemRegion { - paddr: virt_to_phys((_stext as usize).into()), + paddr: direct_virt_to_phys((_stext as usize).into()), size: _etext as usize - _stext as usize, flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::EXECUTE, name: ".text", }, MemRegion { - paddr: virt_to_phys((_srodata as usize).into()), + paddr: direct_virt_to_phys((_srodata as usize).into()), size: _erodata as usize - _srodata as usize, flags: MemRegionFlags::RESERVED | MemRegionFlags::READ, name: ".rodata", }, MemRegion { - paddr: virt_to_phys((_sdata as usize).into()), + paddr: direct_virt_to_phys((_sdata as usize).into()), size: _edata as usize - _sdata as usize, flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE, name: ".data .tdata .tbss .percpu", }, MemRegion { - paddr: virt_to_phys((boot_stack as usize).into()), + paddr: direct_virt_to_phys((boot_stack as usize).into()), size: boot_stack_top as usize - boot_stack as usize, flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE, name: "boot stack", }, MemRegion { - paddr: virt_to_phys((_sbss as usize).into()), + paddr: direct_virt_to_phys((_sbss as usize).into()), size: _ebss as usize - _sbss as usize, flags: MemRegionFlags::RESERVED | MemRegionFlags::READ | MemRegionFlags::WRITE, name: ".bss", @@ -138,7 +155,7 @@ pub(crate) fn default_mmio_regions() -> impl Iterator { /// Returns the default free memory regions (kernel image end to physical memory end). #[allow(dead_code)] pub(crate) fn default_free_regions() -> impl Iterator { - let start = virt_to_phys((_ekernel as usize).into()).align_up_4k(); + let start = direct_virt_to_phys((_ekernel as usize).into()).align_up_4k(); let end = PhysAddr::from(ruxconfig::PHYS_MEMORY_END).align_down_4k(); core::iter::once(MemRegion { paddr: start, diff --git a/modules/ruxhal/src/paging.rs b/modules/ruxhal/src/paging.rs index cd3faeabe..ae7754a2f 100644 --- a/modules/ruxhal/src/paging.rs +++ b/modules/ruxhal/src/paging.rs @@ -8,14 +8,19 @@ */ //! Page table manipulation. +extern crate alloc; +use crate::arch::flush_tlb; +use spinlock::SpinNoIrq; +use crate::mem::{ + direct_virt_to_phys, memory_regions, phys_to_virt, MemRegionFlags, PhysAddr, VirtAddr, + PAGE_SIZE_4K, +}; use axalloc::global_allocator; -use page_table::PagingIf; - -use crate::mem::{phys_to_virt, virt_to_phys, MemRegionFlags, PhysAddr, VirtAddr, PAGE_SIZE_4K}; +use lazy_init::LazyInit; #[doc(no_inline)] -pub use page_table::{MappingFlags, PageSize, PagingError, PagingResult}; +use page_table::{MappingFlags, PageSize, PagingError, PagingIf, PagingResult}; impl From for MappingFlags { fn from(f: MemRegionFlags) -> Self { @@ -47,7 +52,7 @@ impl PagingIf for PagingIfImpl { fn alloc_frame() -> Option { global_allocator() .alloc_pages(1, PAGE_SIZE_4K) - .map(|vaddr| virt_to_phys(vaddr.into())) + .map(|vaddr| direct_virt_to_phys(vaddr.into())) .ok() } @@ -73,3 +78,111 @@ cfg_if::cfg_if! { pub type PageTable = page_table::aarch64::A64PageTable; } } + +pub(crate) static KERNEL_PAGE_TABLE: LazyInit> = LazyInit::new(); + +/// Remap the regions for kernel memory +pub fn remap_kernel_memory() -> PagingResult { + if crate::cpu::this_cpu_is_bsp() { + let mut kernel_page_table = PageTable::try_new()?; + for r in memory_regions() { + kernel_page_table.map_region( + phys_to_virt(r.paddr), + r.paddr, + r.size, + r.flags.into(), + true, + )?; + } + + KERNEL_PAGE_TABLE.init_by(SpinNoIrq::new(kernel_page_table)); + } + unsafe { crate::arch::write_page_table_root(KERNEL_PAGE_TABLE.lock().root_paddr()) }; + Ok(()) +} + +/// Temporarily, `malloc` alloc memory in heap simply, and it can not be swapped +/// into swap file. Once the memory is not enough with all memory alloced, it +/// will be too late, as there will be no memory for `malloc` any more. In practice, +/// this is highly likely to cause errors of insufficient memory. To prevent this, +/// mmapping will not alloc from physical address to avoid this. +/// +/// After the page of `malloc` can be swapped, or it raises a propriately handler +/// to swap page when memory is not enough, it will be okay to delete this. +const PAGE_NUM_MIN: usize = 1024; + +/// Obtain fake VirtAddr addresses without performing virtual memory mapping +/// to prevent physical competition between multiple threads. +/// After call the function. the page is alloced in allocator but its virtual +/// address is still on linear mapping region. +/// use `do_pte_map` to do actually page mapping after call this function. +pub fn alloc_page_preload() -> Result { + if global_allocator().available_pages() < PAGE_NUM_MIN { + warn!( + "available page num is {:?}", + global_allocator().available_pages() + ); + return Err(PagingError::NoMemory); + }; + match global_allocator().alloc_pages(1, PAGE_SIZE_4K) { + Ok(fake_vaddr) => Ok(VirtAddr::from(fake_vaddr)), + Err(_) => Err(PagingError::NoMemory), + } +} + +/// Unmap memory for an mmap-induced PageFault and updating PTE entries. +/// After call the function. the page is alloced in allocator but its virtual +/// address is still on linear mapping region. +/// use `do_pte_map` to do actually page mapping after call this function. +pub fn pte_swap_preload(swaped_vaddr: VirtAddr) -> PagingResult { + trace!("swapping swaped_vaddr: {:x?}", swaped_vaddr,); + let mut kernel_page_table = KERNEL_PAGE_TABLE.lock(); + let (paddr, _) = kernel_page_table.unmap(swaped_vaddr)?; + flush_tlb(Some(swaped_vaddr)); + Ok(phys_to_virt(paddr)) +} + +/// Map memory for an mmap-induced PageFault and updating PTE entries, +/// This function must be called after `alloc_page_preload` and +/// `pte_swap_preload` when the mapping operator is ready. +pub fn do_pte_map(vaddr: VirtAddr, fake_vaddr: VirtAddr, flags: MappingFlags) -> PagingResult { + KERNEL_PAGE_TABLE.lock().map( + vaddr, + direct_virt_to_phys(fake_vaddr), + PageSize::Size4K, + flags, + ) +} + +/// Query PTE entries of the virtual address. +/// +/// get the physical address information corresponding to the virtual address from the page table +pub fn pte_query(vaddr: VirtAddr) -> PagingResult<(PhysAddr, MappingFlags, PageSize)> { + let kernel_page_table = KERNEL_PAGE_TABLE.lock(); + kernel_page_table.query(vaddr) +} + +/// Update flags or physical address for an PTE entries. +/// +/// change the physical address or access permissions mapped by the virtual address +pub fn pte_update_page( + vaddr: VirtAddr, + paddr: Option, + flags: Option, +) -> PagingResult { + trace!("updating vaddr: {:x?} {:x?} {:x?}", vaddr, paddr, flags); + KERNEL_PAGE_TABLE.lock().update(vaddr, paddr, flags)?; + flush_tlb(Some(vaddr)); + Ok(()) +} + +/// Unmapping and decalloc memory for an page in page table. +/// +/// release the corresponding memory at the same time +pub fn pte_unmap_page(vaddr: VirtAddr) -> PagingResult { + trace!("unmapping vaddr: {:x?}", vaddr); + let (paddr, _) = KERNEL_PAGE_TABLE.lock().unmap(vaddr)?; + global_allocator().dealloc_pages(phys_to_virt(paddr).as_usize(), 1); + flush_tlb(Some(vaddr)); + Ok(()) +} diff --git a/modules/ruxhal/src/platform/aarch64_qemu_virt/mp.rs b/modules/ruxhal/src/platform/aarch64_qemu_virt/mp.rs index 95c6a3bb9..3f8be002e 100644 --- a/modules/ruxhal/src/platform/aarch64_qemu_virt/mp.rs +++ b/modules/ruxhal/src/platform/aarch64_qemu_virt/mp.rs @@ -7,13 +7,13 @@ * See the Mulan PSL v2 for more details. */ -use crate::mem::{virt_to_phys, PhysAddr, VirtAddr}; +use crate::mem::{direct_virt_to_phys, PhysAddr, VirtAddr}; /// Starts the given secondary CPU with its boot stack. pub fn start_secondary_cpu(cpu_id: usize, stack_top: PhysAddr) { extern "C" { fn _start_secondary(); } - let entry = virt_to_phys(VirtAddr::from(_start_secondary as usize)); + let entry = direct_virt_to_phys(VirtAddr::from(_start_secondary as usize)); crate::platform::aarch64_common::psci::cpu_on(cpu_id, entry.as_usize(), stack_top.as_usize()); } diff --git a/modules/ruxhal/src/platform/aarch64_raspi/mp.rs b/modules/ruxhal/src/platform/aarch64_raspi/mp.rs index e8a8fcf99..bfd89e06d 100644 --- a/modules/ruxhal/src/platform/aarch64_raspi/mp.rs +++ b/modules/ruxhal/src/platform/aarch64_raspi/mp.rs @@ -6,7 +6,7 @@ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. */ -use crate::mem::{phys_to_virt, virt_to_phys, PhysAddr, VirtAddr}; +use crate::mem::{direct_virt_to_phys, phys_to_virt, PhysAddr, VirtAddr}; static mut SECONDARY_STACK_TOP: usize = 0; @@ -39,7 +39,8 @@ pub static CPU_SPIN_TABLE: [PhysAddr; 4] = [ /// Starts the given secondary CPU with its boot stack. pub fn start_secondary_cpu(cpu_id: usize, stack_top: PhysAddr) { - let entry_paddr = virt_to_phys(VirtAddr::from(modify_stack_and_start as usize)).as_usize(); + let entry_paddr = + direct_virt_to_phys(VirtAddr::from(modify_stack_and_start as usize)).as_usize(); unsafe { // set the boot code address of the given secondary CPU let spintable_vaddr = phys_to_virt(CPU_SPIN_TABLE[cpu_id]); diff --git a/modules/ruxhal/src/platform/riscv64_qemu_virt/mp.rs b/modules/ruxhal/src/platform/riscv64_qemu_virt/mp.rs index 0f2a093ad..1db69cf5f 100644 --- a/modules/ruxhal/src/platform/riscv64_qemu_virt/mp.rs +++ b/modules/ruxhal/src/platform/riscv64_qemu_virt/mp.rs @@ -7,7 +7,7 @@ * See the Mulan PSL v2 for more details. */ -use crate::mem::{virt_to_phys, PhysAddr, VirtAddr}; +use crate::mem::{direct_virt_to_phys, PhysAddr, VirtAddr}; /// Starts the given secondary CPU with its boot stack. pub fn start_secondary_cpu(hartid: usize, stack_top: PhysAddr) { @@ -18,6 +18,6 @@ pub fn start_secondary_cpu(hartid: usize, stack_top: PhysAddr) { warn!("HSM SBI extension is not supported for current SEE."); return; } - let entry = virt_to_phys(VirtAddr::from(_start_secondary as usize)); + let entry = direct_virt_to_phys(VirtAddr::from(_start_secondary as usize)); sbi_rt::hart_start(hartid, entry.as_usize(), stack_top.as_usize()); } diff --git a/modules/ruxhal/src/trap.rs b/modules/ruxhal/src/trap.rs index ea145654a..344ca06ac 100644 --- a/modules/ruxhal/src/trap.rs +++ b/modules/ruxhal/src/trap.rs @@ -8,9 +8,19 @@ */ //! Trap handling. - use crate_interface::{call_interface, def_interface}; +/// Several reasons for page missing exceptions. +#[derive(Debug)] +pub enum PageFaultCause { + /// pageFault caused by memory WRITE. + WRITE, + /// pageFault caused by memory READ. + READ, + /// pageFault caused by INSTRUCTION fetch. + INSTRUCTION, +} + /// Trap handler interface. /// /// This trait is defined with the [`#[def_interface]`][1] attribute. Users @@ -21,11 +31,19 @@ use crate_interface::{call_interface, def_interface}; #[def_interface] pub trait TrapHandler { /// Handles interrupt requests for the given IRQ number. - fn handle_irq(irq_num: usize); + fn handle_irq(_irq_num: usize) { + panic!("No handle_irq implement"); + } /// Handles system call from user app. #[cfg(feature = "musl")] - fn handle_syscall(syscall_id: usize, args: [usize; 6]) -> isize; - // more e.g.: handle_page_fault(); + fn handle_syscall(_syscall_id: usize, _args: [usize; 6]) -> isize { + panic!("No handle_syscall implement"); + } + /// Handles page fault for mmap. + #[cfg(feature = "paging")] + fn handle_page_fault(_vaddr: usize, _caus: PageFaultCause) -> bool { + panic!("No handle_page_fault implement"); + } } /// Call the external IRQ handler. @@ -40,3 +58,10 @@ pub(crate) fn handle_irq_extern(irq_num: usize) { pub(crate) fn handle_syscall(syscall_id: usize, args: [usize; 6]) -> isize { call_interface!(TrapHandler::handle_syscall, syscall_id, args) } + +/// Call the external IRQ handler. +#[allow(dead_code)] +#[cfg(feature = "paging")] +pub(crate) fn handle_page_fault(vaddr: usize, cause: PageFaultCause) -> bool { + call_interface!(TrapHandler::handle_page_fault, vaddr, cause) +} diff --git a/modules/ruxruntime/src/lib.rs b/modules/ruxruntime/src/lib.rs index 80701e284..f481f1fdf 100644 --- a/modules/ruxruntime/src/lib.rs +++ b/modules/ruxruntime/src/lib.rs @@ -388,30 +388,7 @@ fn init_allocator() { } #[cfg(feature = "paging")] -fn remap_kernel_memory() -> Result<(), ruxhal::paging::PagingError> { - use lazy_init::LazyInit; - use ruxhal::mem::{memory_regions, phys_to_virt}; - use ruxhal::paging::PageTable; - - static KERNEL_PAGE_TABLE: LazyInit = LazyInit::new(); - - if ruxhal::cpu::this_cpu_is_bsp() { - let mut kernel_page_table = PageTable::try_new()?; - for r in memory_regions() { - kernel_page_table.map_region( - phys_to_virt(r.paddr), - r.paddr, - r.size, - r.flags.into(), - true, - )?; - } - KERNEL_PAGE_TABLE.init_by(kernel_page_table); - } - - unsafe { ruxhal::arch::write_page_table_root(KERNEL_PAGE_TABLE.root_paddr()) }; - Ok(()) -} +use ruxhal::paging::remap_kernel_memory; #[cfg(feature = "irq")] fn init_interrupt() { diff --git a/modules/ruxruntime/src/mp.rs b/modules/ruxruntime/src/mp.rs index 9e3e6be29..7b6025541 100644 --- a/modules/ruxruntime/src/mp.rs +++ b/modules/ruxruntime/src/mp.rs @@ -9,7 +9,7 @@ use core::sync::atomic::{AtomicUsize, Ordering}; use ruxconfig::{SMP, TASK_STACK_SIZE}; -use ruxhal::mem::{virt_to_phys, VirtAddr}; +use ruxhal::mem::{direct_virt_to_phys, VirtAddr}; #[link_section = ".bss.stack"] static mut SECONDARY_BOOT_STACK: [[u8; TASK_STACK_SIZE]; SMP - 1] = [[0; TASK_STACK_SIZE]; SMP - 1]; @@ -20,7 +20,7 @@ pub fn start_secondary_cpus(primary_cpu_id: usize) { let mut logic_cpu_id = 0; for i in 0..SMP { if i != primary_cpu_id { - let stack_top = virt_to_phys(VirtAddr::from(unsafe { + let stack_top = direct_virt_to_phys(VirtAddr::from(unsafe { SECONDARY_BOOT_STACK[logic_cpu_id].as_ptr_range().end as usize })); diff --git a/platforms/aarch64-qemu-virt.toml b/platforms/aarch64-qemu-virt.toml index 7ff8fbb0d..95016c294 100644 --- a/platforms/aarch64-qemu-virt.toml +++ b/platforms/aarch64-qemu-virt.toml @@ -19,6 +19,10 @@ phys-memory-size = "0x8000_0000" # 2G kernel-base-paddr = "0x4008_0000" # Base virtual address of the kernel image. kernel-base-vaddr = "0xffff_0000_4008_0000" +# virtual start address of the mapping memory. +mmap-start-vaddr = "0xffff_8000_0000_0000" +# virtual end address of the mapping memory. +mmap-end-vaddr = "0xffff_f000_0000_0000" # Linear mapping offset, for quick conversions between physical and virtual # addresses. phys-virt-offset = "0xffff_0000_0000_0000" diff --git a/platforms/aarch64-raspi4.toml b/platforms/aarch64-raspi4.toml index 710b24c7a..ef2e20cc8 100644 --- a/platforms/aarch64-raspi4.toml +++ b/platforms/aarch64-raspi4.toml @@ -13,6 +13,10 @@ phys-memory-size = "0xFC00_0000" # 3G 960M kernel-base-paddr = "0x8_0000" # Base virtual address of the kernel image. kernel-base-vaddr = "0xffff_0000_0008_0000" +# virtual start address of the mapping memory. +mmap-start-vaddr = "0xffff_8000_0000_0000" +# virtual end address of the mapping memory. +mmap-end-vaddr = "0xffff_f000_0000_0000" # Linear mapping offset, for quick conversions between physical and virtual # addresses. phys-virt-offset = "0xffff_0000_0000_0000" diff --git a/platforms/riscv64-qemu-virt.toml b/platforms/riscv64-qemu-virt.toml index 2c0e69ce0..f6a58a447 100644 --- a/platforms/riscv64-qemu-virt.toml +++ b/platforms/riscv64-qemu-virt.toml @@ -14,6 +14,10 @@ phys-memory-size = "0x8000_0000" # 2G kernel-base-paddr = "0x8020_0000" # Base virtual address of the kernel image. kernel-base-vaddr = "0xffff_ffc0_8020_0000" +# virtual start address of the mapping memory. +mmap-start-vaddr = "0xffff_8000_0000_0000" +# virtual end address of the mapping memory. +mmap-end-vaddr = "0xffff_f000_0000_0000" # Linear mapping offset, for quick conversions between physical and virtual # addresses. phys-virt-offset = "0xffff_ffc0_0000_0000" diff --git a/platforms/x86_64-qemu-q35.toml b/platforms/x86_64-qemu-q35.toml index 78fa13af5..a3a119758 100644 --- a/platforms/x86_64-qemu-q35.toml +++ b/platforms/x86_64-qemu-q35.toml @@ -14,6 +14,10 @@ phys-memory-size = "0x8000_0000" # 2G kernel-base-paddr = "0x20_0000" # Base virtual address of the kernel image. kernel-base-vaddr = "0xffff_ff80_0020_0000" +# virtual start address of the mapping memory. +mmap-start-vaddr = "0xffff_8000_0000_0000" +# virtual end address of the mapping memory. +mmap-end-vaddr = "0xffff_f000_0000_0000" # Linear mapping offset, for quick conversions between physical and virtual # addresses. phys-virt-offset = "0xffff_ff80_0000_0000" diff --git a/scripts/make/build_musl.mk b/scripts/make/build_musl.mk index 9c8af1318..018967e57 100644 --- a/scripts/make/build_musl.mk +++ b/scripts/make/build_musl.mk @@ -15,7 +15,7 @@ CFLAGS += -isystem$(CURDIR)/$(inc_dir) LDFLAGS += -nostdlib -static -no-pie --gc-sections -T$(LD_SCRIPT) ifeq ($(MODE), release) - CFLAGS += -O3 + CFLAGS += -O3 else ifeq ($(MODE), reldebug) CFLAGS += -O3 -g else diff --git a/scripts/make/features.mk b/scripts/make/features.mk index 8c5f63cff..6c605bb9f 100644 --- a/scripts/make/features.mk +++ b/scripts/make/features.mk @@ -18,7 +18,7 @@ ifeq ($(APP_TYPE),c) else lib_feat_prefix := ruxlibc/ endif - lib_features := fp_simd alloc multitask fs net fd pipe select poll epoll random-hw signal + lib_features := fp_simd alloc paging multitask fs net fd pipe select poll epoll random-hw signal else # TODO: it's better to use `ruxfeat/` as `ax_feat_prefix`, but all apps need to have `ruxfeat` as a dependency ax_feat_prefix := axstd/ diff --git a/ulib/ruxlibc/Cargo.toml b/ulib/ruxlibc/Cargo.toml index 870bb3d38..196ed6cdf 100644 --- a/ulib/ruxlibc/Cargo.toml +++ b/ulib/ruxlibc/Cargo.toml @@ -29,6 +29,7 @@ fp_simd = ["ruxfeat/fp_simd"] # Memory alloc = ["ruxos_posix_api/alloc"] +paging = ["alloc", "ruxos_posix_api/paging"] tls = ["alloc", "ruxfeat/tls"] # Multi-task diff --git a/ulib/ruxlibc/c/mmap.c b/ulib/ruxlibc/c/mmap.c deleted file mode 100644 index c106e2a62..000000000 --- a/ulib/ruxlibc/c/mmap.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (c) [2023] [Syswonder Community] - * [Ruxos] is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A - * PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. - */ - -#include -#include -#include -#include - -// TODO: -void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off) -{ - if (fildes != -1) { - unimplemented(); - return MAP_FAILED; - } - return malloc(len); -} - -// TODO: -int munmap(void *addr, size_t length) -{ - if (addr == NULL) - return 0; - free(addr); - return 0; -} - -// TODO: -void *mremap(void *old_address, size_t old_size, size_t new_size, int flags, - ... /* void *new_address */) -{ - unimplemented(); - return NULL; -} - -// TODO -int mprotect(void *addr, size_t len, int prot) -{ - unimplemented(); - return 0; -} - -// TODO -int madvise(void *addr, size_t len, int advice) -{ - unimplemented(); - return 0; -} diff --git a/ulib/ruxlibc/include/sys/mman.h b/ulib/ruxlibc/include/sys/mman.h index 7517bf251..29849ccca 100644 --- a/ulib/ruxlibc/include/sys/mman.h +++ b/ulib/ruxlibc/include/sys/mman.h @@ -44,6 +44,8 @@ #define MAP_HUGE_SHIFT 26 #define MAP_HUGE_MASK 0x3f +#define MS_SYNC 0 + #define MAP_FAILED ((void *)-1) /* Flags for mremap. */ diff --git a/ulib/ruxlibc/src/lib.rs b/ulib/ruxlibc/src/lib.rs index 3ecaa4913..160566cff 100644 --- a/ulib/ruxlibc/src/lib.rs +++ b/ulib/ruxlibc/src/lib.rs @@ -68,6 +68,8 @@ mod fs; mod io_mpx; #[cfg(feature = "alloc")] mod malloc; +#[cfg(feature = "alloc")] +mod mmap; #[cfg(feature = "net")] mod net; #[cfg(feature = "pipe")] @@ -121,6 +123,8 @@ pub use self::io_mpx::select; pub use self::io_mpx::{epoll_create, epoll_ctl, epoll_wait}; #[cfg(feature = "alloc")] pub use self::malloc::{free, malloc}; +#[cfg(feature = "alloc")] +pub use self::mmap::{mmap, munmap}; #[cfg(feature = "net")] pub use self::net::{ accept, ax_sendmsg, bind, connect, freeaddrinfo, getaddrinfo, getpeername, getsockname, listen, diff --git a/ulib/ruxlibc/src/mmap.rs b/ulib/ruxlibc/src/mmap.rs new file mode 100644 index 000000000..4573e2cfc --- /dev/null +++ b/ulib/ruxlibc/src/mmap.rs @@ -0,0 +1,64 @@ +/* Copyright (c) [2023] [Syswonder Community] + * [Ruxos] is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +use crate::ctypes; +use core::ffi::{c_int, c_void}; + +use ruxos_posix_api::{sys_madvise, sys_mmap, sys_mprotect, sys_mremap, sys_msync, sys_munmap}; + +/// Map a file or device into virtual memory. +#[no_mangle] +pub unsafe extern "C" fn mmap( + addr: *mut c_void, + len: ctypes::size_t, + prot: c_int, + flags: c_int, + fid: c_int, + offset: ctypes::off_t, +) -> *mut c_void { + sys_mmap(addr, len, prot, flags, fid, offset) +} + +/// Unmap a range address of memory. +#[no_mangle] +pub unsafe extern "C" fn munmap(addr: *mut c_void, len: ctypes::size_t) -> c_int { + sys_munmap(addr, len) +} + +/// Sync pages mapped in memory to file. +#[no_mangle] +pub unsafe extern "C" fn msync(addr: *mut c_void, len: ctypes::size_t, flags: c_int) -> c_int { + sys_msync(addr, len, flags) +} + +/// Remap the address for already mapped memory. +#[no_mangle] +pub unsafe extern "C" fn mremap( + old_addr: *mut c_void, + old_size: ctypes::size_t, + new_size: ctypes::size_t, + flags: c_int, + new_addr: *mut c_void, +) -> *mut c_void { + sys_mremap(old_addr, old_size, new_size, flags, new_addr) +} + +/// Change the accessiblity for already mapped memory. +#[no_mangle] +pub unsafe extern "C" fn mprotect(addr: *mut c_void, len: ctypes::size_t, flags: c_int) -> c_int { + sys_mprotect(addr, len, flags) +} + +/// Advise the operating system about the expected behavior of a specific region of memory. +/// +/// Note: Unimplement yet. +#[no_mangle] +pub unsafe extern "C" fn madvise(addr: *mut c_void, len: ctypes::size_t, advice: c_int) -> c_int { + sys_madvise(addr, len, advice) +} diff --git a/ulib/ruxmusl/Cargo.toml b/ulib/ruxmusl/Cargo.toml index ca56428b1..77b5855b4 100644 --- a/ulib/ruxmusl/Cargo.toml +++ b/ulib/ruxmusl/Cargo.toml @@ -22,6 +22,7 @@ fp_simd = ["ruxfeat/fp_simd"] # Memory alloc = ["ruxos_posix_api/alloc"] +paging = ["alloc", "ruxos_posix_api/paging"] tls = ["alloc", "ruxfeat/tls"] # Multi-task diff --git a/ulib/ruxmusl/src/aarch64/mod.rs b/ulib/ruxmusl/src/aarch64/mod.rs index 9fc21c937..a1dbe05f4 100644 --- a/ulib/ruxmusl/src/aarch64/mod.rs +++ b/ulib/ruxmusl/src/aarch64/mod.rs @@ -129,7 +129,14 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { args[2] as c_int, ) as _, #[cfg(feature = "fs")] - SyscallId::PREAD64 => ruxos_posix_api::sys_pread( + SyscallId::PREAD64 => ruxos_posix_api::sys_pread64( + args[0] as c_int, + args[1] as *mut core::ffi::c_void, + args[2] as ctypes::size_t, + args[3] as ctypes::off_t, + ) as _, + #[cfg(feature = "fs")] + SyscallId::PWRITE64 => ruxos_posix_api::sys_pwrite64( args[0] as c_int, args[1] as *mut core::ffi::c_void, args[2] as ctypes::size_t, @@ -385,6 +392,12 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { args[1] as ctypes::size_t, args[2] as c_int, ) as _, + #[cfg(feature = "alloc")] + SyscallId::MSYNC => ruxos_posix_api::sys_msync( + args[0] as *mut core::ffi::c_void, + args[1] as ctypes::size_t, + args[2] as c_int, + ) as _, SyscallId::PRLIMIT64 => ruxos_posix_api::sys_prlimit64( args[0] as ctypes::pid_t, args[1] as c_int, diff --git a/ulib/ruxmusl/src/aarch64/syscall_id.rs b/ulib/ruxmusl/src/aarch64/syscall_id.rs index 6c2b38665..c4b8e4307 100644 --- a/ulib/ruxmusl/src/aarch64/syscall_id.rs +++ b/ulib/ruxmusl/src/aarch64/syscall_id.rs @@ -54,6 +54,8 @@ pub enum SyscallId { #[cfg(feature = "fs")] PREAD64 = 67, #[cfg(feature = "fs")] + PWRITE64 = 68, + #[cfg(feature = "fs")] PREADV = 69, #[cfg(feature = "select")] PSELECT6 = 72, @@ -140,9 +142,11 @@ pub enum SyscallId { #[cfg(feature = "alloc")] MMAP = 222, #[cfg(feature = "alloc")] - MADVISE = 233, - #[cfg(feature = "alloc")] MPROTECT = 226, + #[cfg(feature = "alloc")] + MSYNC = 227, + #[cfg(feature = "alloc")] + MADVISE = 233, PRLIMIT64 = 261, GETRANDOM = 278, } diff --git a/ulib/ruxmusl/src/x86_64/mod.rs b/ulib/ruxmusl/src/x86_64/mod.rs index 9d5ed0089..fa7a35fd6 100644 --- a/ulib/ruxmusl/src/x86_64/mod.rs +++ b/ulib/ruxmusl/src/x86_64/mod.rs @@ -104,7 +104,15 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { SyscallId::IOCTL => ruxos_posix_api::sys_ioctl(args[0] as c_int, args[1], args[2]) as _, #[cfg(feature = "fs")] - SyscallId::PREAD64 => ruxos_posix_api::sys_pread( + SyscallId::PREAD64 => ruxos_posix_api::sys_pread64( + args[0] as c_int, + args[1] as *mut c_void, + args[2] as ctypes::size_t, + args[3] as ctypes::off_t, + ) as _, + + #[cfg(feature = "fs")] + SyscallId::PWRITE64 => ruxos_posix_api::sys_pwrite64( args[0] as c_int, args[1] as *mut c_void, args[2] as ctypes::size_t, @@ -151,6 +159,13 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { args[4] as *mut core::ffi::c_void, ) as _, + #[cfg(feature = "alloc")] + SyscallId::MSYNC => ruxos_posix_api::sys_msync( + args[0] as *mut core::ffi::c_void, + args[1] as ctypes::size_t, + args[2] as c_int, + ) as _, + #[cfg(feature = "alloc")] SyscallId::MADVISE => { ruxos_posix_api::sys_madvise(args[0] as *mut c_void, args[1], args[2] as c_int) as _ diff --git a/ulib/ruxmusl/src/x86_64/syscall_id.rs b/ulib/ruxmusl/src/x86_64/syscall_id.rs index d0493c156..1526154cb 100644 --- a/ulib/ruxmusl/src/x86_64/syscall_id.rs +++ b/ulib/ruxmusl/src/x86_64/syscall_id.rs @@ -53,6 +53,9 @@ pub enum SyscallId { #[cfg(feature = "fs")] PREAD64 = 17, + #[cfg(feature = "fs")] + PWRITE64 = 18, + #[cfg(feature = "fd")] READV = 19, @@ -70,6 +73,9 @@ pub enum SyscallId { #[cfg(feature = "alloc")] MREMAP = 25, + #[cfg(feature = "alloc")] + MSYNC = 26, + #[cfg(feature = "alloc")] MADVISE = 28, From 24d8d448bf3f40a0113217d9ceb94d0c60c93e0a Mon Sep 17 00:00:00 2001 From: AuYang261 <459461160@qq.com> Date: Tue, 9 Apr 2024 14:20:23 +0800 Subject: [PATCH 07/13] modify c++ benchmark --- apps/c/cpp/axbuild.mk | 7 ++--- apps/c/cpp/std_benchmark.patch | 53 +++++++++++++++++++++++++++------- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/apps/c/cpp/axbuild.mk b/apps/c/cpp/axbuild.mk index 37e8ea604..36003edaa 100644 --- a/apps/c/cpp/axbuild.mk +++ b/apps/c/cpp/axbuild.mk @@ -13,8 +13,7 @@ std_benchmark_dir := $(APP)/std-benchmark std_benchmark_build = $(std_benchmark_dir)/build bench ?= all -benches_available := $(wildcard $(std_benchmark_dir)/cxx/*.bench.cpp) -benches_available := $(patsubst $(std_benchmark_dir)/cxx/%.bench.cpp,%,$(benches_available)) +benches_available := accessors algorithm mutators size_metric string stringstream $(std_benchmark_dir): @echo "Download std-benchmark source code" @@ -31,7 +30,7 @@ build_std-benchmark: $(std_benchmark_dir) $(APP)/axbuild.mk ln -s -f $(CROSS_COMPILE_PATH)/lib/gcc/*-linux-musl/*/libgcc.a ./ && \ $(AR) x libgcc.a _clrsbsi2.o ifeq ($(bench), all) - $(error "Running all benches automatically is not supported, please add 'bench=' arg. \ + $(error "Running all benches automatically is not supported currently, please add 'bench=' arg. \ Available benches: $(benches_available)") endif ifneq ($(filter $(bench),$(benches_available)),) @@ -49,5 +48,3 @@ clean_c:: rm -rf $(std_benchmark_build)/ .PHONY: build_std-benchmark clean_c - - diff --git a/apps/c/cpp/std_benchmark.patch b/apps/c/cpp/std_benchmark.patch index 55e03db0b..7b9cb5d53 100644 --- a/apps/c/cpp/std_benchmark.patch +++ b/apps/c/cpp/std_benchmark.patch @@ -55,16 +55,7 @@ v.insert(v.begin(), val); } state.SetComplexityN(N); -@@ -94,14 +95,15 @@ void BM_assoc_insert_random(benchmark::State& state) { - int N = state.range(0); - using CVT = typename V::value_type; - using VT = typename remove_const::type; -- std::vector temp(N*1000); -+ // TODO: It will panic if *100 or *1000 -+ std::vector temp(N*10); - fill_random(temp); - V v; - auto it = temp.begin(); +@@ -101,7 +101,7 @@ void BM_assoc_insert_random(benchmark::State& state) { while (state.KeepRunning()) { v.insert(*it++); if (it == temp.end()) // FIXME: After temp.end insert will just return. @@ -73,6 +64,29 @@ } state.SetComplexityN(N); } +--- /cxx/size_metric.bench.cpp ++++ /cxx/size_metric.bench.cpp +@@ -7,6 +7,8 @@ + #include + #include + ++#include "test_configs.h" ++ + #define GETNAME(T) #T + + template +--- /cxx/string.bench.cpp ++++ /cxx/string.bench.cpp +@@ -77,7 +77,8 @@ static void BM_strcat(benchmark::State& state) { + benchmark::DoNotOptimize(s1.append(s2)); + s1_sz += s2_sz; + if (s1_sz >= N) { +- // ++ s1_sz = 1; ++ s1 = std::string(N, 0); + } + } + state.SetComplexityN(N); --- /include/test_configs.h +++ /include/test_configs.h @@ -1,6 +1,8 @@ @@ -107,3 +121,22 @@ if(NOT HAVE_STD_REGEX AND NOT HAVE_GNU_POSIX_REGEX AND NOT HAVE_POSIX_REGEX) message(FATAL_ERROR "Failed to determine the source files for the regular expression backend") endif() +--- /include/rng_utils.h ++++ /include/rng_utils.h +@@ -30,9 +30,9 @@ template using gen = typename uniform_distribution::type; + + class random_device { + public: ++ random_device() : e(rd()) {} + template + T get_rand(T min, T max) { +- std::mt19937 e(rd()); // seed the generator + gen d(min, max); // define the range + return d(e); + } +@@ -40,6 +40,7 @@ public: + private: + // TODO: Fix the seed to a constant. + std::random_device rd; // obtain a random number from hardware ++ std::mt19937 e; // seed the generator + }; From 1416cfd5fcf6e1f3793fc004e4a09fbd06c88f8b Mon Sep 17 00:00:00 2001 From: wuzheng Date: Wed, 10 Apr 2024 20:08:26 +0800 Subject: [PATCH 08/13] fix bugs in munmap and warnings for clippy --- api/ruxos_posix_api/src/imp/mmap/api.rs | 75 +++++++++++++------ api/ruxos_posix_api/src/imp/mmap/trap.rs | 6 +- api/ruxos_posix_api/src/imp/mmap/utils.rs | 57 +++++++++++++- api/ruxos_posix_api/src/imp/stdio.rs | 5 +- modules/axnet/src/smoltcp_impl/tcp.rs | 2 - modules/ruxhal/src/paging.rs | 11 ++- .../src/platform/aarch64_common/pl031.rs | 4 +- ulib/ruxlibc/src/io.rs | 4 +- ulib/ruxmusl/src/lib.rs | 1 + ulib/ruxmusl/src/trap.rs | 2 +- ulib/ruxmusl/src/x86_64/mod.rs | 3 + 11 files changed, 133 insertions(+), 37 deletions(-) diff --git a/api/ruxos_posix_api/src/imp/mmap/api.rs b/api/ruxos_posix_api/src/imp/mmap/api.rs index ba5c8bee4..9b6ce2212 100644 --- a/api/ruxos_posix_api/src/imp/mmap/api.rs +++ b/api/ruxos_posix_api/src/imp/mmap/api.rs @@ -19,7 +19,7 @@ use ruxhal::{mem::VirtAddr, paging::pte_update_page}; use super::utils::{ find_free_region, get_mflags_from_usize, get_overlap, release_pages_mapped, shift_mapped_page, - Vma, MEM_MAP, VMA_END, VMA_MAP, + snatch_fixed_region, Vma, MEM_MAP, VMA_END, VMA_MAP, }; #[cfg(feature = "fs")] @@ -39,7 +39,7 @@ pub fn sys_mmap( off: ctypes::off_t, ) -> *mut c_void { debug!( - "sys_mmap <= start: {:p}, len: {:x}, prot:{:x?}, flags:{:x?}, fd: {}", + "sys_mmap <= start: {:p}, len: 0x{:x}, prot:0x{:x?}, flags:0x{:x?}, fd: {}", start, len, prot, flags, fd ); syscall_body!(sys_mmap, { @@ -48,7 +48,7 @@ pub fn sys_mmap( let len = VirtAddr::from(len).align_up_4k().as_usize(); if !VirtAddr::from(start).is_aligned(PAGE_SIZE_4K) || len == 0 { error!( - "mmap failed because start:{:x} is not aligned or len:{:x} == 0", + "mmap failed because start:0x{:x} is not aligned or len:0x{:x} == 0", start, len ); return Err(LinuxError::EINVAL); @@ -60,7 +60,7 @@ pub fn sys_mmap( // check if `MAP_SHARED` or `MAP_PRIVATE` within flags. if (flags & ctypes::MAP_PRIVATE == 0) && (flags & ctypes::MAP_SHARED == 0) { - error!("mmap failed because none of `MAP_PRIVATE` and `MAP_SHARED` exsit"); + error!("mmap failed because none of `MAP_PRIVATE` and `MAP_SHARED` exist"); return Err(LinuxError::EINVAL); } @@ -77,9 +77,15 @@ pub fn sys_mmap( let mut new = Vma::new(fid, offset, prot, flags); let mut vma_map = VMA_MAP.lock(); let addr_condition = if start == 0 { None } else { Some(start) }; - let try_addr = find_free_region(&vma_map, addr_condition, len); + + let try_addr = if flags & ctypes::MAP_FIXED != 0 { + snatch_fixed_region(&mut vma_map, start, len) + } else { + find_free_region(&vma_map, addr_condition, len) + }; + match try_addr { - Some(vaddr) if vaddr == start || flags & ctypes::MAP_FIXED == 0 => { + Some(vaddr) => { new.start_addr = vaddr; new.end_addr = vaddr + len; vma_map.insert(vaddr, new); @@ -92,7 +98,7 @@ pub fn sys_mmap( /// Deletes the mappings for the specified address range pub fn sys_munmap(start: *mut c_void, len: ctypes::size_t) -> c_int { - debug!("sys_munmap <= start: {:p}, len: {:x}", start, len); + debug!("sys_munmap <= start: {:p}, len: 0x{:x}", start, len); syscall_body!(sys_munmap, { // transform C-type into rust-type let start = start as usize; @@ -100,15 +106,20 @@ pub fn sys_munmap(start: *mut c_void, len: ctypes::size_t) -> c_int { if !VirtAddr::from(start).is_aligned(PAGE_SIZE_4K) || len == 0 { error!( - "sys_munmap start_address={:x}, len {:x?} not aligned", + "sys_munmap start_address=0x{:x}, len 0x{:x?} not aligned", start, len ); return Err(LinuxError::EINVAL); } let mut vma_map = VMA_MAP.lock(); + + // In order to ensure that munmap can exit directly if it fails, it must + // ensure that munmap semantics are correct before taking action. + let mut post_shrink: Vec<(usize, usize)> = Vec::new(); // vma should be insert. let mut post_append: Vec<(usize, Vma)> = Vec::new(); // vma should be insert. let mut post_remove: Vec = Vec::new(); // vma should be removed. + let mut node = vma_map.upper_bound_mut(Bound::Included(&start)); let mut counter = 0; // counter to check if all address in [start, start+len) is mapped. while let Some(vma) = node.value_mut() { @@ -127,7 +138,8 @@ pub fn sys_munmap(start: *mut c_void, len: ctypes::size_t) -> c_int { post_append.push((overlapped_end, right_vma)); } if overlapped_start > vma.start_addr { - vma.end_addr = overlapped_start; + // do vma.end_addr = overlapped_start if success + post_shrink.push((vma.start_addr, overlapped_start)); } else { post_remove.push(vma.start_addr); } @@ -138,14 +150,18 @@ pub fn sys_munmap(start: *mut c_void, len: ctypes::size_t) -> c_int { // check if any address in [start, end) not mayed. if counter != end - start { error!( - "munmap {:x?} but only {:x?} Byte inside", + "munmap 0x{:x?} but only 0x{:x?} byte inside", end - start, counter ); return Err(LinuxError::EINVAL); } - // do post action if success. + // do action after success. + for (start, addr) in post_shrink { + let vma_shrinking = vma_map.get_mut(&start).unwrap(); + vma_shrinking.end_addr = addr; + } for key in post_remove { vma_map.remove(&key).expect("there should be no empty"); } @@ -167,7 +183,7 @@ pub fn sys_munmap(start: *mut c_void, len: ctypes::size_t) -> c_int { /// addr must be aligned to a page boundary. pub fn sys_mprotect(start: *mut c_void, len: ctypes::size_t, prot: c_int) -> c_int { debug!( - "sys_mprotect <= addr: {:p}, len: {:x}, prot: {}", + "sys_mprotect <= addr: {:p}, len: 0x{:x}, prot: {}", start, len, prot ); @@ -180,7 +196,11 @@ pub fn sys_mprotect(start: *mut c_void, len: ctypes::size_t, prot: c_int) -> c_i } let syncing_interval = (start, end); + // In order to ensure that munmap can exit directly if it fails, it must + // ensure that munmap semantics are correct before taking action. let mut post_append: Vec<(usize, Vma)> = Vec::new(); + let mut post_shrink: Vec<(usize, usize)> = Vec::new(); + let mut post_align_changed: Vec<(usize, usize)> = Vec::new(); let mut vma_map = VMA_MAP.lock(); let mut node = vma_map.upper_bound_mut(Bound::Included(&start)); @@ -201,13 +221,17 @@ pub fn sys_mprotect(start: *mut c_void, len: ctypes::size_t, prot: c_int) -> c_i post_append.push((overlapped_end, right_vma)); } if overlapped_start > vma.start_addr { - vma.end_addr = overlapped_start; + // do vma.end_addr = overlapped_start if success + post_shrink.push((vma.start_addr, overlapped_start)); + + // The left side of the vma needs to be kept as is, while `prot` + // on the right side need to be modified. let mut overlapped_vma = Vma::clone_from(vma, overlapped_start, overlapped_end); overlapped_vma.prot = prot as u32; post_append.push((overlapped_start, overlapped_vma)) } else { - vma.end_addr = overlapped_end; - vma.prot = prot as u32; + // do vma.end_addr = overlapped_end and vma.prot = prot as u32 if success + post_align_changed.push((vma.start_addr, overlapped_end)); } } node.move_next(); @@ -215,7 +239,7 @@ pub fn sys_mprotect(start: *mut c_void, len: ctypes::size_t, prot: c_int) -> c_i // check if any address in [start, end) not mayed. if counter != end - start { error!( - "munmap {:x?} but only {:x?} Byte inside", + "mprotect 0x{:x?} but only 0x{:x?} byte inside", end - start, counter ); @@ -232,15 +256,24 @@ pub fn sys_mprotect(start: *mut c_void, len: ctypes::size_t, prot: c_int) -> c_i .is_err() { error!( - "Update page prot failed when mprotecting the page: vaddr={:x?}, prot={:?}", + "Updating page prot failed when mprotecting the page: vaddr=0x{:x?}, prot={:?}", vaddr, prot ); } } - // do post action if success. + // do action after success. for (key, value) in post_append { vma_map.insert(key, value); } + for (start, addr) in post_shrink { + let vma_shrinking = vma_map.get_mut(&start).unwrap(); + vma_shrinking.end_addr = addr; + } + for (start, addr) in post_align_changed { + let vma_align_changing = vma_map.get_mut(&start).unwrap(); + vma_align_changing.end_addr = addr; + vma_align_changing.prot = prot as u32; + } Ok(0) }) } @@ -269,9 +302,9 @@ pub fn sys_msync(start: *mut c_void, len: ctypes::size_t, flags: c_int) -> c_int let ret_size = sys_pwrite64(fid, src, size, offset as i64) as usize; if size != ret_size { error!( - "sys_msync: try to pwrite(fid={:x?}, size={:x?}, offset={:x?}) but get ret = {:x?}", - fid, size, offset, ret_size - ); + "sys_msync: try to pwrite(fid=0x{:x?}, size=0x{:x?}, offset=0x{:x?}) but get ret = 0x{:x?}", + fid, size, offset, ret_size + ); return Err(LinuxError::EFAULT); } } diff --git a/api/ruxos_posix_api/src/imp/mmap/trap.rs b/api/ruxos_posix_api/src/imp/mmap/trap.rs index 32ee03d5c..ad86e781d 100644 --- a/api/ruxos_posix_api/src/imp/mmap/trap.rs +++ b/api/ruxos_posix_api/src/imp/mmap/trap.rs @@ -44,7 +44,7 @@ impl ruxhal::trap::TrapHandler for TrapHandlerImpl { let map_flag = get_mflags_from_usize(vma.prot); trace!( - "Page Fault Happening, vaddr:{:x?}, casue:{:?}, map_flags:{:x?}", + "Page Fault Happening, vaddr:0x{:x?}, casue:{:?}, map_flags:0x{:x?}", vaddr, cause, map_flag @@ -141,9 +141,9 @@ impl ruxhal::trap::TrapHandler for TrapHandlerImpl { } } else { for mapped in vma_map.iter() { - warn!("{:x?}", mapped); + warn!("0x{:x?}", mapped); } - warn!("vaddr={:x?},cause={:x?}", vaddr, cause); + warn!("vaddr=0x{:x?},cause=0x{:x?}", vaddr, cause); false } } diff --git a/api/ruxos_posix_api/src/imp/mmap/utils.rs b/api/ruxos_posix_api/src/imp/mmap/utils.rs index b7e589767..01f05c955 100644 --- a/api/ruxos_posix_api/src/imp/mmap/utils.rs +++ b/api/ruxos_posix_api/src/imp/mmap/utils.rs @@ -178,6 +178,61 @@ pub(crate) fn find_free_region( None } +/// Clear the memory of the specified area. return Some(start) if successful. +/// take care of AA-deadlock, this function should not be used after `MEM_MAP` is used. +pub(crate) fn snatch_fixed_region( + vma_map: &mut BTreeMap, + start: usize, + len: usize, +) -> Option { + let end = start + len; + + // Return None if the specified address can't be used + if start >= VMA_START && end <= VMA_END { + return None; + } + + let mut post_append: Vec<(usize, Vma)> = Vec::new(); // vma should be insert. + let mut post_remove: Vec = Vec::new(); // vma should be removed. + + let mut node = vma_map.upper_bound_mut(Bound::Included(&start)); + while let Some(vma) = node.value_mut() { + if vma.start_addr >= end { + break; + } + if let Some((overlapped_start, overlapped_end)) = + get_overlap((start, end), (vma.start_addr, vma.end_addr)) + { + // add node for overlapped vma_ptr + if vma.end_addr > overlapped_end { + let right_vma = Vma::clone_from(vma, overlapped_end, vma.end_addr); + post_append.push((overlapped_end, right_vma)); + } + if overlapped_start > vma.start_addr { + vma.end_addr = overlapped_start + } else { + post_remove.push(vma.start_addr); + } + } + node.move_next(); + } + + // do action after success. + for key in post_remove { + vma_map.remove(&key).expect("there should be no empty"); + } + for (key, value) in post_append { + vma_map.insert(key, value); + } + + // delete the mapped and swapped page. + release_pages_mapped(start, end); + #[cfg(feature = "fs")] + release_pages_swaped(start, end); + + Some(start) +} + /// release the range of [start, end) in mem_map /// take care of AA-deadlock, this function should not be used after `MEM_MAP` is used. pub(crate) fn release_pages_mapped(start: usize, end: usize) { @@ -352,7 +407,7 @@ pub(crate) fn preload_page_with_swap( }, Err(ecode) => panic!( - "Unexpected error {:x?} happening when page fault occurs!", + "Unexpected error 0x{:x?} happening when page fault occurs!", ecode ), } diff --git a/api/ruxos_posix_api/src/imp/stdio.rs b/api/ruxos_posix_api/src/imp/stdio.rs index ecd85f44a..7b9699154 100644 --- a/api/ruxos_posix_api/src/imp/stdio.rs +++ b/api/ruxos_posix_api/src/imp/stdio.rs @@ -10,12 +10,11 @@ use axerrno::AxResult; use axio::{prelude::*, BufReader}; use axsync::Mutex; + #[cfg(feature = "fd")] use { alloc::sync::Arc, - axerrno::AxError, - axerrno::LinuxError, - axerrno::LinuxResult, + axerrno::{AxError, LinuxError, LinuxResult}, axio::PollState, core::sync::atomic::{AtomicBool, Ordering}, }; diff --git a/modules/axnet/src/smoltcp_impl/tcp.rs b/modules/axnet/src/smoltcp_impl/tcp.rs index 8bde01549..de9c14fd5 100644 --- a/modules/axnet/src/smoltcp_impl/tcp.rs +++ b/modules/axnet/src/smoltcp_impl/tcp.rs @@ -34,10 +34,8 @@ const STATE_CONNECTING: u8 = 2; const STATE_CONNECTED: u8 = 3; const STATE_LISTENING: u8 = 4; -const MSG_OOB: i32 = 1; const MSG_PEEK: i32 = 2; const MSG_DONTWAIT: i32 = 4; -const MSG_CTRUNC: i32 = 8; /// A TCP socket that provides POSIX-like APIs. /// diff --git a/modules/ruxhal/src/paging.rs b/modules/ruxhal/src/paging.rs index ae7754a2f..eb2311dc7 100644 --- a/modules/ruxhal/src/paging.rs +++ b/modules/ruxhal/src/paging.rs @@ -135,7 +135,7 @@ pub fn alloc_page_preload() -> Result { /// address is still on linear mapping region. /// use `do_pte_map` to do actually page mapping after call this function. pub fn pte_swap_preload(swaped_vaddr: VirtAddr) -> PagingResult { - trace!("swapping swaped_vaddr: {:x?}", swaped_vaddr,); + trace!("swapping swaped_vaddr: 0x{:x?}", swaped_vaddr,); let mut kernel_page_table = KERNEL_PAGE_TABLE.lock(); let (paddr, _) = kernel_page_table.unmap(swaped_vaddr)?; flush_tlb(Some(swaped_vaddr)); @@ -170,7 +170,12 @@ pub fn pte_update_page( paddr: Option, flags: Option, ) -> PagingResult { - trace!("updating vaddr: {:x?} {:x?} {:x?}", vaddr, paddr, flags); + trace!( + "updating vaddr:0x{:x?} paddr:0x{:x?} flags:0x{:x?}", + vaddr, + paddr, + flags + ); KERNEL_PAGE_TABLE.lock().update(vaddr, paddr, flags)?; flush_tlb(Some(vaddr)); Ok(()) @@ -180,7 +185,7 @@ pub fn pte_update_page( /// /// release the corresponding memory at the same time pub fn pte_unmap_page(vaddr: VirtAddr) -> PagingResult { - trace!("unmapping vaddr: {:x?}", vaddr); + trace!("unmapping vaddr: 0x{:x?}", vaddr); let (paddr, _) = KERNEL_PAGE_TABLE.lock().unmap(vaddr)?; global_allocator().dealloc_pages(phys_to_virt(paddr).as_usize(), 1); flush_tlb(Some(vaddr)); diff --git a/modules/ruxhal/src/platform/aarch64_common/pl031.rs b/modules/ruxhal/src/platform/aarch64_common/pl031.rs index b8ddd9b62..7cced553b 100644 --- a/modules/ruxhal/src/platform/aarch64_common/pl031.rs +++ b/modules/ruxhal/src/platform/aarch64_common/pl031.rs @@ -53,11 +53,11 @@ impl Pl031rtc { } pub unsafe fn read(&self, reg: u32) -> u32 { - core::ptr::read_volatile((PHYS_RTC + reg as usize) as *const u32) + core::ptr::read_volatile((self.address + reg as usize) as *const u32) } pub unsafe fn write(&self, reg: u32, value: u32) { - core::ptr::write_volatile((PHYS_RTC + reg as usize) as *mut u32, value); + core::ptr::write_volatile((self.address + reg as usize) as *mut u32, value); } pub fn time(&self) -> u64 { diff --git a/ulib/ruxlibc/src/io.rs b/ulib/ruxlibc/src/io.rs index d40a7016b..2c7450195 100644 --- a/ulib/ruxlibc/src/io.rs +++ b/ulib/ruxlibc/src/io.rs @@ -11,7 +11,9 @@ use core::ffi::{c_int, c_void}; #[cfg(feature = "fd")] use ruxos_posix_api::sys_ioctl; -use ruxos_posix_api::{sys_read, sys_write, sys_writev}; +#[cfg(not(test))] +use ruxos_posix_api::sys_write; +use ruxos_posix_api::{sys_read, sys_writev}; use crate::{ctypes, utils::e}; diff --git a/ulib/ruxmusl/src/lib.rs b/ulib/ruxmusl/src/lib.rs index 23b4968ea..66f949338 100644 --- a/ulib/ruxmusl/src/lib.rs +++ b/ulib/ruxmusl/src/lib.rs @@ -20,6 +20,7 @@ cfg_if::cfg_if! { use aarch64::{syscall, syscall_id}; } else if #[cfg(target_arch = "x86_64")]{ mod x86_64; + #[cfg(feature = "musl")] use x86_64::{syscall, syscall_id}; } else { mod dummy; diff --git a/ulib/ruxmusl/src/trap.rs b/ulib/ruxmusl/src/trap.rs index 8936f9f03..17fb9aecd 100644 --- a/ulib/ruxmusl/src/trap.rs +++ b/ulib/ruxmusl/src/trap.rs @@ -1,7 +1,7 @@ //! Traphandle implementation //! //! Used to support musl syscall - +#[cfg(feature = "musl")] use crate::syscall_id::SyscallId; /// Traphandler used by musl libc, overwrite handler in ruxruntime diff --git a/ulib/ruxmusl/src/x86_64/mod.rs b/ulib/ruxmusl/src/x86_64/mod.rs index fa7a35fd6..16a467dfe 100644 --- a/ulib/ruxmusl/src/x86_64/mod.rs +++ b/ulib/ruxmusl/src/x86_64/mod.rs @@ -1,9 +1,11 @@ pub mod syscall_id; +#[allow(unused_imports)] use core::ffi::{c_char, c_int, c_ulong, c_void}; use ruxos_posix_api::ctypes::{self, gid_t, pid_t, uid_t}; use syscall_id::SyscallId; +#[allow(dead_code)] pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { debug!("x86 syscall <= syscall_name: {:?}", syscall_id); @@ -288,6 +290,7 @@ pub fn syscall(syscall_id: SyscallId, args: [usize; 6]) -> isize { ruxos_posix_api::sys_execve(args[0] as *const c_char, args[1], args[2]) as _ } + #[allow(unreachable_code)] #[cfg(not(feature = "multitask"))] SyscallId::EXIT => ruxos_posix_api::sys_exit(args[0] as c_int) as _, From 095c24067298edfe805ed954fabcb690f73fc9a3 Mon Sep 17 00:00:00 2001 From: wuzheng Date: Sat, 13 Apr 2024 00:24:33 +0800 Subject: [PATCH 09/13] fix bugs in mmap and syscall handler --- api/ruxos_posix_api/src/imp/fs.rs | 8 +- api/ruxos_posix_api/src/imp/mmap/api.rs | 40 ++++--- api/ruxos_posix_api/src/imp/mmap/trap.rs | 37 +++--- api/ruxos_posix_api/src/imp/mmap/utils.rs | 133 +++++++++++++--------- modules/ruxconfig/defconfig.toml | 4 +- modules/ruxhal/src/arch/aarch64/trap.rs | 6 +- 6 files changed, 131 insertions(+), 97 deletions(-) diff --git a/api/ruxos_posix_api/src/imp/fs.rs b/api/ruxos_posix_api/src/imp/fs.rs index 46338c10a..9d47b0624 100644 --- a/api/ruxos_posix_api/src/imp/fs.rs +++ b/api/ruxos_posix_api/src/imp/fs.rs @@ -23,21 +23,21 @@ use crate::{ctypes, utils::char_ptr_to_str}; use alloc::vec::Vec; pub struct File { - inner: Mutex, + pub(crate) inner: Mutex, } impl File { - fn new(inner: ruxfs::fops::File) -> Self { + pub(crate) fn new(inner: ruxfs::fops::File) -> Self { Self { inner: Mutex::new(inner), } } - fn add_to_fd_table(self) -> LinuxResult { + pub(crate) fn add_to_fd_table(self) -> LinuxResult { super::fd_ops::add_file_like(Arc::new(self)) } - fn from_fd(fd: c_int) -> LinuxResult> { + pub(crate) fn from_fd(fd: c_int) -> LinuxResult> { let f = super::fd_ops::get_file_like(fd)?; f.into_any() .downcast::() diff --git a/api/ruxos_posix_api/src/imp/mmap/api.rs b/api/ruxos_posix_api/src/imp/mmap/api.rs index 9b6ce2212..97b76c22a 100644 --- a/api/ruxos_posix_api/src/imp/mmap/api.rs +++ b/api/ruxos_posix_api/src/imp/mmap/api.rs @@ -23,9 +23,10 @@ use super::utils::{ }; #[cfg(feature = "fs")] -use super::utils::release_pages_swaped; -#[cfg(feature = "fs")] -use crate::imp::fs::sys_pwrite64; +use { + super::utils::{release_pages_swaped, write_into}, + alloc::sync::Arc, +}; /// Creates a new mapping in the virtual address space of the calling process. /// @@ -296,17 +297,10 @@ pub fn sys_msync(start: *mut c_void, len: ctypes::size_t, flags: c_int) -> c_int if !VirtAddr::from(start).is_aligned(PAGE_SIZE_4K) || len == 0 { return Err(LinuxError::EINVAL); } - for (&vaddr, &page_info) in MEM_MAP.lock().range(start..end) { - if let Some((fid, offset, size)) = page_info { - let src = vaddr as *mut c_void; - let ret_size = sys_pwrite64(fid, src, size, offset as i64) as usize; - if size != ret_size { - error!( - "sys_msync: try to pwrite(fid=0x{:x?}, size=0x{:x?}, offset=0x{:x?}) but get ret = 0x{:x?}", - fid, size, offset, ret_size - ); - return Err(LinuxError::EFAULT); - } + for (&vaddr, page_info) in MEM_MAP.lock().range(start..end) { + if let Some((file, offset, size)) = page_info { + let src = vaddr as *mut u8; + write_into(file, src, *offset as u64, *size); } } } @@ -358,13 +352,25 @@ pub fn sys_mremap( } // make sure of consistent_vma is continuous and consistent in both flags and prots. if let Some(ref mut inner_vma) = consistent_vma { - let end_offset = inner_vma.offset + (inner_vma.end_addr - inner_vma.start_addr); if inner_vma.end_addr == vma.start_addr && inner_vma.flags == vma.flags && inner_vma.prot == vma.prot - && inner_vma.fid == vma.fid - && (end_offset == vma.offset || inner_vma.fid < 0) { + #[cfg(feature = "fs")] + if inner_vma.file.is_some() { + if vma.file.is_none() { + return Err(LinuxError::EFAULT); + } + let end_offset = + inner_vma.offset + (inner_vma.end_addr - inner_vma.start_addr); + let vma_file = vma.file.as_ref().unwrap(); + let inner_file = inner_vma.file.as_ref().unwrap(); + if !Arc::ptr_eq(vma_file, inner_file) || end_offset != vma.offset { + return Err(LinuxError::EFAULT); + } + } else if vma.file.is_some() { + return Err(LinuxError::EFAULT); + } inner_vma.end_addr = vma.end_addr; } else { return Err(LinuxError::EFAULT); diff --git a/api/ruxos_posix_api/src/imp/mmap/trap.rs b/api/ruxos_posix_api/src/imp/mmap/trap.rs index ad86e781d..5b0076be6 100644 --- a/api/ruxos_posix_api/src/imp/mmap/trap.rs +++ b/api/ruxos_posix_api/src/imp/mmap/trap.rs @@ -7,18 +7,16 @@ * See the Mulan PSL v2 for more details. */ -use crate::ctypes; - -#[cfg(not(feature = "fs"))] -use ruxhal::paging::alloc_page_preload; #[cfg(feature = "fs")] -use { - crate::imp::fs::sys_pread64, - crate::imp::mmap::utils::{preload_page_with_swap, BITMAP_FREE, SWAPED_MAP, SWAP_FID}, +use crate::{ + ctypes, + imp::mmap::utils::{preload_page_with_swap, read_from, BITMAP_FREE, SWAPED_MAP, SWAP_FILE}, }; +#[cfg(not(feature = "fs"))] +use ruxhal::paging::alloc_page_preload; use crate::imp::mmap::utils::{get_mflags_from_usize, MEM_MAP, VMA_MAP}; -use core::{cmp::min, ffi::c_void, ops::Bound}; +use core::{cmp::min, ops::Bound}; use memory_addr::PAGE_SIZE_4K; use page_table::MappingFlags; use ruxhal::{ @@ -91,15 +89,15 @@ impl ruxhal::trap::TrapHandler for TrapHandlerImpl { preload_page_with_swap(&mut memory_map, &mut swaped_map, &mut off_pool); // Fill target data to assigned physical addresses, from file or zero according to mapping type - let dst = fake_vaddr.as_mut_ptr() as *mut c_void; + let dst = fake_vaddr.as_mut_ptr(); #[cfg(feature = "fs")] { if let Some(off) = swaped_map.remove(&vaddr) { off_pool.push(off); - sys_pread64(*SWAP_FID, dst, size, off as i64); - } else if vma.fid > 0 && !map_flag.is_empty() { - let off = (vma.offset + (vaddr - vma.start_addr)) as i64; - sys_pread64(vma.fid, dst, size, off); + read_from(&SWAP_FILE, dst, off as u64, size); + } else if let Some(file) = &vma.file { + let off = (vma.offset + (vaddr - vma.start_addr)) as u64; + read_from(file, dst, off, size); } else { // Set page to 0 for anonymous mapping // @@ -121,16 +119,22 @@ impl ruxhal::trap::TrapHandler for TrapHandlerImpl { } // Insert the record into `MEM_MAP` with write-back information(`None` if no need to write-back). + #[cfg(feature = "fs")] if (vma.prot & ctypes::PROT_WRITE != 0) && (vma.flags & ctypes::MAP_PRIVATE == 0) - && (vma.fid > 0) + && (vma.file.is_some()) { let map_length = min(PAGE_SIZE_4K, vma.end_addr - vaddr); let offset = vma.offset + (vaddr - vma.start_addr); - memory_map.insert(vaddr, Some((vma.fid, offset, map_length))); + memory_map.insert( + vaddr, + Some((vma.file.as_ref().unwrap().clone(), offset, map_length)), + ); } else { memory_map.insert(vaddr, None); } + #[cfg(not(feature = "fs"))] + memory_map.insert(vaddr, None); // Do actual mmapping for target vaddr // @@ -140,9 +144,6 @@ impl ruxhal::trap::TrapHandler for TrapHandlerImpl { Err(_) => false, } } else { - for mapped in vma_map.iter() { - warn!("0x{:x?}", mapped); - } warn!("vaddr=0x{:x?},cause=0x{:x?}", vaddr, cause); false } diff --git a/api/ruxos_posix_api/src/imp/mmap/utils.rs b/api/ruxos_posix_api/src/imp/mmap/utils.rs index 01f05c955..ab97573f6 100644 --- a/api/ruxos_posix_api/src/imp/mmap/utils.rs +++ b/api/ruxos_posix_api/src/imp/mmap/utils.rs @@ -10,11 +10,7 @@ use crate::ctypes; #[cfg(feature = "fs")] -use { - crate::imp::fs::{sys_open, sys_pread64, sys_pwrite64}, - core::ffi::{c_char, c_void}, - page_table::PagingError, -}; +use {crate::imp::fs::File, alloc::sync::Arc, page_table::PagingError, ruxfs::fops::OpenOptions}; use alloc::{collections::BTreeMap, vec::Vec}; use axsync::Mutex; @@ -49,7 +45,7 @@ used_fs! { pub(crate) const SWAP_PATH: &str = "swap.raw\0"; pub(crate) static SWAPED_MAP: Mutex> = Mutex::new(BTreeMap::new()); // Vaddr => (page_size, offset_at_swaped) lazy_static::lazy_static! { - pub(crate) static ref SWAP_FID: i32 = sys_open(SWAP_PATH.as_ptr() as *const c_char, (ctypes::O_RDWR| ctypes::O_TRUNC| ctypes::O_SYNC) as i32, 0); + pub(crate) static ref SWAP_FILE: Arc = open_swap_file(SWAP_PATH); pub(crate) static ref BITMAP_FREE: Mutex> = Mutex::new((0..SWAP_MAX).step_by(PAGE_SIZE_4K).collect()); } } @@ -57,17 +53,20 @@ used_fs! { pub(crate) static VMA_MAP: Mutex> = Mutex::new(BTreeMap::new()); // start_addr pub(crate) static MEM_MAP: Mutex> = Mutex::new(BTreeMap::new()); // Vaddr => (fid, offset, page_size) -type PageInfo = Option<(Fid, Offset, Len)>; // (fid, offset, page_size) +#[cfg(feature = "fs")] +type PageInfo = Option<(Arc, Offset, Len)>; // (fid, offset, page_size) +#[cfg(not(feature = "fs"))] +type PageInfo = Option; // (fid, offset, page_size) +#[cfg(feature = "fs")] type Offset = usize; -type Fid = i32; type Len = usize; /// Data structure for mapping [start_addr, end_addr) with meta data. -#[derive(Debug)] pub(crate) struct Vma { pub start_addr: usize, pub end_addr: usize, - pub fid: i32, + #[cfg(feature = "fs")] + pub file: Option>, pub offset: usize, pub prot: u32, pub flags: u32, @@ -75,22 +74,30 @@ pub(crate) struct Vma { /// Impl for Vma. impl Vma { - pub fn new(fid: i32, offset: usize, prot: u32, flags: u32) -> Self { + pub(crate) fn new(_fid: i32, offset: usize, prot: u32, flags: u32) -> Self { + #[cfg(feature = "fs")] + let file = if _fid < 0 { + None + } else { + Some(File::from_fd(_fid).expect("should be effective fid")) + }; Vma { start_addr: 0, end_addr: 0, - fid, + #[cfg(feature = "fs")] + file, offset, flags, prot, } } - pub fn clone_from(vma: &Vma, start_addr: usize, end_addr: usize) -> Self { + pub(crate) fn clone_from(vma: &Vma, start_addr: usize, end_addr: usize) -> Self { Vma { start_addr, end_addr, - fid: vma.fid, + #[cfg(feature = "fs")] + file: vma.file.clone(), offset: vma.offset, prot: vma.prot, flags: vma.prot, @@ -98,6 +105,47 @@ impl Vma { } } +/// open target file +#[cfg(feature = "fs")] +fn open_swap_file(filename: &str) -> Arc { + let mut opt = OpenOptions::new(); + opt.read(true); + opt.write(true); + opt.append(true); + opt.create(true); + + let file = ruxfs::fops::File::open(filename, &opt).expect("create swap file failed"); + Arc::new(File::new(file)) +} + +/// read from target file +#[cfg(feature = "fs")] +pub(crate) fn read_from(file: &Arc, buf: *mut u8, offset: u64, len: usize) { + let src = unsafe { core::slice::from_raw_parts_mut(buf, len) }; + let actual_len = file + .inner + .lock() + .read_at(offset, src) + .expect("read_from failed"); + if len != actual_len { + warn!("read_from len=0x{len:x} but actual_len=0x{actual_len:x}"); + } +} + +/// write into target file +#[cfg(feature = "fs")] +pub(crate) fn write_into(file: &Arc, buf: *mut u8, offset: u64, len: usize) { + let src = unsafe { core::slice::from_raw_parts_mut(buf, len) }; + let actual_len = file + .inner + .lock() + .write_at(offset, src) + .expect("write_into failed"); + if len != actual_len { + warn!("write_into len=0x{len:x} but actual_len=0x{actual_len:x}"); + } +} + /// transform usize-like mmap flags to MappingFlags pub(crate) fn get_mflags_from_usize(prot: u32) -> MappingFlags { let mut mmap_prot = MappingFlags::empty(); @@ -188,7 +236,7 @@ pub(crate) fn snatch_fixed_region( let end = start + len; // Return None if the specified address can't be used - if start >= VMA_START && end <= VMA_END { + if start < VMA_START || end > VMA_END { return None; } @@ -238,12 +286,11 @@ pub(crate) fn snatch_fixed_region( pub(crate) fn release_pages_mapped(start: usize, end: usize) { let mut memory_map = MEM_MAP.lock(); let mut removing_vaddr = Vec::new(); - for (&vaddr, &_page_info) in memory_map.range(start..end) { + for (&vaddr, _page_info) in memory_map.range(start..end) { #[cfg(feature = "fs")] - if let Some((fid, offset, size)) = _page_info { - let src = vaddr as *mut c_void; - let offset = offset as i64; - sys_pwrite64(fid, src, size, offset); + if let Some((file, offset, size)) = _page_info { + let src = vaddr as *mut u8; + write_into(file, src, *offset as u64, *size); } if pte_unmap_page(VirtAddr::from(vaddr)).is_err() { panic!("Release page failed when munmapping!"); @@ -282,8 +329,8 @@ pub(crate) fn shift_mapped_page(start: usize, end: usize, vma_offset: usize, cop } let mut opt_buffer = Vec::new(); - for (&start, &page_info) in memory_map.range(start..end) { - opt_buffer.push((start, page_info)); + for (&start, page_info) in memory_map.range(start..end) { + opt_buffer.push((start, page_info.clone())); } for (start, page_info) in opt_buffer { // opt for the PTE. @@ -315,18 +362,13 @@ pub(crate) fn shift_mapped_page(start: usize, end: usize, vma_offset: usize, cop { used_fs! { let offset = swaped_map.get(&start).unwrap(); - sys_pread64( - *SWAP_FID, - dst.as_mut_ptr() as *mut c_void, - PAGE_SIZE_4K, - *offset as i64, - ); + read_from(&SWAP_FILE, start as *mut u8, *offset as u64, PAGE_SIZE_4K); } } (fake_vaddr, flags) }; do_pte_map(VirtAddr::from(start + vma_offset), fake_vaddr, flags).unwrap(); - memory_map.insert(start + vma_offset, page_info); + memory_map.insert(start + vma_offset, page_info.clone()); } used_fs! { @@ -343,18 +385,8 @@ pub(crate) fn shift_mapped_page(start: usize, end: usize, vma_offset: usize, cop .pop() .expect("There are no free space in swap-file!"); let mut rw_buffer: [u8; PAGE_SIZE_4K] = [0_u8; PAGE_SIZE_4K]; - sys_pread64( - *SWAP_FID, - rw_buffer.as_mut_ptr() as *mut c_void, - PAGE_SIZE_4K, - off_in_swap as i64, - ); - sys_pwrite64( - *SWAP_FID, - rw_buffer.as_mut_ptr() as *mut c_void, - PAGE_SIZE_4K, - off_ptr as i64, - ); + read_from(&SWAP_FILE, rw_buffer.as_mut_ptr(), off_in_swap as u64, PAGE_SIZE_4K); + write_into(&SWAP_FILE, rw_buffer.as_mut_ptr(), off_ptr as u64, PAGE_SIZE_4K); } swaped_map.insert(start + vma_offset, off_in_swap); } @@ -376,31 +408,24 @@ pub(crate) fn preload_page_with_swap( #[cfg(feature = "fs")] Err(PagingError::NoMemory) => match memory_map.pop_first() { // For file mapping, the mapped content will be written directly to the original file. - Some((vaddr_swapped, Some((fid, offset, size)))) => { + Some((vaddr_swapped, Some((file, offset, size)))) => { let offset = offset.try_into().unwrap(); - sys_pwrite64(fid, vaddr_swapped as *mut c_void, size, offset); + write_into(&file, vaddr_swapped as *mut u8, offset, size); pte_swap_preload(VirtAddr::from(vaddr_swapped)).unwrap() } // For anonymous mapping, you need to save the mapped memory to the prepared swap file, // and record the memory address and its offset in the swap file. Some((vaddr_swapped, None)) => { let offset_get = off_pool.pop(); - if SWAP_FID.is_negative() || offset_get.is_none() { - panic!( - "No free memory for mmap or swap fid, swap fid={}", - *SWAP_FID - ); - } let offset = offset_get.unwrap(); swaped_map.insert(vaddr_swapped, offset); - sys_pwrite64( - *SWAP_FID, - vaddr_swapped as *mut c_void, + write_into( + &SWAP_FILE, + vaddr_swapped as *mut u8, + offset as u64, PAGE_SIZE_4K, - offset as i64, ); - pte_swap_preload(VirtAddr::from(vaddr_swapped)).unwrap() } _ => panic!("No memory for mmap, check if huge memory leaky exists"), diff --git a/modules/ruxconfig/defconfig.toml b/modules/ruxconfig/defconfig.toml index 60ef682db..bda9cc8df 100644 --- a/modules/ruxconfig/defconfig.toml +++ b/modules/ruxconfig/defconfig.toml @@ -31,8 +31,8 @@ pci-ranges = [] timer-frequency = "0" # Stack size of each task. -task-stack-size = "0x40000" # 256 K -# task-stack-size = "0x80000" # 512 K +# task-stack-size = "0x40000" # 256 K +task-stack-size = "0x80000" # 512 K # Number of timer ticks per second (Hz). A timer tick may contain several timer # interrupts. diff --git a/modules/ruxhal/src/arch/aarch64/trap.rs b/modules/ruxhal/src/arch/aarch64/trap.rs index 431434f3a..42597ffbc 100644 --- a/modules/ruxhal/src/arch/aarch64/trap.rs +++ b/modules/ruxhal/src/arch/aarch64/trap.rs @@ -9,8 +9,8 @@ use core::arch::global_asm; -#[cfg(feature = "irq")] -use crate::arch::enable_irqs; +#[cfg(all(feature = "irq", feature = "musl"))] +use crate::arch::{disable_irqs, enable_irqs}; #[cfg(feature = "paging")] use crate::trap::PageFaultCause; use aarch64_cpu::registers::{ESR_EL1, FAR_EL1}; @@ -74,6 +74,8 @@ fn handle_sync_exception(tf: &mut TrapFrame) { ], ); tf.r[0] = result as u64; + #[cfg(feature = "irq")] + disable_irqs(); } Some(ESR_EL1::EC::Value::DataAbortLowerEL) | Some(ESR_EL1::EC::Value::InstrAbortLowerEL) => { From 631c3f7e3424707f4debcb6bb02412fd92890040 Mon Sep 17 00:00:00 2001 From: yanjuguang Date: Wed, 17 Apr 2024 13:13:12 +0800 Subject: [PATCH 10/13] update rustc version --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index e4a809167..b789cc033 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] profile = "minimal" -channel = "nightly-2023-09-01" +channel = "nightly-2023-12-01" components = ["rust-src", "llvm-tools-preview", "rustfmt", "clippy"] targets = ["x86_64-unknown-none", "riscv64gc-unknown-none-elf", "aarch64-unknown-none-softfloat"] From 5d0b4af0391e390e189c70dae7c2de794027e305 Mon Sep 17 00:00:00 2001 From: thesayol Date: Fri, 12 Apr 2024 20:37:32 +0800 Subject: [PATCH 11/13] fix bugs of SYS_execve that uses SYS_mmap not correctly, and add example app for ELF loader. --- .../src/imp/execve/load_elf.rs | 52 ++++------- api/ruxos_posix_api/src/imp/execve/mod.rs | 91 ++++++++++--------- api/ruxos_posix_api/src/imp/execve/stack.rs | 60 +++++------- apps/c/dl/.gitignore | 10 ++ apps/c/dl/README.md | 31 +++++++ apps/c/dl/axbuild.mk | 6 ++ apps/c/dl/config_linux.toml | 20 ++++ apps/c/dl/features.txt | 11 +++ apps/c/dl/main.c | 7 ++ apps/c/dl/rootfs/hello.c | 10 ++ apps/c/dl/rootfs/libadd.c | 6 ++ 11 files changed, 192 insertions(+), 112 deletions(-) create mode 100644 apps/c/dl/.gitignore create mode 100644 apps/c/dl/README.md create mode 100644 apps/c/dl/axbuild.mk create mode 100644 apps/c/dl/config_linux.toml create mode 100644 apps/c/dl/features.txt create mode 100644 apps/c/dl/main.c create mode 100644 apps/c/dl/rootfs/hello.c create mode 100644 apps/c/dl/rootfs/libadd.c diff --git a/api/ruxos_posix_api/src/imp/execve/load_elf.rs b/api/ruxos_posix_api/src/imp/execve/load_elf.rs index e8730cf39..2359148c1 100644 --- a/api/ruxos_posix_api/src/imp/execve/load_elf.rs +++ b/api/ruxos_posix_api/src/imp/execve/load_elf.rs @@ -1,19 +1,12 @@ -use crate::{ctypes::kstat, utils::char_ptr_to_str, *}; +use crate::{ctypes::kstat, *}; use alloc::{vec, vec::Vec}; -use core::{ - ffi::c_char, - ptr::{null, null_mut}, -}; +use core::ptr::null_mut; #[derive(Debug)] pub struct ElfProg { - pub name: Vec, - pub path: Vec, - pub platform: Vec, - pub rand: Vec, pub base: usize, pub entry: usize, - pub interp_path: *const c_char, + pub interp_path: Vec, pub phent: usize, pub phnum: usize, pub phdr: usize, @@ -23,13 +16,11 @@ impl ElfProg { /// read elf from `path`, and copy LOAD segments to a alloacated memory /// /// and load interp, if needed. - pub fn new(filepath: *const c_char) -> Self { - let name = char_ptr_to_str(filepath).unwrap().as_bytes().to_vec(); - let path = name.clone(); - debug!("sys_execve: new elf prog: {:?}", char_ptr_to_str(filepath)); + pub fn new(filepath: &str) -> Self { + debug!("sys_execve: new elf prog: {filepath}"); // open file - let fd = sys_open(filepath, ctypes::O_RDWR as i32, 0); + let fd = sys_open(filepath.as_ptr() as _, ctypes::O_RDWR as _, 0); // get file size let mut buf = ctypes::kstat { @@ -49,16 +40,23 @@ impl ElfProg { .expect("parse ELF failed"); // get program's LOAD mem size - let mut msize = 0; + let mut min_addr = 0; + let mut max_addr = 0; let segs = file.segments().unwrap(); for seg in segs { if seg.p_type == elf::abi::PT_LOAD { - msize += seg.p_memsz; + min_addr = min_addr.min(seg.p_vaddr); + max_addr = max_addr.max(seg.p_vaddr + seg.p_memsz); } } + let msize = (max_addr - min_addr) as usize; + + // alloc memory for LOAD + let prot = ctypes::PROT_WRITE | ctypes::PROT_READ | ctypes::PROT_EXEC; + let flags = ctypes::MAP_ANONYMOUS | ctypes::MAP_PRIVATE; + let base = crate::sys_mmap(null_mut(), msize, prot as _, flags as _, -1, 0) as usize; // copy LOAD segments - let base = crate::sys_mmap(null_mut(), msize as usize, 0, 0, 0, 0) as usize; for seg in segs { if seg.p_type == elf::abi::PT_LOAD { let data = file.segment_data(&seg).unwrap(); @@ -74,23 +72,15 @@ impl ElfProg { let entry = file.ehdr.e_entry as usize + base; // parse interpreter - let mut interp_path = null::(); + let mut interp_path = vec![]; for seg in file.segments().unwrap() { if seg.p_type == elf::abi::PT_INTERP { - let data = file.segment_data(&seg).unwrap(); - interp_path = data.as_ptr() as *const c_char; + let data = file.segment_data(&seg).unwrap().to_vec(); + interp_path = data; break; } } - // platform - #[cfg(target_arch = "aarch64")] - let platform = b"aarch64".to_vec(); - #[cfg(target_arch = "x86_64")] - let platform = b"x86_64".to_vec(); - #[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))] - let platform = b"unknown".to_vec(); - // get address of .text for debugging let text_section_addr = base + file @@ -107,10 +97,6 @@ impl ElfProg { Self { base, entry, - name, - path, - platform, - rand: alloc::vec![1, 2], interp_path, phent: file.ehdr.e_phentsize as usize, phnum: file.ehdr.e_phnum as usize, diff --git a/api/ruxos_posix_api/src/imp/execve/mod.rs b/api/ruxos_posix_api/src/imp/execve/mod.rs index 93886d94a..4b1dc5c46 100644 --- a/api/ruxos_posix_api/src/imp/execve/mod.rs +++ b/api/ruxos_posix_api/src/imp/execve/mod.rs @@ -1,29 +1,32 @@ -use core::ffi::c_char; - mod auxv; mod load_elf; mod stack; use alloc::vec; +use core::ffi::c_char; use crate::{ + config, imp::stat::{sys_getgid, sys_getuid}, - sys_getegid, sys_geteuid, + sys_getegid, sys_geteuid, sys_random, + utils::char_ptr_to_str, }; /// int execve(const char *pathname, char *const argv[], char *const envp[] ); pub fn sys_execve(pathname: *const c_char, argv: usize, envp: usize) -> ! { use auxv::*; - let prog = load_elf::ElfProg::new(pathname); + let path = char_ptr_to_str(pathname).unwrap(); + let prog = load_elf::ElfProg::new(path); // get entry let mut entry = prog.entry; // if interp is needed let mut at_base = 0; - if !prog.interp_path.is_null() { - let interp_prog = load_elf::ElfProg::new(prog.interp_path); + if !prog.interp_path.is_empty() { + let interp_path = char_ptr_to_str(prog.interp_path.as_ptr() as _).unwrap(); + let interp_prog = load_elf::ElfProg::new(interp_path); entry = interp_prog.entry; at_base = interp_prog.base; debug!("sys_execve: INTERP base is {:x}", at_base); @@ -32,18 +35,13 @@ pub fn sys_execve(pathname: *const c_char, argv: usize, envp: usize) -> ! { // create stack let mut stack = stack::Stack::new(); - let name = prog.name; - let platform = prog.platform; - // non 8B info - stack.push(vec![0u8; 32], 16); - let p_progname = stack.push(name, 16); - let _p_plat = stack.push(platform, 16); // platform - let p_rand = stack.push(prog.rand, 16); // rand + stack.push(&[0u8; 32], 16); + let rand = unsafe { [sys_random(), sys_random()] }; + let p_rand = stack.push(&rand, 16); // auxv - // TODO: vdso and rand - // TODO: a way to get pagesz instead of a constant + // TODO: vdso let auxv = vec![ AT_PHDR, prog.phdr, @@ -54,9 +52,11 @@ pub fn sys_execve(pathname: *const c_char, argv: usize, envp: usize) -> ! { AT_BASE, at_base, AT_PAGESZ, - 0x1000, + config::PAGE_SIZE_4K, AT_HWCAP, 0, + AT_PLATFORM, + platform(), AT_CLKTCK, 100, AT_FLAGS, @@ -74,7 +74,7 @@ pub fn sys_execve(pathname: *const c_char, argv: usize, envp: usize) -> ! { AT_SECURE, 0, AT_EXECFN, - p_progname, + pathname as usize, AT_RANDOM, p_rand, AT_SYSINFO_EHDR, @@ -88,53 +88,48 @@ pub fn sys_execve(pathname: *const c_char, argv: usize, envp: usize) -> ! { // handle envs and args let mut env_vec = vec![]; let mut arg_vec = vec![]; - let mut argc = 0; - let envp = envp as *const usize; + let mut envp = envp as *const usize; unsafe { - let mut i = 0; - while *envp.add(i) != 0 { - env_vec.push(*envp.add(i)); - i += 1; + while *envp != 0 { + env_vec.push(*envp); + envp = envp.add(1); } env_vec.push(0); } - let argv = argv as *const usize; + let mut argv = argv as *const usize; unsafe { - let mut i = 0; - loop { - let p = *argv.add(i); - if p == 0 { - break; - } - arg_vec.push(p); - argc += 1; - i += 1; + while *argv != 0 { + arg_vec.push(*argv); + argv = argv.add(1); } - arg_vec.push(0); } // push - stack.push(auxv, 16); - stack.push(env_vec, 8); - stack.push(arg_vec, 8); - let _sp = stack.push(vec![argc as usize], 8); + stack.push(&auxv, 16); + stack.push(&env_vec, 8); + stack.push(&arg_vec, 8); + let sp = stack.push(&[arg_vec.len() - 1], 8); // argc // try run debug!( - "sys_execve: run at entry 0x{entry:x}, then it will jump to 0x{:x} ", + "sys_execve: sp is 0x{sp:x}, run at 0x{entry:x}, then jump to 0x{:x} ", prog.entry ); + set_sp_and_jmp(sp, entry); +} + +fn set_sp_and_jmp(sp: usize, entry: usize) -> ! { #[cfg(target_arch = "aarch64")] unsafe { core::arch::asm!(" mov sp, {} - blr {} + br {} ", - in(reg)_sp, + in(reg)sp, in(reg)entry, ); } @@ -144,10 +139,20 @@ pub fn sys_execve(pathname: *const c_char, argv: usize, envp: usize) -> ! { mov rsp, {} jmp {} ", - in(reg)_sp, + in(reg)sp, in(reg)entry, ); } + unreachable!("sys_execve: unknown arch, sp 0x{sp:x}, entry 0x{entry:x}"); +} + +fn platform() -> usize { + #[cfg(target_arch = "aarch64")] + const PLATFORM_STRING: &[u8] = b"aarch64\0"; + #[cfg(target_arch = "x86_64")] + const PLATFORM_STRING: &[u8] = b"x86_64\0"; + #[cfg(not(any(target_arch = "aarch64", target_arch = "x86_64")))] + const PLATFORM_STRING: &[u8] = b"unknown\0"; - unreachable!("sys_execve: unknown arch"); + PLATFORM_STRING.as_ptr() as usize } diff --git a/api/ruxos_posix_api/src/imp/execve/stack.rs b/api/ruxos_posix_api/src/imp/execve/stack.rs index a741263e7..4561a09f3 100644 --- a/api/ruxos_posix_api/src/imp/execve/stack.rs +++ b/api/ruxos_posix_api/src/imp/execve/stack.rs @@ -1,55 +1,43 @@ -use core::{mem::size_of, ptr::null_mut}; +use alloc::{vec, vec::Vec}; -use crate::*; +const STACK_SIZE: usize = ruxconfig::TASK_STACK_SIZE; #[derive(Debug)] pub struct Stack { - sp: usize, - start: usize, - end: usize, + /// stack + data: Vec, + /// index of top byte of stack + top: usize, } impl Stack { - // alloc a stack + /// alloc a stack pub fn new() -> Self { - let size = 0xa00000; // 10M - let p = sys_mmap(null_mut(), size, 0, 0, 0, 0); - - let start = p as usize; - let sp = start + size; - let end = sp; - - Self { sp, start, end } + Self { + data: vec![0u8; STACK_SIZE], + top: STACK_SIZE, + } } - pub fn align(&mut self, align: usize) -> usize { - self.sp -= self.sp % align; - self.sp + /// addr of top of stack + pub fn sp(&self) -> usize { + self.data.as_ptr() as usize + self.top } - pub fn push(&mut self, thing: alloc::vec::Vec, align: usize) -> usize { - let size = thing.len() * size_of::(); - self.sp -= size; - self.sp = self.align(align); // align 16B + /// push data to stack and return the addr of sp + pub fn push(&mut self, data: &[T], align: usize) -> usize { + // move sp to right place + self.top -= core::mem::size_of_val(data); + self.top = memory_addr::align_down(self.top, align); - if self.sp < self.start { - panic!("stack overflow"); - } + assert!(self.top <= self.data.len(), "sys_execve: stack overflow."); - let mut pt = self.sp as *mut T; + // write data into stack + let sp = self.sp() as *mut T; unsafe { - for t in thing { - *pt = t; - pt = pt.add(1); - } + sp.copy_from_nonoverlapping(data.as_ptr(), data.len()); } - self.sp - } -} - -impl Drop for Stack { - fn drop(&mut self) { - sys_munmap(self.start as *mut _, self.end - self.start); + sp as usize } } diff --git a/apps/c/dl/.gitignore b/apps/c/dl/.gitignore new file mode 100644 index 000000000..e3ce33a96 --- /dev/null +++ b/apps/c/dl/.gitignore @@ -0,0 +1,10 @@ +ruxgo_bld +compile_commands.json +.cache +/rootfs/bin/* +/rootfs/lib/* +/rootfs/dev +/rootfs/etc +/rootfs/proc +/rootfs/sys +/rootfs/tmp diff --git a/apps/c/dl/README.md b/apps/c/dl/README.md new file mode 100644 index 000000000..721c5bacb --- /dev/null +++ b/apps/c/dl/README.md @@ -0,0 +1,31 @@ +# ELF loader + +> Read the RuxOS Book for detail. + +## Quick Start + +1. Compile the C files with Musl in `rootfs/`. + +```sh +cd rootfs/ +musl-gcc libadd.c -shared -o lib/libadd.so +musl-gcc hello.c -Llib -ladd -o bin/hello +``` + +2. Copy the Musl dyanmic linker to `rootfs/lib`. + +3. Run + +Run with `ruxgo`: + +```sh +# in apps/c/dl +ruxgo -b && ruxgo -r +``` + +Run with `make` + +```sh +# in the RuxOS main directory. +make run ARCH=aarch64 A=apps/c/dl V9P=y MUSL=y LOG=debug +``` diff --git a/apps/c/dl/axbuild.mk b/apps/c/dl/axbuild.mk new file mode 100644 index 000000000..55cc2d0f4 --- /dev/null +++ b/apps/c/dl/axbuild.mk @@ -0,0 +1,6 @@ +app-objs=main.o + +ARGS = /bin/hello +ENVS = +V9P_PATH=${APP}/rootfs +# make run ARCH=aarch64 A=apps/c/dl V9P=y MUSL=y LOG=debug \ No newline at end of file diff --git a/apps/c/dl/config_linux.toml b/apps/c/dl/config_linux.toml new file mode 100644 index 000000000..9083a1ad2 --- /dev/null +++ b/apps/c/dl/config_linux.toml @@ -0,0 +1,20 @@ +[build] +compiler = "gcc" +loader_app = ["y", "/bin/hello"] + +[os] +name = "ruxos" +services = ["alloc", "paging", "musl", "multitask", "fs", "virtio-9p"] +ulib = "ruxmusl" +develop = "y" + +[os.platform] +name = "aarch64-qemu-virt" +mode = "release" +log = "info" + +[os.platform.qemu] +memory = "2g" +v9p = "y" +v9p_path = "./rootfs" +args = "/bin/hello" diff --git a/apps/c/dl/features.txt b/apps/c/dl/features.txt new file mode 100644 index 000000000..0b7506227 --- /dev/null +++ b/apps/c/dl/features.txt @@ -0,0 +1,11 @@ +paging +alloc +irq +musl +multitask +fs +pipe +poll +rtc +signal +virtio-9p \ No newline at end of file diff --git a/apps/c/dl/main.c b/apps/c/dl/main.c new file mode 100644 index 000000000..cb479e391 --- /dev/null +++ b/apps/c/dl/main.c @@ -0,0 +1,7 @@ +#include +#include + +int main(int argc, char** argv, char**envp) { + execv(argv[0], argv); + return 0; +} \ No newline at end of file diff --git a/apps/c/dl/rootfs/hello.c b/apps/c/dl/rootfs/hello.c new file mode 100644 index 000000000..f7180dfaf --- /dev/null +++ b/apps/c/dl/rootfs/hello.c @@ -0,0 +1,10 @@ +#include + +extern int add(int, int); + +int main() +{ + printf("hello world\n"); + add(1, 2); + return 0; +} diff --git a/apps/c/dl/rootfs/libadd.c b/apps/c/dl/rootfs/libadd.c new file mode 100644 index 000000000..1be20d21b --- /dev/null +++ b/apps/c/dl/rootfs/libadd.c @@ -0,0 +1,6 @@ +#include + +int add(int a, int b) +{ + printf("%d + %d = %d\n", a, b, a + b); +} \ No newline at end of file From 279e3719ff32b0674b32d05284188afc371fbd38 Mon Sep 17 00:00:00 2001 From: yanjuguang Date: Wed, 24 Apr 2024 16:47:16 +0800 Subject: [PATCH 12/13] fix CI warnings remove /dev/foo/bar change license import crates_interface,kernel_guard,handler_table,memory_addr from crates.io --- Cargo.lock | 8 + Cargo.toml | 8 - README.md | 4 + api/ruxos_posix_api/Cargo.toml | 6 +- api/ruxos_posix_api/src/lib.rs | 1 - apps/c/dl/features.txt | 2 +- apps/fs/shell/Cargo.toml | 2 +- crates/allocator/src/lib.rs | 1 - crates/crate_interface/Cargo.toml | 20 - crates/crate_interface/README.md | 38 -- crates/crate_interface/src/lib.rs | 196 --------- .../tests/test_crate_interface.rs | 43 -- crates/driver_9p/Cargo.toml | 2 +- crates/driver_display/Cargo.toml | 2 +- crates/dtb/Cargo.toml | 2 +- crates/flatten_objects/src/lib.rs | 1 - crates/handler_table/Cargo.toml | 14 - crates/handler_table/README.md | 23 - crates/handler_table/src/lib.rs | 58 --- crates/kernel_guard/Cargo.toml | 20 - crates/kernel_guard/README.md | 56 --- crates/kernel_guard/src/arch/aarch64.rs | 23 - crates/kernel_guard/src/arch/mod.rs | 23 - crates/kernel_guard/src/arch/riscv.rs | 27 -- crates/kernel_guard/src/arch/x86.rs | 29 -- crates/kernel_guard/src/lib.rs | 248 ----------- crates/memory_addr/Cargo.toml | 14 - crates/memory_addr/README.md | 20 - crates/memory_addr/src/lib.rs | 393 ------------------ crates/page_table/Cargo.toml | 2 +- crates/page_table/src/lib.rs | 1 - crates/page_table_entry/Cargo.toml | 2 +- crates/percpu/Cargo.toml | 2 +- crates/spinlock/Cargo.toml | 2 +- doc/README.md | 4 - modules/axalloc/Cargo.toml | 2 +- modules/axlog/Cargo.toml | 2 +- modules/rux9p/Cargo.toml | 2 +- modules/ruxdisplay/Cargo.toml | 2 +- modules/ruxfs/Cargo.toml | 4 +- modules/ruxfs/src/mounts.rs | 3 - modules/ruxfs/src/root.rs | 6 +- modules/ruxfs/tests/test_common/mod.rs | 9 - modules/ruxfutex/Cargo.toml | 6 +- modules/ruxhal/Cargo.toml | 8 +- modules/ruxhal/src/lib.rs | 1 - modules/ruxhal/src/platform/dummy/mod.rs | 4 +- modules/ruxruntime/Cargo.toml | 4 +- modules/ruxtask/Cargo.toml | 6 +- ulib/ruxmusl/Cargo.toml | 6 +- 50 files changed, 53 insertions(+), 1309 deletions(-) delete mode 100644 crates/crate_interface/Cargo.toml delete mode 100644 crates/crate_interface/README.md delete mode 100644 crates/crate_interface/src/lib.rs delete mode 100644 crates/crate_interface/tests/test_crate_interface.rs delete mode 100644 crates/handler_table/Cargo.toml delete mode 100644 crates/handler_table/README.md delete mode 100644 crates/handler_table/src/lib.rs delete mode 100644 crates/kernel_guard/Cargo.toml delete mode 100644 crates/kernel_guard/README.md delete mode 100644 crates/kernel_guard/src/arch/aarch64.rs delete mode 100644 crates/kernel_guard/src/arch/mod.rs delete mode 100644 crates/kernel_guard/src/arch/riscv.rs delete mode 100644 crates/kernel_guard/src/arch/x86.rs delete mode 100644 crates/kernel_guard/src/lib.rs delete mode 100644 crates/memory_addr/Cargo.toml delete mode 100644 crates/memory_addr/README.md delete mode 100644 crates/memory_addr/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index b53869d52..c4fb205fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -493,6 +493,8 @@ checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48" [[package]] name = "crate_interface" version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54b79db793871881b52a1eb5dc6fd869743122e34795f12db8e183dcb6a4f28" dependencies = [ "proc-macro2", "quote", @@ -848,6 +850,8 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "handler_table" version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "011878ffbfb4cbfcbd9fd799d1168a65897b0b0195fc55f9ec73d27f1685b1dd" [[package]] name = "hash32" @@ -966,6 +970,8 @@ dependencies = [ [[package]] name = "kernel_guard" version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5638cc8298368ef284589ad372890c849b520cccd50567d86a77a9232e68afdc" dependencies = [ "cfg-if", "crate_interface", @@ -1065,6 +1071,8 @@ dependencies = [ [[package]] name = "memory_addr" version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91b53e2ffbb2aaf3b738bd38ddd7ca8c511e47e05cd03fc09eacb7c5fa1285e5" [[package]] name = "micromath" diff --git a/Cargo.toml b/Cargo.toml index 29f519fc3..ff52575d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,6 @@ members = [ "crates/axfs_vfs", "crates/axio", "crates/capability", - "crates/crate_interface", "crates/driver_9p", "crates/driver_block", "crates/driver_common", @@ -22,11 +21,8 @@ members = [ "crates/driver_virtio", "crates/dtb", "crates/flatten_objects", - "crates/handler_table", - "crates/kernel_guard", "crates/lazy_init", "crates/linked_list", - "crates/memory_addr", "crates/page_table", "crates/page_table_entry", "crates/percpu", @@ -71,7 +67,3 @@ lto = true [profile.reldebug] inherits = "release" debug = true - - -[patch.crates-io] -crate_interface = { path = "crates/crate_interface" } diff --git a/README.md b/README.md index 5747cf316..74f02b87a 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ RuxOS was inspired by [Unikraft](https://github.com/unikraft/unikraft) and [Arce * [x] SMP scheduling with single run queue * [x] File system * [x] Compatible with Linux apps +* [x] Dynamically loading apps * [ ] Interrupt driven device I/O * [ ] Async I/O @@ -63,6 +64,9 @@ The currently supported applications (Rust), as well as their dependent modules | [iperf](apps/c/iperf/) | alloc, paging, net, fs, blkfs, select, fp_simd | A network performance test tool | | [redis](apps/c/redis/) | alloc, paging, fp_simd, irq, multitask, fs, blkfs, net, pipe, epoll, poll, virtio-9p, rtc | A Redis server on Ruxos | | [sqlite3](apps/c/sqlite3/) | alloc, paging, fs, fp_simd, blkfs | A simple test for Sqlite3 API | +| [cpp](apps/c/cpp/) | alloc, paging, irq, multitask, fs, random-hw | C++ benchmark | +| [dl](apps/c/dl/) | paging, alloc, irq, musl, multitask, fs, pipe, poll, rtc, signal, virtio-9p | An example for dynamically loading apps | + ## Build & Run diff --git a/api/ruxos_posix_api/Cargo.toml b/api/ruxos_posix_api/Cargo.toml index b767b2d72..b62f65c7b 100644 --- a/api/ruxos_posix_api/Cargo.toml +++ b/api/ruxos_posix_api/Cargo.toml @@ -11,7 +11,7 @@ authors = [ "Shiping Yuan ", ] description = "POSIX-compatible APIs for Ruxos modules" -license = "GPL-3.0-or-later OR Apache-2.0" +license = "Mulan PSL v2" repository = "https://github.com/syswonder/ruxos/tree/main/api/ruxos_posix_api" [features] @@ -52,14 +52,14 @@ axnet = { path = "../../modules/axnet", optional = true } # Other crates axio = { path = "../../crates/axio" } axerrno = { path = "../../crates/axerrno" } -memory_addr = { path = "../../crates/memory_addr" } +memory_addr = "0.1.0" static_assertions = "1.1.0" spin = { version = "0.9" } spinlock = { path = "../../crates/spinlock" } lazy_static = { version = "1.4", features = ["spin_no_std"] } flatten_objects = { path = "../../crates/flatten_objects" } page_table = { path = "../../crates/page_table" } -crate_interface = { path = "../../crates/crate_interface" } +crate_interface = "0.1.1" cfg-if = "1.0" elf = { version = "0.7", default-features = false } diff --git a/api/ruxos_posix_api/src/lib.rs b/api/ruxos_posix_api/src/lib.rs index 0a0a8debd..5bd396cee 100644 --- a/api/ruxos_posix_api/src/lib.rs +++ b/api/ruxos_posix_api/src/lib.rs @@ -13,7 +13,6 @@ #![cfg_attr(all(not(test), not(doc)), no_std)] #![feature(ip_in_core)] -#![feature(result_option_inspect)] #![feature(doc_cfg)] #![feature(doc_auto_cfg)] #![allow(clippy::missing_safety_doc)] diff --git a/apps/c/dl/features.txt b/apps/c/dl/features.txt index 0b7506227..ed120d4d3 100644 --- a/apps/c/dl/features.txt +++ b/apps/c/dl/features.txt @@ -8,4 +8,4 @@ pipe poll rtc signal -virtio-9p \ No newline at end of file +virtio-9p diff --git a/apps/fs/shell/Cargo.toml b/apps/fs/shell/Cargo.toml index 25d70a3af..069c77a3b 100644 --- a/apps/fs/shell/Cargo.toml +++ b/apps/fs/shell/Cargo.toml @@ -13,5 +13,5 @@ default = [] [dependencies] axfs_vfs = { path = "../../../crates/axfs_vfs", optional = true } axfs_ramfs = { path = "../../../crates/axfs_ramfs", optional = true } -crate_interface = { path = "../../../crates/crate_interface", optional = true } +crate_interface = { version = "0.1.1", optional = true } axstd = { path = "../../../ulib/axstd", features = ["alloc", "fs","blkfs"], optional = true } diff --git a/crates/allocator/src/lib.rs b/crates/allocator/src/lib.rs index 8fd653b09..061c9f763 100644 --- a/crates/allocator/src/lib.rs +++ b/crates/allocator/src/lib.rs @@ -18,7 +18,6 @@ //! - [`IdAllocator`]: Used to allocate unique IDs. #![no_std] -#![feature(result_option_inspect)] #![cfg_attr(feature = "allocator_api", feature(allocator_api))] #[cfg(feature = "bitmap")] diff --git a/crates/crate_interface/Cargo.toml b/crates/crate_interface/Cargo.toml deleted file mode 100644 index 7608daea3..000000000 --- a/crates/crate_interface/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "crate_interface" -version = "0.1.1" -edition = "2021" -authors = ["Yuekai Jia "] -description = "Provides a way to define an interface (trait) in a crate, but can implement or use it in any crate." -license = "GPL-3.0-or-later OR Apache-2.0" -homepage = "https://github.com/rcore-os/arceos" -repository = "https://github.com/rcore-os/arceos/tree/main/crates/crate_interface" -documentation = "https://rcore-os.github.io/arceos/crate_interface/index.html" -keywords = ["arceos", "api", "macro"] -categories = ["development-tools::procedural-macro-helpers", "no-std"] - -[dependencies] -proc-macro2 = "1.0" -quote = "1.0" -syn = { version = "2.0", features = ["full"] } - -[lib] -proc-macro = true diff --git a/crates/crate_interface/README.md b/crates/crate_interface/README.md deleted file mode 100644 index ca910ca7c..000000000 --- a/crates/crate_interface/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# crate_interface - -[![Crates.io](https://img.shields.io/crates/v/crate_interface)](https://crates.io/crates/crate_interface) - -Provides a way to **define** an interface (trait) in a crate, but can -**implement** or **use** it in any crate. It 's usually used to solve -the problem of *circular dependencies* between crates. - -## Example - -```rust -// Define the interface -#[crate_interface::def_interface] -pub trait HelloIf { - fn hello(&self, name: &str, id: usize) -> String; -} - -// Implement the interface in any crate -struct HelloIfImpl; - -#[crate_interface::impl_interface] -impl HelloIf for HelloIfImpl { - fn hello(&self, name: &str, id: usize) -> String { - format!("Hello, {} {}!", name, id) - } -} - -// Call `HelloIfImpl::hello` in any crate -use crate_interface::call_interface; -assert_eq!( - call_interface!(HelloIf::hello("world", 123)), - "Hello, world 123!" -); -assert_eq!( - call_interface!(HelloIf::hello, "rust", 456), // another calling style - "Hello, rust 456!" -); -``` diff --git a/crates/crate_interface/src/lib.rs b/crates/crate_interface/src/lib.rs deleted file mode 100644 index 6ae5e40fd..000000000 --- a/crates/crate_interface/src/lib.rs +++ /dev/null @@ -1,196 +0,0 @@ -/* Copyright (c) [2023] [Syswonder Community] - * [Ruxos] is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ - -#![doc = include_str!("../README.md")] -#![feature(iter_next_chunk)] - -use proc_macro::TokenStream; -use proc_macro2::Span; -use quote::{format_ident, quote}; -use syn::{Error, FnArg, ImplItem, ImplItemFn, ItemImpl, ItemTrait, TraitItem, Type}; - -fn compiler_error(err: Error) -> TokenStream { - err.to_compile_error().into() -} - -/// Define an interface. -/// -/// This attribute should be added above the definition of a trait. All traits -/// that use the attribute cannot have the same name. -/// -/// It is not necessary to define it in the same crate as the implementation, -/// but it is required that these crates are linked together. -/// -/// See the [crate-level documentation](crate) for more details. -#[proc_macro_attribute] -pub fn def_interface(attr: TokenStream, item: TokenStream) -> TokenStream { - if !attr.is_empty() { - return compiler_error(Error::new( - Span::call_site(), - "expect an empty attribute: `#[crate_interface_def]`", - )); - } - - let ast = syn::parse_macro_input!(item as ItemTrait); - let trait_name = &ast.ident; - - let mut extern_fn_list = vec![]; - for item in &ast.items { - if let TraitItem::Fn(method) = item { - let mut sig = method.sig.clone(); - let fn_name = &sig.ident; - sig.ident = format_ident!("__{}_{}", trait_name, fn_name); - sig.inputs = syn::punctuated::Punctuated::new(); - - for arg in &method.sig.inputs { - if let FnArg::Typed(_) = arg { - sig.inputs.push(arg.clone()); - } - } - - let extern_fn = quote! { - #sig; - }; - extern_fn_list.push(extern_fn); - } - } - - quote! { - #ast - extern "Rust" { - #(#extern_fn_list)* - } - } - .into() -} - -/// Implement the interface for a struct. -/// -/// This attribute should be added above the implementation of a trait for a -/// struct, and the trait must be defined with -/// [`#[def_interface]`](macro@crate::def_interface). -/// -/// It is not necessary to implement it in the same crate as the definition, but -/// it is required that these crates are linked together. -/// -/// See the [crate-level documentation](crate) for more details. -#[proc_macro_attribute] -pub fn impl_interface(attr: TokenStream, item: TokenStream) -> TokenStream { - if !attr.is_empty() { - return compiler_error(Error::new( - Span::call_site(), - "expect an empty attribute: `#[crate_interface_impl]`", - )); - } - - let mut ast = syn::parse_macro_input!(item as ItemImpl); - let trait_name = if let Some((_, path, _)) = &ast.trait_ { - &path.segments.last().unwrap().ident - } else { - return compiler_error(Error::new_spanned(ast, "expect a trait implementation")); - }; - let impl_name = if let Type::Path(path) = &ast.self_ty.as_ref() { - path.path.get_ident().unwrap() - } else { - return compiler_error(Error::new_spanned(ast, "expect a trait implementation")); - }; - - for item in &mut ast.items { - if let ImplItem::Fn(method) = item { - let (attrs, vis, sig, stmts) = - (&method.attrs, &method.vis, &method.sig, &method.block.stmts); - let fn_name = &sig.ident; - let extern_fn_name = format_ident!("__{}_{}", trait_name, fn_name).to_string(); - - let mut new_sig = sig.clone(); - new_sig.ident = format_ident!("{}", extern_fn_name); - new_sig.inputs = syn::punctuated::Punctuated::new(); - - let mut args = vec![]; - let mut has_self = false; - for arg in &sig.inputs { - match arg { - FnArg::Receiver(_) => has_self = true, - FnArg::Typed(ty) => { - args.push(ty.pat.clone()); - new_sig.inputs.push(arg.clone()); - } - } - } - - let call_impl = if has_self { - quote! { - let IMPL: #impl_name = #impl_name; - IMPL.#fn_name( #(#args),* ) - } - } else { - quote! { #impl_name::#fn_name( #(#args),* ) } - }; - - let item = quote! { - #(#attrs)* - #vis - #sig - { - { - #[export_name = #extern_fn_name] - extern "Rust" #new_sig { - #call_impl - } - } - #(#stmts)* - } - } - .into(); - *method = syn::parse_macro_input!(item as ImplItemFn); - } - } - - quote! { #ast }.into() -} - -/// Call a function in the interface. -/// -/// It is not necessary to call it in the same crate as the implementation, but -/// it is required that these crates are linked together. -/// -/// See the [crate-level documentation](crate) for more details. -#[proc_macro] -pub fn call_interface(item: TokenStream) -> TokenStream { - parse_call_interface(item) - .unwrap_or_else(|msg| compiler_error(Error::new(Span::call_site(), msg))) -} - -fn parse_call_interface(item: TokenStream) -> Result { - let mut iter = item.into_iter(); - let tt = iter - .next_chunk::<4>() - .or(Err("expect `Trait::func`"))? - .map(|t| t.to_string()); - - let trait_name = &tt[0]; - if tt[1] != ":" || tt[2] != ":" { - return Err("missing `::`".into()); - } - let fn_name = &tt[3]; - let extern_fn_name = format!("__{}_{}", trait_name, fn_name); - - let mut args = iter.map(|x| x.to_string()).collect::>().join(""); - if args.starts_with(',') { - args.remove(0); - } else if args.starts_with('(') && args.ends_with(')') { - args.remove(0); - args.pop(); - } - - let call = format!("unsafe {{ {}( {} ) }}", extern_fn_name, args); - Ok(call - .parse::() - .or(Err("expect a correct argument list"))?) -} diff --git a/crates/crate_interface/tests/test_crate_interface.rs b/crates/crate_interface/tests/test_crate_interface.rs deleted file mode 100644 index a90079e5b..000000000 --- a/crates/crate_interface/tests/test_crate_interface.rs +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (c) [2023] [Syswonder Community] - * [Ruxos] is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ - -use crate_interface::*; - -#[def_interface] -trait SimpleIf { - fn foo() -> u32 { - 123 - } - - /// Test comments - fn bar(&self, a: u16, b: &[u8], c: &str); -} - -struct SimpleIfImpl; - -#[impl_interface] -impl SimpleIf for SimpleIfImpl { - #[inline] - fn foo() -> u32 { - 456 - } - - /// Test comments2 - fn bar(&self, a: u16, b: &[u8], c: &str) { - println!("{} {:?} {}", a, b, c); - assert_eq!(b[1], 3); - } -} - -#[test] -fn test_crate_interface_call() { - call_interface!(SimpleIf::bar, 123, &[2, 3, 5, 7, 11], "test"); - call_interface!(SimpleIf::bar(123, &[2, 3, 5, 7, 11], "test")); - assert_eq!(call_interface!(SimpleIf::foo), 456); -} diff --git a/crates/driver_9p/Cargo.toml b/crates/driver_9p/Cargo.toml index 8c07a9808..dd56965c8 100644 --- a/crates/driver_9p/Cargo.toml +++ b/crates/driver_9p/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" authors = ["Zheng Wu "] description = "Common traits and types for 9p drivers" -license = "GPL-3.0-or-later OR Apache-2.0" +license = "Mulan PSL v2" homepage = "https://github.com/syswonder/ruxos" repository = "https://github.com/syswonder/ruxos/tree/main/crates/driver_9p" diff --git a/crates/driver_display/Cargo.toml b/crates/driver_display/Cargo.toml index 5c8836802..a98048ec6 100644 --- a/crates/driver_display/Cargo.toml +++ b/crates/driver_display/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" authors = ["Shiping Yuan "] description = "Common traits and types for graphics device drivers" -license = "GPL-3.0-or-later OR Apache-2.0" +license = "Mulan PSL v2" homepage = "https://github.com/syswonder/ruxos" repository = "https://github.com/syswonder/ruxos/tree/main/crates/driver_display" diff --git a/crates/dtb/Cargo.toml b/crates/dtb/Cargo.toml index 64f5e1cb7..2f65516dd 100644 --- a/crates/dtb/Cargo.toml +++ b/crates/dtb/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" authors = ["Leping Wang "] description = "Device tree basic operations" -license = "GPL-3.0-or-later OR Apache-2.0" +license = "Mulan PSL v2" homepage = "https://github.com/syswonder/ruxos" repository = "https://github.com/syswonder/ruxos/tree/main/crates/dtb" diff --git a/crates/flatten_objects/src/lib.rs b/crates/flatten_objects/src/lib.rs index 25760028a..11387fb8b 100644 --- a/crates/flatten_objects/src/lib.rs +++ b/crates/flatten_objects/src/lib.rs @@ -39,7 +39,6 @@ //! ``` #![no_std] -#![feature(const_maybe_uninit_zeroed)] #![feature(maybe_uninit_uninit_array)] #![feature(const_maybe_uninit_uninit_array)] diff --git a/crates/handler_table/Cargo.toml b/crates/handler_table/Cargo.toml deleted file mode 100644 index e4ecacea9..000000000 --- a/crates/handler_table/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "handler_table" -version = "0.1.0" -edition = "2021" -authors = ["Yuekai Jia "] -description = "A lock-free table of event handlers" -license = "GPL-3.0-or-later OR Apache-2.0" -homepage = "https://github.com/rcore-os/arceos" -repository = "https://github.com/rcore-os/arceos/tree/main/crates/handler_table" -documentation = "https://rcore-os.github.io/arceos/handler_table/index.html" -keywords = ["arceos", "event", "lock-free"] -categories = ["no-std"] - -[dependencies] diff --git a/crates/handler_table/README.md b/crates/handler_table/README.md deleted file mode 100644 index 33878d1ad..000000000 --- a/crates/handler_table/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# handler_table - -[![Crates.io](https://img.shields.io/crates/v/handler_table)](https://crates.io/crates/handler_table) - -A lock-free table of event handlers. - -## Examples - -```rust -use handler_table::HandlerTable; - -static TABLE: HandlerTable<8> = HandlerTable::new(); - -TABLE.register_handler(0, || { - println!("Hello, event 0!"); -}); -TABLE.register_handler(1, || { - println!("Hello, event 1!"); -}); - -assert!(TABLE.handle(0)); // print "Hello, event 0!" -assert!(!TABLE.handle(2)); // unregistered -``` diff --git a/crates/handler_table/src/lib.rs b/crates/handler_table/src/lib.rs deleted file mode 100644 index efe992e53..000000000 --- a/crates/handler_table/src/lib.rs +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) [2023] [Syswonder Community] - * [Ruxos] is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ - -#![no_std] -#![doc = include_str!("../README.md")] - -use core::sync::atomic::{AtomicUsize, Ordering}; - -/// The type of an event handler. -/// -/// Currently no arguments and return values are supported. -pub type Handler = fn(); - -/// A lock-free table of event handlers. -/// -/// It internally uses an array of `AtomicUsize` to store the handlers. -pub struct HandlerTable { - handlers: [AtomicUsize; N], -} - -impl HandlerTable { - /// Creates a new handler table with all entries empty. - #[allow(clippy::declare_interior_mutable_const)] - pub const fn new() -> Self { - const EMPTY: AtomicUsize = AtomicUsize::new(0); - Self { - handlers: [EMPTY; N], - } - } - - /// Registers a handler for the given index. - pub fn register_handler(&self, idx: usize, handler: Handler) -> bool { - self.handlers[idx] - .compare_exchange(0, handler as usize, Ordering::Acquire, Ordering::Relaxed) - .is_ok() - } - - /// Handles the event with the given index. - /// - /// Returns `true` if the event is handled, `false` if no handler is - /// registered for the given index. - pub fn handle(&self, idx: usize) -> bool { - let handler = self.handlers[idx].load(Ordering::Acquire); - if handler != 0 { - let handler: Handler = unsafe { core::mem::transmute(handler) }; - handler(); - true - } else { - false - } - } -} diff --git a/crates/kernel_guard/Cargo.toml b/crates/kernel_guard/Cargo.toml deleted file mode 100644 index 841470199..000000000 --- a/crates/kernel_guard/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "kernel_guard" -version = "0.1.0" -edition = "2021" -authors = ["Yuekai Jia "] -description = "RAII wrappers to create a critical section with local IRQs or preemption disabled" -license = "GPL-3.0-or-later OR Apache-2.0" -homepage = "https://github.com/rcore-os/arceos" -repository = "https://github.com/rcore-os/arceos/tree/main/crates/kernel_guard" -documentation = "https://rcore-os.github.io/arceos/kernel_guard/index.html" -keywords = ["arceos", "synchronization", "preemption"] -categories = ["os", "no-std"] - -[features] -preempt = [] -default = [] - -[dependencies] -cfg-if = "1.0" -crate_interface = "0.1" diff --git a/crates/kernel_guard/README.md b/crates/kernel_guard/README.md deleted file mode 100644 index 4f137e084..000000000 --- a/crates/kernel_guard/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# kernel_guard - -[![Crates.io](https://img.shields.io/crates/v/kernel_guard)](https://crates.io/crates/kernel_guard) - -RAII wrappers to create a critical section with local IRQs or preemption -disabled, used to implement spin locks in kernel. - -The critical section is created after the guard struct is created, and is -ended when the guard falls out of scope. - -The crate user must implement the `KernelGuardIf` trait using -[`crate_interface::impl_interface`](https://crates.io/crates/crate_interface) to provide the low-level implementantion -of how to enable/disable kernel preemption, if the feature `preempt` is -enabled. - -Available guards: - -- `NoOp`: Does nothing around the critical section. -- `IrqSave`: Disables/enables local IRQs around the critical section. -- `NoPreempt`: Disables/enables kernel preemption around the critical -section. -- `NoPreemptIrqSave`: Disables/enables both kernel preemption and local -IRQs around the critical section. - -## Crate features - -- `preempt`: Use in the preemptive system. If this feature is enabled, you -need to implement the `KernelGuardIf` trait in other crates. Otherwise -the preemption enable/disable operations will be no-ops. This feature is -disabled by default. - -## Examples - -```rust -use kernel_guard::{KernelGuardIf, NoPreempt}; - -struct KernelGuardIfImpl; - -#[crate_interface::impl_interface] -impl KernelGuardIf for KernelGuardIfImpl { - fn enable_preempt() { - // Your implementation here - } - fn disable_preempt() { - // Your implementation here - } -} - -let guard = NoPreempt::new(); -/* The critical section starts here - -Do something that requires preemption to be disabled - -The critical section ends here */ -drop(guard); -``` diff --git a/crates/kernel_guard/src/arch/aarch64.rs b/crates/kernel_guard/src/arch/aarch64.rs deleted file mode 100644 index d8fe72831..000000000 --- a/crates/kernel_guard/src/arch/aarch64.rs +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (c) [2023] [Syswonder Community] - * [Ruxos] is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ - -use core::arch::asm; - -#[inline] -pub fn local_irq_save_and_disable() -> usize { - let flags: usize; - // save `DAIF` flags, mask `I` bit (disable IRQs) - unsafe { asm!("mrs {}, daif; msr daifset, #2", out(reg) flags) }; - flags -} - -#[inline] -pub fn local_irq_restore(flags: usize) { - unsafe { asm!("msr daif, {}", in(reg) flags) }; -} diff --git a/crates/kernel_guard/src/arch/mod.rs b/crates/kernel_guard/src/arch/mod.rs deleted file mode 100644 index c88782965..000000000 --- a/crates/kernel_guard/src/arch/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (c) [2023] [Syswonder Community] - * [Ruxos] is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ - -#![cfg_attr(not(target_os = "none"), allow(dead_code))] - -cfg_if::cfg_if! { - if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] { - mod x86; - pub use self::x86::*; - } else if #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] { - mod riscv; - pub use self::riscv::*; - } else if #[cfg(target_arch = "aarch64")] { - mod aarch64; - pub use self::aarch64::*; - } -} diff --git a/crates/kernel_guard/src/arch/riscv.rs b/crates/kernel_guard/src/arch/riscv.rs deleted file mode 100644 index c11f7e180..000000000 --- a/crates/kernel_guard/src/arch/riscv.rs +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (c) [2023] [Syswonder Community] - * [Ruxos] is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ - -use core::arch::asm; - -/// Bit 1: Supervisor Interrupt Enable -const SIE_BIT: usize = 1 << 1; - -#[inline] -pub fn local_irq_save_and_disable() -> usize { - let flags: usize; - // clear the `SIE` bit, and return the old CSR - unsafe { asm!("csrrc {}, sstatus, {}", out(reg) flags, const SIE_BIT) }; - flags & SIE_BIT -} - -#[inline] -pub fn local_irq_restore(flags: usize) { - // restore the `SIE` bit - unsafe { asm!("csrrs x0, sstatus, {}", in(reg) flags) }; -} diff --git a/crates/kernel_guard/src/arch/x86.rs b/crates/kernel_guard/src/arch/x86.rs deleted file mode 100644 index 272b2659a..000000000 --- a/crates/kernel_guard/src/arch/x86.rs +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (c) [2023] [Syswonder Community] - * [Ruxos] is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ - -use core::arch::asm; - -/// Interrupt Enable Flag (IF) -const IF_BIT: usize = 1 << 9; - -#[inline] -pub fn local_irq_save_and_disable() -> usize { - let flags: usize; - unsafe { asm!("pushf; pop {}; cli", out(reg) flags) }; - flags & IF_BIT -} - -#[inline] -pub fn local_irq_restore(flags: usize) { - if flags != 0 { - unsafe { asm!("sti") }; - } else { - unsafe { asm!("cli") }; - } -} diff --git a/crates/kernel_guard/src/lib.rs b/crates/kernel_guard/src/lib.rs deleted file mode 100644 index ebe97c7ad..000000000 --- a/crates/kernel_guard/src/lib.rs +++ /dev/null @@ -1,248 +0,0 @@ -/* Copyright (c) [2023] [Syswonder Community] - * [Ruxos] is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ - -//! RAII wrappers to create a critical section with local IRQs or preemption -//! disabled, used to implement spin locks in kernel. -//! -//! The critical section is created after the guard struct is created, and is -//! ended when the guard falls out of scope. -//! -//! The crate user must implement the [`KernelGuardIf`] trait using -//! [`crate_interface::impl_interface`] to provide the low-level implementantion -//! of how to enable/disable kernel preemption, if the feature `preempt` is -//! enabled. -//! -//! Available guards: -//! -//! - [`NoOp`]: Does nothing around the critical section. -//! - [`IrqSave`]: Disables/enables local IRQs around the critical section. -//! - [`NoPreempt`]: Disables/enables kernel preemption around the critical -//! section. -//! - [`NoPreemptIrqSave`]: Disables/enables both kernel preemption and local -//! IRQs around the critical section. -//! -//! # Crate features -//! -//! - `preempt`: Use in the preemptive system. If this feature is enabled, you -//! need to implement the [`KernelGuardIf`] trait in other crates. Otherwise -//! the preemption enable/disable operations will be no-ops. This feature is -//! disabled by default. -//! -//! # Examples -//! -//! ``` -//! use kernel_guard::{KernelGuardIf, NoPreempt}; -//! -//! struct KernelGuardIfImpl; -//! -//! #[crate_interface::impl_interface] -//! impl KernelGuardIf for KernelGuardIfImpl { -//! fn enable_preempt() { -//! // Your implementation here -//! } -//! fn disable_preempt() { -//! // Your implementation here -//! } -//! } -//! -//! let guard = NoPreempt::new(); -//! /* The critical section starts here -//! -//! Do something that requires preemption to be disabled -//! -//! The critical section ends here */ -//! drop(guard); -//! ``` - -#![no_std] -#![feature(asm_const)] - -mod arch; - -/// Low-level interfaces that must be implemented by the crate user. -#[crate_interface::def_interface] -pub trait KernelGuardIf { - /// How to enable kernel preemption. - fn enable_preempt(); - - /// How to disable kernel preemption. - fn disable_preempt(); -} - -/// A base trait that all guards implement. -pub trait BaseGuard { - /// The saved state when entering the critical section. - type State: Clone + Copy; - - /// Something that must be done before entering the critical section. - fn acquire() -> Self::State; - - /// Something that must be done after leaving the critical section. - fn release(state: Self::State); -} - -/// A no-op guard that does nothing around the critical section. -pub struct NoOp; - -cfg_if::cfg_if! { - // For user-mode std apps, we use the alias of [`NoOp`] for all guards, - // since we can not disable IRQs or preemption in user-mode. - if #[cfg(any(target_os = "none", doc))] { - /// A guard that disables/enables local IRQs around the critical section. - pub struct IrqSave(usize); - - /// A guard that disables/enables kernel preemption around the critical - /// section. - pub struct NoPreempt; - - /// A guard that disables/enables both kernel preemption and local IRQs - /// around the critical section. - /// - /// When entering the critical section, it disables kernel preemption - /// first, followed by local IRQs. When leaving the critical section, it - /// re-enables local IRQs first, followed by kernel preemption. - pub struct NoPreemptIrqSave(usize); - } else { - /// Alias of [`NoOp`]. - pub type IrqSave = NoOp; - - /// Alias of [`NoOp`]. - pub type NoPreempt = NoOp; - - /// Alias of [`NoOp`]. - pub type NoPreemptIrqSave = NoOp; - } -} - -impl BaseGuard for NoOp { - type State = (); - fn acquire() -> Self::State {} - fn release(_state: Self::State) {} -} - -impl NoOp { - /// Creates a new [`NoOp`] guard. - pub const fn new() -> Self { - Self - } -} - -impl Drop for NoOp { - fn drop(&mut self) {} -} - -#[cfg(any(target_os = "none", doc))] -mod imp { - use super::*; - - impl BaseGuard for IrqSave { - type State = usize; - - #[inline] - fn acquire() -> Self::State { - super::arch::local_irq_save_and_disable() - } - - #[inline] - fn release(state: Self::State) { - // restore IRQ states - super::arch::local_irq_restore(state); - } - } - - impl BaseGuard for NoPreempt { - type State = (); - fn acquire() -> Self::State { - // disable preempt - #[cfg(feature = "preempt")] - crate_interface::call_interface!(KernelGuardIf::disable_preempt); - } - fn release(_state: Self::State) { - // enable preempt - #[cfg(feature = "preempt")] - crate_interface::call_interface!(KernelGuardIf::enable_preempt); - } - } - - impl BaseGuard for NoPreemptIrqSave { - type State = usize; - fn acquire() -> Self::State { - // disable preempt - #[cfg(feature = "preempt")] - crate_interface::call_interface!(KernelGuardIf::disable_preempt); - // disable IRQs and save IRQ states - super::arch::local_irq_save_and_disable() - } - fn release(state: Self::State) { - // restore IRQ states - super::arch::local_irq_restore(state); - // enable preempt - #[cfg(feature = "preempt")] - crate_interface::call_interface!(KernelGuardIf::enable_preempt); - } - } - - impl IrqSave { - /// Creates a new [`IrqSave`] guard. - pub fn new() -> Self { - Self(Self::acquire()) - } - } - - impl Drop for IrqSave { - fn drop(&mut self) { - Self::release(self.0) - } - } - - impl Default for IrqSave { - fn default() -> Self { - Self::new() - } - } - - impl NoPreempt { - /// Creates a new [`NoPreempt`] guard. - pub fn new() -> Self { - Self::acquire(); - Self - } - } - - impl Drop for NoPreempt { - fn drop(&mut self) { - Self::release(()) - } - } - - impl Default for NoPreempt { - fn default() -> Self { - Self::new() - } - } - - impl NoPreemptIrqSave { - /// Creates a new [`NoPreemptIrqSave`] guard. - pub fn new() -> Self { - Self(Self::acquire()) - } - } - - impl Drop for NoPreemptIrqSave { - fn drop(&mut self) { - Self::release(self.0) - } - } - - impl Default for NoPreemptIrqSave { - fn default() -> Self { - Self::new() - } - } -} diff --git a/crates/memory_addr/Cargo.toml b/crates/memory_addr/Cargo.toml deleted file mode 100644 index 1b900359d..000000000 --- a/crates/memory_addr/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "memory_addr" -version = "0.1.0" -edition = "2021" -authors = ["Yuekai Jia "] -description = "Wrappers and helper functions for physical and virtual addresses" -license = "GPL-3.0-or-later OR Apache-2.0" -homepage = "https://github.com/rcore-os/arceos" -repository = "https://github.com/rcore-os/arceos/tree/main/crates/memory_addr" -documentation = "https://rcore-os.github.io/arceos/memory_addr/index.html" -keywords = ["arceos", "address", "virtual-memory"] -categories = ["os", "memory-management", "no-std"] - -[dependencies] diff --git a/crates/memory_addr/README.md b/crates/memory_addr/README.md deleted file mode 100644 index 2b1768b5f..000000000 --- a/crates/memory_addr/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# memory_addr - -[![Crates.io](https://img.shields.io/crates/v/memory_addr)](https://crates.io/crates/memory_addr) - -Wrappers and helper functions for physical and virtual memory addresses. - -## Examples - -```rust -use memory_addr::{PhysAddr, VirtAddr}; - -let phys_addr = PhysAddr::from(0x12345678); -let virt_addr = VirtAddr::from(0x87654321); - -assert_eq!(phys_addr.align_down(0x1000usize), PhysAddr::from(0x12345000)); -assert_eq!(phys_addr.align_offset_4k(), 0x678); -assert_eq!(virt_addr.align_up_4k(), VirtAddr::from(0x87655000)); -assert!(!virt_addr.is_aligned_4k()); -assert!(VirtAddr::from(0xabcedf0).is_aligned(16usize)); -``` diff --git a/crates/memory_addr/src/lib.rs b/crates/memory_addr/src/lib.rs deleted file mode 100644 index 55646faf0..000000000 --- a/crates/memory_addr/src/lib.rs +++ /dev/null @@ -1,393 +0,0 @@ -/* Copyright (c) [2023] [Syswonder Community] - * [Ruxos] is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * http://license.coscl.org.cn/MulanPSL2 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ - -#![no_std] -#![feature(const_mut_refs)] -#![doc = include_str!("../README.md")] - -use core::fmt; -use core::ops::{Add, AddAssign, Sub, SubAssign}; - -/// The size of a 4K page (4096 bytes). -pub const PAGE_SIZE_4K: usize = 0x1000; - -/// Align address downwards. -/// -/// Returns the greatest `x` with alignment `align` so that `x <= addr`. -/// -/// The alignment must be a power of two. -#[inline] -pub const fn align_down(addr: usize, align: usize) -> usize { - addr & !(align - 1) -} - -/// Align address upwards. -/// -/// Returns the smallest `x` with alignment `align` so that `x >= addr`. -/// -/// The alignment must be a power of two. -#[inline] -pub const fn align_up(addr: usize, align: usize) -> usize { - (addr + align - 1) & !(align - 1) -} - -/// Returns the offset of the address within the alignment. -/// -/// Equivalent to `addr % align`, but the alignment must be a power of two. -#[inline] -pub const fn align_offset(addr: usize, align: usize) -> usize { - addr & (align - 1) -} - -/// Checks whether the address has the demanded alignment. -/// -/// Equivalent to `addr % align == 0`, but the alignment must be a power of two. -#[inline] -pub const fn is_aligned(addr: usize, align: usize) -> bool { - align_offset(addr, align) == 0 -} - -/// Align address downwards to 4096 (bytes). -#[inline] -pub const fn align_down_4k(addr: usize) -> usize { - align_down(addr, PAGE_SIZE_4K) -} - -/// Align address upwards to 4096 (bytes). -#[inline] -pub const fn align_up_4k(addr: usize) -> usize { - align_up(addr, PAGE_SIZE_4K) -} - -/// Returns the offset of the address within a 4K-sized page. -#[inline] -pub const fn align_offset_4k(addr: usize) -> usize { - align_offset(addr, PAGE_SIZE_4K) -} - -/// Checks whether the address is 4K-aligned. -#[inline] -pub const fn is_aligned_4k(addr: usize) -> bool { - is_aligned(addr, PAGE_SIZE_4K) -} - -/// A physical memory address. -/// -/// It's a wrapper type around an `usize`. -#[repr(transparent)] -#[derive(Copy, Clone, Default, Ord, PartialOrd, Eq, PartialEq)] -pub struct PhysAddr(usize); - -/// A virtual memory address. -/// -/// It's a wrapper type around an `usize`. -#[repr(transparent)] -#[derive(Copy, Clone, Default, Ord, PartialOrd, Eq, PartialEq)] -pub struct VirtAddr(usize); - -impl PhysAddr { - /// Converts an `usize` to a physical address. - #[inline] - pub const fn from(addr: usize) -> Self { - Self(addr) - } - - /// Converts the address to an `usize`. - #[inline] - pub const fn as_usize(self) -> usize { - self.0 - } - - /// Aligns the address downwards to the given alignment. - /// - /// See the [`align_down`] function for more information. - #[inline] - pub fn align_down(self, align: U) -> Self - where - U: Into, - { - Self(align_down(self.0, align.into())) - } - - /// Aligns the address upwards to the given alignment. - /// - /// See the [`align_up`] function for more information. - #[inline] - pub fn align_up(self, align: U) -> Self - where - U: Into, - { - Self(align_up(self.0, align.into())) - } - - /// Returns the offset of the address within the given alignment. - /// - /// See the [`align_offset`] function for more information. - #[inline] - pub fn align_offset(self, align: U) -> usize - where - U: Into, - { - align_offset(self.0, align.into()) - } - - /// Checks whether the address has the demanded alignment. - /// - /// See the [`is_aligned`] function for more information. - #[inline] - pub fn is_aligned(self, align: U) -> bool - where - U: Into, - { - is_aligned(self.0, align.into()) - } - - /// Aligns the address downwards to 4096 (bytes). - #[inline] - pub fn align_down_4k(self) -> Self { - self.align_down(PAGE_SIZE_4K) - } - - /// Aligns the address upwards to 4096 (bytes). - #[inline] - pub fn align_up_4k(self) -> Self { - self.align_up(PAGE_SIZE_4K) - } - - /// Returns the offset of the address within a 4K-sized page. - #[inline] - pub fn align_offset_4k(self) -> usize { - self.align_offset(PAGE_SIZE_4K) - } - - /// Checks whether the address is 4K-aligned. - #[inline] - pub fn is_aligned_4k(self) -> bool { - self.is_aligned(PAGE_SIZE_4K) - } -} - -impl VirtAddr { - /// Converts an `usize` to a virtual address. - #[inline] - pub const fn from(addr: usize) -> Self { - Self(addr) - } - - /// Converts the address to an `usize`. - #[inline] - pub const fn as_usize(self) -> usize { - self.0 - } - - /// Converts the virtual address to a raw pointer. - #[inline] - pub const fn as_ptr(self) -> *const u8 { - self.0 as *const u8 - } - - /// Converts the virtual address to a mutable raw pointer. - #[inline] - pub const fn as_mut_ptr(self) -> *mut u8 { - self.0 as *mut u8 - } - - /// Aligns the address downwards to the given alignment. - /// - /// See the [`align_down`] function for more information. - #[inline] - pub fn align_down(self, align: U) -> Self - where - U: Into, - { - Self(align_down(self.0, align.into())) - } - - /// Aligns the address upwards to the given alignment. - /// - /// See the [`align_up`] function for more information. - #[inline] - pub fn align_up(self, align: U) -> Self - where - U: Into, - { - Self(align_up(self.0, align.into())) - } - - /// Returns the offset of the address within the given alignment. - /// - /// See the [`align_offset`] function for more information. - #[inline] - pub fn align_offset(self, align: U) -> usize - where - U: Into, - { - align_offset(self.0, align.into()) - } - - /// Checks whether the address has the demanded alignment. - /// - /// See the [`is_aligned`] function for more information. - #[inline] - pub fn is_aligned(self, align: U) -> bool - where - U: Into, - { - is_aligned(self.0, align.into()) - } - - /// Aligns the address downwards to 4096 (bytes). - #[inline] - pub fn align_down_4k(self) -> Self { - self.align_down(PAGE_SIZE_4K) - } - - /// Aligns the address upwards to 4096 (bytes). - #[inline] - pub fn align_up_4k(self) -> Self { - self.align_up(PAGE_SIZE_4K) - } - - /// Returns the offset of the address within a 4K-sized page. - #[inline] - pub fn align_offset_4k(self) -> usize { - self.align_offset(PAGE_SIZE_4K) - } - - /// Checks whether the address is 4K-aligned. - #[inline] - pub fn is_aligned_4k(self) -> bool { - self.is_aligned(PAGE_SIZE_4K) - } -} - -impl From for PhysAddr { - #[inline] - fn from(addr: usize) -> Self { - Self(addr) - } -} - -impl From for VirtAddr { - #[inline] - fn from(addr: usize) -> Self { - Self(addr) - } -} - -impl From for usize { - #[inline] - fn from(addr: PhysAddr) -> usize { - addr.0 - } -} - -impl From for usize { - #[inline] - fn from(addr: VirtAddr) -> usize { - addr.0 - } -} - -impl Add for PhysAddr { - type Output = Self; - #[inline] - fn add(self, rhs: usize) -> Self { - Self(self.0 + rhs) - } -} - -impl AddAssign for PhysAddr { - #[inline] - fn add_assign(&mut self, rhs: usize) { - *self = *self + rhs; - } -} - -impl Sub for PhysAddr { - type Output = Self; - #[inline] - fn sub(self, rhs: usize) -> Self { - Self(self.0 - rhs) - } -} - -impl SubAssign for PhysAddr { - #[inline] - fn sub_assign(&mut self, rhs: usize) { - *self = *self - rhs; - } -} - -impl Add for VirtAddr { - type Output = Self; - #[inline] - fn add(self, rhs: usize) -> Self { - Self(self.0 + rhs) - } -} - -impl AddAssign for VirtAddr { - #[inline] - fn add_assign(&mut self, rhs: usize) { - *self = *self + rhs; - } -} - -impl Sub for VirtAddr { - type Output = Self; - #[inline] - fn sub(self, rhs: usize) -> Self { - Self(self.0 - rhs) - } -} - -impl SubAssign for VirtAddr { - #[inline] - fn sub_assign(&mut self, rhs: usize) { - *self = *self - rhs; - } -} - -impl fmt::Debug for PhysAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_fmt(format_args!("PA:{:#x}", self.0)) - } -} - -impl fmt::Debug for VirtAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_fmt(format_args!("VA:{:#x}", self.0)) - } -} - -impl fmt::LowerHex for PhysAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_fmt(format_args!("PA:{:#x}", self.0)) - } -} - -impl fmt::UpperHex for PhysAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_fmt(format_args!("PA:{:#X}", self.0)) - } -} - -impl fmt::LowerHex for VirtAddr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_fmt(format_args!("VA:{:#x}", self.0)) - } -} - -impl fmt::UpperHex for VirtAddr { - #[inline] - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_fmt(format_args!("VA:{:#X}", self.0)) - } -} diff --git a/crates/page_table/Cargo.toml b/crates/page_table/Cargo.toml index 4178458b1..6cc0ff95c 100644 --- a/crates/page_table/Cargo.toml +++ b/crates/page_table/Cargo.toml @@ -11,5 +11,5 @@ documentation = "https://rcore-os.github.io/arceos/page_table/index.html" [dependencies] log = "0.4" -memory_addr = { path = "../memory_addr" } +memory_addr = "0.1.0" page_table_entry = { path = "../page_table_entry" } diff --git a/crates/page_table/src/lib.rs b/crates/page_table/src/lib.rs index 1ff711300..a86a95658 100644 --- a/crates/page_table/src/lib.rs +++ b/crates/page_table/src/lib.rs @@ -28,7 +28,6 @@ #![no_std] #![feature(const_trait_impl)] -#![feature(result_option_inspect)] #![feature(doc_auto_cfg)] #[macro_use] diff --git a/crates/page_table_entry/Cargo.toml b/crates/page_table_entry/Cargo.toml index 2a86e6b7a..c42558047 100644 --- a/crates/page_table_entry/Cargo.toml +++ b/crates/page_table_entry/Cargo.toml @@ -12,7 +12,7 @@ documentation = "https://rcore-os.github.io/arceos/page_table_entry/index.html" [dependencies] log = "0.4" bitflags = "2.2" -memory_addr = { path = "../memory_addr" } +memory_addr = "0.1.0" aarch64-cpu = "9.3" # TODO: put it in [target.'cfg(target_arch = "aarch64")'.dependencies] [target.'cfg(target_arch = "x86_64")'.dependencies] diff --git a/crates/percpu/Cargo.toml b/crates/percpu/Cargo.toml index 864169122..25f82144e 100644 --- a/crates/percpu/Cargo.toml +++ b/crates/percpu/Cargo.toml @@ -20,7 +20,7 @@ default = [] [dependencies] cfg-if = "1.0" -kernel_guard = { path = "../kernel_guard", optional = true } +kernel_guard = { version = "0.1.0", optional = true } percpu_macros = { path = "../percpu_macros" } [target.'cfg(target_arch = "x86_64")'.dependencies] diff --git a/crates/spinlock/Cargo.toml b/crates/spinlock/Cargo.toml index 1dd75e3d2..4cd97499d 100644 --- a/crates/spinlock/Cargo.toml +++ b/crates/spinlock/Cargo.toml @@ -16,4 +16,4 @@ default = [] [dependencies] cfg-if = "1.0" -kernel_guard = { path = "../kernel_guard" } +kernel_guard = "0.1.0" diff --git a/doc/README.md b/doc/README.md index 5d0a93ca5..43706d0b6 100644 --- a/doc/README.md +++ b/doc/README.md @@ -28,7 +28,6 @@ * [axfs_vfs](../crates/axfs_vfs): Virtual filesystem interfaces used by Ruxos. * [axio](../crates/axio): `std::io`-like I/O traits for `no_std` environment. * [capability](../crates/capability): Provide basic capability-based security. -* [crate_interface](../crates/crate_interface): Provides a way to define an interface (trait) in a crate, but can implement or use it in any crate. [![Crates.io](https://img.shields.io/crates/v/crate_interface)](https://crates.io/crates/crate_interface) * [driver_9p](../crates/driver_9p/): Basic 9pfs operation traits for 9p protocol drivers. * [driver_block](../crates/driver_block): Common traits and types for block storage drivers. * [driver_common](../crates/driver_common): Device driver interfaces used by Ruxos. @@ -37,11 +36,8 @@ * [driver_pci](../crates/driver_pci): Structures and functions for PCI bus operations. * [driver_virtio](../crates/driver_virtio): Wrappers of some devices in the `virtio-drivers` crate, that implement traits in the `driver_common` series crates. * [flatten_objects](../crates/flatten_objects): A container that stores numbered objects. Each object can be assigned with a unique ID. -* [handler_table](../crates/handler_table): A lock-free table of event handlers. [![Crates.io](https://img.shields.io/crates/v/handler_table)](https://crates.io/crates/handler_table) -* [kernel_guard](../crates/kernel_guard): RAII wrappers to create a critical section with local IRQs or preemption disabled. [![Crates.io](https://img.shields.io/crates/v/kernel_guard)](https://crates.io/crates/kernel_guard) * [lazy_init](../crates/lazy_init): A wrapper for lazy initialized values without concurrency safety but more efficient. * [linked_list](../crates/linked_list): Linked lists that supports arbitrary removal in constant time. -* [memory_addr](../crates/memory_addr): Wrappers and helper functions for physical and virtual addresses. [![Crates.io](https://img.shields.io/crates/v/memory_addr)](https://crates.io/crates/memory_addr) * [page_table](../crates/page_table): Generic page table structures for various hardware architectures. * [page_table_entry](../crates/page_table_entry): Page table entry definition for various hardware architectures. * [percpu](../crates/percpu): Define and access per-CPU data structures. diff --git a/modules/axalloc/Cargo.toml b/modules/axalloc/Cargo.toml index 40eedf404..311476037 100644 --- a/modules/axalloc/Cargo.toml +++ b/modules/axalloc/Cargo.toml @@ -19,6 +19,6 @@ buddy = ["allocator/buddy"] log = "0.4" cfg-if = "1.0" spinlock = { path = "../../crates/spinlock" } -memory_addr = { path = "../../crates/memory_addr" } +memory_addr = "0.1.0" allocator = { path = "../../crates/allocator", features = ["bitmap"] } axerrno = { path = "../../crates/axerrno" } diff --git a/modules/axlog/Cargo.toml b/modules/axlog/Cargo.toml index a679060a4..98ecdcf70 100644 --- a/modules/axlog/Cargo.toml +++ b/modules/axlog/Cargo.toml @@ -23,7 +23,7 @@ default = [] cfg-if = "1.0" log = "0.4" spinlock = { path = "../../crates/spinlock" } -crate_interface = { path = "../../crates/crate_interface" } +crate_interface = { version = "0.1.1" } chrono = { version = "0.4", optional = true } [dev-dependencies] diff --git a/modules/rux9p/Cargo.toml b/modules/rux9p/Cargo.toml index a792d24f1..e24320b2a 100644 --- a/modules/rux9p/Cargo.toml +++ b/modules/rux9p/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" authors = ["Zheng Wu "] description = "RuxOS Plan-9 filesystem module" -license = "GPL-3.0-or-later OR Apache-2.0" +license = "Mulan PSL v2" homepage = "https://github.com/syswonder/ruxos" repository = "https://github.com/syswonder/ruxos/tree/main/modules/rux9p" diff --git a/modules/ruxdisplay/Cargo.toml b/modules/ruxdisplay/Cargo.toml index d4daaef87..33ab19f23 100644 --- a/modules/ruxdisplay/Cargo.toml +++ b/modules/ruxdisplay/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" authors = ["Shiping Yuan "] description = "Ruxos graphics module" -license = "GPL-3.0-or-later OR Apache-2.0" +license = "Mulan PSL v2" homepage = "https://github.com/syswonder/ruxos" repository = "https://github.com/syswonder/ruxos/tree/main/modules/ruxdisplay" diff --git a/modules/ruxfs/Cargo.toml b/modules/ruxfs/Cargo.toml index 91d3356c7..6b95596e9 100644 --- a/modules/ruxfs/Cargo.toml +++ b/modules/ruxfs/Cargo.toml @@ -38,9 +38,9 @@ axfs_devfs = { path = "../../crates/axfs_devfs", optional = true } axfs_ramfs = { path = "../../crates/axfs_ramfs", optional = true } ruxdriver = { path = "../ruxdriver", features = ["block"] } axsync = { path = "../axsync" } -crate_interface = { path = "../../crates/crate_interface", optional = true } +crate_interface = { version = "0.1.1", optional = true } axalloc = { path = "../axalloc", optional = true } -memory_addr = { path = "../../crates/memory_addr" } +memory_addr = "0.1.0" [dependencies.fatfs] git = "https://github.com/rafalh/rust-fatfs" diff --git a/modules/ruxfs/src/mounts.rs b/modules/ruxfs/src/mounts.rs index b6dbf224f..b5d74cae0 100644 --- a/modules/ruxfs/src/mounts.rs +++ b/modules/ruxfs/src/mounts.rs @@ -18,16 +18,13 @@ use crate::fs; pub(crate) fn devfs() -> Arc { let null = fs::devfs::NullDev; let zero = fs::devfs::ZeroDev; - let bar = fs::devfs::ZeroDev; let random = fs::devfs::RandomDev; let urandom = fs::devfs::RandomDev; let devfs = fs::devfs::DeviceFileSystem::new(); - let foo_dir = devfs.mkdir("foo"); devfs.add("null", Arc::new(null)); devfs.add("zero", Arc::new(zero)); devfs.add("random", Arc::new(random)); devfs.add("urandom", Arc::new(urandom)); - foo_dir.add("bar", Arc::new(bar)); Arc::new(devfs) } diff --git a/modules/ruxfs/src/root.rs b/modules/ruxfs/src/root.rs index 4d381cfdb..eb19f2c60 100644 --- a/modules/ruxfs/src/root.rs +++ b/modules/ruxfs/src/root.rs @@ -162,7 +162,11 @@ impl VfsNodeOps for RootDirectory { } pub(crate) fn init_rootfs(mount_points: Vec) { - let main_fs = mount_points.get(0).expect("No filesystem found").fs.clone(); + let main_fs = mount_points + .first() + .expect("No filesystem found") + .fs + .clone(); let mut root_dir = RootDirectory::new(main_fs); for mp in mount_points.iter().skip(1) { diff --git a/modules/ruxfs/tests/test_common/mod.rs b/modules/ruxfs/tests/test_common/mod.rs index 37a085f75..2eee93c9d 100644 --- a/modules/ruxfs/tests/test_common/mod.rs +++ b/modules/ruxfs/tests/test_common/mod.rs @@ -217,14 +217,6 @@ fn test_devfs_ramfs() -> Result<()> { assert!(!md.is_file()); assert!(md.is_dir()); - // stat /dev/foo/bar - let fname = ".//.///././/./dev///.///./foo//././bar"; - let file = File::open(fname)?; - let md = file.metadata()?; - println!("metadata of {:?}: {:?}", fname, md); - assert_eq!(md.file_type(), FileType::CharDevice); - assert!(!md.is_dir()); - // error cases assert_err!(fs::metadata("/dev/null/"), NotADirectory); assert_err!(fs::create_dir("dev"), AlreadyExists); @@ -242,7 +234,6 @@ fn test_devfs_ramfs() -> Result<()> { assert_eq!(fs::write(".///dev//..//233//.///test.txt", "test"), Ok(())); assert_err!(fs::remove_file("./dev//../..//233//.///test.txt"), NotFound); assert_eq!(fs::remove_file("./dev//..//233//../233/./test.txt"), Ok(())); - assert_eq!(fs::remove_dir("dev//foo/../foo/../.././/233"), Ok(())); assert_err!(fs::remove_dir("very/../dev//"), PermissionDenied); // tests in /tmp diff --git a/modules/ruxfutex/Cargo.toml b/modules/ruxfutex/Cargo.toml index a3c5e50ed..c4f2d8a10 100644 --- a/modules/ruxfutex/Cargo.toml +++ b/modules/ruxfutex/Cargo.toml @@ -5,7 +5,7 @@ version = "0.1.0" edition = "2021" authors = ["Zhi Zhou "] description = "Ruxos futex implementation" -license = "GPL-3.0-or-later OR Apache-2.0" +license = "Mulan PSL v2" homepage = "https://github.com/syswonder/ruxos" repository = "https://github.com/syswonder/ruxos/tree/main/modules/ruxfutex" @@ -15,7 +15,7 @@ default = [] irq = ["ruxtask/irq"] [dependencies] -# Ruxos modules +# RuxOS modules axerrno = { path = "../../crates/axerrno" } ruxconfig = { path = "../ruxconfig" } @@ -30,4 +30,4 @@ ahash = { version = "0.8.7", default-features = false, features = [ ] } [dev-dependencies] -memory_addr = { path = "../../crates/memory_addr" } +memory_addr = "0.1.0" diff --git a/modules/ruxhal/Cargo.toml b/modules/ruxhal/Cargo.toml index 0e5186f1b..d485d82a8 100644 --- a/modules/ruxhal/Cargo.toml +++ b/modules/ruxhal/Cargo.toml @@ -31,16 +31,16 @@ embedded-hal = "0.2.7" axlog = { path = "../axlog" } ruxconfig = { path = "../ruxconfig" } axalloc = { path = "../axalloc", optional = true } -kernel_guard = { path = "../../crates/kernel_guard" } +kernel_guard = "0.1.0" spinlock = { path = "../../crates/spinlock" } ratio = { path = "../../crates/ratio" } lazy_init = { path = "../../crates/lazy_init" } page_table = { path = "../../crates/page_table", optional = true } page_table_entry = { path = "../../crates/page_table_entry" } percpu = { path = "../../crates/percpu" } -memory_addr = { path = "../../crates/memory_addr" } -handler_table = { path = "../../crates/handler_table" } -crate_interface = { path = "../../crates/crate_interface" } +memory_addr = "0.1.0" +handler_table = "0.1.0" +crate_interface = "0.1.1" [target.'cfg(target_arch = "x86_64")'.dependencies] x86 = "0.52" diff --git a/modules/ruxhal/src/lib.rs b/modules/ruxhal/src/lib.rs index 3785e3498..fcb78a72d 100644 --- a/modules/ruxhal/src/lib.rs +++ b/modules/ruxhal/src/lib.rs @@ -36,7 +36,6 @@ #![no_std] #![feature(asm_const)] #![feature(naked_functions)] -#![feature(const_maybe_uninit_zeroed)] #![feature(const_option)] #![feature(doc_auto_cfg)] diff --git a/modules/ruxhal/src/platform/dummy/mod.rs b/modules/ruxhal/src/platform/dummy/mod.rs index 9e627cd7d..164f9b6a8 100644 --- a/modules/ruxhal/src/platform/dummy/mod.rs +++ b/modules/ruxhal/src/platform/dummy/mod.rs @@ -69,7 +69,9 @@ pub mod time { } #[cfg(feature = "rtc")] - pub fn rtc_write_time(seconds: u32) -> u64 {} + pub fn rtc_write_time(seconds: u32) -> u64 { + 0 + } } #[cfg(feature = "irq")] diff --git a/modules/ruxruntime/Cargo.toml b/modules/ruxruntime/Cargo.toml index f0615e5e1..849acd6d5 100644 --- a/modules/ruxruntime/Cargo.toml +++ b/modules/ruxruntime/Cargo.toml @@ -49,8 +49,8 @@ ruxtask = { path = "../ruxtask", optional = true } axsync = { path = "../axsync", optional = true } ruxfutex = { path = "../ruxfutex", optional = true } -crate_interface = { path = "../../crates/crate_interface" } +crate_interface = "0.1.1" percpu = { path = "../../crates/percpu", optional = true } -kernel_guard = { path = "../../crates/kernel_guard", optional = true } +kernel_guard = { version = "0.1.0", optional = true } lazy_init = { path = "../../crates/lazy_init", optional = true } dtb = { path = "../../crates/dtb", optional = true } diff --git a/modules/ruxtask/Cargo.toml b/modules/ruxtask/Cargo.toml index a2227c092..14618f1ed 100644 --- a/modules/ruxtask/Cargo.toml +++ b/modules/ruxtask/Cargo.toml @@ -37,11 +37,11 @@ ruxconfig = { path = "../ruxconfig", optional = true } percpu = { path = "../../crates/percpu", optional = true } spinlock = { path = "../../crates/spinlock", optional = true } lazy_init = { path = "../../crates/lazy_init", optional = true } -memory_addr = { path = "../../crates/memory_addr", optional = true } +memory_addr = { version = "0.1.0", optional = true } scheduler = { path = "../../crates/scheduler", optional = true } timer_list = { path = "../../crates/timer_list", optional = true } -kernel_guard = { path = "../../crates/kernel_guard", optional = true } -crate_interface = { path = "../../crates/crate_interface", optional = true } +kernel_guard = { version = "0.1.0", optional = true } +crate_interface = { version = "0.1.1", optional = true } [dev-dependencies] rand = "0.8" diff --git a/ulib/ruxmusl/Cargo.toml b/ulib/ruxmusl/Cargo.toml index 77b5855b4..cdbf28ba1 100644 --- a/ulib/ruxmusl/Cargo.toml +++ b/ulib/ruxmusl/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" authors = ["yanjuguang "] description = "Ruxos compatible layer for Musl libc" -license = "GPL-3.0-or-later OR Apache-2.0 OR MulanPSL2" +license = "Mulan PSL v2" homepage = "https://github.com/syswonder/ruxos" repository = "https://github.com/syswonder/ruxos/tree/main/ulib/ruxmusl" @@ -58,5 +58,5 @@ ruxos_posix_api = { path = "../../api/ruxos_posix_api" } num_enum = { version = "0.5.11", default-features = false } ruxhal = { path = "../../modules/ruxhal" } axlog = { path = "../../modules/axlog" } -kernel_guard = { path = "../../crates/kernel_guard" } -crate_interface = { path = "../../crates/crate_interface" } +kernel_guard = "0.1.0" +crate_interface = "0.1.1" From d2926bf20cd92ba5bb5b57ad20fb0ab0d4dd9252 Mon Sep 17 00:00:00 2001 From: Sssssaltyfish <47731209+Sssssaltyfish@users.noreply.github.com> Date: Sat, 23 Mar 2024 21:27:02 +0800 Subject: [PATCH 13/13] Implemented rv64 syscall utility by modifying musl --- api/ruxos_posix_api/src/imp/pthread/mod.rs | 7 +- api/ruxos_posix_api/src/lib.rs | 6 +- platforms/riscv64-qemu-virt.toml | 3 +- scripts/make/build_musl.mk | 17 +- scripts/make/qemu.mk | 2 +- ulib/ruxmusl/.gitignore | 1 + ulib/ruxmusl/src/lib.rs | 5 + ulib/ruxmusl/src/riscv64/mod.rs | 417 ++++++++++++++++++ .../patches/arch/riscv64/syscall_arch.h | 47 ++ .../patches/arch/riscv64/syscall_asm.inc | 7 + .../patches/src/signal/riscv64/restore.s | 10 + .../patches/src/thread/riscv64/clone.s | 37 ++ .../patches/src/thread/riscv64/syscall_cp.s | 31 ++ .../riscv64/src/thread/riscv64/__unmapself.s | 9 + ulib/ruxmusl/src/riscv64/syscall_id.rs | 130 ++++++ 15 files changed, 715 insertions(+), 14 deletions(-) create mode 100644 ulib/ruxmusl/src/riscv64/mod.rs create mode 100644 ulib/ruxmusl/src/riscv64/patches/arch/riscv64/syscall_arch.h create mode 100644 ulib/ruxmusl/src/riscv64/patches/arch/riscv64/syscall_asm.inc create mode 100644 ulib/ruxmusl/src/riscv64/patches/src/signal/riscv64/restore.s create mode 100644 ulib/ruxmusl/src/riscv64/patches/src/thread/riscv64/clone.s create mode 100644 ulib/ruxmusl/src/riscv64/patches/src/thread/riscv64/syscall_cp.s create mode 100644 ulib/ruxmusl/src/riscv64/src/thread/riscv64/__unmapself.s create mode 100644 ulib/ruxmusl/src/riscv64/syscall_id.rs diff --git a/api/ruxos_posix_api/src/imp/pthread/mod.rs b/api/ruxos_posix_api/src/imp/pthread/mod.rs index 74ce409c7..6d95dae34 100644 --- a/api/ruxos_posix_api/src/imp/pthread/mod.rs +++ b/api/ruxos_posix_api/src/imp/pthread/mod.rs @@ -98,7 +98,7 @@ impl Pthread { } /// Posix create, used by musl libc - #[cfg(all(feature = "musl", any(target_arch = "x86_64", target_arch = "aarch64")))] + #[cfg(feature = "musl")] fn pcreate( _attr: *const ctypes::pthread_attr_t, start_routine: extern "C" fn(arg: *mut c_void) -> *mut c_void, @@ -246,7 +246,10 @@ unsafe impl Send for ForceSendSync {} unsafe impl Sync for ForceSendSync {} /// Create new thread by `sys_clone`, return new thread ID -#[cfg(all(feature = "musl", target_arch = "aarch64"))] +#[cfg(all( + feature = "musl", + any(target_arch = "aarch64", target_arch = "riscv64") +))] pub unsafe fn sys_clone( flags: c_int, stack: *mut c_void, diff --git a/api/ruxos_posix_api/src/lib.rs b/api/ruxos_posix_api/src/lib.rs index 5bd396cee..e336544b4 100644 --- a/api/ruxos_posix_api/src/lib.rs +++ b/api/ruxos_posix_api/src/lib.rs @@ -111,11 +111,7 @@ pub use imp::signal::{sys_getitimer, sys_kill, sys_setitimer, sys_sigaction, sys #[cfg(feature = "multitask")] pub use imp::pthread::futex::sys_futex; -#[cfg(all( - feature = "multitask", - feature = "musl", - any(target_arch = "aarch64", target_arch = "x86_64") -))] +#[cfg(all(feature = "multitask", feature = "musl",))] pub use imp::pthread::sys_clone; #[cfg(all(feature = "multitask", feature = "musl"))] pub use imp::pthread::sys_set_tid_address; diff --git a/platforms/riscv64-qemu-virt.toml b/platforms/riscv64-qemu-virt.toml index f6a58a447..0675a3f41 100644 --- a/platforms/riscv64-qemu-virt.toml +++ b/platforms/riscv64-qemu-virt.toml @@ -9,7 +9,8 @@ family = "riscv64-qemu-virt" phys-memory-base = "0x8000_0000" # Size of the whole physical memory. # phys-memory-size = "0x800_0000" # 128M -phys-memory-size = "0x8000_0000" # 2G +phys-memory-size = "0x4000_0000" # 1G +# phys-memory-size = "0x8000_0000" # 2G # Base physical address of the kernel image. kernel-base-paddr = "0x8020_0000" # Base virtual address of the kernel image. diff --git a/scripts/make/build_musl.mk b/scripts/make/build_musl.mk index 018967e57..cba1f56f7 100644 --- a/scripts/make/build_musl.mk +++ b/scripts/make/build_musl.mk @@ -3,11 +3,15 @@ rust_lib := target/$(TARGET)/$(MODE)/lib$(rust_lib_name).a musl_version := 1.2.3 +build_suffix := _$(ARCH)_$(MODE) muslibc_dir := ulib/ruxmusl -build_dir := $(muslibc_dir)/build_musl_$(ARCH) +build_dir := $(muslibc_dir)/build_musl$(build_suffix) +install_dir_name := install$(build_suffix) +install_dir := $(muslibc_dir)/$(install_dir_name) + musl_dir := $(muslibc_dir)/musl-$(musl_version) -inc_dir := $(muslibc_dir)/install/include -c_lib := $(muslibc_dir)/install/lib/libc.a +inc_dir := $(install_dir)/include +c_lib := $(install_dir)/lib/libc.a libgcc := CFLAGS += -nostdinc -fno-builtin -ffreestanding -Wall @@ -42,14 +46,17 @@ else endif build_musl: -ifeq ($(wildcard $(build_dir)),) +ifeq ($(wildcard $(install_dir)),) ifeq ($(wildcard $(musl_dir)),) @echo "Download musl-1.2.3 source code" wget https://musl.libc.org/releases/musl-1.2.3.tar.gz -P $(muslibc_dir) tar -zxvf $(muslibc_dir)/musl-1.2.3.tar.gz -C $(muslibc_dir) && rm -f $(muslibc_dir)/musl-1.2.3.tar.gz endif mkdir -p $(build_dir) - cd $(build_dir) && ../musl-1.2.3/configure --prefix=../install --exec-prefix=../ --syslibdir=../install/lib --disable-shared ARCH=$(RUX_ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) CFLAGS='$(CFLAGS)' + ifeq ($(ARCH), riscv64) + cp -rf $(muslibc_dir)/src/riscv64/patches/* $(musl_dir) + endif + cd $(build_dir) && ../musl-1.2.3/configure --prefix=../$(install_dir_name) --exec-prefix=../ --syslibdir=../$(install_dir_name)/lib --disable-shared ARCH=$(RUX_ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) CFLAGS='$(CFLAGS)' cd $(build_dir) && $(MAKE) -j && $(MAKE) install endif diff --git a/scripts/make/qemu.mk b/scripts/make/qemu.mk index 5a6340438..bb98422ed 100644 --- a/scripts/make/qemu.mk +++ b/scripts/make/qemu.mk @@ -29,7 +29,7 @@ qemu_args-aarch64 := \ -machine virt \ -kernel $(OUT_BIN) -qemu_args-y := -m 2G -smp $(SMP) $(qemu_args-$(ARCH)) \ +qemu_args-y := -m 1G -smp $(SMP) $(qemu_args-$(ARCH)) \ -append ";$(ARGS);$(ENVS)" qemu_args-$(BLK) += \ diff --git a/ulib/ruxmusl/.gitignore b/ulib/ruxmusl/.gitignore index 53e1983f5..8d2d567be 100644 --- a/ulib/ruxmusl/.gitignore +++ b/ulib/ruxmusl/.gitignore @@ -1,3 +1,4 @@ build_* install +install_* musl-* diff --git a/ulib/ruxmusl/src/lib.rs b/ulib/ruxmusl/src/lib.rs index 66f949338..47ee0b65e 100644 --- a/ulib/ruxmusl/src/lib.rs +++ b/ulib/ruxmusl/src/lib.rs @@ -4,6 +4,8 @@ //! //! Only support AARCH64 right now +#![feature(asm_const)] +#![feature(naked_functions)] #![cfg_attr(all(not(test), not(doc)), no_std)] #[macro_use] @@ -22,6 +24,9 @@ cfg_if::cfg_if! { mod x86_64; #[cfg(feature = "musl")] use x86_64::{syscall, syscall_id}; + } else if #[cfg(target_arch = "riscv64")]{ + mod riscv64; + use riscv64::{syscall, syscall_id}; } else { mod dummy; use dummy::{syscall, syscall_id}; diff --git a/ulib/ruxmusl/src/riscv64/mod.rs b/ulib/ruxmusl/src/riscv64/mod.rs new file mode 100644 index 000000000..436023b01 --- /dev/null +++ b/ulib/ruxmusl/src/riscv64/mod.rs @@ -0,0 +1,417 @@ +pub mod syscall_id; + +use core::{arch::asm, ffi::c_int, mem}; +use ruxos_posix_api::ctypes; +use syscall_id::SyscallId; + +type SyscallArgs = [usize; 6]; + +#[no_mangle] +#[naked] +pub unsafe extern "C" fn riscv_syscall_asm( + _a0: usize, + _a1: usize, + _a2: usize, + _a3: usize, + _a4: usize, + _a5: usize, + _: usize, + _syscall_id: usize, +) { + asm!( + " + addi sp,sp,-{arg_ret_size} + sd a0,0(sp) + sd a1,8(sp) + sd a2,16(sp) + sd a3,24(sp) + sd a4,32(sp) + sd a5,40(sp) + sd ra,48(sp) + + mv a0,a7 + mv a1,sp + call {syscall_entry} + + ld ra,48(sp) + addi sp,sp,{arg_ret_size} + ret", + arg_ret_size = const mem::size_of::() + mem::size_of::(), + syscall_entry = sym riscv_syscall_entry, + options(noreturn), + ); +} + +#[no_mangle] +pub extern "C" fn riscv_syscall_entry(syscall_id: usize, args: &SyscallArgs) -> isize { + let id = SyscallId::try_from(syscall_id).unwrap_or(SyscallId::INVALID); + syscall(id, *args) +} + +pub fn syscall(syscall_id: SyscallId, args: SyscallArgs) -> isize { + debug!("syscall <= syscall_name: {:?}", syscall_id); + + unsafe { + match syscall_id { + SyscallId::INVALID => ruxos_posix_api::sys_invalid(syscall_id as usize as c_int) as _, + #[cfg(feature = "fs")] + SyscallId::GETCWD => { + ruxos_posix_api::sys_getcwd(args[0] as *mut core::ffi::c_char, args[1]) as _ + } + #[cfg(feature = "epoll")] + SyscallId::EPOLL_CREATE1 => ruxos_posix_api::sys_epoll_create(args[0] as c_int) as _, + #[cfg(feature = "epoll")] + SyscallId::EPOLL_CTL => ruxos_posix_api::sys_epoll_ctl( + args[0] as c_int, + args[1] as c_int, + args[2] as c_int, + args[3] as *mut ctypes::epoll_event, + ) as _, + #[cfg(feature = "epoll")] + SyscallId::EPOLL_PWAIT => ruxos_posix_api::sys_epoll_pwait( + args[0] as c_int, + args[1] as *mut ctypes::epoll_event, + args[2] as c_int, + args[3] as c_int, + args[4] as *const ctypes::sigset_t, + args[5] as *const ctypes::size_t, + ) as _, + #[cfg(feature = "fd")] + SyscallId::DUP => ruxos_posix_api::sys_dup(args[0] as c_int) as _, + #[cfg(feature = "fd")] + SyscallId::DUP3 => { + ruxos_posix_api::sys_dup3(args[0] as c_int, args[1] as c_int, args[2] as c_int) as _ + } + #[cfg(feature = "fd")] + SyscallId::FCNTL => { + ruxos_posix_api::sys_fcntl(args[0] as c_int, args[1] as c_int, args[2]) as _ + } + #[cfg(feature = "fd")] + SyscallId::IOCTL => ruxos_posix_api::sys_ioctl(args[0] as c_int, args[1], args[2]) as _, + #[cfg(feature = "fs")] + SyscallId::MKDIRAT => ruxos_posix_api::sys_mkdirat( + args[0] as c_int, + args[1] as *const core::ffi::c_char, + args[2] as ctypes::mode_t, + ) as _, + #[cfg(feature = "fs")] + SyscallId::UNLINKAT => ruxos_posix_api::sys_unlinkat( + args[0] as c_int, + args[1] as *const core::ffi::c_char, + args[2] as c_int, + ) as _, + #[cfg(feature = "fs")] + SyscallId::FCHOWNAT => ruxos_posix_api::sys_fchownat( + args[0] as c_int, + args[1] as *const core::ffi::c_char, + args[2] as ctypes::uid_t, + args[3] as ctypes::gid_t, + args[4] as c_int, + ) as _, + #[cfg(feature = "fs")] + SyscallId::RENAMEAT => ruxos_posix_api::sys_renameat( + args[0] as c_int, + args[1] as *const core::ffi::c_char, + args[2] as c_int, + args[3] as *const core::ffi::c_char, + ) as _, + #[cfg(feature = "fs")] + SyscallId::OPENAT => ruxos_posix_api::sys_openat( + args[0], + args[1] as *const core::ffi::c_char, + args[2] as c_int, + args[3] as ctypes::mode_t, + ) as _, + #[cfg(feature = "fd")] + SyscallId::CLOSE => ruxos_posix_api::sys_close(args[0] as c_int) as _, + #[cfg(feature = "pipe")] + SyscallId::PIPE2 => ruxos_posix_api::sys_pipe2( + core::slice::from_raw_parts_mut(args[0] as *mut c_int, 2), + args[1] as c_int, + ) as _, + #[cfg(feature = "fs")] + SyscallId::GETDENTS64 => ruxos_posix_api::sys_getdents64( + args[0] as c_int, + args[1] as *mut ctypes::dirent, + args[2] as ctypes::size_t, + ) as _, + #[cfg(feature = "fs")] + SyscallId::LSEEK => ruxos_posix_api::sys_lseek( + args[0] as c_int, + args[1] as ctypes::off_t, + args[2] as c_int, + ) as _, + SyscallId::READ => ruxos_posix_api::sys_read( + args[0] as c_int, + args[1] as *mut core::ffi::c_void, + args[2], + ) as _, + SyscallId::WRITE => ruxos_posix_api::sys_write( + args[0] as c_int, + args[1] as *mut core::ffi::c_void, + args[2], + ) as _, + #[cfg(feature = "fd")] + SyscallId::READV => ruxos_posix_api::sys_readv( + args[0] as c_int, + args[1] as *const ctypes::iovec, + args[2] as c_int, + ) as _, + #[cfg(feature = "fd")] + SyscallId::WRITEV => ruxos_posix_api::sys_writev( + args[0] as c_int, + args[1] as *const ctypes::iovec, + args[2] as c_int, + ) as _, + #[cfg(feature = "fs")] + SyscallId::PREAD64 => ruxos_posix_api::sys_pread64( + args[0] as c_int, + args[1] as *mut core::ffi::c_void, + args[2] as ctypes::size_t, + args[3] as ctypes::off_t, + ) as _, + #[cfg(feature = "fs")] + SyscallId::PREADV => ruxos_posix_api::sys_preadv( + args[0] as c_int, + args[1] as *const ctypes::iovec, + args[2] as c_int, + args[3] as ctypes::off_t, + ) as _, + #[cfg(feature = "select")] + SyscallId::PSELECT6 => ruxos_posix_api::sys_pselect6( + args[0] as c_int, + args[1] as *mut ctypes::fd_set, + args[2] as *mut ctypes::fd_set, + args[3] as *mut ctypes::fd_set, + args[4] as *mut ctypes::timeval, + args[5] as *const core::ffi::c_void, + ) as _, + #[cfg(feature = "poll")] + SyscallId::PPOLL => ruxos_posix_api::sys_ppoll( + args[0] as *mut ctypes::pollfd, + args[1] as ctypes::nfds_t, + args[2] as *const ctypes::timespec, + args[3] as *const ctypes::sigset_t, + args[4] as ctypes::size_t, + ) as _, + #[cfg(feature = "fs")] + SyscallId::READLINKAT => ruxos_posix_api::sys_readlinkat( + args[0] as c_int, + args[1] as *const core::ffi::c_char, + args[2] as *mut core::ffi::c_char, + args[3] as ctypes::size_t, + ) as _, + #[cfg(feature = "fs")] + SyscallId::NEWFSTATAT => ruxos_posix_api::sys_newfstatat( + args[0] as c_int, + args[1] as *const core::ffi::c_char, + args[2] as *mut ctypes::kstat, + args[3] as c_int, + ) as _, + #[cfg(feature = "fs")] + SyscallId::FSTAT => { + ruxos_posix_api::sys_fstat(args[0] as c_int, args[1] as *mut core::ffi::c_void) as _ + } + #[cfg(feature = "fs")] + SyscallId::FSYNC => ruxos_posix_api::sys_fsync(args[0] as c_int) as _, + SyscallId::GETEUID => ruxos_posix_api::sys_geteuid() as _, + SyscallId::GETEGID => ruxos_posix_api::sys_getegid() as _, + #[cfg(feature = "fs")] + SyscallId::FDATASYNC => ruxos_posix_api::sys_fdatasync(args[0] as c_int) as _, + #[allow(unreachable_code)] + #[cfg(not(feature = "multitask"))] + SyscallId::EXIT => ruxos_posix_api::sys_exit(args[0] as c_int) as _, + #[allow(unreachable_code)] + #[cfg(feature = "multitask")] + SyscallId::EXIT => { + ruxos_posix_api::sys_pthread_exit(args[0] as *mut core::ffi::c_void) as _ + } + #[cfg(feature = "multitask")] + SyscallId::SET_TID_ADDRESS => ruxos_posix_api::sys_set_tid_address(args[0]) as _, + #[cfg(feature = "multitask")] + SyscallId::FUTEX => ruxos_posix_api::sys_futex( + args[0], + args[1] as _, + args[2] as _, + args[3], + args[4] as _, + args[5] as _, + ) as _, + SyscallId::NANO_SLEEP => ruxos_posix_api::sys_nanosleep( + args[0] as *const ctypes::timespec, + args[1] as *mut ctypes::timespec, + ) as _, + SyscallId::CLOCK_SETTIME => ruxos_posix_api::sys_clock_settime( + args[0] as ctypes::clockid_t, + args[1] as *const ctypes::timespec, + ) as _, + SyscallId::CLOCK_GETTIME => ruxos_posix_api::sys_clock_gettime( + args[0] as ctypes::clockid_t, + args[1] as *mut ctypes::timespec, + ) as _, + SyscallId::SCHED_YIELD => ruxos_posix_api::sys_sched_yield() as _, + #[cfg(feature = "signal")] + SyscallId::SIGALTSTACK => ruxos_posix_api::sys_sigaltstack( + args[0] as *const core::ffi::c_void, + args[1] as *mut core::ffi::c_void, + ) as _, + #[cfg(feature = "signal")] + SyscallId::RT_SIGACTION => ruxos_posix_api::sys_rt_sigaction( + args[0] as c_int, + args[1] as *const ctypes::sigaction, + args[2] as *mut ctypes::sigaction, + args[3] as ctypes::size_t, + ) as _, + #[cfg(feature = "signal")] + SyscallId::RT_SIGPROCMASK => ruxos_posix_api::sys_rt_sigprocmask( + args[0] as c_int, + args[1] as *const usize, + args[2] as *mut usize, + args[3], + ) as _, + SyscallId::UNAME => ruxos_posix_api::sys_uname(args[0] as *mut core::ffi::c_void) as _, + SyscallId::GETRLIMIT => { + ruxos_posix_api::sys_getrlimit(args[0] as c_int, args[1] as *mut ctypes::rlimit) + as _ + } + SyscallId::SETRLIMIT => { + ruxos_posix_api::sys_setrlimit(args[0] as c_int, args[1] as *const ctypes::rlimit) + as _ + } + SyscallId::UMASK => ruxos_posix_api::sys_umask(args[0] as ctypes::mode_t) as _, + #[cfg(feature = "multitask")] + SyscallId::GETPID => ruxos_posix_api::sys_getpid() as _, + SyscallId::SYSINFO => { + ruxos_posix_api::sys_sysinfo(args[0] as *mut ctypes::sysinfo) as _ + } + #[cfg(feature = "net")] + SyscallId::SOCKET => { + ruxos_posix_api::sys_socket(args[0] as c_int, args[1] as c_int, args[2] as c_int) + as _ + } + #[cfg(feature = "net")] + SyscallId::BIND => ruxos_posix_api::sys_bind( + args[0] as c_int, + args[1] as *const ctypes::sockaddr, + args[2] as ctypes::socklen_t, + ) as _, + #[cfg(feature = "net")] + SyscallId::LISTEN => { + ruxos_posix_api::sys_listen(args[0] as c_int, args[1] as c_int) as _ + } + #[cfg(feature = "net")] + SyscallId::ACCEPT => ruxos_posix_api::sys_accept( + args[0] as c_int, + args[1] as *mut ctypes::sockaddr, + args[2] as *mut ctypes::socklen_t, + ) as _, + #[cfg(feature = "net")] + SyscallId::CONNECT => ruxos_posix_api::sys_connect( + args[0] as c_int, + args[1] as *const ctypes::sockaddr, + args[2] as ctypes::socklen_t, + ) as _, + #[cfg(feature = "net")] + SyscallId::GETSOCKNAME => ruxos_posix_api::sys_getsockname( + args[0] as c_int, + args[1] as *mut ctypes::sockaddr, + args[2] as *mut ctypes::socklen_t, + ) as _, + #[cfg(feature = "net")] + SyscallId::GETPEERNAME => ruxos_posix_api::sys_getpeername( + args[0] as c_int, + args[1] as *mut ctypes::sockaddr, + args[2] as *mut ctypes::socklen_t, + ) as _, + #[cfg(feature = "net")] + SyscallId::SENDTO => ruxos_posix_api::sys_sendto( + args[0] as c_int, + args[1] as *const core::ffi::c_void, + args[2] as ctypes::size_t, + args[3] as c_int, + args[4] as *const ctypes::sockaddr, + args[5] as ctypes::socklen_t, + ) as _, + #[cfg(feature = "net")] + SyscallId::RECVFROM => ruxos_posix_api::sys_recvfrom( + args[0] as c_int, + args[1] as *mut core::ffi::c_void, + args[2] as ctypes::size_t, + args[3] as c_int, + args[4] as *mut ctypes::sockaddr, + args[5] as *mut ctypes::socklen_t, + ) as _, + #[cfg(feature = "net")] + SyscallId::SETSOCKOPT => ruxos_posix_api::sys_setsockopt( + args[0] as c_int, + args[1] as c_int, + args[2] as c_int, + args[3] as *const core::ffi::c_void, + args[4] as ctypes::socklen_t, + ) as _, + #[cfg(feature = "net")] + SyscallId::SHUTDOWN => { + ruxos_posix_api::sys_shutdown(args[0] as c_int, args[1] as c_int) as _ + } + #[cfg(feature = "net")] + SyscallId::SENDMSG => ruxos_posix_api::sys_sendmsg( + args[0] as c_int, + args[1] as *const ctypes::msghdr, + args[2] as c_int, + ) as _, + #[cfg(feature = "alloc")] + SyscallId::MUNMAP => ruxos_posix_api::sys_munmap( + args[0] as *mut core::ffi::c_void, + args[1] as ctypes::size_t, + ) as _, + #[cfg(feature = "alloc")] + SyscallId::MREMAP => ruxos_posix_api::sys_mremap( + args[0] as *mut core::ffi::c_void, + args[1] as ctypes::size_t, + args[2] as ctypes::size_t, + args[3] as c_int, + args[4] as *mut core::ffi::c_void, + ) as _, + #[cfg(feature = "multitask")] + SyscallId::CLONE => ruxos_posix_api::sys_clone( + args[0] as c_int, + args[1] as *mut core::ffi::c_void, + args[2] as *mut ctypes::pid_t, + args[3] as *mut core::ffi::c_void, + args[4] as *mut ctypes::pid_t, + ) as _, + #[cfg(feature = "alloc")] + SyscallId::MMAP => ruxos_posix_api::sys_mmap( + args[0] as *mut core::ffi::c_void, + args[1] as ctypes::size_t, + args[2] as c_int, + args[3] as c_int, + args[4] as c_int, + args[5] as ctypes::off_t, + ) as _, + #[cfg(feature = "alloc")] + SyscallId::MADVISE => ruxos_posix_api::sys_madvise( + args[0] as *mut core::ffi::c_void, + args[1] as ctypes::size_t, + args[2] as c_int, + ) as _, + #[cfg(feature = "alloc")] + SyscallId::MPROTECT => ruxos_posix_api::sys_mprotect( + args[0] as *mut core::ffi::c_void, + args[1] as ctypes::size_t, + args[2] as c_int, + ) as _, + SyscallId::PRLIMIT64 => ruxos_posix_api::sys_prlimit64( + args[0] as ctypes::pid_t, + args[1] as c_int, + args[2] as *const ctypes::rlimit, + args[3] as *mut ctypes::rlimit, + ) as _, + SyscallId::GETRANDOM => ruxos_posix_api::sys_getrandom( + args[0] as *mut core::ffi::c_void, + args[1] as ctypes::size_t, + args[2] as c_int, + ) as _, + } + } +} diff --git a/ulib/ruxmusl/src/riscv64/patches/arch/riscv64/syscall_arch.h b/ulib/ruxmusl/src/riscv64/patches/arch/riscv64/syscall_arch.h new file mode 100644 index 000000000..2663191c3 --- /dev/null +++ b/ulib/ruxmusl/src/riscv64/patches/arch/riscv64/syscall_arch.h @@ -0,0 +1,47 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +extern long riscv_syscall_asm(long a0, long a1, long a2, long a3, long a4, long a5, long _, + long a7); + +static inline long __syscall0(long n) +{ + return riscv_syscall_asm(0, 0, 0, 0, 0, 0, 0, n); +} + +static inline long __syscall1(long n, long a) +{ + return riscv_syscall_asm(a, 0, 0, 0, 0, 0, 0, n); +} + +static inline long __syscall2(long n, long a, long b) +{ + return riscv_syscall_asm(a, b, 0, 0, 0, 0, 0, n); +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + return riscv_syscall_asm(a, b, c, 0, 0, 0, 0, n); +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + return riscv_syscall_asm(a, b, c, d, 0, 0, 0, n); +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + return riscv_syscall_asm(a, b, c, d, e, 0, 0, n); +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + return riscv_syscall_asm(a, b, c, d, e, f, 0, n); +} + +#define VDSO_USEFUL +/* We don't have a clock_gettime function. +#define VDSO_CGT_SYM "__vdso_clock_gettime" +#define VDSO_CGT_VER "LINUX_2.6" */ + +#define IPC_64 0 diff --git a/ulib/ruxmusl/src/riscv64/patches/arch/riscv64/syscall_asm.inc b/ulib/ruxmusl/src/riscv64/patches/arch/riscv64/syscall_asm.inc new file mode 100644 index 000000000..e05418ebb --- /dev/null +++ b/ulib/ruxmusl/src/riscv64/patches/arch/riscv64/syscall_asm.inc @@ -0,0 +1,7 @@ +.macro RUX_SYSCALL_ASM + addi sp,sp,-8 + sd ra,0(sp) # might be able to store ra in sscratch? + call riscv_syscall_asm + ld ra,0(sp) + addi sp,sp,8 +.endm diff --git a/ulib/ruxmusl/src/riscv64/patches/src/signal/riscv64/restore.s b/ulib/ruxmusl/src/riscv64/patches/src/signal/riscv64/restore.s new file mode 100644 index 000000000..a4936c9e1 --- /dev/null +++ b/ulib/ruxmusl/src/riscv64/patches/src/signal/riscv64/restore.s @@ -0,0 +1,10 @@ +.include "syscall_asm.inc" + +.global __restore +.type __restore, %function +__restore: +.global __restore_rt +.type __restore_rt, %function +__restore_rt: + li a7, 139 # SYS_rt_sigreturn + RUX_SYSCALL_ASM diff --git a/ulib/ruxmusl/src/riscv64/patches/src/thread/riscv64/clone.s b/ulib/ruxmusl/src/riscv64/patches/src/thread/riscv64/clone.s new file mode 100644 index 000000000..3e76a8076 --- /dev/null +++ b/ulib/ruxmusl/src/riscv64/patches/src/thread/riscv64/clone.s @@ -0,0 +1,37 @@ +# __clone(func, stack, flags, arg, ptid, tls, ctid) +# a0, a1, a2, a3, a4, a5, a6 + +# syscall(SYS_clone, flags, stack, ptid, tls, ctid) +# a7 a0, a1, a2, a3, a4 + +.include "syscall_asm.inc" + +.global __clone +.type __clone, %function +__clone: + # Save func and arg to stack + addi a1, a1, -16 + sd a0, 0(a1) + sd a3, 8(a1) + + # Call SYS_clone + mv a0, a2 + mv a2, a4 + mv a3, a5 + mv a4, a6 + li a7, 220 # SYS_clone + RUX_SYSCALL_ASM + + beqz a0, 1f + # Parent + ret + + + # Child +1: ld a1, 0(sp) + ld a0, 8(sp) + jalr a1 + + # Exit + li a7, 93 # SYS_exit + RUX_SYSCALL_ASM diff --git a/ulib/ruxmusl/src/riscv64/patches/src/thread/riscv64/syscall_cp.s b/ulib/ruxmusl/src/riscv64/patches/src/thread/riscv64/syscall_cp.s new file mode 100644 index 000000000..b8b578e9d --- /dev/null +++ b/ulib/ruxmusl/src/riscv64/patches/src/thread/riscv64/syscall_cp.s @@ -0,0 +1,31 @@ +.include "syscall_asm.inc" + +.global __cp_begin +.hidden __cp_begin +.global __cp_end +.hidden __cp_end +.global __cp_cancel +.hidden __cp_cancel +.hidden __cancel +.global __syscall_cp_asm +.hidden __syscall_cp_asm +.type __syscall_cp_asm, %function +__syscall_cp_asm: +__cp_begin: + lw t0, 0(a0) + bnez t0, __cp_cancel + + mv t0, a1 + mv a0, a2 + mv a1, a3 + mv a2, a4 + mv a3, a5 + mv a4, a6 + mv a5, a7 + ld a6, 0(sp) + mv a7, t0 + RUX_SYSCALL_ASM +__cp_end: + ret +__cp_cancel: + tail __cancel diff --git a/ulib/ruxmusl/src/riscv64/src/thread/riscv64/__unmapself.s b/ulib/ruxmusl/src/riscv64/src/thread/riscv64/__unmapself.s new file mode 100644 index 000000000..0a4cc61ba --- /dev/null +++ b/ulib/ruxmusl/src/riscv64/src/thread/riscv64/__unmapself.s @@ -0,0 +1,9 @@ +.include "syscall_asm.inc" + +.global __unmapself +.type __unmapself, %function +__unmapself: + li a7, 215 # SYS_munmap + RUX_SYSCALL_ASM + li a7, 93 # SYS_exit + RUX_SYSCALL_ASM diff --git a/ulib/ruxmusl/src/riscv64/syscall_id.rs b/ulib/ruxmusl/src/riscv64/syscall_id.rs new file mode 100644 index 000000000..efbf20336 --- /dev/null +++ b/ulib/ruxmusl/src/riscv64/syscall_id.rs @@ -0,0 +1,130 @@ +use num_enum::TryFromPrimitive; + +// TODO: syscall id are architecture-dependent +#[allow(clippy::upper_case_acronyms)] +#[allow(non_camel_case_types)] +#[repr(usize)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, TryFromPrimitive)] +pub enum SyscallId { + INVALID = 999, + #[cfg(feature = "fs")] + GETCWD = 17, + #[cfg(feature = "epoll")] + EPOLL_CREATE1 = 20, + #[cfg(feature = "epoll")] + EPOLL_CTL = 21, + #[cfg(feature = "epoll")] + EPOLL_PWAIT = 22, + #[cfg(feature = "fd")] + DUP = 23, + #[cfg(feature = "fd")] + DUP3 = 24, + #[cfg(feature = "fd")] + FCNTL = 25, + #[cfg(feature = "fd")] + IOCTL = 29, + #[cfg(feature = "fs")] + MKDIRAT = 34, + #[cfg(feature = "fs")] + UNLINKAT = 35, + #[cfg(feature = "fs")] + RENAMEAT = 38, + #[cfg(feature = "fs")] + FCHOWNAT = 54, + #[cfg(feature = "fs")] + OPENAT = 56, + #[cfg(feature = "fd")] + CLOSE = 57, + #[cfg(feature = "pipe")] + PIPE2 = 59, + #[cfg(feature = "fs")] + GETDENTS64 = 61, + #[cfg(feature = "fs")] + LSEEK = 62, + READ = 63, + WRITE = 64, + #[cfg(feature = "fd")] + READV = 65, + #[cfg(feature = "fd")] + WRITEV = 66, + #[cfg(feature = "fs")] + PREAD64 = 67, + #[cfg(feature = "fs")] + PREADV = 69, + #[cfg(feature = "select")] + PSELECT6 = 72, + #[cfg(feature = "poll")] + PPOLL = 73, + #[cfg(feature = "fs")] + READLINKAT = 78, + #[cfg(feature = "fs")] + NEWFSTATAT = 79, + #[cfg(feature = "fs")] + FSTAT = 80, + #[cfg(feature = "fs")] + FSYNC = 82, + #[cfg(feature = "fs")] + FDATASYNC = 83, + EXIT = 93, + #[cfg(feature = "multitask")] + SET_TID_ADDRESS = 96, + #[cfg(feature = "multitask")] + FUTEX = 98, + NANO_SLEEP = 101, + CLOCK_SETTIME = 112, + CLOCK_GETTIME = 113, + SCHED_YIELD = 124, + #[cfg(feature = "signal")] + SIGALTSTACK = 132, + #[cfg(feature = "signal")] + RT_SIGACTION = 134, + #[cfg(feature = "signal")] + RT_SIGPROCMASK = 135, + UNAME = 160, + GETRLIMIT = 163, + SETRLIMIT = 164, + UMASK = 166, + #[cfg(feature = "multitask")] + GETPID = 172, + GETEUID = 175, + GETEGID = 177, + SYSINFO = 179, + #[cfg(feature = "net")] + SOCKET = 198, + #[cfg(feature = "net")] + BIND = 200, + #[cfg(feature = "net")] + LISTEN = 201, + #[cfg(feature = "net")] + ACCEPT = 202, + #[cfg(feature = "net")] + CONNECT = 203, + #[cfg(feature = "net")] + GETSOCKNAME = 204, + #[cfg(feature = "net")] + GETPEERNAME = 205, + #[cfg(feature = "net")] + SENDTO = 206, + #[cfg(feature = "net")] + RECVFROM = 207, + #[cfg(feature = "net")] + SETSOCKOPT = 208, + #[cfg(feature = "net")] + SHUTDOWN = 210, + #[cfg(feature = "net")] + SENDMSG = 211, + #[cfg(feature = "alloc")] + MUNMAP = 215, + #[cfg(feature = "alloc")] + MREMAP = 216, + #[cfg(feature = "multitask")] + CLONE = 220, + #[cfg(feature = "alloc")] + MMAP = 222, + #[cfg(feature = "alloc")] + MADVISE = 233, + #[cfg(feature = "alloc")] + MPROTECT = 226, + PRLIMIT64 = 261, + GETRANDOM = 278, +}