40fe1917ea
[ 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: 06220d78f24a ("powerpc/pseries: Introduce rwlock to gatekeep DTLB usage") Tested-by: Kajol Jain <kjain@linux.ibm.com> Reviewed-by: Nysal Jan K.A <nysal@linux.ibm.com> Reviewed-by: Kajol Jain <kjain@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://patch.msgid.link/20240819122401.513203-1-mpe@ellerman.id.au Signed-off-by: Sasha Levin <sashal@kernel.org>
52 lines
1.5 KiB
C
Executable file
52 lines
1.5 KiB
C
Executable file
#ifndef _ASM_POWERPC_DTL_H
|
|
#define _ASM_POWERPC_DTL_H
|
|
|
|
#include <linux/rwsem.h>
|
|
#include <asm/lppaca.h>
|
|
|
|
/*
|
|
* Layout of entries in the hypervisor's dispatch trace log buffer.
|
|
*/
|
|
struct dtl_entry {
|
|
u8 dispatch_reason;
|
|
u8 preempt_reason;
|
|
__be16 processor_id;
|
|
__be32 enqueue_to_dispatch_time;
|
|
__be32 ready_to_enqueue_time;
|
|
__be32 waiting_to_ready_time;
|
|
__be64 timebase;
|
|
__be64 fault_addr;
|
|
__be64 srr0;
|
|
__be64 srr1;
|
|
};
|
|
|
|
#define DISPATCH_LOG_BYTES 4096 /* bytes per cpu */
|
|
#define N_DISPATCH_LOG (DISPATCH_LOG_BYTES / sizeof(struct dtl_entry))
|
|
|
|
/*
|
|
* Dispatch trace log event enable mask:
|
|
* 0x1: voluntary virtual processor waits
|
|
* 0x2: time-slice preempts
|
|
* 0x4: virtual partition memory page faults
|
|
*/
|
|
#define DTL_LOG_CEDE 0x1
|
|
#define DTL_LOG_PREEMPT 0x2
|
|
#define DTL_LOG_FAULT 0x4
|
|
#define DTL_LOG_ALL (DTL_LOG_CEDE | DTL_LOG_PREEMPT | DTL_LOG_FAULT)
|
|
|
|
extern struct kmem_cache *dtl_cache;
|
|
extern struct rw_semaphore dtl_access_lock;
|
|
|
|
/*
|
|
* When CONFIG_VIRT_CPU_ACCOUNTING_NATIVE = y, the cpu accounting code controls
|
|
* reading from the dispatch trace log. If other code wants to consume
|
|
* DTL entries, it can set this pointer to a function that will get
|
|
* called once for each DTL entry that gets processed.
|
|
*/
|
|
extern void (*dtl_consumer)(struct dtl_entry *entry, u64 index);
|
|
|
|
extern void register_dtl_buffer(int cpu);
|
|
extern void alloc_dtl_buffers(unsigned long *time_limit);
|
|
extern long hcall_vphn(unsigned long cpu, u64 flags, __be32 *associativity);
|
|
|
|
#endif /* _ASM_POWERPC_DTL_H */
|