Message ID | 20220701131648.34292-2-roger.pau@citrix.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | x86/vmx: implement Bus Lock and VM Notify | expand |
On 01.07.2022 15:16, Roger Pau Monne wrote: > --- a/xen/arch/x86/hvm/vmx/vmx.c > +++ b/xen/arch/x86/hvm/vmx/vmx.c > @@ -4065,6 +4065,11 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) > > if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) ) > return vmx_failed_vmentry(exit_reason, regs); > + if ( unlikely(exit_reason & VMX_EXIT_REASONS_BUS_LOCK) ) > + { > + perfc_incr(buslock); > + exit_reason &= ~VMX_EXIT_REASONS_BUS_LOCK; > + } To cover for the flag bit, don't you also need to mask it off in nvmx_idtv_handling()? Or (didn't go into detail with checking whether there aren't any counter indications) pass the exit reason there from vmx_vmexit_handler(), instead of re-reading it from the VMCS? Jan
On Mon, Jul 04, 2022 at 11:27:37AM +0200, Jan Beulich wrote: > On 01.07.2022 15:16, Roger Pau Monne wrote: > > --- a/xen/arch/x86/hvm/vmx/vmx.c > > +++ b/xen/arch/x86/hvm/vmx/vmx.c > > @@ -4065,6 +4065,11 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) > > > > if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) ) > > return vmx_failed_vmentry(exit_reason, regs); > > + if ( unlikely(exit_reason & VMX_EXIT_REASONS_BUS_LOCK) ) > > + { > > + perfc_incr(buslock); > > + exit_reason &= ~VMX_EXIT_REASONS_BUS_LOCK; > > + } > > To cover for the flag bit, don't you also need to mask it off in > nvmx_idtv_handling()? Or (didn't go into detail with checking whether > there aren't any counter indications) pass the exit reason there from > vmx_vmexit_handler(), instead of re-reading it from the VMCS? This seem to be an existing issue with nvmx_idtv_handling(), as it should use just the low 16bits to check against the VM Exit reason codes. I can send a pre-patch to fix it, could pass exit reason from vmx_vmexit_handler(), but I would still need to cast to uint16_t for comparing against exit reason codes, as there's a jump into the 'out' label before VMX_EXIT_REASONS_BUS_LOCK is masked out. I think there's a similar issue with nvmx_n2_vmexit_handler() that doesn't cast the value to uint16_t and is called before VMX_EXIT_REASONS_BUS_LOCK is removed from exit reason. Thanks, Roger.
> From: Roger Pau Monne <roger.pau@citrix.com> > Sent: Friday, July 1, 2022 9:17 PM > > @@ -4065,6 +4065,11 @@ void vmx_vmexit_handler(struct cpu_user_regs > *regs) > > if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) ) > return vmx_failed_vmentry(exit_reason, regs); Add a blank line. > + if ( unlikely(exit_reason & VMX_EXIT_REASONS_BUS_LOCK) ) > + { > + perfc_incr(buslock); > + exit_reason &= ~VMX_EXIT_REASONS_BUS_LOCK; > + } > > if ( v->arch.hvm.vmx.vmx_realmode ) > { > @@ -4561,6 +4566,15 @@ void vmx_vmexit_handler(struct cpu_user_regs > *regs) > vmx_handle_descriptor_access(exit_reason); > break; > > + case EXIT_REASON_BUS_LOCK: > + /* > + * Nothing to do: just taking a vmexit should be enough of a pause to > + * prevent a VM from crippling the host with bus locks. Note > + * EXIT_REASON_BUS_LOCK will always have bit 26 set in exit_reason, > and > + * hence the perf counter is already increased. > + */ > + break; > + Would it be helpful from diagnostic angle by throwing out a warning, once per the culprit domain?
> From: Roger Pau Monné <roger.pau@citrix.com> > Sent: Monday, July 4, 2022 6:07 PM > > On Mon, Jul 04, 2022 at 11:27:37AM +0200, Jan Beulich wrote: > > On 01.07.2022 15:16, Roger Pau Monne wrote: > > > --- a/xen/arch/x86/hvm/vmx/vmx.c > > > +++ b/xen/arch/x86/hvm/vmx/vmx.c > > > @@ -4065,6 +4065,11 @@ void vmx_vmexit_handler(struct > cpu_user_regs *regs) > > > > > > if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) ) > > > return vmx_failed_vmentry(exit_reason, regs); > > > + if ( unlikely(exit_reason & VMX_EXIT_REASONS_BUS_LOCK) ) > > > + { > > > + perfc_incr(buslock); > > > + exit_reason &= ~VMX_EXIT_REASONS_BUS_LOCK; > > > + } > > > > To cover for the flag bit, don't you also need to mask it off in > > nvmx_idtv_handling()? Or (didn't go into detail with checking whether > > there aren't any counter indications) pass the exit reason there from > > vmx_vmexit_handler(), instead of re-reading it from the VMCS? > > This seem to be an existing issue with nvmx_idtv_handling(), as it > should use just the low 16bits to check against the VM Exit reason > codes. > > I can send a pre-patch to fix it, could pass exit reason from > vmx_vmexit_handler(), but I would still need to cast to uint16_t for > comparing against exit reason codes, as there's a jump into the 'out' > label before VMX_EXIT_REASONS_BUS_LOCK is masked out. or just masking out the bit in an earlier place which then also covers nvmx_n2_vmexit_handler() below? There are a few other goto's and return's before the point where that bit is currently masked out. Having bus lock counted even in those failure paths is also not a bad thing imho... > > I think there's a similar issue with nvmx_n2_vmexit_handler() that > doesn't cast the value to uint16_t and is called before > VMX_EXIT_REASONS_BUS_LOCK is removed from exit reason. >
On Tue, Jul 19, 2022 at 07:26:08AM +0000, Tian, Kevin wrote: > > From: Roger Pau Monne <roger.pau@citrix.com> > > Sent: Friday, July 1, 2022 9:17 PM > > > > @@ -4065,6 +4065,11 @@ void vmx_vmexit_handler(struct cpu_user_regs > > *regs) > > > > if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) ) > > return vmx_failed_vmentry(exit_reason, regs); > > Add a blank line. > > > + if ( unlikely(exit_reason & VMX_EXIT_REASONS_BUS_LOCK) ) > > + { > > + perfc_incr(buslock); > > + exit_reason &= ~VMX_EXIT_REASONS_BUS_LOCK; > > + } > > > > if ( v->arch.hvm.vmx.vmx_realmode ) > > { > > @@ -4561,6 +4566,15 @@ void vmx_vmexit_handler(struct cpu_user_regs > > *regs) > > vmx_handle_descriptor_access(exit_reason); > > break; > > > > + case EXIT_REASON_BUS_LOCK: > > + /* > > + * Nothing to do: just taking a vmexit should be enough of a pause to > > + * prevent a VM from crippling the host with bus locks. Note > > + * EXIT_REASON_BUS_LOCK will always have bit 26 set in exit_reason, > > and > > + * hence the perf counter is already increased. > > + */ > > + break; > > + > > Would it be helpful from diagnostic angle by throwing out a warning, > once per the culprit domain? Hm, not sure. I've assumed that increasing the counter would be enough, but that's not tied to a domain. I will leave as-is unless someone else expresses interest in this (and can also be added later if desired). Thanks, Roger.
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 56fed2db03..d388e6729c 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -209,6 +209,7 @@ static void __init vmx_display_features(void) P(cpu_has_vmx_virt_exceptions, "Virtualisation Exceptions"); P(cpu_has_vmx_pml, "Page Modification Logging"); P(cpu_has_vmx_tsc_scaling, "TSC Scaling"); + P(cpu_has_vmx_bus_lock_detection, "Bus Lock Detection"); #undef P if ( !printed ) @@ -318,7 +319,8 @@ static int vmx_init_vmcs_config(bool bsp) SECONDARY_EXEC_ENABLE_VM_FUNCTIONS | SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS | SECONDARY_EXEC_XSAVES | - SECONDARY_EXEC_TSC_SCALING); + SECONDARY_EXEC_TSC_SCALING | + SECONDARY_EXEC_BUS_LOCK_DETECTION); if ( _vmx_misc_cap & VMX_MISC_VMWRITE_ALL ) opt |= SECONDARY_EXEC_ENABLE_VMCS_SHADOWING; if ( opt_vpid_enabled ) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index f08a00dcbb..853f3a9111 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -4065,6 +4065,11 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) ) return vmx_failed_vmentry(exit_reason, regs); + if ( unlikely(exit_reason & VMX_EXIT_REASONS_BUS_LOCK) ) + { + perfc_incr(buslock); + exit_reason &= ~VMX_EXIT_REASONS_BUS_LOCK; + } if ( v->arch.hvm.vmx.vmx_realmode ) { @@ -4561,6 +4566,15 @@ void vmx_vmexit_handler(struct cpu_user_regs *regs) vmx_handle_descriptor_access(exit_reason); break; + case EXIT_REASON_BUS_LOCK: + /* + * Nothing to do: just taking a vmexit should be enough of a pause to + * prevent a VM from crippling the host with bus locks. Note + * EXIT_REASON_BUS_LOCK will always have bit 26 set in exit_reason, and + * hence the perf counter is already increased. + */ + break; + case EXIT_REASON_VMX_PREEMPTION_TIMER_EXPIRED: case EXIT_REASON_INVPCID: /* fall through */ diff --git a/xen/arch/x86/include/asm/hvm/vmx/vmcs.h b/xen/arch/x86/include/asm/hvm/vmx/vmcs.h index 9119aa8536..5d3edc1642 100644 --- a/xen/arch/x86/include/asm/hvm/vmx/vmcs.h +++ b/xen/arch/x86/include/asm/hvm/vmx/vmcs.h @@ -266,6 +266,7 @@ extern u32 vmx_vmentry_control; #define SECONDARY_EXEC_ENABLE_VIRT_EXCEPTIONS 0x00040000 #define SECONDARY_EXEC_XSAVES 0x00100000 #define SECONDARY_EXEC_TSC_SCALING 0x02000000 +#define SECONDARY_EXEC_BUS_LOCK_DETECTION 0x40000000 extern u32 vmx_secondary_exec_control; #define VMX_EPT_EXEC_ONLY_SUPPORTED 0x00000001 @@ -345,6 +346,8 @@ extern u64 vmx_ept_vpid_cap; (vmx_secondary_exec_control & SECONDARY_EXEC_XSAVES) #define cpu_has_vmx_tsc_scaling \ (vmx_secondary_exec_control & SECONDARY_EXEC_TSC_SCALING) +#define cpu_has_vmx_bus_lock_detection \ + (vmx_secondary_exec_control & SECONDARY_EXEC_BUS_LOCK_DETECTION) #define VMCS_RID_TYPE_MASK 0x80000000 diff --git a/xen/arch/x86/include/asm/hvm/vmx/vmx.h b/xen/arch/x86/include/asm/hvm/vmx/vmx.h index 8eedf59155..03995701a1 100644 --- a/xen/arch/x86/include/asm/hvm/vmx/vmx.h +++ b/xen/arch/x86/include/asm/hvm/vmx/vmx.h @@ -159,6 +159,7 @@ static inline void pi_clear_sn(struct pi_desc *pi_desc) * Exit Reasons */ #define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000 +#define VMX_EXIT_REASONS_BUS_LOCK (1u << 26) #define EXIT_REASON_EXCEPTION_NMI 0 #define EXIT_REASON_EXTERNAL_INTERRUPT 1 @@ -219,6 +220,7 @@ static inline void pi_clear_sn(struct pi_desc *pi_desc) #define EXIT_REASON_PML_FULL 62 #define EXIT_REASON_XSAVES 63 #define EXIT_REASON_XRSTORS 64 +#define EXIT_REASON_BUS_LOCK 74 /* Remember to also update VMX_PERF_EXIT_REASON_SIZE! */ /* diff --git a/xen/arch/x86/include/asm/perfc_defn.h b/xen/arch/x86/include/asm/perfc_defn.h index b07063b7d8..d6eb661940 100644 --- a/xen/arch/x86/include/asm/perfc_defn.h +++ b/xen/arch/x86/include/asm/perfc_defn.h @@ -6,7 +6,7 @@ PERFCOUNTER_ARRAY(exceptions, "exceptions", 32) #ifdef CONFIG_HVM -#define VMX_PERF_EXIT_REASON_SIZE 65 +#define VMX_PERF_EXIT_REASON_SIZE 75 #define VMEXIT_NPF_PERFC 143 #define SVM_PERF_EXIT_REASON_SIZE (VMEXIT_NPF_PERFC + 1) PERFCOUNTER_ARRAY(vmexits, "vmexits", @@ -125,4 +125,6 @@ PERFCOUNTER(realmode_exits, "vmexits from realmode") PERFCOUNTER(pauseloop_exits, "vmexits from Pause-Loop Detection") +PERFCOUNTER(buslock, "Bus Locks Detected") + /*#endif*/ /* __XEN_PERFC_DEFN_H__ */