Skip to content

Commit ab978c6

Browse files
committed
Merge branch 'kvm-6.11-sev-snp' into HEAD
Pull base x86 KVM support for running SEV-SNP guests from Michael Roth: * add some basic infrastructure and introduces a new KVM_X86_SNP_VM vm_type to handle differences versus the existing KVM_X86_SEV_VM and KVM_X86_SEV_ES_VM types. * implement the KVM API to handle the creation of a cryptographic launch context, encrypt/measure the initial image into guest memory, and finalize it before launching it. * implement handling for various guest-generated events such as page state changes, onlining of additional vCPUs, etc. * implement the gmem/mmu hooks needed to prepare gmem-allocated pages before mapping them into guest private memory ranges as well as cleaning them up prior to returning them to the host for use as normal memory. Because those cleanup hooks supplant certain activities like issuing WBINVDs during KVM MMU invalidations, avoid duplicating that work to avoid unecessary overhead. This merge leaves out support support for attestation guest requests and for loading the signing keys to be used for attestation requests.
2 parents f9d1b54 + b2ec042 commit ab978c6

File tree

21 files changed

+1923
-57
lines changed

21 files changed

+1923
-57
lines changed

Documentation/virt/kvm/x86/amd-memory-encryption.rst

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,112 @@ issued by the hypervisor to make the guest ready for execution.
466466

467467
Returns: 0 on success, -negative on error
468468

469+
18. KVM_SEV_SNP_LAUNCH_START
470+
----------------------------
471+
472+
The KVM_SNP_LAUNCH_START command is used for creating the memory encryption
473+
context for the SEV-SNP guest. It must be called prior to issuing
474+
KVM_SEV_SNP_LAUNCH_UPDATE or KVM_SEV_SNP_LAUNCH_FINISH;
475+
476+
Parameters (in): struct kvm_sev_snp_launch_start
477+
478+
Returns: 0 on success, -negative on error
479+
480+
::
481+
482+
struct kvm_sev_snp_launch_start {
483+
__u64 policy; /* Guest policy to use. */
484+
__u8 gosvw[16]; /* Guest OS visible workarounds. */
485+
__u16 flags; /* Must be zero. */
486+
__u8 pad0[6];
487+
__u64 pad1[4];
488+
};
489+
490+
See SNP_LAUNCH_START in the SEV-SNP specification [snp-fw-abi]_ for further
491+
details on the input parameters in ``struct kvm_sev_snp_launch_start``.
492+
493+
19. KVM_SEV_SNP_LAUNCH_UPDATE
494+
-----------------------------
495+
496+
The KVM_SEV_SNP_LAUNCH_UPDATE command is used for loading userspace-provided
497+
data into a guest GPA range, measuring the contents into the SNP guest context
498+
created by KVM_SEV_SNP_LAUNCH_START, and then encrypting/validating that GPA
499+
range so that it will be immediately readable using the encryption key
500+
associated with the guest context once it is booted, after which point it can
501+
attest the measurement associated with its context before unlocking any
502+
secrets.
503+
504+
It is required that the GPA ranges initialized by this command have had the
505+
KVM_MEMORY_ATTRIBUTE_PRIVATE attribute set in advance. See the documentation
506+
for KVM_SET_MEMORY_ATTRIBUTES for more details on this aspect.
507+
508+
Upon success, this command is not guaranteed to have processed the entire
509+
range requested. Instead, the ``gfn_start``, ``uaddr``, and ``len`` fields of
510+
``struct kvm_sev_snp_launch_update`` will be updated to correspond to the
511+
remaining range that has yet to be processed. The caller should continue
512+
calling this command until those fields indicate the entire range has been
513+
processed, e.g. ``len`` is 0, ``gfn_start`` is equal to the last GFN in the
514+
range plus 1, and ``uaddr`` is the last byte of the userspace-provided source
515+
buffer address plus 1. In the case where ``type`` is KVM_SEV_SNP_PAGE_TYPE_ZERO,
516+
``uaddr`` will be ignored completely.
517+
518+
Parameters (in): struct kvm_sev_snp_launch_update
519+
520+
Returns: 0 on success, < 0 on error, -EAGAIN if caller should retry
521+
522+
::
523+
524+
struct kvm_sev_snp_launch_update {
525+
__u64 gfn_start; /* Guest page number to load/encrypt data into. */
526+
__u64 uaddr; /* Userspace address of data to be loaded/encrypted. */
527+
__u64 len; /* 4k-aligned length in bytes to copy into guest memory.*/
528+
__u8 type; /* The type of the guest pages being initialized. */
529+
__u8 pad0;
530+
__u16 flags; /* Must be zero. */
531+
__u32 pad1;
532+
__u64 pad2[4];
533+
534+
};
535+
536+
where the allowed values for page_type are #define'd as::
537+
538+
KVM_SEV_SNP_PAGE_TYPE_NORMAL
539+
KVM_SEV_SNP_PAGE_TYPE_ZERO
540+
KVM_SEV_SNP_PAGE_TYPE_UNMEASURED
541+
KVM_SEV_SNP_PAGE_TYPE_SECRETS
542+
KVM_SEV_SNP_PAGE_TYPE_CPUID
543+
544+
See the SEV-SNP spec [snp-fw-abi]_ for further details on how each page type is
545+
used/measured.
546+
547+
20. KVM_SEV_SNP_LAUNCH_FINISH
548+
-----------------------------
549+
550+
After completion of the SNP guest launch flow, the KVM_SEV_SNP_LAUNCH_FINISH
551+
command can be issued to make the guest ready for execution.
552+
553+
Parameters (in): struct kvm_sev_snp_launch_finish
554+
555+
Returns: 0 on success, -negative on error
556+
557+
::
558+
559+
struct kvm_sev_snp_launch_finish {
560+
__u64 id_block_uaddr;
561+
__u64 id_auth_uaddr;
562+
__u8 id_block_en;
563+
__u8 auth_key_en;
564+
__u8 vcek_disabled;
565+
__u8 host_data[32];
566+
__u8 pad0[3];
567+
__u16 flags; /* Must be zero */
568+
__u64 pad1[4];
569+
};
570+
571+
572+
See SNP_LAUNCH_FINISH in the SEV-SNP specification [snp-fw-abi]_ for further
573+
details on the input parameters in ``struct kvm_sev_snp_launch_finish``.
574+
469575
Device attribute API
470576
====================
471577

@@ -497,9 +603,11 @@ References
497603
==========
498604

499605

500-
See [white-paper]_, [api-spec]_, [amd-apm]_ and [kvm-forum]_ for more info.
606+
See [white-paper]_, [api-spec]_, [amd-apm]_, [kvm-forum]_, and [snp-fw-abi]_
607+
for more info.
501608

502609
.. [white-paper] https://developer.amd.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
503610
.. [api-spec] https://support.amd.com/TechDocs/55766_SEV-KM_API_Specification.pdf
504611
.. [amd-apm] https://support.amd.com/TechDocs/24593.pdf (section 15.34)
505612
.. [kvm-forum] https://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
613+
.. [snp-fw-abi] https://www.amd.com/system/files/TechDocs/56860.pdf

arch/x86/include/asm/kvm-x86-ops.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ KVM_X86_OP(vcpu_deliver_sipi_vector)
139139
KVM_X86_OP_OPTIONAL_RET0(vcpu_get_apicv_inhibit_reasons);
140140
KVM_X86_OP_OPTIONAL(get_untagged_addr)
141141
KVM_X86_OP_OPTIONAL(alloc_apic_backing_page)
142+
KVM_X86_OP_OPTIONAL_RET0(gmem_prepare)
143+
KVM_X86_OP_OPTIONAL_RET0(private_max_mapping_level)
144+
KVM_X86_OP_OPTIONAL(gmem_invalidate)
142145

143146
#undef KVM_X86_OP
144147
#undef KVM_X86_OP_OPTIONAL

arch/x86/include/asm/kvm_host.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@
121121
KVM_ARCH_REQ_FLAGS(31, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
122122
#define KVM_REQ_HV_TLB_FLUSH \
123123
KVM_ARCH_REQ_FLAGS(32, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
124+
#define KVM_REQ_UPDATE_PROTECTED_GUEST_STATE KVM_ARCH_REQ(34)
124125

125126
#define CR0_RESERVED_BITS \
126127
(~(unsigned long)(X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | X86_CR0_TS \
@@ -1812,6 +1813,9 @@ struct kvm_x86_ops {
18121813

18131814
gva_t (*get_untagged_addr)(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags);
18141815
void *(*alloc_apic_backing_page)(struct kvm_vcpu *vcpu);
1816+
int (*gmem_prepare)(struct kvm *kvm, kvm_pfn_t pfn, gfn_t gfn, int max_order);
1817+
void (*gmem_invalidate)(kvm_pfn_t start, kvm_pfn_t end);
1818+
int (*private_max_mapping_level)(struct kvm *kvm, kvm_pfn_t pfn);
18151819
};
18161820

18171821
struct kvm_x86_nested_ops {
@@ -1939,6 +1943,7 @@ void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
19391943
const struct kvm_memory_slot *memslot);
19401944
void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm, u64 gen);
19411945
void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned long kvm_nr_mmu_pages);
1946+
void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end);
19421947

19431948
int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3);
19441949

arch/x86/include/asm/sev-common.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@
5959
#define GHCB_MSR_AP_RESET_HOLD_RESULT_POS 12
6060
#define GHCB_MSR_AP_RESET_HOLD_RESULT_MASK GENMASK_ULL(51, 0)
6161

62+
/* Preferred GHCB GPA Request */
63+
#define GHCB_MSR_PREF_GPA_REQ 0x010
64+
#define GHCB_MSR_GPA_VALUE_POS 12
65+
#define GHCB_MSR_GPA_VALUE_MASK GENMASK_ULL(51, 0)
66+
67+
#define GHCB_MSR_PREF_GPA_RESP 0x011
68+
#define GHCB_MSR_PREF_GPA_NONE 0xfffffffffffff
69+
6270
/* GHCB GPA Register */
6371
#define GHCB_MSR_REG_GPA_REQ 0x012
6472
#define GHCB_MSR_REG_GPA_REQ_VAL(v) \
@@ -93,11 +101,17 @@ enum psc_op {
93101
/* GHCBData[11:0] */ \
94102
GHCB_MSR_PSC_REQ)
95103

104+
#define GHCB_MSR_PSC_REQ_TO_GFN(msr) (((msr) & GENMASK_ULL(51, 12)) >> 12)
105+
#define GHCB_MSR_PSC_REQ_TO_OP(msr) (((msr) & GENMASK_ULL(55, 52)) >> 52)
106+
96107
#define GHCB_MSR_PSC_RESP 0x015
97108
#define GHCB_MSR_PSC_RESP_VAL(val) \
98109
/* GHCBData[63:32] */ \
99110
(((u64)(val) & GENMASK_ULL(63, 32)) >> 32)
100111

