[RFC,02/16] x86/kvm: Introduce KVM memory protection feature
diff mbox series

Message ID 20200522125214.31348-3-kirill.shutemov@linux.intel.com
State New
Headers show
Series
  • KVM protected memory extension
Related show

Commit Message

Kirill A. Shutemov May 22, 2020, 12:52 p.m. UTC
Provide basic helpers, KVM_FEATURE and a hypercall.

Host side doesn't provide the feature yet, so it is a dead code for now.

Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
---
 arch/x86/include/asm/kvm_para.h      |  5 +++++
 arch/x86/include/uapi/asm/kvm_para.h |  3 ++-
 arch/x86/kernel/kvm.c                | 16 ++++++++++++++++
 include/uapi/linux/kvm_para.h        |  3 ++-
 4 files changed, 25 insertions(+), 2 deletions(-)

Comments

Vitaly Kuznetsov May 25, 2020, 2:58 p.m. UTC | #1
"Kirill A. Shutemov" <kirill@shutemov.name> writes:

> Provide basic helpers, KVM_FEATURE and a hypercall.
>
> Host side doesn't provide the feature yet, so it is a dead code for now.
>
> Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
> ---
>  arch/x86/include/asm/kvm_para.h      |  5 +++++
>  arch/x86/include/uapi/asm/kvm_para.h |  3 ++-
>  arch/x86/kernel/kvm.c                | 16 ++++++++++++++++
>  include/uapi/linux/kvm_para.h        |  3 ++-
>  4 files changed, 25 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
> index 9b4df6eaa11a..3ce84fc07144 100644
> --- a/arch/x86/include/asm/kvm_para.h
> +++ b/arch/x86/include/asm/kvm_para.h
> @@ -10,11 +10,16 @@ extern void kvmclock_init(void);
>  
>  #ifdef CONFIG_KVM_GUEST
>  bool kvm_check_and_clear_guest_paused(void);
> +bool kvm_mem_protected(void);
>  #else
>  static inline bool kvm_check_and_clear_guest_paused(void)
>  {
>  	return false;
>  }
> +static inline bool kvm_mem_protected(void)
> +{
> +	return false;
> +}
>  #endif /* CONFIG_KVM_GUEST */
>  
>  #define KVM_HYPERCALL \
> diff --git a/arch/x86/include/uapi/asm/kvm_para.h b/arch/x86/include/uapi/asm/kvm_para.h
> index 2a8e0b6b9805..c3b499acc98f 100644
> --- a/arch/x86/include/uapi/asm/kvm_para.h
> +++ b/arch/x86/include/uapi/asm/kvm_para.h
> @@ -28,9 +28,10 @@
>  #define KVM_FEATURE_PV_UNHALT		7
>  #define KVM_FEATURE_PV_TLB_FLUSH	9
>  #define KVM_FEATURE_ASYNC_PF_VMEXIT	10
> -#define KVM_FEATURE_PV_SEND_IPI	11
> +#define KVM_FEATURE_PV_SEND_IPI		11

Nit: spurrious change

>  #define KVM_FEATURE_POLL_CONTROL	12
>  #define KVM_FEATURE_PV_SCHED_YIELD	13
> +#define KVM_FEATURE_MEM_PROTECTED	14
>  
>  #define KVM_HINTS_REALTIME      0
>  
> diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
> index 6efe0410fb72..bda761ca0d26 100644
> --- a/arch/x86/kernel/kvm.c
> +++ b/arch/x86/kernel/kvm.c
> @@ -35,6 +35,13 @@
>  #include <asm/tlb.h>
>  #include <asm/cpuidle_haltpoll.h>
>  
> +static bool mem_protected;
> +
> +bool kvm_mem_protected(void)
> +{
> +	return mem_protected;
> +}
> +

Honestly, I don't see a need for kvm_mem_protected(), just rename the
bool if you need kvm_ prefix :-)

