From: Richard Henderson <rth@twiddle.net>
To: linux-kernel@vger.kernel.org
Cc: ink@jurassic.park.msu.ru, mattst88@gmail.com,
linux-alpha@vger.kernel.org, Thomas Gleixner <tglx@linutronix.de>
Subject: [RFC PATCH 10/10] alpha: Use qemu+cserve provided high-res clock and alarm.
Date: Tue, 16 Jul 2013 10:34:18 -0700 [thread overview]
Message-ID: <1373996058-13399-11-git-send-email-rth@twiddle.net> (raw)
In-Reply-To: <1373996058-13399-1-git-send-email-rth@twiddle.net>
QEMU provides a high-resolution timer and alarm; use this for
a clock source and clock event source when available.
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Richard Henderson <rth@twiddle.net>
---
arch/alpha/include/asm/pal.h | 14 ++++++
arch/alpha/kernel/irq_alpha.c | 2 +-
arch/alpha/kernel/proto.h | 2 +-
arch/alpha/kernel/time.c | 106 ++++++++++++++++++++++++++++++++++++++++--
4 files changed, 117 insertions(+), 7 deletions(-)
diff --git a/arch/alpha/include/asm/pal.h b/arch/alpha/include/asm/pal.h
index ccaa49a..5422a47 100644
--- a/arch/alpha/include/asm/pal.h
+++ b/arch/alpha/include/asm/pal.h
@@ -168,5 +168,19 @@ qemu_set_alarm_abs(unsigned long expire)
: "$0", "$18", "$19", "$20", "$21");
}
+static inline unsigned long
+qemu_get_vmtime(void)
+{
+ register unsigned long v0 __asm__("$0");
+ register unsigned long a0 __asm__("$16") = 7;
+
+ asm("call_pal %2 # cserve get_time"
+ : "=r"(v0), "+r"(a0)
+ : "i"(PAL_cserve)
+ : "$17", "$18", "$19", "$20", "$21");
+
+ return v0;
+}
+
#endif /* !__ASSEMBLY__ */
#endif /* __ALPHA_PAL_H */
diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c
index 49d50e2..00add72 100644
--- a/arch/alpha/kernel/irq_alpha.c
+++ b/arch/alpha/kernel/irq_alpha.c
@@ -214,7 +214,7 @@ process_mcheck_info(unsigned long vector, unsigned long la_ptr,
*/
struct irqaction timer_irqaction = {
- .handler = timer_interrupt,
+ .handler = rtc_timer_interrupt,
.name = "timer",
};
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
index 175f7a4..db31ffb 100644
--- a/arch/alpha/kernel/proto.h
+++ b/arch/alpha/kernel/proto.h
@@ -140,7 +140,7 @@ extern void handle_ipi(struct pt_regs *);
/* extern void reset_for_srm(void); */
/* time.c */
-extern irqreturn_t timer_interrupt(int irq, void *dev);
+extern irqreturn_t rtc_timer_interrupt(int irq, void *dev);
extern void init_clockevent(void);
extern void common_init_rtc(void);
extern unsigned long est_cycle_freq;
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index ec45001..3b7601e 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -89,7 +89,7 @@ static inline __u32 rpcc(void)
static DEFINE_PER_CPU(struct clock_event_device, cpu_ce);
irqreturn_t
-timer_interrupt(int irq, void *dev)
+rtc_timer_interrupt(int irq, void *dev)
{
int cpu = smp_processor_id();
struct clock_event_device *ce = &per_cpu(cpu_ce, cpu);
@@ -119,8 +119,8 @@ rtc_ce_set_next_event(unsigned long evt, struct clock_event_device *ce)
return -EINVAL;
}
-void __init
-init_clockevent(void)
+static void __init
+init_rtc_clockevent(void)
{
int cpu = smp_processor_id();
struct clock_event_device *ce = &per_cpu(cpu_ce, cpu);
@@ -137,6 +137,83 @@ init_clockevent(void)
clockevents_config_and_register(ce, CONFIG_HZ, 0, 0);
}
+\f
+/*
+ * The QEMU clock as a clocksource primitive.
+ */
+
+static cycle_t
+qemu_cs_read(struct clocksource *cs)
+{
+ return qemu_get_vmtime();
+}
+
+static struct clocksource qemu_cs = {
+ .name = "qemu",
+ .rating = 400,
+ .read = qemu_cs_read,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .mult = 1,
+ .shift = 0,
+ .max_idle_ns = LONG_MAX
+};
+
+/*
+ * The QEMU clock and alarm as a clock_event_device primitive.
+ */
+
+
+static void
+qemu_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce)
+{
+ /* The mode member of CE is updated for us in generic code.
+ Just make sure that the event is disabled. */
+ qemu_set_alarm_abs(0);
+}
+
+static int
+qemu_ce_set_next_event(unsigned long evt, struct clock_event_device *ce)
+{
+ qemu_set_alarm_rel(evt);
+ return 0;
+}
+
+static irqreturn_t
+qemu_timer_interrupt(int irq, void *dev)
+{
+ int cpu = smp_processor_id();
+ struct clock_event_device *ce = &per_cpu(cpu_ce, cpu);
+
+ ce->event_handler(ce);
+ return IRQ_HANDLED;
+}
+
+static void __init
+init_qemu_clockevent(void)
+{
+ int cpu = smp_processor_id();
+ struct clock_event_device *ce = &per_cpu(cpu_ce, cpu);
+
+ *ce = (struct clock_event_device){
+ .name = "qemu",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .min_delta_ns = 1000,
+ .min_delta_ticks = 1000,
+ .max_delta_ns = LONG_MAX,
+ .max_delta_ticks = LONG_MAX,
+ .mult = 1,
+ .shift = 0,
+ .rating = 400,
+ .cpumask = cpumask_of(cpu),
+ .set_mode = qemu_ce_set_mode,
+ .set_next_event = qemu_ce_set_next_event,
+ };
+
+ clockevents_register_device(ce);
+}
+
+\f
void __init
common_init_rtc(void)
{
@@ -324,6 +401,15 @@ time_init(void)
unsigned long cycle_freq, tolerance;
long diff;
+ if (alpha_using_qemu) {
+ clocksource_register(&qemu_cs);
+ init_qemu_clockevent();
+
+ timer_irqaction.handler = qemu_timer_interrupt;
+ init_rtc_irq();
+ return;
+ }
+
/* Calibrate CPU clock -- attempt #1. */
if (!est_cycle_freq)
est_cycle_freq = validate_cc_value(calibrate_cc_with_pit());
@@ -363,7 +449,17 @@ time_init(void)
/* Startup the timer source. */
alpha_mv.init_rtc();
+ init_rtc_clockevent();
+}
- /* Start up the clock event device. */
- init_clockevent();
+/* Initialize the clock_event_device for secondary cpus. */
+#ifdef CONFIG_SMP
+void __init
+init_clockevent(void)
+{
+ if (alpha_using_qemu)
+ init_qemu_clockevent();
+ else
+ init_rtc_clockevent();
}
+#endif
--
1.8.1.4
next prev parent reply other threads:[~2013-07-16 17:35 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-16 17:34 [RFC PATCH 00/10] Alpha support for QEMU Richard Henderson
2013-07-16 17:34 ` [RFC PATCH 01/10] alpha: Don't if-out dp264_device_interrupt Richard Henderson
2013-07-16 17:34 ` [RFC PATCH 02/10] alpha: Notice if we're being run under QEMU Richard Henderson
2013-07-16 17:34 ` [RFC PATCH 03/10] alpha: Force the user-visible HZ to a constant 1024 Richard Henderson
2013-07-16 17:34 ` [RFC PATCH 04/10] alpha: Allow HZ to be configured Richard Henderson
2013-07-16 17:34 ` [RFC PATCH 05/10] alpha: Primitive support for CPU power down Richard Henderson
2013-07-17 5:17 ` Matt Turner
2013-07-17 13:16 ` Richard Henderson
2013-07-16 17:34 ` [RFC PATCH 06/10] alpha: Reorganize rtc handling Richard Henderson
2013-07-16 17:34 ` [RFC PATCH 07/10] alpha: Add an rtc driver for the qemu wallclock PALcall Richard Henderson
2013-07-16 17:34 ` [RFC PATCH 08/10] alpha: Always enable the rpcc clocksource for single processor Richard Henderson
2013-07-16 17:34 ` [RFC PATCH 09/10] alpha: Switch to GENERIC_CLOCKEVENTS Richard Henderson
2013-07-16 17:34 ` Richard Henderson [this message]
2013-07-18 1:14 ` [RFC PATCH 00/10] Alpha support for QEMU Michael Cree
2013-07-18 13:38 ` Richard Henderson
2013-07-18 21:28 ` Michael Cree
2013-07-18 22:04 ` Richard Henderson
2013-07-19 10:03 ` Michael Cree
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=1373996058-13399-11-git-send-email-rth@twiddle.net \
--to=rth@twiddle.net \
--cc=ink@jurassic.park.msu.ru \
--cc=linux-alpha@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mattst88@gmail.com \
--cc=tglx@linutronix.de \
/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
all inboxes | Powered by JetHome®