@@ -676,7 +676,8 @@ 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(Error **errp, uint16_t *pv_cmd,
+ uint16_t *pv_rc, uint16_t *pv_rrc)
{
IplParameterBlock *ipib = s390_ipl_get_iplb_pv();
IPLBlockPV *ipib_pv = &ipib->pv;
@@ -685,12 +686,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,
+ errp, pv_cmd, pv_rc, pv_rrc);
g_free(hdr);
return rc;
}
-int s390_ipl_pv_unpack(void)
+int s390_ipl_pv_unpack(uint16_t *pv_cmd, uint16_t *pv_rc, uint16_t *pv_rrc)
{
IplParameterBlock *ipib = s390_ipl_get_iplb_pv();
IPLBlockPV *ipib_pv = &ipib->pv;
@@ -699,7 +701,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_cmd, pv_rc, pv_rrc);
if (rc) {
break;
}
@@ -26,8 +26,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(Error **errp, uint16_t *pv_cmd,
+ uint16_t *pv_rc, uint16_t *pv_rrc);
+int s390_ipl_pv_unpack(uint16_t *pv_cmd, uint16_t *pv_rc, uint16_t *pv_rrc);
void s390_ipl_prepare_cpu(S390CPU *cpu);
IplParameterBlock *s390_ipl_get_iplb(void);
IplParameterBlock *s390_ipl_get_iplb_pv(void);
@@ -53,6 +53,13 @@
static Error *pv_mig_blocker;
+struct diag308response {
+ uint16_t pv_cmd;
+ uint16_t pv_rrc;
+ uint16_t pv_rc;
+ uint16_t diag_rc;
+};
+
static S390CPU *s390x_new_cpu(const char *typename, uint32_t core_id,
Error **errp)
{
@@ -364,7 +371,10 @@ 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,
+ uint16_t *pv_cmd,
+ uint16_t *pv_rc,
+ uint16_t *pv_rrc)
{
Error *local_err = NULL;
int rc;
@@ -407,19 +417,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(&local_err, pv_cmd, pv_rc, pv_rrc);
if (rc) {
goto out_err;
}
/* Decrypt image */
- rc = s390_ipl_pv_unpack();
+ rc = s390_ipl_pv_unpack(pv_cmd, pv_rc, pv_rrc);
if (rc) {
goto out_err;
}
/* Verify integrity */
- rc = s390_pv_verify();
+ rc = s390_pv_verify(pv_cmd, pv_rc, pv_rrc);
if (rc) {
goto out_err;
}
@@ -452,6 +462,7 @@ static void s390_machine_reset(MachineState *machine, ResetType type)
{
S390CcwMachineState *ms = S390_CCW_MACHINE(machine);
enum s390_reset reset_type;
+ struct diag308response resp;
CPUState *cs, *t;
S390CPU *cpu;
@@ -539,8 +550,9 @@ 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, &resp.pv_cmd, &resp.pv_rc, &resp.pv_rrc)) {
+ resp.diag_rc = DIAG_308_RC_INVAL_FOR_PV;
+ s390_pv_inject_reset_error(cs, (uint64_t *)(&resp));
/*
* Continue after the diag308 so the guest knows something
* went wrong.
@@ -30,7 +30,7 @@ static struct kvm_s390_pv_info_vm info_vm;
static struct kvm_s390_pv_info_dump info_dump;
static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data,
- int *pvrc)
+ uint16_t *pv_rc, uint16_t *pv_rrc)
{
struct kvm_pv_cmd pv_cmd = {
.cmd = cmd,
@@ -47,9 +47,13 @@ static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data,
"IOCTL rc: %d", cmd, cmdname, pv_cmd.rc, pv_cmd.rrc,
rc);
}
- if (pvrc) {
- *pvrc = pv_cmd.rc;
+ if (pv_rc) {
+ *pv_rc = pv_cmd.rc;
}
+ if (pv_rrc) {
+ *pv_rrc = pv_cmd.rrc;
+ }
+
return rc;
}
@@ -57,8 +61,11 @@ static int __s390_pv_cmd(uint32_t cmd, const char *cmdname, void *data,
* This macro lets us pass the command as a string to the function so
* we can print it on an error.
*/
-#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data, NULL)
-#define s390_pv_cmd_pvrc(cmd, data, pvrc) __s390_pv_cmd(cmd, #cmd, data, pvrc)
+#define s390_pv_cmd(cmd, data) __s390_pv_cmd(cmd, #cmd, data, NULL, NULL)
+#define s390_pv_cmd_pvrc(cmd, data, pv_rc) \
+ __s390_pv_cmd(cmd, #cmd, data, pv_rc, NULL)
+#define s390_pv_cmd_pvrc_pvrrc(cmd, data, pv_rc, pv_rrc) \
+ __s390_pv_cmd(cmd, #cmd, data, pv_rc, pv_rrc)
static void s390_pv_cmd_exit(uint32_t cmd, void *data)
{
@@ -149,18 +156,21 @@ bool s390_pv_vm_try_disable_async(S390CcwMachineState *ms)
}
#define DIAG_308_UV_RC_INVAL_HOSTKEY 0x0108
-int s390_pv_set_sec_parms(uint64_t origin, uint64_t length, Error **errp)
+int s390_pv_set_sec_parms(uint64_t origin, uint64_t length,
+ Error **errp, uint16_t *pv_cmd,
+ uint16_t *pv_rc, uint16_t *pv_rrc)
{
- int ret, pvrc;
+ int ret;
struct kvm_s390_pv_sec_parm args = {
.origin = origin,
.length = length,
};
- ret = s390_pv_cmd_pvrc(KVM_PV_SET_SEC_PARMS, &args, &pvrc);
+ *pv_cmd = KVM_PV_SET_SEC_PARMS;
+ ret = s390_pv_cmd_pvrc_pvrrc(*pv_cmd, &args, pv_rc, pv_rrc);
if (ret) {
error_setg(errp, "Failed to set secure execution parameters");
- if (pvrc == DIAG_308_UV_RC_INVAL_HOSTKEY) {
+ if (*pv_rc == DIAG_308_UV_RC_INVAL_HOSTKEY) {
error_append_hint(errp, "Please check whether the image is "
"correctly encrypted for this host\n");
}
@@ -172,7 +182,9 @@ int s390_pv_set_sec_parms(uint64_t origin, uint64_t length, Error **errp)
/*
* Called for each component in the SE type IPL parameter block 0.
*/
-int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak)
+int s390_pv_unpack(uint64_t addr, uint64_t size,
+ uint64_t tweak, uint16_t *pv_cmd,
+ uint16_t *pv_rc, uint16_t *pv_rrc)
{
struct kvm_s390_pv_unp args = {
.addr = addr,
@@ -180,7 +192,8 @@ int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak)
.tweak = tweak,
};
- return s390_pv_cmd(KVM_PV_UNPACK, &args);
+ *pv_cmd = KVM_PV_UNPACK;
+ return s390_pv_cmd_pvrc_pvrrc(*pv_cmd, &args, pv_rc, pv_rrc);
}
void s390_pv_prep_reset(void)
@@ -188,9 +201,10 @@ void s390_pv_prep_reset(void)
s390_pv_cmd_exit(KVM_PV_PREP_RESET, NULL);
}
-int s390_pv_verify(void)
+int s390_pv_verify(uint16_t *pv_cmd, uint16_t *pv_rc, uint16_t *pv_rrc)
{
- return s390_pv_cmd(KVM_PV_VERIFY, NULL);
+ *pv_cmd = KVM_PV_VERIFY;
+ return s390_pv_cmd_pvrc_pvrrc(*pv_cmd, NULL, pv_rc, pv_rrc);
}
void s390_pv_unshare(void)
@@ -198,13 +212,13 @@ void s390_pv_unshare(void)
s390_pv_cmd_exit(KVM_PV_UNSHARE_ALL, NULL);
}
-void s390_pv_inject_reset_error(CPUState *cs)
+void s390_pv_inject_reset_error(CPUState *cs, uint64_t *resp)
{
int r1 = (cs->kvm_run->s390_sieic.ipa & 0x00f0) >> 4;
CPUS390XState *env = &S390_CPU(cs)->env;
/* Report that we are unable to enter protected mode */
- env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV;
+ env->regs[r1 + 1] = *resp;
}
uint64_t kvm_s390_pv_dmp_get_size_cpu(void)
@@ -42,12 +42,16 @@ int s390_pv_query_info(void);
int s390_pv_vm_enable(void);
void s390_pv_vm_disable(void);
bool s390_pv_vm_try_disable_async(S390CcwMachineState *ms);
-int s390_pv_set_sec_parms(uint64_t origin, uint64_t length, Error **errp);
-int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak);
+int s390_pv_set_sec_parms(uint64_t origin, uint64_t length,
+ Error **errp, uint16_t *pv_cmd,
+ uint16_t *pv_rc, uint16_t *pv_rrc);
+int s390_pv_unpack(uint64_t addr, uint64_t size,
+ uint64_t tweak, uint16_t *pv_cmd,
+ uint16_t *pv_rc, uint16_t *pv_rrc);
void s390_pv_prep_reset(void);
-int s390_pv_verify(void);
+int s390_pv_verify(uint16_t *pv_cmd, uint16_t *pv_rc, uint16_t *pv_rrc);
void s390_pv_unshare(void);
-void s390_pv_inject_reset_error(CPUState *cs);
+void s390_pv_inject_reset_error(CPUState *cs, uint64_t *resp);
uint64_t kvm_s390_pv_dmp_get_size_cpu(void);
uint64_t kvm_s390_pv_dmp_get_size_mem_state(void);
uint64_t kvm_s390_pv_dmp_get_size_completion_data(void);
@@ -63,12 +67,19 @@ static inline int s390_pv_vm_enable(void) { return 0; }
static inline void s390_pv_vm_disable(void) {}
static inline bool s390_pv_vm_try_disable_async(S390CcwMachineState *ms) { return false; }
static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length,
- Error **errp) { return 0; }
-static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { return 0; }
+ Error **errp, uint16_t *pv_cmd,
+ uint16_t *pv_rc, uint16_t *pv_rrc)
+ { return 0; }
+static inline int s390_pv_unpack(uint64_t addr, uint64_t size,
+ uint64_t tweak, uint16_t *pv_cmd,
+ uint16_t *pv_rc, uint16_t *pv_rrc)
+ { return 0; }
static inline void s390_pv_prep_reset(void) {}
-static inline int s390_pv_verify(void) { return 0; }
+static inline int s390_pv_verify(uint16_t *pv_cmd,
+ uint16_t *pv_rc,
+ uint16_t *pv_rrc) { return 0; }
static inline void s390_pv_unshare(void) {}
-static inline void s390_pv_inject_reset_error(CPUState *cs) {};
+static inline void s390_pv_inject_reset_error(CPUState *cs, uint64_t *resp) {};
static inline uint64_t kvm_s390_pv_dmp_get_size_cpu(void) { return 0; }
static inline uint64_t kvm_s390_pv_dmp_get_size_mem_state(void) { return 0; }
static inline uint64_t kvm_s390_pv_dmp_get_size_completion_data(void) { return 0; }
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). Signed-off-by: Gautam Gala <ggala@linux.ibm.com> --- hw/s390x/ipl.c | 11 ++++++---- hw/s390x/ipl.h | 5 +++-- hw/s390x/s390-virtio-ccw.c | 24 +++++++++++++++------ target/s390x/kvm/pv.c | 44 +++++++++++++++++++++++++------------- target/s390x/kvm/pv.h | 27 ++++++++++++++++------- 5 files changed, 76 insertions(+), 35 deletions(-)