>  static int kvmapf = 1;
>  
>  static int __init parse_no_kvmapf(char *arg)
> @@ -727,6 +734,15 @@ static void __init kvm_init_platform(void)
>  {
>  	kvmclock_init();
>  	x86_platform.apic_post_init = kvm_apic_init;
> +
> +	if (kvm_para_has_feature(KVM_FEATURE_MEM_PROTECTED)) {
> +		if (kvm_hypercall0(KVM_HC_ENABLE_MEM_PROTECTED)) {
> +			pr_err("Failed to enable KVM memory protection\n");
> +			return;
> +		}
> +
> +		mem_protected = true;
> +	}
>  }

Personally, I'd prefer to do this via setting a bit in a KVM-specific
MSR instead. The benefit is that the guest doesn't need to remember if
it enabled the feature or not, it can always read the config msr. May
come handy for e.g. kexec/kdump.

>  
>  const __initconst struct hypervisor_x86 x86_hyper_kvm = {
> diff --git a/include/uapi/linux/kvm_para.h b/include/uapi/linux/kvm_para.h
> index 8b86609849b9..1a216f32e572 100644
> --- a/include/uapi/linux/kvm_para.h
> +++ b/include/uapi/linux/kvm_para.h
> @@ -27,8 +27,9 @@
>  #define KVM_HC_MIPS_EXIT_VM		7
>  #define KVM_HC_MIPS_CONSOLE_OUTPUT	8
>  #define KVM_HC_CLOCK_PAIRING		9
> -#define KVM_HC_SEND_IPI		10
> +#define KVM_HC_SEND_IPI			10

Same spurrious change detected.

>  #define KVM_HC_SCHED_YIELD		11
> +#define KVM_HC_ENABLE_MEM_PROTECTED	12
>  
>  /*
>   * hypercalls use architecture specific
Kirill A. Shutemov May 25, 2020, 3:15 p.m. UTC | #2
On Mon, May 25, 2020 at 04:58:51PM +0200, Vitaly Kuznetsov wrote:
> "Kirill A. Shutemov" <kirill@shutemov.name> writes:
> 
> > Provide basic helpers, KVM_FEATURE and a hypercall.
> >
> > Host side doesn't provide the feature yet, so it is a dead code for now.
> >
> > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
> > ---
> >  arch/x86/include/asm/kvm_para.h      |  5 +++++
> >  arch/x86/include/uapi/asm/kvm_para.h |  3 ++-
> >  arch/x86/kernel/kvm.c                | 16 ++++++++++++++++
> >  include/uapi/linux/kvm_para.h        |  3 ++-
> >  4 files changed, 25 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
> > index 9b4df6eaa11a..3ce84fc07144 100644
> > --- a/arch/x86/include/asm/kvm_para.h
> > +++ b/arch/x86/include/asm/kvm_para.h
> > @@ -10,11 +10,16 @@ extern void kvmclock_init(void);
> >  
> >  #ifdef CONFIG_KVM_GUEST
> >  bool kvm_check_and_clear_guest_paused(void);
> > +bool kvm_mem_protected(void);
> >  #else
> >  static inline bool kvm_check_and_clear_guest_paused(void)
> >  {
> >  	return false;
> >  }
> > +static inline bool kvm_mem_protected(void)
> > +{
> > +	return false;
> > +}
> >  #endif /* CONFIG_KVM_GUEST */
> >  
> >  #define KVM_HYPERCALL \
> > diff --git a/arch/x86/include/uapi/asm/kvm_para.h b/arch/x86/include/uapi/asm/kvm_para.h
> > index 2a8e0b6b9805..c3b499acc98f 100644
> > --- a/arch/x86/include/uapi/asm/kvm_para.h
> > +++ b/arch/x86/include/uapi/asm/kvm_para.h
> > @@ -28,9 +28,10 @@
> >  #define KVM_FEATURE_PV_UNHALT		7
> >  #define KVM_FEATURE_PV_TLB_FLUSH	9
> >  #define KVM_FEATURE_ASYNC_PF_VMEXIT	10
> > -#define KVM_FEATURE_PV_SEND_IPI	11
> > +#define KVM_FEATURE_PV_SEND_IPI		11
> 
> Nit: spurrious change
> 

I fixed indentation while there. (Look at the file, not the diff to see
what I mean).

> >  #define KVM_FEATURE_POLL_CONTROL	12
> >  #define KVM_FEATURE_PV_SCHED_YIELD	13
> > +#define KVM_FEATURE_MEM_PROTECTED	14
> >  
> >  #define KVM_HINTS_REALTIME      0
> >  
> > diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
> > index 6efe0410fb72..bda761ca0d26 100644
> > --- a/arch/x86/kernel/kvm.c
> > +++ b/arch/x86/kernel/kvm.c
> > @@ -35,6 +35,13 @@
> >  #include <asm/tlb.h>
> >  #include <asm/cpuidle_haltpoll.h>
> >  
> > +static bool mem_protected;
> > +
> > +bool kvm_mem_protected(void)
> > +{
> > +	return mem_protected;
> > +}
> > +
> 
> Honestly, I don't see a need for kvm_mem_protected(), just rename the
> bool if you need kvm_ prefix :-)

