From: Brian Cain <brian.cain@oss.qualcomm.com>
To: linux-hexagon@vger.kernel.org
Cc: marco.liebel@oss.qualcomm.com, pierrick.bouvier@oss.qualcomm.com,
sid.manning@oss.qualcomm.com,
Brian Cain <brian.cain@oss.qualcomm.com>
Subject: [PATCH v2] hexagon: add hwcap
Date: Wed, 9 Sep 2026 17:33:46 -0700 [thread overview]
Message-ID: <20260910003346.596593-1-brian.cain@oss.qualcomm.com> (raw)
Provide hwcap interface for userspace programs to discover the Hexagon CPU
capabilities.
Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
---
arch/hexagon/include/asm/elf.h | 3 +-
arch/hexagon/include/asm/hexagon_vm.h | 59 ++++++++++++++
arch/hexagon/include/asm/hwcap.h | 25 ++++++
arch/hexagon/include/uapi/asm/hwcap.h | 60 ++++++++++++++
arch/hexagon/kernel/setup.c | 109 ++++++++++++++++++++++++++
arch/hexagon/kernel/vm_ops.S | 4 +
6 files changed, 259 insertions(+), 1 deletion(-)
create mode 100644 arch/hexagon/include/asm/hwcap.h
create mode 100644 arch/hexagon/include/uapi/asm/hwcap.h
diff --git a/arch/hexagon/include/asm/elf.h b/arch/hexagon/include/asm/elf.h
index 5bfdd9b147fd..127e750613bd 100644
--- a/arch/hexagon/include/asm/elf.h
+++ b/arch/hexagon/include/asm/elf.h
@@ -11,6 +11,7 @@
#include <asm/ptrace.h>
#include <asm/user.h>
#include <linux/elf-em.h>
+#include <asm/hwcap.h>
struct elf32_hdr;
@@ -198,7 +199,7 @@ do { \
* This yields a mask that user programs can use to figure out what
* instruction set this cpu supports.
*/
-#define ELF_HWCAP (0)
+#define ELF_HWCAP (elf_hwcap)
/*
* This yields a string that ld.so will use to load implementation
diff --git a/arch/hexagon/include/asm/hexagon_vm.h b/arch/hexagon/include/asm/hexagon_vm.h
index 9aa2493fe786..f9cae71ad82f 100644
--- a/arch/hexagon/include/asm/hexagon_vm.h
+++ b/arch/hexagon/include/asm/hexagon_vm.h
@@ -38,6 +38,7 @@
#define HVM_TRAP1_VMSETREGS 21
#define HVM_TRAP1_VMGETREGS 22
#define HVM_TRAP1_VMTIMEROP 24
+#define HVM_TRAP1_VMGETINFO 26
#ifndef __ASSEMBLY__
@@ -65,6 +66,63 @@ enum VM_INT_OPS {
hvmi_clear
};
+enum VM_INFO_TYPE {
+ vm_info_build_id,
+ vm_info_boot_flags,
+ vm_info_stlb,
+ vm_info_syscfg,
+ vm_info_livelock,
+ vm_info_rev,
+ vm_info_ssbase,
+ vm_info_tlb_free,
+ vm_info_tlb_size,
+ vm_info_physaddr,
+ vm_info_tcm_base,
+ vm_info_l2mem_size,
+ vm_info_tcm_size,
+ vm_info_h2k_pgsize,
+ vm_info_h2k_npages,
+ vm_info_l2vic_base,
+ vm_info_timer_base,
+ vm_info_timer_int,
+ vm_info_error,
+ vm_info_hthreads,
+ vm_info_l2tag_size,
+ vm_info_l2cfg_base,
+ vm_info_clade_base,
+ vm_info_cfgbase,
+ vm_info_hvx_vlength,
+ vm_info_hmx_instances = 34,
+};
+
+struct vm_rev {
+ union {
+ unsigned long raw;
+ struct {
+ unsigned long isa:8;
+ unsigned long l2tags:4;
+ unsigned long l2size:4;
+ unsigned long layer:4;
+ unsigned long unused:4;
+ unsigned long metal:8;
+ };
+ };
+};
+
+struct vm_boot_flags {
+ union {
+ unsigned long raw;
+ struct {
+ unsigned long use_tcm:1;
+ unsigned long have_hvx:1;
+ unsigned long have_sample:1;
+ unsigned long ext_ok:1;
+ unsigned long have_dma:1;
+ unsigned long have_hmx:1;
+ };
+ };
+};
+
extern void _K_VM_event_vector(void);
void __vmrte(void);
@@ -82,6 +140,7 @@ void __vmstop(void);
long __vmwait(void);
void __vmyield(void);
long __vmvpid(void);
+unsigned long __vmgetinfo(unsigned long);
static inline long __vmcache_ickill(void)
{
diff --git a/arch/hexagon/include/asm/hwcap.h b/arch/hexagon/include/asm/hwcap.h
new file mode 100644
index 000000000000..6bfbcec66d31
--- /dev/null
+++ b/arch/hexagon/include/asm/hwcap.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Hexagon hardware capability definitions
+ *
+ * Copyright Qualcomm Technologies, Inc. and its subsidiaries
+ */
+
+#ifndef __ASM_HEXAGON_HWCAP_H
+#define __ASM_HEXAGON_HWCAP_H
+
+#include <uapi/asm/hwcap.h>
+
+/* Kernel-internal definitions: ISA versions are used directly from UAPI */
+
+#ifndef __ASSEMBLER__
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP (elf_hwcap)
+
+extern unsigned long elf_hwcap;
+#endif
+
+#endif /* __ASM_HEXAGON_HWCAP_H */
diff --git a/arch/hexagon/include/uapi/asm/hwcap.h b/arch/hexagon/include/uapi/asm/hwcap.h
new file mode 100644
index 000000000000..a58b9593169b
--- /dev/null
+++ b/arch/hexagon/include/uapi/asm/hwcap.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Hexagon hardware capability definitions - User API
+ *
+ * Copyright Qualcomm Technologies, Inc. and its subsidiaries
+ */
+
+#ifndef _UAPI__ASM_HEXAGON_HWCAP_H
+#define _UAPI__ASM_HEXAGON_HWCAP_H
+
+/*
+ * HWCAP flags - for AT_HWCAP
+ *
+ * ISA Version Encoding:
+ * Bits 0-6 encode the ISA version as enumeration values
+ */
+
+/* ISA version encoding */
+#define HWCAP_HEXAGON_ISA_MASK 0x7F /* ISA version mask */
+
+/* ISA version enumeration values */
+#define HWCAP_HEXAGON_ISA_V2 1 /* Hexagon V2 */
+#define HWCAP_HEXAGON_ISA_V3 2 /* Hexagon V3 */
+#define HWCAP_HEXAGON_ISA_V4 3 /* Hexagon V4 */
+#define HWCAP_HEXAGON_ISA_V5 4 /* Hexagon V5 */
+#define HWCAP_HEXAGON_ISA_V55 5 /* Hexagon V55 */
+#define HWCAP_HEXAGON_ISA_V60 6 /* Hexagon V60 */
+#define HWCAP_HEXAGON_ISA_V62 7 /* Hexagon V62 */
+#define HWCAP_HEXAGON_ISA_V65 8 /* Hexagon V65 */
+#define HWCAP_HEXAGON_ISA_V66 9 /* Hexagon V66 */
+#define HWCAP_HEXAGON_ISA_V67 10 /* Hexagon V67 */
+#define HWCAP_HEXAGON_ISA_V68 11 /* Hexagon V68 */
+#define HWCAP_HEXAGON_ISA_V69 12 /* Hexagon V69 */
+#define HWCAP_HEXAGON_ISA_V71 13 /* Hexagon V71 */
+#define HWCAP_HEXAGON_ISA_V73 14 /* Hexagon V73 */
+#define HWCAP_HEXAGON_ISA_V75 15 /* Hexagon V75 */
+#define HWCAP_HEXAGON_ISA_V77 16 /* Hexagon V77 */
+#define HWCAP_HEXAGON_ISA_V79 17 /* Hexagon V79 */
+#define HWCAP_HEXAGON_ISA_V81 18 /* Hexagon V81 */
+
+/* Essential feature flags */
+#define HWCAP_HEXAGON_HVX (1 << 7) /* HVX (Hexagon Vector eXtensions) */
+#define HWCAP_HEXAGON_CABAC (1 << 8) /* CABAC acceleration */
+#define HWCAP_HEXAGON_HVX_LENGTH_128B (1 << 9) /* HVX 128-byte vector length */
+#define HWCAP_HEXAGON_HVX_IEEE_FP (1 << 10) /* HVX IEEE floating point */
+#define HWCAP_HEXAGON_AUDIO (1 << 11) /* Audio ISA extensions */
+#define HWCAP_HEXAGON_HMX (1 << 12) /* HMX matrix extensions */
+
+/* Bits 13-31 reserved for future use */
+
+/* Utility macros for userspace applications */
+#define HWCAP_HEXAGON_GET_ISA(hwcap) ((hwcap) & HWCAP_HEXAGON_ISA_MASK)
+#define HWCAP_HEXAGON_IS_ISA(hwcap, version) (HWCAP_HEXAGON_GET_ISA(hwcap) == (version))
+#define HWCAP_HEXAGON_HAS_ISA(hwcap, version) (HWCAP_HEXAGON_GET_ISA(hwcap) >= (version))
+
+/*
+ * HWCAP2 is not currently used by Hexagon.
+ */
+
+#endif /* _UAPI__ASM_HEXAGON_HWCAP_H */
diff --git a/arch/hexagon/kernel/setup.c b/arch/hexagon/kernel/setup.c
index 621674e86232..a0f51f247a9c 100644
--- a/arch/hexagon/kernel/setup.c
+++ b/arch/hexagon/kernel/setup.c
@@ -20,6 +20,11 @@
#include <asm/hexagon_vm.h>
#include <asm/vm_mmu.h>
#include <asm/time.h>
+#include <asm/hwcap.h>
+
+unsigned long elf_hwcap __read_mostly;
+
+EXPORT_SYMBOL_GPL(elf_hwcap);
char cmd_line[COMMAND_LINE_SIZE];
static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
@@ -31,6 +36,109 @@ void calibrate_delay(void)
loops_per_jiffy = thread_freq_mhz * 1000000 / HZ;
}
+/*
+ * populate hardware capabilities using vmgetinfo
+ */
+static void __init setup_hwcap(void)
+{
+ struct vm_rev rev;
+ struct vm_boot_flags boot_flags;
+ unsigned long hvx_vlength;
+ unsigned long hmx_instances;
+ unsigned int isa;
+
+ elf_hwcap = 0;
+
+ /* Get revision information for ISA version */
+ rev.raw = __vmgetinfo(vm_info_rev);
+ boot_flags.raw = __vmgetinfo(vm_info_boot_flags);
+
+ isa = ((rev.isa >> 4) & 0xf) * 10 + (rev.isa & 0xf);
+
+ switch (isa) {
+ case 81:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V81;
+ break;
+ case 79:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V79;
+ break;
+ case 77:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V77;
+ break;
+ case 75:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V75;
+ break;
+ case 73:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V73;
+ break;
+ case 71:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V71;
+ break;
+ case 69:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V69;
+ break;
+ case 68:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V68;
+ break;
+ case 67:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V67;
+ break;
+ case 66:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V66;
+ break;
+ case 65:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V65;
+ break;
+ case 62:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V62;
+ break;
+ case 60:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V60;
+ break;
+ case 55:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V55;
+ break;
+ case 5:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V5;
+ break;
+ case 4:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V4;
+ break;
+ case 3:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V3;
+ break;
+ case 2:
+ elf_hwcap |= HWCAP_HEXAGON_ISA_V2;
+ break;
+ default:
+ /* Unknown ISA version - leave ISA field as 0 */
+ break;
+ }
+
+ /* Check for HVX support */
+ hvx_vlength = __vmgetinfo(vm_info_hvx_vlength);
+ if (hvx_vlength) {
+ elf_hwcap |= HWCAP_HEXAGON_HVX;
+
+ if (hvx_vlength >= 128)
+ elf_hwcap |= HWCAP_HEXAGON_HVX_LENGTH_128B;
+ }
+
+ hmx_instances = __vmgetinfo(vm_info_hmx_instances);
+ if (boot_flags.have_hmx && hmx_instances && hmx_instances != ~0UL)
+ elf_hwcap |= HWCAP_HEXAGON_HMX;
+
+ printk(KERN_INFO "Hexagon hwcap: 0x%08lx (v%u%s%s%s%s%s%s)\n",
+ elf_hwcap,
+ isa,
+ (elf_hwcap & HWCAP_HEXAGON_HVX) ? ", HVX" : "",
+ (elf_hwcap & HWCAP_HEXAGON_HVX_LENGTH_128B) ? ", HVX-128B" : "",
+ (elf_hwcap & HWCAP_HEXAGON_HVX_IEEE_FP) ? ", HVX-IEEE-FP" : "",
+ (elf_hwcap & HWCAP_HEXAGON_AUDIO) ? ", Audio" : "",
+ (elf_hwcap & HWCAP_HEXAGON_CABAC) ? ", CABAC" : "",
+ (elf_hwcap & HWCAP_HEXAGON_HMX) ? ", HMX" : "");
+}
+
/*
* setup_arch - high level architectural setup routine
* @cmdline_p: pointer to pointer to command-line arguments
@@ -55,6 +163,7 @@ void __init setup_arch(char **cmdline_p)
printk(KERN_INFO "PHYS_OFFSET=0x%08lx\n", PHYS_OFFSET);
+ setup_hwcap();
/*
* Simulator has a few differences from the hardware.
* For now, check uninitialized-but-mapped memory
diff --git a/arch/hexagon/kernel/vm_ops.S b/arch/hexagon/kernel/vm_ops.S
index f61c04d485f6..7bf32c55e050 100644
--- a/arch/hexagon/kernel/vm_ops.S
+++ b/arch/hexagon/kernel/vm_ops.S
@@ -25,6 +25,10 @@ ENTRY(__vmsetvec)
trap1(#HVM_TRAP1_VMSETVEC);
jumpr R31;
+ENTRY(__vmgetinfo)
+ trap1(#HVM_TRAP1_VMGETINFO);
+ jumpr R31;
+
ENTRY(__vmsetie)
trap1(#HVM_TRAP1_VMSETIE);
jumpr R31;
--
2.34.1
reply other threads:[~2026-09-10 0:33 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260910003346.596593-1-brian.cain@oss.qualcomm.com \
--to=brian.cain@oss.qualcomm.com \
--cc=linux-hexagon@vger.kernel.org \
--cc=marco.liebel@oss.qualcomm.com \
--cc=pierrick.bouvier@oss.qualcomm.com \
--cc=sid.manning@oss.qualcomm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.