Reviewed-by: Farhan Ali <alifm@linux.ibm.com>
On 9/17/2025 4:21 PM, Zhuoying Cai wrote:
> From: Collin Walling <walling@linux.ibm.com>
>
> In order to support secure IPL (aka secure boot) for the s390-ccw BIOS,
> a new s390 DIAGNOSE instruction is introduced to leverage QEMU for
> handling operations such as signature verification and certificate
> retrieval.
>
> Currently, only subcode 0 is supported with this patch, which is used to
> query a bitmap of which subcodes are supported.
>
> Signed-off-by: Collin Walling <walling@linux.ibm.com>
> ---
> docs/specs/s390x-secure-ipl.rst | 18 ++++++++++++++++++
> include/hw/s390x/ipl/diag508.h | 15 +++++++++++++++
> target/s390x/diag.c | 27 +++++++++++++++++++++++++++
> target/s390x/kvm/kvm.c | 14 ++++++++++++++
> target/s390x/s390x-internal.h | 2 ++
> target/s390x/tcg/misc_helper.c | 7 +++++++
> 6 files changed, 83 insertions(+)
> create mode 100644 include/hw/s390x/ipl/diag508.h
>
> diff --git a/docs/specs/s390x-secure-ipl.rst b/docs/specs/s390x-secure-ipl.rst
> index e28f0b40d7..0919425e9a 100644
> --- a/docs/specs/s390x-secure-ipl.rst
> +++ b/docs/specs/s390x-secure-ipl.rst
> @@ -48,3 +48,21 @@ Subcode 2 - store verification certificates
> storage specified in the VCB input length field.
>
> VCE contains various information of a VC from the CS.
> +
> +
> +Secure IPL Data Structures, Facilities, and Functions
> +=====================================================
> +
> +DIAGNOSE function code 'X'508' - KVM IPL extensions
> +---------------------------------------------------
> +
> +DIAGNOSE 'X'508' is reserved for KVM guest use in order to facilitate
> +communication of additional IPL operations that cannot be handled by userspace,
> +such as signature verification for secure IPL.
> +
> +If the function code specifies 0x508, KVM IPL extension functions are performed.
> +These functions are meant to provide extended functionality for s390 guest boot
> +that requires assistance from QEMU.
> +
> +Subcode 0 - query installed subcodes
> + Returns a 64-bit mask indicating which subcodes are supported.
> diff --git a/include/hw/s390x/ipl/diag508.h b/include/hw/s390x/ipl/diag508.h
> new file mode 100644
> index 0000000000..6281ad8299
> --- /dev/null
> +++ b/include/hw/s390x/ipl/diag508.h
> @@ -0,0 +1,15 @@
> +/*
> + * S/390 DIAGNOSE 508 definitions and structures
> + *
> + * Copyright 2025 IBM Corp.
> + * Author(s): Collin Walling <walling@linux.ibm.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef S390X_DIAG508_H
> +#define S390X_DIAG508_H
> +
> +#define DIAG_508_SUBC_QUERY_SUBC 0x0000
> +
> +#endif
> diff --git a/target/s390x/diag.c b/target/s390x/diag.c
> index d5f6c54df3..ee64257dbc 100644
> --- a/target/s390x/diag.c
> +++ b/target/s390x/diag.c
> @@ -20,6 +20,7 @@
> #include "hw/s390x/cert-store.h"
> #include "hw/s390x/ipl.h"
> #include "hw/s390x/ipl/diag320.h"
> +#include "hw/s390x/ipl/diag508.h"
> #include "hw/s390x/s390-virtio-ccw.h"
> #include "system/kvm.h"
> #include "kvm/kvm_s390x.h"
> @@ -600,3 +601,29 @@ void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
> break;
> }
> }
> +
> +void handle_diag_508(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
> +{
> + uint64_t subcode = env->regs[r3];
> + int rc;
> +
> + if (env->psw.mask & PSW_MASK_PSTATE) {
> + s390_program_interrupt(env, PGM_PRIVILEGED, ra);
> + return;
> + }
> +
> + if ((subcode & ~0x0ffffULL) || (r1 & 1)) {
> + s390_program_interrupt(env, PGM_SPECIFICATION, ra);
> + return;
> + }
> +
> + switch (subcode) {
> + case DIAG_508_SUBC_QUERY_SUBC:
> + rc = 0;
> + break;
> + default:
> + s390_program_interrupt(env, PGM_SPECIFICATION, ra);
> + return;
> + }
> + env->regs[r1 + 1] = rc;
> +}
> diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c
> index 5510fc2fc5..ae6cd3d506 100644
> --- a/target/s390x/kvm/kvm.c
> +++ b/target/s390x/kvm/kvm.c
> @@ -101,6 +101,7 @@
> #define DIAG_CERT_STORE 0x320
> #define DIAG_KVM_HYPERCALL 0x500
> #define DIAG_KVM_BREAKPOINT 0x501
> +#define DIAG_SECURE_IPL 0x508
>
> #define ICPT_INSTRUCTION 0x04
> #define ICPT_PROGRAM 0x08
> @@ -1571,6 +1572,16 @@ static void kvm_handle_diag_320(S390CPU *cpu, struct kvm_run *run)
> handle_diag_320(&cpu->env, r1, r3, RA_IGNORED);
> }
>
> +static void kvm_handle_diag_508(S390CPU *cpu, struct kvm_run *run)
> +{
> + uint64_t r1, r3;
> +
> + r1 = (run->s390_sieic.ipa & 0x00f0) >> 4;
> + r3 = run->s390_sieic.ipa & 0x000f;
> +
> + handle_diag_508(&cpu->env, r1, r3, RA_IGNORED);
> +}
> +
> #define DIAG_KVM_CODE_MASK 0x000000000000ffff
>
> static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
> @@ -1604,6 +1615,9 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
> case DIAG_CERT_STORE:
> kvm_handle_diag_320(cpu, run);
> break;
> + case DIAG_SECURE_IPL:
> + kvm_handle_diag_508(cpu, run);
> + break;
> default:
> trace_kvm_insn_diag(func_code);
> kvm_s390_program_interrupt(cpu, PGM_SPECIFICATION);
> diff --git a/target/s390x/s390x-internal.h b/target/s390x/s390x-internal.h
> index ecff2d07a1..7cca8a67de 100644
> --- a/target/s390x/s390x-internal.h
> +++ b/target/s390x/s390x-internal.h
> @@ -393,6 +393,8 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3,
> uintptr_t ra);
> void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3,
> uintptr_t ra);
> +void handle_diag_508(CPUS390XState *env, uint64_t r1, uint64_t r3,
> + uintptr_t ra);
>
>
> /* translate.c */
> diff --git a/target/s390x/tcg/misc_helper.c b/target/s390x/tcg/misc_helper.c
> index 412c34ed93..ddbf495118 100644
> --- a/target/s390x/tcg/misc_helper.c
> +++ b/target/s390x/tcg/misc_helper.c
> @@ -149,6 +149,13 @@ void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num)
> bql_unlock();
> r = 0;
> break;
> + case 0x508:
> + /* secure ipl operations */
> + bql_lock();
> + handle_diag_508(env, r1, r3, GETPC());
> + bql_unlock();
> + r = 0;
> + break;
> default:
> r = -1;
> break;