|
13 | 13 | #include <linux/slab.h>
|
14 | 14 | #include <linux/vmalloc.h>
|
15 | 15 | #include <linux/mmiotrace.h>
|
| 16 | +#include <linux/mem_encrypt.h> |
| 17 | +#include <linux/efi.h> |
16 | 18 |
|
17 | 19 | #include <asm/set_memory.h>
|
18 | 20 | #include <asm/e820/api.h>
|
|
21 | 23 | #include <asm/tlbflush.h>
|
22 | 24 | #include <asm/pgalloc.h>
|
23 | 25 | #include <asm/pat.h>
|
| 26 | +#include <asm/setup.h> |
24 | 27 |
|
25 | 28 | #include "physaddr.h"
|
26 | 29 |
|
@@ -417,6 +420,183 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
|
417 | 420 | iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
|
418 | 421 | }
|
419 | 422 |
|
| 423 | +/* |
| 424 | + * Examine the physical address to determine if it is an area of memory |
| 425 | + * that should be mapped decrypted. If the memory is not part of the |
| 426 | + * kernel usable area it was accessed and created decrypted, so these |
| 427 | + * areas should be mapped decrypted. |
| 428 | + */ |
| 429 | +static bool memremap_should_map_decrypted(resource_size_t phys_addr, |
| 430 | + unsigned long size) |
| 431 | +{ |
| 432 | + /* Check if the address is outside kernel usable area */ |
| 433 | + switch (e820__get_entry_type(phys_addr, phys_addr + size - 1)) { |
| 434 | + case E820_TYPE_RESERVED: |
| 435 | + case E820_TYPE_ACPI: |
| 436 | + case E820_TYPE_NVS: |
| 437 | + case E820_TYPE_UNUSABLE: |
| 438 | + return true; |
| 439 | + default: |
| 440 | + break; |
| 441 | + } |
| 442 | + |
| 443 | + return false; |
| 444 | +} |
| 445 | + |
| 446 | +/* |
| 447 | + * Examine the physical address to determine if it is EFI data. Check |
| 448 | + * it against the boot params structure and EFI tables and memory types. |
| 449 | + */ |
| 450 | +static bool memremap_is_efi_data(resource_size_t phys_addr, |
| 451 | + unsigned long size) |
| 452 | +{ |
| 453 | + u64 paddr; |
| 454 | + |
| 455 | + /* Check if the address is part of EFI boot/runtime data */ |
| 456 | + if (!efi_enabled(EFI_BOOT)) |
| 457 | + return false; |
| 458 | + |
| 459 | + paddr = boot_params.efi_info.efi_memmap_hi; |
| 460 | + paddr <<= 32; |
| 461 | + paddr |= boot_params.efi_info.efi_memmap; |
| 462 | + if (phys_addr == paddr) |
| 463 | + return true; |
| 464 | + |
| 465 | + paddr = boot_params.efi_info.efi_systab_hi; |
| 466 | + paddr <<= 32; |
| 467 | + paddr |= boot_params.efi_info.efi_systab; |
| 468 | + if (phys_addr == paddr) |
| 469 | + return true; |
| 470 | + |
| 471 | + if (efi_is_table_address(phys_addr)) |
| 472 | + return true; |
| 473 | + |
| 474 | + switch (efi_mem_type(phys_addr)) { |
| 475 | + case EFI_BOOT_SERVICES_DATA: |
| 476 | + case EFI_RUNTIME_SERVICES_DATA: |
| 477 | + return true; |
| 478 | + default: |
| 479 | + break; |
| 480 | + } |
| 481 | + |
| 482 | + return false; |
| 483 | +} |
| 484 | + |
| 485 | +/* |
| 486 | + * Examine the physical address to determine if it is boot data by checking |
| 487 | + * it against the boot params setup_data chain. |
| 488 | + */ |
| 489 | +static bool memremap_is_setup_data(resource_size_t phys_addr, |
| 490 | + unsigned long size) |
| 491 | +{ |
| 492 | + struct setup_data *data; |
| 493 | + u64 paddr, paddr_next; |
| 494 | + |
| 495 | + paddr = boot_params.hdr.setup_data; |
| 496 | + while (paddr) { |
| 497 | + unsigned int len; |
| 498 | + |
| 499 | + if (phys_addr == paddr) |
| 500 | + return true; |
| 501 | + |
| 502 | + data = memremap(paddr, sizeof(*data), |
| 503 | + MEMREMAP_WB | MEMREMAP_DEC); |
| 504 | + |
| 505 | + paddr_next = data->next; |
| 506 | + len = data->len; |
| 507 | + |
| 508 | + memunmap(data); |
| 509 | + |
| 510 | + if ((phys_addr > paddr) && (phys_addr < (paddr + len))) |
| 511 | + return true; |
| 512 | + |
| 513 | + paddr = paddr_next; |
| 514 | + } |
| 515 | + |
| 516 | + return false; |
| 517 | +} |
| 518 | + |
| 519 | +/* |
| 520 | + * Examine the physical address to determine if it is boot data by checking |
| 521 | + * it against the boot params setup_data chain (early boot version). |
| 522 | + */ |
| 523 | +static bool __init early_memremap_is_setup_data(resource_size_t phys_addr, |
| 524 | + unsigned long size) |
| 525 | +{ |
| 526 | + struct setup_data *data; |
| 527 | + u64 paddr, paddr_next; |
| 528 | + |
| 529 | + paddr = boot_params.hdr.setup_data; |
| 530 | + while (paddr) { |
| 531 | + unsigned int len; |
| 532 | + |
| 533 | + if (phys_addr == paddr) |
| 534 | + return true; |
| 535 | + |
| 536 | + data = early_memremap_decrypted(paddr, sizeof(*data)); |
| 537 | + |
| 538 | + paddr_next = data->next; |
| 539 | + len = data->len; |
| 540 | + |
| 541 | + early_memunmap(data, sizeof(*data)); |
| 542 | + |
| 543 | + if ((phys_addr > paddr) && (phys_addr < (paddr + len))) |
| 544 | + return true; |
| 545 | + |
| 546 | + paddr = paddr_next; |
| 547 | + } |
| 548 | + |
| 549 | + return false; |
| 550 | +} |
| 551 | + |
| 552 | +/* |
| 553 | + * Architecture function to determine if RAM remap is allowed. By default, a |
| 554 | + * RAM remap will map the data as encrypted. Determine if a RAM remap should |
| 555 | + * not be done so that the data will be mapped decrypted. |
| 556 | + */ |
| 557 | +bool arch_memremap_can_ram_remap(resource_size_t phys_addr, unsigned long size, |
| 558 | + unsigned long flags) |
| 559 | +{ |
| 560 | + if (!sme_active()) |
| 561 | + return true; |
| 562 | + |
| 563 | + if (flags & MEMREMAP_ENC) |
| 564 | + return true; |
| 565 | + |
| 566 | + if (flags & MEMREMAP_DEC) |
| 567 | + return false; |
| 568 | + |
| 569 | + if (memremap_is_setup_data(phys_addr, size) || |
| 570 | + memremap_is_efi_data(phys_addr, size) || |
| 571 | + memremap_should_map_decrypted(phys_addr, size)) |
| 572 | + return false; |
| 573 | + |
| 574 | + return true; |
| 575 | +} |
| 576 | + |
| 577 | +/* |
| 578 | + * Architecture override of __weak function to adjust the protection attributes |
| 579 | + * used when remapping memory. By default, early_memremap() will map the data |
| 580 | + * as encrypted. Determine if an encrypted mapping should not be done and set |
| 581 | + * the appropriate protection attributes. |
| 582 | + */ |
| 583 | +pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr, |
| 584 | + unsigned long size, |
| 585 | + pgprot_t prot) |
| 586 | +{ |
| 587 | + if (!sme_active()) |
| 588 | + return prot; |
| 589 | + |
| 590 | + if (early_memremap_is_setup_data(phys_addr, size) || |
| 591 | + memremap_is_efi_data(phys_addr, size) || |
| 592 | + memremap_should_map_decrypted(phys_addr, size)) |
| 593 | + prot = pgprot_decrypted(prot); |
| 594 | + else |
| 595 | + prot = pgprot_encrypted(prot); |
| 596 | + |
| 597 | + return prot; |
| 598 | +} |
| 599 | + |
420 | 600 | #ifdef CONFIG_ARCH_USE_MEMREMAP_PROT
|
421 | 601 | /* Remap memory with encryption */
|
422 | 602 | void __init *early_memremap_encrypted(resource_size_t phys_addr,
|
|
0 commit comments