s390/vmem: introduce and use SEGMENT_KERNEL and REGION3_KERNEL
authorHeiko Carstens <heiko.carstens@de.ibm.com>
Wed, 11 May 2016 08:52:07 +0000 (10:52 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 13 Jun 2016 13:58:13 +0000 (15:58 +0200)
Instead of open-coded SEGMENT_KERNEL and REGION3_KERNEL assignments use
defines.  Also to make e.g. pmd_wrprotect() work on the kernel mapping
a couple more flags must be set. Therefore add the missing flags also.

In order to make everything symmetrical this patch also adds software
dirty, young, read and write bits for region 3 table entries.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/pgtable.h
arch/s390/mm/vmem.c

index 58e9950fd57f9640392ae453129616068c4aaddf..898456957c443d87e669cca7ed2464819e941681 100644 (file)
@@ -270,9 +270,20 @@ static inline int is_module_addr(void *addr)
 #define _REGION3_ENTRY         (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH)
 #define _REGION3_ENTRY_EMPTY   (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INVALID)
 
-#define _REGION3_ENTRY_LARGE   0x400   /* RTTE-format control, large page  */
 #define _REGION3_ENTRY_RO      0x200   /* page protection bit              */
 
+#define _REGION3_ENTRY_DIRTY   0x2000  /* SW region dirty bit */
+#define _REGION3_ENTRY_YOUNG   0x1000  /* SW region young bit */
+#define _REGION3_ENTRY_LARGE   0x0400  /* RTTE-format control, large page  */
+#define _REGION3_ENTRY_READ    0x0002  /* SW region read bit */
+#define _REGION3_ENTRY_WRITE   0x0001  /* SW region write bit */
+
+#ifdef CONFIG_MEM_SOFT_DIRTY
+#define _REGION3_ENTRY_SOFT_DIRTY 0x4000 /* SW region soft dirty bit */
+#else
+#define _REGION3_ENTRY_SOFT_DIRTY 0x0000 /* SW region soft dirty bit */
+#endif
+
 /* Bits in the segment table entry */
 #define _SEGMENT_ENTRY_BITS    0xfffffffffffffe33UL
 #define _SEGMENT_ENTRY_BITS_LARGE 0xfffffffffff0ff33UL
@@ -297,7 +308,8 @@ static inline int is_module_addr(void *addr)
 #endif
 
 /*
- * Segment table entry encoding (R = read-only, I = invalid, y = young bit):
+ * Segment table and region3 table entry encoding
+ * (R = read-only, I = invalid, y = young bit):
  *                             dy..R...I...rw
  * prot-none, clean, old       00..1...1...00
  * prot-none, clean, young     01..1...1...00
@@ -391,6 +403,33 @@ static inline int is_module_addr(void *addr)
                                 _SEGMENT_ENTRY_READ)
 #define SEGMENT_WRITE  __pgprot(_SEGMENT_ENTRY_READ | \
                                 _SEGMENT_ENTRY_WRITE)
+#define SEGMENT_KERNEL __pgprot(_SEGMENT_ENTRY |       \
+                                _SEGMENT_ENTRY_LARGE | \
+                                _SEGMENT_ENTRY_READ |  \
+                                _SEGMENT_ENTRY_WRITE | \
+                                _SEGMENT_ENTRY_YOUNG | \
+                                _SEGMENT_ENTRY_DIRTY)
+#define SEGMENT_KERNEL_RO __pgprot(_SEGMENT_ENTRY |    \
+                                _SEGMENT_ENTRY_LARGE | \
+                                _SEGMENT_ENTRY_READ |  \
+                                _SEGMENT_ENTRY_YOUNG | \
+                                _SEGMENT_ENTRY_PROTECT)
+
+/*
+ * Region3 entry (large page) protection definitions.
+ */
+
+#define REGION3_KERNEL __pgprot(_REGION_ENTRY_TYPE_R3 | \
+                                _REGION3_ENTRY_LARGE |  \
+                                _REGION3_ENTRY_READ |   \
+                                _REGION3_ENTRY_WRITE |  \
+                                _REGION3_ENTRY_YOUNG |  \
+                                _REGION3_ENTRY_DIRTY)
+#define REGION3_KERNEL_RO __pgprot(_REGION_ENTRY_TYPE_R3 | \
+                                  _REGION3_ENTRY_LARGE |  \
+                                  _REGION3_ENTRY_READ |   \
+                                  _REGION3_ENTRY_YOUNG |  \
+                                  _REGION_ENTRY_PROTECT)
 
 static inline int mm_has_pgste(struct mm_struct *mm)
 {
index a64b91a8e5ac7a8096eee7614d00ffd6bb4a5429..2020ef8c041339dfa1aaf9c53e973dc616f4a18f 100644 (file)
@@ -99,9 +99,8 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
                if (MACHINE_HAS_EDAT2 && pud_none(*pu_dir) && address &&
                    !(address & ~PUD_MASK) && (address + PUD_SIZE <= end) &&
                     !debug_pagealloc_enabled()) {
-                       pud_val(*pu_dir) = __pa(address) |
-                               _REGION_ENTRY_TYPE_R3 | _REGION3_ENTRY_LARGE |
-                               (ro ? _REGION_ENTRY_PROTECT : 0);
+                       pud_val(*pu_dir) = address |
+                               pgprot_val(ro ? REGION3_KERNEL_RO : REGION3_KERNEL);
                        address += PUD_SIZE;
                        continue;
                }
@@ -115,10 +114,8 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
                if (MACHINE_HAS_EDAT1 && pmd_none(*pm_dir) && address &&
                    !(address & ~PMD_MASK) && (address + PMD_SIZE <= end) &&
                    !debug_pagealloc_enabled()) {
-                       pmd_val(*pm_dir) = __pa(address) |
-                               _SEGMENT_ENTRY | _SEGMENT_ENTRY_LARGE |
-                               _SEGMENT_ENTRY_YOUNG |
-                               (ro ? _SEGMENT_ENTRY_PROTECT : 0);
+                       pmd_val(*pm_dir) = address |
+                               pgprot_val(ro ? SEGMENT_KERNEL_RO : SEGMENT_KERNEL);
                        address += PMD_SIZE;
                        continue;
                }
@@ -130,7 +127,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro)
                }
 
                pt_dir = pte_offset_kernel(pm_dir, address);
-               pte_val(*pt_dir) = __pa(address) |
+               pte_val(*pt_dir) = address |
                        pgprot_val(ro ? PAGE_KERNEL_RO : PAGE_KERNEL);
                address += PAGE_SIZE;
        }