[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