diff mbox series

[RFC,03/12] kvm/vmx: Introduce the new tertiary processor-based VM-execution controls

Message ID 1611565580-47718-4-git-send-email-robert.hu@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series KVM: Support Intel KeyLocker | expand

Commit Message

Robert Hoo Jan. 25, 2021, 9:06 a.m. UTC
The Tertiary Exec Control field is enabled by Primary Exec Control field's
bit 17. And the Tertiary-Exec-Control-Field.bit[0] in turn controls the
'LOADIWKEY' VM-exit. Its companion VMX CTRL MSR is IA32_VMX_PROCBASED_CTLS3
(0x492). Please be noted that they're 64 bit, different from previous
control fields.

Signed-off-by: Robert Hoo <robert.hu@linux.intel.com>
---
 arch/x86/include/asm/msr-index.h   |  1 +
 arch/x86/include/asm/vmx.h         |  3 +++
 arch/x86/include/asm/vmxfeatures.h |  3 ++-
 arch/x86/kernel/cpu/feat_ctl.c     |  9 +++++++++
 arch/x86/kvm/vmx/capabilities.h    |  7 +++++++
 arch/x86/kvm/vmx/vmcs.h            |  1 +
 arch/x86/kvm/vmx/vmx.c             | 23 ++++++++++++++++++++---
 arch/x86/kvm/vmx/vmx.h             |  8 ++++++++
 8 files changed, 51 insertions(+), 4 deletions(-)

Comments

