virtual memory

If you are new to development, plan on spending some time here before visiting the other forums.

Moderator:Moderators

xixpsychoxix
Posts:59
Joined:Tue Oct 13, 2009 8:49 pm
Re: virtual memory

Post by xixpsychoxix » Tue Feb 23, 2010 3:41 am

oh. sry. I guess you mean my kernel code, so here it is. this is the entire file kernel.cpp:

Code: Select all


#include <stdio.h>
#include <ctype.h>
#include <HAL.h>
#include <exception.h>
#include <mboot.h>
#include <phys_manager.h>
#include <virt_manager.h>
#include <keyboard.h>
#include <string.h>
#include <floppy.h>
#include <fat12.h>
#include <kheap.h>

#define DEFAULT_COLOR 0x07

void InitializeSystem          (multiboot_info *);
void PrintLogo                 ();
void RunInteractiveCommandLine ();
void GetCommand                (char *, int, bool);
bool RunCommand                (char *);
void ReadDiskSector            ();
void InitCallbacks             (int (__cdecl *)(char *));
int  InsertCallback            (int (__cdecl *)(char *), char *cmd_name);
int  LookupCallback            (char *cmd);
void make_lower                (char *str);
void make_upper				   (char *str);

//callbacks
int no_funct_present (char *args);

int get_diskinfo (char *args);
int read         (char *args);
int cls          (char *args);
int help         (char *args);
int exit         (char *args);
int echo         (char *args);
int color        (char *args);
int edit         (char *args);

void printmem (uint8_t *mem, uint16_t count)
{
	while (count-- > 0)
		putc32 (*mem++);
}

struct memory_region
{
	uint32_t start_lo;
	uint32_t start_hi;
	uint32_t size_lo;
	uint32_t size_hi;
	uint32_t type;
	uint32_t acpi_3_0;
};

char *strMemoryTypes[] = {
	{ "Available" },
	{ "Reserved" },
	{ "ACPI Reclaim" },
	{ "ACPI NVS Memory" }
};


diskinfo diskdat;
uint16_t cmd_count = 0;
uint32_t kernelSize = 0;
uint32_t size = 0;
bool echo_is_on = true;
uint8_t colors = DEFAULT_COLOR;

int (*function_list[100])(char *);
char names[100][10];
char abs_name[11];

int _cdecl main (multiboot_info* bootinfo)
{
	_asm mov word ptr [kernelSize],dx

	InitializeSystem (bootinfo);

	//initialize the callback system for the command line
	InitCallbacks (no_funct_present);

	//set the callback list up
	InsertCallback (get_diskinfo, "diskinfo");
	InsertCallback (read, "read");
	InsertCallback (cls, "cls");
	InsertCallback (help, "help");
	InsertCallback (exit, "exit");
	InsertCallback (echo, "echo");
	InsertCallback (color, "color");
	//InsertCallback (edit, "edit");

	setpos (0, 0);
	PrintLogo ();
	
	printf ("Operating System Command Line Interface online...\n");
	printf ("Commands: \"Help\": List commands.\n");
	printf ("          \"Exit\": Shutdown System\n");
	printf ("          \"Cls\": Clear the display\n");
	printf ("          \"Echo\": Get current echo status. Type echo help for more info.\n");
	printf ("          \"Read\": Read a disk sector\n");

	RunInteractiveCommandLine ();

	printf ("\nThe system has been halted because shutdown is not available yet.\n");
	printf ("You may now shut down your system safely.");

	for (;;);
	return 0;
}

void _cdecl kernel_entry (multiboot_info* bootinfo)
{
#ifdef ARCH_X86

	_asm {
		cli
		
		mov ax,0x10
		mov ds,ax
		mov es,ax
		mov gs,ax
		mov fs,ax
	}
#endif

	main (bootinfo);

#ifdef ARCH_X86

	_asm cli
	_asm hlt

#endif
}

