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: '*'
|
NUM_PPI: '*'
|
||||||
INTERRUPT_CONTROLLER: '*'
|
INTERRUPT_CONTROLLER: '*'
|
||||||
TIMER: '*'
|
TIMER: '*'
|
||||||
|
KERNEL_WCET: '*'
|
||||||
|
CLK_MAGIC: '*'
|
||||||
|
CLK_SHIFT: '*'
|
||||||
|
TIMER_PRECISION: '*'
|
||||||
|
|||||||
@@ -84,6 +84,9 @@ if(DEFINED CONFIGURE_MAX_IRQ)
|
|||||||
math(EXPR BITS "${BITS} + 1")
|
math(EXPR BITS "${BITS} + 1")
|
||||||
endif()
|
endif()
|
||||||
set(CONFIGURE_IRQ_SLOT_BITS "${BITS}" CACHE INTERNAL "")
|
set(CONFIGURE_IRQ_SLOT_BITS "${BITS}" CACHE INTERNAL "")
|
||||||
|
if(NOT DEFINED ${CONFIGURE_TIMER_PRECISION})
|
||||||
|
set(CONFIGURE_TIMER_PRECISION "0")
|
||||||
|
endif()
|
||||||
configure_file(
|
configure_file(
|
||||||
src/arch/${KernelArch}/platform_gen.h.in
|
src/arch/${KernelArch}/platform_gen.h.in
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/gen_headers/plat/platform_gen.h @ONLY
|
${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_INTERRUPT_CONTROLLER CACHE)
|
||||||
unset(CONFIGURE_TIMER CACHE)
|
unset(CONFIGURE_TIMER CACHE)
|
||||||
unset(CONFIGURE_SMMU 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)
|
function(declare_default_headers)
|
||||||
cmake_parse_arguments(
|
cmake_parse_arguments(
|
||||||
PARSE_ARGV
|
PARSE_ARGV
|
||||||
0
|
0
|
||||||
CONFIGURE
|
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 "")
|
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_INTERRUPT_CONTROLLER "${CONFIGURE_INTERRUPT_CONTROLLER}" CACHE INTERNAL "")
|
||||||
set(CONFIGURE_TIMER "${CONFIGURE_TIMER}" CACHE INTERNAL "")
|
set(CONFIGURE_TIMER "${CONFIGURE_TIMER}" CACHE INTERNAL "")
|
||||||
set(CONFIGURE_SMMU "${CONFIGURE_SMMU}" 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()
|
endfunction()
|
||||||
|
|
||||||
# For all of the common variables we set a default value here if they haven't
|
# 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
|
#define CNT_CVAL CNTV_CVAL
|
||||||
#endif
|
#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_ */
|
#endif /* __ARCH_MODE_MACHINE_TIMER_H_ */
|
||||||
|
|||||||
@@ -26,4 +26,27 @@
|
|||||||
#endif
|
#endif
|
||||||
#define CNTFRQ "cntfrq_el0"
|
#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_ */
|
#endif /* __ARCH_MODE_MACHINE_TIMER_H_ */
|
||||||
|
|||||||
@@ -15,6 +15,48 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <stdint.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 <mode/machine/timer.h>
|
||||||
#include <plat/machine/hardware.h>
|
#include <plat/machine/hardware.h>
|
||||||
|
|
||||||
@@ -29,5 +71,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void initTimer(void);
|
void initTimer(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __ARCH_MACHINE_TIMER_H_ */
|
#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);
|
write_it_asid_pool(it_ap_cap, it_pd_cap);
|
||||||
|
|
||||||
|
#ifdef CONFIG_KERNEL_MCS
|
||||||
|
NODE_STATE(ksCurTime) = getCurrentTime();
|
||||||
|
#endif
|
||||||
|
|
||||||
/* create the idle thread */
|
/* create the idle thread */
|
||||||
if (!create_idle_thread()) {
|
if (!create_idle_thread()) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -13,7 +13,13 @@
|
|||||||
#ifndef __ARM_PLAT_H
|
#ifndef __ARM_PLAT_H
|
||||||
#define __ARM_PLAT_H
|
#define __ARM_PLAT_H
|
||||||
|
|
||||||
|
#include <autoconf.h>
|
||||||
|
|
||||||
#define TIMER_CLOCK_HZ @CONFIGURE_TIMER_FREQUENCY@
|
#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 {
|
enum IRQConstants {
|
||||||
maxIRQ = @CONFIGURE_MAX_IRQ@
|
maxIRQ = @CONFIGURE_MAX_IRQ@
|
||||||
} platform_interrupt_t;
|
} platform_interrupt_t;
|
||||||
@@ -27,4 +33,12 @@ enum IRQConstants {
|
|||||||
#if (defined(CONFIGURE_SMMU) && defined(CONFIG_ARM_SMMU))
|
#if (defined(CONFIGURE_SMMU) && defined(CONFIG_ARM_SMMU))
|
||||||
#include CONFIGURE_SMMU
|
#include CONFIGURE_SMMU
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_KERNEL_MCS
|
||||||
|
static inline CONST time_t getKernelWcetUs(void)
|
||||||
|
{
|
||||||
|
return @CONFIGURE_KERNEL_WCET@;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* !__ARM_PLAT_H */
|
#endif /* !__ARM_PLAT_H */
|
||||||
|
|||||||
Reference in New Issue
Block a user