|
20 | 20 | #include <linux/interrupt.h>
|
21 | 21 | #include <clocksource/hyperv_timer.h>
|
22 | 22 | #include <asm/mshyperv.h>
|
| 23 | +#include <linux/set_memory.h> |
23 | 24 | #include "hyperv_vmbus.h"
|
24 | 25 |
|
25 | 26 | /* The one and only */
|
@@ -78,7 +79,7 @@ int hv_post_message(union hv_connection_id connection_id,
|
78 | 79 |
|
79 | 80 | int hv_synic_alloc(void)
|
80 | 81 | {
|
81 |
| - int cpu; |
| 82 | + int cpu, ret = -ENOMEM; |
82 | 83 | struct hv_per_cpu_context *hv_cpu;
|
83 | 84 |
|
84 | 85 | /*
|
@@ -123,26 +124,76 @@ int hv_synic_alloc(void)
|
123 | 124 | goto err;
|
124 | 125 | }
|
125 | 126 | }
|
| 127 | + |
| 128 | + if (hv_isolation_type_en_snp()) { |
| 129 | + ret = set_memory_decrypted((unsigned long) |
| 130 | + hv_cpu->synic_message_page, 1); |
| 131 | + if (ret) { |
| 132 | + pr_err("Failed to decrypt SYNIC msg page: %d\n", ret); |
| 133 | + hv_cpu->synic_message_page = NULL; |
| 134 | + |
| 135 | + /* |
| 136 | + * Free the event page here so that hv_synic_free() |
| 137 | + * won't later try to re-encrypt it. |
| 138 | + */ |
| 139 | + free_page((unsigned long)hv_cpu->synic_event_page); |
| 140 | + hv_cpu->synic_event_page = NULL; |
| 141 | + goto err; |
| 142 | + } |
| 143 | + |
| 144 | + ret = set_memory_decrypted((unsigned long) |
| 145 | + hv_cpu->synic_event_page, 1); |
| 146 | + if (ret) { |
| 147 | + pr_err("Failed to decrypt SYNIC event page: %d\n", ret); |
| 148 | + hv_cpu->synic_event_page = NULL; |
| 149 | + goto err; |
| 150 | + } |
| 151 | + |
| 152 | + memset(hv_cpu->synic_message_page, 0, PAGE_SIZE); |
| 153 | + memset(hv_cpu->synic_event_page, 0, PAGE_SIZE); |
| 154 | + } |
126 | 155 | }
|
127 | 156 |
|
128 | 157 | return 0;
|
| 158 | + |
129 | 159 | err:
|
130 | 160 | /*
|
131 | 161 | * Any memory allocations that succeeded will be freed when
|
132 | 162 | * the caller cleans up by calling hv_synic_free()
|
133 | 163 | */
|
134 |
| - return -ENOMEM; |
| 164 | + return ret; |
135 | 165 | }
|
136 | 166 |
|
137 | 167 |
|
138 | 168 | void hv_synic_free(void)
|
139 | 169 | {
|
140 |
| - int cpu; |
| 170 | + int cpu, ret; |
141 | 171 |
|
142 | 172 | for_each_present_cpu(cpu) {
|
143 | 173 | struct hv_per_cpu_context *hv_cpu
|
144 | 174 | = per_cpu_ptr(hv_context.cpu_context, cpu);
|
145 | 175 |
|
| 176 | + /* It's better to leak the page if the encryption fails. */ |
| 177 | + if (hv_isolation_type_en_snp()) { |
| 178 | + if (hv_cpu->synic_message_page) { |
| 179 | + ret = set_memory_encrypted((unsigned long) |
| 180 | + hv_cpu->synic_message_page, 1); |
| 181 | + if (ret) { |
| 182 | + pr_err("Failed to encrypt SYNIC msg page: %d\n", ret); |
| 183 | + hv_cpu->synic_message_page = NULL; |
| 184 | + } |
| 185 | + } |
| 186 | + |
| 187 | + if (hv_cpu->synic_event_page) { |
| 188 | + ret = set_memory_encrypted((unsigned long) |
| 189 | + hv_cpu->synic_event_page, 1); |
| 190 | + if (ret) { |
| 191 | + pr_err("Failed to encrypt SYNIC event page: %d\n", ret); |
| 192 | + hv_cpu->synic_event_page = NULL; |
| 193 | + } |
| 194 | + } |
| 195 | + } |
| 196 | + |
146 | 197 | free_page((unsigned long)hv_cpu->synic_event_page);
|
147 | 198 | free_page((unsigned long)hv_cpu->synic_message_page);
|
148 | 199 | }
|
|
0 commit comments