@@ -1,6 +1,7 @@
#include <xen/cpu.h>
#include <xen/domain_page.h>
#include <xen/iocap.h>
+#include <xen/ioreq.h>
#include <xen/lib.h>
#include <xen/sched.h>
#include <xen/softirq.h>
@@ -749,17 +750,25 @@ static void p2m_free_entry(struct p2m_domain *p2m,
if ( !p2m_is_valid(entry) )
return;
- /* Nothing to do but updating the stats if the entry is a super-page. */
- if ( p2m_is_superpage(entry, level) )
+ if ( p2m_is_superpage(entry, level) || (level == 3) )
{
- p2m->stats.mappings[level]--;
- return;
- }
+#ifdef CONFIG_IOREQ_SERVER
+ /*
+ * If this gets called then either the entry was replaced by an entry
+ * with a different base (valid case) or the shattering of a superpage
+ * has failed (error case).
+ * So, at worst, the spurious mapcache invalidation might be sent.
+ */
+ if ( (p2m->domain == current->domain) &&
+ domain_has_ioreq_server(p2m->domain) &&
+ p2m_is_ram(entry.p2m.type) )
+ p2m->domain->mapcache_invalidate = true;
+#endif
- if ( level == 3 )
- {
p2m->stats.mappings[level]--;
- p2m_put_l3_page(entry);
+ /* Nothing to do if the entry is a super-page. */
+ if ( level == 3 )
+ p2m_put_l3_page(entry);
return;
}
@@ -1451,6 +1451,7 @@ static void do_trap_hypercall(struct cpu_user_regs *regs, register_t *nr,
const union hsr hsr)
{
arm_hypercall_fn_t call = NULL;
+ struct vcpu *curr = current;
BUILD_BUG_ON(NR_hypercalls < ARRAY_SIZE(arm_hypercall_table) );
@@ -1467,7 +1468,7 @@ static void do_trap_hypercall(struct cpu_user_regs *regs, register_t *nr,
return;
}
- current->hcall_preempted = false;
+ curr->hcall_preempted = false;
perfc_incra(hypercalls, *nr);
call = arm_hypercall_table[*nr].fn;
@@ -1480,7 +1481,7 @@ static void do_trap_hypercall(struct cpu_user_regs *regs, register_t *nr,
HYPERCALL_RESULT_REG(regs) = call(HYPERCALL_ARGS(regs));
#ifndef NDEBUG
- if ( !current->hcall_preempted )
+ if ( !curr->hcall_preempted )
{
/* Deliberately corrupt parameter regs used by this hypercall. */
switch ( arm_hypercall_table[*nr].nr_args ) {
@@ -1497,8 +1498,21 @@ static void do_trap_hypercall(struct cpu_user_regs *regs, register_t *nr,
#endif
/* Ensure the hypercall trap instruction is re-executed. */
- if ( current->hcall_preempted )
+ if ( curr->hcall_preempted )
regs->pc -= 4; /* re-execute 'hvc #XEN_HYPERCALL_TAG' */
+
+#ifdef CONFIG_IOREQ_SERVER
+ /*
+ * We call ioreq_signal_mapcache_invalidate from do_trap_hypercall()
+ * because the only way a guest can modify its P2M on Arm is via an
+ * hypercall.
+ * Note that sending the invalidation request causes the vCPU to block
+ * until all the IOREQ servers have acknowledged the invalidation.
+ */
+ if ( unlikely(curr->domain->mapcache_invalidate) &&
+ test_and_clear_bool(curr->domain->mapcache_invalidate) )
+ ioreq_signal_mapcache_invalidate();
+#endif
}
void arch_hypercall_tasklet_result(struct vcpu *v, long res)