xref: /linux/arch/arm64/kernel/rsi.c (revision 8838a1a2d219a86ab05e679c73f68dd75a25aca5)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2023 ARM Ltd.
4  */
5 
6 #include <linux/jump_label.h>
7 #include <linux/memblock.h>
8 #include <linux/psci.h>
9 #include <linux/swiotlb.h>
10 #include <linux/cc_platform.h>
11 #include <linux/platform_device.h>
12 
13 #include <asm/io.h>
14 #include <asm/mem_encrypt.h>
15 #include <asm/rsi.h>
16 
17 static struct realm_config config;
18 
19 unsigned long prot_ns_shared;
20 EXPORT_SYMBOL(prot_ns_shared);
21 
22 DEFINE_STATIC_KEY_FALSE_RO(rsi_present);
23 EXPORT_SYMBOL(rsi_present);
24 
25 bool cc_platform_has(enum cc_attr attr)
26 {
27 	switch (attr) {
28 	case CC_ATTR_MEM_ENCRYPT:
29 		return is_realm_world();
30 	default:
31 		return false;
32 	}
33 }
34 EXPORT_SYMBOL_GPL(cc_platform_has);
35 
36 static bool rsi_version_matches(void)
37 {
38 	unsigned long ver_lower, ver_higher;
39 	unsigned long ret = rsi_request_version(RSI_ABI_VERSION,
40 						&ver_lower,
41 						&ver_higher);
42 
43 	if (ret == SMCCC_RET_NOT_SUPPORTED)
44 		return false;
45 
46 	if (ret != RSI_SUCCESS) {
47 		pr_err("RME: RMM doesn't support RSI version %lu.%lu. Supported range: %lu.%lu-%lu.%lu\n",
48 		       RSI_ABI_VERSION_MAJOR, RSI_ABI_VERSION_MINOR,
49 		       RSI_ABI_VERSION_GET_MAJOR(ver_lower),
50 		       RSI_ABI_VERSION_GET_MINOR(ver_lower),
51 		       RSI_ABI_VERSION_GET_MAJOR(ver_higher),
52 		       RSI_ABI_VERSION_GET_MINOR(ver_higher));
53 		return false;
54 	}
55 
56 	pr_info("RME: Using RSI version %lu.%lu\n",
57 		RSI_ABI_VERSION_GET_MAJOR(ver_lower),
58 		RSI_ABI_VERSION_GET_MINOR(ver_lower));
59 
60 	return true;
61 }
62 
63 static void __init arm64_rsi_setup_memory(void)
64 {
65 	u64 i;
66 	phys_addr_t start, end;
67 
68 	/*
69 	 * Iterate over the available memory ranges and convert the state to
70 	 * protected memory. We should take extra care to ensure that we DO NOT
71 	 * permit any "DESTROYED" pages to be converted to "RAM".
72 	 *
73 	 * panic() is used because if the attempt to switch the memory to
74 	 * protected has failed here, then future accesses to the memory are
75 	 * simply going to be reflected as a SEA (Synchronous External Abort)
76 	 * which we can't handle.  Bailing out early prevents the guest limping
77 	 * on and dying later.
78 	 */
79 	for_each_mem_range(i, &start, &end) {
80 		if (rsi_set_memory_range_protected_safe(start, end)) {
81 			panic("Failed to set memory range to protected: %pa-%pa",
82 			      &start, &end);
83 		}
84 	}
85 }
86 
87 bool __arm64_is_protected_mmio(phys_addr_t base, size_t size)
88 {
89 	enum ripas ripas;
90 	phys_addr_t end, top;
91 
92 	/* Overflow ? */
93 	if (WARN_ON(base + size <= base))
94 		return false;
95 
96 	end = ALIGN(base + size, RSI_GRANULE_SIZE);
97 	base = ALIGN_DOWN(base, RSI_GRANULE_SIZE);
98 
99 	while (base < end) {
100 		if (WARN_ON(rsi_ipa_state_get(base, end, &ripas, &top)))
101 			break;
102 		if (WARN_ON(top <= base))
103 			break;
104 		if (ripas != RSI_RIPAS_DEV)
105 			break;
106 		base = top;
107 	}
108 
109 	return base >= end;
110 }
111 EXPORT_SYMBOL(__arm64_is_protected_mmio);
112 
113 static int realm_ioremap_hook(phys_addr_t phys, size_t size, pgprot_t *prot)
114 {
115 	if (__arm64_is_protected_mmio(phys, size))
116 		*prot = pgprot_encrypted(*prot);
117 	else
118 		*prot = pgprot_decrypted(*prot);
119 
120 	return 0;
121 }
122 
123 void __init arm64_rsi_init(void)
124 {
125 	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC)
126 		return;
127 	if (!rsi_version_matches())
128 		return;
129 	if (WARN_ON(rsi_get_realm_config(&config)))
130 		return;
131 	prot_ns_shared = BIT(config.ipa_bits - 1);
132 
133 	if (arm64_ioremap_prot_hook_register(realm_ioremap_hook))
134 		return;
135 
136 	if (realm_register_memory_enc_ops())
137 		return;
138 
139 	arm64_rsi_setup_memory();
140 
141 	static_branch_enable(&rsi_present);
142 }
143 
144 static struct platform_device rsi_dev = {
145 	.name = RSI_PDEV_NAME,
146 	.id = PLATFORM_DEVID_NONE
147 };
148 
149 static int __init arm64_create_dummy_rsi_dev(void)
150 {
151 	if (is_realm_world() &&
152 	    platform_device_register(&rsi_dev))
153 		pr_err("failed to register rsi platform device\n");
154 	return 0;
155 }
156 
157 arch_initcall(arm64_create_dummy_rsi_dev)
158