Message ID | 20240429140208.238056-3-ryan.roberts@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | arm64/mm: Enable userfaultfd write-protect | expand |
On Mon, Apr 29, 2024 at 03:02:06PM +0100, Ryan Roberts wrote: > PTE_INVALID was previously occupying bit 59, which when a PTE is valid > can either be IGNORED, PBHA[0] or AttrIndex[3], depending on the HW > configuration. In practice this is currently not a problem because > PTE_INVALID can only be 1 when PTE_VALID=0 and upstream Linux always > requires the bit set to 0 for a valid pte. > > However, if in future Linux wants to use the field (e.g. AttrIndex[3]) > then we could end up with confusion when PTE_INVALID comes along and > corrupts the field - we would ideally want to preserve it even for an > invalid (but present) pte. > > The other problem with bit 59 is that it prevents the offset field of a > swap entry within a swap pte from growing beyond 51 bits. By moving > PTE_INVALID to a low bit we can lay the swap pte out so that the > offset field could grow to 53 bits in future. > > So let's move PTE_INVALID to overlay PTE_NS (bit 5). PTE_NS is res0 for > SW outside of the secure state so Linux will never need to touch it. > > These are both marginal benefits, but make things a bit tidier in my > opinion. > > Signed-off-by: Ryan Roberts <ryan.roberts@arm.com> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> (subject to renaming PTE_INVALID to PTE_PRESENT_INVALID)
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h index ef207a0d4f0d..7e1fea3a4328 100644 --- a/arch/arm64/include/asm/pgtable-hwdef.h +++ b/arch/arm64/include/asm/pgtable-hwdef.h @@ -160,6 +160,7 @@ #define PTE_TYPE_MASK (_AT(pteval_t, 3) << 0) #define PTE_TYPE_PAGE (_AT(pteval_t, 3) << 0) #define PTE_TABLE_BIT (_AT(pteval_t, 1) << 1) +#define PTE_NS (_AT(pteval_t, 1) << 5) /* NS */ #define PTE_USER (_AT(pteval_t, 1) << 6) /* AP[1] */ #define PTE_RDONLY (_AT(pteval_t, 1) << 7) /* AP[2] */ #define PTE_SHARED (_AT(pteval_t, 3) << 8) /* SH[1:0], inner shareable */ diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h index de62e6881154..ddf55895c9c2 100644 --- a/arch/arm64/include/asm/pgtable-prot.h +++ b/arch/arm64/include/asm/pgtable-prot.h @@ -18,7 +18,7 @@ #define PTE_DIRTY (_AT(pteval_t, 1) << 55) #define PTE_SPECIAL (_AT(pteval_t, 1) << 56) #define PTE_DEVMAP (_AT(pteval_t, 1) << 57) -#define PTE_INVALID (_AT(pteval_t, 1) << 59) /* only when !PTE_VALID */ +#define PTE_INVALID (PTE_NS) /* only when !PTE_VALID */ #define _PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) #define _PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 8dd4637d6b56..d966d2ee1097 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -1244,11 +1244,11 @@ static inline pmd_t pmdp_establish(struct vm_area_struct *vma, * Encode and decode a swap entry: * bits 0-1: present (must be zero) * bits 2: remember PG_anon_exclusive - * bits 3-7: swap type - * bits 8-57: swap offset - * bit 59: PTE_INVALID (must be zero) + * bit 5: PTE_INVALID (must be zero) + * bits 6-10: swap type + * bits 11-60: swap offset */ -#define __SWP_TYPE_SHIFT 3 +#define __SWP_TYPE_SHIFT 6 #define __SWP_TYPE_BITS 5 #define __SWP_OFFSET_BITS 50 #define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1)
PTE_INVALID was previously occupying bit 59, which when a PTE is valid can either be IGNORED, PBHA[0] or AttrIndex[3], depending on the HW configuration. In practice this is currently not a problem because PTE_INVALID can only be 1 when PTE_VALID=0 and upstream Linux always requires the bit set to 0 for a valid pte. However, if in future Linux wants to use the field (e.g. AttrIndex[3]) then we could end up with confusion when PTE_INVALID comes along and corrupts the field - we would ideally want to preserve it even for an invalid (but present) pte. The other problem with bit 59 is that it prevents the offset field of a swap entry within a swap pte from growing beyond 51 bits. By moving PTE_INVALID to a low bit we can lay the swap pte out so that the offset field could grow to 53 bits in future. So let's move PTE_INVALID to overlay PTE_NS (bit 5). PTE_NS is res0 for SW outside of the secure state so Linux will never need to touch it. These are both marginal benefits, but make things a bit tidier in my opinion. Signed-off-by: Ryan Roberts <ryan.roberts@arm.com> --- arch/arm64/include/asm/pgtable-hwdef.h | 1 + arch/arm64/include/asm/pgtable-prot.h | 2 +- arch/arm64/include/asm/pgtable.h | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-)