Port-alpha archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Alpha timecounter
> Date: Thu, 2 Nov 2017 09:23:26 +0100
> From: Martin Husemann <martin%duskware.de@localhost>
>
> I tested it too. I get two "PCC: local cc desynchronized" messages
> at boot time and then everything seems to be working fine. Ran full
> atf tests and the hardwareclockbackward (for a few minutes only
> though, have it still running).
Oops. The `PCC: local cc desynchronized' message means it _didn't_
work, and the system probably switched you to using the clockinterrupt
timecounter. Check `sysctl kern.timecounter' to see.
Maybe, if it happened at boot time, the cross-CPU calibration simply
had not yet run. So try the attached patch instead?
Index: sys/kern/kern_cctr.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_cctr.c,v
retrieving revision 1.9
diff -p -u -r1.9 kern_cctr.c
--- sys/kern/kern_cctr.c 3 Jan 2009 03:31:23 -0000 1.9
+++ sys/kern/kern_cctr.c 2 Nov 2017 15:08:27 -0000
@@ -95,6 +95,12 @@ void cc_calibrate_cpu(struct cpu_info *)
static int64_t cc_cal_val; /* last calibrate time stamp */
+/*
+ * Highest cc witnessed globally. We assume the calibration happens
+ * once a second.
+ */
+static volatile u_int cc_global __cacheline_aligned;
+
static struct timecounter cc_timecounter = {
.tc_get_timecount = cc_get_timecount,
.tc_poll_pps = cc_calibrate,
@@ -124,6 +130,13 @@ cc_init(timecounter_get_t getcc, uint64_
cc_timecounter.tc_frequency = freq;
cc_timecounter.tc_name = name;
cc_timecounter.tc_quality = quality;
+
+ /* Calibrate the local CPU and prime it before we try to use it. */
+ kpreempt_disable();
+ cc_calibrate_cpu(&cc_timecounter);
+ cc_global = cc_get_timecount_local(&cc_timecounter);
+ kpreempt_enable();
+
tc_init(&cc_timecounter);
return &cc_timecounter;
@@ -132,8 +145,8 @@ cc_init(timecounter_get_t getcc, uint64_
/*
* pick up tick count scaled to reference tick count
*/
-u_int
-cc_get_timecount(struct timecounter *tc)
+static u_int
+cc_get_timecount_local(struct timecounter *tc)
{
struct cpu_info *ci;
int64_t rcc, cc, ncsw;
@@ -186,6 +199,37 @@ cc_get_timecount(struct timecounter *tc)
}
/*
+ * advance the global view of the clock by our tick count and return it
+ */
+u_int
+cc_get_timecount(struct timecounter *tc)
+{
+ u_int freq = tc->tc_frequency;
+ u_int local, global, result;
+
+ do {
+ local = cc_get_timecount_local(tc);
+ global = cc_global;
+ if ((local - global) < freq) {
+ /* We're ahead, so use our counter. */
+ result = local;
+ } else {
+ /* We're behind or desynced, so use the global. */
+ result = global + 1;
+ }
+ } while (atomic_cas_uint(&cc_global, global, result) != global);
+
+ if (__predict_false((local - global) > freq &&
+ (global - local) > freq)) {
+ /* More than 1sec away from global: bad. */
+ printf("%s: local cc desynchronized\n", tc->tc_name);
+ tc_gonebad(tc);
+ }
+
+ return result;
+}
+
+/*
* called once per clock tick via the pps callback
* for the calibration of the TSC counters.
* it is called only for the PRIMARY cpu. all
Home |
Main Index |
Thread Index |
Old Index