On Mon, Jul 31, 2023 at 04:36:31PM -0500, Josh Poimboeuf wrote:
On Mon, Jul 31, 2023 at 12:16:59PM +0100, Valentin Schneider wrote:
You're quite right - fabricating an artificial warning with a call to __flush_tlb_local():
vmlinux.o: warning: objtool: pv_ops[1]: indirect call to native_flush_tlb_local() leaves .noinstr.text section vmlinux.o: warning: objtool: __flush_tlb_all_noinstr+0x4: call to {dynamic}() leaves .noinstr.text section
Interestingly the second one doesn't seem to have triggered the "pv_ops" bit of call_dest_name. Seems like any call to insn_reloc(NULL, x) will return NULL.
Yeah, that's weird.
Trickling down the file yields:
vmlinux.o: warning: objtool: pv_ops[1]: indirect call to native_flush_tlb_local() leaves .noinstr.text section vmlinux.o: warning: objtool: __flush_tlb_all_noinstr+0x4: call to pv_ops[0]() leaves .noinstr.text section
In my case (!PARAVIRT_XXL) pv_ops should look like: [0]: .cpu.io_delay [1]: .mmu.flush_tlb_user()
so pv_ops[1] looks right. Seems like pv_call_dest() gets it right because it uses arch_dest_reloc_offset().
If I use the above to fix up validate_call(), would we still need pv_call_dest() & co?
The functionality in pv_call_dest() is still needed because it goes through all the possible targets for the .mmu.flush_tlb_user() pointer -- xen_flush_tlb() and native_flush_tlb_local() -- and makes sure they're noinstr.
Ideally it would only print a single warning for this case, something like:
vmlinux.o: warning: objtool: __flush_tlb_all_noinstr+0x4: indirect call to native_flush_tlb_local() leaves .noinstr.text section
But then what for the case where there are multiple implementations and more than one isn't noinstr? IIRC that is where these double prints came from. One is the callsite (always one) and the second is the offending implementation (but there could be more).
I left out "pv_ops[1]" because it's already long enough :-)
The index number is useful when also looking at the assembler, which IIRC is an indexed indirect call.