is_hardware_domain(d));
}
+static uint64_t guest_efer(const struct domain *d)
+{
+ uint64_t val;
+
+ /* Hide unknown bits, and unconditionally hide SVME from guests. */
+ val = read_efer() & EFER_KNOWN_MASK & ~EFER_SVME;
+ /*
+ * Hide the 64-bit features from 32-bit guests. SCE has
+ * vendor-dependent behaviour.
+ */
+ if ( is_pv_32bit_domain(d) )
+ val &= ~(EFER_LME | EFER_LMA |
+ (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL
+ ? EFER_SCE : 0));
+ return val;
+}
+
static int read_msr(unsigned int reg, uint64_t *val,
struct x86_emulate_ctxt *ctxt)
{
return X86EMUL_OKAY;
case MSR_EFER:
- /* Hide unknown bits, and unconditionally hide SVME from guests. */
- *val = read_efer() & EFER_KNOWN_MASK & ~EFER_SVME;
- /*
- * Hide the 64-bit features from 32-bit guests. SCE has
- * vendor-dependent behaviour.
- */
- if ( is_pv_32bit_domain(currd) )
- *val &= ~(EFER_LME | EFER_LMA |
- (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL
- ? EFER_SCE : 0));
+ *val = guest_efer(currd);
return X86EMUL_OKAY;
case MSR_K7_FID_VID_CTL:
curr->arch.pv.gs_base_user = val;
return X86EMUL_OKAY;
+ case MSR_EFER:
+ /*
+ * Reject writes which change the value, but Linux depends on being
+ * able to write back the current value.
+ */
+ if ( val != guest_efer(currd) )
+ break;
+ return X86EMUL_OKAY;
+
case MSR_K7_FID_VID_STATUS:
case MSR_K7_FID_VID_CTL:
case MSR_K8_PSTATE_LIMIT: