64bit Environment and Mode Switching

1, Concepts:

CS.L
L (long) flag in Code Segment entry of GDT or LDT, indicating long mode

CS.D
D (doubleword) flag in Code Segment entry of GDT or LDT, indicating protected mode

.code32
Indicating a 32bit code segment

.code64
Indicating a 64bit code segment

EFER
Extended Feature Enable Register, a special configuration register for 64bit machine.

EFER.LME
Long Mode Enable flag in EFER, when enabled, the CPU works in either compatibility
mode or long mode.
Disabling paging also disables EFER.LME.

EFER.LMA
Long Mode Activity flag in EFER, when enabled, the CPU works in long mode.
Setting CS.L=1 also sets EFER.LMA=1, and clearing CS.L also clears EFER.LMA.

PAE
Page Address Extension, a flag in cr4, when enabled, the CPU can access more than 4GB
memory, it is required by compatibility mode and long mode.

PGE
Page Global Enable, a flag in cr4, when enabled, a page can have Global Page attribute
so that it will stay in cache as long as the cache size is allow.
This flag is only available in 64 bit machine.

Compatibility Mode
When a CPU runs in .code32, has EFER.LME=1 and CS.L=0 (CS.D=1), it works in
compatibility mode. This is a transition mode that can execute both 64 bit instructions
32 bit ones.

Long Mode
When a CPU runs in .code64, has EFER.LME=1 and CS.L=1 (CS.D=0), it works in Long mode.
In this mode, all instructions and addressings are interpreted as 64 bit long.

Identity Mapping
A page mapping that maps a virtual address to the same physical address, this mapping is
required in mode switching that involves paging.

 

2, Registers

In 64 bit mode (compatibility mode or long mode), all accessible registers include:

64 bit registers:
rax, rbx, rcx, rdx, r8, r9, r10, r11, r12, r13, r14, r15, rsi, rdi, rsp, rbp

All config registers become 64 bits:
cr0~cr4, cr8 (64bit mode only, Task Priority Register (TPR))

32 bit registers:
eax, ebx, ecx, edx, esi, edi, esp, ebp

All segment registers are also 32 bits, but their content has no effect,
note that they should not be used to prefix an address in long mode.
cs, ds, es, ss, fs, gs

16 bit registers:
ax, bx, cx, dx, si, di, sp, bp

8 bit registers:
ah, al, bh, bl, ch, cl, dh, dl


Among them,
    rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp
are extended from
    eax, ebx, ecx, edx, esi, edi, esp, ebp
respectively.

  But everytime when the lower 32bit register is loaded with a new value, the higher
32bit will be cleared, this is very important in programming.

 

 

3, 64 bit parameter passing in GCC

All parameters are extended to 64 bit before passing, the order is:
 rdi, rsi, rdx, rcx, r8, r9, r10, ...

For example, in assembly code, one can call a C function this way:

This is the prototype of a C function:
 void printk_at(int x, int y, int color, int attr, char *fmt, ...);

This is the method to call that function in NASM format:

 extern printk_at

 teststr   db   'The value of EDI is %d/n', 0

 call printk_at in function code:
  push_all                ; a macro to push all common registers
  mov     eax, edi
  mov     edi, 0          ; x
  mov     esi, 21         ; y
  mov     edx, 7          ; white color
  mov     ecx, 0          ; black background
  mov     r8, teststr     ; display string
  mov     r9, rax         ; value, only eax will be used
  call    printk_at
  pop_all                 ; a macro to pop all common registers

 

 


4, Alignment issue
In assembly code, all 64 bit data should be aligned to 64 bit boundary, or else a
write to it (with MOV instruction) will cause the machine to reboot.
In C, all data are aligned automatically by compiler.

 

 

