diff options
author | Jason J. Herne <jjherne@us.ibm.com> | 2013-04-25 04:25:50 +0000 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2013-04-26 20:18:24 +0200 |
commit | 420840e58b85f7f4e5493dca3f273566f261090a (patch) | |
tree | 5a7dc181c082e7be48acbbc871cdf54d56d99c68 /target-s390x/kvm.c | |
parent | 7dc5af5545bb72e1343cc959b3f0e5cdd8758f1f (diff) | |
download | qemu-420840e58b85f7f4e5493dca3f273566f261090a.zip qemu-420840e58b85f7f4e5493dca3f273566f261090a.tar.gz qemu-420840e58b85f7f4e5493dca3f273566f261090a.tar.bz2 |
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.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 644f484..02b2e39 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, ®); + 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, ®); + 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, ®); + 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, ®); + 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, ®); + 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, ®); + 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; } |