Page 1 of 1

my OS reboots when it enables paging

Posted: Mon Jan 11, 2016 9:40 am
by Hygon
I'm making an OS. and I made the code that enables paging.
before enabling paging, it initilizes page directory and page table
I cannot found what wrong is/

below is my paging source code.(sorry, the annotations are korean..)

Code: Select all

---- /Kernel/Sources/mm/page.c ----

/*
Author : Hygon
Date : 2016-01-07
Last Edited Date :

참고 문헌 : http://wiki.osdev.org/Tutorials#Memory_Management
memo :  디렉터리를 not present 로 설정했는데
필요 할 때마다 present 로 변경되는 코드를 넣어야 한다.
그걸 고치고 나도 오류가 나면 원인을 더 찾아보자..

*페이지 디렉터리(4b*1024) +  페이지 테이블 (4b*1024*1024)의 여유공간 필요

*/
#include "../include/lib/stdio.h"
#include "../include/types.h"
#include "../include/mm/page.h"

int init_image_area()
{

	//이미지 크기를 불러온 후에 이미지 만큼의 크기는 실제 물리 공간에 연결
	//0~5M 4kb까지 연결 5M 4KB / 4KB - 1 을 인덱스로 해서 매핑 	
	for(int i, addr = 0; i < 1280; i++){  //1024*1024(Image & Stack) + 4096(pgd) + 4096*1024(pmd) - 1 = 1280
		mmap(addr, addr, 3);
		addr+=4096;

}
	return 1;
}

void init_pgd()
{
	pgd_t *page_dir = (unsigned int *) PGD_ADDRESS; // 0x100000 부터 시작
	unsigned int pmd_addr = PGD_ADDRESS + 1024;
	
	for(int i = 0; i < 1024; i++){ //  엔트리 1024개 설정

		page_dir[i] = pmd_addr | PGE_DEFAULT;
		pmd_addr += 4096;
	//Present : 0, Read/Write
	}

}
void init_pmd()
{
	pmd_t **page_table = (pmd_t **)PGD_ADDRESS  + 1024;
	unsigned int pte_addr = 0;
	pte_addr = 0;
	for(int i = 0; i < 1024; i++){	
	

		for(int i2=0; i2 < 1024; i2++){
			page_table[i][i2] = pte_addr | PTE_DEFAULT;
			//위의 비트 OR 연산이 이해가 가지 않는경우 직접 2진수로 변환해보길 바란다.
			pte_addr += 4096;
		}

}

}
int mmap(const unsigned int virtual, const unsigned int physical,const int flags)
{
	if((physical % 4096) != 0)
		return -1; //주소가 4096 바이트로 정렬되지 않음

	vaddress *vaddr;
	vaddr = (vaddress *) virtual;
	unsigned int **page = (unsigned int**)PGD_ADDRESS + 1024;
	pte_t *pte = (pte_t *)&page[vaddr->dir_index][vaddr->table_index];

	if((pte->flags << 11) < 0) //P 비트를 부호 비트로 바꾼 후 1인경우
		return 0; //페이지가 이미 사용중 (p 비트가 1)

	pte->addr = pte->addr | (physical / 4096);
	pte->flags = pte->flags | flags;
	return 1; //성공
}
int munmap(const unsigned int virtual)
{	
	if((virtual % 4096) != 0)
		return -1; //주소가 4096 바이트로 정렬되지 않음

	vaddress *vaddr = (vaddress *) virtual;
	unsigned int **page = (unsigned int **)PGD_ADDRESS + 1024;
	pte_t *pte = (pte_t *)&page[vaddr->dir_index][vaddr->table_index];

	pte->addr = pte->addr ^ pte->addr; //a xor a 는 a=0과 같다.
	pte->flags = pte->flags ^ pte->flags; 	

	return 1;
}
void alloc_pages()
{}
void free_pages()
{}
void get_free_pages()
{}

void enable_paging()
{
	unsigned int cr0; 
	__asm__ __volatile__("mov %0, %%cr3" : : "b"(PGD_ADDRESS));
	__asm__ __volatile__("mov %%cr0, %0": "=r"(cr0));
	cr0 |= 0x80000000;
	__asm__ __volatile__("mov %0, %%cr0":: "r"(cr0));
	return;
}

---- end of page.c ----

and I uploaded the entire source code.

