PB PenguinBurner
PenguinBurner engineering research · 11 August 2026

AMD RDNA undervolting on Linux: what exists, what we can hack, and what we can visualize

Source-level analysis of Linux 7.1.5–7.1.8, 7.2-rc7, current public AMD DRM trees, and the path toward a single PenguinBurner tuning model for AMD and NVIDIA. RX 9060 and RX 9070 are the primary target. RDNA3 follows for the six-boundary experiment; RDNA2 remains a useful stock global-offset backend without the six-boundary claim.

Primary sources only No RX 9070 hardware result claimed Experimental kernel patch clearly separated
1
supported voltage control

Modern AMDGPU exposes one signed millivolt offset for the whole firmware-managed V/F curve.

6
internal boundary-offset slots

SMU13/14 carry six offsets around five PWL zones, but stock Linux broadcasts one value to all six.

0
returned base-curve points

No modern AMDGPU getter enumerates the hidden V/F curve. We can sample its operating response instead.

Bottom line

Modern RDNA support is viable, but it is a different control model from NVIDIA. The shared product should be built around capabilities and typed tuning plans—not around a universal editable curve.

CapabilityNVIDIA in PenguinBurnerAMD stock 7.1.8AMD SMU14 experiment
Enumerate editable V/F binsYesNoNo
Independent voltage-shape controlMany frequency offsets at voltage binsNoSix coarse boundary offsets, if PMFW accepts them
Whole-curve voltage offsetNot the current NVIDIA modelvo NKeep vo N compatible
Observe current voltage/frequencyYesYes when board/firmware exports the metricsSame telemetry
Read six boundary offsetsNot applicableOnly element zero is reportedPatch can report all six
Read hidden base curveHidden NVAPI pathNo public getterStill no base-curve getter
Terminology: the six SMU values are signed voltage offsets at region boundaries. They are not six absolute (frequency, voltage) coordinates. Exposing them would produce a coarse curve-shaping control, not NVIDIA-style editing of dozens of bins.
Why NVIDIA is not a fixed-offset scan: PenguinBurner's recorded RTX 5080 fixture contains 78 editable voltage bins spanning 760–1240 mV. The NVIDIA plan can assign a different frequency offset to each bin and reshape or flatten the high-voltage tail. “100+ points” is not universal—the observed 5080 example has 78—but it is still fundamentally richer than AMD's one global scalar. The shared interface must preserve that distinction.

Scope by generation

TargetSupported stock planSix-boundary experimentPenguinBurner scope
RDNA2 / inspected SMU11 pathsGlobal vo where the live ABI exposes itNo six-slot table found on the relevant pathSimple global-offset support only
RDNA3 / inspected SMU13.0.0 and 13.0.7 pathsGlobal voSix slots exist; investigate after RDNA4Stock support plus later experimental qualification
RDNA4 / SMU14.0.2 and 14.0.3Global voSix slots exist; first patch and hardware targetPrimary RX 9060/9070 target

Marketing generation is not the dispatch key. PenguinBurner must inspect the selected card's live tokens and ranges, then advertise GLOBAL_VOLTAGE_OFFSET or the explicitly patched ZONE_BOUNDARY_OFFSETS capability. This keeps RDNA2 inside the same adapter without forcing it into the RDNA3/4 experiment.

Exactly what Linux 7.1.8 can do on modern AMD

This is the stock-kernel implementation target. Every item must be capability-probed on the selected PCI device; board firmware and the OverDrive feature mask remain authoritative.

1. Global voltage offset—the supported path

Confirmed upstream The documented pp_od_clk_voltage command is vo <offset_mv>. AMDGPU describes it as an extra offset applied to the whole V/F curve. The generic parser sends one PP_OD_EDIT_VDDGFX_OFFSET value; the SMU13 and SMU14 handlers copy it into every internal boundary slot. Linux 7.1.8 therefore provides one scalar—not per-point control.

# Schematic sequence; exact card path and emitted range must be discovered.
write power_dpm_force_performance_level: manual
write pp_od_clk_voltage: vo <signed millivolts inside VDDGFX_OFFSET range>
write pp_od_clk_voltage: c
read  pp_od_clk_voltage                 # verify committed state

# Restore OverDrive state:
write pp_od_clk_voltage: r
write pp_od_clk_voltage: c
restore the performance-level policy captured before the transaction

PenguinBurner can scan progressively more-negative values, but it must use the card's reported range and read back every commit. Fixed presets such as −50/−100/−150 mV can be search seeds, never assumed-safe universal values. A crash-safe baseline, rollback, and final verification are mandatory.

