On 1/6/25 09:35, Rik van Riel wrote: > On Mon, 2025-01-06 at 09:29 -0800, Dave Hansen wrote: >> On 12/30/24 09:53, Rik van Riel wrote: >>> --- a/arch/x86/mm/tlb.c >>> +++ b/arch/x86/mm/tlb.c >>> @@ -1074,6 +1074,12 @@ static void do_flush_tlb_all(void *info) >>> void flush_tlb_all(void) >>> { >>> count_vm_tlb_event(NR_TLB_REMOTE_FLUSH); >>> + if (cpu_feature_enabled(X86_FEATURE_INVLPGB)) { >>> + guard(preempt)(); >>> + invlpgb_flush_all(); >>> + tlbsync(); >>> + return; >>> + } >> >> After seeing a few of these, I'd really prefer that the preempt and >> tlbsync() logic be hidden in the invlpgb_*() helper, or *a* helper at >> least. >> >> This would be a lot easier on the eyes if it were something like: >> >> flushed = invlpgb_flush_all(); >> if (flushed) >> return; > > One issue here is that some of the invlpgb helpers > are supposed to be asynchronous, because we can > have multiple of those flushes pending simultaneously, > and then wait for them to complete with a tlbsync. > > How would we avoid the confusion between the two > types (async vs sync) invlpgb helpers? It could be done with naming. Either preface things with __ or give them "sync" suffixes. We could also do it with a calling convention: struct invlpgb_seq; start_invlpgb(&invlpgb_seq); invlpgb_flush_addr(&invlpgb_seq, start, end); end_invlpgb(&invlpgb_seq); The things that can logically get done in sequence need to have the start/end, and need to have the struct passed in. The ones that have the internal sync don't have the argument.