Skip to content

Commit 16ba448

Browse files
hcahcaVasily Gorbik
authored andcommitted
s390/cmma: fix initial kernel address space page table walk
If the cmma no-dat feature is available the kernel page tables are walked to identify and mark all pages which are used for address translation (all region, segment, and page tables). In a subsequent loop all other pages are marked as "no-dat" pages with the ESSA instruction. This information is visible to the hypervisor, so that the hypervisor can optimize purging of guest TLB entries. The initial loop however does not cover the complete kernel address space. This can result in pages being marked as not being used for dynamic address translation, even though they are. In turn guest TLB entries incorrectly may not be purged. Fix this by adjusting the end address of the kernel address range being walked. Cc: <stable@vger.kernel.org> Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com> Reviewed-by: Alexander Gordeev <agordeev@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
1 parent c8b5d57 commit 16ba448

1 file changed

Lines changed: 10 additions & 3 deletions

File tree

arch/s390/mm/page-states.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,15 +151,22 @@ static void mark_kernel_p4d(pgd_t *pgd, unsigned long addr, unsigned long end)
151151

152152
static void mark_kernel_pgd(void)
153153
{
154-
unsigned long addr, next;
154+
unsigned long addr, next, max_addr;
155155
struct page *page;
156156
pgd_t *pgd;
157157
int i;
158158

159159
addr = 0;
160+
/*
161+
* Figure out maximum virtual address accessible with the
162+
* kernel ASCE. This is required to keep the page table walker
163+
* from accessing non-existent entries.
164+
*/
165+
max_addr = (S390_lowcore.kernel_asce.val & _ASCE_TYPE_MASK) >> 2;
166+
max_addr = 1UL << (max_addr * 11 + 31);
160167
pgd = pgd_offset_k(addr);
161168
do {
162-
next = pgd_addr_end(addr, MODULES_END);
169+
next = pgd_addr_end(addr, max_addr);
163170
if (pgd_none(*pgd))
164171
continue;
165172
if (!pgd_folded(*pgd)) {
@@ -168,7 +175,7 @@ static void mark_kernel_pgd(void)
168175
set_bit(PG_arch_1, &page[i].flags);
169176
}
170177
mark_kernel_p4d(pgd, addr, next);
171-
} while (pgd++, addr = next, addr != MODULES_END);
178+
} while (pgd++, addr = next, addr != max_addr);
172179
}
173180

174181
void __init cmma_init_nodat(void)

0 commit comments

Comments
 (0)