From 90e8adfb27c0f10fa352cc9268affaca8f9fb2f7 Mon Sep 17 00:00:00 2001 From: geos_one Date: Fri, 4 Sep 2009 15:13:34 +0000 Subject: [PATCH] add undervolt git-svn-id: https://svn.disconnected-by-peer.at/svn/linamh/trunk/linamh@1543 6952d904-891a-0410-993b-d76249ca496b --- sys-power/undervolt/Manifest | 5 + sys-power/undervolt/files/functions.bash | 165 ++++++++++++++++ .../undervolt/files/linux-phc-optimize.bash | 179 ++++++++++++++++++ sys-power/undervolt/files/undervolt.confd | 22 +++ sys-power/undervolt/files/undervolt.initd | 113 +++++++++++ sys-power/undervolt/undervolt-1.ebuild | 29 +++ 6 files changed, 513 insertions(+) create mode 100644 sys-power/undervolt/Manifest create mode 100644 sys-power/undervolt/files/functions.bash create mode 100644 sys-power/undervolt/files/linux-phc-optimize.bash create mode 100644 sys-power/undervolt/files/undervolt.confd create mode 100644 sys-power/undervolt/files/undervolt.initd create mode 100644 sys-power/undervolt/undervolt-1.ebuild diff --git a/sys-power/undervolt/Manifest b/sys-power/undervolt/Manifest new file mode 100644 index 00000000..5675c5bd --- /dev/null +++ b/sys-power/undervolt/Manifest @@ -0,0 +1,5 @@ +AUX functions.bash 3234 RMD160 e360fbe368c897677bce7dc656acd434afc032df SHA1 59bcc66163b9717f5a56e12a9c53b9af552ff5f0 SHA256 233ec1f391dabc2def1d2838f450c6ba4a5846d2d7beb92dd5bade21b35dd15b +AUX linux-phc-optimize.bash 4596 RMD160 10bda6d0fe9209b6c0639a2a74ca734a2b6197c8 SHA1 94c281b6218433c331ae19eaace25b6283ab6c47 SHA256 88ee7ba18669960e1497605334ec26748f98360c7c9f6bd05dcc4a1929f2a303 +AUX undervolt.confd 1054 RMD160 5dd92c3c45d1192898ef996a85bb1f094b5c7a0b SHA1 b64a650a3dcb1e43de35db3a6902c77cb797eb03 SHA256 a0921aa0471832c4d3d538de00505a6ab93a1794c7c2df48ed027725d5faf81d +AUX undervolt.initd 2808 RMD160 647be5efd98a241023da1eb585fed03fabd2d473 SHA1 9a4c27add2d9dc1ecab2f9be5189084e0376789e SHA256 6fca74f1177db0ccf92889e87401ce3e10cde46e6f15b1151dd2be65b361d5ef +EBUILD undervolt-1.ebuild 726 RMD160 0f10c715c95ef64f4ecc867f1c75fc8439cca08a SHA1 7441fcd7b4ce0838c9276b56fda4674689fa47b7 SHA256 a1a4bba1c40ef8cd9b9ed4173d131152963565eac24779acc7d53c890d5cd9f8 diff --git a/sys-power/undervolt/files/functions.bash b/sys-power/undervolt/files/functions.bash new file mode 100644 index 00000000..12ad625a --- /dev/null +++ b/sys-power/undervolt/files/functions.bash @@ -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 $? +} + diff --git a/sys-power/undervolt/files/linux-phc-optimize.bash b/sys-power/undervolt/files/linux-phc-optimize.bash new file mode 100644 index 00000000..95dffa96 --- /dev/null +++ b/sys-power/undervolt/files/linux-phc-optimize.bash @@ -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 diff --git a/sys-power/undervolt/files/undervolt.confd b/sys-power/undervolt/files/undervolt.confd new file mode 100644 index 00000000..e77c2921 --- /dev/null +++ b/sys-power/undervolt/files/undervolt.confd @@ -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" \ No newline at end of file diff --git a/sys-power/undervolt/files/undervolt.initd b/sys-power/undervolt/files/undervolt.initd new file mode 100644 index 00000000..b3fbf439 --- /dev/null +++ b/sys-power/undervolt/files/undervolt.initd @@ -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 +} \ No newline at end of file diff --git a/sys-power/undervolt/undervolt-1.ebuild b/sys-power/undervolt/undervolt-1.ebuild new file mode 100644 index 00000000..44f03156 --- /dev/null +++ b/sys-power/undervolt/undervolt-1.ebuild @@ -0,0 +1,29 @@ +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +EAPI="2" + +inherit eutils + +DESCRIPTION="A collection of undervolt scripts" +HOMEPAGE="http://www.linux-phc.org/forum/viewtopic.php?f=19&t=44 http://www.s3pp.de/misc/linux-phc-optimize.bash" +# SRC_URI="mirror://sourceforge/${PN}/${PF}.tar.gz" + +LICENSE="GPL-2" +SLOT="0" +KEYWORDS="~amd64 ~x86" +IUSE="" + +DEPEND="" +RDEPEND="app-benchmarks/cpuburn" + +src_compile() { :; } + +src_install() { + newinitd ${FILESDIR}/undervolt.initd undervolt + newconfd ${FILESDIR}/undervolt.confd undervolt + insinto /usr/share/undervolt + doins ${FILESDIR}/functions.bash + newbin ${FILESDIR}/linux-phc-optimize.bash undervolt-optimize +}