Initializing Paging from within the kernel
Initializing Paging from within the kernel
Can I initialize paging after my C kernel has started, and been linked at 0x100000? Or do i have to initialize it before and link it to a virtual address. Also, ive written a working physical memory allocator with the help of Tim's tutorial, what i dont understand is, once paging is enabled, how does the physical allocator work? Wont the addresses all be virtual?
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Initializing Paging from within the kernel
It is possible to handle the paging initialization either before or within the "C" part of the kernel. However, when paging is enabled within the C kernel, it is preferable to keep the kernel region identically mapped (so that you can still use the same logical addresses for the kernel with or without paging).
If you want to load your kernel in high addresses like 0xC000.0000 .. 0xFFFF.FFFF like Linux does, it is probably easier to initialize paging before you execute the kernel - as these addresses are unlikely to be valid memory without paging...
If you see nothing wrong with having your kernel located in the low memory range (either real mode area or just starting at 1Mb), then you can just keep the same mapping.
As people might want to keep 1MB area free for the use of VM86 programs, the "kernel in low area" seems not to be in the mood.
What you could also do is
1. load your kernel in physical memory starting at 1MB.
2. have no paging at start-up, but a kernel code & data segment that have a base such as 1MB == 3GB (0xC000.0000)
3. Enable paging mapping logical linear address 0xC000.0000 -> ... to physical addresses 0x0010.0000 -> ...)
4. Reset the base of kernel code & data segment so that you have a flat-mode kernel.
From a "programming" point of view, everything remains at the same address and using the same physical memory. You just played on the 2 aspects of the MMU to keep the same translation before and after paging enabling.
Keeping cs.base!=0 is not wishable as it usually prevent the use of fast system calls, etc.
may the CR3 be with You, Use it wisely
If you want to load your kernel in high addresses like 0xC000.0000 .. 0xFFFF.FFFF like Linux does, it is probably easier to initialize paging before you execute the kernel - as these addresses are unlikely to be valid memory without paging...
If you see nothing wrong with having your kernel located in the low memory range (either real mode area or just starting at 1Mb), then you can just keep the same mapping.
As people might want to keep 1MB area free for the use of VM86 programs, the "kernel in low area" seems not to be in the mood.
What you could also do is
1. load your kernel in physical memory starting at 1MB.
2. have no paging at start-up, but a kernel code & data segment that have a base such as 1MB == 3GB (0xC000.0000)
3. Enable paging mapping logical linear address 0xC000.0000 -> ... to physical addresses 0x0010.0000 -> ...)
4. Reset the base of kernel code & data segment so that you have a flat-mode kernel.
From a "programming" point of view, everything remains at the same address and using the same physical memory. You just played on the 2 aspects of the MMU to keep the same translation before and after paging enabling.
Keeping cs.base!=0 is not wishable as it usually prevent the use of fast system calls, etc.
may the CR3 be with You, Use it wisely
Re:Initializing Paging from within the kernel
If paging is enabled before the IDT is loaded, should it be loaded with a virtual address or a physical one?
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Initializing Paging from within the kernel
IDTR.base should always be loaded with a physical address, as GDTR.base and CR3 ...
Re:Initializing Paging from within the kernel
Im sure it says in the intel manuals that the GDT and IDT use virtual addresses to find there locations?
Peter
Peter
Re:Initializing Paging from within the kernel
Nope, it's physical, plain and simple. That's why there is no selector associated with the GDT/IDT registers.pskyboy wrote: Im sure it says in the intel manuals that the GDT and IDT use virtual addresses to find there locations?
Peter
Think of it logically. If the base is a virtual address then how can you load the GDT/IDT register in pmode without a GDT already being present, there would be nowhere to lookup a selector.
-
- Member
- Posts: 1600
- Joined: Wed Oct 18, 2006 11:59 am
- Location: Vienna/Austria
- Contact:
Re:Initializing Paging from within the kernel
*where are lizards? ... ah there is one sofa lizard*
GDT/IDT registers have to be provided with PHYSICAL Adresses. Everything clear?
Prior to enabling paging, it is very wise to have idt up and running - with exception handlers installed.
GDT/IDT registers have to be provided with PHYSICAL Adresses. Everything clear?
Prior to enabling paging, it is very wise to have idt up and running - with exception handlers installed.
... the osdever formerly known as beyond infinity ...
BlueillusionOS iso image
BlueillusionOS iso image
Re:Initializing Paging from within the kernel
Not physical -- linear. If you use LGDT or LIDT with paging enabled, you must use a virtual address. Paging applies to LGDT and LIDT but segment base addresses don't.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Initializing Paging from within the kernel
woow ? so if i enable paging and if i don't have identity mapping for the pages where GDT and IDT are, i must reload GDTR and IDTR in order to have the new virtual address (still referring to the same old physical address) loaded ?Tim Robinson wrote: Not physical -- linear. If you use LGDT or LIDT with paging enabled, you must use a virtual address. Paging applies to LGDT and LIDT but segment base addresses don't.
Re:Initializing Paging from within the kernel
I'm not sure on this.
This works:
This works:
- Set up GDT and switch to protected mode
- Enable paging
- Reload segment registers
- Enable pmode, paging, etc.
- Set up a new GDT (e.g. replacing the old one GRUB set up)
- Use LGDT with virtual (paged) address
- Enable pmode, paging, etc.
- Set up a new GDT
- Use LGDT with physical (RAM) address
Re:Initializing Paging from within the kernel
Hmm, actually things get kinda odd once you start using paging and thinking about these instructions.
The intel manuals specificly state that GDTR/IDTR contain a linear base address and a limit.
Now without paging that's quite simple, linear = physical.
With paging enabled linear != physical though.
LGDT and LIDT also use a linear address, not logical. So they skip the selector:offset translation step.
Now with paging enabled those linear addresses get translated into physical via the page tables. So changing the page tables would screw up the GDT, which obviously doesn't happen.
Guess Tim's right and the physical address is cached in GDTR/IDTR, not the linear address.
Very confusing little area, and the manual isn't exactly transparent on the subject.
BTW, am I the only one confused by this. I always thought memory translation went:
Logical -> Linear -> Physical
So when people are using the term virtual do they mean linear?
The intel manuals specificly state that GDTR/IDTR contain a linear base address and a limit.
Now without paging that's quite simple, linear = physical.
With paging enabled linear != physical though.
LGDT and LIDT also use a linear address, not logical. So they skip the selector:offset translation step.
Now with paging enabled those linear addresses get translated into physical via the page tables. So changing the page tables would screw up the GDT, which obviously doesn't happen.
Guess Tim's right and the physical address is cached in GDTR/IDTR, not the linear address.
Very confusing little area, and the manual isn't exactly transparent on the subject.
BTW, am I the only one confused by this. I always thought memory translation went:
Logical -> Linear -> Physical
So when people are using the term virtual do they mean linear?
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Initializing Paging from within the kernel
I don't feel so ... the GDT can span accross several pages, and i don't remember to have seen any constraints like "all the pages of the GDT must be physically contiguous in memory", which advocates for a paging-translated access to the GDT.Tim Robinson wrote: I guess LGDT caches the 'real' (physical) base address.
There is of course a cache of the physical base address ... but in the Translation Lookaside Buffers ...
Re:Initializing Paging from within the kernel
No way Pype, I just don't buy it.
Let's say your kernel reallocates the page the GDT was contained in, changing linear->physical address calculation. Now that would break your GDT/IDT completely because it would be being translated to the wrong physical address. Then there's the simple cost of translation (Why bother with it if you don't need it?) and for selector loading you simply don't need it.
Guess the only way to know about this for sure is to get paging working properly, load a new gdt, remap the page tables and flush the TLBs. I'm just not convinced that the GDT relies on that base address translation remaining valid after loading.
Let's say your kernel reallocates the page the GDT was contained in, changing linear->physical address calculation. Now that would break your GDT/IDT completely because it would be being translated to the wrong physical address. Then there's the simple cost of translation (Why bother with it if you don't need it?) and for selector loading you simply don't need it.
Guess the only way to know about this for sure is to get paging working properly, load a new gdt, remap the page tables and flush the TLBs. I'm just not convinced that the GDT relies on that base address translation remaining valid after loading.
Re:Initializing Paging from within the kernel
That's true! I do it... I load my GDT & IDT after enbling paging with:Tim Robinson wrote: Not physical -- linear. If you use LGDT or LIDT with paging enabled, you must use a virtual address. Paging applies to LGDT and LIDT but segment base addresses don't.
__asm__ __volatile__ ("lgdtl (%0)" : : "r"((dword)&gdt_ptr));
__asm__("lidtl (%0)" : : "r"((dword)&idt_ptr));
...where &gdt_ptr and &idt_ptr are virtual addresses.