From: Oliver Upton <oliver.upton@linux.dev>
To: kvmarm@lists.linux.dev
Cc: kvm@vger.kernel.org, Will Deacon <will@kernel.org>,
Julien Thierry <julien.thierry.kdev@gmail.com>,
Marc Zyngier <maz@kernel.org>,
Alexandru Elisei <alexandru.elisei@arm.com>,
Andre Przywara <andre.przywara@arm.com>,
Oliver Upton <oliver.upton@linux.dev>
Subject: [PATCH kvmtool v2 3/9] arm64: Combine kvm.c
Date: Fri, 4 Apr 2025 09:52:26 -0700 [thread overview]
Message-ID: <20250404165233.3205127-4-oliver.upton@linux.dev> (raw)
In-Reply-To: <20250404165233.3205127-1-oliver.upton@linux.dev>
Glue together the ARM common and previously arm64-specific bits into one
source file.
Acked-by: Marc Zyngier <maz@kernel.org>
Reviewed-by: Alexandru Elisei <alexandru.elisei@arm.com>
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
Makefile | 1 -
arm/aarch64/include/kvm/kvm-arch.h | 22 ---
arm/aarch64/kvm.c | 212 ---------------------
arm/include/{arm-common => kvm}/kvm-arch.h | 6 +-
arm/kvm.c | 207 ++++++++++++++++++++
5 files changed, 212 insertions(+), 236 deletions(-)
delete mode 100644 arm/aarch64/include/kvm/kvm-arch.h
delete mode 100644 arm/aarch64/kvm.c
rename arm/include/{arm-common => kvm}/kvm-arch.h (97%)
diff --git a/Makefile b/Makefile
index cf50cf7..72027e0 100644
--- a/Makefile
+++ b/Makefile
@@ -180,7 +180,6 @@ ifeq ($(ARCH), arm64)
OBJS += hw/serial.o
OBJS += arm/arm-cpu.o
OBJS += arm/aarch64/kvm-cpu.o
- OBJS += arm/aarch64/kvm.o
OBJS += arm/pvtime.o
OBJS += arm/pmu.o
ARCH_INCLUDE := arm/include
diff --git a/arm/aarch64/include/kvm/kvm-arch.h b/arm/aarch64/include/kvm/kvm-arch.h
deleted file mode 100644
index 2d1a4ed..0000000
--- a/arm/aarch64/include/kvm/kvm-arch.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef KVM__KVM_ARCH_H
-#define KVM__KVM_ARCH_H
-
-#include <linux/sizes.h>
-
-struct kvm;
-void kvm__arch_read_kernel_header(struct kvm *kvm, int fd);
-unsigned long long kvm__arch_get_kern_offset(struct kvm *kvm);
-u64 kvm__arch_get_kernel_size(struct kvm *kvm);
-
-u64 kvm__arch_get_payload_region_size(struct kvm *kvm);
-
-int kvm__arch_get_ipa_limit(struct kvm *kvm);
-void kvm__arch_enable_mte(struct kvm *kvm);
-
-#define MAX_PAGE_SIZE SZ_64K
-
-#define ARCH_HAS_CFG_RAM_ADDRESS 1
-
-#include "arm-common/kvm-arch.h"
-
-#endif /* KVM__KVM_ARCH_H */
diff --git a/arm/aarch64/kvm.c b/arm/aarch64/kvm.c
deleted file mode 100644
index 98b2437..0000000
--- a/arm/aarch64/kvm.c
+++ /dev/null
@@ -1,212 +0,0 @@
-#include "kvm/kvm.h"
-
-#include <asm/image.h>
-
-#include <linux/byteorder.h>
-#include <linux/cpumask.h>
-#include <linux/sizes.h>
-
-#include <kvm/util.h>
-
-static struct arm64_image_header *kernel_header;
-
-int vcpu_affinity_parser(const struct option *opt, const char *arg, int unset)
-{
- struct kvm *kvm = opt->ptr;
- const char *cpulist = arg;
- cpumask_t *cpumask;
- int cpu, ret;
-
- kvm->cfg.arch.vcpu_affinity = cpulist;
-
- cpumask = calloc(1, cpumask_size());
- if (!cpumask)
- die_perror("calloc");
-
- ret = cpulist_parse(cpulist, cpumask);
- if (ret) {
- free(cpumask);
- return ret;
- }
-
- kvm->arch.vcpu_affinity_cpuset = CPU_ALLOC(NR_CPUS);
- if (!kvm->arch.vcpu_affinity_cpuset)
- die_perror("CPU_ALLOC");
- CPU_ZERO_S(CPU_ALLOC_SIZE(NR_CPUS), kvm->arch.vcpu_affinity_cpuset);
-
- for_each_cpu(cpu, cpumask)
- CPU_SET(cpu, kvm->arch.vcpu_affinity_cpuset);
-
- return 0;
-}
-
-void kvm__arch_validate_cfg(struct kvm *kvm)
-{
-
- if (kvm->cfg.ram_addr < ARM_MEMORY_AREA) {
- die("RAM address is below the I/O region ending at %luGB",
- ARM_MEMORY_AREA >> 30);
- }
-
- if (kvm->cfg.arch.aarch32_guest &&
- kvm->cfg.ram_addr + kvm->cfg.ram_size > SZ_4G) {
- die("RAM extends above 4GB");
- }
-}
-
-u64 kvm__arch_default_ram_address(void)
-{
- return ARM_MEMORY_AREA;
-}
-
-void kvm__arch_read_kernel_header(struct kvm *kvm, int fd)
-{
- const char *debug_str;
- off_t cur_offset;
- ssize_t size;
-
- if (kvm->cfg.arch.aarch32_guest)
- return;
-
- kernel_header = malloc(sizeof(*kernel_header));
- if (!kernel_header)
- return;
-
- cur_offset = lseek(fd, 0, SEEK_CUR);
- if (cur_offset == (off_t)-1 || lseek(fd, 0, SEEK_SET) == (off_t)-1) {
- debug_str = "Failed to seek in kernel image file";
- goto fail;
- }
-
- size = xread(fd, kernel_header, sizeof(*kernel_header));
- if (size < 0 || (size_t)size < sizeof(*kernel_header))
- die("Failed to read kernel image header");
-
- lseek(fd, cur_offset, SEEK_SET);
-
- if (memcmp(&kernel_header->magic, ARM64_IMAGE_MAGIC, sizeof(kernel_header->magic))) {
- debug_str = "Kernel image magic not matching";
- kernel_header = NULL;
- goto fail;
- }
-
- return;
-
-fail:
- pr_debug("%s, using defaults", debug_str);
-}
-
-/*
- * Return the TEXT_OFFSET value that the guest kernel expects. Note
- * that pre-3.17 kernels expose this value using the native endianness
- * instead of Little-Endian. BE kernels of this vintage may fail to
- * boot. See Documentation/arm64/booting.rst in your local kernel tree.
- */
-unsigned long long kvm__arch_get_kern_offset(struct kvm *kvm)
-{
- const char *debug_str;
-
- /* the 32bit kernel offset is a well known value */
- if (kvm->cfg.arch.aarch32_guest)
- return 0x8000;
-
- if (!kernel_header) {
- debug_str = "Kernel header is missing";
- goto default_offset;
- }
-
- if (!le64_to_cpu(kernel_header->image_size)) {
- debug_str = "Image size is 0";
- goto default_offset;
- }
-
- return le64_to_cpu(kernel_header->text_offset);
-
-default_offset:
- pr_debug("%s, assuming TEXT_OFFSET to be 0x80000", debug_str);
- return 0x80000;
-}
-
-u64 kvm__arch_get_kernel_size(struct kvm *kvm)
-{
- if (kvm->cfg.arch.aarch32_guest || !kernel_header)
- return 0;
-
- return le64_to_cpu(kernel_header->image_size);
-}
-
-u64 kvm__arch_get_payload_region_size(struct kvm *kvm)
-{
- if (kvm->cfg.arch.aarch32_guest)
- return SZ_256M;
-
- return SZ_512M;
-}
-
-int kvm__arch_get_ipa_limit(struct kvm *kvm)
-{
- int ret;
-
- ret = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_ARM_VM_IPA_SIZE);
- if (ret <= 0)
- ret = 0;
-
- return ret;
-}
-
-int kvm__get_vm_type(struct kvm *kvm)
-{
- unsigned int ipa_bits, max_ipa_bits;
- unsigned long max_ipa;
-
- /* If we're running on an old kernel, use 0 as the VM type */
- max_ipa_bits = kvm__arch_get_ipa_limit(kvm);
- if (!max_ipa_bits)
- return 0;
-
- /* Otherwise, compute the minimal required IPA size */
- max_ipa = kvm->cfg.ram_addr + kvm->cfg.ram_size - 1;
- ipa_bits = max(32, fls_long(max_ipa));
- pr_debug("max_ipa %lx ipa_bits %d max_ipa_bits %d",
- max_ipa, ipa_bits, max_ipa_bits);
-
- if (ipa_bits > max_ipa_bits)
- die("Memory too large for this system (needs %d bits, %d available)", ipa_bits, max_ipa_bits);
-
- return KVM_VM_TYPE_ARM_IPA_SIZE(ipa_bits);
-}
-
-void kvm__arch_enable_mte(struct kvm *kvm)
-{
- struct kvm_enable_cap cap = {
- .cap = KVM_CAP_ARM_MTE,
- };
-
- if (kvm->cfg.arch.aarch32_guest) {
- pr_debug("MTE is incompatible with AArch32");
- return;
- }
-
- if (kvm->cfg.arch.mte_disabled) {
- pr_debug("MTE disabled by user");
- return;
- }
-
- if (!kvm__supports_extension(kvm, KVM_CAP_ARM_MTE)) {
- pr_debug("MTE capability not available");
- return;
- }
-
- if (ioctl(kvm->vm_fd, KVM_ENABLE_CAP, &cap))
- die_perror("KVM_ENABLE_CAP(KVM_CAP_ARM_MTE)");
-
- pr_debug("MTE capability enabled");
-}
-
-static int kvm__arch_free_kernel_header(struct kvm *kvm)
-{
- free(kernel_header);
-
- return 0;
-}
-late_exit(kvm__arch_free_kernel_header);
diff --git a/arm/include/arm-common/kvm-arch.h b/arm/include/kvm/kvm-arch.h
similarity index 97%
rename from arm/include/arm-common/kvm-arch.h
rename to arm/include/kvm/kvm-arch.h
index 60eec02..b097186 100644
--- a/arm/include/arm-common/kvm-arch.h
+++ b/arm/include/kvm/kvm-arch.h
@@ -82,7 +82,11 @@
#define VIRTIO_RING_ENDIAN (VIRTIO_ENDIAN_LE | VIRTIO_ENDIAN_BE)
-#define ARCH_HAS_PCI_EXP 1
+#define ARCH_HAS_PCI_EXP 1
+#define ARCH_HAS_CFG_RAM_ADDRESS 1
+
+#define MAX_PAGE_SIZE SZ_64K
+
static inline bool arm_addr_in_ioport_region(u64 phys_addr)
{
diff --git a/arm/kvm.c b/arm/kvm.c
index cc0cc4f..11c7a16 100644
--- a/arm/kvm.c
+++ b/arm/kvm.c
@@ -7,10 +7,16 @@
#include "arm-common/gic.h"
+#include <linux/byteorder.h>
+#include <linux/cpumask.h>
#include <linux/kernel.h>
#include <linux/kvm.h>
#include <linux/sizes.h>
+#include <asm/image.h>
+
+static struct arm64_image_header *kernel_header;
+
struct kvm_ext kvm_req_ext[] = {
{ DEFINE_KVM_EXT(KVM_CAP_IRQCHIP) },
{ DEFINE_KVM_EXT(KVM_CAP_ONE_REG) },
@@ -87,6 +93,33 @@ void kvm__arch_set_cmdline(char *cmdline, bool video)
{
}
+static void kvm__arch_enable_mte(struct kvm *kvm)
+{
+ struct kvm_enable_cap cap = {
+ .cap = KVM_CAP_ARM_MTE,
+ };
+
+ if (kvm->cfg.arch.aarch32_guest) {
+ pr_debug("MTE is incompatible with AArch32");
+ return;
+ }
+
+ if (kvm->cfg.arch.mte_disabled) {
+ pr_debug("MTE disabled by user");
+ return;
+ }
+
+ if (!kvm__supports_extension(kvm, KVM_CAP_ARM_MTE)) {
+ pr_debug("MTE capability not available");
+ return;
+ }
+
+ if (ioctl(kvm->vm_fd, KVM_ENABLE_CAP, &cap))
+ die_perror("KVM_ENABLE_CAP(KVM_CAP_ARM_MTE)");
+
+ pr_debug("MTE capability enabled");
+}
+
void kvm__arch_init(struct kvm *kvm)
{
/* Create the virtual GIC. */
@@ -96,6 +129,90 @@ void kvm__arch_init(struct kvm *kvm)
kvm__arch_enable_mte(kvm);
}
+static u64 kvm__arch_get_payload_region_size(struct kvm *kvm)
+{
+ if (kvm->cfg.arch.aarch32_guest)
+ return SZ_256M;
+
+ return SZ_512M;
+}
+
+/*
+ * Return the TEXT_OFFSET value that the guest kernel expects. Note
+ * that pre-3.17 kernels expose this value using the native endianness
+ * instead of Little-Endian. BE kernels of this vintage may fail to
+ * boot. See Documentation/arm64/booting.rst in your local kernel tree.
+ */
+static u64 kvm__arch_get_kern_offset(struct kvm *kvm)
+{
+ const char *debug_str;
+
+ /* the 32bit kernel offset is a well known value */
+ if (kvm->cfg.arch.aarch32_guest)
+ return 0x8000;
+
+ if (!kernel_header) {
+ debug_str = "Kernel header is missing";
+ goto default_offset;
+ }
+
+ if (!le64_to_cpu(kernel_header->image_size)) {
+ debug_str = "Image size is 0";
+ goto default_offset;
+ }
+
+ return le64_to_cpu(kernel_header->text_offset);
+
+default_offset:
+ pr_debug("%s, assuming TEXT_OFFSET to be 0x80000", debug_str);
+ return 0x80000;
+}
+
+static void kvm__arch_read_kernel_header(struct kvm *kvm, int fd)
+{
+ const char *debug_str;
+ off_t cur_offset;
+ ssize_t size;
+
+ if (kvm->cfg.arch.aarch32_guest)
+ return;
+
+ kernel_header = malloc(sizeof(*kernel_header));
+ if (!kernel_header)
+ return;
+
+ cur_offset = lseek(fd, 0, SEEK_CUR);
+ if (cur_offset == (off_t)-1 || lseek(fd, 0, SEEK_SET) == (off_t)-1) {
+ debug_str = "Failed to seek in kernel image file";
+ goto fail;
+ }
+
+ size = xread(fd, kernel_header, sizeof(*kernel_header));
+ if (size < 0 || (size_t)size < sizeof(*kernel_header))
+ die("Failed to read kernel image header");
+
+ lseek(fd, cur_offset, SEEK_SET);
+
+ if (memcmp(&kernel_header->magic, ARM64_IMAGE_MAGIC, sizeof(kernel_header->magic))) {
+ debug_str = "Kernel image magic not matching";
+ kernel_header = NULL;
+ goto fail;
+ }
+
+ return;
+
+fail:
+ pr_debug("%s, using defaults", debug_str);
+}
+
+static u64 kvm__arch_get_kernel_size(struct kvm *kvm)
+{
+ if (kvm->cfg.arch.aarch32_guest || !kernel_header)
+ return 0;
+
+ return le64_to_cpu(kernel_header->image_size);
+}
+
#define FDT_ALIGN SZ_2M
#define INITRD_ALIGN 4
bool kvm__arch_load_kernel_image(struct kvm *kvm, int fd_kernel, int fd_initrd,
@@ -264,3 +381,93 @@ int kvm__arch_setup_firmware(struct kvm *kvm)
{
return 0;
}
+
+int vcpu_affinity_parser(const struct option *opt, const char *arg, int unset)
+{
+ struct kvm *kvm = opt->ptr;
+ const char *cpulist = arg;
+ cpumask_t *cpumask;
+ int cpu, ret;
+
+ kvm->cfg.arch.vcpu_affinity = cpulist;
+
+ cpumask = calloc(1, cpumask_size());
+ if (!cpumask)
+ die_perror("calloc");
+
+ ret = cpulist_parse(cpulist, cpumask);
+ if (ret) {
+ free(cpumask);
+ return ret;
+ }
+
+ kvm->arch.vcpu_affinity_cpuset = CPU_ALLOC(NR_CPUS);
+ if (!kvm->arch.vcpu_affinity_cpuset)
+ die_perror("CPU_ALLOC");
+ CPU_ZERO_S(CPU_ALLOC_SIZE(NR_CPUS), kvm->arch.vcpu_affinity_cpuset);
+
+ for_each_cpu(cpu, cpumask)
+ CPU_SET(cpu, kvm->arch.vcpu_affinity_cpuset);
+
+ return 0;
+}
+
+void kvm__arch_validate_cfg(struct kvm *kvm)
+{
+
+ if (kvm->cfg.ram_addr < ARM_MEMORY_AREA) {
+ die("RAM address is below the I/O region ending at %luGB",
+ ARM_MEMORY_AREA >> 30);
+ }
+
+ if (kvm->cfg.arch.aarch32_guest &&
+ kvm->cfg.ram_addr + kvm->cfg.ram_size > SZ_4G) {
+ die("RAM extends above 4GB");
+ }
+}
+
+u64 kvm__arch_default_ram_address(void)
+{
+ return ARM_MEMORY_AREA;
+}
+
+static int kvm__arch_get_ipa_limit(struct kvm *kvm)
+{
+ int ret;
+
+ ret = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_ARM_VM_IPA_SIZE);
+ if (ret <= 0)
+ ret = 0;
+
+ return ret;
+}
+
+int kvm__get_vm_type(struct kvm *kvm)
+{
+ unsigned int ipa_bits, max_ipa_bits;
+ unsigned long max_ipa;
+
+ /* If we're running on an old kernel, use 0 as the VM type */
+ max_ipa_bits = kvm__arch_get_ipa_limit(kvm);
+ if (!max_ipa_bits)
+ return 0;
+
+ /* Otherwise, compute the minimal required IPA size */
+ max_ipa = kvm->cfg.ram_addr + kvm->cfg.ram_size - 1;
+ ipa_bits = max(32, fls_long(max_ipa));
+ pr_debug("max_ipa %lx ipa_bits %d max_ipa_bits %d",
+ max_ipa, ipa_bits, max_ipa_bits);
+
+ if (ipa_bits > max_ipa_bits)
+ die("Memory too large for this system (needs %d bits, %d available)", ipa_bits, max_ipa_bits);
+
+ return KVM_VM_TYPE_ARM_IPA_SIZE(ipa_bits);
+}
+
+static int kvm__arch_free_kernel_header(struct kvm *kvm)
+{
+ free(kernel_header);
+
+ return 0;
+}
+late_exit(kvm__arch_free_kernel_header);
--
2.39.5
next prev parent reply other threads:[~2025-04-04 16:52 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-04 16:52 [PATCH kvmtool v2 0/9] arm: Drop support for 32-bit kvmtool Oliver Upton
2025-04-04 16:52 ` [PATCH kvmtool v2 1/9] Drop support for 32-bit arm Oliver Upton
2025-04-04 16:52 ` [PATCH kvmtool v2 2/9] arm64: Move arm64-only features into main directory Oliver Upton
2025-04-04 16:52 ` Oliver Upton [this message]
2025-04-04 16:52 ` [PATCH kvmtool v2 4/9] arm64: Merge kvm-cpu.c Oliver Upton
2025-04-04 16:52 ` [PATCH kvmtool v2 5/9] arm64: Combine kvm-config-arch.h Oliver Upton
2025-04-04 16:52 ` [PATCH kvmtool v2 6/9] arm64: Move remaining kvm/* headers Oliver Upton
2025-04-04 16:52 ` [PATCH kvmtool v2 7/9] arm64: Move asm headers Oliver Upton
2025-04-04 16:52 ` [PATCH kvmtool v2 8/9] arm64: Rename top-level directory Oliver Upton
2025-04-04 16:52 ` [PATCH kvmtool v2 9/9] arm64: Get rid of the 'arm-common' include directory Oliver Upton
2025-04-04 16:52 ` [PATCH v4 00/19] KVM: arm64: Debug cleanups Oliver Upton
2025-04-04 16:55 ` Oliver Upton
2025-04-17 14:27 ` [PATCH kvmtool v2 0/9] arm: Drop support for 32-bit kvmtool Will Deacon
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250404165233.3205127-4-oliver.upton@linux.dev \
--to=oliver.upton@linux.dev \
--cc=alexandru.elisei@arm.com \
--cc=andre.przywara@arm.com \
--cc=julien.thierry.kdev@gmail.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=maz@kernel.org \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.