@@ -798,7 +798,7 @@ static void cf_check sh_unshadow_for_p2m
struct domain *d, unsigned long gfn, l1_pgentry_t old, l1_pgentry_t new,
unsigned int level)
{
- mfn_t omfn = l1e_get_mfn(old);
+ mfn_t omfn = l1e_get_mfn(old), nmfn;
unsigned int oflags = l1e_get_flags(old);
p2m_type_t p2mt = p2m_flags_to_type(oflags);
bool flush = false;
@@ -810,19 +810,30 @@ static void cf_check sh_unshadow_for_p2m
if ( unlikely(!d->arch.paging.shadow.total_pages) )
return;
+ /* Only previously present / valid entries need processing. */
+ if ( !(oflags & _PAGE_PRESENT) ||
+ (!p2m_is_valid(p2mt) && !p2m_is_grant(p2mt)) ||
+ !mfn_valid(omfn) )
+ return;
+
+ nmfn = l1e_get_flags(new) & _PAGE_PRESENT ? l1e_get_mfn(new) : INVALID_MFN;
+
switch ( level )
{
default:
/*
* The following assertion is to make sure we don't step on 1GB host
- * page support of HVM guest.
+ * page support of HVM guest. Plus we rely on ->set_entry() to never
+ * be called with orders above PAGE_ORDER_2M, not even to install
+ * non-present entries (which in principle ought to be fine even
+ * without respective large page support).
*/
- ASSERT(!((oflags & _PAGE_PRESENT) && (oflags & _PAGE_PSE)));
+ ASSERT(!(oflags & _PAGE_PSE));
break;
/* If we're removing an MFN from the p2m, remove it from the shadows too */
case 1:
- if ( (p2m_is_valid(p2mt) || p2m_is_grant(p2mt)) && mfn_valid(omfn) )
+ if ( !mfn_eq(nmfn, omfn) )
{
sh_remove_all_shadows_and_parents(d, omfn);
if ( sh_remove_all_mappings(d, omfn, _gfn(gfn)) )
@@ -836,13 +847,13 @@ static void cf_check sh_unshadow_for_p2m
* scheme, that's OK, but otherwise they must be unshadowed.
*/
case 2:
- if ( !(oflags & _PAGE_PRESENT) || !(oflags & _PAGE_PSE) )
+ if ( !(oflags & _PAGE_PSE) )
break;
- if ( p2m_is_valid(p2mt) && mfn_valid(omfn) )
+ ASSERT(!p2m_is_grant(p2mt));
+
{
unsigned int i;
- mfn_t nmfn = l1e_get_mfn(new);
l1_pgentry_t *npte = NULL;
/* If we're replacing a superpage with a normal L1 page, map it */
Pull common checks out of the switch(). This includes extending a _PAGE_PRESENT check to L1 as well, which presumably was deemed redundant with p2m_is_valid() || p2m_is_grant(), but I think we are better off being explicit in all cases. Note that for L2 (or higher) the grant check isn't strictly necessary, as grants are only ever single pages. Leave a respective assertion. For L1 replace the moved out condition with an MFN comparison: There's no need for any update or flushing when the two match. Signed-off-by: Jan Beulich <jbeulich@suse.com> --- v2: Split from previous bigger patch. Add grant related assertion for L2.