aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@ozlabs.org>2018-01-12 04:55:20 -0500
committerPaul Mackerras <paulus@ozlabs.org>2018-01-15 19:54:45 -0500
commit5855564c8ab2d9cefca7b2933bd19818eb795e40 (patch)
treec88ee266f0bd640b2cc83ca9c891353fadd259aa
parent1627301020cb460f5a74e13c291f8db3b2a8062e (diff)
KVM: PPC: Book3S HV: Enable migration of decrementer register
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>
-rw-r--r--Documentation/virtual/kvm/api.txt1
-rw-r--r--arch/powerpc/include/uapi/asm/kvm.h2
-rw-r--r--arch/powerpc/kvm/book3s_hv.c8
-rw-r--r--arch/powerpc/kvm/powerpc.c2
4 files changed, 12 insertions, 1 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index f670e4b9e7f3..c6f9eebb79f2 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1841,6 +1841,7 @@ registers, find a list below:
1841 PPC | KVM_REG_PPC_DBSR | 32 1841 PPC | KVM_REG_PPC_DBSR | 32
1842 PPC | KVM_REG_PPC_TIDR | 64 1842 PPC | KVM_REG_PPC_TIDR | 64
1843 PPC | KVM_REG_PPC_PSSCR | 64 1843 PPC | KVM_REG_PPC_PSSCR | 64
1844 PPC | KVM_REG_PPC_DEC_EXPIRY | 64
1844 PPC | KVM_REG_PPC_TM_GPR0 | 64 1845 PPC | KVM_REG_PPC_TM_GPR0 | 64
1845 ... 1846 ...
1846 PPC | KVM_REG_PPC_TM_GPR31 | 64 1847 PPC | KVM_REG_PPC_TM_GPR31 | 64
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index 61d6049f4c1e..8aaec831053a 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -607,6 +607,8 @@ struct kvm_ppc_rmmu_info {
607#define KVM_REG_PPC_TIDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbc) 607#define KVM_REG_PPC_TIDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbc)
608#define KVM_REG_PPC_PSSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbd) 608#define KVM_REG_PPC_PSSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbd)
609 609
610#define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe)
611
610/* Transactional Memory checkpointed state: 612/* Transactional Memory checkpointed state:
611 * This is all GPRs, all VSX regs and a subset of SPRs 613 * This is all GPRs, all VSX regs and a subset of SPRs
612 */ 614 */
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index c4f0bebfc5ba..b2d448c75008 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -1497,6 +1497,10 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
1497 case KVM_REG_PPC_ARCH_COMPAT: 1497 case KVM_REG_PPC_ARCH_COMPAT:
1498 *val = get_reg_val(id, vcpu->arch.vcore->arch_compat); 1498 *val = get_reg_val(id, vcpu->arch.vcore->arch_compat);
1499 break; 1499 break;
1500 case KVM_REG_PPC_DEC_EXPIRY:
1501 *val = get_reg_val(id, vcpu->arch.dec_expires +
1502 vcpu->arch.vcore->tb_offset);
1503 break;
1500 default: 1504 default:
1501 r = -EINVAL; 1505 r = -EINVAL;
1502 break; 1506 break;
@@ -1724,6 +1728,10 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
1724 case KVM_REG_PPC_ARCH_COMPAT: 1728 case KVM_REG_PPC_ARCH_COMPAT:
1725 r = kvmppc_set_arch_compat(vcpu, set_reg_val(id, *val)); 1729 r = kvmppc_set_arch_compat(vcpu, set_reg_val(id, *val));
1726 break; 1730 break;
1731 case KVM_REG_PPC_DEC_EXPIRY:
1732 vcpu->arch.dec_expires = set_reg_val(id, *val) -
1733 vcpu->arch.vcore->tb_offset;
1734 break;
1727 default: 1735 default:
1728 r = -EINVAL; 1736 r = -EINVAL;
1729 break; 1737 break;
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index c2c7ef330553..7c9e45f54186 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -758,7 +758,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
758 758
759 hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); 759 hrtimer_init(&vcpu->arch.dec_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
760 vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup; 760 vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup;
761 vcpu->arch.dec_expires = ~(u64)0; 761 vcpu->arch.dec_expires = get_tb();
762 762
763#ifdef CONFIG_KVM_EXIT_TIMING 763#ifdef CONFIG_KVM_EXIT_TIMING
764 mutex_init(&vcpu->arch.exit_timing_lock); 764 mutex_init(&vcpu->arch.exit_timing_lock);