Page 1 of 2
Address Spaces
Posted: Mon Oct 21, 2002 11:33 am
by PlayOS
Hi all,
Just wondering what the most common (or best) way to handle address spaces between different processes?
Should I use a seperate page directory for each process or should I share a single page directory?
What are your thoughts either way?
Thanks.
Re:Address Spaces
Posted: Tue Oct 22, 2002 4:30 am
by Tim
Unless all your processes share most of their pages (and you don't mind rewriting the one page directory on every address space switch), it will be easier to use a separate page directory for each.
Re:Address Spaces
Posted: Tue Oct 22, 2002 5:00 am
by _PlayOS
Thanks Tim,
How do I go about switching page directories, are there certain conditions that must be met like when you initially switch into paging?
thanks.
Re:Address Spaces
Posted: Tue Oct 22, 2002 6:03 am
by Pype.Clicker
I recommend that the kernel code that performs thread management (threadCreate, threadDestroy, ...), process management and scheduling is available in every address space (i.e. by mapping that code with the appropriated kernel data in every page directory...).
This way, the kernel runs the same in every address space. (it is theorically possible, using task-based exceptions, task-based IRQ handlers and system calls to keep the whole kernel in a separated address space, but it sounds like a CPU-time waste to my senses)
if you want to switch to another address space, all you need to do is
Code: Select all
mov eax, [next_thread.pdbr_address]
mov cr3,eax
which will flush the page mapping cache and reload the page directory base address register (and thus any further memory reference will be interpreted in the new space).
Note however that this operation has a cost: more memory access (the current bottleneck in the architecture) just after the switch.
- at least your kernel code should be marked "global" page so that the switches don't trash the correspondance for it
- if you have a large area (4Mb) of pages that are contiguous in physical memory (that's what i have for my micro-kernel : first 4MB are the same in every space and map first 4MB of physical memory), use a huge (4MB) page rather than 1024 normal (4Kb) pages: you'll save page cache entries for the rest of the system
and, before switching, ensure everything you need is available in the planned directory (i.e. there are pages that map your code) and that the code is still at the proper location (i.e. its physicall address == its logical address).
Re:Address Spaces
Posted: Tue Oct 22, 2002 6:08 am
by _PlayOS
So basically the only restriction on changing the page directory is that the code that does the switch is on a page that has a linear address that is equal to its physical address.
Re:Address Spaces
Posted: Tue Oct 22, 2002 8:00 am
by Pype.Clicker
yep. but for your convenience, its better either to load the kernel *after* paging is engaged or to keep the whole kernel with physical=linear mapping (otherwise, you'll need to relocate the whole kernel to its new base address)
Re:Address Spaces
Posted: Tue Oct 22, 2002 10:39 am
by _PlayOS
Thats a bit rough then.
I thought that if the current linear address stays valid then the processor could continue without a problem, for example:
say that the eip register has 0x5ef45ef (Linear) in it, and I change the page directory, but set it up so that the current code is still at the same linear address, which would keep eip valid, wouldn't the processor just fetch eip (which points to 0x5ef45ef) and find a valid instruction execute that address and because this is where it was going anyway I thought that it might just keep going.
Is this just wishful thinking?
thanks.
Re:Address Spaces
Posted: Tue Oct 22, 2002 2:30 pm
by Tim
The processor is happy as long as EIP doesn't need to change before and after you enable paging. The question is: how do you make linear address 0x5ef45ef valid without enabling paging?
What I do is program the GDT base address with a special value. My kernel starts at virtual address 0xC0000000, which needs to be valid even though paging isn't enabled (which it isn't, at the start). Note that the kernel could be loaded at any physical address.
Remember that the CPU adds the segment base address to the linear address to form a physical address. That is:
physical = base + linear
I have:
0x100000 = base + 0xC0000000
or:
base = 0x100000 - 0xC0000000 = 0x40100000
Although this is a negative value, the CPU doesn't seem to mind, and it just wraps round.
Re:Address Spaces
Posted: Tue Oct 22, 2002 9:38 pm
by PlayOS
OK, well I already have paging enabled, what I am wanting to do it switch to a different page directory everytime the scheduler changes tasks so I was needing a fairly fast and efficient way to do it. That is why I was thinking that if I was at linear address X then if that address stayed consistent for every address space then the processor would just continue processing code at the same address.
What are the most common ways that this is handled?
Is it very common to have a different page directory for each task?
Thanks.
Re:Address Spaces
Posted: Thu Oct 24, 2002 8:28 am
by Tim
OK, the best way is to keep your kernel page tables mapped into every address space. That way kernel code and data are always valid, regardless of what user code is running.
Re:Address Spaces
Posted: Thu Oct 24, 2002 9:04 am
by Pype.Clicker
most unices do have a separate page directory for each process. now, what you can also do is (provided that your processes are small enough) is to keep them all in the same address space and give them a separate LOCAL DESCRIPTOR TABLE, just reloading segment descriptors for the user mode (when kernel returns). this will surely be faster and will give you the ability to provide memory sharing with a low cost (just creating segments to the right places)...
damn! this sounds cool (tough not portable
... i need this in Clicker too
Re:Address Spaces
Posted: Fri Oct 25, 2002 5:51 am
by Tim
This thought occurred to me, too. What you could do is split the address space into four 1GB chunks, one of which is always the kernel. Then you could keep, say, the three last used processes in the bottom three chunks. Each of them would think they had a 1GB address space starting at address zero, because they each get a different segment (from the GDT or LDT).
Provided that the kernel is the only piece of software which is allowed to change selectors, the three are protected from each other. It also allows very fast IPC with a selector reload instead of an address space switch.
Re:Address Spaces
Posted: Fri Oct 25, 2002 10:48 am
by PlayOS
This sounds good, any ideas on how to prevent user programs from trying to force a selector change?
Re:Address Spaces
Posted: Mon Oct 28, 2002 3:07 am
by Pype.Clicker
just mark the selectors it shouldn't access as being not present will cause troubles with multiprocessor systems ... imho, a separate LDT per process is the best way around (the only selectors a process can use are the one the kernel gave it
Re:Address Spaces
Posted: Tue Oct 29, 2002 12:41 pm
by Tim
I think the selectors in this scheme should go into the GDT. If you think about it, you've got (say) four processes running in one address space, each looking at its memory using a different selector. How can that work if each process is using a different LDT?
The purpose of this scheme (well, my scheme at least) is to allow the kernel to access data from different address spaces at no cost. Making it switch LDTs to do that just adds extra complication. In any case, the user-mode apps won't know that this scheme is taking place; all they will notice is that they can only access 1GB instead of 4GB (or less). And once you start using the LDT actively (i.e. giving applications far pointers and expecting them to do their own seg reg loads) you break compatibility with most current 32-bit compilers, assemblers and linkers.