diff options
author | Janosch Frank <frankja@linux.ibm.com> | 2020-03-23 04:36:06 -0400 |
---|---|---|
committer | Cornelia Huck <cohuck@redhat.com> | 2020-04-29 14:30:54 +0200 |
commit | c3347ed0d2ee42a7dcf7bfe7f9c3884a9596727a (patch) | |
tree | f53ebc5ea6b896de2b8b63cbd34eac6941611737 /target/s390x | |
parent | 9b39d29470e9dbef24ee842a44ea56bd92b855ea (diff) |
s390x: protvirt: Support unpack facility
The unpack facility provides the means to setup a protected guest. A
protected guest cannot be introspected by the hypervisor or any
user/administrator of the machine it is running on.
Protected guests are encrypted at rest and need a special boot
mechanism via diag308 subcode 8 and 10.
Code 8 sets the PV specific IPLB which is retained separately from
those set via code 5.
Code 10 is used to unpack the VM into protected memory, verify its
integrity and start it.
Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Co-developed-by: Christian Borntraeger <borntraeger@de.ibm.com> [Changes
to machine]
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20200323083606.24520-1-frankja@linux.ibm.com>
[CH: fixed up KVM_PV_VM_ -> KVM_PV_]
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Diffstat (limited to 'target/s390x')
-rw-r--r-- | target/s390x/cpu.c | 1 | ||||
-rw-r--r-- | target/s390x/cpu_features_def.inc.h | 1 | ||||
-rw-r--r-- | target/s390x/diag.c | 39 | ||||
-rw-r--r-- | target/s390x/kvm-stub.c | 5 | ||||
-rw-r--r-- | target/s390x/kvm.c | 5 | ||||
-rw-r--r-- | target/s390x/kvm_s390x.h | 1 |
6 files changed, 50 insertions, 2 deletions
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index 427a46e3e1..bb7a588e3b 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -37,6 +37,7 @@ #include "sysemu/hw_accel.h" #include "hw/qdev-properties.h" #ifndef CONFIG_USER_ONLY +#include "hw/s390x/pv.h" #include "hw/boards.h" #include "sysemu/arch_init.h" #include "sysemu/sysemu.h" diff --git a/target/s390x/cpu_features_def.inc.h b/target/s390x/cpu_features_def.inc.h index 31dff0d84e..60db28351d 100644 --- a/target/s390x/cpu_features_def.inc.h +++ b/target/s390x/cpu_features_def.inc.h @@ -107,6 +107,7 @@ DEF_FEAT(DEFLATE_BASE, "deflate-base", STFL, 151, "Deflate-conversion facility ( DEF_FEAT(VECTOR_PACKED_DECIMAL_ENH, "vxpdeh", STFL, 152, "Vector-Packed-Decimal-Enhancement Facility") DEF_FEAT(MSA_EXT_9, "msa9-base", STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)") DEF_FEAT(ETOKEN, "etoken", STFL, 156, "Etoken facility") +DEF_FEAT(UNPACK, "unpack", STFL, 161, "Unpack facility") /* Features exposed via SCLP SCCB Byte 80 - 98 (bit numbers relative to byte-80) */ DEF_FEAT(SIE_GSLS, "gsls", SCLP_CONF_CHAR, 40, "SIE: Guest-storage-limit-suppression facility") diff --git a/target/s390x/diag.c b/target/s390x/diag.c index 8aba6341f9..b2cbefb8cf 100644 --- a/target/s390x/diag.c +++ b/target/s390x/diag.c @@ -20,6 +20,8 @@ #include "sysemu/cpus.h" #include "hw/s390x/ipl.h" #include "hw/s390x/s390-virtio-ccw.h" +#include "hw/s390x/pv.h" +#include "kvm_s390x.h" int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) { @@ -52,6 +54,10 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr, uintptr_t ra, bool write) { + /* Handled by the Ultravisor */ + if (s390_is_pv()) { + return 0; + } if ((r1 & 1) || (addr & ~TARGET_PAGE_MASK)) { s390_program_interrupt(env, PGM_SPECIFICATION, ra); return -1; @@ -67,6 +73,7 @@ static int diag308_parm_check(CPUS390XState *env, uint64_t r1, uint64_t addr, void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) { + bool valid; CPUState *cs = env_cpu(env); uint64_t addr = env->regs[r1]; uint64_t subcode = env->regs[r3]; @@ -82,6 +89,11 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) return; } + if (subcode >= DIAG308_PV_SET && !s390_has_feat(S390_FEAT_UNPACK)) { + s390_program_interrupt(env, PGM_SPECIFICATION, ra); + return; + } + switch (subcode) { case DIAG308_RESET_MOD_CLR: s390_ipl_reset_request(cs, S390_RESET_MODIFIED_CLEAR); @@ -94,6 +106,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: if (diag308_parm_check(env, r1, addr, ra, false)) { return; } @@ -106,7 +119,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(iplb)) { + valid = subcode == DIAG308_PV_SET ? iplb_valid_pv(iplb) : iplb_valid(iplb); + if (!valid) { env->regs[r1 + 1] = DIAG_308_RC_INVALID; goto out; } @@ -117,10 +131,15 @@ out: g_free(iplb); return; case DIAG308_STORE: + case DIAG308_PV_STORE: 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_pv(); + } 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; @@ -128,6 +147,22 @@ out: env->regs[r1 + 1] = DIAG_308_RC_NO_CONF; } return; + case DIAG308_PV_START: + iplb = s390_ipl_get_iplb_pv(); + if (!iplb) { + env->regs[r1 + 1] = DIAG_308_RC_NO_PV_CONF; + return; + } + + if (kvm_s390_get_hpage_1m()) { + error_report("Protected VMs can currently not be backed with " + "huge pages"); + env->regs[r1 + 1] = DIAG_308_RC_INVAL_FOR_PV; + return; + } + + s390_ipl_reset_request(cs, S390_RESET_PV); + break; default: s390_program_interrupt(env, PGM_SPECIFICATION, ra); break; diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c index c4cd497f85..aa185017a2 100644 --- a/target/s390x/kvm-stub.c +++ b/target/s390x/kvm-stub.c @@ -39,6 +39,11 @@ int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu) return 0; } +int kvm_s390_get_hpage_1m(void) +{ + return 0; +} + int kvm_s390_get_ri(void) { return 0; diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index 7f7ebab842..b2b14bde2b 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -321,6 +321,11 @@ void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp) cap_hpage_1m = 1; } +int kvm_s390_get_hpage_1m(void) +{ + return cap_hpage_1m; +} + static void ccw_machine_class_foreach(ObjectClass *oc, void *opaque) { MachineClass *mc = MACHINE_CLASS(oc); diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h index 0b21789796..dea813f450 100644 --- a/target/s390x/kvm_s390x.h +++ b/target/s390x/kvm_s390x.h @@ -23,6 +23,7 @@ void kvm_s390_program_interrupt(S390CPU *cpu, uint16_t code); int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state); void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu); int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu); +int kvm_s390_get_hpage_1m(void); int kvm_s390_get_ri(void); int kvm_s390_get_gs(void); int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock); |