void InitializeSystem (multiboot_info *bootinfo)
{
	clrscr32 (colors);
	setpos (0, 0);
	setcolor (colors);

	InitializeHAL ();
	enable ();

	setvect (0,(void (__cdecl &)(void))divide_by_zero_fault);
	setvect (1,(void (__cdecl &)(void))single_step_trap);
	setvect (2,(void (__cdecl &)(void))nmi_trap);
	setvect (3,(void (__cdecl &)(void))breakpoint_trap);
	setvect (4,(void (__cdecl &)(void))overflow_trap);
	setvect (5,(void (__cdecl &)(void))bounds_check_fault);
	setvect (6,(void (__cdecl &)(void))invalid_opcode_fault);
	setvect (7,(void (__cdecl &)(void))no_device_fault);
	setvect (8,(void (__cdecl &)(void))double_fault_abort);
	setvect (10,(void (__cdecl &)(void))invalid_tss_fault);
	setvect (11,(void (__cdecl &)(void))no_segment_fault);
	setvect (12,(void (__cdecl &)(void))stack_fault);
	setvect (13,(void (__cdecl &)(void))general_protection_fault);
	setvect (14,(void (__cdecl &)(void))page_fault);
	setvect (16,(void (__cdecl &)(void))fpu_fault);
	setvect (17,(void (__cdecl &)(void))alignment_check_fault);
	setvect (18,(void (__cdecl &)(void))machine_check_abort);
	setvect (19,(void (__cdecl &)(void))simd_fpu_fault);

	uint32_t memSize = 1024 + bootinfo->m_memoryLo + bootinfo->m_memoryHi * 64;
	pmmgr_init (memSize, 0xC0000000 + kernelSize*512);

	memory_region *region = (memory_region *) 0x1000;
	for (int i=0; i<10; ++i) {

		if (region[i].type>4)
			break;

		if (i>0 && region[i].start_lo==0)
			break;

		pmmgr_init_region (region[i].start_lo, region[i].size_lo);
	}
	pmmgr_deinit_region (0xC0000000, kernelSize*512);

	vmmgr_initialize ();

	kkybrd_install (33);
	flpydsk_set_working_drive (0);
	flpydsk_install (38);

	kheap = create_heap (KHEAP_START, KHEAP_START+KHEAP_INITIAL_SIZE, KHEAP_START+KHEAP_INITIAL_SIZE, 0, 0);
}

void RunInteractiveCommandLine ()
{
	char cmd_buf[100];

	while (1)
	{
		GetCommand (cmd_buf, 95, echo_is_on);
		if (RunCommand (cmd_buf) == true)
			break;
	}
}

void sleep (int ms)
{
	static int ticks = ms + get_tick_count ();
	while (ticks > get_tick_count ())
		;
}

KEYCODE getch ()
{
	KEYCODE key = KEY_UNKNOWN;

	while (key==KEY_UNKNOWN)
		key = kkybrd_get_last_key ();

	kkybrd_discard_last_key ();
	return key;
}

void CommandPrompt ()
{
	printf ("(NO DRIVE SUPPORTED YET):\\>");
}

void GetCommand (char *buf, int n, bool prompt)
{
	if (prompt)
		CommandPrompt ();

	KEYCODE key = KEY_UNKNOWN;
	int i = 0;
	bool buf_char = false;

	while (i < n)
	{
		buf_char = true;
		key = getch ();

		if (key == KEY_RETURN)
			break;

		if (key == KEY_BACKSPACE)
		{
			buf_char = false;
			if (i > 0)
			{
				unsigned x, y;
				getpos (&x, &y);
				if (x > 0)
					setpos (--x, y);
				else
				{
					y--;
					x = get_horizontal ();
				}
				putc32 (' ');
				setpos (x, y);

				i--;
			}
		}

		if (buf_char)
		{
			char c = kkybrd_key_to_ascii (key);
			if (c)
			{
				putc32 (c);
				buf[i++] = c;
			}
		}
		sleep (10);
	}
	buf[i] = '\0';
}

bool RunCommand (char *buf)
{
	int result = function_list[LookupCallback (buf)] (buf);

	if (result == 1)
	{
		int loc = LocateFile (buf);

		if (!loc)
		{
			printf ("Bad command or filename. Please try again.\n");
			return false;
		}

		else
		{
			printf ("File found. To edit this file, use the edit command.\n");

			/* int len = GetFileLength (loc);
			char *buf = (char *) alloc (len, 0, kheap);
			
			if (buf)
			{
				ReadFile (loc, len, sizeof (char), buf);
				printf ("File successfully loaded!\n");
			}

			else
				printf ("Could not allocate space!\n");
			*/

			return false;
		}
	}

	else if (result == -1)
		return true;

	else
		return false;
}

