* [PATCH v8 01/29] KVM: Introduce file_to_kvm_<arch>() infrastructure
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 13:45 ` sashiko-bot
2026-09-18 13:30 ` [PATCH v8 02/29] KVM: Add file back-pointer to struct kvm Steffen Eiden
` (28 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Add a macro mechanism that generates an opt-in and arch-namespaced
file_to_kvm_<arch>() to convert a file reference to a kvm object if the
file handle represents a kvm handle.
Activate for x86 and for s390 (native KVM only).
Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/include/asm/kvm_host_s390.h | 2 ++
arch/x86/include/asm/kvm_host.h | 2 ++
arch/x86/kvm/Makefile | 1 +
include/linux/kvm_host.h | 12 ++++++++++++
virt/kvm/kvm_main.c | 11 +++++++++++
5 files changed, 28 insertions(+)
diff --git a/arch/s390/include/asm/kvm_host_s390.h b/arch/s390/include/asm/kvm_host_s390.h
index cd692f8fb764..8a7eed5847e1 100644
--- a/arch/s390/include/asm/kvm_host_s390.h
+++ b/arch/s390/include/asm/kvm_host_s390.h
@@ -27,6 +27,8 @@
#include <asm/isc.h>
#include <asm/guarded_storage.h>
+#define kvm_file_to_kvm_arch s390
+
#define KVM_HAVE_MMU_RWLOCK
#define KVM_MAX_VCPUS 255
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 683bb8bf43a9..e460073ff176 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -44,6 +44,8 @@
#include <hyperv/hvhdk.h>
+#define kvm_file_to_kvm_arch x86
+
#define __KVM_HAVE_ARCH_VCPU_DEBUGFS
/*
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index 0474604ab8a1..e6d395ede9e2 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -61,6 +61,7 @@ exports_grep_trailer := --include='*.[ch]' -nrw $(srctree)/virt/kvm $(srctree)/a
-e kvm_page_track_unregister_notifier \
-e kvm_write_track_add_gfn \
-e kvm_write_track_remove_gfn \
+ -e kvm_file_to_kvm_fn \
-e kvm_get_kvm \
-e kvm_get_kvm_safe \
-e kvm_put_kvm
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 03bfc92864b6..a1bf6d4a8f46 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1082,6 +1082,18 @@ void kvm_get_kvm(struct kvm *kvm);
bool kvm_get_kvm_safe(struct kvm *kvm);
void kvm_put_kvm(struct kvm *kvm);
bool file_is_kvm(struct file *file);
+
+/*
+ * Architectures define kvm_file_to_kvm_arch to <arch>
+ * to get a typed, arch-namespaced helper:
+ *
+ * static inline struct kvm *file_to_kvm_<arch>(struct file *file)
+ */
+#ifdef kvm_file_to_kvm_arch
+#define kvm_file_to_kvm_fn CONCATENATE(file_to_kvm_, kvm_file_to_kvm_arch)
+struct kvm *kvm_file_to_kvm_fn(struct file *file);
+#endif /* kvm_file_to_kvm_arch */
+
void kvm_put_kvm_no_destroy(struct kvm *kvm);
static inline struct kvm_memslots *__kvm_memslots(struct kvm *kvm, int as_id)
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 65eb26a0520d..0172ca94f82e 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -5496,6 +5496,17 @@ bool file_is_kvm(struct file *file)
}
EXPORT_SYMBOL_FOR_KVM_INTERNAL(file_is_kvm);
+#ifdef kvm_file_to_kvm_arch
+struct kvm *kvm_file_to_kvm_fn(struct file *file)
+{
+ if (!file || file->f_op != &kvm_vm_fops)
+ return NULL;
+
+ return file->private_data;
+}
+EXPORT_SYMBOL_GPL(kvm_file_to_kvm_fn);
+#endif
+
static int kvm_dev_ioctl_create_vm(unsigned long type)
{
char fdname[ITOA_MAX_LEN + 1];
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 01/29] KVM: Introduce file_to_kvm_<arch>() infrastructure
2026-09-18 13:30 ` [PATCH v8 01/29] KVM: Introduce file_to_kvm_<arch>() infrastructure Steffen Eiden
@ 2026-09-18 13:45 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 13:45 UTC (permalink / raw)
To: Steffen Eiden
Cc: Heiko Carstens, Oliver Upton, kvm, linux-s390, Marc Zyngier,
Alexander Gordeev, Christian Borntraeger, kvmarm, Vasily Gorbik
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] kvm: comment incorrectly documents file_to_kvm_<arch> as static inline
--
commit 75f01ce5173332e48e8ba4fd2b83b6d3584388c4
Author: Steffen Eiden <seiden@linux.ibm.com>
KVM: Introduce file_to_kvm_<arch>() infrastructure
Add a macro mechanism that generates an opt-in and arch-namespaced
file_to_kvm_<arch>() to convert a file reference to a kvm object if the
file handle represents a kvm handle.
[ ... ]
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 03bfc92864b6e..a1bf6d4a8f460 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -1082,6 +1082,18 @@ void kvm_get_kvm(struct kvm *kvm);
> bool kvm_get_kvm_safe(struct kvm *kvm);
> void kvm_put_kvm(struct kvm *kvm);
> bool file_is_kvm(struct file *file);
> +
> +/*
> + * Architectures define kvm_file_to_kvm_arch to <arch>
> + * to get a typed, arch-namespaced helper:
> + *
> + * static inline struct kvm *file_to_kvm_<arch>(struct file *file)
^^^^^^^^^^^^^
[Severity: Low]
Is this comment accurate in describing the generated function as static
inline?
The code below actually declares an out-of-line exported function rather
than a static inline helper. Could this be misleading to someone reading
the header file who might assume the function is inlined and doesn't incur
function call overhead?
> + */
> +#ifdef kvm_file_to_kvm_arch
> +#define kvm_file_to_kvm_fn CONCATENATE(file_to_kvm_, kvm_file_to_kvm_arch)
> +struct kvm *kvm_file_to_kvm_fn(struct file *file);
> +#endif /* kvm_file_to_kvm_arch */
> +
> void kvm_put_kvm_no_destroy(struct kvm *kvm);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=1
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 02/29] KVM: Add file back-pointer to struct kvm
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
2026-09-18 13:30 ` [PATCH v8 01/29] KVM: Introduce file_to_kvm_<arch>() infrastructure Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 13:56 ` sashiko-bot
2026-09-18 13:30 ` [PATCH v8 03/29] KVM: x86: Use file_to_kvm_x86() in SEV Steffen Eiden
` (27 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Add kvm->file as a no-reference back-pointer to the VM file in struct
kvm. The pointer is set at VM creation time and cleared under
WRITE_ONCE() in kvm_vm_release() before the file is freed.
Callers storing the file must take their own reference.
Co-developed-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
include/linux/kvm_host.h | 6 ++++++
virt/kvm/kvm_main.c | 4 ++++
2 files changed, 10 insertions(+)
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index a1bf6d4a8f46..2b56fb4e8555 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -784,6 +784,12 @@ struct kvm {
* kvm_swap_active_memslots().
*/
struct mutex slots_arch_lock;
+ /*
+ * Back-reference to the VM file for subsystems (e.g., VFIO). Holds no
+ * reference to avoid pinning the VM. Callers storing the file must
+ * take their own reference.
+ */
+ struct file *file;
struct mm_struct *mm; /* userspace tied to this vm */
unsigned long nr_memslot_pages;
/* The two memslot sets - active and inactive (per address space) */
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 0172ca94f82e..bab71d398236 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1352,6 +1352,8 @@ static int kvm_vm_release(struct inode *inode, struct file *filp)
kvm_irqfd_release(kvm);
+ WRITE_ONCE(kvm->file, NULL);
+
kvm_put_kvm(kvm);
return 0;
}
@@ -5532,6 +5534,8 @@ static int kvm_dev_ioctl_create_vm(unsigned long type)
goto put_kvm;
}
+ kvm->file = file;
+
/*
* Don't call kvm_put_kvm anymore at this point; file->f_op is
* already set, with ->release() being kvm_vm_release(). In error
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* [PATCH v8 03/29] KVM: x86: Use file_to_kvm_x86() in SEV
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
2026-09-18 13:30 ` [PATCH v8 01/29] KVM: Introduce file_to_kvm_<arch>() infrastructure Steffen Eiden
2026-09-18 13:30 ` [PATCH v8 02/29] KVM: Add file back-pointer to struct kvm Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 14:02 ` sashiko-bot
2026-09-18 13:30 ` [PATCH v8 04/29] KVM/vfio: Use file-based reference counting for KVM Steffen Eiden
` (26 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Use the new arch-namespaced helper instead of open-coding the file
check and private_data cast separately.
Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/x86/kvm/svm/sev.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 5705723f1f41..6b0eacde4f06 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -2145,10 +2145,10 @@ int sev_vm_move_enc_context_from(struct kvm *kvm, unsigned int source_fd)
if (fd_empty(f))
return -EBADF;
- if (!file_is_kvm(fd_file(f)))
+ source_kvm = file_to_kvm_x86(fd_file(f));
+ if (!source_kvm)
return -EBADF;
- source_kvm = fd_file(f)->private_data;
ret = sev_lock_two_vms(kvm, source_kvm);
if (ret)
return ret;
@@ -2866,10 +2866,10 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
if (fd_empty(f))
return -EBADF;
- if (!file_is_kvm(fd_file(f)))
+ source_kvm = file_to_kvm_x86(fd_file(f));
+ if (!source_kvm)
return -EBADF;
- source_kvm = fd_file(f)->private_data;
ret = sev_lock_two_vms(kvm, source_kvm);
if (ret)
return ret;
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* [PATCH v8 04/29] KVM/vfio: Use file-based reference counting for KVM
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (2 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 03/29] KVM: x86: Use file_to_kvm_x86() in SEV Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 14:26 ` sashiko-bot
2026-09-18 13:30 ` [PATCH v8 05/29] KVM: Restrict kvm_get_kvm/kvm_put_kvm export to internal KVM modules Steffen Eiden
` (25 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Replace manual module reference counting with file-based reference
counting for KVM integration. Previously, VFIO used symbol_get() to
obtain function pointers for kvm_get_kvm_safe() and kvm_put_kvm(),
then manually tracked module references through these symbols. This
approach required storing the put_kvm function pointer in each device
and carefully managing symbol references.
Pass struct file pointers instead of struct kvm pointers throughout the
VFIO-KVM interface, leveraging the kernel's existing file reference
counting via get_file()/get_file_active() and fput(). Convert the x86
page-track API likewise, and update vfio_ap and vfio_pci_zdev to use
file_to_kvm_s390(). This simplifies the code and removes all remaining
externally exported symbols for KVM which would appear twice for when a
second concurrent KVM module is introduced.
Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Co-developed-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Reviewed-by: Jason J. Herne <jjherne@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/x86/include/asm/kvm_page_track.h | 8 ++--
arch/x86/kvm/mmu/page_track.c | 22 +++++++----
drivers/s390/crypto/vfio_ap_ops.c | 20 +++++++---
drivers/vfio/group.c | 11 +++++-
drivers/vfio/pci/vfio_pci_zdev.c | 8 +++-
drivers/vfio/vfio.h | 12 +++---
drivers/vfio/vfio_main.c | 57 +++++++++------------------
include/linux/vfio.h | 5 +--
virt/kvm/vfio.c | 13 ++++--
9 files changed, 84 insertions(+), 72 deletions(-)
diff --git a/arch/x86/include/asm/kvm_page_track.h b/arch/x86/include/asm/kvm_page_track.h
index 3d040741044b..046a25c8fe4f 100644
--- a/arch/x86/include/asm/kvm_page_track.h
+++ b/arch/x86/include/asm/kvm_page_track.h
@@ -44,13 +44,13 @@ struct kvm_page_track_notifier_node {
struct kvm_page_track_notifier_node *node);
};
-int kvm_page_track_register_notifier(struct kvm *kvm,
+int kvm_page_track_register_notifier(struct file *file,
struct kvm_page_track_notifier_node *n);
-void kvm_page_track_unregister_notifier(struct kvm *kvm,
+void kvm_page_track_unregister_notifier(struct file *file,
struct kvm_page_track_notifier_node *n);
-int kvm_write_track_add_gfn(struct kvm *kvm, gfn_t gfn);
-int kvm_write_track_remove_gfn(struct kvm *kvm, gfn_t gfn);
+int kvm_write_track_add_gfn(struct file *file, gfn_t gfn);
+int kvm_write_track_remove_gfn(struct file *file, gfn_t gfn);
#else
/*
* Allow defining a node in a structure even if page tracking is disabled, e.g.
diff --git a/arch/x86/kvm/mmu/page_track.c b/arch/x86/kvm/mmu/page_track.c
index 7e8195a311bb..f12558dfcd81 100644
--- a/arch/x86/kvm/mmu/page_track.c
+++ b/arch/x86/kvm/mmu/page_track.c
@@ -16,6 +16,8 @@
#include <linux/kvm_host.h>
#include <linux/rculist.h>
+#include <asm/kvm_page_track.h>
+
#include "mmu.h"
#include "mmu_internal.h"
#include "page_track.h"
@@ -237,10 +239,11 @@ static int kvm_enable_external_write_tracking(struct kvm *kvm)
* register the notifier so that event interception for the tracked guest
* pages can be received.
*/
-int kvm_page_track_register_notifier(struct kvm *kvm,
+int kvm_page_track_register_notifier(struct file *file,
struct kvm_page_track_notifier_node *n)
{
struct kvm_page_track_notifier_head *head;
+ struct kvm *kvm = file_to_kvm_x86(file);
int r;
if (!kvm || kvm->mm != current->mm)
@@ -252,7 +255,7 @@ int kvm_page_track_register_notifier(struct kvm *kvm,
return r;
}
- kvm_get_kvm(kvm);
+ get_file(file);
head = &kvm->arch.track_notifier_head;
@@ -267,10 +270,11 @@ EXPORT_SYMBOL_GPL(kvm_page_track_register_notifier);
* stop receiving the event interception. It is the opposed operation of
* kvm_page_track_register_notifier().
*/
-void kvm_page_track_unregister_notifier(struct kvm *kvm,
+void kvm_page_track_unregister_notifier(struct file *file,
struct kvm_page_track_notifier_node *n)
{
struct kvm_page_track_notifier_head *head;
+ struct kvm *kvm = file_to_kvm_x86(file);
head = &kvm->arch.track_notifier_head;
@@ -279,7 +283,7 @@ void kvm_page_track_unregister_notifier(struct kvm *kvm,
write_unlock(&kvm->mmu_lock);
synchronize_srcu(&head->track_srcu);
- kvm_put_kvm(kvm);
+ fput(file);
}
EXPORT_SYMBOL_GPL(kvm_page_track_unregister_notifier);
@@ -336,11 +340,12 @@ void kvm_page_track_delete_slot(struct kvm *kvm, struct kvm_memory_slot *slot)
* add guest page to the tracking pool so that corresponding access on that
* page will be intercepted.
*
- * @kvm: the guest instance we are interested in.
+ * @file: the VM file of the guest instance we are interested in.
* @gfn: the guest page.
*/
-int kvm_write_track_add_gfn(struct kvm *kvm, gfn_t gfn)
+int kvm_write_track_add_gfn(struct file *file, gfn_t gfn)
{
+ struct kvm *kvm = file_to_kvm_x86(file);
struct kvm_memory_slot *slot;
int idx;
@@ -366,11 +371,12 @@ EXPORT_SYMBOL_GPL(kvm_write_track_add_gfn);
* remove the guest page from the tracking pool which stops the interception
* of corresponding access on that page.
*
- * @kvm: the guest instance we are interested in.
+ * @file: the VM file of the guest instance we are interested in.
* @gfn: the guest page.
*/
-int kvm_write_track_remove_gfn(struct kvm *kvm, gfn_t gfn)
+int kvm_write_track_remove_gfn(struct file *file, gfn_t gfn)
{
+ struct kvm *kvm = file_to_kvm_x86(file);
struct kvm_memory_slot *slot;
int idx;
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 940c0ff668be..556e643244f2 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -1822,17 +1822,27 @@ static const struct attribute_group *vfio_ap_mdev_attr_groups[] = {
/**
* vfio_ap_mdev_set_kvm - sets all data for @matrix_mdev that are needed
- * to manage AP resources for the guest whose state is represented by @kvm
+ * to manage AP resources for the guest whose state is represented by
+ * @kvm_file
*
* @matrix_mdev: a mediated matrix device
- * @kvm: reference to KVM instance
+ * @kvm_file: the KVM VM file this vfio device is associated with
*
- * Return: 0 if no other mediated matrix device has a reference to @kvm;
+ * Return: 0 if no other mediated matrix device has a reference to the VM;
* otherwise, returns an -EPERM.
*/
static int vfio_ap_mdev_set_kvm(struct ap_matrix_mdev *matrix_mdev,
- struct kvm *kvm)
+ struct file *kvm_file)
{
+ struct kvm *kvm;
+
+ if (!kvm_file)
+ return -ENOENT;
+
+ kvm = file_to_kvm_s390(kvm_file);
+ if (!kvm)
+ return -ENOENT;
+
if (kvm->arch.crypto.crycbd) {
get_update_locks_for_kvm(kvm);
if (kvm->arch.crypto.pqap_hook) {
@@ -1841,7 +1851,6 @@ static int vfio_ap_mdev_set_kvm(struct ap_matrix_mdev *matrix_mdev,
}
kvm->arch.crypto.pqap_hook = &matrix_mdev->pqap_hook;
- kvm_get_kvm(kvm);
matrix_mdev->kvm = kvm;
vfio_ap_mdev_update_guest_apcb(matrix_mdev);
release_update_locks_for_kvm(kvm);
@@ -1894,7 +1903,6 @@ static void vfio_ap_mdev_unset_kvm(struct ap_matrix_mdev *matrix_mdev)
matrix_mdev->kvm = NULL;
release_update_locks_for_kvm(kvm);
- kvm_put_kvm(kvm);
}
}
diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c
index b2299e5bc6df..5bf8cbdff377 100644
--- a/drivers/vfio/group.c
+++ b/drivers/vfio/group.c
@@ -860,11 +860,20 @@ bool vfio_group_enforced_coherent(struct vfio_group *group)
return ret;
}
-void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm)
+void vfio_group_set_kvm(struct vfio_group *group, struct file *kvm)
{
+ struct file *old;
+
+ if (kvm)
+ get_file(kvm);
+
spin_lock(&group->kvm_ref_lock);
+ old = group->kvm;
group->kvm = kvm;
spin_unlock(&group->kvm_ref_lock);
+
+ if (old)
+ fput(old);
}
/**
diff --git a/drivers/vfio/pci/vfio_pci_zdev.c b/drivers/vfio/pci/vfio_pci_zdev.c
index f47f36314a1c..332bc66db55b 100644
--- a/drivers/vfio/pci/vfio_pci_zdev.c
+++ b/drivers/vfio/pci/vfio_pci_zdev.c
@@ -184,6 +184,7 @@ int vfio_pci_zdev_feature_err(struct vfio_device *device, u32 flags,
int vfio_pci_zdev_open_device(struct vfio_pci_core_device *vdev)
{
struct zpci_dev *zdev = to_zpci(vdev->pdev);
+ struct kvm *kvm;
int ret;
if (!zdev)
@@ -195,9 +196,14 @@ int vfio_pci_zdev_open_device(struct vfio_pci_core_device *vdev)
return 0;
ret = -ENOENT;
+ kvm = file_to_kvm_s390(vdev->vdev.kvm);
+ if (!kvm)
+ goto recovery;
+
if (zpci_kvm_hook.kvm_register)
- ret = zpci_kvm_hook.kvm_register(zdev, vdev->vdev.kvm);
+ ret = zpci_kvm_hook.kvm_register(zdev, kvm);
+recovery:
if (ret)
zpci_stop_mediated_recovery(zdev);
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index 7728bc99b63d..9b619951a5d0 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -23,7 +23,7 @@ struct vfio_device_file {
u8 access_granted;
u32 devid; /* only valid when iommufd is valid */
spinlock_t kvm_ref_lock; /* protect kvm field */
- struct kvm *kvm;
+ struct file *kvm;
struct iommufd_ctx *iommufd; /* protected by struct vfio_device_set::lock */
};
@@ -88,7 +88,7 @@ struct vfio_group {
#endif
enum vfio_group_type type;
struct mutex group_lock;
- struct kvm *kvm;
+ struct file *kvm;
struct file *opened_file;
struct iommufd_ctx *iommufd;
spinlock_t kvm_ref_lock;
@@ -107,7 +107,7 @@ void vfio_device_group_unuse_iommu(struct vfio_device *device);
void vfio_df_group_close(struct vfio_device_file *df);
struct vfio_group *vfio_group_from_file(struct file *file);
bool vfio_group_enforced_coherent(struct vfio_group *group);
-void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm);
+void vfio_group_set_kvm(struct vfio_group *group, struct file *kvm);
bool vfio_device_has_container(struct vfio_device *device);
int __init vfio_group_init(void);
void vfio_group_cleanup(void);
@@ -165,7 +165,7 @@ static inline bool vfio_group_enforced_coherent(struct vfio_group *group)
return true;
}
-static inline void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm)
+static inline void vfio_group_set_kvm(struct vfio_group *group, struct file *kvm)
{
}
@@ -429,11 +429,11 @@ static inline void vfio_virqfd_exit(void)
#endif
#if IS_ENABLED(CONFIG_KVM)
-void vfio_device_get_kvm_safe(struct vfio_device *device, struct kvm *kvm);
+void vfio_device_get_kvm_safe(struct vfio_device *device, struct file *kvm);
void vfio_device_put_kvm(struct vfio_device *device);
#else
static inline void vfio_device_get_kvm_safe(struct vfio_device *device,
- struct kvm *kvm)
+ struct file *kvm)
{
}
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index 423ead48aafe..ed96acfa8635 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -472,36 +472,14 @@ void vfio_unregister_group_dev(struct vfio_device *device)
EXPORT_SYMBOL_GPL(vfio_unregister_group_dev);
#if IS_ENABLED(CONFIG_KVM)
-void vfio_device_get_kvm_safe(struct vfio_device *device, struct kvm *kvm)
+void vfio_device_get_kvm_safe(struct vfio_device *device, struct file *kvm)
{
- void (*pfn)(struct kvm *kvm);
- bool (*fn)(struct kvm *kvm);
- bool ret;
-
lockdep_assert_held(&device->dev_set->lock);
if (!kvm)
return;
- pfn = symbol_get(kvm_put_kvm);
- if (WARN_ON(!pfn))
- return;
-
- fn = symbol_get(kvm_get_kvm_safe);
- if (WARN_ON(!fn)) {
- symbol_put(kvm_put_kvm);
- return;
- }
-
- ret = fn(kvm);
- symbol_put(kvm_get_kvm_safe);
- if (!ret) {
- symbol_put(kvm_put_kvm);
- return;
- }
-
- device->put_kvm = pfn;
- device->kvm = kvm;
+ device->kvm = get_file(kvm);
}
void vfio_device_put_kvm(struct vfio_device *device)
@@ -511,14 +489,7 @@ void vfio_device_put_kvm(struct vfio_device *device)
if (!device->kvm)
return;
- if (WARN_ON(!device->put_kvm))
- goto clear;
-
- device->put_kvm(device->kvm);
- device->put_kvm = NULL;
- symbol_put(kvm_put_kvm);
-
-clear:
+ fput(device->kvm);
device->kvm = NULL;
}
#endif
@@ -1544,9 +1515,13 @@ bool vfio_file_enforced_coherent(struct file *file)
}
EXPORT_SYMBOL_GPL(vfio_file_enforced_coherent);
-static void vfio_device_file_set_kvm(struct file *file, struct kvm *kvm)
+static void vfio_device_file_set_kvm(struct file *file, struct file *kvm)
{
struct vfio_device_file *df = file->private_data;
+ struct file *old;
+
+ if (kvm)
+ get_file(kvm);
/*
* The kvm is first recorded in the vfio_device_file, and will
@@ -1554,28 +1529,32 @@ static void vfio_device_file_set_kvm(struct file *file, struct kvm *kvm)
* iommufd successfully in the vfio device cdev path.
*/
spin_lock(&df->kvm_ref_lock);
+ old = df->kvm;
df->kvm = kvm;
spin_unlock(&df->kvm_ref_lock);
+
+ if (old)
+ fput(old);
}
/**
* vfio_file_set_kvm - Link a kvm with VFIO drivers
- * @file: VFIO group file or VFIO device file
- * @kvm: KVM to link
+ * @vfio_file: VFIO group file or VFIO device file
+ * @kvm: KVM file to link
*
* When a VFIO device is first opened the KVM will be available in
* device->kvm if one was associated with the file.
*/
-void vfio_file_set_kvm(struct file *file, struct kvm *kvm)
+void vfio_file_set_kvm(struct file *vfio_file, struct file *kvm)
{
struct vfio_group *group;
- group = vfio_group_from_file(file);
+ group = vfio_group_from_file(vfio_file);
if (group)
vfio_group_set_kvm(group, kvm);
- if (vfio_device_from_file(file))
- vfio_device_file_set_kvm(file, kvm);
+ if (vfio_device_from_file(vfio_file))
+ vfio_device_file_set_kvm(vfio_file, kvm);
}
EXPORT_SYMBOL_GPL(vfio_file_set_kvm);
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 45f08986359e..0cc91c6f96d2 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -54,7 +54,7 @@ struct vfio_device {
struct list_head dev_set_list;
unsigned int migration_flags;
u8 precopy_info_v2;
- struct kvm *kvm;
+ struct file *kvm;
/* Members below here are private, not for driver use */
unsigned int index;
@@ -66,7 +66,6 @@ struct vfio_device {
unsigned int open_count;
struct completion comp;
struct iommufd_access *iommufd_access;
- void (*put_kvm)(struct kvm *kvm);
struct inode *inode;
#if IS_ENABLED(CONFIG_IOMMUFD)
struct iommufd_device *iommufd_device;
@@ -378,7 +377,7 @@ static inline bool vfio_file_has_dev(struct file *file, struct vfio_device *devi
#endif
bool vfio_file_is_valid(struct file *file);
bool vfio_file_enforced_coherent(struct file *file);
-void vfio_file_set_kvm(struct file *file, struct kvm *kvm);
+void vfio_file_set_kvm(struct file *vfio_file, struct file *kvm);
#define VFIO_PIN_PAGES_MAX_ENTRIES (PAGE_SIZE/sizeof(unsigned long))
diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c
index 6cdc4e9a333a..19548a430942 100644
--- a/virt/kvm/vfio.c
+++ b/virt/kvm/vfio.c
@@ -35,15 +35,15 @@ struct kvm_vfio {
bool noncoherent;
};
-static void kvm_vfio_file_set_kvm(struct file *file, struct kvm *kvm)
+static void kvm_vfio_file_set_kvm(struct file *vfio_file, struct file *kvm)
{
- void (*fn)(struct file *file, struct kvm *kvm);
+ void (*fn)(struct file *vfio_file, struct file *kvm);
fn = symbol_get(vfio_file_set_kvm);
if (!fn)
return;
- fn(file, kvm);
+ fn(vfio_file, kvm);
symbol_put(vfio_file_set_kvm);
}
@@ -144,6 +144,7 @@ static int kvm_vfio_file_add(struct kvm_device *dev, unsigned int fd)
{
struct kvm_vfio *kv = dev->private;
struct kvm_vfio_file *kvf;
+ struct file *kvm_file __free(fput) = NULL;
struct file *filp __free(fput) = NULL;
filp = fget(fd);
@@ -154,6 +155,10 @@ static int kvm_vfio_file_add(struct kvm_device *dev, unsigned int fd)
if (!kvm_vfio_file_is_valid(filp))
return -EINVAL;
+ kvm_file = get_file_active(&dev->kvm->file);
+ if (!kvm_file)
+ return -ENOENT;
+
guard(mutex)(&kv->lock);
list_for_each_entry(kvf, &kv->file_list, node) {
@@ -168,7 +173,7 @@ static int kvm_vfio_file_add(struct kvm_device *dev, unsigned int fd)
kvf->file = get_file(filp);
list_add_tail(&kvf->node, &kv->file_list);
- kvm_vfio_file_set_kvm(kvf->file, dev->kvm);
+ kvm_vfio_file_set_kvm(kvf->file, kvm_file);
kvm_vfio_update_coherency(dev);
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 04/29] KVM/vfio: Use file-based reference counting for KVM
2026-09-18 13:30 ` [PATCH v8 04/29] KVM/vfio: Use file-based reference counting for KVM Steffen Eiden
@ 2026-09-18 14:26 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 14:26 UTC (permalink / raw)
To: Steffen Eiden
Cc: Vasily Gorbik, kvmarm, linux-s390, Christian Borntraeger,
Heiko Carstens, Marc Zyngier, Oliver Upton, Alexander Gordeev,
kvm
> Replace manual module reference counting with file-based reference
> counting for KVM integration. Previously, VFIO used symbol_get() to
> obtain function pointers for kvm_get_kvm_safe() and kvm_put_kvm(),
> then manually tracked module references through these symbols. This
> approach required storing the put_kvm function pointer in each device
> and carefully managing symbol references.
>
> Pass struct file pointers instead of struct kvm pointers throughout the
> VFIO-KVM interface, leveraging the kernel's existing file reference
> counting via get_file()/get_file_active() and fput(). Convert the x86
> page-track API likewise, and update vfio_ap and vfio_pci_zdev to use
> file_to_kvm_s390(). This simplifies the code and removes all remaining
> externally exported symbols for KVM which would appear twice for when a
> second concurrent KVM module is introduced.
>
> Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
> Co-developed-by: Sean Christopherson <seanjc@google.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> Reviewed-by: Jason J. Herne <jjherne@linux.ibm.com>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=4
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 05/29] KVM: Restrict kvm_get_kvm/kvm_put_kvm export to internal KVM modules
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (3 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 04/29] KVM/vfio: Use file-based reference counting for KVM Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 14:30 ` sashiko-bot
2026-09-18 13:30 ` [PATCH v8 06/29] KVM: Move export symbol check macros to Makefile.kvm Steffen Eiden
` (24 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Switch kvm_get_kvm, kvm_get_kvm_safe, and kvm_put_kvm from
EXPORT_SYMBOL_GPL to EXPORT_SYMBOL_FOR_KVM_INTERNAL. These symbols are
now only used within KVM itself. No external module needs them now that
VFIO uses file-based reference counting. Remove the corresponding
exemptions from the x86 KVM Makefile exports check.
Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/x86/kvm/Makefile | 5 +----
virt/kvm/kvm_main.c | 6 +++---
2 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index e6d395ede9e2..c6bf463f5032 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -61,10 +61,7 @@ exports_grep_trailer := --include='*.[ch]' -nrw $(srctree)/virt/kvm $(srctree)/a
-e kvm_page_track_unregister_notifier \
-e kvm_write_track_add_gfn \
-e kvm_write_track_remove_gfn \
- -e kvm_file_to_kvm_fn \
- -e kvm_get_kvm \
- -e kvm_get_kvm_safe \
- -e kvm_put_kvm
+ -e kvm_file_to_kvm_fn
# Force grep to emit a goofy group separator that can in turn be replaced with
# the above newline macro (newlines in Make are a nightmare). Note, grep only
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index bab71d398236..891a67cb365a 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1314,7 +1314,7 @@ void kvm_get_kvm(struct kvm *kvm)
{
refcount_inc(&kvm->users_count);
}
-EXPORT_SYMBOL_GPL(kvm_get_kvm);
+EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_get_kvm);
/*
* Make sure the vm is not during destruction, which is a safe version of
@@ -1324,14 +1324,14 @@ bool kvm_get_kvm_safe(struct kvm *kvm)
{
return refcount_inc_not_zero(&kvm->users_count);
}
-EXPORT_SYMBOL_GPL(kvm_get_kvm_safe);
+EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_get_kvm_safe);
void kvm_put_kvm(struct kvm *kvm)
{
if (refcount_dec_and_test(&kvm->users_count))
kvm_destroy_vm(kvm);
}
-EXPORT_SYMBOL_GPL(kvm_put_kvm);
+EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_put_kvm);
/*
* Used to put a reference that was taken on behalf of an object associated
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 05/29] KVM: Restrict kvm_get_kvm/kvm_put_kvm export to internal KVM modules
2026-09-18 13:30 ` [PATCH v8 05/29] KVM: Restrict kvm_get_kvm/kvm_put_kvm export to internal KVM modules Steffen Eiden
@ 2026-09-18 14:30 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 14:30 UTC (permalink / raw)
To: Steffen Eiden
Cc: Oliver Upton, Heiko Carstens, linux-s390, Alexander Gordeev,
Vasily Gorbik, Marc Zyngier, kvm, Christian Borntraeger, kvmarm
> Switch kvm_get_kvm, kvm_get_kvm_safe, and kvm_put_kvm from
> EXPORT_SYMBOL_GPL to EXPORT_SYMBOL_FOR_KVM_INTERNAL. These symbols are
> now only used within KVM itself. No external module needs them now that
> VFIO uses file-based reference counting. Remove the corresponding
> exemptions from the x86 KVM Makefile exports check.
>
> Suggested-by: Sean Christopherson <seanjc@google.com>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=5
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 06/29] KVM: Move export symbol check macros to Makefile.kvm
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (4 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 05/29] KVM: Restrict kvm_get_kvm/kvm_put_kvm export to internal KVM modules Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 14:37 ` sashiko-bot
2026-09-18 13:30 ` [PATCH v8 07/29] KVM: Make device name configurable Steffen Eiden
` (23 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
The EXPORT_SYMBOL_GPL/EXPORT_SYMBOL enforcement logic in
arch/x86/kvm/Makefile is useful for any KVM architecture wanting to
restrict the exported symbols. Move the check macros to
virt/kvm/Makefile.kvm so they can be shared.
Arch Makefiles only need to set kvm_exports_allowed to a space-separated
list of symbols that are permitted and then call kvm_check_exports for
each symbol type they want to enforce.
No functional change.
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/x86/kvm/Makefile | 49 +++++++++----------------------------------
virt/kvm/Makefile.kvm | 33 +++++++++++++++++++++++++++++
2 files changed, 43 insertions(+), 39 deletions(-)
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index c6bf463f5032..1bfd630c0767 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -54,43 +54,14 @@ clean-files += kvm-asm-offsets.h
# Only a handful of exports intended for other modules (VFIO, KVMGT) should
# use EXPORT_SYMBOL_GPL, and EXPORT_SYMBOL should never be used.
ifdef CONFIG_KVM_X86
-# Search recursively for whole words and print line numbers. Filter out the
-# allowed set of exports, i.e. those that are intended for external usage.
-exports_grep_trailer := --include='*.[ch]' -nrw $(srctree)/virt/kvm $(srctree)/arch/x86/kvm | \
- grep -v -e kvm_page_track_register_notifier \
- -e kvm_page_track_unregister_notifier \
- -e kvm_write_track_add_gfn \
- -e kvm_write_track_remove_gfn \
- -e kvm_file_to_kvm_fn
-
-# Force grep to emit a goofy group separator that can in turn be replaced with
-# the above newline macro (newlines in Make are a nightmare). Note, grep only
-# prints the group separator when N lines of context are requested via -C,
-# a.k.a. --NUM. Simply request zero lines. Print the separator only after
-# filtering out expected exports to avoid extra newlines in the error message.
-define get_kvm_exports
-$(shell grep "$(1)" -C0 $(exports_grep_trailer) | grep "$(1)" -C0 --group-separator="!SEP!")
-endef
-
-define check_kvm_exports
-nr_kvm_exports := $(shell grep "$(1)" $(exports_grep_trailer) | wc -l)
-
-ifneq (0,$$(nr_kvm_exports))
-$$(error ERROR ***\
-$$(newline)found $$(nr_kvm_exports) unwanted occurrences of $(1):\
-$$(newline) $(subst !SEP!,$$(newline) ,$(call get_kvm_exports,$(1)))\
-$$(newline)in directories:\
-$$(newline) $(srctree)/arch/x86/kvm\
-$$(newline) $(srctree)/virt/kvm\
-$$(newline)Use EXPORT_SYMBOL_FOR_KVM_INTERNAL, not $(1))
-endif # nr_kvm_exports != 0
-undefine nr_kvm_exports
-endef # check_kvm_exports
-
-$(eval $(call check_kvm_exports,EXPORT_SYMBOL_GPL))
-$(eval $(call check_kvm_exports,EXPORT_SYMBOL))
-
-undefine check_kvm_exports
-undefine get_kvm_exports
-undefine exports_grep_trailer
+kvm_exports_allowed := kvm_page_track_register_notifier \
+ kvm_page_track_unregister_notifier \
+ kvm_write_track_add_gfn \
+ kvm_write_track_remove_gfn \
+ kvm_file_to_kvm_fn
+
+$(eval $(call kvm_check_exports,EXPORT_SYMBOL_GPL))
+$(eval $(call kvm_check_exports,EXPORT_SYMBOL))
+
+undefine kvm_exports_allowed
endif # CONFIG_KVM_X86
diff --git a/virt/kvm/Makefile.kvm b/virt/kvm/Makefile.kvm
index d047d4cf58c9..dd40544b8ecb 100644
--- a/virt/kvm/Makefile.kvm
+++ b/virt/kvm/Makefile.kvm
@@ -13,3 +13,36 @@ kvm-$(CONFIG_HAVE_KVM_IRQ_ROUTING) += $(KVM)/irqchip.o
kvm-$(CONFIG_HAVE_KVM_DIRTY_RING) += $(KVM)/dirty_ring.o
kvm-$(CONFIG_HAVE_KVM_PFNCACHE) += $(KVM)/pfncache.o
kvm-$(CONFIG_KVM_GUEST_MEMFD) += $(KVM)/guest_memfd.o
+
+# Force grep to emit a goofy group separator that can in turn be replaced with
+# the above newline macro (newlines in Make are a nightmare). Note, grep only
+# prints the group separator when N lines of context are requested via -C,
+# a.k.a. --NUM. Simply request zero lines. Print the separator only after
+# filtering out expected exports to avoid extra newlines in the error message.
+define __kvm_get_exports
+$(shell grep "$(1)" -C0 --include='*.[ch]' -nrw \
+ $(srctree)/virt/kvm $(srctree)/arch/$(SRCARCH)/kvm \
+ $(addprefix | grep -v -e ,$(kvm_exports_allowed)) \
+ | grep "$(1)" -C0 --group-separator="!SEP!")
+endef
+
+
+KVM_CHECK_EXPORT_DIRS ?= $(srctree)/virt/kvm $(srctree)/arch/$(ARCH)/kvm
+
+# Fail the build if any unwanted $(1) usage is found outside kvm_exports_allowed.
+define kvm_check_exports
+kvm_nr_exports := $(shell grep "$(1)" --include='*.[ch]' -nrw \
+ $(KVM_CHECK_EXPORT_DIRS) \
+ $(addprefix | grep -v -e ,$(kvm_exports_allowed)) | wc -l)
+
+ifneq (0,$$(kvm_nr_exports))
+$$(error ERROR ***\
+$$(newline)found $$(kvm_nr_exports) unwanted occurrences of $(1):\
+$$(newline) $(subst !SEP!,$$(newline) ,$(call __kvm_get_exports,$(1)))\
+$$(newline)in directories:\
+$$(newline) $(KVM_CHECK_EXPORT_DIRS)\
+$$(newline)If this is a valid exception add it to kvm_exports_allowed or\
+$$(newline)use EXPORT_SYMBOL_FOR_KVM_INTERNAL, not $(1))
+endif # kvm_nr_exports != 0
+undefine kvm_nr_exports
+endef # kvm_check_exports
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 06/29] KVM: Move export symbol check macros to Makefile.kvm
2026-09-18 13:30 ` [PATCH v8 06/29] KVM: Move export symbol check macros to Makefile.kvm Steffen Eiden
@ 2026-09-18 14:37 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 14:37 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvm, Marc Zyngier, Alexander Gordeev, kvmarm, Vasily Gorbik,
Oliver Upton, linux-s390, Heiko Carstens, Christian Borntraeger
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] kvm: missing arch export symbol check due to $(ARCH) vs $(SRCARCH)
--
commit df2119cb096c289e1baffa51941e2be7e3687ea1
Author: Steffen Eiden <seiden@linux.ibm.com>
KVM: Move export symbol check macros to Makefile.kvm
The EXPORT_SYMBOL_GPL/EXPORT_SYMBOL enforcement logic in
arch/x86/kvm/Makefile is useful for any KVM architecture wanting to
restrict the exported symbols. Move the check macros to
virt/kvm/Makefile.kvm so they can be shared.
> diff --git a/virt/kvm/Makefile.kvm b/virt/kvm/Makefile.kvm
> index d047d4cf58c9f..dd40544b8ecb1 100644
> --- a/virt/kvm/Makefile.kvm
> +++ b/virt/kvm/Makefile.kvm
[ ... ]
> @@ -13,3 +13,36 @@ kvm-$(CONFIG_HAVE_KVM_IRQ_ROUTING) += $(KVM)/irqchip.o
> kvm-$(CONFIG_HAVE_KVM_DIRTY_RING) += $(KVM)/dirty_ring.o
> kvm-$(CONFIG_HAVE_KVM_PFNCACHE) += $(KVM)/pfncache.o
> kvm-$(CONFIG_KVM_GUEST_MEMFD) += $(KVM)/guest_memfd.o
> +
> +# Force grep to emit a goofy group separator that can in turn be replaced with
> +# the above newline macro (newlines in Make are a nightmare). Note, grep only
> +# prints the group separator when N lines of context are requested via -C,
> +# a.k.a. --NUM. Simply request zero lines. Print the separator only after
> +# filtering out expected exports to avoid extra newlines in the error message.
> +define __kvm_get_exports
> +$(shell grep "$(1)" -C0 --include='*.[ch]' -nrw \
> + $(srctree)/virt/kvm $(srctree)/arch/$(SRCARCH)/kvm \
[Severity: Low]
Does this hardcoded path create a mismatch between the counting and reporting
phases?
By using $(SRCARCH) here instead of reusing the $(KVM_CHECK_EXPORT_DIRS)
variable, __kvm_get_exports and kvm_check_exports use different source
directories for their grep commands.
> + $(addprefix | grep -v -e ,$(kvm_exports_allowed)) \
> + | grep "$(1)" -C0 --group-separator="!SEP!")
> +endef
> +
> +
> +KVM_CHECK_EXPORT_DIRS ?= $(srctree)/virt/kvm $(srctree)/arch/$(ARCH)/kvm
[Severity: Low]
Will using $(ARCH) instead of $(SRCARCH) cause the check to miss the actual
architecture source directory during compilation?
On architectures like x86_64, $(ARCH) evaluates to x86_64, but the actual
source directory is mapped to arch/x86 (which is what $(SRCARCH) resolves to).
This causes grep inside kvm_check_exports to silently skip arch/x86_64/kvm
because the directory does not exist, missing the EXPORT_SYMBOL validation
entirely for the architecture-specific KVM code.
> +
> +# Fail the build if any unwanted $(1) usage is found outside kvm_exports_allowed.
> +define kvm_check_exports
> +kvm_nr_exports := $(shell grep "$(1)" --include='*.[ch]' -nrw \
> + $(KVM_CHECK_EXPORT_DIRS) \
> + $(addprefix | grep -v -e ,$(kvm_exports_allowed)) | wc -l)
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=6
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 07/29] KVM: Make device name configurable
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (5 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 06/29] KVM: Move export symbol check macros to Makefile.kvm Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 14:58 ` sashiko-bot
2026-09-18 13:30 ` [PATCH v8 08/29] KVM: Move architecture capability Kconfigs to header defines Steffen Eiden
` (22 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Allow KVM implementations to choose alternative device names. This is
especially useful for architectures providing multiple KVM
implementations simultaneously. Architectures providing multiple KVM
implementations must compile the KVM common code once per
implementation and mange symbols.
Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/kvm/gmap/trace_gmap.h | 4 +++-
arch/s390/kvm/s390/Makefile | 2 +-
include/linux/kvm_host.h | 3 +++
include/trace/events/kvm.h | 8 +++++++-
virt/kvm/Makefile.kvm | 5 +++++
virt/kvm/kvm_main.c | 10 +++++-----
6 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/arch/s390/kvm/gmap/trace_gmap.h b/arch/s390/kvm/gmap/trace_gmap.h
index 15ec88bdce55..78d26dae59f9 100644
--- a/arch/s390/kvm/gmap/trace_gmap.h
+++ b/arch/s390/kvm/gmap/trace_gmap.h
@@ -4,8 +4,10 @@
#include <linux/tracepoint.h>
+#undef UNPACK_KVM
+#define UNPACK_KVM(name) name
#undef TRACE_SYSTEM
-#define TRACE_SYSTEM kvm
+#define TRACE_SYSTEM UNPACK_KVM(KVM_DEV_NAME)
#undef TRACE_INCLUDE_PATH
#define TRACE_INCLUDE_PATH ../gmap
#undef TRACE_INCLUDE_FILE
diff --git a/arch/s390/kvm/s390/Makefile b/arch/s390/kvm/s390/Makefile
index 762a63826423..b91334db90a2 100644
--- a/arch/s390/kvm/s390/Makefile
+++ b/arch/s390/kvm/s390/Makefile
@@ -4,7 +4,7 @@ KVM := ../../../../virt/kvm
include $(srctree)/virt/kvm/Makefile.kvm
include $(srctree)/arch/s390/kvm/gmap/Makefile
-ccflags-y := -I$(src) -I$(srctree)/arch/s390/kvm/gmap
+ccflags-y += -I$(src) -I$(srctree)/arch/s390/kvm/gmap
kvm-y += s390.o intercept.o interrupt.o priv.o sigp.o
kvm-y += diag.o gaccess.o guestdbg.o vsie.o pv.o
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 2b56fb4e8555..5926478563e8 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -45,6 +45,9 @@
#include <asm/kvm_host.h>
#include <linux/kvm_dirty_ring.h>
+#define __KVM_DEV_STRING(name, x) __stringify(name ## _ ## x)
+#define KVM_DEV_STRING(x) __KVM_DEV_STRING(KVM_DEV_NAME, x)
+
#ifndef KVM_MAX_VCPU_IDS
#define KVM_MAX_VCPU_IDS KVM_MAX_VCPUS
#endif
diff --git a/include/trace/events/kvm.h b/include/trace/events/kvm.h
index b282e3a86769..f37582730ffc 100644
--- a/include/trace/events/kvm.h
+++ b/include/trace/events/kvm.h
@@ -4,8 +4,14 @@
#include <linux/tracepoint.h>
+#undef UNPACK_KVM
+#define UNPACK_KVM(name) name
#undef TRACE_SYSTEM
-#define TRACE_SYSTEM kvm
+#define TRACE_SYSTEM UNPACK_KVM(KVM_DEV_NAME)
+#undef TRACE_SYSTEM_VAR
+#define TRACE_SYSTEM_VAR kvm
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE kvm
#define ERSN(x) { KVM_EXIT_##x, "KVM_EXIT_" #x }
diff --git a/virt/kvm/Makefile.kvm b/virt/kvm/Makefile.kvm
index dd40544b8ecb..ee66d460c494 100644
--- a/virt/kvm/Makefile.kvm
+++ b/virt/kvm/Makefile.kvm
@@ -5,6 +5,11 @@
KVM ?= ../../../virt/kvm
+KVM_DEV_NAME ?= kvm
+KVM_DEV_MINOR ?= KVM_MINOR
+
+ccflags-y +=-DKVM_DEV_NAME=$(KVM_DEV_NAME) -DKVM_DEV_MINOR=$(KVM_DEV_MINOR)
+
kvm-y := $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/binary_stats.o
kvm-$(CONFIG_KVM_VFIO) += $(KVM)/vfio.o
kvm-$(CONFIG_KVM_MMIO) += $(KVM)/coalesced_mmio.o
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 891a67cb365a..4f25e170b542 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -5596,8 +5596,8 @@ static struct file_operations kvm_chardev_ops = {
};
static struct miscdevice kvm_dev = {
- KVM_MINOR,
- "kvm",
+ KVM_DEV_MINOR,
+ __stringify(KVM_DEV_NAME),
&kvm_chardev_ops,
};
@@ -6376,7 +6376,7 @@ static void kvm_init_debug(void)
const struct kvm_stats_desc *pdesc;
int i;
- kvm_debugfs_dir = debugfs_create_dir("kvm", NULL);
+ kvm_debugfs_dir = debugfs_create_dir(__stringify(KVM_DEV_NAME), NULL);
for (i = 0; i < kvm_vm_stats_header.num_desc; ++i) {
pdesc = &kvm_vm_stats_desc[i];
@@ -6521,7 +6521,7 @@ int kvm_init(unsigned vcpu_size, unsigned vcpu_align, struct module *module)
if (!vcpu_align)
vcpu_align = __alignof__(struct kvm_vcpu);
kvm_vcpu_cache =
- kmem_cache_create_usercopy("kvm_vcpu", vcpu_size, vcpu_align,
+ kmem_cache_create_usercopy(KVM_DEV_STRING(vcpu), vcpu_size, vcpu_align,
SLAB_ACCOUNT,
offsetof(struct kvm_vcpu, arch),
offsetofend(struct kvm_vcpu, stats_id)
@@ -6574,7 +6574,7 @@ int kvm_init(unsigned vcpu_size, unsigned vcpu_align, struct module *module)
*/
r = misc_register(&kvm_dev);
if (r) {
- pr_err("kvm: misc device register failed\n");
+ pr_err(__stringify(KVM_DEV_NAME) ": misc device register failed\n");
goto err_register;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 07/29] KVM: Make device name configurable
2026-09-18 13:30 ` [PATCH v8 07/29] KVM: Make device name configurable Steffen Eiden
@ 2026-09-18 14:58 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 14:58 UTC (permalink / raw)
To: Steffen Eiden
Cc: Marc Zyngier, Alexander Gordeev, Heiko Carstens, linux-s390,
Vasily Gorbik, kvmarm, kvm, Christian Borntraeger, Oliver Upton
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] kvm: KVM_DEV_STRING macro evaluates to literal "KVM_DEV_NAME_vcpu"
- [Low] kvm: hardcoded "kvm" strings bypass the configurable device name
--
commit d598c93c97a669f28341c88d4d371abfd9c3b335
Author: Steffen Eiden <seiden@linux.ibm.com>
KVM: Make device name configurable
Allow KVM implementations to choose alternative device names. This is
especially useful for architectures providing multiple KVM
implementations simultaneously.
[ ... ]
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 2b56fb4e85557..5926478563e88 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -45,6 +45,9 @@
> #include <asm/kvm_host.h>
> #include <linux/kvm_dirty_ring.h>
>
> +#define __KVM_DEV_STRING(name, x) __stringify(name ## _ ## x)
> +#define KVM_DEV_STRING(x) __KVM_DEV_STRING(KVM_DEV_NAME, x)
[Severity: Medium]
Does KVM_DEV_STRING(vcpu) expand to the literal string "KVM_DEV_NAME_vcpu"
instead of the expected configured name?
Because the name parameter in __KVM_DEV_STRING is adjacent to the ##
token-pasting operator, the C preprocessor does not macro-expand it before
pasting. The tokens KVM_DEV_NAME, _, and vcpu are pasted into
KVM_DEV_NAME_vcpu, which __stringify converts to the literal string.
Does this need an extra level of macro indirection to evaluate the arguments
before pasting?
[ ... ]
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 891a67cb365ab..4f25e170b542c 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -5596,8 +5596,8 @@ static struct file_operations kvm_chardev_ops = {
> };
>
> static struct miscdevice kvm_dev = {
> - KVM_MINOR,
> - "kvm",
> + KVM_DEV_MINOR,
> + __stringify(KVM_DEV_NAME),
[Severity: Low]
Are there other hardcoded "kvm" strings that will bypass this configurable
device name when creating a VM or interacting with KVM infrastructure?
For instance, processes utilizing different KVM implementations will have
indistinguishable workqueues and anonymous inodes, reducing observability:
virt/kvm/eventfd.c:kvm_irqfd_init() {
...
irqfd_cleanup_wq = alloc_workqueue("kvm-irqfd-cleanup", WQ_PERCPU, 0);
...
}
virt/kvm/kvm_main.c:kvm_create_vm() {
...
file = anon_inode_getfile("kvm-vm", &kvm_vm_fops, kvm, O_RDWR);
...
}
And also hardcoded log prefixes:
virt/kvm/kvm_main.c:kvm_shutdown() {
...
pr_info("kvm: exiting hardware virtualization\n");
...
}
Do these strings also need to use the configured device name to ensure
concurrent KVM instances are cleanly segregated?
[Severity: Low]
This is a pre-existing issue, but does generic multiple KVM support conflict
with hardcoded core kernel singletons?
If architectures using CONFIG_KVM_GENERIC_HARDWARE_ENABLING attempt to load
multiple KVM modules simultaneously, the second module will fail to initialize.
The core hotplug subsystem returns -EBUSY when a second implementation invokes
it since the hotplug state is statically assigned:
virt/kvm/kvm_main.c:kvm_enable_virtualization() {
...
r = cpuhp_setup_state(CPUHP_AP_KVM_ONLINE, "kvm/cpu:online",
kvm_online_cpu, kvm_offline_cpu);
...
}
Also, concurrent registrations of guest info callbacks trigger a WARN_ON_ONCE
since the core kernel only maintains a single pointer:
virt/kvm/kvm_main.c:__kvm_register_perf_callbacks() {
...
perf_register_guest_info_callbacks(&kvm_guest_cbs);
...
}
Can these singletons be adjusted to support concurrent implementations?
> &kvm_chardev_ops,
> };
>
[ ... ]
> @@ -6521,7 +6521,7 @@ int kvm_init(unsigned vcpu_size, unsigned vcpu_align, struct module *module)
> if (!vcpu_align)
> vcpu_align = __alignof__(struct kvm_vcpu);
> kvm_vcpu_cache =
> - kmem_cache_create_usercopy("kvm_vcpu", vcpu_size, vcpu_align,
> + kmem_cache_create_usercopy(KVM_DEV_STRING(vcpu), vcpu_size, vcpu_align,
[Severity: Medium]
With the KVM_DEV_STRING() macro evaluating to the literal string
"KVM_DEV_NAME_vcpu", will all KVM modules unconditionally attempt to create a
kmem_cache named literally "KVM_DEV_NAME_vcpu" during module initialization?
This causes duplicate slab names across multiple KVM implementations, leading
to sysfs creation warnings (SLUB: Unable to add cache KVM_DEV_NAME_vcpu to
sysfs) and broken observability in /proc/slabinfo. Although SLUB permits
duplicate names and proceeds with cache creation, this seems to break the
intended uniqueness.
> SLAB_ACCOUNT,
> offsetof(struct kvm_vcpu, arch),
> offsetofend(struct kvm_vcpu, stats_id)
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=7
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 08/29] KVM: Move architecture capability Kconfigs to header defines
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (6 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 07/29] KVM: Make device name configurable Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 15:07 ` sashiko-bot
2026-09-21 7:09 ` Steffen Eiden
2026-09-18 13:30 ` [PATCH v8 09/29] KVM: Replace CONFIG_KVM_MMIO with KVM_NO_MMIO Steffen Eiden
` (21 subsequent siblings)
29 siblings, 2 replies; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Historically, KVM feature opt-ins and callbacks (e.g. read-only memory,
MSI routing, generic pre-fault memory, lockless aging, halt-polling
controls, and vcpu run PID changes) were configured globally via Kconfig
symbols (CONFIG_HAVE_KVM_* and CONFIG_KVM_*).
With s390 hosting multiple independent KVM implementations within the
same kernel build (native s390 KVM and arm64 on s390), global Kconfig
selections force both implementations to inherit options that only apply
to one of them. For instance, selecting KVM_GENERIC_PRE_FAULT_MEMORY for
native s390 would force arm64 on s390 to provide unused dummy stubs.
Replace these global Kconfig options with architecture-specific opt-in
defines in <asm/kvm_host.h> and standardize their naming by dropping the
HAVE_ prefix:
- KVM_GENERIC_PRE_FAULT_MEMORY
- KVM_INVALID_WAKEUPS
- KVM_MSI (formerly HAVE_KVM_MSI)
- KVM_NO_POLL (formerly HAVE_KVM_NO_POLL)
- KVM_READONLY_MEM (formerly HAVE_KVM_READONLY_MEM)
- KVM_VCPU_RUN_PID_CHANGE (formerly HAVE_KVM_VCPU_RUN_PID_CHANGE)
This allows each architecture and guest implementation to configure its
supported capabilities independently in its kvm_host header and eliminates
unnecessary fallback stubs across different KVM targets.
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/arm64/include/asm/kvm_host.h | 3 +++
arch/arm64/kvm/Kconfig | 3 ---
arch/loongarch/include/asm/kvm_host.h | 2 ++
arch/loongarch/kvm/Kconfig | 2 --
arch/mips/include/asm/kvm_host.h | 1 +
arch/mips/kvm/Kconfig | 1 -
arch/powerpc/include/asm/kvm_host.h | 3 +++
arch/powerpc/kvm/Kconfig | 1 -
arch/riscv/include/asm/kvm_host.h | 2 ++
arch/riscv/kvm/Kconfig | 2 --
arch/s390/include/asm/kvm_host_s390.h | 4 ++++
arch/s390/kvm/Kconfig | 3 ---
arch/x86/include/asm/kvm_host.h | 4 ++++
arch/x86/kvm/Kconfig | 4 ----
include/linux/kvm_host.h | 20 ++++++++++++--------
virt/kvm/Kconfig | 20 +-------------------
virt/kvm/kvm_main.c | 8 ++++----
17 files changed, 36 insertions(+), 47 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 27fe0cd5b2d7..9c314d0568b1 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -30,6 +30,9 @@
#include <asm/vncr_mapping.h>
#define __KVM_HAVE_ARCH_INTC_INITIALIZED
+#define KVM_MSI
+#define KVM_READONLY_MEM
+#define KVM_VCPU_RUN_PID_CHANGE
#define KVM_HALT_POLL_NS_DEFAULT 500000
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 449154f9a485..7329124deb2f 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -28,12 +28,9 @@ menuconfig KVM
select KVM_VFIO
select HAVE_KVM_DIRTY_RING_ACQ_REL
select NEED_KVM_DIRTY_RING_WITH_BITMAP
- select HAVE_KVM_MSI
select HAVE_KVM_IRQCHIP
select HAVE_KVM_IRQ_ROUTING
select HAVE_KVM_IRQ_BYPASS
- select HAVE_KVM_READONLY_MEM
- select HAVE_KVM_VCPU_RUN_PID_CHANGE
select SCHED_INFO
select GUEST_PERF_EVENTS if PERF_EVENTS
select KVM_GUEST_MEMFD
diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h
index 65d91c3ce313..4cb370a8d09b 100644
--- a/arch/loongarch/include/asm/kvm_host.h
+++ b/arch/loongarch/include/asm/kvm_host.h
@@ -26,6 +26,8 @@
#include <asm/loongarch.h>
#define __KVM_HAVE_ARCH_INTC_INITIALIZED
+#define KVM_MSI
+#define KVM_READONLY_MEM
/* Loongarch KVM register ids */
#define KVM_GET_IOC_CSR_IDX(id) ((id & KVM_CSR_IDX_MASK) >> LOONGARCH_REG_SHIFT)
diff --git a/arch/loongarch/kvm/Kconfig b/arch/loongarch/kvm/Kconfig
index 15da2d88c0c1..a427429a2b05 100644
--- a/arch/loongarch/kvm/Kconfig
+++ b/arch/loongarch/kvm/Kconfig
@@ -23,8 +23,6 @@ config KVM
select HAVE_KVM_DIRTY_RING_ACQ_REL
select HAVE_KVM_IRQ_ROUTING
select HAVE_KVM_IRQCHIP
- select HAVE_KVM_MSI
- select HAVE_KVM_READONLY_MEM
select KVM_COMMON
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select KVM_GENERIC_HARDWARE_ENABLING
diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index c14b10821817..8e484bb482ba 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -893,5 +893,6 @@ static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) {}
static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {}
#define __KVM_HAVE_ARCH_FLUSH_REMOTE_TLBS
+#define KVM_READONLY_MEM
#endif /* __MIPS_KVM_HOST_H__ */
diff --git a/arch/mips/kvm/Kconfig b/arch/mips/kvm/Kconfig
index b1b9a1d67758..c24b872afbcb 100644
--- a/arch/mips/kvm/Kconfig
+++ b/arch/mips/kvm/Kconfig
@@ -24,7 +24,6 @@ config KVM
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select KVM_MMIO
select KVM_GENERIC_HARDWARE_ENABLING
- select HAVE_KVM_READONLY_MEM
help
Support for hosting Guest kernels.
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 2d139c807577..ad7c34e9b227 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -49,6 +49,9 @@
#endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */
#define __KVM_HAVE_ARCH_INTC_INITIALIZED
+#ifdef CONFIG_KVM_MPIC
+#define KVM_MSI
+#endif
#define KVM_HALT_POLL_NS_DEFAULT 10000 /* 10 us */
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index b6bc2fc86dca..1fae2de8fa68 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -232,7 +232,6 @@ config KVM_MPIC
depends on KVM && PPC_E500
select HAVE_KVM_IRQCHIP
select HAVE_KVM_IRQ_ROUTING
- select HAVE_KVM_MSI
help
Enable support for emulating MPIC devices inside the
host kernel, rather than relying on userspace to emulate.
diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
index a30600579231..23b5560e97ba 100644
--- a/arch/riscv/include/asm/kvm_host.h
+++ b/arch/riscv/include/asm/kvm_host.h
@@ -47,6 +47,8 @@
#define KVM_REQ_STEAL_UPDATE KVM_ARCH_REQ(6)
#define __KVM_HAVE_ARCH_FLUSH_REMOTE_TLBS_RANGE
+#define KVM_MSI
+#define KVM_READONLY_MEM
#define KVM_HAVE_MMU_RWLOCK
diff --git a/arch/riscv/kvm/Kconfig b/arch/riscv/kvm/Kconfig
index ec2cee0a39e0..3cb4f8037300 100644
--- a/arch/riscv/kvm/Kconfig
+++ b/arch/riscv/kvm/Kconfig
@@ -22,8 +22,6 @@ config KVM
depends on RISCV_SBI && MMU
select HAVE_KVM_IRQCHIP
select HAVE_KVM_IRQ_ROUTING
- select HAVE_KVM_MSI
- select HAVE_KVM_READONLY_MEM
select HAVE_KVM_DIRTY_RING_ACQ_REL
select KVM_COMMON
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
diff --git a/arch/s390/include/asm/kvm_host_s390.h b/arch/s390/include/asm/kvm_host_s390.h
index 8a7eed5847e1..5fd7f49d7c0d 100644
--- a/arch/s390/include/asm/kvm_host_s390.h
+++ b/arch/s390/include/asm/kvm_host_s390.h
@@ -34,6 +34,10 @@
#define KVM_INTERNAL_MEM_SLOTS 1
+#define KVM_GENERIC_PRE_FAULT_MEMORY
+#define KVM_INVALID_WAKEUPS
+#define KVM_NO_POLL
+
#define KVM_S390_MANAGES_S390_GUEST 1
/*
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
index 8d3ee17a1bcb..a6ff2e5aa19b 100644
--- a/arch/s390/kvm/Kconfig
+++ b/arch/s390/kvm/Kconfig
@@ -25,12 +25,9 @@ config KVM
select KVM_COMMON
select HAVE_KVM_IRQCHIP
select HAVE_KVM_IRQ_ROUTING
- select HAVE_KVM_INVALID_WAKEUPS
- select HAVE_KVM_NO_POLL
select KVM_VFIO
select VIRT_XFER_TO_GUEST_WORK
select KVM_MMU_LOCKLESS_AGING
- select KVM_GENERIC_PRE_FAULT_MEMORY
help
Support hosting paravirtualized guest machines using the SIE
virtualization capability on the mainframe. This should work
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index e460073ff176..cfe22832a4df 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -47,6 +47,10 @@
#define kvm_file_to_kvm_arch x86
#define __KVM_HAVE_ARCH_VCPU_DEBUGFS
+#define KVM_GENERIC_PRE_FAULT_MEMORY
+#define KVM_MSI
+#define KVM_NO_POLL
+#define KVM_READONLY_MEM
/*
* CONFIG_KVM_MAX_NR_VCPUS is defined iff CONFIG_KVM!=n, provide a dummy max if
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 538ed1e80332..fa20f64d6a2f 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -28,7 +28,6 @@ config KVM_X86
select HAVE_KVM_DIRTY_RING_ACQ_REL
select HAVE_KVM_IRQ_BYPASS
select HAVE_KVM_IRQ_ROUTING
- select HAVE_KVM_READONLY_MEM
select VHOST_TASK
select KVM_ASYNC_PF
select USER_RETURN_NOTIFIER
@@ -37,15 +36,12 @@ config KVM_X86
select PERF_EVENTS
select GUEST_PERF_EVENTS
select PERF_GUEST_MEDIATED_PMU
- select HAVE_KVM_MSI
select HAVE_KVM_CPU_RELAX_INTERCEPT
- select HAVE_KVM_NO_POLL
select VIRT_XFER_TO_GUEST_WORK
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select KVM_VFIO
select HAVE_KVM_PM_NOTIFIER if PM
select KVM_GENERIC_HARDWARE_ENABLING
- select KVM_GENERIC_PRE_FAULT_MEMORY
select KVM_WERROR if WERROR
select KVM_GUEST_MEMFD if X86_64
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 5926478563e8..b7bd20fc9e34 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -749,7 +749,11 @@ static inline u64 kvm_gmem_get_supported_flags(struct kvm *kvm)
#ifndef kvm_arch_has_readonly_mem
static inline bool kvm_arch_has_readonly_mem(struct kvm *kvm)
{
- return IS_ENABLED(CONFIG_HAVE_KVM_READONLY_MEM);
+#ifdef KVM_READONLY_MEM
+ return true;
+#else
+ return false;
+#endif
}
#endif
@@ -2481,7 +2485,7 @@ void kvm_arch_update_irqfd_routing(struct kvm_kernel_irqfd *irqfd,
struct kvm_kernel_irq_routing_entry *new);
#endif /* CONFIG_HAVE_KVM_IRQ_BYPASS */
-#ifdef CONFIG_HAVE_KVM_INVALID_WAKEUPS
+#ifdef KVM_INVALID_WAKEUPS
/* If we wakeup during the poll time, was it a sucessful poll? */
static inline bool vcpu_valid_wakeup(struct kvm_vcpu *vcpu)
{
@@ -2493,9 +2497,9 @@ static inline bool vcpu_valid_wakeup(struct kvm_vcpu *vcpu)
{
return true;
}
-#endif /* CONFIG_HAVE_KVM_INVALID_WAKEUPS */
+#endif /* KVM_INVALID_WAKEUPS */
-#ifdef CONFIG_HAVE_KVM_NO_POLL
+#ifdef KVM_NO_POLL
/* Callback that tells if we must not poll */
bool kvm_arch_no_poll(struct kvm_vcpu *vcpu);
#else
@@ -2503,18 +2507,18 @@ static inline bool kvm_arch_no_poll(struct kvm_vcpu *vcpu)
{
return false;
}
-#endif /* CONFIG_HAVE_KVM_NO_POLL */
+#endif /* KVM_NO_POLL */
void kvm_arch_guest_memory_reclaimed(struct kvm *kvm);
-#ifdef CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE
+#ifdef KVM_VCPU_RUN_PID_CHANGE
int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu);
#else
static inline int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
{
return 0;
}
-#endif /* CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE */
+#endif /* KVM_VCPU_RUN_PID_CHANGE */
#ifdef CONFIG_VIRT_XFER_TO_GUEST_WORK
static inline void kvm_handle_signal_exit(struct kvm_vcpu *vcpu)
@@ -2663,7 +2667,7 @@ void kvm_arch_gmem_reclaim(kvm_pfn_t pfn, kvm_pfn_t nr_pages);
void kvm_arch_gmem_invalidate_range(struct kvm *kvm, struct kvm_gfn_range *range);
#endif
-#ifdef CONFIG_KVM_GENERIC_PRE_FAULT_MEMORY
+#ifdef KVM_GENERIC_PRE_FAULT_MEMORY
long kvm_arch_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu,
struct kvm_pre_fault_memory *range);
#endif
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
index c3c0ee253fc7..008b110ebdb7 100644
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -9,7 +9,7 @@ config KVM_COMMON
select PREEMPT_NOTIFIERS
config HAVE_KVM_PFNCACHE
- bool
+ booCONFIG_ltt
config HAVE_KVM_IRQCHIP
bool
@@ -50,27 +50,15 @@ config KVM_ASYNC_PF
config KVM_ASYNC_PF_SYNC
bool
-config HAVE_KVM_MSI
- bool
-
-config HAVE_KVM_READONLY_MEM
- bool
-
config HAVE_KVM_CPU_RELAX_INTERCEPT
bool
config KVM_VFIO
bool
-config HAVE_KVM_INVALID_WAKEUPS
- bool
-
config KVM_GENERIC_DIRTYLOG_READ_PROTECT
bool
-config KVM_GENERIC_PRE_FAULT_MEMORY
- bool
-
config KVM_COMPAT
def_bool y
depends on KVM && COMPAT && !(S390 || ARM64 || RISCV)
@@ -79,12 +67,6 @@ config HAVE_KVM_IRQ_BYPASS
tristate
select IRQ_BYPASS_MANAGER
-config HAVE_KVM_VCPU_RUN_PID_CHANGE
- bool
-
-config HAVE_KVM_NO_POLL
- bool
-
config VIRT_XFER_TO_GUEST_WORK
bool
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 4f25e170b542..a7ce1f22b3de 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -4351,7 +4351,7 @@ static int kvm_vcpu_ioctl_get_stats_fd(struct kvm_vcpu *vcpu)
return fd;
}
-#ifdef CONFIG_KVM_GENERIC_PRE_FAULT_MEMORY
+#ifdef KVM_GENERIC_PRE_FAULT_MEMORY
static int kvm_vcpu_pre_fault_memory(struct kvm_vcpu *vcpu,
struct kvm_pre_fault_memory *range)
{
@@ -4650,7 +4650,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
r = kvm_vcpu_ioctl_get_stats_fd(vcpu);
break;
}
-#ifdef CONFIG_KVM_GENERIC_PRE_FAULT_MEMORY
+#ifdef KVM_GENERIC_PRE_FAULT_MEMORY
case KVM_PRE_FAULT_MEMORY: {
struct kvm_pre_fault_memory range;
@@ -4891,7 +4891,7 @@ static int kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS:
case KVM_CAP_INTERNAL_ERROR_DATA:
-#ifdef CONFIG_HAVE_KVM_MSI
+#ifdef KVM_MSI
case KVM_CAP_SIGNAL_MSI:
#endif
#ifdef CONFIG_HAVE_KVM_IRQCHIP
@@ -5281,7 +5281,7 @@ static long kvm_vm_ioctl(struct file *filp,
r = kvm_ioeventfd(kvm, &data);
break;
}
-#ifdef CONFIG_HAVE_KVM_MSI
+#ifdef KVM_MSI
case KVM_SIGNAL_MSI: {
struct kvm_msi msi;
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 08/29] KVM: Move architecture capability Kconfigs to header defines
2026-09-18 13:30 ` [PATCH v8 08/29] KVM: Move architecture capability Kconfigs to header defines Steffen Eiden
@ 2026-09-18 15:07 ` sashiko-bot
2026-09-21 7:09 ` Steffen Eiden
1 sibling, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 15:07 UTC (permalink / raw)
To: Steffen Eiden
Cc: Alexander Gordeev, Christian Borntraeger, Marc Zyngier,
Vasily Gorbik, linux-s390, Heiko Carstens, Oliver Upton, kvmarm,
kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] kconfig: syntax error in virt/kvm/Kconfig due to 'booCONFIG_ltt' typo
--
commit ee51b43b92593e9aef02197487e12632baf77f58
Author: Steffen Eiden <seiden@linux.ibm.com>
KVM: Move architecture capability Kconfigs to header defines
Historically, KVM feature opt-ins and callbacks (e.g. read-only memory,
MSI routing, generic pre-fault memory, lockless aging, halt-polling
controls, and vcpu run PID changes) were configured globally via Kconfig
symbols (CONFIG_HAVE_KVM_* and CONFIG_KVM_*).
With s390 hosting multiple independent KVM implementations within the
same kernel build (native s390 KVM and arm64 on s390), global Kconfig
selections force both implementations to inherit options that only apply
to one of them.
> diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
> index c3c0ee253fc77..008b110ebdb7a 100644
> --- a/virt/kvm/Kconfig
> +++ b/virt/kvm/Kconfig
> @@ -9,7 +9,7 @@ config KVM_COMMON
> select PREEMPT_NOTIFIERS
>
> config HAVE_KVM_PFNCACHE
> - bool
> + booCONFIG_ltt
[Severity: Low]
Is booCONFIG_ltt a typo for bool under config HAVE_KVM_PFNCACHE in
virt/kvm/Kconfig?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=8
^ permalink raw reply [flat|nested] 80+ messages in thread
* Re: [PATCH v8 08/29] KVM: Move architecture capability Kconfigs to header defines
2026-09-18 13:30 ` [PATCH v8 08/29] KVM: Move architecture capability Kconfigs to header defines Steffen Eiden
2026-09-18 15:07 ` sashiko-bot
@ 2026-09-21 7:09 ` Steffen Eiden
1 sibling, 0 replies; 80+ messages in thread
From: Steffen Eiden @ 2026-09-21 7:09 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390,
Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
On Fri, Sep 18, 2026 at 03:30:45PM +0200, Steffen Eiden wrote:
> Historically, KVM feature opt-ins and callbacks (e.g. read-only memory,
> MSI routing, generic pre-fault memory, lockless aging, halt-polling
> controls, and vcpu run PID changes) were configured globally via Kconfig
> symbols (CONFIG_HAVE_KVM_* and CONFIG_KVM_*).
>
> With s390 hosting multiple independent KVM implementations within the
> same kernel build (native s390 KVM and arm64 on s390), global Kconfig
> selections force both implementations to inherit options that only apply
> to one of them. For instance, selecting KVM_GENERIC_PRE_FAULT_MEMORY for
> native s390 would force arm64 on s390 to provide unused dummy stubs.
>
> Replace these global Kconfig options with architecture-specific opt-in
> defines in <asm/kvm_host.h> and standardize their naming by dropping the
> HAVE_ prefix:
> - KVM_GENERIC_PRE_FAULT_MEMORY
> - KVM_INVALID_WAKEUPS
> - KVM_MSI (formerly HAVE_KVM_MSI)
> - KVM_NO_POLL (formerly HAVE_KVM_NO_POLL)
> - KVM_READONLY_MEM (formerly HAVE_KVM_READONLY_MEM)
> - KVM_VCPU_RUN_PID_CHANGE (formerly HAVE_KVM_VCPU_RUN_PID_CHANGE)
>
> This allows each architecture and guest implementation to configure its
> supported capabilities independently in its kvm_host header and eliminates
> unnecessary fallback stubs across different KVM targets.
>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
> ---
> arch/arm64/include/asm/kvm_host.h | 3 +++
> arch/arm64/kvm/Kconfig | 3 ---
> arch/loongarch/include/asm/kvm_host.h | 2 ++
> arch/loongarch/kvm/Kconfig | 2 --
> arch/mips/include/asm/kvm_host.h | 1 +
> arch/mips/kvm/Kconfig | 1 -
> arch/powerpc/include/asm/kvm_host.h | 3 +++
> arch/powerpc/kvm/Kconfig | 1 -
> arch/riscv/include/asm/kvm_host.h | 2 ++
> arch/riscv/kvm/Kconfig | 2 --
> arch/s390/include/asm/kvm_host_s390.h | 4 ++++
> arch/s390/kvm/Kconfig | 3 ---
> arch/x86/include/asm/kvm_host.h | 4 ++++
> arch/x86/kvm/Kconfig | 4 ----
> include/linux/kvm_host.h | 20 ++++++++++++--------
> virt/kvm/Kconfig | 20 +-------------------
> virt/kvm/kvm_main.c | 8 ++++----
> 17 files changed, 36 insertions(+), 47 deletions(-)
>
...
> diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
> index c3c0ee253fc7..008b110ebdb7 100644
> --- a/virt/kvm/Kconfig
> +++ b/virt/kvm/Kconfig
> @@ -9,7 +9,7 @@ config KVM_COMMON
> select PREEMPT_NOTIFIERS
>
> config HAVE_KVM_PFNCACHE
> - bool
> + booCONFIG_ltt
Sorry, that must have sneaked in last minute.
Obviously, this is a mistake.
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 09/29] KVM: Replace CONFIG_KVM_MMIO with KVM_NO_MMIO
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (7 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 08/29] KVM: Move architecture capability Kconfigs to header defines Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 15:15 ` sashiko-bot
2026-09-18 13:30 ` [PATCH v8 10/29] arm64: Use proper include variant Steffen Eiden
` (20 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Defining KVM_MMIO is not flexible enough for multi-KVM systems where one
KVM implements MMIO but others do not. Therefore, remove KVM_MMIO from
the config space and use the macro KVM_NO_MMIO instead.
Define KVM_NO_MMIO for KVM/s390 and for selected KVM/powerpc
configurations.
coalesced_mmio.c is now always compiled&linked. However, for
architectures/configurations defining KVM_NO_MMIO this effectively
collapses to an empty object with no mmio code.
No functional changes.
Suggested-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/arm64/kvm/Kconfig | 1 -
arch/loongarch/kvm/Kconfig | 1 -
arch/mips/kvm/Kconfig | 1 -
arch/powerpc/include/asm/kvm_host.h | 7 +++++++
arch/powerpc/kvm/Kconfig | 4 ----
arch/riscv/kvm/Kconfig | 1 -
arch/s390/include/asm/kvm_host_s390.h | 2 ++
arch/x86/kvm/Kconfig | 1 -
include/linux/kvm_host.h | 2 +-
virt/kvm/Kconfig | 3 ---
virt/kvm/Makefile.kvm | 4 ++--
virt/kvm/coalesced_mmio.c | 4 ++++
virt/kvm/coalesced_mmio.h | 2 +-
virt/kvm/kvm_main.c | 8 ++++----
14 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 7329124deb2f..8475f32ad9e6 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -22,7 +22,6 @@ menuconfig KVM
select KVM_COMMON
select KVM_GENERIC_HARDWARE_ENABLING
select HAVE_KVM_CPU_RELAX_INTERCEPT
- select KVM_MMIO
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select VIRT_XFER_TO_GUEST_WORK
select KVM_VFIO
diff --git a/arch/loongarch/kvm/Kconfig b/arch/loongarch/kvm/Kconfig
index a427429a2b05..fd387326d2f2 100644
--- a/arch/loongarch/kvm/Kconfig
+++ b/arch/loongarch/kvm/Kconfig
@@ -26,7 +26,6 @@ config KVM
select KVM_COMMON
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select KVM_GENERIC_HARDWARE_ENABLING
- select KVM_MMIO
select VIRT_XFER_TO_GUEST_WORK
select SCHED_INFO
select GUEST_PERF_EVENTS if PERF_EVENTS
diff --git a/arch/mips/kvm/Kconfig b/arch/mips/kvm/Kconfig
index c24b872afbcb..849ce7c7c4df 100644
--- a/arch/mips/kvm/Kconfig
+++ b/arch/mips/kvm/Kconfig
@@ -22,7 +22,6 @@ config KVM
select EXPORT_UASM
select KVM_COMMON
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
- select KVM_MMIO
select KVM_GENERIC_HARDWARE_ENABLING
help
Support for hosting Guest kernels.
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index ad7c34e9b227..620f163d65a9 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -29,6 +29,13 @@
#define __KVM_HAVE_ARCH_VCPU_DEBUGFS
+#if !defined(CONFIG_KVM_BOOK3S_32_HANDLER) && \
+ !defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE) && \
+ !defined(CONFIG_KVM_E500V2) && \
+ !defined(CONFIG_KVM_E500MC)
+#define KVM_NO_MMIO
+#endif
+
#define KVM_MAX_VCPUS NR_CPUS
#define KVM_MAX_VCORES NR_CPUS
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig
index 1fae2de8fa68..cacc22e34afd 100644
--- a/arch/powerpc/kvm/Kconfig
+++ b/arch/powerpc/kvm/Kconfig
@@ -30,7 +30,6 @@ config KVM_BOOK3S_HANDLER
config KVM_BOOK3S_32_HANDLER
bool
select KVM_BOOK3S_HANDLER
- select KVM_MMIO
config KVM_BOOK3S_64_HANDLER
bool
@@ -38,7 +37,6 @@ config KVM_BOOK3S_64_HANDLER
config KVM_BOOK3S_PR_POSSIBLE
bool
- select KVM_MMIO
config KVM_BOOK3S_HV_POSSIBLE
bool
@@ -201,7 +199,6 @@ config KVM_E500V2
depends on PPC_E500 && !PPC_E500MC
depends on !CONTEXT_TRACKING_USER
select KVM
- select KVM_MMIO
help
Support running unmodified E500 guest kernels in virtual machines on
E500v2 host processors.
@@ -216,7 +213,6 @@ config KVM_E500MC
depends on PPC_E500MC
depends on !CONTEXT_TRACKING_USER
select KVM
- select KVM_MMIO
select KVM_BOOKE_HV
help
Support running unmodified E500MC/E5500/E6500 guest kernels in
diff --git a/arch/riscv/kvm/Kconfig b/arch/riscv/kvm/Kconfig
index 3cb4f8037300..2e3c4e6c1cd7 100644
--- a/arch/riscv/kvm/Kconfig
+++ b/arch/riscv/kvm/Kconfig
@@ -26,7 +26,6 @@ config KVM
select KVM_COMMON
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
select KVM_GENERIC_HARDWARE_ENABLING
- select KVM_MMIO
select VIRT_XFER_TO_GUEST_WORK
select SCHED_INFO
select GUEST_PERF_EVENTS if PERF_EVENTS
diff --git a/arch/s390/include/asm/kvm_host_s390.h b/arch/s390/include/asm/kvm_host_s390.h
index 5fd7f49d7c0d..451346f32008 100644
--- a/arch/s390/include/asm/kvm_host_s390.h
+++ b/arch/s390/include/asm/kvm_host_s390.h
@@ -40,6 +40,8 @@
#define KVM_S390_MANAGES_S390_GUEST 1
+#define KVM_NO_MMIO
+
/*
* These seem to be used for allocating ->chip in the routing table, which we
* don't use. 1 is as small as we can get to reduce the needed memory. If we
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index fa20f64d6a2f..82b6c91e763b 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -31,7 +31,6 @@ config KVM_X86
select VHOST_TASK
select KVM_ASYNC_PF
select USER_RETURN_NOTIFIER
- select KVM_MMIO
select SCHED_INFO
select PERF_EVENTS
select GUEST_PERF_EVENTS
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index b7bd20fc9e34..7ebc9aaaec2d 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -846,7 +846,7 @@ struct kvm {
struct kvm_vm_stat stat;
struct kvm_arch arch;
refcount_t users_count;
-#ifdef CONFIG_KVM_MMIO
+#ifndef KVM_NO_MMIO
struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
spinlock_t ring_lock;
struct list_head coalesced_zones;
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
index 008b110ebdb7..69b47cb6526c 100644
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -40,9 +40,6 @@ config NEED_KVM_DIRTY_RING_WITH_BITMAP
bool
depends on HAVE_KVM_DIRTY_RING
-config KVM_MMIO
- bool
-
config KVM_ASYNC_PF
bool
diff --git a/virt/kvm/Makefile.kvm b/virt/kvm/Makefile.kvm
index ee66d460c494..9a3b05a01c62 100644
--- a/virt/kvm/Makefile.kvm
+++ b/virt/kvm/Makefile.kvm
@@ -10,9 +10,9 @@ KVM_DEV_MINOR ?= KVM_MINOR
ccflags-y +=-DKVM_DEV_NAME=$(KVM_DEV_NAME) -DKVM_DEV_MINOR=$(KVM_DEV_MINOR)
-kvm-y := $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/binary_stats.o
+kvm-y := $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/binary_stats.o \
+ $(KVM)/coalesced_mmio.o
kvm-$(CONFIG_KVM_VFIO) += $(KVM)/vfio.o
-kvm-$(CONFIG_KVM_MMIO) += $(KVM)/coalesced_mmio.o
kvm-$(CONFIG_KVM_ASYNC_PF) += $(KVM)/async_pf.o
kvm-$(CONFIG_HAVE_KVM_IRQ_ROUTING) += $(KVM)/irqchip.o
kvm-$(CONFIG_HAVE_KVM_DIRTY_RING) += $(KVM)/dirty_ring.o
diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c
index 6b1d90161099..d6cae6855237 100644
--- a/virt/kvm/coalesced_mmio.c
+++ b/virt/kvm/coalesced_mmio.c
@@ -15,6 +15,8 @@
#include <linux/slab.h>
#include <linux/kvm.h>
+#ifndef KVM_NO_MMIO
+
#include "coalesced_mmio.h"
static inline struct kvm_coalesced_mmio_dev *to_mmio(struct kvm_io_device *dev)
@@ -188,3 +190,5 @@ int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm,
*/
return 0;
}
+
+#endif /* !KVM_NO_MMIO */
diff --git a/virt/kvm/coalesced_mmio.h b/virt/kvm/coalesced_mmio.h
index 36f84264ed25..bcaa34fce1e8 100644
--- a/virt/kvm/coalesced_mmio.h
+++ b/virt/kvm/coalesced_mmio.h
@@ -11,7 +11,7 @@
*
*/
-#ifdef CONFIG_KVM_MMIO
+#ifndef KVM_NO_MMIO
#include <linux/list.h>
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index a7ce1f22b3de..32b8aad8fa2b 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -4061,7 +4061,7 @@ static vm_fault_t kvm_vcpu_fault(struct vm_fault *vmf)
else if (vmf->pgoff == KVM_PIO_PAGE_OFFSET)
page = virt_to_page(vcpu->arch.pio_data);
#endif
-#ifdef CONFIG_KVM_MMIO
+#ifndef KVM_NO_MMIO
else if (vmf->pgoff == KVM_COALESCED_MMIO_PAGE_OFFSET)
page = virt_to_page(vcpu->kvm->coalesced_mmio_ring);
#endif
@@ -4902,7 +4902,7 @@ static int kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
case KVM_CAP_ENABLE_CAP_VM:
case KVM_CAP_HALT_POLL:
return 1;
-#ifdef CONFIG_KVM_MMIO
+#ifndef KVM_NO_MMIO
case KVM_CAP_COALESCED_MMIO:
return KVM_COALESCED_MMIO_PAGE_OFFSET;
case KVM_CAP_COALESCED_PIO:
@@ -5243,7 +5243,7 @@ static long kvm_vm_ioctl(struct file *filp,
break;
}
#endif
-#ifdef CONFIG_KVM_MMIO
+#ifndef KVM_NO_MMIO
case KVM_REGISTER_COALESCED_MMIO: {
struct kvm_coalesced_mmio_zone zone;
@@ -5578,7 +5578,7 @@ static long kvm_dev_ioctl(struct file *filp,
#ifdef CONFIG_X86
r += PAGE_SIZE; /* pio data page */
#endif
-#ifdef CONFIG_KVM_MMIO
+#ifndef KVM_NO_MMIO
r += PAGE_SIZE; /* coalesced mmio ring page */
#endif
break;
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 09/29] KVM: Replace CONFIG_KVM_MMIO with KVM_NO_MMIO
2026-09-18 13:30 ` [PATCH v8 09/29] KVM: Replace CONFIG_KVM_MMIO with KVM_NO_MMIO Steffen Eiden
@ 2026-09-18 15:15 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 15:15 UTC (permalink / raw)
To: Steffen Eiden
Cc: Marc Zyngier, Christian Borntraeger, kvm, linux-s390,
Heiko Carstens, Alexander Gordeev, Vasily Gorbik, Oliver Upton,
kvmarm
> Defining KVM_MMIO is not flexible enough for multi-KVM systems where one
> KVM implements MMIO but others do not. Therefore, remove KVM_MMIO from
> the config space and use the macro KVM_NO_MMIO instead.
> Define KVM_NO_MMIO for KVM/s390 and for selected KVM/powerpc
> configurations.
>
> coalesced_mmio.c is now always compiled&linked. However, for
> architectures/configurations defining KVM_NO_MMIO this effectively
> collapses to an empty object with no mmio code.
>
> No functional changes.
>
> Suggested-by: Marc Zyngier <maz@kernel.org>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=9
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 10/29] arm64: Use proper include variant
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (8 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 09/29] KVM: Replace CONFIG_KVM_MMIO with KVM_NO_MMIO Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 15:16 ` sashiko-bot
2026-09-28 14:01 ` Catalin Marinas
2026-09-18 13:30 ` [PATCH v8 11/29] arm64: ptrace: Use constants for compat register numbers Steffen Eiden
` (19 subsequent siblings)
29 siblings, 2 replies; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Use <> for including the sysreg header as it is not discoverable from
the current directory.
Fixes: c07d8017bceb ("arm64/sysreg: Enable automatic generation of system register definitions")
Acked-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/arm64/include/asm/sysreg.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 7aa08d59d494..4bfdac9401bd 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -173,7 +173,7 @@
* come from here. The header relies on the definition of sys_reg()
* earlier in this file.
*/
-#include "asm/sysreg-defs.h"
+#include <asm/sysreg-defs.h>
/*
* System registers, organised loosely by encoding but grouped together
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 10/29] arm64: Use proper include variant
2026-09-18 13:30 ` [PATCH v8 10/29] arm64: Use proper include variant Steffen Eiden
@ 2026-09-18 15:16 ` sashiko-bot
2026-09-28 14:01 ` Catalin Marinas
1 sibling, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 15:16 UTC (permalink / raw)
To: Steffen Eiden
Cc: Vasily Gorbik, kvmarm, Alexander Gordeev, linux-s390, kvm,
Christian Borntraeger, Heiko Carstens, Marc Zyngier, Oliver Upton
> Use <> for including the sysreg header as it is not discoverable from
> the current directory.
>
> Fixes: c07d8017bceb ("arm64/sysreg: Enable automatic generation of system register definitions")
> Acked-by: Marc Zyngier <maz@kernel.org>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=10
^ permalink raw reply [flat|nested] 80+ messages in thread* Re: [PATCH v8 10/29] arm64: Use proper include variant
2026-09-18 13:30 ` [PATCH v8 10/29] arm64: Use proper include variant Steffen Eiden
2026-09-18 15:16 ` sashiko-bot
@ 2026-09-28 14:01 ` Catalin Marinas
1 sibling, 0 replies; 80+ messages in thread
From: Catalin Marinas @ 2026-09-28 14:01 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390,
Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
Friedrich Welter, Fuad Tabba, Gautam Gala, Hariharan Mari,
Heiko Carstens, Hendrik Brueckner, Ilya Leoshkevich,
Janosch Frank, Joey Gouly, Marc Zyngier, Nico Boehr,
Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
On Fri, Sep 18, 2026 at 03:30:47PM +0200, Steffen Eiden wrote:
> Use <> for including the sysreg header as it is not discoverable from
> the current directory.
>
> Fixes: c07d8017bceb ("arm64/sysreg: Enable automatic generation of system register definitions")
> Acked-by: Marc Zyngier <maz@kernel.org>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 11/29] arm64: ptrace: Use constants for compat register numbers
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (9 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 10/29] arm64: Use proper include variant Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 15:20 ` sashiko-bot
2026-09-28 14:01 ` Catalin Marinas
2026-09-18 13:30 ` [PATCH v8 12/29] arm64: sysreg: Convert SPSR_ELx to automatic register generation Steffen Eiden
` (18 subsequent siblings)
29 siblings, 2 replies; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Define an enum to determine the register number for the mapping from
AArch32 and AArch64 registers. This allows for a more flexible use of
the register mappings.
Reviewed-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/arm64/include/asm/ptrace.h | 60 ++++++++++++++++++++++-----------
1 file changed, 41 insertions(+), 19 deletions(-)
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index f7dc5fb9427d..49a83a0636b9 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -102,26 +102,48 @@
#define COMPAT_USER_SZ 296
/* Architecturally defined mapping between AArch32 and AArch64 registers */
+enum {
+ __compat_fp = 11,
+ __compat_sp = 13,
+ __compat_lr = 14,
+ __compat_sp_hyp = 15,
+ __compat_lr_irq = 16,
+ __compat_sp_irq = 17,
+ __compat_lr_svc = 18,
+ __compat_sp_svc = 19,
+ __compat_lr_abt = 20,
+ __compat_sp_abt = 21,
+ __compat_lr_und = 22,
+ __compat_sp_und = 23,
+ __compat_r8_fiq = 24,
+ __compat_r9_fiq = 25,
+ __compat_r10_fiq = 26,
+ __compat_r11_fiq = 27,
+ __compat_r12_fiq = 28,
+ __compat_sp_fiq = 29,
+ __compat_lr_fiq = 30,
+};
+
#define compat_usr(x) regs[(x)]
-#define compat_fp regs[11]
-#define compat_sp regs[13]
-#define compat_lr regs[14]
-#define compat_sp_hyp regs[15]
-#define compat_lr_irq regs[16]
-#define compat_sp_irq regs[17]
-#define compat_lr_svc regs[18]
-#define compat_sp_svc regs[19]
-#define compat_lr_abt regs[20]
-#define compat_sp_abt regs[21]
-#define compat_lr_und regs[22]
-#define compat_sp_und regs[23]
-#define compat_r8_fiq regs[24]
-#define compat_r9_fiq regs[25]
-#define compat_r10_fiq regs[26]
-#define compat_r11_fiq regs[27]
-#define compat_r12_fiq regs[28]
-#define compat_sp_fiq regs[29]
-#define compat_lr_fiq regs[30]
+#define compat_fp regs[__compat_fp]
+#define compat_sp regs[__compat_sp]
+#define compat_lr regs[__compat_lr]
+#define compat_sp_hyp regs[__compat_sp_hyp]
+#define compat_lr_irq regs[__compat_lr_irq]
+#define compat_sp_irq regs[__compat_sp_irq]
+#define compat_lr_svc regs[__compat_lr_svc]
+#define compat_sp_svc regs[__compat_sp_svc]
+#define compat_lr_abt regs[__compat_lr_abt]
+#define compat_sp_abt regs[__compat_sp_abt]
+#define compat_lr_und regs[__compat_lr_und]
+#define compat_sp_und regs[__compat_sp_und]
+#define compat_r8_fiq regs[__compat_r8_fiq]
+#define compat_r9_fiq regs[__compat_r9_fiq]
+#define compat_r10_fiq regs[__compat_r10_fiq]
+#define compat_r11_fiq regs[__compat_r11_fiq]
+#define compat_r12_fiq regs[__compat_r12_fiq]
+#define compat_sp_fiq regs[__compat_sp_fiq]
+#define compat_lr_fiq regs[__compat_lr_fiq]
static inline unsigned long compat_psr_to_pstate(const unsigned long psr)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 11/29] arm64: ptrace: Use constants for compat register numbers
2026-09-18 13:30 ` [PATCH v8 11/29] arm64: ptrace: Use constants for compat register numbers Steffen Eiden
@ 2026-09-18 15:20 ` sashiko-bot
2026-09-28 14:01 ` Catalin Marinas
1 sibling, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 15:20 UTC (permalink / raw)
To: Steffen Eiden
Cc: Christian Borntraeger, Heiko Carstens, kvm, Alexander Gordeev,
kvmarm, Vasily Gorbik, Oliver Upton, Marc Zyngier, linux-s390
> Define an enum to determine the register number for the mapping from
> AArch32 and AArch64 registers. This allows for a more flexible use of
> the register mappings.
>
> Reviewed-by: Marc Zyngier <maz@kernel.org>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=11
^ permalink raw reply [flat|nested] 80+ messages in thread
* Re: [PATCH v8 11/29] arm64: ptrace: Use constants for compat register numbers
2026-09-18 13:30 ` [PATCH v8 11/29] arm64: ptrace: Use constants for compat register numbers Steffen Eiden
2026-09-18 15:20 ` sashiko-bot
@ 2026-09-28 14:01 ` Catalin Marinas
1 sibling, 0 replies; 80+ messages in thread
From: Catalin Marinas @ 2026-09-28 14:01 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390,
Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
Friedrich Welter, Fuad Tabba, Gautam Gala, Hariharan Mari,
Heiko Carstens, Hendrik Brueckner, Ilya Leoshkevich,
Janosch Frank, Joey Gouly, Marc Zyngier, Nico Boehr,
Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
On Fri, Sep 18, 2026 at 03:30:48PM +0200, Steffen Eiden wrote:
> Define an enum to determine the register number for the mapping from
> AArch32 and AArch64 registers. This allows for a more flexible use of
> the register mappings.
>
> Reviewed-by: Marc Zyngier <maz@kernel.org>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 12/29] arm64: sysreg: Convert SPSR_ELx to automatic register generation
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (10 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 11/29] arm64: ptrace: Use constants for compat register numbers Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 15:24 ` sashiko-bot
2026-09-28 15:08 ` Catalin Marinas
2026-09-18 13:30 ` [PATCH v8 13/29] KVM: arm64: Access elements of vcpu_gp_regs individually Steffen Eiden
` (17 subsequent siblings)
29 siblings, 2 replies; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Convert SPSR_EL{1, 2, 12} to automatic register generation as per
DDIO616 2026-06. No functional change.
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/arm64/include/asm/sysreg.h | 3 --
arch/arm64/tools/sysreg | 51 +++++++++++++++++++++++++++++++++
2 files changed, 51 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 4bfdac9401bd..1aa601c95188 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -295,7 +295,6 @@
#define SYS_APGAKEYLO_EL1 sys_reg(3, 0, 2, 3, 0)
#define SYS_APGAKEYHI_EL1 sys_reg(3, 0, 2, 3, 1)
-#define SYS_SPSR_EL1 sys_reg(3, 0, 4, 0, 0)
#define SYS_ELR_EL1 sys_reg(3, 0, 4, 0, 1)
#define SYS_ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0)
@@ -518,7 +517,6 @@
#define SYS_VTTBR_EL2 sys_reg(3, 4, 2, 1, 0)
#define SYS_HAFGRTR_EL2 sys_reg(3, 4, 3, 1, 6)
-#define SYS_SPSR_EL2 sys_reg(3, 4, 4, 0, 0)
#define SYS_ELR_EL2 sys_reg(3, 4, 4, 0, 1)
#define SYS_SP_EL1 sys_reg(3, 4, 4, 1, 0)
#define SYS_SPSR_irq sys_reg(3, 4, 4, 3, 0)
@@ -604,7 +602,6 @@
#define SYS_BRBCR_EL12 sys_reg(2, 5, 9, 0, 0)
#define SYS_TTBR0_EL12 sys_reg(3, 5, 2, 0, 0)
#define SYS_TTBR1_EL12 sys_reg(3, 5, 2, 0, 1)
-#define SYS_SPSR_EL12 sys_reg(3, 5, 4, 0, 0)
#define SYS_ELR_EL12 sys_reg(3, 5, 4, 0, 1)
#define SYS_AFSR0_EL12 sys_reg(3, 5, 5, 1, 0)
#define SYS_AFSR1_EL12 sys_reg(3, 5, 5, 1, 1)
diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index e2d37ee221b8..893b5f9df575 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -401,6 +401,57 @@ Res0 3:1
Field 0 SO
EndSysreg
+SysregFields SPSR_ELx
+Res0 63:37
+Field 36 UINJ
+Field 35 PACM
+Field 34 EXLOCK
+Res0 33
+Field 32 PM
+Field 31 N
+Field 30 Z
+Field 29 C
+Field 28 V
+Res0 27:26
+Field 25 TCO
+Field 24 DIT
+Field 23 UAO
+Field 22 PAN
+Field 21 SS
+Field 20 IL
+Res0 19:14
+Field 13 ALLINT
+Field 12 SSBS
+Field 11:10 BTYPE
+Field 9 D
+Field 8 A
+Field 7 I
+Field 6 F
+Res0 5
+Field 4 M4
+Enum 3:0 M
+ 0b0000 EL0
+ 0b0100 EL1t
+ 0b0101 EL1h
+ 0b1000 EL2t
+ 0b1001 EL2h
+ 0b1100 EL3t
+ 0b1101 EL3h
+EndEnum
+EndSysregFields
+
+Sysreg SPSR_EL1 3 0 4 0 0
+Fields SPSR_ELx
+EndSysreg
+
+Sysreg SPSR_EL2 3 4 4 0 0
+Fields SPSR_ELx
+EndSysreg
+
+Sysreg SPSR_EL12 3 5 4 0 0
+Mapping SPSR_EL1
+EndSysreg
+
Sysreg ID_PFR0_EL1 3 0 0 1 0
Res0 63:32
UnsignedEnum 31:28 RAS
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 12/29] arm64: sysreg: Convert SPSR_ELx to automatic register generation
2026-09-18 13:30 ` [PATCH v8 12/29] arm64: sysreg: Convert SPSR_ELx to automatic register generation Steffen Eiden
@ 2026-09-18 15:24 ` sashiko-bot
2026-09-28 15:08 ` Catalin Marinas
1 sibling, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 15:24 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvmarm, Alexander Gordeev, kvm, Christian Borntraeger,
Heiko Carstens, Oliver Upton, Marc Zyngier, linux-s390,
Vasily Gorbik
> Convert SPSR_EL{1, 2, 12} to automatic register generation as per
> DDIO616 2026-06. No functional change.
>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=12
^ permalink raw reply [flat|nested] 80+ messages in thread* Re: [PATCH v8 12/29] arm64: sysreg: Convert SPSR_ELx to automatic register generation
2026-09-18 13:30 ` [PATCH v8 12/29] arm64: sysreg: Convert SPSR_ELx to automatic register generation Steffen Eiden
2026-09-18 15:24 ` sashiko-bot
@ 2026-09-28 15:08 ` Catalin Marinas
2026-09-28 15:36 ` Steffen Eiden
1 sibling, 1 reply; 80+ messages in thread
From: Catalin Marinas @ 2026-09-28 15:08 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390,
Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
Friedrich Welter, Fuad Tabba, Gautam Gala, Hariharan Mari,
Heiko Carstens, Hendrik Brueckner, Ilya Leoshkevich,
Janosch Frank, Joey Gouly, Marc Zyngier, Nico Boehr,
Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
On Fri, Sep 18, 2026 at 03:30:49PM +0200, Steffen Eiden wrote:
> Convert SPSR_EL{1, 2, 12} to automatic register generation as per
> DDIO616 2026-06. No functional change.
What's this document? DDI0616 is the SME spec (also s/DDIO/DDI0/ -
replace letter O with zero). Maybe use DDI0601 (system registers spec)
or the Arm ARM, DDI0487.
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 80+ messages in thread* Re: [PATCH v8 12/29] arm64: sysreg: Convert SPSR_ELx to automatic register generation
2026-09-28 15:08 ` Catalin Marinas
@ 2026-09-28 15:36 ` Steffen Eiden
0 siblings, 0 replies; 80+ messages in thread
From: Steffen Eiden @ 2026-09-28 15:36 UTC (permalink / raw)
To: Catalin Marinas
Cc: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390,
Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
Friedrich Welter, Fuad Tabba, Gautam Gala, Hariharan Mari,
Heiko Carstens, Hendrik Brueckner, Ilya Leoshkevich,
Janosch Frank, Joey Gouly, Marc Zyngier, Nico Boehr,
Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
On Mon, Sep 28, 2026 at 04:08:27PM +0100, Catalin Marinas wrote:
> On Fri, Sep 18, 2026 at 03:30:49PM +0200, Steffen Eiden wrote:
> > Convert SPSR_EL{1, 2, 12} to automatic register generation as per
> > DDIO616 2026-06. No functional change.
>
> What's this document? DDI0616 is the SME spec (also s/DDIO/DDI0/ -
> replace letter O with zero). Maybe use DDI0601 (system registers spec)
> or the Arm ARM, DDI0487.
yes, I used DDI0601. Sorry.
But Arm ARM, DDI0487 will do the job as well.
>
> Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Thanks.
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 13/29] KVM: arm64: Access elements of vcpu_gp_regs individually
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (11 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 12/29] arm64: sysreg: Convert SPSR_ELx to automatic register generation Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 15:28 ` sashiko-bot
2026-09-18 13:30 ` [PATCH v8 14/29] KVM: arm64: Use accessor functions for core regs Steffen Eiden
` (16 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
While for arm64 the members of vcpu_gp_regs are allocated continuous
this is not necessarily true for other architectures implementing ARM.
Let vcpu_gp_regs() no longer return the address of the user_pt_regs in
the vcpu context but the address of the gp-register array field in the
user_pt_reg struct. Note, this change semantically excludes pc from the
GPRs.
No functional change.
Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/arm64/include/asm/kvm_emulate.h | 14 ++++++++------
arch/arm64/include/asm/kvm_host.h | 2 +-
arch/arm64/kvm/guest.c | 2 +-
arch/arm64/kvm/hyp/exception.c | 4 ++--
arch/arm64/kvm/hyp/include/hyp/adjust_pc.h | 4 ++--
arch/arm64/kvm/hyp/include/hyp/switch.h | 4 ++--
6 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index a3c1928bdf74..8603766c1b4d 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -133,12 +133,12 @@ static inline void vcpu_set_vsesr(struct kvm_vcpu *vcpu, u64 vsesr)
static __always_inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu)
{
- return (unsigned long *)&vcpu_gp_regs(vcpu)->pc;
+ return (unsigned long *)&vcpu->arch.ctxt.regs.pc;
}
static __always_inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu)
{
- return (unsigned long *)&vcpu_gp_regs(vcpu)->pstate;
+ return (unsigned long *)&vcpu->arch.ctxt.regs.pstate;
}
static __always_inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
@@ -167,14 +167,14 @@ static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
static __always_inline unsigned long vcpu_get_reg(const struct kvm_vcpu *vcpu,
u8 reg_num)
{
- return (reg_num == 31) ? 0 : vcpu_gp_regs(vcpu)->regs[reg_num];
+ return (reg_num == 31) ? 0 : vcpu_gp_regs(vcpu)[reg_num];
}
static __always_inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
unsigned long val)
{
if (reg_num != 31)
- vcpu_gp_regs(vcpu)->regs[reg_num] = val;
+ vcpu_gp_regs(vcpu)[reg_num] = val;
}
static inline bool vcpu_is_el2_ctxt(const struct kvm_cpu_context *ctxt)
@@ -750,13 +750,15 @@ static inline void kvm_reset_vcpu_core(struct kvm_vcpu *vcpu)
pstate = VCPU_RESET_PSTATE_EL1;
/* Reset core registers */
- memset(vcpu_gp_regs(vcpu), 0, sizeof(*vcpu_gp_regs(vcpu)));
+ memset(vcpu_gp_regs(vcpu), 0, sizeof(vcpu_gp_regs(vcpu)));
+ *vcpu_pc(vcpu) = 0;
+ vcpu->arch.ctxt.regs.sp = 0;
memset(&vcpu->arch.ctxt.fp_regs, 0, sizeof(vcpu->arch.ctxt.fp_regs));
vcpu->arch.ctxt.spsr_abt = 0;
vcpu->arch.ctxt.spsr_und = 0;
vcpu->arch.ctxt.spsr_irq = 0;
vcpu->arch.ctxt.spsr_fiq = 0;
- vcpu_gp_regs(vcpu)->pstate = pstate;
+ *vcpu_cpsr(vcpu) = pstate;
}
/* PSCI reset handling for a vcpu. */
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 9c314d0568b1..fc0037efa0b4 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -1161,7 +1161,7 @@ struct kvm_vcpu_arch {
#define vcpu_clear_on_unsupported_cpu(vcpu) \
vcpu_clear_flag(vcpu, ON_UNSUPPORTED_CPU)
-#define vcpu_gp_regs(v) (&(v)->arch.ctxt.regs)
+#define vcpu_gp_regs(v) ((v)->arch.ctxt.regs.regs)
/*
* Only use __vcpu_sys_reg/ctxt_sys_reg if you know you want the
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index b01d6622b872..81d850d5a328 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -134,7 +134,7 @@ static void *core_reg_addr(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
KVM_REG_ARM_CORE_REG(regs.regs[30]):
off -= KVM_REG_ARM_CORE_REG(regs.regs[0]);
off /= 2;
- return &vcpu->arch.ctxt.regs.regs[off];
+ return &vcpu_gp_regs(vcpu)[off];
case KVM_REG_ARM_CORE_REG(regs.sp):
return &vcpu->arch.ctxt.regs.sp;
diff --git a/arch/arm64/kvm/hyp/exception.c b/arch/arm64/kvm/hyp/exception.c
index 754e2dc1df54..0640c9ccaa3c 100644
--- a/arch/arm64/kvm/hyp/exception.c
+++ b/arch/arm64/kvm/hyp/exception.c
@@ -276,12 +276,12 @@ static void enter_exception32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset)
switch(mode) {
case PSR_AA32_MODE_ABT:
__vcpu_write_spsr_abt(vcpu, host_spsr_to_spsr32(spsr));
- vcpu_gp_regs(vcpu)->compat_lr_abt = return_address;
+ vcpu_gp_regs(vcpu)[__compat_lr_abt] = return_address;
break;
case PSR_AA32_MODE_UND:
__vcpu_write_spsr_und(vcpu, host_spsr_to_spsr32(spsr));
- vcpu_gp_regs(vcpu)->compat_lr_und = return_address;
+ vcpu_gp_regs(vcpu)[__compat_lr_und] = return_address;
break;
}
diff --git a/arch/arm64/kvm/hyp/include/hyp/adjust_pc.h b/arch/arm64/kvm/hyp/include/hyp/adjust_pc.h
index 4fdfeabefeb4..a049983bd5c3 100644
--- a/arch/arm64/kvm/hyp/include/hyp/adjust_pc.h
+++ b/arch/arm64/kvm/hyp/include/hyp/adjust_pc.h
@@ -33,11 +33,11 @@ static inline void kvm_skip_instr(struct kvm_vcpu *vcpu)
static inline void __kvm_skip_instr(struct kvm_vcpu *vcpu)
{
*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
- vcpu_gp_regs(vcpu)->pstate = read_sysreg_el2(SYS_SPSR);
+ *vcpu_cpsr(vcpu) = read_sysreg_el2(SYS_SPSR);
kvm_skip_instr(vcpu);
- write_sysreg_el2(vcpu_gp_regs(vcpu)->pstate, SYS_SPSR);
+ write_sysreg_el2(*vcpu_cpsr(vcpu), SYS_SPSR);
write_sysreg_el2(*vcpu_pc(vcpu), SYS_ELR);
}
diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
index 1ce7130e2549..a2a054fec2e2 100644
--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
+++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
@@ -470,7 +470,7 @@ static inline bool kvm_hyp_handle_mops(struct kvm_vcpu *vcpu, u64 *exit_code)
u64 spsr;
*vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
- arm64_mops_reset_regs(vcpu_gp_regs(vcpu), vcpu->arch.fault.esr_el2);
+ arm64_mops_reset_regs(&vcpu->arch.ctxt.regs, vcpu->arch.fault.esr_el2);
write_sysreg_el2(*vcpu_pc(vcpu), SYS_ELR);
/*
@@ -902,7 +902,7 @@ static inline void synchronize_vcpu_pstate(struct kvm_vcpu *vcpu)
/*
* Check for the conditions of Cortex-A510's #2077057. When these occur
* SPSR_EL2 can't be trusted, but isn't needed either as it is
- * unchanged from the value in vcpu_gp_regs(vcpu)->pstate.
+ * unchanged from the value in vcpu_cpsr(vcpu).
* Are we single-stepping the guest, and took a PAC exception from the
* active-not-pending state?
*/
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 13/29] KVM: arm64: Access elements of vcpu_gp_regs individually
2026-09-18 13:30 ` [PATCH v8 13/29] KVM: arm64: Access elements of vcpu_gp_regs individually Steffen Eiden
@ 2026-09-18 15:28 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 15:28 UTC (permalink / raw)
To: Steffen Eiden
Cc: Marc Zyngier, Oliver Upton, linux-s390, Vasily Gorbik, kvmarm,
Alexander Gordeev, Heiko Carstens, Christian Borntraeger, kvm
> While for arm64 the members of vcpu_gp_regs are allocated continuous
> this is not necessarily true for other architectures implementing ARM.
>
> Let vcpu_gp_regs() no longer return the address of the user_pt_regs in
> the vcpu context but the address of the gp-register array field in the
> user_pt_reg struct. Note, this change semantically excludes pc from the
> GPRs.
>
> No functional change.
>
> Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
> Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=13
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 14/29] KVM: arm64: Use accessor functions for core regs
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (12 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 13/29] KVM: arm64: Access elements of vcpu_gp_regs individually Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 15:32 ` sashiko-bot
2026-09-18 13:30 ` [PATCH v8 15/29] arm64: Prepare sharing arm64 headers with s390 Steffen Eiden
` (15 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Instead of accessing the value directly use assessor function that
abstract the actual location of the register values. Add a helper
function to reset fpsimd registers. Enables other KVM implementations to
reuse this code.
No functional changes.
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/arm64/include/asm/kvm_emulate.h | 34 ++++++++++++++++++++++++++--
arch/arm64/kvm/guest.c | 14 ++++++------
2 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index 8603766c1b4d..b31d50bdf59e 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -141,6 +141,31 @@ static __always_inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu)
return (unsigned long *)&vcpu->arch.ctxt.regs.pstate;
}
+static __always_inline unsigned long *vcpu_sp_el0(struct kvm_vcpu *vcpu)
+{
+ return (unsigned long *)&vcpu->arch.ctxt.regs.sp;
+}
+
+static __always_inline u64 *vcpu_sp_el1(struct kvm_vcpu *vcpu)
+{
+ return __ctxt_sys_reg(&vcpu->arch.ctxt, SP_EL1);
+}
+
+static __always_inline __u128 *vcpu_vreg(struct kvm_vcpu *vcpu, int n)
+{
+ return &vcpu->arch.ctxt.fp_regs.vregs[n];
+}
+
+static __always_inline __u32 *vcpu_fpsr(struct kvm_vcpu *vcpu)
+{
+ return &vcpu->arch.ctxt.fp_regs.fpsr;
+}
+
+static __always_inline __u32 *vcpu_fpcr(struct kvm_vcpu *vcpu)
+{
+ return &vcpu->arch.ctxt.fp_regs.fpcr;
+}
+
static __always_inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
{
return !!(*vcpu_cpsr(vcpu) & PSR_MODE32_BIT);
@@ -737,6 +762,11 @@ static inline void vcpu_set_hcrx(struct kvm_vcpu *vcpu)
}
}
+static inline void kvm_reset_fpsimd(struct kvm_vcpu *vcpu)
+{
+ memset(&vcpu->arch.ctxt.fp_regs, 0, sizeof(vcpu->arch.ctxt.fp_regs));
+}
+
/* Reset a vcpu's core registers. */
static inline void kvm_reset_vcpu_core(struct kvm_vcpu *vcpu)
{
@@ -752,8 +782,8 @@ static inline void kvm_reset_vcpu_core(struct kvm_vcpu *vcpu)
/* Reset core registers */
memset(vcpu_gp_regs(vcpu), 0, sizeof(vcpu_gp_regs(vcpu)));
*vcpu_pc(vcpu) = 0;
- vcpu->arch.ctxt.regs.sp = 0;
- memset(&vcpu->arch.ctxt.fp_regs, 0, sizeof(vcpu->arch.ctxt.fp_regs));
+ *vcpu_sp_el0(vcpu) = 0;
+ kvm_reset_fpsimd(vcpu);
vcpu->arch.ctxt.spsr_abt = 0;
vcpu->arch.ctxt.spsr_und = 0;
vcpu->arch.ctxt.spsr_irq = 0;
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 81d850d5a328..773f6c8e5026 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -137,16 +137,16 @@ static void *core_reg_addr(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
return &vcpu_gp_regs(vcpu)[off];
case KVM_REG_ARM_CORE_REG(regs.sp):
- return &vcpu->arch.ctxt.regs.sp;
+ return vcpu_sp_el0(vcpu);
case KVM_REG_ARM_CORE_REG(regs.pc):
- return &vcpu->arch.ctxt.regs.pc;
+ return vcpu_pc(vcpu);
case KVM_REG_ARM_CORE_REG(regs.pstate):
- return &vcpu->arch.ctxt.regs.pstate;
+ return vcpu_cpsr(vcpu);
case KVM_REG_ARM_CORE_REG(sp_el1):
- return __ctxt_sys_reg(&vcpu->arch.ctxt, SP_EL1);
+ return vcpu_sp_el1(vcpu);
case KVM_REG_ARM_CORE_REG(elr_el1):
return __ctxt_sys_reg(&vcpu->arch.ctxt, ELR_EL1);
@@ -170,13 +170,13 @@ static void *core_reg_addr(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
KVM_REG_ARM_CORE_REG(fp_regs.vregs[31]):
off -= KVM_REG_ARM_CORE_REG(fp_regs.vregs[0]);
off /= 4;
- return &vcpu->arch.ctxt.fp_regs.vregs[off];
+ return vcpu_vreg(vcpu, off);
case KVM_REG_ARM_CORE_REG(fp_regs.fpsr):
- return &vcpu->arch.ctxt.fp_regs.fpsr;
+ return vcpu_fpsr(vcpu);
case KVM_REG_ARM_CORE_REG(fp_regs.fpcr):
- return &vcpu->arch.ctxt.fp_regs.fpcr;
+ return vcpu_fpcr(vcpu);
default:
return NULL;
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* [PATCH v8 15/29] arm64: Prepare sharing arm64 headers with s390
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (13 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 14/29] KVM: arm64: Use accessor functions for core regs Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 15:39 ` sashiko-bot
2026-09-28 15:11 ` Catalin Marinas
2026-09-18 13:30 ` [PATCH v8 16/29] arm64: Share " Steffen Eiden
` (14 subsequent siblings)
29 siblings, 2 replies; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Prepare the sharing of arm64 headers with s390 by moving definitions
inside headers to reduce the number of shared markers. Clean up includes
to further streamline the sharing of headers.
No functional change.
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/arm64/include/asm/esr.h | 4 +-
arch/arm64/include/asm/kvm_arm.h | 5 +-
arch/arm64/include/asm/kvm_emulate.h | 5 +-
arch/arm64/include/asm/kvm_host.h | 102 ++++++++++++++-------------
arch/arm64/include/asm/sysreg.h | 2 +-
5 files changed, 62 insertions(+), 56 deletions(-)
diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index f816f5d77f1a..da085c83b57e 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -7,7 +7,7 @@
#ifndef __ASM_ESR_H
#define __ASM_ESR_H
-#include <asm/memory.h>
+#include <asm/brk-imm.h>
#include <asm/sysreg.h>
#define ESR_ELx_EC_UNKNOWN UL(0x00)
@@ -435,7 +435,7 @@
#define ESR_ELx_IT_GCSPOPX 7
#ifndef __ASSEMBLER__
-#include <asm/types.h>
+#include <linux/types.h>
static inline unsigned long esr_brk_comment(unsigned long esr)
{
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 4bfbd827c5aa..57edd8437200 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -7,10 +7,11 @@
#ifndef __ARM64_KVM_ARM_H__
#define __ARM64_KVM_ARM_H__
+#include <linux/const.h>
+#include <linux/bits.h>
+#include <linux/types.h>
#include <asm/esr.h>
-#include <asm/memory.h>
#include <asm/sysreg.h>
-#include <asm/types.h>
/*
* Because I'm terribly lazy and that repainting the whole of the KVM
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index b31d50bdf59e..a34a9417ff4d 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -44,11 +44,12 @@ enum exception_type {
bool kvm_condition_valid32(const struct kvm_vcpu *vcpu);
void kvm_skip_instr32(struct kvm_vcpu *vcpu);
+int kvm_inject_dabt_excl_atomic(struct kvm_vcpu *vcpu, u64 addr);
+int kvm_inject_serror_esr(struct kvm_vcpu *vcpu, u64 esr);
+
void kvm_inject_undefined(struct kvm_vcpu *vcpu);
void kvm_inject_sync(struct kvm_vcpu *vcpu, u64 esr);
-int kvm_inject_serror_esr(struct kvm_vcpu *vcpu, u64 esr);
int kvm_inject_sea(struct kvm_vcpu *vcpu, bool iabt, u64 addr);
-int kvm_inject_dabt_excl_atomic(struct kvm_vcpu *vcpu, u64 addr);
void kvm_inject_size_fault(struct kvm_vcpu *vcpu);
static inline int kvm_inject_sea_dabt(struct kvm_vcpu *vcpu, u64 addr)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index fc0037efa0b4..1e48af601f9d 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -59,6 +59,46 @@
#define KVM_REQ_MAP_L1_VNCR_EL2 KVM_ARCH_REQ(10)
#define KVM_REQ_VGIC_PROCESS_UPDATE KVM_ARCH_REQ(11)
+/* Bit indices for kvm_arch::flags */
+enum {
+ /*
+ * If we encounter a data abort without valid instruction syndrome
+ * information, report this to user space. User space can (and
+ * should) opt in to this feature if KVM_CAP_ARM_NISV_TO_USER is
+ * supported.
+ */
+ KVM_ARCH_FLAG_RETURN_NISV_IO_ABORT_TO_USER,
+ /* Memory Tagging Extension enabled for the guest */
+ KVM_ARCH_FLAG_MTE_ENABLED,
+ /* At least one vCPU has ran in the VM */
+ KVM_ARCH_FLAG_HAS_RAN_ONCE,
+ /* The vCPU feature set for the VM is configured */
+ KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED,
+ /* PSCI SYSTEM_SUSPEND enabled for the guest */
+ KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED,
+ /* VM counter offset */
+ KVM_ARCH_FLAG_VM_COUNTER_OFFSET,
+ /* Timer PPIs made immutable */
+ KVM_ARCH_FLAG_TIMER_PPIS_IMMUTABLE,
+ /* Initial ID reg values loaded */
+ KVM_ARCH_FLAG_ID_REGS_INITIALIZED,
+ /* Fine-Grained UNDEF initialised */
+ KVM_ARCH_FLAG_FGU_INITIALIZED,
+ /* SVE exposed to guest */
+ KVM_ARCH_FLAG_GUEST_HAS_SVE,
+ /* MIDR_EL1, REVIDR_EL1, and AIDR_EL1 are writable from userspace */
+ KVM_ARCH_FLAG_WRITABLE_IMP_ID_REGS,
+ /* Unhandled SEAs are taken to userspace */
+ KVM_ARCH_FLAG_EXIT_SEA,
+};
+
+struct vcpu_reset_state {
+ unsigned long pc;
+ unsigned long r0;
+ bool be;
+ bool reset;
+};
+
#define KVM_DIRTY_LOG_MANUAL_CAPS (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
KVM_DIRTY_LOG_INITIALLY_SET)
@@ -341,35 +381,6 @@ struct kvm_arch {
/* Protects VM-scoped configuration data */
struct mutex config_lock;
- /*
- * If we encounter a data abort without valid instruction syndrome
- * information, report this to user space. User space can (and
- * should) opt in to this feature if KVM_CAP_ARM_NISV_TO_USER is
- * supported.
- */
-#define KVM_ARCH_FLAG_RETURN_NISV_IO_ABORT_TO_USER 0
- /* Memory Tagging Extension enabled for the guest */
-#define KVM_ARCH_FLAG_MTE_ENABLED 1
- /* At least one vCPU has ran in the VM */
-#define KVM_ARCH_FLAG_HAS_RAN_ONCE 2
- /* The vCPU feature set for the VM is configured */
-#define KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED 3
- /* PSCI SYSTEM_SUSPEND enabled for the guest */
-#define KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED 4
- /* VM counter offset */
-#define KVM_ARCH_FLAG_VM_COUNTER_OFFSET 5
- /* Timer PPIs made immutable */
-#define KVM_ARCH_FLAG_TIMER_PPIS_IMMUTABLE 6
- /* Initial ID reg values loaded */
-#define KVM_ARCH_FLAG_ID_REGS_INITIALIZED 7
- /* Fine-Grained UNDEF initialised */
-#define KVM_ARCH_FLAG_FGU_INITIALIZED 8
- /* SVE exposed to guest */
-#define KVM_ARCH_FLAG_GUEST_HAS_SVE 9
- /* MIDR_EL1, REVIDR_EL1, and AIDR_EL1 are writable from userspace */
-#define KVM_ARCH_FLAG_WRITABLE_IMP_ID_REGS 10
- /* Unhandled SEAs are taken to userspace */
-#define KVM_ARCH_FLAG_EXIT_SEA 11
unsigned long flags;
/* VM-wide vCPU feature set */
@@ -838,13 +849,6 @@ extern s64 kvm_nvhe_sym(hyp_physvirt_offset);
extern u64 kvm_nvhe_sym(hyp_cpu_logical_map)[NR_CPUS];
#define hyp_cpu_logical_map CHOOSE_NVHE_SYM(hyp_cpu_logical_map)
-struct vcpu_reset_state {
- unsigned long pc;
- unsigned long r0;
- bool be;
- bool reset;
-};
-
struct vncr_tlb;
struct kvm_vcpu_arch {
@@ -1049,6 +1053,11 @@ struct kvm_vcpu_arch {
/* pKVM VCPU setup completed */
#define VCPU_PKVM_FINALIZED __vcpu_single_flag(cflags, BIT(2))
+int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu, int feature);
+bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu);
+
+#define kvm_arm_vcpu_sve_finalized(vcpu) vcpu_get_flag(vcpu, VCPU_SVE_FINALIZED)
+
/* Exception pending */
#define PENDING_EXCEPTION __vcpu_single_flag(iflags, BIT(0))
/*
@@ -1242,14 +1251,6 @@ struct kvm_vcpu_stat {
u64 exits;
};
-unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
-int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
-int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
-int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
-
-unsigned long kvm_arm_num_sys_reg_descs(struct kvm_vcpu *vcpu);
-int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
-
int __kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu,
struct kvm_vcpu_events *events);
@@ -1328,6 +1329,14 @@ int __init populate_nv_trap_config(void);
void kvm_calculate_traps(struct kvm_vcpu *vcpu);
+unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
+int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
+int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+
+unsigned long kvm_arm_num_sys_reg_descs(struct kvm_vcpu *vcpu);
+int kvm_arm_copy_sys_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
+
/* MMIO helpers */
void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data);
unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
@@ -1511,11 +1520,6 @@ struct kvm *kvm_arch_alloc_vm(void);
#define vcpu_is_protected(vcpu) kvm_vm_is_protected((vcpu)->kvm)
-int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu, int feature);
-bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu);
-
-#define kvm_arm_vcpu_sve_finalized(vcpu) vcpu_get_flag(vcpu, VCPU_SVE_FINALIZED)
-
#define kvm_has_mte(kvm) \
(system_supports_mte() && \
test_bit(KVM_ARCH_FLAG_MTE_ENABLED, &(kvm)->arch.flags))
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 1aa601c95188..ab205f9db94a 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -1263,6 +1263,6 @@
FIELD_PREP(reg##_##field##_MASK, \
SYS_FIELD_VALUE(reg, field, val))
-#endif
+#endif /* __ASSEMBLER__ */
#endif /* __ASM_SYSREG_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 15/29] arm64: Prepare sharing arm64 headers with s390
2026-09-18 13:30 ` [PATCH v8 15/29] arm64: Prepare sharing arm64 headers with s390 Steffen Eiden
@ 2026-09-18 15:39 ` sashiko-bot
2026-09-28 15:11 ` Catalin Marinas
1 sibling, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 15:39 UTC (permalink / raw)
To: Steffen Eiden
Cc: Christian Borntraeger, linux-s390, Heiko Carstens, Marc Zyngier,
Vasily Gorbik, kvmarm, kvm, Alexander Gordeev, Oliver Upton
> Prepare the sharing of arm64 headers with s390 by moving definitions
> inside headers to reduce the number of shared markers. Clean up includes
> to further streamline the sharing of headers.
>
> No functional change.
>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=15
^ permalink raw reply [flat|nested] 80+ messages in thread
* Re: [PATCH v8 15/29] arm64: Prepare sharing arm64 headers with s390
2026-09-18 13:30 ` [PATCH v8 15/29] arm64: Prepare sharing arm64 headers with s390 Steffen Eiden
2026-09-18 15:39 ` sashiko-bot
@ 2026-09-28 15:11 ` Catalin Marinas
1 sibling, 0 replies; 80+ messages in thread
From: Catalin Marinas @ 2026-09-28 15:11 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390,
Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
Friedrich Welter, Fuad Tabba, Gautam Gala, Hariharan Mari,
Heiko Carstens, Hendrik Brueckner, Ilya Leoshkevich,
Janosch Frank, Joey Gouly, Marc Zyngier, Nico Boehr,
Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
On Fri, Sep 18, 2026 at 03:30:52PM +0200, Steffen Eiden wrote:
> Prepare the sharing of arm64 headers with s390 by moving definitions
> inside headers to reduce the number of shared markers. Clean up includes
> to further streamline the sharing of headers.
>
> No functional change.
>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 16/29] arm64: Share arm64 headers with s390
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (14 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 15/29] arm64: Prepare sharing arm64 headers with s390 Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 15:50 ` sashiko-bot
2026-09-28 16:07 ` Catalin Marinas
2026-09-18 13:30 ` [PATCH v8 17/29] KVM: arm64: Share arm64 code " Steffen Eiden
` (13 subsequent siblings)
29 siblings, 2 replies; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Allow sharing of arm64 headers with s390 by marking the shared regions
or add a comment that the whole file is shared.
The shared regions are marked with:
#ifdef ARM64_S390_COMMON
/* insert shared definitions here */
#endif /* ARM64_S390_COMMON */
The preprocessor symbol ARM64_S390_COMMON is always defined for arm64.
s390 later will generate its own view of arm64 headers based on the
content inside the ifdef/endif block.
No functional change.
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/arm64/Makefile | 5 +++++
arch/arm64/include/asm/brk-imm.h | 1 +
arch/arm64/include/asm/esr.h | 1 +
arch/arm64/include/asm/kvm_arm.h | 1 +
arch/arm64/include/asm/kvm_emulate.h | 18 ++++++++++++++++++
arch/arm64/include/asm/kvm_host.h | 13 +++++++++++++
arch/arm64/include/asm/ptrace.h | 4 ++++
arch/arm64/include/asm/sysreg.h | 15 +++++++++++++++
8 files changed, 58 insertions(+)
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 6b005c8fef70..12cbad460258 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -45,6 +45,11 @@ KBUILD_CFLAGS += $(CC_FLAGS_NO_FPU) \
KBUILD_CFLAGS += $(call cc-disable-warning, psabi)
KBUILD_AFLAGS += $(compat_vdso)
+# Enable all code shared to s390
+KBUILD_CFLAGS += -DARM64_S390_COMMON
+KBUILD_AFLAGS += -DARM64_S390_COMMON
+KBUILD_CPPFLAGS += -DARM64_S390_COMMON
+
ifeq ($(call rustc-min-version, 108500),y)
KBUILD_RUSTFLAGS += --target=aarch64-unknown-none-softfloat
else
diff --git a/arch/arm64/include/asm/brk-imm.h b/arch/arm64/include/asm/brk-imm.h
index beb42c62b6ac..dd2d153dc0d8 100644
--- a/arch/arm64/include/asm/brk-imm.h
+++ b/arch/arm64/include/asm/brk-imm.h
@@ -2,6 +2,7 @@
/*
* Copyright (C) 2012 ARM Ltd.
*/
+/* Whole file is shared with s390 */
#ifndef __ASM_BRK_IMM_H
#define __ASM_BRK_IMM_H
diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index da085c83b57e..2cb73bde7346 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -3,6 +3,7 @@
* Copyright (C) 2013 - ARM Ltd
* Author: Marc Zyngier <marc.zyngier@arm.com>
*/
+/* Whole file is shared with s390 */
#ifndef __ASM_ESR_H
#define __ASM_ESR_H
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 57edd8437200..678f0daed445 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -3,6 +3,7 @@
* Copyright (C) 2012,2013 - ARM Ltd
* Author: Marc Zyngier <marc.zyngier@arm.com>
*/
+/* Whole file is shared with s390 */
#ifndef __ARM64_KVM_ARM_H__
#define __ARM64_KVM_ARM_H__
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index a34a9417ff4d..09f04a5686a1 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -47,6 +47,7 @@ void kvm_skip_instr32(struct kvm_vcpu *vcpu);
int kvm_inject_dabt_excl_atomic(struct kvm_vcpu *vcpu, u64 addr);
int kvm_inject_serror_esr(struct kvm_vcpu *vcpu, u64 esr);
+#ifdef ARM64_S390_COMMON
void kvm_inject_undefined(struct kvm_vcpu *vcpu);
void kvm_inject_sync(struct kvm_vcpu *vcpu, u64 esr);
int kvm_inject_sea(struct kvm_vcpu *vcpu, bool iabt, u64 addr);
@@ -62,6 +63,8 @@ static inline int kvm_inject_sea_iabt(struct kvm_vcpu *vcpu, u64 addr)
return kvm_inject_sea(vcpu, true, addr);
}
+#endif /* ARM64_S390_COMMON */
+
static inline int kvm_inject_serror(struct kvm_vcpu *vcpu)
{
/*
@@ -185,6 +188,7 @@ static inline void vcpu_set_thumb(struct kvm_vcpu *vcpu)
*vcpu_cpsr(vcpu) |= PSR_AA32_T_BIT;
}
+#ifdef ARM64_S390_COMMON
/*
* vcpu_get_reg and vcpu_set_reg should always be passed a register number
* coming from a read of ESR_EL2. Otherwise, it may give the wrong result on
@@ -203,6 +207,8 @@ static __always_inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
vcpu_gp_regs(vcpu)[reg_num] = val;
}
+#endif /* ARM64_S390_COMMON */
+
static inline bool vcpu_is_el2_ctxt(const struct kvm_cpu_context *ctxt)
{
switch (ctxt->regs.pstate & (PSR_MODE32_BIT | PSR_MODE_MASK)) {
@@ -405,6 +411,7 @@ static inline u64 kvm_vcpu_get_disr(const struct kvm_vcpu *vcpu)
return vcpu->arch.fault.disr_el1;
}
+#ifdef ARM64_S390_COMMON
static inline u32 kvm_vcpu_hvc_get_imm(const struct kvm_vcpu *vcpu)
{
return kvm_vcpu_get_esr(vcpu) & ESR_ELx_xVC_IMM_MASK;
@@ -482,6 +489,8 @@ static __always_inline u8 kvm_vcpu_trap_get_fault(const struct kvm_vcpu *vcpu)
return kvm_vcpu_get_esr(vcpu) & ESR_ELx_FSC;
}
+#endif /* ARM64_S390_COMMON */
+
static inline
bool kvm_vcpu_trap_is_permission_fault(const struct kvm_vcpu *vcpu)
{
@@ -522,6 +531,7 @@ static __always_inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
return ESR_ELx_SYS64_ISS_RT(esr);
}
+#ifdef ARM64_S390_COMMON
static inline bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
{
if (kvm_vcpu_abt_iss1tw(vcpu)) {
@@ -546,6 +556,8 @@ static inline bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
return kvm_vcpu_dabt_iswrite(vcpu);
}
+#endif /* ARM64_S390_COMMON */
+
static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
{
return __vcpu_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK;
@@ -587,6 +599,7 @@ static inline bool kvm_vcpu_is_be(struct kvm_vcpu *vcpu)
return vcpu_read_sys_reg(vcpu, r) & bit;
}
+#ifdef ARM64_S390_COMMON
static inline unsigned long vcpu_data_guest_to_host(struct kvm_vcpu *vcpu,
unsigned long data,
unsigned int len)
@@ -662,6 +675,8 @@ static __always_inline void kvm_incr_pc(struct kvm_vcpu *vcpu)
vcpu_set_flag((v), e); \
} while (0)
+#endif /* ARM64_S390_COMMON */
+
/*
* Returns a 'sanitised' view of CPTR_EL2, translating from nVHE to the VHE
* format if E2H isn't set.
@@ -768,6 +783,7 @@ static inline void kvm_reset_fpsimd(struct kvm_vcpu *vcpu)
memset(&vcpu->arch.ctxt.fp_regs, 0, sizeof(vcpu->arch.ctxt.fp_regs));
}
+#ifdef ARM64_S390_COMMON
/* Reset a vcpu's core registers. */
static inline void kvm_reset_vcpu_core(struct kvm_vcpu *vcpu)
{
@@ -792,6 +808,8 @@ static inline void kvm_reset_vcpu_core(struct kvm_vcpu *vcpu)
*vcpu_cpsr(vcpu) = pstate;
}
+#endif /* ARM64_S390_COMMON */
+
/* PSCI reset handling for a vcpu. */
static inline void kvm_reset_vcpu_psci(struct kvm_vcpu *vcpu,
struct vcpu_reset_state *reset_state)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 1e48af601f9d..cfb74a472e9b 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -42,6 +42,7 @@
#define KVM_MAX_VCPUS VGIC_V3_MAX_CPUS
+#ifdef ARM64_S390_COMMON
#define KVM_VCPU_MAX_FEATURES 10
#define KVM_VCPU_VALID_FEATURES (BIT(KVM_VCPU_MAX_FEATURES) - 1)
@@ -99,6 +100,8 @@ struct vcpu_reset_state {
bool reset;
};
+#endif /* ARM64_S390_COMMON */
+
#define KVM_DIRTY_LOG_MANUAL_CAPS (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
KVM_DIRTY_LOG_INITIALLY_SET)
@@ -958,6 +961,7 @@ struct kvm_vcpu_arch {
pid_t pid;
};
+#ifdef ARM64_S390_COMMON
/*
* Each 'flag' is composed of a comma-separated triplet:
*
@@ -1116,6 +1120,8 @@ bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu);
/* KVM is currently emulating an L2 to L1 exception */
#define IN_NESTED_EXCEPTION __vcpu_single_flag(sflags, BIT(9))
+#endif /* ARM64_S390_COMMON */
+
#define vcpu_sve_max_vq(vcpu) sve_vq_from_vl((vcpu)->arch.sve_max_vl)
#define vcpu_sve_zcr_elx(vcpu) \
@@ -1329,6 +1335,7 @@ int __init populate_nv_trap_config(void);
void kvm_calculate_traps(struct kvm_vcpu *vcpu);
+#ifdef ARM64_S390_COMMON
unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu);
int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices);
int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
@@ -1344,6 +1351,8 @@ unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len);
int kvm_handle_mmio_return(struct kvm_vcpu *vcpu);
int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa);
+#endif /* ARM64_S390_COMMON */
+
/*
* Returns true if a Performance Monitoring Interrupt (PMI), a.k.a. perf event,
* arrived in guest context. For arm64, any event that arrives while a vCPU is
@@ -1536,11 +1545,15 @@ static inline bool __vcpu_has_feature(const struct kvm_arch *ka, int feature)
return test_bit(feature, ka->vcpu_features);
}
+#ifdef ARM64_S390_COMMON
+
#define kvm_vcpu_has_feature(k, f) __vcpu_has_feature(&(k)->arch, (f))
#define vcpu_has_feature(v, f) __vcpu_has_feature(&(v)->kvm->arch, (f))
#define kvm_vcpu_initialized(v) vcpu_get_flag(v, VCPU_INITIALIZED)
+#endif /* ARM64_S390_COMMON */
+
int kvm_trng_call(struct kvm_vcpu *vcpu);
#ifdef CONFIG_KVM
extern phys_addr_t hyp_mem_base;
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 49a83a0636b9..05c1307fa62f 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -26,6 +26,8 @@
#define GIC_PRIO_PSR_I_SET GICV3_PRIO_PSR_I_SET
+#ifdef ARM64_S390_COMMON
+
/* Additional SPSR bits not exposed in the UABI */
#define PSR_MODE_THREAD_BIT (1 << 0)
#define PSR_IL_BIT (1 << 20)
@@ -66,6 +68,8 @@
#define PSR_AA32_IT_MASK 0x0600fc00 /* If-Then execution state mask */
#define PSR_AA32_GE_MASK 0x000f0000
+#endif /* ARM64_S390_COMMON */
+
#ifdef CONFIG_CPU_BIG_ENDIAN
#define PSR_AA32_ENDSTATE PSR_AA32_E_BIT
#else
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index ab205f9db94a..1c5c4df260be 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -16,6 +16,8 @@
#include <asm/gpr-num.h>
+#ifdef ARM64_S390_COMMON
+
/*
* ARMv8 ARM reserves the following encoding for system registers:
* (Ref: ARMv8 ARM, Section: "System instruction class encoding overview",
@@ -50,6 +52,8 @@
#define sys_reg_CRm(id) (((id) >> CRm_shift) & CRm_mask)
#define sys_reg_Op2(id) (((id) >> Op2_shift) & Op2_mask)
+#endif /* ARM64_S390_COMMON */
+
#ifndef CONFIG_BROKEN_GAS_INST
#ifdef __ASSEMBLER__
@@ -123,6 +127,8 @@
#define GSB_SYS_BARRIER_INSN __SYS_BARRIER_INSN(1, 0, 12, 0, 0, 31)
#define GSB_ACK_BARRIER_INSN __SYS_BARRIER_INSN(1, 0, 12, 0, 1, 31)
+#ifdef ARM64_S390_COMMON
+
/* Data cache zero operations */
#define SYS_DC_ISW sys_insn(1, 0, 7, 6, 2)
#define SYS_DC_IGSW sys_insn(1, 0, 7, 6, 4)
@@ -832,6 +838,8 @@
#define SCTLR_ELx_A (BIT(1))
#define SCTLR_ELx_M (BIT(0))
+#endif /* ARM64_S390_COMMON */
+
#ifdef CONFIG_CPU_BIG_ENDIAN
#define ENDIAN_SET_EL2 SCTLR_ELx_EE
#else
@@ -866,6 +874,7 @@
SCTLR_EL1_LSMAOE | SCTLR_EL1_nTLSMD | SCTLR_EL1_EIS | \
SCTLR_EL1_TSCXT | SCTLR_EL1_EOS)
+#ifdef ARM64_S390_COMMON
/* MAIR_ELx memory attributes (used by Linux) */
#define MAIR_ATTR_DEVICE_nGnRnE UL(0x00)
#define MAIR_ATTR_DEVICE_nGnRE UL(0x04)
@@ -1102,6 +1111,8 @@
#define GICV5_GICR_CDNMIA_TYPE_MASK GENMASK_ULL(31, 29)
#define GICV5_GICR_CDNMIA_ID_MASK GENMASK_ULL(23, 0)
+#endif /* ARM64_S390_COMMON */
+
#define gicr_insn(insn) read_sysreg_s(GICV5_OP_GICR_##insn)
#define gic_insn(v, insn) write_sysreg_s(v, GICV5_OP_GIC_##insn)
@@ -1251,6 +1262,8 @@
par; \
})
+#ifdef ARM64_S390_COMMON
+
#define SYS_FIELD_VALUE(reg, field, val) reg##_##field##_##val
#define SYS_FIELD_GET(reg, field, val) \
@@ -1263,6 +1276,8 @@
FIELD_PREP(reg##_##field##_MASK, \
SYS_FIELD_VALUE(reg, field, val))
+#endif /* ARM64_S390_COMMON */
+
#endif /* __ASSEMBLER__ */
#endif /* __ASM_SYSREG_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 16/29] arm64: Share arm64 headers with s390
2026-09-18 13:30 ` [PATCH v8 16/29] arm64: Share " Steffen Eiden
@ 2026-09-18 15:50 ` sashiko-bot
2026-09-28 16:07 ` Catalin Marinas
1 sibling, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 15:50 UTC (permalink / raw)
To: Steffen Eiden
Cc: Christian Borntraeger, Vasily Gorbik, linux-s390, Marc Zyngier,
Heiko Carstens, kvmarm, Alexander Gordeev, Oliver Upton, kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] build: fragile cross-architecture coupling via text extraction
--
commit 7c91cae0fde64b5f320fb846c975eb58dd534362
Author: Steffen Eiden <seiden@linux.ibm.com>
arm64: Share arm64 headers with s390
This commit prepares arm64 headers to be shared with s390 by adding
ifdef markers and comments. A preprocessor symbol is added to the arm64
Makefile to keep the code active on arm64 while s390 can extract it.
> diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> index 6b005c8fef706..12cbad460258f 100644
> --- a/arch/arm64/Makefile
> +++ b/arch/arm64/Makefile
> @@ -45,6 +45,11 @@ KBUILD_CFLAGS += $(CC_FLAGS_NO_FPU) \
> KBUILD_CFLAGS += $(call cc-disable-warning, psabi)
> KBUILD_AFLAGS += $(compat_vdso)
>
> +# Enable all code shared to s390
> +KBUILD_CFLAGS += -DARM64_S390_COMMON
[Severity: Low]
Does adding a global define purely to wrap code for an s390 extraction
script create a fragile build coupling? This couples the s390 build to
the exact formatting and macro placement in arm64 headers.
> +KBUILD_AFLAGS += -DARM64_S390_COMMON
> +KBUILD_CPPFLAGS += -DARM64_S390_COMMON
> +
[ ... ]
> diff --git a/arch/arm64/include/asm/brk-imm.h b/arch/arm64/include/asm/brk-imm.h
> index beb42c62b6acc..dd2d153dc0d81 100644
> --- a/arch/arm64/include/asm/brk-imm.h
> +++ b/arch/arm64/include/asm/brk-imm.h
> @@ -2,6 +2,7 @@
> /*
> * Copyright (C) 2012 ARM Ltd.
> */
> +/* Whole file is shared with s390 */
[Severity: Low]
Is it robust to rely on an informal textual comment to drive cross-architecture
sharing instead of moving the file to an architecture-neutral location like
asm-generic? Normal refactoring by arm64 maintainers could trivially break
the s390 build if they remove or modify these marker comments.
>
> #ifndef __ASM_BRK_IMM_H
> #define __ASM_BRK_IMM_H
[ ... ]
> diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
> index a34a9417ff4da..09f04a5686a18 100644
> --- a/arch/arm64/include/asm/kvm_emulate.h
> +++ b/arch/arm64/include/asm/kvm_emulate.h
> @@ -47,6 +47,7 @@ void kvm_skip_instr32(struct kvm_vcpu *vcpu);
> int kvm_inject_dabt_excl_atomic(struct kvm_vcpu *vcpu, u64 addr);
> int kvm_inject_serror_esr(struct kvm_vcpu *vcpu, u64 esr);
>
> +#ifdef ARM64_S390_COMMON
> void kvm_inject_undefined(struct kvm_vcpu *vcpu);
[Severity: Low]
Could this genuinely shared component be factored into a common include
directory like include/kvm or include/linux instead of being spliced via
build-time regex parsing? Adding s390-specific extraction guards into
arm64 headers requires arm64 maintainers to accommodate s390 build scripts
when modifying ifdef boundaries.
> void kvm_inject_sync(struct kvm_vcpu *vcpu, u64 esr);
> int kvm_inject_sea(struct kvm_vcpu *vcpu, bool iabt, u64 addr);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=16
^ permalink raw reply [flat|nested] 80+ messages in thread
* Re: [PATCH v8 16/29] arm64: Share arm64 headers with s390
2026-09-18 13:30 ` [PATCH v8 16/29] arm64: Share " Steffen Eiden
2026-09-18 15:50 ` sashiko-bot
@ 2026-09-28 16:07 ` Catalin Marinas
2026-09-28 16:23 ` Steffen Eiden
1 sibling, 1 reply; 80+ messages in thread
From: Catalin Marinas @ 2026-09-28 16:07 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390,
Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
Friedrich Welter, Fuad Tabba, Gautam Gala, Hariharan Mari,
Heiko Carstens, Hendrik Brueckner, Ilya Leoshkevich,
Janosch Frank, Joey Gouly, Marc Zyngier, Nico Boehr,
Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
On Fri, Sep 18, 2026 at 03:30:53PM +0200, Steffen Eiden wrote:
> diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> index 6b005c8fef70..12cbad460258 100644
> --- a/arch/arm64/Makefile
> +++ b/arch/arm64/Makefile
> @@ -45,6 +45,11 @@ KBUILD_CFLAGS += $(CC_FLAGS_NO_FPU) \
> KBUILD_CFLAGS += $(call cc-disable-warning, psabi)
> KBUILD_AFLAGS += $(compat_vdso)
>
> +# Enable all code shared to s390
> +KBUILD_CFLAGS += -DARM64_S390_COMMON
> +KBUILD_AFLAGS += -DARM64_S390_COMMON
> +KBUILD_CPPFLAGS += -DARM64_S390_COMMON
Do we actually need these defines? They seem only to be used as markers
for the awk scripts to extract the definitions. Why do we need the C
preprocessor involved at all? Could we not just have comment markers:
/* ARM64_S390_COMMON_BEGIN */
...
/* ARM64_S390_COMMON_END */
(also the CPPFLAGS definition was enough, it gets copied into the others
automatically)
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index ab205f9db94a..1c5c4df260be 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -16,6 +16,8 @@
>
> #include <asm/gpr-num.h>
>
> +#ifdef ARM64_S390_COMMON
> +
> /*
> * ARMv8 ARM reserves the following encoding for system registers:
> * (Ref: ARMv8 ARM, Section: "System instruction class encoding overview",
> @@ -50,6 +52,8 @@
> #define sys_reg_CRm(id) (((id) >> CRm_shift) & CRm_mask)
> #define sys_reg_Op2(id) (((id) >> Op2_shift) & Op2_mask)
>
> +#endif /* ARM64_S390_COMMON */
> +
> #ifndef CONFIG_BROKEN_GAS_INST
>
> #ifdef __ASSEMBLER__
> @@ -123,6 +127,8 @@
> #define GSB_SYS_BARRIER_INSN __SYS_BARRIER_INSN(1, 0, 12, 0, 0, 31)
> #define GSB_ACK_BARRIER_INSN __SYS_BARRIER_INSN(1, 0, 12, 0, 1, 31)
>
> +#ifdef ARM64_S390_COMMON
> +
> /* Data cache zero operations */
> #define SYS_DC_ISW sys_insn(1, 0, 7, 6, 2)
> #define SYS_DC_IGSW sys_insn(1, 0, 7, 6, 4)
> @@ -832,6 +838,8 @@
> #define SCTLR_ELx_A (BIT(1))
> #define SCTLR_ELx_M (BIT(0))
>
> +#endif /* ARM64_S390_COMMON */
> +
> #ifdef CONFIG_CPU_BIG_ENDIAN
> #define ENDIAN_SET_EL2 SCTLR_ELx_EE
> #else
> @@ -866,6 +874,7 @@
> SCTLR_EL1_LSMAOE | SCTLR_EL1_nTLSMD | SCTLR_EL1_EIS | \
> SCTLR_EL1_TSCXT | SCTLR_EL1_EOS)
>
> +#ifdef ARM64_S390_COMMON
> /* MAIR_ELx memory attributes (used by Linux) */
> #define MAIR_ATTR_DEVICE_nGnRnE UL(0x00)
> #define MAIR_ATTR_DEVICE_nGnRE UL(0x04)
> @@ -1102,6 +1111,8 @@
> #define GICV5_GICR_CDNMIA_TYPE_MASK GENMASK_ULL(31, 29)
> #define GICV5_GICR_CDNMIA_ID_MASK GENMASK_ULL(23, 0)
>
> +#endif /* ARM64_S390_COMMON */
I haven't checked them all but there are a few definitions in here that
depend on arm64-specific configs: e.g. GCR depends on KASAN, TGRAN
macros depend on page size, PA_BITS_52 influences some other values.
I think they should be outside the common definitions shared with s390.
In addition, the awk scripts should reject any CONFIG_ (or at least
CONFIG_ARM64_) lines in the copied files. Ideally report an error rather
than silently masking them out.
--
Catalin
^ permalink raw reply [flat|nested] 80+ messages in thread
* Re: [PATCH v8 16/29] arm64: Share arm64 headers with s390
2026-09-28 16:07 ` Catalin Marinas
@ 2026-09-28 16:23 ` Steffen Eiden
2026-09-29 4:19 ` Andreas Grapentin
0 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-28 16:23 UTC (permalink / raw)
To: Catalin Marinas
Cc: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390,
Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
Friedrich Welter, Fuad Tabba, Gautam Gala, Hariharan Mari,
Heiko Carstens, Hendrik Brueckner, Ilya Leoshkevich,
Janosch Frank, Joey Gouly, Marc Zyngier, Nico Boehr,
Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
On Mon, Sep 28, 2026 at 05:07:52PM +0100, Catalin Marinas wrote:
> On Fri, Sep 18, 2026 at 03:30:53PM +0200, Steffen Eiden wrote:
> > diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
> > index 6b005c8fef70..12cbad460258 100644
> > --- a/arch/arm64/Makefile
> > +++ b/arch/arm64/Makefile
> > @@ -45,6 +45,11 @@ KBUILD_CFLAGS += $(CC_FLAGS_NO_FPU) \
> > KBUILD_CFLAGS += $(call cc-disable-warning, psabi)
> > KBUILD_AFLAGS += $(compat_vdso)
> >
> > +# Enable all code shared to s390
> > +KBUILD_CFLAGS += -DARM64_S390_COMMON
> > +KBUILD_AFLAGS += -DARM64_S390_COMMON
> > +KBUILD_CPPFLAGS += -DARM64_S390_COMMON
>
> Do we actually need these defines? They seem only to be used as markers
> for the awk scripts to extract the definitions. Why do we need the C
> preprocessor involved at all? Could we not just have comment markers:
>
> /* ARM64_S390_COMMON_BEGIN */
> ...
> /* ARM64_S390_COMMON_END */
>
No technically we do not need those. They could be useful if we find out
that AWK is the wrong tool and move to a C Preprocessor + diff based
approach.
if the ifdev is not closed the compiler will complain, but an 'arm did
not destroy us' verifiaction tool ( I will send one soonish) could do
the same.
If the idfef thing is a no-go for you I can use the solely comment based
approach.
> (also the CPPFLAGS definition was enough, it gets copied into the others
> automatically)
ok
>
> > diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> > index ab205f9db94a..1c5c4df260be 100644
> > --- a/arch/arm64/include/asm/sysreg.h
> > +++ b/arch/arm64/include/asm/sysreg.h
> > @@ -16,6 +16,8 @@
> >
> > #include <asm/gpr-num.h>
> >
> > +#ifdef ARM64_S390_COMMON
> > +
> > /*
> > * ARMv8 ARM reserves the following encoding for system registers:
> > * (Ref: ARMv8 ARM, Section: "System instruction class encoding overview",
> > @@ -50,6 +52,8 @@
> > #define sys_reg_CRm(id) (((id) >> CRm_shift) & CRm_mask)
> > #define sys_reg_Op2(id) (((id) >> Op2_shift) & Op2_mask)
> >
> > +#endif /* ARM64_S390_COMMON */
> > +
> > #ifndef CONFIG_BROKEN_GAS_INST
> >
> > #ifdef __ASSEMBLER__
> > @@ -123,6 +127,8 @@
> > #define GSB_SYS_BARRIER_INSN __SYS_BARRIER_INSN(1, 0, 12, 0, 0, 31)
> > #define GSB_ACK_BARRIER_INSN __SYS_BARRIER_INSN(1, 0, 12, 0, 1, 31)
> >
> > +#ifdef ARM64_S390_COMMON
> > +
> > /* Data cache zero operations */
> > #define SYS_DC_ISW sys_insn(1, 0, 7, 6, 2)
> > #define SYS_DC_IGSW sys_insn(1, 0, 7, 6, 4)
> > @@ -832,6 +838,8 @@
> > #define SCTLR_ELx_A (BIT(1))
> > #define SCTLR_ELx_M (BIT(0))
> >
> > +#endif /* ARM64_S390_COMMON */
> > +
> > #ifdef CONFIG_CPU_BIG_ENDIAN
> > #define ENDIAN_SET_EL2 SCTLR_ELx_EE
> > #else
> > @@ -866,6 +874,7 @@
> > SCTLR_EL1_LSMAOE | SCTLR_EL1_nTLSMD | SCTLR_EL1_EIS | \
> > SCTLR_EL1_TSCXT | SCTLR_EL1_EOS)
> >
> > +#ifdef ARM64_S390_COMMON
> > /* MAIR_ELx memory attributes (used by Linux) */
> > #define MAIR_ATTR_DEVICE_nGnRnE UL(0x00)
> > #define MAIR_ATTR_DEVICE_nGnRE UL(0x04)
> > @@ -1102,6 +1111,8 @@
> > #define GICV5_GICR_CDNMIA_TYPE_MASK GENMASK_ULL(31, 29)
> > #define GICV5_GICR_CDNMIA_ID_MASK GENMASK_ULL(23, 0)
> >
> > +#endif /* ARM64_S390_COMMON */
>
> I haven't checked them all but there are a few definitions in here that
> depend on arm64-specific configs: e.g. GCR depends on KASAN, TGRAN
> macros depend on page size, PA_BITS_52 influences some other values.
>
> I think they should be outside the common definitions shared with s390.
> In addition, the awk scripts should reject any CONFIG_ (or at least
> CONFIG_ARM64_) lines in the copied files. Ideally report an error rather
> than silently masking them out.
>
Upon Marcs request (and to keep me sane) we deliberately share more
header stuff than we actually need to
a) keep the number of shared regions low
b) have fewer prepare changes moving things to satisfy a
I do not see an issue if we have a few things shared that are only
active on ARM due to a CONFIG.
Steffen
> --
> Catalin
^ permalink raw reply [flat|nested] 80+ messages in thread
* Re: [PATCH v8 16/29] arm64: Share arm64 headers with s390
2026-09-28 16:23 ` Steffen Eiden
@ 2026-09-29 4:19 ` Andreas Grapentin
2026-09-29 17:00 ` Catalin Marinas
0 siblings, 1 reply; 80+ messages in thread
From: Andreas Grapentin @ 2026-09-29 4:19 UTC (permalink / raw)
To: Steffen Eiden
Cc: Catalin Marinas, kvm, kvmarm, linux-arm-kernel, linux-kernel,
linux-s390, Alexander Gordeev, Arnd Bergmann,
Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
Friedrich Welter, Fuad Tabba, Gautam Gala, Hariharan Mari,
Heiko Carstens, Hendrik Brueckner, Ilya Leoshkevich,
Janosch Frank, Joey Gouly, Marc Zyngier, Nico Boehr,
Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
On Sep 28 26, Steffen Eiden wrote:
> On Mon, Sep 28, 2026 at 05:07:52PM +0100, Catalin Marinas wrote:
> > On Fri, Sep 18, 2026 at 03:30:53PM +0200, Steffen Eiden wrote:
> > > +# Enable all code shared to s390
> > > +KBUILD_CFLAGS += -DARM64_S390_COMMON
> > > +KBUILD_AFLAGS += -DARM64_S390_COMMON
> > > +KBUILD_CPPFLAGS += -DARM64_S390_COMMON
> >
> > Do we actually need these defines? They seem only to be used as markers
> > for the awk scripts to extract the definitions. Why do we need the C
> > preprocessor involved at all? Could we not just have comment markers:
> >
> > /* ARM64_S390_COMMON_BEGIN */
> > ...
> > /* ARM64_S390_COMMON_END */
> >
> No technically we do not need those. They could be useful if we find out
> that AWK is the wrong tool and move to a C Preprocessor + diff based
> approach.
>
> if the ifdev is not closed the compiler will complain, but an 'arm did
> not destroy us' verifiaction tool ( I will send one soonish) could do
> the same.
iirc the last time we discussed this we didn't think that load-bearing
comments were the right tool here. We also briefly floated the idea of
using a #pragma region based approach, but in the end we went with the
#ifdef preprocessor directives instead, as the least invasive
non-comment marker that was available.
Best,
Andreas
^ permalink raw reply [flat|nested] 80+ messages in thread
* Re: [PATCH v8 16/29] arm64: Share arm64 headers with s390
2026-09-29 4:19 ` Andreas Grapentin
@ 2026-09-29 17:00 ` Catalin Marinas
2026-09-30 7:28 ` Steffen Eiden
0 siblings, 1 reply; 80+ messages in thread
From: Catalin Marinas @ 2026-09-29 17:00 UTC (permalink / raw)
To: Andreas Grapentin
Cc: Steffen Eiden, kvm, kvmarm, linux-arm-kernel, linux-kernel,
linux-s390, Alexander Gordeev, Arnd Bergmann,
Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
Friedrich Welter, Fuad Tabba, Gautam Gala, Hariharan Mari,
Heiko Carstens, Hendrik Brueckner, Ilya Leoshkevich,
Janosch Frank, Joey Gouly, Marc Zyngier, Nico Boehr,
Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
On Tue, Sep 29, 2026 at 06:19:20AM +0200, Andreas Grapentin wrote:
> On Sep 28 26, Steffen Eiden wrote:
> > On Mon, Sep 28, 2026 at 05:07:52PM +0100, Catalin Marinas wrote:
> > > On Fri, Sep 18, 2026 at 03:30:53PM +0200, Steffen Eiden wrote:
> > > > +# Enable all code shared to s390
> > > > +KBUILD_CFLAGS += -DARM64_S390_COMMON
> > > > +KBUILD_AFLAGS += -DARM64_S390_COMMON
> > > > +KBUILD_CPPFLAGS += -DARM64_S390_COMMON
> > >
> > > Do we actually need these defines? They seem only to be used as markers
> > > for the awk scripts to extract the definitions. Why do we need the C
> > > preprocessor involved at all? Could we not just have comment markers:
> > >
> > > /* ARM64_S390_COMMON_BEGIN */
> > > ...
> > > /* ARM64_S390_COMMON_END */
> > >
> > No technically we do not need those. They could be useful if we find out
> > that AWK is the wrong tool and move to a C Preprocessor + diff based
> > approach.
> >
> > if the ifdev is not closed the compiler will complain, but an 'arm did
> > not destroy us' verifiaction tool ( I will send one soonish) could do
> > the same.
>
> iirc the last time we discussed this we didn't think that load-bearing
> comments were the right tool here. We also briefly floated the idea of
> using a #pragma region based approach, but in the end we went with the
> #ifdef preprocessor directives instead, as the least invasive
> non-comment marker that was available.
The downside is that the macro affects the preprocessed code. We need to
ensure they don't leak in uapi headers for example. Not a fan of this
approach but I don't have a better suggestion either. At least we could
write them as:
#if ARM64_S390_COMMON == 1
so we get an error if someone misspells the macro name (or they leak in
uapi headers, vDSO).
It would also be useful for the awk scripts look for the paired #endif
rather than relying on the comment at the end of the line. Otherwise
it's not really different from just sticking to comments.
--
Catalin
^ permalink raw reply [flat|nested] 80+ messages in thread
* Re: [PATCH v8 16/29] arm64: Share arm64 headers with s390
2026-09-29 17:00 ` Catalin Marinas
@ 2026-09-30 7:28 ` Steffen Eiden
2026-09-30 7:55 ` Marc Zyngier
0 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-30 7:28 UTC (permalink / raw)
To: Catalin Marinas
Cc: Andreas Grapentin, kvm, kvmarm, linux-arm-kernel, linux-kernel,
linux-s390, Alexander Gordeev, Arnd Bergmann,
Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
Friedrich Welter, Fuad Tabba, Gautam Gala, Hariharan Mari,
Heiko Carstens, Hendrik Brueckner, Ilya Leoshkevich,
Janosch Frank, Joey Gouly, Marc Zyngier, Nico Boehr,
Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
On Tue, Sep 29, 2026 at 06:00:12PM +0100, Catalin Marinas wrote:
> On Tue, Sep 29, 2026 at 06:19:20AM +0200, Andreas Grapentin wrote:
> > On Sep 28 26, Steffen Eiden wrote:
> > > On Mon, Sep 28, 2026 at 05:07:52PM +0100, Catalin Marinas wrote:
> > > > On Fri, Sep 18, 2026 at 03:30:53PM +0200, Steffen Eiden wrote:
> > > > > +# Enable all code shared to s390
> > > > > +KBUILD_CFLAGS += -DARM64_S390_COMMON
> > > > > +KBUILD_AFLAGS += -DARM64_S390_COMMON
> > > > > +KBUILD_CPPFLAGS += -DARM64_S390_COMMON
> > > >
> > > > Do we actually need these defines? They seem only to be used as markers
> > > > for the awk scripts to extract the definitions. Why do we need the C
> > > > preprocessor involved at all? Could we not just have comment markers:
> > > >
> > > > /* ARM64_S390_COMMON_BEGIN */
> > > > ...
> > > > /* ARM64_S390_COMMON_END */
> > > >
> > > No technically we do not need those. They could be useful if we find out
> > > that AWK is the wrong tool and move to a C Preprocessor + diff based
> > > approach.
> > >
> > > if the ifdev is not closed the compiler will complain, but an 'arm did
> > > not destroy us' verifiaction tool ( I will send one soonish) could do
> > > the same.
> >
> > iirc the last time we discussed this we didn't think that load-bearing
> > comments were the right tool here. We also briefly floated the idea of
> > using a #pragma region based approach, but in the end we went with the
> > #ifdef preprocessor directives instead, as the least invasive
> > non-comment marker that was available.
>
> The downside is that the macro affects the preprocessed code. We need to
> ensure they don't leak in uapi headers for example. Not a fan of this
> approach but I don't have a better suggestion either. At least we could
> write them as:
>
> #if ARM64_S390_COMMON == 1
This is a great idea and an improvement. Thanks.
@Marc: Shall I sent a v9 of this series or do you want to pick v8 and I
send this as an improvement once picked?
Regarding UAPI: We will either import the whole uapi header or noting.
We will not modify ARM uapi headers for the arm64 on s390 feature.
>
> so we get an error if someone misspells the macro name (or they leak in
> uapi headers, vDSO).
>
> It would also be useful for the awk scripts look for the paired #endif
> rather than relying on the comment at the end of the line. Otherwise
> it's not really different from just sticking to comments.
>
Are you suggesting that the AWK scripts should track the #if% and #endif
in the code and warn or reject if the marked endif for the shared code
does not match pairing with the starting #if? That makes sense yes. I'll
investigate and would add this as an improvement later on.
Steffen
^ permalink raw reply [flat|nested] 80+ messages in thread
* Re: [PATCH v8 16/29] arm64: Share arm64 headers with s390
2026-09-30 7:28 ` Steffen Eiden
@ 2026-09-30 7:55 ` Marc Zyngier
2026-09-30 8:18 ` Will Deacon
2026-09-30 8:53 ` Steffen Eiden
0 siblings, 2 replies; 80+ messages in thread
From: Marc Zyngier @ 2026-09-30 7:55 UTC (permalink / raw)
To: Steffen Eiden
Cc: Catalin Marinas, Andreas Grapentin, kvm, kvmarm, linux-arm-kernel,
linux-kernel, linux-s390, Alexander Gordeev, Arnd Bergmann,
Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
Friedrich Welter, Fuad Tabba, Gautam Gala, Hariharan Mari,
Heiko Carstens, Hendrik Brueckner, Ilya Leoshkevich,
Janosch Frank, Joey Gouly, Nico Boehr, Nina Schoetterl-Glausch,
Oliver Upton, Paolo Bonzini, Suzuki K Poulose, Sven Schnelle,
Ulrich Weigand, Vasily Gorbik, Will Deacon, Zenghui Yu
On Wed, 30 Sep 2026 08:28:03 +0100,
Steffen Eiden <seiden@linux.ibm.com> wrote:
>
> On Tue, Sep 29, 2026 at 06:00:12PM +0100, Catalin Marinas wrote:
> > On Tue, Sep 29, 2026 at 06:19:20AM +0200, Andreas Grapentin wrote:
> > > On Sep 28 26, Steffen Eiden wrote:
> > > > On Mon, Sep 28, 2026 at 05:07:52PM +0100, Catalin Marinas wrote:
> > > > > On Fri, Sep 18, 2026 at 03:30:53PM +0200, Steffen Eiden wrote:
> > > > > > +# Enable all code shared to s390
> > > > > > +KBUILD_CFLAGS += -DARM64_S390_COMMON
> > > > > > +KBUILD_AFLAGS += -DARM64_S390_COMMON
> > > > > > +KBUILD_CPPFLAGS += -DARM64_S390_COMMON
> > > > >
> > > > > Do we actually need these defines? They seem only to be used as markers
> > > > > for the awk scripts to extract the definitions. Why do we need the C
> > > > > preprocessor involved at all? Could we not just have comment markers:
> > > > >
> > > > > /* ARM64_S390_COMMON_BEGIN */
> > > > > ...
> > > > > /* ARM64_S390_COMMON_END */
> > > > >
> > > > No technically we do not need those. They could be useful if we find out
> > > > that AWK is the wrong tool and move to a C Preprocessor + diff based
> > > > approach.
> > > >
> > > > if the ifdev is not closed the compiler will complain, but an 'arm did
> > > > not destroy us' verifiaction tool ( I will send one soonish) could do
> > > > the same.
> > >
> > > iirc the last time we discussed this we didn't think that load-bearing
> > > comments were the right tool here. We also briefly floated the idea of
> > > using a #pragma region based approach, but in the end we went with the
> > > #ifdef preprocessor directives instead, as the least invasive
> > > non-comment marker that was available.
> >
> > The downside is that the macro affects the preprocessed code. We need to
> > ensure they don't leak in uapi headers for example. Not a fan of this
> > approach but I don't have a better suggestion either. At least we could
> > write them as:
> >
> > #if ARM64_S390_COMMON == 1
>
> This is a great idea and an improvement. Thanks.
>
> @Marc: Shall I sent a v9 of this series or do you want to pick v8 and I
> send this as an improvement once picked?
Please send a v9. That's invasive enough that it warrants it.
> > It would also be useful for the awk scripts look for the paired #endif
> > rather than relying on the comment at the end of the line. Otherwise
> > it's not really different from just sticking to comments.
> >
>
> Are you suggesting that the AWK scripts should track the #if% and #endif
> in the code and warn or reject if the marked endif for the shared code
> does not match pairing with the starting #if? That makes sense yes. I'll
> investigate and would add this as an improvement later on.
I think the suggestion is to teach the script about the #if/#endif
nesting, and therefore to not require the trailing comment on #endif
(i.e. the script acts as a normal cpp).
It should only be a matter of counting the #{if,ifdef}s and #endif
past the ARM64_S390_COMMON guard.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 80+ messages in thread* Re: [PATCH v8 16/29] arm64: Share arm64 headers with s390
2026-09-30 7:55 ` Marc Zyngier
@ 2026-09-30 8:18 ` Will Deacon
2026-09-30 8:53 ` Steffen Eiden
1 sibling, 0 replies; 80+ messages in thread
From: Will Deacon @ 2026-09-30 8:18 UTC (permalink / raw)
To: Marc Zyngier
Cc: Steffen Eiden, Catalin Marinas, Andreas Grapentin, kvm, kvmarm,
linux-arm-kernel, linux-kernel, linux-s390, Alexander Gordeev,
Arnd Bergmann, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Nico Boehr,
Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Zenghui Yu
On Wed, Sep 30, 2026 at 08:55:49AM +0100, Marc Zyngier wrote:
> On Wed, 30 Sep 2026 08:28:03 +0100,
> Steffen Eiden <seiden@linux.ibm.com> wrote:
> >
> > On Tue, Sep 29, 2026 at 06:00:12PM +0100, Catalin Marinas wrote:
> > > On Tue, Sep 29, 2026 at 06:19:20AM +0200, Andreas Grapentin wrote:
> > > > On Sep 28 26, Steffen Eiden wrote:
> > > > > On Mon, Sep 28, 2026 at 05:07:52PM +0100, Catalin Marinas wrote:
> > > > > > On Fri, Sep 18, 2026 at 03:30:53PM +0200, Steffen Eiden wrote:
> > > > > > > +# Enable all code shared to s390
> > > > > > > +KBUILD_CFLAGS += -DARM64_S390_COMMON
> > > > > > > +KBUILD_AFLAGS += -DARM64_S390_COMMON
> > > > > > > +KBUILD_CPPFLAGS += -DARM64_S390_COMMON
> > > > > >
> > > > > > Do we actually need these defines? They seem only to be used as markers
> > > > > > for the awk scripts to extract the definitions. Why do we need the C
> > > > > > preprocessor involved at all? Could we not just have comment markers:
> > > > > >
> > > > > > /* ARM64_S390_COMMON_BEGIN */
> > > > > > ...
> > > > > > /* ARM64_S390_COMMON_END */
> > > > > >
> > > > > No technically we do not need those. They could be useful if we find out
> > > > > that AWK is the wrong tool and move to a C Preprocessor + diff based
> > > > > approach.
> > > > >
> > > > > if the ifdev is not closed the compiler will complain, but an 'arm did
> > > > > not destroy us' verifiaction tool ( I will send one soonish) could do
> > > > > the same.
> > > >
> > > > iirc the last time we discussed this we didn't think that load-bearing
> > > > comments were the right tool here. We also briefly floated the idea of
> > > > using a #pragma region based approach, but in the end we went with the
> > > > #ifdef preprocessor directives instead, as the least invasive
> > > > non-comment marker that was available.
> > >
> > > The downside is that the macro affects the preprocessed code. We need to
> > > ensure they don't leak in uapi headers for example. Not a fan of this
> > > approach but I don't have a better suggestion either. At least we could
> > > write them as:
> > >
> > > #if ARM64_S390_COMMON == 1
> >
> > This is a great idea and an improvement. Thanks.
> >
> > @Marc: Shall I sent a v9 of this series or do you want to pick v8 and I
> > send this as an improvement once picked?
>
> Please send a v9. That's invasive enough that it warrants it.
>
> > > It would also be useful for the awk scripts look for the paired #endif
> > > rather than relying on the comment at the end of the line. Otherwise
> > > it's not really different from just sticking to comments.
> > >
> >
> > Are you suggesting that the AWK scripts should track the #if% and #endif
> > in the code and warn or reject if the marked endif for the shared code
> > does not match pairing with the starting #if? That makes sense yes. I'll
> > investigate and would add this as an improvement later on.
>
> I think the suggestion is to teach the script about the #if/#endif
> nesting, and therefore to not require the trailing comment on #endif
> (i.e. the script acts as a normal cpp).
>
> It should only be a matter of counting the #{if,ifdef}s and #endif
> past the ARM64_S390_COMMON guard.
Yeah, and the check on the comment anchor could still remain as a rough
consistency check.
Will
^ permalink raw reply [flat|nested] 80+ messages in thread* Re: [PATCH v8 16/29] arm64: Share arm64 headers with s390
2026-09-30 7:55 ` Marc Zyngier
2026-09-30 8:18 ` Will Deacon
@ 2026-09-30 8:53 ` Steffen Eiden
1 sibling, 0 replies; 80+ messages in thread
From: Steffen Eiden @ 2026-09-30 8:53 UTC (permalink / raw)
To: Marc Zyngier
Cc: Catalin Marinas, Andreas Grapentin, kvm, kvmarm, linux-arm-kernel,
linux-kernel, linux-s390, Alexander Gordeev, Arnd Bergmann,
Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
Friedrich Welter, Fuad Tabba, Gautam Gala, Hariharan Mari,
Heiko Carstens, Hendrik Brueckner, Ilya Leoshkevich,
Janosch Frank, Joey Gouly, Nico Boehr, Nina Schoetterl-Glausch,
Oliver Upton, Paolo Bonzini, Suzuki K Poulose, Sven Schnelle,
Ulrich Weigand, Vasily Gorbik, Will Deacon, Zenghui Yu
On Wed, Sep 30, 2026 at 08:55:49AM +0100, Marc Zyngier wrote:
> On Wed, 30 Sep 2026 08:28:03 +0100,
> Steffen Eiden <seiden@linux.ibm.com> wrote:
> >
> > On Tue, Sep 29, 2026 at 06:00:12PM +0100, Catalin Marinas wrote:
> > > On Tue, Sep 29, 2026 at 06:19:20AM +0200, Andreas Grapentin wrote:
> > > > On Sep 28 26, Steffen Eiden wrote:
> > > > > On Mon, Sep 28, 2026 at 05:07:52PM +0100, Catalin Marinas wrote:
> > > > > > On Fri, Sep 18, 2026 at 03:30:53PM +0200, Steffen Eiden wrote:
> > > > > > > +# Enable all code shared to s390
> > > > > > > +KBUILD_CFLAGS += -DARM64_S390_COMMON
> > > > > > > +KBUILD_AFLAGS += -DARM64_S390_COMMON
> > > > > > > +KBUILD_CPPFLAGS += -DARM64_S390_COMMON
> > > > > >
> > > > > > Do we actually need these defines? They seem only to be used as markers
> > > > > > for the awk scripts to extract the definitions. Why do we need the C
> > > > > > preprocessor involved at all? Could we not just have comment markers:
> > > > > >
> > > > > > /* ARM64_S390_COMMON_BEGIN */
> > > > > > ...
> > > > > > /* ARM64_S390_COMMON_END */
> > > > > >
> > > > > No technically we do not need those. They could be useful if we find out
> > > > > that AWK is the wrong tool and move to a C Preprocessor + diff based
> > > > > approach.
> > > > >
> > > > > if the ifdev is not closed the compiler will complain, but an 'arm did
> > > > > not destroy us' verifiaction tool ( I will send one soonish) could do
> > > > > the same.
> > > >
> > > > iirc the last time we discussed this we didn't think that load-bearing
> > > > comments were the right tool here. We also briefly floated the idea of
> > > > using a #pragma region based approach, but in the end we went with the
> > > > #ifdef preprocessor directives instead, as the least invasive
> > > > non-comment marker that was available.
> > >
> > > The downside is that the macro affects the preprocessed code. We need to
> > > ensure they don't leak in uapi headers for example. Not a fan of this
> > > approach but I don't have a better suggestion either. At least we could
> > > write them as:
> > >
> > > #if ARM64_S390_COMMON == 1
> >
> > This is a great idea and an improvement. Thanks.
> >
> > @Marc: Shall I sent a v9 of this series or do you want to pick v8 and I
> > send this as an improvement once picked?
>
> Please send a v9. That's invasive enough that it warrants it.
Will send one ASAP.
>
> > > It would also be useful for the awk scripts look for the paired #endif
> > > rather than relying on the comment at the end of the line. Otherwise
> > > it's not really different from just sticking to comments.
> > >
> >
> > Are you suggesting that the AWK scripts should track the #if% and #endif
> > in the code and warn or reject if the marked endif for the shared code
> > does not match pairing with the starting #if? That makes sense yes. I'll
> > investigate and would add this as an improvement later on.
>
> I think the suggestion is to teach the script about the #if/#endif
> nesting, and therefore to not require the trailing comment on #endif
> (i.e. the script acts as a normal cpp).
>
> It should only be a matter of counting the #{if,ifdef}s and #endif
> past the ARM64_S390_COMMON guard.
>
Yes, countin is what I had in mind. I will deliver this feature (or fix?)
as an improvement later on. At this point we may actually use the cpp to
do that for us. This requires some investigation from my side. IMO the
current implementation is a good first step we can use as a starting
point for further improvements.
Steffen
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 17/29] KVM: arm64: Share arm64 code with s390
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (15 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 16/29] arm64: Share " Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 16:02 ` sashiko-bot
2026-09-18 13:30 ` [PATCH v8 18/29] s390/tools: Use arm64 headers Steffen Eiden
` (12 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Mark functions that s390 can use to implement arm on s390 as shared
functions.
No functional change.
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/arm64/kvm/arm.c | 3 +++
arch/arm64/kvm/guest.c | 6 ++++++
arch/arm64/kvm/mmio.c | 2 ++
3 files changed, 11 insertions(+)
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 8b080804bc90..6b92a3c1d490 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -1603,6 +1603,7 @@ static unsigned long system_supported_vcpu_features(void)
return features;
}
+#ifdef ARM64_S390_COMMON
static int kvm_vcpu_init_check_features(struct kvm_vcpu *vcpu,
const struct kvm_vcpu_init *init)
{
@@ -1656,6 +1657,8 @@ static bool kvm_vcpu_init_changed(struct kvm_vcpu *vcpu,
KVM_VCPU_MAX_FEATURES);
}
+#endif /* ARM64_S390_COMMON */
+
static int kvm_setup_vcpu(struct kvm_vcpu *vcpu)
{
struct kvm *kvm = vcpu->kvm;
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 773f6c8e5026..6ca5a9f357cd 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -62,6 +62,7 @@ const struct kvm_stats_header kvm_vcpu_stats_header = {
sizeof(kvm_vcpu_stats_desc),
};
+#ifdef ARM64_S390_COMMON
static bool core_reg_offset_is_vreg(u64 off)
{
return off >= KVM_REG_ARM_CORE_REG(fp_regs.vregs) &&
@@ -306,6 +307,8 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
return err;
}
+#endif /* ARM64_S390_COMMON */
+
#define vq_word(vq) (((vq) - SVE_VQ_MIN) / 64)
#define vq_mask(vq) ((u64)1 << ((vq) - SVE_VQ_MIN) % 64)
#define vq_present(vqs, vq) (!!((vqs)[vq_word(vq)] & vq_mask(vq)))
@@ -543,6 +546,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
return -EINVAL;
}
+#ifdef ARM64_S390_COMMON
static int copy_core_reg_indices(const struct kvm_vcpu *vcpu,
u64 __user *uindices)
{
@@ -591,6 +595,8 @@ static unsigned long num_core_regs(const struct kvm_vcpu *vcpu)
return copy_core_reg_indices(vcpu, NULL);
}
+#endif /* ARM64_S390_COMMON */
+
static unsigned long num_sve_regs(const struct kvm_vcpu *vcpu)
{
const unsigned int slices = vcpu_sve_slices(vcpu);
diff --git a/arch/arm64/kvm/mmio.c b/arch/arm64/kvm/mmio.c
index d1c3a352d5a2..5161102da507 100644
--- a/arch/arm64/kvm/mmio.c
+++ b/arch/arm64/kvm/mmio.c
@@ -10,6 +10,7 @@
#include "trace.h"
+#ifdef ARM64_S390_COMMON
void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data)
{
void *datap = NULL;
@@ -258,3 +259,4 @@ int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
run->exit_reason = KVM_EXIT_MMIO;
return 0;
}
+#endif /* ARM64_S390_COMMON */
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 17/29] KVM: arm64: Share arm64 code with s390
2026-09-18 13:30 ` [PATCH v8 17/29] KVM: arm64: Share arm64 code " Steffen Eiden
@ 2026-09-18 16:02 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 16:02 UTC (permalink / raw)
To: Steffen Eiden
Cc: Heiko Carstens, Vasily Gorbik, kvmarm, Oliver Upton,
Alexander Gordeev, linux-s390, Marc Zyngier,
Christian Borntraeger, kvm
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] kvm: arm64: severe cross-architecture coupling using preprocessor markers
- [Low] kvm: arm64: incomplete abstraction of ELR_EL1 and SPSR registers
--
commit 336c61211f9a8d50d065b41830fda851e8868db0
Author: Steffen Eiden <seiden@linux.ibm.com>
Subject: KVM: arm64: Share arm64 code with s390
This commit marks functions in the arm64 KVM implementation that s390 can
use as shared functions. It does this by wrapping them in ARM64_S390_COMMON
preprocessor guards.
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 8b080804bc90b..6b92a3c1d490d 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -1603,6 +1603,7 @@ static unsigned long system_supported_vcpu_features(void)
> return features;
> }
>
> +#ifdef ARM64_S390_COMMON
> static int kvm_vcpu_init_check_features(struct kvm_vcpu *vcpu,
[Severity: Medium]
Does this approach create a severe cross-architecture coupling?
Using a preprocessor macro like this as a purely textual marker for an awk
script (copy-arm64c.awk) on s390 to blindly extract arm64 C code leaves
callers unprotected. To prevent the arm64 build from failing, the macro must
be globally appended to KBUILD_CFLAGS in arch/arm64/Makefile, because
callers of the wrapped functions (e.g., kvm_arm_num_regs() calling
num_core_regs()) are left outside the macro block.
Should cross-architecture sharing be properly implemented via common kernel
directories (such as virt/kvm), rather than by parsing macros?
[ ... ]
> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index 773f6c8e50265..6ca5a9f357cdb 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -62,6 +62,7 @@ const struct kvm_stats_header kvm_vcpu_stats_header = {
> sizeof(kvm_vcpu_stats_desc),
> };
>
> +#ifdef ARM64_S390_COMMON
> static bool core_reg_offset_is_vreg(u64 off)
[Severity: Low]
Does this incomplete abstraction force downstream workarounds in s390?
By wrapping this section to share it with s390, the abstraction of register
accesses remains incomplete. For instance, core_reg_addr() accesses ELR_EL1
and all SPSR variants by directly referencing the ARM64-specific
vcpu->arch.ctxt structure:
case KVM_REG_ARM_CORE_REG(elr_el1):
return __ctxt_sys_reg(&vcpu->arch.ctxt, ELR_EL1);
case KVM_REG_ARM_CORE_REG(spsr[KVM_SPSR_ABT]):
return &vcpu->arch.ctxt.spsr_abt;
Does this force the s390 architecture to artificially replicate the ARM64
kvm_cpu_context layout with dummy structures (like spsr_abt) to allow the
extracted code to compile, defeating the purpose of the register abstraction
layer?
[ ... ]
> @@ -543,6 +546,7 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
> return -EINVAL;
> }
>
> +#ifdef ARM64_S390_COMMON
> static int copy_core_reg_indices(const struct kvm_vcpu *vcpu,
> u64 __user *uindices)
[Severity: Medium]
This is another instance of wrapping arm64 code with s390-specific macros
for code extraction. Are callers of this function properly protected?
For example, callers like kvm_arm_num_regs() that call num_core_regs()
remain outside the macro block, leading to the same architectural coupling
issues mentioned above.
[ ... ]
> diff --git a/arch/arm64/kvm/mmio.c b/arch/arm64/kvm/mmio.c
> index d1c3a352d5a22..5161102da5077 100644
> --- a/arch/arm64/kvm/mmio.c
> +++ b/arch/arm64/kvm/mmio.c
> @@ -10,6 +10,7 @@
>
> #include "trace.h"
>
> +#ifdef ARM64_S390_COMMON
> void kvm_mmio_write_buf(void *buf, unsigned int len, unsigned long data)
[Severity: Medium]
Here the macro is used to wrap almost the entire file's contents, showing
the extreme extent of this cross-architecture code sharing mechanism.
Does this indicate that the shared logic should be abstracted into a common
file rather than conditionally compiled out of arm64 specific files?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=17
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 18/29] s390/tools: Use arm64 headers
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (16 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 17/29] KVM: arm64: Share arm64 code " Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 16:09 ` sashiko-bot
2026-09-18 13:30 ` [PATCH v8 19/29] KVM: s390: Use arm64 code Steffen Eiden
` (11 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Introduce a flexible system for sharing ARM64 headers with s390 KVM.
Selected arm64 headers or snippet of headers will be reachable by s390
code through asm/header.h.
Add copy-arm64h.awk that detects ARM64_S390_COMMON markers and extracts
marked section into a generated header consumable by s390. Falls back to
full file copy when no markers are found.
Transform copied includes by replacing '#include <asm/...>' with
'#include <arm64/...>' and similar for uapi headers to ensure
correct path resolution on s390 and allow for a clear separation of s390
asm headers and arm64 asm headers.
Integrate this extraction into the s390/kapi target, conditional on
CONFIG_KVM.
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/tools/Makefile | 9 +++-
arch/s390/tools/Makefile.arm64h | 56 ++++++++++++++++++++++
arch/s390/tools/copy-arm64h-full.awk | 47 ++++++++++++++++++
arch/s390/tools/copy-arm64h.awk | 71 ++++++++++++++++++++++++++++
4 files changed, 182 insertions(+), 1 deletion(-)
create mode 100644 arch/s390/tools/Makefile.arm64h
create mode 100644 arch/s390/tools/copy-arm64h-full.awk
create mode 100644 arch/s390/tools/copy-arm64h.awk
diff --git a/arch/s390/tools/Makefile b/arch/s390/tools/Makefile
index f2862364fb42..6a97beff03a2 100644
--- a/arch/s390/tools/Makefile
+++ b/arch/s390/tools/Makefile
@@ -3,12 +3,19 @@
# Makefile for s390 specific build tools
#
+include $(srctree)/arch/s390/tools/Makefile.arm64h
+
kapi := arch/$(ARCH)/include/generated/asm
kapi-hdrs-y := $(kapi)/facility-defs.h $(kapi)/dis-defs.h
+targets += $(addprefix ../../../,$(kapi-hdrs-y))
+targets += $(patsubst $(objtree)/%,../../../%,$(ARM64_TARGETS))
+
+kapi-hdrs-$(CONFIG_KVM) += $(ARM64_TARGETS)
+
PHONY += kapi
-kapi: $(kapi-hdrs-y)
+kapi: $(kapi-hdrs-y) $(kapi-hdrs-m)
hostprogs += gen_facilities
hostprogs += gen_opcode_table
diff --git a/arch/s390/tools/Makefile.arm64h b/arch/s390/tools/Makefile.arm64h
new file mode 100644
index 000000000000..069473ea335d
--- /dev/null
+++ b/arch/s390/tools/Makefile.arm64h
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Share ARM64 headers with s390 KVM
+#
+
+arm64api := $(objtree)/arch/$(ARCH)/include/generated/arm64
+arm64uapi := $(objtree)/arch/$(ARCH)/include/generated/uapi/arm64
+
+# List of ARM64 headers to share with s390 KVM
+# Format: [uapi:]header.h or header-gen.h
+#
+# * header.h - from arch/arm64/include/asm/ to arm64/
+# * uapi:header.h - from arch/arm64/include/uapi/asm/ to uapi/arm64/
+# * header-gen.h - generated as header-gen.h from ARM64 header header.h
+# If a header contains partial markers (#ifdef ARM64_S390_COMMON) only this part will be copied.
+# If the file does not contain any markers the whole file will be copied.
+ARM64_SHARED_HEADERS := \
+ brk-imm.h \
+ esr.h \
+ kvm_arm.h \
+ kvm_emulate-gen.h \
+ kvm_host.h \
+ ptrace-gen.h \
+ sysreg-gen.h \
+ uapi:hwcap.h \
+ uapi:kvm.h \
+ uapi:ptrace.h \
+ uapi:sve_context.h \
+
+quiet_cmd_gen_arm_hdr = GEN $@
+ cmd_gen_arm_hdr = mkdir -p $(dir $@); \
+ $(AWK) -f $(src)/copy-arm64h.awk $< > $@ || \
+ $(AWK) -f $(src)/copy-arm64h-full.awk -v srcfile="$(subst $(srctree)/,,$(subst $(srctree)/../,,$<))" $< > $@ || \
+ { echo "Error: Unbalanced ARM64_S390_COMMON markers in $<" >&2; rm -f $@; exit 1; }
+
+arm64-type = $(firstword $(subst :, ,$(1)))
+arm64-base = $(or $(word 2,$(subst :, ,$(1))),$(1))
+arm64-src-base = $(patsubst %-gen.h,%.h,$(call arm64-base,$(1)))
+
+arm64-src = $(srctree)/arch/arm64/include/$(if $(filter uapi,$(call arm64-type,$(1))),uapi/)asm/$(call arm64-src-base,$(1))
+arm64-dst = $(if $(filter uapi,$(call arm64-type,$(1))),$(arm64uapi),$(arm64api))/$(call arm64-base,$(1))
+
+$(foreach hdr,$(ARM64_SHARED_HEADERS),\
+ $(eval $(call arm64-dst,$(hdr)): $(call arm64-src,$(hdr)) $(src)/copy-arm64h.awk $(src)/copy-arm64h-full.awk FORCE))
+
+ARM64_TARGETS := $(sort $(foreach hdr,$(ARM64_SHARED_HEADERS),$(call arm64-dst,$(hdr))))
+$(ARM64_TARGETS):
+ $(call if_changed,gen_arm_hdr)
+
+quiet_cmd_gen_sysreg_arm64 = GEN $@
+ cmd_gen_sysreg_arm64 = mkdir -p $(dir $@); $(AWK) -f $(srctree)/arch/arm64/tools/gen-sysreg.awk $(srctree)/arch/arm64/tools/sysreg > $@
+
+$(arm64api)/sysreg-defs.h: $(srctree)/arch/arm64/tools/gen-sysreg.awk $(srctree)/arch/arm64/tools/sysreg FORCE
+ $(call if_changed,gen_sysreg_arm64)
+
+ARM64_TARGETS += $(arm64api)/sysreg-defs.h
diff --git a/arch/s390/tools/copy-arm64h-full.awk b/arch/s390/tools/copy-arm64h-full.awk
new file mode 100644
index 000000000000..a6aaf9cc3332
--- /dev/null
+++ b/arch/s390/tools/copy-arm64h-full.awk
@@ -0,0 +1,47 @@
+#!/usr/bin/awk -f
+# SPDX-License-Identifier: GPL-2.0
+#
+# Process entire ARM64 headers for sharing with s390 KVM
+#
+# Usage: copy-arm64h-full.awk -v srcfile=<source_path> <input_file>
+#
+# This processes the entire file (unlike copy-arm64h.awk which only extracts marked sections)
+
+BEGIN {
+ max_guard_line = 25
+ guard_found = 0
+ header_added = 0
+}
+
+# Find and process the include guard in the first few lines
+NR <= max_guard_line && !guard_found && /^#ifndef [A-Z_0-9]+$/ {
+ guard_name = $2
+ guard_found = 1
+ print "/* This header was copied from " srcfile " */"
+ print ""
+ print
+ header_added = 1
+ next
+}
+
+# Transform include directives
+/^#include <uapi\/asm\// {
+ sub(/<uapi\/asm\//, "<uapi/arm64/")
+ print
+ next
+}
+
+/^#include <asm\// {
+ sub(/<asm\//, "<arm64/")
+ print
+ next
+}
+
+/ARM64_S390_COMMON/ {
+ exit 1
+}
+
+# Pass through all other lines
+{
+ print
+}
diff --git a/arch/s390/tools/copy-arm64h.awk b/arch/s390/tools/copy-arm64h.awk
new file mode 100644
index 000000000000..e7fb00ffb987
--- /dev/null
+++ b/arch/s390/tools/copy-arm64h.awk
@@ -0,0 +1,71 @@
+#!/usr/bin/awk -f
+# SPDX-License-Identifier: GPL-2.0
+#
+# Extract marked sections from ARM64 headers for sharing with s390 KVM
+#
+# Usage: copy-arm64h.awk <input_file>
+#
+# Extracts all sections between start/end markers. If no markers found, signals for fallback.
+BEGIN {
+ # Constants
+ start_pattern = "^#ifdef ARM64_S390_COMMON$"
+ end_pattern = "^#endif \\/\\* ARM64_S390_COMMON \\*\\/$"
+ max_guard_line = 25
+
+ # State variables
+ copying = found_marker = 0
+ guard_name = ""
+ file_header_done = 0
+}
+
+NR <= max_guard_line && !guard_name && /^#ifndef [A-Za-z0-9_]+$/ {
+ guard_name = $2
+ filename = FILENAME
+ sub(/^.*arch\/arm64\//, "arch/arm64/", filename)
+ print "/*"
+ print " * This header was automatically generated from " filename
+ print " * Do not modify this file directly."
+ print " */"
+ print "#ifndef " guard_name
+ print "#define " guard_name
+ print ""
+ next
+}
+
+NR > max_guard_line && !guard_name && !file_header_done {
+ print "error: no include guard found in first " max_guard_line " lines" > "/dev/stderr"
+ file_header_done = 1
+ exit 1
+}
+
+!guard_name {
+ print
+ next
+}
+
+$0 ~ start_pattern {
+ if (copying) { exit 1 }
+ copying = found_marker = 1
+ next
+}
+
+guard_name && !found_marker {
+ next
+}
+
+$0 ~ end_pattern { copying = 0; next }
+
+copying {
+ gsub(/#include <asm\//, "#include <arm64/")
+ gsub(/#include <uapi\/asm\//, "#include <uapi/arm64/")
+ print
+ next
+}
+
+END {
+ if (found_marker) {
+ print ""
+ print "#endif /* " guard_name " */"
+ }
+ exit !found_marker || copying
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 18/29] s390/tools: Use arm64 headers
2026-09-18 13:30 ` [PATCH v8 18/29] s390/tools: Use arm64 headers Steffen Eiden
@ 2026-09-18 16:09 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 16:09 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvmarm, kvm, Marc Zyngier, linux-s390, Heiko Carstens,
Vasily Gorbik, Oliver Upton, Christian Borntraeger,
Alexander Gordeev
> Introduce a flexible system for sharing ARM64 headers with s390 KVM.
> Selected arm64 headers or snippet of headers will be reachable by s390
> code through asm/header.h.
>
> Add copy-arm64h.awk that detects ARM64_S390_COMMON markers and extracts
> marked section into a generated header consumable by s390. Falls back to
> full file copy when no markers are found.
>
> Transform copied includes by replacing '#include <asm/...>' with
> '#include <arm64/...>' and similar for uapi headers to ensure
> correct path resolution on s390 and allow for a clear separation of s390
> asm headers and arm64 asm headers.
>
> Integrate this extraction into the s390/kapi target, conditional on
> CONFIG_KVM.
>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=18
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 19/29] KVM: s390: Use arm64 code
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (17 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 18/29] s390/tools: Use arm64 headers Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 16:14 ` sashiko-bot
2026-09-18 13:30 ` [PATCH v8 20/29] s390: Introduce Start Arm Execution instruction Steffen Eiden
` (10 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Add the infrastructure to extract KVM/arm64 code into s390 at built
time similar to the arm64 header sharing. Add copy-arm64c.awk hat
detects ARM64_S390_COMMON markers and extracts marked section into an
.inc file that can be consumed by arm on s390 host code. If no marker is
found make will fail.
To ensure that no code is consumed twice by accident a guard is added
during file generation. A s390 C file wanting to consume such an inc
file must first define __INCL_GEN_ARM_FILE otherwise the inc file will
emit a compile error.
Example:
#define __INCL_GEN_ARM_FILE
#include <generated/arm.inc>
#undef __INCL_GEN_ARM_FILE
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/kvm/arm64/.gitignore | 2 +
arch/s390/kvm/arm64/Makefile.gen | 26 +++++++++++
arch/s390/kvm/arm64/copy-arm64c.awk | 72 +++++++++++++++++++++++++++++
3 files changed, 100 insertions(+)
create mode 100644 arch/s390/kvm/arm64/.gitignore
create mode 100644 arch/s390/kvm/arm64/Makefile.gen
create mode 100644 arch/s390/kvm/arm64/copy-arm64c.awk
diff --git a/arch/s390/kvm/arm64/.gitignore b/arch/s390/kvm/arm64/.gitignore
new file mode 100644
index 000000000000..bd9d90694676
--- /dev/null
+++ b/arch/s390/kvm/arm64/.gitignore
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+generated/*
diff --git a/arch/s390/kvm/arm64/Makefile.gen b/arch/s390/kvm/arm64/Makefile.gen
new file mode 100644
index 000000000000..e12714203bde
--- /dev/null
+++ b/arch/s390/kvm/arm64/Makefile.gen
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Extracts ARM64 marked sections to .inc files that are included by main source
+# files
+
+# List of ARM64 C files to extract
+ARM64_CFILES := \
+ arm.c \
+ guest.c \
+ mmio.c \
+
+quiet_cmd_extract_inc = GEN $@
+ cmd_extract_inc = mkdir -p $(dir $@); \
+ $(AWK) -f $(src)/copy-arm64c.awk $< > $@ || \
+ { echo "Error: No or unbalanced ARM64_S390_COMMON markers in $<" >&2; rm -f $@; exit 1; }
+
+$(obj)/generated/%.inc: $(srctree)/arch/arm64/kvm/%.c $(src)/copy-arm64c.awk FORCE
+ $(call if_changed,extract_inc)
+
+ARM64_INC_FILES := $(foreach cfile,$(ARM64_CFILES),generated/$(basename $(cfile)).inc)
+
+targets += $(ARM64_INC_FILES)
+clean-files += generated/*.inc
+
+$(foreach cfile,$(basename $(ARM64_CFILES)),\
+ $(eval $(obj)/$(cfile).o: $(obj)/generated/$(cfile).inc))
diff --git a/arch/s390/kvm/arm64/copy-arm64c.awk b/arch/s390/kvm/arm64/copy-arm64c.awk
new file mode 100644
index 000000000000..5561619aa70c
--- /dev/null
+++ b/arch/s390/kvm/arm64/copy-arm64c.awk
@@ -0,0 +1,72 @@
+#!/usr/bin/awk -f
+# SPDX-License-Identifier: GPL-2.0
+#
+# Extract marked sections from ARM64 C files for sharing with s390 KVM
+#
+# Usage: copy-arm64c.awk <input_file>
+#
+# Extracts all sections between start/end markers. If no markers found, signals failure.
+
+BEGIN {
+ # Constants
+ start_pattern = "^#ifdef ARM64_S390_COMMON$"
+ end_pattern = "^#endif /\\* ARM64_S390_COMMON \\*/$"
+
+ # State variables
+ copying = found_marker = 0
+ file_header_done = 0
+}
+
+!file_header_done {
+ if (/^\/\*/ || /^\/\/ SPDX-License-Identifier:/) {
+ print
+ next
+ }
+ if (/[[:space:]]\*([[:space:]]|$)/) {
+ print
+ next
+ }
+ if (/\*\//) {
+ print " *"
+ } else {
+ print "/*"
+ }
+
+ filename = FILENAME
+ sub(/^.*arch\/arm64\//, "arch/arm64/", filename)
+ print " * This file was automatically generated from " filename
+ print " * Do not modify this file directly."
+ print " */"
+ print ""
+ print "#ifndef __INCL_GEN_ARM_FILE"
+ print "#error included .inc file w/o proper guard definition"
+ print "#else"
+ print "#undef __INCL_GEN_ARM_FILE"
+ print "#endif /* __INCL_GEN_ARM_FILE */"
+ print ""
+
+ file_header_done = 1
+}
+
+$0 ~ start_pattern {
+ if (copying) { error = 1; exit 1 }
+ copying = found_marker = 1
+ next
+}
+
+$0 ~ end_pattern {
+ if (!copying) { error = 1; exit }
+ copying = 0
+ next
+}
+
+copying {
+ gsub(/#include <asm\//, "#include <arm64/")
+ gsub(/#include <uapi\/asm\//, "#include <uapi/arm64/")
+ print
+ next
+}
+
+END {
+ exit error || !found_marker || copying
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 19/29] KVM: s390: Use arm64 code
2026-09-18 13:30 ` [PATCH v8 19/29] KVM: s390: Use arm64 code Steffen Eiden
@ 2026-09-18 16:14 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 16:14 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvmarm, Oliver Upton, Marc Zyngier, linux-s390,
Christian Borntraeger, Heiko Carstens, Vasily Gorbik, kvm,
Alexander Gordeev
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] build: cross-arch C code extraction via awk breaks tooling and modularity
--
commit e83a74be06a131ec905dd0c83821e6279b998572
Author: Steffen Eiden <seiden@linux.ibm.com>
KVM: s390: Use arm64 code
This commit introduces build infrastructure to extract marked sections
from ARM64 C files into generated .inc files for use in the s390 KVM
host code. It adds the copy-arm64c.awk script that searches for
ARM64_S390_COMMON markers and copies the matched code verbatim.
> diff --git a/arch/s390/kvm/arm64/copy-arm64c.awk b/arch/s390/kvm/arm64/copy-arm64c.awk
> new file mode 100644
> index 0000000000000..5561619aa70c8
> --- /dev/null
> +++ b/arch/s390/kvm/arm64/copy-arm64c.awk
> @@ -0,0 +1,72 @@
[ ... ]
> +BEGIN {
> + # Constants
> + start_pattern = "^#ifdef ARM64_S390_COMMON$"
> + end_pattern = "^#endif /\\* ARM64_S390_COMMON \\*/$"
[Severity: Medium]
Does tightly coupling the s390 build to the exact source code formatting
in the arm64 tree present a maintenance burden?
Sharing architecture code via text extraction of C files violates kernel
modularity principles. It imposes a burden on ARM64 maintainers who must
now preserve s390-specific markers (ARM64_S390_COMMON) and formatting.
The established Linux kernel paradigm for cross-architecture code sharing
is to abstract common logic into standalone .c files in a shared
location (e.g., virt/kvm/).
[ ... ]
> +copying {
> + gsub(/#include <asm\//, "#include <arm64/")
> + gsub(/#include <uapi\/asm\//, "#include <uapi/arm64/")
> + print
> + next
> +}
[Severity: Medium]
Does copying C source code into a new file without emitting C preprocessor
#line directives break standard developer tooling?
Without #line directives, compiler errors, warnings, and debugger (GDB)
symbols will map to the generated .inc files instead of the original
arch/arm64 source, degrading debuggability.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=19
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 20/29] s390: Introduce Start Arm Execution instruction
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (18 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 19/29] KVM: s390: Use arm64 code Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 16:28 ` sashiko-bot
2026-09-28 15:53 ` Ilya Leoshkevich
2026-09-18 13:30 ` [PATCH v8 21/29] KVM: s390: arm64: Introduce host definitions Steffen Eiden
` (9 subsequent siblings)
29 siblings, 2 replies; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
The Start Arm Execution (SAE) instruction is the centerpiece for
executing arm64 (KVM) guests on s390. Its purpose is, similar to SIE, to
enable accelerated execution of arm64 virtual machines. SAE expects the
physical address of a control block as the only argument.
The host is responsible to save & restore
- GPRs 0-13
- access register 0-15
- breaking event register (BEAR)
- vector/floating point registers
between SAE executions to guarantee host consistency.
GPRs and BEAR are save and restores in the asm functions. The other
register are handled in within C code. Access registers are handled in a
later patch and SVEs will be handled when they are introduced in a
future series. Most arm64 registers are handled by a satellite block
called save_area. Some registers, frequently used by hypervisors, are
placed into the SAE control block itself.
Enlighten asm/kvm_host_types.h for the new header variant. The new
header is chosen instead of asm/kvm_host_s390_types.h if KVM_S390_ARM64
is defined.
Co-developed-by: Andreas Grapentin <gra@linux.ibm.com>
Signed-off-by: Andreas Grapentin <gra@linux.ibm.com>
Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/include/asm/asm-prototypes.h | 1 +
arch/s390/include/asm/kvm_host_arm64_types.h | 124 +++++++++++++++++++
arch/s390/include/asm/kvm_host_types.h | 4 +
arch/s390/include/asm/sae.h | 58 +++++++++
arch/s390/include/asm/stacktrace.h | 5 +
arch/s390/kernel/asm-offsets.c | 1 +
arch/s390/kernel/entry.S | 22 ++++
arch/s390/tools/opcodes.txt | 3 +
8 files changed, 218 insertions(+)
create mode 100644 arch/s390/include/asm/kvm_host_arm64_types.h
create mode 100644 arch/s390/include/asm/sae.h
diff --git a/arch/s390/include/asm/asm-prototypes.h b/arch/s390/include/asm/asm-prototypes.h
index d4da4436d02b..faa2afb259a1 100644
--- a/arch/s390/include/asm/asm-prototypes.h
+++ b/arch/s390/include/asm/asm-prototypes.h
@@ -6,6 +6,7 @@
#include <asm/bug.h>
#include <asm/fpu.h>
#include <asm/nospec-branch.h>
+#include <asm/sae.h>
#include <asm-generic/asm-prototypes.h>
#endif /* _ASM_S390_PROTOTYPES_H */
diff --git a/arch/s390/include/asm/kvm_host_arm64_types.h b/arch/s390/include/asm/kvm_host_arm64_types.h
new file mode 100644
index 000000000000..8783a66d3029
--- /dev/null
+++ b/arch/s390/include/asm/kvm_host_arm64_types.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ASM_KVM_HOST_ARM64_TYPES_H
+#define ASM_KVM_HOST_ARM64_TYPES_H
+
+#include <linux/types.h>
+#include <linux/kvm_types.h>
+#include <linux/compiler_attributes.h>
+#include <asm/page.h>
+#include <asm/fault.h>
+
+struct kvm_sae_block {
+ u64 _0000[16]; /* 0x0000 */
+#define SAE_ICPTR_SPURIOUS 0x00
+#define SAE_ICPTR_VALIDITY 0x01
+#define SAE_ICPTR_HOST_ACCESS_EXCEPTION 0x02
+#define SAE_ICPTR_SYNCHRONOUS_EXCEPTION 0x03
+#define SAE_ICPTR_TIMER 0x04
+#define SAE_ICPTR_PE_INTERCOMM 0x05
+#define SAE_ICPTR_GUEST_ADDRESS_SIZE 0x06
+#define SAE_ICPTR_STOP 0x07
+#define SAE_ICPTR_MIO_ADDRESS 0x08
+#define SAE_ICPTR_PMU 0x09
+#define SAE_ICPTR_MAINTENANCE 0x0a
+ u8 icptr; /* 0x0080 */
+ u8 _0081[7]; /* 0x0081 */
+ u64 scad; /* 0x0088 */
+ u64 _0090[16]; /* 0x0090 */
+ u32 cntp_ctl; /* 0x0110 */
+ u32 cntv_ctl; /* 0x0114 */
+ u8 irq_ctl; /* 0x0118 */
+ u8 _0119[7]; /* 0x0119 */
+ struct {
+ u64 ich_hcr_el2; /* 0x0120 */
+ u64 ich_vmcr_el2; /* 0x0128 */
+ u64 ich_ap0r0_el2; /* 0x0130 */
+ u64 ich_ap1r0_el2; /* 0x0138 */
+ u64 _0140[2]; /* 0x0140 */
+ u64 ich_lrn_el2[4]; /* 0x0150 */
+ u64 _0170[4]; /* 0x0170 */
+ } ic_regs;
+ u64 _0190[12]; /* 0x0190 */
+ u64 contextidr_el1; /* 0x01f0 */
+ u32 wip; /* 0x01f8 */
+ u32 _01fc; /* 0x01fc */
+#define SAE_SD_FORMAT_0 0x00
+ u8 sdf; /* 0x0200 */
+ u8 _0201[7]; /* 0x0201 */
+ u64 mso; /* 0x0208 */
+ u64 msl; /* 0x0210 */
+ u64 hbasce; /* 0x0218 */
+ u64 _0220; /* 0x0220 */
+ u64 gpto; /* 0x0228 */
+ u64 ic; /* 0x0230 */
+ u64 ec; /* 0x0238 */
+ u64 save_area; /* 0x0240 */
+ u64 _0248[7]; /* 0x0248 */
+ u8 _0280[6]; /* 0x0280 */
+ u16 lrcpua; /* 0x0286 */
+ u64 pstate; /* 0x0288 */
+ u64 pc; /* 0x0290 */
+ u64 sp_el0; /* 0x0298 */
+ u64 sp_el1; /* 0x02a0 */
+ u64 _02a8; /* 0x02a8 */
+ struct { /* 0x02b0 */
+ u32 _fpcr_res0;
+ u32 fpcr;
+ };
+ struct { /* 0x02b8 */
+ u32 _fpsr_res0;
+ u32 fpsr;
+ };
+ u16 sve_pregs[16]; /* 0x02c0 */
+ u16 sve_ffr; /* 0x02e0 */
+ u8 _02e2[6]; /* 0x02e2 */
+ u64 _02e8[3]; /* 0x02e8 */
+
+ u64 gpr[31]; /* 0x0300 */
+ u64 _03f8; /* 0x03f8 */
+
+ union {
+ u64 icptd[8]; /* 0x0400 */
+ /* validity-interception reason; icptr 0x01 */
+ u16 vir; /* 0x0400 */
+ /* host access interception details; icptr 0x02 */
+ struct {
+ u64 esr_el2; /* 0x0400 */
+ u8 _0408[6]; /* 0x0408 */
+ u16 pic; /* 0x040e */
+ union teid teid; /* 0x0410 */
+ gva_t far_el2; /* 0x0418 */
+ gva_t vaddr; /* 0x0420 */
+ u64 suppl; /* 0x0428 */
+ u8 gltl; /* 0x0430 */
+ u8 _0431[7]; /* 0x0431 */
+ u64 _0438; /* 0x0438 */
+ } hai;
+ /* exception-interception details; icptr 0x03 */
+ struct {
+ u64 esr_el2; /* 0x0400 */
+ u64 _0408[2]; /* 0x0408 */
+ gva_t far_el2; /* 0x0418 */
+ } trap;
+ /* timer-interception reason; icptr 0x04 */
+#define SAE_IR_TIMER_ID_VIRT BIT(6)
+#define SAE_IR_TIMER_ID_PHYS BIT(7)
+ u8 tir; /* 0x0400 */
+ };
+ u64 _0440[376]; /* 0x0440 */
+} __packed __aligned(PAGE_SIZE);
+static_assert(sizeof(struct kvm_sae_block) == PAGE_SIZE);
+
+struct kvm_sae_save_area {
+#define SAE_SAVE_AREA_FORMAT_0 0x00
+ u8 saf; /* 0x0000 */
+ u8 _0001[5]; /* 0x0001 */
+#define SAE_SAS_VALID BIT(0)
+ u16 sas; /* 0x0006 */
+ u64 sdo; /* 0x0008 */
+ u64 _0010[2]; /* 0x0010 */
+ u64 regs[508]; /* 0x0020 */
+} __packed __aligned(PAGE_SIZE);
+static_assert(sizeof(struct kvm_sae_save_area) == PAGE_SIZE);
+
+#endif /* ASM_KVM_HOST_ARM64_TYPES_H */
diff --git a/arch/s390/include/asm/kvm_host_types.h b/arch/s390/include/asm/kvm_host_types.h
index e5bdba07cab0..d308739ebcf5 100644
--- a/arch/s390/include/asm/kvm_host_types.h
+++ b/arch/s390/include/asm/kvm_host_types.h
@@ -3,6 +3,10 @@
#ifndef ASM_KVM_HOST_TYPES_H
#define ASM_KVM_HOST_TYPES_H
+#ifdef KVM_S390_ARM64
+#include <asm/kvm_host_arm64_types.h>
+#else
#include <asm/kvm_host_s390_types.h>
+#endif /* KVM_S390_ARM64 */
#endif /* ASM_KVM_HOST_TYPES_H */
diff --git a/arch/s390/include/asm/sae.h b/arch/s390/include/asm/sae.h
new file mode 100644
index 000000000000..b644e65c4e37
--- /dev/null
+++ b/arch/s390/include/asm/sae.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_S390_SAE_H
+#define __ASM_S390_SAE_H
+
+#include <linux/linkage.h>
+#include <linux/types.h>
+
+#ifndef __ASSEMBLER__
+
+/* defined in arch/s390/kernel/entry.S */
+asmlinkage void __sae64a(phys_addr_t sae_block_phys);
+
+#include <linux/io.h>
+#include <asm/kvm_host_arm64_types.h>
+
+/**
+ * sae64a() - Start Arm Execution
+ * @sae_block: pointer to the SAE control block
+ */
+static inline void sae64a(struct kvm_sae_block *sae_block)
+{
+ __sae64a(virt_to_phys(sae_block));
+}
+
+/**
+ * stiasrm() - STore and Invalidate Arm System Register Multiple
+ * @save_area: Pointer to SAE save area
+ *
+ * Store the guest system registers to the save area.
+ * The values in the guest are no longer valid.
+ */
+static __always_inline void stiasrm(struct kvm_sae_save_area *save_area)
+{
+ asm volatile(
+ " .insn rre,0xb9a70000,%[r1],0\n"
+ : "+m"(*save_area)
+ : [r1] "a"(save_area)
+ );
+}
+
+/**
+ * lasrm() - Load Arm System Register Multiple
+ *
+ * @save_area: Pointer to SAE save area
+ *
+ * Load the system registers from save_area into the guest.
+ */
+static __always_inline void lasrm(struct kvm_sae_save_area *save_area)
+{
+ asm volatile(
+ " .insn rre,0xb9a60000,%[r1],0\n"
+ :
+ : "m"(*save_area), [r1] "a"(save_area)
+ );
+}
+
+#endif /* !__ASSEMBLER__ */
+#endif /* __ASM_S390_SAE_H */
diff --git a/arch/s390/include/asm/stacktrace.h b/arch/s390/include/asm/stacktrace.h
index ac3606c3babe..2d332d7c8145 100644
--- a/arch/s390/include/asm/stacktrace.h
+++ b/arch/s390/include/asm/stacktrace.h
@@ -59,6 +59,7 @@ static inline bool on_stack(struct stack_info *info,
struct stack_frame {
union {
unsigned long empty[9];
+ /* SIE stack frame */
struct {
unsigned long sie_control_block;
unsigned long sie_savearea;
@@ -68,6 +69,10 @@ struct stack_frame {
unsigned long sie_guest_asce;
unsigned long sie_irq;
};
+ /* SAE stack frame */
+ struct {
+ unsigned long sae_bear;
+ };
};
unsigned long gprs[10];
unsigned long back_chain;
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index f6dd2b67dcee..f9f9c2246074 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -70,6 +70,7 @@ int main(void)
OFFSET(__SF_SIE_CONTROL_PHYS, stack_frame, sie_control_block_phys);
OFFSET(__SF_SIE_GUEST_ASCE, stack_frame, sie_guest_asce);
OFFSET(__SF_SIE_IRQ, stack_frame, sie_irq);
+ OFFSET(__SF_SAE_BEAR, stack_frame, sae_bear);
DEFINE(STACK_FRAME_OVERHEAD, sizeof(struct stack_frame));
BLANK();
OFFSET(__SFUSER_BACKCHAIN, stack_frame_user, back_chain);
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 10dd9bbdf985..af515f2b6c11 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -245,6 +245,28 @@ EXPORT_SYMBOL(__sie64a)
EXPORT_SYMBOL(sie_exit)
#endif
+#if IS_ENABLED(CONFIG_KVM)
+/*
+ * __sae64a calling convention:
+ * %r2 pointer to sae control block physical address
+ */
+SYM_FUNC_START(__sae64a)
+ stmg %r6,%r14,__SF_GPRS(%r15) # store kernel registers
+ STBEAR __SF_SAE_BEAR(%r15) # save breaking event address register
+ .insn rre,0xb9a50000,%r2,0 # Start Arm Execution
+ LBEAR __SF_SAE_BEAR(%r15) # restore breaking event address register
+ lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
+ xgr %r0,%r0 # clear guest registers to
+ xgr %r1,%r1 # prevent speculative use
+ xgr %r2,%r2
+ xgr %r3,%r3
+ xgr %r4,%r4
+ xgr %r5,%r5
+ BR_EX %r14
+SYM_FUNC_END(__sae64a)
+EXPORT_SYMBOL(__sae64a)
+#endif
+
/*
* SVC interrupt handler routine. System calls are synchronous events and
* are entered with interrupts disabled.
diff --git a/arch/s390/tools/opcodes.txt b/arch/s390/tools/opcodes.txt
index def2659f6602..0e4773c94af0 100644
--- a/arch/s390/tools/opcodes.txt
+++ b/arch/s390/tools/opcodes.txt
@@ -594,6 +594,9 @@ b9a0 clp RRF_U0RR
b9a1 tpei RRE_RR
b9a2 ptf RRE_R0
b9a4 uvc RRF_URR
+b9a5 sae RRE_R0
+b9a6 lasrm RRE_R0
+b9a7 stiasrm RRE_R0
b9aa lptea RRF_RURR2
b9ab essa RRF_U0RR
b9ac irbm RRE_RR
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 20/29] s390: Introduce Start Arm Execution instruction
2026-09-18 13:30 ` [PATCH v8 20/29] s390: Introduce Start Arm Execution instruction Steffen Eiden
@ 2026-09-18 16:28 ` sashiko-bot
2026-09-28 15:53 ` Ilya Leoshkevich
1 sibling, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 16:28 UTC (permalink / raw)
To: Steffen Eiden
Cc: Alexander Gordeev, Marc Zyngier, linux-s390,
Christian Borntraeger, kvmarm, Heiko Carstens, Oliver Upton,
Vasily Gorbik, kvm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] s390: missing `nop` padding after SAE instruction execution
--
commit 97e095ed7008049c3b17921733022a1015bd2720
Author: Steffen Eiden <seiden@linux.ibm.com>
s390: Introduce Start Arm Execution instruction
This commit introduces the Start Arm Execution (SAE) instruction to enable
accelerated execution of arm64 virtual machines on s390. It adds the
necessary assembly wrapper __sae64a, control blocks, and architecture
types.
> diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
> --- a/arch/s390/kernel/entry.S
> +++ b/arch/s390/kernel/entry.S
[ ... ]
> @@ -245,6 +245,28 @@ EXPORT_SYMBOL(__sie64a)
> EXPORT_SYMBOL(sie_exit)
> #endif
>
> +#if IS_ENABLED(CONFIG_KVM)
> +/*
> + * __sae64a calling convention:
> + * %r2 pointer to sae control block physical address
> + */
> +SYM_FUNC_START(__sae64a)
> + stmg %r6,%r14,__SF_GPRS(%r15) # store kernel registers
> + STBEAR __SF_SAE_BEAR(%r15) # save breaking event address register
> + .insn rre,0xb9a50000,%r2,0 # Start Arm Execution
> + LBEAR __SF_SAE_BEAR(%r15) # restore breaking event address register
[Severity: Medium]
Should there be a nopr 7 padding inserted after the SAE instruction here?
For the SIE instruction, the handler explicitly includes a nopr 7 cushion
because if a machine check is triggered by the immediately following instruction
(in this case LBEAR), the hardware may incorrectly attribute the exception to
the guest context instead of the host.
Since the hardware behavior for SAE likely mirrors SIE, does this path require
similar padding to safely handle machine-check boundaries?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=20
^ permalink raw reply [flat|nested] 80+ messages in thread
* Re: [PATCH v8 20/29] s390: Introduce Start Arm Execution instruction
2026-09-18 13:30 ` [PATCH v8 20/29] s390: Introduce Start Arm Execution instruction Steffen Eiden
2026-09-18 16:28 ` sashiko-bot
@ 2026-09-28 15:53 ` Ilya Leoshkevich
2026-09-28 16:15 ` Steffen Eiden
1 sibling, 1 reply; 80+ messages in thread
From: Ilya Leoshkevich @ 2026-09-28 15:53 UTC (permalink / raw)
To: Steffen Eiden, kvm, kvmarm, linux-arm-kernel, linux-kernel,
linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner, Janosch Frank,
Joey Gouly, Marc Zyngier, Nico Boehr, Nina Schoetterl-Glausch,
Oliver Upton, Paolo Bonzini, Suzuki K Poulose, Sven Schnelle,
Ulrich Weigand, Vasily Gorbik, Will Deacon, Zenghui Yu
On 9/18/26 15:30, Steffen Eiden wrote:
> The Start Arm Execution (SAE) instruction is the centerpiece for
> executing arm64 (KVM) guests on s390. Its purpose is, similar to SIE, to
> enable accelerated execution of arm64 virtual machines. SAE expects the
> physical address of a control block as the only argument.
>
> The host is responsible to save & restore
> - GPRs 0-13
> - access register 0-15
^^^^^^^^
registers> - breaking event register (BEAR)
> - vector/floating point registers
> between SAE executions to guarantee host consistency.
>
> GPRs and BEAR are save and restores in the asm functions. The other
^^^^^^^^^^^^^^^^^
saved and restored
> register are handled in within C code. Access registers are handled in a
^^^^^^^^ ^^
registers not needed probably?
> later patch and SVEs will be handled when they are introduced in a
> future series. Most arm64 registers are handled by a satellite block
> called save_area. Some registers, frequently used by hypervisors, are
> placed into the SAE control block itself.
>
> Enlighten asm/kvm_host_types.h for the new header variant. The new
> header is chosen instead of asm/kvm_host_s390_types.h if KVM_S390_ARM64
> is defined.
>
> Co-developed-by: Andreas Grapentin <gra@linux.ibm.com>
> Signed-off-by: Andreas Grapentin <gra@linux.ibm.com>
> Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
> Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
> ---
> arch/s390/include/asm/asm-prototypes.h | 1 +
> arch/s390/include/asm/kvm_host_arm64_types.h | 124 +++++++++++++++++++
> arch/s390/include/asm/kvm_host_types.h | 4 +
> arch/s390/include/asm/sae.h | 58 +++++++++
> arch/s390/include/asm/stacktrace.h | 5 +
> arch/s390/kernel/asm-offsets.c | 1 +
> arch/s390/kernel/entry.S | 22 ++++
> arch/s390/tools/opcodes.txt | 3 +
> 8 files changed, 218 insertions(+)
> create mode 100644 arch/s390/include/asm/kvm_host_arm64_types.h
> create mode 100644 arch/s390/include/asm/sae.h
[...]
> +#if IS_ENABLED(CONFIG_KVM)
> +/*
> + * __sae64a calling convention:
> + * %r2 pointer to sae control block physical address
^^^^^^^^^^ I guess it's just a physical address and not a
pointer to it?
^^^ sometimes it's called "sae", sometimes "SAE" -
it would be nice to have some consistency> + */
> +SYM_FUNC_START(__sae64a)
> + stmg %r6,%r14,__SF_GPRS(%r15) # store kernel registers
Strictly speaking we don't need to save %r14, but I guess you do this
for unwinding?
> + STBEAR __SF_SAE_BEAR(%r15) # save breaking event address register
> + .insn rre,0xb9a50000,%r2,0 # Start Arm Execution
> + LBEAR __SF_SAE_BEAR(%r15) # restore breaking event address register
> + lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
> + xgr %r0,%r0 # clear guest registers to
> + xgr %r1,%r1 # prevent speculative use
> + xgr %r2,%r2
> + xgr %r3,%r3
> + xgr %r4,%r4
> + xgr %r5,%r5
> + BR_EX %r14
> +SYM_FUNC_END(__sae64a)
> +EXPORT_SYMBOL(__sae64a)
> +#endif
[...]
^ permalink raw reply [flat|nested] 80+ messages in thread* Re: [PATCH v8 20/29] s390: Introduce Start Arm Execution instruction
2026-09-28 15:53 ` Ilya Leoshkevich
@ 2026-09-28 16:15 ` Steffen Eiden
2026-09-28 16:18 ` Ilya Leoshkevich
0 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-28 16:15 UTC (permalink / raw)
To: Ilya Leoshkevich
Cc: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390,
Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner, Janosch Frank,
Joey Gouly, Marc Zyngier, Nico Boehr, Nina Schoetterl-Glausch,
Oliver Upton, Paolo Bonzini, Suzuki K Poulose, Sven Schnelle,
Ulrich Weigand, Vasily Gorbik, Will Deacon, Zenghui Yu
On Mon, Sep 28, 2026 at 05:53:33PM +0200, Ilya Leoshkevich wrote:
>
>
> On 9/18/26 15:30, Steffen Eiden wrote:
> > The Start Arm Execution (SAE) instruction is the centerpiece for
> > executing arm64 (KVM) guests on s390. Its purpose is, similar to SIE, to
> > enable accelerated execution of arm64 virtual machines. SAE expects the
> > physical address of a control block as the only argument.
> >
> > The host is responsible to save & restore
> > - GPRs 0-13
> > - access register 0-15
> ^^^^^^^^
> registers> - breaking event register (BEAR)
> > - vector/floating point registers
> > between SAE executions to guarantee host consistency.
> >
> > GPRs and BEAR are save and restores in the asm functions. The other
> ^^^^^^^^^^^^^^^^^
> saved and restored
>
> > register are handled in within C code. Access registers are handled in a
> ^^^^^^^^ ^^
> registers not needed probably?
>
> > later patch and SVEs will be handled when they are introduced in a
> > future series. Most arm64 registers are handled by a satellite block
> > called save_area. Some registers, frequently used by hypervisors, are
> > placed into the SAE control block itself.
> >
> > Enlighten asm/kvm_host_types.h for the new header variant. The new
> > header is chosen instead of asm/kvm_host_s390_types.h if KVM_S390_ARM64
> > is defined.
> >
> > Co-developed-by: Andreas Grapentin <gra@linux.ibm.com>
> > Signed-off-by: Andreas Grapentin <gra@linux.ibm.com>
> > Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
> > Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
> > Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
> > ---
> > arch/s390/include/asm/asm-prototypes.h | 1 +
> > arch/s390/include/asm/kvm_host_arm64_types.h | 124 +++++++++++++++++++
> > arch/s390/include/asm/kvm_host_types.h | 4 +
> > arch/s390/include/asm/sae.h | 58 +++++++++
> > arch/s390/include/asm/stacktrace.h | 5 +
> > arch/s390/kernel/asm-offsets.c | 1 +
> > arch/s390/kernel/entry.S | 22 ++++
> > arch/s390/tools/opcodes.txt | 3 +
> > 8 files changed, 218 insertions(+)
> > create mode 100644 arch/s390/include/asm/kvm_host_arm64_types.h
> > create mode 100644 arch/s390/include/asm/sae.h
>
> [...]
> > +#if IS_ENABLED(CONFIG_KVM)
> > +/*
> > + * __sae64a calling convention:
> > + * %r2 pointer to sae control block physical address
> ^^^^^^^^^^ I guess it's just a physical address and not a
> pointer to it?
>
yes. Fixing.
> ^^^ sometimes it's called "sae", sometimes "SAE" -
> it would be nice to have some consistency> + */
Thanks, I will convert everything to SAE
> > +SYM_FUNC_START(__sae64a)
> > + stmg %r6,%r14,__SF_GPRS(%r15) # store kernel registers
>
> Strictly speaking we don't need to save %r14, but I guess you do this
> for unwinding?
yes. Also, some later (unsent) patch needs this and before I forget this, let's
do it now.
>
> > + STBEAR __SF_SAE_BEAR(%r15) # save breaking event address register
> > + .insn rre,0xb9a50000,%r2,0 # Start Arm Execution
> > + LBEAR __SF_SAE_BEAR(%r15) # restore breaking event address register
> > + lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
> > + xgr %r0,%r0 # clear guest registers to
> > + xgr %r1,%r1 # prevent speculative use
> > + xgr %r2,%r2
> > + xgr %r3,%r3
> > + xgr %r4,%r4
> > + xgr %r5,%r5
> > + BR_EX %r14
> > +SYM_FUNC_END(__sae64a)
> > +EXPORT_SYMBOL(__sae64a)
> > +#endif
> [...]
^ permalink raw reply [flat|nested] 80+ messages in thread
* Re: [PATCH v8 20/29] s390: Introduce Start Arm Execution instruction
2026-09-28 16:15 ` Steffen Eiden
@ 2026-09-28 16:18 ` Ilya Leoshkevich
0 siblings, 0 replies; 80+ messages in thread
From: Ilya Leoshkevich @ 2026-09-28 16:18 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390,
Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner, Janosch Frank,
Joey Gouly, Marc Zyngier, Nico Boehr, Nina Schoetterl-Glausch,
Oliver Upton, Paolo Bonzini, Suzuki K Poulose, Sven Schnelle,
Ulrich Weigand, Vasily Gorbik, Will Deacon, Zenghui Yu
On 9/28/26 18:15, Steffen Eiden wrote:
> On Mon, Sep 28, 2026 at 05:53:33PM +0200, Ilya Leoshkevich wrote:
>>
>>
>> On 9/18/26 15:30, Steffen Eiden wrote:
>>> The Start Arm Execution (SAE) instruction is the centerpiece for
>>> executing arm64 (KVM) guests on s390. Its purpose is, similar to SIE, to
>>> enable accelerated execution of arm64 virtual machines. SAE expects the
>>> physical address of a control block as the only argument.
>>>
>>> The host is responsible to save & restore
>>> - GPRs 0-13
>>> - access register 0-15
>> ^^^^^^^^
>> registers> - breaking event register (BEAR)
>>> - vector/floating point registers
>>> between SAE executions to guarantee host consistency.
>>>
>>> GPRs and BEAR are save and restores in the asm functions. The other
>> ^^^^^^^^^^^^^^^^^
>> saved and restored
>>
>>> register are handled in within C code. Access registers are handled in a
>> ^^^^^^^^ ^^
>> registers not needed probably?
>>
>>> later patch and SVEs will be handled when they are introduced in a
>>> future series. Most arm64 registers are handled by a satellite block
>>> called save_area. Some registers, frequently used by hypervisors, are
>>> placed into the SAE control block itself.
>>>
>>> Enlighten asm/kvm_host_types.h for the new header variant. The new
>>> header is chosen instead of asm/kvm_host_s390_types.h if KVM_S390_ARM64
>>> is defined.
>>>
>>> Co-developed-by: Andreas Grapentin <gra@linux.ibm.com>
>>> Signed-off-by: Andreas Grapentin <gra@linux.ibm.com>
>>> Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
>>> Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
>>> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
>>> ---
>>> arch/s390/include/asm/asm-prototypes.h | 1 +
>>> arch/s390/include/asm/kvm_host_arm64_types.h | 124 +++++++++++++++++++
>>> arch/s390/include/asm/kvm_host_types.h | 4 +
>>> arch/s390/include/asm/sae.h | 58 +++++++++
>>> arch/s390/include/asm/stacktrace.h | 5 +
>>> arch/s390/kernel/asm-offsets.c | 1 +
>>> arch/s390/kernel/entry.S | 22 ++++
>>> arch/s390/tools/opcodes.txt | 3 +
>>> 8 files changed, 218 insertions(+)
>>> create mode 100644 arch/s390/include/asm/kvm_host_arm64_types.h
>>> create mode 100644 arch/s390/include/asm/sae.h
[...]
>>> +SYM_FUNC_START(__sae64a)
>>> + stmg %r6,%r14,__SF_GPRS(%r15) # store kernel registers
>>
>> Strictly speaking we don't need to save %r14, but I guess you do this
>> for unwinding?
> yes. Also, some later (unsent) patch needs this and before I forget this, let's
> do it now.
Thanks for the clarification!
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
with typos fixes.
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 21/29] KVM: s390: arm64: Introduce host definitions
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (19 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 20/29] s390: Introduce Start Arm Execution instruction Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 16:44 ` sashiko-bot
2026-09-18 13:30 ` [PATCH v8 22/29] s390/hwcaps: Report SAE support as hwcap Steffen Eiden
` (8 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Add all basic definitions the arm on s390 KVM host requires. Including,
but not limited to, struct kvm*arch definitions, various functions (to
be implemented in the following patches), and various defines required
to run arm64 guests.
Enlighten asm/kvm_host.h for the new header variant. The new
header is chosen instead of asm/kvm_host_s390.h if KVM_S390_ARM64
is defined.
Co-developed-by: Andreas Grapentin <gra@linux.ibm.com>
Signed-off-by: Andreas Grapentin <gra@linux.ibm.com>
Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/include/asm/kvm.h | 6 +
arch/s390/include/asm/kvm_host.h | 9 ++
arch/s390/include/asm/kvm_host_arm64.h | 212 +++++++++++++++++++++++++
3 files changed, 227 insertions(+)
create mode 100644 arch/s390/include/asm/kvm.h
create mode 100644 arch/s390/include/asm/kvm_host_arm64.h
diff --git a/arch/s390/include/asm/kvm.h b/arch/s390/include/asm/kvm.h
new file mode 100644
index 000000000000..aeb11dc631d5
--- /dev/null
+++ b/arch/s390/include/asm/kvm.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifdef KVM_S390_ARM64
+#include <uapi/arm64/kvm.h>
+#else
+#include <uapi/asm/kvm.h>
+#endif
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 147325978225..cd6d572883ab 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -3,7 +3,16 @@
#ifndef ASM_KVM_HOST_H
#define ASM_KVM_HOST_H
+#ifdef KVM_S390_ARM64
+#include <asm/kvm_host_arm64.h>
+#else
#include <asm/kvm_host_s390.h>
+#endif
+
+static inline bool kvm_arch_pmi_in_guest(struct kvm_vcpu *vcpu)
+{
+ return false;
+}
#define PGM_OPERATION 0x01
#define PGM_PRIVILEGED_OP 0x02
diff --git a/arch/s390/include/asm/kvm_host_arm64.h b/arch/s390/include/asm/kvm_host_arm64.h
new file mode 100644
index 000000000000..3d036361b63b
--- /dev/null
+++ b/arch/s390/include/asm/kvm_host_arm64.h
@@ -0,0 +1,212 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ASM_KVM_HOST_ARM64_H
+#define ASM_KVM_HOST_ARM64_H
+
+#include <linux/bug.h>
+
+#include <asm/kvm_host_types.h>
+#include <asm/debug.h>
+
+#define vcpu_gp_regs(v) ((v)->arch.sae_block.gpr)
+
+#include <arm64/kvm_host.h>
+#include <arm64/ptrace.h>
+
+#include <asm/sae.h>
+
+#define KVM_HAVE_MMU_RWLOCK
+#define KVM_MAX_VCPUS 1
+#define KVM_READONLY_MEM
+#define KVM_VCPU_RUN_PID_CHANGE
+
+#define KVM_S390_ARM64_IMPL_FEATURES 0
+#define KVM_HALT_POLL_NS_DEFAULT 50000
+
+#define KVM_S390_MANAGES_S390_GUEST 0
+
+/* Minimal (=no) vgic definitions */
+#define KVM_IRQCHIP_NUM_PINS 1
+#define irqchip_in_kernel(_k) false
+
+#define __ctxt_sys_reg(ctx, reg) NULL
+struct kvm_cpu_context {
+ /*
+ * These are just for 32 bit, which we don't have, making them RES0.
+ * They are exposed to user space.
+ */
+ u64 spsr_abt;
+ u64 spsr_und;
+ u64 spsr_irq;
+ u64 spsr_fiq;
+
+ __vector128 __aligned(16) vregs[32];
+};
+
+struct kvm_vcpu_arch {
+ struct kvm_sae_block sae_block;
+ struct kvm_sae_save_area save_area;
+ struct kvm_cpu_context ctxt;
+
+ u32 host_acrs[NUM_ACRS];
+
+ /* Hypervisor Configuration Register */
+ u64 hcr_el2;
+
+ /* Configuration flags, set once and for all before the vcpu can run */
+ u8 cflags;
+
+ /* Input flags to the hypervisor code, potentially cleared after use */
+ u8 iflags;
+
+ /* State flags for kernel bookkeeping, unused by the hypervisor code */
+ u8 sflags;
+
+ /*
+ * Don't run the guest (internal implementation need).
+ *
+ * Contrary to the flags above, this is set/cleared outside of
+ * a vcpu context, and thus cannot be mixed with the flags
+ * themselves (or the flag accesses need to be made atomic).
+ */
+ bool pause;
+
+ /* vcpu power state */
+ struct kvm_mp_state mp_state;
+ /* lock for mp_state & reset_state.reset */
+ spinlock_t mp_state_lock;
+
+ /* vcpu reset state */
+ struct vcpu_reset_state reset_state;
+
+ /* GMAP */
+ struct gmap *gmap;
+ struct kvm_s390_mmu_cache *mc;
+
+ void *debugfs_state_data;
+};
+
+struct kvm_vcpu_stat {
+ struct kvm_vcpu_stat_generic generic;
+ /* ARM64 stats */
+ u64 hvc_exit_stat;
+ u64 wfe_exit_stat;
+ u64 wfi_exit_stat;
+ u64 mmio_exit_user;
+ u64 mmio_exit_kernel;
+ u64 signal_exits;
+ u64 exits;
+ /* GMAP stats */
+ u64 pfault_sync;
+};
+
+#define kvm_has_mte(_kvm) false
+#define vcpu_has_sve(_vcpu) false
+#define vcpu_has_ptrauth(_vcpu) false
+
+struct kvm_arch_memory_slot {
+};
+
+struct kvm_arch {
+ struct gmap *gmap;
+ u64 guest_phys_size;
+
+ /* VM-wide vCPU feature set */
+ unsigned long flags;
+
+ /* Protects VM-scoped configuration data */
+ struct mutex config_lock;
+
+ debug_info_t *dbf;
+
+ DECLARE_BITMAP(vcpu_features, KVM_VCPU_MAX_FEATURES);
+
+ unsigned long mem_limit;
+};
+
+static inline bool __vcpu_has_feature(const struct kvm_arch *ka, int feature)
+{
+ return test_bit(feature, ka->vcpu_features);
+}
+
+struct kvm_vm_stat {
+ struct kvm_vm_stat_generic generic;
+};
+
+static inline bool system_has_full_ptr_auth(void)
+{
+ return true;
+}
+
+#define kvm_vm_is_protected(_kvm) false
+#define vcpu_is_protected(_vcpu) false
+
+#define vcpu_is_loaded(_vcpu) ((_vcpu)->cpu != -1)
+
+#define KVM_HVA_ERR_BAD -1UL
+#define KVM_HVA_ERR_RO_BAD -2UL
+
+static inline bool kvm_is_error_hva(unsigned long addr)
+{
+ return IS_ERR_VALUE(addr);
+}
+
+u32 get_kvm_ipa_limit(void);
+
+/* unused, but required functions */
+static inline void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *slot) {}
+static inline void kvm_arch_memslots_updated(struct kvm *kvm, u64 gen) {}
+static inline void kvm_arch_flush_shadow_all(struct kvm *kvm) {}
+static inline void kvm_arch_flush_shadow_memslot(struct kvm *kvm, struct kvm_memory_slot *slot) {}
+static inline void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu) {}
+static inline void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) {}
+static inline void kvm_arch_sync_events(struct kvm *kvm) {}
+static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
+static inline void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm,
+ struct kvm_memory_slot *slot,
+ gfn_t gfn_offset,
+ unsigned long mask) {}
+
+int kvm_handle_guest_abort(struct kvm_vcpu *vcpu);
+void kvm_reset_vcpu(struct kvm_vcpu *vcpu);
+
+/* arm64 guests do not use async-pf. Defined because Kbuild requires it as s390 kvm turns it on. */
+#define ASYNC_PF_PER_VCPU 0
+struct kvm_arch_async_pf {
+ unsigned long pfault_token;
+};
+
+#define __unsupp_async_call(fn) WARN_ONCE(true, "async not supported on kvm-arm64 %s", fn)
+
+static inline bool kvm_arch_can_dequeue_async_page_present(struct kvm_vcpu *vcpu)
+{
+ __unsupp_async_call(__func__);
+ return false;
+};
+
+static inline void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu,
+ struct kvm_async_pf *work)
+{
+ __unsupp_async_call(__func__);
+};
+
+static inline bool kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu,
+ struct kvm_async_pf *work)
+{
+ __unsupp_async_call(__func__);
+ return false;
+};
+
+static inline void kvm_arch_async_page_present(struct kvm_vcpu *vcpu,
+ struct kvm_async_pf *work)
+{
+ __unsupp_async_call(__func__);
+};
+
+static inline void kvm_arch_async_page_present_queued(struct kvm_vcpu *vcpu)
+{
+ __unsupp_async_call(__func__);
+};
+
+#define kvm_supports_32bit_el0() false
+
+#endif /* ASM_KVM_HOST_ARM64_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 21/29] KVM: s390: arm64: Introduce host definitions
2026-09-18 13:30 ` [PATCH v8 21/29] KVM: s390: arm64: Introduce host definitions Steffen Eiden
@ 2026-09-18 16:44 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 16:44 UTC (permalink / raw)
To: Steffen Eiden
Cc: Vasily Gorbik, Oliver Upton, Christian Borntraeger, kvm,
Alexander Gordeev, Marc Zyngier, kvmarm, Heiko Carstens,
linux-s390
> Add all basic definitions the arm on s390 KVM host requires. Including,
> but not limited to, struct kvm*arch definitions, various functions (to
> be implemented in the following patches), and various defines required
> to run arm64 guests.
>
> Enlighten asm/kvm_host.h for the new header variant. The new
> header is chosen instead of asm/kvm_host_s390.h if KVM_S390_ARM64
> is defined.
>
> Co-developed-by: Andreas Grapentin <gra@linux.ibm.com>
> Signed-off-by: Andreas Grapentin <gra@linux.ibm.com>
> Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
> Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=21
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 22/29] s390/hwcaps: Report SAE support as hwcap
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (20 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 21/29] KVM: s390: arm64: Introduce host definitions Steffen Eiden
@ 2026-09-18 13:30 ` Steffen Eiden
2026-09-18 16:49 ` sashiko-bot
2026-09-28 15:58 ` Ilya Leoshkevich
2026-09-18 13:31 ` [PATCH v8 23/29] KVM: s390: Add basic arm64 kvm module Steffen Eiden
` (7 subsequent siblings)
29 siblings, 2 replies; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:30 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
From: Hendrik Brueckner <brueckner@linux.ibm.com>
Report SAE support as hwcap (and /proc/cpuinfo)
Signed-off-by: Hendrik Brueckner <brueckner@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
---
arch/s390/include/asm/elf.h | 2 ++
arch/s390/include/asm/sclp.h | 5 ++++-
arch/s390/kernel/processor.c | 3 +++
drivers/s390/char/sclp_early.c | 1 +
4 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h
index bb63fa4d20bb..ad3108ecfb07 100644
--- a/arch/s390/include/asm/elf.h
+++ b/arch/s390/include/asm/elf.h
@@ -123,6 +123,7 @@ enum {
HWCAP_NR_NNPA = 20,
HWCAP_NR_PCI_MIO = 21,
HWCAP_NR_SIE = 22,
+ HWCAP_NR_SAE = 23,
HWCAP_NR_MAX
};
@@ -150,6 +151,7 @@ enum {
#define HWCAP_NNPA BIT(HWCAP_NR_NNPA)
#define HWCAP_PCI_MIO BIT(HWCAP_NR_PCI_MIO)
#define HWCAP_SIE BIT(HWCAP_NR_SIE)
+#define HWCAP_SAE BIT(HWCAP_NR_SAE)
/*
* These are used to set parameters in the core dumps.
diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h
index 44066550b9b1..68f61b71a2d5 100644
--- a/arch/s390/include/asm/sclp.h
+++ b/arch/s390/include/asm/sclp.h
@@ -56,7 +56,9 @@ struct sclp_core_entry {
u8 siif : 1;
u8 sigpif : 1;
u8 : 3;
- u8 reserved2[3];
+ u8 aef: 1;
+ u8 : 7;
+ u8 reserved2[2];
u8 : 2;
u8 ib : 1;
u8 cei : 1;
@@ -109,6 +111,7 @@ struct sclp_info {
unsigned char has_aeni : 1;
unsigned char has_aisi : 1;
unsigned char has_astfleie2 : 1;
+ unsigned char has_aef : 1;
unsigned int ibc;
unsigned int mtid;
unsigned int mtid_cp;
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c
index e33a3eccda56..6da55a158027 100644
--- a/arch/s390/kernel/processor.c
+++ b/arch/s390/kernel/processor.c
@@ -150,6 +150,7 @@ static void show_cpu_summary(struct seq_file *m, void *v)
[HWCAP_NR_NNPA] = "nnpa",
[HWCAP_NR_PCI_MIO] = "pcimio",
[HWCAP_NR_SIE] = "sie",
+ [HWCAP_NR_SAE] = "sae",
};
int i, cpu;
@@ -254,6 +255,8 @@ static int __init setup_hwcaps(void)
/* virtualization support */
if (sclp.has_sief2)
elf_hwcap |= HWCAP_SIE;
+ if (sclp.has_aef)
+ elf_hwcap |= HWCAP_SAE;
return 0;
}
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c
index 22dd797e6229..e58d24b95bd1 100644
--- a/drivers/s390/char/sclp_early.c
+++ b/drivers/s390/char/sclp_early.c
@@ -96,6 +96,7 @@ static void __init sclp_early_facilities_detect(void)
sclp.has_ib = cpue->ib;
sclp.has_cei = cpue->cei;
sclp.has_skey = cpue->skey;
+ sclp.has_aef = cpue->aef;
break;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 22/29] s390/hwcaps: Report SAE support as hwcap
2026-09-18 13:30 ` [PATCH v8 22/29] s390/hwcaps: Report SAE support as hwcap Steffen Eiden
@ 2026-09-18 16:49 ` sashiko-bot
2026-09-28 15:58 ` Ilya Leoshkevich
1 sibling, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 16:49 UTC (permalink / raw)
To: Steffen Eiden
Cc: Marc Zyngier, kvmarm, kvm, linux-s390, Christian Borntraeger,
Oliver Upton, Alexander Gordeev, Heiko Carstens, Vasily Gorbik
> From: Hendrik Brueckner <brueckner@linux.ibm.com>
>
> Report SAE support as hwcap (and /proc/cpuinfo)
>
> Signed-off-by: Hendrik Brueckner <brueckner@linux.ibm.com>
> Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=22
^ permalink raw reply [flat|nested] 80+ messages in thread
* Re: [PATCH v8 22/29] s390/hwcaps: Report SAE support as hwcap
2026-09-18 13:30 ` [PATCH v8 22/29] s390/hwcaps: Report SAE support as hwcap Steffen Eiden
2026-09-18 16:49 ` sashiko-bot
@ 2026-09-28 15:58 ` Ilya Leoshkevich
1 sibling, 0 replies; 80+ messages in thread
From: Ilya Leoshkevich @ 2026-09-28 15:58 UTC (permalink / raw)
To: Steffen Eiden, kvm, kvmarm, linux-arm-kernel, linux-kernel,
linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner, Janosch Frank,
Joey Gouly, Marc Zyngier, Nico Boehr, Nina Schoetterl-Glausch,
Oliver Upton, Paolo Bonzini, Suzuki K Poulose, Sven Schnelle,
Ulrich Weigand, Vasily Gorbik, Will Deacon, Zenghui Yu
On 9/18/26 15:30, Steffen Eiden wrote:
> From: Hendrik Brueckner <brueckner@linux.ibm.com>
>
> Report SAE support as hwcap (and /proc/cpuinfo)
>
> Signed-off-by: Hendrik Brueckner <brueckner@linux.ibm.com>
> Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
> Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
> ---
> arch/s390/include/asm/elf.h | 2 ++
> arch/s390/include/asm/sclp.h | 5 ++++-
> arch/s390/kernel/processor.c | 3 +++
> drivers/s390/char/sclp_early.c | 1 +
> 4 files changed, 10 insertions(+), 1 deletion(-)
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 23/29] KVM: s390: Add basic arm64 kvm module
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (21 preceding siblings ...)
2026-09-18 13:30 ` [PATCH v8 22/29] s390/hwcaps: Report SAE support as hwcap Steffen Eiden
@ 2026-09-18 13:31 ` Steffen Eiden
2026-09-18 17:00 ` sashiko-bot
2026-09-28 14:15 ` Hendrik Brueckner
2026-09-18 13:31 ` [PATCH v8 24/29] KVM: s390: arm64: Implement required functions Steffen Eiden
` (6 subsequent siblings)
29 siblings, 2 replies; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:31 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Add basic code for the new arm64 on s390 KVM implementation.
Add kernel module boilerplate code and trivial functions.
Add tracing scaffolding.
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/kvm/arm64/arm.c | 147 ++++++++++++++++++++++++++++++++++++
arch/s390/kvm/arm64/arm.h | 44 +++++++++++
arch/s390/kvm/arm64/guest.c | 92 ++++++++++++++++++++++
arch/s390/kvm/arm64/trace.h | 18 +++++
4 files changed, 301 insertions(+)
create mode 100644 arch/s390/kvm/arm64/arm.c
create mode 100644 arch/s390/kvm/arm64/arm.h
create mode 100644 arch/s390/kvm/arm64/guest.c
create mode 100644 arch/s390/kvm/arm64/trace.h
diff --git a/arch/s390/kvm/arm64/arm.c b/arch/s390/kvm/arm64/arm.c
new file mode 100644
index 000000000000..8b056fc836d7
--- /dev/null
+++ b/arch/s390/kvm/arm64/arm.c
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define KMSG_COMPONENT "kvm-s390-arm64"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/miscdevice.h>
+#include <linux/kvm.h>
+#include <linux/kvm_types.h>
+#include <linux/kvm_host.h>
+
+#include "arm.h"
+
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
+static unsigned long system_supported_vcpu_features(void);
+
+#define __INCL_GEN_ARM_FILE
+#include "generated/arm.inc"
+#undef __INCL_GEN_ARM_FILE
+
+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
+{
+ int ret;
+
+ switch (ext) {
+ case KVM_CAP_NR_VCPUS:
+ case KVM_CAP_MAX_VCPUS:
+ case KVM_CAP_MAX_VCPU_ID:
+ ret = KVM_MAX_VCPUS;
+ break;
+ case KVM_CAP_ARM_VM_IPA_SIZE:
+ ret = get_kvm_ipa_limit();
+ break;
+ case KVM_CAP_IOEVENTFD:
+ ret = 1;
+ break;
+ default:
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static u64 kvm_max_guest_address(void)
+{
+ u64 max_addr;
+
+ max_addr = min_t(u64, TASK_SIZE_MAX, sclp.hamax);
+ max_addr = max_t(u64, max_addr, SZ_1G - 1);
+ return ALIGN_DOWN(max_addr + 1, SZ_1G) - 1;
+}
+
+vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+{
+ return VM_FAULT_SIGBUS;
+}
+
+long kvm_arch_dev_ioctl(struct file *filp,
+ unsigned int ioctl, unsigned long arg)
+{
+ return -EINVAL;
+}
+
+u32 get_kvm_ipa_limit(void)
+{
+ return fls64(kvm_max_guest_address() + 1) - 1;
+}
+
+int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
+{
+ return 0;
+}
+
+void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
+{
+}
+
+int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
+ struct kvm_mp_state *mp_state)
+{
+ *mp_state = READ_ONCE(vcpu->arch.mp_state);
+ return 0;
+}
+
+int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
+ struct kvm_mp_state *mp_state)
+{
+ return -EINVAL;
+}
+
+int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
+{
+ return 0;
+}
+
+static unsigned long system_supported_vcpu_features(void)
+{
+ unsigned long features = KVM_S390_ARM64_IMPL_FEATURES;
+
+ return features;
+}
+
+bool kvm_arch_irqchip_in_kernel(struct kvm *kvm)
+{
+ return false;
+}
+
+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm,
+ int irq_source_id, int level, bool line_status)
+{
+ return -EINVAL;
+}
+
+int kvm_set_routing_entry(struct kvm *kvm,
+ struct kvm_kernel_irq_routing_entry *e,
+ const struct kvm_irq_routing_entry *ue)
+{
+ return -EINVAL;
+}
+
+int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
+{
+ return 0;
+}
+
+long kvm_arch_vcpu_unlocked_ioctl(struct file *filp, unsigned int ioctl,
+ unsigned long arg)
+{
+ return -ENOIOCTLCMD;
+}
+
+static int __init kvm_s390_arm64_init(void)
+{
+ if (!sclp.has_aef)
+ return -ENXIO;
+
+ return kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE);
+}
+
+static __exit void kvm_s390_arm64_exit(void)
+{
+ kvm_exit();
+}
+
+module_init(kvm_s390_arm64_init);
+module_exit(kvm_s390_arm64_exit);
diff --git a/arch/s390/kvm/arm64/arm.h b/arch/s390/kvm/arm64/arm.h
new file mode 100644
index 000000000000..b38eb44c11fe
--- /dev/null
+++ b/arch/s390/kvm/arm64/arm.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ARCH_S390_KVM_ARM64_H
+#define ARCH_S390_KVM_ARM64_H
+
+static __always_inline int kvm_is_ucontrol(struct kvm *kvm)
+{
+ return 0;
+}
+
+static __always_inline int __kvm_s390_pv_destroy_page(struct page *page)
+{
+ return 0;
+}
+
+static __always_inline void kvm_s390_vsie_gmap_notifier(struct gmap *gmap, gpa_t start, gpa_t end)
+{
+}
+
+static __always_inline int kvm_s390_pv_get_handle(struct kvm *kvm)
+{
+ return 0;
+}
+
+static __always_inline int kvm_s390_is_migration_mode(struct kvm *kvm)
+{
+ return false;
+}
+
+static __always_inline bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu)
+{
+ return false;
+}
+
+static __always_inline void kvm_s390_update_cmma_dirty(struct kvm *kvm, struct kvm_memory_slot *old)
+{
+}
+
+/* should never be called */
+static __always_inline int kvm_s390_vm_stop_migration(struct kvm *kvm)
+{
+ return -EINVAL;
+}
+
+#endif /* ARCH_S390_KVM_ARM64_H */
diff --git a/arch/s390/kvm/arm64/guest.c b/arch/s390/kvm/arm64/guest.c
new file mode 100644
index 000000000000..fd6442d9e4f4
--- /dev/null
+++ b/arch/s390/kvm/arm64/guest.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/kvm_host.h>
+#include <linux/kvm.h>
+
+#include <arm64/kvm_emulate.h>
+#include <arm64/kvm_nested.h>
+
+#include "guest.h"
+
+#define __INCL_GEN_ARM_FILE
+#include "generated/guest.inc"
+#undef __INCL_GEN_ARM_FILE
+
+const struct kvm_stats_desc kvm_vm_stats_desc[] = {
+ KVM_GENERIC_VM_STATS()
+};
+
+const struct kvm_stats_header kvm_vm_stats_header = {
+ .name_size = KVM_STATS_NAME_SIZE,
+ .num_desc = ARRAY_SIZE(kvm_vm_stats_desc),
+ .id_offset = sizeof(struct kvm_stats_header),
+ .desc_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE,
+ .data_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE +
+ sizeof(kvm_vm_stats_desc),
+};
+
+const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
+ KVM_GENERIC_VCPU_STATS(),
+ /* ARM64 stats */
+ STATS_DESC_COUNTER(VCPU, hvc_exit_stat),
+ STATS_DESC_COUNTER(VCPU, wfe_exit_stat),
+ STATS_DESC_COUNTER(VCPU, wfi_exit_stat),
+ STATS_DESC_COUNTER(VCPU, mmio_exit_user),
+ STATS_DESC_COUNTER(VCPU, mmio_exit_kernel),
+ STATS_DESC_COUNTER(VCPU, signal_exits),
+ STATS_DESC_COUNTER(VCPU, exits),
+ /* GMAP stats */
+ STATS_DESC_COUNTER(VCPU, pfault_sync),
+};
+
+const struct kvm_stats_header kvm_vcpu_stats_header = {
+ .name_size = KVM_STATS_NAME_SIZE,
+ .num_desc = ARRAY_SIZE(kvm_vcpu_stats_desc),
+ .id_offset = sizeof(struct kvm_stats_header),
+ .desc_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE,
+ .data_offset = sizeof(struct kvm_stats_header) + KVM_STATS_NAME_SIZE +
+ sizeof(kvm_vcpu_stats_desc),
+};
+
+int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+ return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
+{
+ return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
+ struct kvm_sregs *sregs)
+{
+ return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
+ struct kvm_sregs *sregs)
+{
+ return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+ return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
+{
+ return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
+ struct kvm_translation *tr)
+{
+ return -EINVAL;
+}
+
+int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
+ struct kvm_guest_debug *dbg)
+{
+ return -EINVAL;
+}
diff --git a/arch/s390/kvm/arm64/trace.h b/arch/s390/kvm/arm64/trace.h
new file mode 100644
index 000000000000..3a5dcd039c13
--- /dev/null
+++ b/arch/s390/kvm/arm64/trace.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#if !defined(KVM_ARM64_TRACE_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define KVM_ARM64_TRACE_KVM_H
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM kvm
+
+#endif /* KVM_ARM64_TRACE_KVM_H */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 23/29] KVM: s390: Add basic arm64 kvm module
2026-09-18 13:31 ` [PATCH v8 23/29] KVM: s390: Add basic arm64 kvm module Steffen Eiden
@ 2026-09-18 17:00 ` sashiko-bot
2026-09-28 14:15 ` Hendrik Brueckner
1 sibling, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 17:00 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvmarm, Oliver Upton, Heiko Carstens, Vasily Gorbik, linux-s390,
Alexander Gordeev, Marc Zyngier, Christian Borntraeger, kvm
> Add basic code for the new arm64 on s390 KVM implementation.
> Add kernel module boilerplate code and trivial functions.
> Add tracing scaffolding.
>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=23
^ permalink raw reply [flat|nested] 80+ messages in thread
* Re: [PATCH v8 23/29] KVM: s390: Add basic arm64 kvm module
2026-09-18 13:31 ` [PATCH v8 23/29] KVM: s390: Add basic arm64 kvm module Steffen Eiden
2026-09-18 17:00 ` sashiko-bot
@ 2026-09-28 14:15 ` Hendrik Brueckner
2026-09-28 14:22 ` Steffen Eiden
1 sibling, 1 reply; 80+ messages in thread
From: Hendrik Brueckner @ 2026-09-28 14:15 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390,
Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
On Fri, Sep 18, 2026 at 03:31:00PM +0200, Steffen Eiden wrote:
> Add basic code for the new arm64 on s390 KVM implementation.
> Add kernel module boilerplate code and trivial functions.
> Add tracing scaffolding.
>
> Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
> ---
> arch/s390/kvm/arm64/arm.c | 147 ++++++++++++++++++++++++++++++++++++
> arch/s390/kvm/arm64/arm.h | 44 +++++++++++
> arch/s390/kvm/arm64/guest.c | 92 ++++++++++++++++++++++
> arch/s390/kvm/arm64/trace.h | 18 +++++
> 4 files changed, 301 insertions(+)
> create mode 100644 arch/s390/kvm/arm64/arm.c
> create mode 100644 arch/s390/kvm/arm64/arm.h
> create mode 100644 arch/s390/kvm/arm64/guest.c
> create mode 100644 arch/s390/kvm/arm64/trace.h
>
> diff --git a/arch/s390/kvm/arm64/arm.c b/arch/s390/kvm/arm64/arm.c
> new file mode 100644
> index 000000000000..8b056fc836d7
> --- /dev/null
> +++ b/arch/s390/kvm/arm64/arm.c
[..]
> +static int __init kvm_s390_arm64_init(void)
> +{
> + if (!sclp.has_aef)
> + return -ENXIO;
I suggest to use -ENODEV here to be consistent with s390 kvm module.
The arm64 module also return -ENODEV when not available.
^ permalink raw reply [flat|nested] 80+ messages in thread* Re: [PATCH v8 23/29] KVM: s390: Add basic arm64 kvm module
2026-09-28 14:15 ` Hendrik Brueckner
@ 2026-09-28 14:22 ` Steffen Eiden
0 siblings, 0 replies; 80+ messages in thread
From: Steffen Eiden @ 2026-09-28 14:22 UTC (permalink / raw)
To: Hendrik Brueckner
Cc: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390,
Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Ilya Leoshkevich, Janosch Frank,
Joey Gouly, Marc Zyngier, Nico Boehr, Nina Schoetterl-Glausch,
Oliver Upton, Paolo Bonzini, Suzuki K Poulose, Sven Schnelle,
Ulrich Weigand, Vasily Gorbik, Will Deacon, Zenghui Yu
On Mon, Sep 28, 2026 at 04:15:58PM +0200, Hendrik Brueckner wrote:
> On Fri, Sep 18, 2026 at 03:31:00PM +0200, Steffen Eiden wrote:
> > Add basic code for the new arm64 on s390 KVM implementation.
> > Add kernel module boilerplate code and trivial functions.
> > Add tracing scaffolding.
> >
> > Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
> > ---
> > arch/s390/kvm/arm64/arm.c | 147 ++++++++++++++++++++++++++++++++++++
> > arch/s390/kvm/arm64/arm.h | 44 +++++++++++
> > arch/s390/kvm/arm64/guest.c | 92 ++++++++++++++++++++++
> > arch/s390/kvm/arm64/trace.h | 18 +++++
> > 4 files changed, 301 insertions(+)
> > create mode 100644 arch/s390/kvm/arm64/arm.c
> > create mode 100644 arch/s390/kvm/arm64/arm.h
> > create mode 100644 arch/s390/kvm/arm64/guest.c
> > create mode 100644 arch/s390/kvm/arm64/trace.h
> >
> > diff --git a/arch/s390/kvm/arm64/arm.c b/arch/s390/kvm/arm64/arm.c
> > new file mode 100644
> > index 000000000000..8b056fc836d7
> > --- /dev/null
> > +++ b/arch/s390/kvm/arm64/arm.c
>
> [..]
>
> > +static int __init kvm_s390_arm64_init(void)
> > +{
> > + if (!sclp.has_aef)
> > + return -ENXIO;
>
> I suggest to use -ENODEV here to be consistent with s390 kvm module.
> The arm64 module also return -ENODEV when not available.
Makes sense. Thanks
Steffen
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 24/29] KVM: s390: arm64: Implement required functions
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (22 preceding siblings ...)
2026-09-18 13:31 ` [PATCH v8 23/29] KVM: s390: Add basic arm64 kvm module Steffen Eiden
@ 2026-09-18 13:31 ` Steffen Eiden
2026-09-18 17:13 ` sashiko-bot
2026-09-18 13:31 ` [PATCH v8 25/29] KVM: s390: arm64: Implement vm/vcpu create destroy Steffen Eiden
` (5 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:31 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Implement the mostly trivial functions that the shared arm64 (kvm)
code & headers oblige s390 to implement.
MAINTAINERS: Add arch/s390/include/arm64/* to KVM/s390
Implement a very basic smccc handler that (non-compliantly) is just able
to stop a vcpu.
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
MAINTAINERS | 1 +
arch/s390/include/arm64/kvm_emulate.h | 130 ++++++++++++++++++++++++++
arch/s390/include/arm64/kvm_nested.h | 11 +++
arch/s390/include/arm64/ptrace.h | 11 +++
arch/s390/include/arm64/sysreg.h | 13 +++
arch/s390/kvm/arm64/handle_exit.c | 128 +++++++++++++++++++++++++
arch/s390/kvm/arm64/inject_fault.c | 21 +++++
7 files changed, 315 insertions(+)
create mode 100644 arch/s390/include/arm64/kvm_emulate.h
create mode 100644 arch/s390/include/arm64/kvm_nested.h
create mode 100644 arch/s390/include/arm64/ptrace.h
create mode 100644 arch/s390/include/arm64/sysreg.h
create mode 100644 arch/s390/kvm/arm64/handle_exit.c
create mode 100644 arch/s390/kvm/arm64/inject_fault.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 3b2eb2a7a89a..8c23370b5a3c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14372,6 +14372,7 @@ L: kvm@vger.kernel.org
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvms390/linux.git
F: Documentation/virt/kvm/s390*
+F: arch/s390/include/arm64/*
F: arch/s390/include/asm/gmap_helpers.h
F: arch/s390/include/asm/kvm*
F: arch/s390/include/uapi/asm/kvm*
diff --git a/arch/s390/include/arm64/kvm_emulate.h b/arch/s390/include/arm64/kvm_emulate.h
new file mode 100644
index 000000000000..416c4f96db05
--- /dev/null
+++ b/arch/s390/include/arm64/kvm_emulate.h
@@ -0,0 +1,130 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __S390_ARM64_KVM_EMULATE_H__
+#define __S390_ARM64_KVM_EMULATE_H__
+
+#include <asm/fault.h>
+#include <linux/kvm_host.h>
+
+#include <arm64/kvm_nested.h>
+#include <arm64/ptrace.h>
+#include <arm64/kvm_arm.h>
+#include <arm64/sysreg.h>
+
+static __always_inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu)
+{
+ return (unsigned long *)&vcpu->arch.sae_block.pc;
+}
+
+static __always_inline unsigned long *vcpu_cpsr(const struct kvm_vcpu *vcpu)
+{
+ return (unsigned long *)&vcpu->arch.sae_block.pstate;
+}
+
+static __always_inline unsigned long *vcpu_sp_el0(const struct kvm_vcpu *vcpu)
+{
+ return (unsigned long *)&vcpu->arch.sae_block.sp_el0;
+}
+
+static __always_inline u64 *vcpu_sp_el1(struct kvm_vcpu *vcpu)
+{
+ return &vcpu->arch.sae_block.sp_el1;
+}
+
+static __always_inline __vector128 *vcpu_vreg(struct kvm_vcpu *vcpu, int off)
+{
+ return &vcpu->arch.ctxt.vregs[off];
+}
+
+static __always_inline u32 *vcpu_fpsr(struct kvm_vcpu *vcpu)
+{
+ return &vcpu->arch.sae_block.fpsr;
+}
+
+static __always_inline u32 *vcpu_fpcr(struct kvm_vcpu *vcpu)
+{
+ return &vcpu->arch.sae_block.fpcr;
+}
+
+static __always_inline bool vcpu_mode_is_32bit(const struct kvm_vcpu *vcpu)
+{
+ return false;
+}
+
+static __always_inline u64 kvm_vcpu_get_esr(const struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.sae_block.hai.esr_el2;
+}
+
+static inline unsigned long *vcpu_hcr(struct kvm_vcpu *vcpu)
+{
+ return (unsigned long *)&vcpu->arch.hcr_el2;
+}
+
+static __always_inline unsigned long kvm_vcpu_get_hfar(const struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.sae_block.hai.far_el2;
+}
+
+static __always_inline phys_addr_t kvm_vcpu_get_fault_ipa(const struct kvm_vcpu *vcpu)
+{
+ return gfn_to_gpa(vcpu->arch.sae_block.hai.teid.addr);
+}
+
+static inline u16 kvm_vcpu_fault_pic(const struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.sae_block.hai.pic & PGM_INT_CODE_MASK;
+}
+
+static __always_inline
+bool kvm_vcpu_trap_is_permission_fault(const struct kvm_vcpu *vcpu)
+{
+ return kvm_vcpu_fault_pic(vcpu) == PGM_PROTECTION;
+}
+
+static __always_inline bool kvm_condition_valid(const struct kvm_vcpu *vcpu)
+{
+ return true;
+}
+
+static __always_inline bool vcpu_el1_is_32bit(struct kvm_vcpu *vcpu)
+{
+ return false;
+}
+
+static inline bool kvm_vcpu_is_be(struct kvm_vcpu *vcpu)
+{
+ return false;
+}
+
+static inline int kvm_vcpu_abt_gltl(struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.sae_block.hai.gltl;
+}
+
+static inline bool vcpu_mode_priv(const struct kvm_vcpu *vcpu)
+{
+ u32 mode = *vcpu_cpsr(vcpu) & PSR_MODE_MASK;
+
+ return mode != PSR_MODE_EL0t;
+}
+
+static inline void kvm_skip_instr(struct kvm_vcpu *vcpu)
+{
+ *vcpu_pc(vcpu) += 4;
+ *vcpu_cpsr(vcpu) &= ~PSR_BTYPE_MASK;
+
+ /* advance the singlestep state machine */
+ *vcpu_cpsr(vcpu) &= ~SPSR_ELx_SS;
+}
+
+static inline void kvm_reset_fpsimd(struct kvm_vcpu *vcpu)
+{
+ memset(vcpu->arch.ctxt.vregs, 0, sizeof(vcpu->arch.ctxt.vregs));
+ vcpu->arch.sae_block.fpsr = 0;
+ vcpu->arch.sae_block.fpcr = 0;
+}
+
+#include <arm64/kvm_emulate-gen.h>
+
+#endif /* __S390_ARM64_KVM_EMULATE_H__ */
diff --git a/arch/s390/include/arm64/kvm_nested.h b/arch/s390/include/arm64/kvm_nested.h
new file mode 100644
index 000000000000..e950b1a10c41
--- /dev/null
+++ b/arch/s390/include/arm64/kvm_nested.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef ASM_KVM_NESTED_H
+#define ASM_KVM_NESTED_H
+
+static inline bool vcpu_has_nv(const struct kvm_vcpu *vcpu)
+{
+ return false;
+}
+
+#endif /* ASM_KVM_NESTED_H */
diff --git a/arch/s390/include/arm64/ptrace.h b/arch/s390/include/arm64/ptrace.h
new file mode 100644
index 000000000000..449b85582c97
--- /dev/null
+++ b/arch/s390/include/arm64/ptrace.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __S390_ARM64_PTRACE_H__
+#define __S390_ARM64_PTRACE_H__
+
+#include <arm64/sysreg.h>
+#include <uapi/arm64/ptrace.h>
+
+#include <arm64/ptrace-gen.h>
+
+#endif /* __S390_ARM64_PTRACE_H__ */
diff --git a/arch/s390/include/arm64/sysreg.h b/arch/s390/include/arm64/sysreg.h
new file mode 100644
index 000000000000..ac6b638fef56
--- /dev/null
+++ b/arch/s390/include/arm64/sysreg.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __S390_ARM64_SYSREG_H__
+#define __S390_ARM64_SYSREG_H__
+
+#include <linux/bits.h>
+#include <linux/stringify.h>
+#include <linux/kasan-tags.h>
+#include <linux/kconfig.h>
+
+#include <arm64/sysreg-gen.h>
+
+#endif /* __S390_ARM64_SYSREG_H__ */
diff --git a/arch/s390/kvm/arm64/handle_exit.c b/arch/s390/kvm/arm64/handle_exit.c
new file mode 100644
index 000000000000..046e905ffcb6
--- /dev/null
+++ b/arch/s390/kvm/arm64/handle_exit.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/kvm_host.h>
+
+#include <arm64/esr.h>
+#include <arm64/kvm_emulate.h>
+
+typedef int (*exit_handle_fn)(struct kvm_vcpu *);
+static exit_handle_fn arm_exit_handlers[ESR_ELx_EC_MAX + 1];
+
+#define PSCI_0_2_FN_SYSTEM_OFF 0x84000008
+#define PSCI_RET_NOT_SUPPORTED -1
+#define PSCI_RET_INTERNAL_FAILURE -6
+/*
+ * Temporary smc/hvc handler. Non-compliant implementation (features missing).
+ * Implements only system off so that test programs are able to end their execution.
+ * Multi-vCPU power state management and KVM_REQ_SLEEP handling are deferred
+ * to future SMP series.
+ */
+static int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
+{
+ u32 func_id = vcpu_get_reg(vcpu, 0);
+ u64 val = PSCI_RET_NOT_SUPPORTED;
+ int ret = 1;
+
+ if (func_id == PSCI_0_2_FN_SYSTEM_OFF) {
+ scoped_guard(spinlock, &vcpu->arch.mp_state_lock) {
+ WRITE_ONCE(vcpu->arch.mp_state.mp_state, KVM_MP_STATE_STOPPED);
+ }
+ memset(&vcpu->run->system_event, 0,
+ sizeof(vcpu->run->system_event));
+ vcpu->run->system_event.type = KVM_SYSTEM_EVENT_SHUTDOWN;
+ vcpu->run->system_event.ndata = 1;
+ vcpu->run->system_event.data[0] = 0;
+ vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
+ val = PSCI_RET_INTERNAL_FAILURE;
+ ret = 0;
+ }
+ vcpu_set_reg(vcpu, 0, val);
+
+ return ret;
+}
+
+static int handle_hvc(struct kvm_vcpu *vcpu)
+{
+ vcpu->stat.hvc_exit_stat++;
+ return kvm_smccc_call_handler(vcpu);
+}
+
+static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu)
+{
+ u64 esr = kvm_vcpu_get_esr(vcpu);
+
+ kvm_pr_unimpl("Unknown exception class: esr: %#016llx -- %s\n",
+ esr, esr_get_class_string(esr));
+
+ kvm_inject_undefined(vcpu);
+ return 1;
+}
+
+static exit_handle_fn arm_exit_handlers[] = {
+ [0 ... ESR_ELx_EC_MAX] = kvm_handle_unknown_ec,
+ [ESR_ELx_EC_HVC64] = handle_hvc,
+};
+
+static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
+{
+ u64 esr = kvm_vcpu_get_esr(vcpu);
+ u8 esr_ec = ESR_ELx_EC(esr);
+
+ return arm_exit_handlers[esr_ec];
+}
+
+/*
+ * We may be single-stepping an emulated instruction. If the emulation
+ * has been completed in the kernel, we can return to userspace with a
+ * KVM_EXIT_DEBUG, otherwise userspace needs to complete its
+ * emulation first.
+ */
+static int handle_trap_exceptions(struct kvm_vcpu *vcpu)
+{
+ exit_handle_fn exit_handler;
+
+ exit_handler = kvm_get_exit_handler(vcpu);
+ return exit_handler(vcpu);
+}
+
+/* manually copied from arch/arm64/kernel/traps.c */
+static const char * const esr_class_str[] = {
+ [0 ... ESR_ELx_EC_MAX] = "UNRECOGNIZED EC",
+ [ESR_ELx_EC_UNKNOWN] = "Unknown/Uncategorized",
+ [ESR_ELx_EC_WFx] = "WFI/WFE",
+ [ESR_ELx_EC_FP_ASIMD] = "ASIMD",
+ [ESR_ELx_EC_PAC] = "PAC",
+ [ESR_ELx_EC_BTI] = "BTI",
+ [ESR_ELx_EC_ILL] = "PSTATE.IL",
+ [ESR_ELx_EC_SVC64] = "SVC (AArch64)",
+ [ESR_ELx_EC_HVC64] = "HVC (AArch64)",
+ [ESR_ELx_EC_SMC64] = "SMC (AArch64)",
+ [ESR_ELx_EC_SYS64] = "MSR/MRS (AArch64)",
+ [ESR_ELx_EC_SVE] = "SVE",
+ [ESR_ELx_EC_ERET] = "ERET/ERETAA/ERETAB",
+ [ESR_ELx_EC_FPAC] = "FPAC",
+ [ESR_ELx_EC_SME] = "SME",
+ [ESR_ELx_EC_IMP_DEF] = "EL3 IMP DEF",
+ [ESR_ELx_EC_IABT_LOW] = "IABT (lower EL)",
+ [ESR_ELx_EC_IABT_CUR] = "IABT (current EL)",
+ [ESR_ELx_EC_PC_ALIGN] = "PC Alignment",
+ [ESR_ELx_EC_DABT_LOW] = "DABT (lower EL)",
+ [ESR_ELx_EC_DABT_CUR] = "DABT (current EL)",
+ [ESR_ELx_EC_SP_ALIGN] = "SP Alignment",
+ [ESR_ELx_EC_MOPS] = "MOPS",
+ [ESR_ELx_EC_FP_EXC64] = "FP (AArch64)",
+ [ESR_ELx_EC_GCS] = "Guarded Control Stack",
+ [ESR_ELx_EC_SERROR] = "SError",
+ [ESR_ELx_EC_BREAKPT_LOW] = "Breakpoint (lower EL)",
+ [ESR_ELx_EC_BREAKPT_CUR] = "Breakpoint (current EL)",
+ [ESR_ELx_EC_SOFTSTP_LOW] = "Software Step (lower EL)",
+ [ESR_ELx_EC_SOFTSTP_CUR] = "Software Step (current EL)",
+ [ESR_ELx_EC_WATCHPT_LOW] = "Watchpoint (lower EL)",
+ [ESR_ELx_EC_WATCHPT_CUR] = "Watchpoint (current EL)",
+ [ESR_ELx_EC_BRK64] = "BRK (AArch64)",
+};
+
+const char *esr_get_class_string(unsigned long esr)
+{
+ return esr_class_str[ESR_ELx_EC(esr)];
+}
diff --git a/arch/s390/kvm/arm64/inject_fault.c b/arch/s390/kvm/arm64/inject_fault.c
new file mode 100644
index 000000000000..425dbeaa421c
--- /dev/null
+++ b/arch/s390/kvm/arm64/inject_fault.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <arm64/kvm_emulate.h>
+
+/**
+ * kvm_inject_undefined - inject an undefined instruction into the guest
+ * @vcpu: The vCPU in which to inject the exception
+ *
+ * It is assumed that this code is called from the VCPU thread and that the
+ * VCPU therefore is not currently executing guest code.
+ */
+void kvm_inject_undefined(struct kvm_vcpu *vcpu)
+{
+ /* Stub until s390 supports arm64 sysregs TODO sysregs*/
+}
+
+int kvm_inject_sea(struct kvm_vcpu *vcpu, bool iabt, u64 addr)
+{
+ /* Stub until s390 supports arm64 sysregs TODO sysregs*/
+ return 1;
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 24/29] KVM: s390: arm64: Implement required functions
2026-09-18 13:31 ` [PATCH v8 24/29] KVM: s390: arm64: Implement required functions Steffen Eiden
@ 2026-09-18 17:13 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 17:13 UTC (permalink / raw)
To: Steffen Eiden
Cc: Marc Zyngier, Heiko Carstens, linux-s390, Vasily Gorbik,
Alexander Gordeev, Oliver Upton, kvm, Christian Borntraeger,
kvmarm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] kvm: arm64: guest-triggerable host infinite loop due to empty exception stubs
--
commit d9fe4f13dd483ddf56413b5d5c4c9d6582209f75
Author: Steffen Eiden <seiden@linux.ibm.com>
KVM: s390: arm64: Implement required functions
This commit implements various stub functions and simple handlers required
by the shared ARM64 KVM code for the s390 architecture. It includes an
initial smccc handler to stop a vCPU and several exception injection stubs.
> diff --git a/arch/s390/kvm/arm64/handle_exit.c b/arch/s390/kvm/arm64/handle_exit.c
> --- /dev/null
> +++ b/arch/s390/kvm/arm64/handle_exit.c
[ ... ]
> +static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu)
> +{
> + u64 esr = kvm_vcpu_get_esr(vcpu);
> +
> + kvm_pr_unimpl("Unknown exception class: esr: %#016llx -- %s\n",
> + esr, esr_get_class_string(esr));
> +
> + kvm_inject_undefined(vcpu);
> + return 1;
> +}
[Severity: Medium]
Because kvm_inject_undefined() is currently an empty stub, does returning 1
here tell the run loop to resume the guest without modifying its state?
If the guest's PC is not advanced, this can cause the guest to immediately
re-trap the exact same instruction, leading to an infinite trap loop that
pegs the host VCPU thread at 100% and spams the kernel log.
> diff --git a/arch/s390/kvm/arm64/inject_fault.c b/arch/s390/kvm/arm64/inject_fault.c
> --- /dev/null
> +++ b/arch/s390/kvm/arm64/inject_fault.c
[ ... ]
> +void kvm_inject_undefined(struct kvm_vcpu *vcpu)
> +{
> + /* Stub until s390 supports arm64 sysregs TODO sysregs*/
> +}
[Severity: Medium]
Will leaving this as an empty stub fail to advance the Program Counter or
modify guest registers to actually inject the exception?
Failing to modify the guest state before returning to execution means any
unprivileged guest executing an undefined instruction could trivially trigger
an infinite loop.
> +
> +int kvm_inject_sea(struct kvm_vcpu *vcpu, bool iabt, u64 addr)
> +{
> + /* Stub until s390 supports arm64 sysregs TODO sysregs*/
> + return 1;
> +}
[Severity: Medium]
Can returning 1 from this empty memory fault stub identically cause an
infinite loop for unimplemented memory faults?
Since the guest state isn't modified to inject the fault, resuming it will
simply re-execute the failing instruction over and over.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=24
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 25/29] KVM: s390: arm64: Implement vm/vcpu create destroy.
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (23 preceding siblings ...)
2026-09-18 13:31 ` [PATCH v8 24/29] KVM: s390: arm64: Implement required functions Steffen Eiden
@ 2026-09-18 13:31 ` Steffen Eiden
2026-09-18 17:24 ` sashiko-bot
2026-09-18 13:31 ` [PATCH v8 26/29] KVM: s390: arm64: Implement vCPU IOCTLs Steffen Eiden
` (4 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:31 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Implement init and destroy IOCTLS for vcpu and vm.
Implement arch vm IOCTL. Use s390 gmap and gmap plumbing.
Implement function (stubs) required by gamp.
Co-developed-by: Janosch Frank <frankja@linux.ibm.com>
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Co-developed-by: Andreas Grapentin <gra@linux.ibm.com>
Signed-off-by: Andreas Grapentin <gra@linux.ibm.com>
Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/kvm/arm64/arm.c | 189 ++++++++++++++++++++++++++++++++
arch/s390/kvm/arm64/arm.h | 14 +++
arch/s390/kvm/gmap/faultin.c | 5 +
arch/s390/kvm/gmap/gmap.c | 4 +
arch/s390/kvm/gmap/kvm_mmu.c | 4 +
arch/s390/kvm/gmap/trace_gmap.h | 13 +++
6 files changed, 229 insertions(+)
diff --git a/arch/s390/kvm/arm64/arm.c b/arch/s390/kvm/arm64/arm.c
index 8b056fc836d7..446070fea29f 100644
--- a/arch/s390/kvm/arm64/arm.c
+++ b/arch/s390/kvm/arm64/arm.c
@@ -8,6 +8,9 @@
#include <linux/kvm_types.h>
#include <linux/kvm_host.h>
+#include <gmap.h>
+#include <kvm_mmu.h>
+
#include "arm.h"
#define CREATE_TRACE_POINTS
@@ -19,6 +22,8 @@ static unsigned long system_supported_vcpu_features(void);
#include "generated/arm.inc"
#undef __INCL_GEN_ARM_FILE
+#define KVM_PHYS_SHIFT (40)
+
int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
{
int ret;
@@ -51,6 +56,83 @@ static u64 kvm_max_guest_address(void)
return ALIGN_DOWN(max_addr + 1, SZ_1G) - 1;
}
+static int kvm_gmap_init(struct kvm *kvm)
+{
+ struct crst_table *table;
+
+ kvm->arch.gmap = gmap_new(kvm, gpa_to_gfn(kvm->arch.guest_phys_size));
+
+ if (!kvm->arch.gmap)
+ return -ENOMEM;
+
+ /* arm64 (on s390) do not have pfault */
+ clear_bit(GMAP_FLAG_PFAULT_ENABLED, &kvm->arch.gmap->flags);
+ set_bit(GMAP_FLAG_ALLOW_HPAGE_1M, &kvm->arch.gmap->flags);
+
+ table = dereference_asce(kvm->arch.gmap->asce);
+ crst_table_init((void *)table, _CRSTE_HOLE(table->crstes[0].h.tt).val);
+
+ return 0;
+}
+
+static int kvm_vm_type_ipa_size_shift(unsigned long type)
+{
+ int phys_shift;
+
+ phys_shift = KVM_VM_TYPE_ARM_IPA_SIZE(type);
+ if (phys_shift) {
+ if (phys_shift > get_kvm_ipa_limit() ||
+ phys_shift < ARM64_MIN_PARANGE_BITS)
+ return -EINVAL;
+ } else {
+ phys_shift = KVM_PHYS_SHIFT;
+ if (phys_shift > get_kvm_ipa_limit()) {
+ pr_warn_once("%s using unsupported default IPA limit\n",
+ current->comm);
+ return -EINVAL;
+ }
+ }
+
+ return phys_shift;
+}
+
+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
+{
+ char debug_name[32];
+ int ret;
+
+ if (type & ~KVM_VM_TYPE_ARM_IPA_SIZE_MASK)
+ return -EINVAL;
+
+ ret = kvm_vm_type_ipa_size_shift(type);
+ if (ret < 0)
+ return ret;
+ kvm->arch.guest_phys_size = 1UL << ret;
+
+ mutex_init(&kvm->arch.config_lock);
+ bitmap_zero(kvm->arch.vcpu_features, KVM_VCPU_MAX_FEATURES);
+
+ snprintf(debug_name, sizeof(debug_name), "kvm-arm64-%u-%u",
+ current->pid, get_random_u32());
+ kvm->arch.dbf = debug_register(debug_name, 32, 1, 7 * sizeof(long));
+ if (!kvm->arch.dbf)
+ return -ENOMEM;
+ debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
+
+ ret = kvm_gmap_init(kvm);
+ if (ret)
+ goto out_err;
+ kvm->arch.mem_limit = kvm->arch.guest_phys_size;
+
+ VM_EVENT(kvm, 3, "vm created with type %lu", type);
+ return 0;
+
+out_err:
+ debug_unregister(kvm->arch.dbf);
+
+ return ret;
+}
+
vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
{
return VM_FAULT_SIGBUS;
@@ -62,6 +144,13 @@ long kvm_arch_dev_ioctl(struct file *filp,
return -EINVAL;
}
+void kvm_arch_destroy_vm(struct kvm *kvm)
+{
+ kvm_destroy_vcpus(kvm);
+ debug_unregister(kvm->arch.dbf);
+ kvm->arch.gmap = gmap_put(kvm->arch.gmap);
+}
+
u32 get_kvm_ipa_limit(void)
{
return fls64(kvm_max_guest_address() + 1) - 1;
@@ -72,10 +161,43 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
return 0;
}
+int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
+{
+ struct kvm_sae_block *sae_block = &vcpu->arch.sae_block;
+ struct kvm_sae_save_area *save_area = &vcpu->arch.save_area;
+
+ spin_lock_init(&vcpu->arch.mp_state_lock);
+
+ /* Force users to call KVM_ARM_VCPU_INIT */
+ vcpu_clear_flag(vcpu, VCPU_INITIALIZED);
+
+ vcpu->arch.mc = kvm_s390_new_mmu_cache();
+ if (!vcpu->arch.mc)
+ return -ENOMEM;
+
+ sae_block->hbasce = vcpu->kvm->arch.gmap->asce.val;
+ sae_block->mso = 0L;
+ sae_block->msl = vcpu->kvm->arch.mem_limit - 1;
+ sae_block->save_area = virt_to_phys(save_area);
+
+ VM_EVENT(vcpu->kvm, 3,
+ "create cpu %d at 0x%p, sae block at 0x%p, satellite at 0x%p",
+ vcpu->vcpu_id, vcpu, &vcpu->arch.sae_block,
+ &vcpu->arch.save_area);
+ return 0;
+}
+
void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
{
}
+void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
+{
+ kvm_s390_free_mmu_cache(vcpu->arch.mc);
+
+ VCPU_EVENT(vcpu, 3, "%s", "free cpu");
+}
+
int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
struct kvm_mp_state *mp_state)
{
@@ -101,6 +223,73 @@ static unsigned long system_supported_vcpu_features(void)
return features;
}
+int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
+ struct kvm_dirty_log *log)
+{
+ return s390_kvm_mmu_get_dirty_log(kvm, log);
+}
+
+bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
+{
+ scoped_guard(read_lock, &kvm->mmu_lock)
+ return gmap_age_gfn(kvm->arch.gmap, range->start, range->end);
+}
+
+void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
+{
+ gfn_t last_gfn = memslot->base_gfn + memslot->npages;
+
+ scoped_guard(read_lock, &kvm->mmu_lock)
+ gmap_sync_dirty_log(kvm->arch.gmap, memslot->base_gfn, last_gfn);
+}
+
+int kvm_arch_prepare_memory_region(struct kvm *kvm,
+ const struct kvm_memory_slot *old,
+ struct kvm_memory_slot *new,
+ enum kvm_mr_change change)
+{
+ return s390_kvm_mmu_prepare_memory_region(kvm, old, new, change);
+}
+
+void kvm_arch_commit_memory_region(struct kvm *kvm, struct kvm_memory_slot *old,
+ const struct kvm_memory_slot *new,
+ enum kvm_mr_change change)
+{
+ s390_kvm_mmu_commit_memory_region(kvm, old, new, change);
+}
+
+bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
+{
+ return gmap_unmap_gfn_range(kvm->arch.gmap, range->slot, range->start, range->end);
+}
+
+bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
+{
+ scoped_guard(read_lock, &kvm->mmu_lock)
+ return dat_test_age_gfn(kvm->arch.gmap->asce, range->start, range->end);
+}
+
+int kvm_arch_vm_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+
+ switch (ioctl) {
+ case KVM_ARM_PREFERRED_TARGET: {
+ struct kvm_vcpu_init init = {
+ .target = KVM_ARM_TARGET_GENERIC_V8,
+ };
+
+ if (copy_to_user(argp, &init, sizeof(init)))
+ return -EFAULT;
+
+ return 0;
+ }
+
+ default:
+ return -EINVAL;
+ }
+}
+
bool kvm_arch_irqchip_in_kernel(struct kvm *kvm)
{
return false;
diff --git a/arch/s390/kvm/arm64/arm.h b/arch/s390/kvm/arm64/arm.h
index b38eb44c11fe..c743595506fa 100644
--- a/arch/s390/kvm/arm64/arm.h
+++ b/arch/s390/kvm/arm64/arm.h
@@ -2,6 +2,20 @@
#ifndef ARCH_S390_KVM_ARM64_H
#define ARCH_S390_KVM_ARM64_H
+#include <linux/compiler_attributes.h>
+#include <linux/kvm_host.h>
+
+#define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...) \
+ debug_sprintf_event((d_kvm)->arch.dbf, d_loglevel, \
+ __stringify(KVM_DEV_NAME) ": " d_string "\n", \
+ d_args)
+
+#define VCPU_EVENT(d_vcpu, d_loglevel, d_string, d_args...) \
+ debug_sprintf_event((d_vcpu)->kvm->arch.dbf, d_loglevel, \
+ __stringify(KVM_DEV_NAME) " %02d[%016llx-%016llx]: " d_string "\n", \
+ (d_vcpu)->vcpu_id, (d_vcpu)->arch.sae_block.pstate, \
+ (d_vcpu)->arch.sae_block.pc, d_args)
+
static __always_inline int kvm_is_ucontrol(struct kvm *kvm)
{
return 0;
diff --git a/arch/s390/kvm/gmap/faultin.c b/arch/s390/kvm/gmap/faultin.c
index 1dc79807012c..2e93bd563d5c 100644
--- a/arch/s390/kvm/gmap/faultin.c
+++ b/arch/s390/kvm/gmap/faultin.c
@@ -10,6 +10,11 @@
#include "gmap.h"
#include "faultin.h"
+#ifdef KVM_S390_ARM64
+#include "arm.h"
+#else
+#include "s390.h"
+#endif
bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu);
#define CREATE_TRACE_POINTS
diff --git a/arch/s390/kvm/gmap/gmap.c b/arch/s390/kvm/gmap/gmap.c
index 4968330e9553..b7071f50f7ad 100644
--- a/arch/s390/kvm/gmap/gmap.c
+++ b/arch/s390/kvm/gmap/gmap.c
@@ -21,7 +21,11 @@
#include "dat.h"
#include "gmap.h"
+#ifdef KVM_S390_ARM64
+#include "arm.h"
+#else
#include "s390.h"
+#endif
#include "faultin.h"
static int gmap_limit_to_type(gfn_t limit)
diff --git a/arch/s390/kvm/gmap/kvm_mmu.c b/arch/s390/kvm/gmap/kvm_mmu.c
index b08b8229bb6f..a26a16193467 100644
--- a/arch/s390/kvm/gmap/kvm_mmu.c
+++ b/arch/s390/kvm/gmap/kvm_mmu.c
@@ -3,7 +3,11 @@
#include <linux/kvm_types.h>
#include <linux/kvm_host.h>
+#ifdef KVM_S390_ARM64
+#include "arm.h"
+#else
#include "s390.h"
+#endif
#include "gmap.h"
#include "dat.h"
#include "kvm_mmu.h"
diff --git a/arch/s390/kvm/gmap/trace_gmap.h b/arch/s390/kvm/gmap/trace_gmap.h
index 78d26dae59f9..1dce3ef3b0d9 100644
--- a/arch/s390/kvm/gmap/trace_gmap.h
+++ b/arch/s390/kvm/gmap/trace_gmap.h
@@ -13,6 +13,18 @@
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE trace_gmap
+#ifdef KVM_S390_ARM64
+#define __KVM_FIELDS \
+ __field(unsigned long, pstate) \
+ __field(unsigned long, pc)
+#define __KVM_ASSIGN ({\
+ __entry->pstate = vcpu->arch.sae_block.pstate; \
+ __entry->pc = vcpu->arch.sae_block.pc; \
+ })
+#define __KVM_PRINT \
+ __entry->pstate, \
+ __entry->pc
+#else
#define __KVM_FIELDS \
__field(unsigned long, pswmask) \
__field(unsigned long, pswaddr)
@@ -23,6 +35,7 @@
#define __KVM_PRINT \
__entry->pswmask,\
__entry->pswaddr
+#endif
TRACE_EVENT(kvm_s390_major_guest_pfault,
TP_PROTO(struct kvm_vcpu *vcpu),
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* [PATCH v8 26/29] KVM: s390: arm64: Implement vCPU IOCTLs
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (24 preceding siblings ...)
2026-09-18 13:31 ` [PATCH v8 25/29] KVM: s390: arm64: Implement vm/vcpu create destroy Steffen Eiden
@ 2026-09-18 13:31 ` Steffen Eiden
2026-09-18 17:45 ` sashiko-bot
2026-09-18 13:31 ` [PATCH v8 27/29] KVM: s390: arm64: Implement basic page fault handler Steffen Eiden
` (3 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:31 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Implement all required vCPU (arch) IOCTLs.
Co-developed-by: Andreas Grapentin <gra@linux.ibm.com>
Signed-off-by: Andreas Grapentin <gra@linux.ibm.com>
Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/kvm/arm64/arm.c | 404 ++++++++++++++++++++++++++++++
arch/s390/kvm/arm64/guest.c | 47 +++-
arch/s390/kvm/arm64/handle_exit.c | 32 +++
arch/s390/kvm/arm64/handle_exit.h | 9 +
arch/s390/kvm/arm64/reset.c | 71 ++++++
arch/s390/kvm/arm64/trace.h | 2 +-
6 files changed, 562 insertions(+), 3 deletions(-)
create mode 100644 arch/s390/kvm/arm64/handle_exit.h
create mode 100644 arch/s390/kvm/arm64/reset.c
diff --git a/arch/s390/kvm/arm64/arm.c b/arch/s390/kvm/arm64/arm.c
index 446070fea29f..bb3e7fa8cad5 100644
--- a/arch/s390/kvm/arm64/arm.c
+++ b/arch/s390/kvm/arm64/arm.c
@@ -7,11 +7,19 @@
#include <linux/kvm.h>
#include <linux/kvm_types.h>
#include <linux/kvm_host.h>
+#include <linux/cleanup.h>
+#include <linux/fpu.h>
+
+#include <asm/access-regs.h>
+
+#include <arm64/kvm_emulate.h>
+#include <arm64/sysreg.h>
#include <gmap.h>
#include <kvm_mmu.h>
#include "arm.h"
+#include "handle_exit.h"
#define CREATE_TRACE_POINTS
#include "trace.h"
@@ -198,6 +206,22 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
VCPU_EVENT(vcpu, 3, "%s", "free cpu");
}
+void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
+{
+ save_access_regs(&vcpu->arch.host_acrs[0]);
+ vcpu->cpu = cpu;
+
+ lasrm(&vcpu->arch.save_area);
+}
+
+void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
+{
+ stiasrm(&vcpu->arch.save_area);
+
+ vcpu->cpu = -1;
+ restore_access_regs(&vcpu->arch.host_acrs[0]);
+}
+
int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
struct kvm_mp_state *mp_state)
{
@@ -223,6 +247,386 @@ static unsigned long system_supported_vcpu_features(void)
return features;
}
+bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
+{
+ return vcpu_mode_priv(vcpu);
+}
+
+int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
+{
+ struct kvm *kvm = vcpu->kvm;
+
+ if (!kvm_vcpu_initialized(vcpu))
+ return -ENOEXEC;
+
+ if (!kvm_arm_vcpu_is_finalized(vcpu))
+ return -EPERM;
+
+ if (likely(READ_ONCE(vcpu->pid)))
+ return 0;
+
+ scoped_guard(mutex, &kvm->arch.config_lock)
+ set_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags);
+
+ return 0;
+}
+
+/**
+ * check_vcpu_requests - check and handle pending vCPU requests
+ * @vcpu: the VCPU pointer
+ *
+ * Return: 1 if we should enter the guest
+ * 0 if we should exit to userspace
+ * < 0 if we should exit to userspace, where the return value indicates
+ * an error
+ */
+static int check_vcpu_requests(struct kvm_vcpu *vcpu)
+{
+ if (kvm_request_pending(vcpu)) {
+ if (kvm_check_request(KVM_REQ_VCPU_RESET, vcpu))
+ kvm_reset_vcpu(vcpu);
+ /*
+ * Clear IRQ_PENDING requests that were made to guarantee
+ * that a VCPU sees new virtual interrupts.
+ */
+ kvm_check_request(KVM_REQ_IRQ_PENDING, vcpu);
+ kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu);
+ }
+
+ return 1;
+}
+
+static int kvm_vcpu_initialize(struct kvm_vcpu *vcpu,
+ const struct kvm_vcpu_init *init)
+{
+ unsigned long features = init->features[0];
+ struct kvm *kvm = vcpu->kvm;
+
+ guard(mutex)(&kvm->arch.config_lock);
+ if (test_bit(KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED, &kvm->arch.flags) &&
+ kvm_vcpu_init_changed(vcpu, init))
+ return -EINVAL;
+
+ bitmap_copy(kvm->arch.vcpu_features, &features, KVM_VCPU_MAX_FEATURES);
+
+ kvm_reset_vcpu(vcpu);
+
+ set_bit(KVM_ARCH_FLAG_VCPU_FEATURES_CONFIGURED, &kvm->arch.flags);
+ vcpu_set_flag(vcpu, VCPU_INITIALIZED);
+
+ return 0;
+}
+
+static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
+ const struct kvm_vcpu_init *init)
+{
+ int ret;
+
+ if (init->target != KVM_ARM_TARGET_GENERIC_V8)
+ return -EINVAL;
+
+ ret = kvm_vcpu_init_check_features(vcpu, init);
+ if (ret)
+ return ret;
+
+ if (!kvm_vcpu_initialized(vcpu))
+ return kvm_vcpu_initialize(vcpu, init);
+
+ if (kvm_vcpu_init_changed(vcpu, init))
+ return -EINVAL;
+
+ kvm_reset_vcpu(vcpu);
+
+ return 0;
+}
+
+static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
+ struct kvm_vcpu_init *init)
+{
+ struct kvm_sae_save_area *save_area = &vcpu->arch.save_area;
+ struct kvm_sae_block *sae_block = &vcpu->arch.sae_block;
+ int ret;
+
+ sae_block->save_area = virt_to_phys(save_area);
+ save_area->sdo = virt_to_phys(sae_block);
+
+ ret = kvm_vcpu_set_target(vcpu, init);
+ if (ret)
+ return ret;
+
+ scoped_guard(spinlock, &vcpu->arch.mp_state_lock) {
+ WRITE_ONCE(vcpu->arch.mp_state.mp_state, KVM_MP_STATE_RUNNABLE);
+ }
+
+ return 0;
+}
+
+int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level,
+ bool line_status)
+{
+ /* stub for now*/
+ return -EINVAL;
+}
+
+static void adjust_pc(struct kvm_vcpu *vcpu)
+{
+ if (vcpu_get_flag(vcpu, INCREMENT_PC)) {
+ kvm_skip_instr(vcpu);
+ vcpu_clear_flag(vcpu, INCREMENT_PC);
+ }
+}
+
+static void arm_vcpu_run(struct kvm_vcpu *vcpu)
+{
+ struct kvm_sae_block *sae_block = &vcpu->arch.sae_block;
+
+ adjust_pc(vcpu);
+
+ local_irq_disable();
+ guest_timing_enter_irqoff();
+ guest_state_enter_irqoff();
+ local_irq_enable();
+
+ sae64a(sae_block);
+
+ local_irq_disable();
+ guest_state_exit_irqoff();
+ guest_timing_exit_irqoff();
+ local_irq_enable();
+}
+
+/** kvm_arch_vcpu_ioctl_run() - run arm64 vCPU
+ *
+ * Execute arm64 guest instructions using SAE.
+ *
+ * Returns:
+ * 1 enter the guest (should not be observed by userspace)
+ * 0 exit to userspace
+ * < 0 exit to userspace, where the return value indicates n error
+ *
+ *
+ */
+int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
+{
+ DECLARE_KERNEL_FPU_ONSTACK32(fpu_save);
+ struct kvm_run *kvm_run = vcpu->run;
+ int ret;
+
+ if (kvm_run->exit_reason == KVM_EXIT_MMIO) {
+ ret = kvm_handle_mmio_return(vcpu);
+ if (ret <= 0)
+ return ret;
+ }
+
+ vcpu_load(vcpu);
+
+ kernel_fpu_begin(&fpu_save, KERNEL_FPC | KERNEL_VXR);
+ load_vx_regs((vcpu->arch.ctxt.vregs));
+
+ if (!vcpu->wants_to_run) {
+ ret = -EINTR;
+ goto out;
+ }
+
+ kvm_sigset_activate(vcpu);
+
+ might_fault();
+
+ kvm_vcpu_srcu_read_lock(vcpu);
+
+ ret = 1;
+ while (ret > 0) {
+
+ ret = kvm_xfer_to_guest_mode_handle_work(vcpu);
+ if (!ret)
+ ret = 1;
+
+ if (ret > 0)
+ ret = check_vcpu_requests(vcpu);
+
+ if (ret <= 0)
+ break;
+
+ vcpu->arch.sae_block.icptr = 0;
+
+ smp_store_mb(vcpu->mode, IN_GUEST_MODE);
+
+ if (kvm_request_pending(vcpu)) {
+ vcpu->mode = OUTSIDE_GUEST_MODE;
+ continue;
+ }
+
+ kvm_vcpu_srcu_read_unlock(vcpu);
+
+ arm_vcpu_run(vcpu);
+
+ vcpu->mode = OUTSIDE_GUEST_MODE;
+ vcpu->stat.exits++;
+
+ kvm_vcpu_srcu_read_lock(vcpu);
+
+ ret = handle_exit(vcpu);
+ }
+
+ kvm_vcpu_srcu_read_unlock(vcpu);
+
+ kvm_sigset_deactivate(vcpu);
+out:
+ if (unlikely(vcpu_get_flag(vcpu, INCREMENT_PC)))
+ adjust_pc(vcpu);
+
+ save_vx_regs(vcpu->arch.ctxt.vregs);
+ kernel_fpu_end(&fpu_save, KERNEL_FPC | KERNEL_VXR);
+ vcpu_put(vcpu);
+
+ return ret;
+}
+
+static int kvm_arm_vcpu_set_attr(struct kvm_vcpu *vcpu,
+ struct kvm_device_attr *attr)
+{
+ int ret;
+
+ switch (attr->group) {
+ default:
+ ret = -ENXIO;
+ break;
+ }
+
+ return ret;
+}
+
+static int kvm_arm_vcpu_get_attr(struct kvm_vcpu *vcpu,
+ struct kvm_device_attr *attr)
+{
+ int ret;
+
+ switch (attr->group) {
+ default:
+ ret = -ENXIO;
+ break;
+ }
+
+ return ret;
+}
+
+static int kvm_arm_vcpu_has_attr(struct kvm_vcpu *vcpu,
+ struct kvm_device_attr *attr)
+{
+ int ret;
+
+ switch (attr->group) {
+ default:
+ ret = -ENXIO;
+ break;
+ }
+
+ return ret;
+}
+
+long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
+{
+ struct kvm_vcpu *vcpu = filp->private_data;
+ void __user *argp = (void __user *)arg;
+ struct kvm_device_attr attr;
+ int ret;
+
+ switch (ioctl) {
+ case KVM_ARM_VCPU_INIT: {
+ struct kvm_vcpu_init init;
+
+ ret = -EFAULT;
+ if (copy_from_user(&init, argp, sizeof(init)))
+ break;
+
+ ret = kvm_arch_vcpu_ioctl_vcpu_init(vcpu, &init);
+ break;
+ }
+ case KVM_SET_ONE_REG:
+ case KVM_GET_ONE_REG: {
+ struct kvm_one_reg reg;
+
+ ret = -ENOEXEC;
+ if (unlikely(!kvm_vcpu_initialized(vcpu)))
+ break;
+
+ ret = -EFAULT;
+ if (copy_from_user(®, argp, sizeof(reg)))
+ break;
+
+ if (kvm_check_request(KVM_REQ_VCPU_RESET, vcpu))
+ kvm_reset_vcpu(vcpu);
+
+ if (ioctl == KVM_SET_ONE_REG)
+ ret = kvm_arm_set_reg(vcpu, ®);
+ else
+ ret = kvm_arm_get_reg(vcpu, ®);
+ break;
+ }
+ case KVM_GET_REG_LIST: {
+ struct kvm_reg_list __user *user_list = argp;
+ struct kvm_reg_list reg_list;
+ unsigned int n;
+
+ ret = -ENOEXEC;
+ if (unlikely(!kvm_vcpu_initialized(vcpu)))
+ break;
+ ret = -EPERM;
+ if (!kvm_arm_vcpu_is_finalized(vcpu))
+ break;
+ ret = -EFAULT;
+ if (copy_from_user(®_list, user_list, sizeof(reg_list)))
+ break;
+ n = reg_list.n;
+ reg_list.n = kvm_arm_num_regs(vcpu);
+ if (copy_to_user(user_list, ®_list, sizeof(reg_list)))
+ break;
+ ret = -E2BIG;
+ if (n < reg_list.n)
+ break;
+ ret = kvm_arm_copy_reg_indices(vcpu, user_list->reg);
+ break;
+ }
+ case KVM_ARM_VCPU_FINALIZE: {
+ int what;
+
+ if (!kvm_vcpu_initialized(vcpu))
+ return -ENOEXEC;
+
+ if (get_user(what, (const int __user *)argp))
+ return -EFAULT;
+
+ ret = kvm_arm_vcpu_finalize(vcpu, what);
+ break;
+ }
+ case KVM_SET_DEVICE_ATTR: {
+ ret = -EFAULT;
+ if (copy_from_user(&attr, argp, sizeof(attr)))
+ break;
+ ret = kvm_arm_vcpu_set_attr(vcpu, &attr);
+ break;
+ }
+ case KVM_GET_DEVICE_ATTR: {
+ ret = -EFAULT;
+ if (copy_from_user(&attr, argp, sizeof(attr)))
+ break;
+ ret = kvm_arm_vcpu_get_attr(vcpu, &attr);
+ break;
+ }
+ case KVM_HAS_DEVICE_ATTR: {
+ ret = -EFAULT;
+ if (copy_from_user(&attr, argp, sizeof(attr)))
+ break;
+ ret = kvm_arm_vcpu_has_attr(vcpu, &attr);
+ break;
+ }
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
struct kvm_dirty_log *log)
{
diff --git a/arch/s390/kvm/arm64/guest.c b/arch/s390/kvm/arm64/guest.c
index fd6442d9e4f4..4ea6fe2c270d 100644
--- a/arch/s390/kvm/arm64/guest.c
+++ b/arch/s390/kvm/arm64/guest.c
@@ -5,8 +5,6 @@
#include <arm64/kvm_emulate.h>
#include <arm64/kvm_nested.h>
-#include "guest.h"
-
#define __INCL_GEN_ARM_FILE
#include "generated/guest.inc"
#undef __INCL_GEN_ARM_FILE
@@ -47,6 +45,51 @@ const struct kvm_stats_header kvm_vcpu_stats_header = {
sizeof(kvm_vcpu_stats_desc),
};
+int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
+{
+ int ret;
+
+ ret = copy_core_reg_indices(vcpu, uindices);
+ if (ret < 0)
+ return ret;
+ uindices += ret;
+
+ return 0;
+}
+
+unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
+{
+ return num_core_regs(vcpu);
+}
+
+int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+ /* We currently use nothing arch-specific in upper 32 bits */
+ if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM64 >> 32)
+ return -EINVAL;
+
+ switch (reg->id & KVM_REG_ARM_COPROC_MASK) {
+ case KVM_REG_ARM_CORE:
+ return get_core_reg(vcpu, reg);
+ default:
+ return -EINVAL;
+ }
+}
+
+int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+ /* We currently use nothing arch-specific in upper 32 bits */
+ if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM64 >> 32)
+ return -EINVAL;
+
+ switch (reg->id & KVM_REG_ARM_COPROC_MASK) {
+ case KVM_REG_ARM_CORE:
+ return set_core_reg(vcpu, reg);
+ default:
+ return -EINVAL;
+ }
+}
+
int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
{
return -EINVAL;
diff --git a/arch/s390/kvm/arm64/handle_exit.c b/arch/s390/kvm/arm64/handle_exit.c
index 046e905ffcb6..38a2cc4ee4e1 100644
--- a/arch/s390/kvm/arm64/handle_exit.c
+++ b/arch/s390/kvm/arm64/handle_exit.c
@@ -5,6 +5,8 @@
#include <arm64/esr.h>
#include <arm64/kvm_emulate.h>
+#include "handle_exit.h"
+
typedef int (*exit_handle_fn)(struct kvm_vcpu *);
static exit_handle_fn arm_exit_handlers[ESR_ELx_EC_MAX + 1];
@@ -85,6 +87,36 @@ static int handle_trap_exceptions(struct kvm_vcpu *vcpu)
return exit_handler(vcpu);
}
+/*
+ * Return > 0 to return to guest, < 0 on error, 0 (and set exit_reason) on
+ * proper exit to userspace.
+ */
+int handle_exit(struct kvm_vcpu *vcpu)
+{
+ u8 icptr = vcpu->arch.sae_block.icptr;
+ int ret = 1;
+
+ switch (icptr) {
+ case SAE_ICPTR_SPURIOUS:
+ break;
+ case SAE_ICPTR_VALIDITY:
+ WARN_ONCE(true, "SAE: validity intercept. vir: 0x%04x",
+ vcpu->arch.sae_block.vir);
+ vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+ ret = 0;
+ break;
+ case SAE_ICPTR_GUEST_ADDRESS_SIZE:
+ case SAE_ICPTR_HOST_ACCESS_EXCEPTION:
+ case SAE_ICPTR_SYNCHRONOUS_EXCEPTION:
+ ret = handle_trap_exceptions(vcpu);
+ break;
+ default:
+ vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+ ret = 0;
+ }
+ return ret;
+}
+
/* manually copied from arch/arm64/kernel/traps.c */
static const char * const esr_class_str[] = {
[0 ... ESR_ELx_EC_MAX] = "UNRECOGNIZED EC",
diff --git a/arch/s390/kvm/arm64/handle_exit.h b/arch/s390/kvm/arm64/handle_exit.h
new file mode 100644
index 000000000000..65ae58721537
--- /dev/null
+++ b/arch/s390/kvm/arm64/handle_exit.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef KVM_ARM64_HANDLE_EXIT_H
+#define KVM_ARM64_HANDLE_EXIT_H
+
+#include <linux/kvm_host.h>
+
+int handle_exit(struct kvm_vcpu *vcpu);
+
+#endif /* KVM_ARM64_HANDLE_EXIT_H */
diff --git a/arch/s390/kvm/arm64/reset.c b/arch/s390/kvm/arm64/reset.c
new file mode 100644
index 000000000000..e4cdce1dbf9d
--- /dev/null
+++ b/arch/s390/kvm/arm64/reset.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/kvm_host.h>
+#include <linux/fpu.h>
+
+#include <arm64/kvm_emulate.h>
+#include <arm64/kvm_nested.h>
+
+bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu)
+{
+ return true;
+}
+
+static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
+{
+ vcpu->arch.hcr_el2 = HCR_EL2_E2H | HCR_EL2_RW | HCR_EL2_AMO |
+ HCR_EL2_IMO | HCR_EL2_FMO | HCR_EL2_PTW;
+ /* traps */
+ vcpu->arch.hcr_el2 |= HCR_EL2_TSC | HCR_EL2_TID1 | HCR_EL2_TID2 |
+ HCR_EL2_TID3 | HCR_EL2_TID4 | HCR_EL2_TID5 |
+ HCR_EL2_TIDCP | HCR_EL2_TLOR;
+}
+
+void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_reset_state reset_state;
+ bool loaded;
+
+ scoped_guard(spinlock, &vcpu->arch.mp_state_lock) {
+ reset_state = vcpu->arch.reset_state;
+ vcpu->arch.reset_state.reset = false;
+ }
+
+ /*
+ * Disable preemption around the vcpu reset as we might otherwise race with
+ * preempt notifiers which call stiasrm/lasrm from put/load
+ */
+ preempt_disable();
+
+ /* The reset must run with an unloaded save area */
+ loaded = vcpu_is_loaded(vcpu);
+ if (loaded)
+ vcpu_put(vcpu);
+
+ kvm_reset_vcpu_core(vcpu);
+
+ /* Reset special registers */
+ vcpu_reset_hcr(vcpu);
+
+ if (reset_state.reset) {
+ *vcpu_pc(vcpu) = reset_state.pc;
+ vcpu_clear_flag(vcpu, PENDING_EXCEPTION);
+ vcpu_clear_flag(vcpu, EXCEPT_MASK);
+ vcpu_clear_flag(vcpu, INCREMENT_PC);
+ vcpu_set_reg(vcpu, 0, reset_state.r0);
+ }
+
+ /* Load new vx-regs into HW if they are currently loaded */
+ if (current->thread.kfpu_flags)
+ load_vx_regs(vcpu->arch.ctxt.vregs);
+
+ if (loaded)
+ vcpu_load(vcpu);
+
+ preempt_enable();
+}
+
+int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu, int feature)
+{
+ return -EINVAL;
+}
diff --git a/arch/s390/kvm/arm64/trace.h b/arch/s390/kvm/arm64/trace.h
index 3a5dcd039c13..1e3cb6108196 100644
--- a/arch/s390/kvm/arm64/trace.h
+++ b/arch/s390/kvm/arm64/trace.h
@@ -5,7 +5,7 @@
#include <linux/tracepoint.h>
#undef TRACE_SYSTEM
-#define TRACE_SYSTEM kvm
+#define TRACE_SYSTEM kvm_arm64
#endif /* KVM_ARM64_TRACE_KVM_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 26/29] KVM: s390: arm64: Implement vCPU IOCTLs
2026-09-18 13:31 ` [PATCH v8 26/29] KVM: s390: arm64: Implement vCPU IOCTLs Steffen Eiden
@ 2026-09-18 17:45 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 17:45 UTC (permalink / raw)
To: Steffen Eiden
Cc: Heiko Carstens, kvmarm, Christian Borntraeger, Vasily Gorbik,
linux-s390, kvm, Marc Zyngier, Alexander Gordeev, Oliver Upton
Thank you for your contribution! Sashiko AI review found 9 potential issue(s) to consider:
- [Critical] kvm: guest memory corruption due to missing TLB flush on KVM_REQ_TLB_FLUSH
- [High] kvm: host-side hang due to sleepable operation inside SRCU read lock
- [High] kvm: missed IPIs and vCPU requests due to unprotected IN_GUEST_MODE transition
- [High] kvm: silent state corruption due to missing vcpu_load/put in ioctl dispatcher
- [High] kvm: ABBA deadlock via redundant vcpu_load() in kvm_arch_vcpu_ioctl_run
- [High] kvm: sleeping in atomic context in kvm_reset_vcpu()
- [High] kvm: Use-After-Free risk via enabled IRQs inside RCU Extended Quiescent State
- [Medium] kvm: host-userspace DoS via WARN_ONCE on SAE validity intercept
- [Medium] kvm: information leak via uninitialized KVM_EXIT_FAIL_ENTRY fields
--
commit ca6265bd830c0d19959272a1e3c2c5ff1c794f65
Author: Steffen Eiden <seiden@linux.ibm.com>
Subject: KVM: s390: arm64: Implement vCPU IOCTLs
Implement all required vCPU (arch) IOCTLs.
> diff --git a/arch/s390/kvm/arm64/arm.c b/arch/s390/kvm/arm64/arm.c
> --- a/arch/s390/kvm/arm64/arm.c
> +++ b/arch/s390/kvm/arm64/arm.c
[ ... ]
> +static int check_vcpu_requests(struct kvm_vcpu *vcpu)
> +{
> + if (kvm_request_pending(vcpu)) {
> + if (kvm_check_request(KVM_REQ_VCPU_RESET, vcpu))
> + kvm_reset_vcpu(vcpu);
> + /*
> + * Clear IRQ_PENDING requests that were made to guarantee
> + * that a VCPU sees new virtual interrupts.
> + */
> + kvm_check_request(KVM_REQ_IRQ_PENDING, vcpu);
> + kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu);
[Severity: Critical]
This clears the KVM_REQ_TLB_FLUSH bit, but is the actual hardware TLB flush
instruction or gmap_tlb_flush() missing here? Could this allow the guest to
continue accessing physical memory using stale page table entries?
> + }
> +
> + return 1;
> +}
[ ... ]
> +static void arm_vcpu_run(struct kvm_vcpu *vcpu)
> +{
> + struct kvm_sae_block *sae_block = &vcpu->arch.sae_block;
> +
> + adjust_pc(vcpu);
> +
> + local_irq_disable();
> + guest_timing_enter_irqoff();
> + guest_state_enter_irqoff();
> + local_irq_enable();
> +
> + sae64a(sae_block);
[Severity: High]
Are host interrupts being explicitly enabled right after
guest_state_enter_irqoff() transitions context tracking into an RCU Extended
Quiescent State? If a host interrupt fires here, could its handler execute
while RCU is suspended, risking a Use-After-Free?
> +
> + local_irq_disable();
> + guest_state_exit_irqoff();
> + guest_timing_exit_irqoff();
> + local_irq_enable();
> +}
[ ... ]
> +int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
> +{
> + DECLARE_KERNEL_FPU_ONSTACK32(fpu_save);
> + struct kvm_run *kvm_run = vcpu->run;
> + int ret;
> +
> + if (kvm_run->exit_reason == KVM_EXIT_MMIO) {
> + ret = kvm_handle_mmio_return(vcpu);
> + if (ret <= 0)
> + return ret;
> + }
> +
> + vcpu_load(vcpu);
[Severity: High]
Doesn't the generic KVM core code already acquire vcpu->mutex via
vcpu_load() before calling kvm_arch_vcpu_ioctl_run()? Could calling
vcpu_load() again here cause an immediate self-deadlock on vcpu->mutex?
> +
> + kernel_fpu_begin(&fpu_save, KERNEL_FPC | KERNEL_VXR);
> + load_vx_regs((vcpu->arch.ctxt.vregs));
[ ... ]
> + might_fault();
> +
> + kvm_vcpu_srcu_read_lock(vcpu);
> +
> + ret = 1;
> + while (ret > 0) {
> +
> + ret = kvm_xfer_to_guest_mode_handle_work(vcpu);
[Severity: High]
Does kvm_xfer_to_guest_mode_handle_work() perform sleepable operations
(like processing TIF_NEED_RESCHED or signals) while the SRCU read lock is
held? Might this stall the SRCU grace period indefinitely and hang the host
during VM operations like memslot updates?
> + if (!ret)
> + ret = 1;
> +
> + if (ret > 0)
> + ret = check_vcpu_requests(vcpu);
> +
> + if (ret <= 0)
> + break;
> +
> + vcpu->arch.sae_block.icptr = 0;
> +
> + smp_store_mb(vcpu->mode, IN_GUEST_MODE);
> +
> + if (kvm_request_pending(vcpu)) {
> + vcpu->mode = OUTSIDE_GUEST_MODE;
> + continue;
> + }
[Severity: High]
Is the transition to IN_GUEST_MODE and the check for pending requests
happening before local interrupts are disabled? If a concurrent vCPU kick
occurs immediately after the check, could the host handle the IPI and the
vCPU enter the guest without re-checking requests, thereby missing the kick?
> +
> + kvm_vcpu_srcu_read_unlock(vcpu);
> +
> + arm_vcpu_run(vcpu);
[ ... ]
> +long kvm_arch_vcpu_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
> +{
> + struct kvm_vcpu *vcpu = filp->private_data;
> + void __user *argp = (void __user *)arg;
> + struct kvm_device_attr attr;
> + int ret;
> +
> + switch (ioctl) {
> + case KVM_ARM_VCPU_INIT: {
> + struct kvm_vcpu_init init;
[Severity: High]
Do KVM_ARM_VCPU_INIT and KVM_SET_ONE_REG modify architectural state without
calling vcpu_load() and vcpu_put()? Could this lead to physical CPU state
corruption or leaked preempt notifiers if the vCPU is not properly bound to
the physical CPU during these modifications?
> +
> + ret = -EFAULT;
> + if (copy_from_user(&init, argp, sizeof(init)))
> + break;
[ ... ]
> diff --git a/arch/s390/kvm/arm64/handle_exit.c b/arch/s390/kvm/arm64/handle_exit.c
> --- a/arch/s390/kvm/arm64/handle_exit.c
> +++ b/arch/s390/kvm/arm64/handle_exit.c
[ ... ]
> +int handle_exit(struct kvm_vcpu *vcpu)
> +{
> + u8 icptr = vcpu->arch.sae_block.icptr;
> + int ret = 1;
> +
> + switch (icptr) {
> + case SAE_ICPTR_SPURIOUS:
> + break;
> + case SAE_ICPTR_VALIDITY:
> + WARN_ONCE(true, "SAE: validity intercept. vir: 0x%04x",
> + vcpu->arch.sae_block.vir);
[Severity: Medium]
Could this WARN_ONCE be triggered by an unprivileged host-userspace process
providing malformed VCPU state via ioctls? KVM guidelines generally forbid
userspace-reachable warnings since they can act as a denial of service if
panic_on_warn is set. Should this return an error instead?
> + vcpu->run->exit_reason = KVM_EXIT_FAIL_ENTRY;
> + ret = 0;
> + break;
[Severity: Medium]
Does this leave the hardware_entry_failure_reason and cpu fields of
vcpu->run->fail_entry uninitialized before returning to userspace? Could
this potentially leak stale kernel memory from the shared kvm_run union?
> + case SAE_ICPTR_GUEST_ADDRESS_SIZE:
[ ... ]
> diff --git a/arch/s390/kvm/arm64/reset.c b/arch/s390/kvm/arm64/reset.c
> --- a/arch/s390/kvm/arm64/reset.c
> +++ b/arch/s390/kvm/arm64/reset.c
[ ... ]
> +void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
> +{
> + struct vcpu_reset_state reset_state;
> + bool loaded;
> +
> + scoped_guard(spinlock, &vcpu->arch.mp_state_lock) {
> + reset_state = vcpu->arch.reset_state;
> + vcpu->arch.reset_state.reset = false;
> + }
> +
> + /*
> + * Disable preemption around the vcpu reset as we might otherwise race with
> + * preempt notifiers which call stiasrm/lasrm from put/load
> + */
> + preempt_disable();
> +
> + /* The reset must run with an unloaded save area */
> + loaded = vcpu_is_loaded(vcpu);
> + if (loaded)
> + vcpu_put(vcpu);
[Severity: High]
Are we calling vcpu_put() and vcpu_load() (which acquire the sleepable
vcpu->mutex) while inside a preempt_disable() block? Could this cause a
BUG: sleeping function called from invalid context panic during a vCPU
reset?
> +
> + kvm_reset_vcpu_core(vcpu);
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=26
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 27/29] KVM: s390: arm64: Implement basic page fault handler
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (25 preceding siblings ...)
2026-09-18 13:31 ` [PATCH v8 26/29] KVM: s390: arm64: Implement vCPU IOCTLs Steffen Eiden
@ 2026-09-18 13:31 ` Steffen Eiden
2026-09-18 17:55 ` sashiko-bot
2026-09-18 13:31 ` [PATCH v8 28/29] KVM: s390: arm64: Integrate arm on s390 Steffen Eiden
` (2 subsequent siblings)
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:31 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Add host functionality to page in guest memory. If the guest does
something unexpected or illegal exit to userspace abort guest execution.
This behaviour will be changed to guest error injects once all sysregs
are accessible for the host.
Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/kvm/arm64/handle_exit.c | 2 +
arch/s390/kvm/arm64/mmio.c | 15 +++
arch/s390/kvm/arm64/mmu.c | 180 ++++++++++++++++++++++++++++++
arch/s390/kvm/arm64/trace.h | 50 +++++++++
4 files changed, 247 insertions(+)
create mode 100644 arch/s390/kvm/arm64/mmio.c
create mode 100644 arch/s390/kvm/arm64/mmu.c
diff --git a/arch/s390/kvm/arm64/handle_exit.c b/arch/s390/kvm/arm64/handle_exit.c
index 38a2cc4ee4e1..804ecc1d79ee 100644
--- a/arch/s390/kvm/arm64/handle_exit.c
+++ b/arch/s390/kvm/arm64/handle_exit.c
@@ -63,6 +63,8 @@ static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu)
static exit_handle_fn arm_exit_handlers[] = {
[0 ... ESR_ELx_EC_MAX] = kvm_handle_unknown_ec,
[ESR_ELx_EC_HVC64] = handle_hvc,
+ [ESR_ELx_EC_IABT_LOW] = kvm_handle_guest_abort,
+ [ESR_ELx_EC_DABT_LOW] = kvm_handle_guest_abort,
};
static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
diff --git a/arch/s390/kvm/arm64/mmio.c b/arch/s390/kvm/arm64/mmio.c
new file mode 100644
index 000000000000..908a6b43ddf7
--- /dev/null
+++ b/arch/s390/kvm/arm64/mmio.c
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/kvm_host.h>
+#include <linux/bitfield.h>
+
+#include <trace/events/kvm.h>
+
+#include <arm64/kvm_emulate.h>
+#include <arm64/sysreg.h>
+
+#include "trace.h"
+
+#define __INCL_GEN_ARM_FILE
+#include "generated/mmio.inc"
+#undef __INCL_GEN_ARM_FILE
diff --git a/arch/s390/kvm/arm64/mmu.c b/arch/s390/kvm/arm64/mmu.c
new file mode 100644
index 000000000000..e561fee9ca97
--- /dev/null
+++ b/arch/s390/kvm/arm64/mmu.c
@@ -0,0 +1,180 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/kvm_host.h>
+
+#include <arm64/kvm_emulate.h>
+
+#include <faultin.h>
+
+#include "trace.h"
+
+static inline bool kvm_s390_cur_gmap_fault_is_write(struct kvm_vcpu *vcpu)
+{
+ return (vcpu->arch.sae_block.hai.pic & PGM_INT_CODE_MASK) == PGM_PROTECTION ||
+ vcpu->arch.sae_block.hai.teid.fsi == TEID_FSI_STORE;
+}
+
+/*
+ * user_mem_abort() - handle a dat fault for the gmap of a vcpu
+ *
+ * Return: 0 on success, < 0 in case of error.
+ * Context: The mm lock must not be held before calling. May sleep.
+ */
+static int user_mem_abort(struct kvm_vcpu *vcpu, gpa_t fault_ipa,
+ struct kvm_memory_slot *slot, hva_t hva)
+{
+ struct guest_fault f = { };
+ int ret;
+
+ if (kvm_s390_cur_gmap_fault_is_write(vcpu))
+ f.write_attempt = FOLL_WRITE;
+ f.gfn = gpa_to_gfn(fault_ipa);
+
+ ret = kvm_s390_faultin_gfn(vcpu, NULL, &f);
+ if (ret <= 0)
+ return ret;
+ if (ret == PGM_ADDRESSING)
+ /*
+ * Without the relevant sysregs we cannot do anything for now.
+ * Go back to userspace with an error. TODO sysreg handling
+ */
+ return -ENOEXEC;
+ KVM_BUG_ON(ret, vcpu->kvm);
+ return -EINVAL;
+}
+
+static int kvm_handle_pic(struct kvm_vcpu *vcpu, bool *translation)
+{
+ switch (kvm_vcpu_fault_pic(vcpu)) {
+ /* expected cases: */
+ case PGM_ASCE_TYPE:
+ case PGM_REGION_FIRST_TRANS:
+ case PGM_REGION_SECOND_TRANS:
+ case PGM_REGION_THIRD_TRANS:
+ case PGM_SEGMENT_TRANSLATION:
+ case PGM_PAGE_TRANSLATION:
+ *translation = true;
+ break;
+ case PGM_PROTECTION:
+ break;
+ /* unexpected cases: */
+ case 0:
+ KVM_BUG(1, vcpu->kvm, "On MMU fault path but no fault occurred");
+ return -EFAULT;
+ default:
+ KVM_BUG(1, vcpu->kvm, "Unexpected program interrupt 0x%x, TEID 0x%016lx",
+ vcpu->arch.sae_block.hai.pic, vcpu->arch.sae_block.hai.teid.val);
+ send_sig(SIGSEGV, current, 0);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
+{
+ struct kvm_memory_slot *memslot;
+ bool translation = false;
+ phys_addr_t fault_ipa;
+ unsigned long hva;
+ bool write_fault;
+ bool guest_size_err;
+ bool writable;
+ bool is_iabt;
+ int ret;
+ gfn_t gfn;
+ int idx;
+
+ fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
+ is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
+ guest_size_err = vcpu->arch.sae_block.icptr == SAE_ICPTR_GUEST_ADDRESS_SIZE;
+
+ if (guest_size_err) {
+ translation = true;
+ } else {
+ ret = kvm_handle_pic(vcpu, &translation);
+ if (ret)
+ return ret;
+ }
+
+ if (translation) {
+ /*
+ * For both cases:
+ * Without the relevant sysregs we cannot do anything for now.
+ * Go back to userspace with an error. TODO sysreg handling
+ */
+ if (fault_ipa >= BIT_ULL(get_kvm_ipa_limit()))
+ return -ENOEXEC;
+
+ if (fault_ipa >= vcpu->kvm->arch.guest_phys_size)
+ return -ENOEXEC;
+ }
+
+ trace_kvm_guest_fault(*vcpu_pc(vcpu), kvm_vcpu_get_esr(vcpu),
+ kvm_vcpu_get_hfar(vcpu), fault_ipa);
+
+ idx = srcu_read_lock(&vcpu->kvm->srcu);
+
+ gfn = fault_ipa >> PAGE_SHIFT;
+
+ memslot = gfn_to_memslot(vcpu->kvm, gfn);
+ hva = gfn_to_hva_memslot_prot(memslot, gfn, &writable);
+ write_fault = kvm_is_write_fault(vcpu);
+ if (kvm_is_error_hva(hva) || (write_fault && !writable)) {
+ ret = -ENOEXEC;
+ /*
+ * The guest has put either its instructions or its page-tables
+ * somewhere it shouldn't have. Userspace won't be able to do
+ * anything about this (there's no syndrome for a start).
+ *
+ * Without the relevant sysregs we cannot do anything for now.
+ * Go back to userspace with an error. TODO sysreg handling
+ */
+ if (is_iabt)
+ goto out_unlock;
+
+ if (kvm_vcpu_abt_iss1tw(vcpu)) {
+ /*
+ * Without the relevant sysregs we cannot do anything for now.
+ * Go back to userspace with an error. TODO sysreg handling
+ */
+ goto out_unlock;
+ }
+
+ /*
+ * Check for a cache maintenance operation. Assume the guest is
+ * cautious and skip instruction
+ */
+ if (kvm_is_error_hva(hva) && kvm_vcpu_dabt_is_cm(vcpu)) {
+ kvm_incr_pc(vcpu);
+ ret = 1;
+ goto out_unlock;
+ }
+
+ /*
+ * The IPA is reported as [MAX:12], so we need to
+ * complement it with the bottom 12 bits from the
+ * faulting VA. This is always 12 bits, irrespective
+ * of the page size.
+ */
+ fault_ipa |= kvm_vcpu_get_hfar(vcpu) & ((1 << 12) - 1);
+ ret = io_mem_abort(vcpu, fault_ipa);
+ goto out_unlock;
+ }
+
+ /* Userspace should not be able to register out-of-bounds IPAs */
+ VM_BUG_ON(fault_ipa >= vcpu->kvm->arch.guest_phys_size);
+ /*
+ * Proper guest size faults have been injected.
+ * In theory it's fine to have device memory higher than MSL,
+ * even if not currently possible, but that would have been handled above.
+ * So if we get here with a guest size intercept, we have a bug somewhere.
+ */
+ VM_BUG_ON(guest_size_err);
+
+ ret = user_mem_abort(vcpu, fault_ipa, memslot, hva);
+ if (!ret)
+ ret = 1;
+out_unlock:
+ srcu_read_unlock(&vcpu->kvm->srcu, idx);
+ return ret;
+}
diff --git a/arch/s390/kvm/arm64/trace.h b/arch/s390/kvm/arm64/trace.h
index 1e3cb6108196..6d4f4af9eee6 100644
--- a/arch/s390/kvm/arm64/trace.h
+++ b/arch/s390/kvm/arm64/trace.h
@@ -7,6 +7,56 @@
#undef TRACE_SYSTEM
#define TRACE_SYSTEM kvm_arm64
+TRACE_EVENT(kvm_mmio_nisv,
+ TP_PROTO(unsigned long vcpu_pc, unsigned long esr,
+ unsigned long far, unsigned long ipa),
+ TP_ARGS(vcpu_pc, esr, far, ipa),
+
+ TP_STRUCT__entry(
+ __field( unsigned long, vcpu_pc )
+ __field( unsigned long, esr )
+ __field( unsigned long, far )
+ __field( unsigned long, ipa )
+ ),
+
+ TP_fast_assign(
+ __entry->vcpu_pc = vcpu_pc;
+ __entry->esr = esr;
+ __entry->far = far;
+ __entry->ipa = ipa;
+ ),
+
+ TP_printk("ipa %#016lx, esr %#016lx, far %#016lx, pc %#016lx",
+ __entry->ipa, __entry->esr,
+ __entry->far, __entry->vcpu_pc)
+);
+
+TRACE_EVENT(kvm_guest_fault,
+ TP_PROTO(unsigned long vcpu_pc, unsigned long hsr,
+ unsigned long hxfar,
+ unsigned long long ipa),
+ TP_ARGS(vcpu_pc, hsr, hxfar, ipa),
+
+ TP_STRUCT__entry(
+ __field( unsigned long, vcpu_pc )
+ __field( unsigned long, hsr )
+ __field( unsigned long, hxfar )
+ __field( unsigned long long, ipa )
+ ),
+
+ TP_fast_assign(
+ __entry->vcpu_pc = vcpu_pc;
+ __entry->hsr = hsr;
+ __entry->hxfar = hxfar;
+ __entry->ipa = ipa;
+ ),
+
+ TP_printk("ipa %#llx, hsr %#08lx, hxfar %#08lx, pc %#016lx",
+ __entry->ipa, __entry->hsr,
+ __entry->hxfar, __entry->vcpu_pc)
+);
+
+
#endif /* KVM_ARM64_TRACE_KVM_H */
#undef TRACE_INCLUDE_PATH
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 27/29] KVM: s390: arm64: Implement basic page fault handler
2026-09-18 13:31 ` [PATCH v8 27/29] KVM: s390: arm64: Implement basic page fault handler Steffen Eiden
@ 2026-09-18 17:55 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 17:55 UTC (permalink / raw)
To: Steffen Eiden
Cc: Vasily Gorbik, Marc Zyngier, linux-s390, kvmarm, Oliver Upton,
kvm, Alexander Gordeev, Christian Borntraeger, Heiko Carstens
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] kvm: arm64: Guest-triggerable KVM_BUG in kvm_handle_pic() causes host DoS
--
commit 3f769665af940a4bd5628fcd7a471a6e0e436b79
Author: Steffen Eiden <seiden@linux.ibm.com>
KVM: s390: arm64: Implement basic page fault handler
This commit adds host functionality to page in guest memory. If the guest
does something unexpected or illegal, the host aborts guest execution and
returns to userspace.
> --- /dev/null
> +++ b/arch/s390/kvm/arm64/mmu.c
[ ... ]
> +static int kvm_handle_pic(struct kvm_vcpu *vcpu, bool *translation)
> +{
> + switch (kvm_vcpu_fault_pic(vcpu)) {
> + /* expected cases: */
> + case PGM_ASCE_TYPE:
> + case PGM_REGION_FIRST_TRANS:
> + case PGM_REGION_SECOND_TRANS:
> + case PGM_REGION_THIRD_TRANS:
> + case PGM_SEGMENT_TRANSLATION:
> + case PGM_PAGE_TRANSLATION:
> + *translation = true;
> + break;
> + case PGM_PROTECTION:
> + break;
> + /* unexpected cases: */
> + case 0:
> + KVM_BUG(1, vcpu->kvm, "On MMU fault path but no fault occurred");
[Severity: High]
Does this allow a guest to trigger a host denial of service?
If the hardware reports an abort without an underlying s390 PIC, such as
non-translation traps like cache maintenance, an untrusted guest could reach
this path.
KVM_BUG triggers a host WARN_ONCE, which panics the host kernel in
environments configured with panic_on_warn. KVM architectural guidelines
forbid assertions that are reachable by untrusted guest inputs.
> + return -EFAULT;
> + default:
> + KVM_BUG(1, vcpu->kvm, "Unexpected program interrupt 0x%x, TEID 0x%016lx",
> + vcpu->arch.sae_block.hai.pic, vcpu->arch.sae_block.hai.teid.val);
[Severity: High]
Could a guest also trigger a host panic by hitting this default case?
A malicious or fuzzing guest might execute instructions that generate an
unexpected ARM abort syndrome or access memory topologies that result in an
unhandled PIC, such as PGM_ADDRESSING.
Similar to the case 0 above, using KVM_BUG here allows an untrusted guest
to reach a warning, potentially crashing the host.
> + send_sig(SIGSEGV, current, 0);
> + return -EFAULT;
> + }
> +
> + return 0;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=27
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 28/29] KVM: s390: arm64: Integrate arm on s390
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (26 preceding siblings ...)
2026-09-18 13:31 ` [PATCH v8 27/29] KVM: s390: arm64: Implement basic page fault handler Steffen Eiden
@ 2026-09-18 13:31 ` Steffen Eiden
2026-09-18 18:11 ` sashiko-bot
2026-09-18 13:31 ` [PATCH v8 29/29] KVM: s390: Enforce no unexpected external symbol exports in s390 KVM Steffen Eiden
2026-09-18 13:38 ` [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:31 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Add all Kbuild/Makefile configurations to build a second KVM module on
s390 implementing the arm64-KVM API. To prevent symbol conflicts with
kvm-s390 all internal symbols in kvm-arm64 are mangled if compiled as
built-in. The new module ins named kvm-arm64.
As in this case the build does not go through the normal build process
the module parameter handling would be messed up. By forcing
KBUILD_MODNAME to kvm-arm64 all parameters are at the same location and
not at object/basename of the object file where the parameter is
introduced.
Co-developed-by: Andreas Grapentin <gra@linux.ibm.com>
Signed-off-by: Andreas Grapentin <gra@linux.ibm.com>
Co-developed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Co-developed-by: Gautam Gala <ggala@linux.ibm.com>
Signed-off-by: Gautam Gala <ggala@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/include/asm/Kbuild | 1 +
arch/s390/kvm/Kconfig | 28 +++++++----
arch/s390/kvm/Makefile | 1 +
arch/s390/kvm/arm64/Makefile | 93 ++++++++++++++++++++++++++++++++++++
arch/s390/kvm/arm64/arm.c | 2 +-
5 files changed, 115 insertions(+), 10 deletions(-)
create mode 100644 arch/s390/kvm/arm64/Makefile
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 0c1fc47c3ba0..9409970a2123 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += asm-offsets.h
generic-y += mcs_spinlock.h
generic-y += mmzone.h
generic-y += ring_buffer.h
+
diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
index a6ff2e5aa19b..4e060185c2fb 100644
--- a/arch/s390/kvm/Kconfig
+++ b/arch/s390/kvm/Kconfig
@@ -19,6 +19,7 @@ if VIRTUALIZATION
config KVM
def_tristate y
prompt "Kernel-based Virtual Machine (KVM) support"
+ depends on HAS_IOMEM
select HAVE_KVM_CPU_RELAX_INTERCEPT
select KVM_ASYNC_PF
select KVM_ASYNC_PF_SYNC
@@ -28,16 +29,25 @@ config KVM
select KVM_VFIO
select VIRT_XFER_TO_GUEST_WORK
select KVM_MMU_LOCKLESS_AGING
+ select GUEST_PERF_EVENTS if PERF_EVENTS
+ select SCHED_INFO
help
- Support hosting paravirtualized guest machines using the SIE
- virtualization capability on the mainframe. This should work
- on any 64bit machine.
-
- This module provides access to the hardware capabilities through
- a character device node named /dev/kvm.
-
- To compile this as a module, choose M here: the module
- will be called kvm.
+ Enable support for hosting virtualized, hardware-accelerated
+ virtual machines via two modules: kvm and kvm_arm64.
+
+ The kvm module provides access to host hardware-accelerated s390
+ guests using the Start Interpretive Execution (SIE) instruction via a
+ character device node named /dev/kvm. This requires a 64-bit machine
+ (hardware model).
+
+ The kvm_arm64 module provides access to host hardware-accelerated
+ arm64 guests using the Start ARM Execution (SAE) instruction via a
+ character device node named /dev/kvm_arm64. This requires hardware
+ models that support the Arm execution facility (AEF).
+
+ To compile this driver as a module, choose M here. The module will be
+ called kvm for the SIE acceleration and kvm_arm64 for the SAE
+ acceleration.
If unsure, say N.
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
index a4e3875b5bdd..380db443a0e9 100644
--- a/arch/s390/kvm/Makefile
+++ b/arch/s390/kvm/Makefile
@@ -4,3 +4,4 @@
# Copyright IBM Corp. 2008
obj-$(CONFIG_KVM) += s390/
+obj-$(CONFIG_KVM) += arm64/
diff --git a/arch/s390/kvm/arm64/Makefile b/arch/s390/kvm/arm64/Makefile
new file mode 100644
index 000000000000..bd78d64939d1
--- /dev/null
+++ b/arch/s390/kvm/arm64/Makefile
@@ -0,0 +1,93 @@
+# SPDX-License-Identifier: GPL-2.0
+
+KVM := ../../../../virt/kvm
+KVM_DEV_NAME = kvm_arm64
+KVM_DEV_MINOR = MISC_DYNAMIC_MINOR
+include $(srctree)/virt/kvm/Makefile.kvm
+include $(srctree)/arch/s390/kvm/gmap/Makefile
+include $(src)/Makefile.gen
+
+ccflags-y += -I $(src) -I $(objtree)/$(obj) -I$(srctree)/arch/s390/kvm/gmap -DKVM_S390_ARM64
+
+kvm-arm64-obj := \
+ arm.o \
+ guest.o \
+ handle_exit.o \
+ inject_fault.o \
+ mmio.o \
+ mmu.o \
+ reset.o \
+
+kvm-arm64-obj += $(patsubst %.o,%-arm64.o,$(kvm-y))
+kvm-arm64-obj += $(patsubst %.o,%-arm64.o,$(gmap-y))
+
+targets += $(kvm-arm64-obj)
+
+$(obj)/%-arm64.o: $(src)/%.c FORCE
+ @mkdir -p $(dir $@)
+ $(call if_changed_rule,cc_o_c)
+
+ifeq ($(CONFIG_KVM),m)
+
+kvm-arm64-y = $(kvm-arm64-obj)
+
+else ifeq ($(CONFIG_KVM),y)
+
+KVM_ARM64_GEN_DIR := $(objtree)/arch/${SRCARCH}/include/generated/asm
+KVM_ARM64_MODNAME_H := $(KVM_ARM64_GEN_DIR)/kvm_arm64_modname.h
+ccflags-y += -include $(KVM_ARM64_MODNAME_H)
+
+targets += $(KVM_ARM64_MODNAME_H)
+
+quiet_cmd_kvm_arm64_modname_h = GEN $@
+ cmd_kvm_arm64_modname_h = { \
+ echo '/* Automatically generated; do not edit. */'; \
+ echo '\#ifndef _KVM_ARM64_MODNAME_H'; \
+ echo '\#define _KVM_ARM64_MODNAME_H'; \
+ echo '\#undef KBUILD_MODNAME'; \
+ echo '\#define KBUILD_MODNAME "kvm_arm64"'; \
+ echo '\#endif /* _KVM_ARM64_MODNAME_H */'; \
+ } > $@
+
+$(addprefix $(obj)/,$(kvm-arm64-obj)): $(KVM_ARM64_MODNAME_H)
+
+$(KVM_ARM64_MODNAME_H):
+ @mkdir -p $(KVM_ARM64_GEN_DIR)
+ $(call cmd,kvm_arm64_modname_h)
+
+prereq-o-cmd = $(foreach o, $(filter %.o, $^), $(dir $(o)).$(notdir $(o)).cmd)
+cmd_gen_symversions_o = \
+ grep --no-filename "^\#SYMVER" $(prereq-o-cmd) >> $(dot-target).cmd || true
+
+define rule_ld_o_o
+ $(call cmd_and_savecmd,ld)
+ $(call cmd,gen_symversions_o)
+endef
+
+LDFLAGS_kvm-unnamespaced.o := -r
+$(obj)/kvm-unnamespaced.o: $(addprefix $(obj)/,$(kvm-arm64-obj)) FORCE
+ $(call if_changed_rule,ld_o_o)
+
+quiet_cmd_nm_filter = NMFLTR $@
+ cmd_nm_filter = $(NM) --defined-only --format=just-symbols $< | sort -u > $@
+
+$(obj)/kvm_symbol_list: $(obj)/kvm-unnamespaced.o FORCE
+ $(call if_changed,nm_filter)
+
+define rule_oc_o_o
+ $(call cmd_and_savecmd,objcopy)
+ $(call cmd,gen_objtooldep)
+ $(call cmd,gen_symversions_o)
+endef
+
+OBJCOPYFLAGS_kvm-namespaced.o := -O $(LD_BFD) --localize-symbols=$(obj)/kvm_symbol_list
+$(obj)/kvm-namespaced.o: $(obj)/kvm-unnamespaced.o $(obj)/kvm_symbol_list FORCE
+ $(call if_changed_rule,oc_o_o)
+
+kvm-arm64-y = kvm-namespaced.o
+
+targets += kvm-unnamespaced.o kvm_symbol_list kvm-namespaced.o
+
+endif
+
+obj-$(CONFIG_KVM) += kvm-arm64.o
diff --git a/arch/s390/kvm/arm64/arm.c b/arch/s390/kvm/arm64/arm.c
index bb3e7fa8cad5..43e40fc78501 100644
--- a/arch/s390/kvm/arm64/arm.c
+++ b/arch/s390/kvm/arm64/arm.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
-#define KMSG_COMPONENT "kvm-s390-arm64"
+#define KMSG_COMPONENT "kvm_arm64"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#include <linux/miscdevice.h>
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 28/29] KVM: s390: arm64: Integrate arm on s390
2026-09-18 13:31 ` [PATCH v8 28/29] KVM: s390: arm64: Integrate arm on s390 Steffen Eiden
@ 2026-09-18 18:11 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 18:11 UTC (permalink / raw)
To: Steffen Eiden
Cc: Christian Borntraeger, linux-s390, Oliver Upton, Heiko Carstens,
Marc Zyngier, kvm, Alexander Gordeev, Vasily Gorbik, kvmarm
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] kconfig: HAS_IOMEM dependency unintentionally breaks native s390 KVM
- [Low] kbuild: duplicate symbol exports and tracepoint conflicts in kvm-arm64
--
commit 884410e372d8436737ad12a739eafeab45f8d49c
Author: Steffen Eiden <seiden@linux.ibm.com>
KVM: s390: arm64: Integrate arm on s390
This commit adds the Kbuild and Makefile configurations necessary to build a
second KVM module on s390 that implements the arm64-KVM API. It introduces
symbol mangling for built-in compilation to prevent conflicts with kvm-s390,
and it forces the KBUILD_MODNAME to kvm-arm64 to handle module parameters
correctly.
> diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig
> index a6ff2e5aa19b7..4e060185c2fb3 100644
> --- a/arch/s390/kvm/Kconfig
> +++ b/arch/s390/kvm/Kconfig
> @@ -19,6 +19,7 @@ if VIRTUALIZATION
> config KVM
> def_tristate y
> prompt "Kernel-based Virtual Machine (KVM) support"
> + depends on HAS_IOMEM
[Severity: High]
Could this new dependency on HAS_IOMEM unintentionally break backwards
compatibility for native s390 KVM?
On the s390 architecture, HAS_IOMEM is defined strictly as PCI support.
If a user disables PCI, HAS_IOMEM evaluates to false, making the entire KVM
subsystem unselectable.
Native s390 KVM does not actually require PCI support to function properly.
> select HAVE_KVM_CPU_RELAX_INTERCEPT
> select KVM_ASYNC_PF
[ ... ]
> diff --git a/arch/s390/kvm/arm64/Makefile b/arch/s390/kvm/arm64/Makefile
> new file mode 100644
> index 0000000000000..bd78d64939d1a
> --- /dev/null
> +++ b/arch/s390/kvm/arm64/Makefile
> @@ -0,0 +1,93 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +KVM := ../../../../virt/kvm
[ ... ]
> +kvm-arm64-obj := \
> + arm.o \
> + guest.o \
> + handle_exit.o \
> + inject_fault.o \
> + mmio.o \
> + mmu.o \
> + reset.o \
> +
> +kvm-arm64-obj += $(patsubst %.o,%-arm64.o,$(kvm-y))
[Severity: Low]
Will this pattern force generic kvm files, which contain exported macros and
tracepoint definitions, to be compiled a second time?
This can lead to the kernel build failing during the modpost phase due to
duplicate exported symbols.
> +kvm-arm64-obj += $(patsubst %.o,%-arm64.o,$(gmap-y))
> +
> +targets += $(kvm-arm64-obj)
> +
> +$(obj)/%-arm64.o: $(src)/%.c FORCE
> + @mkdir -p $(dir $@)
> + $(call if_changed_rule,cc_o_c)
> +
> +ifeq ($(CONFIG_KVM),m)
> +
> +kvm-arm64-y = $(kvm-arm64-obj)
[Severity: Low]
Is it intentional that no symbol localization is attempted here for the
module case?
This seems to guarantee a module namespace conflict. Both kvm.ko and
kvm-arm64.ko will globally export the same tracepoints.
> +
> +else ifeq ($(CONFIG_KVM),y)
[ ... ]
> +define rule_oc_o_o
> + $(call cmd_and_savecmd,objcopy)
> + $(call cmd,gen_objtooldep)
> + $(call cmd,gen_symversions_o)
> +endef
> +
> +OBJCOPYFLAGS_kvm-namespaced.o := -O $(LD_BFD) --localize-symbols=$(obj)/kvm_symbol_list
> +$(obj)/kvm-namespaced.o: $(obj)/kvm-unnamespaced.o $(obj)/kvm_symbol_list FORCE
> + $(call if_changed_rule,oc_o_o)
[Severity: Low]
Can this objcopy command create a state that modpost will reject when
checking the vmlinux binary?
While this transforms target symbols to local, it preserves the
.export_symbol structures.
Modpost intentionally terminates the build when it encounters local symbols
that have .export_symbol sections.
> +
> +kvm-arm64-y = kvm-namespaced.o
> +
> +targets += kvm-unnamespaced.o kvm_symbol_list kvm-namespaced.o
> +
> +endif
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=28
^ permalink raw reply [flat|nested] 80+ messages in thread
* [PATCH v8 29/29] KVM: s390: Enforce no unexpected external symbol exports in s390 KVM
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (27 preceding siblings ...)
2026-09-18 13:31 ` [PATCH v8 28/29] KVM: s390: arm64: Integrate arm on s390 Steffen Eiden
@ 2026-09-18 13:31 ` Steffen Eiden
2026-09-18 18:19 ` sashiko-bot
2026-09-18 13:38 ` [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
29 siblings, 1 reply; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:31 UTC (permalink / raw)
To: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390
Cc: Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
Add a Makefile check to arch/s390/kvm that fails the build on any
EXPORT_SYMBOL_GPL or EXPORT_SYMBOL not in the allowed list. A symbol
may only use EXPORT_SYMBOL_GPL if it is defined in exactly one of the
two s390 KVM modules (kvm or kvm-arm64). A symbol defined in both
modules could cause a link conflict if built builtin.
While at it remove the unnecessary EXPORT_SYMBOL_GPL from
kvm_s390_pv_is_protected, which has no external callers.
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/kvm/Makefile | 1 +
arch/s390/kvm/arm64/Makefile | 14 ++++++++++++++
arch/s390/kvm/s390/Makefile | 16 ++++++++++++++++
arch/s390/kvm/s390/pv.c | 1 -
4 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/arch/s390/kvm/Makefile b/arch/s390/kvm/Makefile
index 380db443a0e9..0e474335bb78 100644
--- a/arch/s390/kvm/Makefile
+++ b/arch/s390/kvm/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_KVM) += s390/
obj-$(CONFIG_KVM) += arm64/
+
diff --git a/arch/s390/kvm/arm64/Makefile b/arch/s390/kvm/arm64/Makefile
index bd78d64939d1..d84d3be74037 100644
--- a/arch/s390/kvm/arm64/Makefile
+++ b/arch/s390/kvm/arm64/Makefile
@@ -3,6 +3,7 @@
KVM := ../../../../virt/kvm
KVM_DEV_NAME = kvm_arm64
KVM_DEV_MINOR = MISC_DYNAMIC_MINOR
+KVM_CHECK_EXPORT_DIRS ?= $(srctree)/virt/kvm $(srctree)/arch/s390/kvm/gmap $(src)
include $(srctree)/virt/kvm/Makefile.kvm
include $(srctree)/arch/s390/kvm/gmap/Makefile
include $(src)/Makefile.gen
@@ -91,3 +92,16 @@ targets += kvm-unnamespaced.o kvm_symbol_list kvm-namespaced.o
endif
obj-$(CONFIG_KVM) += kvm-arm64.o
+
+# Fail the build if there is unexpected EXPORT_SYMBOL_GPL (or EXPORT_SYMBOL)
+# usage in arm64 KVM code. A symbol may only use EXPORT_SYMBOL_GPL if it is
+# defined in exactly one of the two s390 KVM modules (kvm or kvm_arm64). A
+# symbol defined in both would cause a conflict during linking if builtin is
+# selected. Catch the issue early.
+
+# This "symbol" is not exported by arm on s390 but still in the source code and the
+# export check scans unexpanded source code.
+kvm_exports_allowed := kvm_file_to_kvm_fn
+
+$(eval $(call kvm_check_exports,EXPORT_SYMBOL_GPL))
+$(eval $(call kvm_check_exports,EXPORT_SYMBOL))
diff --git a/arch/s390/kvm/s390/Makefile b/arch/s390/kvm/s390/Makefile
index b91334db90a2..5d6eb45d3037 100644
--- a/arch/s390/kvm/s390/Makefile
+++ b/arch/s390/kvm/s390/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
KVM := ../../../../virt/kvm
+KVM_CHECK_EXPORT_DIRS ?= $(srctree)/virt/kvm $(srctree)/arch/$(ARCH)/kvm/gmap $(src)
include $(srctree)/virt/kvm/Makefile.kvm
include $(srctree)/arch/s390/kvm/gmap/Makefile
@@ -12,3 +13,18 @@ kvm-y += $(gmap-y)
kvm-$(CONFIG_VFIO_PCI_ZDEV_KVM) += pci.o
obj-$(CONFIG_KVM) += kvm.o
+
+# Fail the build if there is unexpected EXPORT_SYMBOL_GPL (or EXPORT_SYMBOL)
+# usage in s390 KVM code. A symbol may only use EXPORT_SYMBOL_GPL if it is
+# defined in exactly one of the two s390 KVM modules (kvm or kvm_arm64). A
+# symbol defined in both would cause a conflict during linking if builtin is
+# selected. Catch the issue early.
+kvm_exports_allowed := kvm_s390_pv_cpu_is_protected \
+ kvm_arch_crypto_set_masks \
+ kvm_arch_crypto_clear_masks \
+ kvm_s390_gisc_register \
+ kvm_s390_gisc_unregister \
+ kvm_file_to_kvm_fn
+
+$(eval $(call kvm_check_exports,EXPORT_SYMBOL_GPL))
+$(eval $(call kvm_check_exports,EXPORT_SYMBOL))
diff --git a/arch/s390/kvm/s390/pv.c b/arch/s390/kvm/s390/pv.c
index b18abd0e29ef..1fec224e4d2b 100644
--- a/arch/s390/kvm/s390/pv.c
+++ b/arch/s390/kvm/s390/pv.c
@@ -29,7 +29,6 @@ bool kvm_s390_pv_is_protected(struct kvm *kvm)
lockdep_assert_held(&kvm->lock);
return !!kvm_s390_pv_get_handle(kvm);
}
-EXPORT_SYMBOL_GPL(kvm_s390_pv_is_protected);
bool kvm_s390_pv_cpu_is_protected(struct kvm_vcpu *vcpu)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 80+ messages in thread* Re: [PATCH v8 29/29] KVM: s390: Enforce no unexpected external symbol exports in s390 KVM
2026-09-18 13:31 ` [PATCH v8 29/29] KVM: s390: Enforce no unexpected external symbol exports in s390 KVM Steffen Eiden
@ 2026-09-18 18:19 ` sashiko-bot
0 siblings, 0 replies; 80+ messages in thread
From: sashiko-bot @ 2026-09-18 18:19 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvmarm, Oliver Upton, kvm, Vasily Gorbik, Christian Borntraeger,
Alexander Gordeev, Heiko Carstens, linux-s390, Marc Zyngier
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Makefile: kvm_check_exports prints false-positive violations in error log
--
commit 539bcae6d5e99f65300c56bf0e306743cc8f639c
Author: Steffen Eiden <seiden@linux.ibm.com>
KVM: s390: Enforce no unexpected external symbol exports in s390 KVM
Add a Makefile check to arch/s390/kvm that fails the build on any
EXPORT_SYMBOL_GPL or EXPORT_SYMBOL not in the allowed list. A symbol
may only use EXPORT_SYMBOL_GPL if it is defined in exactly one of the
two s390 KVM modules (kvm or kvm-arm64).
> diff --git a/arch/s390/kvm/arm64/Makefile b/arch/s390/kvm/arm64/Makefile
> index bd78d64939d1a..d84d3be74037d 100644
> --- a/arch/s390/kvm/arm64/Makefile
> +++ b/arch/s390/kvm/arm64/Makefile
[ ... ]
> @@ -91,3 +92,16 @@ targets += kvm-unnamespaced.o kvm_symbol_list kvm-namespaced.o
> endif
>
> obj-$(CONFIG_KVM) += kvm-arm64.o
> +
> +# Fail the build if there is unexpected EXPORT_SYMBOL_GPL (or EXPORT_SYMBOL)
> +# usage in arm64 KVM code. A symbol may only use EXPORT_SYMBOL_GPL if it is
> +# defined in exactly one of the two s390 KVM modules (kvm or kvm_arm64). A
> +# symbol defined in both would cause a conflict during linking if builtin is
> +# selected. Catch the issue early.
> +
> +# This "symbol" is not exported by arm on s390 but still in the source code and the
> +# export check scans unexpanded source code.
> +kvm_exports_allowed := kvm_file_to_kvm_fn
> +
> +$(eval $(call kvm_check_exports,EXPORT_SYMBOL_GPL))
[Severity: Low]
Will kvm_check_exports print false-positive violations in the error log here?
While KVM_CHECK_EXPORT_DIRS is overridden in this Makefile to restrict the
export check to its own specific directories, __kvm_get_exports ignores this
customization and hardcodes the search path to:
$(srctree)/virt/kvm $(srctree)/arch/$(SRCARCH)/kvm
This search path covers the entire s390/kvm tree. If an unwanted export
triggers a build error in the arm64 module, the error message invoking
__kvm_get_exports will inadvertently list valid, allowed exports from the
s390 module as unwanted occurrences.
> +$(eval $(call kvm_check_exports,EXPORT_SYMBOL))
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260918133107.1042730-1-seiden@linux.ibm.com?part=29
^ permalink raw reply [flat|nested] 80+ messages in thread
* Re: [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM
2026-09-18 13:30 [PATCH v8 00/29] KVM: s390: Introduce arm64 KVM Steffen Eiden
` (28 preceding siblings ...)
2026-09-18 13:31 ` [PATCH v8 29/29] KVM: s390: Enforce no unexpected external symbol exports in s390 KVM Steffen Eiden
@ 2026-09-18 13:38 ` Steffen Eiden
29 siblings, 0 replies; 80+ messages in thread
From: Steffen Eiden @ 2026-09-18 13:38 UTC (permalink / raw)
To: Steffen Eiden
Cc: kvm, kvmarm, linux-arm-kernel, linux-kernel, linux-s390,
Alexander Gordeev, Andreas Grapentin, Arnd Bergmann,
Catalin Marinas, Christian Borntraeger, Claudio Imbrenda,
David Hildenbrand, Friedrich Welter, Fuad Tabba, Gautam Gala,
Hariharan Mari, Heiko Carstens, Hendrik Brueckner,
Ilya Leoshkevich, Janosch Frank, Joey Gouly, Marc Zyngier,
Nico Boehr, Nina Schoetterl-Glausch, Oliver Upton, Paolo Bonzini,
Suzuki K Poulose, Sven Schnelle, Ulrich Weigand, Vasily Gorbik,
Will Deacon, Zenghui Yu
On Fri, Sep 18, 2026 at 03:30:37PM +0200, Steffen Eiden wrote:
> Introduce arm-on-s390. Enable KVM-accelerated ARM CPU virtualisation on s390.
>
...
>
> Hendrik Brueckner (1):
> s390/hwcaps: Report SAE support as hwcap
>
> Steffen Eiden (28):
> KVM: Introduce file_to_kvm_<arch>() infrastructure
> KVM: Add file back-pointer to struct kvm
> KVM: x86: Use file_to_kvm_x86() in SEV
> KVM/vfio: Use file-based reference counting for KVM
> KVM: Restrict kvm_get_kvm/kvm_put_kvm export to internal KVM modules
@Sean: I think yo udeserve Co-authorshiop for those 4
(if not already there)
If you think the same please give me your signoff
Steffen
> KVM: Move export symbol check macros to Makefile.kvm
> KVM: Make device name configurable
> KVM: Move architecture capability Kconfigs to header defines
> KVM: Replace CONFIG_KVM_MMIO with KVM_NO_MMIO
> arm64: Use proper include variant
> arm64: ptrace: Use constants for compat register numbers
> arm64: sysreg: Convert SPSR_ELx to automatic register generation
> KVM: arm64: Access elements of vcpu_gp_regs individually
> KVM: arm64: Use accessor functions for core regs
> arm64: Prepare sharing arm64 headers with s390
> arm64: Share arm64 headers with s390
> KVM: arm64: Share arm64 code with s390
> s390/tools: Use arm64 headers
> KVM: s390: Use arm64 code
> s390: Introduce Start Arm Execution instruction
> KVM: s390: arm64: Introduce host definitions
> KVM: s390: Add basic arm64 kvm module
> KVM: s390: arm64: Implement required functions
> KVM: s390: arm64: Implement vm/vcpu create destroy.
> KVM: s390: arm64: Implement vCPU IOCTLs
> KVM: s390: arm64: Implement basic page fault handler
> KVM: s390: arm64: Integrate arm on s390
> KVM: s390: Enforce no unexpected external symbol exports in s390 KVM
...
^ permalink raw reply [flat|nested] 80+ messages in thread