when load control register during in switching rmode 2 pmode
the intel sdm suggestion
From intel sdm 10.9.1 Switching to Protected Mode
, it give following steps:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
3. Execute a MOV CR0 instruction that sets the PE flag (and optionally the PG
flag) in control register CR0.
4. Immediately following the MOV CR0 instruction, execute a far JMP or far CALL
instruction. (This operation is typically a far jump or call to the next
instruction in the instruction stream.)
5. It can be found that after executing "MOV to CR0" (set PE), the relevant
instructions of the load control register can be executed.
...
9. After entering protected mode, the segment registers continue to hold the
contents they had in real-address mode. The JMP or CALL instruction in step
4 resets the CS register. Perform one of the following operations to update
the contents of the remaining segment registers.
+ Reload segment registers DS, SS, ES, FS, and GS. If the ES, FS, and/or GS
registers are not going to be used, load them with a null selector.
...
This means that after we execute the MOV to CR0 (set PE) instruction, it is best to execute a far jump or call immediately. After completing the above steps, go to load control register
But on my own opinion, after executing “MOV to CR0” (set PE), the CPU has entered protected mode. At this time, executing MOV to SS, MOV to DS will also successfully load the control register from the segment descriptor.
test
I wrote a small program and run it in qemu, part of it is as follows:
1
2
3
4
5
6
7
8
9
10
11
lgdt %cs:gdt_desc
mov $0x28, %eax
mov %eax, %es
mov $1, %eax
mov %eax, %cr0
mov $0x28, %eax
mov %eax, %es
ljmp $0x10, $.startup_prot
The above code modifies the ES selector before and after the mov to CR0 (set PE) instruction. Debugging using qemu+gdb.
- gdb print information
1
2
3
4
5
6
7
8
9
10
11
12
13
14
(gdb) ni
38 mov $0x28, %eax
(gdb) ni
39 mov %eax, %es
(gdb)
41 mov $1, %eax
(gdb) ni
42 mov %eax, %cr0
(gdb) ni
44 mov $0x28, %eax
(gdb) ni
45 mov %eax, %es
(gdb) ni
46 ljmp $0x10, $.startup_prot
- When gdb is executed to position
39
, use the qemu monitorinfo registers
command to obtain the ES register value:1
ES =0028 00000280 0000ffff 00009300
- When gdb is executed to position
46
, use the qemu monitorinfo registers
command to obtain the ES register value:1
ES =0028 00000000 ffffffff 00cf9300 DPL=0 DS [-WA]
It can be found that after executing “MOV to CR0” (set PE), the relevant instructions of the load control register can be executed successfully.
So I want to ask, is it reasonable to execute the “load control register” instruction immediately after MOV to CR0 (set PE), and what is the meaning of step 5 in the manual?
Thanks