Re: TLB flushes on fixmap changes
From: Linus Torvalds
Date: Fri Aug 24 2018 - 20:59:20 EST
Adding a few people to the cc.
On Fri, Aug 24, 2018 at 1:24 PM Nadav Amit <nadav.amit@xxxxxxxxx> wrote:
> >
> > Can you actually find something that changes the fixmaps after boot
> > (again, ignoring kmap)?
>
> At least the alternatives mechanism appears to do so.
>
> IIUC the following path is possible when adding a module:
>
> jump_label_add_module()
> ->__jump_label_update()
> ->arch_jump_label_transform()
> ->__jump_label_transform()
> ->text_poke_bp()
> ->text_poke()
> ->set_fixmap()
Yeah, that looks a bit iffy.
But making the tlb flush global wouldn't help. This is running on a
local core, and if there are other CPU's that can do this at the same
time, then they'd just fight about the same mapping.
Honestly, I think it's ok just because I *hope* this is all serialized
anyway (jump_label_lock? But what about other users of text_poke?).
But I'd be a lot happier about it if it either used an explicit lock
to make sure, or used per-cpu fixmap entries.
And the tlb flush is done *after* the address is used, which is bogus anyway.
> And a similar path can happen when static_key_enable/disable() is called.
Same comments.
How about replacing that
local_irq_save(flags);
... do critical things here ...
local_irq_restore(flags);
in text_poke() with
static DEFINE_SPINLOCK(poke_lock);
spin_lock_irqsave(&poke_lock, flags);
... do critical things here ...
spin_unlock_irqrestore(&poke_lock, flags);
and moving the local_flush_tlb() to after the set_fixmaps, but before
the access through the virtual address.
But changing things to do a global tlb flush would just be wrong.
Linus