Commit fc3d4392 authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Luis Henriques

powerpc/mm: Recompute hash value after a failed update

commit 36b35d5d upstream.

If we had secondary hash flag set, we ended up modifying hash value in
the updatepp code path. Hence with a failed updatepp we will be using
a wrong hash value for the following hash insert. Fix this by
recomputing hash before insert.

Without this patch we can end up with using wrong slot number in linux
pte. That can result in us missing an hash pte update or invalidate
which can cause memory corruption or even machine check.

Fixes: 6d492ecc ("powerpc/THP: Add code to handle HPTE faults for hugepages")
Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Reviewed-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent f68edfcd
...@@ -136,7 +136,6 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, ...@@ -136,7 +136,6 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
BUG_ON(index >= 4096); BUG_ON(index >= 4096);
vpn = hpt_vpn(ea, vsid, ssize); vpn = hpt_vpn(ea, vsid, ssize);
hash = hpt_hash(vpn, shift, ssize);
hpte_slot_array = get_hpte_slot_array(pmdp); hpte_slot_array = get_hpte_slot_array(pmdp);
if (psize == MMU_PAGE_4K) { if (psize == MMU_PAGE_4K) {
/* /*
...@@ -151,6 +150,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, ...@@ -151,6 +150,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
valid = hpte_valid(hpte_slot_array, index); valid = hpte_valid(hpte_slot_array, index);
if (valid) { if (valid) {
/* update the hpte bits */ /* update the hpte bits */
hash = hpt_hash(vpn, shift, ssize);
hidx = hpte_hash_index(hpte_slot_array, index); hidx = hpte_hash_index(hpte_slot_array, index);
if (hidx & _PTEIDX_SECONDARY) if (hidx & _PTEIDX_SECONDARY)
hash = ~hash; hash = ~hash;
...@@ -176,6 +176,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, ...@@ -176,6 +176,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid,
if (!valid) { if (!valid) {
unsigned long hpte_group; unsigned long hpte_group;
hash = hpt_hash(vpn, shift, ssize);
/* insert new entry */ /* insert new entry */
pa = pmd_pfn(__pmd(old_pmd)) << PAGE_SHIFT; pa = pmd_pfn(__pmd(old_pmd)) << PAGE_SHIFT;
new_pmd |= _PAGE_HASHPTE; new_pmd |= _PAGE_HASHPTE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment