Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(xen): update xenclient and xenplatform to the latest structure #433

Merged
merged 1 commit into from
Dec 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ repository = "https://github.com/edera-dev/krata"

[workspace.dependencies]
async-trait = "0.1.83"
bit-vec = "0.8.0"
byteorder = "1"
c2rust-bitfields = "0.19.0"
elf = "0.7.4"
env_logger = "0.11.5"
flate2 = "1.0"
Expand Down
2 changes: 2 additions & 0 deletions crates/xen/xenclient/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ edition = "2021"
resolver = "2"

[dependencies]
async-trait = { workspace = true }
bit-vec = { workspace = true }
indexmap = { workspace = true }
log = { workspace = true }
krata-xencall = { path = "../xencall", version = "^0.0.23" }
Expand Down
65 changes: 32 additions & 33 deletions crates/xen/xenclient/examples/boot.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
use std::sync::Arc;
use std::{env, process};
use tokio::fs;
use uuid::Uuid;
use xenclient::error::Result;
use xenclient::{DomainConfig, XenClient};
use xenplatform::domain::BaseDomainConfig;

#[cfg(target_arch = "x86_64")]
type RuntimePlatform = xenplatform::x86pv::X86PvPlatform;

#[cfg(not(target_arch = "x86_64"))]
type RuntimePlatform = xenplatform::unsupported::UnsupportedPlatform;
use xenclient::tx::channel::ChannelDeviceConfig;
use xenclient::{config::DomainConfig, XenClient};
use xenplatform::domain::{
KernelFormat, PlatformDomainConfig, PlatformKernelConfig, PlatformOptions,
PlatformResourcesConfig,
};
use xenplatform::RuntimePlatformType;

#[tokio::main]
async fn main() -> Result<()> {
Expand All @@ -22,32 +22,31 @@ async fn main() -> Result<()> {
}
let kernel_image_path = args.get(1).expect("argument not specified");
let initrd_path = args.get(2).expect("argument not specified");
let client = XenClient::new(0, RuntimePlatform::new()).await?;
let config = DomainConfig {
base: BaseDomainConfig {
uuid: Uuid::new_v4(),
max_vcpus: 1,
target_vcpus: 1,
max_mem_mb: 512,
target_mem_mb: 512,
enable_iommu: true,
kernel: fs::read(&kernel_image_path).await?,
initrd: fs::read(&initrd_path).await?,
let client = XenClient::new().await?;

let mut config = DomainConfig::new();
config.platform(PlatformDomainConfig {
uuid: Uuid::new_v4(),
platform: RuntimePlatformType::Pv,
kernel: PlatformKernelConfig {
data: Arc::new(fs::read(&kernel_image_path).await?),
format: KernelFormat::ElfCompressed,
cmdline: "earlyprintk=xen earlycon=xen console=hvc0 init=/init".to_string(),
owner_domid: 0,
initrd: Some(Arc::new(fs::read(&initrd_path).await?)),
},
resources: PlatformResourcesConfig {
max_vcpus: 1,
assigned_vcpus: 1,
max_memory_mb: 512,
assigned_memory_mb: 512,
},
backend_domid: 0,
name: "xenclient-test".to_string(),
swap_console_backend: None,
disks: vec![],
channels: vec![],
vifs: vec![],
pcis: vec![],
filesystems: vec![],
extra_keys: vec![],
extra_rw_paths: vec![],
};
let created = client.create(&config).await?;
println!("created domain {}", created.domid);
options: PlatformOptions { iommu: true },
});
config.name("xenclient-test");
let mut channel = ChannelDeviceConfig::new();
channel.default_console().backend_initialized();
config.add_channel(channel);
let created = client.create(config).await?;
println!("created domain {}", created.platform.domid);
Ok(())
}
66 changes: 66 additions & 0 deletions crates/xen/xenclient/examples/boot_speed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use std::sync::Arc;
use std::{env, process};
use tokio::fs;
use uuid::Uuid;
use xenclient::config::{DomainConfig, DomainResult};
use xenclient::error::Result;
use xenclient::tx::channel::ChannelDeviceConfig;
use xenclient::XenClient;
use xenplatform::domain::{
KernelFormat, PlatformDomainConfig, PlatformKernelConfig, PlatformOptions,
PlatformResourcesConfig,
};
use xenplatform::elfloader::ElfImageLoader;
use xenplatform::RuntimePlatformType;

#[tokio::main]
async fn main() -> Result<()> {
env_logger::init();

let args: Vec<String> = env::args().collect();
if args.len() != 2 {
println!("usage: boot-speed <kernel-image>");
process::exit(1);
}
let kernel_path = args.get(1).expect("argument not specified");
let kernel = Arc::new(fs::read(kernel_path).await?);
let kernel = ElfImageLoader::load(kernel)?.into_elf_bytes();
let client = XenClient::new().await?;

for i in 0..5u32 {
let start = std::time::Instant::now();
let domain = create_domain(&client, kernel.clone(), i).await?;
let end = std::time::Instant::now();
let duration = end - start;
println!("boot setup time: {:?}", duration);
client.destroy(domain.platform.domid).await?;
}
Ok(())
}

async fn create_domain(client: &XenClient, kernel: Arc<Vec<u8>>, i: u32) -> Result<DomainResult> {
let mut config = DomainConfig::new();
config.platform(PlatformDomainConfig {
uuid: Uuid::new_v4(),
platform: RuntimePlatformType::Pv,
kernel: PlatformKernelConfig {
data: kernel,
format: KernelFormat::ElfUncompressed,
cmdline: "earlyprintk=xen earlycon=xen console=hvc0 init=/init".to_string(),
initrd: None,
},
resources: PlatformResourcesConfig {
max_vcpus: 1,
assigned_vcpus: 1,
max_memory_mb: 512,
assigned_memory_mb: 512,
},
options: PlatformOptions { iommu: true },
});
config.name(format!("xenboot-{}", i));
config.start(false);
let mut channel = ChannelDeviceConfig::new();
channel.default_console().backend_initialized();
config.add_channel(channel);
client.create(config).await
}
185 changes: 185 additions & 0 deletions crates/xen/xenclient/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
use std::collections::HashMap;

use xencall::XenCall;
pub use xenplatform::domain::PlatformDomainConfig;
use xenplatform::domain::PlatformDomainInfo;

use crate::{
error::Result,
tx::{
channel::ChannelDeviceConfig,
fs9p::Fs9pDeviceConfig,
pci::PciRootDeviceConfig,
vbd::VbdDeviceConfig,
vif::VifDeviceConfig,
{BlockDeviceResult, DeviceResult},
},
};

pub struct DomainConfig {
platform: Option<PlatformDomainConfig>,
name: Option<String>,
backend_domid: u32,
channels: Vec<ChannelDeviceConfig>,
vifs: Vec<VifDeviceConfig>,
vbds: Vec<VbdDeviceConfig>,
fs9ps: Vec<Fs9pDeviceConfig>,
pci: Option<PciRootDeviceConfig>,
extra_keys: HashMap<String, String>,
extra_rw_paths: Vec<String>,
start: bool,
}

impl Default for DomainConfig {
fn default() -> Self {
Self::new()
}
}

impl DomainConfig {
pub fn new() -> Self {
Self {
platform: None,
name: None,
backend_domid: 0,
channels: Vec::new(),
vifs: Vec::new(),
vbds: Vec::new(),
fs9ps: Vec::new(),
pci: None,
extra_keys: HashMap::new(),
extra_rw_paths: Vec::new(),
start: true,
}
}

pub fn platform(&mut self, platform: PlatformDomainConfig) -> &mut Self {
self.platform = Some(platform);
self
}

pub fn get_platform(&self) -> &Option<PlatformDomainConfig> {
&self.platform
}

pub fn name(&mut self, name: impl AsRef<str>) -> &mut Self {
self.name = Some(name.as_ref().to_string());
self
}

pub fn get_name(&self) -> &Option<String> {
&self.name
}

pub fn backend_domid(&mut self, backend_domid: u32) -> &mut Self {
self.backend_domid = backend_domid;
self
}

pub fn get_backend_domid(&self) -> u32 {
self.backend_domid
}

pub fn add_channel(&mut self, channel: ChannelDeviceConfig) -> &mut Self {
self.channels.push(channel);
self
}

pub fn get_channels(&self) -> &Vec<ChannelDeviceConfig> {
&self.channels
}

pub fn add_vif(&mut self, vif: VifDeviceConfig) -> &mut Self {
self.vifs.push(vif);
self
}

pub fn get_vifs(&self) -> &Vec<VifDeviceConfig> {
&self.vifs
}

pub fn add_vbd(&mut self, vbd: VbdDeviceConfig) -> &mut Self {
self.vbds.push(vbd);
self
}

pub fn get_vbds(&self) -> &Vec<VbdDeviceConfig> {
&self.vbds
}

pub fn add_fs9p(&mut self, fs9p: Fs9pDeviceConfig) -> &mut Self {
self.fs9ps.push(fs9p);
self
}

pub fn get_fs9ps(&self) -> &Vec<Fs9pDeviceConfig> {
&self.fs9ps
}

pub fn pci(&mut self, pci: PciRootDeviceConfig) -> &mut Self {
self.pci = Some(pci);
self
}

pub fn get_pci(&self) -> &Option<PciRootDeviceConfig> {
&self.pci
}

pub fn add_extra_key(&mut self, key: impl AsRef<str>, value: impl ToString) -> &mut Self {
self.extra_keys
.insert(key.as_ref().to_string(), value.to_string());
self
}

pub fn get_extra_keys(&self) -> &HashMap<String, String> {
&self.extra_keys
}

pub fn add_rw_path(&mut self, path: impl AsRef<str>) -> &mut Self {
self.extra_rw_paths.push(path.as_ref().to_string());
self
}

pub fn get_rw_paths(&self) -> &Vec<String> {
&self.extra_rw_paths
}

pub fn start(&mut self, start: bool) -> &mut Self {
self.start = start;
self
}

pub fn get_start(&self) -> bool {
self.start
}

pub fn done(self) -> Self {
self
}

pub(crate) async fn prepare(
&mut self,
domid: u32,
call: &XenCall,
platform: &PlatformDomainInfo,
) -> Result<()> {
if let Some(pci) = self.pci.as_mut() {
pci.prepare(domid, call).await?;
}

for channel in &mut self.channels {
channel.prepare(platform).await?;
}

Ok(())
}
}

pub struct DomainResult {
pub platform: PlatformDomainInfo,
pub channels: Vec<DeviceResult>,
pub vifs: Vec<DeviceResult>,
pub vbds: Vec<BlockDeviceResult>,
pub fs9ps: Vec<DeviceResult>,
pub pci: Option<DeviceResult>,
}
Loading
Loading