Adds lifetime to IoCmd, init ipmi commands (#869)

Co-authored-by: tompro <tomas.prochazka@apertia.cz>
This commit is contained in:
SuchAFuriousDeath 2024-06-01 18:27:13 +02:00 committed by GitHub
parent fda9f97bc2
commit 47faa7333e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 500 additions and 71 deletions

View File

@ -28,3 +28,11 @@ impl DeviceDriver for Hid {
todo!()
}
}
#[repr(C)]
#[derive(Debug)]
pub struct OpenPortArgs {
user_id: u32,
ty: u32,
index: u32,
}

View File

@ -1,8 +1,8 @@
use super::FioDeviceGetNameArg;
use crate::dev::{
CuMask, DceFlipControlArg, DceRegisterBufferPtrsArg, DceSubmitFlipArg, DingDongForWorkload,
DmemAllocate, DmemAvailable, DmemQuery, MapComputeQueueArg, MipStatsReport, PrtAperture,
RngInput, SubmitArg, UnmapComputeQueueArg,
DmemAllocate, DmemAvailable, DmemQuery, MapComputeQueueArg, MipStatsReport, OpenPortArgs,
PrtAperture, RngInput, SubmitArg, UnmapComputeQueueArg,
};
use crate::dmem::{BlockpoolExpandArgs, BlockpoolStats};
use crate::errno::ENOTTY;
@ -17,10 +17,10 @@ use std::fmt::Debug;
/// should not be messed with.
macro_rules! commands {
(
$vis:vis enum $enum_name:ident {
$vis:vis enum $enum_name:ident<$lt:lifetime> {
$(
$( #[$attr:meta] )*
$variant:ident $( (& $(mut $($hack:lifetime)? )? $type:ty) )? = $value:literal,
$variant:ident $( (&$vlt:lifetime $(mut $($hack:lifetime)? )? $type:ty) )? = $value:literal,
)*
}
) => {
@ -32,7 +32,7 @@ macro_rules! commands {
$vis enum $enum_name<'a> {
$(
$( #[$attr] )*
$variant $( (&'a $(mut $($hack)? )? $type) )? = {
$variant $( (& $vlt $(mut $($hack)? )? $type) )? = {
assert!( !$enum_name::is_invalid($value) );
$(
@ -44,7 +44,7 @@ macro_rules! commands {
)*
}
impl<'a> $enum_name<'a> {
impl<$lt> $enum_name<$lt> {
pub const IOCPARM_SHIFT: u32 = 13;
pub const IOCPARM_MASK: u32 = (1 << Self::IOCPARM_SHIFT) - 1;
pub const IOC_VOID: u32 = 0x20000000;
@ -91,120 +91,123 @@ macro_rules! commands {
// TODO: implement void ioctl commands with int data
commands! {
pub enum IoCmd {
pub enum IoCmd<'a> {
/// sceKernelMemoryPoolExpand
BPOOLEXPAND(&mut BlockpoolExpandArgs) = 0xc020a801,
BPOOLEXPAND(&'a mut BlockpoolExpandArgs) = 0xc020a801,
/// sceKernelMemoryPoolGetBlockStats
BPOOLSTATS(&mut BlockpoolStats) = 0x4010a802,
BPOOLSTATS(&'a mut BlockpoolStats) = 0x4010a802,
/// An unkown bnet command, called from libSceNet
BNETUNK(&Unknown36) = 0x802450c9,
BNETUNK(&'a Unknown36) = 0x802450c9,
/// Flip control.
DCEFLIPCONTROL(&mut DceFlipControlArg) = 0xC0308203,
/// Flip control
DCEFLIPCONTROL(&'a mut DceFlipControlArg) = 0xC0308203,
/// Submit flip
DCESUBMITFLIP(&mut DceSubmitFlipArg) = 0xC0488204,
DCESUBMITFLIP(&'a mut DceSubmitFlipArg) = 0xC0488204,
/// Register buffer pointers
DCEREGBUFPTRS(&mut DceRegisterBufferPtrsArg) = 0xC0308206,
DCEREGBUFPTRS(&'a mut DceRegisterBufferPtrsArg) = 0xC0308206,
/// Register buffer attribute
DCEREGBUFATTR(&mut Unknown48) = 0xC0308207,
DCEREGBUFATTR(&'a mut Unknown48) = 0xC0308207,
/// Deregister identifier
DCEDEREGIDENT(&u64) = 0x80088209,
DCEDEREGIDENT(&'a u64) = 0x80088209,
/// Get media size in bytes.
DIOCGMEDIASIZE(&mut i64) = 0x40086418,
DIOCGMEDIASIZE(&'a mut i64) = 0x40086418,
/// sceKernelInitializeDipsw
DIPSWINIT = 0x20008800,
/// sceKernelSetDipsw
DIPSWSET(&Unknown2) = 0x80028801,
DIPSWSET(&'a Unknown2) = 0x80028801,
/// sceKernelUnsetDipsw
DIPSWUNSET(&Unknown2) = 0x80028802,
DIPSWUNSET(&'a Unknown2) = 0x80028802,
/// sceKernelCheckDipsw
DIPSWCHECK(&mut Unknown8) = 0xc0088803,
DIPSWCHECK(&'a mut Unknown8) = 0xc0088803,
/// sceKernelReadDipswData
DIPSWREAD(&Unknown16) = 0x80108804,
DIPSWREAD(&'a Unknown16) = 0x80108804,
/// sceKernelWriteDipswData
DIPSWWRITE(&Unknown16) = 0x80108805,
DIPSWWRITE(&'a Unknown16) = 0x80108805,
/// sceKernelCheckDipsw
DIPSWCHECK2(&mut i32) = 0x40048806,
DIPSWCHECK2(&'a mut i32) = 0x40048806,
/// Unkown dipsw command
DIPSWUNK(&mut i32) = 0x40048807,
DIPSWUNK(&'a mut i32) = 0x40048807,
/// Allocate direct memory
DMEMALLOC(&mut DmemAllocate) = 0xc0288001,
DMEMALLOC(&'a mut DmemAllocate) = 0xc0288001,
/// Get total size?
DMEMTOTAL(&mut usize) = 0x4008800a,
DMEMTOTAL(&'a mut usize) = 0x4008800a,
/// Get PRT aperture
DMEMGETPRT(&mut PrtAperture) = 0xc018800c,
DMEMGETPRT(&'a mut PrtAperture) = 0xc018800c,
/// Allocate main direct memory
DMEMALLOCMAIN(&mut DmemAllocate) = 0xc0288011,
DMEMALLOCMAIN(&'a mut DmemAllocate) = 0xc0288011,
/// Query direct memory
DMEMQUERY(&DmemQuery) = 0x80288012,
DMEMQUERY(&'a DmemQuery) = 0x80288012,
/// Get available memory size
DMEMGETAVAIL(&mut DmemAvailable) = 0xc0208016,
DMEMGETAVAIL(&'a mut DmemAvailable) = 0xc0208016,
/// Set close on exec on fd.
FIOCLEX = 0x20006601,
/// Remove close on exec on fd.
FIONCLEX = 0x20006602,
/// Get # bytes to read
FIONREAD(&mut i32) = 0x4004667f,
FIONREAD(&'a mut i32) = 0x4004667f,
/// Set/clear non-blocking I/O.
FIONBIO(&i32) = 0x8004667e,
FIONBIO(&'a i32) = 0x8004667e,
/// Set/clear async I/O.
FIOASYNC(&i32) = 0x8004667d,
FIOASYNC(&'a i32) = 0x8004667d,
/// Set owner
FIOSETOWN(&i32) = 0x8004667c,
FIOSETOWN(&'a i32) = 0x8004667c,
/// Get owner
FIOGETOWN(&mut i32) = 0x4004667b,
FIOGETOWN(&'a mut i32) = 0x4004667b,
/// get d_flags type part
FIODTYPE(&mut i32) = 0x4004667a,
FIODTYPE(&'a mut i32) = 0x4004667a,
/// Get start blk #
FIOGETLBA(&mut i32) = 0x40046679,
FIOGETLBA(&'a mut i32) = 0x40046679,
/// Get dev. name
FIODGNAME(&FioDeviceGetNameArg) = 0x80106678,
FIODGNAME(&'a FioDeviceGetNameArg) = 0x80106678,
/// Get # bytes (yet) to write
FIONWRITE(&mut i32) = 0x40046677,
FIONWRITE(&'a mut i32) = 0x40046677,
/// Get space in send queue
FIONSPACE(&mut i32) = 0x40046676,
FIONSPACE(&'a mut i32) = 0x40046676,
/// Seek data.
FIOSEEKDATA(&mut i64) = 0xc0086661,
FIOSEEKDATA(&'a mut i64) = 0xc0086661,
/// Seek hole.
FIOSEEKHOLE(&mut i64) = 0xc0086662,
FIOSEEKHOLE(&'a mut i64) = 0xc0086662,
/// Set wave limit multiplier
GCSETWAVELIMITMULTIPLIER(&mut i64) = 0xc0088101,
GCSETWAVELIMITMULTIPLIER(&'a mut i64) = 0xc0088101,
/// Submit
GCSUBMIT(&mut SubmitArg) = 0xc0108102,
GCSUBMIT(&'a mut SubmitArg) = 0xc0108102,
/// Get CU mask
GCGETCUMASK(&mut CuMask) = 0xc010810b,
GCGETCUMASK(&'a mut CuMask) = 0xc010810b,
/// Map compute queue
GCMAPCOMPUTEQUEUE(&mut MapComputeQueueArg) = 0xc030810d,
GCMAPCOMPUTEQUEUE(&'a mut MapComputeQueueArg) = 0xc030810d,
/// Unmap compute queue
GCUNMAPCOMPUTEQUEUE(&mut UnmapComputeQueueArg) = 0xc00c810e,
GCUNMAPCOMPUTEQUEUE(&'a mut UnmapComputeQueueArg) = 0xc00c810e,
/// Set GS ring queue sizes
GCSETGSRINGSIZES(&mut Unknown12) = 0xc00c8110,
GCSETGSRINGSIZES(&'a mut Unknown12) = 0xc00c8110,
/// Get mip stats report
GCMIPSTATSREPORT(&mut MipStatsReport) = 0xc0848119,
GCMIPSTATSREPORT(&'a mut MipStatsReport) = 0xc0848119,
/// Currently unknown gc command
GCARESUBMITSALLOWED(&mut Unknown8) = 0xc008811b,
GCARESUBMITSALLOWED(&'a mut Unknown8) = 0xc008811b,
/// Ding dong for workload
GCDINGDONGFORWORKLOAD(&mut DingDongForWorkload) = 0xc010811c,
GCDINGDONGFORWORKLOAD(&'a mut DingDongForWorkload) = 0xc010811c,
/// Get number of tca units
GCGETNUMTCAUNITS(&mut i32) = 0xc004811f,
GCGETNUMTCAUNITS(&'a mut i32) = 0xc004811f,
/// Open port for user
HIDOPENPORTFORUSER(&'a OpenPortArgs) = 0x800c4802,
/// Get genuine random
RNGGETGENUINE(&mut RngInput) = 0x40445301,
RNGGETGENUINE(&'a mut RngInput) = 0x40445301,
/// Fips186Prng
RNGFIPS(&mut RngInput) = 0x40445302,
RNGFIPS(&'a mut RngInput) = 0x40445302,
/// Cat oob mark?
SIOCATMARK(&mut i32) = 0x40047307,
SIOCATMARK(&'a mut i32) = 0x40047307,
/// Set process group
SIOCSPGRP(&i32) = 0x80047308,
SIOCSPGRP(&'a i32) = 0x80047308,
/// Get process group
SIOCGPGRP(&mut i32) = 0x40047309,
SIOCGPGRP(&'a mut i32) = 0x40047309,
/// Become controlling terminal.
TIOCSCTTY = 0x20007461,

View File

@ -4,10 +4,12 @@ pub use self::entry::*;
mod entry;
const ENTRY_COUNT: usize = 0x80;
/// An implementation of `sys/kern/orbis_idt.c`.
#[derive(Debug)]
pub struct Idt<T> {
sets: Vec<[Option<Entry<T>>; 0x80]>,
sets: Vec<[Option<Entry<T>>; ENTRY_COUNT]>,
next: usize,
limit: usize,
}
@ -20,7 +22,7 @@ impl<T> Idt<T> {
assert_ne!(limit, 0);
// Allocate the first set.
let sets = vec![[Self::NONE; 0x80]];
let sets = vec![[Self::NONE; ENTRY_COUNT]];
Self {
sets,
@ -44,7 +46,7 @@ impl<T> Idt<T> {
{
// Allocate a new set if necessary.
let id = self.next;
let set = id / 0x80;
let set = id / ENTRY_COUNT;
while set >= self.sets.len() {
todo!("id_alloc with entries span across the first set");
@ -52,7 +54,7 @@ impl<T> Idt<T> {
// Get the entry.
let set = &mut self.sets[set];
let entry = &mut set[id % 0x80];
let entry = &mut set[id % ENTRY_COUNT];
assert!(entry.is_none());
@ -72,8 +74,8 @@ impl<T> Idt<T> {
}
let i = id & 0x1fff;
let set = self.sets.get_mut(i / 0x80)?;
let entry = set[i % 0x80].as_mut()?;
let set = self.sets.get_mut(i / ENTRY_COUNT)?;
let entry = set[i % ENTRY_COUNT].as_mut()?;
if let Some(ty) = ty {
if entry.ty() != ty {

212
src/kernel/src/ipmi/cmd.rs Normal file
View File

@ -0,0 +1,212 @@
use crate::syscalls::SysErr;
macro_rules! ipmi_command {
(
$( #[$meta:meta] )*
$vis:vis enum $enum_name:ident<$lt:lifetime> {
$(
$variant:ident $( (& $vlt:lifetime mut $arg_ty:ty) )? = $value:expr,
)*
}
) => {
$( #[$meta] )*
$vis enum $enum_name<$lt> {
$(
$variant $( (& $vlt mut $arg_ty) )? = $value,
)*
}
impl<$lt> $enum_name<$lt> {
pub(super) unsafe fn from_raw(cmd: u32, arg: *mut (), size: usize) -> Result<Self, SysErr> {
match cmd {
$(
$value => {
assert!(!arg.is_null());
Ok($enum_name::$variant $( (&mut * {arg as *mut $arg_ty}) )?)
}
)*
_ => todo!("Unhandled ipmi command {:#x}", cmd)
}
}
}
}
}
ipmi_command! {
#[repr(u32)]
#[derive(Debug)]
// TODO: add the rest of the commands
pub(super) enum IpmiCommand<'a> {
CreateServer(&'a mut CreateServerArgs) = 0x0,
DestroyServer = 0x1,
CreateClient(&'a mut CreateClientArgs) = 0x2,
DestroyClient = 0x3,
CreateSession(&'a mut CreateSessionArgs) = 0x4,
DestroySession = 0x5,
ServerReceivePacket(&'a mut ServerReceivePacketArgs) = 0x201,
InvokeAsyncMethod(&'a mut InvokeAsyncMethodArgs) = 0x241,
TryGetResult(&'a mut TryGetResultArgs) = 0x243,
TryGetMessage(&'a mut TryGetMessagetArgs) = 0x252,
DisconnectClient(&'a mut ClientDisconnectArgs) = 0x310,
InvokeSyncMethod(&'a mut InvokeSyncMethodArgs) = 0x320,
ConnectClient(&'a mut ConnectArgs) = 0x400,
PollEventFlag(&'a mut PollEventFlagArgs) = 0x491,
}
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct CreateServerArgs {
imp: usize,
name: *const u8,
config: *const IpmiCreateServerConfig,
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct CreateClientArgs {
imp: usize,
name: *const u8,
config: *const IpmiCreateClientConfig,
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct CreateSessionArgs {
imp: usize,
user_data: *const SessionUserData,
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct ServerReceivePacketArgs {
buf: *mut u8,
buf_size: usize,
packet_info: *const IpmiPacketInfo,
unk: *mut u32,
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct InvokeAsyncMethodArgs {
method: u32,
evf_index: u32,
evf_value: u64,
num_in_data: u32,
info: *const DataInfo,
result: *mut i32,
flags: u32,
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct TryGetResultArgs {
method: u32,
unk: u32,
result: *mut i32,
num_data: u32,
info: *mut BufferInfo,
_pad: u64,
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct ClientDisconnectArgs {
status: *mut u32,
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct TryGetMessagetArgs {
queue_index: u32,
msg: *mut u8,
msg_size: *mut usize,
max_size: usize,
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct InvokeSyncMethodArgs {
method: u32,
in_data_len: u32,
out_data_len: u32,
unk: u32,
in_data: usize,
out_data: usize,
ret: usize,
flags: u32,
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct ConnectArgs {
user_data: usize,
user_data_len: usize,
status: usize,
arg3: usize,
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct PollEventFlagArgs {
index: u32,
pattern_set: u64,
mode: u32,
pattern_set_out: *mut u64,
}
#[repr(C)]
#[derive(Debug)]
struct IpmiCreateServerConfig {
size: usize,
unk1: u32,
unk2: u32,
unk3: u32,
unk4: u32,
enable_multiple_server_threads: u32,
unk5: u32,
unk6: u64,
user_data: *const (),
event_handler: *const (),
}
#[repr(C)]
#[derive(Debug)]
struct IpmiCreateClientConfig {
size: usize,
unk: [u32; 80],
user_data: *const (),
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct BufferInfo {
data: *mut u8,
capacity: usize,
size: usize,
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct DataInfo {
data: *mut u8,
size: usize,
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct SessionUserData {
size: usize,
data: *const u8,
}
#[repr(C)]
#[derive(Debug)]
pub(super) struct IpmiPacketInfo {
size: usize,
ty: u32,
client_kid: u32,
event_handler: *const (),
}

195
src/kernel/src/ipmi/mod.rs Normal file
View File

@ -0,0 +1,195 @@
use crate::{
info,
process::VThread,
syscalls::{SysErr, SysIn, SysOut, Syscalls},
warn,
};
use std::sync::Arc;
mod cmd;
use cmd::*;
pub struct IpmiManager {}
impl IpmiManager {
pub fn new(syscalls: &mut Syscalls) -> Arc<Self> {
let ipmi = Arc::new(Self {});
syscalls.register(622, &ipmi, Self::sys_ipmi_mgr_call);
ipmi
}
fn sys_ipmi_mgr_call(self: &Arc<Self>, td: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
const BUF_SIZE: usize = 0x40;
let cmd: u32 = i.args[0].try_into().unwrap();
let kid: u32 = i.args[1].try_into().unwrap();
let out: *mut i32 = i.args[2].into();
let arg: *mut () = i.args[3].into();
let size: usize = i.args[4].into();
let mut retval: i32 = 0;
if size > BUF_SIZE {
retval = -0x7ff1ffff;
todo!();
}
match cmd {
..=0x270 => todo!(),
0x271 | 0x372 | 0x473 => todo!(),
_ => {}
}
let cmd = unsafe { IpmiCommand::from_raw(cmd, arg, size) }?;
info!("ipmimgr_call with cmd = {cmd:?}");
let ret = match cmd {
IpmiCommand::CreateServer(arg) => self.create_server(arg, &mut retval, td),
IpmiCommand::DestroyServer => self.destroy_server(kid, &mut retval, td),
IpmiCommand::CreateClient(arg) => self.create_client(arg, &mut retval, td),
IpmiCommand::DestroyClient => self.destroy_client(kid, &mut retval, td),
IpmiCommand::CreateSession(arg) => self.create_session(arg, &mut retval, td),
IpmiCommand::DestroySession => self.destroy_session(kid, &mut retval, td),
IpmiCommand::ServerReceivePacket(arg) => {
self.server_receive_packet(arg, kid, &mut retval, td)
}
IpmiCommand::InvokeAsyncMethod(arg) => {
self.invoke_async_method(arg, kid, &mut retval, td)
}
IpmiCommand::TryGetResult(arg) => self.try_get_result(arg, kid, &mut retval, td),
IpmiCommand::TryGetMessage(arg) => self.try_get_message(arg, kid, &mut retval, td),
IpmiCommand::DisconnectClient(arg) => self.disconnect_client(arg, kid, &mut retval, td),
IpmiCommand::InvokeSyncMethod(arg) => {
self.invoke_sync_method(arg, kid, &mut retval, td)
}
IpmiCommand::ConnectClient(arg) => self.connect_client(arg, kid, &mut retval, td),
IpmiCommand::PollEventFlag(arg) => self.poll_event_flag(arg, kid, &mut retval, td),
};
todo!()
}
fn create_server(
&self,
args: &CreateServerArgs,
ret: &mut i32,
td: &VThread,
) -> Result<(), SysErr> {
todo!()
}
fn destroy_server(&self, id: u32, ret: &mut i32, td: &VThread) -> Result<(), SysErr> {
todo!()
}
fn create_client(
&self,
args: &CreateClientArgs,
ret: &mut i32,
td: &VThread,
) -> Result<(), SysErr> {
todo!()
}
fn destroy_client(&self, id: u32, ret: &mut i32, td: &VThread) -> Result<(), SysErr> {
todo!()
}
fn create_session(
&self,
args: &CreateSessionArgs,
ret: &mut i32,
td: &VThread,
) -> Result<(), SysErr> {
todo!()
}
fn destroy_session(&self, id: u32, ret: &mut i32, td: &VThread) -> Result<(), SysErr> {
todo!()
}
fn server_receive_packet(
&self,
args: &ServerReceivePacketArgs,
kid: u32,
ret: &mut i32,
td: &VThread,
) -> Result<(), SysErr> {
todo!()
}
fn invoke_async_method(
&self,
args: &InvokeAsyncMethodArgs,
kid: u32,
ret: &mut i32,
td: &VThread,
) -> Result<(), SysErr> {
todo!()
}
fn try_get_result(
&self,
args: &TryGetResultArgs,
kid: u32,
ret: &mut i32,
td: &VThread,
) -> Result<(), SysErr> {
todo!()
}
fn try_get_message(
&self,
args: &TryGetMessagetArgs,
kid: u32,
ret: &mut i32,
td: &VThread,
) -> Result<(), SysErr> {
todo!()
}
fn disconnect_client(
&self,
args: &ClientDisconnectArgs,
kid: u32,
ret: &mut i32,
td: &VThread,
) -> Result<(), SysErr> {
todo!()
}
fn invoke_sync_method(
&self,
args: &mut InvokeSyncMethodArgs,
kid: u32,
ret: &mut i32,
td: &VThread,
) -> Result<(), SysErr> {
todo!()
}
fn connect_client(
&self,
args: &ConnectArgs,
kid: u32,
ret: &mut i32,
td: &VThread,
) -> Result<(), SysErr> {
todo!()
}
fn poll_event_flag(
&self,
args: &PollEventFlagArgs,
kid: u32,
ret: &mut i32,
td: &VThread,
) -> Result<(), SysErr> {
todo!()
}
}

View File

@ -54,6 +54,7 @@ mod hv;
mod idps;
mod idt;
mod imgact;
mod ipmi;
mod kqueue;
mod log;
mod namedobj;

View File

@ -382,16 +382,19 @@ impl ProcManager {
}
fn sys_cpuset_setaffinity(self: &Arc<Self>, _: &VThread, i: &SysIn) -> Result<SysOut, SysErr> {
let level: CpuLevel = i.args[0].try_into()?;
let which: CpuWhich = i.args[1].try_into()?;
let id: i64 = i.args[2].into();
let cpusetsize: usize = i.args[3].into();
let mask: *const u8 = i.args[4].into();
// TODO: Refactor this for readability.
if cpusetsize.wrapping_sub(8) > 8 {
return Err(SysErr::Raw(ERANGE));
}
if cpusetsize >= 9 {
todo!()
}
let mut buf = vec![0u8; cpusetsize];
unsafe { std::ptr::copy_nonoverlapping(mask, buf.as_mut_ptr(), cpusetsize) };
todo!()
}

View File

@ -616,13 +616,18 @@ impl Vm {
let flags: MappingFlags = i.args[1].try_into().unwrap();
let operations: *const BatchMapArg = i.args[2].into();
let num_of_ops: i32 = i.args[3].try_into().unwrap();
let num_of_processed_ops: *mut i32 = i.args[4].into();
let num_out: *mut i32 = i.args[4].into();
if flags.bits() & 0xe0bffb6f != 0 {
return Err(SysErr::Raw(EINVAL));
}
let slice_size = num_of_ops.try_into().ok().ok_or(SysErr::Raw(EINVAL))?;
let slice_size = match num_of_ops.try_into() {
Ok(size) => size,
Err(_) if num_out.is_null() => return Err(SysErr::Raw(EINVAL)),
Err(_) => todo!(),
};
let operations = unsafe { std::slice::from_raw_parts(operations, slice_size) };
let mut processed = 0;
@ -680,9 +685,9 @@ impl Vm {
// TODO: invalidate TLB
if !num_of_processed_ops.is_null() {
if !num_out.is_null() {
unsafe {
*num_of_processed_ops = processed;
*num_out = processed;
}
}