On 20/11/2019 12.43, Janosch Frank wrote: > For diag308 subcodes 8 - 10 we have a new ipib of type 5. The ipib > holds the address and length of the secure execution header, as well > as a list of guest components. > > Each component is a block of memory, for example kernel or initrd, > which needs to be decrypted by the Ultravisor in order to run a > protected VM. The secure execution header instructs the Ultravisor on > how to handle the protected VM and its components. > > Subcodes 8 and 9 are similiar to 5 and 6 and subcode 10 will finally > start the protected guest. > > Subcodes 8-10 are not valid in protected mode, we have to do a subcode > 3 and then the 8 and 10 combination for a protected reboot. > > Signed-off-by: Janosch Frank <fran...@linux.ibm.com> > --- [...] > diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h > index d4813105db..7b8a493509 100644 > --- a/hw/s390x/ipl.h > +++ b/hw/s390x/ipl.h > @@ -15,6 +15,24 @@ > #include "cpu.h" > #include "hw/qdev-core.h" > > +struct IPLBlockPVComp { > + uint64_t tweak_pref; > + uint64_t addr; > + uint64_t size; > +} QEMU_PACKED; > +typedef struct IPLBlockPVComp IPLBlockPVComp; > + > +struct IPLBlockPV { > + uint8_t reserved[84]; > + uint8_t reserved67[3];
What does the "67" mean here? > + uint8_t version; > + uint32_t num_comp; > + uint64_t pv_header_addr; > + uint64_t pv_header_len; > + struct IPLBlockPVComp components[]; > +} QEMU_PACKED; > +typedef struct IPLBlockPV IPLBlockPV; Given the fact that we had quite some headaches with QEMU_PACKED structs in the past already, and the structs seem to be naturally aligned ... what about dropping the QEMU_PACKED here and using QEMU_BUILD_BUG() to assert that the struct has the correct size? [...] > @@ -185,4 +211,11 @@ static inline bool iplb_valid_fcp(IplParameterBlock > *iplb) > iplb->pbt == S390_IPL_TYPE_FCP; > } > > +static inline bool iplb_valid_se(IplParameterBlock *iplb) > +{ > + return be32_to_cpu(iplb->len) >= S390_IPLB_MIN_PV_LEN && > + iplb->pbt == S390_IPL_TYPE_PV; > +} > + > + Drop one empty line? > #endif > diff --git a/target/s390x/diag.c b/target/s390x/diag.c > index 067c667ba7..32049bb4ee 100644 > --- a/target/s390x/diag.c > +++ b/target/s390x/diag.c > @@ -52,6 +52,8 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, > uint64_t r3) > #define DIAG_308_RC_OK 0x0001 > #define DIAG_308_RC_NO_CONF 0x0102 > #define DIAG_308_RC_INVALID 0x0402 > +#define DIAG_308_RC_NO_PV_CONF 0x0a02 > +#define DIAG_308_RC_INV_FOR_PV 0x0b02 > > #define DIAG308_RES_MOD_CLR 0 > #define DIAG308_RES_LOAD_NORM 1 > @@ -59,6 +61,9 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, > uint64_t r3) > #define DIAG308_LOAD_NORMAL_DUMP 4 > #define DIAG308_SET 5 > #define DIAG308_STORE 6 > +#define DIAG308_PV_SET 8 > +#define DIAG308_PV_STORE 9 > +#define DIAG308_PV_START 10 > > static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr, > uintptr_t ra, bool write) > @@ -105,6 +110,7 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, > uint64_t r3, uintptr_t ra) > s390_ipl_reset_request(cs, S390_RESET_REIPL); > break; > case DIAG308_SET: > + case DIAG308_PV_SET: /* Set SE parms */ > if (diag308_parm_check(env, r1, addr, ra, false)) { > return; > } > @@ -117,7 +123,8 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, > uint64_t r3, uintptr_t ra) > > cpu_physical_memory_read(addr, iplb, be32_to_cpu(iplb->len)); > > - if (!iplb_valid_ccw(iplb) && !iplb_valid_fcp(iplb)) { > + if (!iplb_valid_ccw(iplb) && !iplb_valid_fcp(iplb) && > + !(iplb_valid_se(iplb) && s390_ipl_pv_check_comp(iplb) >= 0)) { > env->regs[r1 + 1] = DIAG_308_RC_INVALID; > goto out; > } > @@ -128,10 +135,15 @@ out: > g_free(iplb); > return; > case DIAG308_STORE: > + case DIAG308_PV_STORE: /* Get SE parms */ > if (diag308_parm_check(env, r1, addr, ra, true)) { > return; > } > - iplb = s390_ipl_get_iplb(); > + if (subcode == DIAG308_PV_STORE) { > + iplb = s390_ipl_get_iplb_secure(); > + } else { > + iplb = s390_ipl_get_iplb(); > + } > if (iplb) { > cpu_physical_memory_write(addr, iplb, be32_to_cpu(iplb->len)); > env->regs[r1 + 1] = DIAG_308_RC_OK; > @@ -139,6 +151,16 @@ out: > env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; > } > return; > + break; <hamletmode> To return or to break, that's the question... </hamletmode> ... please choose one of the two. > + case DIAG308_PV_START: /* SE start */ > + iplb = s390_ipl_get_iplb_secure(); > + if (!iplb_valid_se(iplb)) { > + env->regs[r1 + 1] = DIAG_308_RC_NO_PV_CONF; > + return; > + } > + > + s390_ipl_reset_request(cs, S390_RESET_PV); > + break; > default: > s390_program_interrupt(env, PGM_SPECIFICATION, ra); > break; > Thomas