From: Razvan Cojocaru Date: Thu, 15 Nov 2018 12:35:08 +0000 (+0100) Subject: x86/altp2m: propagate ept.ad changes to all active altp2ms X-Git-Tag: archive/raspbian/4.14.0+80-gd101b417b7-1+rpi1^2~63^2~2922 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=303cee10a677dd8c5c130e50ddad6517c12e0276;p=xen.git x86/altp2m: propagate ept.ad changes to all active altp2ms This patch is a pre-requisite for fixing the logdirty VGA issue (display freezes when switching to a new altp2m view early in a domain's lifetime). The new ept_set_ad_sync() function has been added to update all active altp2ms' ept.ad. New altp2ms will inherit the hostp2m's ept.ad value. The p2m_{en,dis}able_hardware_log_dirty() hostp2m locking has been moved to the new ept_{en,dis}able_hardware_log_dirty() functions as part of the code refactoring, while locks for the individual altp2ms are taken in ept_set_ad_sync() (called by ept_{en,dis}able_pml()). Suggested-by: George Dunlap Signed-off-by: Razvan Cojocaru Tested-by: Tamas K Lengyel Acked-by: George Dunlap Reviewed-by: Kevin Tian --- diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c index 407e299e50..fabcd06f07 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 @@ -1222,6 +1223,34 @@ static void ept_tlb_flush(struct p2m_domain *p2m) ept_sync_domain_mask(p2m, p2m->domain->dirty_cpumask); } +static void ept_set_ad_sync(struct domain *d, bool value) +{ + struct p2m_domain *hostp2m = p2m_get_hostp2m(d); + + ASSERT(p2m_locked_by_me(hostp2m)); + + hostp2m->ept.ad = value; + + if ( unlikely(altp2m_active(d)) ) + { + unsigned int i; + + for ( i = 0; i < MAX_ALTP2M; i++ ) + { + struct p2m_domain *p2m; + + if ( d->arch.altp2m_eptp[i] == mfn_x(INVALID_MFN) ) + continue; + + p2m = d->arch.altp2m_p2m[i]; + + p2m_lock(p2m); + p2m->ept.ad = value; + p2m_unlock(p2m); + } + } +} + static void ept_enable_pml(struct p2m_domain *p2m) { /* Domain must have been paused */ @@ -1236,7 +1265,7 @@ static void ept_enable_pml(struct p2m_domain *p2m) return; /* Enable EPT A/D bit for PML */ - p2m->ept.ad = 1; + ept_set_ad_sync(p2m->domain, true); vmx_domain_update_eptp(p2m->domain); } @@ -1248,10 +1277,28 @@ static void ept_disable_pml(struct p2m_domain *p2m) vmx_domain_disable_pml(p2m->domain); /* Disable EPT A/D bit */ - p2m->ept.ad = 0; + ept_set_ad_sync(p2m->domain, false); vmx_domain_update_eptp(p2m->domain); } +static void ept_enable_hardware_log_dirty(struct p2m_domain *p2m) +{ + struct p2m_domain *hostp2m = p2m_get_hostp2m(p2m->domain); + + p2m_lock(hostp2m); + ept_enable_pml(hostp2m); + p2m_unlock(hostp2m); +} + +static void ept_disable_hardware_log_dirty(struct p2m_domain *p2m) +{ + struct p2m_domain *hostp2m = p2m_get_hostp2m(p2m->domain); + + p2m_lock(hostp2m); + ept_disable_pml(hostp2m); + p2m_unlock(hostp2m); +} + static void ept_flush_pml_buffers(struct p2m_domain *p2m) { /* Domain must have been paused */ @@ -1281,8 +1328,8 @@ int ept_p2m_init(struct p2m_domain *p2m) if ( cpu_has_vmx_pml ) { - p2m->enable_hardware_log_dirty = ept_enable_pml; - p2m->disable_hardware_log_dirty = ept_disable_pml; + p2m->enable_hardware_log_dirty = ept_enable_hardware_log_dirty; + p2m->disable_hardware_log_dirty = ept_disable_hardware_log_dirty; p2m->flush_hardware_cached_dirty = ept_flush_pml_buffers; } @@ -1390,8 +1437,10 @@ 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->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 4bdc5e34e0..6a1abb6df5 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -360,11 +360,7 @@ void p2m_enable_hardware_log_dirty(struct domain *d) struct p2m_domain *p2m = p2m_get_hostp2m(d); if ( p2m->enable_hardware_log_dirty ) - { - p2m_lock(p2m); p2m->enable_hardware_log_dirty(p2m); - p2m_unlock(p2m); - } } void p2m_disable_hardware_log_dirty(struct domain *d) @@ -372,11 +368,7 @@ void p2m_disable_hardware_log_dirty(struct domain *d) struct p2m_domain *p2m = p2m_get_hostp2m(d); if ( p2m->disable_hardware_log_dirty ) - { - p2m_lock(p2m); p2m->disable_hardware_log_dirty(p2m); - p2m_unlock(p2m); - } } void p2m_flush_hardware_cached_dirty(struct domain *d)