void ReadDiskSector ()
{
	uint32_t sectornum = 0;
	char sectnumbuf[4];
	uint8_t *sector = 0;

	printf ("\nEnter sector number:> ");
	GetCommand (sectnumbuf, 3, false);
	sectornum = atoi (sectnumbuf);

	printf ("\n\rSector %i contents:\n\n\r", sectornum);

	sector = flpydsk_read_sector (sectornum);

	if (sector != 0)
	{
		int i = 0;
		for (int c = 0; c < 4; c++)
		{
			for (int j = 0; j < 128; j++)
				printf ("0x%x ", sector[i+j]);

			i += 128;
			printf ("\nPress any key to continue...\n");
			getch ();
		}
	}
	else
		printf ("Error reading disk sector %d\n", sectornum);

	printf ("\nDone.");
}

void PrintLogo (void)
{
	printf ("\n");
	printf ("      _____   _____   _____                                               \n"
			"     / / \\ \\ / __  \\ / ___/------------------------------------------  \n"
			"    / /__/ // /  / // /_      Ben's Microcomputer Operating System        \n"
			"   / /  \\ \\/ /  / / \\__ \\    Windows 3.1 Style Interface Coming Soon  \n"
			"  / /___/ / /__/ /____/ /  ------------------------------------------     \n"
			" /_______/ \\____//_____/                                                 \n");
}

int LookupCallback (char *cmd)
{
	char *temp = (char *) alloc (strlen (cmd), 0, kheap);
	strcpy (temp, cmd);

	make_lower (temp);
	char *command = strtok (temp, " ");

	int i = 0;

	while (i < 100)
	{
		if (strcmp (temp, names[i]) == 0)
			return i;
		i++;
	}
	return 0;
}

void InitCallbacks (int (*def_proc)(char *))
{
	int i = 0;

	while (i < 100)
		function_list[i++] = def_proc;

	i = 0;

	while (i < 100)
		strcpy (names[i++], "default");
}

int InsertCallback (int (*funct)(char *), char *cmd)
{
	cmd_count++;

	function_list[cmd_count] = funct;
	strcpy (names[cmd_count], cmd);

	return cmd_count;
}

void make_lower (char *str)
{
	while (tolower(*str++))
		;
}

void make_upper (char *str)
{
	while (toupper (*str++))
		;
}

int no_funct_present (char *args)
{
	return 1;
}

int get_diskinfo (char *args)
{
	InitDiskStruct (&diskdat);
	printf ("\nNot done yet...\n");
	return 0;
}

int read (char *args)
{
	ReadDiskSector ();
	return 0;
}

int cls (char *args)
{
	clrscr32 (colors);

	PrintLogo ();
	return 0;
}

int help (char *args)
{
	clrscr32 (colors);
	PrintLogo ();

	printf ("Commands: \"Help\": List commands.\n");
	printf ("          \"Exit\": Shutdown System\n");
	printf ("          \"Cls\" : Clear the display\n");
	printf ("          \"Echo\": Get current echo status. Type echo help for more info.\n");
	printf ("          \"Read\": Read a disk sector\n");

	return 0;
}

int exit (char *args)
{
	return -1;
}

int echo (char *args)
{
	char *param = strstr (args, " ");
	param = strtok (param, "\0");
	
	if (!param)
		printf ("\nECHO is %s", echo_is_on ? "on" : "off");

	else if (strcmp (param, "on") == 0)
		echo_is_on = true;

	else if (strcmp (param, "off") == 0)
		echo_is_on = false;

	else
		printf ("\n%s", param);

	printf ("\n");
	return 0;
}

int color (char *args)
{
	char *new_color = strstr (args, " ");
	new_color = strtok (new_color, " \0");

	if (!new_color)
	{
		clrscr32 (DEFAULT_COLOR);
		//setcolor (DEFAULT_COLOR);
		return 0;
	}

	unsigned short new_colors = atoi (new_color);

	colors = new_colors;
	clrscr32 (new_colors);
	//setcolor (new_colors);

	return 0;
}

int edit (char *args)
{
	char *fname = strstr (args, " ");
	fname = strtok (args, " \n\0");

	return 0;
}

alot of the stuff isn't done yet... sry if this is more info than you needed. i wasn't sure which parts you were looking for.

User avatar
Mike
Site Admin
Posts:465
Joined:Sat Oct 20, 2007 7:58 pm
Contact:

Re: virtual memory

Post by Mike » Tue Feb 23, 2010 3:47 am

Hello,

I have not yet looked through all of the code but this is going to cause problems:

Code: Select all

pmmgr_deinit_region (0xC0000000, kernelSize*512);
Make sure to only use physical addresses when working with the PMM, never virtual addresses. Change 0xc0000000 to the physical base address of your kernel (series uses 1MB). The same problem exists with your call to pmmgr_init. (Also make sure the size is right in the above code to the size of your kernel.)
Lead Programmer for BrokenThorn Entertainment, Co.
Website: http://www.brokenthorn.com
Email: webmaster@brokenthorn.com

xixpsychoxix
Posts:59
Joined:Tue Oct 13, 2009 8:49 pm

Re: virtual memory

Post by xixpsychoxix » Tue Feb 23, 2010 3:56 am

oh ok. i thought that i took all of that code directly from the tutorial but i'll check to see if i did or not. if i did i think it's wrong in the tutorial too. i was wondering about this when i first looked at it. i'll fix it and see what happens.


yeah, looking at demo 12 i found the following code:

Code: Select all


	pmmngr_init (bootinfo->m_memorySize, 0xC0000000 + kernelSize*512);
	DebugPrintf("pmm initialized with %i KB\n", bootinfo->m_memorySize);

but lower in the code it is:

Code: Select all


	pmmngr_deinit_region (0x100000, kernelSize*512);
	DebugPrintf ("pmm regions initialized: %i allocation blocks; block size: %i bytes",
		pmmngr_get_block_count (), pmmngr_get_block_size () );

so is the first example correct?

User avatar
Mike
Site Admin
Posts:465
Joined:Sat Oct 20, 2007 7:58 pm
Contact:

Re: virtual memory

Post by Mike » Tue Feb 23, 2010 4:03 am

Hello,

Please give me a chapter number or name. It is an error - it seems fixed in later chapters. Do not use the virtual address.
Lead Programmer for BrokenThorn Entertainment, Co.
Website: http://www.brokenthorn.com
Email: webmaster@brokenthorn.com

xixpsychoxix
Posts:59
Joined:Tue Oct 13, 2009 8:49 pm

Re: virtual memory

Post by xixpsychoxix » Tue Feb 23, 2010 4:06 am

that was from the chapter on virtual memory.

here is the exact code i am using to map those pages to their frames:

Code: Select all


//this is the initialization routine

void InitializeSystem (multiboot_info *bootinfo)
{
	clrscr32 (colors);
	setpos (0, 0);
	setcolor (colors);

	InitializeHAL ();
	enable ();

	setvect (0,(void (__cdecl &)(void))divide_by_zero_fault);
	setvect (1,(void (__cdecl &)(void))single_step_trap);
	setvect (2,(void (__cdecl &)(void))nmi_trap);
	setvect (3,(void (__cdecl &)(void))breakpoint_trap);
	setvect (4,(void (__cdecl &)(void))overflow_trap);
	setvect (5,(void (__cdecl &)(void))bounds_check_fault);
	setvect (6,(void (__cdecl &)(void))invalid_opcode_fault);
	setvect (7,(void (__cdecl &)(void))no_device_fault);
	setvect (8,(void (__cdecl &)(void))double_fault_abort);
	setvect (10,(void (__cdecl &)(void))invalid_tss_fault);
	setvect (11,(void (__cdecl &)(void))no_segment_fault);
	setvect (12,(void (__cdecl &)(void))stack_fault);
	setvect (13,(void (__cdecl &)(void))general_protection_fault);
	setvect (14,(void (__cdecl &)(void))page_fault);
	setvect (16,(void (__cdecl &)(void))fpu_fault);
	setvect (17,(void (__cdecl &)(void))alignment_check_fault);
	setvect (18,(void (__cdecl &)(void))machine_check_abort);
	setvect (19,(void (__cdecl &)(void))simd_fpu_fault);

	uint32_t memSize = 1024 + bootinfo->m_memoryLo + bootinfo->m_memoryHi * 64;
	pmmgr_init (memSize, 0x100000 + kernelSize*512);

	memory_region *region = (memory_region *) 0x1000;
	for (int i=0; i<10; ++i) {

		if (region[i].type>4)
			break;

		if (i>0 && region[i].start_lo==0)
			break;

		pmmgr_init_region (region[i].start_lo, region[i].size_lo);
	}
	pmmgr_deinit_region (0x100000, kernelSize*512);

	vmmgr_initialize ();

        // this is where I try to map the pages
        // am i doing something wrong here?

	for (int i = 0, j = 0; i < 1024; i++, j += 4096)
		MmMapPage (pmmgr_alloc_block (), (char *) 0xD0000000+j);

        // this is just to see if the pages mapped correctly
	char *test = (char *) 0xD0000000;
	*test = 'H';

	kkybrd_install (33);
	flpydsk_set_working_drive (0);
	flpydsk_install (38);

	kheap = create_heap (KHEAP_START, KHEAP_START+KHEAP_INITIAL_SIZE, KHEAP_START+KHEAP_INITIAL_SIZE, 0, 0);
}

