svn commit: r271189 - head/sys/arm/arm

Andrew Turner andrew at FreeBSD.org
Sat Sep 6 13:21:08 UTC 2014


Author: andrew
Date: Sat Sep  6 13:21:07 2014
New Revision: 271189
URL: http://svnweb.freebsd.org/changeset/base/271189

Log:
  Allow us to use the virtual timer. It is currently disabled, but should
  be usable as the default timer in place of the physical timer.
  
  We are guaranteed to have access to the virtual timer, but when running
  under a hypervisor may not have access to the physical.
  
  Differential Revision: https://reviews.freebsd.org/D588

Modified:
  head/sys/arm/arm/generic_timer.c

Modified: head/sys/arm/arm/generic_timer.c
==============================================================================
--- head/sys/arm/arm/generic_timer.c	Sat Sep  6 11:19:12 2014	(r271188)
+++ head/sys/arm/arm/generic_timer.c	Sat Sep  6 13:21:07 2014	(r271189)
@@ -67,7 +67,7 @@ __FBSDID("$FreeBSD$");
 
 #define	GT_CNTKCTL_PL0PTEN	(1 << 9) /* PL0 Physical timer reg access */
 #define	GT_CNTKCTL_PL0VTEN	(1 << 8) /* PL0 Virtual timer reg access */
-#define	GT_CNTKCTL_EVNTI	(1 << 4) /* Virtual counter event bits */
+#define	GT_CNTKCTL_EVNTI	(0xf << 4) /* Virtual counter event bits */
 #define	GT_CNTKCTL_EVNTDIR	(1 << 3) /* Virtual counter event transition */
 #define	GT_CNTKCTL_EVNTEN	(1 << 2) /* Enables virtual counter events */
 #define	GT_CNTKCTL_PL0VCTEN	(1 << 1) /* PL0 CNTVCT and CNTFRQ access */
@@ -78,6 +78,7 @@ struct arm_tmr_softc {
 	void			*ihl[4];
 	uint32_t		clkfreq;
 	struct eventtimer	et;
+	bool			physical;
 };
 
 static struct arm_tmr_softc *arm_tmr_sc = NULL;
@@ -101,81 +102,83 @@ static struct timecounter arm_tmr_timeco
 	.tc_quality        = 1000,
 };
 
-static inline int
+static int
 get_freq(void)
 {
 	uint32_t val;
 
+	/* cntfrq */
 	__asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
 
 	return (val);
 }
 
-static inline int
-set_freq(uint32_t val)
-{
-
-	__asm volatile("mcr p15, 0, %[val], c14, c0, 0" : :
-	    [val] "r" (val));
-	isb();
-
-	return (val);
-}
-
-
-static inline long
-get_cntpct(void)
+static long
+get_cntxct(bool physical)
 {
 	uint64_t val;
 
-	__asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (val));
+	isb();
+	if (physical)
+		/* cntpct */
+		__asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (val));
+	else
+		/* cntvct */
+		__asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (val));
 
 	return (val);
 }
 
-static inline int
-set_ctrl(uint32_t val)
+static int
+set_ctrl(uint32_t val, bool physical)
 {
 
-	__asm volatile("mcr p15, 0, %[val], c14, c2, 1" : :
-	    [val] "r" (val));
+	if (physical)
+		/* cntp_ctl */
+		__asm volatile("mcr p15, 0, %[val], c14, c2, 1" : :
+		    [val] "r" (val));
+	else
+		/* cntv_ctl */
+		__asm volatile("mcr p15, 0, %[val], c14, c3, 1" : :
+		    [val] "r" (val));
 	isb();
 
 	return (0);
 }
 
-static inline int
-set_tval(uint32_t val)
+static int
+set_tval(uint32_t val, bool physical)
 {
 
-	__asm volatile("mcr p15, 0, %[val], c14, c2, 0" : :
-	    [val] "r" (val));
+	if (physical)
+		/* cntp_tval */
+		__asm volatile("mcr p15, 0, %[val], c14, c2, 0" : :
+		    [val] "r" (val));
+	else
+		/* cntv_tval */
+		__asm volatile("mcr p15, 0, %[val], c14, c3, 0" : :
+		    [val] "r" (val));
 	isb();
 
 	return (0);
 }
 
