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'로 변경하는 것도 좋습니다. –