Skip to content

Commit 8439381

Browse files
committed
x86/mtrr: Prevent CPU hotplug lock recursion
Larry reported a CPU hotplug lock recursion in the MTRR code. ============================================ WARNING: possible recursive locking detected systemd-udevd/153 is trying to acquire lock: (cpu_hotplug_lock.rw_sem){.+.+.+}, at: [<c030fc26>] stop_machine+0x16/0x30 but task is already holding lock: (cpu_hotplug_lock.rw_sem){.+.+.+}, at: [<c0234353>] mtrr_add_page+0x83/0x470 .... cpus_read_lock+0x48/0x90 stop_machine+0x16/0x30 mtrr_add_page+0x18b/0x470 mtrr_add+0x3e/0x70 mtrr_add_page() holds the hotplug rwsem already and calls stop_machine() which acquires it again. Call stop_machine_cpuslocked() instead. Reported-and-tested-by: Larry Finger <[email protected]> Reported-by: Dmitry Vyukov <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1708140920250.1865@nanos Cc: "Paul E. McKenney" <[email protected]> Cc: Borislav Petkov <[email protected]>
1 parent b45e4c4 commit 8439381

File tree

1 file changed

+15
-3
lines changed
  • arch/x86/kernel/cpu/mtrr

1 file changed

+15
-3
lines changed

arch/x86/kernel/cpu/mtrr/main.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,18 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ
237237
stop_machine(mtrr_rendezvous_handler, &data, cpu_online_mask);
238238
}
239239

240+
static void set_mtrr_cpuslocked(unsigned int reg, unsigned long base,
241+
unsigned long size, mtrr_type type)
242+
{
243+
struct set_mtrr_data data = { .smp_reg = reg,
244+
.smp_base = base,
245+
.smp_size = size,
246+
.smp_type = type
247+
};
248+
249+
stop_machine_cpuslocked(mtrr_rendezvous_handler, &data, cpu_online_mask);
250+
}
251+
240252
static void set_mtrr_from_inactive_cpu(unsigned int reg, unsigned long base,
241253
unsigned long size, mtrr_type type)
242254
{
@@ -370,15 +382,15 @@ int mtrr_add_page(unsigned long base, unsigned long size,
370382
/* Search for an empty MTRR */
371383
i = mtrr_if->get_free_region(base, size, replace);
372384
if (i >= 0) {
373-
set_mtrr(i, base, size, type);
385+
set_mtrr_cpuslocked(i, base, size, type);
374386
if (likely(replace < 0)) {
375387
mtrr_usage_table[i] = 1;
376388
} else {
377389
mtrr_usage_table[i] = mtrr_usage_table[replace];
378390
if (increment)
379391
mtrr_usage_table[i]++;
380392
if (unlikely(replace != i)) {
381-
set_mtrr(replace, 0, 0, 0);
393+
set_mtrr_cpuslocked(replace, 0, 0, 0);
382394
mtrr_usage_table[replace] = 0;
383395
}
384396
}
@@ -506,7 +518,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
506518
goto out;
507519
}
508520
if (--mtrr_usage_table[reg] < 1)
509-
set_mtrr(reg, 0, 0, 0);
521+
set_mtrr_cpuslocked(reg, 0, 0, 0);
510522
error = reg;
511523
out:
512524
mutex_unlock(&mtrr_mutex);

0 commit comments

Comments
 (0)