Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/loongarch/include/asm/alternative.h
26488 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
#ifndef _ASM_ALTERNATIVE_H
3
#define _ASM_ALTERNATIVE_H
4
5
#ifndef __ASSEMBLER__
6
7
#include <linux/types.h>
8
#include <linux/stddef.h>
9
#include <linux/stringify.h>
10
#include <asm/asm.h>
11
12
struct alt_instr {
13
s32 instr_offset; /* offset to original instruction */
14
s32 replace_offset; /* offset to replacement instruction */
15
u16 feature; /* feature bit set for replacement */
16
u8 instrlen; /* length of original instruction */
17
u8 replacementlen; /* length of new instruction */
18
} __packed;
19
20
/*
21
* Debug flag that can be tested to see whether alternative
22
* instructions were patched in already:
23
*/
24
extern int alternatives_patched;
25
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
26
27
extern void alternative_instructions(void);
28
extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
29
30
#define b_replacement(num) "664"#num
31
#define e_replacement(num) "665"#num
32
33
#define alt_end_marker "663"
34
#define alt_slen "662b-661b"
35
#define alt_total_slen alt_end_marker"b-661b"
36
#define alt_rlen(num) e_replacement(num)"f-"b_replacement(num)"f"
37
38
#define __OLDINSTR(oldinstr, num) \
39
"661:\n\t" oldinstr "\n662:\n" \
40
".fill -(((" alt_rlen(num) ")-(" alt_slen ")) > 0) * " \
41
"((" alt_rlen(num) ")-(" alt_slen ")) / 4, 4, 0x03400000\n"
42
43
#define OLDINSTR(oldinstr, num) \
44
__OLDINSTR(oldinstr, num) \
45
alt_end_marker ":\n"
46
47
#define alt_max_short(a, b) "((" a ") ^ (((" a ") ^ (" b ")) & -(-((" a ") < (" b ")))))"
48
49
/*
50
* Pad the second replacement alternative with additional NOPs if it is
51
* additionally longer than the first replacement alternative.
52
*/
53
#define OLDINSTR_2(oldinstr, num1, num2) \
54
"661:\n\t" oldinstr "\n662:\n" \
55
".fill -((" alt_max_short(alt_rlen(num1), alt_rlen(num2)) " - (" alt_slen ")) > 0) * " \
56
"(" alt_max_short(alt_rlen(num1), alt_rlen(num2)) " - (" alt_slen ")) / 4, " \
57
"4, 0x03400000\n" \
58
alt_end_marker ":\n"
59
60
#define ALTINSTR_ENTRY(feature, num) \
61
" .long 661b - .\n" /* label */ \
62
" .long " b_replacement(num)"f - .\n" /* new instruction */ \
63
" .short " __stringify(feature) "\n" /* feature bit */ \
64
" .byte " alt_total_slen "\n" /* source len */ \
65
" .byte " alt_rlen(num) "\n" /* replacement len */
66
67
#define ALTINSTR_REPLACEMENT(newinstr, feature, num) /* replacement */ \
68
b_replacement(num)":\n\t" newinstr "\n" e_replacement(num) ":\n\t"
69
70
/* alternative assembly primitive: */
71
#define ALTERNATIVE(oldinstr, newinstr, feature) \
72
OLDINSTR(oldinstr, 1) \
73
".pushsection .altinstructions,\"a\"\n" \
74
ALTINSTR_ENTRY(feature, 1) \
75
".popsection\n" \
76
".subsection 1\n" \
77
ALTINSTR_REPLACEMENT(newinstr, feature, 1) \
78
".previous\n"
79
80
#define ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2)\
81
OLDINSTR_2(oldinstr, 1, 2) \
82
".pushsection .altinstructions,\"a\"\n" \
83
ALTINSTR_ENTRY(feature1, 1) \
84
ALTINSTR_ENTRY(feature2, 2) \
85
".popsection\n" \
86
".subsection 1\n" \
87
ALTINSTR_REPLACEMENT(newinstr1, feature1, 1) \
88
ALTINSTR_REPLACEMENT(newinstr2, feature2, 2) \
89
".previous\n"
90
91
/*
92
* Alternative instructions for different CPU types or capabilities.
93
*
94
* This allows to use optimized instructions even on generic binary
95
* kernels.
96
*
97
* length of oldinstr must be longer or equal the length of newinstr
98
* It can be padded with nops as needed.
99
*
100
* For non barrier like inlines please define new variants
101
* without volatile and memory clobber.
102
*/
103
#define alternative(oldinstr, newinstr, feature) \
104
(asm volatile (ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory"))
105
106
#define alternative_2(oldinstr, newinstr1, feature1, newinstr2, feature2) \
107
(asm volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory"))
108
109
#endif /* __ASSEMBLER__ */
110
111
#endif /* _ASM_ALTERNATIVE_H */
112
113