Hi, Here is a work-in-progress driver for the Intel eXtreme Tuning Utility. The main purpose is to add more sensors to the existing pool.
I am very interested in tests on recent Intel K- and X-series processors! None the less, please test on all Intel cpus and if you see acpixtu attaching please send me a private mail with the dmesg and acpidump. I initially implemented it for the x260, but there is a mysterious XTUS AML external method that seems to be blocking it on my machine. I tried overwritting it with hacks in dsdt.c but failed. After seeing a few more acpidumps (that don't have the blocking XTUS method) I decided to send it here for wider tests. Thank you, Paul Index: arch/amd64/amd64/locore.S =================================================================== RCS file: /cvs/src/sys/arch/amd64/amd64/locore.S,v retrieving revision 1.82 diff -u -p -u -p -r1.82 locore.S --- arch/amd64/amd64/locore.S 16 Jul 2016 06:04:29 -0000 1.82 +++ arch/amd64/amd64/locore.S 2 Sep 2016 15:05:06 -0000 @@ -1202,3 +1202,18 @@ _C_LABEL(xen_hypercall_page): _C_LABEL(hv_hypercall_page): .skip 0x1000, 0xcc #endif /* NXEN > 0 */ + +/* acpixtu_smi_read(sc->sc_fadt->smi_cmd, xtu_port, &settings_addr) */ +ENTRY(acpixtu_smi_read) + /* Read BIOS Settings Command */ + xorl %ecx,%ecx + /* 32-bit Physical Memory Data Location */ + movl %edx, %ebx + /* Write the SW SMI Command Value to the SW SMI Port */ + movq %rdi, %rdx + movq %rsi, %rax + outb %al, %dx + /* Return Value in EBX */ + xorq %rax, %rax + movl %ebx, %eax + ret Index: arch/amd64/conf/GENERIC =================================================================== RCS file: /cvs/src/sys/arch/amd64/conf/GENERIC,v retrieving revision 1.430 diff -u -p -u -p -r1.430 GENERIC --- arch/amd64/conf/GENERIC 1 Sep 2016 10:04:51 -0000 1.430 +++ arch/amd64/conf/GENERIC 2 Sep 2016 15:05:07 -0000 @@ -67,6 +67,7 @@ sdhc* at acpi? acpicbkbd* at acpi? acpials* at acpi? tpm* at acpi? +acpixtu* at acpi? mpbios0 at bios0 Index: dev/acpi/acpireg.h =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpireg.h,v retrieving revision 1.36 diff -u -p -u -p -r1.36 acpireg.h --- dev/acpi/acpireg.h 10 Jul 2016 20:36:41 -0000 1.36 +++ dev/acpi/acpireg.h 2 Sep 2016 15:05:07 -0000 @@ -778,4 +778,7 @@ struct acpi_ivrs { #define ACPI_DEV_DWIIC4 "INT3433" #define ACPI_DEV_DWIIC5 "80860F41" +/* Intel Extreme Tuning Utility */ +#define ACPI_DEV_XTU "INT3394" + #endif /* !_DEV_ACPI_ACPIREG_H_ */ Index: dev/acpi/acpixtu.c =================================================================== RCS file: dev/acpi/acpixtu.c diff -N dev/acpi/acpixtu.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/acpi/acpixtu.c 2 Sep 2016 15:05:07 -0000 @@ -0,0 +1,252 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2016 Paul Irofti <piro...@openbsd.org> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/types.h> +#include <sys/pool.h> + +#include <machine/bus.h> + +#include <dev/acpi/acpivar.h> +#include <dev/acpi/acpidev.h> +#include <dev/acpi/amltypes.h> +#include <dev/acpi/dsdt.h> + +struct acpixtu_softc { + struct device sc_dev; + + struct acpi_softc *sc_acpi; + struct aml_node *sc_devnode; + + int sc_tsdd; + int sc_vsdd; + int sc_fsdd; +}; + +int acpixtu_match(struct device *, void *, void *); +void acpixtu_attach(struct device *, struct device *, void *); +int acpixtu_notify(struct aml_node *, int, void *); + +struct cfattach acpixtu_ca = { + sizeof(struct acpixtu_softc), acpixtu_match, acpixtu_attach +}; + +struct cfdriver acpixtu_cd = { + NULL, "acpixtu", DV_DULL +}; + +static const char *acpixtu_hids[] = { ACPI_DEV_XTU, 0 }; +uint32_t acpixtu_smi_read(int, int, uint8_t *); + +static int +acpixtu_get_data(struct acpixtu_softc *sc, char *method) +{ + struct aml_value res; + int i; + + if (aml_evalname(sc->sc_acpi, sc->sc_devnode, method, 0, NULL, &res)) { + printf("%s: %s method is absent\n", DEVNAME(sc), method); + return 1; + } + printf("%s: %s(%s) AML dump\n", DEVNAME(sc), __func__, method); + aml_showvalue(&res); + if (res.type == AML_OBJTYPE_INTEGER && !aml_val2int(&res)) { + printf("%s: %s got null package\n", DEVNAME(sc), method); + aml_freevalue(&res); + return 1; + } else if (res.type != AML_OBJTYPE_PACKAGE) { + aml_freevalue(&res); + return 1; + } + printf("%s: %s(%s) sensor data\n", DEVNAME(sc), __func__, method); + for (i = 0; i < res.length; i += 4) { + int usage, id, value; + usage = aml_val2int(res.v_package[i]); + id = aml_val2int(res.v_package[i + 1]); + value = aml_val2int(res.v_package[i + 2]); + value = value - 2732; + printf("sensor[%d]: %d %d %d\n", i/4, usage, id, value); + } + aml_freevalue(&res); + return 0; +} + +int +acpixtu_match(struct device *parent, void *match, void *aux) +{ + struct acpi_attach_args *aaa = aux; + struct cfdata *cf = match; + + return acpi_matchhids(aaa, acpixtu_hids, cf->cf_driver->cd_name); +} + +void +acpixtu_attach(struct device *parent, struct device *self, void *aux) +{ + struct acpixtu_softc *sc = (struct acpixtu_softc *)self; + struct acpi_attach_args *aaa = aux; + + struct aml_value args, res; + int64_t version, major, minor, sampling; + int i, xtu_port; + uint32_t rc; + +#define ACPIXTU_INFO_SIZE 0x20 + uint8_t *info, *preinfo; + uint32_t info_length = ACPIXTU_INFO_SIZE; + uint16_t info_major = 2; + uint16_t info_minor = 0; + + sc->sc_acpi = (struct acpi_softc *)parent; + sc->sc_devnode = aaa->aaa_node; + + if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "IVER", 0, NULL, &res)) + return; + if (res.type != AML_OBJTYPE_INTEGER) + return; + version = aml_val2int(&res); + major = version >> 16; + minor = version & 0x0000ffff; + + printf(": %s ver%lld.%lld", sc->sc_devnode->name, major, minor); + + if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "GACI", 0, NULL, &res)) + return; + if (res.type == AML_OBJTYPE_PACKAGE) { + if (aml_val2int(res.v_package[0]) != 0) { + printf(" GACI failed (%lld)", + aml_val2int(res.v_package[0])); + return; + } + if (res.v_package[1]->type == AML_OBJTYPE_INTEGER && + aml_val2int(res.v_package[1]) == 0) + printf(" monitor-only"); + } + aml_freevalue(&res); + printf("\n"); + + /* Enable sensors */ + sc->sc_tsdd = sc->sc_vsdd = sc->sc_fsdd = 1; + + /* Fetch XMP Profiles */ + memset(&args, 0, sizeof(args)); + + args.v_integer = 1; + args.type = AML_OBJTYPE_INTEGER; + aml_evalname(sc->sc_acpi, sc->sc_devnode, "GXDV", 1, &args, &res); + printf("GXDV 1:\n"); + aml_showvalue(&res); + aml_freevalue(&res); + + args.v_integer = 2; + aml_evalname(sc->sc_acpi, sc->sc_devnode, "GXDV", 1, &args, &res); + printf("GXDV 2:\n"); + aml_showvalue(&res); + aml_freevalue(&res); + + /* Fetch SMI Command Value */ + aml_evalname(sc->sc_acpi, sc->sc_devnode, "GSCV", 0, NULL, &res); + if (res.type == AML_OBJTYPE_PACKAGE) { + for (i = 0; i < res.length; i++) { + xtu_port = aml_val2int(res.v_package[i]); + printf("%s: SMI (type %d) cmd %d\n", DEVNAME(sc), + res.v_package[i]->type, xtu_port); + } + } else if (res.type == AML_OBJTYPE_INTEGER) { + xtu_port = aml_val2int(&res); + printf("%s: SMI (type %d) cmd %d\n", DEVNAME(sc), + res.type, xtu_port); + } else + printf("%s: SMI unhandled type %d\n", DEVNAME(sc), res.type); + aml_freevalue(&res); + + /* + * Issue an SMI Read to collect current BIOS state + */ + preinfo = info = dma_alloc(ACPIXTU_INFO_SIZE, PR_WAITOK | PR_ZERO); + memcpy(&info[0], "$BD2", 4); /* Signature */ + memcpy(&info[4], &info_length, sizeof(info_length)); /* Length */ + memcpy(&info[8], &info_major, sizeof(info_major)); /* Ver. Major */ + memcpy(&info[10], &info_minor, sizeof(info_minor)); /* Ver. Minor */ + printf("%s: info ptr %p ", DEVNAME(sc), info); + for (i = 0; i < ACPIXTU_INFO_SIZE; i++) + printf("0x%x ", info[i]); + printf("\n"); + + printf("%s: smi_read(%d, %d, %p)\n", DEVNAME(sc), + sc->sc_acpi->sc_fadt->smi_cmd, xtu_port, info); + rc = acpixtu_smi_read(sc->sc_acpi->sc_fadt->smi_cmd, xtu_port, info); + + printf("%s: info ptr %p ret %X ", DEVNAME(sc), info, rc); + if (preinfo != info) + return; + memcpy(&info_length, &info[0], 4); + printf("result %X", info_length); + memcpy(&info_length, &info[4], 4); + printf(" len %X", info_length); + memcpy(&info_major, &info[8], sizeof(info_major)); /* Ver. Major */ + memcpy(&info_minor, &info[10], sizeof(info_minor)); /* Ver. Minor */ + printf(" version %d.%d ", info_major, info_minor); + memcpy(&info_length, &info[0xc], 4); + printf(" settings %d ", info_length); + printf("\n"); + + /* Sensor Sampling Period */ + aml_evalname(sc->sc_acpi, sc->sc_devnode, "SDSP", 0, NULL, &res); + if (res.type == AML_OBJTYPE_INTEGER) { + sampling = aml_val2int(&res); + printf("%s: Sampling %lld00ms\n", DEVNAME(sc), sampling); + } else + printf("%s: Sampling unhandled type %d\n", + DEVNAME(sc), res.type); + aml_freevalue(&res); + + /* + * XXX: Wait for sensor data to be available. + * Ideally this would be a poll argument. + */ + if (sampling) + delay(sampling * 10 * 1000); + + aml_register_notify(sc->sc_devnode, aaa->aaa_dev, + acpixtu_notify, sc, ACPIDEV_POLL); + + dma_free(info, ACPIXTU_INFO_SIZE); +} + +int +acpixtu_notify(struct aml_node *node, int notify, void *arg) +{ + struct acpixtu_softc *sc = arg; + + if (sc->sc_tsdd && acpixtu_get_data(sc, "TSDD")) { + printf("%s: disabling TSDD\n", DEVNAME(sc)); + sc->sc_tsdd = 0; + } + if (sc->sc_vsdd && acpixtu_get_data(sc, "VSDD")) { + printf("%s: disabling VSDD\n", DEVNAME(sc)); + sc->sc_vsdd = 0; + } + if (sc->sc_fsdd && acpixtu_get_data(sc, "FSDD")) { + printf("%s: disabling FSDD\n", DEVNAME(sc)); + sc->sc_fsdd = 0; + } + + return 0; +} Index: dev/acpi/files.acpi =================================================================== RCS file: /cvs/src/sys/dev/acpi/files.acpi,v retrieving revision 1.35 diff -u -p -u -p -r1.35 files.acpi --- dev/acpi/files.acpi 3 Aug 2016 17:23:38 -0000 1.35 +++ dev/acpi/files.acpi 2 Sep 2016 15:05:07 -0000 @@ -145,3 +145,8 @@ file dev/acpi/acpials.c acpials device tpm attach tpm at acpi file dev/acpi/tpm.c tpm + +# Intel Extreme Tuning Utility +device acpixtu +attach acpixtu at acpi +file dev/acpi/acpixtu.c acpixtu