hypervisor: support set bell type (asynchronous) traps

This commit is contained in:
equation314 2020-07-16 22:27:56 +08:00
parent 0a47a003d9
commit 08640b373f
5 changed files with 62 additions and 34 deletions

View File

@ -1,7 +1,12 @@
use {
crate::{object::*, signal::Port, vm::VmAddressRegion},
alloc::sync::Arc,
rvm::{Guest as GuestInner, RvmError, RvmResult, TrapKind},
crate::{
object::*,
signal::{Port, PortPacket},
vm::VmAddressRegion,
},
alloc::sync::{Arc, Weak},
core::convert::{TryFrom, TryInto},
rvm::{Guest as GuestInner, RvmError, RvmExitPacket, RvmPort, RvmResult, TrapKind},
rvm::{GuestPhysAddr, GuestPhysMemorySetTrait, HostPhysAddr},
};
@ -38,13 +43,12 @@ impl Guest {
kind: u32,
addr: usize,
size: usize,
_port: Option<Arc<Port>>,
port: Option<Weak<Port>>,
key: u64,
) -> ZxResult {
// TODO: port
use core::convert::TryFrom;
let rvm_port = port.map(|p| -> Arc<dyn RvmPort> { Arc::new(GuestPort(p)) });
self.inner
.set_trap(TrapKind::try_from(kind)?, addr, size, key)
.set_trap(TrapKind::try_from(kind)?, addr, size, rvm_port, key)
.map_err(From::from)
}
@ -78,7 +82,7 @@ impl GuestPhysMemorySetTrait for GuestPhysMemorySet {
/// Add a contiguous guest physical memory region and create mapping,
/// with the target host physical address `hpaddr` (optional).
fn add_map(
fn map(
&self,
_gpaddr: GuestPhysAddr,
_size: usize,
@ -89,7 +93,7 @@ impl GuestPhysMemorySetTrait for GuestPhysMemorySet {
}
/// Remove a guest physical memory region, destroy the mapping.
fn remove_map(&self, gpaddr: GuestPhysAddr, size: usize) -> RvmResult {
fn unmap(&self, gpaddr: GuestPhysAddr, size: usize) -> RvmResult {
self.vmar.unmap(gpaddr, size).map_err(From::from)
}
@ -119,3 +123,18 @@ impl GuestPhysMemorySetTrait for GuestPhysMemorySet {
self.vmar.table_phys()
}
}
#[derive(Debug)]
struct GuestPort(Weak<Port>);
impl RvmPort for GuestPort {
fn send(&self, packet: RvmExitPacket) -> RvmResult {
let packet: PortPacket = packet.try_into()?;
if let Some(port) = self.0.upgrade() {
port.push(packet);
Ok(())
} else {
Err(RvmError::BadState)
}
}
}

View File

@ -42,18 +42,14 @@ impl From<ZxError> for RvmError {
}
}
pub struct VmmPageTable {
rvm_page_table: ArchRvmPageTable,
}
pub struct VmmPageTable(ArchRvmPageTable);
#[derive(Debug)]
struct VmmPageTableFlags(MMUFlags);
impl VmmPageTable {
pub fn new() -> Self {
Self {
rvm_page_table: ArchRvmPageTable::new(),
}
Self(ArchRvmPageTable::new())
}
}
@ -64,27 +60,27 @@ impl PageTableTrait for VmmPageTable {
hpaddr: HostPhysAddr,
flags: MMUFlags,
) -> Result<(), ()> {
self.rvm_page_table
self.0
.map(gpaddr, hpaddr, VmmPageTableFlags(flags))
.map_err(|_| ())
}
fn unmap(&mut self, gpaddr: GuestPhysAddr) -> Result<(), ()> {
self.rvm_page_table.unmap(gpaddr).map_err(|_| ())
self.0.unmap(gpaddr).map_err(|_| ())
}
fn protect(&mut self, gpaddr: GuestPhysAddr, flags: MMUFlags) -> Result<(), ()> {
self.rvm_page_table
self.0
.protect(gpaddr, VmmPageTableFlags(flags))
.map_err(|_| ())
}
fn query(&mut self, gpaddr: GuestPhysAddr) -> Result<HostPhysAddr, ()> {
self.rvm_page_table.query(gpaddr).map_err(|_| ())
self.0.query(gpaddr).map_err(|_| ())
}
fn table_phys(&self) -> HostPhysAddr {
self.rvm_page_table.table_phys()
self.0.table_phys()
}
}

View File

@ -57,6 +57,15 @@ impl Vcpu {
}
}
impl From<rvm::BellPacket> for PacketGuestBell {
fn from(bell: rvm::BellPacket) -> Self {
Self {
addr: bell.addr,
..Default::default()
}
}
}
impl From<rvm::IoPacket> for PacketGuestIo {
fn from(io: rvm::IoPacket) -> Self {
Self {
@ -88,20 +97,21 @@ impl TryInto<PortPacket> for rvm::RvmExitPacket {
#[allow(unsafe_code)]
fn try_into(self) -> ZxResult<PortPacket> {
use rvm::RvmExitPacketKind;
match self.kind {
RvmExitPacketKind::GuestIo => Ok(PortPacketRepr {
key: self.key,
status: ZxError::OK,
data: PayloadRepr::GuestIo(unsafe { self.inner.io.into() }),
let data = match self.kind {
RvmExitPacketKind::GuestBell => {
PayloadRepr::GuestBell(unsafe { self.inner.bell.into() })
}
.into()),
RvmExitPacketKind::GuestMmio => Ok(PortPacketRepr {
key: self.key,
status: ZxError::OK,
data: PayloadRepr::GuestMem(unsafe { self.inner.mmio.into() }),
RvmExitPacketKind::GuestIo => PayloadRepr::GuestIo(unsafe { self.inner.io.into() }),
RvmExitPacketKind::GuestMmio => {
PayloadRepr::GuestMem(unsafe { self.inner.mmio.into() })
}
.into()),
_ => Err(ZxError::NOT_SUPPORTED),
_ => return Err(ZxError::NOT_SUPPORTED),
};
Ok(PortPacketRepr {
key: self.key,
status: ZxError::OK,
data,
}
.into())
}
}

View File

@ -72,7 +72,7 @@ impl Port {
self.base.signal_set(Signal::READABLE);
}
/// Push an `User` type `packet` into the port.
/// Push a `User` type `packet` into the port.
pub fn push_user(&self, packet: impl Into<PortPacket>) -> ZxResult<()> {
let mut packet = packet.into();
packet.type_ = PacketType::User;

View File

@ -65,7 +65,10 @@ impl Syscall<'_> {
let proc = self.thread.proc();
let guest = proc.get_object_with_rights::<Guest>(handle, Rights::WRITE)?;
let port = if port_handle != INVALID_HANDLE {
Some(proc.get_object_with_rights::<Port>(port_handle, Rights::WRITE)?)
Some(Arc::downgrade(&proc.get_object_with_rights::<Port>(
port_handle,
Rights::WRITE,
)?))
} else {
None
};