.. | .. |
---|
23 | 23 | #include <linux/gfp.h> |
---|
24 | 24 | |
---|
25 | 25 | #include <asm/smp.h> |
---|
| 26 | +#include <asm/cacheflush.h> |
---|
26 | 27 | |
---|
27 | 28 | #include "psp-dev.h" |
---|
28 | 29 | #include "sev-dev.h" |
---|
.. | .. |
---|
138 | 139 | return 0; |
---|
139 | 140 | } |
---|
140 | 141 | |
---|
| 142 | +static void *sev_fw_alloc(unsigned long len) |
---|
| 143 | +{ |
---|
| 144 | + struct page *page; |
---|
| 145 | + |
---|
| 146 | + page = alloc_pages(GFP_KERNEL, get_order(len)); |
---|
| 147 | + if (!page) |
---|
| 148 | + return NULL; |
---|
| 149 | + |
---|
| 150 | + return page_address(page); |
---|
| 151 | +} |
---|
| 152 | + |
---|
141 | 153 | static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret) |
---|
142 | 154 | { |
---|
143 | 155 | struct psp_device *psp = psp_master; |
---|
144 | 156 | struct sev_device *sev; |
---|
145 | 157 | unsigned int phys_lsb, phys_msb; |
---|
146 | 158 | unsigned int reg, ret = 0; |
---|
| 159 | + int buf_len; |
---|
147 | 160 | |
---|
148 | 161 | if (!psp || !psp->sev_data) |
---|
149 | 162 | return -ENODEV; |
---|
.. | .. |
---|
153 | 166 | |
---|
154 | 167 | sev = psp->sev_data; |
---|
155 | 168 | |
---|
156 | | - if (data && WARN_ON_ONCE(!virt_addr_valid(data))) |
---|
| 169 | + buf_len = sev_cmd_buffer_len(cmd); |
---|
| 170 | + if (WARN_ON_ONCE(!data != !buf_len)) |
---|
157 | 171 | return -EINVAL; |
---|
158 | 172 | |
---|
| 173 | + /* |
---|
| 174 | + * Copy the incoming data to driver's scratch buffer as __pa() will not |
---|
| 175 | + * work for some memory, e.g. vmalloc'd addresses, and @data may not be |
---|
| 176 | + * physically contiguous. |
---|
| 177 | + */ |
---|
| 178 | + if (data) |
---|
| 179 | + memcpy(sev->cmd_buf, data, buf_len); |
---|
| 180 | + |
---|
159 | 181 | /* Get the physical address of the command buffer */ |
---|
160 | | - phys_lsb = data ? lower_32_bits(__psp_pa(data)) : 0; |
---|
161 | | - phys_msb = data ? upper_32_bits(__psp_pa(data)) : 0; |
---|
| 182 | + phys_lsb = data ? lower_32_bits(__psp_pa(sev->cmd_buf)) : 0; |
---|
| 183 | + phys_msb = data ? upper_32_bits(__psp_pa(sev->cmd_buf)) : 0; |
---|
162 | 184 | |
---|
163 | 185 | dev_dbg(sev->dev, "sev command id %#x buffer 0x%08x%08x timeout %us\n", |
---|
164 | 186 | cmd, phys_msb, phys_lsb, psp_timeout); |
---|
165 | 187 | |
---|
166 | 188 | print_hex_dump_debug("(in): ", DUMP_PREFIX_OFFSET, 16, 2, data, |
---|
167 | | - sev_cmd_buffer_len(cmd), false); |
---|
| 189 | + buf_len, false); |
---|
168 | 190 | |
---|
169 | 191 | iowrite32(phys_lsb, sev->io_regs + sev->vdata->cmdbuff_addr_lo_reg); |
---|
170 | 192 | iowrite32(phys_msb, sev->io_regs + sev->vdata->cmdbuff_addr_hi_reg); |
---|
.. | .. |
---|
200 | 222 | } |
---|
201 | 223 | |
---|
202 | 224 | print_hex_dump_debug("(out): ", DUMP_PREFIX_OFFSET, 16, 2, data, |
---|
203 | | - sev_cmd_buffer_len(cmd), false); |
---|
| 225 | + buf_len, false); |
---|
| 226 | + |
---|
| 227 | + /* |
---|
| 228 | + * Copy potential output from the PSP back to data. Do this even on |
---|
| 229 | + * failure in case the caller wants to glean something from the error. |
---|
| 230 | + */ |
---|
| 231 | + if (data) |
---|
| 232 | + memcpy(data, sev->cmd_buf, buf_len); |
---|
204 | 233 | |
---|
205 | 234 | return ret; |
---|
206 | 235 | } |
---|
.. | .. |
---|
304 | 333 | |
---|
305 | 334 | static int sev_get_platform_state(int *state, int *error) |
---|
306 | 335 | { |
---|
307 | | - struct sev_device *sev = psp_master->sev_data; |
---|
| 336 | + struct sev_user_data_status data; |
---|
308 | 337 | int rc; |
---|
309 | 338 | |
---|
310 | | - rc = __sev_do_cmd_locked(SEV_CMD_PLATFORM_STATUS, |
---|
311 | | - &sev->status_cmd_buf, error); |
---|
| 339 | + rc = __sev_do_cmd_locked(SEV_CMD_PLATFORM_STATUS, &data, error); |
---|
312 | 340 | if (rc) |
---|
313 | 341 | return rc; |
---|
314 | 342 | |
---|
315 | | - *state = sev->status_cmd_buf.state; |
---|
| 343 | + *state = data.state; |
---|
316 | 344 | return rc; |
---|
317 | 345 | } |
---|
318 | 346 | |
---|
.. | .. |
---|
350 | 378 | |
---|
351 | 379 | static int sev_ioctl_do_platform_status(struct sev_issue_cmd *argp) |
---|
352 | 380 | { |
---|
353 | | - struct sev_device *sev = psp_master->sev_data; |
---|
354 | | - struct sev_user_data_status *data = &sev->status_cmd_buf; |
---|
| 381 | + struct sev_user_data_status data; |
---|
355 | 382 | int ret; |
---|
356 | 383 | |
---|
357 | | - ret = __sev_do_cmd_locked(SEV_CMD_PLATFORM_STATUS, data, &argp->error); |
---|
| 384 | + memset(&data, 0, sizeof(data)); |
---|
| 385 | + |
---|
| 386 | + ret = __sev_do_cmd_locked(SEV_CMD_PLATFORM_STATUS, &data, &argp->error); |
---|
358 | 387 | if (ret) |
---|
359 | 388 | return ret; |
---|
360 | 389 | |
---|
361 | | - if (copy_to_user((void __user *)argp->data, data, sizeof(*data))) |
---|
| 390 | + if (copy_to_user((void __user *)argp->data, &data, sizeof(data))) |
---|
362 | 391 | ret = -EFAULT; |
---|
363 | 392 | |
---|
364 | 393 | return ret; |
---|
.. | .. |
---|
385 | 414 | { |
---|
386 | 415 | struct sev_device *sev = psp_master->sev_data; |
---|
387 | 416 | struct sev_user_data_pek_csr input; |
---|
388 | | - struct sev_data_pek_csr *data; |
---|
| 417 | + struct sev_data_pek_csr data; |
---|
389 | 418 | void __user *input_address; |
---|
390 | 419 | void *blob = NULL; |
---|
391 | 420 | int ret; |
---|
.. | .. |
---|
396 | 425 | if (copy_from_user(&input, (void __user *)argp->data, sizeof(input))) |
---|
397 | 426 | return -EFAULT; |
---|
398 | 427 | |
---|
399 | | - data = kzalloc(sizeof(*data), GFP_KERNEL); |
---|
400 | | - if (!data) |
---|
401 | | - return -ENOMEM; |
---|
| 428 | + memset(&data, 0, sizeof(data)); |
---|
402 | 429 | |
---|
403 | 430 | /* userspace wants to query CSR length */ |
---|
404 | 431 | if (!input.address || !input.length) |
---|
.. | .. |
---|
406 | 433 | |
---|
407 | 434 | /* allocate a physically contiguous buffer to store the CSR blob */ |
---|
408 | 435 | input_address = (void __user *)input.address; |
---|
409 | | - if (input.length > SEV_FW_BLOB_MAX_SIZE) { |
---|
410 | | - ret = -EFAULT; |
---|
411 | | - goto e_free; |
---|
412 | | - } |
---|
| 436 | + if (input.length > SEV_FW_BLOB_MAX_SIZE) |
---|
| 437 | + return -EFAULT; |
---|
413 | 438 | |
---|
414 | | - blob = kmalloc(input.length, GFP_KERNEL); |
---|
415 | | - if (!blob) { |
---|
416 | | - ret = -ENOMEM; |
---|
417 | | - goto e_free; |
---|
418 | | - } |
---|
| 439 | + blob = kzalloc(input.length, GFP_KERNEL); |
---|
| 440 | + if (!blob) |
---|
| 441 | + return -ENOMEM; |
---|
419 | 442 | |
---|
420 | | - data->address = __psp_pa(blob); |
---|
421 | | - data->len = input.length; |
---|
| 443 | + data.address = __psp_pa(blob); |
---|
| 444 | + data.len = input.length; |
---|
422 | 445 | |
---|
423 | 446 | cmd: |
---|
424 | 447 | if (sev->state == SEV_STATE_UNINIT) { |
---|
.. | .. |
---|
427 | 450 | goto e_free_blob; |
---|
428 | 451 | } |
---|
429 | 452 | |
---|
430 | | - ret = __sev_do_cmd_locked(SEV_CMD_PEK_CSR, data, &argp->error); |
---|
| 453 | + ret = __sev_do_cmd_locked(SEV_CMD_PEK_CSR, &data, &argp->error); |
---|
431 | 454 | |
---|
432 | 455 | /* If we query the CSR length, FW responded with expected data. */ |
---|
433 | | - input.length = data->len; |
---|
| 456 | + input.length = data.len; |
---|
434 | 457 | |
---|
435 | 458 | if (copy_to_user((void __user *)argp->data, &input, sizeof(input))) { |
---|
436 | 459 | ret = -EFAULT; |
---|
.. | .. |
---|
444 | 467 | |
---|
445 | 468 | e_free_blob: |
---|
446 | 469 | kfree(blob); |
---|
447 | | -e_free: |
---|
448 | | - kfree(data); |
---|
449 | 470 | return ret; |
---|
450 | 471 | } |
---|
451 | 472 | |
---|
.. | .. |
---|
465 | 486 | static int sev_get_api_version(void) |
---|
466 | 487 | { |
---|
467 | 488 | struct sev_device *sev = psp_master->sev_data; |
---|
468 | | - struct sev_user_data_status *status; |
---|
| 489 | + struct sev_user_data_status status; |
---|
469 | 490 | int error = 0, ret; |
---|
470 | 491 | |
---|
471 | | - status = &sev->status_cmd_buf; |
---|
472 | | - ret = sev_platform_status(status, &error); |
---|
| 492 | + ret = sev_platform_status(&status, &error); |
---|
473 | 493 | if (ret) { |
---|
474 | 494 | dev_err(sev->dev, |
---|
475 | 495 | "SEV: failed to get status. Error: %#x\n", error); |
---|
476 | 496 | return 1; |
---|
477 | 497 | } |
---|
478 | 498 | |
---|
479 | | - sev->api_major = status->api_major; |
---|
480 | | - sev->api_minor = status->api_minor; |
---|
481 | | - sev->build = status->build; |
---|
482 | | - sev->state = status->state; |
---|
| 499 | + sev->api_major = status.api_major; |
---|
| 500 | + sev->api_minor = status.api_minor; |
---|
| 501 | + sev->build = status.build; |
---|
| 502 | + sev->state = status.state; |
---|
483 | 503 | |
---|
484 | 504 | return 0; |
---|
485 | 505 | } |
---|
.. | .. |
---|
577 | 597 | { |
---|
578 | 598 | struct sev_device *sev = psp_master->sev_data; |
---|
579 | 599 | struct sev_user_data_pek_cert_import input; |
---|
580 | | - struct sev_data_pek_cert_import *data; |
---|
| 600 | + struct sev_data_pek_cert_import data; |
---|
581 | 601 | void *pek_blob, *oca_blob; |
---|
582 | 602 | int ret; |
---|
583 | 603 | |
---|
.. | .. |
---|
587 | 607 | if (copy_from_user(&input, (void __user *)argp->data, sizeof(input))) |
---|
588 | 608 | return -EFAULT; |
---|
589 | 609 | |
---|
590 | | - data = kzalloc(sizeof(*data), GFP_KERNEL); |
---|
591 | | - if (!data) |
---|
592 | | - return -ENOMEM; |
---|
593 | | - |
---|
594 | 610 | /* copy PEK certificate blobs from userspace */ |
---|
595 | 611 | pek_blob = psp_copy_user_blob(input.pek_cert_address, input.pek_cert_len); |
---|
596 | | - if (IS_ERR(pek_blob)) { |
---|
597 | | - ret = PTR_ERR(pek_blob); |
---|
598 | | - goto e_free; |
---|
599 | | - } |
---|
| 612 | + if (IS_ERR(pek_blob)) |
---|
| 613 | + return PTR_ERR(pek_blob); |
---|
600 | 614 | |
---|
601 | | - data->pek_cert_address = __psp_pa(pek_blob); |
---|
602 | | - data->pek_cert_len = input.pek_cert_len; |
---|
| 615 | + data.reserved = 0; |
---|
| 616 | + data.pek_cert_address = __psp_pa(pek_blob); |
---|
| 617 | + data.pek_cert_len = input.pek_cert_len; |
---|
603 | 618 | |
---|
604 | 619 | /* copy PEK certificate blobs from userspace */ |
---|
605 | 620 | oca_blob = psp_copy_user_blob(input.oca_cert_address, input.oca_cert_len); |
---|
.. | .. |
---|
608 | 623 | goto e_free_pek; |
---|
609 | 624 | } |
---|
610 | 625 | |
---|
611 | | - data->oca_cert_address = __psp_pa(oca_blob); |
---|
612 | | - data->oca_cert_len = input.oca_cert_len; |
---|
| 626 | + data.oca_cert_address = __psp_pa(oca_blob); |
---|
| 627 | + data.oca_cert_len = input.oca_cert_len; |
---|
613 | 628 | |
---|
614 | 629 | /* If platform is not in INIT state then transition it to INIT */ |
---|
615 | 630 | if (sev->state != SEV_STATE_INIT) { |
---|
.. | .. |
---|
618 | 633 | goto e_free_oca; |
---|
619 | 634 | } |
---|
620 | 635 | |
---|
621 | | - ret = __sev_do_cmd_locked(SEV_CMD_PEK_CERT_IMPORT, data, &argp->error); |
---|
| 636 | + ret = __sev_do_cmd_locked(SEV_CMD_PEK_CERT_IMPORT, &data, &argp->error); |
---|
622 | 637 | |
---|
623 | 638 | e_free_oca: |
---|
624 | 639 | kfree(oca_blob); |
---|
625 | 640 | e_free_pek: |
---|
626 | 641 | kfree(pek_blob); |
---|
627 | | -e_free: |
---|
628 | | - kfree(data); |
---|
629 | 642 | return ret; |
---|
630 | 643 | } |
---|
631 | 644 | |
---|
632 | 645 | static int sev_ioctl_do_get_id2(struct sev_issue_cmd *argp) |
---|
633 | 646 | { |
---|
634 | 647 | struct sev_user_data_get_id2 input; |
---|
635 | | - struct sev_data_get_id *data; |
---|
| 648 | + struct sev_data_get_id data; |
---|
636 | 649 | void __user *input_address; |
---|
637 | 650 | void *id_blob = NULL; |
---|
638 | 651 | int ret; |
---|
.. | .. |
---|
646 | 659 | |
---|
647 | 660 | input_address = (void __user *)input.address; |
---|
648 | 661 | |
---|
649 | | - data = kzalloc(sizeof(*data), GFP_KERNEL); |
---|
650 | | - if (!data) |
---|
651 | | - return -ENOMEM; |
---|
652 | | - |
---|
653 | 662 | if (input.address && input.length) { |
---|
654 | | - id_blob = kmalloc(input.length, GFP_KERNEL); |
---|
655 | | - if (!id_blob) { |
---|
656 | | - kfree(data); |
---|
| 663 | + /* |
---|
| 664 | + * The length of the ID shouldn't be assumed by software since |
---|
| 665 | + * it may change in the future. The allocation size is limited |
---|
| 666 | + * to 1 << (PAGE_SHIFT + MAX_ORDER - 1) by the page allocator. |
---|
| 667 | + * If the allocation fails, simply return ENOMEM rather than |
---|
| 668 | + * warning in the kernel log. |
---|
| 669 | + */ |
---|
| 670 | + id_blob = kzalloc(input.length, GFP_KERNEL | __GFP_NOWARN); |
---|
| 671 | + if (!id_blob) |
---|
657 | 672 | return -ENOMEM; |
---|
658 | | - } |
---|
659 | 673 | |
---|
660 | | - data->address = __psp_pa(id_blob); |
---|
661 | | - data->len = input.length; |
---|
| 674 | + data.address = __psp_pa(id_blob); |
---|
| 675 | + data.len = input.length; |
---|
| 676 | + } else { |
---|
| 677 | + data.address = 0; |
---|
| 678 | + data.len = 0; |
---|
662 | 679 | } |
---|
663 | 680 | |
---|
664 | | - ret = __sev_do_cmd_locked(SEV_CMD_GET_ID, data, &argp->error); |
---|
| 681 | + ret = __sev_do_cmd_locked(SEV_CMD_GET_ID, &data, &argp->error); |
---|
665 | 682 | |
---|
666 | 683 | /* |
---|
667 | 684 | * Firmware will return the length of the ID value (either the minimum |
---|
668 | 685 | * required length or the actual length written), return it to the user. |
---|
669 | 686 | */ |
---|
670 | | - input.length = data->len; |
---|
| 687 | + input.length = data.len; |
---|
671 | 688 | |
---|
672 | 689 | if (copy_to_user((void __user *)argp->data, &input, sizeof(input))) { |
---|
673 | 690 | ret = -EFAULT; |
---|
.. | .. |
---|
675 | 692 | } |
---|
676 | 693 | |
---|
677 | 694 | if (id_blob) { |
---|
678 | | - if (copy_to_user(input_address, id_blob, data->len)) { |
---|
| 695 | + if (copy_to_user(input_address, id_blob, data.len)) { |
---|
679 | 696 | ret = -EFAULT; |
---|
680 | 697 | goto e_free; |
---|
681 | 698 | } |
---|
.. | .. |
---|
683 | 700 | |
---|
684 | 701 | e_free: |
---|
685 | 702 | kfree(id_blob); |
---|
686 | | - kfree(data); |
---|
687 | 703 | |
---|
688 | 704 | return ret; |
---|
689 | 705 | } |
---|
.. | .. |
---|
733 | 749 | struct sev_device *sev = psp_master->sev_data; |
---|
734 | 750 | struct sev_user_data_pdh_cert_export input; |
---|
735 | 751 | void *pdh_blob = NULL, *cert_blob = NULL; |
---|
736 | | - struct sev_data_pdh_cert_export *data; |
---|
| 752 | + struct sev_data_pdh_cert_export data; |
---|
737 | 753 | void __user *input_cert_chain_address; |
---|
738 | 754 | void __user *input_pdh_cert_address; |
---|
739 | 755 | int ret; |
---|
.. | .. |
---|
751 | 767 | if (copy_from_user(&input, (void __user *)argp->data, sizeof(input))) |
---|
752 | 768 | return -EFAULT; |
---|
753 | 769 | |
---|
754 | | - data = kzalloc(sizeof(*data), GFP_KERNEL); |
---|
755 | | - if (!data) |
---|
756 | | - return -ENOMEM; |
---|
| 770 | + memset(&data, 0, sizeof(data)); |
---|
757 | 771 | |
---|
758 | 772 | /* Userspace wants to query the certificate length. */ |
---|
759 | 773 | if (!input.pdh_cert_address || |
---|
.. | .. |
---|
765 | 779 | input_cert_chain_address = (void __user *)input.cert_chain_address; |
---|
766 | 780 | |
---|
767 | 781 | /* Allocate a physically contiguous buffer to store the PDH blob. */ |
---|
768 | | - if (input.pdh_cert_len > SEV_FW_BLOB_MAX_SIZE) { |
---|
769 | | - ret = -EFAULT; |
---|
770 | | - goto e_free; |
---|
771 | | - } |
---|
| 782 | + if (input.pdh_cert_len > SEV_FW_BLOB_MAX_SIZE) |
---|
| 783 | + return -EFAULT; |
---|
772 | 784 | |
---|
773 | 785 | /* Allocate a physically contiguous buffer to store the cert chain blob. */ |
---|
774 | | - if (input.cert_chain_len > SEV_FW_BLOB_MAX_SIZE) { |
---|
775 | | - ret = -EFAULT; |
---|
776 | | - goto e_free; |
---|
777 | | - } |
---|
| 786 | + if (input.cert_chain_len > SEV_FW_BLOB_MAX_SIZE) |
---|
| 787 | + return -EFAULT; |
---|
778 | 788 | |
---|
779 | | - pdh_blob = kmalloc(input.pdh_cert_len, GFP_KERNEL); |
---|
780 | | - if (!pdh_blob) { |
---|
781 | | - ret = -ENOMEM; |
---|
782 | | - goto e_free; |
---|
783 | | - } |
---|
| 789 | + pdh_blob = kzalloc(input.pdh_cert_len, GFP_KERNEL); |
---|
| 790 | + if (!pdh_blob) |
---|
| 791 | + return -ENOMEM; |
---|
784 | 792 | |
---|
785 | | - data->pdh_cert_address = __psp_pa(pdh_blob); |
---|
786 | | - data->pdh_cert_len = input.pdh_cert_len; |
---|
| 793 | + data.pdh_cert_address = __psp_pa(pdh_blob); |
---|
| 794 | + data.pdh_cert_len = input.pdh_cert_len; |
---|
787 | 795 | |
---|
788 | | - cert_blob = kmalloc(input.cert_chain_len, GFP_KERNEL); |
---|
| 796 | + cert_blob = kzalloc(input.cert_chain_len, GFP_KERNEL); |
---|
789 | 797 | if (!cert_blob) { |
---|
790 | 798 | ret = -ENOMEM; |
---|
791 | 799 | goto e_free_pdh; |
---|
792 | 800 | } |
---|
793 | 801 | |
---|
794 | | - data->cert_chain_address = __psp_pa(cert_blob); |
---|
795 | | - data->cert_chain_len = input.cert_chain_len; |
---|
| 802 | + data.cert_chain_address = __psp_pa(cert_blob); |
---|
| 803 | + data.cert_chain_len = input.cert_chain_len; |
---|
796 | 804 | |
---|
797 | 805 | cmd: |
---|
798 | | - ret = __sev_do_cmd_locked(SEV_CMD_PDH_CERT_EXPORT, data, &argp->error); |
---|
| 806 | + ret = __sev_do_cmd_locked(SEV_CMD_PDH_CERT_EXPORT, &data, &argp->error); |
---|
799 | 807 | |
---|
800 | 808 | /* If we query the length, FW responded with expected data. */ |
---|
801 | | - input.cert_chain_len = data->cert_chain_len; |
---|
802 | | - input.pdh_cert_len = data->pdh_cert_len; |
---|
| 809 | + input.cert_chain_len = data.cert_chain_len; |
---|
| 810 | + input.pdh_cert_len = data.pdh_cert_len; |
---|
803 | 811 | |
---|
804 | 812 | if (copy_to_user((void __user *)argp->data, &input, sizeof(input))) { |
---|
805 | 813 | ret = -EFAULT; |
---|
.. | .. |
---|
824 | 832 | kfree(cert_blob); |
---|
825 | 833 | e_free_pdh: |
---|
826 | 834 | kfree(pdh_blob); |
---|
827 | | -e_free: |
---|
828 | | - kfree(data); |
---|
829 | 835 | return ret; |
---|
830 | 836 | } |
---|
831 | 837 | |
---|
.. | .. |
---|
985 | 991 | if (!sev) |
---|
986 | 992 | goto e_err; |
---|
987 | 993 | |
---|
| 994 | + sev->cmd_buf = (void *)devm_get_free_pages(dev, GFP_KERNEL, 0); |
---|
| 995 | + if (!sev->cmd_buf) |
---|
| 996 | + goto e_sev; |
---|
| 997 | + |
---|
988 | 998 | psp->sev_data = sev; |
---|
989 | 999 | |
---|
990 | 1000 | sev->dev = dev; |
---|
.. | .. |
---|
996 | 1006 | if (!sev->vdata) { |
---|
997 | 1007 | ret = -ENODEV; |
---|
998 | 1008 | dev_err(dev, "sev: missing driver data\n"); |
---|
999 | | - goto e_sev; |
---|
| 1009 | + goto e_buf; |
---|
1000 | 1010 | } |
---|
1001 | 1011 | |
---|
1002 | 1012 | psp_set_sev_irq_handler(psp, sev_irq_handler, sev); |
---|
.. | .. |
---|
1011 | 1021 | |
---|
1012 | 1022 | e_irq: |
---|
1013 | 1023 | psp_clear_sev_irq_handler(psp); |
---|
| 1024 | +e_buf: |
---|
| 1025 | + devm_free_pages(dev, (unsigned long)sev->cmd_buf); |
---|
1014 | 1026 | e_sev: |
---|
1015 | 1027 | devm_kfree(dev, sev); |
---|
1016 | 1028 | e_err: |
---|
.. | .. |
---|
1063 | 1075 | void sev_pci_init(void) |
---|
1064 | 1076 | { |
---|
1065 | 1077 | struct sev_device *sev = psp_master->sev_data; |
---|
1066 | | - struct page *tmr_page; |
---|
1067 | 1078 | int error, rc; |
---|
1068 | 1079 | |
---|
1069 | 1080 | if (!sev) |
---|
.. | .. |
---|
1079 | 1090 | sev_get_api_version(); |
---|
1080 | 1091 | |
---|
1081 | 1092 | /* Obtain the TMR memory area for SEV-ES use */ |
---|
1082 | | - tmr_page = alloc_pages(GFP_KERNEL, get_order(SEV_ES_TMR_SIZE)); |
---|
1083 | | - if (tmr_page) { |
---|
1084 | | - sev_es_tmr = page_address(tmr_page); |
---|
1085 | | - } else { |
---|
1086 | | - sev_es_tmr = NULL; |
---|
| 1093 | + sev_es_tmr = sev_fw_alloc(SEV_ES_TMR_SIZE); |
---|
| 1094 | + if (sev_es_tmr) |
---|
| 1095 | + /* Must flush the cache before giving it to the firmware */ |
---|
| 1096 | + clflush_cache_range(sev_es_tmr, SEV_ES_TMR_SIZE); |
---|
| 1097 | + else |
---|
1087 | 1098 | dev_warn(sev->dev, |
---|
1088 | 1099 | "SEV: TMR allocation failed, SEV-ES support unavailable\n"); |
---|
1089 | | - } |
---|
1090 | 1100 | |
---|
1091 | 1101 | /* Initialize the platform */ |
---|
1092 | 1102 | rc = sev_platform_init(&error); |
---|