* Re: [PATCH v2 03/19] device core: Introduce confidential device acceptance
From: Jason Gunthorpe @ 2026-03-26 12:00 UTC (permalink / raw)
To: Dan Williams
Cc: Greg KH, linux-coco, linux-pci, aik, aneesh.kumar, yilun.xu,
bhelgaas, alistair23, lukas, Christoph Hellwig, Marek Szyprowski,
Robin Murphy, Roman Kisel, Samuel Ortiz, Rafael J. Wysocki,
Danilo Krummrich
In-Reply-To: <69c48b682e6fe_7ee310068@dwillia2-mobl4.notmuch>
On Wed, Mar 25, 2026 at 06:27:04PM -0700, Dan Williams wrote:
> Jason Gunthorpe wrote:
> [..]
> > > Right, the potential to see in-between states concerns me because TSM
> > > uAPIs would have fully enabled the device to wreak havoc, meanwhile
> > > dev->trust is still showing the device at some lower level of trust. So
> > > I think trust modification needs to be synchronous with privileges
> > > granted/revoked.
> >
> > If an iommu is present then the device will still be blocked even
> > though it is in RUN, I'm not sure this synchronicity is so important.
>
> Oh, maybe we are just quibbling about where the mechanism lives. The
> "unblock DMA" step in current preliminary patches is currently behind
> the "struct pci_tsm_ops::accept()" op which also handles transitioning
> the device to RUN / T=1. It is a bus callback.
>
> However, if the IOMMU layer is enlightened to block/unblock DMA on trust
> setting then the TDISP "unblock DMA" step can be factored out of this bus
> callback and into the IOMMU trust responder.
Yes, I would prefer this because it makes the whole IOMMU mechanism
entirely general and not tied to TDISP - which I think is sort of what
Greg is pushing on too.
> I assume this would also expect that encrypted MMIO mappings are also
> not established while trust is less than "TCB"? That would require some
> additional enabling to catch attempts to establish an encrypted mapping
> that the hardware is prepared for, but dev->trust is not, all without
> needing to modify the driver to worry about this difference. Drivers
> would just see ioremap() failure in this case.
Hmm.. I don't know if this matters. Once we decide to use the device
the MMIO should be mapped in the correct way, whatever that is.
If we decide to eventually allow a lower trust while T=1 then that
should be taken to mean the user wants all the features protecting the
communication channel but also all the IOMMU features restricting what
memory the device can access.
Remember there are two parallel things here, one is T=1 which is
designed to protect against hypervisor and physical attacks, the other
is the trust level and iommu which would be able to protect against
attacks from an attested device itself.
Even if you are in a T=1 environment you may still decide you don't
really trust the device firmware that much and would prefer to have it
more restricted.
For example, if you have a system with a NVMe drive then all the data
on the drive is probably still encrypted and has be CPU-decrypted
before it can be used. It would be reasonable to run in T=1 and attest
the drive to limit attack surface but also use the IOMMU to limit NVMe
access to only the memory used to bounce to the CPU decryption as an
additional fortification.
This is why I am tending to prefer that the kernel's view of trust
level and the physical HW capability are somewhat orthogonal
things. Even if the HW has high security the user may still prefer
that the kernel distrust.
Jason
^ permalink raw reply
* Re: [PATCH v6 12/22] x86/virt/tdx: Reset software states during TDX module shutdown
From: Chao Gao @ 2026-03-26 12:35 UTC (permalink / raw)
To: linux-kernel, linux-coco, kvm
Cc: binbin.wu, dan.j.williams, dave.hansen, ira.weiny, kai.huang, kas,
nik.borisov, paulmck, pbonzini, reinette.chatre, rick.p.edgecombe,
sagis, seanjc, tony.lindgren, vannapurve, vishal.l.verma,
yilun.xu, xiaoyao.li, yan.y.zhao, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, x86, H. Peter Anvin
In-Reply-To: <20260326084448.29947-13-chao.gao@intel.com>
> int tdx_module_shutdown(void)
> {
> struct tdx_module_args args = {};
>+ int ret, cpu;
>
> /*
> * Shut down the TDX module and prepare handoff data for the next
>@@ -1188,7 +1189,23 @@ int tdx_module_shutdown(void)
> * modules as new modules likely have higher handoff version.
> */
> args.rcx = tdx_sysinfo.handoff.module_hv;
>- return seamcall_prerr(TDH_SYS_SHUTDOWN, &args);
>+ ret = seamcall_prerr(TDH_SYS_SHUTDOWN, &args);
>+ if (ret)
>+ return ret;
>+
>+ tdx_module_status = TDX_MODULE_UNINITIALIZED;
Sashiko commented:
"""
If a TDX module update fails after this shutdown completes, does this leave
the system in an unrecoverable state?
Since tdx_module_status is left as TDX_MODULE_UNINITIALIZED, if KVM is
later reloaded, it appears it will call tdx_enable(), observe the
uninitialized status, and invoke init_tdx_module() again.
Because init_tdx_module() is not re-entrant, won't it blindly append
duplicate memory regions to the global tdx_memlist and allocate new TDMR
arrays and PAMT memory?
This seems like it would permanently leak the previous allocations and
eventually fail when construct_tdmrs() rejects overlapping TDMRs. Is there
a mechanism to prevent re-initialization if the subsequent update steps fail?
"""
This is a valid issue.
A fix is: set tdx_module_status to TDX_MODULE_ERROR here. Failures preserve
ERROR state; success explicitly transitions to INITIALIZED (patch 15).
Alternatively, we could introduce a dedicated shutdown state.
Note that the VMXON series moves TDX initialization to boot time, eliminating
runtime re-initialization (init_tdx_module() calls) entirely.
^ permalink raw reply
* Re: [PATCH v6 16/22] x86/virt/tdx: Update tdx_sysinfo and check features post-update
From: Chao Gao @ 2026-03-26 13:03 UTC (permalink / raw)
To: linux-kernel, linux-coco, kvm
Cc: binbin.wu, dan.j.williams, dave.hansen, ira.weiny, kai.huang, kas,
nik.borisov, paulmck, pbonzini, reinette.chatre, rick.p.edgecombe,
sagis, seanjc, tony.lindgren, vannapurve, vishal.l.verma,
yilun.xu, xiaoyao.li, yan.y.zhao, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, x86, H. Peter Anvin
In-Reply-To: <20260326084448.29947-17-chao.gao@intel.com>
>+int tdx_module_post_update(struct tdx_sys_info *info)
>+{
>+ struct tdx_sys_info_version *old, *new;
>+ int ret;
>+
>+ /* Shouldn't fail as the update has succeeded. */
>+ ret = get_tdx_sys_info(info);
>+ if (WARN_ONCE(ret, "version retrieval failed after update, replace the TDX module\n"))
>+ return ret;
>+
>+ old = &tdx_sysinfo.version;
>+ new = &info->version;
>+ pr_info("version %u.%u.%02u -> %u.%u.%02u\n", old->major_version,
>+ old->minor_version,
>+ old->update_version,
>+ new->major_version,
>+ new->minor_version,
>+ new->update_version);
>+
>+ /*
>+ * Blindly refreshing the entire tdx_sysinfo could disrupt running
>+ * software, as it may subtly rely on the previous state unless
>+ * proven otherwise.
>+ *
>+ * Only refresh version information (including handoff version)
>+ * that does not affect functionality, and ignore all other
>+ * changes.
>+ */
>+ tdx_sysinfo.version = info->version;
>+ tdx_sysinfo.handoff = info->handoff;
Sashiko commented:
"""
Because stop_machine() has already completed in seamldr_install_module(),
other CPUs will have resumed execution by the time this is called.
Since tdx_sysinfo.version and tdx_sysinfo.handoff are multi-byte structures
and are updated here without holding a lock, could concurrent readers observe
torn reads if they access these fields simultaneously?
"""
This is valid. tdx_sysinfo.handoff has no concurrent readers. so, no fix is
needed.
tdx_sysinfo.version may be read by userspace via sysfs. However, major/minor
versions don't change across updates, so only update_version needs
READ/WRITE_ONCE() to prevent torn reads. I will apply this fix:
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 432d80b21ef0..0e7668bf20a1 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -1276,7 +1276,7 @@ int tdx_module_post_update(struct tdx_sys_info *info)
* that does not affect functionality, and ignore all other
* changes.
*/
- tdx_sysinfo.version = info->version;
+ WRITE_ONCE(tdx_sysinfo.version.update_version, info->version.update_version);
tdx_sysinfo.handoff = info->handoff;
if (!memcmp(&tdx_sysinfo, info, sizeof(*info)))
diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-host/tdx-host.c
index d4a552853021..43a55666145c 100644
--- a/drivers/virt/coco/tdx-host/tdx-host.c
+++ b/drivers/virt/coco/tdx-host/tdx-host.c
@@ -40,7 +40,7 @@ static ssize_t version_show(struct device *dev, struct device_attribute *attr,
return sysfs_emit(buf, TDX_VERSION_FMT"\n", ver->major_version,
ver->minor_version,
- ver->update_version);
+ READ_ONCE(ver->update_version));
}
static DEVICE_ATTR_RO(version);
>+
>+ if (!memcmp(&tdx_sysinfo, info, sizeof(*info)))
>+ return 0;
>+
>+ pr_info("TDX module features have changed after updates, but might not take effect.\n");
>+ pr_info("Please consider updating your BIOS to install the TDX module.\n");
>+ return 0;
>+}
>+
> static bool is_pamt_page(unsigned long phys)
> {
> struct tdmr_info_list *tdmr_list = &tdx_tdmr_list;
>diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h
>index c62874b87d7a..f8686247c660 100644
>--- a/arch/x86/virt/vmx/tdx/tdx.h
>+++ b/arch/x86/virt/vmx/tdx/tdx.h
>@@ -4,6 +4,8 @@
>
> #include <linux/bits.h>
>
>+#include <asm/tdx_global_metadata.h>
>+
> /*
> * This file contains both macros and data structures defined by the TDX
> * architecture and Linux defined software data structures and functions.
>@@ -122,5 +124,6 @@ struct tdmr_info_list {
>
> int tdx_module_shutdown(void);
> int tdx_module_run_update(void);
>+int tdx_module_post_update(struct tdx_sys_info *info);
>
> #endif
>--
>2.47.3
>
^ permalink raw reply related
* Re: [PATCH v2 03/19] device core: Introduce confidential device acceptance
From: Greg KH @ 2026-03-26 15:00 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Dan Williams, linux-coco, linux-pci, aik, aneesh.kumar, yilun.xu,
bhelgaas, alistair23, lukas, Christoph Hellwig, Marek Szyprowski,
Robin Murphy, Roman Kisel, Samuel Ortiz, Rafael J. Wysocki,
Danilo Krummrich
In-Reply-To: <20260326120046.GG67624@nvidia.com>
On Thu, Mar 26, 2026 at 09:00:46AM -0300, Jason Gunthorpe wrote:
> On Wed, Mar 25, 2026 at 06:27:04PM -0700, Dan Williams wrote:
> > Jason Gunthorpe wrote:
> > [..]
> > > > Right, the potential to see in-between states concerns me because TSM
> > > > uAPIs would have fully enabled the device to wreak havoc, meanwhile
> > > > dev->trust is still showing the device at some lower level of trust. So
> > > > I think trust modification needs to be synchronous with privileges
> > > > granted/revoked.
> > >
> > > If an iommu is present then the device will still be blocked even
> > > though it is in RUN, I'm not sure this synchronicity is so important.
> >
> > Oh, maybe we are just quibbling about where the mechanism lives. The
> > "unblock DMA" step in current preliminary patches is currently behind
> > the "struct pci_tsm_ops::accept()" op which also handles transitioning
> > the device to RUN / T=1. It is a bus callback.
> >
> > However, if the IOMMU layer is enlightened to block/unblock DMA on trust
> > setting then the TDISP "unblock DMA" step can be factored out of this bus
> > callback and into the IOMMU trust responder.
>
> Yes, I would prefer this because it makes the whole IOMMU mechanism
> entirely general and not tied to TDISP - which I think is sort of what
> Greg is pushing on too.
That is what I am going to _require_ here :)
> > I assume this would also expect that encrypted MMIO mappings are also
> > not established while trust is less than "TCB"? That would require some
> > additional enabling to catch attempts to establish an encrypted mapping
> > that the hardware is prepared for, but dev->trust is not, all without
> > needing to modify the driver to worry about this difference. Drivers
> > would just see ioremap() failure in this case.
>
> Hmm.. I don't know if this matters. Once we decide to use the device
> the MMIO should be mapped in the correct way, whatever that is.
>
> If we decide to eventually allow a lower trust while T=1 then that
> should be taken to mean the user wants all the features protecting the
> communication channel but also all the IOMMU features restricting what
> memory the device can access.
>
> Remember there are two parallel things here, one is T=1 which is
> designed to protect against hypervisor and physical attacks, the other
> is the trust level and iommu which would be able to protect against
> attacks from an attested device itself.
>
> Even if you are in a T=1 environment you may still decide you don't
> really trust the device firmware that much and would prefer to have it
> more restricted.
>
> For example, if you have a system with a NVMe drive then all the data
> on the drive is probably still encrypted and has be CPU-decrypted
> before it can be used. It would be reasonable to run in T=1 and attest
> the drive to limit attack surface but also use the IOMMU to limit NVMe
> access to only the memory used to bounce to the CPU decryption as an
> additional fortification.
>
> This is why I am tending to prefer that the kernel's view of trust
> level and the physical HW capability are somewhat orthogonal
> things. Even if the HW has high security the user may still prefer
> that the kernel distrust.
I agree, that's a good way of putting this.
greg k-h
^ permalink raw reply
* Re: [PATCH v2 00/16] fs,x86/resctrl: Add kernel-mode (e.g., PLZA) support to the resctrl subsystem
From: Babu Moger @ 2026-03-26 17:12 UTC (permalink / raw)
To: Reinette Chatre, corbet, tony.luck, Dave.Martin, james.morse,
tglx, mingo, bp, dave.hansen
Cc: skhan, x86, hpa, peterz, juri.lelli, vincent.guittot,
dietmar.eggemann, rostedt, bsegall, mgorman, vschneid, kas,
rick.p.edgecombe, akpm, pmladek, rdunlap, dapeng1.mi, kees, elver,
paulmck, lirongqing, safinaskar, fvdl, seanjc, pawan.kumar.gupta,
xin, tiala, Neeraj.Upadhyay, chang.seok.bae, thomas.lendacky,
elena.reshetova, linux-doc, linux-kernel, linux-coco, kvm,
eranian, peternewman
In-Reply-To: <14a8ad0a-e842-4268-871a-0762f1169e03@intel.com>
Hi Reinette,
Thanks for the review comments. Will address one by one.
On 3/24/26 17:51, Reinette Chatre wrote:
> Hi Babu,
>
> On 3/12/26 1:36 PM, Babu Moger wrote:
>> This series adds support for Privilege-Level Zero Association (PLZA) to the
>> resctrl subsystem. PLZA is an AMD feature that allows specifying a CLOSID
>> and/or RMID for execution in kernel mode (privilege level zero), so that
>> kernel work is not subject to the same resource constrains as the current
>> user-space task. This avoids kernel operations being aggressively throttled
>> when a task's memory bandwidth is heavily limited.
>>
>> The feature documentation is not yet publicly available, but it is expected
>> to be released in the next few weeks. In the meantime, a brief description
>> of the features is provided below.
>>
>> Privilege Level Zero Association (PLZA)
>>
>> Privilege Level Zero Association (PLZA) allows the hardware to
>> automatically associate execution in Privilege Level Zero (CPL=0) with a
>> specific COS (Class of Service) and/or RMID (Resource Monitoring
>> Identifier). The QoS feature set already has a mechanism to associate
>> execution on each logical processor with an RMID or COS. PLZA allows the
>> system to override this per-thread association for a thread that is
>> executing with CPL=0.
>> ------------------------------------------------------------------------
>>
>> The series introduces the feature in a way that supports the interface in
>> a generic manner to accomodate MPAM or other vendor specific implimentation.
>>
>> Below is the detailed requirements provided by Reinette:
>> https://lore.kernel.org/lkml/2ab556af-095b-422b-9396-f845c6fd0342@intel.com/
> Our discussion considered how resctrl could support PLZA in a generic way while
> also preparing to support MPAM's variants and how PLZA may evolve to have similar
> capabilities when considering the capabilities of its registers.
>
> This does not mean that your work needs to implement everything that was discussed.
> Instead, this work is expected to just support what PLZA is capable of today but
> do so in a way that the future enhancements could be added to.
>
> This series is quite difficult to follow since it appears to implement a full
> featured generic interface while PLZA cannot take advantage of it.
>
> Could you please simplify this work to focus on just enabling PLZA and only
> add interfaces needed to do so?
Sure. Will try. Lets continue the discussion.
>
>> Summary:
>> 1. Kernel-mode/PLZA controls and status should be exposed under the resctrl
>> info directory:/sys/fs/resctrl/info/, not as a separate or arch-specific path.
>>
>> 2. Add two info files
>>
>> a. kernel_mode
>> Purpose: Control how resource allocation and monitoring apply in kernel mode
>> (e.g. inherit from task vs global assign).
>>
>> Read: List supported modes and show current one (e.g. with [brackets]).
>> Write: Set current mode by name (e.g. inherit_ctrl_and_mon, global_assign_ctrl_assign_mon).
>>
>> b. kernel_mode_assignment
>>
>> Purpose: When a “global assign” kernel mode is active, specify which resctrl group
>> (CLOSID/RMID) is used for kernel work.
>>
>> Read: Show the assigned group in a path-like form (e.g. //, ctrl1//, ctrl1/mon1/).
>> Write: Assign or clear the group used for kernel mode (and optionally clear with an empty write).
>>
>> The patches are based on top of commit (v7.0.0-rc3)
>> 839e91ce3f41b (tip/master) Merge branch into tip/master: 'x86/tdx'
>> ------------------------------------------------------------------------
>>
>> Examples: kernel_mode and kernel_mode_assignment
>>
>> All paths below are under /sys/fs/resctrl/ (e.g. info/kernel_mode means
>> /sys/fs/resctrl/info/kernel_mode). Resctrl must be mounted and the platform
>> must support the relevant modes (e.g. AMD with PLZA).
>>
>> 1) kernel_mode — show and set the current kernel mode
>>
>> Read supported modes and which one is active (current in brackets):
>>
>> $ cat info/kernel_mode
>> [inherit_ctrl_and_mon]
>> global_assign_ctrl_inherit_mon
>> global_assign_ctrl_assign_mon
>>
>> Set the active mode (e.g. use one CLOSID+RMID for all kernel work):
>>
>> $ echo "global_assign_ctrl_assign_mon" > info/kernel_mode
>> $ cat info/kernel_mode
>> inherit_ctrl_and_mon
>> global_assign_ctrl_inherit_mon
>> [global_assign_ctrl_assign_mon]
>>
>> Mode meanings:
>> - inherit_ctrl_and_mon: kernel uses same CLOSID/RMID as the current task (default).
>> - global_assign_ctrl_inherit_mon: one CLOSID for all kernel work; RMID inherited from user.
>> - global_assign_ctrl_assign_mon: one resource group (CLOSID+RMID) for all kernel work.
>>
>> 2) kernel_mode_assignment — show and set which group is used for kernel work
>>
>> Only relevant when kernel_mode is not "inherit_ctrl_and_mon". Read the
> To help with future usages please connect visibility of this file with the mode in
> info/kernel_mode. This helps us to support future modes with other resctrl files, possible
> within each resource group.
> Specifically, kernel_mode_assignment is not visible to user space if mode is "inherit_ctrl_and_mon",
> while it is visible when mode is global_assign_ctrl_inherit_mon or global_assign_ctrl_assign_mon.
Sure. Will do.
>
>> currently assigned group (path format is "CTRL_MON/MON/"):
> The format depends on the mode, right? If the mode is "global_assign_ctrl_inherit_mon"
> then it should only contain a control group, alternatively, if the mode is
> "global_assign_ctrl_assign_mon" then it contains control and mon group. This gives
> resctrl future flexibility to change format for future modes.
This can be done both ways. Whole purpose of these groups is to get
CLOSID and RMID to enable PLZA. User can echo CTRL_MON or MON group to
kernel_mode_assignment in any of the modes. We can decide what needs to
be updated in MSR (PQR_PLZA_ASSOC) based on what kernel mode is selected.
>
> We should also consider the scenario when it is a "monitoring only" system, which can
> happen independent from what hardware actually supports, for example, if user boots
> with "rdt=!l3cat,!l2cat,!mba,!smba". In this case I assume CLOS should just always be
> zero and thus only "default control group" is accepted?
Yes. It depends on how we want to implement like we mentioned above.
>
>> $ cat info/kernel_mode_assignment
>> //
>>
>> "//" means the default CTRL_MON group is assigned. Assign a specific
>> group instead (e.g. a CTRL_MON group "ctrl1", or a MON group "mon1" under it):
>>
>> $ echo "ctrl1//" > info/kernel_mode_assignment
>> $ cat info/kernel_mode_assignment
>> ctrl1//
>>
>> $ echo "ctrl1/mon1/" > info/kernel_mode_assignment
>> $ cat info/kernel_mode_assignment
>> ctrl1/mon1/
>>
>> Clear the assignment (no dedicated group for kernel work):
>>
>> $ echo >> info/kernel_mode_assignment
>> $ cat info/kernel_mode_assignment
>> Kmode is not configured
> This does not look right. Would this not create a conflict between info/kernel_mode
> and info/kernel_mode_assignment about what the current mode is? The way I see it
> info/kernel_mode_assignment must always contain a valid group.
Yes. We can do that.
>
>> Errors (e.g. invalid group name or unsupported mode) are reported in
>> info/last_cmd_status.
>>
>> ---
>>
>> v2:
>> This is similar to RFC with new proposal. Names of the some interfaces
>> are not final. Lets fix that later as we move forward.
>>
>> Separated the two features: Global Bandwidth Enforcement (GLBE) and
>> Privilege Level Zero Association (PLZA).
>>
>> This series only adds support for PLZA.
>>
>> Used the name of the feature as kmode instead of PLZA. That can be changed as well.
>>
>> Tony suggested using global variables to store the kernel mode
>> CLOSID and RMID. However, the kernel mode CLOSID and RMID are
>> coming from rdtgroup structure with the new interface. Accessing
>> them requires holding the associated lock, which would make the
>> context switch path unnecessarily expensive. So, dropped the idea.
>> https://lore.kernel.org/lkml/aXuxVSbk1GR2ttzF@agluck-desk3/
>> Let me know if there are other ways to optimize this.
> I do not see why the context switch path needs to be touched at all with this
> implementation. Since PLZA only supports global assignment does it not mean that resctrl
> only needs to update PQR_PLZA_ASSOC when user writes to info/kernel_mode and
> info/kernel_mode_assignment?
Each thread has an MSR to configure whether to associate privilege level
zero execution with a separate COS and/or RMID, and the value of the COS
and/or RMID. PLZA may be enabled or disabled on a per-thread
basis. However, the COS and RMID association and configuration must be
the same for all threads in the QOS Domain.
So, PQR_PLZA_ASSOC is a per thread MSR just like PQR_ASSOC.
Privilege-Level Zero Association (PLZA) allows the user to specify a COS
and/or RMID associated with execution in Privilege-Level Zero. When
enabled on a HW thread, when that thread enters Privilige-Level Zero,
transactions associated with that thread will be associated with the
PLZA COS and/or RMID. Otherwise, the HW thread will be associated with
the COS and RMID identified by PQR_ASSOC.
More below.
>
> Consider some of the scenarios:
>
> resctrl mount with default state:
>
> # cat info/kernel_mode
> [inherit_ctrl_and_mon]
> global_assign_ctrl_inherit_mon
> global_assign_ctrl_assign_mon
> # ls info/kernel_mode_assignment
> ls: cannot access 'info/kernel_mode_assignment': No such file or directory
>
> enable global_assign_ctrl_assign_mon mode:
> # echo "global_assign_ctrl_assign_mon" > info/kernel_mode
>
> Expectation here is that when user space sets this mode as above then resctrl would
> in turn program MSR_IA32_PQR_PLZA_ASSOC on all CPUs to be:
> MSR_IA32_PQR_PLZA_ASSOC.rmid=0
> MSR_IA32_PQR_PLZA_ASSOC.rmid_en=1
> MSR_IA32_PQR_PLZA_ASSOC.closid=0
> MSR_IA32_PQR_PLZA_ASSOC.closid_en=1
> MSR_IA32_PQR_PLZA_ASSOC.plza_en=1
>
> I do not see why it is necessary to maintain any per-CPU or per-task state or needing
> to touch the context switch code. Since PLZA only supports global could it not
> just set MSR_IA32_PQR_PLZA_ASSOC on all online CPUs and be done with it?
> Only caveat is that if a CPU is offline then this setting needs to be stashed
> so that MSR_IA32_PQR_PLZA_ASSOC can be set when new CPU comes online.
>
> The way that rdtgroup_config_kmode() introduced in patch #11 assumes it is dealing
> with RDT_RESOURCE_L3 and traverses the resource domain list and resource group
> CPU mask seems unnecessary to me as well as error prone since the system may only
> have, for example, RDT_RESOURCE_MBA enabled or even just monitoring. Why not just set
> MSR_IA32_PQR_PLZA_ASSOC on all CPUs and be done?
>
> To continue the scenarios ...
>
> After user's setting above related files read:
> # cat info/kernel_mode
> inherit_ctrl_and_mon
> global_assign_ctrl_inherit_mon
> [global_assign_ctrl_assign_mon]
> # cat info/kernel_mode_assignment
> //
>
> Modify group used by global_assign_ctrl_assign_mon mode:
> # echo 'ctrl1/mon1/' > info/kernel_mode_assignment
>
> Expectation here is that when user space sets this then resctrl would
> program MSR_IA32_PQR_PLZA_ASSOC on all CPUs to be:
> MSR_IA32_PQR_PLZA_ASSOC.rmid=<rmid of mon1>
> MSR_IA32_PQR_PLZA_ASSOC.rmid_en=1
> MSR_IA32_PQR_PLZA_ASSOC.closid=<closid of ctrl1>
> MSR_IA32_PQR_PLZA_ASSOC.closid_en=1
> MSR_IA32_PQR_PLZA_ASSOC.plza_en=1
This works correctly when PLZA associations are defined by per CPU. For
example, lets assume that *ctrl1* is assigned *CLOSID 1*.
In this scenario, every task in the system running on a any CPU will use
the limits associated with *CLOSID 1* whenever it enters Privilege-Level
Zero, because the CPU's *PQR_PLZA_ASSOC* register has PLZA enabled and
CLOSID is 1.
Now consider task-based association:
We have two resctrl groups:
* *ctrl1 -> CLOSID 1 -> task1.plza = 1 : *User wants PLZA be enabled
for this task.
* *ctrl2 -> CLOSID 2 -> task2.plza = 0 : *User wants PLZA
disabled for this task.
Suppose *task1* is first scheduled on *CPU 0*. This behaves as expected:
since CPU 0 's *PQR_PLZA_ASSOC* contains *CLOSID 1, plza_en =1*, task1
will use the limits from CLOSID 1 when it enters Privilege-Level Zero.
However, if *task2* later runs on *CPU 0*, we expect it to use *CLOSID
2* in both user mode and kernel mode, because user has PLZA disabled for
this task. But CPU 0 still has *CLOSID 1, **plza_en =1* in its
PQR_PLZA_ASSOC register.
As a result, task2 will incorrectly run with *CLOSID 1* when entering
Privilege-Level Zero something we explicitly want to avoid.
At that point, PLZA must be disabled on CPU 0 to prevent the unintended
association. Hope this explanation makes the issue clear.
Thanks
Babu
>
> Enable global_assign_ctrl_inherit_mon mode:
> # echo "global_assign_ctrl_inherit_mon" > info/kernel_mode
>
> Expectation here is that when user space sets this mode then resctrl would
> program MSR_IA32_PQR_PLZA_ASSOC on all CPUs to be:
> MSR_IA32_PQR_PLZA_ASSOC.rmid=0
> MSR_IA32_PQR_PLZA_ASSOC.rmid_en=0
> MSR_IA32_PQR_PLZA_ASSOC.closid=0
> MSR_IA32_PQR_PLZA_ASSOC.closid_en=1
> MSR_IA32_PQR_PLZA_ASSOC.plza_en=1
>
> # cat info/kernel_mode
> inherit_ctrl_and_mon
> [global_assign_ctrl_inherit_mon]
> global_assign_ctrl_assign_mon
> # cat info/kernel_mode_assignment <==== returns just a ctrl group
> /
>
> Modify group used by global_assign_ctrl_inherit_mon mode:
> # echo ctrl1 > info/kernel_mode_assignment
>
> Expectation here is that when user space sets this then resctrl would
> program MSR_IA32_PQR_PLZA_ASSOC on all CPUs to be:
> MSR_IA32_PQR_PLZA_ASSOC.rmid=0
> MSR_IA32_PQR_PLZA_ASSOC.rmid_en=0
> MSR_IA32_PQR_PLZA_ASSOC.closid=<closid of ctrl1>
> MSR_IA32_PQR_PLZA_ASSOC.closid_en=1
> MSR_IA32_PQR_PLZA_ASSOC.plza_en=1
>
> # cat info/kernel_mode_assignment <==== returns just a ctrl group
> ctrl/
>
> Enable inherit_ctrl_and_mon mode:
> # echo "inherit_ctrl_and_mon" > info/kernel_mode
>
> Expectation here is that when user space sets this mode then resctrl would
> program MSR_IA32_PQR_PLZA_ASSOC on all CPUs to be:
> MSR_IA32_PQR_PLZA_ASSOC.rmid=0
> MSR_IA32_PQR_PLZA_ASSOC.rmid_en=0
> MSR_IA32_PQR_PLZA_ASSOC.closid=0
> MSR_IA32_PQR_PLZA_ASSOC.closid_en=0
> MSR_IA32_PQR_PLZA_ASSOC.plza_en=0
>
> At this point info/kernel_mode_assignment is not visible anymore:
>
> # ls info/kernel_mode_assignment
> ls: cannot access 'info/kernel_mode_assignment': No such file or directory
>
> >From what I understand above exposes and enables full capability of PLZA. All the other
> per-task and per-cpu handling in this series is not something that PLZA can benefit from.
> If this is not the case, what am I missing? Could this series be simplified to just support
> PLZA today? When next hardware with more capability needs to be supported resctrl could be
> enhanced to support it by using the more accurate information about what the hardware is
> capable of.
>
> We also do not really know what use cases users prefer. This may even be sufficient.
>
> Reinette
>
^ permalink raw reply
* Re: [PATCH 2/2] x86/tdx: Accept hotplugged memory before online
From: Paolo Bonzini @ 2026-03-26 18:25 UTC (permalink / raw)
To: Edgecombe, Rick P
Cc: Marc-André Lureau, Borislav Petkov, kas, Qiang, Chenyi,
Anvin, H. Peter, Ingo Molnar, Kernel Mailing List, Linux,
Dave Hansen, Thomas Gleixner, kvm, linux-coco,
the arch/x86 maintainers
In-Reply-To: <7802b50589c80a7276a50cc473c1aa579750a30c.camel@intel.com>
Il mer 25 mar 2026, 18:21 Edgecombe, Rick P
<rick.p.edgecombe@intel.com> ha scritto:
>
> Ah, I see now! So the problem is not that the kernel is accidentally
> re-accepting the memory. It's that host userspace is not actually
> removing the memory during unplug. Hmm. Why not fix userspace then? If
> the memory is unplugged it should not be usable anymore by the guest.
> If it is still accessible then it seems kind of like a bug, no?
>
> And! This totally justifies the warning. If the error is ignored, the
> guest would think the memory is zeroed, but it could have old data in
> it. It's exactly the kind of tricks a VMM could play to attack the
> guest.
>
> Another option could be to perform a TDG.MEM.PAGE.RELEASE TDCALL from
> the guest when it unplugs the memory, to put it in an unaccepted state.
> This would be more robust to buggy VMM behavior. But working around
> buggy VM behavior would need a high bar.
Wouldn't it actually be a very low bar? Just from these two paragraphs
of yours, it's clear that the line between buggy and malicious is
fine, in fact I think userspace should not care at all about removing
the memory. Only the guest cares about acceptance state.
Doing a RELEASE TDCALL seems more robust and not hard.
Paolo
^ permalink raw reply
* Re: [PATCH v2 03/19] device core: Introduce confidential device acceptance
From: Dan Williams @ 2026-03-26 18:31 UTC (permalink / raw)
To: Jason Gunthorpe, Dan Williams
Cc: Greg KH, linux-coco, linux-pci, aik, aneesh.kumar, yilun.xu,
bhelgaas, alistair23, lukas, Christoph Hellwig, Marek Szyprowski,
Robin Murphy, Roman Kisel, Samuel Ortiz, Rafael J. Wysocki,
Danilo Krummrich
In-Reply-To: <20260326120046.GG67624@nvidia.com>
Jason Gunthorpe wrote:
[..]
> > I assume this would also expect that encrypted MMIO mappings are also
> > not established while trust is less than "TCB"? That would require some
> > additional enabling to catch attempts to establish an encrypted mapping
> > that the hardware is prepared for, but dev->trust is not, all without
> > needing to modify the driver to worry about this difference. Drivers
> > would just see ioremap() failure in this case.
>
> Hmm.. I don't know if this matters. Once we decide to use the device
> the MMIO should be mapped in the correct way, whatever that is.
>
> If we decide to eventually allow a lower trust while T=1 then that
> should be taken to mean the user wants all the features protecting the
> communication channel but also all the IOMMU features restricting what
> memory the device can access.
The question is whether any part of the kernel would ever track that
secrets in MMIO writes should not be written to TCB-external devices...
but that is probably a "trust=0" situation. "trust=1" means "be careful
what you send to this device whether the transport is protected or not".
> Remember there are two parallel things here, one is T=1 which is
> designed to protect against hypervisor and physical attacks, the other
> is the trust level and iommu which would be able to protect against
> attacks from an attested device itself.
>
> Even if you are in a T=1 environment you may still decide you don't
> really trust the device firmware that much and would prefer to have it
> more restricted.
>
> For example, if you have a system with a NVMe drive then all the data
> on the drive is probably still encrypted and has be CPU-decrypted
> before it can be used. It would be reasonable to run in T=1 and attest
> the drive to limit attack surface but also use the IOMMU to limit NVMe
> access to only the memory used to bounce to the CPU decryption as an
> additional fortification.
>
> This is why I am tending to prefer that the kernel's view of trust
> level and the physical HW capability are somewhat orthogonal
> things. Even if the HW has high security the user may still prefer
> that the kernel distrust.
Sounds workable to me.
^ permalink raw reply
* Re: [PATCH v2 01/16] fs/resctrl: Add kernel mode (kmode) data structures and arch hook
From: Babu Moger @ 2026-03-26 18:41 UTC (permalink / raw)
To: Reinette Chatre, corbet, tony.luck, Dave.Martin, james.morse,
tglx, mingo, bp, dave.hansen
Cc: skhan, x86, hpa, peterz, juri.lelli, vincent.guittot,
dietmar.eggemann, rostedt, bsegall, mgorman, vschneid, kas,
rick.p.edgecombe, akpm, pmladek, rdunlap, dapeng1.mi, kees, elver,
paulmck, lirongqing, safinaskar, fvdl, seanjc, pawan.kumar.gupta,
xin, tiala, Neeraj.Upadhyay, chang.seok.bae, thomas.lendacky,
elena.reshetova, linux-doc, linux-kernel, linux-coco, kvm,
eranian, peternewman
In-Reply-To: <57c72d52-e62a-44f6-a08a-891a354058e5@intel.com>
Hi Reinette,
On 3/24/26 17:51, Reinette Chatre wrote:
> Hi Babu,
>
> On 3/12/26 1:36 PM, Babu Moger wrote:
>> Add resctrl_kmode, resctrl_kmode_cfg, kernel mode bit defines, and
>> resctrl_arch_get_kmode_cfg() for resctrl kernel mode (e.g. PLZA) support.
> We should not have to start every series from scratch.
> Documentation/process/maintainer-tip.rst. Always.
Sure. Yea. I did not focus on that aspect of patch submission in this
series. Will do next revision.
>
>> ---
>> include/linux/resctrl.h | 10 ++++++++++
>> include/linux/resctrl_types.h | 30 ++++++++++++++++++++++++++++++
>> 2 files changed, 40 insertions(+)
>>
>> diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
>> index 006e57fd7ca5..2c36d1ac392f 100644
>> --- a/include/linux/resctrl.h
>> +++ b/include/linux/resctrl.h
>> @@ -699,6 +699,16 @@ int resctrl_arch_io_alloc_enable(struct rdt_resource *r, bool enable);
>> */
>> bool resctrl_arch_get_io_alloc_enabled(struct rdt_resource *r);
>>
>> +/**
>> + * resctrl_arch_get_kmode_cfg() - Get resctrl kernel mode configuration
>> + * @kcfg: Filled with current kernel mode config (kmode, kmode_cur, k_rdtgrp).
>> + *
>> + * Used by the arch (e.g. x86) to report which kernel mode is active and,
>> + * when a global assign mode is in use, which rdtgroup is assigned to
>> + * kernel work.
>> + */
>> +void resctrl_arch_get_kmode_cfg(struct resctrl_kmode_cfg *kcfg);
> This interface does not look right. Would it not be resctrl fs that determines
> which resource group is assigned? This cannot be set by arch. Why does arch decide
> which mode is active? Is this not also resctrl fs? Should arch not just tell
> resctrl fs what it supports?
Yes. Sure. Let the arch tell what is supported. Let fs decide what is
default.
>
>> +
>> extern unsigned int resctrl_rmid_realloc_threshold;
>> extern unsigned int resctrl_rmid_realloc_limit;
>>
>> diff --git a/include/linux/resctrl_types.h b/include/linux/resctrl_types.h
>> index a5f56faa18d2..6b78b08eab29 100644
>> --- a/include/linux/resctrl_types.h
>> +++ b/include/linux/resctrl_types.h
>> @@ -65,7 +65,37 @@ enum resctrl_event_id {
>> QOS_NUM_EVENTS,
>> };
>>
>> +/**
>> + * struct resctrl_kmode - Resctrl kernel mode descriptor
>> + * @name: Human-readable name of the kernel mode.
>> + * @val: Bitmask value for the kernel mode (e.g. INHERIT_CTRL_AND_MON).
>> + */
>> +struct resctrl_kmode {
>> + char name[32];
>> + u32 val;
>> +};
> There is no reason why this needs to be in a central header exposed to archs. Could
> this not be a static within the only function that uses it? Something like
> rdt_mode_str[]?
Yes. I think so.
>
>> +
>> +/**
>> + * struct resctrl_kmode_cfg - Resctrl kernel mode configuration
>> + * @kmode: Requested kernel mode.
>> + * @kmode_cur: Currently active kernel mode.
>> + * @k_rdtgrp: Resource control structure in use, or NULL otherwise.
>> + */
>> +struct resctrl_kmode_cfg {
>> + u32 kmode;
>> + u32 kmode_cur;
>> + struct rdtgroup *k_rdtgrp;
>> +};
>> +
>> #define QOS_NUM_L3_MBM_EVENTS (QOS_L3_MBM_LOCAL_EVENT_ID - QOS_L3_MBM_TOTAL_EVENT_ID + 1)
>> #define MBM_STATE_IDX(evt) ((evt) - QOS_L3_MBM_TOTAL_EVENT_ID)
>>
>> +/* Resctrl kernel mode bits (e.g. for PLZA). */
>> +#define INHERIT_CTRL_AND_MON BIT(0) /* Kernel uses same CLOSID/RMID as user. */
>> +/* One CLOSID for all kernel work; RMID inherited from user. */
>> +#define GLOBAL_ASSIGN_CTRL_INHERIT_MON BIT(1)
>> +/* One resource group (CLOSID+RMID) for all kernel work. */
>> +#define GLOBAL_ASSIGN_CTRL_ASSIGN_MON BIT(2)
>> +#define RESCTRL_KERNEL_MODES_NUM 3
> I think it will make the code much easier to understand if the different modes are described by an
> enum. For example,
Yes. Sure.
>
> enum resctrl_kernel_modes {
> INHERIT_CTRL_AND_MON,
> GLOBAL_ASSIGN_CTRL_INHERIT_MON,
> GLOBAL_ASSIGN_CTRL_ASSIGN_MON,
> RESCTRL_KMODE_LAST = GLOBAL_ASSIGN_CTRL_ASSIGN_MON
> };
> #define RESCTRL_NUM_KERNEL_MODES (RESCTRL_KMODE_LAST + 1)
>
> The supported kernel modes can still be managed as a bitmap with intuitive API using the
> enum that will make the code easier to read. For example, __set_bit(INHERIT_CTRL_AND_MON, ...)
> or BIT(INHERIT_CTRL_AND_MON). The naming is awkward at the moment though, we should improve here.
>
Sure. Yes. We need to think about naming.. Let me think about it.
Thanks
Babu
^ permalink raw reply
* Re: [PATCH v2 02/16] fs, x86/resctrl: Add architecture routines for kernel mode initialization
From: Babu Moger @ 2026-03-26 19:10 UTC (permalink / raw)
To: Reinette Chatre, corbet, tony.luck, Dave.Martin, james.morse,
tglx, mingo, bp, dave.hansen
Cc: skhan, x86, hpa, peterz, juri.lelli, vincent.guittot,
dietmar.eggemann, rostedt, bsegall, mgorman, vschneid, kas,
rick.p.edgecombe, akpm, pmladek, rdunlap, dapeng1.mi, kees, elver,
paulmck, lirongqing, safinaskar, fvdl, seanjc, pawan.kumar.gupta,
xin, tiala, Neeraj.Upadhyay, chang.seok.bae, thomas.lendacky,
elena.reshetova, linux-doc, linux-kernel, linux-coco, kvm,
eranian, peternewman
In-Reply-To: <3ef56c9c-cfe4-4e3c-8598-f2217e538c8c@intel.com>
Hi Reinette,
On 3/24/26 17:53, Reinette Chatre wrote:
> Hi Babu,
>
> On 3/12/26 1:36 PM, Babu Moger wrote:
>> Implement the resctrl kernel mode (kmode) arch initialization.
>>
>> - Add resctrl_arch_get_kmode_cfg() to fill the default kernel mode
>> (INHERIT_CTRL_AND_MON). This can be extended later (e.g. for PLZA) to set
>> additional modes.
> I do not think this is something that the architecture should set, at least
> at this time. Every mode has different requirements and this just lets the arch set
> it without any support for what configurations it implies. For example, if
> arch sets a different default mode than INHERIT_CTRL_AND_MON then PQR_PLZA_ASSOC
> needs to be programmed as the CPUs come online and this does not seem to
> accommodate this. This implementation appears to have significant assumptions on
> what architecture will end up setting since it is only considering PLZA.
Sure. Let the arch report what is supported. Will change it to set the
default in fs code.
Users can change change modes from FS code.
>
>> - Add global resctrl_kcfg and resctrl_kmode_init() to initialize default
>> values.
>>
>> Signed-off-by: Babu Moger <babu.moger@amd.com>
>> ---
>> v2: New patch to handle PLZA interfaces with /sys/fs/resctrl/info/ directory.
>> https://lore.kernel.org/lkml/2ab556af-095b-422b-9396-f845c6fd0342@intel.com/
>> ---
>> arch/x86/kernel/cpu/resctrl/core.c | 7 +++++++
>> fs/resctrl/rdtgroup.c | 10 ++++++++++
>> 2 files changed, 17 insertions(+)
>>
>> diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
>> index 7667cf7c4e94..4c3ab2d93909 100644
>> --- a/arch/x86/kernel/cpu/resctrl/core.c
>> +++ b/arch/x86/kernel/cpu/resctrl/core.c
>> @@ -892,6 +892,13 @@ bool resctrl_arch_is_evt_configurable(enum resctrl_event_id evt)
>> }
>> }
>>
>> +void resctrl_arch_get_kmode_cfg(struct resctrl_kmode_cfg *kcfg)
>> +{
>> + kcfg->kmode = INHERIT_CTRL_AND_MON;
>> + kcfg->kmode_cur = INHERIT_CTRL_AND_MON;
>> + kcfg->k_rdtgrp = NULL;
>> +}
> I already commented on the arch vs filesystem settings.
>
> When using an arch helper this forces all architectures to support this helper. Is a
> helper required? Is it perhaps possible for arch to set a property instead? For example,
> how enumeration is handled?
> I think the assumption here is that INHERIT_CTRL_AND_MON is the default and expected to
> be supported by all architectures. I do not see why arch should set this as default but
> instead this should be from resctrl fs. At the same time it is expected that the
> architecture supports this mode so there needs to be a failure if an architecture does
> not support this mode?
I will change. Arch sets the supported modes. FS sets the default.
Users can change it to required mode later.
>
> I'm going to stop here. I think the comments so far may result in major changes already
> making further detailed review of patches unnecessary.
Based on my comments below you may need to re-look at the some of the
patches.
https://lore.kernel.org/lkml/47c0db32-d0e0-4c53-90bd-b74863d233dc@amd.com/
I am fine otherwise also. Let continue that discussion.
Thanks
Babu
>
> Reinette
>
^ permalink raw reply
* Re: [PATCH v2 03/19] device core: Introduce confidential device acceptance
From: Jason Gunthorpe @ 2026-03-26 19:28 UTC (permalink / raw)
To: Dan Williams
Cc: Greg KH, linux-coco, linux-pci, aik, aneesh.kumar, yilun.xu,
bhelgaas, alistair23, lukas, Christoph Hellwig, Marek Szyprowski,
Robin Murphy, Roman Kisel, Samuel Ortiz, Rafael J. Wysocki,
Danilo Krummrich
In-Reply-To: <69c57b745af0f_7ee31003@dwillia2-mobl4.notmuch>
On Thu, Mar 26, 2026 at 11:31:16AM -0700, Dan Williams wrote:
> Jason Gunthorpe wrote:
> [..]
> > > I assume this would also expect that encrypted MMIO mappings are also
> > > not established while trust is less than "TCB"? That would require some
> > > additional enabling to catch attempts to establish an encrypted mapping
> > > that the hardware is prepared for, but dev->trust is not, all without
> > > needing to modify the driver to worry about this difference. Drivers
> > > would just see ioremap() failure in this case.
> >
> > Hmm.. I don't know if this matters. Once we decide to use the device
> > the MMIO should be mapped in the correct way, whatever that is.
> >
> > If we decide to eventually allow a lower trust while T=1 then that
> > should be taken to mean the user wants all the features protecting the
> > communication channel but also all the IOMMU features restricting what
> > memory the device can access.
>
> The question is whether any part of the kernel would ever track that
> secrets in MMIO writes should not be written to TCB-external devices...
> but that is probably a "trust=0" situation. "trust=1" means "be careful
> what you send to this device whether the transport is protected or not".
Right, the kernel has no idea what is secret or not, it is up to
userspace not to give the device secrets if it doesn't fully trust it.
Jason
^ permalink raw reply
* Re: [PATCH 2/2] x86/tdx: Accept hotplugged memory before online
From: Edgecombe, Rick P @ 2026-03-26 20:40 UTC (permalink / raw)
To: pbonzini@redhat.com
Cc: x86@kernel.org, dave.hansen@linux.intel.com,
marcandre.lureau@redhat.com, kas@kernel.org, hpa@zytor.com,
linux-kernel@vger.kernel.org, mingo@redhat.com, bp@alien8.de,
Qiang, Chenyi, tglx@kernel.org, linux-coco@lists.linux.dev,
kvm@vger.kernel.org
In-Reply-To: <CABgObfZ7_w8Q-dW=Sd4YA3P==BuN1edPv7Ty4EpPyU8ctW6RLg@mail.gmail.com>
Hi Paolo!
On Thu, 2026-03-26 at 19:25 +0100, Paolo Bonzini wrote:
> > Another option could be to perform a TDG.MEM.PAGE.RELEASE TDCALL from
> > the guest when it unplugs the memory, to put it in an unaccepted state.
> > This would be more robust to buggy VMM behavior. But working around
> > buggy VM behavior would need a high bar.
>
> Wouldn't it actually be a very low bar? Just from these two paragraphs
> of yours, it's clear that the line between buggy and malicious is
> fine, in fact I think userspace should not care at all about removing
> the memory. Only the guest cares about acceptance state.
>
> Doing a RELEASE TDCALL seems more robust and not hard.
I mean I guess the contract is a bit fuzzy. The reason why I was thinking it was
a host userspace bug is because the conventional bare metal behavior of
unplugging memory should be that it is no longer accessible, right? If the guest
could still use the unplugged memory, it could be surprising for userspace and
the guest. Also, ideally I'd think the behavior wouldn't cover up guest bugs
where it tried to keep using the memory. So forgetting about TDX, isn't it
better behavior in general for unplugging memory, to actually pull it from the
guest? Did I look at that wrong?
As for the bar to change the guest, I was first imagining it would be the size
of the accept memory plumbing. Which was not a small effort and has had a steady
stream of bugs to squash where the accept was missed.
But I didn't actually POC anything to check the scope so maybe that was a bit
hasty. Should we do a POC? But considering the scope, I wonder if SNP has the
same problem.
^ permalink raw reply
* Re: [PATCH v2 09/19] PCI/TSM: Support creating encrypted MMIO descriptors via TDISP Report
From: Alexey Kardashevskiy @ 2026-03-26 23:38 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Xu Yilun, Aneesh Kumar K.V, Dan Williams, linux-coco, linux-pci,
gregkh, bhelgaas, alistair23, lukas, Arnd Bergmann
In-Reply-To: <20260323182014.GR7340@nvidia.com>
On 24/3/26 05:20, Jason Gunthorpe wrote:
> On Mon, Mar 16, 2026 at 04:19:30PM +1100, Alexey Kardashevskiy wrote:
>
>> and btw this only works if the entity generating the MMIO reporting
>> offset (==TSM) knows about BARs sizes, which is not the case for AMD
>> - the FW has no access to the config space (so the HV needs to feed
>> this to the FW? may be). Thanks,
>
> Then your platform just shouldn't use the mmio offset feature. Set it
> to 0 always.
pcie r7, Table 11-16 TDI Report Structure, MMIO_RANGE:
"Each MMIO Range of the TDI is reported with the MMIO reporting offset added."
My english struggles here - can the above be interpreted as "Each reported MMIO Range ..."?
as if it is each (except msix), then I know where msix is and can amend the report inside the VM if msix is not locked. Thanks,
--
Alexey
^ permalink raw reply
* Re: [PATCH 2/2] x86/tdx: Accept hotplugged memory before online
From: Chenyi Qiang @ 2026-03-27 3:05 UTC (permalink / raw)
To: Marc-André Lureau, Edgecombe, Rick P
Cc: bp@alien8.de, kas@kernel.org, hpa@zytor.com, mingo@redhat.com,
x86@kernel.org, tglx@kernel.org, dave.hansen@linux.intel.com,
kvm@vger.kernel.org, linux-coco@lists.linux.dev,
linux-kernel@vger.kernel.org, Bonzini, Paolo,
David Hildenbrand (Arm)
In-Reply-To: <CAMxuvaytU-pM+rviUbNGWMhvbAYutwvaSXW_O=sn+QfOzF35Xw@mail.gmail.com>
On 3/25/2026 6:29 PM, Marc-André Lureau wrote:
> Hi
>
> On Wed, Mar 25, 2026 at 2:04 AM Edgecombe, Rick P
> <rick.p.edgecombe@intel.com> wrote:
>>
>> On Tue, 2026-03-24 at 19:21 +0400, Marc-André Lureau wrote:
>>> In TDX guests, hotplugged memory (e.g., via virtio-mem) is never
>>> accepted before use. The first access triggers a fatal "SEPT entry in
>>> PENDING state" EPT violation and KVM terminates the guest.
>>>
>>> Fix this by registering a MEM_GOING_ONLINE memory hotplug notifier that
>>> calls tdx_accept_memory() for the range being onlined.
>>>
>>> The notifier returns NOTIFY_BAD on acceptance failure, preventing the
>>> memory from going online.
>>
>> Does this depend on patch 1 somehow?
>
> Yes, if I plug, unplug and plug again I get this without PATCH 1:
> [root@rhel10-server ~]# [ 5707.392231] virtio_mem virtio5: plugged
> size: 0x80000000
> [ 5707.395583] virtio_mem virtio5: requested size: 0x0
>
> [root@rhel10-server ~]# [ 5714.648501] virtio_mem virtio5: plugged
> size: 0x2e00000
> [ 5714.651808] virtio_mem virtio5: requested size: 0x80000000
> [ 5714.676296] tdx: Failed to accept memory [0x108000000, 0x110000000)
> [ 5714.683980] tdx: Failed to accept memory [0x110000000, 0x118000000)
> [ 5714.686997] tdx: Failed to accept memory [0x140000000, 0x148000000)
> [ 5714.689989] tdx: Failed to accept memory [0x128000000, 0x130000000)
> [ 5714.694981] tdx: Failed to accept memory [0x148000000, 0x150000000)
> [ 5714.704064] tdx: Failed to accept memory [0x138000000, 0x140000000)
> [ 5714.710144] tdx: Failed to accept memory [0x118000000, 0x120000000)
> [ 5714.722532] tdx: Failed to accept memory [0x130000000, 0x138000000)
>
> My understanding is that QEMU should eventually unplug the memory and
> PUNCH_HOLE then KVM should TDH.MEM.PAGE.REMOVE, but that doesn't seem
> to happen.
I guess it doesn't happen because virtio-mem in QEMU only PUNCH_HOLE the
shared memory by ram_block_discard_range() but it doesn't touch the private
memory which should be discarded by ram_block_discard_guest_memfd_range().
Is this strictly required? According to the specification,
> it may not be.
>
>
^ permalink raw reply
* Re: [PATCH 1/2] x86/virt/tdx: Use PFN directly for mapping guest private memory
From: Yan Zhao @ 2026-03-27 7:03 UTC (permalink / raw)
To: Edgecombe, Rick P
Cc: Hansen, Dave, kvm@vger.kernel.org, linux-coco@lists.linux.dev,
Huang, Kai, Li, Xiaoyao, dave.hansen@linux.intel.com,
kas@kernel.org, seanjc@google.com, mingo@redhat.com,
pbonzini@redhat.com, binbin.wu@linux.intel.com,
ackerleytng@google.com, linux-kernel@vger.kernel.org,
Yamahata, Isaku, sagis@google.com, Annapurve, Vishal,
bp@alien8.de, tglx@kernel.org, yilun.xu@linux.intel.com,
x86@kernel.org
In-Reply-To: <189f00877360117ab91ec3a6cb8b8239f4fff06a.camel@intel.com>
On Thu, Mar 26, 2026 at 12:57:26AM +0800, Edgecombe, Rick P wrote:
> On Wed, 2026-03-25 at 17:10 +0800, Yan Zhao wrote:
> > > I don't really understand what this is saying.
> > >
> > > Is the concern that KVM might want to set up page tables for memory
> > > that differ from how it was allocated? I'm a bit worried that this
> > > assumes something about folios that doesn't always hold.
> > >
> > > I think the hugetlbfs gigantic support uses folios in at least a
> > > few spots today.
> > Below is the background of this problem. I'll try to include a short
> > summary in the next version's patch logs.
>
> While this patchset is kind of pre-work for TDX huge pages, the reason
> to separate it out and push it earlier is because it has some value on
> it's own. So I'd think to focus mostly on the impact of the change
> today.
>
> How about this justification:
> 1. Because KVM handles guest memory as PFNs, and the SEAMCALLs under
> discussion are only used there, PFN is more natural.
>
> 2. The struct page was partly making sure we didn't pass a wrong arg
> (typical type safety) and partly ensuring that KVM doesn't pass non-
> convertible memory, however the SEAMCALLs themselves can check this for
> the kernel. So the case is already covered by warnings.
>
> In conclusion, the PFN is more natural and the original purpose of
> struct page is already covered.
>
>
> Sean said somewhere IIRC that he would have NAKed the struct page thing
> if he had seen it, for even the base support. And the two points above
> don't actually require discussion of even huge pages. So does it
> actually add any value to dive into the issues you list below?
I wanted to mention the issues listed below because I'm not sure if anyone has
the same question as me: why do we have to convert struct page to PFN if they
can both achieve the same purpose, given that currently all private memory
allocated by gmem has struct page backing?
The background can also reduce confusion if the patch log mentions hugepage and
single folio.
So, maybe also avoid mentioning hugepage and single folio things if you think
it's better to just mention the above two points?
> > In TDX huge page v3, I added logic that assumes PFNs are contained in
> > a single folio in both TDX's map/unmap paths [1][2]:
> > if (start_idx + npages > folio_nr_pages(folio))
> > return TDX_OPERAND_INVALID;
> > This not only assumes the PFNs have corresponding struct page, but
> > also assumes they must be contained in a single folio, since with
> > only base_page + npages, it's not easy to get the ith page's pointer
> > without first ensuring the pages are contained in a single folio.
> >
> > This should work since current KVM/guest_memfd only allocates memory
> > with struct page and maps them into S-EPT at a level lower than or
> > equal to the backend folio size. That is, a single S-EPT mapping
> > cannot span multiple backend folios.
> >
> > However, Ackerley's 1G hugetlb-based gmem splits the backend folio
> > [3] ahead of splitting/unmapping them from S-EPT [4], due to
> > implementation limitations mentioned at [5]. It makes the warning in
> > [1] hit upon invoking TDX's unmap callback.
> >
> > Moreover, Google's future gmem may manage PFNs independently in the
> > future,
>
> I think we can adapt to such changes when they eventually come up. It's
> not just about not merging code to be used by out-of-tree code. It also
> shrinks what we have to consider at each stage. So we can eventually
> get there.
Ok.
> > so TDX's private memory may have no corresponding struct page, and
> > KVM would map them via VM_PFNMAP, similar to mapping pass-through
> > MMIOs or other PFNs without struct page or with non-refcounted struct
> > page in normal VMs. Given that KVM has
> > suffered a lot from handling VM_PFNMAP memory for non-refcounted
> > struct page [6] in normal VMs, and TDX mapping/unmapping callbacks
> > have no semantic reason to dictate where and how KVM/guest_memfd
> > should allocate and map memory, Sean suggested dropping the
> > unnecessary assumption that memory to be mapped/unmapped to/from S-
> > EPT must be contained in a single folio (though he didn't object
> > reasonable sanity checks on if the PFNs are TDX convertible).
> >
> >
> > [1]
> > https://lore.kernel.org/kvm/20260106101929.24937-1-yan.y.zhao@intel.com
> > [2]
> > https://lore.kernel.org/kvm/20260106101826.24870-1-yan.y.zhao@intel.com
> > [3]
> > https://github.com/googleprodkernel/linux-cc/blob/wip-gmem-conversions-hugetlb-restructuring-12-08-25/virt/kvm/guest_memfd.c#L909
> > [4]
> > https://github.com/googleprodkernel/linux-cc/blob/wip-gmem-conversions-hugetlb-restructuring-12-08-25/virt/kvm/guest_memfd.c#L918
> > [5] https://lore.kernel.org/kvm/diqzqzrzdfvh.fsf@google.com/
> > [6]
> > https://lore.kernel.org/all/20241010182427.1434605-1-seanjc@google.com
>
^ permalink raw reply
* Re: [PATCH v2 16/19] samples/devsec: Introduce a "Device Security TSM" sample driver
From: Lai, Yi @ 2026-03-27 8:44 UTC (permalink / raw)
To: Dan Williams
Cc: linux-coco, linux-pci, gregkh, aik, aneesh.kumar, yilun.xu,
bhelgaas, alistair23, lukas, jgg, yi1.lai
In-Reply-To: <20260303000207.1836586-17-dan.j.williams@intel.com>
On Mon, Mar 02, 2026 at 04:02:04PM -0800, Dan Williams wrote:
> 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);
> +}
> +
Hi Dan,
While validating devsec mode transitions, I hit a reproducible crash in the
sample devsec driver.
Reproducer:
1. lock with devsec tsm
2. unlock
Observed: NULL pointer dereference in the MMIO teardown path
Expected: unlock from LOCKED should return to UNLOCKED safely.
My understanding is that this is a sample driver implementation bug - missing
NULL guard before MMIO teardown.
A follow-up question: do you prefer current design and each device
security TSM driver is responsible for MMIO check, or should tsm/core
adds a NULL guard to avoid potential crash?
Regards,
Yi Lai
> +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
* Re: [PATCH 2/2] x86/tdx: Accept hotplugged memory before online
From: David Hildenbrand (Arm) @ 2026-03-27 8:49 UTC (permalink / raw)
To: Chenyi Qiang, Marc-André Lureau, Edgecombe, Rick P
Cc: bp@alien8.de, kas@kernel.org, hpa@zytor.com, mingo@redhat.com,
x86@kernel.org, tglx@kernel.org, dave.hansen@linux.intel.com,
kvm@vger.kernel.org, linux-coco@lists.linux.dev,
linux-kernel@vger.kernel.org, Bonzini, Paolo
In-Reply-To: <da98d671-eb7e-4e78-97b0-fedeb9d01f69@intel.com>
On 3/27/26 04:05, Chenyi Qiang wrote:
>
>
> On 3/25/2026 6:29 PM, Marc-André Lureau wrote:
>> Hi
>>
>> On Wed, Mar 25, 2026 at 2:04 AM Edgecombe, Rick P
>> <rick.p.edgecombe@intel.com> wrote:
>>>
>>>
>>> Does this depend on patch 1 somehow?
>>
>> Yes, if I plug, unplug and plug again I get this without PATCH 1:
>> [root@rhel10-server ~]# [ 5707.392231] virtio_mem virtio5: plugged
>> size: 0x80000000
>> [ 5707.395583] virtio_mem virtio5: requested size: 0x0
>>
>> [root@rhel10-server ~]# [ 5714.648501] virtio_mem virtio5: plugged
>> size: 0x2e00000
>> [ 5714.651808] virtio_mem virtio5: requested size: 0x80000000
>> [ 5714.676296] tdx: Failed to accept memory [0x108000000, 0x110000000)
>> [ 5714.683980] tdx: Failed to accept memory [0x110000000, 0x118000000)
>> [ 5714.686997] tdx: Failed to accept memory [0x140000000, 0x148000000)
>> [ 5714.689989] tdx: Failed to accept memory [0x128000000, 0x130000000)
>> [ 5714.694981] tdx: Failed to accept memory [0x148000000, 0x150000000)
>> [ 5714.704064] tdx: Failed to accept memory [0x138000000, 0x140000000)
>> [ 5714.710144] tdx: Failed to accept memory [0x118000000, 0x120000000)
>> [ 5714.722532] tdx: Failed to accept memory [0x130000000, 0x138000000)
>>
>> My understanding is that QEMU should eventually unplug the memory and
>> PUNCH_HOLE then KVM should TDH.MEM.PAGE.REMOVE, but that doesn't seem
>> to happen.
>
> I guess it doesn't happen because virtio-mem in QEMU only PUNCH_HOLE the
> shared memory by ram_block_discard_range() but it doesn't touch the private
> memory which should be discarded by ram_block_discard_guest_memfd_range().
>
> Is this strictly required? According to the specification,
So far nobody specified how virtio-mem should behave in a CoCo environment.
I assume that we need enhancements on the driver and the device side.
In Linux, we should not be accepting memory during memory
onlining/offlining through notifiers, as we might only hot(un)plug parts
of a memory block etc.
We need some explicit calls into the core before we hand hotplugged
memory to the core, and before we hand back unplugged memory to the device.
In QEMU, I would similarly assume that we might have to perform some
additional work when converting memory blocks. *maybe* that would just
be done by the guest that converts memory from private to shared before
unplug etc.
--
Cheers,
David
^ permalink raw reply
* Re: [PATCH 2/2] x86/tdx: Accept hotplugged memory before online
From: Yan Zhao @ 2026-03-27 8:28 UTC (permalink / raw)
To: Marc-André Lureau
Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H. Peter Anvin, Kiryl Shutsemau, Rick Edgecombe, Chenyi Qiang,
linux-kernel, linux-coco, kvm
In-Reply-To: <20260324-tdx-hotplug-fixes-v1-2-8f29f2c17278@redhat.com>
On Tue, Mar 24, 2026 at 07:21:48PM +0400, Marc-André Lureau wrote:
> In TDX guests, hotplugged memory (e.g., via virtio-mem) is never
> accepted before use. The first access triggers a fatal "SEPT entry in
> PENDING state" EPT violation and KVM terminates the guest.
>
> Fix this by registering a MEM_GOING_ONLINE memory hotplug notifier that
> calls tdx_accept_memory() for the range being onlined.
>
> The notifier returns NOTIFY_BAD on acceptance failure, preventing the
> memory from going online.
>
> Assisted-by: Claude:claude-opus-4-6
> Reported-by: Chenyi Qiang <chenyi.qiang@intel.com>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> ---
> arch/x86/coco/tdx/tdx.c | 38 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 38 insertions(+)
>
> diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
> index 7b2833705d475..89f90bc303258 100644
> --- a/arch/x86/coco/tdx/tdx.c
> +++ b/arch/x86/coco/tdx/tdx.c
> @@ -8,6 +8,7 @@
> #include <linux/export.h>
> #include <linux/io.h>
> #include <linux/kexec.h>
> +#include <linux/memory.h>
> #include <asm/coco.h>
> #include <asm/tdx.h>
> #include <asm/vmx.h>
> @@ -1194,3 +1195,40 @@ void __init tdx_early_init(void)
>
> tdx_announce();
> }
> +
> +#ifdef CONFIG_MEMORY_HOTPLUG
> +static int tdx_guest_memory_notifier(struct notifier_block *nb,
> + unsigned long action, void *v)
> +{
> + struct memory_notify *mn = v;
> + phys_addr_t start, end;
> +
> + if (action != MEM_GOING_ONLINE)
> + return NOTIFY_OK;
> +
> + start = PFN_PHYS(mn->start_pfn);
> + end = start + PFN_PHYS(mn->nr_pages);
> +
> + if (!tdx_accept_memory(start, end)) {
> + pr_err("Failed to accept memory [0x%llx, 0x%llx)\n",
> + (unsigned long long)start,
> + (unsigned long long)end);
> + return NOTIFY_BAD;
> + }
> +
> + return NOTIFY_OK;
> +}
> +
> +static struct notifier_block tdx_guest_memory_nb = {
> + .notifier_call = tdx_guest_memory_notifier,
> +};
> +
> +static int __init tdx_guest_memory_init(void)
> +{
> + if (!cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
> + return 0;
> +
> + return register_memory_notifier(&tdx_guest_memory_nb);
> +}
If I read the code correctly,
online_pages
1. memory_notify(MEM_GOING_ONLINE, &mem_arg);
2. online_pages_range(pfn, nr_pages);
(*online_page_callback)(page, order);
generic_online_page
__free_pages_core(page, order, MEMINIT_HOTPLUG);
In __free_pages_core(), there's accept_memory() already:
if (page_contains_unaccepted(page, order)) {
if (order == MAX_PAGE_ORDER && __free_unaccepted(page))
return;
accept_memory(page_to_phys(page), PAGE_SIZE << order);
}
__free_unaccepted() also adds the pages to the unaccepted_pages list, so
cond_accept_memory() will accept the memory later:
So, is it because the virtio mem sets online_page_callback to
virtio_mem_online_page_cb, which doesn't invoke __free_pages_core() properly?
Or am I missing something that makes the memory notifier approach necessary?
Thanks
Yan
> +core_initcall(tdx_guest_memory_init);
> +#endif
>
> --
> 2.53.0
>
>
^ permalink raw reply
* COCONUT-SVSM Development Release v2026.03-devel
From: Jörg Rödel @ 2026-03-27 9:21 UTC (permalink / raw)
To: coconut-svsm, linux-coco
Hi,
The COCONUT-SVSM development release for March is now tagged. It features 48
non-merge commits since the February release, among them changes from
first-time contributors.
The highlights of this release are:
- More improvements to the boot flow to get closer to a minimal stage2
implementation.
- Memory management improvements.
- Lots of changes to our CI workflows to improve their security, speed,
and coverage.
The shortlog is attached. Happy testing!
-Joerg
Carlos López (14):
mm/alloc: remove recursion from HeapMemoryRegion::free_page_order()
mm/alloc: remove recursion from HeapMemoryRegion::refill_page_list()
mm/alloc/tests: verify error variant in test_page_alloc_oom()
Makefile: add Miri target
Documentation: INSTALL: document --no-detdev option
Documentation: add TESTING.md
kernel: mm/pgtable: homogenize PageTable::map_4k()
kernel: mm/pgtable: homogenize PageTable::map_2m()
boot: bootimg/elf: page-align kernel ELF size
virtio-drivers: remove enumn dependency
libtcgtpm: disable bindgen unneeded features
github/workflows: do not add rust-src component
github/workflows: run builds in parallel
github/workflows: update actions to Node.js 24
Joerg Roedel (7):
github/workflows: Implement security best practices
github/workflows: Add a dependency review workflow
docs: Document GitHub workflow security requirements
workflows/publish-docs: Limit permissions even more
workflows/manual-verify: Do not use pre-built verusfmt
workflows/publish-docs: Install mkdocs from packages
COCONUT-SVSM Release 2026.03-devel
Jon Lange (16):
boot_params: remove vtom from boot parameter block
stage2: make VTOM a register parameter
boot_params: remove stage1 info from boot params
stage1: remove non-TDX logic
sev: remove SEV metadata generation
Merge pull request #989 from 00xc/mm/pgtable/map_4k
idt: allocate kernel IDT in the boot image
kernel: enable suppression of VTOM in the SVSM
Merge pull request #1003 from joergroedel/gh-workflows
bootimg: map the kernel heap with 2 MB pages
kernel: simplify memory launch parameters
svsm: dynamically expand the kernel region from the kernel
Merge pull request #1007 from luigix25/makefile_cleanup
workflows: move CI test artifacts to a separate directory
svsm: fix heap size calculation after kernel region expansion
svsm: validate memory correctly during kernel region expansion
Jörg Rödel (15):
Merge pull request #970 from msft-jlange/stage1
Merge pull request #967 from 00xc/mm/alloc
Merge pull request #993 from TanyaAgarwal25/tanya/add-nocc-doc
Merge pull request #995 from 00xc/boot/bootimg/align_heap
Merge pull request #996 from luigix25/add_missing_spdx
Merge pull request #991 from osteffenrh/igvmmeasure-error-msg
Merge pull request #999 from luigix25/remove_sudo
Merge pull request #1000 from n-ramacciotti/update_gdbstub
Merge pull request #1008 from msft-jlange/no_vtom
Merge pull request #1001 from 00xc/ci/parallel-v2
Merge pull request #1009 from nhandt64/chore/ignore-vscode
Merge pull request #1017 from msft-jlange/qemu_ci
Merge pull request #1016 from 00xc/ci/actions-node24
Merge pull request #1013 from joergroedel/gh-workflows
Merge pull request #1019 from msft-jlange/heap_info
Luigi Leonardi (4):
block: remove `VirtIOBlkDevice` abstraction
workspace: add missing SPDX headers
scripts/launch_guest: avoid sudo when using TCG acceleration
Makefile: remove broken targets
Nhan Dang (1):
gitignore: ignore .vscode folder
Nicola Ramacciotti (1):
cargo.toml: Update gdbstub to 0.7.10
Oliver Steffen (5):
igvmmeasure: Report the value of a wrong CR0 setting
igvmmeasure: Report unexpected VMSA GPA values
igvmmeasure: KVM check: allow real-mode
igvmmeasure: Split off KVM check errors
igvmmeasure: Reformat error message
Peter Fang (1):
Merge pull request #1005 from msft-jlange/dynamic_heap
Stefano Garzarella (4):
Merge pull request #979 from 00xc/docs/dev/testing
Merge pull request #980 from luigix25/blk_refactor
Merge pull request #983 from TanyaAgarwal25/main
Merge pull request #985 from TanyaAgarwal25/tanya/use-prefix
Tanya Agarwal (3):
doc/INSTALL: fix PKG_CONFIG_PATH typo in configure command
doc/INSTALL: simplify QEMU build instructions
docs: add native mode instructions to run SVSM without coco hardware
^ permalink raw reply
* Re: [PATCH v5 0/2] dma-buf: heaps: system: add an option to allocate explicitly shared/decrypted memory
From: Marek Szyprowski @ 2026-03-27 9:38 UTC (permalink / raw)
To: Jiri Pirko, dri-devel, linaro-mm-sig, iommu, linux-media
Cc: sumit.semwal, benjamin.gaignard, Brian.Starkey, jstultz,
tjmercier, christian.koenig, robin.murphy, jgg, leon,
sean.anderson, ptesarik, catalin.marinas, aneesh.kumar,
suzuki.poulose, steven.price, thomas.lendacky, john.allen,
ashish.kalra, suravee.suthikulpanit, linux-coco
In-Reply-To: <20260325192352.437608-1-jiri@resnulli.us>
On 25.03.2026 20:23, Jiri Pirko wrote:
> From: Jiri Pirko <jiri@nvidia.com>
>
> Confidential computing (CoCo) VMs/guests, such as AMD SEV and Intel TDX,
> run with private/encrypted memory which creates a challenge
> for devices that do not support DMA to it (no TDISP support).
>
> For kernel-only DMA operations, swiotlb bounce buffering provides a
> transparent solution by copying data through shared memory.
> However, the only way to get this memory into userspace is via the DMA
> API's dma_alloc_pages()/dma_mmap_pages() type interfaces which limits
> the use of the memory to a single DMA device, and is incompatible with
> pin_user_pages().
>
> These limitations are particularly problematic for the RDMA subsystem
> which makes heavy use of pin_user_pages() and expects flexible memory
> usage between many different DMA devices.
>
> This patch series enables userspace to explicitly request shared
> (decrypted) memory allocations from new dma-buf system_cc_shared heap.
> Userspace can mmap this memory and pass the dma-buf fd to other
> existing importers such as RDMA or DRM devices to access the
> memory. The DMA API is improved to allow the dma heap exporter to DMA
> map the shared memory to each importing device.
>
> Based on dma-mapping-for-next e7442a68cd1ee797b585f045d348781e9c0dde0d
I would like to merge this to dma-mapping-next, but I feel a bit
uncomfortable with my lack of knowledge about CoCo and friends. Could
those who know a bit more about it provide some Reviewed-by tags?
Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland
^ permalink raw reply
* Re: [PATCH v2 09/19] PCI/TSM: Support creating encrypted MMIO descriptors via TDISP Report
From: Jason Gunthorpe @ 2026-03-27 11:49 UTC (permalink / raw)
To: Alexey Kardashevskiy
Cc: Xu Yilun, Aneesh Kumar K.V, Dan Williams, linux-coco, linux-pci,
gregkh, bhelgaas, alistair23, lukas, Arnd Bergmann
In-Reply-To: <fa1c6e1e-068c-46d7-a623-58c225bb03f4@amd.com>
On Fri, Mar 27, 2026 at 10:38:15AM +1100, Alexey Kardashevskiy wrote:
>
>
> On 24/3/26 05:20, Jason Gunthorpe wrote:
> > On Mon, Mar 16, 2026 at 04:19:30PM +1100, Alexey Kardashevskiy wrote:
> >
> > > and btw this only works if the entity generating the MMIO reporting
> > > offset (==TSM) knows about BARs sizes, which is not the case for AMD
> > > - the FW has no access to the config space (so the HV needs to feed
> > > this to the FW? may be). Thanks,
> >
> > Then your platform just shouldn't use the mmio offset feature. Set it
> > to 0 always.
>
> pcie r7, Table 11-16 TDI Report Structure, MMIO_RANGE:
>
> "Each MMIO Range of the TDI is reported with the MMIO reporting offset added."
>
> My english struggles here - can the above be interpreted as "Each reported MMIO Range ..."?
>
> as if it is each (except msix), then I know where msix is and can
> amend the report inside the VM if msix is not locked. Thanks,
To do this you must be convert between the offset'd and phys_addr_t
versions otherwise you have no idea where the translated ones fall
within the BAR, so you can't figure out if msix is covered or not.
Jason
^ permalink raw reply
* Re: [PATCH v5 0/2] dma-buf: heaps: system: add an option to allocate explicitly shared/decrypted memory
From: Jason Gunthorpe @ 2026-03-27 12:10 UTC (permalink / raw)
To: Marek Szyprowski, T.J. Mercier
Cc: Jiri Pirko, dri-devel, linaro-mm-sig, iommu, linux-media,
sumit.semwal, benjamin.gaignard, Brian.Starkey, jstultz,
tjmercier, christian.koenig, robin.murphy, leon, sean.anderson,
ptesarik, catalin.marinas, aneesh.kumar, suzuki.poulose,
steven.price, thomas.lendacky, john.allen, ashish.kalra,
suravee.suthikulpanit, linux-coco
In-Reply-To: <f2047cd7-91a8-4f6a-b6b9-0e4f143f6854@samsung.com>
On Fri, Mar 27, 2026 at 10:38:10AM +0100, Marek Szyprowski wrote:
> On 25.03.2026 20:23, Jiri Pirko wrote:
> > From: Jiri Pirko <jiri@nvidia.com>
> >
> > Confidential computing (CoCo) VMs/guests, such as AMD SEV and Intel TDX,
> > run with private/encrypted memory which creates a challenge
> > for devices that do not support DMA to it (no TDISP support).
> >
> > For kernel-only DMA operations, swiotlb bounce buffering provides a
> > transparent solution by copying data through shared memory.
> > However, the only way to get this memory into userspace is via the DMA
> > API's dma_alloc_pages()/dma_mmap_pages() type interfaces which limits
> > the use of the memory to a single DMA device, and is incompatible with
> > pin_user_pages().
> >
> > These limitations are particularly problematic for the RDMA subsystem
> > which makes heavy use of pin_user_pages() and expects flexible memory
> > usage between many different DMA devices.
> >
> > This patch series enables userspace to explicitly request shared
> > (decrypted) memory allocations from new dma-buf system_cc_shared heap.
> > Userspace can mmap this memory and pass the dma-buf fd to other
> > existing importers such as RDMA or DRM devices to access the
> > memory. The DMA API is improved to allow the dma heap exporter to DMA
> > map the shared memory to each importing device.
> >
> > Based on dma-mapping-for-next e7442a68cd1ee797b585f045d348781e9c0dde0d
>
> I would like to merge this to dma-mapping-next, but I feel a bit
> uncomfortable with my lack of knowledge about CoCo and friends. Could
> those who know a bit more about it provide some Reviewed-by tags?
I'm confident in the CC stuff, I was hoping to see someone from dmabuf
heap land ack that the uAPI design is OK.. TJ?
Jason
^ permalink raw reply
* Re: SVSM Development Call March 25, 2026
From: Jörg Rödel @ 2026-03-27 12:30 UTC (permalink / raw)
To: coconut-svsm, linux-coco
In-Reply-To: <iuafzrd25l3whbifc3m7tcxf2bq3hqe4bymuwrqhtpmcujipfc@2qxd6c547gz2>
Meeting minutes are ready for review:
https://github.com/coconut-svsm/governance/pull/101
-Joerg
^ permalink raw reply
* [PATCH v2 00/31] PCI/TSM: PCIe Link Encryption Establishment via TDX platform services
From: Xu Yilun @ 2026-03-27 16:01 UTC (permalink / raw)
To: linux-coco, linux-pci, dan.j.williams, x86
Cc: chao.gao, dave.jiang, baolu.lu, yilun.xu, yilun.xu,
zhenzhong.duan, kvm, rick.p.edgecombe, dave.hansen, kas,
xiaoyao.li, vishal.l.verma, linux-kernel
This series is based on mainline v7.0-rc2 and targets v7.1 (quite
aggressive though). The merge path will be through tsm.git with tip.git
acks where needed. I know there are several parallel series on the fly,
so Dave you can wait for Dan to review, or ack/nak as you have time,
thanks. No KVM change, no acks from kvm.git is needed.
== Overview ==
This series adds a PCI/TSM low-level driver implementation for TDX
Connect (the TEE I/O architecture for Intel platforms). PCI/TSM is the
Linux PCI core subsystem [1][2] that supports Link Encryption & trust
establishment between CoCo-VM and assigned devices, allowing CoCo-VM to
accept devices for private memory access (private DMA). This series
only implements Link Encryption. It is a pre-requisite for trusted
device assignment in TDX system.
Two protocols, SPDM (Security Protocol and Data Model) and PCI
IDE (Integrity and Data Encryption) work together to establish the Link
Encryption. SPDM creates trust on untrusted transit for key exchanging.
IDE performs the actual real-time encryption for data traffic. In TSM
world, they are managed by secure firmwares, e.g. TDX Module.
To manage these protocols, TDX Module introduces Extensions to support
long running / hard-irq preemptible flows inside. Host invokes these
flows via Extension-SEAMCALLs.
This series has 2 distinct parts:
Patches 1-13: TDX core cleanups and TDX Module Extensions enabling
Patches 14-31: tdx_host TSM driver for PCIe Link Encryption
[1]: https://lore.kernel.org/linux-coco/20251031212902.2256310-1-dan.j.williams@intel.com/
[2]: https://lore.kernel.org/linux-coco/20251105040055.2832866-1-dan.j.williams@intel.com/
== Merge notes ==
- Merge conflicts with parallel series:
Sean's VMXON: https://lore.kernel.org/all/20260214012702.2368778-1-seanjc@google.com/
Chao's runtime update: https://lore.kernel.org/all/20260326084448.29947-1-chao.gao@intel.com/
- Picked several patches from parallel series:
Patch 1: https://lore.kernel.org/all/20260323-fuller_tdx_kexec_support-v2-1-87a36409e051@intel.com/
Patch 14: https://lore.kernel.org/all/20260303000207.1836586-2-dan.j.williams@intel.com/
Patch 15: https://lore.kernel.org/all/20260326084448.29947-3-chao.gao@intel.com/
== Changelog ==
v2:
- Subject change. previously it was:
"PCI/TSM: TDX Connect: SPDM Session and IDE Establishment"
- Remove __free() for core TDX and refactor all tdx_ext functions
- Use kzalloc(PAGE_SIZE, ...) instead of alloc_page() in TDX core
- Check feature0 support before reading optional global metadata
- Split the TDX Module Extensions enabling into small patches
- Enable TDX Module Extensions along with Basic TDX enabling
- Refactor SEAMCALL version handling
- For tdx_page_array, make page allocation method configurable
- For TDX Module Extensions, use contiguous page allocation
- For IOMMU_MT, use a custom page allocation
- Print TDX Extensions memory usage
- Various Changelog & comments refine
v1: https://lore.kernel.org/all/20251117022311.2443900-1-yilun.xu@linux.intel.com/
- No tdx_enable() needed in tdx-host
- Simplify tdx_page_array kAPI, no singleton mode input
- Refactor the handling of TDX_INTERRUPTED_RESUMABLE
- Refine the usage of scope-based cleanup in tdx-host
- Set nr_stream_id in tdx-host, not in PCI ACPI initialization
- Use KEYP table + ECAP bit50 to decide Domain ID reservation
- Refactor IDE Address Association Register setup
- Remove prototype patches
- Refactor tdx_enable_ext() locking because of Sean's change
- Pick ACPICA KEYP patch from ACPICA repo
- Select TDX Connect feature for TDH.SYS.CONFIG, remove temporary
solution for TDH.SYS.INIT
- Use Rick's tdx_errno.h movement patch [6]
- Factor out scope-based cleanup patches in mm
- Remove redunant header files, add header files only when first used
- Use dev_err_probe() when possible
- keyp_info_match() refactor
- Use bitfield.h macros for PAGE_LIST_INFO & HPA_ARRAY_T raw value
- Remove reserved fields for spdm_config_info_t
- Simplify return for tdh_ide_stream_block()
- Other small fixes for Jonathan's comments
RFC: https://lore.kernel.org/linux-coco/20250919142237.418648-1-dan.j.williams@intel.com/
Chao Gao (1):
coco/tdx-host: Introduce a "tdx_host" device
Dan Williams (1):
PCI/TSM: Report active IDE streams per host bridge
Dave Jiang (1):
acpi: Add KEYP support to fw_table parsing
Kiryl Shutsemau (1):
x86/tdx: Move all TDX error defines into <asm/shared/tdx_errno.h>
Lu Baolu (2):
iommu/vt-d: Cache max domain ID to avoid redundant calculation
iommu/vt-d: Reserve the MSB domain ID bit for the TDX module
Xu Yilun (21):
x86/virt/tdx: Move bit definitions of TDX_FEATURES0 to public header
x86/virt/tdx: Add tdx_page_array helpers for new TDX Module objects
x86/virt/tdx: Support allocating contiguous pages for tdx_page_array
x86/virt/tdx: Extend tdx_page_array to support IOMMU_MT
x86/virt/tdx: Read global metadata for TDX Module Extensions/Connect
x86/virt/tdx: Embed version info in SEAMCALL leaf function definitions
x86/virt/tdx: Configure TDX Module with optional TDX Connect feature
x86/virt/tdx: Move tdx_clflush_page() up in the file
x86/virt/tdx: Add extra memory to TDX Module for Extensions
x86/virt/tdx: Make TDX Module initialize Extensions
x86/virt/tdx: Enable the Extensions after basic TDX Module init
x86/virt/tdx: Extend tdx_clflush_page() to handle compound pages
coco/tdx-host: Support Link TSM for TDX host
x86/virt/tdx: Add a helper to loop on TDX_INTERRUPTED_RESUMABLE
iommu/vt-d: Export a helper to do function for each dmar_drhd_unit
coco/tdx-host: Setup all trusted IOMMUs on TDX Connect init
mm: Add __free() support for __free_page()
coco/tdx-host: Parse ACPI KEYP table to init IDE for PCI host bridges
x86/virt/tdx: Add SEAMCALL wrappers for IDE stream management
coco/tdx-host: Implement IDE stream setup/teardown
coco/tdx-host: Finally enable SPDM session and IDE Establishment
Zhenzhong Duan (4):
x86/virt/tdx: Add SEAMCALL wrappers for trusted IOMMU setup and clear
coco/tdx-host: Add a helper to exchange SPDM messages through DOE
x86/virt/tdx: Add SEAMCALL wrappers for SPDM management
coco/tdx-host: Implement SPDM session setup
drivers/virt/coco/Kconfig | 2 +
drivers/virt/coco/tdx-host/Kconfig | 16 +
drivers/virt/coco/Makefile | 1 +
drivers/virt/coco/tdx-host/Makefile | 1 +
Documentation/ABI/testing/sysfs-class-tsm | 13 +
arch/x86/include/asm/shared/tdx.h | 1 +
.../vmx => include/asm/shared}/tdx_errno.h | 30 +-
arch/x86/include/asm/tdx.h | 95 +-
arch/x86/include/asm/tdx_global_metadata.h | 14 +
arch/x86/kvm/vmx/tdx.h | 1 -
arch/x86/virt/vmx/tdx/tdx.h | 42 +-
drivers/iommu/intel/iommu.h | 2 +
include/linux/acpi.h | 3 +
include/linux/dmar.h | 2 +
include/linux/fw_table.h | 1 +
include/linux/gfp.h | 1 +
include/linux/pci-ide.h | 4 +
include/linux/tsm.h | 3 +
arch/x86/virt/vmx/tdx/tdx.c | 839 ++++++++++++++-
arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 36 +
drivers/acpi/tables.c | 12 +-
drivers/iommu/intel/dmar.c | 67 ++
drivers/iommu/intel/iommu.c | 10 +-
drivers/pci/ide.c | 9 +-
drivers/virt/coco/tdx-host/tdx-host.c | 952 ++++++++++++++++++
drivers/virt/coco/tsm-core.c | 97 ++
lib/fw_table.c | 9 +
27 files changed, 2202 insertions(+), 61 deletions(-)
create mode 100644 drivers/virt/coco/tdx-host/Kconfig
create mode 100644 drivers/virt/coco/tdx-host/Makefile
rename arch/x86/{kvm/vmx => include/asm/shared}/tdx_errno.h (61%)
create mode 100644 drivers/virt/coco/tdx-host/tdx-host.c
base-commit: 11439c4635edd669ae435eec308f4ab8a0804808
--
2.25.1
^ permalink raw reply
* [PATCH v2 01/31] x86/tdx: Move all TDX error defines into <asm/shared/tdx_errno.h>
From: Xu Yilun @ 2026-03-27 16:01 UTC (permalink / raw)
To: linux-coco, linux-pci, dan.j.williams, x86
Cc: chao.gao, dave.jiang, baolu.lu, yilun.xu, yilun.xu,
zhenzhong.duan, kvm, rick.p.edgecombe, dave.hansen, kas,
xiaoyao.li, vishal.l.verma, linux-kernel
In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com>
From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Today there are two separate locations where TDX error codes are defined:
arch/x86/include/asm/tdx.h
arch/x86/kvm/vmx/tdx_errno.h
They have some overlap that is already defined similarly. Reduce the
duplication and prepare to introduce some helpers for these error codes in
the central place by unifying them. Join them at:
asm/shared/tdx_errno.h
...and update the headers that contained the duplicated definitions to
include the new unified header.
"asm/shared" is used for sharing TDX code between the early compressed
code and the normal kernel code. While the compressed code for the guest
doesn't use these error code header definitions today, it does make the
types of calls that return the values they define. So place the defines in
"shared" location so that it can, but leave such cleanups for future
changes.
Also, adjust BITUL() -> _BITULL() to address 32 bit build errors after the
move.
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
[enhance log]
Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
Reviewed-by: Chao Gao <chao.gao@intel.com>
---
arch/x86/include/asm/shared/tdx.h | 1 +
.../vmx => include/asm/shared}/tdx_errno.h | 28 +++++++++++++++----
arch/x86/include/asm/tdx.h | 21 --------------
arch/x86/kvm/vmx/tdx.h | 1 -
4 files changed, 23 insertions(+), 28 deletions(-)
rename arch/x86/{kvm/vmx => include/asm/shared}/tdx_errno.h (64%)
diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h
index 8bc074c8d7c6..6a1646fc2b2f 100644
--- a/arch/x86/include/asm/shared/tdx.h
+++ b/arch/x86/include/asm/shared/tdx.h
@@ -4,6 +4,7 @@
#include <linux/bits.h>
#include <linux/types.h>
+#include <asm/shared/tdx_errno.h>
#define TDX_HYPERCALL_STANDARD 0
diff --git a/arch/x86/kvm/vmx/tdx_errno.h b/arch/x86/include/asm/shared/tdx_errno.h
similarity index 64%
rename from arch/x86/kvm/vmx/tdx_errno.h
rename to arch/x86/include/asm/shared/tdx_errno.h
index 6ff4672c4181..8bf6765cf082 100644
--- a/arch/x86/kvm/vmx/tdx_errno.h
+++ b/arch/x86/include/asm/shared/tdx_errno.h
@@ -1,14 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/* architectural status code for SEAMCALL */
-
-#ifndef __KVM_X86_TDX_ERRNO_H
-#define __KVM_X86_TDX_ERRNO_H
+#ifndef _ASM_X86_SHARED_TDX_ERRNO_H
+#define _ASM_X86_SHARED_TDX_ERRNO_H
+#include <asm/trapnr.h>
+/* Upper 32 bit of the TDX error code encodes the status */
#define TDX_SEAMCALL_STATUS_MASK 0xFFFFFFFF00000000ULL
/*
- * TDX SEAMCALL Status Codes (returned in RAX)
+ * TDX Status Codes (returned in RAX)
*/
+#define TDX_SUCCESS 0ULL
#define TDX_NON_RECOVERABLE_VCPU 0x4000000100000000ULL
#define TDX_NON_RECOVERABLE_TD 0x4000000200000000ULL
#define TDX_NON_RECOVERABLE_TD_NON_ACCESSIBLE 0x6000000500000000ULL
@@ -17,6 +18,7 @@
#define TDX_OPERAND_INVALID 0xC000010000000000ULL
#define TDX_OPERAND_BUSY 0x8000020000000000ULL
#define TDX_PREVIOUS_TLB_EPOCH_BUSY 0x8000020100000000ULL
+#define TDX_RND_NO_ENTROPY 0x8000020300000000ULL
#define TDX_PAGE_METADATA_INCORRECT 0xC000030000000000ULL
#define TDX_VCPU_NOT_ASSOCIATED 0x8000070200000000ULL
#define TDX_KEY_GENERATION_FAILED 0x8000080000000000ULL
@@ -28,6 +30,20 @@
#define TDX_EPT_ENTRY_STATE_INCORRECT 0xC0000B0D00000000ULL
#define TDX_METADATA_FIELD_NOT_READABLE 0xC0000C0200000000ULL
+/*
+ * SW-defined error codes.
+ *
+ * Bits 47:40 == 0xFF indicate Reserved status code class that never used by
+ * TDX module.
+ */
+#define TDX_ERROR _BITULL(63)
+#define TDX_NON_RECOVERABLE _BITULL(62)
+#define TDX_SW_ERROR (TDX_ERROR | GENMASK_ULL(47, 40))
+#define TDX_SEAMCALL_VMFAILINVALID (TDX_SW_ERROR | _ULL(0xFFFF0000))
+
+#define TDX_SEAMCALL_GP (TDX_SW_ERROR | X86_TRAP_GP)
+#define TDX_SEAMCALL_UD (TDX_SW_ERROR | X86_TRAP_UD)
+
/*
* TDX module operand ID, appears in 31:0 part of error code as
* detail information
@@ -37,4 +53,4 @@
#define TDX_OPERAND_ID_SEPT 0x92
#define TDX_OPERAND_ID_TD_EPOCH 0xa9
-#endif /* __KVM_X86_TDX_ERRNO_H */
+#endif /* _ASM_X86_SHARED_TDX_ERRNO_H */
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 6b338d7f01b7..e040e0467ae4 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -9,29 +9,8 @@
#include <asm/errno.h>
#include <asm/ptrace.h>
-#include <asm/trapnr.h>
#include <asm/shared/tdx.h>
-/*
- * SW-defined error codes.
- *
- * Bits 47:40 == 0xFF indicate Reserved status code class that never used by
- * TDX module.
- */
-#define TDX_ERROR _BITUL(63)
-#define TDX_NON_RECOVERABLE _BITUL(62)
-#define TDX_SW_ERROR (TDX_ERROR | GENMASK_ULL(47, 40))
-#define TDX_SEAMCALL_VMFAILINVALID (TDX_SW_ERROR | _UL(0xFFFF0000))
-
-#define TDX_SEAMCALL_GP (TDX_SW_ERROR | X86_TRAP_GP)
-#define TDX_SEAMCALL_UD (TDX_SW_ERROR | X86_TRAP_UD)
-
-/*
- * TDX module SEAMCALL leaf function error codes
- */
-#define TDX_SUCCESS 0ULL
-#define TDX_RND_NO_ENTROPY 0x8000020300000000ULL
-
#ifndef __ASSEMBLER__
#include <uapi/asm/mce.h>
diff --git a/arch/x86/kvm/vmx/tdx.h b/arch/x86/kvm/vmx/tdx.h
index 45b5183ccb36..ce2720a028ad 100644
--- a/arch/x86/kvm/vmx/tdx.h
+++ b/arch/x86/kvm/vmx/tdx.h
@@ -3,7 +3,6 @@
#define __KVM_X86_VMX_TDX_H
#include "tdx_arch.h"
-#include "tdx_errno.h"
#ifdef CONFIG_KVM_INTEL_TDX
#include "common.h"
--
2.25.1
^ permalink raw reply related
* [PATCH v2 02/31] x86/virt/tdx: Move bit definitions of TDX_FEATURES0 to public header
From: Xu Yilun @ 2026-03-27 16:01 UTC (permalink / raw)
To: linux-coco, linux-pci, dan.j.williams, x86
Cc: chao.gao, dave.jiang, baolu.lu, yilun.xu, yilun.xu,
zhenzhong.duan, kvm, rick.p.edgecombe, dave.hansen, kas,
xiaoyao.li, vishal.l.verma, linux-kernel
In-Reply-To: <20260327160132.2946114-1-yilun.xu@linux.intel.com>
Move bit definitions of TDX_FEATURES0 to TDX core public header.
Kernel users get TDX_FEATURES0 bitmap via tdx_get_sysinfo(). It is
reasonable to also public the definitions of each bit. TDX Connect (a
new TDX feature to enable Trusted I/O virtualization) will add new bits
and check them in separate kernel modules.
Take the opportunity to change its type to BIT_ULL since TDX_FEATURES0
is explicitly defined as 64-bit in both TDX Module Specification and
TDX core code.
Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
---
arch/x86/include/asm/tdx.h | 4 ++++
arch/x86/virt/vmx/tdx/tdx.h | 3 ---
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index e040e0467ae4..65c4da396450 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -127,6 +127,10 @@ static __always_inline u64 sc_retry(sc_func_t func, u64 fn,
int tdx_cpu_enable(void);
int tdx_enable(void);
const char *tdx_dump_mce_info(struct mce *m);
+
+/* Bit definitions of TDX_FEATURES0 metadata field */
+#define TDX_FEATURES0_NO_RBP_MOD BIT_ULL(18)
+
const struct tdx_sys_info *tdx_get_sysinfo(void);
int tdx_guest_keyid_alloc(void);
diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h
index 82bb82be8567..c641b4632826 100644
--- a/arch/x86/virt/vmx/tdx/tdx.h
+++ b/arch/x86/virt/vmx/tdx/tdx.h
@@ -84,9 +84,6 @@ struct tdmr_info {
DECLARE_FLEX_ARRAY(struct tdmr_reserved_area, reserved_areas);
} __packed __aligned(TDMR_INFO_ALIGNMENT);
-/* Bit definitions of TDX_FEATURES0 metadata field */
-#define TDX_FEATURES0_NO_RBP_MOD BIT(18)
-
/*
* Do not put any hardware-defined TDX structure representations below
* this comment!
--
2.25.1
^ 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;
as well as URLs for NNTP newsgroup(s).