Now that I have implemented multitasking, memory management, and flat binary loading/execution, the next step would be multitasking flat binaries. Problem is I have all of my binaries linked at 0x600000. I could either switch to ELF and use relocation (not much information about that besides white papers on the format's specs), require all user programs to link at a different address (yuck), or create a separate virtual address space for each one by mapping the physical address I loaded the program at to 0x600000 (where I linked it).
Well I tried to do option 3. Now I hate pasting lots of code on here but I really have no way of debugging this unless Bochs can output its memory map for me and I have looked this over multiple times and tried out various things but to no avail.
InitMem SHOULD set up a linear mapping of physical -> virtual memory based on the amount of physical memory in KB (obtained from GRUB via multiboot header). Then it should set the rest of the page directory as not present and install the page directory into CR3 and enable CR0.
The map page function should do just as it implies, map a physical to virtual address.
The reload_page_mapping function is called to switch address spaces.
Upon loading a program, I allocate a page for it and map it to 0x600000.
I then copy the code to address 0x600000 which SHOULD now point to the allocated page from step 1. Now I just create a new task structure and set address to the physical address.
Cut to when the scheduler runs. After picking a new task, I switch address spaces.
When I actually run it, the first program I load is run in each virtual console instead of having both programs run at the same time. Something is awry with address space switching.
Having problems with address space switching.
Re:Having problems with address space switching.
Well, since nobody has replied, let me ask you this. Is simply changing the CR3 enough to switch address spaces? In that case, I at least know that the code that maps and sets up paging is at fault as opposed to the actual address space switching code.
Re:Having problems with address space switching.
Yes, it is. Writing to CR3 also flushes the whole TLB, so you won't have troubles with cached translations either. But mind that this does not apply to writes to the page directory itself, or the page tables: there you will have to invalidate the corresponding TLB entries yourself.TheChuckster wrote: Is simply changing the CR3 enough to switch address spaces?
cheers Joe
Re:Having problems with address space switching.
Hi,
One way to find your problem would be to replace your "write_cr3()" macro with something that does an infinite loop.
This way you could could use Bochs debugger to stop it, and then manually check if everything is correct using the "xp" instruction.
I'd start with the value you were about to put into CR3, and then check the page directory, and then check page tables.
Also, whenever you change the contents of a page table you should "invalidate the TLB" so that the CPU realises that it's been changed. The best way to do this is with the INVLPG instruction, but reloading CR3 can also work (if you don't use "global pages").
For example, you could probably call "reload_page_mapping()" at the end of the "map_page()" function...
Cheers,
Brendan
Changing CR3 is all that is required to switch address spaces..TheChuckster wrote: Well, since nobody has replied, let me ask you this. Is simply changing the CR3 enough to switch address spaces? In that case, I at least know that the code that maps and sets up paging is at fault as opposed to the actual address space switching code.
One way to find your problem would be to replace your "write_cr3()" macro with something that does an infinite loop.
This way you could could use Bochs debugger to stop it, and then manually check if everything is correct using the "xp" instruction.
I'd start with the value you were about to put into CR3, and then check the page directory, and then check page tables.
Also, whenever you change the contents of a page table you should "invalidate the TLB" so that the CPU realises that it's been changed. The best way to do this is with the INVLPG instruction, but reloading CR3 can also work (if you don't use "global pages").
For example, you could probably call "reload_page_mapping()" at the end of the "map_page()" function...
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re:Having problems with address space switching.
I switched code back to KJ's paging tutorial.
This is what you see at the page directory location in RAM.
Is 0x00201023 even right? Doesn't the address need bit shifted left by some number to get it in bits 32-12?
Reverting back to my own code, my page directory looks like this:
Where's that 2 coming from before the 3 in the first entry?! And shouldn't my page table addresses be increasing by 1000h because they're 4096 bytes long?
Code: Select all
0x00200000 <bogus+ 0>: 0x00201023 0x00000002 0x00000002 0x00000002
0x00200010 <bogus+ 16>: 0x00000002 0x00000002 0x00000002 0x00000002
0x00200020 <bogus+ 32>: 0x00000002 0x00000002
Code: Select all
page_directory[0] = (unsigned long)page_table;
page_directory[0] = page_directory[0] | 3;
Reverting back to my own code, my page directory looks like this:
Code: Select all
0x00200000 <bogus+ 0>: 0x00201023 0x00205003 0x00209003 0x0020d003
0x00200010 <bogus+ 16>: 0x00211003 0x00215003 0x00219003 0x00000002
0x00200020 <bogus+ 32>: 0x00000002 0x00000002
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Having problems with address space switching.
the '2' before '3' just means your page has been accessed. See intel manual for details about those bits, but "dirty" and "accessed" are set by the CPU as memory is referenced.
Also, yes, stepping should be 0x1000 between each page ...
However, "pagetable" is an unsigned pointer, so when you have
'pagetable' points to the next _unsigned_, not the next byte, that is, pagetable now equals 0xcafebac2 ...
So guess, if you write page_table + i*4096, the resulting value is actually a pointer ix16K bytes further than page_table
Also, yes, stepping should be 0x1000 between each page ...
However, "pagetable" is an unsigned pointer, so when you have
Code: Select all
pagetable=(unsigned*)0xcafebabe;
pagetable++;
So guess, if you write page_table + i*4096, the resulting value is actually a pointer ix16K bytes further than page_table