Boot loop when changing page directory

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
monarrk
Posts: 20
Joined: Mon Nov 02, 2020 4:53 pm
Libera.chat IRC: monarrk

Boot loop when changing page directory

Post 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!
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: Boot loop when changing page directory

Post 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.
monarrk
Posts: 20
Joined: Mon Nov 02, 2020 4:53 pm
Libera.chat IRC: monarrk

Re: Boot loop when changing page directory

Post 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
User avatar
bloodline
Member
Member
Posts: 264
Joined: Tue Sep 15, 2020 8:07 am
Location: London, UK

Re: Boot loop when changing page directory

Post 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?
CuriOS: A single address space GUI based operating system built upon a fairly pure Microkernel/Nanokernel. Download latest bootable x86 Disk Image: https://github.com/h5n1xp/CuriOS/blob/main/disk.img.zip
Discord:https://discord.gg/zn2vV2Su
monarrk
Posts: 20
Joined: Mon Nov 02, 2020 4:53 pm
Libera.chat IRC: monarrk

Re: Boot loop when changing page directory

Post 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
User avatar
bloodline
Member
Member
Posts: 264
Joined: Tue Sep 15, 2020 8:07 am
Location: London, UK

Re: Boot loop when changing page directory

Post 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.
Last edited by bloodline on Mon Nov 09, 2020 9:25 am, edited 1 time in total.
CuriOS: A single address space GUI based operating system built upon a fairly pure Microkernel/Nanokernel. Download latest bootable x86 Disk Image: https://github.com/h5n1xp/CuriOS/blob/main/disk.img.zip
Discord:https://discord.gg/zn2vV2Su
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: Boot loop when changing page directory

Post 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.
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
monarrk
Posts: 20
Joined: Mon Nov 02, 2020 4:53 pm
Libera.chat IRC: monarrk

Re: Boot loop when changing page directory

Post 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?
User avatar
bloodline
Member
Member
Posts: 264
Joined: Tue Sep 15, 2020 8:07 am
Location: London, UK

Re: Boot loop when changing page directory

Post 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.
CuriOS: A single address space GUI based operating system built upon a fairly pure Microkernel/Nanokernel. Download latest bootable x86 Disk Image: https://github.com/h5n1xp/CuriOS/blob/main/disk.img.zip
Discord:https://discord.gg/zn2vV2Su
monarrk
Posts: 20
Joined: Mon Nov 02, 2020 4:53 pm
Libera.chat IRC: monarrk

Re: Boot loop when changing page directory

Post 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?
Last edited by monarrk on Tue Nov 03, 2020 11:35 am, edited 1 time in total.
monarrk
Posts: 20
Joined: Mon Nov 02, 2020 4:53 pm
Libera.chat IRC: monarrk

Re: Boot loop when changing page directory

Post 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!
User avatar
bloodline
Member
Member
Posts: 264
Joined: Tue Sep 15, 2020 8:07 am
Location: London, UK

Re: Boot loop when changing page directory

Post 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 :)
CuriOS: A single address space GUI based operating system built upon a fairly pure Microkernel/Nanokernel. Download latest bootable x86 Disk Image: https://github.com/h5n1xp/CuriOS/blob/main/disk.img.zip
Discord:https://discord.gg/zn2vV2Su
Post Reply