[PATCH kernel 9/9] pci: Allow encrypted MMIO mapping via sysfs

From: Alexey Kardashevskiy

Date: Wed Feb 25 2026 - 00:44:48 EST


Add another resource#d_enc to allow mapping MMIO as
an encrypted/private region.

Unlike resourceN_wc, the node is added always as ability to
map MMIO as private depends on negotiation with the TSM which
happens quite late.

Signed-off-by: Alexey Kardashevskiy <aik@xxxxxxx>
---
include/linux/pci.h | 2 +-
drivers/pci/mmap.c | 11 +++++++-
drivers/pci/pci-sysfs.c | 27 +++++++++++++++-----
drivers/pci/proc.c | 2 +-
4 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/include/linux/pci.h b/include/linux/pci.h
index 1a31353dc109..6e258b793278 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -2217,7 +2217,7 @@ pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
*/
int pci_mmap_resource_range(struct pci_dev *dev, int bar,
struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state, int write_combine);
+ enum pci_mmap_state mmap_state, int write_combine, int enc);

#ifndef arch_can_pci_mmap_wc
#define arch_can_pci_mmap_wc() 0
diff --git a/drivers/pci/mmap.c b/drivers/pci/mmap.c
index 8da3347a95c4..90a8ab4753b8 100644
--- a/drivers/pci/mmap.c
+++ b/drivers/pci/mmap.c
@@ -23,7 +23,7 @@ static const struct vm_operations_struct pci_phys_vm_ops = {

int pci_mmap_resource_range(struct pci_dev *pdev, int bar,
struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state, int write_combine)
+ enum pci_mmap_state mmap_state, int write_combine, int enc)
{
unsigned long size;
int ret;
@@ -46,6 +46,15 @@ int pci_mmap_resource_range(struct pci_dev *pdev, int bar,

vma->vm_ops = &pci_phys_vm_ops;

+ /*
+ * Calling remap_pfn_range() directly as io_remap_pfn_range()
+ * enforces shared mapping.
+ */
+ if (enc)
+ return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ pgprot_encrypted(vma->vm_page_prot));
+
return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
vma->vm_end - vma->vm_start,
vma->vm_page_prot);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 7f9237a926c2..715407eb8b15 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1104,7 +1104,7 @@ void pci_remove_legacy_files(struct pci_bus *b)
* Use the regular PCI mapping routines to map a PCI resource into userspace.
*/
static int pci_mmap_resource(struct kobject *kobj, const struct bin_attribute *attr,
- struct vm_area_struct *vma, int write_combine)
+ struct vm_area_struct *vma, int write_combine, int enc)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
int bar = (unsigned long)attr->private;
@@ -1124,21 +1124,28 @@ static int pci_mmap_resource(struct kobject *kobj, const struct bin_attribute *a

mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;

- return pci_mmap_resource_range(pdev, bar, vma, mmap_type, write_combine);
+ return pci_mmap_resource_range(pdev, bar, vma, mmap_type, write_combine, enc);
}

static int pci_mmap_resource_uc(struct file *filp, struct kobject *kobj,
const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
- return pci_mmap_resource(kobj, attr, vma, 0);
+ return pci_mmap_resource(kobj, attr, vma, 0, 0);
}

static int pci_mmap_resource_wc(struct file *filp, struct kobject *kobj,
const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
- return pci_mmap_resource(kobj, attr, vma, 1);
+ return pci_mmap_resource(kobj, attr, vma, 1, 0);
+}
+
+static int pci_mmap_resource_enc(struct file *filp, struct kobject *kobj,
+ const struct bin_attribute *attr,
+ struct vm_area_struct *vma)
+{
+ return pci_mmap_resource(kobj, attr, vma, 0, 1);
}

static ssize_t pci_resource_io(struct file *filp, struct kobject *kobj,
@@ -1232,7 +1239,7 @@ static void pci_remove_resource_files(struct pci_dev *pdev)
}
}

-static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
+static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine, int enc)
{
/* allocate attribute structure, piggyback attribute name */
int name_len = write_combine ? 13 : 10;
@@ -1250,6 +1257,9 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
if (write_combine) {
sprintf(res_attr_name, "resource%d_wc", num);
res_attr->mmap = pci_mmap_resource_wc;
+ } else if (enc) {
+ sprintf(res_attr_name, "resource%d_enc", num);
+ res_attr->mmap = pci_mmap_resource_enc;
} else {
sprintf(res_attr_name, "resource%d", num);
if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
@@ -1310,11 +1320,14 @@ static int pci_create_resource_files(struct pci_dev *pdev)
if (!pci_resource_len(pdev, i))
continue;

- retval = pci_create_attr(pdev, i, 0);
+ retval = pci_create_attr(pdev, i, 0, 0);
/* for prefetchable resources, create a WC mappable file */
if (!retval && arch_can_pci_mmap_wc() &&
pdev->resource[i].flags & IORESOURCE_PREFETCH)
- retval = pci_create_attr(pdev, i, 1);
+ retval = pci_create_attr(pdev, i, 1, 0);
+ /* Add node for private MMIO mapping */
+ if (!retval)
+ retval = pci_create_attr(pdev, i, 0, 1);
if (retval) {
pci_remove_resource_files(pdev);
return retval;
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 9348a0fb8084..e0c0ece7f3f5 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -288,7 +288,7 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
/* Adjust vm_pgoff to be the offset within the resource */
vma->vm_pgoff -= start >> PAGE_SHIFT;
ret = pci_mmap_resource_range(dev, i, vma,
- fpriv->mmap_state, write_combine);
+ fpriv->mmap_state, write_combine, 0);
if (ret < 0)
return ret;

--
2.52.0