1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use std::sync::Arc;

use crate::{
    boot::{BootSetup, BootSetupPlatform},
    elfloader::ElfImageLoader,
};
use uuid::Uuid;
use xencall::XenCall;

use crate::error::Result;

pub const XEN_EXTRA_MEMORY_KB: u64 = 2048;

pub struct BaseDomainManager<P: BootSetupPlatform> {
    call: XenCall,
    pub platform: Arc<P>,
}

impl<P: BootSetupPlatform> BaseDomainManager<P> {
    pub async fn new(call: XenCall, platform: P) -> Result<BaseDomainManager<P>> {
        Ok(BaseDomainManager {
            call,
            platform: Arc::new(platform),
        })
    }

    pub async fn create(&self, config: BaseDomainConfig) -> Result<CreatedDomain> {
        let mut domain = self.platform.create_domain(config.enable_iommu);
        domain.handle = config.uuid.into_bytes();
        domain.max_vcpus = config.max_vcpus;
        let domid = self.call.create_domain(domain).await?;
        self.call.set_max_vcpus(domid, config.max_vcpus).await?;
        self.call
            .set_max_mem(domid, (config.max_mem_mb * 1024) + XEN_EXTRA_MEMORY_KB)
            .await?;
        let loader = ElfImageLoader::load_file_kernel(&config.kernel)?;
        let platform = (*self.platform).clone();
        let mut boot = BootSetup::new(self.call.clone(), domid, platform, loader, None);
        let mut domain = boot
            .initialize(
                &config.initrd,
                config.target_mem_mb,
                config.max_mem_mb,
                config.max_vcpus,
                &config.cmdline,
            )
            .await?;
        boot.boot(&mut domain).await?;
        Ok(CreatedDomain {
            domid,
            store_evtchn: domain.store_evtchn,
            store_mfn: domain.store_mfn,
            console_evtchn: domain.console_evtchn,
            console_mfn: domain.console_mfn,
        })
    }

    pub async fn destroy(&self, domid: u32) -> Result<()> {
        self.call.destroy_domain(domid).await?;
        Ok(())
    }
}

#[derive(Clone, Debug)]
pub struct BaseDomainConfig {
    pub uuid: Uuid,
    pub owner_domid: u32,
    pub max_vcpus: u32,
    pub target_vcpus: u32,
    pub max_mem_mb: u64,
    pub target_mem_mb: u64,
    pub kernel: Vec<u8>,
    pub initrd: Vec<u8>,
    pub cmdline: String,
    pub enable_iommu: bool,
}

#[derive(Clone, Debug)]
pub struct CreatedDomain {
    pub domid: u32,
    pub store_evtchn: u32,
    pub store_mfn: u64,
    pub console_evtchn: u32,
    pub console_mfn: u64,
}