⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 op_model_arm11_core.c

📁 linux 内核源代码
💻 C
字号:
/** * @file op_model_arm11_core.c * ARM11 Event Monitor Driver * @remark Copyright 2004 ARM SMP Development Team */#include <linux/types.h>#include <linux/errno.h>#include <linux/oprofile.h>#include <linux/interrupt.h>#include <linux/irq.h>#include <linux/smp.h>#include "op_counter.h"#include "op_arm_model.h"#include "op_model_arm11_core.h"/* * ARM11 PMU support */static inline void arm11_write_pmnc(u32 val){	/* upper 4bits and 7, 11 are write-as-0 */	val &= 0x0ffff77f;	asm volatile("mcr p15, 0, %0, c15, c12, 0" : : "r" (val));}static inline u32 arm11_read_pmnc(void){	u32 val;	asm volatile("mrc p15, 0, %0, c15, c12, 0" : "=r" (val));	return val;}static void arm11_reset_counter(unsigned int cnt){	u32 val = -(u32)counter_config[CPU_COUNTER(smp_processor_id(), cnt)].count;	switch (cnt) {	case CCNT:		asm volatile("mcr p15, 0, %0, c15, c12, 1" : : "r" (val));		break;	case PMN0:		asm volatile("mcr p15, 0, %0, c15, c12, 2" : : "r" (val));		break;	case PMN1:		asm volatile("mcr p15, 0, %0, c15, c12, 3" : : "r" (val));		break;	}}int arm11_setup_pmu(void){	unsigned int cnt;	u32 pmnc;	if (arm11_read_pmnc() & PMCR_E) {		printk(KERN_ERR "oprofile: CPU%u PMU still enabled when setup new event counter.\n", smp_processor_id());		return -EBUSY;	}	/* initialize PMNC, reset overflow, D bit, C bit and P bit. */	arm11_write_pmnc(PMCR_OFL_PMN0 | PMCR_OFL_PMN1 | PMCR_OFL_CCNT |			 PMCR_C | PMCR_P);	for (pmnc = 0, cnt = PMN0; cnt <= CCNT; cnt++) {		unsigned long event;		if (!counter_config[CPU_COUNTER(smp_processor_id(), cnt)].enabled)			continue;		event = counter_config[CPU_COUNTER(smp_processor_id(), cnt)].event & 255;		/*		 * Set event (if destined for PMNx counters)		 */		if (cnt == PMN0) {			pmnc |= event << 20;		} else if (cnt == PMN1) {			pmnc |= event << 12;		}		/*		 * We don't need to set the event if it's a cycle count		 * Enable interrupt for this counter		 */		pmnc |= PMCR_IEN_PMN0 << cnt;		arm11_reset_counter(cnt);	}	arm11_write_pmnc(pmnc);	return 0;}int arm11_start_pmu(void){	arm11_write_pmnc(arm11_read_pmnc() | PMCR_E);	return 0;}int arm11_stop_pmu(void){	unsigned int cnt;	arm11_write_pmnc(arm11_read_pmnc() & ~PMCR_E);	for (cnt = PMN0; cnt <= CCNT; cnt++)		arm11_reset_counter(cnt);	return 0;}/* * CPU counters' IRQ handler (one IRQ per CPU) */static irqreturn_t arm11_pmu_interrupt(int irq, void *arg){	struct pt_regs *regs = get_irq_regs();	unsigned int cnt;	u32 pmnc;	pmnc = arm11_read_pmnc();	for (cnt = PMN0; cnt <= CCNT; cnt++) {		if ((pmnc & (PMCR_OFL_PMN0 << cnt)) && (pmnc & (PMCR_IEN_PMN0 << cnt))) {			arm11_reset_counter(cnt);			oprofile_add_sample(regs, CPU_COUNTER(smp_processor_id(), cnt));		}	}	/* Clear counter flag(s) */	arm11_write_pmnc(pmnc);	return IRQ_HANDLED;}int arm11_request_interrupts(int *irqs, int nr){	unsigned int i;	int ret = 0;	for(i = 0; i < nr; i++) {		ret = request_irq(irqs[i], arm11_pmu_interrupt, IRQF_DISABLED, "CP15 PMU", NULL);		if (ret != 0) {			printk(KERN_ERR "oprofile: unable to request IRQ%u for MPCORE-EM\n",			       irqs[i]);			break;		}	}	if (i != nr)		while (i-- != 0)			free_irq(irqs[i], NULL);	return ret;}void arm11_release_interrupts(int *irqs, int nr){	unsigned int i;	for (i = 0; i < nr; i++)		free_irq(irqs[i], NULL);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -