ASSERT(v->arch.vm_event);
- /* The actual write will occur in hvm_do_resume() (if permitted). */
- v->arch.vm_event->write_data.do_write.msr = 1;
- v->arch.vm_event->write_data.msr = msr;
- v->arch.vm_event->write_data.value = msr_content;
+ if ( hvm_monitor_msr(msr, msr_content, msr_old_content) )
+ {
+ /* The actual write will occur in hvm_do_resume(), if permitted. */
+ v->arch.vm_event->write_data.do_write.msr = 1;
+ v->arch.vm_event->write_data.msr = msr;
+ v->arch.vm_event->write_data.value = msr_content;
- hvm_monitor_msr(msr, msr_content, msr_old_content);
- return X86EMUL_OKAY;
+ return X86EMUL_OKAY;
+ }
}
if ( (ret = guest_wrmsr(v, msr, msr_content)) != X86EMUL_UNHANDLEABLE )
.u.write_ctrlreg.old_value = old
};
- if ( monitor_traps(curr, sync, &req) >= 0 )
- return 1;
+ return monitor_traps(curr, sync, &req) >= 0 &&
+ curr->domain->arch.monitor.control_register_values;
}
- return 0;
+ return false;
}
bool hvm_monitor_emul_unimplemented(void)
monitor_traps(curr, true, &req) == 1;
}
-void hvm_monitor_msr(unsigned int msr, uint64_t new_value, uint64_t old_value)
+bool hvm_monitor_msr(unsigned int msr, uint64_t new_value, uint64_t old_value)
{
struct vcpu *curr = current;
.u.mov_to_msr.old_value = old_value
};
- monitor_traps(curr, 1, &req);
+ return monitor_traps(curr, 1, &req) >= 0 &&
+ curr->domain->arch.monitor.control_register_values;
}
+
+ return false;
}
void hvm_monitor_descriptor_access(uint64_t exit_info,
* This is used to filter out pagefaults.
*/
unsigned int inguest_pagefault_disabled : 1;
+ unsigned int control_register_values : 1;
struct monitor_msr_bitmap *msr_bitmap;
uint64_t write_ctrlreg_mask[4];
} monitor;
};
/*
- * Called for current VCPU on crX/MSR changes by guest.
- * The event might not fire if the client has subscribed to it in onchangeonly
- * mode, hence the bool return type for control register write events.
+ * Called for current VCPU on crX/MSR changes by guest. Bool return signals
+ * whether emulation should be postponed.
*/
bool hvm_monitor_cr(unsigned int index, unsigned long value,
unsigned long old);
#define hvm_monitor_crX(cr, new, old) \
hvm_monitor_cr(VM_EVENT_X86_##cr, new, old)
-void hvm_monitor_msr(unsigned int msr, uint64_t value, uint64_t old_value);
+bool hvm_monitor_msr(unsigned int msr, uint64_t value, uint64_t old_value);
void hvm_monitor_descriptor_access(uint64_t exit_info,
uint64_t vmx_exit_qualification,
uint8_t descriptor, bool is_write);
domain_unpause(d);
break;
+ case XEN_DOMCTL_MONITOR_OP_CONTROL_REGISTERS:
+ d->arch.monitor.control_register_values = true;
+ break;
+
default:
rc = -EOPNOTSUPP;
}
#define XEN_DOMCTL_MONITOR_OP_DISABLE 1
#define XEN_DOMCTL_MONITOR_OP_GET_CAPABILITIES 2
#define XEN_DOMCTL_MONITOR_OP_EMULATE_EACH_REP 3
+/*
+ * Control register feature can result in guest-crashes when the monitor
+ * subsystem is being turned off. User has to take special precautions
+ * to ensure all vCPUs have resumed before it is safe to turn it off.
+ */
+#define XEN_DOMCTL_MONITOR_OP_CONTROL_REGISTERS 4
#define XEN_DOMCTL_MONITOR_EVENT_WRITE_CTRLREG 0
#define XEN_DOMCTL_MONITOR_EVENT_MOV_TO_MSR 1