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: Andreas Grapentin <Andreas.Grapentin@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>,
Gautam Gala <ggala@linux.ibm.com>,
Hendrik Brueckner <brueckner@linux.ibm.com>,
Janosch Frank <frankja@linux.ibm.com>,
Joey Gouly <joey.gouly@arm.com>, Marc Zyngier <maz@kernel.org>,
Nina Schoetterl-Glausch <oss@nina.schoetterlglausch.eu>,
Oliver Upton <oupton@kernel.org>,
Paolo Bonzini <pbonzini@redhat.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Ulrich Weigand <Ulrich.Weigand@de.ibm.com>,
Will Deacon <will@kernel.org>, Zenghui Yu <yuzenghui@huawei.com>
Subject: [PATCH v1 19/27] s390: Introduce Start Arm Execution instruction
Date: Thu, 2 Apr 2026 06:21:15 +0200 [thread overview]
Message-ID: <20260402042125.3948963-20-seiden@linux.ibm.com> (raw)
In-Reply-To: <20260402042125.3948963-1-seiden@linux.ibm.com>
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.
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 | 128 +++++++++++++++++++
arch/s390/include/asm/sae.h | 39 ++++++
arch/s390/include/asm/stacktrace.h | 5 +
arch/s390/kernel/asm-offsets.c | 1 +
arch/s390/kernel/entry.S | 24 ++++
arch/s390/tools/opcodes.txt | 3 +
7 files changed, 201 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 7bd1801cf241..2bf4b52f4d2d 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>
__int128_t __ashlti3(__int128_t a, int b);
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..9cbc9a88f515
--- /dev/null
+++ b/arch/s390/include/asm/kvm_host_arm64_types.h
@@ -0,0 +1,128 @@
+/* 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_SYSTEM_REGISTER 0x08
+#define SAE_ICPTR_PMU 0x09
+#define SAE_ICPTR_MAINTENANCE 0x0a
+ u8 icptr; /* 0x0080 */
+ u8 _0081[7]; /* 0x0081 */
+ u64 scad; /* 0x0088 */
+ u64 _0090[16]; /* 0x00b0 */
+ 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[13]; /* 0x0190 */
+ 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 */
+ u64 fpcr; /* 0x02b0 */
+ u64 fpsr; /* 0x02b8 */
+ 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 */
+#define SAE_VIR_UNKNOWN 0x00
+#define SAE_VIR_UNSUPP_FORMAT 0x01
+#define SAE_VIR_MSO_BOUNDS 0x02
+#define SAE_VIR_MSLA 0x03
+#define SAE_VIR_MGPAS 0x04
+#define SAE_VIR_INVAL_SYSREG 0x05
+#define SAE_VIR_HOST_CONTROL 0x06
+#define SAE_VIR_SCA 0x07
+#define SAE_VIR_MSO_ALIGN 0x08
+#define SAE_VIR_HLC 0x09
+#define SEA_VIR_IRPTC 0x0a
+ u16 vir; /* 0x0400 */
+ /* host access interception details; icptr 0x02 */
+ struct {
+ u64 esr_elz; /* 0x0400 */
+ u8 _0408[6]; /* 0x0408 */
+ u16 pic; /* 0x040e */
+ union teid teid; /* 0x0410 */
+ gva_t far_elz; /* 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 {
+ gva_t esr_elz; /* 0x0400 */
+ u64 _0408[2]; /* 0x0408 */
+ u64 far_elz; /* 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_ULL(0)
+ u16 sas; /* 0x0006 */
+ u64 sdo; /* 0x0008 */
+ u64 _0010[2]; /* 0x0010 */
+ u64 regs[507]; /* 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/sae.h b/arch/s390/include/asm/sae.h
new file mode 100644
index 000000000000..d7be5ebb25d5
--- /dev/null
+++ b/arch/s390/include/asm/sae.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_S390_SAE_H
+#define __ASM_S390_SAE_H
+
+/* defined in arch/s390/kernel/entry.S */
+int __sae64a(phys_addr_t sae_block_phys);
+
+/**
+ * __sae64a() - Start Arm Execution
+ */
+static inline void sae64a(struct kvm_sae_block *sae_block)
+{
+ __sae64a(virt_to_phys(sae_block));
+}
+
+/**
+ * stiasrm() - STore and Invalidate Arm System Register Multiple
+ */
+static __always_inline void stiasrm(struct kvm_sae_save_area *save_area)
+{
+ asm volatile(".insn rre,0xb9a70000,%[r1],0\n"
+ : "=m"(*save_area)
+ : [r1] "d"(save_area));
+}
+
+/**
+ * lasrm() - Load Arm System Register Multiple
+ *
+ */
+static __always_inline void lasrm(struct kvm_sae_save_area *save_area)
+{
+ asm volatile(".insn rre,0xb9a60000,%[r1],0\n"
+ :
+ : "m" (*save_area),
+ [r1] "d" (save_area)
+ );
+}
+
+#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 8619adf91cdb..8ef992734bf8 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -68,6 +68,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 ac8d75a209fa..fc5f1dd77e6c 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -244,6 +244,30 @@ EXPORT_SYMBOL(__sie64a)
EXPORT_SYMBOL(sie_exit)
#endif
+#if IS_ENABLED(CONFIG_KVM_ARM64)
+/*
+ * __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
+# Let the next instruction be NOP to avoid triggering a machine check
+# and handling it in a guest as result of the instruction execution.
+ nopr 7
+ LBEAR __SF_SAE_BEAR(%r15) # restore breaking event address register
+ xgr %r0,%r0 # clear guest registers to
+ xgr %r1,%r1 # prevent speculative use
+ xgr %r3,%r3
+ xgr %r4,%r4
+ xgr %r5,%r5
+ lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
+ 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.51.0
next prev parent reply other threads:[~2026-04-02 4:22 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-02 4:20 [PATCH v1 00/27] KVM: s390: Introduce arm64 KVM Steffen Eiden
2026-04-02 4:20 ` [PATCH v1 01/27] VFIO: take reference to the KVM module Steffen Eiden
2026-04-02 9:18 ` Paolo Bonzini
2026-04-02 4:20 ` [PATCH v1 02/27] KVM, vfio: remove symbol_get(kvm_get_kvm_safe) from vfio Steffen Eiden
2026-04-02 4:20 ` [PATCH v1 03/27] KVM, vfio: remove symbol_get(kvm_put_kvm) " Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 04/27] arm64: Provide arm64 UAPI for other host architectures Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 05/27] arm64: Extract sysreg definitions Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 06/27] arm64: Provide arm64 API for non-native architectures Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 07/27] KVM: arm64: Provide arm64 KVM " Steffen Eiden
2026-04-02 10:08 ` Marc Zyngier
2026-04-02 11:26 ` Christian Borntraeger
2026-04-02 4:21 ` [PATCH v1 08/27] arm64: Extract pstate definitions from ptrace Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 09/27] KVM: arm64: Share kvm_emulate definitions Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 10/27] KVM: arm64: Make some arm64 KVM code shareable Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 11/27] KVM: arm64: Access elements of vcpu_gp_regs individually Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 12/27] KVM: arm64: Share reset general register code Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 13/27] KVM: arm64: Extract & share ipa size shift calculation Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 14/27] KVM: s390: Move s390 kvm code into a subdirectory Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 15/27] KVM: S390: Refactor gmap Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 16/27] KVM: Make device name configurable Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 17/27] KVM: Remove KVM_MMIO as config option Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 18/27] KVM: s390: Prepare kvm-s390 for a second kvm module Steffen Eiden
2026-04-02 4:21 ` Steffen Eiden [this message]
2026-04-02 4:21 ` [PATCH v1 20/27] KVM: s390: arm64: Introduce host definitions Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 21/27] s390/hwcaps: Report SAE support as hwcap Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 22/27] KVM: s390: Add basic arm64 kvm module Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 23/27] KVM: s390: arm64: Implement required functions Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 24/27] KVM: s390: arm64: Implement vm/vcpu create destroy Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 25/27] KVM: s390: arm64: Implement vCPU IOCTLs Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 26/27] KVM: s390: arm64: Implement basic page fault handler Steffen Eiden
2026-04-02 4:21 ` [PATCH v1 27/27] KVM: s390: arm64: Enable KVM_ARM64 config and Kbuild Steffen Eiden
2026-04-02 8:53 ` [PATCH v1 00/27] KVM: s390: Introduce arm64 KVM David Hildenbrand (Arm)
2026-04-02 10:07 ` Christian Borntraeger
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=20260402042125.3948963-20-seiden@linux.ibm.com \
--to=seiden@linux.ibm.com \
--cc=Andreas.Grapentin@ibm.com \
--cc=Ulrich.Weigand@de.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=ggala@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=maz@kernel.org \
--cc=oss@nina.schoetterlglausch.eu \
--cc=oupton@kernel.org \
--cc=pbonzini@redhat.com \
--cc=suzuki.poulose@arm.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