mirror of https://github.com/torvalds/linux.git
arm64 updates for 7.1 (second round):
Core features:
- Add workaround for C1-Pro erratum 4193714 - early CME (SME unit)
DVMSync acknowledgement. The fix consists of sending IPIs on TLB
maintenance to those CPUs running in user space with SME enabled
- Include kernel-hwcap.h in list of generated files (missed in a recent
commit generating the KERNEL_HWCAP_* macros)
CCA:
- Fix RSI_INCOMPLETE error check in arm-cca-guest
MPAM:
- Fix an unmount->remount problem with the CDP emulation, uninitialised
variable and checker warnings
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEE5RElWfyWxS+3PLO2a9axLQDIXvEFAmnmQZcACgkQa9axLQDI
XvGouA//SXlo7hQyM41rkgRru9oqftrGg0y6nxz4Z089kv50cm3Jlf/nUuti6vah
BMBLCGXA1iOQrGIVmuvtCxDRrfYZWpfKGuT9A0gmEoMqrGIpWl9gfBQG+uR+YrQX
4kp5DLqB85WrJIPiy7HUV6GQoCbFuMrRJwxl89IdWZSobaei3SczTmnttwyJtxG5
/BMitl024TYdiOPNo8bhiML1wIJCaTHvH4IrtCHPyUHEAtsHSMy00y0OrSKBtA/9
ZHZRpY7Po/jnL7YUs1AfYwsaSXjkvqXN0K1Tdavzm75k6lpJmbM3VsZabG/CEuvK
PCOGV++is4Y/A+7aQsCwXKeVnY3b6AC4sextytNq0g3GZ7I+Ht9O6nbsp5ZmyXzB
HRiFxmFS1pSQOMX9f1neKi3vxDMTy1tKPeccTTzL8dNnxTvUBXnoWfPoJh3cpbjm
Dbhe1kksiEn01WWFacGtkIPDa9c+Bkd2T+8wrsk85Z+u3Z0JPM5PfOn6v3X9YlKl
K7W8fhvlDL1wP+iyWcMT5zdo+xzHY4ZxuyWbi9a4RhKc6lFHVVG2mpUuPwSsh2ma
NnxkDouriuoADHBir89U71N483HSnNfSjhlVSFYD2LFCre5KOZM4KYZ2vwWb8Sy4
79q+BlVRUTQ5O6XjePoSPjUW4APPNviHJsF4E4IiqHkd9O5lMZU=
=LNY2
-----END PGP SIGNATURE-----
Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
Pull more arm64 updates from Catalin Marinas:
"The main 'feature' is a workaround for C1-Pro erratum 4193714
requiring IPIs during TLB maintenance if a process is running in user
space with SME enabled.
The hardware acknowledges the DVMSync messages before completing
in-flight SME accesses, with security implications. The workaround
makes use of the mm_cpumask() to track the cores that need
interrupting (arm64 hasn't used this mask before).
The rest are fixes for MPAM, CCA and generated header that turned up
during the merging window or shortly before.
Summary:
Core features:
- Add workaround for C1-Pro erratum 4193714 - early CME (SME unit)
DVMSync acknowledgement. The fix consists of sending IPIs on TLB
maintenance to those CPUs running in user space with SME enabled
- Include kernel-hwcap.h in list of generated files (missed in a
recent commit generating the KERNEL_HWCAP_* macros)
CCA:
- Fix RSI_INCOMPLETE error check in arm-cca-guest
MPAM:
- Fix an unmount->remount problem with the CDP emulation,
uninitialised variable and checker warnings"
* tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm_mpam: resctrl: Make resctrl_mon_ctx_waiters static
arm_mpam: resctrl: Fix the check for no monitor components found
arm_mpam: resctrl: Fix MBA CDP alloc_capable handling on unmount
virt: arm-cca-guest: fix error check for RSI_INCOMPLETE
arm64/hwcap: Include kernel-hwcap.h in list of generated files
arm64: errata: Work around early CME DVMSync acknowledgement
arm64: cputype: Add C1-Pro definitions
arm64: tlb: Pass the corresponding mm to __tlbi_sync_s1ish()
arm64: tlb: Introduce __tlbi_sync_s1ish_{kernel,batch}() for TLB maintenance
This commit is contained in:
commit
13f24586a2
|
|
@ -202,6 +202,8 @@ stable kernels.
|
|||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | Neoverse-V3AE | #3312417 | ARM64_ERRATUM_3194386 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | C1-Pro | #4193714 | ARM64_ERRATUM_4193714 |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
| ARM | MMU-500 | #841119,826419 | ARM_SMMU_MMU_500_CPRE_ERRATA|
|
||||
| | | #562869,1047329 | |
|
||||
+----------------+-----------------+-----------------+-----------------------------+
|
||||
|
|
|
|||
|
|
@ -1142,6 +1142,18 @@ config ARM64_ERRATUM_4311569
|
|||
|
||||
If unsure, say Y.
|
||||
|
||||
config ARM64_ERRATUM_4193714
|
||||
bool "C1-Pro: 4193714: SME DVMSync early acknowledgement"
|
||||
depends on ARM64_SME
|
||||
default y
|
||||
help
|
||||
Enable workaround for C1-Pro acknowledging the DVMSync before
|
||||
the SME memory accesses are complete. This will cause TLB
|
||||
maintenance for processes using SME to also issue an IPI to
|
||||
the affected CPUs.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config CAVIUM_ERRATUM_22375
|
||||
bool "Cavium erratum 22375, 24313"
|
||||
default y
|
||||
|
|
|
|||
|
|
@ -17,4 +17,5 @@ generic-y += parport.h
|
|||
generic-y += user.h
|
||||
|
||||
generated-y += cpucap-defs.h
|
||||
generated-y += kernel-hwcap.h
|
||||
generated-y += sysreg-defs.h
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ cpucap_is_possible(const unsigned int cap)
|
|||
return IS_ENABLED(CONFIG_ARM64_WORKAROUND_REPEAT_TLBI);
|
||||
case ARM64_WORKAROUND_SPECULATIVE_SSBS:
|
||||
return IS_ENABLED(CONFIG_ARM64_ERRATUM_3194386);
|
||||
case ARM64_WORKAROUND_4193714:
|
||||
return IS_ENABLED(CONFIG_ARM64_ERRATUM_4193714);
|
||||
case ARM64_MPAM:
|
||||
/*
|
||||
* KVM MPAM support doesn't rely on the host kernel supporting MPAM.
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@
|
|||
#define ARM_CPU_PART_CORTEX_A725 0xD87
|
||||
#define ARM_CPU_PART_CORTEX_A720AE 0xD89
|
||||
#define ARM_CPU_PART_NEOVERSE_N3 0xD8E
|
||||
#define ARM_CPU_PART_C1_PRO 0xD8B
|
||||
|
||||
#define APM_CPU_PART_XGENE 0x000
|
||||
#define APM_CPU_VAR_POTENZA 0x00
|
||||
|
|
@ -189,6 +190,7 @@
|
|||
#define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725)
|
||||
#define MIDR_CORTEX_A720AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720AE)
|
||||
#define MIDR_NEOVERSE_N3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N3)
|
||||
#define MIDR_C1_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_C1_PRO)
|
||||
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
|
||||
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
|
||||
#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
|
||||
|
|
|
|||
|
|
@ -428,6 +428,24 @@ static inline size_t sme_state_size(struct task_struct const *task)
|
|||
return __sme_state_size(task_get_sme_vl(task));
|
||||
}
|
||||
|
||||
void sme_enable_dvmsync(void);
|
||||
void sme_set_active(void);
|
||||
void sme_clear_active(void);
|
||||
|
||||
static inline void sme_enter_from_user_mode(void)
|
||||
{
|
||||
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714) &&
|
||||
test_thread_flag(TIF_SME))
|
||||
sme_clear_active();
|
||||
}
|
||||
|
||||
static inline void sme_exit_to_user_mode(void)
|
||||
{
|
||||
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714) &&
|
||||
test_thread_flag(TIF_SME))
|
||||
sme_set_active();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void sme_user_disable(void) { BUILD_BUG(); }
|
||||
|
|
@ -456,6 +474,9 @@ static inline size_t sme_state_size(struct task_struct const *task)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline void sme_enter_from_user_mode(void) { }
|
||||
static inline void sme_exit_to_user_mode(void) { }
|
||||
|
||||
#endif /* ! CONFIG_ARM64_SME */
|
||||
|
||||
/* For use by EFI runtime services calls only */
|
||||
|
|
|
|||
|
|
@ -2,11 +2,17 @@
|
|||
#ifndef _ARCH_ARM64_TLBBATCH_H
|
||||
#define _ARCH_ARM64_TLBBATCH_H
|
||||
|
||||
#include <linux/cpumask.h>
|
||||
|
||||
struct arch_tlbflush_unmap_batch {
|
||||
#ifdef CONFIG_ARM64_ERRATUM_4193714
|
||||
/*
|
||||
* For arm64, HW can do tlb shootdown, so we don't
|
||||
* need to record cpumask for sending IPI
|
||||
* Track CPUs that need SME DVMSync on completion of this batch.
|
||||
* Otherwise, the arm64 HW can do tlb shootdown, so we don't need to
|
||||
* record cpumask for sending IPI
|
||||
*/
|
||||
cpumask_var_t cpumask;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* _ARCH_ARM64_TLBBATCH_H */
|
||||
|
|
|
|||
|
|
@ -80,6 +80,71 @@ static inline unsigned long get_trans_granule(void)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64_ERRATUM_4193714
|
||||
|
||||
void sme_do_dvmsync(const struct cpumask *mask);
|
||||
|
||||
static inline void sme_dvmsync(struct mm_struct *mm)
|
||||
{
|
||||
if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
|
||||
return;
|
||||
|
||||
sme_do_dvmsync(mm_cpumask(mm));
|
||||
}
|
||||
|
||||
static inline void sme_dvmsync_add_pending(struct arch_tlbflush_unmap_batch *batch,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Order the mm_cpumask() read after the hardware DVMSync.
|
||||
*/
|
||||
dsb(ish);
|
||||
if (cpumask_empty(mm_cpumask(mm)))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Allocate the batch cpumask on first use. Fall back to an immediate
|
||||
* IPI for this mm in case of failure.
|
||||
*/
|
||||
if (!cpumask_available(batch->cpumask) &&
|
||||
!zalloc_cpumask_var(&batch->cpumask, GFP_ATOMIC)) {
|
||||
sme_do_dvmsync(mm_cpumask(mm));
|
||||
return;
|
||||
}
|
||||
|
||||
cpumask_or(batch->cpumask, batch->cpumask, mm_cpumask(mm));
|
||||
}
|
||||
|
||||
static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch)
|
||||
{
|
||||
if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
|
||||
return;
|
||||
|
||||
if (!cpumask_available(batch->cpumask))
|
||||
return;
|
||||
|
||||
sme_do_dvmsync(batch->cpumask);
|
||||
cpumask_clear(batch->cpumask);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void sme_dvmsync(struct mm_struct *mm)
|
||||
{
|
||||
}
|
||||
static inline void sme_dvmsync_add_pending(struct arch_tlbflush_unmap_batch *batch,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
}
|
||||
static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARM64_ERRATUM_4193714 */
|
||||
|
||||
/*
|
||||
* Level-based TLBI operations.
|
||||
*
|
||||
|
|
@ -213,7 +278,21 @@ do { \
|
|||
* Complete broadcast TLB maintenance issued by the host which invalidates
|
||||
* stage 1 information in the host's own translation regime.
|
||||
*/
|
||||
static inline void __tlbi_sync_s1ish(void)
|
||||
static inline void __tlbi_sync_s1ish(struct mm_struct *mm)
|
||||
{
|
||||
dsb(ish);
|
||||
__repeat_tlbi_sync(vale1is, 0);
|
||||
sme_dvmsync(mm);
|
||||
}
|
||||
|
||||
static inline void __tlbi_sync_s1ish_batch(struct arch_tlbflush_unmap_batch *batch)
|
||||
{
|
||||
dsb(ish);
|
||||
__repeat_tlbi_sync(vale1is, 0);
|
||||
sme_dvmsync_batch(batch);
|
||||
}
|
||||
|
||||
static inline void __tlbi_sync_s1ish_kernel(void)
|
||||
{
|
||||
dsb(ish);
|
||||
__repeat_tlbi_sync(vale1is, 0);
|
||||
|
|
@ -322,7 +401,7 @@ static inline void flush_tlb_all(void)
|
|||
{
|
||||
dsb(ishst);
|
||||
__tlbi(vmalle1is);
|
||||
__tlbi_sync_s1ish();
|
||||
__tlbi_sync_s1ish_kernel();
|
||||
isb();
|
||||
}
|
||||
|
||||
|
|
@ -334,7 +413,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
|
|||
asid = __TLBI_VADDR(0, ASID(mm));
|
||||
__tlbi(aside1is, asid);
|
||||
__tlbi_user(aside1is, asid);
|
||||
__tlbi_sync_s1ish();
|
||||
__tlbi_sync_s1ish(mm);
|
||||
mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL);
|
||||
}
|
||||
|
||||
|
|
@ -355,7 +434,7 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
|
|||
*/
|
||||
static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
|
||||
{
|
||||
__tlbi_sync_s1ish();
|
||||
__tlbi_sync_s1ish_batch(batch);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -557,7 +636,7 @@ static __always_inline void __do_flush_tlb_range(struct vm_area_struct *vma,
|
|||
|
||||
if (!(flags & TLBF_NOSYNC)) {
|
||||
if (!(flags & TLBF_NOBROADCAST))
|
||||
__tlbi_sync_s1ish();
|
||||
__tlbi_sync_s1ish(mm);
|
||||
else
|
||||
dsb(nsh);
|
||||
}
|
||||
|
|
@ -618,7 +697,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
|
|||
dsb(ishst);
|
||||
__flush_s1_tlb_range_op(vaale1is, start, pages, stride, 0,
|
||||
TLBI_TTL_UNKNOWN);
|
||||
__tlbi_sync_s1ish();
|
||||
__tlbi_sync_s1ish_kernel();
|
||||
isb();
|
||||
}
|
||||
|
||||
|
|
@ -632,7 +711,7 @@ static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr)
|
|||
|
||||
dsb(ishst);
|
||||
__tlbi(vaae1is, addr);
|
||||
__tlbi_sync_s1ish();
|
||||
__tlbi_sync_s1ish_kernel();
|
||||
isb();
|
||||
}
|
||||
|
||||
|
|
@ -643,6 +722,7 @@ static inline void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *b
|
|||
|
||||
__flush_tlb_range(&vma, start, end, PAGE_SIZE, 3,
|
||||
TLBF_NOWALKCACHE | TLBF_NOSYNC);
|
||||
sme_dvmsync_add_pending(batch, mm);
|
||||
}
|
||||
|
||||
static inline bool __pte_flags_need_flush(ptdesc_t oldval, ptdesc_t newval)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <asm/cpu.h>
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/fpsimd.h>
|
||||
#include <asm/kvm_asm.h>
|
||||
#include <asm/smp_plat.h>
|
||||
|
||||
|
|
@ -575,6 +576,23 @@ static const struct midr_range erratum_spec_ssbs_list[] = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARM64_ERRATUM_4193714
|
||||
static bool has_sme_dvmsync_erratum(const struct arm64_cpu_capabilities *entry,
|
||||
int scope)
|
||||
{
|
||||
if (!id_aa64pfr1_sme(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1)))
|
||||
return false;
|
||||
|
||||
return is_affected_midr_range(entry, scope);
|
||||
}
|
||||
|
||||
static void cpu_enable_sme_dvmsync(const struct arm64_cpu_capabilities *__unused)
|
||||
{
|
||||
if (this_cpu_has_cap(ARM64_WORKAROUND_4193714))
|
||||
sme_enable_dvmsync();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38
|
||||
static const struct midr_range erratum_ac03_cpu_38_list[] = {
|
||||
MIDR_ALL_VERSIONS(MIDR_AMPERE1),
|
||||
|
|
@ -901,6 +919,18 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
|||
.matches = need_arm_si_l1_workaround_4311569,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_ERRATUM_4193714
|
||||
{
|
||||
.desc = "C1-Pro SME DVMSync early acknowledgement",
|
||||
.capability = ARM64_WORKAROUND_4193714,
|
||||
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
|
||||
.matches = has_sme_dvmsync_erratum,
|
||||
.cpu_enable = cpu_enable_sme_dvmsync,
|
||||
/* C1-Pro r0p0 - r1p2 (the latter only when REVIDR_EL1[0]==0) */
|
||||
.midr_range = MIDR_RANGE(MIDR_C1_PRO, 0, 0, 1, 2),
|
||||
MIDR_FIXED(MIDR_CPU_VAR_REV(1, 2), BIT(0)),
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD
|
||||
{
|
||||
.desc = "ARM errata 2966298, 3117295",
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include <asm/daifflags.h>
|
||||
#include <asm/esr.h>
|
||||
#include <asm/exception.h>
|
||||
#include <asm/fpsimd.h>
|
||||
#include <asm/irq_regs.h>
|
||||
#include <asm/kprobes.h>
|
||||
#include <asm/mmu.h>
|
||||
|
|
@ -70,6 +71,7 @@ static __always_inline void arm64_enter_from_user_mode(struct pt_regs *regs)
|
|||
{
|
||||
enter_from_user_mode(regs);
|
||||
mte_disable_tco_entry(current);
|
||||
sme_enter_from_user_mode();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -83,6 +85,7 @@ static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs)
|
|||
local_irq_disable();
|
||||
exit_to_user_mode_prepare_legacy(regs);
|
||||
local_daif_mask();
|
||||
sme_exit_to_user_mode();
|
||||
mte_check_tfsr_exit();
|
||||
exit_to_user_mode();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include <linux/compiler.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpu_pm.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/linkage.h>
|
||||
|
|
@ -28,6 +29,7 @@
|
|||
#include <linux/sched/task_stack.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/swab.h>
|
||||
|
|
@ -1358,6 +1360,83 @@ void do_sve_acc(unsigned long esr, struct pt_regs *regs)
|
|||
put_cpu_fpsimd_context();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64_ERRATUM_4193714
|
||||
|
||||
/*
|
||||
* SME/CME erratum handling.
|
||||
*/
|
||||
static cpumask_t sme_dvmsync_cpus;
|
||||
|
||||
/*
|
||||
* These helpers are only called from non-preemptible contexts, so
|
||||
* smp_processor_id() is safe here.
|
||||
*/
|
||||
void sme_set_active(void)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
if (!cpumask_test_cpu(cpu, &sme_dvmsync_cpus))
|
||||
return;
|
||||
|
||||
cpumask_set_cpu(cpu, mm_cpumask(current->mm));
|
||||
|
||||
/*
|
||||
* A subsequent (post ERET) SME access may use a stale address
|
||||
* translation. On C1-Pro, a TLBI+DSB on a different CPU will wait for
|
||||
* the completion of cpumask_set_cpu() above as it appears in program
|
||||
* order before the SME access. The post-TLBI+DSB read of mm_cpumask()
|
||||
* will lead to the IPI being issued.
|
||||
*
|
||||
* https://lore.kernel.org/r/ablEXwhfKyJW1i7l@J2N7QTR9R3
|
||||
*/
|
||||
}
|
||||
|
||||
void sme_clear_active(void)
|
||||
{
|
||||
unsigned int cpu = smp_processor_id();
|
||||
|
||||
if (!cpumask_test_cpu(cpu, &sme_dvmsync_cpus))
|
||||
return;
|
||||
|
||||
/*
|
||||
* With SCTLR_EL1.IESB enabled, the SME memory transactions are
|
||||
* completed on entering EL1.
|
||||
*/
|
||||
cpumask_clear_cpu(cpu, mm_cpumask(current->mm));
|
||||
}
|
||||
|
||||
static void sme_dvmsync_ipi(void *unused)
|
||||
{
|
||||
/*
|
||||
* With SCTLR_EL1.IESB on, taking an exception is sufficient to ensure
|
||||
* the completion of the SME memory accesses, so no need for an
|
||||
* explicit DSB.
|
||||
*/
|
||||
}
|
||||
|
||||
void sme_do_dvmsync(const struct cpumask *mask)
|
||||
{
|
||||
/*
|
||||
* This is called from the TLB maintenance functions after the DSB ISH
|
||||
* to send the hardware DVMSync message. If this CPU sees the mask as
|
||||
* empty, the remote CPU executing sme_set_active() would have seen
|
||||
* the DVMSync and no IPI required.
|
||||
*/
|
||||
if (cpumask_empty(mask))
|
||||
return;
|
||||
|
||||
preempt_disable();
|
||||
smp_call_function_many(mask, sme_dvmsync_ipi, NULL, true);
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
void sme_enable_dvmsync(void)
|
||||
{
|
||||
cpumask_set_cpu(smp_processor_id(), &sme_dvmsync_cpus);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARM64_ERRATUM_4193714 */
|
||||
|
||||
/*
|
||||
* Trapped SME access
|
||||
*
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/reboot.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/elfcore.h>
|
||||
#include <linux/pm.h>
|
||||
|
|
@ -340,8 +341,41 @@ void flush_thread(void)
|
|||
flush_gcs();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARM64_ERRATUM_4193714
|
||||
|
||||
static void arch_dup_tlbbatch_mask(struct task_struct *dst)
|
||||
{
|
||||
/*
|
||||
* Clear the inherited cpumask with memset() to cover both cases where
|
||||
* cpumask_var_t is a pointer or an array. It will be allocated lazily
|
||||
* in sme_dvmsync_add_pending() if CPUMASK_OFFSTACK=y.
|
||||
*/
|
||||
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
|
||||
memset(&dst->tlb_ubc.arch.cpumask, 0,
|
||||
sizeof(dst->tlb_ubc.arch.cpumask));
|
||||
}
|
||||
|
||||
static void arch_release_tlbbatch_mask(struct task_struct *tsk)
|
||||
{
|
||||
if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
|
||||
free_cpumask_var(tsk->tlb_ubc.arch.cpumask);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void arch_dup_tlbbatch_mask(struct task_struct *dst)
|
||||
{
|
||||
}
|
||||
|
||||
static void arch_release_tlbbatch_mask(struct task_struct *tsk)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARM64_ERRATUM_4193714 */
|
||||
|
||||
void arch_release_task_struct(struct task_struct *tsk)
|
||||
{
|
||||
arch_release_tlbbatch_mask(tsk);
|
||||
fpsimd_release_task(tsk);
|
||||
}
|
||||
|
||||
|
|
@ -357,6 +391,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
|
|||
|
||||
*dst = *src;
|
||||
|
||||
arch_dup_tlbbatch_mask(dst);
|
||||
|
||||
/*
|
||||
* Drop stale reference to src's sve_state and convert dst to
|
||||
* non-streaming FPSIMD mode.
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ __do_compat_cache_op(unsigned long start, unsigned long end)
|
|||
* We pick the reserved-ASID to minimise the impact.
|
||||
*/
|
||||
__tlbi(aside1is, 0UL);
|
||||
__tlbi_sync_s1ish();
|
||||
__tlbi_sync_s1ish(current->mm);
|
||||
}
|
||||
|
||||
ret = caches_clean_inval_user_pou(start, start + chunk);
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ WORKAROUND_2077057
|
|||
WORKAROUND_2457168
|
||||
WORKAROUND_2645198
|
||||
WORKAROUND_2658417
|
||||
WORKAROUND_4193714
|
||||
WORKAROUND_4311569
|
||||
WORKAROUND_AMPERE_AC03_CPU_38
|
||||
WORKAROUND_AMPERE_AC04_CPU_23
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#include "mpam_internal.h"
|
||||
|
||||
DECLARE_WAIT_QUEUE_HEAD(resctrl_mon_ctx_waiters);
|
||||
static DECLARE_WAIT_QUEUE_HEAD(resctrl_mon_ctx_waiters);
|
||||
|
||||
/*
|
||||
* The classes we've picked to map to resctrl resources, wrapped
|
||||
|
|
@ -220,10 +220,18 @@ int resctrl_arch_set_cdp_enabled(enum resctrl_res_level rid, bool enable)
|
|||
if (cdp_enabled && !mpam_resctrl_controls[RDT_RESOURCE_MBA].cdp_enabled)
|
||||
mpam_resctrl_controls[RDT_RESOURCE_MBA].resctrl_res.alloc_capable = false;
|
||||
|
||||
/*
|
||||
* If resctrl has attempted to enable CDP on MBA, re-enable MBA as two
|
||||
* configurations will be provided so there is no aliasing problem.
|
||||
*/
|
||||
if (mpam_resctrl_controls[RDT_RESOURCE_MBA].cdp_enabled &&
|
||||
mpam_resctrl_controls[RDT_RESOURCE_MBA].class)
|
||||
mpam_resctrl_controls[RDT_RESOURCE_MBA].resctrl_res.alloc_capable = true;
|
||||
|
||||
/* On unmount when CDP is disabled, re-enable MBA */
|
||||
if (!cdp_enabled && mpam_resctrl_controls[RDT_RESOURCE_MBA].class)
|
||||
mpam_resctrl_controls[RDT_RESOURCE_MBA].resctrl_res.alloc_capable = true;
|
||||
|
||||
if (enable) {
|
||||
if (mpam_partid_max < 1)
|
||||
return -EINVAL;
|
||||
|
|
@ -1399,7 +1407,7 @@ mpam_resctrl_alloc_domain(unsigned int cpu, struct mpam_resctrl_res *res)
|
|||
}
|
||||
|
||||
if (r->mon_capable) {
|
||||
struct mpam_component *any_mon_comp;
|
||||
struct mpam_component *any_mon_comp = NULL;
|
||||
struct mpam_resctrl_mon *mon;
|
||||
enum resctrl_event_id eventid;
|
||||
|
||||
|
|
|
|||
|
|
@ -157,7 +157,8 @@ static int arm_cca_report_new(struct tsm_report *report, void *data)
|
|||
} while (info.result == RSI_INCOMPLETE &&
|
||||
info.offset < RSI_GRANULE_SIZE);
|
||||
|
||||
if (info.result != RSI_SUCCESS) {
|
||||
/* Break out in case of failure */
|
||||
if (info.result != RSI_SUCCESS && info.result != RSI_INCOMPLETE) {
|
||||
ret = -ENXIO;
|
||||
token_size = 0;
|
||||
goto exit_free_granule_page;
|
||||
|
|
|
|||
Loading…
Reference in New Issue