|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v9 2/5] x86/ioreq server: Add DMOP to map guest ram with p2m_ioreq_server to an ioreq server.
>>> On 21.03.17 at 03:52, <yu.c.zhang@xxxxxxxxxxxxxxx> wrote:
> ---
> xen/arch/x86/hvm/dm.c | 37 ++++++++++++++++++--
> xen/arch/x86/hvm/emulate.c | 65 ++++++++++++++++++++++++++++++++---
> xen/arch/x86/hvm/ioreq.c | 38 +++++++++++++++++++++
> xen/arch/x86/mm/hap/nested_hap.c | 2 +-
> xen/arch/x86/mm/p2m-ept.c | 8 ++++-
> xen/arch/x86/mm/p2m-pt.c | 19 +++++++----
> xen/arch/x86/mm/p2m.c | 74
> ++++++++++++++++++++++++++++++++++++++++
> xen/arch/x86/mm/shadow/multi.c | 3 +-
> xen/include/asm-x86/hvm/ioreq.h | 2 ++
> xen/include/asm-x86/p2m.h | 26 ++++++++++++--
> xen/include/public/hvm/dm_op.h | 28 +++++++++++++++
> xen/include/public/hvm/hvm_op.h | 8 ++++-
> 12 files changed, 290 insertions(+), 20 deletions(-)
Btw., isn't there a libdevicemodel wrapper missing here for this new
sub-op?
> @@ -177,8 +178,64 @@ static int hvmemul_do_io(
> break;
> case X86EMUL_UNHANDLEABLE:
> {
> - struct hvm_ioreq_server *s =
> - hvm_select_ioreq_server(curr->domain, &p);
> + /*
> + * Xen isn't emulating the instruction internally, so see if
> + * there's an ioreq server that can handle it. Rules:
> + *
> + * - PIO and "normal" MMIO run through hvm_select_ioreq_server()
> + * to choose the ioreq server by range. If no server is found,
> + * the access is ignored.
> + *
> + * - p2m_ioreq_server accesses are handled by the designated
> + * ioreq_server for the domain, but there are some corner
> + * cases:
> + *
> + * - If the domain ioreq_server is NULL, assume there is a
> + * race between the unbinding of ioreq server and guest fault
> + * so re-try the instruction.
And that retry won't come back here because of? (The answer
should not include any behavior added by subsequent patches.)
> + */
> + struct hvm_ioreq_server *s = NULL;
> + p2m_type_t p2mt = p2m_invalid;
> +
> + if ( is_mmio )
> + {
> + unsigned long gmfn = paddr_to_pfn(addr);
> +
> + get_gfn_query_unlocked(currd, gmfn, &p2mt);
> +
> + if ( p2mt == p2m_ioreq_server )
> + {
> + unsigned int flags;
> +
> + /*
> + * Value of s could be stale, when we lost a race
> + * with dm_op which unmaps p2m_ioreq_server from the
> + * ioreq server. Yet there's no cheap way to avoid
> + * this, so device model need to do the check.
> + */
> + s = p2m_get_ioreq_server(currd, &flags);
> +
> + /*
> + * If p2mt is ioreq_server but ioreq_server is NULL,
> + * we probably lost a race with unbinding of ioreq
> + * server, just retry the access.
> + */
This repeats the earlier comment - please settle on where to state
this, but don't say the exact same thing twice within a few lines of
code.
> + if ( s == NULL )
> + {
> + rc = X86EMUL_RETRY;
> + vio->io_req.state = STATE_IOREQ_NONE;
> + break;
> + }
> + }
> + }
> +
> + /*
> + * Value of s could be stale, when we lost a race with dm_op
> + * which unmaps this PIO/MMIO address from the ioreq server.
> + * The device model side need to do the check.
I think "will do" would be more natural here, or add "anyway" to
the end of the sentence.
> @@ -914,6 +916,42 @@ int hvm_unmap_io_range_from_ioreq_server(struct domain
> *d, ioservid_t id,
> return rc;
> }
>
> +int hvm_map_mem_type_to_ioreq_server(struct domain *d, ioservid_t id,
> + uint32_t type, uint32_t flags)
> +{
> + struct hvm_ioreq_server *s;
> + int rc;
> +
> + /* For now, only HVMMEM_ioreq_server is supported. */
> + if ( type != HVMMEM_ioreq_server )
> + return -EINVAL;
> +
> + /* For now, only write emulation is supported. */
> + if ( flags & ~(XEN_DMOP_IOREQ_MEM_ACCESS_WRITE) )
Stray parentheses.
> --- a/xen/arch/x86/mm/hap/nested_hap.c
> +++ b/xen/arch/x86/mm/hap/nested_hap.c
> @@ -172,7 +172,7 @@ nestedhap_walk_L0_p2m(struct p2m_domain *p2m, paddr_t
> L1_gpa, paddr_t *L0_gpa,
> if ( *p2mt == p2m_mmio_direct )
> goto direct_mmio_out;
> rc = NESTEDHVM_PAGEFAULT_MMIO;
> - if ( *p2mt == p2m_mmio_dm )
> + if ( *p2mt == p2m_mmio_dm || *p2mt == p2m_ioreq_server )
Btw., how does this addition match up with the rc value being
assigned right before the if()?
> --- a/xen/arch/x86/mm/p2m-ept.c
> +++ b/xen/arch/x86/mm/p2m-ept.c
> @@ -131,6 +131,13 @@ static void ept_p2m_type_to_flags(struct p2m_domain
> *p2m, ept_entry_t *entry,
> entry->r = entry->w = entry->x = 1;
> entry->a = entry->d = !!cpu_has_vmx_ept_ad;
> break;
> + case p2m_ioreq_server:
> + entry->r = 1;
> + entry->w = !(p2m->ioreq.flags & XEN_DMOP_IOREQ_MEM_ACCESS_WRITE);
Is this effectively open coded p2m_get_ioreq_server() actually
okay? If so, why does the function need to be used elsewhere,
instead of doing direct, lock-free accesses?
> +void p2m_destroy_ioreq_server(const struct domain *d,
> + const struct hvm_ioreq_server *s)
> +{
> + struct p2m_domain *p2m = p2m_get_hostp2m(d);
> +
> + spin_lock(&p2m->ioreq.lock);
> +
> + if ( p2m->ioreq.server == s )
> + {
> + p2m->ioreq.server = NULL;
> + p2m->ioreq.flags = 0;
> + }
> +
> + spin_unlock(&p2m->ioreq.lock);
> +}
Is this function really needed? I.e. can't the caller simply call
p2m_set_ioreq_server(d, 0, s) instead?
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |