add undervolt

git-svn-id: https://svn.disconnected-by-peer.at/svn/linamh/trunk/linamh@1543 6952d904-891a-0410-993b-d76249ca496b
This commit is contained in:
geos_one
2009-09-04 15:13:34 +00:00
parent d26bd1d18f
commit 90e8adfb27
6 changed files with 513 additions and 0 deletions

View File

@@ -0,0 +1,165 @@
#!/bin/bash
# This file contains script functions to help modifying files.
# confirm_append Appends to the end of the file
# confirm_replace Locates a line and replaces a substring
#
# The functions are controlled through variables:
# file="/path/to/edited/file"
# pattern="installed" Will skip if pattern matches. Leave empty to disable.
#
# confirm_append:
# append="String to be appended.\n - Here's another line"
#
# confirm_replace:
# line="Line search pattern"
# search="String search pattern"
# replace="Replace matched substring with this"
# Text Colors:
esc="\033["
tc000="${esc}30m"
tcf00="${esc}31m"
tc0f0="${esc}32m"
tcff0="${esc}33m"
tc00f="${esc}34m"
tcf0f="${esc}35m"
tc0ff="${esc}36m"
tcfff="${esc}37m"
tcRst="${esc}0m"
# Background Colors:
bc000="${esc}40m"
bcf00="${esc}41m"
bc0f0="${esc}42m"
bcff0="${esc}43m"
bc00f="${esc}44m"
bcf0f="${esc}45m"
bc0ff="${esc}46m"
bcfff="${esc}47m"
check () {
s=$?
if [ "$s" = "0" ]; then
printf "$tc0f0> Success!$tcRst\n"
else
printf "$tcf00> PhaiL!!!$tcRst\n$tcff0> Smash your head on keyboard to continue.$tcRst\n"
read -n 1 -s > /dev/null
fi
return $s
}
confirm () {
loop=1
while [ "$loop" = "1" ]; do
printf "Do you want to continue? [Y/n/?] "
read -n 1 -s answer
case "$answer" in
"Y" | "y" | "" )
printf "${tc0f0}Yes$tcRst\n"
loop=0
return 0
;;
"?" )
printf "${tc00f}?$tcRst\nIt's really just a ${tc0f0}Yes$tcRst or ${tcf00}No$tcRst >:-[\n"
;;
"N" | "n" )
printf "${tcf00}No$tcRst\n"
loop=0
return 1
;;
* )
printf "${tcff0}$answer$tcRst\n"
;;
esac
done
}
confirm_section () {
confirm || {
printf "$tc00f> Skipping entire section.$tcRst\n"
exit 1
}
}
backup () {
printf "Creating backup ${file}~\n"
cp -a "$file" "${file}~"
check
return $?
}
file_check () {
s=0
if [[ "$create" && ! -f "$file" ]]; then
create=
printf " Create $file\n"
printf "$content" | tee "$file"
check || return $?
s=1
fi
if [[ "$owner" && "`stat -c %U:%G \"$file\"`" != "$owner" ]]; then
printf " Change ownsership of $file\n"
chown "$owner" "$file"
check || return $?
s=1
fi
if [[ "$perm" && "`stat -c %a \"$file\"`" != "$perm" ]]; then
printf " Change permissions of $file\n"
chmod "$perm" "$file"
check || return $?
s=1
fi
if [ "$s" = "0" ]; then
printf "${tc00f}> SKIPPED:$tcRst Already applied\n"
fi
return 0
}
pattern_count () {
awk "/$pattern/{n++}; END {print n+0}" "$file"
}
line_count () {
awk "/$line/{n++}; END {print n+0}" "$file"
}
pattern_confirm () {
if [ ! -f "$file" ]; then
printf "${tcff0}> WARNING:$tcRst Could not find $file\n"
return 1
fi
if [[ ( "$pattern" && "`pattern_count`" -gt "0" ) || ( ! "$pattern" && "`line_count`" = "0" ) ]]; then
printf "${tc00f}> SKIPPED:$tcRst Already applied\n"
return 1
fi
return 0
}
append () {
printf "Appending to $file\n"
printf "$append" | tee -a "$file" > /dev/null
check
return $?
}
replace () {
printf "Scanning $file\n"
result="`awk \"/$line/{sub(/$search/, \\\"$replace\\\")}; {print}\" \"${file}\"`"
check && {
printf "Writing $file\n"
printf "$result" | tee "$file" > /dev/null
}
check
return $?
}
confirm_append () {
pattern_confirm && confirm && append
return $?
}
confirm_replace () {
pattern_confirm && confirm && replace
return $?
}

View File

