This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Windows C++ ARM CPU detection in user mode

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.