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

Re: [PATCH v4 02/10] x86/mm: Avoid hard-coding PAT in get_page_from_l1e()



On Thu, Dec 15, 2022 at 06:57:44PM -0500, Demi Marie Obenour wrote:
> get_page_from_l1e() relied on Xen's choice of PAT, which is brittle in
> the face of future PAT changes.  Instead, compute the actual cacheability
> used by the CPU and switch on that, as this will work no matter what PAT
> Xen uses.
> 
> No functional change intended.
> 
> Signed-off-by: Demi Marie Obenour <demi@xxxxxxxxxxxxxxxxxxxxxx>
> ---
> Changes since v3:
> - Compute and use the actual cacheability as seen by the processor.
> 
> Changes since v2:
> - Improve commit message.
> ---
>  xen/arch/x86/include/asm/processor.h |  8 ++++++++
>  xen/arch/x86/mm.c                    | 19 +++++++++++++------
>  2 files changed, 21 insertions(+), 6 deletions(-)
> 
> diff --git a/xen/arch/x86/include/asm/processor.h 
> b/xen/arch/x86/include/asm/processor.h
> index 
> 8e2816fae9b97bd4e153a30cc3802971fe0355af..c3205ed9e10c1a57d23c5ecead66bebd82d87d06
>  100644
> --- a/xen/arch/x86/include/asm/processor.h
> +++ b/xen/arch/x86/include/asm/processor.h
> @@ -100,6 +100,14 @@
>  
>  #ifndef __ASSEMBLY__
>  
> +/* Convert from PAT/PCD/PWT embedded in PTE flags to actual cacheability 
> value */
> +static inline unsigned int pte_flags_to_cacheability(unsigned int flags)
> +{
> +    unsigned int pat_shift = ((flags & _PAGE_PAT) >> 2) |
> +                             (flags & (_PAGE_PCD|_PAGE_PWT));

This could also be written as

    unsigned int pat_shift = pte_flags_to_cacheattr(flags) << 3;

which might be easiser to read.

> +    return 0xFF & (XEN_MSR_PAT >> pat_shift);
> +}
> +
>  struct domain;
>  struct vcpu;
>  
> diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
> index 
> 78b1972e4170cacccc9c37c6e64e76e66a7da87f..802073a01c5cf4dc3cf1d58d28ea4d4e9e8149c7
>  100644
> --- a/xen/arch/x86/mm.c
> +++ b/xen/arch/x86/mm.c
> @@ -959,15 +959,22 @@ get_page_from_l1e(
>              flip = _PAGE_RW;
>          }
>  
> -        switch ( l1f & PAGE_CACHE_ATTRS )
> +        /* Force cacheable memtypes to UC */
> +        switch ( pte_flags_to_cacheability(l1f) )
>          {
> -        case 0: /* WB */
> -            flip |= _PAGE_PWT | _PAGE_PCD;
> +        case X86_MT_UC:
> +        case X86_MT_UCM:
> +        case X86_MT_WC:
> +            /* not cached */
>              break;
> -        case _PAGE_PWT: /* WT */
> -        case _PAGE_PWT | _PAGE_PAT: /* WP */
> -            flip |= _PAGE_PCD | (l1f & _PAGE_PAT);
> +        case X86_MT_WB:
> +        case X86_MT_WT:
> +        case X86_MT_WP:
> +            /* cacheable, force to UC */
> +            flip |= (l1f & PAGE_CACHE_ATTRS) ^ _PAGE_UC;
>              break;
> +        default:
> +            BUG();

Question for future reference: is this an appropriate use of BUG()?  The
default case is clearly unreachable, and I actually considered using
unreachable() here, but this isn’t performance-critical code from what I
can tell.  If execution *does* reach here something is seriously wrong.
-- 
Sincerely,
Demi Marie Obenour (she/her/hers)
Invisible Things Lab

Attachment: signature.asc
Description: PGP signature


 


Rackspace

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