lkml.org 
[lkml]   [2019]   [Feb]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH RFC 26/39] KVM: x86/xen: grant unmap support
    Date
    From: Ankur Arora <ankur.a.arora@oracle.com>

    Grant unmap removes the grant from maptrack and marks it as not in use.
    We maintain a one-to-one correspondence between grant table and maptrack
    entries so there's no contention in allocation/free.

    Co-developed-by: Joao Martins <joao.m.martins@oracle.com>
    Signed-off-by: Ankur Arora <ankur.a.arora@oracle.com>
    Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
    ---
    arch/x86/kvm/xen.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
    1 file changed, 73 insertions(+)

    diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
    index 3603645086a7..8f06924e0dfa 100644
    --- a/arch/x86/kvm/xen.c
    +++ b/arch/x86/kvm/xen.c
    @@ -1684,6 +1684,69 @@ static int shim_hcall_gntmap(struct kvm_xen *ld,
    return 0;
    }

    +static int shim_hcall_gntunmap(struct kvm_xen *xen,
    + struct gnttab_unmap_grant_ref *op)
    +{
    + struct kvm_grant_map *map, unmap;
    + struct grant_entry_v1 **rgt;
    + struct grant_entry_v1 *shah;
    + struct kvm *rd = NULL;
    + domid_t domid;
    + u32 ref;
    +
    + domid = handle_get_domid(op->handle);
    + ref = handle_get_grant(op->handle);
    +
    +
    + rd = kvm_xen_find_vm(domid);
    + if (unlikely(!rd)) {
    + /* We already teardown all ongoing grant maps */
    + op->status = GNTST_okay;
    + return 0;
    + }
    +
    + if (unlikely(ref >= gnttab_entries(rd))) {
    + pr_err("gnttab: bad ref %u\n", ref);
    + op->status = GNTST_bad_handle;
    + return 0;
    + }
    +
    + rgt = rd->arch.xen.gnttab.frames_v1;
    + map = maptrack_entry(rd->arch.xen.gnttab.handle, ref);
    +
    + /*
    + * The test_and_clear_bit (below) serializes ownership of this
    + * grant-entry. After we clear it, there can be a grant-map on this
    + * entry. So we cache the unmap entry before relinquishing ownership.
    + */
    + unmap = *map;
    +
    + if (!test_and_clear_bit(_KVM_GNTMAP_ACTIVE,
    + (unsigned long *) &map->flags)) {
    + pr_err("gnttab: bad flags for %u (dom %u ref %u) flags %x\n",
    + op->handle, domid, ref, unmap.flags);
    + op->status = GNTST_bad_handle;
    + return 0;
    + }
    +
    + /* Give up the reference taken in get_user_pages_remote(). */
    + put_page(virt_to_page(unmap.gpa));
    +
    + shah = shared_entry(rgt, unmap.ref);
    +
    + /*
    + * We have cleared _KVM_GNTMAP_ACTIVE, so a simultaneous grant-map
    + * could update the shah and we would stomp all over it but the
    + * guest deserves it.
    + */
    + if (!(unmap.flags & GNTMAP_readonly))
    + clear_bit(_GTF_writing, (unsigned long *) &shah->flags);
    + clear_bit(_GTF_reading, (unsigned long *) &shah->flags);
    +
    + op->status = GNTST_okay;
    + return 0;
    +}
    +
    static int shim_hcall_gnttab(int op, void *p, int count)
    {
    int ret = -ENOSYS;
    @@ -1698,6 +1761,16 @@ static int shim_hcall_gnttab(int op, void *p, int count)
    ret = 0;
    break;
    }
    + case GNTTABOP_unmap_grant_ref: {
    + struct gnttab_unmap_grant_ref *ref = p;
    +
    + for (i = 0; i < count; i++) {
    + shim_hcall_gntunmap(xen_shim, ref + i);
    + ref[i].host_addr = 0;
    + }
    + ret = 0;
    + break;
    + }
    default:
    pr_info("lcall-gnttab:op default=%d\n", op);
    break;
    --
    2.11.0
    \
     
     \ /
      Last update: 2019-02-20 21:21    [W:4.244 / U:0.092 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site