From: marc.zyngier@arm.com (Marc Zyngier)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH 4/4] ARM: arch_timers: dynamic switch to physical timer and virtual timer offloading
Date: Fri, 6 Jul 2012 10:20:22 +0100 [thread overview]
Message-ID: <1341566422-20368-5-git-send-email-marc.zyngier@arm.com> (raw)
In-Reply-To: <1341566422-20368-1-git-send-email-marc.zyngier@arm.com>
In an environment supporting virtualization (KVM), the virtual timer
is reserved to the guests, while we rely on the physical timer for
the host.
For this, we need to:
- switch the host CPUs from the virtual timer to the physical one
- provide an interrupt handler that is called by the virtual
timer's interrupt handler.
The new function arch_timer_switch_to_phys() performs this task.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/include/asm/arch_timer.h | 6 +++++
arch/arm/kernel/arch_timer.c | 49 +++++++++++++++++++++++++++++++++++++
2 files changed, 55 insertions(+)
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
index 72c6822..7cd1e27 100644
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -2,11 +2,13 @@
#define __ASMARM_ARCH_TIMER_H
#include <linux/clocksource.h>
+#include <linux/interrupt.h>
#ifdef CONFIG_ARM_ARCH_TIMER
int arch_timer_of_register(void);
int arch_timer_sched_clock_init(void);
struct timecounter *arch_timer_get_timecounter(void);
+void arch_timer_switch_to_phys(irq_handler_t);
#else
static inline int arch_timer_of_register(void)
{
@@ -22,6 +24,10 @@ static inline struct timecounter *arch_timer_get_timecounter(void)
{
return NULL;
}
+
+static inline void arch_timer_switch_to_phys(irq_handler_t handler)
+{
+}
#endif
#endif
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index 4473f66..1bb632a 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -50,6 +50,8 @@ struct arch_timer_reg_ops {
static struct arch_timer_reg_ops __percpu **arch_timer_reg_ops;
+static irq_handler_t arch_timer_virt_external_handler;
+
/*
* Architected system timer support.
*/
@@ -204,6 +206,19 @@ static irqreturn_t arch_timer_handler(int irq, void *dev_id)
static irqreturn_t arch_timer_virt_handler(int irq, void *dev_id)
{
+ if (arch_timer_virt_external_handler) {
+ unsigned long ctrl;
+
+ ctrl = arch_timer_virt_reg_read(ARCH_TIMER_REG_CTRL);
+ if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {
+ ctrl |= ARCH_TIMER_CTRL_IT_MASK;
+ arch_timer_virt_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+ return arch_timer_virt_external_handler(irq, NULL);
+ }
+
+ return IRQ_NONE;
+ }
+
return arch_timer_handler(irq, dev_id);
}
@@ -509,3 +524,37 @@ int __init arch_timer_sched_clock_init(void)
setup_sched_clock(arch_counter_get_cnt32, 32, arch_timer_rate);
return 0;
}
+
+static void arch_timer_switch_cpu_to_phys(void *dummy)
+{
+ u32 cvall, cvalh, val;
+
+ pr_info("Switching CPU%d to physical timer\n", smp_processor_id());
+
+ asm volatile("mrrc p15, 3, %0, %1, c14 \n" /* Read CNTV_CVAL */
+ "mcrr p15, 2, %0, %1, c14 \n" /* Write CNTP_CVAL */
+ : "=r" (cvall), "=r" (cvalh));
+
+ isb();
+
+ val = arch_timer_virt_reg_read(ARCH_TIMER_REG_CTRL);
+ arch_timer_virt_reg_write(ARCH_TIMER_REG_CTRL,
+ val & ~ARCH_TIMER_CTRL_ENABLE);
+ arch_timer_phys_reg_write(ARCH_TIMER_REG_CTRL, val);
+ *__this_cpu_ptr(arch_timer_reg_ops) = &arch_timer_phys_ops;
+}
+
+void arch_timer_switch_to_phys(irq_handler_t handler)
+{
+ int cpu;
+
+ if (!arch_timer_use_virtual)
+ return;
+
+ for_each_online_cpu(cpu)
+ smp_call_function_single(cpu, arch_timer_switch_cpu_to_phys,
+ NULL, 1);
+
+ arch_timer_use_virtual = false;
+ arch_timer_virt_external_handler = handler;
+}
--
1.7.10.3
next prev parent reply other threads:[~2012-07-06 9:20 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-06 9:20 [RFC PATCH 0/4] arch_timers patches to enable KVM support Marc Zyngier
2012-07-06 9:20 ` [RFC PATCH 1/4] ARM: arch_timers: enable the use of the virtual timer Marc Zyngier
2012-07-16 21:12 ` Christopher Covington
2012-07-17 16:41 ` Christopher Covington
2012-07-06 9:20 ` [RFC PATCH 2/4] ARM: arch_timers: register a time/cycle counter Marc Zyngier
2012-07-17 16:41 ` Christopher Covington
2012-07-06 9:20 ` [RFC PATCH 3/4] ARM: arch_timers: give the virtual timer its own interrupt handler Marc Zyngier
2012-07-17 16:57 ` Christopher Covington
2012-07-06 9:20 ` Marc Zyngier [this message]
2012-07-17 19:02 ` [RFC PATCH 4/4] ARM: arch_timers: dynamic switch to physical timer and virtual timer offloading Christopher Covington
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1341566422-20368-5-git-send-email-marc.zyngier@arm.com \
--to=marc.zyngier@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).