Stock-kernel preconditions: pp_od_clk_voltage is created only when OverDrive is supported and enabled. OverDrive bit 14 is not in the upstream default stable feature mask, so a missing node may reflect the effective amdgpu.ppfeaturemask policy rather than the silicon. The files are root-writable. PenguinBurner should diagnose both conditions, never silently edit boot parameters, and route every write through penguin-burnerd after an explicit user action.

2. Clock, power, fan, and policy controls

Control7.1.8 surfacePractical meaning
Graphics clockpp_od_clk_voltage tokens emitted by the cardSMU backends differ: min/max clocks or an offset. Parse the live output.
Power caphwmon power1_cap, _min, _maxEnough to define lower-power Efficiency and higher-headroom Performance candidates when supported.
Fan controlhwmon PWM and optional gpu_od/fan_curveIndependent capability; never assume every board exposes the firmware curve editor.
DPM policypower_dpm_force_performance_levelManual OverDrive changes require policy coordination and restoration.
RecoveryOverDrive reset; separate GPU recovery machineryUse r + c for normal rollback. A full GPU reset is escalation, not routine restore.

What changed specifically in the 7.1.x stable updates

None of those commits changed PP_OD_EDIT_VDDGFX_OFFSET, the six-slot broadcast, the fan ABI, or added a voltage-curve getter.

3. Telemetry available to an Auto-UV scanner

Confirmed upstream Documented hwmon attributes include GPU voltage in0_input, GFX clock freq1_input, memory clock, temperature, power, fan, and cap limits when the ASIC/firmware supplies them. gpu_busy_percent, mem_busy_percent, and versioned binary gpu_metrics add utilization and a synchronized metrics snapshot. Linux 7.1.8 specifically fixed torn gpu_metrics reads, which is useful for response sampling.

4. Things 7.1.8 does not expose

What 7.2 and newer public trees actually change

None of the inspected changes turn AMD into a per-point curve API. They still matter for a reliable PenguinBurner backend.

TreeTuning-adjacent changesPer-point/per-zone UV?
7.1.5 → 7.1.8 Power-unit correction, atomic gpu_metrics, pp_table safety/APU restriction, UMD state restore, display fixes. No change
7.2-rc7 OD parser/output hardening, corrected SMU14 power-limit range, SMU14.0.2 energy-metric fix, GFX12 queue/reset and display robustness. No change
Post-7.2 AMD DRM / linux-next Queued power-limit accounting and restoration across AC/DC changes, resume, table reload, and reset. No public patch found

RX 9060 uses MP1 14.0.2 and RX 9070/9070 XT uses MP1 14.0.3 in the official hardware table. Both dispatch through the shared smu_v14_0_2 backend, so both get the same scalar-only voltage semantics—and both are good targets for the same carefully gated experiment.

The six-boundary SMU13/14 experiment

The driver is currently the narrowing point on the inspected SMU13/14 paths: the full OverDrive table contains six values, while the public edit path deliberately broadcasts one input and reports only slot zero. Patch SMU14 first for RX 9060/9070; treat SMU13 as a separate follow-up qualification.

What the stock handler does

Confirmed upstream SMU14 defines PP_NUM_RTAVFS_PWL_ZONES = 5 and six VoltageOffsetPerZoneBoundary[] entries. The 7.2-rc7 edit handler loops over all six entries and assigns the same input[0]. Its read path prints only element zero. The 7.1.8 code has the same semantics.

Can we add a six-value setter?

Experiment proposal Yes at the kernel-driver layer. Preserve vo N as the supported broadcast operation, add an explicitly experimental command that accepts exactly six signed values, validate every element against firmware-provided bounds, write the complete OverDrive table, commit, and read it back.

# Existing ABI remains unchanged:
vo -75                       # broadcast -75 mV to B0..B5

# Illustrative private-patch syntax—not an upstream ABI:
voz -20 -30 -45 -60 -75 -85 # independently stage B0..B5
c                            # commit through the normal OD transaction
r                            # reset remains available

The token name voz is intentionally presented as a design placeholder. An upstream RFC should let AMD maintainers choose the ABI. The important properties are atomic six-value input, unchanged legacy behavior, per-slot validation, full readback, and an obvious experimental capability flag.

Can we add a six-value getter?

Experiment proposal Yes. The complete SMU OverDrive table is already retrieved from firmware; the current display function merely selects [0]. A diagnostic patch can emit B0 through B5 after a fresh table read, and the setter can compare requested values with that firmware readback.

