Hey osdevers,
I've been a little lost with this for a while so I thought I would post here for some help.
I have been vaguely following along JamesM's tutorials for developing my OS. I am at the stage in my kernel where I have enabled paging, mapped the first 4MB of physical memory to a higher address (0xc0000000, using the gdt trick) and moved my kernel stack to a different address (0xe0000000). This moving of the stack is done after cloning the kernel directory so that when I clone a page directory, it gets copied rather than linked. This is all fine.
Now in order to create a new task, I clone the page directory. In order to do the cloning of the physical frame, I have to disable paging. When this happens, esp and ebp are no longer valid so in my copy_frame_physical assembly stub, I change my gdt to the trickgdt. The problem is that the stack is no longer the same physical location (since I moved it to a page that is mapped to a different physical address). To fix this I pass the offset to the physical address of esp as a parameter to copy_frame_physical. I then subtract this offset from esp and ebp to get the right physical address. However, this is still failing and causing a triple fault.
My question is, what is the normal way to do this copying of frames when you have a higher half kernel? Is there a cleaner approach?
Note: I haven't provided code as it's on a different machine and I can't get it. I will update the thread with my code tomorrow. In the meantime, if any of you have already done this, I would really appreciate the help (and if possible some code!)
Thanks and best regards!
Manohar
Disabling paging for copying physical frame
- NickJohnson
- Member
- Posts: 1249
- Joined: Tue Mar 24, 2009 8:11 pm
- Location: Sunnyvale, California
Re: Disabling paging for copying physical frame
You can just reserve a region of virtual memory, map in the source and destination frames you want to copy, then do the copy without turning off paging. The overhead of flushing the TLB once is probably less than turning paging on and off, and you can copy multiple frames in one memcpy() operation because they can be made contiguous, so it should be significantly faster.
In general, take any algorithms/suggestions from JamesM's tutorial with a pretty big grain of salt. Many are over-complicated or extremely inefficient, and some just flat out don't work.
In general, take any algorithms/suggestions from JamesM's tutorial with a pretty big grain of salt. Many are over-complicated or extremely inefficient, and some just flat out don't work.
Re: Disabling paging for copying physical frame
Right. That was on my mind after reading a post here a while back but won't these two pages get copied every time you clone a page table?
- NickJohnson
- Member
- Posts: 1249
- Joined: Tue Mar 24, 2009 8:11 pm
- Location: Sunnyvale, California
Re: Disabling paging for copying physical frame
As long as you make sure to allocate that space in a place where its contents won't be copied (i.e. above the higher half) then you should be fine. You could also have some sort of special case in your clone function that avoids touching that region.
Re: Disabling paging for copying physical frame
Yes,
You really only need an empty* ring 0 stack for the interrupts/irqs. This can be simply done by allocating 1-2 frames and mapping them to some arbitrary address.
*Not really empty, but contains the TCB
You really only need an empty* ring 0 stack for the interrupts/irqs. This can be simply done by allocating 1-2 frames and mapping them to some arbitrary address.
*Not really empty, but contains the TCB
Re: Disabling paging for copying physical frame
@berkus Do you mean the trick of iterating over the stack and adding offsets? Any more details on why it doesn't work? I used it in mine and it seems (ostensibly) to work fine. I just map a few pages at 0xe000000 for the stack and copy the stuff over.
@NickJohnson Yes I would have to add some special cases to ignore certain addresses where I map these two temporary "cloning" pages.
I guess mostly I'm just curios to know how others are doing this as the whole process seems a little inelegant. I guess it's just another quirk of the x86 architecture
Thanks!
@NickJohnson Yes I would have to add some special cases to ignore certain addresses where I map these two temporary "cloning" pages.
I guess mostly I'm just curios to know how others are doing this as the whole process seems a little inelegant. I guess it's just another quirk of the x86 architecture
Thanks!
Re: Disabling paging for copying physical frame
One problem is the code that actually updates all the base pointers in the stack has no way to tell the difference between a base pointer or a normal integer. An integer variable, which had the value of an address within the stack by coincidence, would be changed when it shouldn't be.mvanga wrote:@berkus Do you mean the trick of iterating over the stack and adding offsets? Any more details on why it doesn't work? I used it in mine and it seems (ostensibly) to work fine. I just map a few pages at 0xe000000 for the stack and copy the stuff over.
Another problem with the way the stack is dealt with in the JamesM tutorials is the stack pointer you get passed initially by GRUB could be defined to be anything according to the multiboot standard - this means it could point to a memory location you really don't want to be writing to (the kernel code itself, multiboot modules, ACPI tables, some memory mapped I/O area, some memory that doesn't exist.... absolutely anywhere basically.) The tutorials just use whatever GRUB leaves the stack pointer as.
It's fairly easy just to reserve some stack space inside your kernel image itself e.g.
Code: Select all
section .bss align=16
stack_start:
resb 8192
stack_end:
Code: Select all
mov esp, stack_end