From 6d42a07e95928bda91b2ca546dd6fde10a28b342 Mon Sep 17 00:00:00 2001 From: wheatfox Date: Tue, 25 Feb 2025 17:24:28 +0800 Subject: [PATCH] Implement `getcpu` syscall and add corresponding test application --- docs/src/kernel/linux-compatibility.md | 2 +- kernel/src/syscall/arch/riscv.rs | 2 ++ kernel/src/syscall/arch/x86.rs | 2 ++ kernel/src/syscall/getcpu.rs | 27 ++++++++++++++++++++++++++ kernel/src/syscall/mod.rs | 1 + test/apps/Makefile | 1 + test/apps/getcpu/Makefile | 5 +++++ test/apps/getcpu/getcpu.c | 24 +++++++++++++++++++++++ 8 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 kernel/src/syscall/getcpu.rs create mode 100644 test/apps/getcpu/Makefile create mode 100644 test/apps/getcpu/getcpu.c diff --git a/docs/src/kernel/linux-compatibility.md b/docs/src/kernel/linux-compatibility.md index 815ac1196..3f6f6dd66 100644 --- a/docs/src/kernel/linux-compatibility.md +++ b/docs/src/kernel/linux-compatibility.md @@ -329,7 +329,7 @@ provided by Linux on x86-64 architecture. | 306 | syncfs | ❌ | | 307 | sendmmsg | ❌ | | 308 | setns | ❌ | -| 309 | getcpu | ❌ | +| 309 | getcpu | ✅ | | 310 | process_vm_readv | ❌ | | 311 | process_vm_writev | ❌ | | 312 | kcmp | ❌ | diff --git a/kernel/src/syscall/arch/riscv.rs b/kernel/src/syscall/arch/riscv.rs index 9b28dafdb..10540f1a7 100644 --- a/kernel/src/syscall/arch/riscv.rs +++ b/kernel/src/syscall/arch/riscv.rs @@ -26,6 +26,7 @@ use crate::syscall::{ flock::sys_flock, fsync::{sys_fdatasync, sys_fsync}, futex::sys_futex, + getcpu::sys_getcpu, getcwd::sys_getcwd, getdents64::sys_getdents64, getegid::sys_getegid, @@ -225,6 +226,7 @@ impl_syscall_nums_and_dispatch_fn! { SYS_GETRUSAGE = 165 => sys_getrusage(args[..2]); SYS_UMASK = 166 => sys_umask(args[..1]); SYS_PRCTL = 167 => sys_prctl(args[..5]); + SYS_GETCPU = 168 => sys_getcpu(args[..3]); SYS_GETTIMEOFDAY = 169 => sys_gettimeofday(args[..1]); SYS_GETPID = 172 => sys_getpid(args[..0]); SYS_GETPPID = 173 => sys_getppid(args[..0]); diff --git a/kernel/src/syscall/arch/x86.rs b/kernel/src/syscall/arch/x86.rs index 82640f52a..62e270dca 100644 --- a/kernel/src/syscall/arch/x86.rs +++ b/kernel/src/syscall/arch/x86.rs @@ -29,6 +29,7 @@ use crate::syscall::{ fork::sys_fork, fsync::{sys_fdatasync, sys_fsync}, futex::sys_futex, + getcpu::sys_getcpu, getcwd::sys_getcwd, getdents64::{sys_getdents, sys_getdents64}, getegid::sys_getegid, @@ -314,6 +315,7 @@ impl_syscall_nums_and_dispatch_fn! { SYS_PREADV = 295 => sys_preadv(args[..4]); SYS_PWRITEV = 296 => sys_pwritev(args[..4]); SYS_PRLIMIT64 = 302 => sys_prlimit64(args[..4]); + SYS_GETCPU = 309 => sys_getcpu(args[..3]); SYS_GETRANDOM = 318 => sys_getrandom(args[..3]); SYS_EXECVEAT = 322 => sys_execveat(args[..5], &mut user_ctx); SYS_PREADV2 = 327 => sys_preadv2(args[..5]); diff --git a/kernel/src/syscall/getcpu.rs b/kernel/src/syscall/getcpu.rs new file mode 100644 index 000000000..da285391a --- /dev/null +++ b/kernel/src/syscall/getcpu.rs @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MPL-2.0 + +use ostd::{cpu::PinCurrentCpu, task::disable_preempt}; + +use super::SyscallReturn; +use crate::prelude::*; + +pub fn sys_getcpu(cpu: Vaddr, node: Vaddr, _tcache: Vaddr, ctx: &Context) -> Result { + // The third argument tcache is unused after Linux 2.6.24 so we ignore it + let preempt_guard = disable_preempt(); + let cpuid = preempt_guard.current_cpu(); + drop(preempt_guard); + debug!( + "getcpu: cpuid = {}, total_cpus = {}", + cpuid.as_usize(), + ostd::cpu::num_cpus() + ); + // Since cpu and node can be NULL, we need to check them before writing + if cpu != 0 { + ctx.user_space() + .write_val::(cpu, &cpuid.as_usize())?; + } + if node != 0 { + ctx.user_space().write_val::(node, &0)?; // TODO: NUMA is not supported + } + Ok(SyscallReturn::Return(0)) +} diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 9d7e1a115..f9f3a4211 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -37,6 +37,7 @@ mod flock; mod fork; mod fsync; mod futex; +mod getcpu; mod getcwd; mod getdents64; mod getegid; diff --git a/test/apps/Makefile b/test/apps/Makefile index 1bfc85a01..34ee898cc 100644 --- a/test/apps/Makefile +++ b/test/apps/Makefile @@ -23,6 +23,7 @@ TEST_APPS := \ file_io \ fork \ fork_c \ + getcpu \ getpid \ hello_c \ hello_pie \ diff --git a/test/apps/getcpu/Makefile b/test/apps/getcpu/Makefile new file mode 100644 index 000000000..ce42e33b0 --- /dev/null +++ b/test/apps/getcpu/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: MPL-2.0 + +include ../test_common.mk + +EXTRA_C_FLAGS := \ No newline at end of file diff --git a/test/apps/getcpu/getcpu.c b/test/apps/getcpu/getcpu.c new file mode 100644 index 000000000..0944f59bf --- /dev/null +++ b/test/apps/getcpu/getcpu.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MPL-2.0 + +#define _GNU_SOURCE +#include +#include +#include +#include + +int main() +{ + unsigned int cpu, node; + + // Directly test the getcpu syscall because glibc's getcpu() may not + // use the getcpu syscall to retrieve CPU info + long ret = syscall(SYS_getcpu, &cpu, &node, NULL); + if (ret != 0) { + perror("syscall getcpu"); + exit(EXIT_FAILURE); + } + + printf("getcpu syscall: cpu = %u, node = %u\n", cpu, node); + + return 0; +} \ No newline at end of file