PERFORCE change 92848 for review

John Baldwin jhb at FreeBSD.org
Mon Mar 6 06:25:06 PST 2006


http://perforce.freebsd.org/chv.cgi?CH=92848

Change 92848 by jhb at jhb_zion on 2006/03/06 14:24:04

	Attempt to fix the alpha cpu ticker.  The RPCC register is not
	exactly like the TSC on i386.  The upper 32-bits have a quirky
	meaning, so we basically have to treat it like a 32-bit counter
	and handle the roll-overs ourself.  I think this may end up not
	being any cheaper than just using the alpha timecounter, though
	perhaps it will be cheaper for SMP where we have to use the i8254
	right now for cpu_ticks.

Affected files ...

.. //depot/projects/smpng/sys/alpha/alpha/clock.c#23 edit
.. //depot/projects/smpng/sys/alpha/alpha/interrupt.c#38 edit
.. //depot/projects/smpng/sys/alpha/include/md_var.h#9 edit
.. //depot/projects/smpng/sys/alpha/include/pcpu.h#5 edit

Differences ...

==== //depot/projects/smpng/sys/alpha/alpha/clock.c#23 (text+ko) ====

@@ -152,7 +152,7 @@
 
 	calibrate_clocks(cycles_per_sec, &pcc, &freq);
 	cycles_per_sec = pcc;
-	set_cputicker(alpha_rpcc, cycles_per_sec, 0);
+	set_cputicker(read_cycle_count, cycles_per_sec, 0);
 
 	/*
 	 * XXX: TurboLaser doesn't have an i8254 counter.
@@ -556,6 +556,30 @@
 	return alpha_rpcc();
 }
 
+/*
+ * The RPCC register actually consists of two halves.  The lower half
+ * is a raw 32-bit counter that wraps.  The upper half is defined in
+ * the Digital UNIX PAL as being a raw per-process cycle count mod 2^32
+ * that is updated on each call to swpctx.  In order to produce a 64-bit
+ * counter, we just use the lower half and simulate the upper 32-bits.
+ * The architecture guarantees that there will always be at least one
+ * clock interrupt in between overlaps in the lower half, so as long as
+ * we call this function every clock interrupt we should not miss any
+ * overlaps.
+ */
+uint64_t
+read_cycle_count(void)
+{
+	unsigned pcc_cnt;
+
+	/* Assert a critical section? */
+	pcc_cnt = alpha_rpcc() & 0xffffffff;
+	if (pcc_cnt < PCPU_GET(last_pcc_cnt))
+		PCPU_SET(pcc_base, PCPU_GET(pcc_base) + 1);
+	PCPU_SET(last_pcc_cnt, pcc_cnt);
+	return (pcc_cnt | (PCPU_GET(pcc_base) << 32));
+}
+
 int
 acquire_timer2(int mode)
 {

==== //depot/projects/smpng/sys/alpha/alpha/interrupt.c#38 (text+ko) ====

@@ -483,6 +483,9 @@
 #endif
 	if (platform.clockintr) {
 		critical_enter();
+
+		/* Check for PCC roll-over. */
+		(void)read_cycle_count();
 #ifdef SMP
 		/*
 		 * Only one processor drives the actual timer.

==== //depot/projects/smpng/sys/alpha/include/md_var.h#9 (text+ko) ====

@@ -84,6 +84,7 @@
 int	is_physical_memory(vm_offset_t addr);
 void	machine_check(unsigned long, struct trapframe *, unsigned long,
 	    unsigned long);
+uint64_t read_cycle_count(void);
 void	regdump(struct trapframe *);
 void	regtoframe(struct reg *, struct trapframe *);
 void	set_iointr(void (*)(void *, unsigned long));

==== //depot/projects/smpng/sys/alpha/include/pcpu.h#5 (text+ko) ====

@@ -38,7 +38,9 @@
 	u_int64_t	pc_idlepcbphys;		/* pa of pc_idlepcb */	\
 	u_int64_t	pc_pending_ipis;	/* pending IPI's */	\
 	u_int32_t	pc_next_asn;		/* next ASN to alloc */	\
-	u_int32_t	pc_current_asngen	/* ASN rollover check */
+	u_int32_t	pc_current_asngen	/* ASN rollover check */ \
+	u_int32_t	pc_last_ppc_cnt;	/* Previous PCC_CNT value */ \
+	u_int32_t	pc_ppc_base;		/* Hi word of cycle count. */
 
 struct pcpu;
 


More information about the p4-projects mailing list