void mce_intel_feature_init(struct cpuinfo_x86 *c);
void amd_nonfatal_mcheck_init(struct cpuinfo_x86 *c);
+int is_vmce_ready(struct mcinfo_bank *bank, struct domain *d);
+
u64 mce_cap_init(void);
extern int firstbank;
-int mca_ctl_conflict(struct mcinfo_bank *bank, struct domain *d);
int intel_mce_rdmsr(uint32_t msr, uint64_t *val);
int intel_mce_wrmsr(uint32_t msr, uint64_t val);
BUG_ON( result->owner == DOMID_COW );
if ( result->owner != DOMID_XEN ) {
d = get_domain_by_id(result->owner);
- if ( mca_ctl_conflict(bank, d) )
+ if ( !is_vmce_ready(bank, d) )
{
- /* Guest has different MCE ctl with hypervisor */
+ /* Should not inject vMCE to guest */
if ( d )
put_domain(d);
return;
return 0;
}
-int mca_ctl_conflict(struct mcinfo_bank *bank, struct domain *d)
+static int mca_ctl_conflict(struct mcinfo_bank *bank, struct domain *d)
{
int bank_nr;
return 1;
return 0;
}
+
+static int is_hvm_vmce_ready(struct mcinfo_bank *bank, struct domain *d)
+{
+ struct vcpu *v;
+ int no_vmce = 0, i;
+
+ if (!is_hvm_domain(d))
+ return 0;
+
+ /* kill guest if not enabled vMCE */
+ for_each_vcpu(d, v)
+ {
+ if (!(v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_MCE))
+ {
+ no_vmce = 1;
+ break;
+ }
+
+ if (!mce_broadcast)
+ break;
+ }
+
+ if (no_vmce)
+ return 0;
+
+ /* Guest has virtualized family/model information */
+ for ( i = 0; i < MAX_CPUID_INPUT; i++ )
+ {
+ if (d->arch.cpuids[i].input[0] == 0x1)
+ {
+ uint32_t veax = d->arch.cpuids[i].eax, vfam, vmod;
+
+ vfam = (veax >> 8) & 15;
+ vmod = (veax >> 4) & 15;
+
+ if (vfam == 0x6 || vfam == 0xf)
+ vmod += ((veax >> 16) & 0xF) << 4;
+ if (vfam == 0xf)
+ vfam += (veax >> 20) & 0xff;
+
+ if ( ( vfam != boot_cpu_data.x86 ) ||
+ (vmod != boot_cpu_data.x86_model) )
+ {
+ dprintk(XENLOG_WARNING,
+ "No vmce for different virtual family/model cpuid\n");
+ no_vmce = 1;
+ }
+ break;
+ }
+ }
+
+ if (no_vmce)
+ return 0;
+
+ /* Guest has different MCE ctl value setting */
+ if (mca_ctl_conflict(bank, d))
+ {
+ dprintk(XENLOG_WARNING,
+ "No vmce, guest has different mca control setting\n");
+ return 0;
+ }
+
+ return 1;
+}
+
+int is_vmce_ready(struct mcinfo_bank *bank, struct domain *d)
+{
+ if ( d == dom0)
+ return dom0_vmce_enabled();
+
+ /* No vMCE to HVM guest now */
+ if ( is_hvm_domain(d) )
+ return is_hvm_vmce_ready(bank, d);
+
+ return 0;
+}