# Illustrative patched readback—not present in stock 7.1.8:
OD_VDDGFX_OFFSET_ZONES:
0: <signed mV at B0>
1: <signed mV at B1>
2: <signed mV at B2>
3: <signed mV at B3>
4: <signed mV at B4>
5: <signed mV at B5>
What this getter does not solve: it returns six adjustments, not the stock voltage or frequency at each boundary. Without a documented boundary map or base-curve getter, PenguinBurner must label them B0…B5 and must not draw them at invented MHz/mV coordinates.

What we still have to prove on hardware

Encouraging evidence

  • The firmware table truly carries six independently addressable fields.
  • The full table already crosses the kernel/PMFW boundary.
  • SMU14 declares advanced/full-control fields and an OD curve-offset error code.
  • RX 9060 and RX 9070 share the backend to patch first.

Unknown until an RX 9000 test

  • Whether PMFW accepts unequal offsets or silently normalizes them.
  • Whether a hidden advanced mode is required—and how to enable it safely.
  • Per-slot bounds, interpolation behavior, and persistence across reset/resume.
  • Whether unequal offsets produce stable, useful curve shaping.
Safety boundary: start with an isolated test kernel on RDNA4, a stock recovery kernel, no boot-time application, zeroed slots, and tiny single-slot deltas. Verify firmware readback and exercise idle, load, and rapid transitions before increasing magnitude. Do not blindly toggle undocumented advanced mode fields. This page proposes an experiment; it does not claim the firmware accepts unequal values.

What AMD getters actually offer

Stock modern AMD exposes configured controls and the current operating state—not the full function the firmware uses to choose voltage at every frequency.

QuestionBest sourceAnswer
What voltage offset and OD ranges are configured?pp_od_clk_voltageYes: supported tokens, state, and ranges; modern stock readback shows the scalar.
What clock and voltage is the GPU using now?gpu_metrics or hwmon freq1_input + in0_inputOften, capability-dependent. Metric versions and averaging differ.
What are temperature, power, fan, and utilization now?gpu_metrics, hwmon, busy-percent filesYes when exposed; missing values must remain “unavailable.”
What DPM levels exist/currently apply?pp_dpm_sclk and related filesWhere supported; levels are not an absolute V/F curve.
What are all hidden V/F points?No public modern ABINo.
What are all six internal offsets?Stock display functionNo: only slot zero. A patch can expose all six.
Where are the six boundary frequencies?No documented ABINo safe mapping found.

The internal SMU table also contains droop/PWL coefficients. Their presence suggests a piecewise mathematical curve, not a dense public list of 100+ points. The scaling and relationship to the six offset boundaries are not documented as a userspace ABI, so decoding them would be a separate reverse-engineering project—not something PenguinBurner should silently rely on.

How PenguinBurner can visualize an opaque AMD curve

Call it a measured operating response, not “the firmware V/F curve.” Each dot is something the GPU actually reported while a controlled workload was running.

1 · Apply candidateGlobal offset now; six boundaries only in an experimental kernel.
2 · Exercise statesIdle, light, medium, full load, and rapid transitions.
3 · Sample snapshotsClock, voltage, power, utilization, temperature, throttling, timestamp.
4 · AggregateGroup clock into 25–50 MHz bins; compute median and 10–90% band.
5 · CompareOverlay stock, candidate, tiers, failures, gaps, and sample density.
Schematic UI: measured operating response This is an explanatory drawing, not RX 9070 test data. No numerical results are implied.
Observed GFX frequency → Observed GPU voltage → SCHEMATIC · SAMPLED TELEMETRY
stock median candidate median raw accepted samples 10–90% observed band

Show

  • Faint raw samples, binned median, confidence/dispersion band, and sample count.
  • Stock versus current candidate and final Efficiency/Balanced/Performance overlays.
  • Red markers for throttling, instability, reset, or a failed probe.
  • Gaps where telemetry is missing or sample density is insufficient.
  • A separate six-node offset strip when the patched capability exists.

Never imply

  • That interpolation through samples is the firmware's stored curve.
  • That every frequency has one deterministic voltage independent of temperature and limits.
  • That B0…B5 have known MHz positions before the mapping is proven.
  • That absent voltage metrics equal zero.
  • That a passed workload proves universal stability.

One PenguinBurner interface for AMD and NVIDIA

Use one orchestration contract with a tagged voltage-control payload. Share identity, telemetry, lifecycle, scoring, persistence, rollback, and verification; let candidate construction remain capability-specific.

NVIDIA adapter
  • NVML facts/controls
  • hidden NVAPI V/F snapshot
  • per-bin frequency offsets