For !CONFIG_KVM_GUEST it would not be a variable. We may want to change it
to static branch or something in the future.

> >  static int kvmapf = 1;
> >  
> >  static int __init parse_no_kvmapf(char *arg)
> > @@ -727,6 +734,15 @@ static void __init kvm_init_platform(void)
> >  {
> >  	kvmclock_init();
> >  	x86_platform.apic_post_init = kvm_apic_init;
> > +
> > +	if (kvm_para_has_feature(KVM_FEATURE_MEM_PROTECTED)) {
> > +		if (kvm_hypercall0(KVM_HC_ENABLE_MEM_PROTECTED)) {
> > +			pr_err("Failed to enable KVM memory protection\n");
> > +			return;
> > +		}
> > +
> > +		mem_protected = true;
> > +	}
> >  }
> 
> Personally, I'd prefer to do this via setting a bit in a KVM-specific
> MSR instead. The benefit is that the guest doesn't need to remember if
> it enabled the feature or not, it can always read the config msr. May
> come handy for e.g. kexec/kdump.

I think we would need to remember it anyway. Accessing MSR is somewhat
expensive. But, okay, I can rework it MSR if needed.

Note, that we can avoid the enabling algother, if we modify BIOS to deal
with private/shared memory. Currently BIOS get system crash if we enable
the feature from time zero.

> >  const __initconst struct hypervisor_x86 x86_hyper_kvm = {
> > diff --git a/include/uapi/linux/kvm_para.h b/include/uapi/linux/kvm_para.h
> > index 8b86609849b9..1a216f32e572 100644
> > --- a/include/uapi/linux/kvm_para.h
> > +++ b/include/uapi/linux/kvm_para.h
> > @@ -27,8 +27,9 @@
> >  #define KVM_HC_MIPS_EXIT_VM		7
> >  #define KVM_HC_MIPS_CONSOLE_OUTPUT	8
> >  #define KVM_HC_CLOCK_PAIRING		9
> > -#define KVM_HC_SEND_IPI		10
> > +#define KVM_HC_SEND_IPI			10
> 
> Same spurrious change detected.

The same justification :)

