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 7D788C433EF for ; Wed, 13 Apr 2022 14:22:17 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 8E02983D8C; Wed, 13 Apr 2022 16:21: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="DMiwLFXT"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 1737983DD5; Wed, 13 Apr 2022 16:21:54 +0200 (CEST) Received: from mail-wr1-x44a.google.com (mail-wr1-x44a.google.com [IPv6:2a00:1450:4864:20::44a]) (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 1802D83C97 for ; Wed, 13 Apr 2022 16:21:51 +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=3ftxWYgYKBqsLdNfWWRZZRWP.NZXf-MZZeWTded.OPYi.OP@flex--ascull.bounces.google.com Received: by mail-wr1-x44a.google.com with SMTP id 65-20020adf8147000000b00207982c3692so417531wrm.15 for ; Wed, 13 Apr 2022 07:21:51 -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=QydZh7PXiWn2hyMXsR/txxa1/gT+GHhotEzZoizB4K8=; b=DMiwLFXTsLx8dONQrttDGOjdGCUYjlBPdVCUmHn4H4kCyV9PYH16GaWX/62WmooewF cJm5GjHgrThFV9zVX/YCrlal9VeskRfvquip4mNvUkTTpk3wTgJoCc8IFzwddGwZfant ZitwRQzpwV6++BSBlX/0zY2Z7UepB67OnKOCevKPChNmJEhOhNaGFbFPWAfSx0rZxpMk aGSdW4t9tD+MU2YWYTo6r0QbT5FnxLumdUrFDuS8H9u9i9KRZcDvrv1y3LfO2xTtO30T xyE080qUFp+Q+JdKEgJ54bjYZCF2nqWlo8X7onAbJatETOVkkns/VJr/zq0gCAc83jj1 0Q/w== 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=QydZh7PXiWn2hyMXsR/txxa1/gT+GHhotEzZoizB4K8=; b=thkM3C+HXw/ce0AUnXRk719vDRO6bCXdu1u/CidPycGajo737THdmPgDWRly5Orh1H J6nTTqse1Lw0/RAxXPaJ2OSofBcNwP/Y0AGJ6EzRcx8JCTwlB/THBjhIgp/AvrW0t9gy 8GuPVu/IQMdCjTEMWO8b3IKaF45jdpFvCuVJ13yMliofoK6pUkQ49BErIFZSOvAM9iFC 7NWpuF1LevxCToEIc/Nu9DU/FtuHIx2P9lRuD6CH4/0lT9eRoIscf18pwOS1W8k6VqmA xi6Qy894Qd66NuprMXCnNF8atWYg1xEiB9PM6fqobGmSM4U9oDqRqcuqO1bKV4zuKjMz FiGg== X-Gm-Message-State: AOAM530AbbPY2wRIVPFZrKZDnhTfFhOs5FvMuYsX/mfkWxsN2/k3Mmdq ba045NuWZwyj8hogcfajgYEmFaT1BsypBtTnuLKmhK0Lf1Y/AQbCz2sc+wmNEOA3Tr9YLqwTSvS h9er3n1IUkvejBnlLTnuVkRJkJ3ALNidNzD/wWCgm5oBhSLJm9k7RnbIaBQA= X-Google-Smtp-Source: ABdhPJwhVD1qVKNvGuYmUDWjd7K2UejQh+920g5dG0i1dSNzWzPtwrvcSAiLnVm/s6pGlowprBDHGjjUXOU= X-Received: from ascull.c.googlers.com ([fda3:e722:ac3:cc00:28:9cb1:c0a8:1510]) (user=ascull job=sendgmr) by 2002:a05:600c:3ac7:b0:38e:c6ef:ff0 with SMTP id d7-20020a05600c3ac700b0038ec6ef0ff0mr8431218wms.8.1649859710667; Wed, 13 Apr 2022 07:21:50 -0700 (PDT) Date: Wed, 13 Apr 2022 14:21:28 +0000 In-Reply-To: <20220413142137.560987-1-ascull@google.com> Message-Id: <20220413142137.560987-4-ascull@google.com> Mime-Version: 1.0 References: <20220413142137.560987-1-ascull@google.com> X-Mailer: git-send-email 2.35.1.1178.g4f1659d476-goog Subject: [PATCH v2 03/12] virtio_ring: Maintain a shadow copy of descriptors From: Andrew Scull To: u-boot@lists.denx.de Cc: sjg@chromium.org, 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 The shared descriptors should only be written by the guest driver, however, the device is still able to overwrite and corrupt them. Maintain a private shadow copy of the descriptors for the driver to use for state tracking, removing the need to read from the shared descriptors. Signed-off-by: Andrew Scull Reviewed-by: Simon Glass --- drivers/virtio/virtio_ring.c | 49 ++++++++++++++++++++++++------------ include/virtio_ring.h | 10 ++++++++ 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 8e0cb3d666..69fd8c6aa0 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -19,13 +19,21 @@ static unsigned int virtqueue_attach_desc(struct virtqueue *vq, unsigned int i, struct virtio_sg *sg, u16 flags) { + struct vring_desc_shadow *desc_shadow = &vq->vring_desc_shadow[i]; struct vring_desc *desc = &vq->vring.desc[i]; - desc->addr = cpu_to_virtio64(vq->vdev, (u64)(uintptr_t)sg->addr); - desc->len = cpu_to_virtio32(vq->vdev, sg->length); - desc->flags = cpu_to_virtio16(vq->vdev, flags); + /* Update the shadow descriptor. */ + desc_shadow->addr = (u64)(uintptr_t)sg->addr; + desc_shadow->len = sg->length; + desc_shadow->flags = flags; - return virtio16_to_cpu(vq->vdev, desc->next); + /* Update the shared descriptor to match the shadow. */ + desc->addr = cpu_to_virtio64(vq->vdev, desc_shadow->addr); + desc->len = cpu_to_virtio32(vq->vdev, desc_shadow->len); + desc->flags = cpu_to_virtio16(vq->vdev, desc_shadow->flags); + desc->next = cpu_to_virtio16(vq->vdev, desc_shadow->next); + + return desc_shadow->next; } int virtqueue_add(struct virtqueue *vq, struct virtio_sg *sgs[], @@ -67,7 +75,8 @@ int virtqueue_add(struct virtqueue *vq, struct virtio_sg *sgs[], i = virtqueue_attach_desc(vq, i, sgs[n], flags); } /* Last one doesn't continue */ - desc[prev].flags &= cpu_to_virtio16(vq->vdev, ~VRING_DESC_F_NEXT); + vq->vring_desc_shadow[prev].flags &= ~VRING_DESC_F_NEXT; + desc[prev].flags = cpu_to_virtio16(vq->vdev, vq->vring_desc_shadow[prev].flags); /* We're using some buffers from the free list. */ vq->num_free -= descs_used; @@ -136,17 +145,16 @@ void virtqueue_kick(struct virtqueue *vq) static void detach_buf(struct virtqueue *vq, unsigned int head) { unsigned int i; - __virtio16 nextflag = cpu_to_virtio16(vq->vdev, VRING_DESC_F_NEXT); /* Put back on free list: unmap first-level descriptors and find end */ i = head; - while (vq->vring.desc[i].flags & nextflag) { - i = virtio16_to_cpu(vq->vdev, vq->vring.desc[i].next); + while (vq->vring_desc_shadow[i].flags & VRING_DESC_F_NEXT) { + i = vq->vring_desc_shadow[i].next; vq->num_free++; } - vq->vring.desc[i].next = cpu_to_virtio16(vq->vdev, vq->free_head); + vq->vring_desc_shadow[i].next = vq->free_head; vq->free_head = head; /* Plus final descriptor */ @@ -199,8 +207,7 @@ void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len) virtio_store_mb(&vring_used_event(&vq->vring), cpu_to_virtio16(vq->vdev, vq->last_used_idx)); - return (void *)(uintptr_t)virtio64_to_cpu(vq->vdev, - vq->vring.desc[i].addr); + return (void *)(uintptr_t)vq->vring_desc_shadow[i].addr; } static struct virtqueue *__vring_new_virtqueue(unsigned int index, @@ -209,6 +216,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index, { unsigned int i; struct virtqueue *vq; + struct vring_desc_shadow *vring_desc_shadow; struct virtio_dev_priv *uc_priv = dev_get_uclass_priv(udev); struct udevice *vdev = uc_priv->vdev; @@ -216,10 +224,17 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index, if (!vq) return NULL; + vring_desc_shadow = calloc(vring.num, sizeof(struct vring_desc_shadow)); + if (!vring_desc_shadow) { + free(vq); + return NULL; + } + vq->vdev = vdev; vq->index = index; vq->num_free = vring.num; vq->vring = vring; + vq->vring_desc_shadow = vring_desc_shadow; vq->last_used_idx = 0; vq->avail_flags_shadow = 0; vq->avail_idx_shadow = 0; @@ -237,7 +252,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int index, /* Put everything in free lists */ vq->free_head = 0; for (i = 0; i < vring.num - 1; i++) - vq->vring.desc[i].next = cpu_to_virtio16(vdev, i + 1); + vq->vring_desc_shadow[i].next = i + 1; return vq; } @@ -290,6 +305,7 @@ struct virtqueue *vring_create_virtqueue(unsigned int index, unsigned int num, void vring_del_virtqueue(struct virtqueue *vq) { free(vq->vring.desc); + free(vq->vring_desc_shadow); list_del(&vq->list); free(vq); } @@ -335,11 +351,12 @@ void virtqueue_dump(struct virtqueue *vq) printf("\tlast_used_idx %u, avail_flags_shadow %u, avail_idx_shadow %u\n", vq->last_used_idx, vq->avail_flags_shadow, vq->avail_idx_shadow); - printf("Descriptor dump:\n"); + printf("Shadow descriptor dump:\n"); for (i = 0; i < vq->vring.num; i++) { - printf("\tdesc[%u] = { 0x%llx, len %u, flags %u, next %u }\n", - i, vq->vring.desc[i].addr, vq->vring.desc[i].len, - vq->vring.desc[i].flags, vq->vring.desc[i].next); + struct vring_desc_shadow *desc = &vq->vring_desc_shadow[i]; + + printf("\tdesc_shadow[%u] = { 0x%llx, len %u, flags %u, next %u }\n", + i, desc->addr, desc->len, desc->flags, desc->next); } printf("Avail ring dump:\n"); diff --git a/include/virtio_ring.h b/include/virtio_ring.h index 6fc0593b14..52cbe77c0a 100644 --- a/include/virtio_ring.h +++ b/include/virtio_ring.h @@ -55,6 +55,14 @@ struct vring_desc { __virtio16 next; }; +/* Shadow of struct vring_desc in guest byte order. */ +struct vring_desc_shadow { + u64 addr; + u32 len; + u16 flags; + u16 next; +}; + struct vring_avail { __virtio16 flags; __virtio16 idx; @@ -89,6 +97,7 @@ struct vring { * @index: the zero-based ordinal number for this queue * @num_free: number of elements we expect to be able to fit * @vring: actual memory layout for this queue + * @vring_desc_shadow: guest-only copy of descriptors * @event: host publishes avail event idx * @free_head: head of free buffer list * @num_added: number we've added since last sync @@ -102,6 +111,7 @@ struct virtqueue { unsigned int index; unsigned int num_free; struct vring vring; + struct vring_desc_shadow *vring_desc_shadow; bool event; unsigned int free_head; unsigned int num_added; -- 2.35.1.1178.g4f1659d476-goog