5, Switching from protected mode to long mode

 1) Enable PAE and PGE in cr4
  xorl %eax, %eax
  btsl $5, %eax     # PAE: Page Address Extension
  btsl $7, %eax     # PGE: Page Global Enable
  movl %eax, %cr4

 2) Load pagetable in cr3, the page mapping must be an identity mapping.
  movl $pgtable, %eax # address of 4 level page table
  movl %eax, %cr3

 3) Setup EFER, so that when paging is enabled,
    we will be in compatibility mode

  movl $MSR_EFER, %ecx  # MSR_EFER = 0xc0000080
  rdmsr
  /* Fool rdmsr and reset %eax to avoid dependences */
  xorl %eax, %eax
  btsl $_EFER_LME, %eax # _EFER_LME = 8, Enable Long Mode
  btsl $_EFER_SCE, %eax # _EFER_SCE = 0, Enable System Call

  btl $20,%edi
  jnc     1f
  btsl $_EFER_NX, %eax   /* _EFER_NX = 11, No Execute supported? */
  1:

  wrmsr  /* Make changes effective */

 4) Enable paging and other flags in cr0
  xorl %eax, %eax
  btsl $31, %eax  # Enable paging
  btsl $0,  %eax  # Enable protected mode
  btsl $1,  %eax  # Enable MP
  btsl $4,  %eax  # Enable ET
  btsl $5,  %eax  # Enable NE
  btsl $16, %eax  # Enable WP
  btsl $18, %eax  # Enable AM
  movl %eax, %cr0 # Make changes effective

 5) Use a long jump to make flags effective, now we are in compatibility mode

 6) Load 64 bit GDT and IDT and long-jump to 64 bit long mode in .code64 segment

  lgdt pGDT64   # CS.L = 1, CS.D = 0
  lidt pIDT64

  /* set up data segments. actually 0 would do too */
  movl $KERNEL_DS,%eax
  movl %eax,%ds
  movl %eax,%ss
  movl %eax,%es

  movl    $long_mode_ptr, %eax # located in .code64 segment
  ljmp *(%eax)          # Finally jump in 64bit long mode

 

 


6, Switching back from long mode to protected mode

 1) Disable interrupt and MNI
  cli   # no interrupts allowed !
  movb $0x80, %al # disable NMI
  outb %al, $0x70

 2) Use a long jump to jump into .code32 segment
  
  movl    $reach_code32_ptr, %eax
  ljmp *(%eax)          # Jump in .code32 segment

 3) Load 32bit GDT and IDT, and long jump to compatibility mode
  /*
   * MUST load GDT with CS.L=0 and ljmp before clearing cr0.PG
   */
  movl $idt_32, %eax
  lidt (%eax)   # load idt with 0,0
  movl $gdt_32, %eax
  lgdt (%eax)   # load 32 bit gdt, CS.L=0, CS.D=1

  /* Jump to compatibility mode */
  movl    $reach_compat_ptr, %eax
  ljmp *(%eax)            # EFER.LMA is automatically cleared

 4) Clear page flag in cr0 to disable paging, and jump to protected mode

  /* Reload 32 bit segment reigsters */
  movl $KERNEL_DS, %eax
  movl %eax, %ds
  movl %eax, %es
  movl %eax, %ss

  movl %cr0, %eax
  andl $0x7fffffff, %eax    # set cr0.PG=0
  movl %eax, %cr0

  /* Disable Long Mode in EFER.
   * According to Intel menual, this is not necessary,
   * but I need to be more assured
   */
  movl $MSR_EFER, %ecx  # MSR_EFER = 0xc0000080
  rdmsr
  btrl $_EFER_LME, %eax # EFER_LME = bit 8
  btrl $_EFER_LMA, %eax # EFER_LMA = bit 10
  wrmsr               # Make changes effective

  /* Jump in protected mode with paging off */
  movl    $reach_prot_ptr, %eax
  ljmp *(%eax)            # EFER.LME will be automatically cleared

 5) Now we are in protected mode with paging off

 

 

References:

* IA 32 Intel Architecture Software Developer's Manual
  http://developer.intel.com/design/pentium4/manuals/

Refer to Vol 3A, page 69 for details of control registers.
Refer to Vol 3A, page 140 for GDT entry description.
Refer to Vol 3A, page 180 for details of EFER description.

 

Yu Zhenshen
August, 27th, 2009 in Shenzhen

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值