cpuinfo
Information about each CPU in the system
The cpuinfo area contains information about each CPU in the system, such as the CPU type, speed, capabilities, performance, and cache sizes.
The number of cpuinfo_entry instances is equal to the value in the num_cpu member of the syspage_entry structure. Each cpuinfo_entry structure is automatically filled in by the startup library function init_cpuinfo(). The members include:
- cpu
- A number that represents the type of CPU. The meaning of this number depends on the CPU architecture. For example, for the x86 processor family, this number is the processor chip number (e.g., 586).
- speed
- The MHz rating of the processor.
- flags
- The CPU capabilities; see
flags
below. - smp_hwcoreid
- A number identifying each core; used for SMP.
- idle_history
- Reserved.
- spare1
- Not used.
- name
- An index into the strings member in the system page structure. The character string at the specified index contains an ASCII, NULL-terminated machine name.
- ins_cache
- An index into the cacheattr array, which is described below. This index points to the first definition in a list for the instruction cache.
- data_cache
- An index into the cacheattr array, which is described below. This index points to the first definition in a list for the data cache.
flags
The flags member contains a bitmapped indication of the CPU's capabilities. The prefix for a flag name (i.e., macro constant) indicates the CPU family it applies to. For instance, AARCH64_ indicates this constant is for use on the AArch64 (64-bit ARM) family of processors. If there is no prefix, the constant is generic; it is relevant to any CPU supported by QNX OS.
Generic flags are defined in <sys/syspage.h>, while architecture-specific flags are defined in <arch/syspage.h>. You'll need the values to interpret the output of the pidin syspage command.
This bit: | Means that the CPU has or supports: |
---|---|
CPU_FLAG_FPU | A Floating Point Unit (FPU) |
CPU_FLAG_MMU | A Memory Management Unit (MMU), and the MMU is enabled (i.e., the CPU is currently in virtual addressing mode) |
AARCH64_CPU_ACTLR | Auxiliary Control Register |
AARCH64_CPU_FLAG_CC_INCR_32 | A 32-bit clock cycle counter (CLOCKCYCLES_INCR_BIT is 32) |
AARCH64_CPU_FLAG_ICACHE_COHERENT | A coherent ICache. Saves one ICache invalidation at boot time. |
AARCH64_CPU_FLAG_KRYO_TLB | The system needs to use the workaround for the Qualcomm Technologies Falkor/Kryo erratum 1003 or the Qualcomm Falkor errata 1009 for Kryo. If your target needs to use this workaround, you must manually set this flag using the -F option for startup-*. |
AARCH64_CPU_FLAG_LSE | The system supports the Large System Extension; see
LL/SC vs LSE atomic operations,below |
AARCH64_CPU_FLAG_SMP | Multiple processors |
AARCH64_CPU_FLAG_SIMD | NEON technology, a 128-bit SIMD architecture extension to the ARM Cortex-A series processor |
AARCH64_CPU_FLAG_VHE | ARM v8.1 and more recent. Support virtualization host extensions (VHE). |
AARCH64_CPU_PAUTH | CPU supports Pointer Authentication (ARM v8.3 and more recent). This flag is set using the -U option for startup-*. When -U is specified, the kernel checks each CPU to determine if it supports Pointer Authentication and then sets AARCH64_CPU_PAUTH for CPUs that support it. |
AARCH64_CPU_SSBS | If this flag is set for CPU 0, the kernel checks each CPU to determine if it supports FEAT_SSBS
(Speculative Store Bypass Safe (SSBS)).
To check for a CPU's SSBS support, the kernel queries the CPU's ID_AA64PFR1_EL1 feature register (not its cpuinfo entry). If the CPU supports SSBS, its PSTATE.SSBS bit is set. A CPU's PSTATE.SSBS bit is not cleared if AARCH64_CPU_SSBS is not set for cpuinfo for CPU 0. |
X86_64_CPU_AVX | Advanced Vector Extensions |
X86_64_CPU_BSWAP | BSWAP instruction |
X86_64_CPU_CMOV | CMOV xx instructions |
X86_64_CPU_CPUID | CPUID instruction |
X86_64_CPU_FXSR | FXSAVE/FXRSTOR instructions |
X86_64_CPU_INVARIANT_TSC | Invariant (constant) Time Stamp Counter |
X86_64_CPU_INVLPG | INVLPG instruction |
X86_64_CPU_MMX | MMX instructions |
X86_64_CPU_MTRR | MTRR (Memory Type Range Register) registers |
X86_64_CPU_NX | No-eXecute PTE bit |
X86_64_CPU_PAE | Extended addressing |
X86_64_CPU_PAT | Page Attribute Tables |
X86_64_CPU_PCID | Process-Context Identifiers |
X86_64_CPU_PGE | TLB global mappings |
X86_64_CPU_PSE | Needs TLB flush when splitting a large page |
X86_64_CPU_PTESPLIT_TLBFLUSH | Page size extensions |
X86_64_CPU_RDTSC | RDTSC instruction |
X86_64_CPU_SEP | SYSENTER and SYSEXIT
instructions |
X86_64_CPU_SIMD | SIMD instructions |
X86_64_CPU_SSE2 | Streaming SIMD Extensions 2 |
X86_64_CPU_XSAVE | XSAVE and XRSTOR
instructions |
X86_64_CPU_WP | WP bit in the CR0
register |
LL/SC vs LSE atomic operations
The ARMv8-A architecture (see https://developer.arm.com/documentation/ddi0487/latest/) provides two groups of opcodes for atomic operations:
- standard load-link/store conditional (LLSC)
- ARMv8.1-A Large System Extension (LSE)
On the 64-bit ARM variant of procnto, if all CPUs support LSE atomics, the set of QNX-specific atomic functions default to using LSE, otherwise we revert to LLSC. The following QNX OS functions are affected:
- atomic_add()
- atomic_add_value()
- atomic_clr()
- atomic_clr_value()
- atomic_set()
- atomic_set_value()
- atomic_sub()
- atomic_sub_value()
- atomic_toggle()
- atomic_toggle_value()
Note that pthread_spin_lock() and pthread_spin_trylock() use these atomic functions; pthread_barrier_wait() and pthread_mutex_destroy() also use them, but to a lesser extent.
If all the CPUs in your system support ARMv8.1-A LSE atomics, you can profile these functions using both LLSC and LSE to determine which version gives better performance. On systems that default to LSE, you can revert to using LLSC by clearing the AARCH64_CPU_FLAG_LSE flag in the system page by either temporarily modifying the startup, or if the startup supports the -F option, clearing the CPU flag by passing -F~0x8000 to startup.
Note that the set of C11-specific atomic functions (such as atomic_fetch_add() in stdatomic.h) use LSE instructions only if you specify -march==armv8-a+lse or -march=armv8.N (where N is 1 or higher) on the compiler command line. The default is to build for the lowest common denominator ARMv8 instruction set, which doesn't include the LSE instructions.