FreeBSD throttle cpu clock on high temperature

cpufreebsdpower-managementtemperature

I'm using a laptop with bad cooling system, so my CPU sometimes hits very high temperature, and linux kernel is able to throttle cpu clock to cool it as I can see in dmesg:

[22612.245243] CPU3: Core temperature above threshold, cpu clock throttled (total events = 617268)
...
[22612.257307] CPU3: Core temperature/speed normal
etc

Lately, I installed FreeBSD to play with it and I noticed that it uses CPU at full speed all the time, even when I set powerd to -a hiadaptive -b adaptive -i 85 -r 60 -p 100, so after some usage CPU temp goes above normal and FreeBSD just restarts instead of throttling.
I also tried to use C-states but it doesn't helped.

How can I configure it to get linux behavior?

Best Answer

I had a similar problem in that my firewall (an old laptop) would shut down due to CPU overheat. I used the following steps to solve the problem, valid for the pfSense firewall:

1) Download FreeBSD cpu-speed.sh file from GitHub by dreamcat4

2) Create file cpu-speed.sh, and paste contents from source linked in previous step, through pfSense management interface, using Diagnostics >> Edit File

3) Enable execution of file cpu-speed.sh in fSense management interface, using Diagnostics >> Command Prompt and the command $ chmod +x /[path_to_file]/cpu-speed.sh

4) Check available CPU frequencies by running $ sysctl dev.cpu.0.freq_levels in Command Prompt

4) Run file cpu-speed.sh [valid_CPU_frq] using command $ cd /[path_to_file] && ./cpu-speed.sh [valid_CPU_frq]

5) Check current (new) CPU frequency using command $ sysctl dev.cpu.0.freq

6) Done.

I chose the min acceptable CPU core frequency for my CPU, and was able to permanently reduce the CPU core temp of my CPU from +90 C to < 60 C.

EDIT: To avoid dead links in the future, please find the code by dreamcat4 (as linked above) for file cpu-speed.sh below:

#!/bin/sh
#
# cpu-speed:
#   Requirements - be the root user, FreeBSD 9.2 or higher.
# 
#   Get or set the CPU frequency. This command with no arguments will
#   print the current CPU frequency. CPU may be idling at it's lowest speed.
#
#   This command takes 1 optional argument - new MAX cpu freq (in Mhz).
#   expressed as an integer number. e.g. "cpu 800" - set max freq 800 Mhz.
#   This MAX figure is the new max frequency it is allowed to clock up to.
#
#   Number is rounded off to the nearest allowed frequency multiplier.
#

show_all_cpu_sysctl_settings()
{
# Most FreeBSD kernel settings are read-only. Some may look like duplicates.
# Very few are read-write (so we use powerd). Some CPU settings depend on the CPU family.

# This command should reveal all the CPU-related key names:
    sysctl - a | grep - i cpu
}

set_cpu_speed()
{
# To change the max clock, we must restart the "powerd" rc.d service 
# with new cmdline arguments. "man powerd" for more information.
    if ["$(id -u)" = "0"]; then
    if [!"$(grep "cpuspeed" " / etc / rc.conf")"]; then
       echo "" >> "/etc/rc.conf"
      echo "powerd_enable=\"YES\"" >> "/etc/rc.conf"

      # make the cmdline argument to -M flag a txt substitution with the txt file "/etc/cpuspeed"
    echo "powerd_flags=\"-M \$(cat /etc/cpuspeed)\"" >> "/etc/rc.conf"
    fi

    if ["$1"]; then
# write our new cpu speed to the txt file "/etc/cpuspeed"
      echo "$1" > / etc / cpuspeed

# restart powerd daemon to read the new cpu speed
      / etc / rc.d / powerd restart > / dev / null
    fi
  fi


}

print_current_cpu_freq()
{
# Report back the current cpu frequency for core "0"
    sysctl dev.cpu.0.freq
}

show_possible_cpu_speeds()
{
# Show a list of all possible cpu frequency steps for core "0"
    sysctl dev.cpu.0.freq_levels
}

main()
{
    set_cpu_speed "$@";
    sleep 1; # give it a chance to update before we check the new value
  print_current_cpu_freq;
    show_possible_cpu_speeds;
}

# Entry point
main "$@"
Related Question