Skip to content
Snippets Groups Projects
Commit 330d87f9 authored by Jonathan Hanks's avatar Jonathan Hanks
Browse files

Merge branch 'issue-334' into 'master'

Adding functions with more general real-time/isolation language because this functionality extends to more general core isolation use-cases.

Closes #334

See merge request cds/advligorts!289
parents 9a9979e3 389af56c
No related branches found
No related tags found
2 merge requests!439RCG 5.0 release fro deb 10,!289Adding functions with more general real-time/isolation language because this functionality extends to more general core isolation use-cases.
*.cmd
*.mod
*.mod.c
*.symvers
*.d
......@@ -5,28 +5,40 @@
MODULE_LICENSE( "Dual BSD/GPL" );
static void ( *original_play_dead_handler )( void ) = NULL;
play_dead_handler_fp_t original_play_dead_handler = NULL;
static DEFINE_PER_CPU( void ( * )( void ), fe_code );
static DEFINE_PER_CPU( play_dead_handler_fp_t , fe_code );
int is_cpu_occupied( unsigned int cpu )
{
return 0 != per_cpu( fe_code, cpu );
}
EXPORT_SYMBOL( is_cpu_occupied );
int
is_cpu_taken_by_rcg_model( unsigned int cpu )
{
return 0 != per_cpu( fe_code, cpu );
return is_cpu_occupied( cpu );
}
EXPORT_SYMBOL( is_cpu_taken_by_rcg_model );
void
set_fe_code_idle( void ( *ptr )( void ), unsigned int cpu )
void set_rt_callback( play_dead_handler_fp_t ptr, unsigned int cpu )
{
per_cpu( fe_code, cpu ) = ptr;
}
EXPORT_SYMBOL( set_rt_callback );
void
set_fe_code_idle( play_dead_handler_fp_t ptr, unsigned int cpu )
{
set_rt_callback(ptr, cpu);
}
EXPORT_SYMBOL( set_fe_code_idle );
static void
ligo_play_dead( void )
{
void ( *handler )( void ) = per_cpu( fe_code, smp_processor_id( ) );
play_dead_handler_fp_t handler = per_cpu( fe_code, smp_processor_id( ) );
printk( KERN_ALERT "entering ligo_play_dead, cpu handler = %p", handler );
if ( handler )
......
#ifndef RTS_CPU_ISOLATOR_H
#define RTS_CPU_ISOLATOR_H
#include <linux/version.h>
//
// This is the function pointer type of the kernel's play_dead()
// function that we overwrite in order to inject LIGO's "real-time"
// module code. It should match the play_dead() prototype in:
// https://elixir.bootlin.com/linux/v5.10/source/arch/x86/include/asm/smp.h
//
typedef void (*play_dead_handler_fp_t)( void );
///
/// @brief This utility function is used to check if a module
/// has already used this interface to isolate the given CPU.
///
/// @param cpu The CPU number the caller is checking (0 indexed)
///
/// @return 0 if the core has been taken, >0 if it is free
///
extern int is_cpu_occupied( unsigned int cpu );
/// @deprecated
/// @brief Proxy function for the is_cpu_occupied() function above.
/// This function is retained for compatibility with legacy code.
///
/// @param cpu The CPU number the caller is checking (0 indexed)
///
/// @return 0 if the core has been taken, >0 if it is free
///
extern int is_cpu_taken_by_rcg_model( unsigned int cpu );
extern void set_fe_code_idle( void ( *ptr )( void ), unsigned int cpu );
///
/// @brief This function is used to set the function that is
/// called when the "real-time" execution is started.
/// It must be set before calling rts_isolator_exec()
///
/// @param rt_runner_func A function pointer to the "real-time" code
/// you would like to run
///
/// @param cpu The CPU number to isolate the code on (0 indexed)
///
extern void set_rt_callback( play_dead_handler_fp_t rt_runner_func, unsigned int cpu );
/// @deprecated
/// @brief Proxy function for the set_rt_callback() function above.
/// This function is retained for compatibility with legacy code.
///
/// @param rt_runner_func A function pointer to the "real-time" code
/// you would like to run
///
/// @param cpu The CPU number to isolate the code on (0 indexed)
///
extern void set_fe_code_idle( play_dead_handler_fp_t rt_runner_func, unsigned int cpu );
///
/// @brief Instead of calling CPU up/down directly, new real-time module
/// implementers should use the rts_isolator_exec() and
/// rts_isolator_cleanup() functions defined here, and this header
/// will track any changes needed for differing kernel versions.
///
/// All CPU_IDs are 0 indexed.
///
#if LINUX_VERSION_CODE <= KERNEL_VERSION(5,6,0)
static inline int rts_isolator_exec( unsigned int CPU_ID ){ return cpu_down(CPU_ID); }
static inline int rts_isolator_cleanup( unsigned int CPU_ID ){ return cpu_up(CPU_ID); }
#else //This is 5.10.0 and newer, caller interface is the same between versions
static inline int rts_isolator_exec( unsigned int CPU_ID ){ return remove_cpu(CPU_ID); }
static inline int rts_isolator_cleanup( unsigned int CPU_ID ){ return add_cpu(CPU_ID); }
#endif
/// Other Notes
///
///
/// The general usage for getting your module to run in "real-time"
/// mode with this driver is:
///
/// == In your module init ==
///
/// 1. Check if the core you are planning to use is free with:
/// if( is_cpu_taken_by_rcg_model( CPU_ID ) == 0 ) ERROR;
///
/// 2. Set your "real-time" module code function pointer:
/// set_fe_code_idle( rt_runner_func, CPU_ID );
/// msleep( 100 ); // Wait for a bit
///
/// 3. Isolate the core and run the "real-time" code. We bring the
/// CPU "down" so the callback we set with set_fe_code_idle() is run:
/// rts_isolator_exec( CPU_ID ); //This is usally the last thing done
/// //in the module_init() function
/// == End module init ==
///
/// 4. Allow your "real-time" module to run and do its job.
///
/// 5. When you want to stop the "real-time" module and bring the CPU back.
/// First signal your "real-time" module to exit. This is usually done
/// through the use of a global varable that your module_exit() function
/// and your "real-time" runner function (rt_runner_func above) can both
/// see. Second call the rts_isolator_cleanup() function. Ex:
///
/// void rt_user_mod_exit( void ) {
/// g_stop_rt_function = 1; //The rt_runner_func is checking this
/// each iteration to see if it should exit
/// msleep( 1000 ); //Wait for some time to let it exit,
/// //or use another var to signal an exit
/// set_fe_code_idle( 0, CPU_ID ); //Unset the injected handler, code will
/// use linux default CPU shutdown if 0
/// msleep( 1000 ); //Wait for some time
/// rts_isolator_cleanup( CPU_ID ); //Call the cleanup function
/// msleep( 1000 ); //Wait for some more time
/// }
/// module_exit( rt_user_mod_exit );
///
#endif // RTS_CPU_ISOLATOR_H
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment