/* * hal-cpu.h - CPU related Hardware Abstraction Layer * * Authors Ghassan Almaless (2008,2009,2010,2011,2012) * Alain Greiner (2016) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH. * * ALMOS-MKH is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _HAL_CPU_H_ #define _HAL_CPU_H_ #include #include /***************************************************************************************** * All CPU specific implementations must define the functions and macros * specified in this CPU Hardware Abstraction Layer. ****************************************************************************************/ #define CPU_USR_MODE // CPU in user mode with interrupts enabled #define CPU_SYS_MODE // CPU in kernel mode with interrupts disabled ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // CPU context operations / implementation in the cpu/***/hal_context. ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// /***************************************************************************************** * This function initializes a CPU execution context from informations contained * in a thread descriptor * @ ctx : pointer on the hal_context_t structure. * @ thread : pointer on the thread descriptor. ****************************************************************************************/ extern void hal_context_init( cpu_context_t * ctx, thread_t * thread ); /***************************************************************************************** * This function sets a new value in the thread slot of the calling CPU context. * @ ctx : pointer on the hal_context_t structure. * @ thread : pointer on the thread. ****************************************************************************************/ extern void hal_context_set_thread( cpu_context_t * ctx, thread_t * thread ); /***************************************************************************************** * This function sets a new value in the cp2_ptpr slot of the calling CPU context. * @ ctx : pointer on the hal_context_t structure. * @ ppm : pointer on the (source) physical memory manager. ****************************************************************************************/ extern void hal_context_set_pmm( cpu_context_t * ctx, pmm_t * pmm ); /***************************************************************************************** * This function sets a new value in the sigreturn_func slot of the calling CPU context. * @ ctx : pointer on the hal_context_t structure. * @ func : function pointer. ****************************************************************************************/ extern void hal_context_set_sigreturn( cpu_context_t * ctx, void * func ); /***************************************************************************************** * This function should be used to launch a new thread. * It loads the calling CPU registers from the values contained in the context argument, * and jumps to the address defined in the entry_func slot, using an eret. * @ ctx : pointer on the hal_context_t structure. ****************************************************************************************/ extern void hal_context_load( cpu_context_t * ctx); /***************************************************************************************** * This function saves the calling CPU registers to the CPU context argument. * @ ctx : pointer on the hal_context_t structure. ****************************************************************************************/ extern void hal_context_save( cpu_context_t * ctx ); /***************************************************************************************** * This function restores the CPU registers from the CPU context argument. * @ ctx : pointer on the hal_context_t structure. ****************************************************************************************/ extern void hal_context_restore( cpu_context_t * ctx, uint32_t val ); /***************************************************************************************** * This function initializes an uzone structure. * @ uzone : pointer on the structure to initialise. ****************************************************************************************/ extern void hal_uzone_init( cpu_uzone_t * uzone ); /***************************************************************************************** * This function copies the content of a source uzone to a destination uzone. * @ dst : pointer on the destination structure. * @ src : pointer on the source structure. ****************************************************************************************/ extern void hal_uzone_dup( cpu_uzone_t * dst, hal_uzone_t * src ); /***************************************************************************************** * This function save the fpu registers in the thread uzone. ****************************************************************************************/ extern void hal_fpu_context_save( cpu_uzone_t * uzone ); /***************************************************************************************** * This function restore the fpu registers from the thread uzone. ****************************************************************************************/ extern void hal_fpu_context_restore( cpu_uzone_t * uzone ); /***************************************************************************************** * This function TODO ??? [AG] ****************************************************************************************/ extern error_t hal_uzone_getattr( cpu_uzone_t * uzone, hal_uzone_attr_t * attr); /***************************************************************************************** * This function TODO ??? [AG] ****************************************************************************************/ extern error_t hal_uzone_setattr( cpu_uzone_t * uzone, hal_uzone_attr_t * attr); /***************************************************************************************** * This function TODO ??? [AG] ****************************************************************************************/ extern void hal_signal_notify( thread_t * this, void * handler, uint32_t sig ); //////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// // CPU special registers access / implementation in cpu/***/special.c //////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// /***************************************************************************************** * This function returns the global core identifier from the calling core register. ****************************************************************************************/ extern inline gid_t hal_get_gid(); /***************************************************************************************** * This function returns the content of the calling core cycles counter register. ****************************************************************************************/ extern inline uint32_t hal_time_stamp(); /***************************************************************************************** * This function returns the current thread pointer from the calling core register. ****************************************************************************************/ extern inline thread_t * hal_get_current_thread(); /***************************************************************************************** * This function registers a thread pointer in the calling CPU register. ****************************************************************************************/ extern inline void hal_set_current_thread(thread_t * thread); /***************************************************************************************** * This function writes into the proper CPU register to enable the floating point unit. ****************************************************************************************/ extern inline void hal_fpu_enable(); /***************************************************************************************** * This function writes into the proper CPU register to disable the floating point unit. ****************************************************************************************/ extern inline void hal_fpu_disable(); /***************************************************************************************** * This function returns the current value of stack pointer from CPU register. ****************************************************************************************/ extern inline uint32_t hal_get_stack(); /***************************************************************************************** * This function registers a new value in the CPU stack pointer and returns previous one. ****************************************************************************************/ extern inline uint32_t hal_set_stack( void * new_val ); ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // IRQ disable / restore operations / implementation in cpu/***/irqmask.c ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// /***************************************************************************************** * This function disables all IRQs, and saves the CPU SR state if required. * TODO : Warning this function discards the CU3 access bit * @ old : address of buffer to save the SR (no save if NULL). ****************************************************************************************/ extern inline void hal_disable_all_irq( uint32_t * old ); /***************************************************************************************** * This function enables all IRQs, and saves the CPU SR state if required. * @ old : address of buffer to save the SR (no save if NULL). ****************************************************************************************/ extern inline void hal_enable_all_irq( uint32_t * old ); /***************************************************************************************** * This function returns true if all IRQs are disabled. ****************************************************************************************/ extern inline bool_t hal_all_irq_disabled(); /***************************************************************************************** * This function restores a previously SCPU SR state. * @ old : value to be written in CPU SR register ****************************************************************************************/ extern inline void hal_restore_irq( uint32_t old ); ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Atomic Operations / Implementation in cpu/***/atomic.c // // Implementation of atomic read-then-write operations depends on the CPU instruction set. ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// /***************************************************************************************** * This blocking function makes an atomic "and" between a 32 bits mask, and a 32 bits * unsigned int shared variable, returning only when atomic operation is successful. * @ ptr : pointer on the shared variable * @ val : mask value ****************************************************************************************/ extern inline void hal_atomic_and( uint32_t * ptr, uint32_t val ); /***************************************************************************************** * This blocking function makes an atomic "or" between a 32 bits mask, and a 32 bits * unsigned int shared variable, returning only when atomic operation is successful. * @ ptr : pointer on the shared variable * @ val : mask value ****************************************************************************************/ extern inline void hal_atomic_or( uint32_t * ptr, uint32_t val ); /***************************************************************************************** * This blocking function atomically adds a positive or negative value to a 32 bits * unsigned int shared variable, returning only when atomic add is successful. * @ ptr : pointer on the shared variable * @ val : signed value to add * @ return shared variable value before add ****************************************************************************************/ extern inline uint32_t hal_atomic_add( uint32_t * ptr, int32_t val ); /***************************************************************************************** * This blocking function atomically increments a 32 bits unsigned int shared variable, * returning only when atomic increment is successful. * @ ptr : pointer on the shared variable * @ return shared variable value before increment ****************************************************************************************/ extern inline uint32_t hal_atomic_inc( uint32_t * ptr ); /***************************************************************************************** * This blocking function atomically decrements a 32 bits unsigned int shared variable, * returning only when atomic decrement is successful. * @ ptr : pointer on the shared variable * @ return shared variable value before decrement ****************************************************************************************/ extern inline uint32_t hal_atomic_dec( uint32_t * ptr ); /***************************************************************************************** * This non blocking function makes an atomic Compare-And-Swap on a 32 bits unsigned int * shared variable, returning a Boolean to indicate both success and atomicity. * @ ptr : pointer on the shared variable * @ old : expected value for the shared variable * @ new : value to be writen if success * @ return true if (current == old) and (access is atomic) ****************************************************************************************/ extern inline bool_t hal_atomic_cas( uint32_t * ptr, uint32_t old, uint32_t new ); /***************************************************************************************** * This non blocking function makes an atomic Test-And-Set on a 32 bits unsigned int * shared variable, returning a Boolean to indicate both success and atomicity. * @ ptr : pointer on the shared variable * @ val : value to be writen if success * @ return true if (current == 0) and (access is atomic) ****************************************************************************************/ extern inline bool_t hal_atomic_test_set( uint32_t * ptr, uint32_t val ); ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // L1 cache related operations / Implementation in the cpu/***/cache.c ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// /***************************************************************************************** * This function makes an uncachable read to a 32 bits variable in local memory. * @ ptr : pointer on the variable * @ returns the value ****************************************************************************************/ extern inline uint32_t hal_uncached_read( uint32_t * ptr ); /***************************************************************************************** * This function invalidates the cache line containing a given address. * @ ptr : address in local memory ****************************************************************************************/ extern inline void hal_invalid_dcache_line( void * ptr ); /***************************************************************************************** * This blocking function flushes the write buffer to synchronize all pending writes. ****************************************************************************************/ extern inline void hal_wbflush(); /***************************************************************************************** * This forbids code reordering by the compiler. ****************************************************************************************/ extern inline void hal_rdbar(); /***************************************************************************************** * This function forces the calling core in idle-low-power mode. ****************************************************************************************/ extern inline void hal_core_sleep(); ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Remote accesses / implementation in cpu/***/remote.c // // Kernel accesses to local memory bank and peripherals can use normal C pointers. // kernel accesses to remote memory banks or peripherals must use the following // dedicated functions, that can have implementations depending on architectures. ///////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// /***************************************************************************************** * This function writes a single byte in a remote cluster. * @ xp : extended pointer to remote cluster * @ data : value to be written ****************************************************************************************/ extern inline void hal_remote_sb( xptr_t xp, char data ); /***************************************************************************************** * This function writes an aligned 32 bits word in a remote cluster. * @ xp : extended pointer to remote cluster * @ data : value to be written ****************************************************************************************/ extern inline void hal_remote_sw( xptr_t xp, uint32_t data ); /***************************************************************************************** * This function writes an aligned 64 bits word in a remote cluster. * @ xp : extended pointer to remote cluster * @ data : value to be written ****************************************************************************************/ extern inline void hal_remote_swd( xptr_t xp, uint64_t data ); /***************************************************************************************** * This function writes a pointer (32 or 64 bits) in a remote cluster. * @ xp : extended pointer to remote cluster * @ pt : value to be written ****************************************************************************************/ extern inline void hal_remote_spt( xptr_t xp, void * pt ); /***************************************************************************************** * This function reads a single byte in a remote cluster. * @ xp : extended pointer to remote data * @ return read value ****************************************************************************************/ extern inline char hal_remote_lb( xptr_t xp ); /***************************************************************************************** * This function reads an aligned 32 bits word in a remote cluster. * @ xp : extended pointer to remote data * @ return read value ****************************************************************************************/ extern inline uint32_t hal_remote_lw( xptr_t xp ) /***************************************************************************************** * This function reads an aligned 64 bits word in a remote cluster. * @ xp : extended pointer to remote data * @ return read value ****************************************************************************************/ extern inline uint64_t hal_remote_lwd( xptr_t xp ) /***************************************************************************************** * This function reads a poiter (32 or 64 bits) in a remote cluster. * @ xp : extended pointer to remote data * @ return read value ****************************************************************************************/ extern inline void * hal_remote_lpt( xptr_t xp ); /***************************************************************************************** * This function reads an uncachable 32 bits word in a remote cluster. * @ xp : extended pointer to remote data * @ return read value ****************************************************************************************/ extern inline uint32_t hal_remote_lw_unc( xptr_t xp ); /***************************************************************************************** * This function makes an atomic Compare-And-Swap in a remote cluster. * @ xp : extended pointer to remote data * @ old : expected value * @ new : new value to be written * @ return true if success / return false if failure ****************************************************************************************/ extern inline bool_t hal_remote_atomic_cas( xptr_t xp, uint32_t old, uint32_t new ); /***************************************************************************************** * This function adds atomically an increment to the current value of * a 32 bits integer in a remote cluster. * @ xp : extended pointer to remote data * @ incr : increment value. * @ return old value (before increment) of the remote integer ****************************************************************************************/ extern inline uint32_t hal_remote_atomic_add( xptr_t xp, uint32_t incr ); /***************************************************************************************** * This non blocking function tries to make an atomic increment to the current * value of a 32 bits integer in a remote cluster. * @ xp : extended pointer to remote data * @ incr : increment value. * @ old : local buffer address for the read value (before increment) * @ return true if success / return false if failure ****************************************************************************************/ extern inline error_t hal_remote_atomic_try_add( xptr_t xp, uint32_t incr, uint32_t * old ); /***************************************************************************************** * This function makes a memcpy from a source remote buffer in kernel space to another * destination remote buffer in kernel space. * @ dst : extended pointer to destination buffer * @ src : extended pointer to source buffer * @ size : number of bytes to move ****************************************************************************************/ extern inline void hal_remote_memcpy( xptr_t dst, xptr_t src, size_t size ); //////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// // User space access / implementation in cpu/***/uspace.c // // When moving data between user space and kernel space, the user address is always // a virtual address, but the kernel address can be a physical address, on some // architectures. Therefore, data transfers must use the following functions. //////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////// /***************************************************************************************** * This function tranfers a data buffer from the user space to the kernel space. * @ kdst : destination address in kernel space * @ usrc : source address in user space * @ size : number of bytes to transfer. ****************************************************************************************/ extern void hal_copy_from_uspace( void * kdst, void * usrc, uint32_t size ); /***************************************************************************************** * This function tranfers a data buffer from the kernel space to the user space. * @ udst : destination address in user space. * @ ksrc : source address in kernel space. * @ size : number of bytes to transfer. ****************************************************************************************/ extern void hal_copy_to_uspace( void * udst, void * ksrc, uint32_t size ); #endif /* _HAL_CPU_H_ */