extern VOID CPUMON_Remove_Cpuhooks ( void ) { #if defined(PERFMON_V1) || defined(PERFMON_V2_ALT) int status; SEP_PRINT_DEBUG("CPUMON_Remove_Cpuhooks: entered... pmv=0x%p \n", SYS_Read_PMV()); /* * if Perfmon1 or Perfmon2_alt is set, we used the perfmon.c * interface to steal perfmon.c's interrupt handler for our use. * Now we must release it back. * Don't free_irq() because perfmon.c still wants to use it */ status = CPUMON_REMOVE_INTERRUPT(&desc); if (status) { SEP_PRINT_WARNING("CPUMON_Remove_Cpuhooks: CPUMON_REMOVE_INTERRUPT returned: %d\n",status); } #elif !defined(PERFMON_V2) SEP_PRINT_DEBUG("CPUMON_Remove_Cpuhooks: entered... pmv=0x%p \n", SYS_Read_PMV()); if (xchg(&pebs_irqaction, 0)) { free_irq(ebs_irq, NULL); } #endif SEP_PRINT_DEBUG("CPUMON_Remove_Cpuhooks: exit... pmv=0x%p \n", SYS_Read_PMV()); return; }
extern VOID UTILITY_Set_PMV_Mask ( VOID ) { U64 pmv; pmv = SYS_Read_PMV(); pmv |= PMV_MASK_BIT; SYS_Write_PMV(pmv); return; }
extern VOID UTILITY_Clear_PMV_Mask ( VOID ) { U64 pmv; pmv = SYS_Read_PMV(); pmv &= ~PMV_MASK_BIT; SYS_Write_PMV(pmv); return; }
/*! * @fn int CPUMON_Install_Cpuhooks(VOID) * @brief Assign the PMU interrupt to the driver * * @return zero if successful, non-zero error value if something failed * * Install the driver ebs handler onto the PMU interrupt. If perfmon is * compiled in then we ask perfmon for the interrupt, otherwise we ask the * kernel... * * <I>Special Notes:</I> * * @Note This routine is for Itanium(R)-based systems only! * * For IA32, the LBRs are not frozen when a PMU interrupt is taken. * Since the LBRs capture information on every branch, for the LBR * registers to be useful, we need to freeze them as quickly as * possible after the interrupt. This means hooking the IDT directly * to call a driver specific interrupt handler. That happens in the * vtxsys.S file via samp_get_set_idt_entry. The real routine being * called first upon PMU interrupt is t_ebs (in vtxsys.S) and that * routine calls PMI_Interrupt_Handler()... * */ extern void CPUMON_Install_Cpuhooks ( void ) { int status = -1; SEP_PRINT_DEBUG("CPUMON_Install_Cpuhooks: entered... pmv 0x%p \n", SYS_Read_PMV()); #if defined(PERFMON_V1) || defined(PERFMON_V2_ALT) /* * if Perfmon1 or Perfmon2_alt is set, we can use the perfmon.c * interface to steal perfmon.c's interrupt handler for our use * perfmon.c has already done register_percpu_irq() */ ebs_irq = SEP_PERFMON_IRQ; desc.handler = &PMI_Interrupt_Handler; status = CPUMON_INSTALL_INTERRUPT(&desc); if (status) { SEP_PRINT_ERROR("CPUMON_Install_Cpuhooks: CPUMON_INSTALL_INTERRUPT returned %d\n",status); } #elif !defined(PERFMON_V2) if (pebs_irqaction) { return status; } #ifdef SA_PERCPU_IRQ_SUPPORTED ebs_irq = SEP_PERFMON_IRQ; pebs_irqaction = (struct irqaction *) 1; status = request_irq(SEP_PERFMON_IRQ, PMI_Interrupt_Handler, SA_INTERRUPT | SA_PERCPU_IRQ, "SEP Sampling", NULL); #else { pebs_irqaction = kmalloc(sizeof (struct irqaction), GFP_ATOMIC); if (pebs_irqaction) { memset(pebs_irqaction, 0, sizeof (struct irqaction)); ebs_irq = SEP_PERFMON_IRQ; pebs_irqaction->handler = (void *)PMI_Interrupt_Handler; pebs_irqaction->flags = SA_INTERRUPT; pebs_irqaction->name = SEP_DRIVER_NAME; pebs_irqaction->dev_id = NULL; register_percpu_irq(ebs_irq, pebs_irqaction); status = 0; } else { SEP_PRINT_WARNING("couldn't kmalloc pebs_irqaction (%d bytes)\n", (int)sizeof(struct irqaction)); } } #endif #endif SEP_PRINT("IRQ vector 0x%x will be used for handling PMU interrupts\n", SEP_PERFMON_IRQ); SEP_PRINT_DEBUG("CPUMON_Install_Cpuhooks: exit...... rc=0x%x pmv=0x%p \n", status, SYS_Read_PMV()); return; }