2013-01-24 01:21:58 +07: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 21:41:00 +07:00
|
|
|
#include <linux/irq.h>
|
2017-05-03 01:19:15 +07:00
|
|
|
#include <linux/uaccess.h>
|
2013-01-24 01:21:58 +07:00
|
|
|
|
2013-03-27 22:56:11 +07:00
|
|
|
#include <clocksource/arm_arch_timer.h>
|
2013-01-24 01:21:58 +07:00
|
|
|
#include <asm/arch_timer.h>
|
2016-12-02 02:32:05 +07:00
|
|
|
#include <asm/kvm_hyp.h>
|
2013-01-24 01:21:58 +07: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 20:31:01 +07:00
|
|
|
#include <kvm/arm_vgic.h>
|
|
|
|
#include <kvm/arm_arch_timer.h>
|
2013-01-24 01:21:58 +07:00
|
|
|
|
2015-08-30 18:57:20 +07:00
|
|
|
#include "trace.h"
|
|
|
|
|
2013-01-24 01:21:58 +07:00
|
|
|
static struct timecounter *timecounter;
|
2013-04-30 13:32:15 +07:00
|
|
|
static unsigned int host_vtimer_irq;
|
2016-08-16 21:03:02 +07:00
|
|
|
static u32 host_vtimer_irq_flags;
|
2013-01-24 01:21:58 +07:00
|
|
|
|
2018-01-26 22:06:51 +07:00
|
|
|
static DEFINE_STATIC_KEY_FALSE(has_gic_active_state);
|
|
|
|
|
2017-05-03 01:14:06 +07:00
|
|
|
static const struct kvm_irq_level default_ptimer_irq = {
|
|
|
|
.irq = 30,
|
|
|
|
.level = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct kvm_irq_level default_vtimer_irq = {
|
|
|
|
.irq = 27,
|
|
|
|
.level = 1,
|
|
|
|
};
|
|
|
|
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx);
|
|
|
|
static void kvm_timer_update_irq(struct kvm_vcpu *vcpu, bool new_level,
|
|
|
|
struct arch_timer_context *timer_ctx);
|
2017-01-06 22:07:48 +07:00
|
|
|
static bool kvm_timer_should_fire(struct arch_timer_context *timer_ctx);
|
2016-01-30 02:04:48 +07:00
|
|
|
|
2017-02-03 22:20:08 +07:00
|
|
|
u64 kvm_phys_timer_read(void)
|
2013-01-24 01:21:58 +07:00
|
|
|
{
|
|
|
|
return timecounter->cc->read(timecounter->cc);
|
|
|
|
}
|
|
|
|
|
2018-01-26 22:06:51 +07:00
|
|
|
static inline bool userspace_irqchip(struct kvm *kvm)
|
|
|
|
{
|
|
|
|
return static_branch_unlikely(&userspace_irqchip_in_use) &&
|
|
|
|
unlikely(!irqchip_in_kernel(kvm));
|
|
|
|
}
|
|
|
|
|
2017-06-17 15:09:19 +07:00
|
|
|
static void soft_timer_start(struct hrtimer *hrt, u64 ns)
|
2013-01-24 01:21:58 +07:00
|
|
|
{
|
2017-06-17 15:09:19 +07:00
|
|
|
hrtimer_start(hrt, ktime_add_ns(ktime_get(), ns),
|
2013-01-24 01:21:58 +07:00
|
|
|
HRTIMER_MODE_ABS);
|
|
|
|
}
|
|
|
|
|
2017-06-17 15:09:19 +07:00
|
|
|
static void soft_timer_cancel(struct hrtimer *hrt, struct work_struct *work)
|
2013-01-24 01:21:58 +07:00
|
|
|
{
|
2017-06-17 15:09:19 +07:00
|
|
|
hrtimer_cancel(hrt);
|
2017-06-18 14:32:08 +07:00
|
|
|
if (work)
|
|
|
|
cancel_work_sync(work);
|
2013-01-24 01:21:58 +07:00
|
|
|
}
|
|
|
|
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
|
|
|
|
{
|
|
|
|
struct kvm_vcpu *vcpu = *(struct kvm_vcpu **)dev_id;
|
|
|
|
struct arch_timer_context *vtimer;
|
|
|
|
|
2017-12-15 01:54:50 +07:00
|
|
|
/*
|
|
|
|
* We may see a timer interrupt after vcpu_put() has been called which
|
|
|
|
* sets the CPU's vcpu pointer to NULL, because even though the timer
|
|
|
|
* has been disabled in vtimer_save_state(), the hardware interrupt
|
|
|
|
* signal may not have been retired from the interrupt controller yet.
|
|
|
|
*/
|
|
|
|
if (!vcpu)
|
|
|
|
return IRQ_HANDLED;
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
|
2018-01-25 20:20:19 +07:00
|
|
|
vtimer = vcpu_vtimer(vcpu);
|
|
|
|
if (kvm_timer_should_fire(vtimer))
|
KVM: arm/arm64: Don't cache the timer IRQ level
The timer logic was designed after a strict idea of modeling an
interrupt line level in software, meaning that only transitions in the
level need to be reported to the VGIC. This works well for the timer,
because the arch timer code is in complete control of the device and can
track the transitions of the line.
However, as we are about to support using the HW bit in the VGIC not
just for the timer, but also for VFIO which cannot track transitions of
the interrupt line, we have to decide on an interface between the GIC
and other subsystems for level triggered mapped interrupts, which both
the timer and VFIO can use.
VFIO only sees an asserting transition of the physical interrupt line,
and tells the VGIC when that happens. That means that part of the
interrupt flow is offloaded to the hardware.
To use the same interface for VFIO devices and the timer, we therefore
have to change the timer (we cannot change VFIO because it doesn't know
the details of the device it is assigning to a VM).
Luckily, changing the timer is simple, we just need to stop 'caching'
the line level, but instead let the VGIC know the state of the timer
every time there is a potential change in the line level, and when the
line level should be asserted from the timer ISR. The VGIC can ignore
extra notifications using its validate mechanism.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Julien Thierry <julien.thierry@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2017-09-04 16:56:37 +07:00
|
|
|
kvm_timer_update_irq(vcpu, true, vtimer);
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
|
2018-01-26 22:06:51 +07:00
|
|
|
if (userspace_irqchip(vcpu->kvm) &&
|
|
|
|
!static_branch_unlikely(&has_gic_active_state))
|
|
|
|
disable_percpu_irq(host_vtimer_irq);
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
|
2013-01-24 01:21:58 +07:00
|
|
|
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 00:02:55 +07: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 01:21:58 +07: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 15:37:22 +07: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 00:02:55 +07: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.
|
|
|
|
*/
|
2017-06-04 19:44:01 +07:00
|
|
|
kvm_vcpu_wake_up(vcpu);
|
2013-01-24 01:21:58 +07:00
|
|
|
}
|
|
|
|
|
2017-02-03 22:20:01 +07:00
|
|
|
static u64 kvm_timer_compute_delta(struct arch_timer_context *timer_ctx)
|
2016-04-06 15:37:22 +07:00
|
|
|
{
|
2016-12-22 02:32:01 +07:00
|
|
|
u64 cval, now;
|
2016-04-06 15:37:22 +07:00
|
|
|
|
2017-02-03 22:20:01 +07:00
|
|
|
cval = timer_ctx->cnt_cval;
|
|
|
|
now = kvm_phys_timer_read() - timer_ctx->cntvoff;
|
2016-04-06 15:37:22 +07:00
|
|
|
|
|
|
|
if (now < cval) {
|
|
|
|
u64 ns;
|
|
|
|
|
|
|
|
ns = cyclecounter_cyc2ns(timecounter->cc,
|
|
|
|
cval - now,
|
|
|
|
timecounter->mask,
|
|
|
|
&timecounter->frac);
|
|
|
|
return ns;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-02-03 22:20:05 +07:00
|
|
|
static bool kvm_timer_irq_can_fire(struct arch_timer_context *timer_ctx)
|
|
|
|
{
|
|
|
|
return !(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_IT_MASK) &&
|
|
|
|
(timer_ctx->cnt_ctl & ARCH_TIMER_CTRL_ENABLE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns the earliest expiration time in ns among guest timers.
|
|
|
|
* Note that it will return 0 if none of timers can fire.
|
|
|
|
*/
|
|
|
|
static u64 kvm_timer_earliest_exp(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
u64 min_virt = ULLONG_MAX, min_phys = ULLONG_MAX;
|
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
|
|
|
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
|
|
|
|
|
|
|
|
if (kvm_timer_irq_can_fire(vtimer))
|
|
|
|
min_virt = kvm_timer_compute_delta(vtimer);
|
|
|
|
|
|
|
|
if (kvm_timer_irq_can_fire(ptimer))
|
|
|
|
min_phys = kvm_timer_compute_delta(ptimer);
|
|
|
|
|
|
|
|
/* If none of timers can fire, then return 0 */
|
|
|
|
if ((min_virt == ULLONG_MAX) && (min_phys == ULLONG_MAX))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return min(min_virt, min_phys);
|
|
|
|
}
|
|
|
|
|
2017-06-17 21:33:02 +07:00
|
|
|
static enum hrtimer_restart kvm_bg_timer_expire(struct hrtimer *hrt)
|
2013-01-24 01:21:58 +07:00
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer;
|
2016-04-06 15:37:22 +07:00
|
|
|
struct kvm_vcpu *vcpu;
|
|
|
|
u64 ns;
|
|
|
|
|
2017-06-17 21:33:02 +07:00
|
|
|
timer = container_of(hrt, struct arch_timer_cpu, bg_timer);
|
2016-04-06 15:37:22 +07: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 22:20:05 +07:00
|
|
|
ns = kvm_timer_earliest_exp(vcpu);
|
2016-04-06 15:37:22 +07:00
|
|
|
if (unlikely(ns)) {
|
|
|
|
hrtimer_forward_now(hrt, ns_to_ktime(ns));
|
|
|
|
return HRTIMER_RESTART;
|
|
|
|
}
|
|
|
|
|
2016-08-31 00:59:51 +07:00
|
|
|
schedule_work(&timer->expired);
|
2013-01-24 01:21:58 +07:00
|
|
|
return HRTIMER_NORESTART;
|
|
|
|
}
|
|
|
|
|
2017-06-18 14:32:08 +07:00
|
|
|
static enum hrtimer_restart kvm_phys_timer_expire(struct hrtimer *hrt)
|
|
|
|
{
|
2017-06-18 15:42:55 +07:00
|
|
|
struct arch_timer_context *ptimer;
|
|
|
|
struct arch_timer_cpu *timer;
|
|
|
|
struct kvm_vcpu *vcpu;
|
|
|
|
u64 ns;
|
|
|
|
|
|
|
|
timer = container_of(hrt, struct arch_timer_cpu, phys_timer);
|
|
|
|
vcpu = container_of(timer, struct kvm_vcpu, arch.timer_cpu);
|
|
|
|
ptimer = vcpu_ptimer(vcpu);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check that the timer has really expired from the guest's
|
|
|
|
* PoV (NTP on the host may have forced it to expire
|
|
|
|
* early). If not ready, schedule for a later time.
|
|
|
|
*/
|
|
|
|
ns = kvm_timer_compute_delta(ptimer);
|
|
|
|
if (unlikely(ns)) {
|
|
|
|
hrtimer_forward_now(hrt, ns_to_ktime(ns));
|
|
|
|
return HRTIMER_RESTART;
|
|
|
|
}
|
|
|
|
|
|
|
|
kvm_timer_update_irq(vcpu, true, ptimer);
|
2017-06-18 14:32:08 +07:00
|
|
|
return HRTIMER_NORESTART;
|
|
|
|
}
|
|
|
|
|
2017-01-06 22:07:48 +07:00
|
|
|
static 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 00:02:55 +07:00
|
|
|
{
|
2016-12-22 02:32:01 +07: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 00:02:55 +07:00
|
|
|
|
2018-01-25 20:20:19 +07:00
|
|
|
if (timer_ctx->loaded) {
|
|
|
|
u32 cnt_ctl;
|
|
|
|
|
|
|
|
/* Only the virtual timer can be loaded so far */
|
|
|
|
cnt_ctl = read_sysreg_el0(cntv_ctl);
|
|
|
|
return (cnt_ctl & ARCH_TIMER_CTRL_ENABLE) &&
|
|
|
|
(cnt_ctl & ARCH_TIMER_CTRL_IT_STAT) &&
|
|
|
|
!(cnt_ctl & ARCH_TIMER_CTRL_IT_MASK);
|
|
|
|
}
|
|
|
|
|
2017-02-03 22:20:01 +07: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 00:02:55 +07:00
|
|
|
return false;
|
|
|
|
|
2017-02-03 22:20:01 +07: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 00:02:55 +07:00
|
|
|
|
|
|
|
return cval <= now;
|
|
|
|
}
|
|
|
|
|
2017-01-06 22:07:48 +07:00
|
|
|
bool kvm_timer_is_pending(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
|
|
|
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
|
|
|
|
|
2018-01-25 20:20:19 +07:00
|
|
|
if (kvm_timer_should_fire(vtimer))
|
2017-01-06 22:07:48 +07:00
|
|
|
return true;
|
|
|
|
|
|
|
|
return kvm_timer_should_fire(ptimer);
|
|
|
|
}
|
|
|
|
|
KVM: arm/arm64: Support arch timers with a userspace gic
If you're running with a userspace gic or other interrupt controller
(that is no vgic in the kernel), then you have so far not been able to
use the architected timers, because the output of the architected
timers, which are driven inside the kernel, was a kernel-only construct
between the arch timer code and the vgic.
This patch implements the new KVM_CAP_ARM_USER_IRQ feature, where we use a
side channel on the kvm_run structure, run->s.regs.device_irq_level, to
always notify userspace of the timer output levels when using a userspace
irqchip.
This works by ensuring that before we enter the guest, if the timer
output level has changed compared to what we last told userspace, we
don't enter the guest, but instead return to userspace to notify it of
the new level. If we are exiting, because of an MMIO for example, and
the level changed at the same time, the value is also updated and
userspace can sample the line as it needs. This is nicely achieved
simply always updating the timer_irq_level field after the main run
loop.
Note that the kvm_timer_update_irq trace event is changed to show the
host IRQ number for the timer instead of the guest IRQ number, because
the kernel no longer know which IRQ userspace wires up the timer signal
to.
Also note that this patch implements all required functionality but does
not yet advertise the capability.
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2016-09-28 02:08:06 +07:00
|
|
|
/*
|
|
|
|
* Reflect the timer output level into the kvm_run structure
|
|
|
|
*/
|
|
|
|
void kvm_timer_update_run(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
|
|
|
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
|
|
|
|
struct kvm_sync_regs *regs = &vcpu->run->s.regs;
|
|
|
|
|
|
|
|
/* Populate the device bitmap with the timer states */
|
|
|
|
regs->device_irq_level &= ~(KVM_ARM_DEV_EL1_VTIMER |
|
|
|
|
KVM_ARM_DEV_EL1_PTIMER);
|
2018-01-25 20:20:19 +07:00
|
|
|
if (kvm_timer_should_fire(vtimer))
|
KVM: arm/arm64: Support arch timers with a userspace gic
If you're running with a userspace gic or other interrupt controller
(that is no vgic in the kernel), then you have so far not been able to
use the architected timers, because the output of the architected
timers, which are driven inside the kernel, was a kernel-only construct
between the arch timer code and the vgic.
This patch implements the new KVM_CAP_ARM_USER_IRQ feature, where we use a
side channel on the kvm_run structure, run->s.regs.device_irq_level, to
always notify userspace of the timer output levels when using a userspace
irqchip.
This works by ensuring that before we enter the guest, if the timer
output level has changed compared to what we last told userspace, we
don't enter the guest, but instead return to userspace to notify it of
the new level. If we are exiting, because of an MMIO for example, and
the level changed at the same time, the value is also updated and
userspace can sample the line as it needs. This is nicely achieved
simply always updating the timer_irq_level field after the main run
loop.
Note that the kvm_timer_update_irq trace event is changed to show the
host IRQ number for the timer instead of the guest IRQ number, because
the kernel no longer know which IRQ userspace wires up the timer signal
to.
Also note that this patch implements all required functionality but does
not yet advertise the capability.
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2016-09-28 02:08:06 +07:00
|
|
|
regs->device_irq_level |= KVM_ARM_DEV_EL1_VTIMER;
|
2018-01-25 20:20:19 +07:00
|
|
|
if (kvm_timer_should_fire(ptimer))
|
KVM: arm/arm64: Support arch timers with a userspace gic
If you're running with a userspace gic or other interrupt controller
(that is no vgic in the kernel), then you have so far not been able to
use the architected timers, because the output of the architected
timers, which are driven inside the kernel, was a kernel-only construct
between the arch timer code and the vgic.
This patch implements the new KVM_CAP_ARM_USER_IRQ feature, where we use a
side channel on the kvm_run structure, run->s.regs.device_irq_level, to
always notify userspace of the timer output levels when using a userspace
irqchip.
This works by ensuring that before we enter the guest, if the timer
output level has changed compared to what we last told userspace, we
don't enter the guest, but instead return to userspace to notify it of
the new level. If we are exiting, because of an MMIO for example, and
the level changed at the same time, the value is also updated and
userspace can sample the line as it needs. This is nicely achieved
simply always updating the timer_irq_level field after the main run
loop.
Note that the kvm_timer_update_irq trace event is changed to show the
host IRQ number for the timer instead of the guest IRQ number, because
the kernel no longer know which IRQ userspace wires up the timer signal
to.
Also note that this patch implements all required functionality but does
not yet advertise the capability.
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2016-09-28 02:08:06 +07:00
|
|
|
regs->device_irq_level |= KVM_ARM_DEV_EL1_PTIMER;
|
|
|
|
}
|
|
|
|
|
2017-02-03 22:20:01 +07: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 20:01:27 +07:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2017-02-03 22:20:01 +07:00
|
|
|
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 17:03:45 +07:00
|
|
|
|
2018-01-26 22:06:51 +07:00
|
|
|
if (!userspace_irqchip(vcpu->kvm)) {
|
KVM: arm/arm64: Support arch timers with a userspace gic
If you're running with a userspace gic or other interrupt controller
(that is no vgic in the kernel), then you have so far not been able to
use the architected timers, because the output of the architected
timers, which are driven inside the kernel, was a kernel-only construct
between the arch timer code and the vgic.
This patch implements the new KVM_CAP_ARM_USER_IRQ feature, where we use a
side channel on the kvm_run structure, run->s.regs.device_irq_level, to
always notify userspace of the timer output levels when using a userspace
irqchip.
This works by ensuring that before we enter the guest, if the timer
output level has changed compared to what we last told userspace, we
don't enter the guest, but instead return to userspace to notify it of
the new level. If we are exiting, because of an MMIO for example, and
the level changed at the same time, the value is also updated and
userspace can sample the line as it needs. This is nicely achieved
simply always updating the timer_irq_level field after the main run
loop.
Note that the kvm_timer_update_irq trace event is changed to show the
host IRQ number for the timer instead of the guest IRQ number, because
the kernel no longer know which IRQ userspace wires up the timer signal
to.
Also note that this patch implements all required functionality but does
not yet advertise the capability.
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2016-09-28 02:08:06 +07:00
|
|
|
ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
|
|
|
|
timer_ctx->irq.irq,
|
2017-05-16 17:41:18 +07:00
|
|
|
timer_ctx->irq.level,
|
|
|
|
timer_ctx);
|
KVM: arm/arm64: Support arch timers with a userspace gic
If you're running with a userspace gic or other interrupt controller
(that is no vgic in the kernel), then you have so far not been able to
use the architected timers, because the output of the architected
timers, which are driven inside the kernel, was a kernel-only construct
between the arch timer code and the vgic.
This patch implements the new KVM_CAP_ARM_USER_IRQ feature, where we use a
side channel on the kvm_run structure, run->s.regs.device_irq_level, to
always notify userspace of the timer output levels when using a userspace
irqchip.
This works by ensuring that before we enter the guest, if the timer
output level has changed compared to what we last told userspace, we
don't enter the guest, but instead return to userspace to notify it of
the new level. If we are exiting, because of an MMIO for example, and
the level changed at the same time, the value is also updated and
userspace can sample the line as it needs. This is nicely achieved
simply always updating the timer_irq_level field after the main run
loop.
Note that the kvm_timer_update_irq trace event is changed to show the
host IRQ number for the timer instead of the guest IRQ number, because
the kernel no longer know which IRQ userspace wires up the timer signal
to.
Also note that this patch implements all required functionality but does
not yet advertise the capability.
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2016-09-28 02:08:06 +07:00
|
|
|
WARN_ON(ret);
|
|
|
|
}
|
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 20:01:27 +07:00
|
|
|
}
|
|
|
|
|
2017-06-18 15:41:06 +07:00
|
|
|
/* Schedule the background timer for the emulated timer. */
|
2017-06-18 15:42:55 +07:00
|
|
|
static void phys_timer_emulate(struct kvm_vcpu *vcpu)
|
2017-06-18 15:41:06 +07:00
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
2017-06-18 15:42:55 +07:00
|
|
|
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
|
2017-06-18 15:41:06 +07:00
|
|
|
|
2017-06-18 15:42:55 +07:00
|
|
|
/*
|
KVM: arm/arm64: Fix potential loss of ptimer interrupts
kvm_timer_update_state() is called when changing the phys timer
configuration registers, either via vcpu reset, as a result of a trap
from the guest, or when userspace programs the registers.
phys_timer_emulate() is in turn called by kvm_timer_update_state() to
either cancel an existing software timer, or program a new software
timer, to emulate the behavior of a real phys timer, based on the change
in configuration registers.
Unfortunately, the interaction between these two functions left a small
race; if the conceptual emulated phys timer should actually fire, but
the soft timer hasn't executed its callback yet, we cancel the timer in
phys_timer_emulate without injecting an irq. This only happens if the
check in kvm_timer_update_state is called before the timer should fire,
which is relatively unlikely, but possible.
The solution is to update the state of the phys timer after calling
phys_timer_emulate, which will pick up the pending timer state and
update the interrupt value.
Note that this leaves the opportunity of raising the interrupt twice,
once in the just-programmed soft timer, and once in
kvm_timer_update_state. Since this always happens synchronously with
the VCPU execution, there is no harm in this, and the guest ever only
sees a single timer interrupt.
Cc: Stable <stable@vger.kernel.org> # 4.15+
Signed-off-by: Christoffer Dall <christoffer.dall@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2018-07-25 16:21:27 +07:00
|
|
|
* If the timer can fire now, we don't need to have a soft timer
|
|
|
|
* scheduled for the future. If the timer cannot fire at all,
|
|
|
|
* then we also don't need a soft timer.
|
2017-06-18 15:42:55 +07:00
|
|
|
*/
|
|
|
|
if (kvm_timer_should_fire(ptimer) || !kvm_timer_irq_can_fire(ptimer)) {
|
|
|
|
soft_timer_cancel(&timer->phys_timer, NULL);
|
2017-06-18 15:41:06 +07:00
|
|
|
return;
|
2017-06-18 15:42:55 +07:00
|
|
|
}
|
2017-06-18 15:41:06 +07:00
|
|
|
|
2017-06-18 15:42:55 +07:00
|
|
|
soft_timer_start(&timer->phys_timer, kvm_timer_compute_delta(ptimer));
|
2017-06-18 15:41:06 +07:00
|
|
|
}
|
|
|
|
|
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 20:01:27 +07:00
|
|
|
/*
|
2017-06-18 15:42:55 +07:00
|
|
|
* Check if there was a change in the timer state, so that we should either
|
|
|
|
* raise or lower the line level to the GIC or schedule a background timer to
|
|
|
|
* emulate the physical 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 20:01:27 +07:00
|
|
|
*/
|
2016-09-28 02:08:04 +07:00
|
|
|
static void 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 20:01:27 +07:00
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
2017-02-03 22:19:59 +07:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2017-02-03 22:20:04 +07:00
|
|
|
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
|
KVM: arm/arm64: Don't cache the timer IRQ level
The timer logic was designed after a strict idea of modeling an
interrupt line level in software, meaning that only transitions in the
level need to be reported to the VGIC. This works well for the timer,
because the arch timer code is in complete control of the device and can
track the transitions of the line.
However, as we are about to support using the HW bit in the VGIC not
just for the timer, but also for VFIO which cannot track transitions of
the interrupt line, we have to decide on an interface between the GIC
and other subsystems for level triggered mapped interrupts, which both
the timer and VFIO can use.
VFIO only sees an asserting transition of the physical interrupt line,
and tells the VGIC when that happens. That means that part of the
interrupt flow is offloaded to the hardware.
To use the same interface for VFIO devices and the timer, we therefore
have to change the timer (we cannot change VFIO because it doesn't know
the details of the device it is assigning to a VM).
Luckily, changing the timer is simple, we just need to stop 'caching'
the line level, but instead let the VGIC know the state of the timer
every time there is a potential change in the line level, and when the
line level should be asserted from the timer ISR. The VGIC can ignore
extra notifications using its validate mechanism.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Julien Thierry <julien.thierry@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2017-09-04 16:56:37 +07:00
|
|
|
bool 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 20:01:27 +07:00
|
|
|
|
KVM: arm/arm64: Support arch timers with a userspace gic
If you're running with a userspace gic or other interrupt controller
(that is no vgic in the kernel), then you have so far not been able to
use the architected timers, because the output of the architected
timers, which are driven inside the kernel, was a kernel-only construct
between the arch timer code and the vgic.
This patch implements the new KVM_CAP_ARM_USER_IRQ feature, where we use a
side channel on the kvm_run structure, run->s.regs.device_irq_level, to
always notify userspace of the timer output levels when using a userspace
irqchip.
This works by ensuring that before we enter the guest, if the timer
output level has changed compared to what we last told userspace, we
don't enter the guest, but instead return to userspace to notify it of
the new level. If we are exiting, because of an MMIO for example, and
the level changed at the same time, the value is also updated and
userspace can sample the line as it needs. This is nicely achieved
simply always updating the timer_irq_level field after the main run
loop.
Note that the kvm_timer_update_irq trace event is changed to show the
host IRQ number for the timer instead of the guest IRQ number, because
the kernel no longer know which IRQ userspace wires up the timer signal
to.
Also note that this patch implements all required functionality but does
not yet advertise the capability.
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2016-09-28 02:08:06 +07:00
|
|
|
if (unlikely(!timer->enabled))
|
2016-09-28 02:08:04 +07:00
|
|
|
return;
|
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 20:01:27 +07:00
|
|
|
|
KVM: arm/arm64: Don't cache the timer IRQ level
The timer logic was designed after a strict idea of modeling an
interrupt line level in software, meaning that only transitions in the
level need to be reported to the VGIC. This works well for the timer,
because the arch timer code is in complete control of the device and can
track the transitions of the line.
However, as we are about to support using the HW bit in the VGIC not
just for the timer, but also for VFIO which cannot track transitions of
the interrupt line, we have to decide on an interface between the GIC
and other subsystems for level triggered mapped interrupts, which both
the timer and VFIO can use.
VFIO only sees an asserting transition of the physical interrupt line,
and tells the VGIC when that happens. That means that part of the
interrupt flow is offloaded to the hardware.
To use the same interface for VFIO devices and the timer, we therefore
have to change the timer (we cannot change VFIO because it doesn't know
the details of the device it is assigning to a VM).
Luckily, changing the timer is simple, we just need to stop 'caching'
the line level, but instead let the VGIC know the state of the timer
every time there is a potential change in the line level, and when the
line level should be asserted from the timer ISR. The VGIC can ignore
extra notifications using its validate mechanism.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Julien Thierry <julien.thierry@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2017-09-04 16:56:37 +07:00
|
|
|
/*
|
|
|
|
* The vtimer virtual interrupt is a 'mapped' interrupt, meaning part
|
|
|
|
* of its lifecycle is offloaded to the hardware, and we therefore may
|
|
|
|
* not have lowered the irq.level value before having to signal a new
|
|
|
|
* interrupt, but have to signal an interrupt every time the level is
|
|
|
|
* asserted.
|
|
|
|
*/
|
|
|
|
level = kvm_timer_should_fire(vtimer);
|
|
|
|
kvm_timer_update_irq(vcpu, level, vtimer);
|
2016-02-03 23:56:51 +07:00
|
|
|
|
KVM: arm/arm64: Fix potential loss of ptimer interrupts
kvm_timer_update_state() is called when changing the phys timer
configuration registers, either via vcpu reset, as a result of a trap
from the guest, or when userspace programs the registers.
phys_timer_emulate() is in turn called by kvm_timer_update_state() to
either cancel an existing software timer, or program a new software
timer, to emulate the behavior of a real phys timer, based on the change
in configuration registers.
Unfortunately, the interaction between these two functions left a small
race; if the conceptual emulated phys timer should actually fire, but
the soft timer hasn't executed its callback yet, we cancel the timer in
phys_timer_emulate without injecting an irq. This only happens if the
check in kvm_timer_update_state is called before the timer should fire,
which is relatively unlikely, but possible.
The solution is to update the state of the phys timer after calling
phys_timer_emulate, which will pick up the pending timer state and
update the interrupt value.
Note that this leaves the opportunity of raising the interrupt twice,
once in the just-programmed soft timer, and once in
kvm_timer_update_state. Since this always happens synchronously with
the VCPU execution, there is no harm in this, and the guest ever only
sees a single timer interrupt.
Cc: Stable <stable@vger.kernel.org> # 4.15+
Signed-off-by: Christoffer Dall <christoffer.dall@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
2018-07-25 16:21:27 +07:00
|
|
|
phys_timer_emulate(vcpu);
|
|
|
|
|
2017-02-03 22:20:04 +07:00
|
|
|
if (kvm_timer_should_fire(ptimer) != ptimer->irq.level)
|
|
|
|
kvm_timer_update_irq(vcpu, !ptimer->irq.level, ptimer);
|
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 20:01:27 +07:00
|
|
|
}
|
|
|
|
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
static void vtimer_save_state(struct kvm_vcpu *vcpu)
|
2017-01-04 22:10:28 +07:00
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
local_irq_save(flags);
|
|
|
|
|
|
|
|
if (!vtimer->loaded)
|
|
|
|
goto out;
|
2017-01-04 22:10:28 +07:00
|
|
|
|
2018-01-26 22:06:51 +07:00
|
|
|
if (timer->enabled) {
|
|
|
|
vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl);
|
|
|
|
vtimer->cnt_cval = read_sysreg_el0(cntv_cval);
|
|
|
|
}
|
2017-01-04 22:10:28 +07:00
|
|
|
|
|
|
|
/* Disable the virtual timer */
|
|
|
|
write_sysreg_el0(0, cntv_ctl);
|
2017-12-15 01:54:50 +07:00
|
|
|
isb();
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
|
|
|
|
vtimer->loaded = false;
|
|
|
|
out:
|
|
|
|
local_irq_restore(flags);
|
2017-01-04 22:10:28 +07: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 00:48:21 +07: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 22:20:01 +07:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2017-02-03 22:20:05 +07:00
|
|
|
struct arch_timer_context *ptimer = vcpu_ptimer(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 00:48:21 +07:00
|
|
|
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
vtimer_save_state(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 00:48:21 +07:00
|
|
|
/*
|
2017-02-03 22:20:05 +07:00
|
|
|
* No need to schedule a background timer if any guest timer has
|
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 00:48:21 +07:00
|
|
|
* already expired, because kvm_vcpu_block will return before putting
|
|
|
|
* the thread to sleep.
|
|
|
|
*/
|
2017-02-03 22:20:05 +07:00
|
|
|
if (kvm_timer_should_fire(vtimer) || kvm_timer_should_fire(ptimer))
|
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 00:48:21 +07:00
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
2017-02-03 22:20:05 +07:00
|
|
|
* If both timers are not capable of raising interrupts (disabled or
|
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 00:48:21 +07:00
|
|
|
* masked), then there's no more work for us to do.
|
|
|
|
*/
|
2017-02-03 22:20:05 +07:00
|
|
|
if (!kvm_timer_irq_can_fire(vtimer) && !kvm_timer_irq_can_fire(ptimer))
|
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 00:48:21 +07:00
|
|
|
return;
|
|
|
|
|
2017-02-03 22:20:05 +07:00
|
|
|
/*
|
|
|
|
* The guest timers have not yet expired, schedule a background timer.
|
|
|
|
* Set the earliest expiration time among the guest timers.
|
|
|
|
*/
|
2017-06-17 21:33:02 +07:00
|
|
|
soft_timer_start(&timer->bg_timer, kvm_timer_earliest_exp(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 00:48:21 +07:00
|
|
|
}
|
|
|
|
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
static void vtimer_restore_state(struct kvm_vcpu *vcpu)
|
2017-01-04 22:10:28 +07:00
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
local_irq_save(flags);
|
|
|
|
|
|
|
|
if (vtimer->loaded)
|
|
|
|
goto out;
|
2017-01-04 22:10:28 +07:00
|
|
|
|
|
|
|
if (timer->enabled) {
|
|
|
|
write_sysreg_el0(vtimer->cnt_cval, cntv_cval);
|
|
|
|
isb();
|
|
|
|
write_sysreg_el0(vtimer->cnt_ctl, cntv_ctl);
|
|
|
|
}
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
|
|
|
|
vtimer->loaded = true;
|
|
|
|
out:
|
|
|
|
local_irq_restore(flags);
|
2017-01-04 22:10:28 +07: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 00:48:21 +07:00
|
|
|
void kvm_timer_unschedule(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
2017-06-17 15:09:19 +07:00
|
|
|
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
vtimer_restore_state(vcpu);
|
|
|
|
|
2017-06-17 21:33:02 +07:00
|
|
|
soft_timer_cancel(&timer->bg_timer, &timer->expired);
|
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 00:48:21 +07:00
|
|
|
}
|
|
|
|
|
2017-01-04 22:10:28 +07:00
|
|
|
static void set_cntvoff(u64 cntvoff)
|
|
|
|
{
|
|
|
|
u32 low = lower_32_bits(cntvoff);
|
|
|
|
u32 high = upper_32_bits(cntvoff);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Since kvm_call_hyp doesn't fully support the ARM PCS especially on
|
|
|
|
* 32-bit systems, but rather passes register by register shifted one
|
|
|
|
* place (we put the function address in r0/x0), we cannot simply pass
|
|
|
|
* a 64-bit value as an argument, but have to split the value in two
|
|
|
|
* 32-bit halves.
|
|
|
|
*/
|
|
|
|
kvm_call_hyp(__kvm_timer_set_cntvoff, low, high);
|
|
|
|
}
|
|
|
|
|
2018-01-26 22:06:51 +07:00
|
|
|
static inline void set_vtimer_irq_phys_active(struct kvm_vcpu *vcpu, bool active)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
r = irq_set_irqchip_state(host_vtimer_irq, IRQCHIP_STATE_ACTIVE, active);
|
|
|
|
WARN_ON(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kvm_timer_vcpu_load_gic(struct kvm_vcpu *vcpu)
|
2013-01-24 01:21:58 +07:00
|
|
|
{
|
2017-02-03 22:19:59 +07:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2015-10-16 17:41:21 +07:00
|
|
|
bool phys_active;
|
2016-01-30 02:04:48 +07:00
|
|
|
|
2018-01-26 22:06:51 +07:00
|
|
|
if (irqchip_in_kernel(vcpu->kvm))
|
|
|
|
phys_active = kvm_vgic_map_is_active(vcpu, vtimer->irq.irq);
|
|
|
|
else
|
|
|
|
phys_active = vtimer->irq.level;
|
|
|
|
set_vtimer_irq_phys_active(vcpu, phys_active);
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
}
|
2016-01-30 02:04:48 +07:00
|
|
|
|
2018-01-26 22:06:51 +07:00
|
|
|
static void kvm_timer_vcpu_load_nogic(struct kvm_vcpu *vcpu)
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
{
|
2018-01-26 22:06:51 +07:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* When using a userspace irqchip with the architected timers and a
|
|
|
|
* host interrupt controller that doesn't support an active state, we
|
|
|
|
* must still prevent continuously exiting from the guest, and
|
|
|
|
* therefore mask the physical interrupt by disabling it on the host
|
|
|
|
* interrupt controller when the virtual level is high, such that the
|
|
|
|
* guest can make forward progress. Once we detect the output level
|
|
|
|
* being de-asserted, we unmask the interrupt again so that we exit
|
|
|
|
* from the guest when the timer fires.
|
|
|
|
*/
|
|
|
|
if (vtimer->irq.level)
|
|
|
|
disable_percpu_irq(host_vtimer_irq);
|
|
|
|
else
|
|
|
|
enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags);
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2018-07-25 16:21:28 +07:00
|
|
|
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
|
|
|
|
if (unlikely(!timer->enabled))
|
|
|
|
return;
|
|
|
|
|
2018-01-26 22:06:51 +07:00
|
|
|
if (static_branch_likely(&has_gic_active_state))
|
|
|
|
kvm_timer_vcpu_load_gic(vcpu);
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
else
|
2018-01-26 22:06:51 +07:00
|
|
|
kvm_timer_vcpu_load_nogic(vcpu);
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
|
|
|
|
set_cntvoff(vtimer->cntvoff);
|
|
|
|
|
|
|
|
vtimer_restore_state(vcpu);
|
|
|
|
|
2017-06-18 15:42:55 +07:00
|
|
|
/* Set the background timer for the physical timer emulation. */
|
|
|
|
phys_timer_emulate(vcpu);
|
2018-07-25 16:21:28 +07:00
|
|
|
|
|
|
|
/* If the timer fired while we weren't running, inject it now */
|
|
|
|
if (kvm_timer_should_fire(ptimer) != ptimer->irq.level)
|
|
|
|
kvm_timer_update_irq(vcpu, !ptimer->irq.level, ptimer);
|
2013-01-24 01:21:58 +07:00
|
|
|
}
|
|
|
|
|
KVM: arm/arm64: Support arch timers with a userspace gic
If you're running with a userspace gic or other interrupt controller
(that is no vgic in the kernel), then you have so far not been able to
use the architected timers, because the output of the architected
timers, which are driven inside the kernel, was a kernel-only construct
between the arch timer code and the vgic.
This patch implements the new KVM_CAP_ARM_USER_IRQ feature, where we use a
side channel on the kvm_run structure, run->s.regs.device_irq_level, to
always notify userspace of the timer output levels when using a userspace
irqchip.
This works by ensuring that before we enter the guest, if the timer
output level has changed compared to what we last told userspace, we
don't enter the guest, but instead return to userspace to notify it of
the new level. If we are exiting, because of an MMIO for example, and
the level changed at the same time, the value is also updated and
userspace can sample the line as it needs. This is nicely achieved
simply always updating the timer_irq_level field after the main run
loop.
Note that the kvm_timer_update_irq trace event is changed to show the
host IRQ number for the timer instead of the guest IRQ number, because
the kernel no longer know which IRQ userspace wires up the timer signal
to.
Also note that this patch implements all required functionality but does
not yet advertise the capability.
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2016-09-28 02:08:06 +07:00
|
|
|
bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
|
|
|
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
|
|
|
|
struct kvm_sync_regs *sregs = &vcpu->run->s.regs;
|
|
|
|
bool vlevel, plevel;
|
|
|
|
|
|
|
|
if (likely(irqchip_in_kernel(vcpu->kvm)))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
vlevel = sregs->device_irq_level & KVM_ARM_DEV_EL1_VTIMER;
|
|
|
|
plevel = sregs->device_irq_level & KVM_ARM_DEV_EL1_PTIMER;
|
|
|
|
|
2018-01-25 20:20:19 +07:00
|
|
|
return kvm_timer_should_fire(vtimer) != vlevel ||
|
|
|
|
kvm_timer_should_fire(ptimer) != plevel;
|
KVM: arm/arm64: Support arch timers with a userspace gic
If you're running with a userspace gic or other interrupt controller
(that is no vgic in the kernel), then you have so far not been able to
use the architected timers, because the output of the architected
timers, which are driven inside the kernel, was a kernel-only construct
between the arch timer code and the vgic.
This patch implements the new KVM_CAP_ARM_USER_IRQ feature, where we use a
side channel on the kvm_run structure, run->s.regs.device_irq_level, to
always notify userspace of the timer output levels when using a userspace
irqchip.
This works by ensuring that before we enter the guest, if the timer
output level has changed compared to what we last told userspace, we
don't enter the guest, but instead return to userspace to notify it of
the new level. If we are exiting, because of an MMIO for example, and
the level changed at the same time, the value is also updated and
userspace can sample the line as it needs. This is nicely achieved
simply always updating the timer_irq_level field after the main run
loop.
Note that the kvm_timer_update_irq trace event is changed to show the
host IRQ number for the timer instead of the guest IRQ number, because
the kernel no longer know which IRQ userspace wires up the timer signal
to.
Also note that this patch implements all required functionality but does
not yet advertise the capability.
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2016-09-28 02:08:06 +07:00
|
|
|
}
|
|
|
|
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
2017-01-04 22:10:28 +07:00
|
|
|
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
if (unlikely(!timer->enabled))
|
|
|
|
return;
|
|
|
|
|
|
|
|
vtimer_save_state(vcpu);
|
|
|
|
|
2017-06-18 15:42:55 +07:00
|
|
|
/*
|
|
|
|
* Cancel the physical timer emulation, because the only case where we
|
|
|
|
* need it after a vcpu_put is in the context of a sleeping VCPU, and
|
|
|
|
* in that case we already factor in the deadline for the physical
|
|
|
|
* timer when scheduling the bg_timer.
|
|
|
|
*
|
|
|
|
* In any case, we re-schedule the hrtimer for the physical timer when
|
|
|
|
* coming back to the VCPU thread in kvm_timer_vcpu_load().
|
|
|
|
*/
|
|
|
|
soft_timer_cancel(&timer->phys_timer, NULL);
|
|
|
|
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
/*
|
|
|
|
* The kernel may decide to run userspace after calling vcpu_put, so
|
|
|
|
* we reset cntvoff to 0 to ensure a consistent read between user
|
|
|
|
* accesses to the virtual counter and kernel access to the physical
|
2018-02-19 22:38:07 +07:00
|
|
|
* counter of non-VHE case. For VHE, the virtual counter uses a fixed
|
|
|
|
* virtual offset of zero, so no need to zero CNTVOFF_EL2 register.
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
*/
|
2018-02-19 22:38:07 +07:00
|
|
|
if (!has_vhe())
|
|
|
|
set_cntvoff(0);
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
}
|
|
|
|
|
2017-10-28 00:34:30 +07:00
|
|
|
/*
|
|
|
|
* With a userspace irqchip we have to check if the guest de-asserted the
|
|
|
|
* timer and if so, unmask the timer irq signal on the host interrupt
|
|
|
|
* controller to ensure that we see future timer signals.
|
|
|
|
*/
|
|
|
|
static void unmask_vtimer_irq_user(struct kvm_vcpu *vcpu)
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
{
|
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
|
|
|
|
2018-01-26 22:06:51 +07:00
|
|
|
if (!kvm_timer_should_fire(vtimer)) {
|
|
|
|
kvm_timer_update_irq(vcpu, false, vtimer);
|
|
|
|
if (static_branch_likely(&has_gic_active_state))
|
|
|
|
set_vtimer_irq_phys_active(vcpu, false);
|
|
|
|
else
|
|
|
|
enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags);
|
KVM: arm/arm64: Avoid timer save/restore in vcpu entry/exit
We don't need to save and restore the hardware timer state and examine
if it generates interrupts on on every entry/exit to the guest. The
timer hardware is perfectly capable of telling us when it has expired
by signaling interrupts.
When taking a vtimer interrupt in the host, we don't want to mess with
the timer configuration, we just want to forward the physical interrupt
to the guest as a virtual interrupt. We can use the split priority drop
and deactivate feature of the GIC to do this, which leaves an EOI'ed
interrupt active on the physical distributor, making sure we don't keep
taking timer interrupts which would prevent the guest from running. We
can then forward the physical interrupt to the VM using the HW bit in
the LR of the GIC, like we do already, which lets the guest directly
deactivate both the physical and virtual timer simultaneously, allowing
the timer hardware to exit the VM and generate a new physical interrupt
when the timer output is again asserted later on.
We do need to capture this state when migrating VCPUs between physical
CPUs, however, which we use the vcpu put/load functions for, which are
called through preempt notifiers whenever the thread is scheduled away
from the CPU or called directly if we return from the ioctl to
userspace.
One caveat is that we have to save and restore the timer state in both
kvm_timer_vcpu_[put/load] and kvm_timer_[schedule/unschedule], because
we can have the following flows:
1. kvm_vcpu_block
2. kvm_timer_schedule
3. schedule
4. kvm_timer_vcpu_put (preempt notifier)
5. schedule (vcpu thread gets scheduled back)
6. kvm_timer_vcpu_load (preempt notifier)
7. kvm_timer_unschedule
And a version where we don't actually call schedule:
1. kvm_vcpu_block
2. kvm_timer_schedule
7. kvm_timer_unschedule
Since kvm_timer_[schedule/unschedule] may not be followed by put/load,
but put/load also may be called independently, we call the timer
save/restore functions from both paths. Since they rely on the loaded
flag to never save/restore when unnecessary, this doesn't cause any
harm, and we ensure that all invokations of either set of functions work
as intended.
An added benefit beyond not having to read and write the timer sysregs
on every entry and exit is that we no longer have to actively write the
active state to the physical distributor, because we configured the
irq for the vtimer to only get a priority drop when handling the
interrupt in the GIC driver (we called irq_set_vcpu_affinity()), and
the interrupt stays active after firing on the host.
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
2016-10-17 01:30:38 +07:00
|
|
|
}
|
KVM: arm/arm64: Support arch timers with a userspace gic
If you're running with a userspace gic or other interrupt controller
(that is no vgic in the kernel), then you have so far not been able to
use the architected timers, because the output of the architected
timers, which are driven inside the kernel, was a kernel-only construct
between the arch timer code and the vgic.
This patch implements the new KVM_CAP_ARM_USER_IRQ feature, where we use a
side channel on the kvm_run structure, run->s.regs.device_irq_level, to
always notify userspace of the timer output levels when using a userspace
irqchip.
This works by ensuring that before we enter the guest, if the timer
output level has changed compared to what we last told userspace, we
don't enter the guest, but instead return to userspace to notify it of
the new level. If we are exiting, because of an MMIO for example, and
the level changed at the same time, the value is also updated and
userspace can sample the line as it needs. This is nicely achieved
simply always updating the timer_irq_level field after the main run
loop.
Note that the kvm_timer_update_irq trace event is changed to show the
host IRQ number for the timer instead of the guest IRQ number, because
the kernel no longer know which IRQ userspace wires up the timer signal
to.
Also note that this patch implements all required functionality but does
not yet advertise the capability.
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2016-09-28 02:08:06 +07:00
|
|
|
}
|
|
|
|
|
2013-01-24 01:21:58 +07:00
|
|
|
void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
2018-01-26 22:06:51 +07:00
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
|
|
|
|
|
|
|
if (unlikely(!timer->enabled))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (unlikely(!irqchip_in_kernel(vcpu->kvm)))
|
|
|
|
unmask_vtimer_irq_user(vcpu);
|
2013-01-24 01:21:58 +07:00
|
|
|
}
|
|
|
|
|
2017-05-03 01:14:06 +07:00
|
|
|
int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu)
|
2013-04-30 13:32:15 +07:00
|
|
|
{
|
2018-03-05 17:36:38 +07:00
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
2017-02-03 22:19:59 +07:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2017-02-03 22:20:03 +07:00
|
|
|
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
|
2013-04-30 13:32:15 +07:00
|
|
|
|
2015-09-04 21:24:39 +07: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 22:19:59 +07:00
|
|
|
vtimer->cnt_ctl = 0;
|
2017-02-03 22:20:03 +07:00
|
|
|
ptimer->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 20:01:27 +07:00
|
|
|
kvm_timer_update_state(vcpu);
|
2015-09-04 21:24:39 +07:00
|
|
|
|
2018-03-05 17:36:38 +07:00
|
|
|
if (timer->enabled && irqchip_in_kernel(vcpu->kvm))
|
|
|
|
kvm_vgic_reset_mapped_irq(vcpu, vtimer->irq.irq);
|
|
|
|
|
2016-05-18 22:26:00 +07:00
|
|
|
return 0;
|
2013-04-30 13:32:15 +07:00
|
|
|
}
|
|
|
|
|
2017-02-03 22:20:00 +07: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 01:21:58 +07:00
|
|
|
void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
2017-05-03 01:14:06 +07:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
|
|
|
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
|
2013-01-24 01:21:58 +07:00
|
|
|
|
2017-02-03 22:20:00 +07:00
|
|
|
/* Synchronize cntvoff across all vtimers of a VM. */
|
|
|
|
update_vtimer_cntvoff(vcpu, kvm_phys_timer_read());
|
2017-02-03 22:20:03 +07:00
|
|
|
vcpu_ptimer(vcpu)->cntvoff = 0;
|
2017-02-03 22:20:00 +07:00
|
|
|
|
2013-01-24 01:21:58 +07:00
|
|
|
INIT_WORK(&timer->expired, kvm_timer_inject_irq_work);
|
2017-06-17 21:33:02 +07:00
|
|
|
hrtimer_init(&timer->bg_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
|
|
|
|
timer->bg_timer.function = kvm_bg_timer_expire;
|
2017-05-03 01:14:06 +07:00
|
|
|
|
2017-06-18 14:32:08 +07:00
|
|
|
hrtimer_init(&timer->phys_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
|
|
|
|
timer->phys_timer.function = kvm_phys_timer_expire;
|
|
|
|
|
2017-05-03 01:14:06 +07:00
|
|
|
vtimer->irq.irq = default_vtimer_irq.irq;
|
|
|
|
ptimer->irq.irq = default_ptimer_irq.irq;
|
2013-01-24 01:21:58 +07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void kvm_timer_init_interrupt(void *info)
|
|
|
|
{
|
2016-08-16 21:03:02 +07:00
|
|
|
enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags);
|
2013-01-24 01:21:58 +07:00
|
|
|
}
|
|
|
|
|
2013-12-13 20:23:26 +07:00
|
|
|
int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
|
|
|
|
{
|
2017-02-03 22:19:59 +07:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2017-06-17 13:08:57 +07:00
|
|
|
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
|
2013-12-13 20:23:26 +07:00
|
|
|
|
|
|
|
switch (regid) {
|
|
|
|
case KVM_REG_ARM_TIMER_CTL:
|
2017-06-17 13:08:57 +07:00
|
|
|
vtimer->cnt_ctl = value & ~ARCH_TIMER_CTRL_IT_STAT;
|
2013-12-13 20:23:26 +07:00
|
|
|
break;
|
|
|
|
case KVM_REG_ARM_TIMER_CNT:
|
2017-02-03 22:20:00 +07:00
|
|
|
update_vtimer_cntvoff(vcpu, kvm_phys_timer_read() - value);
|
2013-12-13 20:23:26 +07:00
|
|
|
break;
|
|
|
|
case KVM_REG_ARM_TIMER_CVAL:
|
2017-02-03 22:19:59 +07:00
|
|
|
vtimer->cnt_cval = value;
|
2013-12-13 20:23:26 +07:00
|
|
|
break;
|
2017-06-17 13:08:57 +07:00
|
|
|
case KVM_REG_ARM_PTIMER_CTL:
|
|
|
|
ptimer->cnt_ctl = value & ~ARCH_TIMER_CTRL_IT_STAT;
|
|
|
|
break;
|
|
|
|
case KVM_REG_ARM_PTIMER_CVAL:
|
|
|
|
ptimer->cnt_cval = value;
|
|
|
|
break;
|
|
|
|
|
2013-12-13 20:23:26 +07:00
|
|
|
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 20:01:27 +07:00
|
|
|
|
|
|
|
kvm_timer_update_state(vcpu);
|
2013-12-13 20:23:26 +07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-06-17 13:08:57 +07:00
|
|
|
static u64 read_timer_ctl(struct arch_timer_context *timer)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Set ISTATUS bit if it's expired.
|
|
|
|
* Note that according to ARMv8 ARM Issue A.k, ISTATUS bit is
|
|
|
|
* UNKNOWN when ENABLE bit is 0, so we chose to set ISTATUS bit
|
|
|
|
* regardless of ENABLE bit for our implementation convenience.
|
|
|
|
*/
|
|
|
|
if (!kvm_timer_compute_delta(timer))
|
|
|
|
return timer->cnt_ctl | ARCH_TIMER_CTRL_IT_STAT;
|
|
|
|
else
|
|
|
|
return timer->cnt_ctl;
|
|
|
|
}
|
|
|
|
|
2013-12-13 20:23:26 +07:00
|
|
|
u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid)
|
|
|
|
{
|
2017-06-17 13:08:57 +07:00
|
|
|
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
|
2017-02-03 22:19:59 +07:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2013-12-13 20:23:26 +07:00
|
|
|
|
|
|
|
switch (regid) {
|
|
|
|
case KVM_REG_ARM_TIMER_CTL:
|
2017-06-17 13:08:57 +07:00
|
|
|
return read_timer_ctl(vtimer);
|
2013-12-13 20:23:26 +07:00
|
|
|
case KVM_REG_ARM_TIMER_CNT:
|
2017-02-03 22:20:00 +07:00
|
|
|
return kvm_phys_timer_read() - vtimer->cntvoff;
|
2013-12-13 20:23:26 +07:00
|
|
|
case KVM_REG_ARM_TIMER_CVAL:
|
2017-02-03 22:19:59 +07:00
|
|
|
return vtimer->cnt_cval;
|
2017-06-17 13:08:57 +07:00
|
|
|
case KVM_REG_ARM_PTIMER_CTL:
|
|
|
|
return read_timer_ctl(ptimer);
|
|
|
|
case KVM_REG_ARM_PTIMER_CVAL:
|
|
|
|
return ptimer->cnt_cval;
|
|
|
|
case KVM_REG_ARM_PTIMER_CNT:
|
|
|
|
return kvm_phys_timer_read();
|
2013-12-13 20:23:26 +07:00
|
|
|
}
|
|
|
|
return (u64)-1;
|
|
|
|
}
|
2013-01-24 01:21:58 +07:00
|
|
|
|
2016-07-14 00:16:47 +07:00
|
|
|
static int kvm_timer_starting_cpu(unsigned int cpu)
|
2013-01-24 01:21:58 +07:00
|
|
|
{
|
2016-07-14 00:16:47 +07:00
|
|
|
kvm_timer_init_interrupt(NULL);
|
|
|
|
return 0;
|
2013-01-24 01:21:58 +07:00
|
|
|
}
|
|
|
|
|
2016-07-14 00:16:47 +07:00
|
|
|
static int kvm_timer_dying_cpu(unsigned int cpu)
|
|
|
|
{
|
|
|
|
disable_percpu_irq(host_vtimer_irq);
|
|
|
|
return 0;
|
|
|
|
}
|
2013-01-24 01:21:58 +07:00
|
|
|
|
2017-12-07 18:46:15 +07:00
|
|
|
int kvm_timer_hyp_init(bool has_gic)
|
2013-01-24 01:21:58 +07:00
|
|
|
{
|
2016-04-11 22:32:58 +07:00
|
|
|
struct arch_timer_kvm_info *info;
|
2013-01-24 01:21:58 +07:00
|
|
|
int err;
|
|
|
|
|
2016-04-11 22:32:58 +07:00
|
|
|
info = arch_timer_get_kvm_info();
|
|
|
|
timecounter = &info->timecounter;
|
2013-01-24 01:21:58 +07:00
|
|
|
|
2016-12-05 16:32:11 +07:00
|
|
|
if (!timecounter->cc) {
|
|
|
|
kvm_err("kvm_arch_timer: uninitialized timecounter\n");
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
2016-04-11 22:32:58 +07:00
|
|
|
if (info->virtual_irq <= 0) {
|
|
|
|
kvm_err("kvm_arch_timer: invalid virtual timer IRQ: %d\n",
|
|
|
|
info->virtual_irq);
|
2013-01-24 01:21:58 +07:00
|
|
|
return -ENODEV;
|
|
|
|
}
|
2016-04-11 22:32:58 +07:00
|
|
|
host_vtimer_irq = info->virtual_irq;
|
2013-01-24 01:21:58 +07:00
|
|
|
|
2016-08-16 21:03:02 +07: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 22:32:58 +07:00
|
|
|
err = request_percpu_irq(host_vtimer_irq, kvm_arch_timer_handler,
|
2013-01-24 01:21:58 +07: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 22:32:58 +07:00
|
|
|
host_vtimer_irq, err);
|
2016-09-08 17:45:59 +07:00
|
|
|
return err;
|
2013-01-24 01:21:58 +07:00
|
|
|
}
|
|
|
|
|
2017-12-07 18:46:15 +07:00
|
|
|
if (has_gic) {
|
|
|
|
err = irq_set_vcpu_affinity(host_vtimer_irq,
|
|
|
|
kvm_get_running_vcpus());
|
|
|
|
if (err) {
|
|
|
|
kvm_err("kvm_arch_timer: error setting vcpu affinity\n");
|
|
|
|
goto out_free_irq;
|
|
|
|
}
|
2018-01-26 22:06:51 +07:00
|
|
|
|
|
|
|
static_branch_enable(&has_gic_active_state);
|
2017-07-05 17:50:27 +07:00
|
|
|
}
|
|
|
|
|
2018-03-02 15:16:30 +07:00
|
|
|
kvm_debug("virtual timer IRQ%d\n", host_vtimer_irq);
|
2013-01-24 01:21:58 +07:00
|
|
|
|
2016-07-14 00:16:47 +07:00
|
|
|
cpuhp_setup_state(CPUHP_AP_KVM_ARM_TIMER_STARTING,
|
2016-12-22 02:19:54 +07:00
|
|
|
"kvm/arm/timer:starting", kvm_timer_starting_cpu,
|
2016-07-14 00:16:47 +07:00
|
|
|
kvm_timer_dying_cpu);
|
2017-07-05 17:50:27 +07:00
|
|
|
return 0;
|
|
|
|
out_free_irq:
|
|
|
|
free_percpu_irq(host_vtimer_irq, kvm_get_running_vcpus());
|
2013-01-24 01:21:58 +07:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
|
|
|
|
{
|
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
2017-02-03 22:19:59 +07:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2013-01-24 01:21:58 +07:00
|
|
|
|
2017-06-17 21:33:02 +07:00
|
|
|
soft_timer_cancel(&timer->bg_timer, &timer->expired);
|
2017-06-18 14:32:08 +07:00
|
|
|
soft_timer_cancel(&timer->phys_timer, NULL);
|
2017-02-03 22:19:59 +07:00
|
|
|
kvm_vgic_unmap_phys_irq(vcpu, vtimer->irq.irq);
|
2013-01-24 01:21:58 +07:00
|
|
|
}
|
|
|
|
|
2017-05-04 18:32:53 +07:00
|
|
|
static bool timer_irqs_are_valid(struct kvm_vcpu *vcpu)
|
2017-05-03 01:19:15 +07:00
|
|
|
{
|
|
|
|
int vtimer_irq, ptimer_irq;
|
2017-05-04 18:32:53 +07:00
|
|
|
int i, ret;
|
2017-05-03 01:19:15 +07:00
|
|
|
|
|
|
|
vtimer_irq = vcpu_vtimer(vcpu)->irq.irq;
|
2017-05-04 18:32:53 +07:00
|
|
|
ret = kvm_vgic_set_owner(vcpu, vtimer_irq, vcpu_vtimer(vcpu));
|
|
|
|
if (ret)
|
|
|
|
return false;
|
2017-05-03 01:19:15 +07:00
|
|
|
|
2017-05-04 18:32:53 +07:00
|
|
|
ptimer_irq = vcpu_ptimer(vcpu)->irq.irq;
|
|
|
|
ret = kvm_vgic_set_owner(vcpu, ptimer_irq, vcpu_ptimer(vcpu));
|
|
|
|
if (ret)
|
2017-05-03 01:19:15 +07:00
|
|
|
return false;
|
|
|
|
|
2017-05-04 18:32:53 +07:00
|
|
|
kvm_for_each_vcpu(i, vcpu, vcpu->kvm) {
|
2017-05-03 01:19:15 +07:00
|
|
|
if (vcpu_vtimer(vcpu)->irq.irq != vtimer_irq ||
|
|
|
|
vcpu_ptimer(vcpu)->irq.irq != ptimer_irq)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-10-28 00:34:30 +07:00
|
|
|
bool kvm_arch_timer_get_input_level(int vintid)
|
|
|
|
{
|
|
|
|
struct kvm_vcpu *vcpu = kvm_arm_get_running_vcpu();
|
|
|
|
struct arch_timer_context *timer;
|
|
|
|
|
|
|
|
if (vintid == vcpu_vtimer(vcpu)->irq.irq)
|
|
|
|
timer = vcpu_vtimer(vcpu);
|
|
|
|
else
|
|
|
|
BUG(); /* We only map the vtimer so far */
|
|
|
|
|
|
|
|
return kvm_timer_should_fire(timer);
|
|
|
|
}
|
|
|
|
|
2016-05-18 22:26:00 +07:00
|
|
|
int kvm_timer_enable(struct kvm_vcpu *vcpu)
|
2013-01-24 01:21:58 +07:00
|
|
|
{
|
2016-05-18 22:26:00 +07:00
|
|
|
struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
|
2017-02-03 22:19:59 +07:00
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
2016-05-18 22:26:00 +07:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (timer->enabled)
|
|
|
|
return 0;
|
|
|
|
|
KVM: arm/arm64: Support arch timers with a userspace gic
If you're running with a userspace gic or other interrupt controller
(that is no vgic in the kernel), then you have so far not been able to
use the architected timers, because the output of the architected
timers, which are driven inside the kernel, was a kernel-only construct
between the arch timer code and the vgic.
This patch implements the new KVM_CAP_ARM_USER_IRQ feature, where we use a
side channel on the kvm_run structure, run->s.regs.device_irq_level, to
always notify userspace of the timer output levels when using a userspace
irqchip.
This works by ensuring that before we enter the guest, if the timer
output level has changed compared to what we last told userspace, we
don't enter the guest, but instead return to userspace to notify it of
the new level. If we are exiting, because of an MMIO for example, and
the level changed at the same time, the value is also updated and
userspace can sample the line as it needs. This is nicely achieved
simply always updating the timer_irq_level field after the main run
loop.
Note that the kvm_timer_update_irq trace event is changed to show the
host IRQ number for the timer instead of the guest IRQ number, because
the kernel no longer know which IRQ userspace wires up the timer signal
to.
Also note that this patch implements all required functionality but does
not yet advertise the capability.
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2016-09-28 02:08:06 +07:00
|
|
|
/* Without a VGIC we do not map virtual IRQs to physical IRQs */
|
|
|
|
if (!irqchip_in_kernel(vcpu->kvm))
|
|
|
|
goto no_vgic;
|
|
|
|
|
|
|
|
if (!vgic_initialized(vcpu->kvm))
|
|
|
|
return -ENODEV;
|
|
|
|
|
2017-05-04 18:32:53 +07:00
|
|
|
if (!timer_irqs_are_valid(vcpu)) {
|
2017-05-03 01:19:15 +07:00
|
|
|
kvm_debug("incorrectly configured timer irqs\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2017-10-28 00:30:09 +07:00
|
|
|
ret = kvm_vgic_map_phys_irq(vcpu, host_vtimer_irq, vtimer->irq.irq,
|
2017-10-28 00:34:30 +07:00
|
|
|
kvm_arch_timer_get_input_level);
|
2016-05-18 22:26:00 +07:00
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
|
KVM: arm/arm64: Support arch timers with a userspace gic
If you're running with a userspace gic or other interrupt controller
(that is no vgic in the kernel), then you have so far not been able to
use the architected timers, because the output of the architected
timers, which are driven inside the kernel, was a kernel-only construct
between the arch timer code and the vgic.
This patch implements the new KVM_CAP_ARM_USER_IRQ feature, where we use a
side channel on the kvm_run structure, run->s.regs.device_irq_level, to
always notify userspace of the timer output levels when using a userspace
irqchip.
This works by ensuring that before we enter the guest, if the timer
output level has changed compared to what we last told userspace, we
don't enter the guest, but instead return to userspace to notify it of
the new level. If we are exiting, because of an MMIO for example, and
the level changed at the same time, the value is also updated and
userspace can sample the line as it needs. This is nicely achieved
simply always updating the timer_irq_level field after the main run
loop.
Note that the kvm_timer_update_irq trace event is changed to show the
host IRQ number for the timer instead of the guest IRQ number, because
the kernel no longer know which IRQ userspace wires up the timer signal
to.
Also note that this patch implements all required functionality but does
not yet advertise the capability.
Reviewed-by: Alexander Graf <agraf@suse.de>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
2016-09-28 02:08:06 +07:00
|
|
|
no_vgic:
|
2016-11-09 09:50:14 +07:00
|
|
|
timer->enabled = 1;
|
2016-05-18 22:26:00 +07:00
|
|
|
return 0;
|
2014-12-13 03:19:23 +07:00
|
|
|
}
|
2013-01-24 01:21:58 +07:00
|
|
|
|
2016-12-02 02:32:05 +07: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);
|
|
|
|
}
|
2017-05-03 01:19:15 +07:00
|
|
|
|
|
|
|
static void set_timer_irqs(struct kvm *kvm, int vtimer_irq, int ptimer_irq)
|
|
|
|
{
|
|
|
|
struct kvm_vcpu *vcpu;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
kvm_for_each_vcpu(i, vcpu, kvm) {
|
|
|
|
vcpu_vtimer(vcpu)->irq.irq = vtimer_irq;
|
|
|
|
vcpu_ptimer(vcpu)->irq.irq = ptimer_irq;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int kvm_arm_timer_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
|
|
|
|
{
|
|
|
|
int __user *uaddr = (int __user *)(long)attr->addr;
|
|
|
|
struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
|
|
|
|
struct arch_timer_context *ptimer = vcpu_ptimer(vcpu);
|
|
|
|
int irq;
|
|
|
|
|
|
|
|
if (!irqchip_in_kernel(vcpu->kvm))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (get_user(irq, uaddr))
|
|
|
|
return -EFAULT;
|
|
|
|
|
|
|
|
if (!(irq_is_ppi(irq)))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (vcpu->arch.timer_cpu.enabled)
|
|
|
|
return -EBUSY;
|
|
|
|
|
|
|
|
switch (attr->attr) {
|
|
|
|
case KVM_ARM_VCPU_TIMER_IRQ_VTIMER:
|
|
|
|
set_timer_irqs(vcpu->kvm, irq, ptimer->irq.irq);
|
|
|
|
break;
|
|
|
|
case KVM_ARM_VCPU_TIMER_IRQ_PTIMER:
|
|
|
|
set_timer_irqs(vcpu->kvm, vtimer->irq.irq, irq);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int kvm_arm_timer_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
|
|
|
|
{
|
|
|
|
int __user *uaddr = (int __user *)(long)attr->addr;
|
|
|
|
struct arch_timer_context *timer;
|
|
|
|
int irq;
|
|
|
|
|
|
|
|
switch (attr->attr) {
|
|
|
|
case KVM_ARM_VCPU_TIMER_IRQ_VTIMER:
|
|
|
|
timer = vcpu_vtimer(vcpu);
|
|
|
|
break;
|
|
|
|
case KVM_ARM_VCPU_TIMER_IRQ_PTIMER:
|
|
|
|
timer = vcpu_ptimer(vcpu);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return -ENXIO;
|
|
|
|
}
|
|
|
|
|
|
|
|
irq = timer->irq.irq;
|
|
|
|
return put_user(irq, uaddr);
|
|
|
|
}
|
|
|
|
|
|
|
|
int kvm_arm_timer_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
|
|
|
|
{
|
|
|
|
switch (attr->attr) {
|
|
|
|
case KVM_ARM_VCPU_TIMER_IRQ_VTIMER:
|
|
|
|
case KVM_ARM_VCPU_TIMER_IRQ_PTIMER:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -ENXIO;
|
|
|
|
}
|