[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2] x86/ept: limit calls to memory_type_changed()


  • To: Jan Beulich <jbeulich@xxxxxxxx>
  • From: Roger Pau Monné <roger.pau@xxxxxxxxxx>
  • Date: Wed, 28 Sep 2022 12:08:17 +0200
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=citrix.com; dmarc=pass action=none header.from=citrix.com; dkim=pass header.d=citrix.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=+ePhxvt2zlcSYriCgVKyNQZELQ9eTrq7ZD5C+Vj2xrQ=; b=AD/al+wpka6LWjT17fTjqrZ8rbLqLDm0D7CxyqtA10ksSwVXbxHAA1T7fOHbW2m42Xxi8LoNazmSTz4OjnmC00vdSvOqTGpO8K7zwHukuE9T3dPywLFBzE40BwXBjsQvnIDPDPebZ/Zk/AXuJDoR6KFsCFkwF4wjqbQEeYBDfGpz8paVb4M3jncDvwkJkFALUEb2FYR0RNY4oarr3QzA8LkdeTntl5xfp19HbCoGnpc0ldxSSQlstr/nS6T+zetU0JgcAv5Db0MQsfWH5gHcU+ffijKTZBThnWKpzGSx0XcrEpUyv64ho1xNauS9wOlMLaF+ynl2PR1KgRbgIynK/Q==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ZVyc6YZwEH2n+QxqjI9Dg49MTiOG+XmCYqXXAwDKWCeT8Uxxj65qxfsdy+zziEjkB/ttvryLna78J96X2WsMwinkMDCWVOi1cBwa70YDOS9uh//nJKAg6sjppeOvJlfWoDLLHU3W7BiVGQutDxzVRnAhklgFwvWizjV+rWhqcjqlaSOKtlbpsC5F0Qv/jt+cAmm33m9CcWwAQSdpJNAV1ezW9J87pnjazAeK5SJectPp2bd3HpgLi2pGpEEs/AZK90yK9q3L2DlfbL0oHCFcHrDQrJ77oZZQ7n6rGjx06KJxg3m6/LjQ4bWAgQdFaU5t+aBFqOHsPAzTuPAGOobjjw==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=citrix.com;
  • Cc: Stefano Stabellini <sstabellini@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Bertrand Marquis <bertrand.marquis@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>, Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, George Dunlap <george.dunlap@xxxxxxxxxx>, Wei Liu <wl@xxxxxxx>, Jun Nakajima <jun.nakajima@xxxxxxxxx>, Kevin Tian <kevin.tian@xxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxxx
  • Delivery-date: Wed, 28 Sep 2022 10:08:39 +0000
  • Ironport-data: A9a23:ahcgSKrqNsbxjjBhE2jGiPR9J6heBmK0ZBIvgKrLsJaIsI4StFCzt garIBnSOquIYGWnc4gjOdzj9BwD6pXXyt8wHgs9rS0zHiNA8JuZCYyVIHmrMnLJJKUvbq7FA +Y2MYCccZ9uHhcwgj/3b9ANeFEljfngqoLUUbKCYGYpLeNdYH9JoQp5nOIkiZJfj9G8Agec0 fv/uMSaM1K+s9JOGjt8B5mr9VU+55wehBtC5gZkPaER7AeH/5UoJMl3yZ+ZfiOQrrZ8RoZWd 86bpJml82XQ+QsaC9/Nut4XpWVTH9Y+lSDX4pZnc/DKbipq/0Te4Y5iXBYoUm9Fii3hojxE4 I4lWapc6+seFvakdOw1C3G0GszlVEFM0OevzXOX6aR/w6BaGpdFLjoH4EweZOUlFuhL7W5m3 OcbNTIvMBW6mc226YuQSM5yuJoZI5y+VG8fkikIITDxK98DGcyGaYOaoNhS0XE3m9xEGuvYa 4wBcz1zYR/cYhpJfFAKFJY5m+TujX76G9FagAvN+exrvC6MkEotiNABM/KMEjCObd9SkUuC4 HrP4kzyAw0ANczZwj2Amp6prr+WwHuhBt9KfFG+3sBjv0yW2E8UMyEPWAuEr6GdtEKgavsKf iT4/QJr98De7neDTNPwQhm5q36spQMHVpxbFOhSwBqW1qPe7gKdB24FZj1MctorsIkxXzNC/ l2Um9LkAxR/vbvTTmiSnp+eoCmuIyETISkHbDUdUAoey9D5pcc4iRenZuhkFKm5n9jkAwbay jqBrDU9r7gLhMtN3KK+lXjYhxq8q56PSRQ6ji3VQ2Tj6Ap6bYykYoWA6F7H4PIGJ4GcJnGCs WYFnY6C7ekIJZCLiCGJBu4KGdmB9/uDdTHRn1NrN50g7Ci2vW6ue5hK5zNzL1svNdwLEQIFe 2fWsAJVoZVVbH2jaPcrZ5rrU5hyi6/9Cd7iS/bYKMJUZYR8fxOG+ycoYlOM22fqkw4nlqRX1 YqnTPtAxE0yUcxPpAdajc9HuVP37kjSHV/ueK0=
  • Ironport-hdrordr: A9a23:fy2Tiqm35Eeul/yhflUCWPAVNF7pDfOwimdD5ihNYBxZY6Wkfp +V8cjzhCWftN9OYhodcLC7V5Voj0mskKKdxbNhRYtKPTOWwVdASbsP0WKM+V3d8kHFh41gPO JbAtND4b7LfCRHZKTBkW6F+r8bqbHokZxAx92uqUuFJTsaFp2IhD0JbjpzfHcGJjWvUvECZe ChD4d81kydkTN9VLXKOlA1G8z44/HbnpPvZhALQzYh9Qm1lDutrJr3CQKR0BsyWy5Ghe5Kyx mMryXJooGY992rwB7V0GHeq7xQhdva09NGQOiBkNIcJDnAghuhIK5hR7qBljYop/zH0idirP D85zMbe+hj4XLYeW+45TPrxgnbyT4rr0TvzFeJ6EGT1PDRdXYfMY5slIhZehzW5w4Lp9dnyp 9G2Gqfqt5+EQ7AtD6V3amFazha0m6P5VYym+8aiHJSFaEEbqVKkIAZ9ERJVL8dASPB7pw9Gu UGNrCQ2B9vSyLVU5nlhBgv/DT1NU5DXituA3Jy8PB96gIm00yQlCAjtY8idnRpzuNOd3AL3Z WHDk1SrsA+ciYnV9MDOA4/e7rINoXse2O5DIvAGyWRKIg3f1TwlrXQ3JIZoMmXRb1g9upApH 2GaiISiVIP
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On Wed, Sep 28, 2022 at 10:01:26AM +0200, Jan Beulich wrote:
> On 27.09.2022 17:39, Roger Pau Monne wrote:
> > memory_type_changed() is currently only implemented for Intel EPT, and
> > results in the invalidation of EMT attributes on all the entries in
> > the EPT page tables.  Such invalidation causes EPT_MISCONFIG vmexits
> > when the guest tries to access any gfns for the first time, which
> > results in the recalculation of the EMT for the accessed page.  The
> > vmexit and the recalculations are expensive, and as such should be
> > avoided when possible.
> > 
> > Remove the call to memory_type_changed() from
> > XEN_DOMCTL_memory_mapping: there are no modifications of the
> > iomem_caps ranges anymore that could alter the return of
> > cache_flush_permitted() from that domctl.
> > 
> > Encapsulate calls to memory_type_changed() resulting from changes to
> > the domain iomem_caps or ioport_caps ranges in the helpers themselves
> > (io{ports,mem}_{permit,deny}_access()), and add a note in
> > epte_get_entry_emt() to remind that changes to the logic there likely
> > need to be propagaed to the IO capabilities helpers.
> > 
> > Note changes to the IO ports or memory ranges are not very common
> > during guest runtime, but Citrix Hypervisor has an use case for them
> > related to device passthrough.
> > 
> > Some Arm callers (implementations of the iomem_deny_access function
> > pointer field in gic_hw_operations struct) pass a const domain pointer
> > to iomem_deny_access(), which is questionable.  It works because
> > the rangeset is allocated separately from the domain struct, but
> > conceptually seems wrong to me, as passing a const pointer would imply
> > no changes to the domain data, and denying iomem accesses does change
> > the domain data.  Fix this by removing the const attribute from the
> > affected functions and call chain.
> 
> Personally I think this adjustment would better be a separate, prereq
> change.

