Skip to content

Commit f9cecb3

Browse files
committed
Merge branch 'kvm-sev-init2' into HEAD
The idea that no parameter would ever be necessary when enabling SEV or SEV-ES for a VM was decidedly optimistic. The first source of variability that was encountered is the desired set of VMSA features, as that affects the measurement of the VM's initial state and cannot be changed arbitrarily by the hypervisor. This series adds all the APIs that are needed to customize the features, with room for future enhancements: - a new /dev/kvm device attribute to retrieve the set of supported features (right now, only debug swap) - a new sub-operation for KVM_MEM_ENCRYPT_OP that can take a struct, replacing the existing KVM_SEV_INIT and KVM_SEV_ES_INIT It then puts the new op to work by including the VMSA features as a field of the The existing KVM_SEV_INIT and KVM_SEV_ES_INIT use the full set of supported VMSA features for backwards compatibility; but I am considering also making them use zero as the feature mask, and will gladly adjust the patches if so requested. In order to avoid creating *two* new KVM_MEM_ENCRYPT_OPs, I decided that I could as well make SEV and SEV-ES use VM types. This allows SEV-SNP to reuse the KVM_SEV_INIT2 ioctl. And while at it, KVM_SEV_INIT2 also includes two bugfixes. First of all, SEV-ES VM, when created with the new VM type instead of KVM_SEV_ES_INIT, reject KVM_GET_REGS/KVM_SET_REGS and friends on the vCPU file descriptor once the VMSA has been encrypted... which is how the API should have always behaved. Second, they also synchronize the FPU and AVX state. Signed-off-by: Paolo Bonzini <[email protected]>
2 parents 531f520 + 8c53183 commit f9cecb3

File tree

25 files changed

+703
-185
lines changed

25 files changed

+703
-185
lines changed

Documentation/virt/kvm/api.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8819,6 +8819,8 @@ means the VM type with value @n is supported. Possible values of @n are::
88198819

88208820
#define KVM_X86_DEFAULT_VM 0
88218821
#define KVM_X86_SW_PROTECTED_VM 1
8822+
#define KVM_X86_SEV_VM 2
8823+
#define KVM_X86_SEV_ES_VM 3
88228824

88238825
Note, KVM_X86_SW_PROTECTED_VM is currently only for development and testing.
88248826
Do not use KVM_X86_SW_PROTECTED_VM for "real" VMs, and especially not in

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

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,49 @@ are defined in ``<linux/psp-dev.h>``.
7676
KVM implements the following commands to support common lifecycle events of SEV
7777
guests, such as launching, running, snapshotting, migrating and decommissioning.
7878

79-
1. KVM_SEV_INIT
80-
---------------
79+
1. KVM_SEV_INIT2
80+
----------------
8181

82-
The KVM_SEV_INIT command is used by the hypervisor to initialize the SEV platform
82+
The KVM_SEV_INIT2 command is used by the hypervisor to initialize the SEV platform
8383
context. In a typical workflow, this command should be the first command issued.
8484

85+
For this command to be accepted, either KVM_X86_SEV_VM or KVM_X86_SEV_ES_VM
86+
must have been passed to the KVM_CREATE_VM ioctl. A virtual machine created
87+
with those machine types in turn cannot be run until KVM_SEV_INIT2 is invoked.
88+
89+
Parameters: struct kvm_sev_init (in)
8590

8691
Returns: 0 on success, -negative on error
8792

93+
::
94+
95+
struct kvm_sev_init {
96+
__u64 vmsa_features; /* initial value of features field in VMSA */
97+
__u32 flags; /* must be 0 */
98+
__u32 pad[9];
99+
};
100+
101+
It is an error if the hypervisor does not support any of the bits that
102+
are set in ``flags`` or ``vmsa_features``. ``vmsa_features`` must be
103+
0 for SEV virtual machines, as they do not have a VMSA.
104+
105+
This command replaces the deprecated KVM_SEV_INIT and KVM_SEV_ES_INIT commands.
106+
The commands did not have any parameters (the ```data``` field was unused) and
107+
only work for the KVM_X86_DEFAULT_VM machine type (0).
108+
109+
They behave as if:
110+
111+
* the VM type is KVM_X86_SEV_VM for KVM_SEV_INIT, or KVM_X86_SEV_ES_VM for
112+
KVM_SEV_ES_INIT
113+
114+
* the ``flags`` and ``vmsa_features`` fields of ``struct kvm_sev_init`` are
115+
set to zero
116+
117+
If the ``KVM_X86_SEV_VMSA_FEATURES`` attribute does not exist, the hypervisor only
118+
supports KVM_SEV_INIT and KVM_SEV_ES_INIT. In that case, note that KVM_SEV_ES_INIT
119+
might set the debug swap VMSA feature (bit 5) depending on the value of the
120+
``debug_swap`` parameter of ``kvm-amd.ko``.
121+
88122
2. KVM_SEV_LAUNCH_START
89123
-----------------------
90124

