Skip to content

Commit 5deafa2

Browse files
Gautam GalaClaudio Imbrenda
authored andcommitted
KVM: s390: Fix to clear PTE when discarding a swapped page
KVM run fails when guests with 'cmm' cpu feature and host are under memory pressure and use swap heavily. This is because npages becomes ENOMEN (out of memory) in hva_to_pfn_slow() which inturn propagates as EFAULT to qemu. Clearing the page table entry when discarding an address that maps to a swap entry resolves the issue. Fixes: 2001979 ("KVM: s390: Refactor and split some gmap helpers") Cc: [email protected] Suggested-by: Claudio Imbrenda <[email protected]> Signed-off-by: Gautam Gala <[email protected]> Reviewed-by: Claudio Imbrenda <[email protected]> Signed-off-by: Claudio Imbrenda <[email protected]>
1 parent 352ccf8 commit 5deafa2

File tree

3 files changed

+34
-23
lines changed

3 files changed

+34
-23
lines changed

arch/s390/include/asm/pgtable.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2010,4 +2010,26 @@ static inline unsigned long gmap_pgste_get_pgt_addr(unsigned long *pgt)
20102010
return res;
20112011
}
20122012

2013+
static inline pgste_t pgste_get_lock(pte_t *ptep)
2014+
{
2015+
unsigned long value = 0;
2016+
#ifdef CONFIG_PGSTE
2017+
unsigned long *ptr = (unsigned long *)(ptep + PTRS_PER_PTE);
2018+
2019+
do {
2020+
value = __atomic64_or_barrier(PGSTE_PCL_BIT, ptr);
2021+
} while (value & PGSTE_PCL_BIT);
2022+
value |= PGSTE_PCL_BIT;
2023+
#endif
2024+
return __pgste(value);
2025+
}
2026+
2027+
static inline void pgste_set_unlock(pte_t *ptep, pgste_t pgste)
2028+
{
2029+
#ifdef CONFIG_PGSTE
2030+
barrier();
2031+
WRITE_ONCE(*(unsigned long *)(ptep + PTRS_PER_PTE), pgste_val(pgste) & ~PGSTE_PCL_BIT);
2032+
#endif
2033+
}
2034+
20132035
#endif /* _S390_PAGE_H */

arch/s390/mm/gmap_helpers.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/pagewalk.h>
1414
#include <linux/ksm.h>
1515
#include <asm/gmap_helpers.h>
16+
#include <asm/pgtable.h>
1617

1718
/**
1819
* ptep_zap_swap_entry() - discard a swap entry.
@@ -45,6 +46,7 @@ void gmap_helper_zap_one_page(struct mm_struct *mm, unsigned long vmaddr)
4546
{
4647
struct vm_area_struct *vma;
4748
spinlock_t *ptl;
49+
pgste_t pgste;
4850
pte_t *ptep;
4951

5052
mmap_assert_locked(mm);
@@ -58,8 +60,16 @@ void gmap_helper_zap_one_page(struct mm_struct *mm, unsigned long vmaddr)
5860
ptep = get_locked_pte(mm, vmaddr, &ptl);
5961
if (unlikely(!ptep))
6062
return;
61-
if (pte_swap(*ptep))
63+
if (pte_swap(*ptep)) {
64+
preempt_disable();
65+
pgste = pgste_get_lock(ptep);
66+
6267
ptep_zap_swap_entry(mm, pte_to_swp_entry(*ptep));
68+
pte_clear(mm, vmaddr, ptep);
69+
70+
pgste_set_unlock(ptep, pgste);
71+
preempt_enable();
72+
}
6373
pte_unmap_unlock(ptep, ptl);
6474
}
6575
EXPORT_SYMBOL_GPL(gmap_helper_zap_one_page);

arch/s390/mm/pgtable.c

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <asm/tlbflush.h>
2424
#include <asm/mmu_context.h>
2525
#include <asm/page-states.h>
26+
#include <asm/pgtable.h>
2627
#include <asm/machine.h>
2728

2829
pgprot_t pgprot_writecombine(pgprot_t prot)
@@ -114,28 +115,6 @@ static inline pte_t ptep_flush_lazy(struct mm_struct *mm,
114115
return old;
115116
}
116117

117-
static inline pgste_t pgste_get_lock(pte_t *ptep)
118-
{
119-
unsigned long value = 0;
120-
#ifdef CONFIG_PGSTE
121-
unsigned long *ptr = (unsigned long *)(ptep + PTRS_PER_PTE);
122-
123-
do {
124-
value = __atomic64_or_barrier(PGSTE_PCL_BIT, ptr);
125-
} while (value & PGSTE_PCL_BIT);
126-
value |= PGSTE_PCL_BIT;
127-
#endif
128-
return __pgste(value);
129-
}
130-
131-
static inline void pgste_set_unlock(pte_t *ptep, pgste_t pgste)
132-
{
133-
#ifdef CONFIG_PGSTE
134-
barrier();
135-
WRITE_ONCE(*(unsigned long *)(ptep + PTRS_PER_PTE), pgste_val(pgste) & ~PGSTE_PCL_BIT);
136-
#endif
137-
}
138-
139118
static inline pgste_t pgste_get(pte_t *ptep)
140119
{
141120
unsigned long pgste = 0;

0 commit comments

Comments
 (0)