Linux Confidential Computing Development
 help / color / mirror / Atom feed
* Re: [PATCH kernel 2/9] pci/tsm: Add tsm_tdi_status
From: dan.j.williams @ 2026-02-25  6:33 UTC (permalink / raw)
  To: Alexey Kardashevskiy, x86
  Cc: linux-kernel, kvm, linux-pci, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Sean Christopherson,
	Paolo Bonzini, Andy Lutomirski, Peter Zijlstra, Bjorn Helgaas,
	Dan Williams, Marek Szyprowski, Robin Murphy, Andrew Morton,
	Catalin Marinas, Michael Ellerman, Mike Rapoport, Tom Lendacky,
	Ard Biesheuvel, Neeraj Upadhyay, Ashish Kalra, Stefano Garzarella,
	Melody Wang, Seongman Lee, Joerg Roedel, Nikunj A Dadhania,
	Michael Roth, Suravee Suthikulpanit, Andi Kleen,
	Kuppuswamy Sathyanarayanan, Tony Luck, David Woodhouse,
	Greg Kroah-Hartman, Denis Efremov, Geliang Tang, Piotr Gregor,
	Michael S. Tsirkin, Alex Williamson, Arnd Bergmann, Jesse Barnes,
	Jacob Pan, Yinghai Lu, Kevin Brodsky, Jonathan Cameron,
	Aneesh Kumar K.V (Arm), Xu Yilun, Herbert Xu, Kim Phillips,
	Konrad Rzeszutek Wilk, Stefano Stabellini, Claire Chang,
	linux-coco, iommu, Alexey Kardashevskiy
In-Reply-To: <20260225053806.3311234-3-aik@amd.com>

Alexey Kardashevskiy wrote:
> Define a structure with all info about a TDI such as TDISP status,
> bind state, used START_INTERFACE options and the report digest.
> 
> This will be extended and shared to the userspace.
> 
> Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
> ---
> 
> Make it uapi? We might want a sysfs node per a field so probably not.
> For now its only user is AMD SEV TIO with a plan to expose this struct
> as a whole via sysfs.

Say more about what this uapi when sysfs already has lock+accept
indications?

Or are you just talking about exporting the TDISP report as a binary
blob?

I think the kernel probably wants a generic abstraction for asserting
that the tsm layer believes the report remains valid between fetch and
run. In other words I am not sure arch features like intf_report_counter
ever show up anywhere in uapi outside of debugfs.

^ permalink raw reply

* [RFC PATCH kernel] iommufd: Allow mapping from KVM's guest_memfd
From: Alexey Kardashevskiy @ 2026-02-25  7:52 UTC (permalink / raw)
  To: linux-kernel
  Cc: kvm, Jason Gunthorpe, Kevin Tian, Joerg Roedel, Will Deacon,
	Robin Murphy, Paolo Bonzini, Steve Sistare, Nicolin Chen, iommu,
	Alexey Kardashevskiy, linux-coco, Dan Williams, Santosh Shukla,
	Pratik R . Sampat, Ackerley Tng, Sean Christopherson, Fuad Tabba,
	Xu Yilun, Aneesh Kumar K . V

CoCo VMs get their private memory allocated from guest_memfd
("gmemfd") which is a KVM facility similar to memfd.
The gmemfds does not allow mapping private memory to the userspace
so the IOMMU_IOAS_MAP ioctl does not work.

Use the existing IOMMU_IOAS_MAP_FILE ioctl to allow mapping from
fd + offset. Detect the gmemfd case in pfn_reader_user_pin().

For the new guest_memfd type, no additional reference is taken as
pinning is guaranteed by the KVM guest_memfd library.

There is no KVM-GMEMFD->IOMMUFD direct notification mechanism as
the assumption is that:
1) page stage change events will be handled by VMM which is going
to call IOMMUFD to remap pages;
2) shrinking GMEMFD equals to VM memory unplug and VMM is going to
handle it.

Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
---

This is for Trusted IO == TEE-IO == PCIe TDISP, etc.

Previously posted here:
https://lore.kernel.org/r/20250218111017.491719-13-aik@amd.com
The main comment was "what is the lifetime of those folios()" and
GMEMFD + QEMU should take care of it.

And horrendous stuff like this is not really useful:
https://github.com/AMDESE/linux-kvm/commit/7d73fd2cccb8489b1

---
 include/linux/kvm_host.h      |  4 +
 drivers/iommu/iommufd/pages.c | 80 ++++++++++++++++++--
 virt/kvm/guest_memfd.c        | 36 +++++++++
 3 files changed, 113 insertions(+), 7 deletions(-)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 995db7a7ba57..9369cf22b24e 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -2673,4 +2673,8 @@ unsigned long kvm_get_vm_memory_attributes(struct kvm *kvm, gfn_t gfn);
 int kvm_vm_ioctl_set_mem_attributes(struct kvm *kvm,
 					   struct kvm_memory_attributes2 *attrs);
 
+bool kvm_is_gmemfd(struct file *file);
+struct folio *kvm_gmemfd_get_pfn(struct file *file, unsigned long index,
+				 unsigned long *pfn, int *max_order);
+
 #endif
diff --git a/drivers/iommu/iommufd/pages.c b/drivers/iommu/iommufd/pages.c
index dbe51ecb9a20..4c07e39e17d0 100644
--- a/drivers/iommu/iommufd/pages.c
+++ b/drivers/iommu/iommufd/pages.c
@@ -56,6 +56,9 @@
 #include <linux/slab.h>
 #include <linux/sched/mm.h>
 #include <linux/vfio_pci_core.h>
+#include <linux/pagemap.h>
+#include <linux/memcontrol.h>
+#include <linux/kvm_host.h>
 
 #include "double_span.h"
 #include "io_pagetable.h"
@@ -660,7 +663,8 @@ static void batch_from_pages(struct pfn_batch *batch, struct page **pages,
 }
 
 static int batch_from_folios(struct pfn_batch *batch, struct folio ***folios_p,
-			     unsigned long *offset_p, unsigned long npages)
+			     unsigned long *offset_p, unsigned long npages,
+			     bool do_pin)
 {
 	int rc = 0;
 	struct folio **folios = *folios_p;
@@ -676,7 +680,7 @@ static int batch_from_folios(struct pfn_batch *batch, struct folio ***folios_p,
 
 		if (!batch_add_pfn_num(batch, pfn, nr, BATCH_CPU_MEMORY))
 			break;
-		if (nr > 1) {
+		if (nr > 1 && do_pin) {
 			rc = folio_add_pins(folio, nr - 1);
 			if (rc) {
 				batch_remove_pfn_num(batch, nr);
@@ -697,6 +701,7 @@ static int batch_from_folios(struct pfn_batch *batch, struct folio ***folios_p,
 static void batch_unpin(struct pfn_batch *batch, struct iopt_pages *pages,
 			unsigned int first_page_off, size_t npages)
 {
+	bool do_unpin = !kvm_is_gmemfd(pages->file);
 	unsigned int cur = 0;
 
 	while (first_page_off) {
@@ -710,9 +715,12 @@ static void batch_unpin(struct pfn_batch *batch, struct iopt_pages *pages,
 		size_t to_unpin = min_t(size_t, npages,
 					batch->npfns[cur] - first_page_off);
 
-		unpin_user_page_range_dirty_lock(
-			pfn_to_page(batch->pfns[cur] + first_page_off),
-			to_unpin, pages->writable);
+		/* Do nothing for guest_memfd */
+		if (do_unpin)
+			unpin_user_page_range_dirty_lock(
+				pfn_to_page(batch->pfns[cur] + first_page_off),
+				to_unpin, pages->writable);
+
 		iopt_pages_sub_npinned(pages, to_unpin);
 		cur++;
 		first_page_off = 0;
@@ -872,6 +880,57 @@ static long pin_memfd_pages(struct pfn_reader_user *user, unsigned long start,
 	return npages_out;
 }
 
+static long pin_guest_memfd_pages(struct pfn_reader_user *user, loff_t start, unsigned long npages)
+{
+	struct page **upages = user->upages;
+	unsigned long offset = 0;
+	loff_t uptr = start;
+	long rc = 0;
+
+	for (unsigned long i = 0; (uptr - start) < (npages << PAGE_SHIFT); ++i) {
+		unsigned long gfn = 0, pfn = 0;
+		int max_order = 0;
+		struct folio *folio;
+
+		folio = kvm_gmemfd_get_pfn(user->file, uptr >> PAGE_SHIFT, &pfn, &max_order);
+		if (IS_ERR(folio))
+			rc = PTR_ERR(folio);
+
+		if (rc == -EINVAL && i == 0) {
+			pr_err_once("Must be vfio mmio at gfn=%lx pfn=%lx, skipping\n", gfn, pfn);
+			return rc;
+		}
+
+		if (rc) {
+			pr_err("%s: %ld %ld %lx -> %lx\n", __func__,
+			       rc, i, (unsigned long) uptr, (unsigned long) pfn);
+			break;
+		}
+
+		if (i == 0)
+			offset = offset_in_folio(folio, start) >> PAGE_SHIFT;
+
+		user->ufolios[i] = folio;
+
+		if (upages) {
+			unsigned long np = (1UL << (max_order + PAGE_SHIFT)) - offset_in_folio(folio, uptr);
+
+			for (unsigned long j = 0; j < np; ++j)
+				*upages++ = folio_page(folio, offset + j);
+		}
+
+		uptr += (1UL << (max_order + PAGE_SHIFT)) - offset_in_folio(folio, uptr);
+	}
+
+	if (!rc) {
+		rc = npages;
+		user->ufolios_next = user->ufolios;
+		user->ufolios_offset = offset;
+	}
+
+	return rc;
+}
+
 static int pfn_reader_user_pin(struct pfn_reader_user *user,
 			       struct iopt_pages *pages,
 			       unsigned long start_index,
@@ -925,7 +984,13 @@ static int pfn_reader_user_pin(struct pfn_reader_user *user,
 
 	if (user->file) {
 		start = pages->start + (start_index * PAGE_SIZE);
-		rc = pin_memfd_pages(user, start, npages);
+		if (kvm_is_gmemfd(pages->file)) {
+			rc = pin_guest_memfd_pages(user, start, npages);
+		} else {
+			pr_err("UNEXP PINFD start=%lx sz=%lx file=%lx",
+				start, npages << PAGE_SHIFT, (ulong) pages->file);
+			rc = pin_memfd_pages(user, start, npages);
+		}
 	} else if (!remote_mm) {
 		uptr = (uintptr_t)(pages->uptr + start_index * PAGE_SIZE);
 		rc = pin_user_pages_fast(uptr, npages, user->gup_flags,
@@ -1221,7 +1286,8 @@ static int pfn_reader_fill_span(struct pfn_reader *pfns)
 				 npages);
 	else
 		rc = batch_from_folios(&pfns->batch, &user->ufolios_next,
-				       &user->ufolios_offset, npages);
+				       &user->ufolios_offset, npages,
+				       !kvm_is_gmemfd(pfns->pages->file));
 	return rc;
 }
 
diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c
index e4e21068cf2a..2a313888c21b 100644
--- a/virt/kvm/guest_memfd.c
+++ b/virt/kvm/guest_memfd.c
@@ -1794,3 +1794,39 @@ void kvm_gmem_exit(void)
 	rcu_barrier();
 	kmem_cache_destroy(kvm_gmem_inode_cachep);
 }
+
+bool kvm_is_gmemfd(struct file *file)
+{
+	if (!file)
+		return false;
+
+	if (file->f_op != &kvm_gmem_fops)
+		return false;
+
+	return true;
+}
+EXPORT_SYMBOL_GPL(kvm_is_gmemfd);
+
+struct folio *kvm_gmemfd_get_pfn(struct file *file, unsigned long index,
+				 unsigned long *pfn, int *max_order)
+{
+	struct inode *inode = file_inode(file);
+	struct folio *folio;
+
+	if (!inode || !kvm_is_gmemfd(file))
+		return NULL;
+
+	folio = kvm_gmem_get_folio(inode, index);
+	if (!folio)
+		return NULL;
+
+
+	*pfn = folio_pfn(folio) + (index & (folio_nr_pages(folio) - 1));
+	*max_order = folio_order(folio);
+
+	folio_put(folio);
+	folio_unlock(folio);
+
+	return folio;
+}
+EXPORT_SYMBOL_GPL(kvm_gmemfd_get_pfn);
-- 
2.52.0


^ permalink raw reply related

* Re: [PATCH kernel 1/9] pci/tsm: Add TDISP report blob and helpers to parse it
From: Arnd Bergmann @ 2026-02-25 10:10 UTC (permalink / raw)
  To: Dan Williams, Alexey Kardashevskiy, x86
  Cc: linux-kernel, kvm, linux-pci, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Sean Christopherson,
	Paolo Bonzini, Andy Lutomirski, Peter Zijlstra, Bjorn Helgaas,
	Marek Szyprowski, Robin Murphy, Andrew Morton, Catalin Marinas,
	Michael Ellerman, Mike Rapoport, Tom Lendacky, Ard Biesheuvel,
	Neeraj Upadhyay, Ashish Kalra, Stefano Garzarella, Melody Wang,
	Seongman Lee, Joerg Roedel, Nikunj A Dadhania, Michael Roth,
	Suravee Suthikulpanit, Andi Kleen, Kuppuswamy Sathyanarayanan,
	Tony Luck, David Woodhouse, Greg Kroah-Hartman, Denis Efremov,
	Geliang Tang, Piotr Gregor, Michael S. Tsirkin, Alex Williamson,
	Jesse Barnes, Jacob Pan, Yinghai Lu, Kevin Brodsky,
	Jonathan Cameron, Aneesh Kumar K.V (Arm), Xu Yilun, Herbert Xu,
	Kim Phillips, Konrad Rzeszutek Wilk, Stefano Stabellini,
	Claire Chang, linux-coco, iommu
In-Reply-To: <699e93db9ad47_1cc510090@dwillia2-mobl4.notmuch>

On Wed, Feb 25, 2026, at 07:16, dan.j.williams@intel.com wrote:
> Alexey Kardashevskiy wrote:
> [..]
>> +struct tdi_report_header {
>> +	__u16 interface_info; /* TSM_TDI_REPORT_xxx */
>> +	__u16 reserved2;
>> +	__u16 msi_x_message_control;
>> +	__u16 lnr_control;
>> +	__u32 tph_control;
>> +	__u32 mmio_range_count;
>> +} __packed;
>> +
>> +/*
>> + * Each MMIO Range of the TDI is reported with the MMIO reporting offset added.
>> + * Base and size in units of 4K pages
>> + */
>> +#define TSM_TDI_REPORT_MMIO_MSIX_TABLE		BIT(0)
>> +#define TSM_TDI_REPORT_MMIO_PBA			BIT(1)
>> +#define TSM_TDI_REPORT_MMIO_IS_NON_TEE		BIT(2)
>> +#define TSM_TDI_REPORT_MMIO_IS_UPDATABLE	BIT(3)
>> +#define TSM_TDI_REPORT_MMIO_RESERVED		GENMASK(15, 4)
>> +#define TSM_TDI_REPORT_MMIO_RANGE_ID		GENMASK(31, 16)
>> +
>> +struct tdi_report_mmio_range {
>> +	__u64 first_page;		/* First 4K page with offset added */
>> +	__u32 num;			/* Number of 4K pages in this range */
>> +	__u32 range_attributes;		/* TSM_TDI_REPORT_MMIO_xxx */
>
> Those should be __le64 and le32, right? But see below for another
> option...

If these come from DMA transfers from a device, yes.

>> +} __packed;

The structure appears to be allocated with kzalloc, so it is always
aligned to __alignof__(u64) or higher, and it's better to drop the
__packed annotation.

>
> /*
>  * PCIe ECN TEE Device Interface Security Protocol (TDISP)
>  *
>  * Device Interface Report data object layout as defined by PCIe r7.0 
> section
>  * 11.3.11
>  */
> #define PCI_TSM_DEVIF_REPORT_INFO 0
> #define PCI_TSM_DEVIF_REPORT_MSIX 4
> #define PCI_TSM_DEVIF_REPORT_LNR 6
> #define PCI_TSM_DEVIF_REPORT_TPH 8
> #define PCI_TSM_DEVIF_REPORT_MMIO_COUNT 12
> #define  PCI_TSM_DEVIF_REPORT_MMIO_PFN 0 /* An interface report 'pfn' 
> is 4K in size */
> #define  PCI_TSM_DEVIF_REPORT_MMIO_NR_PFNS 8
> #define  PCI_TSM_DEVIF_REPORT_MMIO_ATTR 12
> #define  PCI_TSM_DEVIF_REPORT_MMIO_ATTR_MSIX_TABLE BIT(0)
> #define  PCI_TSM_DEVIF_REPORT_MMIO_ATTR_MSIX_PBA BIT(1)
> #define  PCI_TSM_DEVIF_REPORT_MMIO_ATTR_IS_NON_TEE BIT(2)
> #define  PCI_TSM_DEVIF_REPORT_MMIO_ATTR_IS_UPDATABLE BIT(3)
> #define  PCI_TSM_DEVIF_REPORT_MMIO_ATTR_RANGE_ID GENMASK(31, 16)
> #define  PCI_TSM_DEVIF_REPORT_MMIO_SIZE (16)
> #define PCI_TSM_DEVIF_REPORT_BASE_SIZE(nr_mmio) (16 + nr_mmio * 
> PCI_TSM_DEVIF_REPORT_MMIO_SIZE)
>
> Any strong feelings one way or the other? I have a mild preference for
> this offset+bitfields approach.

I assume by bitfield you mean the macros above, not the C structure
syntax with ':', right? The macros seem fine to me, while C bitfields
again would make the code nonportable due to architecture specific
bitfield positioning.

       Arnd

^ permalink raw reply

* Re: [RFC PATCH kernel] iommufd: Allow mapping from KVM's guest_memfd
From: Sean Christopherson @ 2026-02-25 13:55 UTC (permalink / raw)
  To: Alexey Kardashevskiy
  Cc: linux-kernel, kvm, Jason Gunthorpe, Kevin Tian, Joerg Roedel,
	Will Deacon, Robin Murphy, Paolo Bonzini, Steve Sistare,
	Nicolin Chen, iommu, linux-coco, Dan Williams, Santosh Shukla,
	Pratik R . Sampat, Ackerley Tng, Fuad Tabba, Xu Yilun,
	Aneesh Kumar K . V
In-Reply-To: <20260225075211.3353194-1-aik@amd.com>

On Wed, Feb 25, 2026, Alexey Kardashevskiy wrote:
> For the new guest_memfd type, no additional reference is taken as
> pinning is guaranteed by the KVM guest_memfd library.
> 
> There is no KVM-GMEMFD->IOMMUFD direct notification mechanism as
> the assumption is that:
> 1) page stage change events will be handled by VMM which is going
> to call IOMMUFD to remap pages;
> 2) shrinking GMEMFD equals to VM memory unplug and VMM is going to
> handle it.

The VMM is outside of the kernel's effective TCB.  Assuming the VMM will always
do the right thing is a non-starter.

^ permalink raw reply

* Re: [PATCH] KVM: TDX: Set SIGNIFCANT_INDEX flag for supported CPUIDs
From: Sean Christopherson @ 2026-02-25 13:59 UTC (permalink / raw)
  To: Binbin Wu
  Cc: Rick P Edgecombe, Xiaoyao Li, changyuanl@google.com,
	pbonzini@redhat.com, Binbin Wu, Isaku Yamahata, bp@alien8.de,
	x86@kernel.org, kas@kernel.org, hpa@zytor.com, mingo@redhat.com,
	linux-kernel@vger.kernel.org, dave.hansen@linux.intel.com,
	tglx@kernel.org, kvm@vger.kernel.org, linux-coco@lists.linux.dev
In-Reply-To: <66336533-8bee-4219-9936-3163c7ce06bb@linux.intel.com>

On Wed, Feb 25, 2026, Binbin Wu wrote:
> Do we need to consider the panic_on_warn case? I guess the option will not be
> enabled in a production environment?

Nope.  That's even explicitly called out in Documentation/process/coding-style.rst:

  Do not worry about panic_on_warn users
  **************************************
  
  A few more words about panic_on_warn: Remember that ``panic_on_warn`` is an
  available kernel option, and that many users set this option. This is why
  there is a "Do not WARN lightly" writeup, above. However, the existence of
  panic_on_warn users is not a valid reason to avoid the judicious use
  WARN*(). That is because, whoever enables panic_on_warn has explicitly
  asked the kernel to crash if a WARN*() fires, and such users must be
  prepared to deal with the consequences of a system that is somewhat more
  likely to crash.

^ permalink raw reply

* Re: [PATCH v3 00/16] KVM: x86/tdx: Have TDX handle VMXON during bringup
From: Chao Gao @ 2026-02-25 14:38 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
	Kiryl Shutsemau, Peter Zijlstra, Arnaldo Carvalho de Melo,
	Namhyung Kim, Paolo Bonzini, linux-kernel, linux-coco, kvm,
	linux-perf-users, Xu Yilun, Dan Williams
In-Reply-To: <20260214012702.2368778-1-seanjc@google.com>

On Fri, Feb 13, 2026 at 05:26:46PM -0800, Sean Christopherson wrote:
>Assuming I didn't break anything between v2 and v3, I think this is ready to
>rip.  Given the scope of the KVM changes, and that they extend outside of x86,
>my preference is to take this through the KVM tree.  But a stable topic branch
>in tip would work too, though I think we'd want it sooner than later so that
>it can be used as a base. 
>
>Chao, I deliberately omitted your Tested-by, as I shuffled things around enough
>while splitting up the main patch that I'm not 100% positive I didn't regress
>anything relative to v2.

I tested CPU hotplug/unplug, kvm-intel.ko loading/reloading, TD launches, and
loading kvm-intel.ko with tdx=1 when the TDX Module wasn't loaded. No issues
were found with this v3.

Tested-by: Chao Gao <chao.gao@intel.com>

^ permalink raw reply

* Re: [PATCH] KVM: TDX: Set SIGNIFCANT_INDEX flag for supported CPUIDs
From: Binbin Wu @ 2026-02-25 15:03 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Rick P Edgecombe, Xiaoyao Li, changyuanl@google.com,
	pbonzini@redhat.com, Binbin Wu, Isaku Yamahata, bp@alien8.de,
	x86@kernel.org, kas@kernel.org, hpa@zytor.com, mingo@redhat.com,
	linux-kernel@vger.kernel.org, dave.hansen@linux.intel.com,
	tglx@kernel.org, kvm@vger.kernel.org, linux-coco@lists.linux.dev
In-Reply-To: <aZ8AKZQ4L5n7wVMT@google.com>



On 2/25/2026 9:59 PM, Sean Christopherson wrote:
> On Wed, Feb 25, 2026, Binbin Wu wrote:
>> Do we need to consider the panic_on_warn case? I guess the option will not be
>> enabled in a production environment?
> 
> Nope.  That's even explicitly called out in Documentation/process/coding-style.rst:

Thanks for the info, and sorry for not checking it before asking the question.

> 
>   Do not worry about panic_on_warn users
>   **************************************
>   
>   A few more words about panic_on_warn: Remember that ``panic_on_warn`` is an
>   available kernel option, and that many users set this option. This is why
>   there is a "Do not WARN lightly" writeup, above. However, the existence of
>   panic_on_warn users is not a valid reason to avoid the judicious use
>   WARN*(). That is because, whoever enables panic_on_warn has explicitly
>   asked the kernel to crash if a WARN*() fires, and such users must be
>   prepared to deal with the consequences of a system that is somewhat more
>   likely to crash.
> 


^ permalink raw reply

* Re: [PATCH kernel 4/9] dma/swiotlb: Stop forcing SWIOTLB for TDISP devices
From: dan.j.williams @ 2026-02-25 16:30 UTC (permalink / raw)
  To: Alexey Kardashevskiy, x86
  Cc: linux-kernel, kvm, linux-pci, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Sean Christopherson,
	Paolo Bonzini, Andy Lutomirski, Peter Zijlstra, Bjorn Helgaas,
	Dan Williams, Marek Szyprowski, Robin Murphy, Andrew Morton,
	Catalin Marinas, Michael Ellerman, Mike Rapoport, Tom Lendacky,
	Ard Biesheuvel, Neeraj Upadhyay, Ashish Kalra, Stefano Garzarella,
	Melody Wang, Seongman Lee, Joerg Roedel, Nikunj A Dadhania,
	Michael Roth, Suravee Suthikulpanit, Andi Kleen,
	Kuppuswamy Sathyanarayanan, Tony Luck, David Woodhouse,
	Greg Kroah-Hartman, Denis Efremov, Geliang Tang, Piotr Gregor,
	Michael S. Tsirkin, Alex Williamson, Arnd Bergmann, Jesse Barnes,
	Jacob Pan, Yinghai Lu, Kevin Brodsky, Jonathan Cameron,
	Aneesh Kumar K.V (Arm), Xu Yilun, Herbert Xu, Kim Phillips,
	Konrad Rzeszutek Wilk, Stefano Stabellini, Claire Chang,
	linux-coco, iommu, Alexey Kardashevskiy
In-Reply-To: <20260225053806.3311234-5-aik@amd.com>

Alexey Kardashevskiy wrote:
> SWIOTLB is enforced when encrypted guest memory is detected
> in pci_swiotlb_detect() which is required for legacy devices.
> 
> Skip SWIOTLB for TDISP devices.
> 
> Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
> ---
>  include/linux/swiotlb.h | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
> index 3dae0f592063..119c25d639a7 100644
> --- a/include/linux/swiotlb.h
> +++ b/include/linux/swiotlb.h
> @@ -173,6 +173,15 @@ static inline bool is_swiotlb_force_bounce(struct device *dev)
>  {
>  	struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
>  
> +	/*
> +	 * CC_ATTR_GUEST_MEM_ENCRYPT enforces SWIOTLB_FORCE in
> +	 * swiotlb_init_remap() to allow legacy devices access arbitrary
> +	 * VM encrypted memory.
> +	 * Skip it for TDISP devices capable of DMA-ing the encrypted memory.
> +	 */
> +	if (device_cc_accepted(dev))
> +		return false;

I worry this further muddies the meaning of the swiotlb force option.
What if you want to force swiotlb operation on accepted devices?

For example:

@@ -173,7 +176,13 @@ static inline bool is_swiotlb_force_bounce(struct device *dev)
 {
        struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
 
-       return mem && mem->force_bounce;
+       if (!mem)
+               return false;
+       if (mem->force_bounce)
+               return true;
+       if (mem->bounce_unaccepted && !device_cc_accepted(dev))
+               return true;
+       return false;
 }
 
 void swiotlb_init(bool addressing_limited, unsigned int flags);

^ permalink raw reply

* Re: [PATCH v2] KVM: x86: synthesize CPUID bits only if CPU capability is set
From: Nikolay Borisov @ 2026-02-25 16:43 UTC (permalink / raw)
  To: Carlos López, seanjc, bp, kvm
  Cc: linux-coco, jmattson, binbin.wu, Paolo Bonzini, Thomas Gleixner,
	Ingo Molnar, Dave Hansen,
	maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT), H. Peter Anvin,
	open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)
In-Reply-To: <20260209153108.70667-2-clopez@suse.de>



On 9.02.26 г. 17:31 ч., Carlos López wrote:
> KVM incorrectly synthesizes CPUID bits for KVM-only leaves, as the
> following branch in kvm_cpu_cap_init() is never taken:
> 
>      if (leaf < NCAPINTS)
>          kvm_cpu_caps[leaf] &= kernel_cpu_caps[leaf];
> 
> This means that bits set via SYNTHESIZED_F() for KVM-only leaves are
> unconditionally set. This for example can cause issues for SEV-SNP
> guests running on Family 19h CPUs, as TSA_SQ_NO and TSA_L1_NO are
> always enabled by KVM in 80000021[ECX]. When userspace issues a
> SNP_LAUNCH_UPDATE command to update the CPUID page for the guest, SNP
> firmware will explicitly reject the command if the page sets sets these
> bits on vulnerable CPUs.
> 
> To fix this, check in SYNTHESIZED_F() that the corresponding X86
> capability is set before adding it to to kvm_cpu_cap_features.
> 
> Fixes: 31272abd5974 ("KVM: SVM: Advertise TSA CPUID bits to guests")
> Link: https://lore.kernel.org/all/20260208164233.30405-1-clopez@suse.de/
> Signed-off-by: Carlos López <clopez@suse.de>

Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>

> ---
> v2: fix SYNTHESIZED_F() instead of using SCATTERED_F() for TSA bits
>   arch/x86/kvm/cpuid.c | 5 ++++-
>   1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
> index 88a5426674a1..5f41924987c7 100644
> --- a/arch/x86/kvm/cpuid.c
> +++ b/arch/x86/kvm/cpuid.c
> @@ -770,7 +770,10 @@ do {									\
>   #define SYNTHESIZED_F(name)					\
>   ({								\
>   	kvm_cpu_cap_synthesized |= feature_bit(name);		\
> -	F(name);						\
> +								\
> +	BUILD_BUG_ON(X86_FEATURE_##name >= MAX_CPU_FEATURES);	\
> +	if (boot_cpu_has(X86_FEATURE_##name))			\
> +		F(name);					\
>   })
>   
>   /*


^ permalink raw reply

* Re: [PATCH kernel 4/9] dma/swiotlb: Stop forcing SWIOTLB for TDISP devices
From: Robin Murphy @ 2026-02-25 16:48 UTC (permalink / raw)
  To: Alexey Kardashevskiy, x86
  Cc: linux-kernel, kvm, linux-pci, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Sean Christopherson,
	Paolo Bonzini, Andy Lutomirski, Peter Zijlstra, Bjorn Helgaas,
	Dan Williams, Marek Szyprowski, Andrew Morton, Catalin Marinas,
	Michael Ellerman, Mike Rapoport, Tom Lendacky, Ard Biesheuvel,
	Neeraj Upadhyay, Ashish Kalra, Stefano Garzarella, Melody Wang,
	Seongman Lee, Joerg Roedel, Nikunj A Dadhania, Michael Roth,
	Suravee Suthikulpanit, Andi Kleen, Kuppuswamy Sathyanarayanan,
	Tony Luck, David Woodhouse, Greg Kroah-Hartman, Denis Efremov,
	Geliang Tang, Piotr Gregor, Michael S. Tsirkin, Alex Williamson,
	Arnd Bergmann, Jesse Barnes, Jacob Pan, Yinghai Lu, Kevin Brodsky,
	Jonathan Cameron, Aneesh Kumar K.V (Arm), Xu Yilun, Herbert Xu,
	Kim Phillips, Konrad Rzeszutek Wilk, Stefano Stabellini,
	Claire Chang, linux-coco, iommu
In-Reply-To: <20260225053806.3311234-5-aik@amd.com>

On 2026-02-25 5:37 am, Alexey Kardashevskiy wrote:
> SWIOTLB is enforced when encrypted guest memory is detected
> in pci_swiotlb_detect() which is required for legacy devices.
> 
> Skip SWIOTLB for TDISP devices.
> 
> Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
> ---
>   include/linux/swiotlb.h | 9 +++++++++
>   1 file changed, 9 insertions(+)
> 
> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
> index 3dae0f592063..119c25d639a7 100644
> --- a/include/linux/swiotlb.h
> +++ b/include/linux/swiotlb.h
> @@ -173,6 +173,15 @@ static inline bool is_swiotlb_force_bounce(struct device *dev)
>   {
>   	struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
>   
> +	/*
> +	 * CC_ATTR_GUEST_MEM_ENCRYPT enforces SWIOTLB_FORCE in
> +	 * swiotlb_init_remap() to allow legacy devices access arbitrary
> +	 * VM encrypted memory.
> +	 * Skip it for TDISP devices capable of DMA-ing the encrypted memory.
> +	 */
> +	if (device_cc_accepted(dev))
> +		return false;

This seems backwards - how does it make sense for arch code to force 
SWIOTLB globally on the grounds that all DMA must be to shared memory, 
but then generic code override that because it claims to know better?

I'd expect to see something more like:

	if (is_cc_platform && !device_cc_accepted)
		return true;

here, and then get rid of the rest of the (ab)use of SWIOTLB_FORCE for 
this purpose entirely.

However there is the fiddly aspect that it's not necessarily strictly 
enough to just un-force SWIOTLB; we really want to actively ensure that 
no private memory can *ever* end up getting bounced through a shared 
SWIOTLB buffer. The private/shared state is really a property of the 
individual DMA mappings, though, rather than an overall property of the 
device itself (since a device that's trusted to access private memory 
isn't necessarily prohibited from still also accessing shared memory as 
well), hmmm...

Thanks,
Robin.

> +
>   	return mem && mem->force_bounce;
>   }
>   


^ permalink raw reply

* Re: [PATCH kernel 5/9] x86/mm: Stop forcing decrypted page state for TDISP devices
From: dan.j.williams @ 2026-02-25 16:51 UTC (permalink / raw)
  To: Alexey Kardashevskiy, x86
  Cc: linux-kernel, kvm, linux-pci, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Sean Christopherson,
	Paolo Bonzini, Andy Lutomirski, Peter Zijlstra, Bjorn Helgaas,
	Dan Williams, Marek Szyprowski, Robin Murphy, Andrew Morton,
	Catalin Marinas, Michael Ellerman, Mike Rapoport, Tom Lendacky,
	Ard Biesheuvel, Neeraj Upadhyay, Ashish Kalra, Stefano Garzarella,
	Melody Wang, Seongman Lee, Joerg Roedel, Nikunj A Dadhania,
	Michael Roth, Suravee Suthikulpanit, Andi Kleen,
	Kuppuswamy Sathyanarayanan, Tony Luck, David Woodhouse,
	Greg Kroah-Hartman, Denis Efremov, Geliang Tang, Piotr Gregor,
	Michael S. Tsirkin, Alex Williamson, Arnd Bergmann, Jesse Barnes,
	Jacob Pan, Yinghai Lu, Kevin Brodsky, Jonathan Cameron,
	Aneesh Kumar K.V (Arm), Xu Yilun, Herbert Xu, Kim Phillips,
	Konrad Rzeszutek Wilk, Stefano Stabellini, Claire Chang,
	linux-coco, iommu, Alexey Kardashevskiy
In-Reply-To: <20260225053806.3311234-6-aik@amd.com>

Alexey Kardashevskiy wrote:
> The DMA subsystem does is forcing private-to-shared
> page conversion in force_dma_unencrypted().
> 
> Return false from force_dma_unencrypted() for TDISP devices.
> 
> Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
> ---
>  arch/x86/mm/mem_encrypt.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
> index 95bae74fdab2..8daa6482b080 100644
> --- a/arch/x86/mm/mem_encrypt.c
> +++ b/arch/x86/mm/mem_encrypt.c
> @@ -20,10 +20,11 @@
>  bool force_dma_unencrypted(struct device *dev)
>  {
>  	/*
> -	 * For SEV, all DMA must be to unencrypted addresses.
> +	 * dma_direct_alloc() forces page state change if private memory is
> +	 * allocated for DMA. Skip conversion if the TDISP device is accepted.

Looks ok, but I would not reference "TDISP" here. TDISP is the PCI
"accept" protocol. Other buses might accept devices via other
bus-specific protocols.

^ permalink raw reply

* Re: [PATCH kernel 6/9] x86/dma-direct: Stop changing encrypted page state for TDISP devices
From: Robin Murphy @ 2026-02-25 17:08 UTC (permalink / raw)
  To: Alexey Kardashevskiy, x86
  Cc: linux-kernel, kvm, linux-pci, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Sean Christopherson,
	Paolo Bonzini, Andy Lutomirski, Peter Zijlstra, Bjorn Helgaas,
	Dan Williams, Marek Szyprowski, Andrew Morton, Catalin Marinas,
	Michael Ellerman, Mike Rapoport, Tom Lendacky, Ard Biesheuvel,
	Neeraj Upadhyay, Ashish Kalra, Stefano Garzarella, Melody Wang,
	Seongman Lee, Joerg Roedel, Nikunj A Dadhania, Michael Roth,
	Suravee Suthikulpanit, Andi Kleen, Kuppuswamy Sathyanarayanan,
	Tony Luck, David Woodhouse, Greg Kroah-Hartman, Denis Efremov,
	Geliang Tang, Piotr Gregor, Michael S. Tsirkin, Alex Williamson,
	Arnd Bergmann, Jesse Barnes, Jacob Pan, Yinghai Lu, Kevin Brodsky,
	Jonathan Cameron, Aneesh Kumar K.V (Arm), Xu Yilun, Herbert Xu,
	Kim Phillips, Konrad Rzeszutek Wilk, Stefano Stabellini,
	Claire Chang, linux-coco, iommu
In-Reply-To: <20260225053806.3311234-7-aik@amd.com>

On 2026-02-25 5:37 am, Alexey Kardashevskiy wrote:
> TDISP devices operate in CoCo VMs only and capable of accessing
> encrypted guest memory.
> 
> Currently when SME is on, the DMA subsystem forces the SME mask in
> DMA handles in phys_to_dma() which assumes IOMMU pass through
> which is never the case with CoCoVM running with a TDISP device.
> 
> Define X86's version of phys_to_dma() to skip leaking SME mask to
> the device.
> 
> Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
> ---
> 
> Doing this in the generic version breaks ARM which uses
> the SME mask in DMA handles, hence ARCH_HAS_PHYS_TO_DMA.

That smells a bit off... In CCA we should be in the same boat, wherein a 
trusted device can access memory at a DMA address based on its "normal" 
(private) GPA, rather than having to be redirected to the shared alias 
(it's really not an "SME mask" in that sense at all).

I guess this comes back to the point I just raised on the previous patch 
- the current assumption is that devices cannot access private memory at 
all, and thus phys_to_dma() is implicitly only dealing with the 
mechanics of how the given device accesses shared memory. Once that no 
longer holds, I don't see how we can find the right answer without also 
consulting the relevant state of paddr itself, and that really *should* 
be able to be commonly abstracted across CoCo environments. And if in 
the process of that we could untangle the "implicit vs. explicit SME 
mask for shared memory or non-CoCo SME" case from common code and punt 
*that* into an x86-specific special case, all the better :)

Thanks,
Robin.

> pci_device_add() enforces the FFFF_FFFF coherent DMA mask so
> dma_alloc_coherent() fails when SME=on, this is how I ended up fixing
> phys_to_dma() and not quite sure it is the right fix.
> ---
>   arch/x86/Kconfig                  |  1 +
>   arch/x86/include/asm/dma-direct.h | 39 ++++++++++++++++++++
>   2 files changed, 40 insertions(+)
> 
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index fa3b616af03a..c46283064518 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -112,6 +112,7 @@ config X86
>   	select ARCH_HAS_UBSAN
>   	select ARCH_HAS_DEBUG_WX
>   	select ARCH_HAS_ZONE_DMA_SET if EXPERT
> +	select ARCH_HAS_PHYS_TO_DMA
>   	select ARCH_HAVE_NMI_SAFE_CMPXCHG
>   	select ARCH_HAVE_EXTRA_ELF_NOTES
>   	select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE
> diff --git a/arch/x86/include/asm/dma-direct.h b/arch/x86/include/asm/dma-direct.h
> new file mode 100644
> index 000000000000..f50e03d643c1
> --- /dev/null
> +++ b/arch/x86/include/asm/dma-direct.h
> @@ -0,0 +1,39 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef ASM_X86_DMA_DIRECT_H
> +#define ASM_X86_DMA_DIRECT_H 1
> +
> +static inline dma_addr_t __phys_to_dma(struct device *dev, phys_addr_t paddr)
> +{
> +	if (dev->dma_range_map)
> +		return translate_phys_to_dma(dev, paddr);
> +	return paddr;
> +}
> +
> +static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
> +{
> +	/*
> +	 * TDISP devices only work in CoCoVMs and rely on IOMMU to
> +	 * decide on the memory encryption.
> +	 * Stop leaking the SME mask in DMA handles and return
> +	 * the real address.
> +	 */
> +	if (device_cc_accepted(dev))
> +		return dma_addr_unencrypted(__phys_to_dma(dev, paddr));
> +
> +	return dma_addr_encrypted(__phys_to_dma(dev, paddr));
> +}
> +
> +static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
> +{
> +	return daddr;
> +}
> +
> +static inline dma_addr_t phys_to_dma_unencrypted(struct device *dev,
> +						 phys_addr_t paddr)
> +{
> +	return dma_addr_unencrypted(__phys_to_dma(dev, paddr));
> +}
> +
> +#define phys_to_dma_unencrypted phys_to_dma_unencrypted
> +
> +#endif /* ASM_X86_DMA_DIRECT_H */


^ permalink raw reply

* Re: [PATCH 00/14] KVM: x86: Emulator MMIO fix and cleanups
From: Edgecombe, Rick P @ 2026-02-25 17:32 UTC (permalink / raw)
  To: pbonzini@redhat.com, kas@kernel.org, seanjc@google.com
  Cc: x86@kernel.org, zhangjiaji1@huawei.com, binbin.wu@linux.intel.com,
	Li, Xiaoyao, linux-kernel@vger.kernel.org,
	thomas.lendacky@amd.com, kvm@vger.kernel.org,
	linux-coco@lists.linux.dev, michael.roth@amd.com
In-Reply-To: <20260225012049.920665-1-seanjc@google.com>

On Tue, 2026-02-24 at 17:20 -0800, Sean Christopherson wrote:
> Fix a UAF stack bug where KVM references a stack pointer around an exit to
> userspace, and then clean up the related code to try to make it easier to
> maintain (not necessarily "easy", but "easier").
> 
> The SEV-ES and TDX changes are compile-tested only.

I ran it through our TDX CI.

Tested-by: Rick Edgecombe <rick.p.edgecombe@intel.com>

^ permalink raw reply

* Re: [PATCH 14/14] KVM: x86: Add helpers to prepare kvm_run for userspace MMIO exit
From: Edgecombe, Rick P @ 2026-02-25 17:32 UTC (permalink / raw)
  To: pbonzini@redhat.com, kas@kernel.org, seanjc@google.com
  Cc: x86@kernel.org, zhangjiaji1@huawei.com, binbin.wu@linux.intel.com,
	Li, Xiaoyao, linux-kernel@vger.kernel.org,
	thomas.lendacky@amd.com, kvm@vger.kernel.org,
	linux-coco@lists.linux.dev, michael.roth@amd.com
In-Reply-To: <20260225012049.920665-15-seanjc@google.com>

On Tue, 2026-02-24 at 17:20 -0800, Sean Christopherson wrote:
> +static inline void __kvm_prepare_emulated_mmio_exit(struct kvm_vcpu *vcpu,
> +						    gpa_t gpa, unsigned int len,
> +						    const void *data,
> +						    bool is_write)
> +{
> +	struct kvm_run *run = vcpu->run;
> +
> +	run->mmio.len = min(8u, len);

I would think to extract this to a local var so it can be used twice.

> +	run->mmio.is_write = is_write;
> +	run->exit_reason = KVM_EXIT_MMIO;
> +	run->mmio.phys_addr = gpa;
> +	if (is_write)
> +		memcpy(run->mmio.data, data, min(8u, len));
> +}
> +


^ permalink raw reply

* Re: [PATCH kernel 4/9] dma/swiotlb: Stop forcing SWIOTLB for TDISP devices
From: Robin Murphy @ 2026-02-25 18:00 UTC (permalink / raw)
  To: dan.j.williams, Alexey Kardashevskiy, x86
  Cc: linux-kernel, kvm, linux-pci, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Sean Christopherson,
	Paolo Bonzini, Andy Lutomirski, Peter Zijlstra, Bjorn Helgaas,
	Marek Szyprowski, Andrew Morton, Catalin Marinas,
	Michael Ellerman, Mike Rapoport, Tom Lendacky, Ard Biesheuvel,
	Neeraj Upadhyay, Ashish Kalra, Stefano Garzarella, Melody Wang,
	Seongman Lee, Joerg Roedel, Nikunj A Dadhania, Michael Roth,
	Suravee Suthikulpanit, Andi Kleen, Kuppuswamy Sathyanarayanan,
	Tony Luck, David Woodhouse, Greg Kroah-Hartman, Denis Efremov,
	Geliang Tang, Piotr Gregor, Michael S. Tsirkin, Alex Williamson,
	Arnd Bergmann, Jesse Barnes, Jacob Pan, Yinghai Lu, Kevin Brodsky,
	Jonathan Cameron, Aneesh Kumar K.V (Arm), Xu Yilun, Herbert Xu,
	Kim Phillips, Konrad Rzeszutek Wilk, Stefano Stabellini,
	Claire Chang, linux-coco, iommu
In-Reply-To: <699f238873ae7_1cc5100b6@dwillia2-mobl4.notmuch>

On 2026-02-25 4:30 pm, dan.j.williams@intel.com wrote:
> Alexey Kardashevskiy wrote:
>> SWIOTLB is enforced when encrypted guest memory is detected
>> in pci_swiotlb_detect() which is required for legacy devices.
>>
>> Skip SWIOTLB for TDISP devices.
>>
>> Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
>> ---
>>   include/linux/swiotlb.h | 9 +++++++++
>>   1 file changed, 9 insertions(+)
>>
>> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
>> index 3dae0f592063..119c25d639a7 100644
>> --- a/include/linux/swiotlb.h
>> +++ b/include/linux/swiotlb.h
>> @@ -173,6 +173,15 @@ static inline bool is_swiotlb_force_bounce(struct device *dev)
>>   {
>>   	struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
>>   
>> +	/*
>> +	 * CC_ATTR_GUEST_MEM_ENCRYPT enforces SWIOTLB_FORCE in
>> +	 * swiotlb_init_remap() to allow legacy devices access arbitrary
>> +	 * VM encrypted memory.
>> +	 * Skip it for TDISP devices capable of DMA-ing the encrypted memory.
>> +	 */
>> +	if (device_cc_accepted(dev))
>> +		return false;
> 
> I worry this further muddies the meaning of the swiotlb force option.
> What if you want to force swiotlb operation on accepted devices?

For that we'd need a whole other private SWIOTLB plus the logic to 
decide which one to use in the first place. And if you really wanted an 
option to forcibly expose all DMA through shared memory regardless of 
TDISP and friends, that would logically want to be a higher-level CoCo 
option rather than belonging to SWIOTLB itself ;)

Thanks,
Robin.

> For example:
> 
> @@ -173,7 +176,13 @@ static inline bool is_swiotlb_force_bounce(struct device *dev)
>   {
>          struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
>   
> -       return mem && mem->force_bounce;
> +       if (!mem)
> +               return false;
> +       if (mem->force_bounce)
> +               return true;
> +       if (mem->bounce_unaccepted && !device_cc_accepted(dev))
> +               return true;
> +       return false;
>   }
>   
>   void swiotlb_init(bool addressing_limited, unsigned int flags);


^ permalink raw reply

* Re: [PATCH 14/14] KVM: x86: Add helpers to prepare kvm_run for userspace MMIO exit
From: Sean Christopherson @ 2026-02-25 19:22 UTC (permalink / raw)
  To: Rick P Edgecombe
  Cc: pbonzini@redhat.com, kas@kernel.org, x86@kernel.org,
	zhangjiaji1@huawei.com, binbin.wu@linux.intel.com, Xiaoyao Li,
	linux-kernel@vger.kernel.org, thomas.lendacky@amd.com,
	kvm@vger.kernel.org, linux-coco@lists.linux.dev,
	michael.roth@amd.com
In-Reply-To: <8bed2406e9f5f30f8f01c1da731fae6e040da827.camel@intel.com>

On Wed, Feb 25, 2026, Rick P Edgecombe wrote:
> On Tue, 2026-02-24 at 17:20 -0800, Sean Christopherson wrote:
> > +static inline void __kvm_prepare_emulated_mmio_exit(struct kvm_vcpu *vcpu,
> > +						    gpa_t gpa, unsigned int len,
> > +						    const void *data,
> > +						    bool is_write)
> > +{
> > +	struct kvm_run *run = vcpu->run;
> > +
> > +	run->mmio.len = min(8u, len);
> 
> I would think to extract this to a local var so it can be used twice.

Ya, either way works for me.  The copy+paste is a little gross, but it's also
unlikely that anyone is going to modify this code (or if they did, that any goofs
wouldn't be immediately disastrous).

> > +	run->mmio.is_write = is_write;
> > +	run->exit_reason = KVM_EXIT_MMIO;
> > +	run->mmio.phys_addr = gpa;
> > +	if (is_write)
> > +		memcpy(run->mmio.data, data, min(8u, len));
> > +}
> > +
> 

^ permalink raw reply

* Re: [PATCH] KVM: SEV: Track SNP launch state and disallow invalid userspace interactions
From: Sean Christopherson @ 2026-02-25 20:05 UTC (permalink / raw)
  To: Jethro Beekman
  Cc: Paolo Bonzini, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, kvm, linux-kernel, linux-coco
In-Reply-To: <d98692e2-d96b-4c36-8089-4bc1e5cc3d57@fortanix.com>

On Mon, Jan 19, 2026, Jethro Beekman wrote:
> Calling any of the SNP_LAUNCH_ ioctls after SNP_LAUNCH_FINISH results in a
> kernel page fault due to RMP violation. Track SNP launch state and exit early.

What exactly trips the RMP #PF?  A backtrace would be especially helpful for
posterity.

I ask because it's basically impossible to determine if this approach is optimal
without knowing exactly what's going wrong.  Semantically it sounds reasonable,
but ideally KVM would naturally handle userspace stupidity (without exploding).

^ permalink raw reply

* Re: [PATCH] KVM: SEV: Track SNP launch state and disallow invalid userspace interactions
From: Jethro Beekman @ 2026-02-25 20:13 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Paolo Bonzini, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, kvm, linux-kernel, linux-coco
In-Reply-To: <aZ9V_O5SGGKa-Vdn@google.com>

On 2026-02-25 12:05, Sean Christopherson wrote:
> On Mon, Jan 19, 2026, Jethro Beekman wrote:
>> Calling any of the SNP_LAUNCH_ ioctls after SNP_LAUNCH_FINISH results in a
>> kernel page fault due to RMP violation. Track SNP launch state and exit early.
> 
> What exactly trips the RMP #PF?  A backtrace would be especially helpful for
> posterity.

Here's a backtrace for calling ioctl(KVM_SEV_SNP_LAUNCH_FINISH) twice. Note this is with a modified version of QEMU.

BUG: unable to handle page fault for address: ff1276cbfdf36000
#PF: supervisor write access in kernel mode
#PF: error_code(0x80000003) - RMP violation
PGD 5a31801067 P4D 5a31802067 PUD 40ccfb5063 PMD 40e5954063 PTE 80000040fdf36163
SEV-SNP: PFN 0x40fdf36, RMP entry: [0x6010fffffffff001 - 0x000000000000001f]
Oops: Oops: 0003 [#1] SMP NOPTI
CPU: 33 UID: 0 PID: 996180 Comm: qemu-system-x86 Tainted: G           OE       6.18.0-8-generic #8-Ubuntu PREEMPT(voluntary) 
Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
Hardware name: Dell Inc. PowerEdge R7625/0H1TJT, BIOS 1.5.8 07/21/2023
RIP: 0010:sev_es_sync_vmsa+0x54/0x4c0 [kvm_amd]
Code: 89 f8 48 8d b2 00 04 00 00 48 89 e5 41 56 41 54 53 48 83 ec 30 48 8b 9f 18 1c 00 00 48 8b 8a 00 04 00 00 4c 8b 07 48 8d 7b 08 <48> 89 0b 48 89 d9 48 8b 92 e0 06 00 00 48 83 e7 f8 48 29 f9 48 89
RSP: 0018:ff42462db15fb8b8 EFLAGS: 00010286
RAX: ff1276d253008000 RBX: ff1276cbfdf36000 RCX: 0000ffff00930000
RDX: ff1276cb899e6000 RSI: ff1276cb899e6400 RDI: ff1276cbfdf36008
RBP: ff42462db15fb900 R08: ff1276cbfb1f2000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: ff1276cbfb1f2000
R13: 00007fffffffdc10 R14: ff1276cbfb1f3188 R15: ff42462db15fba70
FS:  00007ffff6846f40(0000) GS:ff1276cacfaf0000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ff1276cbfdf36000 CR3: 0000004628e03004 CR4: 0000000000f71ef0
PKRU: 55555554
Call Trace:
 <TASK>
 snp_launch_update_vmsa+0x19d/0x290 [kvm_amd]
 snp_launch_finish+0xb6/0x380 [kvm_amd]
 sev_mem_enc_ioctl+0x14e/0x720 [kvm_amd]
 kvm_arch_vm_ioctl+0x837/0xcf0 [kvm]
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? hook_file_ioctl+0x10/0x20
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? __x64_sys_ioctl+0xbd/0x100
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? kvm_vm_ioctl+0x3fd/0xcc0 [kvm]
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? __x64_sys_ioctl+0xbd/0x100
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? arch_exit_to_user_mode_prepare.isra.0+0xd/0xe0
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? rseq_get_rseq_cs.isra.0+0x16/0x240
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? kvm_vm_ioctl+0x3fd/0xcc0 [kvm]
 ? srso_alias_return_thunk+0x5/0xfbef5
 kvm_vm_ioctl+0x3fd/0xcc0 [kvm]
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? arch_exit_to_user_mode_prepare.isra.0+0xc5/0xe0
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? do_syscall_64+0xb9/0x10f0
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? __rseq_handle_notify_resume+0xbb/0x1c0
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? hook_file_ioctl+0x10/0x20
 ? srso_alias_return_thunk+0x5/0xfbef5
 __x64_sys_ioctl+0xa3/0x100
 ? arch_exit_to_user_mode_prepare.isra.0+0xc5/0xe0
 x64_sys_call+0xfe0/0x2350
 do_syscall_64+0x81/0x10f0
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? arch_exit_to_user_mode_prepare.isra.0+0xd/0x100
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? irqentry_exit_to_user_mode+0x2d/0x1d0
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? irqentry_exit+0x43/0x50
 ? srso_alias_return_thunk+0x5/0xfbef5
 ? exc_page_fault+0x90/0x1b0
 entry_SYSCALL_64_after_hwframe+0x76/0x7e
RIP: 0033:0x7ffff673287d
Code: 04 25 28 00 00 00 48 89 45 c8 31 c0 48 8d 45 10 c7 45 b0 10 00 00 00 48 89 45 b8 48 8d 45 d0 48 89 45 c0 b8 10 00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 1a 48 8b 45 c8 64 48 2b 04 25 28 00 00 00
RSP: 002b:00007fffffffda80 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00000000c008aeba RCX: 00007ffff673287d
RDX: 00007fffffffdc10 RSI: 00000000c008aeba RDI: 0000000000000008
RBP: 00007fffffffdad0 R08: 0000000000811000 R09: 00005555562737f0
R10: 00005555576631b0 R11: 0000000000000246 R12: 00007fffffffdc10
R13: 0000555557695f80 R14: 0000000000001000 R15: 00007fff73c75000
 </TASK>
Modules linked in: kvm_amd nf_conntrack_netlink veth ecdsa_generic vfio_pci vfio_pci_core vfio_iommu_type1 vfio iommufd amd_atl intel_rapl_msr intel_rapl_common amd64_edac edac_mce_amd xfrm_user xfrm_algo xt_set ip_set bonding cfg80211 nft_chain_nat xt_MASQUERADE nf_nat binfmt_misc xt_addrtype xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nft_compat nf_tables xfs nls_iso8859_1 ipmi_ssif platform_profile dell_wmi video spd5118 sparse_keymap kvm irqbypass dell_smbios dax_hmem dcdbas cxl_acpi rapl cxl_port dell_wmi_descriptor wmi_bmof mgag200 i2c_algo_bit acpi_power_meter cxl_core i2c_piix4 einj ipmi_si acpi_ipmi k10temp ccp i2c_smbus ipmi_devintf mlx5_fwctl joydev input_leds fwctl ipmi_msghandler mac_hid nfsd auth_rpcgss nfs_acl lockd grace sch_fq_codel sunrpc br_netfilter bridge stp llc overlay efi_pstore dm_multipath nfnetlink dmi_sysfs ip_tables x_tables autofs4 btrfs blake2b_generic raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx xor raid6_pq raid1 linear mlx5_ib
 ib_uverbs macsec ib_core raid0 hid_generic usbhid hid mlx5_core nvme mlxfw nvme_core psample polyval_clmulni ghash_clmulni_intel nvme_keyring tls ahci nvme_auth megaraid_sas libahci pci_hyperv_intf hkdf wmi aesni_intel [last unloaded: kvm_amd(OE)]
CR2: ff1276cbfdf36000
---[ end trace 0000000000000000 ]---
pstore: backend (erst) writing error (-22)
RIP: 0010:sev_es_sync_vmsa+0x54/0x4c0 [kvm_amd]
Code: 89 f8 48 8d b2 00 04 00 00 48 89 e5 41 56 41 54 53 48 83 ec 30 48 8b 9f 18 1c 00 00 48 8b 8a 00 04 00 00 4c 8b 07 48 8d 7b 08 <48> 89 0b 48 89 d9 48 8b 92 e0 06 00 00 48 83 e7 f8 48 29 f9 48 89
RSP: 0018:ff42462db15fb8b8 EFLAGS: 00010286
RAX: ff1276d253008000 RBX: ff1276cbfdf36000 RCX: 0000ffff00930000
RDX: ff1276cb899e6000 RSI: ff1276cb899e6400 RDI: ff1276cbfdf36008
RBP: ff42462db15fb900 R08: ff1276cbfb1f2000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: ff1276cbfb1f2000
R13: 00007fffffffdc10 R14: ff1276cbfb1f3188 R15: ff42462db15fba70
FS:  00007ffff6846f40(0000) GS:ff1276cacfaf0000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ff1276cbfdf36000 CR3: 0000004628e03004 CR4: 0000000000f71ef0
PKRU: 55555554
note: qemu-system-x86[996180] exited with irqs disabled

--
Jethro Beekman | CTO | Fortanix

^ permalink raw reply

* Re: [PATCH 00/14] KVM: x86: Emulator MMIO fix and cleanups
From: Tom Lendacky @ 2026-02-25 20:19 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini, Kiryl Shutsemau
  Cc: kvm, x86, linux-coco, linux-kernel, Yashu Zhang, Rick Edgecombe,
	Binbin Wu, Xiaoyao Li, Michael Roth
In-Reply-To: <20260225012049.920665-1-seanjc@google.com>

On 2/24/26 19:20, Sean Christopherson wrote:
> Fix a UAF stack bug where KVM references a stack pointer around an exit to
> userspace, and then clean up the related code to try to make it easier to
> maintain (not necessarily "easy", but "easier").
> 
> The SEV-ES and TDX changes are compile-tested only.
> 
> Sean Christopherson (14):
>   KVM: x86: Use scratch field in MMIO fragment to hold small write
>     values
>   KVM: x86: Open code handling of completed MMIO reads in
>     emulator_read_write()
>   KVM: x86: Trace unsatisfied MMIO reads on a per-page basis
>   KVM: x86: Use local MMIO fragment variable to clean up
>     emulator_read_write()
>   KVM: x86: Open code read vs. write userspace MMIO exits in
>     emulator_read_write()
>   KVM: x86: Move MMIO write tracing into vcpu_mmio_write()
>   KVM: x86: Harden SEV-ES MMIO against on-stack use-after-free
>   KVM: x86: Dedup kvm_sev_es_mmio_{read,write}()
>   KVM: x86: Consolidate SEV-ES MMIO emulation into a single public API
>   KVM: x86: Bury emulator read/write ops in
>     emulator_{read,write}_emulated()
>   KVM: x86: Fold emulator_write_phys() into write_emulate()
>   KVM: x86: Rename .read_write_emulate() to .read_write_guest()
>   KVM: x86: Don't panic the kernel if completing userspace I/O / MMIO
>     goes sideways
>   KVM: x86: Add helpers to prepare kvm_run for userspace MMIO exit
> 
>  arch/x86/include/asm/kvm_host.h |   3 -
>  arch/x86/kvm/emulate.c          |  13 ++
>  arch/x86/kvm/svm/sev.c          |  20 +--
>  arch/x86/kvm/vmx/tdx.c          |  14 +-
>  arch/x86/kvm/x86.c              | 287 ++++++++++++++------------------
>  arch/x86/kvm/x86.h              |  30 +++-
>  include/linux/kvm_host.h        |   3 +-
>  7 files changed, 178 insertions(+), 192 deletions(-)

A quick boot test was fine. I'm scheduling it to run through our CI to
see if anything pops up.

Thanks,
Tom

> 
> 
> base-commit: 183bb0ce8c77b0fd1fb25874112bc8751a461e49


^ permalink raw reply

* Re: [PATCH] KVM: SEV: Track SNP launch state and disallow invalid userspace interactions
From: Sean Christopherson @ 2026-02-25 20:21 UTC (permalink / raw)
  To: Jethro Beekman
  Cc: Paolo Bonzini, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, kvm, linux-kernel, linux-coco
In-Reply-To: <928a31e1-bb6f-44d4-b1de-654d6968fd55@fortanix.com>

On Wed, Feb 25, 2026, Jethro Beekman wrote:
> On 2026-02-25 12:05, Sean Christopherson wrote:
> > On Mon, Jan 19, 2026, Jethro Beekman wrote:
> >> Calling any of the SNP_LAUNCH_ ioctls after SNP_LAUNCH_FINISH results in a
> >> kernel page fault due to RMP violation. Track SNP launch state and exit early.
> > 
> > What exactly trips the RMP #PF?  A backtrace would be especially helpful for
> > posterity.
> 
> Here's a backtrace for calling ioctl(KVM_SEV_SNP_LAUNCH_FINISH) twice. Note this is with a modified version of QEMU.

> RIP: 0010:sev_es_sync_vmsa+0x54/0x4c0 [kvm_amd]
>  snp_launch_update_vmsa+0x19d/0x290 [kvm_amd]
>  snp_launch_finish+0xb6/0x380 [kvm_amd]
>  sev_mem_enc_ioctl+0x14e/0x720 [kvm_amd]
>  kvm_arch_vm_ioctl+0x837/0xcf0 [kvm]

Ah, it's the VMSA that's being accessed.  Can't we just do?

diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 723f4452302a..1e40ae592c93 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -882,6 +882,9 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm)
        u8 *d;
        int i;
 
+       if (vcpu->arch.guest_state_protected)
+               return -EINVAL;
+
        /* Check some debug related fields before encrypting the VMSA */
        if (svm->vcpu.guest_debug || (svm->vmcb->save.dr7 & ~DR7_FIXED_1))
                return -EINVAL;

^ permalink raw reply related

* Re: [PATCH] KVM: SEV: Track SNP launch state and disallow invalid userspace interactions
From: Jethro Beekman @ 2026-02-25 20:30 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Paolo Bonzini, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Dave Hansen, x86, H. Peter Anvin, kvm, linux-kernel, linux-coco
In-Reply-To: <aZ9Zs0laC2p5W-OL@google.com>

On 2026-02-25 12:21, Sean Christopherson wrote:
> On Wed, Feb 25, 2026, Jethro Beekman wrote:
>> On 2026-02-25 12:05, Sean Christopherson wrote:
>>> On Mon, Jan 19, 2026, Jethro Beekman wrote:
>>>> Calling any of the SNP_LAUNCH_ ioctls after SNP_LAUNCH_FINISH results in a
>>>> kernel page fault due to RMP violation. Track SNP launch state and exit early.
>>>
>>> What exactly trips the RMP #PF?  A backtrace would be especially helpful for
>>> posterity.
>>
>> Here's a backtrace for calling ioctl(KVM_SEV_SNP_LAUNCH_FINISH) twice. Note this is with a modified version of QEMU.
> 
>> RIP: 0010:sev_es_sync_vmsa+0x54/0x4c0 [kvm_amd]
>>  snp_launch_update_vmsa+0x19d/0x290 [kvm_amd]
>>  snp_launch_finish+0xb6/0x380 [kvm_amd]
>>  sev_mem_enc_ioctl+0x14e/0x720 [kvm_amd]
>>  kvm_arch_vm_ioctl+0x837/0xcf0 [kvm]
> 
> Ah, it's the VMSA that's being accessed.  Can't we just do?
> 
> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> index 723f4452302a..1e40ae592c93 100644
> --- a/arch/x86/kvm/svm/sev.c
> +++ b/arch/x86/kvm/svm/sev.c
> @@ -882,6 +882,9 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm)
>         u8 *d;
>         int i;
>  
> +       if (vcpu->arch.guest_state_protected)
> +               return -EINVAL;
> +
>         /* Check some debug related fields before encrypting the VMSA */
>         if (svm->vcpu.guest_debug || (svm->vmcb->save.dr7 & ~DR7_FIXED_1))
>                 return -EINVAL;

I tried relying on guest_state_protected instead of creating new state but I don't think it's sufficient. In particular, your proposal may fix snp_launch_finish() but I don't believe this addresses the issues in snp_launch_update() and sev_vcpu_create().

-- 
Jethro Beekman | CTO | Fortanix

^ permalink raw reply

* Re: [PATCH kernel 4/9] dma/swiotlb: Stop forcing SWIOTLB for TDISP devices
From: dan.j.williams @ 2026-02-25 20:57 UTC (permalink / raw)
  To: Robin Murphy, dan.j.williams, Alexey Kardashevskiy, x86
  Cc: linux-kernel, kvm, linux-pci, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Sean Christopherson,
	Paolo Bonzini, Andy Lutomirski, Peter Zijlstra, Bjorn Helgaas,
	Marek Szyprowski, Andrew Morton, Catalin Marinas,
	Michael Ellerman, Mike Rapoport, Tom Lendacky, Ard Biesheuvel,
	Neeraj Upadhyay, Ashish Kalra, Stefano Garzarella, Melody Wang,
	Seongman Lee, Joerg Roedel, Nikunj A Dadhania, Michael Roth,
	Suravee Suthikulpanit, Andi Kleen, Kuppuswamy Sathyanarayanan,
	Tony Luck, David Woodhouse, Greg Kroah-Hartman, Denis Efremov,
	Geliang Tang, Piotr Gregor, Michael S. Tsirkin, Alex Williamson,
	Arnd Bergmann, Jesse Barnes, Jacob Pan, Yinghai Lu, Kevin Brodsky,
	Jonathan Cameron, Aneesh Kumar K.V (Arm), Xu Yilun, Herbert Xu,
	Kim Phillips, Konrad Rzeszutek Wilk, Stefano Stabellini,
	Claire Chang, linux-coco, iommu
In-Reply-To: <04b06a53-769c-44f1-a157-34591b9f8439@arm.com>

Robin Murphy wrote:
> On 2026-02-25 4:30 pm, dan.j.williams@intel.com wrote:
> > Alexey Kardashevskiy wrote:
> >> SWIOTLB is enforced when encrypted guest memory is detected
> >> in pci_swiotlb_detect() which is required for legacy devices.
> >>
> >> Skip SWIOTLB for TDISP devices.
> >>
> >> Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
> >> ---
> >>   include/linux/swiotlb.h | 9 +++++++++
> >>   1 file changed, 9 insertions(+)
> >>
> >> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
> >> index 3dae0f592063..119c25d639a7 100644
> >> --- a/include/linux/swiotlb.h
> >> +++ b/include/linux/swiotlb.h
> >> @@ -173,6 +173,15 @@ static inline bool is_swiotlb_force_bounce(struct device *dev)
> >>   {
> >>   	struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
> >>   
> >> +	/*
> >> +	 * CC_ATTR_GUEST_MEM_ENCRYPT enforces SWIOTLB_FORCE in
> >> +	 * swiotlb_init_remap() to allow legacy devices access arbitrary
> >> +	 * VM encrypted memory.
> >> +	 * Skip it for TDISP devices capable of DMA-ing the encrypted memory.
> >> +	 */
> >> +	if (device_cc_accepted(dev))
> >> +		return false;
> > 
> > I worry this further muddies the meaning of the swiotlb force option.
> > What if you want to force swiotlb operation on accepted devices?
> 
> For that we'd need a whole other private SWIOTLB plus the logic to 
> decide which one to use in the first place.

In this case I was still considering that swiotlb is still implicitly
only shared address bouncining. Indeed, a whole other "private_swiotlb"
mechanism would be needed for private bouncing. Not clear there is a
need for that at present.

Even for this swiotlb=force for "accepted" devices I only see a
potential kernel development use case, not a deployment use case.

> option to forcibly expose all DMA through shared memory regardless of 
> TDISP and friends, that would logically want to be a higher-level CoCo 
> option rather than belonging to SWIOTLB itself ;)

As I have it below, yes, CoCo opts into this bounce_unaccepted mechanism.

As to your other question:

> (since a device that's trusted to access private memory
> isn't necessarily prohibited from still also accessing shared memory as
> well), hmmm...

The specification allows it, but Linux DMA mapping core is not yet ready
for it. So the expectation to start is that the device loses access to
its original shared IOMMU mappings when converted to private operation.

So on ARM where shared addresses are high, it is future work to figure
out how an accepted device might also access shared mappings outside the
device's dma_mask.

> > For example:
> > 
> > @@ -173,7 +176,13 @@ static inline bool is_swiotlb_force_bounce(struct device *dev)
> >   {
> >          struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
> >   
> > -       return mem && mem->force_bounce;
> > +       if (!mem)
> > +               return false;
> > +       if (mem->force_bounce)
> > +               return true;
> > +       if (mem->bounce_unaccepted && !device_cc_accepted(dev))
> > +               return true;
> > +       return false;
> >   }
> >   
> >   void swiotlb_init(bool addressing_limited, unsigned int flags);

^ permalink raw reply

* Re: [PATCH kernel 6/9] x86/dma-direct: Stop changing encrypted page state for TDISP devices
From: dan.j.williams @ 2026-02-25 21:35 UTC (permalink / raw)
  To: Robin Murphy, Alexey Kardashevskiy, x86
  Cc: linux-kernel, kvm, linux-pci, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Sean Christopherson,
	Paolo Bonzini, Andy Lutomirski, Peter Zijlstra, Bjorn Helgaas,
	Dan Williams, Marek Szyprowski, Andrew Morton, Catalin Marinas,
	Michael Ellerman, Mike Rapoport, Tom Lendacky, Ard Biesheuvel,
	Neeraj Upadhyay, Ashish Kalra, Stefano Garzarella, Melody Wang,
	Seongman Lee, Joerg Roedel, Nikunj A Dadhania, Michael Roth,
	Suravee Suthikulpanit, Andi Kleen, Kuppuswamy Sathyanarayanan,
	Tony Luck, David Woodhouse, Greg Kroah-Hartman, Denis Efremov,
	Geliang Tang, Piotr Gregor, Michael S. Tsirkin, Alex Williamson,
	Arnd Bergmann, Jesse Barnes, Jacob Pan, Yinghai Lu, Kevin Brodsky,
	Jonathan Cameron, Aneesh Kumar K.V (Arm), Xu Yilun, Herbert Xu,
	Kim Phillips, Konrad Rzeszutek Wilk, Stefano Stabellini,
	Claire Chang, linux-coco, iommu
In-Reply-To: <d8102507-e537-4e7c-8137-082a43fd270d@arm.com>

Robin Murphy wrote:
> On 2026-02-25 5:37 am, Alexey Kardashevskiy wrote:
> > TDISP devices operate in CoCo VMs only and capable of accessing
> > encrypted guest memory.
> > 
> > Currently when SME is on, the DMA subsystem forces the SME mask in
> > DMA handles in phys_to_dma() which assumes IOMMU pass through
> > which is never the case with CoCoVM running with a TDISP device.
> > 
> > Define X86's version of phys_to_dma() to skip leaking SME mask to
> > the device.
> > 
> > Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
> > ---
> > 
> > Doing this in the generic version breaks ARM which uses
> > the SME mask in DMA handles, hence ARCH_HAS_PHYS_TO_DMA.
> 
> That smells a bit off... In CCA we should be in the same boat, wherein a 
> trusted device can access memory at a DMA address based on its "normal" 
> (private) GPA, rather than having to be redirected to the shared alias 
> (it's really not an "SME mask" in that sense at all).

Not quite, no, CCA *is* in the same boat as TDX, not SEV-SNP. Only
SEV-SNP has this concept that the DMA handle for private memory is the
dma_addr_unencrypted() conversion (C-bit masked) of the CPU physical
address. For CCA and TDX the typical expectation of dma_addr_encrypted()
for accepted devices holds. It just so happens that dma_addr_encrypted()
does not munge the address on  is a nop conversion for CCA and TDX.

^ permalink raw reply

* Re: [PATCH kernel 2/9] pci/tsm: Add tsm_tdi_status
From: Alexey Kardashevskiy @ 2026-02-25 23:42 UTC (permalink / raw)
  To: dan.j.williams, x86
  Cc: linux-kernel, kvm, linux-pci, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Sean Christopherson,
	Paolo Bonzini, Andy Lutomirski, Peter Zijlstra, Bjorn Helgaas,
	Marek Szyprowski, Robin Murphy, Andrew Morton, Catalin Marinas,
	Michael Ellerman, Mike Rapoport, Tom Lendacky, Ard Biesheuvel,
	Neeraj Upadhyay, Ashish Kalra, Stefano Garzarella, Melody Wang,
	Seongman Lee, Joerg Roedel, Nikunj A Dadhania, Michael Roth,
	Suravee Suthikulpanit, Andi Kleen, Kuppuswamy Sathyanarayanan,
	Tony Luck, David Woodhouse, Greg Kroah-Hartman, Denis Efremov,
	Geliang Tang, Piotr Gregor, Michael S. Tsirkin, Alex Williamson,
	Arnd Bergmann, Jesse Barnes, Jacob Pan, Yinghai Lu, Kevin Brodsky,
	Jonathan Cameron, Aneesh Kumar K.V (Arm), Xu Yilun, Herbert Xu,
	Kim Phillips, Konrad Rzeszutek Wilk, Stefano Stabellini,
	Claire Chang, linux-coco, iommu
In-Reply-To: <699e97d6e8be7_1cc51003c@dwillia2-mobl4.notmuch>



On 25/2/26 17:33, dan.j.williams@intel.com wrote:
> Alexey Kardashevskiy wrote:
>> Define a structure with all info about a TDI such as TDISP status,
>> bind state, used START_INTERFACE options and the report digest.
>>
>> This will be extended and shared to the userspace.
>>
>> Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
>> ---
>>
>> Make it uapi? We might want a sysfs node per a field so probably not.
>> For now its only user is AMD SEV TIO with a plan to expose this struct
>> as a whole via sysfs.
> 
> Say more about what this uapi when sysfs already has lock+accept
> indications?
> 
> Or are you just talking about exporting the TDISP report as a binary
> blob?

I mean that between lock and accept the guest userspace wants to read certs/measurements/report to do the attestation. And it will want to know these blobs digests. And probably the TDI state. Although successful write to lock() is an indication of CONFIG_LOCKED, and accept == RUN.

We do not do real attestation in phase2 but the report is required anyway to enable private MMIO so I started shuffling with this structure.

> I think the kernel probably wants a generic abstraction for asserting
> that the tsm layer believes the report remains valid between fetch and
> run. In other words I am not sure arch features like intf_report_counter
> ever show up anywhere in uapi outside of debugfs.

True, this is a shorter (not shorter enough :) ) version of SEV-TIO's TDI_INFO. Thanks,


-- 
Alexey


^ permalink raw reply

* Re: [PATCH kernel 1/9] pci/tsm: Add TDISP report blob and helpers to parse it
From: Alexey Kardashevskiy @ 2026-02-26  0:09 UTC (permalink / raw)
  To: dan.j.williams, x86
  Cc: linux-kernel, kvm, linux-pci, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Dave Hansen, H. Peter Anvin, Sean Christopherson,
	Paolo Bonzini, Andy Lutomirski, Peter Zijlstra, Bjorn Helgaas,
	Marek Szyprowski, Robin Murphy, Andrew Morton, Catalin Marinas,
	Michael Ellerman, Mike Rapoport, Tom Lendacky, Ard Biesheuvel,
	Neeraj Upadhyay, Ashish Kalra, Stefano Garzarella, Melody Wang,
	Seongman Lee, Joerg Roedel, Nikunj A Dadhania, Michael Roth,
	Suravee Suthikulpanit, Andi Kleen, Kuppuswamy Sathyanarayanan,
	Tony Luck, David Woodhouse, Greg Kroah-Hartman, Denis Efremov,
	Geliang Tang, Piotr Gregor, Michael S. Tsirkin, Alex Williamson,
	Arnd Bergmann, Jesse Barnes, Jacob Pan, Yinghai Lu, Kevin Brodsky,
	Jonathan Cameron, Aneesh Kumar K.V (Arm), Xu Yilun, Herbert Xu,
	Kim Phillips, Konrad Rzeszutek Wilk, Stefano Stabellini,
	Claire Chang, linux-coco, iommu
In-Reply-To: <699e93db9ad47_1cc510090@dwillia2-mobl4.notmuch>



On 25/2/26 17:16, dan.j.williams@intel.com wrote:
> Alexey Kardashevskiy wrote:
>> The TDI interface report is defined in PCIe r7.0,
>> chapter "11.3.11 DEVICE_INTERFACE_REPORT". The report enumerates
>> MMIO resources and their properties which will take effect upon
>> transitioning to the RUN state.
>>
>> Store the report in pci_tsm.
>>
>> Define macros and helpers to parse the binary blob.
>>
>> Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
>> ---
>>
>> Probably pci_tsm::report could be struct tdi_report_header*?
> [..]
>> +struct tdi_report_header {
>> +	__u16 interface_info; /* TSM_TDI_REPORT_xxx */
>> +	__u16 reserved2;
>> +	__u16 msi_x_message_control;
>> +	__u16 lnr_control;
>> +	__u32 tph_control;
>> +	__u32 mmio_range_count;
>> +} __packed;
>> +
>> +/*
>> + * Each MMIO Range of the TDI is reported with the MMIO reporting offset added.
>> + * Base and size in units of 4K pages
>> + */
>> +#define TSM_TDI_REPORT_MMIO_MSIX_TABLE		BIT(0)
>> +#define TSM_TDI_REPORT_MMIO_PBA			BIT(1)
>> +#define TSM_TDI_REPORT_MMIO_IS_NON_TEE		BIT(2)
>> +#define TSM_TDI_REPORT_MMIO_IS_UPDATABLE	BIT(3)
>> +#define TSM_TDI_REPORT_MMIO_RESERVED		GENMASK(15, 4)
>> +#define TSM_TDI_REPORT_MMIO_RANGE_ID		GENMASK(31, 16)
>> +
>> +struct tdi_report_mmio_range {
>> +	__u64 first_page;		/* First 4K page with offset added */
>> +	__u32 num;			/* Number of 4K pages in this range */
>> +	__u32 range_attributes;		/* TSM_TDI_REPORT_MMIO_xxx */
> 
> Those should be __le64 and le32, right? 

Oh yes.

> But see below for another
> option...
> 
>> +} __packed;
>> +
>> +struct tdi_report_footer {
>> +	__u32 device_specific_info_len;
>> +	__u8 device_specific_info[];
>> +} __packed;
>> +
>> +#define TDI_REPORT_HDR(rep)		((struct tdi_report_header *) ((rep)->data))
>> +#define TDI_REPORT_MR_NUM(rep)		(TDI_REPORT_HDR(rep)->mmio_range_count)
>> +#define TDI_REPORT_MR_OFF(rep)		((struct tdi_report_mmio_range *) (TDI_REPORT_HDR(rep) + 1))
>> +#define TDI_REPORT_MR(rep, rangeid)	TDI_REPORT_MR_OFF(rep)[rangeid]
>> +#define TDI_REPORT_FTR(rep)		((struct tdi_report_footer *) &TDI_REPORT_MR((rep), \
>> +					TDI_REPORT_MR_NUM(rep)))
>> +
> 
> So we all have a version of a patch like this and the general style
> suggestion I have is to just parse this layout with typical
> offsets+bitfield definitions.
> 
> This follows the precedent, admittedly tiny, of the DOE definitions in
> pci_regs.h. See:
> 
> 	/* DOE Data Object - note not actually registers */
> 
> I have a patch that parses the TDISP report with these defines:
> 
> /*
>   * PCIe ECN TEE Device Interface Security Protocol (TDISP)
>   *
>   * Device Interface Report data object layout as defined by PCIe r7.0 section
>   * 11.3.11
>   */
> #define PCI_TSM_DEVIF_REPORT_INFO 0
> #define PCI_TSM_DEVIF_REPORT_MSIX 4
> #define PCI_TSM_DEVIF_REPORT_LNR 6
> #define PCI_TSM_DEVIF_REPORT_TPH 8
> #define PCI_TSM_DEVIF_REPORT_MMIO_COUNT 12
> #define  PCI_TSM_DEVIF_REPORT_MMIO_PFN 0 /* An interface report 'pfn' is 4K in size */
> #define  PCI_TSM_DEVIF_REPORT_MMIO_NR_PFNS 8
> #define  PCI_TSM_DEVIF_REPORT_MMIO_ATTR 12


I cannot easily see from these what the sizes are. And how many of each.

> #define  PCI_TSM_DEVIF_REPORT_MMIO_ATTR_MSIX_TABLE BIT(0)
> #define  PCI_TSM_DEVIF_REPORT_MMIO_ATTR_MSIX_PBA BIT(1)
> #define  PCI_TSM_DEVIF_REPORT_MMIO_ATTR_IS_NON_TEE BIT(2)
> #define  PCI_TSM_DEVIF_REPORT_MMIO_ATTR_IS_UPDATABLE BIT(3)
> #define  PCI_TSM_DEVIF_REPORT_MMIO_ATTR_RANGE_ID GENMASK(31, 16)
> #define  PCI_TSM_DEVIF_REPORT_MMIO_SIZE (16)
> #define PCI_TSM_DEVIF_REPORT_BASE_SIZE(nr_mmio) (16 + nr_mmio * PCI_TSM_DEVIF_REPORT_MMIO_SIZE)
> 
> Any strong feelings one way or the other? I have a mild preference for
> this offset+bitfields approach.


My variant is just like this (may be need to put it in the comment):

tdi_report_header
tdi_report_mmio_range[]
tdi_report_footer

imho easier on eyes. I can live with either if the majority votes for it. Thanks.

-- 
Alexey


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox