return vpmu_do_interrupt(regs);
}
-static void vmx_set_uc_mode(struct vcpu *v)
-{
- if ( paging_mode_hap(v->domain) )
- ept_change_entry_emt_with_range(
- v->domain, 0, p2m_get_hostp2m(v->domain)->max_mapped_pfn);
- hvm_asid_flush_vcpu(v);
-}
-
static void vmx_set_info_guest(struct vcpu *v)
{
unsigned long intr_shadow;
.msr_read_intercept = vmx_msr_read_intercept,
.msr_write_intercept = vmx_msr_write_intercept,
.invlpg_intercept = vmx_invlpg_intercept,
- .set_uc_mode = vmx_set_uc_mode,
.set_info_guest = vmx_set_info_guest,
.set_rdtsc_exiting = vmx_set_rdtsc_exiting
};
return mfn;
}
-/* WARNING: Only caller doesn't care about PoD pages. So this function will
- * always return 0 for PoD pages, not populate them. If that becomes necessary,
- * pass a p2m_query_t type along to distinguish. */
-static ept_entry_t ept_get_entry_content(struct p2m_domain *p2m,
- unsigned long gfn, int *level)
-{
- ept_entry_t *table = map_domain_page(ept_get_asr(p2m->domain));
- unsigned long gfn_remainder = gfn;
- ept_entry_t *ept_entry;
- ept_entry_t content = { .epte = 0 };
- u32 index;
- int i;
- int ret=0;
-
- /* This pfn is higher than the highest the p2m map currently holds */
- if ( gfn > p2m->max_mapped_pfn )
- goto out;
-
- for ( i = ept_get_wl(p2m->domain); i > 0; i-- )
- {
- ret = ept_next_level(p2m, 1, &table, &gfn_remainder, i);
- if ( !ret || ret == GUEST_TABLE_POD_PAGE )
- goto out;
- else if ( ret == GUEST_TABLE_SUPER_PAGE )
- break;
- }
-
- index = gfn_remainder >> (i * EPT_TABLE_ORDER);
- ept_entry = table + index;
- content = *ept_entry;
- *level = i;
-
- out:
- unmap_domain_page(table);
- return content;
-}
-
void ept_walk_table(struct domain *d, unsigned long gfn)
{
struct p2m_domain *p2m = p2m_get_hostp2m(d);
return ept_get_entry(p2m, gfn, t, a, q);
}
-/*
- * To test if the new emt type is the same with old,
- * return 1 to not to reset ept entry.
- */
-static int need_modify_ept_entry(struct p2m_domain *p2m, unsigned long gfn,
- mfn_t mfn, uint8_t o_ipat, uint8_t o_emt,
- p2m_type_t p2mt)
-{
- uint8_t ipat;
- uint8_t emt;
- bool_t direct_mmio = (p2mt == p2m_mmio_direct);
-
- emt = epte_get_entry_emt(p2m->domain, gfn, mfn, &ipat, direct_mmio);
-
- if ( (emt == o_emt) && (ipat == o_ipat) )
- return 0;
-
- return 1;
-}
-
-void ept_change_entry_emt_with_range(struct domain *d,
- unsigned long start_gfn,
- unsigned long end_gfn)
-{
- unsigned long gfn;
- ept_entry_t e;
- mfn_t mfn;
- int order = 0;
- struct p2m_domain *p2m = p2m_get_hostp2m(d);
-
- p2m_lock(p2m);
- for ( gfn = start_gfn; gfn <= end_gfn; gfn++ )
- {
- int level = 0;
- uint64_t trunk = 0;
-
- e = ept_get_entry_content(p2m, gfn, &level);
- if ( !p2m_has_emt(e.sa_p2mt) )
- continue;
-
- order = 0;
- mfn = _mfn(e.mfn);
-
- if ( is_epte_superpage(&e) )
- {
- while ( level )
- {
- trunk = (1UL << (level * EPT_TABLE_ORDER)) - 1;
- if ( !(gfn & trunk) && (gfn + trunk <= end_gfn) )
- {
- /* gfn assigned with 2M or 1G, and the end covers more than
- * the super page areas.
- * Set emt for super page.
- */
- order = level * EPT_TABLE_ORDER;
- if ( need_modify_ept_entry(p2m, gfn, mfn,
- e.ipat, e.emt, e.sa_p2mt) )
- ept_set_entry(p2m, gfn, mfn, order, e.sa_p2mt, e.access);
- gfn += trunk;
- break;
- }
- level--;
- }
- }
- else /* gfn assigned with 4k */
- {
- if ( need_modify_ept_entry(p2m, gfn, mfn, e.ipat, e.emt, e.sa_p2mt) )
- ept_set_entry(p2m, gfn, mfn, order, e.sa_p2mt, e.access);
- }
- }
- p2m_unlock(p2m);
-}
-
/*
* Walk the whole p2m table, changing any entries of the old type
* to the new type. This is used in hardware-assisted paging to