Skip to content

Commit e3613bb

Browse files
sorearpalmer-dabbelt
authored andcommitted
riscv: Add pte bit to distinguish swap from invalid
Previously, invalid PTEs and swap PTEs had the same binary representation, causing errors when attempting to unmap PROT_NONE mappings, including implicit unmap on exit. Typical error: swap_info_get: Bad swap file entry 40000000007a9879 BUG: Bad page map in process a.out pte:3d4c3cc0 pmd:3e521401 Cc: stable@vger.kernel.org Signed-off-by: Stefan O'Rear <sorear2@gmail.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
1 parent d139371 commit e3613bb

File tree

2 files changed

+10
-4
lines changed

2 files changed

+10
-4
lines changed

arch/riscv/include/asm/pgtable-bits.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@
3535
#define _PAGE_SPECIAL _PAGE_SOFT
3636
#define _PAGE_TABLE _PAGE_PRESENT
3737

38+
/*
39+
* _PAGE_PROT_NONE is set on not-present pages (and ignored by the hardware) to
40+
* distinguish them from swapped out pages
41+
*/
42+
#define _PAGE_PROT_NONE _PAGE_READ
43+
3844
#define _PAGE_PFN_SHIFT 10
3945

4046
/* Set of bits to preserve across pte_modify() */

arch/riscv/include/asm/pgtable.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
/* Page protection bits */
4545
#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER)
4646

47-
#define PAGE_NONE __pgprot(0)
47+
#define PAGE_NONE __pgprot(_PAGE_PROT_NONE)
4848
#define PAGE_READ __pgprot(_PAGE_BASE | _PAGE_READ)
4949
#define PAGE_WRITE __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_WRITE)
5050
#define PAGE_EXEC __pgprot(_PAGE_BASE | _PAGE_EXEC)
@@ -98,7 +98,7 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
9898

9999
static inline int pmd_present(pmd_t pmd)
100100
{
101-
return (pmd_val(pmd) & _PAGE_PRESENT);
101+
return (pmd_val(pmd) & (_PAGE_PRESENT | _PAGE_PROT_NONE));
102102
}
103103

104104
static inline int pmd_none(pmd_t pmd)
@@ -178,7 +178,7 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long addr)
178178

179179
static inline int pte_present(pte_t pte)
180180
{
181-
return (pte_val(pte) & _PAGE_PRESENT);
181+
return (pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROT_NONE));
182182
}
183183

184184
static inline int pte_none(pte_t pte)
@@ -380,7 +380,7 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
380380
*
381381
* Format of swap PTE:
382382
* bit 0: _PAGE_PRESENT (zero)
383-
* bit 1: reserved for future use (zero)
383+
* bit 1: _PAGE_PROT_NONE (zero)
384384
* bits 2 to 6: swap type
385385
* bits 7 to XLEN-1: swap offset
386386
*/

0 commit comments

Comments
 (0)