[svsm-devel] task: Implement system call interface

Carlos Bilbao carlos.bilbao at amd.com
Fri Sep 8 14:55:03 CEST 2023


Hello,

Just opened pull request to add a system call interface [1]. Sharing below
too in case anyone wants to review.

[1] https://github.com/roy-hopkins/svsm/pull/5

Thanks,
Carlos
---
[PATCH] scheduler: Implement system call interface

Added system call interface with enum-based invocation handling.

Signed-off-by: Carlos Bilbao <carlos.bilbao at amd.com>
---
  src/task/syscall.rs | 122 +++++++++++++++++++++++++++++++++++++++++---
  1 file changed, 114 insertions(+), 8 deletions(-)

diff --git a/src/task/syscall.rs b/src/task/syscall.rs
index 3ac7b92..67c0197 100644
--- a/src/task/syscall.rs
+++ b/src/task/syscall.rs
@@ -3,8 +3,13 @@
  // Copyright (c) 2022-2023 SUSE LLC
  //
  // Author: Roy Hopkins <rhopkins at suse.de>
-
+//
+// Other contributors:
+//
+// Carlos Bilbao <carlos.bilbao at amd.com>
+//
  use core::{
+    arch::asm,
      arch::global_asm,
      ffi::{c_char, CStr},
  };
@@ -32,21 +37,122 @@ const MSR_STAR: u32 = 0xc000_0081;
  const MSR_LSTAR: u32 = 0xc000_0082;
  const MSR_SFMASK: u32 = 0xc000_0084;

+#[repr(u32)]
+#[derive(Debug)]
+pub enum SystemCalls {
+    Exit = 0,
+    Log = 1,
+    Sleep = 2,
+}
+
+fn map_to_syscall(index: u32) -> Option<SystemCalls> {
+    match index {
+        1 => Some(SystemCalls::Exit),
+        2 => Some(SystemCalls::Log),
+        3 => Some(SystemCalls::Sleep),
+        _ => None,
+    }
+}
+
+#[inline]
+#[allow(dead_code)]
+pub fn syscall0(id: u32) -> u64 {
+    let ret: u64;
+    // syscall modifies both rcx and r11
+    unsafe {
+        asm!("syscall",
+               inout("rax") id as u64 => ret,
+               options(nostack));
+    }
+
+    ret
+}
+
+#[inline]
+#[allow(dead_code)]
+pub fn syscall1(id: u32, p1: u64) -> u64 {
+    let ret: u64;
+    unsafe {
+        asm!("syscall",
+               inout("rax") id as u64 => ret,
+               in("rdi") p1,
+               options(nostack));
+    }
+
+    ret
+}
+
+#[inline]
+#[allow(dead_code)]
+pub fn syscall2(id: u32, p1: u64, p2: u64) -> u64 {
+    let ret: u64;
+    unsafe {
+        asm!("syscall",
+               inout("rax") id as u64 => ret,
+               in("rdi") p1,
+               in("rsi") p2,
+               options(nostack));
+    }
+
+    ret
+}
+
+#[inline]
+#[allow(dead_code)]
+pub fn syscall3(id: u32, p1: u64, p2: u64, p3: u64) -> u64 {
+    let ret: u64;
+    // syscall modifies both rcx and r11
+    unsafe {
+        asm!("syscall",
+               inout("rax") id as u64 => ret,
+               in("rdi") p1,
+               in("rsi") p2,
+               in("rdx") p3,
+               options(nostack));
+    }
+
+    ret
+}
+
+// In case of adding system calls with more parameters, this is the order
+// in which to fill the registers:
+// p4=r10, p5=r8, p6=r9
+// We can't pass >6 params without using the stack
+// Don't forget to include the call in system_call!() too.
+
+/// System call macro. Example of usage:
+/// system_call!(SystemCalls:CALL_ID, param1)
+///
+#[macro_export]
+macro_rules! system_call {
+    ($id: expr) => {
+        syscall0($id)
+    };
+
+    ($id: expr, $param_1:expr) => {
+        syscall1($id, $param_1 as u64)
+    };
+    ($id: expr, $param_1:expr, $param_2:expr) => {
+        syscall2($id, $param_1 as u64, $param_2 as u64)
+    };
+
+    ($id: expr, $param_1:expr, $param_2:expr, $param_3:expr) => {
+        syscall3($id, $param_1 as u64, $param_2 as u64, $param_3 as u64)
+    };
+}
+
  #[no_mangle]
  extern "C" fn syscall_handler(index: u32, param1: u64) -> u64 {
-    let ret = match index {
-        // exit
-        0 => SyscallRet::Terminate,
-        // log
-        1 => {
+    let ret = match map_to_syscall(index) {
+        Some(SystemCalls::Exit) => SyscallRet::Terminate,
+        Some(SystemCalls::Log) => {
              unsafe {
                  let str = CStr::from_ptr(param1 as *const c_char);
                  log::info!("{}", str.to_str().unwrap());
              }
              SyscallRet::Ok
          }
-        // sleep
-        2 => SyscallRet::Ok,
+        Some(SystemCalls::Sleep) => SyscallRet::Ok,
          _ => {
              log::info!("Invalid syscall received: {}", index);
              SyscallRet::Unknown
-- 
2.41.0



More information about the Svsm-devel mailing list