target/s390x: Return UVC cmd code, RC and RRC value when DIAG 308 Subcode 10 fails to enter secure mode

Extend DIAG308 subcode 10 to return the UVC RC, RRC and command code
in bit positions 32-47, 16-31, and 0-15 of register R1 + 1 if the
function does not complete successfully (in addition to the
previously returned diag response code in bit position 47-63).

Reviewed-by: Janosch Frank <frankja@linux.ibm.com>
Signed-off-by: Gautam Gala <ggala@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Message-ID: <20250423080915.1048123-4-ggala@linux.ibm.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
Gautam Gala 2025-04-23 10:09:15 +02:00 committed by Thomas Huth
parent e27cbd17dd
commit 55a494e53e
5 changed files with 73 additions and 35 deletions

View file

@ -26,7 +26,6 @@
#include "hw/s390x/vfio-ccw.h"
#include "hw/s390x/css.h"
#include "hw/s390x/ebcdic.h"
#include "target/s390x/kvm/pv.h"
#include "hw/scsi/scsi.h"
#include "hw/virtio/virtio-net.h"
#include "ipl.h"
@ -676,7 +675,7 @@ static void s390_ipl_prepare_qipl(S390CPU *cpu)
cpu_physical_memory_unmap(addr, len, 1, len);
}
int s390_ipl_prepare_pv_header(Error **errp)
int s390_ipl_prepare_pv_header(struct S390PVResponse *pv_resp, Error **errp)
{
IplParameterBlock *ipib = s390_ipl_get_iplb_pv();
IPLBlockPV *ipib_pv = &ipib->pv;
@ -685,12 +684,13 @@ int s390_ipl_prepare_pv_header(Error **errp)
cpu_physical_memory_read(ipib_pv->pv_header_addr, hdr,
ipib_pv->pv_header_len);
rc = s390_pv_set_sec_parms((uintptr_t)hdr, ipib_pv->pv_header_len, errp);
rc = s390_pv_set_sec_parms((uintptr_t)hdr, ipib_pv->pv_header_len,
pv_resp, errp);
g_free(hdr);
return rc;
}
int s390_ipl_pv_unpack(void)
int s390_ipl_pv_unpack(struct S390PVResponse *pv_resp)
{
IplParameterBlock *ipib = s390_ipl_get_iplb_pv();
IPLBlockPV *ipib_pv = &ipib->pv;
@ -699,7 +699,8 @@ int s390_ipl_pv_unpack(void)
for (i = 0; i < ipib_pv->num_comp; i++) {
rc = s390_pv_unpack(ipib_pv->components[i].addr,
TARGET_PAGE_ALIGN(ipib_pv->components[i].size),
ipib_pv->components[i].tweak_pref);
ipib_pv->components[i].tweak_pref,
pv_resp);
if (rc) {
break;
}

View file

@ -20,6 +20,7 @@
#include "hw/qdev-core.h"
#include "hw/s390x/ipl/qipl.h"
#include "qom/object.h"
#include "target/s390x/kvm/pv.h"
#define DIAG308_FLAGS_LP_VALID 0x80
#define MAX_BOOT_DEVS 8 /* Max number of devices that may have a bootindex */
@ -28,8 +29,9 @@ void s390_ipl_convert_loadparm(char *ascii_lp, uint8_t *ebcdic_lp);
void s390_ipl_fmt_loadparm(uint8_t *loadparm, char *str, Error **errp);
void s390_rebuild_iplb(uint16_t index, IplParameterBlock *iplb);
void s390_ipl_update_diag308(IplParameterBlock *iplb);
int s390_ipl_prepare_pv_header(Error **errp);
int s390_ipl_pv_unpack(void);
int s390_ipl_prepare_pv_header(struct S390PVResponse *pv_resp,
Error **errp);
int s390_ipl_pv_unpack(struct S390PVResponse *pv_resp);
void s390_ipl_prepare_cpu(S390CPU *cpu);
IplParameterBlock *s390_ipl_get_iplb(void);
IplParameterBlock *s390_ipl_get_iplb_pv(void);

View file

@ -365,7 +365,8 @@ static void s390_machine_unprotect(S390CcwMachineState *ms)
ram_block_discard_disable(false);
}
static int s390_machine_protect(S390CcwMachineState *ms)
static int s390_machine_protect(S390CcwMachineState *ms,
struct S390PVResponse *pv_resp)
{
Error *local_err = NULL;
int rc;
@ -408,19 +409,19 @@ static int s390_machine_protect(S390CcwMachineState *ms)
}
/* Set SE header and unpack */
rc = s390_ipl_prepare_pv_header(&local_err);
rc = s390_ipl_prepare_pv_header(pv_resp, &local_err);
if (rc) {
goto out_err;
}
/* Decrypt image */
rc = s390_ipl_pv_unpack();
rc = s390_ipl_pv_unpack(pv_resp);
if (rc) {
goto out_err;
}
/* Verify integrity */
rc = s390_pv_verify();
rc = s390_pv_verify(pv_resp);
if (rc) {
goto out_err;
}
@ -452,6 +453,7 @@ static void s390_pv_prepare_reset(S390CcwMachineState *ms)
static void s390_machine_reset(MachineState *machine, ResetType type)
{
S390CcwMachineState *ms = S390_CCW_MACHINE(machine);
struct S390PVResponse pv_resp;
enum s390_reset reset_type;
CPUState *cs, *t;
S390CPU *cpu;
@ -540,8 +542,8 @@ static void s390_machine_reset(MachineState *machine, ResetType type)
}
run_on_cpu(cs, s390_do_cpu_reset, RUN_ON_CPU_NULL);
if (s390_machine_protect(ms)) {
s390_pv_inject_reset_error(cs);
if (s390_machine_protect(ms, &pv_resp)) {
s390_pv_inject_reset_error(cs, pv_resp);
/*
* Continue after the diag308 so the guest knows something
* went wrong.