[PATCH v3 00/12] kasan: unify kasan_arch_is_ready() and remove arch-specific implementations

2025-07-17 Thread Sabyrzhan Tasbolatov
This patch series addresses the fragmentation in KASAN initialization
across architectures by introducing a unified approach that eliminates
duplicate static keys and arch-specific kasan_arch_is_ready()
implementations.

The core issue is that different architectures have inconsistent approaches
to KASAN readiness tracking:
- PowerPC, LoongArch, and um arch, each implement own kasan_arch_is_ready()
- Only HW_TAGS mode had a unified static key (kasan_flag_enabled)
- Generic and SW_TAGS modes relied on arch-specific solutions
  or always-on behavior

This series implements two-level approach:
1. kasan_enabled() - compile-time check for KASAN configuration
2. kasan_shadow_initialized() - runtime check for shadow memory readiness

Key improvements:
- Unified static key infrastructure across all KASAN modes
- Runtime overhead only for architectures that actually need it
- Compile-time optimization for arch. with early KASAN initialization
- Complete elimination of arch-specific kasan_arch_is_ready()
- Consistent interface and reduced code duplication

Previous v2 thread: 
https://lore.kernel.org/all/20250626153147.145312-1-snovit...@gmail.com/

Changes in v3 (sorry for the 3-week gap):

0. Included in TO, CC only KASAN devs and people who commented in v2.

1. Addressed Andrey Konovalov's feedback:
   - Kept separate kasan_enabled() and kasan_shadow_initialized() functions
   - Added proper __wrapper functions with clean separation

2. Addressed Christophe Leroy's performance comments:
   - CONFIG_ARCH_DEFER_KASAN is only selected by architectures that need it
   - No static key overhead for architectures that can enable KASAN early
   - PowerPC 32-bit and book3e get compile-time optimization

3. Addressed Heiko Carstens and Alexander Gordeev s390 comments:
   - s390 doesn't select ARCH_DEFER_KASAN (no unnecessary static key overhead)
   - kasan_enable() is a no-op for architectures with early KASAN setup

4. Improved wrapper architecture:
   - All existing wrapper functions in include/linux/kasan.h now check both
 kasan_enabled() && kasan_shadow_initialized()
   - Internal implementation functions focus purely on core functionality
   - Shadow readiness logic is centralized in headers per Andrey's guidance

Architecture-specific changes:
- PowerPC radix MMU: selects ARCH_DEFER_KASAN for runtime control
- LoongArch: selects ARCH_DEFER_KASAN, removes custom kasan_early_stage
- um: selects ARCH_DEFER_KASAN, removes kasan_um_is_ready
- Other architectures: get compile-time optimization, no runtime overhead

The series maintains full backward compatibility while providing optimal
performance for each architecture's needs.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049

=== Current mainline KUnit status

To see if there is any regression, I've tested via compiling a kernel
with CONFIG_KASAN_KUNIT_TEST and running QEMU VM. There are failing tests
in SW_TAGS and GENERIC modes in arm64:

arm64 CONFIG_KASAN_HW_TAGS:
# kasan: pass:62 fail:0 skip:13 total:75
# Totals: pass:62 fail:0 skip:13 total:75
ok 1 kasan

arm64 CONFIG_KASAN_SW_TAGS=y:
# kasan: pass:65 fail:1 skip:9 total:75
# Totals: pass:65 fail:1 skip:9 total:75
not ok 1 kasan
# kasan_strings: EXPECTATION FAILED at mm/kasan/kasan_test_c.c:1598
KASAN failure expected in "strscpy(ptr, src + KASAN_GRANULE_SIZE, 
KASAN_GRANULE_SIZE)", but none occurred

arm64 CONFIG_KASAN_GENERIC=y, CONFIG_KASAN_OUTLINE=y:
# kasan: pass:61 fail:1 skip:13 total:75
# Totals: pass:61 fail:1 skip:13 total:75
not ok 1 kasan
# same failure as above

x86_64 CONFIG_KASAN_GENERIC=y:
# kasan: pass:58 fail:0 skip:17 total:75
# Totals: pass:58 fail:0 skip:17 total:75
ok 1 kasan

=== Testing with patches

Testing in v3:

- Compiled every affected arch with no errors:

$ make CC=clang LD=ld.lld AR=llvm-ar NM=llvm-nm STRIP=llvm-strip \
OBJCOPY=llvm-objcopy OBJDUMP=llvm-objdump READELF=llvm-readelf \
HOSTCC=clang HOSTCXX=clang++ HOSTAR=llvm-ar HOSTLD=ld.lld \
ARCH=$ARCH

$ clang --version
ClangBuiltLinux clang version 19.1.4
Target: x86_64-unknown-linux-gnu
Thread model: posix

- make ARCH=um produces the warning during compiling:
MODPOST Module.symvers
WARNING: modpost: vmlinux: section mismatch in reference: \
kasan_init+0x43 (section: .ltext) -> \
kasan_init_generic (section: .init.text)

AFAIU, it's due to the code in arch/um/kernel/mem.c, where kasan_init()
is placed in own section ".kasan_init", which calls kasan_init_generic()
which is marked with "__init".

- Booting via qemu-system- and running KUnit tests:

* arm64  (GENERIC, HW_TAGS, SW_TAGS): no regression, same above results.
* x86_64 (GENERIC): no regression, no errors

Sabyrzhan Tasbolatov (12):
  lib/kasan: introduce CONFIG_ARCH_DEFER_KASAN option
  kasan: unify static kasan_flag_enabled across modes
  kasan/powerpc: select ARCH_D

[PATCH v3 01/12] lib/kasan: introduce CONFIG_ARCH_DEFER_KASAN option

2025-07-17 Thread Sabyrzhan Tasbolatov
Introduce CONFIG_ARCH_DEFER_KASAN to identify architectures that need
to defer KASAN initialization until shadow memory is properly set up.

Some architectures (like PowerPC with radix MMU) need to set up their
shadow memory mappings before KASAN can be safely enabled, while others
(like s390, x86, arm) can enable KASAN much earlier or even from the
beginning.

This option allows us to:
1. Use static keys only where needed (avoiding overhead)
2. Use compile-time constants for arch that don't need runtime checks
3. Maintain optimal performance for both scenarios

Architectures that need deferred KASAN should select this option.
Architectures that can enable KASAN early will get compile-time
optimizations instead of runtime checks.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049
Signed-off-by: Sabyrzhan Tasbolatov 
---
Changes in v3:
- Introduced CONFIG_ARCH_DEFER_KASAN to control static key usage
---
 lib/Kconfig.kasan | 8 
 1 file changed, 8 insertions(+)

diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index f82889a830f..38456560c85 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -19,6 +19,14 @@ config ARCH_DISABLE_KASAN_INLINE
  Disables both inline and stack instrumentation. Selected by
  architectures that do not support these instrumentation types.
 
+config ARCH_DEFER_KASAN
+   bool
+   help
+ Architectures should select this if they need to defer KASAN
+ initialization until shadow memory is properly set up. This
+ enables runtime control via static keys. Otherwise, KASAN uses
+ compile-time constants for better performance.
+
 config CC_HAS_KASAN_GENERIC
def_bool $(cc-option, -fsanitize=kernel-address)
 
-- 
2.34.1




[PATCH v3 12/12] kasan: add shadow checks to wrappers and rename kasan_arch_is_ready

2025-07-17 Thread Sabyrzhan Tasbolatov
This patch completes:
1. Adding kasan_shadow_initialized() checks to existing wrapper functions
2. Replacing kasan_arch_is_ready() calls with kasan_shadow_initialized()
3. Creating wrapper functions for internal functions that need shadow
   readiness checks
4. Removing the kasan_arch_is_ready() fallback definition

The two-level approach is now fully implemented:
- kasan_enabled() - controls whether KASAN is enabled at all.
  (compile-time for most archs)
- kasan_shadow_initialized() - tracks shadow memory initialization
  (static key for ARCH_DEFER_KASAN archs, compile-time for others)

