]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
x86/bugs: Add a Transient Scheduler Attacks mitigation
authorBorislav Petkov (AMD) <bp@alien8.de>
Wed, 11 Sep 2024 08:53:08 +0000 (10:53 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Jul 2025 13:57:50 +0000 (15:57 +0200)
commit d8010d4ba43e9f790925375a7de100604a5e2dba upstream.

Add the required features detection glue to bugs.c et all in order to
support the TSA mitigation.

Co-developed-by: Kim Phillips <kim.phillips@amd.com>
Signed-off-by: Kim Phillips <kim.phillips@amd.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
14 files changed:
Documentation/ABI/testing/sysfs-devices-system-cpu
Documentation/admin-guide/kernel-parameters.txt
arch/x86/Kconfig
arch/x86/include/asm/cpu.h
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/mwait.h
arch/x86/include/asm/nospec-branch.h
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/scattered.c
arch/x86/kvm/svm/vmenter.S
drivers/base/cpu.c
include/linux/cpu.h

index 1d657a6b1b53bd055407b1abc75e2eb49667672e..0301ac606cddd0d73cc3b0d9989fbdcc75956770 100644 (file)
@@ -524,6 +524,7 @@ What:               /sys/devices/system/cpu/vulnerabilities
                /sys/devices/system/cpu/vulnerabilities/spectre_v1
                /sys/devices/system/cpu/vulnerabilities/spectre_v2
                /sys/devices/system/cpu/vulnerabilities/srbds
+               /sys/devices/system/cpu/vulnerabilities/tsa
                /sys/devices/system/cpu/vulnerabilities/tsx_async_abort
 Date:          January 2018
 Contact:       Linux kernel mailing list <linux-kernel@vger.kernel.org>
index e5e7fddc962fc042f37a9c004c325daf7749175a..f12ba5c12b9166249268f836613d793ce13f1abf 100644 (file)
                        If not specified, "default" is used. In this case,
                        the RNG's choice is left to each individual trust source.
 
+       tsa=            [X86] Control mitigation for Transient Scheduler
+                       Attacks on AMD CPUs. Search the following in your
+                       favourite search engine for more details:
+
+                       "Technical guidance for mitigating transient scheduler
+                       attacks".
+
+                       off             - disable the mitigation
+                       on              - enable the mitigation (default)
+                       user            - mitigate only user/kernel transitions
+                       vm              - mitigate only guest/host transitions
+
+
        tsc=            Disable clocksource stability checks for TSC.
                        Format: <string>
                        [x86] reliable: mark tsc clocksource as reliable, this
index 026a5714f78f394d0856e81aa3433d7f90686573..4eca434fd80bef252bb7925bd96cb61834e1c129 100644 (file)
@@ -2528,6 +2528,15 @@ config MITIGATION_ITS
          disabled, mitigation cannot be enabled via cmdline.
          See <file:Documentation/admin-guide/hw-vuln/indirect-target-selection.rst>
 
+config MITIGATION_TSA
+       bool "Mitigate Transient Scheduler Attacks"
+       depends on CPU_SUP_AMD
+       default y
+       help
+         Enable mitigation for Transient Scheduler Attacks. TSA is a hardware
+         security vulnerability on AMD CPUs which can lead to forwarding of
+         invalid info to subsequent instructions and thus can affect their
+         timing and thereby cause a leakage.
 endif
 
 config ARCH_HAS_ADD_PAGES
index 33d41e350c79575e9815a0d9b6d681aaa4d1404a..5a7491f968cd6e542d1c722cdb023ff855392745 100644 (file)
@@ -72,4 +72,17 @@ void init_ia32_feat_ctl(struct cpuinfo_x86 *c);
 #else
 static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {}
 #endif
+
+union zen_patch_rev {
+       struct {
+               __u32 rev        : 8,
+                     stepping   : 4,
+                     model      : 4,
+                     __reserved : 4,
+                     ext_model  : 4,
+                     ext_fam    : 8;
+       };
+       __u32 ucode_rev;
+};
+
 #endif /* _ASM_X86_CPU_H */
index e2bf1cba02cdde7458f59d1e3e03075a339517af..63b84540cfb356c1bbe40f4ac8c0f9bdcc640c37 100644 (file)
 #define X86_FEATURE_SME_COHERENT       (19*32+10) /* "" AMD hardware-enforced cache coherency */
 
 #define X86_FEATURE_AUTOIBRS           (20*32+ 8) /* "" Automatic IBRS */
+#define X86_FEATURE_VERW_CLEAR         (20*32+ 10) /* "" The memory form of VERW mitigates TSA */
 #define X86_FEATURE_SBPB               (20*32+27) /* "" Selective Branch Prediction Barrier */
 #define X86_FEATURE_IBPB_BRTYPE                (20*32+28) /* "" MSR_PRED_CMD[IBPB] flushes all branch type predictions */
 #define X86_FEATURE_SRSO_NO            (20*32+29) /* "" CPU is not affected by SRSO */
 #define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* "" Clear branch history at vmexit using SW loop */
 #define X86_FEATURE_INDIRECT_THUNK_ITS (21*32 + 5) /* "" Use thunk for indirect branches in lower half of cacheline */
 
+#define X86_FEATURE_TSA_SQ_NO          (21*32+11) /* "" AMD CPU not vulnerable to TSA-SQ */
+#define X86_FEATURE_TSA_L1_NO          (21*32+12) /* "" AMD CPU not vulnerable to TSA-L1 */
+#define X86_FEATURE_CLEAR_CPU_BUF_VM   (21*32+13) /* "" Clear CPU buffers using VERW before VMRUN */
+
 /*
  * BUG word(s)
  */
 #define X86_BUG_IBPB_NO_RET            X86_BUG(1*32 + 4) /* "ibpb_no_ret" IBPB omits return target predictions */
 #define X86_BUG_ITS                    X86_BUG(1*32 + 5) /* CPU is affected by Indirect Target Selection */
 #define X86_BUG_ITS_NATIVE_ONLY                X86_BUG(1*32 + 6) /* CPU is affected by ITS, VMX is not affected */
+#define X86_BUG_TSA                    X86_BUG(1*32+ 9) /* "tsa" CPU is affected by Transient Scheduler Attacks */
 #endif /* _ASM_X86_CPUFEATURES_H */
index 35e20e8a7cc655dfc836394f6e7687b33bb9c77c..20b33e6370c31802472d3a2b07df2637c0ee5538 100644 (file)
@@ -79,7 +79,7 @@ static inline void __mwait(unsigned long eax, unsigned long ecx)
 static inline void __mwaitx(unsigned long eax, unsigned long ebx,
                            unsigned long ecx)
 {
-       /* No MDS buffer clear as this is AMD/HYGON only */
+       /* No need for TSA buffer clearing on AMD */
 
        /* "mwaitx %eax, %ebx, %ecx;" */
        asm volatile(".byte 0x0f, 0x01, 0xfb;"
index f651b0a1f5e2a1dfd740e7a3eb48d0ec59830c36..b62ce153a3c40a05c0b5954d802ce92f0fa6784d 100644 (file)
  * CFLAGS.ZF.
  * Note: Only the memory operand variant of VERW clears the CPU buffers.
  */
-.macro CLEAR_CPU_BUFFERS
-       ALTERNATIVE "jmp .Lskip_verw_\@", "", X86_FEATURE_CLEAR_CPU_BUF
+.macro __CLEAR_CPU_BUFFERS feature
+       ALTERNATIVE "jmp .Lskip_verw_\@", "", \feature
 #ifdef CONFIG_X86_64
        verw x86_verw_sel(%rip)
 #else
 .Lskip_verw_\@:
 .endm
 
+#define CLEAR_CPU_BUFFERS \
+       __CLEAR_CPU_BUFFERS X86_FEATURE_CLEAR_CPU_BUF
+
+#define VM_CLEAR_CPU_BUFFERS \
+       __CLEAR_CPU_BUFFERS X86_FEATURE_CLEAR_CPU_BUF_VM
+
 #ifdef CONFIG_X86_64
 .macro CLEAR_BRANCH_HISTORY
        ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP
@@ -464,7 +470,7 @@ static __always_inline void x86_clear_cpu_buffers(void)
 
 /**
  * x86_idle_clear_cpu_buffers - Buffer clearing support in idle for the MDS
- * vulnerability
+ * and TSA vulnerabilities.
  *
  * Clear CPU buffers if the corresponding static key is enabled
  */
index a8dc7fe5f1003b6b2f676a7082b3919c2742da6e..d409ba7fba85c410a500657dd44b1bbc17cad2fe 100644 (file)
@@ -582,6 +582,61 @@ static void early_init_amd_mc(struct cpuinfo_x86 *c)
 #endif
 }
 
+static bool amd_check_tsa_microcode(void)
+{
+       struct cpuinfo_x86 *c = &boot_cpu_data;
+       union zen_patch_rev p;
+       u32 min_rev = 0;
+
+       p.ext_fam       = c->x86 - 0xf;
+       p.model         = c->x86_model;
+       p.stepping      = c->x86_stepping;
+
+       if (c->x86 == 0x19) {
+               switch (p.ucode_rev >> 8) {
+               case 0xa0011:   min_rev = 0x0a0011d7; break;
+               case 0xa0012:   min_rev = 0x0a00123b; break;
+               case 0xa0082:   min_rev = 0x0a00820d; break;
+               case 0xa1011:   min_rev = 0x0a10114c; break;
+               case 0xa1012:   min_rev = 0x0a10124c; break;
+               case 0xa1081:   min_rev = 0x0a108109; break;
+               case 0xa2010:   min_rev = 0x0a20102e; break;
+               case 0xa2012:   min_rev = 0x0a201211; break;
+               case 0xa4041:   min_rev = 0x0a404108; break;
+               case 0xa5000:   min_rev = 0x0a500012; break;
+               case 0xa6012:   min_rev = 0x0a60120a; break;
+               case 0xa7041:   min_rev = 0x0a704108; break;
+               case 0xa7052:   min_rev = 0x0a705208; break;
+               case 0xa7080:   min_rev = 0x0a708008; break;
+               case 0xa70c0:   min_rev = 0x0a70c008; break;
+               case 0xaa002:   min_rev = 0x0aa00216; break;
+               default:
+                       pr_debug("%s: ucode_rev: 0x%x, current revision: 0x%x\n",
+                                __func__, p.ucode_rev, c->microcode);
+                       return false;
+               }
+       }
+
+       if (!min_rev)
+               return false;
+
+       return c->microcode >= min_rev;
+}
+
+static void tsa_init(struct cpuinfo_x86 *c)
+{
+       if (cpu_has(c, X86_FEATURE_HYPERVISOR))
+               return;
+
+       if (c->x86 == 0x19) {
+               if (amd_check_tsa_microcode())
+                       setup_force_cpu_cap(X86_FEATURE_VERW_CLEAR);
+       } else {
+               setup_force_cpu_cap(X86_FEATURE_TSA_SQ_NO);
+               setup_force_cpu_cap(X86_FEATURE_TSA_L1_NO);
+       }
+}
+
 static void bsp_init_amd(struct cpuinfo_x86 *c)
 {
        if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
@@ -687,6 +742,9 @@ static void early_detect_mem_encrypt(struct cpuinfo_x86 *c)
                if (!(msr & MSR_K7_HWCR_SMMLOCK))
                        goto clear_sev;
 
+
+       tsa_init(c);
+
                return;
 
 clear_all:
index 9d84a82dcdc944e015c9317607a65640e1589086..261aa716971d6efc30608b203b648238bb36212e 100644 (file)
@@ -49,6 +49,7 @@ static void __init l1d_flush_select_mitigation(void);
 static void __init gds_select_mitigation(void);
 static void __init srso_select_mitigation(void);
 static void __init its_select_mitigation(void);
+static void __init tsa_select_mitigation(void);
 
 /* The base value of the SPEC_CTRL MSR without task-specific bits set */
 u64 x86_spec_ctrl_base;
@@ -184,6 +185,7 @@ void __init cpu_select_mitigations(void)
        srso_select_mitigation();
        gds_select_mitigation();
        its_select_mitigation();
+       tsa_select_mitigation();
 }
 
 /*
@@ -2039,6 +2041,94 @@ static void update_mds_branch_idle(void)
 #define TAA_MSG_SMT "TAA CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/tsx_async_abort.html for more details.\n"
 #define MMIO_MSG_SMT "MMIO Stale Data CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/processor_mmio_stale_data.html for more details.\n"
 
+#undef pr_fmt
+#define pr_fmt(fmt)    "Transient Scheduler Attacks: " fmt
+
+enum tsa_mitigations {
+       TSA_MITIGATION_NONE,
+       TSA_MITIGATION_UCODE_NEEDED,
+       TSA_MITIGATION_USER_KERNEL,
+       TSA_MITIGATION_VM,
+       TSA_MITIGATION_FULL,
+};
+
+static const char * const tsa_strings[] = {
+       [TSA_MITIGATION_NONE]           = "Vulnerable",
+       [TSA_MITIGATION_UCODE_NEEDED]   = "Vulnerable: Clear CPU buffers attempted, no microcode",
+       [TSA_MITIGATION_USER_KERNEL]    = "Mitigation: Clear CPU buffers: user/kernel boundary",
+       [TSA_MITIGATION_VM]             = "Mitigation: Clear CPU buffers: VM",
+       [TSA_MITIGATION_FULL]           = "Mitigation: Clear CPU buffers",
+};
+
+static enum tsa_mitigations tsa_mitigation __ro_after_init =
+       IS_ENABLED(CONFIG_MITIGATION_TSA) ? TSA_MITIGATION_FULL : TSA_MITIGATION_NONE;
+
+static int __init tsa_parse_cmdline(char *str)
+{
+       if (!str)
+               return -EINVAL;
+
+       if (!strcmp(str, "off"))
+               tsa_mitigation = TSA_MITIGATION_NONE;
+       else if (!strcmp(str, "on"))
+               tsa_mitigation = TSA_MITIGATION_FULL;
+       else if (!strcmp(str, "user"))
+               tsa_mitigation = TSA_MITIGATION_USER_KERNEL;
+       else if (!strcmp(str, "vm"))
+               tsa_mitigation = TSA_MITIGATION_VM;
+       else
+               pr_err("Ignoring unknown tsa=%s option.\n", str);
+
+       return 0;
+}
+early_param("tsa", tsa_parse_cmdline);
+
+static void __init tsa_select_mitigation(void)
+{
+       if (tsa_mitigation == TSA_MITIGATION_NONE)
+               return;
+
+       if (cpu_mitigations_off() || !boot_cpu_has_bug(X86_BUG_TSA)) {
+               tsa_mitigation = TSA_MITIGATION_NONE;
+               return;
+       }
+
+       if (!boot_cpu_has(X86_FEATURE_VERW_CLEAR))
+               tsa_mitigation = TSA_MITIGATION_UCODE_NEEDED;
+
+       switch (tsa_mitigation) {
+       case TSA_MITIGATION_USER_KERNEL:
+               setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF);
+               break;
+
+       case TSA_MITIGATION_VM:
+               setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF_VM);
+               break;
+
+       case TSA_MITIGATION_UCODE_NEEDED:
+               if (!boot_cpu_has(X86_FEATURE_HYPERVISOR))
+                       goto out;
+
+               pr_notice("Forcing mitigation on in a VM\n");
+
+               /*
+                * On the off-chance that microcode has been updated
+                * on the host, enable the mitigation in the guest just
+                * in case.
+                */
+               fallthrough;
+       case TSA_MITIGATION_FULL:
+               setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF);
+               setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF_VM);
+               break;
+       default:
+               break;
+       }
+
+out:
+       pr_info("%s\n", tsa_strings[tsa_mitigation]);
+}
+
 void cpu_bugs_smt_update(void)
 {
        mutex_lock(&spec_ctrl_mutex);
@@ -2092,6 +2182,24 @@ void cpu_bugs_smt_update(void)
                break;
        }
 
+       switch (tsa_mitigation) {
+       case TSA_MITIGATION_USER_KERNEL:
+       case TSA_MITIGATION_VM:
+       case TSA_MITIGATION_FULL:
+       case TSA_MITIGATION_UCODE_NEEDED:
+               /*
+                * TSA-SQ can potentially lead to info leakage between
+                * SMT threads.
+                */
+               if (sched_smt_active())
+                       static_branch_enable(&cpu_buf_idle_clear);
+               else
+                       static_branch_disable(&cpu_buf_idle_clear);
+               break;
+       case TSA_MITIGATION_NONE:
+               break;
+       }
+
        mutex_unlock(&spec_ctrl_mutex);
 }
 
@@ -3026,6 +3134,11 @@ static ssize_t srso_show_state(char *buf)
                          boot_cpu_has(X86_FEATURE_IBPB_BRTYPE) ? "" : ", no microcode");
 }
 
+static ssize_t tsa_show_state(char *buf)
+{
+       return sysfs_emit(buf, "%s\n", tsa_strings[tsa_mitigation]);
+}
+
 static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
                               char *buf, unsigned int bug)
 {
@@ -3087,6 +3200,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
        case X86_BUG_ITS:
                return its_show_state(buf);
 
+       case X86_BUG_TSA:
+               return tsa_show_state(buf);
+
        default:
                break;
        }
@@ -3171,4 +3287,9 @@ ssize_t cpu_show_indirect_target_selection(struct device *dev, struct device_att
 {
        return cpu_show_common(dev, attr, buf, X86_BUG_ITS);
 }
+
+ssize_t cpu_show_tsa(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       return cpu_show_common(dev, attr, buf, X86_BUG_TSA);
+}
 #endif
index 8db11483e1e151db382c65446c78322312973313..b16a773862368335d6bf29509e7ee1b6819430f8 100644 (file)
@@ -1146,6 +1146,8 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
 #define ITS            BIT(8)
 /* CPU is affected by Indirect Target Selection, but guest-host isolation is not affected */
 #define ITS_NATIVE_ONLY        BIT(9)
+/* CPU is affected by Transient Scheduler Attacks */
+#define TSA            BIT(10)
 
 static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
        VULNBL_INTEL_STEPPINGS(IVYBRIDGE,       X86_STEPPING_ANY,               SRBDS),
@@ -1193,7 +1195,7 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
        VULNBL_AMD(0x16, RETBLEED),
        VULNBL_AMD(0x17, RETBLEED | SMT_RSB | SRSO),
        VULNBL_HYGON(0x18, RETBLEED | SMT_RSB | SRSO),
-       VULNBL_AMD(0x19, SRSO),
+       VULNBL_AMD(0x19, SRSO | TSA),
        {}
 };
 
@@ -1398,6 +1400,16 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
                        setup_force_cpu_bug(X86_BUG_ITS_NATIVE_ONLY);
        }
 
+       if (c->x86_vendor == X86_VENDOR_AMD) {
+               if (!cpu_has(c, X86_FEATURE_TSA_SQ_NO) ||
+                   !cpu_has(c, X86_FEATURE_TSA_L1_NO)) {
+                       if (cpu_matches(cpu_vuln_blacklist, TSA) ||
+                           /* Enable bug on Zen guests to allow for live migration. */
+                           (cpu_has(c, X86_FEATURE_HYPERVISOR) && cpu_has(c, X86_FEATURE_ZEN)))
+                               setup_force_cpu_bug(X86_BUG_TSA);
+               }
+       }
+
        if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
                return;
 
index 0f5211087810c01ad19a9ebd97e869354b04aca5..dfcd3ed94c1cb5bb7d8d67308c247b3d2ab9bd9b 100644 (file)
@@ -44,6 +44,8 @@ static const struct cpuid_bit cpuid_bits[] = {
        { X86_FEATURE_CPB,              CPUID_EDX,  9, 0x80000007, 0 },
        { X86_FEATURE_PROC_FEEDBACK,    CPUID_EDX, 11, 0x80000007, 0 },
        { X86_FEATURE_MBA,              CPUID_EBX,  6, 0x80000008, 0 },
+       { X86_FEATURE_TSA_SQ_NO,        CPUID_ECX,  1, 0x80000021, 0 },
+       { X86_FEATURE_TSA_L1_NO,        CPUID_ECX,  2, 0x80000021, 0 },
        { 0, 0, 0, 0, 0 }
 };
 
index f960608555226476fd94fb89a7ebf072ff1bd14e..eeab012e4ee0203878204764df154e43b9e91286 100644 (file)
@@ -77,6 +77,9 @@ SYM_FUNC_START(__svm_vcpu_run)
        /* "POP" @vmcb to RAX. */
        pop %_ASM_AX
 
+       /* Clobbers EFLAGS.ZF */
+       VM_CLEAR_CPU_BUFFERS
+
        /* Enter guest mode */
        sti
 
@@ -190,6 +193,9 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run)
        /* Move @vmcb to RAX. */
        mov %_ASM_ARG1, %_ASM_AX
 
+       /* Clobbers EFLAGS.ZF */
+       VM_CLEAR_CPU_BUFFERS
+
        /* Enter guest mode */
        sti
 
index df196e0730972cc2bb435c01d938ce28ff5cbba0..0e7f7f54665df95ccd025a5397ca661923418df6 100644 (file)
@@ -601,6 +601,11 @@ ssize_t __weak cpu_show_indirect_target_selection(struct device *dev,
        return sysfs_emit(buf, "Not affected\n");
 }
 
+ssize_t __weak cpu_show_tsa(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       return sysfs_emit(buf, "Not affected\n");
+}
+
 static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
 static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
 static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
@@ -616,6 +621,7 @@ static DEVICE_ATTR(gather_data_sampling, 0444, cpu_show_gds, NULL);
 static DEVICE_ATTR(spec_rstack_overflow, 0444, cpu_show_spec_rstack_overflow, NULL);
 static DEVICE_ATTR(reg_file_data_sampling, 0444, cpu_show_reg_file_data_sampling, NULL);
 static DEVICE_ATTR(indirect_target_selection, 0444, cpu_show_indirect_target_selection, NULL);
+static DEVICE_ATTR(tsa, 0444, cpu_show_tsa, NULL);
 
 static struct attribute *cpu_root_vulnerabilities_attrs[] = {
        &dev_attr_meltdown.attr,
@@ -633,6 +639,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
        &dev_attr_spec_rstack_overflow.attr,
        &dev_attr_reg_file_data_sampling.attr,
        &dev_attr_indirect_target_selection.attr,
+       &dev_attr_tsa.attr,
        NULL
 };
 
index 87b5a176e8489756b0b5d174afc93328ee50233b..ab1b88b169828f30b94337df0758fd6e809c28b3 100644 (file)
@@ -78,6 +78,7 @@ extern ssize_t cpu_show_reg_file_data_sampling(struct device *dev,
                                               struct device_attribute *attr, char *buf);
 extern ssize_t cpu_show_indirect_target_selection(struct device *dev,
                                                  struct device_attribute *attr, char *buf);
+extern ssize_t cpu_show_tsa(struct device *dev, struct device_attribute *attr, char *buf);
 
 extern __printf(4, 5)
 struct device *cpu_device_create(struct device *parent, void *drvdata,