Commit c86fa347 authored by Will Deacon's avatar Will Deacon
Browse files

arm64: mm: Add confidential computing hook to ioremap_prot()



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.

Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Reviewed-by: default avatarSteven Price <steven.price@arm.com>
Acked-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20240830130150.8568-6-will@kernel.org


Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent ebc59b12
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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
+22 −1
Original line number Diff line number Diff line
@@ -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);