Commit 2dffdcba authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky

s390/vmem: introduce and use SEGMENT_KERNEL and REGION3_KERNEL

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: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Acked-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 2e9996fc
...@@ -270,9 +270,20 @@ static inline int is_module_addr(void *addr) ...@@ -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 (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH)
#define _REGION3_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INVALID) #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_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 */ /* Bits in the segment table entry */
#define _SEGMENT_ENTRY_BITS 0xfffffffffffffe33UL #define _SEGMENT_ENTRY_BITS 0xfffffffffffffe33UL
#define _SEGMENT_ENTRY_BITS_LARGE 0xfffffffffff0ff33UL #define _SEGMENT_ENTRY_BITS_LARGE 0xfffffffffff0ff33UL
...@@ -297,7 +308,8 @@ static inline int is_module_addr(void *addr) ...@@ -297,7 +308,8 @@ static inline int is_module_addr(void *addr)
#endif #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 * dy..R...I...rw
* prot-none, clean, old 00..1...1...00 * prot-none, clean, old 00..1...1...00
* prot-none, clean, young 01..1...1...00 * prot-none, clean, young 01..1...1...00
...@@ -391,6 +403,33 @@ static inline int is_module_addr(void *addr) ...@@ -391,6 +403,33 @@ static inline int is_module_addr(void *addr)
_SEGMENT_ENTRY_READ) _SEGMENT_ENTRY_READ)
#define SEGMENT_WRITE __pgprot(_SEGMENT_ENTRY_READ | \ #define SEGMENT_WRITE __pgprot(_SEGMENT_ENTRY_READ | \
_SEGMENT_ENTRY_WRITE) _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) static inline int mm_has_pgste(struct mm_struct *mm)
{ {
......
...@@ -99,9 +99,8 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) ...@@ -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 && if (MACHINE_HAS_EDAT2 && pud_none(*pu_dir) && address &&
!(address & ~PUD_MASK) && (address + PUD_SIZE <= end) && !(address & ~PUD_MASK) && (address + PUD_SIZE <= end) &&
!debug_pagealloc_enabled()) { !debug_pagealloc_enabled()) {
pud_val(*pu_dir) = __pa(address) | pud_val(*pu_dir) = address |
_REGION_ENTRY_TYPE_R3 | _REGION3_ENTRY_LARGE | pgprot_val(ro ? REGION3_KERNEL_RO : REGION3_KERNEL);
(ro ? _REGION_ENTRY_PROTECT : 0);
address += PUD_SIZE; address += PUD_SIZE;
continue; continue;
} }
...@@ -115,10 +114,8 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) ...@@ -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 && if (MACHINE_HAS_EDAT1 && pmd_none(*pm_dir) && address &&
!(address & ~PMD_MASK) && (address + PMD_SIZE <= end) && !(address & ~PMD_MASK) && (address + PMD_SIZE <= end) &&
!debug_pagealloc_enabled()) { !debug_pagealloc_enabled()) {
pmd_val(*pm_dir) = __pa(address) | pmd_val(*pm_dir) = address |
_SEGMENT_ENTRY | _SEGMENT_ENTRY_LARGE | pgprot_val(ro ? SEGMENT_KERNEL_RO : SEGMENT_KERNEL);
_SEGMENT_ENTRY_YOUNG |
(ro ? _SEGMENT_ENTRY_PROTECT : 0);
address += PMD_SIZE; address += PMD_SIZE;
continue; continue;
} }
...@@ -130,7 +127,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) ...@@ -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); 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); pgprot_val(ro ? PAGE_KERNEL_RO : PAGE_KERNEL);
address += PAGE_SIZE; address += PAGE_SIZE;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment