Skip to content

Commit da17702

Browse files
committed
Merge branch 'x86-paravirt-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 paravirt updates from Ingo Molnar: "A handful of paravirt patching code enhancements to make it more robust against patching failures, and related cleanups and not so related cleanups - by Thomas Gleixner and myself" * 'x86-paravirt-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/paravirt: Rename paravirt_patch_site::instrtype to paravirt_patch_site::type x86/paravirt: Standardize 'insn_buff' variable names x86/paravirt: Match paravirt patchlet field definition ordering to initialization ordering x86/paravirt: Replace the paravirt patch asm magic x86/paravirt: Unify the 32/64 bit paravirt patching code x86/paravirt: Detect over-sized patching bugs in paravirt_patch_call() x86/paravirt: Detect over-sized patching bugs in paravirt_patch_insns() x86/paravirt: Remove bogus extern declarations
2 parents 3431a94 + 46938cc commit da17702

File tree

11 files changed

+214
-238
lines changed

11 files changed

+214
-238
lines changed

arch/x86/events/intel/ds.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ static int alloc_pebs_buffer(int cpu)
337337
struct debug_store *ds = hwev->ds;
338338
size_t bsiz = x86_pmu.pebs_buffer_size;
339339
int max, node = cpu_to_node(cpu);
340-
void *buffer, *ibuffer, *cea;
340+
void *buffer, *insn_buff, *cea;
341341

