3.3.4 设置BIOS的x86模式
继续走,下一个函数,set_bios_mode(),跟main来自同一个文件:
94/* 95 * Tell the BIOS what CPU mode we intend to run in. 96 */ 97static void set_bios_mode(void) 98{ 99#ifdef CONFIG_I386 100 struct biosregs ireg; 101 102 initregs(&ireg); 103 ireg.ax = 0xec00; 104 ireg.bx = 2; 105 intcall(0x15, &ireg, NULL); 106#endif 107} |
当然,set_bios_mode函数只针对i386,用于告诉BIOS什么CPU我们将要去运行。对于x86_64来说,是个空函数。这个过程如何处理呢?看到105行,这个intcall是初始化阶段的中断处理函数(牢记,初始化阶段至此,仍然处于实模式阶段,Linux内核的中断系统还没有被初始化,这个函数是内核编译后临时生成的一个bios服务程序,跟前面header.S中的那些int指令效果是一样的),就是将BIOS的寄存器设置成ireg变量。该变量分别针对32位、16位和8位而声明称以下一些联合体:(arch/x86/boot/Boot.h)
struct biosregs { union { struct { u32 edi; u32 esi; u32 ebp; u32 _esp; u32 ebx; u32 edx; u32 ecx; u32 eax; u32 _fsgs; u32 _dses; u32 eflags; }; struct { u16 di, hdi; u16 si, hsi; u16 bp, hbp; u16 _sp, _hsp; u16 bx, hbx; u16 dx, hdx; u16 cx, hcx; u16 ax, hax; u16 gs, fs; u16 es, ds; u16 flags, hflags; }; struct { u8 dil, dih, edi2, edi3; u8 sil, sih, esi2, esi3; u8 bpl, bph, ebp2, ebp3; u8 _spl, _sph, _esp2, _esp3; u8 bl, bh, ebx2, ebx3; u8 dl, dh, edx2, edx3; u8 cl, ch, ecx2, ecx3; u8 al, ah, eax2, eax3; }; }; }; |
当然,102行的initregs()函数是用来做一般初始化的:
void initregs(struct biosregs *reg) { memset(reg, 0, sizeof *reg); reg->eflags |= X86_EFLAGS_CF; reg->ds = ds(); reg->es = ds(); reg->fs = fs(); reg->gs = gs(); } |
我把它贴出来的目的主要是为了说明一下ds()等函数,用来获取段寄存器:
static inline u16 ds(void)
{
u16 seg;
asm("movw %%ds,%0" : "=rm" (seg));
return seg;
}