On 2025-08-25 at 15:59:46 -0500, Samuel Holland wrote: >Hi Maciej, > >On 2025-08-25 3:24 PM, Maciej Wieczor-Retman wrote: >> For an address to be canonical it has to have its top bits equal to each >> other. The number of bits depends on the paging level and whether >> they're supposed to be ones or zeroes depends on whether the address >> points to kernel or user space. >> >> With Linear Address Masking (LAM) enabled, the definition of linear >> address canonicality is modified. Not all of the previously required >> bits need to be equal, only the first and last from the previously equal >> bitmask. So for example a 5-level paging kernel address needs to have >> bits [63] and [56] set. >> >> Add separate __canonical_address() implementation for >> CONFIG_KASAN_SW_TAGS since it's the only thing right now that enables >> LAM for kernel addresses (LAM_SUP bit in CR4). >> >> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@xxxxxxxxx> >> --- >> Changelog v4: >> - Add patch to the series. >> >> arch/x86/include/asm/page.h | 10 ++++++++++ >> 1 file changed, 10 insertions(+) >> >> diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h >> index bcf5cad3da36..a83f23a71f35 100644 >> --- a/arch/x86/include/asm/page.h >> +++ b/arch/x86/include/asm/page.h >> @@ -82,10 +82,20 @@ static __always_inline void *pfn_to_kaddr(unsigned long pfn) >> return __va(pfn << PAGE_SHIFT); >> } >> >> +/* >> + * CONFIG_KASAN_SW_TAGS requires LAM which changes the canonicality checks. >> + */ >> +#ifdef CONFIG_KASAN_SW_TAGS >> +static __always_inline u64 __canonical_address(u64 vaddr, u8 vaddr_bits) >> +{ >> + return (vaddr | BIT_ULL(63) | BIT_ULL(vaddr_bits - 1)); >> +} >> +#else >> static __always_inline u64 __canonical_address(u64 vaddr, u8 vaddr_bits) >> { >> return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits); >> } >> +#endif > >These two implementations have different semantics. The new function works only >on kernel addresses, whereas the existing one works on user addresses as well. >It looks like at least KVM's use of __is_canonical_address() expects the >function to work with user addresses. Thanks for noticing that, I'll think of a way to make it work for user addresses too :) > >Regards, >Samuel > >> >> static __always_inline u64 __is_canonical_address(u64 vaddr, u8 vaddr_bits) >> { > -- Kind regards Maciej Wieczór-Retman