Page 1 of 1

[deleted]

Posted: Thu Jun 10, 2021 11:11 pm
by rpio
[deleted]

Re: How to implement MM?

Posted: Fri Jun 11, 2021 1:01 am
by neon
Hi,

Assuming I understood correctly, I believe the question is about how to update paging structures when Identity Space is removed. Don't worry about working on this for few months, am sure its pretty common -- memory management is arguably one of the most complex parts to get working.

If using 32 bit protected mode... We use recursive paging structures for this. The basic idea is that, during initialization, map a page directory entry to itself (we use the last entry.) What this does is effectively reserve the last 4MB of the virtual address space (assuming the last PDE is recursively mapped) for the current process page tables. This 4MB region will have all the paging structures (i.e. from our kernel):

Code: Select all

MM_PAGE_DIRECTORY_BASE 0xfffff000
MM_PAGE_DIRECTORY_END 0xffffffff
MM_PAGE_TABLE_BASE 0xffc00000
MM_PAGE_TABLE_END 0xffffffff
MM_KERNEL_PAGE_TABLE_BASE 0xfff00000
MM_KERNEL_PAGE_TABLE_END 0xfff00fff
Creating a new page table then just involves getting a new page frame number from the physical memory allocator and setting the PDE from PAGE_DIRECTORY_BASE. This will map a page table within PAGE_TABLE_BASE that you can use to complete the mapping. A downside of this technique is that you lose 4MB of the address space. Another downside is that -- in my opinion -- this technique is very hard to explain and it is recommended to write it down carefully on paper and try to walk through it.

If using 64 bit long mode... the most common recommendation is to just keep Identity Space but mapped into Kernel Space. That way you have access to all of physical memory.

Re: How to implement MM?

Posted: Fri Jun 11, 2021 1:07 am
by rpio
...

Re: How to implement MM?

Posted: Fri Jun 11, 2021 1:16 am
by neon
Hi,

Technically recursive paging works in any mode. It is typically recommended to map Identity Space in Kernel Space for 64 bit long mode because...well...you can so might as well. Recursive paging is typically used in 32 bit protected mode due to the limited 4GB address space: you lose 4MB of the address space but it greatly simplifies paging code in the process.

Re: How to implement MM?

Posted: Fri Jun 11, 2021 5:51 am
by rpio
...

Re: How to implement MM?

Posted: Fri Jun 11, 2021 8:49 am
by neon
Hi,

I am only going to address it in the context of 32 bit protected mode. The process is the same in 64 bit long mode, its just adds additional layers. We also noted earlier that it is very hard to explain and describe through text; we believe it is best to manually walk through it and visualize what is happening. First you must realize how the paging structures map to the virtual address space: a page (i.e. PTE) represents a 4K region of the address space, a page table (PDE) refers to a 4MB region of the address space. The first page table (PDE) is the first 4MB, next page table PDE[1] is the 2nd 4MB, PDE[2] is 3rd 4MB all the way to PDE[1023] for the last 4MB region. Lets walk through it: PDE[1023]=Page Directory (top most layer in 32 bit) is the recursive mapping. So if we try to write to address 0xfffff000 the CPU will lookup PDE[1023] and look at the Page Directory as a Page Table. Since the recursive mapping is setup still, PTE[1023] is still mapped to the page frame of the Page Directory itself. So when accessing 0xfffff000 you would be accessing the Page Directory. But you would also be accessing PTE[1023]. This has the side effect of PTE[0] being at 0xffc00000. Noting each page table is 1024*4 bytes in size, our kernel page table is PDE[768] which maps to 0xffc00000+(768*(1024*4)) = 0xfff00000.

During initialization, we set up recursive paging like this:

Code: Select all

PageDirectoryEntry [0].u.device.valid = 1;
PageDirectoryEntry [0].u.device.pageFrameNumber = IdentitySpacePageTable;

PageDirectoryEntry [KernelPageTableIndex].u.device.valid = 1;
PageDirectoryEntry [KernelPageTableIndex].u.device.pageFrameNumber = KernelPageTable;

PageDirectoryEntry [1023].u.device.valid = 1;
PageDirectoryEntry [1023].u.device.pageFrameNumber = KernelPageDirectory;
When Identity Space is removed, it leaves the kernel page tables and the recursive mapping.

Re: How to implement MM?

Posted: Sat Jun 12, 2021 4:29 am
by rpio
...

Re: How to implement MM?

Posted: Sat Jun 12, 2021 11:22 am
by neon
Hi,
- I didn't really understand the setup of recursive paging, is the only thing I need to do is make the last entry of PD point to PD(the start of it)?
Technically it can be any entry. Most implementations (like Linux 32 bit) uses the last entry. Some implementations use a different index - like Windows (32 bit) uses the 768'th entry. But yes, that PDE[1023]=Page Directory is literally it.
- How do I access tables other then PD(e.g. PT or others in 4 level paging)?
This is where it gets hard to explain due to the recursive definition. Basically, when you map the last page directory entry, any address in the last 4MB region of the address space become effected. What happens is that, during the address translation process, we will go through PDE[1023] to find the page table -- so it will next read the page directory again but this time treating it as a page table. So all page frame numbers in each page table entry refer to the page containing the contents of that respective page table -- keep in mind this is just the page directory being looked at as a page table hence the contents is the same. So to find the page table virtual addresses, we just need to know what page each page table / page directory entry maps to. You have already found one of them: the page directory itself is the last page table -- 1023.

Code: Select all

0xfffff000 is PDE[1023] which is the last page table
0xffffe000 is PDE[1022] which is second to last page table.
0xffffd000 is PDE[1021]
...
0xfff00000 is PDE[768] this is typically the kernel page table for higher half kernels at 3GB
...
0xffc00000 is PDE[0]
So, lets say you need to update the kernel page table. Its respective page directory entry is the 768'th index from 0xfffff000 (MM_PAGE_DIRECTORY_BASE). If you need to update the page table itself, it will always and forever be at 0xfff00000 (MM_KERNEL_PAGE_TABLE_BASE).

Keep in mind all of this assumes you selected the PDE[1023] as the recursive index.

--
I will reiterate that there is no advantage to using recursive paging in 64 bit long mode. You don't lose anything by mapping all of physical memory into kernel space. If you did that, then you can easily determine the actual address and update paging structures. You wouldn't lose memory: in fact, doing this doesn't effect require additional memory at all. Recursive paging was used a lot in 32 bit protected mode as the size of the address space is the same as what was expected of physical memory at the time, so there was few good options available. Using multiple techniques to memory management is important to any good manager: you need to adjust the method depending on the environment to decide how best to manage memory. Even if the intent is trying to make things easier you will end up making it harder by not doing so.

--
As Recursive Paging comes up often, I started writing a small tutorial on it here. It is still a work in progress, but please feel free to point out any potential confusing parts and I will be happy to expand on them as needed.

Re: How to implement MM?

Posted: Sat Jun 12, 2021 11:54 am
by rpio
...

Re: How to implement MM?

Posted: Sat Jun 12, 2021 12:04 pm
by neon
Hi,
the only thing I can think of is that we have an address like 0xffff<index of PT>000, so it interprets PD as PD, then PD as PT and finally it would map the PT at selected offset because it would interpret it as a page
Basically, yes.

Re: How to implement MM?

Posted: Sat Jun 12, 2021 1:06 pm
by rpio
...

Re: How to implement MM?

Posted: Sat Jun 12, 2021 2:53 pm
by neon
Hi,

As I am working out a tutorial at the moment in order to give a more immediate answer I opted to go ahead and refer to this section of the Wiki here as it already documents all of the addresses assuming that you recursively map the last entry of the tables.

--
Perhaps a way to visualize what happens is to imagine overlaying the paging structures on top of each other such that they all share the page that is recursively mapped. For example, in 32 bit non-PAE mode:

Code: Select all

              PD       PT
0xFFFFFFFF    +----+  +----+
              |    |  |    |
0xFFFFF000    +----+  |    |
                      |    |
0xFFC00000            +----+
The last entry of PT is recursively mapped. Likewise in 64 bit:

Code: Select all

                     PML4    PDP        PD       PT
0xFFFFFFFFFFFFFFFF  +----+  +----+    +----+    +----+
                    |    |  |    |    |    |    |    |
0xFFFFFFFFFFFFF000  +----+  |    |    |    |    |    |
                            |    |    |    |    |    |
0xFFFFFFFFFFE00000          +----+    |    |    |    |
                                      |    |    |    |
0xFFFFFFFFC0000000                    +----+    |    |
                                                |    |
0xFFFFFF8000000000                              +----+