我試圖在Qemu上的x86架構上啓用分頁。
但是這個代碼導致三重故障。在x86中啓用分頁Qemu
該代碼段在保護模式被執行。
代碼:https://github.com/mridulv/simpleOperatingSystem
這是內核入口文件
[bits 32]
[extern main]
[extern main2]
[extern page_table]
call main
lea ECX, [page_table - 0xC0000000]
mov CR3, ECX
mov ECX, CR0
or ECX, 0x80000000
mov CR0, ECX
;lea ECX, [StartInHigherHalf]
;jmp ECX
;StartInHigherHalf:
; call main2
jmp $
這是創建的頁面目錄,表內核文件。
unsigned int page_table[1024] __attribute__((aligned(4096)));;
void set_page_tables() {
unsigned int pages_entry[1024 * 1024] __attribute__((aligned(4096)));
unsigned int KERNEL_VIRTUAL_OFFSET = 0xC0000000;
unsigned int KERNEL_FIRST_VIRTUAL_ADDRESS = 0xC0000000 >> 12;
int numPageTables = 4;
int numPagesInPageTable = 1024;
int numPageTableEntriesInPageDirectory = 1024;
int totalPages = numPageTables * numPagesInPageTable;
unsigned int index = 0;
unsigned int *pages_ptr = (unsigned int *)(pages_entry - KERNEL_VIRTUAL_OFFSET);
unsigned int *page_table_ptr = (unsigned int *)(pages_entry - KERNEL_VIRTUAL_OFFSET);
unsigned int positionAndFlags = 7;
while (index < totalPages) {
pages_ptr[index] = positionAndFlags;
index = index + 1;
positionAndFlags += 4096;
}
positionAndFlags = 7;
index = KERNEL_FIRST_VIRTUAL_ADDRESS;
unsigned int totalPagesLeft = KERNEL_FIRST_VIRTUAL_ADDRESS + totalPages;
while (index < totalPagesLeft) {
pages_ptr[index] = positionAndFlags;
index = index + 1;
positionAndFlags += 4096;
}
positionAndFlags = (unsigned int)&pages_ptr[0];
positionAndFlags = positionAndFlags | 7;
index = 0;
while (index < numPageTableEntriesInPageDirectory) {
page_table_ptr[index] = positionAndFlags;
index = index + 1;
positionAndFlags += 4096;
}
}
void main() {
char* video_memory = (char*) 0xb8000;
*video_memory = 'X';
set_page_tables();
}
void main2() {
char* video_memory = (char*) 0xb8004;
*video_memory = 'Y';
// __asm__
// (
// "leal (page_table,), %ecx\n\t" // 0xC0000000 = KERNEL_VIRTUAL_BASE
// "movl %cr3, %ecx"
//);
}
Linker.ld
SECTIONS {
. = 0xC0100000;
.text : AT(ADDR(.text) - 0xC0000000) {
*(.text);
}
. = ALIGN(0x1000);
.bss : AT(ADDR(.bss) - 0xC0000000) {
*(.text);
}
. = ALIGN(0x1000);
.data : AT(ADDR(.data) - 0xC0000000) {
*(.text);
}
}
一些明顯的事情。您不能啓用我可以說的[A20行](http://wiki.osdev.org/A20_Line)。在'boot.asm'中,開始時保存_DL_(啓動驅動器),然後立即放置數據('PROTECTED_MODE_STR'和'BEGIN_STR')。 CPU將嘗試執行數據。在所有代碼之後放置數據(嘗試將它們移至引導簽名之前)。另一個大問題是,你在內存中加載你的內核在0x1000。您的鏈接器腳本使用「0xC0100000」的基礎。這假定你的內核是在0x100000加載的,但你的是在0x1000。所以在你的情況下,你可能需要'0xC0001000' –
我甚至沒有超越那個。但是,即使遇到嘗試啓用分頁的代碼,您也有足夠的問題。 –
我還建議改變之類的東西'LEA ECX,[page_table - 0xC0000000的]''到MOV ECX,page_table - 0xC0000000' –