xenplatform/
domain.rs

1use std::sync::Arc;
2
3use crate::{
4    boot::BootDomain, elfloader::ElfImageLoader, error::Error, ImageLoader, RuntimePlatform,
5    RuntimePlatformType,
6};
7use log::warn;
8use uuid::Uuid;
9use xencall::XenCall;
10
11use crate::error::Result;
12
13pub const XEN_EXTRA_MEMORY_KB: u64 = 2048;
14
15pub struct PlatformDomainManager {
16    call: XenCall,
17}
18
19impl PlatformDomainManager {
20    pub async fn new(call: XenCall) -> Result<PlatformDomainManager> {
21        Ok(PlatformDomainManager { call })
22    }
23
24    fn max_memory_kb(resources: &PlatformResourcesConfig) -> u64 {
25        (resources.max_memory_mb * 1024) + XEN_EXTRA_MEMORY_KB
26    }
27
28    async fn create_base_domain(
29        &self,
30        config: &PlatformDomainConfig,
31        platform: &RuntimePlatform,
32    ) -> Result<u32> {
33        let mut domain = platform.create_domain(config.options.iommu);
34        domain.handle = config.uuid.into_bytes();
35        domain.max_vcpus = config.resources.max_vcpus;
36        let domid = self.call.create_domain(domain).await?;
37        Ok(domid)
38    }
39
40    async fn configure_domain_resources(
41        &self,
42        domid: u32,
43        config: &PlatformDomainConfig,
44    ) -> Result<()> {
45        self.call
46            .set_max_vcpus(domid, config.resources.max_vcpus)
47            .await?;
48        self.call
49            .set_max_mem(
50                domid,
51                PlatformDomainManager::max_memory_kb(&config.resources),
52            )
53            .await?;
54        Ok(())
55    }
56
57    async fn create_internal(
58        &self,
59        domid: u32,
60        config: &PlatformDomainConfig,
61        mut platform: RuntimePlatform,
62    ) -> Result<BootDomain> {
63        self.configure_domain_resources(domid, config).await?;
64        let kernel = config.kernel.clone();
65        let loader = tokio::task::spawn_blocking(move || match kernel.format {
66            KernelFormat::ElfCompressed => ElfImageLoader::load(kernel.data),
67            KernelFormat::ElfUncompressed => Ok(ElfImageLoader::new(kernel.data)),
68        })
69        .await
70        .map_err(Error::AsyncJoinError)??;
71        let loader = ImageLoader::Elf(loader);
72        let mut domain = platform
73            .initialize(
74                domid,
75                self.call.clone(),
76                &loader,
77                &config.kernel,
78                &config.resources,
79            )
80            .await?;
81        platform.boot(domid, self.call.clone(), &mut domain).await?;
82        Ok(domain)
83    }
84
85    pub async fn create(&self, config: PlatformDomainConfig) -> Result<PlatformDomainInfo> {
86        let platform = config.platform.create();
87        let domid = self.create_base_domain(&config, &platform).await?;
88        let domain = match self.create_internal(domid, &config, platform).await {
89            Ok(domain) => domain,
90            Err(error) => {
91                if let Err(destroy_fail) = self.call.destroy_domain(domid).await {
92                    warn!(
93                        "failed to destroy failed domain {}: {}",
94                        domid, destroy_fail
95                    );
96                }
97                return Err(error);
98            }
99        };
100        Ok(PlatformDomainInfo {
101            domid,
102            store_evtchn: domain.store_evtchn,
103            store_mfn: domain.store_mfn,
104            console_evtchn: domain.console_evtchn,
105            console_mfn: domain.console_mfn,
106        })
107    }
108
109    pub async fn destroy(&self, domid: u32) -> Result<()> {
110        self.call.destroy_domain(domid).await?;
111        Ok(())
112    }
113}
114
115#[derive(Clone, Debug)]
116pub struct PlatformDomainConfig {
117    pub uuid: Uuid,
118    pub platform: RuntimePlatformType,
119    pub resources: PlatformResourcesConfig,
120    pub kernel: PlatformKernelConfig,
121    pub options: PlatformOptions,
122}
123
124#[derive(Clone, Debug)]
125pub struct PlatformKernelConfig {
126    pub data: Arc<Vec<u8>>,
127    pub format: KernelFormat,
128    pub initrd: Option<Arc<Vec<u8>>>,
129    pub cmdline: String,
130}
131
132#[derive(Clone, Debug)]
133pub struct PlatformResourcesConfig {
134    pub max_vcpus: u32,
135    pub assigned_vcpus: u32,
136    pub max_memory_mb: u64,
137    pub assigned_memory_mb: u64,
138}
139
140#[derive(Clone, Debug)]
141pub struct PlatformOptions {
142    pub iommu: bool,
143}
144
145#[derive(Clone, Debug)]
146pub enum KernelFormat {
147    ElfUncompressed,
148    ElfCompressed,
149}
150
151#[derive(Clone, Debug)]
152pub struct PlatformDomainInfo {
153    pub domid: u32,
154    pub store_evtchn: u32,
155    pub store_mfn: u64,
156    pub console_evtchn: u32,
157    pub console_mfn: u64,
158}