diff mbox series

[v3,2/3] x86/platform: introduce XENPF_get_ucode_version

Message ID 20230321114745.11044-3-sergey.dyasli@citrix.com (mailing list archive)
State Superseded
Headers show
Series xen-ucode: print information about currently loaded ucode | expand

Commit Message

Sergey Dyasli March 21, 2023, 11:47 a.m. UTC
Currently it's impossible to get CPU's microcode revision after late
loading without looking into Xen logs which is not always convenient.

Add a new platform op in order to get the required data from Xen and
provide a wrapper for libxenctrl.

Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
---
 tools/include/xenctrl.h                  |  2 ++
 tools/libs/ctrl/xc_misc.c                | 21 +++++++++++++++++
 xen/arch/x86/platform_hypercall.c        | 30 ++++++++++++++++++++++++
 xen/arch/x86/x86_64/platform_hypercall.c |  4 ++++
 xen/include/public/platform.h            | 12 ++++++++++
 xen/include/xlat.lst                     |  1 +
 6 files changed, 70 insertions(+)

Comments

Andrew Cooper March 21, 2023, 1:07 p.m. UTC | #1
On 21/03/2023 11:47 am, Sergey Dyasli wrote:
> Currently it's impossible to get CPU's microcode revision after late
> loading without looking into Xen logs which is not always convenient.

It's not impossible (you can do `modprobe msr; rdmsr 0x8b`), but it is
inconvenient for library code.

>
> Add a new platform op in order to get the required data from Xen and
> provide a wrapper for libxenctrl.
>
> Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
> ---
>  tools/include/xenctrl.h                  |  2 ++
>  tools/libs/ctrl/xc_misc.c                | 21 +++++++++++++++++
>  xen/arch/x86/platform_hypercall.c        | 30 ++++++++++++++++++++++++
>  xen/arch/x86/x86_64/platform_hypercall.c |  4 ++++
>  xen/include/public/platform.h            | 12 ++++++++++
>  xen/include/xlat.lst                     |  1 +
>  6 files changed, 70 insertions(+)
>
> diff --git a/tools/include/xenctrl.h b/tools/include/xenctrl.h
> index 8aa747dc2e..d3ef7a48a5 100644
> --- a/tools/include/xenctrl.h
> +++ b/tools/include/xenctrl.h
> @@ -1187,6 +1187,8 @@ int xc_cputopoinfo(xc_interface *xch, unsigned *max_cpus,
>                     xc_cputopo_t *cputopo);
>  int xc_microcode_update(xc_interface *xch, const void *buf, size_t len);
>  int xc_get_cpu_version(xc_interface *xch, struct xenpf_pcpu_version *cpu_ver);
> +int xc_get_ucode_version(xc_interface *xch,
> +                         struct xenpf_ucode_version *ucode_ver);

Throughout, we should use "revision" rather than "version" as that is
the terminology used by both Intel and AMD.