Robert Hoo Jan. 26, 2021, 9:27 a.m. UTC | #1
On Mon, 2021-01-25 at 10:41 +0100, Vitaly Kuznetsov wrote:
> Robert Hoo <robert.hu@linux.intel.com> writes:
> 
[...]
> >  
> >  /*
> > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> > index 47b8357..12a926e 100644
> > --- a/arch/x86/kvm/vmx/vmx.c
> > +++ b/arch/x86/kvm/vmx/vmx.c
> > @@ -2376,6 +2376,7 @@ static __init int setup_vmcs_config(struct
> > vmcs_config *vmcs_conf,
> >  	u32 _pin_based_exec_control = 0;
> >  	u32 _cpu_based_exec_control = 0;
> >  	u32 _cpu_based_2nd_exec_control = 0;
> > +	u64 _cpu_based_3rd_exec_control = 0;
> >  	u32 _vmexit_control = 0;
> >  	u32 _vmentry_control = 0;
> >  
> > @@ -2397,7 +2398,8 @@ static __init int setup_vmcs_config(struct
> > vmcs_config *vmcs_conf,
> >  
> >  	opt = CPU_BASED_TPR_SHADOW |
> >  	      CPU_BASED_USE_MSR_BITMAPS |
> > -	      CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
> > +	      CPU_BASED_ACTIVATE_SECONDARY_CONTROLS |
> > +	      CPU_BASED_ACTIVATE_TERTIARY_CONTROLS;
> >  	if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,
> >  				&_cpu_based_exec_control) < 0)
> >  		return -EIO;
> > @@ -2557,6 +2559,7 @@ static __init int setup_vmcs_config(struct
> > vmcs_config *vmcs_conf,
> >  	vmcs_conf->pin_based_exec_ctrl = _pin_based_exec_control;
> >  	vmcs_conf->cpu_based_exec_ctrl = _cpu_based_exec_control;
> >  	vmcs_conf->cpu_based_2nd_exec_ctrl =
> > _cpu_based_2nd_exec_control;
> > +	vmcs_conf->cpu_based_3rd_exec_ctrl =
> > _cpu_based_3rd_exec_control;
> >  	vmcs_conf->vmexit_ctrl         = _vmexit_control;
> >  	vmcs_conf->vmentry_ctrl        = _vmentry_control;
> >  
> > @@ -4200,6 +4203,12 @@ u32 vmx_exec_control(struct vcpu_vmx *vmx)
> >  #define vmx_adjust_sec_exec_exiting(vmx, exec_control, lname,
> > uname) \
> >  	vmx_adjust_sec_exec_control(vmx, exec_control, lname, uname,
> > uname##_EXITING, true)
> >  
> > +static u64 vmx_tertiary_exec_control(struct vcpu_vmx *vmx)
> > +{
> > +	/* Though currently, no special adjustment. There might be in
> > the future*/
> > +	return vmcs_config.cpu_based_3rd_exec_ctrl;
> > +}
> > +
> >  static void vmx_compute_secondary_exec_control(struct vcpu_vmx
> > *vmx)
> >  {
> >  	struct kvm_vcpu *vcpu = &vmx->vcpu;
> > @@ -4310,6 +4319,9 @@ static void init_vmcs(struct vcpu_vmx *vmx)
> >  		secondary_exec_controls_set(vmx, vmx-
> > >secondary_exec_control);
> >  	}
> >  
> > +	if (cpu_has_tertiary_exec_ctrls())
> > +		tertiary_exec_controls_set(vmx,
> > vmx_tertiary_exec_control(vmx));
> > +
> >  	if (kvm_vcpu_apicv_active(&vmx->vcpu)) {
> >  		vmcs_write64(EOI_EXIT_BITMAP0, 0);
> >  		vmcs_write64(EOI_EXIT_BITMAP1, 0);
> > @@ -5778,6 +5790,7 @@ void dump_vmcs(void)
> >  {
> >  	u32 vmentry_ctl, vmexit_ctl;
> >  	u32 cpu_based_exec_ctrl, pin_based_exec_ctrl,
> > secondary_exec_control;
> > +	u64 tertiary_exec_control = 0;
> >  	unsigned long cr4;
> >  	u64 efer;
> >  
> > @@ -5796,6 +5809,9 @@ void dump_vmcs(void)
> >  	if (cpu_has_secondary_exec_ctrls())
> >  		secondary_exec_control =
> > vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
> >  
> > +	if (cpu_has_tertiary_exec_ctrls())
> > +		tertiary_exec_control =
> > vmcs_read64(TERTIARY_VM_EXEC_CONTROL);
> 
> We'll have to do something about Enlightened VMCS I believe. In
> theory,
> when eVMCS is in use, 'CPU_BASED_ACTIVATE_TERTIARY_CONTROLS' should
> not
> be exposed, e.g. when KVM hosts a EVMCS enabled guest the control
> should
> be filtered out. Something like (completely untested):
> 
> diff --git a/arch/x86/kvm/vmx/evmcs.c b/arch/x86/kvm/vmx/evmcs.c
> index 41f24661af04..c44ff05f3235 100644
> --- a/arch/x86/kvm/vmx/evmcs.c
> +++ b/arch/x86/kvm/vmx/evmcs.c
> @@ -299,6 +299,7 @@ const unsigned int nr_evmcs_1_fields =
> ARRAY_SIZE(vmcs_field_to_evmcs_1);
>  
>  __init void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf)
>  {
> +       vmcs_conf->cpu_based_exec_ctrl &=
> ~EVMCS1_UNSUPPORTED_EXEC_CTRL;
>         vmcs_conf->pin_based_exec_ctrl &=
> ~EVMCS1_UNSUPPORTED_PINCTRL;
>         vmcs_conf->cpu_based_2nd_exec_ctrl &=
> ~EVMCS1_UNSUPPORTED_2NDEXEC;
>  
> diff --git a/arch/x86/kvm/vmx/evmcs.h b/arch/x86/kvm/vmx/evmcs.h
> index bd41d9462355..bf2c5e7a4a8f 100644
> --- a/arch/x86/kvm/vmx/evmcs.h
> +++ b/arch/x86/kvm/vmx/evmcs.h
> @@ -50,6 +50,7 @@ DECLARE_STATIC_KEY_FALSE(enable_evmcs);
>   */
>  #define EVMCS1_UNSUPPORTED_PINCTRL (PIN_BASED_POSTED_INTR | \
>                                     PIN_BASED_VMX_PREEMPTION_TIMER)
> +#define EVMCS1_UNSUPPORTED_EXEC_CTRL
> (CPU_BASED_ACTIVATE_TERTIARY_CONTROLS)
>  #define
> EVMCS1_UNSUPPORTED_2NDEXEC                                     \
>         (SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY
> |                         \
>          SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES
> |                      \
> 
> should do the job I think.

Agree, until L0 HyperV supports the new tertiary control, L1 KVM shall
not expose it to its guests. Thanks Vitaly pointing out, and with
detailed explanation.

BTW, when would enlightened VMCS support VMCS Tertiary Control and Key
Locker feature?
> 
> > +
> >  	pr_err("*** Guest State ***\n");
> >  	pr_err("CR0: actual=0x%016lx, shadow=0x%016lx,
> > gh_mask=%016lx\n",
> >  	       vmcs_readl(GUEST_CR0), vmcs_readl(CR0_READ_SHADOW),
> > @@ -5878,8 +5894,9 @@ void dump_vmcs(void)
> >  		       vmcs_read64(HOST_IA32_PERF_GLOBAL_CTRL));
> >  
> >  	pr_err("*** Control State ***\n");
> > -	pr_err("PinBased=%08x CPUBased=%08x SecondaryExec=%08x\n",
> > -	       pin_based_exec_ctrl, cpu_based_exec_ctrl,
> > secondary_exec_control);
> > +	pr_err("PinBased=0x%08x CPUBased=0x%08x SecondaryExec=0x%08x
> > TertiaryExec=0x%016llx\n",
> > +	       pin_based_exec_ctrl, cpu_based_exec_ctrl,
> > secondary_exec_control,
> > +	       tertiary_exec_control);
> >  	pr_err("EntryControls=%08x ExitControls=%08x\n", vmentry_ctl,
> > vmexit_ctl);
> >  	pr_err("ExceptionBitmap=%08x PFECmask=%08x PFECmatch=%08x\n",
> >  	       vmcs_read32(EXCEPTION_BITMAP),
> > diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
> > index f6f66e5..94f1c27 100644
> > --- a/arch/x86/kvm/vmx/vmx.h
> > +++ b/arch/x86/kvm/vmx/vmx.h
> > @@ -373,6 +373,14 @@ static inline u8 vmx_get_rvi(void)
> >  BUILD_CONTROLS_SHADOW(exec, CPU_BASED_VM_EXEC_CONTROL)
> >  BUILD_CONTROLS_SHADOW(secondary_exec, SECONDARY_VM_EXEC_CONTROL)
> >  
> > +static inline void tertiary_exec_controls_set(struct vcpu_vmx
> > *vmx, u64 val)
> > +{
> > +	if (vmx->loaded_vmcs->controls_shadow.tertiary_exec != val) {
> > +		vmcs_write64(TERTIARY_VM_EXEC_CONTROL, val);
> > +		vmx->loaded_vmcs->controls_shadow.tertiary_exec = val;
> > +	}
> > +}
> > +
> >  static inline void vmx_register_cache_reset(struct kvm_vcpu *vcpu)
> >  {
> >  	vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 <<
> > VCPU_REGS_RSP)
> 
>
Robert Hoo Feb. 3, 2021, 6:32 a.m. UTC | #2
On Mon, 2021-01-25 at 10:41 +0100, Vitaly Kuznetsov wrote:
> Robert Hoo <robert.hu@linux.intel.com> writes:
> We'll have to do something about Enlightened VMCS I believe. In
> theory,
> when eVMCS is in use, 'CPU_BASED_ACTIVATE_TERTIARY_CONTROLS' should
> not
> be exposed, e.g. when KVM hosts a EVMCS enabled guest the control
> should
> be filtered out. Something like (completely untested):
> 
> diff --git a/arch/x86/kvm/vmx/evmcs.c b/arch/x86/kvm/vmx/evmcs.c
> index 41f24661af04..c44ff05f3235 100644
> --- a/arch/x86/kvm/vmx/evmcs.c
> +++ b/arch/x86/kvm/vmx/evmcs.c
> @@ -299,6 +299,7 @@ const unsigned int nr_evmcs_1_fields =
> ARRAY_SIZE(vmcs_field_to_evmcs_1);
>  
>  __init void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf)
>  {
> +       vmcs_conf->cpu_based_exec_ctrl &=
> ~EVMCS1_UNSUPPORTED_EXEC_CTRL;
>         vmcs_conf->pin_based_exec_ctrl &=
> ~EVMCS1_UNSUPPORTED_PINCTRL;
>         vmcs_conf->cpu_based_2nd_exec_ctrl &=
> ~EVMCS1_UNSUPPORTED_2NDEXEC;
>  
> diff --git a/arch/x86/kvm/vmx/evmcs.h b/arch/x86/kvm/vmx/evmcs.h
> index bd41d9462355..bf2c5e7a4a8f 100644
> --- a/arch/x86/kvm/vmx/evmcs.h
> +++ b/arch/x86/kvm/vmx/evmcs.h
> @@ -50,6 +50,7 @@ DECLARE_STATIC_KEY_FALSE(enable_evmcs);
>   */
>  #define EVMCS1_UNSUPPORTED_PINCTRL (PIN_BASED_POSTED_INTR | \
>                                     PIN_BASED_VMX_PREEMPTION_TIMER)
> +#define EVMCS1_UNSUPPORTED_EXEC_CTRL
> (CPU_BASED_ACTIVATE_TERTIARY_CONTROLS)
>  #define
> EVMCS1_UNSUPPORTED_2NDEXEC                                     \
>         (SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY
> |                         \
>          SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES
> |                      \
> 
> should do the job I think.
> 
Hi Vitaly,

I'm going to incorporate above patch in my next version. Shall I have
it your signed-off-by?
[setup_vmcs_config: filter out tertiary control when using eVMCS]
signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Vitaly Kuznetsov Feb. 3, 2021, 8:45 a.m. UTC | #3
Robert Hoo <robert.hu@linux.intel.com> writes:

> On Mon, 2021-01-25 at 10:41 +0100, Vitaly Kuznetsov wrote:
>> Robert Hoo <robert.hu@linux.intel.com> writes:
>> We'll have to do something about Enlightened VMCS I believe. In
>> theory,
>> when eVMCS is in use, 'CPU_BASED_ACTIVATE_TERTIARY_CONTROLS' should
>> not
>> be exposed, e.g. when KVM hosts a EVMCS enabled guest the control
>> should
>> be filtered out. Something like (completely untested):
>> 
>> diff --git a/arch/x86/kvm/vmx/evmcs.c b/arch/x86/kvm/vmx/evmcs.c
>> index 41f24661af04..c44ff05f3235 100644
>> --- a/arch/x86/kvm/vmx/evmcs.c
>> +++ b/arch/x86/kvm/vmx/evmcs.c
>> @@ -299,6 +299,7 @@ const unsigned int nr_evmcs_1_fields =
>> ARRAY_SIZE(vmcs_field_to_evmcs_1);
>>  
>>  __init void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf)
>>  {
>> +       vmcs_conf->cpu_based_exec_ctrl &=
>> ~EVMCS1_UNSUPPORTED_EXEC_CTRL;
>>         vmcs_conf->pin_based_exec_ctrl &=
>> ~EVMCS1_UNSUPPORTED_PINCTRL;
>>         vmcs_conf->cpu_based_2nd_exec_ctrl &=
>> ~EVMCS1_UNSUPPORTED_2NDEXEC;
>>  
>> diff --git a/arch/x86/kvm/vmx/evmcs.h b/arch/x86/kvm/vmx/evmcs.h
>> index bd41d9462355..bf2c5e7a4a8f 100644
>> --- a/arch/x86/kvm/vmx/evmcs.h
>> +++ b/arch/x86/kvm/vmx/evmcs.h
>> @@ -50,6 +50,7 @@ DECLARE_STATIC_KEY_FALSE(enable_evmcs);
>>   */
>>  #define EVMCS1_UNSUPPORTED_PINCTRL (PIN_BASED_POSTED_INTR | \
>>                                     PIN_BASED_VMX_PREEMPTION_TIMER)
>> +#define EVMCS1_UNSUPPORTED_EXEC_CTRL
>> (CPU_BASED_ACTIVATE_TERTIARY_CONTROLS)
>>  #define
>> EVMCS1_UNSUPPORTED_2NDEXEC                                     \
>>         (SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY
>> |                         \
>>          SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES
>> |                      \
>> 
>> should do the job I think.
>> 
> Hi Vitaly,
>
> I'm going to incorporate above patch in my next version. Shall I have
> it your signed-off-by?
> [setup_vmcs_config: filter out tertiary control when using eVMCS]
> signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>

You can just incorporate it into your patch or, in case you want to have
it separate, feel free just add a 'Suggested-by: Vitaly Kuznetsov
<vkuznets@redhat.com>' tag.

Thanks!
Sean Christopherson April 5, 2021, 3:38 p.m. UTC | #4
On Mon, Jan 25, 2021, Robert Hoo wrote:
> diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
> index f6f66e5..94f1c27 100644
> --- a/arch/x86/kvm/vmx/vmx.h
> +++ b/arch/x86/kvm/vmx/vmx.h
> @@ -373,6 +373,14 @@ static inline u8 vmx_get_rvi(void)
>  BUILD_CONTROLS_SHADOW(exec, CPU_BASED_VM_EXEC_CONTROL)
>  BUILD_CONTROLS_SHADOW(secondary_exec, SECONDARY_VM_EXEC_CONTROL)
>  
> +static inline void tertiary_exec_controls_set(struct vcpu_vmx *vmx, u64 val)
> +{
> +	if (vmx->loaded_vmcs->controls_shadow.tertiary_exec != val) {
> +		vmcs_write64(TERTIARY_VM_EXEC_CONTROL, val);
> +		vmx->loaded_vmcs->controls_shadow.tertiary_exec = val;
> +	}
> +}

Add a "bits" param to the builder macros and use string concatenation, then the
tertiary controls can share those macros.

diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index 7886a08505cc..328039157535 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -398,25 +398,25 @@ static inline u8 vmx_get_rvi(void)
        return vmcs_read16(GUEST_INTR_STATUS) & 0xff;
 }

-#define BUILD_CONTROLS_SHADOW(lname, uname)                                \
-static inline void lname##_controls_set(struct vcpu_vmx *vmx, u32 val)     \
-{                                                                          \
-       if (vmx->loaded_vmcs->controls_shadow.lname != val) {               \
-               vmcs_write32(uname, val);                                   \
-               vmx->loaded_vmcs->controls_shadow.lname = val;              \
-       }                                                                   \
-}                                                                          \
-static inline u32 lname##_controls_get(struct vcpu_vmx *vmx)               \
-{                                                                          \
-       return vmx->loaded_vmcs->controls_shadow.lname;                     \
-}                                                                          \
-static inline void lname##_controls_setbit(struct vcpu_vmx *vmx, u32 val)   \
-{                                                                          \
-       lname##_controls_set(vmx, lname##_controls_get(vmx) | val);         \
-}                                                                          \
-static inline void lname##_controls_clearbit(struct vcpu_vmx *vmx, u32 val) \
-{                                                                          \
-       lname##_controls_set(vmx, lname##_controls_get(vmx) & ~val);        \
+#define BUILD_CONTROLS_SHADOW(lname, uname, bits)                              \
+static inline void lname##_controls_set(struct vcpu_vmx *vmx, u##bits val)     \
+{                                                                              \
+       if (vmx->loaded_vmcs->controls_shadow.lname != val) {                   \
+               vmcs_write##bits(uname, val);                                   \
+               vmx->loaded_vmcs->controls_shadow.lname = val;                  \
+       }                                                                       \
+}                                                                              \
+static inline u##bits lname##_controls_get(struct vcpu_vmx *vmx)               \
+{                                                                              \
+       return vmx->loaded_vmcs->controls_shadow.lname;                         \
+}                                                                              \
+static inline void lname##_controls_setbit(struct vcpu_vmx *vmx, u##bits val)  \
+{                                                                              \
+       lname##_controls_set(vmx, lname##_controls_get(vmx) | val);             \
+}                                                                              \
+static inline void lname##_controls_clearbit(struct vcpu_vmx *vmx, u##bits val)        \
+{                                                                              \
+       lname##_controls_set(vmx, lname##_controls_get(vmx) & ~val);            \
 }
 BUILD_CONTROLS_SHADOW(vm_entry, VM_ENTRY_CONTROLS)
 BUILD_CONTROLS_SHADOW(vm_exit, VM_EXIT_CONTROLS)

> +
>  static inline void vmx_register_cache_reset(struct kvm_vcpu *vcpu)
>  {
>  	vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP)
> -- 
> 1.8.3.1
>
Robert Hoo April 6, 2021, 3:37 a.m. UTC | #5
On Mon, 2021-04-05 at 15:38 +0000, Sean Christopherson wrote:
> On Mon, Jan 25, 2021, Robert Hoo wrote:
> > diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
> > index f6f66e5..94f1c27 100644
> > --- a/arch/x86/kvm/vmx/vmx.h
> > +++ b/arch/x86/kvm/vmx/vmx.h
> > @@ -373,6 +373,14 @@ static inline u8 vmx_get_rvi(void)
> >  BUILD_CONTROLS_SHADOW(exec, CPU_BASED_VM_EXEC_CONTROL)
> >  BUILD_CONTROLS_SHADOW(secondary_exec, SECONDARY_VM_EXEC_CONTROL)
> >  
> > +static inline void tertiary_exec_controls_set(struct vcpu_vmx
> > *vmx, u64 val)
> > +{
> > +	if (vmx->loaded_vmcs->controls_shadow.tertiary_exec != val) {
> > +		vmcs_write64(TERTIARY_VM_EXEC_CONTROL, val);
> > +		vmx->loaded_vmcs->controls_shadow.tertiary_exec = val;
> > +	}
> > +}
> 
> Add a "bits" param to the builder macros and use string
> concatenation, then the
> tertiary controls can share those macros.
> 
> diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
> index 7886a08505cc..328039157535 100644
> --- a/arch/x86/kvm/vmx/vmx.h
> +++ b/arch/x86/kvm/vmx/vmx.h
> @@ -398,25 +398,25 @@ static inline u8 vmx_get_rvi(void)
>         return vmcs_read16(GUEST_INTR_STATUS) & 0xff;
>  }
> 
> -#define BUILD_CONTROLS_SHADOW(lname,
> uname)                                \
> -static inline void lname##_controls_set(struct vcpu_vmx *vmx, u32
> val)     \
> -{                                                                   
>        \
> -       if (vmx->loaded_vmcs->controls_shadow.lname != val)
> {               \
> -               vmcs_write32(uname,
> val);                                   \
> -               vmx->loaded_vmcs->controls_shadow.lname =
> val;              \
> -       }                                                            
>        \
> -}                                                                   
>        \
> -static inline u32 lname##_controls_get(struct vcpu_vmx
> *vmx)               \
> -{                                                                   
>        \
> -       return vmx->loaded_vmcs-
> >controls_shadow.lname;                     \
> -}                                                                   
>        \
> -static inline void lname##_controls_setbit(struct vcpu_vmx *vmx, u32
> val)   \
> -{                                                                   
>        \
> -       lname##_controls_set(vmx, lname##_controls_get(vmx) |
> val);         \
> -}                                                                   
>        \
> -static inline void lname##_controls_clearbit(struct vcpu_vmx *vmx,
> u32 val) \
> -{                                                                   
>        \
> -       lname##_controls_set(vmx, lname##_controls_get(vmx) &
> ~val);        \
> +#define BUILD_CONTROLS_SHADOW(lname, uname,
> bits)                              \
> +static inline void lname##_controls_set(struct vcpu_vmx *vmx,
> u##bits val)     \
> +{                                                                   
>            \
> +       if (vmx->loaded_vmcs->controls_shadow.lname != val)
> {                   \
> +               vmcs_write##bits(uname,
> val);                                   \
> +               vmx->loaded_vmcs->controls_shadow.lname =
> val;                  \
> +       }                                                            
>            \
> +}                                                                   
>            \
> +static inline u##bits lname##_controls_get(struct vcpu_vmx
> *vmx)               \
> +{                                                                   
>            \
> +       return vmx->loaded_vmcs-
> >controls_shadow.lname;                         \
> +}                                                                   
>            \
> +static inline void lname##_controls_setbit(struct vcpu_vmx *vmx,
> u##bits val)  \
> +{                                                                   
>            \
> +       lname##_controls_set(vmx, lname##_controls_get(vmx) |
> val);             \
> +}                                                                   
>            \
> +static inline void lname##_controls_clearbit(struct vcpu_vmx *vmx,
> u##bits val)        \
> +{                                                                   
>            \
> +       lname##_controls_set(vmx, lname##_controls_get(vmx) &
> ~val);            \
>  }
>  BUILD_CONTROLS_SHADOW(vm_entry, VM_ENTRY_CONTROLS)
>  BUILD_CONTROLS_SHADOW(vm_exit, VM_EXIT_CONTROLS)
> 
Nice. I like this. Thanks Sean.

Shall I separated this hunk a patch and have your "Signed-off-by:"?

> > +
> >  static inline void vmx_register_cache_reset(struct kvm_vcpu *vcpu)
> >  {
> >  	vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 <<
> > VCPU_REGS_RSP)
> > -- 
> > 1.8.3.1
> >
diff mbox series

Patch

diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index c0b9157..3bca658 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -902,6 +902,7 @@ 
 #define MSR_IA32_VMX_TRUE_EXIT_CTLS      0x0000048f
 #define MSR_IA32_VMX_TRUE_ENTRY_CTLS     0x00000490
 #define MSR_IA32_VMX_VMFUNC             0x00000491
+#define MSR_IA32_VMX_PROCBASED_CTLS3    0x00000492
 
 /* VMX_BASIC bits and bitmasks */
 #define VMX_BASIC_VMCS_SIZE_SHIFT	32
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index f8ba528..1517692 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -31,6 +31,7 @@ 
 #define CPU_BASED_RDTSC_EXITING                 VMCS_CONTROL_BIT(RDTSC_EXITING)
 #define CPU_BASED_CR3_LOAD_EXITING		VMCS_CONTROL_BIT(CR3_LOAD_EXITING)
 #define CPU_BASED_CR3_STORE_EXITING		VMCS_CONTROL_BIT(CR3_STORE_EXITING)