help me!

Re: my OS reboots when it enables paging

Posted: Mon Jan 11, 2016 10:51 am
by iansjack
Run your code under a debugger. Set a breakpoint just before you enable paging and check your page tables to see that they contain what you think they should. You should also check your GDT and IDT to see that they look reasonable. Also set breakpoints at the start of your handlers for page fault exceptions and GPF exceptions. That way you can tell the nature of the initial fault and, if it is a page fault, the address causing that fault.

With that information at you disposal it should be easy to review your code to see where the error lies.

Re: my OS reboots when it enables paging

Posted: Mon Jan 11, 2016 2:42 pm
by gerryg400

Code: Select all

int init_image_area()
{

   //이미지 크기를 불러온 후에 이미지 만큼의 크기는 실제 물리 공간에 연결
   //0~5M 4kb까지 연결 5M 4KB / 4KB - 1 을 인덱스로 해서 매핑    
   for(int i, addr = 0; i < 1280; i++){  //1024*1024(Image & Stack) + 4096(pgd) + 4096*1024(pmd) - 1 = 1280
      mmap(addr, addr, 3);
      addr+=4096;

}
   return 1;
}
You didn't initialise the variable i

Re: my OS reboots when it enables paging

Posted: Thu Jan 14, 2016 6:33 am
by digo_rp
try to learn with identy map 1:1 its the simplest way to learn paging...

first you should init your page_dir with all "0" zeroes.

Something like this!

for ( i = 0; i < 1024; i++ )
{
PageDir.Present = 0;
PageDir.ReadWrite = 1;
PageDir.Supervisor = 0;
PageDir.WriteThrough = 0;
PageDir.PageSize = 0;
PageDir.PageTableBaseAddress = 0;
}

then init pagetable with size of your kernel...

Address4KB = 0;

for ( i = 0; i < 1024; i++ )
{
PageTable.Present = 1;
PageTable.ReadWrite = 1;
PageTable.WriteThrough = 1;
PageTable.CacheDisabled = 0;
PageTable[i].Supervisor = Supervisor;
PageTable[i].GlobalPage = GlobalPage;
PageTable[i].PageBaseAddress = ((Address4KB & PBA_MASK) >> PAGE_SHIFT);

Address4KB += 4096;
}

that code above will map the first 4MB of memory

then finally set page_dir entry[0].

AddrPTE = PageTable;
PageDir[0].Present = 1;
PageDir[0].ReadWrite = 1;
PageDir[0].Supervisor = 1;
PageDir[0].WriteThrough = 1;
PageDir[0].PageSize = 0;
PageDir[0].GlobalPage = GlobalPage;
PageDir[0].PageTableBaseAddress = (((unsigned)AddrPTE & PTBA_MASK) >> PAGE_SHIFT);


This is the simplest way to use paging!

sorry for my poor english... :D

I hope this helps

Re: my OS reboots when it enables paging

Posted: Fri Jan 15, 2016 2:43 am
by Hygon
Thanks! I'l try to do it.
and actually I didn't initialized zero spaces to zero!

Re: my OS reboots when it enables paging

Posted: Fri Jan 15, 2016 2:48 am
by Hygon
iansjack wrote:Run your code under a debugger. Set a breakpoint just before you enable paging and check your page tables to see that they contain what you think they should. You should also check your GDT and IDT to see that they look reasonable. Also set breakpoints at the start of your handlers for page fault exceptions and GPF exceptions. That way you can tell the nature of the initial fault and, if it is a page fault, the address causing that fault.

With that information at you disposal it should be easy to review your code to see where the error lies.
Thanks!

Re: my OS reboots when it enables paging

Posted: Fri Jan 15, 2016 2:49 am
by Hygon
gerryg400 wrote:

Code: Select all

int init_image_area()
{

   //이미지 크기를 불러온 후에 이미지 만큼의 크기는 실제 물리 공간에 연결
   //0~5M 4kb까지 연결 5M 4KB / 4KB - 1 을 인덱스로 해서 매핑    
   for(int i, addr = 0; i < 1280; i++){  //1024*1024(Image & Stack) + 4096(pgd) + 4096*1024(pmd) - 1 = 1280
      mmap(addr, addr, 3);
      addr+=4096;

}
   return 1;
}
You didn't initialise the variable i
Thank you! I didn't catch it