Basic Paging for Long Mode setup

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
BringerOfShadows
Posts: 15
Joined: Thu Nov 08, 2012 2:59 am

Basic Paging for Long Mode setup

Post by BringerOfShadows »

I am writing a set of functions to implement a preliminary paging table to shift into long mode. Right now I think I have it set up to map the first 14MB of memory, and a way to reliably get the memory map. I am hoping that someone can point out errors or give suggestions on how to improve my code. I will also be posting updates to the file as I work out how to map the rest of memory.

Code: Select all

#include <multiboot2.h>
#include <stdarg.h>

// Using Multiboot 2

#define SPACE_GIGABYTE 0x40000000	// 1 Gigabyte
#define SPACE_MEGABYTE 0x00200000	// 2 Megabytes
#define SPACE_KILOBYTE 0x00001000	// 4 Kilobytes
#define TABLE 0x8	// size in bytes of a paging table entry

uint64_t *PML4[512] = 0x8000;
uint64_t *PDP[512] = 0x9000;
uint64_t *PD[512][512] = 0xA000;
uint64_t *PT = 0x4A000;

uint64_t* memStart(uint64_t addr)
{
	struct multiboot_tag* tag;
	struct multiboot_memory_map_t *mmap;
	uint64_t mmap_len;
	uint64_t entry_size;
	tag = (struct multiboot_tag *)addr + 8;
	while(tag->type != MULTIBOOT_TAG_TYPE_END)
	{
		if(tag->type == MULTIBOOT_TAG_TYPE_MMAP)
		{
			mmap = ((multiboot_tag_mmap *)tag)->entries;			// set mmap to location of Memory map
			mmap_len = tag + tag->size;								// get length of the memory map
			entry_size = ((multiboot_tag_mmap *)tag)->entry_size;	// get size of the memory map entries.
		}
	}
	uint32_t entries;
	entries = GetEntries(*mmap, mmap_len, entry_size);
	multiboot_memory_map_t memMap[entries];
	multiboot_memory_map_t *memMapP = &memMap;
	fillMemMap(*mmap, mmap_len, entry_size, *memMapP);
	sortMemMap(*memMapP, entries);
	fillPageTables(*memMapP, entries);
	return *PML4;
}

void fillMemMap(multiboot_memory_map_t *mmap, uint64_t mmap_len,
	uint64_t entry_size, multiboot_memory_map_t *memMapP)
{
	for(entries=0;mmap < (mmap + mmap_len);
		mmap = (multiboot_memory_map_t *)
		((uint64_t) mmap 
		+ (entry_size))
	{
		entries++;
		memMapP->addr = mmap->addr;
		memMapP->len = mmap->len;
		memMapP->type = mmap->type;
		memMapP++;
	}
}

uint32_t GetEntries(multiboot_memory_map_t *mmap, uint64_t mmap_len, uint64_t entry_size)
{
	uint32_t entries;
	for(entries=0;mmap < (mmap + mmap_len);
		mmap = (multiboot_memory_map_t *)
		((uint64_t) mmap 
		+ (entry_size))
	{
		entries++;
	}
	return entries;
}

void sortMemMap(multiboot_memory_map_t *memMapP, uint32_t entries)
{
	multiboot_memory_map_t swap, *Start;
	Start = memMapP;
	for(int i=0;i<entries;i++)
	{
		for(int j;j<entries-i;j++)
		{
			if(memMapP->addr > ((memMapP+1)->addr)
			{
				 swap = *memMapP;
				 *memMapP = *(memMapP+1);
				 *(memMapP+1) = swap;
			}
			memMapP++;
		}
		memMapP = Start;
	}
	
}

void fillPageTables(multiboot_memory_map_t *memMapP, uint32_t entries)
{
	// point first entry of PML4 to Page Directory Pointers and initiallize the first 14 MB
	*PML4[0] = PDP + 0x7;  // 0x7 User, Write, Present
	uint64_t addr = 0x00000;
	uint64_t size = 0;
	// map first 14 MB as 2MB Pages
	*PDP[0] = PD + 0x07;
	for(int i=0; i<7; i++)
	{
		*PD[0][i] = addr + 0x83;
		addr += 0x200000;
	}
	// first 14 MB mapped as 0x0000000000000000 - 0x0000000000E00000
	// TODO: after setting up paging, remap page table locations to higher memory.

}
Link to most recent Version: MemStart.c
Post Reply