3.3.2 初始化堆
回到main函数,第二个函数,init_heap(),用来检查内核初始化阶段使用的堆:
109static void init_heap(void) 110{ 111 char *stack_end; 112 113 if (boot_params.hdr.loadflags & CAN_USE_HEAP) { 114 asm("leal %P1(%%esp),%0" 115 : "=r" (stack_end) : "i" (-STACK_SIZE)); 116 117 heap_end = (char *) 118 ((size_t)boot_params.hdr.heap_end_ptr + 0x200); 119 if (heap_end > stack_end) 120 heap_end = stack_end; 121 } else { 122 /* Boot protocol 2.00 only, no heap available */ 123 puts("WARNING: Ancient bootloader, some functionality " 124 "may be limited!/n"); 125 } 126} |
这个函数也简单,跟我们在“准备实模式下c语言环境”中一样,hdr字段的loadflags标记如果CAN_USE_HEAP被置位,则说明本体系支持堆。我们这里用的x86最新的协议时支持的,所以进入if分支。If分支内检查堆的大小,不能益出,如果发现溢出,就调整到stack_end。
3.3.3 确保支持当前运行的CPU
看过了init_heap函数,我们继续看第三个函数,validate_cpu():
35int validate_cpu(void) 36{ 37 u32 *err_flags; 38 int cpu_level, req_level; 39 const unsigned char *msg_strs; 40 41 check_cpu(&cpu_level, &req_level, &err_flags); 42 43 if (cpu_level < req_level) { 44 printf("This kernel requires an %s CPU, ", 45 cpu_name(req_level)); 46 printf("but only detected an %s CPU./n", 47 cpu_name(cpu_level)); 48 return -1; 49 } 50 51 if (err_flags) { 52 int i, j; 53 puts("This kernel requires the following features " 54 "not present on the CPU:/n"); 55 56 msg_strs = (const unsigned char *)x86_cap_strs; 57 58 for (i = 0; i < NCAPINTS; i++) { 59 u32 e = err_flags[i]; 60 61 for (j = 0; j < 32; j++) { 62 if (msg_strs[0] < i || 63 (msg_strs[0] == i && msg_strs[1] < j)) { 64 /* Skip to the next string */ 65 msg_strs += 2; 66 while (*msg_strs++) 67 ; 68 } 69 if (e & 1) { 70 if (msg_strs[0] == i && 71 msg_strs[1] == j && 72 msg_strs[2]) 73 printf("%s ", msg_strs+2); 74 else 75 printf("%d:%d ", i, j); 76 } 77 e >>= 1; 78 } 79 } 80 putchar('/n'); 81 return -1; 82 } else { 83 return 0; 84 } 85} |
这个函数也比较简单,注意第41行,check_cpu,通过指令读取cpu的信息,存放在cpu_level、req_level和err_flags三个内部变量中。req_level表示内核需要运行的CPU最低版本,cpu_level表示系统实际的CPU版本,当然,如果cpu_level < req_level,那自然就报错啦。至于具体用了哪些汇编指令,自己去/arch/x86/boot/Cpucheck.c中看,这里不在话下。