This provides complete elimination of kasan_arch_is_ready() calls from
KASAN implementation while moving all shadow readiness logic to
wrapper functions.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049
Signed-off-by: Sabyrzhan Tasbolatov 
---
Changes in v3:
- Addresses Andrey's feedback to move shadow checks to wrappers
- Rename kasan_arch_is_ready with kasan_shadow_initialized
- Added kasan_shadow_initialized() checks to all necessary wrapper functions
- Eliminated all remaining kasan_arch_is_ready() usage per reviewer guidance
---
 include/linux/kasan.h | 36 +++-
 mm/kasan/common.c |  9 +++--
 mm/kasan/generic.c| 12 +++-
 mm/kasan/kasan.h  | 36 ++--
 mm/kasan/shadow.c | 32 +++-
 5 files changed, 66 insertions(+), 59 deletions(-)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 51a8293d1af..292bd741d8d 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -194,7 +194,7 @@ bool __kasan_slab_pre_free(struct kmem_cache *s, void 
*object,
 static __always_inline bool kasan_slab_pre_free(struct kmem_cache *s,
void *object)
 {
-   if (kasan_enabled())
+   if (kasan_enabled() && kasan_shadow_initialized())
return __kasan_slab_pre_free(s, object, _RET_IP_);
return false;
 }
@@ -229,7 +229,7 @@ static __always_inline bool kasan_slab_free(struct 
kmem_cache *s,
void *object, bool init,
bool still_accessible)
 {
-   if (kasan_enabled())
+   if (kasan_enabled() && kasan_shadow_initialized())
return __kasan_slab_free(s, object, init, still_accessible);
return false;
 }
@@ -237,7 +237,7 @@ static __always_inline bool kasan_slab_free(struct 
kmem_cache *s,
 void __kasan_kfree_large(void *ptr, unsigned long ip);
 static __always_inline void kasan_kfree_large(void *ptr)
 {
-   if (kasan_enabled())
+   if (kasan_enabled() && kasan_shadow_initialized())
__kasan_kfree_large(ptr, _RET_IP_);
 }
 
@@ -302,7 +302,7 @@ bool __kasan_mempool_poison_pages(struct page *page, 
unsigned int order,
 static __always_inline bool kasan_mempool_poison_pages(struct page *page,
   unsigned int order)
 {
-   if (kasan_enabled())
+   if (kasan_enabled() && kasan_shadow_initialized())
return __kasan_mempool_poison_pages(page, order, _RET_IP_);
return true;
 }
@@ -356,7 +356,7 @@ bool __kasan_mempool_poison_object(void *ptr, unsigned long 
ip);
  */
 static __always_inline bool kasan_mempool_poison_object(void *ptr)
 {
-   if (kasan_enabled())
+   if (kasan_enabled() && kasan_shadow_initialized())
return __kasan_mempool_poison_object(ptr, _RET_IP_);
return true;
 }
@@ -568,11 +568,29 @@ static inline void kasan_init_hw_tags(void) { }
 #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
 
 void kasan_populate_early_vm_area_shadow(void *start, unsigned long size);
-int kasan_populate_vmalloc(unsigned long addr, unsigned long size);
-void kasan_release_vmalloc(unsigned long start, unsigned long end,
+
+int __kasan_populate_vmalloc(unsigned long addr, unsigned long size);
+static inline int kasan_populate_vmalloc(unsigned long addr, unsigned long 
size)
+{
+   if (!kasan_shadow_initialized())
+   return 0;
+   return __kasan_populate_vmalloc(addr, size);
+}
+
+void __kasan_release_vmalloc(unsigned long start, unsigned long end,
   unsigned long free_region_start,
   unsigned long free_region_end,
   unsigned long flags);
+static inline void kasan_release_vmalloc(unsigned long start,
+  unsigned long end,
+  unsigned long free_region_start,
+  unsigned long free_region_end,
+  unsigned long flags)
+{
+   if (kasan_shadow_initialized())
+   __kasan_release_vmalloc(start, end, free_region_start,
+  free_region_end, flags);
+}
 
 #else /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */
 
@@ -598,7 +616,7 @@ static __always_inline vo

[PATCH v3 10/12] kasan/s390: call kasan_init_generic in kasan_init

2025-07-17 Thread Sabyrzhan Tasbolatov
Call kasan_init_generic() which handles Generic KASAN initialization
and prints the banner. Since s390 doesn't select ARCH_DEFER_KASAN,
kasan_enable() will be a no-op, and kasan_enabled() will return
IS_ENABLED(CONFIG_KASAN) for optimal compile-time behavior.

s390 sets up KASAN mappings in the decompressor and can run with KASAN
enabled from very early, so it doesn't need runtime control.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049
Signed-off-by: Sabyrzhan Tasbolatov 
---
 arch/s390/kernel/early.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
index 54cf0923050..7ada1324f6a 100644
--- a/arch/s390/kernel/early.c
+++ b/arch/s390/kernel/early.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -65,7 +66,7 @@ static void __init kasan_early_init(void)
 {
 #ifdef CONFIG_KASAN
init_task.kasan_depth = 0;
-   pr_info("KernelAddressSanitizer initialized\n");
+   kasan_init_generic();
 #endif
 }
 
-- 
2.34.1




[PATCH v3 11/12] kasan/riscv: call kasan_init_generic in kasan_init

2025-07-17 Thread Sabyrzhan Tasbolatov
Call kasan_init_generic() which handles Generic KASAN initialization
and prints the banner. Since riscv doesn't select ARCH_DEFER_KASAN,
kasan_enable() will be a no-op, and kasan_enabled() will return
IS_ENABLED(CONFIG_KASAN) for optimal compile-time behavior.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049
Signed-off-by: Sabyrzhan Tasbolatov 
---
 arch/riscv/mm/kasan_init.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/riscv/mm/kasan_init.c b/arch/riscv/mm/kasan_init.c
index 41c635d6aca..ba2709b1eec 100644
--- a/arch/riscv/mm/kasan_init.c
+++ b/arch/riscv/mm/kasan_init.c
@@ -530,6 +530,7 @@ void __init kasan_init(void)
 
memset(kasan_early_shadow_page, KASAN_SHADOW_INIT, PAGE_SIZE);
init_task.kasan_depth = 0;
+   kasan_init_generic();
 
csr_write(CSR_SATP, PFN_DOWN(__pa(swapper_pg_dir)) | satp_mode);
local_flush_tlb_all();
-- 
2.34.1




[PATCH v3 08/12] kasan/um: select ARCH_DEFER_KASAN and call kasan_init_generic

2025-07-17 Thread Sabyrzhan Tasbolatov
UserMode Linux needs deferred KASAN initialization as it has a custom
kasan_arch_is_ready() implementation that tracks shadow memory readiness
via the kasan_um_is_ready flag.

Select ARCH_DEFER_KASAN to enable the unified static key mechanism
for runtime KASAN control. Call kasan_init_generic() which handles
Generic KASAN initialization and enables the static key.

Delete the key kasan_um_is_ready in favor of the unified kasan_enabled()
interface.

Note that kasan_init_generic has __init macro, which is called by
kasan_init() which is not marked with __init in arch/um code.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049
Signed-off-by: Sabyrzhan Tasbolatov 
---
Changes in v3:
- Added CONFIG_ARCH_DEFER_KASAN selection for proper runtime control
---
 arch/um/Kconfig | 1 +
 arch/um/include/asm/kasan.h | 5 -
 arch/um/kernel/mem.c| 4 ++--
 3 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index f08e8a7fac9..fd6d78bba52 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -8,6 +8,7 @@ config UML
select ARCH_WANTS_DYNAMIC_TASK_STRUCT
select ARCH_HAS_CPU_FINALIZE_INIT
select ARCH_HAS_FORTIFY_SOURCE
+   select ARCH_DEFER_KASAN
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_KCOV
select ARCH_HAS_STRNCPY_FROM_USER
diff --git a/arch/um/include/asm/kasan.h b/arch/um/include/asm/kasan.h
index f97bb1f7b85..81bcdc0f962 100644
--- a/arch/um/include/asm/kasan.h
+++ b/arch/um/include/asm/kasan.h
@@ -24,11 +24,6 @@
 
 #ifdef CONFIG_KASAN
 void kasan_init(void);
-extern int kasan_um_is_ready;
-
-#ifdef CONFIG_STATIC_LINK
-#define kasan_arch_is_ready() (kasan_um_is_ready)
-#endif
 #else
 static inline void kasan_init(void) { }
 #endif /* CONFIG_KASAN */
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 76bec7de81b..058cb70e330 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -21,9 +21,9 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_KASAN
-int kasan_um_is_ready;
 void kasan_init(void)
 {
/*
@@ -32,7 +32,7 @@ void kasan_init(void)
 */
kasan_map_memory((void *)KASAN_SHADOW_START, KASAN_SHADOW_SIZE);
init_task.kasan_depth = 0;
-   kasan_um_is_ready = true;
+   kasan_init_generic();
 }
 
 static void (*kasan_init_ptr)(void)
-- 
2.34.1




[PATCH v3 09/12] kasan/x86: call kasan_init_generic in kasan_init

2025-07-17 Thread Sabyrzhan Tasbolatov
Call kasan_init_generic() which handles Generic KASAN initialization
and prints the banner. Since x86 doesn't select ARCH_DEFER_KASAN,
kasan_enable() will be a no-op, and kasan_enabled() will return
IS_ENABLED(CONFIG_KASAN) for optimal compile-time behavior.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049
Signed-off-by: Sabyrzhan Tasbolatov 
---
 arch/x86/mm/kasan_init_64.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
index 0539efd0d21..998b6010d6d 100644
--- a/arch/x86/mm/kasan_init_64.c
+++ b/arch/x86/mm/kasan_init_64.c
@@ -451,5 +451,5 @@ void __init kasan_init(void)
__flush_tlb_all();
 
init_task.kasan_depth = 0;
-   pr_info("KernelAddressSanitizer initialized\n");
+   kasan_init_generic();
 }
-- 
2.34.1




[PATCH v3 03/12] kasan/powerpc: select ARCH_DEFER_KASAN and call kasan_init_generic

2025-07-17 Thread Sabyrzhan Tasbolatov
PowerPC with radix MMU is the primary architecture that needs deferred
KASAN initialization, as it requires complex shadow memory setup before
KASAN can be safely enabled.

Select ARCH_DEFER_KASAN for PPC_RADIX_MMU to enable the static key
mechanism for runtime KASAN control. Other PowerPC configurations
(like book3e and 32-bit) can enable KASAN early and will use
compile-time constants instead.

Also call kasan_init_generic() which handles Generic KASAN initialization.
For PowerPC radix MMU (which selects ARCH_DEFER_KASAN), this enables
the static key. For other PowerPC variants, kasan_enable() is a no-op
and kasan_enabled() returns IS_ENABLED(CONFIG_KASAN).

Remove the PowerPC-specific static key and kasan_arch_is_ready()
implementation in favor of the unified interface.

This ensures that:
- PowerPC radix gets the runtime control it needs
- Other PowerPC variants get optimal compile-time behavior
- No unnecessary overhead is added where not needed

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049
Fixes: 55d77bae7342 ("kasan: fix Oops due to missing calls to 
kasan_arch_is_ready()")
Signed-off-by: Sabyrzhan Tasbolatov 
---
Changes in v3:
- Added CONFIG_ARCH_DEFER_KASAN selection for PPC_RADIX_MMU only
- Kept ARCH_DISABLE_KASAN_INLINE selection since it's needed independently
---
 arch/powerpc/Kconfig   |  1 +
 arch/powerpc/include/asm/kasan.h   | 12 
 arch/powerpc/mm/kasan/init_32.c|  2 +-
 arch/powerpc/mm/kasan/init_book3e_64.c |  2 +-
 arch/powerpc/mm/kasan/init_book3s_64.c |  6 +-
 5 files changed, 4 insertions(+), 19 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c3e0cc83f12..e5a6aae6a77 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -123,6 +123,7 @@ config PPC
#
select ARCH_32BIT_OFF_T if PPC32
select ARCH_DISABLE_KASAN_INLINEif PPC_RADIX_MMU
+   select ARCH_DEFER_KASAN if PPC_RADIX_MMU
select ARCH_DMA_DEFAULT_COHERENTif !NOT_COHERENT_CACHE
select ARCH_ENABLE_MEMORY_HOTPLUG
select ARCH_ENABLE_MEMORY_HOTREMOVE
diff --git a/arch/powerpc/include/asm/kasan.h b/arch/powerpc/include/asm/kasan.h
index b5bbb94c51f..957a57c1db5 100644
--- a/arch/powerpc/include/asm/kasan.h
+++ b/arch/powerpc/include/asm/kasan.h
@@ -53,18 +53,6 @@
 #endif
 
 #ifdef CONFIG_KASAN
-#ifdef CONFIG_PPC_BOOK3S_64
-DECLARE_STATIC_KEY_FALSE(powerpc_kasan_enabled_key);
-
-static __always_inline bool kasan_arch_is_ready(void)
-{
-   if (static_branch_likely(&powerpc_kasan_enabled_key))
-   return true;
-   return false;
-}
-
-#define kasan_arch_is_ready kasan_arch_is_ready
-#endif
 
 void kasan_early_init(void);
 void kasan_mmu_init(void);
diff --git a/arch/powerpc/mm/kasan/init_32.c b/arch/powerpc/mm/kasan/init_32.c
index 03666d790a5..1d083597464 100644
--- a/arch/powerpc/mm/kasan/init_32.c
+++ b/arch/powerpc/mm/kasan/init_32.c
@@ -165,7 +165,7 @@ void __init kasan_init(void)
 
/* At this point kasan is fully initialized. Enable error messages */
init_task.kasan_depth = 0;
-   pr_info("KASAN init done\n");
+   kasan_init_generic();
 }
 
 void __init kasan_late_init(void)
diff --git a/arch/powerpc/mm/kasan/init_book3e_64.c 
b/arch/powerpc/mm/kasan/init_book3e_64.c
index 60c78aac0f6..0d3a73d6d4b 100644
--- a/arch/powerpc/mm/kasan/init_book3e_64.c
+++ b/arch/powerpc/mm/kasan/init_book3e_64.c
@@ -127,7 +127,7 @@ void __init kasan_init(void)
 
/* Enable error messages */
init_task.kasan_depth = 0;
-   pr_info("KASAN init done\n");
+   kasan_init_generic();
 }
 
 void __init kasan_late_init(void) { }
diff --git a/arch/powerpc/mm/kasan/init_book3s_64.c 
b/arch/powerpc/mm/kasan/init_book3s_64.c
index 7d959544c07..dcafa641804 100644
--- a/arch/powerpc/mm/kasan/init_book3s_64.c
+++ b/arch/powerpc/mm/kasan/init_book3s_64.c
@@ -19,8 +19,6 @@
 #include 
 #include 
 
-DEFINE_STATIC_KEY_FALSE(powerpc_kasan_enabled_key);
-
 static void __init kasan_init_phys_region(void *start, void *end)
 {
unsigned long k_start, k_end, k_cur;
@@ -92,11 +90,9 @@ void __init kasan_init(void)
 */
memset(kasan_early_shadow_page, 0, PAGE_SIZE);
 
-   static_branch_inc(&powerpc_kasan_enabled_key);
-
/* Enable error messages */
init_task.kasan_depth = 0;
-   pr_info("KASAN init done\n");
+   kasan_init_generic();
 }
 
 void __init kasan_early_init(void) { }
-- 
2.34.1




[PATCH v3 07/12] kasan/loongarch: select ARCH_DEFER_KASAN and call kasan_init_generic

2025-07-17 Thread Sabyrzhan Tasbolatov
LoongArch needs deferred KASAN initialization as it has a custom
kasan_arch_is_ready() implementation that tracks shadow memory
readiness via the kasan_early_stage flag.

Select ARCH_DEFER_KASAN to enable the unified static key mechanism
for runtime KASAN control. Call kasan_init_generic() which handles
Generic KASAN initialization and enables the static key.

Replace kasan_arch_is_ready() with kasan_enabled() and delete the
flag kasan_early_stage in favor of the unified kasan_enabled()
interface.

Note that init_task.kasan_depth = 0 is called after kasan_init_generic(),
which is different than in other arch kasan_init(). This is left
unchanged as it cannot be tested.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049
Signed-off-by: Sabyrzhan Tasbolatov 
---
Changes in v3:
- Added CONFIG_ARCH_DEFER_KASAN selection to enable proper runtime control
---
 arch/loongarch/Kconfig | 1 +
 arch/loongarch/include/asm/kasan.h | 7 ---
 arch/loongarch/mm/kasan_init.c | 7 ++-
 3 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index 4b19f93379a..07130809a35 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -9,6 +9,7 @@ config LOONGARCH
select ACPI_PPTT if ACPI
select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
select ARCH_BINFMT_ELF_STATE
+   select ARCH_DEFER_KASAN
select ARCH_DISABLE_KASAN_INLINE
select ARCH_ENABLE_MEMORY_HOTPLUG
select ARCH_ENABLE_MEMORY_HOTREMOVE
diff --git a/arch/loongarch/include/asm/kasan.h 
b/arch/loongarch/include/asm/kasan.h
index 62f139a9c87..0e50e5b5e05 100644
--- a/arch/loongarch/include/asm/kasan.h
+++ b/arch/loongarch/include/asm/kasan.h
@@ -66,7 +66,6 @@
 #define XKPRANGE_WC_SHADOW_OFFSET  (KASAN_SHADOW_START + 
XKPRANGE_WC_KASAN_OFFSET)
 #define XKVRANGE_VC_SHADOW_OFFSET  (KASAN_SHADOW_START + 
XKVRANGE_VC_KASAN_OFFSET)
 
-extern bool kasan_early_stage;
 extern unsigned char kasan_early_shadow_page[PAGE_SIZE];
 
 #define kasan_mem_to_shadow kasan_mem_to_shadow
@@ -75,12 +74,6 @@ void *kasan_mem_to_shadow(const void *addr);
 #define kasan_shadow_to_mem kasan_shadow_to_mem
 const void *kasan_shadow_to_mem(const void *shadow_addr);
 
-#define kasan_arch_is_ready kasan_arch_is_ready
-static __always_inline bool kasan_arch_is_ready(void)
-{
-   return !kasan_early_stage;
-}
-
 #define addr_has_metadata addr_has_metadata
 static __always_inline bool addr_has_metadata(const void *addr)
 {
diff --git a/arch/loongarch/mm/kasan_init.c b/arch/loongarch/mm/kasan_init.c
index d2681272d8f..cf8315f9119 100644
--- a/arch/loongarch/mm/kasan_init.c
+++ b/arch/loongarch/mm/kasan_init.c
@@ -40,11 +40,9 @@ static pgd_t kasan_pg_dir[PTRS_PER_PGD] __initdata 
__aligned(PAGE_SIZE);
 #define __pte_none(early, pte) (early ? pte_none(pte) : \
 ((pte_val(pte) & _PFN_MASK) == (unsigned long)__pa(kasan_early_shadow_page)))
 
-bool kasan_early_stage = true;
-
 void *kasan_mem_to_shadow(const void *addr)
 {
-   if (!kasan_arch_is_ready()) {
+   if (!kasan_enabled()) {
return (void *)(kasan_early_shadow_page);
} else {
unsigned long maddr = (unsigned long)addr;
@@ -298,7 +296,7 @@ void __init kasan_init(void)
kasan_populate_early_shadow(kasan_mem_to_shadow((void *)VMALLOC_START),
kasan_mem_to_shadow((void 
*)KFENCE_AREA_END));
 
-   kasan_early_stage = false;
+   kasan_init_generic();
 
/* Populate the linear mapping */
for_each_mem_range(i, &pa_start, &pa_end) {
@@ -329,5 +327,4 @@ void __init kasan_init(void)
 
/* At this point kasan is fully initialized. Enable error messages */
init_task.kasan_depth = 0;
-   pr_info("KernelAddressSanitizer initialized.\n");
 }
-- 
2.34.1




[PATCH v3 02/12] kasan: unify static kasan_flag_enabled across modes

2025-07-17 Thread Sabyrzhan Tasbolatov
Historically, the runtime static key kasan_flag_enabled existed only for
CONFIG_KASAN_HW_TAGS mode. Generic and SW_TAGS modes either relied on
architecture-specific kasan_arch_is_ready() implementations or evaluated
KASAN checks unconditionally, leading to code duplication.

This patch implements two-level approach:

1. kasan_enabled() - controls if KASAN is enabled at all (compile-time)
2. kasan_shadow_initialized() - tracks shadow memory
   initialization (runtime)

For architectures that select ARCH_DEFER_KASAN: kasan_shadow_initialized()
uses a static key that gets enabled when shadow memory is ready.

For architectures that don't: kasan_shadow_initialized() returns
IS_ENABLED(CONFIG_KASAN) since shadow is ready from the start.

This provides:
- Consistent interface across all KASAN modes
- Runtime control only where actually needed
- Compile-time constants for optimal performance where possible
- Clear separation between "KASAN configured" vs "shadow ready"

Also adds kasan_init_generic() function that enables the shadow flag and
handles initialization for Generic mode, and updates SW_TAGS and HW_TAGS
to use the unified kasan_shadow_enable() function.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049
Signed-off-by: Sabyrzhan Tasbolatov 
---
Changes in v3:
- Only architectures that need deferred KASAN get runtime overhead
- Added kasan_shadow_initialized() for shadow memory readiness tracking
- kasan_enabled() now provides compile-time check for KASAN configuration
---
 include/linux/kasan-enabled.h | 34 ++
 include/linux/kasan.h |  6 ++
 mm/kasan/common.c |  9 +
 mm/kasan/generic.c| 11 +++
 mm/kasan/hw_tags.c|  9 +
 mm/kasan/sw_tags.c|  2 ++
 6 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/include/linux/kasan-enabled.h b/include/linux/kasan-enabled.h
index 6f612d69ea0..fa99dc58f95 100644
--- a/include/linux/kasan-enabled.h
+++ b/include/linux/kasan-enabled.h
@@ -4,32 +4,50 @@
 
 #include 
 
-#ifdef CONFIG_KASAN_HW_TAGS
+/* Controls whether KASAN is enabled at all (compile-time check). */
+static __always_inline bool kasan_enabled(void)
+{
+   return IS_ENABLED(CONFIG_KASAN);
+}
 
+#ifdef CONFIG_ARCH_DEFER_KASAN
+/*
+ * Global runtime flag for architectures that need deferred KASAN.
+ * Switched to 'true' by the appropriate kasan_init_*()
+ * once KASAN is fully initialized.
+ */
 DECLARE_STATIC_KEY_FALSE(kasan_flag_enabled);
 
-static __always_inline bool kasan_enabled(void)
+static __always_inline bool kasan_shadow_initialized(void)
 {
return static_branch_likely(&kasan_flag_enabled);
 }
 
-static inline bool kasan_hw_tags_enabled(void)
+static inline void kasan_enable(void)
+{
+   static_branch_enable(&kasan_flag_enabled);
+}
+#else
+/* For architectures that can enable KASAN early, use compile-time check. */
+static __always_inline bool kasan_shadow_initialized(void)
 {
return kasan_enabled();
 }
 
-#else /* CONFIG_KASAN_HW_TAGS */
+/* No-op for architectures that don't need deferred KASAN. */
+static inline void kasan_enable(void) {}
+#endif /* CONFIG_ARCH_DEFER_KASAN */
 
-static inline bool kasan_enabled(void)
+#ifdef CONFIG_KASAN_HW_TAGS
+static inline bool kasan_hw_tags_enabled(void)
 {
-   return IS_ENABLED(CONFIG_KASAN);
+   return kasan_enabled();
 }
-
+#else
 static inline bool kasan_hw_tags_enabled(void)
 {
return false;
 }
-
 #endif /* CONFIG_KASAN_HW_TAGS */
 
 #endif /* LINUX_KASAN_ENABLED_H */
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 890011071f2..51a8293d1af 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -543,6 +543,12 @@ void kasan_report_async(void);
 
 #endif /* CONFIG_KASAN_HW_TAGS */
 
+#ifdef CONFIG_KASAN_GENERIC
+void __init kasan_init_generic(void);
+#else
+static inline void kasan_init_generic(void) { }
+#endif
+
 #ifdef CONFIG_KASAN_SW_TAGS
 void __init kasan_init_sw_tags(void);
 #else
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index ed4873e18c7..c3a6446404d 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -32,6 +32,15 @@
 #include "kasan.h"
 #include "../slab.h"
 
+#ifdef CONFIG_ARCH_DEFER_KASAN
+/*
+ * Definition of the unified static key declared in kasan-enabled.h.
+ * This provides consistent runtime enable/disable across KASAN modes.
+ */
+DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled);
+EXPORT_SYMBOL(kasan_flag_enabled);
+#endif
+
 struct slab *kasan_addr_to_slab(const void *addr)
 {
if (virt_addr_valid(addr))
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index d54e89f8c3e..03b6d322ff6 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -36,6 +36,17 @@
 #include "kasan.h"
 #include "../slab.h"
 
+/*
+ * Initialize Generic KASAN and enable runtime checks.
+ * This should be called from arch kasan_init() once shadow memory is ready.
+ */
+void __init kasan_init_generic(void)
+{
+   kasan_enable();
+
+   

[PATCH v3 04/12] kasan/arm64: call kasan_init_generic in kasan_init

2025-07-17 Thread Sabyrzhan Tasbolatov
Call kasan_init_generic() which handles Generic KASAN initialization.
Since arm64 doesn't select ARCH_DEFER_KASAN, this will be a no-op for
the runtime flag but will print the initialization banner.

For SW_TAGS and HW_TAGS modes, their respective init functions will
handle the flag enabling.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049
Signed-off-by: Sabyrzhan Tasbolatov 
---
 arch/arm64/mm/kasan_init.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/arch/arm64/mm/kasan_init.c b/arch/arm64/mm/kasan_init.c
index d541ce45dae..abeb81bf6eb 100644
--- a/arch/arm64/mm/kasan_init.c
+++ b/arch/arm64/mm/kasan_init.c
@@ -399,14 +399,12 @@ void __init kasan_init(void)
 {
kasan_init_shadow();
kasan_init_depth();
-#if defined(CONFIG_KASAN_GENERIC)
+   kasan_init_generic();
/*
 * Generic KASAN is now fully initialized.
 * Software and Hardware Tag-Based modes still require
 * kasan_init_sw_tags() and kasan_init_hw_tags() correspondingly.
 */
-   pr_info("KernelAddressSanitizer initialized (generic)\n");
-#endif
 }
 
 #endif /* CONFIG_KASAN_GENERIC || CONFIG_KASAN_SW_TAGS */
-- 
2.34.1




[PATCH v3 06/12] kasan/xtensa: call kasan_init_generic in kasan_init

2025-07-17 Thread Sabyrzhan Tasbolatov
Call kasan_init_generic() which handles Generic KASAN initialization
and prints the banner. Since xtensa doesn't select ARCH_DEFER_KASAN,
kasan_enable() will be a no-op.

Note that arch/xtensa still uses "current" instead of "init_task" pointer
in `current->kasan_depth = 0;` to enable error messages. This is left
unchanged as it cannot be tested.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049
Signed-off-by: Sabyrzhan Tasbolatov 
---
 arch/xtensa/mm/kasan_init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/xtensa/mm/kasan_init.c b/arch/xtensa/mm/kasan_init.c
index f39c4d83173..0524b9ed5e6 100644
--- a/arch/xtensa/mm/kasan_init.c
+++ b/arch/xtensa/mm/kasan_init.c
@@ -94,5 +94,5 @@ void __init kasan_init(void)
 
/* At this point kasan is fully initialized. Enable error messages. */
current->kasan_depth = 0;
-   pr_info("KernelAddressSanitizer initialized\n");
+   kasan_init_generic();
 }
-- 
2.34.1




[PATCH v3 05/12] kasan/arm: call kasan_init_generic in kasan_init

2025-07-17 Thread Sabyrzhan Tasbolatov
Call kasan_init_generic() which handles Generic KASAN initialization
and prints the banner. Since arm doesn't select ARCH_DEFER_KASAN,
kasan_enable() will be a no-op, but kasan_enabled() will return
IS_ENABLED(CONFIG_KASAN) for optimal compile-time behavior.

Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217049
Signed-off-by: Sabyrzhan Tasbolatov 
---
 arch/arm/mm/kasan_init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mm/kasan_init.c b/arch/arm/mm/kasan_init.c
index 111d4f70313..c6625e808bf 100644
--- a/arch/arm/mm/kasan_init.c
+++ b/arch/arm/mm/kasan_init.c
@@ -300,6 +300,6 @@ void __init kasan_init(void)
local_flush_tlb_all();
 
memset(kasan_early_shadow_page, 0, PAGE_SIZE);
-   pr_info("Kernel address sanitizer initialized\n");
init_task.kasan_depth = 0;
+   kasan_init_generic();
 }
-- 
2.34.1




Re: [PATCH v2] integrity: Extract secure boot enquiry function out of IMA

2025-07-17 Thread GONG Ruiqi


On 7/8/2025 4:35 AM, Nayna Jain wrote:
> 
> On 7/2/25 10:07 PM, GONG Ruiqi wrote:
>> 
>> ...
>>
>> "We encountered a boot failure issue in an in-house testing, where the
>> kernel refused to load its modules since it couldn't verify their
>> signature. The root cause turned out to be the early return of
>> load_uefi_certs(), where arch_ima_get_secureboot() returned false
>> unconditionally due to CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT=n, even
>> though the secure boot was enabled.
> Thanks for sharing additional details.
> 
> From x86 Kconfig:
> 
> /For config x86:
> 
>     imply IMA_SECURE_AND_OR_TRUSTED_BOOT    if EFI
> /
> And IMA_SECURE_AND_OR_TRUSTED_BOOT is dependent on IMA_ARCH_POLICY .
> 
> And from Linux Kernel Kbuild documentation( https://docs.kernel.org/
> kbuild/kconfig-language.html) :
> 
> /weak reverse dependencies: “imply”  [“if” ]
> 
> This is similar to “select” as it enforces a lower limit on another
> symbol except that the “implied” symbol’s value may still be set to n
> from a direct dependency or with a visible prompt.
> 
> /Following the example from the documentation, if  it is EFI enabled and
> IMA_ARCH_POLICY is set to y then this config should be default enabled.
> 
> If it is EFI enabled and IMA_ARCH_POLICY is set to N, then the setting
> for IMA_SECURE_AND_OR_TRUSTED_BOOT should be prompted during the build.
> The default setting for prompt is N. So, the person doing the build
> should actually select Y to enable IMA_ARCH_POLICY.
> 
> Wondering what is the scenario for you? Unless you have IMA_ARCH_POLICY
> set to N, this config should have been ideally enabled. If you have
> explicitly set it to N, am curious any specific reason for that.

Hi Nayna. Sorry for the late reply. Super busy these days...

Yes, IMA_ARCH_POLICY was not set. The testing was conducted on
openEuler[1], a Linux distro mainly for arm64 & x86, and the kernel was
compiled based on its own openeuler_defconfig[2], which set
IMA_ARCH_POLICY to N.

-Ruiqi

[1]: https://www.openeuler.org/en/
[2]:
https://gitee.com/openeuler/kernel/blob/OLK-6.6/arch/arm64/configs/openeuler_defconfig


> 
> Thanks & Regards,
> 
>    - Nayna
>>
>> ...




Re: [PATCH v2 0/7] syscore: Pass context data to callbacks

2025-07-17 Thread Greg Kroah-Hartman
On Thu, Jul 17, 2025 at 12:32:34PM +0200, Thierry Reding wrote:
> From: Thierry Reding 
> 
> Hi,
> 
> Something that's been bugging me over the years is how some drivers have
> had to adopt file-scoped variables to pass data into something like the
> syscore operations. This is often harmless, but usually leads to drivers
> not being able to deal with multiple instances, or additional frameworks
> or data structures needing to be created to handle multiple instances.
> 
> This series proposes to "objectify" struct syscore_ops by passing a
> pointer to struct syscore_ops to the syscore callbacks. Implementations
> of these callbacks can then make use of container_of() to get access to
> contextual data that struct syscore_ops was embedded in. This elegantly
> avoids the need for file-scoped, singleton variables, by tying syscore
> to individual instances.
> 
> Patch 1 contains the bulk of these changes. It's fairly intrusive
> because it does the conversion of the function signature all in one
> patch. An alternative would've been to introduce new callbacks such that
> these changes could be staged in. However, the amount of changes here
> are not quite numerous enough to justify that, in my opinion, and
> syscore isn't very frequently used, so the risk of another user getting
> added while this is merged is rather small. All in all I think merging
> this in one go is the simplest way.

All at once is good, I like the idea, but:

> Patches 2-7 are conversions of some existing drivers to take advantage
> of this new parameter and tie the code to per-instance data.

That's great, but none of these conversions actually get rid of the
global structure, so what actually was helped here other than the churn
of this "potentially" allowing the global data variables from being
removed in the future?

So how does this actually help?

Also, small nit, make the function pointers const please :)

thanks,

greg k-h



Re: [PATCH v2] powerpc: Replace the obsolete address of the FSF

2025-07-17 Thread Zavras, Alexios
Thanks, Richard.

I've opened an issue for the SPDX License List 
https://github.com/spdx/license-list-XML/issues/2785 and if no one else reacts 
faster, I plan to submit a PR to implement this next week.

-- zvr --

From: Richard Fontana 
Sent: Sunday, July 13, 2025 16:27
To: Maciej W. Rozycki 
Cc: Segher Boessenkool ; Greg Kroah-Hartman 
; Christoph Hellwig ; Thomas 
Huth ; Madhavan Srinivasan ; Michael 
Ellerman ; Thomas Gleixner ; Nicholas 
Piggin ; Christophe Leroy ; 
linuxppc-dev@lists.ozlabs.org ; 
linux-ker...@vger.kernel.org ; 
k...@vger.kernel.org ; linux-s...@vger.kernel.org 
; J Lovejoy 
Subject: Re: [PATCH v2] powerpc: Replace the obsolete address of the FSF

On Sat, Jul 12, 2025 at 6:48 PM Maciej W. Rozycki  wrote:
>
> On Fri, 11 Jul 2025, Richard Fontana wrote:
>
> > > > while this one:
> > > >
> > > >  *As a special exception, if you link this library with files
> > > >  *compiled with GCC to produce an executable, this does not cause
> > > >  *the resulting executable to be covered by the GNU General Public 
> > > > License.
> > > >  *This exception does not however invalidate any other reasons why
> > > >  *the executable file might be covered by the GNU General Public 
> > > > License.
> > > >
> > > > does not seem to be in the SPDX exception list. It is very similar to
> > > > `GNU-compiler-exception` except it specifically mentions GCC instead
> > > > of saying "a GNU compiler".
> > >
> > > https://spdx.org/licenses/GNU-compiler-exception.html
> > >
> > > is exactly this.
> >
> > No, because `GNU-compiler-exception` as defined here
> > https://github.com/spdx/license-list-XML/blob/main/src/exceptions/GNU-compiler-exception.xml
> > assumes use of the term "GCC" rather than "a GNU compiler".
>
>  I don't know what the legal status of the statement referred is, however
> the original exception as published[1] by FSF says:
>
> '"GCC" means a version of the GNU Compiler Collection, with or without
> modifications, governed by version 3 (or a specified later version) of the
> GNU General Public License (GPL) with the option of using any subsequent
> versions published by the FSF.'

> which I think makes it clear that "GCC" is a collection of "GNU compilers"
> and therefore the two terms are synonymous to each other for the purpose
> of said exception (in the old days "GCC" stood for "GNU C Compiler", but
> the old meaning makes no sense anymore now that we have compilers for Ada,
> Fortran and many other languages included in GCC).
>
>  NB up to date versions of CRT code refer to the exception as published
> rather than pasting an old version of its text:
>
> 'Under Section 7 of GPL version 3, you are granted additional
> permissions described in the GCC Runtime Library Exception, version
> 3.1, as published by the Free Software Foundation.'
>
> References:
>
> [1] "GCC Runtime Library Exception", version 3.1,
> 

I think we're basically talking past each other. The definition of
"GCC" in the GCC runtime library exception 3.1 is irrelevant because
that file does not refer to that exception. In SPDX, license (and
exception) identifiers are precisely defined. Unless I'm missing
something there is no official SPDX identifier that corresponds to
this text:

  As a special exception, if you link this library with files
  compiled with GCC to produce an executable, this does not cause
  the resulting executable to be covered by the GNU General Public License.
  This exception does not however invalidate any other reasons why
  the executable file might be covered by the GNU General Public License.

I'm not personally a major supporter of SPDX and I'm the last person
who would want to be associated with SPDX pedanticism but it's a
standard and if the Linux kernel project is going to use it IMO it
should conform to that standard, otherwise you're basically making ad
hoc definitions of pseudo-SPDX expressions or redefinitions of
already-defined SPDX identifiers, which seems to defeat the purpose of
using SPDX expressions at all. Under that standard, there is currently
no SPDX identifier representing the above text (as far as I can tell).
The solution is either to propose a modification of
`GNU-compiler-exception` so that "GCC" is accepted as an alternative
to "a GNU compiler", or to propose a new exception to be added to
SPDX's exception list, or to use a custom-defined `AdditionRef-`
identifier.

Richard


Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928


[PATCH v2 1/7] syscore: Pass context data to callbacks

2025-07-17 Thread Thierry Reding
From: Thierry Reding 

Pass a pointer to the syscore_ops structure that was registered to the
callbacks. This enables callbacks to act on instance data (syscore_ops
can be embedded into other structures, and driver-specific data can be
obtained using container_of()) rather than the current practice of
relying on global variables.

Signed-off-by: Thierry Reding 
---
Changes in v2:
- add missing kerneldoc for added ops parameter

 arch/arm/mach-exynos/mcpm-exynos.c|  4 ++--
 arch/arm/mach-exynos/suspend.c| 14 +++---
 arch/arm/mach-pxa/irq.c   |  4 ++--
 arch/arm/mach-pxa/mfp-pxa2xx.c|  4 ++--
 arch/arm/mach-pxa/mfp-pxa3xx.c|  4 ++--
 arch/arm/mach-pxa/smemc.c |  4 ++--
 arch/arm/mach-s3c/irq-pm-s3c64xx.c|  4 ++--
 arch/arm/mach-s5pv210/pm.c|  2 +-
 arch/arm/mach-versatile/integrator_ap.c   |  4 ++--
 arch/arm/mm/cache-b15-rac.c   |  4 ++--
 arch/loongarch/kernel/smp.c   |  4 ++--
 arch/mips/alchemy/common/dbdma.c  |  4 ++--
 arch/mips/alchemy/common/irq.c|  8 
 arch/mips/alchemy/common/usb.c|  4 ++--
 arch/mips/pci/pci-alchemy.c   |  4 ++--
 arch/powerpc/platforms/cell/spu_base.c|  2 +-
 arch/powerpc/platforms/powermac/pic.c |  4 ++--
 arch/powerpc/sysdev/fsl_lbc.c |  4 ++--
 arch/powerpc/sysdev/fsl_pci.c |  4 ++--
 arch/powerpc/sysdev/ipic.c|  4 ++--
 arch/powerpc/sysdev/mpic.c|  4 ++--
 arch/powerpc/sysdev/mpic_timer.c  |  2 +-
 arch/sh/mm/pmb.c  |  2 +-
 arch/x86/events/amd/ibs.c |  4 ++--
 arch/x86/hyperv/hv_init.c |  4 ++--
 arch/x86/kernel/amd_gart_64.c |  2 +-
 arch/x86/kernel/apic/apic.c   |  4 ++--
 arch/x86/kernel/apic/io_apic.c|  9 +++--
 arch/x86/kernel/cpu/aperfmperf.c  |  6 +++---
 arch/x86/kernel/cpu/intel_epb.c   |  8 
 arch/x86/kernel/cpu/mce/core.c|  6 +++---
 arch/x86/kernel/cpu/microcode/core.c  |  7 ++-
 arch/x86/kernel/cpu/mtrr/legacy.c |  4 ++--
 arch/x86/kernel/cpu/umwait.c  |  2 +-
 arch/x86/kernel/i8237.c   |  2 +-
 arch/x86/kernel/i8259.c   |  6 +++---
 arch/x86/kernel/kvm.c |  4 ++--
 drivers/acpi/pci_link.c   |  2 +-
 drivers/acpi/sleep.c  |  4 ++--
 drivers/base/firmware_loader/main.c   |  2 +-
 drivers/base/syscore.c|  8 
 drivers/bus/mvebu-mbus.c  |  4 ++--
 drivers/clk/at91/pmc.c|  4 ++--
 drivers/clk/imx/clk-vf610.c   |  4 ++--
 drivers/clk/ingenic/pm.c  |  4 ++--
 drivers/clk/ingenic/tcu.c |  4 ++--
 drivers/clk/mvebu/common.c|  4 ++--
 drivers/clk/rockchip/clk-rk3288.c |  4 ++--
 drivers/clk/samsung/clk-s5pv210-audss.c   |  4 ++--
 drivers/clk/samsung/clk.c |  4 ++--
 drivers/clk/tegra/clk-tegra210.c  |  4 ++--
 drivers/clocksource/timer-armada-370-xp.c |  4 ++--
 drivers/cpuidle/cpuidle-psci.c|  4 ++--
 drivers/gpio/gpio-mxc.c   |  4 ++--
 drivers/gpio/gpio-pxa.c   |  4 ++--
 drivers/gpio/gpio-sa1100.c|  4 ++--
 drivers/hv/vmbus_drv.c|  4 ++--
 drivers/iommu/amd/init.c  |  4 ++--
 drivers/iommu/intel/iommu.c   |  4 ++--
 drivers/irqchip/exynos-combiner.c |  6 --
 drivers/irqchip/irq-armada-370-xp.c   |  4 ++--
 drivers/irqchip/irq-bcm7038-l1.c  |  4 ++--
 drivers/irqchip/irq-gic-v3-its.c  |  4 ++--
 drivers/irqchip/irq-i8259.c   |  4 ++--
 drivers/irqchip/irq-imx-gpcv2.c   |  4 ++--
 drivers/irqchip/irq-loongson-eiointc.c|  4 ++--
 drivers/irqchip/irq-loongson-htpic.c  |  2 +-
 drivers/irqchip/irq-loongson-htvec.c  |  4 ++--
 drivers/irqchip/irq-loongson-pch-lpc.c|  4 ++--
 drivers/irqchip/irq-loongson-pch-pic.c|  4 ++--
 drivers/irqchip/irq-mchp-eic.c|  4 ++--
 drivers/irqchip/irq-mst-intc.c|  4 ++--
 drivers/irqchip/irq-mtk-cirq.c|  4 ++--
 drivers/irqchip/irq-renesas-rzg2l.c   |  4 ++--
 drivers/irqchip/irq-sa11x0.c  |  4 ++--
 drivers/irqchip/irq-sifive-plic.c |  4 ++--
 drivers/irqchip/irq-sun6i-r.c | 10 +-
 drivers/irqchip/irq-tegra.c   |  4 ++--
 drivers/irqchip/irq-vic.c |  4 ++--
 drivers/leds/trigger/ledtrig-cpu.c|  6 +++---
 drivers/macintosh/via-pmu.c   |  4 ++--
 drivers/power/reset/sc27xx-poweroff.c |  2 +-
 drivers/sh/clk/core.c |  2 +-
 drivers/sh/intc/core.c|  4 ++--
 drivers/soc/bcm/brcmstb/biuctrl.c |  4 ++--
 drivers/soc/tegra/pmc.c

[PATCH v2 0/7] syscore: Pass context data to callbacks

2025-07-17 Thread Thierry Reding
From: Thierry Reding 

Hi,

Something that's been bugging me over the years is how some drivers have
had to adopt file-scoped variables to pass data into something like the
syscore operations. This is often harmless, but usually leads to drivers
not being able to deal with multiple instances, or additional frameworks
or data structures needing to be created to handle multiple instances.

This series proposes to "objectify" struct syscore_ops by passing a
pointer to struct syscore_ops to the syscore callbacks. Implementations
of these callbacks can then make use of container_of() to get access to
contextual data that struct syscore_ops was embedded in. This elegantly
avoids the need for file-scoped, singleton variables, by tying syscore
to individual instances.

Patch 1 contains the bulk of these changes. It's fairly intrusive
because it does the conversion of the function signature all in one
patch. An alternative would've been to introduce new callbacks such that
these changes could be staged in. However, the amount of changes here
are not quite numerous enough to justify that, in my opinion, and
syscore isn't very frequently used, so the risk of another user getting
added while this is merged is rather small. All in all I think merging
this in one go is the simplest way.

Patches 2-7 are conversions of some existing drivers to take advantage
of this new parameter and tie the code to per-instance data.

Given that the recipient list for this is huge, I'm limiting this to
Greg (because it's at the core a... core change) and a set of larger
lists for architectures and subsystems that are impacted.

Changes in v2:
- kerneldoc fixes

Thanks,
Thierry

Thierry Reding (7):
  syscore: Pass context data to callbacks
  MIPS: Embed syscore_ops in PCI context
  bus: mvebu-mbus: Embed syscore_ops in mbus context
  clk: ingenic: tcu: Embed syscore_ops in TCU context
  clk: mvebu: Embed syscore_ops in clock context
  irqchip/irq-imx-gpcv2: Embed syscore_ops in chip context
  soc/tegra: pmc: Derive PMC context from syscore ops

 arch/arm/mach-exynos/mcpm-exynos.c|  4 +-
 arch/arm/mach-exynos/suspend.c| 14 +++---
 arch/arm/mach-pxa/irq.c   |  4 +-
 arch/arm/mach-pxa/mfp-pxa2xx.c|  4 +-
 arch/arm/mach-pxa/mfp-pxa3xx.c|  4 +-
 arch/arm/mach-pxa/smemc.c |  4 +-
 arch/arm/mach-s3c/irq-pm-s3c64xx.c|  4 +-
 arch/arm/mach-s5pv210/pm.c|  2 +-
 arch/arm/mach-versatile/integrator_ap.c   |  4 +-
 arch/arm/mm/cache-b15-rac.c   |  4 +-
 arch/loongarch/kernel/smp.c   |  4 +-
 arch/mips/alchemy/common/dbdma.c  |  4 +-
 arch/mips/alchemy/common/irq.c|  8 ++--
 arch/mips/alchemy/common/usb.c|  4 +-
 arch/mips/pci/pci-alchemy.c   | 28 ++--
 arch/powerpc/platforms/cell/spu_base.c|  2 +-
 arch/powerpc/platforms/powermac/pic.c |  4 +-
 arch/powerpc/sysdev/fsl_lbc.c |  4 +-
 arch/powerpc/sysdev/fsl_pci.c |  4 +-
 arch/powerpc/sysdev/ipic.c|  4 +-
 arch/powerpc/sysdev/mpic.c|  4 +-
 arch/powerpc/sysdev/mpic_timer.c  |  2 +-
 arch/sh/mm/pmb.c  |  2 +-
 arch/x86/events/amd/ibs.c |  4 +-
 arch/x86/hyperv/hv_init.c |  4 +-
 arch/x86/kernel/amd_gart_64.c |  2 +-
 arch/x86/kernel/apic/apic.c   |  4 +-
 arch/x86/kernel/apic/io_apic.c|  9 +++-
 arch/x86/kernel/cpu/aperfmperf.c  |  6 +--
 arch/x86/kernel/cpu/intel_epb.c   |  8 ++--
 arch/x86/kernel/cpu/mce/core.c|  6 +--
 arch/x86/kernel/cpu/microcode/core.c  |  7 ++-
 arch/x86/kernel/cpu/mtrr/legacy.c |  4 +-
 arch/x86/kernel/cpu/umwait.c  |  2 +-
 arch/x86/kernel/i8237.c   |  2 +-
 arch/x86/kernel/i8259.c   |  6 +--
 arch/x86/kernel/kvm.c |  4 +-
 drivers/acpi/pci_link.c   |  2 +-
 drivers/acpi/sleep.c  |  4 +-
 drivers/base/firmware_loader/main.c   |  2 +-
 drivers/base/syscore.c|  8 ++--
 drivers/bus/mvebu-mbus.c  | 24 +-
 drivers/clk/at91/pmc.c|  4 +-
 drivers/clk/imx/clk-vf610.c   |  4 +-
 drivers/clk/ingenic/pm.c  |  4 +-
 drivers/clk/ingenic/tcu.c | 54 +++
 drivers/clk/mvebu/common.c| 25 +++
 drivers/clk/rockchip/clk-rk3288.c |  4 +-
 drivers/clk/samsung/clk-s5pv210-audss.c   |  4 +-
 drivers/clk/samsung/clk.c |  4 +-
 drivers/clk/tegra/clk-tegra210.c  |  4 +-
 drivers/clocksource/timer-armada-370-xp.c |  4 +-
 drivers/cpuidle/cpuidle-psci.c|  4 +-
 drivers/gpio/gpio-mxc.c   |  4 +-
 drivers/gpio/gpio-pxa.c   |  4 +-
 drivers/gpio/gpio-sa1100.c|  4 +-
 drivers/hv/vmbus_drv.c   

[PATCH v2 2/7] MIPS: Embed syscore_ops in PCI context

2025-07-17 Thread Thierry Reding
From: Thierry Reding 

This enables the syscore callbacks to obtain the PCI context without
relying on a separate global variable.

Signed-off-by: Thierry Reding 
---
 arch/mips/pci/pci-alchemy.c | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/arch/mips/pci/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c
index a20de7160b6b..02f0616518e1 100644
--- a/arch/mips/pci/pci-alchemy.c
+++ b/arch/mips/pci/pci-alchemy.c
@@ -33,6 +33,7 @@
 
 struct alchemy_pci_context {
struct pci_controller alchemy_pci_ctrl; /* leave as first member! */
+   struct syscore_ops pmops;
void __iomem *regs; /* ctrl base */
/* tools for wired entry for config space access */
unsigned long last_elo0;
@@ -46,6 +47,12 @@ struct alchemy_pci_context {
int (*board_pci_idsel)(unsigned int devsel, int assert);
 };
 
+static inline struct alchemy_pci_context *
+syscore_to_pci_context(struct syscore_ops *ops)
+{
+   return container_of(ops, struct alchemy_pci_context, pmops);
+}
+
 /* for syscore_ops. There's only one PCI controller on Alchemy chips, so this
  * should suffice for now.
  */
@@ -306,9 +313,7 @@ static int alchemy_pci_def_idsel(unsigned int devsel, int 
assert)
 /* save PCI controller register contents. */
 static int alchemy_pci_suspend(struct syscore_ops *ops)
 {
-   struct alchemy_pci_context *ctx = __alchemy_pci_ctx;
-   if (!ctx)
-   return 0;
+   struct alchemy_pci_context *ctx = syscore_to_pci_context(ops);
 
ctx->pm[0]  = __raw_readl(ctx->regs + PCI_REG_CMEM);
ctx->pm[1]  = __raw_readl(ctx->regs + PCI_REG_CONFIG) & 0x0009;
@@ -328,9 +333,7 @@ static int alchemy_pci_suspend(struct syscore_ops *ops)
 
 static void alchemy_pci_resume(struct syscore_ops *ops)
 {
-   struct alchemy_pci_context *ctx = __alchemy_pci_ctx;
-   if (!ctx)
-   return;
+   struct alchemy_pci_context *ctx = syscore_to_pci_context(ops);
 
__raw_writel(ctx->pm[0],  ctx->regs + PCI_REG_CMEM);
__raw_writel(ctx->pm[2],  ctx->regs + PCI_REG_B2BMASK_CCH);
@@ -354,11 +357,6 @@ static void alchemy_pci_resume(struct syscore_ops *ops)
alchemy_pci_wired_entry(ctx);   /* install it */
 }
 
-static struct syscore_ops alchemy_pci_pmops = {
-   .suspend= alchemy_pci_suspend,
-   .resume = alchemy_pci_resume,
-};
-
 static int alchemy_pci_probe(struct platform_device *pdev)
 {
struct alchemy_pci_platdata *pd = pdev->dev.platform_data;
@@ -478,7 +476,9 @@ static int alchemy_pci_probe(struct platform_device *pdev)
 
__alchemy_pci_ctx = ctx;
platform_set_drvdata(pdev, ctx);
-   register_syscore_ops(&alchemy_pci_pmops);
+   ctx->pmops.suspend = alchemy_pci_suspend;
+   ctx->pmops.resume = alchemy_pci_resume;
+   register_syscore_ops(&ctx->pmops);
register_pci_controller(&ctx->alchemy_pci_ctrl);
 
dev_info(&pdev->dev, "PCI controller at %ld MHz\n",
-- 
2.50.0




[PATCH v2 3/7] bus: mvebu-mbus: Embed syscore_ops in mbus context

2025-07-17 Thread Thierry Reding
From: Thierry Reding 

This enables the syscore callbacks to obtain the mbus context without
relying on a separate global variable.

Signed-off-by: Thierry Reding 
---
 drivers/bus/mvebu-mbus.c | 20 
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index 92daa45cc844..1f22bff0773c 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -130,6 +130,7 @@ struct mvebu_mbus_win_data {
 };
 
 struct mvebu_mbus_state {
+   struct syscore_ops syscore;
void __iomem *mbuswins_base;
void __iomem *sdramwins_base;
void __iomem *mbusbridge_base;
@@ -148,6 +149,12 @@ struct mvebu_mbus_state {
struct mvebu_mbus_win_data wins[MBUS_WINS_MAX];
 };
 
+static inline struct mvebu_mbus_state *
+syscore_to_mbus(struct syscore_ops *ops)
+{
+   return container_of(ops, struct mvebu_mbus_state, syscore);
+}
+
 static struct mvebu_mbus_state mbus_state;
 
 /*
@@ -1008,7 +1015,7 @@ fs_initcall(mvebu_mbus_debugfs_init);
 
 static int mvebu_mbus_suspend(struct syscore_ops *ops)
 {
-   struct mvebu_mbus_state *s = &mbus_state;
+   struct mvebu_mbus_state *s = syscore_to_mbus(ops);
int win;
 
if (!s->mbusbridge_base)
@@ -1042,7 +1049,7 @@ static int mvebu_mbus_suspend(struct syscore_ops *ops)
 
 static void mvebu_mbus_resume(struct syscore_ops *ops)
 {
-   struct mvebu_mbus_state *s = &mbus_state;
+   struct mvebu_mbus_state *s = syscore_to_mbus(ops);
int win;
 
writel(s->mbus_bridge_ctrl,
@@ -1069,11 +1076,6 @@ static void mvebu_mbus_resume(struct syscore_ops *ops)
}
 }
 
-static struct syscore_ops mvebu_mbus_syscore_ops = {
-   .suspend= mvebu_mbus_suspend,
-   .resume = mvebu_mbus_resume,
-};
-
 static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
 phys_addr_t mbuswins_phys_base,
 size_t mbuswins_size,
@@ -1118,7 +1120,9 @@ static int __init mvebu_mbus_common_init(struct 
mvebu_mbus_state *mbus,
writel(UNIT_SYNC_BARRIER_ALL,
   mbus->mbuswins_base + UNIT_SYNC_BARRIER_OFF);
 
-   register_syscore_ops(&mvebu_mbus_syscore_ops);
+   mbus->syscore.suspend = mvebu_mbus_suspend;
+   mbus->syscore.resume = mvebu_mbus_resume;
+   register_syscore_ops(&mbus->syscore);
 
return 0;
 }
-- 
2.50.0




[PATCH v2 4/7] clk: ingenic: tcu: Embed syscore_ops in TCU context

2025-07-17 Thread Thierry Reding
From: Thierry Reding 

This enables the syscore callbacks to obtain the TCU context without
relying on a separate global variable.

Signed-off-by: Thierry Reding 
---
 drivers/clk/ingenic/tcu.c | 54 ++-
 1 file changed, 25 insertions(+), 29 deletions(-)

diff --git a/drivers/clk/ingenic/tcu.c b/drivers/clk/ingenic/tcu.c
index 85bd4bc73c1b..503a58d08224 100644
--- a/drivers/clk/ingenic/tcu.c
+++ b/drivers/clk/ingenic/tcu.c
@@ -53,9 +53,9 @@ struct ingenic_tcu {
struct clk *clk;
 
struct clk_hw_onecell_data *clocks;
-};
 
-static struct ingenic_tcu *ingenic_tcu;
+   struct syscore_ops syscore;
+};
 
 static inline struct ingenic_tcu_clk *to_tcu_clk(struct clk_hw *hw)
 {
@@ -332,6 +332,24 @@ static const struct of_device_id __maybe_unused 
ingenic_tcu_of_match[] __initcon
{ /* sentinel */ }
 };
 
+static int __maybe_unused tcu_pm_suspend(struct syscore_ops *ops)
+{
+   struct ingenic_tcu *tcu = container_of(ops, typeof(*tcu), syscore);
+
+   if (tcu->clk)
+   clk_disable(tcu->clk);
+
+   return 0;
+}
+
+static void __maybe_unused tcu_pm_resume(struct syscore_ops *ops)
+{
+   struct ingenic_tcu *tcu = container_of(ops, typeof(*tcu), syscore);
+
+   if (tcu->clk)
+   clk_enable(tcu->clk);
+}
+
 static int __init ingenic_tcu_probe(struct device_node *np)
 {
const struct of_device_id *id = of_match_node(ingenic_tcu_of_match, np);
@@ -430,7 +448,11 @@ static int __init ingenic_tcu_probe(struct device_node *np)
goto err_unregister_ost_clock;
}
 
-   ingenic_tcu = tcu;
+   if (IS_ENABLED(CONFIG_PM_SLEEP)) {
+   tcu->syscore.suspend = tcu_pm_suspend;
+   tcu->syscore.resume = tcu_pm_resume;
+   register_syscore_ops(&tcu->syscore);
+   }
 
return 0;
 
@@ -455,38 +477,12 @@ static int __init ingenic_tcu_probe(struct device_node 
*np)
return ret;
 }
 
-static int __maybe_unused tcu_pm_suspend(struct syscore_ops *ops)
-{
-   struct ingenic_tcu *tcu = ingenic_tcu;
-
-   if (tcu->clk)
-   clk_disable(tcu->clk);
-
-   return 0;
-}
-
-static void __maybe_unused tcu_pm_resume(struct syscore_ops *ops)
-{
-   struct ingenic_tcu *tcu = ingenic_tcu;
-
-   if (tcu->clk)
-   clk_enable(tcu->clk);
-}
-
-static struct syscore_ops __maybe_unused tcu_pm_ops = {
-   .suspend = tcu_pm_suspend,
-   .resume = tcu_pm_resume,
-};
-
 static void __init ingenic_tcu_init(struct device_node *np)
 {
int ret = ingenic_tcu_probe(np);
 
if (ret)
pr_crit("Failed to initialize TCU clocks: %d\n", ret);
-
-   if (IS_ENABLED(CONFIG_PM_SLEEP))
-   register_syscore_ops(&tcu_pm_ops);
 }
 
 CLK_OF_DECLARE_DRIVER(jz4740_cgu, "ingenic,jz4740-tcu", ingenic_tcu_init);
-- 
2.50.0




[PATCH v2 5/7] clk: mvebu: Embed syscore_ops in clock context

2025-07-17 Thread Thierry Reding
From: Thierry Reding 

This enables the syscore callbacks to obtain the clock context without
relying on a separate global variable.

Signed-off-by: Thierry Reding 
---
 drivers/clk/mvebu/common.c | 21 ++---
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c
index ee77d307efe0..53712c3e5087 100644
--- a/drivers/clk/mvebu/common.c
+++ b/drivers/clk/mvebu/common.c
@@ -189,6 +189,7 @@ void __init mvebu_coreclk_setup(struct device_node *np,
 DEFINE_SPINLOCK(ctrl_gating_lock);
 
 struct clk_gating_ctrl {
+   struct syscore_ops syscore;
spinlock_t *lock;
struct clk **gates;
int num_gates;
@@ -196,11 +197,15 @@ struct clk_gating_ctrl {
u32 saved_reg;
 };
 
-static struct clk_gating_ctrl *ctrl;
+static inline struct clk_gating_ctrl *from_syscore(struct syscore_ops *ops)
+{
+   return container_of(ops, struct clk_gating_ctrl, syscore);
+}
 
 static struct clk *clk_gating_get_src(
struct of_phandle_args *clkspec, void *data)
 {
+   struct clk_gating_ctrl *ctrl = data;
int n;
 
if (clkspec->args_count < 1)
@@ -217,23 +222,23 @@ static struct clk *clk_gating_get_src(
 
 static int mvebu_clk_gating_suspend(struct syscore_ops *ops)
 {
+   struct clk_gating_ctrl *ctrl = from_syscore(ops);
+
ctrl->saved_reg = readl(ctrl->base);
return 0;
 }
 
 static void mvebu_clk_gating_resume(struct syscore_ops *ops)
 {
+   struct clk_gating_ctrl *ctrl = from_syscore(ops);
+
writel(ctrl->saved_reg, ctrl->base);
 }
 
-static struct syscore_ops clk_gate_syscore_ops = {
-   .suspend = mvebu_clk_gating_suspend,
-   .resume = mvebu_clk_gating_resume,
-};
-
 void __init mvebu_clk_gating_setup(struct device_node *np,
   const struct clk_gating_soc_desc *desc)
 {
+   static struct clk_gating_ctrl *ctrl;
struct clk *clk;
void __iomem *base;
const char *default_parent = NULL;
@@ -284,7 +289,9 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
 
of_clk_add_provider(np, clk_gating_get_src, ctrl);
 
-   register_syscore_ops(&clk_gate_syscore_ops);
+   ctrl->syscore.suspend = mvebu_clk_gating_suspend;
+   ctrl->syscore.resume = mvebu_clk_gating_resume;
+   register_syscore_ops(&ctrl->syscore);
 
return;
 gates_out:
-- 
2.50.0




[PATCH v2 6/7] irqchip/irq-imx-gpcv2: Embed syscore_ops in chip context

2025-07-17 Thread Thierry Reding
From: Thierry Reding 

This enables the syscore callbacks to obtain the IRQ chip context
without relying on a separate global variable.

Signed-off-by: Thierry Reding 
---
 drivers/irqchip/irq-imx-gpcv2.c | 29 +++--
 1 file changed, 11 insertions(+), 18 deletions(-)

diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c
index bdee15a327f3..8e606baf3a01 100644
--- a/drivers/irqchip/irq-imx-gpcv2.c
+++ b/drivers/irqchip/irq-imx-gpcv2.c
@@ -19,6 +19,7 @@
 
 
 struct gpcv2_irqchip_data {
+   struct syscore_ops  syscore;
struct raw_spinlock rlock;
void __iomem*gpc_base;
u32 wakeup_sources[IMR_NUM];
@@ -26,7 +27,11 @@ struct gpcv2_irqchip_data {
u32 cpu2wakeup;
 };
 
-static struct gpcv2_irqchip_data *imx_gpcv2_instance __ro_after_init;
+static inline struct gpcv2_irqchip_data *
+from_syscore(struct syscore_ops *ops)
+{
+   return container_of(ops, struct gpcv2_irqchip_data, syscore);
+}
 
 static void __iomem *gpcv2_idx_to_reg(struct gpcv2_irqchip_data *cd, int i)
 {
@@ -35,14 +40,10 @@ static void __iomem *gpcv2_idx_to_reg(struct 
gpcv2_irqchip_data *cd, int i)
 
 static int gpcv2_wakeup_source_save(struct syscore_ops *ops)
 {
-   struct gpcv2_irqchip_data *cd;
+   struct gpcv2_irqchip_data *cd = from_syscore(ops);
void __iomem *reg;
int i;
 
-   cd = imx_gpcv2_instance;
-   if (!cd)
-   return 0;
-
for (i = 0; i < IMR_NUM; i++) {
reg = gpcv2_idx_to_reg(cd, i);
cd->saved_irq_mask[i] = readl_relaxed(reg);
@@ -54,22 +55,13 @@ static int gpcv2_wakeup_source_save(struct syscore_ops *ops)
 
 static void gpcv2_wakeup_source_restore(struct syscore_ops *ops)
 {
-   struct gpcv2_irqchip_data *cd;
+   struct gpcv2_irqchip_data *cd = from_syscore(ops);
int i;
 
-   cd = imx_gpcv2_instance;
-   if (!cd)
-   return;
-
for (i = 0; i < IMR_NUM; i++)
writel_relaxed(cd->saved_irq_mask[i], gpcv2_idx_to_reg(cd, i));
 }
 
-static struct syscore_ops imx_gpcv2_syscore_ops = {
-   .suspend= gpcv2_wakeup_source_save,
-   .resume = gpcv2_wakeup_source_restore,
-};
-
 static int imx_gpcv2_irq_set_wake(struct irq_data *d, unsigned int on)
 {
struct gpcv2_irqchip_data *cd = d->chip_data;
@@ -275,8 +267,9 @@ static int __init imx_gpcv2_irqchip_init(struct device_node 
*node,
 */
writel_relaxed(~0x1, cd->gpc_base + cd->cpu2wakeup);
 
-   imx_gpcv2_instance = cd;
-   register_syscore_ops(&imx_gpcv2_syscore_ops);
+   cd->syscore.suspend = gpcv2_wakeup_source_save;
+   cd->syscore.resume = gpcv2_wakeup_source_restore;
+   register_syscore_ops(&cd->syscore);
 
/*
 * Clear the OF_POPULATED flag set in of_irq_init so that
-- 
2.50.0




[PATCH v2 7/7] soc/tegra: pmc: Derive PMC context from syscore ops

2025-07-17 Thread Thierry Reding
From: Thierry Reding 

Rather than relying on a global variable, make use of the fact that the
syscore ops are embedded in the PMC context and can be obtained via
container_of().

Signed-off-by: Thierry Reding 
---
 drivers/soc/tegra/pmc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 455e55cbd2cc..a5c179636a69 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -3143,6 +3143,7 @@ static void tegra186_pmc_process_wake_events(struct 
tegra_pmc *pmc, unsigned int
 
 static void tegra186_pmc_wake_syscore_resume(struct syscore_ops *ops)
 {
+   struct tegra_pmc *pmc = container_of(ops, struct tegra_pmc, syscore);
u32 status, mask;
unsigned int i;
 
@@ -3156,6 +3157,8 @@ static void tegra186_pmc_wake_syscore_resume(struct 
syscore_ops *ops)
 
 static int tegra186_pmc_wake_syscore_suspend(struct syscore_ops *ops)
 {
+   struct tegra_pmc *pmc = container_of(ops, struct tegra_pmc, syscore);
+
wke_read_sw_wake_status(pmc);
 
/* flip the wakeup trigger for dual-edge triggered pads
-- 
2.50.0




[PATCH bpf-next 1/1] powerpc64/bpf: Add jit support for load_acquire and store_release

2025-07-17 Thread Puranjay Mohan
Add JIT support for the load_acquire and store_release instructions. The
implementation is similar to the kernel where:

load_acquire  => plain load -> lwsync
store_release => lwsync -> plain store

To test the correctness of the implementation, following selftests were
run:

  [fedora@linux-kernel bpf]$ sudo ./test_progs -a \
  verifier_load_acquire,verifier_store_release,atomics
  #11/1atomics/add:OK
  #11/2atomics/sub:OK
  #11/3atomics/and:OK
  #11/4atomics/or:OK
  #11/5atomics/xor:OK
  #11/6atomics/cmpxchg:OK
  #11/7atomics/xchg:OK
  #11  atomics:OK
  #519/1   verifier_load_acquire/load-acquire, 8-bit:OK
  #519/2   verifier_load_acquire/load-acquire, 8-bit @unpriv:OK
  #519/3   verifier_load_acquire/load-acquire, 16-bit:OK
  #519/4   verifier_load_acquire/load-acquire, 16-bit @unpriv:OK
  #519/5   verifier_load_acquire/load-acquire, 32-bit:OK
  #519/6   verifier_load_acquire/load-acquire, 32-bit @unpriv:OK
  #519/7   verifier_load_acquire/load-acquire, 64-bit:OK
  #519/8   verifier_load_acquire/load-acquire, 64-bit @unpriv:OK
  #519/9   verifier_load_acquire/load-acquire with uninitialized
  src_reg:OK
  #519/10  verifier_load_acquire/load-acquire with uninitialized src_reg
  @unpriv:OK
  #519/11  verifier_load_acquire/load-acquire with non-pointer src_reg:OK
  #519/12  verifier_load_acquire/load-acquire with non-pointer src_reg
  @unpriv:OK
  #519/13  verifier_load_acquire/misaligned load-acquire:OK
  #519/14  verifier_load_acquire/misaligned load-acquire @unpriv:OK
  #519/15  verifier_load_acquire/load-acquire from ctx pointer:OK
  #519/16  verifier_load_acquire/load-acquire from ctx pointer @unpriv:OK
  #519/17  verifier_load_acquire/load-acquire with invalid register R15:OK
  #519/18  verifier_load_acquire/load-acquire with invalid register R15
  @unpriv:OK
  #519/19  verifier_load_acquire/load-acquire from pkt pointer:OK
  #519/20  verifier_load_acquire/load-acquire from flow_keys pointer:OK
  #519/21  verifier_load_acquire/load-acquire from sock pointer:OK
  #519 verifier_load_acquire:OK
  #556/1   verifier_store_release/store-release, 8-bit:OK
  #556/2   verifier_store_release/store-release, 8-bit @unpriv:OK
  #556/3   verifier_store_release/store-release, 16-bit:OK
  #556/4   verifier_store_release/store-release, 16-bit @unpriv:OK
  #556/5   verifier_store_release/store-release, 32-bit:OK
  #556/6   verifier_store_release/store-release, 32-bit @unpriv:OK
  #556/7   verifier_store_release/store-release, 64-bit:OK
  #556/8   verifier_store_release/store-release, 64-bit @unpriv:OK
  #556/9   verifier_store_release/store-release with uninitialized
  src_reg:OK
  #556/10  verifier_store_release/store-release with uninitialized src_reg
  @unpriv:OK
  #556/11  verifier_store_release/store-release with uninitialized
  dst_reg:OK
  #556/12  verifier_store_release/store-release with uninitialized dst_reg
  @unpriv:OK
  #556/13  verifier_store_release/store-release with non-pointer
  dst_reg:OK
  #556/14  verifier_store_release/store-release with non-pointer dst_reg
  @unpriv:OK
  #556/15  verifier_store_release/misaligned store-release:OK
  #556/16  verifier_store_release/misaligned store-release @unpriv:OK
  #556/17  verifier_store_release/store-release to ctx pointer:OK
  #556/18  verifier_store_release/store-release to ctx pointer @unpriv:OK
  #556/19  verifier_store_release/store-release, leak pointer to stack:OK
  #556/20  verifier_store_release/store-release, leak pointer to stack
  @unpriv:OK
  #556/21  verifier_store_release/store-release, leak pointer to map:OK
  #556/22  verifier_store_release/store-release, leak pointer to map
  @unpriv:OK
  #556/23  verifier_store_release/store-release with invalid register
  R15:OK
  #556/24  verifier_store_release/store-release with invalid register R15
  @unpriv:OK
  #556/25  verifier_store_release/store-release to pkt pointer:OK
  #556/26  verifier_store_release/store-release to flow_keys pointer:OK
  #556/27  verifier_store_release/store-release to sock pointer:OK
  #556 verifier_store_release:OK
  Summary: 3/55 PASSED, 0 SKIPPED, 0 FAILED

Signed-off-by: Puranjay Mohan 
---
 arch/powerpc/include/asm/ppc-opcode.h|  1 +
 arch/powerpc/net/bpf_jit_comp64.c| 82 
 tools/testing/selftests/bpf/progs/bpf_misc.h |  3 +-
 3 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/ppc-opcode.h 
b/arch/powerpc/include/asm/ppc-opcode.h
index 4312bcb913a42..8053b24afc395 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -425,6 +425,7 @@
 #define PPC_RAW_SC()   (0x4402)
 #define PPC_RAW_SYNC() (0x7c0004ac)
 #define PPC_RAW_ISYNC()(0x4c00012c)
+#define PPC_RAW_LWSYNC()   (0x7c2004ac)
 
 /*
  * Define what the VSX XX1 form instructions will look like, then add
diff --git a/arch/powerpc/net/bpf_jit_comp64.c 
b/arch/powerpc/net/bpf_

Re: [PATCH v6 0/4] PCI: Add support for resetting the Root Ports in a platform specific way

2025-07-17 Thread Krishna Chaitanya Chundru




On 7/15/2025 7:51 PM, Manivannan Sadhasivam via B4 Relay wrote:

Hi,

Currently, in the event of AER/DPC, PCI core will try to reset the slot (Root
Port) and its subordinate devices by invoking bridge control reset and FLR. But
in some cases like AER Fatal error, it might be necessary to reset the Root
Ports using the PCI host bridge drivers in a platform specific way (as indicated
by the TODO in the pcie_do_recovery() function in drivers/pci/pcie/err.c).
Otherwise, the PCI link won't be recovered successfully.

So this series adds a new callback 'pci_host_bridge::reset_root_port' for the
host bridge drivers to reset the Root Port when a fatal error happens.

Also, this series allows the host bridge drivers to handle PCI link down event
by resetting the Root Ports and recovering the bus. This is accomplished by the
help of the new 'pci_host_handle_link_down()' API. Host bridge drivers are
expected to call this API (preferrably from a threaded IRQ handler) with
relevant Root Port 'pci_dev' when a link down event is detected for the port.
The API will reuse the pcie_do_recovery() function to recover the link if AER
support is enabled, otherwise it will directly call the reset_root_port()
callback of the host bridge driver (if exists).

For reference, I've modified the pcie-qcom driver to call
pci_host_handle_link_down() API with Root Port 'pci_dev' after receiving the
LINK_DOWN global_irq event and populated 'pci_host_bridge::reset_root_port()'
callback to reset the Root Port. Since the Qcom PCIe controllers support only
a single Root Port (slot) per controller instance, the API is going to be
invoked only once. For multi Root Port controllers, the controller driver is
expected to detect the Root Port that received the link down event and call
the pci_host_handle_link_down() API with 'pci_dev' of that Root Port.

Testing
---

I've lost access to my test setup now. So Krishna (Cced) will help with testing
on the Qcom platform and Wilfred or Niklas should be able to test it on Rockchip
platform. For the moment, this series is compile tested only.

Tested on QCOM platform rb3gen2.


Changes in v6:
- Incorporated the patch: 
https://lore.kernel.org/all/20250524185304.26698-2-manivannan.sadhasi...@linaro.org/
- Link to v5: 
https://lore.kernel.org/r/20250715-pci-port-reset-v5-0-26a5d278d...@oss.qualcomm.com

Changes in v5:
* Reworked the pci_host_handle_link_down() to accept Root Port instead of
   resetting all Root Ports in the event of link down.
* Renamed 'reset_slot' to 'reset_root_port' to avoid confusion as both terms
   were used interchangibly and the series is intended to reset Root Port only.
* Added the Rockchip driver change to this series.
* Dropped the applied patches and review/tested tags due to rework.
* Rebased on top of v6.16-rc1.

Changes in v4:
- Handled link down first in the irq handler
- Updated ICC & OPP bandwidth after link up in reset_slot() callback
- Link to v3: 
https://lore.kernel.org/r/20250417-pcie-reset-slot-v3-0-59a10811c...@linaro.org

Changes in v3:
- Made the pci-host-common driver as a common library for host controller
   drivers
- Moved the reset slot code to pci-host-common library
- Link to v2: 
https://lore.kernel.org/r/20250416-pcie-reset-slot-v2-0-efe76b278...@linaro.org

Changes in v2:
- Moved calling reset_slot() callback from pcie_do_recovery() to 
pcibios_reset_secondary_bus()
- Link to v1: 
https://lore.kernel.org/r/20250404-pcie-reset-slot-v1-0-98952918b...@linaro.org

Signed-off-by: Manivannan Sadhasivam 

Tested-by: Krishna Chaitanya Chundru 

- Krishna Chaitanya.

---
Manivannan Sadhasivam (3):
   PCI/ERR: Add support for resetting the Root Ports in a platform specific 
way
   PCI: host-common: Add link down handling for Root Ports
   PCI: qcom: Add support for resetting the Root Port due to link down event

Wilfred Mallawa (1):
   PCI: dw-rockchip: Add support to reset Root Port upon link down event

  drivers/pci/controller/dwc/Kconfig|   2 +
  drivers/pci/controller/dwc/pcie-dw-rockchip.c |  91 ++-
  drivers/pci/controller/dwc/pcie-qcom.c| 120 --
  drivers/pci/controller/pci-host-common.c  |  33 +++
  drivers/pci/controller/pci-host-common.h  |   1 +
  drivers/pci/pci.c |  21 +
  drivers/pci/pcie/err.c|   6 +-
  include/linux/pci.h   |   1 +
  8 files changed, 260 insertions(+), 15 deletions(-)
---
base-commit: 19272b37aa4f83ca52bdf9c16d5d81bdd1354494
change-id: 20250715-pci-port-reset-4d9519570123

Best regards,




Re: [PATCH v6 2/4] PCI: host-common: Add link down handling for Root Portsy

2025-07-17 Thread Frank Li
On Tue, Jul 15, 2025 at 07:51:05PM +0530, Manivannan Sadhasivam via B4 Relay 
wrote:
> From: Manivannan Sadhasivam 
>
> The PCI link, when down, needs to be recovered to bring it back. But on
> some platforms, that cannot be done in a generic way as link recovery
> procedure is platform specific. So add a new API
> pci_host_handle_link_down() that could be called by the host bridge drivers
> for a specific Root Port when the link goes down.
>
> The API accepts the 'pci_dev' corresponding to the Root Port which observed
> the link down event. If CONFIG_PCIEAER is enabled, the API calls
> pcie_do_recovery() function with 'pci_channel_io_frozen' as the state. This
> will result in the execution of the AER Fatal error handling code. Since
> the link down recovery is pretty much the same as AER Fatal error handling,
> pcie_do_recovery() helper is reused here. First, the AER error_detected()
> callback will be triggered for the bridge and then for the downstream
> devices. Finally, pci_host_reset_root_port() will be called for the Root
> Port, which will reset the Root Port using 'reset_root_port' callback to
> recover the link. Once that's done, resume message will be broadcasted to
> the bridge and the downstream devices, indicating successful link recovery.
>
> But if CONFIG_PCIEAER is not enabled in the kernel, only
> pci_host_reset_root_port() API will be called, which will in turn call
> pci_bus_error_reset() to just reset the Root Port as there is no way we
> could inform the drivers about link recovery.
>
> Signed-off-by: Manivannan Sadhasivam 
> Signed-off-by: Manivannan Sadhasivam 

Reviewed-by: Frank Li 

> ---
>  drivers/pci/controller/pci-host-common.c | 33 
> 
>  drivers/pci/controller/pci-host-common.h |  1 +
>  drivers/pci/pci.c|  1 +
>  drivers/pci/pcie/err.c   |  1 +
>  4 files changed, 36 insertions(+)
>
> diff --git a/drivers/pci/controller/pci-host-common.c 
> b/drivers/pci/controller/pci-host-common.c
> index 
> b0992325dd65f0da8e216ec8a2153af365225d1d..51eacb6cb57443338e995f17afd3b2564bbd1f83
>  100644
> --- a/drivers/pci/controller/pci-host-common.c
> +++ b/drivers/pci/controller/pci-host-common.c
> @@ -12,9 +12,11 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>
> +#include "../pci.h"
>  #include "pci-host-common.h"
>
>  static void gen_pci_unmap_cfg(void *ptr)
> @@ -104,5 +106,36 @@ void pci_host_common_remove(struct platform_device *pdev)
>  }
>  EXPORT_SYMBOL_GPL(pci_host_common_remove);
>
> +static pci_ers_result_t pci_host_reset_root_port(struct pci_dev *dev)
> +{
> + int ret;
> +
> + ret = pci_bus_error_reset(dev);
> + if (ret) {
> + pci_err(dev, "Failed to reset Root Port: %d\n", ret);
> + return PCI_ERS_RESULT_DISCONNECT;
> + }
> +
> + pci_info(dev, "Root Port has been reset\n");
> +
> + return PCI_ERS_RESULT_RECOVERED;
> +}
> +
> +static void pci_host_recover_root_port(struct pci_dev *port)
> +{
> +#if IS_ENABLED(CONFIG_PCIEAER)
> + pcie_do_recovery(port, pci_channel_io_frozen, pci_host_reset_root_port);
> +#else
> + pci_host_reset_root_port(port);
> +#endif
> +}
> +
> +void pci_host_handle_link_down(struct pci_dev *port)
> +{
> + pci_info(port, "Recovering Root Port due to Link Down\n");
> + pci_host_recover_root_port(port);
> +}
> +EXPORT_SYMBOL_GPL(pci_host_handle_link_down);
> +
>  MODULE_DESCRIPTION("Common library for PCI host controller drivers");
>  MODULE_LICENSE("GPL v2");
> diff --git a/drivers/pci/controller/pci-host-common.h 
> b/drivers/pci/controller/pci-host-common.h
> index 
> 65bd9e032353827221a6af59858c46fdbe5916bf..cb0a07c8773ec87838164e994b34a62d2c8118be
>  100644
> --- a/drivers/pci/controller/pci-host-common.h
> +++ b/drivers/pci/controller/pci-host-common.h
> @@ -16,5 +16,6 @@ int pci_host_common_probe(struct platform_device *pdev);
>  int pci_host_common_init(struct platform_device *pdev,
>const struct pci_ecam_ops *ops);
>  void pci_host_common_remove(struct platform_device *pdev);
> +void pci_host_handle_link_down(struct pci_dev *port);
>
>  #endif
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 
> b29264aa2be33b18a58b3b3db1d1fb0f6483e5e8..39310422634a9551efc8aded565b7cc30f4989d0
>  100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -5768,6 +5768,7 @@ int pci_bus_error_reset(struct pci_dev *bridge)
>   mutex_unlock(&pci_slot_mutex);
>   return pci_bus_reset(bridge->subordinate, PCI_RESET_DO_RESET);
>  }
> +EXPORT_SYMBOL_GPL(pci_bus_error_reset);
>
>  /**
>   * pci_probe_reset_bus - probe whether a PCI bus can be reset
> diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
> index 
> b834fc0d705938540d3d7d3d8739770c09fe7cf1..3e3084bb7cb7fa06b526e6fab60e77927aba0ad0
>  100644
> --- a/drivers/pci/pcie/err.c
> +++ b/drivers/pci/pcie/err.c
> @@ -270,3 +270,4 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
>
>   

Re: [PATCH v3 5/6] PCI: pnv_php: Fix surprise plug detection and recovery

2025-07-17 Thread Timothy Pearson



- Original Message -
> From: "Bjorn Helgaas" 
> To: "Timothy Pearson" 
> Cc: "linuxppc-dev" , "linux-kernel" 
> , "linux-pci"
> , "Madhavan Srinivasan" , 
> "Michael Ellerman" ,
> "christophe leroy" , "Naveen N Rao" 
> , "Bjorn Helgaas"
> , "Shawn Anastasio" 
> Sent: Thursday, July 17, 2025 6:27:45 PM
> Subject: Re: [PATCH v3 5/6] PCI: pnv_php: Fix surprise plug detection and 
> recovery

> On Tue, Jul 15, 2025 at 04:39:06PM -0500, Timothy Pearson wrote:
>> The existing PowerNV hotplug code did not handle surprise plug events
>> correctly, leading to a complete failure of the hotplug system after
>> device removal and a required reboot to detect new devices.
> 
>> +++ b/drivers/pci/hotplug/pnv_php.c
>> @@ -4,12 +4,14 @@
>>   *
>>   * Copyright Gavin Shan, IBM Corporation 2016.
>>   * Copyright (C) 2025 Raptor Engineering, LLC
>> + * Copyright (C) 2025 Raptor Computing Systems, LLC
> 
> Just to double-check that you want both copyright lines here?

Yes, both entities ended up sponsoring this part of the work over time.  Thank 
you for double checking!



Re: [PATCH v6 1/4] PCI/ERR: Add support for resetting the Root Ports in a platform specific wayy

2025-07-17 Thread Frank Li
On Tue, Jul 15, 2025 at 07:51:04PM +0530, Manivannan Sadhasivam via B4 Relay 
wrote:
> From: Manivannan Sadhasivam 
>
> Some host bridge devices require resetting the Root Ports in a platform
> specific way to recover them from error conditions such as Fatal AER
> errors, Link Down etc... So introduce pci_host_bridge::reset_root_port()
> callback and call it from pcibios_reset_secondary_bus() if available. Also,
> save the Root Port config space before reset and restore it afterwards.
>
> The 'reset_root_port' callback is responsible for resetting the given Root
> Port referenced by the 'pci_dev' pointer in a platform specific way and
> bring it back to the working state if possible. If any error occurs during
> the reset operation, relevant errno should be returned.

Reviewed-by: Frank Li 

>
> Signed-off-by: Manivannan Sadhasivam 
> Signed-off-by: Manivannan Sadhasivam 
> ---
>  drivers/pci/pci.c  | 20 
>  drivers/pci/pcie/err.c |  5 -
>  include/linux/pci.h|  1 +
>  3 files changed, 21 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 
> e9448d55113bdfd2263d8e2f6b3ec802f56b712e..b29264aa2be33b18a58b3b3db1d1fb0f6483e5e8
>  100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -4964,6 +4964,26 @@ void pci_reset_secondary_bus(struct pci_dev *dev)
>
>  void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)
>  {
> + struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
> + int ret;
> +
> + if (pci_is_root_bus(dev->bus) && host->reset_root_port) {
> + /*
> +  * Save the config space of the Root Port before doing the
> +  * reset, since the state could be lost. The Endpoint state
> +  * should've been saved by the caller.
> +  */
> + pci_save_state(dev);
> + ret = host->reset_root_port(host, dev);
> + if (ret)
> + pci_err(dev, "Failed to reset Root Port: %d\n", ret);
> + else
> + /* Now restore it on success */
> + pci_restore_state(dev);
> +
> + return;
> + }
> +
>   pci_reset_secondary_bus(dev);
>  }
>
> diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
> index 
> de6381c690f5c21f00021cdc7bde8d93a5c7db52..b834fc0d705938540d3d7d3d8739770c09fe7cf1
>  100644
> --- a/drivers/pci/pcie/err.c
> +++ b/drivers/pci/pcie/err.c
> @@ -234,11 +234,6 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
>   }
>
>   if (status == PCI_ERS_RESULT_NEED_RESET) {
> - /*
> -  * TODO: Should call platform-specific
> -  * functions to reset slot before calling
> -  * drivers' slot_reset callbacks?
> -  */
>   status = PCI_ERS_RESULT_RECOVERED;
>   pci_dbg(bridge, "broadcast slot_reset message\n");
>   pci_walk_bridge(bridge, report_slot_reset, &status);
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 
> 05e68f35f39238f8b9ce08df97b384d1c1e89bbe..e7c118a961910a307ec365f17b8fe4f2585267e8
>  100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -599,6 +599,7 @@ struct pci_host_bridge {
>   void (*release_fn)(struct pci_host_bridge *);
>   int (*enable_device)(struct pci_host_bridge *bridge, struct pci_dev 
> *dev);
>   void (*disable_device)(struct pci_host_bridge *bridge, struct pci_dev 
> *dev);
> + int (*reset_root_port)(struct pci_host_bridge *bridge, struct pci_dev 
> *dev);
>   void*release_data;
>   unsigned intignore_reset_delay:1;   /* For entire hierarchy */
>   unsigned intno_ext_tags:1;  /* No Extended Tags */
>
> --
> 2.45.2
>
>



[PATCH RESEND bpf-next 1/1] powerpc64/bpf: Add jit support for load_acquire and store_release

2025-07-17 Thread Puranjay Mohan
Add JIT support for the load_acquire and store_release instructions. The
implementation is similar to the kernel where:

load_acquire  => plain load -> lwsync
store_release => lwsync -> plain store

To test the correctness of the implementation, following selftests were
run:

  [fedora@linux-kernel bpf]$ sudo ./test_progs -a \
  verifier_load_acquire,verifier_store_release,atomics
  #11/1atomics/add:OK
  #11/2atomics/sub:OK
  #11/3atomics/and:OK
  #11/4atomics/or:OK
  #11/5atomics/xor:OK
  #11/6atomics/cmpxchg:OK
  #11/7atomics/xchg:OK
  #11  atomics:OK
  #519/1   verifier_load_acquire/load-acquire, 8-bit:OK
  #519/2   verifier_load_acquire/load-acquire, 8-bit @unpriv:OK
  #519/3   verifier_load_acquire/load-acquire, 16-bit:OK
  #519/4   verifier_load_acquire/load-acquire, 16-bit @unpriv:OK
  #519/5   verifier_load_acquire/load-acquire, 32-bit:OK
  #519/6   verifier_load_acquire/load-acquire, 32-bit @unpriv:OK
  #519/7   verifier_load_acquire/load-acquire, 64-bit:OK
  #519/8   verifier_load_acquire/load-acquire, 64-bit @unpriv:OK
  #519/9   verifier_load_acquire/load-acquire with uninitialized
  src_reg:OK
  #519/10  verifier_load_acquire/load-acquire with uninitialized src_reg
  @unpriv:OK
  #519/11  verifier_load_acquire/load-acquire with non-pointer src_reg:OK
  #519/12  verifier_load_acquire/load-acquire with non-pointer src_reg
  @unpriv:OK
  #519/13  verifier_load_acquire/misaligned load-acquire:OK
  #519/14  verifier_load_acquire/misaligned load-acquire @unpriv:OK
  #519/15  verifier_load_acquire/load-acquire from ctx pointer:OK
  #519/16  verifier_load_acquire/load-acquire from ctx pointer @unpriv:OK
  #519/17  verifier_load_acquire/load-acquire with invalid register R15:OK
  #519/18  verifier_load_acquire/load-acquire with invalid register R15
  @unpriv:OK
  #519/19  verifier_load_acquire/load-acquire from pkt pointer:OK
  #519/20  verifier_load_acquire/load-acquire from flow_keys pointer:OK
  #519/21  verifier_load_acquire/load-acquire from sock pointer:OK
  #519 verifier_load_acquire:OK
  #556/1   verifier_store_release/store-release, 8-bit:OK
  #556/2   verifier_store_release/store-release, 8-bit @unpriv:OK
  #556/3   verifier_store_release/store-release, 16-bit:OK
  #556/4   verifier_store_release/store-release, 16-bit @unpriv:OK
  #556/5   verifier_store_release/store-release, 32-bit:OK
  #556/6   verifier_store_release/store-release, 32-bit @unpriv:OK
  #556/7   verifier_store_release/store-release, 64-bit:OK
  #556/8   verifier_store_release/store-release, 64-bit @unpriv:OK
  #556/9   verifier_store_release/store-release with uninitialized
  src_reg:OK
  #556/10  verifier_store_release/store-release with uninitialized src_reg
  @unpriv:OK
  #556/11  verifier_store_release/store-release with uninitialized
  dst_reg:OK
  #556/12  verifier_store_release/store-release with uninitialized dst_reg
  @unpriv:OK
  #556/13  verifier_store_release/store-release with non-pointer
  dst_reg:OK
  #556/14  verifier_store_release/store-release with non-pointer dst_reg
  @unpriv:OK
  #556/15  verifier_store_release/misaligned store-release:OK
  #556/16  verifier_store_release/misaligned store-release @unpriv:OK
  #556/17  verifier_store_release/store-release to ctx pointer:OK
  #556/18  verifier_store_release/store-release to ctx pointer @unpriv:OK
  #556/19  verifier_store_release/store-release, leak pointer to stack:OK
  #556/20  verifier_store_release/store-release, leak pointer to stack
  @unpriv:OK
  #556/21  verifier_store_release/store-release, leak pointer to map:OK
  #556/22  verifier_store_release/store-release, leak pointer to map
  @unpriv:OK
  #556/23  verifier_store_release/store-release with invalid register
  R15:OK
  #556/24  verifier_store_release/store-release with invalid register R15
  @unpriv:OK
  #556/25  verifier_store_release/store-release to pkt pointer:OK
  #556/26  verifier_store_release/store-release to flow_keys pointer:OK
  #556/27  verifier_store_release/store-release to sock pointer:OK
  #556 verifier_store_release:OK
  Summary: 3/55 PASSED, 0 SKIPPED, 0 FAILED

Signed-off-by: Puranjay Mohan 
---
 arch/powerpc/include/asm/ppc-opcode.h|  1 +
 arch/powerpc/net/bpf_jit_comp64.c| 82 
 tools/testing/selftests/bpf/progs/bpf_misc.h |  3 +-
 3 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/ppc-opcode.h 
b/arch/powerpc/include/asm/ppc-opcode.h
index 4312bcb913a42..8053b24afc395 100644
--- a/arch/powerpc/include/asm/ppc-opcode.h
+++ b/arch/powerpc/include/asm/ppc-opcode.h
@@ -425,6 +425,7 @@
 #define PPC_RAW_SC()   (0x4402)
 #define PPC_RAW_SYNC() (0x7c0004ac)
 #define PPC_RAW_ISYNC()(0x4c00012c)
+#define PPC_RAW_LWSYNC()   (0x7c2004ac)
 
 /*
  * Define what the VSX XX1 form instructions will look like, then add
diff --git a/arch/powerpc/net/bpf_jit_comp64.c 
b/arch/powerpc/net/bpf_

Re: [PATCH RESEND bpf-next 1/1] powerpc64/bpf: Add jit support for load_acquire and store_release

2025-07-17 Thread puranjay
Puranjay Mohan  writes:

Somehow the cover letter for this patch was missed, adding it here:

To test the functionality of these special instructions, a tool called
blitmus[0] was used to convert the following baseline litmus test[1] to bpf
programs:

 C MP+poonceonces

 (*
  * Result: Sometimes
  *
  * Can the counter-intuitive message-passing outcome be prevented with
  * no ordering at all?
  *)

 {}

 P0(int *buf, int *flag)
 {
 WRITE_ONCE(*buf, 1);
 WRITE_ONCE(*flag, 1);
 }

 P1(int *buf, int *flag)
 {
 int r0;
 int r1;

 r0 = READ_ONCE(*flag);
 r1 = READ_ONCE(*buf);
 }

 exists (1:r0=1 /\ 1:r1=0) (* Bad outcome. *)

Running the generated bpf program shows that the bad outcome is possible on
powerpc:

 [fedora@linux-kernel blitmus]$ sudo ./mp_poonceonces
 Starting litmus test with configuration:
   Test: MP+poonceonces
   Iterations: 4100

 Test MP+poonceonces Allowed
 Histogram (4 states)
 21548375 :>1:r0=0; 1:r1=0;
 301187   :>1:r0=0; 1:r1=1;
 337147   *>1:r0=1; 1:r1=0;
 18813291 :>1:r0=1; 1:r1=1;
 Ok

 Witnesses
 Positive: 337147, Negative: 40662853
 Condition exists (1:r0=1 /\ 1:r1=0) is validated
 Observation MP+poonceonces Sometimes 337147 40662853
 Time MP+poonceonces 13.48

 Thu Jul 17 18:12:51 UTC

Now the second write and the first read is converted to store_release and
load_acquire and it gives us the following litmus test[2]

 C MP+pooncerelease+poacquireonce

 (*
  * Result: Never
  *
  * This litmus test demonstrates that smp_store_release() and
  * smp_load_acquire() provide sufficient ordering for the message-passing
  * pattern.
  *)

 {}

 P0(int *buf, int *flag)
 {
 WRITE_ONCE(*buf, 1);
 smp_store_release(flag, 1);
 }

 P1(int *buf, int *flag)
 {
 int r0;
 int r1;

 r0 = smp_load_acquire(flag);
 r1 = READ_ONCE(*buf);
 }

 exists (1:r0=1 /\ 1:r1=0) (* Bad outcome. *)


Running the generated bpf program shows that the bad outcome is *not* possible
on powerpc with the implementation in this patch:

 [fedora@linux-kernel blitmus]$ sudo ./mp_pooncerelease_poacquireonce
 Starting litmus test with configuration:
   Test: MP+pooncerelease+poacquireonce
   Iterations: 4100

 Test MP+pooncerelease+poacquireonce Allowed
 Histogram (3 states)
 21036021 :>1:r0=0; 1:r1=0;
 14488694 :>1:r0=0; 1:r1=1;
 5475285  :>1:r0=1; 1:r1=1;
 No

 Witnesses
 Positive: 0, Negative: 4100
 Condition exists (1:r0=1 /\ 1:r1=0) is NOT validated
 Observation MP+pooncerelease+poacquireonce Never 0 4100
 Time MP+pooncerelease+poacquireonce 13.74

 Thu Jul 17 18:13:40 UTC

[0] https://github.com/puranjaymohan/blitmus
[1] 
https://github.com/puranjaymohan/blitmus/blob/main/litmus_tests/MP%2Bpoonceonces.litmus
[2] 
https://github.com/puranjaymohan/blitmus/blob/main/litmus_tests/MP%2Bpooncerelease%2Bpoacquireonce.litmus



Re: [PATCH v3 01/12] lib/kasan: introduce CONFIG_ARCH_DEFER_KASAN option

2025-07-17 Thread Andrew Morton
On Thu, 17 Jul 2025 19:27:21 +0500 Sabyrzhan Tasbolatov  
wrote:

> Introduce CONFIG_ARCH_DEFER_KASAN to identify architectures that need
> to defer KASAN initialization until shadow memory is properly set up.
> 
> Some architectures (like PowerPC with radix MMU) need to set up their
> shadow memory mappings before KASAN can be safely enabled, while others
> (like s390, x86, arm) can enable KASAN much earlier or even from the
> beginning.
> 
> This option allows us to:
> 1. Use static keys only where needed (avoiding overhead)
> 2. Use compile-time constants for arch that don't need runtime checks
> 3. Maintain optimal performance for both scenarios
> 
> Architectures that need deferred KASAN should select this option.
> Architectures that can enable KASAN early will get compile-time
> optimizations instead of runtime checks.

Looks nice and appears quite mature.  I'm reluctant to add it to mm.git
during -rc6, especially given the lack of formal review and ack tags.

But but but, that's what the mm-new branch is for.  I guess I'll add it
to get some additional exposure, but whether I'll advance it into
mm-unstable/linux-next for this cycle is unclear.

What do you (and others) think?



[PATCH net-next] ibmveth: Add multi buffers rx replenishment hcall support

2025-07-17 Thread Mingming Cao
This patch enables batched RX buffer replenishment in ibmveth by
using the new firmware-supported h_add_logical_lan_buffers() hcall
 to submit up to 8 RX buffers in a single call, instead of repeatedly
calling the single-buffer h_add_logical_lan_buffer() hcall.

During the probe, with the patch, the driver queries ILLAN attributes
to detect IBMVETH_ILLAN_RX_MULTI_BUFF_SUPPORT bit. If the attribute is
present, rx_buffers_per_hcall is set to 8, enabling batched replenishment.
Otherwise, it defaults to 1, preserving the original upstream behavior
 with no change in code flow for unsupported systems.

The core rx replenish logic remains the same. But when batching
is enabled, the driver aggregates up to 8 fully prepared descriptors
into a single h_add_logical_lan_buffers() hypercall. If any allocation
or DMA mapping fails while preparing a batch, only the successfully
prepared buffers are submitted, and the remaining are deferred for
the next replenish cycle.

If at runtime the firmware stops accepting the batched hcall—e,g,
after a Live Partition Migration (LPM) to a host that does not
support h_add_logical_lan_buffers(), the hypercall returns H_FUNCTION.
In that case, the driver transparently disables batching, resets
rx_buffers_per_hcall to 1, and falls back to the single-buffer hcall
in next future replenishments to take care of these and future buffers.

Test were done on systems with firmware that both supports and
does not support the new h_add_logical_lan_buffers hcall.

On supported firmware, this reduces hypercall overhead significantly
over multiple buffers. SAR measurements showed about a 15% improvement
in packet processing rate under moderate RX load, with heavier traffic
seeing gains more than 30%

Signed-off-by: Mingming Cao 
Reviewed-by: Brian King 
Reviewed-by: Haren Myneni 
Reviewed-by: Dave Marquardt 
---
 arch/powerpc/include/asm/hvcall.h  |   1 +
 drivers/net/ethernet/ibm/ibmveth.c | 203 +++--
 drivers/net/ethernet/ibm/ibmveth.h |  15 +++
 3 files changed, 151 insertions(+), 68 deletions(-)

diff --git a/arch/powerpc/include/asm/hvcall.h 
b/arch/powerpc/include/asm/hvcall.h
index 6df6dbbe1e7c..ea6c8dc400d2 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -270,6 +270,7 @@
 #define H_QUERY_INT_STATE   0x1E4
 #define H_POLL_PENDING 0x1D8
 #define H_ILLAN_ATTRIBUTES 0x244
+#define H_ADD_LOGICAL_LAN_BUFFERS 0x248
 #define H_MODIFY_HEA_QP0x250
 #define H_QUERY_HEA_QP 0x254
 #define H_QUERY_HEA0x258
diff --git a/drivers/net/ethernet/ibm/ibmveth.c 
b/drivers/net/ethernet/ibm/ibmveth.c
index 24046fe16634..8e885270d546 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -211,98 +211,153 @@ static inline void ibmveth_flush_buffer(void *addr, 
unsigned long length)
 static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter,
  struct ibmveth_buff_pool *pool)
 {
-   u32 i;
-   u32 count = pool->size - atomic_read(&pool->available);
-   u32 buffers_added = 0;
-   struct sk_buff *skb;
-   unsigned int free_index, index;
-   u64 correlator;
+   struct device *dev = &adapter->vdev->dev;
+   u32 remaining = pool->size - atomic_read(&pool->available);
+   union ibmveth_buf_desc descs[IBMVETH_MAX_RX_PER_HCALL] = {0};
+   u64 correlators[IBMVETH_MAX_RX_PER_HCALL] = {0};
+   u32 index;
+   u32 i, filled, batch;
unsigned long lpar_rc;
dma_addr_t dma_addr;
+   u32 buffers_added = 0;
 
mb();
 
-   for (i = 0; i < count; ++i) {
-   union ibmveth_buf_desc desc;
+   batch = adapter->rx_buffers_per_hcall;
 
-   free_index = pool->consumer_index;
-   index = pool->free_map[free_index];
-   skb = NULL;
+   while (remaining > 0) {
+   unsigned int free_index = pool->consumer_index;
 
-   if (WARN_ON(index == IBM_VETH_INVALID_MAP)) {
-   schedule_work(&adapter->work);
-   goto bad_index_failure;
-   }
+   /* Fill a batch of descriptors */
+   for (filled = 0; filled < min(remaining, batch); filled++) {
+   index = pool->free_map[free_index];
+   if (WARN_ON(index == IBM_VETH_INVALID_MAP)) {
+   adapter->replenish_add_buff_failure++;
+   netdev_info(adapter->netdev,
+   "Invalid map index %u, reset\n", 
index);
+   schedule_work(&adapter->work);
+   break;
+   }
 
-   /* are we allocating a new buffer or recycling an old one */
-   if (pool->skbuff[index])
-   goto reuse;
+   if (!pool->skbuff[index]) {
+   

Re: [PATCH v3 5/6] PCI: pnv_php: Fix surprise plug detection and recovery

2025-07-17 Thread Bjorn Helgaas
On Tue, Jul 15, 2025 at 04:39:06PM -0500, Timothy Pearson wrote:
> The existing PowerNV hotplug code did not handle surprise plug events
> correctly, leading to a complete failure of the hotplug system after
> device removal and a required reboot to detect new devices.

> +++ b/drivers/pci/hotplug/pnv_php.c
> @@ -4,12 +4,14 @@
>   *
>   * Copyright Gavin Shan, IBM Corporation 2016.
>   * Copyright (C) 2025 Raptor Engineering, LLC
> + * Copyright (C) 2025 Raptor Computing Systems, LLC

Just to double-check that you want both copyright lines here?



Re: [PATCH v3 0/6] PowerNV PCIe Hotplug Driver Fixes

2025-07-17 Thread Bjorn Helgaas
On Tue, Jul 15, 2025 at 04:31:49PM -0500, Timothy Pearson wrote:
> Hello all,
> 
> This series includes several fixes for bugs in the PowerNV PCIe hotplug
> driver that were discovered in testing with a Microsemi Switchtec PM8533
> PFX 48xG3 PCIe switch on a PowerNV system, as well as one workaround for
> PCIe switches that don't correctly implement slot presence detection
> such as the aforementioned one. Without the workaround, the switch works
> and downstream devices can be hot-unplugged, but the devices never come
> back online after being plugged in again until the system is rebooted.
> Other hotplug drivers (like pciehp_hpc) use a similar workaround.
> 
> Also included are fixes for the EEH driver to make it hotplug safe,
> and a small patch to enable all three attention indicator states per
> the PCIe specification.
> 
> Thanks,
> 
> Shawn Anastasio (2):
>   PCI: pnv_php: Properly clean up allocated IRQs on unplug
>   PCI: pnv_php: Work around switches with broken presence detection
> 
> Timothy Pearson (4):
>   powerpc/eeh: Export eeh_unfreeze_pe()
>   powerpc/eeh: Make EEH driver device hotplug safe
>   PCI: pnv_php: Fix surprise plug detection and recovery
>   PCI: pnv_php: Enable third attention indicator state
> 
>  arch/powerpc/kernel/eeh.c |   1 +
>  arch/powerpc/kernel/eeh_driver.c  |  48 --
>  arch/powerpc/kernel/eeh_pe.c  |  10 +-
>  arch/powerpc/kernel/pci-hotplug.c |   3 +
>  drivers/pci/hotplug/pnv_php.c | 244 +++---
>  5 files changed, 263 insertions(+), 43 deletions(-)

I'm OK with this from a PCI perspective, and I optimistically put it
on pci/hotplug.

I'm happy to merge via the PCI tree, but would need acks from the
powerpc folks for the arch/powerpc parts.

Alternatively it could be merged via powerpc with my ack on the
drivers/pci patches:

Acked-by: Bjorn Helgaas 

If you do merge via powerpc, I made some comment formatting and commit
log tweaks that I would like reflected in the drivers/pci part.  These
are on
https://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git/log/?h=hotplug

Bjorn