- /*
-
* The actual transition into protected mode
-
*/
-
-
#include
-
#include
-
#include
-
#include
-
-
.text
-
.code16
-
-
/*
-
* void protected_mode_jump(u32 entrypoint, u32 bootparams); 这里的entrypoint就是32位kernel启动代码的入口,通过code32_start传入,bootparams是已经整理好的32位的线性地址,不需要进一步转换转换。eax是entrypoint,edx是bootparams。
-
*/
-
GLOBAL(protected_mode_jump)
-
movl %edx, %esi # Pointer to boot_params table //保存boot_params的指针
-
-
xorl %ebx, %ebx
-
movw %cs, %bx
-
shll $4, %ebx //ebx里面是实模式启动代码所用到的空间上限
-
addl %ebx, 2f //2f位置的内容是指向in_pm32的相对位移,调整该位移以指向in_pm32在实际内存中的地址。
-
jmp 1f # Short jump to serialize on 386/486
-
1:
//_BOOT_DS和_BOOT_TSS在arch/x86/include/asm/Segment.h里面定义。
-
movw $__BOOT_DS, %cx
-
movw $__BOOT_TSS, %di
-
-
movl %cr0, %edx
-
orb $X86_CR0_PE, %dl # Protected mode
-
movl %edx, %cr0 //CR0的保护模式置位
-
-
# Transition to 32-bit mode。//跳转到in_pm32,设置完CR0之后必须使用长跳转来使CPU进入保护模式。
-
.byte 0x66, 0xea # ljmpl opcode
-
2: .long in_pm32 # offset
-
.word __BOOT_CS # segment
-
ENDPROC(protected_mode_jump)
-
-
.code32
-
.section ".text32","ax"
-
GLOBAL(in_pm32)
-
# Set up data segments for flat 32-bit mode
- //
初始化数据段,ecx=_BOOT_DS,是在go_to_protected_mode里面设定的DS的选择字。是相对于GDT头的位移量。在
arch/x86/include/asm/Segment.h里面定义。实际上这个选择字指向的是0-4G的所有内存空间,和CS是一样的。
-
movl %ecx, %ds
-
movl %ecx, %es
-
movl %ecx, %fs
-
movl %ecx, %gs
-
movl %ecx, %ss
-
# The 32-bit code sets up its own stack, but this way we do have
-
# a valid stack if some debugging hack wants to use it.
-
addl %ebx, %esp //初始化堆栈。将原先实模式启动代码的空间全部用作堆栈。
-
-
# Set up TR to make Intel VT happy
-
ltr %di //设置Task Stack Segment. %di里面是TSS的选择字。该选择字在GDT里,
-
-
# Clear registers to allow for future extensions to the
-
# 32-bit boot protocol
-
xorl %ecx, %ecx
-
xorl %edx, %edx
-
xorl %ebx, %ebx
-
xorl %ebp, %ebp
-
xorl %edi, %edi
-
-
# Set up LDTR to make Intel VT happy
-
lldt %cx //将LDTR设为0
-
-
jmpl *%eax # Jump to the 32-bit entrypoint //让我们跳到code32_start吧。
-
ENDPROC(in_pm32)