2011-08-24 3 views
4

저는 bochs에서 x86에서 동작하는 장난감 커널을 가지고 있습니다. 페이징을 사용하면 Bochs가 3 중 오류로 리셋됩니다. 오류를 유발하는 모든 메모리 액세스가있는 것처럼 보입니다. 그래서, 내가 페이징을 설정하는 데 오류가 있다고 가정하고, 문제는 내 인터럽트 처리기와 다릅니다. 여기에 코드가 있습니다.x86 페이징을 설정하는 방법은 무엇입니까? 트리플 폴트 에러 받기

paging.c

#include "paging.h" 
#include "lib.h" 
#include "screen.h" 
#include "descriptor_tables.h" 

typedef struct page_dir_entry_s{ 
    bool present:1; 
    bool writeable:1; 
    bool user_access:1; 
    bool write_through:1; 
    bool cache_disabled:1; 
    bool accessed:1; 
    bool unused0:1; 
    bool use_mb:1;//makes pages 4MB not 4KB 
    bool unused1:4; 
    u32 frame:20; 
} page_dir_entry_t; 

typedef struct page_table_entry_s{ 
    bool present:1; 
    bool writeable:1; 
    bool user_access:1; 
    bool write_through:1; 
    bool cache_disabled:1; 
    bool accessed:1; 
    bool dirty:1; 
    bool unused0:1; 
    bool global:1; 
    bool unused1:3; 
    u32 phys_page_addr:20; 
} page_table_entry_t; 

extern u32 end;//as declared in the linker script 

static u32 next_addr=0; 
static page_dir_entry_t* page_dir=NULL; 
static page_table_entry_t* page_table=NULL; 

extern void enable_paging(u32); 

void InitPaging(){ 
    next_addr=end; 
    while((next_addr%4096)!=0) 
     ++next_addr; 
    page_dir=(void*)next_addr; 
    next_addr+=4*1024; 
    memset(page_dir,0,4*1024); 
    page_table=(void*)next_addr; 
    next_addr+=4; 
    u32 addr=0; 
    u32 i=0; 
    *(((u32*)page_table)+i)=0;//zero it out 
    while(addr<next_addr){ 
     page_table[i].present=true; 
     page_table[i].writeable=true; 
     page_table[i].phys_page_addr=addr; 
     ++i; 
     *(((u32*)page_table)+i)=0;//zero it out 
     addr+=(1024*4);//4KB 
     next_addr+=4; 
    } 

    page_dir[0].writeable=true; 
    page_dir[0].present=true; 
    page_dir[0].frame=(u32)page_table; 

    enable_paging((u32)page_dir); 
} 

paging_asm.s

[global enable_paging] 
enable_paging: 
    mov eax,[esp+4] 
    mov cr3,eax 
    mov eax,cr0 
    or eax,0x80000000 
    mov cr0,eax 
    ret 
+1

커널 뒤에 스택을 넣었습니까? 그렇다면 모든 스택 액세스는 스택없이 인터럽트를 처리 할 수 ​​없으므로 3 중 오류가 발생합니다. bochs에 디버거가 활성화되어 있다면,'show dbg-all'을 사용하여 원인에 대한 더 많은 정보를 얻으십시오. 또한 next_addr = next_addr = (next_addr + 0xFFF) & 0xFFFFF000' – ughoavgfhw

+0

next_addr = 0x250A8000이고 esp = 0x7FE2C이므로 문제가되지 않습니다. – Maz

+0

최소 작업 페이지 예제 : https://github.com/cirosantilli/x86-bare-metal-examples/blob/24988411adf10cf9f6afd1566e35472eb8ae771a/paging.S –

답변

1

"프레임"및 "phys_page_addr"필드의 (이 페이징 모드) 비트 12 내지 32이다 실제 주소.

페이징은 오프셋 (0 - 4K)으로 아무 것도 수행하지 않습니다. 최소한의에서

, 당신이 필요합니다

page_table[i].phys_page_addr=addr >> 12; 

와 '요지'와 'page_table'모두 4096에 정렬되어 있기 때문에

page_dir[0].frame=((u32)page_table) >> 12; 

, 이것은 단지 여분의 0을 제거합니다.