forked from Imagelibrary/seL4
mcs: provide tickless api for arm timers
This does not implement the timers for any platforms, but provides the generic arm arch, and aarch32/aarch64 infrastructure for tickless timer drivers.
This commit is contained in:
@@ -53,3 +53,7 @@ additional_commands:
|
||||
NUM_PPI: '*'
|
||||
INTERRUPT_CONTROLLER: '*'
|
||||
TIMER: '*'
|
||||
KERNEL_WCET: '*'
|
||||
CLK_MAGIC: '*'
|
||||
CLK_SHIFT: '*'
|
||||
TIMER_PRECISION: '*'
|
||||
|
||||
@@ -84,6 +84,9 @@ if(DEFINED CONFIGURE_MAX_IRQ)
|
||||
math(EXPR BITS "${BITS} + 1")
|
||||
endif()
|
||||
set(CONFIGURE_IRQ_SLOT_BITS "${BITS}" CACHE INTERNAL "")
|
||||
if(NOT DEFINED ${CONFIGURE_TIMER_PRECISION})
|
||||
set(CONFIGURE_TIMER_PRECISION "0")
|
||||
endif()
|
||||
configure_file(
|
||||
src/arch/${KernelArch}/platform_gen.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/gen_headers/plat/platform_gen.h @ONLY
|
||||
|
||||
@@ -102,13 +102,22 @@ unset(CONFIGURE_NUM_PPI CACHE)
|
||||
unset(CONFIGURE_INTERRUPT_CONTROLLER CACHE)
|
||||
unset(CONFIGURE_TIMER CACHE)
|
||||
unset(CONFIGURE_SMMU CACHE)
|
||||
unset(CONFIGURE_CLK_SHIFT CACHE)
|
||||
unset(CONFIGURE_CLK_MAGIC CACHE)
|
||||
unset(CONFIGURE_KERNEL_WCET CACHE)
|
||||
unset(CONFIGURE_TIMER_PRECISION CACHE)
|
||||
# CLK_SHIFT and CLK_MAGIC are generated from tools/reciprocal.py
|
||||
# based on the TIMER_CLK_HZ to simulate division.
|
||||
# This could be moved to a cmake function
|
||||
# in future to build the values on the first build. Note the calculation
|
||||
# can take a long time though.
|
||||
function(declare_default_headers)
|
||||
cmake_parse_arguments(
|
||||
PARSE_ARGV
|
||||
0
|
||||
CONFIGURE
|
||||
""
|
||||
"TIMER_FREQUENCY;MAX_IRQ;NUM_PPI;PLIC_MAX_NUM_INT;INTERRUPT_CONTROLLER;TIMER;SMMU"
|
||||
"TIMER_FREQUENCY;MAX_IRQ;NUM_PPI;PLIC_MAX_NUM_INT;INTERRUPT_CONTROLLER;TIMER;SMMU;CLK_SHIFT;CLK_MAGIC;KERNEL_WCET;TIMER_PRECISION"
|
||||
""
|
||||
)
|
||||
set(CONFIGURE_TIMER_FREQUENCY "${CONFIGURE_TIMER_FREQUENCY}" CACHE INTERNAL "")
|
||||
@@ -118,6 +127,10 @@ function(declare_default_headers)
|
||||
set(CONFIGURE_INTERRUPT_CONTROLLER "${CONFIGURE_INTERRUPT_CONTROLLER}" CACHE INTERNAL "")
|
||||
set(CONFIGURE_TIMER "${CONFIGURE_TIMER}" CACHE INTERNAL "")
|
||||
set(CONFIGURE_SMMU "${CONFIGURE_SMMU}" CACHE INTERNAL "")
|
||||
set(CONFIGURE_CLK_SHIFT "${CONFIGURE_CLK_SHIFT}" CACHE INTERNAL "")
|
||||
set(CONFIGURE_CLK_MAGIC "${CONFIGURE_CLK_MAGIC}" CACHE INTERNAL "")
|
||||
set(CONFIGURE_KERNEL_WCET "${CONFIGURE_KERNEL_WCET}" CACHE INTERNAL "")
|
||||
set(CONFIGURE_TIMER_PRECISION "${CONFIGURE_TIMER_PRECISION}" CACHE INTERNAL "")
|
||||
endfunction()
|
||||
|
||||
# For all of the common variables we set a default value here if they haven't
|
||||
|
||||
@@ -30,4 +30,32 @@
|
||||
#define CNT_CVAL CNTV_CVAL
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KERNEL_MCS
|
||||
#include <util.h>
|
||||
|
||||
/* timer function definitions that work for all 32bit arm platforms that provide
|
||||
* CLK_MAGIC and TIMER_CLOCK_MHZ -- these definitions might need to move
|
||||
* if we come across an arm platform that does not suit this model */
|
||||
|
||||
/* get the max value ticksToUs can be passed without overflowing */
|
||||
static inline CONST ticks_t getMaxTicksToUs(void)
|
||||
{
|
||||
#if USE_KHZ
|
||||
return UINT64_MAX / KHZ_IN_MHZ / CLK_MAGIC;
|
||||
#else
|
||||
return UINT64_MAX / CLK_MAGIC;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline CONST time_t ticksToUs(ticks_t ticks)
|
||||
{
|
||||
/* simulate 64bit division using multiplication by reciprocal */
|
||||
#if USE_KHZ
|
||||
return (ticks * KHZ_IN_MHZ) * CLK_MAGIC >> CLK_SHIFT;
|
||||
#else
|
||||
return (ticks * CLK_MAGIC) >> CLK_SHIFT;
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_KERNEL_MCS */
|
||||
|
||||
#endif /* __ARCH_MODE_MACHINE_TIMER_H_ */
|
||||
|
||||
@@ -26,4 +26,27 @@
|
||||
#endif
|
||||
#define CNTFRQ "cntfrq_el0"
|
||||
|
||||
#ifdef CONFIG_KERNEL_MCS
|
||||
#include <stdint.h>
|
||||
#include <util.h>
|
||||
|
||||
/* timer function definitions that work for all 64 bit arm platforms */
|
||||
static inline CONST ticks_t getMaxTicksToUs(void)
|
||||
{
|
||||
#if USE_KHZ
|
||||
return UINT64_MAX / TIMER_CLOCK_KHZ;
|
||||
#else
|
||||
return UINT64_MAX;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline CONST time_t ticksToUs(ticks_t ticks)
|
||||
{
|
||||
#if USE_KHZ
|
||||
return (ticks * TIMER_CLOCK_KHZ) / TIMER_CLOCK_MHZ;
|
||||
#else
|
||||
return ticks / TIMER_CLOCK_MHZ;
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_KERNEL_MCS */
|
||||
#endif /* __ARCH_MODE_MACHINE_TIMER_H_ */
|
||||
|
||||
@@ -15,6 +15,48 @@
|
||||
|
||||
#include <config.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef CONFIG_KERNEL_MCS
|
||||
#include <types.h>
|
||||
#include <util.h>
|
||||
#include <mode/util.h>
|
||||
|
||||
#define USE_KHZ (TIMER_CLOCK_HZ % HZ_IN_MHZ > 0)
|
||||
#define TIMER_CLOCK_KHZ (TIMER_CLOCK_HZ / HZ_IN_KHZ)
|
||||
#define TIMER_CLOCK_MHZ (TIMER_CLOCK_HZ / HZ_IN_MHZ)
|
||||
|
||||
#include <plat/platform_gen.h>
|
||||
#include <mode/machine/timer.h>
|
||||
|
||||
void initTimer(void);
|
||||
|
||||
/* get the max value usToTicks can be passed without overflowing */
|
||||
static inline CONST time_t getMaxUsToTicks(void)
|
||||
{
|
||||
#if USE_KHZ
|
||||
return UINT64_MAX / TIMER_CLOCK_KHZ;
|
||||
#else
|
||||
return UINT64_MAX / TIMER_CLOCK_MHZ;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline CONST ticks_t usToTicks(time_t us)
|
||||
{
|
||||
#if USE_KHZ
|
||||
/* reciprocal division overflows too quickly for dividing by KHZ_IN_MHZ.
|
||||
* This operation isn't used frequently or on many platforms, so use manual
|
||||
* division here */
|
||||
return div64(us * TIMER_CLOCK_KHZ, KHZ_IN_MHZ);
|
||||
#else
|
||||
return us * TIMER_CLOCK_MHZ;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline CONST ticks_t getTimerPrecision(void)
|
||||
{
|
||||
return usToTicks(TIMER_PRECISION);
|
||||
}
|
||||
#else /* CONFIG_KERNEL_MCS */
|
||||
#include <mode/machine/timer.h>
|
||||
#include <plat/machine/hardware.h>
|
||||
|
||||
@@ -29,5 +71,6 @@
|
||||
#endif
|
||||
|
||||
void initTimer(void);
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_MACHINE_TIMER_H_ */
|
||||
|
||||
@@ -487,6 +487,10 @@ static BOOT_CODE bool_t try_init_kernel(
|
||||
}
|
||||
write_it_asid_pool(it_ap_cap, it_pd_cap);
|
||||
|
||||
#ifdef CONFIG_KERNEL_MCS
|
||||
NODE_STATE(ksCurTime) = getCurrentTime();
|
||||
#endif
|
||||
|
||||
/* create the idle thread */
|
||||
if (!create_idle_thread()) {
|
||||
return false;
|
||||
|
||||
@@ -13,7 +13,13 @@
|
||||
#ifndef __ARM_PLAT_H
|
||||
#define __ARM_PLAT_H
|
||||
|
||||
#include <autoconf.h>
|
||||
|
||||
#define TIMER_CLOCK_HZ @CONFIGURE_TIMER_FREQUENCY@
|
||||
#define CLK_MAGIC @CONFIGURE_CLK_MAGIC@
|
||||
#define CLK_SHIFT @CONFIGURE_CLK_SHIFT@
|
||||
#define TIMER_PRECISION @CONFIGURE_TIMER_PRECISION@
|
||||
|
||||
enum IRQConstants {
|
||||
maxIRQ = @CONFIGURE_MAX_IRQ@
|
||||
} platform_interrupt_t;
|
||||
@@ -27,4 +33,12 @@ enum IRQConstants {
|
||||
#if (defined(CONFIGURE_SMMU) && defined(CONFIG_ARM_SMMU))
|
||||
#include CONFIGURE_SMMU
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KERNEL_MCS
|
||||
static inline CONST time_t getKernelWcetUs(void)
|
||||
{
|
||||
return @CONFIGURE_KERNEL_WCET@;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !__ARM_PLAT_H */
|
||||
|
||||
Reference in New Issue
Block a user