@@ -0,0 +1,179 @@
#!/bin/bash
. /usr/share/undervolt/functions.bash || {
printf "ERROR: Could not load functions.bash\n"
exit 1
}
# http://phc.athousandnights.de/
printf "\n I assume you have linux-phc correctly installed and working.
This script will optimize your voltages at every speed setting by
systematically lowering them while stressing the CPU.
Each voltage will be turned down until your system crashes, and the final
setting for that voltage will be 2 VIDs above that to \"ensure\" stability.
WARNING:
This script will crash your system as many times as there are VIDs to tweak.
You might destroy your hardware, break laws and/or die in vain if you continue.\n\n"
confirm || exit 0
cpufreq=/sys/devices/system/cpu/cpu0/cpufreq
phc_vids=$cpufreq/phc_vids
printf "\n\nWill use current directory to store/retrieve test results.\n"
printf "\nRead phc_default_vids:\n"
cat $cpufreq/phc_default_vids > /dev/null
check || exit 1
def_vids=`cat $cpufreq/phc_default_vids`
if [ -f phc_tweaked_vids ]; then
printf "\nLoad VIDs from 'phc_tweaked_vids'\n"
cur_vids=`cat phc_tweaked_vids`
else
printf "\nRead default VIDs.\n"
cur_vids="$def_vids"
fi
count_phc=`printf "$def_vids" | awk '{print NF}'`
count_tweak=`printf "$cur_vids" | awk '{printf NF}'`
if [ "$count_phc" != "$count_tweak" ]; then
printf "$tcf00> ERROR:$tcRst Wrong VID count!\n"
exit 1
fi
let count_phc--
check || {
printf "$tcf00> ERROR:$tcRst Number of VIDs is zero!\n"
exit 1
}
if [[ -f phc_tweaked_vids && -f phc_cur_pos ]]; then
printf "Load position from 'phc_cur_pos'\n"
cur_pos=`cat phc_cur_pos`
let ++cur_pos
check || exit 1
else
printf "Reset position to 0.\n"
cur_pos=0
fi
printf "Read available frequencies.\n"
freqs=`cat $cpufreq/scaling_available_frequencies`
c=0
for i in $freqs; do
let c++
freq[c]=$i
done
if [ "$c" != "$count_tweak" ]; then
printf "$tcf00> ERROR:$tcRst Number of frequencies ($c) and VIDs ($count_tweak) do not match!\n"
exit 1
fi
check
#printf "$cur_vids" | awk '{for (i=1; i<=NF; i++) print $i}'
c=0
for i in $cur_vids; do
let c++
vid[c]=$i
if [ "$c" -lt "$cur_pos" ]; then
vids_done="$vids_done$i "
fi
if [ "$c" = "$cur_pos" ]; then
printf "\nLast VID: $i\n"
let vid[c]+=2
if [ "${vid[$c]}" -gt "${vid[$(( $c - 1 ))]}" ]; then
printf "Replace with VID from previous position.\n"
let vid[c]=vid[c-1]
else
printf "Increase by +2\n"
fi
vid_last="${vid[c]} "
fi
if [ "$(( c - 1 ))" = "$cur_pos" ]; then
vid_next="$i"
else if [ "$c" -gt "$cur_pos" ]; then
vids_rem="$vids_rem $i"
fi
fi
done
printf "\nDefault VIDs: $def_vids
Current VIDs: $tc0f0$vids_done$tcf00$vid_last$tcff0$vid_next$tcRst$vids_rem\n"
printf "$vids_done$vid_last$vid_next$vids_rem" > phc_tweaked_vids
printf "$cur_pos" > phc_cur_pos
if [ "$cur_pos" -gt "$count_phc" ]; then
printf "\nAll VIDs have been tweaked!
Results are in the file 'phc_tweaked_vids' - use with care.\n"
printf "\nAll done! - Have a nice day.\n"
exit 0
fi
if [ "x$vid_last" != "x" ]; then
if [ "$vid_next" -gt "${vid[$cur_pos]}" ]; then
printf "\nNext VID higher than last - copying."
vid[$(( cur_pos + 1 ))]=${vid[$cur_pos]}
fi
fi
let ++cur_pos
printf "\nSwitch to 'userspace' scaling governor.\n"
printf "userspace" | tee $cpufreq/scaling_governor > /dev/null
check || exit 1
printf "Set frequency to ${freq[$cur_pos]}.\n"
printf "${freq[$cur_pos]}" | tee $cpufreq/scaling_setspeed > /dev/null
check || exit 1
printf "Run burnMMX.\n"
grep [b]urnMMX > /dev/null && printf "...already running.\n" || burnMMX &
printf " PID: $!\n"
recover () {
printf "\n\nRecovering CPU.\n"
printf "$vids_done$vid_last$((${vid[$cur_pos]} + 2))$vids_rem" | tee $cpufreq/phc_vids > /dev/null
printf "ondemand" | tee $cpufreq/scaling_governor > /dev/null
pkill burnMMX
printf "\nRun this script again to continue the optimization.\n"
}
printf "\n-----\nStart testing.\n"
confirm || {
recover
exit 1
}
while [[ 1 ]]; do
let vid[cur_pos]--
printf "\nDefault VIDs: $def_vids
Current VIDs: $tc0f0$vids_done$tc0f0$vid_last$tcf00${vid[$cur_pos]}$tcRst$vids_rem
Testing VID: ${vid[$cur_pos]} ($(( ${vid[$cur_pos]} * 16 + 700)) mV)\n"
printf "$vids_done$vid_last${vid[$cur_pos]}$vids_rem" > phc_tweaked_vids
sync
if [ "${vid[$cur_pos]}" -lt "0" ]; then
printf "\n\nThe lowest acceptable VID is 0."
recover
exit 0
fi
printf "$vids_done$vid_last${vid[$cur_pos]}$vids_rem" | tee $cpufreq/phc_vids > /dev/null
c=0
while [ "$c" -lt "30" ]; do
ps aux | grep [b]urnMMX > /dev/null || {
printf "\nburnMMX crashed!"
recover
exit 0
}
printf "."
sleep 0.5
let c++
done
done

