Pull x86 SEV updates from Borislav Petkov: - Add the necessary glue so that the kernel can run as a confidential SEV-SNP vTOM guest on Hyper-V. A vTOM guest basically splits the address space in two parts: encrypted and unencrypted. The use case being running unmodified guests on the Hyper-V confidential computing hypervisor - Double-buffer messages between the guest and the hardware PSP device so that no partial buffers are copied back'n'forth and thus potential message integrity and leak attacks are possible - Name the return value the sev-guest driver returns when the hw PSP device hasn't been called, explicitly - Cleanups * tag 'x86_sev_for_v6.4_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/hyperv: Change vTOM handling to use standard coco mechanisms init: Call mem_encrypt_init() after Hyper-V hypercall init is done x86/mm: Handle decryption/re-encryption of bss_decrypted consistently Drivers: hv: Explicitly request decrypted in vmap_pfn() calls x86/hyperv: Reorder code to facilitate future work x86/ioremap: Add hypervisor callback for private MMIO mapping in coco VM x86/sev: Change snp_guest_issue_request()'s fw_err argument virt/coco/sev-guest: Double-buffer messages crypto: ccp: Get rid of __sev_platform_init_locked()'s local function pointer crypto: ccp - Name -1 return value as SEV_RET_NO_FW_CALL
Unified · Split
| @@ -37,11 +37,11 @@ along with a description: · 36 unmodified lines | |||
| 37 | the return value. General error numbers (-ENOMEM, -EINVAL) | 37 | the return value. General error numbers (-ENOMEM, -EINVAL) |
| 38 | are not detailed, but errors with specific meanings are. | 38 | are not detailed, but errors with specific meanings are. |
| 39 | 39 | ||
| 40 | The guest ioctl should be issued on a file descriptor of the /dev/sev-guest device. | 40 | The guest ioctl should be issued on a file descriptor of the /dev/sev-guest |
| 41 | The ioctl accepts struct snp_user_guest_request. The input and output structure is | 41 | device. The ioctl accepts struct snp_user_guest_request. The input and |
| 42 | specified through the req_data and resp_data field respectively. If the ioctl fails | 42 | output structure is specified through the req_data and resp_data field |
| 43 | to execute due to a firmware error, then fw_err code will be set otherwise the | 43 | respectively. If the ioctl fails to execute due to a firmware error, then |
| 44 | fw_err will be set to 0x00000000000000ff. | 44 | the fw_error code will be set, otherwise fw_error will be set to -1. |
| 45 | 45 | ||
| 46 | The firmware checks that the message sequence counter is one greater than | 46 | The firmware checks that the message sequence counter is one greater than |
| 47 | the guests message sequence counter. If guest driver fails to increment message | 47 | the guests message sequence counter. If guest driver fails to increment message |
| @@ -57,8 +57,14 @@ counter (e.g. counter overflow), then -EIO will be returned. · 9 unmodified lines | |||
| 57 | __u64 req_data; | 57 | __u64 req_data; |
| 58 | __u64 resp_data; | 58 | __u64 resp_data; |
| 59 | 59 | ||
| 60 | /* firmware error code on failure (see psp-sev.h) */ | 60 | /* bits[63:32]: VMM error code, bits[31:0] firmware error code (see psp-sev.h) */ |
| 61 | __u64 fw_err; | 61 | union { |
| 62 | __u64 exitinfo2; | ||
| 63 | struct { | ||
| 64 | __u32 fw_error; | ||
| 65 | __u32 vmm_error; | ||
| 66 | }; | ||
| 67 | }; | ||
| 62 | }; | 68 | }; |
| 63 | 69 | ||
| 64 | 2.1 SNP_GET_REPORT | 70 | 2.1 SNP_GET_REPORT |
| @@ -29,6 +29,22 @@ static bool intel_cc_platform_has(enum cc_attr attr) · 28 unmodified lines | |||
| 29 | } | 29 | } |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | /* | ||
| 33 | * Handle the SEV-SNP vTOM case where sme_me_mask is zero, and | ||
| 34 | * the other levels of SME/SEV functionality, including C-bit | ||
| 35 | * based SEV-SNP, are not enabled. | ||
| 36 | */ | ||
| 37 | static __maybe_unused bool amd_cc_platform_vtom(enum cc_attr attr) | ||
| 38 | { | ||
| 39 | switch (attr) { | ||
| 40 | case CC_ATTR_GUEST_MEM_ENCRYPT: | ||
| 41 | case CC_ATTR_MEM_ENCRYPT: | ||
| 42 | return true; | ||
| 43 | default: | ||
| 44 | return false; | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 32 | /* | 48 | /* |
| 33 | * SME and SEV are very similar but they are not the same, so there are | 49 | * SME and SEV are very similar but they are not the same, so there are |
| 34 | * times that the kernel will need to distinguish between SME and SEV. The | 50 | * times that the kernel will need to distinguish between SME and SEV. The |
| @@ -41,9 +57,14 @@ static bool intel_cc_platform_has(enum cc_attr attr) · 6 unmodified lines | |||
| 41 | * up under SME the trampoline area cannot be encrypted, whereas under SEV | 57 | * up under SME the trampoline area cannot be encrypted, whereas under SEV |
| 42 | * the trampoline area must be encrypted. | 58 | * the trampoline area must be encrypted. |
| 43 | */ | 59 | */ |
| 60 | |||
| 44 | static bool amd_cc_platform_has(enum cc_attr attr) | 61 | static bool amd_cc_platform_has(enum cc_attr attr) |
| 45 | { | 62 | { |
| 46 | #ifdef CONFIG_AMD_MEM_ENCRYPT | 63 | #ifdef CONFIG_AMD_MEM_ENCRYPT |
| 64 | |||
| 65 | if (sev_status & MSR_AMD64_SNP_VTOM) | ||
| 66 | return amd_cc_platform_vtom(attr); | ||
| 67 | |||
| 47 | switch (attr) { | 68 | switch (attr) { |
| 48 | case CC_ATTR_MEM_ENCRYPT: | 69 | case CC_ATTR_MEM_ENCRYPT: |
| 49 | return sme_me_mask; | 70 | return sme_me_mask; |
| @@ -76,11 +97,6 @@ static bool amd_cc_platform_has(enum cc_attr attr) · 26 unmodified lines | |||
| 76 | #endif | 97 | #endif |
| 77 | } | 98 | } |
| 78 | 99 | ||
| 79 | static bool hyperv_cc_platform_has(enum cc_attr attr) | ||
| 80 | { | ||
| 81 | return attr == CC_ATTR_GUEST_MEM_ENCRYPT; | ||
| 82 | } | ||
| 83 | |||
| 84 | bool cc_platform_has(enum cc_attr attr) | 100 | bool cc_platform_has(enum cc_attr attr) |
| 85 | { | 101 | { |
| 86 | switch (vendor) { | 102 | switch (vendor) { |
| @@ -88,8 +104,6 @@ bool cc_platform_has(enum cc_attr attr) · 1 unmodified line | |||
| 88 | return amd_cc_platform_has(attr); | 104 | return amd_cc_platform_has(attr); |
| 89 | case CC_VENDOR_INTEL: | 105 | case CC_VENDOR_INTEL: |
| 90 | return intel_cc_platform_has(attr); | 106 | return intel_cc_platform_has(attr); |
| 91 | case CC_VENDOR_HYPERV: | ||
| 92 | return hyperv_cc_platform_has(attr); | ||
| 93 | default: | 107 | default: |
| 94 | return false; | 108 | return false; |
| 95 | } | 109 | } |
| @@ -103,11 +117,14 @@ u64 cc_mkenc(u64 val) · 7 unmodified lines | |||
| 103 | * encryption status of the page. | 117 | * encryption status of the page. |
| 104 | * | 118 | * |
| 105 | * - for AMD, bit *set* means the page is encrypted | 119 | * - for AMD, bit *set* means the page is encrypted |
| 106 | * - for Intel *clear* means encrypted. | 120 | * - for AMD with vTOM and for Intel, *clear* means encrypted |
| 107 | */ | 121 | */ |
| 108 | switch (vendor) { | 122 | switch (vendor) { |
| 109 | case CC_VENDOR_AMD: | 123 | case CC_VENDOR_AMD: |
| 110 | return val | cc_mask; | 124 | if (sev_status & MSR_AMD64_SNP_VTOM) |
| 125 | return val & ~cc_mask; | ||
| 126 | else | ||
| 127 | return val | cc_mask; | ||
| 111 | case CC_VENDOR_INTEL: | 128 | case CC_VENDOR_INTEL: |
| 112 | return val & ~cc_mask; | 129 | return val & ~cc_mask; |
| 113 | default: | 130 | default: |
| @@ -120,7 +137,10 @@ u64 cc_mkdec(u64 val) · 6 unmodified lines | |||
| 120 | /* See comment in cc_mkenc() */ | 137 | /* See comment in cc_mkenc() */ |
| 121 | switch (vendor) { | 138 | switch (vendor) { |
| 122 | case CC_VENDOR_AMD: | 139 | case CC_VENDOR_AMD: |
| 123 | return val & ~cc_mask; | 140 | if (sev_status & MSR_AMD64_SNP_VTOM) |
| 141 | return val | cc_mask; | ||
| 142 | else | ||
| 143 | return val & ~cc_mask; | ||
| 124 | case CC_VENDOR_INTEL: | 144 | case CC_VENDOR_INTEL: |
| 125 | return val | cc_mask; | 145 | return val | cc_mask; |
| 126 | default: | 146 | default: |
| @@ -29,7 +29,6 @@ · 28 unmodified lines | |||
| 29 | #include <linux/syscore_ops.h> | 29 | #include <linux/syscore_ops.h> |
| 30 | #include <clocksource/hyperv_timer.h> | 30 | #include <clocksource/hyperv_timer.h> |
| 31 | #include <linux/highmem.h> | 31 | #include <linux/highmem.h> |
| 32 | #include <linux/swiotlb.h> | ||
| 33 | 32 | ||
| 34 | int hyperv_init_cpuhp; | 33 | int hyperv_init_cpuhp; |
| 35 | u64 hv_current_partition_id = ~0ull; | 34 | u64 hv_current_partition_id = ~0ull; |
| @@ -504,16 +503,6 @@ void __init hyperv_init(void) · 468 unmodified lines | |||
| 504 | /* Query the VMs extended capability once, so that it can be cached. */ | 503 | /* Query the VMs extended capability once, so that it can be cached. */ |
| 505 | hv_query_ext_cap(0); | 504 | hv_query_ext_cap(0); |
| 506 | 505 | ||
| 507 | #ifdef CONFIG_SWIOTLB | ||
| 508 | /* | ||
| 509 | * Swiotlb bounce buffer needs to be mapped in extra address | ||
| 510 | * space. Map function doesn't work in the early place and so | ||
| 511 | * call swiotlb_update_mem_attributes() here. | ||
| 512 | */ | ||
| 513 | if (hv_is_isolation_supported()) | ||
| 514 | swiotlb_update_mem_attributes(); | ||
| 515 | #endif | ||
| 516 | |||
| 517 | return; | 506 | return; |
| 518 | 507 | ||
| 519 | clean_guest_os_id: | 508 | clean_guest_os_id: |
| @@ -13,6 +13,8 @@ · 12 unmodified lines | |||
| 13 | #include <asm/svm.h> | 13 | #include <asm/svm.h> |
| 14 | #include <asm/sev.h> | 14 | #include <asm/sev.h> |
| 15 | #include <asm/io.h> | 15 | #include <asm/io.h> |
| 16 | #include <asm/coco.h> | ||
| 17 | #include <asm/mem_encrypt.h> | ||
| 16 | #include <asm/mshyperv.h> | 18 | #include <asm/mshyperv.h> |
| 17 | #include <asm/hypervisor.h> | 19 | #include <asm/hypervisor.h> |
| 18 | 20 | ||
| @@ -233,41 +235,6 @@ void hv_ghcb_msr_read(u64 msr, u64 *value) · 214 unmodified lines | |||
| 233 | local_irq_restore(flags); | 235 | local_irq_restore(flags); |
| 234 | } | 236 | } |
| 235 | EXPORT_SYMBOL_GPL(hv_ghcb_msr_read); | 237 | EXPORT_SYMBOL_GPL(hv_ghcb_msr_read); |
| 236 | #endif | ||
| 237 | |||
| 238 | enum hv_isolation_type hv_get_isolation_type(void) | ||
| 239 | { | ||
| 240 | if (!(ms_hyperv.priv_high & HV_ISOLATION)) | ||
| 241 | return HV_ISOLATION_TYPE_NONE; | ||
| 242 | return FIELD_GET(HV_ISOLATION_TYPE, ms_hyperv.isolation_config_b); | ||
| 243 | } | ||
| 244 | EXPORT_SYMBOL_GPL(hv_get_isolation_type); | ||
| 245 | |||
| 246 | /* | ||
| 247 | * hv_is_isolation_supported - Check system runs in the Hyper-V | ||
| 248 | * isolation VM. | ||
| 249 | */ | ||
| 250 | bool hv_is_isolation_supported(void) | ||
| 251 | { | ||
| 252 | if (!cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) | ||
| 253 | return false; | ||
| 254 | |||
| 255 | if (!hypervisor_is_type(X86_HYPER_MS_HYPERV)) | ||
| 256 | return false; | ||
| 257 | |||
| 258 | return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE; | ||
| 259 | } | ||
| 260 | |||
| 261 | DEFINE_STATIC_KEY_FALSE(isolation_type_snp); | ||
| 262 | |||
| 263 | /* | ||
| 264 | * hv_isolation_type_snp - Check system runs in the AMD SEV-SNP based | ||
| 265 | * isolation VM. | ||
| 266 | */ | ||
| 267 | bool hv_isolation_type_snp(void) | ||
| 268 | { | ||
| 269 | return static_branch_unlikely(&isolation_type_snp); | ||
| 270 | } | ||
| 271 | 238 | ||
| 272 | /* | 239 | /* |
| 273 | * hv_mark_gpa_visibility - Set pages visible to host via hvcall. | 240 | * hv_mark_gpa_visibility - Set pages visible to host via hvcall. |
| @@ -320,27 +287,25 @@ static int hv_mark_gpa_visibility(u16 count, const u64 pfn[], · 46 unmodified lines | |||
| 320 | } | 287 | } |
| 321 | 288 | ||
| 322 | /* | 289 | /* |
| 323 | * hv_set_mem_host_visibility - Set specified memory visible to host. | 290 | * hv_vtom_set_host_visibility - Set specified memory visible to host. |
| 324 | * | 291 | * |
| 325 | * In Isolation VM, all guest memory is encrypted from host and guest | 292 | * In Isolation VM, all guest memory is encrypted from host and guest |
| 326 | * needs to set memory visible to host via hvcall before sharing memory | 293 | * needs to set memory visible to host via hvcall before sharing memory |
| 327 | * with host. This function works as wrap of hv_mark_gpa_visibility() | 294 | * with host. This function works as wrap of hv_mark_gpa_visibility() |
| 328 | * with memory base and size. | 295 | * with memory base and size. |
| 329 | */ | 296 | */ |
| 330 | int hv_set_mem_host_visibility(unsigned long kbuffer, int pagecount, bool visible) | 297 | static bool hv_vtom_set_host_visibility(unsigned long kbuffer, int pagecount, bool enc) |
| 331 | { | 298 | { |
| 332 | enum hv_mem_host_visibility visibility = visible ? | 299 | enum hv_mem_host_visibility visibility = enc ? |
| 333 | VMBUS_PAGE_VISIBLE_READ_WRITE : VMBUS_PAGE_NOT_VISIBLE; | 300 | VMBUS_PAGE_NOT_VISIBLE : VMBUS_PAGE_VISIBLE_READ_WRITE; |
| 334 | u64 *pfn_array; | 301 | u64 *pfn_array; |
| 335 | int ret = 0; | 302 | int ret = 0; |
| 303 | bool result = true; | ||
| 336 | int i, pfn; | 304 | int i, pfn; |
| 337 | 305 | ||
| 338 | if (!hv_is_isolation_supported() || !hv_hypercall_pg) | ||
| 339 | return 0; | ||
| 340 | |||
| 341 | pfn_array = kmalloc(HV_HYP_PAGE_SIZE, GFP_KERNEL); | 306 | pfn_array = kmalloc(HV_HYP_PAGE_SIZE, GFP_KERNEL); |
| 342 | if (!pfn_array) | 307 | if (!pfn_array) |
| 343 | return -ENOMEM; | 308 | return false; |
| 344 | 309 | ||
| 345 | for (i = 0, pfn = 0; i < pagecount; i++) { | 310 | for (i = 0, pfn = 0; i < pagecount; i++) { |
| 346 | pfn_array[pfn] = virt_to_hvpfn((void *)kbuffer + i * HV_HYP_PAGE_SIZE); | 311 | pfn_array[pfn] = virt_to_hvpfn((void *)kbuffer + i * HV_HYP_PAGE_SIZE); |
| @@ -349,17 +314,68 @@ int hv_set_mem_host_visibility(unsigned long kbuffer, int pagecount, bool visibl · 2 unmodified lines | |||
| 349 | if (pfn == HV_MAX_MODIFY_GPA_REP_COUNT || i == pagecount - 1) { | 314 | if (pfn == HV_MAX_MODIFY_GPA_REP_COUNT || i == pagecount - 1) { |
| 350 | ret = hv_mark_gpa_visibility(pfn, pfn_array, | 315 | ret = hv_mark_gpa_visibility(pfn, pfn_array, |
| 351 | visibility); | 316 | visibility); |
| 352 | if (ret) | 317 | if (ret) { |
| 318 | result = false; | ||
| 353 | goto err_free_pfn_array; | 319 | goto err_free_pfn_array; |
| 320 | } | ||
| 354 | pfn = 0; | 321 | pfn = 0; |
| 355 | } | 322 | } |
| 356 | } | 323 | } |
| 357 | 324 | ||
| 358 | err_free_pfn_array: | 325 | err_free_pfn_array: |
| 359 | kfree(pfn_array); | 326 | kfree(pfn_array); |
| 360 | return ret; | 327 | return result; |
| 328 | } | ||
| 329 | |||
| 330 | static bool hv_vtom_tlb_flush_required(bool private) | ||
| 331 | { | ||
| 332 | return true; | ||
| 361 | } | 333 | } |
| 362 | 334 | ||
| 335 | static bool hv_vtom_cache_flush_required(void) | ||
| 336 | { | ||
| 337 | return false; | ||
| 338 | } | ||
| 339 | |||
| 340 | static bool hv_is_private_mmio(u64 addr) | ||
| 341 | { | ||
| 342 | /* | ||
| 343 | * Hyper-V always provides a single IO-APIC in a guest VM. | ||
| 344 | * When a paravisor is used, it is emulated by the paravisor | ||
| 345 | * in the guest context and must be mapped private. | ||
| 346 | */ | ||
| 347 | if (addr >= HV_IOAPIC_BASE_ADDRESS && | ||
| 348 | addr < (HV_IOAPIC_BASE_ADDRESS + PAGE_SIZE)) | ||
| 349 | return true; | ||
| 350 | |||
| 351 | /* Same with a vTPM */ | ||
| 352 | if (addr >= VTPM_BASE_ADDRESS && | ||
| 353 | addr < (VTPM_BASE_ADDRESS + PAGE_SIZE)) | ||
| 354 | return true; | ||
| 355 | |||
| 356 | return false; | ||
| 357 | } | ||
| 358 | |||
| 359 | void __init hv_vtom_init(void) | ||
| 360 | { | ||
| 361 | /* | ||
| 362 | * By design, a VM using vTOM doesn't see the SEV setting, | ||
| 363 | * so SEV initialization is bypassed and sev_status isn't set. | ||
| 364 | * Set it here to indicate a vTOM VM. | ||
| 365 | */ | ||
| 366 | sev_status = MSR_AMD64_SNP_VTOM; | ||
| 367 | cc_set_vendor(CC_VENDOR_AMD); | ||
| 368 | cc_set_mask(ms_hyperv.shared_gpa_boundary); | ||
| 369 | physical_mask &= ms_hyperv.shared_gpa_boundary - 1; | ||
| 370 | |||
| 371 | x86_platform.hyper.is_private_mmio = hv_is_private_mmio; | ||
| 372 | x86_platform.guest.enc_cache_flush_required = hv_vtom_cache_flush_required; | ||
| 373 | x86_platform.guest.enc_tlb_flush_required = hv_vtom_tlb_flush_required; | ||
| 374 | x86_platform.guest.enc_status_change_finish = hv_vtom_set_host_visibility; | ||
| 375 | } | ||
| 376 | |||
| 377 | #endif /* CONFIG_AMD_MEM_ENCRYPT */ | ||
| 378 | |||
| 363 | /* | 379 | /* |
| 364 | * hv_map_memory - map memory to extra space in the AMD SEV-SNP Isolation VM. | 380 | * hv_map_memory - map memory to extra space in the AMD SEV-SNP Isolation VM. |
| 365 | */ | 381 | */ |
| @@ -377,7 +393,7 @@ void *hv_map_memory(void *addr, unsigned long size) · 11 unmodified lines | |||
| 377 | pfns[i] = vmalloc_to_pfn(addr + i * PAGE_SIZE) + | 393 | pfns[i] = vmalloc_to_pfn(addr + i * PAGE_SIZE) + |
| 378 | (ms_hyperv.shared_gpa_boundary >> PAGE_SHIFT); | 394 | (ms_hyperv.shared_gpa_boundary >> PAGE_SHIFT); |
| 379 | 395 | ||
| 380 | vaddr = vmap_pfn(pfns, size / PAGE_SIZE, PAGE_KERNEL_IO); | 396 | vaddr = vmap_pfn(pfns, size / PAGE_SIZE, pgprot_decrypted(PAGE_KERNEL)); |
| 381 | kfree(pfns); | 397 | kfree(pfns); |
| 382 | 398 | ||
| 383 | return vaddr; | 399 | return vaddr; |
| @@ -387,3 +403,37 @@ void hv_unmap_memory(void *addr) · 3 unmodified lines | |||
| 387 | { | 403 | { |
| 388 | vunmap(addr); | 404 | vunmap(addr); |
| 389 | } | 405 | } |
| 406 | |||
| 407 | enum hv_isolation_type hv_get_isolation_type(void) | ||
| 408 | { | ||
| 409 | if (!(ms_hyperv.priv_high & HV_ISOLATION)) | ||
| 410 | return HV_ISOLATION_TYPE_NONE; | ||
| 411 | return FIELD_GET(HV_ISOLATION_TYPE, ms_hyperv.isolation_config_b); | ||
| 412 | } | ||
| 413 | EXPORT_SYMBOL_GPL(hv_get_isolation_type); | ||
| 414 | |||
| 415 | /* | ||
| 416 | * hv_is_isolation_supported - Check system runs in the Hyper-V | ||
| 417 | * isolation VM. | ||
| 418 | */ | ||
| 419 | bool hv_is_isolation_supported(void) | ||
| 420 | { | ||
| 421 | if (!cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) | ||
| 422 | return false; | ||
| 423 | |||
| 424 | if (!hypervisor_is_type(X86_HYPER_MS_HYPERV)) | ||
| 425 | return false; | ||
| 426 | |||
| 427 | return hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE; | ||
| 428 | } | ||
| 429 | |||
| 430 | DEFINE_STATIC_KEY_FALSE(isolation_type_snp); | ||
| 431 | |||
| 432 | /* | ||
| 433 | * hv_isolation_type_snp - Check system runs in the AMD SEV-SNP based | ||
| 434 | * isolation VM. | ||
| 435 | */ | ||
| 436 | bool hv_isolation_type_snp(void) | ||
| 437 | { | ||
| 438 | return static_branch_unlikely(&isolation_type_snp); | ||
| 439 | } | ||
| @@ -7,7 +7,6 @@ · 6 unmodified lines | |||
| 7 | enum cc_vendor { | 7 | enum cc_vendor { |
| 8 | CC_VENDOR_NONE, | 8 | CC_VENDOR_NONE, |
| 9 | CC_VENDOR_AMD, | 9 | CC_VENDOR_AMD, |
| 10 | CC_VENDOR_HYPERV, | ||
| 11 | CC_VENDOR_INTEL, | 10 | CC_VENDOR_INTEL, |
| 12 | }; | 11 | }; |
| 13 | 12 | ||
| @@ -56,6 +56,7 @@ void __init sev_es_init_vc_handling(void); · 55 unmodified lines | |||
| 56 | #else /* !CONFIG_AMD_MEM_ENCRYPT */ | 56 | #else /* !CONFIG_AMD_MEM_ENCRYPT */ |
| 57 | 57 | ||
| 58 | #define sme_me_mask 0ULL | 58 | #define sme_me_mask 0ULL |
| 59 | #define sev_status 0ULL | ||
| 59 | 60 | ||
| 60 | static inline void __init sme_early_encrypt(resource_size_t paddr, | 61 | static inline void __init sme_early_encrypt(resource_size_t paddr, |
| 61 | unsigned long size) { } | 62 | unsigned long size) { } |
| @@ -11,6 +11,14 @@ · 10 unmodified lines | |||
| 11 | #include <asm/paravirt.h> | 11 | #include <asm/paravirt.h> |
| 12 | #include <asm/mshyperv.h> | 12 | #include <asm/mshyperv.h> |
| 13 | 13 | ||
| 14 | /* | ||
| 15 | * Hyper-V always provides a single IO-APIC at this MMIO address. | ||
| 16 | * Ideally, the value should be looked up in ACPI tables, but it | ||
| 17 | * is needed for mapping the IO-APIC early in boot on Confidential | ||
| 18 | * VMs, before ACPI functions can be used. | ||
| 19 | */ | ||
| 20 | #define HV_IOAPIC_BASE_ADDRESS 0xfec00000 | ||
| 21 | |||
| 14 | union hv_ghcb; | 22 | union hv_ghcb; |
| 15 | 23 | ||
| 16 | DECLARE_STATIC_KEY_FALSE(isolation_type_snp); | 24 | DECLARE_STATIC_KEY_FALSE(isolation_type_snp); |
| @@ -206,18 +214,19 @@ struct irq_domain *hv_create_pci_msi_domain(void); · 189 unmodified lines | |||
| 206 | int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector, | 214 | int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector, |
| 207 | struct hv_interrupt_entry *entry); | 215 | struct hv_interrupt_entry *entry); |
| 208 | int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry); | 216 | int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry); |
| 209 | int hv_set_mem_host_visibility(unsigned long addr, int numpages, bool visible); | ||
| 210 | 217 | ||
| 211 | #ifdef CONFIG_AMD_MEM_ENCRYPT | 218 | #ifdef CONFIG_AMD_MEM_ENCRYPT |
| 212 | void hv_ghcb_msr_write(u64 msr, u64 value); | 219 | void hv_ghcb_msr_write(u64 msr, u64 value); |
| 213 | void hv_ghcb_msr_read(u64 msr, u64 *value); | 220 | void hv_ghcb_msr_read(u64 msr, u64 *value); |
| 214 | bool hv_ghcb_negotiate_protocol(void); | 221 | bool hv_ghcb_negotiate_protocol(void); |
| 215 | void hv_ghcb_terminate(unsigned int set, unsigned int reason); | 222 | void hv_ghcb_terminate(unsigned int set, unsigned int reason); |
| 223 | void hv_vtom_init(void); | ||
| 216 | #else | 224 | #else |
| 217 | static inline void hv_ghcb_msr_write(u64 msr, u64 value) {} | 225 | static inline void hv_ghcb_msr_write(u64 msr, u64 value) {} |
| 218 | static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {} | 226 | static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {} |
| 219 | static inline bool hv_ghcb_negotiate_protocol(void) { return false; } | 227 | static inline bool hv_ghcb_negotiate_protocol(void) { return false; } |
| 220 | static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {} | 228 | static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {} |
| 229 | static inline void hv_vtom_init(void) {} | ||
| 221 | #endif | 230 | #endif |
| 222 | 231 | ||
| 223 | extern bool hv_isolation_type_snp(void); | 232 | extern bool hv_isolation_type_snp(void); |
| @@ -259,11 +268,6 @@ static inline void hv_set_register(unsigned int reg, u64 value) { } · 35 unmodified lines | |||
| 259 | static inline u64 hv_get_register(unsigned int reg) { return 0; } | 268 | static inline u64 hv_get_register(unsigned int reg) { return 0; } |
| 260 | static inline void hv_set_non_nested_register(unsigned int reg, u64 value) { } | 269 | static inline void hv_set_non_nested_register(unsigned int reg, u64 value) { } |
| 261 | static inline u64 hv_get_non_nested_register(unsigned int reg) { return 0; } | 270 | static inline u64 hv_get_non_nested_register(unsigned int reg) { return 0; } |
| 262 | static inline int hv_set_mem_host_visibility(unsigned long addr, int numpages, | ||
| 263 | bool visible) | ||
| 264 | { | ||
| 265 | return -1; | ||
| 266 | } | ||
| 267 | #endif /* CONFIG_HYPERV */ | 271 | #endif /* CONFIG_HYPERV */ |
| 268 | 272 | ||
| 269 | 273 | ||
| @@ -128,10 +128,6 @@ struct snp_psc_desc { · 127 unmodified lines | |||
| 128 | struct psc_entry entries[VMGEXIT_PSC_MAX_ENTRY]; | 128 | struct psc_entry entries[VMGEXIT_PSC_MAX_ENTRY]; |
| 129 | } __packed; | 129 | } __packed; |
| 130 | 130 | ||
| 131 | /* Guest message request error codes */ | ||
| 132 | #define SNP_GUEST_REQ_INVALID_LEN BIT_ULL(32) | ||
| 133 | #define SNP_GUEST_REQ_ERR_BUSY BIT_ULL(33) | ||
| 134 | |||
| 135 | #define GHCB_MSR_TERM_REQ 0x100 | 131 | #define GHCB_MSR_TERM_REQ 0x100 |
| 136 | #define GHCB_MSR_TERM_REASON_SET_POS 12 | 132 | #define GHCB_MSR_TERM_REASON_SET_POS 12 |
| 137 | #define GHCB_MSR_TERM_REASON_SET_MASK 0xf | 133 | #define GHCB_MSR_TERM_REASON_SET_MASK 0xf |
| @@ -9,6 +9,8 @@ · 8 unmodified lines | |||
| 9 | #define __ASM_ENCRYPTED_STATE_H | 9 | #define __ASM_ENCRYPTED_STATE_H |
| 10 | 10 | ||
| 11 | #include <linux/types.h> | 11 | #include <linux/types.h> |
| 12 | #include <linux/sev-guest.h> | ||
| 13 | |||
| 12 | #include <asm/insn.h> | 14 | #include <asm/insn.h> |
| 13 | #include <asm/sev-common.h> | 15 | #include <asm/sev-common.h> |
| 14 | #include <asm/bootparam.h> | 16 | #include <asm/bootparam.h> |
| @@ -185,6 +187,9 @@ static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate) · 170 unmodified lines | |||
| 185 | 187 | ||
| 186 | return rc; | 188 | return rc; |
| 187 | } | 189 | } |
| 190 | |||
| 191 | struct snp_guest_request_ioctl; | ||
| 192 | |||
| 188 | void setup_ghcb(void); | 193 | void setup_ghcb(void); |
| 189 | void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, | 194 | void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, |
| 190 | unsigned int npages); | 195 | unsigned int npages); |
| @@ -196,7 +201,7 @@ void snp_set_memory_private(unsigned long vaddr, unsigned int npages); · 5 unmodified lines | |||
| 196 | void snp_set_wakeup_secondary_cpu(void); | 201 | void snp_set_wakeup_secondary_cpu(void); |
| 197 | bool snp_init(struct boot_params *bp); | 202 | bool snp_init(struct boot_params *bp); |
| 198 | void __init __noreturn snp_abort(void); | 203 | void __init __noreturn snp_abort(void); |
| 199 | int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned long *fw_err); | 204 | int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio); |
| 200 | #else | 205 | #else |
| 201 | static inline void sev_es_ist_enter(struct pt_regs *regs) { } | 206 | static inline void sev_es_ist_enter(struct pt_regs *regs) { } |
| 202 | static inline void sev_es_ist_exit(void) { } | 207 | static inline void sev_es_ist_exit(void) { } |
| @@ -216,8 +221,7 @@ static inline void snp_set_memory_private(unsigned long vaddr, unsigned int npag · 13 unmodified lines | |||
| 216 | static inline void snp_set_wakeup_secondary_cpu(void) { } | 221 | static inline void snp_set_wakeup_secondary_cpu(void) { } |
| 217 | static inline bool snp_init(struct boot_params *bp) { return false; } | 222 | static inline bool snp_init(struct boot_params *bp) { return false; } |
| 218 | static inline void snp_abort(void) { } | 223 | static inline void snp_abort(void) { } |
| 219 | static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, | 224 | static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio) |
| 220 | unsigned long *fw_err) | ||
| 221 | { | 225 | { |
| 222 | return -ENOTTY; | 226 | return -ENOTTY; |
| 223 | } | 227 | } |
| @@ -259,11 +259,15 @@ struct x86_legacy_features { · 258 unmodified lines | |||
| 259 | * VMMCALL under SEV-ES. Needs to return 'false' | 259 | * VMMCALL under SEV-ES. Needs to return 'false' |
| 260 | * if the checks fail. Called from the #VC | 260 | * if the checks fail. Called from the #VC |
| 261 | * exception handler. | 261 | * exception handler. |
| 262 | * @is_private_mmio: For CoCo VMs, must map MMIO address as private. | ||
| 263 | * Used when device is emulated by a paravisor | ||
| 264 | * layer in the VM context. | ||
| 262 | */ | 265 | */ |
| 263 | struct x86_hyper_runtime { | 266 | struct x86_hyper_runtime { |
| 264 | void (*pin_vcpu)(int cpu); | 267 | void (*pin_vcpu)(int cpu); |
| 265 | void (*sev_es_hcall_prepare)(struct ghcb *ghcb, struct pt_regs *regs); | 268 | void (*sev_es_hcall_prepare)(struct ghcb *ghcb, struct pt_regs *regs); |
| 266 | bool (*sev_es_hcall_finish)(struct ghcb *ghcb, struct pt_regs *regs); | 269 | bool (*sev_es_hcall_finish)(struct ghcb *ghcb, struct pt_regs *regs); |
| 270 | bool (*is_private_mmio)(u64 addr); | ||
| 267 | }; | 271 | }; |
| 268 | 272 | ||
| 269 | /** | 273 | /** |
| @@ -66,6 +66,7 @@ · 65 unmodified lines | |||
| 66 | #include <asm/hw_irq.h> | 66 | #include <asm/hw_irq.h> |
| 67 | #include <asm/apic.h> | 67 | #include <asm/apic.h> |
| 68 | #include <asm/pgtable.h> | 68 | #include <asm/pgtable.h> |
| 69 | #include <asm/x86_init.h> | ||
| 69 | 70 | ||
| 70 | #define for_each_ioapic(idx) \ | 71 | #define for_each_ioapic(idx) \ |
| 71 | for ((idx) = 0; (idx) < nr_ioapics; (idx)++) | 72 | for ((idx) = 0; (idx) < nr_ioapics; (idx)++) |
| @@ -2680,10 +2681,15 @@ static void io_apic_set_fixmap(enum fixed_addresses idx, phys_addr_t phys) · 2608 unmodified lines | |||
| 2680 | pgprot_t flags = FIXMAP_PAGE_NOCACHE; | 2681 | pgprot_t flags = FIXMAP_PAGE_NOCACHE; |
| 2681 | 2682 | ||
| 2682 | /* | 2683 | /* |
| 2683 | * Ensure fixmaps for IOAPIC MMIO respect memory encryption pgprot | 2684 | * Ensure fixmaps for IO-APIC MMIO respect memory encryption pgprot |
| 2684 | * bits, just like normal ioremap(): | 2685 | * bits, just like normal ioremap(): |
| 2685 | */ | 2686 | */ |
| 2686 | flags = pgprot_decrypted(flags); | 2687 | if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) { |
| 2688 | if (x86_platform.hyper.is_private_mmio(phys)) | ||
| 2689 | flags = pgprot_encrypted(flags); | ||
| 2690 | else | ||
| 2691 | flags = pgprot_decrypted(flags); | ||
| 2692 | } | ||
| 2687 | 2693 | ||
| 2688 | __set_fixmap(idx, phys, flags); | 2694 | __set_fixmap(idx, phys, flags); |
| 2689 | } | 2695 | } |
| @@ -33,7 +33,6 @@ · 32 unmodified lines | |||
| 33 | #include <asm/nmi.h> | 33 | #include <asm/nmi.h> |
| 34 | #include <clocksource/hyperv_timer.h> | 34 | #include <clocksource/hyperv_timer.h> |
| 35 | #include <asm/numa.h> | 35 | #include <asm/numa.h> |
| 36 | #include <asm/coco.h> | ||
| 37 | 36 | ||
| 38 | /* Is Linux running as the root partition? */ | 37 | /* Is Linux running as the root partition? */ |
| 39 | bool hv_root_partition; | 38 | bool hv_root_partition; |
| @@ -401,8 +400,10 @@ static void __init ms_hyperv_init_platform(void) · 361 unmodified lines | |||
| 401 | if (ms_hyperv.priv_high & HV_ISOLATION) { | 400 | if (ms_hyperv.priv_high & HV_ISOLATION) { |
| 402 | ms_hyperv.isolation_config_a = cpuid_eax(HYPERV_CPUID_ISOLATION_CONFIG); | 401 | ms_hyperv.isolation_config_a = cpuid_eax(HYPERV_CPUID_ISOLATION_CONFIG); |
| 403 | ms_hyperv.isolation_config_b = cpuid_ebx(HYPERV_CPUID_ISOLATION_CONFIG); | 402 | ms_hyperv.isolation_config_b = cpuid_ebx(HYPERV_CPUID_ISOLATION_CONFIG); |
| 404 | ms_hyperv.shared_gpa_boundary = | 403 | |
| 405 | BIT_ULL(ms_hyperv.shared_gpa_boundary_bits); | 404 | if (ms_hyperv.shared_gpa_boundary_active) |
| 405 | ms_hyperv.shared_gpa_boundary = | ||
| 406 | BIT_ULL(ms_hyperv.shared_gpa_boundary_bits); | ||
| 406 | 407 | ||
| 407 | pr_info("Hyper-V: Isolation Config: Group A 0x%x, Group B 0x%x\n", | 408 | pr_info("Hyper-V: Isolation Config: Group A 0x%x, Group B 0x%x\n", |
| 408 | ms_hyperv.isolation_config_a, ms_hyperv.isolation_config_b); | 409 | ms_hyperv.isolation_config_a, ms_hyperv.isolation_config_b); |
| @@ -413,11 +414,6 @@ static void __init ms_hyperv_init_platform(void) · 4 unmodified lines | |||
| 413 | swiotlb_unencrypted_base = ms_hyperv.shared_gpa_boundary; | 414 | swiotlb_unencrypted_base = ms_hyperv.shared_gpa_boundary; |
| 414 | #endif | 415 | #endif |
| 415 | } | 416 | } |
| 416 | /* Isolation VMs are unenlightened SEV-based VMs, thus this check: */ | ||
| 417 | if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT)) { | ||
| 418 | if (hv_get_isolation_type() != HV_ISOLATION_TYPE_NONE) | ||
| 419 | cc_set_vendor(CC_VENDOR_HYPERV); | ||
| 420 | } | ||
| 421 | } | 417 | } |
| 422 | 418 | ||
| 423 | if (hv_max_functions_eax >= HYPERV_CPUID_NESTED_FEATURES) { | 419 | if (hv_max_functions_eax >= HYPERV_CPUID_NESTED_FEATURES) { |
| @@ -486,6 +482,9 @@ static void __init ms_hyperv_init_platform(void) · 62 unmodified lines | |||
| 486 | i8253_clear_counter_on_shutdown = false; | 482 | i8253_clear_counter_on_shutdown = false; |
| 487 | 483 | ||
| 488 | #if IS_ENABLED(CONFIG_HYPERV) | 484 | #if IS_ENABLED(CONFIG_HYPERV) |
| 485 | if ((hv_get_isolation_type() == HV_ISOLATION_TYPE_VBS) || | ||
| 486 | (hv_get_isolation_type() == HV_ISOLATION_TYPE_SNP)) | ||
| 487 | hv_vtom_init(); | ||
| 489 | /* | 488 | /* |
| 490 | * Setup the hook to get control post apic initialization. | 489 | * Setup the hook to get control post apic initialization. |
| 491 | */ | 490 | */ |
| @@ -22,6 +22,8 @@ · 21 unmodified lines | |||
| 22 | #include <linux/efi.h> | 22 | #include <linux/efi.h> |
| 23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
| 25 | #include <linux/psp-sev.h> | ||
| 26 | #include <uapi/linux/sev-guest.h> | ||
| 25 | 27 | ||
| 26 | #include <asm/cpu_entry_area.h> | 28 | #include <asm/cpu_entry_area.h> |
| 27 | #include <asm/stacktrace.h> | 29 | #include <asm/stacktrace.h> |
| @@ -2175,7 +2177,7 @@ static int __init init_sev_config(char *str) · 2147 unmodified lines | |||
| 2175 | } | 2177 | } |
| 2176 | __setup("sev=", init_sev_config); | 2178 | __setup("sev=", init_sev_config); |
| 2177 | 2179 | ||
| 2178 | int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned long *fw_err) | 2180 | int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio) |
| 2179 | { | 2181 | { |
| 2180 | struct ghcb_state state; | 2182 | struct ghcb_state state; |
| 2181 | struct es_em_ctxt ctxt; | 2183 | struct es_em_ctxt ctxt; |
| @@ -2183,8 +2185,7 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned · 1 unmodified line | |||
| 2183 | struct ghcb *ghcb; | 2185 | struct ghcb *ghcb; |
| 2184 | int ret; | 2186 | int ret; |
| 2185 | 2187 | ||
| 2186 | if (!fw_err) | 2188 | rio->exitinfo2 = SEV_RET_NO_FW_CALL; |
| 2187 | return -EINVAL; | ||
| 2188 | 2189 | ||
| 2189 | /* | 2190 | /* |
| 2190 | * __sev_get_ghcb() needs to run with IRQs disabled because it is using | 2191 | * __sev_get_ghcb() needs to run with IRQs disabled because it is using |
| @@ -2209,16 +2210,16 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned · 18 unmodified lines | |||
| 2209 | if (ret) | 2210 | if (ret) |
| 2210 | goto e_put; | 2211 | goto e_put; |
| 2211 | 2212 | ||
| 2212 | *fw_err = ghcb->save.sw_exit_info_2; | 2213 | rio->exitinfo2 = ghcb->save.sw_exit_info_2; |
| 2213 | switch (*fw_err) { | 2214 | switch (rio->exitinfo2) { |
| 2214 | case 0: | 2215 | case 0: |
| 2215 | break; | 2216 | break; |
| 2216 | 2217 | ||
| 2217 | case SNP_GUEST_REQ_ERR_BUSY: | 2218 | case SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_BUSY): |
| 2218 | ret = -EAGAIN; | 2219 | ret = -EAGAIN; |
| 2219 | break; | 2220 | break; |
| 2220 | 2221 | ||
| 2221 | case SNP_GUEST_REQ_INVALID_LEN: | 2222 | case SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN): |
| 2222 | /* Number of expected pages are returned in RBX */ | 2223 | /* Number of expected pages are returned in RBX */ |
| 2223 | if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) { | 2224 | if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) { |
| 2224 | input->data_npages = ghcb_get_rbx(ghcb); | 2225 | input->data_npages = ghcb_get_rbx(ghcb); |
| @@ -134,6 +134,7 @@ static void enc_status_change_prepare_noop(unsigned long vaddr, int npages, bool · 133 unmodified lines | |||
| 134 | static bool enc_status_change_finish_noop(unsigned long vaddr, int npages, bool enc) { return false; } | 134 | static bool enc_status_change_finish_noop(unsigned long vaddr, int npages, bool enc) { return false; } |
| 135 | static bool enc_tlb_flush_required_noop(bool enc) { return false; } | 135 | static bool enc_tlb_flush_required_noop(bool enc) { return false; } |
| 136 | static bool enc_cache_flush_required_noop(void) { return false; } | 136 | static bool enc_cache_flush_required_noop(void) { return false; } |
| 137 | static bool is_private_mmio_noop(u64 addr) {return false; } | ||
| 137 | 138 | ||
| 138 | struct x86_platform_ops x86_platform __ro_after_init = { | 139 | struct x86_platform_ops x86_platform __ro_after_init = { |
| 139 | .calibrate_cpu = native_calibrate_cpu_early, | 140 | .calibrate_cpu = native_calibrate_cpu_early, |
| @@ -149,6 +150,7 @@ struct x86_platform_ops x86_platform __ro_after_init = { · 9 unmodified lines | |||
| 149 | .realmode_reserve = reserve_real_mode, | 150 | .realmode_reserve = reserve_real_mode, |
| 150 | .realmode_init = init_real_mode, | 151 | .realmode_init = init_real_mode, |
| 151 | .hyper.pin_vcpu = x86_op_int_noop, | 152 | .hyper.pin_vcpu = x86_op_int_noop, |
| 153 | .hyper.is_private_mmio = is_private_mmio_noop, | ||
| 152 | 154 | ||
| 153 | .guest = { | 155 | .guest = { |
| 154 | .enc_status_change_prepare = enc_status_change_prepare_noop, | 156 | .enc_status_change_prepare = enc_status_change_prepare_noop, |
| @@ -116,6 +116,11 @@ static void __ioremap_check_other(resource_size_t addr, struct ioremap_desc *des · 115 unmodified lines | |||
| 116 | if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) | 116 | if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) |
| 117 | return; | 117 | return; |
| 118 | 118 | ||
| 119 | if (x86_platform.hyper.is_private_mmio(addr)) { | ||
| 120 | desc->flags |= IORES_MAP_ENCRYPTED; | ||
| 121 | return; | ||
| 122 | } | ||
| 123 | |||
| 119 | if (!IS_ENABLED(CONFIG_EFI)) | 124 | if (!IS_ENABLED(CONFIG_EFI)) |
| 120 | return; | 125 | return; |
| 121 | 126 | ||
| @@ -513,10 +513,14 @@ void __init mem_encrypt_free_decrypted_mem(void) · 512 unmodified lines | |||
| 513 | npages = (vaddr_end - vaddr) >> PAGE_SHIFT; | 513 | npages = (vaddr_end - vaddr) >> PAGE_SHIFT; |
| 514 | 514 | ||
| 515 | /* | 515 | /* |
| 516 | * The unused memory range was mapped decrypted, change the encryption | 516 | * If the unused memory range was mapped decrypted, change the encryption |
| 517 | * attribute from decrypted to encrypted before freeing it. | 517 | * attribute from decrypted to encrypted before freeing it. Base the |
| 518 | * re-encryption on the same condition used for the decryption in | ||
| 519 | * sme_postprocess_startup(). Higher level abstractions, such as | ||
| 520 | * CC_ATTR_MEM_ENCRYPT, aren't necessarily equivalent in a Hyper-V VM | ||
| 521 | * using vTOM, where sme_me_mask is always zero. | ||
| 518 | */ | 522 | */ |
| 519 | if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) { | 523 | if (sme_me_mask) { |
| 520 | r = set_memory_encrypted(vaddr, npages); | 524 | r = set_memory_encrypted(vaddr, npages); |
| 521 | if (r) { | 525 | if (r) { |
| 522 | pr_warn("failed to free unused decrypted pages\n"); | 526 | pr_warn("failed to free unused decrypted pages\n"); |
| @@ -2175,9 +2175,6 @@ static int __set_memory_enc_pgtable(unsigned long addr, int numpages, bool enc) · 2174 unmodified lines | |||
| 2175 | 2175 | ||
| 2176 | static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc) | 2176 | static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc) |
| 2177 | { | 2177 | { |
| 2178 | if (hv_is_isolation_supported()) | ||
| 2179 | return hv_set_mem_host_visibility(addr, numpages, !enc); | ||
| 2180 | |||
| 2181 | if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) | 2178 | if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) |
| 2182 | return __set_memory_enc_pgtable(addr, numpages, enc); | 2179 | return __set_memory_enc_pgtable(addr, numpages, enc); |
| 2183 | 2180 | ||
| @@ -442,12 +442,19 @@ static int __sev_init_ex_locked(int *error) · 441 unmodified lines | |||
| 442 | return __sev_do_cmd_locked(SEV_CMD_INIT_EX, &data, error); | 442 | return __sev_do_cmd_locked(SEV_CMD_INIT_EX, &data, error); |
| 443 | } | 443 | } |
| 444 | 444 | ||
| 445 | static inline int __sev_do_init_locked(int *psp_ret) | ||
| 446 | { | ||
| 447 | if (sev_init_ex_buffer) | ||
| 448 | return __sev_init_ex_locked(psp_ret); | ||
| 449 | else | ||
| 450 | return __sev_init_locked(psp_ret); | ||
| 451 | } | ||
| 452 | |||
| 445 | static int __sev_platform_init_locked(int *error) | 453 | static int __sev_platform_init_locked(int *error) |
| 446 | { | 454 | { |
| 455 | int rc = 0, psp_ret = SEV_RET_NO_FW_CALL; | ||
| 447 | struct psp_device *psp = psp_master; | 456 | struct psp_device *psp = psp_master; |
| 448 | struct sev_device *sev; | 457 | struct sev_device *sev; |
| 449 | int rc = 0, psp_ret = -1; | ||
| 450 | int (*init_function)(int *error); | ||
| 451 | 458 | ||
| 452 | if (!psp || !psp->sev_data) | 459 | if (!psp || !psp->sev_data) |
| 453 | return -ENODEV; | 460 | return -ENODEV; |
| @@ -458,15 +465,12 @@ static int __sev_platform_init_locked(int *error) · 4 unmodified lines | |||
| 458 | return 0; | 465 | return 0; |
| 459 | 466 | ||
| 460 | if (sev_init_ex_buffer) { | 467 | if (sev_init_ex_buffer) { |
| 461 | init_function = __sev_init_ex_locked; | ||
| 462 | rc = sev_read_init_ex_file(); | 468 | rc = sev_read_init_ex_file(); |
| 463 | if (rc) | 469 | if (rc) |
| 464 | return rc; | 470 | return rc; |
| 465 | } else { | ||
| 466 | init_function = __sev_init_locked; | ||
| 467 | } | 471 | } |
| 468 | 472 | ||
| 469 | rc = init_function(&psp_ret); | 473 | rc = __sev_do_init_locked(&psp_ret); |
| 470 | if (rc && psp_ret == SEV_RET_SECURE_DATA_INVALID) { | 474 | if (rc && psp_ret == SEV_RET_SECURE_DATA_INVALID) { |
| 471 | /* | 475 | /* |
| 472 | * Initialization command returned an integrity check failure | 476 | * Initialization command returned an integrity check failure |
| @@ -475,9 +479,11 @@ static int __sev_platform_init_locked(int *error) · 2 unmodified lines | |||
| 475 | * initialization function should succeed by replacing the state | 479 | * initialization function should succeed by replacing the state |
| 476 | * with a reset state. | 480 | * with a reset state. |
| 477 | */ | 481 | */ |
| 478 | dev_err(sev->dev, "SEV: retrying INIT command because of SECURE_DATA_INVALID error. Retrying once to reset PSP SEV state."); | 482 | dev_err(sev->dev, |
| 479 | rc = init_function(&psp_ret); | 483 | "SEV: retrying INIT command because of SECURE_DATA_INVALID error. Retrying once to reset PSP SEV state."); |
| 484 | rc = __sev_do_init_locked(&psp_ret); | ||
| 480 | } | 485 | } |
| 486 | |||
| 481 | if (error) | 487 | if (error) |
| 482 | *error = psp_ret; | 488 | *error = psp_ret; |
| 483 | 489 | ||
| @@ -211,7 +211,7 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info, · 210 unmodified lines | |||
| 211 | 211 | ||
| 212 | ring_info->ring_buffer = (struct hv_ring_buffer *) | 212 | ring_info->ring_buffer = (struct hv_ring_buffer *) |
| 213 | vmap_pfn(pfns_wraparound, page_cnt * 2 - 1, | 213 | vmap_pfn(pfns_wraparound, page_cnt * 2 - 1, |
| 214 | PAGE_KERNEL); | 214 | pgprot_decrypted(PAGE_KERNEL)); |
| 215 | kfree(pfns_wraparound); | 215 | kfree(pfns_wraparound); |
| 216 | 216 | ||
| 217 | if (!ring_info->ring_buffer) | 217 | if (!ring_info->ring_buffer) |
| @@ -2156,7 +2156,6 @@ void vmbus_device_unregister(struct hv_device *device_obj) · 2155 unmodified lines | |||
| 2156 | * VMBUS is an acpi enumerated device. Get the information we | 2156 | * VMBUS is an acpi enumerated device. Get the information we |
| 2157 | * need from DSDT. | 2157 | * need from DSDT. |
| 2158 | */ | 2158 | */ |
| 2159 | #define VTPM_BASE_ADDRESS 0xfed40000 | ||
| 2160 | static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx) | 2159 | static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx) |
| 2161 | { | 2160 | { |
| 2162 | resource_size_t start = 0; | 2161 | resource_size_t start = 0; |
| @@ -46,7 +46,15 @@ struct snp_guest_dev { · 45 unmodified lines | |||
| 46 | 46 | ||
| 47 | void *certs_data; | 47 | void *certs_data; |
| 48 | struct snp_guest_crypto *crypto; | 48 | struct snp_guest_crypto *crypto; |
| 49 | /* request and response are in unencrypted memory */ | ||
| 49 | struct snp_guest_msg *request, *response; | 50 | struct snp_guest_msg *request, *response; |
| 51 | |||
| 52 | /* | ||
| 53 | * Avoid information leakage by double-buffering shared messages | ||
| 54 | * in fields that are in regular encrypted memory. | ||
| 55 | */ | ||
| 56 | struct snp_guest_msg secret_request, secret_response; | ||
| 57 | |||
| 50 | struct snp_secrets_page_layout *layout; | 58 | struct snp_secrets_page_layout *layout; |
| 51 | struct snp_req_data input; | 59 | struct snp_req_data input; |
| 52 | u32 *os_area_msg_seqno; | 60 | u32 *os_area_msg_seqno; |
| @@ -266,14 +274,17 @@ static int dec_payload(struct snp_guest_dev *snp_dev, struct snp_guest_msg *msg, · 213 unmodified lines | |||
| 266 | static int verify_and_dec_payload(struct snp_guest_dev *snp_dev, void *payload, u32 sz) | 274 | static int verify_and_dec_payload(struct snp_guest_dev *snp_dev, void *payload, u32 sz) |
| 267 | { | 275 | { |
| 268 | struct snp_guest_crypto *crypto = snp_dev->crypto; | 276 | struct snp_guest_crypto *crypto = snp_dev->crypto; |
| 269 | struct snp_guest_msg *resp = snp_dev->response; | 277 | struct snp_guest_msg *resp = &snp_dev->secret_response; |
| 270 | struct snp_guest_msg *req = snp_dev->request; | 278 | struct snp_guest_msg *req = &snp_dev->secret_request; |
| 271 | struct snp_guest_msg_hdr *req_hdr = &req->hdr; | 279 | struct snp_guest_msg_hdr *req_hdr = &req->hdr; |
| 272 | struct snp_guest_msg_hdr *resp_hdr = &resp->hdr; | 280 | struct snp_guest_msg_hdr *resp_hdr = &resp->hdr; |
| 273 | 281 | ||
| 274 | dev_dbg(snp_dev->dev, "response [seqno %lld type %d version %d sz %d]\n", | 282 | dev_dbg(snp_dev->dev, "response [seqno %lld type %d version %d sz %d]\n", |
| 275 | resp_hdr->msg_seqno, resp_hdr->msg_type, resp_hdr->msg_version, resp_hdr->msg_sz); | 283 | resp_hdr->msg_seqno, resp_hdr->msg_type, resp_hdr->msg_version, resp_hdr->msg_sz); |
| 276 | 284 | ||
| 285 | /* Copy response from shared memory to encrypted memory. */ | ||
| 286 | memcpy(resp, snp_dev->response, sizeof(*resp)); | ||
| 287 | |||
| 277 | /* Verify that the sequence counter is incremented by 1 */ | 288 | /* Verify that the sequence counter is incremented by 1 */ |
| 278 | if (unlikely(resp_hdr->msg_seqno != (req_hdr->msg_seqno + 1))) | 289 | if (unlikely(resp_hdr->msg_seqno != (req_hdr->msg_seqno + 1))) |
| 279 | return -EBADMSG; | 290 | return -EBADMSG; |
| @@ -297,7 +308,7 @@ static int verify_and_dec_payload(struct snp_guest_dev *snp_dev, void *payload, · 17 unmodified lines | |||
| 297 | static int enc_payload(struct snp_guest_dev *snp_dev, u64 seqno, int version, u8 type, | 308 | static int enc_payload(struct snp_guest_dev *snp_dev, u64 seqno, int version, u8 type, |
| 298 | void *payload, size_t sz) | 309 | void *payload, size_t sz) |
| 299 | { | 310 | { |
| 300 | struct snp_guest_msg *req = snp_dev->request; | 311 | struct snp_guest_msg *req = &snp_dev->secret_request; |
| 301 | struct snp_guest_msg_hdr *hdr = &req->hdr; | 312 | struct snp_guest_msg_hdr *hdr = &req->hdr; |
| 302 | 313 | ||
| 303 | memset(req, 0, sizeof(*req)); | 314 | memset(req, 0, sizeof(*req)); |
| @@ -321,11 +332,12 @@ static int enc_payload(struct snp_guest_dev *snp_dev, u64 seqno, int version, u8 · 17 unmodified lines | |||
| 321 | return __enc_payload(snp_dev, req, payload, sz); | 332 | return __enc_payload(snp_dev, req, payload, sz); |
| 322 | } | 333 | } |
| 323 | 334 | ||
| 324 | static int __handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, __u64 *fw_err) | 335 | static int __handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, |
| 336 | struct snp_guest_request_ioctl *rio) | ||
| 325 | { | 337 | { |
| 326 | unsigned long err = 0xff, override_err = 0; | ||
| 327 | unsigned long req_start = jiffies; | 338 | unsigned long req_start = jiffies; |
| 328 | unsigned int override_npages = 0; | 339 | unsigned int override_npages = 0; |
| 340 | u64 override_err = 0; | ||
| 329 | int rc; | 341 | int rc; |
| 330 | 342 | ||
| 331 | retry_request: | 343 | retry_request: |
| @@ -335,7 +347,7 @@ retry_request: · 3 unmodified lines | |||
| 335 | * sequence number must be incremented or the VMPCK must be deleted to | 347 | * sequence number must be incremented or the VMPCK must be deleted to |
| 336 | * prevent reuse of the IV. | 348 | * prevent reuse of the IV. |
| 337 | */ | 349 | */ |
| 338 | rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err); | 350 | rc = snp_issue_guest_request(exit_code, &snp_dev->input, rio); |
| 339 | switch (rc) { | 351 | switch (rc) { |
| 340 | case -ENOSPC: | 352 | case -ENOSPC: |
| 341 | /* | 353 | /* |
| @@ -353,7 +365,7 @@ retry_request: · 11 unmodified lines | |||
| 353 | * request buffer size was too small and give the caller the | 365 | * request buffer size was too small and give the caller the |
| 354 | * required buffer size. | 366 | * required buffer size. |
| 355 | */ | 367 | */ |
| 356 | override_err = SNP_GUEST_REQ_INVALID_LEN; | 368 | override_err = SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN); |
| 357 | 369 | ||
| 358 | /* | 370 | /* |
| 359 | * If this call to the firmware succeeds, the sequence number can | 371 | * If this call to the firmware succeeds, the sequence number can |
| @@ -366,7 +378,7 @@ retry_request: · 6 unmodified lines | |||
| 366 | goto retry_request; | 378 | goto retry_request; |
| 367 | 379 | ||
| 368 | /* | 380 | /* |
| 369 | * The host may return SNP_GUEST_REQ_ERR_EBUSY if the request has been | 381 | * The host may return SNP_GUEST_VMM_ERR_BUSY if the request has been |
| 370 | * throttled. Retry in the driver to avoid returning and reusing the | 382 | * throttled. Retry in the driver to avoid returning and reusing the |
| 371 | * message sequence number on a different message. | 383 | * message sequence number on a different message. |
| 372 | */ | 384 | */ |
| @@ -387,27 +399,29 @@ retry_request: · 14 unmodified lines | |||
| 387 | */ | 399 | */ |
| 388 | snp_inc_msg_seqno(snp_dev); | 400 | snp_inc_msg_seqno(snp_dev); |
| 389 | 401 | ||
| 390 | if (fw_err) | 402 | if (override_err) { |
| 391 | *fw_err = override_err ?: err; | 403 | rio->exitinfo2 = override_err; |
| 404 | |||
| 405 | /* | ||
| 406 | * If an extended guest request was issued and the supplied certificate | ||
| 407 | * buffer was not large enough, a standard guest request was issued to | ||
| 408 | * prevent IV reuse. If the standard request was successful, return -EIO | ||
| 409 | * back to the caller as would have originally been returned. | ||
| 410 | */ | ||
| 411 | if (!rc && override_err == SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN)) | ||
| 412 | rc = -EIO; | ||
| 413 | } | ||
| 392 | 414 | ||
| 393 | if (override_npages) | 415 | if (override_npages) |
| 394 | snp_dev->input.data_npages = override_npages; | 416 | snp_dev->input.data_npages = override_npages; |
| 395 | 417 | ||
| 396 | /* | ||
| 397 | * If an extended guest request was issued and the supplied certificate | ||
| 398 | * buffer was not large enough, a standard guest request was issued to | ||
| 399 | * prevent IV reuse. If the standard request was successful, return -EIO | ||
| 400 | * back to the caller as would have originally been returned. | ||
| 401 | */ | ||
| 402 | if (!rc && override_err == SNP_GUEST_REQ_INVALID_LEN) | ||
| 403 | return -EIO; | ||
| 404 | |||
| 405 | return rc; | 418 | return rc; |
| 406 | } | 419 | } |
| 407 | 420 | ||
| 408 | static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, int msg_ver, | 421 | static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, |
| 409 | u8 type, void *req_buf, size_t req_sz, void *resp_buf, | 422 | struct snp_guest_request_ioctl *rio, u8 type, |
| 410 | u32 resp_sz, __u64 *fw_err) | 423 | void *req_buf, size_t req_sz, void *resp_buf, |
| 424 | u32 resp_sz) | ||
| 411 | { | 425 | { |
| 412 | u64 seqno; | 426 | u64 seqno; |
| 413 | int rc; | 427 | int rc; |
| @@ -417,19 +431,31 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in · 3 unmodified lines | |||
| 417 | if (!seqno) | 431 | if (!seqno) |
| 418 | return -EIO; | 432 | return -EIO; |
| 419 | 433 | ||
| 434 | /* Clear shared memory's response for the host to populate. */ | ||
| 420 | memset(snp_dev->response, 0, sizeof(struct snp_guest_msg)); | 435 | memset(snp_dev->response, 0, sizeof(struct snp_guest_msg)); |
| 421 | 436 | ||
| 422 | /* Encrypt the userspace provided payload */ | 437 | /* Encrypt the userspace provided payload in snp_dev->secret_request. */ |
| 423 | rc = enc_payload(snp_dev, seqno, msg_ver, type, req_buf, req_sz); | 438 | rc = enc_payload(snp_dev, seqno, rio->msg_version, type, req_buf, req_sz); |
| 424 | if (rc) | 439 | if (rc) |
| 425 | return rc; | 440 | return rc; |
| 426 | 441 | ||
| 427 | rc = __handle_guest_request(snp_dev, exit_code, fw_err); | 442 | /* |
| 443 | * Write the fully encrypted request to the shared unencrypted | ||
| 444 | * request page. | ||
| 445 | */ | ||
| 446 | memcpy(snp_dev->request, &snp_dev->secret_request, | ||
| 447 | sizeof(snp_dev->secret_request)); | ||
| 448 | |||
| 449 | rc = __handle_guest_request(snp_dev, exit_code, rio); | ||
| 428 | if (rc) { | 450 | if (rc) { |
| 429 | if (rc == -EIO && *fw_err == SNP_GUEST_REQ_INVALID_LEN) | 451 | if (rc == -EIO && |
| 452 | rio->exitinfo2 == SNP_GUEST_VMM_ERR(SNP_GUEST_VMM_ERR_INVALID_LEN)) | ||
| 430 | return rc; | 453 | return rc; |
| 431 | 454 | ||
| 432 | dev_alert(snp_dev->dev, "Detected error from ASP request. rc: %d, fw_err: %llu\n", rc, *fw_err); | 455 | dev_alert(snp_dev->dev, |
| 456 | "Detected error from ASP request. rc: %d, exitinfo2: 0x%llx\n", | ||
| 457 | rc, rio->exitinfo2); | ||
| 458 | |||
| 433 | snp_disable_vmpck(snp_dev); | 459 | snp_disable_vmpck(snp_dev); |
| 434 | return rc; | 460 | return rc; |
| 435 | } | 461 | } |
| @@ -469,9 +495,9 @@ static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_io · 33 unmodified lines | |||
| 469 | if (!resp) | 495 | if (!resp) |
| 470 | return -ENOMEM; | 496 | return -ENOMEM; |
| 471 | 497 | ||
| 472 | rc = handle_guest_request(snp_dev, SVM_VMGEXIT_GUEST_REQUEST, arg->msg_version, | 498 | rc = handle_guest_request(snp_dev, SVM_VMGEXIT_GUEST_REQUEST, arg, |
| 473 | SNP_MSG_REPORT_REQ, &req, sizeof(req), resp->data, | 499 | SNP_MSG_REPORT_REQ, &req, sizeof(req), resp->data, |
| 474 | resp_len, &arg->fw_err); | 500 | resp_len); |
| 475 | if (rc) | 501 | if (rc) |
| 476 | goto e_free; | 502 | goto e_free; |
| 477 | 503 | ||
| @@ -509,9 +535,8 @@ static int get_derived_key(struct snp_guest_dev *snp_dev, struct snp_guest_reque · 31 unmodified lines | |||
| 509 | if (copy_from_user(&req, (void __user *)arg->req_data, sizeof(req))) | 535 | if (copy_from_user(&req, (void __user *)arg->req_data, sizeof(req))) |
| 510 | return -EFAULT; | 536 | return -EFAULT; |
| 511 | 537 | ||
| 512 | rc = handle_guest_request(snp_dev, SVM_VMGEXIT_GUEST_REQUEST, arg->msg_version, | 538 | rc = handle_guest_request(snp_dev, SVM_VMGEXIT_GUEST_REQUEST, arg, |
| 513 | SNP_MSG_KEY_REQ, &req, sizeof(req), buf, resp_len, | 539 | SNP_MSG_KEY_REQ, &req, sizeof(req), buf, resp_len); |
| 514 | &arg->fw_err); | ||
| 515 | if (rc) | 540 | if (rc) |
| 516 | return rc; | 541 | return rc; |
| 517 | 542 | ||
| @@ -571,12 +596,12 @@ cmd: · 53 unmodified lines | |||
| 571 | return -ENOMEM; | 596 | return -ENOMEM; |
| 572 | 597 | ||
| 573 | snp_dev->input.data_npages = npages; | 598 | snp_dev->input.data_npages = npages; |
| 574 | ret = handle_guest_request(snp_dev, SVM_VMGEXIT_EXT_GUEST_REQUEST, arg->msg_version, | 599 | ret = handle_guest_request(snp_dev, SVM_VMGEXIT_EXT_GUEST_REQUEST, arg, |
| 575 | SNP_MSG_REPORT_REQ, &req.data, | 600 | SNP_MSG_REPORT_REQ, &req.data, |
| 576 | sizeof(req.data), resp->data, resp_len, &arg->fw_err); | 601 | sizeof(req.data), resp->data, resp_len); |
| 577 | 602 | ||
| 578 | /* If certs length is invalid then copy the returned length */ | 603 | /* If certs length is invalid then copy the returned length */ |
| 579 | if (arg->fw_err == SNP_GUEST_REQ_INVALID_LEN) { | 604 | if (arg->vmm_error == SNP_GUEST_VMM_ERR_INVALID_LEN) { |
| 580 | req.certs_len = snp_dev->input.data_npages << PAGE_SHIFT; | 605 | req.certs_len = snp_dev->input.data_npages << PAGE_SHIFT; |
| 581 | 606 | ||
| 582 | if (copy_to_user((void __user *)arg->req_data, &req, sizeof(req))) | 607 | if (copy_to_user((void __user *)arg->req_data, &req, sizeof(req))) |
| @@ -611,7 +636,7 @@ static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long · 28 unmodified lines | |||
| 611 | if (copy_from_user(&input, argp, sizeof(input))) | 636 | if (copy_from_user(&input, argp, sizeof(input))) |
| 612 | return -EFAULT; | 637 | return -EFAULT; |
| 613 | 638 | ||
| 614 | input.fw_err = 0xff; | 639 | input.exitinfo2 = 0xff; |
| 615 | 640 | ||
| 616 | /* Message version must be non-zero */ | 641 | /* Message version must be non-zero */ |
| 617 | if (!input.msg_version) | 642 | if (!input.msg_version) |
| @@ -642,7 +667,7 @@ static long snp_guest_ioctl(struct file *file, unsigned int ioctl, unsigned long · 24 unmodified lines | |||
| 642 | 667 | ||
| 643 | mutex_unlock(&snp_cmd_mutex); | 668 | mutex_unlock(&snp_cmd_mutex); |
| 644 | 669 | ||
| 645 | if (input.fw_err && copy_to_user(argp, &input, sizeof(input))) | 670 | if (input.exitinfo2 && copy_to_user(argp, &input, sizeof(input))) |
| 646 | return -EFAULT; | 671 | return -EFAULT; |
| 647 | 672 | ||
| 648 | return ret; | 673 | return ret; |
| @@ -26,6 +26,8 @@ · 25 unmodified lines | |||
| 26 | #include <asm/ptrace.h> | 26 | #include <asm/ptrace.h> |
| 27 | #include <asm/hyperv-tlfs.h> | 27 | #include <asm/hyperv-tlfs.h> |
| 28 | 28 | ||
| 29 | #define VTPM_BASE_ADDRESS 0xfed40000 | ||
| 30 | |||
| 29 | struct ms_hyperv_info { | 31 | struct ms_hyperv_info { |
| 30 | u32 features; | 32 | u32 features; |
| 31 | u32 priv_high; | 33 | u32 priv_high; |
| @@ -36,6 +36,13 @@ enum { · 35 unmodified lines | |||
| 36 | * SEV Firmware status code | 36 | * SEV Firmware status code |
| 37 | */ | 37 | */ |
| 38 | typedef enum { | 38 | typedef enum { |
| 39 | /* | ||
| 40 | * This error code is not in the SEV spec. Its purpose is to convey that | ||
| 41 | * there was an error that prevented the SEV firmware from being called. | ||
| 42 | * The SEV API error codes are 16 bits, so the -1 value will not overlap | ||
| 43 | * with possible values from the specification. | ||
| 44 | */ | ||
| 45 | SEV_RET_NO_FW_CALL = -1, | ||
| 39 | SEV_RET_SUCCESS = 0, | 46 | SEV_RET_SUCCESS = 0, |
| 40 | SEV_RET_INVALID_PLATFORM_STATE, | 47 | SEV_RET_INVALID_PLATFORM_STATE, |
| 41 | SEV_RET_INVALID_GUEST_STATE, | 48 | SEV_RET_INVALID_GUEST_STATE, |
| @@ -52,8 +52,14 @@ struct snp_guest_request_ioctl { · 51 unmodified lines | |||
| 52 | __u64 req_data; | 52 | __u64 req_data; |
| 53 | __u64 resp_data; | 53 | __u64 resp_data; |
| 54 | 54 | ||
| 55 | /* firmware error code on failure (see psp-sev.h) */ | 55 | /* bits[63:32]: VMM error code, bits[31:0] firmware error code (see psp-sev.h) */ |
| 56 | __u64 fw_err; | 56 | union { |
| 57 | __u64 exitinfo2; | ||
| 58 | struct { | ||
| 59 | __u32 fw_error; | ||
| 60 | __u32 vmm_error; | ||
| 61 | }; | ||
| 62 | }; | ||
| 57 | }; | 63 | }; |
| 58 | 64 | ||
| 59 | struct snp_ext_report_req { | 65 | struct snp_ext_report_req { |
| @@ -77,4 +83,12 @@ struct snp_ext_report_req { · 17 unmodified lines | |||
| 77 | /* Get SNP extended report as defined in the GHCB specification version 2. */ | 83 | /* Get SNP extended report as defined in the GHCB specification version 2. */ |
| 78 | #define SNP_GET_EXT_REPORT _IOWR(SNP_GUEST_REQ_IOC_TYPE, 0x2, struct snp_guest_request_ioctl) | 84 | #define SNP_GET_EXT_REPORT _IOWR(SNP_GUEST_REQ_IOC_TYPE, 0x2, struct snp_guest_request_ioctl) |
| 79 | 85 | ||
| 86 | /* Guest message request EXIT_INFO_2 constants */ | ||
| 87 | #define SNP_GUEST_FW_ERR_MASK GENMASK_ULL(31, 0) | ||
| 88 | #define SNP_GUEST_VMM_ERR_SHIFT 32 | ||
| 89 | #define SNP_GUEST_VMM_ERR(x) (((u64)x) << SNP_GUEST_VMM_ERR_SHIFT) | ||
| 90 | |||
| 91 | #define SNP_GUEST_VMM_ERR_INVALID_LEN 1 | ||
| 92 | #define SNP_GUEST_VMM_ERR_BUSY 2 | ||
| 93 | |||
| 80 | #endif /* __UAPI_LINUX_SEV_GUEST_H_ */ | 94 | #endif /* __UAPI_LINUX_SEV_GUEST_H_ */ |
| @@ -1092,14 +1092,6 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void) · 1091 unmodified lines | |||
| 1092 | */ | 1092 | */ |
| 1093 | locking_selftest(); | 1093 | locking_selftest(); |
| 1094 | 1094 | ||
| 1095 | /* | ||
| 1096 | * This needs to be called before any devices perform DMA | ||
| 1097 | * operations that might use the SWIOTLB bounce buffers. It will | ||
| 1098 | * mark the bounce buffers as decrypted so that their usage will | ||
| 1099 | * not cause "plain-text" data to be decrypted when accessed. | ||
| 1100 | */ | ||
| 1101 | mem_encrypt_init(); | ||
| 1102 | |||
| 1103 | #ifdef CONFIG_BLK_DEV_INITRD | 1095 | #ifdef CONFIG_BLK_DEV_INITRD |
| 1104 | if (initrd_start && !initrd_below_start_ok && | 1096 | if (initrd_start && !initrd_below_start_ok && |
| 1105 | page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) { | 1097 | page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) { |
| @@ -1116,6 +1108,17 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void) · 10 unmodified lines | |||
| 1116 | late_time_init(); | 1108 | late_time_init(); |
| 1117 | sched_clock_init(); | 1109 | sched_clock_init(); |
| 1118 | calibrate_delay(); | 1110 | calibrate_delay(); |
| 1111 | |||
| 1112 | /* | ||
| 1113 | * This needs to be called before any devices perform DMA | ||
| 1114 | * operations that might use the SWIOTLB bounce buffers. It will | ||
| 1115 | * mark the bounce buffers as decrypted so that their usage will | ||
| 1116 | * not cause "plain-text" data to be decrypted when accessed. It | ||
| 1117 | * must be called after late_time_init() so that Hyper-V x86/x64 | ||
| 1118 | * hypercalls work when the SWIOTLB bounce buffers are decrypted. | ||
| 1119 | */ | ||
| 1120 | mem_encrypt_init(); | ||
| 1121 | |||
| 1119 | pid_idr_init(); | 1122 | pid_idr_init(); |
| 1120 | anon_vma_init(); | 1123 | anon_vma_init(); |
| 1121 | #ifdef CONFIG_X86 | 1124 | #ifdef CONFIG_X86 |