<major>, <minor> and <build> must be integers. The values will be
encoded in guest CPUID 0x40000002 if viridian enlightenments are enabled.
+### vm-notify-window (Intel)
+> `= <integer>`
+
+> Default: `0`
+
+Specify the value of the VM Notify window used to detect locked VMs. Set to -1
+to disable the feature. Value is in units of crystal clock cycles.
+
+Note the hardware might add a threshold to the provided value in order to make
+it safe, and hence using 0 is fine.
+
### vpid (Intel)
> `= <boolean>`
static unsigned int __read_mostly ple_window = 4096;
integer_param("ple_window", ple_window);
+static unsigned int __ro_after_init vm_notify_window;
+integer_param("vm-notify-window", vm_notify_window);
+
static bool __read_mostly opt_ept_pml = true;
static s8 __read_mostly opt_ept_ad = -1;
int8_t __read_mostly opt_ept_exec_sp = -1;
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");
+ P(cpu_has_vmx_notify_vm_exiting, "Notify VM Exit");
#undef P
if ( !printed )
opt |= SECONDARY_EXEC_UNRESTRICTED_GUEST;
if ( opt_ept_pml )
opt |= SECONDARY_EXEC_ENABLE_PML;
+ if ( vm_notify_window != ~0u )
+ opt |= SECONDARY_EXEC_NOTIFY_VM_EXITING;
/*
* "APIC Register Virtualization" and "Virtual Interrupt Delivery"
v->arch.hvm.vmx.exception_bitmap = HVM_TRAP_MASK
| (paging_mode_hap(d) ? 0 : (1U << TRAP_page_fault))
| (v->arch.fully_eager_fpu ? 0 : (1U << TRAP_no_device));
+ if ( cpu_has_vmx_notify_vm_exiting )
+ {
+ __vmwrite(NOTIFY_WINDOW, vm_notify_window);
+ /*
+ * Disable #AC and #DB interception: by using VM Notify Xen is
+ * guaranteed to get a VM exit even if the guest manages to lock the
+ * CPU.
+ */
+ v->arch.hvm.vmx.exception_bitmap &= ~((1U << TRAP_debug) |
+ (1U << TRAP_alignment_check));
+ }
vmx_update_exception_bitmap(v);
v->arch.hvm.guest_cr[0] = X86_CR0_PE | X86_CR0_ET;
void vmx_update_debug_state(struct vcpu *v)
{
+ unsigned int mask = 1u << TRAP_int3;
+
+ if ( !cpu_has_monitor_trap_flag && cpu_has_vmx_notify_vm_exiting )
+ /*
+ * Only allow toggling TRAP_debug if notify VM exit is enabled, as
+ * unconditionally setting TRAP_debug is part of the XSA-156 fix.
+ */
+ mask |= 1u << TRAP_debug;
+
if ( v->arch.hvm.debug_state_latch )
- v->arch.hvm.vmx.exception_bitmap |= 1U << TRAP_int3;
+ v->arch.hvm.vmx.exception_bitmap |= mask;
else
- v->arch.hvm.vmx.exception_bitmap &= ~(1U << TRAP_int3);
+ v->arch.hvm.vmx.exception_bitmap &= ~mask;
vmx_vmcs_enter(v);
vmx_update_exception_bitmap(v);
switch ( vector )
{
case TRAP_debug:
+ if ( cpu_has_monitor_trap_flag && cpu_has_vmx_notify_vm_exiting )
+ goto exit_and_crash;
+
/*
* Updates DR6 where debugger can peek (See 3B 23.2.1,
* Table 23-1, "Exit Qualification for Debug Exceptions").
*/
break;
+ case EXIT_REASON_NOTIFY:
+ __vmread(EXIT_QUALIFICATION, &exit_qualification);
+
+ if ( unlikely(exit_qualification & NOTIFY_VM_CONTEXT_INVALID) )
+ {
+ perfc_incr(vmnotify_crash);
+ gprintk(XENLOG_ERR, "invalid VM context after notify vmexit\n");
+ domain_crash(v->domain);
+ break;
+ }
+
+ if ( unlikely(exit_qualification & INTR_INFO_NMI_UNBLOCKED_BY_IRET) )
+ undo_nmis_unblocked_by_iret();
+
+ break;
+
case EXIT_REASON_VMX_PREEMPTION_TIMER_EXPIRED:
case EXIT_REASON_INVPCID:
/* fall through */
case EXIT_REASON_EPT_MISCONFIG:
case EXIT_REASON_EXTERNAL_INTERRUPT:
case EXIT_REASON_BUS_LOCK:
+ case EXIT_REASON_NOTIFY:
/* pass to L0 handler */
break;
case VMX_EXIT_REASONS_FAILED_VMENTRY:
#define SECONDARY_EXEC_XSAVES 0x00100000
#define SECONDARY_EXEC_TSC_SCALING 0x02000000
#define SECONDARY_EXEC_BUS_LOCK_DETECTION 0x40000000
+#define SECONDARY_EXEC_NOTIFY_VM_EXITING 0x80000000
extern u32 vmx_secondary_exec_control;
#define VMX_EPT_EXEC_ONLY_SUPPORTED 0x00000001
(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 cpu_has_vmx_notify_vm_exiting \
+ (vmx_secondary_exec_control & SECONDARY_EXEC_NOTIFY_VM_EXITING)
#define VMCS_RID_TYPE_MASK 0x80000000
SECONDARY_VM_EXEC_CONTROL = 0x0000401e,
PLE_GAP = 0x00004020,
PLE_WINDOW = 0x00004022,
+ NOTIFY_WINDOW = 0x00004024,
VM_INSTRUCTION_ERROR = 0x00004400,
VM_EXIT_REASON = 0x00004402,
VM_EXIT_INTR_INFO = 0x00004404,
#define EXIT_REASON_XSAVES 63
#define EXIT_REASON_XRSTORS 64
#define EXIT_REASON_BUS_LOCK 74
+#define EXIT_REASON_NOTIFY 75
/* Remember to also update VMX_PERF_EXIT_REASON_SIZE! */
/*
#define INTR_INFO_VALID_MASK 0x80000000 /* 31 */
#define INTR_INFO_RESVD_BITS_MASK 0x7ffff000
+/*
+ * Exit Qualifications for NOTIFY VM EXIT
+ */
+#define NOTIFY_VM_CONTEXT_INVALID 1u
+
/*
* Exit Qualifications for MOV for Control Register Access
*/
#ifdef CONFIG_HVM
-#define VMX_PERF_EXIT_REASON_SIZE 75
+#define VMX_PERF_EXIT_REASON_SIZE 76
#define VMEXIT_NPF_PERFC 143
#define SVM_PERF_EXIT_REASON_SIZE (VMEXIT_NPF_PERFC + 1)
PERFCOUNTER_ARRAY(vmexits, "vmexits",
PERFCOUNTER(iommu_pt_coalesces, "IOMMU page table coalesces")
PERFCOUNTER(buslock, "Bus Locks Detected")
+PERFCOUNTER(vmnotify_crash, "domain crashes by Notify VM Exit")
/*#endif*/ /* __XEN_PERFC_DEFN_H__ */