I followed the Higher Half With GDT tutorial and "loaded" my kernel on the virtual address 0xC0100000. Everything is running fine, but I still don't get how this actually works. I first set the fake GDT, and the base address for code and data is 0x40000000. I understand that it will make the CPU see the 0xC0100000 as 0x100000 (It is where I got my kernel loaded). Then, paging is set up, and the first 4 mb of memory is mapped to 0xC0000000, so I can access the low memory through the higher virtual addresses. I also had to map the first 4mb physical addresses onto the 4mb first virtual addresses. If I don't do this, I believe I'll get a page fault when I try to set the real GDT (with tha base address 0 for code and data).
I read the discussion page of the tutorial, and someone wrote that there's a problem with it. It doesn't clear the first Page Directory Entry after setting up the new GDT. It means that if try to access the first 4 mb virtual adresses, I'll end up accessing the first 4 mb physical addresses. So I cleared the first Page Directory Entry, and I got some page faults at first, because I was directly accessing the multiboot info structure GRUB creates. But I managed it, and the kernel is now working.
But in the meanwhile, I lost the track of what's happening. How the variables addresses are being translated after all. If I try to access an address on the higher half, it will be mapped to lower memory, and it will work. If I try to access a low memory address, I'll get a page fault because it's not properly mapped. But how my kernel is working if It was loaded on the 1 mb of physical memory? I believe the far JUMP executed by the routine which sets the GDT changed the EIP to a high address. But I still don't get how the variables addresses were translated.
If I execute this code:
Code: Select all
int foo = 42;
main()
{
printf("%d", &foo);
}
Well, that's it. If someone could explain what's going on, I'd be thankful.
Thanks in advance.