Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge 'x86/alternatives'

Pick up dependent changes.

Signed-off-by: Borislav Petkov <bp@suse.de>

+486 -642
+5 -9
arch/arm/include/asm/paravirt.h
··· 3 3 #define _ASM_ARM_PARAVIRT_H 4 4 5 5 #ifdef CONFIG_PARAVIRT 6 + #include <linux/static_call_types.h> 7 + 6 8 struct static_key; 7 9 extern struct static_key paravirt_steal_enabled; 8 10 extern struct static_key paravirt_steal_rq_enabled; 9 11 10 - struct pv_time_ops { 11 - unsigned long long (*steal_clock)(int cpu); 12 - }; 12 + u64 dummy_steal_clock(int cpu); 13 13 14 - struct paravirt_patch_template { 15 - struct pv_time_ops time; 16 - }; 17 - 18 - extern struct paravirt_patch_template pv_ops; 14 + DECLARE_STATIC_CALL(pv_steal_clock, dummy_steal_clock); 19 15 20 16 static inline u64 paravirt_steal_clock(int cpu) 21 17 { 22 - return pv_ops.time.steal_clock(cpu); 18 + return static_call(pv_steal_clock)(cpu); 23 19 } 24 20 #endif 25 21
+7 -2
arch/arm/kernel/paravirt.c
··· 9 9 #include <linux/export.h> 10 10 #include <linux/jump_label.h> 11 11 #include <linux/types.h> 12 + #include <linux/static_call.h> 12 13 #include <asm/paravirt.h> 13 14 14 15 struct static_key paravirt_steal_enabled; 15 16 struct static_key paravirt_steal_rq_enabled; 16 17 17 - struct paravirt_patch_template pv_ops; 18 - EXPORT_SYMBOL_GPL(pv_ops); 18 + static u64 native_steal_clock(int cpu) 19 + { 20 + return 0; 21 + } 22 + 23 + DEFINE_STATIC_CALL(pv_steal_clock, native_steal_clock);
+5 -9
arch/arm64/include/asm/paravirt.h
··· 3 3 #define _ASM_ARM64_PARAVIRT_H 4 4 5 5 #ifdef CONFIG_PARAVIRT 6 + #include <linux/static_call_types.h> 7 + 6 8 struct static_key; 7 9 extern struct static_key paravirt_steal_enabled; 8 10 extern struct static_key paravirt_steal_rq_enabled; 9 11 10 - struct pv_time_ops { 11 - unsigned long long (*steal_clock)(int cpu); 12 - }; 12 + u64 dummy_steal_clock(int cpu); 13 13 14 - struct paravirt_patch_template { 15 - struct pv_time_ops time; 16 - }; 17 - 18 - extern struct paravirt_patch_template pv_ops; 14 + DECLARE_STATIC_CALL(pv_steal_clock, dummy_steal_clock); 19 15 20 16 static inline u64 paravirt_steal_clock(int cpu) 21 17 { 22 - return pv_ops.time.steal_clock(cpu); 18 + return static_call(pv_steal_clock)(cpu); 23 19 } 24 20 25 21 int __init pv_time_init(void);
+9 -4
arch/arm64/kernel/paravirt.c
··· 18 18 #include <linux/reboot.h> 19 19 #include <linux/slab.h> 20 20 #include <linux/types.h> 21 + #include <linux/static_call.h> 21 22 22 23 #include <asm/paravirt.h> 23 24 #include <asm/pvclock-abi.h> ··· 27 26 struct static_key paravirt_steal_enabled; 28 27 struct static_key paravirt_steal_rq_enabled; 29 28 30 - struct paravirt_patch_template pv_ops; 31 - EXPORT_SYMBOL_GPL(pv_ops); 29 + static u64 native_steal_clock(int cpu) 30 + { 31 + return 0; 32 + } 33 + 34 + DEFINE_STATIC_CALL(pv_steal_clock, native_steal_clock); 32 35 33 36 struct pv_time_stolen_time_region { 34 37 struct pvclock_vcpu_stolen_time *kaddr; ··· 50 45 early_param("no-steal-acc", parse_no_stealacc); 51 46 52 47 /* return stolen time in ns by asking the hypervisor */ 53 - static u64 pv_steal_clock(int cpu) 48 + static u64 para_steal_clock(int cpu) 54 49 { 55 50 struct pv_time_stolen_time_region *reg; 56 51 ··· 155 150 if (ret) 156 151 return ret; 157 152 158 - pv_ops.time.steal_clock = pv_steal_clock; 153 + static_call_update(pv_steal_clock, para_steal_clock); 159 154 160 155 static_key_slow_inc(&paravirt_steal_enabled); 161 156 if (steal_acc)
+1
arch/x86/Kconfig
··· 774 774 775 775 config PARAVIRT 776 776 bool "Enable paravirtualization code" 777 + depends on HAVE_STATIC_CALL 777 778 help 778 779 This changes the kernel so it can modify itself when it is run 779 780 under a hypervisor, potentially improving performance significantly
+3 -3
arch/x86/entry/entry_32.S
··· 40 40 #include <asm/processor-flags.h> 41 41 #include <asm/irq_vectors.h> 42 42 #include <asm/cpufeatures.h> 43 - #include <asm/alternative-asm.h> 43 + #include <asm/alternative.h> 44 44 #include <asm/asm.h> 45 45 #include <asm/smap.h> 46 46 #include <asm/frame.h> ··· 349 349 * will soon execute iret and the tracer was already set to 350 350 * the irqstate after the IRET: 351 351 */ 352 - DISABLE_INTERRUPTS(CLBR_ANY) 352 + cli 353 353 lss (%esp), %esp /* switch to espfix segment */ 354 354 .Lend_\@: 355 355 #endif /* CONFIG_X86_ESPFIX32 */ ··· 994 994 * when returning from IPI handler and when returning from 995 995 * scheduler to user-space. 996 996 */ 997 - INTERRUPT_RETURN 997 + iret 998 998 999 999 .section .fixup, "ax" 1000 1000 SYM_CODE_START(asm_iret_error)
+1 -1
arch/x86/entry/entry_64.S
··· 305 305 .macro DEBUG_ENTRY_ASSERT_IRQS_OFF 306 306 #ifdef CONFIG_DEBUG_ENTRY 307 307 pushq %rax 308 - SAVE_FLAGS(CLBR_RAX) 308 + SAVE_FLAGS 309 309 testl $X86_EFLAGS_IF, %eax 310 310 jz .Lokay_\@ 311 311 ud2
+1 -1
arch/x86/entry/vdso/vdso32/system_call.S
··· 6 6 #include <linux/linkage.h> 7 7 #include <asm/dwarf2.h> 8 8 #include <asm/cpufeatures.h> 9 - #include <asm/alternative-asm.h> 9 + #include <asm/alternative.h> 10 10 11 11 .text 12 12 .globl __kernel_vsyscall
-114
arch/x86/include/asm/alternative-asm.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #ifndef _ASM_X86_ALTERNATIVE_ASM_H 3 - #define _ASM_X86_ALTERNATIVE_ASM_H 4 - 5 - #ifdef __ASSEMBLY__ 6 - 7 - #include <asm/asm.h> 8 - 9 - #ifdef CONFIG_SMP 10 - .macro LOCK_PREFIX 11 - 672: lock 12 - .pushsection .smp_locks,"a" 13 - .balign 4 14 - .long 672b - . 15 - .popsection 16 - .endm 17 - #else 18 - .macro LOCK_PREFIX 19 - .endm 20 - #endif 21 - 22 - /* 23 - * objtool annotation to ignore the alternatives and only consider the original 24 - * instruction(s). 25 - */ 26 - .macro ANNOTATE_IGNORE_ALTERNATIVE 27 - .Lannotate_\@: 28 - .pushsection .discard.ignore_alts 29 - .long .Lannotate_\@ - . 30 - .popsection 31 - .endm 32 - 33 - /* 34 - * Issue one struct alt_instr descriptor entry (need to put it into 35 - * the section .altinstructions, see below). This entry contains 36 - * enough information for the alternatives patching code to patch an 37 - * instruction. See apply_alternatives(). 38 - */ 39 - .macro altinstruction_entry orig alt feature orig_len alt_len pad_len 40 - .long \orig - . 41 - .long \alt - . 42 - .word \feature 43 - .byte \orig_len 44 - .byte \alt_len 45 - .byte \pad_len 46 - .endm 47 - 48 - /* 49 - * Define an alternative between two instructions. If @feature is 50 - * present, early code in apply_alternatives() replaces @oldinstr with 51 - * @newinstr. ".skip" directive takes care of proper instruction padding 52 - * in case @newinstr is longer than @oldinstr. 53 - */ 54 - .macro ALTERNATIVE oldinstr, newinstr, feature 55 - 140: 56 - \oldinstr 57 - 141: 58 - .skip -(((144f-143f)-(141b-140b)) > 0) * ((144f-143f)-(141b-140b)),0x90 59 - 142: 60 - 61 - .pushsection .altinstructions,"a" 62 - altinstruction_entry 140b,143f,\feature,142b-140b,144f-143f,142b-141b 63 - .popsection 64 - 65 - .pushsection .altinstr_replacement,"ax" 66 - 143: 67 - \newinstr 68 - 144: 69 - .popsection 70 - .endm 71 - 72 - #define old_len 141b-140b 73 - #define new_len1 144f-143f 74 - #define new_len2 145f-144f 75 - 76 - /* 77 - * gas compatible max based on the idea from: 78 - * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax 79 - * 80 - * The additional "-" is needed because gas uses a "true" value of -1. 81 - */ 82 - #define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b))))) 83 - 84 - 85 - /* 86 - * Same as ALTERNATIVE macro above but for two alternatives. If CPU 87 - * has @feature1, it replaces @oldinstr with @newinstr1. If CPU has 88 - * @feature2, it replaces @oldinstr with @feature2. 89 - */ 90 - .macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2 91 - 140: 92 - \oldinstr 93 - 141: 94 - .skip -((alt_max_short(new_len1, new_len2) - (old_len)) > 0) * \ 95 - (alt_max_short(new_len1, new_len2) - (old_len)),0x90 96 - 142: 97 - 98 - .pushsection .altinstructions,"a" 99 - altinstruction_entry 140b,143f,\feature1,142b-140b,144f-143f,142b-141b 100 - altinstruction_entry 140b,144f,\feature2,142b-140b,145f-144f,142b-141b 101 - .popsection 102 - 103 - .pushsection .altinstr_replacement,"ax" 104 - 143: 105 - \newinstr1 106 - 144: 107 - \newinstr2 108 - 145: 109 - .popsection 110 - .endm 111 - 112 - #endif /* __ASSEMBLY__ */ 113 - 114 - #endif /* _ASM_X86_ALTERNATIVE_ASM_H */
+132 -10
arch/x86/include/asm/alternative.h
··· 2 2 #ifndef _ASM_X86_ALTERNATIVE_H 3 3 #define _ASM_X86_ALTERNATIVE_H 4 4 5 - #ifndef __ASSEMBLY__ 6 - 7 5 #include <linux/types.h> 8 - #include <linux/stddef.h> 9 6 #include <linux/stringify.h> 10 7 #include <asm/asm.h> 8 + 9 + #define ALTINSTR_FLAG_INV (1 << 15) 10 + #define ALT_NOT(feat) ((feat) | ALTINSTR_FLAG_INV) 11 + 12 + #ifndef __ASSEMBLY__ 13 + 14 + #include <linux/stddef.h> 11 15 12 16 /* 13 17 * Alternative inline assembly for SMP. ··· 154 150 " .byte " alt_rlen(num) "\n" /* replacement len */ \ 155 151 " .byte " alt_pad_len "\n" /* pad len */ 156 152 157 - #define ALTINSTR_REPLACEMENT(newinstr, feature, num) /* replacement */ \ 153 + #define ALTINSTR_REPLACEMENT(newinstr, num) /* replacement */ \ 158 154 "# ALT: replacement " #num "\n" \ 159 155 b_replacement(num)":\n\t" newinstr "\n" e_replacement(num) ":\n" 160 156 ··· 165 161 ALTINSTR_ENTRY(feature, 1) \ 166 162 ".popsection\n" \ 167 163 ".pushsection .altinstr_replacement, \"ax\"\n" \ 168 - ALTINSTR_REPLACEMENT(newinstr, feature, 1) \ 164 + ALTINSTR_REPLACEMENT(newinstr, 1) \ 169 165 ".popsection\n" 170 166 171 167 #define ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2)\ ··· 175 171 ALTINSTR_ENTRY(feature2, 2) \ 176 172 ".popsection\n" \ 177 173 ".pushsection .altinstr_replacement, \"ax\"\n" \ 178 - ALTINSTR_REPLACEMENT(newinstr1, feature1, 1) \ 179 - ALTINSTR_REPLACEMENT(newinstr2, feature2, 2) \ 174 + ALTINSTR_REPLACEMENT(newinstr1, 1) \ 175 + ALTINSTR_REPLACEMENT(newinstr2, 2) \ 180 176 ".popsection\n" 177 + 178 + /* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */ 179 + #define ALTERNATIVE_TERNARY(oldinstr, feature, newinstr_yes, newinstr_no) \ 180 + ALTERNATIVE_2(oldinstr, newinstr_no, X86_FEATURE_ALWAYS, \ 181 + newinstr_yes, feature) 181 182 182 183 #define ALTERNATIVE_3(oldinsn, newinsn1, feat1, newinsn2, feat2, newinsn3, feat3) \ 183 184 OLDINSTR_3(oldinsn, 1, 2, 3) \ ··· 192 183 ALTINSTR_ENTRY(feat3, 3) \ 193 184 ".popsection\n" \ 194 185 ".pushsection .altinstr_replacement, \"ax\"\n" \ 195 - ALTINSTR_REPLACEMENT(newinsn1, feat1, 1) \ 196 - ALTINSTR_REPLACEMENT(newinsn2, feat2, 2) \ 197 - ALTINSTR_REPLACEMENT(newinsn3, feat3, 3) \ 186 + ALTINSTR_REPLACEMENT(newinsn1, 1) \ 187 + ALTINSTR_REPLACEMENT(newinsn2, 2) \ 188 + ALTINSTR_REPLACEMENT(newinsn3, 3) \ 198 189 ".popsection\n" 199 190 200 191 /* ··· 214 205 215 206 #define alternative_2(oldinstr, newinstr1, feature1, newinstr2, feature2) \ 216 207 asm_inline volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory") 208 + 209 + #define alternative_ternary(oldinstr, feature, newinstr_yes, newinstr_no) \ 210 + asm_inline volatile(ALTERNATIVE_TERNARY(oldinstr, feature, newinstr_yes, newinstr_no) ::: "memory") 217 211 218 212 /* 219 213 * Alternative inline assembly with input. ··· 282 270 * alternative_{input,io,call}() 283 271 */ 284 272 #define ASM_NO_INPUT_CLOBBER(clbr...) "i" (0) : clbr 273 + 274 + #else /* __ASSEMBLY__ */ 275 + 276 + #ifdef CONFIG_SMP 277 + .macro LOCK_PREFIX 278 + 672: lock 279 + .pushsection .smp_locks,"a" 280 + .balign 4 281 + .long 672b - . 282 + .popsection 283 + .endm 284 + #else 285 + .macro LOCK_PREFIX 286 + .endm 287 + #endif 288 + 289 + /* 290 + * objtool annotation to ignore the alternatives and only consider the original 291 + * instruction(s). 292 + */ 293 + .macro ANNOTATE_IGNORE_ALTERNATIVE 294 + .Lannotate_\@: 295 + .pushsection .discard.ignore_alts 296 + .long .Lannotate_\@ - . 297 + .popsection 298 + .endm 299 + 300 + /* 301 + * Issue one struct alt_instr descriptor entry (need to put it into 302 + * the section .altinstructions, see below). This entry contains 303 + * enough information for the alternatives patching code to patch an 304 + * instruction. See apply_alternatives(). 305 + */ 306 + .macro altinstruction_entry orig alt feature orig_len alt_len pad_len 307 + .long \orig - . 308 + .long \alt - . 309 + .word \feature 310 + .byte \orig_len 311 + .byte \alt_len 312 + .byte \pad_len 313 + .endm 314 + 315 + /* 316 + * Define an alternative between two instructions. If @feature is 317 + * present, early code in apply_alternatives() replaces @oldinstr with 318 + * @newinstr. ".skip" directive takes care of proper instruction padding 319 + * in case @newinstr is longer than @oldinstr. 320 + */ 321 + .macro ALTERNATIVE oldinstr, newinstr, feature 322 + 140: 323 + \oldinstr 324 + 141: 325 + .skip -(((144f-143f)-(141b-140b)) > 0) * ((144f-143f)-(141b-140b)),0x90 326 + 142: 327 + 328 + .pushsection .altinstructions,"a" 329 + altinstruction_entry 140b,143f,\feature,142b-140b,144f-143f,142b-141b 330 + .popsection 331 + 332 + .pushsection .altinstr_replacement,"ax" 333 + 143: 334 + \newinstr 335 + 144: 336 + .popsection 337 + .endm 338 + 339 + #define old_len 141b-140b 340 + #define new_len1 144f-143f 341 + #define new_len2 145f-144f 342 + 343 + /* 344 + * gas compatible max based on the idea from: 345 + * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax 346 + * 347 + * The additional "-" is needed because gas uses a "true" value of -1. 348 + */ 349 + #define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b))))) 350 + 351 + 352 + /* 353 + * Same as ALTERNATIVE macro above but for two alternatives. If CPU 354 + * has @feature1, it replaces @oldinstr with @newinstr1. If CPU has 355 + * @feature2, it replaces @oldinstr with @feature2. 356 + */ 357 + .macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2 358 + 140: 359 + \oldinstr 360 + 141: 361 + .skip -((alt_max_short(new_len1, new_len2) - (old_len)) > 0) * \ 362 + (alt_max_short(new_len1, new_len2) - (old_len)),0x90 363 + 142: 364 + 365 + .pushsection .altinstructions,"a" 366 + altinstruction_entry 140b,143f,\feature1,142b-140b,144f-143f,142b-141b 367 + altinstruction_entry 140b,144f,\feature2,142b-140b,145f-144f,142b-141b 368 + .popsection 369 + 370 + .pushsection .altinstr_replacement,"ax" 371 + 143: 372 + \newinstr1 373 + 144: 374 + \newinstr2 375 + 145: 376 + .popsection 377 + .endm 378 + 379 + /* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */ 380 + #define ALTERNATIVE_TERNARY(oldinstr, feature, newinstr_yes, newinstr_no) \ 381 + ALTERNATIVE_2 oldinstr, newinstr_no, X86_FEATURE_ALWAYS, \ 382 + newinstr_yes, feature 285 383 286 384 #endif /* __ASSEMBLY__ */ 287 385
+9 -32
arch/x86/include/asm/cpufeature.h
··· 8 8 9 9 #include <asm/asm.h> 10 10 #include <linux/bitops.h> 11 + #include <asm/alternative.h> 11 12 12 13 enum cpuid_leafs 13 14 { ··· 176 175 */ 177 176 static __always_inline bool _static_cpu_has(u16 bit) 178 177 { 179 - asm_volatile_goto("1: jmp 6f\n" 180 - "2:\n" 181 - ".skip -(((5f-4f) - (2b-1b)) > 0) * " 182 - "((5f-4f) - (2b-1b)),0x90\n" 183 - "3:\n" 184 - ".section .altinstructions,\"a\"\n" 185 - " .long 1b - .\n" /* src offset */ 186 - " .long 4f - .\n" /* repl offset */ 187 - " .word %P[always]\n" /* always replace */ 188 - " .byte 3b - 1b\n" /* src len */ 189 - " .byte 5f - 4f\n" /* repl len */ 190 - " .byte 3b - 2b\n" /* pad len */ 191 - ".previous\n" 192 - ".section .altinstr_replacement,\"ax\"\n" 193 - "4: jmp %l[t_no]\n" 194 - "5:\n" 195 - ".previous\n" 196 - ".section .altinstructions,\"a\"\n" 197 - " .long 1b - .\n" /* src offset */ 198 - " .long 0\n" /* no replacement */ 199 - " .word %P[feature]\n" /* feature bit */ 200 - " .byte 3b - 1b\n" /* src len */ 201 - " .byte 0\n" /* repl len */ 202 - " .byte 0\n" /* pad len */ 203 - ".previous\n" 204 - ".section .altinstr_aux,\"ax\"\n" 205 - "6:\n" 206 - " testb %[bitnum],%[cap_byte]\n" 207 - " jnz %l[t_yes]\n" 208 - " jmp %l[t_no]\n" 209 - ".previous\n" 178 + asm_volatile_goto( 179 + ALTERNATIVE_TERNARY("jmp 6f", %P[feature], "", "jmp %l[t_no]") 180 + ".section .altinstr_aux,\"ax\"\n" 181 + "6:\n" 182 + " testb %[bitnum],%[cap_byte]\n" 183 + " jnz %l[t_yes]\n" 184 + " jmp %l[t_no]\n" 185 + ".previous\n" 210 186 : : [feature] "i" (bit), 211 - [always] "i" (X86_FEATURE_ALWAYS), 212 187 [bitnum] "i" (1 << (bit & 7)), 213 188 [cap_byte] "m" (((const char *)boot_cpu_data.x86_capability)[bit >> 3]) 214 189 : : t_yes, t_no);
+2
arch/x86/include/asm/cpufeatures.h
··· 236 236 #define X86_FEATURE_EPT_AD ( 8*32+17) /* Intel Extended Page Table access-dirty bit */ 237 237 #define X86_FEATURE_VMCALL ( 8*32+18) /* "" Hypervisor supports the VMCALL instruction */ 238 238 #define X86_FEATURE_VMW_VMMCALL ( 8*32+19) /* "" VMware prefers VMMCALL hypercall instruction */ 239 + #define X86_FEATURE_PVUNLOCK ( 8*32+20) /* "" PV unlock function */ 240 + #define X86_FEATURE_VCPUPREEMPT ( 8*32+21) /* "" PV vcpu_is_preempted function */ 239 241 240 242 /* Intel-defined CPU features, CPUID level 0x00000007:0 (EBX), word 9 */ 241 243 #define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* RDFSBASE, WRFSBASE, RDGSBASE, WRGSBASE instructions*/
+1 -6
arch/x86/include/asm/irqflags.h
··· 109 109 } 110 110 #else 111 111 112 - #define ENABLE_INTERRUPTS(x) sti 113 - #define DISABLE_INTERRUPTS(x) cli 114 - 115 112 #ifdef CONFIG_X86_64 116 113 #ifdef CONFIG_DEBUG_ENTRY 117 - #define SAVE_FLAGS(x) pushfq; popq %rax 114 + #define SAVE_FLAGS pushfq; popq %rax 118 115 #endif 119 116 120 117 #define INTERRUPT_RETURN jmp native_iret 121 118 122 - #else 123 - #define INTERRUPT_RETURN iret 124 119 #endif 125 120 126 121 #endif /* __ASSEMBLY__ */
+1 -1
arch/x86/include/asm/mshyperv.h
··· 63 63 static __always_inline void hv_setup_sched_clock(void *sched_clock) 64 64 { 65 65 #ifdef CONFIG_PARAVIRT 66 - pv_ops.time.sched_clock = sched_clock; 66 + paravirt_set_sched_clock(sched_clock); 67 67 #endif 68 68 } 69 69
-1
arch/x86/include/asm/nospec-branch.h
··· 7 7 #include <linux/objtool.h> 8 8 9 9 #include <asm/alternative.h> 10 - #include <asm/alternative-asm.h> 11 10 #include <asm/cpufeatures.h> 12 11 #include <asm/msr-index.h> 13 12 #include <asm/unwind_hints.h>
+76 -91
arch/x86/include/asm/paravirt.h
··· 15 15 #include <linux/bug.h> 16 16 #include <linux/types.h> 17 17 #include <linux/cpumask.h> 18 + #include <linux/static_call_types.h> 18 19 #include <asm/frame.h> 19 20 20 - static inline unsigned long long paravirt_sched_clock(void) 21 + u64 dummy_steal_clock(int cpu); 22 + u64 dummy_sched_clock(void); 23 + 24 + DECLARE_STATIC_CALL(pv_steal_clock, dummy_steal_clock); 25 + DECLARE_STATIC_CALL(pv_sched_clock, dummy_sched_clock); 26 + 27 + void paravirt_set_sched_clock(u64 (*func)(void)); 28 + 29 + static inline u64 paravirt_sched_clock(void) 21 30 { 22 - return PVOP_CALL0(unsigned long long, time.sched_clock); 31 + return static_call(pv_sched_clock)(); 23 32 } 24 33 25 34 struct static_key; ··· 42 33 43 34 static inline u64 paravirt_steal_clock(int cpu) 44 35 { 45 - return PVOP_CALL1(u64, time.steal_clock, cpu); 36 + return static_call(pv_steal_clock)(cpu); 46 37 } 38 + 39 + #ifdef CONFIG_PARAVIRT_SPINLOCKS 40 + void __init paravirt_set_cap(void); 41 + #endif 47 42 48 43 /* The paravirtualized I/O functions */ 49 44 static inline void slow_down_io(void) ··· 135 122 136 123 static inline unsigned long read_cr2(void) 137 124 { 138 - return PVOP_CALLEE0(unsigned long, mmu.read_cr2); 125 + return PVOP_ALT_CALLEE0(unsigned long, mmu.read_cr2, 126 + "mov %%cr2, %%rax;", 127 + ALT_NOT(X86_FEATURE_XENPV)); 139 128 } 140 129 141 130 static inline void write_cr2(unsigned long x) ··· 147 132 148 133 static inline unsigned long __read_cr3(void) 149 134 { 150 - return PVOP_CALL0(unsigned long, mmu.read_cr3); 135 + return PVOP_ALT_CALL0(unsigned long, mmu.read_cr3, 136 + "mov %%cr3, %%rax;", ALT_NOT(X86_FEATURE_XENPV)); 151 137 } 152 138 153 139 static inline void write_cr3(unsigned long x) 154 140 { 155 - PVOP_VCALL1(mmu.write_cr3, x); 141 + PVOP_ALT_VCALL1(mmu.write_cr3, x, 142 + "mov %%rdi, %%cr3", ALT_NOT(X86_FEATURE_XENPV)); 156 143 } 157 144 158 145 static inline void __write_cr4(unsigned long x) ··· 174 157 175 158 static inline void wbinvd(void) 176 159 { 177 - PVOP_VCALL0(cpu.wbinvd); 160 + PVOP_ALT_VCALL0(cpu.wbinvd, "wbinvd", ALT_NOT(X86_FEATURE_XENPV)); 178 161 } 179 162 180 163 static inline u64 paravirt_read_msr(unsigned msr) ··· 388 371 389 372 static inline pte_t __pte(pteval_t val) 390 373 { 391 - return (pte_t) { PVOP_CALLEE1(pteval_t, mmu.make_pte, val) }; 374 + return (pte_t) { PVOP_ALT_CALLEE1(pteval_t, mmu.make_pte, val, 375 + "mov %%rdi, %%rax", 376 + ALT_NOT(X86_FEATURE_XENPV)) }; 392 377 } 393 378 394 379 static inline pteval_t pte_val(pte_t pte) 395 380 { 396 - return PVOP_CALLEE1(pteval_t, mmu.pte_val, pte.pte); 381 + return PVOP_ALT_CALLEE1(pteval_t, mmu.pte_val, pte.pte, 382 + "mov %%rdi, %%rax", ALT_NOT(X86_FEATURE_XENPV)); 397 383 } 398 384 399 385 static inline pgd_t __pgd(pgdval_t val) 400 386 { 401 - return (pgd_t) { PVOP_CALLEE1(pgdval_t, mmu.make_pgd, val) }; 387 + return (pgd_t) { PVOP_ALT_CALLEE1(pgdval_t, mmu.make_pgd, val, 388 + "mov %%rdi, %%rax", 389 + ALT_NOT(X86_FEATURE_XENPV)) }; 402 390 } 403 391 404 392 static inline pgdval_t pgd_val(pgd_t pgd) 405 393 { 406 - return PVOP_CALLEE1(pgdval_t, mmu.pgd_val, pgd.pgd); 394 + return PVOP_ALT_CALLEE1(pgdval_t, mmu.pgd_val, pgd.pgd, 395 + "mov %%rdi, %%rax", ALT_NOT(X86_FEATURE_XENPV)); 407 396 } 408 397 409 398 #define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION ··· 442 419 443 420 static inline pmd_t __pmd(pmdval_t val) 444 421 { 445 - return (pmd_t) { PVOP_CALLEE1(pmdval_t, mmu.make_pmd, val) }; 422 + return (pmd_t) { PVOP_ALT_CALLEE1(pmdval_t, mmu.make_pmd, val, 423 + "mov %%rdi, %%rax", 424 + ALT_NOT(X86_FEATURE_XENPV)) }; 446 425 } 447 426 448 427 static inline pmdval_t pmd_val(pmd_t pmd) 449 428 { 450 - return PVOP_CALLEE1(pmdval_t, mmu.pmd_val, pmd.pmd); 429 + return PVOP_ALT_CALLEE1(pmdval_t, mmu.pmd_val, pmd.pmd, 430 + "mov %%rdi, %%rax", ALT_NOT(X86_FEATURE_XENPV)); 451 431 } 452 432 453 433 static inline void set_pud(pud_t *pudp, pud_t pud) ··· 462 436 { 463 437 pudval_t ret; 464 438 465 - ret = PVOP_CALLEE1(pudval_t, mmu.make_pud, val); 439 + ret = PVOP_ALT_CALLEE1(pudval_t, mmu.make_pud, val, 440 + "mov %%rdi, %%rax", ALT_NOT(X86_FEATURE_XENPV)); 466 441 467 442 return (pud_t) { ret }; 468 443 } 469 444 470 445 static inline pudval_t pud_val(pud_t pud) 471 446 { 472 - return PVOP_CALLEE1(pudval_t, mmu.pud_val, pud.pud); 447 + return PVOP_ALT_CALLEE1(pudval_t, mmu.pud_val, pud.pud, 448 + "mov %%rdi, %%rax", ALT_NOT(X86_FEATURE_XENPV)); 473 449 } 474 450 475 451 static inline void pud_clear(pud_t *pudp) ··· 490 462 491 463 static inline p4d_t __p4d(p4dval_t val) 492 464 { 493 - p4dval_t ret = PVOP_CALLEE1(p4dval_t, mmu.make_p4d, val); 465 + p4dval_t ret = PVOP_ALT_CALLEE1(p4dval_t, mmu.make_p4d, val, 466 + "mov %%rdi, %%rax", 467 + ALT_NOT(X86_FEATURE_XENPV)); 494 468 495 469 return (p4d_t) { ret }; 496 470 } 497 471 498 472 static inline p4dval_t p4d_val(p4d_t p4d) 499 473 { 500 - return PVOP_CALLEE1(p4dval_t, mmu.p4d_val, p4d.p4d); 474 + return PVOP_ALT_CALLEE1(p4dval_t, mmu.p4d_val, p4d.p4d, 475 + "mov %%rdi, %%rax", ALT_NOT(X86_FEATURE_XENPV)); 501 476 } 502 477 503 478 static inline void __set_pgd(pgd_t *pgdp, pgd_t pgd) ··· 587 556 588 557 static __always_inline void pv_queued_spin_unlock(struct qspinlock *lock) 589 558 { 590 - PVOP_VCALLEE1(lock.queued_spin_unlock, lock); 559 + PVOP_ALT_VCALLEE1(lock.queued_spin_unlock, lock, 560 + "movb $0, (%%" _ASM_ARG1 ");", 561 + ALT_NOT(X86_FEATURE_PVUNLOCK)); 591 562 } 592 563 593 564 static __always_inline void pv_wait(u8 *ptr, u8 val) ··· 604 571 605 572 static __always_inline bool pv_vcpu_is_preempted(long cpu) 606 573 { 607 - return PVOP_CALLEE1(bool, lock.vcpu_is_preempted, cpu); 574 + return PVOP_ALT_CALLEE1(bool, lock.vcpu_is_preempted, cpu, 575 + "xor %%" _ASM_AX ", %%" _ASM_AX ";", 576 + ALT_NOT(X86_FEATURE_VCPUPREEMPT)); 608 577 } 609 578 610 579 void __raw_callee_save___native_queued_spin_unlock(struct qspinlock *lock); ··· 680 645 #ifdef CONFIG_PARAVIRT_XXL 681 646 static inline notrace unsigned long arch_local_save_flags(void) 682 647 { 683 - return PVOP_CALLEE0(unsigned long, irq.save_fl); 648 + return PVOP_ALT_CALLEE0(unsigned long, irq.save_fl, "pushf; pop %%rax;", 649 + ALT_NOT(X86_FEATURE_XENPV)); 684 650 } 685 651 686 652 static inline notrace void arch_local_irq_disable(void) 687 653 { 688 - PVOP_VCALLEE0(irq.irq_disable); 654 + PVOP_ALT_VCALLEE0(irq.irq_disable, "cli;", ALT_NOT(X86_FEATURE_XENPV)); 689 655 } 690 656 691 657 static inline notrace void arch_local_irq_enable(void) 692 658 { 693 - PVOP_VCALLEE0(irq.irq_enable); 659 + PVOP_ALT_VCALLEE0(irq.irq_enable, "sti;", ALT_NOT(X86_FEATURE_XENPV)); 694 660 } 695 661 696 662 static inline notrace unsigned long arch_local_irq_save(void) ··· 736 700 .popsection 737 701 738 702 739 - #define COND_PUSH(set, mask, reg) \ 740 - .if ((~(set)) & mask); push %reg; .endif 741 - #define COND_POP(set, mask, reg) \ 742 - .if ((~(set)) & mask); pop %reg; .endif 743 - 744 703 #ifdef CONFIG_X86_64 745 - 746 - #define PV_SAVE_REGS(set) \ 747 - COND_PUSH(set, CLBR_RAX, rax); \ 748 - COND_PUSH(set, CLBR_RCX, rcx); \ 749 - COND_PUSH(set, CLBR_RDX, rdx); \ 750 - COND_PUSH(set, CLBR_RSI, rsi); \ 751 - COND_PUSH(set, CLBR_RDI, rdi); \ 752 - COND_PUSH(set, CLBR_R8, r8); \ 753 - COND_PUSH(set, CLBR_R9, r9); \ 754 - COND_PUSH(set, CLBR_R10, r10); \ 755 - COND_PUSH(set, CLBR_R11, r11) 756 - #define PV_RESTORE_REGS(set) \ 757 - COND_POP(set, CLBR_R11, r11); \ 758 - COND_POP(set, CLBR_R10, r10); \ 759 - COND_POP(set, CLBR_R9, r9); \ 760 - COND_POP(set, CLBR_R8, r8); \ 761 - COND_POP(set, CLBR_RDI, rdi); \ 762 - COND_POP(set, CLBR_RSI, rsi); \ 763 - COND_POP(set, CLBR_RDX, rdx); \ 764 - COND_POP(set, CLBR_RCX, rcx); \ 765 - COND_POP(set, CLBR_RAX, rax) 704 + #ifdef CONFIG_PARAVIRT_XXL 766 705 767 706 #define PARA_PATCH(off) ((off) / 8) 768 707 #define PARA_SITE(ptype, ops) _PVSITE(ptype, ops, .quad, 8) 769 708 #define PARA_INDIRECT(addr) *addr(%rip) 770 - #else 771 - #define PV_SAVE_REGS(set) \ 772 - COND_PUSH(set, CLBR_EAX, eax); \ 773 - COND_PUSH(set, CLBR_EDI, edi); \ 774 - COND_PUSH(set, CLBR_ECX, ecx); \ 775 - COND_PUSH(set, CLBR_EDX, edx) 776 - #define PV_RESTORE_REGS(set) \ 777 - COND_POP(set, CLBR_EDX, edx); \ 778 - COND_POP(set, CLBR_ECX, ecx); \ 779 - COND_POP(set, CLBR_EDI, edi); \ 780 - COND_POP(set, CLBR_EAX, eax) 781 709 782 - #define PARA_PATCH(off) ((off) / 4) 783 - #define PARA_SITE(ptype, ops) _PVSITE(ptype, ops, .long, 4) 784 - #define PARA_INDIRECT(addr) *%cs:addr 785 - #endif 786 - 787 - #ifdef CONFIG_PARAVIRT_XXL 788 710 #define INTERRUPT_RETURN \ 789 - PARA_SITE(PARA_PATCH(PV_CPU_iret), \ 790 - ANNOTATE_RETPOLINE_SAFE; \ 791 - jmp PARA_INDIRECT(pv_ops+PV_CPU_iret);) 711 + ANNOTATE_RETPOLINE_SAFE; \ 712 + ALTERNATIVE_TERNARY("jmp *paravirt_iret(%rip);", \ 713 + X86_FEATURE_XENPV, "jmp xen_iret;", "jmp native_iret;") 792 714 793 - #define DISABLE_INTERRUPTS(clobbers) \ 794 - PARA_SITE(PARA_PATCH(PV_IRQ_irq_disable), \ 795 - PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ 796 - ANNOTATE_RETPOLINE_SAFE; \ 797 - call PARA_INDIRECT(pv_ops+PV_IRQ_irq_disable); \ 798 - PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) 799 - 800 - #define ENABLE_INTERRUPTS(clobbers) \ 801 - PARA_SITE(PARA_PATCH(PV_IRQ_irq_enable), \ 802 - PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ 803 - ANNOTATE_RETPOLINE_SAFE; \ 804 - call PARA_INDIRECT(pv_ops+PV_IRQ_irq_enable); \ 805 - PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) 806 - #endif 807 - 808 - #ifdef CONFIG_X86_64 809 - #ifdef CONFIG_PARAVIRT_XXL 810 715 #ifdef CONFIG_DEBUG_ENTRY 811 - #define SAVE_FLAGS(clobbers) \ 812 - PARA_SITE(PARA_PATCH(PV_IRQ_save_fl), \ 813 - PV_SAVE_REGS(clobbers | CLBR_CALLEE_SAVE); \ 814 - ANNOTATE_RETPOLINE_SAFE; \ 815 - call PARA_INDIRECT(pv_ops+PV_IRQ_save_fl); \ 816 - PV_RESTORE_REGS(clobbers | CLBR_CALLEE_SAVE);) 716 + .macro PARA_IRQ_save_fl 717 + PARA_SITE(PARA_PATCH(PV_IRQ_save_fl), 718 + ANNOTATE_RETPOLINE_SAFE; 719 + call PARA_INDIRECT(pv_ops+PV_IRQ_save_fl);) 720 + .endm 721 + 722 + #define SAVE_FLAGS ALTERNATIVE "PARA_IRQ_save_fl;", "pushf; pop %rax;", \ 723 + ALT_NOT(X86_FEATURE_XENPV) 817 724 #endif 818 725 #endif /* CONFIG_PARAVIRT_XXL */ 819 726 #endif /* CONFIG_X86_64 */ ··· 776 797 777 798 #ifndef CONFIG_PARAVIRT 778 799 static inline void paravirt_arch_exit_mmap(struct mm_struct *mm) 800 + { 801 + } 802 + #endif 803 + 804 + #ifndef CONFIG_PARAVIRT_SPINLOCKS 805 + static inline void paravirt_set_cap(void) 779 806 { 780 807 } 781 808 #endif
+84 -134
arch/x86/include/asm/paravirt_types.h
··· 3 3 #define _ASM_X86_PARAVIRT_TYPES_H 4 4 5 5 /* Bitmask of what can be clobbered: usually at least eax. */ 6 - #define CLBR_NONE 0 7 6 #define CLBR_EAX (1 << 0) 8 7 #define CLBR_ECX (1 << 1) 9 8 #define CLBR_EDX (1 << 2) ··· 14 15 15 16 #define CLBR_ARG_REGS (CLBR_EAX | CLBR_EDX | CLBR_ECX) 16 17 #define CLBR_RET_REG (CLBR_EAX | CLBR_EDX) 17 - #define CLBR_SCRATCH (0) 18 18 #else 19 19 #define CLBR_RAX CLBR_EAX 20 20 #define CLBR_RCX CLBR_ECX ··· 30 32 #define CLBR_ARG_REGS (CLBR_RDI | CLBR_RSI | CLBR_RDX | \ 31 33 CLBR_RCX | CLBR_R8 | CLBR_R9) 32 34 #define CLBR_RET_REG (CLBR_RAX) 33 - #define CLBR_SCRATCH (CLBR_R10 | CLBR_R11) 34 35 35 36 #endif /* X86_64 */ 36 - 37 - #define CLBR_CALLEE_SAVE ((CLBR_ARG_REGS | CLBR_SCRATCH) & ~CLBR_RET_REG) 38 37 39 38 #ifndef __ASSEMBLY__ 40 39 ··· 68 73 const char *name; 69 74 }; 70 75 71 - struct pv_init_ops { 72 - /* 73 - * Patch may replace one of the defined code sequences with 74 - * arbitrary code, subject to the same register constraints. 75 - * This generally means the code is not free to clobber any 76 - * registers other than EAX. The patch function should return 77 - * the number of bytes of code generated, as we nop pad the 78 - * rest in generic code. 79 - */ 80 - unsigned (*patch)(u8 type, void *insn_buff, 81 - unsigned long addr, unsigned len); 82 - } __no_randomize_layout; 83 - 84 76 #ifdef CONFIG_PARAVIRT_XXL 85 77 struct pv_lazy_ops { 86 78 /* Set deferred update mode, used for batching operations. */ ··· 76 94 void (*flush)(void); 77 95 } __no_randomize_layout; 78 96 #endif 79 - 80 - struct pv_time_ops { 81 - unsigned long long (*sched_clock)(void); 82 - unsigned long long (*steal_clock)(int cpu); 83 - } __no_randomize_layout; 84 97 85 98 struct pv_cpu_ops { 86 99 /* hooks for various privileged instructions */ ··· 132 155 int (*write_msr_safe)(unsigned int msr, unsigned low, unsigned high); 133 156 134 157 u64 (*read_pmc)(int counter); 135 - 136 - /* Normal iret. Jump to this with the standard iret stack 137 - frame set up. */ 138 - void (*iret)(void); 139 158 140 159 void (*start_context_switch)(struct task_struct *prev); 141 160 void (*end_context_switch)(struct task_struct *next); ··· 263 290 * number for each function using the offset which we use to indicate 264 291 * what to patch. */ 265 292 struct paravirt_patch_template { 266 - struct pv_init_ops init; 267 - struct pv_time_ops time; 268 293 struct pv_cpu_ops cpu; 269 294 struct pv_irq_ops irq; 270 295 struct pv_mmu_ops mmu; ··· 271 300 272 301 extern struct pv_info pv_info; 273 302 extern struct paravirt_patch_template pv_ops; 303 + extern void (*paravirt_iret)(void); 274 304 275 305 #define PARAVIRT_PATCH(x) \ 276 306 (offsetof(struct paravirt_patch_template, x) / sizeof(void *)) ··· 303 331 /* Simple instruction patching code. */ 304 332 #define NATIVE_LABEL(a,x,b) "\n\t.globl " a #x "_" #b "\n" a #x "_" #b ":\n\t" 305 333 306 - unsigned paravirt_patch_ident_64(void *insn_buff, unsigned len); 307 - unsigned paravirt_patch_default(u8 type, void *insn_buff, unsigned long addr, unsigned len); 308 - unsigned paravirt_patch_insns(void *insn_buff, unsigned len, const char *start, const char *end); 309 - 310 - unsigned native_patch(u8 type, void *insn_buff, unsigned long addr, unsigned len); 334 + unsigned int paravirt_patch(u8 type, void *insn_buff, unsigned long addr, unsigned int len); 311 335 312 336 int paravirt_disable_iospace(void); 313 337 ··· 382 414 * makes sure the incoming and outgoing types are always correct. 383 415 */ 384 416 #ifdef CONFIG_X86_32 385 - #define PVOP_VCALL_ARGS \ 417 + #define PVOP_CALL_ARGS \ 386 418 unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx; 387 - 388 - #define PVOP_CALL_ARGS PVOP_VCALL_ARGS 389 419 390 420 #define PVOP_CALL_ARG1(x) "a" ((unsigned long)(x)) 391 421 #define PVOP_CALL_ARG2(x) "d" ((unsigned long)(x)) ··· 400 434 #define VEXTRA_CLOBBERS 401 435 #else /* CONFIG_X86_64 */ 402 436 /* [re]ax isn't an arg, but the return val */ 403 - #define PVOP_VCALL_ARGS \ 437 + #define PVOP_CALL_ARGS \ 404 438 unsigned long __edi = __edi, __esi = __esi, \ 405 439 __edx = __edx, __ecx = __ecx, __eax = __eax; 406 - 407 - #define PVOP_CALL_ARGS PVOP_VCALL_ARGS 408 440 409 441 #define PVOP_CALL_ARG1(x) "D" ((unsigned long)(x)) 410 442 #define PVOP_CALL_ARG2(x) "S" ((unsigned long)(x)) ··· 428 464 #define PVOP_TEST_NULL(op) ((void)pv_ops.op) 429 465 #endif 430 466 431 - #define PVOP_RETMASK(rettype) \ 467 + #define PVOP_RETVAL(rettype) \ 432 468 ({ unsigned long __mask = ~0UL; \ 469 + BUILD_BUG_ON(sizeof(rettype) > sizeof(unsigned long)); \ 433 470 switch (sizeof(rettype)) { \ 434 471 case 1: __mask = 0xffUL; break; \ 435 472 case 2: __mask = 0xffffUL; break; \ 436 473 case 4: __mask = 0xffffffffUL; break; \ 437 474 default: break; \ 438 475 } \ 439 - __mask; \ 476 + __mask & __eax; \ 440 477 }) 441 478 442 479 443 - #define ____PVOP_CALL(rettype, op, clbr, call_clbr, extra_clbr, \ 444 - pre, post, ...) \ 480 + #define ____PVOP_CALL(ret, op, clbr, call_clbr, extra_clbr, ...) \ 445 481 ({ \ 446 - rettype __ret; \ 447 482 PVOP_CALL_ARGS; \ 448 483 PVOP_TEST_NULL(op); \ 449 - /* This is 32-bit specific, but is okay in 64-bit */ \ 450 - /* since this condition will never hold */ \ 451 - if (sizeof(rettype) > sizeof(unsigned long)) { \ 452 - asm volatile(pre \ 453 - paravirt_alt(PARAVIRT_CALL) \ 454 - post \ 455 - : call_clbr, ASM_CALL_CONSTRAINT \ 456 - : paravirt_type(op), \ 457 - paravirt_clobber(clbr), \ 458 - ##__VA_ARGS__ \ 459 - : "memory", "cc" extra_clbr); \ 460 - __ret = (rettype)((((u64)__edx) << 32) | __eax); \ 461 - } else { \ 462 - asm volatile(pre \ 463 - paravirt_alt(PARAVIRT_CALL) \ 464 - post \ 465 - : call_clbr, ASM_CALL_CONSTRAINT \ 466 - : paravirt_type(op), \ 467 - paravirt_clobber(clbr), \ 468 - ##__VA_ARGS__ \ 469 - : "memory", "cc" extra_clbr); \ 470 - __ret = (rettype)(__eax & PVOP_RETMASK(rettype)); \ 471 - } \ 472 - __ret; \ 473 - }) 474 - 475 - #define __PVOP_CALL(rettype, op, pre, post, ...) \ 476 - ____PVOP_CALL(rettype, op, CLBR_ANY, PVOP_CALL_CLOBBERS, \ 477 - EXTRA_CLOBBERS, pre, post, ##__VA_ARGS__) 478 - 479 - #define __PVOP_CALLEESAVE(rettype, op, pre, post, ...) \ 480 - ____PVOP_CALL(rettype, op.func, CLBR_RET_REG, \ 481 - PVOP_CALLEE_CLOBBERS, , \ 482 - pre, post, ##__VA_ARGS__) 483 - 484 - 485 - #define ____PVOP_VCALL(op, clbr, call_clbr, extra_clbr, pre, post, ...) \ 486 - ({ \ 487 - PVOP_VCALL_ARGS; \ 488 - PVOP_TEST_NULL(op); \ 489 - asm volatile(pre \ 490 - paravirt_alt(PARAVIRT_CALL) \ 491 - post \ 484 + asm volatile(paravirt_alt(PARAVIRT_CALL) \ 492 485 : call_clbr, ASM_CALL_CONSTRAINT \ 493 486 : paravirt_type(op), \ 494 487 paravirt_clobber(clbr), \ 495 488 ##__VA_ARGS__ \ 496 489 : "memory", "cc" extra_clbr); \ 490 + ret; \ 497 491 }) 498 492 499 - #define __PVOP_VCALL(op, pre, post, ...) \ 500 - ____PVOP_VCALL(op, CLBR_ANY, PVOP_VCALL_CLOBBERS, \ 501 - VEXTRA_CLOBBERS, \ 502 - pre, post, ##__VA_ARGS__) 493 + #define ____PVOP_ALT_CALL(ret, op, alt, cond, clbr, call_clbr, \ 494 + extra_clbr, ...) \ 495 + ({ \ 496 + PVOP_CALL_ARGS; \ 497 + PVOP_TEST_NULL(op); \ 498 + asm volatile(ALTERNATIVE(paravirt_alt(PARAVIRT_CALL), \ 499 + alt, cond) \ 500 + : call_clbr, ASM_CALL_CONSTRAINT \ 501 + : paravirt_type(op), \ 502 + paravirt_clobber(clbr), \ 503 + ##__VA_ARGS__ \ 504 + : "memory", "cc" extra_clbr); \ 505 + ret; \ 506 + }) 503 507 504 - #define __PVOP_VCALLEESAVE(op, pre, post, ...) \ 505 - ____PVOP_VCALL(op.func, CLBR_RET_REG, \ 506 - PVOP_VCALLEE_CLOBBERS, , \ 507 - pre, post, ##__VA_ARGS__) 508 + #define __PVOP_CALL(rettype, op, ...) \ 509 + ____PVOP_CALL(PVOP_RETVAL(rettype), op, CLBR_ANY, \ 510 + PVOP_CALL_CLOBBERS, EXTRA_CLOBBERS, ##__VA_ARGS__) 508 511 512 + #define __PVOP_ALT_CALL(rettype, op, alt, cond, ...) \ 513 + ____PVOP_ALT_CALL(PVOP_RETVAL(rettype), op, alt, cond, CLBR_ANY,\ 514 + PVOP_CALL_CLOBBERS, EXTRA_CLOBBERS, \ 515 + ##__VA_ARGS__) 516 + 517 + #define __PVOP_CALLEESAVE(rettype, op, ...) \ 518 + ____PVOP_CALL(PVOP_RETVAL(rettype), op.func, CLBR_RET_REG, \ 519 + PVOP_CALLEE_CLOBBERS, , ##__VA_ARGS__) 520 + 521 + #define __PVOP_ALT_CALLEESAVE(rettype, op, alt, cond, ...) \ 522 + ____PVOP_ALT_CALL(PVOP_RETVAL(rettype), op.func, alt, cond, \ 523 + CLBR_RET_REG, PVOP_CALLEE_CLOBBERS, , ##__VA_ARGS__) 524 + 525 + 526 + #define __PVOP_VCALL(op, ...) \ 527 + (void)____PVOP_CALL(, op, CLBR_ANY, PVOP_VCALL_CLOBBERS, \ 528 + VEXTRA_CLOBBERS, ##__VA_ARGS__) 529 + 530 + #define __PVOP_ALT_VCALL(op, alt, cond, ...) \ 531 + (void)____PVOP_ALT_CALL(, op, alt, cond, CLBR_ANY, \ 532 + PVOP_VCALL_CLOBBERS, VEXTRA_CLOBBERS, \ 533 + ##__VA_ARGS__) 534 + 535 + #define __PVOP_VCALLEESAVE(op, ...) \ 536 + (void)____PVOP_CALL(, op.func, CLBR_RET_REG, \ 537 + PVOP_VCALLEE_CLOBBERS, , ##__VA_ARGS__) 538 + 539 + #define __PVOP_ALT_VCALLEESAVE(op, alt, cond, ...) \ 540 + (void)____PVOP_ALT_CALL(, op.func, alt, cond, CLBR_RET_REG, \ 541 + PVOP_VCALLEE_CLOBBERS, , ##__VA_ARGS__) 509 542 510 543 511 544 #define PVOP_CALL0(rettype, op) \ 512 - __PVOP_CALL(rettype, op, "", "") 545 + __PVOP_CALL(rettype, op) 513 546 #define PVOP_VCALL0(op) \ 514 - __PVOP_VCALL(op, "", "") 547 + __PVOP_VCALL(op) 548 + #define PVOP_ALT_CALL0(rettype, op, alt, cond) \ 549 + __PVOP_ALT_CALL(rettype, op, alt, cond) 550 + #define PVOP_ALT_VCALL0(op, alt, cond) \ 551 + __PVOP_ALT_VCALL(op, alt, cond) 515 552 516 553 #define PVOP_CALLEE0(rettype, op) \ 517 - __PVOP_CALLEESAVE(rettype, op, "", "") 554 + __PVOP_CALLEESAVE(rettype, op) 518 555 #define PVOP_VCALLEE0(op) \ 519 - __PVOP_VCALLEESAVE(op, "", "") 556 + __PVOP_VCALLEESAVE(op) 557 + #define PVOP_ALT_CALLEE0(rettype, op, alt, cond) \ 558 + __PVOP_ALT_CALLEESAVE(rettype, op, alt, cond) 559 + #define PVOP_ALT_VCALLEE0(op, alt, cond) \ 560 + __PVOP_ALT_VCALLEESAVE(op, alt, cond) 520 561 521 562 522 563 #define PVOP_CALL1(rettype, op, arg1) \ 523 - __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1)) 564 + __PVOP_CALL(rettype, op, PVOP_CALL_ARG1(arg1)) 524 565 #define PVOP_VCALL1(op, arg1) \ 525 - __PVOP_VCALL(op, "", "", PVOP_CALL_ARG1(arg1)) 566 + __PVOP_VCALL(op, PVOP_CALL_ARG1(arg1)) 567 + #define PVOP_ALT_VCALL1(op, arg1, alt, cond) \ 568 + __PVOP_ALT_VCALL(op, alt, cond, PVOP_CALL_ARG1(arg1)) 526 569 527 570 #define PVOP_CALLEE1(rettype, op, arg1) \ 528 - __PVOP_CALLEESAVE(rettype, op, "", "", PVOP_CALL_ARG1(arg1)) 571 + __PVOP_CALLEESAVE(rettype, op, PVOP_CALL_ARG1(arg1)) 529 572 #define PVOP_VCALLEE1(op, arg1) \ 530 - __PVOP_VCALLEESAVE(op, "", "", PVOP_CALL_ARG1(arg1)) 573 + __PVOP_VCALLEESAVE(op, PVOP_CALL_ARG1(arg1)) 574 + #define PVOP_ALT_CALLEE1(rettype, op, arg1, alt, cond) \ 575 + __PVOP_ALT_CALLEESAVE(rettype, op, alt, cond, PVOP_CALL_ARG1(arg1)) 576 + #define PVOP_ALT_VCALLEE1(op, arg1, alt, cond) \ 577 + __PVOP_ALT_VCALLEESAVE(op, alt, cond, PVOP_CALL_ARG1(arg1)) 531 578 532 579 533 580 #define PVOP_CALL2(rettype, op, arg1, arg2) \ 534 - __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1), \ 535 - PVOP_CALL_ARG2(arg2)) 581 + __PVOP_CALL(rettype, op, PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2)) 536 582 #define PVOP_VCALL2(op, arg1, arg2) \ 537 - __PVOP_VCALL(op, "", "", PVOP_CALL_ARG1(arg1), \ 538 - PVOP_CALL_ARG2(arg2)) 539 - 540 - #define PVOP_CALLEE2(rettype, op, arg1, arg2) \ 541 - __PVOP_CALLEESAVE(rettype, op, "", "", PVOP_CALL_ARG1(arg1), \ 542 - PVOP_CALL_ARG2(arg2)) 543 - #define PVOP_VCALLEE2(op, arg1, arg2) \ 544 - __PVOP_VCALLEESAVE(op, "", "", PVOP_CALL_ARG1(arg1), \ 545 - PVOP_CALL_ARG2(arg2)) 546 - 583 + __PVOP_VCALL(op, PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2)) 547 584 548 585 #define PVOP_CALL3(rettype, op, arg1, arg2, arg3) \ 549 - __PVOP_CALL(rettype, op, "", "", PVOP_CALL_ARG1(arg1), \ 586 + __PVOP_CALL(rettype, op, PVOP_CALL_ARG1(arg1), \ 550 587 PVOP_CALL_ARG2(arg2), PVOP_CALL_ARG3(arg3)) 551 588 #define PVOP_VCALL3(op, arg1, arg2, arg3) \ 552 - __PVOP_VCALL(op, "", "", PVOP_CALL_ARG1(arg1), \ 589 + __PVOP_VCALL(op, PVOP_CALL_ARG1(arg1), \ 553 590 PVOP_CALL_ARG2(arg2), PVOP_CALL_ARG3(arg3)) 554 591 555 - /* This is the only difference in x86_64. We can make it much simpler */ 556 - #ifdef CONFIG_X86_32 557 592 #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ 558 593 __PVOP_CALL(rettype, op, \ 559 - "push %[_arg4];", "lea 4(%%esp),%%esp;", \ 560 - PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ 561 - PVOP_CALL_ARG3(arg3), [_arg4] "mr" ((u32)(arg4))) 562 - #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ 563 - __PVOP_VCALL(op, \ 564 - "push %[_arg4];", "lea 4(%%esp),%%esp;", \ 565 - "0" ((u32)(arg1)), "1" ((u32)(arg2)), \ 566 - "2" ((u32)(arg3)), [_arg4] "mr" ((u32)(arg4))) 567 - #else 568 - #define PVOP_CALL4(rettype, op, arg1, arg2, arg3, arg4) \ 569 - __PVOP_CALL(rettype, op, "", "", \ 570 594 PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ 571 595 PVOP_CALL_ARG3(arg3), PVOP_CALL_ARG4(arg4)) 572 596 #define PVOP_VCALL4(op, arg1, arg2, arg3, arg4) \ 573 - __PVOP_VCALL(op, "", "", \ 574 - PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ 597 + __PVOP_VCALL(op, PVOP_CALL_ARG1(arg1), PVOP_CALL_ARG2(arg2), \ 575 598 PVOP_CALL_ARG3(arg3), PVOP_CALL_ARG4(arg4)) 576 - #endif 577 599 578 600 /* Lazy mode for batching updates / context switch */ 579 601 enum paravirt_lazy_mode {
+1 -4
arch/x86/include/asm/smap.h
··· 11 11 12 12 #include <asm/nops.h> 13 13 #include <asm/cpufeatures.h> 14 + #include <asm/alternative.h> 14 15 15 16 /* "Raw" instruction opcodes */ 16 17 #define __ASM_CLAC ".byte 0x0f,0x01,0xca" 17 18 #define __ASM_STAC ".byte 0x0f,0x01,0xcb" 18 19 19 20 #ifdef __ASSEMBLY__ 20 - 21 - #include <asm/alternative-asm.h> 22 21 23 22 #ifdef CONFIG_X86_SMAP 24 23 ··· 35 36 #endif /* CONFIG_X86_SMAP */ 36 37 37 38 #else /* __ASSEMBLY__ */ 38 - 39 - #include <asm/alternative.h> 40 39 41 40 #ifdef CONFIG_X86_SMAP 42 41
+1 -2
arch/x86/kernel/Makefile
··· 35 35 KCSAN_SANITIZE := n 36 36 37 37 OBJECT_FILES_NON_STANDARD_test_nx.o := y 38 - OBJECT_FILES_NON_STANDARD_paravirt_patch.o := y 39 38 40 39 ifdef CONFIG_FRAME_POINTER 41 40 OBJECT_FILES_NON_STANDARD_ftrace_$(BITS).o := y ··· 120 121 obj-$(CONFIG_DEBUG_NMI_SELFTEST) += nmi_selftest.o 121 122 122 123 obj-$(CONFIG_KVM_GUEST) += kvm.o kvmclock.o 123 - obj-$(CONFIG_PARAVIRT) += paravirt.o paravirt_patch.o 124 + obj-$(CONFIG_PARAVIRT) += paravirt.o 124 125 obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= paravirt-spinlocks.o 125 126 obj-$(CONFIG_PARAVIRT_CLOCK) += pvclock.o 126 127 obj-$(CONFIG_X86_PMEM_LEGACY_DEVICE) += pmem.o
+44 -8
arch/x86/kernel/alternative.c
··· 28 28 #include <asm/insn.h> 29 29 #include <asm/io.h> 30 30 #include <asm/fixmap.h> 31 + #include <asm/paravirt.h> 31 32 32 33 int __read_mostly alternatives_patched; 33 34 ··· 389 388 */ 390 389 for (a = start; a < end; a++) { 391 390 int insn_buff_sz = 0; 391 + /* Mask away "NOT" flag bit for feature to test. */ 392 + u16 feature = a->cpuid & ~ALTINSTR_FLAG_INV; 392 393 393 394 instr = (u8 *)&a->instr_offset + a->instr_offset; 394 395 replacement = (u8 *)&a->repl_offset + a->repl_offset; 395 396 BUG_ON(a->instrlen > sizeof(insn_buff)); 396 - BUG_ON(a->cpuid >= (NCAPINTS + NBUGINTS) * 32); 397 - if (!boot_cpu_has(a->cpuid)) { 397 + BUG_ON(feature >= (NCAPINTS + NBUGINTS) * 32); 398 + 399 + /* 400 + * Patch if either: 401 + * - feature is present 402 + * - feature not present but ALTINSTR_FLAG_INV is set to mean, 403 + * patch if feature is *NOT* present. 404 + */ 405 + if (!boot_cpu_has(feature) == !(a->cpuid & ALTINSTR_FLAG_INV)) { 398 406 if (a->padlen > 1) 399 407 optimize_nops(a, instr); 400 408 401 409 continue; 402 410 } 403 411 404 - DPRINTK("feat: %d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d), pad: %d", 405 - a->cpuid >> 5, 406 - a->cpuid & 0x1f, 412 + DPRINTK("feat: %s%d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d), pad: %d", 413 + (a->cpuid & ALTINSTR_FLAG_INV) ? "!" : "", 414 + feature >> 5, 415 + feature & 0x1f, 407 416 instr, instr, a->instrlen, 408 417 replacement, a->replacementlen, a->padlen); 409 418 ··· 616 605 BUG_ON(p->len > MAX_PATCH_LEN); 617 606 /* prep the buffer with the original instructions */ 618 607 memcpy(insn_buff, p->instr, p->len); 619 - used = pv_ops.init.patch(p->type, insn_buff, (unsigned long)p->instr, p->len); 608 + used = paravirt_patch(p->type, insn_buff, (unsigned long)p->instr, p->len); 620 609 621 610 BUG_ON(used > p->len); 622 611 ··· 734 723 * patching. 735 724 */ 736 725 726 + /* 727 + * Paravirt patching and alternative patching can be combined to 728 + * replace a function call with a short direct code sequence (e.g. 729 + * by setting a constant return value instead of doing that in an 730 + * external function). 731 + * In order to make this work the following sequence is required: 732 + * 1. set (artificial) features depending on used paravirt 733 + * functions which can later influence alternative patching 734 + * 2. apply paravirt patching (generally replacing an indirect 735 + * function call with a direct one) 736 + * 3. apply alternative patching (e.g. replacing a direct function 737 + * call with a custom code sequence) 738 + * Doing paravirt patching after alternative patching would clobber 739 + * the optimization of the custom code with a function call again. 740 + */ 741 + paravirt_set_cap(); 742 + 743 + /* 744 + * First patch paravirt functions, such that we overwrite the indirect 745 + * call with the direct call. 746 + */ 747 + apply_paravirt(__parainstructions, __parainstructions_end); 748 + 749 + /* 750 + * Then patch alternatives, such that those paravirt calls that are in 751 + * alternatives can be overwritten by their immediate fragments. 752 + */ 737 753 apply_alternatives(__alt_instructions, __alt_instructions_end); 738 754 739 755 #ifdef CONFIG_SMP ··· 778 740 (unsigned long)__smp_locks_end); 779 741 } 780 742 #endif 781 - 782 - apply_paravirt(__parainstructions, __parainstructions_end); 783 743 784 744 restart_nmi(); 785 745 alternatives_patched = 1;
-7
arch/x86/kernel/asm-offsets.c
··· 61 61 OFFSET(IA32_RT_SIGFRAME_sigcontext, rt_sigframe_ia32, uc.uc_mcontext); 62 62 #endif 63 63 64 - #ifdef CONFIG_PARAVIRT_XXL 65 - BLANK(); 66 - OFFSET(PV_IRQ_irq_disable, paravirt_patch_template, irq.irq_disable); 67 - OFFSET(PV_IRQ_irq_enable, paravirt_patch_template, irq.irq_enable); 68 - OFFSET(PV_CPU_iret, paravirt_patch_template, cpu.iret); 69 - #endif 70 - 71 64 #ifdef CONFIG_XEN 72 65 BLANK(); 73 66 OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask);
+3 -2
arch/x86/kernel/cpu/vmware.c
··· 27 27 #include <linux/clocksource.h> 28 28 #include <linux/cpu.h> 29 29 #include <linux/reboot.h> 30 + #include <linux/static_call.h> 30 31 #include <asm/div64.h> 31 32 #include <asm/x86_init.h> 32 33 #include <asm/hypervisor.h> ··· 337 336 vmware_cyc2ns_setup(); 338 337 339 338 if (vmw_sched_clock) 340 - pv_ops.time.sched_clock = vmware_sched_clock; 339 + paravirt_set_sched_clock(vmware_sched_clock); 341 340 342 341 if (vmware_is_stealclock_available()) { 343 342 has_steal_clock = true; 344 - pv_ops.time.steal_clock = vmware_steal_clock; 343 + static_call_update(pv_steal_clock, vmware_steal_clock); 345 344 346 345 /* We use reboot notifier only to disable steal clock */ 347 346 register_reboot_notifier(&vmware_pv_reboot_nb);
+1 -1
arch/x86/kernel/kvm.c
··· 650 650 651 651 if (kvm_para_has_feature(KVM_FEATURE_STEAL_TIME)) { 652 652 has_steal_clock = 1; 653 - pv_ops.time.steal_clock = kvm_steal_clock; 653 + static_call_update(pv_steal_clock, kvm_steal_clock); 654 654 } 655 655 656 656 if (pv_tlb_flush_supported()) {
+1 -1
arch/x86/kernel/kvmclock.c
··· 106 106 if (!stable) 107 107 clear_sched_clock_stable(); 108 108 kvm_sched_clock_offset = kvm_clock_read(); 109 - pv_ops.time.sched_clock = kvm_sched_clock_read; 109 + paravirt_set_sched_clock(kvm_sched_clock_read); 110 110 111 111 pr_info("kvm-clock: using sched offset of %llu cycles", 112 112 kvm_sched_clock_offset);
+9
arch/x86/kernel/paravirt-spinlocks.c
··· 32 32 return pv_ops.lock.vcpu_is_preempted.func == 33 33 __raw_callee_save___native_vcpu_is_preempted; 34 34 } 35 + 36 + void __init paravirt_set_cap(void) 37 + { 38 + if (!pv_is_native_spin_unlock()) 39 + setup_force_cpu_cap(X86_FEATURE_PVUNLOCK); 40 + 41 + if (!pv_is_native_vcpu_is_preempted()) 42 + setup_force_cpu_cap(X86_FEATURE_VCPUPREEMPT); 43 + }
+19 -56
arch/x86/kernel/paravirt.c
··· 14 14 #include <linux/highmem.h> 15 15 #include <linux/kprobes.h> 16 16 #include <linux/pgtable.h> 17 + #include <linux/static_call.h> 17 18 18 19 #include <asm/bug.h> 19 20 #include <asm/paravirt.h> ··· 53 52 } 54 53 55 54 /* Undefined instruction for dealing with missing ops pointers. */ 56 - static const unsigned char ud2a[] = { 0x0f, 0x0b }; 55 + static void paravirt_BUG(void) 56 + { 57 + BUG(); 58 + } 57 59 58 60 struct branch { 59 61 unsigned char opcode; ··· 89 85 { 90 86 return x; 91 87 } 92 - 93 - static unsigned paravirt_patch_jmp(void *insn_buff, const void *target, 94 - unsigned long addr, unsigned len) 95 - { 96 - struct branch *b = insn_buff; 97 - unsigned long delta = (unsigned long)target - (addr+5); 98 - 99 - if (len < 5) { 100 - #ifdef CONFIG_RETPOLINE 101 - WARN_ONCE(1, "Failing to patch indirect JMP in %ps\n", (void *)addr); 102 - #endif 103 - return len; /* call too long for patch site */ 104 - } 105 - 106 - b->opcode = 0xe9; /* jmp */ 107 - b->delta = delta; 108 - 109 - return 5; 110 - } 111 88 #endif 112 89 113 90 DEFINE_STATIC_KEY_TRUE(virt_spin_lock_key); ··· 99 114 static_branch_disable(&virt_spin_lock_key); 100 115 } 101 116 102 - unsigned paravirt_patch_default(u8 type, void *insn_buff, 103 - unsigned long addr, unsigned len) 117 + unsigned int paravirt_patch(u8 type, void *insn_buff, unsigned long addr, 118 + unsigned int len) 104 119 { 105 120 /* 106 121 * Neat trick to map patch type back to the call within the ··· 110 125 unsigned ret; 111 126 112 127 if (opfunc == NULL) 113 - /* If there's no function, patch it with a ud2a (BUG) */ 114 - ret = paravirt_patch_insns(insn_buff, len, ud2a, ud2a+sizeof(ud2a)); 128 + /* If there's no function, patch it with paravirt_BUG() */ 129 + ret = paravirt_patch_call(insn_buff, paravirt_BUG, addr, len); 115 130 else if (opfunc == _paravirt_nop) 116 131 ret = 0; 117 - 118 - #ifdef CONFIG_PARAVIRT_XXL 119 - /* identity functions just return their single argument */ 120 - else if (opfunc == _paravirt_ident_64) 121 - ret = paravirt_patch_ident_64(insn_buff, len); 122 - 123 - else if (type == PARAVIRT_PATCH(cpu.iret)) 124 - /* If operation requires a jmp, then jmp */ 125 - ret = paravirt_patch_jmp(insn_buff, opfunc, addr, len); 126 - #endif 127 132 else 128 133 /* Otherwise call the function. */ 129 134 ret = paravirt_patch_call(insn_buff, opfunc, addr, len); 130 135 131 136 return ret; 132 - } 133 - 134 - unsigned paravirt_patch_insns(void *insn_buff, unsigned len, 135 - const char *start, const char *end) 136 - { 137 - unsigned insn_len = end - start; 138 - 139 - /* Alternative instruction is too large for the patch site and we cannot continue: */ 140 - BUG_ON(insn_len > len || start == NULL); 141 - 142 - memcpy(insn_buff, start, insn_len); 143 - 144 - return insn_len; 145 137 } 146 138 147 139 struct static_key paravirt_steal_enabled; ··· 127 165 static u64 native_steal_clock(int cpu) 128 166 { 129 167 return 0; 168 + } 169 + 170 + DEFINE_STATIC_CALL(pv_steal_clock, native_steal_clock); 171 + DEFINE_STATIC_CALL(pv_sched_clock, native_sched_clock); 172 + 173 + void paravirt_set_sched_clock(u64 (*func)(void)) 174 + { 175 + static_call_update(pv_sched_clock, func); 130 176 } 131 177 132 178 /* These are in entry.S */ ··· 239 269 #define PTE_IDENT __PV_IS_CALLEE_SAVE(_paravirt_ident_64) 240 270 241 271 struct paravirt_patch_template pv_ops = { 242 - /* Init ops. */ 243 - .init.patch = native_patch, 244 - 245 - /* Time ops. */ 246 - .time.sched_clock = native_sched_clock, 247 - .time.steal_clock = native_steal_clock, 248 - 249 272 /* Cpu ops. */ 250 273 .cpu.io_delay = native_io_delay, 251 274 ··· 270 307 .cpu.free_ldt = paravirt_nop, 271 308 272 309 .cpu.load_sp0 = native_load_sp0, 273 - 274 - .cpu.iret = native_iret, 275 310 276 311 #ifdef CONFIG_X86_IOPL_IOPERM 277 312 .cpu.invalidate_io_bitmap = native_tss_invalidate_io_bitmap, ··· 375 414 NOKPROBE_SYMBOL(native_get_debugreg); 376 415 NOKPROBE_SYMBOL(native_set_debugreg); 377 416 NOKPROBE_SYMBOL(native_load_idt); 417 + 418 + void (*paravirt_iret)(void) = native_iret; 378 419 #endif 379 420 380 421 EXPORT_SYMBOL(pv_ops);
-99
arch/x86/kernel/paravirt_patch.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - #include <linux/stringify.h> 3 - 4 - #include <asm/paravirt.h> 5 - #include <asm/asm-offsets.h> 6 - 7 - #define PSTART(d, m) \ 8 - patch_data_##d.m 9 - 10 - #define PEND(d, m) \ 11 - (PSTART(d, m) + sizeof(patch_data_##d.m)) 12 - 13 - #define PATCH(d, m, insn_buff, len) \ 14 - paravirt_patch_insns(insn_buff, len, PSTART(d, m), PEND(d, m)) 15 - 16 - #define PATCH_CASE(ops, m, data, insn_buff, len) \ 17 - case PARAVIRT_PATCH(ops.m): \ 18 - return PATCH(data, ops##_##m, insn_buff, len) 19 - 20 - #ifdef CONFIG_PARAVIRT_XXL 21 - struct patch_xxl { 22 - const unsigned char irq_irq_disable[1]; 23 - const unsigned char irq_irq_enable[1]; 24 - const unsigned char irq_save_fl[2]; 25 - const unsigned char mmu_read_cr2[3]; 26 - const unsigned char mmu_read_cr3[3]; 27 - const unsigned char mmu_write_cr3[3]; 28 - const unsigned char cpu_wbinvd[2]; 29 - const unsigned char mov64[3]; 30 - }; 31 - 32 - static const struct patch_xxl patch_data_xxl = { 33 - .irq_irq_disable = { 0xfa }, // cli 34 - .irq_irq_enable = { 0xfb }, // sti 35 - .irq_save_fl = { 0x9c, 0x58 }, // pushf; pop %[re]ax 36 - .mmu_read_cr2 = { 0x0f, 0x20, 0xd0 }, // mov %cr2, %[re]ax 37 - .mmu_read_cr3 = { 0x0f, 0x20, 0xd8 }, // mov %cr3, %[re]ax 38 - .mmu_write_cr3 = { 0x0f, 0x22, 0xdf }, // mov %rdi, %cr3 39 - .cpu_wbinvd = { 0x0f, 0x09 }, // wbinvd 40 - .mov64 = { 0x48, 0x89, 0xf8 }, // mov %rdi, %rax 41 - }; 42 - 43 - unsigned int paravirt_patch_ident_64(void *insn_buff, unsigned int len) 44 - { 45 - return PATCH(xxl, mov64, insn_buff, len); 46 - } 47 - # endif /* CONFIG_PARAVIRT_XXL */ 48 - 49 - #ifdef CONFIG_PARAVIRT_SPINLOCKS 50 - struct patch_lock { 51 - unsigned char queued_spin_unlock[3]; 52 - unsigned char vcpu_is_preempted[2]; 53 - }; 54 - 55 - static const struct patch_lock patch_data_lock = { 56 - .vcpu_is_preempted = { 0x31, 0xc0 }, // xor %eax, %eax 57 - 58 - # ifdef CONFIG_X86_64 59 - .queued_spin_unlock = { 0xc6, 0x07, 0x00 }, // movb $0, (%rdi) 60 - # else 61 - .queued_spin_unlock = { 0xc6, 0x00, 0x00 }, // movb $0, (%eax) 62 - # endif 63 - }; 64 - #endif /* CONFIG_PARAVIRT_SPINLOCKS */ 65 - 66 - unsigned int native_patch(u8 type, void *insn_buff, unsigned long addr, 67 - unsigned int len) 68 - { 69 - switch (type) { 70 - 71 - #ifdef CONFIG_PARAVIRT_XXL 72 - PATCH_CASE(irq, save_fl, xxl, insn_buff, len); 73 - PATCH_CASE(irq, irq_enable, xxl, insn_buff, len); 74 - PATCH_CASE(irq, irq_disable, xxl, insn_buff, len); 75 - 76 - PATCH_CASE(mmu, read_cr2, xxl, insn_buff, len); 77 - PATCH_CASE(mmu, read_cr3, xxl, insn_buff, len); 78 - PATCH_CASE(mmu, write_cr3, xxl, insn_buff, len); 79 - 80 - PATCH_CASE(cpu, wbinvd, xxl, insn_buff, len); 81 - #endif 82 - 83 - #ifdef CONFIG_PARAVIRT_SPINLOCKS 84 - case PARAVIRT_PATCH(lock.queued_spin_unlock): 85 - if (pv_is_native_spin_unlock()) 86 - return PATCH(lock, queued_spin_unlock, insn_buff, len); 87 - break; 88 - 89 - case PARAVIRT_PATCH(lock.vcpu_is_preempted): 90 - if (pv_is_native_vcpu_is_preempted()) 91 - return PATCH(lock, vcpu_is_preempted, insn_buff, len); 92 - break; 93 - #endif 94 - default: 95 - break; 96 - } 97 - 98 - return paravirt_patch_default(type, insn_buff, addr, len); 99 - }
+2 -1
arch/x86/kernel/tsc.c
··· 14 14 #include <linux/percpu.h> 15 15 #include <linux/timex.h> 16 16 #include <linux/static_key.h> 17 + #include <linux/static_call.h> 17 18 18 19 #include <asm/hpet.h> 19 20 #include <asm/timer.h> ··· 255 254 256 255 bool using_native_sched_clock(void) 257 256 { 258 - return pv_ops.time.sched_clock == native_sched_clock; 257 + return static_call_query(pv_sched_clock) == native_sched_clock; 259 258 } 260 259 #else 261 260 unsigned long long
+1 -1
arch/x86/lib/atomic64_386_32.S
··· 6 6 */ 7 7 8 8 #include <linux/linkage.h> 9 - #include <asm/alternative-asm.h> 9 + #include <asm/alternative.h> 10 10 11 11 /* if you want SMP support, implement these with real spinlocks */ 12 12 .macro LOCK reg
+1 -1
arch/x86/lib/atomic64_cx8_32.S
··· 6 6 */ 7 7 8 8 #include <linux/linkage.h> 9 - #include <asm/alternative-asm.h> 9 + #include <asm/alternative.h> 10 10 11 11 .macro read64 reg 12 12 movl %ebx, %eax
+1 -1
arch/x86/lib/copy_page_64.S
··· 3 3 4 4 #include <linux/linkage.h> 5 5 #include <asm/cpufeatures.h> 6 - #include <asm/alternative-asm.h> 6 + #include <asm/alternative.h> 7 7 #include <asm/export.h> 8 8 9 9 /*
+1 -1
arch/x86/lib/copy_user_64.S
··· 11 11 #include <asm/asm-offsets.h> 12 12 #include <asm/thread_info.h> 13 13 #include <asm/cpufeatures.h> 14 - #include <asm/alternative-asm.h> 14 + #include <asm/alternative.h> 15 15 #include <asm/asm.h> 16 16 #include <asm/smap.h> 17 17 #include <asm/export.h>
+1 -1
arch/x86/lib/memcpy_64.S
··· 4 4 #include <linux/linkage.h> 5 5 #include <asm/errno.h> 6 6 #include <asm/cpufeatures.h> 7 - #include <asm/alternative-asm.h> 7 + #include <asm/alternative.h> 8 8 #include <asm/export.h> 9 9 10 10 .pushsection .noinstr.text, "ax"
+1 -1
arch/x86/lib/memmove_64.S
··· 8 8 */ 9 9 #include <linux/linkage.h> 10 10 #include <asm/cpufeatures.h> 11 - #include <asm/alternative-asm.h> 11 + #include <asm/alternative.h> 12 12 #include <asm/export.h> 13 13 14 14 #undef memmove
+1 -1
arch/x86/lib/memset_64.S
··· 3 3 4 4 #include <linux/linkage.h> 5 5 #include <asm/cpufeatures.h> 6 - #include <asm/alternative-asm.h> 6 + #include <asm/alternative.h> 7 7 #include <asm/export.h> 8 8 9 9 /*
+1 -1
arch/x86/lib/retpoline.S
··· 4 4 #include <linux/linkage.h> 5 5 #include <asm/dwarf2.h> 6 6 #include <asm/cpufeatures.h> 7 - #include <asm/alternative-asm.h> 7 + #include <asm/alternative.h> 8 8 #include <asm/export.h> 9 9 #include <asm/nospec-branch.h> 10 10 #include <asm/unwind_hints.h>
+1 -3
arch/x86/xen/enlighten_pv.c
··· 1070 1070 1071 1071 .read_pmc = xen_read_pmc, 1072 1072 1073 - .iret = xen_iret, 1074 - 1075 1073 .load_tr_desc = paravirt_nop, 1076 1074 .set_ldt = xen_set_ldt, 1077 1075 .load_gdt = xen_load_gdt, ··· 1230 1232 1231 1233 /* Install Xen paravirt ops */ 1232 1234 pv_info = xen_info; 1233 - pv_ops.init.patch = paravirt_patch_default; 1234 1235 pv_ops.cpu = xen_cpu_ops; 1236 + paravirt_iret = xen_iret; 1235 1237 xen_init_irq_ops(); 1236 1238 1237 1239 /*
+13 -13
arch/x86/xen/time.c
··· 379 379 } 380 380 } 381 381 382 - static const struct pv_time_ops xen_time_ops __initconst = { 383 - .sched_clock = xen_sched_clock, 384 - .steal_clock = xen_steal_clock, 385 - }; 386 - 387 382 static struct pvclock_vsyscall_time_info *xen_clock __read_mostly; 388 383 static u64 xen_clock_value_saved; 389 384 ··· 520 525 pvclock_gtod_register_notifier(&xen_pvclock_gtod_notifier); 521 526 } 522 527 523 - void __init xen_init_time_ops(void) 528 + static void __init xen_init_time_common(void) 524 529 { 525 530 xen_sched_clock_offset = xen_clocksource_read(); 526 - pv_ops.time = xen_time_ops; 531 + static_call_update(pv_steal_clock, xen_steal_clock); 532 + paravirt_set_sched_clock(xen_sched_clock); 533 + 534 + x86_platform.calibrate_tsc = xen_tsc_khz; 535 + x86_platform.get_wallclock = xen_get_wallclock; 536 + } 537 + 538 + void __init xen_init_time_ops(void) 539 + { 540 + xen_init_time_common(); 527 541 528 542 x86_init.timers.timer_init = xen_time_init; 529 543 x86_init.timers.setup_percpu_clockev = x86_init_noop; 530 544 x86_cpuinit.setup_percpu_clockev = x86_init_noop; 531 545 532 - x86_platform.calibrate_tsc = xen_tsc_khz; 533 - x86_platform.get_wallclock = xen_get_wallclock; 534 546 /* Dom0 uses the native method to set the hardware RTC. */ 535 547 if (!xen_initial_domain()) 536 548 x86_platform.set_wallclock = xen_set_wallclock; ··· 571 569 return; 572 570 } 573 571 574 - xen_sched_clock_offset = xen_clocksource_read(); 575 - pv_ops.time = xen_time_ops; 572 + xen_init_time_common(); 573 + 576 574 x86_init.timers.setup_percpu_clockev = xen_time_init; 577 575 x86_cpuinit.setup_percpu_clockev = xen_hvm_setup_cpu_clockevents; 578 576 579 - x86_platform.calibrate_tsc = xen_tsc_khz; 580 - x86_platform.get_wallclock = xen_get_wallclock; 581 577 x86_platform.set_wallclock = xen_set_wallclock; 582 578 } 583 579 #endif
+2 -1
drivers/xen/time.c
··· 7 7 #include <linux/math64.h> 8 8 #include <linux/gfp.h> 9 9 #include <linux/slab.h> 10 + #include <linux/static_call.h> 10 11 11 12 #include <asm/paravirt.h> 12 13 #include <asm/xen/hypervisor.h> ··· 176 175 xen_runstate_remote = !HYPERVISOR_vm_assist(VMASST_CMD_enable, 177 176 VMASST_TYPE_runstate_update_flag); 178 177 179 - pv_ops.time.steal_clock = xen_steal_clock; 178 + static_call_update(pv_steal_clock, xen_steal_clock); 180 179 181 180 static_key_slow_inc(&paravirt_steal_enabled); 182 181 if (xen_runstate_remote)
+8 -18
include/linux/static_call.h
··· 20 20 * static_call(name)(args...); 21 21 * static_call_cond(name)(args...); 22 22 * static_call_update(name, func); 23 + * static_call_query(name); 23 24 * 24 25 * Usage example: 25 26 * ··· 92 91 * 93 92 * which will include the required value tests to avoid NULL-pointer 94 93 * dereferences. 94 + * 95 + * To query which function is currently set to be called, use: 96 + * 97 + * func = static_call_query(name); 95 98 */ 96 99 97 100 #include <linux/types.h> ··· 123 118 STATIC_CALL_TRAMP_ADDR(name), func); \ 124 119 }) 125 120 121 + #define static_call_query(name) (READ_ONCE(STATIC_CALL_KEY(name).func)) 122 + 126 123 #ifdef CONFIG_HAVE_STATIC_CALL_INLINE 127 124 128 125 extern int __init static_call_init(void); ··· 133 126 struct static_call_mod *next; 134 127 struct module *mod; /* for vmlinux, mod == NULL */ 135 128 struct static_call_site *sites; 136 - }; 137 - 138 - struct static_call_key { 139 - void *func; 140 - union { 141 - /* bit 0: 0 = mods, 1 = sites */ 142 - unsigned long type; 143 - struct static_call_mod *mods; 144 - struct static_call_site *sites; 145 - }; 146 129 }; 147 130 148 131 /* For finding the key associated with a trampoline */ ··· 184 187 185 188 static inline int static_call_init(void) { return 0; } 186 189 187 - struct static_call_key { 188 - void *func; 189 - }; 190 - 191 190 #define __DEFINE_STATIC_CALL(name, _func, _func_init) \ 192 191 DECLARE_STATIC_CALL(name, _func); \ 193 192 struct static_call_key STATIC_CALL_KEY(name) = { \ ··· 197 204 .func = NULL, \ 198 205 }; \ 199 206 ARCH_DEFINE_STATIC_CALL_NULL_TRAMP(name) 207 + 200 208 201 209 #define static_call_cond(name) (void)__static_call(name) 202 210 ··· 236 242 #else /* Generic implementation */ 237 243 238 244 static inline int static_call_init(void) { return 0; } 239 - 240 - struct static_call_key { 241 - void *func; 242 - }; 243 245 244 246 static inline long __static_call_return0(void) 245 247 {
+18
include/linux/static_call_types.h
··· 58 58 __raw_static_call(name); \ 59 59 }) 60 60 61 + struct static_call_key { 62 + void *func; 63 + union { 64 + /* bit 0: 0 = mods, 1 = sites */ 65 + unsigned long type; 66 + struct static_call_mod *mods; 67 + struct static_call_site *sites; 68 + }; 69 + }; 70 + 61 71 #else /* !CONFIG_HAVE_STATIC_CALL_INLINE */ 62 72 63 73 #define __STATIC_CALL_ADDRESSABLE(name) 64 74 #define __static_call(name) __raw_static_call(name) 75 + 76 + struct static_call_key { 77 + void *func; 78 + }; 65 79 66 80 #endif /* CONFIG_HAVE_STATIC_CALL_INLINE */ 67 81 ··· 90 76 #define static_call(name) __static_call(name) 91 77 92 78 #else 79 + 80 + struct static_call_key { 81 + void *func; 82 + }; 93 83 94 84 #define static_call(name) \ 95 85 ((typeof(STATIC_CALL_TRAMP(name))*)(STATIC_CALL_KEY(name).func))
+18
tools/include/linux/static_call_types.h
··· 58 58 __raw_static_call(name); \ 59 59 }) 60 60 61 + struct static_call_key { 62 + void *func; 63 + union { 64 + /* bit 0: 0 = mods, 1 = sites */ 65 + unsigned long type; 66 + struct static_call_mod *mods; 67 + struct static_call_site *sites; 68 + }; 69 + }; 70 + 61 71 #else /* !CONFIG_HAVE_STATIC_CALL_INLINE */ 62 72 63 73 #define __STATIC_CALL_ADDRESSABLE(name) 64 74 #define __static_call(name) __raw_static_call(name) 75 + 76 + struct static_call_key { 77 + void *func; 78 + }; 65 79 66 80 #endif /* CONFIG_HAVE_STATIC_CALL_INLINE */ 67 81 ··· 90 76 #define static_call(name) __static_call(name) 91 77 92 78 #else 79 + 80 + struct static_call_key { 81 + void *func; 82 + }; 93 83 94 84 #define static_call(name) \ 95 85 ((typeof(STATIC_CALL_TRAMP(name))*)(STATIC_CALL_KEY(name).func))