* Re: [PATCH v12 06/46] arm64: RMI: Define the user ABI
From: Marc Zyngier @ 2026-03-03 13:11 UTC (permalink / raw)
To: Steven Price
Cc: kvm, kvmarm, Catalin Marinas, Will Deacon, James Morse,
Oliver Upton, Suzuki K Poulose, Zenghui Yu, linux-arm-kernel,
linux-kernel, Joey Gouly, Alexandru Elisei, Christoffer Dall,
Fuad Tabba, linux-coco, Ganapatrao Kulkarni, Gavin Shan,
Shanker Donthineni, Alper Gun, Aneesh Kumar K . V, Emi Kisanuki,
Vishal Annapurve
In-Reply-To: <33053e22-6cc6-4d55-bc7f-01f873a15d28@arm.com>
On Mon, 02 Mar 2026 15:23:44 +0000,
Steven Price <steven.price@arm.com> wrote:
>
> Hi Marc,
>
> On 02/03/2026 14:25, Marc Zyngier wrote:
> > On Wed, 17 Dec 2025 10:10:43 +0000,
> > Steven Price <steven.price@arm.com> wrote:
> >>
> >> There is one CAP which identified the presence of CCA, and two ioctls.
> >> One ioctl is used to populate memory and the other is used when user
> >> space is providing the PSCI implementation to identify the target of the
> >> operation.
> >>
> >> Signed-off-by: Steven Price <steven.price@arm.com>
> >> ---
> >> Changes since v11:
> >> * Completely reworked to be more implicit. Rather than having explicit
> >> CAP operations to progress the realm construction these operations
> >> are done when needed (on populating and on first vCPU run).
> >> * Populate and PSCI complete are promoted to proper ioctls.
> >> Changes since v10:
> >> * Rename symbols from RME to RMI.
> >> Changes since v9:
> >> * Improvements to documentation.
> >> * Bump the magic number for KVM_CAP_ARM_RME to avoid conflicts.
> >> Changes since v8:
> >> * Minor improvements to documentation following review.
> >> * Bump the magic numbers to avoid conflicts.
> >> Changes since v7:
> >> * Add documentation of new ioctls
> >> * Bump the magic numbers to avoid conflicts
> >> Changes since v6:
> >> * Rename some of the symbols to make their usage clearer and avoid
> >> repetition.
> >> Changes from v5:
> >> * Actually expose the new VCPU capability (KVM_ARM_VCPU_REC) by bumping
> >> KVM_VCPU_MAX_FEATURES - note this also exposes KVM_ARM_VCPU_HAS_EL2!
> >> ---
> >> Documentation/virt/kvm/api.rst | 57 ++++++++++++++++++++++++++++++++++
> >> include/uapi/linux/kvm.h | 23 ++++++++++++++
> >> 2 files changed, 80 insertions(+)
> >>
> >> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> >> index 01a3abef8abb..2d5dc7e48954 100644
> >> --- a/Documentation/virt/kvm/api.rst
> >> +++ b/Documentation/virt/kvm/api.rst
> >> @@ -6517,6 +6517,54 @@ the capability to be present.
> >>
> >> `flags` must currently be zero.
> >>
> >> +4.144 KVM_ARM_VCPU_RMI_PSCI_COMPLETE
> >> +------------------------------------
> >> +
> >> +:Capability: KVM_CAP_ARM_RMI
> >> +:Architectures: arm64
> >> +:Type: vcpu ioctl
> >> +:Parameters: struct kvm_arm_rmi_psci_complete (in)
> >> +:Returns: 0 if successful, < 0 on error
> >> +
> >> +::
> >> +
> >> + struct kvm_arm_rmi_psci_complete {
> >> + __u64 target_mpidr;
> >> + __u32 psci_status;
> >> + __u32 padding[3];
> >> + };
> >> +
> >> +Where PSCI functions are handled by user space, the RMM needs to be informed of
> >> +the target of the operation using `target_mpidr`, along with the status
> >> +(`psci_status`). The RMM v1.0 specification defines two functions that require
> >> +this call: PSCI_CPU_ON and PSCI_AFFINITY_INFO.
> >> +
> >> +If the kernel is handling PSCI then this is done automatically and the VMM
> >> +doesn't need to call this ioctl.
> >
> > Shouldn't we make handling of PSCI mandatory for VMMs that deal with
> > CCA? I suspect it would simplify the implementation significantly.
>
> What do you mean by making it "mandatory for VMMs"? If you mean PSCI is
> always forwarded to user space then I don't think it's going to make
> much difference. Patch 27 handles the PSCI changes (72 lines added), and
> some of that is adding this uAPI for the VMM to handle it.
>
> Removing the functionality to allow the VMM to handle it would obviously
> simplify things a bit (we can drop this uAPI), but I think the desire is
> to push this onto user space.
And that's what I'm asking for. I do not want this to be optional. CCA
should implies PSCI in userspace, and that's it.
>
> > What vcpu fd does this apply to? The vcpu calling the PSCI function?
> > Or the target? This is pretty important for PSCI_ON. My guess is that
> > this is setting the return value for the caller?
>
> Yes the fd is the vcpu calling PSCI. As you say, this is for the return
> value to be set correctly.
Another question is why do we need the ioctl at all? Why can't it be
done on the first run of the target vcpu? If no PSCI call was issued
to run it, then the run fails.
>
> > Assuming this is indeed for the caller, why do we have a different
> > flow from anything else that returns a result from a hypercall?
>
> I'm not entirely sure what you are suggesting. Do you mean why are we
> not just writing to the GPRS that would contain the result? The issue
> here is that the RMM needs to know the PA of the target REC structure -
> this isn't a return to the guest, but information for the RMM itself to
> complete the PSCI call.
PSCI is a SMC call. SMC calls are routed to userspace as such. For odd
reasons, the RMM treats PSCI differently from any other SMC call.
That seems a very bizarre behaviour to me.
>
> Ultimately even in the case where the VMM is handling PSCI, it's
> actually a combination of the VMM and the RMM - with the RMM validating
> the responses.
I don't see why PSCI is singled out here, irrespective of the tracking
that the RMM wants to do.
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH v12 27/46] KVM: arm64: Handle Realm PSCI requests
From: Marc Zyngier @ 2026-03-03 13:04 UTC (permalink / raw)
To: Suzuki K Poulose
Cc: Steven Price, kvm, kvmarm, Catalin Marinas, Will Deacon,
James Morse, Oliver Upton, Zenghui Yu, linux-arm-kernel,
linux-kernel, Joey Gouly, Alexandru Elisei, Christoffer Dall,
Fuad Tabba, linux-coco, Ganapatrao Kulkarni, Gavin Shan,
Shanker Donthineni, Alper Gun, Aneesh Kumar K . V, Emi Kisanuki,
Vishal Annapurve
In-Reply-To: <ec27e294-0bee-474a-a15b-6be20ee10cd4@arm.com>
On Tue, 03 Mar 2026 09:26:31 +0000,
Suzuki K Poulose <suzuki.poulose@arm.com> wrote:
>
> On 02/03/2026 16:39, Marc Zyngier wrote:
> > On Wed, 17 Dec 2025 10:11:04 +0000,
> > Steven Price <steven.price@arm.com> wrote:
> >>
> >> The RMM needs to be informed of the target REC when a PSCI call is made
> >> with an MPIDR argument. Expose an ioctl to the userspace in case the PSCI
> >> is handled by it.
> >>
> >> Co-developed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> >> Signed-off-by: Steven Price <steven.price@arm.com>
> >> Reviewed-by: Gavin Shan <gshan@redhat.com>
> >> ---
> >> Changes since v11:
> >> * RMM->RMI renaming.
> >> Changes since v6:
> >> * Use vcpu_is_rec() rather than kvm_is_realm(vcpu->kvm).
> >> * Minor renaming/formatting fixes.
> >> ---
> >> arch/arm64/include/asm/kvm_rmi.h | 3 +++
> >> arch/arm64/kvm/arm.c | 25 +++++++++++++++++++++++++
> >> arch/arm64/kvm/psci.c | 30 ++++++++++++++++++++++++++++++
> >> arch/arm64/kvm/rmi.c | 14 ++++++++++++++
> >> 4 files changed, 72 insertions(+)
> >>
> >> diff --git a/arch/arm64/include/asm/kvm_rmi.h b/arch/arm64/include/asm/kvm_rmi.h
> >> index bfe6428eaf16..77da297ca09d 100644
> >> --- a/arch/arm64/include/asm/kvm_rmi.h
> >> +++ b/arch/arm64/include/asm/kvm_rmi.h
> >> @@ -118,6 +118,9 @@ int realm_map_non_secure(struct realm *realm,
> >> kvm_pfn_t pfn,
> >> unsigned long size,
> >> struct kvm_mmu_memory_cache *memcache);
> >> +int realm_psci_complete(struct kvm_vcpu *source,
> >> + struct kvm_vcpu *target,
> >> + unsigned long status);
> >> static inline bool kvm_realm_is_private_address(struct realm
> >> *realm,
> >> unsigned long addr)
> >> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> >> index 06070bc47ee3..fb04d032504e 100644
> >> --- a/arch/arm64/kvm/arm.c
> >> +++ b/arch/arm64/kvm/arm.c
> >> @@ -1797,6 +1797,22 @@ static int kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
> >> return __kvm_arm_vcpu_set_events(vcpu, events);
> >> }
> >> +static int kvm_arm_vcpu_rmi_psci_complete(struct kvm_vcpu *vcpu,
> >> + struct kvm_arm_rmi_psci_complete *arg)
> >> +{
> >> + struct kvm_vcpu *target = kvm_mpidr_to_vcpu(vcpu->kvm, arg->target_mpidr);
> >> +
> >> + if (!target)
> >> + return -EINVAL;
> >> +
> >> + /*
> >> + * RMM v1.0 only supports PSCI_RET_SUCCESS or PSCI_RET_DENIED
> >> + * for the status. But, let us leave it to the RMM to filter
> >> + * for making this future proof.
> >> + */
> >> + return realm_psci_complete(vcpu, target, arg->psci_status);
> >> +}
> >> +
> >> long kvm_arch_vcpu_ioctl(struct file *filp,
> >> unsigned int ioctl, unsigned long arg)
> >> {
> >> @@ -1925,6 +1941,15 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
> >> return kvm_arm_vcpu_finalize(vcpu, what);
> >> }
> >> + case KVM_ARM_VCPU_RMI_PSCI_COMPLETE: {
> >> + struct kvm_arm_rmi_psci_complete req;
> >> +
> >> + if (!vcpu_is_rec(vcpu))
> >> + return -EPERM;
> >
> > Same remark as for the other ioctl: EPERM is not quite describing the
> > problem.
> >
> >> + if (copy_from_user(&req, argp, sizeof(req)))
> >> + return -EFAULT;
> >> + return kvm_arm_vcpu_rmi_psci_complete(vcpu, &req);
> >> + }
> >> default:
> >> r = -EINVAL;
> >> }
> >> diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
> >> index 3b5dbe9a0a0e..a68f3c1878a5 100644
> >> --- a/arch/arm64/kvm/psci.c
> >> +++ b/arch/arm64/kvm/psci.c
> >> @@ -103,6 +103,12 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
> >> reset_state->reset = true;
> >> kvm_make_request(KVM_REQ_VCPU_RESET, vcpu);
> >> + /*
> >> + * Make sure we issue PSCI_COMPLETE before the VCPU can be
> >> + * scheduled.
> >> + */
> >> + if (vcpu_is_rec(vcpu))
> >> + realm_psci_complete(source_vcpu, vcpu, PSCI_RET_SUCCESS);
> >>
> >
> > I really think in-kernel PSCI should be for NS VMs only. The whole
> > reason for moving to userspace support was to stop adding features to
> > an already complex infrastructure, and CCA is exactly the sort of
> > things we want userspace to deal with.
>
> Agreed. How would you like us to enforce this ? Should we always exit
> to the VMM, even if it hasn't requested the handling ? (I guess it is
> fine and in the worst case VMM could exit, it being buggy)
My current train of though is that a CCA VM always routes PSCI to
userspace, no configuration needed. That's part of the contract.
Now, I'm pretty sure we should *also* get rid of the ioctl that
establishes the relationship between MPIDR and REC. I can't see why
this can't be done at the point where the vcpu runs for the first
time, just like this is done for the first CPU.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply
* Re: [PATCH kernel 4/9] dma/swiotlb: Stop forcing SWIOTLB for TDISP devices
From: Jason Gunthorpe @ 2026-03-03 12:43 UTC (permalink / raw)
To: dan.j.williams
Cc: Robin Murphy, Alexey Kardashevskiy, x86, 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: <20260303001911.GA964116@ziepe.ca>
On Mon, Mar 02, 2026 at 08:19:11PM -0400, Jason Gunthorpe wrote:
> > Oh, I thought SEV-TIO had trouble with this, if this is indeed the case,
> > great, ignore my first comment.
>
> Alexey?
>
> I think it is really important that shared mappings continue to be
> reachable by TDISP device.
I think Alexey has clarified this in the other thread, and probably
AMD has some work to do here.
The issue is AMD does not have seperate address spaces for
shared/private like ARM does, instead it relies on a C bit in the *PTE*
to determine shared/private.
The S2 IOMMU page table *does* have the full mapping of all shared &
private pages but the HW requires a matching C bit to permit access.
If there is a S1 IOMMU then the IOPTEs of the VM can provide the C
bit, so no problem.
If there is no S1 then the sDTE of the hypervisor controls the C bit,
and it sounds like currently AMD sets this globally which effectively
locks TDISP RUN devices to *only* access private memory.
I suspect AMD needs to use their vTOM feature to allow shared memory
to remain available to TDISP RUN with a high/low address split.
Alexey, did I capture this properly?
Jason
^ permalink raw reply
* Re: [PATCH kernel 6/9] x86/dma-direct: Stop changing encrypted page state for TDISP devices
From: Jason Gunthorpe @ 2026-03-03 12:15 UTC (permalink / raw)
To: Alexey Kardashevskiy
Cc: Robin Murphy, x86, 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, 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, Jiri Pirko
In-Reply-To: <9cf2e2e6-0fe2-4804-9c62-bc60c89d57c1@amd.com>
On Tue, Mar 03, 2026 at 07:19:36PM +1100, Alexey Kardashevskiy wrote:
> > It seems from your email that the CPU S2 has the Cbit as part of the
> > address and the S1 feeds it through to the S2, so it is genuinely has
> > two addres spaces?
>
> S1/S2 PTEs have Cbit. Addresses to look up those PTEs - do not.
So we are back to what I was saying before: using phys_addr_t to
encode a PTE bit is probably a very confusing idea - especially when
contrasted with the other arches that have a legitimate address bit.
> > Same way it knows if there is no S1?
>
> If no S1 - then sDTE decides on Cbit for the entire ASID (with the help of vTOM).
Sounds like the intention was the IOMMU shared/private space would be
controlled with vTOM which actually does a create a legitimate address
bit in the phys_addr_t.
A sDTE global control is OK for non-TDISP devices, or even devices
that haven't entered RUN yet, but it is not OK for a TDISP device that
must still be able to access shared memory.
> I understand I am often confusing, trying to unconfuse (including myself)... Thanks,
It seems to me the AMD architecture itself is pretty confusing. :\
Jason
^ permalink raw reply
* Re: [PATCH v2 08/19] PCI/TSM: Add "evidence" support
From: Aneesh Kumar K.V @ 2026-03-03 10:16 UTC (permalink / raw)
To: Dan Williams, linux-coco, linux-pci
Cc: gregkh, aik, yilun.xu, bhelgaas, alistair23, lukas, jgg,
Donald Hunter, Jakub Kicinski
In-Reply-To: <20260303000207.1836586-9-dan.j.williams@intel.com>
Dan Williams <dan.j.williams@intel.com> writes:
> Once one accepts the threat model that devices may be adversarial the
> process of establishing trust in the device identity, the integrity +
> confidentiality of its link, and the integrity + confidentiality of its
> MMIO interface requires multiple evidence objects from the device. The
> device's certificate chain, measurements and interface report need to be
> retrieved by the host, validated by the TSM and transmitted to the guest
> all while mitigating TOCTOU races.
>
> All TSM implementations share the same fundamental objects, but vary in how
> the TSM conveys its trust in the objects. Some TSM implementations expect
> the full documents to be conveyed over untrustworthy channels while the TSM
> securely conveys a digest. Others transmit full objects with signed SPDM
> transcripts of requester provided nonces. Some offer a single transcript
> to convey the version, capabilities, and algorithms (VCA) data and
> measurements in one blob while others split VCA as a separate signed blob.
>
> Introduce a netlink interface to dump all these objects in a common way
> across TSM implementations and across host and guest environments.
> Userspace is responsible for handling the variance of "TSM provides combo
> measurements + VCA + nonce + signature, vs TSM provides a digest over a
> secure channel of the same".
>
> The implementation adheres to the guideline from:
> Documentation/userspace-api/netlink/genetlink-legacy.rst
>
> New Netlink families should never respond to a DO operation with
> multiple replies, with ``NLM_F_MULTI`` set. Use a filtered dump
> instead.
>
> Per SPDM, transcripts may grow to be 16MB in size. Large PCI/TSM netlink
> blobs are handled via a sequence of dump messages that userspace must
> concatenate.
>
> Cc: Donald Hunter <donald.hunter@gmail.com>
> Cc: Jakub Kicinski <kuba@kernel.org>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Xu Yilun <yilun.xu@linux.intel.com>
> Cc: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>
> Cc: Alexey Kardashevskiy <aik@amd.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
> drivers/pci/Makefile | 2 +-
> drivers/pci/tsm/Makefile | 9 +
> Documentation/netlink/specs/pci-tsm.yaml | 151 +++++++++++++
> drivers/pci/tsm/netlink.h | 23 ++
> include/linux/pci-tsm.h | 63 ++++++
> include/uapi/linux/pci-tsm-netlink.h | 101 +++++++++
> drivers/pci/{tsm.c => tsm/core.c} | 17 +-
> drivers/pci/tsm/evidence.c | 274 +++++++++++++++++++++++
> drivers/pci/tsm/netlink.c | 43 ++++
> MAINTAINERS | 4 +-
> 10 files changed, 682 insertions(+), 5 deletions(-)
> create mode 100644 drivers/pci/tsm/Makefile
> create mode 100644 Documentation/netlink/specs/pci-tsm.yaml
> create mode 100644 drivers/pci/tsm/netlink.h
> create mode 100644 include/uapi/linux/pci-tsm-netlink.h
> rename drivers/pci/{tsm.c => tsm/core.c} (98%)
> create mode 100644 drivers/pci/tsm/evidence.c
> create mode 100644 drivers/pci/tsm/netlink.c
>
> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
> index e10cfe5a280b..31f5095360af 100644
> --- a/drivers/pci/Makefile
> +++ b/drivers/pci/Makefile
> @@ -35,7 +35,7 @@ obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
> obj-$(CONFIG_VGA_ARB) += vgaarb.o
> obj-$(CONFIG_PCI_DOE) += doe.o
> obj-$(CONFIG_PCI_IDE) += ide.o
> -obj-$(CONFIG_PCI_TSM) += tsm.o
> +obj-$(CONFIG_PCI_TSM) += tsm/
> obj-$(CONFIG_PCI_DYNAMIC_OF_NODES) += of_property.o
> obj-$(CONFIG_PCI_NPEM) += npem.o
> obj-$(CONFIG_PCIE_TPH) += tph.o
> diff --git a/drivers/pci/tsm/Makefile b/drivers/pci/tsm/Makefile
> new file mode 100644
> index 000000000000..afa775224b8d
> --- /dev/null
> +++ b/drivers/pci/tsm/Makefile
> @@ -0,0 +1,9 @@
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Makefile for the PCI/TSM infrastructure
> +
> +obj-$(CONFIG_PCI_TSM) += tsm.o
> +
> +tsm-y := core.o
> +tsm-$(CONFIG_NET) += netlink.o
> +tsm-$(CONFIG_NET) += evidence.o
> diff --git a/Documentation/netlink/specs/pci-tsm.yaml b/Documentation/netlink/specs/pci-tsm.yaml
> new file mode 100644
> index 000000000000..eb7fc03bd705
> --- /dev/null
> +++ b/Documentation/netlink/specs/pci-tsm.yaml
> @@ -0,0 +1,151 @@
> +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)
> +#
> +---
> +name: pci-tsm
> +protocol: genetlink
> +uapi-header: linux/pci-tsm-netlink.h
> +doc: PCI TSM Evidence retrieval over generic netlink
> +
> +definitions:
> + -
> + type: const
> + name: max-object-size
> + value: 0x01000000
> + -
> + type: const
> + name: max-nonce-size
> + value: 256
> + -
> + type: const
> + name: max-obj-type
> + value: 4
> + -
> + name: evidence-type
> + type: enum
> + doc: PCI device security evidence objects
> + entries:
> + -
> + name: cert0
> + doc: SPDM certificate chain from device slot0
> + -
> + name: cert1
> + doc: SPDM certificate chain from device slot1
> + -
> + name: cert2
> + doc: SPDM certificate chain from device slot2
> + -
> + name: cert3
> + doc: SPDM certificate chain from device slot3
> + -
> + name: cert4
> + doc: SPDM certificate chain from device slot4
> + -
> + name: cert5
> + doc: SPDM certificate chain from device slot5
> + -
> + name: cert6
> + doc: SPDM certificate chain from device slot6
> + -
> + name: cert7
> + doc: SPDM certificate chain from device slot7
> + -
> + name: vca
> + doc: SPDM transcript of version, capabilities, and algorithms negotiation
> + -
> + name: measurements
> + doc: SPDM GET_MEASUREMENTS response
> + -
> + name: report
> + doc: TDISP GET_DEVICE_INTERFACE_REPORT response
> +
>
In the case of CCA, the slot number is determined early, when we create
the pdev object that maps to PF0. This is done as part of the connect
callback. Currently, the slot number is hardcoded to 0. I believe we
need to extend connect to include slot information.
Even with that change, we would only have one certificate type.
These would correspond to whichever slot number was selected during
connect.
-aneesh
^ permalink raw reply
* Re: [PATCH v12 27/46] KVM: arm64: Handle Realm PSCI requests
From: Suzuki K Poulose @ 2026-03-03 9:26 UTC (permalink / raw)
To: Marc Zyngier, Steven Price
Cc: kvm, kvmarm, Catalin Marinas, Will Deacon, James Morse,
Oliver Upton, Zenghui Yu, linux-arm-kernel, linux-kernel,
Joey Gouly, Alexandru Elisei, Christoffer Dall, Fuad Tabba,
linux-coco, Ganapatrao Kulkarni, Gavin Shan, Shanker Donthineni,
Alper Gun, Aneesh Kumar K . V, Emi Kisanuki, Vishal Annapurve
In-Reply-To: <86pl5m89ub.wl-maz@kernel.org>
On 02/03/2026 16:39, Marc Zyngier wrote:
> On Wed, 17 Dec 2025 10:11:04 +0000,
> Steven Price <steven.price@arm.com> wrote:
>>
>> The RMM needs to be informed of the target REC when a PSCI call is made
>> with an MPIDR argument. Expose an ioctl to the userspace in case the PSCI
>> is handled by it.
>>
>> Co-developed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> Signed-off-by: Steven Price <steven.price@arm.com>
>> Reviewed-by: Gavin Shan <gshan@redhat.com>
>> ---
>> Changes since v11:
>> * RMM->RMI renaming.
>> Changes since v6:
>> * Use vcpu_is_rec() rather than kvm_is_realm(vcpu->kvm).
>> * Minor renaming/formatting fixes.
>> ---
>> arch/arm64/include/asm/kvm_rmi.h | 3 +++
>> arch/arm64/kvm/arm.c | 25 +++++++++++++++++++++++++
>> arch/arm64/kvm/psci.c | 30 ++++++++++++++++++++++++++++++
>> arch/arm64/kvm/rmi.c | 14 ++++++++++++++
>> 4 files changed, 72 insertions(+)
>>
>> diff --git a/arch/arm64/include/asm/kvm_rmi.h b/arch/arm64/include/asm/kvm_rmi.h
>> index bfe6428eaf16..77da297ca09d 100644
>> --- a/arch/arm64/include/asm/kvm_rmi.h
>> +++ b/arch/arm64/include/asm/kvm_rmi.h
>> @@ -118,6 +118,9 @@ int realm_map_non_secure(struct realm *realm,
>> kvm_pfn_t pfn,
>> unsigned long size,
>> struct kvm_mmu_memory_cache *memcache);
>> +int realm_psci_complete(struct kvm_vcpu *source,
>> + struct kvm_vcpu *target,
>> + unsigned long status);
>>
>> static inline bool kvm_realm_is_private_address(struct realm *realm,
>> unsigned long addr)
>> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
>> index 06070bc47ee3..fb04d032504e 100644
>> --- a/arch/arm64/kvm/arm.c
>> +++ b/arch/arm64/kvm/arm.c
>> @@ -1797,6 +1797,22 @@ static int kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu,
>> return __kvm_arm_vcpu_set_events(vcpu, events);
>> }
>>
>> +static int kvm_arm_vcpu_rmi_psci_complete(struct kvm_vcpu *vcpu,
>> + struct kvm_arm_rmi_psci_complete *arg)
>> +{
>> + struct kvm_vcpu *target = kvm_mpidr_to_vcpu(vcpu->kvm, arg->target_mpidr);
>> +
>> + if (!target)
>> + return -EINVAL;
>> +
>> + /*
>> + * RMM v1.0 only supports PSCI_RET_SUCCESS or PSCI_RET_DENIED
>> + * for the status. But, let us leave it to the RMM to filter
>> + * for making this future proof.
>> + */
>> + return realm_psci_complete(vcpu, target, arg->psci_status);
>> +}
>> +
>> long kvm_arch_vcpu_ioctl(struct file *filp,
>> unsigned int ioctl, unsigned long arg)
>> {
>> @@ -1925,6 +1941,15 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
>>
>> return kvm_arm_vcpu_finalize(vcpu, what);
>> }
>> + case KVM_ARM_VCPU_RMI_PSCI_COMPLETE: {
>> + struct kvm_arm_rmi_psci_complete req;
>> +
>> + if (!vcpu_is_rec(vcpu))
>> + return -EPERM;
>
> Same remark as for the other ioctl: EPERM is not quite describing the
> problem.
>
>> + if (copy_from_user(&req, argp, sizeof(req)))
>> + return -EFAULT;
>> + return kvm_arm_vcpu_rmi_psci_complete(vcpu, &req);
>> + }
>> default:
>> r = -EINVAL;
>> }
>> diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
>> index 3b5dbe9a0a0e..a68f3c1878a5 100644
>> --- a/arch/arm64/kvm/psci.c
>> +++ b/arch/arm64/kvm/psci.c
>> @@ -103,6 +103,12 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
>>
>> reset_state->reset = true;
>> kvm_make_request(KVM_REQ_VCPU_RESET, vcpu);
>> + /*
>> + * Make sure we issue PSCI_COMPLETE before the VCPU can be
>> + * scheduled.
>> + */
>> + if (vcpu_is_rec(vcpu))
>> + realm_psci_complete(source_vcpu, vcpu, PSCI_RET_SUCCESS);
>>
>
> I really think in-kernel PSCI should be for NS VMs only. The whole
> reason for moving to userspace support was to stop adding features to
> an already complex infrastructure, and CCA is exactly the sort of
> things we want userspace to deal with.
Agreed. How would you like us to enforce this ? Should we always exit
to the VMM, even if it hasn't requested the handling ? (I guess it is
fine and in the worst case VMM could exit, it being buggy)
Cheers
Suzuki
>
> Thanks,
>
> M.
>
^ permalink raw reply
* Re: [PATCH v2 00/19] PCI/TSM: TEE I/O infrastructure
From: Aneesh Kumar K.V @ 2026-03-03 9:23 UTC (permalink / raw)
To: Dan Williams, linux-coco, linux-pci
Cc: gregkh, aik, yilun.xu, bhelgaas, alistair23, lukas, jgg,
Andy Lutomirski, Arnd Bergmann, Borislav Petkov,
Christoph Hellwig, Danilo Krummrich, Dave Hansen, Donald Hunter,
H. Peter Anvin, Ingo Molnar, Jakub Kicinski, Jason Gunthorpe,
Luis Chamberlain, Marek Szyprowski, Peter Zijlstra,
Rafael J. Wysocki, Robin Murphy, Roman Kisel, Samuel Ortiz,
Saravana Kannan, Suzuki K Poulose, Thomas Gleixner,
Thomas Gleixner
In-Reply-To: <20260303000207.1836586-1-dan.j.williams@intel.com>
Dan Williams <dan.j.williams@intel.com> writes:
....
To support devices without IDE/DOE support we need something similar.
modified drivers/pci/tsm/core.c
@@ -1236,12 +1236,14 @@ int pci_tsm_pf0_constructor(struct pci_dev *pdev, struct pci_tsm_pf0 *tsm,
struct tsm_dev *tsm_dev)
{
mutex_init(&tsm->lock);
- tsm->doe_mb = pci_find_doe_mailbox(pdev, PCI_VENDOR_ID_PCI_SIG,
- PCI_DOE_FEATURE_CMA);
- if (!tsm->doe_mb) {
- pci_warn(pdev, "TSM init failure, no CMA mailbox\n");
- return -ENODEV;
- }
+
+ /*
+ * Note, low-level TSM driver responsible for determining if it wants to
+ * proceed with a device that has no DOE mailbox. TSM may have an
+ * alternate method for coordinating TDISP.
+ */
+ if (!tsm->doe_mb)
+ pci_dbg(pdev, "no CMA mailbox\n");
return pci_tsm_link_constructor(pdev, &tsm->base_tsm, tsm_dev);
}
^ permalink raw reply
* Re: [PATCH v2 10/19] x86, swiotlb: Teach swiotlb to skip "accepted" devices
From: Aneesh Kumar K.V @ 2026-03-03 9:07 UTC (permalink / raw)
To: Dan Williams, linux-coco, linux-pci
Cc: gregkh, aik, yilun.xu, bhelgaas, alistair23, lukas, jgg,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Marek Szyprowski, Robin Murphy
In-Reply-To: <20260303000207.1836586-11-dan.j.williams@intel.com>
Dan Williams <dan.j.williams@intel.com> writes:
> There are two mechanisms to force SWIOTLB operation, the kernel command
> line option and the internal SWIOTLB_FORCE flag. With the arrival of
> "accepted" devices, devices that have been enabled to DMA to private
> encrypted memory, the SWIOTLB_FORCE flag is an awkward fit. It may be the
> case that SWIOTLB operation wants to be forced regardless of the device
> acceptance state.
>
> Introduce a new SWIOTLB_UNACCPTED flag that allows for both augmenting the
> result of is_swiotlb_force_bounce() dynamically and allowing for an "always
> SWIOTLB" override.
>
> Cc: Thomas Gleixner <tglx@kernel.org>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: x86@kernel.org
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
> include/linux/swiotlb.h | 15 ++++++++++++---
> arch/x86/kernel/pci-dma.c | 2 +-
> kernel/dma/swiotlb.c | 1 +
> 3 files changed, 14 insertions(+), 4 deletions(-)
>
> diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
> index 3dae0f592063..0efb9b8e5dd0 100644
> --- a/include/linux/swiotlb.h
> +++ b/include/linux/swiotlb.h
> @@ -17,6 +17,7 @@ struct scatterlist;
> #define SWIOTLB_VERBOSE (1 << 0) /* verbose initialization */
> #define SWIOTLB_FORCE (1 << 1) /* force bounce buffering */
> #define SWIOTLB_ANY (1 << 2) /* allow any memory for the buffer */
> +#define SWIOTLB_UNACCEPTED (1 << 3) /* swiotlb for unaccepted devices */
>
> /*
> * Maximum allowable number of contiguous slabs to map,
> @@ -91,6 +92,7 @@ struct io_tlb_pool {
> * @nslabs: Total number of IO TLB slabs in all pools.
> * @debugfs: The dentry to debugfs.
> * @force_bounce: %true if swiotlb bouncing is forced
> + * @bounce_unaccepted: %true if unaccepted devices must bounce
> * @for_alloc: %true if the pool is used for memory allocation
> * @can_grow: %true if more pools can be allocated dynamically.
> * @phys_limit: Maximum allowed physical address.
> @@ -109,8 +111,9 @@ struct io_tlb_mem {
> struct io_tlb_pool defpool;
> unsigned long nslabs;
> struct dentry *debugfs;
> - bool force_bounce;
> - bool for_alloc;
> + u8 force_bounce:1;
> + u8 bounce_unaccepted:1;
> + u8 for_alloc:1;
> #ifdef CONFIG_SWIOTLB_DYNAMIC
> bool can_grow;
> u64 phys_limit;
> @@ -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);
> diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
> index 6267363e0189..8a737f501ae5 100644
> --- a/arch/x86/kernel/pci-dma.c
> +++ b/arch/x86/kernel/pci-dma.c
> @@ -61,7 +61,7 @@ static void __init pci_swiotlb_detect(void)
> */
> if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
> x86_swiotlb_enable = true;
> - x86_swiotlb_flags |= SWIOTLB_FORCE;
> + x86_swiotlb_flags |= SWIOTLB_UNACCEPTED;
> }
> }
> #else
> diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
> index a547c7693135..57e9647939fe 100644
> --- a/kernel/dma/swiotlb.c
> +++ b/kernel/dma/swiotlb.c
> @@ -365,6 +365,7 @@ void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags,
>
> io_tlb_default_mem.force_bounce =
> swiotlb_force_bounce || (flags & SWIOTLB_FORCE);
> + io_tlb_default_mem.bounce_unaccepted = flags & SWIOTLB_UNACCEPTED;
>
This should be.
@@ -373,7 +373,7 @@ void __init swiotlb_init_remap(bool addressing_limit, unsigned int flags,
io_tlb_default_mem.force_bounce =
swiotlb_force_bounce || (flags & SWIOTLB_FORCE);
- io_tlb_default_mem.bounce_unaccepted = flags & SWIOTLB_UNACCEPTED;
+ io_tlb_default_mem.bounce_unaccepted = !!(flags & SWIOTLB_UNACCEPTED);
>
> #ifdef CONFIG_SWIOTLB_DYNAMIC
> if (!remap)
> --
> 2.52.0
^ permalink raw reply
* Re: [PATCH kernel 6/9] x86/dma-direct: Stop changing encrypted page state for TDISP devices
From: Alexey Kardashevskiy @ 2026-03-03 8:19 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Robin Murphy, x86, 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, 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, Jiri Pirko
In-Reply-To: <20260302133527.GV44359@ziepe.ca>
On 3/3/26 00:35, Jason Gunthorpe wrote:
> On Mon, Mar 02, 2026 at 04:26:58PM +1100, Alexey Kardashevskiy wrote:
>
>>>> Without secure vIOMMU, no Cbit in the S2 table (==host) for any
>>>> VM. SDTE (==IOMMU) decides on shared/private for the device,
>>>> i.e. (device_cc_accepted()?private:shared).
"no Cbit" here was "there is Cbit in PTe and it is 0", rather than "Cbit is an address bit".
>>> Is this "Cbit" part of the CPU S2 page table address space or is it
>>> actually some PTE bit that says it is "encrypted" ?
afaik it is always (while SNP is enabled) a PTE bit that says "encrypted".
>>> It is confusing when you say it would start working with a vIOMMU.
>>
>> When I mention vIOMMU, I mean the S1 table which is guest owned and
>> which has Cbit in PTEs.
>
> Yes, I understand this.
>
> It seems from your email that the CPU S2 has the Cbit as part of the
> address and the S1 feeds it through to the S2, so it is genuinely has
> two addres spaces?
S1/S2 PTEs have Cbit. Addresses to look up those PTEs - do not.
(both are "addresses" - one in the PTE and another one - to look up the PTE)
> While the IOMMU S1 does not and instead needs a PTE bit which is
> emphatically not an address bit because it does not feed through the
> S2?
afaik IOMMU works the same.
>>> If 1<<51 is a valid IOPTE, and it is an actually address, then it
>>> should be mapped into the IOMMU S2, shouldn't it? If it is in the
>>> IOMMU S2 then shouldn't it work as a dma_addr_t?
>>
>> It should (and checked with the HW folks), I just have not tried it as, like, whyyy.
>
> Well, I think things work more sensibly if you don't have to mangle
> the address..
>
>>> But in this case I would expect the vIOMMU to also use the same GPA
>>> space starting from 0 and also remove the C bit, as the S2 shouldn't
>>> have mappings starting at 1<<51.
>>
>> How would then IOMMU know if DMA targets private or shared memory?
>> The Cbit does not participate in the S2 translation as an address
>> bit but IOMMU still knows what it is.
>
> Same way it knows if there is no S1?
If no S1 - then sDTE decides on Cbit for the entire ASID (with the help of vTOM).
> Why does the S1 change anything?
S1 will have Cbit in individual PTEs, allowing per page control.
>>>> There is vTOM in SDTE which is "every phys_addr_t above vTOM is no
>>>> Cbit, below - with Cbit" (and there is the same thing for the CPU
>>>> side in SEV) but this not it, right?
>>>
>>> That seems like the IOMMU HW is specially handling the address bits in
>>> some way?
>>
>> Yeah there is this capability. Except everything below vTOM is
>> private and every above is shared so SME mask for it would be
>> reverse than the CPU SME mask :) Not using this thing though (not
>> sure why we have it). Thanks,
>
> Weird!!
:)
I understand I am often confusing, trying to unconfuse (including myself)... Thanks,
--
Alexey
^ permalink raw reply
* Re: [PATCH v2 11/19] x86, dma: Allow accepted devices to map private memory
From: Alexey Kardashevskiy @ 2026-03-03 7:36 UTC (permalink / raw)
To: Dan Williams, linux-coco, linux-pci
Cc: gregkh, aneesh.kumar, yilun.xu, bhelgaas, alistair23, lukas, jgg,
Dave Hansen, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, x86, H. Peter Anvin
In-Reply-To: <20260303000207.1836586-12-dan.j.williams@intel.com>
On 3/3/26 11:01, Dan Williams wrote:
> With the arrival of "accepted" devices, devices that have been enabled to
> DMA to private encrypted memory, coherent DMA allocation no longer requires
> page conversion. Update force_dma_unencrypted() to skip accepted devices.
>
> Cc: Dave Hansen <dave.hansen@linux.intel.com>
> Cc: Andy Lutomirski <luto@kernel.org>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Thomas Gleixner <tglx@kernel.org>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: x86@kernel.org
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-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..6d2972ff6ed8 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.
> + * Require unencrypted DMA unless the device has been "accepted",
> + * enabled by a TSM driver to DMA to private encrypted memory.
> */
> if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
> - return true;
> + return !device_cc_accepted(dev);
>
> /*
> * For SME, all DMA must be to unencrypted addresses if the
--
Alexey
^ permalink raw reply
* Re: [PATCH v2 07/19] PCI/TSM: Add Device Security (TVM Guest) ACCEPT operation support
From: Baolu Lu @ 2026-03-03 7:15 UTC (permalink / raw)
To: Dan Williams, linux-coco, linux-pci
Cc: gregkh, aik, aneesh.kumar, yilun.xu, bhelgaas, alistair23, lukas,
jgg
In-Reply-To: <20260303000207.1836586-8-dan.j.williams@intel.com>
On 3/3/26 08:01, Dan Williams wrote:
> The final operation of the PCIe Trusted Execution Environment (TEE) Device
> Interface Security Protocol (TDISP) is asking the TEE Security Manager
> (TEE) to enable private DMA and MMIO.
>
> The story so far in the security lifecycle of the device is that the VMM
> setup an SPDM session and link encryption with the device's physical
> function0. The VMM then assigned either that physical function or other
> virtual function of that device to a VM. The VM asked the TSM to transition
> the device from TDISP UNLOCKED->LOCKED. With the device LOCKED the VM
> validated signed fresh device evidence and expected MMIO mappings.
>
> The VM now accepts the device to transition it from LOCKED to RUN and tell
> the TSM to unblock DMA to VM private memory.
>
> Implement a sysfs trigger to flip the device to private operation and plumb
> that to a 'struct pci_tsm_ops::accept()' operation.
>
> Co-developed-by: Xu Yilun<yilun.xu@linux.intel.com>
> Signed-off-by: Xu Yilun<yilun.xu@linux.intel.com>
> Co-developed-by: Aneesh Kumar K.V (Arm)<aneesh.kumar@kernel.org>
> Signed-off-by: Aneesh Kumar K.V (Arm)<aneesh.kumar@kernel.org>
> Signed-off-by: Dan Williams<dan.j.williams@intel.com>
> ---
> drivers/pci/Kconfig | 2 +
> Documentation/ABI/testing/sysfs-bus-pci | 13 +++++
> include/linux/pci-tsm.h | 7 ++-
> drivers/pci/tsm.c | 69 ++++++++++++++++++++++++-
> 4 files changed, 88 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
> index e3f848ffb52a..c45c6b978e1d 100644
> --- a/drivers/pci/Kconfig
> +++ b/drivers/pci/Kconfig
> @@ -127,6 +127,8 @@ config PCI_IDE
>
> config PCI_TSM
> bool "PCI TSM: Device security protocol support"
> + depends on ARCH_HAS_CC_PLATFORM
> + select CONFIDENTIAL_DEVICES
> select PCI_IDE
> select PCI_DOE
> select TSM
> diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
> index 1ed77b9402a6..c2a5c4fe9373 100644
> --- a/Documentation/ABI/testing/sysfs-bus-pci
> +++ b/Documentation/ABI/testing/sysfs-bus-pci
> @@ -732,3 +732,16 @@ Description:
> 'lock' to teardown the connection. Writes fail with EBUSY if
> this device is bound to a driver. This is a "devsec" TSM
> attribute, see Documentation/ABI/testing/sysfs-class-tsm.
> +
> +What: /sys/bus/pci/devices/.../tsm/accept
> +Contact: linux-coco@lists.linux.dev
> +Description:
> + (RW) Write "1" (or any boolean "true" string) to this file to
> + request that TSM transition the device from the TDISP LOCKED
> + state to the RUN state and arrange the for the secure IOMMU to
Nit: remove the typo extra 'the'
"...and arrange for the secure IOMMU to..."
> + accept requests with T=1 in the PCIe packet header (TLP)
> + targeting private memory. Per TDISP the only exits from the RUN
> + state are via an explicit unlock request or an event that
> + transitions the device to the ERROR state. Writes fail with
> + EBUSY if this device is bound to a driver. This is a "devsec"
> + TSM attribute, see Documentation/ABI/testing/sysfs-class-tsm.
Thanks,
baolu
^ permalink raw reply
* [PATCH v4 4/4] KVM: TDX: Rename KVM_SUPPORTED_TD_ATTRS to KVM_SUPPORTED_TDX_TD_ATTRS
From: Xiaoyao Li @ 2026-03-03 3:03 UTC (permalink / raw)
To: Dave Hansen, Kiryl Shutsemau, Sean Christopherson, Paolo Bonzini
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
linux-coco, kvm, linux-kernel, x86, Rick Edgecombe, Kai Huang,
binbin.wu, Tony Lindgren, xiaoyao.li
In-Reply-To: <20260303030335.766779-1-xiaoyao.li@intel.com>
Rename KVM_SUPPORTED_TD_ATTRS to KVM_SUPPORTED_TDX_TD_ATTRS to include
"TDX" in the name, making it clear that it pertains to TDX.
Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
Reviewed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Reviewed-by: Kiryl Shutsemau <kas@kernel.org>
Acked-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/vmx/tdx.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index c5065f84b78b..eaeda1cfb227 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -75,7 +75,7 @@ void tdh_vp_wr_failed(struct vcpu_tdx *tdx, char *uclass, char *op, u32 field,
pr_err("TDH_VP_WR[%s.0x%x]%s0x%llx failed: 0x%llx\n", uclass, field, op, val, err);
}
-#define KVM_SUPPORTED_TD_ATTRS (TDX_TD_ATTR_SEPT_VE_DISABLE)
+#define KVM_SUPPORTED_TDX_TD_ATTRS (TDX_TD_ATTR_SEPT_VE_DISABLE)
static __always_inline struct kvm_tdx *to_kvm_tdx(struct kvm *kvm)
{
@@ -89,7 +89,7 @@ static __always_inline struct vcpu_tdx *to_tdx(struct kvm_vcpu *vcpu)
static u64 tdx_get_supported_attrs(const struct tdx_sys_info_td_conf *td_conf)
{
- u64 val = KVM_SUPPORTED_TD_ATTRS;
+ u64 val = KVM_SUPPORTED_TDX_TD_ATTRS;
if ((val & td_conf->attributes_fixed1) != td_conf->attributes_fixed1)
return 0;
--
2.43.0
^ permalink raw reply related
* [PATCH v4 3/4] x86/tdx: Rename TDX_ATTR_* to TDX_TD_ATTR_*
From: Xiaoyao Li @ 2026-03-03 3:03 UTC (permalink / raw)
To: Dave Hansen, Kiryl Shutsemau, Sean Christopherson, Paolo Bonzini
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
linux-coco, kvm, linux-kernel, x86, Rick Edgecombe, Kai Huang,
binbin.wu, Tony Lindgren, xiaoyao.li
In-Reply-To: <20260303030335.766779-1-xiaoyao.li@intel.com>
The macros TDX_ATTR_* and DEF_TDX_ATTR_* are related to TD attributes,
which are TD-scope attributes. Naming them as TDX_ATTR_* can be somewhat
confusing and might mislead people into thinking they are TDX global
things.
Rename TDX_ATTR_* to TDX_TD_ATTR_* to explicitly clarify they are
TD-scope things.
Suggested-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
Reviewed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
Reviewed-by: Kiryl Shutsemau <kas@kernel.org>
Acked-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/coco/tdx/debug.c | 26 ++++++++--------
arch/x86/coco/tdx/tdx.c | 8 ++---
arch/x86/include/asm/shared/tdx.h | 50 +++++++++++++++----------------
arch/x86/kvm/vmx/tdx.c | 4 +--
4 files changed, 44 insertions(+), 44 deletions(-)
diff --git a/arch/x86/coco/tdx/debug.c b/arch/x86/coco/tdx/debug.c
index 28990c2ab0a1..8e477db4ce0a 100644
--- a/arch/x86/coco/tdx/debug.c
+++ b/arch/x86/coco/tdx/debug.c
@@ -7,21 +7,21 @@
#include <linux/printk.h>
#include <asm/tdx.h>
-#define DEF_TDX_ATTR_NAME(_name) [TDX_ATTR_##_name##_BIT] = __stringify(_name)
+#define DEF_TDX_TD_ATTR_NAME(_name) [TDX_TD_ATTR_##_name##_BIT] = __stringify(_name)
static __initdata const char *tdx_attributes[] = {
- DEF_TDX_ATTR_NAME(DEBUG),
- DEF_TDX_ATTR_NAME(HGS_PLUS_PROF),
- DEF_TDX_ATTR_NAME(PERF_PROF),
- DEF_TDX_ATTR_NAME(PMT_PROF),
- DEF_TDX_ATTR_NAME(ICSSD),
- DEF_TDX_ATTR_NAME(LASS),
- DEF_TDX_ATTR_NAME(SEPT_VE_DISABLE),
- DEF_TDX_ATTR_NAME(MIGRATABLE),
- DEF_TDX_ATTR_NAME(PKS),
- DEF_TDX_ATTR_NAME(KL),
- DEF_TDX_ATTR_NAME(TPA),
- DEF_TDX_ATTR_NAME(PERFMON),
+ DEF_TDX_TD_ATTR_NAME(DEBUG),
+ DEF_TDX_TD_ATTR_NAME(HGS_PLUS_PROF),
+ DEF_TDX_TD_ATTR_NAME(PERF_PROF),
+ DEF_TDX_TD_ATTR_NAME(PMT_PROF),
+ DEF_TDX_TD_ATTR_NAME(ICSSD),
+ DEF_TDX_TD_ATTR_NAME(LASS),
+ DEF_TDX_TD_ATTR_NAME(SEPT_VE_DISABLE),
+ DEF_TDX_TD_ATTR_NAME(MIGRATABLE),
+ DEF_TDX_TD_ATTR_NAME(PKS),
+ DEF_TDX_TD_ATTR_NAME(KL),
+ DEF_TDX_TD_ATTR_NAME(TPA),
+ DEF_TDX_TD_ATTR_NAME(PERFMON),
};
#define DEF_TD_CTLS_NAME(_name) [TD_CTLS_##_name##_BIT] = __stringify(_name)
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index 7b2833705d47..186915a17c50 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -238,14 +238,14 @@ static void __noreturn tdx_panic(const char *msg)
*
* TDX 1.0 does not allow the guest to disable SEPT #VE on its own. The VMM
* controls if the guest will receive such #VE with TD attribute
- * TDX_ATTR_SEPT_VE_DISABLE.
+ * TDX_TD_ATTR_SEPT_VE_DISABLE.
*
* Newer TDX modules allow the guest to control if it wants to receive SEPT
* violation #VEs.
*
* Check if the feature is available and disable SEPT #VE if possible.
*
- * If the TD is allowed to disable/enable SEPT #VEs, the TDX_ATTR_SEPT_VE_DISABLE
+ * If the TD is allowed to disable/enable SEPT #VEs, the TDX_TD_ATTR_SEPT_VE_DISABLE
* attribute is no longer reliable. It reflects the initial state of the
* control for the TD, but it will not be updated if someone (e.g. bootloader)
* changes it before the kernel starts. Kernel must check TDCS_TD_CTLS bit to
@@ -254,14 +254,14 @@ static void __noreturn tdx_panic(const char *msg)
static void disable_sept_ve(u64 td_attr)
{
const char *msg = "TD misconfiguration: SEPT #VE has to be disabled";
- bool debug = td_attr & TDX_ATTR_DEBUG;
+ bool debug = td_attr & TDX_TD_ATTR_DEBUG;
u64 config, controls;
/* Is this TD allowed to disable SEPT #VE */
tdg_vm_rd(TDCS_CONFIG_FLAGS, &config);
if (!(config & TDCS_CONFIG_FLEXIBLE_PENDING_VE)) {
/* No SEPT #VE controls for the guest: check the attribute */
- if (td_attr & TDX_ATTR_SEPT_VE_DISABLE)
+ if (td_attr & TDX_TD_ATTR_SEPT_VE_DISABLE)
return;
/* Relax SEPT_VE_DISABLE check for debug TD for backtraces */
diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h
index 11f3cf30b1ac..049638e3da74 100644
--- a/arch/x86/include/asm/shared/tdx.h
+++ b/arch/x86/include/asm/shared/tdx.h
@@ -20,31 +20,31 @@
#define TDG_VM_RD 7
#define TDG_VM_WR 8
-/* TDX attributes */
-#define TDX_ATTR_DEBUG_BIT 0
-#define TDX_ATTR_DEBUG BIT_ULL(TDX_ATTR_DEBUG_BIT)
-#define TDX_ATTR_HGS_PLUS_PROF_BIT 4
-#define TDX_ATTR_HGS_PLUS_PROF BIT_ULL(TDX_ATTR_HGS_PLUS_PROF_BIT)
-#define TDX_ATTR_PERF_PROF_BIT 5
-#define TDX_ATTR_PERF_PROF BIT_ULL(TDX_ATTR_PERF_PROF_BIT)
-#define TDX_ATTR_PMT_PROF_BIT 6
-#define TDX_ATTR_PMT_PROF BIT_ULL(TDX_ATTR_PMT_PROF_BIT)
-#define TDX_ATTR_ICSSD_BIT 16
-#define TDX_ATTR_ICSSD BIT_ULL(TDX_ATTR_ICSSD_BIT)
-#define TDX_ATTR_LASS_BIT 27
-#define TDX_ATTR_LASS BIT_ULL(TDX_ATTR_LASS_BIT)
-#define TDX_ATTR_SEPT_VE_DISABLE_BIT 28
-#define TDX_ATTR_SEPT_VE_DISABLE BIT_ULL(TDX_ATTR_SEPT_VE_DISABLE_BIT)
-#define TDX_ATTR_MIGRATABLE_BIT 29
-#define TDX_ATTR_MIGRATABLE BIT_ULL(TDX_ATTR_MIGRATABLE_BIT)
-#define TDX_ATTR_PKS_BIT 30
-#define TDX_ATTR_PKS BIT_ULL(TDX_ATTR_PKS_BIT)
-#define TDX_ATTR_KL_BIT 31
-#define TDX_ATTR_KL BIT_ULL(TDX_ATTR_KL_BIT)
-#define TDX_ATTR_TPA_BIT 62
-#define TDX_ATTR_TPA BIT_ULL(TDX_ATTR_TPA_BIT)
-#define TDX_ATTR_PERFMON_BIT 63
-#define TDX_ATTR_PERFMON BIT_ULL(TDX_ATTR_PERFMON_BIT)
+/* TDX TD attributes */
+#define TDX_TD_ATTR_DEBUG_BIT 0
+#define TDX_TD_ATTR_DEBUG BIT_ULL(TDX_TD_ATTR_DEBUG_BIT)
+#define TDX_TD_ATTR_HGS_PLUS_PROF_BIT 4
+#define TDX_TD_ATTR_HGS_PLUS_PROF BIT_ULL(TDX_TD_ATTR_HGS_PLUS_PROF_BIT)
+#define TDX_TD_ATTR_PERF_PROF_BIT 5
+#define TDX_TD_ATTR_PERF_PROF BIT_ULL(TDX_TD_ATTR_PERF_PROF_BIT)
+#define TDX_TD_ATTR_PMT_PROF_BIT 6
+#define TDX_TD_ATTR_PMT_PROF BIT_ULL(TDX_TD_ATTR_PMT_PROF_BIT)
+#define TDX_TD_ATTR_ICSSD_BIT 16
+#define TDX_TD_ATTR_ICSSD BIT_ULL(TDX_TD_ATTR_ICSSD_BIT)
+#define TDX_TD_ATTR_LASS_BIT 27
+#define TDX_TD_ATTR_LASS BIT_ULL(TDX_TD_ATTR_LASS_BIT)
+#define TDX_TD_ATTR_SEPT_VE_DISABLE_BIT 28
+#define TDX_TD_ATTR_SEPT_VE_DISABLE BIT_ULL(TDX_TD_ATTR_SEPT_VE_DISABLE_BIT)
+#define TDX_TD_ATTR_MIGRATABLE_BIT 29
+#define TDX_TD_ATTR_MIGRATABLE BIT_ULL(TDX_TD_ATTR_MIGRATABLE_BIT)
+#define TDX_TD_ATTR_PKS_BIT 30
+#define TDX_TD_ATTR_PKS BIT_ULL(TDX_TD_ATTR_PKS_BIT)
+#define TDX_TD_ATTR_KL_BIT 31
+#define TDX_TD_ATTR_KL BIT_ULL(TDX_TD_ATTR_KL_BIT)
+#define TDX_TD_ATTR_TPA_BIT 62
+#define TDX_TD_ATTR_TPA BIT_ULL(TDX_TD_ATTR_TPA_BIT)
+#define TDX_TD_ATTR_PERFMON_BIT 63
+#define TDX_TD_ATTR_PERFMON BIT_ULL(TDX_TD_ATTR_PERFMON_BIT)
/* TDX TD-Scope Metadata. To be used by TDG.VM.WR and TDG.VM.RD */
#define TDCS_CONFIG_FLAGS 0x1110000300000016
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index f38e492fb3d5..c5065f84b78b 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -75,7 +75,7 @@ void tdh_vp_wr_failed(struct vcpu_tdx *tdx, char *uclass, char *op, u32 field,
pr_err("TDH_VP_WR[%s.0x%x]%s0x%llx failed: 0x%llx\n", uclass, field, op, val, err);
}
-#define KVM_SUPPORTED_TD_ATTRS (TDX_ATTR_SEPT_VE_DISABLE)
+#define KVM_SUPPORTED_TD_ATTRS (TDX_TD_ATTR_SEPT_VE_DISABLE)
static __always_inline struct kvm_tdx *to_kvm_tdx(struct kvm *kvm)
{
@@ -707,7 +707,7 @@ int tdx_vcpu_create(struct kvm_vcpu *vcpu)
vcpu->arch.l1_tsc_scaling_ratio = kvm_tdx->tsc_multiplier;
vcpu->arch.guest_state_protected =
- !(to_kvm_tdx(vcpu->kvm)->attributes & TDX_ATTR_DEBUG);
+ !(to_kvm_tdx(vcpu->kvm)->attributes & TDX_TD_ATTR_DEBUG);
if ((kvm_tdx->xfam & XFEATURE_MASK_XTILE) == XFEATURE_MASK_XTILE)
vcpu->arch.xfd_no_write_intercept = true;
--
2.43.0
^ permalink raw reply related
* [PATCH v4 2/4] KVM: TDX: Remove redundant definitions of TDX_TD_ATTR_*
From: Xiaoyao Li @ 2026-03-03 3:03 UTC (permalink / raw)
To: Dave Hansen, Kiryl Shutsemau, Sean Christopherson, Paolo Bonzini
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
linux-coco, kvm, linux-kernel, x86, Rick Edgecombe, Kai Huang,
binbin.wu, Tony Lindgren, xiaoyao.li
In-Reply-To: <20260303030335.766779-1-xiaoyao.li@intel.com>
There are definitions of TD attributes bits inside asm/shared/tdx.h as
TDX_ATTR_*.
Remove KVM's definitions and use the ones in asm/shared/tdx.h
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
Reviewed-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Reviewed-by: Kai Huang <kai.huang@intel.com>
Reviewed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Acked-by: Sean Christopherson <seanjc@google.com>
---
arch/x86/kvm/vmx/tdx.c | 4 ++--
arch/x86/kvm/vmx/tdx_arch.h | 6 ------
2 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index c5065f84b78b..f38e492fb3d5 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -75,7 +75,7 @@ void tdh_vp_wr_failed(struct vcpu_tdx *tdx, char *uclass, char *op, u32 field,
pr_err("TDH_VP_WR[%s.0x%x]%s0x%llx failed: 0x%llx\n", uclass, field, op, val, err);
}
-#define KVM_SUPPORTED_TD_ATTRS (TDX_TD_ATTR_SEPT_VE_DISABLE)
+#define KVM_SUPPORTED_TD_ATTRS (TDX_ATTR_SEPT_VE_DISABLE)
static __always_inline struct kvm_tdx *to_kvm_tdx(struct kvm *kvm)
{
@@ -707,7 +707,7 @@ int tdx_vcpu_create(struct kvm_vcpu *vcpu)
vcpu->arch.l1_tsc_scaling_ratio = kvm_tdx->tsc_multiplier;
vcpu->arch.guest_state_protected =
- !(to_kvm_tdx(vcpu->kvm)->attributes & TDX_TD_ATTR_DEBUG);
+ !(to_kvm_tdx(vcpu->kvm)->attributes & TDX_ATTR_DEBUG);
if ((kvm_tdx->xfam & XFEATURE_MASK_XTILE) == XFEATURE_MASK_XTILE)
vcpu->arch.xfd_no_write_intercept = true;
diff --git a/arch/x86/kvm/vmx/tdx_arch.h b/arch/x86/kvm/vmx/tdx_arch.h
index a30e880849e3..350143b9b145 100644
--- a/arch/x86/kvm/vmx/tdx_arch.h
+++ b/arch/x86/kvm/vmx/tdx_arch.h
@@ -75,12 +75,6 @@ struct tdx_cpuid_value {
u32 edx;
} __packed;
-#define TDX_TD_ATTR_DEBUG BIT_ULL(0)
-#define TDX_TD_ATTR_SEPT_VE_DISABLE BIT_ULL(28)
-#define TDX_TD_ATTR_PKS BIT_ULL(30)
-#define TDX_TD_ATTR_KL BIT_ULL(31)
-#define TDX_TD_ATTR_PERFMON BIT_ULL(63)
-
#define TDX_EXT_EXIT_QUAL_TYPE_MASK GENMASK(3, 0)
#define TDX_EXT_EXIT_QUAL_TYPE_PENDING_EPT_VIOLATION 6
/*
--
2.43.0
^ permalink raw reply related
* [PATCH v4 1/4] x86/tdx: Fix the typo in TDX_ATTR_MIGRTABLE
From: Xiaoyao Li @ 2026-03-03 3:03 UTC (permalink / raw)
To: Dave Hansen, Kiryl Shutsemau, Sean Christopherson, Paolo Bonzini
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
linux-coco, kvm, linux-kernel, x86, Rick Edgecombe, Kai Huang,
binbin.wu, Tony Lindgren, xiaoyao.li
In-Reply-To: <20260303030335.766779-1-xiaoyao.li@intel.com>
The TD scoped TDCS attributes are defined by bit positions. In the guest
side of the TDX code, the 'tdx_attributes' string array holds pretty
print names for these attributes, which are generated via macros and
defines. Today these pretty print names are only used to print the
attribute names to dmesg.
Unfortunately there is a typo in the define for the migratable bit.
Change the defines TDX_ATTR_MIGRTABLE* to TDX_ATTR_MIGRATABLE*. Update
the sole user, the tdx_attributes array, to use the fixed name.
Since these defines control the string printed to dmesg, the change is
user visible. But the risk of breakage is almost zero since it is not
exposed in any interface expected to be consumed programmatically.
Fixes: 564ea84c8c14 ("x86/tdx: Dump attributes and TD_CTLS on boot")
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
Reviewed-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Reviewed-by: Kai Huang <kai.huang@intel.com>
Acked-by: Sean Christopherson <seanjc@google.com>
---
Changes in v3:
- Use the rewritten changelog from Rick.
Changes in v2:
- Add the impact of the change in the commit message. (provided by Rick)
---
arch/x86/coco/tdx/debug.c | 2 +-
arch/x86/include/asm/shared/tdx.h | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/x86/coco/tdx/debug.c b/arch/x86/coco/tdx/debug.c
index cef847c8bb67..28990c2ab0a1 100644
--- a/arch/x86/coco/tdx/debug.c
+++ b/arch/x86/coco/tdx/debug.c
@@ -17,7 +17,7 @@ static __initdata const char *tdx_attributes[] = {
DEF_TDX_ATTR_NAME(ICSSD),
DEF_TDX_ATTR_NAME(LASS),
DEF_TDX_ATTR_NAME(SEPT_VE_DISABLE),
- DEF_TDX_ATTR_NAME(MIGRTABLE),
+ DEF_TDX_ATTR_NAME(MIGRATABLE),
DEF_TDX_ATTR_NAME(PKS),
DEF_TDX_ATTR_NAME(KL),
DEF_TDX_ATTR_NAME(TPA),
diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h
index 8bc074c8d7c6..11f3cf30b1ac 100644
--- a/arch/x86/include/asm/shared/tdx.h
+++ b/arch/x86/include/asm/shared/tdx.h
@@ -35,8 +35,8 @@
#define TDX_ATTR_LASS BIT_ULL(TDX_ATTR_LASS_BIT)
#define TDX_ATTR_SEPT_VE_DISABLE_BIT 28
#define TDX_ATTR_SEPT_VE_DISABLE BIT_ULL(TDX_ATTR_SEPT_VE_DISABLE_BIT)
-#define TDX_ATTR_MIGRTABLE_BIT 29
-#define TDX_ATTR_MIGRTABLE BIT_ULL(TDX_ATTR_MIGRTABLE_BIT)
+#define TDX_ATTR_MIGRATABLE_BIT 29
+#define TDX_ATTR_MIGRATABLE BIT_ULL(TDX_ATTR_MIGRATABLE_BIT)
#define TDX_ATTR_PKS_BIT 30
#define TDX_ATTR_PKS BIT_ULL(TDX_ATTR_PKS_BIT)
#define TDX_ATTR_KL_BIT 31
--
2.43.0
^ permalink raw reply related
* [PATCH v4 0/4] x86/tdx: Clean up the definitions of TDX TD ATTRIBUTES
From: Xiaoyao Li @ 2026-03-03 3:03 UTC (permalink / raw)
To: Dave Hansen, Kiryl Shutsemau, Sean Christopherson, Paolo Bonzini
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
linux-coco, kvm, linux-kernel, x86, Rick Edgecombe, Kai Huang,
binbin.wu, Tony Lindgren, xiaoyao.li
The main purpose of this series was to remove redundant macros between
core TDX and KVM, along with a typo fix. They were implemented as patch 1
and patch 2.
During the review of v1 and v2, there was encouragement to refine the
names of the macros related to TD attributes to clarify their scope.
Thus patch 3 and patch 4 are added.
Note, Binbin suggested to rename tdx_attributes[] to tdx_td_attributes[]
during v3 review. However, this v4 doesn't do it but leaves it for future
cleanup to avoid making it more complicated because it also looks like
it needs to rename "Attributes" to "TD Attributes" in tdx_dump_attributes(),
which has user visibility change.
Changes in v4:
- Collect Reviewed-by and Acked-by tags;
- rebase to v7.0-rc1;
v3: https://lore.kernel.org/kvm/20250715091312.563773-1-xiaoyao.li@intel.com/
Changes in v3:
- use the changelog provided by Rick for patch 1;
- collect Reviewed-by on patch 4;
- Add patch 3;
v2: https://lore.kernel.org/all/20250711132620.262334-1-xiaoyao.li@intel.com/
Changes in v2:
- collect Reviewed-by;
- Explains the impact of the change in patch 1 changelog;
- Add patch 3.
v1: https://lore.kernel.org/all/20250708080314.43081-1-xiaoyao.li@intel.com/
Xiaoyao Li (4):
x86/tdx: Fix the typo in TDX_ATTR_MIGRTABLE
KVM: TDX: Remove redundant definitions of TDX_TD_ATTR_*
x86/tdx: Rename TDX_ATTR_* to TDX_TD_ATTR_*
KVM: TDX: Rename KVM_SUPPORTED_TD_ATTRS to KVM_SUPPORTED_TDX_TD_ATTRS
arch/x86/coco/tdx/debug.c | 26 ++++++++--------
arch/x86/coco/tdx/tdx.c | 8 ++---
arch/x86/include/asm/shared/tdx.h | 50 +++++++++++++++----------------
arch/x86/kvm/vmx/tdx.c | 4 +--
arch/x86/kvm/vmx/tdx_arch.h | 6 ----
5 files changed, 44 insertions(+), 50 deletions(-)
base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
--
2.43.0
^ permalink raw reply
* Re: [PATCH v2 08/19] PCI/TSM: Add "evidence" support
From: kernel test robot @ 2026-03-03 3:14 UTC (permalink / raw)
To: Dan Williams, linux-coco, linux-pci
Cc: oe-kbuild-all, gregkh, aik, aneesh.kumar, yilun.xu, bhelgaas,
alistair23, lukas, jgg, Donald Hunter, Jakub Kicinski
In-Reply-To: <20260303000207.1836586-9-dan.j.williams@intel.com>
Hi Dan,
kernel test robot noticed the following build warnings:
[auto build test WARNING on c2012263047689e495e81c96d7d5b0586299578d]
url: https://github.com/intel-lab-lkp/linux/commits/Dan-Williams/PCI-TSM-Report-active-IDE-streams-per-host-bridge/20260303-080409
base: c2012263047689e495e81c96d7d5b0586299578d
patch link: https://lore.kernel.org/r/20260303000207.1836586-9-dan.j.williams%40intel.com
patch subject: [PATCH v2 08/19] PCI/TSM: Add "evidence" support
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
docutils: docutils (Docutils 0.21.2, Python 3.13.5, on linux)
reproduce: (https://download.01.org/0day-ci/archive/20260303/202603030451.0ZpbO6ex-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603030451.0ZpbO6ex-lkp@intel.com/
All warnings (new ones prefixed by >>):
Warning: tools/docs/documentation-file-ref-check references a file that doesn't exist: m,^Documentation/scheduler/sched-pelt
Warning: tools/docs/documentation-file-ref-check references a file that doesn't exist: m,(Documentation/translations/[
Using alabaster theme
WARNING: ./include/crypto/skcipher.h:166 struct member 'SKCIPHER_ALG_COMMON' not described in 'skcipher_alg'
Documentation/driver-api/pci/tsm:147: ./include/linux/pci-tsm.h:112: ERROR: Unexpected indentation. [docutils]
>> Documentation/driver-api/pci/tsm:147: ./include/linux/pci-tsm.h:113: WARNING: Block quote ends without a blank line; unexpected unindent. [docutils]
>> Documentation/driver-api/pci/tsm:147: ./include/linux/pci-tsm.h:116: WARNING: Definition list ends without a blank line; unexpected unindent. [docutils]
ERROR: Cannot find file ./drivers/pci/tsm.c
ERROR: Cannot find file ./drivers/pci/tsm.c
WARNING: No kernel-doc for file ./drivers/pci/tsm.c
WARNING: ./include/linux/virtio.h:183 struct member 'map' not described in 'virtio_device'
WARNING: ./include/linux/virtio.h:183 struct member 'VIRTIO_DECLARE_FEATURES(features' not described in 'virtio_device'
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH 14/14] KVM: x86: Add helpers to prepare kvm_run for userspace MMIO exit
From: Sean Christopherson @ 2026-03-03 2:24 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: <aZ9MDxJ1iEhIbJJ6@google.com>
On Wed, Feb 25, 2026, Sean Christopherson wrote:
> 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).
Ooh, better idea. Since TDX is the only direct user of
__kvm_prepare_emulated_mmio_exit() and it only supports lenths of 1, 2, 4, and 8,
kvm_prepare_emulated_mmio_exit() is the only path that actually needs to cap the
length. Then the inner helper can assert a valid length. Doesn't change anything
in practice, but I like the idea of making the caller be aware of the limitation
(even if that caller is itself a helper).
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;
KVM_BUG_ON(len > 8, vcpu->kvm);
run->mmio.len = len;
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, len);
}
static inline void kvm_prepare_emulated_mmio_exit(struct kvm_vcpu *vcpu,
struct kvm_mmio_fragment *frag)
{
WARN_ON_ONCE(!vcpu->mmio_needed || !vcpu->mmio_nr_fragments);
__kvm_prepare_emulated_mmio_exit(vcpu, frag->gpa, min(8u, frag->len),
frag->data, vcpu->mmio_is_write);
}
^ permalink raw reply
* Re: [PATCH kernel 4/9] dma/swiotlb: Stop forcing SWIOTLB for TDISP devices
From: dan.j.williams @ 2026-03-03 0:29 UTC (permalink / raw)
To: Jason Gunthorpe, dan.j.williams
Cc: Robin Murphy, Alexey Kardashevskiy, x86, 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: <20260303001911.GA964116@ziepe.ca>
Jason Gunthorpe wrote:
[..]
> > I have a v2 of a TEE I/O set going out shortly and sounds like it will
> > need a rethink for this attribute proposal for v3. I think it still helps to
> > have combo sets at this stage so the whole lifecycle is visible in one
> > set, but it is nearly at the point of being too big a set to consider in
> > one sitting.
>
> My problem is I can't get in one place an actually correct picture of
> how the IOVA translation works in all the arches and how the
> phys_addr_t works.
>
> So it is hard to make sense of all these proposals. What I would love
> to see is one series that deals with this:
>
> [PATCH v2 11/19] x86, dma: Allow accepted devices to map private memory
>
> For *all* the arches, along with a description for each of:
> * how their phys_addr_t is constructed
> * how their S2 IOMMU mapping works
> * how a vIOMMU S1 would change any of the above.
>
> Then maybe we can see if we are actually doing it properly or not.
Yes, this is my struggle as well. I will put this on the agenda for the
next CCC call.
[..]
>
> I'm surprised because Xu said:
>
> This is same as Intel TDX, the GPA shared bit are used by IOMMU to
> target shared/private. You can imagine for T=1, there are 2 IOPTs, or
> 1 IOPT with all private at lower address & all shared at higher address.
>
> https://lore.kernel.org/all/aaF6HD2gfe%2Fudl%2Fx@yilunxu-OptiPlex-7050/
>
> So how come that not have exactly the same problem as ARM?
Sorry, yes TDX has same behavior as ARM, excuse the noise.
^ permalink raw reply
* Re: [PATCH kernel 4/9] dma/swiotlb: Stop forcing SWIOTLB for TDISP devices
From: Jason Gunthorpe @ 2026-03-03 0:19 UTC (permalink / raw)
To: dan.j.williams
Cc: Robin Murphy, Alexey Kardashevskiy, x86, 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: <69a622e92cccf_6423c10092@dwillia2-mobl4.notmuch>
On Mon, Mar 02, 2026 at 03:53:13PM -0800, dan.j.williams@intel.com wrote:
> > > 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.
> >
> > Yes, the underlying translation changes, but no, it doesn't loose DMA
> > access to any shared pages, it just goes through the T=1 IOMMU now.
>
> Yes, what I meant to say is that Linux may need to be prepared for
> implementations that do not copy over the shared mappings. At least for
> early staging / minimum viable implementation for first merge.
>
> > The T=1 IOMMU will still have them mapped on all three platforms
> > AFAIK.
>
> Oh, I thought SEV-TIO had trouble with this, if this is indeed the case,
> great, ignore my first comment.
Alexey?
I think it is really important that shared mappings continue to be
reachable by TDISP device.
> I have a v2 of a TEE I/O set going out shortly and sounds like it will
> need a rethink for this attribute proposal for v3. I think it still helps to
> have combo sets at this stage so the whole lifecycle is visible in one
> set, but it is nearly at the point of being too big a set to consider in
> one sitting.
My problem is I can't get in one place an actually correct picture of
how the IOVA translation works in all the arches and how the
phys_addr_t works.
So it is hard to make sense of all these proposals. What I would love
to see is one series that deals with this:
[PATCH v2 11/19] x86, dma: Allow accepted devices to map private memory
For *all* the arches, along with a description for each of:
* how their phys_addr_t is constructed
* how their S2 IOMMU mapping works
* how a vIOMMU S1 would change any of the above.
Then maybe we can see if we are actually doing it properly or not.
> > ARM has a "solution" right now. The location of the high bit is
> > controlled by the VMM and the VMM cannot create a CC VM where the IPA
> > space exceeds the dma_mask of any assigned device.
> >
> > Thus the VMM must limit the total available DRAM to fit within the HW
> > restrictions.
> >
> > Hopefully TDX can do the same.
>
> TDX does not have the same problem, but the ARM "solution" seems
> reasonable for now.
I'm surprised because Xu said:
This is same as Intel TDX, the GPA shared bit are used by IOMMU to
target shared/private. You can imagine for T=1, there are 2 IOPTs, or
1 IOPT with all private at lower address & all shared at higher address.
https://lore.kernel.org/all/aaF6HD2gfe%2Fudl%2Fx@yilunxu-OptiPlex-7050/
So how come that not have exactly the same problem as ARM?
Jason
^ permalink raw reply
* [PATCH v2 19/19] tools/testing/devsec: Add basic evidence retrieval validation
From: Dan Williams @ 2026-03-03 0:02 UTC (permalink / raw)
To: linux-coco, linux-pci
Cc: gregkh, aik, aneesh.kumar, yilun.xu, bhelgaas, alistair23, lukas,
jgg
In-Reply-To: <20260303000207.1836586-1-dan.j.williams@intel.com>
Checkout basic operation of the pci-tsm-netlink ABI. The main complexity is
reassembly of single evidence payloads that span multiple messages.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
tools/testing/devsec/devsec.sh | 46 ++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/tools/testing/devsec/devsec.sh b/tools/testing/devsec/devsec.sh
index ce4a986b74dd..6a9313e7104f 100755
--- a/tools/testing/devsec/devsec.sh
+++ b/tools/testing/devsec/devsec.sh
@@ -126,6 +126,46 @@ ide_multi_test() {
done
}
+check_evidence() {
+ pci_dev=$1
+
+ set +x
+
+ python3 tools/net/ynl/pyynl/cli.py --family pci-tsm --dump evidence-read \
+ --json "{\"type-mask\": 2047, \"dev-name\": \"$(basename $pci_dev)\", \"flags\": 0}" \
+ --output-json > json
+
+ # Coalesce multi-message payloads where the protocol is a tuple
+ # of (type, val) followed by one more (val) only messages.
+ objects=()
+ for obj in $(jq -c '.[]' json); do
+ if [[ $(echo $obj | jq -r 'has("type")') == "true" ]]; then
+ t=$(echo $obj | jq -r '.type')
+ val_len=$(echo $obj | jq -r '.val | length')
+ objects[$t]=$val_len
+ else
+ val_len=$(echo $obj | jq -r '.val | length')
+ objects[$t]=$((objects[$t] + val_len))
+ fi
+ done
+
+ # Check that all 11 objects (PCI_TSM_EVIDENCE_TYPE_MAX) were
+ # returned and only objects 0 and 9
+ # (PCI_TSM_EVIDENCE_TYPE_CERT0,
+ # PCI_TSM_EVIDENCE_TYPE_MEASUREMENTS) have a length of 8192 and
+ # the rest are empty.
+ [[ ${#objects[@]} -eq 11 ]] || err "$LINENO"
+ for i in ${!objects[@]}; do
+ if [[ $i == 0 || $i == 9 ]]; then
+ [[ ${objects[$i]} == 8192 ]] || err "$LINENO"
+ else
+ [[ ${objects[$i]} == 0 ]] || err "$LINENO"
+ fi
+ done
+
+ set -x
+}
+
ide_test() {
pci_dev=${PCI_DEVS[$1]}
fn_dev=${FN_DEVS[$1]}
@@ -155,6 +195,8 @@ ide_test() {
dsm=$(cat $fn_dev/tsm/dsm)
[[ $dsm == $(basename $pci_dev) ]] || err "$LINENO"
+ check_evidence $pci_dev
+
# bind both functions and validate that they display bound to
# the TSM device
echo $(basename $pci_dev) > $tsm_link/device/tsm_bind
@@ -213,6 +255,10 @@ devsec_test() {
[[ -n $tsm_devsec ]] || err "$LINENO"
[[ -n $tsm_link ]] || err "$LINENO"
+ # initialize evidence payloads
+ dd if=/dev/zero of=/sys/bus/faux/devices/devsec_link_tsm/certs bs=4K count=1
+ dd if=/dev/zero of=/sys/bus/faux/devices/devsec_link_tsm/transcript bs=4K count=1
+
# check that devsec bus loads correctly and the TSM is detected
for i in ${!PCI_DEVS[@]}; do
pci_dev=${PCI_DEVS[$i]}
--
2.52.0
^ permalink raw reply related
* [PATCH v2 18/19] samples/devsec: Add evidence support
From: Dan Williams @ 2026-03-03 0:02 UTC (permalink / raw)
To: linux-coco, linux-pci
Cc: gregkh, aik, aneesh.kumar, yilun.xu, bhelgaas, alistair23, lukas,
jgg
In-Reply-To: <20260303000207.1836586-1-dan.j.williams@intel.com>
For testing purposes add "certs" and "transcript" attributes to the devsec
faux devices. Both the link_tsm and devsec_tsm reference the same shared
data. The flow is:
- generate cert chain
- sign simulated evidence
- write blobs to "certs" and "transcript"
- trigger tsm/connect or tsm/lock to consume that evidence
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
samples/devsec/devsec.h | 5 ++
samples/devsec/common.c | 134 +++++++++++++++++++++++++++++++++++++-
samples/devsec/link_tsm.c | 21 +++++-
samples/devsec/tsm.c | 9 ++-
4 files changed, 166 insertions(+), 3 deletions(-)
diff --git a/samples/devsec/devsec.h b/samples/devsec/devsec.h
index e0ea9c6bb5e9..a89ce587cb3b 100644
--- a/samples/devsec/devsec.h
+++ b/samples/devsec/devsec.h
@@ -40,4 +40,9 @@ static inline int devsec_get_domain_nr(struct devsec_sysdata *sd)
}
#endif
extern struct devsec_sysdata *devsec_sysdata[NR_DEVSEC_HOST_BRIDGES];
+extern const struct attribute_group devsec_evidence_group;
+void devsec_evidence_busy(void);
+void devsec_evidence_idle(void);
+struct pci_tsm_evidence;
+void devsec_init_evidence(struct pci_tsm_evidence *evidence);
#endif /* __DEVSEC_H__ */
diff --git a/samples/devsec/common.c b/samples/devsec/common.c
index d0e8648dfe98..5dc4152e8b99 100644
--- a/samples/devsec/common.c
+++ b/samples/devsec/common.c
@@ -1,8 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2024 - 2026 Intel Corporation */
-#include <linux/pci.h>
#include <linux/export.h>
+#include <linux/pci.h>
+#include <linux/pci-tsm.h>
+#include <linux/vmalloc.h>
+#include <uapi/linux/pci-tsm-netlink.h>
#include "devsec.h"
@@ -13,14 +16,143 @@
struct devsec_sysdata *devsec_sysdata[NR_DEVSEC_HOST_BRIDGES];
EXPORT_SYMBOL_FOR_MODULES(devsec_sysdata, "devsec*");
+static struct {
+ void *certs;
+ size_t certs_size;
+ void *transcript;
+ size_t transcript_size;
+ int busy;
+ struct mutex lock;
+} devsec_evidence;
+
+void devsec_init_evidence(struct pci_tsm_evidence *evidence)
+{
+ struct pci_tsm_evidence_object *obj;
+
+ obj = &evidence->obj[PCI_TSM_EVIDENCE_TYPE_CERT0];
+ obj->data = devsec_evidence.certs;
+ obj->len = devsec_evidence.certs_size;
+
+ obj = &evidence->obj[PCI_TSM_EVIDENCE_TYPE_MEASUREMENTS];
+ obj->data = devsec_evidence.transcript;
+ obj->len = devsec_evidence.transcript_size;
+}
+EXPORT_SYMBOL_FOR_MODULES(devsec_init_evidence, "devsec*");
+
+static ssize_t certs_read(struct file *file, struct kobject *kobj,
+ const struct bin_attribute *bin_attr, char *buf,
+ loff_t off, size_t count)
+{
+ guard(mutex)(&devsec_evidence.lock);
+ return memory_read_from_buffer(buf, count, &off, devsec_evidence.certs,
+ devsec_evidence.certs_size);
+}
+
+#define EVIDENCE_MAX_SIZE SZ_16M
+
+static ssize_t evidence_write(char *buf, loff_t off, size_t count, void **data,
+ size_t *data_size)
+{
+ loff_t in_off = 0;
+
+ if (off + count > EVIDENCE_MAX_SIZE)
+ return -EFBIG;
+
+ guard(mutex)(&devsec_evidence.lock);
+ if (devsec_evidence.busy)
+ return -EBUSY;
+ if (off + count > *data_size) {
+ void *new_data = kvrealloc(*data, off + count, GFP_KERNEL);
+
+ if (!new_data)
+ return -ENOMEM;
+ *data = new_data;
+ *data_size = off + count;
+ }
+
+ /* reset the buffer on a single byte write */
+ if (off + count == 1) {
+ kvfree(*data);
+ *data = NULL;
+ *data_size = 0;
+ return 1;
+ }
+
+ return memory_read_from_buffer(*data + off, count, &in_off, buf, count);
+}
+
+static ssize_t certs_write(struct file *file, struct kobject *kobj,
+ const struct bin_attribute *bin_attr, char *buf,
+ loff_t off, size_t count)
+{
+ return evidence_write(buf, off, count, &devsec_evidence.certs,
+ &devsec_evidence.certs_size);
+}
+
+static ssize_t transcript_read(struct file *file, struct kobject *kobj,
+ const struct bin_attribute *bin_attr, char *buf,
+ loff_t off, size_t count)
+{
+ guard(mutex)(&devsec_evidence.lock);
+ return memory_read_from_buffer(buf, count, &off,
+ devsec_evidence.transcript,
+ devsec_evidence.transcript_size);
+}
+
+static ssize_t transcript_write(struct file *file, struct kobject *kobj,
+ const struct bin_attribute *bin_attr, char *buf,
+ loff_t off, size_t count)
+{
+ return evidence_write(buf, off, count, &devsec_evidence.transcript,
+ &devsec_evidence.transcript_size);
+}
+
+static const BIN_ATTR_RW(certs, 0);
+static const BIN_ATTR_RW(transcript, 0);
+
+static const struct bin_attribute *devsec_evidence_attrs[] = {
+ &bin_attr_certs,
+ &bin_attr_transcript,
+ NULL,
+};
+
+/*
+ * Prevent evidence from changing while any sample device is connected or locked
+ */
+void devsec_evidence_busy(void)
+{
+ guard(mutex)(&devsec_evidence.lock);
+ devsec_evidence.busy++;
+}
+EXPORT_SYMBOL_FOR_MODULES(devsec_evidence_busy, "devsec*");
+
+void devsec_evidence_idle(void)
+{
+ guard(mutex)(&devsec_evidence.lock);
+ if (devsec_evidence.busy-- <= 0) {
+ WARN_ON_ONCE(1);
+ devsec_evidence.busy = 0;
+ }
+}
+EXPORT_SYMBOL_FOR_MODULES(devsec_evidence_idle, "devsec*");
+
+const struct attribute_group devsec_evidence_group = {
+ .bin_attrs = devsec_evidence_attrs,
+};
+EXPORT_SYMBOL_FOR_MODULES(devsec_evidence_group, "devsec*");
+
static int __init common_init(void)
{
+ mutex_init(&devsec_evidence.lock);
return 0;
}
module_init(common_init);
static void __exit common_exit(void)
{
+ kvfree(devsec_evidence.certs);
+ kvfree(devsec_evidence.transcript);
+ mutex_destroy(&devsec_evidence.lock);
}
module_exit(common_exit);
diff --git a/samples/devsec/link_tsm.c b/samples/devsec/link_tsm.c
index 2e4c1234bdee..21b6c3c7ea52 100644
--- a/samples/devsec/link_tsm.c
+++ b/samples/devsec/link_tsm.c
@@ -3,6 +3,7 @@
#define dev_fmt(fmt) "devsec: " fmt
#include <linux/device/faux.h>
+#include <crypto/hash_info.h>
#include <linux/pci-tsm.h>
#include <linux/pci-ide.h>
#include <linux/module.h>
@@ -51,6 +52,8 @@ static struct device *pci_tsm_host(struct pci_dev *pdev)
static struct pci_tsm *devsec_tsm_pf0_probe(struct tsm_dev *tsm_dev,
struct pci_dev *pdev)
{
+ struct pci_tsm_evidence *evidence;
+ struct pci_tsm *tsm;
int rc;
dev_dbg(tsm_dev->dev.parent, "%s\n", pci_name(pdev));
@@ -60,10 +63,16 @@ static struct pci_tsm *devsec_tsm_pf0_probe(struct tsm_dev *tsm_dev,
if (!devsec_tsm)
return NULL;
+ tsm = &devsec_tsm->pci.base_tsm;
rc = pci_tsm_pf0_constructor(pdev, &devsec_tsm->pci, tsm_dev);
if (rc)
return NULL;
+ devsec_evidence_busy();
+ evidence = &tsm->evidence;
+ pci_tsm_init_evidence(evidence, 0, HASH_ALGO_SHA384);
+ devsec_init_evidence(evidence);
+
pci_dbg(pdev, "TSM enabled\n");
return &no_free_ptr(devsec_tsm)->pci.base_tsm;
}
@@ -113,6 +122,7 @@ static void devsec_link_tsm_pci_remove(struct pci_tsm *tsm)
if (is_pci_tsm_pf0(pdev)) {
struct devsec_tsm_pf0 *devsec_tsm = to_devsec_tsm_pf0(tsm);
+ devsec_evidence_idle();
pci_tsm_pf0_destructor(&devsec_tsm->pci);
kfree(devsec_tsm);
} else {
@@ -390,7 +400,16 @@ static struct attribute *devsec_link_attrs[] = {
&dev_attr_tsm_request.attr,
NULL,
};
-ATTRIBUTE_GROUPS(devsec_link);
+
+static const struct attribute_group devsec_link_group = {
+ .attrs = devsec_link_attrs,
+};
+
+static const struct attribute_group *devsec_link_groups[] = {
+ &devsec_link_group,
+ &devsec_evidence_group,
+ NULL,
+};
static int __init devsec_link_tsm_init(void)
{
diff --git a/samples/devsec/tsm.c b/samples/devsec/tsm.c
index 46dbe668945a..4a62e05ecf35 100644
--- a/samples/devsec/tsm.c
+++ b/samples/devsec/tsm.c
@@ -6,6 +6,7 @@
#include <linux/pci-tsm.h>
#include <linux/module.h>
#include <linux/pci.h>
+#include <linux/sysfs.h>
#include <linux/tsm.h>
#include "devsec.h"
@@ -105,9 +106,15 @@ static const struct faux_device_ops devsec_device_ops = {
.probe = devsec_tsm_probe,
};
+static const struct attribute_group *devsec_evidence_groups[] = {
+ &devsec_evidence_group,
+ NULL,
+};
+
static int __init devsec_tsm_init(void)
{
- devsec_tsm = faux_device_create("devsec_tsm", NULL, &devsec_device_ops);
+ devsec_tsm = faux_device_create_with_groups(
+ "devsec_tsm", NULL, &devsec_device_ops, devsec_evidence_groups);
if (!devsec_tsm)
return -ENOMEM;
return 0;
--
2.52.0
^ permalink raw reply related
* [PATCH v2 17/19] tools/testing/devsec: Add a script to exercise samples/devsec/
From: Dan Williams @ 2026-03-03 0:02 UTC (permalink / raw)
To: linux-coco, linux-pci
Cc: gregkh, aik, aneesh.kumar, yilun.xu, bhelgaas, alistair23, lukas,
jgg
In-Reply-To: <20260303000207.1836586-1-dan.j.williams@intel.com>
Run the samples/devsec/ infrastructure through the PCIe TDISP connect,
bind, lock, and accept flows. Include tests for module "autoprobe" policy.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
tools/testing/devsec/devsec.sh | 234 +++++++++++++++++++++++++++++++++
MAINTAINERS | 1 +
2 files changed, 235 insertions(+)
create mode 100755 tools/testing/devsec/devsec.sh
diff --git a/tools/testing/devsec/devsec.sh b/tools/testing/devsec/devsec.sh
new file mode 100755
index 000000000000..ce4a986b74dd
--- /dev/null
+++ b/tools/testing/devsec/devsec.sh
@@ -0,0 +1,234 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2025-2026 Intel Corporation
+
+# Checkout PCI/TSM sysfs and driver-core mechanics with the
+# devsec_link_tsm and devsec_tsm sample modules from samples/devsec/.
+
+set -ex
+
+trap 'err $LINENO' ERR
+err() {
+ echo $(basename $0): failed at line $1
+ [ -n "$2" ] && "$2"
+ exit 1
+}
+
+ORDER=""
+
+setup_modules() {
+ if [[ $ORDER == "bus" ]]; then
+ modprobe devsec_bus
+ modprobe devsec_link_tsm
+ modprobe devsec_tsm
+ else
+ modprobe devsec_tsm
+ modprobe devsec_link_tsm
+ modprobe devsec_bus
+ fi
+}
+
+teardown_modules() {
+ if [[ $ORDER == "bus" ]]; then
+ modprobe -r devsec_tsm
+ modprobe -r devsec_link_tsm
+ modprobe -r devsec_bus
+ else
+ modprobe -r devsec_bus
+ modprobe -r devsec_link_tsm
+ modprobe -r devsec_tsm
+ fi
+}
+
+PCI_DEVS=(
+"/sys/bus/pci/devices/10000:01:00.0"
+"/sys/bus/pci/devices/10001:03:00.0"
+)
+FN_DEVS=(
+"/sys/bus/pci/devices/10000:01:00.1"
+"/sys/bus/pci/devices/10001:03:00.1"
+)
+tsm_devsec=""
+tsm_link=""
+devsec_pci="/sys/bus/pci/drivers/devsec_pci"
+
+tdisp_test() {
+ pci_dev=${PCI_DEVS[$1]}
+ fn_dev=${FN_DEVS[$1]}
+ host_bridge=$(dirname $(dirname $(readlink -f $pci_dev)))
+
+ # with the device disconnected from the devsec TSM validate that
+ # the devsec_pci driver loads and honors the autoprobe policy
+ echo "devsec_pci" > $pci_dev/driver_override
+ modprobe devsec_pci "autoprobe=0"
+
+ [[ -e $pci_dev/driver ]] && err "$LINENO"
+ echo $(basename $pci_dev) > $devsec_pci/bind
+ echo $(basename $pci_dev) > $devsec_pci/unbind
+
+ # grab the device's resource from /proc/iomem
+ resource=$(cat /proc/iomem | grep -m1 $(basename $pci_dev) | awk -F ' :' '{print $1}' | tr -d ' ')
+ [[ -n $resource ]] || err "$LINENO"
+
+ # lock and accept the device, validate that the resource is now
+ # marked encrypted
+ echo $(basename $tsm_devsec) > $pci_dev/tsm/lock
+ echo 1 > $pci_dev/tsm/accept
+
+ cat /proc/iomem | grep "$resource" | grep -q -m1 "PCI MMIO Encrypted" || err "$LINENO"
+
+ # validate that the driver now fails with -EINVAL when trying to
+ # bind
+ expect="echo: write error: Invalid argument"
+ echo $(basename $pci_dev) 2>&1 > $devsec_pci/bind | grep -q "$expect" || err "$LINENO"
+
+ # unlock and validate that the encrypted mmio is removed
+ echo $(basename $tsm_devsec) > $pci_dev/tsm/unlock
+ cat /proc/iomem | grep "$resource" | grep -q "PCI MMIO Encrypted" && err "$LINENO"
+
+ modprobe -r devsec_pci
+}
+
+validate_disconnected() {
+ pci_dev=${PCI_DEVS[$1]}
+ fn_dev=${FN_DEVS[$1]}
+ host_bridge=$(dirname $(dirname $(readlink -f $pci_dev)))
+
+ # validate that the dsm is not yet detected and that the sub-function
+ # is aware of any TSM capabilities
+ dsm=$(cat $pci_dev/tsm/dsm) || err "$LINENO from $2"
+ bound=$(cat $pci_dev/tsm/bound) || err "$LINENO from $2"
+ [[ -z $dsm ]] || err "$LINENO from $2"
+ [[ -z $bound ]] || err "$LINENO from $2"
+ [[ ! -e $fn_dev/tsm/dsm ]] || err "$LINENO from $2"
+ [[ ! -e $fn_dev/tsm/bound ]] || err "$LINENO from $2"
+ [[ ! -e $fn_dev/tsm/connect ]] || err "$LINENO from $2"
+ [[ ! -e $fn_dev/tsm/disconnect ]] || err "$LINENO from $2"
+}
+
+# check that all devices can be connected simultaneously
+ide_multi_test() {
+ for pci_dev in ${PCI_DEVS[@]}; do
+ echo $(basename $tsm_link) > $pci_dev/tsm/connect
+ done
+
+ #check stream links show up and point back to the pci_dev
+ for pci_dev in ${PCI_DEVS[@]}; do
+ host_bridge=$(dirname $(dirname $(readlink -f $pci_dev)))
+ hb=$(basename $host_bridge)
+ [[ -e $host_bridge/stream0.0.0 ]] || err "$LINENO"
+ [[ -e $tsm_link/$hb/stream0.0.0 ]] || err "$LINENO"
+ [[ $(readlink -f "$tsm_link/$hb/stream0.0.0") == $(readlink -f $pci_dev) ]] || err "$LINENO"
+ done
+
+ for pci_dev in ${PCI_DEVS[@]}; do
+ echo $(basename $tsm_link) > $pci_dev/tsm/disconnect
+ done
+}
+
+ide_test() {
+ pci_dev=${PCI_DEVS[$1]}
+ fn_dev=${FN_DEVS[$1]}
+ host_bridge=$(dirname $(dirname $(readlink -f $pci_dev)))
+
+ # validate that all of the secure streams are idle by default
+ hb=$(basename $host_bridge)
+ nr=$(cat $host_bridge/available_secure_streams)
+ [[ $nr == 4 ]] || err "$LINENO"
+
+ validate_disconnected $1 $LINENO
+
+ # connect a stream and validate that the stream link shows up at
+ # the host bridge and the TSM
+ echo $(basename $tsm_link) > $pci_dev/tsm/connect
+ nr=$(cat $host_bridge/available_secure_streams)
+ [[ $nr == 3 ]] || err "$LINENO"
+
+ [[ $(cat $pci_dev/tsm/connect) == $(basename $tsm_link) ]] || err "$LINENO"
+ [[ -e $host_bridge/stream0.0.0 ]] || err "$LINENO"
+ [[ -e $tsm_link/$hb/stream0.0.0 ]] || err "$LINENO"
+
+ # with the DSM connected (PF0), validate both it and its
+ # sub-function (PF1) populate tsm/dsm with the PF0 device.
+ dsm=$(cat $pci_dev/tsm/dsm)
+ [[ $dsm == $(basename $pci_dev) ]] || err "$LINENO"
+ dsm=$(cat $fn_dev/tsm/dsm)
+ [[ $dsm == $(basename $pci_dev) ]] || err "$LINENO"
+
+ # bind both functions and validate that they display bound to
+ # the TSM device
+ echo $(basename $pci_dev) > $tsm_link/device/tsm_bind
+ bound=$(cat $pci_dev/tsm/bound)
+ [[ $bound == $(basename $tsm_link) ]] || err "$LINENO"
+ echo $(basename $fn_dev) > $tsm_link/device/tsm_bind
+ bound=$(cat $fn_dev/tsm/bound)
+ [[ $bound == $(basename $tsm_link) ]] || err "$LINENO"
+
+ # test manual unbind
+ echo $(basename $pci_dev) > $tsm_link/device/tsm_unbind
+ bound=$(cat $pci_dev/tsm/bound)
+ [[ -z $bound ]] || err "$LINENO"
+ echo $(basename $fn_dev) > $tsm_link/device/tsm_unbind
+ bound=$(cat $fn_dev/tsm/bound)
+ [[ -z $bound ]] || err "$LINENO"
+
+ # rebind to test automatic unbind at disconnect
+ echo $(basename $pci_dev) > $tsm_link/device/tsm_bind
+ echo $(basename $fn_dev) > $tsm_link/device/tsm_bind
+
+ # check that the links disappear at disconnect and the stream
+ # pool is refilled
+ echo $(basename $tsm_link) > $pci_dev/tsm/disconnect
+ nr=$(cat $host_bridge/available_secure_streams)
+ [[ $nr == 4 ]] || err "$LINENO"
+
+ validate_disconnected $1 $LINENO
+
+ [[ $(cat $pci_dev/tsm/connect) == "" ]] || err "$LINENO"
+ [[ ! -e $host_bridge/stream0.0.0 ]] || err "$LINENO"
+ [[ ! -e $tsm_link/$hb/stream0.0.0 ]] || err "$LINENO"
+}
+
+reconnect() {
+ pci_dev=${PCI_DEVS[$1]}
+ fn_dev=${FN_DEVS[$1]}
+ host_bridge=$(dirname $(dirname $(readlink -f $pci_dev)))
+
+ # reconnect to prepare for surprise removal of the TSM or device
+ echo $(basename $tsm_link) > $pci_dev/tsm/connect
+ [[ $(cat $pci_dev/tsm/connect) == $(basename $tsm_link) ]] || err "$LINENO"
+ [[ -e $host_bridge/stream0.0.0 ]] || err "$LINENO"
+ [[ -e $tsm_link/$hb/stream0.0.0 ]] || err "$LINENO"
+}
+
+devsec_test() {
+ setup_modules
+
+ # find the tsm devices by personality
+ for tsm in /sys/class/tsm/tsm*; do
+ mode=$(cat $tsm/pci_mode)
+ [[ $mode == "devsec" ]] && tsm_devsec=$tsm
+ [[ $mode == "link" ]] && tsm_link=$tsm
+ done
+ [[ -n $tsm_devsec ]] || err "$LINENO"
+ [[ -n $tsm_link ]] || err "$LINENO"
+
+ # check that devsec bus loads correctly and the TSM is detected
+ for i in ${!PCI_DEVS[@]}; do
+ pci_dev=${PCI_DEVS[$i]}
+ [[ -e $pci_dev ]] || err "$LINENO"
+ [[ -e $pci_dev/tsm ]] || err "$LINENO"
+ done
+
+ ide_multi_test
+ ide_test 0
+ tdisp_test 0
+
+ reconnect 0
+ teardown_modules
+}
+
+ORDER="bus"
+devsec_test
+ORDER="tsm"
+devsec_test
diff --git a/MAINTAINERS b/MAINTAINERS
index 889546f66f2f..a62b32481094 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -26541,6 +26541,7 @@ F: include/linux/*tsm*.h
F: include/uapi/linux/pci-tsm-netlink.h
F: samples/devsec/
F: samples/tsm-mr/
+F: tools/testing/devsec/
TRUSTED SERVICES TEE DRIVER
M: Balint Dobszay <balint.dobszay@arm.com>
--
2.52.0
^ permalink raw reply related
* [PATCH v2 16/19] samples/devsec: Introduce a "Device Security TSM" sample driver
From: Dan Williams @ 2026-03-03 0:02 UTC (permalink / raw)
To: linux-coco, linux-pci
Cc: gregkh, aik, aneesh.kumar, yilun.xu, bhelgaas, alistair23, lukas,
jgg
In-Reply-To: <20260303000207.1836586-1-dan.j.williams@intel.com>
There are 2 sides to a TEE Security Manager (TSM), the 'link' TSM, and the
'devsec' TSM. The 'link' TSM, outside the TEE, establishes physical link
confidentiality and integerity, and a secure session for transporting
commands the manage the security state of devices. The 'devsec' TSM, within
the TEE, issues requests for confidential devices to lock their
configuration and transition to secure operation.
Implement a sample implementation of a 'devsec' TSM. This leverages the PCI
core's ability to register multiple TSMs at a time to load a sample
devsec_tsm module alongside the existing devsec_link_tsm module. When both
are loaded the TSM personality is selected by choosing to 'connect' vs
'lock' the device.
Drivers like tdx_guest, sev_guest, or arm-cca-guest are examples of "Device
Security TSM" drivers.
A devsec_pci driver is included to test the device_cc_probe() helper for
drivers that need to coordinate some configuration before 'lock' and
'accept'.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
samples/devsec/Makefile | 6 ++
samples/devsec/pci.c | 39 +++++++++++++
samples/devsec/tsm.c | 124 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 169 insertions(+)
create mode 100644 samples/devsec/pci.c
create mode 100644 samples/devsec/tsm.c
diff --git a/samples/devsec/Makefile b/samples/devsec/Makefile
index da122eb8d23d..0c52448a629f 100644
--- a/samples/devsec/Makefile
+++ b/samples/devsec/Makefile
@@ -8,3 +8,9 @@ devsec_bus-y := bus.o
obj-$(CONFIG_SAMPLE_DEVSEC) += devsec_link_tsm.o
devsec_link_tsm-y := link_tsm.o
+
+obj-$(CONFIG_SAMPLE_DEVSEC) += devsec_tsm.o
+devsec_tsm-y := tsm.o
+
+obj-$(CONFIG_SAMPLE_DEVSEC) += devsec_pci.o
+devsec_pci-y := pci.o
diff --git a/samples/devsec/pci.c b/samples/devsec/pci.c
new file mode 100644
index 000000000000..50519be412ed
--- /dev/null
+++ b/samples/devsec/pci.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2024 - 2026 Intel Corporation */
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+static int devsec_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ void __iomem *base;
+ int rc;
+
+ rc = pcim_enable_device(pdev);
+ if (rc)
+ return dev_err_probe(&pdev->dev, rc, "enable failed\n");
+
+ base = pcim_iomap_region(pdev, 0, KBUILD_MODNAME);
+ if (IS_ERR(base))
+ return dev_err_probe(&pdev->dev, PTR_ERR(base),
+ "iomap failed\n");
+
+ dev_dbg(&pdev->dev, "attach\n");
+ return 0;
+}
+
+static const struct pci_device_id devsec_pci_ids[] = {
+ { PCI_DEVICE(0x8086, 0xffff), .override_only = 1, },
+ { }
+};
+
+static struct pci_driver devsec_pci_driver = {
+ .name = "devsec_pci",
+ .probe = devsec_pci_probe,
+ .id_table = devsec_pci_ids,
+};
+
+module_pci_driver(devsec_pci_driver);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Device Security Sample Infrastructure: Secure PCI Driver");
diff --git a/samples/devsec/tsm.c b/samples/devsec/tsm.c
new file mode 100644
index 000000000000..46dbe668945a
--- /dev/null
+++ b/samples/devsec/tsm.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2024 - 2026 Intel Corporation */
+
+#define dev_fmt(fmt) "devsec: " fmt
+#include <linux/device/faux.h>
+#include <linux/pci-tsm.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/tsm.h>
+#include "devsec.h"
+
+struct devsec_dev_data {
+ struct pci_tsm_devsec pci;
+};
+
+static struct devsec_dev_data *to_devsec_data(struct pci_tsm *tsm)
+{
+ return container_of(tsm, struct devsec_dev_data, pci.base_tsm);
+}
+
+static struct pci_tsm *devsec_tsm_lock(struct tsm_dev *tsm_dev, struct pci_dev *pdev)
+{
+ int rc;
+
+ struct devsec_dev_data *devsec_data __free(kfree) =
+ kzalloc(sizeof(*devsec_data), GFP_KERNEL);
+ if (!devsec_data)
+ return ERR_PTR(-ENOMEM);
+
+ rc = pci_tsm_devsec_constructor(pdev, &devsec_data->pci, tsm_dev);
+ if (rc)
+ return ERR_PTR(rc);
+
+ return &no_free_ptr(devsec_data)->pci.base_tsm;
+}
+
+static void devsec_tsm_unlock(struct pci_tsm *tsm)
+{
+ struct devsec_dev_data *devsec_data = to_devsec_data(tsm);
+ struct pci_tsm_devsec *devsec_tsm = to_pci_tsm_devsec(tsm);
+
+ pci_tsm_mmio_teardown(devsec_tsm->mmio);
+ kfree(devsec_tsm->mmio);
+ kfree(devsec_data);
+}
+
+static int devsec_tsm_accept(struct pci_dev *pdev)
+{
+ struct pci_tsm_devsec *devsec_tsm = to_pci_tsm_devsec(pdev->tsm);
+ int rc;
+
+ struct pci_tsm_mmio *mmio __free(kfree) =
+ kzalloc(struct_size(mmio, mmio, PCI_NUM_RESOURCES), GFP_KERNEL);
+ if (!mmio)
+ return -ENOMEM;
+
+ /*
+ * Typically this range request would come from the TDISP Interface
+ * Report. For this sample, just request all BARs be marked encrypted
+ */
+ for (int i = 0; i < PCI_NUM_RESOURCES; i++) {
+ struct resource *res = pci_tsm_mmio_resource(mmio, mmio->nr);
+
+ if (pci_resource_len(pdev, i) == 0 ||
+ !(pci_resource_flags(pdev, i) & IORESOURCE_MEM))
+ continue;
+ res->start = pci_resource_start(pdev, i);
+ res->end = pci_resource_end(pdev, i);
+ mmio->nr++;
+ }
+
+ rc = pci_tsm_mmio_setup(pdev, mmio);
+ if (rc)
+ return rc;
+ devsec_tsm->mmio = no_free_ptr(mmio);
+ return 0;
+}
+
+static struct pci_tsm_ops devsec_pci_ops = {
+ .lock = devsec_tsm_lock,
+ .unlock = devsec_tsm_unlock,
+ .accept = devsec_tsm_accept,
+};
+
+static void devsec_tsm_remove(void *tsm_dev)
+{
+ tsm_unregister(tsm_dev);
+}
+
+static int devsec_tsm_probe(struct faux_device *fdev)
+{
+ struct tsm_dev *tsm_dev;
+
+ tsm_dev = tsm_register(&fdev->dev, &devsec_pci_ops);
+ if (IS_ERR(tsm_dev))
+ return PTR_ERR(tsm_dev);
+
+ return devm_add_action_or_reset(&fdev->dev, devsec_tsm_remove,
+ tsm_dev);
+}
+
+static struct faux_device *devsec_tsm;
+
+static const struct faux_device_ops devsec_device_ops = {
+ .probe = devsec_tsm_probe,
+};
+
+static int __init devsec_tsm_init(void)
+{
+ devsec_tsm = faux_device_create("devsec_tsm", NULL, &devsec_device_ops);
+ if (!devsec_tsm)
+ return -ENOMEM;
+ return 0;
+}
+module_init(devsec_tsm_init);
+
+static void __exit devsec_tsm_exit(void)
+{
+ faux_device_destroy(devsec_tsm);
+}
+module_exit(devsec_tsm_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Device Security Sample Infrastructure: Device Security TSM Driver");
--
2.52.0
^ permalink raw reply related
* [PATCH v2 15/19] samples/devsec: Add sample TSM bind and guest_request flows
From: Dan Williams @ 2026-03-03 0:02 UTC (permalink / raw)
To: linux-coco, linux-pci
Cc: gregkh, aik, aneesh.kumar, yilun.xu, bhelgaas, alistair23, lukas,
jgg, Samuel Ortiz, Suzuki K Poulose
In-Reply-To: <20260303000207.1836586-1-dan.j.williams@intel.com>
Provide a method to test the basic object lifetime mechanics of 'struct
pci_tdi', and passthrough sysfs message to simulate pci_tsm_guest_req().
Arrange for pci_tsm_bind() and pci_tsm_guest_req() to be invoked via
devsec_link_tsm faux-device sysfs attributes.
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Lukas Wunner <lukas@wunner.de>
Cc: Samuel Ortiz <sameo@rivosinc.com>
Cc: Alexey Kardashevskiy <aik@amd.com>
Cc: Xu Yilun <yilun.xu@linux.intel.com>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: "Aneesh Kumar K.V" <aneesh.kumar@kernel.org>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
Documentation/ABI/testing/sysfs-faux-devsec | 15 ++
samples/devsec/link_tsm.c | 157 +++++++++++++++++++-
2 files changed, 170 insertions(+), 2 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-faux-devsec
diff --git a/Documentation/ABI/testing/sysfs-faux-devsec b/Documentation/ABI/testing/sysfs-faux-devsec
new file mode 100644
index 000000000000..29da17bfa720
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-faux-devsec
@@ -0,0 +1,15 @@
+What: /sys/bus/faux/devices/{devsec_link_tsm,devsec_tsm}
+Contact: linux-coco@lists.linux.dev
+Description:
+ (DIR) The devsec_link_tsm and devsec_tsm faux devices test the
+ kernel's ABIs and flows that support PCIe Trusted Device
+ Interface Security Protocol (TDISP). The devsec_link_tsm device
+ simulates a "host" TSM that establishes an SPDM session and link
+ security (PCIe IDE). The devsec_tsm device simulates a "guest"
+ TSM that implements the lock+accept flows.
+
+What:
+/sys/bus/faux/devices/devsec_link_tsm/{bind,unbind}
+Contact: linux-coco@lists.linux.dev
+Description:
+
diff --git a/samples/devsec/link_tsm.c b/samples/devsec/link_tsm.c
index dea5215ff97b..2e4c1234bdee 100644
--- a/samples/devsec/link_tsm.c
+++ b/samples/devsec/link_tsm.c
@@ -19,6 +19,10 @@ struct devsec_tsm_fn {
struct pci_tsm pci;
};
+struct devsec_tsm_tdi {
+ struct pci_tdi pci;
+};
+
static struct devsec_tsm_pf0 *to_devsec_tsm_pf0(struct pci_tsm *tsm)
{
return container_of(tsm, struct devsec_tsm_pf0, pci.base_tsm);
@@ -29,6 +33,12 @@ static struct devsec_tsm_fn *to_devsec_tsm_fn(struct pci_tsm *tsm)
return container_of(tsm, struct devsec_tsm_fn, pci);
}
+/*
+ * Note that outside of pci_tsm_ops callbacks, this lookup is racy. I.e. does
+ * not account for racing disconnect / unlock after reading ->tsm. The
+ * @devsec_link_groups usage of this is only for best-effort protection against
+ * using this sample / test module to interfere with other TSM drivers.
+ */
static struct device *pci_tsm_host(struct pci_dev *pdev)
{
struct pci_tsm *tsm = READ_ONCE(pdev->tsm);
@@ -157,6 +167,8 @@ static int devsec_link_tsm_connect(struct pci_dev *pdev)
unsigned long __stream_id;
int rc;
+ dev_dbg(pci_tsm_host(pdev), "%s\n", pci_name(pdev));
+
unsigned long *stream_id __free(free_devsec_stream) =
alloc_devsec_stream_id(&__stream_id);
if (!stream_id)
@@ -197,6 +209,8 @@ static void devsec_link_tsm_disconnect(struct pci_dev *pdev)
struct pci_ide *ide;
unsigned long i;
+ dev_dbg(pci_tsm_host(pdev), "%s\n", pci_name(pdev));
+
for_each_set_bit(i, devsec_stream_ids, NR_TSM_STREAMS)
if (devsec_streams[i]->pdev == pdev)
break;
@@ -210,11 +224,56 @@ static void devsec_link_tsm_disconnect(struct pci_dev *pdev)
clear_bit(i, devsec_stream_ids);
}
+static struct pci_tdi *devsec_link_tsm_bind(struct pci_dev *pdev,
+ struct kvm *kvm, u32 tdi_id)
+{
+ struct devsec_tsm_tdi *devsec_tdi =
+ kzalloc(sizeof(struct devsec_tsm_tdi), GFP_KERNEL);
+
+ dev_dbg(pci_tsm_host(pdev), "%s\n", pci_name(pdev));
+
+ if (!devsec_tdi)
+ return ERR_PTR(-ENOMEM);
+
+ pci_tsm_tdi_constructor(pdev, &devsec_tdi->pci, kvm, tdi_id);
+
+ return &devsec_tdi->pci;
+}
+
+static void devsec_link_tsm_unbind(struct pci_tdi *tdi)
+{
+ struct devsec_tsm_tdi *devsec_tdi =
+ container_of(tdi, struct devsec_tsm_tdi, pci);
+
+ dev_dbg(pci_tsm_host(tdi->pdev), "%s\n", pci_name(tdi->pdev));
+
+ kfree(devsec_tdi);
+}
+
+static ssize_t devsec_link_tsm_guest_req(struct pci_tdi *tdi,
+ enum pci_tsm_req_scope scope,
+ sockptr_t req_in, size_t in_len,
+ sockptr_t req_out, size_t out_len,
+ u64 *tsm_code)
+{
+ if (!sockptr_is_kernel(req_in))
+ return -ENXIO;
+
+ dev_dbg(pci_tsm_host(tdi->pdev), "%s\n", pci_name(tdi->pdev));
+ print_hex_dump_debug("devsec req_in ", DUMP_PREFIX_OFFSET, 16, 4,
+ req_in.kernel, min(in_len, 256u), true);
+
+ return 0;
+}
+
static struct pci_tsm_ops devsec_link_pci_ops = {
.probe = devsec_link_tsm_pci_probe,
.remove = devsec_link_tsm_pci_remove,
.connect = devsec_link_tsm_connect,
.disconnect = devsec_link_tsm_disconnect,
+ .bind = devsec_link_tsm_bind,
+ .unbind = devsec_link_tsm_unbind,
+ .guest_req = devsec_link_tsm_guest_req,
};
static void devsec_link_tsm_remove(void *tsm_dev)
@@ -240,10 +299,104 @@ static const struct faux_device_ops devsec_link_device_ops = {
.probe = devsec_link_tsm_probe,
};
+static struct pci_dev *pci_find_device(const char *name)
+{
+ struct device *dev = bus_find_device_by_name(&pci_bus_type, NULL, name);
+
+ if (dev)
+ return to_pci_dev(dev);
+ return NULL;
+}
+
+static ssize_t tsm_bind_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct device *host;
+ int rc;
+
+ struct pci_dev *pdev __free(pci_dev_put) = pci_find_device(buf);
+ if (!pdev)
+ return -ENODEV;
+
+ host = pci_tsm_host(pdev);
+ if (!host || host != &devsec_link_tsm->dev)
+ return -ENXIO;
+
+ rc = pci_tsm_bind(pdev, (struct kvm *)1, pci_dev_id(pdev));
+ if (rc)
+ return rc;
+ return count;
+}
+static DEVICE_ATTR_WO(tsm_bind);
+
+static ssize_t tsm_unbind_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct device *host;
+
+ struct pci_dev *pdev __free(pci_dev_put) = pci_find_device(buf);
+ if (!pdev)
+ return -ENODEV;
+
+ host = pci_tsm_host(pdev);
+ if (!host || host != &devsec_link_tsm->dev)
+ return -ENXIO;
+
+ pci_tsm_unbind(pdev);
+ return count;
+}
+static DEVICE_ATTR_WO(tsm_unbind);
+
+static ssize_t tsm_request_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *__buf, size_t count)
+{
+ ssize_t rc;
+ u64 tsm_code = 0;
+ struct device *host;
+ char req_out[16] = {0};
+ size_t out_len = sizeof(req_out);
+
+ struct pci_dev *pdev __free(pci_dev_put) = pci_find_device(__buf);
+ if (!pdev)
+ return -ENODEV;
+
+ char *buf __free(kvfree) = kvmemdup(__buf, count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ host = pci_tsm_host(pdev);
+ if (!host || host != &devsec_link_tsm->dev)
+ return -ENXIO;
+
+ rc = pci_tsm_guest_req(pdev, PCI_TSM_REQ_INFO, KERNEL_SOCKPTR(buf),
+ count, KERNEL_SOCKPTR(req_out), out_len,
+ &tsm_code);
+ if (rc)
+ return rc;
+
+ return count;
+}
+static DEVICE_ATTR_WO(tsm_request);
+
+/*
+ * Facilitate testing of the bind and request flows in lieu of VFIO/IOMMUFD
+ * support to exercise these paths.
+ */
+static struct attribute *devsec_link_attrs[] = {
+ &dev_attr_tsm_bind.attr,
+ &dev_attr_tsm_unbind.attr,
+ &dev_attr_tsm_request.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(devsec_link);
+
static int __init devsec_link_tsm_init(void)
{
- devsec_link_tsm = faux_device_create("devsec_link_tsm", NULL,
- &devsec_link_device_ops);
+ devsec_link_tsm = faux_device_create_with_groups(
+ "devsec_link_tsm", NULL, &devsec_link_device_ops,
+ devsec_link_groups);
if (!devsec_link_tsm)
return -ENOMEM;
return 0;
--
2.52.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox