All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR
@ 2019-11-11 12:30 Liran Alon
  2019-11-11 12:30 ` [PATCH 1/2] KVM: VMX: Refactor update_cr8_intercept() Liran Alon
  2019-11-11 12:30 ` [PATCH 2/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR Liran Alon
  0 siblings, 2 replies; 13+ messages in thread
From: Liran Alon @ 2019-11-11 12:30 UTC (permalink / raw)
  To: pbonzini, rkrcmar, kvm; +Cc: sean.j.christopherson, jmattson, vkuznets

Hi,

This patch series aims to fix an issue in nVMX when host use TPR-Threshold (APICv disabled)
and L1 provides to L2 direct access to L1 TPR.

1st patch is just a simple refactoring patch which also simplifies next patch.
2nd is the issue fix. For futher information, see patch commit message.

A kvm-unit-test was written to simulate this issue and will be submitted seperately.

Regards,
-Liran


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/2] KVM: VMX: Refactor update_cr8_intercept()
  2019-11-11 12:30 [PATCH 0/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR Liran Alon
@ 2019-11-11 12:30 ` Liran Alon
  2019-11-11 14:57   ` Paolo Bonzini
  2019-11-11 12:30 ` [PATCH 2/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR Liran Alon
  1 sibling, 1 reply; 13+ messages in thread
From: Liran Alon @ 2019-11-11 12:30 UTC (permalink / raw)
  To: pbonzini, rkrcmar, kvm
  Cc: sean.j.christopherson, jmattson, vkuznets, Liran Alon, Joao Martins

No functional changes.

Reviewed-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Liran Alon <liran.alon@oracle.com>
---
 arch/x86/kvm/vmx/vmx.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index f53b0c74f7c8..d5742378d031 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -6013,17 +6013,14 @@ static void vmx_l1d_flush(struct kvm_vcpu *vcpu)
 static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
 {
 	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+	int tpr_threshold;
 
 	if (is_guest_mode(vcpu) &&
 		nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
 		return;
 
-	if (irr == -1 || tpr < irr) {
-		vmcs_write32(TPR_THRESHOLD, 0);
-		return;
-	}
-
-	vmcs_write32(TPR_THRESHOLD, irr);
+	tpr_threshold = ((irr == -1) || (tpr < irr)) ? 0 : irr;
+	vmcs_write32(TPR_THRESHOLD, tpr_threshold);
 }
 
 void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 2/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR
  2019-11-11 12:30 [PATCH 0/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR Liran Alon
  2019-11-11 12:30 ` [PATCH 1/2] KVM: VMX: Refactor update_cr8_intercept() Liran Alon
@ 2019-11-11 12:30 ` Liran Alon
  2019-11-11 15:02   ` Paolo Bonzini
  1 sibling, 1 reply; 13+ messages in thread
From: Liran Alon @ 2019-11-11 12:30 UTC (permalink / raw)
  To: pbonzini, rkrcmar, kvm
  Cc: sean.j.christopherson, jmattson, vkuznets, Liran Alon, Joao Martins

When L1 don't use TPR-Shadow to run L2, L0 configures vmcs02 without
TPR-Shadow and install intercepts on CR8 access (load and store).

If L1 do not intercept L2 CR8 access, L0 intercepts on those accesses
will emulate load/store on L1's LAPIC TPR. If in this case L2 lowers
TPR such that there is now an injectable interrupt to L1,
apic_update_ppr() will request a KVM_REQ_EVENT which will trigger a call
to update_cr8_intercept() to update TPR-Threshold to highest pending IRR
priority.

However, this update to TPR-Threshold is done while active vmcs is
vmcs02 instead of vmcs01. Thus, when later at some point L0 will
emulate an exit from L2 to L1, L1 will still run with high
TPR-Threshold. This will result in every VMEntry to L1 to immediately
exit on TPR_BELOW_THRESHOLD and continue to do so infinitely until
some condition will cause KVM_REQ_EVENT to be set.
(Note that TPR_BELOW_THRESHOLD exit handler do not set KVM_REQ_EVENT
until apic_update_ppr() will notice a new injectable interrupt for PPR)

To fix this issue, change update_cr8_intercept() such that if L2 lowers
L1's TPR in a way that requires to lower L1's TPR-Threshold, save update
to TPR-Threshold and apply it to vmcs01 when L0 emulates an exit from
L2 to L1.

Reviewed-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Liran Alon <liran.alon@oracle.com>
---
 arch/x86/kvm/vmx/nested.c | 6 +++++-
 arch/x86/kvm/vmx/vmx.c    | 6 +++++-
 arch/x86/kvm/vmx/vmx.h    | 3 +++
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 2c4336ac7576..9197f6631c02 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -2075,11 +2075,13 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12)
 
 	if (exec_control & CPU_BASED_TPR_SHADOW)
 		vmcs_write32(TPR_THRESHOLD, vmcs12->tpr_threshold);
