riscv/mm: fix soft-dirty migration PMDs being treated as present
Subsystems (3)
PATCH 1/1 riscv/mm: fix soft-dirty migration PMDs being treated as present
RISC-V uses _PAGE_EXEC for swap soft-dirty tracking when CONFIG_MEM_SOFT_DIRTY is enabled and Svrsw60t59b is available. That's a problem for PMD migration entries, since pmd_present() also checks _PAGE_LEAF (R/W/X) to recognize THPs with _PAGE_PRESENT temporarily cleared during splitting.
When a soft-dirty THP is migrated, set_pmd_migration_entry() preserves soft-dirty with pmd_swp_mksoft_dirty(), setting the X bit in the migration PMD. Even with _PAGE_PRESENT clear, we end up treating a migration PMD as a present THP! The fault handler skips pmd_migration_entry_wait(), and a write fault can end up in do_huge_pmd_wp_page(), where pmd_page() decodes the migration entry as a mapped PFN.
Move the swap soft-dirty bit to bit 12 and start the swap offset at bit 13 when CONFIG_MEM_SOFT_DIRTY is enabled. This keeps R/W/X clear in migration PMDs and lets us keep the existing pmd_present() check for invalidated THPs. Leave the offset at bit 12 when soft-dirty tracking is disabled.
---
I found this while reviewing Usama's PMD-level swap entries series [1] and comparing the swap flag bits with the PMD presence checks across architectures.
[1] https://lore.kernel.org/all/[email protected]/
arch/riscv/include/asm/pgtable-bits.h | 6 +++--- arch/riscv/include/asm/pgtable.h | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-)
arch/riscv/include/asm/pgtable-bits.h +3 -3
@@ -27,12 +27,12 @@ ((riscv_has_extension_unlikely (RISCV_ISA_EXT_SVRSW60T59B )) ? \ (1UL <<59 ) :0 )/* -* Bit 3 is always zero for swap entry computation, so we -* can borrow it for swap page soft-dirty tracking. +* Bit 12 is reserved for swap soft-dirty tracking. The swap offset +* starts at bit 13 when CONFIG_MEM_SOFT_DIRTY is enabled. */#define _PAGE_SWP_SOFT_DIRTY \ ((riscv_has_extension_unlikely(RISCV_ISA_EXT_SVRSW60T59B)) ? \ - _PAGE_EXEC : 0) + (1UL << 12) : 0)#else #define _PAGE_SOFT_DIRTY 0#define _PAGE_SWP_SOFT_DIRTY 0
arch/riscv/include/asm/pgtable.h +6 -4
@@ -1178,18 +1178,20 @@ static inline pud_t pud_modify(pud_t pud, pgprot_t newprot)* * Format of swap PTE: * bit 0: _PAGE_PRESENT (zero) -* bit 1 to 2: (zero) -* bit 3: _PAGE_SWP_SOFT_DIRTY +* bit 1 to 3: _PAGE_LEAF (zero) * bit 4: _PAGE_SWP_UFFD * bit 5: _PAGE_PROT_NONE (zero) * bit 6: exclusive marker * bits 7 to 11: swap type -* bits 12 to XLEN-1: swap offset +* bit 12: _PAGE_SWP_SOFT_DIRTY (CONFIG_MEM_SOFT_DIRTY) +* bits 12/13 to XLEN-1: swap offset (without/with CONFIG_MEM_SOFT_DIRTY) */ #define __SWP_TYPE_SHIFT 7#define __SWP_TYPE_BITS 5#define __SWP_TYPE_MASK ((1UL << __SWP_TYPE_BITS) - 1) -#define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) +#define __SWP_OFFSET_SHIFT \ + (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT + \ + IS_ENABLED(CONFIG_MEM_SOFT_DIRTY))#define MAX_SWAPFILES_CHECK () \ BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS)
Signature · 1 line
2.49.0
Quoted 5 lines · Lance Yang
RISC-V uses
_PAGE_EXECfor swap soft-dirty tracking whenCONFIG_MEM_SOFT_DIRTYis enabled and Svrsw60t59b is available. That's a problem for PMD migration entries, sincepmd_present()also checks_PAGE_LEAF(R/W/X) to recognize THPs with_PAGE_PRESENTtemporarily cleared during splitting.
I'm curious: why do we have to set leaf indications for non-present things? The HW sure will ignore it, right?
Is this a sw problem? Who needs that?
Quoted 8 lines
When a soft-dirty THP is migrated,
set_pmd_migration_entry()preserves soft-dirty withpmd_swp_mksoft_dirty(), setting the X bit in the migration PMD. Even with_PAGE_PRESENTclear, we end up treating a migration PMD as a present THP! The fault handler skipspmd_migration_entry_wait(), and a write fault can end up indo_huge_pmd_wp_page(), wherepmd_page()decodes the migration entry as a mapped PFN.
That sounds bad.
Quoted 6 lines
Move the swap soft-dirty bit to bit 12 and start the swap offset at bit 13 when
CONFIG_MEM_SOFT_DIRTYis enabled. This keeps R/W/X clear in migration PMDs and lets us keep the existingpmd_present()check for invalidated THPs. Leave the offset at bit 12 when soft-dirty tracking is disabled.
That reduces the effective swap size (and PFN we can store). Could that be a problem?
Quoted 64 lines
Fixes 2a3ebad4db63 ("riscv: mm: add soft-dirty page tracking support")Signed-off-by Lance Yang <[email protected]>---
I found this while reviewing Usama's PMD-level swap entries series [1] and comparing the swap flag bits with the PMD presence checks across architectures.[1] https://lore.kernel.org/all/[email protected]/
arch/riscv/include/asm/pgtable-bits.h | 6 +++--- arch/riscv/include/asm/pgtable.h | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-)arch/riscv/include/asm/pgtable-bits.h +3
-3@@ -27,12 +27,12 @@ ((riscv_has_extension_unlikely (RISCV_ISA_EXT_SVRSW60T59B )) ? \ (1UL <<59 ) :0 )/* -* Bit 3 is always zero for swap entry computation, so we -* can borrow it for swap page soft-dirty tracking. +* Bit 12 is reserved for swap soft-dirty tracking. The swap offset +* starts at bit 13 when CONFIG_MEM_SOFT_DIRTY is enabled. */#define _PAGE_SWP_SOFT_DIRTY \ ((riscv_has_extension_unlikely(RISCV_ISA_EXT_SVRSW60T59B)) ? \ - _PAGE_EXEC : 0) + (1UL << 12) : 0)#else #define _PAGE_SOFT_DIRTY 0#define _PAGE_SWP_SOFT_DIRTY 0arch/riscv/include/asm/pgtable.h +6
-4@@ -1178,18 +1178,20 @@ static inline pud_t pud_modify(pud_t pud, pgprot_t newprot)* * Format of swap PTE: * bit 0: _PAGE_PRESENT (zero) -* bit 1 to 2: (zero) -* bit 3: _PAGE_SWP_SOFT_DIRTY +* bit 1 to 3: _PAGE_LEAF (zero) * bit 4: _PAGE_SWP_UFFD * bit 5: _PAGE_PROT_NONE (zero) * bit 6: exclusive marker * bits 7 to 11: swap type -* bits 12 to XLEN-1: swap offset +* bit 12: _PAGE_SWP_SOFT_DIRTY (CONFIG_MEM_SOFT_DIRTY) +* bits 12/13 to XLEN-1: swap offset (without/with CONFIG_MEM_SOFT_DIRTY) */ #define __SWP_TYPE_SHIFT 7#define __SWP_TYPE_BITS 5#define __SWP_TYPE_MASK ((1UL << __SWP_TYPE_BITS) - 1) -#define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) +#define __SWP_OFFSET_SHIFT \ + (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT + \ + IS_ENABLED(CONFIG_MEM_SOFT_DIRTY))#define MAX_SWAPFILES_CHECK () \ BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS)
Signature · 3 lines
Cheers, David
Quoted 9 lines · David Hildenbrand (Arm)
Quoted 5 lines · Lance Yang
RISC-V uses
_PAGE_EXECfor swap soft-dirty tracking whenCONFIG_MEM_SOFT_DIRTYis enabled and Svrsw60t59b is available. That's a problem for PMD migration entries, sincepmd_present()also checks_PAGE_LEAF(R/W/X) to recognize THPs with_PAGE_PRESENTtemporarily cleared during splitting.I'm curious: why do we have to set leaf indications for non-present things? The HW sure will ignore it, right?
Yeah, that surprised me too :) Still wrapping my head around the details
...
Quoted 1 line
Is this a sw problem? Who needs that?
IIUC, it's for software during a PMD split.
__split_huge_pmd_locked() invalidates the huge PMD and flushes the TLB before installing the PTE table. Software still needs pmd_present() and pmd_trans_huge() to recognize the THP in between.
RISC-V clears V but keeps the R/W/X bits for that, so the entry is invalid to hardware but still identifiable as a THP by software.
Hopefully I didn't miss something.
Quoted 10 lines
Quoted 8 lines
When a soft-dirty THP is migrated,
set_pmd_migration_entry()preserves soft-dirty withpmd_swp_mksoft_dirty(), setting the X bit in the migration PMD. Even with_PAGE_PRESENTclear, we end up treating a migration PMD as a present THP! The fault handler skipspmd_migration_entry_wait(), and a write fault can end up indo_huge_pmd_wp_page(), wherepmd_page()decodes the migration entry as a mapped PFN.That sounds bad.
YES, looks a bit off ...
Quoted 9 lines
Quoted 6 lines
Move the swap soft-dirty bit to bit 12 and start the swap offset at bit 13 when
CONFIG_MEM_SOFT_DIRTYis enabled. This keeps R/W/X clear in migration PMDs and lets us keep the existingpmd_present()check for invalidated THPs. Leave the offset at bit 12 when soft-dirty tracking is disabled.That reduces the effective swap size (and PFN we can store). Could that be a problem?
We don't need all 52 bits of the swap offset.
RV64 PFNs only need 44 bits for migration entries, and actual swap is already limited to about 16 TiB per area with 4 KiB pages by last_page (__u32) and swap_info_struct.max (unsigned int).
So there's room to reserve a bit without reducing the supported swap size or PFN range.
CONFIG_MEM_SOFT_DIRTY is only available on RV64, so RV32 keeps its 20-bit offset.
[...]
Cheers, Lance
Quoted 15 lines · Lance Yang
Quoted 9 lines · David Hildenbrand (Arm)
Quoted 5 lines · Lance Yang
RISC-V uses
_PAGE_EXECfor swap soft-dirty tracking whenCONFIG_MEM_SOFT_DIRTYis enabled and Svrsw60t59b is available. That's a problem for PMD migration entries, sincepmd_present()also checks_PAGE_LEAF(R/W/X) to recognize THPs with_PAGE_PRESENTtemporarily cleared during splitting.I'm curious: why do we have to set leaf indications for non-present things? The HW sure will ignore it, right?
Yeah, that surprised me too :) Still wrapping my head around the details
...
Quoted 7 lines
Quoted 1 line
Is this a sw problem? Who needs that?
IIUC, it's for software during a PMD split.
__split_huge_pmd_locked()invalidates the huge PMD and flushes the TLB before installing the PTE table. Software still needspmd_present()andpmd_trans_huge()to recognize the THP in between.
Also, x86 keeps _PAGE_PSE to identify the huge PMD. RISC-V doesn't have a separate leaf bit, so it keeps the R/W/X bits to identify the PMD as a leaf entry :)
Quoted 44 lines
RISC-V clears V but keeps the R/W/X bits for that, so the entry is invalid to hardware but still identifiable as a THP by software.
Hopefully I didn't miss something.
Quoted 10 lines
Quoted 8 lines
When a soft-dirty THP is migrated,
set_pmd_migration_entry()preserves soft-dirty withpmd_swp_mksoft_dirty(), setting the X bit in the migration PMD. Even with_PAGE_PRESENTclear, we end up treating a migration PMD as a present THP! The fault handler skipspmd_migration_entry_wait(), and a write fault can end up indo_huge_pmd_wp_page(), wherepmd_page()decodes the migration entry as a mapped PFN.That sounds bad.
YES, looks a bit off ...
Quoted 9 lines
Quoted 6 lines
Move the swap soft-dirty bit to bit 12 and start the swap offset at bit 13 when
CONFIG_MEM_SOFT_DIRTYis enabled. This keeps R/W/X clear in migration PMDs and lets us keep the existingpmd_present()check for invalidated THPs. Leave the offset at bit 12 when soft-dirty tracking is disabled.That reduces the effective swap size (and PFN we can store). Could that be a problem?
We don't need all 52 bits of the swap offset.
RV64 PFNs only need 44 bits for migration entries, and actual swap is already limited to about 16 TiB per area with 4 KiB pages by
last_page(__u32) and swap_info_struct.max (unsigned int).So there's room to reserve a bit without reducing the supported swap size or PFN range.
CONFIG_MEM_SOFT_DIRTYis only available on RV64, so RV32 keeps its 20-bit offset.[...]
Cheers, Lance
Quoted 19 lines · Lance Yang
Quoted 9 lines · David Hildenbrand (Arm)
Quoted 5 lines · Lance Yang
RISC-V uses
_PAGE_EXECfor swap soft-dirty tracking whenCONFIG_MEM_SOFT_DIRTYis enabled and Svrsw60t59b is available. That's a problem for PMD migration entries, sincepmd_present()also checks_PAGE_LEAF(R/W/X) to recognize THPs with_PAGE_PRESENTtemporarily cleared during splitting.I'm curious: why do we have to set leaf indications for non-present things? The HW sure will ignore it, right?
Yeah, that surprised me too :) Still wrapping my head around the details
...Quoted 1 line
Is this a sw problem? Who needs that?
IIUC, it's for software during a PMD split.
Quoted 8 lines
__split_huge_pmd_locked()invalidates the huge PMD and flushes the TLB before installing the PTE table. Software still needspmd_present()andpmd_trans_huge()to recognize the THP in between.RISC-V clears V but keeps the R/W/X bits for that, so the entry is invalid to hardware but still identifiable as a THP by software.
Hopefully I didn't miss something.
I thought some change we performed to GUP-fast wouldn't require that anymore. But my memory is a bit vague ... :)
Quoted 12 lines
Quoted 11 lines
Quoted 9 lines
When a soft-dirty THP is migrated,
set_pmd_migration_entry()preserves soft-dirty withpmd_swp_mksoft_dirty(), setting the X bit in the migration PMD. Even with_PAGE_PRESENTclear, we end up treating a migration PMD as a present THP! The fault handler skipspmd_migration_entry_wait(), and a write fault can end up indo_huge_pmd_wp_page(), wherepmd_page()decodes the migration entry as a mapped PFN.That sounds bad.
[...]
Quoted 10 lines
YES, looks a bit off ...
Quoted 2 lines
That reduces the effective swap size (and PFN we can store). Could that be a problem?
We don't need all 52 bits of the swap offset.
RV64 PFNs only need 44 bits for migration entries, and actual swap is already limited to about 16 TiB per area with 4 KiB pages by
last_page(__u32) and swap_info_struct.max (unsigned int).
Quoted 5 lines
So there's room to reserve a bit without reducing the supported swap size or PFN range.
CONFIG_MEM_SOFT_DIRTYis only available on RV64, so RV32 keeps its 20-bit offset.
Good, can you spell that out in the patch description?
Signature · 3 lines
Cheers, David
Quoted 24 lines · David Hildenbrand (Arm)
Quoted 23 lines · Lance Yang
Quoted 9 lines · David Hildenbrand (Arm)
Quoted 5 lines · Lance Yang
RISC-V uses
_PAGE_EXECfor swap soft-dirty tracking whenCONFIG_MEM_SOFT_DIRTYis enabled and Svrsw60t59b is available. That's a problem for PMD migration entries, sincepmd_present()also checks_PAGE_LEAF(R/W/X) to recognize THPs with_PAGE_PRESENTtemporarily cleared during splitting.I'm curious: why do we have to set leaf indications for non-present things? The HW sure will ignore it, right?
Yeah, that surprised me too :) Still wrapping my head around the details
...Quoted 1 line
Is this a sw problem? Who needs that?
IIUC, it's for software during a PMD split.
__split_huge_pmd_locked()invalidates the huge PMD and flushes the TLB before installing the PTE table. Software still needspmd_present()andpmd_trans_huge()to recognize the THP in between.
Quoted 7 lines
Quoted 4 lines
RISC-V clears V but keeps the R/W/X bits for that, so the entry is invalid to hardware but still identifiable as a THP by software.
Hopefully I didn't miss something.
I thought some change we performed to GUP-fast wouldn't require that anymore. But my memory is a bit vague ... :)
Yeah, I'll have another look at that :)
Quoted 25 lines
Quoted 12 lines
Quoted 11 lines
Quoted 9 lines
When a soft-dirty THP is migrated,
set_pmd_migration_entry()preserves soft-dirty withpmd_swp_mksoft_dirty(), setting the X bit in the migration PMD. Even with_PAGE_PRESENTclear, we end up treating a migration PMD as a present THP! The fault handler skipspmd_migration_entry_wait(), and a write fault can end up indo_huge_pmd_wp_page(), wherepmd_page()decodes the migration entry as a mapped PFN.That sounds bad.
[...]
Quoted 10 lines
YES, looks a bit off ...
Quoted 2 lines
That reduces the effective swap size (and PFN we can store). Could that be a problem?
We don't need all 52 bits of the swap offset.
RV64 PFNs only need 44 bits for migration entries, and actual swap is already limited to about 16 TiB per area with 4 KiB pages by
last_page(__u32) and swap_info_struct.max (unsigned int).
Quoted 7 lines
Quoted 5 lines
So there's room to reserve a bit without reducing the supported swap size or PFN range.
CONFIG_MEM_SOFT_DIRTYis only available on RV64, so RV32 keeps its 20-bit offset.Good, can you spell that out in the patch description?
Sure, will add that to the commit message in v2 once I've heard back from maintainers :)
Cheers, Lance
Quoted 29 lines · Lance Yang
Quoted 27 lines · David Hildenbrand (Arm)
Quoted 26 lines · Lance Yang
Quoted 9 lines · David Hildenbrand (Arm)
Quoted 5 lines · Lance Yang
RISC-V uses
_PAGE_EXECfor swap soft-dirty tracking whenCONFIG_MEM_SOFT_DIRTYis enabled and Svrsw60t59b is available. That's a problem for PMD migration entries, sincepmd_present()also checks_PAGE_LEAF(R/W/X) to recognize THPs with_PAGE_PRESENTtemporarily cleared during splitting.I'm curious: why do we have to set leaf indications for non-present things? The HW sure will ignore it, right?
Yeah, that surprised me too :) Still wrapping my head around the details
...Quoted 1 line
Is this a sw problem? Who needs that?
IIUC, it's for software during a PMD split.
__split_huge_pmd_locked()invalidates the huge PMD and flushes the TLB before installing the PTE table. Software still needspmd_present()andpmd_trans_huge()to recognize the THP in between.RISC-V clears V but keeps the R/W/X bits for that, so the entry is invalid to hardware but still identifiable as a THP by software.
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
Hopefully I didn't miss something.
I thought some change we performed to GUP-fast wouldn't require that anymore. But my memory is a bit vague ... :)
Yeah, I'll have another look at that :)
Emm ... I'm back. Do you mean 4b471e8898c3, which removed the GUP-fast pmd_trans_splitting() check after the THP refcounting rework? That check made GUP-fast bail out during the old THP split. The refcounting rework made extra GUP references prevent the physical split :)
RISC-V gained THP support in 2021 (e88b333142e4), after pmd_trans_splitting() had been removed. It never implemented that helper.
Keeping R/W/X in an invalidated RISC-V PMD preserves its leaf identity for software page-table walks. That requirement is separate from the old GUP-fast splitting check.
For RISC-V, pmd_mkinvalid() clears V and PROT_NONE but keeps R/W/X, so pmd_present() and pmd_trans_huge() still return true:
#define _PAGE_LEAF (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC)
static inline pmd_t pmd_mkinvalid(pmd_t pmd)
{
return __pmd(pmd_val(pmd) & ~(_PAGE_PRESENT|_PAGE_PROT_NONE));
}static inline int pmd_present(pmd_t pmd)
{
/*
* Checking for _PAGE_LEAF is needed too because:
* When splitting a THP, split_huge_page() will temporarily clear
* the present bit, in this situation, pmd_present() and
* pmd_trans_huge() still needs to return true.
*/
return (pmd_val(pmd) & (_PAGE_PRESENT | _PAGE_PROT_NONE | _PAGE_LEAF));
}
static inline bool pmd_leaf(pmd_t pmd)
{
return pmd_present(pmd) && (pmd_val(pmd) & _PAGE_LEAF);
}static inline int pmd_trans_huge(pmd_t pmd)
{
return pmd_leaf(pmd);
}And the rmap walk also needs that leaf indication. page_vma_mapped_walk() checks pmd_trans_huge() before taking the PMD lock, then rereads the entry under the lock. Keeping R/W/X lets it recognize the invalidated THP and wait for the split to finish :)
Anyway, R/W/X still have a job there (RISC-V doesn't have a separate leaf bit), and I don't think we can just drop them yet :D
Cheers, Lance
[...]
Gently ping ... Hi RISC-V folks, any thoughts on the proposed fix?
Quoted 87 lines · Lance Yang
RISC-V uses
_PAGE_EXECfor swap soft-dirty tracking whenCONFIG_MEM_SOFT_DIRTYis enabled and Svrsw60t59b is available. That's a problem for PMD migration entries, sincepmd_present()also checks_PAGE_LEAF(R/W/X) to recognize THPs with_PAGE_PRESENTtemporarily cleared during splitting.When a soft-dirty THP is migrated,
set_pmd_migration_entry()preserves soft-dirty withpmd_swp_mksoft_dirty(), setting the X bit in the migration PMD. Even with_PAGE_PRESENTclear, we end up treating a migration PMD as a present THP! The fault handler skipspmd_migration_entry_wait(), and a write fault can end up indo_huge_pmd_wp_page(), wherepmd_page()decodes the migration entry as a mapped PFN.Move the swap soft-dirty bit to bit 12 and start the swap offset at bit 13 when
CONFIG_MEM_SOFT_DIRTYis enabled. This keeps R/W/X clear in migration PMDs and lets us keep the existingpmd_present()check for invalidated THPs. Leave the offset at bit 12 when soft-dirty tracking is disabled.Fixes 2a3ebad4db63 ("riscv: mm: add soft-dirty page tracking support")Signed-off-by Lance Yang <[email protected]>---
I found this while reviewing Usama's PMD-level swap entries series [1] and comparing the swap flag bits with the PMD presence checks across architectures.[1] https://lore.kernel.org/all/[email protected]/
arch/riscv/include/asm/pgtable-bits.h| 6 +++---arch/riscv/include/asm/pgtable.h| 10 ++++++----2 files changed, 9 insertions(+), 7 deletions(-)arch/riscv/include/asm/pgtable-bits.h +3
-3@@ -27,12 +27,12 @@ ((riscv_has_extension_unlikely (RISCV_ISA_EXT_SVRSW60T59B )) ? \ (1UL <<59 ) :0 )/* -* Bit 3 is always zero for swap entry computation, so we -* can borrow it for swap page soft-dirty tracking. +* Bit 12 is reserved for swap soft-dirty tracking. The swap offset +* starts at bit 13 when CONFIG_MEM_SOFT_DIRTY is enabled. */#define _PAGE_SWP_SOFT_DIRTY \ ((riscv_has_extension_unlikely(RISCV_ISA_EXT_SVRSW60T59B)) ? \ - _PAGE_EXEC : 0) + (1UL << 12) : 0)#else #define _PAGE_SOFT_DIRTY 0#define _PAGE_SWP_SOFT_DIRTY 0arch/riscv/include/asm/pgtable.h +6
-4@@ -1178,18 +1178,20 @@ static inline pud_t pud_modify(pud_t pud, pgprot_t newprot)* * Format of swap PTE: * bit 0: _PAGE_PRESENT (zero) -* bit 1 to 2: (zero) -* bit 3: _PAGE_SWP_SOFT_DIRTY +* bit 1 to 3: _PAGE_LEAF (zero) * bit 4: _PAGE_SWP_UFFD * bit 5: _PAGE_PROT_NONE (zero) * bit 6: exclusive marker * bits 7 to 11: swap type -* bits 12 to XLEN-1: swap offset +* bit 12: _PAGE_SWP_SOFT_DIRTY (CONFIG_MEM_SOFT_DIRTY) +* bits 12/13 to XLEN-1: swap offset (without/with CONFIG_MEM_SOFT_DIRTY) */ #define __SWP_TYPE_SHIFT 7#define __SWP_TYPE_BITS 5#define __SWP_TYPE_MASK ((1UL << __SWP_TYPE_BITS) - 1) -#define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) +#define __SWP_OFFSET_SHIFT \ + (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT + \ + IS_ENABLED(CONFIG_MEM_SOFT_DIRTY))#define MAX_SWAPFILES_CHECK () \ BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > __SWP_TYPE_BITS)Signature · 1 line
2.49.0