VIA was always an underdog of the x86 CPU market, having only a fractional market share, mainly due to non-competitive performance and multiple other reasons. Despite that they had a unique niche and their small CPU design company – Centaur Technology, was closed just few years ago, however, their legacy still lives on with the Chinese Zhaoxin company, which evolves their design and uses Centaur CPU ID. I had been using VIA solutions since 2008, when I bought their unique VT310-DP motherboard. To my knowledge, it is the only known commercial Mini-ITX form-factor motherboard having two physical x86 CPUs (not cores). It was also used as a NetBSD NAS server for a while and sparked my first bug report on which I spent a lot of time debugging. It also led to a fix with the help of NetBSD developers and was caused by specific CPU functionality. This success eventually was a strong push for me to work more on NetBSD development in general. However, this story is not about this board or my NetBSD development history, but about another VIA specific issues I have recently encountered.
The story started from viac7temp(4) driver, which was being attached on VIA Nano CPUs but reporting 0s instead. The driver’s original implementation was using documented Fn_C0000002 CPUID instruction to retrieve CPU temperature from EDX register, thus the assumption was that it didn’t work with newer Nano models. I peeked at the Linux implementation and it was using MSRs (model-specific registers) instead, partially confirming my suspicion, since VIA Nano had a different MSR than C7 models. Unfortunately, those MSRs are not documented in any public datasheets available (Nano datasheets are not available at all). After some discussions I decided to rewrite our driver to use these MSRs as well, and the boost to finish my work came pretty quickly as one person hit the same issue on his VIA Nano based board. I have acquired an old Biostar Viotech 3100+ motherboard based on C7-D CPU to complement my Nano based systems and compare values between MSR and CPUID instruction. However, upon arrival temperature driver was also reporting 0s for C7-D CPU, even if MSR register worked. Unfortunately, my call for testing didn’t receive any responses, I was left guessing, if it was my specific CPU issue or some driver problem. Because of this, I was unable to compare CPUID instruction and MSR values but was able to make the decision easier to switch to MSR implementation. The final commit is shown in the link.
Typically the story would finish with that, but Biostar motherboard had some booting issues, which appeared to be related to BIOS ACPI settings and specific to the install image (or more likely to the bootloader used by it). I decided to spend some time investigating it and tested older NetBSD releases as a result, reaching 6.x release, where temperature driver reported correct value, proving that documented CPUID instruction should work! And here my hunch was telling me it may be related to the rosenbridge backdoor reported back in 2018. The backdoor was related to a so called Alternate Instruction Set (AIS) which could have been enabled and used in VIA C3 CPUs and were created for internal purposes (testing, debugging, etc). Their ability to bypass certain protection mechanisms were documented by VIA itself, and the backdoor took an advantage of them to gain unintended privileged access. It appeared that some models had it enabled by default from the factory, was it as a mistake or some other reasons. NetBSD development team introduced a quick fix to disable it explicitly to all VIA CPUs (among other bugs), which seemed to be an OK decision to do. Back in a day I tested few systems but found nothing unusual at first glance. That wasn’t the case though…
In order to test my theory, I commented out the line which was explicitly disabling the ATLINST mode and returned an older viac7temp temperature driver code, using CPUID instruction for testing and my theory appeared to be correct. CPUID instruction started to report value again! Fortunately, ALTSINST documentation is available in the internet these days which allowed me quickly to understand what may have been happening. ALTINST mode is available only in VIA C3 models, and only latest ones (Nehemiah) exposed an ability to check if they are enabled or supported at all. The NetBSD code was disabling it for all VIA models including C7, Nano and even current Zhaoxin models. Moreover, it was checking ACE (proprietary VIA advanced cryptography engine) flag to make a decision if instructions should be explicitly disabled. These are available in most VIA models after Nehemiah C5P, but not for earlier C3 models (Samuel, Samuel 2, Ezra, Nehemiah C5XL). The documentation was stating that alternate instruction set should not be attempted to enable on unsupported CPUs and could cause undocumented side effects, whose would depend on CPU model and revision! It appeared that temperature sensor for VIA C7 was exactly one of those side effects. Another one I noticed later with cpuctl identify <cpuindex>
command, which was reporting less CPU features than expected. And this issue was affecting not only VIA C7, but later Nano models and even Nehemiah based Eden-N CPU, which was reporting that ALTINST mode is not supported by this CPU. Thus, I rewrote the code to disable alternate instruction set only if it is enabled and supported for C5P CPUs and for earlier I kept it explicit (those were not covered before). The final changes can be observed here. I don’t have early C3 systems and those can theoretically still have side effects on certain models, but at least they are pretty limited to the subset of the oldest models only. If you have any of these and see unusual behavior, bugs reports are welcome!
It was quite an unexpected turn of events for me but the moral of the story is that datasheets are important and sometimes broken functionality can escape the eyes for years. In the end, I was really happy to solve a seemingly small mystery of failing temperature sensor driver which led to the bug fix otherwise difficult to notice and ignored for many years.