让我们现在开始Start Kernel: i386_start_kernel
来源:互联网 发布:散兵坑公式源码 编辑:程序博客网 时间:2024/05/24 01:34
http://blog.chinaunix.net/uid-1701789-id-161409.html
Kernel是从header_32.S里面跳转到i386_start_kernel的。回忆一下在进入i386_start_kernel之前已经建立起来的运行环境:
1. CR3已经指向PMD或者PT的起始地址。
2. PMD或者PT已经完全建立起来,其所指向的页框已经覆盖了从0起始到_end+MAPPING_BEYOND_END的空间。
3. GDT已经指向了gdt_page
4. LDT为空
5. IDT已经初始化
6. boot_params已经保存在0xC0000000以上的空间
7. 堆栈已经建立
8. CPU已经进入保护模式,并且启用了页面。
在以上的基础上,来看看kernel的启动还将怎样进行:
i386_start_kernel在arch/x86/kernel/header32.c里面,代码如下:
- void __init i386_start_kernel(void)
- {
- memblock_init();
- #ifdef CONFIG_X86_TRAMPOLINE
- /*
- * But first pinch a few for the stack/trampoline stuff
- * FIXME: Don't need the extra page at 4K, but need to fix
- * trampoline before removing it. (see the GDT stuff)
- */
- memblock_x86_reserve_range(PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE");
- #endif
- memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS"); //保留kernel本身
- #ifdef CONFIG_BLK_DEV_INITRD
- /* Reserve INITRD */
- if (boot_params.hdr.type_of_loader && boot_params.hdr.ramdisk_image) {
- /* Assume only end is not page aligned */
- u64 ramdisk_image = boot_params.hdr.ramdisk_image;
- u64 ramdisk_size = boot_params.hdr.ramdisk_size;
- u64 ramdisk_end = PAGE_ALIGN(ramdisk_image + ramdisk_size);
- memblock_x86_reserve_range(ramdisk_image, ramdisk_end, "RAMDISK"); //如果使用initrd,则将boot_params.hdr.ramdisk_image指向的initrd空间进行保留。
- }
- #endif
- /* Call the subarch specific early setup function */
- switch (boot_params.hdr.hardware_subarch) {
- case X86_SUBARCH_MRST:
- x86_mrst_early_setup();
- break;
- default:
- i386_default_early_setup();
- break;
- }
- /*
- * At this point everything still needed from the boot loader
- * or BIOS or kernel text should be early reserved or marked not
- * RAM in e820. All other memory is free game.
- */
- start_kernel();
- }
1. memblock_init()在mm/Memblock.c里面被定义。其作用就是初始化memblock这个结构。memblock包含两个重要的成员,分别是memblock.memory和memblock.reserved.其分别代表系统中可用的内存和已经被保留的内存。
memblock.memory和memblock.reserved被定义为以下结构:
- struct memblock_type {
- unsigned long cnt; /* number of regions */
- unsigned long max; /* size of the allocated array */
- struct memblock_region *regions;
- };
在初始化的时候,memblock.memory和memblock.reserved分别被指向两个静态数组:
- static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS + 1] __initdata_memblock;
- static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS + 1] __initdata_memblock;
2. memblock_x86_reserve_range(u64 start, u64 end, char * name)的作用是将起始地址为start, 终止地址为end的内存块标注为系统保留,其结果就是在memblock.reserved中增加一个region.
所以kernel一共建立了三块系统保留的空间。第一是tramponline, 第二是initrd所使用的空间,第三是kernel本身。
3. i386_default_early_setup如下所述初始化了x86_init这个结构的一部分。
- static void __init i386_default_early_setup(void)
- {
- /* Initialize 32bit specific setup functions */
- x86_init.resources.probe_roms = probe_roms;
- x86_init.resources.reserve_resources = i386_reserve_resources;
- x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc;
- reserve_ebda_region();
- }
x86_init的结构和相关结构在arch/x86/include/asm/X86_init.h中定义,详细的解释可以参考这个文件中的注解。它已经写得很清楚了。
- /**
- * struct x86_init_ops - functions for platform specific setup
- *
- */
- struct x86_init_ops {
- struct x86_init_resources resources;
- struct x86_init_mpparse mpparse;
- struct x86_init_irqs irqs;
- struct x86_init_oem oem;
- struct x86_init_paging paging;
- struct x86_init_timers timers;
- struct x86_init_iommu iommu;
- struct x86_init_pci pci;
- };
reserve_ebda_region的作用是保留给PS/2设备使用的EBDA( Extended BIOS Data Area )空间。由于低地址空间实际上是映射到0xC0000000上面去了,所以其保留的空间实际上是基于0xC0000000的虚拟地址。
关于start_kernel.明天再看吧
0 0
- 让我们现在开始Start Kernel: i386_start_kernel
- 现在开始,从这里出发......;Start from here now!
- 让我们开始吧
- 让我们开始吧
- 现在开始
- 现在开始!
- 现在开始
- 现在开始
- 现在开始
- 开始-start
- 开始start
- 写在开始,现在开始
- android Kernel Start
- start kernel flow
- ARM Kernel Start Process
- linux start kernel
- 努力从现在开始
- 从现在开始!
- 解读startx
- 《视频解密》中文版(第四版)第九章NTSC和PAL数字编码和解码(第一部分)
- 再次进入startup_32: 初始化页表
- DLL动态库开发一二
- NSDate转本地时间
- 让我们现在开始Start Kernel: i386_start_kernel
- 《视频解密》中文版(第四版)第九章NTSC和PAL数字编码和解码(第二部分)
- 最快的排序方法(快归堆希)
- Redis 常见的性能问题和解决方法
- Start_Kernel之一 ------勇敢的猜想和胡言乱语
- 求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字。例如2+22+222+2222+22222(此时共有5个数相加),几个数相加有键盘控制。
- 【Structure(结构体)杂谈】Structure(结构体)杂谈系列文章第一季pdf文件
- Linux Epoll介绍和程序实例
- 一个测试理解什么是主、辅LRU(oracle cuug)