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 58A9EC433F5 for ; Thu, 21 Apr 2022 16:12:45 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 4D8D483E9B; Thu, 21 Apr 2022 18:11:56 +0200 (CEST) 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="BjHlaoUh"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 4EB4883E73; Thu, 21 Apr 2022 18:11:40 +0200 (CEST) Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) (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 E117883E60 for ; Thu, 21 Apr 2022 18:11:35 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=3NoJhYgYKBtk5N7PGGBJJBG9.7JHP-6JJOGDNON.89IS.89@flex--ascull.bounces.google.com Received: by mail-yb1-xb49.google.com with SMTP id d129-20020a254f87000000b006411bf3f331so4769028ybb.4 for ; Thu, 21 Apr 2022 09:11:35 -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=fUM+OksIuLClE6ArVO18GDUVfJA9ifdGSogmXenOFyk=; b=BjHlaoUh+rwUiELbTAd1D8Si6lZV2CWZ/w7tK/f/rqWoUr3M3d1l+CMGYWsUTrWmQw ayAfVxhisl4ioi5Rv1dND8c8zmk2ErKvYx4tVOOQnzDwc6lCP9xj005Hh9vSPQ6DnfJV oQBletfPPtcShH8DVFJI8Oabl2QMGiR2qwUCezxlLvKoXb3YxD5Q5TRoeof+NT4kNx1q tr1RKerk7gfOGJJpLQ8HAH6t9YY9kDsI1fX+L2cX6DWnTf0PSw1syj3VX7C8YP0SDiAk hMvfmmSsbC87pxSG3V/iSfJg++9t2lmQafVWedgBao8Sm9bONtrWL+R168+zXenAPaAE +Z3w== 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=fUM+OksIuLClE6ArVO18GDUVfJA9ifdGSogmXenOFyk=; b=vHZpZdvXw2rCK+m2qSUbmx8SwMudPHP1MdtMnGw0PYALkPwLGSxTNosibZ7+18Autg ZbXHJK8/msBs4J7ZJvMN824AgZloGVlMfu8n/6WWHHlNne/H98nBweg1lTbECWvK0MwW oCONMlfQPjV9KAQ2X7L0NQNxZBhLXOBd5/x7ry8rYmQBk2Ii8NP0c/HuUYzsE66MZ5+A 7LEcjFtQim+ICD3olI1IuIJ7aKAdhYUy623rWy/zso4w/BNb5Qy/HSqUk8jRGY4UR574 IJzfTL8Q4ms+1BqvG+C2/aBLjlT66HtCYDvziIxDtGgE6/hBZ1GBU7yhUmOCWsinIN5L MhEg== X-Gm-Message-State: AOAM532aR9NsRXMBu0/mBjOtA/nOmU4sL3VuG/NbEgqaVEHLamQdWn/G pZ31twgj613mHWluGoJ0N7SbUCS/kK3qXa4c2ybbI1zfxT8apXY+oRVLTgahTMqB4QZtNj4X7nW 3wm0zzxoRfdyP1bS4fw5k0WUqWXHY+SLeLnYNrM0NxQs6thI5ja5AlBSzuHo= X-Google-Smtp-Source: ABdhPJwRLAcMItLF/CYMC+VzgtAnISTE8NkzlAga/huE6uTETUeFhby0dnaiE5J86Z7Zpd1s3j6no34GvzI= X-Received: from ascull.c.googlers.com ([fda3:e722:ac3:cc00:28:9cb1:c0a8:1510]) (user=ascull job=sendgmr) by 2002:a0d:ec41:0:b0:2eb:54bb:85a9 with SMTP id r1-20020a0dec41000000b002eb54bb85a9mr443717ywn.242.1650557494553; Thu, 21 Apr 2022 09:11:34 -0700 (PDT) Date: Thu, 21 Apr 2022 16:11:05 +0000 In-Reply-To: <20220421161116.1202023-1-ascull@google.com> Message-Id: <20220421161116.1202023-8-ascull@google.com> Mime-Version: 1.0 References: <20220421161116.1202023-1-ascull@google.com> X-Mailer: git-send-email 2.36.0.rc2.479.g8af0fa9b8e-goog Subject: [PATCH v3 07/18] virtio: pci: Read entire capability into memory From: Andrew Scull To: u-boot@lists.denx.de Cc: sjg@chromium.org, bmeng.cn@gmail.com, trini@konsulko.com, Andrew Scull Content-Type: text/plain; charset="UTF-8" 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 Reviewed-by: Bin Meng --- drivers/virtio/virtio_pci_modern.c | 72 ++++++++++++++++-------------- 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index 6fe5e76572..bf92d9d3ba 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -398,19 +398,23 @@ 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; assert(cap_size >= sizeof(struct virtio_pci_cap)); assert(cap_size <= PCI_CFG_SPACE_SIZE); + 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)) { @@ -418,16 +422,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; } @@ -438,33 +452,24 @@ 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) - 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; } @@ -489,7 +494,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. */ @@ -506,46 +511,45 @@ 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)); + sizeof(struct virtio_pci_cap), + &device_cap); if (device) { - offset = device + offsetof(struct virtio_pci_cap, length); - dm_pci_read_config32(udev, offset, &priv->device_len); + priv->device_len = device_cap.length; + priv->device = virtio_pci_map_capability(udev, &device_cap); } /* 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); debug("(%p): common @ %p, notify base @ %p, device @ %p\n", udev, priv->common, priv->notify_base, priv->device); -- 2.36.0.rc2.479.g8af0fa9b8e-goog