Skip to content

Commit

Permalink
KVM: x86: Add platform hook for initializing private memory
Browse files Browse the repository at this point in the history
TODO: add a CONFIG option rather than relying on a __weak reference for
arch/platform that don't implement this hook

All gmem pages are expected to be 'private' as defined by a particular
arch/platform. Platforms like SEV-SNP require additional operations to
move these pages into a private state, so implement a hook that can be
used to prepare this memory prior to mapping it into a guest.

In some cases, such as SEV-SNP, this memory needs to be written to prior
to converting it to a private page, so also add a __kvm_gmem_get_pfn()
helper that can be used to skip the hook.

Signed-off-by: Michael Roth <michael.roth@amd.com>
  • Loading branch information
mdroth committed May 22, 2023
1 parent 4cedf72 commit adf78d2
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 2 deletions.
1 change: 1 addition & 0 deletions arch/x86/include/asm/kvm-x86-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ KVM_X86_OP(msr_filter_changed)
KVM_X86_OP(complete_emulated_msr)
KVM_X86_OP(vcpu_deliver_sipi_vector)
KVM_X86_OP_OPTIONAL_RET0(vcpu_get_apicv_inhibit_reasons);
KVM_X86_OP_OPTIONAL_RET0(gmem_prepare)

#undef KVM_X86_OP
#undef KVM_X86_OP_OPTIONAL
Expand Down
3 changes: 3 additions & 0 deletions arch/x86/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -1732,6 +1732,9 @@ struct kvm_x86_ops {
* Returns vCPU specific APICv inhibit reasons
*/
unsigned long (*vcpu_get_apicv_inhibit_reasons)(struct kvm_vcpu *vcpu);

int (*gmem_prepare)(struct kvm *kvm, struct kvm_memory_slot *slot,
kvm_pfn_t pfn_start, gfn_t gfn_start, int order);
};

struct kvm_x86_nested_ops {
Expand Down
7 changes: 7 additions & 0 deletions arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -13252,6 +13252,13 @@ bool kvm_arch_no_poll(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_arch_no_poll);

#ifdef CONFIG_KVM_PRIVATE_MEM
int kvm_arch_gmem_prepare(struct kvm *kvm, struct kvm_memory_slot *slot,
kvm_pfn_t pfn_start, gfn_t gfn_start, int order)
{
return static_call(kvm_x86_gmem_prepare)(kvm, slot, pfn_start, gfn_start, order);
}
#endif

int kvm_spec_ctrl_test_value(u64 value)
{
Expand Down
13 changes: 13 additions & 0 deletions include/linux/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -2343,6 +2343,11 @@ static inline bool kvm_mem_is_private(struct kvm *kvm, gfn_t gfn)
#ifdef CONFIG_KVM_PRIVATE_MEM
int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
gfn_t gfn, kvm_pfn_t *pfn, int *order);
int __kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
gfn_t gfn, kvm_pfn_t *pfn, int *order);
int kvm_arch_gmem_prepare(struct kvm *kvm, struct kvm_memory_slot *slot,
kvm_pfn_t pfn_start, gfn_t gfn_start, int order);

#else
static inline int kvm_gmem_get_pfn(struct kvm *kvm,
struct kvm_memory_slot *slot, gfn_t gfn,
Expand All @@ -2351,6 +2356,14 @@ static inline int kvm_gmem_get_pfn(struct kvm *kvm,
KVM_BUG_ON(1, kvm);
return -EIO;
}

static inline int __kvm_gmem_get_pfn(struct kvm *kvm,
struct kvm_memory_slot *slot, gfn_t gfn,
kvm_pfn_t *pfn, int *order)
{
KVM_BUG_ON(1, kvm);
return -EIO;
}
#endif /* CONFIG_KVM_PRIVATE_MEM */

#endif
21 changes: 19 additions & 2 deletions virt/kvm/guest_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -469,9 +469,14 @@ void kvm_gmem_unbind(struct kvm_memory_slot *slot)
slot->gmem.file = NULL;
}

int __weak kvm_arch_gmem_prepare(struct kvm *kvm, struct kvm_memory_slot *slot,
kvm_pfn_t pfn, gfn_t gfn, int order)
{
return 0;
}

int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
gfn_t gfn, kvm_pfn_t *pfn, int *order)
int __kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
gfn_t gfn, kvm_pfn_t *pfn, int *order)
{
pgoff_t index = gfn - slot->base_gfn + slot->gmem.index;
struct file *file = slot->gmem.file;
Expand All @@ -495,6 +500,18 @@ int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,

return 0;
}
EXPORT_SYMBOL_GPL(__kvm_gmem_get_pfn);

int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
gfn_t gfn, kvm_pfn_t *pfn, int *order)
{
int ret = __kvm_gmem_get_pfn(kvm, slot, gfn, pfn, order);

if (ret)
return ret;

return kvm_arch_gmem_prepare(kvm, slot, *pfn, gfn, *order);
}
EXPORT_SYMBOL_GPL(kvm_gmem_get_pfn);

static int kvm_gmem_init_fs_context(struct fs_context *fc)
Expand Down

0 comments on commit adf78d2

Please sign in to comment.