blob: d617b9d385fed0815457dc54e6bd2f53fcc0141a [file]
// Copyright 2016 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
use crate::kernel::types::PAddr;
#[cfg(target_arch = "x86_64")]
use crate::object::validate_resource_ioport;
use crate::object::{
BusTransactionInitiatorDispatcher, HandleValue, InitialMutability, ProcessDispatcher,
VmObjectDispatcher, validate_resource_mmio,
};
use crate::vm::pmm::ALLOC_FLAG_ANY;
use crate::vm::vm_object_paged::VmObjectPaged;
use crate::vm::vm_object_physical::VmObjectPhysical;
use debug::ltracef;
use syscalls_macro::syscall;
use zx_status::Status;
use zx_types::{ZX_POL_NEW_VMO, ZX_RIGHT_MAP, zx_paddr_t};
const LOCAL_TRACE: u32 = 0;
// zx_status_t zx_vmo_create_contiguous
#[syscall]
pub fn sys_vmo_create_contiguous(
bti: HandleValue,
size: usize,
mut alignment_log2: u32,
out: &mut HandleValue,
) -> Result<(), Status> {
ltracef!("size 0x{:x}\n", size);
if size == 0 {
return Err(Status::INVALID_ARGS);
}
if !page::is_page_rounded(size) {
return Err(Status::INVALID_ARGS);
}
if alignment_log2 == 0 {
alignment_log2 = page::SHIFT as u32;
}
// catch obviously wrong values
if alignment_log2 < (page::SHIFT as u32) || alignment_log2 >= u64::BITS {
return Err(Status::INVALID_ARGS);
}
let up = ProcessDispatcher::get_current();
up.enforce_basic_policy(ZX_POL_NEW_VMO)?;
let _bti_dispatcher = up
.handle_table()
.get_dispatcher_with_rights::<BusTransactionInitiatorDispatcher>(&up, bti, ZX_RIGHT_MAP)?;
let align_log2_arg = alignment_log2 as u8;
// create a vm object
let vmo = VmObjectPaged::create_contiguous(ALLOC_FLAG_ANY, size as u64, align_log2_arg)?;
// create a Vm Object dispatcher
let (kernel_handle, rights) =
VmObjectDispatcher::create(&vmo, size as u64, InitialMutability::Mutable)?;
// create a handle and attach the dispatcher to it
*out = up.make_and_add_handle(kernel_handle, rights)?;
Ok(())
}
// zx_status_t zx_vmo_create_physical
#[syscall]
pub fn sys_vmo_create_physical(
hrsrc: HandleValue,
paddr: zx_paddr_t,
size: usize,
out: &mut HandleValue,
) -> Result<(), Status> {
ltracef!("size 0x{:x}\n", size);
if size == 0 {
return Err(Status::INVALID_ARGS);
}
if !page::is_page_rounded(size) {
return Err(Status::INVALID_ARGS);
}
let up = ProcessDispatcher::get_current();
up.enforce_basic_policy(ZX_POL_NEW_VMO)?;
// Memory should be subtracted from the PhysicalAspace allocators, so it's
// safe to assume that if the caller has access to a resource for this specified
// region of MMIO space then it is safe to allow the vmo to be created.
validate_resource_mmio(hrsrc, paddr as u64, size)?;
// create a vm object
let vmo = VmObjectPhysical::create(PAddr(paddr), size)?;
// create a Vm Object dispatcher
let (kernel_handle, rights) = VmObjectDispatcher::create(
&VmObjectPhysical::into_vm_object(vmo),
size as u64,
InitialMutability::Mutable,
)?;
// create a handle and attach the dispatcher to it
*out = up.make_and_add_handle(kernel_handle, rights)?;
Ok(())
}
// zx_status_t zx_ioports_request
#[cfg(target_arch = "x86_64")]
#[syscall]
pub fn sys_ioports_request(hrsrc: HandleValue, io_addr: u16, len: u32) -> Result<(), Status> {
validate_resource_ioport(hrsrc, u64::from(io_addr), len as usize)?;
ltracef!("addr {:#x} len {:#x}\n", io_addr, len);
crate::arch_rs::IoBitmap::with_current(|io_bitmap| {
io_bitmap.set_io_bitmap(u32::from(io_addr), len, true)
})
.unwrap()
}
// zx_status_t zx_ioports_release
#[cfg(target_arch = "x86_64")]
#[syscall]
pub fn sys_ioports_release(hrsrc: HandleValue, io_addr: u16, len: u32) -> Result<(), Status> {
validate_resource_ioport(hrsrc, u64::from(io_addr), len as usize)?;
ltracef!("addr {:#x} len {:#x}\n", io_addr, len);
crate::arch_rs::IoBitmap::with_current(|io_bitmap| {
io_bitmap.set_io_bitmap(u32::from(io_addr), len, false)
})
.unwrap()
}
// zx_status_t zx_ioports_request
#[cfg(not(target_arch = "x86_64"))]
#[syscall]
pub fn sys_ioports_request(_hrsrc: HandleValue, _io_addr: u16, _len: u32) -> Result<(), Status> {
// doesn't make sense on non-x86
Err(Status::NOT_SUPPORTED)
}
// zx_status_t zx_ioports_release
#[cfg(not(target_arch = "x86_64"))]
#[syscall]
pub fn sys_ioports_release(_hrsrc: HandleValue, _io_addr: u16, _len: u32) -> Result<(), Status> {
Err(Status::NOT_SUPPORTED)
}