From 7c714bd0d561dc5dac76ff2705e3c55104c73f1b Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshchenko Date: Thu, 15 Oct 2020 19:44:32 +0300 Subject: xen/arm: Add mapcache invalidation handling We need to send mapcache invalidation request to qemu/demu everytime the page gets removed from a guest. At the moment, the Arm code doesn't explicitely remove the existing mapping before inserting the new mapping. Instead, this is done implicitely by __p2m_set_entry(). So the corresponding flag will be set in __p2m_set_entry() if old entry is a RAM page *and* the new MFN is different. And the invalidation request will be sent in do_trap_hypercall() later on. Signed-off-by: Oleksandr Tyshchenko CC: Julien Grall Message-Id: <1602780274-29141-22-git-send-email-olekstysh@gmail.com> --- xen/arch/arm/p2m.c | 8 ++++++++ xen/arch/arm/traps.c | 13 ++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c index 370173c51b..2693b0c6c6 100644 --- a/xen/arch/arm/p2m.c +++ b/xen/arch/arm/p2m.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -1067,7 +1068,14 @@ static int __p2m_set_entry(struct p2m_domain *p2m, */ if ( p2m_is_valid(orig_pte) && !mfn_eq(lpae_get_mfn(*entry), lpae_get_mfn(orig_pte)) ) + { +#ifdef CONFIG_IOREQ_SERVER + if ( domain_has_ioreq_server(p2m->domain) && + (p2m->domain == current->domain) && p2m_is_ram(orig_pte.p2m.type) ) + p2m->domain->qemu_mapcache_invalidate = true; +#endif p2m_free_entry(p2m, orig_pte, level); + } out: unmap_domain_page(table); diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c index a8f5fdfeae..9eaa3420ef 100644 --- a/xen/arch/arm/traps.c +++ b/xen/arch/arm/traps.c @@ -1442,6 +1442,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 *v = current; BUILD_BUG_ON(NR_hypercalls < ARRAY_SIZE(arm_hypercall_table) ); @@ -1458,7 +1459,7 @@ static void do_trap_hypercall(struct cpu_user_regs *regs, register_t *nr, return; } - current->hcall_preempted = false; + v->hcall_preempted = false; perfc_incra(hypercalls, *nr); call = arm_hypercall_table[*nr].fn; @@ -1471,7 +1472,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 ( !v->hcall_preempted ) { /* Deliberately corrupt parameter regs used by this hypercall. */ switch ( arm_hypercall_table[*nr].nr_args ) { @@ -1488,8 +1489,14 @@ 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 ( v->hcall_preempted ) regs->pc -= 4; /* re-execute 'hvc #XEN_HYPERCALL_TAG' */ + +#ifdef CONFIG_IOREQ_SERVER + if ( unlikely(v->domain->qemu_mapcache_invalidate) && + test_and_clear_bool(v->domain->qemu_mapcache_invalidate) ) + send_invalidate_ioreq(); +#endif } void arch_hypercall_tasklet_result(struct vcpu *v, long res) -- cgit v1.2.3