aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2003-10-22 20:15:10 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2003-10-22 20:15:10 +0000
commit3a0f48841fc28cb432571d6446d8552f5147c91f (patch)
treebc82b84ae7b3ce76f80587708decbd408d31069e
parent455b1d51aa0c69e6b56089b9bbddbf44d43f8048 (diff)
downloadsrc-3a0f48841fc28cb432571d6446d8552f5147c91f.tar.gz
src-3a0f48841fc28cb432571d6446d8552f5147c91f.zip
MFC: Always enable hyperthreading to avoid lockups due to APIC interrupt
routing problems. - Enable cpu_idle_hlt for the SMP case by default since that significantly helps HTT performance. - Provide a facility for disabling individual CPUs by refusing to schedule processes on them. - Use the above to provide a sysctl for disabling or enabling all logical CPUs. The default is to disable all logical CPUs. - Remove the 'HTT' kernel option now that it is obsolete. Submitted by: ps Approved by: re (murray)
Notes
Notes: svn path=/stable/4/; revision=121365
-rw-r--r--sys/i386/i386/machdep.c10
-rw-r--r--sys/i386/i386/mp_machdep.c120
2 files changed, 102 insertions, 28 deletions
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index f83d5476af24..8c6a59466639 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -979,17 +979,19 @@ cpu_halt(void)
* On -stable, cpu_idle() is called with interrupts disabled and must
* return with them enabled.
*/
-#ifdef SMP
-static int cpu_idle_hlt = 0;
-#else
static int cpu_idle_hlt = 1;
-#endif
SYSCTL_INT(_machdep, OID_AUTO, cpu_idle_hlt, CTLFLAG_RW,
&cpu_idle_hlt, 0, "Idle loop HLT enable");
void
cpu_idle(void)
{
+
+#ifdef SMP
+ if (mp_grab_cpu_hlt())
+ return;
+#endif
+
if (cpu_idle_hlt) {
/*
* We must guarentee that hlt is exactly the instruction
diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c
index 3daaa86ff197..adfbe8bcd564 100644
--- a/sys/i386/i386/mp_machdep.c
+++ b/sys/i386/i386/mp_machdep.c
@@ -26,7 +26,6 @@
*/
#include "opt_cpu.h"
-#include "opt_htt.h"
#include "opt_user_ldt.h"
#ifdef SMP
@@ -236,10 +235,9 @@ typedef struct BASETABLE_ENTRY {
#define MP_ANNOUNCE_POST 0x19
-#ifdef HTT
static int need_hyperthreading_fixup;
static u_int logical_cpus;
-#endif
+u_int logical_cpus_mask; /* bit mask of logical cpu's */
/** XXX FIXME: where does this really belong, isa.h/isa.c perhaps? */
int current_postcode;
@@ -330,9 +328,7 @@ static mpfps_t mpfps;
static int search_for_sig(u_int32_t target, int count);
static void mp_enable(u_int boot_addr);
-#ifdef HTT
static void mptable_hyperthread_fixup(u_int id_mask);
-#endif
static void mptable_pass1(void);
static int mptable_pass2(void);
static void default_mp_table(int type);
@@ -344,6 +340,10 @@ static void install_ap_tramp(u_int boot_addr);
static int start_ap(int logicalCpu, u_int boot_addr);
static int apic_int_is_bus_type(int intr, int bus_type);
+static int hlt_cpus_mask;
+static int hlt_logical_cpus = 1;
+static struct sysctl_ctx_list logical_cpu_clist;
+
/*
* Calculate usable address in base memory for AP trampoline code.
*/
@@ -765,9 +765,7 @@ mptable_pass1(void)
void* position;
int count;
int type;
-#ifdef HTT
u_int id_mask;
-#endif
POSTCODE(MPTABLE_PASS1_POST);
@@ -781,9 +779,7 @@ mptable_pass1(void)
mp_nbusses = 0;
mp_napics = 0;
nintrs = 0;
-#ifdef HTT
id_mask = 0;
-#endif
/* check for use of 'default' configuration */
if (MPFPS_MPFB1 != 0) {
@@ -816,10 +812,8 @@ mptable_pass1(void)
if (((proc_entry_ptr)position)->cpu_flags
& PROCENTRY_FLAG_EN) {
++mp_naps;
-#ifdef HTT
id_mask |= 1 <<
((proc_entry_ptr)position)->apic_id;
-#endif
}
break;
case 1: /* bus_entry */
@@ -854,10 +848,8 @@ mptable_pass1(void)
mp_naps = MAXCPU;
}
-#ifdef HTT
/* See if we need to fixup HT logical CPUs. */
mptable_hyperthread_fixup(id_mask);
-#endif
/*
* Count the BSP.
@@ -883,9 +875,7 @@ mptable_pass1(void)
static int
mptable_pass2(void)
{
-#ifdef HTT
struct PROCENTRY proc;
-#endif
int x;
mpcth_t cth;
int totalSize;
@@ -898,12 +888,10 @@ mptable_pass2(void)
POSTCODE(MPTABLE_PASS2_POST);
-#ifdef HTT
/* Initialize fake proc entry for use with HT fixup. */
bzero(&proc, sizeof(proc));
proc.type = 0;
proc.cpu_flags = PROCENTRY_FLAG_EN;
-#endif
pgeflag = 0; /* XXX - Not used under SMP yet. */
@@ -983,7 +971,6 @@ mptable_pass2(void)
if (processor_entry(position, cpu))
++cpu;
-#ifdef HTT
if (need_hyperthreading_fixup) {
/*
* Create fake mptable processor entries
@@ -994,10 +981,10 @@ mptable_pass2(void)
for (i = 1; i < logical_cpus; i++) {
proc.apic_id++;
(void)processor_entry(&proc, cpu);
+ logical_cpus_mask |= (1 << cpu);
cpu++;
}
}
-#endif
break;
case 1:
if (bus_entry(position, bus))
@@ -1030,7 +1017,6 @@ mptable_pass2(void)
return 0;
}
-#ifdef HTT
/*
* Check if we should perform a hyperthreading "fix-up" to
* enumerate any logical CPU's that aren't already listed
@@ -1079,7 +1065,6 @@ mptable_hyperthread_fixup(u_int id_mask)
need_hyperthreading_fixup = 1;
mp_naps *= logical_cpus;
}
-#endif
void
assign_apic_irq(int apic, int intpin, int irq)
@@ -2710,7 +2695,7 @@ forward_statclock(int pscnt)
/* Step 1: Probe state (user, cpu, interrupt, spinlock, idle ) */
- map = other_cpus & ~stopped_cpus ;
+ map = other_cpus & ~(stopped_cpus|hlt_cpus_mask);
checkstate_probed_cpus = 0;
if (map != 0)
selected_apic_ipi(map,
@@ -2785,7 +2770,7 @@ forward_hardclock(int pscnt)
/* Step 1: Probe state (user, cpu, interrupt, spinlock, idle) */
- map = other_cpus & ~stopped_cpus ;
+ map = other_cpus & ~(stopped_cpus|hlt_cpus_mask);
checkstate_probed_cpus = 0;
if (map != 0)
selected_apic_ipi(map,
@@ -2914,7 +2899,7 @@ forward_roundrobin(void)
if (!forward_roundrobin_enabled)
return;
resched_cpus |= other_cpus;
- map = other_cpus & ~stopped_cpus ;
+ map = other_cpus & ~(stopped_cpus|hlt_cpus_mask);
#if 1
selected_apic_ipi(map, XCPUAST_OFFSET, APIC_DELMODE_FIXED);
#else
@@ -3023,3 +3008,90 @@ smp_rendezvous(void (* setup_func)(void *),
/* release lock */
s_unlock(&smp_rv_lock);
}
+
+static int
+sysctl_htl_cpus(SYSCTL_HANDLER_ARGS)
+{
+ u_int mask;
+ int error;
+
+ mask = hlt_cpus_mask;
+ error = sysctl_handle_int(oidp, &mask, 0, req);
+ if (error || !req->newptr)
+ return (error);
+
+ if (logical_cpus_mask != 0 &&
+ (mask & logical_cpus_mask) == logical_cpus_mask)
+ hlt_logical_cpus = 1;
+ else
+ hlt_logical_cpus = 0;
+
+ if ((mask & all_cpus) == all_cpus)
+ mask &= ~(1<<0);
+ hlt_cpus_mask = mask;
+ return (error);
+}
+SYSCTL_PROC(_machdep, OID_AUTO, hlt_cpus, CTLTYPE_INT|CTLFLAG_RW,
+ 0, 0, sysctl_htl_cpus, "IU", "");
+
+static int
+sysctl_hlt_logical_cpus(SYSCTL_HANDLER_ARGS)
+{
+ int disable, error;
+
+ disable = hlt_logical_cpus;
+ error = sysctl_handle_int(oidp, &disable, 0, req);
+ if (error || !req->newptr)
+ return (error);
+
+ if (disable)
+ hlt_cpus_mask |= logical_cpus_mask;
+ else
+ hlt_cpus_mask &= ~logical_cpus_mask;
+
+ if ((hlt_cpus_mask & all_cpus) == all_cpus)
+ hlt_cpus_mask &= ~(1<<0);
+
+ hlt_logical_cpus = disable;
+ return (error);
+}
+
+static void
+cpu_hlt_setup(void *dummy __unused)
+{
+
+ if (logical_cpus_mask != 0) {
+ TUNABLE_INT_FETCH("machdep.hlt_logical_cpus",
+ &hlt_logical_cpus);
+ sysctl_ctx_init(&logical_cpu_clist);
+ SYSCTL_ADD_PROC(&logical_cpu_clist,
+ SYSCTL_STATIC_CHILDREN(_machdep), OID_AUTO,
+ "hlt_logical_cpus", CTLTYPE_INT|CTLFLAG_RW, 0, 0,
+ sysctl_hlt_logical_cpus, "IU", "");
+ SYSCTL_ADD_UINT(&logical_cpu_clist,
+ SYSCTL_STATIC_CHILDREN(_machdep), OID_AUTO,
+ "logical_cpus_mask", CTLTYPE_INT|CTLFLAG_RD,
+ &logical_cpus_mask, 0, "");
+
+ if (hlt_logical_cpus)
+ hlt_cpus_mask |= logical_cpus_mask;
+ }
+}
+SYSINIT(cpu_hlt, SI_SUB_SMP, SI_ORDER_ANY, cpu_hlt_setup, NULL);
+
+int
+mp_grab_cpu_hlt(void)
+{
+ u_int mask = 1 << cpuid;
+ u_int temp;
+ int retval;
+
+ retval = mask & hlt_cpus_mask;
+ while (mask & hlt_cpus_mask) {
+ temp = lapic.tpr;
+ lapic.tpr = LOPRIO_LEVEL;
+ __asm __volatile("sti; hlt" : : : "memory");
+ lapic.tpr = temp;
+ }
+ return (retval);
+}