mips/mm: support __HAVE_ARCH_PTE_SWP_EXCLUSIVE
Let's support __HAVE_ARCH_PTE_SWP_EXCLUSIVE. On 64bit, steal one bit from the type. Generic MM currently only uses 5 bits for the type (MAX_SWAPFILES_SHIFT), so the stolen bit is effectively unused. On 32bit we're able to locate unused bits. As the PTE layout for 32 bit is very confusing, document it a bit better. While at it, mask the type in __swp_entry()/mk_swap_pte(). Link: https://lkml.kernel.org/r/20230113171026.582290-13-david@redhat.com Signed-off-by: David Hildenbrand <david@redhat.com> Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Родитель
b5c88f2153
Коммит
83d3b2b46e
|
@ -191,49 +191,113 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t prot)
|
|||
|
||||
#define pte_page(x) pfn_to_page(pte_pfn(x))
|
||||
|
||||
/*
|
||||
* Encode/decode swap entries and swap PTEs. Swap PTEs are all PTEs that
|
||||
* are !pte_none() && !pte_present().
|
||||
*/
|
||||
#if defined(CONFIG_CPU_R3K_TLB)
|
||||
|
||||
/* Swap entries must have VALID bit cleared. */
|
||||
/*
|
||||
* Format of swap PTEs:
|
||||
*
|
||||
* 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
* <----------- offset ------------> < type -> V G E 0 0 0 0 0 0 P
|
||||
*
|
||||
* E is the exclusive marker that is not stored in swap entries.
|
||||
* _PAGE_PRESENT (P), _PAGE_VALID (V) and_PAGE_GLOBAL (G) have to remain
|
||||
* unused.
|
||||
*/
|
||||
#define __swp_type(x) (((x).val >> 10) & 0x1f)
|
||||
#define __swp_offset(x) ((x).val >> 15)
|
||||
#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 10) | ((offset) << 15) })
|
||||
#define __swp_entry(type, offset) ((swp_entry_t) { (((type) & 0x1f) << 10) | ((offset) << 15) })
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
|
||||
|
||||
/* We borrow bit 7 to store the exclusive marker in swap PTEs. */
|
||||
#define _PAGE_SWP_EXCLUSIVE (1 << 7)
|
||||
|
||||
#else
|
||||
|
||||
#if defined(CONFIG_XPA)
|
||||
|
||||
/* Swap entries must have VALID and GLOBAL bits cleared. */
|
||||
/*
|
||||
* Format of swap PTEs:
|
||||
*
|
||||
* 6 6 6 6 5 5 5 5 5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3
|
||||
* 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2
|
||||
* 0 0 0 0 0 0 E P <------------------ zeroes ------------------->
|
||||
*
|
||||
* 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
* <----------------- offset ------------------> < type -> V G 0 0
|
||||
*
|
||||
* E is the exclusive marker that is not stored in swap entries.
|
||||
* _PAGE_PRESENT (P), _PAGE_VALID (V) and_PAGE_GLOBAL (G) have to remain
|
||||
* unused.
|
||||
*/
|
||||
#define __swp_type(x) (((x).val >> 4) & 0x1f)
|
||||
#define __swp_offset(x) ((x).val >> 9)
|
||||
#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 4) | ((offset) << 9) })
|
||||
#define __swp_entry(type, offset) ((swp_entry_t) { (((type) & 0x1f) << 4) | ((offset) << 9) })
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val })
|
||||
|
||||
/*
|
||||
* We borrow bit 57 (bit 25 in the low PTE) to store the exclusive marker in
|
||||
* swap PTEs.
|
||||
*/
|
||||
#define _PAGE_SWP_EXCLUSIVE (1 << 25)
|
||||
|
||||
#elif defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
|
||||
|
||||
/* Swap entries must have VALID and GLOBAL bits cleared. */
|
||||
/*
|
||||
* Format of swap PTEs:
|
||||
*
|
||||
* 6 6 6 6 5 5 5 5 5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3
|
||||
* 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2
|
||||
* <------------------ zeroes -------------------> E P 0 0 0 0 0 0
|
||||
*
|
||||
* 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
* <------------------- offset --------------------> < type -> V G
|
||||
*
|
||||
* E is the exclusive marker that is not stored in swap entries.
|
||||
* _PAGE_PRESENT (P), _PAGE_VALID (V) and_PAGE_GLOBAL (G) have to remain
|
||||
* unused.
|
||||
*/
|
||||
#define __swp_type(x) (((x).val >> 2) & 0x1f)
|
||||
#define __swp_offset(x) ((x).val >> 7)
|
||||
#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 7) })
|
||||
#define __swp_entry(type, offset) ((swp_entry_t) { (((type) & 0x1f) << 2) | ((offset) << 7) })
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_high })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { 0, (x).val })
|
||||
|
||||
/*
|
||||
* We borrow bit 39 (bit 7 in the low PTE) to store the exclusive marker in swap
|
||||
* PTEs.
|
||||
*/
|
||||
#define _PAGE_SWP_EXCLUSIVE (1 << 7)
|
||||
|
||||
#else
|
||||
/*
|
||||
* Constraints:
|
||||
* _PAGE_PRESENT at bit 0
|
||||
* _PAGE_MODIFIED at bit 4
|
||||
* _PAGE_GLOBAL at bit 6
|
||||
* _PAGE_VALID at bit 7
|
||||
* Format of swap PTEs:
|
||||
*
|
||||
* 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
* <------------- offset --------------> < type -> 0 0 0 0 0 0 E P
|
||||
*
|
||||
* E is the exclusive marker that is not stored in swap entries.
|
||||
* _PAGE_PRESENT (P), _PAGE_VALID (V) and_PAGE_GLOBAL (G) have to remain
|
||||
* unused. The location of V and G varies.
|
||||
*/
|
||||
#define __swp_type(x) (((x).val >> 8) & 0x1f)
|
||||
#define __swp_offset(x) ((x).val >> 13)
|
||||
#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 8) | ((offset) << 13) })
|
||||
#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 8) | ((offset) << 13) })
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
|
||||
|
||||
/* We borrow bit 1 to store the exclusive marker in swap PTEs. */
|
||||
#define _PAGE_SWP_EXCLUSIVE (1 << 1)
|
||||
|
||||
#endif /* defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32) */
|
||||
|
||||
#endif /* defined(CONFIG_CPU_R3K_TLB) */
|
||||
|
|
|
@ -320,16 +320,31 @@ extern void pud_init(void *addr);
|
|||
extern void pmd_init(void *addr);
|
||||
|
||||
/*
|
||||
* Non-present pages: high 40 bits are offset, next 8 bits type,
|
||||
* low 16 bits zero.
|
||||
* Encode/decode swap entries and swap PTEs. Swap PTEs are all PTEs that
|
||||
* are !pte_none() && !pte_present().
|
||||
*
|
||||
* Format of swap PTEs:
|
||||
*
|
||||
* 6 6 6 6 5 5 5 5 5 5 5 5 5 5 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3
|
||||
* 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2
|
||||
* <--------------------------- offset ---------------------------
|
||||
*
|
||||
* 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||
* --------------> E <-- type ---> <---------- zeroes ----------->
|
||||
*
|
||||
* E is the exclusive marker that is not stored in swap entries.
|
||||
*/
|
||||
static inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
|
||||
{ pte_t pte; pte_val(pte) = (type << 16) | (offset << 24); return pte; }
|
||||
{ pte_t pte; pte_val(pte) = ((type & 0x7f) << 16) | (offset << 24); return pte; }
|
||||
|
||||
#define __swp_type(x) (((x).val >> 16) & 0xff)
|
||||
#define __swp_type(x) (((x).val >> 16) & 0x7f)
|
||||
#define __swp_offset(x) ((x).val >> 24)
|
||||
#define __swp_entry(type, offset) ((swp_entry_t) { pte_val(mk_swap_pte((type), (offset))) })
|
||||
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
|
||||
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
|
||||
|
||||
/* We borrow bit 23 to store the exclusive marker in swap PTEs. */
|
||||
#define _PAGE_SWP_EXCLUSIVE (1 << 23)
|
||||
|
||||
#endif /* _ASM_PGTABLE_64_H */
|
||||
|
|
|
@ -528,6 +528,42 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
|
|||
}
|
||||
#endif
|
||||
|
||||
#define __HAVE_ARCH_PTE_SWP_EXCLUSIVE
|
||||
#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
|
||||
static inline int pte_swp_exclusive(pte_t pte)
|
||||
{
|
||||
return pte.pte_low & _PAGE_SWP_EXCLUSIVE;
|
||||
}
|
||||
|
||||
static inline pte_t pte_swp_mkexclusive(pte_t pte)
|
||||
{
|
||||
pte.pte_low |= _PAGE_SWP_EXCLUSIVE;
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_swp_clear_exclusive(pte_t pte)
|
||||
{
|
||||
pte.pte_low &= ~_PAGE_SWP_EXCLUSIVE;
|
||||
return pte;
|
||||
}
|
||||
#else
|
||||
static inline int pte_swp_exclusive(pte_t pte)
|
||||
{
|
||||
return pte_val(pte) & _PAGE_SWP_EXCLUSIVE;
|
||||
}
|
||||
|
||||
static inline pte_t pte_swp_mkexclusive(pte_t pte)
|
||||
{
|
||||
pte_val(pte) |= _PAGE_SWP_EXCLUSIVE;
|
||||
return pte;
|
||||
}
|
||||
|
||||
static inline pte_t pte_swp_clear_exclusive(pte_t pte)
|
||||
{
|
||||
pte_val(pte) &= ~_PAGE_SWP_EXCLUSIVE;
|
||||
return pte;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern void __update_tlb(struct vm_area_struct *vma, unsigned long address,
|
||||
pte_t pte);
|
||||
|
|
Загрузка…
Ссылка в новой задаче