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