blob: dbc1a29284f3a856838bc9b6d4b05558f85c1012 [file] [log] [blame]
Gerd Hoffmann9a0b5812006-03-23 02:59:32 -08001#ifndef _I386_ALTERNATIVE_H
2#define _I386_ALTERNATIVE_H
3
4#ifdef __KERNEL__
5
Kirill Smelkov30343d62006-06-23 02:04:33 -07006#include <asm/types.h>
Rusty Russell139ec7c2006-12-07 02:14:08 +01007#include <linux/stddef.h>
Gerd Hoffmannd167a512006-06-26 13:56:16 +02008#include <linux/types.h>
9
Gerd Hoffmann9a0b5812006-03-23 02:59:32 -080010struct alt_instr {
11 u8 *instr; /* original instruction */
12 u8 *replacement;
13 u8 cpuid; /* cpuid bit set for replacement */
14 u8 instrlen; /* length of original instruction */
15 u8 replacementlen; /* length of new instruction, <= instrlen */
16 u8 pad;
17};
18
Jeremy Fitzhardinge1353ebb2007-05-02 19:27:12 +020019extern void alternative_instructions(void);
Gerd Hoffmann9a0b5812006-03-23 02:59:32 -080020extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
21
22struct module;
Gerd Hoffmann8ec4d412006-07-01 04:36:18 -070023#ifdef CONFIG_SMP
Gerd Hoffmann9a0b5812006-03-23 02:59:32 -080024extern void alternatives_smp_module_add(struct module *mod, char *name,
25 void *locks, void *locks_end,
26 void *text, void *text_end);
27extern void alternatives_smp_module_del(struct module *mod);
28extern void alternatives_smp_switch(int smp);
Gerd Hoffmann8ec4d412006-07-01 04:36:18 -070029#else
30static inline void alternatives_smp_module_add(struct module *mod, char *name,
31 void *locks, void *locks_end,
32 void *text, void *text_end) {}
33static inline void alternatives_smp_module_del(struct module *mod) {}
34static inline void alternatives_smp_switch(int smp) {}
35#endif
Gerd Hoffmann9a0b5812006-03-23 02:59:32 -080036
37#endif
38
39/*
40 * Alternative instructions for different CPU types or capabilities.
41 *
42 * This allows to use optimized instructions even on generic binary
43 * kernels.
44 *
45 * length of oldinstr must be longer or equal the length of newinstr
46 * It can be padded with nops as needed.
47 *
48 * For non barrier like inlines please define new variants
49 * without volatile and memory clobber.
50 */
51#define alternative(oldinstr, newinstr, feature) \
52 asm volatile ("661:\n\t" oldinstr "\n662:\n" \
53 ".section .altinstructions,\"a\"\n" \
54 " .align 4\n" \
55 " .long 661b\n" /* label */ \
56 " .long 663f\n" /* new instruction */ \
57 " .byte %c0\n" /* feature bit */ \
58 " .byte 662b-661b\n" /* sourcelen */ \
59 " .byte 664f-663f\n" /* replacementlen */ \
60 ".previous\n" \
61 ".section .altinstr_replacement,\"ax\"\n" \
62 "663:\n\t" newinstr "\n664:\n" /* replacement */\
63 ".previous" :: "i" (feature) : "memory")
64
65/*
66 * Alternative inline assembly with input.
67 *
68 * Pecularities:
69 * No memory clobber here.
70 * Argument numbers start with 1.
71 * Best is to use constraints that are fixed size (like (%1) ... "r")
72 * If you use variable sized constraints like "m" or "g" in the
73 * replacement maake sure to pad to the worst case length.
74 */
75#define alternative_input(oldinstr, newinstr, feature, input...) \
76 asm volatile ("661:\n\t" oldinstr "\n662:\n" \
77 ".section .altinstructions,\"a\"\n" \
78 " .align 4\n" \
79 " .long 661b\n" /* label */ \
80 " .long 663f\n" /* new instruction */ \
81 " .byte %c0\n" /* feature bit */ \
82 " .byte 662b-661b\n" /* sourcelen */ \
83 " .byte 664f-663f\n" /* replacementlen */ \
84 ".previous\n" \
85 ".section .altinstr_replacement,\"ax\"\n" \
86 "663:\n\t" newinstr "\n664:\n" /* replacement */\
87 ".previous" :: "i" (feature), ##input)
88
89/*
90 * Alternative inline assembly for SMP.
91 *
Gerd Hoffmann9a0b5812006-03-23 02:59:32 -080092 * The LOCK_PREFIX macro defined here replaces the LOCK and
93 * LOCK_PREFIX macros used everywhere in the source tree.
94 *
95 * SMP alternatives use the same data structures as the other
96 * alternatives and the X86_FEATURE_UP flag to indicate the case of a
97 * UP system running a SMP kernel. The existing apply_alternatives()
98 * works fine for patching a SMP kernel for UP.
99 *
100 * The SMP alternative tables can be kept after boot and contain both
101 * UP and SMP versions of the instructions to allow switching back to
102 * SMP at runtime, when hotplugging in a new CPU, which is especially
103 * useful in virtualized environments.
104 *
105 * The very common lock prefix is handled as special case in a
106 * separate table which is a pure address list without replacement ptr
107 * and size information. That keeps the table sizes small.
108 */
109
110#ifdef CONFIG_SMP
Gerd Hoffmann9a0b5812006-03-23 02:59:32 -0800111#define LOCK_PREFIX \
112 ".section .smp_locks,\"a\"\n" \
113 " .align 4\n" \
114 " .long 661f\n" /* address */ \
115 ".previous\n" \
116 "661:\n\tlock; "
117
118#else /* ! CONFIG_SMP */
Gerd Hoffmann9a0b5812006-03-23 02:59:32 -0800119#define LOCK_PREFIX ""
120#endif
121
Rusty Russell139ec7c2006-12-07 02:14:08 +0100122struct paravirt_patch;
123#ifdef CONFIG_PARAVIRT
124void apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end);
125#else
126static inline void
127apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end)
128{}
129#define __start_parainstructions NULL
130#define __stop_parainstructions NULL
131#endif
132
Gerd Hoffmann9a0b5812006-03-23 02:59:32 -0800133#endif /* _I386_ALTERNATIVE_H */