From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
Make CONFIG_KASAN_SW_TAGS available for x86 machines if they have
ADDRESS_MASKING enabled (LAM) as that works similarly to Top-Byte Ignore
(TBI) that allows the software tag-based mode on arm64 platform.
The value for sw_tags KASAN_SHADOW_OFFSET was calculated by rearranging
the formulas for KASAN_SHADOW_START and KASAN_SHADOW_END from
arch/x86/include/asm/kasan.h - the only prerequisites being
KASAN_SHADOW_SCALE_SHIFT of 4, and KASAN_SHADOW_END equal to the
one from KASAN generic mode.
Set scale macro based on KASAN mode: in software tag-based mode 16 bytes
of memory map to one shadow byte and 8 in generic mode.
Disable CONFIG_KASAN_INLINE and CONFIG_KASAN_STACK when
CONFIG_KASAN_SW_TAGS is enabled on x86 until the appropriate compiler
support is available.
Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
---
Changelog v7:
- Add a paragraph to the patch message explaining how the various
addresses and the KASAN_SHADOW_OFFSET were calculated.
Changelog v6:
- Don't enable KASAN if LAM is not supported.
- Move kasan_init_tags() to kasan_init_64.c to not clutter the setup.c
file.
- Move the #ifdef for the KASAN scale shift here.
- Move the gdb code to patch "Use arithmetic shift for shadow
computation".
- Return "depends on KASAN" line to Kconfig.
- Add the defer kasan config option so KASAN can be disabled on hardware
that doesn't have LAM.
Changelog v4:
- Add x86 specific kasan_mem_to_shadow().
- Revert x86 to the older unsigned KASAN_SHADOW_OFFSET. Do the same to
KASAN_SHADOW_START/END.
- Modify scripts/gdb/linux/kasan.py to keep x86 using unsigned offset.
- Disable inline and stack support when software tags are enabled on
x86.
Changelog v3:
- Remove runtime_const from previous patch and merge the rest here.
- Move scale shift definition back to header file.
- Add new kasan offset for software tag based mode.
- Fix patch message typo 32 -> 16, and 16 -> 8.
- Update lib/Kconfig.kasan with x86 now having software tag-based
support.
Changelog v2:
- Remove KASAN dense code.
Documentation/arch/x86/x86_64/mm.rst | 6 ++++--
arch/x86/Kconfig | 4 ++++
arch/x86/boot/compressed/misc.h | 1 +
arch/x86/include/asm/kasan.h | 5 +++++
arch/x86/mm/kasan_init_64.c | 6 ++++++
lib/Kconfig.kasan | 3 ++-
6 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/Documentation/arch/x86/x86_64/mm.rst b/Documentation/arch/x86/x86_64/mm.rst
index a6cf05d51bd8..ccbdbb4cda36 100644
--- a/Documentation/arch/x86/x86_64/mm.rst
+++ b/Documentation/arch/x86/x86_64/mm.rst
@@ -60,7 +60,8 @@ Complete virtual memory map with 4-level page tables
ffffe90000000000 | -23 TB | ffffe9ffffffffff | 1 TB | ... unused hole
ffffea0000000000 | -22 TB | ffffeaffffffffff | 1 TB | virtual memory map (vmemmap_base)
ffffeb0000000000 | -21 TB | ffffebffffffffff | 1 TB | ... unused hole
- ffffec0000000000 | -20 TB | fffffbffffffffff | 16 TB | KASAN shadow memory
+ ffffec0000000000 | -20 TB | fffffbffffffffff | 16 TB | KASAN shadow memory (generic mode)
+ fffff40000000000 | -8 TB | fffffbffffffffff | 8 TB | KASAN shadow memory (software tag-based mode)
__________________|____________|__________________|_________|____________________________________________________________
|
| Identical layout to the 56-bit one from here on:
@@ -130,7 +131,8 @@ Complete virtual memory map with 5-level page tables
ffd2000000000000 | -11.5 PB | ffd3ffffffffffff | 0.5 PB | ... unused hole
ffd4000000000000 | -11 PB | ffd5ffffffffffff | 0.5 PB | virtual memory map (vmemmap_base)
ffd6000000000000 | -10.5 PB | ffdeffffffffffff | 2.25 PB | ... unused hole
- ffdf000000000000 | -8.25 PB | fffffbffffffffff | ~8 PB | KASAN shadow memory
+ ffdf000000000000 | -8.25 PB | fffffbffffffffff | ~8 PB | KASAN shadow memory (generic mode)
+ ffeffc0000000000 | -6 PB | fffffbffffffffff | 4 PB | KASAN shadow memory (software tag-based mode)
__________________|____________|__________________|_________|____________________________________________________________
|
| Identical layout to the 47-bit one from here on:
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 80527299f859..21c71d9e0698 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -67,6 +67,7 @@ config X86
select ARCH_CLOCKSOURCE_INIT
select ARCH_CONFIGURES_CPU_MITIGATIONS
select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
+ select ARCH_DISABLE_KASAN_INLINE if X86_64 && KASAN_SW_TAGS
select ARCH_ENABLE_HUGEPAGE_MIGRATION if X86_64 && HUGETLB_PAGE && MIGRATION
select ARCH_ENABLE_MEMORY_HOTPLUG if X86_64
select ARCH_ENABLE_MEMORY_HOTREMOVE if MEMORY_HOTPLUG
@@ -196,6 +197,8 @@ config X86
select HAVE_ARCH_JUMP_LABEL_RELATIVE
select HAVE_ARCH_KASAN if X86_64
select HAVE_ARCH_KASAN_VMALLOC if X86_64
+ select HAVE_ARCH_KASAN_SW_TAGS if ADDRESS_MASKING
+ select ARCH_NEEDS_DEFER_KASAN if ADDRESS_MASKING
select HAVE_ARCH_KFENCE
select HAVE_ARCH_KMSAN if X86_64
select HAVE_ARCH_KGDB
@@ -410,6 +413,7 @@ config AUDIT_ARCH
config KASAN_SHADOW_OFFSET
hex
depends on KASAN
+ default 0xeffffc0000000000 if KASAN_SW_TAGS
default 0xdffffc0000000000
config HAVE_INTEL_TXT
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index fd855e32c9b9..ba70036c2abd 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -13,6 +13,7 @@
#undef CONFIG_PARAVIRT_SPINLOCKS
#undef CONFIG_KASAN
#undef CONFIG_KASAN_GENERIC
+#undef CONFIG_KASAN_SW_TAGS
#define __NO_FORTIFY
diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h
index 9b7951a79753..b38a1a83af96 100644
--- a/arch/x86/include/asm/kasan.h
+++ b/arch/x86/include/asm/kasan.h
@@ -6,7 +6,12 @@
#include <linux/kasan-tags.h>
#include <linux/types.h>
#define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
+
+#ifdef CONFIG_KASAN_SW_TAGS
+#define KASAN_SHADOW_SCALE_SHIFT 4
+#else
#define KASAN_SHADOW_SCALE_SHIFT 3
+#endif
/*
* Compiler uses shadow offset assuming that addresses start
diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
index 7f5c11328ec1..3a5577341805 100644
--- a/arch/x86/mm/kasan_init_64.c
+++ b/arch/x86/mm/kasan_init_64.c
@@ -465,4 +465,10 @@ void __init kasan_init(void)
init_task.kasan_depth = 0;
kasan_init_generic();
+ pr_info("KernelAddressSanitizer initialized\n");
+
+ if (boot_cpu_has(X86_FEATURE_LAM))
+ kasan_init_sw_tags();
+ else
+ pr_info("KernelAddressSanitizer not initialized (sw-tags): hardware doesn't support LAM\n");
}
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index a4bb610a7a6f..d13ea8da7bfd 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -112,7 +112,8 @@ config KASAN_SW_TAGS
Requires GCC 11+ or Clang.
- Supported only on arm64 CPUs and relies on Top Byte Ignore.
+ Supported on arm64 CPUs that support Top Byte Ignore and on x86 CPUs
+ that support Linear Address Masking.
Consumes about 1/16th of available memory at kernel start and
add an overhead of ~20% for dynamic allocations.
--
2.52.0
For all your $Subjects: make sure they have a verb in the name.
For that consult:
https://kernel.org/doc/html/latest/process/maintainer-tip.html#patch-subject
and the following "Changelog" section.
On Mon, Jan 12, 2026 at 05:28:35PM +0000, Maciej Wieczor-Retman wrote:
> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
...
> Documentation/arch/x86/x86_64/mm.rst | 6 ++++--
> arch/x86/Kconfig | 4 ++++
> arch/x86/boot/compressed/misc.h | 1 +
> arch/x86/include/asm/kasan.h | 5 +++++
> arch/x86/mm/kasan_init_64.c | 6 ++++++
> lib/Kconfig.kasan | 3 ++-
> 6 files changed, 22 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/arch/x86/x86_64/mm.rst b/Documentation/arch/x86/x86_64/mm.rst
> index a6cf05d51bd8..ccbdbb4cda36 100644
> --- a/Documentation/arch/x86/x86_64/mm.rst
> +++ b/Documentation/arch/x86/x86_64/mm.rst
> @@ -60,7 +60,8 @@ Complete virtual memory map with 4-level page tables
> ffffe90000000000 | -23 TB | ffffe9ffffffffff | 1 TB | ... unused hole
> ffffea0000000000 | -22 TB | ffffeaffffffffff | 1 TB | virtual memory map (vmemmap_base)
> ffffeb0000000000 | -21 TB | ffffebffffffffff | 1 TB | ... unused hole
> - ffffec0000000000 | -20 TB | fffffbffffffffff | 16 TB | KASAN shadow memory
> + ffffec0000000000 | -20 TB | fffffbffffffffff | 16 TB | KASAN shadow memory (generic mode)
> + fffff40000000000 | -8 TB | fffffbffffffffff | 8 TB | KASAN shadow memory (software tag-based mode)
These here are non-overlapping ranges. Yours are overlapping. Why?
> __________________|____________|__________________|_________|____________________________________________________________
> |
> | Identical layout to the 56-bit one from here on:
> @@ -130,7 +131,8 @@ Complete virtual memory map with 5-level page tables
> ffd2000000000000 | -11.5 PB | ffd3ffffffffffff | 0.5 PB | ... unused hole
> ffd4000000000000 | -11 PB | ffd5ffffffffffff | 0.5 PB | virtual memory map (vmemmap_base)
> ffd6000000000000 | -10.5 PB | ffdeffffffffffff | 2.25 PB | ... unused hole
> - ffdf000000000000 | -8.25 PB | fffffbffffffffff | ~8 PB | KASAN shadow memory
> + ffdf000000000000 | -8.25 PB | fffffbffffffffff | ~8 PB | KASAN shadow memory (generic mode)
> + ffeffc0000000000 | -6 PB | fffffbffffffffff | 4 PB | KASAN shadow memory (software tag-based mode)
> __________________|____________|__________________|_________|____________________________________________________________
> |
...
> diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
> index 7f5c11328ec1..3a5577341805 100644
> --- a/arch/x86/mm/kasan_init_64.c
> +++ b/arch/x86/mm/kasan_init_64.c
> @@ -465,4 +465,10 @@ void __init kasan_init(void)
>
> init_task.kasan_depth = 0;
> kasan_init_generic();
> + pr_info("KernelAddressSanitizer initialized\n");
Why?
> +
> + if (boot_cpu_has(X86_FEATURE_LAM))
cpu_feature_enabled()
> + kasan_init_sw_tags();
> + else
> + pr_info("KernelAddressSanitizer not initialized (sw-tags): hardware doesn't support LAM\n");
You just said "initialized". Now it is not? How about we make up our minds
first and then issue one single true statement?
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
On 2026-01-13 at 12:45:39 +0100, Borislav Petkov wrote:
>For all your $Subjects: make sure they have a verb in the name.
>
>For that consult:
>
>https://kernel.org/doc/html/latest/process/maintainer-tip.html#patch-subject
>
>and the following "Changelog" section.
Sure, I'll revise these.
>
>On Mon, Jan 12, 2026 at 05:28:35PM +0000, Maciej Wieczor-Retman wrote:
>> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
>
>...
>
>> Documentation/arch/x86/x86_64/mm.rst | 6 ++++--
>> arch/x86/Kconfig | 4 ++++
>> arch/x86/boot/compressed/misc.h | 1 +
>> arch/x86/include/asm/kasan.h | 5 +++++
>> arch/x86/mm/kasan_init_64.c | 6 ++++++
>> lib/Kconfig.kasan | 3 ++-
>> 6 files changed, 22 insertions(+), 3 deletions(-)
>>
>> diff --git a/Documentation/arch/x86/x86_64/mm.rst b/Documentation/arch/x86/x86_64/mm.rst
>> index a6cf05d51bd8..ccbdbb4cda36 100644
>> --- a/Documentation/arch/x86/x86_64/mm.rst
>> +++ b/Documentation/arch/x86/x86_64/mm.rst
>> @@ -60,7 +60,8 @@ Complete virtual memory map with 4-level page tables
>> ffffe90000000000 | -23 TB | ffffe9ffffffffff | 1 TB | ... unused hole
>> ffffea0000000000 | -22 TB | ffffeaffffffffff | 1 TB | virtual memory map (vmemmap_base)
>> ffffeb0000000000 | -21 TB | ffffebffffffffff | 1 TB | ... unused hole
>> - ffffec0000000000 | -20 TB | fffffbffffffffff | 16 TB | KASAN shadow memory
>> + ffffec0000000000 | -20 TB | fffffbffffffffff | 16 TB | KASAN shadow memory (generic mode)
>> + fffff40000000000 | -8 TB | fffffbffffffffff | 8 TB | KASAN shadow memory (software tag-based mode)
>
>These here are non-overlapping ranges. Yours are overlapping. Why?
The two added lines are two alternative ranges based on which mode is chosen
during compile time. Is there some neater way to note this down here?
>> + ffffec0000000000 | -20 TB | fffffbffffffffff | 16 TB | KASAN shadow memory (generic mode)
>> + or
>> + fffff40000000000 | -8 TB | fffffbffffffffff | 8 TB | KASAN shadow memory (software tag-based mode)
Something like this maybe ^ ? Or is the first take okay?
>
>> __________________|____________|__________________|_________|____________________________________________________________
>> |
>> | Identical layout to the 56-bit one from here on:
>> @@ -130,7 +131,8 @@ Complete virtual memory map with 5-level page tables
>> ffd2000000000000 | -11.5 PB | ffd3ffffffffffff | 0.5 PB | ... unused hole
>> ffd4000000000000 | -11 PB | ffd5ffffffffffff | 0.5 PB | virtual memory map (vmemmap_base)
>> ffd6000000000000 | -10.5 PB | ffdeffffffffffff | 2.25 PB | ... unused hole
>> - ffdf000000000000 | -8.25 PB | fffffbffffffffff | ~8 PB | KASAN shadow memory
>> + ffdf000000000000 | -8.25 PB | fffffbffffffffff | ~8 PB | KASAN shadow memory (generic mode)
>> + ffeffc0000000000 | -6 PB | fffffbffffffffff | 4 PB | KASAN shadow memory (software tag-based mode)
>> __________________|____________|__________________|_________|____________________________________________________________
>> |
>
>...
>
>> diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
>> index 7f5c11328ec1..3a5577341805 100644
>> --- a/arch/x86/mm/kasan_init_64.c
>> +++ b/arch/x86/mm/kasan_init_64.c
>> @@ -465,4 +465,10 @@ void __init kasan_init(void)
>>
>> init_task.kasan_depth = 0;
>> kasan_init_generic();
>> + pr_info("KernelAddressSanitizer initialized\n");
>
>Why?
My mistake, that string is already printed by kasan_init_generic(), I'll remove
it.
>
>> +
>> + if (boot_cpu_has(X86_FEATURE_LAM))
>
>cpu_feature_enabled()
Sure, thanks!
>
>> + kasan_init_sw_tags();
>> + else
>> + pr_info("KernelAddressSanitizer not initialized (sw-tags): hardware doesn't support LAM\n");
>
>You just said "initialized". Now it is not? How about we make up our minds
>first and then issue one single true statement?
Yes, I'll keep this one since the "initialized" pr_info() are called from inside
kasan_init_generic() and kasan_init_sw_tags().
>
>--
>Regards/Gruss,
> Boris.
>
>https://people.kernel.org/tglx/notes-about-netiquette
--
Kind regards
Maciej Wieczór-Retman
On Tue, Jan 13, 2026 at 04:00:47PM +0000, Maciej Wieczor-Retman wrote:
> The two added lines are two alternative ranges based on which mode is chosen
> during compile time. Is there some neater way to note this down here?
Explain it with words. Perhaps put a footnote or so. Say that those are
alternative ranges so that it is perfectly clear to readers.
Thx.
--
Regards/Gruss,
Boris.
https://people.kernel.org/tglx/notes-about-netiquette
On Mon, Jan 12, 2026 at 6:28 PM Maciej Wieczor-Retman
<m.wieczorretman@pm.me> wrote:
>
> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
>
> Make CONFIG_KASAN_SW_TAGS available for x86 machines if they have
> ADDRESS_MASKING enabled (LAM) as that works similarly to Top-Byte Ignore
> (TBI) that allows the software tag-based mode on arm64 platform.
>
> The value for sw_tags KASAN_SHADOW_OFFSET was calculated by rearranging
> the formulas for KASAN_SHADOW_START and KASAN_SHADOW_END from
> arch/x86/include/asm/kasan.h - the only prerequisites being
> KASAN_SHADOW_SCALE_SHIFT of 4, and KASAN_SHADOW_END equal to the
> one from KASAN generic mode.
>
> Set scale macro based on KASAN mode: in software tag-based mode 16 bytes
> of memory map to one shadow byte and 8 in generic mode.
>
> Disable CONFIG_KASAN_INLINE and CONFIG_KASAN_STACK when
> CONFIG_KASAN_SW_TAGS is enabled on x86 until the appropriate compiler
> support is available.
>
> Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
> ---
> Changelog v7:
> - Add a paragraph to the patch message explaining how the various
> addresses and the KASAN_SHADOW_OFFSET were calculated.
>
> Changelog v6:
> - Don't enable KASAN if LAM is not supported.
> - Move kasan_init_tags() to kasan_init_64.c to not clutter the setup.c
> file.
> - Move the #ifdef for the KASAN scale shift here.
> - Move the gdb code to patch "Use arithmetic shift for shadow
> computation".
> - Return "depends on KASAN" line to Kconfig.
> - Add the defer kasan config option so KASAN can be disabled on hardware
> that doesn't have LAM.
>
> Changelog v4:
> - Add x86 specific kasan_mem_to_shadow().
> - Revert x86 to the older unsigned KASAN_SHADOW_OFFSET. Do the same to
> KASAN_SHADOW_START/END.
> - Modify scripts/gdb/linux/kasan.py to keep x86 using unsigned offset.
> - Disable inline and stack support when software tags are enabled on
> x86.
>
> Changelog v3:
> - Remove runtime_const from previous patch and merge the rest here.
> - Move scale shift definition back to header file.
> - Add new kasan offset for software tag based mode.
> - Fix patch message typo 32 -> 16, and 16 -> 8.
> - Update lib/Kconfig.kasan with x86 now having software tag-based
> support.
>
> Changelog v2:
> - Remove KASAN dense code.
>
> Documentation/arch/x86/x86_64/mm.rst | 6 ++++--
> arch/x86/Kconfig | 4 ++++
> arch/x86/boot/compressed/misc.h | 1 +
> arch/x86/include/asm/kasan.h | 5 +++++
> arch/x86/mm/kasan_init_64.c | 6 ++++++
> lib/Kconfig.kasan | 3 ++-
> 6 files changed, 22 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/arch/x86/x86_64/mm.rst b/Documentation/arch/x86/x86_64/mm.rst
> index a6cf05d51bd8..ccbdbb4cda36 100644
> --- a/Documentation/arch/x86/x86_64/mm.rst
> +++ b/Documentation/arch/x86/x86_64/mm.rst
> @@ -60,7 +60,8 @@ Complete virtual memory map with 4-level page tables
> ffffe90000000000 | -23 TB | ffffe9ffffffffff | 1 TB | ... unused hole
> ffffea0000000000 | -22 TB | ffffeaffffffffff | 1 TB | virtual memory map (vmemmap_base)
> ffffeb0000000000 | -21 TB | ffffebffffffffff | 1 TB | ... unused hole
> - ffffec0000000000 | -20 TB | fffffbffffffffff | 16 TB | KASAN shadow memory
> + ffffec0000000000 | -20 TB | fffffbffffffffff | 16 TB | KASAN shadow memory (generic mode)
> + fffff40000000000 | -8 TB | fffffbffffffffff | 8 TB | KASAN shadow memory (software tag-based mode)
> __________________|____________|__________________|_________|____________________________________________________________
> |
> | Identical layout to the 56-bit one from here on:
> @@ -130,7 +131,8 @@ Complete virtual memory map with 5-level page tables
> ffd2000000000000 | -11.5 PB | ffd3ffffffffffff | 0.5 PB | ... unused hole
> ffd4000000000000 | -11 PB | ffd5ffffffffffff | 0.5 PB | virtual memory map (vmemmap_base)
> ffd6000000000000 | -10.5 PB | ffdeffffffffffff | 2.25 PB | ... unused hole
> - ffdf000000000000 | -8.25 PB | fffffbffffffffff | ~8 PB | KASAN shadow memory
> + ffdf000000000000 | -8.25 PB | fffffbffffffffff | ~8 PB | KASAN shadow memory (generic mode)
> + ffeffc0000000000 | -6 PB | fffffbffffffffff | 4 PB | KASAN shadow memory (software tag-based mode)
> __________________|____________|__________________|_________|____________________________________________________________
> |
> | Identical layout to the 47-bit one from here on:
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 80527299f859..21c71d9e0698 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -67,6 +67,7 @@ config X86
> select ARCH_CLOCKSOURCE_INIT
> select ARCH_CONFIGURES_CPU_MITIGATIONS
> select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
> + select ARCH_DISABLE_KASAN_INLINE if X86_64 && KASAN_SW_TAGS
> select ARCH_ENABLE_HUGEPAGE_MIGRATION if X86_64 && HUGETLB_PAGE && MIGRATION
> select ARCH_ENABLE_MEMORY_HOTPLUG if X86_64
> select ARCH_ENABLE_MEMORY_HOTREMOVE if MEMORY_HOTPLUG
> @@ -196,6 +197,8 @@ config X86
> select HAVE_ARCH_JUMP_LABEL_RELATIVE
> select HAVE_ARCH_KASAN if X86_64
> select HAVE_ARCH_KASAN_VMALLOC if X86_64
> + select HAVE_ARCH_KASAN_SW_TAGS if ADDRESS_MASKING
> + select ARCH_NEEDS_DEFER_KASAN if ADDRESS_MASKING
Do we need this?
> select HAVE_ARCH_KFENCE
> select HAVE_ARCH_KMSAN if X86_64
> select HAVE_ARCH_KGDB
> @@ -410,6 +413,7 @@ config AUDIT_ARCH
> config KASAN_SHADOW_OFFSET
> hex
> depends on KASAN
> + default 0xeffffc0000000000 if KASAN_SW_TAGS
> default 0xdffffc0000000000
>
> config HAVE_INTEL_TXT
> diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
> index fd855e32c9b9..ba70036c2abd 100644
> --- a/arch/x86/boot/compressed/misc.h
> +++ b/arch/x86/boot/compressed/misc.h
> @@ -13,6 +13,7 @@
> #undef CONFIG_PARAVIRT_SPINLOCKS
> #undef CONFIG_KASAN
> #undef CONFIG_KASAN_GENERIC
> +#undef CONFIG_KASAN_SW_TAGS
>
> #define __NO_FORTIFY
>
> diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h
> index 9b7951a79753..b38a1a83af96 100644
> --- a/arch/x86/include/asm/kasan.h
> +++ b/arch/x86/include/asm/kasan.h
> @@ -6,7 +6,12 @@
> #include <linux/kasan-tags.h>
> #include <linux/types.h>
> #define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
> +
> +#ifdef CONFIG_KASAN_SW_TAGS
> +#define KASAN_SHADOW_SCALE_SHIFT 4
> +#else
> #define KASAN_SHADOW_SCALE_SHIFT 3
> +#endif
>
> /*
> * Compiler uses shadow offset assuming that addresses start
> diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
> index 7f5c11328ec1..3a5577341805 100644
> --- a/arch/x86/mm/kasan_init_64.c
> +++ b/arch/x86/mm/kasan_init_64.c
> @@ -465,4 +465,10 @@ void __init kasan_init(void)
>
> init_task.kasan_depth = 0;
> kasan_init_generic();
> + pr_info("KernelAddressSanitizer initialized\n");
This pr_info is not needed, kasan_init_generic already prints the message.
> +
> + if (boot_cpu_has(X86_FEATURE_LAM))
> + kasan_init_sw_tags();
> + else
> + pr_info("KernelAddressSanitizer not initialized (sw-tags): hardware doesn't support LAM\n");
> }
> diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
> index a4bb610a7a6f..d13ea8da7bfd 100644
> --- a/lib/Kconfig.kasan
> +++ b/lib/Kconfig.kasan
> @@ -112,7 +112,8 @@ config KASAN_SW_TAGS
>
> Requires GCC 11+ or Clang.
>
> - Supported only on arm64 CPUs and relies on Top Byte Ignore.
> + Supported on arm64 CPUs that support Top Byte Ignore and on x86 CPUs
> + that support Linear Address Masking.
>
> Consumes about 1/16th of available memory at kernel start and
> add an overhead of ~20% for dynamic allocations.
> --
> 2.52.0
>
>
On 2026-01-13 at 02:21:47 +0100, Andrey Konovalov wrote:
>On Mon, Jan 12, 2026 at 6:28 PM Maciej Wieczor-Retman
><m.wieczorretman@pm.me> wrote:
>>
>> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
...
>> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
>> index 80527299f859..21c71d9e0698 100644
>> --- a/arch/x86/Kconfig
>> +++ b/arch/x86/Kconfig
>> @@ -67,6 +67,7 @@ config X86
>> select ARCH_CLOCKSOURCE_INIT
>> select ARCH_CONFIGURES_CPU_MITIGATIONS
>> select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
>> + select ARCH_DISABLE_KASAN_INLINE if X86_64 && KASAN_SW_TAGS
>> select ARCH_ENABLE_HUGEPAGE_MIGRATION if X86_64 && HUGETLB_PAGE && MIGRATION
>> select ARCH_ENABLE_MEMORY_HOTPLUG if X86_64
>> select ARCH_ENABLE_MEMORY_HOTREMOVE if MEMORY_HOTPLUG
>> @@ -196,6 +197,8 @@ config X86
>> select HAVE_ARCH_JUMP_LABEL_RELATIVE
>> select HAVE_ARCH_KASAN if X86_64
>> select HAVE_ARCH_KASAN_VMALLOC if X86_64
>> + select HAVE_ARCH_KASAN_SW_TAGS if ADDRESS_MASKING
>> + select ARCH_NEEDS_DEFER_KASAN if ADDRESS_MASKING
>
>Do we need this?
I added this to solve the problem "what should happen when there is no hardware
support (discovered at runtime) but someone requested/compiled the kernel with
LAM and KASAN sw_tags?". I think Samuel suggested the static keys approach
during v6 to solve this issue.
As I recall without it the kernel would just freeze since it would try doing a
bunch of LAM+KASAN related things without LAM working. So that'd end with
various faults and violations.
Technically kasan_init_sw_tags() is locked behind:
if (boot_cpu_has(X86_FEATURE_LAM))
but not running kasan_init_sw_tags() normally doesn't actually disable software
KASAN if we don't have LAM available. Without ARCH_NEEDS_DEFER_KASAN it just
checks whether CONFIG_KASAN is enabled which it would in this scenario.
>
>> select HAVE_ARCH_KFENCE
>> select HAVE_ARCH_KMSAN if X86_64
>> select HAVE_ARCH_KGDB
>> @@ -410,6 +413,7 @@ config AUDIT_ARCH
>> config KASAN_SHADOW_OFFSET
>> hex
>> depends on KASAN
>> + default 0xeffffc0000000000 if KASAN_SW_TAGS
>> default 0xdffffc0000000000
>>
>> config HAVE_INTEL_TXT
>> diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
>> index fd855e32c9b9..ba70036c2abd 100644
>> --- a/arch/x86/boot/compressed/misc.h
>> +++ b/arch/x86/boot/compressed/misc.h
>> @@ -13,6 +13,7 @@
>> #undef CONFIG_PARAVIRT_SPINLOCKS
>> #undef CONFIG_KASAN
>> #undef CONFIG_KASAN_GENERIC
>> +#undef CONFIG_KASAN_SW_TAGS
>>
>> #define __NO_FORTIFY
>>
>> diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h
>> index 9b7951a79753..b38a1a83af96 100644
>> --- a/arch/x86/include/asm/kasan.h
>> +++ b/arch/x86/include/asm/kasan.h
>> @@ -6,7 +6,12 @@
>> #include <linux/kasan-tags.h>
>> #include <linux/types.h>
>> #define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
>> +
>> +#ifdef CONFIG_KASAN_SW_TAGS
>> +#define KASAN_SHADOW_SCALE_SHIFT 4
>> +#else
>> #define KASAN_SHADOW_SCALE_SHIFT 3
>> +#endif
>>
>> /*
>> * Compiler uses shadow offset assuming that addresses start
>> diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
>> index 7f5c11328ec1..3a5577341805 100644
>> --- a/arch/x86/mm/kasan_init_64.c
>> +++ b/arch/x86/mm/kasan_init_64.c
>> @@ -465,4 +465,10 @@ void __init kasan_init(void)
>>
>> init_task.kasan_depth = 0;
>> kasan_init_generic();
>> + pr_info("KernelAddressSanitizer initialized\n");
>
>This pr_info is not needed, kasan_init_generic already prints the message.
Thanks! I'll get rid of it.
>
>> +
>> + if (boot_cpu_has(X86_FEATURE_LAM))
>> + kasan_init_sw_tags();
>> + else
>> + pr_info("KernelAddressSanitizer not initialized (sw-tags): hardware doesn't support LAM\n");
>> }
>> diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
>> index a4bb610a7a6f..d13ea8da7bfd 100644
>> --- a/lib/Kconfig.kasan
>> +++ b/lib/Kconfig.kasan
>> @@ -112,7 +112,8 @@ config KASAN_SW_TAGS
>>
>> Requires GCC 11+ or Clang.
>>
>> - Supported only on arm64 CPUs and relies on Top Byte Ignore.
>> + Supported on arm64 CPUs that support Top Byte Ignore and on x86 CPUs
>> + that support Linear Address Masking.
>>
>> Consumes about 1/16th of available memory at kernel start and
>> add an overhead of ~20% for dynamic allocations.
>> --
>> 2.52.0
>>
>>
--
Kind regards
Maciej Wieczór-Retman
© 2016 - 2026 Red Hat, Inc.