Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F161392550
D44454.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D44454.diff
View Options
diff --git a/sys/amd64/amd64/apic_vector.S b/sys/amd64/amd64/apic_vector.S
--- a/sys/amd64/amd64/apic_vector.S
+++ b/sys/amd64/amd64/apic_vector.S
@@ -144,6 +144,15 @@
KMSAN_LEAVE
jmp doreti
+/*
+ * Local APIC thermal interrupt handler.
+ */
+ INTR_HANDLER thermalint
+ KMSAN_ENTER
+ call lapic_handle_thermal
+ KMSAN_LEAVE
+ jmp doreti
+
#ifdef XENHVM
/*
* Xen event channel upcall interrupt handler.
diff --git a/sys/x86/include/apicvar.h b/sys/x86/include/apicvar.h
--- a/sys/x86/include/apicvar.h
+++ b/sys/x86/include/apicvar.h
@@ -185,12 +185,12 @@
inthand_t
IDTVEC(apic_isr1), IDTVEC(apic_isr2), IDTVEC(apic_isr3),
IDTVEC(apic_isr4), IDTVEC(apic_isr5), IDTVEC(apic_isr6),
- IDTVEC(apic_isr7), IDTVEC(cmcint), IDTVEC(errorint),
- IDTVEC(spuriousint), IDTVEC(timerint),
+ IDTVEC(apic_isr7), IDTVEC(cmcint), IDTVEC(thermalint),
+ IDTVEC(errorint), IDTVEC(spuriousint), IDTVEC(timerint),
IDTVEC(apic_isr1_pti), IDTVEC(apic_isr2_pti), IDTVEC(apic_isr3_pti),
IDTVEC(apic_isr4_pti), IDTVEC(apic_isr5_pti), IDTVEC(apic_isr6_pti),
- IDTVEC(apic_isr7_pti), IDTVEC(cmcint_pti), IDTVEC(errorint_pti),
- IDTVEC(spuriousint_pti), IDTVEC(timerint_pti);
+ IDTVEC(apic_isr7_pti), IDTVEC(cmcint_pti), IDTVEC(thermalint_pti),
+ IDTVEC(errorint_pti), IDTVEC(spuriousint_pti), IDTVEC(timerint_pti);
extern vm_paddr_t lapic_paddr;
extern int *apic_cpuids;
@@ -199,6 +199,7 @@
extern void (*ipi_vectored)(u_int, int);
typedef struct ioapic *ioapic_drv_t;
+typedef void (*lapic_thermal_handle_function)(int, void *);
void apic_register_enumerator(struct apic_enumerator *enumerator);
ioapic_drv_t ioapic_create(vm_paddr_t addr, int32_t apic_id, int intbase);
@@ -233,6 +234,8 @@
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_handle_function thermfunc, void *value);
+void lapic_disable_thermal(void);
int lapic_enable_pcint(void);
void lapic_disable_pcint(void);
void lapic_reenable_pcint(void);
@@ -257,6 +260,7 @@
int lapic_set_lvt_triggermode(u_int apic_id, u_int lvt,
enum intr_trigger trigger);
void lapic_handle_cmc(void);
+void lapic_handle_thermal(void);
void lapic_handle_error(void);
void lapic_handle_intr(int vector, struct trapframe *frame);
void lapic_handle_timer(struct trapframe *frame);
diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
@@ -60,6 +60,7 @@
#include <vm/pmap.h>
#include <x86/apicreg.h>
+#include <machine/atomic.h>
#include <machine/clock.h>
#include <machine/cpufunc.h>
#include <machine/cputypes.h>
@@ -313,6 +314,8 @@
static int __read_mostly lapic_ds_idle_timeout = 1000000;
#endif
unsigned int max_apic_id;
+static void *lapic_thermal_function_value;
+static lapic_thermal_handle_function lapic_thermal_function_ptr;
static int pcint_refcnt = 0;
SYSCTL_NODE(_hw, OID_AUTO, apic, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
@@ -596,7 +599,9 @@
setidt(APIC_ERROR_INT, pti ? IDTVEC(errorint_pti) : IDTVEC(errorint),
SDT_APIC, SEL_KPL, GSEL_APIC);
- /* XXX: Thermal interrupt */
+ /* Thermal interrupt */
+ setidt(APIC_THERMAL_INT, pti ? IDTVEC(thermalint_pti) : IDTVEC(thermalint),
+ SDT_APIC, SEL_KPL, GSEL_APIC);
/* Local APIC CMCI. */
setidt(APIC_CMC_INT, pti ? IDTVEC(cmcint_pti) : IDTVEC(cmcint),
@@ -923,7 +928,9 @@
lapic_read32(LAPIC_LVT_ERROR)));
lapic_write32(LAPIC_ESR, 0);
- /* XXX: Thermal LVT */
+ /* Thermal LVT */
+ 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) {
@@ -1632,6 +1639,69 @@
return (APIC_ELVT_MCA);
}
+void
+lapic_handle_thermal(void)
+{
+ lapic_thermal_handle_function func;
+
+ func = (lapic_thermal_handle_function)atomic_load_acq_ptr(
+ (void *)&lapic_thermal_function_ptr);
+
+ if (func != NULL)
+ func(PCPU_GET(cpuid), lapic_thermal_function_value);
+
+ lapic_eoi();
+}
+
+static void
+lapic_update_thermal(void *dummy __unused)
+{
+ struct lapic *la;
+
+ la = &lapics[lapic_id()];
+ lapic_write32(LAPIC_LVT_THERMAL, lvt_mode(la, APIC_LVT_THERMAL,
+ lapic_read32(LAPIC_LVT_THERMAL)));
+}
+
+void
+lapic_enable_thermal(lapic_thermal_handle_function thermfunc, void *value)
+{
+#ifdef DEV_ATPIC
+ /* Fail if the local APIC is not present. */
+ if (!x2apic_mode && lapic_map == NULL)
+ return;
+#endif
+
+ lapic_thermal_function_value = value;
+ atomic_store_rel_ptr((uintptr_t *)&lapic_thermal_function_ptr,
+ (uintptr_t)thermfunc);
+
+ lvts[APIC_LVT_THERMAL].lvt_masked = 0;
+
+ MPASS(mp_ncpus == 1 || smp_started);
+ smp_rendezvous(NULL, lapic_update_thermal, NULL, NULL);
+}
+
+void
+lapic_disable_thermal(void)
+{
+#ifdef DEV_ATPIC
+ /* Fail if the local APIC is not present. */
+ if (!x2apic_mode && lapic_map == NULL)
+ return;
+#endif
+
+ lvts[APIC_LVT_THERMAL].lvt_masked = 1;
+
+#ifdef SMP
+ KASSERT(mp_ncpus == 1 || smp_started, ("thermal driver unloaded too early"));
+#endif
+ smp_rendezvous(NULL, lapic_update_thermal, NULL, NULL);
+
+ atomic_store_rel_ptr((uintptr_t *)&lapic_thermal_function_ptr,
+ (uintptr_t)NULL);
+}
+
void
lapic_handle_error(void)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jul 4, 9:22 AM (6 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34662531
Default Alt Text
D44454.diff (5 KB)
Attached To
Mode
D44454: intelhfi - Intel TD/HFI driver - Part2: Enable thermal interrupt handler for Local APIC's.
Attached
Detach File
Event Timeline
Log In to Comment