@@ -425,6 +459,18 @@ issued by the hypervisor to make the guest ready for execution.
425459

426460
Returns: 0 on success, -negative on error
427461

462+
Device attribute API
463+
====================
464+
465+
Attributes of the SEV implementation can be retrieved through the
466+
``KVM_HAS_DEVICE_ATTR`` and ``KVM_GET_DEVICE_ATTR`` ioctls on the ``/dev/kvm``
467+
device node, using group ``KVM_X86_GRP_SEV``.
468+
469+
Currently only one attribute is implemented:
470+
471+
* ``KVM_X86_SEV_VMSA_FEATURES``: return the set of all bits that
472+
are accepted in the ``vmsa_features`` of ``KVM_SEV_INIT2``.
473+
428474
Firmware Management
429475
===================
430476

arch/x86/include/asm/fpu/api.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ extern void fpstate_clear_xstate_component(struct fpstate *fps, unsigned int xfe
143143

144144
extern u64 xstate_get_guest_group_perm(void);
145145

146+
extern void *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr);
147+
148+
146149
/* KVM specific functions */
147150
extern bool fpu_alloc_guest_fpstate(struct fpu_guest *gfpu);
148151
extern void fpu_free_guest_fpstate(struct fpu_guest *gfpu);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ KVM_X86_OP(enter_smm)
121121
KVM_X86_OP(leave_smm)
122122
KVM_X86_OP(enable_smi_window)
123123
#endif
124+
KVM_X86_OP_OPTIONAL(dev_get_attr)
124125
KVM_X86_OP_OPTIONAL(mem_enc_ioctl)
125126
KVM_X86_OP_OPTIONAL(mem_enc_register_region)
126127
KVM_X86_OP_OPTIONAL(mem_enc_unregister_region)

arch/x86/include/asm/kvm_host.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,12 +1279,14 @@ enum kvm_apicv_inhibit {
12791279
};
12801280

