From nobody Tue Dec 2 00:26:32 2025 Received: from mail-pl1-f170.google.com (mail-pl1-f170.google.com [209.85.214.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 706F32BE7A1 for ; Mon, 24 Nov 2025 18:29:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764008967; cv=none; b=gsaA//+Pu1DwZcEd78hdMEEC8Hsfg+ml4LSua8vC/plmqTfBA4IEr9r9HjOiez0BSWroZkcR7HLAbNHcf7R3dSj7O0FVPoEMladMw12esCnfB809ctiTmhhLKZcrU63d576TQNvyHuXbkh591l0aIQXW0plWgn4ZQ0kAmyEGogc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764008967; c=relaxed/simple; bh=vsh6gCZNT2fH6DetQwFBewFmmMxYo5Aysy5llP/krFQ=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=Ip4s2/w16FaLyYGNE0upIDl/g+F2onmJgqqJ2xAzd1BBDl+i0NxZXhNehDDJzV7/ZK82sYVsws6fvCBtr63yUvx2NcHb0tcl5HGzr6L9qF7oDI18I4tceL6MsWPqbA0npeeDJovM2lRPLr9nJ92DjBf9VgQonRaGOjeTT0rFrd4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=IHhbsp4x; arc=none smtp.client-ip=209.85.214.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="IHhbsp4x" Received: by mail-pl1-f170.google.com with SMTP id d9443c01a7336-29555b384acso57447045ad.1 for ; Mon, 24 Nov 2025 10:29:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1764008966; x=1764613766; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=l7g4YApcxeWn1QV0962fcWmEJsVfTz87ip5iTpRI8ow=; b=IHhbsp4xhKyUOXbaOao2NTnD52FQgcCC0UmoZ+P2oBqwdJj0u9S4bEdJnwi+t310qa hzWXhbgw/I8dbG3HXKKQNOV0sav8cDNEvkvYCMWzdl8vfyss0a0WZoE5kdw+Pk8+9Lco C5bxjfO08V1loS4SjFhjJ0szimTW0oD6h8oM7Clnddua8pLn045wzh8TNNg3Xui2kxFz SYY396aECshhbmKtpW0hOBo3WpQFFmi2bl4/oOnTlSYXa2kJ3msnkwtICOOjXrwtDr8f vlQ80HG91NA0eyFvW95yuReAQhagJEeWpEXaYt/TiFOUfREiQCH4Qx2uk9JNnldABt9i 58rQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764008966; x=1764613766; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=l7g4YApcxeWn1QV0962fcWmEJsVfTz87ip5iTpRI8ow=; b=hq4qRgRGLevmpjJVLFI1ey3zE8h/f6oQqJXGKYzSss4t+lVmP+/YpZSHEGyv2D/03f aT3ajeGMVOixbsZNzuv3Xttth+uKuYJHI6R0H+OuFy3fLaKa3dv0CLLuSmFtlbazxY5z PWcywJ/TdpN33VEabK2/8EmfUq4P1lEnOaWG6+JLFFPq5Z4KIezyQUf8XTjc1x39ajcv snZyD8FuCwZEdqLsAtxB6HyaI6N7XjE802jxGkCxD7i8wYM1oEaPQkJEejUhX476q+s6 qYN5/Mc+9C3SEt+K1A5ajXG2vrt+L/Zb6OuF/SrqZXO3Tk2MeI+/n+BIK5XzGcT6OFkQ 3SpA== X-Forwarded-Encrypted: i=1; AJvYcCUPMgHk5GUo3fgAFH24PCOj0IiWLNMxbd1mGGcf9kCOKPXFn1wCN5vXvkZMCgLZikQ1schfZdQbdIwj+F0=@vger.kernel.org X-Gm-Message-State: AOJu0YzEFfdQpMo7+Ir6sALDdYm2/6+e/beRZtyfa3ayssm4q31RcvMi 2Z3+Bx4mJ812+V0KVWBBeW9epaEt/iwW3J/PPnsbjejL08p7X5VCpaaB X-Gm-Gg: ASbGnctnMThbLWT7ZZqHzQMTWM3AhXdI6kzgJD18AZkwPnV5jxwFGETLEQpXqUndYM5 MAr7M1HDfDNYdEfaSeaiPsanuvzFK57R0TKNHoxGUlpcK/IEdm5r8WREGrKgDOmWR+4g2tYaBxN OIzpNJUYW+x7jF0BVTdb87Baszchf8YO7kvwlKW+2/8xqcZOQB/J5N2sQURnP2bDCs2BAkvzsEi fhP9uu438FTdC9/brIR8q20/sLo0a2OTHuVJZEOm059bilVjV/eEx9nMGwe1uRFQJ+ek6SeLszz WCClvJaTKD9EjeJXmdK6xPX8idl7rRpbSeVu+H5iClZTy3ieStaI+9Gl74thWDlfI60dyNfdp6M wipaCGEfwnlu6zMKhC6JpZCT6sjAR6+DoCS9eePU6nA+XbFecvNYyq2jqhsskG7YP7Gcru1r/AO jcXhv+pv5+CkQ2gxMAcr35c/96JRk1ouf3Vgo= X-Google-Smtp-Source: AGHT+IFeO+TGaMNPoLfpN+XZe55yTNMT9nF9JthEW58YFJD5Yapc9U9WPxNdIP4Ln2O8C1lyEGrbBw== X-Received: by 2002:a17:902:fc43:b0:295:6e0:7b0d with SMTP id d9443c01a7336-29b6c6bb2f3mr142913995ad.56.1764008965654; Mon, 24 Nov 2025 10:29:25 -0800 (PST) Received: from ubuntu-Virtual-Machine.mshome.net ([70.37.26.65]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29b5b1070c3sm144760415ad.12.2025.11.24.10.29.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Nov 2025 10:29:24 -0800 (PST) From: Tianyu Lan X-Google-Original-From: Tianyu Lan To: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org, decui@microsoft.com, longli@microsoft.com, vdso@hexbites.dev Cc: Tianyu Lan , linux-hyperv@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH] Drivers: hv: Confidential VMBus exernal memory support Date: Mon, 24 Nov 2025 13:29:20 -0500 Message-Id: <20251124182920.9365-1-tiala@microsoft.com> X-Mailer: git-send-email 2.25.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In CVM(Confidential VM), system memory is encrypted by default. Device drivers typically use the swiotlb bounce buffer for DMA memory, which is decrypted and shared between the guest and host. Confidential Vmbus, however, supports a confidential channel that employs encrypted memory for the Vmbus ring buffer and external DMA memory. The support for the confidential ring buffer has already been integrated. In CVM, device drivers usually employ the standard DMA API to map DMA memory with the bounce buffer, which remains transparent to the device driver. For external DMA memory support, Hyper-V specific DMA operations are introduced, bypassing the bounce buffer when the confidential external memory flag is set. These DMA operations might also be reused for TDISP devices in the future, which also support DMA operations with encrypted memory. The DMA operations used are global architecture DMA operations (for details, see get_arch_dma_ops() and get_dma_ops()), and there is no need to set up for each device individually. Signed-off-by: Tianyu Lan Reviewed-by: Roman Kisel --- drivers/hv/vmbus_drv.c | 90 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 0dc4692b411a..ca31231b2c32 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -39,6 +39,9 @@ #include #include #include "hyperv_vmbus.h" +#include "../../kernel/dma/direct.h" + +extern const struct dma_map_ops *dma_ops; =20 struct vmbus_dynid { struct list_head node; @@ -1429,6 +1432,88 @@ static int vmbus_alloc_synic_and_connect(void) return -ENOMEM; } =20 + +static bool hyperv_private_memory_dma(struct device *dev) +{ + struct hv_device *hv_dev =3D device_to_hv_device(dev); + + if (hv_dev && hv_dev->channel && hv_dev->channel->co_external_memory) + return true; + else + return false; +} + +static dma_addr_t hyperv_dma_map_page(struct device *dev, struct page *pag= e, + unsigned long offset, size_t size, + enum dma_data_direction dir, + unsigned long attrs) +{ + phys_addr_t phys =3D page_to_phys(page) + offset; + + if (hyperv_private_memory_dma(dev)) + return __phys_to_dma(dev, phys); + else + return dma_direct_map_phys(dev, phys, size, dir, attrs); +} + +static void hyperv_dma_unmap_page(struct device *dev, dma_addr_t dma_handl= e, + size_t size, enum dma_data_direction dir, unsigned long attrs) +{ + if (!hyperv_private_memory_dma(dev)) + dma_direct_unmap_phys(dev, dma_handle, size, dir, attrs); +} + +static int hyperv_dma_map_sg(struct device *dev, struct scatterlist *sgl, + int nelems, enum dma_data_direction dir, + unsigned long attrs) +{ + struct scatterlist *sg; + dma_addr_t dma_addr; + int i; + + if (hyperv_private_memory_dma(dev)) { + for_each_sg(sgl, sg, nelems, i) { + dma_addr =3D __phys_to_dma(dev, sg_phys(sg)); + sg_dma_address(sg) =3D dma_addr; + sg_dma_len(sg) =3D sg->length; + } + + return nelems; + } else { + return dma_direct_map_sg(dev, sgl, nelems, dir, attrs); + } +} + +static void hyperv_dma_unmap_sg(struct device *dev, struct scatterlist *sg= l, + int nelems, enum dma_data_direction dir, unsigned long attrs) +{ + if (!hyperv_private_memory_dma(dev)) + dma_direct_unmap_sg(dev, sgl, nelems, dir, attrs); +} + +static int hyperv_dma_supported(struct device *dev, u64 mask) +{ + dev->coherent_dma_mask =3D mask; + return 1; +} + +static size_t hyperv_dma_max_mapping_size(struct device *dev) +{ + if (hyperv_private_memory_dma(dev)) + return SIZE_MAX; + else + return swiotlb_max_mapping_size(dev); +} + +const struct dma_map_ops hyperv_dma_ops =3D { + .map_page =3D hyperv_dma_map_page, + .unmap_page =3D hyperv_dma_unmap_page, + .map_sg =3D hyperv_dma_map_sg, + .unmap_sg =3D hyperv_dma_unmap_sg, + .dma_supported =3D hyperv_dma_supported, + .max_mapping_size =3D hyperv_dma_max_mapping_size, +}; + /* * vmbus_bus_init -Main vmbus driver initialization routine. * @@ -1479,8 +1564,11 @@ static int vmbus_bus_init(void) * doing that on each VP while initializing SynIC's wastes time. */ is_confidential =3D ms_hyperv.confidential_vmbus_available; - if (is_confidential) + if (is_confidential) { + dma_ops =3D &hyperv_dma_ops; pr_info("Establishing connection to the confidential VMBus\n"); + } + hv_para_set_sint_proxy(!is_confidential); ret =3D vmbus_alloc_synic_and_connect(); if (ret) --=20 2.50.1