History

Merge tag 'x86_sev_for_v6.4_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

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

Linus Torvalds committed 3 years ago

Commit bc1bb2a2 parents c42b59b 812b05925 files · +311 −168Browse files

Unified · Split

25 files
  1. Documentation/virt/coco/sev-guest.rst +13 −7
  2. arch/x86/coco/core.c +30 −10
  3. arch/x86/hyperv/hv_init.c +0 −11
  4. arch/x86/hyperv/ivm.c +96 −46
  5. arch/x86/include/asm/coco.h +0 −1
  6. arch/x86/include/asm/mem_encrypt.h +1 −0
  7. arch/x86/include/asm/mshyperv.h +10 −6
  8. arch/x86/include/asm/sev-common.h +0 −4
  9. arch/x86/include/asm/sev.h +7 −3
  10. arch/x86/include/asm/x86_init.h +4 −0
  11. arch/x86/kernel/apic/io_apic.c +8 −2
  12. arch/x86/kernel/cpu/mshyperv.c +7 −8
  13. arch/x86/kernel/sev.c +8 −7
  14. arch/x86/kernel/x86_init.c +2 −0
  15. arch/x86/mm/ioremap.c +5 −0
  16. arch/x86/mm/mem_encrypt_amd.c +7 −3
  17. arch/x86/mm/pat/set_memory.c +0 −3
  18. drivers/crypto/ccp/sev-dev.c +14 −8
  19. drivers/hv/ring_buffer.c +1 −1
  20. drivers/hv/vmbus_drv.c +0 −1
  21. drivers/virt/coco/sev-guest/sev-guest.c +62 −37
  22. include/asm-generic/mshyperv.h +2 −0
  23. include/uapi/linux/psp-sev.h +7 −0
  24. include/uapi/linux/sev-guest.h +16 −2
  25. init/main.c +11 −8
