mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
feat: uapi/syscall: define reply convention
This commit is contained in:
parent
d2a4b4899d
commit
ecb0142b69
@ -1,6 +1,7 @@
|
|||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)]
|
||||||
pub enum SysError {
|
pub enum SysError {
|
||||||
Ok,
|
Ok,
|
||||||
|
Invalid,
|
||||||
InvalidArgument,
|
InvalidArgument,
|
||||||
CapTypeMismatch, // Cap, Untyped
|
CapTypeMismatch, // Cap, Untyped
|
||||||
SlotNotEmpty, // Untyped
|
SlotNotEmpty, // Untyped
|
||||||
|
@ -15,6 +15,14 @@ pub enum Syscall {
|
|||||||
// Reply = 7,
|
// Reply = 7,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)]
|
||||||
|
pub enum ReplyLabel {
|
||||||
|
Invalid = 0,
|
||||||
|
Message = 1,
|
||||||
|
Signal = 2,
|
||||||
|
Fault = 3,
|
||||||
|
}
|
||||||
|
|
||||||
/* Syscall convention:
|
/* Syscall convention:
|
||||||
* > Call:
|
* > Call:
|
||||||
* > > +----------+-------------------------+--------------------+
|
* > > +----------+-------------------------+--------------------+
|
||||||
@ -27,9 +35,16 @@ pub enum Syscall {
|
|||||||
* > > if info.transfer_cap { Arguments[-2] = cap_ptr; Arguments[-1] = n_bits; }
|
* > > if info.transfer_cap { Arguments[-2] = cap_ptr; Arguments[-1] = n_bits; }
|
||||||
* >
|
* >
|
||||||
* > Reply:
|
* > Reply:
|
||||||
* > TODO: figure out how vanilla seL4 handle reply
|
* > > +----------+-------------------------+--------------+
|
||||||
|
* > > | [a0] | REG_REPLY_INFO | ReplyInfo |
|
||||||
|
* > > | [a1] | REG_BADGE | Badge |
|
||||||
|
* > > | [a2..a7] | REG_ARG_0..=REG_ARG_MAX | Replied Data |
|
||||||
|
* > > | buffer | REG_ARG_MAX+1.. | Replied Data |
|
||||||
|
* > > +----------+-------------------------+--------------+
|
||||||
|
* > > length = (a0..).length(), extra data are stored on ipc buffer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Call
|
||||||
pub const REG_MESSAGE_INFO: usize = 0;
|
pub const REG_MESSAGE_INFO: usize = 0;
|
||||||
pub const REG_CAP_PTR: usize = 1;
|
pub const REG_CAP_PTR: usize = 1;
|
||||||
pub const REG_ARG_0: usize = 2;
|
pub const REG_ARG_0: usize = 2;
|
||||||
@ -38,6 +53,10 @@ pub const REG_ARG_MAX: usize = 7;
|
|||||||
pub const LEN_ARG_OFFSET_CPTR: usize = 2;
|
pub const LEN_ARG_OFFSET_CPTR: usize = 2;
|
||||||
pub const LEN_ARG_OFFSET_BITS: usize = 1;
|
pub const LEN_ARG_OFFSET_BITS: usize = 1;
|
||||||
|
|
||||||
|
// Reply
|
||||||
|
pub const REG_REPLY_INFO: usize = 0;
|
||||||
|
pub const REG_BADGE: usize = 1;
|
||||||
|
|
||||||
/* MessageInfo layout:
|
/* MessageInfo layout:
|
||||||
* > +---------+--------+--------+--------------+
|
* > +---------+--------+--------+--------------+
|
||||||
* > | label | bits | length | transfer_cap |
|
* > | label | bits | length | transfer_cap |
|
||||||
@ -65,9 +84,9 @@ impl MessageInfo {
|
|||||||
const TRANSFER_CAP_OFFSET: usize = 0;
|
const TRANSFER_CAP_OFFSET: usize = 0;
|
||||||
|
|
||||||
pub fn new(label: Syscall, bits: usize, length: usize, transfer_cap: bool) -> Self {
|
pub fn new(label: Syscall, bits: usize, length: usize, transfer_cap: bool) -> Self {
|
||||||
let label = label.to_usize().unwrap_or(0);
|
let label = label.to_usize().unwrap();
|
||||||
let bits = bits - 1; // stored as n_bits - 1
|
let bits = bits - 1; // stored as n_bits - 1
|
||||||
let transfer_cap = transfer_cap as usize;
|
let transfer_cap = if transfer_cap { 1 } else { 0 };
|
||||||
|
|
||||||
assert!(label <= Self::LABEL_MASK);
|
assert!(label <= Self::LABEL_MASK);
|
||||||
assert!(bits <= Self::BITS_MASK);
|
assert!(bits <= Self::BITS_MASK);
|
||||||
@ -117,6 +136,95 @@ impl TryFrom<usize> for MessageInfo {
|
|||||||
|
|
||||||
fn try_from(value: usize) -> Result<Self, Self::Error> {
|
fn try_from(value: usize) -> Result<Self, Self::Error> {
|
||||||
let info = Self(value);
|
let info = Self(value);
|
||||||
(info.label() != Syscall::Invalid).then_ok(info, SysError::InvalidArgument)
|
(info.label() != Syscall::Invalid).then_ok(info, SysError::Invalid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ReplyInfo layout:
|
||||||
|
* > +---------+--------+--------+------------+-------+
|
||||||
|
* > | label | length | badged | transfered | error |
|
||||||
|
* > | [16:14] | [13:7] | [6] | [5] | [4:0] |
|
||||||
|
* > +---------+--------+--------+------------+-------+
|
||||||
|
* > label: reply label
|
||||||
|
* > length: args.len()
|
||||||
|
* > badged: if badged
|
||||||
|
* > transfered: if cap is transfered
|
||||||
|
* > error: error code
|
||||||
|
*/
|
||||||
|
pub struct ReplyInfo(usize);
|
||||||
|
|
||||||
|
impl ReplyInfo {
|
||||||
|
const LABEL_MASK: usize = MASK!(16 - 14 + 1);
|
||||||
|
const LABEL_OFFSET: usize = 14;
|
||||||
|
|
||||||
|
const LENGTH_MASK: usize = MASK!(13 - 7 + 1);
|
||||||
|
const LENGTH_OFFSET: usize = 7;
|
||||||
|
|
||||||
|
const BADGED_MASK: usize = MASK!(1);
|
||||||
|
const BADGED_OFFSET: usize = 6;
|
||||||
|
|
||||||
|
const TRANSFERED_MASK: usize = MASK!(1);
|
||||||
|
const TRANSFERED_OFFSET: usize = 5;
|
||||||
|
|
||||||
|
const ERROR_MASK: usize = MASK!(4 - 0 + 1);
|
||||||
|
const ERROR_OFFSET: usize = 0;
|
||||||
|
|
||||||
|
pub fn new(label: ReplyLabel, length: usize, badged: bool, transfered: bool, error: SysError) -> Self {
|
||||||
|
let label = label.to_usize().unwrap();
|
||||||
|
let badged = if badged { 1 } else { 0 };
|
||||||
|
let transfered = if transfered { 1 } else { 0 };
|
||||||
|
let error = error.to_usize().unwrap();
|
||||||
|
|
||||||
|
assert!(label <= Self::LABEL_MASK);
|
||||||
|
assert!(length <= Self::LENGTH_MASK);
|
||||||
|
assert!(error <= Self::ERROR_MASK);
|
||||||
|
|
||||||
|
let info = ((label & Self::LABEL_MASK) << Self::LABEL_OFFSET)
|
||||||
|
| ((length & Self::LENGTH_MASK) << Self::LENGTH_OFFSET)
|
||||||
|
| ((badged & Self::BADGED_MASK) << Self::BADGED_OFFSET)
|
||||||
|
| ((transfered & Self::TRANSFERED_MASK) << Self::TRANSFERED_OFFSET)
|
||||||
|
| ((error & Self::ERROR_MASK) << Self::ERROR_OFFSET);
|
||||||
|
Self(info)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn label(&self) -> ReplyLabel {
|
||||||
|
ReplyLabel::from_usize((self.0 >> Self::LABEL_OFFSET) & Self::LABEL_MASK).unwrap_or(ReplyLabel::Invalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn length(&self) -> usize {
|
||||||
|
(self.0 >> Self::LENGTH_OFFSET) & Self::LENGTH_MASK
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn badged(&self) -> bool {
|
||||||
|
(self.0 >> Self::BADGED_OFFSET) & Self::BADGED_MASK != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn transfered(&self) -> bool {
|
||||||
|
(self.0 >> Self::TRANSFERED_OFFSET) & Self::TRANSFERED_MASK != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn error(&self) -> SysError {
|
||||||
|
SysError::from_usize((self.0 >> Self::ERROR_OFFSET) & Self::ERROR_MASK).unwrap_or(SysError::Invalid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for ReplyInfo {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
f.debug_struct("ReplyInfo")
|
||||||
|
.field("label", &self.label())
|
||||||
|
.field("length", &self.length())
|
||||||
|
.field("badged", &self.badged())
|
||||||
|
.field("transfered", &self.transfered())
|
||||||
|
.field("error", &self.error())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<usize> for ReplyInfo {
|
||||||
|
type Error = SysError;
|
||||||
|
|
||||||
|
fn try_from(value: usize) -> Result<Self, Self::Error> {
|
||||||
|
let info = Self(value);
|
||||||
|
(info.label() != ReplyLabel::Invalid).then_ok(info, SysError::Invalid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user