+	else {
+		vmx->nested.l1_tpr_threshold = -1;
 #ifdef CONFIG_X86_64
-	else
 		exec_control |= CPU_BASED_CR8_LOAD_EXITING |
 				CPU_BASED_CR8_STORE_EXITING;
 #endif
+	}
 
 	/*
 	 * A vmexit (to either L1 hypervisor or L0 userspace) is always needed
@@ -4113,6 +4115,8 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
 	vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, vmx->msr_autoload.host.nr);
 	vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, vmx->msr_autoload.guest.nr);
 	vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset);
+	if (vmx->nested.l1_tpr_threshold != -1)
+		vmcs_write32(TPR_THRESHOLD, vmx->nested.l1_tpr_threshold);
 
 	if (kvm_has_tsc_control)
 		decache_tsc_multiplier(vmx);
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index d5742378d031..c4667631a14f 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -6020,7 +6020,11 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
 		return;
 
 	tpr_threshold = ((irr == -1) || (tpr < irr)) ? 0 : irr;
-	vmcs_write32(TPR_THRESHOLD, tpr_threshold);
+
+	if (is_guest_mode(vcpu))
+		to_vmx(vcpu)->nested.l1_tpr_threshold = tpr_threshold;
+	else
+		vmcs_write32(TPR_THRESHOLD, tpr_threshold);
 }
 
 void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index bee16687dc0b..43331dfafffe 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -167,6 +167,9 @@ struct nested_vmx {
 	u64 vmcs01_debugctl;
 	u64 vmcs01_guest_bndcfgs;
 
+	/* to migrate it to L1 if L2 writes to L1's CR8 directly */
+	int l1_tpr_threshold;
+
 	u16 vpid02;
 	u16 last_vpid;
 
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] KVM: VMX: Refactor update_cr8_intercept()
  2019-11-11 12:30 ` [PATCH 1/2] KVM: VMX: Refactor update_cr8_intercept() Liran Alon
@ 2019-11-11 14:57   ` Paolo Bonzini
  2019-11-11 15:00     ` Liran Alon
  0 siblings, 1 reply; 13+ messages in thread
From: Paolo Bonzini @ 2019-11-11 14:57 UTC (permalink / raw)
  To: Liran Alon, rkrcmar, kvm
  Cc: sean.j.christopherson, jmattson, vkuznets, Joao Martins

On 11/11/19 13:30, Liran Alon wrote:
> No functional changes.
> 
> Reviewed-by: Joao Martins <joao.m.martins@oracle.com>
> Signed-off-by: Liran Alon <liran.alon@oracle.com>
> ---
>  arch/x86/kvm/vmx/vmx.c | 9 +++------
>  1 file changed, 3 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index f53b0c74f7c8..d5742378d031 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -6013,17 +6013,14 @@ static void vmx_l1d_flush(struct kvm_vcpu *vcpu)
>  static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
>  {
>  	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
> +	int tpr_threshold;
>  
>  	if (is_guest_mode(vcpu) &&
>  		nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
>  		return;
>  
> -	if (irr == -1 || tpr < irr) {
> -		vmcs_write32(TPR_THRESHOLD, 0);
> -		return;
> -	}
> -
> -	vmcs_write32(TPR_THRESHOLD, irr);
> +	tpr_threshold = ((irr == -1) || (tpr < irr)) ? 0 : irr;

Pascal parentheses? :)

Paolo

> +	vmcs_write32(TPR_THRESHOLD, tpr_threshold);
>  }
>  
>  void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] KVM: VMX: Refactor update_cr8_intercept()
  2019-11-11 14:57   ` Paolo Bonzini
@ 2019-11-11 15:00     ` Liran Alon
  2019-11-11 16:01       ` Paolo Bonzini
  0 siblings, 1 reply; 13+ messages in thread
From: Liran Alon @ 2019-11-11 15:00 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: rkrcmar, kvm, sean.j.christopherson, jmattson, vkuznets, Joao Martins



> On 11 Nov 2019, at 16:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
> 
> On 11/11/19 13:30, Liran Alon wrote:
>> No functional changes.
>> 
>> Reviewed-by: Joao Martins <joao.m.martins@oracle.com>
>> Signed-off-by: Liran Alon <liran.alon@oracle.com>
>> ---
>> arch/x86/kvm/vmx/vmx.c | 9 +++------
>> 1 file changed, 3 insertions(+), 6 deletions(-)
>> 
>> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
>> index f53b0c74f7c8..d5742378d031 100644
>> --- a/arch/x86/kvm/vmx/vmx.c
>> +++ b/arch/x86/kvm/vmx/vmx.c
>> @@ -6013,17 +6013,14 @@ static void vmx_l1d_flush(struct kvm_vcpu *vcpu)
>> static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
>> {
>> 	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
>> +	int tpr_threshold;
>> 
>> 	if (is_guest_mode(vcpu) &&
>> 		nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
>> 		return;
>> 
>> -	if (irr == -1 || tpr < irr) {
>> -		vmcs_write32(TPR_THRESHOLD, 0);
>> -		return;
>> -	}
>> -
>> -	vmcs_write32(TPR_THRESHOLD, irr);
>> +	tpr_threshold = ((irr == -1) || (tpr < irr)) ? 0 : irr;
> 
> Pascal parentheses? :)
> 
> Paolo

What do you mean?

-Liran

> 
>> +	vmcs_write32(TPR_THRESHOLD, tpr_threshold);
>> }
>> 
>> void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
>> 
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR
  2019-11-11 12:30 ` [PATCH 2/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR Liran Alon
@ 2019-11-11 15:02   ` Paolo Bonzini
  2019-11-11 15:24     ` Liran Alon
  0 siblings, 1 reply; 13+ messages in thread
From: Paolo Bonzini @ 2019-11-11 15:02 UTC (permalink / raw)
  To: Liran Alon, rkrcmar, kvm
  Cc: sean.j.christopherson, jmattson, vkuznets, Joao Martins

On 11/11/19 13:30, Liran Alon wrote:
> When L1 don't use TPR-Shadow to run L2, L0 configures vmcs02 without
> TPR-Shadow and install intercepts on CR8 access (load and store).
> 
> If L1 do not intercept L2 CR8 access, L0 intercepts on those accesses
> will emulate load/store on L1's LAPIC TPR. If in this case L2 lowers
> TPR such that there is now an injectable interrupt to L1,
> apic_update_ppr() will request a KVM_REQ_EVENT which will trigger a call
> to update_cr8_intercept() to update TPR-Threshold to highest pending IRR
> priority.
> 
> However, this update to TPR-Threshold is done while active vmcs is
> vmcs02 instead of vmcs01. Thus, when later at some point L0 will
> emulate an exit from L2 to L1, L1 will still run with high
> TPR-Threshold. This will result in every VMEntry to L1 to immediately
> exit on TPR_BELOW_THRESHOLD and continue to do so infinitely until
> some condition will cause KVM_REQ_EVENT to be set.
> (Note that TPR_BELOW_THRESHOLD exit handler do not set KVM_REQ_EVENT
> until apic_update_ppr() will notice a new injectable interrupt for PPR)
> 
> To fix this issue, change update_cr8_intercept() such that if L2 lowers
> L1's TPR in a way that requires to lower L1's TPR-Threshold, save update
> to TPR-Threshold and apply it to vmcs01 when L0 emulates an exit from
> L2 to L1.

Can you explain why the write shouldn't be done to vmcs02 as well?

Paolo

> -	vmcs_write32(TPR_THRESHOLD, tpr_threshold);
> +
> +	if (is_guest_mode(vcpu))
> +		to_vmx(vcpu)->nested.l1_tpr_threshold = tpr_threshold;
> +	else
> +		vmcs_write32(TPR_THRESHOLD, tpr_threshold);
>  }
>  
>  void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
> diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
> index bee16687dc0b..43331dfafffe 100644
> --- a/arch/x86/kvm/vmx/vmx.h
> +++ b/arch/x86/kvm/vmx/vmx.h
> @@ -167,6 +167,9 @@ struct nested_vmx {
>  	u64 vmcs01_debugctl;
>  	u64 vmcs01_guest_bndcfgs;
>  
> +	/* to migrate it to L1 if L2 writes to L1's CR8 directly */
> +	int l1_tpr_threshold;
> +
>  	u16 vpid02;
>  	u16 last_vpid;
>  
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR
  2019-11-11 15:02   ` Paolo Bonzini
@ 2019-11-11 15:24     ` Liran Alon
  2019-11-11 15:59       ` Paolo Bonzini
  2019-11-11 16:07       ` Paolo Bonzini
  0 siblings, 2 replies; 13+ messages in thread
From: Liran Alon @ 2019-11-11 15:24 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: rkrcmar, kvm, sean.j.christopherson, jmattson, vkuznets, Joao Martins



> On 11 Nov 2019, at 17:02, Paolo Bonzini <pbonzini@redhat.com> wrote:
> 
> On 11/11/19 13:30, Liran Alon wrote:
>> When L1 don't use TPR-Shadow to run L2, L0 configures vmcs02 without
>> TPR-Shadow and install intercepts on CR8 access (load and store).
>> 
>> If L1 do not intercept L2 CR8 access, L0 intercepts on those accesses
>> will emulate load/store on L1's LAPIC TPR. If in this case L2 lowers
>> TPR such that there is now an injectable interrupt to L1,
>> apic_update_ppr() will request a KVM_REQ_EVENT which will trigger a call
>> to update_cr8_intercept() to update TPR-Threshold to highest pending IRR
>> priority.
>> 
>> However, this update to TPR-Threshold is done while active vmcs is
>> vmcs02 instead of vmcs01. Thus, when later at some point L0 will
>> emulate an exit from L2 to L1, L1 will still run with high
>> TPR-Threshold. This will result in every VMEntry to L1 to immediately
>> exit on TPR_BELOW_THRESHOLD and continue to do so infinitely until
>> some condition will cause KVM_REQ_EVENT to be set.
>> (Note that TPR_BELOW_THRESHOLD exit handler do not set KVM_REQ_EVENT
>> until apic_update_ppr() will notice a new injectable interrupt for PPR)
>> 
>> To fix this issue, change update_cr8_intercept() such that if L2 lowers
>> L1's TPR in a way that requires to lower L1's TPR-Threshold, save update
>> to TPR-Threshold and apply it to vmcs01 when L0 emulates an exit from
>> L2 to L1.
> 
> Can you explain why the write shouldn't be done to vmcs02 as well?
> 
> Paolo

Because when L1 don’t use TPR-Shadow, L0 configures vmcs02 without TPR-Shadow.
Thus, writing to vmcs02->tpr_threshold doesn’t have any effect.

If l1 do use TPR-Shadow, then VMX’s update_cr8_intercept() doesn’t write to vmcs at all,
because it means L1 defines a vTPR for L2 and thus doesn’t provide it direct access to L1 TPR.

-Liran

> 
>> -	vmcs_write32(TPR_THRESHOLD, tpr_threshold);
>> +
>> +	if (is_guest_mode(vcpu))
>> +		to_vmx(vcpu)->nested.l1_tpr_threshold = tpr_threshold;
>> +	else
>> +		vmcs_write32(TPR_THRESHOLD, tpr_threshold);
>> }
>> 
>> void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
>> diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
>> index bee16687dc0b..43331dfafffe 100644
>> --- a/arch/x86/kvm/vmx/vmx.h
>> +++ b/arch/x86/kvm/vmx/vmx.h
>> @@ -167,6 +167,9 @@ struct nested_vmx {
>> 	u64 vmcs01_debugctl;
>> 	u64 vmcs01_guest_bndcfgs;
>> 
>> +	/* to migrate it to L1 if L2 writes to L1's CR8 directly */
>> +	int l1_tpr_threshold;
>> +
>> 	u16 vpid02;
>> 	u16 last_vpid;
>> 
>> 
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR
  2019-11-11 15:24     ` Liran Alon
@ 2019-11-11 15:59       ` Paolo Bonzini
  2019-11-11 16:07       ` Paolo Bonzini
  1 sibling, 0 replies; 13+ messages in thread
From: Paolo Bonzini @ 2019-11-11 15:59 UTC (permalink / raw)
  To: Liran Alon
  Cc: rkrcmar, kvm, sean.j.christopherson, jmattson, vkuznets, Joao Martins

On 11/11/19 16:24, Liran Alon wrote:
> Because when L1 don’t use TPR-Shadow, L0 configures vmcs02 without TPR-Shadow.
> Thus, writing to vmcs02->tpr_threshold doesn’t have any effect.

Uh, sorry that was obvious:

 	if (exec_control & CPU_BASED_TPR_SHADOW)
 		vmcs_write32(TPR_THRESHOLD, vmcs12->tpr_threshold);

Paolo

> If l1 do use TPR-Shadow, then VMX’s update_cr8_intercept() doesn’t write to vmcs at all,
> because it means L1 defines a vTPR for L2 and thus doesn’t provide it direct access to L1 TPR.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] KVM: VMX: Refactor update_cr8_intercept()
  2019-11-11 15:00     ` Liran Alon
@ 2019-11-11 16:01       ` Paolo Bonzini
  2019-11-11 16:02         ` Liran Alon
  0 siblings, 1 reply; 13+ messages in thread
From: Paolo Bonzini @ 2019-11-11 16:01 UTC (permalink / raw)
  To: Liran Alon
  Cc: rkrcmar, kvm, sean.j.christopherson, jmattson, vkuznets, Joao Martins

On 11/11/19 16:00, Liran Alon wrote:
> 
> 
>> On 11 Nov 2019, at 16:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
>>
>> On 11/11/19 13:30, Liran Alon wrote:
>>> No functional changes.
>>>
>>> Reviewed-by: Joao Martins <joao.m.martins@oracle.com>
>>> Signed-off-by: Liran Alon <liran.alon@oracle.com>
>>> ---
>>> arch/x86/kvm/vmx/vmx.c | 9 +++------
>>> 1 file changed, 3 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
>>> index f53b0c74f7c8..d5742378d031 100644
>>> --- a/arch/x86/kvm/vmx/vmx.c
>>> +++ b/arch/x86/kvm/vmx/vmx.c
>>> @@ -6013,17 +6013,14 @@ static void vmx_l1d_flush(struct kvm_vcpu *vcpu)
>>> static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
>>> {
>>> 	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
>>> +	int tpr_threshold;
>>>
>>> 	if (is_guest_mode(vcpu) &&
>>> 		nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
>>> 		return;
>>>
>>> -	if (irr == -1 || tpr < irr) {
>>> -		vmcs_write32(TPR_THRESHOLD, 0);
>>> -		return;
>>> -	}
>>> -
>>> -	vmcs_write32(TPR_THRESHOLD, irr);
>>> +	tpr_threshold = ((irr == -1) || (tpr < irr)) ? 0 : irr;
>>
>> Pascal parentheses? :)
> 
> What do you mean?

Redundant parentheses around && or || are usually avoided in the kernel,
and they are typical of Pascal (which had weird operator precedence
rules and thus required operands of AND/OR to be parenthesized).

I can remove them when committing the series.

Paolo


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 1/2] KVM: VMX: Refactor update_cr8_intercept()
  2019-11-11 16:01       ` Paolo Bonzini
