根据板子里面的启动信息,cat /proc/kmsg,对着代码看。
start_kernel函数分析
1. set_task_stack_end_magic(&init_task);
抽取关键部分
//找到栈顶位置并设置个魔术字,防止堆栈 将 thread_info 的数据覆盖;
//如果是向上生长的栈,直接通过(task_thread_info + 8K - 1)找到栈底并设置魔术字
//内核栈大小一般为4K或者8K.
set_task_stack_end_magic(&init_task);
stackend = end_of_stack(tsk);
return (unsigned long *)(task_thread_info(p) + 1);
*stackend = STACK_END_MAGIC; // 0x57AC6E9D
//宏定义了就是向上生长
static inline unsigned long *end_of_stack(struct task_struct *p)
{
#ifdef CONFIG_STACK_GROWSUP
return (unsigned long *)((unsigned long)task_thread_info(p) + THREAD_SIZE) - 1;
#else
return (unsigned long *)(task_thread_info(p) + 1);
#endif
}
(栈向下生长的情况)
(栈向上生长的情况)
2. smp_setup_processor_id
int i;
u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0;
u32 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
cpu_logical_map(0) = cpu;
for (i = 1; i < nr_cpu_ids; ++i)
cpu_logical_map(i) = i == cpu ? 0 : i;
/*
* clear __my_cpu_offset on boot CPU to avoid hang caused by
* using percpu variable early, for example, lockdep will
* access percpu variable inside lock_release
*/
set_my_cpu_offset(0);
pr_info("Booting Linux on physical CPU 0x%x\n", mpidr);
先通过is_smp()函数判断是否为smp处理器
static inline bool is_smp(void)
{
#ifndef CONFIG_SMP
return false;
#elif defined(CONFIG_SMP_ON_UP)
extern unsigned int smp_on_up;
return !!smp_on_up;
#else
return true;
#endif
}
我的是imx6ull板子,不是对称多处理器,这里宏没定义,直接返回false。
所以mpidr 为0
3. local_irq_disable
暂时禁止本地中断, 设置完相关的东西后再开启
// 禁止本地中断
local_irq_disable
raw_local_irq_disable
arch_local_irq_disable
4. boot_cpu_init
初始化 Boot CPU
// 设置boot cpu
boot_cpu_init
smp_processor_id
raw_smp_processor_id
current_thread_info()->cpu
set_cpu_online
set_cpu_active
set_cpu_present
set_cpu_possible
5.page_address_init
初始化高端内存线性地址中永久映射的全局变量.IMX6ULL这里的宏没开,所以这里应该是空
page_address_init
// page_address_htable 是个全局结构体数组,
for (i = 0; i < ARRAY_SIZE(page_address_htable); i++)
INIT_LIST_HEAD(&page_address_htable[i].lh);
spin_lock_init(&page_address_htable[i].lock);
6.pr_notice("%s", linux_banner);
linux_banner 字符串保存了 linux 版本号,编译主机,GCC 版本,编译 时间等信息。在开机过程中可以看到log
/* FIXED STRINGS! Don't touc.h! */
const char linux_banner[] =
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
以下是编译生成的文件,路径在include\generated\compile.h
#define UTS_MACHINE "arm"
#define UTS_VERSION "#9 SMP PREEMPT Sat Dec 25 20:49:44 CST 2021"
#define LINUX_COMPILE_BY "zrc"
#define LINUX_COMPILE_HOST "zrc"
#define LINUX_COMPILER "gcc version 4.9.4 (Linaro GCC 4.9-2017.01) "
7. setup_arch
初始化体系相关的部分,实现与体系和芯片有关
// 初始化体系相关的部分,实现与体系和芯片有关
setup_arch(&command_line)
setup_processor(); // 从硬件获得体系相关的信息,并将该信息用于系统的初始化
// __atags_pointer 指向 DTB 所在的物理地址
mdesc = setup_machine_fdt(__atags_pointer)
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有