Profile interrupt events.

Add the interrupt profile points for x86 and ARM arquitectures. This
gives information regarding the time when interrupts occur.

Change-Id: Ic876c0e7f9e8819d53e0578416f09146f4456d3d
Signed-off-by: Yonattan Louise <yonattan.a.louise.mendoza@intel.com>
This commit is contained in:
Yonattan Louise 2015-08-21 19:10:32 -05:00 committed by Anas Nashif
commit d2108bf084
12 changed files with 203 additions and 0 deletions

View file

@ -17,6 +17,7 @@ CONFIG_XIP=y
# CONFIG_KERNEL_PROFILER is not set # CONFIG_KERNEL_PROFILER is not set
# CONFIG_PROFILER_BUFFER_SIZE is not set # CONFIG_PROFILER_BUFFER_SIZE is not set
# CONFIG_PROFILER_CONTEXT_SWITCH is not set # CONFIG_PROFILER_CONTEXT_SWITCH is not set
# CONFIG_PROFILER_INTERRUPT is not set
# #
# Nanokernel Options # Nanokernel Options

View file

@ -72,6 +72,12 @@ SECTION_FUNC(TEXT, _isr_wrapper)
push {lr} /* lr is now the first item on the stack */ push {lr} /* lr is now the first item on the stack */
#ifdef CONFIG_PROFILER_INTERRUPT
push {lr}
bl _sys_profiler_interrupt
pop {lr}
#endif
#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT #ifdef CONFIG_ADVANCED_POWER_MANAGEMENT
/* /*
* All interrupts are disabled when handling idle wakeup. For tickless * All interrupts are disabled when handling idle wakeup. For tickless

View file

@ -18,6 +18,7 @@ CONFIG_XIP=y
# CONFIG_KERNEL_PROFILER is not set # CONFIG_KERNEL_PROFILER is not set
# CONFIG_PROFILER_BUFFER_SIZE is not set # CONFIG_PROFILER_BUFFER_SIZE is not set
# CONFIG_PROFILER_CONTEXT_SWITCH is not set # CONFIG_PROFILER_CONTEXT_SWITCH is not set
# CONFIG_PROFILER_INTERRUPT is not set
# #
# Nanokernel Options # Nanokernel Options

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 2015 Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3) Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* @file
* @brief Profiler support for ARM
*/
#ifndef __PROFILE_ARM_H__
#define __PROFILE_ARM_H__
#include <CortexM/asm_inline_gcc.h>
/**
* @brief Get the identification of the current interrupt.
*
* This routine obtain the key of the interrupt that is currently processed
* if it is called from a ISR context.
*
* @return The key of the interrupt that is currently being processed.
*/
int _sys_current_irq_key_get(void)
{
return _IpsrGet();
}
#endif /* __PROFILE_ARM_H__ */

View file

@ -170,6 +170,15 @@ SECTION_FUNC(TEXT, _IntEnt)
popl %eax popl %eax
#endif #endif
#ifdef CONFIG_PROFILER_INTERRUPT
/*
* Preserve EAX as it contains the stub return address.
*/
pushl %eax
call _sys_profiler_interrupt
popl %eax
#endif
/* load %ecx with &_nanokernel */ /* load %ecx with &_nanokernel */

View file

@ -20,6 +20,7 @@ CONFIG_ENHANCED_SECURITY=y
# CONFIG_KERNEL_PROFILER is not set # CONFIG_KERNEL_PROFILER is not set
# CONFIG_PROFILER_BUFFER_SIZE is not set # CONFIG_PROFILER_BUFFER_SIZE is not set
# CONFIG_PROFILER_CONTEXT_SWITCH is not set # CONFIG_PROFILER_CONTEXT_SWITCH is not set
# CONFIG_PROFILER_INTERRUPT is not set
# #
# Security Options # Security Options

View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 2015 Intel Corporation
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3) Neither the name of Intel Corporation nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* @file
* @brief Profiler support for x86
*/
#ifndef __PROFILE_X86_H__
#define __PROFILE_X86_H__
/**
* @brief Get the identification of the current interrupt.
*
* This routine obtain the key of the interrupt that is currently processed
* if it is called from a ISR context.
*
* @return The key of the interrupt that is currently being processed.
*/
int _sys_current_irq_key_get(void)
{
extern int _loapic_isr_vector_get(void);
return _loapic_isr_vector_get();
}
#endif /* __PROFILE_X86_H__ */

