On Tue, Sep 08, 2026 at 11:59:14AM +0200, Christophe Leroy (CS GROUP) wrote: > > [...] > > --- a/arch/powerpc/include/asm/kasan.h > > +++ b/arch/powerpc/include/asm/kasan.h > > @@ -2,20 +2,17 @@ > > #ifndef __ASM_KASAN_H > > #define __ASM_KASAN_H > > -#if defined(CONFIG_KASAN) && > > !defined(CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX) > > -#define _GLOBAL_KASAN(fn) \ > > - _GLOBAL(fn); \ > > - _GLOBAL(__##fn) > > -#define _GLOBAL_TOC_KASAN(fn) \ > > - _GLOBAL_TOC(fn); \ > > - _GLOBAL_TOC(__##fn) > > -#define EXPORT_SYMBOL_KASAN(fn) \ > > - EXPORT_SYMBOL(__##fn) > > -#else /* CONFIG_KASAN && !CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX */ > > +/* > > + * powerpc requires CC_HAS_KASAN_MEMINTRINSIC_PREFIX whenever KASAN is > > + * enabled (see PPC_CC_HAS_KASAN_MEMINTRINSIC_PREFIX in > > arch/powerpc/Kconfig), > > + * so the compiler always emits __asan_mem*() at instrumented call sites > > and > > + * bare mem*() inside __no_sanitize_address / noinstr code. The old dual > > + * entry-point trick (_GLOBAL_KASAN emitting both memset and __memset) is > > + * therefore never needed. > > + */ > > This explanation belongs to the commit message not to the source code. > Hey Christophe,
Sure i'll move this and rest ahead. [...] > > diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c > > index 6f6801da9dc1..44115f904c2c 100644 > > --- a/arch/powerpc/kernel/cputable.c > > +++ b/arch/powerpc/kernel/cputable.c > > @@ -36,8 +36,8 @@ void __init set_cur_cpu_spec(struct cpu_spec *s) > > t = PTRRELOC(t); > > /* > > - * use memcpy() instead of *t = *s so that GCC replaces it > > - * by __memcpy() when KASAN is active > > + * use memcpy() instead of *t = *s so that the compiler replaces it > > + * by __asan_memcpy() when KASAN is active > > */ > > Does the initial problem still exist with the new __asan_memcpy() approach ? > If not the comment should be removed. > Hey Christophe, Thanks for pointing it out, i took a deeper look into this, here's my understanding on it. On PowerPC during very early boot the kernel is loaded by the bootloader/firmware at some physical address, but the kernel was linked expecting it to run at KERNELBASE(virtual address like 0xc000000000000000). The MMU mapping that makes that virtual address valid hasn't been set up yet. So far for a window of early boot, code is executing at the physical load address while all symbol addresses in the binary refer to the virtual linked address. reloc_offset() computes the gap between these two and PTRRELOC applies it to any pointer. So PTRRELOC(&the_cpu_spec) gives the physical address where the struct actually lives in memory right now, not where the linker thinks it lives. Why *t = *s would be wrong? In set_cur_cpu_spec: struct cpu_spec *t = &the_cpu_spec; // linked (virtual) address t = PTRRELOC(t); // physical address — where it actually is memcpy(t, s, sizeof(*t)); // copy into the right place If you wrote *t = *s instead, the compiler generates a struct assignment. For a large struct like cpu_spec, GCC is free to implement that however it likes — including emitting a call to memcpy(). But crucially, a compiler-generated memcpy call resolves through the GOT/PLT or direct symbol — which points to the linked virtual address of memcpy, not the physical address. At this point in boot, calling through the wrong address would jump to garbage or an unmapped page. memcpy(t, s, sizeof(*t)) written explicitly is different: t is already the corrected physical address, s points into the cpu_specs table which has also been PTRRELOC'd. The explicit call goes through the normal early-boot call mechanism which is safe. The original comment said: "use memcpy() instead of *t = *s so that GCC replaces it by __memcpy() when KASAN is active" This was added because under the old KASAN scheme (!CC_HAS_KASAN_MEMINTRINSIC_PREFIX), KASAN overrode the memset/memcpy linker symbols globally with C wrappers that called kasan_check_range(). If the compiler turned *t = *s into an implicit memcpy(), that would hit the KASAN wrapper — calling kasan_check_range() at a point in early boot where the KASAN shadow isn't mapped yet, causing a crash. Writing memcpy(t, s, sizeof(*t)) explicitly made GCC emit __memcpy() (the raw assembly alias exposed by _GLOBAL_KASAN) instead of the KASAN-wrapped memcpy(), bypassing the shadow check. That was the secondary reason. The primary reason that t is a PTRRELOC-adjusted physical pointer and the copy must go through it correctly was never stated. So the KASAN comment is not required but i think we still need to state why memcpy is required. For PTRRELOC adjustment, comment should reflect that. I'll update the comment and commit message and send out a new version. Regards, Mukesh

