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

Re: [PATCH] x86/AMD: expose SYSCFG, TOM, and TOM2 to Dom0


  • To: Jan Beulich <jbeulich@xxxxxxxx>
  • From: Roger Pau Monné <roger.pau@xxxxxxxxxx>
  • Date: Thu, 27 May 2021 10:33:32 +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-SenderADCheck; bh=jHN9epAEuXEjx8aqD1gWoOXLpmP0sYTmOEO7deqJ1oA=; b=cHQuxQk7m8tXlXfNQLUo/haEVKol6RGnATV44r2koQMAvayjJRSgeAHin24tNhPiSaYma/0fWKYbilgxxhf3mYb8qeh8iMxdcabk4jtOwkDpMC0KkhSIZPmQEDIYVqZmtDVwPGKjfWL17uPpAHN4hmrMQbw7MKvu7UVl8eW9bGVdihqbCdFtgtBvTQuFcoFNbOjy/VrwG5c13r3QIlyoVwG5BoBEc4AOvHyh35CHvnJu8o0OMwxows3c994zCRoovPlzuDIHXSDoMyCUi7ekwLN6ko1aLUlcIuMBEoZ294NtauhCPkHcDFXzHWuR76qFkhaDQ1Wt9BE3pe6B2NjU9Q==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=BALIWWDTQ+ZlIKK28l85+CK4+s6kgnoGO3ZUTrRFyLrOgqpLbLZeSB+9KmXioCQ9MaOgpRqxs3OX3mNy8nIF3bUBZiBfMRBdU/dQuW9tFudAtgX0v2P/3J0rnyJ3/meIEF67nFwkWipIq5rAPWSRJQQyC/3cRif0Ts3udBtpwAG5VAxRxz5qL5LKEWYr4IGUBzzzjBXzPGp1EG0YoBqBuQKD96573sAvtmQGeNT1P7b4Bcx+kfcCfuPJgVga/pspwxIxhMhumM61F45ZJw3H15T0UKqyNUZsNDxadIr0902dYEQhePq24eQFf5w0gC9uG6ySgNY9OdX9PLc8Xlxydg==
  • Authentication-results: esa2.hc3370-68.iphmx.com; dkim=pass (signature verified) header.i=@citrix.onmicrosoft.com
  • Cc: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>, "Andrew Cooper" <andrew.cooper3@xxxxxxxxxx>, Wei Liu <wl@xxxxxxx>, Olaf Hering <olaf@xxxxxxxxx>
  • Delivery-date: Thu, 27 May 2021 08:33:52 +0000
  • Ironport-hdrordr: A9a23:WvpU+K/TJQBiEovjIoZuk+Hadb1zdoMgy1knxilNoENuHPBwxv rAoB1E73PJYVYqOE3Jmbi7Sc+9qFfnhONICOgqTM2ftWzd2VdAQ7sSiLcKrweQfxEWs9QtqZ uIEJIOeOEYb2IK9foSiTPQe71LrajlgcLY99s2jU0dNj2CA5sQnjuRYTzra3GeKjM2YqbQQ/ Gnl7R6TnebCDgqhqvRPAhLY8Hz4/nw0L72ax8PABAqrCOUiymz1bL8Gx+Emj8DTjJm294ZgC j4uj28wp/mn+Cwyxfa2WOWxY9RgsHdxtxKA9HJotQJKw/rlh2jaO1aKvy/VQgO0aOSAWsR4Z zxS09KBbU215qRRBD6nfLV4Xii7N50gEWSjmNx6BDY0L/ErDFTMbsLuWsWSGqe16KM1OsMpp 6j5Fjpw6a/Oymw1BgV1+K4Ii2CqXDE1kbKsdRjxUC3ArFuJYO4k+QkjQpo+cA7bV3HAcYcYb BTMP0=
  • Ironport-sdr: ZBXMOD9DanDRHEUsUOMQpKN4q0ZakTFJS2K+iiZEzR5seMVaQFgwbCg/UU/jTIhlExS0eSt6lw B2C4vHjxzt5QpkMv+7+PV3Qn2TfORVq07ngDJv3moZNvQczsTsV1hIlQ7nIMNWa2x63pZSt6FQ sbsHrIEqST2tjUsU1vpqydmOXXyiuFWIJI/7/87d+vMxI10dIk17iBDXlkWAGWMvf+uPN/iD16 4B1CqDrS+6EpdJaldFccor+jUHASql6dg5C5pD4eS4WpGYz3s05nWV72E+XJvksXSvi3cpWsou +LQ=
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On Wed, May 26, 2021 at 02:59:00PM +0200, Jan Beulich wrote:
> Sufficiently old Linux (3.12-ish) accesses these MSRs in an unguarded
> manner. Furthermore these MSRs, at least on Fam11 and older CPUs, are
> also consulted by modern Linux, and their (bogus) built-in zapping of
> #GP faults from MSR accesses leads to it effectively reading zero
> instead of the intended values, which are relevant for PCI BAR placement
> (which ought to all live in MMIO-type space, not in DRAM-type one).
> 
> For SYSCFG, only certain bits get exposed. In fact, whether to expose
> MtrrVarDramEn is debatable: It controls use of not just TOM, but also
> the IORRs. Introduce (consistently named) constants for the bits we're
> interested in and use them in pre-existing code as well.

I think we should also allow access to the IORRs MSRs for coherency
(c001001{6,9}) for the hardware domain.

> As a welcome side effect, verbosity on/of debug builds gets (perhaps
> significantly) reduced.
> 
> Note that at least as far as those MSR accesses by Linux are concerned,
> there's no similar issue for DomU-s, as the accesses sit behind PCI
> device matching logic. The checked for devices would never be exposed to
> DomU-s in the first place. Nevertheless I think that at least for HVM we
> should return sensible values, not 0 (as svm_msr_read_intercept() does
> right now). The intended values may, however, need to be determined by
> hvmloader, and then get made known to Xen.

Could we maybe come up with a fixed memory layout that hvmloader had
to respect?

Ie: DRAM from 0 to 3G, MMIO from 3G to 4G, and then the remaining
DRAM from 4G in a contiguous single block?

hvmloader would have to place BARs that don't fit in the 3G-4G hole at
the end of DRAM (ie: after TOM2).

> 
> Fixes: 322ec7c89f66 ("x86/pv: disallow access to unknown MSRs")
> Reported-by: Olaf Hering <olaf@xxxxxxxxx>
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> 
> --- a/xen/arch/x86/cpu/amd.c
> +++ b/xen/arch/x86/cpu/amd.c
> @@ -468,14 +468,14 @@ static void check_syscfg_dram_mod_en(voi
>               return;
>  
>       rdmsrl(MSR_K8_SYSCFG, syscfg);
> -     if (!(syscfg & K8_MTRRFIXRANGE_DRAM_MODIFY))
> +     if (!(syscfg & SYSCFG_MTRR_FIX_DRAM_MOD_EN))
>               return;
>  
>       if (!test_and_set_bool(printed))
>               printk(KERN_ERR "MTRR: SYSCFG[MtrrFixDramModEn] not "
>                       "cleared by BIOS, clearing this bit\n");
>  
> -     syscfg &= ~K8_MTRRFIXRANGE_DRAM_MODIFY;
> +     syscfg &= ~SYSCFG_MTRR_FIX_DRAM_MOD_EN;
>       wrmsrl(MSR_K8_SYSCFG, syscfg);
>  }
>  
> --- a/xen/arch/x86/cpu/mtrr/generic.c
> +++ b/xen/arch/x86/cpu/mtrr/generic.c
> @@ -224,7 +224,7 @@ static void __init print_mtrr_state(cons
>               uint64_t syscfg, tom2;
>  
>               rdmsrl(MSR_K8_SYSCFG, syscfg);
> -             if (syscfg & (1 << 21)) {
> +             if (syscfg & SYSCFG_MTRR_TOM2_EN) {
>                       rdmsrl(MSR_K8_TOP_MEM2, tom2);
>                       printk("%sTOM2: %012"PRIx64"%s\n", level, tom2,
>                              syscfg & (1 << 22) ? " (WB)" : "");
> --- a/xen/arch/x86/msr.c
> +++ b/xen/arch/x86/msr.c
> @@ -339,6 +339,19 @@ int guest_rdmsr(struct vcpu *v, uint32_t
>          *val = msrs->tsc_aux;
>          break;
>  
> +    case MSR_K8_SYSCFG:
> +    case MSR_K8_TOP_MEM1:
> +    case MSR_K8_TOP_MEM2:
> +        if ( !(cp->x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON)) )
> +            goto gp_fault;
> +        if ( !is_hardware_domain(d) )
> +            return X86EMUL_UNHANDLEABLE;

It might be clearer to also handle the !is_hardware_domain case here,
instead of deferring to svm_msr_read_intercept:

if ( is_hardware_domain(d) )
    rdmsrl(msr, *val);
else
    *val = 0;

...

> +        rdmsrl(msr, *val);
> +        if ( msr == MSR_K8_SYSCFG )
> +            *val &= (SYSCFG_TOM2_FORCE_WB | SYSCFG_MTRR_TOM2_EN |
> +                     SYSCFG_MTRR_VAR_DRAM_EN | SYSCFG_MTRR_FIX_DRAM_EN);
> +        break;
> +
>      case MSR_K8_HWCR:
>          if ( !(cp->x86_vendor & (X86_VENDOR_AMD | X86_VENDOR_HYGON)) )
>              goto gp_fault;
> --- a/xen/arch/x86/x86_64/mmconf-fam10h.c
> +++ b/xen/arch/x86/x86_64/mmconf-fam10h.c
> @@ -69,7 +69,7 @@ static void __init get_fam10h_pci_mmconf
>       rdmsrl(address, val);
>  
>       /* TOP_MEM2 is not enabled? */
> -     if (!(val & (1<<21))) {
> +     if (!(val & SYSCFG_MTRR_TOM2_EN)) {
>               tom2 = 1ULL << 32;
>       } else {
>               /* TOP_MEM2 */
> --- a/xen/include/asm-x86/msr-index.h
> +++ b/xen/include/asm-x86/msr-index.h
> @@ -116,6 +116,13 @@
>  #define  PASID_PASID_MASK                   0x000fffff
>  #define  PASID_VALID                        (_AC(1, ULL) << 31)
>  
> +#define MSR_K8_SYSCFG                       0xc0010010
> +#define  SYSCFG_MTRR_FIX_DRAM_EN            (_AC(1, ULL) << 18)
> +#define  SYSCFG_MTRR_FIX_DRAM_MOD_EN        (_AC(1, ULL) << 19)
> +#define  SYSCFG_MTRR_VAR_DRAM_EN            (_AC(1, ULL) << 20)
> +#define  SYSCFG_MTRR_TOM2_EN                (_AC(1, ULL) << 21)
> +#define  SYSCFG_TOM2_FORCE_WB               (_AC(1, ULL) << 22)
> +
>  #define MSR_K8_VM_CR                        0xc0010114
>  #define  VM_CR_INIT_REDIRECTION             (_AC(1, ULL) <<  1)
>  #define  VM_CR_SVM_DISABLE                  (_AC(1, ULL) <<  4)
> @@ -279,10 +286,7 @@
>  #define MSR_K8_TOP_MEM1                      0xc001001a
>  #define MSR_K7_CLK_CTL                       0xc001001b
>  #define MSR_K8_TOP_MEM2                      0xc001001d
> -#define MSR_K8_SYSCFG                        0xc0010010
>  
> -#define K8_MTRRFIXRANGE_DRAM_ENABLE  0x00040000 /* MtrrFixDramEn bit    */
> -#define K8_MTRRFIXRANGE_DRAM_MODIFY  0x00080000 /* MtrrFixDramModEn bit */
>  #define K8_MTRR_RDMEM_WRMEM_MASK     0x18181818 /* Mask: RdMem|WrMem    */

That last one seem to be unused, I wonder if you could also drop it as
part of this cleanup?

Thanks, Roger.



 


Rackspace

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