mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-03 13:11:31 +00:00
oh my god, we have a console
This commit is contained in:
@ -1,4 +1,3 @@
|
||||
use xencall::domctl::DomainControl;
|
||||
use xencall::sys::CreateDomain;
|
||||
use xencall::{XenCall, XenCallError};
|
||||
|
||||
@ -6,8 +5,7 @@ fn main() -> Result<(), XenCallError> {
|
||||
env_logger::init();
|
||||
|
||||
let call = XenCall::open()?;
|
||||
let domctl: DomainControl = DomainControl::new(&call);
|
||||
let domid = domctl.create_domain(CreateDomain::default())?;
|
||||
let domid = call.create_domain(CreateDomain::default())?;
|
||||
println!("created domain {}", domid);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,12 +1,10 @@
|
||||
use xencall::domctl::DomainControl;
|
||||
use xencall::{XenCall, XenCallError};
|
||||
|
||||
fn main() -> Result<(), XenCallError> {
|
||||
env_logger::init();
|
||||
|
||||
let call = XenCall::open()?;
|
||||
let domctl: DomainControl = DomainControl::new(&call);
|
||||
let info = domctl.get_domain_info(1)?;
|
||||
let info = call.get_domain_info(1)?;
|
||||
println!("{:?}", info);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,12 +1,10 @@
|
||||
use xencall::domctl::DomainControl;
|
||||
use xencall::{XenCall, XenCallError};
|
||||
|
||||
fn main() -> Result<(), XenCallError> {
|
||||
env_logger::init();
|
||||
|
||||
let call = XenCall::open()?;
|
||||
let domctl: DomainControl = DomainControl::new(&call);
|
||||
let context = domctl.get_vcpu_context(224, 0)?;
|
||||
let context = call.get_vcpu_context(224, 0)?;
|
||||
println!("{:?}", context);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,301 +0,0 @@
|
||||
use crate::sys::{
|
||||
AddressSize, ArchDomainConfig, CreateDomain, DomCtl, DomCtlValue, DomCtlVcpuContext,
|
||||
GetDomainInfo, GetPageFrameInfo3, HypercallInit, MaxMem, MaxVcpus, VcpuGuestContext,
|
||||
VcpuGuestContextAny, HYPERVISOR_DOMCTL, XEN_DOMCTL_CREATEDOMAIN, XEN_DOMCTL_DESTROYDOMAIN,
|
||||
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_UNPAUSEDOMAIN,
|
||||
};
|
||||
use crate::{XenCall, XenCallError};
|
||||
use log::trace;
|
||||
use std::ffi::c_ulong;
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::ptr::addr_of_mut;
|
||||
use std::slice;
|
||||
|
||||
pub struct DomainControl<'a> {
|
||||
pub call: &'a XenCall,
|
||||
}
|
||||
|
||||
impl DomainControl<'_> {
|
||||
pub fn new(call: &XenCall) -> DomainControl {
|
||||
DomainControl { call }
|
||||
}
|
||||
|
||||
pub fn get_domain_info(&self, domid: u32) -> Result<GetDomainInfo, XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} get_domain_info domid={}",
|
||||
self.call.handle.as_raw_fd(),
|
||||
domid
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_GETDOMAININFO,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
get_domain_info: GetDomainInfo {
|
||||
domid: 0,
|
||||
pad1: 0,
|
||||
flags: 0,
|
||||
total_pages: 0,
|
||||
max_pages: 0,
|
||||
outstanding_pages: 0,
|
||||
shr_pages: 0,
|
||||
paged_pages: 0,
|
||||
shared_info_frame: 0,
|
||||
cpu_time: 0,
|
||||
number_online_vcpus: 0,
|
||||
max_vcpu_id: 0,
|
||||
ssidref: 0,
|
||||
handle: [0; 16],
|
||||
cpupool: 0,
|
||||
gpaddr_bits: 0,
|
||||
pad2: [0; 7],
|
||||
arch: ArchDomainConfig {
|
||||
emulation_flags: 0,
|
||||
misc_flags: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
self.call
|
||||
.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(unsafe { domctl.value.get_domain_info })
|
||||
}
|
||||
|
||||
pub fn create_domain(&self, create_domain: CreateDomain) -> Result<u32, XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} create_domain create_domain={:?}",
|
||||
self.call.handle.as_raw_fd(),
|
||||
create_domain
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_CREATEDOMAIN,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid: 0,
|
||||
value: DomCtlValue { create_domain },
|
||||
};
|
||||
self.call
|
||||
.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(domctl.domid)
|
||||
}
|
||||
|
||||
pub fn pause_domain(&self, domid: u32) -> Result<(), XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} pause_domain domid={:?}",
|
||||
self.call.handle.as_raw_fd(),
|
||||
domid,
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_PAUSEDOMAIN,
|
||||
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 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={}",
|
||||
self.call.handle.as_raw_fd(),
|
||||
domid,
|
||||
memkb
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_MAX_MEM,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
max_mem: MaxMem { max_memkb: memkb },
|
||||
},
|
||||
};
|
||||
self.call
|
||||
.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_max_vcpus(&self, domid: u32, max_vcpus: u32) -> Result<(), XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} set_max_vcpus domid={} max_vcpus={}",
|
||||
self.call.handle.as_raw_fd(),
|
||||
domid,
|
||||
max_vcpus
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_MAX_VCPUS,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
max_cpus: MaxVcpus { max_vcpus },
|
||||
},
|
||||
};
|
||||
self.call
|
||||
.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_address_size(&self, domid: u32, size: u32) -> Result<(), XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} set_address_size domid={} size={}",
|
||||
self.call.handle.as_raw_fd(),
|
||||
domid,
|
||||
size,
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_SET_ADDRESS_SIZE,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
address_size: AddressSize { size },
|
||||
},
|
||||
};
|
||||
self.call
|
||||
.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_vcpu_context(
|
||||
&self,
|
||||
domid: u32,
|
||||
vcpu: u32,
|
||||
) -> Result<VcpuGuestContext, XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} get_vcpu_context domid={}",
|
||||
self.call.handle.as_raw_fd(),
|
||||
domid,
|
||||
);
|
||||
let mut wrapper = VcpuGuestContextAny {
|
||||
value: VcpuGuestContext::default(),
|
||||
};
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_GETVCPUCONTEXT,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
vcpu_context: DomCtlVcpuContext {
|
||||
vcpu,
|
||||
ctx: addr_of_mut!(wrapper) as c_ulong,
|
||||
},
|
||||
},
|
||||
};
|
||||
self.call
|
||||
.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(unsafe { wrapper.value })
|
||||
}
|
||||
|
||||
pub fn set_vcpu_context(
|
||||
&self,
|
||||
domid: u32,
|
||||
vcpu: u32,
|
||||
context: &VcpuGuestContext,
|
||||
) -> Result<(), XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} set_vcpu_context domid={} context={:?}",
|
||||
self.call.handle.as_raw_fd(),
|
||||
domid,
|
||||
context,
|
||||
);
|
||||
|
||||
let mut value = VcpuGuestContextAny { value: *context };
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_SETVCPUCONTEXT,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
vcpu_context: DomCtlVcpuContext {
|
||||
vcpu,
|
||||
ctx: addr_of_mut!(value) as c_ulong,
|
||||
},
|
||||
},
|
||||
};
|
||||
self.call
|
||||
.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_page_frame_info(
|
||||
&self,
|
||||
domid: u32,
|
||||
frames: &[u64],
|
||||
) -> Result<Vec<u64>, XenCallError> {
|
||||
let mut buffer: Vec<u64> = frames.to_vec();
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_GETPAGEFRAMEINFO3,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
get_page_frame_info: GetPageFrameInfo3 {
|
||||
num: buffer.len() as u64,
|
||||
array: buffer.as_mut_ptr() as c_ulong,
|
||||
},
|
||||
},
|
||||
};
|
||||
self.call
|
||||
.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
let slice = unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
domctl.value.get_page_frame_info.array as *mut u64,
|
||||
domctl.value.get_page_frame_info.num as usize,
|
||||
)
|
||||
};
|
||||
Ok(slice.to_vec())
|
||||
}
|
||||
|
||||
pub fn hypercall_init(&self, domid: u32, gmfn: u64) -> Result<(), XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} hypercall_init domid={} gmfn={}",
|
||||
self.call.handle.as_raw_fd(),
|
||||
domid,
|
||||
gmfn
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_HYPERCALL_INIT,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
hypercall_init: HypercallInit { gmfn },
|
||||
},
|
||||
};
|
||||
self.call
|
||||
.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn destroy_domain(&self, domid: u32) -> Result<(), XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} destroy_domain domid={}",
|
||||
self.call.handle.as_raw_fd(),
|
||||
domid
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_DESTROYDOMAIN,
|
||||
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(())
|
||||
}
|
||||
}
|
@ -1,20 +1,28 @@
|
||||
pub mod domctl;
|
||||
pub mod memory;
|
||||
pub mod sys;
|
||||
|
||||
use crate::sys::{
|
||||
EvtChnAllocUnbound, Hypercall, MmapBatch, MmapResource, MultiCallEntry, XenCapabilitiesInfo,
|
||||
HYPERVISOR_EVENT_CHANNEL_OP, HYPERVISOR_MULTICALL, HYPERVISOR_XEN_VERSION, XENVER_CAPABILITIES,
|
||||
AddressSize, ArchDomainConfig, CreateDomain, DomCtl, DomCtlValue, DomCtlVcpuContext,
|
||||
EvtChnAllocUnbound, GetDomainInfo, GetPageFrameInfo3, Hypercall, HypercallInit, MaxMem,
|
||||
MaxVcpus, MemoryMap, MemoryReservation, MmapBatch, MmapResource, MmuExtOp, MultiCallEntry,
|
||||
VcpuGuestContext, VcpuGuestContextAny, XenCapabilitiesInfo, HYPERVISOR_DOMCTL,
|
||||
HYPERVISOR_EVENT_CHANNEL_OP, HYPERVISOR_MEMORY_OP, HYPERVISOR_MMUEXT_OP, HYPERVISOR_MULTICALL,
|
||||
HYPERVISOR_XEN_VERSION, XENVER_CAPABILITIES, XEN_DOMCTL_CREATEDOMAIN, XEN_DOMCTL_DESTROYDOMAIN,
|
||||
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_UNPAUSEDOMAIN, XEN_MEM_MEMORY_MAP,
|
||||
XEN_MEM_POPULATE_PHYSMAP,
|
||||
};
|
||||
use libc::{c_int, mmap, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE};
|
||||
use log::trace;
|
||||
use nix::errno::Errno;
|
||||
use std::error::Error;
|
||||
use std::ffi::{c_long, c_ulong, c_void};
|
||||
use std::ffi::{c_long, c_uint, c_ulong, c_void};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::ptr::addr_of_mut;
|
||||
use std::slice;
|
||||
|
||||
pub struct XenCall {
|
||||
pub handle: File,
|
||||
@ -251,4 +259,353 @@ impl XenCall {
|
||||
self.evtchn_op(6, addr_of_mut!(alloc_unbound) as c_ulong)?;
|
||||
Ok(alloc_unbound.port)
|
||||
}
|
||||
|
||||
pub fn get_domain_info(&self, domid: u32) -> Result<GetDomainInfo, XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} get_domain_info domid={}",
|
||||
self.handle.as_raw_fd(),
|
||||
domid
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_GETDOMAININFO,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
get_domain_info: GetDomainInfo {
|
||||
domid: 0,
|
||||
pad1: 0,
|
||||
flags: 0,
|
||||
total_pages: 0,
|
||||
max_pages: 0,
|
||||
outstanding_pages: 0,
|
||||
shr_pages: 0,
|
||||
paged_pages: 0,
|
||||
shared_info_frame: 0,
|
||||
cpu_time: 0,
|
||||
number_online_vcpus: 0,
|
||||
max_vcpu_id: 0,
|
||||
ssidref: 0,
|
||||
handle: [0; 16],
|
||||
cpupool: 0,
|
||||
gpaddr_bits: 0,
|
||||
pad2: [0; 7],
|
||||
arch: ArchDomainConfig {
|
||||
emulation_flags: 0,
|
||||
misc_flags: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
self.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(unsafe { domctl.value.get_domain_info })
|
||||
}
|
||||
|
||||
pub fn create_domain(&self, create_domain: CreateDomain) -> Result<u32, XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} create_domain create_domain={:?}",
|
||||
self.handle.as_raw_fd(),
|
||||
create_domain
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_CREATEDOMAIN,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid: 0,
|
||||
value: DomCtlValue { create_domain },
|
||||
};
|
||||
self.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(domctl.domid)
|
||||
}
|
||||
|
||||
pub fn pause_domain(&self, domid: u32) -> Result<(), XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} pause_domain domid={:?}",
|
||||
self.handle.as_raw_fd(),
|
||||
domid,
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_PAUSEDOMAIN,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue { pad: [0; 128] },
|
||||
};
|
||||
self.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unpause_domain(&self, domid: u32) -> Result<(), XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} unpause_domain domid={:?}",
|
||||
self.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.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={}",
|
||||
self.handle.as_raw_fd(),
|
||||
domid,
|
||||
memkb
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_MAX_MEM,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
max_mem: MaxMem { max_memkb: memkb },
|
||||
},
|
||||
};
|
||||
self.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_max_vcpus(&self, domid: u32, max_vcpus: u32) -> Result<(), XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} set_max_vcpus domid={} max_vcpus={}",
|
||||
self.handle.as_raw_fd(),
|
||||
domid,
|
||||
max_vcpus
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_MAX_VCPUS,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
max_cpus: MaxVcpus { max_vcpus },
|
||||
},
|
||||
};
|
||||
self.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_address_size(&self, domid: u32, size: u32) -> Result<(), XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} set_address_size domid={} size={}",
|
||||
self.handle.as_raw_fd(),
|
||||
domid,
|
||||
size,
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_SET_ADDRESS_SIZE,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
address_size: AddressSize { size },
|
||||
},
|
||||
};
|
||||
self.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_vcpu_context(
|
||||
&self,
|
||||
domid: u32,
|
||||
vcpu: u32,
|
||||
) -> Result<VcpuGuestContext, XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} get_vcpu_context domid={}",
|
||||
self.handle.as_raw_fd(),
|
||||
domid,
|
||||
);
|
||||
let mut wrapper = VcpuGuestContextAny {
|
||||
value: VcpuGuestContext::default(),
|
||||
};
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_GETVCPUCONTEXT,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
vcpu_context: DomCtlVcpuContext {
|
||||
vcpu,
|
||||
ctx: addr_of_mut!(wrapper) as c_ulong,
|
||||
},
|
||||
},
|
||||
};
|
||||
self.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(unsafe { wrapper.value })
|
||||
}
|
||||
|
||||
pub fn set_vcpu_context(
|
||||
&self,
|
||||
domid: u32,
|
||||
vcpu: u32,
|
||||
context: &VcpuGuestContext,
|
||||
) -> Result<(), XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} set_vcpu_context domid={} context={:?}",
|
||||
self.handle.as_raw_fd(),
|
||||
domid,
|
||||
context,
|
||||
);
|
||||
|
||||
let mut value = VcpuGuestContextAny { value: *context };
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_SETVCPUCONTEXT,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
vcpu_context: DomCtlVcpuContext {
|
||||
vcpu,
|
||||
ctx: addr_of_mut!(value) as c_ulong,
|
||||
},
|
||||
},
|
||||
};
|
||||
self.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_page_frame_info(
|
||||
&self,
|
||||
domid: u32,
|
||||
frames: &[u64],
|
||||
) -> Result<Vec<u64>, XenCallError> {
|
||||
let mut buffer: Vec<u64> = frames.to_vec();
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_GETPAGEFRAMEINFO3,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
get_page_frame_info: GetPageFrameInfo3 {
|
||||
num: buffer.len() as u64,
|
||||
array: buffer.as_mut_ptr() as c_ulong,
|
||||
},
|
||||
},
|
||||
};
|
||||
self.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
let slice = unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
domctl.value.get_page_frame_info.array as *mut u64,
|
||||
domctl.value.get_page_frame_info.num as usize,
|
||||
)
|
||||
};
|
||||
Ok(slice.to_vec())
|
||||
}
|
||||
|
||||
pub fn hypercall_init(&self, domid: u32, gmfn: u64) -> Result<(), XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} hypercall_init domid={} gmfn={}",
|
||||
self.handle.as_raw_fd(),
|
||||
domid,
|
||||
gmfn
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_HYPERCALL_INIT,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue {
|
||||
hypercall_init: HypercallInit { gmfn },
|
||||
},
|
||||
};
|
||||
self.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn destroy_domain(&self, domid: u32) -> Result<(), XenCallError> {
|
||||
trace!(
|
||||
"domctl fd={} destroy_domain domid={}",
|
||||
self.handle.as_raw_fd(),
|
||||
domid
|
||||
);
|
||||
let mut domctl = DomCtl {
|
||||
cmd: XEN_DOMCTL_DESTROYDOMAIN,
|
||||
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||
domid,
|
||||
value: DomCtlValue { pad: [0; 128] },
|
||||
};
|
||||
self.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_memory_map(&self, size_of_entry: usize) -> Result<Vec<u8>, XenCallError> {
|
||||
let mut memory_map = MemoryMap {
|
||||
count: 0,
|
||||
buffer: 0,
|
||||
};
|
||||
self.hypercall2(
|
||||
HYPERVISOR_MEMORY_OP,
|
||||
XEN_MEM_MEMORY_MAP as c_ulong,
|
||||
addr_of_mut!(memory_map) as c_ulong,
|
||||
)?;
|
||||
let mut buffer = vec![0u8; memory_map.count as usize * size_of_entry];
|
||||
memory_map.buffer = buffer.as_mut_ptr() as c_ulong;
|
||||
self.hypercall2(
|
||||
HYPERVISOR_MEMORY_OP,
|
||||
XEN_MEM_MEMORY_MAP as c_ulong,
|
||||
addr_of_mut!(memory_map) as c_ulong,
|
||||
)?;
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
pub fn populate_physmap(
|
||||
&self,
|
||||
domid: u32,
|
||||
nr_extents: u64,
|
||||
extent_order: u32,
|
||||
mem_flags: u32,
|
||||
extent_starts: &[u64],
|
||||
) -> Result<Vec<u64>, XenCallError> {
|
||||
trace!("memory fd={} populate_physmap domid={} nr_extents={} extent_order={} mem_flags={} extent_starts={:?}", self.handle.as_raw_fd(), domid, nr_extents, extent_order, mem_flags, extent_starts);
|
||||
let mut extent_starts = extent_starts.to_vec();
|
||||
let ptr = extent_starts.as_mut_ptr();
|
||||
|
||||
let mut reservation = MemoryReservation {
|
||||
extent_start: ptr as c_ulong,
|
||||
nr_extents,
|
||||
extent_order,
|
||||
mem_flags,
|
||||
domid: domid as u16,
|
||||
};
|
||||
|
||||
let calls = &mut [MultiCallEntry {
|
||||
op: HYPERVISOR_MEMORY_OP,
|
||||
result: 0,
|
||||
args: [
|
||||
XEN_MEM_POPULATE_PHYSMAP as c_ulong,
|
||||
addr_of_mut!(reservation) as c_ulong,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
}];
|
||||
self.multicall(calls)?;
|
||||
let code = calls[0].result;
|
||||
if code > !0xfff {
|
||||
return Err(XenCallError::new(
|
||||
format!("failed to populate physmap: {:#x}", code).as_str(),
|
||||
));
|
||||
}
|
||||
if code as usize > extent_starts.len() {
|
||||
return Err(XenCallError::new("failed to populate physmap"));
|
||||
}
|
||||
let extents = extent_starts[0..code as usize].to_vec();
|
||||
Ok(extents)
|
||||
}
|
||||
|
||||
pub fn mmuext(
|
||||
&self,
|
||||
domid: u32,
|
||||
cmd: c_uint,
|
||||
arg1: u64,
|
||||
arg2: u64,
|
||||
) -> Result<(), XenCallError> {
|
||||
let mut ops = MmuExtOp { cmd, arg1, arg2 };
|
||||
|
||||
self.hypercall4(
|
||||
HYPERVISOR_MMUEXT_OP,
|
||||
addr_of_mut!(ops) as c_ulong,
|
||||
1,
|
||||
0,
|
||||
domid as c_ulong,
|
||||
)
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
@ -1,106 +0,0 @@
|
||||
use crate::sys::{
|
||||
MemoryMap, MemoryReservation, MmuExtOp, MultiCallEntry, HYPERVISOR_MEMORY_OP,
|
||||
HYPERVISOR_MMUEXT_OP, XEN_MEM_MEMORY_MAP, XEN_MEM_POPULATE_PHYSMAP,
|
||||
};
|
||||
use crate::{XenCall, XenCallError};
|
||||
|
||||
use log::trace;
|
||||
use std::ffi::{c_uint, c_ulong};
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::ptr::addr_of_mut;
|
||||
|
||||
pub struct MemoryControl<'a> {
|
||||
call: &'a XenCall,
|
||||
}
|
||||
|
||||
impl MemoryControl<'_> {
|
||||
pub fn new(call: &XenCall) -> MemoryControl {
|
||||
MemoryControl { call }
|
||||
}
|
||||
|
||||
pub fn get_memory_map(&self, size_of_entry: usize) -> Result<Vec<u8>, XenCallError> {
|
||||
let mut memory_map = MemoryMap {
|
||||
count: 0,
|
||||
buffer: 0,
|
||||
};
|
||||
self.call.hypercall2(
|
||||
HYPERVISOR_MEMORY_OP,
|
||||
XEN_MEM_MEMORY_MAP as c_ulong,
|
||||
addr_of_mut!(memory_map) as c_ulong,
|
||||
)?;
|
||||
let mut buffer = vec![0u8; memory_map.count as usize * size_of_entry];
|
||||
memory_map.buffer = buffer.as_mut_ptr() as c_ulong;
|
||||
self.call.hypercall2(
|
||||
HYPERVISOR_MEMORY_OP,
|
||||
XEN_MEM_MEMORY_MAP as c_ulong,
|
||||
addr_of_mut!(memory_map) as c_ulong,
|
||||
)?;
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
pub fn populate_physmap(
|
||||
&self,
|
||||
domid: u32,
|
||||
nr_extents: u64,
|
||||
extent_order: u32,
|
||||
mem_flags: u32,
|
||||
extent_starts: &[u64],
|
||||
) -> Result<Vec<u64>, XenCallError> {
|
||||
trace!("memory fd={} populate_physmap domid={} nr_extents={} extent_order={} mem_flags={} extent_starts={:?}", self.call.handle.as_raw_fd(), domid, nr_extents, extent_order, mem_flags, extent_starts);
|
||||
let mut extent_starts = extent_starts.to_vec();
|
||||
let ptr = extent_starts.as_mut_ptr();
|
||||
|
||||
let mut reservation = MemoryReservation {
|
||||
extent_start: ptr as c_ulong,
|
||||
nr_extents,
|
||||
extent_order,
|
||||
mem_flags,
|
||||
domid: domid as u16,
|
||||
};
|
||||
|
||||
let calls = &mut [MultiCallEntry {
|
||||
op: HYPERVISOR_MEMORY_OP,
|
||||
result: 0,
|
||||
args: [
|
||||
XEN_MEM_POPULATE_PHYSMAP as c_ulong,
|
||||
addr_of_mut!(reservation) as c_ulong,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
}];
|
||||
self.call.multicall(calls)?;
|
||||
let code = calls[0].result;
|
||||
if code > !0xfff {
|
||||
return Err(XenCallError::new(
|
||||
format!("failed to populate physmap: {:#x}", code).as_str(),
|
||||
));
|
||||
}
|
||||
if code as usize > extent_starts.len() {
|
||||
return Err(XenCallError::new("failed to populate physmap"));
|
||||
}
|
||||
let extents = extent_starts[0..code as usize].to_vec();
|
||||
Ok(extents)
|
||||
}
|
||||
|
||||
pub fn mmuext(
|
||||
&self,
|
||||
domid: u32,
|
||||
cmd: c_uint,
|
||||
arg1: u64,
|
||||
arg2: u64,
|
||||
) -> Result<(), XenCallError> {
|
||||
let mut ops = MmuExtOp { cmd, arg1, arg2 };
|
||||
|
||||
self.call
|
||||
.hypercall4(
|
||||
HYPERVISOR_MMUEXT_OP,
|
||||
addr_of_mut!(ops) as c_ulong,
|
||||
1,
|
||||
0,
|
||||
domid as c_ulong,
|
||||
)
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user