diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index 52270c6eb..1040f8e8a 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -135,6 +135,7 @@ CONFIG_PICOLIBC CONFIG_POSIX_API CONFIG_POSIX_THREADS CONFIG_PREEMPT_COUNT +CONFIG_PREEMPT_RT CONFIG_PTHREAD_IPC CONFIG_SCHED_INFO CONFIG_SMP diff --git a/linuxkm/Kbuild b/linuxkm/Kbuild index e46987ad9..6f1a2f320 100644 --- a/linuxkm/Kbuild +++ b/linuxkm/Kbuild @@ -145,7 +145,8 @@ ifeq "$(ENABLED_LINUXKM_PIE)" "yes" endif ccflags-y += $(PIE_SUPPORT_FLAGS) $(WOLFCRYPT_PIE_FILES): ccflags-y += $(PIE_FLAGS) - $(WOLFCRYPT_PIE_FILES): ccflags-remove-y += -pg + $(WOLFCRYPT_PIE_FILES): ccflags-remove-y += -pg \ + $(call cc-option,-ftrivial-auto-var-init=zero) ifdef FORCE_GLOBAL_OBJTOOL_OFF undefine CONFIG_OBJTOOL endif diff --git a/linuxkm/linuxkm_wc_port.h b/linuxkm/linuxkm_wc_port.h index 72710b8a4..51bc3f26a 100644 --- a/linuxkm/linuxkm_wc_port.h +++ b/linuxkm/linuxkm_wc_port.h @@ -24,6 +24,27 @@ #ifndef LINUXKM_WC_PORT_H #define LINUXKM_WC_PORT_H + /* + * CRITICAL: Disable ARM64 LSE atomics for out-of-tree modules. + * + * When CONFIG_ARM64_LSE_ATOMICS is enabled, the kernel uses static keys + * (jump labels) in system_uses_lse_atomics() to choose between LSE and + * LL/SC atomic implementations at runtime. These static keys generate + * asm goto statements that reference .jump_table section symbols which + * cannot be resolved in out-of-tree modules, causing: + * "error: impossible constraint in 'asm'" + * + * By undefining CONFIG_ARM64_LSE_ATOMICS here (before any kernel headers + * that use atomics are included), we force use of the LL/SC fallback path + * which works correctly in out-of-tree modules. + * + * This must appear BEFORE #include because that header + * may transitively include headers that use atomics. + */ + #ifdef CONFIG_ARM64_LSE_ATOMICS + #undef CONFIG_ARM64_LSE_ATOMICS + #endif + #include #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) @@ -941,7 +962,15 @@ #endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS */ - typeof(__mutex_init) *__mutex_init; + #ifndef CONFIG_PREEMPT_RT + typeof(__mutex_init) *__mutex_init; + #else + typeof(__rt_mutex_init) *__rt_mutex_init; + typeof(rt_mutex_base_init) *rt_mutex_base_init; + typeof(rt_spin_lock) *rt_spin_lock; + typeof(rt_spin_unlock) *rt_spin_unlock; + #endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) typeof(mutex_lock_nested) *mutex_lock_nested; #else @@ -1048,6 +1077,7 @@ #endif #ifdef CONFIG_ARM64 + #ifndef CONFIG_ARCH_TEGRA #ifdef WC_CONTAINERIZE_THIS /* alt_cb_patch_nops and queued_spin_lock_slowpath are defined early * to allow shimming in system headers, but now we need the native @@ -1062,6 +1092,7 @@ typeof(queued_spin_lock_slowpath) *queued_spin_lock_slowpath; #endif #endif + #endif typeof(preempt_count) *preempt_count; #ifndef _raw_spin_lock_irqsave @@ -1260,7 +1291,17 @@ #error WOLFSSL_USE_SAVE_VECTOR_REGISTERS is set for an unimplemented architecture. #endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS */ - #define __mutex_init WC_PIE_INDIRECT_SYM(__mutex_init) + #ifndef CONFIG_PREEMPT_RT + #define __mutex_init WC_PIE_INDIRECT_SYM(__mutex_init) + #else + /* On RT kernels, __mutex_init is a macro pointing to __rt_mutex_init */ + #undef __mutex_init + #define __rt_mutex_init WC_PIE_INDIRECT_SYM(__rt_mutex_init) + #define __mutex_init(mutex, name, key) __rt_mutex_init(mutex, name, key) + #define rt_mutex_base_init WC_PIE_INDIRECT_SYM(rt_mutex_base_init) + #define rt_spin_lock WC_PIE_INDIRECT_SYM(rt_spin_lock) + #define rt_spin_unlock WC_PIE_INDIRECT_SYM(rt_spin_unlock) + #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) #define mutex_lock_nested WC_PIE_INDIRECT_SYM(mutex_lock_nested) #else @@ -1327,8 +1368,31 @@ /* this is defined in linux/spinlock.h as an inline that calls the unshimmed * raw_spin_unlock_irqrestore(). use a macro here to supersede it. + * Note: On PREEMPT_RT kernels, spinlock_t doesn't have rlock member, + * so we skip this redefinition and use the kernel's native implementation. */ - #define spin_unlock_irqrestore(lock, flags) raw_spin_unlock_irqrestore(&((lock)->rlock), flags) + #ifndef CONFIG_PREEMPT_RT + #define spin_unlock_irqrestore(lock, flags) raw_spin_unlock_irqrestore(&((lock)->rlock), flags) + #else + /* Undo internal wolfSSL PIE macro rewriting */ + #ifdef rt_spin_unlock + #undef rt_spin_unlock + #endif + #ifdef rt_spin_lock + #undef rt_spin_lock + #endif + static inline int wolfssl_spin_unlock_irqrestore_rt(spinlock_t *lock, + unsigned long flags) + { + (void)flags; /* rt_spin_unlock ignores flags */ + WC_PIE_INDIRECT_SYM(rt_spin_unlock)(lock); + return 0; + } + + #undef spin_unlock_irqrestore + #define spin_unlock_irqrestore(lock, flags) \ + wolfssl_spin_unlock_irqrestore_rt((lock), (flags)) + #endif #define wc_linuxkm_sig_ignore_begin WC_PIE_INDIRECT_SYM(wc_linuxkm_sig_ignore_begin); #define wc_linuxkm_sig_ignore_end WC_PIE_INDIRECT_SYM(wc_linuxkm_sig_ignore_end); diff --git a/linuxkm/module_hooks.c b/linuxkm/module_hooks.c index b070649b2..c92074b0a 100644 --- a/linuxkm/module_hooks.c +++ b/linuxkm/module_hooks.c @@ -1310,7 +1310,14 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) { #error WOLFSSL_USE_SAVE_VECTOR_REGISTERS is set for an unsupported architecture. #endif /* WOLFSSL_USE_SAVE_VECTOR_REGISTERS */ - wolfssl_linuxkm_pie_redirect_table.__mutex_init = __mutex_init; + #ifndef CONFIG_PREEMPT_RT + wolfssl_linuxkm_pie_redirect_table.__mutex_init = __mutex_init; + #else + wolfssl_linuxkm_pie_redirect_table.__rt_mutex_init = __rt_mutex_init; + wolfssl_linuxkm_pie_redirect_table.rt_mutex_base_init = rt_mutex_base_init; + wolfssl_linuxkm_pie_redirect_table.rt_spin_lock = rt_spin_lock; + wolfssl_linuxkm_pie_redirect_table.rt_spin_unlock = rt_spin_unlock; + #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0) wolfssl_linuxkm_pie_redirect_table.mutex_lock_nested = mutex_lock_nested; #else @@ -1489,8 +1496,10 @@ static int set_up_wolfssl_linuxkm_pie_redirect_table(void) { #endif #ifdef CONFIG_ARM64 +#ifndef CONFIG_ARCH_TEGRA wolfssl_linuxkm_pie_redirect_table.alt_cb_patch_nops = alt_cb_patch_nops; wolfssl_linuxkm_pie_redirect_table.queued_spin_lock_slowpath = queued_spin_lock_slowpath; +#endif #endif wolfssl_linuxkm_pie_redirect_table.wc_linuxkm_sig_ignore_begin = wc_linuxkm_sig_ignore_begin; diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index ed8223353..462e85a6c 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -4977,6 +4977,7 @@ char* wolfSSL_strnstr(const char* s1, const char* s2, unsigned int n) #if defined(WOLFSSL_LINUXKM) && defined(CONFIG_ARM64) && \ defined(WC_SYM_RELOC_TABLES) +#ifndef CONFIG_ARCH_TEGRA noinstr void my__alt_cb_patch_nops(struct alt_instr *alt, __le32 *origptr, __le32 *updptr, int nr_inst) { @@ -4990,3 +4991,4 @@ void my__queued_spin_lock_slowpath(struct qspinlock *lock, u32 val) (lock, val); } #endif +#endif