diff options
Diffstat (limited to 'share/security/patches/SA-05:09/htt410.patch')
-rw-r--r-- | share/security/patches/SA-05:09/htt410.patch | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/share/security/patches/SA-05:09/htt410.patch b/share/security/patches/SA-05:09/htt410.patch new file mode 100644 index 0000000000..e481de0d0c --- /dev/null +++ b/share/security/patches/SA-05:09/htt410.patch @@ -0,0 +1,184 @@ +Index: sys/i386/i386/mp_machdep.c +=================================================================== +RCS file: /home/ncvs/src/sys/i386/i386/mp_machdep.c,v +retrieving revision 1.115.2.20 +diff -u -p -r1.115.2.20 mp_machdep.c +--- sys/i386/i386/mp_machdep.c 16 Dec 2003 16:32:28 -0000 1.115.2.20 ++++ sys/i386/i386/mp_machdep.c 12 May 2005 19:02:40 -0000 +@@ -342,6 +342,9 @@ static int apic_int_is_bus_type(int intr + + static int hlt_cpus_mask; + static int hlt_logical_cpus = 1; ++static u_int hyperthreading_cpus; ++static u_int hyperthreading_cpus_mask; ++static int hyperthreading_allowed; + static struct sysctl_ctx_list logical_cpu_clist; + + /* +@@ -982,6 +985,9 @@ mptable_pass2(void) + proc.apic_id++; + (void)processor_entry(&proc, cpu); + logical_cpus_mask |= (1 << cpu); ++ if (hyperthreading_cpus > 1 && ++ proc.apic_id % hyperthreading_cpus != 0) ++ hyperthreading_cpus_mask |= (1 << cpu); + cpu++; + } + } +@@ -1033,6 +1039,7 @@ static void + mptable_hyperthread_fixup(u_int id_mask) + { + u_int i, id; ++ u_int threads_per_cache, p[4]; + + /* Nothing to do if there is no HTT support. */ + if ((cpu_feature & CPUID_HTT) == 0) +@@ -1042,6 +1049,48 @@ mptable_hyperthread_fixup(u_int id_mask) + return; + + /* ++ * Work out if hyperthreading is *really* enabled. This ++ * is made really ugly by the fact that processors lie: Dual ++ * core processors claim to be hyperthreaded even when they're ++ * not, presumably because they want to be treated the same ++ * way as HTT with respect to per-cpu software licensing. ++ * At the time of writing (May 12, 2005) the only hyperthreaded ++ * cpus are from Intel, and Intel's dual-core processors can be ++ * identified via the "deterministic cache parameters" cpuid ++ * calls. ++ */ ++ /* ++ * First determine if this is an Intel processor which claims ++ * to have hyperthreading support. ++ */ ++ if ((cpu_feature & CPUID_HTT) && ++ (strcmp(cpu_vendor, "GenuineIntel") == 0)) { ++ /* ++ * If the "deterministic cache parameters" cpuid calls ++ * are available, use them. ++ */ ++ if (cpu_high >= 4) { ++ /* Ask the processor about up to 32 caches. */ ++ for (i = 0; i < 32; i++) { ++ cpuid_count(4, i, p); ++ threads_per_cache = ((p[0] & 0x3ffc000) >> 14) + 1; ++ if (hyperthreading_cpus < threads_per_cache) ++ hyperthreading_cpus = threads_per_cache; ++ if ((p[0] & 0x1f) == 0) ++ break; ++ } ++ } ++ ++ /* ++ * If the deterministic cache parameters are not ++ * available, or if no caches were reported to exist, ++ * just accept what the HTT flag indicated. ++ */ ++ if (hyperthreading_cpus == 0) ++ hyperthreading_cpus = logical_cpus; ++ } ++ ++ /* + * For each APIC ID of a CPU that is set in the mask, + * scan the other candidate APIC ID's for this + * physical processor. If any of those ID's are +@@ -3035,6 +3084,9 @@ sysctl_htl_cpus(SYSCTL_HANDLER_ARGS) + else + hlt_logical_cpus = 0; + ++ if (! hyperthreading_allowed) ++ mask |= hyperthreading_cpus_mask; ++ + if ((mask & all_cpus) == all_cpus) + mask &= ~(1<<0); + hlt_cpus_mask = mask; +@@ -3058,6 +3110,9 @@ sysctl_hlt_logical_cpus(SYSCTL_HANDLER_A + else + hlt_cpus_mask &= ~logical_cpus_mask; + ++ if (! hyperthreading_allowed) ++ hlt_cpus_mask |= hyperthreading_cpus_mask; ++ + if ((hlt_cpus_mask & all_cpus) == all_cpus) + hlt_cpus_mask &= ~(1<<0); + +@@ -3065,6 +3120,34 @@ sysctl_hlt_logical_cpus(SYSCTL_HANDLER_A + return (error); + } + ++static int ++sysctl_hyperthreading_allowed(SYSCTL_HANDLER_ARGS) ++{ ++ int allowed, error; ++ ++ allowed = hyperthreading_allowed; ++ error = sysctl_handle_int(oidp, &allowed, 0, req); ++ if (error || !req->newptr) ++ return (error); ++ ++ if (allowed) ++ hlt_cpus_mask &= ~hyperthreading_cpus_mask; ++ else ++ hlt_cpus_mask |= hyperthreading_cpus_mask; ++ ++ if (logical_cpus_mask != 0 && ++ (hlt_cpus_mask & logical_cpus_mask) == logical_cpus_mask) ++ hlt_logical_cpus = 1; ++ else ++ hlt_logical_cpus = 0; ++ ++ if ((hlt_cpus_mask & all_cpus) == all_cpus) ++ hlt_cpus_mask &= ~(1<<0); ++ ++ hyperthreading_allowed = allowed; ++ return (error); ++} ++ + static void + cpu_hlt_setup(void *dummy __unused) + { +@@ -3084,6 +3167,22 @@ cpu_hlt_setup(void *dummy __unused) + + if (hlt_logical_cpus) + hlt_cpus_mask |= logical_cpus_mask; ++ ++ /* ++ * If necessary for security purposes, force ++ * hyperthreading off, regardless of the value ++ * of hlt_logical_cpus. ++ */ ++ if (hyperthreading_cpus_mask) { ++ TUNABLE_INT_FETCH("machdep.hyperthreading_allowed", ++ &hyperthreading_allowed); ++ SYSCTL_ADD_PROC(&logical_cpu_clist, ++ SYSCTL_STATIC_CHILDREN(_machdep), OID_AUTO, ++ "hyperthreading_allowed", CTLTYPE_INT|CTLFLAG_RW, ++ 0, 0, sysctl_hyperthreading_allowed, "IU", ""); ++ if (! hyperthreading_allowed) ++ hlt_cpus_mask |= hyperthreading_cpus_mask; ++ } + } + } + SYSINIT(cpu_hlt, SI_SUB_SMP, SI_ORDER_ANY, cpu_hlt_setup, NULL); +Index: sys/i386/include/cpufunc.h +=================================================================== +RCS file: /home/ncvs/src/sys/i386/include/cpufunc.h,v +retrieving revision 1.96.2.3 +diff -u -p -r1.96.2.3 cpufunc.h +--- sys/i386/include/cpufunc.h 28 Apr 2002 22:50:54 -0000 1.96.2.3 ++++ sys/i386/include/cpufunc.h 12 May 2005 19:02:40 -0000 +@@ -103,6 +103,14 @@ do_cpuid(u_int ax, u_int *p) + } + + static __inline void ++cpuid_count(u_int ax, u_int cx, u_int *p) ++{ ++ __asm __volatile("cpuid" ++ : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) ++ : "0" (ax), "c" (cx)); ++} ++ ++static __inline void + enable_intr(void) + { + #ifdef SMP |