Commit 89ea60c2 authored by Sean Christopherson's avatar Sean Christopherson Committed by Paolo Bonzini
Browse files

KVM: x86: Add support for "protected VMs" that can utilize private memory



Add a new x86 VM type, KVM_X86_SW_PROTECTED_VM, to serve as a development
and testing vehicle for Confidential (CoCo) VMs, and potentially to even
become a "real" product in the distant future, e.g. a la pKVM.

The private memory support in KVM x86 is aimed at AMD's SEV-SNP and
Intel's TDX, but those technologies are extremely complex (understatement),
difficult to debug, don't support running as nested guests, and require
hardware that's isn't universally accessible.  I.e. relying SEV-SNP or TDX
for maintaining guest private memory isn't a realistic option.

At the very least, KVM_X86_SW_PROTECTED_VM will enable a variety of
selftests for guest_memfd and private memory support without requiring
unique hardware.

Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
Reviewed-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Message-Id: <20231027182217.3615211-24-seanjc@google.com>
Reviewed-by: default avatarFuad Tabba <tabba@google.com>
Tested-by: default avatarFuad Tabba <tabba@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent eed52e43
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -147,10 +147,29 @@ described as 'basic' will be available.
The new VM has no virtual cpus and no memory.
You probably want to use 0 as machine type.

X86:
^^^^

Supported X86 VM types can be queried via KVM_CAP_VM_TYPES.

S390:
^^^^^

In order to create user controlled virtual machines on S390, check
KVM_CAP_S390_UCONTROL and use the flag KVM_VM_S390_UCONTROL as
privileged user (CAP_SYS_ADMIN).

MIPS:
^^^^^

To use hardware assisted virtualization on MIPS (VZ ASE) rather than
the default trap & emulate implementation (which changes the virtual
memory layout to fit in user mode), check KVM_CAP_MIPS_VZ and use the
flag KVM_VM_MIPS_VZ.

ARM64:
^^^^^^

On arm64, the physical address size for a VM (IPA Size limit) is limited
to 40bits by default. The limit can be configured if the host supports the
extension KVM_CAP_ARM_VM_IPA_SIZE. When supported, use
@@ -8765,6 +8784,19 @@ block sizes is exposed in KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES as a
64-bit bitmap (each bit describing a block size). The default value is
0, to disable the eager page splitting.

8.41 KVM_CAP_VM_TYPES
---------------------

:Capability: KVM_CAP_MEMORY_ATTRIBUTES
:Architectures: x86
:Type: system ioctl

This capability returns a bitmap of support VM types.  The 1-setting of bit @n
means the VM type with value @n is supported.  Possible values of @n are::

  #define KVM_X86_DEFAULT_VM	0
  #define KVM_X86_SW_PROTECTED_VM	1

9. Known KVM API problems
=========================

+9 −6
Original line number Diff line number Diff line
@@ -1255,6 +1255,7 @@ enum kvm_apicv_inhibit {
};

struct kvm_arch {
	unsigned long vm_type;
	unsigned long n_used_mmu_pages;
	unsigned long n_requested_mmu_pages;
	unsigned long n_max_mmu_pages;
@@ -2089,6 +2090,12 @@ void kvm_mmu_new_pgd(struct kvm_vcpu *vcpu, gpa_t new_pgd);
void kvm_configure_mmu(bool enable_tdp, int tdp_forced_root_level,
		       int tdp_max_root_level, int tdp_huge_page_level);

#ifdef CONFIG_KVM_PRIVATE_MEM
#define kvm_arch_has_private_mem(kvm) ((kvm)->arch.vm_type != KVM_X86_DEFAULT_VM)
#else
#define kvm_arch_has_private_mem(kvm) false
#endif

static inline u16 kvm_read_ldt(void)
{
	u16 ldt;
@@ -2137,14 +2144,10 @@ enum {
#define HF_SMM_INSIDE_NMI_MASK	(1 << 2)

# define KVM_MAX_NR_ADDRESS_SPACES	2
/* SMM is currently unsupported for guests with private memory. */
# define kvm_arch_nr_memslot_as_ids(kvm) (kvm_arch_has_private_mem(kvm) ? 1 : 2)
# define kvm_arch_vcpu_memslots_id(vcpu) ((vcpu)->arch.hflags & HF_SMM_MASK ? 1 : 0)
# define kvm_memslots_for_spte_role(kvm, role) __kvm_memslots(kvm, (role).smm)

static inline int kvm_arch_nr_memslot_as_ids(struct kvm *kvm)
{
	return KVM_MAX_NR_ADDRESS_SPACES;
}

#else
# define kvm_memslots_for_spte_role(kvm, role) __kvm_memslots(kvm, 0)
#endif
+3 −0
Original line number Diff line number Diff line
@@ -562,4 +562,7 @@ struct kvm_pmu_event_filter {
/* x86-specific KVM_EXIT_HYPERCALL flags. */
#define KVM_EXIT_HYPERCALL_LONG_MODE	BIT(0)

#define KVM_X86_DEFAULT_VM	0
#define KVM_X86_SW_PROTECTED_VM	1

#endif /* _ASM_X86_KVM_H */
+12 −0
Original line number Diff line number Diff line
@@ -77,6 +77,18 @@ config KVM_WERROR

	  If in doubt, say "N".

config KVM_SW_PROTECTED_VM
	bool "Enable support for KVM software-protected VMs"
	depends on EXPERT
	depends on X86_64
	select KVM_GENERIC_PRIVATE_MEM
	help
	  Enable support for KVM software-protected VMs.  Currently "protected"
	  means the VM can be backed with memory provided by
	  KVM_CREATE_GUEST_MEMFD.

	  If unsure, say "N".

config KVM_INTEL
	tristate "KVM for Intel (and compatible) processors support"
	depends on KVM && IA32_FEAT_CTL
+1 −0
Original line number Diff line number Diff line
@@ -297,6 +297,7 @@ static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
		.max_level = KVM_MAX_HUGEPAGE_LEVEL,
		.req_level = PG_LEVEL_4K,
		.goal_level = PG_LEVEL_4K,
		.is_private = kvm_mem_is_private(vcpu->kvm, cr2_or_gpa >> PAGE_SHIFT),
	};
	int r;

Loading