powerpc64: Handle the modern (2.05+) implementaiton of tlbie

By happenstance gcc4 puts 'vpn' into r0 in all uses of TLBIE(), but modern
gcc does not.  Also, the single-argument form of tlbie zeros all unused
arguments, making the modern tlbie instruction use r0 as the RS field
(LPID).

The vpn argument has the bottom 12 bits cleared (the input having been
left-shifted by 12 bits), which just so happens, on the POWER9 and previous
incarnations, to be the number of LPID bits supported.  With those bits
being zero, the instruction:

	tlbie r0, r0

will invalidate the VPN in r0, in LPAR 0 (ignoring the upper bits of r0 for
the RS field).  One build with gcc8 yields:

	tlbie r9, r0

with r0 having arbitrary contents, not equal to r9.  This leads to strange
crashes, behaviors, and panics, due to the requested TLB entry not actually
being invalidated.

As the moea64_native must work on both old and new, we explicitly zero out
r0 so that it can work with only the single argument, built with base gcc
and modern gcc.  isa3_hashtb takes a different approach, encoding the
two-argument form, soas not to explicitly clobber r0, and instead let the
compiler decide.

Reported by:	Brandon Bergren
Tested by:	Brandon Bergren
MFC after:	1 week
This commit is contained in:
Justin Hibbits 2019-03-22 01:43:31 +00:00
parent c297300196
commit 091a23cbf8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=345402
2 changed files with 3 additions and 2 deletions

View file

@ -139,7 +139,8 @@ TLBIE(uint64_t vpn)
{
vpn <<= ADDR_PIDX_SHFT;
__asm __volatile("tlbie %0" :: "r"(vpn) : "memory");
__asm __volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 21)"
:: "r"(vpn), "r"(0) : "memory");
__asm __volatile("eieio; tlbsync; ptesync" ::: "memory");
}

View file

@ -156,7 +156,7 @@ TLBIE(uint64_t vpn) {
vpn &= ~(0xffffULL << 48);
#ifdef __powerpc64__
__asm __volatile("tlbie %0" :: "r"(vpn) : "memory");
__asm __volatile("li 0, 0; tlbie %0" :: "r"(vpn) : "0","memory");
__asm __volatile("eieio; tlbsync; ptesync" ::: "memory");
#else
vpn_hi = (uint32_t)(vpn >> 32);