@@ -866,7 +866,7 @@ static void svm_set_rdtsc_exiting(struct
vmcb_set_general2_intercepts(vmcb, general2_intercepts);
}
-static void svm_set_descriptor_access_exiting(struct vcpu *v, bool enable)
+static bool svm_set_descriptor_access_exiting(struct vcpu *v, bool enable)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
u32 general1_intercepts = vmcb_get_general1_intercepts(vmcb);
@@ -881,6 +881,8 @@ static void svm_set_descriptor_access_ex
general1_intercepts &= ~mask;
vmcb_set_general1_intercepts(vmcb, general1_intercepts);
+
+ return true;
}
static unsigned int svm_get_insn_bytes(struct vcpu *v, uint8_t *buf)
@@ -226,6 +226,7 @@ static int vmx_init_vmcs_config(void)
opt = (SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
SECONDARY_EXEC_WBINVD_EXITING |
SECONDARY_EXEC_ENABLE_EPT |
+ SECONDARY_EXEC_DESCRIPTOR_TABLE_EXITING |
SECONDARY_EXEC_ENABLE_RDTSCP |
SECONDARY_EXEC_PAUSE_LOOP_EXITING |
SECONDARY_EXEC_ENABLE_INVPCID |
@@ -1020,6 +1021,13 @@ static int construct_vmcs(struct vcpu *v
v->arch.hvm_vmx.secondary_exec_control = vmx_secondary_exec_control;
+ /*
+ * Disable descriptor table exiting: It's controlled by the VM event
+ * monitor requesting it.
+ */
+ v->arch.hvm_vmx.secondary_exec_control &=
+ ~SECONDARY_EXEC_DESCRIPTOR_TABLE_EXITING;
+
/* Disable VPID for now: we decide when to enable it on VMENTER. */
v->arch.hvm_vmx.secondary_exec_control &= ~SECONDARY_EXEC_ENABLE_VPID;
@@ -1423,11 +1423,15 @@ static void vmx_set_rdtsc_exiting(struct
vmx_vmcs_exit(v);
}
-static void vmx_set_descriptor_access_exiting(struct vcpu *v, bool enable)
+static bool vmx_set_descriptor_access_exiting(struct vcpu *v, bool enable)
{
if ( enable )
+ {
+ if ( !cpu_has_vmx_dt_exiting )
+ return false;
v->arch.hvm_vmx.secondary_exec_control |=
SECONDARY_EXEC_DESCRIPTOR_TABLE_EXITING;
+ }
else
v->arch.hvm_vmx.secondary_exec_control &=
~SECONDARY_EXEC_DESCRIPTOR_TABLE_EXITING;
@@ -1435,6 +1439,8 @@ static void vmx_set_descriptor_access_ex
vmx_vmcs_enter(v);
vmx_update_secondary_exec_control(v);
vmx_vmcs_exit(v);
+
+ return true;
}
static void vmx_init_hypercall_page(struct domain *d, void *hypercall_page)
@@ -213,7 +213,7 @@ int arch_monitor_domctl_event(struct dom
case XEN_DOMCTL_MONITOR_EVENT_DESC_ACCESS:
{
- bool old_status = ad->monitor.descriptor_access_enabled;
+ bool old_status = ad->monitor.descriptor_access_enabled, ok = true;
struct vcpu *v;
if ( unlikely(old_status == requested_status) )
@@ -223,9 +223,15 @@ int arch_monitor_domctl_event(struct dom
ad->monitor.descriptor_access_enabled = requested_status;
for_each_vcpu ( d, v )
- hvm_funcs.set_descriptor_access_exiting(v, requested_status);
+ {
+ ok = hvm_funcs.set_descriptor_access_exiting(v, requested_status);
+ if ( !ok )
+ break;
+ }
domain_unpause(d);
+ if ( !ok )
+ return -EOPNOTSUPP;
break;
}
@@ -173,7 +173,7 @@ struct hvm_function_table {
void (*handle_cd)(struct vcpu *v, unsigned long value);
void (*set_info_guest)(struct vcpu *v);
void (*set_rdtsc_exiting)(struct vcpu *v, bool_t);
- void (*set_descriptor_access_exiting)(struct vcpu *v, bool);
+ bool (*set_descriptor_access_exiting)(struct vcpu *v, bool);
/* Nested HVM */
int (*nhvm_vcpu_initialise)(struct vcpu *v);
@@ -274,6 +274,8 @@ extern u64 vmx_ept_vpid_cap;
(vmx_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)
#define cpu_has_vmx_ept \
(vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_EPT)
+#define cpu_has_vmx_dt_exiting \
+ (vmx_secondary_exec_control & SECONDARY_EXEC_DESCRIPTOR_TABLE_EXITING)
#define cpu_has_vmx_vpid \
(vmx_secondary_exec_control & SECONDARY_EXEC_ENABLE_VPID)
#define cpu_has_monitor_trap_flag \
@@ -77,13 +77,15 @@ static inline uint32_t arch_monitor_get_
(1U << XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST) |
(1U << XEN_DOMCTL_MONITOR_EVENT_DEBUG_EXCEPTION) |
(1U << XEN_DOMCTL_MONITOR_EVENT_CPUID) |
- (1U << XEN_DOMCTL_MONITOR_EVENT_INTERRUPT) |
- (1U << XEN_DOMCTL_MONITOR_EVENT_DESC_ACCESS);
+ (1U << XEN_DOMCTL_MONITOR_EVENT_INTERRUPT);
/* Since we know this is on VMX, we can just call the hvm func */
if ( hvm_is_singlestep_supported() )
capabilities |= (1U << XEN_DOMCTL_MONITOR_EVENT_SINGLESTEP);
+ if ( cpu_has_vmx_dt_exiting || cpu_has_svm )
+ capabilities |= (1U << XEN_DOMCTL_MONITOR_EVENT_DESC_ACCESS);
+
return capabilities;
}