> >  #define KVM_HC_SCHED_YIELD		11
> > +#define KVM_HC_ENABLE_MEM_PROTECTED	12
> >  
> >  /*
> >   * hypercalls use architecture specific
> 
> -- 
> Vitaly
> 
>
Sean Christopherson May 27, 2020, 5:03 a.m. UTC | #3
On Mon, May 25, 2020 at 06:15:25PM +0300, Kirill A. Shutemov wrote:
> On Mon, May 25, 2020 at 04:58:51PM +0200, Vitaly Kuznetsov wrote:
> > > @@ -727,6 +734,15 @@ static void __init kvm_init_platform(void)
> > >  {
> > >  	kvmclock_init();
> > >  	x86_platform.apic_post_init = kvm_apic_init;
> > > +
> > > +	if (kvm_para_has_feature(KVM_FEATURE_MEM_PROTECTED)) {
> > > +		if (kvm_hypercall0(KVM_HC_ENABLE_MEM_PROTECTED)) {
> > > +			pr_err("Failed to enable KVM memory protection\n");
> > > +			return;
> > > +		}
> > > +
> > > +		mem_protected = true;
> > > +	}
> > >  }
> > 
> > Personally, I'd prefer to do this via setting a bit in a KVM-specific
> > MSR instead. The benefit is that the guest doesn't need to remember if
> > it enabled the feature or not, it can always read the config msr. May
> > come handy for e.g. kexec/kdump.
> 
> I think we would need to remember it anyway. Accessing MSR is somewhat
> expensive. But, okay, I can rework it MSR if needed.

I think Vitaly is talking about the case where the kernel can't easily get
at its cached state, e.g. after booting into a new kernel.  The kernel would
still have an X86_FEATURE bit or whatever, providing a virtual MSR would be
purely for rare slow paths.

That being said, a hypercall plus CPUID bit might be better, e.g. that'd
allow the guest to query the state without risking a #GP.

> Note, that we can avoid the enabling algother, if we modify BIOS to deal
> with private/shared memory. Currently BIOS get system crash if we enable
> the feature from time zero.

Which would mesh better with a CPUID feature bit.
Vitaly Kuznetsov May 27, 2020, 8:39 a.m. UTC | #4
Sean Christopherson <sean.j.christopherson@intel.com> writes:

> On Mon, May 25, 2020 at 06:15:25PM +0300, Kirill A. Shutemov wrote:
>> On Mon, May 25, 2020 at 04:58:51PM +0200, Vitaly Kuznetsov wrote:
>> > > @@ -727,6 +734,15 @@ static void __init kvm_init_platform(void)
>> > >  {
>> > >  	kvmclock_init();
>> > >  	x86_platform.apic_post_init = kvm_apic_init;
>> > > +
>> > > +	if (kvm_para_has_feature(KVM_FEATURE_MEM_PROTECTED)) {
>> > > +		if (kvm_hypercall0(KVM_HC_ENABLE_MEM_PROTECTED)) {
>> > > +			pr_err("Failed to enable KVM memory protection\n");
>> > > +			return;
>> > > +		}
>> > > +
>> > > +		mem_protected = true;
>> > > +	}
>> > >  }
>> > 
>> > Personally, I'd prefer to do this via setting a bit in a KVM-specific
>> > MSR instead. The benefit is that the guest doesn't need to remember if
>> > it enabled the feature or not, it can always read the config msr. May
>> > come handy for e.g. kexec/kdump.
>> 
>> I think we would need to remember it anyway. Accessing MSR is somewhat
>> expensive. But, okay, I can rework it MSR if needed.
>
> I think Vitaly is talking about the case where the kernel can't easily get
> at its cached state, e.g. after booting into a new kernel.  The kernel would
> still have an X86_FEATURE bit or whatever, providing a virtual MSR would be
> purely for rare slow paths.
>
> That being said, a hypercall plus CPUID bit might be better, e.g. that'd
> allow the guest to query the state without risking a #GP.

We have rdmsr_safe() for that! :-) MSR (and hypercall to that matter)
should have an associated CPUID feature bit of course.

Yes, hypercall + CPUID would do but normally we treat CPUID data as
static and in this case we'll make it a dynamically flipping
bit. Especially if we introduce 'KVM_HC_DISABLE_MEM_PROTECTED' later.

>
>> Note, that we can avoid the enabling algother, if we modify BIOS to deal
>> with private/shared memory. Currently BIOS get system crash if we enable
>> the feature from time zero.
>
> Which would mesh better with a CPUID feature bit.
>

And maybe even help us to resolve 'reboot' problem.
Sean Christopherson May 27, 2020, 8:52 a.m. UTC | #5
On Wed, May 27, 2020 at 10:39:33AM +0200, Vitaly Kuznetsov wrote:
> Sean Christopherson <sean.j.christopherson@intel.com> writes:
> 
> > On Mon, May 25, 2020 at 06:15:25PM +0300, Kirill A. Shutemov wrote:
> >> On Mon, May 25, 2020 at 04:58:51PM +0200, Vitaly Kuznetsov wrote:
> >> > > @@ -727,6 +734,15 @@ static void __init kvm_init_platform(void)
> >> > >  {
> >> > >  	kvmclock_init();
> >> > >  	x86_platform.apic_post_init = kvm_apic_init;
> >> > > +
> >> > > +	if (kvm_para_has_feature(KVM_FEATURE_MEM_PROTECTED)) {
> >> > > +		if (kvm_hypercall0(KVM_HC_ENABLE_MEM_PROTECTED)) {
> >> > > +			pr_err("Failed to enable KVM memory protection\n");
> >> > > +			return;
> >> > > +		}
> >> > > +
> >> > > +		mem_protected = true;
> >> > > +	}
> >> > >  }
> >> > 
> >> > Personally, I'd prefer to do this via setting a bit in a KVM-specific
> >> > MSR instead. The benefit is that the guest doesn't need to remember if
> >> > it enabled the feature or not, it can always read the config msr. May
> >> > come handy for e.g. kexec/kdump.
> >> 
> >> I think we would need to remember it anyway. Accessing MSR is somewhat
> >> expensive. But, okay, I can rework it MSR if needed.
> >
> > I think Vitaly is talking about the case where the kernel can't easily get
> > at its cached state, e.g. after booting into a new kernel.  The kernel would
> > still have an X86_FEATURE bit or whatever, providing a virtual MSR would be
> > purely for rare slow paths.
> >
> > That being said, a hypercall plus CPUID bit might be better, e.g. that'd
> > allow the guest to query the state without risking a #GP.
> 
> We have rdmsr_safe() for that! :-) MSR (and hypercall to that matter)
> should have an associated CPUID feature bit of course.

rdmsr_safe() won't fly in early boot, e.g. verify_cpu.  It probably doesn't
matter for late enabling, but it might save some headache if there's ever a
handoff from vBIOS.

> Yes, hypercall + CPUID would do but normally we treat CPUID data as
> static and in this case we'll make it a dynamically flipping

There are multiple examples of dynamic CPUID, e.g. MWAIT and OSPKE.

> bit. Especially if we introduce 'KVM_HC_DISABLE_MEM_PROTECTED' later.
> 
> >
> >> Note, that we can avoid the enabling algother, if we modify BIOS to deal
> >> with private/shared memory. Currently BIOS get system crash if we enable
> >> the feature from time zero.
> >
> > Which would mesh better with a CPUID feature bit.
> >
> 
> And maybe even help us to resolve 'reboot' problem.
> 
> -- 
> Vitaly
>
Huang, Kai June 3, 2020, 2:09 a.m. UTC | #6
On Wed, 2020-05-27 at 10:39 +0200, Vitaly Kuznetsov wrote:
> Sean Christopherson <sean.j.christopherson@intel.com> writes:
> 
> > On Mon, May 25, 2020 at 06:15:25PM +0300, Kirill A. Shutemov wrote:
> > > On Mon, May 25, 2020 at 04:58:51PM +0200, Vitaly Kuznetsov wrote:
> > > > > @@ -727,6 +734,15 @@ static void __init kvm_init_platform(void)
> > > > >  {
> > > > >  	kvmclock_init();
> > > > >  	x86_platform.apic_post_init = kvm_apic_init;
> > > > > +
> > > > > +	if (kvm_para_has_feature(KVM_FEATURE_MEM_PROTECTED)) {
> > > > > +		if (kvm_hypercall0(KVM_HC_ENABLE_MEM_PROTECTED)) {
> > > > > +			pr_err("Failed to enable KVM memory
> > > > > protection\n");
> > > > > +			return;
> > > > > +		}
> > > > > +
> > > > > +		mem_protected = true;
> > > > > +	}
> > > > >  }
> > > > 
> > > > Personally, I'd prefer to do this via setting a bit in a KVM-specific
> > > > MSR instead. The benefit is that the guest doesn't need to remember if
> > > > it enabled the feature or not, it can always read the config msr. May
> > > > come handy for e.g. kexec/kdump.
> > > 
> > > I think we would need to remember it anyway. Accessing MSR is somewhat
> > > expensive. But, okay, I can rework it MSR if needed.
> > 
> > I think Vitaly is talking about the case where the kernel can't easily get
> > at its cached state, e.g. after booting into a new kernel.  The kernel would
> > still have an X86_FEATURE bit or whatever, providing a virtual MSR would be
> > purely for rare slow paths.
> > 
> > That being said, a hypercall plus CPUID bit might be better, e.g. that'd
> > allow the guest to query the state without risking a #GP.
> 
> We have rdmsr_safe() for that! :-) MSR (and hypercall to that matter)
> should have an associated CPUID feature bit of course.
> 
> Yes, hypercall + CPUID would do but normally we treat CPUID data as
> static and in this case we'll make it a dynamically flipping
> bit. Especially if we introduce 'KVM_HC_DISABLE_MEM_PROTECTED' later.

Not sure why is KVM_HC_DISABLE_MEM_PROTECTED needed?

> 
> > > Note, that we can avoid the enabling algother, if we modify BIOS to deal
> > > with private/shared memory. Currently BIOS get system crash if we enable
> > > the feature from time zero.
> > 
> > Which would mesh better with a CPUID feature bit.
> > 
> 
> And maybe even help us to resolve 'reboot' problem.

IMO we can ask Qemu to call hypercall to 'enable' memory protection when
creating VM, and guest kernel *queries* whether it is protected via CPUID
feature bit.
Vitaly Kuznetsov June 3, 2020, 11:14 a.m. UTC | #7
"Huang, Kai" <kai.huang@intel.com> writes:

> On Wed, 2020-05-27 at 10:39 +0200, Vitaly Kuznetsov wrote:
>> Sean Christopherson <sean.j.christopherson@intel.com> writes:
>> 
>> > On Mon, May 25, 2020 at 06:15:25PM +0300, Kirill A. Shutemov wrote:
>> > > On Mon, May 25, 2020 at 04:58:51PM +0200, Vitaly Kuznetsov wrote:
>> > > > > @@ -727,6 +734,15 @@ static void __init kvm_init_platform(void)
>> > > > >  {
>> > > > >  	kvmclock_init();
>> > > > >  	x86_platform.apic_post_init = kvm_apic_init;
>> > > > > +
>> > > > > +	if (kvm_para_has_feature(KVM_FEATURE_MEM_PROTECTED)) {
>> > > > > +		if (kvm_hypercall0(KVM_HC_ENABLE_MEM_PROTECTED)) {
>> > > > > +			pr_err("Failed to enable KVM memory
>> > > > > protection\n");
>> > > > > +			return;
>> > > > > +		}
>> > > > > +
>> > > > > +		mem_protected = true;
>> > > > > +	}
>> > > > >  }
>> > > > 
>> > > > Personally, I'd prefer to do this via setting a bit in a KVM-specific
>> > > > MSR instead. The benefit is that the guest doesn't need to remember if
>> > > > it enabled the feature or not, it can always read the config msr. May
>> > > > come handy for e.g. kexec/kdump.
>> > > 
>> > > I think we would need to remember it anyway. Accessing MSR is somewhat
>> > > expensive. But, okay, I can rework it MSR if needed.
>> > 
>> > I think Vitaly is talking about the case where the kernel can't easily get
>> > at its cached state, e.g. after booting into a new kernel.  The kernel would
>> > still have an X86_FEATURE bit or whatever, providing a virtual MSR would be
>> > purely for rare slow paths.
>> > 
>> > That being said, a hypercall plus CPUID bit might be better, e.g. that'd
>> > allow the guest to query the state without risking a #GP.
>> 
>> We have rdmsr_safe() for that! :-) MSR (and hypercall to that matter)
>> should have an associated CPUID feature bit of course.
>> 
>> Yes, hypercall + CPUID would do but normally we treat CPUID data as
>> static and in this case we'll make it a dynamically flipping
>> bit. Especially if we introduce 'KVM_HC_DISABLE_MEM_PROTECTED' later.
>
> Not sure why is KVM_HC_DISABLE_MEM_PROTECTED needed?
>

I didn't put much thought in it but we may need it to support 'kexec'
case when no reboot is performed but we either need to pass  the data
about which regions are protected from old kernel to the new one or
'unprotect exerything'.

Patch
diff mbox series

diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
index 9b4df6eaa11a..3ce84fc07144 100644
--- a/arch/x86/include/asm/kvm_para.h
+++ b/arch/x86/include/asm/kvm_para.h
@@ -10,11 +10,16 @@  extern void kvmclock_init(void);
 
 #ifdef CONFIG_KVM_GUEST
 bool kvm_check_and_clear_guest_paused(void);
+bool kvm_mem_protected(void);
 #else
 static inline bool kvm_check_and_clear_guest_paused(void)
 {
 	return false;
 }
+static inline bool kvm_mem_protected(void)
+{
+	return false;
+}
 #endif /* CONFIG_KVM_GUEST */
 
 #define KVM_HYPERCALL \
