mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-03 13:11:31 +00:00
krata: begin work on guest message channel
This commit is contained in:
@ -23,14 +23,14 @@ async fn main() -> Result<()> {
|
||||
initrd_path: initrd_path.as_str(),
|
||||
cmdline: "debug elevator=noop",
|
||||
disks: vec![],
|
||||
consoles: vec![],
|
||||
channels: vec![],
|
||||
vifs: vec![],
|
||||
filesystems: vec![],
|
||||
extra_keys: vec![],
|
||||
extra_rw_paths: vec![],
|
||||
event_channels: vec![],
|
||||
};
|
||||
let domid = client.create(&config).await?;
|
||||
println!("created domain {}", domid);
|
||||
let created = client.create(&config).await?;
|
||||
println!("created domain {}", created.domid);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -58,7 +58,6 @@ pub struct BootState {
|
||||
pub kernel_segment: DomainSegment,
|
||||
pub start_info_segment: DomainSegment,
|
||||
pub xenstore_segment: DomainSegment,
|
||||
pub console_segment: DomainSegment,
|
||||
pub boot_stack_segment: DomainSegment,
|
||||
pub p2m_segment: Option<DomainSegment>,
|
||||
pub page_table_segment: Option<DomainSegment>,
|
||||
@ -66,7 +65,7 @@ pub struct BootState {
|
||||
pub shared_info_frame: u64,
|
||||
pub initrd_segment: DomainSegment,
|
||||
pub store_evtchn: u32,
|
||||
pub console_evtchn: u32,
|
||||
pub consoles: Vec<(u32, DomainSegment)>,
|
||||
}
|
||||
|
||||
impl BootSetup<'_> {
|
||||
@ -114,6 +113,7 @@ impl BootSetup<'_> {
|
||||
initrd: &[u8],
|
||||
max_vcpus: u32,
|
||||
mem_mb: u64,
|
||||
console_count: usize,
|
||||
) -> Result<BootState> {
|
||||
debug!("initialize max_vcpus={:?} mem_mb={:?}", max_vcpus, mem_mb);
|
||||
|
||||
@ -145,7 +145,12 @@ impl BootSetup<'_> {
|
||||
}
|
||||
let start_info_segment = self.alloc_page(arch)?;
|
||||
let xenstore_segment = self.alloc_page(arch)?;
|
||||
let console_segment = self.alloc_page(arch)?;
|
||||
let mut consoles: Vec<(u32, DomainSegment)> = Vec::new();
|
||||
for _ in 0..console_count {
|
||||
let evtchn = self.call.evtchn_alloc_unbound(self.domid, 0)?;
|
||||
let page = self.alloc_page(arch)?;
|
||||
consoles.push((evtchn, page));
|
||||
}
|
||||
let page_table_segment = arch.alloc_page_tables(self, &image_info)?;
|
||||
let boot_stack_segment = self.alloc_page(arch)?;
|
||||
|
||||
@ -166,7 +171,6 @@ impl BootSetup<'_> {
|
||||
|
||||
let initrd_segment = initrd_segment.unwrap();
|
||||
let store_evtchn = self.call.evtchn_alloc_unbound(self.domid, 0)?;
|
||||
let console_evtchn = self.call.evtchn_alloc_unbound(self.domid, 0)?;
|
||||
|
||||
let kernel_segment =
|
||||
kernel_segment.ok_or(Error::MemorySetupFailed("kernel_segment missing"))?;
|
||||
@ -175,14 +179,13 @@ impl BootSetup<'_> {
|
||||
kernel_segment,
|
||||
start_info_segment,
|
||||
xenstore_segment,
|
||||
console_segment,
|
||||
consoles,
|
||||
boot_stack_segment,
|
||||
p2m_segment,
|
||||
page_table_segment,
|
||||
image_info,
|
||||
initrd_segment,
|
||||
store_evtchn,
|
||||
console_evtchn,
|
||||
shared_info_frame: 0,
|
||||
};
|
||||
debug!("initialize state={:?}", state);
|
||||
@ -210,7 +213,8 @@ impl BootSetup<'_> {
|
||||
}
|
||||
|
||||
fn gnttab_seed(&mut self, state: &mut BootState) -> Result<()> {
|
||||
let console_gfn = self.phys.p2m[state.console_segment.pfn as usize];
|
||||
let console_gfn =
|
||||
self.phys.p2m[state.consoles.first().map(|x| x.1.pfn).unwrap_or(0) as usize];
|
||||
let xenstore_gfn = self.phys.p2m[state.xenstore_segment.pfn as usize];
|
||||
let addr = self
|
||||
.call
|
||||
|
@ -19,6 +19,7 @@ use crate::arm64::Arm64BootSetup;
|
||||
use crate::boot::BootSetup;
|
||||
use crate::elfloader::ElfImageLoader;
|
||||
use crate::error::{Error, Result};
|
||||
use boot::BootState;
|
||||
use log::{trace, warn};
|
||||
|
||||
use std::fs::read;
|
||||
@ -67,7 +68,10 @@ pub struct DomainNetworkInterface<'a> {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DomainConsole {}
|
||||
pub struct DomainChannel {
|
||||
pub typ: String,
|
||||
pub initialized: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DomainEventChannel<'a> {
|
||||
@ -84,7 +88,7 @@ pub struct DomainConfig<'a> {
|
||||
pub initrd_path: &'a str,
|
||||
pub cmdline: &'a str,
|
||||
pub disks: Vec<DomainDisk<'a>>,
|
||||
pub consoles: Vec<DomainConsole>,
|
||||
pub channels: Vec<DomainChannel>,
|
||||
pub vifs: Vec<DomainNetworkInterface<'a>>,
|
||||
pub filesystems: Vec<DomainFilesystem<'a>>,
|
||||
pub event_channels: Vec<DomainEventChannel<'a>>,
|
||||
@ -92,6 +96,18 @@ pub struct DomainConfig<'a> {
|
||||
pub extra_rw_paths: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CreatedChannel {
|
||||
pub ring_ref: u64,
|
||||
pub evtchn: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CreatedDomain {
|
||||
pub domid: u32,
|
||||
pub channels: Vec<CreatedChannel>,
|
||||
}
|
||||
|
||||
impl XenClient {
|
||||
pub async fn open(current_domid: u32) -> Result<XenClient> {
|
||||
let store = XsdClient::open().await?;
|
||||
@ -99,7 +115,7 @@ impl XenClient {
|
||||
Ok(XenClient { store, call })
|
||||
}
|
||||
|
||||
pub async fn create(&mut self, config: &DomainConfig<'_>) -> Result<u32> {
|
||||
pub async fn create(&mut self, config: &DomainConfig<'_>) -> Result<CreatedDomain> {
|
||||
let mut domain = CreateDomain {
|
||||
max_vcpus: config.max_vcpus,
|
||||
..Default::default()
|
||||
@ -111,7 +127,7 @@ impl XenClient {
|
||||
|
||||
let domid = self.call.create_domain(domain)?;
|
||||
match self.init(domid, &domain, config).await {
|
||||
Ok(_) => Ok(domid),
|
||||
Ok(created) => Ok(created),
|
||||
Err(err) => {
|
||||
// ignore since destroying a domain is best
|
||||
// effort when an error occurs
|
||||
@ -126,7 +142,7 @@ impl XenClient {
|
||||
domid: u32,
|
||||
domain: &CreateDomain,
|
||||
config: &DomainConfig<'_>,
|
||||
) -> Result<()> {
|
||||
) -> Result<CreatedDomain> {
|
||||
trace!(
|
||||
"XenClient init domid={} domain={:?} config={:?}",
|
||||
domid,
|
||||
@ -241,11 +257,11 @@ impl XenClient {
|
||||
self.call.set_max_mem(domid, config.mem_mb * 1024)?;
|
||||
let image_loader = ElfImageLoader::load_file_kernel(config.kernel_path)?;
|
||||
|
||||
let console_evtchn: u32;
|
||||
let xenstore_evtchn: u32;
|
||||
let console_mfn: u64;
|
||||
let xenstore_mfn: u64;
|
||||
|
||||
let p2m: Vec<u64>;
|
||||
let mut state: BootState;
|
||||
{
|
||||
let mut boot = BootSetup::new(&self.call, domid);
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@ -253,18 +269,18 @@ impl XenClient {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
let mut arch = Arm64BootSetup::new();
|
||||
let initrd = read(config.initrd_path)?;
|
||||
let mut state = boot.initialize(
|
||||
state = boot.initialize(
|
||||
&mut arch,
|
||||
&image_loader,
|
||||
initrd.as_slice(),
|
||||
config.max_vcpus,
|
||||
config.mem_mb,
|
||||
1 + config.channels.len(),
|
||||
)?;
|
||||
boot.boot(&mut arch, &mut state, config.cmdline)?;
|
||||
console_evtchn = state.console_evtchn;
|
||||
xenstore_evtchn = state.store_evtchn;
|
||||
console_mfn = boot.phys.p2m[state.console_segment.pfn as usize];
|
||||
xenstore_mfn = boot.phys.p2m[state.xenstore_segment.pfn as usize];
|
||||
p2m = boot.phys.p2m;
|
||||
}
|
||||
|
||||
{
|
||||
@ -329,27 +345,38 @@ impl XenClient {
|
||||
return Err(Error::IntroduceDomainFailed);
|
||||
}
|
||||
self.console_device_add(
|
||||
&DomainChannel {
|
||||
typ: "xenconsoled".to_string(),
|
||||
initialized: true,
|
||||
},
|
||||
&p2m,
|
||||
&state,
|
||||
&dom_path,
|
||||
&backend_dom_path,
|
||||
config.backend_domid,
|
||||
domid,
|
||||
0,
|
||||
Some(console_evtchn),
|
||||
Some(console_mfn),
|
||||
)
|
||||
.await?;
|
||||
|
||||
for (index, _) in config.consoles.iter().enumerate() {
|
||||
self.console_device_add(
|
||||
&dom_path,
|
||||
&backend_dom_path,
|
||||
config.backend_domid,
|
||||
domid,
|
||||
index + 1,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
let mut channels: Vec<CreatedChannel> = Vec::new();
|
||||
for (index, channel) in config.channels.iter().enumerate() {
|
||||
let (Some(ring_ref), Some(evtchn)) = self
|
||||
.console_device_add(
|
||||
channel,
|
||||
&p2m,
|
||||
&state,
|
||||
&dom_path,
|
||||
&backend_dom_path,
|
||||
config.backend_domid,
|
||||
domid,
|
||||
index + 1,
|
||||
)
|
||||
.await?
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
channels.push(CreatedChannel { ring_ref, evtchn });
|
||||
}
|
||||
|
||||
for (index, disk) in config.disks.iter().enumerate() {
|
||||
@ -402,7 +429,7 @@ impl XenClient {
|
||||
}
|
||||
|
||||
self.call.unpause_domain(domid)?;
|
||||
Ok(())
|
||||
Ok(CreatedDomain { domid, channels })
|
||||
}
|
||||
|
||||
async fn disk_device_add(
|
||||
@ -460,18 +487,22 @@ impl XenClient {
|
||||
#[allow(clippy::too_many_arguments, clippy::unnecessary_unwrap)]
|
||||
async fn console_device_add(
|
||||
&mut self,
|
||||
channel: &DomainChannel,
|
||||
p2m: &[u64],
|
||||
state: &BootState,
|
||||
dom_path: &str,
|
||||
backend_dom_path: &str,
|
||||
backend_domid: u32,
|
||||
domid: u32,
|
||||
index: usize,
|
||||
port: Option<u32>,
|
||||
ring: Option<u64>,
|
||||
) -> Result<()> {
|
||||
) -> Result<(Option<u64>, Option<u32>)> {
|
||||
let console = state.consoles.get(index);
|
||||
let port = console.map(|x| x.0);
|
||||
let ring = console.map(|x| p2m[x.1.pfn as usize]);
|
||||
|
||||
let mut backend_entries = vec![
|
||||
("frontend-id", domid.to_string()),
|
||||
("online", "1".to_string()),
|
||||
("state", "1".to_string()),
|
||||
("protocol", "vt100".to_string()),
|
||||
];
|
||||
|
||||
@ -482,15 +513,14 @@ impl XenClient {
|
||||
("tty", "".to_string()),
|
||||
];
|
||||
|
||||
if index == 0 {
|
||||
frontend_entries.push(("type", "xenconsoled".to_string()));
|
||||
} else {
|
||||
frontend_entries.push(("type", "ioemu".to_string()));
|
||||
backend_entries.push(("connection", "pty".to_string()));
|
||||
backend_entries.push(("output", "pty".to_string()));
|
||||
}
|
||||
frontend_entries.push(("type", channel.typ.clone()));
|
||||
backend_entries.push(("type", channel.typ.clone()));
|
||||
|
||||
if port.is_some() && ring.is_some() {
|
||||
if channel.typ != "xenconsoled" {
|
||||
frontend_entries.push(("state", "1".to_string()));
|
||||
}
|
||||
|
||||
frontend_entries.extend_from_slice(&[
|
||||
("port", port.unwrap().to_string()),
|
||||
("ring-ref", ring.unwrap().to_string()),
|
||||
@ -502,6 +532,12 @@ impl XenClient {
|
||||
]);
|
||||
}
|
||||
|
||||
if channel.initialized {
|
||||
backend_entries.push(("state", "4".to_string()));
|
||||
} else {
|
||||
backend_entries.push(("state", "1".to_string()));
|
||||
}
|
||||
|
||||
self.device_add(
|
||||
"console",
|
||||
index as u64,
|
||||
@ -513,7 +549,7 @@ impl XenClient {
|
||||
backend_entries,
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
Ok((ring, port))
|
||||
}
|
||||
|
||||
async fn fs_9p_device_add(
|
||||
|
@ -442,8 +442,9 @@ impl ArchBootSetup for X86BootSetup {
|
||||
(*info).flags = 0;
|
||||
(*info).store_evtchn = state.store_evtchn;
|
||||
(*info).store_mfn = setup.phys.p2m[state.xenstore_segment.pfn as usize];
|
||||
(*info).console.mfn = setup.phys.p2m[state.console_segment.pfn as usize];
|
||||
(*info).console.evtchn = state.console_evtchn;
|
||||
let console = state.consoles.first().unwrap();
|
||||
(*info).console.mfn = setup.phys.p2m[console.1.pfn as usize];
|
||||
(*info).console.evtchn = console.0;
|
||||
(*info).mod_start = state.initrd_segment.vstart;
|
||||
(*info).mod_len = state.initrd_segment.size;
|
||||
for (i, c) in cmdline.chars().enumerate() {
|
||||
|
Reference in New Issue
Block a user