I'm currently developing a core lib which provides detection of ARM CPU features on the Windows platform. On x86 CPUs it is done by the __cpuid intrinsic which allows to read specific information like the brand string and CPU features like supported instruction sets.
I would like to implement something similar for ARM CPUs and started to implement reading the MIDR_EL1 register which provides the architecture version. Unfortunately it seems to be not accessible in user mode.
Here is my current prototype
#include "external.googletest/googletest/include/gtest/gtest.h" #include <intrin.h> #include <windows.h> #define ARM64_MIDR_EL1 ARM64_SYSREG(0b11,0,0,0,0) // Main ID Register #define ARM64_MIDR ARM64_SYSREG(0b1111,0,0,0,0) // Main ID Register TEST (ARM, read_register) { __int64 cntvct = _ReadStatusReg (ARM64_CNTVCT); // defined by winnt.h ok __int64 tpidr_el1 = _ReadStatusReg (ARM64_TPIDR_EL1); // defined by winnt.h, privileged only -> 0xC000001D __int64 null = _ReadStatusReg (0); // 0xC000001D __int64 midr = _ReadStatusReg (ARM64_MIDR); // 0xC000001D __int64 midr_el1 = _ReadStatusReg (ARM64_MIDR_EL1); // 0xC000001D }
Is it possible to access this information in user mode in a windows application in another way? Or am I encoding the opcodes in the wrong way? Or is it currently not possible at all?
Thanks in advance for all helpful answers!
I'm also trying to access various system registers from user space. On Linux, access to some of the system registers that require exception level 1 is trapped and emulated by the Kernel. This behavior is not present in windows, however.
From testing, your register encoding seems to be right, see bellow.
I don't think it's possible now, for a user-space application on Windows to access the *_EL1, *_EL2 or *_EL3 system registers.