Message ID | 1349163209-19712-2-git-send-email-jfrei@linux.vnet.ibm.com |
---|---|
State | New |
Headers | show |
On Tue, Oct 2, 2012 at 7:33 AM, Jens Freimann <jfrei@linux.vnet.ibm.com> wrote: > From: Christian Borntraeger <borntraeger@de.ibm.com> > > Newer kernels provide the guest registers in kvm_run. Lets use > those if available (i.e. the capability is set). This avoids > ioctls on cpu_synchronize_state making intercepts faster. > > In addition, we have now the prefix register, the access registers > the control registers up to date. This helps in certain cases, > e.g. for resolving kernel module addresses with gdb on a guest. > > On return, we update the registers according to the level statement, > i.e. we put all registers for KVM_PUT_FULL_STATE and _RESET_STATE. > > Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> > Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com> > --- > target-s390x/kvm.c | 119 ++++++++++++++++++++++++++++++++++++++++++++--------- > 1 file changed, 99 insertions(+), 20 deletions(-) > > diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c > index 07edf93..cd57da3 100644 > --- a/target-s390x/kvm.c > +++ b/target-s390x/kvm.c > @@ -67,8 +67,11 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { > KVM_CAP_LAST_INFO > }; > > +int cap_sync_regs; static > + > int kvm_arch_init(KVMState *s) > { > + cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS); > return 0; > } > > @@ -88,49 +91,125 @@ void kvm_arch_reset_vcpu(CPUS390XState *env) > /* FIXME: add code to reset vcpu. */ > } > > +/* we want to have the prefix, the GPRS, the ACRS and the CRS up to date */ > +#define QEMU_NEEDED_REGS (KVM_SYNC_PREFIX | KVM_SYNC_GPRS | \ > + KVM_SYNC_ACRS | KVM_SYNC_CRS) > + > +/* But qemu only changes the GPRS */ > +#define QEMU_DIRTY_REGS (KVM_SYNC_GPRS) > + > int kvm_arch_put_registers(CPUS390XState *env, int level) > { > + struct kvm_sregs sregs; > struct kvm_regs regs; > int ret; > int i; > > - ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); > - if (ret < 0) { > - return ret; > - } > + /* always save the PSW and the GPRS*/ > + env->kvm_run->psw_addr = env->psw.addr; > + env->kvm_run->psw_mask = env->psw.mask; > > - for (i = 0; i < 16; i++) { > - regs.gprs[i] = env->regs[i]; > + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) { > + for (i = 0; i < 16; i++) { > + env->kvm_run->s.regs.gprs[i] = env->regs[i]; > + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_GPRS; > + } > + } else { > + for (i = 0; i < 16; i++) { > + regs.gprs[i] = env->regs[i]; > + } > + ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); > + if (ret < 0) { > + return ret; > + } > } > > - ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); > - if (ret < 0) { > - return ret; > + /* Do we need to save more than that? */ > + if (level == KVM_PUT_RUNTIME_STATE) { > + return 0; > } > > - env->kvm_run->psw_addr = env->psw.addr; > - env->kvm_run->psw_mask = env->psw.mask; > + if (cap_sync_regs && > + env->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS && > + env->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) { > + for (i = 0; i < 16; i++) { > + env->kvm_run->s.regs.acrs[i] = env->aregs[i]; > + env->kvm_run->s.regs.crs[i] = env->cregs[i]; > + } > + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_ACRS; > + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_CRS; > + } else { > + for (i = 0; i < 16; i++) { > + sregs.acrs[i] = env->aregs[i]; > + sregs.crs[i] = env->cregs[i]; > + } > + ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs); > + if (ret < 0) { > + return ret; > + } > + } > > - return ret; > + /* Finally the prefix */ > + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { > + env->kvm_run->s.regs.prefix = env->psa; > + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_PREFIX; > + } else { > + /* prefix is only supported via sync regs */ > + } > + return 0; > } > > int kvm_arch_get_registers(CPUS390XState *env) > { > - int ret; > + struct kvm_sregs sregs; > struct kvm_regs regs; > + int ret; > int i; > > - ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); > - if (ret < 0) { > - return ret; > + /* get the PSW */ > + env->psw.addr = env->kvm_run->psw_addr; > + env->psw.mask = env->kvm_run->psw_mask; > + > + /* the GPRS */ > + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) { > + for (i = 0; i < 16; i++) { > + env->regs[i] = env->kvm_run->s.regs.gprs[i]; > + } > + } else { > + ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); > + if (ret < 0) { > + return ret; > + } > + for (i = 0; i < 16; i++) { > + env->regs[i] = regs.gprs[i]; > + } > } > > - for (i = 0; i < 16; i++) { > - env->regs[i] = regs.gprs[i]; > + /* The ACRS and CRS */ > + if (cap_sync_regs && > + env->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS && > + env->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) { > + for (i = 0; i < 16; i++) { > + env->aregs[i] = env->kvm_run->s.regs.acrs[i]; > + env->cregs[i] = env->kvm_run->s.regs.crs[i]; > + } > + } else { > + ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs); > + if (ret < 0) { > + return ret; > + } > + for (i = 0; i < 16; i++) { > + env->aregs[i] = sregs.acrs[i]; > + env->cregs[i] = sregs.crs[i]; > + } > } > > - env->psw.addr = env->kvm_run->psw_addr; > - env->psw.mask = env->kvm_run->psw_mask; > + /* Finally the prefix */ > + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { > + env->psa = env->kvm_run->s.regs.prefix; > + } else { > + /* no prefix without sync regs */ > + } > > return 0; > } > -- > 1.7.11.7 > >
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 07edf93..cd57da3 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -67,8 +67,11 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO }; +int cap_sync_regs; + int kvm_arch_init(KVMState *s) { + cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS); return 0; } @@ -88,49 +91,125 @@ void kvm_arch_reset_vcpu(CPUS390XState *env) /* FIXME: add code to reset vcpu. */ } +/* we want to have the prefix, the GPRS, the ACRS and the CRS up to date */ +#define QEMU_NEEDED_REGS (KVM_SYNC_PREFIX | KVM_SYNC_GPRS | \ + KVM_SYNC_ACRS | KVM_SYNC_CRS) + +/* But qemu only changes the GPRS */ +#define QEMU_DIRTY_REGS (KVM_SYNC_GPRS) + int kvm_arch_put_registers(CPUS390XState *env, int level) { + struct kvm_sregs sregs; struct kvm_regs regs; int ret; int i; - ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); - if (ret < 0) { - return ret; - } + /* always save the PSW and the GPRS*/ + env->kvm_run->psw_addr = env->psw.addr; + env->kvm_run->psw_mask = env->psw.mask; - for (i = 0; i < 16; i++) { - regs.gprs[i] = env->regs[i]; + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) { + for (i = 0; i < 16; i++) { + env->kvm_run->s.regs.gprs[i] = env->regs[i]; + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_GPRS; + } + } else { + for (i = 0; i < 16; i++) { + regs.gprs[i] = env->regs[i]; + } + ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); + if (ret < 0) { + return ret; + } } - ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); - if (ret < 0) { - return ret; + /* Do we need to save more than that? */ + if (level == KVM_PUT_RUNTIME_STATE) { + return 0; } - env->kvm_run->psw_addr = env->psw.addr; - env->kvm_run->psw_mask = env->psw.mask; + if (cap_sync_regs && + env->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS && + env->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) { + for (i = 0; i < 16; i++) { + env->kvm_run->s.regs.acrs[i] = env->aregs[i]; + env->kvm_run->s.regs.crs[i] = env->cregs[i]; + } + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_ACRS; + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_CRS; + } else { + for (i = 0; i < 16; i++) { + sregs.acrs[i] = env->aregs[i]; + sregs.crs[i] = env->cregs[i]; + } + ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs); + if (ret < 0) { + return ret; + } + } - return ret; + /* Finally the prefix */ + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { + env->kvm_run->s.regs.prefix = env->psa; + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_PREFIX; + } else { + /* prefix is only supported via sync regs */ + } + return 0; } int kvm_arch_get_registers(CPUS390XState *env) { - int ret; + struct kvm_sregs sregs; struct kvm_regs regs; + int ret; int i; - ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); - if (ret < 0) { - return ret; + /* get the PSW */ + env->psw.addr = env->kvm_run->psw_addr; + env->psw.mask = env->kvm_run->psw_mask; + + /* the GPRS */ + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) { + for (i = 0; i < 16; i++) { + env->regs[i] = env->kvm_run->s.regs.gprs[i]; + } + } else { + ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); + if (ret < 0) { + return ret; + } + for (i = 0; i < 16; i++) { + env->regs[i] = regs.gprs[i]; + } } - for (i = 0; i < 16; i++) { - env->regs[i] = regs.gprs[i]; + /* The ACRS and CRS */ + if (cap_sync_regs && + env->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS && + env->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) { + for (i = 0; i < 16; i++) { + env->aregs[i] = env->kvm_run->s.regs.acrs[i]; + env->cregs[i] = env->kvm_run->s.regs.crs[i]; + } + } else { + ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs); + if (ret < 0) { + return ret; + } + for (i = 0; i < 16; i++) { + env->aregs[i] = sregs.acrs[i]; + env->cregs[i] = sregs.crs[i]; + } } - env->psw.addr = env->kvm_run->psw_addr; - env->psw.mask = env->kvm_run->psw_mask; + /* Finally the prefix */ + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { + env->psa = env->kvm_run->s.regs.prefix; + } else { + /* no prefix without sync regs */ + } return 0; }