[PATCH v6 10/28] s390x/diag: Introduce DIAG 508 for secure IPL operations

Zhuoying Cai posted 28 patches 1 month, 4 weeks ago
Maintainers: "Daniel P. Berrangé" <berrange@redhat.com>, Thomas Huth <thuth@redhat.com>, Richard Henderson <richard.henderson@linaro.org>, David Hildenbrand <david@redhat.com>, Ilya Leoshkevich <iii@linux.ibm.com>, Halil Pasic <pasic@linux.ibm.com>, Christian Borntraeger <borntraeger@linux.ibm.com>, Eric Farman <farman@linux.ibm.com>, Matthew Rosato <mjrosato@linux.ibm.com>, Jared Rossi <jrossi@linux.ibm.com>, Zhuoying Cai <zycai@linux.ibm.com>, Jason Herne <jjherne@linux.ibm.com>, Eric Blake <eblake@redhat.com>, Markus Armbruster <armbru@redhat.com>
[PATCH v6 10/28] s390x/diag: Introduce DIAG 508 for secure IPL operations
Posted by Zhuoying Cai 1 month, 4 weeks ago
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;
-- 
2.50.1
Re: [PATCH v6 10/28] s390x/diag: Introduce DIAG 508 for secure IPL operations
Posted by Thomas Huth 1 month, 1 week ago
On 18/09/2025 01.21, 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.

Technically, this works also without KVM, right? In that case, I'd maybe 
avoid the term "KVM" here, and just talk about "IPL extensions" and "guest", 
to avoid the confusion about whether this feature can be used with TCG, too, 
or not.

  Thomas
Re: [PATCH v6 10/28] s390x/diag: Introduce DIAG 508 for secure IPL operations
Posted by Collin Walling 1 month, 1 week ago
On 10/7/25 05:47, Thomas Huth wrote:
> On 18/09/2025 01.21, 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.
> 
> Technically, this works also without KVM, right? In that case, I'd maybe 
> avoid the term "KVM" here, and just talk about "IPL extensions" and "guest", 
> to avoid the confusion about whether this feature can be used with TCG, too, 
> or not.
> 
>   Thomas
> 
> 

Fair enough.  None of the secure IPL code leverages KVM, so we can
reword the document a bit.

-- 
Regards,
  Collin
Re: [PATCH v6 10/28] s390x/diag: Introduce DIAG 508 for secure IPL operations
Posted by Farhan Ali 1 month, 2 weeks ago
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;