diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/s390/include/asm/pgtable.h | 22 | ||||
| -rw-r--r-- | arch/s390/mm/gmap_helpers.c | 12 | ||||
| -rw-r--r-- | arch/s390/mm/pgtable.c | 23 | 
3 files changed, 34 insertions, 23 deletions
| diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 6d8bc27a366e..324f96485604 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -2010,4 +2010,26 @@ static inline unsigned long gmap_pgste_get_pgt_addr(unsigned long *pgt)  	return res;  } +static inline pgste_t pgste_get_lock(pte_t *ptep) +{ +	unsigned long value = 0; +#ifdef CONFIG_PGSTE +	unsigned long *ptr = (unsigned long *)(ptep + PTRS_PER_PTE); + +	do { +		value = __atomic64_or_barrier(PGSTE_PCL_BIT, ptr); +	} while (value & PGSTE_PCL_BIT); +	value |= PGSTE_PCL_BIT; +#endif +	return __pgste(value); +} + +static inline void pgste_set_unlock(pte_t *ptep, pgste_t pgste) +{ +#ifdef CONFIG_PGSTE +	barrier(); +	WRITE_ONCE(*(unsigned long *)(ptep + PTRS_PER_PTE), pgste_val(pgste) & ~PGSTE_PCL_BIT); +#endif +} +  #endif /* _S390_PAGE_H */ diff --git a/arch/s390/mm/gmap_helpers.c b/arch/s390/mm/gmap_helpers.c index a45d417ad951..c382005577bd 100644 --- a/arch/s390/mm/gmap_helpers.c +++ b/arch/s390/mm/gmap_helpers.c @@ -13,6 +13,7 @@  #include <linux/pagewalk.h>  #include <linux/ksm.h>  #include <asm/gmap_helpers.h> +#include <asm/pgtable.h>  /**   * 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)  {  	struct vm_area_struct *vma;  	spinlock_t *ptl; +	pgste_t pgste;  	pte_t *ptep;  	mmap_assert_locked(mm); @@ -58,8 +60,16 @@ void gmap_helper_zap_one_page(struct mm_struct *mm, unsigned long vmaddr)  	ptep = get_locked_pte(mm, vmaddr, &ptl);  	if (unlikely(!ptep))  		return; -	if (pte_swap(*ptep)) +	if (pte_swap(*ptep)) { +		preempt_disable(); +		pgste = pgste_get_lock(ptep); +  		ptep_zap_swap_entry(mm, pte_to_swp_entry(*ptep)); +		pte_clear(mm, vmaddr, ptep); + +		pgste_set_unlock(ptep, pgste); +		preempt_enable(); +	}  	pte_unmap_unlock(ptep, ptl);  }  EXPORT_SYMBOL_GPL(gmap_helper_zap_one_page); diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 7df70cd8f739..6b92c348b56f 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -23,6 +23,7 @@  #include <asm/tlbflush.h>  #include <asm/mmu_context.h>  #include <asm/page-states.h> +#include <asm/pgtable.h>  #include <asm/machine.h>  pgprot_t pgprot_writecombine(pgprot_t prot) @@ -114,28 +115,6 @@ static inline pte_t ptep_flush_lazy(struct mm_struct *mm,  	return old;  } -static inline pgste_t pgste_get_lock(pte_t *ptep) -{ -	unsigned long value = 0; -#ifdef CONFIG_PGSTE -	unsigned long *ptr = (unsigned long *)(ptep + PTRS_PER_PTE); - -	do { -		value = __atomic64_or_barrier(PGSTE_PCL_BIT, ptr); -	} while (value & PGSTE_PCL_BIT); -	value |= PGSTE_PCL_BIT; -#endif -	return __pgste(value); -} - -static inline void pgste_set_unlock(pte_t *ptep, pgste_t pgste) -{ -#ifdef CONFIG_PGSTE -	barrier(); -	WRITE_ONCE(*(unsigned long *)(ptep + PTRS_PER_PTE), pgste_val(pgste) & ~PGSTE_PCL_BIT); -#endif -} -  static inline pgste_t pgste_get(pte_t *ptep)  {  	unsigned long pgste = 0; | 
