Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1245957

[PATCH v3 23/24] arm64: Expose feature registers by emulating MRS

From "Suzuki K. Poulose" <suzuki.poulose@arm.com>
Newsgroups linux.kernel
Subject [PATCH v3 23/24] arm64: Expose feature registers by emulating MRS
Date 2015-10-13 19:30 +0200
Message-ID <qjbyI-4SC-53@gated-at.bofh.it> (permalink)
References <qjbyF-4SC-3@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


This patch adds the hook for emulating MRS instruction to
export the 'user visible' value of supported system registers.
We emulate only the following id space for system registers:
	Op0=0, Op1=0, CRn=0.

The rest will fall back to SIGILL.

This capability is also advertised via a new HWCAP_CPUID.

Signed-off-by: Suzuki K. Poulose <suzuki.poulose@arm.com>
---
 arch/arm64/include/asm/sysreg.h     |    6 ++
 arch/arm64/include/uapi/asm/hwcap.h |    1 +
 arch/arm64/kernel/cpufeature.c      |  106 +++++++++++++++++++++++++++++++++++
 arch/arm64/kernel/cpuinfo.c         |    1 +
 4 files changed, 114 insertions(+)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 1997b9e..730a613 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -54,6 +54,9 @@
 #define sys_reg_CRm(id)	(((id) >> CRm_shift) & CRm_mask)
 #define sys_reg_Op2(id)	(((id) >> Op2_shift) & Op2_mask)
 
+/* sys_reg() encoding of id is shifted by 5 for use in mrs */
+#define SYS_REG_IMM_SHIFT		5
+
 #define SYS_MIDR_EL1			sys_reg(3, 0, 0, 0, 0)
 #define SYS_MPIDR_EL1			sys_reg(3, 0, 0, 0, 5)
 #define SYS_REVIDR_EL1			sys_reg(3, 0, 0, 0, 6)
@@ -185,6 +188,9 @@
 #define MVFR1_FPFTZ_SHIFT		0
 
 
+/* Safe value for MPIDR_EL1: Bit31:RES1, Bit30:U:0, Bit24:MT:1 */
+#define SYS_MPIDR_SAFE_VAL	((1UL<<31)|(1UL<<24))
+
 #ifdef __ASSEMBLY__
 
 	.irp	num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h
index 361c8a8..3386e64 100644
--- a/arch/arm64/include/uapi/asm/hwcap.h
+++ b/arch/arm64/include/uapi/asm/hwcap.h
@@ -28,5 +28,6 @@
 #define HWCAP_SHA2		(1 << 6)
 #define HWCAP_CRC32		(1 << 7)
 #define HWCAP_ATOMICS		(1 << 8)
+#define HWCAP_CPUID		(1 << 9)
 
 #endif /* _UAPI__ASM_HWCAP_H */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 3806cb9..200a157 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -26,6 +26,7 @@
 #include <asm/cpu_ops.h>
 #include <asm/processor.h>
 #include <asm/sysreg.h>
+#include <asm/traps.h>
 
 unsigned long elf_hwcap __read_mostly;
 EXPORT_SYMBOL_GPL(elf_hwcap);
@@ -689,6 +690,8 @@ void check_cpu_hwcaps(void)
 {
 	int i;
 	const struct arm64_cpu_capabilities *hwcaps = arm64_hwcaps;
+
+	elf_hwcap |= HWCAP_CPUID;
 	for(i = 0; hwcaps[i].desc; i ++)
 		if (hwcaps[i].matches(&hwcaps[i]))
 			cap_set_hwcap(&hwcaps[i]);
@@ -853,3 +856,106 @@ void __init setup_cpu_features(void)
 		pr_warn("L1_CACHE_BYTES smaller than the Cache Writeback Granule (%d < %d)\n",
 			L1_CACHE_BYTES, cls);
 }
