diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c index 14b5939..b1df904 100644 --- a/xen/arch/x86/mm/p2m-ept.c +++ b/xen/arch/x86/mm/p2m-ept.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -656,6 +657,9 @@ bool_t ept_handle_misconfig(uint64_t gpa) bool_t spurious; int rc; + if ( altp2m_active(curr->domain) ) + p2m = p2m_get_altp2m(curr); + p2m_lock(p2m); spurious = curr->arch.hvm_vmx.ept_spurious_misconfig; @@ -1209,32 +1213,60 @@ static void ept_tlb_flush(struct p2m_domain *p2m) static void ept_enable_pml(struct p2m_domain *p2m) { + unsigned int i; + struct domain *d = p2m->domain; + /* Domain must have been paused */ - ASSERT(atomic_read(&p2m->domain->pause_count)); + ASSERT(atomic_read(&d->pause_count)); /* * No need to return whether vmx_domain_enable_pml has succeeded, as * ept_p2m_type_to_flags will do the check, and write protection will be * used if PML is not enabled. */ - if ( vmx_domain_enable_pml(p2m->domain) ) + if ( vmx_domain_enable_pml(d) ) return; /* Enable EPT A/D bit for PML */ p2m->ept.ad = 1; - vmx_domain_update_eptp(p2m->domain); + + if ( altp2m_active(d) ) + for ( i = 0; i < MAX_ALTP2M; i++ ) + { + if ( d->arch.altp2m_eptp[i] == mfn_x(INVALID_MFN) ) + continue; + + p2m = d->arch.altp2m_p2m[i]; + p2m->ept.ad = 1; + } + + vmx_domain_update_eptp(d); } static void ept_disable_pml(struct p2m_domain *p2m) { + unsigned int i; + struct domain *d = p2m->domain; + /* Domain must have been paused */ - ASSERT(atomic_read(&p2m->domain->pause_count)); + ASSERT(atomic_read(&d->pause_count)); - vmx_domain_disable_pml(p2m->domain); + vmx_domain_disable_pml(d); /* Disable EPT A/D bit */ p2m->ept.ad = 0; - vmx_domain_update_eptp(p2m->domain); + + if ( altp2m_active(d) ) + for ( i = 0; i < MAX_ALTP2M; i++ ) + { + if ( d->arch.altp2m_eptp[i] == mfn_x(INVALID_MFN) ) + continue; + + p2m = d->arch.altp2m_p2m[i]; + p2m->ept.ad = 0; + } + + vmx_domain_update_eptp(d); } static void ept_flush_pml_buffers(struct p2m_domain *p2m) @@ -1375,8 +1407,16 @@ void setup_ept_dump(void) void p2m_init_altp2m_ept(struct domain *d, unsigned int i) { struct p2m_domain *p2m = d->arch.altp2m_p2m[i]; + struct p2m_domain *hostp2m = p2m_get_hostp2m(d); struct ept_data *ept; + p2m->max_mapped_pfn = hostp2m->max_mapped_pfn; + p2m->default_access = hostp2m->default_access; + p2m->domain = hostp2m->domain; + p2m->logdirty_ranges = hostp2m->logdirty_ranges; + p2m->global_logdirty = hostp2m->global_logdirty; + p2m->ept.ad = hostp2m->ept.ad; + p2m->min_remapped_gfn = gfn_x(INVALID_GFN); p2m->max_remapped_gfn = 0; ept = &p2m->ept; diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index c53cab4..c8f4d8f 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -248,7 +249,6 @@ int p2m_init(struct domain *d) int p2m_is_logdirty_range(struct p2m_domain *p2m, unsigned long start, unsigned long end) { - ASSERT(p2m_is_hostp2m(p2m)); if ( p2m->global_logdirty || rangeset_contains_range(p2m->logdirty_ranges, start, end) ) return 1; @@ -257,11 +257,9 @@ int p2m_is_logdirty_range(struct p2m_domain *p2m, unsigned long start, return 0; } -void p2m_change_entry_type_global(struct domain *d, - p2m_type_t ot, p2m_type_t nt) +static void _p2m_change_entry_type_global(struct p2m_domain *p2m, + p2m_type_t ot, p2m_type_t nt) { - struct p2m_domain *p2m = p2m_get_hostp2m(d); - ASSERT(ot != nt); ASSERT(p2m_is_changeable(ot) && p2m_is_changeable(nt)); @@ -271,6 +269,22 @@ void p2m_change_entry_type_global(struct domain *d, p2m_unlock(p2m); } +void p2m_change_entry_type_global(struct domain *d, + p2m_type_t ot, p2m_type_t nt) +{ + unsigned int i; + + if ( !altp2m_active(d) ) + { + _p2m_change_entry_type_global(p2m_get_hostp2m(d), ot, nt); + return; + } + + for ( i = 0; i < MAX_ALTP2M; i++ ) + if ( d->arch.altp2m_eptp[i] != mfn_x(INVALID_MFN) ) + _p2m_change_entry_type_global(d->arch.altp2m_p2m[i], ot, nt); +} + void p2m_memory_type_changed(struct domain *d) { struct p2m_domain *p2m = p2m_get_hostp2m(d); @@ -964,12 +978,12 @@ int p2m_change_type_one(struct domain *d, unsigned long gfn_l, } /* Modify the p2m type of a range of gfns from ot to nt. */ -void p2m_change_type_range(struct domain *d, - unsigned long start, unsigned long end, - p2m_type_t ot, p2m_type_t nt) +static void _p2m_change_type_range(struct p2m_domain *p2m, + unsigned long start, unsigned long end, + p2m_type_t ot, p2m_type_t nt) { + struct domain *d = p2m->domain; unsigned long gfn = start; - struct p2m_domain *p2m = p2m_get_hostp2m(d); int rc = 0; ASSERT(ot != nt); @@ -1022,6 +1036,23 @@ void p2m_change_type_range(struct domain *d, p2m_unlock(p2m); } +void p2m_change_type_range(struct domain *d, + unsigned long start, unsigned long end, + p2m_type_t ot, p2m_type_t nt) +{ + unsigned int i; + + if ( !altp2m_active(d) ) + { + _p2m_change_type_range(p2m_get_hostp2m(d), start, end, ot, nt); + return; + } + + for ( i = 0; i < MAX_ALTP2M; i++ ) + if ( d->arch.altp2m_eptp[i] != mfn_x(INVALID_MFN) ) + _p2m_change_type_range(d->arch.altp2m_p2m[i], start, end, ot, nt); +} + /* * Finish p2m type change for gfns which are marked as need_recalc in a range. * Returns: 0/1 for success, negative for failure