View file

@ -416,3 +416,46 @@ void _loapic_irq_disable(unsigned int irq /* IRQ number of the
*pLvt = *pLvt | LOAPIC_LVT_MASKED; *pLvt = *pLvt | LOAPIC_LVT_MASKED;
irq_unlock(oldLevel); irq_unlock(oldLevel);
} }
/**
* @brief Find the currently executing interrupt vector, if any
*
* This routine finds the vector of the interrupt that is being processed.
* The ISR (In-Service Register) register contain the vectors of the interrupts
* in service. And the higher vector is the indentification of the interrupt
* being currently processed.
*
* ISR registers' offsets:
* --------------------
* | Offset | bits |
* --------------------
* | 0100H | 0:31 |
* | 0110H | 32:63 |
* | 0120H | 64:95 |
* | 0130H | 96:127 |
* | 0140H | 128:159 |
* | 0150H | 160:191 |
* | 0160H | 192:223 |
* | 0170H | 224:255 |
* --------------------
*
* @return The vector of the interrupt that is currently being processed.
*/
int _loapic_isr_vector_get(void)
{
/* pointer to ISR vector table */
volatile int *pReg;
int block=0;
while (block < 8) {
pReg = (volatile int *)
(CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_ISR + (block * 0x10));
if (*pReg) {
return (block * 32) + (find_lsb_set(*pReg) - 1);
}
block++;
}
return 0;
}

View file

@ -263,6 +263,12 @@ void _TIMER_INT_HANDLER(void *unused)
{ {
ARG_UNUSED(unused); ARG_UNUSED(unused);
#ifdef CONFIG_PROFILER_INTERRUPT
extern void _sys_profiler_interrupt(void);
_sys_profiler_interrupt();
#endif
#ifdef CONFIG_INT_LATENCY_BENCHMARK #ifdef CONFIG_INT_LATENCY_BENCHMARK
uint32_t value = __scs.systick.val; uint32_t value = __scs.systick.val;
uint32_t delta = __scs.systick.reload - value; uint32_t delta = __scs.systick.reload - value;

View file

@ -45,6 +45,10 @@
#define PROFILER_CONTEXT_SWITCH_EVENT_ID 0x0001 #define PROFILER_CONTEXT_SWITCH_EVENT_ID 0x0001
#endif #endif
#ifdef CONFIG_PROFILER_INTERRUPT
#define PROFILER_INTERRUPT_EVENT_ID 0x0002
#endif
#ifndef _ASMLANGUAGE #ifndef _ASMLANGUAGE
/** /**
* Global variable of the ring buffer that allows user to implement * Global variable of the ring buffer that allows user to implement

View file

@ -140,6 +140,16 @@ config PROFILER_CONTEXT_SWITCH
depends on KERNEL_PROFILER depends on KERNEL_PROFILER
help help
Enable the context switch event messages. Enable the context switch event messages.
config PROFILER_INTERRUPT
bool
prompt "Interrupt profiler point"
default n
depends on KERNEL_PROFILER
help
Enable interrupt event messages. These messages provide the following
information: The time when interrupts occur.
endmenu endmenu
menu "Security Options" menu "Security Options"

View file

@ -38,6 +38,7 @@
#include <misc/util.h> #include <misc/util.h>
#include <init.h> #include <init.h>
#include <nano_private.h> #include <nano_private.h>
#include <profiler_arch.h>
uint32_t _sys_profiler_buffer[CONFIG_PROFILER_BUFFER_SIZE]; uint32_t _sys_profiler_buffer[CONFIG_PROFILER_BUFFER_SIZE];
@ -120,3 +121,16 @@ void sys_profiler_register_as_collector(void)
_collector_fiber = _nanokernel.current; _collector_fiber = _nanokernel.current;
} }
#endif /* CONFIG_PROFILER_CONTEXT_SWITCH */ #endif /* CONFIG_PROFILER_CONTEXT_SWITCH */
#ifdef CONFIG_PROFILER_INTERRUPT
void _sys_profiler_interrupt()
{
uint32_t data[2];
data[0] = nano_tick_get_32();
data[1] = _sys_current_irq_key_get();
sys_profiler_put(PROFILER_INTERRUPT_EVENT_ID, data, ARRAY_SIZE(data));
}
#endif /* CONFIG_PROFILER_INTERRUPT */