Это из исходного кода Linux arch/arm64/kernel/head.S, показывающего запуск ядра. Код сначала вызывает preserve_boot_args
, а затем вызывает el2_setup
, используя bl
(ветка и ссылка). Я также показал процедуру preserve_boot_args
.
SYM_CODE_START(primary_entry)
bl preserve_boot_args
bl el2_setup // Drop to EL1, w0=cpu_boot_mode
adrp x23, __PHYS_OFFSET
and x23, x23, MIN_KIMG_ALIGN - 1 // KASLR offset, defaults to 0
bl set_cpu_boot_mode_flag
bl __create_page_tables
/*
* The following calls CPU setup code, see arch/arm64/mm/proc.S for
* details.
* On return, the CPU will be ready for the MMU to be turned on and
* the TCR will have been set.
*/
bl __cpu_setup // initialise processor
b __primary_switch
SYM_CODE_END(primary_entry)
SYM_CODE_START_LOCAL(preserve_boot_args)
mov x21, x0 // x21=FDT
adr_l x0, boot_args // record the contents of
stp x21, x1, [x0] // x0 .. x3 at kernel entry
stp x2, x3, [x0, #16]
dmb sy // needed before dc ivac with
// MMU off
mov x1, #0x20 // 4 x 8 bytes
b __inval_dcache_area // tail call
SYM_CODE_END(preserve_boot_args)
Насколько я понимаю, bl
для вызова процедуры (после процедуры возврат по адресу, хранящемуся в lr - регистре ссылок, x30), а b
просто идет по помеченному адресу без возврата. Но в процедуре preserve_boot_args
выше, в самом конце, есть инструкция b __inval_dcache_area
, которая просто переходит к __inval_dcache_area
без возврата. Тогда как он возвращается к исходному коду (где bl el2_setup
)? А чем завершается сама процедура? Определение SYM_CODE_END выглядит следующим образом:
#define SYM_END(name, sym_type) \
.type name sym_type ASM_NL \
.size name, .-name
#endif
Я не могу понять, как этот код заставляет его вернуться по адресу в lr
. Разве мы не должны сделать что-то вроде mv pc, lr
?