112+
/* Set highest bit as a generic error response */
113+
#define GHCB_MSR_PSC_RESP_ERROR (BIT_ULL(63) | GHCB_MSR_PSC_RESP)
114+
101115
/* GHCB Hypervisor Feature Request/Response */
102116
#define GHCB_MSR_HV_FT_REQ 0x080
103117
#define GHCB_MSR_HV_FT_RESP 0x081
@@ -115,8 +129,19 @@ enum psc_op {
115129
* The VMGEXIT_PSC_MAX_ENTRY determines the size of the PSC structure, which
116130
* is a local stack variable in set_pages_state(). Do not increase this value
117131
* without evaluating the impact to stack usage.
132+
*
133+
* Use VMGEXIT_PSC_MAX_COUNT in cases where the actual GHCB-defined max value
134+
* is needed, such as when processing GHCB requests on the hypervisor side.
118135
*/
119136
#define VMGEXIT_PSC_MAX_ENTRY 64
137+
#define VMGEXIT_PSC_MAX_COUNT 253
138+
139+
#define VMGEXIT_PSC_ERROR_GENERIC (0x100UL << 32)
140+
#define VMGEXIT_PSC_ERROR_INVALID_HDR ((1UL << 32) | 1)
141+
#define VMGEXIT_PSC_ERROR_INVALID_ENTRY ((1UL << 32) | 2)
142+
143+
#define VMGEXIT_PSC_OP_PRIVATE 1
144+
#define VMGEXIT_PSC_OP_SHARED 2
120145

121146
struct psc_hdr {
122147
u16 cur_entry;

arch/x86/include/asm/sev.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ extern bool handle_vc_boot_ghcb(struct pt_regs *regs);
9191
/* RMUPDATE detected 4K page and 2MB page overlap. */
9292
#define RMPUPDATE_FAIL_OVERLAP 4
9393

94+
/* PSMASH failed due to concurrent access by another CPU */
95+
#define PSMASH_FAIL_INUSE 3
96+
9497
/* RMP page size */
9598
#define RMP_PG_SIZE_4K 0
9699
#define RMP_PG_SIZE_2M 1

arch/x86/include/asm/svm.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,14 @@ static_assert((X2AVIC_MAX_PHYSICAL_ID & AVIC_PHYSICAL_MAX_INDEX_MASK) == X2AVIC_
285285

286286
#define AVIC_HPA_MASK ~((0xFFFULL << 52) | 0xFFF)
287287

288-
#define SVM_SEV_FEAT_DEBUG_SWAP BIT(5)
288+
#define SVM_SEV_FEAT_SNP_ACTIVE BIT(0)
289+
#define SVM_SEV_FEAT_RESTRICTED_INJECTION BIT(3)
290+
#define SVM_SEV_FEAT_ALTERNATE_INJECTION BIT(4)
291+
#define SVM_SEV_FEAT_DEBUG_SWAP BIT(5)
292+
293+
#define SVM_SEV_FEAT_INT_INJ_MODES \
294+
(SVM_SEV_FEAT_RESTRICTED_INJECTION | \
295+
SVM_SEV_FEAT_ALTERNATE_INJECTION)
289296

290297
struct vmcb_seg {
291298
u16 selector;

arch/x86/include/uapi/asm/kvm.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,11 @@ enum sev_cmd_id {
697697
/* Second time is the charm; improved versions of the above ioctls. */
698698
KVM_SEV_INIT2,
699699

700+
/* SNP-specific commands */
701+
KVM_SEV_SNP_LAUNCH_START = 100,
702+
KVM_SEV_SNP_LAUNCH_UPDATE,
703+
KVM_SEV_SNP_LAUNCH_FINISH,
704+
700705
KVM_SEV_NR_MAX,
701706
};
702707

@@ -824,6 +829,48 @@ struct kvm_sev_receive_update_data {
824829
__u32 pad2;
825830
};
826831

832+
struct kvm_sev_snp_launch_start {
833+
__u64 policy;
834+
__u8 gosvw[16];
835+
__u16 flags;
836+
__u8 pad0[6];
837+
__u64 pad1[4];
838+
};
839+
840+
/* Kept in sync with firmware values for simplicity. */
841+
#define KVM_SEV_SNP_PAGE_TYPE_NORMAL 0x1
842+
#define KVM_SEV_SNP_PAGE_TYPE_ZERO 0x3
843+
#define KVM_SEV_SNP_PAGE_TYPE_UNMEASURED 0x4
844+
#define KVM_SEV_SNP_PAGE_TYPE_SECRETS 0x5
845+
#define KVM_SEV_SNP_PAGE_TYPE_CPUID 0x6
846+
847+
struct kvm_sev_snp_launch_update {
848+
__u64 gfn_start;
849+
__u64 uaddr;
850+
__u64 len;
851+
__u8 type;
852+
__u8 pad0;
853+
__u16 flags;
854+
__u32 pad1;
855+
__u64 pad2[4];
856+
};
857+
858+
#define KVM_SEV_SNP_ID_BLOCK_SIZE 96
859+
#define KVM_SEV_SNP_ID_AUTH_SIZE 4096
860+
#define KVM_SEV_SNP_FINISH_DATA_SIZE 32
861+
862+
struct kvm_sev_snp_launch_finish {
863+
__u64 id_block_uaddr;
864+
__u64 id_auth_uaddr;
865+
__u8 id_block_en;
866+
__u8 auth_key_en;
867+
__u8 vcek_disabled;
868+
__u8 host_data[KVM_SEV_SNP_FINISH_DATA_SIZE];
869+
__u8 pad0[3];
870+
__u16 flags;
871+
__u64 pad1[4];
872+
};
873+
827874
#define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0)
828875
#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1)
829876

@@ -874,5 +921,6 @@ struct kvm_hyperv_eventfd {
874921
#define KVM_X86_SW_PROTECTED_VM 1
875922
#define KVM_X86_SEV_VM 2
876923
#define KVM_X86_SEV_ES_VM 3
924+
#define KVM_X86_SNP_VM 4
877925

878926
#endif /* _ASM_X86_KVM_H */

arch/x86/kvm/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ config KVM_AMD_SEV
139139
depends on KVM_AMD && X86_64
140140
depends on CRYPTO_DEV_SP_PSP && !(KVM_AMD=y && CRYPTO_DEV_CCP_DD=m)
141141
select ARCH_HAS_CC_PLATFORM
142+
select KVM_GENERIC_PRIVATE_MEM
143+
select HAVE_KVM_GMEM_PREPARE
144+
select HAVE_KVM_GMEM_INVALIDATE
142145
help
143146
Provides support for launching Encrypted VMs (SEV) and Encrypted VMs
144147
with Encrypted State (SEV-ES) on AMD processors.

arch/x86/kvm/mmu.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,6 @@ static inline bool kvm_mmu_honors_guest_mtrrs(struct kvm *kvm)
253253
return __kvm_mmu_honors_guest_mtrrs(kvm_arch_has_noncoherent_dma(kvm));
254254
}
255255

256-
void kvm_zap_gfn_range(struct kvm *kvm, gfn_t gfn_start, gfn_t gfn_end);
257-
258256
int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu);
259257

260258
int kvm_mmu_post_init_vm(struct kvm *kvm);

0 commit comments

Comments
 (0)