diff options
Diffstat (limited to 'target-s390x')
-rw-r--r-- | target-s390x/cpu.h | 18 | ||||
-rw-r--r-- | target-s390x/kvm.c | 21 | ||||
-rw-r--r-- | target-s390x/machine.c | 12 |
3 files changed, 51 insertions, 0 deletions
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 07f76ad884..996b79023e 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -135,6 +135,8 @@ typedef struct CPUS390XState { uint64_t gbea; uint64_t pp; + uint8_t riccb[64]; + CPU_COMMON /* reset does memset(0) up to here */ @@ -1159,6 +1161,7 @@ void kvm_s390_reset_vcpu(S390CPU *cpu); int kvm_s390_set_mem_limit(KVMState *s, uint64_t new_limit, uint64_t *hw_limit); void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu); int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu); +int kvm_s390_get_ri(void); void kvm_s390_crypto_reset(void); #else static inline void kvm_s390_io_interrupt(uint16_t subchannel_id, @@ -1209,6 +1212,10 @@ static inline int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu) { return 0; } +static inline int kvm_s390_get_ri(void) +{ + return 0; +} static inline void kvm_s390_crypto_reset(void) { } @@ -1272,11 +1279,22 @@ static inline bool vregs_needed(void *opaque) } return 0; } +static inline bool riccb_needed(void *opaque) +{ + if (kvm_enabled()) { + return kvm_s390_get_ri(); + } + return 0; +} #else static inline bool vregs_needed(void *opaque) { return 0; } +static inline bool riccb_needed(void *opaque) +{ + return 0; +} #endif /* machine check interruption code */ diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index e1859cae04..55ae6d3304 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -46,6 +46,7 @@ #include "hw/s390x/ipl.h" #include "hw/s390x/ebcdic.h" #include "exec/memattrs.h" +#include "hw/s390x/s390-virtio-ccw.h" /* #define DEBUG_KVM */ @@ -135,6 +136,7 @@ static int cap_sync_regs; static int cap_async_pf; static int cap_mem_op; static int cap_s390_irq; +static int cap_ri; static void *legacy_s390_alloc(size_t size, uint64_t *align); @@ -270,6 +272,11 @@ int kvm_arch_init(MachineState *ms, KVMState *s) kvm_vm_enable_cap(s, KVM_CAP_S390_USER_SIGP, 0); kvm_vm_enable_cap(s, KVM_CAP_S390_VECTOR_REGISTERS, 0); kvm_vm_enable_cap(s, KVM_CAP_S390_USER_STSI, 0); + if (ri_allowed()) { + if (kvm_vm_enable_cap(s, KVM_CAP_S390_RI, 0) == 0) { + cap_ri = 1; + } + } return 0; } @@ -386,6 +393,11 @@ int kvm_arch_put_registers(CPUState *cs, int level) kvm_set_one_reg(cs, KVM_REG_S390_PP, &env->pp); } + if (can_sync_regs(cs, KVM_SYNC_RICCB)) { + memcpy(cs->kvm_run->s.regs.riccb, env->riccb, 64); + cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_RICCB; + } + /* pfault parameters */ if (can_sync_regs(cs, KVM_SYNC_PFAULT)) { cs->kvm_run->s.regs.pft = env->pfault_token; @@ -528,6 +540,10 @@ int kvm_arch_get_registers(CPUState *cs) kvm_get_one_reg(cs, KVM_REG_S390_PP, &env->pp); } + if (can_sync_regs(cs, KVM_SYNC_RICCB)) { + memcpy(env->riccb, cs->kvm_run->s.regs.riccb, 64); + } + /* pfault parameters */ if (can_sync_regs(cs, KVM_SYNC_PFAULT)) { env->pfault_token = cs->kvm_run->s.regs.pft; @@ -2136,6 +2152,11 @@ int kvm_s390_get_memslot_count(KVMState *s) return kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS); } +int kvm_s390_get_ri(void) +{ + return cap_ri; +} + int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state) { struct kvm_mp_state mp_state = {}; diff --git a/target-s390x/machine.c b/target-s390x/machine.c index 6b2609054b..a30b16fe3d 100644 --- a/target-s390x/machine.c +++ b/target-s390x/machine.c @@ -135,6 +135,17 @@ static const VMStateDescription vmstate_vregs = { } }; +const VMStateDescription vmstate_riccb = { + .name = "cpu/riccb", + .version_id = 1, + .minimum_version_id = 1, + .needed = riccb_needed, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(env.riccb, S390CPU, 64), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_s390_cpu = { .name = "cpu", .post_load = cpu_post_load, @@ -166,6 +177,7 @@ const VMStateDescription vmstate_s390_cpu = { .subsections = (const VMStateDescription*[]) { &vmstate_fpu, &vmstate_vregs, + &vmstate_riccb, NULL }, }; |