Some code for pmt, can compile but cannot run

This commit is contained in:
heheda 2020-05-03 01:31:41 +08:00
parent f4b8ae829f
commit 099969b41f
9 changed files with 170 additions and 49 deletions

View File

@ -5,22 +5,23 @@ use {
sync::Arc,
vec::Vec,
},
spin::Mutex,
dev::Iommu,
kernel_hal::PAGE_SIZE,
crate::vm::*,
};
// Iommu refers to DummyIommu in fuchsia
// BusTransactionInitiator
#[allow(dead_code)]
pub struct Bti {
base: KObjectBase,
iommu: Arc<Iommu>,
bti_id: u64,
pinned_memory: Vec<Pinned>,
quarantine: Vec<Quarantined>
inner: Mutex<BtiInner>,
}
struct Pinned {
struct BtiInner {
pmts: Vec<Arc<Pmt>>,
quarantine: Vec<Quarantined>
}
struct Quarantined {
@ -35,19 +36,43 @@ impl Bti {
base: KObjectBase::new(),
iommu,
bti_id,
pinned_memory: Vec::new(),
quarantine: Vec::new(),
inner: Mutex::new(BtiInner{
pmts: Vec::new(),
quarantine: Vec::new(),
})
})
}
pub fn get_info(&self) -> ZxInfoBti {
let inner = self.inner.lock();
ZxInfoBti {
minimum_contiguity: PAGE_SIZE as u64,
aspace_size: 0xffffffffffffffff,
pmo_count: self.pinned_memory.len() as u64, // need lock
quarantine_count: self.quarantine.len() as u64, // need lock
minimum_contiguity: self.minimum_contiguity() as u64,
aspace_size: self.aspace_size() as u64,
pmo_count: inner.pmts.len() as u64,
quarantine_count: inner.quarantine.len() as u64,
}
}
pub fn pin(&self,
vmo: Arc<VmObject>,
offset: usize,
size: usize,
perms: IommuPerms) -> ZxResult<Arc<Pmt>> {
if size == 0 {
return Err(ZxError::INVALID_ARGS);
}
let pmt = Pmt::create(self, vmo, perms, offset, size)?;
self.inner.lock().pmts.push(pmt.clone()); // I'm not sure...
Ok(pmt)
}
pub fn minimum_contiguity(&self) -> usize {
self.iommu.minimum_contiguity()
}
pub fn aspace_size(&self) -> usize {
self.iommu.aspace_size()
}
}

View File

@ -1,6 +1,8 @@
use {
crate::object::*,
crate::vm::PAGE_SIZE,
alloc::{sync::Arc, vec::Vec},
bitflags::bitflags,
};
// Iommu refers to DummyIommu in fuchsia
@ -26,4 +28,20 @@ impl Iommu {
pub fn is_valid_bus_txn_id(&self) -> bool {
true
}
pub fn minimum_contiguity(&self) -> usize {
PAGE_SIZE as usize
}
pub fn aspace_size(&self) -> usize {
-1 as isize as usize
}
}
bitflags! {
pub struct IommuPerms: u32 {
const PERM_READ = 1 << 0;
const PERM_WRITE = 1 << 1;
const PERM_EXECUTE = 1 << 2;
}
}

View File

@ -2,5 +2,6 @@ use super::*;
mod bti;
mod iommu;
mod pmt;
pub use self::{bti::*, iommu::*};
pub use self::{bti::*, iommu::*, pmt::*};

View File

@ -0,0 +1,72 @@
#![allow(warnings)]
use {
super::*,
crate::object::*,
crate::vm::{DevVAddr, roundup},
crate::vm::*,
alloc::{
sync::{Arc, Weak},
vec::Vec,
}
};
// PinnedMemoryToken
#[allow(dead_code)]
pub struct Pmt {
base: KObjectBase,
vmo: Arc<VmObject>,
offset: usize,
size: usize,
mapped_addrs: Vec<DevVAddr>,
}
impl_kobject!(Pmt);
impl Drop for Pmt {
fn drop(&mut self) {
// TODO: unpin pages
}
}
impl Pmt {
pub fn create(
bti: &Bti,
vmo: Arc<VmObject>,
perms: IommuPerms,
offset: usize,
size: usize,
) -> ZxResult<Arc<Self>> {
if vmo.is_paged() {
vmo.commit(offset, size)?;
vmo.pin(offset, size)?;
}
let num_addrs: usize = if vmo.is_contiguous() {
1
} else {
roundup(size, bti.minimum_contiguity())
};
let mapped_addrs = Pmt::mapped_into_iommu(num_addrs)?;
Ok(Arc::new(Pmt {
base: KObjectBase::new(),
vmo,
offset,
size,
mapped_addrs,
}))
}
pub fn mapped_into_iommu(_num_addrs: usize) -> ZxResult<Vec<DevVAddr>> {
Err(ZxError::NOT_SUPPORTED)
}
pub fn encode_addrs(
&self,
_compress_results: bool,
_contiguous: bool,
_addrs_count: usize,
) -> ZxResult<Vec<DevVAddr>> {
Err(ZxError::NOT_SUPPORTED)
}
}

View File

