提交 9700230b 编写于 作者: F Fan Zhang 提交者: Cornelia Huck

s390x: enable runtime instrumentation

Introduce run-time-instrumentation support when running under kvm for
virtio-ccw 2.7 machine and make sure older machines can not enable it.

The new ri_allowed field in the s390MachineClass serves as an indicator
whether the feature can be used by the machine and should therefore be
activated if available.

riccb_needed() is used to check whether riccb is needed or not in live
migration.
Signed-off-by: NFan Zhang <zhangfan@linux.vnet.ibm.com>
Signed-off-by: NCornelia Huck <cornelia.huck@de.ibm.com>
上级 946e55f3
...@@ -190,7 +190,9 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data) ...@@ -190,7 +190,9 @@ static void ccw_machine_class_init(ObjectClass *oc, void *data)
MachineClass *mc = MACHINE_CLASS(oc); MachineClass *mc = MACHINE_CLASS(oc);
NMIClass *nc = NMI_CLASS(oc); NMIClass *nc = NMI_CLASS(oc);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
S390CcwMachineClass *s390mc = S390_MACHINE_CLASS(mc);
s390mc->ri_allowed = true;
mc->init = ccw_init; mc->init = ccw_init;
mc->reset = s390_machine_reset; mc->reset = s390_machine_reset;
mc->hot_add_cpu = s390_hot_add_cpu; mc->hot_add_cpu = s390_hot_add_cpu;
...@@ -237,6 +239,20 @@ static inline void machine_set_dea_key_wrap(Object *obj, bool value, ...@@ -237,6 +239,20 @@ static inline void machine_set_dea_key_wrap(Object *obj, bool value,
ms->dea_key_wrap = value; 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) static inline void s390_machine_initfn(Object *obj)
{ {
object_property_add_bool(obj, "aes-key-wrap", object_property_add_bool(obj, "aes-key-wrap",
...@@ -262,6 +278,7 @@ static const TypeInfo ccw_machine_info = { ...@@ -262,6 +278,7 @@ static const TypeInfo ccw_machine_info = {
.abstract = true, .abstract = true,
.instance_size = sizeof(S390CcwMachineState), .instance_size = sizeof(S390CcwMachineState),
.instance_init = s390_machine_initfn, .instance_init = s390_machine_initfn,
.class_size = sizeof(S390CcwMachineClass),
.class_init = ccw_machine_class_init, .class_init = ccw_machine_class_init,
.interfaces = (InterfaceInfo[]) { .interfaces = (InterfaceInfo[]) {
{ TYPE_NMI }, { TYPE_NMI },
...@@ -363,6 +380,9 @@ static void ccw_machine_2_6_instance_options(MachineState *machine) ...@@ -363,6 +380,9 @@ static void ccw_machine_2_6_instance_options(MachineState *machine)
static void ccw_machine_2_6_class_options(MachineClass *mc) 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); ccw_machine_2_7_class_options(mc);
SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_6); SET_MACHINE_COMPAT(mc, CCW_COMPAT_2_6);
} }
......
...@@ -35,6 +35,10 @@ typedef struct S390CcwMachineClass { ...@@ -35,6 +35,10 @@ typedef struct S390CcwMachineClass {
MachineClass parent_class; MachineClass parent_class;
/*< public >*/ /*< public >*/
bool ri_allowed;
} S390CcwMachineClass; } S390CcwMachineClass;
/* runtime-instrumentation allowed by the machine */
bool ri_allowed(void);
#endif #endif
...@@ -135,6 +135,8 @@ typedef struct CPUS390XState { ...@@ -135,6 +135,8 @@ typedef struct CPUS390XState {
uint64_t gbea; uint64_t gbea;
uint64_t pp; uint64_t pp;
uint8_t riccb[64];
CPU_COMMON CPU_COMMON
/* reset does memset(0) up to here */ /* reset does memset(0) up to here */
...@@ -1159,6 +1161,7 @@ void kvm_s390_reset_vcpu(S390CPU *cpu); ...@@ -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); 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); void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu);
int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu); int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu);
int kvm_s390_get_ri(void);
void kvm_s390_crypto_reset(void); void kvm_s390_crypto_reset(void);
#else #else
static inline void kvm_s390_io_interrupt(uint16_t subchannel_id, 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) ...@@ -1209,6 +1212,10 @@ static inline int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu)
{ {
return 0; return 0;
} }
static inline int kvm_s390_get_ri(void)
{
return 0;
}
static inline void kvm_s390_crypto_reset(void) static inline void kvm_s390_crypto_reset(void)
{ {
} }
...@@ -1272,11 +1279,22 @@ static inline bool vregs_needed(void *opaque) ...@@ -1272,11 +1279,22 @@ static inline bool vregs_needed(void *opaque)
} }
return 0; return 0;
} }
static inline bool riccb_needed(void *opaque)
{
if (kvm_enabled()) {
return kvm_s390_get_ri();
}
return 0;
}
#else #else
static inline bool vregs_needed(void *opaque) static inline bool vregs_needed(void *opaque)
{ {
return 0; return 0;
} }
static inline bool riccb_needed(void *opaque)
{
return 0;
}
#endif #endif
/* machine check interruption code */ /* machine check interruption code */
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include "hw/s390x/ipl.h" #include "hw/s390x/ipl.h"
#include "hw/s390x/ebcdic.h" #include "hw/s390x/ebcdic.h"
#include "exec/memattrs.h" #include "exec/memattrs.h"
#include "hw/s390x/s390-virtio-ccw.h"
/* #define DEBUG_KVM */ /* #define DEBUG_KVM */
...@@ -135,6 +136,7 @@ static int cap_sync_regs; ...@@ -135,6 +136,7 @@ static int cap_sync_regs;
static int cap_async_pf; static int cap_async_pf;
static int cap_mem_op; static int cap_mem_op;
static int cap_s390_irq; static int cap_s390_irq;
static int cap_ri;
static void *legacy_s390_alloc(size_t size, uint64_t *align); static void *legacy_s390_alloc(size_t size, uint64_t *align);
...@@ -270,6 +272,11 @@ int kvm_arch_init(MachineState *ms, KVMState *s) ...@@ -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_USER_SIGP, 0);
kvm_vm_enable_cap(s, KVM_CAP_S390_VECTOR_REGISTERS, 0); kvm_vm_enable_cap(s, KVM_CAP_S390_VECTOR_REGISTERS, 0);
kvm_vm_enable_cap(s, KVM_CAP_S390_USER_STSI, 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; return 0;
} }
...@@ -386,6 +393,11 @@ int kvm_arch_put_registers(CPUState *cs, int level) ...@@ -386,6 +393,11 @@ int kvm_arch_put_registers(CPUState *cs, int level)
kvm_set_one_reg(cs, KVM_REG_S390_PP, &env->pp); 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 */ /* pfault parameters */
if (can_sync_regs(cs, KVM_SYNC_PFAULT)) { if (can_sync_regs(cs, KVM_SYNC_PFAULT)) {
cs->kvm_run->s.regs.pft = env->pfault_token; cs->kvm_run->s.regs.pft = env->pfault_token;
...@@ -528,6 +540,10 @@ int kvm_arch_get_registers(CPUState *cs) ...@@ -528,6 +540,10 @@ int kvm_arch_get_registers(CPUState *cs)
kvm_get_one_reg(cs, KVM_REG_S390_PP, &env->pp); 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 */ /* pfault parameters */
if (can_sync_regs(cs, KVM_SYNC_PFAULT)) { if (can_sync_regs(cs, KVM_SYNC_PFAULT)) {
env->pfault_token = cs->kvm_run->s.regs.pft; env->pfault_token = cs->kvm_run->s.regs.pft;
...@@ -2136,6 +2152,11 @@ int kvm_s390_get_memslot_count(KVMState *s) ...@@ -2136,6 +2152,11 @@ int kvm_s390_get_memslot_count(KVMState *s)
return kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS); 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) int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state)
{ {
struct kvm_mp_state mp_state = {}; struct kvm_mp_state mp_state = {};
......
...@@ -135,6 +135,17 @@ static const VMStateDescription vmstate_vregs = { ...@@ -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 = { const VMStateDescription vmstate_s390_cpu = {
.name = "cpu", .name = "cpu",
.post_load = cpu_post_load, .post_load = cpu_post_load,
...@@ -166,6 +177,7 @@ const VMStateDescription vmstate_s390_cpu = { ...@@ -166,6 +177,7 @@ const VMStateDescription vmstate_s390_cpu = {
.subsections = (const VMStateDescription*[]) { .subsections = (const VMStateDescription*[]) {
&vmstate_fpu, &vmstate_fpu,
&vmstate_vregs, &vmstate_vregs,
&vmstate_riccb,
NULL NULL
}, },
}; };
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册