mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
x86/shadow: move OOS flag bit positions
In preparation of reducing struct page_info's shadow_flags field to 16
bits, lower the bit positions used for SHF_out_of_sync and
SHF_oos_may_write.
Instead of also adjusting the open coded use in _get_page_type(),
introduce shadow_prepare_page_type_change() to contain knowledge of the
bit positions to shadow code.
This is part of XSA-280.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Tim Deegan <tim@xen.org>
master commit: d68e1070c3
master date: 2018-11-20 14:59:13 +0100
This commit is contained in:
1 parent
045d4f77e9
commit
4f3858fcf0
4 files changed
+35
-11
No files matched your search
+2
-9
@@ -2761,15 +2761,8 @@ static int __get_page_type(struct page_info *page, unsigned long type,
|
||||
{
|
||||
struct domain *d = page_get_owner(page);
|
||||
|
||||
/* Normally we should never let a page go from type count 0
|
||||
* to type count 1 when it is shadowed. One exception:
|
||||
* out-of-sync shadowed pages are allowed to become
|
||||
* writeable. */
|
||||
if ( d && shadow_mode_enabled(d)
|
||||
&& (page->count_info & PGC_page_table)
|
||||
&& !((page->shadow_flags & (1u<<29))
|
||||
&& type == PGT_writable_page) )
|
||||
shadow_remove_all_shadows(d, _mfn(page_to_mfn(page)));
|
||||
if ( d && shadow_mode_enabled(d) )
|
||||
shadow_prepare_page_type_change(d, page, type);
|
||||
|
||||
ASSERT(!(x & PGT_pae_xen_l2));
|
||||
if ( (x & PGT_type_mask) != type )
|
||||
|
||||
@@ -988,6 +988,9 @@ int sh_unsync(struct vcpu *v, mfn_t gmfn)
|
||||
|| !v->domain->arch.paging.shadow.oos_active )
|
||||
return 0;
|
||||
|
||||
BUILD_BUG_ON(!(typeof(pg->shadow_flags))SHF_out_of_sync);
|
||||
BUILD_BUG_ON(!(typeof(pg->shadow_flags))SHF_oos_may_write);
|
||||
|
||||
pg->shadow_flags |= SHF_out_of_sync|SHF_oos_may_write;
|
||||
oos_hash_add(v, gmfn);
|
||||
perfc_incr(shadow_unsync);
|
||||
@@ -2887,6 +2890,26 @@ void sh_remove_shadows(struct domain *d, mfn_t gmfn, int fast, int all)
|
||||
paging_unlock(d);
|
||||
}
|
||||
|
||||
void shadow_prepare_page_type_change(struct domain *d, struct page_info *page,
|
||||
unsigned long new_type)
|
||||
{
|
||||
if ( !(page->count_info & PGC_page_table) )
|
||||
return;
|
||||
|
||||
#if (SHADOW_OPTIMIZATIONS & SHOPT_OUT_OF_SYNC)
|
||||
/*
|
||||
* Normally we should never let a page go from type count 0 to type
|
||||
* count 1 when it is shadowed. One exception: out-of-sync shadowed
|
||||
* pages are allowed to become writeable.
|
||||
*/
|
||||
if ( (page->shadow_flags & SHF_oos_may_write) &&
|
||||
new_type == PGT_writable_page )
|
||||
return;
|
||||
#endif
|
||||
|
||||
shadow_remove_all_shadows(d, page_to_mfn(page));
|
||||
}
|
||||
|
||||
static void
|
||||
sh_remove_all_shadows_and_parents(struct domain *d, mfn_t gmfn)
|
||||
/* Even harsher: this is a HVM page that we thing is no longer a pagetable.
|
||||
|
||||
@@ -287,8 +287,8 @@ static inline void sh_terminate_list(struct page_list_head *tmp_list)
|
||||
* codepath is called during that time and is sensitive to oos issues, it may
|
||||
* need to use the second flag.
|
||||
*/
|
||||
#define SHF_out_of_sync (1u<<30)
|
||||
#define SHF_oos_may_write (1u<<29)
|
||||
#define SHF_out_of_sync (1u << (SH_type_max_shadow + 1))
|
||||
#define SHF_oos_may_write (1u << (SH_type_max_shadow + 2))
|
||||
|
||||
#endif /* (SHADOW_OPTIMIZATIONS & SHOPT_OUT_OF_SYNC) */
|
||||
|
||||
|
||||
@@ -81,6 +81,10 @@ void shadow_final_teardown(struct domain *d);
|
||||
|
||||
void sh_remove_shadows(struct domain *d, mfn_t gmfn, int fast, int all);
|
||||
|
||||
/* Adjust shadows ready for a guest page to change its type. */
|
||||
void shadow_prepare_page_type_change(struct domain *d, struct page_info *page,
|
||||
unsigned long new_type);
|
||||
|
||||
/* Discard _all_ mappings from the domain's shadows. */
|
||||
void shadow_blow_tables_per_domain(struct domain *d);
|
||||
|
||||
@@ -96,6 +100,10 @@ void shadow_blow_tables_per_domain(struct domain *d);
|
||||
static inline void sh_remove_shadows(struct domain *d, mfn_t gmfn,
|
||||
bool_t fast, bool_t all) {}
|
||||
|
||||
static inline void shadow_prepare_page_type_change(struct domain *d,
|
||||
struct page_info *page,
|
||||
unsigned long new_type) {}
|
||||
|
||||
static inline void shadow_blow_tables_per_domain(struct domain *d) {}
|
||||
|
||||
static inline int shadow_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
|
||||
|
||||