aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSuzuki K Poulose <suzuki.poulose@arm.com>2016-11-08 08:56:20 -0500
committerCatalin Marinas <catalin.marinas@arm.com>2016-11-16 12:50:51 -0500
commita4023f682739439b434165b54af7cb3676a4766e (patch)
treeef2638d37291c56d972f20b69c59a6dee9292c18
parentc02433dd6de32f042cf3ffe476746b1115b8c096 (diff)
arm64: Add hypervisor safe helper for checking constant capabilities
The hypervisor may not have full access to the kernel data structures and hence cannot safely use cpus_have_cap() helper for checking the system capability. Add a safe helper for hypervisors to check a constant system capability, which *doesn't* fall back to checking the bitmap maintained by the kernel. With this, make the cpus_have_cap() only check the bitmask and force constant cap checks to use the new API for quicker checks. Cc: Robert Ritcher <rritcher@cavium.com> Cc: Tirumalesh Chalamarla <tchalamarla@cavium.com> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> Reviewed-by: Will Deacon <will.deacon@arm.com> Reviewed-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--arch/arm64/include/asm/cpufeature.h19
-rw-r--r--arch/arm64/kernel/cpufeature.c2
-rw-r--r--arch/arm64/kernel/process.c2
-rw-r--r--drivers/irqchip/irq-gic-v3.c13
4 files changed, 15 insertions, 21 deletions
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index a27c3245ba21..8b63adb148e7 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -9,8 +9,6 @@
9#ifndef __ASM_CPUFEATURE_H 9#ifndef __ASM_CPUFEATURE_H
10#define __ASM_CPUFEATURE_H 10#define __ASM_CPUFEATURE_H
11 11
12#include <linux/jump_label.h>
13
14#include <asm/hwcap.h> 12#include <asm/hwcap.h>
15#include <asm/sysreg.h> 13#include <asm/sysreg.h>
16 14
@@ -45,6 +43,8 @@
45 43
46#ifndef __ASSEMBLY__ 44#ifndef __ASSEMBLY__
47 45
46#include <linux/bug.h>
47#include <linux/jump_label.h>
48#include <linux/kernel.h> 48#include <linux/kernel.h>
49 49
50/* CPU feature register tracking */ 50/* CPU feature register tracking */
@@ -122,14 +122,19 @@ static inline bool cpu_have_feature(unsigned int num)
122 return elf_hwcap & (1UL << num); 122 return elf_hwcap & (1UL << num);
123} 123}
124 124
125/* System capability check for constant caps */
126static inline bool cpus_have_const_cap(int num)
127{
128 if (num >= ARM64_NCAPS)
129 return false;
130 return static_branch_unlikely(&cpu_hwcap_keys[num]);
131}
132
125static inline bool cpus_have_cap(unsigned int num) 133static inline bool cpus_have_cap(unsigned int num)
126{ 134{
127 if (num >= ARM64_NCAPS) 135 if (num >= ARM64_NCAPS)
128 return false; 136 return false;
129 if (__builtin_constant_p(num)) 137 return test_bit(num, cpu_hwcaps);
130 return static_branch_unlikely(&cpu_hwcap_keys[num]);
131 else
132 return test_bit(num, cpu_hwcaps);
133} 138}
134 139
135static inline void cpus_set_cap(unsigned int num) 140static inline void cpus_set_cap(unsigned int num)
@@ -218,7 +223,7 @@ static inline bool cpu_supports_mixed_endian_el0(void)
218 223
219static inline bool system_supports_32bit_el0(void) 224static inline bool system_supports_32bit_el0(void)
220{ 225{
221 return cpus_have_cap(ARM64_HAS_32BIT_EL0); 226 return cpus_have_const_cap(ARM64_HAS_32BIT_EL0);
222} 227}
223 228
224static inline bool system_supports_mixed_endian_el0(void) 229static inline bool system_supports_mixed_endian_el0(void)
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index c02504ea304b..fc2bd1926607 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1102,5 +1102,5 @@ void __init setup_cpu_features(void)
1102static bool __maybe_unused 1102static bool __maybe_unused
1103cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry, int __unused) 1103cpufeature_pan_not_uao(const struct arm64_cpu_capabilities *entry, int __unused)
1104{ 1104{
1105 return (cpus_have_cap(ARM64_HAS_PAN) && !cpus_have_cap(ARM64_HAS_UAO)); 1105 return (cpus_have_const_cap(ARM64_HAS_PAN) && !cpus_have_const_cap(ARM64_HAS_UAO));
1106} 1106}
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index a98b743631c5..a3a2816ba73a 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -283,7 +283,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
283 memset(childregs, 0, sizeof(struct pt_regs)); 283 memset(childregs, 0, sizeof(struct pt_regs));
284 childregs->pstate = PSR_MODE_EL1h; 284 childregs->pstate = PSR_MODE_EL1h;
285 if (IS_ENABLED(CONFIG_ARM64_UAO) && 285 if (IS_ENABLED(CONFIG_ARM64_UAO) &&
286 cpus_have_cap(ARM64_HAS_UAO)) 286 cpus_have_const_cap(ARM64_HAS_UAO))
287 childregs->pstate |= PSR_UAO_BIT; 287 childregs->pstate |= PSR_UAO_BIT;
288 p->thread.cpu_context.x19 = stack_start; 288 p->thread.cpu_context.x19 = stack_start;
289 p->thread.cpu_context.x20 = stk_sz; 289 p->thread.cpu_context.x20 = stk_sz;
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 19d642eae096..26e1d7fafb1e 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -120,11 +120,10 @@ static void gic_redist_wait_for_rwp(void)
120} 120}
121 121
122#ifdef CONFIG_ARM64 122#ifdef CONFIG_ARM64
123static DEFINE_STATIC_KEY_FALSE(is_cavium_thunderx);
124 123
125static u64 __maybe_unused gic_read_iar(void) 124static u64 __maybe_unused gic_read_iar(void)
126{ 125{
127 if (static_branch_unlikely(&is_cavium_thunderx)) 126 if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_23154))
128 return gic_read_iar_cavium_thunderx(); 127 return gic_read_iar_cavium_thunderx();
129 else 128 else
130 return gic_read_iar_common(); 129 return gic_read_iar_common();
@@ -905,14 +904,6 @@ static const struct irq_domain_ops partition_domain_ops = {
905 .select = gic_irq_domain_select, 904 .select = gic_irq_domain_select,
906}; 905};
907 906
908static void gicv3_enable_quirks(void)
909{
910#ifdef CONFIG_ARM64
911 if (cpus_have_cap(ARM64_WORKAROUND_CAVIUM_23154))
912 static_branch_enable(&is_cavium_thunderx);
913#endif
914}
915
916static int __init gic_init_bases(void __iomem *dist_base, 907static int __init gic_init_bases(void __iomem *dist_base,
917 struct redist_region *rdist_regs, 908 struct redist_region *rdist_regs,
918 u32 nr_redist_regions, 909 u32 nr_redist_regions,
@@ -935,8 +926,6 @@ static int __init gic_init_bases(void __iomem *dist_base,
935 gic_data.nr_redist_regions = nr_redist_regions; 926 gic_data.nr_redist_regions = nr_redist_regions;
936 gic_data.redist_stride = redist_stride; 927 gic_data.redist_stride = redist_stride;
937 928
938 gicv3_enable_quirks();
939
940 /* 929 /*
941 * Find out how many interrupts are supported. 930 * Find out how many interrupts are supported.
942 * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI) 931 * The GIC only supports up to 1020 interrupt sources (SGI+PPI+SPI)