linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: cdall@linaro.org (Christoffer Dall)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC v3 00/10] Provide the EL1 physical timer to the VM
Date: Fri, 3 Feb 2017 13:33:20 +0100	[thread overview]
Message-ID: <20170203123320.GK27852@cbox> (raw)
In-Reply-To: <CAHyh4xhsqS6CijRysFvg+NqGo0rBQU45OhAaZUuHDm4M0JufTg@mail.gmail.com>

On Thu, Feb 02, 2017 at 09:51:13AM -0500, Jintack Lim wrote:
> On Thu, Feb 2, 2017 at 7:31 AM, Christoffer Dall <cdall@linaro.org> wrote:
> > Hi Jintack,
> >
> > On Wed, Feb 01, 2017 at 12:43:00PM -0500, Jintack Lim wrote:
> >> The ARM architecture defines the EL1 physical timer and the virtual timer,
> >> and it is reasonable for an OS to expect to be able to access both.
> >> However, the current KVM implementation does not provide the EL1 physical
> >> timer to VMs but terminates VMs on access to the timer.
> >>
> >> This patch series enables VMs to use the EL1 physical timer through
> >> trap-and-emulate.  The KVM host emulates each EL1 physical timer register
> >> access and sets up the background timer accordingly.  When the background
> >> timer expires, the KVM host injects EL1 physical timer interrupts to the
> >> VM.  Alternatively, it's also possible to allow VMs to access the EL1
> >> physical timer without trapping.  However, this requires somehow using the
> >> EL2 physical timer for the Linux host while running the VM instead of the
> >> EL1 physical timer.  Right now I just implemented trap-and-emulate because
> >> this was straightforward to do, and I leave it to future work to determine
> >> if transferring the EL1 physical timer state to the EL2 timer provides any
> >> performance benefit.
> >>
> >> This feature will be useful for any OS that wishes to access the EL1
> >> physical timer. Nested virtualization is one of those use cases. A nested
> >> hypervisor running inside a VM would think it has full access to the
> >> hardware and naturally tries to use the EL1 physical timer as Linux would
> >> do. Other nested hypervisors may try to use the EL2 physical timer as Xen
> >> would do, but supporting the EL2 physical timer to the VM is out of scope
> >> of this patch series. This patch series will make it easy to add the EL2
> >> timer support in the future, though.
> >>
> >> Note that Linux VMs booting in EL1 will be unaffected by this patch series
> >> and will continue to use only the virtual timer and this patch series will
> >> therefore not introduce any performance degredation as a result of
> >> trap-and-emulate.
> >>
> >> v2 => v3:
> >>  - Rebase on kvmarm/queue
> >>  - Take kvm->lock to synchronize cntvoff across all vtimers
> >>  - Remove unnecessary function parameters
> >>  - Add comments
> >
> > I just gave v3 a test run on my TC2 (32-bit platform) and my guest
> > quickly locks up trying to run cyclictest or when booting the machine it
> > stalls with RCU timeouts.
> 
> Ok. It's my fault not to specify that the emulated physical timer is
> supported/tested on arm64.
> On 32-bit platform, it is supposed to show the same behavior as
> before, but I haven't tested.
> Were you using the physical timer or the virtual timer for the guest?
> 
> >
> > Could you have a look?
> 
> Sure, I'll have a look. I don't have access to my Cubietruck today,
> but I can work on that tomorrow.
> 

Don't bother, I've figured this out for you.

You need the following fixup to your patch:

diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 93c811c..35d7100 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -410,14 +410,21 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 }
 
 /* Make the updates of cntvoff for all vtimer contexts atomic */
