Mailing List Archive

[xen master] x86/shadow: replace sh_reset_l3_up_pointers()
commit d04a6ee164f55f99a638998c60c16c12701d840f
Author: Jan Beulich <jbeulich@suse.com>
AuthorDate: Mon Feb 13 10:07:03 2023 +0100
Commit: Jan Beulich <jbeulich@suse.com>
CommitDate: Mon Feb 13 10:07:03 2023 +0100

x86/shadow: replace sh_reset_l3_up_pointers()

Rather than doing a separate hash walk (and then even using the vCPU
variant, which is to go away), do the up-pointer-clearing right in
sh_unpin(), as an alternative to the (now further limited) enlisting on
a "free floating" list fragment. This utilizes the fact that such list
fragments are traversed only for multi-page shadows (in shadow_free()
and sh_next_page()). Furthermore sh_terminate_list() is a safe guard
only anyway, which isn't in use in the common case (it actually does
something only for BIGMEM configurations).

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
xen/arch/x86/mm/shadow/common.c | 23 -----------------------
xen/arch/x86/mm/shadow/multi.c | 1 -
xen/arch/x86/mm/shadow/private.h | 26 +++++++++++++++-----------
3 files changed, 15 insertions(+), 35 deletions(-)

diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c
index a74b15e3e7..18a23c28e5 100644
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -2369,29 +2369,6 @@ static void sh_detach_old_tables(struct vcpu *v)
}
}

-/**************************************************************************/
-
-/* Reset the up-pointers of every L3 shadow to 0.
- * This is called when l3 shadows stop being pinnable, to clear out all
- * the list-head bits so the up-pointer field is properly inititalised. */
-static int cf_check sh_clear_up_pointer(
- struct vcpu *v, mfn_t smfn, mfn_t unused)
-{
- mfn_to_page(smfn)->up = 0;
- return 0;
-}
-
-void sh_reset_l3_up_pointers(struct vcpu *v)
-{
- static const hash_vcpu_callback_t callbacks[SH_type_unused] = {
- [SH_type_l3_64_shadow] = sh_clear_up_pointer,
- };
-
- HASH_CALLBACKS_CHECK(SHF_L3_64);
- hash_vcpu_foreach(v, SHF_L3_64, callbacks, INVALID_MFN);
-}
-
-
/**************************************************************************/

static void sh_update_paging_modes(struct vcpu *v)
diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c
index 3b06cfaf9a..b6e844df95 100644
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -971,7 +971,6 @@ sh_make_shadow(struct vcpu *v, mfn_t gmfn, u32 shadow_type)
sh_unpin(d, page_to_mfn(sp));
}
d->arch.paging.shadow.opt_flags &= ~SHOPT_LINUX_L3_TOPLEVEL;
- sh_reset_l3_up_pointers(v);
}
}
#endif
diff --git a/xen/arch/x86/mm/shadow/private.h b/xen/arch/x86/mm/shadow/private.h
index 79d82364fc..8cd2d60d13 100644
--- a/xen/arch/x86/mm/shadow/private.h
+++ b/xen/arch/x86/mm/shadow/private.h
@@ -505,11 +505,6 @@ void shadow_blow_tables(struct domain *d);
*/
int sh_remove_all_mappings(struct domain *d, mfn_t gmfn, gfn_t gfn);

-/* Reset the up-pointers of every L3 shadow to 0.
- * This is called when l3 shadows stop being pinnable, to clear out all
- * the list-head bits so the up-pointer field is properly inititalised. */
-void sh_reset_l3_up_pointers(struct vcpu *v);
-
/******************************************************************************
* Flags used in the return value of the shadow_set_lXe() functions...
*/
@@ -729,7 +724,7 @@ static inline void sh_unpin(struct domain *d, mfn_t smfn)
{
struct page_list_head tmp_list, *pin_list;
struct page_info *sp, *next;
- unsigned int i, head_type;
+ unsigned int i, head_type, sz;

ASSERT(mfn_valid(smfn));
sp = mfn_to_page(smfn);
@@ -741,20 +736,29 @@ static inline void sh_unpin(struct domain *d, mfn_t smfn)
return;
sp->u.sh.pinned = 0;

- /* Cut the sub-list out of the list of pinned shadows,
- * stitching it back into a list fragment of its own. */
+ sz = shadow_size(head_type);
+
+ /*
+ * Cut the sub-list out of the list of pinned shadows, stitching
+ * multi-page shadows back into a list fragment of their own.
+ */
pin_list = &d->arch.paging.shadow.pinned_shadows;
INIT_PAGE_LIST_HEAD(&tmp_list);
- for ( i = 0; i < shadow_size(head_type); i++ )
+ for ( i = 0; i < sz; i++ )
{
ASSERT(sp->u.sh.type == head_type);
ASSERT(!i || !sp->u.sh.head);
next = page_list_next(sp, pin_list);
page_list_del(sp, pin_list);
- page_list_add_tail(sp, &tmp_list);
+ if ( sz > 1 )
+ page_list_add_tail(sp, &tmp_list);
+ else if ( head_type == SH_type_l3_64_shadow )
+ sp->up = 0;
sp = next;
}
- sh_terminate_list(&tmp_list);
+
+ if ( sz > 1 )
+ sh_terminate_list(&tmp_list);

sh_put_ref(d, smfn, 0);
}
--
generated by git-patchbot for /home/xen/git/xen.git#master