From 7f5a8c7a6e39d30d60fccfb8d58bb4cb584c8f54 Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Thu, 17 Oct 2024 13:27:23 -0400 Subject: [PATCH] fix(xenplatform): e820 sanitize should now produce valid mappings --- crates/xen/xencall/Cargo.toml | 4 + .../examples/{cputopo.rs => cpu_topology.rs} | 5 - .../xen/xencall/examples/power_management.rs | 2 - crates/xen/xencall/src/lib.rs | 49 ++++++-- crates/xen/xencall/src/sys.rs | 49 +++++++- crates/xen/xenevtchn/Cargo.toml | 2 +- crates/xen/xenplatform/src/x86pv.rs | 110 +----------------- 7 files changed, 97 insertions(+), 124 deletions(-) rename crates/xen/xencall/examples/{cputopo.rs => cpu_topology.rs} (60%) diff --git a/crates/xen/xencall/Cargo.toml b/crates/xen/xencall/Cargo.toml index 8ab2bbc3..aad90500 100644 --- a/crates/xen/xencall/Cargo.toml +++ b/crates/xen/xencall/Cargo.toml @@ -22,6 +22,10 @@ name = "xencall" [dev-dependencies] env_logger = { workspace = true } +[[example]] +name = "xencall-cpu-topology" +path = "examples/cpu_topology.rs" + [[example]] name = "xencall-domain-info" path = "examples/domain_info.rs" diff --git a/crates/xen/xencall/examples/cputopo.rs b/crates/xen/xencall/examples/cpu_topology.rs similarity index 60% rename from crates/xen/xencall/examples/cputopo.rs rename to crates/xen/xencall/examples/cpu_topology.rs index 716ac779..bc1928f5 100644 --- a/crates/xen/xencall/examples/cputopo.rs +++ b/crates/xen/xencall/examples/cpu_topology.rs @@ -1,5 +1,4 @@ use xencall::error::Result; -use xencall::sys::CpuId; use xencall::XenCall; #[tokio::main] @@ -11,9 +10,5 @@ async fn main() -> Result<()> { println!("{:?}", physinfo); let topology = call.cpu_topology().await?; println!("{:?}", topology); - call.set_cpufreq_gov(CpuId::All, "performance").await?; - call.set_cpufreq_gov(CpuId::Single(0), "performance") - .await?; - call.set_turbo_mode(CpuId::All, true).await?; Ok(()) } diff --git a/crates/xen/xencall/examples/power_management.rs b/crates/xen/xencall/examples/power_management.rs index 716ac779..b3ccc082 100644 --- a/crates/xen/xencall/examples/power_management.rs +++ b/crates/xen/xencall/examples/power_management.rs @@ -7,8 +7,6 @@ async fn main() -> Result<()> { env_logger::init(); let call = XenCall::open(0)?; - let physinfo = call.phys_info().await?; - println!("{:?}", physinfo); let topology = call.cpu_topology().await?; println!("{:?}", topology); call.set_cpufreq_gov(CpuId::All, "performance").await?; diff --git a/crates/xen/xencall/src/lib.rs b/crates/xen/xencall/src/lib.rs index f159abfa..48986079 100644 --- a/crates/xen/xencall/src/lib.rs +++ b/crates/xen/xencall/src/lib.rs @@ -10,10 +10,11 @@ use crate::sys::{ PciAssignDevice, XenCapabilitiesInfo, DOMCTL_DEV_PCI, HYPERVISOR_DOMCTL, HYPERVISOR_EVENT_CHANNEL_OP, HYPERVISOR_HVM_OP, HYPERVISOR_MEMORY_OP, HYPERVISOR_MMUEXT_OP, HYPERVISOR_MULTICALL, HYPERVISOR_XEN_VERSION, XENVER_CAPABILITIES, XEN_DOMCTL_ASSIGN_DEVICE, - XEN_DOMCTL_CREATEDOMAIN, XEN_DOMCTL_DESTROYDOMAIN, XEN_DOMCTL_GETDOMAININFO, - XEN_DOMCTL_GETHVMCONTEXT, XEN_DOMCTL_GETPAGEFRAMEINFO3, XEN_DOMCTL_HYPERCALL_INIT, - XEN_DOMCTL_IOMEM_PERMISSION, XEN_DOMCTL_IOPORT_PERMISSION, XEN_DOMCTL_IRQ_PERMISSION, - XEN_DOMCTL_MAX_MEM, XEN_DOMCTL_MAX_VCPUS, XEN_DOMCTL_PAUSEDOMAIN, XEN_DOMCTL_SETHVMCONTEXT, + XEN_DOMCTL_CREATEDOMAIN, XEN_DOMCTL_CREATE_DOMAIN2_INTERFACE_THRESHOLD, + XEN_DOMCTL_DESTROYDOMAIN, XEN_DOMCTL_GETDOMAININFO, XEN_DOMCTL_GETHVMCONTEXT, + XEN_DOMCTL_GETPAGEFRAMEINFO3, XEN_DOMCTL_HYPERCALL_INIT, XEN_DOMCTL_IOMEM_PERMISSION, + XEN_DOMCTL_IOPORT_PERMISSION, XEN_DOMCTL_IRQ_PERMISSION, XEN_DOMCTL_MAX_MEM, + XEN_DOMCTL_MAX_VCPUS, XEN_DOMCTL_PAUSEDOMAIN, XEN_DOMCTL_SETHVMCONTEXT, XEN_DOMCTL_SETVCPUCONTEXT, XEN_DOMCTL_SET_ADDRESS_SIZE, XEN_DOMCTL_SET_PAGING_MEMPOOL_SIZE, XEN_DOMCTL_UNPAUSEDOMAIN, XEN_MEM_ADD_TO_PHYSMAP, XEN_MEM_CLAIM_PAGES, XEN_MEM_MEMORY_MAP, XEN_MEM_POPULATE_PHYSMAP, @@ -25,10 +26,11 @@ use std::ffi::{c_long, c_uint, c_ulong, c_void}; use std::sync::Arc; use std::time::Duration; use sys::{ - CpuId, E820Entry, ForeignMemoryMap, PhysdevMapPirq, Sysctl, SysctlCputopo, SysctlCputopoinfo, - SysctlPhysinfo, SysctlPmOp, SysctlPmOpValue, SysctlReadconsole, SysctlSetCpuFreqGov, - SysctlValue, VcpuGuestContextAny, HYPERVISOR_PHYSDEV_OP, HYPERVISOR_SYSCTL, PHYSDEVOP_MAP_PIRQ, - XEN_DOMCTL_MAX_INTERFACE_VERSION, XEN_DOMCTL_MIN_INTERFACE_VERSION, XEN_MEM_SET_MEMORY_MAP, + CpuId, E820Entry, ForeignMemoryMap, PhysdevMapPirq, SetDomainHandle, Sysctl, SysctlCputopo, + SysctlCputopoinfo, SysctlPhysinfo, SysctlPmOp, SysctlPmOpValue, SysctlReadconsole, + SysctlSetCpuFreqGov, SysctlValue, VcpuGuestContextAny, HYPERVISOR_PHYSDEV_OP, + HYPERVISOR_SYSCTL, PHYSDEVOP_MAP_PIRQ, XEN_DOMCTL_MAX_INTERFACE_VERSION, + XEN_DOMCTL_MIN_INTERFACE_VERSION, XEN_DOMCTL_SETDOMAINHANDLE, XEN_MEM_SET_MEMORY_MAP, XEN_SYSCTL_CPUTOPOINFO, XEN_SYSCTL_MAX_INTERFACE_VERSION, XEN_SYSCTL_MIN_INTERFACE_VERSION, XEN_SYSCTL_PHYSINFO, XEN_SYSCTL_PM_OP, XEN_SYSCTL_PM_OP_DISABLE_TURBO, XEN_SYSCTL_PM_OP_ENABLE_TURBO, XEN_SYSCTL_PM_OP_SET_CPUFREQ_GOV, XEN_SYSCTL_READCONSOLE, @@ -366,6 +368,28 @@ impl XenCall { Ok(alloc_unbound.port) } + pub async fn set_domain_handle(&self, domid: u32, domain_handle: [u8; 16]) -> Result<()> { + trace!( + "domctl fd={} set_domain_handle domid={} handle={:?}", + self.handle.as_raw_fd(), + domid, + domain_handle, + ); + let mut domctl = DomCtl { + cmd: XEN_DOMCTL_SETDOMAINHANDLE, + interface_version: self.domctl_interface_version, + domid, + value: DomCtlValue { + set_domain_handle: SetDomainHandle { + handle: domain_handle, + }, + }, + }; + self.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong) + .await?; + Ok(()) + } + pub async fn get_domain_info(&self, domid: u32) -> Result { trace!( "domctl fd={} get_domain_info domid={}", @@ -395,7 +419,14 @@ impl XenCall { cmd: XEN_DOMCTL_CREATEDOMAIN, interface_version: self.domctl_interface_version, domid: 0, - value: DomCtlValue { create_domain }, + value: if self.domctl_interface_version >= XEN_DOMCTL_CREATE_DOMAIN2_INTERFACE_THRESHOLD + { + DomCtlValue { + create_domain2: create_domain.to_cd_2(), + } + } else { + DomCtlValue { create_domain } + }, }; self.hypercall1(HYPERVISOR_DOMCTL, addr_of_mut!(domctl) as c_ulong) .await?; diff --git a/crates/xen/xencall/src/sys.rs b/crates/xen/xencall/src/sys.rs index 91193193..049a05df 100644 --- a/crates/xen/xencall/src/sys.rs +++ b/crates/xen/xencall/src/sys.rs @@ -231,6 +231,7 @@ pub struct AddressSize { #[derive(Copy, Clone)] pub union DomCtlValue { pub create_domain: CreateDomain, + pub create_domain2: CreateDomain2, pub get_domain_info: GetDomainInfo, pub max_mem: MaxMem, pub max_cpus: MaxVcpus, @@ -244,6 +245,7 @@ pub union DomCtlValue { pub assign_device: AssignDevice, pub hvm_context: HvmContext, pub paging_mempool: PagingMempool, + pub set_domain_handle: SetDomainHandle, pub pad: [u8; 128], } @@ -264,6 +266,24 @@ pub struct CreateDomain { pub arch_domain_config: ArchDomainConfig, } +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub struct CreateDomain2 { + 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 altp2m_opts: u32, + pub vmtrace_size: u32, + pub cpupool_id: u32, + pub arch_domain_config: ArchDomainConfig, +} + impl Default for CreateDomain { fn default() -> Self { CreateDomain { @@ -283,6 +303,32 @@ impl Default for CreateDomain { } } +impl CreateDomain { + pub fn to_cd_2(self) -> CreateDomain2 { + CreateDomain2 { + ssidref: self.ssidref, + handle: self.handle, + flags: self.flags, + iommu_opts: self.iommu_opts, + max_vcpus: self.max_vcpus, + max_evtchn_port: self.max_evtchn_port, + max_grant_frames: self.max_grant_frames, + max_maptrack_frames: self.max_maptrack_frames, + grant_opts: self.grant_opts, + altp2m_opts: 0, + vmtrace_size: self.vmtrace_size, + cpupool_id: self.cpupool_id, + arch_domain_config: self.arch_domain_config, + } + } +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, Default)] +pub struct SetDomainHandle { + pub handle: [u8; 16], +} + #[repr(C)] #[derive(Copy, Clone, Debug, Default)] pub struct GetDomainInfo { @@ -377,7 +423,8 @@ pub struct HypercallInit { } pub const XEN_DOMCTL_MIN_INTERFACE_VERSION: u32 = 0x00000015; -pub const XEN_DOMCTL_MAX_INTERFACE_VERSION: u32 = 0x00000016; +pub const XEN_DOMCTL_MAX_INTERFACE_VERSION: u32 = 0x00000017; +pub const XEN_DOMCTL_CREATE_DOMAIN2_INTERFACE_THRESHOLD: u32 = 0x00000017; pub const SECINITSID_DOMU: u32 = 12; diff --git a/crates/xen/xenevtchn/Cargo.toml b/crates/xen/xenevtchn/Cargo.toml index 200a2889..417f1a13 100644 --- a/crates/xen/xenevtchn/Cargo.toml +++ b/crates/xen/xenevtchn/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "krata-xenevtchn" -description = "An implementation of Xen evtchn for krata" +description = "An implementation of Xen evtchn for krata." license.workspace = true version.workspace = true homepage.workspace = true diff --git a/crates/xen/xenplatform/src/x86pv.rs b/crates/xen/xenplatform/src/x86pv.rs index 1ed2d89a..c9650bda 100644 --- a/crates/xen/xenplatform/src/x86pv.rs +++ b/crates/xen/xenplatform/src/x86pv.rs @@ -287,7 +287,6 @@ impl X86PvPlatform { &self, mut source: Vec, map_limit_kb: u64, - balloon_kb: u64, ) -> Result> { let mut e820 = vec![E820Entry::default(); E820_MAX as usize]; @@ -323,111 +322,10 @@ impl X86PvPlatform { } } - let start_kb = if lowest > 1024 { lowest >> 10 } else { 0 }; + e820[0].addr = 0; + e820[0].size = map_limit_kb << 10; + e820[0].typ = E820_RAM; - let mut idx: usize = 0; - - e820[idx].addr = 0; - e820[idx].size = map_limit_kb << 10; - e820[idx].typ = E820_RAM; - - let mut delta_kb = 0u64; - - if start_kb > 0 && map_limit_kb > start_kb { - delta_kb = map_limit_kb - start_kb; - if delta_kb > 0 { - e820[idx].size -= delta_kb << 10; - } - } - - let ram_end = source[0].addr + source[0].size; - idx += 1; - - for src in &mut source { - let end = src.addr + src.size; - if src.typ == E820_UNUSABLE || end < ram_end { - src.typ = 0; - continue; - } - - if src.typ != E820_RAM { - continue; - } - - if src.addr >= (1 << 32) { - continue; - } - - if src.addr < ram_end { - let delta = ram_end - src.addr; - src.typ = E820_UNUSABLE; - - if src.size < delta { - src.typ = 0; - } else { - src.size -= delta; - src.addr = ram_end; - } - - if src.addr + src.size != end { - src.typ = 0; - } - } - - if end > ram_end { - src.typ = E820_UNUSABLE; - } - } - - if lowest > ram_end { - let mut add_unusable = true; - - for src in &mut source { - if !add_unusable { - break; - } - - if src.typ != E820_UNUSABLE { - continue; - } - - if ram_end != src.addr { - continue; - } - - if lowest != src.addr + src.size { - src.size = lowest - src.addr; - } - add_unusable = false; - } - - if add_unusable { - e820[1].typ = E820_UNUSABLE; - e820[1].addr = ram_end; - e820[1].size = lowest - ram_end; - } - } - - for src in &source { - if src.typ == E820_RAM || src.typ == 0 { - continue; - } - - e820[idx].typ = src.typ; - e820[idx].addr = src.addr; - e820[idx].size = src.size; - idx += 1; - } - - if balloon_kb > 0 || delta_kb > 0 { - e820[idx].typ = E820_RAM; - e820[idx].addr = if (1u64 << 32u64) > highest { - 1u64 << 32u64 - } else { - highest - }; - e820[idx].size = (delta_kb << 10) + (balloon_kb << 10); - } Ok(e820) } } @@ -831,7 +729,7 @@ impl BootSetupPlatform for X86PvPlatform { let map = domain.call.get_memory_map(E820_MAX).await?; let mem_mb = domain.total_pages >> (20 - self.page_shift()); let mem_kb = mem_mb * 1024; - let e820 = self.e820_sanitize(map, mem_kb, 0)?; + let e820 = self.e820_sanitize(map, mem_kb)?; domain.call.set_memory_map(domain.domid, e820).await?; domain