1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * AMD Secure Encrypted Virtualization (SEV) interface |
4 | * |
5 | * Copyright (C) 2016,2019 Advanced Micro Devices, Inc. |
6 | * |
7 | * Author: Brijesh Singh <brijesh.singh@amd.com> |
8 | */ |
9 | |
10 | #include <linux/bitfield.h> |
11 | #include <linux/module.h> |
12 | #include <linux/kernel.h> |
13 | #include <linux/kthread.h> |
14 | #include <linux/sched.h> |
15 | #include <linux/interrupt.h> |
16 | #include <linux/spinlock.h> |
17 | #include <linux/spinlock_types.h> |
18 | #include <linux/types.h> |
19 | #include <linux/mutex.h> |
20 | #include <linux/delay.h> |
21 | #include <linux/hw_random.h> |
22 | #include <linux/ccp.h> |
23 | #include <linux/firmware.h> |
24 | #include <linux/gfp.h> |
25 | #include <linux/cpufeature.h> |
26 | #include <linux/fs.h> |
27 | #include <linux/fs_struct.h> |
28 | #include <linux/psp.h> |
29 | |
30 | #include <asm/smp.h> |
31 | #include <asm/cacheflush.h> |
32 | |
33 | #include "psp-dev.h" |
34 | #include "sev-dev.h" |
35 | |
36 | #define DEVICE_NAME "sev" |
37 | #define SEV_FW_FILE "amd/sev.fw" |
38 | #define SEV_FW_NAME_SIZE 64 |
39 | |
40 | static DEFINE_MUTEX(sev_cmd_mutex); |
41 | static struct sev_misc_dev *misc_dev; |
42 | |
43 | static int psp_cmd_timeout = 100; |
44 | module_param(psp_cmd_timeout, int, 0644); |
45 | MODULE_PARM_DESC(psp_cmd_timeout, " default timeout value, in seconds, for PSP commands" ); |
46 | |
47 | static int psp_probe_timeout = 5; |
48 | module_param(psp_probe_timeout, int, 0644); |
49 | MODULE_PARM_DESC(psp_probe_timeout, " default timeout value, in seconds, during PSP device probe" ); |
50 | |
51 | static char *init_ex_path; |
52 | module_param(init_ex_path, charp, 0444); |
53 | MODULE_PARM_DESC(init_ex_path, " Path for INIT_EX data; if set try INIT_EX" ); |
54 | |
55 | static bool psp_init_on_probe = true; |
56 | module_param(psp_init_on_probe, bool, 0444); |
57 | MODULE_PARM_DESC(psp_init_on_probe, " if true, the PSP will be initialized on module init. Else the PSP will be initialized on the first command requiring it" ); |
58 | |
59 | MODULE_FIRMWARE("amd/amd_sev_fam17h_model0xh.sbin" ); /* 1st gen EPYC */ |
60 | MODULE_FIRMWARE("amd/amd_sev_fam17h_model3xh.sbin" ); /* 2nd gen EPYC */ |
61 | MODULE_FIRMWARE("amd/amd_sev_fam19h_model0xh.sbin" ); /* 3rd gen EPYC */ |
62 | MODULE_FIRMWARE("amd/amd_sev_fam19h_model1xh.sbin" ); /* 4th gen EPYC */ |
63 | |
64 | static bool psp_dead; |
65 | static int psp_timeout; |
66 | |
67 | /* Trusted Memory Region (TMR): |
68 | * The TMR is a 1MB area that must be 1MB aligned. Use the page allocator |
69 | * to allocate the memory, which will return aligned memory for the specified |
70 | * allocation order. |
71 | */ |
72 | #define SEV_ES_TMR_SIZE (1024 * 1024) |
73 | static void *sev_es_tmr; |
74 | |
75 | /* INIT_EX NV Storage: |
76 | * The NV Storage is a 32Kb area and must be 4Kb page aligned. Use the page |
77 | * allocator to allocate the memory, which will return aligned memory for the |
78 | * specified allocation order. |
79 | */ |
80 | #define NV_LENGTH (32 * 1024) |
81 | static void *sev_init_ex_buffer; |
82 | |
83 | static inline bool sev_version_greater_or_equal(u8 maj, u8 min) |
84 | { |
85 | struct sev_device *sev = psp_master->sev_data; |
86 | |
87 | if (sev->api_major > maj) |
88 | return true; |
89 | |
90 | if (sev->api_major == maj && sev->api_minor >= min) |
91 | return true; |
92 | |
93 | return false; |
94 | } |
95 | |
96 | static void sev_irq_handler(int irq, void *data, unsigned int status) |
97 | { |
98 | struct sev_device *sev = data; |
99 | int reg; |
100 | |
101 | /* Check if it is command completion: */ |
102 | if (!(status & SEV_CMD_COMPLETE)) |
103 | return; |
104 | |
105 | /* Check if it is SEV command completion: */ |
106 | reg = ioread32(sev->io_regs + sev->vdata->cmdresp_reg); |
107 | if (FIELD_GET(PSP_CMDRESP_RESP, reg)) { |
108 | sev->int_rcvd = 1; |
109 | wake_up(&sev->int_queue); |
110 | } |
111 | } |
112 | |
113 | static int sev_wait_cmd_ioc(struct sev_device *sev, |
114 | unsigned int *reg, unsigned int timeout) |
115 | { |
116 | int ret; |
117 | |
118 | ret = wait_event_timeout(sev->int_queue, |
119 | sev->int_rcvd, timeout * HZ); |
120 | if (!ret) |
121 | return -ETIMEDOUT; |
122 | |
123 | *reg = ioread32(sev->io_regs + sev->vdata->cmdresp_reg); |
124 | |
125 | return 0; |
126 | } |
127 | |
128 | static int sev_cmd_buffer_len(int cmd) |
129 | { |
130 | switch (cmd) { |
131 | case SEV_CMD_INIT: return sizeof(struct sev_data_init); |
132 | case SEV_CMD_INIT_EX: return sizeof(struct sev_data_init_ex); |
133 | case SEV_CMD_PLATFORM_STATUS: return sizeof(struct sev_user_data_status); |
134 | case SEV_CMD_PEK_CSR: return sizeof(struct sev_data_pek_csr); |
135 | case SEV_CMD_PEK_CERT_IMPORT: return sizeof(struct sev_data_pek_cert_import); |
136 | case SEV_CMD_PDH_CERT_EXPORT: return sizeof(struct sev_data_pdh_cert_export); |
137 | case SEV_CMD_LAUNCH_START: return sizeof(struct sev_data_launch_start); |
138 | case SEV_CMD_LAUNCH_UPDATE_DATA: return sizeof(struct sev_data_launch_update_data); |
139 | case SEV_CMD_LAUNCH_UPDATE_VMSA: return sizeof(struct sev_data_launch_update_vmsa); |
140 | case SEV_CMD_LAUNCH_FINISH: return sizeof(struct sev_data_launch_finish); |
141 | case SEV_CMD_LAUNCH_MEASURE: return sizeof(struct sev_data_launch_measure); |
142 | case SEV_CMD_ACTIVATE: return sizeof(struct sev_data_activate); |
143 | case SEV_CMD_DEACTIVATE: return sizeof(struct sev_data_deactivate); |
144 | case SEV_CMD_DECOMMISSION: return sizeof(struct sev_data_decommission); |
145 | case SEV_CMD_GUEST_STATUS: return sizeof(struct sev_data_guest_status); |
146 | case SEV_CMD_DBG_DECRYPT: return sizeof(struct sev_data_dbg); |
147 | case SEV_CMD_DBG_ENCRYPT: return sizeof(struct sev_data_dbg); |
148 | case SEV_CMD_SEND_START: return sizeof(struct sev_data_send_start); |
149 | case SEV_CMD_SEND_UPDATE_DATA: return sizeof(struct sev_data_send_update_data); |
150 | case SEV_CMD_SEND_UPDATE_VMSA: return sizeof(struct sev_data_send_update_vmsa); |
151 | case SEV_CMD_SEND_FINISH: return sizeof(struct sev_data_send_finish); |
152 | case SEV_CMD_RECEIVE_START: return sizeof(struct sev_data_receive_start); |
153 | case SEV_CMD_RECEIVE_FINISH: return sizeof(struct sev_data_receive_finish); |
154 | case SEV_CMD_RECEIVE_UPDATE_DATA: return sizeof(struct sev_data_receive_update_data); |
155 | case SEV_CMD_RECEIVE_UPDATE_VMSA: return sizeof(struct sev_data_receive_update_vmsa); |
156 | case SEV_CMD_LAUNCH_UPDATE_SECRET: return sizeof(struct sev_data_launch_secret); |
157 | case SEV_CMD_DOWNLOAD_FIRMWARE: return sizeof(struct sev_data_download_firmware); |
158 | case SEV_CMD_GET_ID: return sizeof(struct sev_data_get_id); |
159 | case SEV_CMD_ATTESTATION_REPORT: return sizeof(struct sev_data_attestation_report); |
160 | case SEV_CMD_SEND_CANCEL: return sizeof(struct sev_data_send_cancel); |
161 | default: return 0; |
162 | } |
163 | |
164 | return 0; |
165 | } |
166 | |
167 | static void *sev_fw_alloc(unsigned long len) |
168 | { |
169 | struct page *page; |
170 | |
171 | page = alloc_pages(GFP_KERNEL, order: get_order(size: len)); |
172 | if (!page) |
173 | return NULL; |
174 | |
175 | return page_address(page); |
176 | } |
177 | |
178 | static struct file *open_file_as_root(const char *filename, int flags, umode_t mode) |
179 | { |
180 | struct file *fp; |
181 | struct path root; |
182 | struct cred *cred; |
183 | const struct cred *old_cred; |
184 | |
185 | task_lock(p: &init_task); |
186 | get_fs_root(fs: init_task.fs, root: &root); |
187 | task_unlock(p: &init_task); |
188 | |
189 | cred = prepare_creds(); |
190 | if (!cred) |
191 | return ERR_PTR(error: -ENOMEM); |
192 | cred->fsuid = GLOBAL_ROOT_UID; |
193 | old_cred = override_creds(cred); |
194 | |
195 | fp = file_open_root(&root, filename, flags, mode); |
196 | path_put(&root); |
197 | |
198 | revert_creds(old_cred); |
199 | |
200 | return fp; |
201 | } |
202 | |
203 | static int sev_read_init_ex_file(void) |
204 | { |
205 | struct sev_device *sev = psp_master->sev_data; |
206 | struct file *fp; |
207 | ssize_t nread; |
208 | |
209 | lockdep_assert_held(&sev_cmd_mutex); |
210 | |
211 | if (!sev_init_ex_buffer) |
212 | return -EOPNOTSUPP; |
213 | |
214 | fp = open_file_as_root(filename: init_ex_path, O_RDONLY, mode: 0); |
215 | if (IS_ERR(ptr: fp)) { |
216 | int ret = PTR_ERR(ptr: fp); |
217 | |
218 | if (ret == -ENOENT) { |
219 | dev_info(sev->dev, |
220 | "SEV: %s does not exist and will be created later.\n" , |
221 | init_ex_path); |
222 | ret = 0; |
223 | } else { |
224 | dev_err(sev->dev, |
225 | "SEV: could not open %s for read, error %d\n" , |
226 | init_ex_path, ret); |
227 | } |
228 | return ret; |
229 | } |
230 | |
231 | nread = kernel_read(fp, sev_init_ex_buffer, NV_LENGTH, NULL); |
232 | if (nread != NV_LENGTH) { |
233 | dev_info(sev->dev, |
234 | "SEV: could not read %u bytes to non volatile memory area, ret %ld\n" , |
235 | NV_LENGTH, nread); |
236 | } |
237 | |
238 | dev_dbg(sev->dev, "SEV: read %ld bytes from NV file\n" , nread); |
239 | filp_close(fp, NULL); |
240 | |
241 | return 0; |
242 | } |
243 | |
244 | static int sev_write_init_ex_file(void) |
245 | { |
246 | struct sev_device *sev = psp_master->sev_data; |
247 | struct file *fp; |
248 | loff_t offset = 0; |
249 | ssize_t nwrite; |
250 | |
251 | lockdep_assert_held(&sev_cmd_mutex); |
252 | |
253 | if (!sev_init_ex_buffer) |
254 | return 0; |
255 | |
256 | fp = open_file_as_root(filename: init_ex_path, O_CREAT | O_WRONLY, mode: 0600); |
257 | if (IS_ERR(ptr: fp)) { |
258 | int ret = PTR_ERR(ptr: fp); |
259 | |
260 | dev_err(sev->dev, |
261 | "SEV: could not open file for write, error %d\n" , |
262 | ret); |
263 | return ret; |
264 | } |
265 | |
266 | nwrite = kernel_write(fp, sev_init_ex_buffer, NV_LENGTH, &offset); |
267 | vfs_fsync(file: fp, datasync: 0); |
268 | filp_close(fp, NULL); |
269 | |
270 | if (nwrite != NV_LENGTH) { |
271 | dev_err(sev->dev, |
272 | "SEV: failed to write %u bytes to non volatile memory area, ret %ld\n" , |
273 | NV_LENGTH, nwrite); |
274 | return -EIO; |
275 | } |
276 | |
277 | dev_dbg(sev->dev, "SEV: write successful to NV file\n" ); |
278 | |
279 | return 0; |
280 | } |
281 | |
282 | static int sev_write_init_ex_file_if_required(int cmd_id) |
283 | { |
284 | lockdep_assert_held(&sev_cmd_mutex); |
285 | |
286 | if (!sev_init_ex_buffer) |
287 | return 0; |
288 | |
289 | /* |
290 | * Only a few platform commands modify the SPI/NV area, but none of the |
291 | * non-platform commands do. Only INIT(_EX), PLATFORM_RESET, PEK_GEN, |
292 | * PEK_CERT_IMPORT, and PDH_GEN do. |
293 | */ |
294 | switch (cmd_id) { |
295 | case SEV_CMD_FACTORY_RESET: |
296 | case SEV_CMD_INIT_EX: |
297 | case SEV_CMD_PDH_GEN: |
298 | case SEV_CMD_PEK_CERT_IMPORT: |
299 | case SEV_CMD_PEK_GEN: |
300 | break; |
301 | default: |
302 | return 0; |
303 | } |
304 | |
305 | return sev_write_init_ex_file(); |
306 | } |
307 | |
308 | static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret) |
309 | { |
310 | struct psp_device *psp = psp_master; |
311 | struct sev_device *sev; |
312 | unsigned int cmdbuff_hi, cmdbuff_lo; |
313 | unsigned int phys_lsb, phys_msb; |
314 | unsigned int reg, ret = 0; |
315 | int buf_len; |
316 | |
317 | if (!psp || !psp->sev_data) |
318 | return -ENODEV; |
319 | |
320 | if (psp_dead) |
321 | return -EBUSY; |
322 | |
323 | sev = psp->sev_data; |
324 | |
325 | buf_len = sev_cmd_buffer_len(cmd); |
326 | if (WARN_ON_ONCE(!data != !buf_len)) |
327 | return -EINVAL; |
328 | |
329 | /* |
330 | * Copy the incoming data to driver's scratch buffer as __pa() will not |
331 | * work for some memory, e.g. vmalloc'd addresses, and @data may not be |
332 | * physically contiguous. |
333 | */ |
334 | if (data) |
335 | memcpy(sev->cmd_buf, data, buf_len); |
336 | |
337 | /* Get the physical address of the command buffer */ |
338 | phys_lsb = data ? lower_32_bits(__psp_pa(sev->cmd_buf)) : 0; |
339 | phys_msb = data ? upper_32_bits(__psp_pa(sev->cmd_buf)) : 0; |
340 | |
341 | dev_dbg(sev->dev, "sev command id %#x buffer 0x%08x%08x timeout %us\n" , |
342 | cmd, phys_msb, phys_lsb, psp_timeout); |
343 | |
344 | print_hex_dump_debug("(in): " , DUMP_PREFIX_OFFSET, 16, 2, data, |
345 | buf_len, false); |
346 | |
347 | iowrite32(phys_lsb, sev->io_regs + sev->vdata->cmdbuff_addr_lo_reg); |
348 | iowrite32(phys_msb, sev->io_regs + sev->vdata->cmdbuff_addr_hi_reg); |
349 | |
350 | sev->int_rcvd = 0; |
351 | |
352 | reg = FIELD_PREP(SEV_CMDRESP_CMD, cmd) | SEV_CMDRESP_IOC; |
353 | iowrite32(reg, sev->io_regs + sev->vdata->cmdresp_reg); |
354 | |
355 | /* wait for command completion */ |
356 | ret = sev_wait_cmd_ioc(sev, reg: ®, timeout: psp_timeout); |
357 | if (ret) { |
358 | if (psp_ret) |
359 | *psp_ret = 0; |
360 | |
361 | dev_err(sev->dev, "sev command %#x timed out, disabling PSP\n" , cmd); |
362 | psp_dead = true; |
363 | |
364 | return ret; |
365 | } |
366 | |
367 | psp_timeout = psp_cmd_timeout; |
368 | |
369 | if (psp_ret) |
370 | *psp_ret = FIELD_GET(PSP_CMDRESP_STS, reg); |
371 | |
372 | if (FIELD_GET(PSP_CMDRESP_STS, reg)) { |
373 | dev_dbg(sev->dev, "sev command %#x failed (%#010lx)\n" , |
374 | cmd, FIELD_GET(PSP_CMDRESP_STS, reg)); |
375 | |
376 | /* |
377 | * PSP firmware may report additional error information in the |
378 | * command buffer registers on error. Print contents of command |
379 | * buffer registers if they changed. |
380 | */ |
381 | cmdbuff_hi = ioread32(sev->io_regs + sev->vdata->cmdbuff_addr_hi_reg); |
382 | cmdbuff_lo = ioread32(sev->io_regs + sev->vdata->cmdbuff_addr_lo_reg); |
383 | if (cmdbuff_hi != phys_msb || cmdbuff_lo != phys_lsb) { |
384 | dev_dbg(sev->dev, "Additional error information reported in cmdbuff:" ); |
385 | dev_dbg(sev->dev, " cmdbuff hi: %#010x\n" , cmdbuff_hi); |
386 | dev_dbg(sev->dev, " cmdbuff lo: %#010x\n" , cmdbuff_lo); |
387 | } |
388 | ret = -EIO; |
389 | } else { |
390 | ret = sev_write_init_ex_file_if_required(cmd_id: cmd); |
391 | } |
392 | |
393 | print_hex_dump_debug("(out): " , DUMP_PREFIX_OFFSET, 16, 2, data, |
394 | buf_len, false); |
395 | |
396 | /* |
397 | * Copy potential output from the PSP back to data. Do this even on |
398 | * failure in case the caller wants to glean something from the error. |
399 | */ |
400 | if (data) |
401 | memcpy(data, sev->cmd_buf, buf_len); |
402 | |
403 | return ret; |
404 | } |
405 | |
406 | static int sev_do_cmd(int cmd, void *data, int *psp_ret) |
407 | { |
408 | int rc; |
409 | |
410 | mutex_lock(&sev_cmd_mutex); |
411 | rc = __sev_do_cmd_locked(cmd, data, psp_ret); |
412 | mutex_unlock(lock: &sev_cmd_mutex); |
413 | |
414 | return rc; |
415 | } |
416 | |
417 | static int __sev_init_locked(int *error) |
418 | { |
419 | struct sev_data_init data; |
420 | |
421 | memset(&data, 0, sizeof(data)); |
422 | if (sev_es_tmr) { |
423 | /* |
424 | * Do not include the encryption mask on the physical |
425 | * address of the TMR (firmware should clear it anyway). |
426 | */ |
427 | data.tmr_address = __pa(sev_es_tmr); |
428 | |
429 | data.flags |= SEV_INIT_FLAGS_SEV_ES; |
430 | data.tmr_len = SEV_ES_TMR_SIZE; |
431 | } |
432 | |
433 | return __sev_do_cmd_locked(cmd: SEV_CMD_INIT, data: &data, psp_ret: error); |
434 | } |
435 | |
436 | static int __sev_init_ex_locked(int *error) |
437 | { |
438 | struct sev_data_init_ex data; |
439 | |
440 | memset(&data, 0, sizeof(data)); |
441 | data.length = sizeof(data); |
442 | data.nv_address = __psp_pa(sev_init_ex_buffer); |
443 | data.nv_len = NV_LENGTH; |
444 | |
445 | if (sev_es_tmr) { |
446 | /* |
447 | * Do not include the encryption mask on the physical |
448 | * address of the TMR (firmware should clear it anyway). |
449 | */ |
450 | data.tmr_address = __pa(sev_es_tmr); |
451 | |
452 | data.flags |= SEV_INIT_FLAGS_SEV_ES; |
453 | data.tmr_len = SEV_ES_TMR_SIZE; |
454 | } |
455 | |
456 | return __sev_do_cmd_locked(cmd: SEV_CMD_INIT_EX, data: &data, psp_ret: error); |
457 | } |
458 | |
459 | static inline int __sev_do_init_locked(int *psp_ret) |
460 | { |
461 | if (sev_init_ex_buffer) |
462 | return __sev_init_ex_locked(error: psp_ret); |
463 | else |
464 | return __sev_init_locked(error: psp_ret); |
465 | } |
466 | |
467 | static int __sev_platform_init_locked(int *error) |
468 | { |
469 | int rc = 0, psp_ret = SEV_RET_NO_FW_CALL; |
470 | struct psp_device *psp = psp_master; |
471 | struct sev_device *sev; |
472 | |
473 | if (!psp || !psp->sev_data) |
474 | return -ENODEV; |
475 | |
476 | sev = psp->sev_data; |
477 | |
478 | if (sev->state == SEV_STATE_INIT) |
479 | return 0; |
480 | |
481 | if (sev_init_ex_buffer) { |
482 | rc = sev_read_init_ex_file(); |
483 | if (rc) |
484 | return rc; |
485 | } |
486 | |
487 | rc = __sev_do_init_locked(psp_ret: &psp_ret); |
488 | if (rc && psp_ret == SEV_RET_SECURE_DATA_INVALID) { |
489 | /* |
490 | * Initialization command returned an integrity check failure |
491 | * status code, meaning that firmware load and validation of SEV |
492 | * related persistent data has failed. Retrying the |
493 | * initialization function should succeed by replacing the state |
494 | * with a reset state. |
495 | */ |
496 | dev_err(sev->dev, |
497 | "SEV: retrying INIT command because of SECURE_DATA_INVALID error. Retrying once to reset PSP SEV state." ); |
498 | rc = __sev_do_init_locked(psp_ret: &psp_ret); |
499 | } |
500 | |
501 | if (error) |
502 | *error = psp_ret; |
503 | |
504 | if (rc) |
505 | return rc; |
506 | |
507 | sev->state = SEV_STATE_INIT; |
508 | |
509 | /* Prepare for first SEV guest launch after INIT */ |
510 | wbinvd_on_all_cpus(); |
511 | rc = __sev_do_cmd_locked(cmd: SEV_CMD_DF_FLUSH, NULL, psp_ret: error); |
512 | if (rc) |
513 | return rc; |
514 | |
515 | dev_dbg(sev->dev, "SEV firmware initialized\n" ); |
516 | |
517 | dev_info(sev->dev, "SEV API:%d.%d build:%d\n" , sev->api_major, |
518 | sev->api_minor, sev->build); |
519 | |
520 | return 0; |
521 | } |
522 | |
523 | int sev_platform_init(int *error) |
524 | { |
525 | int rc; |
526 | |
527 | mutex_lock(&sev_cmd_mutex); |
528 | rc = __sev_platform_init_locked(error); |
529 | mutex_unlock(lock: &sev_cmd_mutex); |
530 | |
531 | return rc; |
532 | } |
533 | EXPORT_SYMBOL_GPL(sev_platform_init); |
534 | |
535 | static int __sev_platform_shutdown_locked(int *error) |
536 | { |
537 | struct sev_device *sev = psp_master->sev_data; |
538 | int ret; |
539 | |
540 | if (!sev || sev->state == SEV_STATE_UNINIT) |
541 | return 0; |
542 | |
543 | ret = __sev_do_cmd_locked(cmd: SEV_CMD_SHUTDOWN, NULL, psp_ret: error); |
544 | if (ret) |
545 | return ret; |
546 | |
547 | sev->state = SEV_STATE_UNINIT; |
548 | dev_dbg(sev->dev, "SEV firmware shutdown\n" ); |
549 | |
550 | return ret; |
551 | } |
552 | |
553 | static int sev_platform_shutdown(int *error) |
554 | { |
555 | int rc; |
556 | |
557 | mutex_lock(&sev_cmd_mutex); |
558 | rc = __sev_platform_shutdown_locked(NULL); |
559 | mutex_unlock(lock: &sev_cmd_mutex); |
560 | |
561 | return rc; |
562 | } |
563 | |
564 | static int sev_get_platform_state(int *state, int *error) |
565 | { |
566 | struct sev_user_data_status data; |
567 | int rc; |
568 | |
569 | rc = __sev_do_cmd_locked(cmd: SEV_CMD_PLATFORM_STATUS, data: &data, psp_ret: error); |
570 | if (rc) |
571 | return rc; |
572 | |
573 | *state = data.state; |
574 | return rc; |
575 | } |
576 | |
577 | static int sev_ioctl_do_reset(struct sev_issue_cmd *argp, bool writable) |
578 | { |
579 | int state, rc; |
580 | |
581 | if (!writable) |
582 | return -EPERM; |
583 | |
584 | /* |
585 | * The SEV spec requires that FACTORY_RESET must be issued in |
586 | * UNINIT state. Before we go further lets check if any guest is |
587 | * active. |
588 | * |
589 | * If FW is in WORKING state then deny the request otherwise issue |
590 | * SHUTDOWN command do INIT -> UNINIT before issuing the FACTORY_RESET. |
591 | * |
592 | */ |
593 | rc = sev_get_platform_state(state: &state, error: &argp->error); |
594 | if (rc) |
595 | return rc; |
596 | |
597 | if (state == SEV_STATE_WORKING) |
598 | return -EBUSY; |
599 | |
600 | if (state == SEV_STATE_INIT) { |
601 | rc = __sev_platform_shutdown_locked(error: &argp->error); |
602 | if (rc) |
603 | return rc; |
604 | } |
605 | |
606 | return __sev_do_cmd_locked(cmd: SEV_CMD_FACTORY_RESET, NULL, psp_ret: &argp->error); |
607 | } |
608 | |
609 | static int sev_ioctl_do_platform_status(struct sev_issue_cmd *argp) |
610 | { |
611 | struct sev_user_data_status data; |
612 | int ret; |
613 | |
614 | memset(&data, 0, sizeof(data)); |
615 | |
616 | ret = __sev_do_cmd_locked(cmd: SEV_CMD_PLATFORM_STATUS, data: &data, psp_ret: &argp->error); |
617 | if (ret) |
618 | return ret; |
619 | |
620 | if (copy_to_user(to: (void __user *)argp->data, from: &data, n: sizeof(data))) |
621 | ret = -EFAULT; |
622 | |
623 | return ret; |
624 | } |
625 | |
626 | static int sev_ioctl_do_pek_pdh_gen(int cmd, struct sev_issue_cmd *argp, bool writable) |
627 | { |
628 | struct sev_device *sev = psp_master->sev_data; |
629 | int rc; |
630 | |
631 | if (!writable) |
632 | return -EPERM; |
633 | |
634 | if (sev->state == SEV_STATE_UNINIT) { |
635 | rc = __sev_platform_init_locked(error: &argp->error); |
636 | if (rc) |
637 | return rc; |
638 | } |
639 | |
640 | return __sev_do_cmd_locked(cmd, NULL, psp_ret: &argp->error); |
641 | } |
642 | |
643 | static int sev_ioctl_do_pek_csr(struct sev_issue_cmd *argp, bool writable) |
644 | { |
645 | struct sev_device *sev = psp_master->sev_data; |
646 | struct sev_user_data_pek_csr input; |
647 | struct sev_data_pek_csr data; |
648 | void __user *input_address; |
649 | void *blob = NULL; |
650 | int ret; |
651 | |
652 | if (!writable) |
653 | return -EPERM; |
654 | |
655 | if (copy_from_user(to: &input, from: (void __user *)argp->data, n: sizeof(input))) |
656 | return -EFAULT; |
657 | |
658 | memset(&data, 0, sizeof(data)); |
659 | |
660 | /* userspace wants to query CSR length */ |
661 | if (!input.address || !input.length) |
662 | goto cmd; |
663 | |
664 | /* allocate a physically contiguous buffer to store the CSR blob */ |
665 | input_address = (void __user *)input.address; |
666 | if (input.length > SEV_FW_BLOB_MAX_SIZE) |
667 | return -EFAULT; |
668 | |
669 | blob = kzalloc(size: input.length, GFP_KERNEL); |
670 | if (!blob) |
671 | return -ENOMEM; |
672 | |
673 | data.address = __psp_pa(blob); |
674 | data.len = input.length; |
675 | |
676 | cmd: |
677 | if (sev->state == SEV_STATE_UNINIT) { |
678 | ret = __sev_platform_init_locked(error: &argp->error); |
679 | if (ret) |
680 | goto e_free_blob; |
681 | } |
682 | |
683 | ret = __sev_do_cmd_locked(cmd: SEV_CMD_PEK_CSR, data: &data, psp_ret: &argp->error); |
684 | |
685 | /* If we query the CSR length, FW responded with expected data. */ |
686 | input.length = data.len; |
687 | |
688 | if (copy_to_user(to: (void __user *)argp->data, from: &input, n: sizeof(input))) { |
689 | ret = -EFAULT; |
690 | goto e_free_blob; |
691 | } |
692 | |
693 | if (blob) { |
694 | if (copy_to_user(to: input_address, from: blob, n: input.length)) |
695 | ret = -EFAULT; |
696 | } |
697 | |
698 | e_free_blob: |
699 | kfree(objp: blob); |
700 | return ret; |
701 | } |
702 | |
703 | void *psp_copy_user_blob(u64 uaddr, u32 len) |
704 | { |
705 | if (!uaddr || !len) |
706 | return ERR_PTR(error: -EINVAL); |
707 | |
708 | /* verify that blob length does not exceed our limit */ |
709 | if (len > SEV_FW_BLOB_MAX_SIZE) |
710 | return ERR_PTR(error: -EINVAL); |
711 | |
712 | return memdup_user((void __user *)uaddr, len); |
713 | } |
714 | EXPORT_SYMBOL_GPL(psp_copy_user_blob); |
715 | |
716 | static int sev_get_api_version(void) |
717 | { |
718 | struct sev_device *sev = psp_master->sev_data; |
719 | struct sev_user_data_status status; |
720 | int error = 0, ret; |
721 | |
722 | ret = sev_platform_status(status: &status, error: &error); |
723 | if (ret) { |
724 | dev_err(sev->dev, |
725 | "SEV: failed to get status. Error: %#x\n" , error); |
726 | return 1; |
727 | } |
728 | |
729 | sev->api_major = status.api_major; |
730 | sev->api_minor = status.api_minor; |
731 | sev->build = status.build; |
732 | sev->state = status.state; |
733 | |
734 | return 0; |
735 | } |
736 | |
737 | static int sev_get_firmware(struct device *dev, |
738 | const struct firmware **firmware) |
739 | { |
740 | char fw_name_specific[SEV_FW_NAME_SIZE]; |
741 | char fw_name_subset[SEV_FW_NAME_SIZE]; |
742 | |
743 | snprintf(buf: fw_name_specific, size: sizeof(fw_name_specific), |
744 | fmt: "amd/amd_sev_fam%.2xh_model%.2xh.sbin" , |
745 | boot_cpu_data.x86, boot_cpu_data.x86_model); |
746 | |
747 | snprintf(buf: fw_name_subset, size: sizeof(fw_name_subset), |
748 | fmt: "amd/amd_sev_fam%.2xh_model%.1xxh.sbin" , |
749 | boot_cpu_data.x86, (boot_cpu_data.x86_model & 0xf0) >> 4); |
750 | |
751 | /* Check for SEV FW for a particular model. |
752 | * Ex. amd_sev_fam17h_model00h.sbin for Family 17h Model 00h |
753 | * |
754 | * or |
755 | * |
756 | * Check for SEV FW common to a subset of models. |
757 | * Ex. amd_sev_fam17h_model0xh.sbin for |
758 | * Family 17h Model 00h -- Family 17h Model 0Fh |
759 | * |
760 | * or |
761 | * |
762 | * Fall-back to using generic name: sev.fw |
763 | */ |
764 | if ((firmware_request_nowarn(fw: firmware, name: fw_name_specific, device: dev) >= 0) || |
765 | (firmware_request_nowarn(fw: firmware, name: fw_name_subset, device: dev) >= 0) || |
766 | (firmware_request_nowarn(fw: firmware, SEV_FW_FILE, device: dev) >= 0)) |
767 | return 0; |
768 | |
769 | return -ENOENT; |
770 | } |
771 | |
772 | /* Don't fail if SEV FW couldn't be updated. Continue with existing SEV FW */ |
773 | static int sev_update_firmware(struct device *dev) |
774 | { |
775 | struct sev_data_download_firmware *data; |
776 | const struct firmware *firmware; |
777 | int ret, error, order; |
778 | struct page *p; |
779 | u64 data_size; |
780 | |
781 | if (!sev_version_greater_or_equal(maj: 0, min: 15)) { |
782 | dev_dbg(dev, "DOWNLOAD_FIRMWARE not supported\n" ); |
783 | return -1; |
784 | } |
785 | |
786 | if (sev_get_firmware(dev, firmware: &firmware) == -ENOENT) { |
787 | dev_dbg(dev, "No SEV firmware file present\n" ); |
788 | return -1; |
789 | } |
790 | |
791 | /* |
792 | * SEV FW expects the physical address given to it to be 32 |
793 | * byte aligned. Memory allocated has structure placed at the |
794 | * beginning followed by the firmware being passed to the SEV |
795 | * FW. Allocate enough memory for data structure + alignment |
796 | * padding + SEV FW. |
797 | */ |
798 | data_size = ALIGN(sizeof(struct sev_data_download_firmware), 32); |
799 | |
800 | order = get_order(size: firmware->size + data_size); |
801 | p = alloc_pages(GFP_KERNEL, order); |
802 | if (!p) { |
803 | ret = -1; |
804 | goto fw_err; |
805 | } |
806 | |
807 | /* |
808 | * Copy firmware data to a kernel allocated contiguous |
809 | * memory region. |
810 | */ |
811 | data = page_address(p); |
812 | memcpy(page_address(p) + data_size, firmware->data, firmware->size); |
813 | |
814 | data->address = __psp_pa(page_address(p) + data_size); |
815 | data->len = firmware->size; |
816 | |
817 | ret = sev_do_cmd(cmd: SEV_CMD_DOWNLOAD_FIRMWARE, data, psp_ret: &error); |
818 | |
819 | /* |
820 | * A quirk for fixing the committed TCB version, when upgrading from |
821 | * earlier firmware version than 1.50. |
822 | */ |
823 | if (!ret && !sev_version_greater_or_equal(maj: 1, min: 50)) |
824 | ret = sev_do_cmd(cmd: SEV_CMD_DOWNLOAD_FIRMWARE, data, psp_ret: &error); |
825 | |
826 | if (ret) |
827 | dev_dbg(dev, "Failed to update SEV firmware: %#x\n" , error); |
828 | else |
829 | dev_info(dev, "SEV firmware update successful\n" ); |
830 | |
831 | __free_pages(page: p, order); |
832 | |
833 | fw_err: |
834 | release_firmware(fw: firmware); |
835 | |
836 | return ret; |
837 | } |
838 | |
839 | static int sev_ioctl_do_pek_import(struct sev_issue_cmd *argp, bool writable) |
840 | { |
841 | struct sev_device *sev = psp_master->sev_data; |
842 | struct sev_user_data_pek_cert_import input; |
843 | struct sev_data_pek_cert_import data; |
844 | void *pek_blob, *oca_blob; |
845 | int ret; |
846 | |
847 | if (!writable) |
848 | return -EPERM; |
849 | |
850 | if (copy_from_user(to: &input, from: (void __user *)argp->data, n: sizeof(input))) |
851 | return -EFAULT; |
852 | |
853 | /* copy PEK certificate blobs from userspace */ |
854 | pek_blob = psp_copy_user_blob(input.pek_cert_address, input.pek_cert_len); |
855 | if (IS_ERR(ptr: pek_blob)) |
856 | return PTR_ERR(ptr: pek_blob); |
857 | |
858 | data.reserved = 0; |
859 | data.pek_cert_address = __psp_pa(pek_blob); |
860 | data.pek_cert_len = input.pek_cert_len; |
861 | |
862 | /* copy PEK certificate blobs from userspace */ |
863 | oca_blob = psp_copy_user_blob(input.oca_cert_address, input.oca_cert_len); |
864 | if (IS_ERR(ptr: oca_blob)) { |
865 | ret = PTR_ERR(ptr: oca_blob); |
866 | goto e_free_pek; |
867 | } |
868 | |
869 | data.oca_cert_address = __psp_pa(oca_blob); |
870 | data.oca_cert_len = input.oca_cert_len; |
871 | |
872 | /* If platform is not in INIT state then transition it to INIT */ |
873 | if (sev->state != SEV_STATE_INIT) { |
874 | ret = __sev_platform_init_locked(error: &argp->error); |
875 | if (ret) |
876 | goto e_free_oca; |
877 | } |
878 | |
879 | ret = __sev_do_cmd_locked(cmd: SEV_CMD_PEK_CERT_IMPORT, data: &data, psp_ret: &argp->error); |
880 | |
881 | e_free_oca: |
882 | kfree(objp: oca_blob); |
883 | e_free_pek: |
884 | kfree(objp: pek_blob); |
885 | return ret; |
886 | } |
887 | |
888 | static int sev_ioctl_do_get_id2(struct sev_issue_cmd *argp) |
889 | { |
890 | struct sev_user_data_get_id2 input; |
891 | struct sev_data_get_id data; |
892 | void __user *input_address; |
893 | void *id_blob = NULL; |
894 | int ret; |
895 | |
896 | /* SEV GET_ID is available from SEV API v0.16 and up */ |
897 | if (!sev_version_greater_or_equal(maj: 0, min: 16)) |
898 | return -ENOTSUPP; |
899 | |
900 | if (copy_from_user(to: &input, from: (void __user *)argp->data, n: sizeof(input))) |
901 | return -EFAULT; |
902 | |
903 | input_address = (void __user *)input.address; |
904 | |
905 | if (input.address && input.length) { |
906 | /* |
907 | * The length of the ID shouldn't be assumed by software since |
908 | * it may change in the future. The allocation size is limited |
909 | * to 1 << (PAGE_SHIFT + MAX_ORDER) by the page allocator. |
910 | * If the allocation fails, simply return ENOMEM rather than |
911 | * warning in the kernel log. |
912 | */ |
913 | id_blob = kzalloc(size: input.length, GFP_KERNEL | __GFP_NOWARN); |
914 | if (!id_blob) |
915 | return -ENOMEM; |
916 | |
917 | data.address = __psp_pa(id_blob); |
918 | data.len = input.length; |
919 | } else { |
920 | data.address = 0; |
921 | data.len = 0; |
922 | } |
923 | |
924 | ret = __sev_do_cmd_locked(cmd: SEV_CMD_GET_ID, data: &data, psp_ret: &argp->error); |
925 | |
926 | /* |
927 | * Firmware will return the length of the ID value (either the minimum |
928 | * required length or the actual length written), return it to the user. |
929 | */ |
930 | input.length = data.len; |
931 | |
932 | if (copy_to_user(to: (void __user *)argp->data, from: &input, n: sizeof(input))) { |
933 | ret = -EFAULT; |
934 | goto e_free; |
935 | } |
936 | |
937 | if (id_blob) { |
938 | if (copy_to_user(to: input_address, from: id_blob, n: data.len)) { |
939 | ret = -EFAULT; |
940 | goto e_free; |
941 | } |
942 | } |
943 | |
944 | e_free: |
945 | kfree(objp: id_blob); |
946 | |
947 | return ret; |
948 | } |
949 | |
950 | static int sev_ioctl_do_get_id(struct sev_issue_cmd *argp) |
951 | { |
952 | struct sev_data_get_id *data; |
953 | u64 data_size, user_size; |
954 | void *id_blob, *mem; |
955 | int ret; |
956 | |
957 | /* SEV GET_ID available from SEV API v0.16 and up */ |
958 | if (!sev_version_greater_or_equal(maj: 0, min: 16)) |
959 | return -ENOTSUPP; |
960 | |
961 | /* SEV FW expects the buffer it fills with the ID to be |
962 | * 8-byte aligned. Memory allocated should be enough to |
963 | * hold data structure + alignment padding + memory |
964 | * where SEV FW writes the ID. |
965 | */ |
966 | data_size = ALIGN(sizeof(struct sev_data_get_id), 8); |
967 | user_size = sizeof(struct sev_user_data_get_id); |
968 | |
969 | mem = kzalloc(size: data_size + user_size, GFP_KERNEL); |
970 | if (!mem) |
971 | return -ENOMEM; |
972 | |
973 | data = mem; |
974 | id_blob = mem + data_size; |
975 | |
976 | data->address = __psp_pa(id_blob); |
977 | data->len = user_size; |
978 | |
979 | ret = __sev_do_cmd_locked(cmd: SEV_CMD_GET_ID, data, psp_ret: &argp->error); |
980 | if (!ret) { |
981 | if (copy_to_user(to: (void __user *)argp->data, from: id_blob, n: data->len)) |
982 | ret = -EFAULT; |
983 | } |
984 | |
985 | kfree(objp: mem); |
986 | |
987 | return ret; |
988 | } |
989 | |
990 | static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable) |
991 | { |
992 | struct sev_device *sev = psp_master->sev_data; |
993 | struct sev_user_data_pdh_cert_export input; |
994 | void *pdh_blob = NULL, *cert_blob = NULL; |
995 | struct sev_data_pdh_cert_export data; |
996 | void __user *input_cert_chain_address; |
997 | void __user *input_pdh_cert_address; |
998 | int ret; |
999 | |
1000 | /* If platform is not in INIT state then transition it to INIT. */ |
1001 | if (sev->state != SEV_STATE_INIT) { |
1002 | if (!writable) |
1003 | return -EPERM; |
1004 | |
1005 | ret = __sev_platform_init_locked(error: &argp->error); |
1006 | if (ret) |
1007 | return ret; |
1008 | } |
1009 | |
1010 | if (copy_from_user(to: &input, from: (void __user *)argp->data, n: sizeof(input))) |
1011 | return -EFAULT; |
1012 | |
1013 | memset(&data, 0, sizeof(data)); |
1014 | |
1015 | /* Userspace wants to query the certificate length. */ |
1016 | if (!input.pdh_cert_address || |
1017 | !input.pdh_cert_len || |
1018 | !input.cert_chain_address) |
1019 | goto cmd; |
1020 | |
1021 | input_pdh_cert_address = (void __user *)input.pdh_cert_address; |
1022 | input_cert_chain_address = (void __user *)input.cert_chain_address; |
1023 | |
1024 | /* Allocate a physically contiguous buffer to store the PDH blob. */ |
1025 | if (input.pdh_cert_len > SEV_FW_BLOB_MAX_SIZE) |
1026 | return -EFAULT; |
1027 | |
1028 | /* Allocate a physically contiguous buffer to store the cert chain blob. */ |
1029 | if (input.cert_chain_len > SEV_FW_BLOB_MAX_SIZE) |
1030 | return -EFAULT; |
1031 | |
1032 | pdh_blob = kzalloc(size: input.pdh_cert_len, GFP_KERNEL); |
1033 | if (!pdh_blob) |
1034 | return -ENOMEM; |
1035 | |
1036 | data.pdh_cert_address = __psp_pa(pdh_blob); |
1037 | data.pdh_cert_len = input.pdh_cert_len; |
1038 | |
1039 | cert_blob = kzalloc(size: input.cert_chain_len, GFP_KERNEL); |
1040 | if (!cert_blob) { |
1041 | ret = -ENOMEM; |
1042 | goto e_free_pdh; |
1043 | } |
1044 | |
1045 | data.cert_chain_address = __psp_pa(cert_blob); |
1046 | data.cert_chain_len = input.cert_chain_len; |
1047 | |
1048 | cmd: |
1049 | ret = __sev_do_cmd_locked(cmd: SEV_CMD_PDH_CERT_EXPORT, data: &data, psp_ret: &argp->error); |
1050 | |
1051 | /* If we query the length, FW responded with expected data. */ |
1052 | input.cert_chain_len = data.cert_chain_len; |
1053 | input.pdh_cert_len = data.pdh_cert_len; |
1054 | |
1055 | if (copy_to_user(to: (void __user *)argp->data, from: &input, n: sizeof(input))) { |
1056 | ret = -EFAULT; |
1057 | goto e_free_cert; |
1058 | } |
1059 | |
1060 | if (pdh_blob) { |
1061 | if (copy_to_user(to: input_pdh_cert_address, |
1062 | from: pdh_blob, n: input.pdh_cert_len)) { |
1063 | ret = -EFAULT; |
1064 | goto e_free_cert; |
1065 | } |
1066 | } |
1067 | |
1068 | if (cert_blob) { |
1069 | if (copy_to_user(to: input_cert_chain_address, |
1070 | from: cert_blob, n: input.cert_chain_len)) |
1071 | ret = -EFAULT; |
1072 | } |
1073 | |
1074 | e_free_cert: |
1075 | kfree(objp: cert_blob); |
1076 | e_free_pdh: |
1077 | kfree(objp: pdh_blob); |
1078 | return ret; |
1079 | } |
1080 | |
1081 | static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg) |
1082 | { |
1083 | void __user *argp = (void __user *)arg; |
1084 | struct sev_issue_cmd input; |
1085 | int ret = -EFAULT; |
1086 | bool writable = file->f_mode & FMODE_WRITE; |
1087 | |
1088 | if (!psp_master || !psp_master->sev_data) |
1089 | return -ENODEV; |
1090 | |
1091 | if (ioctl != SEV_ISSUE_CMD) |
1092 | return -EINVAL; |
1093 | |
1094 | if (copy_from_user(to: &input, from: argp, n: sizeof(struct sev_issue_cmd))) |
1095 | return -EFAULT; |
1096 | |
1097 | if (input.cmd > SEV_MAX) |
1098 | return -EINVAL; |
1099 | |
1100 | mutex_lock(&sev_cmd_mutex); |
1101 | |
1102 | switch (input.cmd) { |
1103 | |
1104 | case SEV_FACTORY_RESET: |
1105 | ret = sev_ioctl_do_reset(argp: &input, writable); |
1106 | break; |
1107 | case SEV_PLATFORM_STATUS: |
1108 | ret = sev_ioctl_do_platform_status(argp: &input); |
1109 | break; |
1110 | case SEV_PEK_GEN: |
1111 | ret = sev_ioctl_do_pek_pdh_gen(cmd: SEV_CMD_PEK_GEN, argp: &input, writable); |
1112 | break; |
1113 | case SEV_PDH_GEN: |
1114 | ret = sev_ioctl_do_pek_pdh_gen(cmd: SEV_CMD_PDH_GEN, argp: &input, writable); |
1115 | break; |
1116 | case SEV_PEK_CSR: |
1117 | ret = sev_ioctl_do_pek_csr(argp: &input, writable); |
1118 | break; |
1119 | case SEV_PEK_CERT_IMPORT: |
1120 | ret = sev_ioctl_do_pek_import(argp: &input, writable); |
1121 | break; |
1122 | case SEV_PDH_CERT_EXPORT: |
1123 | ret = sev_ioctl_do_pdh_export(argp: &input, writable); |
1124 | break; |
1125 | case SEV_GET_ID: |
1126 | pr_warn_once("SEV_GET_ID command is deprecated, use SEV_GET_ID2\n" ); |
1127 | ret = sev_ioctl_do_get_id(argp: &input); |
1128 | break; |
1129 | case SEV_GET_ID2: |
1130 | ret = sev_ioctl_do_get_id2(argp: &input); |
1131 | break; |
1132 | default: |
1133 | ret = -EINVAL; |
1134 | goto out; |
1135 | } |
1136 | |
1137 | if (copy_to_user(to: argp, from: &input, n: sizeof(struct sev_issue_cmd))) |
1138 | ret = -EFAULT; |
1139 | out: |
1140 | mutex_unlock(lock: &sev_cmd_mutex); |
1141 | |
1142 | return ret; |
1143 | } |
1144 | |
1145 | static const struct file_operations sev_fops = { |
1146 | .owner = THIS_MODULE, |
1147 | .unlocked_ioctl = sev_ioctl, |
1148 | }; |
1149 | |
1150 | int sev_platform_status(struct sev_user_data_status *data, int *error) |
1151 | { |
1152 | return sev_do_cmd(cmd: SEV_CMD_PLATFORM_STATUS, data, psp_ret: error); |
1153 | } |
1154 | EXPORT_SYMBOL_GPL(sev_platform_status); |
1155 | |
1156 | int sev_guest_deactivate(struct sev_data_deactivate *data, int *error) |
1157 | { |
1158 | return sev_do_cmd(cmd: SEV_CMD_DEACTIVATE, data, psp_ret: error); |
1159 | } |
1160 | EXPORT_SYMBOL_GPL(sev_guest_deactivate); |
1161 | |
1162 | int sev_guest_activate(struct sev_data_activate *data, int *error) |
1163 | { |
1164 | return sev_do_cmd(cmd: SEV_CMD_ACTIVATE, data, psp_ret: error); |
1165 | } |
1166 | EXPORT_SYMBOL_GPL(sev_guest_activate); |
1167 | |
1168 | int sev_guest_decommission(struct sev_data_decommission *data, int *error) |
1169 | { |
1170 | return sev_do_cmd(cmd: SEV_CMD_DECOMMISSION, data, psp_ret: error); |
1171 | } |
1172 | EXPORT_SYMBOL_GPL(sev_guest_decommission); |
1173 | |
1174 | int sev_guest_df_flush(int *error) |
1175 | { |
1176 | return sev_do_cmd(cmd: SEV_CMD_DF_FLUSH, NULL, psp_ret: error); |
1177 | } |
1178 | EXPORT_SYMBOL_GPL(sev_guest_df_flush); |
1179 | |
1180 | static void sev_exit(struct kref *ref) |
1181 | { |
1182 | misc_deregister(misc: &misc_dev->misc); |
1183 | kfree(objp: misc_dev); |
1184 | misc_dev = NULL; |
1185 | } |
1186 | |
1187 | static int sev_misc_init(struct sev_device *sev) |
1188 | { |
1189 | struct device *dev = sev->dev; |
1190 | int ret; |
1191 | |
1192 | /* |
1193 | * SEV feature support can be detected on multiple devices but the SEV |
1194 | * FW commands must be issued on the master. During probe, we do not |
1195 | * know the master hence we create /dev/sev on the first device probe. |
1196 | * sev_do_cmd() finds the right master device to which to issue the |
1197 | * command to the firmware. |
1198 | */ |
1199 | if (!misc_dev) { |
1200 | struct miscdevice *misc; |
1201 | |
1202 | misc_dev = kzalloc(size: sizeof(*misc_dev), GFP_KERNEL); |
1203 | if (!misc_dev) |
1204 | return -ENOMEM; |
1205 | |
1206 | misc = &misc_dev->misc; |
1207 | misc->minor = MISC_DYNAMIC_MINOR; |
1208 | misc->name = DEVICE_NAME; |
1209 | misc->fops = &sev_fops; |
1210 | |
1211 | ret = misc_register(misc); |
1212 | if (ret) |
1213 | return ret; |
1214 | |
1215 | kref_init(kref: &misc_dev->refcount); |
1216 | } else { |
1217 | kref_get(kref: &misc_dev->refcount); |
1218 | } |
1219 | |
1220 | init_waitqueue_head(&sev->int_queue); |
1221 | sev->misc = misc_dev; |
1222 | dev_dbg(dev, "registered SEV device\n" ); |
1223 | |
1224 | return 0; |
1225 | } |
1226 | |
1227 | int sev_dev_init(struct psp_device *psp) |
1228 | { |
1229 | struct device *dev = psp->dev; |
1230 | struct sev_device *sev; |
1231 | int ret = -ENOMEM; |
1232 | |
1233 | if (!boot_cpu_has(X86_FEATURE_SEV)) { |
1234 | dev_info_once(dev, "SEV: memory encryption not enabled by BIOS\n" ); |
1235 | return 0; |
1236 | } |
1237 | |
1238 | sev = devm_kzalloc(dev, size: sizeof(*sev), GFP_KERNEL); |
1239 | if (!sev) |
1240 | goto e_err; |
1241 | |
1242 | sev->cmd_buf = (void *)devm_get_free_pages(dev, GFP_KERNEL, order: 0); |
1243 | if (!sev->cmd_buf) |
1244 | goto e_sev; |
1245 | |
1246 | psp->sev_data = sev; |
1247 | |
1248 | sev->dev = dev; |
1249 | sev->psp = psp; |
1250 | |
1251 | sev->io_regs = psp->io_regs; |
1252 | |
1253 | sev->vdata = (struct sev_vdata *)psp->vdata->sev; |
1254 | if (!sev->vdata) { |
1255 | ret = -ENODEV; |
1256 | dev_err(dev, "sev: missing driver data\n" ); |
1257 | goto e_buf; |
1258 | } |
1259 | |
1260 | psp_set_sev_irq_handler(psp, handler: sev_irq_handler, data: sev); |
1261 | |
1262 | ret = sev_misc_init(sev); |
1263 | if (ret) |
1264 | goto e_irq; |
1265 | |
1266 | dev_notice(dev, "sev enabled\n" ); |
1267 | |
1268 | return 0; |
1269 | |
1270 | e_irq: |
1271 | psp_clear_sev_irq_handler(psp); |
1272 | e_buf: |
1273 | devm_free_pages(dev, addr: (unsigned long)sev->cmd_buf); |
1274 | e_sev: |
1275 | devm_kfree(dev, p: sev); |
1276 | e_err: |
1277 | psp->sev_data = NULL; |
1278 | |
1279 | dev_notice(dev, "sev initialization failed\n" ); |
1280 | |
1281 | return ret; |
1282 | } |
1283 | |
1284 | static void sev_firmware_shutdown(struct sev_device *sev) |
1285 | { |
1286 | sev_platform_shutdown(NULL); |
1287 | |
1288 | if (sev_es_tmr) { |
1289 | /* The TMR area was encrypted, flush it from the cache */ |
1290 | wbinvd_on_all_cpus(); |
1291 | |
1292 | free_pages(addr: (unsigned long)sev_es_tmr, |
1293 | order: get_order(SEV_ES_TMR_SIZE)); |
1294 | sev_es_tmr = NULL; |
1295 | } |
1296 | |
1297 | if (sev_init_ex_buffer) { |
1298 | free_pages(addr: (unsigned long)sev_init_ex_buffer, |
1299 | order: get_order(NV_LENGTH)); |
1300 | sev_init_ex_buffer = NULL; |
1301 | } |
1302 | } |
1303 | |
1304 | void sev_dev_destroy(struct psp_device *psp) |
1305 | { |
1306 | struct sev_device *sev = psp->sev_data; |
1307 | |
1308 | if (!sev) |
1309 | return; |
1310 | |
1311 | sev_firmware_shutdown(sev); |
1312 | |
1313 | if (sev->misc) |
1314 | kref_put(kref: &misc_dev->refcount, release: sev_exit); |
1315 | |
1316 | psp_clear_sev_irq_handler(psp); |
1317 | } |
1318 | |
1319 | int sev_issue_cmd_external_user(struct file *filep, unsigned int cmd, |
1320 | void *data, int *error) |
1321 | { |
1322 | if (!filep || filep->f_op != &sev_fops) |
1323 | return -EBADF; |
1324 | |
1325 | return sev_do_cmd(cmd, data, psp_ret: error); |
1326 | } |
1327 | EXPORT_SYMBOL_GPL(sev_issue_cmd_external_user); |
1328 | |
1329 | void sev_pci_init(void) |
1330 | { |
1331 | struct sev_device *sev = psp_master->sev_data; |
1332 | int error, rc; |
1333 | |
1334 | if (!sev) |
1335 | return; |
1336 | |
1337 | psp_timeout = psp_probe_timeout; |
1338 | |
1339 | if (sev_get_api_version()) |
1340 | goto err; |
1341 | |
1342 | if (sev_update_firmware(dev: sev->dev) == 0) |
1343 | sev_get_api_version(); |
1344 | |
1345 | /* If an init_ex_path is provided rely on INIT_EX for PSP initialization |
1346 | * instead of INIT. |
1347 | */ |
1348 | if (init_ex_path) { |
1349 | sev_init_ex_buffer = sev_fw_alloc(NV_LENGTH); |
1350 | if (!sev_init_ex_buffer) { |
1351 | dev_err(sev->dev, |
1352 | "SEV: INIT_EX NV memory allocation failed\n" ); |
1353 | goto err; |
1354 | } |
1355 | } |
1356 | |
1357 | /* Obtain the TMR memory area for SEV-ES use */ |
1358 | sev_es_tmr = sev_fw_alloc(SEV_ES_TMR_SIZE); |
1359 | if (sev_es_tmr) |
1360 | /* Must flush the cache before giving it to the firmware */ |
1361 | clflush_cache_range(addr: sev_es_tmr, SEV_ES_TMR_SIZE); |
1362 | else |
1363 | dev_warn(sev->dev, |
1364 | "SEV: TMR allocation failed, SEV-ES support unavailable\n" ); |
1365 | |
1366 | if (!psp_init_on_probe) |
1367 | return; |
1368 | |
1369 | /* Initialize the platform */ |
1370 | rc = sev_platform_init(&error); |
1371 | if (rc) |
1372 | dev_err(sev->dev, "SEV: failed to INIT error %#x, rc %d\n" , |
1373 | error, rc); |
1374 | |
1375 | return; |
1376 | |
1377 | err: |
1378 | psp_master->sev_data = NULL; |
1379 | } |
1380 | |
1381 | void sev_pci_exit(void) |
1382 | { |
1383 | struct sev_device *sev = psp_master->sev_data; |
1384 | |
1385 | if (!sev) |
1386 | return; |
1387 | |
1388 | sev_firmware_shutdown(sev); |
1389 | } |
1390 | |