Skip to content

Commit

Permalink
sbi, api: Use i64 in SbiReturn type
Browse files Browse the repository at this point in the history
This moves the type to correctly match the specification. Through the
use of the From trait on SbiReturn it is possible to get access to the
result of the call as the desired type.

In all cases the value is interpretted as the raw bit value with no
runtime checking (e.g. no checking that a u64 fits into the i64.)

The individual users of the the ecall_send() API can choose the type
that they desire and interpret as required.

See: rivosinc/salus#38

Signed-off-by: Rob Bradford <[email protected]>
  • Loading branch information
rbradford authored and abrestic-rivos committed Mar 29, 2023
1 parent 9b83bc4 commit 18febaf
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 18 deletions.
12 changes: 6 additions & 6 deletions src/api/attestation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,14 @@ pub fn get_evidence(
// passed as arguments.
// GetEvidence writes to a single reference to `cert_bytes``, which is
// defined in this scope.
let len = unsafe { ecall_send(&msg) }?;
let len: usize = unsafe { ecall_send(&msg) }?;

// Safety: cert_bytes is backed by a MAX_CERT_SIZE array.
unsafe {
if len as usize > MAX_CERT_SIZE {
if len > MAX_CERT_SIZE {
return Err(Error::Failed);
}
cert_bytes.set_len(len as usize);
cert_bytes.set_len(len);
};

Ok(cert_bytes)
Expand Down Expand Up @@ -110,14 +110,14 @@ pub fn read_measurement(index: usize) -> Result<ArrayVec<u8, MAX_HASH_SIZE>> {

// Safety: ReadMeasurement writes into a single reference to `msmt_bytes`,
// which is defined in this scope.
let len = unsafe { ecall_send(&msg) }?;
let len: usize = unsafe { ecall_send(&msg) }?;

// Safety: msmt_bytes is backed by a MAX_HASH_SIZE array.
unsafe {
if len as usize > MAX_HASH_SIZE {
if len > MAX_HASH_SIZE {
return Err(Error::Failed);
}
msmt_bytes.set_len(len as usize);
msmt_bytes.set_len(len);
};

Ok(msmt_bytes)
Expand Down
2 changes: 1 addition & 1 deletion src/api/cove_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ pub fn get_info() -> Result<TsmInfo> {
len: tsm_info_size,
});
// Safety: The passed info pointer is uniquely owned so it's safe to modify in SBI.
let tsm_info_len = unsafe { ecall_send(&msg)? };
let tsm_info_len: u64 = unsafe { ecall_send(&msg)? };

if tsm_info_len != tsm_info_size {
return Err(Error::Failed);
Expand Down
62 changes: 51 additions & 11 deletions src/sbi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,21 @@ pub struct SbiReturn {
/// The error code (0 for success).
pub error_code: i64,
/// The return value if the operation is successful.
pub return_value: u64,
pub return_value: i64,
}

impl SbiReturn {
/// Returns an `SbiReturn` that indicates success.
pub fn success(return_value: u64) -> Self {
pub fn success(return_value: i64) -> Self {
Self {
error_code: SBI_SUCCESS,
return_value,
}
}
}

impl From<Result<u64>> for SbiReturn {
fn from(result: Result<u64>) -> SbiReturn {
impl From<Result<i64>> for SbiReturn {
fn from(result: Result<i64>) -> SbiReturn {
match result {
Ok(rv) => Self::success(rv),
Err(e) => Self::from(e),
Expand All @@ -90,10 +90,37 @@ impl From<Error> for SbiReturn {
}
}

impl From<SbiReturn> for Result<i64> {
fn from(ret: SbiReturn) -> Result<i64> {
match ret.error_code {
SBI_SUCCESS => Ok(ret.return_value),
e => Err(Error::from_code(e)),
}
}
}

impl From<SbiReturn> for Result<u64> {
fn from(ret: SbiReturn) -> Result<u64> {
match ret.error_code {
SBI_SUCCESS => Ok(ret.return_value),
SBI_SUCCESS => Ok(ret.return_value as u64),
e => Err(Error::from_code(e)),
}
}
}

impl From<SbiReturn> for Result<usize> {
fn from(ret: SbiReturn) -> Result<usize> {
match ret.error_code {
SBI_SUCCESS => Ok(ret.return_value as usize),
e => Err(Error::from_code(e)),
}
}
}

impl From<SbiReturn> for Result<()> {
fn from(ret: SbiReturn) -> Result<()> {
match ret.error_code {
SBI_SUCCESS => Ok(()),
e => Err(Error::from_code(e)),
}
}
Expand Down Expand Up @@ -340,16 +367,23 @@ impl SbiMessage {
/// msg.result(a0, a1)
/// }
/// ```
pub fn result(&self, a0: u64, a1: u64) -> Result<u64> {
pub fn result<T>(&self, a0: i64, a1: i64) -> Result<T>
where
Result<T>: From<SbiReturn>,
{
let ret = SbiReturn {
error_code: a0 as i64,
error_code: a0,
return_value: a1,
};
match self {
// For legacy messages, a0 is 0 on success and an implementation-defined error value on
// failure. Nothing is returned in a1.
SbiMessage::PutChar(_) => match a0 as i64 {
SBI_SUCCESS => Ok(0),
SbiMessage::PutChar(_) => match a0 {
SBI_SUCCESS => SbiReturn {
error_code: 0,
return_value: 0,
}
.into(),
_ => Err(Error::Failed),
},
_ => ret.into(),
Expand All @@ -369,7 +403,10 @@ impl SbiMessage {
/// In addition the caller is placing trust in the firmware or hypervisor to maintain the promises
/// of the interface w.r.t. reading and writing only within the provided bounds.
#[cfg(all(target_arch = "riscv64", target_os = "none"))]
pub unsafe fn ecall_send(msg: &SbiMessage) -> Result<u64> {
pub unsafe fn ecall_send<T>(msg: &SbiMessage) -> Result<T>
where
Result<T>: From<SbiReturn>,
{
// normally error code
let mut a0;
// normally return value
Expand All @@ -388,6 +425,9 @@ pub unsafe fn ecall_send(msg: &SbiMessage) -> Result<u64> {
/// # Safety
///
/// Test-only. Do not call.
pub unsafe fn ecall_send(_msg: &SbiMessage) -> Result<u64> {
pub unsafe fn ecall_send<T>(_msg: &SbiMessage) -> Result<T>
where
Result<T>: From<SbiReturn>,
{
panic!("ecall_send called");
}

0 comments on commit 18febaf

Please sign in to comment.