xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 00/10] xsm: introducing domain roles
@ 2021-05-14 20:54 Daniel P. Smith
  2021-05-14 20:54 ` [RFC PATCH 01/10] headers: introduce new default privilege model Daniel P. Smith
                   ` (9 more replies)
  0 siblings, 10 replies; 16+ messages in thread
From: Daniel P. Smith @ 2021-05-14 20:54 UTC (permalink / raw)
  To: xen-devel
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, jbeulich, wl, roger.pau, tamas, tim, jgross,
	aisaila, ppircalabu, dfaggioli, paul, kevin.tian, dgdegra,
	adam.schwalm, scott.davis

During the hyperlaunch design sessions a request was made to come up with a
formal definition of the roles a domain was allowed to take on. In particular
the primary focus was to answer what is the control domain and what is the
hardware domain. Another comment came up during the discussion on PCI pass
through and how it would work in a disaggregated platform as what was being
proposed as a primary use case for hyperlaunch. Based on these concerns, the
hyperlaunch team took a hard look at what were all the roles that were either
explicitly defined in code, loosely defined in code, as well as those that were
more conceptual or required a solutions like Flask.

The result is that a set of seven explicitly assignable domain roles and three
implied domain roles were identified and defined. To provide for and enforce
these domain roles, it was identified that the core XSM system in fact existed
in this pseudo unsupported but supported existance. Depending on whether XSM
was turned on or off did not turn on or off the XSM hooks, it only deterimined
if the base "dummy policy module" was inlined in for the XSM hooks or if they
were made availble through the xsm_ops op dispatch structure.

This patch set starts with converting the existing security controls to using
the identified domain roles. It then moves to making the domain roles the core
enforcement mechanism for XSM and merging the split state of existance into an
equivalent of its supported form. With the conversion of XSM, the SILO policy
module is refactored to achieve its security goal as an extension of the domain
roles mechanism. The necessary adjustments are made to Flask and the Kconfig
system to support this work.

Due to the impact of this change, every effort was made to ensure the patch set
is bisectable and the features can be tested incrementally. This is an RFC with
limited building and testing completed against it, therefore one may find build
configurations and runtime configurations that do not work.

Daniel P. Smith (10):
  headers: introduce new default privilege model
  control domain: refactor is_control_domain
  xenstore: migrate to default privilege model
  xsm: convert rewrite privilege check function
  hardware domain: convert to domain roles
  xsm-roles: covert the dummy system to roles
  xsm-roles: adjusting core xsm
  xsm-silo: convert silo over to domain roles
  xsm-flask: clean up for domain roles conversion
  common/Kconfig: updating Kconfig for domain roles

 xen/arch/arm/dm.c                     |   2 +-
 xen/arch/arm/domctl.c                 |   6 +-
 xen/arch/arm/hvm.c                    |   2 +-
 xen/arch/arm/mm.c                     |   2 +-
 xen/arch/arm/platform_hypercall.c     |   2 +-
 xen/arch/x86/acpi/cpu_idle.c          |   3 +-
 xen/arch/x86/cpu/mcheck/mce.c         |   2 +-
 xen/arch/x86/cpu/mcheck/vmce.h        |   3 +-
 xen/arch/x86/cpu/vpmu.c               |   9 +-
 xen/arch/x86/crash.c                  |   2 +-
 xen/arch/x86/domctl.c                 |   8 +-
 xen/arch/x86/hvm/dm.c                 |   2 +-
 xen/arch/x86/hvm/hvm.c                |  12 +-
 xen/arch/x86/io_apic.c                |   9 +-
 xen/arch/x86/irq.c                    |   4 +-
 xen/arch/x86/mm.c                     |  22 +-
 xen/arch/x86/mm/mem_paging.c          |   2 +-
 xen/arch/x86/mm/mem_sharing.c         |   8 +-
 xen/arch/x86/mm/p2m.c                 |   2 +-
 xen/arch/x86/mm/paging.c              |   4 +-
 xen/arch/x86/mm/shadow/set.c          |   2 +-
 xen/arch/x86/msi.c                    |   6 +-
 xen/arch/x86/nmi.c                    |   3 +-
 xen/arch/x86/pci.c                    |   2 +-
 xen/arch/x86/physdev.c                |  16 +-
 xen/arch/x86/platform_hypercall.c     |  10 +-
 xen/arch/x86/pv/emul-priv-op.c        |   2 +-
 xen/arch/x86/setup.c                  |   3 +
 xen/arch/x86/sysctl.c                 |   4 +-
 xen/arch/x86/traps.c                  |   2 +-
 xen/arch/x86/x86_64/mm.c              |  11 +-
 xen/common/Kconfig                    |  14 +-
 xen/common/domain.c                   | 120 ++++-
 xen/common/domctl.c                   |  12 +-
 xen/common/event_channel.c            |  15 +-
 xen/common/grant_table.c              |  16 +-
 xen/common/hypfs.c                    |   2 +-
 xen/common/kernel.c                   |   2 +-
 xen/common/kexec.c                    |   4 +-
 xen/common/keyhandler.c               |   4 +-
 xen/common/mem_access.c               |   2 +-
 xen/common/memory.c                   |  16 +-
 xen/common/monitor.c                  |   2 +-
 xen/common/sched/core.c               |   6 +-
 xen/common/shutdown.c                 |  14 +-
 xen/common/sysctl.c                   |   8 +-
 xen/common/vm_event.c                 |   7 +-
 xen/common/xenoprof.c                 |   5 +-
 xen/drivers/char/console.c            |   2 +-
 xen/drivers/char/ns16550.c            |   3 +-
 xen/drivers/passthrough/device_tree.c |   4 +-
 xen/drivers/passthrough/pci.c         |  24 +-
 xen/drivers/passthrough/vtd/iommu.c   |   2 +-
 xen/include/xen/sched.h               |  30 +-
 xen/include/xsm/dummy.h               | 256 +++++-----
 xen/include/xsm/roles.h               |  70 +++
 xen/include/xsm/xsm.h                 | 710 +++++++++++++++++---------
 xen/xsm/Makefile                      |   3 +-
 xen/xsm/dummy.c                       | 160 ------
 xen/xsm/flask/flask_op.c              |   2 +-
 xen/xsm/silo.c                        |  22 +-
 xen/xsm/xsm_core.c                    |  46 +-
 62 files changed, 991 insertions(+), 759 deletions(-)
 create mode 100644 xen/include/xsm/roles.h
 delete mode 100644 xen/xsm/dummy.c

-- 
2.20.1



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

* [RFC PATCH 01/10] headers: introduce new default privilege model
  2021-05-14 20:54 [RFC PATCH 00/10] xsm: introducing domain roles Daniel P. Smith
@ 2021-05-14 20:54 ` Daniel P. Smith
  2021-06-18 13:56   ` Jan Beulich
  2021-05-14 20:54 ` [RFC PATCH 02/10] control domain: refactor is_control_domain Daniel P. Smith
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 16+ messages in thread
From: Daniel P. Smith @ 2021-05-14 20:54 UTC (permalink / raw)
  To: xen-devel
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, jbeulich, wl, roger.pau, tamas, tim, jgross,
	aisaila, ppircalabu, dfaggioli, paul, kevin.tian, dgdegra,
	adam.schwalm, scott.davis

This defines the new privilege roles that a domain may be assigned.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/include/xen/sched.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index cc633fdc07..9b2c277ede 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -457,6 +457,24 @@ struct domain
      */
     bool             creation_finished;
 
+    /* When SILO or Flask are not in use, a domain may have one or more roles
+     * that are desired for it to fulfill. To accomplish these role a set of
+     * privilege is required. A break down of the basic privilege is mapped
+     * to a bit field for assignment and verification.
+     */
+#define XSM_NONE      (1U<<0)  /* No role required to make the call */
+#define XSM_SELF      (1U<<1)  /* Allowed to make the call on self */
+#define XSM_TARGET    (1U<<2)  /* Allowed to make the call on a domain's target */
+#define XSM_PLAT_CTRL (1U<<3)  /* Platform Control: domain that control the overall platform */
+#define XSM_DOM_BUILD (1U<<4)  /* Domain Builder: domain that does domain construction and destruction */
+#define XSM_DOM_SUPER (1U<<5)  /* Domain Supervisor: domain that control the lifecycle, of all domains */
+#define XSM_DEV_EMUL  (1U<<6)  /* Device Emulator: domain that provides its target domain's device emulator */
+#define XSM_DEV_BACK  (1U<<7)  /* Device Backend: domain that provides a device backend */
+#define XSM_HW_CTRL   (1U<<8)  /* Hardware Control: domain with physical hardware access and its allocation for domain usage */
+#define XSM_HW_SUPER  (1U<<9)  /* Hardware Supervisor: domain that control allocated physical hardware */
+#define XSM_XENSTORE  (1U<<31) /* Xenstore: domain that can do privileged operations on xenstore */
+    uint32_t         xsm_roles;
+
     /* Which guest this guest has privileges on */
     struct domain   *target;
 
-- 
2.20.1



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

* [RFC PATCH 02/10] control domain: refactor is_control_domain
  2021-05-14 20:54 [RFC PATCH 00/10] xsm: introducing domain roles Daniel P. Smith
  2021-05-14 20:54 ` [RFC PATCH 01/10] headers: introduce new default privilege model Daniel P. Smith
@ 2021-05-14 20:54 ` Daniel P. Smith
  2021-06-18 14:02   ` Jan Beulich
  2021-05-14 20:54 ` [RFC PATCH 03/10] xenstore: migrate to default privilege model Daniel P. Smith
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 16+ messages in thread
From: Daniel P. Smith @ 2021-05-14 20:54 UTC (permalink / raw)
  To: xen-devel
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, jbeulich, wl, roger.pau, tamas, tim, jgross,
	aisaila, ppircalabu, dfaggioli, paul, kevin.tian, dgdegra,
	adam.schwalm, scott.davis

Move to using the new Domain Control role as the backing to the
is_control_domain check.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/common/domain.c     | 3 +++
 xen/include/xen/sched.h | 4 +++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/xen/common/domain.c b/xen/common/domain.c
index cdda0d1f29..26bba8666d 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -556,6 +556,9 @@ struct domain *domain_create(domid_t domid,
     /* Sort out our idea of is_control_domain(). */
     d->is_privileged = is_priv;
 
+    if (is_priv)
+        d->xsm_roles = CLASSIC_DOM0_PRIVS;
+
     /* Sort out our idea of is_hardware_domain(). */
     if ( domid == 0 || domid == hardware_domid )
     {
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 9b2c277ede..66b79d9c9f 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -473,6 +473,8 @@ struct domain
 #define XSM_HW_CTRL   (1U<<8)  /* Hardware Control: domain with physical hardware access and its allocation for domain usage */
 #define XSM_HW_SUPER  (1U<<9)  /* Hardware Supervisor: domain that control allocated physical hardware */
 #define XSM_XENSTORE  (1U<<31) /* Xenstore: domain that can do privileged operations on xenstore */
+#define CLASSIC_DOM0_PRIVS (XSM_PLAT_CTRL | XSM_DOM_BUILD | XSM_DOM_SUPER | \
+		XSM_DEV_EMUL | XSM_HW_CTRL | XSM_HW_SUPER | XSM_XENSTORE)
     uint32_t         xsm_roles;
 
     /* Which guest this guest has privileges on */
@@ -1049,7 +1051,7 @@ static always_inline bool is_control_domain(const struct domain *d)
     if ( IS_ENABLED(CONFIG_PV_SHIM_EXCLUSIVE) )
         return false;
 
-    return evaluate_nospec(d->is_privileged);
+    return evaluate_nospec(d->xsm_roles & XSM_DOM_SUPER);
 }
 
 #define VM_ASSIST(d, t) (test_bit(VMASST_TYPE_ ## t, &(d)->vm_assist))
-- 
2.20.1



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

* [RFC PATCH 03/10] xenstore: migrate to default privilege model
  2021-05-14 20:54 [RFC PATCH 00/10] xsm: introducing domain roles Daniel P. Smith
  2021-05-14 20:54 ` [RFC PATCH 01/10] headers: introduce new default privilege model Daniel P. Smith
  2021-05-14 20:54 ` [RFC PATCH 02/10] control domain: refactor is_control_domain Daniel P. Smith
@ 2021-05-14 20:54 ` Daniel P. Smith
  2021-05-14 20:54 ` [RFC PATCH 04/10] xsm: convert rewrite privilege check function Daniel P. Smith
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Daniel P. Smith @ 2021-05-14 20:54 UTC (permalink / raw)
  To: xen-devel
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, jbeulich, wl, roger.pau, tamas, tim, jgross,
	aisaila, ppircalabu, dfaggioli, paul, kevin.tian, dgdegra,
	adam.schwalm, scott.davis

Move to using a check for the Xenstore Domain role for the is_xenstore_domain
check.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/common/domain.c     | 3 +++
 xen/include/xen/sched.h | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/xen/common/domain.c b/xen/common/domain.c
index 26bba8666d..1f2c569e5d 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -551,6 +551,9 @@ struct domain *domain_create(domid_t domid,
     {
         d->options = config->flags;
         d->vmtrace_size = config->vmtrace_size;
+
+        if (config->flags & XEN_DOMCTL_CDF_xs_domain)
+            d->xsm_roles = XSM_XENSTORE;
     }
 
     /* Sort out our idea of is_control_domain(). */
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 66b79d9c9f..9a88e5b00f 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -1129,7 +1129,7 @@ static inline bool is_vcpu_online(const struct vcpu *v)
 
 static inline bool is_xenstore_domain(const struct domain *d)
 {
-    return d->options & XEN_DOMCTL_CDF_xs_domain;
+    return d->xsm_roles & XSM_XENSTORE;
 }
 
 static always_inline bool is_iommu_enabled(const struct domain *d)
-- 
2.20.1



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

* [RFC PATCH 04/10] xsm: convert rewrite privilege check function
  2021-05-14 20:54 [RFC PATCH 00/10] xsm: introducing domain roles Daniel P. Smith
                   ` (2 preceding siblings ...)
  2021-05-14 20:54 ` [RFC PATCH 03/10] xenstore: migrate to default privilege model Daniel P. Smith
@ 2021-05-14 20:54 ` Daniel P. Smith
  2021-06-18 14:14   ` Jan Beulich
  2021-05-14 20:54 ` [RFC PATCH 05/10] hardware domain: convert to domain roles Daniel P. Smith
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 16+ messages in thread
From: Daniel P. Smith @ 2021-05-14 20:54 UTC (permalink / raw)
  To: xen-devel
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, jbeulich, wl, roger.pau, tamas, tim, jgross,
	aisaila, ppircalabu, dfaggioli, paul, kevin.tian, dgdegra,
	adam.schwalm, scott.davis

This converts the previous XSM hook dummy checks over to using equivalent domain role privileges.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/arch/arm/dm.c                     |   2 +-
 xen/arch/arm/domctl.c                 |   6 +-
 xen/arch/arm/hvm.c                    |   2 +-
 xen/arch/arm/mm.c                     |   2 +-
 xen/arch/arm/platform_hypercall.c     |   2 +-
 xen/arch/x86/cpu/mcheck/mce.c         |   2 +-
 xen/arch/x86/cpu/vpmu.c               |   2 +-
 xen/arch/x86/domctl.c                 |   8 +-
 xen/arch/x86/hvm/dm.c                 |   2 +-
 xen/arch/x86/hvm/hvm.c                |  12 +-
 xen/arch/x86/irq.c                    |   4 +-
 xen/arch/x86/mm.c                     |  20 +-
 xen/arch/x86/mm/mem_paging.c          |   2 +-
 xen/arch/x86/mm/mem_sharing.c         |   8 +-
 xen/arch/x86/mm/p2m.c                 |   2 +-
 xen/arch/x86/mm/paging.c              |   4 +-
 xen/arch/x86/mm/shadow/set.c          |   2 +-
 xen/arch/x86/msi.c                    |   2 +-
 xen/arch/x86/pci.c                    |   2 +-
 xen/arch/x86/physdev.c                |  16 +-
 xen/arch/x86/platform_hypercall.c     |  10 +-
 xen/arch/x86/pv/emul-priv-op.c        |   2 +-
 xen/arch/x86/sysctl.c                 |   4 +-
 xen/common/domain.c                   |   4 +-
 xen/common/domctl.c                   |  12 +-
 xen/common/event_channel.c            |  12 +-
 xen/common/grant_table.c              |  16 +-
 xen/common/hypfs.c                    |   2 +-
 xen/common/kernel.c                   |   2 +-
 xen/common/kexec.c                    |   2 +-
 xen/common/mem_access.c               |   2 +-
 xen/common/memory.c                   |  16 +-
 xen/common/monitor.c                  |   2 +-
 xen/common/sched/core.c               |   6 +-
 xen/common/sysctl.c                   |   8 +-
 xen/common/vm_event.c                 |   2 +-
 xen/common/xenoprof.c                 |   2 +-
 xen/drivers/char/console.c            |   2 +-
 xen/drivers/passthrough/device_tree.c |   4 +-
 xen/drivers/passthrough/pci.c         |  12 +-
 xen/include/xen/sched.h               |   6 +
 xen/include/xsm/dummy.h               | 256 ++++++++++++++------------
 xen/include/xsm/xsm.h                 |  13 +-
 43 files changed, 253 insertions(+), 246 deletions(-)

diff --git a/xen/arch/arm/dm.c b/xen/arch/arm/dm.c
index 1b3fd6bc7d..7bc2ec42f6 100644
--- a/xen/arch/arm/dm.c
+++ b/xen/arch/arm/dm.c
@@ -45,7 +45,7 @@ int dm_op(const struct dmop_args *op_args)
     if ( rc )
         return rc;
 
-    rc = xsm_dm_op(XSM_DM_PRIV, d);
+    rc = xsm_dm_op(DEV_EMU_PRIVS, d);
     if ( rc )
         goto out;
 
diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
index b7d27f37df..fff8829b9b 100644
--- a/xen/arch/arm/domctl.c
+++ b/xen/arch/arm/domctl.c
@@ -95,11 +95,11 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
          * done by the 2 hypercalls for consistency with other
          * architectures.
          */
-        rc = xsm_map_domain_irq(XSM_HOOK, d, irq, NULL);
+        rc = xsm_map_domain_irq(XSM_NONE, d, irq, NULL);
         if ( rc )
             return rc;
 
-        rc = xsm_bind_pt_irq(XSM_HOOK, d, bind);
+        rc = xsm_bind_pt_irq(XSM_NONE, d, bind);
         if ( rc )
             return rc;
 
@@ -130,7 +130,7 @@ long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
         if ( irq != virq )
             return -EINVAL;
 
-        rc = xsm_unbind_pt_irq(XSM_HOOK, d, bind);
+        rc = xsm_unbind_pt_irq(XSM_NONE, d, bind);
         if ( rc )
             return rc;
 
diff --git a/xen/arch/arm/hvm.c b/xen/arch/arm/hvm.c
index 8951b34086..ec84077988 100644
--- a/xen/arch/arm/hvm.c
+++ b/xen/arch/arm/hvm.c
@@ -101,7 +101,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
         if ( d == NULL )
             return -ESRCH;
 
-        rc = xsm_hvm_param(XSM_TARGET, d, op);
+        rc = xsm_hvm_param(TARGET_PRIVS, d, op);
         if ( rc )
             goto param_fail;
 
diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 59f8a3f15f..7e88d9b1c7 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -1446,7 +1446,7 @@ int xenmem_add_to_physmap_one(
             return -EINVAL;
         }
 
