From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CC8D3C433EF for ; Sun, 20 Mar 2022 11:44:27 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 3503883B22; Sun, 20 Mar 2022 12:43:40 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b="Q/RWwhRn"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id B2BD6839CA; Sun, 20 Mar 2022 12:42:05 +0100 (CET) Received: from mail-wm1-x34a.google.com (mail-wm1-x34a.google.com [IPv6:2a00:1450:4864:20::34a]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id E460B839CA for ; Sun, 20 Mar 2022 12:42:00 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=3CBM3YgYKBiM9RBTKKFNNFKD.BNLT-ANNSKHRSR.CDMW.CD@flex--ascull.bounces.google.com Received: by mail-wm1-x34a.google.com with SMTP id z16-20020a05600c0a1000b0038bebbd8548so8019312wmp.3 for ; Sun, 20 Mar 2022 04:42:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=FTfMmMUSfAic52Wuiu6bv0EU7G23jktXFkINdf7cVn4=; b=Q/RWwhRnjLshoZlMDdMyPd6cyqPy4Aj2ikF3pSLd0KPsRFZJ4yB+6IJqBoKcrMI8Bv fEYwQ/6HjWt0d4DDTAzORwUM5X/wxzK6nVkCURaSTo1a+rz8CgTe3sexsk94RawwaLha xoAMn2QGcxvurMQiHlSapTAKZkNH3UZ383+/3S4C4vukUWd7lgqHJULZhYYUQjtXyyKr zd4U+uGjvf4/K3DQ4E55h+OwzdCEKtOvveyTS2/6+Qkq2mULq3yWYCGBo1GS6A23XXYe 2l7h6QH8C7QO9k2RhGgsWepQUiYc/mor1Y45Y2LTxDe1+S4P/QkyhC/tnmF4lYS9JKvX tMVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=FTfMmMUSfAic52Wuiu6bv0EU7G23jktXFkINdf7cVn4=; b=OGxC2CIXFO7fNQbI6Uyv54zOHVkaU1ob3r/Rm36Dy2q80rb8oH0vli4uV0C9jk19gk BP0lK3Kq3tUgUK3oQydfRjs7P4ZPAesInW/gA192OE5R7zvFqE3C0wdcQdK12cJeEMzH ziMhf+4DiVyt3fJpMiTSsG9M5OyXOBXjP2NYPAhG8xYW0n35CPlRd9fpcLLWv9wiFYDj wLLUCr/uuKAgE95w8qwiTYLzgc24Cr2LV1fsnZk8rPnc2BZ6H0ZfA3fwBXqGh+JfD6DO LJab+NtigRamZNT8hHmHJJgCuzF38X11zzHiL+cXOj+YU/tUX17pm8rPgHFU4Sy4BM8o /XYA== X-Gm-Message-State: AOAM531i62wtliNXEnGYcZXH73A6oRb50pa9pvfk2PCLEkOjzBPNdR82 CNsa4r3bSR9is45/53LwSH5GRTUg+IfUlYaCtZcECoufnia5lIqCarwkFExdWUjghcLD8b1VKgF Ag1qSc60GZLv7Ko9eifKWLgNES9g9xax3uar7V/+lmm4tyFUkRr0Tut5YjsM= X-Google-Smtp-Source: ABdhPJyHlm41u8rg0fXlQ6QWLMT5TK9PjJt2ZGcLWHqYX1RkGZWB1SrDTZB3WKf6o6u9ZOoAxY5XGo5i8Vo= X-Received: from ascull.c.googlers.com ([fda3:e722:ac3:cc00:28:9cb1:c0a8:1510]) (user=ascull job=sendgmr) by 2002:a1c:2b41:0:b0:380:e379:b8b0 with SMTP id r62-20020a1c2b41000000b00380e379b8b0mr15360709wmr.87.1647776520554; Sun, 20 Mar 2022 04:42:00 -0700 (PDT) Date: Sun, 20 Mar 2022 11:41:13 +0000 In-Reply-To: <20220320114118.2237795-1-ascull@google.com> Message-Id: <20220320114118.2237795-7-ascull@google.com> Mime-Version: 1.0 References: <20220320114118.2237795-1-ascull@google.com> X-Mailer: git-send-email 2.35.1.894.gb6a874cedc-goog Subject: [PATCH 06/11] virtio: pci: Read entire capability into memory From: Andrew Scull To: u-boot@lists.denx.de Cc: sjg@chromium.org, bmeng.cn@gmail.com, adelva@google.com, keirf@google.com, ptosi@google.com, Andrew Scull Content-Type: text/plain; charset="UTF-8" X-Mailman-Approved-At: Sun, 20 Mar 2022 12:43:23 +0100 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.5 at phobos.denx.de X-Virus-Status: Clean Read the virtio PCI capability out of the device configuration space to a struct rather than accessing fields directly from the configuration space as they are needed. This both makes access to the fields easier and avoids re-reading fields. Re-reading fields could result in time-of-check to time-of-use problems, should the value in the configuration space change. The range check of the `bar` field and the later call to `dm_pci_read_bar32()` is an example of where this could happen. Signed-off-by: Andrew Scull --- drivers/virtio/virtio_pci_modern.c | 74 ++++++++++++++++-------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index 4b346be257..38a0da0a84 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -393,15 +393,16 @@ static int virtio_pci_notify(struct udevice *udev, struct virtqueue *vq) * @udev: the transport device * @cfg_type: the VIRTIO_PCI_CAP_* value we seek * @cap_size: expected size of the capability + * @cap: capability read from the config space * * Return: offset of the configuration structure */ static int virtio_pci_find_capability(struct udevice *udev, u8 cfg_type, - size_t cap_size) + size_t cap_size, + struct virtio_pci_cap *cap) { int pos; int offset; - u8 type, bar; if (cap_size < sizeof(struct virtio_pci_cap)) return 0; @@ -409,6 +410,9 @@ static int virtio_pci_find_capability(struct udevice *udev, u8 cfg_type, if (cap_size > PCI_CFG_SPACE_SIZE) return 0; + if (!cap) + return 0; + for (pos = dm_pci_find_capability(udev, PCI_CAP_ID_VNDR); pos > 0; pos = dm_pci_find_next_capability(udev, pos, PCI_CAP_ID_VNDR)) { @@ -416,16 +420,26 @@ static int virtio_pci_find_capability(struct udevice *udev, u8 cfg_type, if (PCI_CFG_SPACE_SIZE - cap_size < pos) return 0; + offset = pos + offsetof(struct virtio_pci_cap, cap_vndr); + dm_pci_read_config8(udev, offset, &cap->cap_vndr); + offset = pos + offsetof(struct virtio_pci_cap, cap_next); + dm_pci_read_config8(udev, offset, &cap->cap_next); + offset = pos + offsetof(struct virtio_pci_cap, cap_len); + dm_pci_read_config8(udev, offset, &cap->cap_len); offset = pos + offsetof(struct virtio_pci_cap, cfg_type); - dm_pci_read_config8(udev, offset, &type); + dm_pci_read_config8(udev, offset, &cap->cfg_type); offset = pos + offsetof(struct virtio_pci_cap, bar); - dm_pci_read_config8(udev, offset, &bar); + dm_pci_read_config8(udev, offset, &cap->bar); + offset = pos + offsetof(struct virtio_pci_cap, offset); + dm_pci_read_config32(udev, offset, &cap->offset); + offset = pos + offsetof(struct virtio_pci_cap, length); + dm_pci_read_config32(udev, offset, &cap->length); /* Ignore structures with reserved BAR values */ - if (bar > 0x5) + if (cap->bar > 0x5) continue; - if (type == cfg_type) + if (cap->cfg_type == cfg_type) return pos; } @@ -436,33 +450,27 @@ static int virtio_pci_find_capability(struct udevice *udev, u8 cfg_type, * virtio_pci_map_capability - map base address of the capability * * @udev: the transport device - * @off: offset of the configuration structure + * @cap: capability to map * * Return: base address of the capability */ -static void __iomem *virtio_pci_map_capability(struct udevice *udev, int off) +static void __iomem *virtio_pci_map_capability(struct udevice *udev, + const struct virtio_pci_cap *cap) { - u8 bar; - u32 offset; ulong base; void __iomem *p; - if (!off) + if (!cap) return NULL; - offset = off + offsetof(struct virtio_pci_cap, bar); - dm_pci_read_config8(udev, offset, &bar); - offset = off + offsetof(struct virtio_pci_cap, offset); - dm_pci_read_config32(udev, offset, &offset); - /* * TODO: adding 64-bit BAR support * * Per spec, the BAR is permitted to be either 32-bit or 64-bit. * For simplicity, only read the BAR address as 32-bit. */ - base = dm_pci_read_bar32(udev, bar); - p = (void __iomem *)base + offset; + base = dm_pci_read_bar32(udev, cap->bar); + p = (void __iomem *)base + cap->offset; return p; } @@ -487,7 +495,7 @@ static int virtio_pci_probe(struct udevice *udev) u16 subvendor; u8 revision; int common, notify, device; - u32 common_length; + struct virtio_pci_cap common_cap, notify_cap, device_cap; int offset; /* We only own devices >= 0x1040 and <= 0x107f: leave the rest. */ @@ -504,46 +512,44 @@ static int virtio_pci_probe(struct udevice *udev) /* Check for a common config: if not, use legacy mode (bar 0) */ common = virtio_pci_find_capability(udev, VIRTIO_PCI_CAP_COMMON_CFG, - sizeof(struct virtio_pci_cap)); + sizeof(struct virtio_pci_cap), + &common_cap); if (!common) { printf("(%s): leaving for legacy driver\n", udev->name); return -ENODEV; } - offset = common + offsetof(struct virtio_pci_cap, length); - dm_pci_read_config32(udev, offset, &common_length); - if (common_length < sizeof(struct virtio_pci_common_cfg)) { + if (common_cap.length < sizeof(struct virtio_pci_common_cfg)) { printf("(%s): virtio common config too small\n", udev->name); return -EINVAL; } /* If common is there, notify should be too */ notify = virtio_pci_find_capability(udev, VIRTIO_PCI_CAP_NOTIFY_CFG, - sizeof(struct virtio_pci_notify_cap)); + sizeof(struct virtio_pci_notify_cap), + ¬ify_cap); if (!notify) { printf("(%s): missing capabilities %i/%i\n", udev->name, common, notify); return -EINVAL; } - offset = notify + offsetof(struct virtio_pci_cap, length); - dm_pci_read_config32(udev, offset, &priv->notify_len); + priv->notify_len = notify_cap.length; /* * Device capability is only mandatory for devices that have * device-specific configuration. */ device = virtio_pci_find_capability(udev, VIRTIO_PCI_CAP_DEVICE_CFG, - sizeof(struct virtio_pci_cap)); - if (device) { - offset = device + offsetof(struct virtio_pci_cap, length); - dm_pci_read_config32(udev, offset, &priv->device_len); - } + sizeof(struct virtio_pci_cap), + &device_cap); + if (device) + priv->device_len = device_cap.length; /* Map configuration structures */ - priv->common = virtio_pci_map_capability(udev, common); - priv->notify_base = virtio_pci_map_capability(udev, notify); - priv->device = virtio_pci_map_capability(udev, device); + priv->common = virtio_pci_map_capability(udev, &common_cap); + priv->notify_base = virtio_pci_map_capability(udev, ¬ify_cap); + priv->device = virtio_pci_map_capability(udev, &device_cap); debug("(%p): common @ %p, notify base @ %p, device @ %p\n", udev, priv->common, priv->notify_base, priv->device); -- 2.35.1.894.gb6a874cedc-goog