>  int xc_numainfo(xc_interface *xch, unsigned *max_nodes,
>                  xc_meminfo_t *meminfo, uint32_t *distance);
>  int xc_pcitopoinfo(xc_interface *xch, unsigned num_devs,
> diff --git a/tools/libs/ctrl/xc_misc.c b/tools/libs/ctrl/xc_misc.c
> index f2f6e4348e..b93477d189 100644
> --- a/tools/libs/ctrl/xc_misc.c
> +++ b/tools/libs/ctrl/xc_misc.c
> @@ -246,6 +246,27 @@ int xc_get_cpu_version(xc_interface *xch, struct xenpf_pcpu_version *cpu_ver)
>      return 0;
>  }
>  
> +int xc_get_ucode_version(xc_interface *xch,
> +                         struct xenpf_ucode_version *ucode_ver)
> +{
> +    int ret;
> +    DECLARE_PLATFORM_OP;
> +
> +    if ( !xch || !ucode_ver )
> +        return -1;
> +
> +    platform_op.cmd = XENPF_get_ucode_version;
> +    platform_op.u.ucode_version.xen_cpuid = ucode_ver->xen_cpuid;

Same notes as per patch 1.

> diff --git a/xen/include/public/platform.h b/xen/include/public/platform.h
> index 60caa5ce7e..232df79d5f 100644
> --- a/xen/include/public/platform.h
> +++ b/xen/include/public/platform.h
> @@ -614,6 +614,17 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_symdata_t);
>  typedef struct dom0_vga_console_info xenpf_dom0_console_t;
>  DEFINE_XEN_GUEST_HANDLE(xenpf_dom0_console_t);
>  
> +#define XENPF_get_ucode_version 65
> +struct xenpf_ucode_version {
> +    uint32_t xen_cpuid;       /* IN:  CPU number to get the revision from.  */

We commonly call this just "cpu".  As a platform op pertaining to
microcode, it cannot plausibly be confused with vcpus.

> +    uint32_t cpu_signature;   /* OUT: CPU signature (CPUID.1.EAX).          */

The cpu_ prefix can be dropped, as can ...

> +    uint32_t pf;              /* OUT: Processor Flags.                      */
> +                              /*      Only applicable to Intel.             */
> +    uint32_t ucode_revision;  /* OUT: Microcode Revision.                   */

the ucode_ prefix here.

I'm tempted to say that I'm happy to fix all of this on commit as it's
all mechanical changes.

~Andrew
Jan Beulich March 21, 2023, 1:31 p.m. UTC | #2
On 21.03.2023 12:47, Sergey Dyasli wrote:
> --- a/xen/arch/x86/platform_hypercall.c
> +++ b/xen/arch/x86/platform_hypercall.c
> @@ -640,6 +640,36 @@ ret_t do_platform_op(
>      }
>      break;
>  
> +    case XENPF_get_ucode_version:
> +    {
> +        struct xenpf_ucode_version *ver = &op->u.ucode_version;
> +
> +        if ( !get_cpu_maps() )
> +        {
> +            ret = -EBUSY;
> +            break;
> +        }
> +
> +        if ( (ver->xen_cpuid >= nr_cpu_ids) || !cpu_online(ver->xen_cpuid) )
> +        {
> +            ret = -ENOENT;
> +        }

Nit: Unnecessary braces.

> +        else
> +        {
> +            const struct cpu_signature *sig = &per_cpu(cpu_sig, ver->xen_cpuid);
> +
> +            ver->cpu_signature = sig->sig;
> +            ver->pf = sig->pf;
> +            ver->ucode_revision = sig->rev;
> +        }

While I don't mean to insist on making this work right in this patch, I'd
like to re-raise my earlier comment regarding it also being of possible
interest to know ucode revisions for parked CPUs (they are, after all, an
active entity in the system). Parked CPUs have their per-CPU data retained,
so getting at that data shouldn't be overly difficult (the main aspect
being to tell parked from fully offline CPUs).

Jan
diff mbox series

Patch

diff --git a/tools/include/xenctrl.h b/tools/include/xenctrl.h
index 8aa747dc2e..d3ef7a48a5 100644
--- a/tools/include/xenctrl.h
+++ b/tools/include/xenctrl.h
@@ -1187,6 +1187,8 @@  int xc_cputopoinfo(xc_interface *xch, unsigned *max_cpus,
                    xc_cputopo_t *cputopo);
 int xc_microcode_update(xc_interface *xch, const void *buf, size_t len);
 int xc_get_cpu_version(xc_interface *xch, struct xenpf_pcpu_version *cpu_ver);
+int xc_get_ucode_version(xc_interface *xch,
+                         struct xenpf_ucode_version *ucode_ver);
 int xc_numainfo(xc_interface *xch, unsigned *max_nodes,
                 xc_meminfo_t *meminfo, uint32_t *distance);
 int xc_pcitopoinfo(xc_interface *xch, unsigned num_devs,
diff --git a/tools/libs/ctrl/xc_misc.c b/tools/libs/ctrl/xc_misc.c
index f2f6e4348e..b93477d189 100644
--- a/tools/libs/ctrl/xc_misc.c
+++ b/tools/libs/ctrl/xc_misc.c
@@ -246,6 +246,27 @@  int xc_get_cpu_version(xc_interface *xch, struct xenpf_pcpu_version *cpu_ver)
     return 0;
 }
 
+int xc_get_ucode_version(xc_interface *xch,
+                         struct xenpf_ucode_version *ucode_ver)
+{
+    int ret;
+    DECLARE_PLATFORM_OP;
+
+    if ( !xch || !ucode_ver )
+        return -1;
+
+    platform_op.cmd = XENPF_get_ucode_version;
+    platform_op.u.ucode_version.xen_cpuid = ucode_ver->xen_cpuid;
+
+    ret = do_platform_op(xch, &platform_op);
+    if ( ret != 0 )
+        return ret;
+
+    *ucode_ver = platform_op.u.ucode_version;
+
+    return 0;
+}
+
 int xc_cputopoinfo(xc_interface *xch, unsigned *max_cpus,
                    xc_cputopo_t *cputopo)
 {
diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c
index a2d9526355..d0818fea47 100644
--- a/xen/arch/x86/platform_hypercall.c
+++ b/xen/arch/x86/platform_hypercall.c
@@ -640,6 +640,36 @@  ret_t do_platform_op(
     }
     break;
 
+    case XENPF_get_ucode_version:
+    {
+        struct xenpf_ucode_version *ver = &op->u.ucode_version;
+
+        if ( !get_cpu_maps() )
+        {
+            ret = -EBUSY;
+            break;
+        }
+
+        if ( (ver->xen_cpuid >= nr_cpu_ids) || !cpu_online(ver->xen_cpuid) )
+        {
+            ret = -ENOENT;
+        }
+        else
+        {
+            const struct cpu_signature *sig = &per_cpu(cpu_sig, ver->xen_cpuid);
+
+            ver->cpu_signature = sig->sig;
+            ver->pf = sig->pf;
+            ver->ucode_revision = sig->rev;
+        }
+
+        put_cpu_maps();
+
+        if ( __copy_field_to_guest(u_xenpf_op, op, u.ucode_version) )
+            ret = -EFAULT;
+    }
+    break;
+
     case XENPF_cpu_online:
     {
         int cpu = op->u.cpu_ol.cpuid;
diff --git a/xen/arch/x86/x86_64/platform_hypercall.c b/xen/arch/x86/x86_64/platform_hypercall.c
index 5bf6b958d2..b876fd0c4a 100644
--- a/xen/arch/x86/x86_64/platform_hypercall.c
+++ b/xen/arch/x86/x86_64/platform_hypercall.c
@@ -28,6 +28,10 @@  CHECK_pf_pcpuinfo;
 CHECK_pf_pcpu_version;
 #undef xen_pf_pcpu_version
 
+#define xen_pf_ucode_version xenpf_ucode_version
+CHECK_pf_ucode_version;
+#undef xen_pf_pucode_version
+
 #define xen_pf_enter_acpi_sleep xenpf_enter_acpi_sleep
 CHECK_pf_enter_acpi_sleep;
 #undef xen_pf_enter_acpi_sleep
diff --git a/xen/include/public/platform.h b/xen/include/public/platform.h
index 60caa5ce7e..232df79d5f 100644
--- a/xen/include/public/platform.h
+++ b/xen/include/public/platform.h
@@ -614,6 +614,17 @@  DEFINE_XEN_GUEST_HANDLE(xenpf_symdata_t);
 typedef struct dom0_vga_console_info xenpf_dom0_console_t;
 DEFINE_XEN_GUEST_HANDLE(xenpf_dom0_console_t);
 
+#define XENPF_get_ucode_version 65
+struct xenpf_ucode_version {
+    uint32_t xen_cpuid;       /* IN:  CPU number to get the revision from.  */
+    uint32_t cpu_signature;   /* OUT: CPU signature (CPUID.1.EAX).          */
+    uint32_t pf;              /* OUT: Processor Flags.                      */
+                              /*      Only applicable to Intel.             */
+    uint32_t ucode_revision;  /* OUT: Microcode Revision.                   */
+};
+typedef struct xenpf_ucode_version xenpf_ucode_version_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_ucode_version_t);
+
 /*
  * ` enum neg_errnoval
  * ` HYPERVISOR_platform_op(const struct xen_platform_op*);
@@ -645,6 +656,7 @@  struct xen_platform_op {
         xenpf_resource_op_t           resource_op;
         xenpf_symdata_t               symdata;
         xenpf_dom0_console_t          dom0_console;
+        xenpf_ucode_version_t         ucode_version;
         uint8_t                       pad[128];
     } u;
 };
diff --git a/xen/include/xlat.lst b/xen/include/xlat.lst
index d601a8a984..164f700eb6 100644
--- a/xen/include/xlat.lst
+++ b/xen/include/xlat.lst
@@ -157,6 +157,7 @@ 
 ?	xenpf_pcpuinfo			platform.h
 ?	xenpf_pcpu_version		platform.h
 ?	xenpf_resource_entry		platform.h
+?	xenpf_ucode_version		platform.h
 ?	pmu_data			pmu.h
 ?	pmu_params			pmu.h
 !	sched_poll			sched.h