-        rc = xsm_map_gmfn_foreign(XSM_TARGET, d, od);
+        rc = xsm_map_gmfn_foreign(TARGET_PRIVS, d, od);
         if ( rc )
         {
             put_pg_owner(od);
diff --git a/xen/arch/arm/platform_hypercall.c b/xen/arch/arm/platform_hypercall.c
index 8efac7ee60..4913f65e13 100644
--- a/xen/arch/arm/platform_hypercall.c
+++ b/xen/arch/arm/platform_hypercall.c
@@ -33,7 +33,7 @@ long do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
     if ( d == NULL )
         return -ESRCH;
 
-    ret = xsm_platform_op(XSM_PRIV, op->cmd);
+    ret = xsm_platform_op(XSM_PLAT_CTRL, op->cmd);
     if ( ret )
         return ret;
 
diff --git a/xen/arch/x86/cpu/mcheck/mce.c b/xen/arch/x86/cpu/mcheck/mce.c
index 7f433343bc..f6ce05cba9 100644
--- a/xen/arch/x86/cpu/mcheck/mce.c
+++ b/xen/arch/x86/cpu/mcheck/mce.c
@@ -1376,7 +1376,7 @@ long do_mca(XEN_GUEST_HANDLE_PARAM(xen_mc_t) u_xen_mc)
     struct xen_mc_msrinject *mc_msrinject;
     struct xen_mc_mceinject *mc_mceinject;
 
-    ret = xsm_do_mca(XSM_PRIV);
+    ret = xsm_do_mca(XSM_PLAT_CTRL);
     if ( ret )
         return x86_mcerr("", ret);
 
diff --git a/xen/arch/x86/cpu/vpmu.c b/xen/arch/x86/cpu/vpmu.c
index d8659c63f8..612b87526b 100644
--- a/xen/arch/x86/cpu/vpmu.c
+++ b/xen/arch/x86/cpu/vpmu.c
@@ -706,7 +706,7 @@ long do_xenpmu_op(unsigned int op, XEN_GUEST_HANDLE_PARAM(xen_pmu_params_t) arg)
     if ( !opt_vpmu_enabled || has_vlapic(current->domain) )
         return -EOPNOTSUPP;
 
-    ret = xsm_pmu_op(XSM_OTHER, current->domain, op);
+    ret = xsm_pmu_op(XSM_NONE | XSM_DOM_SUPER, current->domain, op);
     if ( ret )
         return ret;
 
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index e440bd021e..5cbe55a700 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -234,7 +234,7 @@ long arch_do_domctl(
         if ( (fp + np) <= fp || (fp + np) > MAX_IOPORTS )
             ret = -EINVAL;
         else if ( !ioports_access_permitted(currd, fp, fp + np - 1) ||
-                  xsm_ioport_permission(XSM_HOOK, d, fp, fp + np - 1, allow) )
+                  xsm_ioport_permission(XSM_NONE, d, fp, fp + np - 1, allow) )
             ret = -EPERM;
         else if ( allow )
             ret = ioports_permit_access(d, fp, fp + np - 1);
@@ -534,7 +534,7 @@ long arch_do_domctl(
         if ( !is_hvm_domain(d) )
             break;
 
-        ret = xsm_bind_pt_irq(XSM_HOOK, d, bind);
+        ret = xsm_bind_pt_irq(XSM_NONE, d, bind);
         if ( ret )
             break;
 
@@ -569,7 +569,7 @@ long arch_do_domctl(
         if ( irq <= 0 || !irq_access_permitted(currd, irq) )
             break;
 
-        ret = xsm_unbind_pt_irq(XSM_HOOK, d, bind);
+        ret = xsm_unbind_pt_irq(XSM_NONE, d, bind);
         if ( ret )
             break;
 
@@ -616,7 +616,7 @@ long arch_do_domctl(
         if ( !ioports_access_permitted(currd, fmp, fmp + np - 1) )
             break;
 
-        ret = xsm_ioport_mapping(XSM_HOOK, d, fmp, fmp + np - 1, add);
+        ret = xsm_ioport_mapping(XSM_NONE, d, fmp, fmp + np - 1, add);
         if ( ret )
             break;
 
diff --git a/xen/arch/x86/hvm/dm.c b/xen/arch/x86/hvm/dm.c
index b60b9f3364..bc452b551e 100644
--- a/xen/arch/x86/hvm/dm.c
+++ b/xen/arch/x86/hvm/dm.c
@@ -370,7 +370,7 @@ int dm_op(const struct dmop_args *op_args)
     if ( !is_hvm_domain(d) )
         goto out;
 
-    rc = xsm_dm_op(XSM_DM_PRIV, d);
+    rc = xsm_dm_op(DEV_EMU_PRIVS, d);
     if ( rc )
         goto out;
 
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index ae37bc434a..7e9c624037 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -4064,7 +4064,7 @@ static int hvm_allow_set_param(struct domain *d,
     uint64_t value;
     int rc;
 
-    rc = xsm_hvm_param(XSM_TARGET, d, HVMOP_set_param);
+    rc = xsm_hvm_param(TARGET_PRIVS, d, HVMOP_set_param);
     if ( rc )
         return rc;
 
@@ -4211,7 +4211,7 @@ static int hvm_set_param(struct domain *d, uint32_t index, uint64_t value)
         rc = pmtimer_change_ioport(d, value);
         break;
     case HVM_PARAM_ALTP2M:
-        rc = xsm_hvm_param_altp2mhvm(XSM_PRIV, d);
+        rc = xsm_hvm_param_altp2mhvm(XSM_DOM_SUPER, d);
         if ( rc )
             break;
         if ( (value > XEN_ALTP2M_limited) ||
@@ -4340,7 +4340,7 @@ static int hvm_allow_get_param(struct domain *d,
 {
     int rc;
 
-    rc = xsm_hvm_param(XSM_TARGET, d, HVMOP_get_param);
+    rc = xsm_hvm_param(TARGET_PRIVS, d, HVMOP_get_param);
     if ( rc )
         return rc;
 
@@ -4550,7 +4550,7 @@ static int do_altp2m_op(
         goto out;
     }
 
-    if ( (rc = xsm_hvm_altp2mhvm_op(XSM_OTHER, d, mode, a.cmd)) )
+    if ( (rc = xsm_hvm_altp2mhvm_op(TARGET_PRIVS | DEV_EMU_PRIVS, d, mode, a.cmd)) )
         goto out;
 
     switch ( a.cmd )
@@ -4931,7 +4931,7 @@ static int hvmop_get_mem_type(
     if ( d == NULL )
         return -ESRCH;
 
-    rc = xsm_hvm_param(XSM_TARGET, d, HVMOP_get_mem_type);
+    rc = xsm_hvm_param(TARGET_PRIVS, d, HVMOP_get_mem_type);
     if ( rc )
         goto out;
 
@@ -5024,7 +5024,7 @@ long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
         if ( unlikely(d != current->domain) )
             rc = -EOPNOTSUPP;
         else if ( is_hvm_domain(d) && paging_mode_shadow(d) )
-            rc = xsm_hvm_param(XSM_TARGET, d, op);
+            rc = xsm_hvm_param(TARGET_PRIVS, d, op);
         if ( !rc )
             pagetable_dying(a.gpa);
 
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c
index a1693f92dd..cff7cb11cd 100644
--- a/xen/arch/x86/irq.c
+++ b/xen/arch/x86/irq.c
@@ -2122,7 +2122,7 @@ int map_domain_pirq(
         return 0;
     }
 
-    ret = xsm_map_domain_irq(XSM_HOOK, d, irq, data);
+    ret = xsm_map_domain_irq(XSM_NONE, d, irq, data);
     if ( ret )
     {
         dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d mapping to pirq %d\n",
@@ -2342,7 +2342,7 @@ int unmap_domain_pirq(struct domain *d, int pirq)
         nr = msi_desc->msi.nvec;
     }
 
-    ret = xsm_unmap_domain_irq(XSM_HOOK, d, irq,
+    ret = xsm_unmap_domain_irq(XSM_NONE, d, irq,
                                msi_desc ? msi_desc->dev : NULL);
     if ( ret )
         goto done;
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index b7a10bbdd4..8ecb982a84 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -977,7 +977,7 @@ get_page_from_l1e(
          * minor hack can go away.
          */
         if ( (real_pg_owner == NULL) || (pg_owner == l1e_owner) ||
-             xsm_priv_mapping(XSM_TARGET, pg_owner, real_pg_owner) )
+             xsm_priv_mapping(TARGET_PRIVS, pg_owner, real_pg_owner) )
         {
             gdprintk(XENLOG_WARNING,
                      "pg_owner d%d l1e_owner d%d, but real_pg_owner d%d\n",
@@ -3407,7 +3407,7 @@ long do_mmuext_op(
         return -EINVAL;
     }
 
-    rc = xsm_mmuext_op(XSM_TARGET, currd, pg_owner);
+    rc = xsm_mmuext_op(TARGET_PRIVS, currd, pg_owner);
     if ( rc )
     {
         put_pg_owner(pg_owner);
@@ -3497,7 +3497,7 @@ long do_mmuext_op(
                 break;
             }
 
-            rc = xsm_memory_pin_page(XSM_HOOK, currd, pg_owner, page);
+            rc = xsm_memory_pin_page(XSM_NONE, currd, pg_owner, page);
             if ( !rc && unlikely(test_and_set_bit(_PGT_pinned,
                                                   &page->u.inuse.type_info)) )
             {
@@ -4005,7 +4005,7 @@ long do_mmu_update(
             }
             if ( xsm_needed != xsm_checked )
             {
-                rc = xsm_mmu_update(XSM_TARGET, d, pt_owner, pg_owner, xsm_needed);
+                rc = xsm_mmu_update(TARGET_PRIVS, d, pt_owner, pg_owner, xsm_needed);
                 if ( rc )
                     break;
                 xsm_checked = xsm_needed;
@@ -4148,7 +4148,7 @@ long do_mmu_update(
             xsm_needed |= XSM_MMU_MACHPHYS_UPDATE;
             if ( xsm_needed != xsm_checked )
             {
-                rc = xsm_mmu_update(XSM_TARGET, d, NULL, pg_owner, xsm_needed);
+                rc = xsm_mmu_update(TARGET_PRIVS, d, NULL, pg_owner, xsm_needed);
                 if ( rc )
                     break;
                 xsm_checked = xsm_needed;
@@ -4393,7 +4393,7 @@ static int __do_update_va_mapping(
 
     perfc_incr(calls_to_update_va);
 
-    rc = xsm_update_va_mapping(XSM_TARGET, d, pg_owner, val);
+    rc = xsm_update_va_mapping(TARGET_PRIVS, d, pg_owner, val);
     if ( rc )
         return rc;
 
@@ -4632,7 +4632,7 @@ long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         if ( d == NULL )
             return -ESRCH;
 
-        rc = xsm_domain_memory_map(XSM_TARGET, d);
+        rc = xsm_domain_memory_map(TARGET_PRIVS, d);
         if ( rc )
         {
             rcu_unlock_domain(d);
@@ -4699,7 +4699,7 @@ long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         unsigned int i;
         bool store;
 
-        rc = xsm_machine_memory_map(XSM_PRIV);
+        rc = xsm_machine_memory_map(XSM_PLAT_CTRL);
         if ( rc )
             return rc;
 
@@ -4789,9 +4789,9 @@ long arch_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
             return -ESRCH;
 
         if ( cmd == XENMEM_set_pod_target )
-            rc = xsm_set_pod_target(XSM_PRIV, d);
+            rc = xsm_set_pod_target(XSM_DOM_SUPER, d);
         else
-            rc = xsm_get_pod_target(XSM_PRIV, d);
+            rc = xsm_get_pod_target(XSM_DOM_SUPER, d);
 
         if ( rc != 0 )
             goto pod_target_out_unlock;
diff --git a/xen/arch/x86/mm/mem_paging.c b/xen/arch/x86/mm/mem_paging.c
index 01281f786e..6f8420f988 100644
--- a/xen/arch/x86/mm/mem_paging.c
+++ b/xen/arch/x86/mm/mem_paging.c
@@ -452,7 +452,7 @@ int mem_paging_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_paging_op_t) arg)
     if ( rc )
         return rc;
 
-    rc = xsm_mem_paging(XSM_DM_PRIV, d);
+    rc = xsm_mem_paging(DEV_EMU_PRIVS, d);
     if ( rc )
         goto out;
 
diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c
index 98b14f7b0a..ba7a479de0 100644
--- a/xen/arch/x86/mm/mem_sharing.c
+++ b/xen/arch/x86/mm/mem_sharing.c
@@ -1883,7 +1883,7 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
     if ( rc )
         return rc;
 
-    rc = xsm_mem_sharing(XSM_DM_PRIV, d);
+    rc = xsm_mem_sharing(DEV_EMU_PRIVS, d);
     if ( rc )
         goto out;
 
@@ -1928,7 +1928,7 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
         if ( rc )
             goto out;
 
-        rc = xsm_mem_sharing_op(XSM_DM_PRIV, d, cd, mso.op);
+        rc = xsm_mem_sharing_op(DEV_EMU_PRIVS, d, cd, mso.op);
         if ( rc )
         {
             rcu_unlock_domain(cd);
@@ -1994,7 +1994,7 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
         if ( rc )
             goto out;
 
-        rc = xsm_mem_sharing_op(XSM_DM_PRIV, d, cd, mso.op);
+        rc = xsm_mem_sharing_op(DEV_EMU_PRIVS, d, cd, mso.op);
         if ( rc )
         {
             rcu_unlock_domain(cd);
@@ -2056,7 +2056,7 @@ int mem_sharing_memop(XEN_GUEST_HANDLE_PARAM(xen_mem_sharing_op_t) arg)
          * We reuse XENMEM_sharing_op_share XSM check here as this is
          * essentially the same concept repeated over multiple pages.
          */
-        rc = xsm_mem_sharing_op(XSM_DM_PRIV, d, cd,
+        rc = xsm_mem_sharing_op(DEV_EMU_PRIVS, d, cd,
                                 XENMEM_sharing_op_share);
         if ( rc )
         {
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 3840f167b0..5dc0aafd51 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -2611,7 +2611,7 @@ static int p2m_add_foreign(struct domain *tdom, unsigned long fgfn,
             goto out;
     }
 
-    rc = xsm_map_gmfn_foreign(XSM_TARGET, tdom, fdom);
+    rc = xsm_map_gmfn_foreign(TARGET_PRIVS, tdom, fdom);
     if ( rc )
         goto out;
 
diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c
index 8bc14df943..6db47c7101 100644
--- a/xen/arch/x86/mm/paging.c
+++ b/xen/arch/x86/mm/paging.c
@@ -712,7 +712,7 @@ int paging_domctl(struct domain *d, struct xen_domctl_shadow_op *sc,
         return -EBUSY;
     }
 
-    rc = xsm_shadow_control(XSM_HOOK, d, sc->op);
+    rc = xsm_shadow_control(XSM_NONE, d, sc->op);
     if ( rc )
         return rc;
 
@@ -769,7 +769,7 @@ long paging_domctl_continuation(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
     if ( d == NULL )
         return -ESRCH;
 
-    ret = xsm_domctl(XSM_OTHER, d, op.cmd);
+    ret = xsm_domctl(DEV_EMU_PRIVS | XENSTORE_PRIVS | XSM_DOM_SUPER, d, op.cmd);
     if ( !ret )
     {
         if ( domctl_lock_acquire() )
diff --git a/xen/arch/x86/mm/shadow/set.c b/xen/arch/x86/mm/shadow/set.c
index fff4d1633c..066865e1a6 100644
--- a/xen/arch/x86/mm/shadow/set.c
+++ b/xen/arch/x86/mm/shadow/set.c
@@ -106,7 +106,7 @@ shadow_get_page_from_l1e(shadow_l1e_t sl1e, struct domain *d, p2m_type_t type)
          (owner = page_get_owner(mfn_to_page(mfn))) &&
          (d != owner) )
     {
-        res = xsm_priv_mapping(XSM_TARGET, d, owner);
+        res = xsm_priv_mapping(TARGET_PRIVS, d, owner);
         if ( !res )
         {
             res = get_page_from_l1e(sl1e, d, owner);
diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c
index 5febc0ea4b..6d4a873130 100644
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -1310,7 +1310,7 @@ int pci_restore_msi_state(struct pci_dev *pdev)
     if ( !use_msi )
         return -EOPNOTSUPP;
 
-    ret = xsm_resource_setup_pci(XSM_PRIV,
+    ret = xsm_resource_setup_pci(XSM_HW_CTRL,
                                 (pdev->seg << 16) | (pdev->bus << 8) |
                                 pdev->devfn);
     if ( ret )
diff --git a/xen/arch/x86/pci.c b/xen/arch/x86/pci.c
index a9decd4f33..7ca9fc68f2 100644
--- a/xen/arch/x86/pci.c
+++ b/xen/arch/x86/pci.c
@@ -74,7 +74,7 @@ int pci_conf_write_intercept(unsigned int seg, unsigned int bdf,
                              uint32_t *data)
 {
     struct pci_dev *pdev;
-    int rc = xsm_pci_config_permission(XSM_HOOK, current->domain, bdf,
+    int rc = xsm_pci_config_permission(XSM_NONE, current->domain, bdf,
                                        reg, reg + size - 1, 1);
 
     if ( rc < 0 )
diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c
index 23465bcd00..73e5757faf 100644
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -110,7 +110,7 @@ int physdev_map_pirq(domid_t domid, int type, int *index, int *pirq_p,
     if ( d == NULL )
         return -ESRCH;
 
-    ret = xsm_map_domain_pirq(XSM_DM_PRIV, d);
+    ret = xsm_map_domain_pirq(DEV_EMU_PRIVS, d);
     if ( ret )
         goto free_domain;
 
@@ -148,7 +148,7 @@ int physdev_unmap_pirq(domid_t domid, int pirq)
         return -ESRCH;
 
     if ( domid != DOMID_SELF || !is_hvm_domain(d) || !has_pirq(d) )
-        ret = xsm_unmap_domain_pirq(XSM_DM_PRIV, d);
+        ret = xsm_unmap_domain_pirq(DEV_EMU_PRIVS, d);
     if ( ret )
         goto free_domain;
 
@@ -355,7 +355,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         ret = -EFAULT;
         if ( copy_from_guest(&apic, arg, 1) != 0 )
             break;
-        ret = xsm_apic(XSM_PRIV, currd, cmd);
+        ret = xsm_apic(XSM_HW_CTRL, currd, cmd);
         if ( ret )
             break;
         ret = ioapic_guest_read(apic.apic_physbase, apic.reg, &apic.value);
@@ -369,7 +369,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         ret = -EFAULT;
         if ( copy_from_guest(&apic, arg, 1) != 0 )
             break;
-        ret = xsm_apic(XSM_PRIV, currd, cmd);
+        ret = xsm_apic(XSM_HW_CTRL, currd, cmd);
         if ( ret )
             break;
         ret = ioapic_guest_write(apic.apic_physbase, apic.reg, apic.value);
@@ -385,7 +385,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
 
         /* Use the APIC check since this dummy hypercall should still only
          * be called by the domain with access to program the ioapic */
-        ret = xsm_apic(XSM_PRIV, currd, cmd);
+        ret = xsm_apic(XSM_HW_CTRL, currd, cmd);
         if ( ret )
             break;
 
@@ -535,7 +535,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         if ( copy_from_guest(&dev, arg, 1) )
             ret = -EFAULT;
         else
-            ret = xsm_resource_setup_pci(XSM_PRIV,
+            ret = xsm_resource_setup_pci(XSM_HW_CTRL,
                                          (dev.seg << 16) | (dev.bus << 8) |
                                          dev.devfn) ?:
                   pci_prepare_msix(dev.seg, dev.bus, dev.devfn,
@@ -546,7 +546,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
     case PHYSDEVOP_pci_mmcfg_reserved: {
         struct physdev_pci_mmcfg_reserved info;
 
-        ret = xsm_resource_setup_misc(XSM_PRIV);
+        ret = xsm_resource_setup_misc(XSM_HW_CTRL);
         if ( ret )
             break;
 
@@ -611,7 +611,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         if ( setup_gsi.gsi < 0 || setup_gsi.gsi >= nr_irqs_gsi )
             break;
 
-        ret = xsm_resource_setup_gsi(XSM_PRIV, setup_gsi.gsi);
+        ret = xsm_resource_setup_gsi(XSM_HW_CTRL, setup_gsi.gsi);
         if ( ret )
             break;
 
diff --git a/xen/arch/x86/platform_hypercall.c b/xen/arch/x86/platform_hypercall.c
index 23fadbc782..a3e4db9f02 100644
--- a/xen/arch/x86/platform_hypercall.c
+++ b/xen/arch/x86/platform_hypercall.c
@@ -196,7 +196,7 @@ ret_t do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
     if ( op->interface_version != XENPF_INTERFACE_VERSION )
         return -EACCES;
 
-    ret = xsm_platform_op(XSM_PRIV, op->cmd);
+    ret = xsm_platform_op(XSM_PLAT_CTRL, op->cmd);
     if ( ret )
         return ret;
 
@@ -614,7 +614,7 @@ ret_t do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
     {
         int cpu = op->u.cpu_ol.cpuid;
 
-        ret = xsm_resource_plug_core(XSM_HOOK);
+        ret = xsm_resource_plug_core(XSM_NONE);
         if ( ret )
             break;
 
@@ -640,7 +640,7 @@ ret_t do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
     {
         int cpu = op->u.cpu_ol.cpuid;
 
-        ret = xsm_resource_unplug_core(XSM_HOOK);
+        ret = xsm_resource_unplug_core(XSM_NONE);
         if ( ret )
             break;
 
@@ -669,7 +669,7 @@ ret_t do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
     break;
 
     case XENPF_cpu_hotadd:
-        ret = xsm_resource_plug_core(XSM_HOOK);
+        ret = xsm_resource_plug_core(XSM_NONE);
         if ( ret )
             break;
 
@@ -679,7 +679,7 @@ ret_t do_platform_op(XEN_GUEST_HANDLE_PARAM(xen_platform_op_t) u_xenpf_op)
     break;
 
     case XENPF_mem_hotadd:
-        ret = xsm_resource_plug_core(XSM_HOOK);
+        ret = xsm_resource_plug_core(XSM_NONE);
         if ( ret )
             break;
 
diff --git a/xen/arch/x86/pv/emul-priv-op.c b/xen/arch/x86/pv/emul-priv-op.c
index 8889509d2a..b3f7896271 100644
--- a/xen/arch/x86/pv/emul-priv-op.c
+++ b/xen/arch/x86/pv/emul-priv-op.c
@@ -250,7 +250,7 @@ static bool pci_cfg_ok(struct domain *currd, unsigned int start,
     }
 
     return !write ?
-           xsm_pci_config_permission(XSM_HOOK, currd, machine_bdf,
+           xsm_pci_config_permission(XSM_NONE, currd, machine_bdf,
                                      start, start + size - 1, 0) == 0 :
            pci_conf_write_intercept(0, machine_bdf, start, size, write) >= 0;
 }
diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c
index aff52a13f3..a843d5aac5 100644
--- a/xen/arch/x86/sysctl.c
+++ b/xen/arch/x86/sysctl.c
@@ -190,8 +190,8 @@ long arch_do_sysctl(
         }
 
         if ( !ret )
-            ret = plug ? xsm_resource_plug_core(XSM_HOOK)
-                       : xsm_resource_unplug_core(XSM_HOOK);
+            ret = plug ? xsm_resource_plug_core(XSM_NONE)
+                       : xsm_resource_unplug_core(XSM_NONE);
 
         if ( !ret )
             ret = continue_hypercall_on_cpu(0, fn, hcpu);
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 1f2c569e5d..b3a3864421 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -311,7 +311,7 @@ static int late_hwdom_init(struct domain *d)
     if ( d != hardware_domain || d->domain_id == 0 )
         return 0;
 
-    rv = xsm_init_hardware_domain(XSM_HOOK, d);
+    rv = xsm_init_hardware_domain(XSM_NONE, d);
     if ( rv )
         return rv;
 
@@ -655,7 +655,7 @@ struct domain *domain_create(domid_t domid,
         if ( !d->iomem_caps || !d->irq_caps )
             goto fail;
 
-        if ( (err = xsm_domain_create(XSM_HOOK, d, config->ssidref)) != 0 )
+        if ( (err = xsm_domain_create(XSM_NONE, d, config->ssidref)) != 0 )
             goto fail;
 
         d->controller_pause_count = 1;
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index af044e2eda..be7533caf9 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -314,7 +314,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
             return -ESRCH;
     }
 
-    ret = xsm_domctl(XSM_OTHER, d, op->cmd);
+    ret = xsm_domctl(DEV_EMU_PRIVS | XENSTORE_PRIVS | XSM_DOM_SUPER, d, op->cmd);
     if ( ret )
         goto domctl_out_unlock_domonly;
 
@@ -553,7 +553,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
         if ( d == NULL )
             goto getdomaininfo_out;
 
-        ret = xsm_getdomaininfo(XSM_HOOK, d);
+        ret = xsm_getdomaininfo(XSM_NONE, d);
         if ( ret )
             goto getdomaininfo_out;
 
@@ -688,7 +688,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
             break;
         }
         irq = pirq_access_permitted(current->domain, pirq);
-        if ( !irq || xsm_irq_permission(XSM_HOOK, d, irq, allow) )
+        if ( !irq || xsm_irq_permission(XSM_NONE, d, irq, allow) )
             ret = -EPERM;
         else if ( allow )
             ret = irq_permit_access(d, irq);
@@ -709,7 +709,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
 
         if ( !iomem_access_permitted(current->domain,
                                      mfn, mfn + nr_mfns - 1) ||
-             xsm_iomem_permission(XSM_HOOK, d, mfn, mfn + nr_mfns - 1, allow) )
+             xsm_iomem_permission(XSM_NONE, d, mfn, mfn + nr_mfns - 1, allow) )
             ret = -EPERM;
         else if ( allow )
             ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1);
@@ -746,7 +746,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
              !iomem_access_permitted(d, mfn, mfn_end) )
             break;
 
-        ret = xsm_iomem_mapping(XSM_HOOK, d, mfn, mfn_end, add);
+        ret = xsm_iomem_mapping(XSM_NONE, d, mfn, mfn_end, add);
         if ( ret )
             break;
 
@@ -801,7 +801,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
 
         ret = -EOPNOTSUPP;
         if ( is_hvm_domain(e) )
-            ret = xsm_set_target(XSM_HOOK, d, e);
+            ret = xsm_set_target(XSM_NONE, d, e);
         if ( ret )
         {
             put_domain(e);
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index 5479315aae..5c987096d9 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -296,7 +296,7 @@ static long evtchn_alloc_unbound(evtchn_alloc_unbound_t *alloc)
         ERROR_EXIT_DOM(port, d);
     chn = evtchn_from_port(d, port);
 
-    rc = xsm_evtchn_unbound(XSM_TARGET, d, chn, alloc->remote_dom);
+    rc = xsm_evtchn_unbound(TARGET_PRIVS, d, chn, alloc->remote_dom);
     if ( rc )
         goto out;
 
@@ -372,7 +372,7 @@ static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
          (rchn->u.unbound.remote_domid != ld->domain_id) )
         ERROR_EXIT_DOM(-EINVAL, rd);
 
-    rc = xsm_evtchn_interdomain(XSM_HOOK, ld, lchn, rd, rchn);
+    rc = xsm_evtchn_interdomain(XSM_NONE, ld, lchn, rd, rchn);
     if ( rc )
         goto out;
 
@@ -760,7 +760,7 @@ int evtchn_send(struct domain *ld, unsigned int lport)
         goto out;
     }
 
-    ret = xsm_evtchn_send(XSM_HOOK, ld, lchn);
+    ret = xsm_evtchn_send(XSM_NONE, ld, lchn);
     if ( ret )
         goto out;
 
@@ -985,7 +985,7 @@ int evtchn_status(evtchn_status_t *status)
         goto out;
     }
 
-    rc = xsm_evtchn_status(XSM_TARGET, d, chn);
+    rc = xsm_evtchn_status(TARGET_PRIVS, d, chn);
     if ( rc )
         goto out;
 
@@ -1310,7 +1310,7 @@ long do_event_channel_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         if ( d == NULL )
             return -ESRCH;
 
-        rc = xsm_evtchn_reset(XSM_TARGET, current->domain, d);
+        rc = xsm_evtchn_reset(TARGET_PRIVS, current->domain, d);
         if ( !rc )
             rc = evtchn_reset(d, cmd == EVTCHNOP_reset_cont);
 
@@ -1371,7 +1371,7 @@ int alloc_unbound_xen_event_channel(
         goto out;
     chn = evtchn_from_port(ld, port);
 
-    rc = xsm_evtchn_unbound(XSM_TARGET, ld, chn, remote_domid);
+    rc = xsm_evtchn_unbound(TARGET_PRIVS, ld, chn, remote_domid);
     if ( rc )
         goto out;
 
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index ab30e2e8cf..27e4eb1d65 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -1063,7 +1063,7 @@ map_grant_ref(
         return;
     }
 
-    rc = xsm_grant_mapref(XSM_HOOK, ld, rd, op->flags);
+    rc = xsm_grant_mapref(XSM_NONE, ld, rd, op->flags);
     if ( rc )
     {
         rcu_unlock_domain(rd);
@@ -1403,7 +1403,7 @@ unmap_common(
         return;
     }
 
-    rc = xsm_grant_unmapref(XSM_HOOK, ld, rd);
+    rc = xsm_grant_unmapref(XSM_NONE, ld, rd);
     if ( rc )
     {
         rcu_unlock_domain(rd);
@@ -2021,7 +2021,7 @@ gnttab_setup_table(
         goto out;
     }
 
-    if ( xsm_grant_setup(XSM_TARGET, curr->domain, d) )
+    if ( xsm_grant_setup(TARGET_PRIVS, curr->domain, d) )
     {
         op.status = GNTST_permission_denied;
         goto out;
@@ -2103,7 +2103,7 @@ gnttab_query_size(
         goto out;
     }
 
-    if ( xsm_grant_query_size(XSM_TARGET, current->domain, d) )
+    if ( xsm_grant_query_size(TARGET_PRIVS, current->domain, d) )
     {
         op.status = GNTST_permission_denied;
         goto out;
@@ -2274,7 +2274,7 @@ gnttab_transfer(
             goto put_gfn_and_copyback;
         }
 
-        if ( xsm_grant_transfer(XSM_HOOK, d, e) )
+        if ( xsm_grant_transfer(XSM_NONE, d, e) )
         {
             gop.status = GNTST_permission_denied;
         unlock_and_copyback:
@@ -2812,7 +2812,7 @@ static int gnttab_copy_lock_domains(const struct gnttab_copy *op,
     if ( rc < 0 )
         goto error;
 
-    rc = xsm_grant_copy(XSM_HOOK, src->domain, dest->domain);
+    rc = xsm_grant_copy(XSM_NONE, src->domain, dest->domain);
     if ( rc < 0 )
     {
         rc = GNTST_permission_denied;
@@ -3231,7 +3231,7 @@ gnttab_get_status_frames(XEN_GUEST_HANDLE_PARAM(gnttab_get_status_frames_t) uop,
         op.status = GNTST_bad_domain;
         goto out1;
     }
-    rc = xsm_grant_setup(XSM_TARGET, current->domain, d);
+    rc = xsm_grant_setup(TARGET_PRIVS, current->domain, d);
     if ( rc )
     {
         op.status = GNTST_permission_denied;
@@ -3295,7 +3295,7 @@ gnttab_get_version(XEN_GUEST_HANDLE_PARAM(gnttab_get_version_t) uop)
     if ( d == NULL )
         return -ESRCH;
 
-    rc = xsm_grant_query_size(XSM_TARGET, current->domain, d);
+    rc = xsm_grant_query_size(TARGET_PRIVS, current->domain, d);
     if ( rc )
     {
         rcu_unlock_domain(d);
diff --git a/xen/common/hypfs.c b/xen/common/hypfs.c
index e71f7df479..207556896d 100644
--- a/xen/common/hypfs.c
+++ b/xen/common/hypfs.c
@@ -679,7 +679,7 @@ long do_hypfs_op(unsigned int cmd,
     struct hypfs_entry *entry;
     static char path[XEN_HYPFS_MAX_PATHLEN];
 
-    if ( xsm_hypfs_op(XSM_PRIV) )
+    if ( xsm_hypfs_op(XSM_PLAT_CTRL) )
         return -EPERM;
 
     if ( cmd == XEN_HYPFS_OP_get_version )
diff --git a/xen/common/kernel.c b/xen/common/kernel.c
index d77756a81e..5c065e403f 100644
--- a/xen/common/kernel.c
+++ b/xen/common/kernel.c
@@ -459,7 +459,7 @@ __initcall(param_init);
 
 DO(xen_version)(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
 {
-    bool_t deny = !!xsm_xen_version(XSM_OTHER, cmd);
+    bool_t deny = !!xsm_xen_version(XSM_NONE | XSM_PLAT_CTRL, cmd);
 
     switch ( cmd )
     {
diff --git a/xen/common/kexec.c b/xen/common/kexec.c
index ebeee6405a..2d1d1ce205 100644
--- a/xen/common/kexec.c
+++ b/xen/common/kexec.c
@@ -1219,7 +1219,7 @@ static int do_kexec_op_internal(unsigned long op,
 {
     int ret = -EINVAL;
 
-    ret = xsm_kexec(XSM_PRIV);
+    ret = xsm_kexec(XSM_PLAT_CTRL);
     if ( ret )
         return ret;
 
diff --git a/xen/common/mem_access.c b/xen/common/mem_access.c
index 010e6f8dbf..6cbe12994d 100644
--- a/xen/common/mem_access.c
+++ b/xen/common/mem_access.c
@@ -47,7 +47,7 @@ int mem_access_memop(unsigned long cmd,
     if ( !p2m_mem_access_sanity_check(d) )
         goto out;
 
-    rc = xsm_mem_access(XSM_DM_PRIV, d);
+    rc = xsm_mem_access(DEV_EMU_PRIVS, d);
     if ( rc )
         goto out;
 
diff --git a/xen/common/memory.c b/xen/common/memory.c
index 76b9f58478..f51a9cea73 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -603,7 +603,7 @@ static long memory_exchange(XEN_GUEST_HANDLE_PARAM(xen_memory_exchange_t) arg)
         goto fail_early;
     }
 
-    rc = xsm_memory_exchange(XSM_TARGET, d);
+    rc = xsm_memory_exchange(TARGET_PRIVS, d);
     if ( rc )
     {
         rcu_unlock_domain(d);
@@ -1062,7 +1062,7 @@ static long xatp_permission_check(struct domain *d, unsigned int space)
          (!is_hardware_domain(d) || (d != current->domain)) )
         return -EACCES;
 
-    return xsm_add_to_physmap(XSM_TARGET, current->domain, d);
+    return xsm_add_to_physmap(TARGET_PRIVS, current->domain, d);
 }
 
 unsigned int ioreq_server_max_frames(const struct domain *d)
@@ -1222,7 +1222,7 @@ static int acquire_resource(
     if ( rc )
         return rc;
 
-    rc = xsm_domain_resource_map(XSM_DM_PRIV, d);
+    rc = xsm_domain_resource_map(DEV_EMU_PRIVS, d);
     if ( rc )
         goto out;
 
@@ -1378,7 +1378,7 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
              && (reservation.mem_flags & XENMEMF_populate_on_demand) )
             args.memflags |= MEMF_populate_on_demand;
 
-        if ( xsm_memory_adjust_reservation(XSM_TARGET, curr_d, d) )
+        if ( xsm_memory_adjust_reservation(TARGET_PRIVS, curr_d, d) )
         {
             rcu_unlock_domain(d);
             return start_extent;
@@ -1452,7 +1452,7 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         if ( d == NULL )
             return -ESRCH;
 
-        rc = xsm_memory_stat_reservation(XSM_TARGET, curr_d, d);
+        rc = xsm_memory_stat_reservation(TARGET_PRIVS, curr_d, d);
         if ( rc )
         {
             rcu_unlock_domain(d);
@@ -1574,7 +1574,7 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
             return -ESRCH;
 
         rc = paging_mode_translate(d)
-             ? xsm_remove_from_physmap(XSM_TARGET, curr_d, d)
+             ? xsm_remove_from_physmap(TARGET_PRIVS, curr_d, d)
              : -EACCES;
         if ( rc )
         {
@@ -1621,7 +1621,7 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         if ( d == NULL )
             return -EINVAL;
 
-        rc = xsm_claim_pages(XSM_PRIV, d);
+        rc = xsm_claim_pages(XSM_DOM_SUPER, d);
 
         if ( !rc )
             rc = domain_set_outstanding_pages(d, reservation.nr_extents);
@@ -1652,7 +1652,7 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         if ( (d = rcu_lock_domain_by_any_id(topology.domid)) == NULL )
             return -ESRCH;
 
-        rc = xsm_get_vnumainfo(XSM_TARGET, d);
+        rc = xsm_get_vnumainfo(TARGET_PRIVS, d);
         if ( rc )
         {
             rcu_unlock_domain(d);
diff --git a/xen/common/monitor.c b/xen/common/monitor.c
index d5c9ff1cbf..5649097ad5 100644
--- a/xen/common/monitor.c
+++ b/xen/common/monitor.c
@@ -36,7 +36,7 @@ int monitor_domctl(struct domain *d, struct xen_domctl_monitor_op *mop)
     if ( unlikely(current->domain == d) ) /* no domain_pause() */
         return -EPERM;
 
-    rc = xsm_vm_event_control(XSM_PRIV, d, mop->op, mop->event);
+    rc = xsm_vm_event_control(XSM_DOM_SUPER, d, mop->op, mop->event);
     if ( unlikely(rc) )
         return rc;
 
diff --git a/xen/common/sched/core.c b/xen/common/sched/core.c
index 6d34764d38..ff397d6971 100644
--- a/xen/common/sched/core.c
+++ b/xen/common/sched/core.c
@@ -1944,7 +1944,7 @@ ret_t do_sched_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         if ( d == NULL )
             break;
 
-        ret = xsm_schedop_shutdown(XSM_DM_PRIV, current->domain, d);
+        ret = xsm_schedop_shutdown(DEV_EMU_PRIVS, current->domain, d);
         if ( likely(!ret) )
             domain_shutdown(d, sched_remote_shutdown.reason);
 
@@ -2046,7 +2046,7 @@ long sched_adjust(struct domain *d, struct xen_domctl_scheduler_op *op)
 {
     long ret;
 
-    ret = xsm_domctl_scheduler_op(XSM_HOOK, d, op->cmd);
+    ret = xsm_domctl_scheduler_op(XSM_NONE, d, op->cmd);
     if ( ret )
         return ret;
 
@@ -2081,7 +2081,7 @@ long sched_adjust_global(struct xen_sysctl_scheduler_op *op)
     struct cpupool *pool;
     int rc;
 
-    rc = xsm_sysctl_scheduler_op(XSM_HOOK, op->cmd);
+    rc = xsm_sysctl_scheduler_op(XSM_NONE, op->cmd);
     if ( rc )
         return rc;
 
diff --git a/xen/common/sysctl.c b/xen/common/sysctl.c
index 3558641cd9..172f9b528d 100644
--- a/xen/common/sysctl.c
+++ b/xen/common/sysctl.c
@@ -41,7 +41,7 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
     if ( op->interface_version != XEN_SYSCTL_INTERFACE_VERSION )
         return -EACCES;
 
-    ret = xsm_sysctl(XSM_PRIV, op->cmd);
+    ret = xsm_sysctl(XSM_PLAT_CTRL, op->cmd);
     if ( ret )
         return ret;
 
@@ -58,7 +58,7 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
     switch ( op->cmd )
     {
     case XEN_SYSCTL_readconsole:
-        ret = xsm_readconsole(XSM_HOOK, op->u.readconsole.clear);
+        ret = xsm_readconsole(XSM_NONE, op->u.readconsole.clear);
         if ( ret )
             break;
 
@@ -88,7 +88,7 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
             if ( num_domains == op->u.getdomaininfolist.max_domains )
                 break;
 
-            ret = xsm_getdomaininfo(XSM_HOOK, d);
+            ret = xsm_getdomaininfo(XSM_NONE, d);
             if ( ret )
                 continue;
 
@@ -191,7 +191,7 @@ long do_sysctl(XEN_GUEST_HANDLE_PARAM(xen_sysctl_t) u_sysctl)
         if ( op->u.page_offline.end < op->u.page_offline.start )
             break;
 
-        ret = xsm_page_offline(XSM_HOOK, op->u.page_offline.cmd);
+        ret = xsm_page_offline(XSM_NONE, op->u.page_offline.cmd);
         if ( ret )
             break;
 
diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c
index 44d542f23e..103d0a207f 100644
--- a/xen/common/vm_event.c
+++ b/xen/common/vm_event.c
@@ -584,7 +584,7 @@ int vm_event_domctl(struct domain *d, struct xen_domctl_vm_event_op *vec)
         return 0;
     }
 
-    rc = xsm_vm_event_control(XSM_PRIV, d, vec->mode, vec->op);
+    rc = xsm_vm_event_control(XSM_DOM_SUPER, d, vec->mode, vec->op);
     if ( rc )
         return rc;
 
diff --git a/xen/common/xenoprof.c b/xen/common/xenoprof.c
index 1926a92fe4..4268c12e5d 100644
--- a/xen/common/xenoprof.c
+++ b/xen/common/xenoprof.c
@@ -737,7 +737,7 @@ ret_t do_xenoprof_op(int op, XEN_GUEST_HANDLE_PARAM(void) arg)
         return -EPERM;
     }
 
-    ret = xsm_profile(XSM_HOOK, current->domain, op);
+    ret = xsm_profile(XSM_NONE, current->domain, op);
     if ( ret )
         return ret;
 
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index 2358375170..93d51d6420 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -680,7 +680,7 @@ long do_console_io(unsigned int cmd, unsigned int count,
     long rc;
     unsigned int idx, len;
 
-    rc = xsm_console_io(XSM_OTHER, current->domain, cmd);
+    rc = xsm_console_io(XSM_NONE|XSM_DOM_SUPER, current->domain, cmd);
     if ( rc )
         return rc;
 
diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c
index 999b831d90..a51bdd51d6 100644
--- a/xen/drivers/passthrough/device_tree.c
+++ b/xen/drivers/passthrough/device_tree.c
@@ -230,7 +230,7 @@ int iommu_do_dt_domctl(struct xen_domctl *domctl, struct domain *d,
         if ( ret )
             break;
 
-        ret = xsm_assign_dtdevice(XSM_HOOK, d, dt_node_full_name(dev));
+        ret = xsm_assign_dtdevice(XSM_NONE, d, dt_node_full_name(dev));
         if ( ret )
             break;
 
@@ -284,7 +284,7 @@ int iommu_do_dt_domctl(struct xen_domctl *domctl, struct domain *d,
         if ( ret )
             break;
 
-        ret = xsm_deassign_dtdevice(XSM_HOOK, d, dt_node_full_name(dev));
+        ret = xsm_deassign_dtdevice(XSM_NONE, d, dt_node_full_name(dev));
 
         if ( d == dom_io )
             return -EINVAL;
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index 705137f8be..f9669c6afa 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -704,7 +704,7 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn,
     else
         pdev_type = "device";
 
-    ret = xsm_resource_plug_pci(XSM_PRIV, (seg << 16) | (bus << 8) | devfn);
+    ret = xsm_resource_plug_pci(XSM_HW_CTRL, (seg << 16) | (bus << 8) | devfn);
     if ( ret )
         return ret;
 
@@ -814,7 +814,7 @@ int pci_remove_device(u16 seg, u8 bus, u8 devfn)
     struct pci_dev *pdev;
     int ret;
 
-    ret = xsm_resource_unplug_pci(XSM_PRIV, (seg << 16) | (bus << 8) | devfn);
+    ret = xsm_resource_unplug_pci(XSM_HW_CTRL, (seg << 16) | (bus << 8) | devfn);
     if ( ret )
         return ret;
 
@@ -1484,7 +1484,7 @@ static int iommu_get_device_group(
              ((pdev->bus == bus) && (pdev->devfn == devfn)) )
             continue;
 
-        if ( xsm_get_device_group(XSM_HOOK, (seg << 16) | (pdev->bus << 8) | pdev->devfn) )
+        if ( xsm_get_device_group(XSM_NONE, (seg << 16) | (pdev->bus << 8) | pdev->devfn) )
             continue;
 
         sdev_id = ops->get_device_group_id(seg, pdev->bus, pdev->devfn);
@@ -1552,7 +1552,7 @@ int iommu_do_pci_domctl(
         u32 max_sdevs;
         XEN_GUEST_HANDLE_64(uint32) sdevs;
 
-        ret = xsm_get_device_group(XSM_HOOK, domctl->u.get_device_group.machine_sbdf);
+        ret = xsm_get_device_group(XSM_NONE, domctl->u.get_device_group.machine_sbdf);
         if ( ret )
             break;
 
@@ -1603,7 +1603,7 @@ int iommu_do_pci_domctl(
 
         machine_sbdf = domctl->u.assign_device.u.pci.machine_sbdf;
 
-        ret = xsm_assign_device(XSM_HOOK, d, machine_sbdf);
+        ret = xsm_assign_device(XSM_NONE, d, machine_sbdf);
         if ( ret )
             break;
 
@@ -1648,7 +1648,7 @@ int iommu_do_pci_domctl(
 
         machine_sbdf = domctl->u.assign_device.u.pci.machine_sbdf;
 
-        ret = xsm_deassign_device(XSM_HOOK, d, machine_sbdf);
+        ret = xsm_deassign_device(XSM_NONE, d, machine_sbdf);
         if ( ret )
             break;
 
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 9a88e5b00f..39681a5dff 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -475,6 +475,12 @@ struct domain
 #define XSM_XENSTORE  (1U<<31) /* Xenstore: domain that can do privileged operations on xenstore */
 #define CLASSIC_DOM0_PRIVS (XSM_PLAT_CTRL | XSM_DOM_BUILD | XSM_DOM_SUPER | \
 		XSM_DEV_EMUL | XSM_HW_CTRL | XSM_HW_SUPER | XSM_XENSTORE)
+/* Any access for which XSM_DEV_EMUL is the restriction, XSM_DOM_SUPER is an override */
+#define DEV_EMU_PRIVS (XSM_DOM_SUPER | XSM_DEV_EMUL)
+/* Anytime there is an XSM_TARGET check, XSM_SELF also applies, and XSM_DOM_SUPER is an override */
+#define TARGET_PRIVS (XSM_TARGET | XSM_SELF | XSM_DOM_SUPER)
+/* Anytime there is an XSM_XENSTORE check, XSM_DOM_SUPER is an override */
+#define XENSTORE_PRIVS (XSM_XENSTORE | XSM_DOM_SUPER)
     uint32_t         xsm_roles;
 
     /* Which guest this guest has privileges on */
diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h
index a6dab0c809..35c9a4f2d4 100644
--- a/xen/include/xsm/dummy.h
+++ b/xen/include/xsm/dummy.h
@@ -65,37 +65,48 @@ void __xsm_action_mismatch_detected(void);
 #define XSM_INLINE always_inline
 #define XSM_DEFAULT_ARG xsm_default_t action,
 #define XSM_DEFAULT_VOID xsm_default_t action
-#define XSM_ASSERT_ACTION(def) LINKER_BUG_ON(def != action)
+#define XSM_ASSERT_ACTION(def) LINKER_BUG_ON((def) != action)
 
 #endif /* CONFIG_XSM */
 
 static always_inline int xsm_default_action(
     xsm_default_t action, struct domain *src, struct domain *target)
 {
-    switch ( action ) {
-    case XSM_HOOK:
+    /* TODO: these three if's could be squashed into one, decreasing
+     *       the readability/logical reason-ability but may decrease the
+     *       number of spectre gadgets
+     */
+    if ( action & XSM_NONE )
         return 0;
-    case XSM_TARGET:
-        if ( evaluate_nospec(src == target) )
-        {
-            return 0;
-    case XSM_XS_PRIV:
-            if ( evaluate_nospec(is_xenstore_domain(src)) )
-                return 0;
-        }
-        /* fall through */
-    case XSM_DM_PRIV:
-        if ( target && evaluate_nospec(src->target == target) )
-            return 0;
-        /* fall through */
-    case XSM_PRIV:
-        if ( is_control_domain(src) )
-            return 0;
-        return -EPERM;
-    default:
-        LINKER_BUG_ON(1);
-        return -EPERM;
-    }
+
+    if ( (action & XSM_SELF) && ((!target) || (src == target)) )
+        return 0;
+
+    if ( (action & XSM_TARGET) && ((target) && (src->target == target)) )
+        return 0;
+
+    /* XSM_DEV_EMUL is the only domain role with a condition, i.e. the
+     * role only applies to a domain's target.
+     */
+    if ( (action & XSM_DEV_EMUL) && (src->xsm_roles & XSM_DEV_EMUL)
+        && (target) && (src->target == target) )
+        return 0;
+
+    /* Mask out SELF, TARGET, and DEV_EMUL as they have been handled */
+    action &= ~(XSM_SELF & XSM_TARGET & XSM_DEV_EMUL);
+
+    /* Checks if the domain has one of the remaining roles set on it:
+     *      XSM_PLAT_CTRL
+     *      XSM_DOM_BUILD
+     *      XSM_DOM_SUPER
+     *      XSM_HW_CTRL
+     *      XSM_HW_SUPER
+     *      XSM_XENSTORE
+     */
+    if (src->xsm_roles & action)
+        return 0;
+
+    return -EPERM;
 }
 
 static XSM_INLINE void xsm_security_domaininfo(struct domain *d,
@@ -106,60 +117,60 @@ static XSM_INLINE void xsm_security_domaininfo(struct domain *d,
 
 static XSM_INLINE int xsm_domain_create(XSM_DEFAULT_ARG struct domain *d, u32 ssidref)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_getdomaininfo(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_domctl_scheduler_op(XSM_DEFAULT_ARG struct domain *d, int cmd)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_sysctl_scheduler_op(XSM_DEFAULT_ARG int cmd)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_set_target(XSM_DEFAULT_ARG struct domain *d, struct domain *e)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_domctl(XSM_DEFAULT_ARG struct domain *d, int cmd)
 {
-    XSM_ASSERT_ACTION(XSM_OTHER);
+    XSM_ASSERT_ACTION(DEV_EMU_PRIVS | XENSTORE_PRIVS | XSM_DOM_SUPER);
     switch ( cmd )
     {
     case XEN_DOMCTL_ioport_mapping:
     case XEN_DOMCTL_memory_mapping:
     case XEN_DOMCTL_bind_pt_irq:
     case XEN_DOMCTL_unbind_pt_irq:
-        return xsm_default_action(XSM_DM_PRIV, current->domain, d);
+        return xsm_default_action(DEV_EMU_PRIVS, current->domain, d);
     case XEN_DOMCTL_getdomaininfo:
-        return xsm_default_action(XSM_XS_PRIV, current->domain, d);
+        return xsm_default_action(XENSTORE_PRIVS, current->domain, d);
     default:
-        return xsm_default_action(XSM_PRIV, current->domain, d);
+        return xsm_default_action(XSM_DOM_SUPER, current->domain, d);
     }
 }
 
 static XSM_INLINE int xsm_sysctl(XSM_DEFAULT_ARG int cmd)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_PLAT_CTRL);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_readconsole(XSM_DEFAULT_ARG uint32_t clear)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, NULL);
 }
 
@@ -176,113 +187,113 @@ static XSM_INLINE void xsm_free_security_domain(struct domain *d)
 static XSM_INLINE int xsm_grant_mapref(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2,
                                                                 uint32_t flags)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, d1, d2);
 }
 
 static XSM_INLINE int xsm_grant_unmapref(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, d1, d2);
 }
 
 static XSM_INLINE int xsm_grant_setup(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, d1, d2);
 }
 
 static XSM_INLINE int xsm_grant_transfer(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, d1, d2);
 }
 
 static XSM_INLINE int xsm_grant_copy(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, d1, d2);
 }
 
 static XSM_INLINE int xsm_grant_query_size(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, d1, d2);
 }
 
 static XSM_INLINE int xsm_memory_exchange(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_memory_adjust_reservation(XSM_DEFAULT_ARG struct domain *d1,
                                                             struct domain *d2)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, d1, d2);
 }
 
 static XSM_INLINE int xsm_memory_stat_reservation(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, d1, d2);
 }
 
 static XSM_INLINE int xsm_console_io(XSM_DEFAULT_ARG struct domain *d, int cmd)
 {
-    XSM_ASSERT_ACTION(XSM_OTHER);
+    XSM_ASSERT_ACTION(XSM_NONE|XSM_DOM_SUPER);
     if ( d->is_console )
-        return xsm_default_action(XSM_HOOK, d, NULL);
+        return xsm_default_action(XSM_NONE, d, NULL);
 #ifdef CONFIG_VERBOSE_DEBUG
     if ( cmd == CONSOLEIO_write )
-        return xsm_default_action(XSM_HOOK, d, NULL);
+        return xsm_default_action(XSM_NONE, d, NULL);
 #endif
-    return xsm_default_action(XSM_PRIV, d, NULL);
+    return xsm_default_action(XSM_DOM_SUPER, d, NULL);
 }
 
 static XSM_INLINE int xsm_profile(XSM_DEFAULT_ARG struct domain *d, int op)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, d, NULL);
 }
 
 static XSM_INLINE int xsm_kexec(XSM_DEFAULT_VOID)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_PLAT_CTRL);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_schedop_shutdown(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2)
 {
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    XSM_ASSERT_ACTION(DEV_EMU_PRIVS);
     return xsm_default_action(action, d1, d2);
 }
 
 static XSM_INLINE int xsm_memory_pin_page(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2,
                                           struct page_info *page)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, d1, d2);
 }
 
 static XSM_INLINE int xsm_claim_pages(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_DOM_SUPER);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_evtchn_unbound(XSM_DEFAULT_ARG struct domain *d, struct evtchn *chn,
                                          domid_t id2)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_evtchn_interdomain(XSM_DEFAULT_ARG struct domain *d1, struct evtchn
                                 *chan1, struct domain *d2, struct evtchn *chan2)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, d1, d2);
 }
 
@@ -293,19 +304,19 @@ static XSM_INLINE void xsm_evtchn_close_post(struct evtchn *chn)
 
 static XSM_INLINE int xsm_evtchn_send(XSM_DEFAULT_ARG struct domain *d, struct evtchn *chn)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, d, NULL);
 }
 
 static XSM_INLINE int xsm_evtchn_status(XSM_DEFAULT_ARG struct domain *d, struct evtchn *chn)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_evtchn_reset(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, d1, d2);
 }
 
@@ -328,44 +339,44 @@ static XSM_INLINE char *xsm_show_security_evtchn(struct domain *d, const struct
 
 static XSM_INLINE int xsm_init_hardware_domain(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_get_pod_target(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_DOM_SUPER);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_set_pod_target(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_DOM_SUPER);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_get_vnumainfo(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, current->domain, d);
 }
 
 #if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
 static XSM_INLINE int xsm_get_device_group(XSM_DEFAULT_ARG uint32_t machine_bdf)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_assign_device(XSM_DEFAULT_ARG struct domain *d, uint32_t machine_bdf)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_deassign_device(XSM_DEFAULT_ARG struct domain *d, uint32_t machine_bdf)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
@@ -375,14 +386,14 @@ static XSM_INLINE int xsm_deassign_device(XSM_DEFAULT_ARG struct domain *d, uint
 static XSM_INLINE int xsm_assign_dtdevice(XSM_DEFAULT_ARG struct domain *d,
                                           const char *dtpath)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_deassign_dtdevice(XSM_DEFAULT_ARG struct domain *d,
                                             const char *dtpath)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
@@ -390,55 +401,55 @@ static XSM_INLINE int xsm_deassign_dtdevice(XSM_DEFAULT_ARG struct domain *d,
 
 static XSM_INLINE int xsm_resource_plug_core(XSM_DEFAULT_VOID)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_resource_unplug_core(XSM_DEFAULT_VOID)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_resource_plug_pci(XSM_DEFAULT_ARG uint32_t machine_bdf)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_HW_CTRL);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_resource_unplug_pci(XSM_DEFAULT_ARG uint32_t machine_bdf)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_HW_CTRL);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_resource_setup_pci(XSM_DEFAULT_ARG uint32_t machine_bdf)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_HW_CTRL);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_resource_setup_gsi(XSM_DEFAULT_ARG int gsi)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_HW_CTRL);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_resource_setup_misc(XSM_DEFAULT_VOID)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_HW_CTRL);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_page_offline(XSM_DEFAULT_ARG uint32_t cmd)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_hypfs_op(XSM_DEFAULT_VOID)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_PLAT_CTRL);
     return xsm_default_action(action, current->domain, NULL);
 }
 
@@ -461,57 +472,57 @@ static XSM_INLINE char *xsm_show_irq_sid(int irq)
 
 static XSM_INLINE int xsm_map_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    XSM_ASSERT_ACTION(DEV_EMU_PRIVS);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_map_domain_irq(XSM_DEFAULT_ARG struct domain *d,
                                          int irq, const void *data)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_unmap_domain_pirq(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    XSM_ASSERT_ACTION(DEV_EMU_PRIVS);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_bind_pt_irq(XSM_DEFAULT_ARG struct domain *d, struct xen_domctl_bind_pt_irq *bind)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_unbind_pt_irq(XSM_DEFAULT_ARG struct domain *d, struct xen_domctl_bind_pt_irq *bind)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_unmap_domain_irq(XSM_DEFAULT_ARG struct domain *d,
                                            int irq, const void *data)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_irq_permission(XSM_DEFAULT_ARG struct domain *d, int pirq, uint8_t allow)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_iomem_permission(XSM_DEFAULT_ARG struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_iomem_mapping(XSM_DEFAULT_ARG struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
@@ -519,60 +530,61 @@ static XSM_INLINE int xsm_pci_config_permission(XSM_DEFAULT_ARG struct domain *d
                                         uint16_t start, uint16_t end,
                                         uint8_t access)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_add_to_physmap(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, d1, d2);
 }
 
 static XSM_INLINE int xsm_remove_from_physmap(XSM_DEFAULT_ARG struct domain *d1, struct domain *d2)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, d1, d2);
 }
 
 static XSM_INLINE int xsm_map_gmfn_foreign(XSM_DEFAULT_ARG struct domain *d, struct domain *t)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, d, t);
 }
 
 static XSM_INLINE int xsm_hvm_param(XSM_DEFAULT_ARG struct domain *d, unsigned long op)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, current->domain, d);
 }
 
+/* This check is no longer being called */
 static XSM_INLINE int xsm_hvm_control(XSM_DEFAULT_ARG struct domain *d, unsigned long op)
 {
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    XSM_ASSERT_ACTION(DEV_EMU_PRIVS);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_hvm_param_altp2mhvm(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_DOM_SUPER);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_hvm_altp2mhvm_op(XSM_DEFAULT_ARG struct domain *d, uint64_t mode, uint32_t op)
 {
-    XSM_ASSERT_ACTION(XSM_OTHER);
+    XSM_ASSERT_ACTION(TARGET_PRIVS | DEV_EMU_PRIVS);
 
     switch ( mode )
     {
     case XEN_ALTP2M_mixed:
-        return xsm_default_action(XSM_TARGET, current->domain, d);
+        return xsm_default_action(TARGET_PRIVS, current->domain, d);
     case XEN_ALTP2M_external:
-        return xsm_default_action(XSM_DM_PRIV, current->domain, d);
+        return xsm_default_action(DEV_EMU_PRIVS, current->domain, d);
     case XEN_ALTP2M_limited:
         if ( HVMOP_altp2m_vcpu_enable_notify == op )
-            return xsm_default_action(XSM_TARGET, current->domain, d);
-        return xsm_default_action(XSM_DM_PRIV, current->domain, d);
+            return xsm_default_action(TARGET_PRIVS, current->domain, d);
+        return xsm_default_action(DEV_EMU_PRIVS, current->domain, d);
     default:
         return -EPERM;
     }
@@ -580,14 +592,14 @@ static XSM_INLINE int xsm_hvm_altp2mhvm_op(XSM_DEFAULT_ARG struct domain *d, uin
 
 static XSM_INLINE int xsm_vm_event_control(XSM_DEFAULT_ARG struct domain *d, int mode, int op)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_DOM_SUPER);
     return xsm_default_action(action, current->domain, d);
 }
 
 #ifdef CONFIG_MEM_ACCESS
 static XSM_INLINE int xsm_mem_access(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    XSM_ASSERT_ACTION(DEV_EMU_PRIVS);
     return xsm_default_action(action, current->domain, d);
 }
 #endif
@@ -595,7 +607,7 @@ static XSM_INLINE int xsm_mem_access(XSM_DEFAULT_ARG struct domain *d)
 #ifdef CONFIG_HAS_MEM_PAGING
 static XSM_INLINE int xsm_mem_paging(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    XSM_ASSERT_ACTION(DEV_EMU_PRIVS);
     return xsm_default_action(action, current->domain, d);
 }
 #endif
@@ -603,51 +615,51 @@ static XSM_INLINE int xsm_mem_paging(XSM_DEFAULT_ARG struct domain *d)
 #ifdef CONFIG_MEM_SHARING
 static XSM_INLINE int xsm_mem_sharing(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    XSM_ASSERT_ACTION(DEV_EMU_PRIVS);
     return xsm_default_action(action, current->domain, d);
 }
 #endif
 
 static XSM_INLINE int xsm_platform_op(XSM_DEFAULT_ARG uint32_t op)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_PLAT_CTRL);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 #ifdef CONFIG_X86
 static XSM_INLINE int xsm_do_mca(XSM_DEFAULT_VOID)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_PLAT_CTRL);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_shadow_control(XSM_DEFAULT_ARG struct domain *d, uint32_t op)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_mem_sharing_op(XSM_DEFAULT_ARG struct domain *d, struct domain *cd, int op)
 {
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    XSM_ASSERT_ACTION(DEV_EMU_PRIVS);
     return xsm_default_action(action, current->domain, cd);
 }
 
 static XSM_INLINE int xsm_apic(XSM_DEFAULT_ARG struct domain *d, int cmd)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_HW_CTRL);
     return xsm_default_action(action, d, NULL);
 }
 
 static XSM_INLINE int xsm_machine_memory_map(XSM_DEFAULT_VOID)
 {
-    XSM_ASSERT_ACTION(XSM_PRIV);
+    XSM_ASSERT_ACTION(XSM_PLAT_CTRL);
     return xsm_default_action(action, current->domain, NULL);
 }
 
 static XSM_INLINE int xsm_domain_memory_map(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, current->domain, d);
 }
 
@@ -655,7 +667,7 @@ static XSM_INLINE int xsm_mmu_update(XSM_DEFAULT_ARG struct domain *d, struct do
                                      struct domain *f, uint32_t flags)
 {
     int rc = 0;
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     if ( f != dom_io )
         rc = xsm_default_action(action, d, f);
     if ( evaluate_nospec(t) && !rc )
@@ -665,47 +677,47 @@ static XSM_INLINE int xsm_mmu_update(XSM_DEFAULT_ARG struct domain *d, struct do
 
 static XSM_INLINE int xsm_mmuext_op(XSM_DEFAULT_ARG struct domain *d, struct domain *f)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, d, f);
 }
 
 static XSM_INLINE int xsm_update_va_mapping(XSM_DEFAULT_ARG struct domain *d, struct domain *f, 
                                                             l1_pgentry_t pte)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, d, f);
 }
 
 static XSM_INLINE int xsm_priv_mapping(XSM_DEFAULT_ARG struct domain *d, struct domain *t)
 {
-    XSM_ASSERT_ACTION(XSM_TARGET);
+    XSM_ASSERT_ACTION(TARGET_PRIVS);
     return xsm_default_action(action, d, t);
 }
 
 static XSM_INLINE int xsm_ioport_permission(XSM_DEFAULT_ARG struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_ioport_mapping(XSM_DEFAULT_ARG struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
 {
-    XSM_ASSERT_ACTION(XSM_HOOK);
+    XSM_ASSERT_ACTION(XSM_NONE);
     return xsm_default_action(action, current->domain, d);
 }
 
 static XSM_INLINE int xsm_pmu_op (XSM_DEFAULT_ARG struct domain *d, unsigned int op)
 {
-    XSM_ASSERT_ACTION(XSM_OTHER);
+    XSM_ASSERT_ACTION(XSM_NONE | XSM_DOM_SUPER);
     switch ( op )
     {
     case XENPMU_init:
     case XENPMU_finish:
     case XENPMU_lvtpc_set:
     case XENPMU_flush:
-        return xsm_default_action(XSM_HOOK, d, current->domain);
+        return xsm_default_action(XSM_NONE, d, current->domain);
     default:
-        return xsm_default_action(XSM_PRIV, d, current->domain);
+        return xsm_default_action(XSM_DOM_SUPER, d, current->domain);
     }
 }
 
@@ -713,7 +725,7 @@ static XSM_INLINE int xsm_pmu_op (XSM_DEFAULT_ARG struct domain *d, unsigned int
 
 static XSM_INLINE int xsm_dm_op(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    XSM_ASSERT_ACTION(DEV_EMU_PRIVS);
     return xsm_default_action(action, current->domain, d);
 }
 
@@ -745,7 +757,7 @@ static XSM_INLINE int xsm_argo_send(const struct domain *d,
 #include <public/version.h>
 static XSM_INLINE int xsm_xen_version (XSM_DEFAULT_ARG uint32_t op)
 {
-    XSM_ASSERT_ACTION(XSM_OTHER);
+    XSM_ASSERT_ACTION(XSM_NONE | XSM_PLAT_CTRL);
     switch ( op )
     {
     case XENVER_version:
@@ -761,14 +773,14 @@ static XSM_INLINE int xsm_xen_version (XSM_DEFAULT_ARG uint32_t op)
     case XENVER_pagesize:
     case XENVER_guest_handle:
         /* These MUST always be accessible to any guest by default. */
-        return xsm_default_action(XSM_HOOK, current->domain, NULL);
+        return xsm_default_action(XSM_NONE, current->domain, NULL);
     default:
-        return xsm_default_action(XSM_PRIV, current->domain, NULL);
+        return xsm_default_action(XSM_PLAT_CTRL, current->domain, NULL);
     }
 }
 
 static XSM_INLINE int xsm_domain_resource_map(XSM_DEFAULT_ARG struct domain *d)
 {
-    XSM_ASSERT_ACTION(XSM_DM_PRIV);
+    XSM_ASSERT_ACTION(DEV_EMU_PRIVS);
     return xsm_default_action(action, current->domain, d);
 }
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 7bdd254420..b50d8a711f 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -30,18 +30,7 @@ typedef u32 xsm_magic_t;
 #define XSM_MAGIC 0x0
 #endif
 
-/* These annotations are used by callers and in dummy.h to document the
- * default actions of XSM hooks. They should be compiled out otherwise.
- */
-enum xsm_default {
-    XSM_HOOK,     /* Guests can normally access the hypercall */
-    XSM_DM_PRIV,  /* Device model can perform on its target domain */
-    XSM_TARGET,   /* Can perform on self or your target domain */
-    XSM_PRIV,     /* Privileged - normally restricted to dom0 */
-    XSM_XS_PRIV,  /* Xenstore domain - can do some privileged operations */
-    XSM_OTHER     /* Something more complex */
-};
-typedef enum xsm_default xsm_default_t;
+typedef uint32_t xsm_default_t;
 
 struct xsm_operations {
     void (*security_domaininfo) (struct domain *d,
-- 
2.20.1



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

* [RFC PATCH 05/10] hardware domain: convert to domain roles
  2021-05-14 20:54 [RFC PATCH 00/10] xsm: introducing domain roles Daniel P. Smith
                   ` (3 preceding siblings ...)
  2021-05-14 20:54 ` [RFC PATCH 04/10] xsm: convert rewrite privilege check function Daniel P. Smith
@ 2021-05-14 20:54 ` Daniel P. Smith
  2021-06-18 14:47   ` Jan Beulich
  2021-05-14 20:54 ` [RFC PATCH 06/10] xsm-roles: covert the dummy system to roles Daniel P. Smith
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 16+ messages in thread
From: Daniel P. Smith @ 2021-05-14 20:54 UTC (permalink / raw)
  To: xen-devel
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, jbeulich, wl, roger.pau, tamas, tim, jgross,
	aisaila, ppircalabu, dfaggioli, paul, kevin.tian, dgdegra,
	adam.schwalm, scott.davis

This refactors the hardware_domain so that it is works within the
new domain roles construct.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/arch/x86/acpi/cpu_idle.c        |   3 +-
 xen/arch/x86/cpu/mcheck/vmce.h      |   3 +-
 xen/arch/x86/cpu/vpmu.c             |   7 +-
 xen/arch/x86/crash.c                |   2 +-
 xen/arch/x86/io_apic.c              |   9 ++-
 xen/arch/x86/mm.c                   |   2 +-
 xen/arch/x86/msi.c                  |   4 +-
 xen/arch/x86/nmi.c                  |   3 +-
 xen/arch/x86/setup.c                |   3 +
 xen/arch/x86/traps.c                |   2 +-
 xen/arch/x86/x86_64/mm.c            |  11 +--
 xen/common/domain.c                 | 114 ++++++++++++++++++++++------
 xen/common/event_channel.c          |   3 +-
 xen/common/kexec.c                  |   2 +-
 xen/common/keyhandler.c             |   4 +-
 xen/common/shutdown.c               |  14 ++--
 xen/common/vm_event.c               |   5 +-
 xen/common/xenoprof.c               |   3 +-
 xen/drivers/char/ns16550.c          |   3 +-
 xen/drivers/passthrough/pci.c       |  12 +--
 xen/drivers/passthrough/vtd/iommu.c |   2 +-
 xen/include/xen/sched.h             |   7 +-
 22 files changed, 152 insertions(+), 66 deletions(-)

diff --git a/xen/arch/x86/acpi/cpu_idle.c b/xen/arch/x86/acpi/cpu_idle.c
index c092086b33..7a42c56944 100644
--- a/xen/arch/x86/acpi/cpu_idle.c
+++ b/xen/arch/x86/acpi/cpu_idle.c
@@ -1206,7 +1206,8 @@ static void set_cx(
             cx->entry_method = ACPI_CSTATE_EM_HALT;
         break;
     case ACPI_ADR_SPACE_SYSTEM_IO:
-        if ( ioports_deny_access(hardware_domain, cx->address, cx->address) )
+        if ( ioports_deny_access(get_hardware_domain(),
+             cx->address, cx->address) )
             printk(XENLOG_WARNING "Could not deny access to port %04x\n",
                    cx->address);
         cx->entry_method = ACPI_CSTATE_EM_SYSIO;
diff --git a/xen/arch/x86/cpu/mcheck/vmce.h b/xen/arch/x86/cpu/mcheck/vmce.h
index 2e9b32a9bd..774cd8a5af 100644
--- a/xen/arch/x86/cpu/mcheck/vmce.h
+++ b/xen/arch/x86/cpu/mcheck/vmce.h
@@ -6,8 +6,7 @@
 int vmce_init(struct cpuinfo_x86 *c);
 
 #define dom0_vmce_enabled() \
-    (hardware_domain && \
-     evtchn_virq_enabled(domain_vcpu(hardware_domain, 0), VIRQ_MCA))
+    (evtchn_virq_enabled(domain_vcpu(get_hardware_domain(), 0), VIRQ_MCA))
 
 int unmmap_broken_page(struct domain *d, mfn_t mfn, unsigned long gfn);
 
diff --git a/xen/arch/x86/cpu/vpmu.c b/xen/arch/x86/cpu/vpmu.c
index 612b87526b..79715ce7e7 100644
--- a/xen/arch/x86/cpu/vpmu.c
+++ b/xen/arch/x86/cpu/vpmu.c
@@ -169,13 +169,14 @@ int vpmu_do_msr(unsigned int msr, uint64_t *msr_content,
 static inline struct vcpu *choose_hwdom_vcpu(void)
 {
     unsigned idx;
+    struct domain *hwdom = get_hardware_domain();
 
-    if ( hardware_domain->max_vcpus == 0 )
+    if ( hwdom->max_vcpus == 0 )
         return NULL;
 
-    idx = smp_processor_id() % hardware_domain->max_vcpus;
+    idx = smp_processor_id() % hwdom->max_vcpus;
 
-    return hardware_domain->vcpu[idx];
+    return hwdom->vcpu[idx];
 }
 
 void vpmu_do_interrupt(struct cpu_user_regs *regs)
diff --git a/xen/arch/x86/crash.c b/xen/arch/x86/crash.c
index 0611b4fb9b..e47f7da36d 100644
--- a/xen/arch/x86/crash.c
+++ b/xen/arch/x86/crash.c
@@ -210,7 +210,7 @@ void machine_crash_shutdown(void)
     info = kexec_crash_save_info();
     info->xen_phys_start = xen_phys_start;
     info->dom0_pfn_to_mfn_frame_list_list =
-        arch_get_pfn_to_mfn_frame_list_list(hardware_domain);
+        arch_get_pfn_to_mfn_frame_list_list(get_hardware_domain());
 }
 
 /*
diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c
index 58b26d962c..520dea2552 100644
--- a/xen/arch/x86/io_apic.c
+++ b/xen/arch/x86/io_apic.c
@@ -2351,6 +2351,7 @@ int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
     struct IO_APIC_route_entry rte = { 0 };
     unsigned long flags;
     struct irq_desc *desc;
+    struct domain *hwdom = get_hardware_domain();
 
     if ( (apic = ioapic_physbase_to_id(physbase)) < 0 )
         return apic;
@@ -2401,7 +2402,7 @@ int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
     if ( !rte.mask )
     {
         pirq = (irq >= 256) ? irq : rte.vector;
-        if ( pirq >= hardware_domain->nr_pirqs )
+        if ( pirq >= hwdom->nr_pirqs )
             return -EINVAL;
     }
     else
@@ -2443,10 +2444,10 @@ int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
     }
     if ( pirq >= 0 )
     {
-        spin_lock(&hardware_domain->event_lock);
-        ret = map_domain_pirq(hardware_domain, pirq, irq,
+        spin_lock(&hwdom->event_lock);
+        ret = map_domain_pirq(hwdom, pirq, irq,
                               MAP_PIRQ_TYPE_GSI, NULL);
-        spin_unlock(&hardware_domain->event_lock);
+        spin_unlock(&hwdom->event_lock);
         if ( ret < 0 )
             return ret;
     }
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 8ecb982a84..7859eef303 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -4917,7 +4917,7 @@ mfn_t alloc_xen_pagetable_new(void)
     {
         void *ptr = alloc_xenheap_page();
 
-        BUG_ON(!hardware_domain && !ptr);
+        BUG_ON(!ptr);
         return ptr ? virt_to_mfn(ptr) : INVALID_MFN;
     }
 
diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c
index 6d4a873130..ea8a9224ce 100644
--- a/xen/arch/x86/msi.c
+++ b/xen/arch/x86/msi.c
@@ -660,7 +660,7 @@ static int msi_capability_init(struct pci_dev *dev,
 
     *desc = entry;
     /* Restore the original MSI enabled bits  */
-    if ( !hardware_domain )
+    if ( !is_hardware_domain_started() )
     {
         /*
          * ..., except for internal requests (before Dom0 starts), in which
@@ -965,7 +965,7 @@ static int msix_capability_init(struct pci_dev *dev,
     ++msix->used_entries;
 
     /* Restore MSI-X enabled bits */
-    if ( !hardware_domain )
+    if ( !is_hardware_domain_started() )
     {
         /*
          * ..., except for internal requests (before Dom0 starts), in which
diff --git a/xen/arch/x86/nmi.c b/xen/arch/x86/nmi.c
index ab94a96c4d..61a083a836 100644
--- a/xen/arch/x86/nmi.c
+++ b/xen/arch/x86/nmi.c
@@ -594,7 +594,8 @@ static void do_nmi_stats(unsigned char key)
     for_each_online_cpu ( cpu )
         printk("%3u\t%3u\n", cpu, per_cpu(nmi_count, cpu));
 
-    if ( !hardware_domain || !(v = domain_vcpu(hardware_domain, 0)) )
+    if ( !is_hardware_domain_started() ||
+         !(v = domain_vcpu(get_hardware_domain(), 0)) )
         return;
 
     pend = v->arch.nmi_pending;
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index a6658d9769..e184f00117 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -776,6 +776,9 @@ static struct domain *__init create_dom0(const module_t *image,
     if ( IS_ERR(d) || (alloc_dom0_vcpu0(d) == NULL) )
         panic("Error creating domain 0\n");
 
+    /* Ensure the correct roles are assigned */
+    d->xsm_roles = CLASSIC_DOM0_PRIVS;
+
     /* Grab the DOM0 command line. */
     cmdline = image->string ? __va(image->string) : NULL;
     if ( cmdline || kextra )
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 3c2e563cce..dd47afe765 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -1683,7 +1683,7 @@ static bool pci_serr_nmicont(void)
 
 static void nmi_hwdom_report(unsigned int reason_idx)
 {
-    struct domain *d = hardware_domain;
+    struct domain *d = get_hardware_domain();
 
     if ( !d || !d->vcpu || !d->vcpu[0] || !is_pv_domain(d) /* PVH fixme */ )
         return;
diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c
index d7e67311fa..7bdb7a2487 100644
--- a/xen/arch/x86/x86_64/mm.c
+++ b/xen/arch/x86/x86_64/mm.c
@@ -1198,6 +1198,7 @@ int memory_add(unsigned long spfn, unsigned long epfn, unsigned int pxm)
     unsigned long old_max = max_page, old_total = total_pages;
     unsigned long old_node_start, old_node_span, orig_online;
     unsigned long i;
+    struct domain *hwdom = get_hardware_domain();
 
     dprintk(XENLOG_INFO, "memory_add %lx ~ %lx with pxm %x\n", spfn, epfn, pxm);
 
@@ -1280,12 +1281,12 @@ int memory_add(unsigned long spfn, unsigned long epfn, unsigned int pxm)
      * shared or being kept in sync then newly added memory needs to be
      * mapped here.
      */
-    if ( is_iommu_enabled(hardware_domain) &&
-         !iommu_use_hap_pt(hardware_domain) &&
-         !need_iommu_pt_sync(hardware_domain) )
+    if ( is_iommu_enabled(hwdom) &&
+         !iommu_use_hap_pt(hwdom) &&
+         !need_iommu_pt_sync(hwdom) )
     {
         for ( i = spfn; i < epfn; i++ )
-            if ( iommu_legacy_map(hardware_domain, _dfn(i), _mfn(i),
+            if ( iommu_legacy_map(hwdom, _dfn(i), _mfn(i),
                                   1ul << PAGE_ORDER_4K,
                                   IOMMUF_readable | IOMMUF_writable) )
                 break;
@@ -1293,7 +1294,7 @@ int memory_add(unsigned long spfn, unsigned long epfn, unsigned int pxm)
         {
             while (i-- > old_max)
                 /* If statement to satisfy __must_check. */
-                if ( iommu_legacy_unmap(hardware_domain, _dfn(i),
+                if ( iommu_legacy_unmap(hwdom, _dfn(i),
                                         1ul << PAGE_ORDER_4K) )
                     continue;
 
diff --git a/xen/common/domain.c b/xen/common/domain.c
index b3a3864421..d9b75bf835 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -45,6 +45,7 @@
 
 #ifdef CONFIG_X86
 #include <asm/guest.h>
+#include <asm/pv/shim.h>
 #endif
 
 /* Linux config option: propageted to domain0 */
@@ -302,23 +303,50 @@ struct vcpu *vcpu_create(struct domain *d, unsigned int vcpu_id)
     return NULL;
 }
 
-static int late_hwdom_init(struct domain *d)
+/* pivot_hw_ctl:
+ *  This is a one-way pivot from existing to new hardware domain. Upon success
+ *  the domain *next_hwdom will be in control of the hardware and domain
+ *  *curr_hwdom will no longer have access.
+ */
+static int pivot_hw_ctl(struct domain *next_hwdom)
 {
 #ifdef CONFIG_LATE_HWDOM
-    struct domain *dom0;
+    bool already_found = false;
+    struct domain **pd = &domain_list, *curr_hwdom = NULL;
+    domid_t dom0_id = 0;
     int rv;
 
-    if ( d != hardware_domain || d->domain_id == 0 )
+#ifdef CONFIG_PV_SHIM
+    /* On PV shim dom0 != 0 */
+    dom0_id = get_initial_domain_id();
+#endif
+
+    if ( !(next_hwdom->xsm_roles & XSM_HW_CTRL) &&
+         next_hwdom->domain_id == dom0_id )
         return 0;
 
-    rv = xsm_init_hardware_domain(XSM_NONE, d);
+    rv = xsm_init_hardware_domain(XSM_NONE, next_hwdom);
     if ( rv )
         return rv;
 
-    printk("Initialising hardware domain %d\n", hardware_domid);
+    spin_lock(&domlist_read_lock);
+
+    /* Walk whole list to ensure there is only one XSM_HW_CTRL domain */
+    for ( ; *pd != NULL; pd = &(*pd)->next_in_list )
+        if ( (*pd)->xsm_roles & XSM_HW_CTRL ) {
+            if ( !already_found )
+                panic("There should be only one domain with XSM_HW_CTRL\n");
+            already_found = true;
+            curr_hwdom = pd;
+        }
+
+    spin_unlock(&domlist_read_lock);
+
+    ASSERT(curr_hwdom != NULL);
+
+    printk("Initialising hardware domain %d\n", d->domain_id);
 
-    dom0 = rcu_lock_domain_by_id(0);
-    ASSERT(dom0 != NULL);
+    rcu_lock_domain(curr_hwdom);
     /*
      * Hardware resource ranges for domain 0 have been set up from
      * various sources intended to restrict the hardware domain's
@@ -331,17 +359,19 @@ static int late_hwdom_init(struct domain *d)
      * may be modified after this hypercall returns if a more complex
      * device model is desired.
      */
-    rangeset_swap(d->irq_caps, dom0->irq_caps);
-    rangeset_swap(d->iomem_caps, dom0->iomem_caps);
+    rangeset_swap(next_hwdom->irq_caps, curr_hwdom->irq_caps);
+    rangeset_swap(next_hwdom->iomem_caps, curr_hwdom->iomem_caps);
 #ifdef CONFIG_X86
-    rangeset_swap(d->arch.ioport_caps, dom0->arch.ioport_caps);
-    setup_io_bitmap(d);
-    setup_io_bitmap(dom0);
+    rangeset_swap(next_hwdom->arch.ioport_caps, curr_hwdom->arch.ioport_caps);
+    setup_io_bitmap(next_hwdom);
+    setup_io_bitmap(curr_hwdom);
 #endif
 
-    rcu_unlock_domain(dom0);
+    curr_hwdom->xsm_roles &= ! XSM_HW_CTRL;
 
-    iommu_hwdom_init(d);
+    rcu_unlock_domain(curr_hwdom);
+
+    iommu_hwdom_init(next_hwdom);
 
     return rv;
 #else
@@ -530,7 +560,7 @@ struct domain *domain_create(domid_t domid,
                              struct xen_domctl_createdomain *config,
                              bool is_priv)
 {
-    struct domain *d, **pd, *old_hwdom = NULL;
+    struct domain *d, **pd;
     enum { INIT_watchdog = 1u<<1,
            INIT_evtchn = 1u<<3, INIT_gnttab = 1u<<4, INIT_arch = 1u<<5 };
     int err, init_status = 0;
@@ -559,17 +589,19 @@ struct domain *domain_create(domid_t domid,
     /* Sort out our idea of is_control_domain(). */
     d->is_privileged = is_priv;
 
-    if (is_priv)
+    /* reality is that is_priv is only set when construction dom0 */
+    if (is_priv) {
         d->xsm_roles = CLASSIC_DOM0_PRIVS;
+        hardware_domain = d;
+    }
 
     /* Sort out our idea of is_hardware_domain(). */
-    if ( domid == 0 || domid == hardware_domid )
+    if ( domid == hardware_domid )
     {
         if ( hardware_domid < 0 || hardware_domid >= DOMID_FIRST_RESERVED )
             panic("The value of hardware_dom must be a valid domain ID\n");
 
-        old_hwdom = hardware_domain;
-        hardware_domain = d;
+        d->xsm_roles = CLASSIC_HWDOM_PRIVS;
     }
 
     TRACE_1D(TRC_DOM0_DOM_ADD, d->domain_id);
@@ -682,12 +714,14 @@ struct domain *domain_create(domid_t domid,
         if ( (err = sched_init_domain(d, 0)) != 0 )
             goto fail;
 
-        if ( (err = late_hwdom_init(d)) != 0 )
+        if ( (err = pivot_hw_ctl(d)) != 0 )
             goto fail;
 
         /*
          * Must not fail beyond this point, as our caller doesn't know whether
-         * the domain has been entered into domain_list or not.
+         * the domain has been entered into domain_list or not. Additionally
+         * if a hardware control pivot occurred then a failure will leave the
+         * platform without access to hardware.
          */
 
         spin_lock(&domlist_update_lock);
@@ -711,8 +745,6 @@ struct domain *domain_create(domid_t domid,
     err = err ?: -EILSEQ; /* Release build safety. */
 
     d->is_dying = DOMDYING_dead;
-    if ( hardware_domain == d )
-        hardware_domain = old_hwdom;
     atomic_set(&d->refcnt, DOMAIN_DESTROYED);
 
     sched_destroy_domain(d);
@@ -808,6 +840,42 @@ out:
 }
 
 
+bool is_hardware_domain_started()
+{
+    bool exists = false;
+    struct domain **pd = &domain_list;
+
+    if ( *pd != NULL) {
+        rcu_read_lock(&domlist_read_lock);
+
+        for ( ; *pd != NULL; pd = &(*pd)->next_in_list )
+            if ( (*pd)->xsm_roles & XSM_HW_CTRL )
+                break;
+
+        rcu_read_unlock(&domlist_read_lock);
+
+        if ( *pd != NULL )
+            exists = true;
+    }
+
+    if (exists)
+        ASSERT(*pd == hardware_domain);
+
+    return exists;
+}
+
+
+struct domain *get_hardware_domain()
+{
+    if (hardware_domain == NULL)
+        return NULL;
+
+    ASSERT(hardware_domain->xsm_roles & XSM_HW_CTRL);
+
+    return hardware_domain;
+}
+
+
 struct domain *get_domain_by_id(domid_t dom)
 {
     struct domain *d;
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index 5c987096d9..775f7aa00c 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -904,7 +904,8 @@ void send_global_virq(uint32_t virq)
 {
     ASSERT(virq_is_global(virq));
 
-    send_guest_global_virq(global_virq_handlers[virq] ?: hardware_domain, virq);
+    send_guest_global_virq(
+        global_virq_handlers[virq] ?: get_hardware_domain(), virq);
 }
 
 int set_global_virq_handler(struct domain *d, uint32_t virq)
diff --git a/xen/common/kexec.c b/xen/common/kexec.c
index 2d1d1ce205..f36d3f880c 100644
--- a/xen/common/kexec.c
+++ b/xen/common/kexec.c
@@ -903,7 +903,7 @@ static int kexec_load_slot(struct kexec_image *kimage)
 static uint16_t kexec_load_v1_arch(void)
 {
 #ifdef CONFIG_X86
-    return is_pv_32bit_domain(hardware_domain) ? EM_386 : EM_X86_64;
+    return is_pv_32bit_domain(get_hardware_domain()) ? EM_386 : EM_X86_64;
 #else
     return EM_NONE;
 #endif
diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c
index 8b9f378371..c22d02dea7 100644
--- a/xen/common/keyhandler.c
+++ b/xen/common/keyhandler.c
@@ -228,12 +228,12 @@ static void dump_hwdom_registers(unsigned char key)
 {
     struct vcpu *v;
 
-    if ( hardware_domain == NULL )
+    if ( is_hardware_domain_started() )
         return;
 
     printk("'%c' pressed -> dumping Dom0's registers\n", key);
 
-    for_each_vcpu ( hardware_domain, v )
+    for_each_vcpu ( get_hardware_domain(), v )
     {
         if ( alt_key_handling && softirq_pending(smp_processor_id()) )
         {
diff --git a/xen/common/shutdown.c b/xen/common/shutdown.c
index abde48aa4c..a8f475cc6f 100644
--- a/xen/common/shutdown.c
+++ b/xen/common/shutdown.c
@@ -32,43 +32,45 @@ static void noreturn maybe_reboot(void)
 
 void hwdom_shutdown(u8 reason)
 {
+    struct domain *hwdom = get_hardware_domain();
+
     switch ( reason )
     {
     case SHUTDOWN_poweroff:
         printk("Hardware Dom%u halted: halting machine\n",
-               hardware_domain->domain_id);
+               hwdom->domain_id);
         machine_halt();
         break; /* not reached */
 
     case SHUTDOWN_crash:
         debugger_trap_immediate();
-        printk("Hardware Dom%u crashed: ", hardware_domain->domain_id);
+        printk("Hardware Dom%u crashed: ", hwdom->domain_id);
         kexec_crash(CRASHREASON_HWDOM);
         maybe_reboot();
         break; /* not reached */
 
     case SHUTDOWN_reboot:
         printk("Hardware Dom%u shutdown: rebooting machine\n",
-               hardware_domain->domain_id);
+               hwdom->domain_id);
         machine_restart(0);
         break; /* not reached */
 
     case SHUTDOWN_watchdog:
         printk("Hardware Dom%u shutdown: watchdog rebooting machine\n",
-               hardware_domain->domain_id);
+               hwdom->domain_id);
         kexec_crash(CRASHREASON_WATCHDOG);
         machine_restart(0);
         break; /* not reached */
 
     case SHUTDOWN_soft_reset:
         printk("Hardware domain %d did unsupported soft reset, rebooting.\n",
-               hardware_domain->domain_id);
+               hwdom->domain_id);
         machine_restart(0);
         break; /* not reached */
 
     default:
         printk("Hardware Dom%u shutdown (unknown reason %u): ",
-               hardware_domain->domain_id, reason);
+               hwdom->domain_id, reason);
         maybe_reboot();
         break; /* not reached */
     }
diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c
index 103d0a207f..58cfcea056 100644
--- a/xen/common/vm_event.c
+++ b/xen/common/vm_event.c
@@ -577,6 +577,7 @@ void vm_event_cleanup(struct domain *d)
 int vm_event_domctl(struct domain *d, struct xen_domctl_vm_event_op *vec)
 {
     int rc;
+    struct domain *hwdom = get_hardware_domain();
 
     if ( vec->op == XEN_VM_EVENT_GET_VERSION )
     {
@@ -624,7 +625,7 @@ int vm_event_domctl(struct domain *d, struct xen_domctl_vm_event_op *vec)
         {
             rc = -EOPNOTSUPP;
             /* hvm fixme: p2m_is_foreign types need addressing */
-            if ( is_hvm_domain(hardware_domain) )
+            if ( is_hvm_domain(hwdom) )
                 break;
 
             rc = -ENODEV;
@@ -717,7 +718,7 @@ int vm_event_domctl(struct domain *d, struct xen_domctl_vm_event_op *vec)
         case XEN_VM_EVENT_ENABLE:
             rc = -EOPNOTSUPP;
             /* hvm fixme: p2m_is_foreign types need addressing */
-            if ( is_hvm_domain(hardware_domain) )
+            if ( is_hvm_domain(hwdom) )
                 break;
 
             rc = -ENODEV;
diff --git a/xen/common/xenoprof.c b/xen/common/xenoprof.c
index 4268c12e5d..bd8d17df1f 100644
--- a/xen/common/xenoprof.c
+++ b/xen/common/xenoprof.c
@@ -270,7 +270,8 @@ static int alloc_xenoprof_struct(
     bufsize = sizeof(struct xenoprof_buf);
     i = sizeof(struct event_log);
 #ifdef CONFIG_COMPAT
-    d->xenoprof->is_compat = is_pv_32bit_domain(is_passive ? hardware_domain : d);
+    d->xenoprof->is_compat =
+        is_pv_32bit_domain(is_passive ? get_hardware_domain() : d);
     if ( XENOPROF_COMPAT(d->xenoprof) )
     {
         bufsize = sizeof(struct compat_oprof_buf);
diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c
index 16a73d0c0e..e957b4732d 100644
--- a/xen/drivers/char/ns16550.c
+++ b/xen/drivers/char/ns16550.c
@@ -566,7 +566,8 @@ static void __init ns16550_endboot(struct serial_port *port)
 
     if ( uart->remapped_io_base )
         return;
-    rv = ioports_deny_access(hardware_domain, uart->io_base, uart->io_base + 7);
+    rv = ioports_deny_access(get_hardware_domain(),
+            uart->io_base, uart->io_base + 7);
     if ( rv != 0 )
         BUG();
 #endif
diff --git a/xen/drivers/passthrough/pci.c b/xen/drivers/passthrough/pci.c
index f9669c6afa..dcb1472e7e 100644
--- a/xen/drivers/passthrough/pci.c
+++ b/xen/drivers/passthrough/pci.c
@@ -776,7 +776,7 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn,
     ret = 0;
     if ( !pdev->domain )
     {
-        pdev->domain = hardware_domain;
+        pdev->domain = get_hardware_domain();
         ret = iommu_add_device(pdev);
         if ( ret )
         {
@@ -784,7 +784,7 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn,
             goto out;
         }
 
-        list_add(&pdev->domain_list, &hardware_domain->pdev_list);
+        list_add(&pdev->domain_list, &pdev->domain->pdev_list);
     }
     else
         iommu_enable_device(pdev);
@@ -860,7 +860,7 @@ static int deassign_device(struct domain *d, uint16_t seg, uint8_t bus,
     /* De-assignment from dom_io should de-quarantine the device */
     target = ((pdev->quarantine || iommu_quarantine) &&
               pdev->domain != dom_io) ?
-        dom_io : hardware_domain;
+        dom_io : get_hardware_domain();
 
     while ( pdev->phantom_stride )
     {
@@ -879,7 +879,7 @@ static int deassign_device(struct domain *d, uint16_t seg, uint8_t bus,
     if ( ret )
         goto out;
 
-    if ( pdev->domain == hardware_domain  )
+    if ( is_hardware_domain(pdev->domain) )
         pdev->quarantine = false;
 
     pdev->fault.count = 0;
@@ -1403,7 +1403,7 @@ static int device_assigned(u16 seg, u8 bus, u8 devfn)
      * domain or dom_io then it must be assigned to a guest, or be
      * hidden (owned by dom_xen).
      */
-    else if ( pdev->domain != hardware_domain &&
+    else if ( !is_hardware_domain(pdev->domain) &&
               pdev->domain != dom_io )
         rc = -EBUSY;
 
@@ -1426,7 +1426,7 @@ static int assign_device(struct domain *d, u16 seg, u8 bus, u8 devfn, u32 flag)
     /* device_assigned() should already have cleared the device for assignment */
     ASSERT(pcidevs_locked());
     pdev = pci_get_pdev(seg, bus, devfn);
-    ASSERT(pdev && (pdev->domain == hardware_domain ||
+    ASSERT(pdev && (is_hardware_domain(pdev->domain) ||
                     pdev->domain == dom_io));
 
     if ( pdev->msix )
diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c
index b2ca152e1f..580b329db9 100644
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -2358,7 +2358,7 @@ static int reassign_device_ownership(
      * can attempt to send arbitrary LAPIC/MSI messages. We are unprotected
      * by the root complex unless interrupt remapping is enabled.
      */
-    if ( (target != hardware_domain) && !iommu_intremap )
+    if ( (!is_hardware_domain(target)) && !iommu_intremap )
         untrusted_msi = true;
 
     /*
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 39681a5dff..55b7de93d2 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -475,6 +475,7 @@ struct domain
 #define XSM_XENSTORE  (1U<<31) /* Xenstore: domain that can do privileged operations on xenstore */
 #define CLASSIC_DOM0_PRIVS (XSM_PLAT_CTRL | XSM_DOM_BUILD | XSM_DOM_SUPER | \
 		XSM_DEV_EMUL | XSM_HW_CTRL | XSM_HW_SUPER | XSM_XENSTORE)
+#define CLASSIC_HWDOM_PRIVS (XSM_HW_CTRL | XSM_DEV_EMUL)
 /* Any access for which XSM_DEV_EMUL is the restriction, XSM_DOM_SUPER is an override */
 #define DEV_EMU_PRIVS (XSM_DOM_SUPER | XSM_DEV_EMUL)
 /* Anytime there is an XSM_TARGET check, XSM_SELF also applies, and XSM_DOM_SUPER is an override */
@@ -731,6 +732,10 @@ static inline struct domain *rcu_lock_current_domain(void)
     return /*rcu_lock_domain*/(current->domain);
 }
 
+bool is_hardware_domain_started(void);
+
+struct domain *get_hardware_domain(void);
+
 struct domain *get_domain_by_id(domid_t dom);
 
 struct domain *get_pg_owner(domid_t domid);
@@ -1048,7 +1053,7 @@ static always_inline bool is_hardware_domain(const struct domain *d)
     if ( IS_ENABLED(CONFIG_PV_SHIM_EXCLUSIVE) )
         return false;
 
-    return evaluate_nospec(d == hardware_domain);
+    return evaluate_nospec(d->xsm_roles & XSM_HW_CTRL);
 }
 
 /* This check is for functionality specific to a control domain */
-- 
2.20.1



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

* [RFC PATCH 06/10] xsm-roles: covert the dummy system to roles
  2021-05-14 20:54 [RFC PATCH 00/10] xsm: introducing domain roles Daniel P. Smith
                   ` (4 preceding siblings ...)
  2021-05-14 20:54 ` [RFC PATCH 05/10] hardware domain: convert to domain roles Daniel P. Smith
@ 2021-05-14 20:54 ` Daniel P. Smith
  2021-05-14 20:54 ` [RFC PATCH 07/10] xsm-roles: adjusting core xsm Daniel P. Smith
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Daniel P. Smith @ 2021-05-14 20:54 UTC (permalink / raw)
  To: xen-devel
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, jbeulich, wl, roger.pau, tamas, tim, jgross,
	aisaila, ppircalabu, dfaggioli, paul, kevin.tian, dgdegra,
	adam.schwalm, scott.davis

The difference between XSM and non-XSM was whether the "dummy" policy was
invoked via direct calls or through function pointers. The "dummy" policy
enforced a set of rules that effictively defined a loosely set of roles that a
domain may have. This builds on the work of replacing those rules with well
defined roles by moving away from pseudo is or is not XSM and formalizing the
roles checks as the core security framework.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/include/xen/sched.h |   9 -
 xen/include/xsm/roles.h |  70 ++++
 xen/include/xsm/xsm.h   | 689 +++++++++++++++++++++++++++-------------
 xen/xsm/xsm_core.c      |   4 +-
 4 files changed, 544 insertions(+), 228 deletions(-)
 create mode 100644 xen/include/xsm/roles.h

diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 55b7de93d2..d84b047359 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -473,15 +473,6 @@ struct domain
 #define XSM_HW_CTRL   (1U<<8)  /* Hardware Control: domain with physical hardware access and its allocation for domain usage */
 #define XSM_HW_SUPER  (1U<<9)  /* Hardware Supervisor: domain that control allocated physical hardware */
 #define XSM_XENSTORE  (1U<<31) /* Xenstore: domain that can do privileged operations on xenstore */
-#define CLASSIC_DOM0_PRIVS (XSM_PLAT_CTRL | XSM_DOM_BUILD | XSM_DOM_SUPER | \
-		XSM_DEV_EMUL | XSM_HW_CTRL | XSM_HW_SUPER | XSM_XENSTORE)
-#define CLASSIC_HWDOM_PRIVS (XSM_HW_CTRL | XSM_DEV_EMUL)
-/* Any access for which XSM_DEV_EMUL is the restriction, XSM_DOM_SUPER is an override */
-#define DEV_EMU_PRIVS (XSM_DOM_SUPER | XSM_DEV_EMUL)
-/* Anytime there is an XSM_TARGET check, XSM_SELF also applies, and XSM_DOM_SUPER is an override */
-#define TARGET_PRIVS (XSM_TARGET | XSM_SELF | XSM_DOM_SUPER)
-/* Anytime there is an XSM_XENSTORE check, XSM_DOM_SUPER is an override */
-#define XENSTORE_PRIVS (XSM_XENSTORE | XSM_DOM_SUPER)
     uint32_t         xsm_roles;
 
     /* Which guest this guest has privileges on */
diff --git a/xen/include/xsm/roles.h b/xen/include/xsm/roles.h
new file mode 100644
index 0000000000..e6989fffa6
--- /dev/null
+++ b/xen/include/xsm/roles.h
@@ -0,0 +1,70 @@
+/*
+ *  This file contains the XSM roles.
+ *
+ *  This work is based on the original XSM dummy policy.
+ *
+ *  Author:  Daniel P. Smith, <dpsmith@apertussolutions.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2,
+ *  as published by the Free Software Foundation.
+ */
+
+#ifndef __XSM_ROLES_H__
+#define __XSM_ROLES_H__
+
+#include <xen/sched.h>
+
+#define CLASSIC_DOM0_PRIVS (XSM_PLAT_CTRL | XSM_DOM_BUILD | XSM_DOM_SUPER | \
+		XSM_DEV_EMUL | XSM_HW_CTRL | XSM_HW_SUPER | XSM_XENSTORE)
+
+#define CLASSIC_HWDOM_PRIVS (XSM_HW_CTRL | XSM_DEV_EMUL)
+
+/* Any access for which XSM_DEV_EMUL is the restriction, XSM_DOM_SUPER is an override */
+#define DEV_EMU_PRIVS (XSM_DOM_SUPER | XSM_DEV_EMUL)
+
+/* Anytime there is an XSM_TARGET check, XSM_SELF also applies, and XSM_DOM_SUPER is an override */
+#define TARGET_PRIVS (XSM_TARGET | XSM_SELF | XSM_DOM_SUPER)
+
+/* Anytime there is an XSM_XENSTORE check, XSM_DOM_SUPER is an override */
+#define XENSTORE_PRIVS (XSM_XENSTORE | XSM_DOM_SUPER)
+
+typedef uint32_t xsm_role_t;
+
+static always_inline int xsm_validate_role(
+    xsm_role_t allowed, struct domain *src, struct domain *target)
+{
+    if ( allowed & XSM_NONE )
+        return 0;
+
+    if ( (allowed & XSM_SELF) && ((!target) || (src == target)) )
+        return 0;
+
+    if ( (allowed & XSM_TARGET) && ((target) && (src->target == target)) )
+        return 0;
+
+    /* XSM_DEV_EMUL is the only domain role with a condition, i.e. the
+     * role only applies to a domain's target.
+     */
+    if ( (allowed & XSM_DEV_EMUL) && (src->xsm_roles & XSM_DEV_EMUL)
+        && (target) && (src->target == target) )
+        return 0;
+
+    /* Mask out SELF, TARGET, and DEV_EMUL as they have been handled */
+    allowed &= ~(XSM_SELF | XSM_TARGET | XSM_DEV_EMUL);
+
+    /* Checks if the domain has one of the remaining roles set on it:
+     *      XSM_PLAT_CTRL
+     *      XSM_DOM_BUILD
+     *      XSM_DOM_SUPER
+     *      XSM_HW_CTRL
+     *      XSM_HW_SUPER
+     *      XSM_XENSTORE
+     */
+    if (src->xsm_roles & allowed)
+        return 0;
+
+    return -EPERM;
+}
+
+#endif /* __XSM_ROLES_H__ */
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index b50d8a711f..50f2f547dc 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -16,8 +16,12 @@
 #define __XSM_H__
 
 #include <xen/sched.h>
+#include <xsm/roles.h>
 #include <xen/multiboot.h>
 
+#include <public/version.h>
+#include <public/hvm/params.h>
+
 typedef void xsm_op_t;
 DEFINE_XEN_GUEST_HANDLE(xsm_op_t);
 
@@ -30,8 +34,6 @@ typedef u32 xsm_magic_t;
 #define XSM_MAGIC 0x0
 #endif
 
-typedef uint32_t xsm_default_t;
-
 struct xsm_operations {
     void (*security_domaininfo) (struct domain *d,
                                         struct xen_domctl_getdomaininfo *info);
@@ -178,564 +180,797 @@ struct xsm_operations {
 #endif
 };
 
-#ifdef CONFIG_XSM
-
 extern struct xsm_operations *xsm_ops;
 
-#ifndef XSM_NO_WRAPPERS
+#define CALL_XSM_OP(op, ...)                            \
+    do {                                                \
+        if ( xsm_ops && xsm_ops->op )                   \
+            return xsm_ops->op(__VA_ARGS__);            \
+    } while ( 0 )
+
+#define CALL_XSM_OP_NORET(op, ...)                      \
+    do {                                                \
+        if ( xsm_ops && xsm_ops->op ) {                 \
+            xsm_ops->op(__VA_ARGS__);                   \
+            return;                                     \
+        }                                               \
+    } while ( 0 )
+
+#define XSM_ALLOWED_ROLES(def)                          \
+    do {                                                \
+        BUG_ON( !((def) & role) );                      \
+    } while ( 0 )
 
 static inline void xsm_security_domaininfo (struct domain *d,
                                         struct xen_domctl_getdomaininfo *info)
 {
-    xsm_ops->security_domaininfo(d, info);
+    CALL_XSM_OP_NORET(security_domaininfo,d, info);
+
+    return;
 }
 
-static inline int xsm_domain_create (xsm_default_t def, struct domain *d, u32 ssidref)
+static inline int xsm_domain_create (xsm_role_t role, struct domain *d, u32 ssidref)
 {
-    return xsm_ops->domain_create(d, ssidref);
+    CALL_XSM_OP(domain_create, d, ssidref);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_getdomaininfo (xsm_default_t def, struct domain *d)
+static inline int xsm_getdomaininfo (xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->getdomaininfo(d);
+    CALL_XSM_OP(getdomaininfo, d);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_domctl_scheduler_op (xsm_default_t def, struct domain *d, int cmd)
+static inline int xsm_domctl_scheduler_op (xsm_role_t role, struct domain *d, int cmd)
 {
-    return xsm_ops->domctl_scheduler_op(d, cmd);
+    CALL_XSM_OP(domctl_scheduler_op, d, cmd);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_sysctl_scheduler_op (xsm_default_t def, int cmd)
+static inline int xsm_sysctl_scheduler_op (xsm_role_t role, int cmd)
 {
-    return xsm_ops->sysctl_scheduler_op(cmd);
+    CALL_XSM_OP(sysctl_scheduler_op, cmd);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_set_target (xsm_default_t def, struct domain *d, struct domain *e)
+static inline int xsm_set_target (xsm_role_t role, struct domain *d, struct domain *e)
 {
-    return xsm_ops->set_target(d, e);
+    CALL_XSM_OP(set_target, d, e);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_domctl (xsm_default_t def, struct domain *d, int cmd)
+static inline int xsm_domctl (xsm_role_t role, struct domain *d, int cmd)
 {
-    return xsm_ops->domctl(d, cmd);
+    CALL_XSM_OP(domctl, d, cmd);
+    XSM_ALLOWED_ROLES(DEV_EMU_PRIVS | XENSTORE_PRIVS | XSM_DOM_SUPER);
+    switch ( cmd )
+    {
+    case XEN_DOMCTL_ioport_mapping:
+    case XEN_DOMCTL_memory_mapping:
+    case XEN_DOMCTL_bind_pt_irq:
+    case XEN_DOMCTL_unbind_pt_irq:
+        return xsm_validate_role(DEV_EMU_PRIVS, current->domain, d);
+    case XEN_DOMCTL_getdomaininfo:
+        return xsm_validate_role(XENSTORE_PRIVS, current->domain, d);
+    default:
+        return xsm_validate_role(XSM_DOM_SUPER, current->domain, d);
+    }
 }
 
-static inline int xsm_sysctl (xsm_default_t def, int cmd)
+static inline int xsm_sysctl (xsm_role_t role, int cmd)
 {
-    return xsm_ops->sysctl(cmd);
+    CALL_XSM_OP(sysctl, cmd);
+    XSM_ALLOWED_ROLES(XSM_PLAT_CTRL);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_readconsole (xsm_default_t def, uint32_t clear)
+static inline int xsm_readconsole (xsm_role_t role, uint32_t clear)
 {
-    return xsm_ops->readconsole(clear);
+    CALL_XSM_OP(readconsole, clear);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_evtchn_unbound (xsm_default_t def, struct domain *d1, struct evtchn *chn,
+static inline int xsm_evtchn_unbound (xsm_role_t role, struct domain *d1, struct evtchn *chn,
                                                                     domid_t id2)
 {
-    return xsm_ops->evtchn_unbound(d1, chn, id2);
+    CALL_XSM_OP(evtchn_unbound, d1, chn, id2);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, current->domain, d1);
 }
 
-static inline int xsm_evtchn_interdomain (xsm_default_t def, struct domain *d1,
+static inline int xsm_evtchn_interdomain (xsm_role_t role, struct domain *d1,
                 struct evtchn *chan1, struct domain *d2, struct evtchn *chan2)
 {
-    return xsm_ops->evtchn_interdomain(d1, chan1, d2, chan2);
+    CALL_XSM_OP(evtchn_interdomain, d1, chan1, d2, chan2);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, d1, d2);
 }
 
 static inline void xsm_evtchn_close_post (struct evtchn *chn)
 {
-    xsm_ops->evtchn_close_post(chn);
+    CALL_XSM_OP_NORET(evtchn_close_post, chn);
+    return;
 }
 
-static inline int xsm_evtchn_send (xsm_default_t def, struct domain *d, struct evtchn *chn)
+static inline int xsm_evtchn_send (xsm_role_t role, struct domain *d, struct evtchn *chn)
 {
-    return xsm_ops->evtchn_send(d, chn);
+    CALL_XSM_OP(evtchn_send, d, chn);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, d, NULL);
 }
 
-static inline int xsm_evtchn_status (xsm_default_t def, struct domain *d, struct evtchn *chn)
+static inline int xsm_evtchn_status (xsm_role_t role, struct domain *d, struct evtchn *chn)
 {
-    return xsm_ops->evtchn_status(d, chn);
+    CALL_XSM_OP(evtchn_status, d, chn);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_evtchn_reset (xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_evtchn_reset (xsm_role_t role, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->evtchn_reset(d1, d2);
+    CALL_XSM_OP(evtchn_reset, d1, d2);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, d1, d2);
 }
 
-static inline int xsm_grant_mapref (xsm_default_t def, struct domain *d1, struct domain *d2,
+static inline int xsm_grant_mapref (xsm_role_t role, struct domain *d1, struct domain *d2,
                                                                 uint32_t flags)
 {
-    return xsm_ops->grant_mapref(d1, d2, flags);
+    CALL_XSM_OP(grant_mapref, d1, d2, flags);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, d1, d2);
 }
 
-static inline int xsm_grant_unmapref (xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_grant_unmapref (xsm_role_t role, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->grant_unmapref(d1, d2);
+    CALL_XSM_OP(grant_unmapref, d1, d2);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, d1, d2);
 }
 
-static inline int xsm_grant_setup (xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_grant_setup (xsm_role_t role, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->grant_setup(d1, d2);
+    CALL_XSM_OP(grant_setup, d1, d2);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, d1, d2);
 }
 
-static inline int xsm_grant_transfer (xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_grant_transfer (xsm_role_t role, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->grant_transfer(d1, d2);
+    CALL_XSM_OP(grant_transfer, d1, d2);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, d1, d2);
 }
 
-static inline int xsm_grant_copy (xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_grant_copy (xsm_role_t role, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->grant_copy(d1, d2);
+    CALL_XSM_OP(grant_copy, d1, d2);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, d1, d2);
 }
 
-static inline int xsm_grant_query_size (xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_grant_query_size (xsm_role_t role, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->grant_query_size(d1, d2);
+    CALL_XSM_OP(grant_query_size, d1, d2);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, d1, d2);
 }
 
 static inline int xsm_alloc_security_domain (struct domain *d)
 {
-    return xsm_ops->alloc_security_domain(d);
+    CALL_XSM_OP(alloc_security_domain, d);
+    return 0;
 }
 
 static inline void xsm_free_security_domain (struct domain *d)
 {
-    xsm_ops->free_security_domain(d);
+    CALL_XSM_OP_NORET(free_security_domain, d);
+    return;
 }
 
 static inline int xsm_alloc_security_evtchns(
     struct evtchn chn[], unsigned int nr)
 {
-    return xsm_ops->alloc_security_evtchns(chn, nr);
+    CALL_XSM_OP(alloc_security_evtchns, chn, nr);
+    return 0;
 }
 
 static inline void xsm_free_security_evtchns(
     struct evtchn chn[], unsigned int nr)
 {
-    xsm_ops->free_security_evtchns(chn, nr);
+    CALL_XSM_OP_NORET(free_security_evtchns, chn, nr);
+    return;
 }
 
 static inline char *xsm_show_security_evtchn (struct domain *d, const struct evtchn *chn)
 {
-    return xsm_ops->show_security_evtchn(d, chn);
+    CALL_XSM_OP(show_security_evtchn, d, chn);
+    return NULL;
 }
 
-static inline int xsm_init_hardware_domain (xsm_default_t def, struct domain *d)
+static inline int xsm_init_hardware_domain (xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->init_hardware_domain(d);
+    CALL_XSM_OP(init_hardware_domain, d);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_get_pod_target (xsm_default_t def, struct domain *d)
+static inline int xsm_get_pod_target (xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->get_pod_target(d);
+    CALL_XSM_OP(get_pod_target, d);
+    XSM_ALLOWED_ROLES(XSM_DOM_SUPER);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_set_pod_target (xsm_default_t def, struct domain *d)
+static inline int xsm_set_pod_target (xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->set_pod_target(d);
+    CALL_XSM_OP(set_pod_target, d);
+    XSM_ALLOWED_ROLES(XSM_DOM_SUPER);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_memory_exchange (xsm_default_t def, struct domain *d)
+static inline int xsm_memory_exchange (xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->memory_exchange(d);
+    CALL_XSM_OP(memory_exchange, d);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_memory_adjust_reservation (xsm_default_t def, struct domain *d1, struct
+static inline int xsm_memory_adjust_reservation (xsm_role_t role, struct domain *d1, struct
                                                                     domain *d2)
 {
-    return xsm_ops->memory_adjust_reservation(d1, d2);
+    CALL_XSM_OP(memory_adjust_reservation, d1, d2);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, d1, d2);
 }
 
-static inline int xsm_memory_stat_reservation (xsm_default_t def, struct domain *d1,
+static inline int xsm_memory_stat_reservation (xsm_role_t role, struct domain *d1,
                                                             struct domain *d2)
 {
-    return xsm_ops->memory_stat_reservation(d1, d2);
+    CALL_XSM_OP(memory_stat_reservation, d1, d2);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, d1, d2);
 }
 
-static inline int xsm_memory_pin_page(xsm_default_t def, struct domain *d1, struct domain *d2,
+static inline int xsm_memory_pin_page(xsm_role_t role, struct domain *d1, struct domain *d2,
                                       struct page_info *page)
 {
-    return xsm_ops->memory_pin_page(d1, d2, page);
+    CALL_XSM_OP(memory_pin_page, d1, d2, page);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, d1, d2);
 }
 
-static inline int xsm_add_to_physmap(xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_add_to_physmap(xsm_role_t role, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->add_to_physmap(d1, d2);
+    CALL_XSM_OP(add_to_physmap, d1, d2);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, d1, d2);
 }
 
-static inline int xsm_remove_from_physmap(xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_remove_from_physmap(xsm_role_t role, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->remove_from_physmap(d1, d2);
+    CALL_XSM_OP(remove_from_physmap, d1, d2);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, d1, d2);
 }
 
-static inline int xsm_map_gmfn_foreign (xsm_default_t def, struct domain *d, struct domain *t)
+static inline int xsm_map_gmfn_foreign (xsm_role_t role, struct domain *d, struct domain *t)
 {
-    return xsm_ops->map_gmfn_foreign(d, t);
+    CALL_XSM_OP(map_gmfn_foreign, d, t);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, d, t);
 }
 
-static inline int xsm_claim_pages(xsm_default_t def, struct domain *d)
+static inline int xsm_claim_pages(xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->claim_pages(d);
+    CALL_XSM_OP(claim_pages, d);
+    XSM_ALLOWED_ROLES(XSM_DOM_SUPER);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_console_io (xsm_default_t def, struct domain *d, int cmd)
+static inline int xsm_console_io (xsm_role_t role, struct domain *d, int cmd)
 {
-    return xsm_ops->console_io(d, cmd);
+    CALL_XSM_OP(console_io, d, cmd);
+    XSM_ALLOWED_ROLES(XSM_NONE|XSM_DOM_SUPER);
+    if ( d->is_console )
+        return xsm_validate_role(XSM_NONE, d, NULL);
+#ifdef CONFIG_VERBOSE_DEBUG
+    if ( cmd == CONSOLEIO_write )
+        return xsm_validate_role(XSM_NONE, d, NULL);
+#endif
+    return xsm_validate_role(XSM_DOM_SUPER, d, NULL);
 }
 
-static inline int xsm_profile (xsm_default_t def, struct domain *d, int op)
+static inline int xsm_profile (xsm_role_t role, struct domain *d, int op)
 {
-    return xsm_ops->profile(d, op);
+    CALL_XSM_OP(profile, d, op);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, d, NULL);
 }
 
-static inline int xsm_kexec (xsm_default_t def)
+static inline int xsm_kexec (xsm_role_t role)
 {
-    return xsm_ops->kexec();
+    CALL_XSM_OP(kexec);
+    XSM_ALLOWED_ROLES(XSM_PLAT_CTRL);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_schedop_shutdown (xsm_default_t def, struct domain *d1, struct domain *d2)
+static inline int xsm_schedop_shutdown (xsm_role_t role, struct domain *d1, struct domain *d2)
 {
-    return xsm_ops->schedop_shutdown(d1, d2);
+    CALL_XSM_OP(schedop_shutdown, d1, d2);
+    XSM_ALLOWED_ROLES(DEV_EMU_PRIVS);
+    return xsm_validate_role(role, d1, d2);
 }
 
 static inline char *xsm_show_irq_sid (int irq)
 {
-    return xsm_ops->show_irq_sid(irq);
+    CALL_XSM_OP(show_irq_sid, irq);
+    return NULL;
 }
 
-static inline int xsm_map_domain_pirq (xsm_default_t def, struct domain *d)
+static inline int xsm_map_domain_pirq (xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->map_domain_pirq(d);
+    CALL_XSM_OP(map_domain_pirq, d);
+    XSM_ALLOWED_ROLES(DEV_EMU_PRIVS);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_map_domain_irq (xsm_default_t def, struct domain *d, int irq, void *data)
+static inline int xsm_map_domain_irq (xsm_role_t role, struct domain *d, int irq, void *data)
 {
-    return xsm_ops->map_domain_irq(d, irq, data);
+    CALL_XSM_OP(map_domain_irq, d, irq, data);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_unmap_domain_pirq (xsm_default_t def, struct domain *d)
+static inline int xsm_unmap_domain_pirq (xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->unmap_domain_pirq(d);
+    CALL_XSM_OP(unmap_domain_pirq, d);
+    XSM_ALLOWED_ROLES(DEV_EMU_PRIVS);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_unmap_domain_irq (xsm_default_t def, struct domain *d, int irq, void *data)
+static inline int xsm_unmap_domain_irq (xsm_role_t role, struct domain *d, int irq, void *data)
 {
-    return xsm_ops->unmap_domain_irq(d, irq, data);
+    CALL_XSM_OP(unmap_domain_irq, d, irq, data);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_bind_pt_irq(xsm_default_t def, struct domain *d,
+static inline int xsm_bind_pt_irq(xsm_role_t role, struct domain *d,
                                   struct xen_domctl_bind_pt_irq *bind)
 {
-    return xsm_ops->bind_pt_irq(d, bind);
+    CALL_XSM_OP(bind_pt_irq, d, bind);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_unbind_pt_irq(xsm_default_t def, struct domain *d,
+static inline int xsm_unbind_pt_irq(xsm_role_t role, struct domain *d,
                                     struct xen_domctl_bind_pt_irq *bind)
 {
-    return xsm_ops->unbind_pt_irq(d, bind);
+    CALL_XSM_OP(unbind_pt_irq, d, bind);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_irq_permission (xsm_default_t def, struct domain *d, int pirq, uint8_t allow)
+static inline int xsm_irq_permission (xsm_role_t role, struct domain *d, int pirq, uint8_t allow)
 {
-    return xsm_ops->irq_permission(d, pirq, allow);
+    CALL_XSM_OP(irq_permission, d, pirq, allow);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_iomem_permission (xsm_default_t def, struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
+static inline int xsm_iomem_permission (xsm_role_t role, struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
 {
-    return xsm_ops->iomem_permission(d, s, e, allow);
+    CALL_XSM_OP(iomem_permission, d, s, e, allow);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_iomem_mapping (xsm_default_t def, struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
+static inline int xsm_iomem_mapping (xsm_role_t role, struct domain *d, uint64_t s, uint64_t e, uint8_t allow)
 {
-    return xsm_ops->iomem_mapping(d, s, e, allow);
+    CALL_XSM_OP(iomem_mapping, d, s, e, allow);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_pci_config_permission (xsm_default_t def, struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access)
+static inline int xsm_pci_config_permission (xsm_role_t role, struct domain *d, uint32_t machine_bdf, uint16_t start, uint16_t end, uint8_t access)
 {
-    return xsm_ops->pci_config_permission(d, machine_bdf, start, end, access);
+    CALL_XSM_OP(pci_config_permission, d, machine_bdf, start, end, access);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
 #if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
-static inline int xsm_get_device_group(xsm_default_t def, uint32_t machine_bdf)
+static inline int xsm_get_device_group(xsm_role_t role, uint32_t machine_bdf)
 {
-    return xsm_ops->get_device_group(machine_bdf);
+    CALL_XSM_OP(get_device_group, machine_bdf);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_assign_device(xsm_default_t def, struct domain *d, uint32_t machine_bdf)
+static inline int xsm_assign_device(xsm_role_t role, struct domain *d, uint32_t machine_bdf)
 {
-    return xsm_ops->assign_device(d, machine_bdf);
+    CALL_XSM_OP(assign_device, d, machine_bdf);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_deassign_device(xsm_default_t def, struct domain *d, uint32_t machine_bdf)
+static inline int xsm_deassign_device(xsm_role_t role, struct domain *d, uint32_t machine_bdf)
 {
-    return xsm_ops->deassign_device(d, machine_bdf);
+    CALL_XSM_OP(deassign_device, d, machine_bdf);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 #endif /* HAS_PASSTHROUGH && HAS_PCI) */
 
 #if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE)
-static inline int xsm_assign_dtdevice(xsm_default_t def, struct domain *d,
+static inline int xsm_assign_dtdevice(xsm_role_t role, struct domain *d,
                                       const char *dtpath)
 {
-    return xsm_ops->assign_dtdevice(d, dtpath);
+    CALL_XSM_OP(assign_dtdevice, d, dtpath);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_deassign_dtdevice(xsm_default_t def, struct domain *d,
+static inline int xsm_deassign_dtdevice(xsm_role_t role, struct domain *d,
                                         const char *dtpath)
 {
-    return xsm_ops->deassign_dtdevice(d, dtpath);
+    CALL_XSM_OP(deassign_dtdevice, d, dtpath);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
 #endif /* HAS_PASSTHROUGH && HAS_DEVICE_TREE */
 
-static inline int xsm_resource_plug_pci (xsm_default_t def, uint32_t machine_bdf)
+static inline int xsm_resource_plug_pci (xsm_role_t role, uint32_t machine_bdf)
 {
-    return xsm_ops->resource_plug_pci(machine_bdf);
+    CALL_XSM_OP(resource_plug_pci, machine_bdf);
+    XSM_ALLOWED_ROLES(XSM_HW_CTRL);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_resource_unplug_pci (xsm_default_t def, uint32_t machine_bdf)
+static inline int xsm_resource_unplug_pci (xsm_role_t role, uint32_t machine_bdf)
 {
-    return xsm_ops->resource_unplug_pci(machine_bdf);
+    CALL_XSM_OP(resource_unplug_pci, machine_bdf);
+    XSM_ALLOWED_ROLES(XSM_HW_CTRL);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_resource_plug_core (xsm_default_t def)
+static inline int xsm_resource_plug_core (xsm_role_t role)
 {
-    return xsm_ops->resource_plug_core();
+    CALL_XSM_OP(resource_plug_core);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_resource_unplug_core (xsm_default_t def)
+static inline int xsm_resource_unplug_core (xsm_role_t role)
 {
-    return xsm_ops->resource_unplug_core();
+    CALL_XSM_OP(resource_unplug_core);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_resource_setup_pci (xsm_default_t def, uint32_t machine_bdf)
+static inline int xsm_resource_setup_pci (xsm_role_t role, uint32_t machine_bdf)
 {
-    return xsm_ops->resource_setup_pci(machine_bdf);
+    CALL_XSM_OP(resource_setup_pci, machine_bdf);
+    XSM_ALLOWED_ROLES(XSM_HW_CTRL);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_resource_setup_gsi (xsm_default_t def, int gsi)
+static inline int xsm_resource_setup_gsi (xsm_role_t role, int gsi)
 {
-    return xsm_ops->resource_setup_gsi(gsi);
+    CALL_XSM_OP(resource_setup_gsi, gsi);
+    XSM_ALLOWED_ROLES(XSM_HW_CTRL);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_resource_setup_misc (xsm_default_t def)
+static inline int xsm_resource_setup_misc (xsm_role_t role)
 {
-    return xsm_ops->resource_setup_misc();
+    CALL_XSM_OP(resource_setup_misc);
+    XSM_ALLOWED_ROLES(XSM_HW_CTRL);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_page_offline(xsm_default_t def, uint32_t cmd)
+static inline int xsm_page_offline(xsm_role_t role, uint32_t cmd)
 {
-    return xsm_ops->page_offline(cmd);
+    CALL_XSM_OP(page_offline, cmd);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_hypfs_op(xsm_default_t def)
+static inline int xsm_hypfs_op(xsm_role_t role)
 {
-    return xsm_ops->hypfs_op();
+    CALL_XSM_OP(hypfs_op);
+    XSM_ALLOWED_ROLES(XSM_PLAT_CTRL);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
 static inline long xsm_do_xsm_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
 {
-    return xsm_ops->do_xsm_op(op);
+    CALL_XSM_OP(do_xsm_op, op);
+    return -ENOSYS;
 }
 
 #ifdef CONFIG_COMPAT
 static inline int xsm_do_compat_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
 {
-    return xsm_ops->do_compat_op(op);
+    CALL_XSM_OP(do_compat_op, op);
+    return -ENOSYS;
 }
 #endif
 
-static inline int xsm_hvm_param (xsm_default_t def, struct domain *d, unsigned long op)
+static inline int xsm_hvm_param (xsm_role_t role, struct domain *d, unsigned long op)
 {
-    return xsm_ops->hvm_param(d, op);
+    CALL_XSM_OP(hvm_param, d, op);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_hvm_control(xsm_default_t def, struct domain *d, unsigned long op)
+static inline int xsm_hvm_control(xsm_role_t role, struct domain *d, unsigned long op)
 {
-    return xsm_ops->hvm_control(d, op);
+    CALL_XSM_OP(hvm_control, d, op);
+    XSM_ALLOWED_ROLES(DEV_EMU_PRIVS);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_hvm_param_altp2mhvm (xsm_default_t def, struct domain *d)
+static inline int xsm_hvm_param_altp2mhvm (xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->hvm_param_altp2mhvm(d);
+    CALL_XSM_OP(hvm_param_altp2mhvm, d);
+    XSM_ALLOWED_ROLES(XSM_DOM_SUPER);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_hvm_altp2mhvm_op (xsm_default_t def, struct domain *d, uint64_t mode, uint32_t op)
+static inline int xsm_hvm_altp2mhvm_op (xsm_role_t role, struct domain *d, uint64_t mode, uint32_t op)
 {
-    return xsm_ops->hvm_altp2mhvm_op(d, mode, op);
+    CALL_XSM_OP(hvm_altp2mhvm_op, d, mode, op);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS | DEV_EMU_PRIVS);
+
+    switch ( mode )
+    {
+    case XEN_ALTP2M_mixed:
+        return xsm_validate_role(TARGET_PRIVS, current->domain, d);
+    case XEN_ALTP2M_external:
+        return xsm_validate_role(DEV_EMU_PRIVS, current->domain, d);
+    case XEN_ALTP2M_limited:
+        if ( HVMOP_altp2m_vcpu_enable_notify == op )
+            return xsm_validate_role(TARGET_PRIVS, current->domain, d);
+        return xsm_validate_role(DEV_EMU_PRIVS, current->domain, d);
+    default:
+        return -EPERM;
+    }
 }
 
-static inline int xsm_get_vnumainfo (xsm_default_t def, struct domain *d)
+static inline int xsm_get_vnumainfo (xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->get_vnumainfo(d);
+    CALL_XSM_OP(get_vnumainfo, d);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_vm_event_control (xsm_default_t def, struct domain *d, int mode, int op)
+static inline int xsm_vm_event_control (xsm_role_t role, struct domain *d, int mode, int op)
 {
-    return xsm_ops->vm_event_control(d, mode, op);
+    CALL_XSM_OP(vm_event_control, d, mode, op);
+    XSM_ALLOWED_ROLES(XSM_DOM_SUPER);
+    return xsm_validate_role(role, current->domain, d);
 }
 
 #ifdef CONFIG_MEM_ACCESS
-static inline int xsm_mem_access (xsm_default_t def, struct domain *d)
+static inline int xsm_mem_access (xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->mem_access(d);
+    CALL_XSM_OP(mem_access, d);
+    XSM_ALLOWED_ROLES(DEV_EMU_PRIVS);
+    return xsm_validate_role(role, current->domain, d);
 }
 #endif
 
 #ifdef CONFIG_HAS_MEM_PAGING
-static inline int xsm_mem_paging (xsm_default_t def, struct domain *d)
+static inline int xsm_mem_paging (xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->mem_paging(d);
+    CALL_XSM_OP(mem_paging, d);
+    XSM_ALLOWED_ROLES(DEV_EMU_PRIVS);
+    return xsm_validate_role(role, current->domain, d);
 }
 #endif
 
 #ifdef CONFIG_MEM_SHARING
-static inline int xsm_mem_sharing (xsm_default_t def, struct domain *d)
+static inline int xsm_mem_sharing (xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->mem_sharing(d);
+    CALL_XSM_OP(mem_sharing, d);
+    XSM_ALLOWED_ROLES(DEV_EMU_PRIVS);
+    return xsm_validate_role(role, current->domain, d);
 }
 #endif
 
-static inline int xsm_platform_op (xsm_default_t def, uint32_t op)
+static inline int xsm_platform_op (xsm_role_t role, uint32_t op)
 {
-    return xsm_ops->platform_op(op);
+    CALL_XSM_OP(platform_op, op);
+    XSM_ALLOWED_ROLES(XSM_PLAT_CTRL);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
 #ifdef CONFIG_X86
-static inline int xsm_do_mca(xsm_default_t def)
-{
-    return xsm_ops->do_mca();
-}
-
-static inline int xsm_shadow_control (xsm_default_t def, struct domain *d, uint32_t op)
+static inline int xsm_do_mca(xsm_role_t role)
 {
-    return xsm_ops->shadow_control(d, op);
+    CALL_XSM_OP(do_mca);
+    XSM_ALLOWED_ROLES(XSM_PLAT_CTRL);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_mem_sharing_op (xsm_default_t def, struct domain *d, struct domain *cd, int op)
+static inline int xsm_shadow_control (xsm_role_t role, struct domain *d, uint32_t op)
 {
-    return xsm_ops->mem_sharing_op(d, cd, op);
+    CALL_XSM_OP(shadow_control, d, op);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_apic (xsm_default_t def, struct domain *d, int cmd)
+static inline int xsm_mem_sharing_op (xsm_role_t role, struct domain *d, struct domain *cd, int op)
 {
-    return xsm_ops->apic(d, cmd);
+    CALL_XSM_OP(mem_sharing_op, d, cd, op);
+    XSM_ALLOWED_ROLES(DEV_EMU_PRIVS);
+    return xsm_validate_role(role, current->domain, cd);
 }
 
-static inline int xsm_memtype (xsm_default_t def, uint32_t access)
+static inline int xsm_apic (xsm_role_t role, struct domain *d, int cmd)
 {
-    return xsm_ops->memtype(access);
+    CALL_XSM_OP(apic, d, cmd);
+    XSM_ALLOWED_ROLES(XSM_HW_CTRL);
+    return xsm_validate_role(role, d, NULL);
 }
 
-static inline int xsm_machine_memory_map(xsm_default_t def)
+static inline int xsm_machine_memory_map(xsm_role_t role)
 {
-    return xsm_ops->machine_memory_map();
+    CALL_XSM_OP(machine_memory_map);
+    XSM_ALLOWED_ROLES(XSM_PLAT_CTRL);
+    return xsm_validate_role(role, current->domain, NULL);
 }
 
-static inline int xsm_domain_memory_map(xsm_default_t def, struct domain *d)
+static inline int xsm_domain_memory_map(xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->domain_memory_map(d);
+    CALL_XSM_OP(domain_memory_map, d);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_mmu_update (xsm_default_t def, struct domain *d, struct domain *t,
+static inline int xsm_mmu_update (xsm_role_t role, struct domain *d, struct domain *t,
                                   struct domain *f, uint32_t flags)
 {
-    return xsm_ops->mmu_update(d, t, f, flags);
+    int rc = 0;
+    CALL_XSM_OP(mmu_update, d, t, f, flags);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    if ( f != dom_io )
+        rc = xsm_validate_role(role, d, f);
+    if ( evaluate_nospec(t) && !rc )
+        rc = xsm_validate_role(role, d, t);
+    return rc;
 }
 
-static inline int xsm_mmuext_op (xsm_default_t def, struct domain *d, struct domain *f)
+static inline int xsm_mmuext_op (xsm_role_t role, struct domain *d, struct domain *f)
 {
-    return xsm_ops->mmuext_op(d, f);
+    CALL_XSM_OP(mmuext_op, d, f);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, d, f);
 }
 
-static inline int xsm_update_va_mapping(xsm_default_t def, struct domain *d, struct domain *f,
+static inline int xsm_update_va_mapping(xsm_role_t role, struct domain *d, struct domain *f,
                                                             l1_pgentry_t pte)
 {
-    return xsm_ops->update_va_mapping(d, f, pte);
+    CALL_XSM_OP(update_va_mapping, d, f, pte);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, d, f);
 }
 
-static inline int xsm_priv_mapping(xsm_default_t def, struct domain *d, struct domain *t)
+static inline int xsm_priv_mapping(xsm_role_t role, struct domain *d, struct domain *t)
 {
-    return xsm_ops->priv_mapping(d, t);
+    CALL_XSM_OP(priv_mapping, d, t);
+    XSM_ALLOWED_ROLES(TARGET_PRIVS);
+    return xsm_validate_role(role, d, t);
 }
 
-static inline int xsm_ioport_permission (xsm_default_t def, struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
+static inline int xsm_ioport_permission (xsm_role_t role, struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
 {
-    return xsm_ops->ioport_permission(d, s, e, allow);
+    CALL_XSM_OP(ioport_permission, d, s, e, allow);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_ioport_mapping (xsm_default_t def, struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
+static inline int xsm_ioport_mapping (xsm_role_t role, struct domain *d, uint32_t s, uint32_t e, uint8_t allow)
 {
-    return xsm_ops->ioport_mapping(d, s, e, allow);
+    CALL_XSM_OP(ioport_mapping, d, s, e, allow);
+    XSM_ALLOWED_ROLES(XSM_NONE);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_pmu_op (xsm_default_t def, struct domain *d, unsigned int op)
+static inline int xsm_pmu_op (xsm_role_t role, struct domain *d, unsigned int op)
 {
-    return xsm_ops->pmu_op(d, op);
+    CALL_XSM_OP(pmu_op, d, op);
+    XSM_ALLOWED_ROLES(XSM_NONE | XSM_DOM_SUPER);
+    switch ( op )
+    {
+    case XENPMU_init:
+    case XENPMU_finish:
+    case XENPMU_lvtpc_set:
+    case XENPMU_flush:
+        return xsm_validate_role(XSM_NONE, d, current->domain);
+    default:
+        return xsm_validate_role(XSM_DOM_SUPER, d, current->domain);
+    }
 }
 
 #endif /* CONFIG_X86 */
 
-static inline int xsm_dm_op(xsm_default_t def, struct domain *d)
+static inline int xsm_dm_op(xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->dm_op(d);
+    CALL_XSM_OP(dm_op, d);
+    XSM_ALLOWED_ROLES(DEV_EMU_PRIVS);
+    return xsm_validate_role(role, current->domain, d);
 }
 
-static inline int xsm_xen_version (xsm_default_t def, uint32_t op)
+static inline int xsm_xen_version (xsm_role_t role, uint32_t op)
 {
-    return xsm_ops->xen_version(op);
+    CALL_XSM_OP(xen_version, op);
+    XSM_ALLOWED_ROLES(XSM_NONE | XSM_PLAT_CTRL);
+    switch ( op )
+    {
+    case XENVER_version:
+    case XENVER_platform_parameters:
+    case XENVER_get_features:
+        /* These sub-ops ignore the permission checks and return data. */
+        block_speculation();
+        return 0;
+    case XENVER_extraversion:
+    case XENVER_compile_info:
+    case XENVER_capabilities:
+    case XENVER_changeset:
+    case XENVER_pagesize:
+    case XENVER_guest_handle:
+        /* These MUST always be accessible to any guest by default. */
+        return xsm_validate_role(XSM_NONE, current->domain, NULL);
+    default:
+        return xsm_validate_role(XSM_PLAT_CTRL, current->domain, NULL);
+    }
 }
 
-static inline int xsm_domain_resource_map(xsm_default_t def, struct domain *d)
+static inline int xsm_domain_resource_map(xsm_role_t role, struct domain *d)
 {
-    return xsm_ops->domain_resource_map(d);
+    CALL_XSM_OP(domain_resource_map, d);
+    XSM_ALLOWED_ROLES(DEV_EMU_PRIVS);
+    return xsm_validate_role(role, current->domain, d);
 }
 
 #ifdef CONFIG_ARGO
 static inline int xsm_argo_enable(const struct domain *d)
 {
-    return xsm_ops->argo_enable(d);
+    CALL_XSM_OP(argo_enable, d);
+    return 0;
 }
 
 static inline int xsm_argo_register_single_source(const struct domain *d,
                                                   const struct domain *t)
 {
-    return xsm_ops->argo_register_single_source(d, t);
+    CALL_XSM_OP(argo_register_single_source, d, t);
+    return 0;
 }
 
 static inline int xsm_argo_register_any_source(const struct domain *d)
 {
-    return xsm_ops->argo_register_any_source(d);
+    CALL_XSM_OP(argo_register_any_source, d);
+    return 0;
 }
 
 static inline int xsm_argo_send(const struct domain *d, const struct domain *t)
 {
-    return xsm_ops->argo_send(d, t);
+    CALL_XSM_OP(argo_send, d, t);
+    return 0;
 }
 
 #endif /* CONFIG_ARGO */
 
-#endif /* XSM_NO_WRAPPERS */
-
-#ifdef CONFIG_MULTIBOOT
-extern int xsm_multiboot_init(unsigned long *module_map,
-                              const multiboot_info_t *mbi);
-extern int xsm_multiboot_policy_init(unsigned long *module_map,
-                                     const multiboot_info_t *mbi,
-                                     void **policy_buffer,
-                                     size_t *policy_size);
-#endif
-
-#ifdef CONFIG_HAS_DEVICE_TREE
-/*
- * Initialize XSM
- *
- * On success, return 1 if using SILO mode else 0.
- */
-extern int xsm_dt_init(void);
-extern int xsm_dt_policy_init(void **policy_buffer, size_t *policy_size);
-extern bool has_xsm_magic(paddr_t);
-#endif
-
 extern int register_xsm(struct xsm_operations *ops);
 
 extern struct xsm_operations dummy_xsm_ops;
@@ -760,9 +995,29 @@ extern void silo_init(void);
 static inline void silo_init(void) {}
 #endif
 
-#else /* CONFIG_XSM */
+#ifdef CONFIG_XSM_POLICY_MODULES
+
+#ifdef CONFIG_MULTIBOOT
+extern int xsm_multiboot_init(unsigned long *module_map,
+                              const multiboot_info_t *mbi);
+extern int xsm_multiboot_policy_init(unsigned long *module_map,
+                                     const multiboot_info_t *mbi,
+                                     void **policy_buffer,
+                                     size_t *policy_size);
+#endif
+
+#ifdef CONFIG_HAS_DEVICE_TREE
+/*
+ * Initialize XSM
+ *
+ * On success, return 1 if using SILO mode else 0.
+ */
+extern int xsm_dt_init(void);
+extern int xsm_dt_policy_init(void **policy_buffer, size_t *policy_size);
+extern bool has_xsm_magic(paddr_t);
+#endif
 
-#include <xsm/dummy.h>
+#else /* CONFIG_XSM_POLICY_MODULES */
 
 #ifdef CONFIG_MULTIBOOT
 static inline int xsm_multiboot_init (unsigned long *module_map,
@@ -784,6 +1039,6 @@ static inline bool has_xsm_magic(paddr_t start)
 }
 #endif /* CONFIG_HAS_DEVICE_TREE */
 
-#endif /* CONFIG_XSM */
+#endif /* CONFIG_XSM_POLICY_MODULES */
 
 #endif /* __XSM_H */
diff --git a/xen/xsm/xsm_core.c b/xen/xsm/xsm_core.c
index 5eab21e1b1..6bd8ad8751 100644
--- a/xen/xsm/xsm_core.c
+++ b/xen/xsm/xsm_core.c
@@ -18,8 +18,6 @@
 #include <xen/hypercall.h>
 #include <xsm/xsm.h>
 
-#ifdef CONFIG_XSM
-
 #ifdef CONFIG_MULTIBOOT
 #include <asm/setup.h>
 #endif
@@ -32,6 +30,8 @@
 
 struct xsm_operations *xsm_ops;
 
+#ifdef CONFIG_XSM
+
 enum xsm_bootparam {
     XSM_BOOTPARAM_DUMMY,
     XSM_BOOTPARAM_FLASK,
-- 
2.20.1



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

* [RFC PATCH 07/10] xsm-roles: adjusting core xsm
  2021-05-14 20:54 [RFC PATCH 00/10] xsm: introducing domain roles Daniel P. Smith
                   ` (5 preceding siblings ...)
  2021-05-14 20:54 ` [RFC PATCH 06/10] xsm-roles: covert the dummy system to roles Daniel P. Smith
@ 2021-05-14 20:54 ` Daniel P. Smith
  2021-05-14 20:54 ` [RFC PATCH 08/10] xsm-silo: convert silo over to domain roles Daniel P. Smith
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 16+ messages in thread
From: Daniel P. Smith @ 2021-05-14 20:54 UTC (permalink / raw)
  To: xen-devel
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, jbeulich, wl, roger.pau, tamas, tim, jgross,
	aisaila, ppircalabu, dfaggioli, paul, kevin.tian, dgdegra,
	adam.schwalm, scott.davis

This is adjustments and clean ups to the core of xsm for adoption of the domain
roles.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/include/xen/sched.h |   2 +-
 xen/include/xsm/xsm.h   |  26 -------
 xen/xsm/Makefile        |   3 +-
 xen/xsm/dummy.c         | 160 ----------------------------------------
 xen/xsm/xsm_core.c      |  46 +++---------
 5 files changed, 14 insertions(+), 223 deletions(-)
 delete mode 100644 xen/xsm/dummy.c

diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index d84b047359..a00d7fc260 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -120,7 +120,7 @@ struct evtchn
     unsigned short notify_vcpu_id; /* VCPU for local delivery notification */
     uint32_t fifo_lastq;           /* Data for identifying last queue. */
 
-#ifdef CONFIG_XSM
+#ifdef CONFIG_XSM_POLICY
     union {
 #ifdef XSM_NEED_GENERIC_EVTCHN_SSID
         /*
diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h
index 50f2f547dc..8b5e9c737b 100644
--- a/xen/include/xsm/xsm.h
+++ b/xen/include/xsm/xsm.h
@@ -995,8 +995,6 @@ extern void silo_init(void);
 static inline void silo_init(void) {}
 #endif
 
-#ifdef CONFIG_XSM_POLICY_MODULES
-
 #ifdef CONFIG_MULTIBOOT
 extern int xsm_multiboot_init(unsigned long *module_map,
                               const multiboot_info_t *mbi);
@@ -1017,28 +1015,4 @@ extern int xsm_dt_policy_init(void **policy_buffer, size_t *policy_size);
 extern bool has_xsm_magic(paddr_t);
 #endif
 
-#else /* CONFIG_XSM_POLICY_MODULES */
-
-#ifdef CONFIG_MULTIBOOT
-static inline int xsm_multiboot_init (unsigned long *module_map,
-                                      const multiboot_info_t *mbi)
-{
-    return 0;
-}
-#endif
-
-#ifdef CONFIG_HAS_DEVICE_TREE
-static inline int xsm_dt_init(void)
-{
-    return 0;
-}
-
-static inline bool has_xsm_magic(paddr_t start)
-{
-    return false;
-}
-#endif /* CONFIG_HAS_DEVICE_TREE */
-
-#endif /* CONFIG_XSM_POLICY_MODULES */
-
 #endif /* __XSM_H */
diff --git a/xen/xsm/Makefile b/xen/xsm/Makefile
index cf0a728f1c..870bbb8247 100644
--- a/xen/xsm/Makefile
+++ b/xen/xsm/Makefile
@@ -1,6 +1,5 @@
 obj-y += xsm_core.o
-obj-$(CONFIG_XSM) += xsm_policy.o
-obj-$(CONFIG_XSM) += dummy.o
+obj-$(CONFIG_XSM_POLICY) += xsm_policy.o
 obj-$(CONFIG_XSM_SILO) += silo.o
 
 obj-$(CONFIG_XSM_FLASK) += flask/
diff --git a/xen/xsm/dummy.c b/xen/xsm/dummy.c
deleted file mode 100644
index 627f12dbff..0000000000
--- a/xen/xsm/dummy.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- *  This work is based on the LSM implementation in Linux 2.6.13.4.
- *
- *  Author:  George Coker, <gscoker@alpha.ncsc.mil>
- *
- *  Contributors: Michael LeMay, <mdlemay@epoch.ncsc.mil>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2,
- *  as published by the Free Software Foundation.
- */
-
-#define XSM_NO_WRAPPERS
-#include <xsm/dummy.h>
-
-struct xsm_operations dummy_xsm_ops;
-
-#define set_to_dummy_if_null(ops, function)                            \
-    do {                                                               \
-        if ( !ops->function )                                          \
-            ops->function = xsm_##function;                            \
-    } while (0)
-
-void __init xsm_fixup_ops (struct xsm_operations *ops)
-{
-    set_to_dummy_if_null(ops, security_domaininfo);
-    set_to_dummy_if_null(ops, domain_create);
-    set_to_dummy_if_null(ops, getdomaininfo);
-    set_to_dummy_if_null(ops, domctl_scheduler_op);
-    set_to_dummy_if_null(ops, sysctl_scheduler_op);
-    set_to_dummy_if_null(ops, set_target);
-    set_to_dummy_if_null(ops, domctl);
-    set_to_dummy_if_null(ops, sysctl);
-    set_to_dummy_if_null(ops, readconsole);
-
-    set_to_dummy_if_null(ops, evtchn_unbound);
-    set_to_dummy_if_null(ops, evtchn_interdomain);
-    set_to_dummy_if_null(ops, evtchn_close_post);
-    set_to_dummy_if_null(ops, evtchn_send);
-    set_to_dummy_if_null(ops, evtchn_status);
-    set_to_dummy_if_null(ops, evtchn_reset);
-
-    set_to_dummy_if_null(ops, grant_mapref);
-    set_to_dummy_if_null(ops, grant_unmapref);
-    set_to_dummy_if_null(ops, grant_setup);
-    set_to_dummy_if_null(ops, grant_transfer);
-    set_to_dummy_if_null(ops, grant_copy);
-    set_to_dummy_if_null(ops, grant_query_size);
-
-    set_to_dummy_if_null(ops, alloc_security_domain);
-    set_to_dummy_if_null(ops, free_security_domain);
-    set_to_dummy_if_null(ops, alloc_security_evtchns);
-    set_to_dummy_if_null(ops, free_security_evtchns);
-    set_to_dummy_if_null(ops, show_security_evtchn);
-    set_to_dummy_if_null(ops, init_hardware_domain);
-
-    set_to_dummy_if_null(ops, get_pod_target);
-    set_to_dummy_if_null(ops, set_pod_target);
-
-    set_to_dummy_if_null(ops, memory_exchange);
-    set_to_dummy_if_null(ops, memory_adjust_reservation);
-    set_to_dummy_if_null(ops, memory_stat_reservation);
-    set_to_dummy_if_null(ops, memory_pin_page);
-    set_to_dummy_if_null(ops, claim_pages);
-
-    set_to_dummy_if_null(ops, console_io);
-
-    set_to_dummy_if_null(ops, profile);
-
-    set_to_dummy_if_null(ops, kexec);
-    set_to_dummy_if_null(ops, schedop_shutdown);
-
-    set_to_dummy_if_null(ops, show_irq_sid);
-    set_to_dummy_if_null(ops, map_domain_pirq);
-    set_to_dummy_if_null(ops, map_domain_irq);
-    set_to_dummy_if_null(ops, unmap_domain_pirq);
-    set_to_dummy_if_null(ops, unmap_domain_irq);
-    set_to_dummy_if_null(ops, bind_pt_irq);
-    set_to_dummy_if_null(ops, unbind_pt_irq);
-    set_to_dummy_if_null(ops, irq_permission);
-    set_to_dummy_if_null(ops, iomem_permission);
-    set_to_dummy_if_null(ops, iomem_mapping);
-    set_to_dummy_if_null(ops, pci_config_permission);
-    set_to_dummy_if_null(ops, get_vnumainfo);
-
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_PCI)
-    set_to_dummy_if_null(ops, get_device_group);
-    set_to_dummy_if_null(ops, assign_device);
-    set_to_dummy_if_null(ops, deassign_device);
-#endif
-
-#if defined(CONFIG_HAS_PASSTHROUGH) && defined(CONFIG_HAS_DEVICE_TREE)
-    set_to_dummy_if_null(ops, assign_dtdevice);
-    set_to_dummy_if_null(ops, deassign_dtdevice);
-#endif
-
-    set_to_dummy_if_null(ops, resource_plug_core);
-    set_to_dummy_if_null(ops, resource_unplug_core);
-    set_to_dummy_if_null(ops, resource_plug_pci);
-    set_to_dummy_if_null(ops, resource_unplug_pci);
-    set_to_dummy_if_null(ops, resource_setup_pci);
-    set_to_dummy_if_null(ops, resource_setup_gsi);
-    set_to_dummy_if_null(ops, resource_setup_misc);
-
-    set_to_dummy_if_null(ops, page_offline);
-    set_to_dummy_if_null(ops, hypfs_op);
-    set_to_dummy_if_null(ops, hvm_param);
-    set_to_dummy_if_null(ops, hvm_control);
-    set_to_dummy_if_null(ops, hvm_param_altp2mhvm);
-    set_to_dummy_if_null(ops, hvm_altp2mhvm_op);
-
-    set_to_dummy_if_null(ops, do_xsm_op);
-#ifdef CONFIG_COMPAT
-    set_to_dummy_if_null(ops, do_compat_op);
-#endif
-
-    set_to_dummy_if_null(ops, add_to_physmap);
-    set_to_dummy_if_null(ops, remove_from_physmap);
-    set_to_dummy_if_null(ops, map_gmfn_foreign);
-
-    set_to_dummy_if_null(ops, vm_event_control);
-
-#ifdef CONFIG_MEM_ACCESS
-    set_to_dummy_if_null(ops, mem_access);
-#endif
-
-#ifdef CONFIG_HAS_MEM_PAGING
-    set_to_dummy_if_null(ops, mem_paging);
-#endif
-
-#ifdef CONFIG_MEM_SHARING
-    set_to_dummy_if_null(ops, mem_sharing);
-#endif
-
-    set_to_dummy_if_null(ops, platform_op);
-#ifdef CONFIG_X86
-    set_to_dummy_if_null(ops, do_mca);
-    set_to_dummy_if_null(ops, shadow_control);
-    set_to_dummy_if_null(ops, mem_sharing_op);
-    set_to_dummy_if_null(ops, apic);
-    set_to_dummy_if_null(ops, machine_memory_map);
-    set_to_dummy_if_null(ops, domain_memory_map);
-    set_to_dummy_if_null(ops, mmu_update);
-    set_to_dummy_if_null(ops, mmuext_op);
-    set_to_dummy_if_null(ops, update_va_mapping);
-    set_to_dummy_if_null(ops, priv_mapping);
-    set_to_dummy_if_null(ops, ioport_permission);
-    set_to_dummy_if_null(ops, ioport_mapping);
-    set_to_dummy_if_null(ops, pmu_op);
-#endif
-    set_to_dummy_if_null(ops, dm_op);
-    set_to_dummy_if_null(ops, xen_version);
-    set_to_dummy_if_null(ops, domain_resource_map);
-#ifdef CONFIG_ARGO
-    set_to_dummy_if_null(ops, argo_enable);
-    set_to_dummy_if_null(ops, argo_register_single_source);
-    set_to_dummy_if_null(ops, argo_register_any_source);
-    set_to_dummy_if_null(ops, argo_send);
-#endif
-}
diff --git a/xen/xsm/xsm_core.c b/xen/xsm/xsm_core.c
index 6bd8ad8751..89c16511b8 100644
--- a/xen/xsm/xsm_core.c
+++ b/xen/xsm/xsm_core.c
@@ -26,14 +26,12 @@
 #include <asm/setup.h>
 #endif
 
-#define XSM_FRAMEWORK_VERSION    "1.0.0"
+#define XSM_FRAMEWORK_VERSION    "2.0.0"
 
 struct xsm_operations *xsm_ops;
 
-#ifdef CONFIG_XSM
-
 enum xsm_bootparam {
-    XSM_BOOTPARAM_DUMMY,
+    XSM_BOOTPARAM_ROLE,
     XSM_BOOTPARAM_FLASK,
     XSM_BOOTPARAM_SILO,
 };
@@ -44,15 +42,15 @@ static enum xsm_bootparam __initdata xsm_bootparam =
 #elif CONFIG_XSM_SILO_DEFAULT
     XSM_BOOTPARAM_SILO;
 #else
-    XSM_BOOTPARAM_DUMMY;
+    XSM_BOOTPARAM_ROLE;
 #endif
 
 static int __init parse_xsm_param(const char *s)
 {
     int rc = 0;
 
-    if ( !strcmp(s, "dummy") )
-        xsm_bootparam = XSM_BOOTPARAM_DUMMY;
+    if ( !strcmp(s, "role") )
+        xsm_bootparam = XSM_BOOTPARAM_ROLE;
 #ifdef CONFIG_XSM_FLASK
     else if ( !strcmp(s, "flask") )
         xsm_bootparam = XSM_BOOTPARAM_FLASK;
@@ -68,15 +66,6 @@ static int __init parse_xsm_param(const char *s)
 }
 custom_param("xsm", parse_xsm_param);
 
-static inline int verify(struct xsm_operations *ops)
-{
-    /* verify the security_operations structure exists */
-    if ( !ops )
-        return -EINVAL;
-    xsm_fixup_ops(ops);
-    return 0;
-}
-
 static int __init xsm_core_init(const void *policy_buffer, size_t policy_size)
 {
 #ifdef CONFIG_XSM_FLASK_POLICY
@@ -87,17 +76,9 @@ static int __init xsm_core_init(const void *policy_buffer, size_t policy_size)
     }
 #endif
 
-    if ( verify(&dummy_xsm_ops) )
-    {
-        printk(XENLOG_ERR "Could not verify dummy_xsm_ops structure\n");
-        return -EIO;
-    }
-
-    xsm_ops = &dummy_xsm_ops;
-
     switch ( xsm_bootparam )
     {
-    case XSM_BOOTPARAM_DUMMY:
+    case XSM_BOOTPARAM_ROLE:
         break;
 
     case XSM_BOOTPARAM_FLASK:
@@ -116,6 +97,7 @@ static int __init xsm_core_init(const void *policy_buffer, size_t policy_size)
     return 0;
 }
 
+
 #ifdef CONFIG_MULTIBOOT
 int __init xsm_multiboot_init(unsigned long *module_map,
                               const multiboot_info_t *mbi)
@@ -126,6 +108,7 @@ int __init xsm_multiboot_init(unsigned long *module_map,
 
     printk("XSM Framework v" XSM_FRAMEWORK_VERSION " initialized\n");
 
+#ifdef CONFIG_XSM_POLICY
     if ( XSM_MAGIC )
     {
         ret = xsm_multiboot_policy_init(module_map, mbi,
@@ -137,6 +120,7 @@ int __init xsm_multiboot_init(unsigned long *module_map,
             return -EINVAL;
         }
     }
+#endif
 
     ret = xsm_core_init(policy_buffer, policy_size);
     bootstrap_map(NULL);
@@ -154,6 +138,7 @@ int __init xsm_dt_init(void)
 
     printk("XSM Framework v" XSM_FRAMEWORK_VERSION " initialized\n");
 
+#ifdef CONFIG_XSM_POLICY
     if ( XSM_MAGIC )
     {
         ret = xsm_dt_policy_init(&policy_buffer, &policy_size);
@@ -163,6 +148,7 @@ int __init xsm_dt_init(void)
             return -EINVAL;
         }
     }
+#endif
 
     ret = xsm_core_init(policy_buffer, policy_size);
 
@@ -197,13 +183,7 @@ bool __init has_xsm_magic(paddr_t start)
 
 int __init register_xsm(struct xsm_operations *ops)
 {
-    if ( verify(ops) )
-    {
-        printk(XENLOG_ERR "Could not verify xsm_operations structure\n");
-        return -EINVAL;
-    }
-
-    if ( xsm_ops != &dummy_xsm_ops )
+    if ( xsm_ops != NULL )
         return -EAGAIN;
 
     xsm_ops = ops;
@@ -211,8 +191,6 @@ int __init register_xsm(struct xsm_operations *ops)
     return 0;
 }
 
-#endif
-
 long do_xsm_op (XEN_GUEST_HANDLE_PARAM(xsm_op_t) op)
 {
     return xsm_do_xsm_op(op);
-- 
2.20.1



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

* [RFC PATCH 08/10] xsm-silo: convert silo over to domain roles
  2021-05-14 20:54 [RFC PATCH 00/10] xsm: introducing domain roles Daniel P. Smith
                   ` (6 preceding siblings ...)
  2021-05-14 20:54 ` [RFC PATCH 07/10] xsm-roles: adjusting core xsm Daniel P. Smith
@ 2021-05-14 20:54 ` Daniel P. Smith
  2021-07-08 13:17   ` Jan Beulich
  2021-05-14 20:54 ` [RFC PATCH 09/10] xsm-flask: clean up for domain roles conversion Daniel P. Smith
  2021-05-14 20:54 ` [RFC PATCH 10/10] common/Kconfig: updating Kconfig for domain roles Daniel P. Smith
  9 siblings, 1 reply; 16+ messages in thread
From: Daniel P. Smith @ 2021-05-14 20:54 UTC (permalink / raw)
  To: xen-devel
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, jbeulich, wl, roger.pau, tamas, tim, jgross,
	aisaila, ppircalabu, dfaggioli, paul, kevin.tian, dgdegra,
	adam.schwalm, scott.davis

This converts the SILO XSM module to function as an extension to the domain
roles system to implement an extended enforcement policy.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/xsm/silo.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/xen/xsm/silo.c b/xen/xsm/silo.c
index 4850756a3d..3b3ca8fb84 100644
--- a/xen/xsm/silo.c
+++ b/xen/xsm/silo.c
@@ -17,9 +17,11 @@
  * You should have received a copy of the GNU General Public License along with
  * this program; If not, see <http://www.gnu.org/licenses/>.
  */
-#define XSM_NO_WRAPPERS
-#include <xsm/dummy.h>
 
+#include <xsm/xsm.h>
+#include <xsm/roles.h>
+
+#define SILO_ALLOWED_ROLES ( XSM_DOM_SUPER | XSM_DEV_BACK )
 /*
  * Check if inter-domain communication is allowed.
  * Return true when pass check.
@@ -29,8 +31,10 @@ static bool silo_mode_dom_check(const struct domain *ldom,
 {
     const struct domain *currd = current->domain;
 
-    return (is_control_domain(currd) || is_control_domain(ldom) ||
-            is_control_domain(rdom) || ldom == rdom);
+    return ( currd->xsm_roles & SILO_ALLOWED_ROLES ||
+            ldom->xsm_roles & SILO_ALLOWED_ROLES ||
+            rdom->xsm_roles & SILO_ALLOWED_ROLES ||
+            ldom == rdom );
 }
 
 static int silo_evtchn_unbound(struct domain *d1, struct evtchn *chn,
@@ -44,7 +48,7 @@ static int silo_evtchn_unbound(struct domain *d1, struct evtchn *chn,
     else
     {
         if ( silo_mode_dom_check(d1, d2) )
-            rc = xsm_evtchn_unbound(d1, chn, id2);
+            rc = xsm_validate_role(TARGET_PRIVS, current->domain, d1);
         rcu_unlock_domain(d2);
     }
 
@@ -55,7 +59,7 @@ static int silo_evtchn_interdomain(struct domain *d1, struct evtchn *chan1,
                                    struct domain *d2, struct evtchn *chan2)
 {
     if ( silo_mode_dom_check(d1, d2) )
-        return xsm_evtchn_interdomain(d1, chan1, d2, chan2);
+        return xsm_validate_role(XSM_NONE, d1, d2);
     return -EPERM;
 }
 
@@ -63,21 +67,21 @@ static int silo_grant_mapref(struct domain *d1, struct domain *d2,
                              uint32_t flags)
 {
     if ( silo_mode_dom_check(d1, d2) )
-        return xsm_grant_mapref(d1, d2, flags);
+        return xsm_validate_role(XSM_NONE, d1, d2);
     return -EPERM;
 }
 
 static int silo_grant_transfer(struct domain *d1, struct domain *d2)
 {
     if ( silo_mode_dom_check(d1, d2) )
-        return xsm_grant_transfer(d1, d2);
+        return xsm_validate_role(XSM_NONE, d1, d2);
     return -EPERM;
 }
 
 static int silo_grant_copy(struct domain *d1, struct domain *d2)
 {
     if ( silo_mode_dom_check(d1, d2) )
-        return xsm_grant_copy(d1, d2);
+        return xsm_validate_role(XSM_NONE, d1, d2);
     return -EPERM;
 }
 
-- 
2.20.1



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

* [RFC PATCH 09/10] xsm-flask: clean up for domain roles conversion
  2021-05-14 20:54 [RFC PATCH 00/10] xsm: introducing domain roles Daniel P. Smith
                   ` (7 preceding siblings ...)
  2021-05-14 20:54 ` [RFC PATCH 08/10] xsm-silo: convert silo over to domain roles Daniel P. Smith
@ 2021-05-14 20:54 ` Daniel P. Smith
  2021-05-14 20:54 ` [RFC PATCH 10/10] common/Kconfig: updating Kconfig for domain roles Daniel P. Smith
  9 siblings, 0 replies; 16+ messages in thread
From: Daniel P. Smith @ 2021-05-14 20:54 UTC (permalink / raw)
  To: xen-devel
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, jbeulich, wl, roger.pau, tamas, tim, jgross,
	aisaila, ppircalabu, dfaggioli, paul, kevin.tian, dgdegra,
	adam.schwalm, scott.davis

The domain roles approach changed the idea of how the default XSM policy module
is configured. This makes the minor adjustment for that change.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/xsm/flask/flask_op.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xen/xsm/flask/flask_op.c b/xen/xsm/flask/flask_op.c
index 01e52138a1..63c263ebed 100644
--- a/xen/xsm/flask/flask_op.c
+++ b/xen/xsm/flask/flask_op.c
@@ -244,7 +244,7 @@ static int flask_disable(void)
     flask_disabled = 1;
 
     /* Reset xsm_ops to the original module. */
-    xsm_ops = &dummy_xsm_ops;
+    xsm_ops = NULL;
 
     return 0;
 }
-- 
2.20.1



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

* [RFC PATCH 10/10] common/Kconfig: updating Kconfig for domain roles
  2021-05-14 20:54 [RFC PATCH 00/10] xsm: introducing domain roles Daniel P. Smith
                   ` (8 preceding siblings ...)
  2021-05-14 20:54 ` [RFC PATCH 09/10] xsm-flask: clean up for domain roles conversion Daniel P. Smith
@ 2021-05-14 20:54 ` Daniel P. Smith
  9 siblings, 0 replies; 16+ messages in thread
From: Daniel P. Smith @ 2021-05-14 20:54 UTC (permalink / raw)
  To: xen-devel
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, jbeulich, wl, roger.pau, tamas, tim, jgross,
	aisaila, ppircalabu, dfaggioli, paul, kevin.tian, dgdegra,
	adam.schwalm, scott.davis

This adjusts the Kconfig system for the reorganizing of XSM by the introduction
of domain roles.

Signed-off-by: Daniel P. Smith <dpsmith@apertussolutions.com>
---
 xen/common/Kconfig | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 3064bf6b89..560ad274c4 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -199,11 +199,12 @@ config XENOPROF
 
 	  If unsure, say Y.
 
-config XSM
-	bool "Xen Security Modules support"
-	default ARM
+menu "Xen Security Modules"
+
+config XSM_POLICY
+	bool "XSM policy support"
 	---help---
-	  Enables the security framework known as Xen Security Modules which
+	  Enables loadable policy support for Xen Security Modules which
 	  allows administrators fine-grained control over a Xen domain and
 	  its capabilities by defining permissible interactions between domains,
 	  the hypervisor itself, and related resources such as memory and
@@ -214,7 +215,7 @@ config XSM
 config XSM_FLASK
 	def_bool y
 	prompt "FLux Advanced Security Kernel support"
-	depends on XSM
+	depends on XSM_POLICY
 	---help---
 	  Enables FLASK (FLux Advanced Security Kernel) as the access control
 	  mechanism used by the XSM framework.  This provides a mandatory access
@@ -254,7 +255,6 @@ config XSM_FLASK_POLICY
 config XSM_SILO
 	def_bool y
 	prompt "SILO support"
-	depends on XSM
 	---help---
 	  Enables SILO as the access control mechanism used by the XSM framework.
 	  This is not the default module, add boot parameter xsm=silo to choose
@@ -278,6 +278,8 @@ choice
 		bool "SILO" if XSM_SILO
 endchoice
 
+endmenu
+
 config LATE_HWDOM
 	bool "Dedicated hardware domain"
 	default n
-- 
2.20.1



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

* Re: [RFC PATCH 01/10] headers: introduce new default privilege model
  2021-05-14 20:54 ` [RFC PATCH 01/10] headers: introduce new default privilege model Daniel P. Smith
@ 2021-06-18 13:56   ` Jan Beulich
  0 siblings, 0 replies; 16+ messages in thread
From: Jan Beulich @ 2021-06-18 13:56 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, wl, roger.pau, tamas, tim, jgross, aisaila,
	ppircalabu, dfaggioli, paul, kevin.tian, dgdegra, adam.schwalm,
	xen-devel, scott.davis

On 14.05.2021 22:54, Daniel P. Smith wrote:
> --- a/xen/include/xen/sched.h
> +++ b/xen/include/xen/sched.h
> @@ -457,6 +457,24 @@ struct domain
>       */
>      bool             creation_finished;
>  
> +    /* When SILO or Flask are not in use, a domain may have one or more roles
> +     * that are desired for it to fulfill. To accomplish these role a set of
> +     * privilege is required. A break down of the basic privilege is mapped
> +     * to a bit field for assignment and verification.
> +     */
> +#define XSM_NONE      (1U<<0)  /* No role required to make the call */
> +#define XSM_SELF      (1U<<1)  /* Allowed to make the call on self */
> +#define XSM_TARGET    (1U<<2)  /* Allowed to make the call on a domain's target */
> +#define XSM_PLAT_CTRL (1U<<3)  /* Platform Control: domain that control the overall platform */
> +#define XSM_DOM_BUILD (1U<<4)  /* Domain Builder: domain that does domain construction and destruction */
> +#define XSM_DOM_SUPER (1U<<5)  /* Domain Supervisor: domain that control the lifecycle, of all domains */
> +#define XSM_DEV_EMUL  (1U<<6)  /* Device Emulator: domain that provides its target domain's device emulator */
> +#define XSM_DEV_BACK  (1U<<7)  /* Device Backend: domain that provides a device backend */
> +#define XSM_HW_CTRL   (1U<<8)  /* Hardware Control: domain with physical hardware access and its allocation for domain usage */
> +#define XSM_HW_SUPER  (1U<<9)  /* Hardware Supervisor: domain that control allocated physical hardware */
> +#define XSM_XENSTORE  (1U<<31) /* Xenstore: domain that can do privileged operations on xenstore */
> +    uint32_t         xsm_roles;
> +
>      /* Which guest this guest has privileges on */
>      struct domain   *target;

Besides the request to correct various issues with style, I'm struggling
with the differences between some of these, e.g. XSM_HW_CTRL ("allocation
for domain usage") and XSM_HW_SUPER ("control allocated physical hardware").
In the latter case it's not even clear to me what "allocated physical
hardware" is when comparing to just "physical hardware". IOW I think
there's some context (reference to doc) or further commentary missing here.

As a nit, I think in many cases you mean "controls".

I also wonder on what basis you've chosen the place at which you're
inserting the new struct member. I'd expect this to either live next to
related fields, or be put in an available 32-bit padding slot.

Jan



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

* Re: [RFC PATCH 02/10] control domain: refactor is_control_domain
  2021-05-14 20:54 ` [RFC PATCH 02/10] control domain: refactor is_control_domain Daniel P. Smith
@ 2021-06-18 14:02   ` Jan Beulich
  0 siblings, 0 replies; 16+ messages in thread
From: Jan Beulich @ 2021-06-18 14:02 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, wl, roger.pau, tamas, tim, jgross, aisaila,
	ppircalabu, dfaggioli, paul, kevin.tian, dgdegra, adam.schwalm,
	scott.davis, xen-devel

On 14.05.2021 22:54, Daniel P. Smith wrote:
> --- a/xen/common/domain.c
> +++ b/xen/common/domain.c
> @@ -556,6 +556,9 @@ struct domain *domain_create(domid_t domid,
>      /* Sort out our idea of is_control_domain(). */
>      d->is_privileged = is_priv;

With the change to is_control_domain() this is the last use of the
field, so your patch should replace it rather than adding yet
another one. (For layout reasons, "replace" doesn't necessarily
mean "in place").

> +    if (is_priv)

Nit: Please add the missing blanks here.

> --- a/xen/include/xen/sched.h
> +++ b/xen/include/xen/sched.h
> @@ -473,6 +473,8 @@ struct domain
>  #define XSM_HW_CTRL   (1U<<8)  /* Hardware Control: domain with physical hardware access and its allocation for domain usage */
>  #define XSM_HW_SUPER  (1U<<9)  /* Hardware Supervisor: domain that control allocated physical hardware */
>  #define XSM_XENSTORE  (1U<<31) /* Xenstore: domain that can do privileged operations on xenstore */
> +#define CLASSIC_DOM0_PRIVS (XSM_PLAT_CTRL | XSM_DOM_BUILD | XSM_DOM_SUPER | \
> +		XSM_DEV_EMUL | XSM_HW_CTRL | XSM_HW_SUPER | XSM_XENSTORE)

The latest at this point I'm inclined to request that these #define-s
don't all live in the middle of struct domain. When you move them
elsewhere, simply have ...

>      uint32_t         xsm_roles;

... a brief comment next to this point at XSM_* as the values applicable
here.

Jan



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

* Re: [RFC PATCH 04/10] xsm: convert rewrite privilege check function
  2021-05-14 20:54 ` [RFC PATCH 04/10] xsm: convert rewrite privilege check function Daniel P. Smith
@ 2021-06-18 14:14   ` Jan Beulich
  0 siblings, 0 replies; 16+ messages in thread
From: Jan Beulich @ 2021-06-18 14:14 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, wl, roger.pau, tamas, tim, jgross, aisaila,
	ppircalabu, dfaggioli, paul, kevin.tian, dgdegra, adam.schwalm,
	scott.davis, xen-devel

On 14.05.2021 22:54, Daniel P. Smith wrote:

In the title, did you mean just one of "convert" or "rewrite", or
did you omit some punctuation?

> --- a/xen/include/xen/sched.h
> +++ b/xen/include/xen/sched.h
> @@ -475,6 +475,12 @@ struct domain
>  #define XSM_XENSTORE  (1U<<31) /* Xenstore: domain that can do privileged operations on xenstore */
>  #define CLASSIC_DOM0_PRIVS (XSM_PLAT_CTRL | XSM_DOM_BUILD | XSM_DOM_SUPER | \
>  		XSM_DEV_EMUL | XSM_HW_CTRL | XSM_HW_SUPER | XSM_XENSTORE)
> +/* Any access for which XSM_DEV_EMUL is the restriction, XSM_DOM_SUPER is an override */
> +#define DEV_EMU_PRIVS (XSM_DOM_SUPER | XSM_DEV_EMUL)
> +/* Anytime there is an XSM_TARGET check, XSM_SELF also applies, and XSM_DOM_SUPER is an override */
> +#define TARGET_PRIVS (XSM_TARGET | XSM_SELF | XSM_DOM_SUPER)
> +/* Anytime there is an XSM_XENSTORE check, XSM_DOM_SUPER is an override */
> +#define XENSTORE_PRIVS (XSM_XENSTORE | XSM_DOM_SUPER)

I think all of these want to *start* with a common prefix, e.g.
XSM_PRIVS_*. But of course especially these "override" remarks in
the comments again show that for now it is unclear what the
individual bits really mean, and hence whether these combinations
all make sense.

> --- a/xen/include/xsm/dummy.h
> +++ b/xen/include/xsm/dummy.h
> @@ -65,37 +65,48 @@ void __xsm_action_mismatch_detected(void);
>  #define XSM_INLINE always_inline
>  #define XSM_DEFAULT_ARG xsm_default_t action,
>  #define XSM_DEFAULT_VOID xsm_default_t action
> -#define XSM_ASSERT_ACTION(def) LINKER_BUG_ON(def != action)
> +#define XSM_ASSERT_ACTION(def) LINKER_BUG_ON((def) != action)
>  
>  #endif /* CONFIG_XSM */
>  
>  static always_inline int xsm_default_action(
>      xsm_default_t action, struct domain *src, struct domain *target)
>  {
> -    switch ( action ) {
> -    case XSM_HOOK:
> +    /* TODO: these three if's could be squashed into one, decreasing
> +     *       the readability/logical reason-ability but may decrease the
> +     *       number of spectre gadgets
> +     */

Seeing this remark, I'm particularly puzzled by you dropping all
evaluate_nospec().

> +    if ( action & XSM_NONE )
>          return 0;
> -    case XSM_TARGET:
> -        if ( evaluate_nospec(src == target) )
> -        {
> -            return 0;
> -    case XSM_XS_PRIV:
> -            if ( evaluate_nospec(is_xenstore_domain(src)) )
> -                return 0;
> -        }
> -        /* fall through */
> -    case XSM_DM_PRIV:
> -        if ( target && evaluate_nospec(src->target == target) )
> -            return 0;
> -        /* fall through */
> -    case XSM_PRIV:
> -        if ( is_control_domain(src) )
> -            return 0;
> -        return -EPERM;
> -    default:
> -        LINKER_BUG_ON(1);
> -        return -EPERM;
> -    }
> +
> +    if ( (action & XSM_SELF) && ((!target) || (src == target)) )
> +        return 0;
> +
> +    if ( (action & XSM_TARGET) && ((target) && (src->target == target)) )
> +        return 0;

This is an inline function - no need to parenthesize individual
identifiers (also again below). Similarly no need to parenthesize
!target.

> +    /* XSM_DEV_EMUL is the only domain role with a condition, i.e. the
> +     * role only applies to a domain's target.
> +     */
> +    if ( (action & XSM_DEV_EMUL) && (src->xsm_roles & XSM_DEV_EMUL)
> +        && (target) && (src->target == target) )
> +        return 0;
> +
> +    /* Mask out SELF, TARGET, and DEV_EMUL as they have been handled */
> +    action &= ~(XSM_SELF & XSM_TARGET & XSM_DEV_EMUL);
> +
> +    /* Checks if the domain has one of the remaining roles set on it:
> +     *      XSM_PLAT_CTRL
> +     *      XSM_DOM_BUILD
> +     *      XSM_DOM_SUPER
> +     *      XSM_HW_CTRL
> +     *      XSM_HW_SUPER
> +     *      XSM_XENSTORE
> +     */
> +    if (src->xsm_roles & action)

There are style issues here again. I'm not going to mention such any
further. As to the comment, I'm seeing the risk of it ending up stale
the moment yet another role gets added. IOW I'm not convinced you
should enumerate the remaining ones here.

Jan



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

* Re: [RFC PATCH 05/10] hardware domain: convert to domain roles
  2021-05-14 20:54 ` [RFC PATCH 05/10] hardware domain: convert to domain roles Daniel P. Smith
@ 2021-06-18 14:47   ` Jan Beulich
  0 siblings, 0 replies; 16+ messages in thread
From: Jan Beulich @ 2021-06-18 14:47 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, wl, roger.pau, tamas, tim, jgross, aisaila,
	ppircalabu, dfaggioli, paul, kevin.tian, dgdegra, adam.schwalm,
	scott.davis, xen-devel

On 14.05.2021 22:54, Daniel P. Smith wrote:
> --- a/xen/arch/x86/cpu/vpmu.c
> +++ b/xen/arch/x86/cpu/vpmu.c
> @@ -169,13 +169,14 @@ int vpmu_do_msr(unsigned int msr, uint64_t *msr_content,
>  static inline struct vcpu *choose_hwdom_vcpu(void)
>  {
>      unsigned idx;
> +    struct domain *hwdom = get_hardware_domain();

When introducing new pointer variables, please make them pointer-
to-const whenever possible.

> --- a/xen/arch/x86/mm.c
> +++ b/xen/arch/x86/mm.c
> @@ -4917,7 +4917,7 @@ mfn_t alloc_xen_pagetable_new(void)
>      {
>          void *ptr = alloc_xenheap_page();
>  
> -        BUG_ON(!hardware_domain && !ptr);
> +        BUG_ON(!ptr);

This loses an important aspect: We should not crash here anymore once
we've made it far enough to have started constructing Dom0. As you can
see ...

>          return ptr ? virt_to_mfn(ptr) : INVALID_MFN;

... here, the case does actually get handled.

If you make behavioral changes in, especially, an otherwise largely
(seeing its overall size) mechanical change, please make sure you call
them out in the description.

> --- a/xen/arch/x86/setup.c
> +++ b/xen/arch/x86/setup.c
> @@ -776,6 +776,9 @@ static struct domain *__init create_dom0(const module_t *image,
>      if ( IS_ERR(d) || (alloc_dom0_vcpu0(d) == NULL) )
>          panic("Error creating domain 0\n");
>  
> +    /* Ensure the correct roles are assigned */
> +    d->xsm_roles = CLASSIC_DOM0_PRIVS;

Didn't an earlier change put this in place already? This shouldn't be
needed in arch-specific code. The cover letter also doesn't mention
that you're not touching Arm code in this RFC, so a similar change
would then be missing there.

> @@ -302,23 +303,50 @@ struct vcpu *vcpu_create(struct domain *d, unsigned int vcpu_id)
>      return NULL;
>  }
>  
> -static int late_hwdom_init(struct domain *d)
> +/* pivot_hw_ctl:
> + *  This is a one-way pivot from existing to new hardware domain. Upon success
> + *  the domain *next_hwdom will be in control of the hardware and domain
> + *  *curr_hwdom will no longer have access.
> + */
> +static int pivot_hw_ctl(struct domain *next_hwdom)
>  {
>  #ifdef CONFIG_LATE_HWDOM
> -    struct domain *dom0;
> +    bool already_found = false;
> +    struct domain **pd = &domain_list, *curr_hwdom = NULL;
> +    domid_t dom0_id = 0;
>      int rv;
>  
> -    if ( d != hardware_domain || d->domain_id == 0 )
> +#ifdef CONFIG_PV_SHIM
> +    /* On PV shim dom0 != 0 */
> +    dom0_id = get_initial_domain_id();
> +#endif

The suddent need for shim specific logic here also wants explaining
in the description (or, if possible, splitting into a separate
change).

> @@ -559,17 +589,19 @@ struct domain *domain_create(domid_t domid,
>      /* Sort out our idea of is_control_domain(). */
>      d->is_privileged = is_priv;
>  
> -    if (is_priv)
> +    /* reality is that is_priv is only set when construction dom0 */
> +    if (is_priv) {
>          d->xsm_roles = CLASSIC_DOM0_PRIVS;
> +        hardware_domain = d;
> +    }
>  
>      /* Sort out our idea of is_hardware_domain(). */
> -    if ( domid == 0 || domid == hardware_domid )
> +    if ( domid == hardware_domid )

With this change it looks to me as if ...

>      {
>          if ( hardware_domid < 0 || hardware_domid >= DOMID_FIRST_RESERVED )
>              panic("The value of hardware_dom must be a valid domain ID\n");

... this was rendered dead code.

> -        old_hwdom = hardware_domain;
> -        hardware_domain = d;
> +        d->xsm_roles = CLASSIC_HWDOM_PRIVS;

Yet another place where this value gets stored. Ideally there would
be exactly one such place.

> @@ -682,12 +714,14 @@ struct domain *domain_create(domid_t domid,
>          if ( (err = sched_init_domain(d, 0)) != 0 )
>              goto fail;
>  
> -        if ( (err = late_hwdom_init(d)) != 0 )
> +        if ( (err = pivot_hw_ctl(d)) != 0 )
>              goto fail;
>  
>          /*
>           * Must not fail beyond this point, as our caller doesn't know whether
> -         * the domain has been entered into domain_list or not.
> +         * the domain has been entered into domain_list or not. Additionally
> +         * if a hardware control pivot occurred then a failure will leave the
> +         * platform without access to hardware.
>           */

s/will/would/, considering the initial "Must not ..."?

> @@ -711,8 +745,6 @@ struct domain *domain_create(domid_t domid,
>      err = err ?: -EILSEQ; /* Release build safety. */
>  
>      d->is_dying = DOMDYING_dead;
> -    if ( hardware_domain == d )
> -        hardware_domain = old_hwdom;
>      atomic_set(&d->refcnt, DOMAIN_DESTROYED);
>  
>      sched_destroy_domain(d);

Isn't this dealing with earlier failures, and hence needs if not
retaining, then replacing?

> @@ -808,6 +840,42 @@ out:
>  }
>  
>  

I realize you've found a pair of blank lines here, but rather than ...

> +bool is_hardware_domain_started()
> +{
> +    bool exists = false;
> +    struct domain **pd = &domain_list;
> +
> +    if ( *pd != NULL) {
> +        rcu_read_lock(&domlist_read_lock);
> +
> +        for ( ; *pd != NULL; pd = &(*pd)->next_in_list )
> +            if ( (*pd)->xsm_roles & XSM_HW_CTRL )
> +                break;
> +
> +        rcu_read_unlock(&domlist_read_lock);
> +
> +        if ( *pd != NULL )
> +            exists = true;
> +    }
> +
> +    if (exists)
> +        ASSERT(*pd == hardware_domain);
> +
> +    return exists;
> +}
> +
> +

... adding more and ...

> +struct domain *get_hardware_domain()
> +{
> +    if (hardware_domain == NULL)
> +        return NULL;
> +
> +    ASSERT(hardware_domain->xsm_roles & XSM_HW_CTRL);
> +
> +    return hardware_domain;
> +}
> +
> +

... yet more, please insert in the middle of those original two
blank lines. Patch application (especially when larger offsets
are involved, e.g. during backporting activities) benefits from
meaningful context lines rather than many almost identical ones
(and then even relatively close to each other).

As to is_hardware_domain_started() - I'm afraid this is too much
overhead in case there are hundreds or thousands of guests.

> --- a/xen/common/keyhandler.c
> +++ b/xen/common/keyhandler.c
> @@ -228,12 +228,12 @@ static void dump_hwdom_registers(unsigned char key)
>  {
>      struct vcpu *v;
>  
> -    if ( hardware_domain == NULL )
> +    if ( is_hardware_domain_started() )
>          return;

Aren't you inverting the original condition?

> --- a/xen/drivers/passthrough/pci.c
> +++ b/xen/drivers/passthrough/pci.c
> @@ -776,7 +776,7 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn,
>      ret = 0;
>      if ( !pdev->domain )
>      {
> -        pdev->domain = hardware_domain;
> +        pdev->domain = get_hardware_domain();
>          ret = iommu_add_device(pdev);
>          if ( ret )
>          {
> @@ -784,7 +784,7 @@ int pci_add_device(u16 seg, u8 bus, u8 devfn,
>              goto out;
>          }
>  
> -        list_add(&pdev->domain_list, &hardware_domain->pdev_list);
> +        list_add(&pdev->domain_list, &pdev->domain->pdev_list);

It's not immediately obvious that pdev->domain couldn't have changed
by the time we make it here - did you check? I consider this possible
in principle, if e.g. in an error case the device got associated
with the quarantine domain.

> @@ -879,7 +879,7 @@ static int deassign_device(struct domain *d, uint16_t seg, uint8_t bus,
>      if ( ret )
>          goto out;
>  
> -    if ( pdev->domain == hardware_domain  )
> +    if ( is_hardware_domain(pdev->domain) )
>          pdev->quarantine = false;
>  
>      pdev->fault.count = 0;
> @@ -1403,7 +1403,7 @@ static int device_assigned(u16 seg, u8 bus, u8 devfn)
>       * domain or dom_io then it must be assigned to a guest, or be
>       * hidden (owned by dom_xen).
>       */
> -    else if ( pdev->domain != hardware_domain &&
> +    else if ( !is_hardware_domain(pdev->domain) &&
>                pdev->domain != dom_io )
>          rc = -EBUSY;

May I ask that you split out such cleaning up of cases of open-coded
helpers into a separate (prereq) patch, especially when (like here)
the containing patch is already a pretty big one?

> --- a/xen/include/xen/sched.h
> +++ b/xen/include/xen/sched.h
> @@ -475,6 +475,7 @@ struct domain
>  #define XSM_XENSTORE  (1U<<31) /* Xenstore: domain that can do privileged operations on xenstore */
>  #define CLASSIC_DOM0_PRIVS (XSM_PLAT_CTRL | XSM_DOM_BUILD | XSM_DOM_SUPER | \
>  		XSM_DEV_EMUL | XSM_HW_CTRL | XSM_HW_SUPER | XSM_XENSTORE)
> +#define CLASSIC_HWDOM_PRIVS (XSM_HW_CTRL | XSM_DEV_EMUL)

Oh, maybe I was wrong with saying that the same value gets put in
place in multiple locations. The fact that you start distinguishing
Dom0 and hwdom needs calling out in the description. I'm not
convinced of the inclusion of XSM_DEV_EMUL.

I also think CLASSIC_DOM0_PRIVS then should use CLASSIC_HWDOM_PRIVS
instead of re-enumerating what the latter contains, unless there's
a definitive plan for the latter to include bits the former
shouldn't include.

Jan



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

* Re: [RFC PATCH 08/10] xsm-silo: convert silo over to domain roles
  2021-05-14 20:54 ` [RFC PATCH 08/10] xsm-silo: convert silo over to domain roles Daniel P. Smith
@ 2021-07-08 13:17   ` Jan Beulich
  0 siblings, 0 replies; 16+ messages in thread
From: Jan Beulich @ 2021-07-08 13:17 UTC (permalink / raw)
  To: Daniel P. Smith
  Cc: sstabellini, julien, Volodymyr_Babchuk, andrew.cooper3,
	george.dunlap, iwj, wl, roger.pau, tamas, tim, jgross, aisaila,
	ppircalabu, dfaggioli, paul, kevin.tian, dgdegra, adam.schwalm,
	scott.davis, xen-devel

On 14.05.2021 22:54, Daniel P. Smith wrote:
> --- a/xen/xsm/silo.c
> +++ b/xen/xsm/silo.c
> @@ -17,9 +17,11 @@
>   * You should have received a copy of the GNU General Public License along with
>   * this program; If not, see <http://www.gnu.org/licenses/>.
>   */
> -#define XSM_NO_WRAPPERS
> -#include <xsm/dummy.h>
>  
> +#include <xsm/xsm.h>
> +#include <xsm/roles.h>
> +
> +#define SILO_ALLOWED_ROLES ( XSM_DOM_SUPER | XSM_DEV_BACK )

Assuming XSM_DEV_BACK means (or at least may also mean) a backend outside
of Dom0 serving another domain's frontend, ...

> @@ -29,8 +31,10 @@ static bool silo_mode_dom_check(const struct domain *ldom,
>  {
>      const struct domain *currd = current->domain;
>  
> -    return (is_control_domain(currd) || is_control_domain(ldom) ||
> -            is_control_domain(rdom) || ldom == rdom);
> +    return ( currd->xsm_roles & SILO_ALLOWED_ROLES ||
> +            ldom->xsm_roles & SILO_ALLOWED_ROLES ||
> +            rdom->xsm_roles & SILO_ALLOWED_ROLES ||
> +            ldom == rdom );

... I don't think this is an appropriate conversion. Aiui a backend in
a driver domain is out of reach for a domain in SILO mode.

Jan



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

end of thread, other threads:[~2021-07-08 13:18 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-14 20:54 [RFC PATCH 00/10] xsm: introducing domain roles Daniel P. Smith
2021-05-14 20:54 ` [RFC PATCH 01/10] headers: introduce new default privilege model Daniel P. Smith
2021-06-18 13:56   ` Jan Beulich
2021-05-14 20:54 ` [RFC PATCH 02/10] control domain: refactor is_control_domain Daniel P. Smith
2021-06-18 14:02   ` Jan Beulich
2021-05-14 20:54 ` [RFC PATCH 03/10] xenstore: migrate to default privilege model Daniel P. Smith
2021-05-14 20:54 ` [RFC PATCH 04/10] xsm: convert rewrite privilege check function Daniel P. Smith
2021-06-18 14:14   ` Jan Beulich
2021-05-14 20:54 ` [RFC PATCH 05/10] hardware domain: convert to domain roles Daniel P. Smith
2021-06-18 14:47   ` Jan Beulich
2021-05-14 20:54 ` [RFC PATCH 06/10] xsm-roles: covert the dummy system to roles Daniel P. Smith
2021-05-14 20:54 ` [RFC PATCH 07/10] xsm-roles: adjusting core xsm Daniel P. Smith
2021-05-14 20:54 ` [RFC PATCH 08/10] xsm-silo: convert silo over to domain roles Daniel P. Smith
2021-07-08 13:17   ` Jan Beulich
2021-05-14 20:54 ` [RFC PATCH 09/10] xsm-flask: clean up for domain roles conversion Daniel P. Smith
2021-05-14 20:54 ` [RFC PATCH 10/10] common/Kconfig: updating Kconfig for domain roles Daniel P. Smith

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).