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