diff options
author | Garrett D'Amore <garrett@nexenta.com> | 2011-11-28 20:07:13 -0800 |
---|---|---|
committer | Garrett D'Amore <garrett@nexenta.com> | 2011-11-28 20:07:13 -0800 |
commit | 223b8c65a9498294013b99c37d5b9024433237ec (patch) | |
tree | 05545199c342e8de00b9c1fb2fd8f90a5b1ce714 /usr/src | |
parent | 91b2ce10c5268c01c3a1e8a62a4da08d7c5b17a2 (diff) | |
download | illumos-joyent-223b8c65a9498294013b99c37d5b9024433237ec.tar.gz |
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>
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/i86pc/io/pcplusmp/apic_timer.c | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/usr/src/uts/i86pc/io/pcplusmp/apic_timer.c b/usr/src/uts/i86pc/io/pcplusmp/apic_timer.c index ffc1e99f68..348f5034fc 100644 --- a/usr/src/uts/i86pc/io/pcplusmp/apic_timer.c +++ b/usr/src/uts/i86pc/io/pcplusmp/apic_timer.c @@ -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 @@ oneshot_timer_reprogram(hrtime_t time) 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 @@ deadline_timer_disable(void) 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); } |