mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
feat: uapi/syscall: update message info, add cap n_bits field
This commit is contained in:
parent
c352a0b8c6
commit
7b54abcc13
@ -4,17 +4,10 @@ use uapi::{error::*, syscall::*};
|
|||||||
|
|
||||||
pub fn handle_syscall(tcb: &mut TcbObject) -> SysResult {
|
pub fn handle_syscall(tcb: &mut TcbObject) -> SysResult {
|
||||||
let info = MessageInfo::try_from(tcb.trapframe.get_reg(0))?;
|
let info = MessageInfo::try_from(tcb.trapframe.get_reg(0))?;
|
||||||
let cspace = CNodeCap::try_from(tcb.cspace())?;
|
|
||||||
|
|
||||||
let cap_ptr = tcb.trapframe.get_reg(1);
|
|
||||||
let cap = cspace
|
|
||||||
.resolve_address_bits(cap_ptr, usize::BITS as usize)
|
|
||||||
.map_err(SysError::from)?;
|
|
||||||
|
|
||||||
trace!("handle_syscall: info={:?} cap={:?}", info, cap);
|
|
||||||
|
|
||||||
|
// Invalid, Debug*, Yield will bypass the capability check
|
||||||
match info.label() {
|
match info.label() {
|
||||||
Syscall::Invalid => Ok(()),
|
Syscall::Invalid => return Ok(()),
|
||||||
Syscall::DebugPutChar => {
|
Syscall::DebugPutChar => {
|
||||||
if info.length() != 3 {
|
if info.length() != 3 {
|
||||||
return Err(SysError::InvalidArgument);
|
return Err(SysError::InvalidArgument);
|
||||||
@ -22,13 +15,23 @@ pub fn handle_syscall(tcb: &mut TcbObject) -> SysResult {
|
|||||||
|
|
||||||
let c = tcb.trapframe.get_reg(2) as u8 as char;
|
let c = tcb.trapframe.get_reg(2) as u8 as char;
|
||||||
crate::print!("{}", c);
|
crate::print!("{}", c);
|
||||||
|
return Ok(());
|
||||||
Ok(())
|
|
||||||
},
|
},
|
||||||
Syscall::Yield => {
|
Syscall::Yield => {
|
||||||
tcb.clear_timetick();
|
tcb.clear_timetick();
|
||||||
Ok(())
|
return Ok(());
|
||||||
},
|
},
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
|
||||||
|
let cspace = CNodeCap::try_from(tcb.cspace())?;
|
||||||
|
let cap_ptr = tcb.trapframe.get_reg(1);
|
||||||
|
let cap = cspace.resolve_address_bits(cap_ptr, info.bits()).map_err(SysError::from)?;
|
||||||
|
|
||||||
|
trace!("handle_syscall: info={:?} cap={:?}", info, cap);
|
||||||
|
|
||||||
|
match info.label() {
|
||||||
|
Syscall::Send => Ok(()),
|
||||||
_ => unimplemented!("handle_syscall: {:?}, {:?}", info.label(), cap),
|
_ => unimplemented!("handle_syscall: {:?}, {:?}", info.label(), cap),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
root/root.S
12
root/root.S
@ -11,15 +11,15 @@ _start:
|
|||||||
.loop:
|
.loop:
|
||||||
lb a2, 0(t0)
|
lb a2, 0(t0)
|
||||||
beqz a2, .yield
|
beqz a2, .yield
|
||||||
# msg: label = DebugPutChar(1), length = 3
|
# msg: label = DebugPutChar(1), bits = 1, length = 3
|
||||||
# ptr: self-referential to cspace, just to create a valid cptr
|
# ptr: (any)
|
||||||
syscall (1<<12 | 3), 0x0202020202020202
|
syscall (1<<13 | 0<<7 | 3), 0
|
||||||
addi t0, t0, 1
|
addi t0, t0, 1
|
||||||
j .loop
|
j .loop
|
||||||
.yield:
|
.yield:
|
||||||
# msg: label = Yield(2), length = 2
|
# msg: label = Yield(2), bits = 1, length = 2
|
||||||
# ptr: self-referential to cspace, just to create a valid cptr
|
# ptr: (any)
|
||||||
syscall (2<<12 | 2), 0x0202020202020202
|
syscall (2<<13 | 0<<7 | 2), 0
|
||||||
j _start
|
j _start
|
||||||
|
|
||||||
.data
|
.data
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
use core::fmt::Debug;
|
|
||||||
|
|
||||||
use num_traits::{FromPrimitive, ToPrimitive};
|
|
||||||
use utils::MASK;
|
|
||||||
|
|
||||||
use crate::error::SysError;
|
use crate::error::SysError;
|
||||||
|
use core::fmt::Debug;
|
||||||
|
use num_traits::{FromPrimitive, ToPrimitive};
|
||||||
|
use utils::{then::Then, MASK};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, FromPrimitive, ToPrimitive)]
|
||||||
pub enum Syscall {
|
pub enum Syscall {
|
||||||
@ -17,40 +15,62 @@ pub enum Syscall {
|
|||||||
Reply = 7,
|
Reply = 7,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* in vanilla seL4, MessageInfo layout:
|
/* Syscall convention:
|
||||||
* > | label | caps | extra_caps | length |
|
|
||||||
* > | [63:12] | [11:9] | [8:7] | [6:0] |
|
|
||||||
*
|
|
||||||
* in out implementation, MessageInfo layout:
|
|
||||||
* > label: Syscall
|
|
||||||
* > length: args.len()
|
|
||||||
*
|
|
||||||
* Syscall convention:
|
|
||||||
* > Call:
|
* > Call:
|
||||||
* > > [a0]: MessageInfo
|
* > > [a0]: MessageInfo
|
||||||
* > > [a1]: Capability Pointer
|
* > > [a1]: Capability Pointer
|
||||||
* > > [a2..a7]: extra arguments
|
* > > [a2..a7]: extra arguments
|
||||||
* > > length = (a0..a?).len()
|
* > > length = (a0..a?).len()
|
||||||
|
* >
|
||||||
* > Reply:
|
* > Reply:
|
||||||
* > TODO: figure out how vanilla seL4 handle reply
|
* > TODO: figure out how vanilla seL4 handle reply
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* MessageInfo layout:
|
||||||
|
* > | label | bits | length |
|
||||||
|
* > | [63:13] | [12:7] | [6:0] |
|
||||||
|
* > label: Syscall
|
||||||
|
* > bits: cap_ptr n_bits
|
||||||
|
* > length: args.len()
|
||||||
|
*
|
||||||
|
*/
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct MessageInfo(usize);
|
pub struct MessageInfo(usize);
|
||||||
|
|
||||||
impl MessageInfo {
|
impl MessageInfo {
|
||||||
const LABEL_MASK: usize = MASK!(63 - 12 + 1);
|
const LABEL_MASK: usize = MASK!(63 - 13 + 1);
|
||||||
|
const LABEL_OFFSET: usize = 13;
|
||||||
|
|
||||||
pub fn new(label: Syscall, length: usize) -> Self {
|
const BITS_MASK: usize = MASK!(6);
|
||||||
Self((label.to_usize().unwrap_or(0)) << 12 | (length & 0x7f))
|
const BITS_OFFSET: usize = 7;
|
||||||
|
|
||||||
|
const LENGTH_MASK: usize = MASK!(7);
|
||||||
|
const LENGTH_OFFSET: usize = 0;
|
||||||
|
|
||||||
|
pub fn new(label: Syscall, bits: usize, length: usize) -> Self {
|
||||||
|
let label = label.to_usize().unwrap_or(0);
|
||||||
|
let bits = bits - 1; // stored as n_bits - 1
|
||||||
|
|
||||||
|
assert!(label <= Self::LABEL_MASK);
|
||||||
|
assert!(bits <= Self::BITS_MASK);
|
||||||
|
assert!(length <= Self::LENGTH_MASK);
|
||||||
|
|
||||||
|
let info = ((label & Self::LABEL_MASK) << Self::LABEL_OFFSET)
|
||||||
|
| ((bits & Self::BITS_MASK) << Self::BITS_OFFSET)
|
||||||
|
| ((length & Self::LENGTH_MASK) << Self::LENGTH_OFFSET);
|
||||||
|
Self(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn label(&self) -> Syscall {
|
pub fn label(&self) -> Syscall {
|
||||||
Syscall::from_usize((self.0 >> 12) & Self::LABEL_MASK).unwrap_or(Syscall::Invalid)
|
Syscall::from_usize((self.0 >> Self::LABEL_OFFSET) & Self::LABEL_MASK).unwrap_or(Syscall::Invalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bits(&self) -> usize {
|
||||||
|
((self.0 >> Self::BITS_OFFSET) & Self::BITS_MASK) + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn length(&self) -> usize {
|
pub fn length(&self) -> usize {
|
||||||
self.0 & 0x7F
|
(self.0 >> Self::LENGTH_OFFSET) & Self::LENGTH_MASK
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_usize(&self) -> usize {
|
pub fn as_usize(&self) -> usize {
|
||||||
@ -62,6 +82,7 @@ impl Debug for MessageInfo {
|
|||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
f.debug_struct("MessageInfo")
|
f.debug_struct("MessageInfo")
|
||||||
.field("label", &self.label())
|
.field("label", &self.label())
|
||||||
|
.field("bits", &self.bits())
|
||||||
.field("length", &self.length())
|
.field("length", &self.length())
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
@ -71,8 +92,7 @@ impl TryFrom<usize> for MessageInfo {
|
|||||||
type Error = SysError;
|
type Error = SysError;
|
||||||
|
|
||||||
fn try_from(value: usize) -> Result<Self, Self::Error> {
|
fn try_from(value: usize) -> Result<Self, Self::Error> {
|
||||||
let syscall = Syscall::from_usize((value >> 12) & MessageInfo::LABEL_MASK).ok_or(SysError::InvalidArgument)?;
|
let info = Self(value);
|
||||||
let length = value & 0x7F;
|
(info.label() != Syscall::Invalid).then_ok(info, SysError::InvalidArgument)
|
||||||
Ok(Self::new(syscall, length))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user