Switch agtimer from physical timer to virtual timer.

This diff makes the arm generic timer for arm64 use the virtual
timer instead of the physical timer.

Linux uses the virtual timer in the kernel unless it is operating in
hypervisor mode.

The virtual timer is set up so that a hypervisor can run an operating system
under it. This allows the hypervisor adjust time, eg to make it look like
the time spent in a higher level exeption didn't occur.

Access to the physical timer can be disabled from higher exception level,
making it required that the operating system use the virtual timer.

The use of virtual timer vs physical timer came up in a discussion with
Patrick, I decided it was better to just switch the timer now. 

diff --git a/sys/arch/arm64/dev/agtimer.c b/sys/arch/arm64/dev/agtimer.c
index 278ad9a0e19..3c9abc6011a 100644
--- a/sys/arch/arm64/dev/agtimer.c
+++ b/sys/arch/arm64/dev/agtimer.c
@@ -33,9 +33,9 @@
 #include <dev/ofw/openfirm.h>
 
 /* registers */
-#define GTIMER_CNTP_CTL_ENABLE         (1 << 0)
-#define GTIMER_CNTP_CTL_IMASK          (1 << 1)
-#define GTIMER_CNTP_CTL_ISTATUS                (1 << 2)
+#define GTIMER_CNTV_CTL_ENABLE         (1 << 0)
+#define GTIMER_CNTV_CTL_IMASK          (1 << 1)
+#define GTIMER_CNTV_CTL_ISTATUS                (1 << 2)
 
 #define TIMER_FREQUENCY                24 * 1000 * 1000 /* ARM core clock */
 int32_t agtimer_frequency = TIMER_FREQUENCY;
@@ -96,7 +96,7 @@ agtimer_readcnt64(void)
        uint64_t val;
 
        __asm volatile("isb" : : : "memory");
-       __asm volatile("MRS %x0, CNTPCT_EL0" : "=r" (val));
+       __asm volatile("MRS %x0, CNTVCT_EL0" : "=r" (val));
 
        return (val);
 }
@@ -116,7 +116,7 @@ agtimer_get_ctrl(void)
 {
        uint32_t val;
 
-       __asm volatile("MRS %x0, CNTP_CTL_EL0" : "=r" (val));
+       __asm volatile("MRS %x0, CNTV_CTL_EL0" : "=r" (val));
 
        return (val);
 }
@@ -124,7 +124,7 @@ agtimer_get_ctrl(void)
 static inline int
 agtimer_set_ctrl(uint32_t val)
 {
-       __asm volatile("MSR CNTP_CTL_EL0, %x0" : : "r" (val));
+       __asm volatile("MSR CNTV_CTL_EL0, %x0" : : "r" (val));
        __asm volatile("isb" : : : "memory");
 
        return (0);
@@ -133,7 +133,7 @@ agtimer_set_ctrl(uint32_t val)
 static inline int
 agtimer_set_tval(uint32_t val)
 {
-       __asm volatile("MSR CNTP_TVAL_EL0, %x0" : : "r" (val));
+       __asm volatile("MSR CNTV_TVAL_EL0, %x0" : : "r" (val));
        __asm volatile("isb" : : : "memory");
 
        return (0);
@@ -296,18 +296,16 @@ agtimer_cpu_initclocks()
        sc->sc_ticks_err_cnt = sc->sc_ticks_per_second % hz;
        pc->pc_ticks_err_sum = 0;
 
-       /* Setup secure and non-secure timer IRQs. */
-       arm_intr_establish_fdt_idx(sc->sc_node, 0, IPL_CLOCK,
-           agtimer_intr, NULL, "tick");
-       arm_intr_establish_fdt_idx(sc->sc_node, 1, IPL_CLOCK,
+       /* configure virtual timer interupt */
+       arm_intr_establish_fdt_idx(sc->sc_node, 2, IPL_CLOCK,
            agtimer_intr, NULL, "tick");
 
        next = agtimer_readcnt64() + sc->sc_ticks_per_intr;
        pc->pc_nexttickevent = pc->pc_nextstatevent = next;
 
        reg = agtimer_get_ctrl();
-       reg &= ~GTIMER_CNTP_CTL_IMASK;
-       reg |= GTIMER_CNTP_CTL_ENABLE;
+       reg &= ~GTIMER_CNTV_CTL_IMASK;
+       reg |= GTIMER_CNTV_CTL_ENABLE;
        agtimer_set_tval(sc->sc_ticks_per_second);
        agtimer_set_ctrl(reg);
 }
@@ -381,8 +379,8 @@ agtimer_startclock(void)
        pc->pc_nexttickevent = pc->pc_nextstatevent = nextevent;
 
        reg = agtimer_get_ctrl();
-       reg &= ~GTIMER_CNTP_CTL_IMASK;
-       reg |= GTIMER_CNTP_CTL_ENABLE;
+       reg &= ~GTIMER_CNTV_CTL_IMASK;
+       reg |= GTIMER_CNTV_CTL_ENABLE;
        agtimer_set_tval(sc->sc_ticks_per_second);
        agtimer_set_ctrl(reg);
 }
Dale Rahn                               dr...@dalerahn.com

Reply via email to