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 <[email protected]>
+ *
+ * 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