| .. | .. |
|---|
| 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); |
|---|