x86/mm: re-implement get_page_light() using an atomic increment

The current usage of a cmpxchg loop to increase the value of page count is not
optimal on amd64, as there's already an instruction to do an atomic add to a
64bit integer.

Switch the code in get_page_light() to use an atomic increment, as that avoids
a loop construct.  This slightly changes the order of the checks, as current
code will crash before modifying the page count_info if the conditions are not
correct, while with the proposed change the crash will happen immediately
after having carried the counter increase.  Since we are crashing anyway, I
don't believe the re-ordering to have any meaningful impact.

Note that the page must already have a non-zero reference count which prevents
the flags from changing, and the previous usage of the cmpxchg loop didn't
guarantee that the rest of the fields in count_info didn't change while
updating the reference count.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
Roger Pau Monné authored and Andrew Cooper committed 2024-03-01 20:14:19 +00:00
1 parent de17162caf
commit c40bc0576d
1 file changed
+3 -9
+3 -9
View File
@@ -2580,16 +2580,10 @@ bool get_page(struct page_info *page, const struct domain *domain)
*/ */
static void get_page_light(struct page_info *page) static void get_page_light(struct page_info *page)
{ {
unsigned long x, nx, y = page->count_info; unsigned long old_pgc = arch_fetch_and_add(&page->count_info, 1);
do { BUG_ON(!(old_pgc & PGC_count_mask)); /* Not allocated? */
x = y; BUG_ON(!((old_pgc + 1) & PGC_count_mask)); /* Overflow? */
nx = x + 1;
BUG_ON(!(x & PGC_count_mask)); /* Not allocated? */
BUG_ON(!(nx & PGC_count_mask)); /* Overflow? */
y = cmpxchg(&page->count_info, x, nx);
}
while ( unlikely(y != x) );
} }
static int validate_page(struct page_info *page, unsigned long type, static int validate_page(struct page_info *page, unsigned long type,
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.