diff --git a/arch/x86/include/uapi/asm/kvm_para.h b/arch/x86/include/uapi/asm/kvm_para.h
index 2a8e0b6b9805..c3b499acc98f 100644
--- a/arch/x86/include/uapi/asm/kvm_para.h
+++ b/arch/x86/include/uapi/asm/kvm_para.h
@@ -28,9 +28,10 @@ 
 #define KVM_FEATURE_PV_UNHALT		7
 #define KVM_FEATURE_PV_TLB_FLUSH	9
 #define KVM_FEATURE_ASYNC_PF_VMEXIT	10
-#define KVM_FEATURE_PV_SEND_IPI	11
+#define KVM_FEATURE_PV_SEND_IPI		11
 #define KVM_FEATURE_POLL_CONTROL	12
 #define KVM_FEATURE_PV_SCHED_YIELD	13
+#define KVM_FEATURE_MEM_PROTECTED	14
 
 #define KVM_HINTS_REALTIME      0
 
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 6efe0410fb72..bda761ca0d26 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -35,6 +35,13 @@ 
 #include <asm/tlb.h>
 #include <asm/cpuidle_haltpoll.h>
 
+static bool mem_protected;
+
+bool kvm_mem_protected(void)
+{
+	return mem_protected;
+}
+
 static int kvmapf = 1;
 
 static int __init parse_no_kvmapf(char *arg)
