diff options
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); |