diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2013-02-16 05:47:27 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-02-28 03:37:06 -0500 |
commit | 1819ed1f06ade476b701ff764e6cd84a36aee8de (patch) | |
tree | cae60343e840f87116a3966f141ef4df3beb56d2 /arch | |
parent | 2a7d2b96d5cba7568139d9ab157a0e97ab32440f (diff) |
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')
-rw-r--r-- | arch/s390/include/asm/pgtable.h | 2 | ||||
-rw-r--r-- | arch/s390/mm/dump_pagetables.c | 25 |
2 files changed, 22 insertions, 5 deletions
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 97de1200c849..4a2930844d43 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 04e4892247d2..3ad65b04ac15 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 | ||
58 | static void note_page(struct seq_file *m, struct pg_state *st, | 61 | static 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 | |||
128 | static void walk_pmd_level(struct seq_file *m, struct pg_state *st, | 137 | static 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 | |||
150 | static void walk_pud_level(struct seq_file *m, struct pg_state *st, | 165 | static 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); |