Date: Mon, 6 Mar 2006 14:25:04 GMT From: John Baldwin <jhb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 92848 for review Message-ID: <200603061425.k26EP4HE066899@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=92848 Change 92848 by jhb@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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200603061425.k26EP4HE066899>