Commit b0d32e5e authored by Nicholas Piggin's avatar Nicholas Piggin Committed by Kleber Sacilotto de Souza

powerpc/64s: Fix compiler store ordering to SLB shadow area

BugLink: https://bugs.launchpad.net/bugs/1791953

[ Upstream commit 926bc2f1 ]

The stores to update the SLB shadow area must be made as they appear
in the C code, so that the hypervisor does not see an entry with
mismatched vsid and esid. Use WRITE_ONCE for this.

GCC has been observed to elide the first store to esid in the update,
which means that if the hypervisor interrupts the guest after storing
to vsid, it could see an entry with old esid and new vsid, which may
possibly result in memory corruption.
Signed-off-by: default avatarNicholas Piggin <npiggin@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Signed-off-by: default avatarSasha Levin <alexander.levin@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarStefan Bader <stefan.bader@canonical.com>
Signed-off-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
parent 681ee1e5
...@@ -69,14 +69,14 @@ static inline void slb_shadow_update(unsigned long ea, int ssize, ...@@ -69,14 +69,14 @@ static inline void slb_shadow_update(unsigned long ea, int ssize,
* updating it. No write barriers are needed here, provided * updating it. No write barriers are needed here, provided
* we only update the current CPU's SLB shadow buffer. * we only update the current CPU's SLB shadow buffer.
*/ */
p->save_area[index].esid = 0; WRITE_ONCE(p->save_area[index].esid, 0);
p->save_area[index].vsid = cpu_to_be64(mk_vsid_data(ea, ssize, flags)); WRITE_ONCE(p->save_area[index].vsid, cpu_to_be64(mk_vsid_data(ea, ssize, flags)));
p->save_area[index].esid = cpu_to_be64(mk_esid_data(ea, ssize, index)); WRITE_ONCE(p->save_area[index].esid, cpu_to_be64(mk_esid_data(ea, ssize, index)));
} }
static inline void slb_shadow_clear(enum slb_index index) static inline void slb_shadow_clear(enum slb_index index)
{ {
get_slb_shadow()->save_area[index].esid = 0; WRITE_ONCE(get_slb_shadow()->save_area[index].esid, 0);
} }
static inline void create_shadowed_slbe(unsigned long ea, int ssize, static inline void create_shadowed_slbe(unsigned long ea, int ssize,
......
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