From 778524467b97f88a5ea182c7cde190e7eb5adcdc Mon Sep 17 00:00:00 2001 From: Amulyam24 Date: Wed, 11 Feb 2026 16:00:37 +0530 Subject: [PATCH 1/4] runtime-rs: enable building runtime-rs on ppc64le Adds changes in Makefile to build runtime-rs on ppc64le with QEMU support. Signed-off-by: Amulyam24 --- src/runtime-rs/Makefile | 10 +++------- src/runtime-rs/arch/powerpc64le-options.mk | 5 +---- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/runtime-rs/Makefile b/src/runtime-rs/Makefile index e6f817b5a6..2da9e29e82 100644 --- a/src/runtime-rs/Makefile +++ b/src/runtime-rs/Makefile @@ -33,15 +33,11 @@ test: exit 0 install: install-runtime install-configs else ifeq ($(ARCH), powerpc64le) -default: - @echo "PowerPC 64 LE is not currently supported" - exit 0 +default: runtime show-header test: - @echo "PowerPC 64 LE is not currently supported" - exit 0 -install: - @echo "PowerPC 64 LE is not currently supported" + @echo "powerpc64le is not currently supported" exit 0 +install: install-runtime install-configs else ifeq ($(ARCH), riscv64gc) default: runtime show-header test: diff --git a/src/runtime-rs/arch/powerpc64le-options.mk b/src/runtime-rs/arch/powerpc64le-options.mk index 457b0a900e..cedac93463 100644 --- a/src/runtime-rs/arch/powerpc64le-options.mk +++ b/src/runtime-rs/arch/powerpc64le-options.mk @@ -7,9 +7,6 @@ MACHINETYPE := pseries KERNELPARAMS := cgroup_no_v1=all systemd.unified_cgroup_hierarchy=1 MACHINEACCELERATORS := "cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken,cap-large-decr=off,cap-ccf-assist=off" -CPUFEATURES := pmu=off +CPUFEATURES := QEMUCMD := qemu-system-ppc64 - -# dragonball binary name -DBCMD := dragonball From 8d25ff2c36d2d0e02d7426ea34180c3a99faac24 Mon Sep 17 00:00:00 2001 From: Amulyam24 Date: Wed, 11 Feb 2026 16:02:22 +0530 Subject: [PATCH 2/4] runtime-rs: implement set_capabilities for qemu After the qemu VM is booted, while storing the guest details, it fails to set capabilities as it is not yet implemented for QEMU, this change adds a default implementation for it. Signed-off-by: Amulyam24 --- src/runtime-rs/crates/hypervisor/src/qemu/inner.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs b/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs index bfaf6380aa..c5b8ac2629 100644 --- a/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs +++ b/src/runtime-rs/crates/hypervisor/src/qemu/inner.rs @@ -617,8 +617,10 @@ impl QemuInner { todo!() } - pub(crate) fn set_capabilities(&mut self, _flag: CapabilityBits) { - todo!() + pub(crate) fn set_capabilities(&mut self, flag: CapabilityBits) { + let mut caps = Capabilities::default(); + + caps.set(flag) } pub(crate) fn set_guest_memory_block_size(&mut self, size: u32) { From dcb7d025c7f58556f002bad688436880176b1c7a Mon Sep 17 00:00:00 2001 From: Amulyam24 Date: Wed, 11 Feb 2026 16:12:17 +0530 Subject: [PATCH 3/4] runtime-rs: Use libc::TUNSETIFF instead of wrapper TUNSETIFF() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While attaching the tap device, it fails on ppc64le with EBADF "cannot create tap device. File descriptor in bad state (os error 77)\"): unknown” Refactor the ioctl call to use the standard libc::TUNSETIFF constant. Signed-off-by: Amulyam24 --- src/runtime-rs/crates/hypervisor/src/device/tap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime-rs/crates/hypervisor/src/device/tap.rs b/src/runtime-rs/crates/hypervisor/src/device/tap.rs index a7c7e5eea4..eca73c542a 100644 --- a/src/runtime-rs/crates/hypervisor/src/device/tap.rs +++ b/src/runtime-rs/crates/hypervisor/src/device/tap.rs @@ -147,7 +147,7 @@ impl Tap { // ioctl is safe since we call it with a valid tap fd and check the return // value. - let ret = unsafe { ioctl_with_mut_ref(&tuntap, TUNSETIFF(), ifr) }; + let ret = unsafe { ioctl_with_mut_ref(&tuntap, libc::TUNSETIFF as libc::c_ulong, ifr) }; if ret < 0 { return Err(Error::CreateTap(IoError::last_os_error())); } From bf74f683d760fe0269262240d4d4db8b7e81db72 Mon Sep 17 00:00:00 2001 From: Amulyam24 Date: Wed, 11 Feb 2026 16:09:37 +0530 Subject: [PATCH 4/4] runtime-rs: align memory size with desired block size on ppc64le MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit couldn't initialise QMP: Connection reset by peer (os error 104) Caused by: Connection reset by peer (os error 104) qemu stderr: "qemu-system-ppc64: Maximum memory size 0x80000000 is not aligned to 256 MiB” When the default max memory was assigned according to the available host memory, it failed with the above error Align the memory values with the block size of 256 MB on ppc64le. Signed-off-by: Amulyam24 --- src/libs/kata-types/Cargo.toml | 1 + .../kata-types/src/config/hypervisor/mod.rs | 143 ++++++++++++++++++ 2 files changed, 144 insertions(+) diff --git a/src/libs/kata-types/Cargo.toml b/src/libs/kata-types/Cargo.toml index 185b70c05b..012b55109e 100644 --- a/src/libs/kata-types/Cargo.toml +++ b/src/libs/kata-types/Cargo.toml @@ -41,6 +41,7 @@ sysctl = "0.7.1" tempfile = "3.19.1" test-utils = { path = "../test-utils" } nix = "0.26.4" +rstest = "0.18" [features] default = [] diff --git a/src/libs/kata-types/src/config/hypervisor/mod.rs b/src/libs/kata-types/src/config/hypervisor/mod.rs index 6284103102..72839104bc 100644 --- a/src/libs/kata-types/src/config/hypervisor/mod.rs +++ b/src/libs/kata-types/src/config/hypervisor/mod.rs @@ -1077,6 +1077,81 @@ impl MemoryInfo { if self.default_maxmemory == 0 || u64::from(self.default_maxmemory) > host_memory { self.default_maxmemory = host_memory as u32; } + + // Apply PowerPC64 memory alignment + #[cfg(all(target_arch = "powerpc64", target_endian = "little"))] + self.adjust_ppc64_memory_alignment()?; + + Ok(()) + } + + /// Adjusts memory values for PowerPC64 little-endian systems to meet + /// QEMU's 256MB block size alignment requirement. + /// + /// Ensures default_memory is at least 1024MB and both default_memory + /// and default_maxmemory are aligned to 256MB boundaries. + /// Returns an error if aligned values would be equal. + #[cfg(all(target_arch = "powerpc64", target_endian = "little"))] + fn adjust_ppc64_memory_alignment(&mut self) -> Result<()> { + const PPC64_MEM_BLOCK_SIZE: u64 = 256; + const MIN_MEMORY_MB: u64 = 1024; + + fn align_memory(value: u64) -> u64 { + (value / PPC64_MEM_BLOCK_SIZE) * PPC64_MEM_BLOCK_SIZE + } + + let mut mem_size = u64::from(self.default_memory); + let max_mem_size = u64::from(self.default_maxmemory); + + // Ensure minimum memory size + if mem_size < MIN_MEMORY_MB { + info!( + sl!(), + "PowerPC: Increasing default_memory from {}MB to minimum {}MB", + mem_size, + MIN_MEMORY_MB + ); + mem_size = MIN_MEMORY_MB; + } + + // Align both values to 256MB boundaries + let aligned_mem = align_memory(mem_size); + let aligned_max_mem = align_memory(max_mem_size); + + if aligned_mem != mem_size { + info!( + sl!(), + "PowerPC: Aligned default_memory from {}MB to {}MB", mem_size, aligned_mem + ); + } + + if aligned_max_mem != max_mem_size { + info!( + sl!(), + "PowerPC: Aligned default_maxmemory from {}MB to {}MB", + max_mem_size, + aligned_max_mem + ); + } + + // Check if aligned values are equal + if aligned_max_mem != 0 && aligned_max_mem <= aligned_mem { + return Err(std::io::Error::other(format!( + "PowerPC: default_maxmemory ({}MB) <= default_memory ({}MB) after alignment. \ + Requires maxmemory > memory. Please increase default_maxmemory.", + aligned_max_mem, aligned_mem + ))); + } + info!( + sl!(), + "PowerPC: Memory alignment applied - memory: {}MB, max_memory: {}MB", + aligned_mem, + aligned_max_mem + ); + + self.default_memory = aligned_mem as u32; + self.default_maxmemory = aligned_max_mem as u32; + Ok(()) } @@ -1948,4 +2023,72 @@ mod tests { ); } } + + #[cfg(all(target_arch = "powerpc64", target_endian = "little"))] + use rstest::rstest; + + #[rstest] + #[case::memory_below_minimum(512, 2048, 1024, 2048)] + #[case::already_aligned(1024, 2048, 1024, 2048)] + #[case::unaligned_rounds_down(1100, 2100, 1024, 2048)] + #[cfg(all(target_arch = "powerpc64", target_endian = "little"))] + fn test_adjust_ppc64_memory_alignment_success( + #[case] input_memory: u32, + #[case] input_maxmemory: u32, + #[case] expected_memory: u32, + #[case] expected_maxmemory: u32, + ) { + let mut mem = MemoryInfo { + default_memory: input_memory, + default_maxmemory: input_maxmemory, + ..Default::default() + }; + + let result = mem.adjust_ppc64_memory_alignment(); + assert!( + result.is_ok(), + "Expected success but got error: {:?}", + result.err() + ); + assert_eq!( + mem.default_memory, expected_memory, + "Memory not aligned correctly" + ); + assert_eq!( + mem.default_maxmemory, expected_maxmemory, + "Max memory not aligned correctly" + ); + } + + #[rstest] + #[case::equal_after_alignment(1024, 1100, "Requires maxmemory > memory")] + #[case::maxmemory_less_than_memory(2048, 1500, "Requires maxmemory > memory")] + #[cfg(all(target_arch = "powerpc64", target_endian = "little"))] + fn test_adjust_ppc64_memory_alignment_errors( + #[case] input_memory: u32, + #[case] input_maxmemory: u32, + #[case] expected_error_msg: &str, + ) { + let mut mem = MemoryInfo { + default_memory: input_memory, + default_maxmemory: input_maxmemory, + ..Default::default() + }; + + let result = mem.adjust_ppc64_memory_alignment(); + assert!( + result.is_err(), + "Expected error but got success for memory={}, maxmemory={}", + input_memory, + input_maxmemory + ); + + let error_msg = result.unwrap_err().to_string(); + assert!( + error_msg.contains(expected_error_msg), + "Error message '{}' does not contain expected text '{}'", + error_msg, + expected_error_msg + ); + } }