xen/arm: p2m: Re-implement relinquish_p2m_mapping using p2m_{get,set}_entry

The function relinquish_p2m_mapping can be re-implemented using
p2m_{get,set}_entry by iterating over the range mapped and using the
mapping order given by the callee.

Given that the preemption was chosen arbitrarily, it is now done on every
512 iterations. Meaning that Xen may check more often if the function is
preempted when there are no mappings.

Finally drop the operation RELINQUISH in apply_* as nobody is using it
anymore. Note that the functions could have been dropped in one go at
the end, however I find easier to drop the operations one by one
avoiding a big deletion in the patch that remove the last operation.

Signed-off-by: Julien Grall <julien.grall@arm.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
Tested-by: Tamas K Lengyel <tamas@tklengyel.com>
This commit is contained in:
Julien Grall authored and Stefano Stabellini committed 2016-09-27 18:14:12 -07:00
1 parent 2ef3e36ec7
commit 438c5fe4f0
1 file changed
+59 -18
+59 -18
View File
@@ -754,7 +754,6 @@ static int p2m_mem_access_radix_set(struct p2m_domain *p2m, gfn_t gfn,
enum p2m_operation {
INSERT,
REMOVE,
RELINQUISH,
MEMACCESS,
};
@@ -1318,7 +1317,6 @@ static int apply_one_level(struct domain *d,
break;
case RELINQUISH:
case REMOVE:
if ( !p2m_valid(orig_pte) )
{
@@ -1502,17 +1500,6 @@ static int apply_p2m_changes(struct domain *d,
{
switch ( op )
{
case RELINQUISH:
/*
* Arbitrarily, preempt every 512 operations or 8192 nops.
* 512*P2M_ONE_PROGRESS == 8192*P2M_ONE_PROGRESS_NOP == 0x2000
* This is set in preempt_count_limit.
*
*/
p2m->lowest_mapped_gfn = _gfn(addr >> PAGE_SHIFT);
rc = -ERESTART;
goto out;
case MEMACCESS:
{
/*
@@ -1919,16 +1906,70 @@ int p2m_init(struct domain *d)
return rc;
}
/*
* The function will go through the p2m and remove page reference when it
* is required. The mapping will be removed from the p2m.
*
* XXX: See whether the mapping can be left intact in the p2m.
*/
int relinquish_p2m_mapping(struct domain *d)
{
struct p2m_domain *p2m = &d->arch.p2m;
unsigned long nr;
unsigned long count = 0;
p2m_type_t t;
int rc = 0;
unsigned int order;
nr = gfn_x(p2m->max_mapped_gfn) - gfn_x(p2m->lowest_mapped_gfn);
/* Convenience alias */
gfn_t start = p2m->lowest_mapped_gfn;
gfn_t end = p2m->max_mapped_gfn;
return apply_p2m_changes(d, RELINQUISH, p2m->lowest_mapped_gfn, nr,
INVALID_MFN, 0, p2m_invalid,
d->arch.p2m.default_access);
p2m_write_lock(p2m);
for ( ; gfn_x(start) < gfn_x(end);
start = gfn_next_boundary(start, order) )
{
mfn_t mfn = p2m_get_entry(p2m, start, &t, NULL, &order);
count++;
/*
* Arbitrarily preempt every 512 iterations.
*/
if ( !(count % 512) && hypercall_preempt_check() )
{
rc = -ERESTART;
break;
}
/*
* p2m_set_entry will take care of removing reference on page
* when it is necessary and removing the mapping in the p2m.
*/
if ( !mfn_eq(mfn, INVALID_MFN) )
{
/*
* For valid mapping, the start will always be aligned as
* entry will be removed whilst relinquishing.
*/
rc = __p2m_set_entry(p2m, start, order, INVALID_MFN,
p2m_invalid, p2m_access_rwx);
if ( unlikely(rc) )
{
printk(XENLOG_G_ERR "Unable to remove mapping gfn=%#"PRI_gfn" order=%u from the p2m of domain %d\n", gfn_x(start), order, d->domain_id);
break;
}
}
}
/*
* Update lowest_mapped_gfn so on the next call we still start where
* we stopped.
*/
p2m->lowest_mapped_gfn = start;
p2m_write_unlock(p2m);
return rc;
}
int p2m_cache_flush(struct domain *d, gfn_t start, unsigned long nr)
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.