[svsm-devel] task: Implement system call interface

Tom Lendacky thomas.lendacky at amd.com
Mon Sep 11 19:43:08 CEST 2023


On 9/8/23 07:55, Carlos Bilbao wrote:
> 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,
> +}

The SVSM unique syscalls should have numbers that don't conflict with the 
POSIX syscall numbers. This allows for (future) implementation of 
userspace support for things like malloc, mmap, etc.

Thanks,
Tom

> +
> +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


More information about the Svsm-devel mailing list