summaryrefslogtreecommitdiff
path: root/target-s390x/kvm.c
diff options
context:
space:
mode:
authorJason J. Herne <jjherne@us.ibm.com>2013-04-25 04:25:50 +0000
committerAlexander Graf <agraf@suse.de>2013-04-26 20:18:24 +0200
commit420840e58b85f7f4e5493dca3f273566f261090a (patch)
tree5a7dc181c082e7be48acbbc871cdf54d56d99c68 /target-s390x/kvm.c
parent7dc5af5545bb72e1343cc959b3f0e5cdd8758f1f (diff)
downloadqemu-420840e58b85f7f4e5493dca3f273566f261090a.tar.gz
Allow selective runtime register synchronization
We want to avoid expensive register synchronization IOCTL's on the hot path so a new kvm_s390_get_registers_partial() is introduced as a compliment to kvm_arch_get_registers(). The new function is called on the hot path, and kvm_arch_get_registers() is called when we need the complete runtime register state. kvm_arch_put_registers() is updated to only sync the partial runtime set when we've only dirtied the partial runtime set. This is to avoid sending bad data back to KVM if we've only partially synced the runtime register set. Signed-off-by: Jason J. Herne <jjherne@us.ibm.com> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-s390x/kvm.c')
-rw-r--r--target-s390x/kvm.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 644f484c48..02b2e397a2 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -123,6 +123,7 @@ int kvm_arch_put_registers(CPUState *cs, int level)
{
S390CPU *cpu = S390_CPU(cs);
CPUS390XState *env = &cpu->env;
+ struct kvm_one_reg reg;
struct kvm_sregs sregs;
struct kvm_regs regs;
int ret;
@@ -147,6 +148,30 @@ int kvm_arch_put_registers(CPUState *cs, int level)
}
}
+ if (env->runtime_reg_dirty_mask == KVM_S390_RUNTIME_DIRTY_FULL) {
+ reg.id = KVM_REG_S390_CPU_TIMER;
+ reg.addr = (__u64)&(env->cputm);
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+ if (ret < 0) {
+ return ret;
+ }
+
+ reg.id = KVM_REG_S390_CLOCK_COMP;
+ reg.addr = (__u64)&(env->ckc);
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+ if (ret < 0) {
+ return ret;
+ }
+
+ reg.id = KVM_REG_S390_TODPR;
+ reg.addr = (__u64)&(env->todpr);
+ ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
+ if (ret < 0) {
+ return ret;
+ }
+ }
+ env->runtime_reg_dirty_mask = KVM_S390_RUNTIME_DIRTY_NONE;
+
/* Do we need to save more than that? */
if (level == KVM_PUT_RUNTIME_STATE) {
return 0;
@@ -186,11 +211,52 @@ int kvm_arch_get_registers(CPUState *cs)
{
S390CPU *cpu = S390_CPU(cs);
CPUS390XState *env = &cpu->env;
+ struct kvm_one_reg reg;
+ int r;
+
+ r = kvm_s390_get_registers_partial(cs);
+ if (r < 0) {
+ return r;
+ }
+
+ reg.id = KVM_REG_S390_CPU_TIMER;
+ reg.addr = (__u64)&(env->cputm);
+ r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+ if (r < 0) {
+ return r;
+ }
+
+ reg.id = KVM_REG_S390_CLOCK_COMP;
+ reg.addr = (__u64)&(env->ckc);
+ r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+ if (r < 0) {
+ return r;
+ }
+
+ reg.id = KVM_REG_S390_TODPR;
+ reg.addr = (__u64)&(env->todpr);
+ r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
+ if (r < 0) {
+ return r;
+ }
+
+ env->runtime_reg_dirty_mask = KVM_S390_RUNTIME_DIRTY_FULL;
+ return 0;
+}
+
+int kvm_s390_get_registers_partial(CPUState *cs)
+{
+ S390CPU *cpu = S390_CPU(cs);
+ CPUS390XState *env = &cpu->env;
struct kvm_sregs sregs;
struct kvm_regs regs;
int ret;
int i;
+ if (env->runtime_reg_dirty_mask) {
+ return 0;
+ }
+
/* get the PSW */
env->psw.addr = cs->kvm_run->psw_addr;
env->psw.mask = cs->kvm_run->psw_mask;
@@ -236,6 +302,7 @@ int kvm_arch_get_registers(CPUState *cs)
/* no prefix without sync regs */
}
+ env->runtime_reg_dirty_mask = KVM_S390_RUNTIME_DIRTY_PARTIAL;
return 0;
}