aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Certner <olce@FreeBSD.org>2026-07-02 14:26:21 +0000
committerOlivier Certner <olce@FreeBSD.org>2026-07-24 04:33:39 +0000
commit45254c2df093617dfd22336d177b4aece317699c (patch)
tree9c466f9f4bc2ca85b93ad0c9a7bec678876a7444
parent93dbde1542606eda4eb601caf715241869f47966 (diff)
x86/local_apic.c: Fiddle with thermal LVT slot only if supported
The thermal LVT slot does not necessarily exist. According to Intel's Software Developers Manual, for Intel processors supporting 64-bit operation (amd64), probably even the earliest ones should have a local APIC with such a slot (the slot was introduced with Pentium 4 and Xeon processors according to the manual, and the 64-bit implementation in some later versions of them). AMD's Architecture Programmer's Manual also seems to imply that all AMD processors supporting amd64 should have the slot too. So this change may not be needed when i386's code is dropped, but it does not hurt to have it, and it might ease possible MFCs. Change the signature of lapic_enable_thermal() so that it can report failure (if there is no local APIC or if there is no thermal LVT slot). Reviewed by: bnovkov, kib MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D58086 (cherry picked from commit c18ec05395b36bdd12b0129533a553f27eb9b067)
-rw-r--r--sys/x86/include/apicvar.h2
-rw-r--r--sys/x86/x86/local_apic.c22
2 files changed, 17 insertions, 7 deletions
diff --git a/sys/x86/include/apicvar.h b/sys/x86/include/apicvar.h
index e0625a38d198..9eb874881641 100644
--- a/sys/x86/include/apicvar.h
+++ b/sys/x86/include/apicvar.h
@@ -235,7 +235,7 @@ void apic_enable_vector(u_int apic_id, u_int vector);
void apic_disable_vector(u_int apic_id, u_int vector);
void apic_free_vector(u_int apic_id, u_int vector, u_int irq);
void lapic_calibrate_timer(void);
-void lapic_enable_thermal(lapic_thermal_handler_t *func, void *func_arg);
+bool lapic_enable_thermal(lapic_thermal_handler_t *func, void *func_arg);
void lapic_disable_thermal(void);
int lapic_enable_pcint(void);
void lapic_disable_pcint(void);
diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
index 821b17358448..c5cb0867906a 100644
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
@@ -804,9 +804,10 @@ lapic_dump(const char* str)
printf("\n lint0: 0x%08x lint1: 0x%08x TPR: 0x%08x SVR: 0x%08x\n",
lapic_read32(LAPIC_LVT_LINT0), lapic_read32(LAPIC_LVT_LINT1),
lapic_read32(LAPIC_TPR), lapic_read32(LAPIC_SVR));
- printf(" timer: 0x%08x therm: 0x%08x err: 0x%08x",
- lapic_read32(LAPIC_LVT_TIMER), lapic_read32(LAPIC_LVT_THERMAL),
+ printf(" timer: 0x%08x err: 0x%08x", lapic_read32(LAPIC_LVT_TIMER),
lapic_read32(LAPIC_LVT_ERROR));
+ if (maxlvt >= APIC_LVT_THERMAL)
+ printf(" therm: 0x%08x", lapic_read32(LAPIC_LVT_THERMAL));
if (maxlvt >= APIC_LVT_PMC)
printf(" pmc: 0x%08x", lapic_read32(LAPIC_LVT_PCINT));
printf("\n");
@@ -932,8 +933,9 @@ lapic_setup(int boot)
lapic_write32(LAPIC_ESR, 0);
/* Thermal LVT */
- lapic_write32(LAPIC_LVT_THERMAL, lvt_mode(la, APIC_LVT_THERMAL,
- lapic_read32(LAPIC_LVT_THERMAL)));
+ if (maxlvt >= APIC_LVT_THERMAL)
+ lapic_write32(LAPIC_LVT_THERMAL, lvt_mode(la, APIC_LVT_THERMAL,
+ lapic_read32(LAPIC_LVT_THERMAL)));
/* Program the CMCI LVT entry if present. */
if (maxlvt >= APIC_LVT_CMCI) {
@@ -1644,15 +1646,18 @@ lapic_update_thermal(void *dummy __unused)
lapic_read32(LAPIC_LVT_THERMAL)));
}
-void
+bool
lapic_enable_thermal(lapic_thermal_handler_t *func, void *func_arg)
{
#ifdef DEV_ATPIC
/* Fail if the local APIC is not present. */
if (!x2apic_mode && lapic_map == NULL)
- return;
+ return (false);
#endif
+ if (lapic_maxlvt() < APIC_LVT_THERMAL)
+ return (false);
+
lapic_thermal_function_arg = func_arg;
atomic_store_rel_ptr((uintptr_t *)&lapic_thermal_function,
(uintptr_t)func);
@@ -1661,6 +1666,8 @@ lapic_enable_thermal(lapic_thermal_handler_t *func, void *func_arg)
MPASS(mp_ncpus == 1 || smp_started);
smp_rendezvous(NULL, lapic_update_thermal, NULL, NULL);
+
+ return (true);
}
void
@@ -1672,6 +1679,9 @@ lapic_disable_thermal(void)
return;
#endif
+ if (lapic_maxlvt() < APIC_LVT_THERMAL)
+ return;
+
lvts[APIC_LVT_THERMAL].lvt_masked = 1;
#ifdef SMP