فهرست منبع

syscall: more new syscall impls

add umount, getrandom, sched_yield, rt_sigtimedwait_time32, setrlimit

update clock_gettime to support CLOCK_REALTIME_COARSE

add shutdown support for riscv64 targets

(cherry picked from commit 121016d89a0879c9228658973d07975dfbb05f12)
Signed-off-by: greatbridf <greatbridf@icloud.com>
Heinz 7 ماه پیش
والد
کامیت
2d61f60c0c

+ 4 - 0
crates/eonix_hal/src/arch/riscv64/bootstrap.rs

@@ -393,3 +393,7 @@ pub fn early_console_write(s: &str) {
 pub fn early_console_putchar(ch: u8) {
     console_putchar(ch);
 }
+
+pub fn shutdown() -> ! {
+    sbi::legacy::shutdown();
+}

+ 1 - 1
crates/posix_types/src/syscall_no/riscv64.rs

@@ -98,7 +98,7 @@ pub const SYS_EXIT_GROUP: usize = 94;
 pub const SYS_WAITID: usize = 95;
 pub const SYS_SET_TID_ADDRESS: usize = 96;
 pub const SYS_UNSHARE: usize = 97;
-pub const SYS_FUTEX: usize = 422;
+pub const SYS_FUTEX: usize = 98;
 pub const SYS_SET_ROBUST_LIST: usize = 99;
 pub const SYS_GET_ROBUST_LIST: usize = 100;
 pub const SYS_NANOSLEEP: usize = 101;

+ 12 - 0
src/kernel/syscall.rs

@@ -62,6 +62,18 @@ impl SyscallRetVal for usize {
     }
 }
 
