.. | .. |
---|
19 | 19 | #include <linux/atomic.h> |
---|
20 | 20 | #include <asm/bug.h> |
---|
21 | 21 | #include <asm/page.h> |
---|
| 22 | +#include <asm/uv.h> |
---|
22 | 23 | |
---|
23 | 24 | extern pgd_t swapper_pg_dir[]; |
---|
24 | 25 | extern void paging_init(void); |
---|
.. | .. |
---|
86 | 87 | */ |
---|
87 | 88 | extern unsigned long VMALLOC_START; |
---|
88 | 89 | extern unsigned long VMALLOC_END; |
---|
| 90 | +#define VMALLOC_DEFAULT_SIZE ((128UL << 30) - MODULES_LEN) |
---|
89 | 91 | extern struct page *vmemmap; |
---|
| 92 | +extern unsigned long vmemmap_size; |
---|
90 | 93 | |
---|
91 | 94 | #define VMEM_MAX_PHYS ((unsigned long) vmemmap) |
---|
92 | 95 | |
---|
.. | .. |
---|
238 | 241 | #define _REGION_ENTRY_NOEXEC 0x100 /* region no-execute bit */ |
---|
239 | 242 | #define _REGION_ENTRY_OFFSET 0xc0 /* region table offset */ |
---|
240 | 243 | #define _REGION_ENTRY_INVALID 0x20 /* invalid region table entry */ |
---|
241 | | -#define _REGION_ENTRY_TYPE_MASK 0x0c /* region/segment table type mask */ |
---|
| 244 | +#define _REGION_ENTRY_TYPE_MASK 0x0c /* region table type mask */ |
---|
242 | 245 | #define _REGION_ENTRY_TYPE_R1 0x0c /* region first table type */ |
---|
243 | 246 | #define _REGION_ENTRY_TYPE_R2 0x08 /* region second table type */ |
---|
244 | 247 | #define _REGION_ENTRY_TYPE_R3 0x04 /* region third table type */ |
---|
.. | .. |
---|
265 | 268 | #endif |
---|
266 | 269 | |
---|
267 | 270 | #define _REGION_ENTRY_BITS 0xfffffffffffff22fUL |
---|
268 | | -#define _REGION_ENTRY_BITS_LARGE 0xffffffff8000fe2fUL |
---|
269 | 271 | |
---|
270 | 272 | /* Bits in the segment table entry */ |
---|
271 | 273 | #define _SEGMENT_ENTRY_BITS 0xfffffffffffffe33UL |
---|
272 | | -#define _SEGMENT_ENTRY_BITS_LARGE 0xfffffffffff0ff33UL |
---|
273 | 274 | #define _SEGMENT_ENTRY_HARDWARE_BITS 0xfffffffffffffe30UL |
---|
274 | 275 | #define _SEGMENT_ENTRY_HARDWARE_BITS_LARGE 0xfffffffffff00730UL |
---|
275 | 276 | #define _SEGMENT_ENTRY_ORIGIN_LARGE ~0xfffffUL /* large page address */ |
---|
.. | .. |
---|
277 | 278 | #define _SEGMENT_ENTRY_PROTECT 0x200 /* segment protection bit */ |
---|
278 | 279 | #define _SEGMENT_ENTRY_NOEXEC 0x100 /* segment no-execute bit */ |
---|
279 | 280 | #define _SEGMENT_ENTRY_INVALID 0x20 /* invalid segment table entry */ |
---|
| 281 | +#define _SEGMENT_ENTRY_TYPE_MASK 0x0c /* segment table type mask */ |
---|
280 | 282 | |
---|
281 | 283 | #define _SEGMENT_ENTRY (0) |
---|
282 | 284 | #define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INVALID) |
---|
.. | .. |
---|
340 | 342 | #define PTRS_PER_PUD _CRST_ENTRIES |
---|
341 | 343 | #define PTRS_PER_P4D _CRST_ENTRIES |
---|
342 | 344 | #define PTRS_PER_PGD _CRST_ENTRIES |
---|
| 345 | + |
---|
| 346 | +#define MAX_PTRS_PER_P4D PTRS_PER_P4D |
---|
343 | 347 | |
---|
344 | 348 | /* |
---|
345 | 349 | * Segment table and region3 table entry encoding |
---|
.. | .. |
---|
466 | 470 | _SEGMENT_ENTRY_YOUNG | \ |
---|
467 | 471 | _SEGMENT_ENTRY_PROTECT | \ |
---|
468 | 472 | _SEGMENT_ENTRY_NOEXEC) |
---|
| 473 | +#define SEGMENT_KERNEL_EXEC __pgprot(_SEGMENT_ENTRY | \ |
---|
| 474 | + _SEGMENT_ENTRY_LARGE | \ |
---|
| 475 | + _SEGMENT_ENTRY_READ | \ |
---|
| 476 | + _SEGMENT_ENTRY_WRITE | \ |
---|
| 477 | + _SEGMENT_ENTRY_YOUNG | \ |
---|
| 478 | + _SEGMENT_ENTRY_DIRTY) |
---|
469 | 479 | |
---|
470 | 480 | /* |
---|
471 | 481 | * Region3 entry (large page) protection definitions. |
---|
.. | .. |
---|
507 | 517 | { |
---|
508 | 518 | #ifdef CONFIG_PGSTE |
---|
509 | 519 | if (unlikely(mm->context.has_pgste)) |
---|
| 520 | + return 1; |
---|
| 521 | +#endif |
---|
| 522 | + return 0; |
---|
| 523 | +} |
---|
| 524 | + |
---|
| 525 | +static inline int mm_is_protected(struct mm_struct *mm) |
---|
| 526 | +{ |
---|
| 527 | +#ifdef CONFIG_PGSTE |
---|
| 528 | + if (unlikely(atomic_read(&mm->context.is_protected))) |
---|
510 | 529 | return 1; |
---|
511 | 530 | #endif |
---|
512 | 531 | return 0; |
---|
.. | .. |
---|
606 | 625 | |
---|
607 | 626 | static inline int pgd_bad(pgd_t pgd) |
---|
608 | 627 | { |
---|
609 | | - /* |
---|
610 | | - * With dynamic page table levels the pgd can be a region table |
---|
611 | | - * entry or a segment table entry. Check for the bit that are |
---|
612 | | - * invalid for either table entry. |
---|
613 | | - */ |
---|
614 | | - unsigned long mask = |
---|
615 | | - ~_SEGMENT_ENTRY_ORIGIN & ~_REGION_ENTRY_INVALID & |
---|
616 | | - ~_REGION_ENTRY_TYPE_MASK & ~_REGION_ENTRY_LENGTH; |
---|
617 | | - return (pgd_val(pgd) & mask) != 0; |
---|
| 628 | + if ((pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R1) |
---|
| 629 | + return 0; |
---|
| 630 | + return (pgd_val(pgd) & ~_REGION_ENTRY_BITS) != 0; |
---|
| 631 | +} |
---|
| 632 | + |
---|
| 633 | +static inline unsigned long pgd_pfn(pgd_t pgd) |
---|
| 634 | +{ |
---|
| 635 | + unsigned long origin_mask; |
---|
| 636 | + |
---|
| 637 | + origin_mask = _REGION_ENTRY_ORIGIN; |
---|
| 638 | + return (pgd_val(pgd) & origin_mask) >> PAGE_SHIFT; |
---|
618 | 639 | } |
---|
619 | 640 | |
---|
620 | 641 | static inline int p4d_folded(p4d_t p4d) |
---|
.. | .. |
---|
663 | 684 | return pud_val(pud) == _REGION3_ENTRY_EMPTY; |
---|
664 | 685 | } |
---|
665 | 686 | |
---|
| 687 | +#define pud_leaf pud_large |
---|
666 | 688 | static inline int pud_large(pud_t pud) |
---|
667 | 689 | { |
---|
668 | 690 | if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) != _REGION_ENTRY_TYPE_R3) |
---|
.. | .. |
---|
670 | 692 | return !!(pud_val(pud) & _REGION3_ENTRY_LARGE); |
---|
671 | 693 | } |
---|
672 | 694 | |
---|
673 | | -static inline unsigned long pud_pfn(pud_t pud) |
---|
674 | | -{ |
---|
675 | | - unsigned long origin_mask; |
---|
676 | | - |
---|
677 | | - origin_mask = _REGION_ENTRY_ORIGIN; |
---|
678 | | - if (pud_large(pud)) |
---|
679 | | - origin_mask = _REGION3_ENTRY_ORIGIN_LARGE; |
---|
680 | | - return (pud_val(pud) & origin_mask) >> PAGE_SHIFT; |
---|
681 | | -} |
---|
682 | | - |
---|
| 695 | +#define pmd_leaf pmd_large |
---|
683 | 696 | static inline int pmd_large(pmd_t pmd) |
---|
684 | 697 | { |
---|
685 | 698 | return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0; |
---|
.. | .. |
---|
687 | 700 | |
---|
688 | 701 | static inline int pmd_bad(pmd_t pmd) |
---|
689 | 702 | { |
---|
690 | | - if (pmd_large(pmd)) |
---|
691 | | - return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS_LARGE) != 0; |
---|
| 703 | + if ((pmd_val(pmd) & _SEGMENT_ENTRY_TYPE_MASK) > 0 || pmd_large(pmd)) |
---|
| 704 | + return 1; |
---|
692 | 705 | return (pmd_val(pmd) & ~_SEGMENT_ENTRY_BITS) != 0; |
---|
693 | 706 | } |
---|
694 | 707 | |
---|
695 | 708 | static inline int pud_bad(pud_t pud) |
---|
696 | 709 | { |
---|
697 | | - if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R3) |
---|
698 | | - return pmd_bad(__pmd(pud_val(pud))); |
---|
699 | | - if (pud_large(pud)) |
---|
700 | | - return (pud_val(pud) & ~_REGION_ENTRY_BITS_LARGE) != 0; |
---|
| 710 | + unsigned long type = pud_val(pud) & _REGION_ENTRY_TYPE_MASK; |
---|
| 711 | + |
---|
| 712 | + if (type > _REGION_ENTRY_TYPE_R3 || pud_large(pud)) |
---|
| 713 | + return 1; |
---|
| 714 | + if (type < _REGION_ENTRY_TYPE_R3) |
---|
| 715 | + return 0; |
---|
701 | 716 | return (pud_val(pud) & ~_REGION_ENTRY_BITS) != 0; |
---|
702 | 717 | } |
---|
703 | 718 | |
---|
704 | 719 | static inline int p4d_bad(p4d_t p4d) |
---|
705 | 720 | { |
---|
706 | | - if ((p4d_val(p4d) & _REGION_ENTRY_TYPE_MASK) < _REGION_ENTRY_TYPE_R2) |
---|
707 | | - return pud_bad(__pud(p4d_val(p4d))); |
---|
| 721 | + unsigned long type = p4d_val(p4d) & _REGION_ENTRY_TYPE_MASK; |
---|
| 722 | + |
---|
| 723 | + if (type > _REGION_ENTRY_TYPE_R2) |
---|
| 724 | + return 1; |
---|
| 725 | + if (type < _REGION_ENTRY_TYPE_R2) |
---|
| 726 | + return 0; |
---|
708 | 727 | return (p4d_val(p4d) & ~_REGION_ENTRY_BITS) != 0; |
---|
709 | 728 | } |
---|
710 | 729 | |
---|
.. | .. |
---|
718 | 737 | return pmd_val(pmd) == _SEGMENT_ENTRY_EMPTY; |
---|
719 | 738 | } |
---|
720 | 739 | |
---|
721 | | -static inline unsigned long pmd_pfn(pmd_t pmd) |
---|
722 | | -{ |
---|
723 | | - unsigned long origin_mask; |
---|
724 | | - |
---|
725 | | - origin_mask = _SEGMENT_ENTRY_ORIGIN; |
---|
726 | | - if (pmd_large(pmd)) |
---|
727 | | - origin_mask = _SEGMENT_ENTRY_ORIGIN_LARGE; |
---|
728 | | - return (pmd_val(pmd) & origin_mask) >> PAGE_SHIFT; |
---|
729 | | -} |
---|
730 | | - |
---|
731 | 740 | #define pmd_write pmd_write |
---|
732 | 741 | static inline int pmd_write(pmd_t pmd) |
---|
733 | 742 | { |
---|
734 | 743 | return (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) != 0; |
---|
735 | 744 | } |
---|
736 | 745 | |
---|
| 746 | +#define pud_write pud_write |
---|
| 747 | +static inline int pud_write(pud_t pud) |
---|
| 748 | +{ |
---|
| 749 | + return (pud_val(pud) & _REGION3_ENTRY_WRITE) != 0; |
---|
| 750 | +} |
---|
| 751 | + |
---|
737 | 752 | static inline int pmd_dirty(pmd_t pmd) |
---|
738 | 753 | { |
---|
739 | | - int dirty = 1; |
---|
740 | | - if (pmd_large(pmd)) |
---|
741 | | - dirty = (pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY) != 0; |
---|
742 | | - return dirty; |
---|
| 754 | + return (pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY) != 0; |
---|
743 | 755 | } |
---|
744 | 756 | |
---|
745 | 757 | static inline int pmd_young(pmd_t pmd) |
---|
746 | 758 | { |
---|
747 | | - int young = 1; |
---|
748 | | - if (pmd_large(pmd)) |
---|
749 | | - young = (pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG) != 0; |
---|
750 | | - return young; |
---|
| 759 | + return (pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG) != 0; |
---|
751 | 760 | } |
---|
752 | 761 | |
---|
753 | 762 | static inline int pte_present(pte_t pte) |
---|
.. | .. |
---|
853 | 862 | static inline int pte_unused(pte_t pte) |
---|
854 | 863 | { |
---|
855 | 864 | return pte_val(pte) & _PAGE_UNUSED; |
---|
| 865 | +} |
---|
| 866 | + |
---|
| 867 | +/* |
---|
| 868 | + * Extract the pgprot value from the given pte while at the same time making it |
---|
| 869 | + * usable for kernel address space mappings where fault driven dirty and |
---|
| 870 | + * young/old accounting is not supported, i.e _PAGE_PROTECT and _PAGE_INVALID |
---|
| 871 | + * must not be set. |
---|
| 872 | + */ |
---|
| 873 | +static inline pgprot_t pte_pgprot(pte_t pte) |
---|
| 874 | +{ |
---|
| 875 | + unsigned long pte_flags = pte_val(pte) & _PAGE_CHG_MASK; |
---|
| 876 | + |
---|
| 877 | + if (pte_write(pte)) |
---|
| 878 | + pte_flags |= pgprot_val(PAGE_KERNEL); |
---|
| 879 | + else |
---|
| 880 | + pte_flags |= pgprot_val(PAGE_KERNEL_RO); |
---|
| 881 | + pte_flags |= pte_val(pte) & mio_wb_bit_mask; |
---|
| 882 | + |
---|
| 883 | + return __pgprot(pte_flags); |
---|
856 | 884 | } |
---|
857 | 885 | |
---|
858 | 886 | /* |
---|
.. | .. |
---|
975 | 1003 | #define IPTE_NODAT 0x400 |
---|
976 | 1004 | #define IPTE_GUEST_ASCE 0x800 |
---|
977 | 1005 | |
---|
978 | | -static inline void __ptep_ipte(unsigned long address, pte_t *ptep, |
---|
979 | | - unsigned long opt, unsigned long asce, |
---|
980 | | - int local) |
---|
| 1006 | +static __always_inline void __ptep_ipte(unsigned long address, pte_t *ptep, |
---|
| 1007 | + unsigned long opt, unsigned long asce, |
---|
| 1008 | + int local) |
---|
981 | 1009 | { |
---|
982 | 1010 | unsigned long pto = (unsigned long) ptep; |
---|
983 | 1011 | |
---|
.. | .. |
---|
998 | 1026 | : [r1] "a" (pto), [m4] "i" (local) : "memory"); |
---|
999 | 1027 | } |
---|
1000 | 1028 | |
---|
1001 | | -static inline void __ptep_ipte_range(unsigned long address, int nr, |
---|
1002 | | - pte_t *ptep, int local) |
---|
| 1029 | +static __always_inline void __ptep_ipte_range(unsigned long address, int nr, |
---|
| 1030 | + pte_t *ptep, int local) |
---|
1003 | 1031 | { |
---|
1004 | 1032 | unsigned long pto = (unsigned long) ptep; |
---|
1005 | 1033 | |
---|
.. | .. |
---|
1049 | 1077 | static inline pte_t ptep_get_and_clear(struct mm_struct *mm, |
---|
1050 | 1078 | unsigned long addr, pte_t *ptep) |
---|
1051 | 1079 | { |
---|
1052 | | - return ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID)); |
---|
| 1080 | + pte_t res; |
---|
| 1081 | + |
---|
| 1082 | + res = ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID)); |
---|
| 1083 | + if (mm_is_protected(mm) && pte_present(res)) |
---|
| 1084 | + uv_convert_from_secure(pte_val(res) & PAGE_MASK); |
---|
| 1085 | + return res; |
---|
1053 | 1086 | } |
---|
1054 | 1087 | |
---|
1055 | 1088 | #define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION |
---|
1056 | | -pte_t ptep_modify_prot_start(struct mm_struct *, unsigned long, pte_t *); |
---|
1057 | | -void ptep_modify_prot_commit(struct mm_struct *, unsigned long, pte_t *, pte_t); |
---|
| 1089 | +pte_t ptep_modify_prot_start(struct vm_area_struct *, unsigned long, pte_t *); |
---|
| 1090 | +void ptep_modify_prot_commit(struct vm_area_struct *, unsigned long, |
---|
| 1091 | + pte_t *, pte_t, pte_t); |
---|
1058 | 1092 | |
---|
1059 | 1093 | #define __HAVE_ARCH_PTEP_CLEAR_FLUSH |
---|
1060 | 1094 | static inline pte_t ptep_clear_flush(struct vm_area_struct *vma, |
---|
1061 | 1095 | unsigned long addr, pte_t *ptep) |
---|
1062 | 1096 | { |
---|
1063 | | - return ptep_xchg_direct(vma->vm_mm, addr, ptep, __pte(_PAGE_INVALID)); |
---|
| 1097 | + pte_t res; |
---|
| 1098 | + |
---|
| 1099 | + res = ptep_xchg_direct(vma->vm_mm, addr, ptep, __pte(_PAGE_INVALID)); |
---|
| 1100 | + if (mm_is_protected(vma->vm_mm) && pte_present(res)) |
---|
| 1101 | + uv_convert_from_secure(pte_val(res) & PAGE_MASK); |
---|
| 1102 | + return res; |
---|
1064 | 1103 | } |
---|
1065 | 1104 | |
---|
1066 | 1105 | /* |
---|
.. | .. |
---|
1075 | 1114 | unsigned long addr, |
---|
1076 | 1115 | pte_t *ptep, int full) |
---|
1077 | 1116 | { |
---|
| 1117 | + pte_t res; |
---|
| 1118 | + |
---|
1078 | 1119 | if (full) { |
---|
1079 | | - pte_t pte = *ptep; |
---|
| 1120 | + res = *ptep; |
---|
1080 | 1121 | *ptep = __pte(_PAGE_INVALID); |
---|
1081 | | - return pte; |
---|
| 1122 | + } else { |
---|
| 1123 | + res = ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID)); |
---|
1082 | 1124 | } |
---|
1083 | | - return ptep_xchg_lazy(mm, addr, ptep, __pte(_PAGE_INVALID)); |
---|
| 1125 | + if (mm_is_protected(mm) && pte_present(res)) |
---|
| 1126 | + uv_convert_from_secure(pte_val(res) & PAGE_MASK); |
---|
| 1127 | + return res; |
---|
1084 | 1128 | } |
---|
1085 | 1129 | |
---|
1086 | 1130 | #define __HAVE_ARCH_PTEP_SET_WRPROTECT |
---|
.. | .. |
---|
1142 | 1186 | void gmap_pmdp_idte_local(struct mm_struct *mm, unsigned long vmaddr); |
---|
1143 | 1187 | void gmap_pmdp_idte_global(struct mm_struct *mm, unsigned long vmaddr); |
---|
1144 | 1188 | |
---|
| 1189 | +#define pgprot_writecombine pgprot_writecombine |
---|
| 1190 | +pgprot_t pgprot_writecombine(pgprot_t prot); |
---|
| 1191 | + |
---|
| 1192 | +#define pgprot_writethrough pgprot_writethrough |
---|
| 1193 | +pgprot_t pgprot_writethrough(pgprot_t prot); |
---|
| 1194 | + |
---|
1145 | 1195 | /* |
---|
1146 | 1196 | * Certain architectures need to do special things when PTEs |
---|
1147 | 1197 | * within a page table are directly modified. Thus, the following |
---|
.. | .. |
---|
1165 | 1215 | static inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot) |
---|
1166 | 1216 | { |
---|
1167 | 1217 | pte_t __pte; |
---|
1168 | | - pte_val(__pte) = physpage + pgprot_val(pgprot); |
---|
| 1218 | + |
---|
| 1219 | + pte_val(__pte) = physpage | pgprot_val(pgprot); |
---|
1169 | 1220 | if (!MACHINE_HAS_NX) |
---|
1170 | 1221 | pte_val(__pte) &= ~_PAGE_NOEXEC; |
---|
1171 | 1222 | return pte_mkyoung(__pte); |
---|
.. | .. |
---|
1185 | 1236 | #define p4d_index(address) (((address) >> P4D_SHIFT) & (PTRS_PER_P4D-1)) |
---|
1186 | 1237 | #define pud_index(address) (((address) >> PUD_SHIFT) & (PTRS_PER_PUD-1)) |
---|
1187 | 1238 | #define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) |
---|
1188 | | -#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) |
---|
1189 | 1239 | |
---|
1190 | | -#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address)) |
---|
1191 | | -#define pgd_offset_k(address) pgd_offset(&init_mm, address) |
---|
1192 | | - |
---|
1193 | | -#define pmd_deref(pmd) (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN) |
---|
1194 | | -#define pud_deref(pud) (pud_val(pud) & _REGION_ENTRY_ORIGIN) |
---|
1195 | 1240 | #define p4d_deref(pud) (p4d_val(pud) & _REGION_ENTRY_ORIGIN) |
---|
1196 | 1241 | #define pgd_deref(pgd) (pgd_val(pgd) & _REGION_ENTRY_ORIGIN) |
---|
1197 | 1242 | |
---|
1198 | | -static inline p4d_t *p4d_offset(pgd_t *pgd, unsigned long address) |
---|
| 1243 | +static inline unsigned long pmd_deref(pmd_t pmd) |
---|
1199 | 1244 | { |
---|
1200 | | - p4d_t *p4d = (p4d_t *) pgd; |
---|
| 1245 | + unsigned long origin_mask; |
---|
1201 | 1246 | |
---|
1202 | | - if ((pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R1) |
---|
1203 | | - p4d = (p4d_t *) pgd_deref(*pgd); |
---|
1204 | | - return p4d + p4d_index(address); |
---|
| 1247 | + origin_mask = _SEGMENT_ENTRY_ORIGIN; |
---|
| 1248 | + if (pmd_large(pmd)) |
---|
| 1249 | + origin_mask = _SEGMENT_ENTRY_ORIGIN_LARGE; |
---|
| 1250 | + return pmd_val(pmd) & origin_mask; |
---|
1205 | 1251 | } |
---|
1206 | 1252 | |
---|
1207 | | -static inline pud_t *pud_offset(p4d_t *p4d, unsigned long address) |
---|
| 1253 | +static inline unsigned long pmd_pfn(pmd_t pmd) |
---|
1208 | 1254 | { |
---|
1209 | | - pud_t *pud = (pud_t *) p4d; |
---|
1210 | | - |
---|
1211 | | - if ((p4d_val(*p4d) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R2) |
---|
1212 | | - pud = (pud_t *) p4d_deref(*p4d); |
---|
1213 | | - return pud + pud_index(address); |
---|
| 1255 | + return pmd_deref(pmd) >> PAGE_SHIFT; |
---|
1214 | 1256 | } |
---|
1215 | 1257 | |
---|
1216 | | -static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address) |
---|
| 1258 | +static inline unsigned long pud_deref(pud_t pud) |
---|
1217 | 1259 | { |
---|
1218 | | - pmd_t *pmd = (pmd_t *) pud; |
---|
| 1260 | + unsigned long origin_mask; |
---|
1219 | 1261 | |
---|
1220 | | - if ((pud_val(*pud) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) |
---|
1221 | | - pmd = (pmd_t *) pud_deref(*pud); |
---|
1222 | | - return pmd + pmd_index(address); |
---|
| 1262 | + origin_mask = _REGION_ENTRY_ORIGIN; |
---|
| 1263 | + if (pud_large(pud)) |
---|
| 1264 | + origin_mask = _REGION3_ENTRY_ORIGIN_LARGE; |
---|
| 1265 | + return pud_val(pud) & origin_mask; |
---|
1223 | 1266 | } |
---|
| 1267 | + |
---|
| 1268 | +static inline unsigned long pud_pfn(pud_t pud) |
---|
| 1269 | +{ |
---|
| 1270 | + return pud_deref(pud) >> PAGE_SHIFT; |
---|
| 1271 | +} |
---|
| 1272 | + |
---|
| 1273 | +/* |
---|
| 1274 | + * The pgd_offset function *always* adds the index for the top-level |
---|
| 1275 | + * region/segment table. This is done to get a sequence like the |
---|
| 1276 | + * following to work: |
---|
| 1277 | + * pgdp = pgd_offset(current->mm, addr); |
---|
| 1278 | + * pgd = READ_ONCE(*pgdp); |
---|
| 1279 | + * p4dp = p4d_offset(&pgd, addr); |
---|
| 1280 | + * ... |
---|
| 1281 | + * The subsequent p4d_offset, pud_offset and pmd_offset functions |
---|
| 1282 | + * only add an index if they dereferenced the pointer. |
---|
| 1283 | + */ |
---|
| 1284 | +static inline pgd_t *pgd_offset_raw(pgd_t *pgd, unsigned long address) |
---|
| 1285 | +{ |
---|
| 1286 | + unsigned long rste; |
---|
| 1287 | + unsigned int shift; |
---|
| 1288 | + |
---|
| 1289 | + /* Get the first entry of the top level table */ |
---|
| 1290 | + rste = pgd_val(*pgd); |
---|
| 1291 | + /* Pick up the shift from the table type of the first entry */ |
---|
| 1292 | + shift = ((rste & _REGION_ENTRY_TYPE_MASK) >> 2) * 11 + 20; |
---|
| 1293 | + return pgd + ((address >> shift) & (PTRS_PER_PGD - 1)); |
---|
| 1294 | +} |
---|
| 1295 | + |
---|
| 1296 | +#define pgd_offset(mm, address) pgd_offset_raw(READ_ONCE((mm)->pgd), address) |
---|
| 1297 | + |
---|
| 1298 | +static inline p4d_t *p4d_offset_lockless(pgd_t *pgdp, pgd_t pgd, unsigned long address) |
---|
| 1299 | +{ |
---|
| 1300 | + if ((pgd_val(pgd) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R1) |
---|
| 1301 | + return (p4d_t *) pgd_deref(pgd) + p4d_index(address); |
---|
| 1302 | + return (p4d_t *) pgdp; |
---|
| 1303 | +} |
---|
| 1304 | +#define p4d_offset_lockless p4d_offset_lockless |
---|
| 1305 | + |
---|
| 1306 | +static inline p4d_t *p4d_offset(pgd_t *pgdp, unsigned long address) |
---|
| 1307 | +{ |
---|
| 1308 | + return p4d_offset_lockless(pgdp, *pgdp, address); |
---|
| 1309 | +} |
---|
| 1310 | + |
---|
| 1311 | +static inline pud_t *pud_offset_lockless(p4d_t *p4dp, p4d_t p4d, unsigned long address) |
---|
| 1312 | +{ |
---|
| 1313 | + if ((p4d_val(p4d) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R2) |
---|
| 1314 | + return (pud_t *) p4d_deref(p4d) + pud_index(address); |
---|
| 1315 | + return (pud_t *) p4dp; |
---|
| 1316 | +} |
---|
| 1317 | +#define pud_offset_lockless pud_offset_lockless |
---|
| 1318 | + |
---|
| 1319 | +static inline pud_t *pud_offset(p4d_t *p4dp, unsigned long address) |
---|
| 1320 | +{ |
---|
| 1321 | + return pud_offset_lockless(p4dp, *p4dp, address); |
---|
| 1322 | +} |
---|
| 1323 | +#define pud_offset pud_offset |
---|
| 1324 | + |
---|
| 1325 | +static inline pmd_t *pmd_offset_lockless(pud_t *pudp, pud_t pud, unsigned long address) |
---|
| 1326 | +{ |
---|
| 1327 | + if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) >= _REGION_ENTRY_TYPE_R3) |
---|
| 1328 | + return (pmd_t *) pud_deref(pud) + pmd_index(address); |
---|
| 1329 | + return (pmd_t *) pudp; |
---|
| 1330 | +} |
---|
| 1331 | +#define pmd_offset_lockless pmd_offset_lockless |
---|
| 1332 | + |
---|
| 1333 | +static inline pmd_t *pmd_offset(pud_t *pudp, unsigned long address) |
---|
| 1334 | +{ |
---|
| 1335 | + return pmd_offset_lockless(pudp, *pudp, address); |
---|
| 1336 | +} |
---|
| 1337 | +#define pmd_offset pmd_offset |
---|
| 1338 | + |
---|
| 1339 | +static inline unsigned long pmd_page_vaddr(pmd_t pmd) |
---|
| 1340 | +{ |
---|
| 1341 | + return (unsigned long) pmd_deref(pmd); |
---|
| 1342 | +} |
---|
| 1343 | + |
---|
| 1344 | +static inline bool gup_fast_permitted(unsigned long start, unsigned long end) |
---|
| 1345 | +{ |
---|
| 1346 | + return end <= current->mm->context.asce_limit; |
---|
| 1347 | +} |
---|
| 1348 | +#define gup_fast_permitted gup_fast_permitted |
---|
1224 | 1349 | |
---|
1225 | 1350 | #define pfn_pte(pfn,pgprot) mk_pte_phys(__pa((pfn) << PAGE_SHIFT),(pgprot)) |
---|
1226 | 1351 | #define pte_pfn(x) (pte_val(x) >> PAGE_SHIFT) |
---|
.. | .. |
---|
1228 | 1353 | |
---|
1229 | 1354 | #define pmd_page(pmd) pfn_to_page(pmd_pfn(pmd)) |
---|
1230 | 1355 | #define pud_page(pud) pfn_to_page(pud_pfn(pud)) |
---|
1231 | | -#define p4d_page(pud) pfn_to_page(p4d_pfn(p4d)) |
---|
1232 | | - |
---|
1233 | | -/* Find an entry in the lowest level page table.. */ |
---|
1234 | | -#define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr)) |
---|
1235 | | -#define pte_offset_kernel(pmd, address) pte_offset(pmd,address) |
---|
1236 | | -#define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address) |
---|
1237 | | -#define pte_unmap(pte) do { } while (0) |
---|
| 1356 | +#define p4d_page(p4d) pfn_to_page(p4d_pfn(p4d)) |
---|
| 1357 | +#define pgd_page(pgd) pfn_to_page(pgd_pfn(pgd)) |
---|
1238 | 1358 | |
---|
1239 | 1359 | static inline pmd_t pmd_wrprotect(pmd_t pmd) |
---|
1240 | 1360 | { |
---|
.. | .. |
---|
1246 | 1366 | static inline pmd_t pmd_mkwrite(pmd_t pmd) |
---|
1247 | 1367 | { |
---|
1248 | 1368 | pmd_val(pmd) |= _SEGMENT_ENTRY_WRITE; |
---|
1249 | | - if (pmd_large(pmd) && !(pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY)) |
---|
1250 | | - return pmd; |
---|
1251 | | - pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT; |
---|
| 1369 | + if (pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY) |
---|
| 1370 | + pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT; |
---|
1252 | 1371 | return pmd; |
---|
1253 | 1372 | } |
---|
1254 | 1373 | |
---|
1255 | 1374 | static inline pmd_t pmd_mkclean(pmd_t pmd) |
---|
1256 | 1375 | { |
---|
1257 | | - if (pmd_large(pmd)) { |
---|
1258 | | - pmd_val(pmd) &= ~_SEGMENT_ENTRY_DIRTY; |
---|
1259 | | - pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT; |
---|
1260 | | - } |
---|
| 1376 | + pmd_val(pmd) &= ~_SEGMENT_ENTRY_DIRTY; |
---|
| 1377 | + pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT; |
---|
1261 | 1378 | return pmd; |
---|
1262 | 1379 | } |
---|
1263 | 1380 | |
---|
1264 | 1381 | static inline pmd_t pmd_mkdirty(pmd_t pmd) |
---|
1265 | 1382 | { |
---|
1266 | | - if (pmd_large(pmd)) { |
---|
1267 | | - pmd_val(pmd) |= _SEGMENT_ENTRY_DIRTY | |
---|
1268 | | - _SEGMENT_ENTRY_SOFT_DIRTY; |
---|
1269 | | - if (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) |
---|
1270 | | - pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT; |
---|
1271 | | - } |
---|
| 1383 | + pmd_val(pmd) |= _SEGMENT_ENTRY_DIRTY | _SEGMENT_ENTRY_SOFT_DIRTY; |
---|
| 1384 | + if (pmd_val(pmd) & _SEGMENT_ENTRY_WRITE) |
---|
| 1385 | + pmd_val(pmd) &= ~_SEGMENT_ENTRY_PROTECT; |
---|
1272 | 1386 | return pmd; |
---|
1273 | 1387 | } |
---|
1274 | 1388 | |
---|
.. | .. |
---|
1282 | 1396 | static inline pud_t pud_mkwrite(pud_t pud) |
---|
1283 | 1397 | { |
---|
1284 | 1398 | pud_val(pud) |= _REGION3_ENTRY_WRITE; |
---|
1285 | | - if (pud_large(pud) && !(pud_val(pud) & _REGION3_ENTRY_DIRTY)) |
---|
1286 | | - return pud; |
---|
1287 | | - pud_val(pud) &= ~_REGION_ENTRY_PROTECT; |
---|
| 1399 | + if (pud_val(pud) & _REGION3_ENTRY_DIRTY) |
---|
| 1400 | + pud_val(pud) &= ~_REGION_ENTRY_PROTECT; |
---|
1288 | 1401 | return pud; |
---|
1289 | 1402 | } |
---|
1290 | 1403 | |
---|
1291 | 1404 | static inline pud_t pud_mkclean(pud_t pud) |
---|
1292 | 1405 | { |
---|
1293 | | - if (pud_large(pud)) { |
---|
1294 | | - pud_val(pud) &= ~_REGION3_ENTRY_DIRTY; |
---|
1295 | | - pud_val(pud) |= _REGION_ENTRY_PROTECT; |
---|
1296 | | - } |
---|
| 1406 | + pud_val(pud) &= ~_REGION3_ENTRY_DIRTY; |
---|
| 1407 | + pud_val(pud) |= _REGION_ENTRY_PROTECT; |
---|
1297 | 1408 | return pud; |
---|
1298 | 1409 | } |
---|
1299 | 1410 | |
---|
1300 | 1411 | static inline pud_t pud_mkdirty(pud_t pud) |
---|
1301 | 1412 | { |
---|
1302 | | - if (pud_large(pud)) { |
---|
1303 | | - pud_val(pud) |= _REGION3_ENTRY_DIRTY | |
---|
1304 | | - _REGION3_ENTRY_SOFT_DIRTY; |
---|
1305 | | - if (pud_val(pud) & _REGION3_ENTRY_WRITE) |
---|
1306 | | - pud_val(pud) &= ~_REGION_ENTRY_PROTECT; |
---|
1307 | | - } |
---|
| 1413 | + pud_val(pud) |= _REGION3_ENTRY_DIRTY | _REGION3_ENTRY_SOFT_DIRTY; |
---|
| 1414 | + if (pud_val(pud) & _REGION3_ENTRY_WRITE) |
---|
| 1415 | + pud_val(pud) &= ~_REGION_ENTRY_PROTECT; |
---|
1308 | 1416 | return pud; |
---|
1309 | 1417 | } |
---|
1310 | 1418 | |
---|
.. | .. |
---|
1328 | 1436 | |
---|
1329 | 1437 | static inline pmd_t pmd_mkyoung(pmd_t pmd) |
---|
1330 | 1438 | { |
---|
1331 | | - if (pmd_large(pmd)) { |
---|
1332 | | - pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG; |
---|
1333 | | - if (pmd_val(pmd) & _SEGMENT_ENTRY_READ) |
---|
1334 | | - pmd_val(pmd) &= ~_SEGMENT_ENTRY_INVALID; |
---|
1335 | | - } |
---|
| 1439 | + pmd_val(pmd) |= _SEGMENT_ENTRY_YOUNG; |
---|
| 1440 | + if (pmd_val(pmd) & _SEGMENT_ENTRY_READ) |
---|
| 1441 | + pmd_val(pmd) &= ~_SEGMENT_ENTRY_INVALID; |
---|
1336 | 1442 | return pmd; |
---|
1337 | 1443 | } |
---|
1338 | 1444 | |
---|
1339 | 1445 | static inline pmd_t pmd_mkold(pmd_t pmd) |
---|
1340 | 1446 | { |
---|
1341 | | - if (pmd_large(pmd)) { |
---|
1342 | | - pmd_val(pmd) &= ~_SEGMENT_ENTRY_YOUNG; |
---|
1343 | | - pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID; |
---|
1344 | | - } |
---|
| 1447 | + pmd_val(pmd) &= ~_SEGMENT_ENTRY_YOUNG; |
---|
| 1448 | + pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID; |
---|
1345 | 1449 | return pmd; |
---|
1346 | 1450 | } |
---|
1347 | 1451 | |
---|
1348 | 1452 | static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) |
---|
1349 | 1453 | { |
---|
1350 | | - if (pmd_large(pmd)) { |
---|
1351 | | - pmd_val(pmd) &= _SEGMENT_ENTRY_ORIGIN_LARGE | |
---|
1352 | | - _SEGMENT_ENTRY_DIRTY | _SEGMENT_ENTRY_YOUNG | |
---|
1353 | | - _SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_SOFT_DIRTY; |
---|
1354 | | - pmd_val(pmd) |= massage_pgprot_pmd(newprot); |
---|
1355 | | - if (!(pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY)) |
---|
1356 | | - pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT; |
---|
1357 | | - if (!(pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG)) |
---|
1358 | | - pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID; |
---|
1359 | | - return pmd; |
---|
1360 | | - } |
---|
1361 | | - pmd_val(pmd) &= _SEGMENT_ENTRY_ORIGIN; |
---|
| 1454 | + pmd_val(pmd) &= _SEGMENT_ENTRY_ORIGIN_LARGE | |
---|
| 1455 | + _SEGMENT_ENTRY_DIRTY | _SEGMENT_ENTRY_YOUNG | |
---|
| 1456 | + _SEGMENT_ENTRY_LARGE | _SEGMENT_ENTRY_SOFT_DIRTY; |
---|
1362 | 1457 | pmd_val(pmd) |= massage_pgprot_pmd(newprot); |
---|
| 1458 | + if (!(pmd_val(pmd) & _SEGMENT_ENTRY_DIRTY)) |
---|
| 1459 | + pmd_val(pmd) |= _SEGMENT_ENTRY_PROTECT; |
---|
| 1460 | + if (!(pmd_val(pmd) & _SEGMENT_ENTRY_YOUNG)) |
---|
| 1461 | + pmd_val(pmd) |= _SEGMENT_ENTRY_INVALID; |
---|
1363 | 1462 | return pmd; |
---|
1364 | 1463 | } |
---|
1365 | 1464 | |
---|
.. | .. |
---|
1385 | 1484 | #define IDTE_NODAT 0x1000 |
---|
1386 | 1485 | #define IDTE_GUEST_ASCE 0x2000 |
---|
1387 | 1486 | |
---|
1388 | | -static inline void __pmdp_idte(unsigned long addr, pmd_t *pmdp, |
---|
1389 | | - unsigned long opt, unsigned long asce, |
---|
1390 | | - int local) |
---|
| 1487 | +static __always_inline void __pmdp_idte(unsigned long addr, pmd_t *pmdp, |
---|
| 1488 | + unsigned long opt, unsigned long asce, |
---|
| 1489 | + int local) |
---|
1391 | 1490 | { |
---|
1392 | 1491 | unsigned long sto; |
---|
1393 | 1492 | |
---|
.. | .. |
---|
1411 | 1510 | } |
---|
1412 | 1511 | } |
---|
1413 | 1512 | |
---|
1414 | | -static inline void __pudp_idte(unsigned long addr, pud_t *pudp, |
---|
1415 | | - unsigned long opt, unsigned long asce, |
---|
1416 | | - int local) |
---|
| 1513 | +static __always_inline void __pudp_idte(unsigned long addr, pud_t *pudp, |
---|
| 1514 | + unsigned long opt, unsigned long asce, |
---|
| 1515 | + int local) |
---|
1417 | 1516 | { |
---|
1418 | 1517 | unsigned long r3o; |
---|
1419 | 1518 | |
---|
.. | .. |
---|
1509 | 1608 | } |
---|
1510 | 1609 | |
---|
1511 | 1610 | #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR_FULL |
---|
1512 | | -static inline pmd_t pmdp_huge_get_and_clear_full(struct mm_struct *mm, |
---|
| 1611 | +static inline pmd_t pmdp_huge_get_and_clear_full(struct vm_area_struct *vma, |
---|
1513 | 1612 | unsigned long addr, |
---|
1514 | 1613 | pmd_t *pmdp, int full) |
---|
1515 | 1614 | { |
---|
.. | .. |
---|
1518 | 1617 | *pmdp = __pmd(_SEGMENT_ENTRY_EMPTY); |
---|
1519 | 1618 | return pmd; |
---|
1520 | 1619 | } |
---|
1521 | | - return pmdp_xchg_lazy(mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_EMPTY)); |
---|
| 1620 | + return pmdp_xchg_lazy(vma->vm_mm, addr, pmdp, __pmd(_SEGMENT_ENTRY_EMPTY)); |
---|
1522 | 1621 | } |
---|
1523 | 1622 | |
---|
1524 | 1623 | #define __HAVE_ARCH_PMDP_HUGE_CLEAR_FLUSH |
---|
.. | .. |
---|
1623 | 1722 | #define kern_addr_valid(addr) (1) |
---|
1624 | 1723 | |
---|
1625 | 1724 | extern int vmem_add_mapping(unsigned long start, unsigned long size); |
---|
1626 | | -extern int vmem_remove_mapping(unsigned long start, unsigned long size); |
---|
| 1725 | +extern void vmem_remove_mapping(unsigned long start, unsigned long size); |
---|
1627 | 1726 | extern int s390_enable_sie(void); |
---|
1628 | 1727 | extern int s390_enable_skey(void); |
---|
1629 | 1728 | extern void s390_reset_cmma(struct mm_struct *mm); |
---|
.. | .. |
---|
1631 | 1730 | /* s390 has a private copy of get unmapped area to deal with cache synonyms */ |
---|
1632 | 1731 | #define HAVE_ARCH_UNMAPPED_AREA |
---|
1633 | 1732 | #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN |
---|
1634 | | - |
---|
1635 | | -/* |
---|
1636 | | - * No page table caches to initialise |
---|
1637 | | - */ |
---|
1638 | | -static inline void pgtable_cache_init(void) { } |
---|
1639 | | -static inline void check_pgt_cache(void) { } |
---|
1640 | | - |
---|
1641 | | -#include <asm-generic/pgtable.h> |
---|
1642 | 1733 | |
---|
1643 | 1734 | #endif /* _S390_PAGE_H */ |
---|