Page 1 of 2
implementing paging
Posted: Fri Nov 14, 2008 12:42 pm
by kiwipresse
Hi,
I'm trying to implement paging but I'm confused:
is it necessary to set up the GDT (and IDT, get interrupts working etc.) before I want to use paging? I'm wonder whether I just can enable paging then jump to the higher half and set up all the necessary things. I think that this is a better solution since I can access everything with the virtual adress instead of the physical address and I don't need identity paging. Did I miss something? Is is considered that this is dirty?
I furthermore don't want to do things which GRUB already did for me...
Re: implementing paging
Posted: Fri Nov 14, 2008 12:47 pm
by CodeCat
The paging bit in cr0 has no effect until you enable the protected mode bit as well, as far as I know. But I suppose theoretically you can do both at the same time, as long as both the page tables and GDT are set up when you set the protected mode bit. It would just be rather complicated, but it would probably work.
However, the multiboot specification (used by GRUB) does not guarantee that the GDT has been set up at all, so you should not count on it if you want your OS to be multiboot compatible. All GRUB guarantees is that the current setup of the segment registers is a valid flat-mode segment, but even reloading them with the same values might cause trouble. So to avoid any surprises it's best to just set up your own GDT anyway.
Re: implementing paging
Posted: Fri Nov 14, 2008 1:18 pm
by hailstorm
One short answer: yes, it is necessary. As soon as you want to do the jump to the higher half, the GDT must be initialised with at least the code segment you want to jump to. The IDT however, is not so important at this point (that's how I think about it)...
But I believe you have to divide your kernel into two parts. The first part of your kernel has to initialise the GDT and pagetables, before you jump to the higher (2nd) half. Therefore, the first half of your kernel operates in another address space (since the paging system hasn't been setup). Take that in mind when you're about to link your kernel.
Or do I make big mistake by saying this? Haven't been here for a while lately...
Re: implementing paging
Posted: Fri Nov 14, 2008 5:55 pm
by Combuster
Well, you don't need to have a GDT to enter the higher half - only paging (you're not required to reload CS or any other segment register for that). However having a GDT and IDT can save you a lifetime on the next typo so setting them up is a good idea anyway (the best place would be most likely shortly after jumping to the higherhalf)
The GDT was however needed somewhere before to load the segment registers with the enabling of protected mode, so with your own bootloader you might still have it.
Re: implementing paging
Posted: Fri Nov 14, 2008 6:03 pm
by CodeCat
However, you can't have paging without protected mode, and protected mode without at least some form of GDT is impossible. But if the bootloader (GRUB) boots you in protected mode, then you can set up paging without having to worry about the GDT (there is still a GDT, but it's one that the bootloader set up for you), and you can set up the GDT once you're ready to jump to the higher half. Jumping to the higher half requires a far (absolute) jump, which requires having a valid code segment to jump to, which in turn requires a valid GDT entry for that segment.
Re: implementing paging
Posted: Sat Nov 15, 2008 4:18 am
by Combuster
Higherhalf does *not* require a far jump. Even
Higher_Half_bare_bones doesn't use one. Care to explain why you claim that you have to?
Re: implementing paging
Posted: Sat Nov 15, 2008 6:03 am
by CodeCat
Well, it wouldn't work for me otherwise, but I guess I did something wrong then. I figured the jump had to be absolute and the only way to do that in GAS that I could think of was a far jump.
Re: implementing paging
Posted: Sat Nov 15, 2008 7:16 am
by Combuster
try jumping to a register next time, but not knowing how a processor can do an absolute jump doesn't qualify you for claiming that a far jump is the only possible option. And especially after someone else claims the opposite you shouldn't just repeat that without sensible arguments.
Just try to be careful about spreading false information next time, it doesn't help anybody who is looking for the answer and only brings you bad karma, ok?
Re: implementing paging
Posted: Sat Nov 15, 2008 8:14 am
by CodeCat
How can I prevent spreading false information if I'm not aware the information is false to begin with?
Re: implementing paging
Posted: Sat Nov 15, 2008 10:39 am
by Brynet-Inc
CodeCat wrote:How can I prevent spreading false information if I'm not aware the information is false to begin with?
Uh, by consulting a higher authority.. no not that myth, just manuals.
Re: implementing paging
Posted: Sat Nov 15, 2008 12:50 pm
by Combuster
You claimed the following:
- I can't do it
- Therefore everybody else can't do it as well.
And I think we can agree that that usually leads to the wrong conclusions. (And you could have known that prior to posting even without additional information)
The more appropriate rule is "If I can't do it, someone else probably can unless I can prove it is impossible."
Re: implementing paging
Posted: Sat Nov 15, 2008 3:59 pm
by kiwipresse
First things first: thanks for your help!
I looked at other kernel code and discovered that some projects use start addresses below 0xC0000000 in their linker script but still map their kernel (or it seems to me) to the higher half. And nm told me that they are really not in the 0xC0000000 area. My solution was to put the files which are called from GRUB - or from files which are loaded from GRUB - in their own sections and to put the rest of the kernel in the higher half. Then I enabled paging and jumped to the higher half. Everything works.
But now I wonder whether they are using a better solution? How do they solve the address difference? Relocation? PIC? What did I miss and where can I get further information?
Re: implementing paging
Posted: Sat Nov 15, 2008 4:16 pm
by pcmattman
IIRC, they use a GDT trick that makes the addresses appear to be at 0xC0000000 rather than the actual 0x100000.
I personally think using paging and an "init" section in a linker script is much more efficient and (at least to me) makes more sense.
Re: implementing paging
Posted: Tue Nov 18, 2008 12:13 pm
by kiwipresse
Is it really much more efficient? I mean if I can forget which function lives in the higher half I would probably accept little performance penalty...
But I still don't understand the GDT trick... how can the following formula be true?
0xC0100000 + 0x40000000 = 0x100000
And I also founded projects which use the base address 0xE0000000 and 0x1FFFF as limit to achieve the same?!
Can somebody help me and perhaps refer to in-depth information about this? Thanks.
Re: implementing paging
Posted: Tue Nov 18, 2008 4:03 pm
by Combuster
You're thinking in mathematical terms - the processor is limited to 32 bits, so if you do something that creates a result over 32 bits then it will lose part of the result. That's called an
overflow.
And if you didn't find it yet:
Higher Half With GDT