Hi, Peter, On Mon, Jun 15, 2020 at 09:56:49AM +0200, Peter Zijlstra wrote: > On Fri, Jun 12, 2020 at 05:41:33PM -0700, Fenghua Yu wrote: > > +/* > > + * Apply some heuristics to see if the #GP fault was caused by a thread > > + * that hasn't had the IA32_PASID MSR initialized. If it looks like that > > + * is the problem, try initializing the IA32_PASID MSR. If the heuristic > > + * guesses incorrectly, take one more #GP fault. > > How is that going to help? Aren't we then going to run this same > heuristic again and again and again?
The heuristic always initializes the MSR with the per mm PASID IIF the mm has a valid PASID but the MSR doesn't have one. This heuristic usually happens only once on the first #GP in a thread. If the next #GP still comes in, the heuristic finds out the MSR already has a valid PASID and thus will not fixup the MSR any more. The fixup() returns "false" and lets others to handle the #GP. So the heuristic will be executed once (at most) and won't be executed again and again. > > > + */ > > +bool __fixup_pasid_exception(void) > > +{ > > + u64 pasid_msr; > > + unsigned int pasid; > > + > > + /* > > + * This function is called only when this #GP was triggered from user > > + * space. So the mm cannot be NULL. > > + */ > > + pasid = current->mm->pasid; > > + /* If the mm doesn't have a valid PASID, then can't help. */ > > + if (invalid_pasid(pasid)) > > + return false; > > + > > + /* > > + * Since IRQ is disabled now, the current task still owns the FPU on > > That's just weird and confusing. What you want to say is that you rely > on the exception disabling the interrupt. I checked SDM again. You are right. #GP can be interrupted by machine check or other interrupts. So I cannot assume the current task still owns the FPU. Instead of directly rdmsr() and wrmsr(), I will add helpers that can access either the MSR on the processor or the PASID state in the memory. > > > + * this CPU and the PASID MSR can be directly accessed. > > + * > > + * If the MSR has a valid PASID, the #GP must be for some other reason. > > + * > > + * If rdmsr() is really a performance issue, a TIF_ flag may be > > + * added to check if the thread has a valid PASID instead of rdmsr(). > > I don't understand any of this. Nobody except us writes to this MSR, we > should bloody well know what's in it. What gives? Patch 4 describes how to manage the MSR and patch 7 describes the format of the MSR (20-bit PASID value and bit 31 is valid bit). Are they sufficient to help? Or do you mean something else? > > + */ > > + rdmsrl(MSR_IA32_PASID, pasid_msr); > > + if (pasid_msr & MSR_IA32_PASID_VALID) > > + return false; > > + > > + /* Fix up the MSR if the MSR doesn't have a valid PASID. */ > > + wrmsrl(MSR_IA32_PASID, pasid | MSR_IA32_PASID_VALID); > > + > > + return true; > > +} > > -- > > 2.19.1 > > Thanks. -Fenghua