Page 1 of 1

Problem while mapping my memory-bitmap

Posted: Wed Mar 04, 2009 2:34 pm
by rizor
Hello,

I have a problem with the initialization of paging.
The problem is, that the first entry in the first table of my kernel-directory does not set zero as value.
I do not know why the error exists.
If I manipulate the first entry by hand, I get a triple fault of qemu.

Here is the code:

Code: Select all

void paging_init(){
	size_t size;

	krn_dir = (directory_table_t)palloc(PAGING_KERNEL_DIR_SIZE * sizeof(directory_table_t) / PAGING_PAGESIZE);
	memset(krn_dir , EMPTY , PAGING_KERNEL_DIR_SIZE);

	//map the kernel
	size = ((uint32_t)kernel_end - (uint32_t)kernel_start) / PAGING_PAGESIZE;
	puts("\tMapped the kernel ");
	map_init(kernel_start , kernel_mem_start , size);

	//map the txt-video-memory
	size = 80 * 25 * 2 / PAGING_PAGESIZE + 1;
	puts("\tMapped the video-memory ");
	map_init((phys_t)0xB8000 , (virt_t)0xB8000 , size);

	//map the kernel_directory
	puts("\tMapped the kernel-directory ");
	map_init(krn_dir , krn_dir , 1);

	//map the bitmap
	size = bitmap_size / PAGING_PAGESIZE;
	puts("\tMapped the bitmap ");
	map_init(bitmap_entry, bitmap_entry , size);

	//activate paging
	//_write_cr3((uint32_t)kernel_dir);
	//_write_cr0((_read_cr0() | PAGING_ENABLE));

	syscall_register(SYSCALL_MAP_PAGE , map_pages_user , NULL , 1);
	syscall_register(SYSCALL_UNMAP_PAGE , unmap_pages_user , NULL , 2);
}

Code: Select all

void map_init(phys_t paddr , virt_t vaddr , size_t size){
	size_t i , c , offset , overflow = 0;
	size_t start_table , start_page;
	uint32_t phys;
	page_table_t table;

	offset = ((uint32_t)vaddr >> PAGING_SHIFT_TABLE) % PAGING_TABLE_SIZE;

	if(size > PAGING_TABLE_SIZE - offset){
		if(krn_dir[(uint32_t)vaddr >> PAGING_SHIFT_DIRECTORY + 1] == EMPTY)
			create_table(krn_dir , (uint32_t)vaddr >> PAGING_SHIFT_DIRECTORY + 1);

		table = (page_table_t)((uint32_t)krn_dir[(uint32_t)vaddr >> PAGING_SHIFT_DIRECTORY + 1] & PAGING_REMOVEFLAGS);

		overflow = size - PAGING_TABLE_SIZE + offset;

		for(i = 0; i < overflow; i++){
			phys = (uint32_t)paddr + PAGING_TABLE_SIZE - offset + i * PAGING_PAGESIZE;

			if(table[i] != EMPTY)
				panic("Tried to map a mapped page");

			table[i] = phys | PAGING_KERNEL;
		}
	}

	if(krn_dir[(uint32_t)vaddr >> PAGING_SHIFT_DIRECTORY] == EMPTY)
		create_table(krn_dir , (uint32_t)vaddr >> PAGING_SHIFT_DIRECTORY);

	table = (page_table_t)(krn_dir[(uint32_t)vaddr >> PAGING_SHIFT_DIRECTORY] & PAGING_REMOVEFLAGS);

	for(i = 0; i < size - overflow; i++){
		phys = (uint32_t)paddr + i * PAGING_PAGESIZE;

		if(table[i + offset] != EMPTY)
			panic("Tried to map a mapped page");

		table[i + offset] = phys | PAGING_KERNEL;
	}
	puts("from %p to %p\n" , vaddr , (vaddr + size * PAGING_PAGESIZE));
}

Code: Select all

void create_table(directory_table_t directory , size_t dir_offset){
	page_table_t table;

	table = (page_table_t)palloc(PAGING_TABLE_SIZE * sizeof(page_table_t) / PAGING_PAGESIZE);

	if(table == EMPTY)
		//TODO call swapping
		panic("Not enough physical memory");

	memset(table , EMPTY , PAGING_TABLE_SIZE);

	if(dir_offset >= PAGING_KERNEL_DIR_SIZE)
		directory[dir_offset] = (uint32_t)table | PAGING_USER;
	else
		directory[dir_offset] = (uint32_t)table | PAGING_KERNEL;

	table[0] = EMPTY;	//TODO first element of the first table is wrong
}
Can you find the problem?

Thank you.

cu
rizor