]> git.baikalelectronics.ru Git - kernel.git/commitdiff
KVM: PPC: Book3S HV: Enable migration of decrementer register
authorPaul Mackerras <paulus@ozlabs.org>
Fri, 12 Jan 2018 09:55:20 +0000 (20:55 +1100)
committerPaul Mackerras <paulus@ozlabs.org>
Tue, 16 Jan 2018 00:54:45 +0000 (11:54 +1100)
This adds a register identifier for use with the one_reg interface
to allow the decrementer expiry time to be read and written by
userspace.  The decrementer expiry time is in guest timebase units
and is equal to the sum of the decrementer and the guest timebase.
(The expiry time is used rather than the decrementer value itself
because the expiry time is not constantly changing, though the
decrementer value is, while the guest vcpu is not running.)

Without this, a guest vcpu migrated to a new host will see its
decrementer set to some random value.  On POWER8 and earlier, the
decrementer is 32 bits wide and counts down at 512MHz, so the
guest vcpu will potentially see no decrementer interrupts for up
to about 4 seconds, which will lead to a stall.  With POWER9, the
decrementer is now 56 bits side, so the stall can be much longer
(up to 2.23 years) and more noticeable.

To help work around the problem in cases where userspace has not been
updated to migrate the decrementer expiry time, we now set the
default decrementer expiry at vcpu creation time to the current time
rather than the maximum possible value.  This should mean an
immediate decrementer interrupt when a migrated vcpu starts
running.  In cases where the decrementer is 32 bits wide and more
than 4 seconds elapse between the creation of the vcpu and when it
first runs, the decrementer would have wrapped around to positive
values and there may still be a stall - but this is no worse than
the current situation.  In the large-decrementer case, we are sure
to get an immediate decrementer interrupt (assuming the time from
vcpu creation to first run is less than 2.23 years) and we thus
avoid a very long stall.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Documentation/virtual/kvm/api.txt
arch/powerpc/include/uapi/asm/kvm.h
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/powerpc.c

index f670e4b9e7f33fdbb186d9b1c9186c6a2fbf7324..c6f9eebb79f2c053c43a484d2ec6e6586ccd265e 100644 (file)
@@ -1841,6 +1841,7 @@ registers, find a list below:
   PPC  | KVM_REG_PPC_DBSR              | 32
   PPC   | KVM_REG_PPC_TIDR              | 64
   PPC   | KVM_REG_PPC_PSSCR             | 64
+  PPC   | KVM_REG_PPC_DEC_EXPIRY        | 64
   PPC   | KVM_REG_PPC_TM_GPR0           | 64
           ...
   PPC   | KVM_REG_PPC_TM_GPR31          | 64
index 61d6049f4c1eced70ad3fef32f99b3a438da3eab..8aaec831053af0bf4e6dcb6a8fda63737f65a93d 100644 (file)
@@ -607,6 +607,8 @@ struct kvm_ppc_rmmu_info {
 #define KVM_REG_PPC_TIDR       (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbc)
 #define KVM_REG_PPC_PSSCR      (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbd)
 
+#define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe)
+
 /* Transactional Memory checkpointed state:
  * This is all GPRs, all VSX regs and a subset of SPRs
  */
index c4f0bebfc5ba48cb5dd602b012e72f436ce674ef..b2d448c750086b7cdbd01d81be2bdc27884fb59d 100644 (file)
@@ -1497,6 +1497,10 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
        case KVM_REG_PPC_ARCH_COMPAT:
                *val = get_reg_val(id, vcpu->arch.vcore->arch_compat);
                break;
+       case KVM_REG_PPC_DEC_EXPIRY:
+               *val = get_reg_val(id, vcpu->arch.dec_expires +
+                                  vcpu->arch.vcore->tb_offset);
+               break;
        default:
                r = -EINVAL;
                break;
@@ -1724,6 +1728,10 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
        case KVM_REG_PPC_ARCH_COMPAT:
                r = kvmppc_set_arch_compat(vcpu, set_reg_val(id, *val));
                break;
+       case KVM_REG_PPC_DEC_EXPIRY:
+               vcpu->arch.dec_expires = set_reg_val(id, *val) -
+                       vcpu->arch.vcore->tb_offset;
+               break;
        default:
                r = -EINVAL;
                break;
index c2c7ef3305532533414b0506a88de3a66130242a..7c9e45f54186dc887bd893197ae1e2f0a70ee1f3 100644 (file)
@@ -758,7 +758,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 
        hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
        vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup;
-       vcpu->arch.dec_expires = ~(u64)0;
+       vcpu->arch.dec_expires = get_tb();
 
 #ifdef CONFIG_KVM_EXIT_TIMING
        mutex_init(&vcpu->arch.exit_timing_lock);