如何在长模式(64位)下设置CR3寄存器

时间:2015-04-17 22:56:09

标签: assembly operating-system x86-64 page-tables

我正在处理我的操作系统项目。入门代码已跳转到长模式并设置临时页表。我现在已经设置并填充了我自己的pagetables,并按照我需要的方式完成了映射内存。现在我需要在CR3寄存器中设置PML4T的物理地址。

238 void setcr3(void * addr){
239 uint64_t temp=(uint64_t)addr;
240
241   __asm__ ("movq %0, %%cr3;"::"b"(temp));
242 }

执行该指令时崩溃。 GDB一步一步附加

0x0000000000000000 in ?? ()
(gdb) b setcr3
Breakpoint 1 at 0xffffffff80201205: file sys/paging.c, line 238.
(gdb) c
Continuing.

Breakpoint 1, setcr3 (addr=0x221000) at sys/paging.c:238
238     void setcr3(void * addr){
(gdb) si
241       __asm__ ("movq %0, %%cr3;"::"b"(temp));
(gdb) si
0xffffffff80201209      241       __asm__ ("movq %0, %%cr3;"::"b"(temp));
(gdb) si
242     }
(gdb) si
Remote connection closed
(gdb)
244 #define write_cr3(x) \
245 __asm__ __volatile__("movl %0,%%cr3": :"r" (x))


Error while compiling

sys/paging.c: Assembler messages:
sys/paging.c:271: Error: unsupported instruction `mov'

编辑:

printf("address in cr3 %x\n", (uint64_t)pml4t - 0xffffffff80200000 + physbase);
setcr3( (void *) ( (uint64_t)pml4t - 0xffffffff80200000 + physbase) );


line 1 prints:
address in cr3 221000

2 个答案:

答案 0 :(得分:0)

你忘了在故障中显示实际指令。我认为它是movq %rbx, %cr3。此外,您还忘记显示%rbx(或任何源寄存器)的值。

也就是说,指令集引用列出了这两个适用于故障的条件:

  • 如果当前权限级别不为0.
  • 如果尝试将1写入CR3中的任何保留位。

答案 1 :(得分:0)

  

asm (" movq%0,%% cr3;" ::" b"(临时));

代替" b",我建议使用" r"这样编译器就可以处理用于移动值的寄存器,并在执行指令后恢复它。

  

asm 易失性(&#34; movl%0,%% cr3&#34; :::&#34; r&#34;(x)); < / p>

使用movq而不是movl。

  

setcr3((void *)((uint64_t)pml4t - 0xffffffff80200000 + physbase));

如果在内核中第一次设置页表,则只需从pml4t的虚拟地址中扣除0xffffffff80200000,以便将物理地址传递给cr3寄存器。无需添加physbase。这是因为,在加载内核的elf部分后,你可能会在内存中占用第一个可用地址。

最后,最好在asm块之前添加volatile,以便编译器不优化指令。另外,为避免类型转换,请直接使用下面的行代替宏,看看会发生什么。

  

asm 易失性(&#34; movq%[cr3_var],%% cr3;&#34; :: [cr3_var]&#34; r&#34 ;((uint64_t中)pml4t));

相关问题