diff --git a/xencall/src/domctl.rs b/xencall/src/domctl.rs index 4bc63b4..79bd60d 100644 --- a/xencall/src/domctl.rs +++ b/xencall/src/domctl.rs @@ -5,7 +5,7 @@ use crate::sys::{ XEN_DOMCTL_GETDOMAININFO, XEN_DOMCTL_GETPAGEFRAMEINFO3, XEN_DOMCTL_GETVCPUCONTEXT, XEN_DOMCTL_HYPERCALL_INIT, XEN_DOMCTL_INTERFACE_VERSION, XEN_DOMCTL_MAX_MEM, XEN_DOMCTL_MAX_VCPUS, XEN_DOMCTL_PAUSEDOMAIN, XEN_DOMCTL_SETVCPUCONTEXT, - XEN_DOMCTL_SET_ADDRESS_SIZE, + XEN_DOMCTL_SET_ADDRESS_SIZE, XEN_DOMCTL_UNPAUSEDOMAIN, }; use crate::{XenCall, XenCallError}; use log::trace; @@ -98,6 +98,23 @@ impl DomainControl<'_> { Ok(()) } + pub fn unpause_domain(&self, domid: u32) -> Result<(), XenCallError> { + trace!( + "domctl fd={} unpause_domain domid={:?}", + self.call.handle.as_raw_fd(), + domid, + ); + let mut domctl = DomCtl { + cmd: XEN_DOMCTL_UNPAUSEDOMAIN, + interface_version: XEN_DOMCTL_INTERFACE_VERSION, + domid, + value: DomCtlValue { pad: [0; 128] }, + }; + self.call + .hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?; + Ok(()) + } + pub fn set_max_mem(&self, domid: u32, memkb: u64) -> Result<(), XenCallError> { trace!( "domctl fd={} set_max_mem domid={} memkb={}", diff --git a/xencall/src/lib.rs b/xencall/src/lib.rs index cf41e5e..eaa549b 100644 --- a/xencall/src/lib.rs +++ b/xencall/src/lib.rs @@ -3,10 +3,10 @@ pub mod memory; pub mod sys; use crate::sys::{ - Hypercall, MmapBatch, MmapResource, MultiCallEntry, XenCapabilitiesInfo, HYPERVISOR_MULTICALL, - HYPERVISOR_XEN_VERSION, XENVER_CAPABILITIES, + EvtChnAllocUnbound, Hypercall, MmapBatch, MmapResource, MultiCallEntry, XenCapabilitiesInfo, + HYPERVISOR_EVENT_CHANNEL_OP, HYPERVISOR_MULTICALL, HYPERVISOR_XEN_VERSION, XENVER_CAPABILITIES, }; -use libc::{mmap, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE}; +use libc::{c_int, mmap, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE}; use log::trace; use nix::errno::Errno; use std::error::Error; @@ -236,4 +236,19 @@ impl XenCall { )?; Ok(info) } + + pub fn evtchn_op(&self, cmd: c_int, arg: u64) -> Result<(), XenCallError> { + self.hypercall2(HYPERVISOR_EVENT_CHANNEL_OP, cmd as c_ulong, arg)?; + Ok(()) + } + + pub fn evtchn_alloc_unbound(&self, domid: u32, remote_domid: u32) -> Result { + let mut alloc_unbound = EvtChnAllocUnbound { + dom: domid as u16, + remote_dom: remote_domid as u16, + port: 0, + }; + self.evtchn_op(6, addr_of_mut!(alloc_unbound) as c_ulong)?; + Ok(alloc_unbound.port) + } } diff --git a/xencall/src/sys.rs b/xencall/src/sys.rs index bce09a7..2b61a83 100644 --- a/xencall/src/sys.rs +++ b/xencall/src/sys.rs @@ -496,3 +496,11 @@ pub struct MmuExtOp { } pub const MMUEXT_PIN_L4_TABLE: u32 = 3; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct EvtChnAllocUnbound { + pub dom: u16, + pub remote_dom: u16, + pub port: u32, +} diff --git a/xenclient/Cargo.toml b/xenclient/Cargo.toml index 182cf0c..9308ca6 100644 --- a/xenclient/Cargo.toml +++ b/xenclient/Cargo.toml @@ -19,6 +19,9 @@ path = "../xencall" [dependencies.xenstore] path = "../xenstore" +[dependencies.xenevtchn] +path = "../xenevtchn" + [dependencies.uuid] version = "1.6.1" features = ["v4"] diff --git a/xenclient/examples/boot.rs b/xenclient/examples/boot.rs index 7cd1c59..2aad3c9 100644 --- a/xenclient/examples/boot.rs +++ b/xenclient/examples/boot.rs @@ -7,6 +7,7 @@ use xencall::XenCall; use xenclient::boot::BootSetup; use xenclient::elfloader::ElfImageLoader; use xenclient::XenClientError; +use xenevtchn::EventChannel; fn main() -> Result<(), XenClientError> { env_logger::init(); @@ -48,6 +49,10 @@ fn boot( let mut boot = BootSetup::new(call, domctl, &memctl, domid); let initrd = read(initrd_path)?; let mut state = boot.initialize(&image_loader, initrd.as_slice(), 1, 512)?; - boot.boot(&mut state, "debug")?; + boot.boot(&mut state, "debug elevator=noop")?; + domctl.unpause_domain(domid)?; + + let _evtchn = EventChannel::open()?; + Ok(()) } diff --git a/xenclient/src/boot.rs b/xenclient/src/boot.rs index d6c3987..1c72954 100644 --- a/xenclient/src/boot.rs +++ b/xenclient/src/boot.rs @@ -82,6 +82,8 @@ pub struct BootState { pub image_info: BootImageInfo, pub shared_info_frame: u64, pub initrd_segment: DomainSegment, + pub store_evtchn: u32, + pub console_evtchn: u32, } impl BootSetup<'_> { @@ -282,7 +284,8 @@ impl BootSetup<'_> { } let initrd_segment = initrd_segment.unwrap(); - + let store_evtchn = self.domctl.call.evtchn_alloc_unbound(self.domid, 0)?; + let console_evtchn = self.domctl.call.evtchn_alloc_unbound(self.domid, 0)?; let state = BootState { kernel_segment, start_info_segment, @@ -294,6 +297,8 @@ impl BootSetup<'_> { page_table, image_info, initrd_segment, + store_evtchn, + console_evtchn, shared_info_frame: 0, }; debug!("BootSetup initialize state={:?}", state); @@ -491,10 +496,10 @@ impl BootSetup<'_> { (*info).first_p2m_pfn = state.p2m_segment.pfn; (*info).nr_p2m_frames = state.p2m_segment.pages; (*info).flags = 0; - (*info).store_evtchn = 0; + (*info).store_evtchn = state.store_evtchn; (*info).store_mfn = self.phys.p2m[state.xenstore_segment.pfn as usize]; (*info).console.mfn = self.phys.p2m[state.console_segment.pfn as usize]; - (*info).console.evtchn = 0; + (*info).console.evtchn = state.console_evtchn; (*info).mod_start = state.initrd_segment.vstart; (*info).mod_len = state.initrd_segment.size; for (i, c) in cmdline.chars().enumerate() { diff --git a/xenclient/src/lib.rs b/xenclient/src/lib.rs index 8aa261e..d617faa 100644 --- a/xenclient/src/lib.rs +++ b/xenclient/src/lib.rs @@ -12,6 +12,7 @@ use std::string::FromUtf8Error; use xencall::domctl::DomainControl; use xencall::sys::CreateDomain; use xencall::{XenCall, XenCallError}; +use xenevtchn::EventChannelError; use xenstore::bus::XsdBusError; use xenstore::client::{XsdClient, XsdInterface}; @@ -69,6 +70,12 @@ impl From for XenClientError { } } +impl From for XenClientError { + fn from(value: EventChannelError) -> Self { + XenClientError::new(value.to_string().as_str()) + } +} + impl XenClient { pub fn open() -> Result { let store = XsdClient::open()?;