|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 2/4] x86/mem_sharing: introduce and use page_lock_memshr instead of page_lock
Patch cf4b30dca0a "Add debug code to detect illegal page_lock and put_page_type
ordering" added extra sanity checking to page_lock/page_unlock for debug builds
with the assumption that no hypervisor path ever locks two pages at once.
This assumption doesn't hold during memory sharing so we introduce separate
functions, page_lock_memshr and page_unlock_memshr, to be used exclusively
in the memory sharing subsystem.
Also placing these functions behind their appropriate kconfig gates.
Signed-off-by: Tamas K Lengyel <tamas@xxxxxxxxxxxxx>
Cc: Jan Beulich <jbeulich@xxxxxxxx>
Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Cc: Wei Liu <wei.liu2@xxxxxxxxxx>
Cc: Roger Pau Monne <roger.pau@xxxxxxxxxx>
Cc: George Dunlap <george.dunlap@xxxxxxxxxxxxx>
---
v3: this patch was "x86/mm: conditionally check page_lock/page_unlock ownership"
---
xen/arch/x86/mm.c | 46 ++++++++++++++++++++++++++++-------
xen/arch/x86/mm/mem_sharing.c | 4 +--
xen/include/asm-x86/mm.h | 6 ++++-
3 files changed, 44 insertions(+), 12 deletions(-)
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 45fadbab61..c2c92a96ac 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -2030,12 +2030,11 @@ static inline bool current_locked_page_ne_check(struct
page_info *page) {
#define current_locked_page_ne_check(x) true
#endif
-int page_lock(struct page_info *page)
+#if defined(CONFIG_PV) || defined(CONFIG_HAS_MEM_SHARING)
+static int _page_lock(struct page_info *page)
{
unsigned long x, nx;
- ASSERT(current_locked_page_check(NULL));
-
do {
while ( (x = page->u.inuse.type_info) & PGT_locked )
cpu_relax();
@@ -2046,17 +2045,13 @@ int page_lock(struct page_info *page)
return 0;
} while ( cmpxchg(&page->u.inuse.type_info, x, nx) != x );
- current_locked_page_set(page);
-
return 1;
}
-void page_unlock(struct page_info *page)
+static void _page_unlock(struct page_info *page)
{
unsigned long x, nx, y = page->u.inuse.type_info;
- ASSERT(current_locked_page_check(page));
-
do {
x = y;
ASSERT((x & PGT_count_mask) && (x & PGT_locked));
@@ -2065,11 +2060,44 @@ void page_unlock(struct page_info *page)
/* We must not drop the last reference here. */
ASSERT(nx & PGT_count_mask);
} while ( (y = cmpxchg(&page->u.inuse.type_info, x, nx)) != x );
+}
+#endif
- current_locked_page_set(NULL);
+#ifdef CONFIG_HAS_MEM_SHARING
+int page_lock_memshr(struct page_info *page)
+{
+ return _page_lock(page);
}
+void page_unlock_memshr(struct page_info *page)
+{
+ _page_unlock(page);
+}
+#endif
+
#ifdef CONFIG_PV
+int page_lock(struct page_info *page)
+{
+ int rc;
+
+ ASSERT(current_locked_page_check(NULL));
+
+ rc = _page_lock(page);
+
+ current_locked_page_set(page);
+
+ return rc;
+}
+
+void page_unlock(struct page_info *page)
+{
+ ASSERT(current_locked_page_check(page));
+
+ _page_unlock(page);
+
+ current_locked_page_set(NULL);
+}
+
/*
* PTE flags that a guest may change without re-validating the PTE.
* All other bits affect translation, caching, or Xen's safety.
diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c
index e2f74ac770..4b60bab28b 100644
--- a/xen/arch/x86/mm/mem_sharing.c
+++ b/xen/arch/x86/mm/mem_sharing.c
@@ -118,7 +118,7 @@ static inline int mem_sharing_page_lock(struct page_info
*pg)
pg_lock_data_t *pld = &(this_cpu(__pld));
page_sharing_mm_pre_lock();
- rc = page_lock(pg);
+ rc = page_lock_memshr(pg);
if ( rc )
{
preempt_disable();
@@ -135,7 +135,7 @@ static inline void mem_sharing_page_unlock(struct page_info
*pg)
page_sharing_mm_unlock(pld->mm_unlock_level,
&pld->recurse_count);
preempt_enable();
- page_unlock(pg);
+ page_unlock_memshr(pg);
}
static inline shr_handle_t get_next_handle(void)
diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
index 6faa563167..ba49eee24d 100644
--- a/xen/include/asm-x86/mm.h
+++ b/xen/include/asm-x86/mm.h
@@ -356,7 +356,8 @@ struct platform_bad_page {
const struct platform_bad_page *get_platform_badpages(unsigned int
*array_size);
/* Per page locks:
- * page_lock() is used for two purposes: pte serialization, and memory sharing.
+ * page_lock() is used for pte serialization.
+ * page_lock_memshr() is used for memory sharing.
*
* All users of page lock for pte serialization live in mm.c, use it
* to lock a page table page during pte updates, do not take other locks within
@@ -378,6 +379,9 @@ const struct platform_bad_page
*get_platform_badpages(unsigned int *array_size);
int page_lock(struct page_info *page);
void page_unlock(struct page_info *page);
+int page_lock_memshr(struct page_info *page);
+void page_unlock_memshr(struct page_info *page);
+
void put_page_type(struct page_info *page);
int get_page_type(struct page_info *page, unsigned long type);
int put_page_type_preemptible(struct page_info *page);
--
2.20.1
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |