Mercurial > illumos > illumos-gate
changeset 13533:6c1a51927cbd
1333 High kernel cpu usage & dtrace hang on idle system
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Aubrey Li <aubreylee@gmail.com>
Reviewed by: Albert Lee <trisk@nexenta.com>
Reviewed by: Dan McDonald <danmcd@nexenta.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Gordon Ross <gwr@nexenta.com>
author | Garrett D'Amore <garrett@nexenta.com> |
---|---|
date | Mon, 28 Nov 2011 20:07:13 -0800 |
parents | 365e6faae95f |
children | f1634d5c7d82 |
files | usr/src/uts/i86pc/io/pcplusmp/apic_timer.c |
diffstat | 1 files changed, 34 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/i86pc/io/pcplusmp/apic_timer.c Wed Jun 22 16:58:54 2011 -0700 +++ b/usr/src/uts/i86pc/io/pcplusmp/apic_timer.c Mon Nov 28 20:07:13 2011 -0800 @@ -25,6 +25,9 @@ * Copyright (c) 2010, Intel Corporation. * All rights reserved. */ +/* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + */ #include <sys/time.h> #include <sys/psm.h> @@ -286,8 +289,28 @@ static void deadline_timer_enable(void) { + uint64_t ticks; + apic_reg_ops->apic_write(APIC_LOCAL_TIMER, (apic_clkvect + APIC_BASE_VECT) | AV_DEADLINE); + /* + * Now we have to serialize this per the SDM. That is to + * say, the above enabling can race in the pipeline with + * changes to the MSR. We need to make sure the above + * operation is complete before we proceed to reprogram + * the deadline value in reprogram(). The algorithm + * recommended by the Intel SDM 3A in 10.5.1.4 is: + * + * a) write a big value to the deadline register + * b) read the register back + * c) if it reads zero, go back to a and try again + */ + + do { + /* write a really big value */ + wrmsr(IA32_DEADLINE_TSC_MSR, 1ULL << 63); + ticks = rdmsr(IA32_DEADLINE_TSC_MSR); + } while (ticks == 0); } /* deadline timer disable */ @@ -302,17 +325,20 @@ static void deadline_timer_reprogram(hrtime_t time) { + int64_t delta; uint64_t ticks; - if (time <= 0) { - /* - * generate an immediate interrupt - */ - ticks = (uint64_t)tsc_read(); - } else { - ticks = unscalehrtime(time); - } + /* + * Note that this entire routine is called with + * CBE_HIGH_PIL, so we needn't worry about preemption. + */ + delta = time - gethrtime(); + /* The unscalehrtime wants unsigned values. */ + delta = max(delta, 0); + + /* Now we shouldn't be interrupted, we can set the deadline */ + ticks = (uint64_t)tsc_read() + unscalehrtime(delta); wrmsr(IA32_DEADLINE_TSC_MSR, ticks); }