]> Git Repo - linux.git/blob - arch/arm64/kernel/rsi.c
Linux 6.14-rc3
[linux.git] / arch / arm64 / kernel / rsi.c
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)
This page took 0.040461 seconds and 4 git commands to generate.