aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorHeiko Carstens2013-02-16 04:47:27 -0600
committerMartin Schwidefsky2013-02-28 02:37:06 -0600
commit1819ed1f06ade476b701ff764e6cd84a36aee8de (patch)
treecae60343e840f87116a3966f141ef4df3beb56d2 /arch/s390
parent2a7d2b96d5cba7568139d9ab157a0e97ab32440f (diff)
downloadam43-linux-kernel-1819ed1f06ade476b701ff764e6cd84a36aee8de.tar.gz
am43-linux-kernel-1819ed1f06ade476b701ff764e6cd84a36aee8de.tar.xz
am43-linux-kernel-1819ed1f06ade476b701ff764e6cd84a36aee8de.zip
s390/page table dumper: add support for change-recording override bit
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/include/asm/pgtable.h2
-rw-r--r--arch/s390/mm/dump_pagetables.c25
2 files changed, 22 insertions, 5 deletions
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 97de1200c84..4a2930844d4 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -340,6 +340,8 @@ extern unsigned long MODULES_END;
340#define _REGION3_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INV) 340#define _REGION3_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INV)
341 341
342#define _REGION3_ENTRY_LARGE 0x400 /* RTTE-format control, large page */ 342#define _REGION3_ENTRY_LARGE 0x400 /* RTTE-format control, large page */
343#define _REGION3_ENTRY_RO 0x200 /* page protection bit */
344#define _REGION3_ENTRY_CO 0x100 /* change-recording override */
343 345
344/* Bits in the segment table entry */ 346/* Bits in the segment table entry */
345#define _SEGMENT_ENTRY_ORIGIN ~0x7ffUL/* segment table origin */ 347#define _SEGMENT_ENTRY_ORIGIN ~0x7ffUL/* segment table origin */
diff --git a/arch/s390/mm/dump_pagetables.c b/arch/s390/mm/dump_pagetables.c
index 04e4892247d..3ad65b04ac1 100644
--- a/arch/s390/mm/dump_pagetables.c
+++ b/arch/s390/mm/dump_pagetables.c
@@ -49,10 +49,13 @@ static void print_prot(struct seq_file *m, unsigned int pr, int level)
49 { "ASCE", "PGD", "PUD", "PMD", "PTE" }; 49 { "ASCE", "PGD", "PUD", "PMD", "PTE" };
50 50
51 seq_printf(m, "%s ", level_name[level]); 51 seq_printf(m, "%s ", level_name[level]);
52 if (pr & _PAGE_INVALID) 52 if (pr & _PAGE_INVALID) {
53 seq_printf(m, "I\n"); 53 seq_printf(m, "I\n");
54 else 54 return;
55 seq_printf(m, "%s\n", pr & _PAGE_RO ? "RO" : "RW"); 55 }
56 seq_printf(m, "%s", pr & _PAGE_RO ? "RO " : "RW ");
57 seq_printf(m, "%s", pr & _PAGE_CO ? "CO " : " ");
58 seq_putc(m, '\n');
56} 59}
57 60
58static void note_page(struct seq_file *m, struct pg_state *st, 61static void note_page(struct seq_file *m, struct pg_state *st,
@@ -125,6 +128,12 @@ static void walk_pte_level(struct seq_file *m, struct pg_state *st,
125 } 128 }
126} 129}
127 130
131#ifdef CONFIG_64BIT
132#define _PMD_PROT_MASK (_SEGMENT_ENTRY_RO | _SEGMENT_ENTRY_CO)
133#else
134#define _PMD_PROT_MASK 0
135#endif
136
128static void walk_pmd_level(struct seq_file *m, struct pg_state *st, 137static void walk_pmd_level(struct seq_file *m, struct pg_state *st,
129 pud_t *pud, unsigned long addr) 138 pud_t *pud, unsigned long addr)
130{ 139{
@@ -137,7 +146,7 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st,
137 pmd = pmd_offset(pud, addr); 146 pmd = pmd_offset(pud, addr);
138 if (!pmd_none(*pmd)) { 147 if (!pmd_none(*pmd)) {
139 if (pmd_large(*pmd)) { 148 if (pmd_large(*pmd)) {
140 prot = pmd_val(*pmd) & _SEGMENT_ENTRY_RO; 149 prot = pmd_val(*pmd) & _PMD_PROT_MASK;
141 note_page(m, st, prot, 3); 150 note_page(m, st, prot, 3);
142 } else 151 } else
143 walk_pte_level(m, st, pmd, addr); 152 walk_pte_level(m, st, pmd, addr);
@@ -147,6 +156,12 @@ static void walk_pmd_level(struct seq_file *m, struct pg_state *st,
147 } 156 }
148} 157}
149 158
159#ifdef CONFIG_64BIT
160#define _PUD_PROT_MASK (_REGION3_ENTRY_RO | _REGION3_ENTRY_CO)
161#else
162#define _PUD_PROT_MASK 0
163#endif
164
150static void walk_pud_level(struct seq_file *m, struct pg_state *st, 165static void walk_pud_level(struct seq_file *m, struct pg_state *st,
151 pgd_t *pgd, unsigned long addr) 166 pgd_t *pgd, unsigned long addr)
152{ 167{
@@ -159,7 +174,7 @@ static void walk_pud_level(struct seq_file *m, struct pg_state *st,
159 pud = pud_offset(pgd, addr); 174 pud = pud_offset(pgd, addr);
160 if (!pud_none(*pud)) 175 if (!pud_none(*pud))
161 if (pud_large(*pud)) { 176 if (pud_large(*pud)) {
162 prot = pud_val(*pud) & _PAGE_RO; 177 prot = pud_val(*pud) & _PUD_PROT_MASK;
163 note_page(m, st, prot, 2); 178 note_page(m, st, prot, 2);
164 } else 179 } else
165 walk_pmd_level(m, st, pud, addr); 180 walk_pmd_level(m, st, pud, addr);