Right - I was about to split it but didn't want to go through the
hassle if the approach didn't end up being well received.

Do you think placing the calls to memory_type_changed() inside the
{permit,deny}_,access is acceptable?

> > --- a/xen/include/xen/iocap.h
> > +++ b/xen/include/xen/iocap.h
> > @@ -7,13 +7,43 @@
> >  #ifndef __XEN_IOCAP_H__
> >  #define __XEN_IOCAP_H__
> >  
> > +#include <xen/sched.h>
> >  #include <xen/rangeset.h>
> >  #include <asm/iocap.h>
> > +#include <asm/p2m.h>
> 
> That's heavy dependencies you're adding. I wonder if the functions
> wouldn't better become out-of-line ones (but see also below).
> 
> > +static inline int iomem_permit_access(struct domain *d, unsigned long s,
> > +                                      unsigned long e)
> > +{
> > +    bool flush = cache_flush_permitted(d);
> > +    int ret = rangeset_add_range(d->iomem_caps, s, e);
> > +
> > +    if ( !ret && !is_iommu_enabled(d) && !flush )
> > +        /*
> > +         * Only flush if the range(s) are empty before this addition and
> > +         * IOMMU is not enabled for the domain, otherwise it makes no
> > +         * difference for effective cache attribute calculation purposes.
> > +         */
> > +        memory_type_changed(d);
> > +
> > +    return ret;
> > +}
> > +static inline int iomem_deny_access(struct domain *d, unsigned long s,
> > +                                    unsigned long e)
> > +{
> > +    int ret = rangeset_remove_range(d->iomem_caps, s, e);
> > +
> > +    if ( !ret && !is_iommu_enabled(d) && !cache_flush_permitted(d) )
> > +        /*
> > +         * Only flush if the range(s) are empty after this removal and
> > +         * IOMMU is not enabled for the domain, otherwise it makes no
> > +         * difference for effective cache attribute calculation purposes.
> > +         */
> > +        memory_type_changed(d);
> > +
> > +    return ret;
> > +}
> 
> I'm surprised Arm's memory_type_changed() is an empty out-of-line function.
> This means the compiler can't eliminate this code (except when using LTO).
> But then cache_flush_permitted() (resolving to rangeset_is_empty()) can't
> be eliminated either, even if memory_type_changed() was. While gcc doc
> doesn't explicitly say that it may help (the talk about repeated invocations
> only), I wonder whether we shouldn't mark rangeset_is_empty() pure. In a
> reduced example that does help (once memory_type_changed() is also an
> inline function) with gcc12 - no call to rangeset_is_empty() remains.

Can look into it, do you want it to be a prereq of this patch?

Thanks, Roger.



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.