Skip to content

Commit

Permalink
Merge pull request #456 from cxdong/obj-code
Browse files Browse the repository at this point in the history
Implement object management
  • Loading branch information
joergroedel authored Sep 26, 2024
2 parents c77eba0 + 24be6b7 commit 6064a62
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 0 deletions.
9 changes: 9 additions & 0 deletions kernel/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use crate::mm::alloc::AllocError;
use crate::sev::ghcb::GhcbError;
use crate::sev::msr_protocol::GhcbMsrError;
use crate::sev::SevSnpError;
use crate::syscall::ObjError;
use crate::task::TaskError;
use elf::ElfError;

Expand Down Expand Up @@ -83,6 +84,8 @@ pub enum SvsmError {
Acpi,
/// Errors from the filesystem.
FileSystem(FsError),
/// Obj related error
Obj(ObjError),
/// Task management errors,
Task(TaskError),
/// Errors from #VC handler
Expand All @@ -104,3 +107,9 @@ impl From<ApicError> for SvsmError {
Self::Apic(err)
}
}

impl From<ObjError> for SvsmError {
fn from(err: ObjError) -> Self {
Self::Obj(err)
}
}
2 changes: 2 additions & 0 deletions kernel/src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@
// Author: Joerg Roedel <[email protected]>

mod handlers;
mod obj;

pub use handlers::*;
pub use obj::{Obj, ObjError, ObjHandle};
113 changes: 113 additions & 0 deletions kernel/src/syscall/obj.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2024 Intel Corporation.
//
// Author: Chuanxiao Dong <[email protected]>

extern crate alloc;

use crate::cpu::percpu::current_task;
use crate::error::SvsmError;
use alloc::sync::Arc;

#[derive(Clone, Copy, Debug)]
pub enum ObjError {
InvalidHandle,
NotFound,
}

/// An object represents the type of resource like file, VM, vCPU in the
/// COCONUT-SVSM kernel which can be accessible by the user mode. The Obj
/// trait is defined for such type of resource, which can be used to define
/// the common functionalities of the objects. With the trait bounds of Send
/// and Sync, the objects implementing Obj trait could be sent to another
/// thread and shared between threads safely.
pub trait Obj: Send + Sync + core::fmt::Debug {}

/// ObjHandle is a unique identifier for an object in the current process.
/// An ObjHandle can be converted to a u32 id which can be used by the user
/// mode to access this object. The passed id from the user mode by syscalls
/// can be converted to an `ObjHandle`, which is used to access the object in
/// the COCONUT-SVSM kernel.
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct ObjHandle(u32);

impl ObjHandle {
pub fn new(id: u32) -> Self {
Self(id)
}
}

impl From<u32> for ObjHandle {
#[inline]
fn from(id: u32) -> Self {
Self(id)
}
}

impl From<ObjHandle> for u32 {
#[inline]
fn from(obj_handle: ObjHandle) -> Self {
obj_handle.0
}
}

/// Add an object to the current process and assigns it an `ObjHandle`.
///
/// # Arguments
///
/// * `obj` - An `Arc<dyn Obj>` representing the object to be added.
///
/// # Returns
///
/// * `Result<ObjHandle, SvsmError>` - Returns the object handle of the
/// added object if successful, or an `SvsmError` on failure.
///
/// # Errors
///
/// This function will return an error if adding the object to the
/// current task fails.
#[allow(dead_code)]
pub fn obj_add(obj: Arc<dyn Obj>) -> Result<ObjHandle, SvsmError> {
current_task().add_obj(obj)
}

/// Closes an object identified by its ObjHandle.
///
/// # Arguments
///
/// * `id` - The ObjHandle for the object to be closed.
///
/// # Returns
///
/// * `Result<Arc<dyn Obj>>, SvsmError>` - Returns the `Arc<dyn Obj>`
/// on success, or an `SvsmError` on failure.
///
/// # Errors
///
/// This function will return an error if removing the object from the
/// current task fails.
#[allow(dead_code)]
pub fn obj_close(id: ObjHandle) -> Result<Arc<dyn Obj>, SvsmError> {
current_task().remove_obj(id)
}

/// Retrieves an object by its ObjHandle.
///
/// # Arguments
///
/// * `id` - The ObjHandle for the object to be retrieved.
///
/// # Returns
///
/// * `Result<Arc<dyn Obj>>, SvsmError>` - Returns the `Arc<dyn Obj>` on
/// success, or an `SvsmError` on failure.
///
/// # Errors
///
/// This function will return an error if retrieving the object from the
/// current task fails.
#[allow(dead_code)]
pub fn obj_get(id: ObjHandle) -> Result<Arc<dyn Obj>, SvsmError> {
current_task().get_obj(id)
}
88 changes: 88 additions & 0 deletions kernel/src/task/tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

extern crate alloc;

