[svsm-devel] task: Implement system call interface

Carlos Bilbao carlos.bilbao at amd.com
Thu Sep 14 16:28:11 CEST 2023


On 9/11/23 12:43, Tom Lendacky wrote:
> 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 for pointing that out, I have updated the pull request, now we
start with SystemCalls::Exit = 500.

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

Thanks,
Carlos


More information about the Svsm-devel mailing list