aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/include/asm/pgtable.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/include/asm/pgtable.h')
-rw-r--r--arch/s390/include/asm/pgtable.h20
1 files changed, 13 insertions, 7 deletions
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 34ede0ea85a9..4f289ff0b7fe 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -593,14 +593,16 @@ static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste)
593 unsigned long address, bits; 593 unsigned long address, bits;
594 unsigned char skey; 594 unsigned char skey;
595 595
596 if (!pte_present(*ptep))
597 return pgste;
596 address = pte_val(*ptep) & PAGE_MASK; 598 address = pte_val(*ptep) & PAGE_MASK;
597 skey = page_get_storage_key(address); 599 skey = page_get_storage_key(address);
598 bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED); 600 bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);
599 /* Clear page changed & referenced bit in the storage key */ 601 /* Clear page changed & referenced bit in the storage key */
600 if (bits) { 602 if (bits & _PAGE_CHANGED)
601 skey ^= bits; 603 page_set_storage_key(address, skey ^ bits, 1);
602 page_set_storage_key(address, skey, 1); 604 else if (bits)
603 } 605 page_reset_referenced(address);
604 /* Transfer page changed & referenced bit to guest bits in pgste */ 606 /* Transfer page changed & referenced bit to guest bits in pgste */
605 pgste_val(pgste) |= bits << 48; /* RCP_GR_BIT & RCP_GC_BIT */ 607 pgste_val(pgste) |= bits << 48; /* RCP_GR_BIT & RCP_GC_BIT */
606 /* Get host changed & referenced bits from pgste */ 608 /* Get host changed & referenced bits from pgste */
@@ -625,6 +627,8 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste)
625#ifdef CONFIG_PGSTE 627#ifdef CONFIG_PGSTE
626 int young; 628 int young;
627 629
630 if (!pte_present(*ptep))
631 return pgste;
628 young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK); 632 young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK);
629 /* Transfer page referenced bit to pte software bit (host view) */ 633 /* Transfer page referenced bit to pte software bit (host view) */
630 if (young || (pgste_val(pgste) & RCP_HR_BIT)) 634 if (young || (pgste_val(pgste) & RCP_HR_BIT))
@@ -638,13 +642,15 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste)
638 642
639} 643}
640 644
641static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste) 645static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste, pte_t entry)
642{ 646{
643#ifdef CONFIG_PGSTE 647#ifdef CONFIG_PGSTE
644 unsigned long address; 648 unsigned long address;
645 unsigned long okey, nkey; 649 unsigned long okey, nkey;
646 650
647 address = pte_val(*ptep) & PAGE_MASK; 651 if (!pte_present(entry))
652 return;
653 address = pte_val(entry) & PAGE_MASK;
648 okey = nkey = page_get_storage_key(address); 654 okey = nkey = page_get_storage_key(address);
649 nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT); 655 nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT);
650 /* Set page access key and fetch protection bit from pgste */ 656 /* Set page access key and fetch protection bit from pgste */
@@ -712,7 +718,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
712 718
713 if (mm_has_pgste(mm)) { 719 if (mm_has_pgste(mm)) {
714 pgste = pgste_get_lock(ptep); 720 pgste = pgste_get_lock(ptep);
715 pgste_set_pte(ptep, pgste); 721 pgste_set_pte(ptep, pgste, entry);
716 *ptep = entry; 722 *ptep = entry;
717 pgste_set_unlock(ptep, pgste); 723 pgste_set_unlock(ptep, pgste);
718 } else 724 } else