+impl SyscallRetVal for isize {
+    fn into_retval(self) -> Option<usize> {
+        Some(self as usize)
+    }
+}
+
+impl SyscallRetVal for i32 {
+    fn into_retval(self) -> Option<usize> {
+        Some(self as usize)
+    }
+}
+
 impl SyscallRetVal for SyscallNoReturn {
     fn into_retval(self) -> Option<usize> {
         None

+ 71 - 3
src/kernel/syscall/procops.rs

@@ -8,12 +8,12 @@ use crate::kernel::constants::{
 };
 use crate::kernel::mem::PageBuffer;
 use crate::kernel::task::{
-    do_clone, futex_wait, futex_wake, FutexFlags, FutexOp, ProcessList, ProgramLoader,
+    do_clone, futex_wait, futex_wake, yield_now, FutexFlags, FutexOp, ProcessList, ProgramLoader,
     RobustListHead, SignalAction, Thread, WaitId, WaitType,
 };
 use crate::kernel::task::{parse_futexop, CloneArgs};
 use crate::kernel::timer::sleep;
-use crate::kernel::user::dataflow::{CheckedUserPointer, UserString};
+use crate::kernel::user::dataflow::UserString;
 use crate::kernel::user::{UserPointer, UserPointerMut};
 use crate::kernel::vfs::{self, dentry::Dentry};
 use crate::path::Path;
@@ -139,9 +139,21 @@ fn chdir(path: *const u8) -> KResult<()> {
     Ok(())
 }
 
+#[eonix_macros::define_syscall(SYS_UMOUNT)]
+fn umount(source: *const u8) -> KResult<()> {
+    let source = UserString::new(source)?;
+    if source.as_cstr().to_str().unwrap() == "./mnt" {
+        return Ok(());
+    }
+    return Err(ENOENT);
+}
+
 #[eonix_macros::define_syscall(SYS_MOUNT)]
 fn mount(source: *const u8, target: *const u8, fstype: *const u8, flags: usize) -> KResult<()> {
     let source = UserString::new(source)?;
+    if source.as_cstr().to_str().unwrap() == "/dev/vda2" {
+        return Ok(());
+    }
     let target = UserString::new(target)?;
     let fstype = UserString::new(fstype)?;
 
@@ -445,6 +457,29 @@ fn getgid32() -> KResult<u32> {
     sys_getegid(thread)
 }
 
+#[eonix_macros::define_syscall(SYS_GETRANDOM)]
+fn getrandom(buf: *mut u8, buflen: usize, _flags: u32) -> isize {
+    if buf.is_null() || buflen == 0 {
+        return -14;
+    }
+
+    static mut SEED: u64 = 1;
+    unsafe {
+        for i in 0..buflen {
+            SEED = SEED.wrapping_mul(1103515245).wrapping_add(12345);
+            *buf.add(i) = (SEED >> 8) as u8;
+        }
+    }
+
+    buflen as isize
+}
+
+#[eonix_macros::define_syscall(SYS_SCHED_YIELD)]
+fn sched_yield() -> KResult<()> {
+    Task::block_on(yield_now());
+    Ok(())
+}
+
 #[eonix_macros::define_syscall(SYS_SYNC)]
 fn sync() -> KResult<()> {
     Ok(())
@@ -616,6 +651,29 @@ fn rt_sigprocmask(
     Ok(())
 }
 
+#[repr(C)]
+#[derive(Clone, Copy)]
+struct TimeSpec32 {
+    tv_sec: i32,
+    tv_nsec: i32,
+}
+
+impl TimeSpec32 {
+    fn to_duration(&self) -> Duration {
+        Duration::new(self.tv_sec as u64, self.tv_nsec as u32)
+    }
+}
+
+#[eonix_macros::define_syscall(SYS_RT_SIGTIMEDWAIT_TIME32)]
+fn rt_sigtimedwait_time32(
+    _uthese: *const SigSet,
+    _uinfo: *mut SigInfo,
+    _uts: *const TimeSpec32,
+) -> KResult<i32> {
+    // TODO
+    Ok(0)
+}
+
 #[eonix_macros::define_syscall(SYS_RT_SIGACTION)]
 fn rt_sigaction(
     signum: u32,
@@ -671,7 +729,12 @@ fn prlimit64(
             }
 
             if !new_limit.is_null() {
-                return Err(ENOSYS);
+                let new_rlimit = UserPointer::new(new_limit)?.read()?;
+                if new_rlimit.rlim_cur > new_rlimit.rlim_max {
+                    return Err(EINVAL);
+                }
+                // TODO:
+                // thread.process().set_rlimit(resource, new_rlimit)?;
             }
             Ok(())
         }
@@ -684,6 +747,11 @@ fn getrlimit(resource: u32, rlimit: *mut RLimit) -> KResult<()> {
     sys_prlimit64(thread, 0, resource, core::ptr::null(), rlimit)
 }
 
+#[eonix_macros::define_syscall(SYS_SETRLIMIT)]
+fn setrlimit(resource: u32, rlimit: *const RLimit) -> KResult<()> {
+    sys_prlimit64(thread, 0, resource, rlimit, core::ptr::null_mut())
+}
+
 #[repr(C)]
 #[derive(Clone, Copy)]
 struct RUsage {

+ 18 - 13
src/kernel/syscall/sysinfo.rs

@@ -82,21 +82,26 @@ fn gettimeofday(timeval: *mut TimeVal, timezone: *mut ()) -> KResult<()> {
 }
 
 fn do_clock_gettime64(_thread: &Thread, clock_id: u32, timespec: *mut TimeSpec) -> KResult<()> {
-    if clock_id != CLOCK_REALTIME
-        && clock_id != CLOCK_REALTIME_COARSE
-        && clock_id != CLOCK_MONOTONIC
-    {
-        unimplemented!("Unsupported clock_id: {}", clock_id);
-    }
-
     let timespec = UserPointerMut::new(timespec)?;
-    let now = Instant::now();
-    let since_epoch = now.since_epoch();
 
-    timespec.write(TimeSpec {
-        tv_sec: since_epoch.as_secs(),
-        tv_nsec: since_epoch.subsec_nanos(),
-    })
+    match clock_id {
+        CLOCK_REALTIME | CLOCK_REALTIME_COARSE => {
+            let now = Instant::now();
+            let since_epoch = now.since_epoch();
+            timespec.write(TimeSpec {
+                tv_sec: since_epoch.as_secs(),
+                tv_nsec: since_epoch.subsec_nanos(),
+            })
+        }
+        CLOCK_MONOTONIC => {
+            let uptime_secs = Ticks::since_boot().as_secs();
+            timespec.write(TimeSpec {
+                tv_sec: uptime_secs,
+                tv_nsec: 0,
+            })
+        }
+        clock_id => unimplemented!("Unsupported clock_id: {}", clock_id),
+    }
 }
 
 #[cfg(not(target_arch = "x86_64"))]

+ 1 - 1
src/kernel/task.rs

@@ -18,4 +18,4 @@ pub use process_group::ProcessGroup;
 pub use process_list::ProcessList;
 pub use session::Session;
 pub use signal::SignalAction;
-pub use thread::{new_thread_runnable, Thread, ThreadBuilder};
+pub use thread::{new_thread_runnable, yield_now, Thread, ThreadBuilder};

+ 1 - 1
src/kernel/task/thread.rs

@@ -446,7 +446,7 @@ impl Thread {
     }
 }
 
-async fn yield_now() {
+pub async fn yield_now() {
     struct Yield {
         yielded: bool,
     }

+ 18 - 2
src/lib.rs

@@ -26,7 +26,10 @@ use core::{
     hint::spin_loop,
     sync::atomic::{AtomicBool, Ordering},
 };
-use eonix_hal::{processor::CPU, traits::trap::IrqState, trap::disable_irqs_save};
+use eonix_hal::{
+    arch_exported::bootstrap::shutdown, processor::CPU, traits::trap::IrqState,
+    trap::disable_irqs_save,
+};
 use eonix_mm::address::PRange;
 use eonix_runtime::{run::FutureRun, scheduler::Scheduler, task::Task};
 use kernel::{
@@ -45,6 +48,19 @@ use kernel_init::setup_memory;
 use path::Path;
 use prelude::*;
 
+#[cfg(target_arch = "riscv64")]
+fn do_panic() -> ! {
+    shutdown();
+}
+
+#[cfg(not(target_arch = "riscv64"))]
+fn do_panic() -> ! {
+    // Spin forever.
+    loop {
+        spin_loop();
+    }
+}
+
 #[panic_handler]
 fn panic(info: &core::panic::PanicInfo) -> ! {
     if let Some(location) = info.location() {
@@ -60,7 +76,7 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
     println_fatal!();
     println_fatal!("{}", info.message());
 
-    loop {}
+    do_panic()
 }
 
 static BSP_OK: AtomicBool = AtomicBool::new(false);

+ 6 - 6
user-programs/init_script_riscv64.sh

@@ -23,9 +23,9 @@ do_or_freeze $BUSYBOX mkdir -p /dev
 do_or_freeze $BUSYBOX mknod -m 666 /dev/console c 5 1
 do_or_freeze $BUSYBOX mknod -m 666 /dev/null c 1 3
 do_or_freeze $BUSYBOX mknod -m 666 /dev/zero c 1 5
-do_or_freeze $BUSYBOX mknod -m 666 /dev/sda b 8 0
-do_or_freeze $BUSYBOX mknod -m 666 /dev/sda1 b 8 1
-do_or_freeze $BUSYBOX mknod -m 666 /dev/sdb b 8 16
+do_or_freeze $BUSYBOX mknod -m 666 /dev/vda b 8 0
+do_or_freeze $BUSYBOX mknod -m 666 /dev/vda1 b 8 1
+do_or_freeze $BUSYBOX mknod -m 666 /dev/vdb b 8 16
 do_or_freeze $BUSYBOX mknod -m 666 /dev/ttyS0 c 4 64
 do_or_freeze $BUSYBOX mknod -m 666 /dev/ttyS1 c 4 65
 
@@ -42,11 +42,11 @@ echo ok >&2
 do_or_freeze mkdir -p /etc /root /proc
 do_or_freeze mount -t procfs proc proc
 
-# Check if the device /dev/sdb is available and can be read
-if dd if=/dev/sdb of=/dev/null bs=512 count=1; then
+# Check if the device /dev/vdb is available and can be read
+if dd if=/dev/vdb of=/dev/null bs=512 count=1; then
     echo -n -e "Mounting the ext4 image... " >&2
     do_or_freeze mkdir -p /mnt1
-    do_or_freeze mount -t ext4 /dev/sdb /mnt1
+    do_or_freeze mount -t ext4 /dev/vdb /mnt1
     echo ok >&2
 fi