SystemIO conflicts are not firmware bugs
Recorded: Sept. 12, 2026, 12:09 p.m.
| Original | Summarized |
SystemIO conflicts are not firmware bugs Matthew Garrett's Blog Home Archives Search Links RSS Dark Mode SystemIO conflicts are not firmware bugs Sep 09, 2026 6 minute read I’m looking at something entirely unrelated, but tripped over some search results that made me realise that a lot of people still think getting errors like ACPI Warning: SystemIO range 0x0000000000001828-0x000000000000182F conflicts with OpRegion 0x0000000000001800-0x000000000000187F indicate a firmware bug. This is generally untrue. We need to dive a little into what ACPI is to clarify why. 1 OperationRegion(OPR1, SystemIO, 0x400, 0x2) This defines an operation region called “OPR1” at IO port 0x400, 2 bytes long. Inside it are two 8-bit fields, INDX and DATA. These are to be accessed one at a time, do not need the ACPI interpreter to take a global lock when accessing them, and if a subset of the register is modified then the other values should be preserved (irrelevant in this case since the fields are only a byte wide). Now any references to INDX or DATA in this scope will trigger accesses to those registers. So, a method to read the value of register 0x03 would look something like: 1 Method (RD03) { ie, set INDX to 3, and then read the value of DATA and return it. But! What if another ACPI method is running at the same time? Let’s say we have one that writes to register 0x05: 1 Method (WR05, 1) { What happens if RD03 executes while we’re part-way through WR05? INDX might get reset to 0x03, and now WR05 will modify register 0x03 instead of 0x05. Oh no! But we can avoid this - we declare a mutex (Mutex (MUTX, 0x00)), and update our methods to be something like: 1 Method (RD03) { Method (WR05, 1) { Each method takes a lock (waiting up to 0xffff milliseconds and then erroring out if it doesn’t), and performs the access. There’s now no chance of a race. Phew! 1 Device (HDW1) Method (WR05, 1) { which defines an ACPI device and associated methods. The _HID field defines the device type, and a Linux driver can be written that will be automatically loaded if a device with type VEND0001 is seen. That driver can then call ACPI methods associated with the device and access the resources in a way that matches the firmware’s expectations. The ACPI spec used to live at acpi.info, but sadly that seems to have vanished some time after UEFI took over stewardship of the spec ↩︎ You might argue that the firmware should simply not do anything at runtime because it is not the firmware’s job to do that, and I do understand that and you can certainly boot with acpi=off if you want to and no ACPI code will be executed at runtime. Let me know how that goes. ↩︎ I’m not going to present an opinion on that here, merely say that this provides no supporting evidence for that assertion ↩︎ © Built with Hugo |
SystemIO conflicts are not considered firmware bugs. The author argues against the common assumption that errors, such as ACPI warnings about SystemIO range conflicts, necessarily indicate a firmware defect. To understand this, the text delves into the design philosophy of the Advanced Configuration and Power Interface (ACPI) specification and how it contrasts with embedded approaches to hardware abstraction. While ACPI structures information by distributing it as executable code, such as the ACPI Source Language, which is compiled into bytecode interpreted by the operating system, embedded systems typically bake this knowledge directly into the operating system, as seen in Devicetree. ACPI utilizes Operation Regions to structure definitions that describe access to underlying hardware. This mechanism involves defining access to device registers through indexes and data fields. The text illustrates how these regions define specific memory areas and the fields within them, specifying that some accesses can occur without requiring a global lock, and that modifications to a subset of a register should preserve other values. To manage concurrent access and prevent race conditions between different ACPI methods, the specification incorporates mutexes. Methods are required to acquire a lock before performing access to shared resources and release it afterward, ensuring sequential execution and preventing inconsistencies. A conflict scenario arises when a native hardware driver interacts directly with hardware registers without being aware of the ACPI methods. This direct interaction leaves the driver vulnerable to racing against ACPI execution paths, which could lead to incorrect data reads—for example, reading a status flag instead of an actual sensor reading, potentially resulting in catastrophic errors like thermal shutdowns. The kernel mitigates this risk by detecting these potential conflicts, such as a driver attempting to access an address claimed by an ACPI operation region. When such a conflict is detected, the kernel blocks the driver execution and issues a warning, indicating the conflict and suggesting the use of available ACPI drivers instead of native ones. The ACPI structure itself defines devices and their associated methods, which provide a framework for drivers to interact with the hardware in a structured manner. For instance, a device definition specifies an OperationRegion, method definitions, and mutexes. This structure allows a Linux driver to be automatically loaded if the hardware matches a specified type, enabling the driver to call these ACPI methods to access resources in a way that aligns with the firmware’s expectations. Although the author notes that running ACPI code is optional and that the firmware itself is not strictly at fault, attempting to load native drivers without acknowledging the ACPI structure can result in unpredictable and potentially dangerous system states, which the operating system is designed to guard against. |