summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@nexenta.com>2011-11-28 20:07:13 -0800
committerGarrett D'Amore <garrett@nexenta.com>2011-11-28 20:07:13 -0800
commit223b8c65a9498294013b99c37d5b9024433237ec (patch)
tree05545199c342e8de00b9c1fb2fd8f90a5b1ce714 /usr/src
parent91b2ce10c5268c01c3a1e8a62a4da08d7c5b17a2 (diff)
downloadillumos-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.c42
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);
}