Skip to content

Commit 35159b5

Browse files
npigginmpe
authored andcommitted
powerpc/64s: make HPTE lock and native_tlbie_lock irq-safe
With kfence enabled, there are several cases where HPTE and TLBIE locks are called from softirq context, for example: WARNING: inconsistent lock state 6.0.0-11845-g0cbbc95b12ac #1 Tainted: G N -------------------------------- inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage. swapper/0/1 [HC0[0]:SC0[0]:HE1:SE1] takes: c000000002734de8 (native_tlbie_lock){+.?.}-{2:2}, at: .native_hpte_updateboltedpp+0x1a4/0x600 {IN-SOFTIRQ-W} state was registered at: .lock_acquire+0x20c/0x520 ._raw_spin_lock+0x4c/0x70 .native_hpte_invalidate+0x62c/0x840 .hash__kernel_map_pages+0x450/0x640 .kfence_protect+0x58/0xc0 .kfence_guarded_free+0x374/0x5a0 .__slab_free+0x3d0/0x630 .put_cred_rcu+0xcc/0x120 .rcu_core+0x3c4/0x14e0 .__do_softirq+0x1dc/0x7dc .do_softirq_own_stack+0x40/0x60 Fix this by consistently disabling irqs while taking either of these locks. Don't just disable bh because several of the more common cases already disable irqs, so this just makes the locks always irq-safe. Reported-by: Guenter Roeck <[email protected]> Signed-off-by: Nicholas Piggin <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent be83d54 commit 35159b5

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

arch/powerpc/mm/book3s64/hash_native.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,11 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn,
268268
{
269269
struct hash_pte *hptep = htab_address + hpte_group;
270270
unsigned long hpte_v, hpte_r;
271+
unsigned long flags;
271272
int i;
272273

274+
local_irq_save(flags);
275+
273276
if (!(vflags & HPTE_V_BOLTED)) {
274277
DBG_LOW(" insert(group=%lx, vpn=%016lx, pa=%016lx,"
275278
" rflags=%lx, vflags=%lx, psize=%d)\n",
@@ -288,8 +291,10 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn,
288291
hptep++;
289292
}
290293

291-
if (i == HPTES_PER_GROUP)
294+
if (i == HPTES_PER_GROUP) {
295+
local_irq_restore(flags);
292296
return -1;
297+
}
293298

294299
hpte_v = hpte_encode_v(vpn, psize, apsize, ssize) | vflags | HPTE_V_VALID;
295300
hpte_r = hpte_encode_r(pa, psize, apsize) | rflags;
@@ -304,18 +309,20 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn,
304309
hpte_v = hpte_old_to_new_v(hpte_v);
305310
}
306311

307-
release_hpte_lock();
308312
hptep->r = cpu_to_be64(hpte_r);
309313
/* Guarantee the second dword is visible before the valid bit */
310314
eieio();
311315
/*
312316
* Now set the first dword including the valid bit
313317
* NOTE: this also unlocks the hpte
314318
*/
319+
release_hpte_lock();
315320
hptep->v = cpu_to_be64(hpte_v);
316321

317322
__asm__ __volatile__ ("ptesync" : : : "memory");
318323

324+
local_irq_restore(flags);
325+
319326
return i | (!!(vflags & HPTE_V_SECONDARY) << 3);
320327
}
321328

@@ -366,6 +373,9 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
366373
struct hash_pte *hptep = htab_address + slot;
367374
unsigned long hpte_v, want_v;
368375
int ret = 0, local = 0;
376+
unsigned long irqflags;
377+
378+
local_irq_save(irqflags);
369379

370380
want_v = hpte_encode_avpn(vpn, bpsize, ssize);
371381

@@ -409,6 +419,8 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp,
409419
if (!(flags & HPTE_NOHPTE_UPDATE))
410420
tlbie(vpn, bpsize, apsize, ssize, local);
411421

422+
local_irq_restore(irqflags);
423+
412424
return ret;
413425
}
414426

@@ -472,6 +484,9 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
472484
unsigned long vsid;
473485
long slot;
474486
struct hash_pte *hptep;
487+
unsigned long flags;
488+
489+
local_irq_save(flags);
475490

476491
vsid = get_kernel_vsid(ea, ssize);
477492
vpn = hpt_vpn(ea, vsid, ssize);
@@ -490,6 +505,8 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea,
490505
* actual page size will be same.
491506
*/
492507
tlbie(vpn, psize, psize, ssize, 0);
508+
509+
local_irq_restore(flags);
493510
}
494511

495512
/*
@@ -503,6 +520,9 @@ static int native_hpte_removebolted(unsigned long ea, int psize, int ssize)
503520
unsigned long vsid;
504521
long slot;
505522
struct hash_pte *hptep;
523+
unsigned long flags;
524+
525+
local_irq_save(flags);
506526

507527
vsid = get_kernel_vsid(ea, ssize);
508528
vpn = hpt_vpn(ea, vsid, ssize);
@@ -520,6 +540,9 @@ static int native_hpte_removebolted(unsigned long ea, int psize, int ssize)
520540

521541
/* Invalidate the TLB */
522542
tlbie(vpn, psize, psize, ssize, 0);
543+
544+
local_irq_restore(flags);
545+
523546
return 0;
524547
}
525548

0 commit comments

Comments
 (0)