-
Notifications
You must be signed in to change notification settings - Fork 6.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
x86: mmu/demand_paging: supports LRU eviction algorithm #75140
base: main
Are you sure you want to change the base?
x86: mmu/demand_paging: supports LRU eviction algorithm #75140
Conversation
@npitre I actually cannot run this with LRU most of the time, as the LRU code would assert on |
Well... Allright. Fix in #75142.
|
474a06f
to
f74c249
Compare
This adds bits to simulate LRU in software for architectures that do not provide a native mean to figure out least recently used pages. Enabling this changes the eviction selection to clear the access flag if it is set and requeues the page frame for later consideration. Without this, the LRU would simply devolve into picking the earliest paged in frame for eviction. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
The LRU (Least Recently Used) requires additional accounting. So add the code for that. Fixes zephyrproject-rtos#75132 Signed-off-by: Daniel Leung <daniel.leung@intel.com>
f74c249
to
8cabd9a
Compare
Finally got it all working and passing twister with LRU enabled. |
I'm wondering about If I understandit correctly, x86 cannot trigger an exception when a page |
Yes. The hardware only sets the bit when a page is accessed. It is up to software to clear the bit. |
In that case... can't you tweak things a little so an "unaccessed" page is You might have to use another flag to distinguish between really The problems I see with |
That would require clearing the present bit so that any access would generate a page fault. However, handling page fault is expensive on x86. There is no shortcut or "fast interrupt" way of dealing with it.
A more complete and expensive version would be to rearrange periodically. So instead of realtime usage, we sample at fixed interval. Any pages that have been accessed in this period will be moved to the end of queue. So any pages that have not been used for a while would be moved to the front of queue gradually. I did it the way in this PR is to avoid the full rearranging as that would require locking the whole queue, so the code is to do it partially each time an eviction is needed. |
But how expensive is it really?
And that is certainly going to be more expensive than as-needed page fault |
The entrance and exit assembly code before and after any C code have about 70 instructions (in worst case). Most of them are push/pop needing access to main memory. So latency would be even worse if that memory is not already in L1 cache. I took a quick glance at the C page fault handler, and I think marking page being accessed can be done early in that function and should not add too much delays. Then of course the function call to the LRU function to mark page accessed. With all that said, however, I believe that any memory access to pages already in physical memory should not have any additional cost. That it should act as if demand paging is not enabled.
That would depend on how often one goes through the accessed page marking. Though, once you need to involve backing store (i.e. paging in/out memory), the cost is already high. Worst case would be needing to evict a dirty page which requires writing data to backing store. I guess at the end it is a game of where we stash the big baggage of processing. |
Here's what my scenario looks like. RAM size is 8MB. Firmware size is 16MB or more. About half of RAM is At the beginning, many page frames will be free. So for a while there won't When free page frames are exhausted, the eviction algorithm is invoked. Without So maybe the page fault to invoke Maybe at least making this mode of operation an option on x86? |
I need some clarification here... From your description here, Moreover, the fulfill the scheme of least recently used, |
Well, given that later page is appended to the LRU queue with
Of course, "every access" is unrealistic. And yes, the first time a page Now this is only the head page that is made unaccessible to test if it is |
Ah... okay. Let me see what I can do. |
Hm... It is getting tricky on x86. Bits in PTE that are ignored by the CPU have already been re-purposed, so there are no available bits to encode the "not present but still valid" state such that Also piggyback the "clearing the access bit of the queue head" to |
How do you do, then, to support evicted pages? Such a page must fault yet
Nah... you must be able to do it in the pte otherwise it isn't worth it. |
It is not about evicted pages, but to support the 'exception when access bit changes from 0 to 1'. The other bits of PTE need to be preserved in this case. Only the present bit is cleared to generate a "fake" page fault where |
OK... I spent some time looking at the X86 code and I get what you're
saying.
If physical RAM is all below the 2GB mark, you could set bit 31 to
indicate a "soft" fault, hoping that no backing store will use location
token values that big.
Or... you could repurpose MMU_PAT when CONFIG_X86_KPTI=n. That appears
to be the case in qemu_x86_tiny_defconfig.
|
Using bit 31 is not going to work. There is an internal project which maps virtual address on the upper 2GB range (more towards the end of 4GB). Re-purposing the PAT bit is not going to work either. In |
This would be bit 31 of a physical address not a virtual one. Another possibility: is there an actual legitimate case where |
Yep... physical addresses too. The memory map is all over the place... :( I'll need to look into |
The LRU (Least Recently Used) requires additional accounting. So add the code for that.
Fixes #75132