View File

@@ -0,0 +1,22 @@
# Path to the voltage table sysfs interface file
# The init script will detect which one of the 2 below file exists and use the correspond table
VTABLE_PATH_0_2_X="/sys/devices/system/cpu/cpu0/cpufreq/op_points_table"
VTABLE_PATH_0_3_X="/sys/devices/system/cpu/cpu0/cpufreq/phc_controls"
# Switch back to DEFAULT_VTABLE if undervoltage is stopped? [yes/no]
SWITCH_BACK="no"
# Default voltages that will be restored at shutdown if SWITCH_BACK=yes
# Linux PHC 0.2.x uses a table of Frequency:Voltage pairs
# Linux PHC 0.3.x uses a table of FID:VID pairs
#DEFAULT_VTABLE_0_2_X="798000:988,1064000:1116,1330000:1244,1596000:1356"
#DEFAULT_VTABLE_0_3_X="12:16 10:10 8:4 6:0"
# Custom voltages that will be applied at boot time
#CUSTOM_VTABLE_0_2_X="600000:700,800000:764,1000000:860,12000000:956"
#CUSTOM_VTABLE_0_3_X="12:16 10:10 8:4 6:0"
# Set the following to "yes" when the all the settings are configured
# This is a safety to disable setting the voltages with the default
# values of this file that are probably wrong for your CPU
IS_CONFIGURED="no"

View File

@@ -0,0 +1,113 @@
#!/sbin/runscript
# Copyright 1999-2005 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
CUSTOM_VTABLE=" "
DEFAULT_VTABLE=" "
VTABLE_PATH=" "
depend()
{
need localmount
need logger
}
do_error()
{
# Display an error
# $1: Error message
eerror $1
eerror "see http://gentoo-wiki.com/HOWTO_Undervolt_a_Pentium_M_CPU for further information"
eend 1
}
sysfs_check()
{
# Check that the sysfs interface exists
if [ -e ${VTABLE_PATH_0_3_X} ]; then
VTABLE_PATH="${VTABLE_PATH_0_3_X}"
CUSTOM_VTABLE="${CUSTOM_VTABLE_0_3_X}"
DEFAULT_VTABLE="${DEFAULT_VTABLE_0_3_X}"
return 0
else
if [ -e ${VTABLE_PATH_0_2_X} ]; then
VTABLE_PATH="${VTABLE_PATH_0_2_X}"
CUSTOM_VTABLE="${CUSTOM_VTABLE_0_2_X}"
DEFAULT_VTABLE="${DEFAULT_VTABLE_0_2_X}"
return 0
else
logger "Undervolt: SysFs table not found. Can't modify CPU voltages."
eerror "SysFs voltage_table not found. Can't modify CPU voltage table."
eerror "It seems that the undervolting patch has not been applied to the kernel"
do_error "or that the file /etc/conf.d/undervolt is not correctly configured."
return 1
fi
fi
}
einfo_tables()
{
# display current table and a custom table
# $1 : custom table to display
# Display the voltage table currently used by the CPU
einfo "Current table: "`cat ${VTABLE_PATH} `
# Display the custom voltage table
einfo "Configured table: ${1}"
}
set_custom_table()
{
# Set a custom table through the sysfs interface
# $1 : custom table to set
# Display current table and custom table that will be set
einfo_tables "${1}"
# Write the custom voltage to the SysFS interface and display the
# new voltage table that is now used by the CPU if there is no error
echo "${1}" > ${VTABLE_PATH} && \
einfo "Applied table: "`cat ${VTABLE_PATH}`
return $?
}
start()
{
ebegin "Changing CPU voltages table"
if [ "$IS_CONFIGURED" = "yes" ]; then
sysfs_check || return 1
set_custom_table "${CUSTOM_VTABLE}"
eend $?
else
do_error "Custom voltage table is not configured. Check the file /etc/conf.d/undervolt"
fi
}
# I think it is not necessary to switch to the default voltage table on shutdown
# But this init script provides that feature in case you don't agree.
stop()
{
if [ "$SWITCH_BACK" = "yes" ]; then
if [ "$IS_CONFIGURED" = "yes" ]; then
ebegin "Switching back to default CPU voltage table"
sysfs_check || return 1
set_custom_table "${DEFAULT_VTABLE}"
eend $?
else
do_error "Default voltage table is not configured. Check the file /etc/conf.d/undervolt"
fi
else
ebegin "Not switching back to default CPU voltage table (disabled in configuration)"
eend 0
fi
}