From 9bbfa0cab6351d13e1a643f640f2492155bf1124 Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Tue, 11 Oct 2022 21:39:24 +0200 Subject: [PATCH] first commit --- Makefile | 21 +++++++++++++ README | 9 ++++++ undervolt.sh | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 Makefile create mode 100644 README create mode 100644 undervolt.sh diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..df1b690 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +VERSION = 0.0.1 +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/share/man + +undervolt: undervolt.sh + +install: undervolt + mkdir -p ${DESTDIR}${PREFIX}/bin + cp -f undervolt ${DESTDIR}${PREFIX}/bin/undervolt + chmod 755 ${DESTDIR}${PREFIX}/bin/undervolt +# TODO: add a manual page +# mkdir -p ${DESTDIR}${MANPREFIX}/man1 +# sed "s/VERSION/${VERSION}/g" < undervolt.1 > ${DESTDIR}${MANPREFIX}/man1/undervolt.1 +# chmod 644 ${DESTDIR}${MANPREFIX}/man1/undervolt.1 + +uninstall: + rm -f ${DESTDIR}${PREFIX}/bin/undervolt\ + ${DESTDIR}${MANPREFIX}/man1/undervolt.1 + +clean: + rm -f undervolt diff --git a/README b/README new file mode 100644 index 0000000..0a08a4c --- /dev/null +++ b/README @@ -0,0 +1,9 @@ +undervolt +========= + +shell script that uses amdctl[1] and ryzenadj[2] to undervolt and limit the power +consumption of the CPU. + +Only works for AMD Ryzen CPUs. +Tested on: + - Ryzen 5 3500U (Lenovo IdeaPad s540-14API) diff --git a/undervolt.sh b/undervolt.sh new file mode 100644 index 0000000..9e77a3b --- /dev/null +++ b/undervolt.sh @@ -0,0 +1,87 @@ +#!/bin/sh -e + +# TODO: check for root privileges +# TODO: check if all the required tools are available + +CPUS="$(nproc)" +GOVERNOR='ondemand' +# Out your wanted values here +CORE_SPEED_HZ_P0=2300000 # 2.30GHz slightly over the base (2.10GHz) +CORE_SPEED_HZ_P1=1450000 # 1.45GHz +CORE_SPEED_HZ_P2=1000000 # 1.00GHz +# wanted voltage in millivolts +VOLTAGE_MV_P0=1125 # this should be stable +VOLTAGE_MV_P1=900 +VOLTAGE_MV_P2=850 +# Power limits +SUSTAINED_LIMIT_MW=10000 +SLOW_LIMIT_MW=20000 +# Temperature limits +MAX_TEMP_C=85 + +# set cpu frequency scaling driver, use acpi_cpufreq since the ryzen 5 3500u +# does not support the amd_pstate driver +# acpi_cpufreq is already the default + +# enable cpu frequency boost if available +echo 1 > /sys/devices/system/cpu/cpufreq/boost + +# set governor +for c in $(seq 0 $((CPUS-1))) +do + echo $GOVERNOR > /sys/devices/system/cpu/"cpu$c"/cpufreq/scaling_governor +done + +# +# set voltage +# =========== + + +VID_P0="$(amdctl -u $VOLTAGE_MV_P0 | grep vid | awk '{print $3}')" +VID_P1="$(amdctl -u $VOLTAGE_MV_P1 | grep vid | awk '{print $3}')" +VID_P2="$(amdctl -u $VOLTAGE_MV_P2 | grep vid | awk '{print $3}')" + +for c in 0 .. $((CPUS-1)) +do + amdctl -s -m -c $c -p 0 -v "$VID_P0" + amdctl -s -m -c $c -p 1 -v "$VID_P1" + amdctl -s -m -c $c -p 2 -v "$VID_P2" +done + +# +# set frequency +# ============= + +# TODO: get this from amdctl +REFERENCE_CLOCK=100000 + +DID_P0="$(amdctl -c 0 -p 0 -g | grep -1 CpuDid | sed -n '3p' | awk '{print $4}')" +DID_P1="$(amdctl -c 0 -p 1 -g | grep -1 CpuDid | sed -n '3p' | awk '{print $4}')" +DID_P2="$(amdctl -c 0 -p 2 -g | grep -1 CpuDid | sed -n '3p' | awk '{print $4}')" + +# FIXME: this is taken from https://github.com/kevinlekiller/amdctl/blob/master/amdctl.c#L988 +# it would be better to submint a pull request and add an option to +# this automatically for each processor family +FID_P0="$(((CORE_SPEED_HZ_P0*DID_P0)/(REFERENCE_CLOCK*2)))" +FID_P1="$(((CORE_SPEED_HZ_P1*DID_P1)/(REFERENCE_CLOCK*2)))" +FID_P2="$(((CORE_SPEED_HZ_P2*DID_P2)/(REFERENCE_CLOCK*2)))" + + +for c in 0 .. $((CPUS-1)) +do + amdctl -s -m -c $c -p 0 -f $FID_P0 + amdctl -s -m -c $c -p 1 -f $FID_P1 + amdctl -s -m -c $c -p 2 -f $FID_P2 +done + + +# +# Power Limits +# ============ + +ryzenadj --stapm-limit=$SUSTAINED_LIMIT_MW \ + --tctl-temp=$MAX_TEMP_C \ + --slow-limit=$SLOW_LIMIT_MW + + +# TODO: undervolt and overclock slightly the GPU