i always get a page fault when i try to place the 'H' at *test.

User avatar
Mike
Site Admin
Posts:465
Joined:Sat Oct 20, 2007 7:58 pm
Contact:

Re: virtual memory

Post by Mike » Tue Feb 23, 2010 4:20 am

Hello,

Thank you. It seems the next few chapters, including that one, has the same faulty code as well do to them all using the same base code and it will be corrected.

Please use 1MB in place of 3GB in the calls.
Lead Programmer for BrokenThorn Entertainment, Co.
Website: http://www.brokenthorn.com
Email: webmaster@brokenthorn.com

xixpsychoxix
Posts:59
Joined:Tue Oct 13, 2009 8:49 pm

Re: virtual memory

Post by xixpsychoxix » Wed Feb 24, 2010 4:49 am

well i fixed all of the errors that i found but my pmmgr_alloc_block is still returning 0 for some reason. anything else anyone can think of?

pathos
Moderator
Posts:97
Joined:Thu Jan 10, 2008 6:43 pm
Location:USA

Re: virtual memory

Post by pathos » Mon May 10, 2010 3:48 am

Sorry to necro this a bit, but I have a question for xixpsychoxix.

First, did you fix your problem?
Second, I noticed you were setting up your kernel heap. I've been working on mine but it's not coming along great. Could you post your kheap.cpp? I understand if you won't, but I figure there's no harm in asking!

xixpsychoxix
Posts:59
Joined:Tue Oct 13, 2009 8:49 pm

Re: virtual memory

Post by xixpsychoxix » Mon May 10, 2010 4:28 am

hey its no problem i'll post it. actually it's pretty much a copy of James Molloy's memory allocator from that kernel tutorial. It's actually been quite a while since i checked it but yes I'm almost positive that I got it working. Here is the code for kheap.cpp:

Code: Select all

#include <kheap.h>
#include <phys_manager.h>

heap_t *kheap;

static int32_t find_smallest_hole (uint32_t size, uint8_t page_align, heap_t *heap)
{
	uint32_t iterator = 0;

	while (iterator < heap->index.size)
	{
		header_t *header = (header_t *) lookup_ordered_array (iterator, &heap->index);

		if (page_align)
		{
			uint32_t location = (uint32_t) header;
			int32_t offset = 0;

			if ((location + sizeof (header)) & 0xFFFFF000 != 0)
				offset = 0x1000 - (location+sizeof (header_t))%0x1000;

			int32_t hole_size = (int32_t) header->size - offset;

			if (hole_size >= (int32_t) size)
				break;
		}

		else if (header->size >= size)
			break;

		iterator++;
	}

	if (iterator == heap->index.size)
		return -1;
	else
		return iterator;
}

static int8_t header_t_less_than (void *a, void *b)
{
	return (((header_t *) a)->size < ((header_t *) b)->size?1:0);
}

heap_t *create_heap (uint32_t start, uint32_t end_addr, uint32_t max, uint8_t supervisor, uint8_t readonly)
{
	heap_t *heap = (heap_t *) 0xC0200000;

	heap->index = place_ordered_array ((void *) start, HEAP_INDEX_SIZE, &header_t_less_than);
	start += sizeof (type_t)*HEAP_INDEX_SIZE;

	if (start & 0xFFFFF000 != 0)
	{
		start &= 0xFFFFF000;
		start += 0x1000;
	}

	heap->start_address = start;
	heap->end_address = end_addr;
	heap->max_address = max;
	heap->supervisor = supervisor;
	heap->readonly = readonly;

	header_t *hole = (header_t *) start;

	hole->size = end_addr - start;
	hole->magic = HEAP_MAGIC;
	hole->is_hole = 1;

	insert_ordered_array ((void *) hole, &heap->index);
	return heap;
}

//static void expand (uint32_t new_size, heap_t *heap)
//{
//	if (new_size & 0xFFFFF000 != 0)
//	{
//		new_size &= 0xFFFFF000;
//		new_size += 0x1000;
//	}
//
//	if (heap->start_address+new_size > heap->max_address)
//		return;
//
//	uint32_t old_size = heap->end_address - heap->start_address;
//
//}

void *alloc (uint32_t size, uint8_t page_align, heap_t *heap)
{
	uint32_t new_size = size + sizeof (header_t) + sizeof (footer_t);
	int32_t iterator = find_smallest_hole (size, page_align, heap);

	if (iterator == -1)
		return NULL;

	header_t *orig_hole_header = (header_t *) lookup_ordered_array (iterator, &heap->index);
	uint32_t orig_hole_pos = (uint32_t) orig_hole_header;
	uint32_t orig_hole_size = orig_hole_header->size;
	
	if (orig_hole_size-new_size < sizeof(header_t)+sizeof(footer_t))
    {
        // Then just increase the requested size to the size of the hole we found.
        size += orig_hole_size-new_size;
        new_size = orig_hole_size;
    }

    // If we need to page-align the data, do it now and make a new hole in front of our block.
    if (page_align && orig_hole_pos&0xFFFFF000)
    {
        uint32_t new_location   = orig_hole_pos + 0x1000 /* page size */ - (orig_hole_pos&0xFFF) - sizeof(header_t);
        header_t *hole_header = (header_t *)orig_hole_pos;
        hole_header->size     = 0x1000 /* page size */ - (orig_hole_pos&0xFFF) - sizeof(header_t);
        hole_header->magic    = HEAP_MAGIC;
        hole_header->is_hole  = 1;
        footer_t *hole_footer = (footer_t *) ( (uint32_t)new_location - sizeof(footer_t) );
        hole_footer->magic    = HEAP_MAGIC;
        hole_footer->header   = hole_header;
        orig_hole_pos         = new_location;
        orig_hole_size        = orig_hole_size - hole_header->size;
    }
    else
    {
        // Else we don't need this hole any more, delete it from the index.
        remove_ordered_array(iterator, &heap->index);
    }

    // Overwrite the original header...
    header_t *block_header  = (header_t *)orig_hole_pos;
    block_header->magic     = HEAP_MAGIC;
    block_header->is_hole   = 0;
    block_header->size      = new_size;
    // ...And the footer
    footer_t *block_footer  = (footer_t *) (orig_hole_pos + sizeof(header_t) + size);
    block_footer->magic     = HEAP_MAGIC;
    block_footer->header    = block_header;

    // We may need to write a new hole after the allocated block.
    // We do this only if the new hole would have positive size...
    if (orig_hole_size - new_size > 0)
    {
        header_t *hole_header = (header_t *) (orig_hole_pos + sizeof(header_t) + size + sizeof(footer_t));
        hole_header->magic    = HEAP_MAGIC;
        hole_header->is_hole  = 1;
        hole_header->size     = orig_hole_size - new_size;
        footer_t *hole_footer = (footer_t *) ( (uint32_t)hole_header + orig_hole_size - new_size - sizeof(footer_t) );
        if ((uint32_t)hole_footer < heap->end_address)
        {
            hole_footer->magic = HEAP_MAGIC;
            hole_footer->header = hole_header;
        }
        // Put the new hole in the index;
        insert_ordered_array((void*)hole_header, &heap->index);
    }
    
    // ...And we're done!
    return (void *) ( (uint32_t)block_header+sizeof(header_t) );
}

