Page MenuHomeFreeBSD

D44454.diff
No OneTemporary

D44454.diff

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

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)

Event Timeline