-static inline int
-get_ctrl(void)
-{
-	uint32_t val;
-
-	__asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
-
-	return (val);
-}
-
-static inline int
-get_tval(void)
+static int
+get_ctrl(bool physical)
 {
 	uint32_t val;
 
-	__asm volatile("mrc p15, 0, %0, c14, c2, 0" : "=r" (val));
+	if (physical)
+		/* cntp_ctl */
+		__asm volatile("mrc p15, 0, %0, c14, c2, 1" : "=r" (val));
+	else
+		/* cntv_ctl */
+		__asm volatile("mrc p15, 0, %0, c14, c3, 1" : "=r" (val));
 
 	return (val);
 }
 
-static inline void
+static void
 disable_user_access(void)
 {
 	uint32_t cntkctl;
@@ -191,7 +194,7 @@ static unsigned
 arm_tmr_get_timecount(struct timecounter *tc)
 {
 
-	return (get_cntpct());
+	return (get_cntxct(arm_tmr_sc->physical));
 }
 
 static int
@@ -204,11 +207,11 @@ arm_tmr_start(struct eventtimer *et, sbi
 
 	if (first != 0) {
 		counts = ((uint32_t)et->et_frequency * first) >> 32;
-		ctrl = get_ctrl();
+		ctrl = get_ctrl(sc->physical);
 		ctrl &= ~GT_CTRL_INT_MASK;
 		ctrl |= GT_CTRL_ENABLE;
-		set_tval(counts);
-		set_ctrl(ctrl);
+		set_tval(counts, sc->physical);
+		set_ctrl(ctrl, sc->physical);
 		return (0);
 	}
 
@@ -219,11 +222,14 @@ arm_tmr_start(struct eventtimer *et, sbi
 static int
 arm_tmr_stop(struct eventtimer *et)
 {
+	struct arm_tmr_softc *sc;
 	int ctrl;
 
-	ctrl = get_ctrl();
+	sc = (struct arm_tmr_softc *)et->et_priv;
+
+	ctrl = get_ctrl(sc->physical);
 	ctrl &= GT_CTRL_ENABLE;
-	set_ctrl(ctrl);
+	set_ctrl(ctrl, sc->physical);
 
 	return (0);
 }
@@ -235,10 +241,10 @@ arm_tmr_intr(void *arg)
 	int ctrl;
 
 	sc = (struct arm_tmr_softc *)arg;
-	ctrl = get_ctrl();
+	ctrl = get_ctrl(sc->physical);
 	if (ctrl & GT_CTRL_INT_STAT) {
 		ctrl |= GT_CTRL_INT_MASK;
-		set_ctrl(ctrl);
+		set_ctrl(ctrl, sc->physical);
 	}
 
 	if (sc->et.et_active)
@@ -295,12 +301,14 @@ arm_tmr_attach(device_t dev)
 	if (bus_alloc_resources(dev, timer_spec, sc->res)) {
 		device_printf(dev, "could not allocate resources\n");
 		return (ENXIO);
-	};
+	}
+
+	sc->physical = true;
 
 	arm_tmr_sc = sc;
 
-	/* Setup secure and non-secure IRQs handler */
-	for (i = 0; i < 2; i++) {
+	/* Setup secure, non-secure and virtual IRQs handler */
+	for (i = 0; i < 3; i++) {
 		error = bus_setup_intr(dev, sc->res[i], INTR_TYPE_CLK,
 		    arm_tmr_intr, NULL, sc, &sc->ihl[i]);
 		if (error) {
@@ -381,10 +389,10 @@ DELAY(int usec)
 	else
 		counts = usec * counts_per_usec;
 
-	first = get_cntpct();
+	first = get_cntxct(arm_tmr_sc->physical);
 
 	while (counts > 0) {
-		last = get_cntpct();
+		last = get_cntxct(arm_tmr_sc->physical);
 		counts -= (int32_t)(last - first);
 		first = last;
 	}


More information about the svn-src-all mailing list