void free(void *p, heap_t *heap)
{
    // Exit gracefully for null pointers.
    if (p == 0)
        return;

    // Get the header and footer associated with this pointer.
    header_t *header = (header_t*) ( (uint32_t)p - sizeof(header_t) );
    footer_t *footer = (footer_t*) ( (uint32_t)header + header->size - sizeof(footer_t) );

    // Make us a hole.
    header->is_hole = 1;

    // Do we want to add this header into the 'free holes' index?
    char do_add = 1;

    // Unify left
    // If the thing immediately to the left of us is a footer...
    footer_t *test_footer = (footer_t*) ( (uint32_t)header - sizeof(footer_t) );
    if (test_footer->magic == HEAP_MAGIC &&
        test_footer->header->is_hole == 1)
    {
        uint32_t cache_size = header->size; // Cache our current size.
        header = test_footer->header;     // Rewrite our header with the new one.
        footer->header = header;          // Rewrite our footer to point to the new header.
        header->size += cache_size;       // Change the size.
        do_add = 0;                       // Since this header is already in the index, we don't want to add it again.
    }

    // Unify right
    // If the thing immediately to the right of us is a header...
    header_t *test_header = (header_t*) ( (uint32_t)footer + sizeof(footer_t) );
    if (test_header->magic == HEAP_MAGIC &&
        test_header->is_hole)
    {
        header->size += test_header->size; // Increase our size.
        test_footer = (footer_t*) ( (uint32_t)test_header + // Rewrite it's footer to point to our header.
                                    test_header->size - sizeof(footer_t) );
        footer = test_footer;
        // Find and remove this header from the index.
        uint32_t iterator = 0;
        while ( (iterator < heap->index.size) &&
                (lookup_ordered_array(iterator, &heap->index) != (void*)test_header) )
            iterator++;

        // Make sure we actually found the item.
        // Remove it.
        remove_ordered_array(iterator, &heap->index);
    }

    // If required, add us to the index.
    if (do_add == 1)
        insert_ordered_array((void*)header, &heap->index);
}
there are also others (kheap.h):

Code: Select all

#ifndef KHEAP_H
#define KHEAP_H

#define NULL 0

#include <stdint.h>
#include "ordered_array.h"

#define KHEAP_START        0xC0300000
#define KHEAP_INITIAL_SIZE 0x100000
#define HEAP_INDEX_SIZE    0x20000
#define HEAP_MAGIC         0x123890AB
#define HEAP_MIN_SIZE      0x70000

typedef struct
{
	uint32_t magic;
	uint8_t is_hole;
	uint32_t size;
} header_t;

typedef struct
{
	uint32_t magic;
	header_t *header;
} footer_t;

typedef struct
{
	ordered_array_t index;
	uint32_t start_address;
	uint32_t end_address;
	uint32_t max_address;
	uint8_t supervisor;
	uint8_t readonly;
} heap_t;

extern heap_t *kheap;

heap_t *create_heap (uint32_t start, uint32_t end, uint32_t max, uint8_t supervisor, uint8_t readonly);
void   *alloc       (uint32_t size, uint8_t page_align, heap_t *heap);
void   free         (void *p, heap_t *heap);

#endif

Like I said I pretty much just copied James Molloy... I am only working through this tutorial to get an idea of what I am doing, I haven't started my own system quite yet. I needed to add some functionality for some experimentation i was running but here it is.

pathos
Moderator
Posts:97
Joined:Thu Jan 10, 2008 6:43 pm
Location:USA

Re: virtual memory

Post by pathos » Mon May 10, 2010 3:37 pm

Thanks!

Before I can get started on my kernel heap, I'm now having an issue with the file system. I made the changes this thread suggested (moving virtual memory init below physical, changed the init procedure, changing 3GB to 1MB, etc), but now my OS is triple faulting in the procedure below:

Code: Select all

void fsysFatMount()
{
	PBOOTSECTOR bootsector;

	bootsector = (PBOOTSECTOR)floppy_disk_read_sector(0);
	
	_MountInfo.numSectors     = bootsector->Bpb.NumSectors;
	_MountInfo.fatOffset      = 1;
	_MountInfo.fatSize        = bootsector->Bpb.SectorsPerFat;
	_MountInfo.fatEntrySize   = 8;
	_MountInfo.numRootEntries = bootsector->Bpb.NumDirEntries;
	_MountInfo.rootOffset     = (bootsector->Bpb.NumberOfFats * bootsector->Bpb.SectorsPerFat) + 1;
	_MountInfo.rootSize       = (bootsector->Bpb.NumDirEntries * 32) / bootsector->Bpb.BytesPerSector;
}
The OS triple faults any time bootsector-> is accessed.

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: virtual memory

