aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2016-02-04 06:24:46 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2016-02-23 02:56:17 -0500
commit007ccec53da35528bd06fa0063da55b1311054c1 (patch)
treea08ccb42cad189f7a4ca7bee843972a2227128bb
parent2cfc5f9ce7f5e17553e84d36ea9563e677e369d1 (diff)
s390/pageattr: do a single TLB flush for change_page_attr
The change of the access rights for an address range in the kernel address space is currently done with a loop of IPTE + a store of the modified PTE. Between the IPTE and the store the PTE will be invalid, this intermediate state can cause problems with concurrent accesses. Consider a change of a kernel area from read-write to read-only, a concurrent reader of that area should be fine but with the invalid PTE it might get an unexpected exception. Remove the IPTEs for each PTE and do a global flush after all PTEs have been modified. Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/mm/pageattr.c8
1 files changed, 3 insertions, 5 deletions
diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
index 749c98407b41..f2a5c29a97e9 100644
--- a/arch/s390/mm/pageattr.c
+++ b/arch/s390/mm/pageattr.c
@@ -65,19 +65,17 @@ static pte_t *walk_page_table(unsigned long addr)
65static void change_page_attr(unsigned long addr, int numpages, 65static void change_page_attr(unsigned long addr, int numpages,
66 pte_t (*set) (pte_t)) 66 pte_t (*set) (pte_t))
67{ 67{
68 pte_t *ptep, pte; 68 pte_t *ptep;
69 int i; 69 int i;
70 70
71 for (i = 0; i < numpages; i++) { 71 for (i = 0; i < numpages; i++) {
72 ptep = walk_page_table(addr); 72 ptep = walk_page_table(addr);
73 if (WARN_ON_ONCE(!ptep)) 73 if (WARN_ON_ONCE(!ptep))
74 break; 74 break;
75 pte = *ptep; 75 *ptep = set(*ptep);
76 pte = set(pte);
77 __ptep_ipte(addr, ptep);
78 *ptep = pte;
79 addr += PAGE_SIZE; 76 addr += PAGE_SIZE;
80 } 77 }
78 __tlb_flush_kernel();
81} 79}
82 80
83int set_memory_ro(unsigned long addr, int numpages) 81int set_memory_ro(unsigned long addr, int numpages)