From: Steffen Eiden <seiden@linux.ibm.com>
To: Marc Zyngier <maz@kernel.org>, Oliver Upton <oupton@kernel.org>,
Fuad Tabba <fuad.tabba@linux.dev>,
Joey Gouly <joey.gouly@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Zenghui Yu <yuzenghui@huawei.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
Andreas Grapentin <gra@linux.ibm.com>,
Christian Borntraeger <borntraeger@linux.ibm.com>,
Janosch Frank <frankja@linux.ibm.com>,
Claudio Imbrenda <imbrenda@linux.ibm.com>,
David Hildenbrand <david@kernel.org>,
Heiko Carstens <hca@linux.ibm.com>,
Vasily Gorbik <gor@linux.ibm.com>,
Alexander Gordeev <agordeev@linux.ibm.com>,
Sven Schnelle <svens@linux.ibm.com>,
Friedrich Welter <fritz@linux.ibm.com>,
Gautam Gala <ggala@linux.ibm.com>,
Hariharan Mari <hari55@linux.ibm.com>,
Hendrik Brueckner <brueckner@linux.ibm.com>,
Nico Boehr <nrb@linux.ibm.com>,
Ulrich Weigand <Ulrich.Weigand@de.ibm.com>,
Arnd Bergmann <arnd@arndb.de>,
Paolo Bonzini <pbonzini@redhat.com>
Cc: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
linux-kernel@vger.kernel.org, kvm@vger.kernel.org,
linux-s390@vger.kernel.org, Steffen Eiden <seiden@linux.ibm.com>
Subject: [PATCH v3 17/23] KVM: s390: arm64: Integrate sysreg into the host
Date: Fri, 06 Nov 2026 17:07:50 +0100 [thread overview]
Message-ID: <20261106-sysreg-v3-17-75e95980fb10@linux.ibm.com> (raw)
In-Reply-To: <20261106-sysreg-v3-0-75e95980fb10@linux.ibm.com>
Integrate the previously established system register managing
infrastructure into the host. Initialize sysregs during vcpu init.
Finalize sysregs on PID change, Initialize sysreg table on kvm init,
report availability to userspace and let userspace read&modify guest system
register.
Co-developed-by: Andreas Grapentin <gra@linux.ibm.com>
Signed-off-by: Andreas Grapentin <gra@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
---
arch/s390/include/asm/kvm_host_arm64.h | 3 +++
arch/s390/kvm/arm64/arm.c | 29 +++++++++++++++++++++++
arch/s390/kvm/arm64/guest.c | 12 ++++++----
arch/s390/kvm/arm64/handle_exit.c | 1 +
arch/s390/kvm/arm64/reset.c | 42 ++++++++++++++++++++++++++++++++++
arch/s390/kvm/arm64/sys_regs.c | 1 +
6 files changed, 84 insertions(+), 4 deletions(-)
diff --git a/arch/s390/include/asm/kvm_host_arm64.h b/arch/s390/include/asm/kvm_host_arm64.h
index 35b6d8972359..44deae423ace 100644
--- a/arch/s390/include/asm/kvm_host_arm64.h
+++ b/arch/s390/include/asm/kvm_host_arm64.h
@@ -157,6 +157,9 @@ struct kvm_arch {
/* Per-VM ID register storage */
struct kvm_vm_id_regs id_regs;
+
+ /* The EPD as it should be on all VCPUs. */
+ u64 epd;
};
static inline bool __vcpu_has_feature(const struct kvm_arch *ka, int feature)
diff --git a/arch/s390/kvm/arm64/arm.c b/arch/s390/kvm/arm64/arm.c
index ba6235629c7d..62fd71af8968 100644
--- a/arch/s390/kvm/arm64/arm.c
+++ b/arch/s390/kvm/arm64/arm.c
@@ -15,6 +15,7 @@
#include <arm64/kvm_emulate.h>
#include <arm64/sysreg.h>
+#include <arm64/sys_regs.h>
#include <gmap.h>
#include <kvm_mmu.h>
@@ -50,6 +51,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
break;
case KVM_CAP_IOEVENTFD:
case KVM_CAP_PRE_FAULT_MEMORY:
+ case KVM_CAP_ONE_REG:
ret = 1;
break;
default:
@@ -136,6 +138,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
goto out_err;
kvm->arch.mem_limit = kvm->arch.guest_phys_size;
+ kvm->arch.epd = ptff_qagto(0);
+
VM_EVENT(kvm, 3, "vm created with type %lu", type);
return 0;
@@ -193,6 +197,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
sae_block->mso = 0L;
sae_block->msl = vcpu->kvm->arch.mem_limit - 1;
sae_block->save_area = virt_to_phys(save_area);
+ sae_block->gpto = vcpu->kvm->arch.epd;
VM_EVENT(vcpu->kvm, 3,
"create cpu %d at 0x%p, sae block at 0x%p, satellite at 0x%p",
@@ -207,6 +212,7 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
{
+ kfree(vcpu->arch.ccsidr);
kvm_s390_free_mmu_cache(vcpu->arch.mc);
VCPU_EVENT(vcpu, 3, "%s", "free cpu");
@@ -218,6 +224,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
vcpu->cpu = cpu;
lasrm(&vcpu->arch.save_area);
+
+ vcpu->arch.sae_block.gpto = vcpu->kvm->arch.epd;
}
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -261,6 +269,7 @@ bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
{
struct kvm *kvm = vcpu->kvm;
+ int ret;
if (!kvm_vcpu_initialized(vcpu))
return -ENOEXEC;
@@ -271,6 +280,10 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
if (likely(READ_ONCE(vcpu->pid)))
return 0;
+ ret = kvm_vcpu_finalize_sys_regs(vcpu);
+ if (ret)
+ return ret;
+
scoped_guard(mutex, &kvm->arch.config_lock)
set_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags);
@@ -477,9 +490,17 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
trace_kvm_entry(*vcpu_pc(vcpu));
adjust_pc(vcpu);
+ vcpu_write_host_sys_reg(vcpu, vcpu->arch.hcr_el2, SYS_HCR_EL2);
+ vcpu_write_host_sys_reg(vcpu, vcpu->arch.hcrx_el2, SYS_HCRX_EL2);
+ vcpu_write_host_sys_reg(vcpu, vcpu->arch.mpidr, SYS_VMPIDR_EL2);
+ _vcpu_write_sys_reg(vcpu, vcpu->arch.ctxt.elr_el1, SYS_ELR_EL1);
+ _vcpu_write_sys_reg(vcpu, vcpu->arch.ctxt.spsr_el1, SYS_SPSR_EL1);
arm_vcpu_enter_exit(virt_to_phys(&vcpu->arch.sae_block));
+ vcpu->arch.ctxt.elr_el1 = _vcpu_read_sys_reg(vcpu, SYS_ELR_EL1);
+ vcpu->arch.ctxt.spsr_el1 = _vcpu_read_sys_reg(vcpu, SYS_SPSR_EL1);
+
vcpu->mode = OUTSIDE_GUEST_MODE;
vcpu->stat.exits++;
@@ -762,11 +783,19 @@ static bool __init machine_supports_arm64_kvm(void)
static int __init kvm_s390_arm64_init(void)
{
+ int ret;
+
if (!machine_supports_arm64_kvm())
return -ENODEV;
kvm_init_qaaf();
+ ret = kvm_sys_reg_table_init();
+ if (ret) {
+ kvm_info("Error initializing system register tables\n");
+ return ret;
+ }
+
return kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE);
}
diff --git a/arch/s390/kvm/arm64/guest.c b/arch/s390/kvm/arm64/guest.c
index 8b5ee9e79a4f..047460975936 100644
--- a/arch/s390/kvm/arm64/guest.c
+++ b/arch/s390/kvm/arm64/guest.c
@@ -4,6 +4,7 @@
#include <arm64/kvm_emulate.h>
#include <arm64/kvm_nested.h>
+#include <arm64/sys_regs.h>
#define SVE_VQ_MIN __SVE_VQ_MIN
#define SVE_NUM_ZREGS KVM_ARM64_SVE_NUM_ZREGS
@@ -60,12 +61,15 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
return ret;
uindices += ret;
- return 0;
+ return kvm_arm_copy_sys_reg_indices(vcpu, uindices);
}
unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
{
- return num_core_regs(vcpu);
+ unsigned long num = num_core_regs(vcpu);
+
+ num += kvm_arm_num_sys_reg_descs(vcpu);
+ return num;
}
int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
@@ -78,7 +82,7 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
case KVM_REG_ARM_CORE:
return get_core_reg(vcpu, reg);
default:
- return -EINVAL;
+ return kvm_arm_sys_reg_get_reg(vcpu, reg);
}
}
@@ -92,7 +96,7 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
case KVM_REG_ARM_CORE:
return set_core_reg(vcpu, reg);
default:
- return -EINVAL;
+ return kvm_arm_sys_reg_set_reg(vcpu, reg);
}
}
diff --git a/arch/s390/kvm/arm64/handle_exit.c b/arch/s390/kvm/arm64/handle_exit.c
index e0c7773c2165..1653163ed6d6 100644
--- a/arch/s390/kvm/arm64/handle_exit.c
+++ b/arch/s390/kvm/arm64/handle_exit.c
@@ -62,6 +62,7 @@ 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_SYS64] = kvm_handle_sys_reg,
[ESR_ELx_EC_IABT_LOW] = kvm_handle_guest_abort,
[ESR_ELx_EC_DABT_LOW] = kvm_handle_guest_abort,
};
diff --git a/arch/s390/kvm/arm64/reset.c b/arch/s390/kvm/arm64/reset.c
index e4cdce1dbf9d..0339901f5fd0 100644
--- a/arch/s390/kvm/arm64/reset.c
+++ b/arch/s390/kvm/arm64/reset.c
@@ -5,6 +5,10 @@
#include <arm64/kvm_emulate.h>
#include <arm64/kvm_nested.h>
+#include <arm64/sys_regs.h>
+#include <arm64/sysreg.h>
+
+#include <clocksource/arm_arch_timer.h>
bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu)
{
@@ -21,6 +25,39 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
HCR_EL2_TIDCP | HCR_EL2_TLOR;
}
+static inline void vcpu_reset_hcrx(struct kvm_vcpu *vcpu)
+{
+ vcpu->arch.hcrx_el2 = 0;
+ if (kvm_has_feat(vcpu->kvm, ID_AA64ISAR2_EL1, MOPS, IMP))
+ vcpu->arch.hcrx_el2 |= HCRX_EL2_MSCEn;
+}
+
+static inline void vcpu_reset_cptr(struct kvm_vcpu *vcpu)
+{
+ u64 cptr;
+
+ /* we unconditionally have E2H, so disable traps to EL2 for FP and SVE, if enabled */
+ cptr = CPACR_EL1_FPEN;
+ if (vcpu_has_sve(vcpu))
+ cptr |= CPACR_EL1_ZEN;
+ vcpu_write_host_sys_reg(vcpu, cptr, SYS_CPTR_EL2);
+}
+
+static inline void vcpu_reset_cnthctl(struct kvm_vcpu *vcpu)
+{
+ u64 cnthctl;
+
+ /* we unconditionally have E2H, so disable traps to EL2 for physical timer registers */
+ cnthctl = (CNTHCTL_EL1PCEN | CNTHCTL_EL1PCTEN) << 10;
+ vcpu_write_host_sys_reg(vcpu, cnthctl, SYS_CNTHCTL_EL2);
+}
+
+static inline void vcpu_reset_icc(struct kvm_vcpu *vcpu)
+{
+ /* ensure ICC_SRE_EL2.Enable = 1 so ICC_SRE_EL1 is handled in hardware */
+ vcpu_write_host_sys_reg(vcpu, 0xf, SYS_ICC_SRE_EL2);
+}
+
void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
{
struct vcpu_reset_state reset_state;
@@ -43,9 +80,14 @@ void kvm_reset_vcpu(struct kvm_vcpu *vcpu)
vcpu_put(vcpu);
kvm_reset_vcpu_core(vcpu);
+ kvm_reset_sys_regs(vcpu);
/* Reset special registers */
vcpu_reset_hcr(vcpu);
+ vcpu_reset_hcrx(vcpu);
+ vcpu_reset_cptr(vcpu);
+ vcpu_reset_cnthctl(vcpu);
+ vcpu_reset_icc(vcpu);
if (reset_state.reset) {
*vcpu_pc(vcpu) = reset_state.pc;
diff --git a/arch/s390/kvm/arm64/sys_regs.c b/arch/s390/kvm/arm64/sys_regs.c
index b1d4335779c7..417a05ce9015 100644
--- a/arch/s390/kvm/arm64/sys_regs.c
+++ b/arch/s390/kvm/arm64/sys_regs.c
@@ -441,6 +441,7 @@ static int arch_timer_set_user(struct kvm_vcpu *vcpu,
case SYS_CNTPCT_EL0:
gpto = ptff_qagto(val);
vcpu->arch.sae_block.gpto = gpto;
+ vcpu->kvm->arch.epd = gpto;
return 0;
}
--
2.56.0
next prev parent reply other threads:[~2026-11-06 16:09 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-06 16:07 [PATCH v3 00/23] KVM: arm64 on s390 System Register Handling Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 01/23] KVM: arm64: Refactor idreg caching into dedicated structure Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 02/23] KVM: arm64: Extract number of sys_reg_desc into a constant Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 03/23] arm64: sysreg: Convert OSLSR to automatic register generation Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 04/23] arm64: Prepare headers for sysreg sharing with s390 Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 05/23] arm64: Share system register related headers and functions " Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 06/23] KVM: s390: arm64: Prepare for sharing arm64 SVE and ftr-reg code Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 07/23] KVM: arm64: Prepare sys_regs.c for sharing with s390 Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 08/23] KVM: arm64: Share system register code " Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 09/23] s390: tools: Share arm64/kvm headers Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 10/23] s390: Add range check asm macro Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 11/23] s390: Read/write ARM system registers Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 12/23] s390: Query arm guest time Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 13/23] KVM: s390: arm64: Query Available Arm features Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 14/23] KVM: s390: arm64: Verify machine feature set before loading Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 15/23] KVM: s390: arm64: Implement feature sanitisation Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 16/23] KVM: s390: arm64: Implement arm sysreg managing infrastructure Steffen Eiden
2026-11-06 16:07 ` Steffen Eiden [this message]
2026-11-06 16:07 ` [PATCH v3 18/23] KVM: s390: arm64: Use QAAF init save area Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 19/23] KVM: s390: arm64: Implement exception injection Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 20/23] KVM: s390: arm64: Finalize page fault handling Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 21/23] KVM: s390: arm64: Implement SVE for arm guests Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 22/23] KVM: s390: arm64: Promote PTRAUTH capability Steffen Eiden
2026-11-06 16:07 ` [PATCH v3 23/23] s390: Report AEF features to sysfs Steffen Eiden
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261106-sysreg-v3-17-75e95980fb10@linux.ibm.com \
--to=seiden@linux.ibm.com \
--cc=Ulrich.Weigand@de.ibm.com \
--cc=agordeev@linux.ibm.com \
--cc=arnd@arndb.de \
--cc=borntraeger@linux.ibm.com \
--cc=brueckner@linux.ibm.com \
--cc=catalin.marinas@arm.com \
--cc=david@kernel.org \
--cc=frankja@linux.ibm.com \
--cc=fritz@linux.ibm.com \
--cc=fuad.tabba@linux.dev \
--cc=ggala@linux.ibm.com \
--cc=gor@linux.ibm.com \
--cc=gra@linux.ibm.com \
--cc=hari55@linux.ibm.com \
--cc=hca@linux.ibm.com \
--cc=imbrenda@linux.ibm.com \
--cc=joey.gouly@arm.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=maz@kernel.org \
--cc=nrb@linux.ibm.com \
--cc=oupton@kernel.org \
--cc=pbonzini@redhat.com \
--cc=suzuki.poulose@arm.com \
--cc=svens@linux.ibm.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®