use alloc::collections::btree_map::BTreeMap;
use alloc::sync::Arc;
use core::fmt;
use core::mem::size_of;
Expand All @@ -27,6 +28,7 @@ use crate::mm::{
mappings::create_anon_mapping, mappings::create_file_mapping, VMMappingGuard,
SVSM_PERTASK_BASE, SVSM_PERTASK_END, SVSM_PERTASK_STACK_BASE, USER_MEM_END, USER_MEM_START,
};
use crate::syscall::{Obj, ObjError, ObjHandle};
use crate::types::{SVSM_USER_CS, SVSM_USER_DS};
use crate::utils::MemoryRegion;
use intrusive_collections::{intrusive_adapter, LinkedListAtomicLink};
Expand Down Expand Up @@ -139,6 +141,9 @@ pub struct Task {

/// Link to scheduler run queue
runlist_link: LinkedListAtomicLink,

/// Objects shared among threads within the same process
objs: Arc<RWLock<BTreeMap<ObjHandle, Arc<dyn Obj>>>>,
}

// SAFETY: Send + Sync is required for Arc<Task> to implement Send. All members
Expand Down Expand Up @@ -206,6 +211,7 @@ impl Task {
id: TASK_ID_ALLOCATOR.next_id(),
list_link: LinkedListAtomicLink::default(),
runlist_link: LinkedListAtomicLink::default(),
objs: Arc::new(RWLock::new(BTreeMap::new())),
}))
}

Expand Down Expand Up @@ -249,6 +255,7 @@ impl Task {
id: TASK_ID_ALLOCATOR.next_id(),
list_link: LinkedListAtomicLink::default(),
runlist_link: LinkedListAtomicLink::default(),
objs: Arc::new(RWLock::new(BTreeMap::new())),
}))
}

Expand Down Expand Up @@ -475,6 +482,87 @@ impl Task {
self.vm_user_range.as_ref().unwrap().remove(addr)?;
Ok(())
}

/// Adds an object to the current task.
///
/// # Arguments
///
/// * `obj` - The object to be added.
///
/// # Returns
///
/// * `Result<ObjHandle, SvsmError>` - Returns the object handle for the object
/// to be added if successful, or an `SvsmError` on failure.
///
/// # Errors
///
/// This function will return an error if allocating the object handle fails.
pub fn add_obj(&self, obj: Arc<dyn Obj>) -> Result<ObjHandle, SvsmError> {
let mut objs = self.objs.lock_write();
let last_key = objs
.keys()
.last()
.map_or(Some(0), |k| u32::from(*k).checked_add(1))
.ok_or(SvsmError::from(ObjError::InvalidHandle))?;
let id = ObjHandle::new(if last_key != objs.len() as u32 {
objs.keys()
.enumerate()
.find(|(i, &key)| *i as u32 != u32::from(key))
.unwrap()
.0 as u32
} else {
last_key
});

objs.insert(id, obj);

Ok(id)
}

/// Removes an object from the current task.
///
/// # Arguments
///
/// * `id` - The ObjHandle for the object to be removed.
///
/// # Returns
///
/// * `Result<Arc<dyn Obj>>, SvsmError>` - Returns the removed `Arc<dyn Obj>`
/// on success, or an `SvsmError` on failure.
///
/// # Errors
///
/// This function will return an error if the object handle id does not
/// exist in the current task.
pub fn remove_obj(&self, id: ObjHandle) -> Result<Arc<dyn Obj>, SvsmError> {
self.objs
.lock_write()
.remove(&id)
.ok_or(ObjError::NotFound.into())
}

/// Retrieves an object from the current task.
///
/// # Arguments
///
/// * `id` - The ObjHandle for the object to be retrieved.
///
/// # Returns
///
/// * `Result<Arc<dyn Obj>>, SvsmError>` - Returns the `Arc<dyn Obj>` on
/// success, or an `SvsmError` on failure.
///
/// # Errors
///
/// This function will return an error if the object handle id does not exist
/// in the current task.
pub fn get_obj(&self, id: ObjHandle) -> Result<Arc<dyn Obj>, SvsmError> {
self.objs
.lock_read()
.get(&id)
.cloned()
.ok_or(ObjError::NotFound.into())
}
}

pub fn is_task_fault(vaddr: VirtAddr) -> bool {
Expand Down
2 changes: 2 additions & 0 deletions syscall/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@
#![no_std]

mod numbers;
mod obj;

pub use numbers::*;
pub use obj::*;
29 changes: 29 additions & 0 deletions syscall/src/obj.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2024 Intel Corporation.
//
// Author: Chuanxiao Dong <[email protected]>

/// The object is exposed to the user mode via the object-opening related
/// syscalls, which returns the id of the object created by the COCONUT-SVSM
/// kernel. The user mode can make use this id to access the corresponding
/// object via other syscalls. From the user mode's point of view, an
/// ObjHanle is defined to wrap a u32 which is the value returned by an
/// object-opening syscall. This u32 value can be used as the input for the
/// syscalls to access the corresponding kernel object.
#[derive(Debug)]
pub struct ObjHandle(u32);

impl ObjHandle {
#[allow(dead_code)]
pub(crate) fn new(id: u32) -> Self {
Self(id)
}
}

impl From<&ObjHandle> for u32 {
#[inline]
fn from(obj_handle: &ObjHandle) -> Self {
obj_handle.0
}
}

0 comments on commit 6064a62

Please sign in to comment.