12811281
struct kvm_arch {
1282-
unsigned long vm_type;
12831282
unsigned long n_used_mmu_pages;
12841283
unsigned long n_requested_mmu_pages;
12851284
unsigned long n_max_mmu_pages;
12861285
unsigned int indirect_shadow_pages;
12871286
u8 mmu_valid_gen;
1287+
u8 vm_type;
1288+
bool has_private_mem;
1289+
bool has_protected_state;
12881290
struct hlist_head mmu_page_hash[KVM_NUM_MMU_PAGES];
12891291
struct list_head active_mmu_pages;
12901292
struct list_head zapped_obsolete_pages;
@@ -1778,6 +1780,7 @@ struct kvm_x86_ops {
17781780
void (*enable_smi_window)(struct kvm_vcpu *vcpu);
17791781
#endif
17801782

1783+
int (*dev_get_attr)(u32 group, u64 attr, u64 *val);
17811784
int (*mem_enc_ioctl)(struct kvm *kvm, void __user *argp);
17821785
int (*mem_enc_register_region)(struct kvm *kvm, struct kvm_enc_region *argp);
17831786
int (*mem_enc_unregister_region)(struct kvm *kvm, struct kvm_enc_region *argp);
@@ -2152,8 +2155,9 @@ void kvm_mmu_new_pgd(struct kvm_vcpu *vcpu, gpa_t new_pgd);
21522155
void kvm_configure_mmu(bool enable_tdp, int tdp_forced_root_level,
21532156
int tdp_max_root_level, int tdp_huge_page_level);
21542157

2158+
21552159
#ifdef CONFIG_KVM_PRIVATE_MEM
2156-
#define kvm_arch_has_private_mem(kvm) ((kvm)->arch.vm_type != KVM_X86_DEFAULT_VM)
2160+
#define kvm_arch_has_private_mem(kvm) ((kvm)->arch.has_private_mem)
21572161
#else
21582162
#define kvm_arch_has_private_mem(kvm) false
21592163
#endif

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,8 +457,13 @@ struct kvm_sync_regs {
457457

458458
#define KVM_STATE_VMX_PREEMPTION_TIMER_DEADLINE 0x00000001
459459

460-
/* attributes for system fd (group 0) */
461-
#define KVM_X86_XCOMP_GUEST_SUPP 0
460+
/* vendor-independent attributes for system fd (group 0) */
461+
#define KVM_X86_GRP_SYSTEM 0
462+
# define KVM_X86_XCOMP_GUEST_SUPP 0
463+
464+
/* vendor-specific groups and attributes for system fd */
465+
#define KVM_X86_GRP_SEV 1
466+
# define KVM_X86_SEV_VMSA_FEATURES 0
462467

463468
struct kvm_vmx_nested_state_data {
464469
__u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
@@ -689,6 +694,9 @@ enum sev_cmd_id {
689694
/* Guest Migration Extension */
690695
KVM_SEV_SEND_CANCEL,
691696

697+
/* Second time is the charm; improved versions of the above ioctls. */
698+
KVM_SEV_INIT2,
699+
692700
KVM_SEV_NR_MAX,
693701
};
694702

@@ -700,6 +708,12 @@ struct kvm_sev_cmd {
700708
__u32 sev_fd;
701709
};
702710

711+
struct kvm_sev_init {
712+
__u64 vmsa_features;
713+
__u32 flags;
714+
__u32 pad[9];
715+
};
716+
703717
struct kvm_sev_launch_start {
704718
__u32 handle;
705719
__u32 policy;
@@ -856,5 +870,7 @@ struct kvm_hyperv_eventfd {
856870

857871
#define KVM_X86_DEFAULT_VM 0
858872
#define KVM_X86_SW_PROTECTED_VM 1
873+
#define KVM_X86_SEV_VM 2
874+
#define KVM_X86_SEV_ES_VM 3
859875

860876
#endif /* _ASM_X86_KVM_H */

arch/x86/kernel/fpu/xstate.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,7 @@ void *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr)
991991

992992
return __raw_xsave_addr(xsave, xfeature_nr);
993993
}
994+
EXPORT_SYMBOL_GPL(get_xsave_addr);
994995

995996
#ifdef CONFIG_ARCH_HAS_PKEYS
996997

arch/x86/kernel/fpu/xstate.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ extern int copy_sigframe_from_user_to_xstate(struct task_struct *tsk, const void
5454
extern void fpu__init_cpu_xstate(void);
5555
extern void fpu__init_system_xstate(unsigned int legacy_size);
5656

57-
extern void *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr);
58-
5957
static inline u64 xfeatures_mask_supervisor(void)
6058
{
6159
return fpu_kernel_cfg.max_features & XFEATURE_MASK_SUPERVISOR_SUPPORTED;

arch/x86/kvm/Makefile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ kvm-intel-y += vmx/vmx.o vmx/vmenter.o vmx/pmu_intel.o vmx/vmcs12.o \
2626
kvm-intel-$(CONFIG_X86_SGX_KVM) += vmx/sgx.o
2727
kvm-intel-$(CONFIG_KVM_HYPERV) += vmx/hyperv.o vmx/hyperv_evmcs.o
2828

29-
kvm-amd-y += svm/svm.o svm/vmenter.o svm/pmu.o svm/nested.o svm/avic.o \
30-
svm/sev.o
31-
kvm-amd-$(CONFIG_KVM_HYPERV) += svm/hyperv.o
29+
kvm-amd-y += svm/svm.o svm/vmenter.o svm/pmu.o svm/nested.o svm/avic.o
30+
31+
kvm-amd-$(CONFIG_KVM_AMD_SEV) += svm/sev.o
32+
kvm-amd-$(CONFIG_KVM_HYPERV) += svm/hyperv.o
3233

3334
ifdef CONFIG_HYPERV
3435
kvm-y += kvm_onhyperv.o

arch/x86/kvm/cpuid.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,7 @@ void kvm_set_cpu_caps(void)
771771
kvm_cpu_cap_mask(CPUID_8000_000A_EDX, 0);
772772

773773
kvm_cpu_cap_mask(CPUID_8000_001F_EAX,
774-
0 /* SME */ | F(SEV) | 0 /* VM_PAGE_FLUSH */ | F(SEV_ES) |
774+
0 /* SME */ | 0 /* SEV */ | 0 /* VM_PAGE_FLUSH */ | 0 /* SEV_ES */ |
775775
F(SME_COHERENT));
776776

777777
kvm_cpu_cap_mask(CPUID_8000_0021_EAX,

0 commit comments

Comments
 (0)