Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F173913444
D44456.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D44456.diff
View Options
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -220,6 +220,7 @@
clean "ice_ddp.fw"
dev/intel/hfsts.c optional hfsts pci
dev/intel/hfsts_isa.c optional hfsts isa pci
+dev/intelhfi/intelhfi.c optional intelhfi
dev/ioat/ioat.c optional ioat pci
dev/ioat/ioat_test.c optional ioat pci
dev/ixl/if_ixl.c optional ixl pci \
diff --git a/sys/conf/options.amd64 b/sys/conf/options.amd64
--- a/sys/conf/options.amd64
+++ b/sys/conf/options.amd64
@@ -40,6 +40,9 @@
# iWARP client interface support in ixl
IXL_IW opt_ixl.h
+# Intel(R) Hardware Feedback Interface driver
+DEV_INTELHFI opt_intelhfi.h
+
# -------------------------------
# EOF
# -------------------------------
diff --git a/sys/dev/intelhfi/intelhfi.c b/sys/dev/intelhfi/intelhfi.c
new file mode 100644
--- /dev/null
+++ b/sys/dev/intelhfi/intelhfi.c
@@ -0,0 +1,754 @@
+/*
+ * Copyright (c) 2024-2026 Koine Yuusuke
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <sys/cdefs.h>
+#include "opt_global.h"
+#include "opt_intelhfi.h"
+
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/lock.h>
+#include <sys/proc.h>
+#include <sys/smp.h>
+#include <sys/sysctl.h>
+#include <sys/sbuf.h>
+
+#ifdef HMP
+#include <sys/hmp.h>
+#endif
+
+#include <machine/specialreg.h>
+#include <machine/cputypes.h>
+#include <machine/md_var.h>
+#include <machine/bus.h>
+
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+
+#include <x86/intr_machdep.h>
+#include <x86/apicvar.h>
+
+#define INTELHFI_NAME "intelhfi"
+
+#ifdef HMP
+#define INTELHFI_HMP_PRIORITY 40
+#endif
+
+/* Check kernel build option with SMP */
+#ifndef SMP
+#error "intelhfi requires the SMP option in the kernel configuraton."
+#endif
+
+#define ROUNDUP8(n) (((n)+7)&(~7))
+
+#define CPUID_LEAF6_ECX_CLASSES(c) ((uint8_t)((((uint64_t)(c)&CPUID_PERF_TD_CLASSES)>>8)&0x0f))
+#define CPUID_LEAF6_EDX_TBLPAGES(c) (((c)&CPUID_TD_TBLPAGES)>>8)
+
+/* Hardware feedback table - global header flag */
+#define INTELHFI_GH_FLAG_REPORT (1 << 0)
+#define INTELHFI_GH_FLAG_FORCEIDLE (1 << 1)
+
+/*
+ * Structure defines
+ */
+struct intelhfi_instance {
+ uint8_t status;
+
+ struct {
+ uint32_t hfi :1;
+ uint32_t thdirector :1;
+ uint32_t pmaped :1;
+ uint32_t reserved :30;
+ } flags;
+
+ uint32_t hdrsize;
+ uint32_t entrysize;
+ uint32_t allocsize;
+ uint32_t tblsize;
+
+ uint8_t capabilities;
+ uint8_t classes;
+
+ union {
+ void *ptr;
+ uint64_t *timestamp;
+ } hwtable;
+
+ union {
+ void *ptr;
+ uint64_t *timestamp;
+ } cache;
+
+ struct mtx intr_lock;
+
+ uint32_t entries;
+ uint32_t *coremap;
+
+ struct {
+ struct sysctl_ctx_list ctx;
+ struct sysctl_oid *oid;
+ } sysctl;
+};
+
+#define INTELHFI_STATUS_LOADED (1 << 0) /* status bit0: intelhfi loaded */
+#define INTELHFI_STATUS_USEHMP (1 << 1) /* status bit1: HMP use flag */
+
+static struct intelhfi_instance ihfi_inst;
+
+/*
+ * Prototype defines
+ */
+static void intelhfi_get_hwtable(struct intelhfi_instance *inst);
+static void intelhfi_interrupt(int cpu, void *value);
+static void intelhfi_read_hfiindex(void *arg);
+static int intelhfi_create_coremap(void);
+static int intelhfi_device_check(void);
+static int intelhfi_device_init(void);
+static int intelhfi_device_remove(void);
+static int intelhfi_modevent(module_t mod, int type, void *data);
+static int intelhfi_sysctl_printtable(SYSCTL_HANDLER_ARGS);
+static int intelhfi_sysctl_dumptable(SYSCTL_HANDLER_ARGS);
+static int intelhfi_register_sysctl(void);
+static void intelhfi_remove_sysctl(void);
+
+#if !defined(HMP) && defined(DEV_INTELHFI)
+static void intelhfi_sysinit(void *arg __unused);
+#endif /* INTELHFI */
+
+#ifdef HMP
+static void intelhfi_hmp_score_set(struct intelhfi_instance *inst);
+static int intelhfi_hmp_score_provider_probe(void);
+static int intelhfi_hmp_score_provider_init(void);
+#endif /* HMP */
+
+#ifdef HMP
+DPCPU_DECLARE(struct hmp_pcpu, hmp_pcpu);
+#endif /* HMP */
+
+static MALLOC_DEFINE(M_INTELHFI, INTELHFI_NAME, "Buffers for intelhfi driver");
+
+/*
+ * HMP score setter
+ * (Available only if HMP options are define in kernel configuration.)
+ */
+#ifdef HMP
+static void
+intelhfi_hmp_score_set(struct intelhfi_instance *inst)
+{
+ uint8_t *capflags, *entry;
+ uint32_t *map;
+ uint32_t cores, cid;
+ struct hmp_pcpu *hp;
+
+ /* Check change flag in Global header */
+ capflags = (uint8_t *)(inst->cache.ptr) + sizeof(uint64_t);
+ if (!(*(capflags+0) & INTELHFI_GH_FLAG_REPORT)
+ && !(*(capflags+1) & INTELHFI_GH_FLAG_REPORT))
+ return;
+
+ entry = (uint8_t *)(inst->cache.ptr) + inst->hdrsize;
+
+ KASSERT(inst->coremap != NULL, ("Not exist CPU core mapping."));
+
+ map = inst->coremap;
+ for (int grp=0; grp<inst->entries; grp++, entry+=inst->entrysize) {
+ cores = *map++;
+
+ for (uint32_t i=0; i<cores; i++) {
+ cid = *map++;
+
+ hp = DPCPU_ID_PTR(cid, hmp_pcpu);
+ KASSERT(hp != NULL, ("DPCPU area is NULL."));
+
+ if (*(capflags+0) & INTELHFI_GH_FLAG_REPORT)
+ hmp_set_score(hp, HMP_SCORE_PERF, (((hmp_score_t)(*(entry+0)))<<2));
+
+ if (*(capflags+1) & INTELHFI_GH_FLAG_REPORT)
+ hmp_set_score(hp, HMP_SCORE_EFF, (((hmp_score_t)(*(entry+1)))<<2));
+ }
+ }
+}
+#endif /* HMP */
+
+/*
+ * LVT thermal interrupts handler
+ */
+static void
+intelhfi_get_hwtable(struct intelhfi_instance *inst)
+{
+ uint64_t msr_status;
+
+ KASSERT(inst != NULL, ("%s: instance ptr. is NULL.", __func__));
+
+ if (! mtx_trylock_spin(&inst->intr_lock))
+ return;
+
+ /* Check HFI/ITD update status */
+ msr_status = rdmsr(MSR_IA32_PKG_THERM_STATUS);
+ if (msr_status & IA32_PKG_THERM_STATUS_HFI_UPDATED) {
+
+ /* Check HFI/ITD update's timestamp and Copy HFI/ITD HW table to local cache */
+ if (*(inst->cache.timestamp) != *(inst->hwtable.timestamp))
+ memcpy(inst->cache.ptr, inst->hwtable.ptr, inst->tblsize);
+
+#ifdef HMP
+ if (inst->status & INTELHFI_STATUS_USEHMP)
+ intelhfi_hmp_score_set(inst);
+#endif /* HMP */
+
+ /* Clear HFI/ITD update's flag on MSR */
+ msr_status &= ~IA32_PKG_THERM_STATUS_HFI_UPDATED;
+ wrmsr(MSR_IA32_PKG_THERM_STATUS, msr_status);
+ }
+
+ mtx_unlock_spin(&inst->intr_lock);
+}
+
+static void
+intelhfi_interrupt(int cpu, void *value)
+{
+ intelhfi_get_hwtable((struct intelhfi_instance *)value);
+}
+
+/*
+ * intelhfi driver probe & initialization
+ */
+static int
+intelhfi_device_check(void)
+{
+ u_int regs[4];
+
+ /* Check Intel CPU */
+ if (cpu_high < 6 || cpu_vendor_id != CPU_VENDOR_INTEL)
+ return (-1);
+
+ /* Get CPUID Leaf 6 */
+ do_cpuid(0x06, regs);
+
+ /* Check Intel Hardware Feedback & Thread Director feature */
+ if( !(regs[0] & CPUTPM1_HW_FEEDBACK) && !(regs[0] & CPUTPM1_THREAD_DIRECTOR))
+ return (-2);
+
+ /* Check performance reporting features */
+ if (!(regs[3] & CPUID_HF_PERFORMANCE))
+ return (-3);
+
+ /* Check efficiency reporting features */
+ if (!(regs[3] & CPUID_HF_EFFICIENCY))
+ return (-4);
+
+ return (0);
+}
+
+static void
+intelhfi_read_hfiindex(void *arg)
+{
+ uint32_t *grpid;
+ u_int regs[4];
+
+ /* Get CPUID Leaf 6 on the each core */
+ do_cpuid(0x06, regs);
+
+ grpid = (uint32_t *)arg + PCPU_GET(cpuid);
+ *grpid = (uint32_t)((regs[3] & 0xffff0000) >> 16);
+}
+
+static int
+intelhfi_create_coremap(void)
+{
+ int ret = 0;
+ uint32_t *grpid, *map, *index, *core;
+ uint32_t entries = 0;
+
+ /* Alloc temporary memory for HFI table indices for each CPU core */
+ grpid = malloc((sizeof(uint32_t) * mp_ncpus), M_INTELHFI, M_NOWAIT | M_ZERO);
+ if (grpid == NULL) {
+ return (-1);
+ }
+
+ /* Read the HFI table index for each CPU core */
+ smp_rendezvous(NULL, intelhfi_read_hfiindex, NULL, grpid);
+
+ /* Obtain HFI table entries */
+ for (int c=0; c<mp_ncpus; c++) {
+ if (entries < *(grpid+c))
+ entries = *(grpid+c);
+ }
+ ihfi_inst.entries = ++entries;
+
+ /*
+ * Create a map between CPU core IDs and HFI table entries.
+ *
+ * The mapping between CPU core IDs and HFI table entries follows the structure below,
+ * ordered by HFI table entry ID:
+ * <Number of CPU cores belonging to HFI table entry #0>
+ * <1st core ID> <2nd core ID> ... <Last core ID>
+ * <Number of CPU cores belonging to HFI table entry #1>
+ * <1st core ID> <2nd core ID> ... <Last core ID>
+ * ...
+ * <Number of CPU cores belonging to the last HFI table entry>
+ * <1st core ID> <2nd core ID> ... <Last core ID>
+ *
+ * Both the number of CPU cores belonging to an HFI table entry and the CPU core IDs
+ * are of type uint32_t and are stored as an array of uint32_t.
+ */
+ map = malloc((sizeof(uint32_t) * (mp_ncpus+entries)), M_INTELHFI, M_NOWAIT | M_ZERO);
+ if (map == NULL) {
+ ret = -2;
+ goto coremap_err1;
+ }
+
+ /* Create a map from the acquired HFI table index information for each CPU core. */
+ core = map;
+ for (uint32_t i=0; i<entries; i++) {
+ index = core++;
+ for (uint32_t c=0; c<(uint32_t)mp_ncpus; c++) {
+ if (i == *(grpid+c)) {
+ *core++ = c;
+ (*index)++;
+ }
+ }
+ }
+ ihfi_inst.coremap = map;
+
+coremap_err1:
+ free(grpid, M_INTELHFI);
+
+ return (ret);
+}
+
+static int
+intelhfi_device_init(void)
+{
+ int ret = 0;
+ u_int regs[4];
+ uint64_t msrval;
+ uint8_t capabilities;
+ uint8_t classes;
+ void *mapptr;
+
+ /* Check intelhfi loaded */
+ if (ihfi_inst.status & INTELHFI_STATUS_LOADED)
+ return ((ihfi_inst.status & INTELHFI_STATUS_USEHMP) ? 0 : 1);
+
+ /* Check exist Intel HFI/TD */
+ if (intelhfi_device_check())
+ return (2);
+
+ /* Get CPUID Leaf 6 */
+ do_cpuid(0x06, regs);
+
+ /* Check & Get ITD capabilites (CP) */
+ capabilities = 2;
+ if (regs[0] & CPUTPM1_THREAD_DIRECTOR) {
+ capabilities = __builtin_popcount(regs[3] & CPUID_TD_CAPABLITIES);
+
+ if (capabilities != 2) {
+ printf("intelhfi: Not support other than 2 capablities. - disable HFI/ITD.\n");
+ return (3);
+ }
+ }
+
+ /* Check & Get ITD classes (CL) */
+ classes = 1;
+ if (regs[0] & CPUTPM1_THREAD_DIRECTOR) {
+ classes = CPUID_LEAF6_ECX_CLASSES(regs[2]);
+
+ if (classes != 4) {
+ printf("intelhfi: Not support other than 4 classes. - fallback to HFI.\n");
+ classes = 1;
+ }
+ }
+
+ /* Set Intel Hardware Feedback & Thread Director feature flags */
+ if (regs[0] & CPUTPM1_THREAD_DIRECTOR)
+ ihfi_inst.flags.thdirector = 1;
+ if (regs[0] & CPUTPM1_HW_FEEDBACK)
+ ihfi_inst.flags.hfi = 1;
+
+ /* Set Intel Hardware Feedback & Thread Director settings */
+ ihfi_inst.capabilities = capabilities;
+ ihfi_inst.classes = classes;
+
+ /* Create HFI table entry - Core ID map */
+ if (intelhfi_create_coremap()) {
+ printf("intelhfi: Fail to create Core group map due to insufficient memory."
+ " - disable HFI/ITD.\n");
+ return (4);
+ }
+
+ /* Calc. Header & Entry size */
+ ihfi_inst.hdrsize = ROUNDUP8((capabilities * classes)+8);
+ ihfi_inst.entrysize = ROUNDUP8(capabilities * classes);
+ ihfi_inst.tblsize = ROUNDUP8(ihfi_inst.hdrsize + (ihfi_inst.entrysize * ihfi_inst.entries));
+
+ /* Alloc Cache page */
+ ihfi_inst.allocsize = (CPUID_LEAF6_EDX_TBLPAGES(regs[3]) + 1) * PAGE_SIZE;
+ ihfi_inst.cache.ptr = malloc(ihfi_inst.allocsize, M_INTELHFI, M_NOWAIT | M_ZERO);
+ if (ihfi_inst.cache.ptr == NULL) {
+ printf("intelhfi: Not enough memory for local table cache. - disable HFI/ITD.\n");
+ ret = (5);
+ goto scrinit_err1;
+ }
+
+ /* Init. spin-lock structure */
+ mtx_init(&ihfi_inst.intr_lock, "intelhfi Interrupt lock", NULL, MTX_SPIN);
+
+ /* Enable Intel ThreadDirector features for each Core */
+ x86_msr_op(MSR_IA32_HW_FEEDBACK_THREAD_CONFIG, MSR_OP_RENDEZVOUS_ALL | MSR_OP_READ,
+ 0, &msrval);
+ x86_msr_op(MSR_IA32_HW_FEEDBACK_THREAD_CONFIG, MSR_OP_RENDEZVOUS_ALL | MSR_OP_WRITE,
+ msrval | 1ULL, NULL);
+
+ /* Set Hardware feedback interface table */
+ msrval = rdmsr(MSR_IA32_HW_FEEDBACK_PTR);
+ if (msrval == 0) {
+ /* Alloc HFI page */
+ ihfi_inst.hwtable.ptr = kmem_alloc_contig(ihfi_inst.allocsize, M_NOWAIT | M_ZERO, 0,
+ BUS_SPACE_MAXADDR, PAGE_SIZE, 0, VM_MEMATTR_DEFAULT );
+ if (ihfi_inst.hwtable.ptr == NULL) {
+ printf("intelhfi: Not enough memory for Hardware table. - disable HFI/ITD.\n");
+ ret = (6);
+ goto scrinit_err2;
+ }
+
+ ihfi_inst.flags.pmaped = 0;
+
+ /* Set HFI memory page to MSR_IA32_HW_FEEDBACK_PTR MSR */
+ msrval = (uint64_t)vtophys(ihfi_inst.hwtable.ptr) | IA32_HW_FEEDBACK_PTR_ENABLE;
+ wrmsr(MSR_IA32_HW_FEEDBACK_PTR, msrval);
+ } else {
+ /* Mapping hardware feedback table physical page to kernel memory. */
+ mapptr = pmap_mapdev((msrval & ~IA32_HW_FEEDBACK_PTR_ENABLE), ihfi_inst.allocsize);
+ if (NULL == mapptr) {
+ printf("intelhfi: Not enough memory for Hardware mapping table. - disable HFI/ITD.\n");
+ ret = (7);
+ goto scrinit_err2;
+ }
+
+ ihfi_inst.flags.pmaped = 1;
+ ihfi_inst.hwtable.ptr = mapptr;
+ }
+
+ /* Regist sysctl interfaces */
+ if (intelhfi_register_sysctl()) {
+ ret = (8);
+ goto scrinit_err3;
+ }
+
+ /* Enable HFI & Thread Director to MSR_IA32_HW_FEEDBACK_CONFIG MSR */
+ msrval = rdmsr(MSR_IA32_HW_FEEDBACK_CONFIG);
+ if (ihfi_inst.flags.hfi)
+ msrval |= IA32_HW_FEEDBACK_CONFIG_EN_HFI;
+ if (ihfi_inst.flags.thdirector)
+ msrval |= IA32_HW_FEEDBACK_CONFIG_EN_THDIR;
+ wrmsr(MSR_IA32_HW_FEEDBACK_CONFIG, msrval);
+
+ /* Init. copy Hardware feedback table to cache table when reload this module. */
+ if (ihfi_inst.flags.pmaped)
+ memcpy(ihfi_inst.cache.ptr, ihfi_inst.hwtable.ptr, ihfi_inst.allocsize);
+
+ /* Enable Local APIC thermal interrupt handle */
+ lapic_enable_thermal(intelhfi_interrupt, (void *)&ihfi_inst);
+
+ /* Set intelhfi loaded flag */
+ ihfi_inst.status |= INTELHFI_STATUS_LOADED;
+
+#ifdef HMP
+ /* Set intelhfi use HMP flag */
+ ihfi_inst.status |= INTELHFI_STATUS_USEHMP;
+#endif /* HMP */
+
+ printf("intelhfi: Intel(R) Hardware-Feedback Interface\n");
+
+ /* Enable HFI/ITD interrupt */
+ msrval = rdmsr(MSR_IA32_PKG_THERM_INTERRUPT) | IA32_PKG_THERM_INTERRUPT_HFI_ENABLE;
+ wrmsr(MSR_IA32_PKG_THERM_INTERRUPT, msrval);
+
+ return (0);
+
+scrinit_err3:
+ /* Unmap Hardware feedback table physical page area */
+ if (ihfi_inst.flags.pmaped) {
+ pmap_unmapdev(ihfi_inst.hwtable.ptr, ihfi_inst.allocsize);
+ ihfi_inst.hwtable.ptr = NULL;
+ }
+
+scrinit_err2:
+ /* Destroy spin-lock structure */
+ mtx_destroy(&ihfi_inst.intr_lock);
+
+scrinit_err1:
+ /* Free cache area */
+ if (ihfi_inst.cache.ptr != NULL) {
+ free(ihfi_inst.cache.ptr, M_INTELHFI);
+ ihfi_inst.cache.ptr = NULL;
+ }
+
+ return (ret);
+}
+
+/*
+ * intelhfi driver initialization via SYSINIT
+ * (Available only if HMP option is NOT defined and
+ * "device intelhfi" is defined in kernel configuration.)
+ */
+#if !defined(HMP) && defined(DEV_INTELHFI)
+static void
+intelhfi_sysinit(void *arg __unused)
+{
+ intelhfi_device_init();
+}
+SYSINIT(intelhfi, SI_SUB_SMP + 2, SI_ORDER_ANY, intelhfi_sysinit, NULL);
+#endif /* !HMP & INTELHFI */
+
+/*
+ * HMP socre provider
+ * (Available only if HMP options are define in kernel configuration.)
+ */
+#ifdef HMP
+static int
+intelhfi_hmp_score_provider_probe(void)
+{
+ return intelhfi_device_check();
+}
+
+static int
+intelhfi_hmp_score_provider_init(void)
+{
+ return intelhfi_device_init();
+}
+
+static struct hmp_score_provider intelhfi_hmp_score_provider = {
+ .name = INTELHFI_NAME,
+ .priority = INTELHFI_HMP_PRIORITY,
+ .probe = intelhfi_hmp_score_provider_probe,
+ .init = intelhfi_hmp_score_provider_init,
+};
+HMP_SCORE_PROVIDER_DECLARE(intelhfi, intelhfi_hmp_score_provider);
+#endif /* HMP */
+
+/*
+ * Module Interfaces
+ */
+static int
+intelhfi_device_remove(void)
+{
+ uint64_t msr_intr;
+
+ /* Check intelhfi NOT loaded */
+ if (!(ihfi_inst.status & INTELHFI_STATUS_LOADED))
+ return (1);
+
+ /* Remove sysctl interface */
+ intelhfi_remove_sysctl();
+
+ /* Disable HFI/ITD interrupt */
+ msr_intr = rdmsr(MSR_IA32_PKG_THERM_INTERRUPT);
+ msr_intr &= ~IA32_PKG_THERM_INTERRUPT_HFI_ENABLE;
+ wrmsr(MSR_IA32_PKG_THERM_INTERRUPT, msr_intr);
+
+ /* Disable Local APIC thermal interrupt handle */
+ /* TODO:
+ * Currently, Local APIC thermal interrupt handler is only used
+ * by this driver, so Local APIC thermal interrupt is disabled, but
+ * if other drivers are used in the future, instead of disabling Local
+ * APIC thermal interrupt itself, it will be necessary to disable the
+ * interrupt handler of this driver. Must make sure to unregister.
+ */
+ lapic_disable_thermal();
+
+ /* Unmap Hardware feedback table physical page area */
+ if (ihfi_inst.flags.pmaped) {
+ pmap_unmapdev(ihfi_inst.hwtable.ptr, ihfi_inst.allocsize);
+ ihfi_inst.hwtable.ptr = NULL;
+ }
+
+ /*
+ * The physical address set for MSR_IA32_HW_FEEDBACK_PTR MSR and the enable
+ * flag set for MSR_IA32_HW_FEEDBACK_CONFIG MSR should also be disabled,
+ * but the current CPU implementation is that the physical address once
+ * set for MSR_IA32_HW_FEEDBACK_PTR MSR remains inside the CPU even after
+ * being disabled.
+ * For this reason, We have not intentionally disabled them at this time.
+ */
+
+ /* Destroy spin-lock structure */
+ mtx_destroy(&ihfi_inst.intr_lock);
+
+ /* Free cache area */
+ if (ihfi_inst.cache.ptr != NULL) {
+ free(ihfi_inst.cache.ptr, M_INTELHFI);
+ ihfi_inst.cache.ptr = NULL;
+ }
+
+ /* Free HFI table entry - Core ID map */
+ if (ihfi_inst.coremap != NULL) {
+ free(ihfi_inst.coremap, M_INTELHFI);
+ ihfi_inst.coremap = NULL;
+ }
+
+ /* Clear intelhfi loaded flag */
+ ihfi_inst.status &= ~INTELHFI_STATUS_LOADED;
+
+ return (0);
+}
+
+static int
+intelhfi_modevent(module_t mod, int type, void *data)
+{
+ switch (type) {
+ case MOD_LOAD:
+#ifdef DEV_INTELHFI
+ /*
+ * If intelhfi is defined in the kernel configuration and initialized
+ * via HMP or SYSINIT at boot time, it is intentionally returned as 0
+ * to prevent subsequent dynamic loading by the user.
+ */
+ return (0);
+#else
+ return intelhfi_device_init();
+#endif /* DEV_INTELHFI */
+
+ case MOD_UNLOAD:
+#ifdef HMP
+ /* If used from HMP, dynamic unloading must be disabled. */
+ if (ihfi_inst.status & INTELHFI_STATUS_USEHMP)
+ return (EBUSY);
+#endif /* HMP */
+ return intelhfi_device_remove();
+
+ default:
+ return (EOPNOTSUPP);
+ }
+}
+
+static moduledata_t intelhfi_mod = {
+ INTELHFI_NAME, /* module name */
+ intelhfi_modevent, /* event handler */
+ NULL
+};
+DECLARE_MODULE(intelhfi, intelhfi_mod, SI_SUB_SMP + 2, SI_ORDER_ANY);
+
+/*
+ * Sysctls
+ */
+static int
+intelhfi_sysctl_printtable(SYSCTL_HANDLER_ARGS)
+{
+ int err;
+ struct sbuf *buf;
+ uint8_t *entry;
+ uint32_t cores;
+ uint32_t *map;
+
+ buf = sbuf_new_for_sysctl(NULL, NULL, 512, req);
+ if (buf == NULL)
+ return (ENOMEM);
+
+ sbuf_printf(buf, "\nintelhfi: [HFI/ITD table] TimeStamp=%lx\n", *(ihfi_inst.cache.timestamp));
+
+ sbuf_cat(buf, " ");
+ for(int cl=0; cl<ihfi_inst.classes; cl++)
+ sbuf_printf(buf, " Class %d ", cl);
+
+ sbuf_cat(buf, "\n---------");
+ for(int cl=0; cl<ihfi_inst.classes; cl++)
+ sbuf_cat(buf, " Perf: Eff");
+
+ KASSERT(ihfi_inst.entries > 0, ("Number of the HFI table entries is 0."));
+ KASSERT(ihfi_inst.coremap != NULL, ("Not exist CPU core mapping."));
+
+ map = ihfi_inst.coremap;
+ for (uint32_t grp=0; grp<ihfi_inst.entries; grp++) {
+ entry = (uint8_t *)ihfi_inst.cache.ptr + ihfi_inst.hdrsize + (grp * ihfi_inst.entrysize);
+ cores = *map++;
+
+ sbuf_printf(buf, "\n Grp %2d:", grp);
+
+ for (int cl=0; cl<ihfi_inst.classes; cl++, entry+=2)
+ sbuf_printf(buf, " %3d : %3d", *(entry+0), *(entry+1));
+
+ sbuf_printf(buf, " (Core");
+ for (uint32_t n=0; n<cores; n++)
+ sbuf_printf(buf, " #%d", *map++);
+
+ sbuf_printf(buf, ")");
+ }
+
+ err = sbuf_finish(buf);
+
+ sbuf_delete(buf);
+
+ return (err);
+}
+
+static int
+intelhfi_sysctl_dumptable(SYSCTL_HANDLER_ARGS)
+{
+ struct sbuf *buf;
+ uint8_t *p;
+ int err;
+
+ buf = sbuf_new_for_sysctl(NULL, NULL, 512, req);
+ if (buf == NULL)
+ return (ENOMEM);
+
+ sbuf_printf(buf, "\nintelhfi: [Dump HFI/ITD table] TimeStamp=%lx\n",
+ *(ihfi_inst.hwtable.timestamp));
+ sbuf_printf(buf, " Capacity=%u, Class=%u\n",
+ ihfi_inst.capabilities, ihfi_inst.classes);
+
+ sbuf_printf(buf, "\n Table Dump -- Size:%u\n ", ihfi_inst.tblsize);
+ p = (uint8_t *)ihfi_inst.hwtable.ptr;
+ for(uint32_t cur=1; cur<=ihfi_inst.tblsize; cur++, p++) {
+ sbuf_printf(buf, "0x%02x,", *p);
+ if ((cur%16)==0)
+ sbuf_printf(buf, "\n ");
+ }
+
+ err = sbuf_finish(buf);
+
+ sbuf_delete(buf);
+
+ return (err);
+}
+
+static int
+intelhfi_register_sysctl(void)
+{
+ sysctl_ctx_init(&(ihfi_inst.sysctl.ctx));
+
+ ihfi_inst.sysctl.oid = SYSCTL_ADD_NODE( &(ihfi_inst.sysctl.ctx),
+ SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, INTELHFI_NAME,
+ CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
+ "Intel(R) Hardware-Feedback Interface state");
+
+ if (ihfi_inst.sysctl.oid == NULL)
+ return (-1);
+
+ SYSCTL_ADD_PROC( &(ihfi_inst.sysctl.ctx), SYSCTL_CHILDREN(ihfi_inst.sysctl.oid),
+ OID_AUTO, "printtable", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ NULL, 0, intelhfi_sysctl_printtable, "A", "Printout HFI/ITD HW table.");
+
+ SYSCTL_ADD_PROC( &(ihfi_inst.sysctl.ctx), SYSCTL_CHILDREN(ihfi_inst.sysctl.oid),
+ OID_AUTO, "dumptable", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ NULL, 0, intelhfi_sysctl_dumptable, "A", "[DEBUG] Dump HFI/ITD HW table.");
+
+ return (0);
+}
+
+static void
+intelhfi_remove_sysctl(void)
+{
+ sysctl_ctx_free(&(ihfi_inst.sysctl.ctx));
+}
+
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -180,6 +180,7 @@
imgact_binmisc \
${_imx} \
${_intel_pmc} \
+ ${_intelhfi} \
${_intelspi} \
${_io} \
${_ioat} \
@@ -834,6 +835,7 @@
_ichwd= ichwd
_ida= ida
_intel_pmc= intel_pmc
+_intelhfi= intelhfi
_intelspi= intelspi
_ips= ips
_isci= isci
diff --git a/sys/modules/intelhfi/Makefile b/sys/modules/intelhfi/Makefile
new file mode 100644
--- /dev/null
+++ b/sys/modules/intelhfi/Makefile
@@ -0,0 +1,6 @@
+.PATH: ${SRCTOP}/sys/dev/intelhfi
+
+KMOD= intelhfi
+SRCS= intelhfi.c bus_if.h device_if.h opt_intelhfi.h
+
+.include <bsd.kmod.mk>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Sep 30, 7:50 AM (9 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39932710
Default Alt Text
D44456.diff (21 KB)
Attached To
Mode
D44456: intelhfi - Intel TD/HFI driver - Part4: Add intelhfi driver's source-code & Makefile.
Attached
Detach File
Event Timeline
Log In to Comment