- Fix the MSI message data struct definition
- Use local labels in the exception table macros to avoid symbol conflicts with clang LTO builds - A couple of fixes to objtool checking of the relatively newly added SLS and IBT code - Rename a local var in the WARN* macro machinery to prevent shadowing -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEzv7L6UO9uDPlPSfHEsHwGGHeVUoFAmJSwSkACgkQEsHwGGHe VUp6QQ//TGhL2xxLoN+7pYjIBDEDHJ3Oi0m6fOweqyQAZTYcm/rAPqd7hvoWVSoO YsLdWi9jeMwkzG0ItSm/qPVm/UvrViXwuQMdz4nDWqg2IPFIbhgNA3CKCIyPTio2 WHp2NXvYyDnwPMr6xTTRndMDoxiwxMBnXf91pNwoU3toxw0GuUuXan0Y+GKnvx1A sqhbpWO27bAmhKb26wPw5soJVxBbSqx+1TbFVG0Sz/uwYQowMa+nfNg1DXF0sXyJ E/ssqBB6wjl7ANVbQsxBQHRzr/EksLVPwHHrlT8ga/5loin+VJ6mTBCPLgG7SMBE +R1fm79Bp/9KU194fcqhJ3pvnyJPi8hfizzCqNKnK871V8LRzC+jW0l3EdvASEXC sDj0XWsSFoWft9eAtMV11d641uVC4rLB90GyyzmWWrEw9BbxmasBgED6QBx9d+V6 o1L4y58Tsz88HKzwd0PtBkeGDkvkA7xOx8ViG24IeLA0tcbixnfnATQdelQeWKqO 4m3o1JU8ogJp9JCEBY7ZeXyStFjZMedM4U/V0akF6AKnpDuVfR3T5C68cYhoLKBu XU6Swf5sFHImNWp0+54HPnXhHj/uhuwj9YWCkxx/eXViwvVlxSdTdIQWa380EddN 0KhOFLwLOdhha2+81FJc6vmkDHwiu6hlR38yqdGvdxZf/KPKjM0= =kMtP -----END PGP SIGNATURE----- Merge tag 'x86_urgent_for_v5.18_rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull x86 fixes from Borislav Petkov: - Fix the MSI message data struct definition - Use local labels in the exception table macros to avoid symbol conflicts with clang LTO builds - A couple of fixes to objtool checking of the relatively newly added SLS and IBT code - Rename a local var in the WARN* macro machinery to prevent shadowing * tag 'x86_urgent_for_v5.18_rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/msi: Fix msi message data shadow struct x86/extable: Prefer local labels in .set directives x86,bpf: Avoid IBT objtool warning objtool: Fix SLS validation for kcov tail-call replacement objtool: Fix IBT tail-call detection x86/bug: Prevent shadowing in __WARN_FLAGS x86/mm/tlb: Revert retpoline avoidance approach
This commit is contained in:
commit
9c6913b749
|
@ -154,24 +154,24 @@
|
||||||
|
|
||||||
# define DEFINE_EXTABLE_TYPE_REG \
|
# define DEFINE_EXTABLE_TYPE_REG \
|
||||||
".macro extable_type_reg type:req reg:req\n" \
|
".macro extable_type_reg type:req reg:req\n" \
|
||||||
".set found, 0\n" \
|
".set .Lfound, 0\n" \
|
||||||
".set regnr, 0\n" \
|
".set .Lregnr, 0\n" \
|
||||||
".irp rs,rax,rcx,rdx,rbx,rsp,rbp,rsi,rdi,r8,r9,r10,r11,r12,r13,r14,r15\n" \
|
".irp rs,rax,rcx,rdx,rbx,rsp,rbp,rsi,rdi,r8,r9,r10,r11,r12,r13,r14,r15\n" \
|
||||||
".ifc \\reg, %%\\rs\n" \
|
".ifc \\reg, %%\\rs\n" \
|
||||||
".set found, found+1\n" \
|
".set .Lfound, .Lfound+1\n" \
|
||||||
".long \\type + (regnr << 8)\n" \
|
".long \\type + (.Lregnr << 8)\n" \
|
||||||
".endif\n" \
|
".endif\n" \
|
||||||
".set regnr, regnr+1\n" \
|
".set .Lregnr, .Lregnr+1\n" \
|
||||||
".endr\n" \
|
".endr\n" \
|
||||||
".set regnr, 0\n" \
|
".set .Lregnr, 0\n" \
|
||||||
".irp rs,eax,ecx,edx,ebx,esp,ebp,esi,edi,r8d,r9d,r10d,r11d,r12d,r13d,r14d,r15d\n" \
|
".irp rs,eax,ecx,edx,ebx,esp,ebp,esi,edi,r8d,r9d,r10d,r11d,r12d,r13d,r14d,r15d\n" \
|
||||||
".ifc \\reg, %%\\rs\n" \
|
".ifc \\reg, %%\\rs\n" \
|
||||||
".set found, found+1\n" \
|
".set .Lfound, .Lfound+1\n" \
|
||||||
".long \\type + (regnr << 8)\n" \
|
".long \\type + (.Lregnr << 8)\n" \
|
||||||
".endif\n" \
|
".endif\n" \
|
||||||
".set regnr, regnr+1\n" \
|
".set .Lregnr, .Lregnr+1\n" \
|
||||||
".endr\n" \
|
".endr\n" \
|
||||||
".if (found != 1)\n" \
|
".if (.Lfound != 1)\n" \
|
||||||
".error \"extable_type_reg: bad register argument\"\n" \
|
".error \"extable_type_reg: bad register argument\"\n" \
|
||||||
".endif\n" \
|
".endif\n" \
|
||||||
".endm\n"
|
".endm\n"
|
||||||
|
|
|
@ -78,9 +78,9 @@ do { \
|
||||||
*/
|
*/
|
||||||
#define __WARN_FLAGS(flags) \
|
#define __WARN_FLAGS(flags) \
|
||||||
do { \
|
do { \
|
||||||
__auto_type f = BUGFLAG_WARNING|(flags); \
|
__auto_type __flags = BUGFLAG_WARNING|(flags); \
|
||||||
instrumentation_begin(); \
|
instrumentation_begin(); \
|
||||||
_BUG_FLAGS(ASM_UD2, f, ASM_REACHABLE); \
|
_BUG_FLAGS(ASM_UD2, __flags, ASM_REACHABLE); \
|
||||||
instrumentation_end(); \
|
instrumentation_end(); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
|
@ -12,14 +12,17 @@ int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec,
|
||||||
/* Structs and defines for the X86 specific MSI message format */
|
/* Structs and defines for the X86 specific MSI message format */
|
||||||
|
|
||||||
typedef struct x86_msi_data {
|
typedef struct x86_msi_data {
|
||||||
u32 vector : 8,
|
union {
|
||||||
delivery_mode : 3,
|
struct {
|
||||||
dest_mode_logical : 1,
|
u32 vector : 8,
|
||||||
reserved : 2,
|
delivery_mode : 3,
|
||||||
active_low : 1,
|
dest_mode_logical : 1,
|
||||||
is_level : 1;
|
reserved : 2,
|
||||||
|
active_low : 1,
|
||||||
u32 dmar_subhandle;
|
is_level : 1;
|
||||||
|
};
|
||||||
|
u32 dmar_subhandle;
|
||||||
|
};
|
||||||
} __attribute__ ((packed)) arch_msi_msg_data_t;
|
} __attribute__ ((packed)) arch_msi_msg_data_t;
|
||||||
#define arch_msi_msg_data x86_msi_data
|
#define arch_msi_msg_data x86_msi_data
|
||||||
|
|
||||||
|
|
|
@ -855,13 +855,11 @@ done:
|
||||||
nr_invalidate);
|
nr_invalidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool tlb_is_not_lazy(int cpu)
|
static bool tlb_is_not_lazy(int cpu, void *data)
|
||||||
{
|
{
|
||||||
return !per_cpu(cpu_tlbstate_shared.is_lazy, cpu);
|
return !per_cpu(cpu_tlbstate_shared.is_lazy, cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEFINE_PER_CPU(cpumask_t, flush_tlb_mask);
|
|
||||||
|
|
||||||
DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state_shared, cpu_tlbstate_shared);
|
DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state_shared, cpu_tlbstate_shared);
|
||||||
EXPORT_PER_CPU_SYMBOL(cpu_tlbstate_shared);
|
EXPORT_PER_CPU_SYMBOL(cpu_tlbstate_shared);
|
||||||
|
|
||||||
|
@ -890,36 +888,11 @@ STATIC_NOPV void native_flush_tlb_multi(const struct cpumask *cpumask,
|
||||||
* up on the new contents of what used to be page tables, while
|
* up on the new contents of what used to be page tables, while
|
||||||
* doing a speculative memory access.
|
* doing a speculative memory access.
|
||||||
*/
|
*/
|
||||||
if (info->freed_tables) {
|
if (info->freed_tables)
|
||||||
on_each_cpu_mask(cpumask, flush_tlb_func, (void *)info, true);
|
on_each_cpu_mask(cpumask, flush_tlb_func, (void *)info, true);
|
||||||
} else {
|
else
|
||||||
/*
|
on_each_cpu_cond_mask(tlb_is_not_lazy, flush_tlb_func,
|
||||||
* Although we could have used on_each_cpu_cond_mask(),
|
(void *)info, 1, cpumask);
|
||||||
* open-coding it has performance advantages, as it eliminates
|
|
||||||
* the need for indirect calls or retpolines. In addition, it
|
|
||||||
* allows to use a designated cpumask for evaluating the
|
|
||||||
* condition, instead of allocating one.
|
|
||||||
*
|
|
||||||
* This code works under the assumption that there are no nested
|
|
||||||
* TLB flushes, an assumption that is already made in
|
|
||||||
* flush_tlb_mm_range().
|
|
||||||
*
|
|
||||||
* cond_cpumask is logically a stack-local variable, but it is
|
|
||||||
* more efficient to have it off the stack and not to allocate
|
|
||||||
* it on demand. Preemption is disabled and this code is
|
|
||||||
* non-reentrant.
|
|
||||||
*/
|
|
||||||
struct cpumask *cond_cpumask = this_cpu_ptr(&flush_tlb_mask);
|
|
||||||
int cpu;
|
|
||||||
|
|
||||||
cpumask_clear(cond_cpumask);
|
|
||||||
|
|
||||||
for_each_cpu(cpu, cpumask) {
|
|
||||||
if (tlb_is_not_lazy(cpu))
|
|
||||||
__cpumask_set_cpu(cpu, cond_cpumask);
|
|
||||||
}
|
|
||||||
on_each_cpu_mask(cond_cpumask, flush_tlb_func, (void *)info, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void flush_tlb_multi(const struct cpumask *cpumask,
|
void flush_tlb_multi(const struct cpumask *cpumask,
|
||||||
|
|
|
@ -412,6 +412,7 @@ static void emit_indirect_jump(u8 **pprog, int reg, u8 *ip)
|
||||||
EMIT_LFENCE();
|
EMIT_LFENCE();
|
||||||
EMIT2(0xFF, 0xE0 + reg);
|
EMIT2(0xFF, 0xE0 + reg);
|
||||||
} else if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) {
|
} else if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) {
|
||||||
|
OPTIMIZER_HIDE_VAR(reg);
|
||||||
emit_jump(&prog, &__x86_indirect_thunk_array[reg], ip);
|
emit_jump(&prog, &__x86_indirect_thunk_array[reg], ip);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1155,6 +1155,17 @@ static void annotate_call_site(struct objtool_file *file,
|
||||||
: arch_nop_insn(insn->len));
|
: arch_nop_insn(insn->len));
|
||||||
|
|
||||||
insn->type = sibling ? INSN_RETURN : INSN_NOP;
|
insn->type = sibling ? INSN_RETURN : INSN_NOP;
|
||||||
|
|
||||||
|
if (sibling) {
|
||||||
|
/*
|
||||||
|
* We've replaced the tail-call JMP insn by two new
|
||||||
|
* insn: RET; INT3, except we only have a single struct
|
||||||
|
* insn here. Mark it retpoline_safe to avoid the SLS
|
||||||
|
* warning, instead of adding another insn.
|
||||||
|
*/
|
||||||
|
insn->retpoline_safe = true;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1239,11 +1250,20 @@ static bool same_function(struct instruction *insn1, struct instruction *insn2)
|
||||||
return insn1->func->pfunc == insn2->func->pfunc;
|
return insn1->func->pfunc == insn2->func->pfunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_first_func_insn(struct instruction *insn)
|
static bool is_first_func_insn(struct objtool_file *file, struct instruction *insn)
|
||||||
{
|
{
|
||||||
return insn->offset == insn->func->offset ||
|
if (insn->offset == insn->func->offset)
|
||||||
(insn->type == INSN_ENDBR &&
|
return true;
|
||||||
insn->offset == insn->func->offset + insn->len);
|
|
||||||
|
if (ibt) {
|
||||||
|
struct instruction *prev = prev_insn_same_sym(file, insn);
|
||||||
|
|
||||||
|
if (prev && prev->type == INSN_ENDBR &&
|
||||||
|
insn->offset == insn->func->offset + prev->len)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1327,7 +1347,7 @@ static int add_jump_destinations(struct objtool_file *file)
|
||||||
insn->jump_dest->func->pfunc = insn->func;
|
insn->jump_dest->func->pfunc = insn->func;
|
||||||
|
|
||||||
} else if (!same_function(insn, insn->jump_dest) &&
|
} else if (!same_function(insn, insn->jump_dest) &&
|
||||||
is_first_func_insn(insn->jump_dest)) {
|
is_first_func_insn(file, insn->jump_dest)) {
|
||||||
/* internal sibling call (without reloc) */
|
/* internal sibling call (without reloc) */
|
||||||
add_call_dest(file, insn, insn->jump_dest->func, true);
|
add_call_dest(file, insn, insn->jump_dest->func, true);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue