diff mbox series

[v1,06/24] s390x/diag: Implement DIAG 320 subcode 1

Message ID 20250408155527.123341-7-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
DIAG 320 subcode 1 provides information needed to determine
the amount of storage to store one or more certificates.

The subcode value is denoted by setting the left-most bit
of an 8-byte field.

The verification-certificate-storage-size block (VCSSB) contains
the output data when the operation completes successfully.

Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
---
 include/hw/s390x/ipl/diag320.h | 25 ++++++++++++++++++++++
 target/s390x/diag.c            | 39 +++++++++++++++++++++++++++++++++-
 2 files changed, 63 insertions(+), 1 deletion(-)

Comments

Thomas Huth April 11, 2025, 1:57 p.m. UTC | #1
On 08/04/2025 17.55, Zhuoying Cai wrote:
> DIAG 320 subcode 1 provides information needed to determine
> the amount of storage to store one or more certificates.
> 
> The subcode value is denoted by setting the left-most bit
> of an 8-byte field.
> 
> The verification-certificate-storage-size block (VCSSB) contains
> the output data when the operation completes successfully.
> 
> Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
> ---
>   include/hw/s390x/ipl/diag320.h | 25 ++++++++++++++++++++++
>   target/s390x/diag.c            | 39 +++++++++++++++++++++++++++++++++-
>   2 files changed, 63 insertions(+), 1 deletion(-)
> 
> diff --git a/include/hw/s390x/ipl/diag320.h b/include/hw/s390x/ipl/diag320.h
> index d6f70c65df..ded336df25 100644
> --- a/include/hw/s390x/ipl/diag320.h
> +++ b/include/hw/s390x/ipl/diag320.h
> @@ -13,7 +13,32 @@
>   #define S390X_DIAG320_H
>   
>   #define DIAG_320_SUBC_QUERY_ISM     0
> +#define DIAG_320_SUBC_QUERY_VCSI    1
>   
>   #define DIAG_320_RC_OK              0x0001
> +#define DIAG_320_RC_NOMEM           0x0202
> +
> +#define VCSSB_MAX_LEN   128
> +#define VCE_HEADER_LEN  128
> +#define VCB_HEADER_LEN  64
> +
> +#define DIAG_320_ISM_QUERY_VCSI     0x4000000000000000
> +
> +struct VerificationCertificateStorageSizeBlock {
> +    uint32_t length;
> +    uint8_t reserved0[3];
> +    uint8_t version;
> +    uint32_t reserved1[6];
> +    uint16_t totalvc;
> +    uint16_t maxvc;
> +    uint32_t reserved3[7];
> +    uint32_t maxvcelen;
> +    uint32_t reserved4[3];
> +    uint32_t largestvcblen;
> +    uint32_t totalvcblen;
> +    uint32_t reserved5[10];
> +} QEMU_PACKED;
> +typedef struct VerificationCertificateStorageSizeBlock \
> +VerificationCertificateStorageSizeBlock;

That's quite a long name, maybe shorten to VerificationCertStorageBlock or 
something similar?

>   
>   #endif
> diff --git a/target/s390x/diag.c b/target/s390x/diag.c
> index c64b935c87..cc639819ec 100644
> --- a/target/s390x/diag.c
> +++ b/target/s390x/diag.c
> @@ -194,6 +194,7 @@ out:
>   void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
>   {
>       S390CPU *cpu = env_archcpu(env);
> +    S390IPLCertificateStore *qcs = s390_ipl_get_certificate_store();
>       uint64_t subcode = env->regs[r3];
>       uint64_t addr = env->regs[r1];
>       int rc;
> @@ -210,7 +211,7 @@ void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
>   
>       switch (subcode) {
>       case DIAG_320_SUBC_QUERY_ISM:
> -        uint64_t ism =  0;
> +        uint64_t ism = DIAG_320_ISM_QUERY_VCSI;

That likely should be a cpu_to_be64(DIAG_320_ISM_QUERY_VCSI) instead.

>   
>           if (s390_cpu_virt_mem_write(cpu, addr, (uint8_t)r1, &ism,
>                                       be64_to_cpu(sizeof(ism)))) {
> @@ -218,6 +219,42 @@ void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
>               return;
>           }
>   
> +        rc = DIAG_320_RC_OK;
> +        break;
> +    case DIAG_320_SUBC_QUERY_VCSI:
> +        VerificationCertificateStorageSizeBlock vcssb;
> +
> +        if (!diag_parm_addr_valid(addr, sizeof(VerificationCertificateStorageSizeBlock),
> +                                  true)) {
> +            s390_program_interrupt(env, PGM_ADDRESSING, ra);
> +            return;
> +        }
> +
> +        if (!qcs || !qcs->count) {
> +            vcssb.length = 4;
> +        } else {
> +            vcssb.length = VCSSB_MAX_LEN;
> +            vcssb.version = 0;
> +            vcssb.totalvc = qcs->count;
> +            vcssb.maxvc = MAX_CERTIFICATES;
> +            vcssb.maxvcelen = VCE_HEADER_LEN + qcs->max_cert_size;
> +            vcssb.largestvcblen = VCB_HEADER_LEN + vcssb.maxvcelen;
> +            vcssb.totalvcblen = VCB_HEADER_LEN + qcs->count * VCE_HEADER_LEN +
> +                                qcs->total_bytes;

You also need cpu_to_beXX() for these values here, too.

> +        }
> +
> +        if (vcssb.length < 128) {
> +            rc = DIAG_320_RC_NOMEM;
> +            break;
> +        }
> +
> +        if (s390_cpu_virt_mem_write(cpu, addr, (uint8_t)r1, &vcssb,
> +                                    be64_to_cpu(

And that be64_to_cpu() is wrong here.

  Thomas

> +                                        sizeof(VerificationCertificateStorageSizeBlock)
> +                                    ))) {
> +            s390_cpu_virt_mem_handle_exc(cpu, ra);
> +            return;
> +        }
>           rc = DIAG_320_RC_OK;
>           break;
>       default:
Farhan Ali April 11, 2025, 5:40 p.m. UTC | #2
On 4/8/2025 8:55 AM, Zhuoying Cai wrote:
> DIAG 320 subcode 1 provides information needed to determine
> the amount of storage to store one or more certificates.
>
> The subcode value is denoted by setting the left-most bit
> of an 8-byte field.
>
> The verification-certificate-storage-size block (VCSSB) contains
> the output data when the operation completes successfully.
>
> Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
> ---
>   include/hw/s390x/ipl/diag320.h | 25 ++++++++++++++++++++++
>   target/s390x/diag.c            | 39 +++++++++++++++++++++++++++++++++-
>   2 files changed, 63 insertions(+), 1 deletion(-)
>
> diff --git a/include/hw/s390x/ipl/diag320.h b/include/hw/s390x/ipl/diag320.h
> index d6f70c65df..ded336df25 100644
> --- a/include/hw/s390x/ipl/diag320.h
> +++ b/include/hw/s390x/ipl/diag320.h
> @@ -13,7 +13,32 @@
>   #define S390X_DIAG320_H
>   
>   #define DIAG_320_SUBC_QUERY_ISM     0
> +#define DIAG_320_SUBC_QUERY_VCSI    1
>   
>   #define DIAG_320_RC_OK              0x0001
> +#define DIAG_320_RC_NOMEM           0x0202
> +
> +#define VCSSB_MAX_LEN   128
> +#define VCE_HEADER_LEN  128
> +#define VCB_HEADER_LEN  64
> +
> +#define DIAG_320_ISM_QUERY_VCSI     0x4000000000000000
> +
> +struct VerificationCertificateStorageSizeBlock {
> +    uint32_t length;
> +    uint8_t reserved0[3];
> +    uint8_t version;
> +    uint32_t reserved1[6];
> +    uint16_t totalvc;
> +    uint16_t maxvc;
> +    uint32_t reserved3[7];
> +    uint32_t maxvcelen;
> +    uint32_t reserved4[3];
> +    uint32_t largestvcblen;
> +    uint32_t totalvcblen;
> +    uint32_t reserved5[10];
> +} QEMU_PACKED;
> +typedef struct VerificationCertificateStorageSizeBlock \
> +VerificationCertificateStorageSizeBlock;
>   
>   #endif
> diff --git a/target/s390x/diag.c b/target/s390x/diag.c
> index c64b935c87..cc639819ec 100644
> --- a/target/s390x/diag.c
> +++ b/target/s390x/diag.c
> @@ -194,6 +194,7 @@ out:
>   void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
>   {
>       S390CPU *cpu = env_archcpu(env);
> +    S390IPLCertificateStore *qcs = s390_ipl_get_certificate_store();
>       uint64_t subcode = env->regs[r3];
>       uint64_t addr = env->regs[r1];
>       int rc;
> @@ -210,7 +211,7 @@ void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
>   
>       switch (subcode) {
>       case DIAG_320_SUBC_QUERY_ISM:
> -        uint64_t ism =  0;
> +        uint64_t ism = DIAG_320_ISM_QUERY_VCSI;
>   
>           if (s390_cpu_virt_mem_write(cpu, addr, (uint8_t)r1, &ism,
>                                       be64_to_cpu(sizeof(ism)))) {
> @@ -218,6 +219,42 @@ void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
>               return;
>           }
>   
> +        rc = DIAG_320_RC_OK;
> +        break;
> +    case DIAG_320_SUBC_QUERY_VCSI:
> +        VerificationCertificateStorageSizeBlock vcssb;
> +
> +        if (!diag_parm_addr_valid(addr, sizeof(VerificationCertificateStorageSizeBlock),
> +                                  true)) {
> +            s390_program_interrupt(env, PGM_ADDRESSING, ra);
> +            return;
> +        }
> +
> +        if (!qcs || !qcs->count) {
> +            vcssb.length = 4;
> +        } else {
> +            vcssb.length = VCSSB_MAX_LEN;
> +            vcssb.version = 0;
> +            vcssb.totalvc = qcs->count;
> +            vcssb.maxvc = MAX_CERTIFICATES;
> +            vcssb.maxvcelen = VCE_HEADER_LEN + qcs->max_cert_size;
> +            vcssb.largestvcblen = VCB_HEADER_LEN + vcssb.maxvcelen;
> +            vcssb.totalvcblen = VCB_HEADER_LEN + qcs->count * VCE_HEADER_LEN +
> +                                qcs->total_bytes;
> +        }
> +

Do we need this if check below? or can we move it above where we check 
for !qcs || !qcs->count?

> +        if (vcssb.length < 128) {
> +            rc = DIAG_320_RC_NOMEM;
> +            break;
> +        }
> +
> +        if (s390_cpu_virt_mem_write(cpu, addr, (uint8_t)r1, &vcssb,
> +                                    be64_to_cpu(
> +                                        sizeof(VerificationCertificateStorageSizeBlock)
> +                                    ))) {
> +            s390_cpu_virt_mem_handle_exc(cpu, ra);
> +            return;
> +        }
>           rc = DIAG_320_RC_OK;
>           break;
>       default:
Collin Walling April 17, 2025, 7:57 p.m. UTC | #3
On 4/11/25 9:57 AM, Thomas Huth wrote:
> On 08/04/2025 17.55, Zhuoying Cai wrote:
>> DIAG 320 subcode 1 provides information needed to determine
>> the amount of storage to store one or more certificates.
>>
>> The subcode value is denoted by setting the left-most bit
>> of an 8-byte field.
>>
>> The verification-certificate-storage-size block (VCSSB) contains
>> the output data when the operation completes successfully.
>>
>> Signed-off-by: Zhuoying Cai <zycai@linux.ibm.com>
>> ---
>>   include/hw/s390x/ipl/diag320.h | 25 ++++++++++++++++++++++
>>   target/s390x/diag.c            | 39 +++++++++++++++++++++++++++++++++-
>>   2 files changed, 63 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/hw/s390x/ipl/diag320.h b/include/hw/s390x/ipl/diag320.h
>> index d6f70c65df..ded336df25 100644
>> --- a/include/hw/s390x/ipl/diag320.h
>> +++ b/include/hw/s390x/ipl/diag320.h
>> @@ -13,7 +13,32 @@
>>   #define S390X_DIAG320_H
>>   
>>   #define DIAG_320_SUBC_QUERY_ISM     0
>> +#define DIAG_320_SUBC_QUERY_VCSI    1
>>   
>>   #define DIAG_320_RC_OK              0x0001
>> +#define DIAG_320_RC_NOMEM           0x0202
>> +
>> +#define VCSSB_MAX_LEN   128
>> +#define VCE_HEADER_LEN  128
>> +#define VCB_HEADER_LEN  64
>> +
>> +#define DIAG_320_ISM_QUERY_VCSI     0x4000000000000000
>> +
>> +struct VerificationCertificateStorageSizeBlock {
>> +    uint32_t length;
>> +    uint8_t reserved0[3];
>> +    uint8_t version;
>> +    uint32_t reserved1[6];
>> +    uint16_t totalvc;
>> +    uint16_t maxvc;
>> +    uint32_t reserved3[7];
>> +    uint32_t maxvcelen;
>> +    uint32_t reserved4[3];
>> +    uint32_t largestvcblen;
>> +    uint32_t totalvcblen;
>> +    uint32_t reserved5[10];
>> +} QEMU_PACKED;
>> +typedef struct VerificationCertificateStorageSizeBlock \
>> +VerificationCertificateStorageSizeBlock;
> 
> That's quite a long name, maybe shorten to VerificationCertStorageBlock or 
> something similar?
> 

I think it would benefit many of the data structures using the
"VerificationCertificate" prefix to be short-handed to "VC".

[...]
diff mbox series

Patch

diff --git a/include/hw/s390x/ipl/diag320.h b/include/hw/s390x/ipl/diag320.h
index d6f70c65df..ded336df25 100644
--- a/include/hw/s390x/ipl/diag320.h
+++ b/include/hw/s390x/ipl/diag320.h
@@ -13,7 +13,32 @@ 
 #define S390X_DIAG320_H
 
 #define DIAG_320_SUBC_QUERY_ISM     0
+#define DIAG_320_SUBC_QUERY_VCSI    1
 
 #define DIAG_320_RC_OK              0x0001
+#define DIAG_320_RC_NOMEM           0x0202
+
+#define VCSSB_MAX_LEN   128
+#define VCE_HEADER_LEN  128
+#define VCB_HEADER_LEN  64
+
+#define DIAG_320_ISM_QUERY_VCSI     0x4000000000000000
+
+struct VerificationCertificateStorageSizeBlock {
+    uint32_t length;
+    uint8_t reserved0[3];
+    uint8_t version;
+    uint32_t reserved1[6];
+    uint16_t totalvc;
+    uint16_t maxvc;
+    uint32_t reserved3[7];
+    uint32_t maxvcelen;
+    uint32_t reserved4[3];
+    uint32_t largestvcblen;
+    uint32_t totalvcblen;
+    uint32_t reserved5[10];
+} QEMU_PACKED;
+typedef struct VerificationCertificateStorageSizeBlock \
+VerificationCertificateStorageSizeBlock;
 
 #endif
diff --git a/target/s390x/diag.c b/target/s390x/diag.c
index c64b935c87..cc639819ec 100644
--- a/target/s390x/diag.c
+++ b/target/s390x/diag.c
@@ -194,6 +194,7 @@  out:
 void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
 {
     S390CPU *cpu = env_archcpu(env);
+    S390IPLCertificateStore *qcs = s390_ipl_get_certificate_store();
     uint64_t subcode = env->regs[r3];
     uint64_t addr = env->regs[r1];
     int rc;
@@ -210,7 +211,7 @@  void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
 
     switch (subcode) {
     case DIAG_320_SUBC_QUERY_ISM:
-        uint64_t ism =  0;
+        uint64_t ism = DIAG_320_ISM_QUERY_VCSI;
 
         if (s390_cpu_virt_mem_write(cpu, addr, (uint8_t)r1, &ism,
                                     be64_to_cpu(sizeof(ism)))) {
@@ -218,6 +219,42 @@  void handle_diag_320(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra)
             return;
         }
 
+        rc = DIAG_320_RC_OK;
+        break;
+    case DIAG_320_SUBC_QUERY_VCSI:
+        VerificationCertificateStorageSizeBlock vcssb;
+
+        if (!diag_parm_addr_valid(addr, sizeof(VerificationCertificateStorageSizeBlock),
+                                  true)) {
+            s390_program_interrupt(env, PGM_ADDRESSING, ra);
+            return;
+        }
+
+        if (!qcs || !qcs->count) {
+            vcssb.length = 4;
+        } else {
+            vcssb.length = VCSSB_MAX_LEN;
+            vcssb.version = 0;
+            vcssb.totalvc = qcs->count;
+            vcssb.maxvc = MAX_CERTIFICATES;
+            vcssb.maxvcelen = VCE_HEADER_LEN + qcs->max_cert_size;
+            vcssb.largestvcblen = VCB_HEADER_LEN + vcssb.maxvcelen;
+            vcssb.totalvcblen = VCB_HEADER_LEN + qcs->count * VCE_HEADER_LEN +
+                                qcs->total_bytes;
+        }
+
+        if (vcssb.length < 128) {
+            rc = DIAG_320_RC_NOMEM;
+            break;
+        }
+
+        if (s390_cpu_virt_mem_write(cpu, addr, (uint8_t)r1, &vcssb,
+                                    be64_to_cpu(
+                                        sizeof(VerificationCertificateStorageSizeBlock)
+                                    ))) {
+            s390_cpu_virt_mem_handle_exc(cpu, ra);
+            return;
+        }
         rc = DIAG_320_RC_OK;
         break;
     default: