]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 10 Mar 2025 16:16:36 +0000 (17:16 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 10 Mar 2025 16:16:36 +0000 (17:16 +0100)
added patches:
kvm-e500-always-restore-irqs.patch
selftests-bpf-clean-up-open-coded-gettid-syscall-invocations.patch
uprobes-fix-race-in-uprobe_free_utask.patch
x86-mm-don-t-disable-pcid-when-invlpg-has-been-fixed-by-microcode.patch

queue-6.12/kvm-e500-always-restore-irqs.patch [new file with mode: 0644]
queue-6.12/selftests-bpf-clean-up-open-coded-gettid-syscall-invocations.patch [new file with mode: 0644]
queue-6.12/uprobes-fix-race-in-uprobe_free_utask.patch [new file with mode: 0644]
queue-6.12/x86-mm-don-t-disable-pcid-when-invlpg-has-been-fixed-by-microcode.patch [new file with mode: 0644]

diff --git a/queue-6.12/kvm-e500-always-restore-irqs.patch b/queue-6.12/kvm-e500-always-restore-irqs.patch
new file mode 100644 (file)
index 0000000..8236732
--- /dev/null
@@ -0,0 +1,42 @@
+From 87ecfdbc699cc95fac73291b52650283ddcf929d Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Sun, 12 Jan 2025 10:34:44 +0100
+Subject: KVM: e500: always restore irqs
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+commit 87ecfdbc699cc95fac73291b52650283ddcf929d upstream.
+
+If find_linux_pte fails, IRQs will not be restored.  This is unlikely
+to happen in practice since it would have been reported as hanging
+hosts, but it should of course be fixed anyway.
+
+Cc: stable@vger.kernel.org
+Reported-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/kvm/e500_mmu_host.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/powerpc/kvm/e500_mmu_host.c
++++ b/arch/powerpc/kvm/e500_mmu_host.c
+@@ -481,7 +481,6 @@ static inline int kvmppc_e500_shadow_map
+               if (pte_present(pte)) {
+                       wimg = (pte_val(pte) >> PTE_WIMGE_SHIFT) &
+                               MAS2_WIMGE_MASK;
+-                      local_irq_restore(flags);
+               } else {
+                       local_irq_restore(flags);
+                       pr_err_ratelimited("%s: pte not present: gfn %lx,pfn %lx\n",
+@@ -490,8 +489,9 @@ static inline int kvmppc_e500_shadow_map
+                       goto out;
+               }
+       }
+-      kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg);
++      local_irq_restore(flags);
++      kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg);
+       kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize,
+                               ref, gvaddr, stlbe);
diff --git a/queue-6.12/selftests-bpf-clean-up-open-coded-gettid-syscall-invocations.patch b/queue-6.12/selftests-bpf-clean-up-open-coded-gettid-syscall-invocations.patch
new file mode 100644 (file)
index 0000000..25ecf6e
--- /dev/null
@@ -0,0 +1,262 @@
+From 0e2fb011a0ba8e2258ce776fdf89fbd589c2a3a6 Mon Sep 17 00:00:00 2001
+From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Date: Mon, 4 Nov 2024 09:19:58 -0800
+Subject: selftests/bpf: Clean up open-coded gettid syscall invocations
+
+From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+
+commit 0e2fb011a0ba8e2258ce776fdf89fbd589c2a3a6 upstream.
+
+Availability of the gettid definition across glibc versions supported by
+BPF selftests is not certain. Currently, all users in the tree open-code
+syscall to gettid. Convert them to a common macro definition.
+
+Reviewed-by: Jiri Olsa <jolsa@kernel.org>
+Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Link: https://lore.kernel.org/r/20241104171959.2938862-3-memxor@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Reported-by: Colm Harrington <colm.harrington@oracle.com>
+Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
+---
+ tools/testing/selftests/bpf/benchs/bench_trigger.c           |    3 ++-
+ tools/testing/selftests/bpf/bpf_util.h                       |    9 +++++++++
+ tools/testing/selftests/bpf/map_tests/task_storage_map.c     |    3 ++-
+ tools/testing/selftests/bpf/prog_tests/bpf_cookie.c          |    2 +-
+ tools/testing/selftests/bpf/prog_tests/bpf_iter.c            |    6 +++---
+ tools/testing/selftests/bpf/prog_tests/cgrp_local_storage.c  |   10 +++++-----
+ tools/testing/selftests/bpf/prog_tests/core_reloc.c          |    2 +-
+ tools/testing/selftests/bpf/prog_tests/linked_funcs.c        |    2 +-
+ tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c |    2 +-
+ tools/testing/selftests/bpf/prog_tests/rcu_read_lock.c       |    4 ++--
+ tools/testing/selftests/bpf/prog_tests/task_local_storage.c  |    8 ++++----
+ tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c   |    2 +-
+ 12 files changed, 32 insertions(+), 21 deletions(-)
+
+--- a/tools/testing/selftests/bpf/benchs/bench_trigger.c
++++ b/tools/testing/selftests/bpf/benchs/bench_trigger.c
+@@ -4,6 +4,7 @@
+ #include <argp.h>
+ #include <unistd.h>
+ #include <stdint.h>
++#include "bpf_util.h"
+ #include "bench.h"
+ #include "trigger_bench.skel.h"
+ #include "trace_helpers.h"
+@@ -72,7 +73,7 @@ static __always_inline void inc_counter(
+       unsigned slot;
+       if (unlikely(tid == 0))
+-              tid = syscall(SYS_gettid);
++              tid = sys_gettid();
+       /* multiplicative hashing, it's fast */
+       slot = 2654435769U * tid;
+--- a/tools/testing/selftests/bpf/bpf_util.h
++++ b/tools/testing/selftests/bpf/bpf_util.h
+@@ -6,6 +6,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <errno.h>
++#include <syscall.h>
+ #include <bpf/libbpf.h> /* libbpf_num_possible_cpus */
+ static inline unsigned int bpf_num_possible_cpus(void)
+@@ -59,4 +60,12 @@ static inline void bpf_strlcpy(char *dst
+       (offsetof(TYPE, MEMBER) + sizeof_field(TYPE, MEMBER))
+ #endif
++/* Availability of gettid across glibc versions is hit-and-miss, therefore
++ * fallback to syscall in this macro and use it everywhere.
++ */
++#ifndef sys_gettid
++#define sys_gettid() syscall(SYS_gettid)
++#endif
++
++
+ #endif /* __BPF_UTIL__ */
+--- a/tools/testing/selftests/bpf/map_tests/task_storage_map.c
++++ b/tools/testing/selftests/bpf/map_tests/task_storage_map.c
+@@ -12,6 +12,7 @@
+ #include <bpf/bpf.h>
+ #include <bpf/libbpf.h>
++#include "bpf_util.h"
+ #include "test_maps.h"
+ #include "task_local_storage_helpers.h"
+ #include "read_bpf_task_storage_busy.skel.h"
+@@ -115,7 +116,7 @@ void test_task_storage_map_stress_lookup
+       CHECK(err, "attach", "error %d\n", err);
+       /* Trigger program */
+-      syscall(SYS_gettid);
++      sys_gettid();
+       skel->bss->pid = 0;
+       CHECK(skel->bss->busy != 0, "bad bpf_task_storage_busy", "got %d\n", skel->bss->busy);
+--- a/tools/testing/selftests/bpf/prog_tests/bpf_cookie.c
++++ b/tools/testing/selftests/bpf/prog_tests/bpf_cookie.c
+@@ -690,7 +690,7 @@ void test_bpf_cookie(void)
+       if (!ASSERT_OK_PTR(skel, "skel_open"))
+               return;
+-      skel->bss->my_tid = syscall(SYS_gettid);
++      skel->bss->my_tid = sys_gettid();
+       if (test__start_subtest("kprobe"))
+               kprobe_subtest(skel);
+--- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
++++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
+@@ -226,7 +226,7 @@ static void test_task_common_nocheck(str
+       ASSERT_OK(pthread_create(&thread_id, NULL, &do_nothing_wait, NULL),
+                 "pthread_create");
+-      skel->bss->tid = syscall(SYS_gettid);
++      skel->bss->tid = sys_gettid();
+       do_dummy_read_opts(skel->progs.dump_task, opts);
+@@ -255,10 +255,10 @@ static void *run_test_task_tid(void *arg
+       union bpf_iter_link_info linfo;
+       int num_unknown_tid, num_known_tid;
+-      ASSERT_NEQ(getpid(), syscall(SYS_gettid), "check_new_thread_id");
++      ASSERT_NEQ(getpid(), sys_gettid(), "check_new_thread_id");
+       memset(&linfo, 0, sizeof(linfo));
+-      linfo.task.tid = syscall(SYS_gettid);
++      linfo.task.tid = sys_gettid();
+       opts.link_info = &linfo;
+       opts.link_info_len = sizeof(linfo);
+       test_task_common(&opts, 0, 1);
+--- a/tools/testing/selftests/bpf/prog_tests/cgrp_local_storage.c
++++ b/tools/testing/selftests/bpf/prog_tests/cgrp_local_storage.c
+@@ -63,14 +63,14 @@ static void test_tp_btf(int cgroup_fd)
+       if (!ASSERT_OK(err, "map_delete_elem"))
+               goto out;
+-      skel->bss->target_pid = syscall(SYS_gettid);
++      skel->bss->target_pid = sys_gettid();
+       err = cgrp_ls_tp_btf__attach(skel);
+       if (!ASSERT_OK(err, "skel_attach"))
+               goto out;
+-      syscall(SYS_gettid);
+-      syscall(SYS_gettid);
++      sys_gettid();
++      sys_gettid();
+       skel->bss->target_pid = 0;
+@@ -154,7 +154,7 @@ static void test_recursion(int cgroup_fd
+               goto out;
+       /* trigger sys_enter, make sure it does not cause deadlock */
+-      syscall(SYS_gettid);
++      sys_gettid();
+ out:
+       cgrp_ls_recursion__destroy(skel);
+@@ -224,7 +224,7 @@ static void test_yes_rcu_lock(__u64 cgro
+               return;
+       CGROUP_MODE_SET(skel);
+-      skel->bss->target_pid = syscall(SYS_gettid);
++      skel->bss->target_pid = sys_gettid();
+       bpf_program__set_autoload(skel->progs.yes_rcu_lock, true);
+       err = cgrp_ls_sleepable__load(skel);
+--- a/tools/testing/selftests/bpf/prog_tests/core_reloc.c
++++ b/tools/testing/selftests/bpf/prog_tests/core_reloc.c
+@@ -1010,7 +1010,7 @@ static void run_core_reloc_tests(bool us
+       struct data *data;
+       void *mmap_data = NULL;
+-      my_pid_tgid = getpid() | ((uint64_t)syscall(SYS_gettid) << 32);
++      my_pid_tgid = getpid() | ((uint64_t)sys_gettid() << 32);
+       for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
+               char btf_file[] = "/tmp/core_reloc.btf.XXXXXX";
+--- a/tools/testing/selftests/bpf/prog_tests/linked_funcs.c
++++ b/tools/testing/selftests/bpf/prog_tests/linked_funcs.c
+@@ -20,7 +20,7 @@ void test_linked_funcs(void)
+       bpf_program__set_autoload(skel->progs.handler1, true);
+       bpf_program__set_autoload(skel->progs.handler2, true);
+-      skel->rodata->my_tid = syscall(SYS_gettid);
++      skel->rodata->my_tid = sys_gettid();
+       skel->bss->syscall_id = SYS_getpgid;
+       err = linked_funcs__load(skel);
+--- a/tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c
++++ b/tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c
+@@ -23,7 +23,7 @@ static int get_pid_tgid(pid_t *pid, pid_
+       struct stat st;
+       int err;
+-      *pid = syscall(SYS_gettid);
++      *pid = sys_gettid();
+       *tgid = getpid();
+       err = stat("/proc/self/ns/pid", &st);
+--- a/tools/testing/selftests/bpf/prog_tests/rcu_read_lock.c
++++ b/tools/testing/selftests/bpf/prog_tests/rcu_read_lock.c
+@@ -21,7 +21,7 @@ static void test_success(void)
+       if (!ASSERT_OK_PTR(skel, "skel_open"))
+               return;
+-      skel->bss->target_pid = syscall(SYS_gettid);
++      skel->bss->target_pid = sys_gettid();
+       bpf_program__set_autoload(skel->progs.get_cgroup_id, true);
+       bpf_program__set_autoload(skel->progs.task_succ, true);
+@@ -58,7 +58,7 @@ static void test_rcuptr_acquire(void)
+       if (!ASSERT_OK_PTR(skel, "skel_open"))
+               return;
+-      skel->bss->target_pid = syscall(SYS_gettid);
++      skel->bss->target_pid = sys_gettid();
+       bpf_program__set_autoload(skel->progs.task_acquire, true);
+       err = rcu_read_lock__load(skel);
+--- a/tools/testing/selftests/bpf/prog_tests/task_local_storage.c
++++ b/tools/testing/selftests/bpf/prog_tests/task_local_storage.c
+@@ -23,14 +23,14 @@ static void test_sys_enter_exit(void)
+       if (!ASSERT_OK_PTR(skel, "skel_open_and_load"))
+               return;
+-      skel->bss->target_pid = syscall(SYS_gettid);
++      skel->bss->target_pid = sys_gettid();
+       err = task_local_storage__attach(skel);
+       if (!ASSERT_OK(err, "skel_attach"))
+               goto out;
+-      syscall(SYS_gettid);
+-      syscall(SYS_gettid);
++      sys_gettid();
++      sys_gettid();
+       /* 3x syscalls: 1x attach and 2x gettid */
+       ASSERT_EQ(skel->bss->enter_cnt, 3, "enter_cnt");
+@@ -99,7 +99,7 @@ static void test_recursion(void)
+       /* trigger sys_enter, make sure it does not cause deadlock */
+       skel->bss->test_pid = getpid();
+-      syscall(SYS_gettid);
++      sys_gettid();
+       skel->bss->test_pid = 0;
+       task_ls_recursion__detach(skel);
+--- a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c
++++ b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c
+@@ -125,7 +125,7 @@ static void *child_thread(void *ctx)
+       struct child *child = ctx;
+       int c = 0, err;
+-      child->tid = syscall(SYS_gettid);
++      child->tid = sys_gettid();
+       /* let parent know we are ready */
+       err = write(child->c2p[1], &c, 1);
diff --git a/queue-6.12/uprobes-fix-race-in-uprobe_free_utask.patch b/queue-6.12/uprobes-fix-race-in-uprobe_free_utask.patch
new file mode 100644 (file)
index 0000000..947ec39
--- /dev/null
@@ -0,0 +1,85 @@
+From b583ef82b671c9a752fbe3e95bd4c1c51eab764d Mon Sep 17 00:00:00 2001
+From: Jiri Olsa <jolsa@kernel.org>
+Date: Thu, 9 Jan 2025 15:14:40 +0100
+Subject: uprobes: Fix race in uprobe_free_utask
+
+From: Jiri Olsa <jolsa@kernel.org>
+
+commit b583ef82b671c9a752fbe3e95bd4c1c51eab764d upstream.
+
+Max Makarov reported kernel panic [1] in perf user callchain code.
+
+The reason for that is the race between uprobe_free_utask and bpf
+profiler code doing the perf user stack unwind and is triggered
+within uprobe_free_utask function:
+  - after current->utask is freed and
+  - before current->utask is set to NULL
+
+ general protection fault, probably for non-canonical address 0x9e759c37ee555c76: 0000 [#1] SMP PTI
+ RIP: 0010:is_uprobe_at_func_entry+0x28/0x80
+ ...
+  ? die_addr+0x36/0x90
+  ? exc_general_protection+0x217/0x420
+  ? asm_exc_general_protection+0x26/0x30
+  ? is_uprobe_at_func_entry+0x28/0x80
+  perf_callchain_user+0x20a/0x360
+  get_perf_callchain+0x147/0x1d0
+  bpf_get_stackid+0x60/0x90
+  bpf_prog_9aac297fb833e2f5_do_perf_event+0x434/0x53b
+  ? __smp_call_single_queue+0xad/0x120
+  bpf_overflow_handler+0x75/0x110
+  ...
+  asm_sysvec_apic_timer_interrupt+0x1a/0x20
+ RIP: 0010:__kmem_cache_free+0x1cb/0x350
+ ...
+  ? uprobe_free_utask+0x62/0x80
+  ? acct_collect+0x4c/0x220
+  uprobe_free_utask+0x62/0x80
+  mm_release+0x12/0xb0
+  do_exit+0x26b/0xaa0
+  __x64_sys_exit+0x1b/0x20
+  do_syscall_64+0x5a/0x80
+
+It can be easily reproduced by running following commands in
+separate terminals:
+
+  # while :; do bpftrace -e 'uprobe:/bin/ls:_start  { printf("hit\n"); }' -c ls; done
+  # bpftrace -e 'profile:hz:100000 { @[ustack()] = count(); }'
+
+Fixing this by making sure current->utask pointer is set to NULL
+before we start to release the utask object.
+
+[1] https://github.com/grafana/pyroscope/issues/3673
+
+Fixes: cfa7f3d2c526 ("perf,x86: avoid missing caller address in stack traces captured in uprobe")
+Reported-by: Max Makarov <maxpain@linux.com>
+Signed-off-by: Jiri Olsa <jolsa@kernel.org>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Acked-by: Oleg Nesterov <oleg@redhat.com>
+Acked-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/r/20250109141440.2692173-1-jolsa@kernel.org
+[Christian Simon: Rebased for 6.12.y, due to mainline change https://lore.kernel.org/all/20240929144239.GA9475@redhat.com/]
+Signed-off-by: Christian Simon <simon@swine.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/events/uprobes.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/events/uprobes.c
++++ b/kernel/events/uprobes.c
+@@ -1775,6 +1775,7 @@ void uprobe_free_utask(struct task_struc
+       if (!utask)
+               return;
++      t->utask = NULL;
+       if (utask->active_uprobe)
+               put_uprobe(utask->active_uprobe);
+@@ -1784,7 +1785,6 @@ void uprobe_free_utask(struct task_struc
+       xol_free_insn_slot(t);
+       kfree(utask);
+-      t->utask = NULL;
+ }
+ /*
diff --git a/queue-6.12/x86-mm-don-t-disable-pcid-when-invlpg-has-been-fixed-by-microcode.patch b/queue-6.12/x86-mm-don-t-disable-pcid-when-invlpg-has-been-fixed-by-microcode.patch
new file mode 100644 (file)
index 0000000..a1578b2
--- /dev/null
@@ -0,0 +1,79 @@
+From f24f669d03f884a6ef95cca84317d0f329e93961 Mon Sep 17 00:00:00 2001
+From: Xi Ruoyao <xry111@xry111.site>
+Date: Wed, 22 May 2024 10:06:24 +0800
+Subject: x86/mm: Don't disable PCID when INVLPG has been fixed by microcode
+
+From: Xi Ruoyao <xry111@xry111.site>
+
+commit f24f669d03f884a6ef95cca84317d0f329e93961 upstream.
+
+Per the "Processor Specification Update" documentations referred by
+the intel-microcode-20240312 release note, this microcode release has
+fixed the issue for all affected models.
+
+So don't disable PCID if the microcode is new enough.  The precise
+minimum microcode revision fixing the issue was provided by Pawan
+Intel.
+
+[ dhansen: comment and changelog tweaks ]
+
+Signed-off-by: Xi Ruoyao <xry111@xry111.site>
+Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
+Acked-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Link: https://lore.kernel.org/all/168436059559.404.13934972543631851306.tip-bot2@tip-bot2/
+Link: https://github.com/intel/Intel-Linux-Processor-Microcode-Data-Files/releases/tag/microcode-20240312
+Link: https://cdrdv2.intel.com/v1/dl/getContent/740518 # RPL042, rev. 13
+Link: https://cdrdv2.intel.com/v1/dl/getContent/682436 # ADL063, rev. 24
+Link: https://lore.kernel.org/all/20240325231300.qrltbzf6twm43ftb@desk/
+Link: https://lore.kernel.org/all/20240522020625.69418-1-xry111%40xry111.site
+Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/mm/init.c |   23 ++++++++++++++---------
+ 1 file changed, 14 insertions(+), 9 deletions(-)
+
+--- a/arch/x86/mm/init.c
++++ b/arch/x86/mm/init.c
+@@ -263,28 +263,33 @@ static void __init probe_page_size_mask(
+ }
+ /*
+- * INVLPG may not properly flush Global entries
+- * on these CPUs when PCIDs are enabled.
++ * INVLPG may not properly flush Global entries on
++ * these CPUs.  New microcode fixes the issue.
+  */
+ static const struct x86_cpu_id invlpg_miss_ids[] = {
+-      X86_MATCH_VFM(INTEL_ALDERLAKE,      0),
+-      X86_MATCH_VFM(INTEL_ALDERLAKE_L,    0),
+-      X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, 0),
+-      X86_MATCH_VFM(INTEL_RAPTORLAKE,     0),
+-      X86_MATCH_VFM(INTEL_RAPTORLAKE_P,   0),
+-      X86_MATCH_VFM(INTEL_RAPTORLAKE_S,   0),
++      X86_MATCH_VFM(INTEL_ALDERLAKE,      0x2e),
++      X86_MATCH_VFM(INTEL_ALDERLAKE_L,    0x42c),
++      X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, 0x11),
++      X86_MATCH_VFM(INTEL_RAPTORLAKE,     0x118),
++      X86_MATCH_VFM(INTEL_RAPTORLAKE_P,   0x4117),
++      X86_MATCH_VFM(INTEL_RAPTORLAKE_S,   0x2e),
+       {}
+ };
+ static void setup_pcid(void)
+ {
++      const struct x86_cpu_id *invlpg_miss_match;
++
+       if (!IS_ENABLED(CONFIG_X86_64))
+               return;
+       if (!boot_cpu_has(X86_FEATURE_PCID))
+               return;
+-      if (x86_match_cpu(invlpg_miss_ids)) {
++      invlpg_miss_match = x86_match_cpu(invlpg_miss_ids);
++
++      if (invlpg_miss_match &&
++          boot_cpu_data.microcode < invlpg_miss_match->driver_data) {
+               pr_info("Incomplete global flushes, disabling PCID");
+               setup_clear_cpu_cap(X86_FEATURE_PCID);
+               return;