MachineClass *mc = MACHINE_CLASS(oc);
NMIClass *nc = NMI_CLASS(oc);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
+ S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
+ s390mc->ri_allowed = true;
mc->init = ccw_init;
mc->reset = s390_machine_reset;
mc->hot_add_cpu = s390_hot_add_cpu;
ms->dea_key_wrap = value;
}
+bool ri_allowed(void)
+{
+ if (kvm_enabled()) {
+ MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
+ if (object_class_dynamic_cast(OBJECT_CLASS(mc),
+ TYPE_S390_CCW_MACHINE)) {
+ S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
+
+ return s390mc->ri_allowed;
+ }
+ }
+ return 0;
+}
+
static inline void s390_machine_initfn(Object *obj)
{
object_property_add_bool(obj, "aes-key-wrap",
.abstract = true,
.instance_size = sizeof(S390CcwMachineState),
.instance_init = s390_machine_initfn,
+ .class_size = sizeof(S390CcwMachineClass),
.class_init = ccw_machine_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_NMI },
static void ccw_machine_2_6_class_options(MachineClass *mc)
{
+ S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
+
+ s390mc->ri_allowed = false;
ccw_machine_2_7_class_options(mc);
SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_6);
}
MachineClass parent_class;
/*< public >*/
+ bool ri_allowed;
} S390CcwMachineClass;
+/* runtime-instrumentation allowed by the machine */
+bool ri_allowed(void);
+
#endif
uint64_t gbea;
uint64_t pp;
+ uint8_t riccb[64];
+
CPU_COMMON
/* reset does memset(0) up to here */
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,
{
return 0;
}
+static inline int kvm_s390_get_ri(void)
+{
+ return 0;
+}
static inline void kvm_s390_crypto_reset(void)
{
}
}
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 */
#include "hw/s390x/ipl.h"
#include "hw/s390x/ebcdic.h"
#include "exec/memattrs.h"
+#include "hw/s390x/s390-virtio-ccw.h"
/* #define DEBUG_KVM */
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);
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;
}
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;
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;
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 = {};
}
};
+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,
.subsections = (const VMStateDescription*[]) {
&vmstate_fpu,
&vmstate_vregs,
+ &vmstate_riccb,
NULL
},
};