-static void update_vtimer_cntvoff(struct kvm *kvm, u64 cntvoff)
+static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff)
 {
 	int i;
-	struct kvm_vcpu *vcpu;
+	struct kvm *kvm = vcpu->kvm;
+	struct kvm_vcpu *tmp;
 
 	mutex_lock(&kvm->lock);
-	kvm_for_each_vcpu(i, vcpu, kvm)
-		vcpu_vtimer(vcpu)->cntvoff = cntvoff;
+	kvm_for_each_vcpu(i, tmp, kvm)
+		vcpu_vtimer(tmp)->cntvoff = cntvoff;
+
+	/*
+	 * When called from the vcpu create path, the CPU being created is not
+	 * included in the loop above, so we just set it here as well.
+	 */
+	vcpu_vtimer(vcpu)->cntvoff = cntvoff;
 	mutex_unlock(&kvm->lock);
 }
 
@@ -426,7 +433,7 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 
 	/* Synchronize cntvoff across all vtimers of a VM. */
-	update_vtimer_cntvoff(vcpu->kvm, kvm_phys_timer_read());
+	update_vtimer_cntvoff(vcpu, kvm_phys_timer_read());
 	vcpu_ptimer(vcpu)->cntvoff = 0;
 
 	INIT_WORK(&timer->expired, kvm_timer_inject_irq_work);
@@ -448,7 +455,7 @@ int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
 		vtimer->cnt_ctl = value;
 		break;
 	case KVM_REG_ARM_TIMER_CNT:
-		update_vtimer_cntvoff(vcpu->kvm, kvm_phys_timer_read() - value);
+		update_vtimer_cntvoff(vcpu, kvm_phys_timer_read() - value);
 		break;
 	case KVM_REG_ARM_TIMER_CVAL:
 		vtimer->cnt_cval = value;

This is an amuzing one.

Thanks,
-Christoffer

  parent reply	other threads:[~2017-02-03 12:33 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-01 17:43 [RFC v3 00/10] Provide the EL1 physical timer to the VM Jintack Lim
2017-02-01 17:43 ` [RFC v3 01/10] KVM: arm/arm64: Abstract virtual timer context into separate structure Jintack Lim
2017-02-01 17:43 ` [RFC v3 02/10] KVM: arm/arm64: Move cntvoff to each timer context Jintack Lim
2017-02-02 10:03   ` Christoffer Dall
2017-02-01 17:43 ` [RFC v3 03/10] KVM: arm/arm64: Decouple kvm timer functions from virtual timer Jintack Lim
2017-02-02 10:04   ` Christoffer Dall
2017-02-01 17:43 ` [RFC v3 04/10] KVM: arm/arm64: Add the EL1 physical timer context Jintack Lim
2017-02-02 10:15   ` Christoffer Dall
2017-02-01 17:43 ` [RFC v3 05/10] KVM: arm/arm64: Initialize the emulated EL1 physical timer Jintack Lim
2017-02-02 10:15   ` Christoffer Dall
2017-02-01 17:43 ` [RFC v3 06/10] KVM: arm/arm64: Update the physical timer interrupt level Jintack Lim
2017-02-02 10:15   ` Christoffer Dall
2017-02-01 17:43 ` [RFC v3 07/10] KVM: arm/arm64: Set a background timer to the earliest timer expiration Jintack Lim
2017-02-02 10:30   ` Christoffer Dall
2017-02-01 17:43 ` [RFC v3 08/10] KVM: arm/arm64: Set up a background timer for the physical timer emulation Jintack Lim
2017-02-02 10:30   ` Christoffer Dall
2017-02-01 17:43 ` [RFC v3 09/10] KVM: arm64: Add the EL1 physical timer access handler Jintack Lim
2017-02-02 10:31   ` Christoffer Dall
2017-02-01 17:43 ` [RFC v3 10/10] KVM: arm/arm64: Emulate the EL1 phys timer registers Jintack Lim
2017-02-02 10:31   ` Christoffer Dall
2017-02-02 12:31 ` [RFC v3 00/10] Provide the EL1 physical timer to the VM Christoffer Dall
2017-02-02 14:51   ` Jintack Lim
2017-02-02 15:08     ` Christoffer Dall
2017-02-03 12:33     ` Christoffer Dall [this message]
2017-02-03 13:14       ` Jintack Lim
2017-02-03 13:34         ` Christoffer Dall

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170203123320.GK27852@cbox \
    --to=cdall@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).