Shared GPU tuning contract
  • capabilities + stable device identity
  • telemetry snapshot
  • apply typed plan + readback
  • restore captured baseline
  • run/score/verify candidates
AMDGPU adapter
  • sysfs/hwmon facts
  • global offset now
  • six-boundary offsets only when patched
enum VoltageControl {
    PerPointCurve { points: Vec<VfOffset> },          // NVIDIA
    GlobalOffset { offset_mv: i32 },                  // stock modern AMD
    ZoneBoundaryOffsets { offsets_mv: [i32; 6] },     // patched SMU13/14 only
    None,
}

struct TuningPlan {
    device_id: StablePciIdentity,
    voltage: VoltageControl,
    gfx_clock: Option<ClockControl>,
    memory_clock: Option<ClockControl>,
    power_limit: Option<PowerLimit>,
    fan: Option<FanControl>,
}

trait GpuTuningBackend {
    fn capabilities(&self) -> Capabilities;
    fn telemetry(&self) -> TelemetrySnapshot;
    fn capture_baseline(&self) -> BaselineToken;
    fn apply(&self, plan: &TuningPlan) -> AppliedReadback;
    fn restore(&self, baseline: &BaselineToken) -> AppliedReadback;
}

PenguinBurner design The Rust daemon remains the only privileged writer. AMD sysfs writes, OD commit/reset, fan changes, and recovery belong behind /run/penguin-burnerd.sock, just like NVIDIA mutations. Python and Qt consume typed daemon capabilities; they do not open a second privileged engine.

Do not add an adapter method named simply get_curve() and fabricate AMD points. Instead expose voltage_control.kind, optional editable controls, and a distinct measured-response series. Profiles should persist the tagged plan, PCI identity, kernel/driver/firmware facts, ranges, captured baseline, and verification evidence. A profile is revalidated when capabilities change.

Efficiency, Balanced, and Performance on AMD

The same three product goals remain possible without pretending AMD has NVIDIA's curve editor. PenguinBurner searches the controls the card actually exposes.

TierGlobal voltage strategyClock/power strategySelection target
EfficiencyMost-negative verified stable scalar offsetLower power cap and, where supported, lower clock target/offsetBest performance per watt subject to a performance floor
BalancedModerate verified negative offsetNear-stock clocks and a moderate capMeaningful power/temperature reduction with little performance loss
PerformanceMild negative or zero offset, whichever remains stablePositive GFX control and/or higher permitted power capHighest verified throughput inside thermal and power guardrails

Yes, Performance can push clocks and power upward if the card exposes those controls. Efficiency can push them downward. A negative voltage offset does not itself lock an exact voltage; firmware continues choosing the operating point. Search candidates should therefore be explicit tuples such as {offset_mv, gfx_control, power_limit}, scored using measured output, energy, temperature, throttling, and stability.

What can be shared with NVIDIA: workload management, crash markers, progressive search, telemetry capture, scoring, persistence, final verification, tier selection, and adaptive runtime switching. What must differ: candidate identity and generation. NVIDIA reshapes/flattens bins; stock AMD shifts the firmware curve globally; experimental AMD may shape six boundaries.

How to take the six-boundary idea upstream

First prove that PMFW accepts unequal values on RX 9060/9070. Then turn the evidence into a narrow RFC rather than asking upstream to accept an untested UI concept.

  1. Build the private SMU14 diagnostic patch with legacy scalar behavior, atomic six-value set, six-value get, validation, reset, and readback logs.
  2. Capture exact board, VBIOS, PMFW, kernel commit, OD ranges, accepted/rejected arrays, runtime telemetry, transition tests, reset/resume behavior, and recovery.
  3. Document the missing contract questions: slot bounds, interpolation, boundary mapping, advanced-mode requirements, and long-term ABI.
  4. Open a focused request in the DRM/AMD project, linking the evidence and PenguinBurner Discussion #43.
  5. Send the RFC/patch to amd-gfx and the current AMD PowerPlay/SWSMU and AMDGPU maintainers listed in the kernel MAINTAINERS file.

No matching public patch series or announced roadmap exposing independent VoltageOffsetPerZoneBoundary[] values was found in mainline, drm-next, AMD staging, linux-next, or the searched public patch queue as of the research date. That is absence of public evidence—not proof AMD will never support it.

Primary sources

Claims above were checked against project documentation and source, not forum recipes.

Validation status: conclusions about exposed APIs are source-level findings. No RX 9060 or RX 9070 was exercised for this report. Usable offset ranges, telemetry quality, PMFW handling of unequal boundary offsets, stability, reset behavior, and performance must be measured on real hardware.