342342
if (!x86_pmu.pebs)
343343
return 0;
@@ -351,12 +351,12 @@ static int alloc_pebs_buffer(int cpu)
351351
* buffer then.
352352
*/
353353
if (x86_pmu.intel_cap.pebs_format < 2) {
354-
ibuffer = kzalloc_node(PEBS_FIXUP_SIZE, GFP_KERNEL, node);
355-
if (!ibuffer) {
354+
insn_buff = kzalloc_node(PEBS_FIXUP_SIZE, GFP_KERNEL, node);
355+
if (!insn_buff) {
356356
dsfree_pages(buffer, bsiz);
357357
return -ENOMEM;
358358
}
359-
per_cpu(insn_buffer, cpu) = ibuffer;
359+
per_cpu(insn_buffer, cpu) = insn_buff;
360360
}
361361
hwev->ds_pebs_vaddr = buffer;
362362
/* Update the cpu entry area mapping */

arch/x86/include/asm/paravirt_types.h

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ struct pv_init_ops {
8888
* the number of bytes of code generated, as we nop pad the
8989
* rest in generic code.
9090
*/
91-
unsigned (*patch)(u8 type, void *insnbuf,
91+
unsigned (*patch)(u8 type, void *insn_buff,
9292
unsigned long addr, unsigned len);
9393
} __no_randomize_layout;
9494

@@ -370,18 +370,11 @@ extern struct paravirt_patch_template pv_ops;
370370
/* Simple instruction patching code. */
371371
#define NATIVE_LABEL(a,x,b) "\n\t.globl " a #x "_" #b "\n" a #x "_" #b ":\n\t"
372372

373-
#define DEF_NATIVE(ops, name, code) \
374-
__visible extern const char start_##ops##_##name[], end_##ops##_##name[]; \
375-
asm(NATIVE_LABEL("start_", ops, name) code NATIVE_LABEL("end_", ops, name))
373+
unsigned paravirt_patch_ident_64(void *insn_buff, unsigned len);
374+
unsigned paravirt_patch_default(u8 type, void *insn_buff, unsigned long addr, unsigned len);
375+
unsigned paravirt_patch_insns(void *insn_buff, unsigned len, const char *start, const char *end);
376376

377-
unsigned paravirt_patch_ident_64(void *insnbuf, unsigned len);
378-
unsigned paravirt_patch_default(u8 type, void *insnbuf,
379-
unsigned long addr, unsigned len);
380-
381-
unsigned paravirt_patch_insns(void *insnbuf, unsigned len,
382-
const char *start, const char *end);
383-
384-
unsigned native_patch(u8 type, void *ibuf, unsigned long addr, unsigned len);
377+
unsigned native_patch(u8 type, void *insn_buff, unsigned long addr, unsigned len);
385378

386379
int paravirt_disable_iospace(void);
387380

@@ -679,8 +672,8 @@ u64 _paravirt_ident_64(u64);
679672

680673
/* These all sit in the .parainstructions section to tell us what to patch. */
681674
struct paravirt_patch_site {
682-
u8 *instr; /* original instructions */
683-
u8 instrtype; /* type of this instruction */
675+
u8 *instr; /* original instructions */
676+
u8 type; /* type of this instruction */
684677
u8 len; /* length of original instruction */
685678
};
686679

arch/x86/kernel/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ KASAN_SANITIZE_paravirt.o := n
3030

3131
OBJECT_FILES_NON_STANDARD_relocate_kernel_$(BITS).o := y
3232
OBJECT_FILES_NON_STANDARD_test_nx.o := y
33-
OBJECT_FILES_NON_STANDARD_paravirt_patch_$(BITS).o := y
33+
OBJECT_FILES_NON_STANDARD_paravirt_patch.o := y
3434

3535
ifdef CONFIG_FRAME_POINTER
3636
OBJECT_FILES_NON_STANDARD_ftrace_$(BITS).o := y
@@ -112,7 +112,7 @@ obj-$(CONFIG_AMD_NB) += amd_nb.o
112112
obj-$(CONFIG_DEBUG_NMI_SELFTEST) += nmi_selftest.o
113113

114114
obj-$(CONFIG_KVM_GUEST) += kvm.o kvmclock.o
115-
obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch_$(BITS).o
115+
obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch.o
116116
obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= paravirt-spinlocks.o
117117
obj-$(CONFIG_PARAVIRT_CLOCK) += pvclock.o
118118
obj-$(CONFIG_X86_PMEM_LEGACY_DEVICE) += pmem.o

arch/x86/kernel/alternative.c

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ static inline bool is_jmp(const u8 opcode)
278278
}
279279

280280
static void __init_or_module
281-
recompute_jump(struct alt_instr *a, u8 *orig_insn, u8 *repl_insn, u8 *insnbuf)
281+
recompute_jump(struct alt_instr *a, u8 *orig_insn, u8 *repl_insn, u8 *insn_buff)
282282
{
283283
u8 *next_rip, *tgt_rip;
284284
s32 n_dspl, o_dspl;
@@ -287,7 +287,7 @@ recompute_jump(struct alt_instr *a, u8 *orig_insn, u8 *repl_insn, u8 *insnbuf)
287287
if (a->replacementlen != 5)
288288
return;
289289

290-
o_dspl = *(s32 *)(insnbuf + 1);
290+
o_dspl = *(s32 *)(insn_buff + 1);
291291

292292
/* next_rip of the replacement JMP */
293293
next_rip = repl_insn + a->replacementlen;
@@ -313,18 +313,18 @@ recompute_jump(struct alt_instr *a, u8 *orig_insn, u8 *repl_insn, u8 *insnbuf)
313313
two_byte_jmp:
314314
n_dspl -= 2;
315315

316-
insnbuf[0] = 0xeb;
317-
insnbuf[1] = (s8)n_dspl;
318-
add_nops(insnbuf + 2, 3);
316+
insn_buff[0] = 0xeb;
317+
insn_buff[1] = (s8)n_dspl;
318+
add_nops(insn_buff + 2, 3);
319319

320320
repl_len = 2;
321321
goto done;
322322

323323
five_byte_jmp:
324324
n_dspl -= 5;
325325

326-
insnbuf[0] = 0xe9;
327-
*(s32 *)&insnbuf[1] = n_dspl;
326+
insn_buff[0] = 0xe9;
327+
*(s32 *)&insn_buff[1] = n_dspl;
328328

329329
repl_len = 5;
330330

@@ -371,7 +371,7 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
371371
{
372372
struct alt_instr *a;
373373
u8 *instr, *replacement;
374-
u8 insnbuf[MAX_PATCH_LEN];
374+
u8 insn_buff[MAX_PATCH_LEN];
375375

376376
DPRINTK("alt table %px, -> %px", start, end);
377377
/*
@@ -384,11 +384,11 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
384384
* order.
385385
*/
386386
for (a = start; a < end; a++) {
387-
int insnbuf_sz = 0;
387+
int insn_buff_sz = 0;
388388

389389
instr = (u8 *)&a->instr_offset + a->instr_offset;
390390
replacement = (u8 *)&a->repl_offset + a->repl_offset;
391-
BUG_ON(a->instrlen > sizeof(insnbuf));
391+
BUG_ON(a->instrlen > sizeof(insn_buff));
392392
BUG_ON(a->cpuid >= (NCAPINTS + NBUGINTS) * 32);
393393
if (!boot_cpu_has(a->cpuid)) {
394394
if (a->padlen > 1)
@@ -406,33 +406,33 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start,
406406
DUMP_BYTES(instr, a->instrlen, "%px: old_insn: ", instr);
407407
DUMP_BYTES(replacement, a->replacementlen, "%px: rpl_insn: ", replacement);
408408

409-
memcpy(insnbuf, replacement, a->replacementlen);
410-
insnbuf_sz = a->replacementlen;
409+
memcpy(insn_buff, replacement, a->replacementlen);
410+
insn_buff_sz = a->replacementlen;
411411

412412
/*
413413
* 0xe8 is a relative jump; fix the offset.
414414
*
415415
* Instruction length is checked before the opcode to avoid
416416
* accessing uninitialized bytes for zero-length replacements.
417417
*/
418-
if (a->replacementlen == 5 && *insnbuf == 0xe8) {
419-
*(s32 *)(insnbuf + 1) += replacement - instr;
418+
if (a->replacementlen == 5 && *insn_buff == 0xe8) {
419+
*(s32 *)(insn_buff + 1) += replacement - instr;
420420
DPRINTK("Fix CALL offset: 0x%x, CALL 0x%lx",
421-
*(s32 *)(insnbuf + 1),
422-
(unsigned long)instr + *(s32 *)(insnbuf + 1) + 5);
421+
*(s32 *)(insn_buff + 1),
422+
(unsigned long)instr + *(s32 *)(insn_buff + 1) + 5);
423423
}
424424

425425
if (a->replacementlen && is_jmp(replacement[0]))
426-
recompute_jump(a, instr, replacement, insnbuf);
426+
recompute_jump(a, instr, replacement, insn_buff);
427427

428428
if (a->instrlen > a->replacementlen) {
429-
add_nops(insnbuf + a->replacementlen,
429+
add_nops(insn_buff + a->replacementlen,
430430
a->instrlen - a->replacementlen);
431-
insnbuf_sz += a->instrlen - a->replacementlen;
431+
insn_buff_sz += a->instrlen - a->replacementlen;
432432
}
433-
DUMP_BYTES(insnbuf, insnbuf_sz, "%px: final_insn: ", instr);
433+
DUMP_BYTES(insn_buff, insn_buff_sz, "%px: final_insn: ", instr);
434434

435-
text_poke_early(instr, insnbuf, insnbuf_sz);
435+
text_poke_early(instr, insn_buff, insn_buff_sz);
436436
}
437437
}
438438

@@ -594,22 +594,21 @@ void __init_or_module apply_paravirt(struct paravirt_patch_site *start,
594594
struct paravirt_patch_site *end)
595595
{
596596
struct paravirt_patch_site *p;
597-
char insnbuf[MAX_PATCH_LEN];
597+
char insn_buff[MAX_PATCH_LEN];
598598

599599
for (p = start; p < end; p++) {
600600
unsigned int used;
601601

602602
BUG_ON(p->len > MAX_PATCH_LEN);
603603
/* prep the buffer with the original instructions */
604-
memcpy(insnbuf, p->instr, p->len);
605-
used = pv_ops.init.patch(p->instrtype, insnbuf,
606-
(unsigned long)p->instr, p->len);
604+
memcpy(insn_buff, p->instr, p->len);
605+
used = pv_ops.init.patch(p->type, insn_buff, (unsigned long)p->instr, p->len);
607606

608607
BUG_ON(used > p->len);
609608

610609
/* Pad the rest with nops */
611-
add_nops(insnbuf + used, p->len - used);
612-
text_poke_early(p->instr, insnbuf, p->len);
610+
add_nops(insn_buff + used, p->len - used);
611+
text_poke_early(p->instr, insn_buff, p->len);
613612
}
614613
}
615614
extern struct paravirt_patch_site __start_parainstructions[],

arch/x86/kernel/kprobes/opt.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op,
422422
void arch_optimize_kprobes(struct list_head *oplist)
423423
{
424424
struct optimized_kprobe *op, *tmp;
425-
u8 insn_buf[RELATIVEJUMP_SIZE];
425+
u8 insn_buff[RELATIVEJUMP_SIZE];
426426

427427
list_for_each_entry_safe(op, tmp, oplist, list) {
428428
s32 rel = (s32)((long)op->optinsn.insn -
@@ -434,10 +434,10 @@ void arch_optimize_kprobes(struct list_head *oplist)
434434
memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE,
435435
RELATIVE_ADDR_SIZE);
436436

437-
insn_buf[0] = RELATIVEJUMP_OPCODE;
438-
*(s32 *)(&insn_buf[1]) = rel;
437+
insn_buff[0] = RELATIVEJUMP_OPCODE;
438+
*(s32 *)(&insn_buff[1]) = rel;
439439

440-
text_poke_bp(op->kp.addr, insn_buf, RELATIVEJUMP_SIZE,
440+
text_poke_bp(op->kp.addr, insn_buff, RELATIVEJUMP_SIZE,
441441
op->optinsn.insn);
442442

443443
list_del_init(&op->list);
@@ -447,12 +447,12 @@ void arch_optimize_kprobes(struct list_head *oplist)
447447
/* Replace a relative jump with a breakpoint (int3). */
448448
void arch_unoptimize_kprobe(struct optimized_kprobe *op)
449449
{
450-
u8 insn_buf[RELATIVEJUMP_SIZE];
450+
u8 insn_buff[RELATIVEJUMP_SIZE];
451451

452452
/* Set int3 to first byte for kprobes */
453-
insn_buf[0] = BREAKPOINT_INSTRUCTION;
454-
memcpy(insn_buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
455-
text_poke_bp(op->kp.addr, insn_buf, RELATIVEJUMP_SIZE,
453+
insn_buff[0] = BREAKPOINT_INSTRUCTION;
454+
memcpy(insn_buff + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
455+
text_poke_bp(op->kp.addr, insn_buff, RELATIVEJUMP_SIZE,
456456
op->optinsn.insn);
457457
}
458458

arch/x86/kernel/paravirt.c

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -58,24 +58,24 @@ struct branch {
5858
u32 delta;
5959
} __attribute__((packed));
6060

61-
static unsigned paravirt_patch_call(void *insnbuf, const void *target,
61+
static unsigned paravirt_patch_call(void *insn_buff, const void *target,
6262
unsigned long addr, unsigned len)
6363
{
64-
struct branch *b = insnbuf;
65-
unsigned long delta = (unsigned long)target - (addr+5);
66-
67-
if (len < 5) {
68-
#ifdef CONFIG_RETPOLINE
69-
WARN_ONCE(1, "Failing to patch indirect CALL in %ps\n", (void *)addr);
70-
#endif
71-
return len; /* call too long for patch site */
64+
const int call_len = 5;
65+
struct branch *b = insn_buff;
66+
unsigned long delta = (unsigned long)target - (addr+call_len);
67+
68+
if (len < call_len) {
69+
pr_warn("paravirt: Failed to patch indirect CALL at %ps\n", (void *)addr);
70+
/* Kernel might not be viable if patching fails, bail out: */
71+
BUG_ON(1);
7272
}
7373

7474
b->opcode = 0xe8; /* call */
7575
b->delta = delta;
76-
BUILD_BUG_ON(sizeof(*b) != 5);
76+
BUILD_BUG_ON(sizeof(*b) != call_len);
7777

78-
return 5;
78+
return call_len;
7979
}
8080

8181
#ifdef CONFIG_PARAVIRT_XXL
@@ -85,10 +85,10 @@ u64 notrace _paravirt_ident_64(u64 x)
8585
return x;
8686
}
8787

88-
static unsigned paravirt_patch_jmp(void *insnbuf, const void *target,
88+
static unsigned paravirt_patch_jmp(void *insn_buff, const void *target,
8989
unsigned long addr, unsigned len)
9090
{
91-
struct branch *b = insnbuf;
91+
struct branch *b = insn_buff;
9292
unsigned long delta = (unsigned long)target - (addr+5);
9393

9494
if (len < 5) {
@@ -113,7 +113,7 @@ void __init native_pv_lock_init(void)
113113
static_branch_disable(&virt_spin_lock_key);
114114
}
115115

116-
unsigned paravirt_patch_default(u8 type, void *insnbuf,
116+
unsigned paravirt_patch_default(u8 type, void *insn_buff,
117117
unsigned long addr, unsigned len)
118118
{
119119
/*
@@ -125,36 +125,36 @@ unsigned paravirt_patch_default(u8 type, void *insnbuf,
125125

126126
if (opfunc == NULL)
127127
/* If there's no function, patch it with a ud2a (BUG) */
128-
ret = paravirt_patch_insns(insnbuf, len, ud2a, ud2a+sizeof(ud2a));
128+
ret = paravirt_patch_insns(insn_buff, len, ud2a, ud2a+sizeof(ud2a));
129129
else if (opfunc == _paravirt_nop)
130130
ret = 0;
131131

132132
#ifdef CONFIG_PARAVIRT_XXL
133133
/* identity functions just return their single argument */
134134
else if (opfunc == _paravirt_ident_64)
135-
ret = paravirt_patch_ident_64(insnbuf, len);
135+
ret = paravirt_patch_ident_64(insn_buff, len);
136136

137137
else if (type == PARAVIRT_PATCH(cpu.iret) ||
138138
type == PARAVIRT_PATCH(cpu.usergs_sysret64))
139139
/* If operation requires a jmp, then jmp */
140-
ret = paravirt_patch_jmp(insnbuf, opfunc, addr, len);
140+
ret = paravirt_patch_jmp(insn_buff, opfunc, addr, len);
141141
#endif
142142
else
143143
/* Otherwise call the function. */
144-
ret = paravirt_patch_call(insnbuf, opfunc, addr, len);
144+
ret = paravirt_patch_call(insn_buff, opfunc, addr, len);
145145

146146
return ret;
147147
}
148148

149-
unsigned paravirt_patch_insns(void *insnbuf, unsigned len,
149+
unsigned paravirt_patch_insns(void *insn_buff, unsigned len,
150150
const char *start, const char *end)
151151
{
152152
unsigned insn_len = end - start;
153153

154-
if (insn_len > len || start == NULL)
155-
insn_len = len;
156-
else
157-
memcpy(insnbuf, start, insn_len);
154+
/* Alternative instruction is too large for the patch site and we cannot continue: */
155+
BUG_ON(insn_len > len || start == NULL);
156+
157+
memcpy(insn_buff, start, insn_len);
158158

159159
return insn_len;
160160
}

0 commit comments

Comments
 (0)