-
Notifications
You must be signed in to change notification settings - Fork 164
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_64: mm: support numa migration pte entry #379
base: main
Are you sure you want to change the base?
Conversation
The PRESENT bit alone does not indicate whether a page actually exists. The PRESENT bit is also cleared for numa migration pte entries, even though the page is present. Therefore, to determine if a page truly exists, we need to check pte and convert it to phys in the same way the kernel does. Signed-off-by: Hao Li <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a great find, thank you! I left a few comments.
table = entry & ADDRESS_MASK; | ||
if (!(entry & PRESENT) || (entry & PSE) || level == 0) { | ||
table = entry & PTE_PFN_MASK; | ||
if (!(entry & _PAGE_PRESENT) || (entry & PSE) || level == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can huge pages also have numa migration entries? pmd_present()
in the kernel checks _PAGE_PROTNONE
, so maybe 2MB huge pages can? If so, this check probably needs to be slightly different (and depend on the level).
if (pte_present(entry)) | ||
*phys_addr_ret = pte_phys(entry); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will also get entries for higher levels (for huge pages or unmapped levels), so the pte_*
names are not completely accurate. The functions themselves probably also need to depend on the level as noted above.
|
||
static inline uint64_t protnone_mask(uint64_t val) | ||
{ | ||
return __pte_needs_invert(val) ? ~0ull : 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In theory, ~0ull
could be a different size than uint64_t
, so I'd feel better about:
return __pte_needs_invert(val) ? ~0ull : 0; | |
return __pte_needs_invert(val) ? -1 : 0; |
static inline bool __pte_needs_invert(uint64_t val) | ||
{ | ||
return val && !(val & _PAGE_PRESENT); | ||
} | ||
|
||
static inline uint64_t protnone_mask(uint64_t val) | ||
{ | ||
return __pte_needs_invert(val) ? ~0ull : 0; | ||
} | ||
|
||
static inline uint64_t pte_flags(uint64_t pte) | ||
{ | ||
return pte & ((1 << PAGE_SHIFT) - 1); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer to fold these small helpers into their callers.
The PRESENT bit alone does not indicate whether a page actually exists. The PRESENT bit is also cleared for numa migration pte entries, even though the page is present. Therefore, to determine if a page truly exists, we need to check pte and convert it to phys in the same way the kernel does.
Fix #370
Signed-off-by: Hao Li [email protected]