<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Linux Sin Humo (Publicaciones sobre power-management)</title><link>https://sergiobelkin.com/</link><description></description><atom:link href="https://sergiobelkin.com/categories/power-management.xml" rel="self" type="application/rss+xml"></atom:link><language>es</language><copyright>Contents © 2026 &lt;a href="mailto:sebelk@gmail.com"&gt;sebelk&lt;/a&gt; 
&lt;a rel="license" href="https://creativecommons.org/licenses/by-nc-sa/4.0/"&gt;
&lt;img alt="Creative Commons License BY-NC-SA"
style="border-width:0; margin-bottom:12px;"
src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png"&gt;&lt;/a&gt;
</copyright><lastBuildDate>Tue, 23 Jun 2026 04:04:26 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Intel y AMD: quién fija el límite de potencia del CPU</title><link>https://sergiobelkin.com/posts/intel-amd-control-temperatura-frecuencia/</link><dc:creator>sebelk</dc:creator><description>&lt;figure&gt;&lt;img src="https://sergiobelkin.com/images/intel-amd-control-temperatura-frecuencia.webp"&gt;&lt;/figure&gt; &lt;p&gt;Hace unas semanas conté cómo limité térmicamente una notebook Intel usada como CPU box en clamshell —tapa cerrada, monitor portátil encima, la máquina debajo de todo—: &lt;a href="https://sergiobelkin.com/posts/gestion-termica-clamshell-rapl-tuned/"&gt;Gestión térmica en notebook clamshell con RAPL y tuned&lt;/a&gt;. La idea era bajar a mano el techo de potencia para que el CPU no entrara en throttling (que no se frenara solo al recalentarse).&lt;/p&gt;
&lt;p&gt;Cuando fui a repetir lo mismo en un equipo &lt;strong&gt;AMD Ryzen&lt;/strong&gt;, el ejercicio derivó en algo más interesante que portar una receta. Intel y AMD no se diferencian solo en &lt;em&gt;cómo&lt;/em&gt; se toca el límite: se diferencian en &lt;strong&gt;quién puede fijar el límite&lt;/strong&gt; de la potencia y la frecuencia — el hardware solo, o también vos. Y esa diferencia, no el clamshell, es lo que vale la pena contar.&lt;/p&gt;
&lt;p&gt;El clamshell quedó como lo que era: el escenario que me obligó a medir. Lo uso de banco de pruebas, pero el tema es la comparación.&lt;/p&gt;
&lt;h3 id="como-controla-intel-el-limite-lo-escribis-vos"&gt;Cómo controla Intel: el límite lo escribís vos&lt;/h3&gt;
&lt;p&gt;En Intel, el techo de potencia es algo que &lt;strong&gt;escribís vos&lt;/strong&gt;. RAPL (&lt;em&gt;Running Average Power Limit&lt;/em&gt;) expone dos límites de potencia: PL1, el techo sostenido que el chip mantiene en el tiempo, y PL2, uno más alto que se permite por ráfagas cortas (el boost). Viven en el powercap framework del kernel —la interfaz bajo &lt;code&gt;/sys/class/powercap&lt;/code&gt; para poner topes de potencia— y son de lectura/escritura:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12000000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;powercap&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;intel&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rapl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;constraint_0_power_limit_uw&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Ese &lt;code&gt;echo&lt;/code&gt; baja la potencia disponible y el PCU (&lt;em&gt;Power Control Unit&lt;/em&gt;) del CPU la respeta. El hardware sigue teniendo su propia gestión térmica, pero &lt;strong&gt;ese tope es un control compartido&lt;/strong&gt;: el sysadmin puede ponerlo por debajo del default de fábrica, y el procesador lo aplica.&lt;/p&gt;
&lt;h3 id="como-controla-amd-el-limite-lo-decide-el-firmware"&gt;Cómo controla AMD: el límite lo decide el firmware&lt;/h3&gt;
&lt;p&gt;En AMD ese control, sencillamente, no te lo dan. La rama de powercap puede existir —los Ryzen modernos exponen RAPL— pero con una diferencia decisiva:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;En AMD, el RAPL del powercap &lt;strong&gt;reporta energía consumida&lt;/strong&gt; (&lt;code&gt;energy_uj&lt;/code&gt;), pero los archivos de límite de potencia (&lt;code&gt;constraint_*_power_limit_uw&lt;/code&gt;) no se exponen. El máximo de potencia no se fija desde el sistema operativo.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;No es un problema de permisos: el kernel no expone esa escritura para AMD por ninguna vía mainline (lo que viene de fábrica en el kernel oficial). Y hasta la &lt;em&gt;lectura&lt;/em&gt; de energía está acotada: el &lt;code&gt;energy_uj&lt;/code&gt; que aparece más abajo es legible solo por root desde el kernel 5.10, como mitigación de un ataque de canal lateral (PLATYPUS). Escritura del límite, en cambio, nunca hubo. El gobierno de la potencia y la frecuencia ocurre &lt;strong&gt;adentro del SMU&lt;/strong&gt; (&lt;em&gt;System Management Unit&lt;/em&gt;), el microcontrolador del SoC, que regula solo, en tiempo real, contra el primero de varios límites que se sature —potencia, corriente y temperatura—. El sistema operativo no hace esa regulación fina ni escribe el límite de potencia, pero tampoco es un espectador pasivo: le fija la &lt;strong&gt;política&lt;/strong&gt; dentro de la cual optimizar —el gobernador, la preferencia de eficiencia o rendimiento (EPP) y el perfil de energía— y lee la telemetría.&lt;/p&gt;
&lt;p&gt;Comprobalo en tu propia máquina. En vez de apuntar a un archivo puntual, listá el contenido de la zona del paquete y mirá qué hay:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;cat /sys/class/powercap/intel-rapl:0/name
ls -l /sys/class/powercap/intel-rapl:0/
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Dos cosas para notar. La primera: el dominio se llama &lt;code&gt;intel-rapl&lt;/code&gt; aun en una máquina AMD. No es un error — el soporte RAPL de AMD se registra reusando el mismo framework y el mismo nombre que ya existía en el kernel. La segunda, y es el punto: en mi equipo Ryzen el &lt;code&gt;name&lt;/code&gt; da &lt;code&gt;package-0&lt;/code&gt; y adentro solo hay &lt;code&gt;energy_uj&lt;/code&gt; (el contador de energía consumida, de lectura). No existe &lt;strong&gt;ningún&lt;/strong&gt; archivo &lt;code&gt;constraint_*&lt;/code&gt; — ni &lt;code&gt;constraint_0_power_limit_uw&lt;/code&gt; ni sus variantes. En un Intel, esa misma carpeta tendría los &lt;code&gt;constraint_0_*&lt;/code&gt; (PL1) y &lt;code&gt;constraint_1_*&lt;/code&gt; (PL2): los archivos donde se escribe el techo de potencia. En AMD el concepto de límite ni se expone. RAPL mide; no limita. Y es así por cómo está implementado el driver de AMD en mainline, no por una particularidad de este equipo —aunque no probé cada combinación de kernel y BIOS.&lt;/p&gt;
&lt;h3 id="la-evidencia-que-hace-el-firmware-de-amd-bajo-carga"&gt;La evidencia: qué hace el firmware de AMD bajo carga&lt;/h3&gt;
&lt;p&gt;Medí el equipo AMD en clamshell y en AC —la condición real de un CPU box: tapa cerrada, en corriente, con un monitor de 14" apoyado encima bloqueando el aire— con un baseline en reposo y un stress de 20 minutos sostenidos (&lt;code&gt;stress-ng --cpu 0&lt;/code&gt;), registrando temperatura de paquete (&lt;code&gt;Tctl&lt;/code&gt;, el sensor que reporta AMD vía &lt;code&gt;k10temp&lt;/code&gt;) y frecuencia.&lt;/p&gt;
&lt;p&gt;En reposo, ~40 °C. Bajo carga, la temperatura sube despacio y se asienta cerca de 73 °C —todavía trepando muy de a poco al cabo de los 20 minutos—, mientras la frecuencia se mantiene alrededor de ~3,0 GHz toda la corrida, sin caídas abruptas:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;59&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;59.2&lt;/span&gt;&lt;span class="err"&gt;°&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;3044.129&lt;/span&gt;&lt;span class="n"&gt;MHz&lt;/span&gt;
&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;05&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;69.0&lt;/span&gt;&lt;span class="err"&gt;°&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;3019.180&lt;/span&gt;&lt;span class="n"&gt;MHz&lt;/span&gt;
&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;71.2&lt;/span&gt;&lt;span class="err"&gt;°&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;3019.166&lt;/span&gt;&lt;span class="n"&gt;MHz&lt;/span&gt;
&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;73.4&lt;/span&gt;&lt;span class="err"&gt;°&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;freq&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;3019.182&lt;/span&gt;&lt;span class="n"&gt;MHz&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Dos cosas para leer de ahí:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;El firmware sostiene un punto de operación estable de ~3,0 GHz con todos los núcleos cargados, sin que nadie intervenga.&lt;/strong&gt; No es un techo que le puse yo: &lt;code&gt;scaling_max_freq&lt;/code&gt; estaba en el máximo de fábrica. Es el SMU manteniendo la frecuencia que la potencia disponible le permite sostener.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;La temperatura se queda lejos de cualquier límite.&lt;/strong&gt; 73 °C, lejos de su límite térmico —el Tjmax: la temperatura a la que el chip se frena o se apaga para no dañarse, del orden de 90–100 °C según el modelo de Ryzen—: margen de sobra. Y en 20 minutos no hubo una sola caída abrupta de frecuencia: el firmware regula y se queda quieto.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="que-significa-la-diferencia"&gt;Qué significa la diferencia&lt;/h3&gt;
&lt;p&gt;Dos formas de repartir el control:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;En Intel el control se reparte.&lt;/strong&gt; El PCU regula, pero te deja escribir el techo de potencia en mainline (PL1/PL2): podés bajar el límite por debajo del default de fábrica y el procesador lo respeta. Queda compartido entre el hardware y vos. En el post Intel fijé PL1 bajo y &lt;code&gt;tuned&lt;/code&gt; activo, y la frecuencia se sostuvo estable en clamshell — aunque, en realidad, apliqué las dos cosas juntas y no aislé cuánto aportó cada una.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;En AMD el control queda en el firmware.&lt;/strong&gt; El SMU regula de forma autónoma; el sistema operativo le marca una preferencia —hacia eficiencia o rendimiento, vía EPP y el perfil de energía— pero no le escribe el límite de potencia. Para ponerle un techo duro desde mainline, lo único que queda es la &lt;strong&gt;frecuencia&lt;/strong&gt; (&lt;code&gt;scaling_max_freq&lt;/code&gt;). Pero —y esto es lo que muestran las mediciones— el firmware ya está haciendo la regulación: en 20 minutos de carga sostuvo la frecuencia estable por su cuenta, sin que yo tocara nada.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;De esto se sigue algo que va a contramano del reflejo de optimizar:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;En este equipo AMD, bajar el techo de frecuencia no solo es &lt;strong&gt;innecesario&lt;/strong&gt; (el firmware ya regula solo) — es &lt;strong&gt;contraproducente&lt;/strong&gt;: le quitarías rendimiento que el chip podía sostener, sin ganar nada en seguridad térmica.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;La receta de RAPL no se porta a AMD, y no solo porque la API sea distinta (el powercap de AMD solo expone telemetría, sin archivos de límite). Y el problema que la justificaba, en este hardware, tampoco existe: el firmware moderno de AMD gobierna el clamshell solo.&lt;/p&gt;
&lt;h3 id="si-igual-queres-meter-mano-en-amd"&gt;Si igual querés meter mano en AMD&lt;/h3&gt;
&lt;p&gt;Para cerrar, las dos vías reales y su estado:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Techo de frecuencia (&lt;code&gt;scaling_max_freq&lt;/code&gt;, mainline).&lt;/strong&gt; Es lo que el kernel te da, sin agregar nada, para ponerle un techo duro: un &lt;code&gt;echo&lt;/code&gt; por core, persistible al boot (un &lt;em&gt;profile&lt;/em&gt; de &lt;code&gt;tuned&lt;/code&gt; o un service propio), sin tocar voltaje. Útil &lt;strong&gt;si tu equipo sí oscila&lt;/strong&gt; o si querés sacrificar rendimiento a propósito por un equipo más fresco. Por lo que vimos, para seguridad térmica acá sobra.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;El tope de potencia (PPT vía &lt;code&gt;ryzenadj&lt;/code&gt;).&lt;/strong&gt; Es la forma de llegar a ese tope del SMU desde el sistema —los límites que AMD llama PPT (&lt;em&gt;Package Power Tracking&lt;/em&gt;, el tope de potencia del paquete) y STAPM (atado a la temperatura de la carcasa)— pero queda &lt;strong&gt;fuera de mainline&lt;/strong&gt;: &lt;code&gt;ryzenadj&lt;/code&gt; (LGPL-3.0) se compila a mano y necesita el módulo &lt;code&gt;ryzen_smu&lt;/code&gt; (GPL-2.0), que vive &lt;em&gt;out-of-tree&lt;/em&gt; —fuera del árbol del kernel— y hay que recompilar en cada actualización (eso lo automatiza DKMS), además de pelear con Secure Boot. Es libre y se usa en producción en handhelds (Bazzite, Steam Deck), pero es tooling de entusiasta, no de infraestructura. Y es justamente la prueba de la tesis: &lt;strong&gt;el control que Intel expone en mainline, en AMD hay que buscarlo fuera del árbol.&lt;/strong&gt; Nada de esto es peligroso —es runtime, no flashea firmware, un reboot revierte todo— pero para un CPU box que tiene que comportarse como infraestructura, el costo no se justifica.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="contrastar-la-premisa-y-despues-medir"&gt;Contrastar la premisa y después medir&lt;/h3&gt;
&lt;p&gt;El reflejo sería asumir que el setup Intel se porta cambiando una ruta de &lt;code&gt;/sys&lt;/code&gt;. Pero la premisa hay que contrastarla, y no es la misma en los dos fabricantes: en AMD el archivo para establecer un límite ni siquiera está. Contrastarla a tiempo es lo que evita el desvío siguiente —buscar &lt;em&gt;la herramienta que sí escribe watts&lt;/em&gt; y terminar en &lt;code&gt;ryzenadj&lt;/code&gt; con un módulo out-of-tree—. Y antes de salir a buscar esa herramienta, conviene medir: acá la medición mostró que no había nada que arreglar.&lt;/p&gt;
&lt;p&gt;La diferencia de arquitectura entre Intel y AMD define si te toca intervenir o si el firmware ya lo hace.&lt;/p&gt;
&lt;h3 id="lo-que-me-llevo"&gt;Lo que me llevo&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Intel y AMD difieren en quién escribe el límite de potencia: Intel te lo deja en mainline (RAPL r/w); AMD lo retiene en el SMU —desde el SO le marcás una preferencia (eficiencia o rendimiento) y leés energía, pero el tope no lo escribís—.&lt;/li&gt;
&lt;li&gt;En AMD, el firmware sostiene una frecuencia estable por su cuenta (~3,0 GHz en 20 min de carga) y la temperatura se queda con margen de sobra respecto del Tjmax. Sin oscilación ni throttling.&lt;/li&gt;
&lt;li&gt;En AMD el tope de potencia (PPT) no se escribe en mainline —solo con tooling out-of-tree (&lt;code&gt;ryzenadj&lt;/code&gt;)—; en mainline tenés la política (EPP, perfil de energía) y un techo por la frecuencia (&lt;code&gt;scaling_max_freq&lt;/code&gt;), pero no el límite de watts directo. Es la contracara exacta de lo que Intel expone de fábrica.&lt;/li&gt;
&lt;li&gt;Antes de optimizar, medir: en este equipo, bajar el techo habría sido contraproducente.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tuned&lt;/code&gt; cruza sin cambios entre plataformas — solo cambia el driver de scaling debajo (&lt;code&gt;amd_pstate&lt;/code&gt; en vez de &lt;code&gt;intel_pstate&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="fuentes"&gt;Fuentes&lt;/h3&gt;
&lt;p&gt;Documentación oficial y mediciones en el propio equipo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Documentación oficial&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Framework powercap del kernel (RAPL, zonas, &lt;code&gt;constraint_*&lt;/code&gt; de lectura/escritura en Intel): &lt;a href="https://docs.kernel.org/power/powercap/powercap.html"&gt;Power Capping Framework&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Driver &lt;code&gt;amd-pstate&lt;/code&gt; y sus modos (active/EPP): &lt;a href="https://docs.kernel.org/admin-guide/pm/amd-pstate.html"&gt;amd-pstate CPU Performance Scaling Driver&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Restricción de &lt;code&gt;energy_uj&lt;/code&gt; a root como mitigación de canal lateral: &lt;a href="https://platypusattack.com/"&gt;PLATYPUS&lt;/a&gt; y &lt;a href="https://nvd.nist.gov/vuln/detail/CVE-2020-12912"&gt;CVE-2020-12912&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ryzenadj&lt;/code&gt; (LGPL-3.0; PPT/STAPM; necesita el módulo &lt;code&gt;ryzen_smu&lt;/code&gt;): &lt;a href="https://github.com/FlyGoat/RyzenAdj"&gt;FlyGoat/RyzenAdj&lt;/a&gt;. Módulo &lt;code&gt;ryzen_smu&lt;/code&gt; (GPL-2.0, out-of-tree): &lt;a href="https://github.com/leogx9r/ryzen_smu"&gt;leogx9r/ryzen_smu&lt;/a&gt;; para hardware reciente (Zen 5), forks activos como &lt;a href="https://github.com/amkillam/ryzen_smu"&gt;amkillam/ryzen_smu&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Uso de &lt;code&gt;ryzenadj&lt;/code&gt; + &lt;code&gt;ryzen_smu&lt;/code&gt; en handhelds (undervolt del Steam Deck, vía un service con config en &lt;code&gt;/etc/default/ryzenadj&lt;/code&gt;): &lt;a href="https://github.com/ublue-os/bazzite"&gt;Bazzite&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Tjmax exacto por procesador (depende del modelo): &lt;a href="https://www.amd.com/en/products/specifications/processors.html"&gt;especificaciones de AMD&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Verificado en el equipo&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Que el powercap de AMD solo expone &lt;code&gt;energy_uj&lt;/code&gt; y ningún &lt;code&gt;constraint_*&lt;/code&gt;, y la jerarquía &lt;code&gt;package-0&lt;/code&gt;/&lt;code&gt;core&lt;/code&gt;: los comandos &lt;code&gt;cat&lt;/code&gt;/&lt;code&gt;ls&lt;/code&gt; sobre &lt;code&gt;/sys/class/powercap/&lt;/code&gt; que están en el cuerpo. El driver (&lt;code&gt;amd-pstate-epp&lt;/code&gt;) y las palancas de política (EPP, &lt;code&gt;platform_profile&lt;/code&gt;) se leen read-only de &lt;code&gt;/sys/devices/system/cpu/cpufreq/&lt;/code&gt; y &lt;code&gt;/sys/firmware/acpi/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Que el firmware sostiene la frecuencia sin intervención: baseline y stress de 20 minutos, reproducibles con &lt;code&gt;stress-ng --cpu 0&lt;/code&gt; y la lectura de &lt;code&gt;Tctl&lt;/code&gt; (&lt;code&gt;k10temp&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;</description><category>amd-pstate</category><category>monitoreo</category><category>power-management</category><category>sysadmin</category><guid>https://sergiobelkin.com/posts/intel-amd-control-temperatura-frecuencia/</guid><pubDate>Tue, 23 Jun 2026 04:03:53 GMT</pubDate></item><item><title>Gestión térmica en notebook clamshell con RAPL y tuned</title><link>https://sergiobelkin.com/posts/gestion-termica-clamshell-rapl-tuned/</link><dc:creator>sebelk</dc:creator><description>&lt;p&gt;Tapa cerrada, monitor portátil apoyado encima, notebook como CPU box debajo de todo: lo que se llama modo &lt;em&gt;clamshell&lt;/em&gt; —la notebook cerrada como una almeja, usada solo como unidad de cómputo con monitor externo—. El objetivo: evitar que suba la temperatura dañando el hardware.&lt;/p&gt;
&lt;h3 id="el-problema-brevemente"&gt;El problema, brevemente&lt;/h3&gt;
&lt;p&gt;Los notebooks toman aire por abajo y/o expulsan calor por arriba del teclado. Un monitor portátil apoyado en clamshell rompe ese flujo. Como no se puede recuperar la disipación sin tocar hardware, lo que queda es &lt;strong&gt;bajar voluntariamente el techo de potencia&lt;/strong&gt; para que el CPU jamás llegue a temperaturas de throttling.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Mejor 12W tibios sostenidos que un loop entre 28W ardiendo y 5W throttleado.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Eso es todo. El resto del post es la pelea para implementarlo en Fedora 43 (el setup no cambió en Fedora 44).&lt;/p&gt;
&lt;h3 id="las-tres-palancas"&gt;Las tres palancas&lt;/h3&gt;
&lt;p&gt;Linux expone tres puntos donde tocar, y cada uno opera en un plano distinto del sistema:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;RAPL&lt;/strong&gt; (&lt;em&gt;Running Average Power Limit&lt;/em&gt;). El CPU Intel se autoimpone límites de potencia: PL1 sostenido, PL2 boost. Están en &lt;code&gt;/sys/class/powercap/intel-rapl/&lt;/code&gt;. Si los bajás, el CPU físicamente no puede consumir más. Es el techo duro, aplicado por el hardware del procesador (el PCU, &lt;em&gt;Power Control Unit&lt;/em&gt;): no depende ni del scheduler ni del usuario.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;tuned&lt;/strong&gt;. Daemon de gestión de perfiles de energía. Desde Fedora 41 es el default del sistema (vía &lt;code&gt;tuned-ppd&lt;/code&gt;), reemplazando a &lt;code&gt;power-profiles-daemon&lt;/code&gt;. Maneja governor, EPP, runtime PM, sysctls, sysfs. &lt;em&gt;No baja literalmente el consumo: configura los subsistemas del kernel para que ellos lo hagan&lt;/em&gt;. Opera en el plano de las políticas, no del hardware — por eso no se solapa con RAPL.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;thermald&lt;/strong&gt;. Reactivo: lee zonas térmicas y aplica medidas correctivas cuando se calienta. En este equipo nunca funcionó, y de eso también va el post.&lt;/p&gt;
&lt;h3 id="rapl-primer-round"&gt;RAPL, primer round&lt;/h3&gt;
&lt;p&gt;Bajar PL1 a 12W y PL2 a 20W es un &lt;code&gt;echo&lt;/code&gt; a un archivo en &lt;code&gt;/sys/&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12000000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tee&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;powercap&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;intel&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rapl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;constraint_0_power_limit_uw&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Tres segundos, listo. Después de verificar que el valor quedó aplicado y que las temperaturas en stress test caían a una zona razonable, vino la primera trampa con la que choco cada tanto y siempre me tomo unos minutos para acordarme:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;/sys&lt;/code&gt; no persiste. Lo que escribís ahí desaparece al reboot.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Solución: un service unit propio (&lt;code&gt;rapl-limits.service&lt;/code&gt;) que reaplica los valores al boot. Heredoc, &lt;code&gt;daemon-reload&lt;/code&gt;, &lt;code&gt;enable --now&lt;/code&gt;. Hecho.&lt;/p&gt;
&lt;h3 id="thermald-el-daemon-zombi"&gt;thermald, el daemon zombi&lt;/h3&gt;
&lt;p&gt;Acá viene la parte que me costó descubrir.&lt;/p&gt;
&lt;p&gt;Habilito &lt;code&gt;thermald&lt;/code&gt;, escribo un &lt;code&gt;/etc/thermald/thermal-conf.xml&lt;/code&gt; custom, lo arranco. &lt;code&gt;systemctl status&lt;/code&gt; lo reporta activo. &lt;code&gt;ps -ef | grep thermald&lt;/code&gt; muestra el proceso vivo. Todo bien.&lt;/p&gt;
&lt;p&gt;Solo que no estaba haciendo absolutamente nada.&lt;/p&gt;
&lt;p&gt;Días después, ya con el sistema funcionando bien y con thermald deshabilitado por sospechoso, abro &lt;code&gt;journalctl -u thermald&lt;/code&gt; para confirmar la sospecha. Encuentro esto, mezclado entre los logs:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nx"&gt;thermald&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1010&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Thermal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;No&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;coretemp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sysfs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;found&lt;/span&gt;
&lt;span class="nx"&gt;thermald&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1010&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Thermal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;DTS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;hwmon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;No&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Zones&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;present&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Need&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;configure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;manually&lt;/span&gt;
&lt;span class="nx"&gt;thermald&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1010&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;XML&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;zone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;invalid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sensor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;x86_pkg_temp&lt;/span&gt;
&lt;span class="nx"&gt;thermald&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1010&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Zone&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;unable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Una sola causa raíz, dos síntomas en el log:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;No había un sensor térmico del CPU que descubrir.&lt;/strong&gt; El módulo que expone la temperatura de paquete no estaba cargado (&lt;code&gt;No coretemp sysfs found&lt;/code&gt;), así que thermald arrancó sin ninguna zona del CPU a la vista. Lo venía diciendo desde el primer boot del histórico, mucho antes de que yo empezara a tocar nada.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;El &lt;code&gt;invalid sensor type x86_pkg_temp&lt;/code&gt; no significa lo que parece.&lt;/strong&gt; &lt;code&gt;x86_pkg_temp&lt;/code&gt; es el nombre correcto del sensor de paquete; thermald no lo rechaza por schema. Resuelve el tipo en runtime contra los sensores que efectivamente descubrió, y como no había ninguno, la búsqueda volvió vacía y el bind falló. El mensaje dice "invalid type" pero quiere decir "no encontré un sensor de ese tipo en este sistema".&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Resultado: el daemon arrancaba, intentaba bindear las zonas definidas en el XML, no encontraba el sensor, y se quedaba corriendo sin nada que monitorear. Vivo, ocupando memoria, sin función.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;systemctl status&lt;/code&gt; te dice si systemd cree que el servicio está bien. No te dice si el servicio está haciendo lo que tiene que hacer. Para eso está &lt;code&gt;journalctl&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="validacion-empirica"&gt;Validación empírica&lt;/h3&gt;
&lt;p&gt;Antes de tomar la decisión final de desactivar thermald, corrí un baseline de 6 minutos midiendo Package temp y frecuencia, después un stress test de 6 minutos exactos midiendo lo mismo, y los comparé. Lo que vi fue lo que esperaba: con RAPL fijo en 12W y &lt;code&gt;tuned&lt;/code&gt; manejando el resto en su profile balanced, las temperaturas se mantenían en una zona estable y la frecuencia se sostenía sin las caídas abruptas del clamshell sin tunear.&lt;/p&gt;
&lt;p&gt;La pregunta que la medición respondía no era &lt;em&gt;"¿thermald aporta?"&lt;/em&gt; — eso ya estaba contestado de antemano por los logs. Era la otra: &lt;em&gt;"¿con solo RAPL+tuned alcanza para clamshell?"&lt;/em&gt;. La respuesta fue sí, y eso permitió cerrar el setup con tranquilidad.&lt;/p&gt;
&lt;h3 id="estado-final"&gt;Estado final&lt;/h3&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;tuned                 → active (profile balanced)
RAPL PL1=12W PL2=20W  → fijo vía rapl-limits.service
thermald              → disabled (no podía operar en este hardware)
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Filosofía: &lt;strong&gt;un techo duro de potencia (RAPL), un orquestador de estado (tuned), nada reactivo encima&lt;/strong&gt;. Tres piezas, ninguna pelea con la otra, todas debuggeables.&lt;/p&gt;
&lt;h3 id="una-nota-sobre-como-empece"&gt;Una nota sobre cómo empecé&lt;/h3&gt;
&lt;p&gt;Originalmente armé el setup con &lt;code&gt;tlp&lt;/code&gt; + RAPL, siguiendo una sugerencia de Claude (vía claude.ai) que asumía &lt;code&gt;power-profiles-daemon&lt;/code&gt; como el daemon por defecto en Fedora. No contrasté la premisa. Cuando fui a verificarla, descubrí que desde Fedora 41 el default pasó a &lt;code&gt;tuned&lt;/code&gt; (vía &lt;code&gt;tuned-ppd&lt;/code&gt;), no PPD. Y para este escenario — clamshell estático, siempre AC, sin diferenciar AC/BAT, sin que &lt;code&gt;tlp-rdw&lt;/code&gt; aporte nada — &lt;code&gt;tlp&lt;/code&gt; no resolvía nada que &lt;code&gt;tuned&lt;/code&gt; no resuelva. Migré. El post documenta el setup resultante, no el camino original.&lt;/p&gt;
&lt;p&gt;La lección no es "no preguntarle a una IA". Es &lt;strong&gt;verificar la premisa que la IA está usando, no solo la recomendación que te entrega&lt;/strong&gt;. Un asistente puede recomendar una herramienta correctamente &lt;em&gt;condicional a&lt;/em&gt; un default que ya no es el actual; sin contrastar esa premisa, terminás con un setup más complicado del necesario.&lt;/p&gt;
&lt;h3 id="lo-que-me-llevo"&gt;Lo que me llevo&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Un daemon puede estar "running" y no estar haciendo nada. La verdad está en los logs de aplicación, no en &lt;code&gt;systemctl status&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Un unit file propio de pocas líneas a veces es la decisión correcta y que no requiere demasiado esfuerzo.&lt;/li&gt;
&lt;li&gt;El consejo técnico de una IA puede ser internamente coherente y aún así basarse en premisas obsoletas (defaults, versiones, comandos). El costo de chequear la premisa antes de implementar es bajo; el costo de no hacerlo se paga cada vez que volvés a tocar el equipo.&lt;/li&gt;
&lt;/ul&gt;</description><category>monitoreo</category><category>power-management</category><category>sysadmin</category><guid>https://sergiobelkin.com/posts/gestion-termica-clamshell-rapl-tuned/</guid><pubDate>Sat, 30 May 2026 22:56:08 GMT</pubDate></item></channel></rss>