Довольно часто возникает потребность получить температуру центрального процессора. На FreeBSD 9.0 я однажды пришел к решению, но затем вышла FreeBSD 9.1, времени обновиться не было, а надежды на нативную поддержку датчика температуры в AMD K15 были. Как следует из названия, в данной статье будет рассматриваться исключительно кривой метод получения температуры процессора, в силу отсутствия поддержки оной как таковой в текущей стабильной FreeBSD 9.1.
Рассмотрим способ получения температуры с определенной погрешностью (почему именно с погрешностью, станет понятно уже сейчас):
Для начала, скачаем модуль amdtemp из FreeBSD-HEAD:
# cd /usr/src/sys/dev/amdtemp/
# fetch https://raw.github.com/freebsd/freebsd-head/master/sys/dev/amdtemp/amdtemp.c
Далее, так как поддержка датчика температуры даже в head до сих пор не адекватная, предложу вот такой костыль:
--- amdtemp.c.orig 2013-02-16 14:24:14.030226619 +0400
+++ amdtemp.c 2013-02-16 14:25:54.031260014 +0400
@@ -324,6 +324,13 @@
case 0x11:
case 0x12:
case 0x14:
+ /*
+ * There is only one sensor per package.
+ */
+ sc->sc_ntemps = 1;
+
+ sc->sc_gettemp = amdtemp_gettemp;
+ break;
case 0x15:
/*
* There is only one sensor per package.
@@ -331,6 +338,7 @@
sc->sc_ntemps = 1;
sc->sc_gettemp = amdtemp_gettemp;
+ sc->sc_offset = 20;
break;
}
Ну, собственно выполним сборку с некоторыми предварительными действиями (которые могут потребоваться, если мир ещё не собирался):
# cd /usr/src/sys/modules/amdtemp
# ln -s /usr/src/sys @
# ln -s /usr/src/sys/amd64/include machine
# ln -s /usr/src/sys/x68/include x86
# WERROR= NO_WERROR= export WERROR NO_WERROR
# make
Warning: Object directory not changed from original /usr/src/sys/modules/amdtemp
awk -f @/tools/makeobjops.awk @/kern/bus_if.m -h
awk -f @/tools/makeobjops.awk @/kern/device_if.m -h
awk -f @/tools/makeobjops.awk @/dev/pci/pci_if.m -h
gcc -m64 -fomit-frame-pointer -Wall -O3 -s -march=native -mfpmath=sse -O2 -s -march=native -m64 -fomit-frame-pointer -fno-strict-aliasing -D_KERNEL -
DKLD_MODULE -nostdinc -I. -I@ -I@/contrib/altq -finline-limit=8000 --param inline-unit-growth=100 --param large-function-growth=1000 -fno-common -fno-
omit-frame-pointer -mno-sse -mcmodel=kernel -mno-red-zone -mno-mmx -msoft-float -fno-asynchronous-unwind-tables -ffreestanding -fstack-protector -
std=iso9899:1999 -fstack-protector -Wall -Wredundant-decls -Wnested-externs -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Winline -Wcast-qual
-Wundef -Wno-pointer-sign -fformat-extensions -Wmissing-include-dirs -fdiagnostics-show-option -c /usr/src/sys/modules/amdtemp/../../dev/amdtemp/amdtemp.c
/usr/src/sys/modules/amdtemp/../../dev/amdtemp/amdtemp.c:1: warning: SSE instruction set disabled, using 387 arithmetics
ld -d -warn-common -r -d -o amdtemp.ko amdtemp.o
:> export_syms
awk -f /usr/src/sys/modules/amdtemp/../../conf/kmod_syms.awk amdtemp.ko export_syms | xargs -J% objcopy % amdtemp.ko
objcopy --strip-debug amdtemp.ko
Проверим работу свежесобранного модуля. Для этого, выгрузим его, если он был загружен и загрузим новую версию:
# kldunload amdtemp
# kldload ./amdtemp.ko
# sysctl dev.amdtemp.0.core0.sensor0
dev.amdtemp.0.core0.sensor0: 43,1C
Ну и в варианте - один датчик на ядро (что примечательно, датчик-то всего единственный):
# sysctl -a | grep tempe
dev.cpu.0.temperature: 43,1C
dev.cpu.1.temperature: 43,1C
dev.cpu.2.temperature: 43,1C
dev.cpu.3.temperature: 43,1C
dev.cpu.4.temperature: 43,1C
dev.cpu.5.temperature: 43,1C
dev.cpu.6.temperature: 43,1C
dev.cpu.7.temperature: 43,1C
Если всё работает, можно выполнить замещение текущего модуля свежесобранным:
# cp /boot/kernel/amdtemp.ko /boot/kernel/amdtemp.ko.old
# cp amdtemp.ko /boot/kernel/amdtemp.ko
Ну и для загрузки модуля при старте системы, убедимся в наличии соответствующей строки в loader.conf:
# vi /boot/loader.conf
amdtemp_load="YES"
Теперь можно смело использовать примерное значение температуры. Будем надеяться, что разработчики довольно быстро сделают из костыля прочную подпорку и уже во FreeBSD10 мы увидим адекватную работу с датчиком температуры на AMD K15.
Примечание:
Значение dev.amdtemp.0.sensor_offset я выбирал экспериментально и не долго думая (чтобы показатели в системе совпадали с показателями BIOS).