mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-02 12:50:54 +00:00
implement support for creating domains
This commit is contained in:
parent
4b31d95e43
commit
35f3346858
@ -3,6 +3,6 @@ members = [
|
|||||||
"xenstore",
|
"xenstore",
|
||||||
"xenevtchn",
|
"xenevtchn",
|
||||||
"xencall",
|
"xencall",
|
||||||
"xencl"
|
"xenclient"
|
||||||
]
|
]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
@ -7,10 +7,18 @@ resolver = "2"
|
|||||||
[lib]
|
[lib]
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
|
[dependencies.uuid]
|
||||||
|
version = "1.6.1"
|
||||||
|
features = ["v4"]
|
||||||
|
|
||||||
[dependencies.nix]
|
[dependencies.nix]
|
||||||
version = "0.27.1"
|
version = "0.27.1"
|
||||||
features = ["ioctl"]
|
features = ["ioctl"]
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "xencall-simple"
|
name = "xencall-domain-info"
|
||||||
path = "examples/simple.rs"
|
path = "examples/domain_info.rs"
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "xencall-domain-create"
|
||||||
|
path = "examples/domain_create.rs"
|
||||||
|
11
xencall/examples/domain_create.rs
Normal file
11
xencall/examples/domain_create.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use xencall::domctl::DomainControl;
|
||||||
|
use xencall::sys::CreateDomain;
|
||||||
|
use xencall::{XenCall, XenCallError};
|
||||||
|
|
||||||
|
fn main() -> Result<(), XenCallError> {
|
||||||
|
let mut call = XenCall::open()?;
|
||||||
|
let mut domctl: DomainControl = DomainControl::new(&mut call);
|
||||||
|
let info = domctl.create_domain(CreateDomain::default())?;
|
||||||
|
println!("created domain {}", info.domid);
|
||||||
|
Ok(())
|
||||||
|
}
|
10
xencall/examples/domain_info.rs
Normal file
10
xencall/examples/domain_info.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
use xencall::domctl::DomainControl;
|
||||||
|
use xencall::{XenCall, XenCallError};
|
||||||
|
|
||||||
|
fn main() -> Result<(), XenCallError> {
|
||||||
|
let mut call = XenCall::open()?;
|
||||||
|
let mut domctl: DomainControl = DomainControl::new(&mut call);
|
||||||
|
let info = domctl.get_domain_info(1)?;
|
||||||
|
println!("{:?}", info);
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -1,11 +0,0 @@
|
|||||||
use std::ffi::c_ulong;
|
|
||||||
use std::ptr::addr_of;
|
|
||||||
use xencall::{XenCall, XenCallError};
|
|
||||||
|
|
||||||
fn main() -> Result<(), XenCallError> {
|
|
||||||
let mut call = XenCall::open()?;
|
|
||||||
let message = "Hello World";
|
|
||||||
let bytes = message.as_bytes();
|
|
||||||
call.hypercall3(18, 0, bytes.len() as c_ulong, addr_of!(bytes) as c_ulong)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
73
xencall/src/domctl.rs
Normal file
73
xencall/src/domctl.rs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
use crate::sys::{
|
||||||
|
ArchDomainConfig, CreateDomain, DomCtl, DomCtlValue, GetDomainInfo, HYPERVISOR_DOMCTL,
|
||||||
|
XEN_DOMCTL_CREATEDOMAIN, XEN_DOMCTL_GETDOMAININFO, XEN_DOMCTL_INTERFACE_VERSION,
|
||||||
|
};
|
||||||
|
use crate::{XenCall, XenCallError};
|
||||||
|
use std::ffi::c_ulong;
|
||||||
|
use std::ptr::addr_of;
|
||||||
|
|
||||||
|
pub struct DomainControl<'a> {
|
||||||
|
call: &'a mut XenCall,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CreatedDomain {
|
||||||
|
pub domid: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DomainControl<'_> {
|
||||||
|
pub fn new(call: &mut XenCall) -> DomainControl {
|
||||||
|
DomainControl { call }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_domain_info(&mut self, domid: u32) -> Result<GetDomainInfo, XenCallError> {
|
||||||
|
let domctl = DomCtl {
|
||||||
|
cmd: XEN_DOMCTL_GETDOMAININFO,
|
||||||
|
interface_version: XEN_DOMCTL_INTERFACE_VERSION,
|
||||||
|
domid,
|
||||||
|
value: DomCtlValue {
|
||||||
|
get_domain_info: GetDomainInfo {
|
||||||
|
domid,
|
||||||
|
pad1: 0,
|
||||||
|
flags: 0,
|
||||||
|
total_pages: 0,
|
||||||
|
max_pages: 0,
|
||||||
|
outstanding_pages: 0,
|
||||||
|
shr_pages: 0,
|
||||||
|
paged_pages: 0,
|
||||||
|
shared_info_frame: 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!(domctl) as c_ulong)?;
|
||||||
|
Ok(unsafe { domctl.value.get_domain_info })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_domain(
|
||||||
|
&mut self,
|
||||||
|
create_domain: CreateDomain,
|
||||||
|
) -> Result<CreatedDomain, XenCallError> {
|
||||||
|
let 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!(domctl) as c_ulong)?;
|
||||||
|
Ok(CreatedDomain {
|
||||||
|
domid: domctl.domid,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
mod sys;
|
pub mod domctl;
|
||||||
|
pub mod sys;
|
||||||
|
|
||||||
use crate::sys::Hypercall;
|
use crate::sys::Hypercall;
|
||||||
use nix::errno::Errno;
|
use nix::errno::Errno;
|
||||||
@ -60,9 +61,9 @@ impl XenCall {
|
|||||||
|
|
||||||
pub fn hypercall(&mut self, op: c_ulong, arg: [c_ulong; 5]) -> Result<c_long, XenCallError> {
|
pub fn hypercall(&mut self, op: c_ulong, arg: [c_ulong; 5]) -> Result<c_long, XenCallError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut call = Hypercall { op, arg, retval: 0 };
|
let mut call = Hypercall { op, arg };
|
||||||
sys::hypercall(self.handle.as_raw_fd(), &mut call)?;
|
let result = sys::hypercall(self.handle.as_raw_fd(), &mut call)?;
|
||||||
Ok(call.retval)
|
Ok(result as c_long)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,249 @@
|
|||||||
use nix::{ioctl_readwrite_bad, request_code_none};
|
/// Handwritten hypercall bindings.
|
||||||
use std::ffi::{c_long, c_ulong};
|
use nix::ioctl_readwrite_bad;
|
||||||
|
use std::ffi::c_ulong;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct Hypercall {
|
pub struct Hypercall {
|
||||||
pub op: c_ulong,
|
pub op: c_ulong,
|
||||||
pub arg: [c_ulong; 5],
|
pub arg: [c_ulong; 5],
|
||||||
pub retval: c_long,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ioctl_readwrite_bad!(hypercall, request_code_none!(b'E', 0), Hypercall);
|
const IOCTL_PRIVCMD_HYPERCALL: u64 = 0x305000;
|
||||||
|
|
||||||
|
ioctl_readwrite_bad!(hypercall, IOCTL_PRIVCMD_HYPERCALL, Hypercall);
|
||||||
|
|
||||||
|
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 union DomCtlValue {
|
||||||
|
pub create_domain: CreateDomain,
|
||||||
|
pub get_domain_info: GetDomainInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct GetDomainInfo {
|
||||||
|
pub domid: u32,
|
||||||
|
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 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 ArchDomainConfig {
|
||||||
|
pub emulation_flags: u32,
|
||||||
|
pub misc_flags: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const XEN_DOMCTL_INTERFACE_VERSION: u32 = 0x00000015;
|
||||||
|
pub const SECINITSID_DOMU: u32 = 13;
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use xencl::{XenClient, XenClientError};
|
|
||||||
|
|
||||||
fn main() -> Result<(), XenClientError> {
|
|
||||||
let mut client = XenClient::open()?;
|
|
||||||
let entries: HashMap<String, String> = HashMap::new();
|
|
||||||
client.create(2, entries)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use std::error::Error;
|
|
||||||
use std::fmt::{Display, Formatter};
|
|
||||||
use xenstore::bus::XsdBusError;
|
|
||||||
use xenstore::client::{XsdClient, XsdInterface};
|
|
||||||
|
|
||||||
pub struct XenClient {
|
|
||||||
store: XsdClient,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct XenClientError {
|
|
||||||
message: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl XenClientError {
|
|
||||||
pub fn new(msg: &str) -> XenClientError {
|
|
||||||
XenClientError {
|
|
||||||
message: msg.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for XenClientError {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "{}", self.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error for XenClientError {
|
|
||||||
fn description(&self) -> &str {
|
|
||||||
&self.message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<std::io::Error> for XenClientError {
|
|
||||||
fn from(value: std::io::Error) -> Self {
|
|
||||||
XenClientError::new(value.to_string().as_str())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<XsdBusError> for XenClientError {
|
|
||||||
fn from(value: XsdBusError) -> Self {
|
|
||||||
XenClientError::new(value.to_string().as_str())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl XenClient {
|
|
||||||
pub fn open() -> Result<XenClient, XenClientError> {
|
|
||||||
let store = XsdClient::open()?;
|
|
||||||
Ok(XenClient { store })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create(
|
|
||||||
&mut self,
|
|
||||||
domid: u32,
|
|
||||||
entries: HashMap<String, String>,
|
|
||||||
) -> Result<(), XenClientError> {
|
|
||||||
let domain = self.store.get_domain_path(domid)?;
|
|
||||||
let mut tx = self.store.transaction()?;
|
|
||||||
for (key, value) in entries {
|
|
||||||
let path = format!("{}/{}", domain, key);
|
|
||||||
tx.write(path.as_str(), value.into_bytes())?;
|
|
||||||
}
|
|
||||||
tx.commit()?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +1,22 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "xencl"
|
name = "xenclient"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
|
[dependencies.xencall]
|
||||||
|
path = "../xencall"
|
||||||
|
|
||||||
[dependencies.xenstore]
|
[dependencies.xenstore]
|
||||||
path = "../xenstore"
|
path = "../xenstore"
|
||||||
|
|
||||||
|
[dependencies.uuid]
|
||||||
|
version = "1.6.1"
|
||||||
|
features = ["v4"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "xencl-simple"
|
name = "xenclient-simple"
|
||||||
path = "examples/simple.rs"
|
path = "examples/simple.rs"
|
16
xenclient/examples/simple.rs
Normal file
16
xenclient/examples/simple.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
use xenclient::create::{DomainConfig, PvDomainConfig};
|
||||||
|
use xenclient::{XenClient, XenClientError};
|
||||||
|
|
||||||
|
fn main() -> Result<(), XenClientError> {
|
||||||
|
let mut client = XenClient::open()?;
|
||||||
|
let mut config = DomainConfig::new();
|
||||||
|
config.configure_cpus(1);
|
||||||
|
config.configure_memory(524288, 524288, 0);
|
||||||
|
config.configure_pv(PvDomainConfig::new(
|
||||||
|
"/boot/vmlinuz-6.1.0-17-amd64".to_string(),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
));
|
||||||
|
client.create(2, config)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
88
xenclient/src/create.rs
Normal file
88
xenclient/src/create.rs
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub struct DomainConfig {
|
||||||
|
vm_entries: HashMap<String, String>,
|
||||||
|
domain_entries: HashMap<String, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PvDomainConfig {
|
||||||
|
kernel: String,
|
||||||
|
ramdisk: Option<String>,
|
||||||
|
cmdline: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DomainConfig {
|
||||||
|
pub fn new() -> DomainConfig {
|
||||||
|
DomainConfig {
|
||||||
|
vm_entries: HashMap::new(),
|
||||||
|
domain_entries: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn put_vm(&mut self, key: &str, value: String) {
|
||||||
|
self.vm_entries.insert(key.to_string(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn put_vm_str(&mut self, key: &str, value: &str) {
|
||||||
|
self.put_vm(key, value.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn put_domain(&mut self, key: &str, value: String) {
|
||||||
|
self.vm_entries.insert(key.to_string(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn put_domain_str(&mut self, key: &str, value: &str) {
|
||||||
|
self.put_domain(key, value.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn configure_memory(&mut self, maxkb: u32, targetkb: u32, videokb: u32) {
|
||||||
|
self.put_domain("memory/static-max", maxkb.to_string());
|
||||||
|
self.put_domain("memory/target", targetkb.to_string());
|
||||||
|
self.put_domain("memory/videoram", videokb.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn configure_cpus(&mut self, maxvcpus: u32) {
|
||||||
|
for i in 0..maxvcpus {
|
||||||
|
println!("{}", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn configure_pv(&mut self, pv: PvDomainConfig) {
|
||||||
|
self.put_vm_str("image/ostype", "linux");
|
||||||
|
self.put_vm("image/kernel", pv.kernel);
|
||||||
|
|
||||||
|
match pv.ramdisk {
|
||||||
|
None => {}
|
||||||
|
Some(ramdisk) => self.put_vm("image/ramdisk", ramdisk),
|
||||||
|
}
|
||||||
|
|
||||||
|
match pv.cmdline {
|
||||||
|
None => {}
|
||||||
|
Some(cmdline) => self.put_vm("image/cmdline", cmdline),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clone_vm_entries(&self) -> HashMap<String, String> {
|
||||||
|
self.vm_entries.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clone_domain_entries(&self) -> HashMap<String, String> {
|
||||||
|
self.domain_entries.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DomainConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
DomainConfig::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PvDomainConfig {
|
||||||
|
pub fn new(kernel: String, ramdisk: Option<String>, cmdline: Option<String>) -> PvDomainConfig {
|
||||||
|
PvDomainConfig {
|
||||||
|
kernel,
|
||||||
|
ramdisk,
|
||||||
|
cmdline,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
99
xenclient/src/lib.rs
Normal file
99
xenclient/src/lib.rs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
pub mod create;
|
||||||
|
|
||||||
|
use crate::create::DomainConfig;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::string::FromUtf8Error;
|
||||||
|
use xencall::domctl::DomainControl;
|
||||||
|
use xencall::sys::CreateDomain;
|
||||||
|
use xencall::{XenCall, XenCallError};
|
||||||
|
use xenstore::bus::XsdBusError;
|
||||||
|
use xenstore::client::{XsdClient, XsdInterface};
|
||||||
|
|
||||||
|
pub struct XenClient {
|
||||||
|
store: XsdClient,
|
||||||
|
call: XenCall,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct XenClientError {
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XenClientError {
|
||||||
|
pub fn new(msg: &str) -> XenClientError {
|
||||||
|
XenClientError {
|
||||||
|
message: msg.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for XenClientError {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for XenClientError {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
&self.message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for XenClientError {
|
||||||
|
fn from(value: std::io::Error) -> Self {
|
||||||
|
XenClientError::new(value.to_string().as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<XsdBusError> for XenClientError {
|
||||||
|
fn from(value: XsdBusError) -> Self {
|
||||||
|
XenClientError::new(value.to_string().as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<XenCallError> for XenClientError {
|
||||||
|
fn from(value: XenCallError) -> Self {
|
||||||
|
XenClientError::new(value.to_string().as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<FromUtf8Error> for XenClientError {
|
||||||
|
fn from(value: FromUtf8Error) -> Self {
|
||||||
|
XenClientError::new(value.to_string().as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XenClient {
|
||||||
|
pub fn open() -> Result<XenClient, XenClientError> {
|
||||||
|
let store = XsdClient::open()?;
|
||||||
|
let call = XenCall::open()?;
|
||||||
|
Ok(XenClient { store, call })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create(&mut self, config: DomainConfig) -> Result<(), XenClientError> {
|
||||||
|
let mut domctl = DomainControl::new(&mut self.call);
|
||||||
|
let created = domctl.create_domain(CreateDomain::default())?;
|
||||||
|
let domain = self.store.get_domain_path(created.domid)?;
|
||||||
|
let vm = self.store.read_string(format!("{}/vm", domain).as_str())?;
|
||||||
|
|
||||||
|
let mut tx = self.store.transaction()?;
|
||||||
|
|
||||||
|
for (key, value) in config.clone_domain_entries() {
|
||||||
|
let path = format!("{}/{}", domain, key);
|
||||||
|
tx.write(path.as_str(), value.into_bytes())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let domid_path = format!("{}/domid", domain);
|
||||||
|
tx.write(domid_path.as_str(), created.domid.to_string().into_bytes())?;
|
||||||
|
|
||||||
|
for (key, value) in config.clone_domain_entries() {
|
||||||
|
let path = format!("{}/{}", vm, key);
|
||||||
|
tx.write(path.as_str(), value.into_bytes())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.commit()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -160,10 +160,24 @@ impl XsdSocket {
|
|||||||
typ: u32,
|
typ: u32,
|
||||||
string: &str,
|
string: &str,
|
||||||
) -> Result<XsdResponse, XsdBusError> {
|
) -> Result<XsdResponse, XsdBusError> {
|
||||||
let path = CString::new(string)?;
|
let text = CString::new(string)?;
|
||||||
let buf = path.as_bytes_with_nul();
|
let buf = text.as_bytes_with_nul();
|
||||||
self.send(tx, typ, buf)
|
self.send(tx, typ, buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn send_multiple(
|
||||||
|
&mut self,
|
||||||
|
tx: u32,
|
||||||
|
typ: u32,
|
||||||
|
array: &[&str],
|
||||||
|
) -> Result<XsdResponse, XsdBusError> {
|
||||||
|
let mut buf: Vec<u8> = Vec::new();
|
||||||
|
for item in array {
|
||||||
|
buf.extend_from_slice(item.as_bytes());
|
||||||
|
buf.push(0);
|
||||||
|
}
|
||||||
|
self.send(tx, typ, buf.as_slice())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for XsdSocket {
|
impl Drop for XsdSocket {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::bus::{XsdBusError, XsdSocket};
|
use crate::bus::{XsdBusError, XsdSocket};
|
||||||
use crate::sys::{
|
use crate::sys::{
|
||||||
XSD_DIRECTORY, XSD_GET_DOMAIN_PATH, XSD_MKDIR, XSD_READ, XSD_RM, XSD_TRANSACTION_END,
|
XSD_DIRECTORY, XSD_GET_DOMAIN_PATH, XSD_INTRODUCE, XSD_MKDIR, XSD_READ, XSD_RM,
|
||||||
XSD_TRANSACTION_START, XSD_WRITE,
|
XSD_TRANSACTION_END, XSD_TRANSACTION_START, XSD_WRITE,
|
||||||
};
|
};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
|
||||||
@ -12,7 +12,9 @@ pub struct XsdClient {
|
|||||||
pub trait XsdInterface {
|
pub trait XsdInterface {
|
||||||
fn list(&mut self, path: &str) -> Result<Vec<String>, XsdBusError>;
|
fn list(&mut self, path: &str) -> Result<Vec<String>, XsdBusError>;
|
||||||
fn read(&mut self, path: &str) -> Result<Vec<u8>, XsdBusError>;
|
fn read(&mut self, path: &str) -> Result<Vec<u8>, XsdBusError>;
|
||||||
|
fn read_string(&mut self, path: &str) -> Result<String, XsdBusError>;
|
||||||
fn write(&mut self, path: &str, data: Vec<u8>) -> Result<bool, XsdBusError>;
|
fn write(&mut self, path: &str, data: Vec<u8>) -> Result<bool, XsdBusError>;
|
||||||
|
fn write_string(&mut self, path: &str, data: String) -> Result<bool, XsdBusError>;
|
||||||
fn mkdir(&mut self, path: &str) -> Result<bool, XsdBusError>;
|
fn mkdir(&mut self, path: &str) -> Result<bool, XsdBusError>;
|
||||||
fn rm(&mut self, path: &str) -> Result<bool, XsdBusError>;
|
fn rm(&mut self, path: &str) -> Result<bool, XsdBusError>;
|
||||||
}
|
}
|
||||||
@ -62,6 +64,24 @@ impl XsdClient {
|
|||||||
.send_single(0, XSD_GET_DOMAIN_PATH, domid.to_string().as_str())?;
|
.send_single(0, XSD_GET_DOMAIN_PATH, domid.to_string().as_str())?;
|
||||||
response.parse_string()
|
response.parse_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn introduce_domain(
|
||||||
|
&mut self,
|
||||||
|
domid: u32,
|
||||||
|
mfn: u32,
|
||||||
|
eventchn: u32,
|
||||||
|
) -> Result<String, XsdBusError> {
|
||||||
|
let response = self.socket.send_multiple(
|
||||||
|
0,
|
||||||
|
XSD_INTRODUCE,
|
||||||
|
&[
|
||||||
|
domid.to_string().as_str(),
|
||||||
|
mfn.to_string().as_str(),
|
||||||
|
eventchn.to_string().as_str(),
|
||||||
|
],
|
||||||
|
)?;
|
||||||
|
response.parse_string()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct XsdTransaction<'a> {
|
pub struct XsdTransaction<'a> {
|
||||||
@ -78,10 +98,18 @@ impl XsdInterface for XsdClient {
|
|||||||
self.read(0, path)
|
self.read(0, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_string(&mut self, path: &str) -> Result<String, XsdBusError> {
|
||||||
|
Ok(String::from_utf8(self.read(0, path)?)?)
|
||||||
|
}
|
||||||
|
|
||||||
fn write(&mut self, path: &str, data: Vec<u8>) -> Result<bool, XsdBusError> {
|
fn write(&mut self, path: &str, data: Vec<u8>) -> Result<bool, XsdBusError> {
|
||||||
self.write(0, path, data)
|
self.write(0, path, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_string(&mut self, path: &str, data: String) -> Result<bool, XsdBusError> {
|
||||||
|
self.write(0, path, data.into_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
fn mkdir(&mut self, path: &str) -> Result<bool, XsdBusError> {
|
fn mkdir(&mut self, path: &str) -> Result<bool, XsdBusError> {
|
||||||
self.mkdir(0, path)
|
self.mkdir(0, path)
|
||||||
}
|
}
|
||||||
@ -100,10 +128,18 @@ impl XsdInterface for XsdTransaction<'_> {
|
|||||||
self.client.read(self.tx, path)
|
self.client.read(self.tx, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_string(&mut self, path: &str) -> Result<String, XsdBusError> {
|
||||||
|
Ok(String::from_utf8(self.client.read(self.tx, path)?)?)
|
||||||
|
}
|
||||||
|
|
||||||
fn write(&mut self, path: &str, data: Vec<u8>) -> Result<bool, XsdBusError> {
|
fn write(&mut self, path: &str, data: Vec<u8>) -> Result<bool, XsdBusError> {
|
||||||
self.client.write(self.tx, path, data)
|
self.client.write(self.tx, path, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_string(&mut self, path: &str, data: String) -> Result<bool, XsdBusError> {
|
||||||
|
self.client.write(self.tx, path, data.into_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
fn mkdir(&mut self, path: &str) -> Result<bool, XsdBusError> {
|
fn mkdir(&mut self, path: &str) -> Result<bool, XsdBusError> {
|
||||||
self.client.mkdir(self.tx, path)
|
self.client.mkdir(self.tx, path)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user