Commit 94d553ce authored by Heiko Carstens's avatar Heiko Carstens Committed by Vasily Gorbik
Browse files

s390/mm: Convert pgste_val() into function



Similar to all other *_val() functions convert the last remaining
architecture specific mm primitive pgste_val() into a function.

Add set_pgste_bit() and clear_pgste_bit() helper functions which allow to
clear and set pgste bits. This is also similar to e.g. set_pte_bit() and
other helper functions.

Acked-by: default avatarAlexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent bb2598c0
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -89,7 +89,10 @@ static inline unsigned long pgprot_val(pgprot_t pgprot)
	return pgprot.pgprot;
}

#define pgste_val(x)	((x).pgste)
static inline unsigned long pgste_val(pgste_t pgste)
{
	return pgste.pgste;
}

static inline unsigned long pte_val(pte_t pte)
{
+10 −0
Original line number Diff line number Diff line
@@ -592,6 +592,16 @@ static inline int mm_alloc_pgste(struct mm_struct *mm)
	return 0;
}

static inline pgste_t clear_pgste_bit(pgste_t pgste, unsigned long mask)
{
	return __pgste(pgste_val(pgste) & ~mask);
}

static inline pgste_t set_pgste_bit(pgste_t pgste, unsigned long mask)
{
	return __pgste(pgste_val(pgste) | mask);
}

static inline pte_t clear_pte_bit(pte_t pte, pgprot_t prot)
{
	return __pte(pte_val(pte) & ~pgprot_val(prot));
+25 −25
Original line number Diff line number Diff line
@@ -173,10 +173,10 @@ static inline pgste_t pgste_update_all(pte_t pte, pgste_t pgste,
	skey = (unsigned long) page_get_storage_key(address);
	bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);
	/* Transfer page changed & referenced bit to guest bits in pgste */
	pgste_val(pgste) |= bits << 48;		/* GR bit & GC bit */
	pgste = set_pgste_bit(pgste, bits << 48); /* GR bit & GC bit */
	/* Copy page access key and fetch protection bit to pgste */
	pgste_val(pgste) &= ~(PGSTE_ACC_BITS | PGSTE_FP_BIT);
	pgste_val(pgste) |= (skey & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56;
	pgste = clear_pgste_bit(pgste, PGSTE_ACC_BITS | PGSTE_FP_BIT);
	pgste = set_pgste_bit(pgste, (skey & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56);
#endif
	return pgste;

@@ -220,7 +220,7 @@ static inline pgste_t pgste_set_pte(pte_t *ptep, pgste_t pgste, pte_t entry)
		}
		if (!(pte_val(entry) & _PAGE_PROTECT))
			/* This pte allows write access, set user-dirty */
			pgste_val(pgste) |= PGSTE_UC_BIT;
			pgste = set_pgste_bit(pgste, PGSTE_UC_BIT);
	}
#endif
	set_pte(ptep, entry);
@@ -236,7 +236,7 @@ static inline pgste_t pgste_pte_notify(struct mm_struct *mm,

	bits = pgste_val(pgste) & (PGSTE_IN_BIT | PGSTE_VSIE_BIT);
	if (bits) {
		pgste_val(pgste) ^= bits;
		pgste = __pgste(pgste_val(pgste) ^ bits);
		ptep_notify(mm, addr, ptep, bits);
	}
#endif
@@ -609,7 +609,7 @@ void ptep_set_pte_at(struct mm_struct *mm, unsigned long addr,
	/* the mm_has_pgste() check is done in set_pte_at() */
	preempt_disable();
	pgste = pgste_get_lock(ptep);
	pgste_val(pgste) &= ~_PGSTE_GPS_ZERO;
	pgste = clear_pgste_bit(pgste, _PGSTE_GPS_ZERO);
	pgste_set_key(ptep, pgste, entry, mm);
	pgste = pgste_set_pte(ptep, pgste, entry);
	pgste_set_unlock(ptep, pgste);
@@ -622,7 +622,7 @@ void ptep_set_notify(struct mm_struct *mm, unsigned long addr, pte_t *ptep)

	preempt_disable();
	pgste = pgste_get_lock(ptep);
	pgste_val(pgste) |= PGSTE_IN_BIT;
	pgste = set_pgste_bit(pgste, PGSTE_IN_BIT);
	pgste_set_unlock(ptep, pgste);
	preempt_enable();
}
@@ -667,7 +667,7 @@ int ptep_force_prot(struct mm_struct *mm, unsigned long addr,
		entry = clear_pte_bit(entry, __pgprot(_PAGE_INVALID));
		entry = set_pte_bit(entry, __pgprot(_PAGE_PROTECT));
	}
	pgste_val(pgste) |= bit;
	pgste = set_pgste_bit(pgste, bit);
	pgste = pgste_set_pte(ptep, pgste, entry);
	pgste_set_unlock(ptep, pgste);
	return 0;
@@ -687,7 +687,7 @@ int ptep_shadow_pte(struct mm_struct *mm, unsigned long saddr,
	if (!(pte_val(spte) & _PAGE_INVALID) &&
	    !((pte_val(spte) & _PAGE_PROTECT) &&
	      !(pte_val(pte) & _PAGE_PROTECT))) {
		pgste_val(spgste) |= PGSTE_VSIE_BIT;
		spgste = set_pgste_bit(spgste, PGSTE_VSIE_BIT);
		tpgste = pgste_get_lock(tptep);
		tpte = __pte((pte_val(spte) & PAGE_MASK) |
			     (pte_val(pte) & _PAGE_PROTECT));
@@ -745,7 +745,7 @@ void ptep_zap_unused(struct mm_struct *mm, unsigned long addr,
		pte_clear(mm, addr, ptep);
	}
	if (reset)
		pgste_val(pgste) &= ~(_PGSTE_GPS_USAGE_MASK | _PGSTE_GPS_NODAT);
		pgste = clear_pgste_bit(pgste, _PGSTE_GPS_USAGE_MASK | _PGSTE_GPS_NODAT);
	pgste_set_unlock(ptep, pgste);
	preempt_enable();
}
@@ -758,8 +758,8 @@ void ptep_zap_key(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
	/* Clear storage key ACC and F, but set R/C */
	preempt_disable();
	pgste = pgste_get_lock(ptep);
	pgste_val(pgste) &= ~(PGSTE_ACC_BITS | PGSTE_FP_BIT);
	pgste_val(pgste) |= PGSTE_GR_BIT | PGSTE_GC_BIT;
	pgste = clear_pgste_bit(pgste, PGSTE_ACC_BITS | PGSTE_FP_BIT);
	pgste = set_pgste_bit(pgste, PGSTE_GR_BIT | PGSTE_GC_BIT);
	ptev = pte_val(*ptep);
	if (!(ptev & _PAGE_INVALID) && (ptev & _PAGE_WRITE))
		page_set_storage_key(ptev & PAGE_MASK, PAGE_DEFAULT_KEY, 0);
@@ -780,7 +780,7 @@ bool ptep_test_and_clear_uc(struct mm_struct *mm, unsigned long addr,

	pgste = pgste_get_lock(ptep);
	dirty = !!(pgste_val(pgste) & PGSTE_UC_BIT);
	pgste_val(pgste) &= ~PGSTE_UC_BIT;
	pgste = clear_pgste_bit(pgste, PGSTE_UC_BIT);
	pte = *ptep;
	if (dirty && (pte_val(pte) & _PAGE_PRESENT)) {
		pgste = pgste_pte_notify(mm, addr, ptep, pgste);
@@ -842,11 +842,11 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
	if (!ptep)
		goto again;
	new = old = pgste_get_lock(ptep);
	pgste_val(new) &= ~(PGSTE_GR_BIT | PGSTE_GC_BIT |
	new = clear_pgste_bit(new, PGSTE_GR_BIT | PGSTE_GC_BIT |
				   PGSTE_ACC_BITS | PGSTE_FP_BIT);
	keyul = (unsigned long) key;
	pgste_val(new) |= (keyul & (_PAGE_CHANGED | _PAGE_REFERENCED)) << 48;
	pgste_val(new) |= (keyul & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56;
	new = set_pgste_bit(new, (keyul & (_PAGE_CHANGED | _PAGE_REFERENCED)) << 48);
	new = set_pgste_bit(new, (keyul & (_PAGE_ACC_BITS | _PAGE_FP_BIT)) << 56);
	if (!(pte_val(*ptep) & _PAGE_INVALID)) {
		unsigned long bits, skey;

@@ -857,12 +857,12 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
		/* Set storage key ACC and FP */
		page_set_storage_key(paddr, skey, !nq);
		/* Merge host changed & referenced into pgste  */
		pgste_val(new) |= bits << 52;
		new = set_pgste_bit(new, bits << 52);
	}
	/* changing the guest storage key is considered a change of the page */
	if ((pgste_val(new) ^ pgste_val(old)) &
	    (PGSTE_ACC_BITS | PGSTE_FP_BIT | PGSTE_GR_BIT | PGSTE_GC_BIT))
		pgste_val(new) |= PGSTE_UC_BIT;
		new = set_pgste_bit(new, PGSTE_UC_BIT);

	pgste_set_unlock(ptep, new);
	pte_unmap_unlock(ptep, ptl);
@@ -950,19 +950,19 @@ int reset_guest_reference_bit(struct mm_struct *mm, unsigned long addr)
		goto again;
	new = old = pgste_get_lock(ptep);
	/* Reset guest reference bit only */
	pgste_val(new) &= ~PGSTE_GR_BIT;
	new = clear_pgste_bit(new, PGSTE_GR_BIT);

	if (!(pte_val(*ptep) & _PAGE_INVALID)) {
		paddr = pte_val(*ptep) & PAGE_MASK;
		cc = page_reset_referenced(paddr);
		/* Merge real referenced bit into host-set */
		pgste_val(new) |= ((unsigned long) cc << 53) & PGSTE_HR_BIT;
		new = set_pgste_bit(new, ((unsigned long)cc << 53) & PGSTE_HR_BIT);
	}
	/* Reflect guest's logical view, not physical */
	cc |= (pgste_val(old) & (PGSTE_GR_BIT | PGSTE_GC_BIT)) >> 49;
	/* Changing the guest storage key is considered a change of the page */
	if ((pgste_val(new) ^ pgste_val(old)) & PGSTE_GR_BIT)
		pgste_val(new) |= PGSTE_UC_BIT;
		new = set_pgste_bit(new, PGSTE_UC_BIT);

	pgste_set_unlock(ptep, new);
	pte_unmap_unlock(ptep, ptl);
@@ -1126,7 +1126,7 @@ int pgste_perform_essa(struct mm_struct *mm, unsigned long hva, int orc,
	if (res)
		pgstev |= _PGSTE_GPS_ZERO;

	pgste_val(pgste) = pgstev;
	pgste = __pgste(pgstev);
	pgste_set_unlock(ptep, pgste);
	pte_unmap_unlock(ptep, ptl);
	return res;
@@ -1159,8 +1159,8 @@ int set_pgste_bits(struct mm_struct *mm, unsigned long hva,
		return -EFAULT;
	new = pgste_get_lock(ptep);

	pgste_val(new) &= ~bits;
	pgste_val(new) |= value & bits;
	new = clear_pgste_bit(new, bits);
	new = set_pgste_bit(new, value & bits);

	pgste_set_unlock(ptep, new);
	pte_unmap_unlock(ptep, ptl);