···1818#include <linux/reboot.h>1919#include <linux/slab.h>2020#include <linux/types.h>2121+#include <linux/static_call.h>21222223#include <asm/paravirt.h>2324#include <asm/pvclock-abi.h>···2726struct static_key paravirt_steal_enabled;2827struct static_key paravirt_steal_rq_enabled;29283030-struct paravirt_patch_template pv_ops;3131-EXPORT_SYMBOL_GPL(pv_ops);2929+static u64 native_steal_clock(int cpu)3030+{3131+ return 0;3232+}3333+3434+DEFINE_STATIC_CALL(pv_steal_clock, native_steal_clock);32353336struct pv_time_stolen_time_region {3437 struct pvclock_vcpu_stolen_time *kaddr;···5045early_param("no-steal-acc", parse_no_stealacc);51465247/* return stolen time in ns by asking the hypervisor */5353-static u64 pv_steal_clock(int cpu)4848+static u64 para_steal_clock(int cpu)5449{5550 struct pv_time_stolen_time_region *reg;5651···155150 if (ret)156151 return ret;157152158158- pv_ops.time.steal_clock = pv_steal_clock;153153+ static_call_update(pv_steal_clock, para_steal_clock);159154160155 static_key_slow_inc(¶virt_steal_enabled);161156 if (steal_acc)
+1
arch/x86/Kconfig
···774774775775config PARAVIRT776776 bool "Enable paravirtualization code"777777+ depends on HAVE_STATIC_CALL777778 help778779 This changes the kernel so it can modify itself when it is run779780 under a hypervisor, potentially improving performance significantly
+3-3
arch/x86/entry/entry_32.S
···4040#include <asm/processor-flags.h>4141#include <asm/irq_vectors.h>4242#include <asm/cpufeatures.h>4343-#include <asm/alternative-asm.h>4343+#include <asm/alternative.h>4444#include <asm/asm.h>4545#include <asm/smap.h>4646#include <asm/frame.h>···349349 * will soon execute iret and the tracer was already set to350350 * the irqstate after the IRET:351351 */352352- DISABLE_INTERRUPTS(CLBR_ANY)352352+ cli353353 lss (%esp), %esp /* switch to espfix segment */354354.Lend_\@:355355#endif /* CONFIG_X86_ESPFIX32 */···994994 * when returning from IPI handler and when returning from995995 * scheduler to user-space.996996 */997997- INTERRUPT_RETURN997997+ iret998998999999.section .fixup, "ax"10001000SYM_CODE_START(asm_iret_error)
···11-/* SPDX-License-Identifier: GPL-2.0 */22-#ifndef _ASM_X86_ALTERNATIVE_ASM_H33-#define _ASM_X86_ALTERNATIVE_ASM_H44-55-#ifdef __ASSEMBLY__66-77-#include <asm/asm.h>88-99-#ifdef CONFIG_SMP1010- .macro LOCK_PREFIX1111-672: lock1212- .pushsection .smp_locks,"a"1313- .balign 41414- .long 672b - .1515- .popsection1616- .endm1717-#else1818- .macro LOCK_PREFIX1919- .endm2020-#endif2121-2222-/*2323- * objtool annotation to ignore the alternatives and only consider the original2424- * instruction(s).2525- */2626-.macro ANNOTATE_IGNORE_ALTERNATIVE2727- .Lannotate_\@:2828- .pushsection .discard.ignore_alts2929- .long .Lannotate_\@ - .3030- .popsection3131-.endm3232-3333-/*3434- * Issue one struct alt_instr descriptor entry (need to put it into3535- * the section .altinstructions, see below). This entry contains3636- * enough information for the alternatives patching code to patch an3737- * instruction. See apply_alternatives().3838- */3939-.macro altinstruction_entry orig alt feature orig_len alt_len pad_len4040- .long \orig - .4141- .long \alt - .4242- .word \feature4343- .byte \orig_len4444- .byte \alt_len4545- .byte \pad_len4646-.endm4747-4848-/*4949- * Define an alternative between two instructions. If @feature is5050- * present, early code in apply_alternatives() replaces @oldinstr with5151- * @newinstr. ".skip" directive takes care of proper instruction padding5252- * in case @newinstr is longer than @oldinstr.5353- */5454-.macro ALTERNATIVE oldinstr, newinstr, feature5555-140:5656- \oldinstr5757-141:5858- .skip -(((144f-143f)-(141b-140b)) > 0) * ((144f-143f)-(141b-140b)),0x905959-142:6060-6161- .pushsection .altinstructions,"a"6262- altinstruction_entry 140b,143f,\feature,142b-140b,144f-143f,142b-141b6363- .popsection6464-6565- .pushsection .altinstr_replacement,"ax"6666-143:6767- \newinstr6868-144:6969- .popsection7070-.endm7171-7272-#define old_len 141b-140b7373-#define new_len1 144f-143f7474-#define new_len2 145f-144f7575-7676-/*7777- * gas compatible max based on the idea from:7878- * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax7979- *8080- * The additional "-" is needed because gas uses a "true" value of -1.8181- */8282-#define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))8383-8484-8585-/*8686- * Same as ALTERNATIVE macro above but for two alternatives. If CPU8787- * has @feature1, it replaces @oldinstr with @newinstr1. If CPU has8888- * @feature2, it replaces @oldinstr with @feature2.8989- */9090-.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature29191-140:9292- \oldinstr9393-141:9494- .skip -((alt_max_short(new_len1, new_len2) - (old_len)) > 0) * \9595- (alt_max_short(new_len1, new_len2) - (old_len)),0x909696-142:9797-9898- .pushsection .altinstructions,"a"9999- altinstruction_entry 140b,143f,\feature1,142b-140b,144f-143f,142b-141b100100- altinstruction_entry 140b,144f,\feature2,142b-140b,145f-144f,142b-141b101101- .popsection102102-103103- .pushsection .altinstr_replacement,"ax"104104-143:105105- \newinstr1106106-144:107107- \newinstr2108108-145:109109- .popsection110110-.endm111111-112112-#endif /* __ASSEMBLY__ */113113-114114-#endif /* _ASM_X86_ALTERNATIVE_ASM_H */
+132-10
arch/x86/include/asm/alternative.h
···22#ifndef _ASM_X86_ALTERNATIVE_H33#define _ASM_X86_ALTERNATIVE_H4455-#ifndef __ASSEMBLY__66-75#include <linux/types.h>88-#include <linux/stddef.h>96#include <linux/stringify.h>107#include <asm/asm.h>88+99+#define ALTINSTR_FLAG_INV (1 << 15)1010+#define ALT_NOT(feat) ((feat) | ALTINSTR_FLAG_INV)1111+1212+#ifndef __ASSEMBLY__1313+1414+#include <linux/stddef.h>11151216/*1317 * Alternative inline assembly for SMP.···154150 " .byte " alt_rlen(num) "\n" /* replacement len */ \155151 " .byte " alt_pad_len "\n" /* pad len */156152157157-#define ALTINSTR_REPLACEMENT(newinstr, feature, num) /* replacement */ \153153+#define ALTINSTR_REPLACEMENT(newinstr, num) /* replacement */ \158154 "# ALT: replacement " #num "\n" \159155 b_replacement(num)":\n\t" newinstr "\n" e_replacement(num) ":\n"160156···165161 ALTINSTR_ENTRY(feature, 1) \166162 ".popsection\n" \167163 ".pushsection .altinstr_replacement, \"ax\"\n" \168168- ALTINSTR_REPLACEMENT(newinstr, feature, 1) \164164+ ALTINSTR_REPLACEMENT(newinstr, 1) \169165 ".popsection\n"170166171167#define ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2)\···175171 ALTINSTR_ENTRY(feature2, 2) \176172 ".popsection\n" \177173 ".pushsection .altinstr_replacement, \"ax\"\n" \178178- ALTINSTR_REPLACEMENT(newinstr1, feature1, 1) \179179- ALTINSTR_REPLACEMENT(newinstr2, feature2, 2) \174174+ ALTINSTR_REPLACEMENT(newinstr1, 1) \175175+ ALTINSTR_REPLACEMENT(newinstr2, 2) \180176 ".popsection\n"177177+178178+/* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */179179+#define ALTERNATIVE_TERNARY(oldinstr, feature, newinstr_yes, newinstr_no) \180180+ ALTERNATIVE_2(oldinstr, newinstr_no, X86_FEATURE_ALWAYS, \181181+ newinstr_yes, feature)181182182183#define ALTERNATIVE_3(oldinsn, newinsn1, feat1, newinsn2, feat2, newinsn3, feat3) \183184 OLDINSTR_3(oldinsn, 1, 2, 3) \···192183 ALTINSTR_ENTRY(feat3, 3) \193184 ".popsection\n" \194185 ".pushsection .altinstr_replacement, \"ax\"\n" \195195- ALTINSTR_REPLACEMENT(newinsn1, feat1, 1) \196196- ALTINSTR_REPLACEMENT(newinsn2, feat2, 2) \197197- ALTINSTR_REPLACEMENT(newinsn3, feat3, 3) \186186+ ALTINSTR_REPLACEMENT(newinsn1, 1) \187187+ ALTINSTR_REPLACEMENT(newinsn2, 2) \188188+ ALTINSTR_REPLACEMENT(newinsn3, 3) \198189 ".popsection\n"199190200191/*···214205215206#define alternative_2(oldinstr, newinstr1, feature1, newinstr2, feature2) \216207 asm_inline volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory")208208+209209+#define alternative_ternary(oldinstr, feature, newinstr_yes, newinstr_no) \210210+ asm_inline volatile(ALTERNATIVE_TERNARY(oldinstr, feature, newinstr_yes, newinstr_no) ::: "memory")217211218212/*219213 * Alternative inline assembly with input.···282270 * alternative_{input,io,call}()283271 */284272#define ASM_NO_INPUT_CLOBBER(clbr...) "i" (0) : clbr273273+274274+#else /* __ASSEMBLY__ */275275+276276+#ifdef CONFIG_SMP277277+ .macro LOCK_PREFIX278278+672: lock279279+ .pushsection .smp_locks,"a"280280+ .balign 4281281+ .long 672b - .282282+ .popsection283283+ .endm284284+#else285285+ .macro LOCK_PREFIX286286+ .endm287287+#endif288288+289289+/*290290+ * objtool annotation to ignore the alternatives and only consider the original291291+ * instruction(s).292292+ */293293+.macro ANNOTATE_IGNORE_ALTERNATIVE294294+ .Lannotate_\@:295295+ .pushsection .discard.ignore_alts296296+ .long .Lannotate_\@ - .297297+ .popsection298298+.endm299299+300300+/*301301+ * Issue one struct alt_instr descriptor entry (need to put it into302302+ * the section .altinstructions, see below). This entry contains303303+ * enough information for the alternatives patching code to patch an304304+ * instruction. See apply_alternatives().305305+ */306306+.macro altinstruction_entry orig alt feature orig_len alt_len pad_len307307+ .long \orig - .308308+ .long \alt - .309309+ .word \feature310310+ .byte \orig_len311311+ .byte \alt_len312312+ .byte \pad_len313313+.endm314314+315315+/*316316+ * Define an alternative between two instructions. If @feature is317317+ * present, early code in apply_alternatives() replaces @oldinstr with318318+ * @newinstr. ".skip" directive takes care of proper instruction padding319319+ * in case @newinstr is longer than @oldinstr.320320+ */321321+.macro ALTERNATIVE oldinstr, newinstr, feature322322+140:323323+ \oldinstr324324+141:325325+ .skip -(((144f-143f)-(141b-140b)) > 0) * ((144f-143f)-(141b-140b)),0x90326326+142:327327+328328+ .pushsection .altinstructions,"a"329329+ altinstruction_entry 140b,143f,\feature,142b-140b,144f-143f,142b-141b330330+ .popsection331331+332332+ .pushsection .altinstr_replacement,"ax"333333+143:334334+ \newinstr335335+144:336336+ .popsection337337+.endm338338+339339+#define old_len 141b-140b340340+#define new_len1 144f-143f341341+#define new_len2 145f-144f342342+343343+/*344344+ * gas compatible max based on the idea from:345345+ * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax346346+ *347347+ * The additional "-" is needed because gas uses a "true" value of -1.348348+ */349349+#define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))350350+351351+352352+/*353353+ * Same as ALTERNATIVE macro above but for two alternatives. If CPU354354+ * has @feature1, it replaces @oldinstr with @newinstr1. If CPU has355355+ * @feature2, it replaces @oldinstr with @feature2.356356+ */357357+.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2358358+140:359359+ \oldinstr360360+141:361361+ .skip -((alt_max_short(new_len1, new_len2) - (old_len)) > 0) * \362362+ (alt_max_short(new_len1, new_len2) - (old_len)),0x90363363+142:364364+365365+ .pushsection .altinstructions,"a"366366+ altinstruction_entry 140b,143f,\feature1,142b-140b,144f-143f,142b-141b367367+ altinstruction_entry 140b,144f,\feature2,142b-140b,145f-144f,142b-141b368368+ .popsection369369+370370+ .pushsection .altinstr_replacement,"ax"371371+143:372372+ \newinstr1373373+144:374374+ \newinstr2375375+145:376376+ .popsection377377+.endm378378+379379+/* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */380380+#define ALTERNATIVE_TERNARY(oldinstr, feature, newinstr_yes, newinstr_no) \381381+ ALTERNATIVE_2 oldinstr, newinstr_no, X86_FEATURE_ALWAYS, \382382+ newinstr_yes, feature285383286384#endif /* __ASSEMBLY__ */287385
···2828#include <asm/insn.h>2929#include <asm/io.h>3030#include <asm/fixmap.h>3131+#include <asm/paravirt.h>31323233int __read_mostly alternatives_patched;3334···389388 */390389 for (a = start; a < end; a++) {391390 int insn_buff_sz = 0;391391+ /* Mask away "NOT" flag bit for feature to test. */392392+ u16 feature = a->cpuid & ~ALTINSTR_FLAG_INV;392393393394 instr = (u8 *)&a->instr_offset + a->instr_offset;394395 replacement = (u8 *)&a->repl_offset + a->repl_offset;395396 BUG_ON(a->instrlen > sizeof(insn_buff));396396- BUG_ON(a->cpuid >= (NCAPINTS + NBUGINTS) * 32);397397- if (!boot_cpu_has(a->cpuid)) {397397+ BUG_ON(feature >= (NCAPINTS + NBUGINTS) * 32);398398+399399+ /*400400+ * Patch if either:401401+ * - feature is present402402+ * - feature not present but ALTINSTR_FLAG_INV is set to mean,403403+ * patch if feature is *NOT* present.404404+ */405405+ if (!boot_cpu_has(feature) == !(a->cpuid & ALTINSTR_FLAG_INV)) {398406 if (a->padlen > 1)399407 optimize_nops(a, instr);400408401409 continue;402410 }403411404404- DPRINTK("feat: %d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d), pad: %d",405405- a->cpuid >> 5,406406- a->cpuid & 0x1f,412412+ DPRINTK("feat: %s%d*32+%d, old: (%pS (%px) len: %d), repl: (%px, len: %d), pad: %d",413413+ (a->cpuid & ALTINSTR_FLAG_INV) ? "!" : "",414414+ feature >> 5,415415+ feature & 0x1f,407416 instr, instr, a->instrlen,408417 replacement, a->replacementlen, a->padlen);409418···616605 BUG_ON(p->len > MAX_PATCH_LEN);617606 /* prep the buffer with the original instructions */618607 memcpy(insn_buff, p->instr, p->len);619619- used = pv_ops.init.patch(p->type, insn_buff, (unsigned long)p->instr, p->len);608608+ used = paravirt_patch(p->type, insn_buff, (unsigned long)p->instr, p->len);620609621610 BUG_ON(used > p->len);622611···734723 * patching.735724 */736725726726+ /*727727+ * Paravirt patching and alternative patching can be combined to728728+ * replace a function call with a short direct code sequence (e.g.729729+ * by setting a constant return value instead of doing that in an730730+ * external function).731731+ * In order to make this work the following sequence is required:732732+ * 1. set (artificial) features depending on used paravirt733733+ * functions which can later influence alternative patching734734+ * 2. apply paravirt patching (generally replacing an indirect735735+ * function call with a direct one)736736+ * 3. apply alternative patching (e.g. replacing a direct function737737+ * call with a custom code sequence)738738+ * Doing paravirt patching after alternative patching would clobber739739+ * the optimization of the custom code with a function call again.740740+ */741741+ paravirt_set_cap();742742+743743+ /*744744+ * First patch paravirt functions, such that we overwrite the indirect745745+ * call with the direct call.746746+ */747747+ apply_paravirt(__parainstructions, __parainstructions_end);748748+749749+ /*750750+ * Then patch alternatives, such that those paravirt calls that are in751751+ * alternatives can be overwritten by their immediate fragments.752752+ */737753 apply_alternatives(__alt_instructions, __alt_instructions_end);738754739755#ifdef CONFIG_SMP···778740 (unsigned long)__smp_locks_end);779741 }780742#endif781781-782782- apply_paravirt(__parainstructions, __parainstructions_end);783743784744 restart_nmi();785745 alternatives_patched = 1;
···1414#include <linux/percpu.h>1515#include <linux/timex.h>1616#include <linux/static_key.h>1717+#include <linux/static_call.h>17181819#include <asm/hpet.h>1920#include <asm/timer.h>···255254256255bool using_native_sched_clock(void)257256{258258- return pv_ops.time.sched_clock == native_sched_clock;257257+ return static_call_query(pv_sched_clock) == native_sched_clock;259258}260259#else261260unsigned long long
+1-1
arch/x86/lib/atomic64_386_32.S
···66 */7788#include <linux/linkage.h>99-#include <asm/alternative-asm.h>99+#include <asm/alternative.h>10101111/* if you want SMP support, implement these with real spinlocks */1212.macro LOCK reg