Documentation/virt/coco/sev-guest.rst+13−7
@@ -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
40The guest ioctl should be issued on a file descriptor of the /dev/sev-guest device.40The guest ioctl should be issued on a file descriptor of the /dev/sev-guest
41The ioctl accepts struct snp_user_guest_request. The input and output structure is41device. The ioctl accepts struct snp_user_guest_request. The input and
42specified through the req_data and resp_data field respectively. If the ioctl fails42output structure is specified through the req_data and resp_data field
43to execute due to a firmware error, then fw_err code will be set otherwise the43respectively. If the ioctl fails to execute due to a firmware error, then
44fw_err will be set to 0x00000000000000ff.44the fw_error code will be set, otherwise fw_error will be set to -1.
45 45
46The firmware checks that the message sequence counter is one greater than46The firmware checks that the message sequence counter is one greater than
47the guests message sequence counter. If guest driver fails to increment message47the 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
642.1 SNP_GET_REPORT702.1 SNP_GET_REPORT
arch/x86/coco/core.c+30−10
@@ -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 */
37static __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 are49 * 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. The50 * 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 SEV57 * 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
44static bool amd_cc_platform_has(enum cc_attr attr)61static bool amd_cc_platform_has(enum cc_attr attr)
45{62{
46#ifdef CONFIG_AMD_MEM_ENCRYPT63#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#endif97#endif
77}98}
78 99
79static bool hyperv_cc_platform_has(enum cc_attr attr)
80{
81 return attr == CC_ATTR_GUEST_MEM_ENCRYPT;
82}
83
84bool cc_platform_has(enum cc_attr attr)100bool 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 encrypted119 * - 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:
arch/x86/hyperv/hv_init.c+0−11
@@ -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
34int hyperv_init_cpuhp;33int hyperv_init_cpuhp;
35u64 hv_current_partition_id = ~0ull;34u64 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
519clean_guest_os_id:508clean_guest_os_id:
arch/x86/hyperv/ivm.c+96−46
@@ -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}
235EXPORT_SYMBOL_GPL(hv_ghcb_msr_read);237EXPORT_SYMBOL_GPL(hv_ghcb_msr_read);
236#endif
237
238enum 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}
244EXPORT_SYMBOL_GPL(hv_get_isolation_type);
245
246/*
247 * hv_is_isolation_supported - Check system runs in the Hyper-V
248 * isolation VM.
249 */
250bool 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
261DEFINE_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 */
267bool 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 guest292 * In Isolation VM, all guest memory is encrypted from host and guest
326 * needs to set memory visible to host via hvcall before sharing memory293 * 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 */
330int hv_set_mem_host_visibility(unsigned long kbuffer, int pagecount, bool visible)297static 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
330static bool hv_vtom_tlb_flush_required(bool private)
331{
332 return true;
361}333}
362 334
335static bool hv_vtom_cache_flush_required(void)
336{
337 return false;
338}
339
340static 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
359void __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
407enum 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}
413EXPORT_SYMBOL_GPL(hv_get_isolation_type);
414
415/*
416 * hv_is_isolation_supported - Check system runs in the Hyper-V
417 * isolation VM.
418 */
419bool 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
430DEFINE_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 */
436bool hv_isolation_type_snp(void)
437{
438 return static_branch_unlikely(&isolation_type_snp);
439}
arch/x86/include/asm/coco.h+0−1
@@ -7,7 +7,6 @@ · 6 unmodified lines
7enum cc_vendor {7enum 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
arch/x86/include/asm/mem_encrypt.h+1−0
@@ -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 0ULL58#define sme_me_mask 0ULL
59#define sev_status 0ULL
59 60
60static inline void __init sme_early_encrypt(resource_size_t paddr,61static inline void __init sme_early_encrypt(resource_size_t paddr,
61 unsigned long size) { }62 unsigned long size) { }
arch/x86/include/asm/mshyperv.h+10−6
@@ -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
14union hv_ghcb;22union hv_ghcb;
15 23
16DECLARE_STATIC_KEY_FALSE(isolation_type_snp);24DECLARE_STATIC_KEY_FALSE(isolation_type_snp);
@@ -206,18 +214,19 @@ struct irq_domain *hv_create_pci_msi_domain(void); · 189 unmodified lines
206int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector,214int 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);
208int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry);216int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry);
209int hv_set_mem_host_visibility(unsigned long addr, int numpages, bool visible);
210 217
211#ifdef CONFIG_AMD_MEM_ENCRYPT218#ifdef CONFIG_AMD_MEM_ENCRYPT
212void hv_ghcb_msr_write(u64 msr, u64 value);219void hv_ghcb_msr_write(u64 msr, u64 value);
213void hv_ghcb_msr_read(u64 msr, u64 *value);220void hv_ghcb_msr_read(u64 msr, u64 *value);
214bool hv_ghcb_negotiate_protocol(void);221bool hv_ghcb_negotiate_protocol(void);
215void hv_ghcb_terminate(unsigned int set, unsigned int reason);222void hv_ghcb_terminate(unsigned int set, unsigned int reason);
223void hv_vtom_init(void);
216#else224#else
217static inline void hv_ghcb_msr_write(u64 msr, u64 value) {}225static inline void hv_ghcb_msr_write(u64 msr, u64 value) {}
218static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {}226static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {}
219static inline bool hv_ghcb_negotiate_protocol(void) { return false; }227static inline bool hv_ghcb_negotiate_protocol(void) { return false; }
220static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {}228static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {}
229static inline void hv_vtom_init(void) {}
221#endif230#endif
222 231
223extern bool hv_isolation_type_snp(void);232extern bool hv_isolation_type_snp(void);
@@ -259,11 +268,6 @@ static inline void hv_set_register(unsigned int reg, u64 value) { } · 35 unmodified lines
259static inline u64 hv_get_register(unsigned int reg) { return 0; }268static inline u64 hv_get_register(unsigned int reg) { return 0; }
260static inline void hv_set_non_nested_register(unsigned int reg, u64 value) { }269static inline void hv_set_non_nested_register(unsigned int reg, u64 value) { }
261static inline u64 hv_get_non_nested_register(unsigned int reg) { return 0; }270static inline u64 hv_get_non_nested_register(unsigned int reg) { return 0; }
262static 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
arch/x86/include/asm/sev-common.h+0−4
@@ -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 0x100131#define GHCB_MSR_TERM_REQ 0x100
136#define GHCB_MSR_TERM_REASON_SET_POS 12132#define GHCB_MSR_TERM_REASON_SET_POS 12
137#define GHCB_MSR_TERM_REASON_SET_MASK 0xf133#define GHCB_MSR_TERM_REASON_SET_MASK 0xf
arch/x86/include/asm/sev.h+7−3
@@ -9,6 +9,8 @@ · 8 unmodified lines
9#define __ASM_ENCRYPTED_STATE_H9#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
191struct snp_guest_request_ioctl;
192
188void setup_ghcb(void);193void setup_ghcb(void);
189void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr,194void __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
196void snp_set_wakeup_secondary_cpu(void);201void snp_set_wakeup_secondary_cpu(void);
197bool snp_init(struct boot_params *bp);202bool snp_init(struct boot_params *bp);
198void __init __noreturn snp_abort(void);203void __init __noreturn snp_abort(void);
199int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned long *fw_err);204int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio);
200#else205#else
201static inline void sev_es_ist_enter(struct pt_regs *regs) { }206static inline void sev_es_ist_enter(struct pt_regs *regs) { }
202static inline void sev_es_ist_exit(void) { }207static 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
216static inline void snp_set_wakeup_secondary_cpu(void) { }221static inline void snp_set_wakeup_secondary_cpu(void) { }
217static inline bool snp_init(struct boot_params *bp) { return false; }222static inline bool snp_init(struct boot_params *bp) { return false; }
218static inline void snp_abort(void) { }223static inline void snp_abort(void) { }
219static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input,224static 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}
arch/x86/include/asm/x86_init.h+4−0
@@ -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 #VC260 * 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 */
263struct x86_hyper_runtime {266struct 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/**
arch/x86/kernel/apic/io_apic.c+8−2
@@ -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 pgprot2684 * 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}
arch/x86/kernel/cpu/mshyperv.c+7−8
@@ -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? */
39bool hv_root_partition;38bool 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#endif415#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 */
arch/x86/kernel/sev.c+8−7
@@ -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
2178int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned long *fw_err)2180int 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 using2191 * __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);
arch/x86/kernel/x86_init.c+2−0
@@ -134,6 +134,7 @@ static void enc_status_change_prepare_noop(unsigned long vaddr, int npages, bool · 133 unmodified lines
134static bool enc_status_change_finish_noop(unsigned long vaddr, int npages, bool enc) { return false; }134static bool enc_status_change_finish_noop(unsigned long vaddr, int npages, bool enc) { return false; }
135static bool enc_tlb_flush_required_noop(bool enc) { return false; }135static bool enc_tlb_flush_required_noop(bool enc) { return false; }
136static bool enc_cache_flush_required_noop(void) { return false; }136static bool enc_cache_flush_required_noop(void) { return false; }
137static bool is_private_mmio_noop(u64 addr) {return false; }
137 138
138struct x86_platform_ops x86_platform __ro_after_init = {139struct 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,
arch/x86/mm/ioremap.c+5−0
@@ -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
arch/x86/mm/mem_encrypt_amd.c+7−3
@@ -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 encryption516 * 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");
arch/x86/mm/pat/set_memory.c+0−3
@@ -2175,9 +2175,6 @@ static int __set_memory_enc_pgtable(unsigned long addr, int numpages, bool enc) · 2174 unmodified lines
2175 2175
2176static int __set_memory_enc_dec(unsigned long addr, int numpages, bool enc)2176static 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
drivers/crypto/ccp/sev-dev.c+14−8
@@ -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
445static 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
445static int __sev_platform_init_locked(int *error)453static 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 failure476 * 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 state479 * 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
drivers/hv/ring_buffer.c+1−1
@@ -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)
drivers/hv/vmbus_drv.c+0−1
@@ -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 we2156 * 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
2160static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx)2159static 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;
drivers/virt/coco/sev-guest/sev-guest.c+62−37
@@ -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
266static int verify_and_dec_payload(struct snp_guest_dev *snp_dev, void *payload, u32 sz)274static 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
297static int enc_payload(struct snp_guest_dev *snp_dev, u64 seqno, int version, u8 type,308static 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
324static int __handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, __u64 *fw_err)335static 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
331retry_request:343retry_request:
@@ -335,7 +347,7 @@ retry_request: · 3 unmodified lines
335 * sequence number must be incremented or the VMPCK must be deleted to347 * 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 the365 * 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 can371 * 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 been381 * 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 the382 * 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
408static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, int msg_ver,421static 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;
include/asm-generic/mshyperv.h+2−0
@@ -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
29struct ms_hyperv_info {31struct ms_hyperv_info {
30 u32 features;32 u32 features;
31 u32 priv_high;33 u32 priv_high;
include/uapi/linux/psp-sev.h+7−0
@@ -36,6 +36,13 @@ enum { · 35 unmodified lines
36 * SEV Firmware status code36 * SEV Firmware status code
37 */37 */
38typedef enum {38typedef 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,
include/uapi/linux/sev-guest.h+16−2
@@ -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
59struct snp_ext_report_req {65struct 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_ */
init/main.c+11−8
@@ -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_INITRD1095#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_X861124#ifdef CONFIG_X86

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t