Page 1 of 1

Boot loop when changing page directory

Posted: Mon Nov 02, 2020 5:47 pm
by monarrk
Hello there,

I'm a first time poster and I'm still learning a lot so please be kind :)

I'm attempting to start adding multitasking into my kernel. At the moment, I am having a bug where it gets stuck in a boot loop after trying to change the page directory to the current_directory by moving into cr3.

This started out a little more originally, but after encountering the bug, I basically just copied the paging.c file from http://www.jamesmolloy.co.uk/tutorial_h ... sking.html to see if I was accidentally doing something wrong, but the error still persisted.

Does anyone know what the issue here is?

The functions in question:

Code: Select all

void initialize_paging() {
	// The size of physical memory. For the moment we
	// assume it is 16MB big.
	u32 mem_end_page = 0x1000000;

	nframes = mem_end_page / 0x1000;
	frames = (u32*)kmalloc(INDEX_FROM_BIT(nframes));
	memory_set(frames, 0, INDEX_FROM_BIT(nframes));

	// Let's make a page directory.
	//u32 phys;
	kernel_directory = (page_directory_t*)kmalloc_a(sizeof(page_directory_t));
	memory_set(kernel_directory, 0, sizeof(page_directory_t));
	kernel_directory->physicalAddr = (u32)kernel_directory->tablesPhysical;

	// Map some pages in the kernel heap area.
	// Here we call get_page but not alloc_frame. This causes page_table_t's
	// to be created where necessary. We can't allocate frames yet because they
	// they need to be identity mapped first below, and yet we can't increase
	// placement_addr between identity mapping and enabling the heap!
	for (u32 i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += 0x1000)
		get_page(i, 1, kernel_directory);

	// We need to identity map (phys addr = virt addr) from
	// 0x0 to the end of used memory, so we can access this
	// transparently, as if paging wasn't enabled.
	// NOTE that we use a while loop here deliberately.
	// inside the loop body we actually change placement_addr
	// by calling kmalloc(). A while loop causes this to be
	// computed on-the-fly rather than once at the start.
	// Allocate a lil' bit extra so the kernel heap can be
	// initialised properly.
	for (u32 i = 0; i < placement_addr + 0x1000; i += 0x1000) {
		// Kernel code is readable but not writeable from userspace.
		alloc_frame(get_page(i, 1, kernel_directory), 0, 0);
	}

	// Now allocate those pages we mapped earlier.
	for (u32 i = KHEAP_START; i < KHEAP_START + KHEAP_INITIAL_SIZE; i += 0x1000)
		alloc_frame(get_page(i, 1, kernel_directory), 0, 0);

	// Before we enable paging, we must register our page fault handler.
	register_interrupt_handler(14, page_fault);

	// Now, enable paging!
	switch_page_directory(kernel_directory);

	// Initialise the kernel heap.
	kheap = create_heap(KHEAP_START, KHEAP_START + KHEAP_INITIAL_SIZE, 0xCFFFF000, 0, 0);

	serial_print("Cloning kernel_directory to current_directory...");
	current_directory = clone_directory(kernel_directory);
	serial_print("OK\n");

	serial_print("Switching page directory to current_directory...");
	switch_page_directory(current_directory);
	serial_print("OK\n");
}

void switch_page_directory(page_directory_t* dir) {
	current_directory = dir;
	asm volatile("mov %0, %%cr3" ::"r"(dir->physicalAddr));
	u32 cr0;
	asm volatile("mov %%cr0, %0"
				 : "=r"(cr0));
	cr0 |= 0x80000000; // Enable paging!
	asm volatile("mov %0, %%cr0" ::"r"(cr0));
}
The full source: https://gitlab.com/monarrk/untrust/-/bl ... mem/page.c

Thank you very much!

Re: Boot loop when changing page directory

Posted: Mon Nov 02, 2020 9:09 pm
by Octocontrabass
monarrk wrote:At the moment, I am having a bug where it gets stuck in a boot loop after trying to change the page directory to the current_directory by moving into cr3.
Are you using a virtual machine? Have you checked its logs? Depending on the VM, you might be able to enable additional logging to tell you exactly which faults are causing it to reboot. My guess is there's something wrong with your new page tables, though!

Using a VM with a built-in debugger or attached to a separate debugger, you can examine the contents of memory to see if your new page directory and tables have reasonable contents, and make sure the value you're putting into CR3 is correct. (Assuming it's a page fault, anyway. You might need to examine something else if you're getting a different kind of fault.)
monarrk wrote:This started out a little more originally, but after encountering the bug, I basically just copied the paging.c file from http://www.jamesmolloy.co.uk/tutorial_h ... sking.html to see if I was accidentally doing something wrong, but the error still persisted.
That tutorial is known to have many bugs. It might be best to go back to debugging the code you wrote yourself.

Re: Boot loop when changing page directory

Posted: Tue Nov 03, 2020 7:33 am
by monarrk
Using a VM with a built-in debugger or attached to a separate debugger, you can examine the contents of memory to see if your new page directory and tables have reasonable contents, and make sure the value you're putting into CR3 is correct. (Assuming it's a page fault, anyway. You might need to examine something else if you're getting a different kind of fault.)
I'm using qemu so I'll look into that. It's a bit confusing because I'm pretty sure it isn't a page fault, as page faults should be handled and just cause a panic, not a boot loop, but maybe something extra weird is happening.
That tutorial is known to have many bugs. It might be best to go back to debugging the code you wrote yourself.
Damn ok, are there any good resources you know of that cover multitasking then? I tried looking online and this tutorial was a relief as something that actually explained stuff instead of just having me read code from already existing kernels with no explanation

Re: Boot loop when changing page directory

Posted: Tue Nov 03, 2020 8:54 am
by bloodline
monarrk wrote: Damn ok, are there any good resources you know of that cover multitasking then? I tried looking online and this tutorial was a relief as something that actually explained stuff instead of just having me read code from already existing kernels with no explanation
Do you need paging with this project if it's the multitasking part you are interested in?

Re: Boot loop when changing page directory

Posted: Tue Nov 03, 2020 10:38 am
by monarrk
Do you need paging with this project if it's the multitasking part you are interested in?
oh, well I was of the impression that paging was necessary for multitasking, is it not? If not, then yes, it is just multitasking that I am concerned with

Re: Boot loop when changing page directory

Posted: Tue Nov 03, 2020 10:58 am
by bloodline
monarrk wrote:
Do you need paging with this project if it's the multitasking part you are interested in?
oh, well I was of the impression that paging was necessary for multitasking, is it not? If not, then yes, it is just multitasking that I am concerned with
Paging and multitasking are two separate things. My OS project has no paging, the whole RAM is just single 32bit flat address space, I may add paging later, but at the moment all tasks live in the same address space. With paging, each task lives in its own virtual address space, this has the advatage that a rogue task can't accidentally write over another task's data/code, but requires the kernel to do more book keeping and has a task switching performance penalty, as the MMU must be reloaded each task switch, also sending messages to other tasks needs a more involved system.

With multitasking, the key is CPU contexts. You need a way to halt the CPU, save its state, then load in a new context, run for a bit, then save the state, and load in another context.
Have you decided which type of multitasking model you prefer? I personally use pre-emptive, that way tasks don't need to know they are multitasking. I use a timed interrupt which saves the current state of the running task on it's own stack, and then loads the state of the next ready task from its stack and executes until it's time is up. If this is a bit difficult, you could try co-operative multitasking, where each task is expected to wilfully give up the CPU, I think this is easier to implement, but I can't think of a useful application for it in the modern world.

Re: Boot loop when changing page directory

Posted: Tue Nov 03, 2020 11:03 am
by nexos
No, you don't need paging for multitasking. Making a process manager without paging or even segmentation could be a pain. The reason why is because GCC sets the base address for executables to one set address. With a flat address space, apps would trample on one another. But JamesM's tutorial is a bug pot. His paging code isn't good at all. I would recommend learning from reading the Intel manuals, or for a semi good paging implementation, Brokenthorn.

Re: Boot loop when changing page directory

Posted: Tue Nov 03, 2020 11:06 am
by monarrk
bloodline wrote:Have you decided which type of multitasking model you prefer?
I think I'd like to use pre-emptive multitasking, but I'm attempting to make an exokernel and I'm playing with the idea of letting libOSes use cooperative multitasking (although this is probably a bad idea from a security perspective). Do you have any opinions on this?

Re: Boot loop when changing page directory

Posted: Tue Nov 03, 2020 11:18 am
by bloodline
monarrk wrote:
bloodline wrote:Have you decided which type of multitasking model you prefer?
I think I'd like to use pre-emptive multitasking, but I'm attempting to make an exokernel and I'm playing with the idea of letting libOSes use cooperative multitasking (although this is probably a bad idea from a security perspective). Do you have any opinions on this?
Exokernels are a rather nebulous concept... do you have an existing example that inspired you?

Also Exokenels, as I understand them, don’t use virtual address spaces so you don’t really want paging.

Re: Boot loop when changing page directory

Posted: Tue Nov 03, 2020 11:28 am
by monarrk
bloodline wrote:Exokernels are a rather nebulous concept... do you have an existing example that inspired you?
yeah, I'm finding this out while trying to implement this. I don't have one in particular which has inspired me, but I have been reading exokernel paper which sort of outlines things. More than trying to conform really well to any particular implementation I'm concerned with just having something that works well but retains the general core philosophies (smaller software, modular, low level control, etc).
bloodline wrote:Also Exokenels, as I understand them, don’t use virtual address spaces so you don’t really want paging.
I would agree with this, but I think I've found myself in a hole of solving one problem and creating another and now I'm just making a monolithic kernel by accident.

The main issue, I think, that I am facing is how to load/initialize libOSes from the kernel. The way I have tried to do it here is to load an initrd from grub which contains "initialization binaries" for each libOS which lets them set up however they need. As I'm typing this, I'm realizing this doesn't make that much sense. Is there a better way to go about doing this?

Re: Boot loop when changing page directory

Posted: Tue Nov 03, 2020 11:29 am
by monarrk
nexos wrote:I would recommend learning from reading the Intel manuals, or for a semi good paging implementation, Brokenthorn.
I'll look at brokenthorn now, thank you!

Re: Boot loop when changing page directory

Posted: Tue Nov 03, 2020 11:35 am
by bloodline
monarrk wrote:
bloodline wrote:Exokernels are a rather nebulous concept... do you have an existing example that inspired you?
yeah, I'm finding this out while trying to implement this. I don't have one in particular which has inspired me, but I have been reading exokernel paper which sort of outlines things. More than trying to conform really well to any particular implementation I'm concerned with just having something that works well but retains the general core philosophies (smaller software, modular, low level control, etc).
My own concept (which I’m bringing over from my Microcontroller work), is that the Kernel does little more than manage address space and cpu time. I’m also including IPC in there as well, otherwise it would be difficult to manage... But applications are free to implement their own abstractions in top of a very simple framework provided. It’s micro kernel in concept, but not a million miles from an exokernel :)