s390x/kvm: rework KVM synchronize to tracing for some ONEREGS
Some ONE_REGS on s390 are not protected by a capability. Older kernels might not provide those and return an error. Fortunately these registers are only critical for the migration path. There is no need to error out on reset and normal runtime. Furthermore, these kernels don't provide a proper dirty bitmap anyway, so let's use tracing for those errors. Also provide generic one reg helper to simplify the code. Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
This commit is contained in:
parent
9ffd26859d
commit
860643bc5a
@ -36,6 +36,7 @@
|
|||||||
#include "sysemu/device_tree.h"
|
#include "sysemu/device_tree.h"
|
||||||
#include "qapi/qmp/qjson.h"
|
#include "qapi/qmp/qjson.h"
|
||||||
#include "monitor/monitor.h"
|
#include "monitor/monitor.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
/* #define DEBUG_KVM */
|
/* #define DEBUG_KVM */
|
||||||
|
|
||||||
@ -128,14 +129,42 @@ void kvm_arch_reset_vcpu(CPUState *cpu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int kvm_set_one_reg(CPUState *cs, uint64_t id, void *source)
|
||||||
|
{
|
||||||
|
struct kvm_one_reg reg;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
reg.id = id;
|
||||||
|
reg.addr = (uint64_t) source;
|
||||||
|
r = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
||||||
|
if (r) {
|
||||||
|
trace_kvm_failed_reg_set(id, strerror(errno));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target)
|
||||||
|
{
|
||||||
|
struct kvm_one_reg reg;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
reg.id = id;
|
||||||
|
reg.addr = (uint64_t) target;
|
||||||
|
r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||||
|
if (r) {
|
||||||
|
trace_kvm_failed_reg_get(id, strerror(errno));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int kvm_arch_put_registers(CPUState *cs, int level)
|
int kvm_arch_put_registers(CPUState *cs, int level)
|
||||||
{
|
{
|
||||||
S390CPU *cpu = S390_CPU(cs);
|
S390CPU *cpu = S390_CPU(cs);
|
||||||
CPUS390XState *env = &cpu->env;
|
CPUS390XState *env = &cpu->env;
|
||||||
struct kvm_one_reg reg;
|
|
||||||
struct kvm_sregs sregs;
|
struct kvm_sregs sregs;
|
||||||
struct kvm_regs regs;
|
struct kvm_regs regs;
|
||||||
int ret;
|
int r;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* always save the PSW and the GPRS*/
|
/* always save the PSW and the GPRS*/
|
||||||
@ -151,9 +180,9 @@ int kvm_arch_put_registers(CPUState *cs, int level)
|
|||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
regs.gprs[i] = env->regs[i];
|
regs.gprs[i] = env->regs[i];
|
||||||
}
|
}
|
||||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s);
|
r = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s);
|
||||||
if (ret < 0) {
|
if (r < 0) {
|
||||||
return ret;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,47 +191,27 @@ int kvm_arch_put_registers(CPUState *cs, int level)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
reg.id = KVM_REG_S390_CPU_TIMER;
|
/*
|
||||||
reg.addr = (__u64)&(env->cputm);
|
* These ONE_REGS are not protected by a capability. As they are only
|
||||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
* necessary for migration we just trace a possible error, but don't
|
||||||
if (ret < 0) {
|
* return with an error return code.
|
||||||
return ret;
|
*/
|
||||||
}
|
kvm_set_one_reg(cs, KVM_REG_S390_CPU_TIMER, &env->cputm);
|
||||||
|
kvm_set_one_reg(cs, KVM_REG_S390_CLOCK_COMP, &env->ckc);
|
||||||
reg.id = KVM_REG_S390_CLOCK_COMP;
|
kvm_set_one_reg(cs, KVM_REG_S390_TODPR, &env->todpr);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cap_async_pf) {
|
if (cap_async_pf) {
|
||||||
reg.id = KVM_REG_S390_PFTOKEN;
|
r = kvm_set_one_reg(cs, KVM_REG_S390_PFTOKEN, &env->pfault_token);
|
||||||
reg.addr = (__u64)&(env->pfault_token);
|
if (r < 0) {
|
||||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
return r;
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
r = kvm_set_one_reg(cs, KVM_REG_S390_PFCOMPARE, &env->pfault_compare);
|
||||||
reg.id = KVM_REG_S390_PFCOMPARE;
|
if (r < 0) {
|
||||||
reg.addr = (__u64)&(env->pfault_compare);
|
return r;
|
||||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
r = kvm_set_one_reg(cs, KVM_REG_S390_PFSELECT, &env->pfault_select);
|
||||||
reg.id = KVM_REG_S390_PFSELECT;
|
if (r < 0) {
|
||||||
reg.addr = (__u64)&(env->pfault_select);
|
return r;
|
||||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, ®);
|
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,9 +229,9 @@ int kvm_arch_put_registers(CPUState *cs, int level)
|
|||||||
sregs.acrs[i] = env->aregs[i];
|
sregs.acrs[i] = env->aregs[i];
|
||||||
sregs.crs[i] = env->cregs[i];
|
sregs.crs[i] = env->cregs[i];
|
||||||
}
|
}
|
||||||
ret = kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs);
|
r = kvm_vcpu_ioctl(cs, KVM_SET_SREGS, &sregs);
|
||||||
if (ret < 0) {
|
if (r < 0) {
|
||||||
return ret;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +249,6 @@ int kvm_arch_get_registers(CPUState *cs)
|
|||||||
{
|
{
|
||||||
S390CPU *cpu = S390_CPU(cs);
|
S390CPU *cpu = S390_CPU(cs);
|
||||||
CPUS390XState *env = &cpu->env;
|
CPUS390XState *env = &cpu->env;
|
||||||
struct kvm_one_reg reg;
|
|
||||||
struct kvm_sregs sregs;
|
struct kvm_sregs sregs;
|
||||||
struct kvm_regs regs;
|
struct kvm_regs regs;
|
||||||
int i, r;
|
int i, r;
|
||||||
@ -288,46 +296,25 @@ int kvm_arch_get_registers(CPUState *cs)
|
|||||||
env->psa = cs->kvm_run->s.regs.prefix;
|
env->psa = cs->kvm_run->s.regs.prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* One Regs */
|
/*
|
||||||
reg.id = KVM_REG_S390_CPU_TIMER;
|
* These ONE_REGS are not protected by a capability. As they are only
|
||||||
reg.addr = (__u64)&(env->cputm);
|
* necessary for migration we just trace a possible error, but don't
|
||||||
r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
* return with an error return code.
|
||||||
if (r < 0) {
|
*/
|
||||||
return r;
|
kvm_get_one_reg(cs, KVM_REG_S390_CPU_TIMER, &env->cputm);
|
||||||
}
|
kvm_get_one_reg(cs, KVM_REG_S390_CLOCK_COMP, &env->ckc);
|
||||||
|
kvm_get_one_reg(cs, KVM_REG_S390_TODPR, &env->todpr);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cap_async_pf) {
|
if (cap_async_pf) {
|
||||||
reg.id = KVM_REG_S390_PFTOKEN;
|
r = kvm_get_one_reg(cs, KVM_REG_S390_PFTOKEN, &env->pfault_token);
|
||||||
reg.addr = (__u64)&(env->pfault_token);
|
|
||||||
r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
r = kvm_get_one_reg(cs, KVM_REG_S390_PFCOMPARE, &env->pfault_compare);
|
||||||
reg.id = KVM_REG_S390_PFCOMPARE;
|
|
||||||
reg.addr = (__u64)&(env->pfault_compare);
|
|
||||||
r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
r = kvm_get_one_reg(cs, KVM_REG_S390_PFSELECT, &env->pfault_select);
|
||||||
reg.id = KVM_REG_S390_PFSELECT;
|
|
||||||
reg.addr = (__u64)&(env->pfault_select);
|
|
||||||
r = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -1243,3 +1243,7 @@ xen_pv_mmio_write(uint64_t addr) "WARNING: write to Xen PV Device MMIO space (ad
|
|||||||
# hw/pci/pci_host.c
|
# hw/pci/pci_host.c
|
||||||
pci_cfg_read(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x -> 0x%x"
|
pci_cfg_read(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x -> 0x%x"
|
||||||
pci_cfg_write(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x <- 0x%x"
|
pci_cfg_write(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x <- 0x%x"
|
||||||
|
|
||||||
|
# target-s390/kvm.c
|
||||||
|
kvm_failed_reg_get(uint64_t id, const char *msg) "Warning: Unable to retrieve ONEREG %" PRIu64 " from KVM: %s"
|
||||||
|
kvm_failed_reg_set(uint64_t id, const char *msg) "Warning: Unable to set ONEREG %" PRIu64 " to KVM: %s"
|
||||||
|
Loading…
Reference in New Issue
Block a user