forked from rcore-os/zCore
hypervisor: support set bell type (asynchronous) traps
This commit is contained in:
parent
0a47a003d9
commit
08640b373f
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue