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 |
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:
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:
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 --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:
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(-)