Skip to content

Commit dcd3c0b

Browse files
mpesfX-bot
authored andcommitted
powerpc/pseries: Fix dtl_access_lock to be a rw_semaphore
[ Upstream commit cadae3a45d23aa4f6485938a67cbc47aaaa25e38 ] The dtl_access_lock needs to be a rw_sempahore, a sleeping lock, because the code calls kmalloc() while holding it, which can sleep: # echo 1 > /proc/powerpc/vcpudispatch_stats BUG: sleeping function called from invalid context at include/linux/sched/mm.h:337 in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 199, name: sh preempt_count: 1, expected: 0 3 locks held by sh/199: #0: c00000000a0743f8 (sb_writers#3){.+.+}-{0:0}, at: vfs_write+0x324/0x438 #1: c0000000028c7058 (dtl_enable_mutex){+.+.}-{3:3}, at: vcpudispatch_stats_write+0xd4/0x5f4 #2: c0000000028c70b8 (dtl_access_lock){+.+.}-{2:2}, at: vcpudispatch_stats_write+0x220/0x5f4 CPU: 0 PID: 199 Comm: sh Not tainted 6.10.0-rc4 #152 Hardware name: IBM pSeries (emulated by qemu) POWER9 (raw) 0x4e1202 0xf000005 of:SLOF,HEAD hv:linux,kvm pSeries Call Trace: dump_stack_lvl+0x130/0x148 (unreliable) __might_resched+0x174/0x410 kmem_cache_alloc_noprof+0x340/0x3d0 alloc_dtl_buffers+0x124/0x1ac vcpudispatch_stats_write+0x2a8/0x5f4 proc_reg_write+0xf4/0x150 vfs_write+0xfc/0x438 ksys_write+0x88/0x148 system_call_exception+0x1c4/0x5a0 system_call_common+0xf4/0x258 Fixes: 06220d7 ("powerpc/pseries: Introduce rwlock to gatekeep DTLB usage") Tested-by: Kajol Jain <[email protected]> Reviewed-by: Nysal Jan K.A <[email protected]> Reviewed-by: Kajol Jain <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Sasha Levin <[email protected]>
1 parent adc6964 commit dcd3c0b

File tree

3 files changed

+10
-10
lines changed

3 files changed

+10
-10
lines changed

arch/powerpc/include/asm/dtl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#ifndef _ASM_POWERPC_DTL_H
22
#define _ASM_POWERPC_DTL_H
33

4+
#include <linux/rwsem.h>
45
#include <asm/lppaca.h>
5-
#include <linux/spinlock_types.h>
66

77
/*
88
* Layout of entries in the hypervisor's dispatch trace log buffer.
@@ -35,7 +35,7 @@ struct dtl_entry {
3535
#define DTL_LOG_ALL (DTL_LOG_CEDE | DTL_LOG_PREEMPT | DTL_LOG_FAULT)
3636

3737
extern struct kmem_cache *dtl_cache;
38-
extern rwlock_t dtl_access_lock;
38+
extern struct rw_semaphore dtl_access_lock;
3939

4040
/*
4141
* When CONFIG_VIRT_CPU_ACCOUNTING_NATIVE = y, the cpu accounting code controls

arch/powerpc/platforms/pseries/dtl.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,15 +181,15 @@ static int dtl_enable(struct dtl *dtl)
181181
return -EBUSY;
182182

183183
/* ensure there are no other conflicting dtl users */
184-
if (!read_trylock(&dtl_access_lock))
184+
if (!down_read_trylock(&dtl_access_lock))
185185
return -EBUSY;
186186

187187
n_entries = dtl_buf_entries;
188188
buf = kmem_cache_alloc_node(dtl_cache, GFP_KERNEL, cpu_to_node(dtl->cpu));
189189
if (!buf) {
190190
printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n",
191191
__func__, dtl->cpu);
192-
read_unlock(&dtl_access_lock);
192+
up_read(&dtl_access_lock);
193193
return -ENOMEM;
194194
}
195195

@@ -207,7 +207,7 @@ static int dtl_enable(struct dtl *dtl)
207207
spin_unlock(&dtl->lock);
208208

209209
if (rc) {
210-
read_unlock(&dtl_access_lock);
210+
up_read(&dtl_access_lock);
211211
kmem_cache_free(dtl_cache, buf);
212212
}
213213

@@ -222,7 +222,7 @@ static void dtl_disable(struct dtl *dtl)
222222
dtl->buf = NULL;
223223
dtl->buf_entries = 0;
224224
spin_unlock(&dtl->lock);
225-
read_unlock(&dtl_access_lock);
225+
up_read(&dtl_access_lock);
226226
}
227227

228228
/* file interface */

arch/powerpc/platforms/pseries/lpar.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ struct vcpu_dispatch_data {
166166
*/
167167
#define NR_CPUS_H NR_CPUS
168168

169-
DEFINE_RWLOCK(dtl_access_lock);
169+
DECLARE_RWSEM(dtl_access_lock);
170170
static DEFINE_PER_CPU(struct vcpu_dispatch_data, vcpu_disp_data);
171171
static DEFINE_PER_CPU(u64, dtl_entry_ridx);
172172
static DEFINE_PER_CPU(struct dtl_worker, dtl_workers);
@@ -460,7 +460,7 @@ static int dtl_worker_enable(unsigned long *time_limit)
460460
{
461461
int rc = 0, state;
462462

463-
if (!write_trylock(&dtl_access_lock)) {
463+
if (!down_write_trylock(&dtl_access_lock)) {
464464
rc = -EBUSY;
465465
goto out;
466466
}
@@ -476,7 +476,7 @@ static int dtl_worker_enable(unsigned long *time_limit)
476476
pr_err("vcpudispatch_stats: unable to setup workqueue for DTL processing\n");
477477
free_dtl_buffers(time_limit);
478478
reset_global_dtl_mask();
479-
write_unlock(&dtl_access_lock);
479+
up_write(&dtl_access_lock);
480480
rc = -EINVAL;
481481
goto out;
482482
}
@@ -491,7 +491,7 @@ static void dtl_worker_disable(unsigned long *time_limit)
491491
cpuhp_remove_state(dtl_worker_state);
492492
free_dtl_buffers(time_limit);
493493
reset_global_dtl_mask();
494-
write_unlock(&dtl_access_lock);
494+
up_write(&dtl_access_lock);
495495
}
496496

497497
static ssize_t vcpudispatch_stats_write(struct file *file, const char __user *p,

0 commit comments

Comments
 (0)