From nobody Thu May 16 07:43:39 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1620293145; cv=none; d=zohomail.com; s=zohoarc; b=Tl94H59LL5/OvUanNBu4v7t8g/ZQDBRmjEyptyyzgp5CR76bYvdz98Yli3WJDwsDnsU43cCxvQC1Ru3v+uixnXglPRZLQaaoB6Meae8x3Yr86zaSiKBy49NKafej0Mp1v/Hkk0ItgQmVE94Zn7qPwPUT53TRLXWchV/tYd3Ql/0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1620293145; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To; bh=KnO3xu1/y2KAuFqYE9XFXZBiO0nwlakLchjruO0d+bI=; b=WGunzUmfIrL4//0Ix3B/agBbeldFYd0UMt9DXHEQvEtQmpxygmH46HsXOJqb0vAzvCASL3F6wjeNwDZDs5WftOlRbtvnZTBPU446oVMjqwfpGCC/d/Zs4sA2C+JuRSIOMZjZqid6oHpatIhCb4el+/q82Gaar/H36nxiIGIzSl8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1620293145576338.5947455623559; Thu, 6 May 2021 02:25:45 -0700 (PDT) Received: from localhost ([::1]:33014 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1leaGN-0002WQ-4I for importer@patchew.org; Thu, 06 May 2021 05:25:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:32962) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lea1d-0006lZ-Am for qemu-devel@nongnu.org; Thu, 06 May 2021 05:10:29 -0400 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:60831) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lea1b-0004s7-60 for qemu-devel@nongnu.org; Thu, 06 May 2021 05:10:29 -0400 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-161-c7BC9CbuMO67MnDYuGNKEQ-1; Thu, 06 May 2021 05:10:24 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id C6633107ACE3 for ; Thu, 6 May 2021 09:10:23 +0000 (UTC) Received: from sirius.home.kraxel.org (ovpn-112-11.ams2.redhat.com [10.36.112.11]) by smtp.corp.redhat.com (Postfix) with ESMTPS id CE08D5C582; Thu, 6 May 2021 09:10:03 +0000 (UTC) Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id CDA40180062B; Thu, 6 May 2021 11:10:01 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1620292226; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=KnO3xu1/y2KAuFqYE9XFXZBiO0nwlakLchjruO0d+bI=; b=NdfT2xxIPch0mU5v9476nGg4s+e9aajpcHa7txWmOSUAvcnG91n7yD923N90mqpCvgfgUf jEet2ipoHPpl+AMD2tbVI/7cFPbHqeh1hMDKYrF7v+rxENcZZVMoFavxByrHM9bZsB0mzz Bu4/jLVSkcGBtyTpXyR6vgwVgd2zJsk= X-MC-Unique: c7BC9CbuMO67MnDYuGNKEQ-1 From: Gerd Hoffmann To: qemu-devel@nongnu.org Subject: [PATCH] virtio-gpu: handle partial maps properly Date: Thu, 6 May 2021 11:10:01 +0200 Message-Id: <20210506091001.1301250-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=kraxel@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=216.205.24.124; envelope-from=kraxel@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -34 X-Spam_score: -3.5 X-Spam_bar: --- X-Spam_report: (-3.5 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.693, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: eric.auger@redhat.com, Gerd Hoffmann , "Michael S. Tsirkin" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" dma_memory_map() may map only a part of the request. Happens if the request can't be mapped in one go, for example due to a iommu creating a linear dma mapping for scattered physical pages. Should that be the case virtio-gpu must call dma_memory_map() again with the remaining range instead of simply throwing an error. Note that this change implies the number of iov entries may differ from the number of mapping entries sent by the guest. Therefore the iov_len bookkeeping needs some updates too, we have to explicitly pass around the iov length now. Reported-by: Auger Eric Signed-off-by: Gerd Hoffmann Reviewed-by: Eric Auger Tested-by: Eric Auger --- include/hw/virtio/virtio-gpu.h | 3 +- hw/display/virtio-gpu-3d.c | 7 ++-- hw/display/virtio-gpu.c | 75 ++++++++++++++++++++-------------- 3 files changed, 51 insertions(+), 34 deletions(-) diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index fae149235c58..0d15af41d96d 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -209,7 +209,8 @@ void virtio_gpu_get_edid(VirtIOGPU *g, int virtio_gpu_create_mapping_iov(VirtIOGPU *g, struct virtio_gpu_resource_attach_backin= g *ab, struct virtio_gpu_ctrl_command *cmd, - uint64_t **addr, struct iovec **iov); + uint64_t **addr, struct iovec **iov, + uint32_t *niov); void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g, struct iovec *iov, uint32_t count); void virtio_gpu_process_cmdq(VirtIOGPU *g); diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c index d98964858e13..72c14d91324b 100644 --- a/hw/display/virtio-gpu-3d.c +++ b/hw/display/virtio-gpu-3d.c @@ -283,22 +283,23 @@ static void virgl_resource_attach_backing(VirtIOGPU *= g, { struct virtio_gpu_resource_attach_backing att_rb; struct iovec *res_iovs; + uint32_t res_niov; int ret; =20 VIRTIO_GPU_FILL_CMD(att_rb); trace_virtio_gpu_cmd_res_back_attach(att_rb.resource_id); =20 - ret =3D virtio_gpu_create_mapping_iov(g, &att_rb, cmd, NULL, &res_iovs= ); + ret =3D virtio_gpu_create_mapping_iov(g, &att_rb, cmd, NULL, &res_iovs= , &res_niov); if (ret !=3D 0) { cmd->error =3D VIRTIO_GPU_RESP_ERR_UNSPEC; return; } =20 ret =3D virgl_renderer_resource_attach_iov(att_rb.resource_id, - res_iovs, att_rb.nr_entries); + res_iovs, res_niov); =20 if (ret !=3D 0) - virtio_gpu_cleanup_mapping_iov(g, res_iovs, att_rb.nr_entries); + virtio_gpu_cleanup_mapping_iov(g, res_iovs, res_niov); } =20 static void virgl_resource_detach_backing(VirtIOGPU *g, diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index c9f5e36fd076..1dd3648f32a3 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -608,11 +608,12 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g, int virtio_gpu_create_mapping_iov(VirtIOGPU *g, struct virtio_gpu_resource_attach_backin= g *ab, struct virtio_gpu_ctrl_command *cmd, - uint64_t **addr, struct iovec **iov) + uint64_t **addr, struct iovec **iov, + uint32_t *niov) { struct virtio_gpu_mem_entry *ents; size_t esize, s; - int i; + int e, v; =20 if (ab->nr_entries > 16384) { qemu_log_mask(LOG_GUEST_ERROR, @@ -633,37 +634,53 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g, return -1; } =20 - *iov =3D g_malloc0(sizeof(struct iovec) * ab->nr_entries); + *iov =3D NULL; if (addr) { - *addr =3D g_malloc0(sizeof(uint64_t) * ab->nr_entries); + *addr =3D NULL; } - for (i =3D 0; i < ab->nr_entries; i++) { - uint64_t a =3D le64_to_cpu(ents[i].addr); - uint32_t l =3D le32_to_cpu(ents[i].length); - hwaddr len =3D l; - (*iov)[i].iov_base =3D dma_memory_map(VIRTIO_DEVICE(g)->dma_as, - a, &len, DMA_DIRECTION_TO_DEVI= CE); - (*iov)[i].iov_len =3D len; - if (addr) { - (*addr)[i] =3D a; - } - if (!(*iov)[i].iov_base || len !=3D l) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory = for" - " resource %d element %d\n", - __func__, ab->resource_id, i); - if ((*iov)[i].iov_base) { - i++; /* cleanup the 'i'th map */ + for (e =3D 0, v =3D 0; e < ab->nr_entries; e++) { + uint64_t a =3D le64_to_cpu(ents[e].addr); + uint32_t l =3D le32_to_cpu(ents[e].length); + hwaddr len; + void *map; + + do { + len =3D l; + map =3D dma_memory_map(VIRTIO_DEVICE(g)->dma_as, + a, &len, DMA_DIRECTION_TO_DEVICE); + if (!map) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO mem= ory for" + " resource %d element %d\n", + __func__, ab->resource_id, e); + virtio_gpu_cleanup_mapping_iov(g, *iov, v); + g_free(ents); + *iov =3D NULL; + if (addr) { + g_free(*addr); + *addr =3D NULL; + } + return -1; } - virtio_gpu_cleanup_mapping_iov(g, *iov, i); - g_free(ents); - *iov =3D NULL; + + if (!(v % 16)) { + *iov =3D g_realloc(*iov, sizeof(struct iovec) * (v + 16)); + if (addr) { + *addr =3D g_realloc(*addr, sizeof(uint64_t) * (v + 16)= ); + } + } + (*iov)[v].iov_base =3D map; + (*iov)[v].iov_len =3D len; if (addr) { - g_free(*addr); - *addr =3D NULL; + (*addr)[v] =3D a; } - return -1; - } + + a +=3D len; + l -=3D len; + v +=3D 1; + } while (l > 0); } + *niov =3D v; + g_free(ents); return 0; } @@ -717,13 +734,11 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g, return; } =20 - ret =3D virtio_gpu_create_mapping_iov(g, &ab, cmd, &res->addrs, &res->= iov); + ret =3D virtio_gpu_create_mapping_iov(g, &ab, cmd, &res->addrs, &res->= iov, &res->iov_cnt); if (ret !=3D 0) { cmd->error =3D VIRTIO_GPU_RESP_ERR_UNSPEC; return; } - - res->iov_cnt =3D ab.nr_entries; } =20 static void --=20 2.31.1