Post by halofreak1990 » Thu May 27, 2010 10:38 pm

Hi, I'm encountering the same problem with the VFS demo as pathos.
Through some testing, I found out that it seems to hang when executing flpydsk_read_sector (0); to get the FAT data.
my guess is that the DMA code is not (entirely) compatible with the VMM

FYI, I'm using VirtualPC 2007, though I'm not sure what the hanging means. I do know that an 'unrecoverable processor error' equals a triple fault.

My OS boots in a similar verbose way as Linux, making it quite easy to spot where things go awry.

pathos
Moderator
Posts:97
Joined:Thu Jan 10, 2008 6:43 pm
Location:USA

Re: virtual memory

Post by pathos » Fri May 28, 2010 12:44 am

halofreak1990 wrote:Hi, I'm encountering the same problem with the VFS demo as pathos.
Through some testing, I found out that it seems to hang when executing flpydsk_read_sector (0); to get the FAT data.
my guess is that the DMA code is not (entirely) compatible with the VMM

FYI, I'm using VirtualPC 2007, though I'm not sure what the hanging means. I do know that an 'unrecoverable processor error' equals a triple fault.

My OS boots in a similar verbose way as Linux, making it quite easy to spot where things go awry.
It's the DMA_BUFFER at 0x1000 which was causing the problem (I think that's where it was at least -- I don't have my code in front of me, so I could be mistaken.) If you put it somewhere else, say 0x3000, that will fix that problem...
...and cause another one with virtual memory manager. I wasn't able to ever sort it all out. I'll just wait until Mike moves on with the series. Eventually he'll meet the same problem and have to fix it. =P

halofreak1990
Posts:92
Joined:Thu May 27, 2010 8:54 pm
Location:Netherlands

Re: virtual memory

Post by halofreak1990 » Fri May 28, 2010 9:19 am

Hi, pathos,
A bit of calculating tells me that 0x1000 is 4KB in memory.
Now, I'm not quite sure about this, but, can we freely access the memory below where the kernel is mapped? (1 MB)
If we can't, it immediately explains why the DMA doesn't work. In that case we need to remap the DMA buffer to somewhere after the kernel, or allow it to be mapped into the space < 1 MB

pathos
Moderator
Posts:97
Joined:Thu Jan 10, 2008 6:43 pm
Location:USA

Re: virtual memory

Post by pathos » Fri May 28, 2010 2:13 pm

halofreak1990 wrote:Hi, pathos,
A bit of calculating tells me that 0x1000 is 4KB in memory.
Now, I'm not quite sure about this, but, can we freely access the memory below where the kernel is mapped? (1 MB)
If we can't, it immediately explains why the DMA doesn't work. In that case we need to remap the DMA buffer to somewhere after the kernel, or allow it to be mapped into the space < 1 MB
I think we can freely map the memory below 1 MB, but some of it may already be in use, like 0x1000, which is where our physical memory map is written. One way to handle the DMA buffer is to ask the memory manager for block:

Code: Select all

	DMA_BUFFER = (int)pmmgr_alloc_block();
However, when I did this, other problems ended up arising when I tried to do some page mapping. There may be another bug with the physical memory manager, or even the virtual MM.

User avatar
Mike
Site Admin
Posts:465
Joined:Sat Oct 20, 2007 7:58 pm
Contact:

Re: virtual memory

Post by Mike » Fri May 28, 2010 8:54 pm

Hello everyone,

I have released a version of the Chapter 22 demo with the changes described in this chapter. It can be located here. Only the SysCore project has been changed.

Changes include:

-VMM is now properly initialized after PMM and MmInitialize updated
-DMA buffer is dynamically allocated
-Two new routines added to the floppy driver to allow you to set and get the DMA buffer address
-MmMapPage() routine
-Kernel is at 3GB Virtual

Please note that this was a very quick update to the demo, because of this not all bugs might be fixed. Please try the provided demo and please let me know if there are any issues.

Thanks :D
Lead Programmer for BrokenThorn Entertainment, Co.
Website: http://www.brokenthorn.com
Email: webmaster@brokenthorn.com

Post Reply