struct domain *real_pg_owner;
bool write;
- if ( !(l1f & _PAGE_PRESENT) )
+ if ( unlikely(!(l1f & _PAGE_PRESENT)) )
+ {
+ ASSERT_UNREACHABLE();
return 0;
+ }
if ( unlikely(l1f & l1_disallow_mask(l1e_owner)) )
{
return -EBUSY;
}
-
-/* NB. Virtual address 'l2e' maps to a machine address within frame 'pfn'. */
-/*
- * get_page_from_l2e returns:
- * 1 => page not present
- * 0 => success
- * <0 => error code
- */
define_get_linear_pagetable(l2);
static int
get_page_from_l2e(
unsigned long mfn = l2e_get_pfn(l2e);
int rc;
- if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
- return pv_l1tf_check_l2e(d, l2e) ? -ERESTART : 1;
-
if ( unlikely((l2e_get_flags(l2e) & L2_DISALLOW_MASK)) )
{
gdprintk(XENLOG_WARNING, "Bad L2 flags %x\n",
return rc;
}
-
-/*
- * get_page_from_l3e returns:
- * 1 => page not present
- * 0 => success
- * <0 => error code
- */
define_get_linear_pagetable(l3);
static int
get_page_from_l3e(
{
int rc;
- if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
- return pv_l1tf_check_l3e(d, l3e) ? -ERESTART : 1;
-
if ( unlikely((l3e_get_flags(l3e) & l3_disallow_mask(d))) )
{
gdprintk(XENLOG_WARNING, "Bad L3 flags %x\n",
return rc;
}
-/*
- * get_page_from_l4e returns:
- * 1 => page not present
- * 0 => success
- * <0 => error code
- */
define_get_linear_pagetable(l4);
static int
get_page_from_l4e(
{
int rc;
- if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
- return pv_l1tf_check_l4e(d, l4e) ? -ERESTART : 1;
-
if ( unlikely((l4e_get_flags(l4e) & L4_DISALLOW_MASK)) )
{
gdprintk(XENLOG_WARNING, "Bad L4 flags %x\n",
if ( ret )
goto out;
}
-
- switch ( ret = get_page_from_l1e(pl1e[i], d, d) )
+ else switch ( ret = get_page_from_l1e(pl1e[i], d, d) )
{
default:
goto fail;
for ( i = page->nr_validated_ptes; i < L2_PAGETABLE_ENTRIES; i++ )
{
+ l2_pgentry_t l2e;
+
if ( i > page->nr_validated_ptes && hypercall_preempt_check() )
{
page->nr_validated_ptes = i;
break;
}
- if ( !is_guest_l2_slot(d, type, i) ||
- (rc = get_page_from_l2e(pl2e[i], pfn, d)) > 0 )
+ if ( !is_guest_l2_slot(d, type, i) )
continue;
+ l2e = pl2e[i];
+
+ if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
+ {
+ if ( !pv_l1tf_check_l2e(d, l2e) )
+ continue;
+ rc = -ERESTART;
+ }
+ else
+ rc = get_page_from_l2e(l2e, pfn, d);
+
if ( unlikely(rc == -ERESTART) )
{
page->nr_validated_ptes = i;
break;
}
- pl2e[i] = adjust_guest_l2e(pl2e[i], d);
+ pl2e[i] = adjust_guest_l2e(l2e, d);
}
- if ( rc >= 0 && (type & PGT_pae_xen_l2) )
+ if ( !rc && (type & PGT_pae_xen_l2) )
init_xen_pae_l2_slots(pl2e, d);
unmap_domain_page(pl2e);
- return rc > 0 ? 0 : rc;
+ return rc;
}
static int alloc_l3_table(struct page_info *page)
for ( i = page->nr_validated_ptes; i < L3_PAGETABLE_ENTRIES;
i++, partial = 0 )
{
+ l3_pgentry_t l3e = pl3e[i];
+
if ( is_pv_32bit_domain(d) && (i == 3) )
{
- if ( !(l3e_get_flags(pl3e[i]) & _PAGE_PRESENT) ||
- (l3e_get_flags(pl3e[i]) & l3_disallow_mask(d)) )
+ if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ||
+ (l3e_get_flags(l3e) & l3_disallow_mask(d)) )
rc = -EINVAL;
else
rc = get_page_and_type_from_mfn(
- l3e_get_mfn(pl3e[i]),
+ l3e_get_mfn(l3e),
PGT_l2_page_table | PGT_pae_xen_l2, d, partial, 1);
}
- else if ( (rc = get_page_from_l3e(pl3e[i], pfn, d, partial)) > 0 )
- continue;
+ else if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
+ {
+ if ( !pv_l1tf_check_l3e(d, l3e) )
+ continue;
+ rc = -ERESTART;
+ }
+ else
+ rc = get_page_from_l3e(l3e, pfn, d, partial);
if ( rc == -ERESTART )
{
if ( rc < 0 )
break;
- pl3e[i] = adjust_guest_l3e(pl3e[i], d);
+ pl3e[i] = adjust_guest_l3e(l3e, d);
}
- if ( rc >= 0 && !create_pae_xen_mappings(d, pl3e) )
+ if ( !rc && !create_pae_xen_mappings(d, pl3e) )
rc = -EINVAL;
if ( rc < 0 && rc != -ERESTART && rc != -EINTR )
{
}
unmap_domain_page(pl3e);
- return rc > 0 ? 0 : rc;
+ return rc;
}
void init_xen_pae_l2_slots(l2_pgentry_t *l2t, const struct domain *d)
for ( i = page->nr_validated_ptes; i < L4_PAGETABLE_ENTRIES;
i++, partial = 0 )
{
- if ( !is_guest_l4_slot(d, i) ||
- (rc = get_page_from_l4e(pl4e[i], pfn, d, partial)) > 0 )
+ l4_pgentry_t l4e;
+
+ if ( !is_guest_l4_slot(d, i) )
continue;
+ l4e = pl4e[i];
+
+ if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
+ {
+ if ( !pv_l1tf_check_l4e(d, l4e) )
+ continue;
+ rc = -ERESTART;
+ }
+ else
+ rc = get_page_from_l4e(l4e, pfn, d, partial);
+
if ( rc == -ERESTART )
{
page->nr_validated_ptes = i;
return rc;
}
- pl4e[i] = adjust_guest_l4e(pl4e[i], d);
+ pl4e[i] = adjust_guest_l4e(l4e, d);
}
- if ( rc >= 0 )
+ if ( !rc )
{
init_xen_l4_slots(pl4e, _mfn(pfn),
d, INVALID_MFN, VM_ASSIST(d, m2p_strict));
atomic_inc(&d->arch.pv_domain.nr_l4_pages);
- rc = 0;
}
unmap_domain_page(pl4e);