@ -12,6 +12,9 @@ pub type PhysAddr = usize;
/// Virtual Address
pub type VirtAddr = usize;
// Device Address
pub type DevVAddr = usize;
/// Size of a page
pub const PAGE_SIZE: usize = 0x1000;
@ -29,6 +32,10 @@ pub fn pages(size: usize) -> usize {
size.wrapping_add(PAGE_SIZE - 1) / PAGE_SIZE
}
pub fn roundup(x: usize, align: usize) -> usize {
x.wrapping_add(align - 1) / align
}
pub fn roundup_pages(size: usize) -> usize {
if page_aligned(size) {
size

View File

@ -92,7 +92,13 @@ pub trait VMObjectTrait: Sync + Send {
Err(ZxError::NOT_SUPPORTED)
}
fn is_contiguous(&self) -> bool;
fn is_contiguous(&self) -> bool {
return false;
}
fn is_paged(&self) -> bool {
return false;
}
}
pub struct VmObject {

View File

@ -458,7 +458,7 @@ impl VMObjectTrait for VMObjectPaged {
return res;
}
let start_page = offset / PAGE_SIZE;
let end_page = (start_page + len - 1) / PAGE_SIZE + 1;
let end_page = pages(offset + len);
for i in start_page .. end_page {
let frame = inner.frames.get(&i).unwrap();
if frame.pin_count == VM_PAGE_OBJECT_MAX_PIN_COUNT {
@ -490,7 +490,7 @@ impl VMObjectTrait for VMObjectPaged {
}
let start_page = offset / PAGE_SIZE;
let end_page = (start_page + len - 1) / PAGE_SIZE + 1;
let end_page = pages(offset + len);
for i in start_page..end_page {
let frame = inner.frames.get(&i).unwrap();
if frame.pin_count == 0 {
@ -503,11 +503,9 @@ impl VMObjectTrait for VMObjectPaged {
Ok(())
}
// TODO: for vmo_create_contiguous
fn is_contiguous(&self) -> bool {
false
fn is_paged(&self) -> bool {
return true;
}
}
enum CommitResult {

View File

@ -3,7 +3,7 @@
use {
super::*,
zircon_object::{
dev::{Bti, Iommu},
dev::*,
resource::*,
},
bitflags::bitflags,
@ -72,7 +72,7 @@ impl Syscall<'_> {
vmo: HandleValue,
offset: usize,
size: usize,
addrs: UserOutPtr<PhysAddr>,
mut addrs: UserOutPtr<DevVAddr>,
addrs_count: usize,
mut out: UserOutPtr<HandleValue>,
) -> ZxResult {
@ -90,23 +90,21 @@ impl Syscall<'_> {
return Err(ZxError::ACCESS_DENIED);
}
let mut iommu_perms = IommuOptions::empty();
let mut compress_results = false;
let mut contiguous = false;
let mut iommu_perms = IommuPerms::empty();
let options = BtiOptions::from_bits_truncate(options);
if options.contains(BtiOptions::PERM_READ) {
if !rights.contains(Rights::READ) {
return Err(ZxError::ACCESS_DENIED);
}
iommu_perms.insert(IommuOptions::PERM_READ)
iommu_perms.insert(IommuPerms::PERM_READ)
}
if options.contains(BtiOptions::PERM_WRITE) {
if !rights.contains(Rights::WRITE) {
return Err(ZxError::ACCESS_DENIED);
}
iommu_perms.insert(IommuOptions::PERM_WRITE);
iommu_perms.insert(IommuPerms::PERM_WRITE);
}
if options.contains(BtiOptions::PERM_EXECUTE) {
@ -116,25 +114,24 @@ impl Syscall<'_> {
if !rights.contains(Rights::READ) {
return Err(ZxError::ACCESS_DENIED);
}
iommu_perms.insert(IommuOptions::PERM_EXECUTE);
iommu_perms.insert(IommuPerms::PERM_EXECUTE);
}
if options.contains(BtiOptions::CONTIGUOUS) && options.contains(BtiOptions::COMPRESS) {
return Err(ZxError::INVALID_ARGS);
}
if options.contains(BtiOptions::COMPRESS) {
compress_results = true;
}
if options.contains(BtiOptions::CONTIGUOUS) {
if !vmo.is_contiguous() {
return Err(ZxError::INVALID_ARGS);
}
contiguous = true;
if options.contains(BtiOptions::CONTIGUOUS) && !vmo.is_contiguous() {
return Err(ZxError::INVALID_ARGS)
}
let compress_results = options.contains(BtiOptions::COMPRESS);
let contiguous = options.contains(BtiOptions::CONTIGUOUS);
Err(ZxError::NOT_SUPPORTED)
let pmt = bti.pin(vmo, offset, size, iommu_perms)?;
addrs.write_array(&pmt.as_ref().encode_addrs(compress_results, contiguous, addrs_count)?)?;
let handle = proc.add_handle(Handle::new(pmt, Rights::INSPECT));
out.write(handle)?;
Ok(())
}
}
@ -151,10 +148,3 @@ bitflags! {
}
}
bitflags! {
struct IommuOptions: u32 {
const PERM_READ = 1 << 0;
const PERM_WRITE = 1 << 1;
const PERM_EXECUTE = 1 << 2;
}
}

View File

@ -3,7 +3,7 @@ use {
alloc::vec::Vec,
core::convert::TryFrom,
numeric_enum_macro::numeric_enum,
zircon_object::{signal::Port, task::*, vm::*},
zircon_object::{signal::Port, task::*, vm::*, dev::*},
};
impl Syscall<'_> {
@ -289,6 +289,10 @@ impl Syscall<'_> {
actual.write(count)?;
avail.write(avail_count)?;
}
Topic::Bti => {
let bti = proc.get_object_with_rights::<Bti>(handle, Rights::INSPECT)?;
UserOutPtr::<ZxInfoBti>::from(buffer).write(bti.get_info())?;
}
_ => {
error!("not supported info topic: {:?}", topic);
return Err(ZxError::NOT_SUPPORTED);