Переглянути джерело

feat: add syscall ppoll, fix clock_gettime for riscv64

greatbridf 7 місяців тому
батько
коміт
fae9380b40

+ 1 - 1
Makefile.src

@@ -120,7 +120,7 @@ $(BINARY_DIR)/eonix_kernel: $(KERNEL_DEPS)
 build/kernel.sym: $(BINARY_DIR)/eonix_kernel
 	cargo objcopy -q $(CARGO_FLAGS) -- --only-keep-debug build/kernel.sym
 
-build/fs-%.img: init_script.sh script/build-img.sh $(USER_PROGRAMS)
+build/fs-%.img: user-programs/init_script_%.sh script/build-img.sh $(USER_PROGRAMS)
 	ARCH=$* OUTPUT=$@ sh script/build-img.sh
 
 build/mbr.bin: $(BINARY_DIR)/eonix_kernel

+ 2 - 0
crates/posix_types/src/ctypes.rs

@@ -35,6 +35,8 @@ impl PtrT {
 }
 
 impl Long {
+    pub const ZERO: Self = Self(0);
+
     pub fn new(value: usize) -> Result<Self, PosixError> {
         value.try_into().map(Self).map_err(|_| PosixError::EINVAL)
     }

+ 2 - 4
crates/posix_types/src/syscall_no/riscv64.rs

@@ -72,7 +72,7 @@ pub const SYS_PREADV: usize = 69;
 pub const SYS_PWRITEV: usize = 70;
 pub const SYS_SENDFILE64: usize = 71;
 pub const SYS_PSELECT6_TIME32: usize = 72;
-pub const SYS_PPOLL_TIME32: usize = 73;
+pub const SYS_PPOLL: usize = 73;
 pub const SYS_SIGNALFD4: usize = 74;
 pub const SYS_VMSPLICE: usize = 75;
 pub const SYS_SPLICE: usize = 76;
@@ -108,13 +108,11 @@ pub const SYS_KEXEC_LOAD: usize = 104;
 pub const SYS_INIT_MODULE: usize = 105;
 pub const SYS_DELETE_MODULE: usize = 106;
 pub const SYS_TIMER_CREATE: usize = 107;
-pub const SYS_TIMER_GETTIME: usize = 408;
 pub const SYS_TIMER_GETOVERRUN: usize = 109;
 pub const SYS_TIMER_SETTIME: usize = 409;
 pub const SYS_TIMER_DELETE: usize = 111;
 pub const SYS_CLOCK_SETTIME: usize = 404;
-pub const SYS_CLOCK_GETTIME: usize = 403;
-pub const SYS_CLOCK_GETTIME64: usize = 403;
+pub const SYS_CLOCK_GETTIME: usize = 113;
 pub const SYS_CLOCK_GETRES: usize = 406;
 pub const SYS_CLOCK_NANOSLEEP: usize = 407;
 pub const SYS_SYSLOG: usize = 116;

+ 2 - 2
script/build-img.sh

@@ -33,12 +33,12 @@ if [ "$ARCH" = "x86_64" ]; then
     $SUDO cp ./user-programs/busybox-minimal build/mnt/busybox_
     $SUDO cp ./user-programs/ld-musl-i386.so.1 build/mnt/ld-musl-i386.so.1
     $SUDO cp ./user-programs/pthread_test build/mnt/pthread_test
+    $SUDO cp ./user-programs/init_script_x86_64.sh build/mnt/initsh
 elif [ "$ARCH" = "riscv64" ]; then
     $SUDO cp ./user-programs/busybox.static build/mnt/busybox
+    $SUDO cp ./user-programs/init_script_riscv64.sh build/mnt/initsh
 fi
 
-$SUDO cp ./init_script.sh build/mnt/initsh
-
 # Add your custom files here
 
 

+ 39 - 18
src/kernel/syscall/file_rw.rs

@@ -22,8 +22,10 @@ use crate::{
 };
 use alloc::sync::Arc;
 use eonix_runtime::task::Task;
+use posix_types::ctypes::{Long, PtrT};
 use posix_types::open::{AtFlags, OpenFlags};
-use posix_types::stat::{Stat, StatX};
+use posix_types::signal::SigSet;
+use posix_types::stat::{Stat, StatX, TimeSpec};
 use posix_types::syscall_no::*;
 
 impl FromSyscallArg for OpenFlags {
@@ -230,7 +232,7 @@ fn unlink(pathname: *const u8) -> KResult<()> {
 }
 
 #[eonix_macros::define_syscall(SYS_SYMLINKAT)]
-fn symlinkat(dirfd: FD, target: *const u8, linkpath: *const u8) -> KResult<()> {
+fn symlinkat(target: *const u8, dirfd: FD, linkpath: *const u8) -> KResult<()> {
     let target = UserString::new(target)?;
     let dentry = dentry_from(thread, dirfd, linkpath, false)?;
 
@@ -240,7 +242,7 @@ fn symlinkat(dirfd: FD, target: *const u8, linkpath: *const u8) -> KResult<()> {
 #[cfg(target_arch = "x86_64")]
 #[eonix_macros::define_syscall(SYS_SYMLINK)]
 fn symlink(target: *const u8, linkpath: *const u8) -> KResult<()> {
-    sys_symlinkat(thread, FD::AT_FDCWD, target, linkpath)
+    sys_symlinkat(thread, target, FD::AT_FDCWD, linkpath)
 }
 
 #[eonix_macros::define_syscall(SYS_MKNODAT)]
@@ -291,16 +293,15 @@ fn llseek(fd: FD, offset_high: u32, offset_low: u32, result: *mut u64, whence: u
     result.copy(&new_offset)?.ok_or(EFAULT)
 }
 
-// TODO!!!: This type should differ based on architecture.
 #[repr(C)]
-#[derive(Default, Clone, Copy)]
-struct IoVec32 {
-    base: u32,
-    len: u32,
+#[derive(Clone, Copy)]
+struct IoVec {
+    base: PtrT,
+    len: Long,
 }
 
 #[eonix_macros::define_syscall(SYS_READV)]
-fn readv(fd: FD, iov_user: *const IoVec32, iovcnt: u32) -> KResult<usize> {
+fn readv(fd: FD, iov_user: *const IoVec, iovcnt: u32) -> KResult<usize> {
     let file = thread.files.get(fd).ok_or(EBADF)?;
 
     let mut iov_user = UserPointer::new(iov_user)?;
@@ -312,8 +313,10 @@ fn readv(fd: FD, iov_user: *const IoVec32, iovcnt: u32) -> KResult<usize> {
         })
         .filter_map(|iov_result| match iov_result {
             Err(err) => Some(Err(err)),
-            Ok(IoVec32 { len: 0, .. }) => None,
-            Ok(IoVec32 { base, len }) => Some(UserBuffer::new(base as *mut u8, len as usize)),
+            Ok(IoVec {
+                len: Long::ZERO, ..
+            }) => None,
+            Ok(IoVec { base, len }) => Some(UserBuffer::new(base.addr() as *mut u8, len.get())),
         })
         .collect::<KResult<Vec<_>>>()?;
 
@@ -332,7 +335,7 @@ fn readv(fd: FD, iov_user: *const IoVec32, iovcnt: u32) -> KResult<usize> {
 }
 
 #[eonix_macros::define_syscall(SYS_WRITEV)]
-fn writev(fd: FD, iov_user: *const IoVec32, iovcnt: u32) -> KResult<usize> {
+fn writev(fd: FD, iov_user: *const IoVec, iovcnt: u32) -> KResult<usize> {
     let file = thread.files.get(fd).ok_or(EBADF)?;
 
     let mut iov_user = UserPointer::new(iov_user)?;
@@ -344,9 +347,12 @@ fn writev(fd: FD, iov_user: *const IoVec32, iovcnt: u32) -> KResult<usize> {
         })
         .filter_map(|iov_result| match iov_result {
             Err(err) => Some(Err(err)),
-            Ok(IoVec32 { len: 0, .. }) => None,
-            Ok(IoVec32 { base, len }) => Some(
-                CheckedUserPointer::new(base as *mut u8, len as usize).map(|ptr| ptr.into_stream()),
+            Ok(IoVec {
+                len: Long::ZERO, ..
+            }) => None,
+            Ok(IoVec { base, len }) => Some(
+                CheckedUserPointer::new(base.addr() as *mut u8, len.get())
+                    .map(|ptr| ptr.into_stream()),
             ),
         })
         .collect::<KResult<Vec<_>>>()?;
@@ -419,9 +425,7 @@ struct UserPollFd {
     revents: u16,
 }
 
-#[cfg(target_arch = "x86_64")]
-#[eonix_macros::define_syscall(SYS_POLL)]
-fn poll(fds: *mut UserPollFd, nfds: u32, _timeout: u32) -> KResult<u32> {
+fn do_poll(thread: &Thread, fds: *mut UserPollFd, nfds: u32, _timeout: u32) -> KResult<u32> {
     match nfds {
         0 => Ok(0),
         2.. => unimplemented!("Poll with {} fds", nfds),
@@ -442,4 +446,21 @@ fn poll(fds: *mut UserPollFd, nfds: u32, _timeout: u32) -> KResult<u32> {
     }
 }
 
+#[eonix_macros::define_syscall(SYS_PPOLL)]
+fn ppoll(
+    fds: *mut UserPollFd,
+    nfds: u32,
+    _timeout_ptr: *const TimeSpec,
+    _sigmask: *const SigSet,
+) -> KResult<u32> {
+    // TODO: Implement ppoll with signal mask and timeout
+    do_poll(thread, fds, nfds, 0)
+}
+
+#[cfg(target_arch = "x86_64")]
+#[eonix_macros::define_syscall(SYS_POLL)]
+fn poll(fds: *mut UserPollFd, nfds: u32, timeout: u32) -> KResult<u32> {
+    do_poll(thread, fds, nfds, timeout)
+}
+
 pub fn keep_alive() {}

+ 14 - 2
src/kernel/syscall/sysinfo.rs

@@ -1,6 +1,7 @@
 use crate::{
     kernel::{
         constants::{CLOCK_MONOTONIC, CLOCK_REALTIME, EINVAL},
+        task::Thread,
         timer::ticks,
         user::UserPointerMut,
     },
@@ -79,8 +80,7 @@ fn gettimeofday(timeval: *mut TimeVal, timezone: *mut ()) -> KResult<()> {
     Ok(())
 }
 
-#[eonix_macros::define_syscall(SYS_CLOCK_GETTIME64)]
-fn clock_gettime64(clock_id: u32, timespec: *mut TimeSpec) -> KResult<()> {
+fn do_clock_gettime64(_thread: &Thread, clock_id: u32, timespec: *mut TimeSpec) -> KResult<()> {
     if clock_id != CLOCK_REALTIME && clock_id != CLOCK_MONOTONIC {
         unimplemented!("Unsupported clock_id: {}", clock_id);
     }
@@ -93,6 +93,18 @@ fn clock_gettime64(clock_id: u32, timespec: *mut TimeSpec) -> KResult<()> {
     })
 }
 
+#[cfg(not(target_arch = "x86_64"))]
+#[eonix_macros::define_syscall(SYS_CLOCK_GETTIME)]
+fn clock_gettime(clock_id: u32, timespec: *mut TimeSpec) -> KResult<()> {
+    do_clock_gettime64(thread, clock_id, timespec)
+}
+
+#[cfg(target_arch = "x86_64")]
+#[eonix_macros::define_syscall(SYS_CLOCK_GETTIME64)]
+fn clock_gettime64(clock_id: u32, timespec: *mut TimeSpec) -> KResult<()> {
+    do_clock_gettime64(thread, clock_id, timespec)
+}
+
 #[repr(C)]
 #[derive(Clone, Copy)]
 struct Sysinfo {

+ 88 - 0
user-programs/init_script_riscv64.sh

@@ -0,0 +1,88 @@
+#!/mnt/busybox sh
+
+BUSYBOX=/mnt/busybox
+
+freeze() {
+    echo "an error occurred while executing '''$@''', freezing..." >&2
+
+    while true; do
+        true
+    done
+}
+
+do_or_freeze() {
+    if $@; then
+        return
+    fi
+
+    freeze $@
+}
+
+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/ttyS0 c 4 64
+do_or_freeze $BUSYBOX mknod -m 666 /dev/ttyS1 c 4 65
+
+echo -n -e "deploying busybox... " >&2
+
+do_or_freeze $BUSYBOX mkdir -p /bin
+do_or_freeze $BUSYBOX --install -s /bin
+do_or_freeze $BUSYBOX mkdir -p /lib
+
+export PATH="/bin"
+
+echo ok >&2
+
+do_or_freeze mkdir -p /etc /root /proc
+do_or_freeze mount -t procfs proc proc
+
+cp /mnt/ld-musl-i386.so.1 /lib/ld-musl-i386.so.1
+ln -s /lib/ld-musl-i386.so.1 /lib/libc.so
+
+cat > /etc/passwd <<EOF
+root:x:0:0:root:/root:/mnt/busybox sh
+EOF
+
+cat > /etc/group <<EOF
+root:x:0:root
+EOF
+
+cat > /etc/profile <<EOF
+export PATH=/bin
+EOF
+
+cat > /root/.profile <<EOF
+export HOME=/root
+
+alias ll="ls -l "
+alias la="ls -la "
+EOF
+
+cat > /root/test.c <<EOF
+#include <stdio.h>
+
+int main() {
+    int var = 0;
+    printf("Hello, world!\n");
+    printf("Please input a number: \n");
+    scanf("%d", &var);
+    if (var > 0) {
+        printf("You typed a positive number.\n");
+    } else if (var == 0 ) {
+        printf("You input a zero.\n");
+    } else {
+        printf("You typed a negative number.\n");
+    }
+    return 0;
+}
+EOF
+
+exec $BUSYBOX sh -l < /dev/ttyS0 > /dev/ttyS0 2> /dev/ttyS0
+
+# We don't have a working init yet, so we use busybox sh directly for now.
+# exec /mnt/init /bin/sh -c 'exec sh -l < /dev/ttyS0 > /dev/ttyS0 2> /dev/ttyS0'

+ 0 - 0
init_script.sh → user-programs/init_script_x86_64.sh