@ 2019-11-11 16:02         ` Liran Alon
  0 siblings, 0 replies; 13+ messages in thread
From: Liran Alon @ 2019-11-11 16:02 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: rkrcmar, kvm, sean.j.christopherson, jmattson, vkuznets, Joao Martins



> On 11 Nov 2019, at 18:01, Paolo Bonzini <pbonzini@redhat.com> wrote:
> 
> On 11/11/19 16:00, Liran Alon wrote:
>> 
>> 
>>> On 11 Nov 2019, at 16:57, Paolo Bonzini <pbonzini@redhat.com> wrote:
>>> 
>>> On 11/11/19 13:30, Liran Alon wrote:
>>>> No functional changes.
>>>> 
>>>> Reviewed-by: Joao Martins <joao.m.martins@oracle.com>
>>>> Signed-off-by: Liran Alon <liran.alon@oracle.com>
>>>> ---
>>>> arch/x86/kvm/vmx/vmx.c | 9 +++------
>>>> 1 file changed, 3 insertions(+), 6 deletions(-)
>>>> 
>>>> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
>>>> index f53b0c74f7c8..d5742378d031 100644
>>>> --- a/arch/x86/kvm/vmx/vmx.c
>>>> +++ b/arch/x86/kvm/vmx/vmx.c
>>>> @@ -6013,17 +6013,14 @@ static void vmx_l1d_flush(struct kvm_vcpu *vcpu)
>>>> static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
>>>> {
>>>> 	struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
>>>> +	int tpr_threshold;
>>>> 
>>>> 	if (is_guest_mode(vcpu) &&
>>>> 		nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW))
>>>> 		return;
>>>> 
>>>> -	if (irr == -1 || tpr < irr) {
>>>> -		vmcs_write32(TPR_THRESHOLD, 0);
>>>> -		return;
>>>> -	}
>>>> -
>>>> -	vmcs_write32(TPR_THRESHOLD, irr);
>>>> +	tpr_threshold = ((irr == -1) || (tpr < irr)) ? 0 : irr;
>>> 
>>> Pascal parentheses? :)
>> 
>> What do you mean?
> 
> Redundant parentheses around && or || are usually avoided in the kernel,
> and they are typical of Pascal (which had weird operator precedence
> rules and thus required operands of AND/OR to be parenthesized).
> 
> I can remove them when committing the series.
> 
> Paolo

I see. Sure no problem you can remove them.

Thanks,
-Liran



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR
  2019-11-11 15:24     ` Liran Alon
  2019-11-11 15:59       ` Paolo Bonzini
@ 2019-11-11 16:07       ` Paolo Bonzini
  2019-11-11 16:17         ` Liran Alon
  1 sibling, 1 reply; 13+ messages in thread
From: Paolo Bonzini @ 2019-11-11 16:07 UTC (permalink / raw)
  To: Liran Alon
  Cc: rkrcmar, kvm, sean.j.christopherson, jmattson, vkuznets, Joao Martins

On 11/11/19 16:24, Liran Alon wrote:
>> Can you explain why the write shouldn't be done to vmcs02 as well?
>
> Because when L1 don’t use TPR-Shadow, L0 configures vmcs02 without TPR-Shadow.
> Thus, writing to vmcs02->tpr_threshold doesn’t have any effect.
> 
> If l1 do use TPR-Shadow, then VMX’s update_cr8_intercept() doesn’t write to vmcs at all,
> because it means L1 defines a vTPR for L2 and thus doesn’t provide it direct access to L1 TPR.

But I'm still not sure about another aspect of the patch.  The write to
vmcs01 can be done even if TPR_SHADOW was set in vmcs12, because no one
takes care of clearing vmx->nested.l1_tpr_threshold.  Should
"vmx->nested.l1_tpr_threshold = -1;" be outside the if?

Also, what happens to_vmx(vcpu)->nested.l1_tpr_threshold if the guest is
migrated while L2 is running without TPR shadow?  Perhaps it would be
easier to just rerun update_cr8_intercept on nested_vmx_vmexit.

Paolo


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR
  2019-11-11 16:07       ` Paolo Bonzini
@ 2019-11-11 16:17         ` Liran Alon
  2019-11-11 16:50           ` Paolo Bonzini
  0 siblings, 1 reply; 13+ messages in thread
From: Liran Alon @ 2019-11-11 16:17 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: rkrcmar, kvm, sean.j.christopherson, jmattson, vkuznets, Joao Martins



> On 11 Nov 2019, at 18:07, Paolo Bonzini <pbonzini@redhat.com> wrote:
> 
> On 11/11/19 16:24, Liran Alon wrote:
>>> Can you explain why the write shouldn't be done to vmcs02 as well?
>> 
>> Because when L1 don’t use TPR-Shadow, L0 configures vmcs02 without TPR-Shadow.
>> Thus, writing to vmcs02->tpr_threshold doesn’t have any effect.
>> 
>> If l1 do use TPR-Shadow, then VMX’s update_cr8_intercept() doesn’t write to vmcs at all,
>> because it means L1 defines a vTPR for L2 and thus doesn’t provide it direct access to L1 TPR.
> 
> But I'm still not sure about another aspect of the patch.  The write to
> vmcs01 can be done even if TPR_SHADOW was set in vmcs12, because no one
> takes care of clearing vmx->nested.l1_tpr_threshold.  Should
> "vmx->nested.l1_tpr_threshold = -1;" be outside the if?

If I understand you correctly, you refer to the case where L1 first enters L2 without TPR-Shadow,
then L2 lowers L1 TPR directly (which load vmx->nested.l1_tpr_threshold with value), then an
emualted exit happen from L2 to L1 which writes to vmcs01->tpr_threshold the value of
vmx->nested.l1_tpr_threshold. Then L1 enters again L2 but this time with TPR-Shadow and
prepare_vmcs02_early() doesn’t clear vmx->nested.l1_tpr_threshold which will cause next
exit from L2 to L1 to wrongly write the value of vmx->nested.l1_tpr_threshold to vmcs01->tpr_threshold.

So yes I think you are right. Good catch.
We should move vmx->nested.l1_tpr_threshold = -1; outside of the if.
Should I send v2 or will you change on apply?

> 
> Also, what happens to_vmx(vcpu)->nested.l1_tpr_threshold if the guest is
> migrated while L2 is running without TPR shadow?  Perhaps it would be
> easier to just rerun update_cr8_intercept on nested_vmx_vmexit.
> 

On restore of state during migration, kvm_apic_set_state() must be called which
will also request a KVM_REQ_EVENT which will make sure to call update_cr8_intercept().
If vCPU is currently in guest-mode, this should update vmx->nested.l1_tpr_threshold.

-Liran

> Paolo



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR
  2019-11-11 16:17         ` Liran Alon
@ 2019-11-11 16:50           ` Paolo Bonzini
  0 siblings, 0 replies; 13+ messages in thread
From: Paolo Bonzini @ 2019-11-11 16:50 UTC (permalink / raw)
  To: Liran Alon
  Cc: rkrcmar, kvm, sean.j.christopherson, jmattson, vkuznets, Joao Martins

On 11/11/19 17:17, Liran Alon wrote:
> If I understand you correctly, you refer to the case where L1 first enters L2 without TPR-Shadow,
> then L2 lowers L1 TPR directly (which load vmx->nested.l1_tpr_threshold with value), then an
> emualted exit happen from L2 to L1 which writes to vmcs01->tpr_threshold the value of
> vmx->nested.l1_tpr_threshold. Then L1 enters again L2 but this time with TPR-Shadow and
> prepare_vmcs02_early() doesn’t clear vmx->nested.l1_tpr_threshold which will cause next
> exit from L2 to L1 to wrongly write the value of vmx->nested.l1_tpr_threshold to vmcs01->tpr_threshold.
> 
> So yes I think you are right. Good catch.
> We should move vmx->nested.l1_tpr_threshold = -1; outside of the if.
> Should I send v2 or will you change on apply?

I can do that too.

>> Also, what happens to_vmx(vcpu)->nested.l1_tpr_threshold if the guest is
>> migrated while L2 is running without TPR shadow?  Perhaps it would be
>> easier to just rerun update_cr8_intercept on nested_vmx_vmexit.
>>
> On restore of state during migration, kvm_apic_set_state() must be called which
> will also request a KVM_REQ_EVENT which will make sure to call update_cr8_intercept().
> If vCPU is currently in guest-mode, this should update vmx->nested.l1_tpr_threshold.

Okay, that makes sense.  I was half-sure that update_cr8_intercept()
would be called, but I couldn't think of the exact path.

Paolo


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2019-11-11 16:50 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-11 12:30 [PATCH 0/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR Liran Alon
2019-11-11 12:30 ` [PATCH 1/2] KVM: VMX: Refactor update_cr8_intercept() Liran Alon
2019-11-11 14:57   ` Paolo Bonzini
2019-11-11 15:00     ` Liran Alon
2019-11-11 16:01       ` Paolo Bonzini
2019-11-11 16:02         ` Liran Alon
2019-11-11 12:30 ` [PATCH 2/2] KVM: nVMX: Update vmcs01 TPR_THRESHOLD if L2 changed L1 TPR Liran Alon
2019-11-11 15:02   ` Paolo Bonzini
2019-11-11 15:24     ` Liran Alon
2019-11-11 15:59       ` Paolo Bonzini
2019-11-11 16:07       ` Paolo Bonzini
2019-11-11 16:17         ` Liran Alon
2019-11-11 16:50           ` Paolo Bonzini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.