2015-04-17 116 views
2

我正在開發我的操作系統項目。啓動器代碼已經跳轉到長模式並設置臨時頁表。我現在已經安裝並填充了自己的頁面表,並以我需要的方式完成了映射內存。現在我需要在CR3寄存器中設置PML4T的物理地址。如何在長模式下設置CR3寄存器(64位)

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 
+0

你忘了指定你的目標體系 – m0skit0

回答

0

你忘了展現在故障的實際指令。我假設它是movq %rbx, %cr3。此外,您還忘記顯示%rbx(或任何源寄存器)的值。

這就是說,指令集參考列出了故障這兩個適用條件:

  • 如果如果試圖以一個1寫入任何保留的當前特權級別不是0
  • 位在CR3。
+1

值Im寫入到寄存器0x221000 –

+0

即根據列出的條件看起來無害的。仔細檢查它實際上並不是更改後的分頁表,禁止讀取下一條指令。您的調試環境可能也是一個問題。我能夠將'0x221000'寫入'cr3'。除非您可以發佈完整的可運行代碼,否則我認爲我無法提供更多幫助。 – Jester

0

ASM( 「MOVQ%0,%% CR 3;」 :: 「B」(臨時));

代替「b」,我推薦使用「r」,以便編譯器負責使用哪個寄存器來移動值並在執行指令後恢復它。

ASM揮發性( 「MOVL%0,%% CR3」: 「R」(X));

使用movq而不是movl。

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

如果被設置在內核中首次頁表,你只需要從pml4t的虛擬地址,以物理地址傳遞給CR3寄存器中扣除0xffffffff80200000。沒有必要添加physbase。這是因爲,你可能在加載內核的elf部分之後在內存中佔用第一個可用地址。

最後,最好在asm塊之前添加volatile,這樣編譯器不會優化指令。此外,爲了避免類型轉換,請直接使用下面的代碼行來代替宏,看看會發生什麼。

ASM揮發性( 「MOVQ%[cr3_var],%% CR 3;」 :: [cr3_var] 「R」((uint64_t中)pml4t));

相關問題