+#define CPU_BASED_ACTIVATE_TERTIARY_CONTROLS    VMCS_CONTROL_BIT(TER_CONTROLS)
 #define CPU_BASED_CR8_LOAD_EXITING              VMCS_CONTROL_BIT(CR8_LOAD_EXITING)
 #define CPU_BASED_CR8_STORE_EXITING             VMCS_CONTROL_BIT(CR8_STORE_EXITING)
 #define CPU_BASED_TPR_SHADOW                    VMCS_CONTROL_BIT(VIRTUAL_TPR)
@@ -219,6 +220,8 @@  enum vmcs_field {
 	ENCLS_EXITING_BITMAP_HIGH	= 0x0000202F,
 	TSC_MULTIPLIER                  = 0x00002032,
 	TSC_MULTIPLIER_HIGH             = 0x00002033,
+	TERTIARY_VM_EXEC_CONTROL        = 0x00002034,
+	TERTIARY_VM_EXEC_CONTROL_HIGH   = 0x00002035,
 	GUEST_PHYSICAL_ADDRESS          = 0x00002400,
 	GUEST_PHYSICAL_ADDRESS_HIGH     = 0x00002401,
 	VMCS_LINK_POINTER               = 0x00002800,
diff --git a/arch/x86/include/asm/vmxfeatures.h b/arch/x86/include/asm/vmxfeatures.h
index 9915990..75a15c2 100644
--- a/arch/x86/include/asm/vmxfeatures.h
+++ b/arch/x86/include/asm/vmxfeatures.h
@@ -5,7 +5,7 @@ 
 /*
  * Defines VMX CPU feature bits
  */
-#define NVMXINTS			3 /* N 32-bit words worth of info */
+#define NVMXINTS			5 /* N 32-bit words worth of info */
 
 /*
  * Note: If the comment begins with a quoted string, that string is used
@@ -43,6 +43,7 @@ 
 #define VMX_FEATURE_RDTSC_EXITING	( 1*32+ 12) /* "" VM-Exit on RDTSC */
 #define VMX_FEATURE_CR3_LOAD_EXITING	( 1*32+ 15) /* "" VM-Exit on writes to CR3 */
 #define VMX_FEATURE_CR3_STORE_EXITING	( 1*32+ 16) /* "" VM-Exit on reads from CR3 */
+#define VMX_FEATURE_TER_CONTROLS        (1*32 + 17) /* "" Enable Tertiary VM-Execution Controls */
 #define VMX_FEATURE_CR8_LOAD_EXITING	( 1*32+ 19) /* "" VM-Exit on writes to CR8 */
 #define VMX_FEATURE_CR8_STORE_EXITING	( 1*32+ 20) /* "" VM-Exit on reads from CR8 */
 #define VMX_FEATURE_VIRTUAL_TPR		( 1*32+ 21) /* "vtpr" TPR virtualization, a.k.a. TPR shadow */
diff --git a/arch/x86/kernel/cpu/feat_ctl.c b/arch/x86/kernel/cpu/feat_ctl.c
index 29a3bed..e7bf637 100644
--- a/arch/x86/kernel/cpu/feat_ctl.c
+++ b/arch/x86/kernel/cpu/feat_ctl.c
@@ -15,6 +15,8 @@  enum vmx_feature_leafs {
 	MISC_FEATURES = 0,
 	PRIMARY_CTLS,
 	SECONDARY_CTLS,
+	TERTIARY_CTLS_LOW,
+	TERTIARY_CTLS_HIGH,
 	NR_VMX_FEATURE_WORDS,
 };
 
@@ -42,6 +44,13 @@  static void init_vmx_capabilities(struct cpuinfo_x86 *c)
 	rdmsr_safe(MSR_IA32_VMX_PROCBASED_CTLS2, &ign, &supported);
 	c->vmx_capability[SECONDARY_CTLS] = supported;
 
+	/*
+	 * For tertiary execution controls MSR, it's actually a 64bit allowed-1.
+	 */
+	rdmsr_safe(MSR_IA32_VMX_PROCBASED_CTLS3, &ign, &supported);
+	c->vmx_capability[TERTIARY_CTLS_LOW] = ign;
+	c->vmx_capability[TERTIARY_CTLS_HIGH] = supported;
+
 	rdmsr(MSR_IA32_VMX_PINBASED_CTLS, ign, supported);
 	rdmsr_safe(MSR_IA32_VMX_VMFUNC, &ign, &funcs);
 
diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilities.h
index 3a18614..d8bbde4 100644
--- a/arch/x86/kvm/vmx/capabilities.h
+++ b/arch/x86/kvm/vmx/capabilities.h
@@ -57,6 +57,7 @@  struct vmcs_config {
 	u32 pin_based_exec_ctrl;
 	u32 cpu_based_exec_ctrl;
 	u32 cpu_based_2nd_exec_ctrl;
+	u64 cpu_based_3rd_exec_ctrl;
 	u32 vmexit_ctrl;
 	u32 vmentry_ctrl;
 	struct nested_vmx_msrs nested;
@@ -130,6 +131,12 @@  static inline bool cpu_has_secondary_exec_ctrls(void)
 		CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
 }
 
+static inline bool cpu_has_tertiary_exec_ctrls(void)
+{
+	return vmcs_config.cpu_based_exec_ctrl &
+		CPU_BASED_ACTIVATE_TERTIARY_CONTROLS;
+}
+
 static inline bool cpu_has_vmx_virtualize_apic_accesses(void)
 {
 	return vmcs_config.cpu_based_2nd_exec_ctrl &
diff --git a/arch/x86/kvm/vmx/vmcs.h b/arch/x86/kvm/vmx/vmcs.h
index 1472c6c..343c329 100644
--- a/arch/x86/kvm/vmx/vmcs.h
+++ b/arch/x86/kvm/vmx/vmcs.h
@@ -48,6 +48,7 @@  struct vmcs_controls_shadow {
 	u32 pin;
 	u32 exec;
 	u32 secondary_exec;
+	u64 tertiary_exec;
 };
 
 /*
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 47b8357..12a926e 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -2376,6 +2376,7 @@  static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
 	u32 _pin_based_exec_control = 0;
 	u32 _cpu_based_exec_control = 0;
 	u32 _cpu_based_2nd_exec_control = 0;
+	u64 _cpu_based_3rd_exec_control = 0;
 	u32 _vmexit_control = 0;
 	u32 _vmentry_control = 0;
 
@@ -2397,7 +2398,8 @@  static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
 
 	opt = CPU_BASED_TPR_SHADOW |
 	      CPU_BASED_USE_MSR_BITMAPS |
-	      CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
+	      CPU_BASED_ACTIVATE_SECONDARY_CONTROLS |
+	      CPU_BASED_ACTIVATE_TERTIARY_CONTROLS;
 	if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,
 				&_cpu_based_exec_control) < 0)
 		return -EIO;
@@ -2557,6 +2559,7 @@  static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
 	vmcs_conf->pin_based_exec_ctrl = _pin_based_exec_control;
 	vmcs_conf->cpu_based_exec_ctrl = _cpu_based_exec_control;
 	vmcs_conf->cpu_based_2nd_exec_ctrl = _cpu_based_2nd_exec_control;
+	vmcs_conf->cpu_based_3rd_exec_ctrl = _cpu_based_3rd_exec_control;
 	vmcs_conf->vmexit_ctrl         = _vmexit_control;
 	vmcs_conf->vmentry_ctrl        = _vmentry_control;
 
@@ -4200,6 +4203,12 @@  u32 vmx_exec_control(struct vcpu_vmx *vmx)
 #define vmx_adjust_sec_exec_exiting(vmx, exec_control, lname, uname) \
 	vmx_adjust_sec_exec_control(vmx, exec_control, lname, uname, uname##_EXITING, true)
 
+static u64 vmx_tertiary_exec_control(struct vcpu_vmx *vmx)
+{
+	/* Though currently, no special adjustment. There might be in the future*/
+	return vmcs_config.cpu_based_3rd_exec_ctrl;
+}
+
 static void vmx_compute_secondary_exec_control(struct vcpu_vmx *vmx)
 {
 	struct kvm_vcpu *vcpu = &vmx->vcpu;
@@ -4310,6 +4319,9 @@  static void init_vmcs(struct vcpu_vmx *vmx)
 		secondary_exec_controls_set(vmx, vmx->secondary_exec_control);
 	}
 
+	if (cpu_has_tertiary_exec_ctrls())
+		tertiary_exec_controls_set(vmx, vmx_tertiary_exec_control(vmx));
+
 	if (kvm_vcpu_apicv_active(&vmx->vcpu)) {
 		vmcs_write64(EOI_EXIT_BITMAP0, 0);
 		vmcs_write64(EOI_EXIT_BITMAP1, 0);
@@ -5778,6 +5790,7 @@  void dump_vmcs(void)
 {
 	u32 vmentry_ctl, vmexit_ctl;
 	u32 cpu_based_exec_ctrl, pin_based_exec_ctrl, secondary_exec_control;
+	u64 tertiary_exec_control = 0;
 	unsigned long cr4;
 	u64 efer;
 
@@ -5796,6 +5809,9 @@  void dump_vmcs(void)
 	if (cpu_has_secondary_exec_ctrls())
 		secondary_exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
 
+	if (cpu_has_tertiary_exec_ctrls())
+		tertiary_exec_control = vmcs_read64(TERTIARY_VM_EXEC_CONTROL);
+
 	pr_err("*** Guest State ***\n");
 	pr_err("CR0: actual=0x%016lx, shadow=0x%016lx, gh_mask=%016lx\n",
 	       vmcs_readl(GUEST_CR0), vmcs_readl(CR0_READ_SHADOW),
@@ -5878,8 +5894,9 @@  void dump_vmcs(void)
 		       vmcs_read64(HOST_IA32_PERF_GLOBAL_CTRL));
 
 	pr_err("*** Control State ***\n");
-	pr_err("PinBased=%08x CPUBased=%08x SecondaryExec=%08x\n",
-	       pin_based_exec_ctrl, cpu_based_exec_ctrl, secondary_exec_control);
+	pr_err("PinBased=0x%08x CPUBased=0x%08x SecondaryExec=0x%08x TertiaryExec=0x%016llx\n",
+	       pin_based_exec_ctrl, cpu_based_exec_ctrl, secondary_exec_control,
+	       tertiary_exec_control);
 	pr_err("EntryControls=%08x ExitControls=%08x\n", vmentry_ctl, vmexit_ctl);
 	pr_err("ExceptionBitmap=%08x PFECmask=%08x PFECmatch=%08x\n",
 	       vmcs_read32(EXCEPTION_BITMAP),
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index f6f66e5..94f1c27 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -373,6 +373,14 @@  static inline u8 vmx_get_rvi(void)
 BUILD_CONTROLS_SHADOW(exec, CPU_BASED_VM_EXEC_CONTROL)
 BUILD_CONTROLS_SHADOW(secondary_exec, SECONDARY_VM_EXEC_CONTROL)
 
+static inline void tertiary_exec_controls_set(struct vcpu_vmx *vmx, u64 val)
+{
+	if (vmx->loaded_vmcs->controls_shadow.tertiary_exec != val) {
+		vmcs_write64(TERTIARY_VM_EXEC_CONTROL, val);
+		vmx->loaded_vmcs->controls_shadow.tertiary_exec = val;
+	}
+}
+
 static inline void vmx_register_cache_reset(struct kvm_vcpu *vcpu)
 {
 	vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP)