Factor out some logic from the gic-demo that reads and programs the
generic virtual timer, including read-out of the timer frequency from
CNTFRQ.
hypervisor/arch/arm/include/asm/sysregs.h | 2 ++
inmates/lib/arm/Makefile | 2 +-
inmates/lib/arm/include/inmates/inmate.h | 16 +++++++++
inmates/lib/arm/timer.c | 55 +++++++++++++++++++++++++++++++
4 files changed, 74 insertions(+), 1 deletion(-)
create mode 100644 inmates/lib/arm/timer.c
diff --git a/hypervisor/arch/arm/include/asm/sysregs.h b/hypervisor/arch/arm/include/asm/sysregs.h
index d1f63b3..3011364 100644
--- a/hypervisor/arch/arm/include/asm/sysregs.h
+++ b/hypervisor/arch/arm/include/asm/sysregs.h
@@ -97,6 +97,8 @@
#define TPIDRURO SYSREG_32(0, c13, c0, 3)
#define TPIDRPRW SYSREG_32(0, c13, c0, 4)
+#define CNTFRQ SYSREG_32(0, c14, c0, 0)
+
#define ATS1HR SYSREG_32(4, c7, c8, 0)
#define ICIALLUIS SYSREG_32(0, c7, c1, 0)
diff --git a/inmates/lib/arm/Makefile b/inmates/lib/arm/Makefile
index 8478a49..c116181 100644
--- a/inmates/lib/arm/Makefile
+++ b/inmates/lib/arm/Makefile
@@ -14,7 +14,7 @@ include $(INMATES_LIB)/Makefile.lib
always := lib.a
-lib-y := header.o gic.o printk.o
+lib-y := header.o gic.o printk.o timer.o
lib-$(CONFIG_ARM_GIC) += gic-v2.o
lib-$(CONFIG_ARM_GIC_V3) += gic-v3.o
lib-$(CONFIG_SERIAL_AMBA_PL011) += uart-pl011.o
diff --git a/inmates/lib/arm/include/inmates/inmate.h b/inmates/lib/arm/include/inmates/inmate.h
index 062ada3..63a3e35 100644
--- a/inmates/lib/arm/include/inmates/inmate.h
+++ b/inmates/lib/arm/include/inmates/inmate.h
@@ -13,6 +13,17 @@
#define _JAILHOUSE_INMATES_INMATE_H
#ifndef __ASSEMBLY__
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
static inline void *memset(void *addr, int val, unsigned int size)
{
@@ -34,5 +45,10 @@ typedef void (*irq_handler_t)(unsigned int);
void gic_setup(irq_handler_t handler);
void gic_enable_irq(unsigned int irq);
+unsigned long timer_get_frequency(void);
+u64 timer_get_ticks(void);
+u64 timer_ticks_to_ns(u64 ticks);
+void timer_start(u64 timeout);
+
#endif /* !__ASSEMBLY__ */
#endif
diff --git a/inmates/lib/arm/timer.c b/inmates/lib/arm/timer.c
new file mode 100644
index 0000000..5f5e865
--- /dev/null
+++ b/inmates/lib/arm/timer.c
@@ -0,0 +1,55 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) ARM Limited, 2014
+ * Copyright (c) Siemens AG, 2015
+ *
+ * Authors:
+ * Jean-Philippe Brucker <
jean-phili...@arm.com>
+ * Jan Kiszka <
jan.k...@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <asm/sysregs.h>
+#include <inmates/inmate.h>
+
+unsigned long timer_get_frequency(void)
+{
+ u32 freq;
+
+ arm_read_sysreg(CNTFRQ, freq);
+ return freq;
+}
+
+u64 timer_get_ticks(void)
+{
+ u64 pct64;
+
+ arm_read_sysreg(CNTPCT, pct64);
+ return pct64;
+}
+
+static unsigned long emul_division(u64 val, u64 div)
+{
+ unsigned long cnt = 0;
+
+ while (val > div) {
+ val -= div;
+ cnt++;
+ }
+ return cnt;
+}
+
+u64 timer_ticks_to_ns(u64 ticks)
+{
+ return emul_division(ticks * 1000,
+ timer_get_frequency() / 1000 / 1000);
+}
+
+void timer_start(u64 timeout)
+{
+ arm_write_sysreg(CNTV_TVAL_EL0, timeout);
+ arm_write_sysreg(CNTV_CTL_EL0, 1);
+}
--
2.1.4