mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen/arm: introduce put_page_nr and get_page_nr
Later, we need to add the right amount of references, which should be the number of borrower domains, to the owner domain. Since we only have get_page() to increment the page reference by 1, a loop is needed per page, which is inefficient and time-consuming. To save the loop time, this commit introduces a set of new helpers put_page_nr() and get_page_nr() to increment/drop the page reference by nr. Signed-off-by: Penny Zheng <penny.zheng@arm.com> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org> Reviewed-by: Julien Grall <jgrall@amazon.com>
This commit is contained in:
1 parent
83d55ba817
commit
5951b856d8
2 files changed
+37
-9
No files matched your search
@@ -363,6 +363,10 @@ void free_init_memory(void);
|
||||
int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
|
||||
unsigned int order);
|
||||
|
||||
extern bool get_page_nr(struct page_info *page, const struct domain *domain,
|
||||
unsigned long nr);
|
||||
extern void put_page_nr(struct page_info *page, unsigned long nr);
|
||||
|
||||
extern void put_page_type(struct page_info *page);
|
||||
static inline void put_page_and_type(struct page_info *page)
|
||||
{
|
||||
|
||||
+33
-9
@@ -1465,21 +1465,29 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct domain *page_get_owner_and_reference(struct page_info *page)
|
||||
static struct domain *page_get_owner_and_nr_reference(struct page_info *page,
|
||||
unsigned long nr)
|
||||
{
|
||||
unsigned long x, y = page->count_info;
|
||||
struct domain *owner;
|
||||
|
||||
/* Restrict nr to avoid "double" overflow */
|
||||
if ( nr >= PGC_count_mask )
|
||||
{
|
||||
ASSERT_UNREACHABLE();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
do {
|
||||
x = y;
|
||||
/*
|
||||
* Count == 0: Page is not allocated, so we cannot take a reference.
|
||||
* Count == -1: Reference count would wrap, which is invalid.
|
||||
*/
|
||||
if ( unlikely(((x + 1) & PGC_count_mask) <= 1) )
|
||||
if ( unlikely(((x + nr) & PGC_count_mask) <= nr) )
|
||||
return NULL;
|
||||
}
|
||||
while ( (y = cmpxchg(&page->count_info, x, x + 1)) != x );
|
||||
while ( (y = cmpxchg(&page->count_info, x, x + nr)) != x );
|
||||
|
||||
owner = page_get_owner(page);
|
||||
ASSERT(owner);
|
||||
@@ -1487,14 +1495,19 @@ struct domain *page_get_owner_and_reference(struct page_info *page)
|
||||
return owner;
|
||||
}
|
||||
|
||||
void put_page(struct page_info *page)
|
||||
struct domain *page_get_owner_and_reference(struct page_info *page)
|
||||
{
|
||||
return page_get_owner_and_nr_reference(page, 1);
|
||||
}
|
||||
|
||||
void put_page_nr(struct page_info *page, unsigned long nr)
|
||||
{
|
||||
unsigned long nx, x, y = page->count_info;
|
||||
|
||||
do {
|
||||
ASSERT((y & PGC_count_mask) != 0);
|
||||
ASSERT((y & PGC_count_mask) >= nr);
|
||||
x = y;
|
||||
nx = x - 1;
|
||||
nx = x - nr;
|
||||
}
|
||||
while ( unlikely((y = cmpxchg(&page->count_info, x, nx)) != x) );
|
||||
|
||||
@@ -1507,19 +1520,30 @@ void put_page(struct page_info *page)
|
||||
}
|
||||
}
|
||||
|
||||
bool get_page(struct page_info *page, const struct domain *domain)
|
||||
void put_page(struct page_info *page)
|
||||
{
|
||||
const struct domain *owner = page_get_owner_and_reference(page);
|
||||
put_page_nr(page, 1);
|
||||
}
|
||||
|
||||
bool get_page_nr(struct page_info *page, const struct domain *domain,
|
||||
unsigned long nr)
|
||||
{
|
||||
const struct domain *owner = page_get_owner_and_nr_reference(page, nr);
|
||||
|
||||
if ( likely(owner == domain) )
|
||||
return true;
|
||||
|
||||
if ( owner != NULL )
|
||||
put_page(page);
|
||||
put_page_nr(page, nr);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool get_page(struct page_info *page, const struct domain *domain)
|
||||
{
|
||||
return get_page_nr(page, domain, 1);
|
||||
}
|
||||
|
||||
/* Common code requires get_page_type and put_page_type.
|
||||
* We don't care about typecounts so we just do the minimum to make it
|
||||
* happy. */
|
||||
|
||||