Whole file
erpalma/throttled
The author described this change as “daemon: fix MSR field encoding edge cases”. It counts as a record because the checks below fail on the code as it stood at c8ec04706 and pass on 72b148e2b, with nothing else changed between the two runs.
Projecterpalma/throttled
Fix saved2026-07-23
Sharing licenceMIT · LICENSE
Change size+12 −2
What the code was meant to do, written into the code itself as a save note
daemon: fix MSR field encoding edge cases
The change
| 532 | 532 | def calc_undervolt_mv(msr_value): | |
| 533 | 533 | """Return the offset voltage (in mV) from the given raw MSR 150h value.""" | |
| 534 | 534 | offset = (msr_value & 0xFFE00000) >> 21 | |
| 535 | - | offset = offset if offset <= 0x400 else -(0x800 - offset) | |
| 535 | + | # 11-bit two's complement: values >= 0x400 are negative | |
| 536 | + | offset = offset if offset < 0x400 else -(0x800 - offset) | |
| 536 | 537 | return int(round(offset / 1.024)) | |
| 537 | 538 | ||
| 538 | 539 | ||
| ⋯ | |||
| 573 | 574 | """Return the value to be written in the MSR 150h for setting the given | |
| 574 | 575 | IccMax (in A) to the given current plane. | |
| 575 | 576 | """ | |
| 576 | - | assert 0 < current <= 0x3FF | |
| 577 | + | # the MSR field is 10 bits of 1/4 A steps: max 0x3FF / 4 = 255.75 A | |
| 578 | + | assert 0 < current <= 0x3FF / 4 | |
| 577 | 579 | assert plane in CURRENT_PLANES | |
| 578 | 580 | current = int(round(current * 4)) | |
| 579 | 581 | return 0x8000001700000000 | (CURRENT_PLANES[plane] << 40) | current | |
| ⋯ | |||
| 738 | 740 | ) | |
| 739 | 741 | Trip_Temp_C = valid_trip_temp | |
| 740 | 742 | trip_offset = int(round(critical_temp - Trip_Temp_C)) | |
| 743 | + | if trip_offset > 63: | |
| 744 | + | # the offset field is 6 bits wide: a larger value would | |
| 745 | + | # spill into adjacent bits and corrupt the register | |
| 746 | + | log( | |
| 747 | + | f'[!] Overriding "Trip_Temp_C" in "{power_source:s}": offset {trip_offset:d} ' | |
| 748 | + | f'exceeds the 6-bit MSR field, clamping to {critical_temp - 63:d} C' | |
| 749 | + | ) | |
| 750 | + | trip_offset = 63 | |
| 741 | 751 | regs[power_source]['MSR_TEMPERATURE_TARGET'] = trip_offset << 24 | |
| 742 | 752 | else: | |
| 743 | 753 | log(f'[I] {power_source:s} trip temperature is disabled in config.') | |
The check that tells the two apart
fail→pass·tests/test_msr_encoding.py::MsrEncodingTests::test_icc_max_encoder_rejects_values_that_overflow_ten_bits
fail→pass·tests/test_msr_encoding.py::MsrEncodingTests::test_trip_offset_is_clamped_to_the_six_bit_msr_field
fail→pass·tests/test_msr_encoding.py::MsrEncodingTests::test_undervolt_decode_handles_the_sign_boundary
Check file tests/test_msr_encoding.py, taken without changes from the fix and copied onto the older code, so the exact same check runs against both versions.
Origin and history
The code before itc8ec0470697b81426a6e96f15e0c55d5757afcc8
Broken version dated2026-06-07
Modulethrottled
Units changedcalc_icc_max_msr, calc_reg_values, calc_undervolt_mv
Fingerprint78ab6ed41ab2bba9
Checked2026-08-18 by goldset/0.1
Every field above is generated by our program. None of it is written by hand.