Recent changes made to Linux 5.8 have outlined that kvmtool
hardcodes the text offset instead of reading it from the arm64
image itself.
To address this, import the image header structure into kvmtool
and do the right thing. 32bit guests are still loaded to their
usual locations.
While we're at it, check the image magic and default to the text
offset to be 0x8 when image_size is 0, as described in the
kernel's booting.rst document.
Cc: Alexandru Elisei
Reported-by: Ard Biesheuvel
Signed-off-by: Marc Zyngier
---
Notes:
v2: Check magic, assume offset to be 0x8000 if image_size is 0.
Makefile | 1 +
arm/aarch32/include/kvm/kvm-arch.h | 2 +-
arm/aarch64/include/asm/image.h| 59 ++
arm/aarch64/include/kvm/kvm-arch.h | 5 +--
arm/aarch64/kvm.c | 43 ++
arm/kvm.c | 2 +-
6 files changed, 107 insertions(+), 5 deletions(-)
create mode 100644 arm/aarch64/include/asm/image.h
create mode 100644 arm/aarch64/kvm.c
diff --git a/Makefile b/Makefile
index d27ff38..35bb118 100644
--- a/Makefile
+++ b/Makefile
@@ -179,6 +179,7 @@ ifeq ($(ARCH), arm64)
OBJS+= $(OBJS_ARM_COMMON)
OBJS+= arm/aarch64/arm-cpu.o
OBJS+= arm/aarch64/kvm-cpu.o
+ OBJS+= arm/aarch64/kvm.o
ARCH_INCLUDE:= $(HDRS_ARM_COMMON)
ARCH_INCLUDE+= -Iarm/aarch64/include
diff --git a/arm/aarch32/include/kvm/kvm-arch.h
b/arm/aarch32/include/kvm/kvm-arch.h
index cd31e72..a772bb1 100644
--- a/arm/aarch32/include/kvm/kvm-arch.h
+++ b/arm/aarch32/include/kvm/kvm-arch.h
@@ -1,7 +1,7 @@
#ifndef KVM__KVM_ARCH_H
#define KVM__KVM_ARCH_H
-#define ARM_KERN_OFFSET(...) 0x8000
+#define kvm__arch_get_kern_offset(...) 0x8000
#define ARM_MAX_MEMORY(...)ARM_LOMAP_MAX_MEMORY
diff --git a/arm/aarch64/include/asm/image.h b/arm/aarch64/include/asm/image.h
new file mode 100644
index 000..c2b1321
--- /dev/null
+++ b/arm/aarch64/include/asm/image.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASM_IMAGE_H
+#define __ASM_IMAGE_H
+
+#define ARM64_IMAGE_MAGIC "ARM\x64"
+
+#define ARM64_IMAGE_FLAG_BE_SHIFT 0
+#define ARM64_IMAGE_FLAG_PAGE_SIZE_SHIFT (ARM64_IMAGE_FLAG_BE_SHIFT + 1)
+#define ARM64_IMAGE_FLAG_PHYS_BASE_SHIFT \
+ (ARM64_IMAGE_FLAG_PAGE_SIZE_SHIFT + 2)
+#define ARM64_IMAGE_FLAG_BE_MASK 0x1
+#define ARM64_IMAGE_FLAG_PAGE_SIZE_MASK0x3
+#define ARM64_IMAGE_FLAG_PHYS_BASE_MASK0x1
+
+#define ARM64_IMAGE_FLAG_LE0
+#define ARM64_IMAGE_FLAG_BE1
+#define ARM64_IMAGE_FLAG_PAGE_SIZE_4K 1
+#define ARM64_IMAGE_FLAG_PAGE_SIZE_16K 2
+#define ARM64_IMAGE_FLAG_PAGE_SIZE_64K 3
+#define ARM64_IMAGE_FLAG_PHYS_BASE 1
+
+#ifndef __ASSEMBLY__
+
+#define arm64_image_flag_field(flags, field) \
+ (((flags) >> field##_SHIFT) & field##_MASK)
+
+/*
+ * struct arm64_image_header - arm64 kernel image header
+ * See Documentation/arm64/booting.rst for details
+ *
+ * @code0: Executable code, or
+ * @mz_header alternatively used for part of MZ header
+ * @code1: Executable code
+ * @text_offset: Image load offset
+ * @image_size:Effective Image size
+ * @flags: kernel flags
+ * @reserved: reserved
+ * @magic: Magic number
+ * @reserved5: reserved, or
+ * @pe_header: alternatively used for PE COFF offset
+ */
+
+struct arm64_image_header {
+ __le32 code0;
+ __le32 code1;
+ __le64 text_offset;
+ __le64 image_size;
+ __le64 flags;
+ __le64 res2;
+ __le64 res3;
+ __le64 res4;
+ __le32 magic;
+ __le32 res5;
+};
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_IMAGE_H */
diff --git a/arm/aarch64/include/kvm/kvm-arch.h
b/arm/aarch64/include/kvm/kvm-arch.h
index 9de623a..55ef8ed 100644
--- a/arm/aarch64/include/kvm/kvm-arch.h
+++ b/arm/aarch64/include/kvm/kvm-arch.h
@@ -1,9 +1,8 @@
#ifndef KVM__KVM_ARCH_H
#define KVM__KVM_ARCH_H
-#define ARM_KERN_OFFSET(kvm) ((kvm)->cfg.arch.aarch32_guest ? \
- 0x8000 : \
- 0x8)
+struct kvm;
+unsigned long long kvm__arch_get_kern_offset(struct kvm *kvm, int fd);
#define ARM_MAX_MEMORY(kvm)((kvm)->cfg.arch.aarch32_guest ? \
ARM_LOMAP_MAX_MEMORY: \
diff --git a/arm/aarch64/kvm.c b/arm/aarch64/kvm.c
new file mode 100644
index 000..a46d438
--- /dev/null
+++ b/arm/aarch64/kvm.c
@@ -0,0 +1,43 @@
+#include "kvm/kvm.h"
+
+#include
+
+#include
+
+/*
+ * Return the TEXT_OFFSET value that the guest kernel expects. Note
+ * that pre-3.17 kernels expose thi