krata: reorganize crates

This commit is contained in:
Alex Zenla
2024-03-07 18:12:47 +00:00
parent c0eeab4047
commit 7bc0c95f00
97 changed files with 24 additions and 24 deletions

View File

@ -0,0 +1,34 @@
[package]
name = "xencall"
version.workspace = true
edition = "2021"
resolver = "2"
[dependencies]
libc = { workspace = true }
log = { workspace = true }
nix = { workspace = true, features = ["ioctl"] }
thiserror = { workspace = true }
uuid = { workspace = true }
[lib]
name = "xencall"
[dev-dependencies]
env_logger = { workspace = true }
[[example]]
name = "xencall-domain-info"
path = "examples/domain_info.rs"
[[example]]
name = "xencall-domain-create"
path = "examples/domain_create.rs"
[[example]]
name = "xencall-version-capabilities"
path = "examples/version_capabilities.rs"
[[example]]
name = "xencall-vcpu-context"
path = "examples/vcpu_context.rs"

View File

@ -0,0 +1,12 @@
use xencall::error::Result;
use xencall::sys::CreateDomain;
use xencall::XenCall;
fn main() -> Result<()> {
env_logger::init();
let call = XenCall::open()?;
let domid = call.create_domain(CreateDomain::default())?;
println!("created domain {}", domid);
Ok(())
}

View File

@ -0,0 +1,11 @@
use xencall::error::Result;
use xencall::XenCall;
fn main() -> Result<()> {
env_logger::init();
let call = XenCall::open()?;
let info = call.get_domain_info(1)?;
println!("{:?}", info);
Ok(())
}

View File

@ -0,0 +1,11 @@
use xencall::error::Result;
use xencall::XenCall;
fn main() -> Result<()> {
env_logger::init();
let call = XenCall::open()?;
let context = call.get_vcpu_context(224, 0)?;
println!("{:?}", context);
Ok(())
}

View File

@ -0,0 +1,11 @@
use xencall::error::Result;
use xencall::XenCall;
fn main() -> Result<()> {
env_logger::init();
let call = XenCall::open()?;
let info = call.get_version_capabilities()?;
println!("{:?}", info);
Ok(())
}

View File

@ -0,0 +1,13 @@
use std::io;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("kernel error")]
Kernel(#[from] nix::errno::Errno),
#[error("io issue encountered")]
Io(#[from] io::Error),
#[error("populate physmap failed")]
PopulatePhysmapFailed,
}
pub type Result<T> = std::result::Result<T, Error>;

View File

@ -0,0 +1,624 @@
pub mod error;
pub mod sys;
use crate::error::{Error, Result};
use crate::sys::{
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_CLAIM_PAGES, XEN_MEM_MEMORY_MAP,
XEN_MEM_POPULATE_PHYSMAP,
};
use libc::{c_int, mmap, usleep, MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE};
use log::trace;
use nix::errno::Errno;
use std::ffi::{c_long, c_uint, c_ulong, c_void};
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,
}
impl XenCall {
pub fn open() -> Result<XenCall> {
let file = OpenOptions::new()
.read(true)
.write(true)
.open("/dev/xen/privcmd")?;
Ok(XenCall { handle: file })
}
pub fn mmap(&self, addr: u64, len: u64) -> Option<u64> {
trace!(
"call fd={} mmap addr={:#x} len={}",
self.handle.as_raw_fd(),
addr,
len
);
unsafe {
let ptr = mmap(
addr as *mut c_void,
len as usize,
PROT_READ | PROT_WRITE,
MAP_SHARED,
self.handle.as_raw_fd(),
0,
);
if ptr == MAP_FAILED {
None
} else {
Some(ptr as u64)
}
}
}
pub fn hypercall(&self, op: c_ulong, arg: [c_ulong; 5]) -> Result<c_long> {
trace!(
"call fd={} hypercall op={:#x} arg={:?}",
self.handle.as_raw_fd(),
op,
arg
);
unsafe {
let mut call = Hypercall { op, arg };
let result = sys::hypercall(self.handle.as_raw_fd(), &mut call)?;
Ok(result as c_long)
}
}
pub fn hypercall0(&self, op: c_ulong) -> Result<c_long> {
self.hypercall(op, [0, 0, 0, 0, 0])
}
pub fn hypercall1(&self, op: c_ulong, arg1: c_ulong) -> Result<c_long> {
self.hypercall(op, [arg1, 0, 0, 0, 0])
}
pub fn hypercall2(&self, op: c_ulong, arg1: c_ulong, arg2: c_ulong) -> Result<c_long> {
self.hypercall(op, [arg1, arg2, 0, 0, 0])
}
pub fn hypercall3(
&self,
op: c_ulong,
arg1: c_ulong,
arg2: c_ulong,
arg3: c_ulong,
) -> Result<c_long> {
self.hypercall(op, [arg1, arg2, arg3, 0, 0])
}
pub fn hypercall4(
&self,
op: c_ulong,
arg1: c_ulong,
arg2: c_ulong,
arg3: c_ulong,
arg4: c_ulong,
) -> Result<c_long> {
self.hypercall(op, [arg1, arg2, arg3, arg4, 0])
}
pub fn hypercall5(
&self,
op: c_ulong,
arg1: c_ulong,
arg2: c_ulong,
arg3: c_ulong,
arg4: c_ulong,
arg5: c_ulong,
) -> Result<c_long> {
self.hypercall(op, [arg1, arg2, arg3, arg4, arg5])
}
pub fn multicall(&self, calls: &mut [MultiCallEntry]) -> Result<()> {
trace!(
"call fd={} multicall calls={:?}",
self.handle.as_raw_fd(),
calls
);
self.hypercall2(
HYPERVISOR_MULTICALL,
calls.as_mut_ptr() as c_ulong,
calls.len() as c_ulong,
)?;
Ok(())
}
pub fn map_resource(
&self,
domid: u32,
typ: u32,
id: u32,
idx: u32,
num: u64,
addr: u64,
) -> Result<()> {
let mut resource = MmapResource {
dom: domid as u16,
typ,
id,
idx,
num,
addr,
};
unsafe {
sys::mmap_resource(self.handle.as_raw_fd(), &mut resource)?;
}
Ok(())
}
pub fn mmap_batch(&self, domid: u32, num: u64, addr: u64, mfns: Vec<u64>) -> Result<c_long> {
trace!(
"call fd={} mmap_batch domid={} num={} addr={:#x} mfns={:?}",
self.handle.as_raw_fd(),
domid,
num,
addr,
mfns
);
unsafe {
let mut mfns = mfns.clone();
let mut errors = vec![0i32; mfns.len()];
let mut batch = MmapBatch {
num: num as u32,
domid: domid as u16,
addr,
mfns: mfns.as_mut_ptr(),
errors: errors.as_mut_ptr(),
};
let result = sys::mmapbatch(self.handle.as_raw_fd(), &mut batch);
if let Err(errno) = result {
if errno != Errno::ENOENT {
return Err(errno)?;
}
usleep(100);
let mut i: usize = 0;
let mut paged: usize = 0;
loop {
if errors[i] != libc::ENOENT {
i += 1;
continue;
}
paged += 1;
let mut batch = MmapBatch {
num: 1,
domid: domid as u16,
addr: addr + ((i as u64) << 12),
mfns: mfns.as_mut_ptr().add(i),
errors: errors.as_mut_ptr().add(i),
};
loop {
i += 1;
if i < num as usize {
if errors[i] != libc::ENOENT {
break;
}
batch.num += 1;
}
}
let result = sys::mmapbatch(self.handle.as_raw_fd(), &mut batch);
if let Err(n) = result {
if n != Errno::ENOENT {
return Err(n)?;
}
}
if i < num as usize {
break;
}
let count = result.unwrap();
if count <= 0 {
break;
}
}
return Ok(paged as c_long);
}
Ok(result.unwrap() as c_long)
}
}
pub fn get_version_capabilities(&self) -> Result<XenCapabilitiesInfo> {
trace!(
"call fd={} get_version_capabilities",
self.handle.as_raw_fd()
);
let mut info = XenCapabilitiesInfo {
capabilities: [0; 1024],
};
self.hypercall2(
HYPERVISOR_XEN_VERSION,
XENVER_CAPABILITIES,
addr_of_mut!(info) as c_ulong,
)?;
Ok(info)
}
pub fn evtchn_op(&self, cmd: c_int, arg: u64) -> Result<()> {
self.hypercall2(HYPERVISOR_EVENT_CHANNEL_OP, cmd as c_ulong, arg)?;
Ok(())
}
pub fn evtchn_alloc_unbound(&self, domid: u32, remote_domid: u32) -> Result<u32> {
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)
}
pub fn get_domain_info(&self, domid: u32) -> Result<GetDomainInfo> {
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> {
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<()> {
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<()> {
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<()> {
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<()> {
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<()> {
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> {
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<()> {
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>> {
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<()> {
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<()> {
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>> {
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>> {
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(Error::PopulatePhysmapFailed);
}
if code as usize > extent_starts.len() {
return Err(Error::PopulatePhysmapFailed);
}
let extents = extent_starts[0..code as usize].to_vec();
Ok(extents)
}
pub fn claim_pages(&self, domid: u32, pages: u64) -> Result<()> {
trace!(
"memory fd={} claim_pages domid={} pages={}",
self.handle.as_raw_fd(),
domid,
pages
);
let mut reservation = MemoryReservation {
extent_start: 0,
nr_extents: pages,
extent_order: 0,
mem_flags: 0,
domid: domid as u16,
};
self.hypercall2(
HYPERVISOR_MEMORY_OP,
XEN_MEM_CLAIM_PAGES as c_ulong,
addr_of_mut!(reservation) as c_ulong,
)?;
Ok(())
}
pub fn mmuext(&self, domid: u32, cmd: c_uint, arg1: u64, arg2: u64) -> Result<()> {
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(|_| ())
}
}

View File

@ -0,0 +1,507 @@
/// Handwritten hypercall bindings.
use nix::ioctl_readwrite_bad;
use std::ffi::{c_char, c_int, c_uint, c_ulong};
use uuid::Uuid;
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct Hypercall {
pub op: c_ulong,
pub arg: [c_ulong; 5],
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
pub struct MmapEntry {
pub va: u64,
pub mfn: u64,
pub npages: u64,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
pub struct MmapResource {
pub dom: u16,
pub typ: u32,
pub id: u32,
pub idx: u32,
pub num: u64,
pub addr: u64,
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct MmapBatch {
pub num: u32,
pub domid: u16,
pub addr: u64,
pub mfns: *mut u64,
pub errors: *mut c_int,
}
#[repr(C)]
#[derive(Clone, Debug)]
pub struct Mmap {
pub num: c_int,
pub dom: u16,
pub entry: *mut MmapEntry,
}
const IOCTL_PRIVCMD_HYPERCALL: u64 = 0x305000;
const IOCTL_PRIVCMD_MMAP: u64 = 0x105002;
const IOCTL_PRIVCMD_MMAPBATCH_V2: u64 = 0x205004;
const IOCTL_PRIVCMD_MMAP_RESOURCE: u64 = 0x205007;
ioctl_readwrite_bad!(hypercall, IOCTL_PRIVCMD_HYPERCALL, Hypercall);
ioctl_readwrite_bad!(mmap, IOCTL_PRIVCMD_MMAP, Mmap);
ioctl_readwrite_bad!(mmapbatch, IOCTL_PRIVCMD_MMAPBATCH_V2, MmapBatch);
ioctl_readwrite_bad!(mmap_resource, IOCTL_PRIVCMD_MMAP_RESOURCE, MmapResource);
pub const HYPERVISOR_SET_TRAP_TABLE: c_ulong = 0;
pub const HYPERVISOR_MMU_UPDATE: c_ulong = 1;
pub const HYPERVISOR_SET_GDT: c_ulong = 2;
pub const HYPERVISOR_STACK_SWITCH: c_ulong = 3;
pub const HYPERVISOR_SET_CALLBACKS: c_ulong = 4;
pub const HYPERVISOR_FPU_TASKSWITCH: c_ulong = 5;
pub const HYPERVISOR_SCHED_OP_COMPAT: c_ulong = 6;
pub const HYPERVISOR_PLATFORM_OP: c_ulong = 7;
pub const HYPERVISOR_SET_DEBUGREG: c_ulong = 8;
pub const HYPERVISOR_GET_DEBUGREG: c_ulong = 9;
pub const HYPERVISOR_UPDATE_DESCRIPTOR: c_ulong = 10;
pub const HYPERVISOR_MEMORY_OP: c_ulong = 12;
pub const HYPERVISOR_MULTICALL: c_ulong = 13;
pub const HYPERVISOR_UPDATE_VA_MAPPING: c_ulong = 14;
pub const HYPERVISOR_SET_TIMER_OP: c_ulong = 15;
pub const HYPERVISOR_EVENT_CHANNEL_OP_COMPAT: c_ulong = 16;
pub const HYPERVISOR_XEN_VERSION: c_ulong = 17;
pub const HYPERVISOR_CONSOLE_IO: c_ulong = 18;
pub const HYPERVISOR_PHYSDEV_OP_COMPAT: c_ulong = 19;
pub const HYPERVISOR_GRANT_TABLE_OP: c_ulong = 20;
pub const HYPERVISOR_VM_ASSIST: c_ulong = 21;
pub const HYPERVISOR_UPDATE_VA_MAPPING_OTHERDOMAIN: c_ulong = 22;
pub const HYPERVISOR_IRET: c_ulong = 23;
pub const HYPERVISOR_VCPU_OP: c_ulong = 24;
pub const HYPERVISOR_SET_SEGMENT_BASE: c_ulong = 25;
pub const HYPERVISOR_MMUEXT_OP: c_ulong = 26;
pub const HYPERVISOR_XSM_OP: c_ulong = 27;
pub const HYPERVISOR_NMI_OP: c_ulong = 28;
pub const HYPERVISOR_SCHED_OP: c_ulong = 29;
pub const HYPERVISOR_CALLBACK_OP: c_ulong = 30;
pub const HYPERVISOR_XENOPROF_OP: c_ulong = 31;
pub const HYPERVISOR_EVENT_CHANNEL_OP: c_ulong = 32;
pub const HYPERVISOR_PHYSDEV_OP: c_ulong = 33;
pub const HYPERVISOR_HVM_OP: c_ulong = 34;
pub const HYPERVISOR_SYSCTL: c_ulong = 35;
pub const HYPERVISOR_DOMCTL: c_ulong = 36;
pub const HYPERVISOR_KEXEC_OP: c_ulong = 37;
pub const HYPERVISOR_TMEM_OP: c_ulong = 38;
pub const HYPERVISOR_XC_RESERVED_OP: c_ulong = 39;
pub const HYPERVISOR_XENPMU_OP: c_ulong = 40;
pub const HYPERVISOR_DM_OP: c_ulong = 41;
pub const XEN_DOMCTL_CDF_HVM_GUEST: u32 = 1 << 0;
pub const XEN_DOMCTL_CDF_HAP: u32 = 1 << 1;
pub const XEN_DOMCTL_CDF_S3_INTEGRITY: u32 = 1 << 2;
pub const XEN_DOMCTL_CDF_OOS_OFF: u32 = 1 << 3;
pub const XEN_DOMCTL_CDF_XS_DOMAIN: u32 = 1 << 4;
pub const XEN_X86_EMU_LAPIC: u32 = 1 << 0;
pub const XEN_X86_EMU_HPET: u32 = 1 << 1;
pub const XEN_X86_EMU_PM: u32 = 1 << 2;
pub const XEN_X86_EMU_RTC: u32 = 1 << 3;
pub const XEN_X86_EMU_IOAPIC: u32 = 1 << 4;
pub const XEN_X86_EMU_PIC: u32 = 1 << 5;
pub const XEN_X86_EMU_VGA: u32 = 1 << 6;
pub const XEN_X86_EMU_IOMMU: u32 = 1 << 7;
pub const XEN_X86_EMU_PIT: u32 = 1 << 8;
pub const XEN_X86_EMU_USE_PIRQ: u32 = 1 << 9;
pub const XEN_X86_EMU_ALL: u32 = XEN_X86_EMU_LAPIC
| XEN_X86_EMU_HPET
| XEN_X86_EMU_PM
| XEN_X86_EMU_RTC
| XEN_X86_EMU_IOAPIC
| XEN_X86_EMU_PIC
| XEN_X86_EMU_VGA
| XEN_X86_EMU_IOMMU
| XEN_X86_EMU_PIT
| XEN_X86_EMU_USE_PIRQ;
pub const XEN_DOMCTL_CREATEDOMAIN: u32 = 1;
pub const XEN_DOMCTL_DESTROYDOMAIN: u32 = 2;
pub const XEN_DOMCTL_PAUSEDOMAIN: u32 = 3;
pub const XEN_DOMCTL_UNPAUSEDOMAIN: u32 = 4;
pub const XEN_DOMCTL_GETDOMAININFO: u32 = 5;
pub const XEN_DOMCTL_GETMEMLIST: u32 = 6;
pub const XEN_DOMCTL_SETVCPUAFFINITY: u32 = 9;
pub const XEN_DOMCTL_SHADOW_OP: u32 = 10;
pub const XEN_DOMCTL_MAX_MEM: u32 = 11;
pub const XEN_DOMCTL_SETVCPUCONTEXT: u32 = 12;
pub const XEN_DOMCTL_GETVCPUCONTEXT: u32 = 13;
pub const XEN_DOMCTL_GETVCPUINFO: u32 = 14;
pub const XEN_DOMCTL_MAX_VCPUS: u32 = 15;
pub const XEN_DOMCTL_SCHEDULER_OP: u32 = 16;
pub const XEN_DOMCTL_SETDOMAINHANDLE: u32 = 17;
pub const XEN_DOMCTL_SETDEBUGGING: u32 = 18;
pub const XEN_DOMCTL_IRQ_PERMISSION: u32 = 19;
pub const XEN_DOMCTL_IOMEM_PERMISSION: u32 = 20;
pub const XEN_DOMCTL_IOPORT_PERMISSION: u32 = 21;
pub const XEN_DOMCTL_HYPERCALL_INIT: u32 = 22;
pub const XEN_DOMCTL_SETTIMEOFFSET: u32 = 24;
pub const XEN_DOMCTL_GETVCPUAFFINITY: u32 = 25;
pub const XEN_DOMCTL_RESUMEDOMAIN: u32 = 27;
pub const XEN_DOMCTL_SENDTRIGGER: u32 = 28;
pub const XEN_DOMCTL_SUBSCRIBE: u32 = 29;
pub const XEN_DOMCTL_GETHVMCONTEXT: u32 = 33;
pub const XEN_DOMCTL_SETHVMCONTEXT: u32 = 34;
pub const XEN_DOMCTL_SET_ADDRESS_SIZE: u32 = 35;
pub const XEN_DOMCTL_GET_ADDRESS_SIZE: u32 = 36;
pub const XEN_DOMCTL_ASSIGN_DEVICE: u32 = 37;
pub const XEN_DOMCTL_BIND_PT_IRQ: u32 = 38;
pub const XEN_DOMCTL_MEMORY_MAPPING: u32 = 39;
pub const XEN_DOMCTL_IOPORT_MAPPING: u32 = 40;
pub const XEN_DOMCTL_PIN_MEM_CACHEATTR: u32 = 41;
pub const XEN_DOMCTL_SET_EXT_VCPUCONTEXT: u32 = 42;
pub const XEN_DOMCTL_GET_EXT_VCPUCONTEXT: u32 = 43;
pub const XEN_DOMCTL_TEST_ASSIGN_DEVICE: u32 = 45;
pub const XEN_DOMCTL_SET_TARGET: u32 = 46;
pub const XEN_DOMCTL_DEASSIGN_DEVICE: u32 = 47;
pub const XEN_DOMCTL_UNBIND_PT_IRQ: u32 = 48;
pub const XEN_DOMCTL_SET_CPUID: u32 = 49;
pub const XEN_DOMCTL_GET_DEVICE_GROUP: u32 = 50;
pub const XEN_DOMCTL_SET_MACHINE_ADDRESS_SIZE: u32 = 51;
pub const XEN_DOMCTL_GET_MACHINE_ADDRESS_SIZE: u32 = 52;
pub const XEN_DOMCTL_SUPPRESS_SPURIOUS_PAGE_FAULTS: u32 = 53;
pub const XEN_DOMCTL_DEBUG_OP: u32 = 54;
pub const XEN_DOMCTL_GETHVMCONTEXT_PARTIAL: u32 = 55;
pub const XEN_DOMCTL_VM_EVENT_OP: u32 = 56;
pub const XEN_DOMCTL_MEM_SHARING_OP: u32 = 57;
pub const XEN_DOMCTL_DISABLE_MIGRATE: u32 = 58;
pub const XEN_DOMCTL_GETTSCINFO: u32 = 59;
pub const XEN_DOMCTL_SETTSCINFO: u32 = 60;
pub const XEN_DOMCTL_GETPAGEFRAMEINFO3: u32 = 61;
pub const XEN_DOMCTL_SETVCPUEXTSTATE: u32 = 62;
pub const XEN_DOMCTL_GETVCPUEXTSTATE: u32 = 63;
pub const XEN_DOMCTL_SET_ACCESS_REQUIRED: u32 = 64;
pub const XEN_DOMCTL_AUDIT_P2M: u32 = 65;
pub const XEN_DOMCTL_SET_VIRQ_HANDLER: u32 = 66;
pub const XEN_DOMCTL_SET_BROKEN_PAGE_P2M: u32 = 67;
pub const XEN_DOMCTL_SETNODEAFFINITY: u32 = 68;
pub const XEN_DOMCTL_GETNODEAFFINITY: u32 = 69;
pub const XEN_DOMCTL_SET_MAX_EVTCHN: u32 = 70;
pub const XEN_DOMCTL_CACHEFLUSH: u32 = 71;
pub const XEN_DOMCTL_GET_VCPU_MSRS: u32 = 72;
pub const XEN_DOMCTL_SET_VCPU_MSRS: u32 = 73;
pub const XEN_DOMCTL_SETVNUMAINFO: u32 = 74;
pub const XEN_DOMCTL_PSR_CMT_OP: u32 = 75;
pub const XEN_DOMCTL_MONITOR_OP: u32 = 77;
pub const XEN_DOMCTL_PSR_CAT_OP: u32 = 78;
pub const XEN_DOMCTL_SOFT_RESET: u32 = 79;
pub const XEN_DOMCTL_SET_GNTTAB_LIMITS: u32 = 80;
pub const XEN_DOMCTL_VUART_OP: u32 = 81;
pub const XEN_DOMCTL_GDBSX_GUESTMEMIO: u32 = 1000;
pub const XEN_DOMCTL_GDBSX_PAUSEVCPU: u32 = 1001;
pub const XEN_DOMCTL_GDBSX_UNPAUSEVCPU: u32 = 1002;
pub const XEN_DOMCTL_GDBSX_DOMSTATUS: u32 = 1003;
#[repr(C)]
#[derive(Copy, Clone)]
pub struct DomCtl {
pub cmd: u32,
pub interface_version: u32,
pub domid: u32,
pub value: DomCtlValue,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct DomCtlVcpuContext {
pub vcpu: u32,
pub ctx: u64,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct AddressSize {
pub size: u32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union DomCtlValue {
pub create_domain: CreateDomain,
pub get_domain_info: GetDomainInfo,
pub max_mem: MaxMem,
pub max_cpus: MaxVcpus,
pub hypercall_init: HypercallInit,
pub vcpu_context: DomCtlVcpuContext,
pub address_size: AddressSize,
pub get_page_frame_info: GetPageFrameInfo3,
pub pad: [u8; 128],
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct CreateDomain {
pub ssidref: u32,
pub handle: [u8; 16],
pub flags: u32,
pub iommu_opts: u32,
pub max_vcpus: u32,
pub max_evtchn_port: u32,
pub max_grant_frames: i32,
pub max_maptrack_frames: i32,
pub grant_opts: u32,
pub vmtrace_size: u32,
pub cpupool_id: u32,
pub arch_domain_config: ArchDomainConfig,
}
impl Default for CreateDomain {
fn default() -> Self {
CreateDomain {
ssidref: SECINITSID_DOMU,
handle: Uuid::new_v4().into_bytes(),
flags: 0,
iommu_opts: 0,
max_vcpus: 1,
max_evtchn_port: 1023,
max_grant_frames: -1,
max_maptrack_frames: -1,
grant_opts: 2,
vmtrace_size: 0,
cpupool_id: 0,
arch_domain_config: ArchDomainConfig {
emulation_flags: 0,
misc_flags: 0,
},
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct GetDomainInfo {
pub domid: u16,
pub pad1: u16,
pub flags: u32,
pub total_pages: u64,
pub max_pages: u64,
pub outstanding_pages: u64,
pub shr_pages: u64,
pub paged_pages: u64,
pub shared_info_frame: u64,
pub cpu_time: u64,
pub number_online_vcpus: u32,
pub max_vcpu_id: u32,
pub ssidref: u32,
pub handle: [u8; 16],
pub cpupool: u32,
pub gpaddr_bits: u8,
pub pad2: [u8; 7],
pub arch: ArchDomainConfig,
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct GetPageFrameInfo3 {
pub num: u64,
pub array: c_ulong,
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct ArchDomainConfig {
pub emulation_flags: u32,
pub misc_flags: u32,
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct MaxMem {
pub max_memkb: u64,
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct MaxVcpus {
pub max_vcpus: u32,
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct HypercallInit {
pub gmfn: u64,
}
pub const XEN_DOMCTL_INTERFACE_VERSION: u32 = 0x00000015;
pub const SECINITSID_DOMU: u32 = 12;
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct XenCapabilitiesInfo {
pub capabilities: [c_char; 1024],
}
pub const XENVER_CAPABILITIES: u64 = 3;
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct MemoryReservation {
pub extent_start: c_ulong,
pub nr_extents: c_ulong,
pub extent_order: c_uint,
pub mem_flags: c_uint,
pub domid: u16,
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct MultiCallEntry {
pub op: c_ulong,
pub result: c_ulong,
pub args: [c_ulong; 6],
}
pub const XEN_MEM_POPULATE_PHYSMAP: u32 = 6;
pub const XEN_MEM_MEMORY_MAP: u32 = 9;
pub const XEN_MEM_CLAIM_PAGES: u32 = 24;
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct MemoryMap {
pub count: c_uint,
pub buffer: c_ulong,
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct VcpuGuestContextFpuCtx {
pub x: [c_char; 512],
}
impl Default for VcpuGuestContextFpuCtx {
fn default() -> Self {
VcpuGuestContextFpuCtx { x: [0; 512] }
}
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
pub struct CpuUserRegs {
pub r15: u64,
pub r14: u64,
pub r13: u64,
pub r12: u64,
pub rbp: u64,
pub rbx: u64,
pub r11: u64,
pub r10: u64,
pub r9: u64,
pub r8: u64,
pub rax: u64,
pub rcx: u64,
pub rdx: u64,
pub rsi: u64,
pub rdi: u64,
pub error_code: u32,
pub entry_vector: u32,
pub rip: u64,
pub cs: u16,
_pad0: [u16; 1],
pub saved_upcall_mask: u8,
_pad1: [u8; 3],
pub rflags: u64,
pub rsp: u64,
pub ss: u16,
_pad2: [u16; 3],
pub es: u16,
_pad3: [u16; 3],
pub ds: u16,
_pad4: [u16; 3],
pub fs: u16,
_pad5: [u16; 3],
pub gs: u16,
_pad6: [u16; 3],
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Default)]
pub struct TrapInfo {
pub vector: u8,
pub flags: u8,
pub cs: u16,
pub address: u64,
}
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct VcpuGuestContext {
pub fpu_ctx: VcpuGuestContextFpuCtx,
pub flags: u64,
pub user_regs: CpuUserRegs,
pub trap_ctx: [TrapInfo; 256],
pub ldt_base: u64,
pub ldt_ents: u64,
pub gdt_frames: [u64; 16],
pub gdt_ents: u64,
pub kernel_ss: u64,
pub kernel_sp: u64,
pub ctrlreg: [u64; 8],
pub debugreg: [u64; 8],
pub event_callback_eip: u64,
pub failsafe_callback_eip: u64,
pub syscall_callback_eip: u64,
pub vm_assist: u64,
pub fs_base: u64,
pub gs_base_kernel: u64,
pub gs_base_user: u64,
}
impl Default for VcpuGuestContext {
fn default() -> Self {
VcpuGuestContext {
fpu_ctx: Default::default(),
flags: 0,
user_regs: Default::default(),
trap_ctx: [TrapInfo::default(); 256],
ldt_base: 0,
ldt_ents: 0,
gdt_frames: [0; 16],
gdt_ents: 0,
kernel_ss: 0,
kernel_sp: 0,
ctrlreg: [0; 8],
debugreg: [0; 8],
event_callback_eip: 0,
failsafe_callback_eip: 0,
syscall_callback_eip: 0,
vm_assist: 0,
fs_base: 0,
gs_base_kernel: 0,
gs_base_user: 0,
}
}
}
pub union VcpuGuestContextAny {
pub value: VcpuGuestContext,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct MmuExtOp {
pub cmd: c_uint,
pub arg1: c_ulong,
pub arg2: c_ulong,
}
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,
}