Skip to content
  • Aneesh Kumar K.V's avatar
    powerpc/mm/hash: Fix the reference bit update when handling hash fault · dc47c0c1
    Aneesh Kumar K.V authored
    When we converted the asm routines to C functions, we missed updating
    HPTE_R_R based on _PAGE_ACCESSED. ASM code used to copy over the lower
    bits from pte via.
    
    andi.	r3,r30,0x1fe		/* Get basic set of flags */
    
    We also update the code such that we won't update the Change bit ('C'
    bit) always. This was added by commit c5cf0e30 ("powerpc: Fix
    buglet with MMU hash management").
    
    With hash64, we need to make sure that hardware doesn't do a pte update
    directly. This is because we do end up with entries in TLB with no hash
    page table entry. This happens because when we find a hash bucket full,
    we "evict" a more/less random entry from it. When we do that we don't
    invalidate the TLB (hpte_remove) because we assume the old translation
    is still technically "valid". For more info look at commit
    0608d692("powerpc/mm: Always invalidate tlb on hpte invalidate and
    update").
    
    Thus it's critical that valid hash PTEs always have reference bit set
    and writeable ones have change bit set. We do this by hashing a
    non-dirty linux PTE as read-only and always setting _PAGE_ACCESSED (and
    thus R) when hashing anything else in. Any attempt by Linux at clearing
    those bits also removes the corresponding hash entry.
    
    Commit 5cf0e30bf3d8 did that for 'C' bit by enabling 'C' bit always.
    We don't really need to do that because we never map a RW pte entry
    without setting 'C' bit. On READ fault on a RW pte entry, we still map
    it READ only, hence a store update in the page will still cause a hash
    pte fault.
    
    This patch reverts the part of commit c5cf0e30 ("[PATCH] powerpc:
    Fix buglet with MMU hash management") and retain the updatepp part.
    
    - If we hit the updatepp path on native, the old code without that
      commit, would fail to set C bcause native_hpte_updatepp()
      was implemented to filter the same bits as H_PROTECT and not let C
      through thus we would "upgrade" a RO HPTE to RW without setting C
      thus causing the bug. So the real fix in that commit was the change
      to native_hpte_updatepp
    
    Fixes: 89ff7250
    
     ("powerpc/mm: Convert __hash_page_64K to C")
    Cc: stable@vger.kernel.org # v4.5+
    Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
    Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
    Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
    dc47c0c1