2013-01-24 02:21:58 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2012 ARM Ltd.
|
|
|
|
* Author: Marc Zyngier <marc.zyngier@arm.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
|
|
* published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/cpu.h>
|
|
|
|
#include <linux/kvm.h>
|
|
|
|
#include <linux/kvm_host.h>
|
|
|
|
#include <linux/interrupt.h>
|
2016-06-04 22:41:00 +08:00
|
|
|
#include <linux/irq.h>
|
2013-01-24 02:21:58 +08:00
|
|
|
|
2013-03-27 23:56:11 +08:00
|
|
|
#include <clocksource/arm_arch_timer.h>
|
2013-01-24 02:21:58 +08:00
|
|
|
#include <asm/arch_timer.h>
|
2016-12-02 03:32:05 +08:00
|
|
|
#include <asm/kvm_hyp.h>
|
2013-01-24 02:21:58 +08:00
|
|
|
|
ARM: KVM: move GIC/timer code to a common location
As KVM/arm64 is looming on the horizon, it makes sense to move some
of the common code to a single location in order to reduce duplication.
The code could live anywhere. Actually, most of KVM is already built
with a bunch of ugly ../../.. hacks in the various Makefiles, so we're
not exactly talking about style here. But maybe it is time to start
moving into a less ugly direction.
The include files must be in a "public" location, as they are accessed
from non-KVM files (arch/arm/kernel/asm-offsets.c).
For this purpose, introduce two new locations:
- virt/kvm/arm/ : x86 and ia64 already share the ioapic code in
virt/kvm, so this could be seen as a (very ugly) precedent.
- include/kvm/ : there is already an include/xen, and while the
intent is slightly different, this seems as good a location as
any
Eventually, we should probably have independant Makefiles at every
levels (just like everywhere else in the kernel), but this is just
the first step.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Gleb Natapov <gleb@redhat.com>
2013-05-14 21:31:01 +08:00
|
|
|
#include <kvm/arm_vgic.h>
|
|
|
|
#include <kvm/arm_arch_timer.h>
|
2013-01-24 02:21:58 +08:00
|
|
|
|
2015-08-30 19:57:20 +08:00
|
|
|
#include "trace.h"
|
|
|
|
|
2013-01-24 02:21:58 +08:00
|
|
|
static struct timecounter *timecounter;
|
2013-04-30 14:32:15 +08:00
|
|
|
static unsigned int host_vtimer_irq;
|
2016-08-16 22:03:02 +08:00
|
|
|
static u32 host_vtimer_irq_flags;
|
2013-01-24 02:21:58 +08:00
|
|
|
|
2016-01-30 03:04:48 +08:00
|
|
|
void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
2017-02-03 23:19:59 +08:00
|
|
|
vcpu_vtimer(vcpu)->active_cleared_last = false;
|
2016-01-30 03:04:48 +08:00
|
|
|
}
|
|
|
|
|
2016-12-22 03:32:01 +08:00
|
|
|
static u64 kvm_phys_timer_read(void)
|
2013-01-24 02:21:58 +08:00
|
|
|
{
|
|
|
|
return timecounter->cc->read(timecounter->cc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool timer_is_armed(struct arch_timer_cpu *timer)
|
|
|
|
{
|
|
|
|
return timer->armed;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* timer_arm: as in "arm the timer", not as in ARM the company */
|
|
|
|
static void timer_arm(struct arch_timer_cpu *timer, u64 ns)
|
|
|
|
{
|
|
|
|
timer->armed = true;
|
|
|
|
hrtimer_start(&timer->timer, ktime_add_ns(ktime_get(), ns),
|
|
|
|
HRTIMER_MODE_ABS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void timer_disarm(struct arch_timer_cpu *timer)
|
|
|
|
{
|
|
|
|
if (timer_is_armed(timer)) {
|
|
|
|
hrtimer_cancel(&timer->timer);
|
|
|
|
cancel_work_sync(&timer->expired);
|
|
|
|
timer->armed = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
|
|
|
|
{
|
|
|
|
struct kvm_vcpu *vcpu = *(struct kvm_vcpu **)dev_id;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We disable the timer in the world switch and let it be
|
|
|
|
* handled by kvm_timer_sync_hwstate(). Getting a timer
|
|
|
|
* interrupt at this point is a sure sign of some major
|
|
|
|
* breakage.
|
|
|
|
*/
|
|
|
|
pr_warn("Unexpected interrupt %d on vcpu %p\n", irq, vcpu);
|
|
|
|
return IRQ_HANDLED;
|
|
|
|
}
|
|
|
|
|
arm/arm64: KVM: Fix migration race in the arch timer
When a VCPU is no longer running, we currently check to see if it has a
timer scheduled in the future, and if it does, we schedule a host
hrtimer to notify is in case the timer expires while the VCPU is still
not running. When the hrtimer fires, we mask the guest's timer and
inject the timer IRQ (still relying on the guest unmasking the time when
it receives the IRQ).
This is all good and fine, but when migration a VM (checkpoint/restore)
this introduces a race. It is unlikely, but possible, for the following
sequence of events to happen:
1. Userspace stops the VM
2. Hrtimer for VCPU is scheduled
3. Userspace checkpoints the VGIC state (no pending timer interrupts)
4. The hrtimer fires, schedules work in a workqueue
5. Workqueue function runs, masks the timer and injects timer interrupt
6. Userspace checkpoints the timer state (timer masked)
At restore time, you end up with a masked timer without any timer
interrupts and your guest halts never receiving timer interrupts.
Fix this by only kicking the VCPU in the workqueue function, and sample
the expired state of the timer when entering the guest again and inject
the interrupt and mask the timer only then.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-03-14 01:02:55 +08:00
|
|
|
/*
|
|
|
|
* Work function for handling the backup timer that we schedule when a vcpu is
|
|
|
|
* no longer running, but had a timer programmed to fire in the future.
|
|
|
|
*/
|
2013-01-24 02:21:58 +08:00
|
|
|
static void kvm_timer_inject_irq_work(struct work_struct *work)
|
|
|
|
{
|
|
|
|
struct kvm_vcpu *vcpu;
|
|
|
|
|
|
|
|
vcpu = container_of(work, struct kvm_vcpu, arch.timer_cpu.expired);
|
2016-04-06 16:37:22 +08:00
|
|
|
|
arm/arm64: KVM: Fix migration race in the arch timer
When a VCPU is no longer running, we currently check to see if it has a
timer scheduled in the future, and if it does, we schedule a host
hrtimer to notify is in case the timer expires while the VCPU is still
not running. When the hrtimer fires, we mask the guest's timer and
inject the timer IRQ (still relying on the guest unmasking the time when
it receives the IRQ).
This is all good and fine, but when migration a VM (checkpoint/restore)
this introduces a race. It is unlikely, but possible, for the following
sequence of events to happen:
1. Userspace stops the VM
2. Hrtimer for VCPU is scheduled
3. Userspace checkpoints the VGIC state (no pending timer interrupts)
4. The hrtimer fires, schedules work in a workqueue
5. Workqueue function runs, masks the timer and injects timer interrupt
6. Userspace checkpoints the timer state (timer masked)
At restore time, you end up with a masked timer without any timer
interrupts and your guest halts never receiving timer interrupts.
Fix this by only kicking the VCPU in the workqueue function, and sample
the expired state of the timer when entering the guest again and inject
the interrupt and mask the timer only then.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-03-14 01:02:55 +08:00
|
|
|
/*
|
|
|
|
* If the vcpu is blocked we want to wake it up so that it will see
|
|
|
|
* the timer has expired when entering the guest.
|
|
|
|
*/
|
|
|
|
kvm_vcpu_kick(vcpu);
|
2013-01-24 02:21:58 +08:00
|
|
|
}
|
|
|
|
|
2017-02-03 23:20:01 +08:00
|
|
|
static u64 kvm_timer_compute_delta(struct arch_timer_context *timer_ctx)
|
2016-04-06 16:37:22 +08:00
|
|
|
{
|
2016-12-22 03:32:01 +08:00
|
|
|
u64 cval, now;
|
2016-04-06 16:37:22 +08:00
|
|
|
|
2017-02-03 23:20:01 +08:00
|
|
|
cval = timer_ctx->cnt_cval;
|
|
|
|
now = kvm_phys_timer_read() - timer_ctx->cntvoff;
|
2016-04-06 16:37:22 +08:00
|
|
|
|
|
|
|
if (now < cval) {
|
|
|
|
u64 ns;
|
|
|
|
|
|
|
|
ns = cyclecounter_cyc2ns(timecounter->cc,
|
|
|
|
cval - now,
|
|
|
|
timecounter->mask,
|
|
|
|
&timecounter->frac);
|
|
|
|
return ns;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-24 02:21:58 +08:00
|
|
|
static enum hrtimer_restart kvm_timer_expire(struct hrtimer *hrt)
|
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer;
|
2016-04-06 16:37:22 +08:00
|
|
|
struct kvm_vcpu *vcpu;
|
|
|
|
u64 ns;
|
|
|
|
|
2013-01-24 02:21:58 +08:00
|
|
|
timer = container_of(hrt, struct arch_timer_cpu, timer);
|
2016-04-06 16:37:22 +08:00
|
|
|
vcpu = container_of(timer, struct kvm_vcpu, arch.timer_cpu);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check that the timer has really expired from the guest's
|
|
|
|
* PoV (NTP on the host may have forced it to expire
|
|
|
|
* early). If we should have slept longer, restart it.
|
|
|
|
*/
|
2017-02-03 23:20:01 +08:00
|
|
|
ns = kvm_timer_compute_delta(vcpu_vtimer(vcpu));
|
2016-04-06 16:37:22 +08:00
|
|
|
if (unlikely(ns)) {
|
|
|
|
hrtimer_forward_now(hrt, ns_to_ktime(ns));
|
|
|
|
return HRTIMER_RESTART;
|
|
|
|
}
|
|
|
|
|
2016-08-31 01:59:51 +08:00
|
|
|
schedule_work(&timer->expired);
|
2013-01-24 02:21:58 +08:00
|
|
|
return HRTIMER_NORESTART;
|
|
|
|
}
|
|
|
|
|
2017-02-03 23:20:01 +08:00
|
|
|
static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx)
|
arm/arm64: KVM: arch_timer: Only schedule soft timer on vcpu_block
We currently schedule a soft timer every time we exit the guest if the
timer did not expire while running the guest. This is really not
necessary, because the only work we do in the timer work function is to
kick the vcpu.
Kicking the vcpu does two things:
(1) If the vpcu thread is on a waitqueue, make it runnable and remove it
from the waitqueue.
(2) If the vcpu is running on a different physical CPU from the one
doing the kick, it sends a reschedule IPI.
The second case cannot happen, because the soft timer is only ever
scheduled when the vcpu is not running. The first case is only relevant
when the vcpu thread is on a waitqueue, which is only the case when the
vcpu thread has called kvm_vcpu_block().
Therefore, we only need to make sure a timer is scheduled for
kvm_vcpu_block(), which we do by encapsulating all calls to
kvm_vcpu_block() with kvm_timer_{un}schedule calls.
Additionally, we only schedule a soft timer if the timer is enabled and
unmasked, since it is useless otherwise.
Note that theoretically userspace can use the SET_ONE_REG interface to
change registers that should cause the timer to fire, even if the vcpu
is blocked without a scheduled timer, but this case was not supported
before this patch and we leave it for future work for now.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-26 01:48:21 +08:00
|
|
|
{
|
2017-02-03 23:20:01 +08:00
|
|
|
return !(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) &&
|
|
|
|
(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_ENABLE);
|
arm/arm64: KVM: arch_timer: Only schedule soft timer on vcpu_block
We currently schedule a soft timer every time we exit the guest if the
timer did not expire while running the guest. This is really not
necessary, because the only work we do in the timer work function is to
kick the vcpu.
Kicking the vcpu does two things:
(1) If the vpcu thread is on a waitqueue, make it runnable and remove it
from the waitqueue.
(2) If the vcpu is running on a different physical CPU from the one
doing the kick, it sends a reschedule IPI.
The second case cannot happen, because the soft timer is only ever
scheduled when the vcpu is not running. The first case is only relevant
when the vcpu thread is on a waitqueue, which is only the case when the
vcpu thread has called kvm_vcpu_block().
Therefore, we only need to make sure a timer is scheduled for
kvm_vcpu_block(), which we do by encapsulating all calls to
kvm_vcpu_block() with kvm_timer_{un}schedule calls.
Additionally, we only schedule a soft timer if the timer is enabled and
unmasked, since it is useless otherwise.
Note that theoretically userspace can use the SET_ONE_REG interface to
change registers that should cause the timer to fire, even if the vcpu
is blocked without a scheduled timer, but this case was not supported
before this patch and we leave it for future work for now.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-26 01:48:21 +08:00
|
|
|
}
|
|
|
|
|
2017-02-03 23:20:01 +08:00
|
|
|
bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx)
|
arm/arm64: KVM: Fix migration race in the arch timer
When a VCPU is no longer running, we currently check to see if it has a
timer scheduled in the future, and if it does, we schedule a host
hrtimer to notify is in case the timer expires while the VCPU is still
not running. When the hrtimer fires, we mask the guest's timer and
inject the timer IRQ (still relying on the guest unmasking the time when
it receives the IRQ).
This is all good and fine, but when migration a VM (checkpoint/restore)
this introduces a race. It is unlikely, but possible, for the following
sequence of events to happen:
1. Userspace stops the VM
2. Hrtimer for VCPU is scheduled
3. Userspace checkpoints the VGIC state (no pending timer interrupts)
4. The hrtimer fires, schedules work in a workqueue
5. Workqueue function runs, masks the timer and injects timer interrupt
6. Userspace checkpoints the timer state (timer masked)
At restore time, you end up with a masked timer without any timer
interrupts and your guest halts never receiving timer interrupts.
Fix this by only kicking the VCPU in the workqueue function, and sample
the expired state of the timer when entering the guest again and inject
the interrupt and mask the timer only then.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-03-14 01:02:55 +08:00
|
|
|
{
|
2016-12-22 03:32:01 +08:00
|
|
|
u64 cval, now;
|
arm/arm64: KVM: Fix migration race in the arch timer
When a VCPU is no longer running, we currently check to see if it has a
timer scheduled in the future, and if it does, we schedule a host
hrtimer to notify is in case the timer expires while the VCPU is still
not running. When the hrtimer fires, we mask the guest's timer and
inject the timer IRQ (still relying on the guest unmasking the time when
it receives the IRQ).
This is all good and fine, but when migration a VM (checkpoint/restore)
this introduces a race. It is unlikely, but possible, for the following
sequence of events to happen:
1. Userspace stops the VM
2. Hrtimer for VCPU is scheduled
3. Userspace checkpoints the VGIC state (no pending timer interrupts)
4. The hrtimer fires, schedules work in a workqueue
5. Workqueue function runs, masks the timer and injects timer interrupt
6. Userspace checkpoints the timer state (timer masked)
At restore time, you end up with a masked timer without any timer
interrupts and your guest halts never receiving timer interrupts.
Fix this by only kicking the VCPU in the workqueue function, and sample
the expired state of the timer when entering the guest again and inject
the interrupt and mask the timer only then.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-03-14 01:02:55 +08:00
|
|
|
|
2017-02-03 23:20:01 +08:00
|
|
|
if (!kvm_timer_irq_can_fire(timer_ctx))
|
arm/arm64: KVM: Fix migration race in the arch timer
When a VCPU is no longer running, we currently check to see if it has a
timer scheduled in the future, and if it does, we schedule a host
hrtimer to notify is in case the timer expires while the VCPU is still
not running. When the hrtimer fires, we mask the guest's timer and
inject the timer IRQ (still relying on the guest unmasking the time when
it receives the IRQ).
This is all good and fine, but when migration a VM (checkpoint/restore)
this introduces a race. It is unlikely, but possible, for the following
sequence of events to happen:
1. Userspace stops the VM
2. Hrtimer for VCPU is scheduled
3. Userspace checkpoints the VGIC state (no pending timer interrupts)
4. The hrtimer fires, schedules work in a workqueue
5. Workqueue function runs, masks the timer and injects timer interrupt
6. Userspace checkpoints the timer state (timer masked)
At restore time, you end up with a masked timer without any timer
interrupts and your guest halts never receiving timer interrupts.
Fix this by only kicking the VCPU in the workqueue function, and sample
the expired state of the timer when entering the guest again and inject
the interrupt and mask the timer only then.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-03-14 01:02:55 +08:00
|
|
|
return false;
|
|
|
|
|
2017-02-03 23:20:01 +08:00
|
|
|
cval = timer_ctx->cnt_cval;
|
|
|
|
now = kvm_phys_timer_read() - timer_ctx->cntvoff;
|
arm/arm64: KVM: Fix migration race in the arch timer
When a VCPU is no longer running, we currently check to see if it has a
timer scheduled in the future, and if it does, we schedule a host
hrtimer to notify is in case the timer expires while the VCPU is still
not running. When the hrtimer fires, we mask the guest's timer and
inject the timer IRQ (still relying on the guest unmasking the time when
it receives the IRQ).
This is all good and fine, but when migration a VM (checkpoint/restore)
this introduces a race. It is unlikely, but possible, for the following
sequence of events to happen:
1. Userspace stops the VM
2. Hrtimer for VCPU is scheduled
3. Userspace checkpoints the VGIC state (no pending timer interrupts)
4. The hrtimer fires, schedules work in a workqueue
5. Workqueue function runs, masks the timer and injects timer interrupt
6. Userspace checkpoints the timer state (timer masked)
At restore time, you end up with a masked timer without any timer
interrupts and your guest halts never receiving timer interrupts.
Fix this by only kicking the VCPU in the workqueue function, and sample
the expired state of the timer when entering the guest again and inject
the interrupt and mask the timer only then.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-03-14 01:02:55 +08:00
|
|
|
|
|
|
|
return cval <= now;
|
|
|
|
}
|
|
|
|
|
2017-02-03 23:20:01 +08:00
|
|
|
static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
|
|
|
|
struct arch_timer_context *timer_ctx)
|
arm/arm64: KVM: Rework the arch timer to use level-triggered semantics
The arch timer currently uses edge-triggered semantics in the sense that
the line is never sampled by the vgic and lowering the line from the
timer to the vgic doesn't have any effect on the pending state of
virtual interrupts in the vgic. This means that we do not support a
guest with the otherwise valid behavior of (1) disable interrupts (2)
enable the timer (3) disable the timer (4) enable interrupts. Such a
guest would validly not expect to see any interrupts on real hardware,
but will see interrupts on KVM.
This patch fixes this shortcoming through the following series of
changes.
First, we change the flow of the timer/vgic sync/flush operations. Now
the timer is always flushed/synced before the vgic, because the vgic
samples the state of the timer output. This has the implication that we
move the timer operations in to non-preempible sections, but that is
fine after the previous commit getting rid of hrtimer schedules on every
entry/exit.
Second, we change the internal behavior of the timer, letting the timer
keep track of its previous output state, and only lower/raise the line
to the vgic when the state changes. Note that in theory this could have
been accomplished more simply by signalling the vgic every time the
state *potentially* changed, but we don't want to be hitting the vgic
more often than necessary.
Third, we get rid of the use of the map->active field in the vgic and
instead simply set the interrupt as active on the physical distributor
whenever the input to the GIC is asserted and conversely clear the
physical active state when the input to the GIC is deasserted.
Fourth, and finally, we now initialize the timer PPIs (and all the other
unused PPIs for now), to be level-triggered, and modify the sync code to
sample the line state on HW sync and re-inject a new interrupt if it is
still pending at that time.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-30 21:01:27 +08:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
BUG_ON(!vgic_initialized(vcpu->kvm));
|
|
|
|
|
2017-02-03 23:20:01 +08:00
|
|
|
timer_ctx->active_cleared_last = false;
|
|
|
|
timer_ctx->irq.level = new_level;
|
|
|
|
trace_kvm_timer_update_irq(vcpu->vcpu_id, timer_ctx->irq.irq,
|
|
|
|
timer_ctx->irq.level);
|
2017-02-01 18:03:45 +08:00
|
|
|
|
2017-02-03 23:20:01 +08:00
|
|
|
ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, timer_ctx->irq.irq,
|
|
|
|
timer_ctx->irq.level);
|
arm/arm64: KVM: Rework the arch timer to use level-triggered semantics
The arch timer currently uses edge-triggered semantics in the sense that
the line is never sampled by the vgic and lowering the line from the
timer to the vgic doesn't have any effect on the pending state of
virtual interrupts in the vgic. This means that we do not support a
guest with the otherwise valid behavior of (1) disable interrupts (2)
enable the timer (3) disable the timer (4) enable interrupts. Such a
guest would validly not expect to see any interrupts on real hardware,
but will see interrupts on KVM.
This patch fixes this shortcoming through the following series of
changes.
First, we change the flow of the timer/vgic sync/flush operations. Now
the timer is always flushed/synced before the vgic, because the vgic
samples the state of the timer output. This has the implication that we
move the timer operations in to non-preempible sections, but that is
fine after the previous commit getting rid of hrtimer schedules on every
entry/exit.
Second, we change the internal behavior of the timer, letting the timer
keep track of its previous output state, and only lower/raise the line
to the vgic when the state changes. Note that in theory this could have
been accomplished more simply by signalling the vgic every time the
state *potentially* changed, but we don't want to be hitting the vgic
more often than necessary.
Third, we get rid of the use of the map->active field in the vgic and
instead simply set the interrupt as active on the physical distributor
whenever the input to the GIC is asserted and conversely clear the
physical active state when the input to the GIC is deasserted.
Fourth, and finally, we now initialize the timer PPIs (and all the other
unused PPIs for now), to be level-triggered, and modify the sync code to
sample the line state on HW sync and re-inject a new interrupt if it is
still pending at that time.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-30 21:01:27 +08:00
|
|
|
WARN_ON(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if there was a change in the timer state (should we raise or lower
|
|
|
|
* the line level to the GIC).
|
|
|
|
*/
|
2016-02-04 00:56:51 +08:00
|
|
|
static int kvm_timer_update_state(struct kvm_vcpu *vcpu)
|
arm/arm64: KVM: Rework the arch timer to use level-triggered semantics
The arch timer currently uses edge-triggered semantics in the sense that
the line is never sampled by the vgic and lowering the line from the
timer to the vgic doesn't have any effect on the pending state of
virtual interrupts in the vgic. This means that we do not support a
guest with the otherwise valid behavior of (1) disable interrupts (2)
enable the timer (3) disable the timer (4) enable interrupts. Such a
guest would validly not expect to see any interrupts on real hardware,
but will see interrupts on KVM.
This patch fixes this shortcoming through the following series of
changes.
First, we change the flow of the timer/vgic sync/flush operations. Now
the timer is always flushed/synced before the vgic, because the vgic
samples the state of the timer output. This has the implication that we
move the timer operations in to non-preempible sections, but that is
fine after the previous commit getting rid of hrtimer schedules on every
entry/exit.
Second, we change the internal behavior of the timer, letting the timer
keep track of its previous output state, and only lower/raise the line
to the vgic when the state changes. Note that in theory this could have
been accomplished more simply by signalling the vgic every time the
state *potentially* changed, but we don't want to be hitting the vgic
more often than necessary.
Third, we get rid of the use of the map->active field in the vgic and
instead simply set the interrupt as active on the physical distributor
whenever the input to the GIC is asserted and conversely clear the
physical active state when the input to the GIC is deasserted.
Fourth, and finally, we now initialize the timer PPIs (and all the other
unused PPIs for now), to be level-triggered, and modify the sync code to
sample the line state on HW sync and re-inject a new interrupt if it is
still pending at that time.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-30 21:01:27 +08:00
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
2017-02-03 23:19:59 +08:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
arm/arm64: KVM: Rework the arch timer to use level-triggered semantics
The arch timer currently uses edge-triggered semantics in the sense that
the line is never sampled by the vgic and lowering the line from the
timer to the vgic doesn't have any effect on the pending state of
virtual interrupts in the vgic. This means that we do not support a
guest with the otherwise valid behavior of (1) disable interrupts (2)
enable the timer (3) disable the timer (4) enable interrupts. Such a
guest would validly not expect to see any interrupts on real hardware,
but will see interrupts on KVM.
This patch fixes this shortcoming through the following series of
changes.
First, we change the flow of the timer/vgic sync/flush operations. Now
the timer is always flushed/synced before the vgic, because the vgic
samples the state of the timer output. This has the implication that we
move the timer operations in to non-preempible sections, but that is
fine after the previous commit getting rid of hrtimer schedules on every
entry/exit.
Second, we change the internal behavior of the timer, letting the timer
keep track of its previous output state, and only lower/raise the line
to the vgic when the state changes. Note that in theory this could have
been accomplished more simply by signalling the vgic every time the
state *potentially* changed, but we don't want to be hitting the vgic
more often than necessary.
Third, we get rid of the use of the map->active field in the vgic and
instead simply set the interrupt as active on the physical distributor
whenever the input to the GIC is asserted and conversely clear the
physical active state when the input to the GIC is deasserted.
Fourth, and finally, we now initialize the timer PPIs (and all the other
unused PPIs for now), to be level-triggered, and modify the sync code to
sample the line state on HW sync and re-inject a new interrupt if it is
still pending at that time.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-30 21:01:27 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If userspace modified the timer registers via SET_ONE_REG before
|
2017-02-03 23:19:59 +08:00
|
|
|
* the vgic was initialized, we mustn't set the vtimer->irq.level value
|
arm/arm64: KVM: Rework the arch timer to use level-triggered semantics
The arch timer currently uses edge-triggered semantics in the sense that
the line is never sampled by the vgic and lowering the line from the
timer to the vgic doesn't have any effect on the pending state of
virtual interrupts in the vgic. This means that we do not support a
guest with the otherwise valid behavior of (1) disable interrupts (2)
enable the timer (3) disable the timer (4) enable interrupts. Such a
guest would validly not expect to see any interrupts on real hardware,
but will see interrupts on KVM.
This patch fixes this shortcoming through the following series of
changes.
First, we change the flow of the timer/vgic sync/flush operations. Now
the timer is always flushed/synced before the vgic, because the vgic
samples the state of the timer output. This has the implication that we
move the timer operations in to non-preempible sections, but that is
fine after the previous commit getting rid of hrtimer schedules on every
entry/exit.
Second, we change the internal behavior of the timer, letting the timer
keep track of its previous output state, and only lower/raise the line
to the vgic when the state changes. Note that in theory this could have
been accomplished more simply by signalling the vgic every time the
state *potentially* changed, but we don't want to be hitting the vgic
more often than necessary.
Third, we get rid of the use of the map->active field in the vgic and
instead simply set the interrupt as active on the physical distributor
whenever the input to the GIC is asserted and conversely clear the
physical active state when the input to the GIC is deasserted.
Fourth, and finally, we now initialize the timer PPIs (and all the other
unused PPIs for now), to be level-triggered, and modify the sync code to
sample the line state on HW sync and re-inject a new interrupt if it is
still pending at that time.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-30 21:01:27 +08:00
|
|
|
* because the guest would never see the interrupt. Instead wait
|
|
|
|
* until we call this function from kvm_timer_flush_hwstate.
|
|
|
|
*/
|
2016-05-18 23:26:00 +08:00
|
|
|
if (!vgic_initialized(vcpu->kvm) || !timer->enabled)
|
2016-02-04 00:56:51 +08:00
|
|
|
return -ENODEV;
|
arm/arm64: KVM: Rework the arch timer to use level-triggered semantics
The arch timer currently uses edge-triggered semantics in the sense that
the line is never sampled by the vgic and lowering the line from the
timer to the vgic doesn't have any effect on the pending state of
virtual interrupts in the vgic. This means that we do not support a
guest with the otherwise valid behavior of (1) disable interrupts (2)
enable the timer (3) disable the timer (4) enable interrupts. Such a
guest would validly not expect to see any interrupts on real hardware,
but will see interrupts on KVM.
This patch fixes this shortcoming through the following series of
changes.
First, we change the flow of the timer/vgic sync/flush operations. Now
the timer is always flushed/synced before the vgic, because the vgic
samples the state of the timer output. This has the implication that we
move the timer operations in to non-preempible sections, but that is
fine after the previous commit getting rid of hrtimer schedules on every
entry/exit.
Second, we change the internal behavior of the timer, letting the timer
keep track of its previous output state, and only lower/raise the line
to the vgic when the state changes. Note that in theory this could have
been accomplished more simply by signalling the vgic every time the
state *potentially* changed, but we don't want to be hitting the vgic
more often than necessary.
Third, we get rid of the use of the map->active field in the vgic and
instead simply set the interrupt as active on the physical distributor
whenever the input to the GIC is asserted and conversely clear the
physical active state when the input to the GIC is deasserted.
Fourth, and finally, we now initialize the timer PPIs (and all the other
unused PPIs for now), to be level-triggered, and modify the sync code to
sample the line state on HW sync and re-inject a new interrupt if it is
still pending at that time.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-30 21:01:27 +08:00
|
|
|
|
2017-02-03 23:20:01 +08:00
|
|
|
if (kvm_timer_should_fire(vtimer) != vtimer->irq.level)
|
|
|
|
kvm_timer_update_irq(vcpu, !vtimer->irq.level, vtimer);
|
2016-02-04 00:56:51 +08:00
|
|
|
|
|
|
|
return 0;
|
arm/arm64: KVM: Rework the arch timer to use level-triggered semantics
The arch timer currently uses edge-triggered semantics in the sense that
the line is never sampled by the vgic and lowering the line from the
timer to the vgic doesn't have any effect on the pending state of
virtual interrupts in the vgic. This means that we do not support a
guest with the otherwise valid behavior of (1) disable interrupts (2)
enable the timer (3) disable the timer (4) enable interrupts. Such a
guest would validly not expect to see any interrupts on real hardware,
but will see interrupts on KVM.
This patch fixes this shortcoming through the following series of
changes.
First, we change the flow of the timer/vgic sync/flush operations. Now
the timer is always flushed/synced before the vgic, because the vgic
samples the state of the timer output. This has the implication that we
move the timer operations in to non-preempible sections, but that is
fine after the previous commit getting rid of hrtimer schedules on every
entry/exit.
Second, we change the internal behavior of the timer, letting the timer
keep track of its previous output state, and only lower/raise the line
to the vgic when the state changes. Note that in theory this could have
been accomplished more simply by signalling the vgic every time the
state *potentially* changed, but we don't want to be hitting the vgic
more often than necessary.
Third, we get rid of the use of the map->active field in the vgic and
instead simply set the interrupt as active on the physical distributor
whenever the input to the GIC is asserted and conversely clear the
physical active state when the input to the GIC is deasserted.
Fourth, and finally, we now initialize the timer PPIs (and all the other
unused PPIs for now), to be level-triggered, and modify the sync code to
sample the line state on HW sync and re-inject a new interrupt if it is
still pending at that time.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-30 21:01:27 +08:00
|
|
|
}
|
|
|
|
|
arm/arm64: KVM: arch_timer: Only schedule soft timer on vcpu_block
We currently schedule a soft timer every time we exit the guest if the
timer did not expire while running the guest. This is really not
necessary, because the only work we do in the timer work function is to
kick the vcpu.
Kicking the vcpu does two things:
(1) If the vpcu thread is on a waitqueue, make it runnable and remove it
from the waitqueue.
(2) If the vcpu is running on a different physical CPU from the one
doing the kick, it sends a reschedule IPI.
The second case cannot happen, because the soft timer is only ever
scheduled when the vcpu is not running. The first case is only relevant
when the vcpu thread is on a waitqueue, which is only the case when the
vcpu thread has called kvm_vcpu_block().
Therefore, we only need to make sure a timer is scheduled for
kvm_vcpu_block(), which we do by encapsulating all calls to
kvm_vcpu_block() with kvm_timer_{un}schedule calls.
Additionally, we only schedule a soft timer if the timer is enabled and
unmasked, since it is useless otherwise.
Note that theoretically userspace can use the SET_ONE_REG interface to
change registers that should cause the timer to fire, even if the vcpu
is blocked without a scheduled timer, but this case was not supported
before this patch and we leave it for future work for now.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-26 01:48:21 +08:00
|
|
|
/*
|
|
|
|
* Schedule the background timer before calling kvm_vcpu_block, so that this
|
|
|
|
* thread is removed from its waitqueue and made runnable when there's a timer
|
|
|
|
* interrupt to handle.
|
|
|
|
*/
|
|
|
|
void kvm_timer_schedule(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
2017-02-03 23:20:01 +08:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
arm/arm64: KVM: arch_timer: Only schedule soft timer on vcpu_block
We currently schedule a soft timer every time we exit the guest if the
timer did not expire while running the guest. This is really not
necessary, because the only work we do in the timer work function is to
kick the vcpu.
Kicking the vcpu does two things:
(1) If the vpcu thread is on a waitqueue, make it runnable and remove it
from the waitqueue.
(2) If the vcpu is running on a different physical CPU from the one
doing the kick, it sends a reschedule IPI.
The second case cannot happen, because the soft timer is only ever
scheduled when the vcpu is not running. The first case is only relevant
when the vcpu thread is on a waitqueue, which is only the case when the
vcpu thread has called kvm_vcpu_block().
Therefore, we only need to make sure a timer is scheduled for
kvm_vcpu_block(), which we do by encapsulating all calls to
kvm_vcpu_block() with kvm_timer_{un}schedule calls.
Additionally, we only schedule a soft timer if the timer is enabled and
unmasked, since it is useless otherwise.
Note that theoretically userspace can use the SET_ONE_REG interface to
change registers that should cause the timer to fire, even if the vcpu
is blocked without a scheduled timer, but this case was not supported
before this patch and we leave it for future work for now.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-26 01:48:21 +08:00
|
|
|
|
|
|
|
BUG_ON(timer_is_armed(timer));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* No need to schedule a background timer if the guest timer has
|
|
|
|
* already expired, because kvm_vcpu_block will return before putting
|
|
|
|
* the thread to sleep.
|
|
|
|
*/
|
2017-02-03 23:20:01 +08:00
|
|
|
if (kvm_timer_should_fire(vtimer))
|
arm/arm64: KVM: arch_timer: Only schedule soft timer on vcpu_block
We currently schedule a soft timer every time we exit the guest if the
timer did not expire while running the guest. This is really not
necessary, because the only work we do in the timer work function is to
kick the vcpu.
Kicking the vcpu does two things:
(1) If the vpcu thread is on a waitqueue, make it runnable and remove it
from the waitqueue.
(2) If the vcpu is running on a different physical CPU from the one
doing the kick, it sends a reschedule IPI.
The second case cannot happen, because the soft timer is only ever
scheduled when the vcpu is not running. The first case is only relevant
when the vcpu thread is on a waitqueue, which is only the case when the
vcpu thread has called kvm_vcpu_block().
Therefore, we only need to make sure a timer is scheduled for
kvm_vcpu_block(), which we do by encapsulating all calls to
kvm_vcpu_block() with kvm_timer_{un}schedule calls.
Additionally, we only schedule a soft timer if the timer is enabled and
unmasked, since it is useless otherwise.
Note that theoretically userspace can use the SET_ONE_REG interface to
change registers that should cause the timer to fire, even if the vcpu
is blocked without a scheduled timer, but this case was not supported
before this patch and we leave it for future work for now.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-26 01:48:21 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the timer is not capable of raising interrupts (disabled or
|
|
|
|
* masked), then there's no more work for us to do.
|
|
|
|
*/
|
2017-02-03 23:20:01 +08:00
|
|
|
if (!kvm_timer_irq_can_fire(vtimer))
|
arm/arm64: KVM: arch_timer: Only schedule soft timer on vcpu_block
We currently schedule a soft timer every time we exit the guest if the
timer did not expire while running the guest. This is really not
necessary, because the only work we do in the timer work function is to
kick the vcpu.
Kicking the vcpu does two things:
(1) If the vpcu thread is on a waitqueue, make it runnable and remove it
from the waitqueue.
(2) If the vcpu is running on a different physical CPU from the one
doing the kick, it sends a reschedule IPI.
The second case cannot happen, because the soft timer is only ever
scheduled when the vcpu is not running. The first case is only relevant
when the vcpu thread is on a waitqueue, which is only the case when the
vcpu thread has called kvm_vcpu_block().
Therefore, we only need to make sure a timer is scheduled for
kvm_vcpu_block(), which we do by encapsulating all calls to
kvm_vcpu_block() with kvm_timer_{un}schedule calls.
Additionally, we only schedule a soft timer if the timer is enabled and
unmasked, since it is useless otherwise.
Note that theoretically userspace can use the SET_ONE_REG interface to
change registers that should cause the timer to fire, even if the vcpu
is blocked without a scheduled timer, but this case was not supported
before this patch and we leave it for future work for now.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-26 01:48:21 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* The timer has not yet expired, schedule a background timer */
|
2017-02-03 23:20:01 +08:00
|
|
|
timer_arm(timer, kvm_timer_compute_delta(vtimer));
|
arm/arm64: KVM: arch_timer: Only schedule soft timer on vcpu_block
We currently schedule a soft timer every time we exit the guest if the
timer did not expire while running the guest. This is really not
necessary, because the only work we do in the timer work function is to
kick the vcpu.
Kicking the vcpu does two things:
(1) If the vpcu thread is on a waitqueue, make it runnable and remove it
from the waitqueue.
(2) If the vcpu is running on a different physical CPU from the one
doing the kick, it sends a reschedule IPI.
The second case cannot happen, because the soft timer is only ever
scheduled when the vcpu is not running. The first case is only relevant
when the vcpu thread is on a waitqueue, which is only the case when the
vcpu thread has called kvm_vcpu_block().
Therefore, we only need to make sure a timer is scheduled for
kvm_vcpu_block(), which we do by encapsulating all calls to
kvm_vcpu_block() with kvm_timer_{un}schedule calls.
Additionally, we only schedule a soft timer if the timer is enabled and
unmasked, since it is useless otherwise.
Note that theoretically userspace can use the SET_ONE_REG interface to
change registers that should cause the timer to fire, even if the vcpu
is blocked without a scheduled timer, but this case was not supported
before this patch and we leave it for future work for now.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-26 01:48:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void kvm_timer_unschedule(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
|
|
|
timer_disarm(timer);
|
|
|
|
}
|
|
|
|
|
2013-01-24 02:21:58 +08:00
|
|
|
/**
|
|
|
|
* kvm_timer_flush_hwstate - prepare to move the virt timer to the cpu
|
|
|
|
* @vcpu: The vcpu pointer
|
|
|
|
*
|
arm/arm64: KVM: arch_timer: Only schedule soft timer on vcpu_block
We currently schedule a soft timer every time we exit the guest if the
timer did not expire while running the guest. This is really not
necessary, because the only work we do in the timer work function is to
kick the vcpu.
Kicking the vcpu does two things:
(1) If the vpcu thread is on a waitqueue, make it runnable and remove it
from the waitqueue.
(2) If the vcpu is running on a different physical CPU from the one
doing the kick, it sends a reschedule IPI.
The second case cannot happen, because the soft timer is only ever
scheduled when the vcpu is not running. The first case is only relevant
when the vcpu thread is on a waitqueue, which is only the case when the
vcpu thread has called kvm_vcpu_block().
Therefore, we only need to make sure a timer is scheduled for
kvm_vcpu_block(), which we do by encapsulating all calls to
kvm_vcpu_block() with kvm_timer_{un}schedule calls.
Additionally, we only schedule a soft timer if the timer is enabled and
unmasked, since it is useless otherwise.
Note that theoretically userspace can use the SET_ONE_REG interface to
change registers that should cause the timer to fire, even if the vcpu
is blocked without a scheduled timer, but this case was not supported
before this patch and we leave it for future work for now.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-26 01:48:21 +08:00
|
|
|
* Check if the virtual timer has expired while we were running in the host,
|
|
|
|
* and inject an interrupt if that was the case.
|
2013-01-24 02:21:58 +08:00
|
|
|
*/
|
|
|
|
void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
2017-02-03 23:19:59 +08:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2015-10-16 18:41:21 +08:00
|
|
|
bool phys_active;
|
|
|
|
int ret;
|
2013-01-24 02:21:58 +08:00
|
|
|
|
2016-02-04 00:56:51 +08:00
|
|
|
if (kvm_timer_update_state(vcpu))
|
|
|
|
return;
|
2015-10-16 18:41:21 +08:00
|
|
|
|
|
|
|
/*
|
2015-11-24 23:23:05 +08:00
|
|
|
* If we enter the guest with the virtual input level to the VGIC
|
|
|
|
* asserted, then we have already told the VGIC what we need to, and
|
|
|
|
* we don't need to exit from the guest until the guest deactivates
|
|
|
|
* the already injected interrupt, so therefore we should set the
|
|
|
|
* hardware active state to prevent unnecessary exits from the guest.
|
|
|
|
*
|
|
|
|
* Also, if we enter the guest with the virtual timer interrupt active,
|
|
|
|
* then it must be active on the physical distributor, because we set
|
|
|
|
* the HW bit and the guest must be able to deactivate the virtual and
|
|
|
|
* physical interrupt at the same time.
|
|
|
|
*
|
|
|
|
* Conversely, if the virtual input level is deasserted and the virtual
|
|
|
|
* interrupt is not active, then always clear the hardware active state
|
|
|
|
* to ensure that hardware interrupts from the timer triggers a guest
|
|
|
|
* exit.
|
|
|
|
*/
|
2017-02-03 23:19:59 +08:00
|
|
|
phys_active = vtimer->irq.level ||
|
|
|
|
kvm_vgic_map_is_active(vcpu, vtimer->irq.irq);
|
2015-10-16 18:41:21 +08:00
|
|
|
|
2016-01-30 03:04:48 +08:00
|
|
|
/*
|
|
|
|
* We want to avoid hitting the (re)distributor as much as
|
|
|
|
* possible, as this is a potentially expensive MMIO access
|
|
|
|
* (not to mention locks in the irq layer), and a solution for
|
|
|
|
* this is to cache the "active" state in memory.
|
|
|
|
*
|
|
|
|
* Things to consider: we cannot cache an "active set" state,
|
|
|
|
* because the HW can change this behind our back (it becomes
|
|
|
|
* "clear" in the HW). We must then restrict the caching to
|
|
|
|
* the "clear" state.
|
|
|
|
*
|
|
|
|
* The cache is invalidated on:
|
|
|
|
* - vcpu put, indicating that the HW cannot be trusted to be
|
|
|
|
* in a sane state on the next vcpu load,
|
|
|
|
* - any change in the interrupt state
|
|
|
|
*
|
|
|
|
* Usage conditions:
|
|
|
|
* - cached value is "active clear"
|
|
|
|
* - value to be programmed is "active clear"
|
|
|
|
*/
|
2017-02-03 23:19:59 +08:00
|
|
|
if (vtimer->active_cleared_last && !phys_active)
|
2016-01-30 03:04:48 +08:00
|
|
|
return;
|
|
|
|
|
2016-06-04 22:41:00 +08:00
|
|
|
ret = irq_set_irqchip_state(host_vtimer_irq,
|
2015-10-16 18:41:21 +08:00
|
|
|
IRQCHIP_STATE_ACTIVE,
|
|
|
|
phys_active);
|
|
|
|
WARN_ON(ret);
|
2016-01-30 03:04:48 +08:00
|
|
|
|
2017-02-03 23:19:59 +08:00
|
|
|
vtimer->active_cleared_last = !phys_active;
|
2013-01-24 02:21:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* kvm_timer_sync_hwstate - sync timer state from cpu
|
|
|
|
* @vcpu: The vcpu pointer
|
|
|
|
*
|
arm/arm64: KVM: arch_timer: Only schedule soft timer on vcpu_block
We currently schedule a soft timer every time we exit the guest if the
timer did not expire while running the guest. This is really not
necessary, because the only work we do in the timer work function is to
kick the vcpu.
Kicking the vcpu does two things:
(1) If the vpcu thread is on a waitqueue, make it runnable and remove it
from the waitqueue.
(2) If the vcpu is running on a different physical CPU from the one
doing the kick, it sends a reschedule IPI.
The second case cannot happen, because the soft timer is only ever
scheduled when the vcpu is not running. The first case is only relevant
when the vcpu thread is on a waitqueue, which is only the case when the
vcpu thread has called kvm_vcpu_block().
Therefore, we only need to make sure a timer is scheduled for
kvm_vcpu_block(), which we do by encapsulating all calls to
kvm_vcpu_block() with kvm_timer_{un}schedule calls.
Additionally, we only schedule a soft timer if the timer is enabled and
unmasked, since it is useless otherwise.
Note that theoretically userspace can use the SET_ONE_REG interface to
change registers that should cause the timer to fire, even if the vcpu
is blocked without a scheduled timer, but this case was not supported
before this patch and we leave it for future work for now.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-26 01:48:21 +08:00
|
|
|
* Check if the virtual timer has expired while we were running in the guest,
|
|
|
|
* and inject an interrupt if that was the case.
|
2013-01-24 02:21:58 +08:00
|
|
|
*/
|
|
|
|
void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
|
|
|
|
|
|
|
BUG_ON(timer_is_armed(timer));
|
|
|
|
|
arm/arm64: KVM: Rework the arch timer to use level-triggered semantics
The arch timer currently uses edge-triggered semantics in the sense that
the line is never sampled by the vgic and lowering the line from the
timer to the vgic doesn't have any effect on the pending state of
virtual interrupts in the vgic. This means that we do not support a
guest with the otherwise valid behavior of (1) disable interrupts (2)
enable the timer (3) disable the timer (4) enable interrupts. Such a
guest would validly not expect to see any interrupts on real hardware,
but will see interrupts on KVM.
This patch fixes this shortcoming through the following series of
changes.
First, we change the flow of the timer/vgic sync/flush operations. Now
the timer is always flushed/synced before the vgic, because the vgic
samples the state of the timer output. This has the implication that we
move the timer operations in to non-preempible sections, but that is
fine after the previous commit getting rid of hrtimer schedules on every
entry/exit.
Second, we change the internal behavior of the timer, letting the timer
keep track of its previous output state, and only lower/raise the line
to the vgic when the state changes. Note that in theory this could have
been accomplished more simply by signalling the vgic every time the
state *potentially* changed, but we don't want to be hitting the vgic
more often than necessary.
Third, we get rid of the use of the map->active field in the vgic and
instead simply set the interrupt as active on the physical distributor
whenever the input to the GIC is asserted and conversely clear the
physical active state when the input to the GIC is deasserted.
Fourth, and finally, we now initialize the timer PPIs (and all the other
unused PPIs for now), to be level-triggered, and modify the sync code to
sample the line state on HW sync and re-inject a new interrupt if it is
still pending at that time.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-30 21:01:27 +08:00
|
|
|
/*
|
|
|
|
* The guest could have modified the timer registers or the timer
|
|
|
|
* could have expired, update the timer state.
|
|
|
|
*/
|
|
|
|
kvm_timer_update_state(vcpu);
|
2013-01-24 02:21:58 +08:00
|
|
|
}
|
|
|
|
|
2014-06-23 20:59:13 +08:00
|
|
|
int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
|
|
|
|
const struct kvm_irq_level *irq)
|
2013-04-30 14:32:15 +08:00
|
|
|
{
|
2017-02-03 23:19:59 +08:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2013-04-30 14:32:15 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The vcpu timer irq number cannot be determined in
|
|
|
|
* kvm_timer_vcpu_init() because it is called much before
|
|
|
|
* kvm_vcpu_set_target(). To handle this, we determine
|
|
|
|
* vcpu timer irq number when the vcpu is reset.
|
|
|
|
*/
|
2017-02-03 23:19:59 +08:00
|
|
|
vtimer->irq.irq = irq->irq;
|
2014-06-23 20:59:13 +08:00
|
|
|
|
2015-09-04 22:24:39 +08:00
|
|
|
/*
|
|
|
|
* The bits in CNTV_CTL are architecturally reset to UNKNOWN for ARMv8
|
|
|
|
* and to 0 for ARMv7. We provide an implementation that always
|
|
|
|
* resets the timer to be disabled and unmasked and is compliant with
|
|
|
|
* the ARMv7 architecture.
|
|
|
|
*/
|
2017-02-03 23:19:59 +08:00
|
|
|
vtimer->cnt_ctl = 0;
|
arm/arm64: KVM: Rework the arch timer to use level-triggered semantics
The arch timer currently uses edge-triggered semantics in the sense that
the line is never sampled by the vgic and lowering the line from the
timer to the vgic doesn't have any effect on the pending state of
virtual interrupts in the vgic. This means that we do not support a
guest with the otherwise valid behavior of (1) disable interrupts (2)
enable the timer (3) disable the timer (4) enable interrupts. Such a
guest would validly not expect to see any interrupts on real hardware,
but will see interrupts on KVM.
This patch fixes this shortcoming through the following series of
changes.
First, we change the flow of the timer/vgic sync/flush operations. Now
the timer is always flushed/synced before the vgic, because the vgic
samples the state of the timer output. This has the implication that we
move the timer operations in to non-preempible sections, but that is
fine after the previous commit getting rid of hrtimer schedules on every
entry/exit.
Second, we change the internal behavior of the timer, letting the timer
keep track of its previous output state, and only lower/raise the line
to the vgic when the state changes. Note that in theory this could have
been accomplished more simply by signalling the vgic every time the
state *potentially* changed, but we don't want to be hitting the vgic
more often than necessary.
Third, we get rid of the use of the map->active field in the vgic and
instead simply set the interrupt as active on the physical distributor
whenever the input to the GIC is asserted and conversely clear the
physical active state when the input to the GIC is deasserted.
Fourth, and finally, we now initialize the timer PPIs (and all the other
unused PPIs for now), to be level-triggered, and modify the sync code to
sample the line state on HW sync and re-inject a new interrupt if it is
still pending at that time.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-30 21:01:27 +08:00
|
|
|
kvm_timer_update_state(vcpu);
|
2015-09-04 22:24:39 +08:00
|
|
|
|
2016-05-18 23:26:00 +08:00
|
|
|
return 0;
|
2013-04-30 14:32:15 +08:00
|
|
|
}
|
|
|
|
|
2017-02-03 23:20:00 +08:00
|
|
|
/* Make the updates of cntvoff for all vtimer contexts atomic */
|
|
|
|
static void update_vtimer_cntvoff(struct kvm_vcpu *vcpu, u64 cntvoff)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct kvm *kvm = vcpu->kvm;
|
|
|
|
struct kvm_vcpu *tmp;
|
|
|
|
|
|
|
|
mutex_lock(&kvm->lock);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2013-01-24 02:21:58 +08:00
|
|
|
void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
|
|
|
|
2017-02-03 23:20:00 +08:00
|
|
|
/* Synchronize cntvoff across all vtimers of a VM. */
|
|
|
|
update_vtimer_cntvoff(vcpu, kvm_phys_timer_read());
|
|
|
|
|
2013-01-24 02:21:58 +08:00
|
|
|
INIT_WORK(&timer->expired, kvm_timer_inject_irq_work);
|
|
|
|
hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
|
|
|
|
timer->timer.function = kvm_timer_expire;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kvm_timer_init_interrupt(void *info)
|
|
|
|
{
|
2016-08-16 22:03:02 +08:00
|
|
|
enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags);
|
2013-01-24 02:21:58 +08:00
|
|
|
}
|
|
|
|
|
2013-12-13 21:23:26 +08:00
|
|
|
int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
|
|
|
|
{
|
2017-02-03 23:19:59 +08:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2013-12-13 21:23:26 +08:00
|
|
|
|
|
|
|
switch (regid) {
|
|
|
|
case KVM_REG_ARM_TIMER_CTL:
|
2017-02-03 23:19:59 +08:00
|
|
|
vtimer->cnt_ctl = value;
|
2013-12-13 21:23:26 +08:00
|
|
|
break;
|
|
|
|
case KVM_REG_ARM_TIMER_CNT:
|
2017-02-03 23:20:00 +08:00
|
|
|
update_vtimer_cntvoff(vcpu, kvm_phys_timer_read() - value);
|
2013-12-13 21:23:26 +08:00
|
|
|
break;
|
|
|
|
case KVM_REG_ARM_TIMER_CVAL:
|
2017-02-03 23:19:59 +08:00
|
|
|
vtimer->cnt_cval = value;
|
2013-12-13 21:23:26 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -1;
|
|
|
|
}
|
arm/arm64: KVM: Rework the arch timer to use level-triggered semantics
The arch timer currently uses edge-triggered semantics in the sense that
the line is never sampled by the vgic and lowering the line from the
timer to the vgic doesn't have any effect on the pending state of
virtual interrupts in the vgic. This means that we do not support a
guest with the otherwise valid behavior of (1) disable interrupts (2)
enable the timer (3) disable the timer (4) enable interrupts. Such a
guest would validly not expect to see any interrupts on real hardware,
but will see interrupts on KVM.
This patch fixes this shortcoming through the following series of
changes.
First, we change the flow of the timer/vgic sync/flush operations. Now
the timer is always flushed/synced before the vgic, because the vgic
samples the state of the timer output. This has the implication that we
move the timer operations in to non-preempible sections, but that is
fine after the previous commit getting rid of hrtimer schedules on every
entry/exit.
Second, we change the internal behavior of the timer, letting the timer
keep track of its previous output state, and only lower/raise the line
to the vgic when the state changes. Note that in theory this could have
been accomplished more simply by signalling the vgic every time the
state *potentially* changed, but we don't want to be hitting the vgic
more often than necessary.
Third, we get rid of the use of the map->active field in the vgic and
instead simply set the interrupt as active on the physical distributor
whenever the input to the GIC is asserted and conversely clear the
physical active state when the input to the GIC is deasserted.
Fourth, and finally, we now initialize the timer PPIs (and all the other
unused PPIs for now), to be level-triggered, and modify the sync code to
sample the line state on HW sync and re-inject a new interrupt if it is
still pending at that time.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2015-08-30 21:01:27 +08:00
|
|
|
|
|
|
|
kvm_timer_update_state(vcpu);
|
2013-12-13 21:23:26 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
|
|
|
|
{
|
2017-02-03 23:19:59 +08:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2013-12-13 21:23:26 +08:00
|
|
|
|
|
|
|
switch (regid) {
|
|
|
|
case KVM_REG_ARM_TIMER_CTL:
|
2017-02-03 23:19:59 +08:00
|
|
|
return vtimer->cnt_ctl;
|
2013-12-13 21:23:26 +08:00
|
|
|
case KVM_REG_ARM_TIMER_CNT:
|
2017-02-03 23:20:00 +08:00
|
|
|
return kvm_phys_timer_read() - vtimer->cntvoff;
|
2013-12-13 21:23:26 +08:00
|
|
|
case KVM_REG_ARM_TIMER_CVAL:
|
2017-02-03 23:19:59 +08:00
|
|
|
return vtimer->cnt_cval;
|
2013-12-13 21:23:26 +08:00
|
|
|
}
|
|
|
|
return (u64)-1;
|
|
|
|
}
|
2013-01-24 02:21:58 +08:00
|
|
|
|
2016-07-14 01:16:47 +08:00
|
|
|
static int kvm_timer_starting_cpu(unsigned int cpu)
|
2013-01-24 02:21:58 +08:00
|
|
|
{
|
2016-07-14 01:16:47 +08:00
|
|
|
kvm_timer_init_interrupt(NULL);
|
|
|
|
return 0;
|
2013-01-24 02:21:58 +08:00
|
|
|
}
|
|
|
|
|
2016-07-14 01:16:47 +08:00
|
|
|
static int kvm_timer_dying_cpu(unsigned int cpu)
|
|
|
|
{
|
|
|
|
disable_percpu_irq(host_vtimer_irq);
|
|
|
|
return 0;
|
|
|
|
}
|
2013-01-24 02:21:58 +08:00
|
|
|
|
|
|
|
int kvm_timer_hyp_init(void)
|
|
|
|
{
|
2016-04-11 23:32:58 +08:00
|
|
|
struct arch_timer_kvm_info *info;
|
2013-01-24 02:21:58 +08:00
|
|
|
int err;
|
|
|
|
|
2016-04-11 23:32:58 +08:00
|
|
|
info = arch_timer_get_kvm_info();
|
|
|
|
timecounter = &info->timecounter;
|
2013-01-24 02:21:58 +08:00
|
|
|
|
2016-12-05 17:32:11 +08:00
|
|
|
if (!timecounter->cc) {
|
|
|
|
kvm_err("kvm_arch_timer: uninitialized timecounter\n");
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2016-04-11 23:32:58 +08:00
|
|
|
if (info->virtual_irq <= 0) {
|
|
|
|
kvm_err("kvm_arch_timer: invalid virtual timer IRQ: %d\n",
|
|
|
|
info->virtual_irq);
|
2013-01-24 02:21:58 +08:00
|
|
|
return -ENODEV;
|
|
|
|
}
|
2016-04-11 23:32:58 +08:00
|
|
|
host_vtimer_irq = info->virtual_irq;
|
2013-01-24 02:21:58 +08:00
|
|
|
|
2016-08-16 22:03:02 +08:00
|
|
|
host_vtimer_irq_flags = irq_get_trigger_type(host_vtimer_irq);
|
|
|
|
if (host_vtimer_irq_flags != IRQF_TRIGGER_HIGH &&
|
|
|
|
host_vtimer_irq_flags != IRQF_TRIGGER_LOW) {
|
|
|
|
kvm_err("Invalid trigger for IRQ%d, assuming level low\n",
|
|
|
|
host_vtimer_irq);
|
|
|
|
host_vtimer_irq_flags = IRQF_TRIGGER_LOW;
|
|
|
|
}
|
|
|
|
|
2016-04-11 23:32:58 +08:00
|
|
|
err = request_percpu_irq(host_vtimer_irq, kvm_arch_timer_handler,
|
2013-01-24 02:21:58 +08:00
|
|
|
"kvm guest timer", kvm_get_running_vcpus());
|
|
|
|
if (err) {
|
|
|
|
kvm_err("kvm_arch_timer: can't request interrupt %d (%d)\n",
|
2016-04-11 23:32:58 +08:00
|
|
|
host_vtimer_irq, err);
|
2016-09-08 18:45:59 +08:00
|
|
|
return err;
|
2013-01-24 02:21:58 +08:00
|
|
|
}
|
|
|
|
|
2016-04-11 23:32:58 +08:00
|
|
|
kvm_info("virtual timer IRQ%d\n", host_vtimer_irq);
|
2013-01-24 02:21:58 +08:00
|
|
|
|
2016-07-14 01:16:47 +08:00
|
|
|
cpuhp_setup_state(CPUHP_AP_KVM_ARM_TIMER_STARTING,
|
2016-12-22 03:19:54 +08:00
|
|
|
"kvm/arm/timer:starting", kvm_timer_starting_cpu,
|
2016-07-14 01:16:47 +08:00
|
|
|
kvm_timer_dying_cpu);
|
2013-01-24 02:21:58 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
2017-02-03 23:19:59 +08:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2013-01-24 02:21:58 +08:00
|
|
|
|
|
|
|
timer_disarm(timer);
|
2017-02-03 23:19:59 +08:00
|
|
|
kvm_vgic_unmap_phys_irq(vcpu, vtimer->irq.irq);
|
2013-01-24 02:21:58 +08:00
|
|
|
}
|
|
|
|
|
2016-05-18 23:26:00 +08:00
|
|
|
int kvm_timer_enable(struct kvm_vcpu *vcpu)
|
2013-01-24 02:21:58 +08:00
|
|
|
{
|
2016-05-18 23:26:00 +08:00
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
2017-02-03 23:19:59 +08:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2016-05-18 23:26:00 +08:00
|
|
|
struct irq_desc *desc;
|
|
|
|
struct irq_data *data;
|
|
|
|
int phys_irq;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (timer->enabled)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find the physical IRQ number corresponding to the host_vtimer_irq
|
|
|
|
*/
|
|
|
|
desc = irq_to_desc(host_vtimer_irq);
|
|
|
|
if (!desc) {
|
|
|
|
kvm_err("%s: no interrupt descriptor\n", __func__);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = irq_desc_get_irq_data(desc);
|
|
|
|
while (data->parent_data)
|
|
|
|
data = data->parent_data;
|
|
|
|
|
|
|
|
phys_irq = data->hwirq;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Tell the VGIC that the virtual interrupt is tied to a
|
|
|
|
* physical interrupt. We do that once per VCPU.
|
|
|
|
*/
|
2017-02-03 23:19:59 +08:00
|
|
|
ret = kvm_vgic_map_phys_irq(vcpu, vtimer->irq.irq, phys_irq);
|
2016-05-18 23:26:00 +08:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
2016-11-09 10:50:14 +08:00
|
|
|
timer->enabled = 1;
|
2016-05-18 23:26:00 +08:00
|
|
|
|
|
|
|
return 0;
|
2014-12-13 04:19:23 +08:00
|
|
|
}
|
2013-01-24 02:21:58 +08:00
|
|
|
|
2016-12-02 03:32:05 +08:00
|
|
|
/*
|
|
|
|
* On VHE system, we only need to configure trap on physical timer and counter
|
|
|
|
* accesses in EL0 and EL1 once, not for every world switch.
|
|
|
|
* The host kernel runs at EL2 with HCR_EL2.TGE == 1,
|
|
|
|
* and this makes those bits have no effect for the host kernel execution.
|
|
|
|
*/
|
|
|
|
void kvm_timer_init_vhe(void)
|
|
|
|
{
|
|
|
|
/* When HCR_EL2.E2H ==1, EL1PCEN and EL1PCTEN are shifted by 10 */
|
|
|
|
u32 cnthctl_shift = 10;
|
|
|
|
u64 val;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Disallow physical timer access for the guest.
|
|
|
|
* Physical counter access is allowed.
|
|
|
|
*/
|
|
|
|
val = read_sysreg(cnthctl_el2);
|
|
|
|
val &= ~(CNTHCTL_EL1PCEN << cnthctl_shift);
|
|
|
|
val |= (CNTHCTL_EL1PCTEN << cnthctl_shift);
|
|
|
|
write_sysreg(val, cnthctl_el2);
|
|
|
|
}
|