Having problems with address space switching.

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
TheChuckster

Having problems with address space switching.

Post by TheChuckster »

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.
TheChuckster

Re:Having problems with address space switching.

Post by TheChuckster »

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.
JoeKayzA

Re:Having problems with address space switching.

Post by JoeKayzA »

TheChuckster wrote: Is simply changing the CR3 enough to switch address spaces?
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.

cheers Joe
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re:Having problems with address space switching.

Post by Brendan »

Hi,
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.
Changing CR3 is all that is required to switch address spaces..

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.
TheChuckster

Re:Having problems with address space switching.

Post by TheChuckster »

I switched code back to KJ's paging tutorial.

Code: Select all

0x00200000 <bogus+       0>:    0x00201023      0x00000002      0x00000002      0x00000002
0x00200010 <bogus+      16>:    0x00000002      0x00000002      0x00000002      0x00000002
0x00200020 <bogus+      32>:    0x00000002      0x00000002
This is what you see at the page directory location in RAM.

Code: Select all

page_directory[0] = (unsigned long)page_table;
page_directory[0] = page_directory[0] | 3;
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:

Code: Select all

0x00200000 <bogus+       0>:    0x00201023      0x00205003      0x00209003      0x0020d003
0x00200010 <bogus+      16>:    0x00211003      0x00215003      0x00219003      0x00000002
0x00200020 <bogus+      32>:    0x00000002      0x00000002
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?
User avatar
Pype.Clicker
Member
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.

Post by Pype.Clicker »

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

Code: Select all

pagetable=(unsigned*)0xcafebabe;
pagetable++;
'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 :P
Post Reply