Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
e44d6c40 PM |
2 | #ifndef __ASM_SH_PGTABLE_3LEVEL_H |
3 | #define __ASM_SH_PGTABLE_3LEVEL_H | |
5d9b4b19 | 4 | |
9849a569 | 5 | #define __ARCH_USE_5LEVEL_HACK |
5d9b4b19 MF |
6 | #include <asm-generic/pgtable-nopud.h> |
7 | ||
8 | /* | |
9 | * Some cores need a 3-level page table layout, for example when using | |
10 | * 64-bit PTEs and 4K pages. | |
11 | */ | |
782bb5a5 | 12 | #define PAGETABLE_LEVELS 3 |
5d9b4b19 | 13 | |
782bb5a5 | 14 | #define PTE_MAGNITUDE 3 /* 64-bit PTEs on SH-X2 TLB */ |
5d9b4b19 MF |
15 | |
16 | /* PGD bits */ | |
782bb5a5 | 17 | #define PGDIR_SHIFT 30 |
5d9b4b19 MF |
18 | |
19 | #define PTRS_PER_PGD 4 | |
20 | #define USER_PTRS_PER_PGD 2 | |
21 | ||
22 | /* PMD bits */ | |
3f5ab768 | 23 | #define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - PTE_MAGNITUDE)) |
5d9b4b19 MF |
24 | #define PMD_SIZE (1UL << PMD_SHIFT) |
25 | #define PMD_MASK (~(PMD_SIZE-1)) | |
26 | ||
3f5ab768 | 27 | #define PTRS_PER_PMD ((1 << PGDIR_SHIFT) / PMD_SIZE) |
5d9b4b19 MF |
28 | |
29 | #define pmd_ERROR(e) \ | |
30 | printk("%s:%d: bad pmd %016llx.\n", __FILE__, __LINE__, pmd_val(e)) | |
31 | ||
32 | typedef struct { unsigned long long pmd; } pmd_t; | |
33 | #define pmd_val(x) ((x).pmd) | |
34 | #define __pmd(x) ((pmd_t) { (x) } ) | |
35 | ||
36 | static inline unsigned long pud_page_vaddr(pud_t pud) | |
37 | { | |
38 | return pud_val(pud); | |
39 | } | |
40 | ||
41 | #define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) | |
42 | static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) | |
43 | { | |
44 | return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(address); | |
45 | } | |
46 | ||
47 | #define pud_none(x) (!pud_val(x)) | |
48 | #define pud_present(x) (pud_val(x)) | |
49 | #define pud_clear(xp) do { set_pud(xp, __pud(0)); } while (0) | |
50 | #define pud_bad(x) (pud_val(x) & ~PAGE_MASK) | |
51 | ||
52 | /* | |
53 | * (puds are folded into pgds so this doesn't get actually called, | |
54 | * but the define is needed for a generic inline function.) | |
55 | */ | |
56 | #define set_pud(pudptr, pudval) do { *(pudptr) = (pudval); } while(0) | |
57 | ||
e44d6c40 | 58 | #endif /* __ASM_SH_PGTABLE_3LEVEL_H */ |