Read performance mode, fan speeds, and temperatures from the Corsair AI Workstation 300 on Linux — directly from ACPI MMIO, no kernel module required.
Status: Working on Bazzite 40+ / Fedora Atomic · KDE Plasma 6 · AMD Strix Halo
- Reports the current performance mode (Balanced / Max / Quiet) as set by Corsair iCUE on Windows or the hardware Fn keys
- Reads live fan speeds in RPM for both chassis fans (correctly shows off when fans stop at idle)
- Reads CPU and GPU temperatures and EC-reported power draw from the embedded controller
- Provides a KDE Plasma 6 panel widget — mode name (color-coded) plus fan RPMs, no sudo at runtime
The Corsair AI Workstation 300 exposes a custom ACPI region named ERAX at physical address 0xFEC40400. It is declared as a SystemMemory operation region in the machine's DSDT and is read/written by the Corsair WMI ACPI driver (WMAA) to communicate mode changes and sensor data between firmware and iCUE on Windows.
On Linux, we map this region directly through /dev/mem using Python's mmap. Decompiling the DSDT with iasl revealed the field names and byte offsets for mode, fans, and temperatures — confirmed by cross-referencing against live readings at known mode states.
Note:
/dev/memaccess is gated byCONFIG_STRICT_DEVMEM. Bazzite and Fedora ship with strict devmem enabled, but theERAXregion at0xFEC40400falls outside the protected range and is readable without patching the kernel.
| File | Description |
|---|---|
corsair-status-writer.py |
Daemon. Reads ERAX every second, writes /run/corsair-status (JSON). Run as root via systemd. |
corsair-mode.py |
One-shot or live mode watcher. Reads FCMO at ERAX+0x31 directly. Requires sudo. |
corsair-power.py |
Full live monitor: mode + fans + EC temps + EC power + RAPL cross-check, 1s samples. Requires sudo. |
corsair-monitor.service |
Systemd unit for the daemon. |
plasmoid/com.user.corsair-monitor/ |
KDE Plasma 6 widget source. Reads /run/corsair-status — no sudo at runtime. |
- Python 3 (stdlib only — no pip installs)
acpica-toolsif you want to re-derive the offsets:sudo dnf install acpica-tools- Bazzite 40+ or Fedora Atomic with kernel 6.11+ (other distros likely work if
/dev/memis accessible)
git clone https://github.com/bhill00/corsair300ai-bazzite-widget.git
cd corsair300ai-bazzite-widget
sudo cp corsair-status-writer.py /usr/local/bin/corsair-status-writer.pysudo cp corsair-monitor.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now corsair-monitor.service
sudo systemctl status corsair-monitor.servicecat /run/corsair-status
# {"mode":"Balanced","mode_raw":0,"fan1":1250,"fan2":1260,"cput":45,"gput":38}# Check the current performance mode
sudo python3 corsair-mode.py
# Watch for mode changes in real time
sudo python3 corsair-mode.py --watch
# Full live power and thermal table
sudo python3 corsair-power.pyThe widget reads /run/corsair-status via a Plasma5Support executable DataSource. No elevated privileges needed after the daemon is running.
mkdir -p ~/.local/share/plasma/plasmoids/
cp -r plasmoid/com.user.corsair-monitor ~/.local/share/plasma/plasmoids/
# Restart the shell to register the widget
plasmashell --replace &Then: right-click panel → Add or Manage Widgets → search Corsair → drag to panel.
The compact view shows mode name (color-coded) and fan1/fan2 RPM. Click to expand for CPU temperature.
Physical base: 0xFEC40400. Offsets derived from DSDT decompile (iasl -d dsdt.dat).
To extract your own DSDT:
sudo cat /sys/firmware/acpi/tables/DSDT > dsdt.dat
iasl -d dsdt.dat| DSDT name | Offset | Size | Description |
|---|---|---|---|
FCMO |
0x31 |
1 byte | Current performance mode |
FN1L |
0x35 |
1 byte | Fan 1 high byte |
FN1H |
0x36 |
1 byte | Fan 1 low byte — RPM = `(FN1L<<8) |
FN2L |
0x37 |
1 byte | Fan 2 high byte |
FN2H |
0x38 |
1 byte | Fan 2 low byte — RPM = `(FN2L<<8) |
CPUT |
0x70 |
1 byte | CPU temperature (°C) |
GPUT |
0x71 |
1 byte | GPU temperature (°C, 0 when idle) |
CPAD |
0x72 |
1 byte | EC-reported CPU power (W) |
GPAD |
0x73 |
1 byte | EC-reported GPU power (W) |
| FCMO | Mode | Approx. TDP | Fan behavior |
|---|---|---|---|
0 |
Balanced | ~85 W | Stop-on-idle; spin up under load |
1 |
Max | ~120 W | Always spinning |
2 |
Quiet | ~55 W | Stop-on-idle; aggressive fan-stop threshold |
3 |
Super | TBD | Present in DSDT; not yet characterized |
Mode is set by iCUE on Windows and persists across reboots. These scripts are read-only — they never write to ERAX.
EC power double-counting: On AMD Strix Halo, the CPU complex and integrated GPU share a single die. The sum of CPAD + GPAD will often exceed actual package power. Cross-check with RAPL (/sys/class/powercap/amd_energy/ or the amd_energy kernel module).
Fan stop at idle: In Balanced and Quiet modes, both fans stop completely at idle. fan1 and fan2 reading 0 is normal, not a sensor error.
Portability: The ERAX base address and byte offsets are specific to the Corsair AI Workstation 300. They are unlikely to apply to other Corsair products without re-deriving from that machine's DSDT.
The WMI GUID and ACPI method structure were identified by examining the DSDT. The ERAX field mappings were discovered by correlating DSDT field definitions with live memory readings taken while switching modes on Windows and observing which bytes changed.
There is no upstream Linux kernel driver for this hardware. This is a read-only userspace approach — it cannot change performance modes or modify firmware state.
- pettijohn/corsair-ai-workstation-performance-level-linux — earlier Linux work on this hardware; useful reference for WMI GUID identification.
GPL-2.0-or-later
