diff mbox

[v2,09/12] x86/vmce, tools/libxl: expose LMCE capability in guest MSR_IA32_MCG_CAP

Message ID 20170317064614.23539-10-haozhong.zhang@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Haozhong Zhang March 17, 2017, 6:46 a.m. UTC
If LMCE is supported by host and ' mca_caps = [ "lmce" ] ' is present
in xl config, the LMCE capability will be exposed in guest MSR_IA32_MCG_CAP.
By default, LMCE is not exposed to guest so as to keep the backwards migration
compatibility.

Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
---
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Wei Liu <wei.liu2@citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

Changes in v2:
 * Allow restore an LMCE enabled guest on an LMCE-incapable host.
 * Change xl config to "mca_caps = [ "lmce" ]", which can be extended to
   support other MCA capabilities in the future.
---
 docs/man/xl.cfg.pod.5.in        | 24 ++++++++++++++++++++++++
 tools/libxl/libxl_dom.c         | 30 ++++++++++++++++++++++++++++++
 tools/libxl/libxl_types.idl     |  1 +
 tools/xl/xl_parse.c             |  4 ++++
 xen/arch/x86/cpu/mcheck/vmce.c  | 19 ++++++++++++++++++-
 xen/arch/x86/hvm/hvm.c          |  5 +++++
 xen/include/asm-x86/mce.h       |  1 +
 xen/include/public/hvm/params.h |  7 ++++++-
 8 files changed, 89 insertions(+), 2 deletions(-)

Comments

Jan Beulich March 20, 2017, 4:33 p.m. UTC | #1
>>> On 17.03.17 at 07:46, <haozhong.zhang@intel.com> wrote:
> --- a/xen/include/public/hvm/params.h
> +++ b/xen/include/public/hvm/params.h
> @@ -259,6 +259,11 @@
>   */
>  #define HVM_PARAM_VM86_TSS_SIZED 37
>  
> -#define HVM_NR_PARAMS 38
> +/* Enable MCA capabilities. */
> +#define HVM_PARAM_MCA_CAP 38
> +#define HVMMCA_CAP_LMCE   (1UL << 27)

How come this is bit 27 rather than bit 0? Further, to match up with
other, future definitions here, I think you mean 1ULL (or, to be
precise, xen_mk_ullong()).

> +#define HVMMCA_CAP_MASK   HVMMCA_CAP_LMCE

For both of these, please add XEN_ at the front (perhaps replacing
HVM, or if not, add another underscore between HVM and MCA).

Jan
Ian Jackson March 20, 2017, 6:27 p.m. UTC | #2
Haozhong Zhang writes ("[PATCH v2 09/12] x86/vmce, tools/libxl: expose LMCE capability in guest MSR_IA32_MCG_CAP"):
> If LMCE is supported by host and ' mca_caps = [ "lmce" ] ' is
> present in xl config, the LMCE capability will be exposed in guest
> MSR_IA32_MCG_CAP.  By default, LMCE is not exposed to guest so as to
> keep the backwards migration compatibility.

Excluse my ignorance, but I'm not sure what MCE, MCA and LMCE are.
I'm guessing MC = Machine Check ?

Is MCA "Machine Check Architecture" ?  Is that precisely the machinery
for handling MCEs, or is it something else ?

I think we may need a bit of care in the user-facing interface to try
to make the names and docs comprehensible.

> +=head3 x86
> +
> +=over 4
> +
> +=item B<mca_caps=[ "CAP", "CAP", ... ]>
> +
> +(HVM only) Enable MCA capabilities besides default ones enabled
> +by Xen hypervisor for the HVM domain. "CAP" can be one in the
> +following list:

Would it be incorrect to replace references to "MCA" with "MCE" (eg,
changing "mca_caps" to "mce_caps" here) ?

Ian.
Haozhong Zhang March 21, 2017, 7:14 a.m. UTC | #3
On 03/20/17 10:33 -0600, Jan Beulich wrote:
> >>> On 17.03.17 at 07:46, <haozhong.zhang@intel.com> wrote:
> > --- a/xen/include/public/hvm/params.h
> > +++ b/xen/include/public/hvm/params.h
> > @@ -259,6 +259,11 @@
> >   */
> >  #define HVM_PARAM_VM86_TSS_SIZED 37
> >  
> > -#define HVM_NR_PARAMS 38
> > +/* Enable MCA capabilities. */
> > +#define HVM_PARAM_MCA_CAP 38
> > +#define HVMMCA_CAP_LMCE   (1UL << 27)
> 
> How come this is bit 27 rather than bit 0? Further, to match up with
> other, future definitions here, I think you mean 1ULL (or, to be
> precise, xen_mk_ullong()).
>

I intended to use the same bit in MSR_IA32_MCG_CAP to clarify its
semantic, but I realize it's unnecessary as I still need to introduce
HVMMCA_CAP_* for each bit.

Thanks,
Haozhong
Haozhong Zhang March 21, 2017, 7:29 a.m. UTC | #4
On 03/20/17 18:27 +0000, Ian Jackson wrote:
> Haozhong Zhang writes ("[PATCH v2 09/12] x86/vmce, tools/libxl: expose LMCE capability in guest MSR_IA32_MCG_CAP"):
> > If LMCE is supported by host and ' mca_caps = [ "lmce" ] ' is
> > present in xl config, the LMCE capability will be exposed in guest
> > MSR_IA32_MCG_CAP.  By default, LMCE is not exposed to guest so as to
> > keep the backwards migration compatibility.
> 
> Excluse my ignorance, but I'm not sure what MCE, MCA and LMCE are.
> I'm guessing MC = Machine Check ?
>

Yes.

> Is MCA "Machine Check Architecture" ?  Is that precisely the machinery
> for handling MCEs, or is it something else ?

Yes for both.

And LMCE stands for 'Local Machine Check Error', which is only sent to
the affected CPU, in contrast to the current ones on Intel CPU that
are broadcast to all CPUs.

> 
> I think we may need a bit of care in the user-facing interface to try
> to make the names and docs comprehensible.
>

'mca_caps' stands for capabilities of the machine check architecture
present to guest. I choose this name because the existing
intel_init_mca() uses "MCA capability" when it prints supported
capabilities, and ...

> > +=head3 x86
> > +
> > +=over 4
> > +
> > +=item B<mca_caps=[ "CAP", "CAP", ... ]>
> > +
> > +(HVM only) Enable MCA capabilities besides default ones enabled
> > +by Xen hypervisor for the HVM domain. "CAP" can be one in the
> > +following list:
> 
> Would it be incorrect to replace references to "MCA" with "MCE" (eg,
> changing "mca_caps" to "mce_caps" here) ?
>

... besides for consistency with intel_init_mca(), Intel SDM uses "the
information about the machine check architecture" (at the beginning of
section "IA32_MCG_CAP MSR", Vol 3). 'mca_caps' currently is for
capabilities indicated by IA32_MCG_CAP, so I think 'mca' is a better
name than 'mce'.

Thanks,
Haozhong
Haozhong Zhang March 21, 2017, 7:35 a.m. UTC | #5
On 03/21/17 15:29 +0800, Haozhong Zhang wrote:
> On 03/20/17 18:27 +0000, Ian Jackson wrote:
> > Haozhong Zhang writes ("[PATCH v2 09/12] x86/vmce, tools/libxl: expose LMCE capability in guest MSR_IA32_MCG_CAP"):
[..]
> > Is MCA "Machine Check Architecture" ?  Is that precisely the machinery
> > for handling MCEs, or is it something else ?

More precisely, MCA is "the mechanism for detecting and reporting
hardware (machine) errors", according to Intel SDM Vol 3, Section
"MACHINE-CHECK ARCHITECTURE".

Haozhong
Jan Beulich March 21, 2017, 9:30 a.m. UTC | #6
>>> On 20.03.17 at 19:27, <ian.jackson@eu.citrix.com> wrote:
> Haozhong Zhang writes ("[PATCH v2 09/12] x86/vmce, tools/libxl: expose LMCE 
> capability in guest MSR_IA32_MCG_CAP"):
>> +=head3 x86
>> +
>> +=over 4
>> +
>> +=item B<mca_caps=[ "CAP", "CAP", ... ]>
>> +
>> +(HVM only) Enable MCA capabilities besides default ones enabled
>> +by Xen hypervisor for the HVM domain. "CAP" can be one in the
>> +following list:
> 
> Would it be incorrect to replace references to "MCA" with "MCE" (eg,
> changing "mca_caps" to "mce_caps" here) ?

MCE (Machine Check Exception) is only part of MCA, so I don't
think the terms can be used interchangeably. Namely I think
mce_caps would be wrong.

Jan
Wei Liu March 27, 2017, 3:34 p.m. UTC | #7
On Fri, Mar 17, 2017 at 02:46:11PM +0800, Haozhong Zhang wrote:
> If LMCE is supported by host and ' mca_caps = [ "lmce" ] ' is present
> in xl config, the LMCE capability will be exposed in guest MSR_IA32_MCG_CAP.
> By default, LMCE is not exposed to guest so as to keep the backwards migration
> compatibility.
> 
> Signed-off-by: Haozhong Zhang <haozhong.zhang@intel.com>
[...]
> +static int hvm_set_mca_capabilities(libxl__gc *gc, uint32_t domid,
> +                                    libxl_domain_build_info *const info)
> +{
> +    int i, rc = 0;
> +    const libxl_string_list xl_caps = info->u.hvm.mca_caps;
> +    unsigned long caps = 0;
> +
> +    if (!xl_caps)
> +        return 0;
> +
> +    for (i = 0; xl_caps[i] != NULL; i++) {
> +        if (!strcmp(xl_caps[i], "lmce"))
> +            caps |= HVMMCA_CAP_LMCE;
> +        else {
> +            LOG(ERROR, "Unsupported MCA capability %s", xl_caps[i]);
> +            rc = ERROR_FAIL;
> +            break;
> +        }
> +    }
> +

This is not how we normally do this.  Parsing should normally be done in
xl. Is there any particular reason you chose to parse here?

> +    if (!rc)
> +        rc = xc_hvm_param_set(CTX->xch, domid, HVM_PARAM_MCA_CAP, caps);
> +
> +    return rc;
> +}
>  #endif
>  
>  static void hvm_set_conf_params(xc_interface *handle, uint32_t domid,
> @@ -438,6 +464,10 @@ int libxl__build_pre(libxl__gc *gc, uint32_t domid,
>          rc = hvm_set_viridian_features(gc, domid, info);
>          if (rc)
>              return rc;
> +
> +        rc = hvm_set_mca_capabilities(gc, domid, info);
> +        if (rc)
> +            return rc;
>  #endif
>      }
>  
> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> index a612d1f..71c6c33 100644
> --- a/tools/libxl/libxl_types.idl
> +++ b/tools/libxl/libxl_types.idl
> @@ -550,6 +550,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
>                                         ("serial_list",      libxl_string_list),
>                                         ("rdm", libxl_rdm_reserve),
>                                         ("rdm_mem_boundary_memkb", MemKB),
> +                                       ("mca_caps",         libxl_string_list),

You need to add a LIBXL_HAVE_MCA_CAPS to libxl.h

Wei.
diff mbox

Patch

diff --git a/docs/man/xl.cfg.pod.5.in b/docs/man/xl.cfg.pod.5.in
index 505c111..d75dcd2 100644
--- a/docs/man/xl.cfg.pod.5.in
+++ b/docs/man/xl.cfg.pod.5.in
@@ -2021,6 +2021,30 @@  natively or via hardware backwards compatibility support.
 
 =back
 
+=head3 x86
+
+=over 4
+
+=item B<mca_caps=[ "CAP", "CAP", ... ]>
+
+(HVM only) Enable MCA capabilities besides default ones enabled
+by Xen hypervisor for the HVM domain. "CAP" can be one in the
+following list:
+
+=over 4
+
+=item B<"lmce">
+
+Intel local MCE
+
+=item B<default>
+
+No MCA capabilities in above list are enabled.
+
+=back
+
+=back
+
 =head1 SEE ALSO
 
 =over 4
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index d519c8d..91b2f08 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -275,6 +275,32 @@  err:
     libxl_bitmap_dispose(&enlightenments);
     return ERROR_FAIL;
 }
+
+static int hvm_set_mca_capabilities(libxl__gc *gc, uint32_t domid,
+                                    libxl_domain_build_info *const info)
+{
+    int i, rc = 0;
+    const libxl_string_list xl_caps = info->u.hvm.mca_caps;
+    unsigned long caps = 0;
+
+    if (!xl_caps)
+        return 0;
+
+    for (i = 0; xl_caps[i] != NULL; i++) {
+        if (!strcmp(xl_caps[i], "lmce"))
+            caps |= HVMMCA_CAP_LMCE;
+        else {
+            LOG(ERROR, "Unsupported MCA capability %s", xl_caps[i]);
+            rc = ERROR_FAIL;
+            break;
+        }
+    }
+
+    if (!rc)
+        rc = xc_hvm_param_set(CTX->xch, domid, HVM_PARAM_MCA_CAP, caps);
+
+    return rc;
+}
 #endif
 
 static void hvm_set_conf_params(xc_interface *handle, uint32_t domid,
@@ -438,6 +464,10 @@  int libxl__build_pre(libxl__gc *gc, uint32_t domid,
         rc = hvm_set_viridian_features(gc, domid, info);
         if (rc)
             return rc;
+
+        rc = hvm_set_mca_capabilities(gc, domid, info);
+        if (rc)
+            return rc;
 #endif
     }
 
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index a612d1f..71c6c33 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -550,6 +550,7 @@  libxl_domain_build_info = Struct("domain_build_info",[
                                        ("serial_list",      libxl_string_list),
                                        ("rdm", libxl_rdm_reserve),
                                        ("rdm_mem_boundary_memkb", MemKB),
+                                       ("mca_caps",         libxl_string_list),
                                        ])),
                  ("pv", Struct(None, [("kernel", string),
                                       ("slack_memkb", MemKB),
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
index 1ef0c27..11a9f51 100644
--- a/tools/xl/xl_parse.c
+++ b/tools/xl/xl_parse.c
@@ -1084,6 +1084,10 @@  void parse_config_data(const char *config_source,
 
         if (!xlu_cfg_get_long (config, "rdm_mem_boundary", &l, 0))
             b_info->u.hvm.rdm_mem_boundary_memkb = l * 1024;
+
+        xlu_cfg_get_list_as_string_list(config, "mca_caps",
+                                        &b_info->u.hvm.mca_caps, false);
+
         break;
     case LIBXL_DOMAIN_TYPE_PV:
     {
diff --git a/xen/arch/x86/cpu/mcheck/vmce.c b/xen/arch/x86/cpu/mcheck/vmce.c
index 994a50e..5dc790f 100644
--- a/xen/arch/x86/cpu/mcheck/vmce.c
+++ b/xen/arch/x86/cpu/mcheck/vmce.c
@@ -74,7 +74,7 @@  int vmce_restore_vcpu(struct vcpu *v, const struct hvm_vmce_vcpu *ctxt)
     unsigned long guest_mcg_cap;
 
     if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
-        guest_mcg_cap = INTEL_GUEST_MCG_CAP;
+        guest_mcg_cap = INTEL_GUEST_MCG_CAP | MCG_LMCE_P;
     else
         guest_mcg_cap = AMD_GUEST_MCG_CAP;
 
@@ -546,3 +546,20 @@  int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn)
     return rc;
 }
 
+int vmce_enable_mca_cap(struct domain *d, uint64_t cap)
+{
+    struct vcpu *v;
+
+    if ( cap & ~HVMMCA_CAP_MASK )
+        return -EINVAL;
+
+    if ( cap & HVMMCA_CAP_LMCE )
+    {
+        if ( !lmce_support )
+            return -EINVAL;
+        for_each_vcpu(d, v)
+            v->arch.vmce.mcg_cap |= MCG_LMCE_P;
+    }
+
+    return 0;
+}
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index ccfae4f..0007e3d 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -4045,6 +4045,7 @@  static int hvm_allow_set_param(struct domain *d,
     case HVM_PARAM_IOREQ_SERVER_PFN:
     case HVM_PARAM_NR_IOREQ_SERVER_PAGES:
     case HVM_PARAM_ALTP2M:
+    case HVM_PARAM_MCA_CAP:
         if ( value != 0 && a->value != value )
             rc = -EEXIST;
         break;
@@ -4257,6 +4258,10 @@  static int hvmop_set_param(
                                                (0x10000 / 8) + 1) << 32);
         a.value |= VM86_TSS_UPDATED;
         break;
+
+    case HVM_PARAM_MCA_CAP:
+        rc = vmce_enable_mca_cap(d, a.value);
+        break;
     }
 
     if ( rc != 0 )
diff --git a/xen/include/asm-x86/mce.h b/xen/include/asm-x86/mce.h
index dee66b3..70eb50c 100644
--- a/xen/include/asm-x86/mce.h
+++ b/xen/include/asm-x86/mce.h
@@ -38,6 +38,7 @@  extern int vmce_restore_vcpu(struct vcpu *, const struct hvm_vmce_vcpu *);
 extern int vmce_wrmsr(uint32_t msr, uint64_t val);
 extern int vmce_rdmsr(uint32_t msr, uint64_t *val);
 extern bool vmce_support_lmce(const struct vcpu *v);
+extern int vmce_enable_mca_cap(struct domain *d, uint64_t cap);
 
 extern unsigned int nr_mce_banks;
 
diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
index 58c8478..266c123 100644
--- a/xen/include/public/hvm/params.h
+++ b/xen/include/public/hvm/params.h
@@ -259,6 +259,11 @@ 
  */
 #define HVM_PARAM_VM86_TSS_SIZED 37
 
-#define HVM_NR_PARAMS 38
+/* Enable MCA capabilities. */
+#define HVM_PARAM_MCA_CAP 38
+#define HVMMCA_CAP_LMCE   (1UL << 27)
+#define HVMMCA_CAP_MASK   HVMMCA_CAP_LMCE
+
+#define HVM_NR_PARAMS 39
 
 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */