mirror of
https://github.com/xen-project/xen.git
synced 2026-10-30 03:00:05 +01:00
x86 shadow: reset up-pointers on all l3s when l3s stop being pinnable.
Walking the pinned-shadows list isn't enough: there could be an unpinned (but still shadowed) l3 somewhere and if we later try to unshadow it it'll have an up-pointer of PAGE_LIST_NULL:PAGE_LIST_NULL. Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
This commit is contained in:
1 parent
49c831eaa4
commit
367bfd397c
3 files changed
+48
-3
No files matched your search
@@ -2774,6 +2774,47 @@ sh_remove_all_shadows_and_parents(struct vcpu *v, mfn_t gmfn)
|
||||
* It means extra emulated writes and slows down removal of mappings. */
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
/* 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 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 hash_callback_t callbacks[SH_type_unused] = {
|
||||
NULL, /* none */
|
||||
NULL, /* l1_32 */
|
||||
NULL, /* fl1_32 */
|
||||
NULL, /* l2_32 */
|
||||
NULL, /* l1_pae */
|
||||
NULL, /* fl1_pae */
|
||||
NULL, /* l2_pae */
|
||||
NULL, /* l2h_pae */
|
||||
NULL, /* l1_64 */
|
||||
NULL, /* fl1_64 */
|
||||
NULL, /* l2_64 */
|
||||
NULL, /* l2h_64 */
|
||||
#if CONFIG_PAGING_LEVELS >= 4
|
||||
sh_clear_up_pointer, /* l3_64 */
|
||||
#else
|
||||
NULL, /* l3_64 */
|
||||
#endif
|
||||
NULL, /* l4_64 */
|
||||
NULL, /* p2m */
|
||||
NULL /* unused */
|
||||
};
|
||||
static unsigned int callback_mask = 1 << SH_type_l3_64_shadow;
|
||||
|
||||
hash_foreach(v, callback_mask, callbacks, _mfn(INVALID_MFN));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
static void sh_update_paging_modes(struct vcpu *v)
|
||||
|
||||
@@ -1634,12 +1634,10 @@ sh_make_shadow(struct vcpu *v, mfn_t gmfn, u32 shadow_type)
|
||||
page_list_for_each_safe(sp, t, &v->domain->arch.paging.shadow.pinned_shadows)
|
||||
{
|
||||
if ( sp->u.sh.type == SH_type_l3_64_shadow )
|
||||
{
|
||||
sh_unpin(v, page_to_mfn(sp));
|
||||
sp->up = 0;
|
||||
}
|
||||
}
|
||||
v->domain->arch.paging.shadow.opt_flags &= ~SHOPT_LINUX_L3_TOPLEVEL;
|
||||
sh_reset_l3_up_pointers(v);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -475,6 +475,12 @@ mfn_t oos_snapshot_lookup(struct vcpu *v, mfn_t gmfn);
|
||||
|
||||
#endif /* (SHADOW_OPTIMIZATIONS & SHOPT_OUT_OF_SYNC) */
|
||||
|
||||
|
||||
/* 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...
|
||||
*/
|
||||
|
||||