Received: by 10.192.165.148 with SMTP id m20csp772091imm; Fri, 27 Apr 2018 07:17:29 -0700 (PDT) X-Google-Smtp-Source: AB8JxZrjpod8h5d2amvt05ZWo/haEoHIgc3nj96yuzGMpBagmcXijLBT1oePwWu5UJuBXrEoH00B X-Received: by 2002:a63:6d0b:: with SMTP id i11-v6mr2279477pgc.276.1524838649621; Fri, 27 Apr 2018 07:17:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1524838649; cv=none; d=google.com; s=arc-20160816; b=pMc+y5iW5G/gqbovT4OO1yvEoJYYEiEpMOieqAz+R7wiXRt4ZhvF5e/toQpz4fEJub TKqah/gYHb6UEFNvU4/6AcD6HsDii9vC+Dntc05ITPmH+UYlzcNNJ62EcEQV7BGf7eCx W1D0pOrVLEzBeuEzfeu1rwU/NjfmnUr7YUdSruAUI74bcIe3ZPYh3Vr4g3c0cR/B/UQ/ 4k51biSm0m8SMKMhRiR6Nx4v1QbDj86VIGYzrBuCO/3ORkarcx1+9YXm7liZdoGCJhff 3EEN5e5swGDZaaQ4nPhFMuBo6IeSVCPptClu8C+Tr6aNcQbm8gqnNglDQZkssVvsyPn8 wXCQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=4DpZiKBOSX5fk8tPYQnKuPOOkyzuEitP7+8h7rchjfk=; b=n0d+Fa2IOicHBOsWypSK0YxVKKe5YOzOPoAm3ap/JUjX9a8t/SWa/IgpE/1gu10nAS 8JMOKIIkwtDI4HILCmAn3BP8Glxb822csj7+/bQaIF6/MHnD33/hJJ4+yU0VmFaGmtPE 1Y1gBsLjOmGLCgQdh+PxBHhDDyGmbfsC3IxTveSMMwNlxTaNfWgwXS/CaNjZu6IitdYl Apj9wmKpG2I0q3hi4guYC0SPp9Qnj7AKd51GdP/CfL2eflJlxy4p1BbnZyjSvn3J900p /4GWxlcaythoVK22HqaI8kV4pBL3WbAmfBxZMjMcXVyr4s6ZpT4ScG/l839ZqiMrzRqx cVJw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id t65-v6si1302319pgc.343.2018.04.27.07.17.15; Fri, 27 Apr 2018 07:17:29 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935466AbeD0OPg (ORCPT + 99 others); Fri, 27 Apr 2018 10:15:36 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:41380 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S935310AbeD0OPd (ORCPT ); Fri, 27 Apr 2018 10:15:33 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8A25311F54C; Fri, 27 Apr 2018 14:15:32 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-116-57.ams2.redhat.com [10.36.116.57]) by smtp.corp.redhat.com (Postfix) with ESMTP id E0A8DAB3FF; Fri, 27 Apr 2018 14:15:25 +0000 (UTC) From: Eric Auger To: eric.auger.pro@gmail.com, eric.auger@redhat.com, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, marc.zyngier@arm.com, cdall@kernel.org, peter.maydell@linaro.org Cc: andre.przywara@arm.com, drjones@redhat.com, wei@redhat.com Subject: [PATCH v4 07/12] KVM: arm/arm64: Helper to register a new redistributor region Date: Fri, 27 Apr 2018 16:15:00 +0200 Message-Id: <1524838505-3823-8-git-send-email-eric.auger@redhat.com> In-Reply-To: <1524838505-3823-1-git-send-email-eric.auger@redhat.com> References: <1524838505-3823-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Fri, 27 Apr 2018 14:15:32 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Fri, 27 Apr 2018 14:15:32 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eric.auger@redhat.com' RCPT:'' Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org We introduce a new helper that creates and inserts a new redistributor region into the rdist region list. This helper both handles the case where the redistributor region size is known at registration time and the legacy case where it is not (eventually depending on the number of online vcpus). Depending on pfns, we perform all the possible checks that we can do: - end of memory crossing - incorrect alignment of the base address - collision with distributor region if already defined - collision with already registered rdist regions - check of the new index Rdist regions must be inserted by increasing order of indices. Indices must be contiguous. Signed-off-by: Eric Auger --- v3 -> v4: - inversed check in vgic_v3_rdist_overlap - use list_last_entry in vgic_v3_insert_redist_region - improve comment in vgic_v3_insert_redist_region - introduce vgic_dist_overlap --- virt/kvm/arm/vgic/vgic-mmio-v3.c | 89 ++++++++++++++++++++++++++++++++-------- virt/kvm/arm/vgic/vgic.h | 8 ++++ 2 files changed, 81 insertions(+), 16 deletions(-) diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c index ce5c927..cbf8f4e 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c @@ -680,14 +680,63 @@ static int vgic_register_all_redist_iodevs(struct kvm *kvm) return ret; } -int vgic_v3_set_redist_base(struct kvm *kvm, u64 addr) +/** + * vgic_v3_insert_redist_region - Insert a new redistributor region + * + * Performs various checks before inserting the rdist region in the list. + * Those tests depend on whether the size of the rdist region is known + * (ie. count != 0). The list is sorted by rdist region index. + * + * @kvm: kvm handle + * @index: redist region index + * @base: base of the new rdist region + * @count: number of redistributors the region is made of (of 0 in the old style + * single region, whose size is induced from the number of vcpus) + * + * Return 0 on success, < 0 otherwise + */ +static int vgic_v3_insert_redist_region(struct kvm *kvm, uint32_t index, + gpa_t base, uint32_t count) { - struct vgic_dist *vgic = &kvm->arch.vgic; + struct vgic_dist *d = &kvm->arch.vgic; struct vgic_redist_region *rdreg; + struct list_head *rd_regions = &d->rd_regions; + struct list_head *last = rd_regions->prev; + size_t size = count * KVM_VGIC_V3_REDIST_SIZE; int ret; - /* vgic_check_ioaddr makes sure we don't do this twice */ - if (!list_empty(&vgic->rd_regions)) + /* single rdist region already set ?*/ + if (!count && !list_empty(rd_regions)) + return -EINVAL; + + /* cross the end of memory ? */ + if (base + size < base) + return -EINVAL; + + if (list_empty(rd_regions)) { + if (index != 0) + return -EINVAL; + } else { + rdreg = list_entry(last, struct vgic_redist_region, list); + if (index != rdreg->index + 1) + return -EINVAL; + + /* Cannot add an explicitly sized regions after legacy region */ + if (!rdreg->count) + return -EINVAL; + } + + /* + * For legacy single-region redistributor regions (!count), + * check that the redistributor region does not overlap with the + * distributor's address space. + */ + if (!count && !IS_VGIC_ADDR_UNDEF(d->vgic_dist_base) && + vgic_dist_overlap(kvm, base, size)) + return -EINVAL; + + /* collision with any other rdist region? */ + if (vgic_v3_rdist_overlap(kvm, base, size)) return -EINVAL; rdreg = kzalloc(sizeof(*rdreg), GFP_KERNEL); @@ -696,17 +745,29 @@ int vgic_v3_set_redist_base(struct kvm *kvm, u64 addr) rdreg->base = VGIC_ADDR_UNDEF; - ret = vgic_check_ioaddr(kvm, &rdreg->base, addr, SZ_64K); + ret = vgic_check_ioaddr(kvm, &rdreg->base, base, SZ_64K); if (ret) - goto out; + goto free; - rdreg->base = addr; - if (!vgic_v3_check_base(kvm)) { - ret = -EINVAL; - goto out; - } + rdreg->base = base; + rdreg->count = count; + rdreg->free_index = 0; + rdreg->index = index; - list_add(&rdreg->list, &vgic->rd_regions); + list_add_tail(&rdreg->list, rd_regions); + return 0; +free: + kfree(rdreg); + return ret; +} + +int vgic_v3_set_redist_base(struct kvm *kvm, u64 addr) +{ + int ret; + + ret = vgic_v3_insert_redist_region(kvm, 0, addr, 0); + if (ret) + return ret; /* * Register iodevs for each existing VCPU. Adding more VCPUs @@ -717,10 +778,6 @@ int vgic_v3_set_redist_base(struct kvm *kvm, u64 addr) return ret; return 0; - -out: - kfree(rdreg); - return ret; } int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr) diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h index e6e3ae9..6af7d8a 100644 --- a/virt/kvm/arm/vgic/vgic.h +++ b/virt/kvm/arm/vgic/vgic.h @@ -272,6 +272,14 @@ vgic_v3_rd_region_size(struct kvm *kvm, struct vgic_redist_region *rdreg) } bool vgic_v3_rdist_overlap(struct kvm *kvm, gpa_t base, size_t size); +static inline bool vgic_dist_overlap(struct kvm *kvm, gpa_t base, size_t size) +{ + struct vgic_dist *d = &kvm->arch.vgic; + + return (base + size > d->vgic_dist_base) && + (base < d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE); +} + int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its, u32 devid, u32 eventid, struct vgic_irq **irq); struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi); -- 2.5.5