diff mbox series

[v2,5/7] arm64: mm: Add confidential computing hook to ioremap_prot()

Message ID 20240830130150.8568-6-will@kernel.org (mailing list archive)
State New, archived
Headers show
Series Support for running as a pKVM protected guest | expand

Commit Message

Will Deacon Aug. 30, 2024, 1:01 p.m. UTC
Confidential Computing environments such as pKVM and Arm's CCA
distinguish between shared (i.e. emulated) and private (i.e. assigned)
MMIO regions.

Introduce a hook into our implementation of ioremap_prot() so that MMIO
regions can be shared if necessary.

Signed-off-by: Will Deacon <will@kernel.org>
---
 arch/arm64/include/asm/io.h |  4 ++++
 arch/arm64/mm/ioremap.c     | 23 ++++++++++++++++++++++-
 2 files changed, 26 insertions(+), 1 deletion(-)

Comments

Catalin Marinas Sept. 2, 2024, 7:08 p.m. UTC | #1
On Fri, Aug 30, 2024 at 02:01:48PM +0100, Will Deacon wrote:
> @@ -16,7 +28,16 @@ void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
>  	if (WARN_ON(pfn_is_map_memory(__phys_to_pfn(phys_addr))))
>  		return NULL;
>  
> -	return generic_ioremap_prot(phys_addr, size, __pgprot(prot));
> +	/*
> +	 * If a hook is registered (e.g. for confidential computing
> +	 * purposes), call that now and barf if it fails.
> +	 */
> +	if (unlikely(ioremap_prot_hook) &&
> +	    WARN_ON(ioremap_prot_hook(phys_addr, size, &pgprot))) {
> +		return NULL;
> +	}
> +
> +	return generic_ioremap_prot(phys_addr, size, pgprot);
>  }
>  EXPORT_SYMBOL(ioremap_prot);

I mentioned on the CCA series, the patch is all good but we may need
something similar for io_remap_pfn_range() which uses
pgprot_decrypted() (I think it mostly matters for the pKVM case).
Will Deacon Sept. 4, 2024, 12:29 p.m. UTC | #2
On Mon, Sep 02, 2024 at 08:08:45PM +0100, Catalin Marinas wrote:
> On Fri, Aug 30, 2024 at 02:01:48PM +0100, Will Deacon wrote:
> > @@ -16,7 +28,16 @@ void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
> >  	if (WARN_ON(pfn_is_map_memory(__phys_to_pfn(phys_addr))))
> >  		return NULL;
> >  
> > -	return generic_ioremap_prot(phys_addr, size, __pgprot(prot));
> > +	/*
> > +	 * If a hook is registered (e.g. for confidential computing
> > +	 * purposes), call that now and barf if it fails.
> > +	 */
> > +	if (unlikely(ioremap_prot_hook) &&
> > +	    WARN_ON(ioremap_prot_hook(phys_addr, size, &pgprot))) {
> > +		return NULL;
> > +	}
> > +
> > +	return generic_ioremap_prot(phys_addr, size, pgprot);
> >  }
> >  EXPORT_SYMBOL(ioremap_prot);
> 
> I mentioned on the CCA series, the patch is all good but we may need
> something similar for io_remap_pfn_range() which uses
> pgprot_decrypted() (I think it mostly matters for the pKVM case).

Thanks for pointing this out.

We've not needed this on Android yet, but I think that it would be
pretty straightforward to add with an arm64 definition of
io_remap_pfn_range(). I'd just prefer to leave that until we know that
we need it -- in all likelihood a driver would MMIO_GUARD the resources
as part of its own ioremap() before remapping into userspace.

Will
diff mbox series

Patch

diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 41fd90895dfc..1ada23a6ec19 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -271,6 +271,10 @@  __iowrite64_copy(void __iomem *to, const void *from, size_t count)
  * I/O memory mapping functions.
  */
 
+typedef int (*ioremap_prot_hook_t)(phys_addr_t phys_addr, size_t size,
+				   pgprot_t *prot);
+int arm64_ioremap_prot_hook_register(const ioremap_prot_hook_t hook);
+
 #define ioremap_prot ioremap_prot
 
 #define _PAGE_IOREMAP PROT_DEVICE_nGnRE
diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
index 269f2f63ab7d..6cc0b7e7eb03 100644
--- a/arch/arm64/mm/ioremap.c
+++ b/arch/arm64/mm/ioremap.c
@@ -3,10 +3,22 @@ 
 #include <linux/mm.h>
 #include <linux/io.h>
 
+static ioremap_prot_hook_t ioremap_prot_hook;
+
+int arm64_ioremap_prot_hook_register(ioremap_prot_hook_t hook)
+{
+	if (WARN_ON(ioremap_prot_hook))
+		return -EBUSY;
+
+	ioremap_prot_hook = hook;
+	return 0;
+}
+
 void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
 			   unsigned long prot)
 {
 	unsigned long last_addr = phys_addr + size - 1;
+	pgprot_t pgprot = __pgprot(prot);
 
 	/* Don't allow outside PHYS_MASK */
 	if (last_addr & ~PHYS_MASK)
@@ -16,7 +28,16 @@  void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
 	if (WARN_ON(pfn_is_map_memory(__phys_to_pfn(phys_addr))))
 		return NULL;
 
-	return generic_ioremap_prot(phys_addr, size, __pgprot(prot));
+	/*
+	 * If a hook is registered (e.g. for confidential computing
+	 * purposes), call that now and barf if it fails.
+	 */
+	if (unlikely(ioremap_prot_hook) &&
+	    WARN_ON(ioremap_prot_hook(phys_addr, size, &pgprot))) {
+		return NULL;
+	}
+
+	return generic_ioremap_prot(phys_addr, size, pgprot);
 }
 EXPORT_SYMBOL(ioremap_prot);