arm64 pmap: Add ATTR_CONTIGUOUS support [Part 1]

The ATTR_CONTIGUOUS bit within an L3 page table entry designates that
L3 page as being part of an aligned, physically contiguous collection
of L3 pages.  For example, 16 aligned, physically contiguous 4 KB pages
can form a 64 KB superpage, occupying a single TLB entry.  While this
change only creates ATTR_CONTIGUOUS mappings in a few places,
specifically, the direct map and pmap_kenter{,_device}(), it adds all
of the necessary code for handling them once they exist, including
demotion, protection, and removal.  Consequently, new ATTR_CONTIGUOUS
usage can be added (and tested) incrementally.

Modify the implementation of sysctl vm.pmap.kernel_maps so that it
correctly reports the number of ATTR_CONTIGUOUS mappings on machines
configured to use a 16 KB base page size, where an ATTR_CONTIGUOUS
mapping consists of 128 base pages.

Additionally, this change adds support for creating L2 superpage
mappings to pmap_kenter{,_device}().

Reviewed by:	markj
Tested by:	gallatin
Differential Revision:	https://reviews.freebsd.org/D42737
This commit is contained in:
Eliot Solomon authored and Alan Cox committed 2024-03-30 13:37:17 -05:00
1 parent 9241ebc796
commit fd6cb031f5
2 files changed
+740 -48

No files matched your search

+719 -48
View File
File diff suppressed because it is too large. Load diff
+21
View File
@@ -120,6 +120,12 @@ typedef uint64_t pt_entry_t; /* page table entry */
#define ATTR_DESCR_TYPE_PAGE 2
#define ATTR_DESCR_TYPE_BLOCK 0
/*
* Superpage promotion requires that the bits specified by the following
* mask all be identical in the constituent PTEs.
*/
#define ATTR_PROMOTE (ATTR_MASK & ~(ATTR_CONTIGUOUS | ATTR_AF))
#if PAGE_SIZE == PAGE_SIZE_4K
#define L0_SHIFT 39
#define L1_SHIFT 30
@@ -187,6 +193,21 @@ typedef uint64_t pt_entry_t; /* page table entry */
#define Ln_ADDR_MASK (Ln_ENTRIES - 1)
#define Ln_TABLE_MASK ((1 << 12) - 1)
/*
* The number of contiguous Level 3 entries (with ATTR_CONTIGUOUS set) that
* can be coalesced into a single TLB entry
*/
#if PAGE_SIZE == PAGE_SIZE_4K
#define L3C_ENTRIES 16
#elif PAGE_SIZE == PAGE_SIZE_16K
#define L3C_ENTRIES 128
#else
#error Unsupported page size
#endif
#define L3C_SIZE (L3C_ENTRIES * L3_SIZE)
#define L3C_OFFSET (L3C_SIZE - 1)
#define pmap_l0_index(va) (((va) >> L0_SHIFT) & L0_ADDR_MASK)
#define pmap_l1_index(va) (((va) >> L1_SHIFT) & Ln_ADDR_MASK)
#define pmap_l2_index(va) (((va) >> L2_SHIFT) & Ln_ADDR_MASK)