以aarch64平台__kern_hyp_va为例:
ALTERNATIVE_CB("and %0, %0, #1\n"
"ror %0, %0, #1\n"
"add %0, %0, #0\n"
"add %0, %0, #0, lsl 12\n"
"ror %0, %0, #63\n",
kvm_update_va_mask)
展开后最终为:
.if 1 == 1
661:
and %0, %0, #1
ror %0, %0, #1
add %0, %0, #0
add %0, %0, #0, lsl 12
ror %0, %0, #63
662:
.pushsection .altinstructions,"a"
.word 661b - . /* label */
.word kvm_update_va_mask - . /* callback */
.hword ARM64_NCAPS /* feature bit */
.byte 662b-661b /* source len */
.byte 664f-663f
.popsection
663:
664:
.endif
启动中会执行alt动作:
apply_boot_alternatives
__apply_alternatives
关键过程是:
origptr = ALT_ORIG_PTR(alt);
updptr = is_module ? origptr : lm_alias(origptr);
nr_inst = alt->orig_len / AARCH64_INSN_SIZE;
if (alt->cpufeature < ARM64_CB_PATCH)
alt_cb = patch_alternative;
else
alt_cb = ALT_REPL_PTR(alt);
alt_cb(alt, origptr, updptr, nr_inst);
重点是origptr = ALT_ORIG_PTR(alt)语句,最终展开后为:
(void *)&alt->alt_offset + alt->alt_offset
alt是altinstructions代码段的起始地址,alt->alt_offset存的是替换函数距此的偏移值,因此(void *)&alt->alt_offset等于这条语句的地址
.word kvm_update_va_mask - . /* callback */
因此,这条语句的地址加上语句的内容(kvm_update_va_mask距这条语句的偏移)
(void *)&alt->alt_offset + alt->alt_offset
就等于kvm_update_va_mask函数的地址,找到地址,就可以调用了
alt_cb(alt, origptr, updptr, nr_inst);