Message ID | 20201215121119.351650-1-npiggin@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [RFC] mm: generalise COW SMC TLB flushing race comment | expand |
On Tue, Dec 15, 2020 at 10:11:19PM +1000, Nicholas Piggin wrote: > I'm not sure if I'm completely missing something here, but AFAIKS the > reference to the mysterious "COW SMC race" confuses the issue. The original > changelog and mailing list thread didn't help me either. Also, I had no idea that SMC meant Self Modifying Code until you prompted me to go and look up the commit. I thought it meant the Japanese corporation. So this commit is a big improvement. It's the only place we use the acronym 'SMC' in mm/ Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
On Tue, 15 Dec 2020 22:11:19 +1000 Nicholas Piggin <npiggin@gmail.com> wrote: > I'm not sure if I'm completely missing something here, but AFAIKS the > reference to the mysterious "COW SMC race" confuses the issue. The original > changelog and mailing list thread didn't help me either. > > This SMC race is where the problem was detected, but isn't the general > problem bigger and more obvious: that the new PTE could be picked > up at any time by any TLB while entries for the old PTE exist in other > TLBs before the TLB flush takes effect? > > The case where the iTLB and dTLB of a CPU are pointing at different > pages is an interesting one but follows from the general problem. > > The other (minor) thing with the comment I think it makes it a bit > clearer to say what the old code was doing (i.e., it avoids the race > as opposed to what?). Could we please have a signed-off-by for this?
diff --git a/mm/memory.c b/mm/memory.c index ecda25d855ea..fd034b908070 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2880,11 +2880,13 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf) entry = mk_pte(new_page, vma->vm_page_prot); entry = pte_mkyoung(entry); entry = maybe_mkwrite(pte_mkdirty(entry), vma); + /* * Clear the pte entry and flush it first, before updating the - * pte with the new entry. This will avoid a race condition - * seen in the presence of one thread doing SMC and another - * thread doing COW. + * pte with the new entry, to keep TLBs on different CPUs in + * sync. This code used to set the new PTE then flush TLBs, but + * that left a window where the new PTE could be loaded into + * some TLBs while the old PTE remains in others. */ ptep_clear_flush_notify(vma, vmf->address, vmf->pte); page_add_new_anon_rmap(new_page, vma, vmf->address, false);