VMEXIT_INVALID = -1
};
+enum clean_bits {
+ CLEAN_BITS_I = 1 << 0,
+ CLEAN_BITS_IOPM = 1 << 1,
+ CLEAN_BITS_ASID = 1 << 2,
+ CLEAN_BITS_TPR = 1 << 3,
+ CLEAN_BITS_NP = 1 << 4,
+ CLEAN_BITS_CRX = 1 << 5,
+ CLEAN_BITS_DRX = 1 << 6,
+ CLEAN_BITS_DT = 1 << 7,
+ CLEAN_BITS_SEG = 1 << 8,
+ CLEAN_BITS_CR2 = 1 << 9,
+ CLEAN_BITS_LBR = 1 << 10,
+ CLEAN_BITS_AVIC = 1 << 11
+};
+
typedef u64 vintr_t;
typedef u64 eventinj_t;
typedef u64 lbrctrl_t;
eventinj_t eventinj; /* offset 0xA8 */
u64 n_cr3; /* offset 0xB0 */
lbrctrl_t lbr_control; /* offset 0xB8 */
- u64 res09; /* offset 0xC0 */
+ u64 clean_bits; /* offset 0xC0 */
u64 nextrip; /* offset 0xC8 */
u8 bytes_fetched; /* offset 0xD0 */
u8 guest_bytes[15];
/* TODO: Setup AVIC */
+ /* Explicitly mark all of the state as new */
+ vmcb->clean_bits = 0;
+
return vcpu_set_cell_config(cpu_data->cell, vmcb);
}
vmcb->dr7 = 0x00000400;
+ /* Almost all of the guest state changed */
+ vmcb->clean_bits = 0;
+
ok &= vcpu_set_cell_config(cpu_data->cell, vmcb);
/* This is always false, but to be consistent with vmx.c... */
vcpu_tlb_flush();
vmcb->efer = efer;
+ vmcb->clean_bits &= ~CLEAN_BITS_CRX;
}
bool vcpu_get_guest_paging_structs(struct guest_paging_structures *pg_structs)
vmcb->cr0 = val & SVM_CR0_CLEARED_BITS;
if (val & X86_CR0_PG)
update_efer(cpu_data);
+ vmcb->clean_bits &= ~CLEAN_BITS_CRX;
out:
return ok;
if ((efer ^ vmcb->efer) & (EFER_LME | EFER_NXE))
vcpu_tlb_flush();
vmcb->efer = efer;
+ vmcb->clean_bits &= ~CLEAN_BITS_CRX;
goto out;
}
write_msr(MSR_GS_BASE, (unsigned long)cpu_data);
cpu_data->stats[JAILHOUSE_CPU_STAT_VMEXITS_TOTAL]++;
+ /*
+ * All guest state is marked unmodified; individual handlers must clear
+ * the bits as needed.
+ */
+ vmcb->clean_bits = 0xffffffff;
switch (vmcb->exitcode) {
case VMEXIT_INVALID:
struct vmcb *vmcb = &cpu_data->vmcb;
vcpu_reset(cpu_data, APIC_BSP_PSEUDO_SIPI);
+ /* No need to clear VMCB Clean bit: vcpu_reset() already does this */
vmcb->n_cr3 = paging_hvirt2phys(parked_mode_npt);
vcpu_tlb_flush();