diff mbox series

[v1,08/24] s390x/diag: Introduce DIAG 508 for secure IPL operations

Message ID 20250408155527.123341-9-zycai@linux.ibm.com (mailing list archive)
State New
Headers show
Series Secure IPL Support for SCSI Scheme of virtio-blk/virtio-scsi Devices | expand

Commit Message

Zhuoying Cai April 8, 2025, 3:55 p.m. UTC
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>
---
 hw/s390x/ipl.h                 |  1 +
 include/hw/s390x/ipl/diag508.h | 17 +++++++++++++++++
 target/s390x/diag.c            | 26 ++++++++++++++++++++++++++
 target/s390x/kvm/kvm.c         | 14 ++++++++++++++
 target/s390x/s390x-internal.h  |  2 ++
 5 files changed, 60 insertions(+)
 create mode 100644 include/hw/s390x/ipl/diag508.h

Comments

Thomas Huth April 11, 2025, 2:22 p.m. UTC | #1
On 08/04/2025 17.55, 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>
> ---
>   hw/s390x/ipl.h                 |  1 +
>   include/hw/s390x/ipl/diag508.h | 17 +++++++++++++++++
>   target/s390x/diag.c            | 26 ++++++++++++++++++++++++++
>   target/s390x/kvm/kvm.c         | 14 ++++++++++++++
>   target/s390x/s390x-internal.h  |  2 ++
>   5 files changed, 60 insertions(+)
>   create mode 100644 include/hw/s390x/ipl/diag508.h
> 
> diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
> index 822535ad76..e9ef8ddccd 100644
> --- a/hw/s390x/ipl.h
> +++ b/hw/s390x/ipl.h
> @@ -18,6 +18,7 @@
>   #include "exec/address-spaces.h"
>   #include "hw/qdev-core.h"
>   #include "hw/s390x/ipl/diag320.h"
> +#include "hw/s390x/ipl/diag508.h"
>   #include "hw/s390x/ipl/qipl.h"
>   #include "qom/object.h"
>   
> diff --git a/include/hw/s390x/ipl/diag508.h b/include/hw/s390x/ipl/diag508.h
> new file mode 100644
> index 0000000000..83c4439cb2
> --- /dev/null
> +++ b/include/hw/s390x/ipl/diag508.h
> @@ -0,0 +1,17 @@
> +/*
> + * S/390 DIAGNOSE 508 definitions and structures
> + *
> + * Copyright 2025 IBM Corp.
> + * Author(s): Collin Walling <walling@linux.ibm.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or (at
> + * your option) any later version. See the COPYING file in the top-level
> + * directory.
> + */
> +
> +#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 82e4dc9e1e..ad7f4b5025 100644
> --- a/target/s390x/diag.c
> +++ b/target/s390x/diag.c
> @@ -488,3 +488,29 @@ void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
>       }
>       env->regs[r1 + 1] = rc;
>   }
> +
> +void handle_diag_508(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
> +{
> +    uint64_t subcode = env->regs[r3];
> +    int rc;

Do we need to check some feature bit here? e.g. check 
s390_has_feat(S390_FEAT_DIAG_320) here, too?

> +    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;
> +}

  Thomas
diff mbox series

Patch

diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index 822535ad76..e9ef8ddccd 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -18,6 +18,7 @@ 
 #include "exec/address-spaces.h"
 #include "hw/qdev-core.h"
 #include "hw/s390x/ipl/diag320.h"
+#include "hw/s390x/ipl/diag508.h"
 #include "hw/s390x/ipl/qipl.h"
 #include "qom/object.h"
 
diff --git a/include/hw/s390x/ipl/diag508.h b/include/hw/s390x/ipl/diag508.h
new file mode 100644
index 0000000000..83c4439cb2
--- /dev/null
+++ b/include/hw/s390x/ipl/diag508.h
@@ -0,0 +1,17 @@ 
+/*
+ * S/390 DIAGNOSE 508 definitions and structures
+ *
+ * Copyright 2025 IBM Corp.
+ * Author(s): Collin Walling <walling@linux.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
+ * your option) any later version. See the COPYING file in the top-level
+ * directory.
+ */
+
+#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 82e4dc9e1e..ad7f4b5025 100644
--- a/target/s390x/diag.c
+++ b/target/s390x/diag.c
@@ -488,3 +488,29 @@  void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
     }
     env->regs[r1 + 1] = rc;
 }
+
+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 b013751478..a5c5150c04 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
@@ -1572,6 +1573,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)
@@ -1605,6 +1616,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 86a652f833..df0973266a 100644
--- a/target/s390x/s390x-internal.h
+++ b/target/s390x/s390x-internal.h
@@ -402,6 +402,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 */