From: Steffen Eiden <seiden@linux•ibm.com>
To: kvm@vger•kernel.org, kvmarm@lists•linux.dev,
linux-arm-kernel@lists•infradead.org,
linux-kernel@vger•kernel.org, linux-s390@vger•kernel.org
Cc: Alexander Gordeev <agordeev@linux•ibm.com>,
Andreas Grapentin <gra@linux•ibm.com>,
Arnd Bergmann <arnd@arndb•de>,
Catalin Marinas <catalin.marinas@arm•com>,
Christian Borntraeger <borntraeger@linux•ibm.com>,
Claudio Imbrenda <imbrenda@linux•ibm.com>,
David Hildenbrand <david@kernel•org>,
Friedrich Welter <fritz@linux•ibm.com>,
Gautam Gala <ggala@linux•ibm.com>,
Hariharan Mari <hari55@linux•ibm.com>,
Heiko Carstens <hca@linux•ibm.com>,
Hendrik Brueckner <brueckner@linux•ibm.com>,
Ilya Leoshkevich <iii@linux•ibm.com>,
Janosch Frank <frankja@linux•ibm.com>,
Joey Gouly <joey.gouly@arm•com>, Marc Zyngier <maz@kernel•org>,
Nico Boehr <nrb@linux•ibm.com>,
Nina Schoetterl-Glausch <oss@nina•schoetterlglausch.eu>,
Oliver Upton <oupton@kernel•org>,
Paolo Bonzini <pbonzini@redhat•com>,
Suzuki K Poulose <suzuki.poulose@arm•com>,
Sven Schnelle <svens@linux•ibm.com>,
Ulrich Weigand <Ulrich.Weigand@de•ibm.com>,
Vasily Gorbik <gor@linux•ibm.com>, Will Deacon <will@kernel•org>,
Zenghui Yu <yuzenghui@huawei•com>
Subject: [PATCH v3 26/27] KVM: s390: arm64: Implement basic page fault handler
Date: Fri, 29 May 2026 17:50:40 +0200 [thread overview]
Message-ID: <20260529155050.2902245-27-seiden@linux.ibm.com> (raw)
In-Reply-To: <20260529155050.2902245-1-seiden@linux.ibm.com>
Add host functionality to page in guest memory. If the guest does
something unexpected or illegal exit to userspace which very likely has
to stop 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/arm.c | 1 +
arch/s390/kvm/arm64/handle_exit.c | 2 +
arch/s390/kvm/arm64/mmu.c | 178 ++++++++++++++++++++++++++++++
3 files changed, 181 insertions(+)
create mode 100644 arch/s390/kvm/arm64/mmu.c
diff --git a/arch/s390/kvm/arm64/arm.c b/arch/s390/kvm/arm64/arm.c
index 18eca2261e0d..bf0866659421 100644
--- a/arch/s390/kvm/arm64/arm.c
+++ b/arch/s390/kvm/arm64/arm.c
@@ -437,6 +437,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
vcpu->arch.sae_block.vir);
ret = -EINVAL;
break;
+ case SAE_ICPTR_HOST_ACCESS_EXCEPTION:
case SAE_ICPTR_SYNCHRONOUS_EXCEPTION:
ret = handle_trap_exceptions(vcpu);
break;
diff --git a/arch/s390/kvm/arm64/handle_exit.c b/arch/s390/kvm/arm64/handle_exit.c
index 89933a604876..bccd644fb07c 100644
--- a/arch/s390/kvm/arm64/handle_exit.c
+++ b/arch/s390/kvm/arm64/handle_exit.c
@@ -47,4 +47,6 @@ static int handle_hvc(struct kvm_vcpu *vcpu)
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,
};
diff --git a/arch/s390/kvm/arm64/mmu.c b/arch/s390/kvm/arm64/mmu.c
new file mode 100644
index 000000000000..8759cbafbaff
--- /dev/null
+++ b/arch/s390/kvm/arm64/mmu.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/kvm_host.h>
+
+#include <asm/kvm_emulate.h>
+#include <asm/kvm_mmu.h>
+
+#include "faultin.h"
+
+static inline bool kvm_s390_cur_gmap_fault_is_write(struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.sae_block.hai.pic == 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 esr;
+ unsigned long hva;
+ bool write_fault;
+ bool guest_size_err;
+ bool writable;
+ bool is_iabt;
+ int ret;
+ gfn_t gfn;
+ int idx;
+
+ esr = kvm_vcpu_get_esr(vcpu);
+ 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 >= kvm_phys_size(vcpu->kvm))
+ return -ENOEXEC;
+ }
+
+ 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 >= kvm_phys_size(vcpu->kvm));
+ /*
+ * 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;
+}
--
2.53.0
next prev parent reply other threads:[~2026-05-29 15:51 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-29 15:50 [PATCH v3 00/27] KVM: s390: Introduce arm64 KVM Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 01/27] VFIO: take reference to the KVM module Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 02/27] KVM, vfio: remove symbol_get(kvm_get_kvm_safe) from vfio Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 03/27] KVM, vfio: remove symbol_get(kvm_put_kvm) " Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 04/27] uapi: KVM: Provide arm64 UAPI for other host architectures Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 05/27] arm64: Extract sysreg definitions Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 06/27] arm64: Provide arm64 API for non-native architectures Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 07/27] KVM: arm64: Provide arm64 KVM " Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 08/27] arm64: Extract pstate definitions from ptrace Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 09/27] KVM: arm64: Share kvm_emulate definitions Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 10/27] KVM: arm64: Make some arm64 KVM code shareable Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 11/27] KVM: arm64: Access elements of vcpu_gp_regs individually Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 12/27] KVM: arm64: Share reset general register code Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 13/27] KVM: arm64: Extract & share ipa size shift calculation Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 14/27] KVM: s390: Move s390 kvm code into a subdirectory Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 15/27] KVM: S390: Refactor gmap Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 16/27] KVM: Make device name configurable Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 17/27] KVM: Remove KVM_MMIO as config option Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 18/27] KVM: s390: Prepare kvm-s390 for a second kvm module Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 19/27] s390: Introduce Start Arm Execution instruction Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 20/27] KVM: s390: arm64: Introduce host definitions Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 21/27] s390/hwcaps: Report SAE support as hwcap Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 22/27] KVM: s390: Add basic arm64 kvm module Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 23/27] KVM: s390: arm64: Implement required functions Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 24/27] KVM: s390: arm64: Implement vm/vcpu create destroy Steffen Eiden
2026-05-29 15:50 ` [PATCH v3 25/27] KVM: s390: arm64: Implement vCPU IOCTLs Steffen Eiden
2026-05-29 15:50 ` Steffen Eiden [this message]
2026-05-29 15:50 ` [PATCH v3 27/27] KVM: s390: arm64: Enable KVM_ARM64 config and Kbuild 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=20260529155050.2902245-27-seiden@linux.ibm.com \
--to=seiden@linux$(echo .)ibm.com \
--cc=Ulrich.Weigand@de$(echo .)ibm.com \
--cc=agordeev@linux$(echo .)ibm.com \
--cc=arnd@arndb$(echo .)de \
--cc=borntraeger@linux$(echo .)ibm.com \
--cc=brueckner@linux$(echo .)ibm.com \
--cc=catalin.marinas@arm$(echo .)com \
--cc=david@kernel$(echo .)org \
--cc=frankja@linux$(echo .)ibm.com \
--cc=fritz@linux$(echo .)ibm.com \
--cc=ggala@linux$(echo .)ibm.com \
--cc=gor@linux$(echo .)ibm.com \
--cc=gra@linux$(echo .)ibm.com \
--cc=hari55@linux$(echo .)ibm.com \
--cc=hca@linux$(echo .)ibm.com \
--cc=iii@linux$(echo .)ibm.com \
--cc=imbrenda@linux$(echo .)ibm.com \
--cc=joey.gouly@arm$(echo .)com \
--cc=kvm@vger$(echo .)kernel.org \
--cc=kvmarm@lists$(echo .)linux.dev \
--cc=linux-arm-kernel@lists$(echo .)infradead.org \
--cc=linux-kernel@vger$(echo .)kernel.org \
--cc=linux-s390@vger$(echo .)kernel.org \
--cc=maz@kernel$(echo .)org \
--cc=nrb@linux$(echo .)ibm.com \
--cc=oss@nina$(echo .)schoetterlglausch.eu \
--cc=oupton@kernel$(echo .)org \
--cc=pbonzini@redhat$(echo .)com \
--cc=suzuki.poulose@arm$(echo .)com \
--cc=svens@linux$(echo .)ibm.com \
--cc=will@kernel$(echo .)org \
--cc=yuzenghui@huawei$(echo .)com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
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