@@ -727,6 +734,15 @@  static void __init kvm_init_platform(void)
 {
 	kvmclock_init();
 	x86_platform.apic_post_init = kvm_apic_init;
+
+	if (kvm_para_has_feature(KVM_FEATURE_MEM_PROTECTED)) {
+		if (kvm_hypercall0(KVM_HC_ENABLE_MEM_PROTECTED)) {
+			pr_err("Failed to enable KVM memory protection\n");
+			return;
+		}
+
+		mem_protected = true;
+	}
 }
 
 const __initconst struct hypervisor_x86 x86_hyper_kvm = {
diff --git a/include/uapi/linux/kvm_para.h b/include/uapi/linux/kvm_para.h
index 8b86609849b9..1a216f32e572 100644
--- a/include/uapi/linux/kvm_para.h
+++ b/include/uapi/linux/kvm_para.h
@@ -27,8 +27,9 @@ 
 #define KVM_HC_MIPS_EXIT_VM		7
 #define KVM_HC_MIPS_CONSOLE_OUTPUT	8
 #define KVM_HC_CLOCK_PAIRING		9
-#define KVM_HC_SEND_IPI		10
+#define KVM_HC_SEND_IPI			10
 #define KVM_HC_SCHED_YIELD		11
+#define KVM_HC_ENABLE_MEM_PROTECTED	12
 
 /*
  * hypercalls use architecture specific