1c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches#define pr_fmt(fmt) "SMP alternatives: " fmt
2c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches
39a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann#include <linux/module.h>
4f6a570333e554b48ad589e7137c77c57809eee81Al Viro#include <linux/sched.h>
52f1dafe50cc4e58a239fd81bd47f87f32042a1eePekka Paalanen#include <linux/mutex.h>
69a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann#include <linux/list.h>
78b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulich#include <linux/stringify.h>
819d36ccdc34f5ed444f8a6af0cbfdb6790eb1177Andi Kleen#include <linux/mm.h>
919d36ccdc34f5ed444f8a6af0cbfdb6790eb1177Andi Kleen#include <linux/vmalloc.h>
103945dab45aa8c89014893bfa8eb1e1661a409cefMasami Hiramatsu#include <linux/memory.h>
113d55cc8a058ee96291d6d45b1e35121b9920eca3Masami Hiramatsu#include <linux/stop_machine.h>
125a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
13fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina#include <linux/kdebug.h>
149a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann#include <asm/alternative.h>
159a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann#include <asm/sections.h>
1619d36ccdc34f5ed444f8a6af0cbfdb6790eb1177Andi Kleen#include <asm/pgtable.h>
178f4e956b313dcccbc7be6f10808952345e3b638cAndi Kleen#include <asm/mce.h>
188f4e956b313dcccbc7be6f10808952345e3b638cAndi Kleen#include <asm/nmi.h>
19e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers#include <asm/cacheflush.h>
2078ff7fae04554b49d29226ed12536268c2500d1fMasami Hiramatsu#include <asm/tlbflush.h>
21e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers#include <asm/io.h>
2278ff7fae04554b49d29226ed12536268c2500d1fMasami Hiramatsu#include <asm/fixmap.h>
239a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
24ab144f5ec64c42218a555ec1dbde6b60cf2982d6Andi Kleen#define MAX_PATCH_LEN (255-1)
25ab144f5ec64c42218a555ec1dbde6b60cf2982d6Andi Kleen
268b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulichstatic int __initdata_or_module debug_alternative;
27b7fb4af06c18496950a45b365f7a09c47ea64c17Jeremy Fitzhardinge
28d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmannstatic int __init debug_alt(char *str)
29d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann{
30d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann	debug_alternative = 1;
31d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann	return 1;
32d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann}
33d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann__setup("debug-alternative", debug_alt);
34d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann
3509488165d5cc795a90b789c5657b1cbd279beb16Jan Beulichstatic int noreplace_smp;
3609488165d5cc795a90b789c5657b1cbd279beb16Jan Beulich
37b7fb4af06c18496950a45b365f7a09c47ea64c17Jeremy Fitzhardingestatic int __init setup_noreplace_smp(char *str)
38b7fb4af06c18496950a45b365f7a09c47ea64c17Jeremy Fitzhardinge{
39b7fb4af06c18496950a45b365f7a09c47ea64c17Jeremy Fitzhardinge	noreplace_smp = 1;
40b7fb4af06c18496950a45b365f7a09c47ea64c17Jeremy Fitzhardinge	return 1;
41b7fb4af06c18496950a45b365f7a09c47ea64c17Jeremy Fitzhardinge}
42b7fb4af06c18496950a45b365f7a09c47ea64c17Jeremy Fitzhardinge__setup("noreplace-smp", setup_noreplace_smp);
43b7fb4af06c18496950a45b365f7a09c47ea64c17Jeremy Fitzhardinge
44959b4fdfe7e27bcf101e2381e500e4076f2bb9ceJeremy Fitzhardinge#ifdef CONFIG_PARAVIRT
458b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulichstatic int __initdata_or_module noreplace_paravirt = 0;
46959b4fdfe7e27bcf101e2381e500e4076f2bb9ceJeremy Fitzhardinge
47959b4fdfe7e27bcf101e2381e500e4076f2bb9ceJeremy Fitzhardingestatic int __init setup_noreplace_paravirt(char *str)
48959b4fdfe7e27bcf101e2381e500e4076f2bb9ceJeremy Fitzhardinge{
49959b4fdfe7e27bcf101e2381e500e4076f2bb9ceJeremy Fitzhardinge	noreplace_paravirt = 1;
50959b4fdfe7e27bcf101e2381e500e4076f2bb9ceJeremy Fitzhardinge	return 1;
51959b4fdfe7e27bcf101e2381e500e4076f2bb9ceJeremy Fitzhardinge}
52959b4fdfe7e27bcf101e2381e500e4076f2bb9ceJeremy Fitzhardinge__setup("noreplace-paravirt", setup_noreplace_paravirt);
53959b4fdfe7e27bcf101e2381e500e4076f2bb9ceJeremy Fitzhardinge#endif
54b7fb4af06c18496950a45b365f7a09c47ea64c17Jeremy Fitzhardinge
55c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches#define DPRINTK(fmt, ...)				\
56c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perchesdo {							\
57c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches	if (debug_alternative)				\
58c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches		printk(KERN_DEBUG fmt, ##__VA_ARGS__);	\
59c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches} while (0)
60d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann
61dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin/*
62dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin * Each GENERIC_NOPX is of X bytes, and defined as an array of bytes
63dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin * that correspond to that nop. Getting from one nop to the next, we
64dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin * add to the array the offset that is equal to the sum of all sizes of
65dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin * nops preceding the one we are after.
66dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin *
67dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin * Note: The GENERIC_NOP5_ATOMIC is at the end, as it breaks the
68dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin * nice symmetry of sizes of the previous nops.
69dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin */
708b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulich#if defined(GENERIC_NOP1) && !defined(CONFIG_X86_64)
71dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvinstatic const unsigned char intelnops[] =
72dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin{
73dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	GENERIC_NOP1,
74dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	GENERIC_NOP2,
75dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	GENERIC_NOP3,
76dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	GENERIC_NOP4,
77dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	GENERIC_NOP5,
78dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	GENERIC_NOP6,
79dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	GENERIC_NOP7,
80dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	GENERIC_NOP8,
81dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	GENERIC_NOP5_ATOMIC
82dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin};
83dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvinstatic const unsigned char * const intel_nops[ASM_NOP_MAX+2] =
84dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin{
859a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	NULL,
869a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	intelnops,
879a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	intelnops + 1,
889a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	intelnops + 1 + 2,
899a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	intelnops + 1 + 2 + 3,
909a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	intelnops + 1 + 2 + 3 + 4,
919a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	intelnops + 1 + 2 + 3 + 4 + 5,
929a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	intelnops + 1 + 2 + 3 + 4 + 5 + 6,
939a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
94dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
959a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann};
96d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann#endif
97d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann
98d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann#ifdef K8_NOP1
99dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvinstatic const unsigned char k8nops[] =
100dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin{
101dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K8_NOP1,
102dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K8_NOP2,
103dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K8_NOP3,
104dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K8_NOP4,
105dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K8_NOP5,
106dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K8_NOP6,
107dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K8_NOP7,
108dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K8_NOP8,
109dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K8_NOP5_ATOMIC
110dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin};
111dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvinstatic const unsigned char * const k8_nops[ASM_NOP_MAX+2] =
112dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin{
1139a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	NULL,
1149a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k8nops,
1159a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k8nops + 1,
1169a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k8nops + 1 + 2,
1179a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k8nops + 1 + 2 + 3,
1189a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k8nops + 1 + 2 + 3 + 4,
1199a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k8nops + 1 + 2 + 3 + 4 + 5,
1209a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k8nops + 1 + 2 + 3 + 4 + 5 + 6,
1219a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
122dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
1239a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann};
124d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann#endif
125d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann
1268b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulich#if defined(K7_NOP1) && !defined(CONFIG_X86_64)
127dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvinstatic const unsigned char k7nops[] =
128dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin{
129dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K7_NOP1,
130dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K7_NOP2,
131dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K7_NOP3,
132dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K7_NOP4,
133dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K7_NOP5,
134dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K7_NOP6,
135dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K7_NOP7,
136dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K7_NOP8,
137dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	K7_NOP5_ATOMIC
138dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin};
139dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvinstatic const unsigned char * const k7_nops[ASM_NOP_MAX+2] =
140dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin{
1419a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	NULL,
1429a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k7nops,
1439a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k7nops + 1,
1449a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k7nops + 1 + 2,
1459a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k7nops + 1 + 2 + 3,
1469a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k7nops + 1 + 2 + 3 + 4,
1479a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k7nops + 1 + 2 + 3 + 4 + 5,
1489a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k7nops + 1 + 2 + 3 + 4 + 5 + 6,
1499a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
150dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
1519a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann};
152d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann#endif
153d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann
15432c464f5d9701db45bc1673288594e664065388eJan Beulich#ifdef P6_NOP1
155cb09cad44f07044d9810f18f6f9a6a6f3771f979Avi Kivitystatic const unsigned char p6nops[] =
156dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin{
157dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	P6_NOP1,
158dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	P6_NOP2,
159dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	P6_NOP3,
160dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	P6_NOP4,
161dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	P6_NOP5,
162dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	P6_NOP6,
163dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	P6_NOP7,
164dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	P6_NOP8,
165dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	P6_NOP5_ATOMIC
166dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin};
167dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvinstatic const unsigned char * const p6_nops[ASM_NOP_MAX+2] =
168dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin{
16932c464f5d9701db45bc1673288594e664065388eJan Beulich	NULL,
17032c464f5d9701db45bc1673288594e664065388eJan Beulich	p6nops,
17132c464f5d9701db45bc1673288594e664065388eJan Beulich	p6nops + 1,
17232c464f5d9701db45bc1673288594e664065388eJan Beulich	p6nops + 1 + 2,
17332c464f5d9701db45bc1673288594e664065388eJan Beulich	p6nops + 1 + 2 + 3,
17432c464f5d9701db45bc1673288594e664065388eJan Beulich	p6nops + 1 + 2 + 3 + 4,
17532c464f5d9701db45bc1673288594e664065388eJan Beulich	p6nops + 1 + 2 + 3 + 4 + 5,
17632c464f5d9701db45bc1673288594e664065388eJan Beulich	p6nops + 1 + 2 + 3 + 4 + 5 + 6,
17732c464f5d9701db45bc1673288594e664065388eJan Beulich	p6nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
178dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	p6nops + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8,
17932c464f5d9701db45bc1673288594e664065388eJan Beulich};
18032c464f5d9701db45bc1673288594e664065388eJan Beulich#endif
18132c464f5d9701db45bc1673288594e664065388eJan Beulich
182dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin/* Initialize these to a safe default */
183d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann#ifdef CONFIG_X86_64
184dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvinconst unsigned char * const *ideal_nops = p6_nops;
185dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin#else
186dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvinconst unsigned char * const *ideal_nops = intel_nops;
187dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin#endif
188d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann
189dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvinvoid __init arch_init_ideal_nops(void)
190d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann{
191dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	switch (boot_cpu_data.x86_vendor) {
192dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	case X86_VENDOR_INTEL:
193d8d9766c8c29f71c37bc4b74cc9fcf6a192c9bfdH. Peter Anvin		/*
194d8d9766c8c29f71c37bc4b74cc9fcf6a192c9bfdH. Peter Anvin		 * Due to a decoder implementation quirk, some
195d8d9766c8c29f71c37bc4b74cc9fcf6a192c9bfdH. Peter Anvin		 * specific Intel CPUs actually perform better with
196d8d9766c8c29f71c37bc4b74cc9fcf6a192c9bfdH. Peter Anvin		 * the "k8_nops" than with the SDM-recommended NOPs.
197d8d9766c8c29f71c37bc4b74cc9fcf6a192c9bfdH. Peter Anvin		 */
198d8d9766c8c29f71c37bc4b74cc9fcf6a192c9bfdH. Peter Anvin		if (boot_cpu_data.x86 == 6 &&
199d8d9766c8c29f71c37bc4b74cc9fcf6a192c9bfdH. Peter Anvin		    boot_cpu_data.x86_model >= 0x0f &&
200d8d9766c8c29f71c37bc4b74cc9fcf6a192c9bfdH. Peter Anvin		    boot_cpu_data.x86_model != 0x1c &&
201d8d9766c8c29f71c37bc4b74cc9fcf6a192c9bfdH. Peter Anvin		    boot_cpu_data.x86_model != 0x26 &&
202d8d9766c8c29f71c37bc4b74cc9fcf6a192c9bfdH. Peter Anvin		    boot_cpu_data.x86_model != 0x27 &&
203d8d9766c8c29f71c37bc4b74cc9fcf6a192c9bfdH. Peter Anvin		    boot_cpu_data.x86_model < 0x30) {
204d8d9766c8c29f71c37bc4b74cc9fcf6a192c9bfdH. Peter Anvin			ideal_nops = k8_nops;
205d8d9766c8c29f71c37bc4b74cc9fcf6a192c9bfdH. Peter Anvin		} else if (boot_cpu_has(X86_FEATURE_NOPL)) {
206dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin			   ideal_nops = p6_nops;
207dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin		} else {
208dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin#ifdef CONFIG_X86_64
209dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin			ideal_nops = k8_nops;
210dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin#else
211dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin			ideal_nops = intel_nops;
212dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin#endif
213dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin		}
214d6250a3f12edb3a86db9598ffeca3de8b4a219e9Alan Cox		break;
215dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	default:
216dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin#ifdef CONFIG_X86_64
217dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin		ideal_nops = k8_nops;
218dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin#else
219dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin		if (boot_cpu_has(X86_FEATURE_K8))
220dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin			ideal_nops = k8_nops;
221dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin		else if (boot_cpu_has(X86_FEATURE_K7))
222dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin			ideal_nops = k7_nops;
223dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin		else
224dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin			ideal_nops = intel_nops;
225dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin#endif
226dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin	}
2279a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann}
2289a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
229ab144f5ec64c42218a555ec1dbde6b60cf2982d6Andi Kleen/* Use this to add nops to a buffer, then text_poke the whole buffer. */
2308b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulichstatic void __init_or_module add_nops(void *insns, unsigned int len)
231139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell{
232139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell	while (len > 0) {
233139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell		unsigned int noplen = len;
234139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell		if (noplen > ASM_NOP_MAX)
235139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell			noplen = ASM_NOP_MAX;
236dc326fca2b640fc41aed7c015d0f456935a66255H. Peter Anvin		memcpy(insns, ideal_nops[noplen], noplen);
237139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell		insns += noplen;
238139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell		len -= noplen;
239139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell	}
240139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell}
241139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell
242d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmannextern struct alt_instr __alt_instructions[], __alt_instructions_end[];
2435967ed87ade85a421ef814296c3c7f182b08c225Jan Beulichextern s32 __smp_locks[], __smp_locks_end[];
244fa6f2cc77081792e4edca9168420a3422299ef15Jason Baronvoid *text_poke_early(void *addr, const void *opcode, size_t len);
245d167a51877e94dda73dd656c51f363502309f713Gerd Hoffmann
2469a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann/* Replace instructions with better alternatives for this CPU type.
2479a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann   This runs before SMP is initialized to avoid SMP problems with
2480d2eb44f631d9d0a826efa3156f157477fdaecf4Lucas De Marchi   self modifying code. This implies that asymmetric systems where
2499a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann   APs have less capabilities than the boot processor are not handled.
2509a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann   Tough. Make sure you disable such features by hand. */
2519a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
2528b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulichvoid __init_or_module apply_alternatives(struct alt_instr *start,
2538b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulich					 struct alt_instr *end)
2549a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann{
2559a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	struct alt_instr *a;
25659e97e4d6fbcd5b74a94cb48bcbfc6f8478a5e93Andy Lutomirski	u8 *instr, *replacement;
2571b1d9258181bae199dc940f4bd0298126b9a73d9Jan Beulich	u8 insnbuf[MAX_PATCH_LEN];
2589a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
25977bf90ed66116a1fc0e2f0554ecac75a54290cc0Harvey Harrison	DPRINTK("%s: alt table %p -> %p\n", __func__, start, end);
260509731336313b3799cf03071d72c64fa6383895eFenghua Yu	/*
261509731336313b3799cf03071d72c64fa6383895eFenghua Yu	 * The scan order should be from start to end. A later scanned
262509731336313b3799cf03071d72c64fa6383895eFenghua Yu	 * alternative code can overwrite a previous scanned alternative code.
263509731336313b3799cf03071d72c64fa6383895eFenghua Yu	 * Some kernel functions (e.g. memcpy, memset, etc) use this order to
264509731336313b3799cf03071d72c64fa6383895eFenghua Yu	 * patch code.
265509731336313b3799cf03071d72c64fa6383895eFenghua Yu	 *
266509731336313b3799cf03071d72c64fa6383895eFenghua Yu	 * So be careful if you want to change the scan order to any other
267509731336313b3799cf03071d72c64fa6383895eFenghua Yu	 * order.
268509731336313b3799cf03071d72c64fa6383895eFenghua Yu	 */
2699a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	for (a = start; a < end; a++) {
27059e97e4d6fbcd5b74a94cb48bcbfc6f8478a5e93Andy Lutomirski		instr = (u8 *)&a->instr_offset + a->instr_offset;
27159e97e4d6fbcd5b74a94cb48bcbfc6f8478a5e93Andy Lutomirski		replacement = (u8 *)&a->repl_offset + a->repl_offset;
2729a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann		BUG_ON(a->replacementlen > a->instrlen);
273ab144f5ec64c42218a555ec1dbde6b60cf2982d6Andi Kleen		BUG_ON(a->instrlen > sizeof(insnbuf));
27465fc985b37dc241c4db7cd32adcbc989193fe3c8Borislav Petkov		BUG_ON(a->cpuid >= (NCAPINTS + NBUGINTS) * 32);
2759a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann		if (!boot_cpu_has(a->cpuid))
2769a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann			continue;
27759e97e4d6fbcd5b74a94cb48bcbfc6f8478a5e93Andy Lutomirski
27859e97e4d6fbcd5b74a94cb48bcbfc6f8478a5e93Andy Lutomirski		memcpy(insnbuf, replacement, a->replacementlen);
27959e97e4d6fbcd5b74a94cb48bcbfc6f8478a5e93Andy Lutomirski
28059e97e4d6fbcd5b74a94cb48bcbfc6f8478a5e93Andy Lutomirski		/* 0xe8 is a relative jump; fix the offset. */
28159e97e4d6fbcd5b74a94cb48bcbfc6f8478a5e93Andy Lutomirski		if (*insnbuf == 0xe8 && a->replacementlen == 5)
28259e97e4d6fbcd5b74a94cb48bcbfc6f8478a5e93Andy Lutomirski		    *(s32 *)(insnbuf + 1) += replacement - instr;
28359e97e4d6fbcd5b74a94cb48bcbfc6f8478a5e93Andy Lutomirski
28459e97e4d6fbcd5b74a94cb48bcbfc6f8478a5e93Andy Lutomirski		add_nops(insnbuf + a->replacementlen,
28559e97e4d6fbcd5b74a94cb48bcbfc6f8478a5e93Andy Lutomirski			 a->instrlen - a->replacementlen);
28659e97e4d6fbcd5b74a94cb48bcbfc6f8478a5e93Andy Lutomirski
287e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers		text_poke_early(instr, insnbuf, a->instrlen);
2889a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	}
2899a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann}
2909a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
2918ec4d41f88872e6a5980558e362c0174dce54e40Gerd Hoffmann#ifdef CONFIG_SMP
2928ec4d41f88872e6a5980558e362c0174dce54e40Gerd Hoffmann
2935967ed87ade85a421ef814296c3c7f182b08c225Jan Beulichstatic void alternatives_smp_lock(const s32 *start, const s32 *end,
2945967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich				  u8 *text, u8 *text_end)
2959a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann{
2965967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich	const s32 *poff;
2979a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
2983945dab45aa8c89014893bfa8eb1e1661a409cefMasami Hiramatsu	mutex_lock(&text_mutex);
2995967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich	for (poff = start; poff < end; poff++) {
3005967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich		u8 *ptr = (u8 *)poff + *poff;
3015967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich
3025967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich		if (!*poff || ptr < text || ptr >= text_end)
3039a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann			continue;
304f88f07e0f0fd6376e081b10930d272a08fbf082fMathieu Desnoyers		/* turn DS segment override prefix into lock prefix */
305d9c5841e22231e4e49fd0a1004164e6fce59b7a6H. Peter Anvin		if (*ptr == 0x3e)
306d9c5841e22231e4e49fd0a1004164e6fce59b7a6H. Peter Anvin			text_poke(ptr, ((unsigned char []){0xf0}), 1);
3074b8073e467e6a66b6a5a8e799d28bc3b243c0d78Peter Senna Tschudin	}
3083945dab45aa8c89014893bfa8eb1e1661a409cefMasami Hiramatsu	mutex_unlock(&text_mutex);
3099a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann}
3109a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
3115967ed87ade85a421ef814296c3c7f182b08c225Jan Beulichstatic void alternatives_smp_unlock(const s32 *start, const s32 *end,
3125967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich				    u8 *text, u8 *text_end)
3139a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann{
3145967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich	const s32 *poff;
3159a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
3163945dab45aa8c89014893bfa8eb1e1661a409cefMasami Hiramatsu	mutex_lock(&text_mutex);
3175967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich	for (poff = start; poff < end; poff++) {
3185967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich		u8 *ptr = (u8 *)poff + *poff;
3195967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich
3205967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich		if (!*poff || ptr < text || ptr >= text_end)
3219a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann			continue;
322f88f07e0f0fd6376e081b10930d272a08fbf082fMathieu Desnoyers		/* turn lock prefix into DS segment override prefix */
323d9c5841e22231e4e49fd0a1004164e6fce59b7a6H. Peter Anvin		if (*ptr == 0xf0)
324d9c5841e22231e4e49fd0a1004164e6fce59b7a6H. Peter Anvin			text_poke(ptr, ((unsigned char []){0x3E}), 1);
3254b8073e467e6a66b6a5a8e799d28bc3b243c0d78Peter Senna Tschudin	}
3263945dab45aa8c89014893bfa8eb1e1661a409cefMasami Hiramatsu	mutex_unlock(&text_mutex);
3279a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann}
3289a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
3299a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmannstruct smp_alt_module {
3309a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	/* what is this ??? */
3319a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	struct module	*mod;
3329a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	char		*name;
3339a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
3349a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	/* ptrs to lock prefixes */
3355967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich	const s32	*locks;
3365967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich	const s32	*locks_end;
3379a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
3389a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	/* .text segment, needed to avoid patching init code ;) */
3399a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	u8		*text;
3409a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	u8		*text_end;
3419a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
3429a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	struct list_head next;
3439a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann};
3449a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmannstatic LIST_HEAD(smp_alt_modules);
3452f1dafe50cc4e58a239fd81bd47f87f32042a1eePekka Paalanenstatic DEFINE_MUTEX(smp_alt);
346816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russellstatic bool uniproc_patched = false;	/* protected by smp_alt */
3479a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
3488b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulichvoid __init_or_module alternatives_smp_module_add(struct module *mod,
3498b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulich						  char *name,
3508b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulich						  void *locks, void *locks_end,
3518b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulich						  void *text,  void *text_end)
3529a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann{
3539a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	struct smp_alt_module *smp;
3549a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
355816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell	mutex_lock(&smp_alt);
356816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell	if (!uniproc_patched)
357816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell		goto unlock;
358b7fb4af06c18496950a45b365f7a09c47ea64c17Jeremy Fitzhardinge
359816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell	if (num_possible_cpus() == 1)
360816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell		/* Don't bother remembering, we'll never have to undo it. */
361816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell		goto smp_unlock;
3629a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
3639a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	smp = kzalloc(sizeof(*smp), GFP_KERNEL);
3649a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	if (NULL == smp)
365816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell		/* we'll run the (safe but slow) SMP code then ... */
366816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell		goto unlock;
3679a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
3689a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	smp->mod	= mod;
3699a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	smp->name	= name;
3709a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	smp->locks	= locks;
3719a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	smp->locks_end	= locks_end;
3729a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	smp->text	= text;
3739a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	smp->text_end	= text_end;
3749a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	DPRINTK("%s: locks %p -> %p, text %p -> %p, name %s\n",
37577bf90ed66116a1fc0e2f0554ecac75a54290cc0Harvey Harrison		__func__, smp->locks, smp->locks_end,
3769a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann		smp->text, smp->text_end, smp->name);
3779a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
3789a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	list_add_tail(&smp->next, &smp_alt_modules);
379816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russellsmp_unlock:
380816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell	alternatives_smp_unlock(locks, locks_end, text, text_end);
381816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russellunlock:
3822f1dafe50cc4e58a239fd81bd47f87f32042a1eePekka Paalanen	mutex_unlock(&smp_alt);
3839a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann}
3849a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
3858b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulichvoid __init_or_module alternatives_smp_module_del(struct module *mod)
3869a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann{
3879a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	struct smp_alt_module *item;
3889a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
3892f1dafe50cc4e58a239fd81bd47f87f32042a1eePekka Paalanen	mutex_lock(&smp_alt);
3909a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	list_for_each_entry(item, &smp_alt_modules, next) {
3919a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann		if (mod != item->mod)
3929a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann			continue;
3939a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann		list_del(&item->next);
3949a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann		kfree(item);
395816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell		break;
3969a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	}
3972f1dafe50cc4e58a239fd81bd47f87f32042a1eePekka Paalanen	mutex_unlock(&smp_alt);
3989a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann}
3999a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
400816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russellvoid alternatives_enable_smp(void)
4019a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann{
4029a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	struct smp_alt_module *mod;
4039a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
404816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell	/* Why bother if there are no other CPUs? */
405816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell	BUG_ON(num_possible_cpus() == 1);
4069a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
4072f1dafe50cc4e58a239fd81bd47f87f32042a1eePekka Paalanen	mutex_lock(&smp_alt);
408ca74a6f84e68b44867022f4a4f3ec17c087c864eAndi Kleen
409816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell	if (uniproc_patched) {
410c767a54ba0657e52e6edaa97cbe0b0a8bf1c1655Joe Perches		pr_info("switching to SMP code\n");
411816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell		BUG_ON(num_online_cpus() != 1);
41253756d3722172815f52272b28c6d5d5e9639addeJeremy Fitzhardinge		clear_cpu_cap(&boot_cpu_data, X86_FEATURE_UP);
41353756d3722172815f52272b28c6d5d5e9639addeJeremy Fitzhardinge		clear_cpu_cap(&cpu_data(0), X86_FEATURE_UP);
4149a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann		list_for_each_entry(mod, &smp_alt_modules, next)
4159a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann			alternatives_smp_lock(mod->locks, mod->locks_end,
4169a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann					      mod->text, mod->text_end);
417816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell		uniproc_patched = false;
4189a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	}
4192f1dafe50cc4e58a239fd81bd47f87f32042a1eePekka Paalanen	mutex_unlock(&smp_alt);
4209a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann}
4219a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
4222cfa19780d61740f65790c5bae363b759d7c96faMasami Hiramatsu/* Return 1 if the address range is reserved for smp-alternatives */
4232cfa19780d61740f65790c5bae363b759d7c96faMasami Hiramatsuint alternatives_text_reserved(void *start, void *end)
4242cfa19780d61740f65790c5bae363b759d7c96faMasami Hiramatsu{
4252cfa19780d61740f65790c5bae363b759d7c96faMasami Hiramatsu	struct smp_alt_module *mod;
4265967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich	const s32 *poff;
427076dc4a65a6d99a16979e2c7917e669fb8c91ee5Masami Hiramatsu	u8 *text_start = start;
428076dc4a65a6d99a16979e2c7917e669fb8c91ee5Masami Hiramatsu	u8 *text_end = end;
4292cfa19780d61740f65790c5bae363b759d7c96faMasami Hiramatsu
4302cfa19780d61740f65790c5bae363b759d7c96faMasami Hiramatsu	list_for_each_entry(mod, &smp_alt_modules, next) {
431076dc4a65a6d99a16979e2c7917e669fb8c91ee5Masami Hiramatsu		if (mod->text > text_end || mod->text_end < text_start)
4322cfa19780d61740f65790c5bae363b759d7c96faMasami Hiramatsu			continue;
4335967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich		for (poff = mod->locks; poff < mod->locks_end; poff++) {
4345967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich			const u8 *ptr = (const u8 *)poff + *poff;
4355967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich
4365967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich			if (text_start <= ptr && text_end > ptr)
4372cfa19780d61740f65790c5bae363b759d7c96faMasami Hiramatsu				return 1;
4385967ed87ade85a421ef814296c3c7f182b08c225Jan Beulich		}
4392cfa19780d61740f65790c5bae363b759d7c96faMasami Hiramatsu	}
4402cfa19780d61740f65790c5bae363b759d7c96faMasami Hiramatsu
4412cfa19780d61740f65790c5bae363b759d7c96faMasami Hiramatsu	return 0;
4422cfa19780d61740f65790c5bae363b759d7c96faMasami Hiramatsu}
4438ec4d41f88872e6a5980558e362c0174dce54e40Gerd Hoffmann#endif
4448ec4d41f88872e6a5980558e362c0174dce54e40Gerd Hoffmann
445139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell#ifdef CONFIG_PARAVIRT
4468b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulichvoid __init_or_module apply_paravirt(struct paravirt_patch_site *start,
4478b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulich				     struct paravirt_patch_site *end)
448139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell{
44998de032b681d8a7532d44dfc66aa5c0c1c755a9dJeremy Fitzhardinge	struct paravirt_patch_site *p;
450ab144f5ec64c42218a555ec1dbde6b60cf2982d6Andi Kleen	char insnbuf[MAX_PATCH_LEN];
451139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell
452959b4fdfe7e27bcf101e2381e500e4076f2bb9ceJeremy Fitzhardinge	if (noreplace_paravirt)
453959b4fdfe7e27bcf101e2381e500e4076f2bb9ceJeremy Fitzhardinge		return;
454959b4fdfe7e27bcf101e2381e500e4076f2bb9ceJeremy Fitzhardinge
455139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell	for (p = start; p < end; p++) {
456139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell		unsigned int used;
457139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell
458ab144f5ec64c42218a555ec1dbde6b60cf2982d6Andi Kleen		BUG_ON(p->len > MAX_PATCH_LEN);
459d34fda4a84c18402640a1a2342d6e6d9829e6db7Chris Wright		/* prep the buffer with the original instructions */
460d34fda4a84c18402640a1a2342d6e6d9829e6db7Chris Wright		memcpy(insnbuf, p->instr, p->len);
46193b1eab3d29e7ea32ee583de3362da84db06ded8Jeremy Fitzhardinge		used = pv_init_ops.patch(p->instrtype, p->clobbers, insnbuf,
46293b1eab3d29e7ea32ee583de3362da84db06ded8Jeremy Fitzhardinge					 (unsigned long)p->instr, p->len);
4637f63c41c6c57371a0931da3940c6620c2301442cJeremy Fitzhardinge
46463f70270ccd981ce40a8ff58c03a8c2e97e368beJeremy Fitzhardinge		BUG_ON(used > p->len);
46563f70270ccd981ce40a8ff58c03a8c2e97e368beJeremy Fitzhardinge
466139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell		/* Pad the rest with nops */
467ab144f5ec64c42218a555ec1dbde6b60cf2982d6Andi Kleen		add_nops(insnbuf + used, p->len - used);
468e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers		text_poke_early(p->instr, insnbuf, p->len);
469139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell	}
470139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell}
47198de032b681d8a7532d44dfc66aa5c0c1c755a9dJeremy Fitzhardingeextern struct paravirt_patch_site __start_parainstructions[],
472139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell	__stop_parainstructions[];
473139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell#endif	/* CONFIG_PARAVIRT */
474139ec7c416248b9ea227d21839235344edfee1e0Rusty Russell
4759a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmannvoid __init alternative_instructions(void)
4769a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann{
4778f4e956b313dcccbc7be6f10808952345e3b638cAndi Kleen	/* The patching is not fully atomic, so try to avoid local interruptions
4788f4e956b313dcccbc7be6f10808952345e3b638cAndi Kleen	   that might execute the to be patched code.
4798f4e956b313dcccbc7be6f10808952345e3b638cAndi Kleen	   Other CPUs are not running. */
4808f4e956b313dcccbc7be6f10808952345e3b638cAndi Kleen	stop_nmi();
481123aa76ec0cab5d4881cd8509faed43231e68801Andi Kleen
482123aa76ec0cab5d4881cd8509faed43231e68801Andi Kleen	/*
483123aa76ec0cab5d4881cd8509faed43231e68801Andi Kleen	 * Don't stop machine check exceptions while patching.
484123aa76ec0cab5d4881cd8509faed43231e68801Andi Kleen	 * MCEs only happen when something got corrupted and in this
485123aa76ec0cab5d4881cd8509faed43231e68801Andi Kleen	 * case we must do something about the corruption.
486123aa76ec0cab5d4881cd8509faed43231e68801Andi Kleen	 * Ignoring it is worse than a unlikely patching race.
487123aa76ec0cab5d4881cd8509faed43231e68801Andi Kleen	 * Also machine checks tend to be broadcast and if one CPU
488123aa76ec0cab5d4881cd8509faed43231e68801Andi Kleen	 * goes into machine check the others follow quickly, so we don't
489123aa76ec0cab5d4881cd8509faed43231e68801Andi Kleen	 * expect a machine check to cause undue problems during to code
490123aa76ec0cab5d4881cd8509faed43231e68801Andi Kleen	 * patching.
491123aa76ec0cab5d4881cd8509faed43231e68801Andi Kleen	 */
4928f4e956b313dcccbc7be6f10808952345e3b638cAndi Kleen
4939a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	apply_alternatives(__alt_instructions, __alt_instructions_end);
4949a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann
4958ec4d41f88872e6a5980558e362c0174dce54e40Gerd Hoffmann#ifdef CONFIG_SMP
496816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell	/* Patch to UP if other cpus not imminent. */
497816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell	if (!noreplace_smp && (num_present_cpus() == 1 || setup_max_cpus <= 1)) {
498816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell		uniproc_patched = true;
4999a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann		alternatives_smp_module_add(NULL, "core kernel",
5009a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann					    __smp_locks, __smp_locks_end,
5019a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann					    _text, _etext);
5029a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann	}
5038f4e956b313dcccbc7be6f10808952345e3b638cAndi Kleen
504816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell	if (!uniproc_patched || num_possible_cpus() == 1)
505f68fd5f480248ca49e20e30a8e2387bc54694580Fengguang Wu		free_init_pages("SMP alternatives",
506f68fd5f480248ca49e20e30a8e2387bc54694580Fengguang Wu				(unsigned long)__smp_locks,
507f68fd5f480248ca49e20e30a8e2387bc54694580Fengguang Wu				(unsigned long)__smp_locks_end);
508816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell#endif
509816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell
510816afe4ff98ee10b1d30fd66361be132a0a5cee6Rusty Russell	apply_paravirt(__parainstructions, __parainstructions_end);
511f68fd5f480248ca49e20e30a8e2387bc54694580Fengguang Wu
5128f4e956b313dcccbc7be6f10808952345e3b638cAndi Kleen	restart_nmi();
5139a0b5817ad97bb718ab85322759d19a238712b47Gerd Hoffmann}
51419d36ccdc34f5ed444f8a6af0cbfdb6790eb1177Andi Kleen
515e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers/**
516e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * text_poke_early - Update instructions on a live kernel at boot time
517e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * @addr: address to modify
518e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * @opcode: source of the copy
519e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * @len: length to copy
520e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers *
52119d36ccdc34f5ed444f8a6af0cbfdb6790eb1177Andi Kleen * When you use this code to patch more than one byte of an instruction
52219d36ccdc34f5ed444f8a6af0cbfdb6790eb1177Andi Kleen * you need to make sure that other CPUs cannot execute this code in parallel.
523e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * Also no thread must be currently preempted in the middle of these
524e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * instructions. And on the local CPU you need to be protected again NMI or MCE
525e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * handlers seeing an inconsistent instruction while you patch.
52619d36ccdc34f5ed444f8a6af0cbfdb6790eb1177Andi Kleen */
527fa6f2cc77081792e4edca9168420a3422299ef15Jason Baronvoid *__init_or_module text_poke_early(void *addr, const void *opcode,
5288b5a10fc6fd02289ea03480f93382b1a99006142Jan Beulich					      size_t len)
52919d36ccdc34f5ed444f8a6af0cbfdb6790eb1177Andi Kleen{
530e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers	unsigned long flags;
531e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers	local_irq_save(flags);
53219d36ccdc34f5ed444f8a6af0cbfdb6790eb1177Andi Kleen	memcpy(addr, opcode, len);
533e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers	sync_core();
5345367b6887e7d8c870a5da7d9b8c6e9c207684e43Ben Hutchings	local_irq_restore(flags);
535e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers	/* Could also do a CLFLUSH here to speed up CPU recovery; but
536e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers	   that causes hangs on some VIA CPUs. */
537e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers	return addr;
538e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers}
539e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers
540e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers/**
541e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * text_poke - Update instructions on a live kernel
542e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * @addr: address to modify
543e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * @opcode: source of the copy
544e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * @len: length to copy
545e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers *
546e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * Only atomic text poke/set should be allowed when not doing early patching.
547e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * It means the size must be writable atomically and the address must be aligned
548e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * in a way that permits an atomic write. It also makes sure we fit on a single
549e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers * page.
55078ff7fae04554b49d29226ed12536268c2500d1fMasami Hiramatsu *
55178ff7fae04554b49d29226ed12536268c2500d1fMasami Hiramatsu * Note: Must be called under text_mutex.
552e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers */
5539c54b6164eeb292a0eac86c6913bd8daaff35e62Masami Hiramatsuvoid *text_poke(void *addr, const void *opcode, size_t len)
554e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers{
55578ff7fae04554b49d29226ed12536268c2500d1fMasami Hiramatsu	unsigned long flags;
556e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers	char *vaddr;
557b7b66baa8bc3f8e0cda6576e31e9bde09382565dMathieu Desnoyers	struct page *pages[2];
558b7b66baa8bc3f8e0cda6576e31e9bde09382565dMathieu Desnoyers	int i;
559e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers
560b7b66baa8bc3f8e0cda6576e31e9bde09382565dMathieu Desnoyers	if (!core_kernel_text((unsigned long)addr)) {
561b7b66baa8bc3f8e0cda6576e31e9bde09382565dMathieu Desnoyers		pages[0] = vmalloc_to_page(addr);
562b7b66baa8bc3f8e0cda6576e31e9bde09382565dMathieu Desnoyers		pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
56315a601eb9cdc2a9cc69d5fc745317805a85c064cMathieu Desnoyers	} else {
564b7b66baa8bc3f8e0cda6576e31e9bde09382565dMathieu Desnoyers		pages[0] = virt_to_page(addr);
56500c6b2d5d7b2414bd46c620d6a8c37fa7a716f29Ingo Molnar		WARN_ON(!PageReserved(pages[0]));
566b7b66baa8bc3f8e0cda6576e31e9bde09382565dMathieu Desnoyers		pages[1] = virt_to_page(addr + PAGE_SIZE);
567e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers	}
568b7b66baa8bc3f8e0cda6576e31e9bde09382565dMathieu Desnoyers	BUG_ON(!pages[0]);
5697cf49427042400d40bdc80b5c3399b6b5945afa8Masami Hiramatsu	local_irq_save(flags);
57078ff7fae04554b49d29226ed12536268c2500d1fMasami Hiramatsu	set_fixmap(FIX_TEXT_POKE0, page_to_phys(pages[0]));
57178ff7fae04554b49d29226ed12536268c2500d1fMasami Hiramatsu	if (pages[1])
57278ff7fae04554b49d29226ed12536268c2500d1fMasami Hiramatsu		set_fixmap(FIX_TEXT_POKE1, page_to_phys(pages[1]));
57378ff7fae04554b49d29226ed12536268c2500d1fMasami Hiramatsu	vaddr = (char *)fix_to_virt(FIX_TEXT_POKE0);
574b7b66baa8bc3f8e0cda6576e31e9bde09382565dMathieu Desnoyers	memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
57578ff7fae04554b49d29226ed12536268c2500d1fMasami Hiramatsu	clear_fixmap(FIX_TEXT_POKE0);
57678ff7fae04554b49d29226ed12536268c2500d1fMasami Hiramatsu	if (pages[1])
57778ff7fae04554b49d29226ed12536268c2500d1fMasami Hiramatsu		clear_fixmap(FIX_TEXT_POKE1);
57878ff7fae04554b49d29226ed12536268c2500d1fMasami Hiramatsu	local_flush_tlb();
57919d36ccdc34f5ed444f8a6af0cbfdb6790eb1177Andi Kleen	sync_core();
580a534b679180025aa324ebd63c05516e478551cfdAndi Kleen	/* Could also do a CLFLUSH here to speed up CPU recovery; but
581a534b679180025aa324ebd63c05516e478551cfdAndi Kleen	   that causes hangs on some VIA CPUs. */
582b7b66baa8bc3f8e0cda6576e31e9bde09382565dMathieu Desnoyers	for (i = 0; i < len; i++)
583b7b66baa8bc3f8e0cda6576e31e9bde09382565dMathieu Desnoyers		BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]);
5847cf49427042400d40bdc80b5c3399b6b5945afa8Masami Hiramatsu	local_irq_restore(flags);
585e587cadd8f47e202a30712e2906a65a0606d5865Mathieu Desnoyers	return addr;
58619d36ccdc34f5ed444f8a6af0cbfdb6790eb1177Andi Kleen}
5873d55cc8a058ee96291d6d45b1e35121b9920eca3Masami Hiramatsu
588fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosinastatic void do_sync_core(void *info)
589fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina{
590fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	sync_core();
591fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina}
592fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
593fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosinastatic bool bp_patching_in_progress;
594fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosinastatic void *bp_int3_handler, *bp_int3_addr;
595fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
59617f41571bb2c4a398785452ac2718a6c5d77180eJiri Kosinaint poke_int3_handler(struct pt_regs *regs)
597fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina{
598fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	/* bp_patching_in_progress */
599fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	smp_rmb();
600fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
601fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	if (likely(!bp_patching_in_progress))
60217f41571bb2c4a398785452ac2718a6c5d77180eJiri Kosina		return 0;
603fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
60417f41571bb2c4a398785452ac2718a6c5d77180eJiri Kosina	if (user_mode_vm(regs) || regs->ip != (unsigned long)bp_int3_addr)
60517f41571bb2c4a398785452ac2718a6c5d77180eJiri Kosina		return 0;
606fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
607fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	/* set up the specified breakpoint handler */
60817f41571bb2c4a398785452ac2718a6c5d77180eJiri Kosina	regs->ip = (unsigned long) bp_int3_handler;
60917f41571bb2c4a398785452ac2718a6c5d77180eJiri Kosina
61017f41571bb2c4a398785452ac2718a6c5d77180eJiri Kosina	return 1;
611fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
612fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina}
61317f41571bb2c4a398785452ac2718a6c5d77180eJiri Kosina
614fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina/**
615fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina * text_poke_bp() -- update instructions on live kernel on SMP
616fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina * @addr:	address to patch
617fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina * @opcode:	opcode of new instruction
618fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina * @len:	length to copy
619fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina * @handler:	address to jump to when the temporary breakpoint is hit
620fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina *
621fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina * Modify multi-byte instruction by using int3 breakpoint on SMP.
622ea8596bb2d8d37957f3e92db9511c50801689180Masami Hiramatsu * We completely avoid stop_machine() here, and achieve the
623ea8596bb2d8d37957f3e92db9511c50801689180Masami Hiramatsu * synchronization using int3 breakpoint.
624fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina *
625fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina * The way it is done:
626fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina *	- add a int3 trap to the address that will be patched
627fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina *	- sync cores
628fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina *	- update all but the first byte of the patched range
629fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina *	- sync cores
630fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina *	- replace the first byte (int3) by the first byte of
631fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina *	  replacing opcode
632fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina *	- sync cores
633fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina *
634fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina * Note: must be called under text_mutex.
635fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina */
636fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosinavoid *text_poke_bp(void *addr, const void *opcode, size_t len, void *handler)
637fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina{
638fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	unsigned char int3 = 0xcc;
639fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
640fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	bp_int3_handler = handler;
641fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	bp_int3_addr = (u8 *)addr + sizeof(int3);
642fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	bp_patching_in_progress = true;
643fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	/*
644fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	 * Corresponding read barrier in int3 notifier for
645fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	 * making sure the in_progress flags is correctly ordered wrt.
646fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	 * patching
647fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	 */
648fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	smp_wmb();
649fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
650fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	text_poke(addr, &int3, sizeof(int3));
651fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
652fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	on_each_cpu(do_sync_core, NULL, 1);
653fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
654fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	if (len - sizeof(int3) > 0) {
655fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina		/* patch all but the first byte */
656fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina		text_poke((char *)addr + sizeof(int3),
657fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina			  (const char *) opcode + sizeof(int3),
658fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina			  len - sizeof(int3));
659fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina		/*
660fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina		 * According to Intel, this core syncing is very likely
661fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina		 * not necessary and we'd be safe even without it. But
662fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina		 * better safe than sorry (plus there's not only Intel).
663fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina		 */
664fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina		on_each_cpu(do_sync_core, NULL, 1);
665fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	}
666fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
667fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	/* patch the first byte */
668fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	text_poke(addr, opcode, sizeof(int3));
669fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
670fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	on_each_cpu(do_sync_core, NULL, 1);
671fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
672fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	bp_patching_in_progress = false;
673fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	smp_wmb();
674fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
675fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina	return addr;
676fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina}
677fd4363fff3d96795d3feb1b3fb48ce590f186bddJiri Kosina
678