Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[IA64] perfmon: make pfm_sysctl a global, and other cleanup

- make pfm_sysctl a global such that it is possible
to enable/disable debug printk in sampling formats
using PFM_DEBUG.

- remove unused pfm_debug_var variable

- fix a bug in pfm_handle_work where an BUG_ON() could
be triggered. There is a path where pfm_handle_work()
can be called with interrupts enabled, i.e., when
TIF_NEED_RESCHED is set. The fix correct the masking
and unmasking of interrupts in pfm_handle_work() such
that we restore the interrupt mask as it was upon entry.

signed-off-by: stephane eranian <eranian@hpl.hp.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>

authored by

Stephane Eranian and committed by
Tony Luck
4944930a 658b32ca

+42 -42
+28 -31
arch/ia64/kernel/perfmon.c
··· 480 480 #define PFM_CMD_ARG_MANY -1 /* cannot be zero */ 481 481 482 482 typedef struct { 483 - int debug; /* turn on/off debugging via syslog */ 484 - int debug_ovfl; /* turn on/off debug printk in overflow handler */ 485 - int fastctxsw; /* turn on/off fast (unsecure) ctxsw */ 486 - int expert_mode; /* turn on/off value checking */ 487 - int debug_pfm_read; 488 - } pfm_sysctl_t; 489 - 490 - typedef struct { 491 483 unsigned long pfm_spurious_ovfl_intr_count; /* keep track of spurious ovfl interrupts */ 492 484 unsigned long pfm_replay_ovfl_intr_count; /* keep track of replayed ovfl interrupts */ 493 485 unsigned long pfm_ovfl_intr_count; /* keep track of ovfl interrupts */ ··· 506 514 static pmu_config_t *pmu_conf; 507 515 508 516 /* sysctl() controls */ 509 - static pfm_sysctl_t pfm_sysctl; 510 - int pfm_debug_var; 517 + pfm_sysctl_t pfm_sysctl; 518 + EXPORT_SYMBOL(pfm_sysctl); 511 519 512 520 static ctl_table pfm_ctl_table[]={ 513 521 {1, "debug", &pfm_sysctl.debug, sizeof(int), 0666, NULL, &proc_dointvec, NULL,}, ··· 1568 1576 goto abort_locked; 1569 1577 } 1570 1578 1571 - DPRINT(("[%d] fd=%d type=%d\n", current->pid, msg->pfm_gen_msg.msg_ctx_fd, msg->pfm_gen_msg.msg_type)); 1579 + DPRINT(("fd=%d type=%d\n", msg->pfm_gen_msg.msg_ctx_fd, msg->pfm_gen_msg.msg_type)); 1572 1580 1573 1581 ret = -EFAULT; 1574 1582 if(copy_to_user(buf, msg, sizeof(pfm_msg_t)) == 0) ret = sizeof(pfm_msg_t); ··· 3687 3695 3688 3696 pfm_sysctl.debug = m == 0 ? 0 : 1; 3689 3697 3690 - pfm_debug_var = pfm_sysctl.debug; 3691 - 3692 3698 printk(KERN_INFO "perfmon debugging %s (timing reset)\n", pfm_sysctl.debug ? "on" : "off"); 3693 3699 3694 3700 if (m == 0) { ··· 4986 4996 } 4987 4997 4988 4998 static int pfm_ovfl_notify_user(pfm_context_t *ctx, unsigned long ovfl_pmds); 4989 - 4999 + /* 5000 + * pfm_handle_work() can be called with interrupts enabled 5001 + * (TIF_NEED_RESCHED) or disabled. The down_interruptible 5002 + * call may sleep, therefore we must re-enable interrupts 5003 + * to avoid deadlocks. It is safe to do so because this function 5004 + * is called ONLY when returning to user level (PUStk=1), in which case 5005 + * there is no risk of kernel stack overflow due to deep 5006 + * interrupt nesting. 5007 + */ 4990 5008 void 4991 5009 pfm_handle_work(void) 4992 5010 { 4993 5011 pfm_context_t *ctx; 4994 5012 struct pt_regs *regs; 4995 - unsigned long flags; 5013 + unsigned long flags, dummy_flags; 4996 5014 unsigned long ovfl_regs; 4997 5015 unsigned int reason; 4998 5016 int ret; ··· 5037 5039 //if (CTX_OVFL_NOBLOCK(ctx)) goto skip_blocking; 5038 5040 if (reason == PFM_TRAP_REASON_RESET) goto skip_blocking; 5039 5041 5042 + /* 5043 + * restore interrupt mask to what it was on entry. 5044 + * Could be enabled/diasbled. 5045 + */ 5040 5046 UNPROTECT_CTX(ctx, flags); 5041 5047 5042 - /* 5043 - * pfm_handle_work() is currently called with interrupts disabled. 5044 - * The down_interruptible call may sleep, therefore we 5045 - * must re-enable interrupts to avoid deadlocks. It is 5046 - * safe to do so because this function is called ONLY 5047 - * when returning to user level (PUStk=1), in which case 5048 - * there is no risk of kernel stack overflow due to deep 5049 - * interrupt nesting. 5050 - */ 5051 - BUG_ON(flags & IA64_PSR_I); 5048 + /* 5049 + * force interrupt enable because of down_interruptible() 5050 + */ 5052 5051 local_irq_enable(); 5053 5052 5054 5053 DPRINT(("before block sleeping\n")); ··· 5059 5064 DPRINT(("after block sleeping ret=%d\n", ret)); 5060 5065 5061 5066 /* 5062 - * disable interrupts to restore state we had upon entering 5063 - * this function 5067 + * lock context and mask interrupts again 5068 + * We save flags into a dummy because we may have 5069 + * altered interrupts mask compared to entry in this 5070 + * function. 5064 5071 */ 5065 - local_irq_disable(); 5066 - 5067 - PROTECT_CTX(ctx, flags); 5072 + PROTECT_CTX(ctx, dummy_flags); 5068 5073 5069 5074 /* 5070 5075 * we need to read the ovfl_regs only after wake-up ··· 5090 5095 ctx->ctx_ovfl_regs[0] = 0UL; 5091 5096 5092 5097 nothing_to_do: 5093 - 5098 + /* 5099 + * restore flags as they were upon entry 5100 + */ 5094 5101 UNPROTECT_CTX(ctx, flags); 5095 5102 } 5096 5103
+2 -11
arch/ia64/kernel/perfmon_default_smpl.c
··· 20 20 MODULE_DESCRIPTION("perfmon default sampling format"); 21 21 MODULE_LICENSE("GPL"); 22 22 23 - MODULE_PARM(debug, "i"); 24 - MODULE_PARM_DESC(debug, "debug"); 25 - 26 - MODULE_PARM(debug_ovfl, "i"); 27 - MODULE_PARM_DESC(debug_ovfl, "debug ovfl"); 28 - 29 - 30 23 #define DEFAULT_DEBUG 1 31 24 32 25 #ifdef DEFAULT_DEBUG 33 26 #define DPRINT(a) \ 34 27 do { \ 35 - if (unlikely(debug >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \ 28 + if (unlikely(pfm_sysctl.debug >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \ 36 29 } while (0) 37 30 38 31 #define DPRINT_ovfl(a) \ 39 32 do { \ 40 - if (unlikely(debug_ovfl >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \ 33 + if (unlikely(pfm_sysctl.debug > 0 && pfm_sysctl.debug_ovfl >0)) { printk("%s.%d: CPU%d ", __FUNCTION__, __LINE__, smp_processor_id()); printk a; } \ 41 34 } while (0) 42 35 43 36 #else 44 37 #define DPRINT(a) 45 38 #define DPRINT_ovfl(a) 46 39 #endif 47 - 48 - static int debug, debug_ovfl; 49 40 50 41 static int 51 42 default_validate(struct task_struct *task, unsigned int flags, int cpu, void *data)
+12
include/asm-ia64/perfmon.h
··· 254 254 #define PFM_CPUINFO_DCR_PP 0x2 /* if set the system wide session has started */ 255 255 #define PFM_CPUINFO_EXCL_IDLE 0x4 /* the system wide session excludes the idle task */ 256 256 257 + /* 258 + * sysctl control structure. visible to sampling formats 259 + */ 260 + typedef struct { 261 + int debug; /* turn on/off debugging via syslog */ 262 + int debug_ovfl; /* turn on/off debug printk in overflow handler */ 263 + int fastctxsw; /* turn on/off fast (unsecure) ctxsw */ 264 + int expert_mode; /* turn on/off value checking */ 265 + } pfm_sysctl_t; 266 + extern pfm_sysctl_t pfm_sysctl; 267 + 268 + 257 269 #endif /* __KERNEL__ */ 258 270 259 271 #endif /* _ASM_IA64_PERFMON_H */