aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Schaefer <gerald.schaefer@de.ibm.com>2012-10-25 11:42:50 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-10-26 10:44:23 -0400
commitd8e7a33df0976459674dece4b630b5d59796ece7 (patch)
treead283c3a90e5196cf924ed68481bb1e0dc49f8b6
parent156152f84e57bff4d9b5d70be6f3f16116bf6fb1 (diff)
s390/thp: respect page protection in pmd_none() and pmd_present()
Similar to pte_none() and pte_present(), the pmd functions should also respect page protection of huge pages, especially PROT_NONE. This patch also simplifies massage_pgprot_pmd() by adding new definitions for huge page protection. Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/include/asm/pgtable.h35
1 files changed, 22 insertions, 13 deletions
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index dd647c919a66..2d3b7cb26005 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -506,12 +506,15 @@ static inline int pud_bad(pud_t pud)
506 506
507static inline int pmd_present(pmd_t pmd) 507static inline int pmd_present(pmd_t pmd)
508{ 508{
509 return (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN) != 0UL; 509 unsigned long mask = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO;
510 return (pmd_val(pmd) & mask) == _HPAGE_TYPE_NONE ||
511 !(pmd_val(pmd) & _SEGMENT_ENTRY_INV);
510} 512}
511 513
512static inline int pmd_none(pmd_t pmd) 514static inline int pmd_none(pmd_t pmd)
513{ 515{
514 return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) != 0UL; 516 return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) &&
517 !(pmd_val(pmd) & _SEGMENT_ENTRY_RO);
515} 518}
516 519
517static inline int pmd_large(pmd_t pmd) 520static inline int pmd_large(pmd_t pmd)
@@ -1223,6 +1226,11 @@ static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)
1223} 1226}
1224 1227
1225#ifdef CONFIG_TRANSPARENT_HUGEPAGE 1228#ifdef CONFIG_TRANSPARENT_HUGEPAGE
1229
1230#define SEGMENT_NONE __pgprot(_HPAGE_TYPE_NONE)
1231#define SEGMENT_RO __pgprot(_HPAGE_TYPE_RO)
1232#define SEGMENT_RW __pgprot(_HPAGE_TYPE_RW)
1233
1226#define __HAVE_ARCH_PGTABLE_DEPOSIT 1234#define __HAVE_ARCH_PGTABLE_DEPOSIT
1227extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable); 1235extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable);
1228 1236
@@ -1242,16 +1250,15 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
1242 1250
1243static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot) 1251static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
1244{ 1252{
1245 unsigned long pgprot_pmd = 0; 1253 /*
1246 1254 * pgprot is PAGE_NONE, PAGE_RO, or PAGE_RW (see __Pxxx / __Sxxx)
1247 if (pgprot_val(pgprot) & _PAGE_INVALID) { 1255 * Convert to segment table entry format.
1248 if (pgprot_val(pgprot) & _PAGE_SWT) 1256 */
1249 pgprot_pmd |= _HPAGE_TYPE_NONE; 1257 if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE))
1250 pgprot_pmd |= _SEGMENT_ENTRY_INV; 1258 return pgprot_val(SEGMENT_NONE);
1251 } 1259 if (pgprot_val(pgprot) == pgprot_val(PAGE_RO))
1252 if (pgprot_val(pgprot) & _PAGE_RO) 1260 return pgprot_val(SEGMENT_RO);
1253 pgprot_pmd |= _SEGMENT_ENTRY_RO; 1261 return pgprot_val(SEGMENT_RW);
1254 return pgprot_pmd;
1255} 1262}
1256 1263
1257static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) 1264static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
@@ -1269,7 +1276,9 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
1269 1276
1270static inline pmd_t pmd_mkwrite(pmd_t pmd) 1277static inline pmd_t pmd_mkwrite(pmd_t pmd)
1271{ 1278{
1272 pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO; 1279 /* Do not clobber _HPAGE_TYPE_NONE pages! */
1280 if (!(pmd_val(pmd) & _SEGMENT_ENTRY_INV))
1281 pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;
1273 return pmd; 1282 return pmd;
1274} 1283}
1275 1284