All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/13] x86: CPUID and MSR policy marshalling support
@ 2018-07-03 20:55 Andrew Cooper
  2018-07-03 20:55 ` [PATCH 01/13] libx86: Introduce libx86/cpuid.h Andrew Cooper
                   ` (13 more replies)
  0 siblings, 14 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-03 20:55 UTC (permalink / raw)
  To: Xen-devel
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Jan Beulich,
	Daniel De Graaf, Roger Pau Monné

This series introduces libx86, a small shared library between the hypervisor
and libxc, and hypercalls to get/set full CPUID/MSR policies.  Future work
will arrange for XEN_DOMCTL_set_cpumsr_policy to function properly, after the
auditing and comparison logic is sorted.

In the meantime, the data marshalling logic is in a suitable state for review.

Some open questions:

  * The position of libx86 in the source tree.  It probably doesn't want to
    live in its current location.
  * Naming of various files, particularly policy.c (which I don't like, but
    can't think of anything better).
  * A TOCTOU race in the final patch, caused by the copy_from_guest() ABI.
    More details in that patch.

This series is based on x86-next, and can be found in git form here:

  http://xenbits.xen.org/gitweb/?p=people/andrewcoop/xen.git;a=shortlog;h=refs/heads/cpuid-marshal-v1

Andrew Cooper (5):
  libx86: Introduce libx86/cpuid.h
  libx86: Introduce libx86/msr.h and share msr_{domain,vcpu}_policy with userspace
  libx86: Introduce a helper to serialise a cpuid_policy object
  x86: Collect policies together into groups
  libx86: Introduce a helper to deserialise a cpuid_policy object

Roger Pau Monné (5):
  libx86: generate cpuid-autogen.h in the libx86 include dir
  libx86: Share struct cpuid_policy with userspace
  libx86: introduce a libx86 shared library
  libx86: Introduce a helper to serialise msr_{domain,vcpu}_policy objects
  libx86: introduce a helper to deserialize MSR policies

Sergey Dyasli (3):
  x86/sysctl: Implement XEN_SYSCTL_get_cpumsr_policy
  x86/domctl: Implement XEN_DOMCTL_get_cpumsr_policy
  x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy

 .gitignore                                  |   2 +-
 tools/include/Makefile                      |  15 ++
 tools/libxc/Makefile                        |  14 +-
 tools/libxc/include/xenctrl.h               |  15 +-
 tools/libxc/xc_cpuid_x86.c                  | 163 +++++++++++++++++---
 tools/misc/xen-cpuid.c                      | 135 +++++++++++++++-
 tools/tests/x86_emulator/x86-emulate.h      |   2 +
 xen/arch/x86/cpu/common.c                   |   2 +-
 xen/arch/x86/cpuid.c                        |  32 +---
 xen/arch/x86/domctl.c                       | 133 ++++++++++++++++
 xen/arch/x86/msr.c                          |   4 +-
 xen/arch/x86/sysctl.c                       | 101 ++++++++++++
 xen/arch/x86/x86_emulate/x86_emulate.h      |   7 +-
 xen/common/Makefile                         |   1 +
 xen/common/libx86/Makefile                  |   3 +
 xen/common/libx86/cpuid.c                   | 226 +++++++++++++++++++++++++++
 xen/common/libx86/libx86-private.h          |  74 +++++++++
 xen/common/libx86/msr.c                     | 134 ++++++++++++++++
 xen/common/libx86/policies.c                |  19 +++
 xen/include/Makefile                        |   6 +-
 xen/include/asm-x86/cpufeatures.h           |   2 +-
 xen/include/asm-x86/cpuid.h                 | 228 +---------------------------
 xen/include/asm-x86/msr.h                   |  65 ++------
 xen/include/public/arch-x86/xen.h           |  18 +++
 xen/include/public/domctl.h                 |  25 +++
 xen/include/public/sysctl.h                 |  41 +++++
 xen/include/{asm-x86 => xen/libx86}/cpuid.h | 103 +++++--------
 xen/include/xen/libx86/msr.h                |  78 ++++++++++
 xen/include/xen/libx86/policies.h           |  35 +++++
 xen/include/xen/xmalloc.h                   |   7 +
 xen/xsm/flask/hooks.c                       |   3 +
 xen/xsm/flask/policy/access_vectors         |   4 +-
 32 files changed, 1281 insertions(+), 416 deletions(-)
 create mode 100644 xen/common/libx86/Makefile
 create mode 100644 xen/common/libx86/cpuid.c
 create mode 100644 xen/common/libx86/libx86-private.h
 create mode 100644 xen/common/libx86/msr.c
 create mode 100644 xen/common/libx86/policies.c
 copy xen/include/{asm-x86 => xen/libx86}/cpuid.h (77%)
 create mode 100644 xen/include/xen/libx86/msr.h
 create mode 100644 xen/include/xen/libx86/policies.h

-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH 01/13] libx86: Introduce libx86/cpuid.h
  2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
@ 2018-07-03 20:55 ` Andrew Cooper
  2018-07-04  6:54   ` Wei Liu
  2018-07-04  8:21   ` Jan Beulich
  2018-07-03 20:55 ` [PATCH 02/13] libx86: generate cpuid-autogen.h in the libx86 include dir Andrew Cooper
                   ` (12 subsequent siblings)
  13 siblings, 2 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-03 20:55 UTC (permalink / raw)
  To: Xen-devel
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Jan Beulich,
	Roger Pau Monné

Begin to untangle the header dependency tangle by moving definition of
struct cpuid_leaf out of x86_emulate.h into the new cpuid.h.

Additionally, plumb the header through to libxc.  This is technically a
redundant include at this point, but it helps build-test the later changes,
and will be used eventually.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Sergey Dyasli <sergey.dyasli@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
---
 tools/include/Makefile                 |  3 +++
 tools/libxc/xc_cpuid_x86.c             |  2 ++
 xen/arch/x86/x86_emulate/x86_emulate.h |  7 ++-----
 xen/include/asm-x86/cpuid.h            |  4 +++-
 xen/include/xen/libx86/cpuid.h         | 20 ++++++++++++++++++++
 5 files changed, 30 insertions(+), 6 deletions(-)
 create mode 100644 xen/include/xen/libx86/cpuid.h

diff --git a/tools/include/Makefile b/tools/include/Makefile
index 6665105..568012d 100644
--- a/tools/include/Makefile
+++ b/tools/include/Makefile
@@ -21,6 +21,9 @@ xen/.dir:
 	ln -sf $(addprefix $(XEN_ROOT)/xen/include/xen/,libelf.h elfstructs.h) xen/libelf/
 	ln -s ../xen-foreign xen/foreign
 	ln -sf $(XEN_ROOT)/xen/include/acpi acpi
+ifeq ($(CONFIG_X86),y)
+	ln -sf $(XEN_ROOT)/xen/include/xen/libx86 xen/libx86
+endif
 	touch $@
 
 # Not xen/xsm as that clashes with link to
diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index c5c3cdc..6fbf915 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -27,6 +27,8 @@
 #include <xen/hvm/params.h>
 #include <xen-tools/libs.h>
 
+#include <xen/libx86/cpuid.h>
+
 enum {
 #define XEN_CPUFEATURE(name, value) X86_FEATURE_##name = value,
 #include <xen/arch-x86/cpufeatureset.h>
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.h b/xen/arch/x86/x86_emulate/x86_emulate.h
index c22e774..abd9796 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.h
+++ b/xen/arch/x86/x86_emulate/x86_emulate.h
@@ -23,6 +23,8 @@
 #ifndef __X86_EMULATE_H__
 #define __X86_EMULATE_H__
 
+#include <xen/libx86/cpuid.h>
+
 #define MAX_INST_LEN 15
 
 #if defined(__i386__)
@@ -172,11 +174,6 @@ enum x86_emulate_fpu_type {
     X86EMUL_FPU_none
 };
 
-struct cpuid_leaf
-{
-    uint32_t a, b, c, d;
-};
-
 struct x86_emulate_state;
 
 /*
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index 4113a5e..9637303 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -18,7 +18,9 @@
 #ifndef __ASSEMBLY__
 #include <xen/types.h>
 #include <xen/kernel.h>
-#include <asm/x86_emulate.h>
+
+#include <xen/libx86/cpuid.h>
+
 #include <public/sysctl.h>
 
 extern const uint32_t known_features[FSCAPINTS];
diff --git a/xen/include/xen/libx86/cpuid.h b/xen/include/xen/libx86/cpuid.h
new file mode 100644
index 0000000..3ccc68e
--- /dev/null
+++ b/xen/include/xen/libx86/cpuid.h
@@ -0,0 +1,20 @@
+/* Common data structures and functions consumed by hypervisor and toolstack */
+#ifndef XEN_LIBX86_CPUID_H
+#define XEN_LIBX86_CPUID_H
+
+struct cpuid_leaf
+{
+    uint32_t a, b, c, d;
+};
+
+#endif /* !XEN_LIBX86_CPUID_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH 02/13] libx86: generate cpuid-autogen.h in the libx86 include dir
  2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
  2018-07-03 20:55 ` [PATCH 01/13] libx86: Introduce libx86/cpuid.h Andrew Cooper
@ 2018-07-03 20:55 ` Andrew Cooper
  2018-07-04  7:03   ` Wei Liu
  2018-07-04  8:33   ` Jan Beulich
  2018-07-03 20:55 ` [PATCH 03/13] libx86: Share struct cpuid_policy with userspace Andrew Cooper
                   ` (11 subsequent siblings)
  13 siblings, 2 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-03 20:55 UTC (permalink / raw)
  To: Xen-devel
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Jan Beulich,
	Roger Pau Monné

From: Roger Pau Monné <roger.pau@citrix.com>

This prevents having to generate it inside the libxc folder.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Sergey Dyasli <sergey.dyasli@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>

RFC - I'm not sure a parallel build of Xen and the tools works.
---
 .gitignore                        |  2 +-
 tools/include/Makefile            | 11 +++++++++++
 tools/libxc/Makefile              |  9 ---------
 tools/libxc/xc_cpuid_x86.c        |  1 -
 xen/include/Makefile              |  6 +++---
 xen/include/asm-x86/cpufeatures.h |  2 +-
 xen/include/xen/libx86/cpuid.h    |  2 ++
 7 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/.gitignore b/.gitignore
index 7004349..9c41d6c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -310,7 +310,6 @@ xen/arch/*/efi/runtime.c
 xen/include/headers*.chk
 xen/include/asm
 xen/include/asm-*/asm-offsets.h
-xen/include/asm-x86/cpuid-autogen.h
 xen/include/compat/*
 xen/include/config/
 xen/include/generated/
@@ -318,6 +317,7 @@ xen/include/public/public
 xen/include/xen/*.new
 xen/include/xen/acm_policy.h
 xen/include/xen/compile.h
+xen/include/xen/libx86/cpuid-autogen.h
 xen/test/livepatch/config.h
 xen/test/livepatch/xen_bye_world.livepatch
 xen/test/livepatch/xen_hello_world.livepatch
diff --git a/tools/include/Makefile b/tools/include/Makefile
index 568012d..fc99da9 100644
--- a/tools/include/Makefile
+++ b/tools/include/Makefile
@@ -26,6 +26,17 @@ ifeq ($(CONFIG_X86),y)
 endif
 	touch $@
 
+ifeq ($(CONFIG_X86),y)
+$(XEN_ROOT)/xen/include/xen/libx86/cpuid-autogen.h: $(XEN_ROOT)/xen/include/public/arch-x86/cpufeatureset.h $(XEN_ROOT)/xen/tools/gen-cpuid.py FORCE
+	$(PYTHON) $(XEN_ROOT)/xen/tools/gen-cpuid.py -i $< -o $@.new
+	$(call move-if-changed,$@.new,$@)
+
+all: $(XEN_ROOT)/xen/include/xen/libx86/cpuid-autogen.h
+# NB: Use a FORCE target to always rebuild the autogenerated cpuid header
+FORCE:
+.PHONY: FORCE
+endif
+
 # Not xen/xsm as that clashes with link to
 # $(XEN_ROOT)/xen/include/public/xsm above.
 xen-xsm/.dir: $(XEN_ROOT)/xen/xsm/flask/policy/mkflask.sh \
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index d26bf8d..0ee0813 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -147,15 +147,6 @@ $(eval $(genpath-target))
 
 xc_private.h: _paths.h
 
-ifeq ($(CONFIG_X86),y)
-
-_xc_cpuid_autogen.h: $(XEN_ROOT)/xen/include/public/arch-x86/cpufeatureset.h $(XEN_ROOT)/xen/tools/gen-cpuid.py
-	$(PYTHON) $(XEN_ROOT)/xen/tools/gen-cpuid.py -i $^ -o $@.new
-	$(call move-if-changed,$@.new,$@)
-
-build: _xc_cpuid_autogen.h
-endif
-
 $(CTRL_LIB_OBJS) $(GUEST_LIB_OBJS) \
 $(CTRL_PIC_OBJS) $(GUEST_PIC_OBJS): xc_private.h
 
diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index 6fbf915..06f104d 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -33,7 +33,6 @@ enum {
 #define XEN_CPUFEATURE(name, value) X86_FEATURE_##name = value,
 #include <xen/arch-x86/cpufeatureset.h>
 };
-#include "_xc_cpuid_autogen.h"
 
 #define bitmaskof(idx)      (1u << ((idx) & 31))
 #define featureword_of(idx) ((idx) >> 5)
diff --git a/xen/include/Makefile b/xen/include/Makefile
index 7c5034e..dd18316 100644
--- a/xen/include/Makefile
+++ b/xen/include/Makefile
@@ -142,13 +142,13 @@ endif
 
 ifeq ($(XEN_TARGET_ARCH),x86_64)
 
-$(BASEDIR)/include/asm-x86/cpuid-autogen.h: $(BASEDIR)/include/public/arch-x86/cpufeatureset.h $(BASEDIR)/tools/gen-cpuid.py FORCE
+$(BASEDIR)/include/xen/libx86/cpuid-autogen.h: $(BASEDIR)/include/public/arch-x86/cpufeatureset.h $(BASEDIR)/tools/gen-cpuid.py FORCE
 	$(PYTHON) $(BASEDIR)/tools/gen-cpuid.py -i $< -o $@.new
 	$(call move-if-changed,$@.new,$@)
 
-all: $(BASEDIR)/include/asm-x86/cpuid-autogen.h
+all: $(BASEDIR)/include/xen/libx86/cpuid-autogen.h
 endif
 
 clean::
 	rm -rf compat config generated headers*.chk
-	rm -f $(BASEDIR)/include/asm-x86/cpuid-autogen.h
+	rm -f $(BASEDIR)/include/xen/libx86/cpuid-autogen.h
diff --git a/xen/include/asm-x86/cpufeatures.h b/xen/include/asm-x86/cpufeatures.h
index 8e5cc53..b7ceb20 100644
--- a/xen/include/asm-x86/cpufeatures.h
+++ b/xen/include/asm-x86/cpufeatures.h
@@ -2,7 +2,7 @@
  * Explicitly intended for multiple inclusion.
  */
 
-#include <asm/cpuid-autogen.h>
+#include <xen/libx86/cpuid-autogen.h>
 
 #define FSCAPINTS FEATURESET_NR_ENTRIES
 
diff --git a/xen/include/xen/libx86/cpuid.h b/xen/include/xen/libx86/cpuid.h
index 3ccc68e..8f101ba 100644
--- a/xen/include/xen/libx86/cpuid.h
+++ b/xen/include/xen/libx86/cpuid.h
@@ -2,6 +2,8 @@
 #ifndef XEN_LIBX86_CPUID_H
 #define XEN_LIBX86_CPUID_H
 
+#include <xen/libx86/cpuid-autogen.h>
+
 struct cpuid_leaf
 {
     uint32_t a, b, c, d;
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH 03/13] libx86: Share struct cpuid_policy with userspace
  2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
  2018-07-03 20:55 ` [PATCH 01/13] libx86: Introduce libx86/cpuid.h Andrew Cooper
  2018-07-03 20:55 ` [PATCH 02/13] libx86: generate cpuid-autogen.h in the libx86 include dir Andrew Cooper
@ 2018-07-03 20:55 ` Andrew Cooper
  2018-07-04  7:08   ` Wei Liu
  2018-07-04  8:36   ` Jan Beulich
  2018-07-03 20:55 ` [PATCH 04/13] libx86: introduce a libx86 shared library Andrew Cooper
                   ` (10 subsequent siblings)
  13 siblings, 2 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-03 20:55 UTC (permalink / raw)
  To: Xen-devel
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Jan Beulich,
	Roger Pau Monné

From: Roger Pau Monné <roger.pau@citrix.com>

No functional change.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Sergey Dyasli <sergey.dyasli@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
---
 tools/libxc/xc_cpuid_x86.c             |   2 +
 tools/tests/x86_emulator/x86-emulate.h |   2 +
 xen/include/asm-x86/cpuid.h            | 219 ---------------------------------
 xen/include/xen/libx86/cpuid.h         | 219 +++++++++++++++++++++++++++++++++
 4 files changed, 223 insertions(+), 219 deletions(-)

diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index 06f104d..5ee4a2d 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -27,6 +27,8 @@
 #include <xen/hvm/params.h>
 #include <xen-tools/libs.h>
 
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+
 #include <xen/libx86/cpuid.h>
 
 enum {
diff --git a/tools/tests/x86_emulator/x86-emulate.h b/tools/tests/x86_emulator/x86-emulate.h
index c5e85de..b204901 100644
--- a/tools/tests/x86_emulator/x86-emulate.h
+++ b/tools/tests/x86_emulator/x86-emulate.h
@@ -21,6 +21,8 @@
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
 
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+
 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
 /* Force a compilation error if condition is true */
 #define BUILD_BUG_ON(cond) ({ _Static_assert(!(cond), "!(" #cond ")"); })
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index 9637303..7a3f2f4 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -4,17 +4,6 @@
 #include <asm/cpufeatureset.h>
 #include <asm/percpu.h>
 
-#define FEATURESET_1d     0 /* 0x00000001.edx      */
-#define FEATURESET_1c     1 /* 0x00000001.ecx      */
-#define FEATURESET_e1d    2 /* 0x80000001.edx      */
-#define FEATURESET_e1c    3 /* 0x80000001.ecx      */
-#define FEATURESET_Da1    4 /* 0x0000000d:1.eax    */
-#define FEATURESET_7b0    5 /* 0x00000007:0.ebx    */
-#define FEATURESET_7c0    6 /* 0x00000007:0.ecx    */
-#define FEATURESET_e7d    7 /* 0x80000007.edx      */
-#define FEATURESET_e8b    8 /* 0x80000008.ebx      */
-#define FEATURESET_7d0    9 /* 0x00000007:0.edx    */
-
 #ifndef __ASSEMBLY__
 #include <xen/types.h>
 #include <xen/kernel.h>
@@ -60,214 +49,6 @@ DECLARE_PER_CPU(struct cpuidmasks, cpuidmasks);
 /* Default masking MSR values, calculated at boot. */
 extern struct cpuidmasks cpuidmask_defaults;
 
-#define CPUID_GUEST_NR_BASIC      (0xdu + 1)
-#define CPUID_GUEST_NR_FEAT       (0u + 1)
-#define CPUID_GUEST_NR_CACHE      (5u + 1)
-#define CPUID_GUEST_NR_TOPO       (1u + 1)
-#define CPUID_GUEST_NR_XSTATE     (62u + 1)
-#define CPUID_GUEST_NR_EXTD_INTEL (0x8u + 1)
-#define CPUID_GUEST_NR_EXTD_AMD   (0x1cu + 1)
-#define CPUID_GUEST_NR_EXTD       MAX(CPUID_GUEST_NR_EXTD_INTEL, \
-                                      CPUID_GUEST_NR_EXTD_AMD)
-
-struct cpuid_policy
-{
-#define DECL_BITFIELD(word) _DECL_BITFIELD(FEATURESET_ ## word)
-#define _DECL_BITFIELD(x)   __DECL_BITFIELD(x)
-#define __DECL_BITFIELD(x)  CPUID_BITFIELD_ ## x
-
-    /* Basic leaves: 0x000000xx */
-    union {
-        struct cpuid_leaf raw[CPUID_GUEST_NR_BASIC];
-        struct {
-            /* Leaf 0x0 - Max and vendor. */
-            uint32_t max_leaf, vendor_ebx, vendor_ecx, vendor_edx;
-
-            /* Leaf 0x1 - Family/model/stepping and features. */
-            uint32_t raw_fms;
-            uint8_t :8,       /* Brand ID. */
-                clflush_size, /* Number of 8-byte blocks per cache line. */
-                lppp,         /* Logical processors per package. */
-                apic_id;      /* Initial APIC ID. */
-            union {
-                uint32_t _1c;
-                struct { DECL_BITFIELD(1c); };
-            };
-            union {
-                uint32_t _1d;
-                struct { DECL_BITFIELD(1d); };
-            };
-
-            /* Leaf 0x2 - TLB/Cache/Prefetch. */
-            uint8_t l2_nr_queries; /* Documented as fixed to 1. */
-            uint8_t l2_desc[15];
-
-            uint64_t :64, :64; /* Leaf 0x3 - PSN. */
-            uint64_t :64, :64; /* Leaf 0x4 - Structured Cache. */
-            uint64_t :64, :64; /* Leaf 0x5 - MONITOR. */
-            uint64_t :64, :64; /* Leaf 0x6 - Therm/Perf. */
-            uint64_t :64, :64; /* Leaf 0x7 - Structured Features. */
-            uint64_t :64, :64; /* Leaf 0x8 - rsvd */
-            uint64_t :64, :64; /* Leaf 0x9 - DCA */
-
-            /* Leaf 0xa - Intel PMU. */
-            uint8_t pmu_version, _pmu[15];
-
-            uint64_t :64, :64; /* Leaf 0xb - Topology. */
-            uint64_t :64, :64; /* Leaf 0xc - rsvd */
-            uint64_t :64, :64; /* Leaf 0xd - XSTATE. */
-        };
-    } basic;
-
-    /* Structured cache leaf: 0x00000004[xx] */
-    union {
-        struct cpuid_leaf raw[CPUID_GUEST_NR_CACHE];
-        struct cpuid_cache_leaf {
-            uint32_t type:5,
-                :27, :32, :32, :32;
-        } subleaf[CPUID_GUEST_NR_CACHE];
-    } cache;
-
-    /* Structured feature leaf: 0x00000007[xx] */
-    union {
-        struct cpuid_leaf raw[CPUID_GUEST_NR_FEAT];
-        struct {
-            /* Subleaf 0. */
-            uint32_t max_subleaf;
-            union {
-                uint32_t _7b0;
-                struct { DECL_BITFIELD(7b0); };
-            };
-            union {
-                uint32_t _7c0;
-                struct { DECL_BITFIELD(7c0); };
-            };
-            union {
-                uint32_t _7d0;
-                struct { DECL_BITFIELD(7d0); };
-            };
-        };
-    } feat;
-
-    /* Extended topology enumeration: 0x0000000B[xx] */
-    union {
-        struct cpuid_leaf raw[CPUID_GUEST_NR_TOPO];
-        struct cpuid_topo_leaf {
-            uint32_t id_shift:5, :27;
-            uint16_t nr_logical, :16;
-            uint8_t level, type, :8, :8;
-            uint32_t x2apic_id;
-        } subleaf[CPUID_GUEST_NR_TOPO];
-    } topo;
-
-    /* Xstate feature leaf: 0x0000000D[xx] */
-    union {
-        struct cpuid_leaf raw[CPUID_GUEST_NR_XSTATE];
-
-        struct {
-            /* Subleaf 0. */
-            uint32_t xcr0_low, /* b */:32, max_size, xcr0_high;
-
-            /* Subleaf 1. */
-            union {
-                uint32_t Da1;
-                struct { DECL_BITFIELD(Da1); };
-            };
-            uint32_t /* b */:32, xss_low, xss_high;
-        };
-
-        /* Per-component common state.  Valid for i >= 2. */
-        struct {
-            uint32_t size, offset;
-            bool xss:1, align:1;
-            uint32_t _res_d;
-        } comp[CPUID_GUEST_NR_XSTATE];
-    } xstate;
-
-    /* Extended leaves: 0x800000xx */
-    union {
-        struct cpuid_leaf raw[CPUID_GUEST_NR_EXTD];
-        struct {
-            /* Leaf 0x80000000 - Max and vendor. */
-            uint32_t max_leaf, vendor_ebx, vendor_ecx, vendor_edx;
-
-            /* Leaf 0x80000001 - Family/model/stepping and features. */
-            uint32_t raw_fms, /* b */:32;
-            union {
-                uint32_t e1c;
-                struct { DECL_BITFIELD(e1c); };
-            };
-            union {
-                uint32_t e1d;
-                struct { DECL_BITFIELD(e1d); };
-            };
-
-            uint64_t :64, :64; /* Brand string. */
-            uint64_t :64, :64; /* Brand string. */
-            uint64_t :64, :64; /* Brand string. */
-            uint64_t :64, :64; /* L1 cache/TLB. */
-            uint64_t :64, :64; /* L2/3 cache/TLB. */
-
-            /* Leaf 0x80000007 - Advanced Power Management. */
-            uint32_t /* a */:32, /* b */:32, /* c */:32;
-            union {
-                uint32_t e7d;
-                struct { DECL_BITFIELD(e7d); };
-            };
-
-            /* Leaf 0x80000008 - Misc addr/feature info. */
-            uint8_t maxphysaddr, maxlinaddr, :8, :8;
-            union {
-                uint32_t e8b;
-                struct { DECL_BITFIELD(e8b); };
-            };
-            uint32_t /* c */:32, /* d */:32;
-        };
-    } extd;
-
-#undef __DECL_BITFIELD
-#undef _DECL_BITFIELD
-#undef DECL_BITFIELD
-
-    /* Toolstack selected Hypervisor max_leaf (if non-zero). */
-    uint8_t hv_limit, hv2_limit;
-
-    /* Value calculated from raw data above. */
-    uint8_t x86_vendor;
-};
-
-/* Fill in a featureset bitmap from a CPUID policy. */
-static inline void cpuid_policy_to_featureset(
-    const struct cpuid_policy *p, uint32_t fs[FSCAPINTS])
-{
-    fs[FEATURESET_1d]  = p->basic._1d;
-    fs[FEATURESET_1c]  = p->basic._1c;
-    fs[FEATURESET_e1d] = p->extd.e1d;
-    fs[FEATURESET_e1c] = p->extd.e1c;
-    fs[FEATURESET_Da1] = p->xstate.Da1;
-    fs[FEATURESET_7b0] = p->feat._7b0;
-    fs[FEATURESET_7c0] = p->feat._7c0;
-    fs[FEATURESET_e7d] = p->extd.e7d;
-    fs[FEATURESET_e8b] = p->extd.e8b;
-    fs[FEATURESET_7d0] = p->feat._7d0;
-}
-
-/* Fill in a CPUID policy from a featureset bitmap. */
-static inline void cpuid_featureset_to_policy(
-    const uint32_t fs[FSCAPINTS], struct cpuid_policy *p)
-{
-    p->basic._1d  = fs[FEATURESET_1d];
-    p->basic._1c  = fs[FEATURESET_1c];
-    p->extd.e1d   = fs[FEATURESET_e1d];
-    p->extd.e1c   = fs[FEATURESET_e1c];
-    p->xstate.Da1 = fs[FEATURESET_Da1];
-    p->feat._7b0  = fs[FEATURESET_7b0];
-    p->feat._7c0  = fs[FEATURESET_7c0];
-    p->extd.e7d   = fs[FEATURESET_e7d];
-    p->extd.e8b   = fs[FEATURESET_e8b];
-    p->feat._7d0  = fs[FEATURESET_7d0];
-}
-
 extern struct cpuid_policy raw_cpuid_policy, host_cpuid_policy,
     pv_max_cpuid_policy, hvm_max_cpuid_policy;
 
diff --git a/xen/include/xen/libx86/cpuid.h b/xen/include/xen/libx86/cpuid.h
index 8f101ba..69bd8a9 100644
--- a/xen/include/xen/libx86/cpuid.h
+++ b/xen/include/xen/libx86/cpuid.h
@@ -4,11 +4,230 @@
 
 #include <xen/libx86/cpuid-autogen.h>
 
+#define FEATURESET_1d     0 /* 0x00000001.edx      */
+#define FEATURESET_1c     1 /* 0x00000001.ecx      */
+#define FEATURESET_e1d    2 /* 0x80000001.edx      */
+#define FEATURESET_e1c    3 /* 0x80000001.ecx      */
+#define FEATURESET_Da1    4 /* 0x0000000d:1.eax    */
+#define FEATURESET_7b0    5 /* 0x00000007:0.ebx    */
+#define FEATURESET_7c0    6 /* 0x00000007:0.ecx    */
+#define FEATURESET_e7d    7 /* 0x80000007.edx      */
+#define FEATURESET_e8b    8 /* 0x80000008.ebx      */
+#define FEATURESET_7d0    9 /* 0x00000007:0.edx    */
+
 struct cpuid_leaf
 {
     uint32_t a, b, c, d;
 };
 
+#define CPUID_GUEST_NR_BASIC      (0xdu + 1)
+#define CPUID_GUEST_NR_FEAT       (0u + 1)
+#define CPUID_GUEST_NR_CACHE      (5u + 1)
+#define CPUID_GUEST_NR_TOPO       (1u + 1)
+#define CPUID_GUEST_NR_XSTATE     (62u + 1)
+#define CPUID_GUEST_NR_EXTD_INTEL (0x8u + 1)
+#define CPUID_GUEST_NR_EXTD_AMD   (0x1cu + 1)
+#define CPUID_GUEST_NR_EXTD       MAX(CPUID_GUEST_NR_EXTD_INTEL, \
+                                      CPUID_GUEST_NR_EXTD_AMD)
+
+struct cpuid_policy
+{
+#define DECL_BITFIELD(word) _DECL_BITFIELD(FEATURESET_ ## word)
+#define _DECL_BITFIELD(x)   __DECL_BITFIELD(x)
+#define __DECL_BITFIELD(x)  CPUID_BITFIELD_ ## x
+
+    /* Basic leaves: 0x000000xx */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_BASIC];
+        struct {
+            /* Leaf 0x0 - Max and vendor. */
+            uint32_t max_leaf, vendor_ebx, vendor_ecx, vendor_edx;
+
+            /* Leaf 0x1 - Family/model/stepping and features. */
+            uint32_t raw_fms;
+            uint8_t :8,       /* Brand ID. */
+                clflush_size, /* Number of 8-byte blocks per cache line. */
+                lppp,         /* Logical processors per package. */
+                apic_id;      /* Initial APIC ID. */
+            union {
+                uint32_t _1c;
+                struct { DECL_BITFIELD(1c); };
+            };
+            union {
+                uint32_t _1d;
+                struct { DECL_BITFIELD(1d); };
+            };
+
+            /* Leaf 0x2 - TLB/Cache/Prefetch. */
+            uint8_t l2_nr_queries; /* Documented as fixed to 1. */
+            uint8_t l2_desc[15];
+
+            uint64_t :64, :64; /* Leaf 0x3 - PSN. */
+            uint64_t :64, :64; /* Leaf 0x4 - Structured Cache. */
+            uint64_t :64, :64; /* Leaf 0x5 - MONITOR. */
+            uint64_t :64, :64; /* Leaf 0x6 - Therm/Perf. */
+            uint64_t :64, :64; /* Leaf 0x7 - Structured Features. */
+            uint64_t :64, :64; /* Leaf 0x8 - rsvd */
+            uint64_t :64, :64; /* Leaf 0x9 - DCA */
+
+            /* Leaf 0xa - Intel PMU. */
+            uint8_t pmu_version, _pmu[15];
+
+            uint64_t :64, :64; /* Leaf 0xb - Topology. */
+            uint64_t :64, :64; /* Leaf 0xc - rsvd */
+            uint64_t :64, :64; /* Leaf 0xd - XSTATE. */
+        };
+    } basic;
+
+    /* Structured cache leaf: 0x00000004[xx] */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_CACHE];
+        struct cpuid_cache_leaf {
+            uint32_t type:5,
+                :27, :32, :32, :32;
+        } subleaf[CPUID_GUEST_NR_CACHE];
+    } cache;
+
+    /* Structured feature leaf: 0x00000007[xx] */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_FEAT];
+        struct {
+            /* Subleaf 0. */
+            uint32_t max_subleaf;
+            union {
+                uint32_t _7b0;
+                struct { DECL_BITFIELD(7b0); };
+            };
+            union {
+                uint32_t _7c0;
+                struct { DECL_BITFIELD(7c0); };
+            };
+            union {
+                uint32_t _7d0;
+                struct { DECL_BITFIELD(7d0); };
+            };
+        };
+    } feat;
+
+    /* Extended topology enumeration: 0x0000000B[xx] */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_TOPO];
+        struct cpuid_topo_leaf {
+            uint32_t id_shift:5, :27;
+            uint16_t nr_logical, :16;
+            uint8_t level, type, :8, :8;
+            uint32_t x2apic_id;
+        } subleaf[CPUID_GUEST_NR_TOPO];
+    } topo;
+
+    /* Xstate feature leaf: 0x0000000D[xx] */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_XSTATE];
+
+        struct {
+            /* Subleaf 0. */
+            uint32_t xcr0_low, /* b */:32, max_size, xcr0_high;
+
+            /* Subleaf 1. */
+            union {
+                uint32_t Da1;
+                struct { DECL_BITFIELD(Da1); };
+            };
+            uint32_t /* b */:32, xss_low, xss_high;
+        };
+
+        /* Per-component common state.  Valid for i >= 2. */
+        struct {
+            uint32_t size, offset;
+            bool xss:1, align:1;
+            uint32_t _res_d;
+        } comp[CPUID_GUEST_NR_XSTATE];
+    } xstate;
+
+    /* Extended leaves: 0x800000xx */
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_EXTD];
+        struct {
+            /* Leaf 0x80000000 - Max and vendor. */
+            uint32_t max_leaf, vendor_ebx, vendor_ecx, vendor_edx;
+
+            /* Leaf 0x80000001 - Family/model/stepping and features. */
+            uint32_t raw_fms, /* b */:32;
+            union {
+                uint32_t e1c;
+                struct { DECL_BITFIELD(e1c); };
+            };
+            union {
+                uint32_t e1d;
+                struct { DECL_BITFIELD(e1d); };
+            };
+
+            uint64_t :64, :64; /* Brand string. */
+            uint64_t :64, :64; /* Brand string. */
+            uint64_t :64, :64; /* Brand string. */
+            uint64_t :64, :64; /* L1 cache/TLB. */
+            uint64_t :64, :64; /* L2/3 cache/TLB. */
+
+            /* Leaf 0x80000007 - Advanced Power Management. */
+            uint32_t /* a */:32, /* b */:32, /* c */:32;
+            union {
+                uint32_t e7d;
+                struct { DECL_BITFIELD(e7d); };
+            };
+
+            /* Leaf 0x80000008 - Misc addr/feature info. */
+            uint8_t maxphysaddr, maxlinaddr, :8, :8;
+            union {
+                uint32_t e8b;
+                struct { DECL_BITFIELD(e8b); };
+            };
+            uint32_t /* c */:32, /* d */:32;
+        };
+    } extd;
+
+#undef __DECL_BITFIELD
+#undef _DECL_BITFIELD
+#undef DECL_BITFIELD
+
+    /* Toolstack selected Hypervisor max_leaf (if non-zero). */
+    uint8_t hv_limit, hv2_limit;
+
+    /* Value calculated from raw data above. */
+    uint8_t x86_vendor;
+};
+
+/* Fill in a featureset bitmap from a CPUID policy. */
+static inline void cpuid_policy_to_featureset(
+    const struct cpuid_policy *p, uint32_t fs[FEATURESET_NR_ENTRIES])
+{
+    fs[FEATURESET_1d]  = p->basic._1d;
+    fs[FEATURESET_1c]  = p->basic._1c;
+    fs[FEATURESET_e1d] = p->extd.e1d;
+    fs[FEATURESET_e1c] = p->extd.e1c;
+    fs[FEATURESET_Da1] = p->xstate.Da1;
+    fs[FEATURESET_7b0] = p->feat._7b0;
+    fs[FEATURESET_7c0] = p->feat._7c0;
+    fs[FEATURESET_e7d] = p->extd.e7d;
+    fs[FEATURESET_e8b] = p->extd.e8b;
+    fs[FEATURESET_7d0] = p->feat._7d0;
+}
+
+/* Fill in a CPUID policy from a featureset bitmap. */
+static inline void cpuid_featureset_to_policy(
+    const uint32_t fs[FEATURESET_NR_ENTRIES], struct cpuid_policy *p)
+{
+    p->basic._1d  = fs[FEATURESET_1d];
+    p->basic._1c  = fs[FEATURESET_1c];
+    p->extd.e1d   = fs[FEATURESET_e1d];
+    p->extd.e1c   = fs[FEATURESET_e1c];
+    p->xstate.Da1 = fs[FEATURESET_Da1];
+    p->feat._7b0  = fs[FEATURESET_7b0];
+    p->feat._7c0  = fs[FEATURESET_7c0];
+    p->extd.e7d   = fs[FEATURESET_e7d];
+    p->extd.e8b   = fs[FEATURESET_e8b];
+    p->feat._7d0  = fs[FEATURESET_7d0];
+}
+
 #endif /* !XEN_LIBX86_CPUID_H */
 
 /*
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH 04/13] libx86: introduce a libx86 shared library
  2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
                   ` (2 preceding siblings ...)
  2018-07-03 20:55 ` [PATCH 03/13] libx86: Share struct cpuid_policy with userspace Andrew Cooper
@ 2018-07-03 20:55 ` Andrew Cooper
  2018-07-04  7:20   ` Wei Liu
  2018-07-04  8:42   ` Jan Beulich
  2018-07-03 20:55 ` [PATCH 05/13] libx86: Introduce libx86/msr.h and share msr_{domain, vcpu}_policy with userspace Andrew Cooper
                   ` (9 subsequent siblings)
  13 siblings, 2 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-03 20:55 UTC (permalink / raw)
  To: Xen-devel
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Jan Beulich,
	Roger Pau Monné

From: Roger Pau Monné <roger.pau@citrix.com>

Move x86_cpuid_lookup_deep_deps() into the shared library, removing the
individual copies from the hypervisor and libxc respectively.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Sergey Dyasli <sergey.dyasli@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
---
 tools/libxc/Makefile               |  5 +++++
 tools/libxc/include/xenctrl.h      |  1 -
 tools/libxc/xc_cpuid_x86.c         | 29 +------------------------
 xen/arch/x86/cpu/common.c          |  2 +-
 xen/arch/x86/cpuid.c               | 32 +--------------------------
 xen/common/Makefile                |  1 +
 xen/common/libx86/Makefile         |  1 +
 xen/common/libx86/cpuid.c          | 44 ++++++++++++++++++++++++++++++++++++++
 xen/common/libx86/libx86-private.h | 42 ++++++++++++++++++++++++++++++++++++
 xen/include/asm-x86/cpuid.h        |  2 --
 xen/include/xen/libx86/cpuid.h     |  2 ++
 11 files changed, 98 insertions(+), 63 deletions(-)
 create mode 100644 xen/common/libx86/Makefile
 create mode 100644 xen/common/libx86/cpuid.c
 create mode 100644 xen/common/libx86/libx86-private.h

diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 0ee0813..f534d90 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -80,6 +80,11 @@ GUEST_SRCS-y += $(ELF_SRCS-y)
 $(patsubst %.c,%.o,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
 $(patsubst %.c,%.opic,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
 
+# Add libx86 to the build
+vpath %.c ../../xen/common/libx86
+
+GUEST_SRCS-$(CONFIG_X86)     += cpuid.c
+
 # new domain builder
 GUEST_SRCS-y                 += xc_dom_core.c xc_dom_boot.c
 GUEST_SRCS-y                 += xc_dom_elfloader.c
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index e8285db..70f54e6 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2547,7 +2547,6 @@ enum xc_static_cpu_featuremask {
     XC_FEATUREMASK_DEEP_FEATURES,
 };
 const uint32_t *xc_get_static_cpu_featuremask(enum xc_static_cpu_featuremask);
-const uint32_t *xc_get_feature_deep_deps(uint32_t feature);
 
 #endif
 
diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index 5ee4a2d..8c7a951 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -133,33 +133,6 @@ const uint32_t *xc_get_static_cpu_featuremask(
     }
 }
 
-const uint32_t *xc_get_feature_deep_deps(uint32_t feature)
-{
-    static const struct {
-        uint32_t feature;
-        uint32_t fs[FEATURESET_NR_ENTRIES];
-    } deep_deps[] = INIT_DEEP_DEPS;
-
-    unsigned int start = 0, end = ARRAY_SIZE(deep_deps);
-
-    BUILD_BUG_ON(ARRAY_SIZE(deep_deps) != NR_DEEP_DEPS);
-
-    /* deep_deps[] is sorted.  Perform a binary search. */
-    while ( start < end )
-    {
-        unsigned int mid = start + ((end - start) / 2);
-
-        if ( deep_deps[mid].feature > feature )
-            end = mid;
-        else if ( deep_deps[mid].feature < feature )
-            start = mid + 1;
-        else
-            return deep_deps[mid].fs;
-    }
-
-    return NULL;
-}
-
 struct cpuid_domain_info
 {
     enum
@@ -679,7 +652,7 @@ static void sanitise_featureset(struct cpuid_domain_info *info)
         const uint32_t *dfs;
 
         if ( !test_bit(b, disabled_features) ||
-             !(dfs = xc_get_feature_deep_deps(b)) )
+             !(dfs = x86_cpuid_lookup_deep_deps(b)) )
              continue;
 
         for ( i = 0; i < ARRAY_SIZE(disabled_features); ++i )
diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
index bdd45c3..ad3dbe7 100644
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -62,7 +62,7 @@ void __init setup_clear_cpu_cap(unsigned int cap)
 		       __builtin_return_address(0), cap);
 
 	__clear_bit(cap, boot_cpu_data.x86_capability);
-	dfs = lookup_deep_deps(cap);
+	dfs = x86_cpuid_lookup_deep_deps(cap);
 
 	if (!dfs)
 		return;
diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index c33c6d4..461aa8c 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -97,7 +97,7 @@ static void sanitise_featureset(uint32_t *fs)
     for_each_set_bit(i, (void *)disabled_features,
                      sizeof(disabled_features) * 8)
     {
-        const uint32_t *dfs = lookup_deep_deps(i);
+        const uint32_t *dfs = x86_cpuid_lookup_deep_deps(i);
         unsigned int j;
 
         ASSERT(dfs); /* deep_features[] should guarentee this. */
@@ -544,36 +544,6 @@ bool recheck_cpu_features(unsigned int cpu)
     return okay;
 }
 
-const uint32_t *lookup_deep_deps(uint32_t feature)
-{
-    static const struct {
-        uint32_t feature;
-        uint32_t fs[FSCAPINTS];
-    } deep_deps[] = INIT_DEEP_DEPS;
-    unsigned int start = 0, end = ARRAY_SIZE(deep_deps);
-
-    BUILD_BUG_ON(ARRAY_SIZE(deep_deps) != NR_DEEP_DEPS);
-
-    /* Fast early exit. */
-    if ( !test_bit(feature, deep_features) )
-        return NULL;
-
-    /* deep_deps[] is sorted.  Perform a binary search. */
-    while ( start < end )
-    {
-        unsigned int mid = start + ((end - start) / 2);
-
-        if ( deep_deps[mid].feature > feature )
-            end = mid;
-        else if ( deep_deps[mid].feature < feature )
-            start = mid + 1;
-        else
-            return deep_deps[mid].fs;
-    }
-
-    return NULL;
-}
-
 void recalculate_cpuid_policy(struct domain *d)
 {
     struct cpuid_policy *p = d->arch.cpuid;
diff --git a/xen/common/Makefile b/xen/common/Makefile
index 24d4752..91058a0 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -80,3 +80,4 @@ subdir-$(CONFIG_UBSAN) += ubsan
 
 subdir-y += libelf
 subdir-$(CONFIG_HAS_DEVICE_TREE) += libfdt
+subdir-$(CONFIG_X86) += libx86
diff --git a/xen/common/libx86/Makefile b/xen/common/libx86/Makefile
new file mode 100644
index 0000000..3fb2e0b
--- /dev/null
+++ b/xen/common/libx86/Makefile
@@ -0,0 +1 @@
+obj-y += cpuid.o
diff --git a/xen/common/libx86/cpuid.c b/xen/common/libx86/cpuid.c
new file mode 100644
index 0000000..9fa7d95
--- /dev/null
+++ b/xen/common/libx86/cpuid.c
@@ -0,0 +1,44 @@
+#include "libx86-private.h"
+
+#include <xen/libx86/cpuid.h>
+
+const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature)
+{
+    static const uint32_t deep_features[] = INIT_DEEP_FEATURES;
+    static const struct {
+        uint32_t feature;
+        uint32_t fs[FEATURESET_NR_ENTRIES];
+    } deep_deps[] = INIT_DEEP_DEPS;
+    unsigned int start = 0, end = ARRAY_SIZE(deep_deps);
+
+    BUILD_BUG_ON(ARRAY_SIZE(deep_deps) != NR_DEEP_DEPS);
+
+    /* Fast early exit. */
+    if ( !test_bit(feature, deep_features) )
+        return NULL;
+
+    /* deep_deps[] is sorted.  Perform a binary search. */
+    while ( start < end )
+    {
+        unsigned int mid = start + ((end - start) / 2);
+
+        if ( deep_deps[mid].feature > feature )
+            end = mid;
+        else if ( deep_deps[mid].feature < feature )
+            start = mid + 1;
+        else
+            return deep_deps[mid].fs;
+    }
+
+    return NULL;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/libx86/libx86-private.h b/xen/common/libx86/libx86-private.h
new file mode 100644
index 0000000..b9f42f7
--- /dev/null
+++ b/xen/common/libx86/libx86-private.h
@@ -0,0 +1,42 @@
+#ifndef XEN_LIBX86_PRIVATE_H
+#define XEN_LIBX86_PRIVATE_H
+
+#ifdef __XEN__
+
+#include <xen/bitops.h>
+#include <xen/kernel.h>
+#include <xen/lib.h>
+#include <xen/types.h>
+
+#else
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#include <xen-tools/libs.h>
+
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+
+#define ARRAY_SIZE(x) (sizeof x / sizeof *x)
+
+static inline bool test_bit(unsigned int bit, const void *vaddr)
+{
+    const char *addr = vaddr;
+
+    return addr[bit / 8] & (1u << (bit % 8));
+}
+
+#endif /* __XEN__ */
+
+#endif /* XEN_LIBX86_PRIVATE_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index 7a3f2f4..ea79445 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -17,8 +17,6 @@ extern const uint32_t special_features[FSCAPINTS];
 
 void init_guest_cpuid(void);
 
-const uint32_t *lookup_deep_deps(uint32_t feature);
-
 /*
  * Expected levelling capabilities (given cpuid vendor/family information),
  * and levelling capabilities actually available (given MSR probing).
diff --git a/xen/include/xen/libx86/cpuid.h b/xen/include/xen/libx86/cpuid.h
index 69bd8a9..233fa13 100644
--- a/xen/include/xen/libx86/cpuid.h
+++ b/xen/include/xen/libx86/cpuid.h
@@ -228,6 +228,8 @@ static inline void cpuid_featureset_to_policy(
     p->feat._7d0  = fs[FEATURESET_7d0];
 }
 
+const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature);
+
 #endif /* !XEN_LIBX86_CPUID_H */
 
 /*
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH 05/13] libx86: Introduce libx86/msr.h and share msr_{domain, vcpu}_policy with userspace
  2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
                   ` (3 preceding siblings ...)
  2018-07-03 20:55 ` [PATCH 04/13] libx86: introduce a libx86 shared library Andrew Cooper
@ 2018-07-03 20:55 ` Andrew Cooper
  2018-07-04  7:21   ` Wei Liu
  2018-07-04  8:43   ` Jan Beulich
  2018-07-03 20:55 ` [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object Andrew Cooper
                   ` (8 subsequent siblings)
  13 siblings, 2 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-03 20:55 UTC (permalink / raw)
  To: Xen-devel
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Jan Beulich,
	Roger Pau Monné

No functional change.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Sergey Dyasli <sergey.dyasli@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
---
 tools/libxc/xc_cpuid_x86.c   |  1 +
 xen/include/asm-x86/msr.h    | 51 +++-----------------------------------
 xen/include/xen/libx86/msr.h | 58 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+), 48 deletions(-)
 create mode 100644 xen/include/xen/libx86/msr.h

diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index 8c7a951..900c639 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -30,6 +30,7 @@
 #define MAX(x, y) ((x) > (y) ? (x) : (y))
 
 #include <xen/libx86/cpuid.h>
+#include <xen/libx86/msr.h>
 
 enum {
 #define XEN_CPUFEATURE(name, value) X86_FEATURE_##name = value,
diff --git a/xen/include/asm-x86/msr.h b/xen/include/asm-x86/msr.h
index d4064f4..d8cb638 100644
--- a/xen/include/asm-x86/msr.h
+++ b/xen/include/asm-x86/msr.h
@@ -8,6 +8,9 @@
 #include <xen/types.h>
 #include <xen/percpu.h>
 #include <xen/errno.h>
+
+#include <xen/libx86/msr.h>
+
 #include <asm/asm_defns.h>
 #include <asm/cpufeature.h>
 
@@ -257,26 +260,6 @@ static inline void wrmsr_tsc_aux(uint32_t val)
     }
 }
 
-/* MSR policy object for shared per-domain MSRs */
-struct msr_domain_policy
-{
-    /*
-     * 0x000000ce - MSR_INTEL_PLATFORM_INFO
-     *
-     * This MSR is non-architectural, but for simplicy we allow it to be read
-     * unconditionally.  CPUID Faulting support can be fully emulated for HVM
-     * guests so can be offered unconditionally, while support for PV guests
-     * is dependent on real hardware support.
-     */
-    union {
-        uint32_t raw;
-        struct {
-            uint32_t :31;
-            bool cpuid_faulting:1;
-        };
-    } plaform_info;
-};
-
 /* RAW msr domain policy: contains the actual values from H/W MSRs */
 extern struct msr_domain_policy raw_msr_domain_policy;
 /*
@@ -285,34 +268,6 @@ extern struct msr_domain_policy raw_msr_domain_policy;
  */
 extern struct msr_domain_policy host_msr_domain_policy;
 
-/* MSR policy object for per-vCPU MSRs */
-struct msr_vcpu_policy
-{
-    /* 0x00000048 - MSR_SPEC_CTRL */
-    struct {
-        /*
-         * Only the bottom two bits are defined, so no need to waste space
-         * with uint64_t at the moment, but use uint32_t for the convenience
-         * of the assembly code.
-         */
-        uint32_t raw;
-    } spec_ctrl;
-
-    /*
-     * 0x00000140 - MSR_INTEL_MISC_FEATURES_ENABLES
-     *
-     * This MSR is non-architectural, but for simplicy we allow it to be read
-     * unconditionally.  The CPUID Faulting bit is the only writeable bit, and
-     * only if enumerated by MSR_PLATFORM_INFO.
-     */
-    union {
-        uint32_t raw;
-        struct {
-            bool cpuid_faulting:1;
-        };
-    } misc_features_enables;
-};
-
 void init_guest_msr_policy(void);
 int init_domain_msr_policy(struct domain *d);
 int init_vcpu_msr_policy(struct vcpu *v);
diff --git a/xen/include/xen/libx86/msr.h b/xen/include/xen/libx86/msr.h
new file mode 100644
index 0000000..6b8b10b
--- /dev/null
+++ b/xen/include/xen/libx86/msr.h
@@ -0,0 +1,58 @@
+/* Common data structures and functions consumed by hypervisor and toolstack */
+#ifndef XEN_LIBX86_MSR_H
+#define XEN_LIBX86_MSR_H
+
+/* MSR policy object for shared per-domain MSRs */
+struct msr_domain_policy
+{
+    /*
+     * 0x000000ce - MSR_INTEL_PLATFORM_INFO
+     *
+     * This MSR is non-architectural, but for simplicy we allow it to be read
+     * unconditionally.  CPUID Faulting support can be fully emulated for HVM
+     * guests so can be offered unconditionally, while support for PV guests
+     * is dependent on real hardware support.
+     */
+    union {
+        uint32_t raw;
+        struct {
+            uint32_t :31;
+            bool cpuid_faulting:1;
+        };
+    } plaform_info;
+};
+
+/* MSR policy object for per-vCPU MSRs */
+struct msr_vcpu_policy
+{
+    /* 0x00000048 - MSR_SPEC_CTRL */
+    struct {
+        uint32_t raw;
+    } spec_ctrl;
+
+    /*
+     * 0x00000140 - MSR_INTEL_MISC_FEATURES_ENABLES
+     *
+     * This MSR is non-architectural, but for simplicy we allow it to be read
+     * unconditionally.  The CPUID Faulting bit is the only writeable bit, and
+     * only if enumerated by MSR_PLATFORM_INFO.
+     */
+    union {
+        uint32_t raw;
+        struct {
+            bool cpuid_faulting:1;
+        };
+    } misc_features_enables;
+};
+
+#endif /* !XEN_LIBX86_MSR_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
  2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
                   ` (4 preceding siblings ...)
  2018-07-03 20:55 ` [PATCH 05/13] libx86: Introduce libx86/msr.h and share msr_{domain, vcpu}_policy with userspace Andrew Cooper
@ 2018-07-03 20:55 ` Andrew Cooper
  2018-07-04  8:42   ` Wei Liu
  2018-07-04  9:01   ` Jan Beulich
  2018-07-03 20:55 ` [PATCH 07/13] libx86: Introduce a helper to serialise msr_{domain, vcpu}_policy objects Andrew Cooper
                   ` (7 subsequent siblings)
  13 siblings, 2 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-03 20:55 UTC (permalink / raw)
  To: Xen-devel
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Jan Beulich,
	Roger Pau Monné

The serialised form is made up of the leaf, subleaf and data tuple.  As this
is the architectural form, it is expected not to change going forwards.

x86_cpuid_copy_to_buffer() is implemented using Xen's regular copy_to_guest
primitives, with an API-compatible memcpy() is used for the libxc half of the
build.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Sergey Dyasli <sergey.dyasli@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
---
 xen/common/libx86/cpuid.c          | 94 ++++++++++++++++++++++++++++++++++++++
 xen/common/libx86/libx86-private.h | 17 +++++++
 xen/include/public/arch-x86/xen.h  | 11 +++++
 xen/include/xen/libx86/cpuid.h     | 25 ++++++++++
 4 files changed, 147 insertions(+)

diff --git a/xen/common/libx86/cpuid.c b/xen/common/libx86/cpuid.c
index 9fa7d95..d38c505 100644
--- a/xen/common/libx86/cpuid.c
+++ b/xen/common/libx86/cpuid.c
@@ -34,6 +34,100 @@ const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature)
 }
 
 /*
+ * Copy a single cpuid_leaf into a provided xen_cpuid_leaf_t buffer,
+ * performing boundary checking against the buffer size.
+ */
+static int copy_leaf_to_buffer(uint32_t leaf, uint32_t subleaf,
+                               const struct cpuid_leaf *data,
+                               cpuid_leaf_buffer_t leaves,
+                               uint32_t *curr_entry, const uint32_t nr_entries)
+{
+    const xen_cpuid_leaf_t val = {
+        leaf, subleaf, data->a, data->b, data->c, data->d,
+    };
+
+    if ( *curr_entry == nr_entries )
+        return -ENOBUFS;
+
+    if ( copy_to_buffer_offset(leaves, *curr_entry, &val, 1) )
+        return -EFAULT;
+
+    ++*curr_entry;
+
+    return 0;
+}
+
+/*
+ * Serialise a cpuid_policy object into an array.  Writes at most
+ * CPUID_MAX_SERIALISED_LEAVES.  On success, nr_entries_p is updated with the
+ * actual number of leaves written.
+ */
+int x86_cpuid_copy_to_buffer(const struct cpuid_policy *p,
+                             cpuid_leaf_buffer_t leaves,
+                             uint32_t *nr_entries_p)
+{
+    const uint32_t nr_entries = *nr_entries_p;
+    uint32_t curr_entry = 0, leaf, subleaf;
+
+#define COPY_LEAF(l, s, data)                                       \
+    ({  int ret;                                                    \
+        if ( (ret = copy_leaf_to_buffer(                            \
+                  l, s, data, leaves, &curr_entry, nr_entries)) )   \
+            return ret;                                             \
+    })
+
+    /* Basic leaves. */
+    for ( leaf = 0; leaf <= MIN(p->basic.max_leaf,
+                                ARRAY_SIZE(p->basic.raw) - 1); ++leaf )
+    {
+        switch ( leaf )
+        {
+        case 0x4:
+            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->cache.raw); ++subleaf )
+                COPY_LEAF(leaf, subleaf, &p->cache.raw[subleaf]);
+            break;
+
+        case 0x7:
+            for ( subleaf = 0;
+                  subleaf <= MIN(p->feat.max_subleaf,
+                                 ARRAY_SIZE(p->feat.raw) - 1); ++subleaf )
+                COPY_LEAF(leaf, subleaf, &p->feat.raw[subleaf]);
+            break;
+
+        case 0xb:
+            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->topo.raw); ++subleaf )
+                COPY_LEAF(leaf, subleaf, &p->topo.raw[subleaf]);
+            break;
+
+        case 0xd:
+            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->xstate.raw); ++subleaf )
+                COPY_LEAF(leaf, subleaf, &p->xstate.raw[subleaf]);
+            break;
+
+        default:
+            COPY_LEAF(leaf, XEN_CPUID_NO_SUBLEAF, &p->basic.raw[leaf]);
+            break;
+        }
+    }
+
+    COPY_LEAF(0x40000000, XEN_CPUID_NO_SUBLEAF,
+              &(struct cpuid_leaf){ p->hv_limit });
+    COPY_LEAF(0x40000100, XEN_CPUID_NO_SUBLEAF,
+              &(struct cpuid_leaf){ p->hv2_limit });
+
+    /* Extended leaves. */
+    for ( leaf = 0; leaf <= MIN(p->extd.max_leaf & 0xfffful,
+                                ARRAY_SIZE(p->extd.raw) - 1); ++leaf )
+        COPY_LEAF(0x80000000 | leaf, XEN_CPUID_NO_SUBLEAF, &p->extd.raw[leaf]);
+
+#undef COPY_LEAF
+
+    *nr_entries_p = curr_entry;
+
+    return 0;
+}
+
+/*
  * Local variables:
  * mode: C
  * c-file-style: "BSD"
diff --git a/xen/common/libx86/libx86-private.h b/xen/common/libx86/libx86-private.h
index b9f42f7..a209850 100644
--- a/xen/common/libx86/libx86-private.h
+++ b/xen/common/libx86/libx86-private.h
@@ -8,8 +8,13 @@
 #include <xen/lib.h>
 #include <xen/types.h>
 
+#include <asm/guest_access.h>
+
+#define copy_to_buffer_offset copy_to_guest_offset
+
 #else
 
+#include <errno.h>
 #include <inttypes.h>
 #include <stdbool.h>
 #include <stddef.h>
@@ -17,6 +22,7 @@
 #include <xen-tools/libs.h>
 
 #define MAX(x, y) ((x) > (y) ? (x) : (y))
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
 
 #define ARRAY_SIZE(x) (sizeof x / sizeof *x)
 
@@ -27,6 +33,17 @@ static inline bool test_bit(unsigned int bit, const void *vaddr)
     return addr[bit / 8] & (1u << (bit % 8));
 }
 
+/* memcpy(), but with copy_to_guest_offset()'s API */
+#define copy_to_buffer_offset(dst, index, src, nr) ({   \
+    const typeof(*(dst)) *s = (src);                    \
+    unsigned int i;                                     \
+                                                        \
+    for ( i = 0; i < (nr); i++ )                        \
+        (dst)[(index) + i] = s[i];                      \
+                                                        \
+    0;                                                  \
+})
+
 #endif /* __XEN__ */
 
 #endif /* XEN_LIBX86_PRIVATE_H */
diff --git a/xen/include/public/arch-x86/xen.h b/xen/include/public/arch-x86/xen.h
index 69ee4bc..f3bdd83 100644
--- a/xen/include/public/arch-x86/xen.h
+++ b/xen/include/public/arch-x86/xen.h
@@ -314,6 +314,17 @@ struct xen_arch_domainconfig {
 #define XEN_ACPI_GPE0_CPUHP_BIT      2
 #endif
 
+/*
+ * Representations of architectural CPUID information.  Used as the
+ * serialised version of Xen's internal representation.
+ */
+typedef struct xen_cpuid_leaf {
+#define XEN_CPUID_NO_SUBLEAF 0xffffffffu
+    uint32_t leaf, subleaf;
+    uint32_t a, b, c, d;
+} xen_cpuid_leaf_t;
+DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t);
+
 #endif /* !__ASSEMBLY__ */
 
 /*
diff --git a/xen/include/xen/libx86/cpuid.h b/xen/include/xen/libx86/cpuid.h
index 233fa13..48ce48d 100644
--- a/xen/include/xen/libx86/cpuid.h
+++ b/xen/include/xen/libx86/cpuid.h
@@ -30,6 +30,19 @@ struct cpuid_leaf
 #define CPUID_GUEST_NR_EXTD       MAX(CPUID_GUEST_NR_EXTD_INTEL, \
                                       CPUID_GUEST_NR_EXTD_AMD)
 
+/*
+ * Maximum number of leaves a struct cpuid_policy turns into when serialised
+ * for interaction with the toolstack.  (Sum of all leaves in each union, less
+ * the entries in basic which sub-unions hang off of.)
+ */
+#define CPUID_MAX_SERIALISED_LEAVES                     \
+    (CPUID_GUEST_NR_BASIC +                             \
+     CPUID_GUEST_NR_FEAT   - !!CPUID_GUEST_NR_FEAT +    \
+     CPUID_GUEST_NR_CACHE  - !!CPUID_GUEST_NR_CACHE +   \
+     CPUID_GUEST_NR_TOPO   - !!CPUID_GUEST_NR_TOPO +    \
+     CPUID_GUEST_NR_XSTATE - !!CPUID_GUEST_NR_XSTATE +  \
+     CPUID_GUEST_NR_EXTD + 2 /* hv_limit and hv2_limit */ )
+
 struct cpuid_policy
 {
 #define DECL_BITFIELD(word) _DECL_BITFIELD(FEATURESET_ ## word)
@@ -230,6 +243,18 @@ static inline void cpuid_featureset_to_policy(
 
 const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature);
 
+#ifdef __XEN__
+#include <public/arch-x86/xen.h>
+typedef XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_leaf_buffer_t;
+#else
+#include <xen/arch-x86/xen.h>
+typedef xen_cpuid_leaf_t *cpuid_leaf_buffer_t;
+#endif
+
+int x86_cpuid_copy_to_buffer(const struct cpuid_policy *p,
+                             cpuid_leaf_buffer_t leaves,
+                             uint32_t *nr_entries_p);
+
 #endif /* !XEN_LIBX86_CPUID_H */
 
 /*
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH 07/13] libx86: Introduce a helper to serialise msr_{domain, vcpu}_policy objects
  2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
                   ` (5 preceding siblings ...)
  2018-07-03 20:55 ` [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object Andrew Cooper
@ 2018-07-03 20:55 ` Andrew Cooper
  2018-07-04  9:16   ` Jan Beulich
  2018-07-03 20:55 ` [PATCH 08/13] x86: Collect policies together into groups Andrew Cooper
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 67+ messages in thread
From: Andrew Cooper @ 2018-07-03 20:55 UTC (permalink / raw)
  To: Xen-devel
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Jan Beulich,
	Roger Pau Monné

From: Roger Pau Monné <roger.pau@citrix.com>

As with CPUID, the an architectural form is used for representing the MSR
data.  It is expected not to change moving forwards, but does have a 32 bit
field (currently reserved) which can be used compatibly if needs be.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Sergey Dyasli <sergey.dyasli@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
---
 tools/include/Makefile             |  1 +
 tools/libxc/Makefile               |  2 +-
 xen/common/libx86/Makefile         |  1 +
 xen/common/libx86/libx86-private.h |  3 ++
 xen/common/libx86/msr.c            | 71 ++++++++++++++++++++++++++++++++++++++
 xen/include/public/arch-x86/xen.h  |  9 ++++-
 xen/include/xen/libx86/msr.h       | 16 +++++++++
 7 files changed, 101 insertions(+), 2 deletions(-)
 create mode 100644 xen/common/libx86/msr.c

diff --git a/tools/include/Makefile b/tools/include/Makefile
index fc99da9..1a0eae7 100644
--- a/tools/include/Makefile
+++ b/tools/include/Makefile
@@ -22,6 +22,7 @@ xen/.dir:
 	ln -s ../xen-foreign xen/foreign
 	ln -sf $(XEN_ROOT)/xen/include/acpi acpi
 ifeq ($(CONFIG_X86),y)
+	ln -sf $(XEN_ROOT)/xen/include/asm-x86 xen/asm
 	ln -sf $(XEN_ROOT)/xen/include/xen/libx86 xen/libx86
 endif
 	touch $@
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index f534d90..407a9d1 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -83,7 +83,7 @@ $(patsubst %.c,%.opic,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
 # Add libx86 to the build
 vpath %.c ../../xen/common/libx86
 
-GUEST_SRCS-$(CONFIG_X86)     += cpuid.c
+GUEST_SRCS-$(CONFIG_X86)     += cpuid.c msr.c
 
 # new domain builder
 GUEST_SRCS-y                 += xc_dom_core.c xc_dom_boot.c
diff --git a/xen/common/libx86/Makefile b/xen/common/libx86/Makefile
index 3fb2e0b..2f9691e 100644
--- a/xen/common/libx86/Makefile
+++ b/xen/common/libx86/Makefile
@@ -1 +1,2 @@
 obj-y += cpuid.o
+obj-y += msr.o
diff --git a/xen/common/libx86/libx86-private.h b/xen/common/libx86/libx86-private.h
index a209850..e4ead1a 100644
--- a/xen/common/libx86/libx86-private.h
+++ b/xen/common/libx86/libx86-private.h
@@ -9,6 +9,7 @@
 #include <xen/types.h>
 
 #include <asm/guest_access.h>
+#include <asm/msr-index.h>
 
 #define copy_to_buffer_offset copy_to_guest_offset
 
@@ -19,6 +20,8 @@
 #include <stdbool.h>
 #include <stddef.h>
 
+#include <xen/asm/msr-index.h>
+
 #include <xen-tools/libs.h>
 
 #define MAX(x, y) ((x) > (y) ? (x) : (y))
diff --git a/xen/common/libx86/msr.c b/xen/common/libx86/msr.c
new file mode 100644
index 0000000..46a3458
--- /dev/null
+++ b/xen/common/libx86/msr.c
@@ -0,0 +1,71 @@
+#include "libx86-private.h"
+
+#include <xen/libx86/msr.h>
+
+/*
+ * Copy a single MSR into the provided msr_entry_buffer_t buffer, performing a
+ * boundary check against the buffer size.
+ */
+static int copy_msr_to_buffer(uint32_t idx, uint64_t val,
+                              msr_entry_buffer_t msrs,
+                              uint32_t *curr_entry, const uint32_t nr_entries)
+{
+    const xen_msr_entry_t ent = { .idx = idx, .val = val };
+
+    if ( *curr_entry == nr_entries )
+        return -ENOBUFS;
+
+    if ( copy_to_buffer_offset(msrs, *curr_entry, &ent, 1) )
+        return -EFAULT;
+
+    ++*curr_entry;
+
+    return 0;
+}
+
+/*
+ * Serialise msr_{domain,vcpu}_policy object into an array.  Writes at most
+ * MSR_MAX_SERIALISED_ENTRIES.  Returns -ENOBUFS if the buffer array is too
+ * short.  On success, nr_entries_p is updated with the actual number of
+ * leaves written.
+ */
+int x86_msr_copy_to_buffer(const struct msr_domain_policy *dp,
+                           const struct msr_vcpu_policy *vp,
+                           msr_entry_buffer_t msrs, uint32_t *nr_entries_p)
+{
+    const uint32_t nr_entries = *nr_entries_p;
+    uint32_t curr_entry = 0;
+
+#define COPY_MSR(idx, val)                                      \
+    ({  int ret;                                                \
+        if ( (ret = copy_msr_to_buffer(                         \
+                  idx, val, msrs, &curr_entry, nr_entries)) )   \
+            return ret;                                         \
+    })
+
+    if ( dp )
+        COPY_MSR(MSR_INTEL_PLATFORM_INFO, dp->plaform_info.raw);
+
+    if ( vp )
+    {
+        COPY_MSR(MSR_SPEC_CTRL, vp->spec_ctrl.raw);
+        COPY_MSR(MSR_INTEL_MISC_FEATURES_ENABLES,
+                 vp->misc_features_enables.raw);
+    }
+
+#undef COPY_MSR
+
+    *nr_entries_p = curr_entry;
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/public/arch-x86/xen.h b/xen/include/public/arch-x86/xen.h
index f3bdd83..55a149f 100644
--- a/xen/include/public/arch-x86/xen.h
+++ b/xen/include/public/arch-x86/xen.h
@@ -315,7 +315,7 @@ struct xen_arch_domainconfig {
 #endif
 
 /*
- * Representations of architectural CPUID information.  Used as the
+ * Representations of architectural CPUID and MSR information.  Used as the
  * serialised version of Xen's internal representation.
  */
 typedef struct xen_cpuid_leaf {
@@ -325,6 +325,13 @@ typedef struct xen_cpuid_leaf {
 } xen_cpuid_leaf_t;
 DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t);
 
+typedef struct xen_msr_entry {
+    uint32_t idx;
+    uint32_t flags; /* Reserved MBZ. */
+    uint64_t val;
+} xen_msr_entry_t;
+DEFINE_XEN_GUEST_HANDLE(xen_msr_entry_t);
+
 #endif /* !__ASSEMBLY__ */
 
 /*
diff --git a/xen/include/xen/libx86/msr.h b/xen/include/xen/libx86/msr.h
index 6b8b10b..8776378 100644
--- a/xen/include/xen/libx86/msr.h
+++ b/xen/include/xen/libx86/msr.h
@@ -2,6 +2,10 @@
 #ifndef XEN_LIBX86_MSR_H
 #define XEN_LIBX86_MSR_H
 
+#define MSR_MAX_SERIALISED_ENTRIES              \
+    (1 + /* msr_domain_policy */                \
+     2   /* msr_vcpu_policy*/ )
+
 /* MSR policy object for shared per-domain MSRs */
 struct msr_domain_policy
 {
@@ -45,6 +49,18 @@ struct msr_vcpu_policy
     } misc_features_enables;
 };
 
+#ifdef __XEN__
+#include <public/arch-x86/xen.h>
+typedef XEN_GUEST_HANDLE_64(xen_msr_entry_t) msr_entry_buffer_t;
+#else
+#include <xen/arch-x86/xen.h>
+typedef xen_msr_entry_t *msr_entry_buffer_t;
+#endif
+
+int x86_msr_copy_to_buffer(const struct msr_domain_policy *dp,
+                           const struct msr_vcpu_policy *vp,
+                           msr_entry_buffer_t msrs, uint32_t *nr_entries_p);
+
 #endif /* !XEN_LIBX86_MSR_H */
 
 /*
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH 08/13] x86: Collect policies together into groups
  2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
                   ` (6 preceding siblings ...)
  2018-07-03 20:55 ` [PATCH 07/13] libx86: Introduce a helper to serialise msr_{domain, vcpu}_policy objects Andrew Cooper
@ 2018-07-03 20:55 ` Andrew Cooper
  2018-07-04  9:22   ` Jan Beulich
  2018-07-03 20:55 ` [PATCH 09/13] x86/sysctl: Implement XEN_SYSCTL_get_cpumsr_policy Andrew Cooper
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 67+ messages in thread
From: Andrew Cooper @ 2018-07-03 20:55 UTC (permalink / raw)
  To: Xen-devel
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Jan Beulich,
	Roger Pau Monné

This is mainly prep work for the following patch, but this specific
abstraction is also specifically useful for the future auditing logic.

Not all of msr_vcpu_policy will be interesting from a domain building
perspective, but some soon-to-appear fields will be (SGX Launch Hash
specifically).  The exact split of MSRs between domain and vcpu policies is
internal to Xen and liable to change moving forwards, so treat the two
structures consistently from the start to avoid problems in the future.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Sergey Dyasli <sergey.dyasli@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
---
 xen/arch/x86/msr.c                |  4 +++-
 xen/arch/x86/sysctl.c             | 23 +++++++++++++++++++++++
 xen/include/asm-x86/cpuid.h       |  3 +++
 xen/include/asm-x86/msr.h         | 16 +++++++++-------
 xen/include/xen/libx86/policies.h | 25 +++++++++++++++++++++++++
 5 files changed, 63 insertions(+), 8 deletions(-)
 create mode 100644 xen/include/xen/libx86/policies.h

diff --git a/xen/arch/x86/msr.c b/xen/arch/x86/msr.c
index d035c67..233eeaf 100644
--- a/xen/arch/x86/msr.c
+++ b/xen/arch/x86/msr.c
@@ -31,7 +31,9 @@ struct msr_domain_policy __read_mostly     raw_msr_domain_policy,
                          __read_mostly hvm_max_msr_domain_policy,
                          __read_mostly  pv_max_msr_domain_policy;
 
-struct msr_vcpu_policy __read_mostly hvm_max_msr_vcpu_policy,
+struct msr_vcpu_policy __read_mostly     raw_msr_vcpu_policy,
+                       __read_mostly    host_msr_vcpu_policy,
+                       __read_mostly hvm_max_msr_vcpu_policy,
                        __read_mostly  pv_max_msr_vcpu_policy;
 
 static void __init calculate_raw_policy(void)
diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c
index 4d372db..c5c00d0 100644
--- a/xen/arch/x86/sysctl.c
+++ b/xen/arch/x86/sysctl.c
@@ -31,6 +31,29 @@
 #include <asm/psr.h>
 #include <asm/cpuid.h>
 
+const struct policy_group system_policies[] = {
+    {
+        &raw_cpuid_policy,
+        &raw_msr_domain_policy,
+        &raw_msr_vcpu_policy,
+    },
+    {
+        &host_cpuid_policy,
+        &host_msr_domain_policy,
+        &host_msr_vcpu_policy,
+    },
+    {
+        &pv_max_cpuid_policy,
+        &pv_max_msr_domain_policy,
+        &pv_max_msr_vcpu_policy,
+    },
+    {
+        &hvm_max_cpuid_policy,
+        &hvm_max_msr_domain_policy,
+        &hvm_max_msr_vcpu_policy,
+    },
+};
+
 struct l3_cache_info {
     int ret;
     unsigned long size;
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index ea79445..5454e44 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -9,6 +9,7 @@
 #include <xen/kernel.h>
 
 #include <xen/libx86/cpuid.h>
+#include <xen/libx86/policies.h>
 
 #include <public/sysctl.h>
 
@@ -50,6 +51,8 @@ extern struct cpuidmasks cpuidmask_defaults;
 extern struct cpuid_policy raw_cpuid_policy, host_cpuid_policy,
     pv_max_cpuid_policy, hvm_max_cpuid_policy;
 
+extern const struct policy_group system_policies[];
+
 /* Check that all previously present features are still available. */
 bool recheck_cpu_features(unsigned int cpu);
 
diff --git a/xen/include/asm-x86/msr.h b/xen/include/asm-x86/msr.h
index d8cb638..e306f97 100644
--- a/xen/include/asm-x86/msr.h
+++ b/xen/include/asm-x86/msr.h
@@ -260,13 +260,15 @@ static inline void wrmsr_tsc_aux(uint32_t val)
     }
 }
 
-/* RAW msr domain policy: contains the actual values from H/W MSRs */
-extern struct msr_domain_policy raw_msr_domain_policy;
-/*
- * HOST msr domain policy: features that Xen actually decided to use,
- * a subset of RAW policy.
- */
-extern struct msr_domain_policy host_msr_domain_policy;
+extern struct msr_domain_policy __read_mostly     raw_msr_domain_policy,
+                                __read_mostly    host_msr_domain_policy,
+                                __read_mostly hvm_max_msr_domain_policy,
+                                __read_mostly  pv_max_msr_domain_policy;
+
+extern struct msr_vcpu_policy __read_mostly     raw_msr_vcpu_policy,
+                              __read_mostly    host_msr_vcpu_policy,
+                              __read_mostly hvm_max_msr_vcpu_policy,
+                              __read_mostly  pv_max_msr_vcpu_policy;
 
 void init_guest_msr_policy(void);
 int init_domain_msr_policy(struct domain *d);
diff --git a/xen/include/xen/libx86/policies.h b/xen/include/xen/libx86/policies.h
new file mode 100644
index 0000000..d6fa1bc
--- /dev/null
+++ b/xen/include/xen/libx86/policies.h
@@ -0,0 +1,25 @@
+/* Common data structures and functions consumed by hypervisor and toolstack */
+#ifndef XEN_LIBX86_POLICIES_H
+#define XEN_LIBX86_POLICIES_H
+
+#include <xen/libx86/cpuid.h>
+#include <xen/libx86/msr.h>
+
+struct policy_group
+{
+    struct cpuid_policy *cp;
+    struct msr_domain_policy *dp;
+    struct msr_vcpu_policy *vp;
+};
+
+#endif /* !XEN_LIBX86_POLICIES_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH 09/13] x86/sysctl: Implement XEN_SYSCTL_get_cpumsr_policy
  2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
                   ` (7 preceding siblings ...)
  2018-07-03 20:55 ` [PATCH 08/13] x86: Collect policies together into groups Andrew Cooper
@ 2018-07-03 20:55 ` Andrew Cooper
  2018-07-04  9:43   ` Jan Beulich
  2018-07-03 20:55 ` [PATCH 10/13] x86/domctl: Implement XEN_DOMCTL_get_cpumsr_policy Andrew Cooper
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 67+ messages in thread
From: Andrew Cooper @ 2018-07-03 20:55 UTC (permalink / raw)
  To: Xen-devel
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Jan Beulich,
	Daniel De Graaf, Roger Pau Monné

From: Sergey Dyasli <sergey.dyasli@citrix.com>

Provide a SYSCTL for the toolstack to obtain complete system CPUID and MSR
policy information.  The split of default vs max policies is introduced into
the API, including a description of the intended behaviour.  For now, max is
the default, but this is intended to change moving forwards.

For the XSM side of things, this subop is closely related to
{phys,cputopo,numa}info, so shares the physinfo access vector.

Extend the xen-cpuid utility to be able to dump the system policies.  An
example output is:

    Xen reports there are maximum 113 leaves and 3 MSRs
    Raw policy: 93 leaves, 3 MSRs
     CPUID:
      leaf     subleaf  -> eax      ebx      ecx      edx
      00000000:ffffffff -> 0000000d:756e6547:6c65746e:49656e69
      00000001:ffffffff -> 000306c3:00100800:7ffafbff:bfebfbff
      00000002:ffffffff -> 76036301:00f0b5ff:00000000:00c10000
      00000004:00000000 -> 1c004121:01c0003f:0000003f:00000000
      00000004:00000001 -> 1c004122:01c0003f:0000003f:00000000
      00000004:00000002 -> 1c004143:01c0003f:000001ff:00000000
      00000004:00000003 -> 1c03c163:03c0003f:00001fff:00000006
      00000005:ffffffff -> 00000040:00000040:00000003:00042120
      00000006:ffffffff -> 00000077:00000002:00000009:00000000
      00000007:00000000 -> 00000000:000027ab:00000000:9c000000
      0000000a:ffffffff -> 07300403:00000000:00000000:00000603
      0000000b:00000000 -> 00000001:00000002:00000100:00000000
      0000000b:00000001 -> 00000004:00000008:00000201:00000000
      0000000d:00000000 -> 00000007:00000340:00000340:00000000
      0000000d:00000001 -> 00000001:00000000:00000000:00000000
      0000000d:00000002 -> 00000100:00000240:00000000:00000000
      80000000:ffffffff -> 80000008:00000000:00000000:00000000
      80000001:ffffffff -> 00000000:00000000:00000021:2c100800
      80000002:ffffffff -> 65746e49:2952286c:6f655820:2952286e
      80000003:ffffffff -> 55504320:2d334520:30343231:20337620
      80000004:ffffffff -> 2e332040:48473034:0000007a:00000000
      80000006:ffffffff -> 00000000:00000000:01006040:00000000
      80000007:ffffffff -> 00000000:00000000:00000000:00000100
      80000008:ffffffff -> 00003027:00000000:00000000:00000000
     MSRs:
      index    -> value
      000000ce -> 0000000080000000
      00000048 -> 0000000000000000
      00000140 -> 0000000000000000

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Sergey Dyasli <sergey.dyasli@citrix.com>
CC: Daniel De Graaf <dgdegra@tycho.nsa.gov>
---
 tools/libxc/include/xenctrl.h       |  6 +++
 tools/libxc/xc_cpuid_x86.c          | 59 ++++++++++++++++++++++++
 tools/misc/xen-cpuid.c              | 89 +++++++++++++++++++++++++++++++++++--
 xen/arch/x86/sysctl.c               | 86 +++++++++++++++++++++++++++++++++--
 xen/include/public/sysctl.h         | 41 +++++++++++++++++
 xen/xsm/flask/hooks.c               |  1 +
 xen/xsm/flask/policy/access_vectors |  2 +-
 7 files changed, 275 insertions(+), 9 deletions(-)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 70f54e6..d1f0925c 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2536,6 +2536,12 @@ int xc_get_cpu_levelling_caps(xc_interface *xch, uint32_t *caps);
 int xc_get_cpu_featureset(xc_interface *xch, uint32_t index,
                           uint32_t *nr_features, uint32_t *featureset);
 
+int xc_get_cpumsr_policy_size(xc_interface *xch, uint32_t *nr_leaves,
+                              uint32_t *nr_msrs);
+int xc_get_system_cpumsr_policy(xc_interface *xch, uint32_t index,
+                                uint32_t *nr_leaves, xen_cpuid_leaf_t *leaves,
+                                uint32_t *nr_msrs, xen_msr_entry_t *msrs);
+
 uint32_t xc_get_cpu_featureset_size(void);
 
 enum xc_static_cpu_featuremask {
diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index 900c639..ce2a584 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -134,6 +134,65 @@ const uint32_t *xc_get_static_cpu_featuremask(
     }
 }
 
+int xc_get_cpumsr_policy_size(xc_interface *xch, uint32_t *nr_leaves,
+                              uint32_t *nr_msrs)
+{
+    struct xen_sysctl sysctl = {};
+    int ret;
+
+    sysctl.cmd = XEN_SYSCTL_get_cpumsr_policy;
+
+    ret = do_sysctl(xch, &sysctl);
+
+    if ( !ret )
+    {
+        *nr_leaves = sysctl.u.cpumsr_policy.nr_leaves;
+        *nr_msrs = sysctl.u.cpumsr_policy.nr_msrs;
+    }
+
+    return ret;
+}
+
+int xc_get_system_cpumsr_policy(xc_interface *xch, uint32_t index,
+                               uint32_t *nr_leaves, xen_cpuid_leaf_t *leaves,
+                               uint32_t *nr_msrs, xen_msr_entry_t *msrs)
+{
+    struct xen_sysctl sysctl = {};
+    DECLARE_HYPERCALL_BOUNCE(leaves,
+                             *nr_leaves * sizeof(*leaves),
+                             XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+    DECLARE_HYPERCALL_BOUNCE(msrs,
+                             *nr_msrs * sizeof(*msrs),
+                             XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+    int ret;
+
+    if ( xc_hypercall_bounce_pre(xch, leaves) )
+        return -1;
+
+    if ( xc_hypercall_bounce_pre(xch, msrs) )
+        return -1;
+
+    sysctl.cmd = XEN_SYSCTL_get_cpumsr_policy;
+    sysctl.u.cpumsr_policy.index = index;
+    sysctl.u.cpumsr_policy.nr_leaves = *nr_leaves;
+    set_xen_guest_handle(sysctl.u.cpumsr_policy.cpuid_policy, leaves);
+    sysctl.u.cpumsr_policy.nr_msrs = *nr_msrs;
+    set_xen_guest_handle(sysctl.u.cpumsr_policy.msr_policy, msrs);
+
+    ret = do_sysctl(xch, &sysctl);
+
+    xc_hypercall_bounce_post(xch, leaves);
+    xc_hypercall_bounce_post(xch, msrs);
+
+    if ( !ret )
+    {
+        *nr_leaves = sysctl.u.cpumsr_policy.nr_leaves;
+        *nr_msrs = sysctl.u.cpumsr_policy.nr_msrs;
+    }
+
+    return ret;
+}
+
 struct cpuid_domain_info
 {
     enum
diff --git a/tools/misc/xen-cpuid.c b/tools/misc/xen-cpuid.c
index e116339..a5b3004 100644
--- a/tools/misc/xen-cpuid.c
+++ b/tools/misc/xen-cpuid.c
@@ -276,9 +276,37 @@ static void dump_info(xc_interface *xch, bool detail)
         free(featuresets[i].fs);
 }
 
+static void print_policy(const char *name,
+                         xen_cpuid_leaf_t *leaves, uint32_t nr_leaves,
+                         xen_msr_entry_t *msrs, uint32_t nr_msrs)
+{
+    unsigned int l;
+
+    printf("%s policy: %u leaves, %u MSRs\n", name, nr_leaves, nr_msrs);
+    printf(" CPUID:\n");
+    printf("  %-8s %-8s -> %-8s %-8s %-8s %-8s\n",
+           "leaf", "subleaf", "eax", "ebx", "ecx", "edx");
+    for ( l = 0; l < nr_leaves; ++l )
+    {
+        /* Skip empty leaves. */
+        if ( !leaves[l].a && !leaves[l].b && !leaves[l].c && !leaves[l].d )
+            continue;
+
+        printf("  %08x:%08x -> %08x:%08x:%08x:%08x\n",
+               leaves[l].leaf, leaves[l].subleaf,
+               leaves[l].a, leaves[l].b, leaves[l].c, leaves[l].d);
+    }
+
+    printf(" MSRs:\n");
+    printf("  %-8s -> %-16s\n", "index", "value");
+    for ( l = 0; l < nr_msrs; ++l )
+        printf("  %08x -> %016lx\n",
+               msrs[l].idx, msrs[l].val);
+}
+
 int main(int argc, char **argv)
 {
-    enum { MODE_UNKNOWN, MODE_INFO, MODE_DETAIL, MODE_INTERPRET }
+    enum { MODE_UNKNOWN, MODE_INFO, MODE_DETAIL, MODE_INTERPRET, MODE_POLICY }
     mode = MODE_UNKNOWN;
 
     nr_features = xc_get_cpu_featureset_size();
@@ -292,10 +320,11 @@ int main(int argc, char **argv)
             { "info", no_argument, NULL, 'i' },
             { "detail", no_argument, NULL, 'd' },
             { "verbose", no_argument, NULL, 'v' },
+            { "policy", no_argument, NULL, 'p' },
             { NULL, 0, NULL, 0 },
         };
 
-        c = getopt_long(argc, argv, "hidv", long_options, &option_index);
+        c = getopt_long(argc, argv, "hidvp", long_options, &option_index);
 
         if ( c == -1 )
             break;
@@ -313,6 +342,10 @@ int main(int argc, char **argv)
             mode = MODE_INFO;
             break;
 
+        case 'p':
+            mode = MODE_POLICY;
+            break;
+
         case 'd':
         case 'v':
             mode = MODE_DETAIL;
@@ -343,7 +376,55 @@ int main(int argc, char **argv)
             mode = MODE_INTERPRET;
     }
 
-    if ( mode == MODE_INFO || mode == MODE_DETAIL )
+    if ( mode == MODE_POLICY )
+    {
+        static const char *const sys_policies[] = {
+            [ XEN_SYSCTL_cpumsr_policy_raw ]          = "Raw",
+            [ XEN_SYSCTL_cpumsr_policy_host ]         = "Host",
+            [ XEN_SYSCTL_cpumsr_policy_pv_max ]       = "PV Max",
+            [ XEN_SYSCTL_cpumsr_policy_hvm_max ]      = "HVM Max",
+            [ XEN_SYSCTL_cpumsr_policy_pv_default ]   = "PV Default",
+            [ XEN_SYSCTL_cpumsr_policy_hvm_default ]  = "HVM Default",
+        };
+        xen_cpuid_leaf_t *leaves;
+        xen_msr_entry_t *msrs;
+        uint32_t pol, max_leaves, max_msrs;
+
+        xc_interface *xch = xc_interface_open(0, 0, 0);
+
+        if ( !xch )
+            err(1, "xc_interface_open");
+
+        if ( xc_get_cpumsr_policy_size(xch, &max_leaves, &max_msrs) )
+            err(1, "xc_get_cpumsr_policy_size(...)");
+        printf("Xen reports there are maximum %u leaves and %u MSRs\n",
+                max_leaves, max_msrs);
+
+        leaves = calloc(max_leaves, sizeof(xen_cpuid_leaf_t));
+        if ( !leaves )
+            err(1, "calloc(max_leaves)");
+        msrs = calloc(max_msrs, sizeof(xen_msr_entry_t));
+        if ( !msrs )
+            err(1, "calloc(max_msrs)");
+
+        for ( pol = 0; pol < ARRAY_SIZE(sys_policies); ++pol )
+        {
+            uint32_t nr_leaves = max_leaves;
+            uint32_t nr_msrs = max_msrs;
+
+            if ( xc_get_system_cpumsr_policy(xch, pol, &nr_leaves, leaves,
+                                             &nr_msrs, msrs) )
+                err(1, "xc_get_system_cpumsr_policy(, %s,,)",
+                    sys_policies[pol]);
+
+            print_policy(sys_policies[pol], leaves, nr_leaves, msrs, nr_msrs);
+        }
+
+        free(leaves);
+        free(msrs);
+        xc_interface_close(xch);
+    }
+    else if ( mode == MODE_INFO || mode == MODE_DETAIL )
     {
         xc_interface *xch = xc_interface_open(0, 0, 0);
 
@@ -377,7 +458,7 @@ int main(int argc, char **argv)
                 if ( i == nr_features )
                     break;
 
-                if ( *ptr == ':' )
+                if ( *ptr == ':' || *ptr == '-' )
                 {
                     ptr++; continue;
                 }
diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c
index c5c00d0..067fc86 100644
--- a/xen/arch/x86/sysctl.c
+++ b/xen/arch/x86/sysctl.c
@@ -32,22 +32,32 @@
 #include <asm/cpuid.h>
 
 const struct policy_group system_policies[] = {
-    {
+    [ XEN_SYSCTL_cpumsr_policy_raw ] = {
         &raw_cpuid_policy,
         &raw_msr_domain_policy,
         &raw_msr_vcpu_policy,
     },
-    {
+    [ XEN_SYSCTL_cpumsr_policy_host ] = {
         &host_cpuid_policy,
         &host_msr_domain_policy,
         &host_msr_vcpu_policy,
     },
-    {
+    [ XEN_SYSCTL_cpumsr_policy_pv_max ] = {
         &pv_max_cpuid_policy,
         &pv_max_msr_domain_policy,
         &pv_max_msr_vcpu_policy,
     },
-    {
+    [ XEN_SYSCTL_cpumsr_policy_hvm_max ] = {
+        &hvm_max_cpuid_policy,
+        &hvm_max_msr_domain_policy,
+        &hvm_max_msr_vcpu_policy,
+    },
+    [ XEN_SYSCTL_cpumsr_policy_pv_default ] = {
+        &pv_max_cpuid_policy,
+        &pv_max_msr_domain_policy,
+        &pv_max_msr_vcpu_policy,
+    },
+    [ XEN_SYSCTL_cpumsr_policy_hvm_default ] = {
         &hvm_max_cpuid_policy,
         &hvm_max_msr_domain_policy,
         &hvm_max_msr_vcpu_policy,
@@ -318,6 +328,74 @@ long arch_do_sysctl(
         break;
     }
 
+    case XEN_SYSCTL_get_cpumsr_policy:
+    {
+        const struct policy_group *group;
+
+        /* Bad policy index? */
+        if ( sysctl->u.cpumsr_policy.index >= ARRAY_SIZE(system_policies) )
+        {
+            ret = -EINVAL;
+            break;
+        }
+        group = &system_policies[sysctl->u.cpumsr_policy.index];
+
+        /* Request for maximum number of leaves/MSRs? */
+        if ( guest_handle_is_null(sysctl->u.cpumsr_policy.cpuid_policy) )
+        {
+            sysctl->u.cpumsr_policy.nr_leaves = CPUID_MAX_SERIALISED_LEAVES;
+            if ( __copy_field_to_guest(u_sysctl, sysctl,
+                                       u.cpumsr_policy.nr_leaves) )
+            {
+                ret = -EFAULT;
+                break;
+            }
+        }
+        if ( guest_handle_is_null(sysctl->u.cpumsr_policy.msr_policy) )
+        {
+            sysctl->u.cpumsr_policy.nr_msrs = MSR_MAX_SERIALISED_ENTRIES;
+            if ( __copy_field_to_guest(u_sysctl, sysctl,
+                                       u.cpumsr_policy.nr_msrs) )
+            {
+                ret = -EFAULT;
+                break;
+            }
+        }
+
+        /* Serialise the information the caller wants. */
+        if ( !guest_handle_is_null(sysctl->u.cpumsr_policy.cpuid_policy) )
+        {
+            if ( (ret = x86_cpuid_copy_to_buffer(
+                      group->cp,
+                      sysctl->u.cpumsr_policy.cpuid_policy,
+                      &sysctl->u.cpumsr_policy.nr_leaves)) )
+                break;
+
+            if ( __copy_field_to_guest(u_sysctl, sysctl,
+                                       u.cpumsr_policy.nr_leaves)  )
+            {
+                ret = -EFAULT;
+                break;
+            }
+        }
+        if ( !guest_handle_is_null(sysctl->u.cpumsr_policy.msr_policy) )
+        {
+            if ( (ret = x86_msr_copy_to_buffer(
+                      group->dp, group->vp,
+                      sysctl->u.cpumsr_policy.msr_policy,
+                      &sysctl->u.cpumsr_policy.nr_msrs)) )
+                break;
+
+            if ( __copy_field_to_guest(u_sysctl, sysctl,
+                                       u.cpumsr_policy.nr_msrs)  )
+            {
+                ret = -EFAULT;
+                break;
+            }
+        }
+        break;
+    }
+
     default:
         ret = -ENOSYS;
         break;
diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h
index 839c1b9..f04bfa8 100644
--- a/xen/include/public/sysctl.h
+++ b/xen/include/public/sysctl.h
@@ -1063,6 +1063,43 @@ struct xen_sysctl_set_parameter {
     uint16_t pad[3];                        /* IN: MUST be zero. */
 };
 
+#if defined(__i386__) || defined(__x86_64__)
+/*
+ * XEN_SYSCTL_get_cpumsr_policy (x86 specific)
+ *
+ * Return information about CPUID and MSR policies available on this host.
+ *  -       Raw: The real H/W values.
+ *  -      Host: The values Xen is using, (after command line overrides, etc).
+ *  -     Max_*: Maximum set of features a PV or HVM guest can use.  Includes
+ *               experimental features outside of security support.
+ *  - Default_*: Default set of features a PV or HVM guest can use.  This is
+ *               the security supported set.
+ */
+struct xen_sysctl_cpumsr_policy {
+#define XEN_SYSCTL_cpumsr_policy_raw          0
+#define XEN_SYSCTL_cpumsr_policy_host         1
+#define XEN_SYSCTL_cpumsr_policy_pv_max       2
+#define XEN_SYSCTL_cpumsr_policy_hvm_max      3
+#define XEN_SYSCTL_cpumsr_policy_pv_default   4
+#define XEN_SYSCTL_cpumsr_policy_hvm_default  5
+    uint32_t index;       /* IN: Which policy to query? */
+    uint32_t nr_leaves;   /* IN/OUT: Number of leaves in/written to
+                           * 'cpuid_policy', or the maximum number of leaves if
+                           * any of the guest handles is NULL.
+                           * NB. All policies come from the same space,
+                           * so have the same maximum length. */
+    uint32_t nr_msrs;     /* IN/OUT: Number of MSRs in/written to
+                           * 'msr_domain_policy', or the maximum number of MSRs
+                           * if any of the guest handles is NULL.
+                           * NB. All policies come from the same space,
+                           * so have the same maximum length. */
+    XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_policy; /* OUT: */
+    XEN_GUEST_HANDLE_64(xen_msr_entry_t) msr_policy;    /* OUT: */
+};
+typedef struct xen_sysctl_cpumsr_policy xen_sysctl_cpumsr_policy_t;
+DEFINE_XEN_GUEST_HANDLE(xen_sysctl_cpumsr_policy_t);
+#endif
+
 struct xen_sysctl {
     uint32_t cmd;
 #define XEN_SYSCTL_readconsole                    1
@@ -1092,6 +1129,7 @@ struct xen_sysctl {
 #define XEN_SYSCTL_get_cpu_featureset            26
 #define XEN_SYSCTL_livepatch_op                  27
 #define XEN_SYSCTL_set_parameter                 28
+#define XEN_SYSCTL_get_cpumsr_policy             29
     uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
     union {
         struct xen_sysctl_readconsole       readconsole;
@@ -1121,6 +1159,9 @@ struct xen_sysctl {
         struct xen_sysctl_cpu_featureset    cpu_featureset;
         struct xen_sysctl_livepatch_op      livepatch;
         struct xen_sysctl_set_parameter     set_parameter;
+#if defined(__i386__) || defined(__x86_64__)
+        struct xen_sysctl_cpumsr_policy     cpumsr_policy;
+#endif
         uint8_t                             pad[128];
     } u;
 };
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 78bc326..1d30b0e 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -801,6 +801,7 @@ static int flask_sysctl(int cmd)
     case XEN_SYSCTL_cputopoinfo:
     case XEN_SYSCTL_numainfo:
     case XEN_SYSCTL_pcitopoinfo:
+    case XEN_SYSCTL_get_cpumsr_policy:
         return domain_has_xen(current->domain, XEN__PHYSINFO);
 
     case XEN_SYSCTL_psr_cmt_op:
diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors
index c5d8548..b5bc7a2 100644
--- a/xen/xsm/flask/policy/access_vectors
+++ b/xen/xsm/flask/policy/access_vectors
@@ -28,7 +28,7 @@ class xen
 # XENPF_microcode_update
     microcode
 # XEN_SYSCTL_physinfo, XEN_SYSCTL_cputopoinfo, XEN_SYSCTL_numainfo
-# XEN_SYSCTL_pcitopoinfo
+# XEN_SYSCTL_pcitopoinfo, XEN_SYSCTL_get_cpumsr_policy
     physinfo
 # XENPF_platform_quirk
     quirk
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH 10/13] x86/domctl: Implement XEN_DOMCTL_get_cpumsr_policy
  2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
                   ` (8 preceding siblings ...)
  2018-07-03 20:55 ` [PATCH 09/13] x86/sysctl: Implement XEN_SYSCTL_get_cpumsr_policy Andrew Cooper
@ 2018-07-03 20:55 ` Andrew Cooper
  2018-07-04  9:48   ` Jan Beulich
  2018-07-05 14:23   ` Sergey Dyasli
  2018-07-03 20:55 ` [PATCH 11/13] libx86: Introduce a helper to deserialise a cpuid_policy object Andrew Cooper
                   ` (3 subsequent siblings)
  13 siblings, 2 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-03 20:55 UTC (permalink / raw)
  To: Xen-devel
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Jan Beulich,
	Daniel De Graaf, Roger Pau Monné

From: Sergey Dyasli <sergey.dyasli@citrix.com>

This finally (after literally years of work!) marks the point where the
toolstack can ask the hypervisor for the current CPUID configuration of a
specific domain.

Also extend xen-cpuid's --policy mode to be able to take a domid and dump a
specific domains CPUID and MSR policy.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Sergey Dyasli <sergey.dyasli@citrix.com>
CC: Daniel De Graaf <dgdegra@tycho.nsa.gov>
---
 tools/libxc/include/xenctrl.h       |  3 ++
 tools/libxc/xc_cpuid_x86.c          | 40 +++++++++++++++++++++++
 tools/misc/xen-cpuid.c              | 64 +++++++++++++++++++++++++++++++------
 xen/arch/x86/domctl.c               | 46 ++++++++++++++++++++++++++
 xen/include/public/domctl.h         | 18 +++++++++++
 xen/xsm/flask/hooks.c               |  1 +
 xen/xsm/flask/policy/access_vectors |  1 +
 7 files changed, 164 insertions(+), 9 deletions(-)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index d1f0925c..15d2b92 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2541,6 +2541,9 @@ int xc_get_cpumsr_policy_size(xc_interface *xch, uint32_t *nr_leaves,
 int xc_get_system_cpumsr_policy(xc_interface *xch, uint32_t index,
                                 uint32_t *nr_leaves, xen_cpuid_leaf_t *leaves,
                                 uint32_t *nr_msrs, xen_msr_entry_t *msrs);
+int xc_get_domain_cpumsr_policy(xc_interface *xch, uint32_t domid,
+                                uint32_t *nr_leaves, xen_cpuid_leaf_t *leaves,
+                                uint32_t *nr_msrs, xen_msr_entry_t *msrs);
 
 uint32_t xc_get_cpu_featureset_size(void);
 
diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index ce2a584..efbac77 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -193,6 +193,46 @@ int xc_get_system_cpumsr_policy(xc_interface *xch, uint32_t index,
     return ret;
 }
 
+int xc_get_domain_cpumsr_policy(xc_interface *xch, uint32_t domid,
+                                uint32_t *nr_leaves, xen_cpuid_leaf_t *leaves,
+                                uint32_t *nr_msrs, xen_msr_entry_t *msrs)
+{
+    DECLARE_DOMCTL;
+    DECLARE_HYPERCALL_BOUNCE(leaves,
+                             *nr_leaves * sizeof(*leaves),
+                             XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+    DECLARE_HYPERCALL_BOUNCE(msrs,
+                             *nr_msrs * sizeof(*msrs),
+                             XC_HYPERCALL_BUFFER_BOUNCE_OUT);
+    int ret;
+
+    if ( xc_hypercall_bounce_pre(xch, leaves) )
+        return -1;
+
+    if ( xc_hypercall_bounce_pre(xch, msrs) )
+        return -1;
+
+    domctl.cmd = XEN_DOMCTL_get_cpumsr_policy;
+    domctl.domain = domid;
+    domctl.u.cpumsr_policy.nr_leaves = *nr_leaves;
+    set_xen_guest_handle(domctl.u.cpumsr_policy.cpuid_policy, leaves);
+    domctl.u.cpumsr_policy.nr_msrs = *nr_msrs;
+    set_xen_guest_handle(domctl.u.cpumsr_policy.msr_policy, msrs);
+
+    ret = do_domctl(xch, &domctl);
+
+    xc_hypercall_bounce_post(xch, leaves);
+    xc_hypercall_bounce_post(xch, msrs);
+
+    if ( !ret )
+    {
+        *nr_leaves = domctl.u.cpumsr_policy.nr_leaves;
+        *nr_msrs = domctl.u.cpumsr_policy.nr_msrs;
+    }
+
+    return ret;
+}
+
 struct cpuid_domain_info
 {
     enum
diff --git a/tools/misc/xen-cpuid.c b/tools/misc/xen-cpuid.c
index a5b3004..52a3694 100644
--- a/tools/misc/xen-cpuid.c
+++ b/tools/misc/xen-cpuid.c
@@ -3,6 +3,8 @@
 #include <err.h>
 #include <getopt.h>
 #include <string.h>
+#include <errno.h>
+#include <limits.h>
 
 #include <xenctrl.h>
 
@@ -308,11 +310,13 @@ int main(int argc, char **argv)
 {
     enum { MODE_UNKNOWN, MODE_INFO, MODE_DETAIL, MODE_INTERPRET, MODE_POLICY }
     mode = MODE_UNKNOWN;
+    int domid = -1;
 
     nr_features = xc_get_cpu_featureset_size();
 
     for ( ;; )
     {
+        const char *tmp_optarg;
         int option_index = 0, c;
         static struct option long_options[] =
         {
@@ -320,11 +324,11 @@ int main(int argc, char **argv)
             { "info", no_argument, NULL, 'i' },
             { "detail", no_argument, NULL, 'd' },
             { "verbose", no_argument, NULL, 'v' },
-            { "policy", no_argument, NULL, 'p' },
+            { "policy", optional_argument, NULL, 'p' },
             { NULL, 0, NULL, 0 },
         };
 
-        c = getopt_long(argc, argv, "hidvp", long_options, &option_index);
+        c = getopt_long(argc, argv, "hidvp::", long_options, &option_index);
 
         if ( c == -1 )
             break;
@@ -344,6 +348,28 @@ int main(int argc, char **argv)
 
         case 'p':
             mode = MODE_POLICY;
+
+            tmp_optarg = optarg;
+
+            /* Make "--policy $DOMID" and "-p $DOMID" work. */
+            if ( !optarg && optind < argc &&
+                 argv[optind] != NULL && argv[optind][0] != '\0' &&
+                 argv[optind][0] != '-' )
+                tmp_optarg = argv[optind++];
+
+            if ( tmp_optarg )
+            {
+                char *endptr;
+
+                errno = 0;
+                domid = strtol(tmp_optarg, &endptr, 0);
+
+                if ( (errno == ERANGE &&
+                      (domid == LONG_MAX || domid == LONG_MIN)) ||
+                     (errno != 0 && domid == 0) ||
+                     endptr == tmp_optarg )
+                    err(1, "strtol(%s,,)", tmp_optarg);
+            }
             break;
 
         case 'd':
@@ -397,8 +423,9 @@ int main(int argc, char **argv)
 
         if ( xc_get_cpumsr_policy_size(xch, &max_leaves, &max_msrs) )
             err(1, "xc_get_cpumsr_policy_size(...)");
-        printf("Xen reports there are maximum %u leaves and %u MSRs\n",
-                max_leaves, max_msrs);
+        if ( domid == -1 )
+            printf("Xen reports there are maximum %u leaves and %u MSRs\n",
+                   max_leaves, max_msrs);
 
         leaves = calloc(max_leaves, sizeof(xen_cpuid_leaf_t));
         if ( !leaves )
@@ -407,17 +434,36 @@ int main(int argc, char **argv)
         if ( !msrs )
             err(1, "calloc(max_msrs)");
 
-        for ( pol = 0; pol < ARRAY_SIZE(sys_policies); ++pol )
+        if ( domid != -1 )
         {
+            char name[20];
             uint32_t nr_leaves = max_leaves;
             uint32_t nr_msrs = max_msrs;
 
-            if ( xc_get_system_cpumsr_policy(xch, pol, &nr_leaves, leaves,
+            if ( xc_get_domain_cpumsr_policy(xch, domid, &nr_leaves, leaves,
                                              &nr_msrs, msrs) )
-                err(1, "xc_get_system_cpumsr_policy(, %s,,)",
-                    sys_policies[pol]);
+                err(1, "xc_get_domain_cpuid_policy(, %d, %d,, %d,)",
+                    domid, nr_leaves, nr_msrs);
 
-            print_policy(sys_policies[pol], leaves, nr_leaves, msrs, nr_msrs);
+            snprintf(name, sizeof(name), "Domain %d", domid);
+            print_policy(name, leaves, nr_leaves, msrs, nr_msrs);
+        }
+        else
+        {
+            /* Get system policies */
+            for ( pol = 0; pol < ARRAY_SIZE(sys_policies); ++pol )
+            {
+                uint32_t nr_leaves = max_leaves;
+                uint32_t nr_msrs = max_msrs;
+
+                if ( xc_get_system_cpumsr_policy(xch, pol, &nr_leaves, leaves,
+                                                 &nr_msrs, msrs) )
+                    err(1, "xc_get_system_cpumsr_policy(, %s,,)",
+                        sys_policies[pol]);
+
+                print_policy(sys_policies[pol], leaves, nr_leaves,
+                             msrs, nr_msrs);
+            }
         }
 
         free(leaves);
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index 3e9580b..8b48349 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -1524,6 +1524,52 @@ long arch_do_domctl(
         recalculate_cpuid_policy(d);
         break;
 
+    case XEN_DOMCTL_get_cpumsr_policy:
+        if ( d == currd ||       /* No domain_pause() */
+             d->max_vcpus == 0 ) /* No vcpus yet. */
+        {
+            ret = -EINVAL;
+            break;
+        }
+
+        domain_pause(d);
+
+        if ( !guest_handle_is_null(domctl->u.cpumsr_policy.cpuid_policy) )
+        {
+            if ( (ret = x86_cpuid_copy_to_buffer(
+                      d->arch.cpuid,
+                      domctl->u.cpumsr_policy.cpuid_policy,
+                      &domctl->u.cpumsr_policy.nr_leaves)) )
+                goto get_cpumsr_policy_out;
+
+            if ( __copy_field_to_guest(u_domctl, domctl,
+                                       u.cpumsr_policy.nr_leaves) )
+            {
+                ret = -EFAULT;
+                goto get_cpumsr_policy_out;
+            }
+        }
+
+        if ( !guest_handle_is_null(domctl->u.cpumsr_policy.msr_policy) )
+        {
+            if ( (ret = x86_msr_copy_to_buffer(
+                      d->arch.msr, d->vcpu[0]->arch.msr,
+                      domctl->u.cpumsr_policy.msr_policy,
+                      &domctl->u.cpumsr_policy.nr_msrs)) )
+                goto get_cpumsr_policy_out;
+
+            if ( __copy_field_to_guest(u_domctl, domctl,
+                                       u.cpumsr_policy.nr_msrs) )
+            {
+                ret = -EFAULT;
+                goto get_cpumsr_policy_out;
+            }
+        }
+
+    get_cpumsr_policy_out:
+        domain_unpause(d);
+        break;
+
     default:
         ret = iommu_do_domctl(domctl, d, u_domctl);
         break;
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index 0535da8..1ca41bd 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -635,6 +635,22 @@ struct xen_domctl_cpuid {
   uint32_t ecx;
   uint32_t edx;
 };
+
+/*
+ * XEN_SYSCTL_{get,set}_cpumsr_policy (x86 specific)
+ *
+ * Query or set the CPUID and MSR policies for a specific domain.
+ */
+struct xen_domctl_cpumsr_policy {
+    uint32_t nr_leaves; /* IN/OUT: Number of leaves in/written to
+                         * 'cpuid_policy'. */
+    uint32_t nr_msrs;   /* IN/OUT: Number of MSRs in/written to
+                         * 'msr_domain_policy' */
+    XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_policy; /* IN/OUT: */
+    XEN_GUEST_HANDLE_64(xen_msr_entry_t) msr_policy;    /* IN/OUT: */
+};
+typedef struct xen_domctl_cpumsr_policy xen_domctl_cpumsr_policy_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_cpumsr_policy_t);
 #endif
 
 /*
@@ -1172,6 +1188,7 @@ struct xen_domctl {
 #define XEN_DOMCTL_soft_reset                    79
 #define XEN_DOMCTL_set_gnttab_limits             80
 #define XEN_DOMCTL_vuart_op                      81
+#define XEN_DOMCTL_get_cpumsr_policy             82
 #define XEN_DOMCTL_gdbsx_guestmemio            1000
 #define XEN_DOMCTL_gdbsx_pausevcpu             1001
 #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
@@ -1216,6 +1233,7 @@ struct xen_domctl {
         struct xen_domctl_mem_sharing_op    mem_sharing_op;
 #if defined(__i386__) || defined(__x86_64__)
         struct xen_domctl_cpuid             cpuid;
+        struct xen_domctl_cpumsr_policy     cpumsr_policy;
         struct xen_domctl_vcpuextstate      vcpuextstate;
         struct xen_domctl_vcpu_msrs         vcpu_msrs;
 #endif
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 1d30b0e..245fcfd 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -717,6 +717,7 @@ static int flask_domctl(struct domain *d, int cmd)
         return current_has_perm(d, SECCLASS_DOMAIN, DOMAIN__SET_VIRQ_HANDLER);
 
     case XEN_DOMCTL_set_cpuid:
+    case XEN_DOMCTL_get_cpumsr_policy:
         return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SET_CPUID);
 
     case XEN_DOMCTL_gettscinfo:
diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors
index b5bc7a2..c92bea3 100644
--- a/xen/xsm/flask/policy/access_vectors
+++ b/xen/xsm/flask/policy/access_vectors
@@ -213,6 +213,7 @@ class domain2
 #  target = the new target domain
     set_as_target
 # XEN_DOMCTL_set_cpuid
+# XEN_DOMCTL_get_cpumsr_policy
     set_cpuid
 # XEN_DOMCTL_gettscinfo
     gettsc
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH 11/13] libx86: Introduce a helper to deserialise a cpuid_policy object
  2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
                   ` (9 preceding siblings ...)
  2018-07-03 20:55 ` [PATCH 10/13] x86/domctl: Implement XEN_DOMCTL_get_cpumsr_policy Andrew Cooper
@ 2018-07-03 20:55 ` Andrew Cooper
  2018-07-04  9:49   ` Jan Beulich
  2018-07-03 20:55 ` [PATCH 12/13] libx86: introduce a helper to deserialize MSR policies Andrew Cooper
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 67+ messages in thread
From: Andrew Cooper @ 2018-07-03 20:55 UTC (permalink / raw)
  To: Xen-devel
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Jan Beulich,
	Roger Pau Monné

As with the serialise side, Xen's copy_from_guest API is used, with a
compatibility wrapper for the userspace build.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Sergey Dyasli <sergey.dyasli@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
---
 xen/common/libx86/cpuid.c          | 88 ++++++++++++++++++++++++++++++++++++++
 xen/common/libx86/libx86-private.h | 12 ++++++
 xen/include/xen/libx86/cpuid.h     |  4 ++
 3 files changed, 104 insertions(+)

diff --git a/xen/common/libx86/cpuid.c b/xen/common/libx86/cpuid.c
index d38c505..659cd6e 100644
--- a/xen/common/libx86/cpuid.c
+++ b/xen/common/libx86/cpuid.c
@@ -128,6 +128,94 @@ int x86_cpuid_copy_to_buffer(const struct cpuid_policy *p,
 }
 
 /*
+ * Copy CPUID data from a buffer, filling in a cpuid_policy object.  Performs
+ * boudary checking of the incomming leaves before filling the appropriate
+ * policy unions, but no content validation is performed.
+ */
+int x86_cpuid_copy_from_buffer(struct cpuid_policy *p,
+                               const cpuid_leaf_buffer_t leaves,
+                               uint32_t nr_leaves, uint32_t *err_leaf,
+                               uint32_t *err_subleaf)
+{
+    unsigned int i;
+    xen_cpuid_leaf_t data;
+    struct cpuid_leaf *l = (void *)&data.a;
+
+    if ( nr_leaves > CPUID_MAX_SERIALISED_LEAVES )
+        return -E2BIG;
+
+    for ( i = 0; i < nr_leaves; ++i )
+    {
+        if ( copy_from_buffer_offset(&data, leaves, i, 1) )
+            return -EFAULT;
+
+        switch ( data.leaf )
+        {
+        case 0 ... ARRAY_SIZE(p->basic.raw) - 1:
+            switch ( data.leaf )
+            {
+            case 0x4:
+                if ( data.subleaf >= ARRAY_SIZE(p->cache.raw) )
+                    goto out_of_range;
+
+                p->cache.raw[data.subleaf] = *l;
+                break;
+
+            case 0x7:
+                if ( data.subleaf >= ARRAY_SIZE(p->feat.raw) )
+                    goto out_of_range;
+
+                p->feat.raw[data.subleaf] = *l;
+                break;
+
+            case 0xb:
+                if ( data.subleaf >= ARRAY_SIZE(p->topo.raw) )
+                    goto out_of_range;
+
+                p->topo.raw[data.subleaf] = *l;
+                break;
+
+            case 0xd:
+                if ( data.subleaf >= ARRAY_SIZE(p->xstate.raw) )
+                    goto out_of_range;
+
+                p->xstate.raw[data.leaf] = *l;
+                break;
+
+            default:
+                p->basic.raw[data.leaf] = *l;
+                break;
+            }
+            break;
+
+        case 0x40000000:
+            p->hv_limit = l->a;
+            break;
+
+        case 0x40000100:
+            p->hv2_limit = l->a;
+            break;
+
+        case 0x80000000 ... 0x80000000 + ARRAY_SIZE(p->extd.raw) - 1:
+            p->extd.raw[data.leaf & 0xffff] = *l;
+            break;
+
+        default:
+            goto out_of_range;
+        }
+    }
+
+    return 0;
+
+ out_of_range:
+    if ( err_leaf )
+        *err_leaf = data.leaf;
+    if ( err_subleaf )
+        *err_subleaf = data.subleaf;
+    return -ERANGE;
+}
+
+/*
  * Local variables:
  * mode: C
  * c-file-style: "BSD"
diff --git a/xen/common/libx86/libx86-private.h b/xen/common/libx86/libx86-private.h
index e4ead1a..04a0865 100644
--- a/xen/common/libx86/libx86-private.h
+++ b/xen/common/libx86/libx86-private.h
@@ -12,6 +12,7 @@
 #include <asm/msr-index.h>
 
 #define copy_to_buffer_offset copy_to_guest_offset
+#define copy_from_buffer_offset copy_from_guest_offset
 
 #else
 
@@ -47,6 +48,17 @@ static inline bool test_bit(unsigned int bit, const void *vaddr)
     0;                                                  \
 })
 
+/* memcpy(), but with copy_from_guest_offset()'s API */
+#define copy_from_buffer_offset(dst, src, index, nr) ({ \
+    const typeof(*(dst)) *s = (src);                    \
+    unsigned int i;                                     \
+                                                        \
+    for ( i = 0; i < (nr); i++ )                        \
+        (dst)[i] = s[(index) + i];                      \
+                                                        \
+    0;                                                  \
+})
+
 #endif /* __XEN__ */
 
 #endif /* XEN_LIBX86_PRIVATE_H */
diff --git a/xen/include/xen/libx86/cpuid.h b/xen/include/xen/libx86/cpuid.h
index 48ce48d..0e71016 100644
--- a/xen/include/xen/libx86/cpuid.h
+++ b/xen/include/xen/libx86/cpuid.h
@@ -254,6 +254,10 @@ typedef xen_cpuid_leaf_t *cpuid_leaf_buffer_t;
 int x86_cpuid_copy_to_buffer(const struct cpuid_policy *p,
                              cpuid_leaf_buffer_t leaves,
                              uint32_t *nr_entries_p);
+int x86_cpuid_copy_from_buffer(struct cpuid_policy *p,
+                               const cpuid_leaf_buffer_t leaves,
+                               uint32_t nr_leaves, uint32_t *err_leaf,
+                               uint32_t *err_subleaf);
 
 #endif /* !XEN_LIBX86_CPUID_H */
 
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH 12/13] libx86: introduce a helper to deserialize MSR policies
  2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
                   ` (10 preceding siblings ...)
  2018-07-03 20:55 ` [PATCH 11/13] libx86: Introduce a helper to deserialise a cpuid_policy object Andrew Cooper
@ 2018-07-03 20:55 ` Andrew Cooper
  2018-07-03 20:55 ` [PATCH 13/13] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy Andrew Cooper
  2018-07-04  8:17 ` [PATCH 00/13] x86: CPUID and MSR policy marshalling support Jan Beulich
  13 siblings, 0 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-03 20:55 UTC (permalink / raw)
  To: Xen-devel; +Cc: Sergey Dyasli, Andrew Cooper, Roger Pau Monné

From: Roger Pau Monné <roger.pau@citrix.com>

Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
 xen/common/libx86/msr.c      | 63 ++++++++++++++++++++++++++++++++++++++++++++
 xen/include/xen/libx86/msr.h |  4 +++
 2 files changed, 67 insertions(+)

diff --git a/xen/common/libx86/msr.c b/xen/common/libx86/msr.c
index 46a3458..13fb660 100644
--- a/xen/common/libx86/msr.c
+++ b/xen/common/libx86/msr.c
@@ -61,6 +61,69 @@ int x86_msr_copy_to_buffer(const struct msr_domain_policy *dp,
 }
 
 /*
+ * Copy MSR data from a buffer, filling optionally msr_domain_policy and
+ * msr_vcpu_policy objects.  MSR indicies are checked for being in range, but
+ * no content validation is performed for in-range MSRs.
+ */
+int x86_msr_copy_from_buffer(struct msr_domain_policy *dp,
+                             struct msr_vcpu_policy *vp,
+                             const msr_entry_buffer_t msrs, uint32_t nr_msrs,
+                             uint32_t *err_msr)
+{
+    unsigned int i;
+    xen_msr_entry_t data;
+
+    if ( nr_msrs > MSR_MAX_SERIALISED_ENTRIES )
+        return -E2BIG;
+
+    for ( i = 0; i < nr_msrs; i++ )
+    {
+        if ( copy_from_buffer_offset(&data, msrs, i, 1) )
+            return -EFAULT;
+
+        if ( data.flags ) /* .flags MBZ */
+            goto err;
+
+        switch ( data.idx )
+        {
+        case MSR_SPEC_CTRL:
+            if ( data.val > ~0u )
+                goto err;
+
+            if ( vp )
+                vp->spec_ctrl.raw = data.val;
+            break;
+
+        case MSR_INTEL_PLATFORM_INFO:
+            if ( data.val > ~0u )
+                goto err;
+
+            if ( dp )
+                dp->plaform_info.raw = data.val;
+            break;
+
+        case MSR_INTEL_MISC_FEATURES_ENABLES:
+            if ( data.val > ~0u )
+                goto err;
+
+            if ( vp )
+                vp->misc_features_enables.raw = data.val;
+            break;
+
+        default:
+            goto err;
+        }
+    }
+
+    return 0;
+
+ err:
+    if ( err_msr )
+        *err_msr = data.idx;
+    return -EINVAL;
+}
+
+/*
  * Local variables:
  * mode: C
  * c-file-style: "BSD"
diff --git a/xen/include/xen/libx86/msr.h b/xen/include/xen/libx86/msr.h
index 8776378..827eb3f 100644
--- a/xen/include/xen/libx86/msr.h
+++ b/xen/include/xen/libx86/msr.h
@@ -60,6 +60,10 @@ typedef xen_msr_entry_t *msr_entry_buffer_t;
 int x86_msr_copy_to_buffer(const struct msr_domain_policy *dp,
                            const struct msr_vcpu_policy *vp,
                            msr_entry_buffer_t msrs, uint32_t *nr_entries_p);
+int x86_msr_copy_from_buffer(struct msr_domain_policy *dp,
+                             struct msr_vcpu_policy *vp,
+                             const msr_entry_buffer_t msrs, uint32_t nr_msrs,
+                             uint32_t *err_msr);
 
 #endif /* !XEN_LIBX86_MSR_H */
 
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH 13/13] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy
  2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
                   ` (11 preceding siblings ...)
  2018-07-03 20:55 ` [PATCH 12/13] libx86: introduce a helper to deserialize MSR policies Andrew Cooper
@ 2018-07-03 20:55 ` Andrew Cooper
  2018-07-04 10:16   ` Jan Beulich
  2018-07-04 10:18   ` Wei Liu
  2018-07-04  8:17 ` [PATCH 00/13] x86: CPUID and MSR policy marshalling support Jan Beulich
  13 siblings, 2 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-03 20:55 UTC (permalink / raw)
  To: Xen-devel
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Jan Beulich,
	Daniel De Graaf, Roger Pau Monné

From: Sergey Dyasli <sergey.dyasli@citrix.com>

This hypercall allows the toolstack to present one combined CPUID and MSR
policy for a domain, which can be audited in one go by Xen, which is necessary
for correctness of the auditing.

A stub x86_policies_are_compatible() function is introduced, although at
present it will always fail the hypercall.

The hypercall ABI allows for update of individual CPUID or MSR entries, so
begins by duplicating the existing policy (for which a helper is introduced),
merging the toolstack data, then checking compatibility of the result.

The system PV/HVM max policy is used for the compatiblity check.

Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Roger Pau Monné <roger.pau@citrix.com>
CC: Sergey Dyasli <sergey.dyasli@citrix.com>
CC: Daniel De Graaf <dgdegra@tycho.nsa.gov>

One awkard corner case is re-deserialising of the vcpu msrs.  The correct fix
would be to allocate a buffer, copy the MSRs list, then deserialise from that,
but trips the bounds checks in the copy_from_guest() helpers.  The compat XLAT
are would work, but would require that we allocate it even for 64bit PV
guests.
---
 tools/libxc/Makefile                |  2 +-
 tools/libxc/include/xenctrl.h       |  5 +++
 tools/libxc/xc_cpuid_x86.c          | 49 +++++++++++++++++++++
 xen/arch/x86/domctl.c               | 87 +++++++++++++++++++++++++++++++++++++
 xen/common/libx86/Makefile          |  1 +
 xen/common/libx86/policies.c        | 19 ++++++++
 xen/include/public/domctl.h         |  7 +++
 xen/include/xen/libx86/policies.h   | 10 +++++
 xen/include/xen/xmalloc.h           |  7 +++
 xen/xsm/flask/hooks.c               |  1 +
 xen/xsm/flask/policy/access_vectors |  1 +
 11 files changed, 188 insertions(+), 1 deletion(-)
 create mode 100644 xen/common/libx86/policies.c

diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 407a9d1..5698fb0 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -83,7 +83,7 @@ $(patsubst %.c,%.opic,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
 # Add libx86 to the build
 vpath %.c ../../xen/common/libx86
 
-GUEST_SRCS-$(CONFIG_X86)     += cpuid.c msr.c
+GUEST_SRCS-$(CONFIG_X86)     += cpuid.c msr.c policies.c
 
 # new domain builder
 GUEST_SRCS-y                 += xc_dom_core.c xc_dom_boot.c
diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 15d2b92..653dcde 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -2544,6 +2544,11 @@ int xc_get_system_cpumsr_policy(xc_interface *xch, uint32_t index,
 int xc_get_domain_cpumsr_policy(xc_interface *xch, uint32_t domid,
                                 uint32_t *nr_leaves, xen_cpuid_leaf_t *leaves,
                                 uint32_t *nr_msrs, xen_msr_entry_t *msrs);
+int xc_set_domain_cpumsr_policy(xc_interface *xch, uint32_t domid,
+                                uint32_t nr_leaves, xen_cpuid_leaf_t *leaves,
+                                uint32_t nr_msrs, xen_msr_entry_t *msrs,
+                                uint32_t *err_leaf_p, uint32_t *err_subleaf_p,
+                                uint32_t *err_msr_idx_p);
 
 uint32_t xc_get_cpu_featureset_size(void);
 
diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index efbac77..ba0cf77 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -233,6 +233,55 @@ int xc_get_domain_cpumsr_policy(xc_interface *xch, uint32_t domid,
     return ret;
 }
 
+int xc_set_domain_cpumsr_policy(xc_interface *xch, uint32_t domid,
+                                uint32_t nr_leaves, xen_cpuid_leaf_t *leaves,
+                                uint32_t nr_msrs, xen_msr_entry_t *msrs,
+                                uint32_t *err_leaf_p, uint32_t *err_subleaf_p,
+                                uint32_t *err_msr_idx_p)
+{
+    DECLARE_DOMCTL;
+    DECLARE_HYPERCALL_BOUNCE(leaves,
+                             nr_leaves * sizeof(*leaves),
+                             XC_HYPERCALL_BUFFER_BOUNCE_IN);
+    DECLARE_HYPERCALL_BOUNCE(msrs,
+                             nr_msrs * sizeof(*msrs),
+                             XC_HYPERCALL_BUFFER_BOUNCE_IN);
+    int ret;
+
+    if ( xc_hypercall_bounce_pre(xch, leaves) )
+        return -1;
+
+    if ( xc_hypercall_bounce_pre(xch, msrs) )
+        return -1;
+
+    domctl.cmd = XEN_DOMCTL_set_cpumsr_policy;
+    domctl.domain = domid;
+    domctl.u.cpumsr_policy.nr_leaves = nr_leaves;
+    set_xen_guest_handle(domctl.u.cpumsr_policy.cpuid_policy, leaves);
+    domctl.u.cpumsr_policy.nr_msrs = nr_msrs;
+    set_xen_guest_handle(domctl.u.cpumsr_policy.msr_policy, msrs);
+    domctl.u.cpumsr_policy.err_leaf = ~0;
+    domctl.u.cpumsr_policy.err_subleaf = ~0;
+    domctl.u.cpumsr_policy.err_msr_idx = ~0;
+
+    ret = do_domctl(xch, &domctl);
+
+    xc_hypercall_bounce_post(xch, leaves);
+    xc_hypercall_bounce_post(xch, msrs);
+
+    if ( !ret )
+    {
+        if ( err_leaf_p )
+            *err_leaf_p = domctl.u.cpumsr_policy.err_leaf;
+        if ( err_subleaf_p )
+            *err_subleaf_p = domctl.u.cpumsr_policy.err_subleaf;
+        if ( err_msr_idx_p )
+            *err_msr_idx_p = domctl.u.cpumsr_policy.err_msr_idx;
+    }
+
+    return ret;
+}
+
 struct cpuid_domain_info
 {
     enum
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index 8b48349..46ee1bb 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -330,6 +330,71 @@ static int update_domain_cpuid_info(struct domain *d,
     return 0;
 }
 
+static int update_domain_cpumsr_policy(struct domain *d,
+                                       xen_domctl_cpumsr_policy_t *xdpc)
+{
+    struct policy_group new = {};
+    const struct policy_group *sys = is_pv_domain(d)
+        ? &system_policies[XEN_SYSCTL_cpumsr_policy_pv_max]
+        : &system_policies[XEN_SYSCTL_cpumsr_policy_hvm_max];
+    struct vcpu *v = d->vcpu[0];
+    int ret = -ENOMEM;
+
+    /* Initialise some help identifying auditing errors. */
+    xdpc->err_leaf = xdpc->err_subleaf = XEN_CPUID_NO_SUBLEAF;
+    xdpc->err_msr_idx = ~0;
+
+    /* Start with existing domain's policies */
+    if ( !(new.cp = xmemdup(d->arch.cpuid)) ||
+         !(new.dp = xmemdup(d->arch.msr)) ||
+         !(new.vp = xmemdup(v->arch.msr)) )
+        goto out;
+
+    /* Merge the toolstack provided data. */
+    if ( (ret = x86_cpuid_copy_from_buffer(
+              new.cp, xdpc->cpuid_policy, xdpc->nr_leaves,
+              &xdpc->err_leaf, &xdpc->err_subleaf)) )
+        goto out;
+
+    if ( (ret = x86_msr_copy_from_buffer(
+              new.dp, new.vp,
+              xdpc->msr_policy, xdpc->nr_msrs, &xdpc->err_msr_idx)) )
+        goto out;
+
+    /* Audit the combined dataset. */
+    ret = x86_policies_are_compatible(sys, &new);
+    if ( ret )
+        goto out;
+
+    /*
+     * Audit was successful.  Replace existing policies, leaving the old
+     * policies to be freed.
+     */
+    SWAP(new.cp, d->arch.cpuid);
+    SWAP(new.dp, d->arch.msr);
+    SWAP(new.vp, v->arch.msr);
+
+    /* Merge the (now audited) vCPU MSRs into every other msr_vcpu_policy. */
+    for ( ; v; v = v->next_in_list )
+    {
+        /* XXX - Figure out how to avoid a TOCTOU race here.  XLAT area? */
+        if ( (ret = x86_msr_copy_from_buffer(
+                  NULL, v->arch.msr, xdpc->msr_policy, xdpc->nr_msrs, NULL)) )
+        {
+            gprintk(XENLOG_ERR, "Error re-deserialising vCPU MSRs: %d\n", ret);
+            domain_crash(d);
+            goto out;
+        }
+    }
+
+ out:
+    xfree(new.cp);
+    xfree(new.dp);
+    xfree(new.vp);
+
+    return ret;
+}
+
 static int vcpu_set_vmce(struct vcpu *v,
                          const struct xen_domctl_ext_vcpucontext *evc)
 {
@@ -1570,6 +1635,28 @@ long arch_do_domctl(
         domain_unpause(d);
         break;
 
+    case XEN_DOMCTL_set_cpumsr_policy:
+        if ( d == currd ||       /* no domain_pause() */
+             d->max_vcpus == 0 ) /* No vcpus yet. */
+        {
+            ret = -EINVAL;
+            break;
+        }
+
+        domain_pause(d);
+
+        if ( d->creation_finished )
+            ret = -EEXIST; /* No changing once the domain is running. */
+        else
+        {
+            ret = update_domain_cpumsr_policy(d, &domctl->u.cpumsr_policy);
+            if ( !ret ) /* Copy domctl->u.cpumsr_policy.err_* to guest. */
+                copyback = true;
+        }
+
+        domain_unpause(d);
+        break;
+
     default:
         ret = iommu_do_domctl(domctl, d, u_domctl);
         break;
diff --git a/xen/common/libx86/Makefile b/xen/common/libx86/Makefile
index 2f9691e..90d64ac 100644
--- a/xen/common/libx86/Makefile
+++ b/xen/common/libx86/Makefile
@@ -1,2 +1,3 @@
 obj-y += cpuid.o
 obj-y += msr.o
+obj-y += policies.o
diff --git a/xen/common/libx86/policies.c b/xen/common/libx86/policies.c
new file mode 100644
index 0000000..80de150
--- /dev/null
+++ b/xen/common/libx86/policies.c
@@ -0,0 +1,19 @@
+#include "libx86-private.h"
+
+#include <xen/libx86/policies.h>
+
+int x86_policies_are_compatible(const struct policy_group *lhs,
+                                const struct policy_group *rhs)
+{
+    return -EOPNOTSUPP;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index 1ca41bd..4bc4629 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -648,6 +648,12 @@ struct xen_domctl_cpumsr_policy {
                          * 'msr_domain_policy' */
     XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_policy; /* IN/OUT: */
     XEN_GUEST_HANDLE_64(xen_msr_entry_t) msr_policy;    /* IN/OUT: */
+    uint32_t err_leaf, err_subleaf; /* OUT, set_policy only.  If not ~0,
+                                     * indicates the leaf/subleaf which
+                                     * auditing objected to. */
+    uint32_t err_msr_idx;           /* OUT, set_policy only.  If not ~0,
+                                     * indicates the MSR idx which
+                                     * auditing objected to. */
 };
 typedef struct xen_domctl_cpumsr_policy xen_domctl_cpumsr_policy_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_cpumsr_policy_t);
@@ -1189,6 +1195,7 @@ struct xen_domctl {
 #define XEN_DOMCTL_set_gnttab_limits             80
 #define XEN_DOMCTL_vuart_op                      81
 #define XEN_DOMCTL_get_cpumsr_policy             82
+#define XEN_DOMCTL_set_cpumsr_policy             83
 #define XEN_DOMCTL_gdbsx_guestmemio            1000
 #define XEN_DOMCTL_gdbsx_pausevcpu             1001
 #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
diff --git a/xen/include/xen/libx86/policies.h b/xen/include/xen/libx86/policies.h
index d6fa1bc..21e0a40 100644
--- a/xen/include/xen/libx86/policies.h
+++ b/xen/include/xen/libx86/policies.h
@@ -12,6 +12,16 @@ struct policy_group
     struct msr_vcpu_policy *vp;
 };
 
+/*
+ * Calculate whether two policies are compatible.
+ *
+ * For typical usage, lhs should be a system policy, and rhs should be a
+ * proposed guest policy.  This largely amounts to "is rhs a subset of lhs",
+ * but some of the checks are rather more complicated in practice.
+ */
+int x86_policies_are_compatible(const struct policy_group *lhs,
+                                const struct policy_group *rhs);
+
 #endif /* !XEN_LIBX86_POLICIES_H */
 
 /*
diff --git a/xen/include/xen/xmalloc.h b/xen/include/xen/xmalloc.h
index cc2673d..ee5fe84 100644
--- a/xen/include/xen/xmalloc.h
+++ b/xen/include/xen/xmalloc.h
@@ -13,6 +13,13 @@
 #define xmalloc(_type) ((_type *)_xmalloc(sizeof(_type), __alignof__(_type)))
 #define xzalloc(_type) ((_type *)_xzalloc(sizeof(_type), __alignof__(_type)))
 
+/* Allocate space for a typed object and copy an existing instance. */
+#define xmemdup(ptr)                                    \
+    ({  typeof(*ptr) *n_ = xmalloc(typeof(*ptr));       \
+        if ( n_ )                                       \
+            memcpy(n_, ptr, sizeof(*ptr));              \
+        n_; })
+
 /* Allocate space for array of typed objects. */
 #define xmalloc_array(_type, _num) \
     ((_type *)_xmalloc_array(sizeof(_type), __alignof__(_type), _num))
diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
index 245fcfd..4ad87c7 100644
--- a/xen/xsm/flask/hooks.c
+++ b/xen/xsm/flask/hooks.c
@@ -718,6 +718,7 @@ static int flask_domctl(struct domain *d, int cmd)
 
     case XEN_DOMCTL_set_cpuid:
     case XEN_DOMCTL_get_cpumsr_policy:
+    case XEN_DOMCTL_set_cpumsr_policy:
         return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__SET_CPUID);
 
     case XEN_DOMCTL_gettscinfo:
diff --git a/xen/xsm/flask/policy/access_vectors b/xen/xsm/flask/policy/access_vectors
index c92bea3..d76dc3f 100644
--- a/xen/xsm/flask/policy/access_vectors
+++ b/xen/xsm/flask/policy/access_vectors
@@ -214,6 +214,7 @@ class domain2
     set_as_target
 # XEN_DOMCTL_set_cpuid
 # XEN_DOMCTL_get_cpumsr_policy
+# XEN_DOMCTL_set_cpumsr_policy
     set_cpuid
 # XEN_DOMCTL_gettscinfo
     gettsc
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* Re: [PATCH 01/13] libx86: Introduce libx86/cpuid.h
  2018-07-03 20:55 ` [PATCH 01/13] libx86: Introduce libx86/cpuid.h Andrew Cooper
@ 2018-07-04  6:54   ` Wei Liu
  2018-07-04  8:21   ` Jan Beulich
  1 sibling, 0 replies; 67+ messages in thread
From: Wei Liu @ 2018-07-04  6:54 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Jan Beulich,
	Roger Pau Monné

On Tue, Jul 03, 2018 at 09:55:14PM +0100, Andrew Cooper wrote:
> Begin to untangle the header dependency tangle by moving definition of
> struct cpuid_leaf out of x86_emulate.h into the new cpuid.h.
> 
> Additionally, plumb the header through to libxc.  This is technically a
> redundant include at this point, but it helps build-test the later changes,
> and will be used eventually.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>

Reviewed-by: Wei Liu <wei.liu2@citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 02/13] libx86: generate cpuid-autogen.h in the libx86 include dir
  2018-07-03 20:55 ` [PATCH 02/13] libx86: generate cpuid-autogen.h in the libx86 include dir Andrew Cooper
@ 2018-07-04  7:03   ` Wei Liu
  2018-07-04  8:33   ` Jan Beulich
  1 sibling, 0 replies; 67+ messages in thread
From: Wei Liu @ 2018-07-04  7:03 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Jan Beulich,
	Roger Pau Monné

On Tue, Jul 03, 2018 at 09:55:15PM +0100, Andrew Cooper wrote:
> From: Roger Pau Monné <roger.pau@citrix.com>
> 
> This prevents having to generate it inside the libxc folder.
> 
> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
> CC: Sergey Dyasli <sergey.dyasli@citrix.com>
> CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
> 
> RFC - I'm not sure a parallel build of Xen and the tools works.

There is a potential race that two make processes write to .new file at
the same time, isn't there?

Wei.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 03/13] libx86: Share struct cpuid_policy with userspace
  2018-07-03 20:55 ` [PATCH 03/13] libx86: Share struct cpuid_policy with userspace Andrew Cooper
@ 2018-07-04  7:08   ` Wei Liu
  2018-07-04  8:36   ` Jan Beulich
  1 sibling, 0 replies; 67+ messages in thread
From: Wei Liu @ 2018-07-04  7:08 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Jan Beulich,
	Roger Pau Monné

On Tue, Jul 03, 2018 at 09:55:16PM +0100, Andrew Cooper wrote:
> From: Roger Pau Monné <roger.pau@citrix.com>
> 
> No functional change.
> 
> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
> CC: Sergey Dyasli <sergey.dyasli@citrix.com>
> CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
> ---
>  tools/libxc/xc_cpuid_x86.c             |   2 +
>  tools/tests/x86_emulator/x86-emulate.h |   2 +
>  xen/include/asm-x86/cpuid.h            | 219 ---------------------------------
>  xen/include/xen/libx86/cpuid.h         | 219 +++++++++++++++++++++++++++++++++
>  4 files changed, 223 insertions(+), 219 deletions(-)
> 
> diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
> index 06f104d..5ee4a2d 100644
> --- a/tools/libxc/xc_cpuid_x86.c
> +++ b/tools/libxc/xc_cpuid_x86.c
> @@ -27,6 +27,8 @@
>  #include <xen/hvm/params.h>
>  #include <xen-tools/libs.h>
>  
> +#define MAX(x, y) ((x) > (y) ? (x) : (y))
> +

It appears that this is more suitable to be put into
include/xen-tools/libs.h

>  #include <xen/libx86/cpuid.h>
>  
>  enum {
> diff --git a/tools/tests/x86_emulator/x86-emulate.h b/tools/tests/x86_emulator/x86-emulate.h
> index c5e85de..b204901 100644
> --- a/tools/tests/x86_emulator/x86-emulate.h
> +++ b/tools/tests/x86_emulator/x86-emulate.h
> @@ -21,6 +21,8 @@
>  
>  #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
>  
> +#define MAX(x, y) ((x) > (y) ? (x) : (y))
> +

And with that libs.h included here you can also delete the BUILD_BUG_ON
in this file.

This can be done either in the next version or as a follow-up patch if
that's easier.

In any case:

Reviewed-by: Wei Liu <wei.liu2@citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 04/13] libx86: introduce a libx86 shared library
  2018-07-03 20:55 ` [PATCH 04/13] libx86: introduce a libx86 shared library Andrew Cooper
@ 2018-07-04  7:20   ` Wei Liu
  2018-07-04  8:42   ` Jan Beulich
  1 sibling, 0 replies; 67+ messages in thread
From: Wei Liu @ 2018-07-04  7:20 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Jan Beulich,
	Roger Pau Monné

On Tue, Jul 03, 2018 at 09:55:17PM +0100, Andrew Cooper wrote:
> From: Roger Pau Monné <roger.pau@citrix.com>
> 
> Move x86_cpuid_lookup_deep_deps() into the shared library, removing the
> individual copies from the hypervisor and libxc respectively.
> 
> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
> CC: Sergey Dyasli <sergey.dyasli@citrix.com>
> CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
> ---
>  tools/libxc/Makefile               |  5 +++++
>  tools/libxc/include/xenctrl.h      |  1 -
>  tools/libxc/xc_cpuid_x86.c         | 29 +------------------------
>  xen/arch/x86/cpu/common.c          |  2 +-
>  xen/arch/x86/cpuid.c               | 32 +--------------------------
>  xen/common/Makefile                |  1 +
>  xen/common/libx86/Makefile         |  1 +
>  xen/common/libx86/cpuid.c          | 44 ++++++++++++++++++++++++++++++++++++++
>  xen/common/libx86/libx86-private.h | 42 ++++++++++++++++++++++++++++++++++++
>  xen/include/asm-x86/cpuid.h        |  2 --
>  xen/include/xen/libx86/cpuid.h     |  2 ++
>  11 files changed, 98 insertions(+), 63 deletions(-)
>  create mode 100644 xen/common/libx86/Makefile
>  create mode 100644 xen/common/libx86/cpuid.c
>  create mode 100644 xen/common/libx86/libx86-private.h
> 
> diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
> index 0ee0813..f534d90 100644
> --- a/tools/libxc/Makefile
> +++ b/tools/libxc/Makefile
> @@ -80,6 +80,11 @@ GUEST_SRCS-y += $(ELF_SRCS-y)
>  $(patsubst %.c,%.o,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
>  $(patsubst %.c,%.opic,$(ELF_SRCS-y)): CFLAGS += -Wno-pointer-sign
>  
> +# Add libx86 to the build
> +vpath %.c ../../xen/common/libx86
> +
> +GUEST_SRCS-$(CONFIG_X86)     += cpuid.c

I think it is better to not expose libx86 to Arm build, so the vpath
should be guarded by CONFIG_X86 too.

ifeq ($(CONFIG_X86),y)
vpath ...
GUEST_SRCS-y += ...
endif

The rest looks fine.

Wei.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 05/13] libx86: Introduce libx86/msr.h and share msr_{domain, vcpu}_policy with userspace
  2018-07-03 20:55 ` [PATCH 05/13] libx86: Introduce libx86/msr.h and share msr_{domain, vcpu}_policy with userspace Andrew Cooper
@ 2018-07-04  7:21   ` Wei Liu
  2018-07-04  8:43   ` Jan Beulich
  1 sibling, 0 replies; 67+ messages in thread
From: Wei Liu @ 2018-07-04  7:21 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Jan Beulich,
	Roger Pau Monné

On Tue, Jul 03, 2018 at 09:55:18PM +0100, Andrew Cooper wrote:
> No functional change.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Reviewed-by: Wei Liu <wei.liu2@citrix.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 00/13] x86: CPUID and MSR policy marshalling support
  2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
                   ` (12 preceding siblings ...)
  2018-07-03 20:55 ` [PATCH 13/13] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy Andrew Cooper
@ 2018-07-04  8:17 ` Jan Beulich
  2018-07-04 10:40   ` Andrew Cooper
  13 siblings, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-04  8:17 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Daniel de Graaf,
	Roger Pau Monne

>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> Some open questions:
> 
>   * The position of libx86 in the source tree.  It probably doesn't want to
>     live in its current location.

So did you intentionally decide against ...

>  .gitignore                                  |   2 +-
>  tools/include/Makefile                      |  15 ++
>  tools/libxc/Makefile                        |  14 +-
>  tools/libxc/include/xenctrl.h               |  15 +-
>  tools/libxc/xc_cpuid_x86.c                  | 163 +++++++++++++++++---
>  tools/misc/xen-cpuid.c                      | 135 +++++++++++++++-
>  tools/tests/x86_emulator/x86-emulate.h      |   2 +
>  xen/arch/x86/cpu/common.c                   |   2 +-
>  xen/arch/x86/cpuid.c                        |  32 +---
>  xen/arch/x86/domctl.c                       | 133 ++++++++++++++++
>  xen/arch/x86/msr.c                          |   4 +-
>  xen/arch/x86/sysctl.c                       | 101 ++++++++++++
>  xen/arch/x86/x86_emulate/x86_emulate.h      |   7 +-
>  xen/common/Makefile                         |   1 +
>  xen/common/libx86/Makefile                  |   3 +
>  xen/common/libx86/cpuid.c                   | 226 +++++++++++++++++++++++++++
>  xen/common/libx86/libx86-private.h          |  74 +++++++++
>  xen/common/libx86/msr.c                     | 134 ++++++++++++++++
>  xen/common/libx86/policies.c                |  19 +++

xen/lib/x86/... or lib/x86/... here and ...

>  xen/include/Makefile                        |   6 +-
>  xen/include/asm-x86/cpufeatures.h           |   2 +-
>  xen/include/asm-x86/cpuid.h                 | 228 +---------------------------
>  xen/include/asm-x86/msr.h                   |  65 ++------
>  xen/include/public/arch-x86/xen.h           |  18 +++
>  xen/include/public/domctl.h                 |  25 +++
>  xen/include/public/sysctl.h                 |  41 +++++
>  xen/include/{asm-x86 => xen/libx86}/cpuid.h | 103 +++++--------
>  xen/include/xen/libx86/msr.h                |  78 ++++++++++
>  xen/include/xen/libx86/policies.h           |  35 +++++

xen/include/lib/x86/... or include/lib/x86/... here, as suggested
on irc? Personally I'd favor the top level variants, as that makes
sufficiently clear that the code is neither specific to the hypervisor
nor specific to the tools.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 01/13] libx86: Introduce libx86/cpuid.h
  2018-07-03 20:55 ` [PATCH 01/13] libx86: Introduce libx86/cpuid.h Andrew Cooper
  2018-07-04  6:54   ` Wei Liu
@ 2018-07-04  8:21   ` Jan Beulich
  2018-07-04 12:03     ` Andrew Cooper
  1 sibling, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-04  8:21 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Xen-devel, Wei Liu, Ian Jackson, Roger Pau Monne

>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> --- a/tools/include/Makefile
> +++ b/tools/include/Makefile
> @@ -21,6 +21,9 @@ xen/.dir:
>  	ln -sf $(addprefix $(XEN_ROOT)/xen/include/xen/,libelf.h elfstructs.h) xen/libelf/
>  	ln -s ../xen-foreign xen/foreign
>  	ln -sf $(XEN_ROOT)/xen/include/acpi acpi
> +ifeq ($(CONFIG_X86),y)
> +	ln -sf $(XEN_ROOT)/xen/include/xen/libx86 xen/libx86
> +endif

Why not set the include path suitably? And otherwise, what harm would
there be installing the link also when targeting ARM?

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 02/13] libx86: generate cpuid-autogen.h in the libx86 include dir
  2018-07-03 20:55 ` [PATCH 02/13] libx86: generate cpuid-autogen.h in the libx86 include dir Andrew Cooper
  2018-07-04  7:03   ` Wei Liu
@ 2018-07-04  8:33   ` Jan Beulich
  1 sibling, 0 replies; 67+ messages in thread
From: Jan Beulich @ 2018-07-04  8:33 UTC (permalink / raw)
  To: Andrew Cooper, Roger Pau Monne
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel

>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> From: Roger Pau Monné <roger.pau@citrix.com>
> 
> This prevents having to generate it inside the libxc folder.

And this is useful / desirable / necessary because of what?

> RFC - I'm not sure a parallel build of Xen and the tools works.

I'm pretty sure it won't with this approach. Considering my comment
just given on patch 1, this suggests yet another model as alternative:
Instead of making the directory a symlink, create a real directory in
the tools tree, symlink all files, and generate the file there. If the
"master" tree sat at the root of the tree, the same would then be
doable for the hypervisor build, thus completely decoupling the two
instances of building the header.

This would then also deal with the risk of the two rules (intentionally
or not) to go out of sync, producing (slightly) different headers.

> --- a/tools/include/Makefile
> +++ b/tools/include/Makefile
> @@ -26,6 +26,17 @@ ifeq ($(CONFIG_X86),y)
>  endif
>  	touch $@
>  
> +ifeq ($(CONFIG_X86),y)
> +$(XEN_ROOT)/xen/include/xen/libx86/cpuid-autogen.h: $(XEN_ROOT)/xen/include/public/arch-x86/cpufeatureset.h $(XEN_ROOT)/xen/tools/gen-cpuid.py FORCE

This being an independent rule, I think it needs to depend on xen/.dir.

> +	$(PYTHON) $(XEN_ROOT)/xen/tools/gen-cpuid.py -i $< -o $@.new
> +	$(call move-if-changed,$@.new,$@)
> +
> +all: $(XEN_ROOT)/xen/include/xen/libx86/cpuid-autogen.h
> +# NB: Use a FORCE target to always rebuild the autogenerated cpuid header
> +FORCE:
> +.PHONY: FORCE
> +endif

The comment is slightly misleading, I'm afraid: The move-if-changed
means the header itself isn't always rebuilt, it's only the intermediate
file which is. Perhaps "... to always invoke the autogenerated cpuid
header rule"?

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 03/13] libx86: Share struct cpuid_policy with userspace
  2018-07-03 20:55 ` [PATCH 03/13] libx86: Share struct cpuid_policy with userspace Andrew Cooper
  2018-07-04  7:08   ` Wei Liu
@ 2018-07-04  8:36   ` Jan Beulich
  1 sibling, 0 replies; 67+ messages in thread
From: Jan Beulich @ 2018-07-04  8:36 UTC (permalink / raw)
  To: Andrew Cooper, Roger Pau Monne
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel

>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> From: Roger Pau Monné <roger.pau@citrix.com>
> 
> No functional change.
> 
> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

This is all fine with me (subject to path name adjustments), but the description
is too short. I'd expect this to at least make clear that this is for convenience,
not because the structure layouts etc have to match.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 04/13] libx86: introduce a libx86 shared library
  2018-07-03 20:55 ` [PATCH 04/13] libx86: introduce a libx86 shared library Andrew Cooper
  2018-07-04  7:20   ` Wei Liu
@ 2018-07-04  8:42   ` Jan Beulich
  2018-07-04 15:48     ` Andrew Cooper
  1 sibling, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-04  8:42 UTC (permalink / raw)
  To: Andrew Cooper, Roger Pau Monne
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel

>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> From: Roger Pau Monné <roger.pau@citrix.com>
> 
> Move x86_cpuid_lookup_deep_deps() into the shared library, removing the
> individual copies from the hypervisor and libxc respectively.
> 
> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
> CC: Sergey Dyasli <sergey.dyasli@citrix.com>
> CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
> ---
>  tools/libxc/Makefile               |  5 +++++
>  tools/libxc/include/xenctrl.h      |  1 -
>  tools/libxc/xc_cpuid_x86.c         | 29 +------------------------
>  xen/arch/x86/cpu/common.c          |  2 +-
>  xen/arch/x86/cpuid.c               | 32 +--------------------------
>  xen/common/Makefile                |  1 +
>  xen/common/libx86/Makefile         |  1 +
>  xen/common/libx86/cpuid.c          | 44 ++++++++++++++++++++++++++++++++++++++
>  xen/common/libx86/libx86-private.h | 42 ++++++++++++++++++++++++++++++++++++

I'm pretty opposed to redundancies in names like this - why can't
this simply be private.h - its placement in the tree makes clear
whose private header this is.

> --- /dev/null
> +++ b/xen/common/libx86/libx86-private.h
> @@ -0,0 +1,42 @@
> +#ifndef XEN_LIBX86_PRIVATE_H
> +#define XEN_LIBX86_PRIVATE_H
> +
> +#ifdef __XEN__
> +
> +#include <xen/bitops.h>
> +#include <xen/kernel.h>
> +#include <xen/lib.h>
> +#include <xen/types.h>
> +
> +#else
> +
> +#include <inttypes.h>
> +#include <stdbool.h>
> +#include <stddef.h>
> +
> +#include <xen-tools/libs.h>
> +
> +#define MAX(x, y) ((x) > (y) ? (x) : (y))
> +
> +#define ARRAY_SIZE(x) (sizeof x / sizeof *x)
> +
> +static inline bool test_bit(unsigned int bit, const void *vaddr)
> +{
> +    const char *addr = vaddr;
> +
> +    return addr[bit / 8] & (1u << (bit % 8));
> +}
> +
> +#endif /* __XEN__ */
> +
> +#endif /* XEN_LIBX86_PRIVATE_H */

Did you consider making this x86-independent but still shared?
None of the above is x86-specific. libelf could then possibly use
this too, for exampled.

Also I think we pretty consistently use sizeof(x), not sizeof x, so
I'd like to ask that ARRAY_SIZE() be adjusted accordingly.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
  2018-07-03 20:55 ` [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object Andrew Cooper
@ 2018-07-04  8:42   ` Wei Liu
  2018-07-04  8:51     ` Jan Beulich
  2018-07-04  9:01   ` Jan Beulich
  1 sibling, 1 reply; 67+ messages in thread
From: Wei Liu @ 2018-07-04  8:42 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Jan Beulich,
	Roger Pau Monné

On Tue, Jul 03, 2018 at 09:55:19PM +0100, Andrew Cooper wrote:
> The serialised form is made up of the leaf, subleaf and data tuple.  As this
> is the architectural form, it is expected not to change going forwards.
> 
> x86_cpuid_copy_to_buffer() is implemented using Xen's regular copy_to_guest
> primitives, with an API-compatible memcpy() is used for the libxc half of the
> build.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
[...]
> diff --git a/xen/include/public/arch-x86/xen.h b/xen/include/public/arch-x86/xen.h
> index 69ee4bc..f3bdd83 100644
> --- a/xen/include/public/arch-x86/xen.h
> +++ b/xen/include/public/arch-x86/xen.h
> @@ -314,6 +314,17 @@ struct xen_arch_domainconfig {
>  #define XEN_ACPI_GPE0_CPUHP_BIT      2
>  #endif
>  
> +/*
> + * Representations of architectural CPUID information.  Used as the
> + * serialised version of Xen's internal representation.
> + */
> +typedef struct xen_cpuid_leaf {
> +#define XEN_CPUID_NO_SUBLEAF 0xffffffffu
> +    uint32_t leaf, subleaf;
> +    uint32_t a, b, c, d;
> +} xen_cpuid_leaf_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t);
> +

Is putting this in public header while leaving
CPUID_MAX_SERIALISED_LEAVES in a private header useful?

How does an external user know how big a buffer it needs to provide to
accommodate the return structure?

Wei.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 05/13] libx86: Introduce libx86/msr.h and share msr_{domain, vcpu}_policy with userspace
  2018-07-03 20:55 ` [PATCH 05/13] libx86: Introduce libx86/msr.h and share msr_{domain, vcpu}_policy with userspace Andrew Cooper
  2018-07-04  7:21   ` Wei Liu
@ 2018-07-04  8:43   ` Jan Beulich
  1 sibling, 0 replies; 67+ messages in thread
From: Jan Beulich @ 2018-07-04  8:43 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Xen-devel, Wei Liu, Ian Jackson, Roger Pau Monne

>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> No functional change.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Same as for the earlier patch: Please make clear here that this is for
convenience only.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
  2018-07-04  8:42   ` Wei Liu
@ 2018-07-04  8:51     ` Jan Beulich
  2018-07-04 16:23       ` Andrew Cooper
  0 siblings, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-04  8:51 UTC (permalink / raw)
  To: Andrew Cooper, Wei Liu
  Cc: Sergey Dyasli, Xen-devel, Ian Jackson, Roger Pau Monne

>>> On 04.07.18 at 10:42, <wei.liu2@citrix.com> wrote:
> On Tue, Jul 03, 2018 at 09:55:19PM +0100, Andrew Cooper wrote:
>> --- a/xen/include/public/arch-x86/xen.h
>> +++ b/xen/include/public/arch-x86/xen.h
>> @@ -314,6 +314,17 @@ struct xen_arch_domainconfig {
>>  #define XEN_ACPI_GPE0_CPUHP_BIT      2
>>  #endif
>>  
>> +/*
>> + * Representations of architectural CPUID information.  Used as the
>> + * serialised version of Xen's internal representation.
>> + */
>> +typedef struct xen_cpuid_leaf {
>> +#define XEN_CPUID_NO_SUBLEAF 0xffffffffu
>> +    uint32_t leaf, subleaf;
>> +    uint32_t a, b, c, d;
>> +} xen_cpuid_leaf_t;
>> +DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t);
>> +
> 
> Is putting this in public header while leaving
> CPUID_MAX_SERIALISED_LEAVES in a private header useful?
> 
> How does an external user know how big a buffer it needs to provide to
> accommodate the return structure?

Yeah, this is indeed hard to tell from this patch alone. And going
over the titles of the remainder of the series it's also not clear
where a use of this structure in a domctl/sysctl would appear.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
  2018-07-03 20:55 ` [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object Andrew Cooper
  2018-07-04  8:42   ` Wei Liu
@ 2018-07-04  9:01   ` Jan Beulich
  2018-07-04 16:46     ` Andrew Cooper
  1 sibling, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-04  9:01 UTC (permalink / raw)
  To: Andrew Cooper, Roger Pau Monne
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel

>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> --- a/xen/common/libx86/cpuid.c
> +++ b/xen/common/libx86/cpuid.c
> @@ -34,6 +34,100 @@ const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature)
>  }
>  
>  /*
> + * Copy a single cpuid_leaf into a provided xen_cpuid_leaf_t buffer,
> + * performing boundary checking against the buffer size.
> + */
> +static int copy_leaf_to_buffer(uint32_t leaf, uint32_t subleaf,
> +                               const struct cpuid_leaf *data,
> +                               cpuid_leaf_buffer_t leaves,
> +                               uint32_t *curr_entry, const uint32_t nr_entries)
> +{
> +    const xen_cpuid_leaf_t val = {
> +        leaf, subleaf, data->a, data->b, data->c, data->d,
> +    };
> +
> +    if ( *curr_entry == nr_entries )
> +        return -ENOBUFS;
> +
> +    if ( copy_to_buffer_offset(leaves, *curr_entry, &val, 1) )
> +        return -EFAULT;
> +
> +    ++*curr_entry;

Following on from what Wei has said - you don't mean to have a way
here then to indicate to a higher up caller how many slots would have
been needed?

> +int x86_cpuid_copy_to_buffer(const struct cpuid_policy *p,
> +                             cpuid_leaf_buffer_t leaves,
> +                             uint32_t *nr_entries_p)
> +{
> +    const uint32_t nr_entries = *nr_entries_p;
> +    uint32_t curr_entry = 0, leaf, subleaf;
> +
> +#define COPY_LEAF(l, s, data)                                       \
> +    ({  int ret;                                                    \
> +        if ( (ret = copy_leaf_to_buffer(                            \
> +                  l, s, data, leaves, &curr_entry, nr_entries)) )   \
> +            return ret;                                             \
> +    })
> +
> +    /* Basic leaves. */
> +    for ( leaf = 0; leaf <= MIN(p->basic.max_leaf,
> +                                ARRAY_SIZE(p->basic.raw) - 1); ++leaf )
> +    {
> +        switch ( leaf )
> +        {
> +        case 0x4:
> +            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->cache.raw); ++subleaf )
> +                COPY_LEAF(leaf, subleaf, &p->cache.raw[subleaf]);
> +            break;
> +
> +        case 0x7:
> +            for ( subleaf = 0;
> +                  subleaf <= MIN(p->feat.max_subleaf,
> +                                 ARRAY_SIZE(p->feat.raw) - 1); ++subleaf )
> +                COPY_LEAF(leaf, subleaf, &p->feat.raw[subleaf]);
> +            break;
> +
> +        case 0xb:
> +            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->topo.raw); ++subleaf )
> +                COPY_LEAF(leaf, subleaf, &p->topo.raw[subleaf]);
> +            break;
> +
> +        case 0xd:
> +            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->xstate.raw); ++subleaf )
> +                COPY_LEAF(leaf, subleaf, &p->xstate.raw[subleaf]);
> +            break;
> +
> +        default:
> +            COPY_LEAF(leaf, XEN_CPUID_NO_SUBLEAF, &p->basic.raw[leaf]);
> +            break;
> +        }
> +    }
> +
> +    COPY_LEAF(0x40000000, XEN_CPUID_NO_SUBLEAF,
> +              &(struct cpuid_leaf){ p->hv_limit });
> +    COPY_LEAF(0x40000100, XEN_CPUID_NO_SUBLEAF,
> +              &(struct cpuid_leaf){ p->hv2_limit });

Is it a good idea to produce wrong (zero) EBX, ECX, and EDX values here?

> @@ -27,6 +33,17 @@ static inline bool test_bit(unsigned int bit, const void *vaddr)
>      return addr[bit / 8] & (1u << (bit % 8));
>  }
>  
> +/* memcpy(), but with copy_to_guest_offset()'s API */
> +#define copy_to_buffer_offset(dst, index, src, nr) ({   \
> +    const typeof(*(dst)) *s = (src);                    \
> +    unsigned int i;                                     \
> +                                                        \
> +    for ( i = 0; i < (nr); i++ )                        \
> +        (dst)[(index) + i] = s[i];                      \
> +                                                        \
> +    0;                                                  \
> +})

Should you try to avoid multiple evaluation of macro arguments
here?

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 07/13] libx86: Introduce a helper to serialise msr_{domain, vcpu}_policy objects
  2018-07-03 20:55 ` [PATCH 07/13] libx86: Introduce a helper to serialise msr_{domain, vcpu}_policy objects Andrew Cooper
@ 2018-07-04  9:16   ` Jan Beulich
  2018-07-04 16:56     ` Andrew Cooper
  0 siblings, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-04  9:16 UTC (permalink / raw)
  To: Andrew Cooper, Roger Pau Monne
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel

>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> From: Roger Pau Monné <roger.pau@citrix.com>
> 
> As with CPUID, the an architectural form is used for representing the MSR

Stray "the".

Apart from that same remark(s) as for the respective CPUID change,
plus ...

> @@ -325,6 +325,13 @@ typedef struct xen_cpuid_leaf {
>  } xen_cpuid_leaf_t;
>  DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t);
>  
> +typedef struct xen_msr_entry {
> +    uint32_t idx;
> +    uint32_t flags; /* Reserved MBZ. */

... it remains unclear in this patch whose responsibility it is to clear this
field. I wonder whether copy_msr_to_buffer() should make sure of this.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 08/13] x86: Collect policies together into groups
  2018-07-03 20:55 ` [PATCH 08/13] x86: Collect policies together into groups Andrew Cooper
@ 2018-07-04  9:22   ` Jan Beulich
  2018-07-04 17:15     ` Andrew Cooper
  0 siblings, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-04  9:22 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Xen-devel, Wei Liu, Ian Jackson, Roger Pau Monne

>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> This is mainly prep work for the following patch, but this specific
> abstraction is also specifically useful for the future auditing logic.
> 
> Not all of msr_vcpu_policy will be interesting from a domain building
> perspective, but some soon-to-appear fields will be (SGX Launch Hash
> specifically).  The exact split of MSRs between domain and vcpu policies is
> internal to Xen and liable to change moving forwards, so treat the two
> structures consistently from the start to avoid problems in the future.

I hope the utility of this grouping will become evident in later
patches.

> --- a/xen/arch/x86/sysctl.c
> +++ b/xen/arch/x86/sysctl.c
> @@ -31,6 +31,29 @@
>  #include <asm/psr.h>
>  #include <asm/cpuid.h>
>  
> +const struct policy_group system_policies[] = {
> +    {
> +        &raw_cpuid_policy,
> +        &raw_msr_domain_policy,
> +        &raw_msr_vcpu_policy,
> +    },
> +    {
> +        &host_cpuid_policy,
> +        &host_msr_domain_policy,
> +        &host_msr_vcpu_policy,
> +    },
> +    {
> +        &pv_max_cpuid_policy,
> +        &pv_max_msr_domain_policy,
> +        &pv_max_msr_vcpu_policy,
> +    },
> +    {
> +        &hvm_max_cpuid_policy,
> +        &hvm_max_msr_domain_policy,
> +        &hvm_max_msr_vcpu_policy,
> +    },
> +};

This being non-static I immediately wonder how correct indexing
into this array is supposed to work. No enum or alike is being added
here.

> --- /dev/null
> +++ b/xen/include/xen/libx86/policies.h
> @@ -0,0 +1,25 @@
> +/* Common data structures and functions consumed by hypervisor and toolstack */
> +#ifndef XEN_LIBX86_POLICIES_H
> +#define XEN_LIBX86_POLICIES_H
> +
> +#include <xen/libx86/cpuid.h>
> +#include <xen/libx86/msr.h>
> +
> +struct policy_group
> +{
> +    struct cpuid_policy *cp;
> +    struct msr_domain_policy *dp;
> +    struct msr_vcpu_policy *vp;
> +};

This is sort of surprising without any libxc change here, and hence
without any use of the type in libxc, but perhaps that'll surface later
on.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 09/13] x86/sysctl: Implement XEN_SYSCTL_get_cpumsr_policy
  2018-07-03 20:55 ` [PATCH 09/13] x86/sysctl: Implement XEN_SYSCTL_get_cpumsr_policy Andrew Cooper
@ 2018-07-04  9:43   ` Jan Beulich
  2018-07-04 17:57     ` Andrew Cooper
  0 siblings, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-04  9:43 UTC (permalink / raw)
  To: Andrew Cooper, Sergey Dyasli
  Cc: Ian Jackson, Daniel de Graaf, Xen-devel, Wei Liu, Roger Pau Monne

Oh, here we go - the title doesn't suggest this is about CPUID as well.

>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> Extend the xen-cpuid utility to be able to dump the system policies.  An
> example output is:
> 
>     Xen reports there are maximum 113 leaves and 3 MSRs
>     Raw policy: 93 leaves, 3 MSRs
>      CPUID:
>       leaf     subleaf  -> eax      ebx      ecx      edx
>       00000000:ffffffff -> 0000000d:756e6547:6c65746e:49656e69

I'd like to suggest to suppress the :fffffff when there are no sub-leaves.

> @@ -377,7 +458,7 @@ int main(int argc, char **argv)
>                  if ( i == nr_features )
>                      break;
>  
> -                if ( *ptr == ':' )
> +                if ( *ptr == ':' || *ptr == '-' )

None of the other changes to this file give any hint why a dash needs
recognizing here all of the sudden. Is this a stray / leftover change?

> --- a/xen/arch/x86/sysctl.c
> +++ b/xen/arch/x86/sysctl.c
> @@ -32,22 +32,32 @@
>  #include <asm/cpuid.h>
>  
>  const struct policy_group system_policies[] = {
> -    {
> +    [ XEN_SYSCTL_cpumsr_policy_raw ] = {

Aha - this clarifies a question I had on the earlier patch. But it would
be nice if that other patch was self contained also in the way of
allowing readers to understand the intentions. And with this I now
wonder whether the pointers in struct policy_group shouldn't all
be const qualified.

> @@ -318,6 +328,74 @@ long arch_do_sysctl(
>          break;
>      }
>  
> +    case XEN_SYSCTL_get_cpumsr_policy:
> +    {
> +        const struct policy_group *group;
> +
> +        /* Bad policy index? */
> +        if ( sysctl->u.cpumsr_policy.index >= ARRAY_SIZE(system_policies) )
> +        {
> +            ret = -EINVAL;
> +            break;
> +        }
> +        group = &system_policies[sysctl->u.cpumsr_policy.index];

Isn't this introducing at least half of a Spectre v1 gadget?

> +        /* Request for maximum number of leaves/MSRs? */
> +        if ( guest_handle_is_null(sysctl->u.cpumsr_policy.cpuid_policy) )
> +        {
> +            sysctl->u.cpumsr_policy.nr_leaves = CPUID_MAX_SERIALISED_LEAVES;
> +            if ( __copy_field_to_guest(u_sysctl, sysctl,
> +                                       u.cpumsr_policy.nr_leaves) )
> +            {
> +                ret = -EFAULT;
> +                break;
> +            }
> +        }
> +        if ( guest_handle_is_null(sysctl->u.cpumsr_policy.msr_policy) )
> +        {
> +            sysctl->u.cpumsr_policy.nr_msrs = MSR_MAX_SERIALISED_ENTRIES;
> +            if ( __copy_field_to_guest(u_sysctl, sysctl,
> +                                       u.cpumsr_policy.nr_msrs) )
> +            {
> +                ret = -EFAULT;
> +                break;
> +            }
> +        }
> +
> +        /* Serialise the information the caller wants. */
> +        if ( !guest_handle_is_null(sysctl->u.cpumsr_policy.cpuid_policy) )
> +        {
> +            if ( (ret = x86_cpuid_copy_to_buffer(
> +                      group->cp,
> +                      sysctl->u.cpumsr_policy.cpuid_policy,
> +                      &sysctl->u.cpumsr_policy.nr_leaves)) )
> +                break;

Coming back to an earlier question, I realize the null handle logic
above is supposed to allow sizing the buffers, but I think it would
be better to allow single invocations to generally work, making a
second invocation necessary just as a fallback. IOW I think the
code here wants to return to the caller the required number of
slots in case of -ENOBUFS. And it should the also ...

> +            if ( __copy_field_to_guest(u_sysctl, sysctl,
> +                                       u.cpumsr_policy.nr_leaves)  )
> +            {
> +                ret = -EFAULT;
> +                break;
> +            }
> +        }
> +        if ( !guest_handle_is_null(sysctl->u.cpumsr_policy.msr_policy) )
> +        {
> +            if ( (ret = x86_msr_copy_to_buffer(
> +                      group->dp, group->vp,
> +                      sysctl->u.cpumsr_policy.msr_policy,
> +                      &sysctl->u.cpumsr_policy.nr_msrs)) )
> +                break;

... be allowed to reach here despite the earlier error.

> --- a/xen/include/public/sysctl.h
> +++ b/xen/include/public/sysctl.h
> @@ -1063,6 +1063,43 @@ struct xen_sysctl_set_parameter {
>      uint16_t pad[3];                        /* IN: MUST be zero. */
>  };
>  
> +#if defined(__i386__) || defined(__x86_64__)
> +/*
> + * XEN_SYSCTL_get_cpumsr_policy (x86 specific)

Perhaps express the "x86 specific" also in the opcode name? And make
more obvious that this is about CPUID and MSRs at the same time? E.g.
XEN_SYSCTL_x86_get_cpuid_msr_policy?

I'm sure you have reasons to munge it all into a single operation.

> + * Return information about CPUID and MSR policies available on this host.
> + *  -       Raw: The real H/W values.
> + *  -      Host: The values Xen is using, (after command line overrides, etc).
> + *  -     Max_*: Maximum set of features a PV or HVM guest can use.  Includes
> + *               experimental features outside of security support.
> + *  - Default_*: Default set of features a PV or HVM guest can use.  This is
> + *               the security supported set.
> + */
> +struct xen_sysctl_cpumsr_policy {
> +#define XEN_SYSCTL_cpumsr_policy_raw          0
> +#define XEN_SYSCTL_cpumsr_policy_host         1
> +#define XEN_SYSCTL_cpumsr_policy_pv_max       2
> +#define XEN_SYSCTL_cpumsr_policy_hvm_max      3
> +#define XEN_SYSCTL_cpumsr_policy_pv_default   4
> +#define XEN_SYSCTL_cpumsr_policy_hvm_default  5
> +    uint32_t index;       /* IN: Which policy to query? */
> +    uint32_t nr_leaves;   /* IN/OUT: Number of leaves in/written to
> +                           * 'cpuid_policy', or the maximum number of leaves if
> +                           * any of the guest handles is NULL.
> +                           * NB. All policies come from the same space,
> +                           * so have the same maximum length. */
> +    uint32_t nr_msrs;     /* IN/OUT: Number of MSRs in/written to
> +                           * 'msr_domain_policy', or the maximum number of MSRs
> +                           * if any of the guest handles is NULL.
> +                           * NB. All policies come from the same space,
> +                           * so have the same maximum length. */
> +    XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_policy; /* OUT: */

Explicit padding (checked to be zero in the handler) above here
please.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 10/13] x86/domctl: Implement XEN_DOMCTL_get_cpumsr_policy
  2018-07-03 20:55 ` [PATCH 10/13] x86/domctl: Implement XEN_DOMCTL_get_cpumsr_policy Andrew Cooper
@ 2018-07-04  9:48   ` Jan Beulich
  2018-07-05 14:23   ` Sergey Dyasli
  1 sibling, 0 replies; 67+ messages in thread
From: Jan Beulich @ 2018-07-04  9:48 UTC (permalink / raw)
  To: Andrew Cooper, Sergey Dyasli
  Cc: Ian Jackson, Daniel de Graaf, Xen-devel, Wei Liu, Roger Pau Monne

>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> From: Sergey Dyasli <sergey.dyasli@citrix.com>
> 
> This finally (after literally years of work!) marks the point where the
> toolstack can ask the hypervisor for the current CPUID configuration of a
> specific domain.
> 
> Also extend xen-cpuid's --policy mode to be able to take a domid and dump a
> specific domains CPUID and MSR policy.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>

Remarks given for the sysctl patch apply here respectively.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 11/13] libx86: Introduce a helper to deserialise a cpuid_policy object
  2018-07-03 20:55 ` [PATCH 11/13] libx86: Introduce a helper to deserialise a cpuid_policy object Andrew Cooper
@ 2018-07-04  9:49   ` Jan Beulich
  0 siblings, 0 replies; 67+ messages in thread
From: Jan Beulich @ 2018-07-04  9:49 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Xen-devel, Wei Liu, Ian Jackson, Roger Pau Monne

>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> @@ -47,6 +48,17 @@ static inline bool test_bit(unsigned int bit, const void *vaddr)
>      0;                                                  \
>  })
>  
> +/* memcpy(), but with copy_from_guest_offset()'s API */
> +#define copy_from_buffer_offset(dst, src, index, nr) ({ \
> +    const typeof(*(dst)) *s = (src);                    \
> +    unsigned int i;                                     \
> +                                                        \
> +    for ( i = 0; i < (nr); i++ )                        \
> +        (dst)[i] = s[(index) + i];                      \
> +                                                        \
> +    0;                                                  \
> +})

Again the question on whether multiple evaluation of macro arguments
would better be avoided here.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 13/13] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy
  2018-07-03 20:55 ` [PATCH 13/13] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy Andrew Cooper
@ 2018-07-04 10:16   ` Jan Beulich
  2018-07-04 18:47     ` Andrew Cooper
  2018-07-04 10:18   ` Wei Liu
  1 sibling, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-04 10:16 UTC (permalink / raw)
  To: Andrew Cooper, Sergey Dyasli
  Cc: Ian Jackson, Daniel de Graaf, Xen-devel, Wei Liu, Roger Pau Monne

>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> From: Sergey Dyasli <sergey.dyasli@citrix.com>
> 
> This hypercall allows the toolstack to present one combined CPUID and MSR
> policy for a domain, which can be audited in one go by Xen, which is necessary
> for correctness of the auditing.
> 
> A stub x86_policies_are_compatible() function is introduced, although at
> present it will always fail the hypercall.
> 
> The hypercall ABI allows for update of individual CPUID or MSR entries, so
> begins by duplicating the existing policy (for which a helper is introduced),
> merging the toolstack data, then checking compatibility of the result.

This reads to me as if it was fine for the tool stack to supply only partial
data (or else there would be no need to merge anything). What's the
thinking behind this, rather than requiring complete sets of data to be
supplied?

> One awkard corner case is re-deserialising of the vcpu msrs.  The correct fix
> would be to allocate a buffer, copy the MSRs list, then deserialise from that,
> but trips the bounds checks in the copy_from_guest() helpers.  The compat XLAT
> are would work, but would require that we allocate it even for 64bit PV
> guests.



> --- a/xen/arch/x86/domctl.c
> +++ b/xen/arch/x86/domctl.c
> @@ -330,6 +330,71 @@ static int update_domain_cpuid_info(struct domain *d,
>      return 0;
>  }
>  
> +static int update_domain_cpumsr_policy(struct domain *d,
> +                                       xen_domctl_cpumsr_policy_t *xdpc)
> +{
> +    struct policy_group new = {};
> +    const struct policy_group *sys = is_pv_domain(d)
> +        ? &system_policies[XEN_SYSCTL_cpumsr_policy_pv_max]
> +        : &system_policies[XEN_SYSCTL_cpumsr_policy_hvm_max];
> +    struct vcpu *v = d->vcpu[0];
> +    int ret = -ENOMEM;
> +
> +    /* Initialise some help identifying auditing errors. */
> +    xdpc->err_leaf = xdpc->err_subleaf = XEN_CPUID_NO_SUBLEAF;
> +    xdpc->err_msr_idx = ~0;

I'm having trouble extracting information from the comment.

> +    /* Start with existing domain's policies */
> +    if ( !(new.cp = xmemdup(d->arch.cpuid)) ||
> +         !(new.dp = xmemdup(d->arch.msr)) ||
> +         !(new.vp = xmemdup(v->arch.msr)) )
> +        goto out;
> +
> +    /* Merge the toolstack provided data. */
> +    if ( (ret = x86_cpuid_copy_from_buffer(
> +              new.cp, xdpc->cpuid_policy, xdpc->nr_leaves,
> +              &xdpc->err_leaf, &xdpc->err_subleaf)) )
> +        goto out;
> +
> +    if ( (ret = x86_msr_copy_from_buffer(
> +              new.dp, new.vp,
> +              xdpc->msr_policy, xdpc->nr_msrs, &xdpc->err_msr_idx)) )
> +        goto out;
> +
> +    /* Audit the combined dataset. */
> +    ret = x86_policies_are_compatible(sys, &new);
> +    if ( ret )
> +        goto out;

I'm afraid I don't follow - where's the merging? All you do is copy the
first so many entries coming from libxc, and using the later so many
entries from the previous policies. How's that going to provide a
complete set, rather than e.g. some duplicate entries and some
missing ones?

> +    /*
> +     * Audit was successful.  Replace existing policies, leaving the old
> +     * policies to be freed.
> +     */
> +    SWAP(new.cp, d->arch.cpuid);
> +    SWAP(new.dp, d->arch.msr);
> +    SWAP(new.vp, v->arch.msr);
> +
> +    /* Merge the (now audited) vCPU MSRs into every other msr_vcpu_policy. */
> +    for ( ; v; v = v->next_in_list )

This open-coded almost-for_each_domain() doesn't look very nice.

> +    {
> +        /* XXX - Figure out how to avoid a TOCTOU race here.  XLAT area? */
> +        if ( (ret = x86_msr_copy_from_buffer(
> +                  NULL, v->arch.msr, xdpc->msr_policy, xdpc->nr_msrs, NULL)) )

Why can't you go from vCPU 0's v->arch.msr here, which is the copied-in
(and sanitized) representation already? Also, is it really a good idea to
assume all vCPU-s have the same policies?

> @@ -1570,6 +1635,28 @@ long arch_do_domctl(
>          domain_unpause(d);
>          break;
>  
> +    case XEN_DOMCTL_set_cpumsr_policy:
> +        if ( d == currd ||       /* no domain_pause() */
> +             d->max_vcpus == 0 ) /* No vcpus yet. */
> +        {
> +            ret = -EINVAL;
> +            break;
> +        }
> +
> +        domain_pause(d);
> +
> +        if ( d->creation_finished )
> +            ret = -EEXIST; /* No changing once the domain is running. */
> +        else
> +        {
> +            ret = update_domain_cpumsr_policy(d, &domctl->u.cpumsr_policy);
> +            if ( !ret ) /* Copy domctl->u.cpumsr_policy.err_* to guest. */
> +                copyback = true;

x86_cpuid_copy_from_buffer(), for example, sets the err_ fields
only when returning -ERANGE. Is the if() condition inverted?

> --- a/xen/include/public/domctl.h
> +++ b/xen/include/public/domctl.h
> @@ -648,6 +648,12 @@ struct xen_domctl_cpumsr_policy {
>                           * 'msr_domain_policy' */
>      XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_policy; /* IN/OUT: */
>      XEN_GUEST_HANDLE_64(xen_msr_entry_t) msr_policy;    /* IN/OUT: */
> +    uint32_t err_leaf, err_subleaf; /* OUT, set_policy only.  If not ~0,
> +                                     * indicates the leaf/subleaf which
> +                                     * auditing objected to. */
> +    uint32_t err_msr_idx;           /* OUT, set_policy only.  If not ~0,
> +                                     * indicates the MSR idx which
> +                                     * auditing objected to. */

Explicit padding again please, with the handler checking it to be
zero.

> --- a/xen/include/xen/xmalloc.h
> +++ b/xen/include/xen/xmalloc.h
> @@ -13,6 +13,13 @@
>  #define xmalloc(_type) ((_type *)_xmalloc(sizeof(_type), __alignof__(_type)))
>  #define xzalloc(_type) ((_type *)_xzalloc(sizeof(_type), __alignof__(_type)))
>  
> +/* Allocate space for a typed object and copy an existing instance. */
> +#define xmemdup(ptr)                                    \
> +    ({  typeof(*ptr) *n_ = xmalloc(typeof(*ptr));       \
> +        if ( n_ )                                       \
> +            memcpy(n_, ptr, sizeof(*ptr));              \
> +        n_; })

Would be nice if this could handle input pointers to const-qualified types.
I vaguely recall having seen a solution to this recently, but I don't recall
where that was or how it looked like. Until then, may I suggest to use
void * instead, despite this opening the risk of type incompatibilities?

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 13/13] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy
  2018-07-03 20:55 ` [PATCH 13/13] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy Andrew Cooper
  2018-07-04 10:16   ` Jan Beulich
@ 2018-07-04 10:18   ` Wei Liu
  2018-07-04 10:33     ` Andrew Cooper
  1 sibling, 1 reply; 67+ messages in thread
From: Wei Liu @ 2018-07-04 10:18 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Jan Beulich,
	Daniel De Graaf, Roger Pau Monné

On Tue, Jul 03, 2018 at 09:55:26PM +0100, Andrew Cooper wrote:
> From: Sergey Dyasli <sergey.dyasli@citrix.com>
> 
> This hypercall allows the toolstack to present one combined CPUID and MSR
> policy for a domain, which can be audited in one go by Xen, which is necessary
> for correctness of the auditing.
> 
> A stub x86_policies_are_compatible() function is introduced, although at
> present it will always fail the hypercall.
> 
> The hypercall ABI allows for update of individual CPUID or MSR entries, so
> begins by duplicating the existing policy (for which a helper is introduced),
> merging the toolstack data, then checking compatibility of the result.
> 
> The system PV/HVM max policy is used for the compatiblity check.
> 
> Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> ---
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
> CC: Wei Liu <wei.liu2@citrix.com>
> CC: Roger Pau Monné <roger.pau@citrix.com>
> CC: Sergey Dyasli <sergey.dyasli@citrix.com>
> CC: Daniel De Graaf <dgdegra@tycho.nsa.gov>
> 
> One awkard corner case is re-deserialising of the vcpu msrs.  The correct fix
> would be to allocate a buffer, copy the MSRs list, then deserialise from that,
> but trips the bounds checks in the copy_from_guest() helpers.  The compat XLAT
> are would work, but would require that we allocate it even for 64bit PV
> guests.

I'm not sure I follow this. The issue isn't obvious from looking at the
code.

> ---
> +    /* Merge the (now audited) vCPU MSRs into every other msr_vcpu_policy. */
> +    for ( ; v; v = v->next_in_list )
> +    {
> +        /* XXX - Figure out how to avoid a TOCTOU race here.  XLAT area? */

What is the TOCTOU race here? 

Wei.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 13/13] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy
  2018-07-04 10:18   ` Wei Liu
@ 2018-07-04 10:33     ` Andrew Cooper
  0 siblings, 0 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-04 10:33 UTC (permalink / raw)
  To: Wei Liu
  Cc: Sergey Dyasli, Ian Jackson, Xen-devel, Jan Beulich,
	Daniel De Graaf, Roger Pau Monné

On 04/07/18 11:18, Wei Liu wrote:
> On Tue, Jul 03, 2018 at 09:55:26PM +0100, Andrew Cooper wrote:
>> From: Sergey Dyasli <sergey.dyasli@citrix.com>
>>
>> This hypercall allows the toolstack to present one combined CPUID and MSR
>> policy for a domain, which can be audited in one go by Xen, which is necessary
>> for correctness of the auditing.
>>
>> A stub x86_policies_are_compatible() function is introduced, although at
>> present it will always fail the hypercall.
>>
>> The hypercall ABI allows for update of individual CPUID or MSR entries, so
>> begins by duplicating the existing policy (for which a helper is introduced),
>> merging the toolstack data, then checking compatibility of the result.
>>
>> The system PV/HVM max policy is used for the compatiblity check.
>>
>> Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
>> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
>> ---
>> CC: Jan Beulich <JBeulich@suse.com>
>> CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
>> CC: Wei Liu <wei.liu2@citrix.com>
>> CC: Roger Pau Monné <roger.pau@citrix.com>
>> CC: Sergey Dyasli <sergey.dyasli@citrix.com>
>> CC: Daniel De Graaf <dgdegra@tycho.nsa.gov>
>>
>> One awkard corner case is re-deserialising of the vcpu msrs.  The correct fix
>> would be to allocate a buffer, copy the MSRs list, then deserialise from that,
>> but trips the bounds checks in the copy_from_guest() helpers.  The compat XLAT
>> are would work, but would require that we allocate it even for 64bit PV
>> guests.
> I'm not sure I follow this. The issue isn't obvious from looking at the
> code.
>
>> ---
>> +    /* Merge the (now audited) vCPU MSRs into every other msr_vcpu_policy. */
>> +    for ( ; v; v = v->next_in_list )
>> +    {
>> +        /* XXX - Figure out how to avoid a TOCTOU race here.  XLAT area? */
> What is the TOCTOU race here?

In the lines you snipped...

>
>> +        if ( (ret = x86_msr_copy_from_buffer(
>> +                  NULL, v->arch.msr, xdpc->msr_policy, xdpc->nr_msrs, NULL)) )
>

xdpc->msr_policy is a pointer into toolstack userspace, which we re-read.

The problem is that we can't copy this up front to a hypervisor buffer
(which would avoid the TOCTOU race), without tripping the access_ok()
check in copy_from_guest().

However, Jan and Sergey (IRL) have suggested an alternative approach
which will work for now.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 00/13] x86: CPUID and MSR policy marshalling support
  2018-07-04  8:17 ` [PATCH 00/13] x86: CPUID and MSR policy marshalling support Jan Beulich
@ 2018-07-04 10:40   ` Andrew Cooper
  2018-07-04 10:44     ` Jan Beulich
  0 siblings, 1 reply; 67+ messages in thread
From: Andrew Cooper @ 2018-07-04 10:40 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Daniel de Graaf,
	Roger Pau Monne

On 04/07/18 09:17, Jan Beulich wrote:
>>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
>> Some open questions:
>>
>>   * The position of libx86 in the source tree.  It probably doesn't want to
>>     live in its current location.
> So did you intentionally decide against ...
>
>>  .gitignore                                  |   2 +-
>>  tools/include/Makefile                      |  15 ++
>>  tools/libxc/Makefile                        |  14 +-
>>  tools/libxc/include/xenctrl.h               |  15 +-
>>  tools/libxc/xc_cpuid_x86.c                  | 163 +++++++++++++++++---
>>  tools/misc/xen-cpuid.c                      | 135 +++++++++++++++-
>>  tools/tests/x86_emulator/x86-emulate.h      |   2 +
>>  xen/arch/x86/cpu/common.c                   |   2 +-
>>  xen/arch/x86/cpuid.c                        |  32 +---
>>  xen/arch/x86/domctl.c                       | 133 ++++++++++++++++
>>  xen/arch/x86/msr.c                          |   4 +-
>>  xen/arch/x86/sysctl.c                       | 101 ++++++++++++
>>  xen/arch/x86/x86_emulate/x86_emulate.h      |   7 +-
>>  xen/common/Makefile                         |   1 +
>>  xen/common/libx86/Makefile                  |   3 +
>>  xen/common/libx86/cpuid.c                   | 226 +++++++++++++++++++++++++++
>>  xen/common/libx86/libx86-private.h          |  74 +++++++++
>>  xen/common/libx86/msr.c                     | 134 ++++++++++++++++
>>  xen/common/libx86/policies.c                |  19 +++
> xen/lib/x86/... or lib/x86/... here and ...
>
>>  xen/include/Makefile                        |   6 +-
>>  xen/include/asm-x86/cpufeatures.h           |   2 +-
>>  xen/include/asm-x86/cpuid.h                 | 228 +---------------------------
>>  xen/include/asm-x86/msr.h                   |  65 ++------
>>  xen/include/public/arch-x86/xen.h           |  18 +++
>>  xen/include/public/domctl.h                 |  25 +++
>>  xen/include/public/sysctl.h                 |  41 +++++
>>  xen/include/{asm-x86 => xen/libx86}/cpuid.h | 103 +++++--------
>>  xen/include/xen/libx86/msr.h                |  78 ++++++++++
>>  xen/include/xen/libx86/policies.h           |  35 +++++
> xen/include/lib/x86/... or include/lib/x86/... here, as suggested
> on irc?

I tried, got stuck, then decided it would be better use of time to post
a v1 for review.

Once a general decision has been made, I'll try to remember/work out how
to use `git filter-branch` without it trying to delete my entire history.

> Personally I'd favor the top level variants, as that makes
> sufficiently clear that the code is neither specific to the hypervisor
> nor specific to the tools.

That's the concern I've got with the top level variant.  I view this as
hypervisor code which we also want to use in libxc, rather than
specifically separate code.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 00/13] x86: CPUID and MSR policy marshalling support
  2018-07-04 10:40   ` Andrew Cooper
@ 2018-07-04 10:44     ` Jan Beulich
  0 siblings, 0 replies; 67+ messages in thread
From: Jan Beulich @ 2018-07-04 10:44 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Daniel de Graaf,
	Roger Pau Monne

>>> On 04.07.18 at 12:40, <andrew.cooper3@citrix.com> wrote:
> On 04/07/18 09:17, Jan Beulich wrote:
>> Personally I'd favor the top level variants, as that makes
>> sufficiently clear that the code is neither specific to the hypervisor
>> nor specific to the tools.
> 
> That's the concern I've got with the top level variant.  I view this as
> hypervisor code which we also want to use in libxc, rather than
> specifically separate code.

But isn't the nature of library code to be used in different environments?
Hence why would you want this specifically qualified as hypervisor code?

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 01/13] libx86: Introduce libx86/cpuid.h
  2018-07-04  8:21   ` Jan Beulich
@ 2018-07-04 12:03     ` Andrew Cooper
  2018-07-04 13:57       ` Jan Beulich
  0 siblings, 1 reply; 67+ messages in thread
From: Andrew Cooper @ 2018-07-04 12:03 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Sergey Dyasli, Xen-devel, Wei Liu, Ian Jackson, Roger Pau Monne

On 04/07/18 09:21, Jan Beulich wrote:
>>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
>> --- a/tools/include/Makefile
>> +++ b/tools/include/Makefile
>> @@ -21,6 +21,9 @@ xen/.dir:
>>  	ln -sf $(addprefix $(XEN_ROOT)/xen/include/xen/,libelf.h elfstructs.h) xen/libelf/
>>  	ln -s ../xen-foreign xen/foreign
>>  	ln -sf $(XEN_ROOT)/xen/include/acpi acpi
>> +ifeq ($(CONFIG_X86),y)
>> +	ln -sf $(XEN_ROOT)/xen/include/xen/libx86 xen/libx86
>> +endif
> Why not set the include path suitably?

Because this is how everything else is currently done.  If we want to
change how tools get their hypervisor header files, that should be
independent work.

> And otherwise, what harm would there be installing the link also when targeting ARM?

I'm fairly sure the ARM folk would object to having libx86 linked into
their tools.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 01/13] libx86: Introduce libx86/cpuid.h
  2018-07-04 12:03     ` Andrew Cooper
@ 2018-07-04 13:57       ` Jan Beulich
  2018-07-06  1:35         ` Doug Goldstein
  0 siblings, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-04 13:57 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Xen-devel, Wei Liu, Ian Jackson, Roger Pau Monne

>>> On 04.07.18 at 14:03, <andrew.cooper3@citrix.com> wrote:
> On 04/07/18 09:21, Jan Beulich wrote:
>>>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
>>> --- a/tools/include/Makefile
>>> +++ b/tools/include/Makefile
>>> @@ -21,6 +21,9 @@ xen/.dir:
>>>  	ln -sf $(addprefix $(XEN_ROOT)/xen/include/xen/,libelf.h elfstructs.h) xen/libelf/
>>>  	ln -s ../xen-foreign xen/foreign
>>>  	ln -sf $(XEN_ROOT)/xen/include/acpi acpi
>>> +ifeq ($(CONFIG_X86),y)
>>> +	ln -sf $(XEN_ROOT)/xen/include/xen/libx86 xen/libx86
>>> +endif
>> Why not set the include path suitably?
> 
> Because this is how everything else is currently done.  If we want to
> change how tools get their hypervisor header files, that should be
> independent work.

How this gets done here has no direct implications on pre-existing
mechanisms.

>> And otherwise, what harm would there be installing the link also when 
> targeting ARM?
> 
> I'm fairly sure the ARM folk would object to having libx86 linked into
> their tools.

"Linked into" is ambiguous in this context - the presence of the headers
does - afaict - not imply any code to appear in an ARM build of the tools.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 04/13] libx86: introduce a libx86 shared library
  2018-07-04  8:42   ` Jan Beulich
@ 2018-07-04 15:48     ` Andrew Cooper
  0 siblings, 0 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-04 15:48 UTC (permalink / raw)
  To: Jan Beulich, Roger Pau Monne
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel

On 04/07/18 09:42, Jan Beulich wrote:
>
>> --- /dev/null
>> +++ b/xen/common/libx86/libx86-private.h
>> @@ -0,0 +1,42 @@
>> +#ifndef XEN_LIBX86_PRIVATE_H
>> +#define XEN_LIBX86_PRIVATE_H
>> +
>> +#ifdef __XEN__
>> +
>> +#include <xen/bitops.h>
>> +#include <xen/kernel.h>
>> +#include <xen/lib.h>
>> +#include <xen/types.h>
>> +
>> +#else
>> +
>> +#include <inttypes.h>
>> +#include <stdbool.h>
>> +#include <stddef.h>
>> +
>> +#include <xen-tools/libs.h>
>> +
>> +#define MAX(x, y) ((x) > (y) ? (x) : (y))
>> +
>> +#define ARRAY_SIZE(x) (sizeof x / sizeof *x)
>> +
>> +static inline bool test_bit(unsigned int bit, const void *vaddr)
>> +{
>> +    const char *addr = vaddr;
>> +
>> +    return addr[bit / 8] & (1u << (bit % 8));
>> +}
>> +
>> +#endif /* __XEN__ */
>> +
>> +#endif /* XEN_LIBX86_PRIVATE_H */
> Did you consider making this x86-independent but still shared?
> None of the above is x86-specific. libelf could then possibly use
> this too, for exampled.
>
> Also I think we pretty consistently use sizeof(x), not sizeof x, so
> I'd like to ask that ARRAY_SIZE() be adjusted accordingly.

In response to several questions across the series, all of the common
macros now live in <xen-tools/libs.h> alongside the already-common
BUILD_BUG_ON() implementation.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
  2018-07-04  8:51     ` Jan Beulich
@ 2018-07-04 16:23       ` Andrew Cooper
  2018-07-05  8:09         ` Wei Liu
  2018-07-05  8:40         ` Jan Beulich
  0 siblings, 2 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-04 16:23 UTC (permalink / raw)
  To: Jan Beulich, Wei Liu
  Cc: Sergey Dyasli, Xen-devel, Ian Jackson, Roger Pau Monne

On 04/07/18 09:51, Jan Beulich wrote:
>>>> On 04.07.18 at 10:42, <wei.liu2@citrix.com> wrote:
>> On Tue, Jul 03, 2018 at 09:55:19PM +0100, Andrew Cooper wrote:
>>> --- a/xen/include/public/arch-x86/xen.h
>>> +++ b/xen/include/public/arch-x86/xen.h
>>> @@ -314,6 +314,17 @@ struct xen_arch_domainconfig {
>>>  #define XEN_ACPI_GPE0_CPUHP_BIT      2
>>>  #endif
>>>  
>>> +/*
>>> + * Representations of architectural CPUID information.  Used as the
>>> + * serialised version of Xen's internal representation.
>>> + */
>>> +typedef struct xen_cpuid_leaf {
>>> +#define XEN_CPUID_NO_SUBLEAF 0xffffffffu
>>> +    uint32_t leaf, subleaf;
>>> +    uint32_t a, b, c, d;
>>> +} xen_cpuid_leaf_t;
>>> +DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t);
>>> +
>> Is putting this in public header while leaving
>> CPUID_MAX_SERIALISED_LEAVES in a private header useful?
>>
>> How does an external user know how big a buffer it needs to provide to
>> accommodate the return structure?
> Yeah, this is indeed hard to tell from this patch alone. And going
> over the titles of the remainder of the series it's also not clear
> where a use of this structure in a domctl/sysctl would appear.

An array of (some number of) xen_cpuid_leaf_t objects is the externally
visible representation of the policy, which is why this definition is
externally visible.

Content of this nature will (eventually) exist in the migration stream,
and it is also the interface by which toolstacks (libxl and Xapi) can
make under-specified modifications to the policies.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
  2018-07-04  9:01   ` Jan Beulich
@ 2018-07-04 16:46     ` Andrew Cooper
  2018-07-05  8:11       ` Wei Liu
  2018-07-05  8:46       ` Jan Beulich
  0 siblings, 2 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-04 16:46 UTC (permalink / raw)
  To: Jan Beulich, Roger Pau Monne
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel

On 04/07/18 10:01, Jan Beulich wrote:
>>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
>> --- a/xen/common/libx86/cpuid.c
>> +++ b/xen/common/libx86/cpuid.c
>> @@ -34,6 +34,100 @@ const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature)
>>  }
>>  
>>  /*
>> + * Copy a single cpuid_leaf into a provided xen_cpuid_leaf_t buffer,
>> + * performing boundary checking against the buffer size.
>> + */
>> +static int copy_leaf_to_buffer(uint32_t leaf, uint32_t subleaf,
>> +                               const struct cpuid_leaf *data,
>> +                               cpuid_leaf_buffer_t leaves,
>> +                               uint32_t *curr_entry, const uint32_t nr_entries)
>> +{
>> +    const xen_cpuid_leaf_t val = {
>> +        leaf, subleaf, data->a, data->b, data->c, data->d,
>> +    };
>> +
>> +    if ( *curr_entry == nr_entries )
>> +        return -ENOBUFS;
>> +
>> +    if ( copy_to_buffer_offset(leaves, *curr_entry, &val, 1) )
>> +        return -EFAULT;
>> +
>> +    ++*curr_entry;
> Following on from what Wei has said - you don't mean to have a way
> here then to indicate to a higher up caller how many slots would have
> been needed?

I don't understand your query.  An individual build has a compile-time
static maximum number of leaves, and this number can be obtained in the
usual way by making a hypercall with a NULL guest handle.

The external representation must not encode this number, as it will
change build to build, hardware to hardware, and in such times as we
gain a load of new features in microcode.

>
>> +int x86_cpuid_copy_to_buffer(const struct cpuid_policy *p,
>> +                             cpuid_leaf_buffer_t leaves,
>> +                             uint32_t *nr_entries_p)
>> +{
>> +    const uint32_t nr_entries = *nr_entries_p;
>> +    uint32_t curr_entry = 0, leaf, subleaf;
>> +
>> +#define COPY_LEAF(l, s, data)                                       \
>> +    ({  int ret;                                                    \
>> +        if ( (ret = copy_leaf_to_buffer(                            \
>> +                  l, s, data, leaves, &curr_entry, nr_entries)) )   \
>> +            return ret;                                             \
>> +    })
>> +
>> +    /* Basic leaves. */
>> +    for ( leaf = 0; leaf <= MIN(p->basic.max_leaf,
>> +                                ARRAY_SIZE(p->basic.raw) - 1); ++leaf )
>> +    {
>> +        switch ( leaf )
>> +        {
>> +        case 0x4:
>> +            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->cache.raw); ++subleaf )
>> +                COPY_LEAF(leaf, subleaf, &p->cache.raw[subleaf]);
>> +            break;
>> +
>> +        case 0x7:
>> +            for ( subleaf = 0;
>> +                  subleaf <= MIN(p->feat.max_subleaf,
>> +                                 ARRAY_SIZE(p->feat.raw) - 1); ++subleaf )
>> +                COPY_LEAF(leaf, subleaf, &p->feat.raw[subleaf]);
>> +            break;
>> +
>> +        case 0xb:
>> +            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->topo.raw); ++subleaf )
>> +                COPY_LEAF(leaf, subleaf, &p->topo.raw[subleaf]);
>> +            break;
>> +
>> +        case 0xd:
>> +            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->xstate.raw); ++subleaf )
>> +                COPY_LEAF(leaf, subleaf, &p->xstate.raw[subleaf]);
>> +            break;
>> +
>> +        default:
>> +            COPY_LEAF(leaf, XEN_CPUID_NO_SUBLEAF, &p->basic.raw[leaf]);
>> +            break;
>> +        }
>> +    }
>> +
>> +    COPY_LEAF(0x40000000, XEN_CPUID_NO_SUBLEAF,
>> +              &(struct cpuid_leaf){ p->hv_limit });
>> +    COPY_LEAF(0x40000100, XEN_CPUID_NO_SUBLEAF,
>> +              &(struct cpuid_leaf){ p->hv2_limit });
> Is it a good idea to produce wrong (zero) EBX, ECX, and EDX values here?

The handling of these leaves currently problematic, and this patch is
bug-compatible with how DOMCTL_set_cpuid currently behaves (See
update_domain_cpuid_info()).

Annoyingly, I need this marshalling series implemented before I can fix
the hypervisor leaves to use the "new" CPUID infrastructure; the main
complication being because of the dynamic location of the Xen leaves.

Eventually, the interface will be that Xen leaves live at 0x40000000 and
the toolstack can manipulate a subset of the information by providing
leaves in the usual manor.  To enable viridian, the toolstack writes
HyperV's signature at 0x40000000, and Xen's at 0x40000100.  This also
allows for a mechanism to hide the Xen CPUID leaves by writing a 0 max leaf.

Amongst other things, this will allow sensible control of the Viridian
features without having to squeeze more bits into the HVMPARAM.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 07/13] libx86: Introduce a helper to serialise msr_{domain, vcpu}_policy objects
  2018-07-04  9:16   ` Jan Beulich
@ 2018-07-04 16:56     ` Andrew Cooper
  2018-07-05  8:49       ` Jan Beulich
  0 siblings, 1 reply; 67+ messages in thread
From: Andrew Cooper @ 2018-07-04 16:56 UTC (permalink / raw)
  To: Jan Beulich, Roger Pau Monne
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel

On 04/07/18 10:16, Jan Beulich wrote:
>
>> @@ -325,6 +325,13 @@ typedef struct xen_cpuid_leaf {
>>  } xen_cpuid_leaf_t;
>>  DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t);
>>  
>> +typedef struct xen_msr_entry {
>> +    uint32_t idx;
>> +    uint32_t flags; /* Reserved MBZ. */
> ... it remains unclear in this patch whose responsibility it is to clear this
> field. I wonder whether copy_msr_to_buffer() should make sure of this.

copy_msr_to_buffer() does explicitly zero this field.

> +    const xen_msr_entry_t ent = { .idx = idx, .val = val };

guarantees that the flags field is 0.

FWIW, an earlier version of this series has an AVAILABLE bit specified
in the flags field, but attempting to the marshalling code work sensibly
is why I eventually decided to write c/s 2df1d2ba132ff "x86/msr: Drop
{MISC_ENABLES,PLATFORM_INFO}.available" as an alternative fix for the
problem.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 08/13] x86: Collect policies together into groups
  2018-07-04  9:22   ` Jan Beulich
@ 2018-07-04 17:15     ` Andrew Cooper
  2018-07-05  8:54       ` Jan Beulich
  0 siblings, 1 reply; 67+ messages in thread
From: Andrew Cooper @ 2018-07-04 17:15 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Sergey Dyasli, Xen-devel, Wei Liu, Ian Jackson, Roger Pau Monne

On 04/07/18 10:22, Jan Beulich wrote:
>>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
>> This is mainly prep work for the following patch, but this specific
>> abstraction is also specifically useful for the future auditing logic.
>>
>> Not all of msr_vcpu_policy will be interesting from a domain building
>> perspective, but some soon-to-appear fields will be (SGX Launch Hash
>> specifically).  The exact split of MSRs between domain and vcpu policies is
>> internal to Xen and liable to change moving forwards, so treat the two
>> structures consistently from the start to avoid problems in the future.
> I hope the utility of this grouping will become evident in later
> patches.

Probably moreso in the followup series with the auditing/subset logic,
but patch 13 does provide the first aspect.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 09/13] x86/sysctl: Implement XEN_SYSCTL_get_cpumsr_policy
  2018-07-04  9:43   ` Jan Beulich
@ 2018-07-04 17:57     ` Andrew Cooper
  2018-07-05  9:08       ` Jan Beulich
  0 siblings, 1 reply; 67+ messages in thread
From: Andrew Cooper @ 2018-07-04 17:57 UTC (permalink / raw)
  To: Jan Beulich, Sergey Dyasli
  Cc: Ian Jackson, Daniel de Graaf, Xen-devel, Wei Liu, Roger Pau Monne

On 04/07/18 10:43, Jan Beulich wrote:
> Oh, here we go - the title doesn't suggest this is about CPUID as well.
>
>>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
>> Extend the xen-cpuid utility to be able to dump the system policies.  An
>> example output is:
>>
>>     Xen reports there are maximum 113 leaves and 3 MSRs
>>     Raw policy: 93 leaves, 3 MSRs
>>      CPUID:
>>       leaf     subleaf  -> eax      ebx      ecx      edx
>>       00000000:ffffffff -> 0000000d:756e6547:6c65746e:49656e69
> I'd like to suggest to suppress the :fffffff when there are no sub-leaves.

This is a developer tool, rather than a user tool, and it is dumping raw
data.

If there were an easy formatter way of expressing "uint32_t or blank"
then yes, but I'm not aware of one.

>
>> @@ -377,7 +458,7 @@ int main(int argc, char **argv)
>>                  if ( i == nr_features )
>>                      break;
>>  
>> -                if ( *ptr == ':' )
>> +                if ( *ptr == ':' || *ptr == '-' )
> None of the other changes to this file give any hint why a dash needs
> recognizing here all of the sudden. Is this a stray / leftover change?

Hmm - at a guess that is a XenServer compatibility improvement, but
probably can be pulled out into a separate change.

Xapi represents feature bitmaps with dash delimiters rather than colon
delimiters, and this alters the parsing to accept both forms.

>
>> --- a/xen/arch/x86/sysctl.c
>> +++ b/xen/arch/x86/sysctl.c
>> @@ -32,22 +32,32 @@
>>  #include <asm/cpuid.h>
>>  
>>  const struct policy_group system_policies[] = {
>> -    {
>> +    [ XEN_SYSCTL_cpumsr_policy_raw ] = {
> Aha - this clarifies a question I had on the earlier patch. But it would
> be nice if that other patch was self contained also in the way of
> allowing readers to understand the intentions.

One thing I could do is introduce the XEN_SYSCTL_cpumsr_policy_* defines
in the previous patch?  I don't want to merge the two patches as that is
too many moving parts to review in a single patch.

> And with this I now
> wonder whether the pointers in struct policy_group shouldn't all
> be const qualified.

Unfortunately that doesn't work with the logic to create a policy_group
for an individual domain during audit.

>
>> @@ -318,6 +328,74 @@ long arch_do_sysctl(
>>          break;
>>      }
>>  
>> +    case XEN_SYSCTL_get_cpumsr_policy:
>> +    {
>> +        const struct policy_group *group;
>> +
>> +        /* Bad policy index? */
>> +        if ( sysctl->u.cpumsr_policy.index >= ARRAY_SIZE(system_policies) )
>> +        {
>> +            ret = -EINVAL;
>> +            break;
>> +        }
>> +        group = &system_policies[sysctl->u.cpumsr_policy.index];
> Isn't this introducing at least half of a Spectre v1 gadget?

Nope :(

It's both halves of the Spectre gadget, when you account for the
dereference when calling x86_*_copy_to_buffer() slightly lower.

I suppose we want to port the Linux array nospec lookup logic so we can
protect the clearly-visible gadgets.

>
>> +        /* Request for maximum number of leaves/MSRs? */
>> +        if ( guest_handle_is_null(sysctl->u.cpumsr_policy.cpuid_policy) )
>> +        {
>> +            sysctl->u.cpumsr_policy.nr_leaves = CPUID_MAX_SERIALISED_LEAVES;
>> +            if ( __copy_field_to_guest(u_sysctl, sysctl,
>> +                                       u.cpumsr_policy.nr_leaves) )
>> +            {
>> +                ret = -EFAULT;
>> +                break;
>> +            }
>> +        }
>> +        if ( guest_handle_is_null(sysctl->u.cpumsr_policy.msr_policy) )
>> +        {
>> +            sysctl->u.cpumsr_policy.nr_msrs = MSR_MAX_SERIALISED_ENTRIES;
>> +            if ( __copy_field_to_guest(u_sysctl, sysctl,
>> +                                       u.cpumsr_policy.nr_msrs) )
>> +            {
>> +                ret = -EFAULT;
>> +                break;
>> +            }
>> +        }
>> +
>> +        /* Serialise the information the caller wants. */
>> +        if ( !guest_handle_is_null(sysctl->u.cpumsr_policy.cpuid_policy) )
>> +        {
>> +            if ( (ret = x86_cpuid_copy_to_buffer(
>> +                      group->cp,
>> +                      sysctl->u.cpumsr_policy.cpuid_policy,
>> +                      &sysctl->u.cpumsr_policy.nr_leaves)) )
>> +                break;
> Coming back to an earlier question, I realize the null handle logic
> above is supposed to allow sizing the buffers, but I think it would
> be better to allow single invocations to generally work, making a
> second invocation necessary just as a fallback. IOW I think the
> code here wants to return to the caller the required number of
> slots in case of -ENOBUFS. And it should the also ...

I don't agree.  Whatever happens, the toolstack has to (once) make a
hypercall requesting the size of the buffers, and there is no plausible
manipulation where the toolstack would start with one sized buffer, and
dynamically size it based on -ENOBUFS.

The independent handling (e.g. only getting CPUID or MSR) is of more use
to the toolstack than having Xen try to stumble on in the face of a hard
error.

>
>> --- a/xen/include/public/sysctl.h
>> +++ b/xen/include/public/sysctl.h
>> @@ -1063,6 +1063,43 @@ struct xen_sysctl_set_parameter {
>>      uint16_t pad[3];                        /* IN: MUST be zero. */
>>  };
>>  
>> +#if defined(__i386__) || defined(__x86_64__)
>> +/*
>> + * XEN_SYSCTL_get_cpumsr_policy (x86 specific)
> Perhaps express the "x86 specific" also in the opcode name? And make
> more obvious that this is about CPUID and MSRs at the same time? E.g.
> XEN_SYSCTL_x86_get_cpuid_msr_policy?
>
> I'm sure you have reasons to munge it all into a single operation.

(Answering in reverse order)

The get operations don't strictly need to be a single operation.  The
set operation specifically must be a single operation, and the getters
have an interface to match.

As for naming, cpumsr_policy wasn't chosen by me, but I can't think of
anything better.  The code is currently consistent and, while I'm open
to a rename, it will impact large quantities of the series.

One concern I have if we end up with a new block of information.  I was
hoping for a generic name, but simply "policy" on its own is too
generic.  cpumsr is, I believe, a contraction of cpuid_msr to avoid
excessive code volume.

Suggestions welcome.

>
>> + * Return information about CPUID and MSR policies available on this host.
>> + *  -       Raw: The real H/W values.
>> + *  -      Host: The values Xen is using, (after command line overrides, etc).
>> + *  -     Max_*: Maximum set of features a PV or HVM guest can use.  Includes
>> + *               experimental features outside of security support.
>> + *  - Default_*: Default set of features a PV or HVM guest can use.  This is
>> + *               the security supported set.
>> + */
>> +struct xen_sysctl_cpumsr_policy {
>> +#define XEN_SYSCTL_cpumsr_policy_raw          0
>> +#define XEN_SYSCTL_cpumsr_policy_host         1
>> +#define XEN_SYSCTL_cpumsr_policy_pv_max       2
>> +#define XEN_SYSCTL_cpumsr_policy_hvm_max      3
>> +#define XEN_SYSCTL_cpumsr_policy_pv_default   4
>> +#define XEN_SYSCTL_cpumsr_policy_hvm_default  5
>> +    uint32_t index;       /* IN: Which policy to query? */
>> +    uint32_t nr_leaves;   /* IN/OUT: Number of leaves in/written to
>> +                           * 'cpuid_policy', or the maximum number of leaves if
>> +                           * any of the guest handles is NULL.
>> +                           * NB. All policies come from the same space,
>> +                           * so have the same maximum length. */
>> +    uint32_t nr_msrs;     /* IN/OUT: Number of MSRs in/written to
>> +                           * 'msr_domain_policy', or the maximum number of MSRs
>> +                           * if any of the guest handles is NULL.
>> +                           * NB. All policies come from the same space,
>> +                           * so have the same maximum length. */
>> +    XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_policy; /* OUT: */
> Explicit padding (checked to be zero in the handler) above here
> please.

Why?  SYSCTLs are unstable and we don't perform similar checks for other
subops.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 13/13] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy
  2018-07-04 10:16   ` Jan Beulich
@ 2018-07-04 18:47     ` Andrew Cooper
  2018-07-05  9:28       ` Jan Beulich
  0 siblings, 1 reply; 67+ messages in thread
From: Andrew Cooper @ 2018-07-04 18:47 UTC (permalink / raw)
  To: Jan Beulich, Sergey Dyasli
  Cc: Ian Jackson, Daniel de Graaf, Xen-devel, Wei Liu, Roger Pau Monne

On 04/07/18 11:16, Jan Beulich wrote:
>>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
>> From: Sergey Dyasli <sergey.dyasli@citrix.com>
>>
>> This hypercall allows the toolstack to present one combined CPUID and MSR
>> policy for a domain, which can be audited in one go by Xen, which is necessary
>> for correctness of the auditing.
>>
>> A stub x86_policies_are_compatible() function is introduced, although at
>> present it will always fail the hypercall.
>>
>> The hypercall ABI allows for update of individual CPUID or MSR entries, so
>> begins by duplicating the existing policy (for which a helper is introduced),
>> merging the toolstack data, then checking compatibility of the result.
> This reads to me as if it was fine for the tool stack to supply only partial
> data (or else there would be no need to merge anything). What's the
> thinking behind this, rather than requiring complete sets of data to be
> supplied?

Unless you have an identical build of Xen and libxc, the toolstack won't
always provide the same leaves as Xen expects.  Such a restriction would
massively hamper development.

More importantly, with the max_extd_leaf being vendor dependent (which
is data earlier in the structure), the toolstack can't reasonably create
a dataset which matches those expectations.  Also you'll get into
problems when migrating from older hosts, and when levelling a policy
down with a lower max_leaf.

The reason for having an architectural representation was deliberately
to prohibit having a hypercall which was a memcpy of an unstable
structure in the background, but with this design comes the fact that
Xen must not expect to find an exact match of data.

>
>> One awkard corner case is re-deserialising of the vcpu msrs.  The correct fix
>> would be to allocate a buffer, copy the MSRs list, then deserialise from that,
>> but trips the bounds checks in the copy_from_guest() helpers.  The compat XLAT
>> are would work, but would require that we allocate it even for 64bit PV
>> guests.
>
>
>> --- a/xen/arch/x86/domctl.c
>> +++ b/xen/arch/x86/domctl.c
>> @@ -330,6 +330,71 @@ static int update_domain_cpuid_info(struct domain *d,
>>      return 0;
>>  }
>>  
>> +static int update_domain_cpumsr_policy(struct domain *d,
>> +                                       xen_domctl_cpumsr_policy_t *xdpc)
>> +{
>> +    struct policy_group new = {};
>> +    const struct policy_group *sys = is_pv_domain(d)
>> +        ? &system_policies[XEN_SYSCTL_cpumsr_policy_pv_max]
>> +        : &system_policies[XEN_SYSCTL_cpumsr_policy_hvm_max];
>> +    struct vcpu *v = d->vcpu[0];
>> +    int ret = -ENOMEM;
>> +
>> +    /* Initialise some help identifying auditing errors. */
>> +    xdpc->err_leaf = xdpc->err_subleaf = XEN_CPUID_NO_SUBLEAF;
>> +    xdpc->err_msr_idx = ~0;
> I'm having trouble extracting information from the comment.

So am I...

These are the fields inside the domctl which try to provide some hint as
to which piece of data is problematic, rather than leaving the user with
simply "somthing is wrong".

>
>> +    /* Start with existing domain's policies */
>> +    if ( !(new.cp = xmemdup(d->arch.cpuid)) ||
>> +         !(new.dp = xmemdup(d->arch.msr)) ||
>> +         !(new.vp = xmemdup(v->arch.msr)) )
>> +        goto out;
>> +
>> +    /* Merge the toolstack provided data. */
>> +    if ( (ret = x86_cpuid_copy_from_buffer(
>> +              new.cp, xdpc->cpuid_policy, xdpc->nr_leaves,
>> +              &xdpc->err_leaf, &xdpc->err_subleaf)) )
>> +        goto out;
>> +
>> +    if ( (ret = x86_msr_copy_from_buffer(
>> +              new.dp, new.vp,
>> +              xdpc->msr_policy, xdpc->nr_msrs, &xdpc->err_msr_idx)) )
>> +        goto out;
>> +
>> +    /* Audit the combined dataset. */
>> +    ret = x86_policies_are_compatible(sys, &new);
>> +    if ( ret )
>> +        goto out;
> I'm afraid I don't follow - where's the merging? All you do is copy the
> first so many entries coming from libxc, and using the later so many
> entries from the previous policies. How's that going to provide a
> complete set, rather than e.g. some duplicate entries and some
> missing ones?

Consider the case where max_leaf is lower than Xen's maximum.  The data
provided by the toolstack can be self consistent and complete without
matching Xen's exact size of structure.

>
>> +    /*
>> +     * Audit was successful.  Replace existing policies, leaving the old
>> +     * policies to be freed.
>> +     */
>> +    SWAP(new.cp, d->arch.cpuid);
>> +    SWAP(new.dp, d->arch.msr);
>> +    SWAP(new.vp, v->arch.msr);
>> +
>> +    /* Merge the (now audited) vCPU MSRs into every other msr_vcpu_policy. */
>> +    for ( ; v; v = v->next_in_list )
> This open-coded almost-for_each_domain() doesn't look very nice.

ITYM for_each_vcpu()

And yes, but for_each_vcpu() is wrong to use here, and we don't have a
for_each_vcpu_other_than_0() helper.

>
>> +    {
>> +        /* XXX - Figure out how to avoid a TOCTOU race here.  XLAT area? */
>> +        if ( (ret = x86_msr_copy_from_buffer(
>> +                  NULL, v->arch.msr, xdpc->msr_policy, xdpc->nr_msrs, NULL)) )
> Why can't you go from vCPU 0's v->arch.msr here, which is the copied-in
> (and sanitized) representation already? Also, is it really a good idea to
> assume all vCPU-s have the same policies?

There are multiple colliding issues which lead to this code, but as
several people have pointed out, its probably over the top.

First, as to the same policy.  This hypercall can currently only be used
before the vcpu has started executing.

As such, it is setting the init state of the MSRs from the guests point
of view, and there is exactly one MSR I'm aware of which has an init
value which depends on the core (that being APIC_BASE.BSP which can
trivially be handled in Xen).  All other MSRs have identical init state
AFAICT, and I don't want to create an interface which makes it easy to
accidentally end up with wrong values.

The re-de-serialising actually came from your suggested usecase to be
able to increase the policy at runtime, .e.g. after a microcode update
and hypervisor livepatch.  In that case, a partial set doesn't want to
copy vCPU0's generally R/W MSRs over other vcpus, because that would be
a bad thing.

However, these two points aren't compatible, so if we accept the "only
before the domain has started running" aspect, then it should be safe to
copy v0's policy over all other vcpus.

Really, the problem here comes from (necessarily) how we will have to
implement SGX_LC and the fact that the LC Hash MSRs may be read-only
domain-wide state, or read-write per-vcpu state depending on a different
MSR setting (MSR_FEAT_CTRL.SGX_LC).

I was initially hoping to have only msr_domain_policy poked via this
interface, and msr_vcpu_policy poked exclusively via per-vcpu
hypercalls.  Then again, at least the complexity is visible at this
point, rather than at some point in the future when we need to try and
retrofit it.

>
>> @@ -1570,6 +1635,28 @@ long arch_do_domctl(
>>          domain_unpause(d);
>>          break;
>>  
>> +    case XEN_DOMCTL_set_cpumsr_policy:
>> +        if ( d == currd ||       /* no domain_pause() */
>> +             d->max_vcpus == 0 ) /* No vcpus yet. */
>> +        {
>> +            ret = -EINVAL;
>> +            break;
>> +        }
>> +
>> +        domain_pause(d);
>> +
>> +        if ( d->creation_finished )
>> +            ret = -EEXIST; /* No changing once the domain is running. */
>> +        else
>> +        {
>> +            ret = update_domain_cpumsr_policy(d, &domctl->u.cpumsr_policy);
>> +            if ( !ret ) /* Copy domctl->u.cpumsr_policy.err_* to guest. */
>> +                copyback = true;
> x86_cpuid_copy_from_buffer(), for example, sets the err_ fields
> only when returning -ERANGE. Is the if() condition inverted?

Oops yes.  This was part of a blanket "ret > 0" correction I needed to
do because the privcmd() ioctl interface isn't sufficiently expressive.

>
>> --- a/xen/include/public/domctl.h
>> +++ b/xen/include/public/domctl.h
>> @@ -648,6 +648,12 @@ struct xen_domctl_cpumsr_policy {
>>                           * 'msr_domain_policy' */
>>      XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_policy; /* IN/OUT: */
>>      XEN_GUEST_HANDLE_64(xen_msr_entry_t) msr_policy;    /* IN/OUT: */
>> +    uint32_t err_leaf, err_subleaf; /* OUT, set_policy only.  If not ~0,
>> +                                     * indicates the leaf/subleaf which
>> +                                     * auditing objected to. */
>> +    uint32_t err_msr_idx;           /* OUT, set_policy only.  If not ~0,
>> +                                     * indicates the MSR idx which
>> +                                     * auditing objected to. */
> Explicit padding again please, with the handler checking it to be
> zero.
>
>> --- a/xen/include/xen/xmalloc.h
>> +++ b/xen/include/xen/xmalloc.h
>> @@ -13,6 +13,13 @@
>>  #define xmalloc(_type) ((_type *)_xmalloc(sizeof(_type), __alignof__(_type)))
>>  #define xzalloc(_type) ((_type *)_xzalloc(sizeof(_type), __alignof__(_type)))
>>  
>> +/* Allocate space for a typed object and copy an existing instance. */
>> +#define xmemdup(ptr)                                    \
>> +    ({  typeof(*ptr) *n_ = xmalloc(typeof(*ptr));       \
>> +        if ( n_ )                                       \
>> +            memcpy(n_, ptr, sizeof(*ptr));              \
>> +        n_; })
> Would be nice if this could handle input pointers to const-qualified types.
> I vaguely recall having seen a solution to this recently, but I don't recall
> where that was or how it looked like. Until then, may I suggest to use
> void * instead, despite this opening the risk of type incompatibilities?

The only way I'm aware of which might fix the const qualified aspect is
_Generic(), but ISTR you can't use typeof() inside.

As for xmemdup() specific, no - this will never want const qualified
types.  The caller is always going to mutate the structure, or they
wouldn't have dup'd the object to begin with.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
  2018-07-04 16:23       ` Andrew Cooper
@ 2018-07-05  8:09         ` Wei Liu
  2018-07-05  8:40         ` Jan Beulich
  1 sibling, 0 replies; 67+ messages in thread
From: Wei Liu @ 2018-07-05  8:09 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Jan Beulich,
	Roger Pau Monne

On Wed, Jul 04, 2018 at 05:23:56PM +0100, Andrew Cooper wrote:
> On 04/07/18 09:51, Jan Beulich wrote:
> >>>> On 04.07.18 at 10:42, <wei.liu2@citrix.com> wrote:
> >> On Tue, Jul 03, 2018 at 09:55:19PM +0100, Andrew Cooper wrote:
> >>> --- a/xen/include/public/arch-x86/xen.h
> >>> +++ b/xen/include/public/arch-x86/xen.h
> >>> @@ -314,6 +314,17 @@ struct xen_arch_domainconfig {
> >>>  #define XEN_ACPI_GPE0_CPUHP_BIT      2
> >>>  #endif
> >>>  
> >>> +/*
> >>> + * Representations of architectural CPUID information.  Used as the
> >>> + * serialised version of Xen's internal representation.
> >>> + */
> >>> +typedef struct xen_cpuid_leaf {
> >>> +#define XEN_CPUID_NO_SUBLEAF 0xffffffffu
> >>> +    uint32_t leaf, subleaf;
> >>> +    uint32_t a, b, c, d;
> >>> +} xen_cpuid_leaf_t;
> >>> +DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t);
> >>> +
> >> Is putting this in public header while leaving
> >> CPUID_MAX_SERIALISED_LEAVES in a private header useful?
> >>
> >> How does an external user know how big a buffer it needs to provide to
> >> accommodate the return structure?
> > Yeah, this is indeed hard to tell from this patch alone. And going
> > over the titles of the remainder of the series it's also not clear
> > where a use of this structure in a domctl/sysctl would appear.
> 
> An array of (some number of) xen_cpuid_leaf_t objects is the externally
> visible representation of the policy, which is why this definition is
> externally visible.
> 
> Content of this nature will (eventually) exist in the migration stream,
> and it is also the interface by which toolstacks (libxl and Xapi) can
> make under-specified modifications to the policies.

Right. An array is needed. How can the caller of
x86_cpuid_copy_to_buffer know how big this array is? It needs to pass in
an array for the data, right?

Wei.

> 
> ~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
  2018-07-04 16:46     ` Andrew Cooper
@ 2018-07-05  8:11       ` Wei Liu
  2018-07-05 10:21         ` Andrew Cooper
  2018-07-05  8:46       ` Jan Beulich
  1 sibling, 1 reply; 67+ messages in thread
From: Wei Liu @ 2018-07-05  8:11 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Jan Beulich,
	Roger Pau Monne

On Wed, Jul 04, 2018 at 05:46:29PM +0100, Andrew Cooper wrote:
> On 04/07/18 10:01, Jan Beulich wrote:
> >>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> >> --- a/xen/common/libx86/cpuid.c
> >> +++ b/xen/common/libx86/cpuid.c
> >> @@ -34,6 +34,100 @@ const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature)
> >>  }
> >>  
> >>  /*
> >> + * Copy a single cpuid_leaf into a provided xen_cpuid_leaf_t buffer,
> >> + * performing boundary checking against the buffer size.
> >> + */
> >> +static int copy_leaf_to_buffer(uint32_t leaf, uint32_t subleaf,
> >> +                               const struct cpuid_leaf *data,
> >> +                               cpuid_leaf_buffer_t leaves,
> >> +                               uint32_t *curr_entry, const uint32_t nr_entries)
> >> +{
> >> +    const xen_cpuid_leaf_t val = {
> >> +        leaf, subleaf, data->a, data->b, data->c, data->d,
> >> +    };
> >> +
> >> +    if ( *curr_entry == nr_entries )
> >> +        return -ENOBUFS;
> >> +
> >> +    if ( copy_to_buffer_offset(leaves, *curr_entry, &val, 1) )
> >> +        return -EFAULT;
> >> +
> >> +    ++*curr_entry;
> > Following on from what Wei has said - you don't mean to have a way
> > here then to indicate to a higher up caller how many slots would have
> > been needed?
> 
> I don't understand your query.  An individual build has a compile-time
> static maximum number of leaves, and this number can be obtained in the
> usual way by making a hypercall with a NULL guest handle.

Ah, this is what I was looking for. I think this should be wrapped into
a function btw.

Wei.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
  2018-07-04 16:23       ` Andrew Cooper
  2018-07-05  8:09         ` Wei Liu
@ 2018-07-05  8:40         ` Jan Beulich
  2018-07-05 13:39           ` Andrew Cooper
  1 sibling, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-05  8:40 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Xen-devel, Wei Liu, Ian Jackson, Roger Pau Monne

>>> On 04.07.18 at 18:23, <andrew.cooper3@citrix.com> wrote:
> On 04/07/18 09:51, Jan Beulich wrote:
>>>>> On 04.07.18 at 10:42, <wei.liu2@citrix.com> wrote:
>>> On Tue, Jul 03, 2018 at 09:55:19PM +0100, Andrew Cooper wrote:
>>>> --- a/xen/include/public/arch-x86/xen.h
>>>> +++ b/xen/include/public/arch-x86/xen.h
>>>> @@ -314,6 +314,17 @@ struct xen_arch_domainconfig {
>>>>  #define XEN_ACPI_GPE0_CPUHP_BIT      2
>>>>  #endif
>>>>  
>>>> +/*
>>>> + * Representations of architectural CPUID information.  Used as the
>>>> + * serialised version of Xen's internal representation.
>>>> + */
>>>> +typedef struct xen_cpuid_leaf {
>>>> +#define XEN_CPUID_NO_SUBLEAF 0xffffffffu
>>>> +    uint32_t leaf, subleaf;
>>>> +    uint32_t a, b, c, d;
>>>> +} xen_cpuid_leaf_t;
>>>> +DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t);
>>>> +
>>> Is putting this in public header while leaving
>>> CPUID_MAX_SERIALISED_LEAVES in a private header useful?
>>>
>>> How does an external user know how big a buffer it needs to provide to
>>> accommodate the return structure?
>> Yeah, this is indeed hard to tell from this patch alone. And going
>> over the titles of the remainder of the series it's also not clear
>> where a use of this structure in a domctl/sysctl would appear.
> 
> An array of (some number of) xen_cpuid_leaf_t objects is the externally
> visible representation of the policy, which is why this definition is
> externally visible.
> 
> Content of this nature will (eventually) exist in the migration stream,
> and it is also the interface by which toolstacks (libxl and Xapi) can
> make under-specified modifications to the policies.

But then how can a merge be as simple as the one done here?
Shouldn't you e.g. match CPUID entries by leaf/subleaf, rather than
relying on a given ordering within the arrays?

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
  2018-07-04 16:46     ` Andrew Cooper
  2018-07-05  8:11       ` Wei Liu
@ 2018-07-05  8:46       ` Jan Beulich
  2018-07-05 13:34         ` Andrew Cooper
  1 sibling, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-05  8:46 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Xen-devel, Wei Liu, Ian Jackson, Roger Pau Monne

>>> On 04.07.18 at 18:46, <andrew.cooper3@citrix.com> wrote:
> On 04/07/18 10:01, Jan Beulich wrote:
>>>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
>>> --- a/xen/common/libx86/cpuid.c
>>> +++ b/xen/common/libx86/cpuid.c
>>> @@ -34,6 +34,100 @@ const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature)
>>>  }
>>>  
>>>  /*
>>> + * Copy a single cpuid_leaf into a provided xen_cpuid_leaf_t buffer,
>>> + * performing boundary checking against the buffer size.
>>> + */
>>> +static int copy_leaf_to_buffer(uint32_t leaf, uint32_t subleaf,
>>> +                               const struct cpuid_leaf *data,
>>> +                               cpuid_leaf_buffer_t leaves,
>>> +                               uint32_t *curr_entry, const uint32_t nr_entries)
>>> +{
>>> +    const xen_cpuid_leaf_t val = {
>>> +        leaf, subleaf, data->a, data->b, data->c, data->d,
>>> +    };
>>> +
>>> +    if ( *curr_entry == nr_entries )
>>> +        return -ENOBUFS;
>>> +
>>> +    if ( copy_to_buffer_offset(leaves, *curr_entry, &val, 1) )
>>> +        return -EFAULT;
>>> +
>>> +    ++*curr_entry;
>> Following on from what Wei has said - you don't mean to have a way
>> here then to indicate to a higher up caller how many slots would have
>> been needed?
> 
> I don't understand your query.  An individual build has a compile-time
> static maximum number of leaves, and this number can be obtained in the
> usual way by making a hypercall with a NULL guest handle.

My point is that this generally is a sub-optimal interface. Seeing how
closely tied libxc is to a specific hypervisor build (or at least version),
I don't see why the caller couldn't set up a suitably sized array without
first querying with a null handle, and only re-issue the call in the
unlikely event that actually a larger buffer is necessary.

> The external representation must not encode this number, as it will
> change build to build, hardware to hardware, and in such times as we
> gain a load of new features in microcode.

Of course.

>>> +int x86_cpuid_copy_to_buffer(const struct cpuid_policy *p,
>>> +                             cpuid_leaf_buffer_t leaves,
>>> +                             uint32_t *nr_entries_p)
>>> +{
>>> +    const uint32_t nr_entries = *nr_entries_p;
>>> +    uint32_t curr_entry = 0, leaf, subleaf;
>>> +
>>> +#define COPY_LEAF(l, s, data)                                       \
>>> +    ({  int ret;                                                    \
>>> +        if ( (ret = copy_leaf_to_buffer(                            \
>>> +                  l, s, data, leaves, &curr_entry, nr_entries)) )   \
>>> +            return ret;                                             \
>>> +    })
>>> +
>>> +    /* Basic leaves. */
>>> +    for ( leaf = 0; leaf <= MIN(p->basic.max_leaf,
>>> +                                ARRAY_SIZE(p->basic.raw) - 1); ++leaf )
>>> +    {
>>> +        switch ( leaf )
>>> +        {
>>> +        case 0x4:
>>> +            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->cache.raw); ++subleaf )
>>> +                COPY_LEAF(leaf, subleaf, &p->cache.raw[subleaf]);
>>> +            break;
>>> +
>>> +        case 0x7:
>>> +            for ( subleaf = 0;
>>> +                  subleaf <= MIN(p->feat.max_subleaf,
>>> +                                 ARRAY_SIZE(p->feat.raw) - 1); ++subleaf )
>>> +                COPY_LEAF(leaf, subleaf, &p->feat.raw[subleaf]);
>>> +            break;
>>> +
>>> +        case 0xb:
>>> +            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->topo.raw); ++subleaf )
>>> +                COPY_LEAF(leaf, subleaf, &p->topo.raw[subleaf]);
>>> +            break;
>>> +
>>> +        case 0xd:
>>> +            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->xstate.raw); ++subleaf )
>>> +                COPY_LEAF(leaf, subleaf, &p->xstate.raw[subleaf]);
>>> +            break;
>>> +
>>> +        default:
>>> +            COPY_LEAF(leaf, XEN_CPUID_NO_SUBLEAF, &p->basic.raw[leaf]);
>>> +            break;
>>> +        }
>>> +    }
>>> +
>>> +    COPY_LEAF(0x40000000, XEN_CPUID_NO_SUBLEAF,
>>> +              &(struct cpuid_leaf){ p->hv_limit });
>>> +    COPY_LEAF(0x40000100, XEN_CPUID_NO_SUBLEAF,
>>> +              &(struct cpuid_leaf){ p->hv2_limit });
>> Is it a good idea to produce wrong (zero) EBX, ECX, and EDX values here?
> 
> The handling of these leaves currently problematic, and this patch is
> bug-compatible with how DOMCTL_set_cpuid currently behaves (See
> update_domain_cpuid_info()).
> 
> Annoyingly, I need this marshalling series implemented before I can fix
> the hypervisor leaves to use the "new" CPUID infrastructure; the main
> complication being because of the dynamic location of the Xen leaves.

Well, okay, but I'd prefer if such restrictions and bug-compatibilities
were spelled out in the commit message.

> Eventually, the interface will be that Xen leaves live at 0x40000000 and
> the toolstack can manipulate a subset of the information by providing
> leaves in the usual manor.  To enable viridian, the toolstack writes
> HyperV's signature at 0x40000000, and Xen's at 0x40000100.  This also
> allows for a mechanism to hide the Xen CPUID leaves by writing a 0 max leaf.
> 
> Amongst other things, this will allow sensible control of the Viridian
> features without having to squeeze more bits into the HVMPARAM.

Ah, interesting - you basically mean to deprecate the current way of
configuring Viridian features then, if I get this right?

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 07/13] libx86: Introduce a helper to serialise msr_{domain, vcpu}_policy objects
  2018-07-04 16:56     ` Andrew Cooper
@ 2018-07-05  8:49       ` Jan Beulich
  0 siblings, 0 replies; 67+ messages in thread
From: Jan Beulich @ 2018-07-05  8:49 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Xen-devel, Wei Liu, Ian Jackson, Roger Pau Monne

>>> On 04.07.18 at 18:56, <andrew.cooper3@citrix.com> wrote:
> On 04/07/18 10:16, Jan Beulich wrote:
>>
>>> @@ -325,6 +325,13 @@ typedef struct xen_cpuid_leaf {
>>>  } xen_cpuid_leaf_t;
>>>  DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t);
>>>  
>>> +typedef struct xen_msr_entry {
>>> +    uint32_t idx;
>>> +    uint32_t flags; /* Reserved MBZ. */
>> ... it remains unclear in this patch whose responsibility it is to clear this
>> field. I wonder whether copy_msr_to_buffer() should make sure of this.
> 
> copy_msr_to_buffer() does explicitly zero this field.
> 
>> +    const xen_msr_entry_t ent = { .idx = idx, .val = val };
> 
> guarantees that the flags field is 0.

Oh, I'm sorry - so it does. I had searched the patch for instances of
"flags" only ...

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 08/13] x86: Collect policies together into groups
  2018-07-04 17:15     ` Andrew Cooper
@ 2018-07-05  8:54       ` Jan Beulich
  0 siblings, 0 replies; 67+ messages in thread
From: Jan Beulich @ 2018-07-05  8:54 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Xen-devel, Wei Liu, Ian Jackson, Roger Pau Monne

>>> On 04.07.18 at 19:15, <andrew.cooper3@citrix.com> wrote:
> On 04/07/18 10:22, Jan Beulich wrote:
>>>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
>>> This is mainly prep work for the following patch, but this specific
>>> abstraction is also specifically useful for the future auditing logic.
>>>
>>> Not all of msr_vcpu_policy will be interesting from a domain building
>>> perspective, but some soon-to-appear fields will be (SGX Launch Hash
>>> specifically).  The exact split of MSRs between domain and vcpu policies is
>>> internal to Xen and liable to change moving forwards, so treat the two
>>> structures consistently from the start to avoid problems in the future.
>> I hope the utility of this grouping will become evident in later
>> patches.
> 
> Probably moreso in the followup series with the auditing/subset logic,
> but patch 13 does provide the first aspect.

Does it? It's a faint hint at best, as long as x86_policies_are_compatible()
is all empty.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 09/13] x86/sysctl: Implement XEN_SYSCTL_get_cpumsr_policy
  2018-07-04 17:57     ` Andrew Cooper
@ 2018-07-05  9:08       ` Jan Beulich
  2018-07-05 14:08         ` Andrew Cooper
  0 siblings, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-05  9:08 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Daniel de Graaf,
	Roger Pau Monne

>>> On 04.07.18 at 19:57, <andrew.cooper3@citrix.com> wrote:
> On 04/07/18 10:43, Jan Beulich wrote:
>>> --- a/xen/arch/x86/sysctl.c
>>> +++ b/xen/arch/x86/sysctl.c
>>> @@ -32,22 +32,32 @@
>>>  #include <asm/cpuid.h>
>>>  
>>>  const struct policy_group system_policies[] = {
>>> -    {
>>> +    [ XEN_SYSCTL_cpumsr_policy_raw ] = {
>> Aha - this clarifies a question I had on the earlier patch. But it would
>> be nice if that other patch was self contained also in the way of
>> allowing readers to understand the intentions.
> 
> One thing I could do is introduce the XEN_SYSCTL_cpumsr_policy_* defines
> in the previous patch?  I don't want to merge the two patches as that is
> too many moving parts to review in a single patch.

I think this would help, yes.

>> And with this I now
>> wonder whether the pointers in struct policy_group shouldn't all
>> be const qualified.
> 
> Unfortunately that doesn't work with the logic to create a policy_group
> for an individual domain during audit.

I don't understand: Is x86_policies_are_compatible() supposed to
alter the policies? Otherwise, if you maintained local separate
pointers in update_domain_cpumsr_policy(), using "new" just for
the purpose of passing to x86_policies_are_compatible(), all
should be fine and it would be crystal clear that anyone handed
a group won't alter anything the group refers to.

>>> @@ -318,6 +328,74 @@ long arch_do_sysctl(
>>>          break;
>>>      }
>>>  
>>> +    case XEN_SYSCTL_get_cpumsr_policy:
>>> +    {
>>> +        const struct policy_group *group;
>>> +
>>> +        /* Bad policy index? */
>>> +        if ( sysctl->u.cpumsr_policy.index >= ARRAY_SIZE(system_policies) )
>>> +        {
>>> +            ret = -EINVAL;
>>> +            break;
>>> +        }
>>> +        group = &system_policies[sysctl->u.cpumsr_policy.index];
>> Isn't this introducing at least half of a Spectre v1 gadget?
> 
> Nope :(
> 
> It's both halves of the Spectre gadget, when you account for the
> dereference when calling x86_*_copy_to_buffer() slightly lower.
> 
> I suppose we want to port the Linux array nospec lookup logic so we can
> protect the clearly-visible gadgets.

I'm confused: You first say "nope", but the rest of your response reads
as if you meant "yes.".

>>> --- a/xen/include/public/sysctl.h
>>> +++ b/xen/include/public/sysctl.h
>>> @@ -1063,6 +1063,43 @@ struct xen_sysctl_set_parameter {
>>>      uint16_t pad[3];                        /* IN: MUST be zero. */
>>>  };
>>>  
>>> +#if defined(__i386__) || defined(__x86_64__)
>>> +/*
>>> + * XEN_SYSCTL_get_cpumsr_policy (x86 specific)
>> Perhaps express the "x86 specific" also in the opcode name? And make
>> more obvious that this is about CPUID and MSRs at the same time? E.g.
>> XEN_SYSCTL_x86_get_cpuid_msr_policy?
>>
>> I'm sure you have reasons to munge it all into a single operation.
> 
> (Answering in reverse order)
> 
> The get operations don't strictly need to be a single operation.  The
> set operation specifically must be a single operation, and the getters
> have an interface to match.
> 
> As for naming, cpumsr_policy wasn't chosen by me, but I can't think of
> anything better.  The code is currently consistent and, while I'm open
> to a rename, it will impact large quantities of the series.
> 
> One concern I have if we end up with a new block of information.  I was
> hoping for a generic name, but simply "policy" on its own is too
> generic.  cpumsr is, I believe, a contraction of cpuid_msr to avoid
> excessive code volume.
> 
> Suggestions welcome.

To cover potential future additions, why not XEN_SYSCTL_get_cpu_policy?
That's neither misleading by abbreviating too much, nor more specific than
we need it to be. However, in this case it might be worthwhile to consider
adding in "x86", as ARM might plausibly want something similar at some
point. Otoh the same name (but different structure contents) could be
used for both.

>>> +struct xen_sysctl_cpumsr_policy {
>>> +#define XEN_SYSCTL_cpumsr_policy_raw          0
>>> +#define XEN_SYSCTL_cpumsr_policy_host         1
>>> +#define XEN_SYSCTL_cpumsr_policy_pv_max       2
>>> +#define XEN_SYSCTL_cpumsr_policy_hvm_max      3
>>> +#define XEN_SYSCTL_cpumsr_policy_pv_default   4
>>> +#define XEN_SYSCTL_cpumsr_policy_hvm_default  5
>>> +    uint32_t index;       /* IN: Which policy to query? */
>>> +    uint32_t nr_leaves;   /* IN/OUT: Number of leaves in/written to
>>> +                           * 'cpuid_policy', or the maximum number of leaves if
>>> +                           * any of the guest handles is NULL.
>>> +                           * NB. All policies come from the same space,
>>> +                           * so have the same maximum length. */
>>> +    uint32_t nr_msrs;     /* IN/OUT: Number of MSRs in/written to
>>> +                           * 'msr_domain_policy', or the maximum number of MSRs
>>> +                           * if any of the guest handles is NULL.
>>> +                           * NB. All policies come from the same space,
>>> +                           * so have the same maximum length. */
>>> +    XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_policy; /* OUT: */
>> Explicit padding (checked to be zero in the handler) above here
>> please.
> 
> Why?  SYSCTLs are unstable and we don't perform similar checks for other
> subops.

You don't like the interface version bumps anyway, as being only
partly useful. If you added and checked explicit padding, no bump
would be needed once the field gains meaning.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 13/13] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy
  2018-07-04 18:47     ` Andrew Cooper
@ 2018-07-05  9:28       ` Jan Beulich
  2018-07-05 17:55         ` Andrew Cooper
  0 siblings, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-05  9:28 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Daniel de Graaf,
	Roger Pau Monne

>>> On 04.07.18 at 20:47, <andrew.cooper3@citrix.com> wrote:
> On 04/07/18 11:16, Jan Beulich wrote:
>>>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
>>> From: Sergey Dyasli <sergey.dyasli@citrix.com>
>>>
>>> This hypercall allows the toolstack to present one combined CPUID and MSR
>>> policy for a domain, which can be audited in one go by Xen, which is necessary
>>> for correctness of the auditing.
>>>
>>> A stub x86_policies_are_compatible() function is introduced, although at
>>> present it will always fail the hypercall.
>>>
>>> The hypercall ABI allows for update of individual CPUID or MSR entries, so
>>> begins by duplicating the existing policy (for which a helper is introduced),
>>> merging the toolstack data, then checking compatibility of the result.
>> This reads to me as if it was fine for the tool stack to supply only partial
>> data (or else there would be no need to merge anything). What's the
>> thinking behind this, rather than requiring complete sets of data to be
>> supplied?
> 
> Unless you have an identical build of Xen and libxc, the toolstack won't
> always provide the same leaves as Xen expects.  Such a restriction would
> massively hamper development.
> 
> More importantly, with the max_extd_leaf being vendor dependent (which
> is data earlier in the structure), the toolstack can't reasonably create
> a dataset which matches those expectations.  Also you'll get into
> problems when migrating from older hosts, and when levelling a policy
> down with a lower max_leaf.
> 
> The reason for having an architectural representation was deliberately
> to prohibit having a hypercall which was a memcpy of an unstable
> structure in the background, but with this design comes the fact that
> Xen must not expect to find an exact match of data.

Okay, I can see the point together with the migration aspect you've
mentioned in another reply on this series.

>>> --- a/xen/arch/x86/domctl.c
>>> +++ b/xen/arch/x86/domctl.c
>>> @@ -330,6 +330,71 @@ static int update_domain_cpuid_info(struct domain *d,
>>>      return 0;
>>>  }
>>>  
>>> +static int update_domain_cpumsr_policy(struct domain *d,
>>> +                                       xen_domctl_cpumsr_policy_t *xdpc)
>>> +{
>>> +    struct policy_group new = {};
>>> +    const struct policy_group *sys = is_pv_domain(d)
>>> +        ? &system_policies[XEN_SYSCTL_cpumsr_policy_pv_max]
>>> +        : &system_policies[XEN_SYSCTL_cpumsr_policy_hvm_max];
>>> +    struct vcpu *v = d->vcpu[0];
>>> +    int ret = -ENOMEM;
>>> +
>>> +    /* Initialise some help identifying auditing errors. */
>>> +    xdpc->err_leaf = xdpc->err_subleaf = XEN_CPUID_NO_SUBLEAF;
>>> +    xdpc->err_msr_idx = ~0;
>> I'm having trouble extracting information from the comment.
> 
> So am I...
> 
> These are the fields inside the domctl which try to provide some hint as
> to which piece of data is problematic, rather than leaving the user with
> simply "somthing is wrong".

Yeah, I did understand the purpose of the fields. I take it the
comment will be dropped or improved then.

>>> +    /* Start with existing domain's policies */
>>> +    if ( !(new.cp = xmemdup(d->arch.cpuid)) ||
>>> +         !(new.dp = xmemdup(d->arch.msr)) ||
>>> +         !(new.vp = xmemdup(v->arch.msr)) )
>>> +        goto out;
>>> +
>>> +    /* Merge the toolstack provided data. */
>>> +    if ( (ret = x86_cpuid_copy_from_buffer(
>>> +              new.cp, xdpc->cpuid_policy, xdpc->nr_leaves,
>>> +              &xdpc->err_leaf, &xdpc->err_subleaf)) )
>>> +        goto out;
>>> +
>>> +    if ( (ret = x86_msr_copy_from_buffer(
>>> +              new.dp, new.vp,
>>> +              xdpc->msr_policy, xdpc->nr_msrs, &xdpc->err_msr_idx)) )
>>> +        goto out;
>>> +
>>> +    /* Audit the combined dataset. */
>>> +    ret = x86_policies_are_compatible(sys, &new);
>>> +    if ( ret )
>>> +        goto out;
>> I'm afraid I don't follow - where's the merging? All you do is copy the
>> first so many entries coming from libxc, and using the later so many
>> entries from the previous policies. How's that going to provide a
>> complete set, rather than e.g. some duplicate entries and some
>> missing ones?
> 
> Consider the case where max_leaf is lower than Xen's maximum.  The data
> provided by the toolstack can be self consistent and complete without
> matching Xen's exact size of structure.

Right. The question on proper merging remains though: Shouldn't CPUID
entries be matched by leaf/subleaf, and MSR ones by MSR index?
Currently there's an implied ordering agreement of the arrays between
caller and callee.

>>> +    /*
>>> +     * Audit was successful.  Replace existing policies, leaving the old
>>> +     * policies to be freed.
>>> +     */
>>> +    SWAP(new.cp, d->arch.cpuid);
>>> +    SWAP(new.dp, d->arch.msr);
>>> +    SWAP(new.vp, v->arch.msr);
>>> +
>>> +    /* Merge the (now audited) vCPU MSRs into every other msr_vcpu_policy. */
>>> +    for ( ; v; v = v->next_in_list )
>> This open-coded almost-for_each_domain() doesn't look very nice.
> 
> ITYM for_each_vcpu()

Oops, of course.

> And yes, but for_each_vcpu() is wrong to use here, and we don't have a
> for_each_vcpu_other_than_0() helper.

Perhaps still better to do

    for_each_vcpu(d, v)
    {
        if ( v->vcpu_id == 0 )
            continue;
        ...
    }

?

>>> +    {
>>> +        /* XXX - Figure out how to avoid a TOCTOU race here.  XLAT area? */
>>> +        if ( (ret = x86_msr_copy_from_buffer(
>>> +                  NULL, v->arch.msr, xdpc->msr_policy, xdpc->nr_msrs, NULL)) )
>> Why can't you go from vCPU 0's v->arch.msr here, which is the copied-in
>> (and sanitized) representation already? Also, is it really a good idea to
>> assume all vCPU-s have the same policies?
> 
> There are multiple colliding issues which lead to this code, but as
> several people have pointed out, its probably over the top.
> 
> First, as to the same policy.  This hypercall can currently only be used
> before the vcpu has started executing.
> 
> As such, it is setting the init state of the MSRs from the guests point
> of view, and there is exactly one MSR I'm aware of which has an init
> value which depends on the core (that being APIC_BASE.BSP which can
> trivially be handled in Xen).  All other MSRs have identical init state
> AFAICT, and I don't want to create an interface which makes it easy to
> accidentally end up with wrong values.

So what about migration? There are certainly differing incoming values
there. Of course there's the MSRs restore record, but no atomic sanity
check between those and the policy here is possible.

> The re-de-serialising actually came from your suggested usecase to be
> able to increase the policy at runtime, .e.g. after a microcode update
> and hypervisor livepatch.  In that case, a partial set doesn't want to
> copy vCPU0's generally R/W MSRs over other vcpus, because that would be
> a bad thing.
> 
> However, these two points aren't compatible, so if we accept the "only
> before the domain has started running" aspect, then it should be safe to
> copy v0's policy over all other vcpus.

I think the description of the change wants to be extended to cover
this.

> Really, the problem here comes from (necessarily) how we will have to
> implement SGX_LC and the fact that the LC Hash MSRs may be read-only
> domain-wide state, or read-write per-vcpu state depending on a different
> MSR setting (MSR_FEAT_CTRL.SGX_LC).
> 
> I was initially hoping to have only msr_domain_policy poked via this
> interface, and msr_vcpu_policy poked exclusively via per-vcpu
> hypercalls.  Then again, at least the complexity is visible at this
> point, rather than at some point in the future when we need to try and
> retrofit it.

Oh, that's certainly very worthwhile; I wasn't even aware of this SGX
induced challenge.

>>> --- a/xen/include/xen/xmalloc.h
>>> +++ b/xen/include/xen/xmalloc.h
>>> @@ -13,6 +13,13 @@
>>>  #define xmalloc(_type) ((_type *)_xmalloc(sizeof(_type), __alignof__(_type)))
>>>  #define xzalloc(_type) ((_type *)_xzalloc(sizeof(_type), __alignof__(_type)))
>>>  
>>> +/* Allocate space for a typed object and copy an existing instance. */
>>> +#define xmemdup(ptr)                                    \
>>> +    ({  typeof(*ptr) *n_ = xmalloc(typeof(*ptr));       \
>>> +        if ( n_ )                                       \
>>> +            memcpy(n_, ptr, sizeof(*ptr));              \
>>> +        n_; })
>> Would be nice if this could handle input pointers to const-qualified types.
>> I vaguely recall having seen a solution to this recently, but I don't recall
>> where that was or how it looked like. Until then, may I suggest to use
>> void * instead, despite this opening the risk of type incompatibilities?
> 
> The only way I'm aware of which might fix the const qualified aspect is
> _Generic(), but ISTR you can't use typeof() inside.
> 
> As for xmemdup() specific, no - this will never want const qualified
> types.  The caller is always going to mutate the structure, or they
> wouldn't have dup'd the object to begin with.

I don't follow: Why wouldn't a caller possibly want to mutate a clone
of a const input structure? What is pointless to be const id the output
structure, yes, but typeof(*(ptr)) [note the missing parentheses in
your code, btw] includes the possible const from what the input points
to.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
  2018-07-05  8:11       ` Wei Liu
@ 2018-07-05 10:21         ` Andrew Cooper
  0 siblings, 0 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-05 10:21 UTC (permalink / raw)
  To: Wei Liu
  Cc: Sergey Dyasli, Xen-devel, Ian Jackson, Jan Beulich, Roger Pau Monne

On 05/07/18 09:11, Wei Liu wrote:
> On Wed, Jul 04, 2018 at 05:46:29PM +0100, Andrew Cooper wrote:
>> On 04/07/18 10:01, Jan Beulich wrote:
>>>>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
>>>> --- a/xen/common/libx86/cpuid.c
>>>> +++ b/xen/common/libx86/cpuid.c
>>>> @@ -34,6 +34,100 @@ const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature)
>>>>  }
>>>>  
>>>>  /*
>>>> + * Copy a single cpuid_leaf into a provided xen_cpuid_leaf_t buffer,
>>>> + * performing boundary checking against the buffer size.
>>>> + */
>>>> +static int copy_leaf_to_buffer(uint32_t leaf, uint32_t subleaf,
>>>> +                               const struct cpuid_leaf *data,
>>>> +                               cpuid_leaf_buffer_t leaves,
>>>> +                               uint32_t *curr_entry, const uint32_t nr_entries)
>>>> +{
>>>> +    const xen_cpuid_leaf_t val = {
>>>> +        leaf, subleaf, data->a, data->b, data->c, data->d,
>>>> +    };
>>>> +
>>>> +    if ( *curr_entry == nr_entries )
>>>> +        return -ENOBUFS;
>>>> +
>>>> +    if ( copy_to_buffer_offset(leaves, *curr_entry, &val, 1) )
>>>> +        return -EFAULT;
>>>> +
>>>> +    ++*curr_entry;
>>> Following on from what Wei has said - you don't mean to have a way
>>> here then to indicate to a higher up caller how many slots would have
>>> been needed?
>> I don't understand your query.  An individual build has a compile-time
>> static maximum number of leaves, and this number can be obtained in the
>> usual way by making a hypercall with a NULL guest handle.
> Ah, this is what I was looking for. I think this should be wrapped into
> a function btw.

It is.  xc_get_cpumsr_policy_size(), in patch 9 where it is first used.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
  2018-07-05  8:46       ` Jan Beulich
@ 2018-07-05 13:34         ` Andrew Cooper
  0 siblings, 0 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-05 13:34 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Sergey Dyasli, Xen-devel, Wei Liu, Ian Jackson, Roger Pau Monne

On 05/07/18 09:46, Jan Beulich wrote:
>>>> On 04.07.18 at 18:46, <andrew.cooper3@citrix.com> wrote:
>> On 04/07/18 10:01, Jan Beulich wrote:
>>>>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
>>>> --- a/xen/common/libx86/cpuid.c
>>>> +++ b/xen/common/libx86/cpuid.c
>>>> @@ -34,6 +34,100 @@ const uint32_t *x86_cpuid_lookup_deep_deps(uint32_t feature)
>>>>  }
>>>>  
>>>>  /*
>>>> + * Copy a single cpuid_leaf into a provided xen_cpuid_leaf_t buffer,
>>>> + * performing boundary checking against the buffer size.
>>>> + */
>>>> +static int copy_leaf_to_buffer(uint32_t leaf, uint32_t subleaf,
>>>> +                               const struct cpuid_leaf *data,
>>>> +                               cpuid_leaf_buffer_t leaves,
>>>> +                               uint32_t *curr_entry, const uint32_t nr_entries)
>>>> +{
>>>> +    const xen_cpuid_leaf_t val = {
>>>> +        leaf, subleaf, data->a, data->b, data->c, data->d,
>>>> +    };
>>>> +
>>>> +    if ( *curr_entry == nr_entries )
>>>> +        return -ENOBUFS;
>>>> +
>>>> +    if ( copy_to_buffer_offset(leaves, *curr_entry, &val, 1) )
>>>> +        return -EFAULT;
>>>> +
>>>> +    ++*curr_entry;
>>> Following on from what Wei has said - you don't mean to have a way
>>> here then to indicate to a higher up caller how many slots would have
>>> been needed?
>> I don't understand your query.  An individual build has a compile-time
>> static maximum number of leaves, and this number can be obtained in the
>> usual way by making a hypercall with a NULL guest handle.
> My point is that this generally is a sub-optimal interface. Seeing how
> closely tied libxc is to a specific hypervisor build (or at least version),
> I don't see why the caller couldn't set up a suitably sized array without
> first querying with a null handle, and only re-issue the call in the
> unlikely event that actually a larger buffer is necessary.

I'm all for good interface design, but what you describe isn't plausibly
going to happen.

Code using the raw hypercall accessors in this series have no idea what
size the buffers need to be, and always need to explicitly ask Xen.

Code in one of the followup series which allows for manipulation of the
policy objects entirely in the toolstack will use its own static idea of
the size of the policies, and never needs to ask Xen.  (At this point,
if you've got a mismatched Xen and Libxc, then tough - you've got no
option but to recompile.)

Anything else is unnecessary extra complexity.

>
>>>> +int x86_cpuid_copy_to_buffer(const struct cpuid_policy *p,
>>>> +                             cpuid_leaf_buffer_t leaves,
>>>> +                             uint32_t *nr_entries_p)
>>>> +{
>>>> +    const uint32_t nr_entries = *nr_entries_p;
>>>> +    uint32_t curr_entry = 0, leaf, subleaf;
>>>> +
>>>> +#define COPY_LEAF(l, s, data)                                       \
>>>> +    ({  int ret;                                                    \
>>>> +        if ( (ret = copy_leaf_to_buffer(                            \
>>>> +                  l, s, data, leaves, &curr_entry, nr_entries)) )   \
>>>> +            return ret;                                             \
>>>> +    })
>>>> +
>>>> +    /* Basic leaves. */
>>>> +    for ( leaf = 0; leaf <= MIN(p->basic.max_leaf,
>>>> +                                ARRAY_SIZE(p->basic.raw) - 1); ++leaf )
>>>> +    {
>>>> +        switch ( leaf )
>>>> +        {
>>>> +        case 0x4:
>>>> +            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->cache.raw); ++subleaf )
>>>> +                COPY_LEAF(leaf, subleaf, &p->cache.raw[subleaf]);
>>>> +            break;
>>>> +
>>>> +        case 0x7:
>>>> +            for ( subleaf = 0;
>>>> +                  subleaf <= MIN(p->feat.max_subleaf,
>>>> +                                 ARRAY_SIZE(p->feat.raw) - 1); ++subleaf )
>>>> +                COPY_LEAF(leaf, subleaf, &p->feat.raw[subleaf]);
>>>> +            break;
>>>> +
>>>> +        case 0xb:
>>>> +            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->topo.raw); ++subleaf )
>>>> +                COPY_LEAF(leaf, subleaf, &p->topo.raw[subleaf]);
>>>> +            break;
>>>> +
>>>> +        case 0xd:
>>>> +            for ( subleaf = 0; subleaf < ARRAY_SIZE(p->xstate.raw); ++subleaf )
>>>> +                COPY_LEAF(leaf, subleaf, &p->xstate.raw[subleaf]);
>>>> +            break;
>>>> +
>>>> +        default:
>>>> +            COPY_LEAF(leaf, XEN_CPUID_NO_SUBLEAF, &p->basic.raw[leaf]);
>>>> +            break;
>>>> +        }
>>>> +    }
>>>> +
>>>> +    COPY_LEAF(0x40000000, XEN_CPUID_NO_SUBLEAF,
>>>> +              &(struct cpuid_leaf){ p->hv_limit });
>>>> +    COPY_LEAF(0x40000100, XEN_CPUID_NO_SUBLEAF,
>>>> +              &(struct cpuid_leaf){ p->hv2_limit });
>>> Is it a good idea to produce wrong (zero) EBX, ECX, and EDX values here?
>> The handling of these leaves currently problematic, and this patch is
>> bug-compatible with how DOMCTL_set_cpuid currently behaves (See
>> update_domain_cpuid_info()).
>>
>> Annoyingly, I need this marshalling series implemented before I can fix
>> the hypervisor leaves to use the "new" CPUID infrastructure; the main
>> complication being because of the dynamic location of the Xen leaves.
> Well, okay, but I'd prefer if such restrictions and bug-compatibilities
> were spelled out in the commit message.

I'll do that, and leave a /* TODO */ here.

>> Eventually, the interface will be that Xen leaves live at 0x40000000 and
>> the toolstack can manipulate a subset of the information by providing
>> leaves in the usual manor.  To enable viridian, the toolstack writes
>> HyperV's signature at 0x40000000, and Xen's at 0x40000100.  This also
>> allows for a mechanism to hide the Xen CPUID leaves by writing a 0 max leaf.
>>
>> Amongst other things, this will allow sensible control of the Viridian
>> features without having to squeeze more bits into the HVMPARAM.
> Ah, interesting - you basically mean to deprecate the current way of
> configuring Viridian features then, if I get this right?

Correct.  The xl.cfg interface can remain the same, but this new
libxc/Xen interface will be far more flexible than the current "all or
nothing" approach.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
  2018-07-05  8:40         ` Jan Beulich
@ 2018-07-05 13:39           ` Andrew Cooper
  2018-07-05 14:05             ` Jan Beulich
  0 siblings, 1 reply; 67+ messages in thread
From: Andrew Cooper @ 2018-07-05 13:39 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Sergey Dyasli, Xen-devel, Wei Liu, Ian Jackson, Roger Pau Monne

On 05/07/18 09:40, Jan Beulich wrote:
>>>> On 04.07.18 at 18:23, <andrew.cooper3@citrix.com> wrote:
>> On 04/07/18 09:51, Jan Beulich wrote:
>>>>>> On 04.07.18 at 10:42, <wei.liu2@citrix.com> wrote:
>>>> On Tue, Jul 03, 2018 at 09:55:19PM +0100, Andrew Cooper wrote:
>>>>> --- a/xen/include/public/arch-x86/xen.h
>>>>> +++ b/xen/include/public/arch-x86/xen.h
>>>>> @@ -314,6 +314,17 @@ struct xen_arch_domainconfig {
>>>>>  #define XEN_ACPI_GPE0_CPUHP_BIT      2
>>>>>  #endif
>>>>>  
>>>>> +/*
>>>>> + * Representations of architectural CPUID information.  Used as the
>>>>> + * serialised version of Xen's internal representation.
>>>>> + */
>>>>> +typedef struct xen_cpuid_leaf {
>>>>> +#define XEN_CPUID_NO_SUBLEAF 0xffffffffu
>>>>> +    uint32_t leaf, subleaf;
>>>>> +    uint32_t a, b, c, d;
>>>>> +} xen_cpuid_leaf_t;
>>>>> +DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t);
>>>>> +
>>>> Is putting this in public header while leaving
>>>> CPUID_MAX_SERIALISED_LEAVES in a private header useful?
>>>>
>>>> How does an external user know how big a buffer it needs to provide to
>>>> accommodate the return structure?
>>> Yeah, this is indeed hard to tell from this patch alone. And going
>>> over the titles of the remainder of the series it's also not clear
>>> where a use of this structure in a domctl/sysctl would appear.
>> An array of (some number of) xen_cpuid_leaf_t objects is the externally
>> visible representation of the policy, which is why this definition is
>> externally visible.
>>
>> Content of this nature will (eventually) exist in the migration stream,
>> and it is also the interface by which toolstacks (libxl and Xapi) can
>> make under-specified modifications to the policies.
> But then how can a merge be as simple as the one done here?
> Shouldn't you e.g. match CPUID entries by leaf/subleaf, rather than
> relying on a given ordering within the arrays?

I'm confused as to where you think there is any implied ordering within
the array.

When serialising the object (this patch), we write the values out in a
fixed order because that is the natural way to do it.

When deserialising the object (patch 13), we walk the array linearly
filling in the cpuid_policy object based on the leaf/subleaf.  The array
can have the leaves in any order and this won't affect the resulting
deserialisation.  (The array can also contain duplicate leaves, which we
can't reasonably be detect, and why there is a sanity upper bounds check).

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object
  2018-07-05 13:39           ` Andrew Cooper
@ 2018-07-05 14:05             ` Jan Beulich
  0 siblings, 0 replies; 67+ messages in thread
From: Jan Beulich @ 2018-07-05 14:05 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Xen-devel, Wei Liu, Ian Jackson, Roger Pau Monne

>>> On 05.07.18 at 15:39, <andrew.cooper3@citrix.com> wrote:
> On 05/07/18 09:40, Jan Beulich wrote:
>>>>> On 04.07.18 at 18:23, <andrew.cooper3@citrix.com> wrote:
>>> On 04/07/18 09:51, Jan Beulich wrote:
>>>>>>> On 04.07.18 at 10:42, <wei.liu2@citrix.com> wrote:
>>>>> On Tue, Jul 03, 2018 at 09:55:19PM +0100, Andrew Cooper wrote:
>>>>>> --- a/xen/include/public/arch-x86/xen.h
>>>>>> +++ b/xen/include/public/arch-x86/xen.h
>>>>>> @@ -314,6 +314,17 @@ struct xen_arch_domainconfig {
>>>>>>  #define XEN_ACPI_GPE0_CPUHP_BIT      2
>>>>>>  #endif
>>>>>>  
>>>>>> +/*
>>>>>> + * Representations of architectural CPUID information.  Used as the
>>>>>> + * serialised version of Xen's internal representation.
>>>>>> + */
>>>>>> +typedef struct xen_cpuid_leaf {
>>>>>> +#define XEN_CPUID_NO_SUBLEAF 0xffffffffu
>>>>>> +    uint32_t leaf, subleaf;
>>>>>> +    uint32_t a, b, c, d;
>>>>>> +} xen_cpuid_leaf_t;
>>>>>> +DEFINE_XEN_GUEST_HANDLE(xen_cpuid_leaf_t);
>>>>>> +
>>>>> Is putting this in public header while leaving
>>>>> CPUID_MAX_SERIALISED_LEAVES in a private header useful?
>>>>>
>>>>> How does an external user know how big a buffer it needs to provide to
>>>>> accommodate the return structure?
>>>> Yeah, this is indeed hard to tell from this patch alone. And going
>>>> over the titles of the remainder of the series it's also not clear
>>>> where a use of this structure in a domctl/sysctl would appear.
>>> An array of (some number of) xen_cpuid_leaf_t objects is the externally
>>> visible representation of the policy, which is why this definition is
>>> externally visible.
>>>
>>> Content of this nature will (eventually) exist in the migration stream,
>>> and it is also the interface by which toolstacks (libxl and Xapi) can
>>> make under-specified modifications to the policies.
>> But then how can a merge be as simple as the one done here?
>> Shouldn't you e.g. match CPUID entries by leaf/subleaf, rather than
>> relying on a given ordering within the arrays?
> 
> I'm confused as to where you think there is any implied ordering within
> the array.
> 
> When serialising the object (this patch), we write the values out in a
> fixed order because that is the natural way to do it.
> 
> When deserialising the object (patch 13), we walk the array linearly
> filling in the cpuid_policy object based on the leaf/subleaf.  The array
> can have the leaves in any order and this won't affect the resulting
> deserialisation.  (The array can also contain duplicate leaves, which we
> can't reasonably be detect, and why there is a sanity upper bounds check).

Oh, yes, I see now - I must have been pretty blind. I'm sorry for the
noise.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 09/13] x86/sysctl: Implement XEN_SYSCTL_get_cpumsr_policy
  2018-07-05  9:08       ` Jan Beulich
@ 2018-07-05 14:08         ` Andrew Cooper
  2018-07-05 14:45           ` Jan Beulich
  0 siblings, 1 reply; 67+ messages in thread
From: Andrew Cooper @ 2018-07-05 14:08 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Sergey Dyasli, Stefano Stabellini, Wei Liu, Ian Jackson,
	Xen-devel, Julien Grall, Daniel de Graaf, Roger Pau Monne

On 05/07/18 10:08, Jan Beulich wrote:
>>>> On 04.07.18 at 19:57, <andrew.cooper3@citrix.com> wrote:
>> On 04/07/18 10:43, Jan Beulich wrote:
>>>> --- a/xen/arch/x86/sysctl.c
>>>> +++ b/xen/arch/x86/sysctl.c
>>>> @@ -32,22 +32,32 @@
>>>>  #include <asm/cpuid.h>
>>>>  
>>>>  const struct policy_group system_policies[] = {
>>>> -    {
>>>> +    [ XEN_SYSCTL_cpumsr_policy_raw ] = {
>>> Aha - this clarifies a question I had on the earlier patch. But it would
>>> be nice if that other patch was self contained also in the way of
>>> allowing readers to understand the intentions.
>> One thing I could do is introduce the XEN_SYSCTL_cpumsr_policy_* defines
>> in the previous patch?  I don't want to merge the two patches as that is
>> too many moving parts to review in a single patch.
> I think this would help, yes.

Ok, in which case I'll also move the max vs default discussion into the
previous patch.

>>> And with this I now
>>> wonder whether the pointers in struct policy_group shouldn't all
>>> be const qualified.
>> Unfortunately that doesn't work with the logic to create a policy_group
>> for an individual domain during audit.
> I don't understand: Is x86_policies_are_compatible() supposed to
> alter the policies? Otherwise, if you maintained local separate
> pointers in update_domain_cpumsr_policy(), using "new" just for
> the purpose of passing to x86_policies_are_compatible(), all
> should be fine and it would be crystal clear that anyone handed
> a group won't alter anything the group refers to.

With this diff:

diff --git a/xen/include/xen/libx86/policies.h
b/xen/include/xen/libx86/policies.h
index 21e0a40..03fe6dd 100644
--- a/xen/include/xen/libx86/policies.h
+++ b/xen/include/xen/libx86/policies.h
@@ -7,9 +7,9 @@
 
 struct policy_group
 {
-    struct cpuid_policy *cp;
-    struct msr_domain_policy *dp;
-    struct msr_vcpu_policy *vp;
+    const struct cpuid_policy *cp;
+    const struct msr_domain_policy *dp;
+    const struct msr_vcpu_policy *vp;
 };
 
 /*

The resulting compiler complains are

domctl.c: In function ‘update_domain_cpumsr_policy’:
domctl.c:355:15: error: passing argument 1 of ‘x86_cpuid_copy_from_buffer’ discards ‘const’ qualifier from pointer target type [-Werror]
               new.cp, xdpc->cpuid_policy, xdpc->nr_leaves,
               ^
In file included from /local/xen.git/xen/include/asm/cpuid.h:11:0,
                 from /local/xen.git/xen/include/asm/cpufeature.h:10,
                 from /local/xen.git/xen/include/asm/processor.h:14,
                 from /local/xen.git/xen/include/asm/system.h:6,
                 from /local/xen.git/xen/include/xen/list.h:11,
                 from /local/xen.git/xen/include/xen/mm.h:50,
                 from domctl.c:9:
/local/xen.git/xen/include/xen/libx86/cpuid.h:257:5: note: expected ‘struct cpuid_policy *’ but argument is of type ‘const struct cpuid_policy *’
 int x86_cpuid_copy_from_buffer(struct cpuid_policy *p,
     ^
domctl.c:360:15: error: passing argument 1 of ‘x86_msr_copy_from_buffer’ discards ‘const’ qualifier from pointer target type [-Werror]
               new.dp, new.vp,
               ^
In file included from /local/xen.git/xen/include/xen/libx86/policies.h:6:0,
                 from /local/xen.git/xen/include/asm/cpuid.h:12,
                 from /local/xen.git/xen/include/asm/cpufeature.h:10,
                 from /local/xen.git/xen/include/asm/processor.h:14,
                 from /local/xen.git/xen/include/asm/system.h:6,
                 from /local/xen.git/xen/include/xen/list.h:11,
                 from /local/xen.git/xen/include/xen/mm.h:50,
                 from domctl.c:9:
/local/xen.git/xen/include/xen/libx86/msr.h:63:5: note: expected ‘struct msr_domain_policy *’ but argument is of type ‘const struct msr_domain_policy *’
 int x86_msr_copy_from_buffer(struct msr_domain_policy *dp,
     ^
domctl.c:360:23: error: passing argument 2 of ‘x86_msr_copy_from_buffer’ discards ‘const’ qualifier from pointer target type [-Werror]
               new.dp, new.vp,
                       ^
In file included from /local/xen.git/xen/include/xen/libx86/policies.h:6:0,
                 from /local/xen.git/xen/include/asm/cpuid.h:12,
                 from /local/xen.git/xen/include/asm/cpufeature.h:10,
                 from /local/xen.git/xen/include/asm/processor.h:14,
                 from /local/xen.git/xen/include/asm/system.h:6,
                 from /local/xen.git/xen/include/xen/list.h:11,
                 from /local/xen.git/xen/include/xen/mm.h:50,
                 from domctl.c:9:
/local/xen.git/xen/include/xen/libx86/msr.h:63:5: note: expected ‘struct msr_vcpu_policy *’ but argument is of type ‘const struct msr_vcpu_policy *’
 int x86_msr_copy_from_buffer(struct msr_domain_policy *dp,
     ^
domctl.c:373:84: error: assignment discards ‘const’ qualifier from pointer target type [-Werror]
     SWAP(new.cp, d->arch.cpuid);
                                                                                    ^
domctl.c:374:80: error: assignment discards ‘const’ qualifier from pointer target type [-Werror]
     SWAP(new.dp, d->arch.msr);
                                                                                ^
domctl.c:375:80: error: assignment discards ‘const’ qualifier from pointer target type [-Werror]
     SWAP(new.vp, v->arch.msr);
                                                                                ^
domctl.c:391:11: error: passing argument 1 of ‘xfree’ discards ‘const’ qualifier from pointer target type [-Werror]
     xfree(new.cp);
           ^
In file included from /local/xen.git/xen/include/xen/lib.h:7:0,
                 from domctl.c:8:
/local/xen.git/xen/include/xen/xmalloc.h:34:13: note: expected ‘void *’ but argument is of type ‘const struct cpuid_policy *’
 extern void xfree(void *);
             ^
domctl.c:392:11: error: passing argument 1 of ‘xfree’ discards ‘const’ qualifier from pointer target type [-Werror]
     xfree(new.dp);
           ^
In file included from /local/xen.git/xen/include/xen/lib.h:7:0,
                 from domctl.c:8:
/local/xen.git/xen/include/xen/xmalloc.h:34:13: note: expected ‘void *’ but argument is of type ‘const struct msr_domain_policy *’
 extern void xfree(void *);
             ^
domctl.c:393:11: error: passing argument 1 of ‘xfree’ discards ‘const’ qualifier from pointer target type [-Werror]
     xfree(new.vp);
           ^
In file included from /local/xen.git/xen/include/xen/lib.h:7:0,
                 from domctl.c:8:
/local/xen.git/xen/include/xen/xmalloc.h:34:13: note: expected ‘void *’ but argument is of type ‘const struct msr_vcpu_policy *’
 extern void xfree(void *);
             ^
cc1: all warnings being treated as errors


Furthermore, while x86_policies_are_compatible() isn't intended to
modify the policies, the other important function for levelling
(x86_calculate_compatible_policy(a, b, out)) will write to its parameter.

>
>>>> @@ -318,6 +328,74 @@ long arch_do_sysctl(
>>>>          break;
>>>>      }
>>>>  
>>>> +    case XEN_SYSCTL_get_cpumsr_policy:
>>>> +    {
>>>> +        const struct policy_group *group;
>>>> +
>>>> +        /* Bad policy index? */
>>>> +        if ( sysctl->u.cpumsr_policy.index >= ARRAY_SIZE(system_policies) )
>>>> +        {
>>>> +            ret = -EINVAL;
>>>> +            break;
>>>> +        }
>>>> +        group = &system_policies[sysctl->u.cpumsr_policy.index];
>>> Isn't this introducing at least half of a Spectre v1 gadget?
>> Nope :(
>>
>> It's both halves of the Spectre gadget, when you account for the
>> dereference when calling x86_*_copy_to_buffer() slightly lower.
>>
>> I suppose we want to port the Linux array nospec lookup logic so we can
>> protect the clearly-visible gadgets.
> I'm confused: You first say "nope", but the rest of your response reads
> as if you meant "yes.".

"No its not half a gadget.  Its a full gadget".

>
>>>> --- a/xen/include/public/sysctl.h
>>>> +++ b/xen/include/public/sysctl.h
>>>> @@ -1063,6 +1063,43 @@ struct xen_sysctl_set_parameter {
>>>>      uint16_t pad[3];                        /* IN: MUST be zero. */
>>>>  };
>>>>  
>>>> +#if defined(__i386__) || defined(__x86_64__)
>>>> +/*
>>>> + * XEN_SYSCTL_get_cpumsr_policy (x86 specific)
>>> Perhaps express the "x86 specific" also in the opcode name? And make
>>> more obvious that this is about CPUID and MSRs at the same time? E.g.
>>> XEN_SYSCTL_x86_get_cpuid_msr_policy?
>>>
>>> I'm sure you have reasons to munge it all into a single operation.
>> (Answering in reverse order)
>>
>> The get operations don't strictly need to be a single operation.  The
>> set operation specifically must be a single operation, and the getters
>> have an interface to match.
>>
>> As for naming, cpumsr_policy wasn't chosen by me, but I can't think of
>> anything better.  The code is currently consistent and, while I'm open
>> to a rename, it will impact large quantities of the series.
>>
>> One concern I have if we end up with a new block of information.  I was
>> hoping for a generic name, but simply "policy" on its own is too
>> generic.  cpumsr is, I believe, a contraction of cpuid_msr to avoid
>> excessive code volume.
>>
>> Suggestions welcome.
> To cover potential future additions, why not XEN_SYSCTL_get_cpu_policy?
> That's neither misleading by abbreviating too much, nor more specific than
> we need it to be. However, in this case it might be worthwhile to consider
> adding in "x86", as ARM might plausibly want something similar at some
> point. Otoh the same name (but different structure contents) could be
> used for both.

Hmm - I suppose "cpu policy" does logically cover any and all of the
main core, without including any of the uncore or chipset, which matches
the intended purpose.

I'll see about applying this naming scheme consistently across the series.

Julien/Stefano: Are you liable to want something like this on ARM?

>
>>>> +struct xen_sysctl_cpumsr_policy {
>>>> +#define XEN_SYSCTL_cpumsr_policy_raw          0
>>>> +#define XEN_SYSCTL_cpumsr_policy_host         1
>>>> +#define XEN_SYSCTL_cpumsr_policy_pv_max       2
>>>> +#define XEN_SYSCTL_cpumsr_policy_hvm_max      3
>>>> +#define XEN_SYSCTL_cpumsr_policy_pv_default   4
>>>> +#define XEN_SYSCTL_cpumsr_policy_hvm_default  5
>>>> +    uint32_t index;       /* IN: Which policy to query? */
>>>> +    uint32_t nr_leaves;   /* IN/OUT: Number of leaves in/written to
>>>> +                           * 'cpuid_policy', or the maximum number of leaves if
>>>> +                           * any of the guest handles is NULL.
>>>> +                           * NB. All policies come from the same space,
>>>> +                           * so have the same maximum length. */
>>>> +    uint32_t nr_msrs;     /* IN/OUT: Number of MSRs in/written to
>>>> +                           * 'msr_domain_policy', or the maximum number of MSRs
>>>> +                           * if any of the guest handles is NULL.
>>>> +                           * NB. All policies come from the same space,
>>>> +                           * so have the same maximum length. */
>>>> +    XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_policy; /* OUT: */
>>> Explicit padding (checked to be zero in the handler) above here
>>> please.
>> Why?  SYSCTLs are unstable and we don't perform similar checks for other
>> subops.
> You don't like the interface version bumps anyway, as being only
> partly useful. If you added and checked explicit padding, no bump
> would be needed once the field gains meaning.

Right, but possibly the only thing worse than an interface version of
questionable utility is inconsistent ABI expectations across different
subops of an otherwise consistent hypercall.

In principle I'd like to improve the ABI expectations of these ops, but
a) we need something much better than this suggestion, and b) I'm not
going to get diverted into fixing that rats nest as part of this series.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply related	[flat|nested] 67+ messages in thread

* Re: [PATCH 10/13] x86/domctl: Implement XEN_DOMCTL_get_cpumsr_policy
  2018-07-03 20:55 ` [PATCH 10/13] x86/domctl: Implement XEN_DOMCTL_get_cpumsr_policy Andrew Cooper
  2018-07-04  9:48   ` Jan Beulich
@ 2018-07-05 14:23   ` Sergey Dyasli
  1 sibling, 0 replies; 67+ messages in thread
From: Sergey Dyasli @ 2018-07-05 14:23 UTC (permalink / raw)
  To: Andrew Cooper, xen-devel
  Cc: Sergey Dyasli, Wei Liu, JBeulich, Ian Jackson, dgdegra, Roger Pau Monne

On Tue, 2018-07-03 at 21:55 +0100, Andrew Cooper wrote:
> From: Sergey Dyasli <sergey.dyasli@citrix.com>
> 
> This finally (after literally years of work!) marks the point where the
> toolstack can ask the hypervisor for the current CPUID configuration of a
> specific domain.
> 
> Also extend xen-cpuid's --policy mode to be able to take a domid and dump a
> specific domains CPUID and MSR policy.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> Signed-off-by: Sergey Dyasli <sergey.dyasli@citrix.com>
> ---
> 
> diff --git a/tools/misc/xen-cpuid.c b/tools/misc/xen-cpuid.c
> index a5b3004..52a3694 100644
> --- a/tools/misc/xen-cpuid.c
> +++ b/tools/misc/xen-cpuid.c
...
> @@ -407,17 +434,36 @@ int main(int argc, char **argv)
>          if ( !msrs )
>              err(1, "calloc(max_msrs)");
>  
> -        for ( pol = 0; pol < ARRAY_SIZE(sys_policies); ++pol )
> +        if ( domid != -1 )
>          {
> +            char name[20];
>              uint32_t nr_leaves = max_leaves;
>              uint32_t nr_msrs = max_msrs;
>  
> -            if ( xc_get_system_cpumsr_policy(xch, pol, &nr_leaves, leaves,
> +            if ( xc_get_domain_cpumsr_policy(xch, domid, &nr_leaves, leaves,
>                                               &nr_msrs, msrs) )
> -                err(1, "xc_get_system_cpumsr_policy(, %s,,)",
> -                    sys_policies[pol]);
> +                err(1, "xc_get_domain_cpuid_policy(, %d, %d,, %d,)",
                                         ^^^^^
This wants to be "cpumsr" for consistency.

> +                    domid, nr_leaves, nr_msrs);
>  
> -            print_policy(sys_policies[pol], leaves, nr_leaves, msrs, nr_msrs);
> +            snprintf(name, sizeof(name), "Domain %d", domid);
> +            print_policy(name, leaves, nr_leaves, msrs, nr_msrs);
> +        }
> +        else
> +        {
> +            /* Get system policies */
> +            for ( pol = 0; pol < ARRAY_SIZE(sys_policies); ++pol )
> +            {
> +                uint32_t nr_leaves = max_leaves;
> +                uint32_t nr_msrs = max_msrs;
> +
> +                if ( xc_get_system_cpumsr_policy(xch, pol, &nr_leaves, leaves,
> +                                                 &nr_msrs, msrs) )
> +                    err(1, "xc_get_system_cpumsr_policy(, %s,,)",
> +                        sys_policies[pol]);
> +
> +                print_policy(sys_policies[pol], leaves, nr_leaves,
> +                             msrs, nr_msrs);
> +            }
>          }
>  
>          free(leaves);
> 
-- 
Thanks,
Sergey
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 09/13] x86/sysctl: Implement XEN_SYSCTL_get_cpumsr_policy
  2018-07-05 14:08         ` Andrew Cooper
@ 2018-07-05 14:45           ` Jan Beulich
  0 siblings, 0 replies; 67+ messages in thread
From: Jan Beulich @ 2018-07-05 14:45 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Stefano Stabellini, Wei Liu, Ian Jackson,
	Xen-devel, Julien Grall, Daniel de Graaf, Roger Pau Monne

>>> On 05.07.18 at 16:08, <andrew.cooper3@citrix.com> wrote:
> On 05/07/18 10:08, Jan Beulich wrote:
>>>>> On 04.07.18 at 19:57, <andrew.cooper3@citrix.com> wrote:
>>> On 04/07/18 10:43, Jan Beulich wrote:
>>>> And with this I now
>>>> wonder whether the pointers in struct policy_group shouldn't all
>>>> be const qualified.
>>> Unfortunately that doesn't work with the logic to create a policy_group
>>> for an individual domain during audit.
>> I don't understand: Is x86_policies_are_compatible() supposed to
>> alter the policies? Otherwise, if you maintained local separate
>> pointers in update_domain_cpumsr_policy(), using "new" just for
>> the purpose of passing to x86_policies_are_compatible(), all
>> should be fine and it would be crystal clear that anyone handed
>> a group won't alter anything the group refers to.
> 
> With this diff:
> 
> diff --git a/xen/include/xen/libx86/policies.h
> b/xen/include/xen/libx86/policies.h
> index 21e0a40..03fe6dd 100644
> --- a/xen/include/xen/libx86/policies.h
> +++ b/xen/include/xen/libx86/policies.h
> @@ -7,9 +7,9 @@
>  
>  struct policy_group
>  {
> -    struct cpuid_policy *cp;
> -    struct msr_domain_policy *dp;
> -    struct msr_vcpu_policy *vp;
> +    const struct cpuid_policy *cp;
> +    const struct msr_domain_policy *dp;
> +    const struct msr_vcpu_policy *vp;
>  };
>  
>  /*
> 
> The resulting compiler complains are
> 
> domctl.c: In function ‘update_domain_cpumsr_policy’:
> domctl.c:355:15: error: passing argument 1 of ‘x86_cpuid_copy_from_buffer’ 
> discards ‘const’ qualifier from pointer target type [-Werror]
>                new.cp, xdpc->cpuid_policy, xdpc->nr_leaves,
>                ^
> In file included from /local/xen.git/xen/include/asm/cpuid.h:11:0,
>                  from /local/xen.git/xen/include/asm/cpufeature.h:10,
>                  from /local/xen.git/xen/include/asm/processor.h:14,
>                  from /local/xen.git/xen/include/asm/system.h:6,
>                  from /local/xen.git/xen/include/xen/list.h:11,
>                  from /local/xen.git/xen/include/xen/mm.h:50,
>                  from domctl.c:9:
> /local/xen.git/xen/include/xen/libx86/cpuid.h:257:5: note: expected ‘struct 
> cpuid_policy *’ but argument is of type ‘const struct cpuid_policy *’
>  int x86_cpuid_copy_from_buffer(struct cpuid_policy *p,
>      ^
> domctl.c:360:15: error: passing argument 1 of ‘x86_msr_copy_from_buffer’ 
> discards ‘const’ qualifier from pointer target type [-Werror]
>                new.dp, new.vp,
>                ^

As said - you'd need local variables being pointers to non-const, and
"new" should be used solely for handing the entire pack to the
auditing function.

> Furthermore, while x86_policies_are_compatible() isn't intended to
> modify the policies, the other important function for levelling
> (x86_calculate_compatible_policy(a, b, out)) will write to its parameter.

Hmm, that's unfortunate. I'd really like to have a way to make sure
(not just by commentary) that checking functions can't alter their
inputs. I agree though that having a second container structure
doesn't look very appealing.

>>>>> @@ -318,6 +328,74 @@ long arch_do_sysctl(
>>>>>          break;
>>>>>      }
>>>>>  
>>>>> +    case XEN_SYSCTL_get_cpumsr_policy:
>>>>> +    {
>>>>> +        const struct policy_group *group;
>>>>> +
>>>>> +        /* Bad policy index? */
>>>>> +        if ( sysctl->u.cpumsr_policy.index >= ARRAY_SIZE(system_policies) )
>>>>> +        {
>>>>> +            ret = -EINVAL;
>>>>> +            break;
>>>>> +        }
>>>>> +        group = &system_policies[sysctl->u.cpumsr_policy.index];
>>>> Isn't this introducing at least half of a Spectre v1 gadget?
>>> Nope :(
>>>
>>> It's both halves of the Spectre gadget, when you account for the
>>> dereference when calling x86_*_copy_to_buffer() slightly lower.
>>>
>>> I suppose we want to port the Linux array nospec lookup logic so we can
>>> protect the clearly-visible gadgets.
>> I'm confused: You first say "nope", but the rest of your response reads
>> as if you meant "yes.".
> 
> "No its not half a gadget.  Its a full gadget".

Right - as I hadn't checked further, I did write "at least".

>>>>> +struct xen_sysctl_cpumsr_policy {
>>>>> +#define XEN_SYSCTL_cpumsr_policy_raw          0
>>>>> +#define XEN_SYSCTL_cpumsr_policy_host         1
>>>>> +#define XEN_SYSCTL_cpumsr_policy_pv_max       2
>>>>> +#define XEN_SYSCTL_cpumsr_policy_hvm_max      3
>>>>> +#define XEN_SYSCTL_cpumsr_policy_pv_default   4
>>>>> +#define XEN_SYSCTL_cpumsr_policy_hvm_default  5
>>>>> +    uint32_t index;       /* IN: Which policy to query? */
>>>>> +    uint32_t nr_leaves;   /* IN/OUT: Number of leaves in/written to
>>>>> +                           * 'cpuid_policy', or the maximum number of leaves if
>>>>> +                           * any of the guest handles is NULL.
>>>>> +                           * NB. All policies come from the same space,
>>>>> +                           * so have the same maximum length. */
>>>>> +    uint32_t nr_msrs;     /* IN/OUT: Number of MSRs in/written to
>>>>> +                           * 'msr_domain_policy', or the maximum number of MSRs
>>>>> +                           * if any of the guest handles is NULL.
>>>>> +                           * NB. All policies come from the same space,
>>>>> +                           * so have the same maximum length. */
>>>>> +    XEN_GUEST_HANDLE_64(xen_cpuid_leaf_t) cpuid_policy; /* OUT: */
>>>> Explicit padding (checked to be zero in the handler) above here
>>>> please.
>>> Why?  SYSCTLs are unstable and we don't perform similar checks for other
>>> subops.
>> You don't like the interface version bumps anyway, as being only
>> partly useful. If you added and checked explicit padding, no bump
>> would be needed once the field gains meaning.
> 
> Right, but possibly the only thing worse than an interface version of
> questionable utility is inconsistent ABI expectations across different
> subops of an otherwise consistent hypercall.
> 
> In principle I'd like to improve the ABI expectations of these ops, but
> a) we need something much better than this suggestion, and b) I'm not
> going to get diverted into fixing that rats nest as part of this series.

I can't help a), but as to b) you certainly shouldn't, yet my frequently
made remark applies here perfectly well: Let's not use bad examples
as excuse to widen the badness. As to consistency, it only took me
looking at the first few lines of sysctl.h to find padding fields in
xen_sysctl_readconsole (I didn't go look whether there's also checking
for them to be zero on input, but the latest for the live patching
sysctl you'll find that padding is validated to be zero).

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 13/13] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy
  2018-07-05  9:28       ` Jan Beulich
@ 2018-07-05 17:55         ` Andrew Cooper
  2018-07-06  7:51           ` Jan Beulich
  0 siblings, 1 reply; 67+ messages in thread
From: Andrew Cooper @ 2018-07-05 17:55 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Daniel de Graaf,
	Roger Pau Monne

On 05/07/18 10:28, Jan Beulich wrote:
>
>>>> +    /*
>>>> +     * Audit was successful.  Replace existing policies, leaving the old
>>>> +     * policies to be freed.
>>>> +     */
>>>> +    SWAP(new.cp, d->arch.cpuid);
>>>> +    SWAP(new.dp, d->arch.msr);
>>>> +    SWAP(new.vp, v->arch.msr);
>>>> +
>>>> +    /* Merge the (now audited) vCPU MSRs into every other msr_vcpu_policy. */
>>>> +    for ( ; v; v = v->next_in_list )
>>> This open-coded almost-for_each_domain() doesn't look very nice.
>> ITYM for_each_vcpu()
> Oops, of course.
>
>> And yes, but for_each_vcpu() is wrong to use here, and we don't have a
>> for_each_vcpu_other_than_0() helper.
> Perhaps still better to do
>
>     for_each_vcpu(d, v)
>     {
>         if ( v->vcpu_id == 0 )
>             continue;
>         ...
>     }
>
> ?

Do you think that looks cleaner? I doubt the compiler can optimise that
into my version.

>
>>>> +    {
>>>> +        /* XXX - Figure out how to avoid a TOCTOU race here.  XLAT area? */
>>>> +        if ( (ret = x86_msr_copy_from_buffer(
>>>> +                  NULL, v->arch.msr, xdpc->msr_policy, xdpc->nr_msrs, NULL)) )
>>> Why can't you go from vCPU 0's v->arch.msr here, which is the copied-in
>>> (and sanitized) representation already? Also, is it really a good idea to
>>> assume all vCPU-s have the same policies?
>> There are multiple colliding issues which lead to this code, but as
>> several people have pointed out, its probably over the top.
>>
>> First, as to the same policy.  This hypercall can currently only be used
>> before the vcpu has started executing.
>>
>> As such, it is setting the init state of the MSRs from the guests point
>> of view, and there is exactly one MSR I'm aware of which has an init
>> value which depends on the core (that being APIC_BASE.BSP which can
>> trivially be handled in Xen).  All other MSRs have identical init state
>> AFAICT, and I don't want to create an interface which makes it easy to
>> accidentally end up with wrong values.
> So what about migration? There are certainly differing incoming values
> there. Of course there's the MSRs restore record, but no atomic sanity
> check between those and the policy here is possible.

Migration is still a problem.  This CPUID/MSR work is the next step on
the path to fixing the "state before policy" problem we've got when
restoring a guest.

Once we have a working CPUID and R/O MSR configuration "blob" which the
toolstack can manipulate, we can (in Xen) require that the toolstack
provide the blob before memory and R/W register state.

When we get to that point, the toolstack shall call
DOMCTL_get_cpumsr_policy (modulo whatever plan I device to fix our R/W
MSR from the VCPU state problem) and place this ahead of the main
memory/register state in the migration stream.

The receiving side will either feed the blob back to Xen, or fabricate
the policy out of thin air at this point.  The current behaviour is to
fabricate a policy out of thin air after all migration stream is
complete, but before unpausing the domain.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 01/13] libx86: Introduce libx86/cpuid.h
  2018-07-04 13:57       ` Jan Beulich
@ 2018-07-06  1:35         ` Doug Goldstein
  2018-07-06  8:07           ` Jan Beulich
  0 siblings, 1 reply; 67+ messages in thread
From: Doug Goldstein @ 2018-07-06  1:35 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Xen-devel,
	Roger Pau Monne

On Wed, Jul 04, 2018 at 07:57:30AM -0600, Jan Beulich wrote:
> >>> On 04.07.18 at 14:03, <andrew.cooper3@citrix.com> wrote:
> > On 04/07/18 09:21, Jan Beulich wrote:
> >>>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
> >>> --- a/tools/include/Makefile
> >>> +++ b/tools/include/Makefile
> >>> @@ -21,6 +21,9 @@ xen/.dir:
> >>>  	ln -sf $(addprefix $(XEN_ROOT)/xen/include/xen/,libelf.h elfstructs.h) xen/libelf/
> >>>  	ln -s ../xen-foreign xen/foreign
> >>>  	ln -sf $(XEN_ROOT)/xen/include/acpi acpi
> >>> +ifeq ($(CONFIG_X86),y)
> >>> +	ln -sf $(XEN_ROOT)/xen/include/xen/libx86 xen/libx86
> >>> +endif
> >> Why not set the include path suitably?
> > 
> > Because this is how everything else is currently done.  If we want to
> > change how tools get their hypervisor header files, that should be
> > independent work.
> 
> How this gets done here has no direct implications on pre-existing
> mechanisms.

While not wrong refactoring the build system appears to be orthogonal to
the entire series. This had been proposed before when I tried to
separate the xen and tools build systems apart before and I do not
recall why it wasn't done.

In short don't block this series on this item.

--
Doug

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 13/13] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy
  2018-07-05 17:55         ` Andrew Cooper
@ 2018-07-06  7:51           ` Jan Beulich
  2018-07-06 10:02             ` Andrew Cooper
  0 siblings, 1 reply; 67+ messages in thread
From: Jan Beulich @ 2018-07-06  7:51 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Daniel de Graaf,
	Roger Pau Monne

>>> On 05.07.18 at 19:55, <andrew.cooper3@citrix.com> wrote:
> On 05/07/18 10:28, Jan Beulich wrote:
>>
>>>>> +    /*
>>>>> +     * Audit was successful.  Replace existing policies, leaving the old
>>>>> +     * policies to be freed.
>>>>> +     */
>>>>> +    SWAP(new.cp, d->arch.cpuid);
>>>>> +    SWAP(new.dp, d->arch.msr);
>>>>> +    SWAP(new.vp, v->arch.msr);
>>>>> +
>>>>> +    /* Merge the (now audited) vCPU MSRs into every other msr_vcpu_policy. */
>>>>> +    for ( ; v; v = v->next_in_list )
>>>> This open-coded almost-for_each_domain() doesn't look very nice.
>>> ITYM for_each_vcpu()
>> Oops, of course.
>>
>>> And yes, but for_each_vcpu() is wrong to use here, and we don't have a
>>> for_each_vcpu_other_than_0() helper.
>> Perhaps still better to do
>>
>>     for_each_vcpu(d, v)
>>     {
>>         if ( v->vcpu_id == 0 )
>>             continue;
>>         ...
>>     }
>>
>> ?
> 
> Do you think that looks cleaner?

Yes. There is exactly one other open coded use of next_in_list in x86
code (with the asm-offsets cleanup in place that I've just sent), and I'd
prefer to see that go away as well (but it's less obvious what a
reasonable replacement would look like there).

> I doubt the compiler can optimise that into my version.

I'm pretty sure it can't, but I'm also pretty sure it doesn't matter here.

>>>>> +    {
>>>>> +        /* XXX - Figure out how to avoid a TOCTOU race here.  XLAT area? */
>>>>> +        if ( (ret = x86_msr_copy_from_buffer(
>>>>> +                  NULL, v->arch.msr, xdpc->msr_policy, xdpc->nr_msrs, NULL)) )
>>>> Why can't you go from vCPU 0's v->arch.msr here, which is the copied-in
>>>> (and sanitized) representation already? Also, is it really a good idea to
>>>> assume all vCPU-s have the same policies?
>>> There are multiple colliding issues which lead to this code, but as
>>> several people have pointed out, its probably over the top.
>>>
>>> First, as to the same policy.  This hypercall can currently only be used
>>> before the vcpu has started executing.
>>>
>>> As such, it is setting the init state of the MSRs from the guests point
>>> of view, and there is exactly one MSR I'm aware of which has an init
>>> value which depends on the core (that being APIC_BASE.BSP which can
>>> trivially be handled in Xen).  All other MSRs have identical init state
>>> AFAICT, and I don't want to create an interface which makes it easy to
>>> accidentally end up with wrong values.
>> So what about migration? There are certainly differing incoming values
>> there. Of course there's the MSRs restore record, but no atomic sanity
>> check between those and the policy here is possible.
> 
> Migration is still a problem.  This CPUID/MSR work is the next step on
> the path to fixing the "state before policy" problem we've got when
> restoring a guest.
> 
> Once we have a working CPUID and R/O MSR configuration "blob" which the
> toolstack can manipulate, we can (in Xen) require that the toolstack
> provide the blob before memory and R/W register state.

Hmm, you talk about r/o MSRs here only, but this then covers the
domain policy object only when looking at what we currently have.
Both MSRs in the vCPU policy object are r/w ones, and hence I'd
like it to be at least clear what the interaction between the policy
and other MSR restore is supposed to be in the end.

This is in particular relevant wrt the derivation of data from vCPU 0
here. With what you do currently, you already make the code
dependent upon the MSRs record coming after the configuration
done here, or else the cloning of vCPU 0 register values would
clobber the intended (restored) ones.

> When we get to that point, the toolstack shall call
> DOMCTL_get_cpumsr_policy (modulo whatever plan I device to fix our R/W
> MSR from the VCPU state problem) and place this ahead of the main
> memory/register state in the migration stream.

It is perhaps the case that r/w MSRs weren't actually meant to go
into the policy structures?

> The receiving side will either feed the blob back to Xen, or fabricate
> the policy out of thin air at this point.  The current behaviour is to
> fabricate a policy out of thin air after all migration stream is
> complete, but before unpausing the domain.

I.e., as mentioned above, you clobber the values coming from the
CPU_MSR record. I don't think this can be the way to go, not even
temporarily.

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 01/13] libx86: Introduce libx86/cpuid.h
  2018-07-06  1:35         ` Doug Goldstein
@ 2018-07-06  8:07           ` Jan Beulich
  0 siblings, 0 replies; 67+ messages in thread
From: Jan Beulich @ 2018-07-06  8:07 UTC (permalink / raw)
  To: Doug Goldstein
  Cc: Sergey Dyasli, Wei Liu, Andrew Cooper, Ian Jackson, Xen-devel,
	Roger Pau Monne

>>> On 06.07.18 at 03:35, <cardoe@cardoe.com> wrote:
> On Wed, Jul 04, 2018 at 07:57:30AM -0600, Jan Beulich wrote:
>> >>> On 04.07.18 at 14:03, <andrew.cooper3@citrix.com> wrote:
>> > On 04/07/18 09:21, Jan Beulich wrote:
>> >>>>> On 03.07.18 at 22:55, <andrew.cooper3@citrix.com> wrote:
>> >>> --- a/tools/include/Makefile
>> >>> +++ b/tools/include/Makefile
>> >>> @@ -21,6 +21,9 @@ xen/.dir:
>> >>>  	ln -sf $(addprefix $(XEN_ROOT)/xen/include/xen/,libelf.h elfstructs.h) 
> xen/libelf/
>> >>>  	ln -s ../xen-foreign xen/foreign
>> >>>  	ln -sf $(XEN_ROOT)/xen/include/acpi acpi
>> >>> +ifeq ($(CONFIG_X86),y)
>> >>> +	ln -sf $(XEN_ROOT)/xen/include/xen/libx86 xen/libx86
>> >>> +endif
>> >> Why not set the include path suitably?
>> > 
>> > Because this is how everything else is currently done.  If we want to
>> > change how tools get their hypervisor header files, that should be
>> > independent work.
>> 
>> How this gets done here has no direct implications on pre-existing
>> mechanisms.
> 
> While not wrong refactoring the build system appears to be orthogonal to
> the entire series. This had been proposed before when I tried to
> separate the xen and tools build systems apart before and I do not
> recall why it wasn't done.

I don't understand: I've not said the current model needs refactoring
_in this series_ (it's likely worthwhile as an independent task). Leave as
is what is there, but don't tie yourself to doing new things the same way.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH 13/13] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy
  2018-07-06  7:51           ` Jan Beulich
@ 2018-07-06 10:02             ` Andrew Cooper
  0 siblings, 0 replies; 67+ messages in thread
From: Andrew Cooper @ 2018-07-06 10:02 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Sergey Dyasli, Wei Liu, Ian Jackson, Xen-devel, Daniel de Graaf,
	Roger Pau Monne

On 06/07/18 08:51, Jan Beulich wrote:
>
>>>>>> +    {
>>>>>> +        /* XXX - Figure out how to avoid a TOCTOU race here.  XLAT area? */
>>>>>> +        if ( (ret = x86_msr_copy_from_buffer(
>>>>>> +                  NULL, v->arch.msr, xdpc->msr_policy, xdpc->nr_msrs, NULL)) )
>>>>> Why can't you go from vCPU 0's v->arch.msr here, which is the copied-in
>>>>> (and sanitized) representation already? Also, is it really a good idea to
>>>>> assume all vCPU-s have the same policies?
>>>> There are multiple colliding issues which lead to this code, but as
>>>> several people have pointed out, its probably over the top.
>>>>
>>>> First, as to the same policy.  This hypercall can currently only be used
>>>> before the vcpu has started executing.
>>>>
>>>> As such, it is setting the init state of the MSRs from the guests point
>>>> of view, and there is exactly one MSR I'm aware of which has an init
>>>> value which depends on the core (that being APIC_BASE.BSP which can
>>>> trivially be handled in Xen).  All other MSRs have identical init state
>>>> AFAICT, and I don't want to create an interface which makes it easy to
>>>> accidentally end up with wrong values.
>>> So what about migration? There are certainly differing incoming values
>>> there. Of course there's the MSRs restore record, but no atomic sanity
>>> check between those and the policy here is possible.
>> Migration is still a problem.  This CPUID/MSR work is the next step on
>> the path to fixing the "state before policy" problem we've got when
>> restoring a guest.
>>
>> Once we have a working CPUID and R/O MSR configuration "blob" which the
>> toolstack can manipulate, we can (in Xen) require that the toolstack
>> provide the blob before memory and R/W register state.
> Hmm, you talk about r/o MSRs here only, but this then covers the
> domain policy object only when looking at what we currently have.
> Both MSRs in the vCPU policy object are r/w ones, and hence I'd
> like it to be at least clear what the interaction between the policy
> and other MSR restore is supposed to be in the end.
>
> This is in particular relevant wrt the derivation of data from vCPU 0
> here. With what you do currently, you already make the code
> dependent upon the MSRs record coming after the configuration
> done here, or else the cloning of vCPU 0 register values would
> clobber the intended (restored) ones.
>
>> When we get to that point, the toolstack shall call
>> DOMCTL_get_cpumsr_policy (modulo whatever plan I device to fix our R/W
>> MSR from the VCPU state problem) and place this ahead of the main
>> memory/register state in the migration stream.
> It is perhaps the case that r/w MSRs weren't actually meant to go
> into the policy structures?
>
>> The receiving side will either feed the blob back to Xen, or fabricate
>> the policy out of thin air at this point.  The current behaviour is to
>> fabricate a policy out of thin air after all migration stream is
>> complete, but before unpausing the domain.
> I.e., as mentioned above, you clobber the values coming from the
> CPU_MSR record. I don't think this can be the way to go, not even
> temporarily.

Jan and I have discussed this on IRC and have a plan.

The only reason msr_vcpu_policy was included in
XEN_DOMCTL_set_cpumsr_policy was for SGX_LC, and because SGX_LC
introduces some MSRs which may want to be RO domain-wide settings or RW
per-vcpu settings.  We can fix this by having an SGX_LC set in both
domain and vcpu blocks, as which block to use is determined by a
different RO setting.

As a result, we can retain the current separation of RO vs RW MSRs and
limit XEN_DOMCTL_set_cpumsr_policy to just the domain MSRs.  This
simplifies things massively, and still allows SGX_LC to coexist in a
fairly clean manner.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

^ permalink raw reply	[flat|nested] 67+ messages in thread

end of thread, other threads:[~2018-07-06 10:02 UTC | newest]

Thread overview: 67+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-03 20:55 [PATCH 00/13] x86: CPUID and MSR policy marshalling support Andrew Cooper
2018-07-03 20:55 ` [PATCH 01/13] libx86: Introduce libx86/cpuid.h Andrew Cooper
2018-07-04  6:54   ` Wei Liu
2018-07-04  8:21   ` Jan Beulich
2018-07-04 12:03     ` Andrew Cooper
2018-07-04 13:57       ` Jan Beulich
2018-07-06  1:35         ` Doug Goldstein
2018-07-06  8:07           ` Jan Beulich
2018-07-03 20:55 ` [PATCH 02/13] libx86: generate cpuid-autogen.h in the libx86 include dir Andrew Cooper
2018-07-04  7:03   ` Wei Liu
2018-07-04  8:33   ` Jan Beulich
2018-07-03 20:55 ` [PATCH 03/13] libx86: Share struct cpuid_policy with userspace Andrew Cooper
2018-07-04  7:08   ` Wei Liu
2018-07-04  8:36   ` Jan Beulich
2018-07-03 20:55 ` [PATCH 04/13] libx86: introduce a libx86 shared library Andrew Cooper
2018-07-04  7:20   ` Wei Liu
2018-07-04  8:42   ` Jan Beulich
2018-07-04 15:48     ` Andrew Cooper
2018-07-03 20:55 ` [PATCH 05/13] libx86: Introduce libx86/msr.h and share msr_{domain, vcpu}_policy with userspace Andrew Cooper
2018-07-04  7:21   ` Wei Liu
2018-07-04  8:43   ` Jan Beulich
2018-07-03 20:55 ` [PATCH 06/13] libx86: Introduce a helper to serialise a cpuid_policy object Andrew Cooper
2018-07-04  8:42   ` Wei Liu
2018-07-04  8:51     ` Jan Beulich
2018-07-04 16:23       ` Andrew Cooper
2018-07-05  8:09         ` Wei Liu
2018-07-05  8:40         ` Jan Beulich
2018-07-05 13:39           ` Andrew Cooper
2018-07-05 14:05             ` Jan Beulich
2018-07-04  9:01   ` Jan Beulich
2018-07-04 16:46     ` Andrew Cooper
2018-07-05  8:11       ` Wei Liu
2018-07-05 10:21         ` Andrew Cooper
2018-07-05  8:46       ` Jan Beulich
2018-07-05 13:34         ` Andrew Cooper
2018-07-03 20:55 ` [PATCH 07/13] libx86: Introduce a helper to serialise msr_{domain, vcpu}_policy objects Andrew Cooper
2018-07-04  9:16   ` Jan Beulich
2018-07-04 16:56     ` Andrew Cooper
2018-07-05  8:49       ` Jan Beulich
2018-07-03 20:55 ` [PATCH 08/13] x86: Collect policies together into groups Andrew Cooper
2018-07-04  9:22   ` Jan Beulich
2018-07-04 17:15     ` Andrew Cooper
2018-07-05  8:54       ` Jan Beulich
2018-07-03 20:55 ` [PATCH 09/13] x86/sysctl: Implement XEN_SYSCTL_get_cpumsr_policy Andrew Cooper
2018-07-04  9:43   ` Jan Beulich
2018-07-04 17:57     ` Andrew Cooper
2018-07-05  9:08       ` Jan Beulich
2018-07-05 14:08         ` Andrew Cooper
2018-07-05 14:45           ` Jan Beulich
2018-07-03 20:55 ` [PATCH 10/13] x86/domctl: Implement XEN_DOMCTL_get_cpumsr_policy Andrew Cooper
2018-07-04  9:48   ` Jan Beulich
2018-07-05 14:23   ` Sergey Dyasli
2018-07-03 20:55 ` [PATCH 11/13] libx86: Introduce a helper to deserialise a cpuid_policy object Andrew Cooper
2018-07-04  9:49   ` Jan Beulich
2018-07-03 20:55 ` [PATCH 12/13] libx86: introduce a helper to deserialize MSR policies Andrew Cooper
2018-07-03 20:55 ` [PATCH 13/13] x86/domctl: Implement XEN_DOMCTL_set_cpumsr_policy Andrew Cooper
2018-07-04 10:16   ` Jan Beulich
2018-07-04 18:47     ` Andrew Cooper
2018-07-05  9:28       ` Jan Beulich
2018-07-05 17:55         ` Andrew Cooper
2018-07-06  7:51           ` Jan Beulich
2018-07-06 10:02             ` Andrew Cooper
2018-07-04 10:18   ` Wei Liu
2018-07-04 10:33     ` Andrew Cooper
2018-07-04  8:17 ` [PATCH 00/13] x86: CPUID and MSR policy marshalling support Jan Beulich
2018-07-04 10:40   ` Andrew Cooper
2018-07-04 10:44     ` Jan Beulich

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.