+
+/*
+ * We emulate only the following system register space.
+ * 	Op0 = 0x3, CRn = 0x0, Op1 = 0x0, CRm = [0 - 7]
+ * See Table C5-6 System instruction encodings for System register accesses,
+ * ARMv8 ARM(ARM DDI 0487A.f) for more details.
+ */
+static int __attribute_const__ is_emulated(u32 id)
+{
+	if (sys_reg_Op0(id) != 0x3 ||
+	    sys_reg_CRn(id) != 0x0 ||
+	    sys_reg_Op1(id) != 0x0 ||
+	    sys_reg_CRm(id) > 7)
+		return 0;
+	return 1;
+}
+
+/*
+ * With CRm = 0, id should be one of :
+ *	MIDR_EL1
+ *	MPIDR_EL1
+ *  	REVIDR_EL1
+ */
+static int emulate_id_reg(u32 id, u64 *valp)
+{
+	switch(id) {
+	case SYS_MIDR_EL1:
+		*valp = read_cpuid_id();
+		return 0;
+	case SYS_MPIDR_EL1:
+		*valp = SYS_MPIDR_SAFE_VAL;
+		return 0;
+	case SYS_REVIDR_EL1:
+		*valp = 0;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int emulate_sys_reg(u32 id, u64 *valp)
+{
+	int rc = -EINVAL;
+	struct arm64_ftr_reg *regp;
+
+	if (!is_emulated(id))
+		goto out;
+
+	if (sys_reg_CRm(id) == 0)
+		rc = emulate_id_reg(id, valp);
+	else {
+		/* We emulate all id's in the space 3, 0, 0, [1-7],x */
+		rc = 0;
+		regp = get_arm64_sys_reg(id);
+		if (regp)
+			*valp = regp->user_val | (regp->sys_val & regp->user_mask);
+		else
+			/*
+			 * Registers we don't track are either IMPLEMENTAION DEFINED
+			 * (e.g, ID_AFR0_EL1) or reserved RAZ.
+			 */
+			*valp = 0;
+	}
+
+out:
+	return rc;
+}
+
+static int emulate_mrs(struct pt_regs *regs, u32 insn)
+{
+	int rc = 0;
+	u32 sys_reg, dst;
+	u64 val = 0;
+
+	/*
+	 * sys_reg values are defined as used in mrs/msr instruction.
+	 * shift the imm value to get the encoding.
+	 */
+	sys_reg = (u32)aarch64_insn_decode_immediate(AARCH64_INSN_IMM_16, insn) << SYS_REG_IMM_SHIFT;
+	rc = emulate_sys_reg(sys_reg, &val);
+	if (rc)
+		return rc;
+	dst = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RT ,insn);
+	regs->user_regs.regs[dst] = val;
+	regs->pc += 4;
+	return 0;
+}
+
+static struct undef_hook mrs_hook = {
+	.instr_mask = 0xfff00000,
+	.instr_val  = 0xd5300000,
+	.pstate_mask = COMPAT_PSR_MODE_MASK,
+	.pstate_val = PSR_MODE_EL0t,
+	.fn = emulate_mrs,
+};
+
+int __init arm64_cpufeature_init(void)
+{
+	register_undef_hook(&mrs_hook);
+	return 0;
+}
+
+late_initcall(arm64_cpufeature_init);
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 789fbea..52331ff 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -58,6 +58,7 @@ static const char *hwcap_str[] = {
 	"sha2",
 	"crc32",
 	"atomics",
+	"cpuid",
 	NULL
 };
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH v3 00/24] arm64: Consolidate CPU feature handling "Suzuki K. Poulose" <suzuki.poulose@arm.com> - 2015-10-13 19:30 +0200
  [PATCH v3 23/24] arm64: Expose feature registers by emulating MRS "Suzuki K. Poulose" <suzuki.poulose@arm.com> - 2015-10-13 19:30 +0200
  [PATCH v3 13/24] arm64: Populate cpuinfo after notify_cpu_starting "Suzuki K. Poulose" <suzuki.poulose@arm.com> - 2015-10-13 19:40 +0200
    Re: [PATCH v3 13/24] arm64: Populate cpuinfo after  notify_cpu_starting Catalin Marinas <catalin.marinas@arm.com> - 2015-10-15 13:00 +0200
      Re: [PATCH v3 13/24] arm64: Populate cpuinfo after  notify_cpu_starting "Suzuki K. Poulose" <Suzuki.Poulose@arm.com> - 2015-10-15 15:30 +0200
  [PATCH v3 04/24] arm64: Move cpu feature detection code "Suzuki K. Poulose" <suzuki.poulose@arm.com> - 2015-10-13 19:40 +0200
  [PATCH v3 08/24] arm64: Handle width of a cpuid feature "Suzuki K. Poulose" <suzuki.poulose@arm.com> - 2015-10-13 19:40 +0200
  [PATCH v3 12/24] arm64: Cleanup mixed endian support detection "Suzuki K. Poulose" <suzuki.poulose@arm.com> - 2015-10-13 19:40 +0200
  [PATCH v3 19/24] arm64/kvm: Make use of the system wide safe values "Suzuki K. Poulose" <suzuki.poulose@arm.com> - 2015-10-13 19:40 +0200
  [PATCH v3 06/24] arm64: Move /proc/cpuinfo handling code "Suzuki K. Poulose" <suzuki.poulose@arm.com> - 2015-10-13 19:40 +0200
  Re: [PATCH v3 00/24] arm64: Consolidate CPU feature handling Dave Martin <Dave.Martin@arm.com> - 2015-10-16 17:20 +0200
    Re: [PATCH v3 00/24] arm64: Consolidate CPU feature handling "Suzuki K. Poulose" <Suzuki.Poulose@arm.com> - 2015-10-16 17:40 +0200
      Re: [PATCH v3 00/24] arm64: Consolidate CPU feature handling Dave Martin <Dave.Martin@arm.com> - 2015-10-16 17:50 +0200

csiph-web