How does GDT trick actually work?
Posted: Mon Jan 09, 2012 7:00 am
It's a noob question. But I'm trying hard, and I still don't get what's happening.
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:
An address bigger than 0xC0000000 is printed. But how this happens if the kernel was loaded on the 1 mb mark? I thought the instructions would reference an address located between 1~2 mb of physical memory, and It'd cause a page fault, because this code would access a page that is not on the memory. But it works, and I'm trying to understand how.
Well, that's it. If someone could explain what's going on, I'd be thankful.
Thanks in advance.
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.