n1vmcb->exit_int_info.raw = 0;
/* Cleanbits */
- n1vmcb->cleanbits.bytes = 0;
+ n1vmcb->cleanbits.raw = 0;
return 0;
}
struct nestedvcpu *nv = &vcpu_nestedhvm(v);
struct nestedsvm *svm = &vcpu_nestedsvm(v);
struct vmcb_struct *ns_vmcb, *n1vmcb, *n2vmcb;
- bool_t vcleanbits_valid;
+ vmcbcleanbits_t clean = {};
int rc;
uint64_t cr0;
ASSERT(n2vmcb != NULL);
/* Check if virtual VMCB cleanbits are valid */
- vcleanbits_valid = 1;
- if ( svm->ns_ovvmcb_pa == INVALID_PADDR )
- vcleanbits_valid = 0;
- if (svm->ns_ovvmcb_pa != nv->nv_vvmcxaddr)
- vcleanbits_valid = 0;
-
-#define vcleanbit_set(_name) \
- (vcleanbits_valid && ns_vmcb->cleanbits.fields._name)
+ if ( svm->ns_ovvmcb_pa != INVALID_PADDR &&
+ svm->ns_ovvmcb_pa == nv->nv_vvmcxaddr )
+ clean = ns_vmcb->cleanbits;
/* Enable l2 guest intercepts */
- if (!vcleanbit_set(intercepts)) {
+ if ( !clean.intercepts )
+ {
svm->ns_cr_intercepts = ns_vmcb->_cr_intercepts;
svm->ns_dr_intercepts = ns_vmcb->_dr_intercepts;
svm->ns_exception_intercepts = ns_vmcb->_exception_intercepts;
n2vmcb->_tsc_offset = n1vmcb->_tsc_offset + ns_vmcb->_tsc_offset;
/* Nested IO permission bitmaps */
- rc = nsvm_vmrun_permissionmap(v, vcleanbit_set(iopm));
+ rc = nsvm_vmrun_permissionmap(v, clean.iopm);
if (rc)
return rc;
n2vmcb->tlb_control = ns_vmcb->tlb_control;
/* Virtual Interrupts */
- if (!vcleanbit_set(tpr)) {
+ if ( !clean.tpr )
+ {
n2vmcb->_vintr = ns_vmcb->_vintr;
n2vmcb->_vintr.fields.intr_masking = 1;
}
n2vmcb->event_inj = ns_vmcb->event_inj;
/* LBR and other virtualization */
- if (!vcleanbit_set(lbr)) {
+ if ( !clean.lbr )
svm->ns_virt_ext = ns_vmcb->virt_ext;
- }
+
n2vmcb->virt_ext.bytes =
n1vmcb->virt_ext.bytes | ns_vmcb->virt_ext.bytes;
*/
/* Segments */
- if (!vcleanbit_set(seg)) {
+ if ( !clean.seg )
+ {
n2vmcb->es = ns_vmcb->es;
n2vmcb->cs = ns_vmcb->cs;
n2vmcb->ss = ns_vmcb->ss;
/* CPL */
n2vmcb->_cpl = ns_vmcb->_cpl;
}
- if (!vcleanbit_set(dt)) {
+ if ( !clean.dt )
+ {
n2vmcb->gdtr = ns_vmcb->gdtr;
n2vmcb->idtr = ns_vmcb->idtr;
}
}
/* DRn */
- if (!vcleanbit_set(dr)) {
+ if ( !clean.dr )
+ {
n2vmcb->_dr7 = ns_vmcb->_dr7;
n2vmcb->_dr6 = ns_vmcb->_dr6;
}
*/
/* PAT */
- if (!vcleanbit_set(np)) {
+ if ( !clean.np )
n2vmcb->_g_pat = ns_vmcb->_g_pat;
- }
- if (!vcleanbit_set(lbr)) {
+ if ( !clean.lbr )
+ {
/* Debug Control MSR */
n2vmcb->_debugctlmsr = ns_vmcb->_debugctlmsr;
}
/* Cleanbits */
- n2vmcb->cleanbits.bytes = 0;
+ n2vmcb->cleanbits.raw = 0;
rc = svm_vmcb_isvalid(__func__, ns_vmcb, v, true);
if (rc) {
regs->rsp = ns_vmcb->rsp;
regs->rflags = ns_vmcb->rflags;
-#undef vcleanbit_set
return 0;
}
else
vmcb->event_inj.raw = 0;
- vmcb->cleanbits.bytes = 0;
+ vmcb->cleanbits.raw = 0;
paging_update_paging_modes(v);
return 0;
case x86_seg_ds:
case x86_seg_es:
case x86_seg_ss: /* cpl */
- vmcb->cleanbits.fields.seg = 0;
+ vmcb->cleanbits.seg = false;
break;
case x86_seg_gdtr:
case x86_seg_idtr:
- vmcb->cleanbits.fields.dt = 0;
+ vmcb->cleanbits.dt = false;
break;
case x86_seg_fs:
svm_restore_dr(v);
svm_vmsave_pa(per_cpu(host_vmcb, cpu));
- vmcb->cleanbits.bytes = 0;
+ vmcb->cleanbits.raw = 0;
svm_tsc_ratio_load(v);
if ( cpu_has_msr_tsc_aux )
hvm_maybe_deassert_evtchn_irq();
- vmcb->cleanbits.bytes = cpu_has_svm_cleanbits ? ~0u : 0u;
+ vmcb->cleanbits.raw = ~0u;
/* Event delivery caused this intercept? Queue for redelivery. */
if ( unlikely(vmcb->exit_int_info.v) &&
printk("KernGSBase = 0x%016"PRIx64" PAT = 0x%016"PRIx64"\n",
vmcb->kerngsbase, vmcb_get_g_pat(vmcb));
printk("H_CR3 = 0x%016"PRIx64" CleanBits = %#x\n",
- vmcb_get_h_cr3(vmcb), vmcb->cleanbits.bytes);
+ vmcb_get_h_cr3(vmcb), vmcb->cleanbits.raw);
/* print out all the selectors */
printk(" sel attr limit base\n");
typedef union
{
- uint32_t bytes;
- struct
- {
- /* cr_intercepts, dr_intercepts, exception_intercepts,
- * general{1,2}_intercepts, pause_filter_count, tsc_offset */
- uint32_t intercepts: 1;
- /* iopm_base_pa, msrpm_base_pa */
- uint32_t iopm: 1;
- /* guest_asid */
- uint32_t asid: 1;
- /* vintr */
- uint32_t tpr: 1;
- /* np_enable, h_cr3, g_pat */
- uint32_t np: 1;
- /* cr0, cr3, cr4, efer */
- uint32_t cr: 1;
- /* dr6, dr7 */
- uint32_t dr: 1;
- /* gdtr, idtr */
- uint32_t dt: 1;
- /* cs, ds, es, ss, cpl */
- uint32_t seg: 1;
- /* cr2 */
- uint32_t cr2: 1;
- /* debugctlmsr, last{branch,int}{to,from}ip */
- uint32_t lbr: 1;
- uint32_t resv: 21;
- } fields;
+ struct {
+ bool intercepts:1; /* 0: cr/dr/exception/general intercepts,
+ * pause_filter_count, tsc_offset */
+ bool iopm:1; /* 1: iopm_base_pa, msrpm_base_pa */
+ bool asid:1; /* 2: guest_asid */
+ bool tpr:1; /* 3: vintr */
+ bool np:1; /* 4: np_enable, h_cr3, g_pat */
+ bool cr:1; /* 5: cr0, cr3, cr4, efer */
+ bool dr:1; /* 6: dr6, dr7 */
+ bool dt:1; /* 7: gdtr, idtr */
+ bool seg:1; /* 8: cs, ds, es, ss, cpl */
+ bool cr2:1; /* 9: cr2 */
+ bool lbr:1; /* 10: debugctlmsr, last{branch,int}{to,from}ip */
+ };
+ uint32_t raw;
} vmcbcleanbits_t;
#define IOPM_SIZE (12 * 1024)
type value) \
{ \
vmcb->_ ## name = value; \
- vmcb->cleanbits.fields.cleanbit = 0; \
+ vmcb->cleanbits.cleanbit = false; \
} \
static inline type \
vmcb_get_ ## name(const struct vmcb_struct *vmcb) \