Currently it's impossible to get CPU's microcode revision after late
loading without looking into Xen logs which is not always convenient.

Leverage xenhypfs to expose struct cpu_signature in a new cpuinfo dir.
The tree structure is:

    /
      cpuinfo/
        cpu-signature
        microcode-revision
        processor-flags

The most useful bit is cpu microcode revision which will get updated
after late ucode loading.

Signed-off-by: Sergey Dyasli <sergey.dya...@citrix.com>
---
 xen/arch/x86/cpu/common.c | 58 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
index 5ad347534a..aa864fdbab 100644
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -1005,3 +1005,61 @@ const struct x86_cpu_id *x86_match_cpu(const struct 
x86_cpu_id table[])
        }
        return NULL;
 }
+
+#ifdef CONFIG_HYPFS
+#include <xen/hypfs.h>
+#include <xen/guest_access.h>
+#include <asm/microcode.h>
+
+static unsigned int cpu_signature;
+static unsigned int processor_flags;
+static unsigned int ucode_revision;
+
+int cf_check hypfs_read_cpusig(
+    const struct hypfs_entry *entry, XEN_GUEST_HANDLE_PARAM(void) uaddr)
+{
+    const struct hypfs_entry_leaf *l;
+    unsigned int size = entry->funcs->getsize(entry);
+    const struct cpu_signature *sig = &per_cpu(cpu_sig,
+                                               cpumask_first(&cpu_online_map));
+
+    l = container_of(entry, const struct hypfs_entry_leaf, e);
+
+    cpu_signature = sig->sig;
+    processor_flags = sig->pf;
+    ucode_revision = sig->rev;
+
+    return copy_to_guest(uaddr, l->u.content, size) ?  -EFAULT : 0;
+}
+
+const struct hypfs_funcs ucode_rev_funcs = {
+    .enter = hypfs_node_enter,
+    .exit = hypfs_node_exit,
+    .read = hypfs_read_cpusig,
+    .write = hypfs_write_deny,
+    .getsize = hypfs_getsize,
+    .findentry = hypfs_leaf_findentry,
+};
+
+static HYPFS_DIR_INIT(cpuinfo, "cpuinfo");
+static HYPFS_FIXEDSIZE_INIT(signature, XEN_HYPFS_TYPE_UINT, "cpu-signature",
+                            cpu_signature, &ucode_rev_funcs, 0);
+static HYPFS_FIXEDSIZE_INIT(pf, XEN_HYPFS_TYPE_UINT, "processor-flags",
+                            processor_flags, &ucode_rev_funcs, 0);
+static HYPFS_FIXEDSIZE_INIT(revision, XEN_HYPFS_TYPE_UINT, 
"microcode-revision",
+                            ucode_revision, &ucode_rev_funcs, 0);
+
+static int __init cf_check cpuinfo_init(void)
+{
+    hypfs_add_dir(&hypfs_root, &cpuinfo, true);
+    hypfs_add_leaf(&cpuinfo, &signature, true);
+
+    if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
+        hypfs_add_leaf(&cpuinfo, &pf, true);
+
+    hypfs_add_leaf(&cpuinfo, &revision, true);
+
+    return 0;
+}
+__initcall(cpuinfo_init);
+#endif /* CONFIG_HYPFS */
-- 
2.17.1


Reply via email to