if ( p2m_to_mask(pt) & P2M_UNMAP_TYPES)
{
ASSERT(mfn_x(r_mfn) == mfn_x(mfn));
- p2m_change_type(d, gfn, pt, p2m_ram_broken);
- rc = 0;
+ rc = p2m_change_type_one(d, gfn, pt, p2m_ram_broken);
}
put_gfn(d, gfn);
unsigned long pfn = domctl->u.set_broken_page_p2m.pfn;
mfn_t mfn = get_gfn_query(d, pfn, &pt);
- if ( unlikely(!mfn_valid(mfn_x(mfn)) || !p2m_is_ram(pt) ||
- (p2m_change_type(d, pfn, pt, p2m_ram_broken) != pt)) )
+ if ( unlikely(!mfn_valid(mfn_x(mfn))) || unlikely(!p2m_is_ram(pt)) )
ret = -EINVAL;
+ else
+ ret = p2m_change_type_one(d, pfn, pt, p2m_ram_broken);
put_gfn(d, pfn);
}
if ( access_w )
{
paging_mark_dirty(v->domain, mfn_x(mfn));
- p2m_change_type(v->domain, gfn, p2m_ram_logdirty, p2m_ram_rw);
+ p2m_change_type_one(v->domain, gfn, p2m_ram_logdirty, p2m_ram_rw);
}
rc = 1;
goto out_put_gfn;
while ( a.nr > start_iter )
{
unsigned long pfn = a.first_pfn + start_iter;
- p2m_type_t t, nt;
+ p2m_type_t t;
get_gfn_unshare(d, pfn, &t);
if ( p2m_is_paging(t) )
goto param_fail4;
}
- nt = p2m_change_type(d, pfn, t, memtype[a.hvmmem_type]);
- if ( nt != t )
- {
- put_gfn(d, pfn);
- printk(XENLOG_G_WARNING
- "d%d: GFN %#lx type changed from %d to %d while trying to change it to %d\n",
- d->domain_id, pfn, t, nt, memtype[a.hvmmem_type]);
- goto param_fail4;
- }
+ rc = p2m_change_type_one(d, pfn, t, memtype[a.hvmmem_type]);
put_gfn(d, pfn);
+ if ( rc )
+ goto param_fail4;
/* Check for continuation if it's not the last interation */
if ( a.nr > ++start_iter && !(start_iter & HVMOP_op_mask) &&
}
/* Change the p2m type, should never fail with p2m locked. */
- BUG_ON(p2m_change_type(d, gfn, p2mt, p2m_ram_shared) != p2mt);
+ BUG_ON(p2m_change_type_one(d, gfn, p2mt, p2m_ram_shared));
/* Account for this page. */
atomic_inc(&nr_shared_mfns);
put_page_and_type(old_page);
private_page_found:
- if ( p2m_change_type(d, gfn, p2m_ram_shared, p2m_ram_rw) !=
- p2m_ram_shared )
+ if ( p2m_change_type_one(d, gfn, p2m_ram_shared, p2m_ram_rw) )
{
gdprintk(XENLOG_ERR, "Could not change p2m type d %hu gfn %lx.\n",
d->domain_id, gfn);
}
-/* Modify the p2m type of a single gfn from ot to nt, returning the
- * entry's previous type. Resets the access permissions. */
-p2m_type_t p2m_change_type(struct domain *d, unsigned long gfn,
- p2m_type_t ot, p2m_type_t nt)
+/*
+ * Modify the p2m type of a single gfn from ot to nt.
+ * Returns: 0 for success, -errno for failure.
+ * Resets the access permissions.
+ */
+int p2m_change_type_one(struct domain *d, unsigned long gfn,
+ p2m_type_t ot, p2m_type_t nt)
{
p2m_access_t a;
p2m_type_t pt;
mfn_t mfn;
struct p2m_domain *p2m = p2m_get_hostp2m(d);
+ int rc;
BUG_ON(p2m_is_grant(ot) || p2m_is_grant(nt));
gfn_lock(p2m, gfn, 0);
mfn = p2m->get_entry(p2m, gfn, &pt, &a, 0, NULL);
- if ( pt == ot )
- p2m_set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, nt, p2m->default_access);
+ rc = likely(pt == ot)
+ ? p2m_set_entry(p2m, gfn, mfn, PAGE_ORDER_4K, nt,
+ p2m->default_access)
+ : -EBUSY;
gfn_unlock(p2m, gfn, 0);
- return pt;
+ return rc;
}
/* Modify the p2m type of a range of gfns from ot to nt. */
p2m_lock(p2m);
for ( i = 0, pfn = begin_pfn; pfn < begin_pfn + nr; i++, pfn++ )
- {
- p2m_type_t pt;
- pt = p2m_change_type(d, pfn, p2m_ram_rw, p2m_ram_logdirty);
- if ( pt == p2m_ram_rw )
+ if ( !p2m_change_type_one(d, pfn, p2m_ram_rw, p2m_ram_logdirty) )
dirty_bitmap[i >> 3] |= (1 << (i & 7));
- }
p2m_unlock(p2m);
unsigned long gfn = base + i;
get_gfn_query(d, gfn, &t);
- p2m_change_type(d, gfn, t, p2m_mmio_dm);
+ p2m_change_type_one(d, gfn, t, p2m_mmio_dm);
put_gfn(d, gfn);
}
p2m_type_t ot, p2m_type_t nt);
/* Compare-exchange the type of a single p2m entry */
-p2m_type_t p2m_change_type(struct domain *d, unsigned long gfn,
- p2m_type_t ot, p2m_type_t nt);
+int p2m_change_type_one(struct domain *d, unsigned long gfn,
+ p2m_type_t ot, p2m_type_t nt);
/* Report a change affecting memory types. */
void p2m_memory_type_changed(struct domain *d);