arch/arm64/kernel/rsi.c

Source file repositories/reference/linux-study-clean/arch/arm64/kernel/rsi.c

File Facts

System
Linux kernel
Corpus path
arch/arm64/kernel/rsi.c
Extension
.c
Size
4517 bytes
Lines
177
Domain
Architecture Layer
Bucket
arch/arm64
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (rsi_set_memory_range_protected_safe(start, end)) {
			panic("Failed to set memory range to protected: %pa-%pa",
			      &start, &end);
		}
	}
}

/*
 * Check if a given PA range is Trusted (e.g., Protected memory, a Trusted Device
 * mapping, or an MMIO emulated in the Realm world).
 *
 * We can rely on the RIPAS value of the region to detect if a given region is
 * protected.
 *
 *  RIPAS_DEV - A trusted device memory or a trusted emulated MMIO (in the Realm
 *		world
 *  RIPAS_RAM - Memory (RAM), protected by the RMM guarantees. (e.g., Firmware
 *		reserved regions for data sharing).
 *
 *  RIPAS_DESTROYED is a special case of one of the above, where the host did
 *  something without our permission and as such we can't do anything about it.
 *
 * The only case where something is emulated by the untrusted hypervisor or is
 * backed by shared memory is indicated by RSI_RIPAS_EMPTY.
 */
bool arm64_rsi_is_protected(phys_addr_t base, size_t size)
{
	enum ripas ripas;
	phys_addr_t end, top;

	/* Overflow ? */
	if (WARN_ON(base + size <= base))
		return false;

	end = ALIGN(base + size, RSI_GRANULE_SIZE);
	base = ALIGN_DOWN(base, RSI_GRANULE_SIZE);

	while (base < end) {
		if (WARN_ON(rsi_ipa_state_get(base, end, &ripas, &top)))
			break;
		if (WARN_ON(top <= base))
			break;
		if (ripas == RSI_RIPAS_EMPTY)
			break;
		base = top;
	}

	return base >= end;
}
EXPORT_SYMBOL(arm64_rsi_is_protected);

static int realm_ioremap_hook(phys_addr_t phys, size_t size, pgprot_t *prot)
{
	if (arm64_rsi_is_protected(phys, size))
		*prot = pgprot_encrypted(*prot);
	else
		*prot = pgprot_decrypted(*prot);

	return 0;
}

void __init arm64_rsi_init(void)
{
	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC)
		return;
	if (!rsi_version_matches())
		return;
	if (WARN_ON(rsi_get_realm_config(lm_alias(&config))))
		return;
	prot_ns_shared = __phys_to_pte_val(BIT(config.ipa_bits - 1));

	if (arm64_ioremap_prot_hook_register(realm_ioremap_hook))
		return;

	if (realm_register_memory_enc_ops())
		return;

	arm64_rsi_setup_memory();

	static_branch_enable(&rsi_present);
}

static struct platform_device rsi_dev = {
	.name = RSI_PDEV_NAME,
	.id = PLATFORM_DEVID_NONE
};

static int __init arm64_create_dummy_rsi_dev(void)
{
	if (is_realm_world() &&

Annotation

Implementation Notes