@samitouri / QOSamiQemu / commits / 06b8b50b05

s390x/diag: Introduce DIAG 508 for secure IPL operations

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> Reviewed-by: Farhan Ali <alifm@linux.ibm.com> Reviewed-by: Thomas Huth <thuth@redhat.com> Link: https://lore.kernel.org/qemu-devel/20260730214624.2328883-12-zycai@linux.ibm.com Signed-off-by: Eric Farman <farman@linux.ibm.com>

Collin Walling committed Jul 30, 2026 at 17:46 UTC 06b8b50b057a08ed3680599866b69240dc006034
6 files changed +83
docs/specs/s390x-secure-ipl.rst
+18
@@ -66,3 +66,21 @@ Subcode 2 - store verification certificates
66 contiguously in a VCE (with zero-padding). Following the header, the
67 key-id is immediately stored. The hash and certificate data follow and
68 may be accessed via the respective offset fields stored in the VCE.
69 +
70 +
71 +Secure IPL Data Structures, Facilities, and Functions
72 +-----------------------------------------------------
73 +
74 +DIAGNOSE function code 'X'508' - IPL extensions
75 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
76 +
77 +DIAGNOSE 'X'508' is reserved for guest use in order to facilitate communication
78 +of additional IPL operations that cannot be handled by guest code, such as
79 +signature verification for secure IPL.
80 +
81 +If the function code specifies 0x508, IPL extension functions are performed.
82 +These functions are meant to provide extended functionality for s390 guest boot
83 +that requires assistance from QEMU.
84 +
85 +Subcode 0 - query installed subcodes
86 + Returns a 64-bit mask indicating which subcodes are supported.
include/hw/s390x/ipl/diag508.h new
+15
@@ -0,0 +1,15 @@
1 +/*
2 + * S/390 DIAGNOSE 508 definitions and structures
3 + *
4 + * Copyright 2025 IBM Corp.
5 + * Author(s): Collin Walling <walling@linux.ibm.com>
6 + *
7 + * SPDX-License-Identifier: GPL-2.0-or-later
8 + */
9 +
10 +#ifndef S390X_DIAG508_H
11 +#define S390X_DIAG508_H
12 +
13 +#define DIAG_508_SUBC_QUERY_SUBC 0x0000
14 +
15 +#endif
target/s390x/diag.c
+27
@@ -20,6 +20,7 @@
20 #include "hw/s390x/cert-store.h"
21 #include "hw/s390x/ipl.h"
22 #include "hw/s390x/ipl/diag320.h"
23 +#include "hw/s390x/ipl/diag508.h"
24 #include "hw/s390x/s390-virtio-ccw.h"
25 #include "system/kvm.h"
26 #include "kvm/kvm_s390x.h"
@@ -618,3 +619,29 @@ void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
619 break;
620 }
621 }
622 +
623 +void handle_diag_508(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
624 +{
625 + uint64_t subcode = env->regs[r3];
626 + int rc;
627 +
628 + if (env->psw.mask & PSW_MASK_PSTATE) {
629 + s390_program_interrupt(env, PGM_PRIVILEGED, ra);
630 + return;
631 + }
632 +
633 + if ((subcode & ~0x0ffffULL) || (r1 & 1)) {
634 + s390_program_interrupt(env, PGM_SPECIFICATION, ra);
635 + return;
636 + }
637 +
638 + switch (subcode) {
639 + case DIAG_508_SUBC_QUERY_SUBC:
640 + rc = 0;
641 + break;
642 + default:
643 + s390_program_interrupt(env, PGM_SPECIFICATION, ra);
644 + return;
645 + }
646 + env->regs[r1 + 1] = rc;
647 +}
target/s390x/kvm/kvm.c
+14
@@ -102,6 +102,7 @@
102 #define DIAG_CERT_STORE 0x320
103 #define DIAG_KVM_HYPERCALL 0x500
104 #define DIAG_KVM_BREAKPOINT 0x501
105 +#define DIAG_SECURE_IPL 0x508
106
107 #define ICPT_INSTRUCTION 0x04
108 #define ICPT_PROGRAM 0x08
@@ -1542,6 +1543,16 @@ static void kvm_handle_diag_320(S390CPU *cpu, struct kvm_run *run)
1543 handle_diag_320(&cpu->env, r1, r3, RA_IGNORED);
1544 }
1545
1546 +static void kvm_handle_diag_508(S390CPU *cpu, struct kvm_run *run)
1547 +{
1548 + uint64_t r1, r3;
1549 +
1550 + r1 = (run->s390_sieic.ipa & 0x00f0) >> 4;
1551 + r3 = run->s390_sieic.ipa & 0x000f;
1552 +
1553 + handle_diag_508(&cpu->env, r1, r3, RA_IGNORED);
1554 +}
1555 +
1556 #define DIAG_KVM_CODE_MASK 0x000000000000ffff
1557
1558 static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
@@ -1575,6 +1586,9 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
1586 case DIAG_CERT_STORE:
1587 kvm_handle_diag_320(cpu, run);
1588 break;
1589 + case DIAG_SECURE_IPL:
1590 + kvm_handle_diag_508(cpu, run);
1591 + break;
1592 default:
1593 trace_kvm_insn_diag(func_code);
1594 kvm_s390_program_interrupt(cpu, PGM_SPECIFICATION);
target/s390x/s390x-internal.h
+2
@@ -390,6 +390,8 @@ bool handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3,
390 uintptr_t ra);
391 void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3,
392 uintptr_t ra);
393 +void handle_diag_508(CPUS390XState *env, uint64_t r1, uint64_t r3,
394 + uintptr_t ra);
395
396
397 /* translate.c */
target/s390x/tcg/misc_helper.c
+7
@@ -154,6 +154,13 @@ void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num)
154 bql_unlock();
155 r = 0;
156 break;
157 + case 0x508:
158 + /* secure ipl operations */
159 + bql_lock();
160 + handle_diag_508(env, r1, r3, GETPC());
161 + bql_unlock();
162 + r = 0;
163 + break;
164 default:
165 r = -1;
166 break;