All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v2 0/6] zynqmp: Add forwarding of platform specific firmware calls
@ 2017-02-07 19:41 Edgar E. Iglesias
  2017-02-07 19:42 ` [RFC v2 1/6] xen/arm: traps: Reorder early overwrite of FID Edgar E. Iglesias
                   ` (5 more replies)
  0 siblings, 6 replies; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-02-07 19:41 UTC (permalink / raw)
  To: xen-devel; +Cc: edgar.iglesias, julien.grall, sstabellini

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

The ZynqMP software stack has an extensive Firmware API based on EEMI:
https://www.xilinx.com/support/documentation/user_guides/ug1200-eemi-api.pdf
https://www.xilinx.com/support/documentation/user_guides/ug1199-zynq-power-management.pdf

Software at EL1 is increasingly dependant on this API. In fact,
a large set of use-cases for Linux already require access to firmware.

Services provided by the API, among other things include:
* Clock Management
* PHY Configuration
* Power Management
* FPGA configuration
* etc

Adding support for accessing firmware can be done in two steps.

1. Allow the hw domain (dom0) to call into firmware. This enables
   all devices to work with PV setups.

2. Allow other guests to use the Firmware API. This will be needed
   to fully support device pass-through.
   We cannot give un-supervised access to unprivileged guests, so
   the idea is to mediate these calls in Xen or in dom0.
   Mediation mainly consists of verfifying access to calls,
   modifying calls and sometimes blocking them.

This patch series implements step #2.

There are quite a few options on how to implement step #2, e.g:
1. Trap HVC/SMC calls from unpriv guests and handle them in dom0.
   This could be done in a user-space agent.
2. Add a PV protocol carrying these calls.
3. Add several generic PV protocols carrying a set of platform independent
   generic calls that get translated or mapped to firmware calls
   in dom0. E.g PV-Clock, PV-Power, PV-FPGA.
4. Same as #1 but doing it all in Xen.
5. Others??

A benefit with #1 and #4 is that we could support unmodified bare-metal
guests. Such guests would continue to issue SMC calls from EL1 just as
if they were running without a hypervisor.

This patch series implements step #2 according to option #4.

EEMI has 3 kinds of resources it operates on.
1. Nodes (can be anything, a device, a CPU, a bus, a PLL)
2. Reset lines
3. MMIO accesses (i.e direct register access)

This implementation relies on the assumption that these
can be associated to a real device with some kind of
register area controlling it. If a guest has access to these
registers (e.g by being granted access via iomem), the
guest is allowed to control the node.

So, we map Nodes and rest-lines to memory addresses and check if
the guest issuing the call has access the device's control regs.

For direct MMIO calls, we map addresses and bitfields within registers
into nodes that get checked for guest ownership.

Guests are only allowed to power up/down and reset devices that are
in their control.

Certain calls, nodes and registers cannot be mapped (yet) to guests.
These fall mostly under dom0's control. A few calls are never allowed
(e.g turning off the current CPU or powering off DDR).

Any feedback would be much appreciated.

Thanks and Best regards!
Edgar

ChangeLog:

v1 -> v2:
* Advance PC after successfully processing an SMC
* Add implementation of a ZynqMP EEMI Mediator

Edgar E. Iglesias (6):
  xen/arm: traps: Reorder early overwrite of FID
  xen/arm: Introduce platform_hvc
  xen/arm: Allow platform_hvc to handle guest SMC calls
  xen/arm: Introduce call_smcc64
  xen/arm: zynqmp: Forward plaform specific firmware calls
  xen/arm: zynqmp: Remove blacklist of ZynqMP's PM node

 xen/arch/arm/platform.c                            |   8 +
 xen/arch/arm/platforms/Makefile                    |   1 +
 xen/arch/arm/platforms/xilinx-zynqmp-eemi.c        | 794 +++++++++++++++++++++
 xen/arch/arm/platforms/xilinx-zynqmp.c             |  22 +-
 xen/arch/arm/traps.c                               |  15 +-
 xen/include/asm-arm/platform.h                     |   5 +
 xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h | 337 +++++++++
 xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h   | 284 ++++++++
 xen/include/asm-arm/processor.h                    |  40 ++
 9 files changed, 1498 insertions(+), 8 deletions(-)
 create mode 100644 xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
 create mode 100644 xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h
 create mode 100644 xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h

-- 
2.7.4


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

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

* [RFC v2 1/6] xen/arm: traps: Reorder early overwrite of FID
  2017-02-07 19:41 [RFC v2 0/6] zynqmp: Add forwarding of platform specific firmware calls Edgar E. Iglesias
@ 2017-02-07 19:42 ` Edgar E. Iglesias
  2017-02-13 22:06   ` Stefano Stabellini
  2017-02-07 19:42 ` [RFC v2 2/6] xen/arm: Introduce platform_hvc Edgar E. Iglesias
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-02-07 19:42 UTC (permalink / raw)
  To: xen-devel; +Cc: edgar.iglesias, julien.grall, sstabellini

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Move the early setting of PSCI_RESULT_REG to a later stage
avoiding the early override of the FID that's stored in
the same register.

No functional change.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 xen/arch/arm/traps.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 92b1d80..c5a4d41 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -1335,8 +1335,6 @@ static void do_trap_psci(struct cpu_user_regs *regs)
 {
     register_t fid = PSCI_ARG(regs,0);
 
-    /* preloading in case psci_mode_check fails */
-    PSCI_RESULT_REG(regs) = PSCI_INVALID_PARAMETERS;
     switch( fid )
     {
     case PSCI_cpu_off:
@@ -1369,6 +1367,7 @@ static void do_trap_psci(struct cpu_user_regs *regs)
     case PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
     case PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
         perfc_incr(vpsci_migrate_info_up_cpu);
+        PSCI_RESULT_REG(regs) = PSCI_INVALID_PARAMETERS;
         if ( psci_mode_check(current->domain, fid) )
             PSCI_RESULT_REG(regs) = do_psci_0_2_migrate_info_up_cpu();
         break;
@@ -1385,6 +1384,7 @@ static void do_trap_psci(struct cpu_user_regs *regs)
     case PSCI_0_2_FN_CPU_ON:
     case PSCI_0_2_FN64_CPU_ON:
         perfc_incr(vpsci_cpu_on);
+        PSCI_RESULT_REG(regs) = PSCI_INVALID_PARAMETERS;
         if ( psci_mode_check(current->domain, fid) )
         {
             register_t vcpuid = PSCI_ARG(regs,1);
@@ -1397,6 +1397,7 @@ static void do_trap_psci(struct cpu_user_regs *regs)
     case PSCI_0_2_FN_CPU_SUSPEND:
     case PSCI_0_2_FN64_CPU_SUSPEND:
         perfc_incr(vpsci_cpu_suspend);
+        PSCI_RESULT_REG(regs) = PSCI_INVALID_PARAMETERS;
         if ( psci_mode_check(current->domain, fid) )
         {
             uint32_t pstate = PSCI_ARG32(regs,1);
@@ -1409,6 +1410,7 @@ static void do_trap_psci(struct cpu_user_regs *regs)
     case PSCI_0_2_FN_AFFINITY_INFO:
     case PSCI_0_2_FN64_AFFINITY_INFO:
         perfc_incr(vpsci_cpu_affinity_info);
+        PSCI_RESULT_REG(regs) = PSCI_INVALID_PARAMETERS;
         if ( psci_mode_check(current->domain, fid) )
         {
             register_t taff = PSCI_ARG(regs,1);
@@ -1420,6 +1422,7 @@ static void do_trap_psci(struct cpu_user_regs *regs)
     case PSCI_0_2_FN_MIGRATE:
     case PSCI_0_2_FN64_MIGRATE:
         perfc_incr(vpsci_cpu_migrate);
+        PSCI_RESULT_REG(regs) = PSCI_INVALID_PARAMETERS;
         if ( psci_mode_check(current->domain, fid) )
         {
             uint32_t tcpu = PSCI_ARG32(regs,1);
-- 
2.7.4


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

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

* [RFC v2 2/6] xen/arm: Introduce platform_hvc
  2017-02-07 19:41 [RFC v2 0/6] zynqmp: Add forwarding of platform specific firmware calls Edgar E. Iglesias
  2017-02-07 19:42 ` [RFC v2 1/6] xen/arm: traps: Reorder early overwrite of FID Edgar E. Iglesias
@ 2017-02-07 19:42 ` Edgar E. Iglesias
  2017-02-13 22:08   ` Stefano Stabellini
  2017-02-07 19:42 ` [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls Edgar E. Iglesias
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-02-07 19:42 UTC (permalink / raw)
  To: xen-devel; +Cc: edgar.iglesias, julien.grall, sstabellini

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Introduce platform_hvc as a way to handle hypercalls that
Xen does not know about in a platform specific way. This
is particularly useful for implementing the SiP (SoC
implementation specific) service calls.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 xen/arch/arm/platform.c        | 8 ++++++++
 xen/arch/arm/traps.c           | 3 +++
 xen/include/asm-arm/platform.h | 5 +++++
 3 files changed, 16 insertions(+)

diff --git a/xen/arch/arm/platform.c b/xen/arch/arm/platform.c
index 0af6d57..90ea6b8 100644
--- a/xen/arch/arm/platform.c
+++ b/xen/arch/arm/platform.c
@@ -127,6 +127,14 @@ void platform_poweroff(void)
         platform->poweroff();
 }
 
+bool platform_hvc(struct cpu_user_regs *regs)
+{
+    if ( platform && platform->hvc )
+        return platform->hvc(regs);
+
+    return false;
+}
+
 bool_t platform_has_quirk(uint32_t quirk)
 {
     uint32_t quirks = 0;
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index c5a4d41..33950d9 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -44,6 +44,7 @@
 #include <asm/cpufeature.h>
 #include <asm/flushtlb.h>
 #include <asm/monitor.h>
+#include <asm/platform.h>
 
 #include "decode.h"
 #include "vtimer.h"
@@ -1430,6 +1431,8 @@ static void do_trap_psci(struct cpu_user_regs *regs)
         }
         break;
     default:
+        if ( platform_hvc(regs) )
+                return;
         domain_crash_synchronous();
         return;
     }
diff --git a/xen/include/asm-arm/platform.h b/xen/include/asm-arm/platform.h
index 08010ba..4d51f0a 100644
--- a/xen/include/asm-arm/platform.h
+++ b/xen/include/asm-arm/platform.h
@@ -26,6 +26,10 @@ struct platform_desc {
     void (*reset)(void);
     /* Platform power-off */
     void (*poweroff)(void);
+    /* Platform specific HVC handler.
+     * Returns true if the call was handled and false if not.
+     */
+    bool (*hvc)(struct cpu_user_regs *regs);
     /*
      * Platform quirks
      * Defined has a function because a platform can support multiple
@@ -55,6 +59,7 @@ int platform_cpu_up(int cpu);
 #endif
 void platform_reset(void);
 void platform_poweroff(void);
+bool platform_hvc(struct cpu_user_regs *regs);
 bool_t platform_has_quirk(uint32_t quirk);
 bool_t platform_device_is_blacklisted(const struct dt_device_node *node);
 
-- 
2.7.4


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

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

* [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-07 19:41 [RFC v2 0/6] zynqmp: Add forwarding of platform specific firmware calls Edgar E. Iglesias
  2017-02-07 19:42 ` [RFC v2 1/6] xen/arm: traps: Reorder early overwrite of FID Edgar E. Iglesias
  2017-02-07 19:42 ` [RFC v2 2/6] xen/arm: Introduce platform_hvc Edgar E. Iglesias
@ 2017-02-07 19:42 ` Edgar E. Iglesias
  2017-02-07 20:38   ` Tamas K Lengyel
  2017-02-07 19:42 ` [RFC v2 4/6] xen/arm: Introduce call_smcc64 Edgar E. Iglesias
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-02-07 19:42 UTC (permalink / raw)
  To: xen-devel; +Cc: edgar.iglesias, julien.grall, sstabellini

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Allow platform_hvc to handle guest SMC calls (as well as
HVC calls) in a platform specific way.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 xen/arch/arm/traps.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 33950d9..1bedc6e 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -2623,6 +2623,11 @@ static void do_trap_smc(struct cpu_user_regs *regs, const union hsr hsr)
     if ( current->domain->arch.monitor.privileged_call_enabled )
         rc = monitor_smc();
 
+    if ( platform_hvc(regs) ) {
+        advance_pc(regs, hsr);
+        rc = 1;
+    }
+
     if ( rc != 1 )
         inject_undef_exception(regs, hsr);
 }
-- 
2.7.4


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

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

* [RFC v2 4/6] xen/arm: Introduce call_smcc64
  2017-02-07 19:41 [RFC v2 0/6] zynqmp: Add forwarding of platform specific firmware calls Edgar E. Iglesias
                   ` (2 preceding siblings ...)
  2017-02-07 19:42 ` [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls Edgar E. Iglesias
@ 2017-02-07 19:42 ` Edgar E. Iglesias
  2017-02-13 22:11   ` Stefano Stabellini
  2017-02-07 19:42 ` [RFC v2 5/6] xen/arm: zynqmp: Forward plaform specific firmware calls Edgar E. Iglesias
  2017-02-07 19:42 ` [RFC v2 6/6] xen/arm: zynqmp: Remove blacklist of ZynqMP's PM node Edgar E. Iglesias
  5 siblings, 1 reply; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-02-07 19:42 UTC (permalink / raw)
  To: xen-devel; +Cc: edgar.iglesias, julien.grall, sstabellini

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Introduce call_smcc64, a helper function to issue 64-bit SMC
calls that follow the SMC Calling Convention. This includes
returning up to 4 64-bit values.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 xen/include/asm-arm/processor.h | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h
index afc0e9a..a604f8c 100644
--- a/xen/include/asm-arm/processor.h
+++ b/xen/include/asm-arm/processor.h
@@ -706,6 +706,46 @@ void vcpu_regs_user_to_hyp(struct vcpu *vcpu,
 int call_smc(register_t function_id, register_t arg0, register_t arg1,
              register_t arg2);
 
+/*
+ * Helper to issue a 64-bit SMC according to the SMC Calling Convention.
+ *
+ * @fid:      Function Identifier
+ * @a0 - a5:  6 arguments
+ * @ret:      Pointer to 4 register_t carrying return values
+ */
+static inline register_t call_smcc64(register_t fid,
+                                     register_t a0,
+                                     register_t a1,
+                                     register_t a2,
+                                     register_t a3,
+                                     register_t a4,
+                                     register_t a5,
+                                     register_t *ret)
+{
+    register register_t x0 asm("x0") = fid;
+    register register_t x1 asm("x1") = a0;
+    register register_t x2 asm("x2") = a1;
+    register register_t x3 asm("x3") = a2;
+    register register_t x4 asm("x4") = a3;
+    register register_t x5 asm("x5") = a4;
+    register register_t x6 asm("x6") = a5;
+
+    asm volatile ("smc #0\n"
+                  : "+r" (x0), "+r" (x1), "+r" (x2), "+r" (x3),
+                    "+r" (x4), "+r" (x5), "+r" (x6)
+                  :
+                  : "x7", "x8", "x9", "x10", "x11", "x12",
+                    "x13", "x14", "x15", "x16", "x17" );
+
+    if (ret) {
+        ret[0] = x0;
+        ret[1] = x1;
+        ret[2] = x2;
+        ret[3] = x3;
+    }
+    return x0;
+}
+
 void do_trap_guest_error(struct cpu_user_regs *regs);
 
 #endif /* __ASSEMBLY__ */
-- 
2.7.4


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

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

* [RFC v2 5/6] xen/arm: zynqmp: Forward plaform specific firmware calls
  2017-02-07 19:41 [RFC v2 0/6] zynqmp: Add forwarding of platform specific firmware calls Edgar E. Iglesias
                   ` (3 preceding siblings ...)
  2017-02-07 19:42 ` [RFC v2 4/6] xen/arm: Introduce call_smcc64 Edgar E. Iglesias
@ 2017-02-07 19:42 ` Edgar E. Iglesias
  2017-02-14  0:02   ` Stefano Stabellini
  2017-02-17 18:47   ` Julien Grall
  2017-02-07 19:42 ` [RFC v2 6/6] xen/arm: zynqmp: Remove blacklist of ZynqMP's PM node Edgar E. Iglesias
  5 siblings, 2 replies; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-02-07 19:42 UTC (permalink / raw)
  To: xen-devel; +Cc: edgar.iglesias, julien.grall, sstabellini

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Implement an EEMI mediator and forward platform specific
firmware calls from guests to firmware.

The EEMI mediator is responsible for implementing access
controls modifying or blocking calls that try to operate
on setup for devices that are not under the calling guest's
control.

EEMI:
https://www.xilinx.com/support/documentation/user_guides/ug1200-eemi-api.pdf

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 xen/arch/arm/platforms/Makefile                    |   1 +
 xen/arch/arm/platforms/xilinx-zynqmp-eemi.c        | 794 +++++++++++++++++++++
 xen/arch/arm/platforms/xilinx-zynqmp.c             |  18 +
 xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h | 337 +++++++++
 xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h   | 284 ++++++++
 5 files changed, 1434 insertions(+)
 create mode 100644 xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
 create mode 100644 xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h
 create mode 100644 xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h

diff --git a/xen/arch/arm/platforms/Makefile b/xen/arch/arm/platforms/Makefile
index 49fa683..b58b71f 100644
--- a/xen/arch/arm/platforms/Makefile
+++ b/xen/arch/arm/platforms/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_ARM_64) += seattle.o
 obj-$(CONFIG_ARM_32) += sunxi.o
 obj-$(CONFIG_ARM_64) += xgene-storm.o
 obj-$(CONFIG_ARM_64) += xilinx-zynqmp.o
+obj-$(CONFIG_ARM_64) += xilinx-zynqmp-eemi.o
diff --git a/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c b/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
new file mode 100644
index 0000000..c2c184d
--- /dev/null
+++ b/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
@@ -0,0 +1,794 @@
+/*
+ * xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
+ *
+ * Xilinx ZynqMP EEMI API mediator.
+ *
+ * Copyright (c) 2017 Xilinx Inc.
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * Mediator for the EEMI Power Mangement API.
+ *
+ * Refs:
+ * https://www.xilinx.com/support/documentation/user_guides/ug1200-eemi-api.pdf
+ *
+ * Background:
+ * The ZynqMP has a subsystem named the PMU with a CPU and special devices
+ * dedicated to running Power Management Firmware. Other masters in the
+ * system need to send requests to the PMU in order to for example:
+ * * Manage power state
+ * * Configure clocks
+ * * Program bitstreams for the programmable logic
+ * * etc
+ *
+ * Allthough the details of the setup are configurable, in the common case
+ * the PMU lives in the Secure world. NS World cannot directly communicate
+ * with it and must use proxy services from ARM Trusted Firmware to reach
+ * the PMU.
+ *
+ * Power Management on the ZynqMP is implemented in a layered manner.
+ * The PMU knows about various masters and will enforce access controls
+ * based on a pre-configured partitioning. This configuration dictates
+ * which devices are owned by the various masters and the PMU FW makes sure
+ * that a given master cannot turn off a device that it does not own or that
+ * is in use by other masters.
+ *
+ * The PMU is not aware of multiple execution states in masters.
+ * For example, it treats the ARMv8 cores as single units and does not
+ * distinguish between Secure vs NS OS:s nor does it know about Hypervisors
+ * and multiple guests. It is up to software on the ARMv8 cores to present
+ * a unified view of its power requirements.
+ *
+ * To implement this unified view, ARM Trusted Firmware at EL3 provides
+ * access to the PM API via SMC calls. ARM Trusted Firmware is responsible
+ * for mediating between the Secure and the NS world, rejecting SMC calls
+ * that request changes that are not allowed.
+ *
+ * Xen running above ATF owns the NS world and is responsible for presenting
+ * unified PM requests taking all guests and the hypervisor into account.
+ *
+ * Implementation:
+ * The PM API contains different classes of calls.
+ * Certain calls are harmless to expose to any guest.
+ * These include calls to get the PM API Version, or to read out the version
+ * of the chip we're running on.
+ *
+ * Other calls are more problematic. Here're some:
+ * * Power requests for nodes (i.e turn on or off a given device)
+ * * Reset line control (i.e reset a given device)
+ * * MMIO access (i.e directly access clock and reset registers)
+ *
+ * Power requests for nodes:
+ * In order to correctly mediate these calls, we need to know if
+ * guests issuing these calls have ownership of the given device.
+ * The approach taken here is to map PM API Nodes identifying
+ * a device into base addresses for registers that belong to that
+ * same device.
+ *
+ * If the guest has access to a devices registers, we give the guest
+ * access to PM API calls that affect that device. This is implemented
+ * by pm_node_access and domain_has_node_access().
+ *
+ * Reset lines:
+ * Reset lines are identified by a list of identifiers that do not relate
+ * to device nodes. We can use the same approach here as for nodes, except
+ * that we need a separate table mapping reset lines to base addresses.
+ * This is implemented by pm_reset_access.
+ *
+ * MMIO access:
+ * These calls allow guests to access certain memory ranges. These ranges
+ * are typically protected for secure-world access only and also from
+ * certain masters only, so guests cannot access them directly.
+ * Registers within the memory regions affect certain nodes. In this case,
+ * our imput is an address and we map that address into a node. If the
+ * guest has ownership of that node, the access is allowed.
+ * Some registers contain bitfields and a single register may contain
+ * bits that affect multiple nodes.
+ *
+ * Some of the calls act on more global state. For example acting on
+ * NODE_PS, which affects many a lot of nodes. This higher level
+ * orchestrating is left for the hardware-domain only.
+ */
+
+#include <xen/iocap.h>
+#include <asm/platform.h>
+#include <asm/platforms/xilinx-zynqmp-eemi.h>
+#include <asm/platforms/xilinx-zynqmp-mm.h>
+
+struct pm_access
+{
+    uint64_t addr;
+    bool hwdom_access;    /* HW domain gets access regardless.  */
+};
+
+/*
+ * This table maps a node into a memory address.
+ * If a guest has access to the address, it has enough control
+ * over the node to grant it access to EEMI calls for that node.
+ */
+static const struct pm_access pm_node_access[] = {
+    /* MM_RPU grants access to alll RPU Nodes.  */
+    [NODE_RPU] = { MM_RPU },
+    [NODE_RPU_0] = { MM_RPU },
+    [NODE_RPU_1] = { MM_RPU },
+    [NODE_IPI_RPU_0] = { MM_RPU },
+
+    /* GPU nodes.  */
+    [NODE_GPU] = { MM_GPU },
+    [NODE_GPU_PP_0] = { MM_GPU },
+    [NODE_GPU_PP_1] = { MM_GPU },
+
+    [NODE_USB_0] = { MM_USB3_0 },
+    [NODE_USB_1] = { MM_USB3_1 },
+    [NODE_TTC_0] = { MM_TTC0 },
+    [NODE_TTC_1] = { MM_TTC1 },
+    [NODE_TTC_2] = { MM_TTC2 },
+    [NODE_TTC_3] = { MM_TTC3 },
+    [NODE_SATA] = { MM_SATA_AHCI_HBA },
+    [NODE_ETH_0] = { MM_GEM0 },
+    [NODE_ETH_1] = { MM_GEM1 },
+    [NODE_ETH_2] = { MM_GEM2 },
+    [NODE_ETH_3] = { MM_GEM3 },
+    [NODE_UART_0] = { MM_UART0 },
+    [NODE_UART_1] = { MM_UART1 },
+    [NODE_SPI_0] = { MM_SPI0 },
+    [NODE_SPI_1] = { MM_SPI1 },
+    [NODE_I2C_0] = { MM_I2C0 },
+    [NODE_I2C_1] = { MM_I2C1 },
+    [NODE_SD_0] = { MM_SD0 },
+    [NODE_SD_1] = { MM_SD1 },
+    [NODE_DP] = { MM_DP },
+
+    /* Guest with GDMA Channel 0 gets PM access. Other guests don't.  */
+    [NODE_GDMA] = { MM_GDMA_CH0 },
+    /* Guest with ADMA Channel 0 gets PM access. Other guests don't.  */
+    [NODE_ADMA] = { MM_ADMA_CH0 },
+
+    [NODE_NAND] = { MM_NAND },
+    [NODE_QSPI] = { MM_QSPI },
+    [NODE_GPIO] = { MM_GPIO },
+    [NODE_CAN_0] = { MM_CAN0 },
+    [NODE_CAN_1] = { MM_CAN1 },
+
+    /* Dom0 only.  */
+    [NODE_AFI] = { .hwdom_access = true },
+    [NODE_APLL] = { .hwdom_access = true },
+    [NODE_VPLL] = { .hwdom_access = true },
+    [NODE_DPLL] = { .hwdom_access = true },
+    [NODE_RPLL] = { .hwdom_access = true },
+    [NODE_IOPLL] = { .hwdom_access = true },
+    [NODE_DDR] = { .hwdom_access = true },
+    [NODE_IPI_APU] = { .hwdom_access = true },
+    [NODE_PCAP] = { .hwdom_access = true },
+
+    [NODE_PCIE] = { MM_PCIE_ATTRIB },
+    [NODE_RTC] = { MM_RTC },
+};
+
+/*
+ * This table maps reset line IDs into a memory address.
+ * If a guest has access to the address, it has enough control
+ * over the affected node to grant it access to EEMI calls for
+ * resetting that node.
+ */
+#define PM_RESET_IDX(n) (n - PM_RESET_PCIE_CFG)
+static const struct pm_access pm_reset_access[] = {
+    [PM_RESET_IDX(PM_RESET_PCIE_CFG)] = { MM_AXIPCIE_MAIN },
+    [PM_RESET_IDX(PM_RESET_PCIE_BRIDGE)] = { MM_PCIE_ATTRIB },
+    [PM_RESET_IDX(PM_RESET_PCIE_CTRL)] = { MM_PCIE_ATTRIB },
+
+    [PM_RESET_IDX(PM_RESET_DP)] = { MM_DP },
+    [PM_RESET_IDX(PM_RESET_SWDT_CRF)] = { MM_SWDT },
+    [PM_RESET_IDX(PM_RESET_AFI_FM5)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_AFI_FM4)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_AFI_FM3)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_AFI_FM2)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_AFI_FM1)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_AFI_FM0)] = { .hwdom_access = true },
+
+    /* Channel 0 grants PM access.  */
+    [PM_RESET_IDX(PM_RESET_GDMA)] = { MM_GDMA_CH0 },
+    [PM_RESET_IDX(PM_RESET_GPU_PP1)] = { MM_GPU },
+    [PM_RESET_IDX(PM_RESET_GPU_PP0)] = { MM_GPU },
+    [PM_RESET_IDX(PM_RESET_GT)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_SATA)] = { MM_SATA_AHCI_HBA },
+
+    /* We don't allow anyone to turn on/off the ACPUs.  */
+    [PM_RESET_IDX(PM_RESET_ACPU3_PWRON)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_ACPU2_PWRON)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_ACPU1_PWRON)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_ACPU0_PWRON)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_APU_L2)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_ACPU3)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_ACPU2)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_ACPU1)] = { 0 },
+    [PM_RESET_IDX(PM_RESET_ACPU0)] = { 0 },
+
+    [PM_RESET_IDX(PM_RESET_DDR)] = { 0 },
+
+    [PM_RESET_IDX(PM_RESET_APM_FPD)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_SOFT)] = { .hwdom_access = true },
+
+    [PM_RESET_IDX(PM_RESET_GEM0)] = { MM_GEM0 },
+    [PM_RESET_IDX(PM_RESET_GEM1)] = { MM_GEM1 },
+    [PM_RESET_IDX(PM_RESET_GEM2)] = { MM_GEM2 },
+    [PM_RESET_IDX(PM_RESET_GEM3)] = { MM_GEM3 },
+
+    [PM_RESET_IDX(PM_RESET_QSPI)] = { MM_QSPI },
+    [PM_RESET_IDX(PM_RESET_UART0)] = { MM_UART0 },
+    [PM_RESET_IDX(PM_RESET_UART1)] = { MM_UART1 },
+    [PM_RESET_IDX(PM_RESET_SPI0)] = { MM_SPI0 },
+    [PM_RESET_IDX(PM_RESET_SPI1)] = { MM_SPI1 },
+    [PM_RESET_IDX(PM_RESET_SDIO0)] = { MM_SD0 },
+    [PM_RESET_IDX(PM_RESET_SDIO1)] = { MM_SD1 },
+    [PM_RESET_IDX(PM_RESET_CAN0)] = { MM_CAN0 },
+    [PM_RESET_IDX(PM_RESET_CAN1)] = { MM_CAN1 },
+    [PM_RESET_IDX(PM_RESET_I2C0)] = { MM_I2C0 },
+    [PM_RESET_IDX(PM_RESET_I2C1)] = { MM_I2C1 },
+    [PM_RESET_IDX(PM_RESET_TTC0)] = { MM_TTC0 },
+    [PM_RESET_IDX(PM_RESET_TTC1)] = { MM_TTC1 },
+    [PM_RESET_IDX(PM_RESET_TTC2)] = { MM_TTC2 },
+    [PM_RESET_IDX(PM_RESET_TTC3)] = { MM_TTC3 },
+    [PM_RESET_IDX(PM_RESET_SWDT_CRL)] = { MM_SWDT },
+    [PM_RESET_IDX(PM_RESET_NAND)] = { MM_NAND },
+    /* ADMA Channel 0 grants access to pull the reset signal.  */
+    [PM_RESET_IDX(PM_RESET_ADMA)] = { MM_ADMA_CH0 },
+    [PM_RESET_IDX(PM_RESET_GPIO)] = { MM_GPIO },
+    /* FIXME: What is this?  */
+    [PM_RESET_IDX(PM_RESET_IOU_CC)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_TIMESTAMP)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_RPU_R50)] = { MM_RPU },
+    [PM_RESET_IDX(PM_RESET_RPU_R51)] = { MM_RPU },
+    [PM_RESET_IDX(PM_RESET_RPU_AMBA)] = { MM_RPU },
+    [PM_RESET_IDX(PM_RESET_OCM)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_RPU_PGE)] = { MM_RPU },
+
+    [PM_RESET_IDX(PM_RESET_USB0_CORERESET)] = { MM_USB3_0 },
+    [PM_RESET_IDX(PM_RESET_USB0_HIBERRESET)] = { MM_USB3_0 },
+    [PM_RESET_IDX(PM_RESET_USB0_APB)] = { MM_USB3_0 },
+
+    [PM_RESET_IDX(PM_RESET_USB1_CORERESET)] = { MM_USB3_1 },
+    [PM_RESET_IDX(PM_RESET_USB1_HIBERRESET)] = { MM_USB3_1 },
+    [PM_RESET_IDX(PM_RESET_USB1_APB)] = { MM_USB3_1 },
+
+    [PM_RESET_IDX(PM_RESET_IPI)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_APM_LPD)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_RTC)] = { MM_RTC },
+    [PM_RESET_IDX(PM_RESET_SYSMON)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_AFI_FM6)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_LPD_SWDT)] = { MM_SWDT },
+    [PM_RESET_IDX(PM_RESET_FPD)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_RPU_DBG1)] = { MM_RPU },
+    [PM_RESET_IDX(PM_RESET_RPU_DBG0)] = { MM_RPU },
+    [PM_RESET_IDX(PM_RESET_DBG_LPD)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_DBG_FPD)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_APLL)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_DPLL)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_VPLL)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_IOPLL)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_RPLL)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_0)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_1)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_2)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_3)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_4)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_5)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_6)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_7)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_8)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_9)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_10)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_11)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_12)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_13)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_14)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_15)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_16)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_17)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_18)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_19)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_20)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_21)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_22)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_23)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_24)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_25)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_26)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_27)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_28)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_29)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_30)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_GPO3_PL_31)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_RPU_LS)] = { MM_RPU },
+    [PM_RESET_IDX(PM_RESET_PS_ONLY)] = { .hwdom_access = true },
+    [PM_RESET_IDX(PM_RESET_PL)] = { .hwdom_access = true },
+};
+
+/*
+ * This table maps reset line IDs into a memory address.
+ * If a guest has access to the address, it has enough control
+ * over the affected node to grant it access to EEMI calls for
+ * resetting that node.
+ */
+static const struct {
+    uint64_t start;
+    uint64_t end;    /* Inclusive. If not set, single reg entry.  */
+    uint32_t mask;   /* Zero means no mask, i.e all bits.  */
+    enum pm_node_id node;
+    bool hwdom_access;
+    bool readonly;
+} pm_mmio_access[] = {
+    {
+        .start = MM_CRF_APB + R_CRF_APLL_CTRL,
+        .end = MM_CRF_APB + R_CRF_ACPU_CTRL,
+        .hwdom_access = true
+    },
+    {
+        .start = MM_CRL_APB + R_CRL_IOPLL_CTRL,
+        .end = MM_CRL_APB + R_CRL_RPLL_TO_FPD_CTRL,
+        .hwdom_access = true
+    },
+    { .start = MM_CRF_APB + R_CRF_DP_VIDEO_REF_CTRL, .node = NODE_DP },
+    { .start = MM_CRF_APB + R_CRF_DP_STC_REF_CTRL, .node = NODE_DP },
+    { .start = MM_CRF_APB + R_CRF_GPU_REF_CTRL, .node = NODE_GPU },
+    { .start = MM_CRF_APB + R_CRF_SATA_REF_CTRL, .node = NODE_SATA },
+    { .start = MM_CRF_APB + R_CRF_PCIE_REF_CTRL, .node = NODE_PCIE },
+    { .start = MM_CRF_APB + R_CRF_GDMA_REF_CTRL, .node = NODE_GDMA },
+    { .start = MM_CRF_APB + R_CRF_DPDMA_REF_CTRL, .node = NODE_DP },
+    { .start = MM_CRL_APB + R_CRL_USB3_DUAL_REF_CTRL, .node = NODE_USB_0 },
+    { .start = MM_CRL_APB + R_CRL_USB0_BUS_REF_CTRL, .node = NODE_USB_0 },
+    { .start = MM_CRL_APB + R_CRL_USB1_BUS_REF_CTRL, .node = NODE_USB_1 },
+    { .start = MM_CRL_APB + R_CRL_USB1_BUS_REF_CTRL, .node = NODE_USB_1 },
+    { .start = MM_CRL_APB + R_CRL_GEM0_REF_CTRL, .node = NODE_ETH_0 },
+    { .start = MM_CRL_APB + R_CRL_GEM1_REF_CTRL, .node = NODE_ETH_1 },
+    { .start = MM_CRL_APB + R_CRL_GEM2_REF_CTRL, .node = NODE_ETH_2 },
+    { .start = MM_CRL_APB + R_CRL_GEM3_REF_CTRL, .node = NODE_ETH_3 },
+    { .start = MM_CRL_APB + R_CRL_QSPI_REF_CTRL, .node = NODE_QSPI },
+    { .start = MM_CRL_APB + R_CRL_SDIO0_REF_CTRL, .node = NODE_SD_0 },
+    { .start = MM_CRL_APB + R_CRL_SDIO1_REF_CTRL, .node = NODE_SD_1 },
+    { .start = MM_CRL_APB + R_CRL_UART0_REF_CTRL, .node = NODE_UART_0 },
+    { .start = MM_CRL_APB + R_CRL_UART1_REF_CTRL, .node = NODE_UART_1 },
+    { .start = MM_CRL_APB + R_CRL_SPI0_REF_CTRL, .node = NODE_SPI_0 },
+    { .start = MM_CRL_APB + R_CRL_SPI1_REF_CTRL, .node = NODE_SPI_1 },
+    { .start = MM_CRL_APB + R_CRL_CAN0_REF_CTRL, .node = NODE_CAN_0 },
+    { .start = MM_CRL_APB + R_CRL_CAN1_REF_CTRL, .node = NODE_CAN_1 },
+    { .start = MM_CRL_APB + R_CRL_CPU_R5_CTRL, .node = NODE_RPU },
+    { .start = MM_CRL_APB + R_CRL_IOU_SWITCH_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_CSU_PLL_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PCAP_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_LPD_SWITCH_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_LPD_LSBUS_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_DBG_LPD_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_NAND_REF_CTRL, .node = NODE_NAND },
+    { .start = MM_CRL_APB + R_CRL_ADMA_REF_CTRL, .node = NODE_ADMA },
+    { .start = MM_CRL_APB + R_CRL_PL0_REF_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL1_REF_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL2_REF_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL3_REF_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL0_THR_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL1_THR_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL2_THR_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL3_THR_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL0_THR_CNT, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL1_THR_CNT, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL2_THR_CNT, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_PL3_THR_CNT, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_GEM_TSU_REF_CTRL, .node = NODE_ETH_0 },
+    { .start = MM_CRL_APB + R_CRL_DLL_REF_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_AMS_REF_CTRL, .hwdom_access = true },
+    { .start = MM_CRL_APB + R_CRL_I2C0_REF_CTRL, .node = NODE_I2C_0 },
+    { .start = MM_CRL_APB + R_CRL_I2C1_REF_CTRL, .node = NODE_I2C_1 },
+    { .start = MM_CRL_APB + R_CRL_TIMESTAMP_REF_CTRL, .hwdom_access = true },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_WDT_CLK_SEL, .hwdom_access = true },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_CAN_MIO_CTRL,
+        .mask = 0x1ff, .node = NODE_CAN_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_CAN_MIO_CTRL,
+        .mask = 0x1ff << 15, .node = NODE_CAN_1
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
+        .mask = 0xf, .node = NODE_ETH_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
+        .mask = 0xf << 5, .node = NODE_ETH_1
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
+        .mask = 0xf << 10, .node = NODE_ETH_2
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
+        .mask = 0xf << 15, .node = NODE_ETH_3
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
+        .mask = 0x7 << 20, .hwdom_access = true
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_SDIO_CLK_CTRL,
+        .mask = 0x7, .node = NODE_SD_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_SDIO_CLK_CTRL,
+        .mask = 0x7 << 17, .node = NODE_SD_1
+    },
+
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_CTRL_REG_SD,
+        .mask = 0x1, .node = NODE_SD_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_CTRL_REG_SD,
+        .mask = 0x1 << 15, .node = NODE_SD_1
+    },
+    /* A series of SD regs with the same layout.  */
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_SD_ITAPDLY,
+        .end = MM_IOU_SLCR + R_IOU_SLCR_SD_CDN_CTRL,
+        .mask = 0x3ff << 0, .node = NODE_SD_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_SD_ITAPDLY,
+        .end = MM_IOU_SLCR + R_IOU_SLCR_SD_CDN_CTRL,
+        .mask = 0x3ff << 16, .node = NODE_SD_1
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CTRL,
+        .mask = 0x3 << 0, .node = NODE_ETH_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CTRL,
+        .mask = 0x3 << 2, .node = NODE_ETH_1
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CTRL,
+        .mask = 0x3 << 4, .node = NODE_ETH_2
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CTRL,
+        .mask = 0x3 << 6, .node = NODE_ETH_3
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TTC_APB_CLK,
+        .mask = 0x3 << 0, .node = NODE_TTC_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TTC_APB_CLK,
+        .mask = 0x3 << 2, .node = NODE_TTC_1
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TTC_APB_CLK,
+        .mask = 0x3 << 4, .node = NODE_TTC_2
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TTC_APB_CLK,
+        .mask = 0x3 << 6, .node = NODE_TTC_3
+    },
+
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TAPDLY_BYPASS,
+        .mask = 0x3, .node = NODE_NAND
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TAPDLY_BYPASS,
+        .mask = 0x1 << 2, .node = NODE_QSPI
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 0, .node = NODE_ETH_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 4, .node = NODE_ETH_1
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 8, .node = NODE_ETH_2
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 12, .node = NODE_ETH_3
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 16, .node = NODE_SD_0
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 20, .node = NODE_SD_1
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 24, .node = NODE_NAND
+    },
+    {
+        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
+        .mask = 0xf << 28, .node = NODE_QSPI
+    },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_VIDEO_PSS_CLK_SEL, .hwdom_access = true },
+    /* No access to R_IOU_SLCR_IOU_INTERCONNECT_ROUTE at all.  */
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_GEM0, .node = NODE_ETH_0 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_GEM1, .node = NODE_ETH_1 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_GEM2, .node = NODE_ETH_2 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_GEM3, .node = NODE_ETH_3 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_SD0, .node = NODE_SD_0 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_SD1, .node = NODE_SD_1 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_CAN0, .node = NODE_CAN_0 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_CAN1, .node = NODE_CAN_1 },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_LQSPI, .node = NODE_QSPI },
+    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_NAND, .node = NODE_NAND },
+    {
+        .start = MM_PMU_GLOBAL + R_PMU_GLOBAL_PWR_STATE,
+        .readonly = true,
+    },
+    {
+        .start = MM_PMU_GLOBAL + R_PMU_GLOBAL_GLOBAL_GEN_STORAGE0,
+        .end = MM_PMU_GLOBAL + R_PMU_GLOBAL_PERS_GLOB_GEN_STORAGE7,
+        .readonly = true,
+    },
+    {
+        /* Universal read-only access to CRF. Linux CCF needs this.  */
+        .start = MM_CRF_APB, .end = MM_CRF_APB + 0x104,
+        .readonly = true,
+    },
+    {
+        /* Universal read-only access to CRL. Linux CCF needs this.  */
+        .start = MM_CRL_APB, .end = MM_CRL_APB + 0x284,
+        .readonly = true,
+    }
+};
+
+static bool pm_check_access(const struct pm_access *acl, struct domain *d, int idx)
+{
+    unsigned long mfn;
+
+    if ( acl[idx].hwdom_access && is_hardware_domain(d) )
+        return true;
+
+    mfn = paddr_to_pfn(acl[idx].addr);
+    if ( !mfn )
+        return false;
+
+    return iomem_access_permitted(d, mfn, mfn);
+}
+
+/* Check if a domain has access to a node.  */
+static bool domain_has_node_access(struct domain *d, enum pm_node_id node)
+{
+    if ( node <= 0 || node > ARRAY_SIZE(pm_node_access) )
+        return false;
+
+    /* NODE_UNKNOWN is treated as a wildcard.  */
+    if ( node == NODE_UNKNOWN )
+        return true;
+
+    return pm_check_access(pm_node_access, d, node);
+}
+
+/* Check if a domain has access to a reset line.  */
+static bool domain_has_reset_access(struct domain *d, enum pm_reset rst)
+{
+    int rst_idx = PM_RESET_IDX(rst);
+
+    if ( rst_idx < 0 || rst_idx > ARRAY_SIZE(pm_reset_access) )
+        return false;
+
+    return pm_check_access(pm_reset_access, d, rst_idx);
+}
+
+/*
+ * Check if a given domain has access to perform an indirect
+ * MMIO access.
+ *
+ * If the provided mask is invalid, it will be fixed up.
+ */
+static bool domain_mediate_mmio_access(struct domain *d,
+                                       bool write, uint64_t addr,
+                                       uint32_t *mask)
+{
+    unsigned int i;
+    bool ret = false;
+    uint32_t prot_mask = 0;
+
+    ASSERT(mask);
+
+    /*
+     * The hardware domain gets read access to everything.
+     * Lower layers will do further filtering.
+     */
+    if ( !write && is_hardware_domain(d) )
+        return true;
+
+    /* Scan the ACL.  */
+    for ( i = 0; i < ARRAY_SIZE(pm_mmio_access); i++ ) {
+        bool r;
+
+        /* Check if the address is OK.  */
+        if ( pm_mmio_access[i].end ) {
+            /* Memory range.  */
+            if ( addr < pm_mmio_access[i].start )
+                continue;
+            if ( addr > pm_mmio_access[i].end )
+                continue;
+        } else {
+            /* Single register.  */
+            if ( addr != pm_mmio_access[i].start )
+                continue;
+        }
+
+        if ( write && pm_mmio_access[i].readonly )
+            continue;
+        if ( pm_mmio_access[i].hwdom_access && !is_hardware_domain(d) )
+            continue;
+
+        /* Unlimited access is represented by a zero mask.  */
+        ASSERT( pm_mmio_access[i].mask != 0xFFFFFFFF );
+
+        r = domain_has_node_access(d, pm_mmio_access[i].node);
+        if ( r ) {
+            /* We've got access to this reg (or parts of it).  */
+            ret = true;
+            /* Masking only applies to writes, so reads can exit here.  */
+            if ( !write )
+                break;
+
+            /* Permit write access to selected bits.  */
+            prot_mask |= pm_mmio_access[i].mask ? pm_mmio_access[i].mask : ~0;
+            printk("match: mask=%x prot_mask=%x\n",
+                   pm_mmio_access[i].mask, prot_mask);
+            if ( prot_mask == 0xFFFFFFFF )
+                break; /* Full access, we're done.  */
+        } else {
+            if ( !pm_mmio_access[i].mask ) {
+                /*
+                 * The entire reg is tied to a device that we don't have
+                 * access to. No point in continuing.
+                 */
+                return false;
+            }
+        }
+    }
+
+    /* Masking only applies to writes.  */
+    if ( write )
+        *mask &= prot_mask;
+    return ret;
+}
+
+bool zynqmp_eemi_mediate(register_t fid,
+                         register_t a0,
+                         register_t a1,
+                         register_t a2,
+                         register_t a3,
+                         register_t a4,
+                         register_t a5,
+                         register_t *ret)
+{
+    bool is_mmio_write = false;
+    unsigned int pm_fn = fid & 0xFFFF;
+    uint32_t pm_arg[4];
+
+    /* Decode pm args.  */
+    pm_arg[0] = a0;
+    pm_arg[1] = a0 >> 32;
+    pm_arg[2] = a1;
+    pm_arg[3] = a1 >> 32;
+
+    ASSERT(ret);
+
+    switch (pm_fn)
+    {
+    /*
+     * We can't allow CPUs to suspend without Xen knowing about it.
+     * We accept but ignore the request and wait for the guest to issue
+     * a WFI which Xen will trap and act accordingly upon.
+     */
+    case PM_SELF_SUSPEND:
+        ret[0] = PM_RET_SUCCESS;
+        goto done;
+
+    case PM_GET_NODE_STATUS:
+    /* API for PUs.  */
+    case PM_REQ_SUSPEND:
+    case PM_FORCE_POWERDOWN:
+    case PM_ABORT_SUSPEND:
+    case PM_REQ_WAKEUP:
+    case PM_SET_WAKEUP_SOURCE:
+    /* API for slaves.  */
+    case PM_REQ_NODE:
+    case PM_RELEASE_NODE:
+    case PM_SET_REQUIREMENT:
+    case PM_SET_MAX_LATENCY:
+        if ( !domain_has_node_access(current->domain, pm_arg[0]) ) {
+            printk("zynqmp-pm: fn=%d No access to node %d\n", pm_fn, pm_arg[0]);
+            ret[0] = PM_RET_ERROR_ACCESS;
+            goto done;
+        }
+        goto forward_to_fw;
+
+    case PM_RESET_ASSERT:
+    case PM_RESET_GET_STATUS:
+        if ( !domain_has_reset_access(current->domain, pm_arg[0]) ) {
+            printk("zynqmp-pm: fn=%d No access to reset %d\n", pm_fn, pm_arg[0]);
+            ret[0] = PM_RET_ERROR_ACCESS;
+            goto done;
+        }
+        goto forward_to_fw;
+
+    /* These calls are safe and always allowed.  */
+    case ZYNQMP_SIP_SVC_CALL_COUNT:
+    case ZYNQMP_SIP_SVC_UID:
+    case ZYNQMP_SIP_SVC_VERSION:
+    case PM_GET_API_VERSION:
+    case PM_GET_CHIPID:
+        goto forward_to_fw;
+
+    /* Mediated MMIO access.  */
+    case PM_MMIO_WRITE:
+        is_mmio_write = true;
+    /* Fallthrough.  */
+    case PM_MMIO_READ:
+        if ( !domain_mediate_mmio_access(current->domain,
+                                         is_mmio_write,
+                                         pm_arg[0], &pm_arg[1]) ) {
+            printk("eemi: fn=%d No access to MMIO %s %x\n",
+                   pm_fn, is_mmio_write ? "write" : "read", pm_arg[0]);
+            ret[0] = PM_RET_ERROR_ACCESS;
+            goto done;
+        }
+        goto forward_to_fw;
+
+    /* Exclusive to Dom0.  */
+    case PM_INIT:
+    case PM_SET_CONFIGURATION:
+    case PM_FPGA_LOAD:
+    case PM_FPGA_GET_STATUS:
+        if ( !is_hardware_domain(current->domain) ) {
+            printk("eemi: fn=%d No access", pm_fn);
+            ret[0] = PM_RET_ERROR_ACCESS;
+            goto done;
+        }
+        goto forward_to_fw;
+
+    /* These calls are never allowed.  */
+    case PM_SYSTEM_SHUTDOWN:
+        ret[0] = PM_RET_ERROR_ACCESS;
+        goto done;
+
+    default:
+        printk("zynqmp-pm: Unhandled PM Call: %d\n", (u32)fid);
+        return false;
+    }
+
+forward_to_fw:
+    /* Re-encode pm args.  */
+    a0 = ((uint64_t)pm_arg[1] << 32) | pm_arg[0];
+    a1 = ((uint64_t)pm_arg[3] << 32) | pm_arg[2];
+    call_smcc64(fid, a0, a1, a2, a3, a4, a5, ret);
+done:
+    return true;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/platforms/xilinx-zynqmp.c b/xen/arch/arm/platforms/xilinx-zynqmp.c
index 2adee91..d826282 100644
--- a/xen/arch/arm/platforms/xilinx-zynqmp.c
+++ b/xen/arch/arm/platforms/xilinx-zynqmp.c
@@ -18,6 +18,7 @@
  */
 
 #include <asm/platform.h>
+#include <asm/platforms/xilinx-zynqmp-eemi.h>
 
 static const char * const zynqmp_dt_compat[] __initconst =
 {
@@ -32,8 +33,25 @@ static const struct dt_device_match zynqmp_blacklist_dev[] __initconst =
     { /* sentinel */ },
 };
 
+bool zynqmp_hvc(struct cpu_user_regs *regs)
+{
+    register_t ret[4] = { 0 };
+
+    if ( !zynqmp_eemi_mediate(regs->x0, regs->x1, regs->x2, regs->x3,
+                              regs->x4, regs->x5, regs->x6, ret) )
+        return false;
+
+    /* Transfer return values into guest registers.  */
+    regs->x0 = ret[0];
+    regs->x1 = ret[1];
+    regs->x2 = ret[2];
+    regs->x3 = ret[3];
+    return true;
+}
+
 PLATFORM_START(xgene_storm, "Xilinx ZynqMP")
     .compatible = zynqmp_dt_compat,
+    .hvc = zynqmp_hvc,
     .blacklist_dev = zynqmp_blacklist_dev,
 PLATFORM_END
 
diff --git a/xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h b/xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h
new file mode 100644
index 0000000..774593c
--- /dev/null
+++ b/xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h
@@ -0,0 +1,337 @@
+/* Xen specifics:  */
+/* Main PM Mediator entry.  */
+bool zynqmp_eemi_mediate(register_t fid,
+                         register_t a0,
+                         register_t a1,
+                         register_t a2,
+                         register_t a3,
+                         register_t a4,
+                         register_t a5,
+                         register_t *ret);
+
+/* Service calls.  */
+#define SVC_MASK             0x3F000000
+#define SVC_SIP              0x02000000    /* SoC Implementation Specific.  */
+#define PM_SIP_SVC           0xC2000000
+
+/* SMC function IDs for SiP Service queries */
+#define ZYNQMP_SIP_SVC_CALL_COUNT       0xff00
+#define ZYNQMP_SIP_SVC_UID              0xff01
+#define ZYNQMP_SIP_SVC_VERSION          0xff03
+
+/* Generic PM defs:  */
+/*
+ * Version number is a 32bit value, like:
+ * (PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR
+ */
+#define PM_VERSION_MAJOR	0
+#define PM_VERSION_MINOR	2
+
+#define PM_VERSION	((PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR)
+
+/* Capabilities for RAM */
+#define PM_CAP_ACCESS	0x1U
+#define PM_CAP_CONTEXT	0x2U
+
+#define MAX_LATENCY	(~0U)
+#define MAX_QOS		100U
+
+/* State arguments of the self suspend */
+#define PM_STATE_CPU_IDLE		0x0U
+#define PM_STATE_SUSPEND_TO_RAM		0xFU
+
+enum pm_api_id {
+	/* Miscellaneous API functions: */
+	PM_GET_API_VERSION = 1, /* Do not change or move */
+	PM_SET_CONFIGURATION,
+	PM_GET_NODE_STATUS,
+	PM_GET_OP_CHARACTERISTIC,
+	PM_REGISTER_NOTIFIER,
+	/* API for suspending of PUs: */
+	PM_REQ_SUSPEND,
+	PM_SELF_SUSPEND,
+	PM_FORCE_POWERDOWN,
+	PM_ABORT_SUSPEND,
+	PM_REQ_WAKEUP,
+	PM_SET_WAKEUP_SOURCE,
+	PM_SYSTEM_SHUTDOWN,
+	/* API for managing PM slaves: */
+	PM_REQ_NODE,
+	PM_RELEASE_NODE,
+	PM_SET_REQUIREMENT,
+	PM_SET_MAX_LATENCY,
+	/* Direct control API functions: */
+	PM_RESET_ASSERT,
+	PM_RESET_GET_STATUS,
+	PM_MMIO_WRITE,
+	PM_MMIO_READ,
+	PM_INIT,
+	PM_FPGA_LOAD,
+	PM_FPGA_GET_STATUS,
+	PM_GET_CHIPID,
+	PM_API_MAX
+};
+
+enum pm_node_id {
+	NODE_UNKNOWN = 0,
+	NODE_APU,
+	NODE_APU_0,
+	NODE_APU_1,
+	NODE_APU_2,
+	NODE_APU_3,
+	NODE_RPU,
+	NODE_RPU_0,
+	NODE_RPU_1,
+	NODE_PL,
+	NODE_FPD,
+	NODE_OCM_BANK_0,
+	NODE_OCM_BANK_1,
+	NODE_OCM_BANK_2,
+	NODE_OCM_BANK_3,
+	NODE_TCM_0_A,
+	NODE_TCM_0_B,
+	NODE_TCM_1_A,
+	NODE_TCM_1_B,
+	NODE_L2,
+	NODE_GPU_PP_0,
+	NODE_GPU_PP_1,
+	NODE_USB_0,
+	NODE_USB_1,
+	NODE_TTC_0,
+	NODE_TTC_1,
+	NODE_TTC_2,
+	NODE_TTC_3,
+	NODE_SATA,
+	NODE_ETH_0,
+	NODE_ETH_1,
+	NODE_ETH_2,
+	NODE_ETH_3,
+	NODE_UART_0,
+	NODE_UART_1,
+	NODE_SPI_0,
+	NODE_SPI_1,
+	NODE_I2C_0,
+	NODE_I2C_1,
+	NODE_SD_0,
+	NODE_SD_1,
+	NODE_DP,
+	NODE_GDMA,
+	NODE_ADMA,
+	NODE_NAND,
+	NODE_QSPI,
+	NODE_GPIO,
+	NODE_CAN_0,
+	NODE_CAN_1,
+	NODE_AFI,
+	NODE_APLL,
+	NODE_VPLL,
+	NODE_DPLL,
+	NODE_RPLL,
+	NODE_IOPLL,
+	NODE_DDR,
+	NODE_IPI_APU,
+	NODE_IPI_RPU_0,
+	NODE_GPU,
+	NODE_PCIE,
+	NODE_PCAP,
+	NODE_RTC,
+	NODE_MAX
+};
+
+enum pm_request_ack {
+	REQ_ACK_NO = 1,
+	REQ_ACK_BLOCKING,
+	REQ_ACK_NON_BLOCKING,
+};
+
+enum pm_abort_reason {
+	ABORT_REASON_WKUP_EVENT = 100,
+	ABORT_REASON_PU_BUSY,
+	ABORT_REASON_NO_PWRDN,
+	ABORT_REASON_UNKNOWN,
+};
+
+enum pm_suspend_reason {
+	SUSPEND_REASON_PU_REQ = 201,
+	SUSPEND_REASON_ALERT,
+	SUSPEND_REASON_SYS_SHUTDOWN,
+};
+
+enum pm_ram_state {
+	PM_RAM_STATE_OFF = 1,
+	PM_RAM_STATE_RETENTION,
+	PM_RAM_STATE_ON,
+};
+
+enum pm_opchar_type {
+	PM_OPCHAR_TYPE_POWER = 1,
+	PM_OPCHAR_TYPE_TEMP,
+	PM_OPCHAR_TYPE_LATENCY,
+};
+
+/**
+ * @PM_RET_SUCCESS:		success
+ * @PM_RET_ERROR_ARGS:		illegal arguments provided
+ * @PM_RET_ERROR_ACCESS:	access rights violation
+ * @PM_RET_ERROR_TIMEOUT:	timeout in communication with PMU
+ * @PM_RET_ERROR_NOTSUPPORTED:	feature not supported
+ * @PM_RET_ERROR_PROC:		node is not a processor node
+ * @PM_RET_ERROR_API_ID:	illegal API ID
+ * @PM_RET_ERROR_OTHER:		other error
+ */
+enum pm_ret_status {
+	PM_RET_SUCCESS,
+	PM_RET_ERROR_ARGS,
+	PM_RET_ERROR_ACCESS,
+	PM_RET_ERROR_TIMEOUT,
+	PM_RET_ERROR_NOTSUPPORTED,
+	PM_RET_ERROR_PROC,
+	PM_RET_ERROR_API_ID,
+	PM_RET_ERROR_FAILURE,
+	PM_RET_ERROR_COMMUNIC,
+	PM_RET_ERROR_DOUBLEREQ,
+	PM_RET_ERROR_OTHER,
+};
+
+/**
+ * @PM_INITIAL_BOOT:	boot is a fresh system startup
+ * @PM_RESUME:		boot is a resume
+ * @PM_BOOT_ERROR:	error, boot cause cannot be identified
+ */
+enum pm_boot_status {
+	PM_INITIAL_BOOT,
+	PM_RESUME,
+	PM_BOOT_ERROR,
+};
+
+enum pm_shutdown_type {
+	PMF_SHUTDOWN_TYPE_SHUTDOWN,
+	PMF_SHUTDOWN_TYPE_RESET,
+};
+
+enum pm_shutdown_subtype {
+	PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM,
+	PMF_SHUTDOWN_SUBTYPE_PS_ONLY,
+	PMF_SHUTDOWN_SUBTYPE_SYSTEM,
+};
+
+enum pm_reset {
+	PM_RESET_START = 999,
+	PM_RESET_PCIE_CFG,
+	PM_RESET_PCIE_BRIDGE,
+	PM_RESET_PCIE_CTRL,
+	PM_RESET_DP,
+	PM_RESET_SWDT_CRF,
+	PM_RESET_AFI_FM5,
+	PM_RESET_AFI_FM4,
+	PM_RESET_AFI_FM3,
+	PM_RESET_AFI_FM2,
+	PM_RESET_AFI_FM1,
+	PM_RESET_AFI_FM0,
+	PM_RESET_GDMA,
+	PM_RESET_GPU_PP1,
+	PM_RESET_GPU_PP0,
+	PM_RESET_GPU,
+	PM_RESET_GT,
+	PM_RESET_SATA,
+	PM_RESET_ACPU3_PWRON,
+	PM_RESET_ACPU2_PWRON,
+	PM_RESET_ACPU1_PWRON,
+	PM_RESET_ACPU0_PWRON,
+	PM_RESET_APU_L2,
+	PM_RESET_ACPU3,
+	PM_RESET_ACPU2,
+	PM_RESET_ACPU1,
+	PM_RESET_ACPU0,
+	PM_RESET_DDR,
+	PM_RESET_APM_FPD,
+	PM_RESET_SOFT,
+	PM_RESET_GEM0,
+	PM_RESET_GEM1,
+	PM_RESET_GEM2,
+	PM_RESET_GEM3,
+	PM_RESET_QSPI,
+	PM_RESET_UART0,
+	PM_RESET_UART1,
+	PM_RESET_SPI0,
+	PM_RESET_SPI1,
+	PM_RESET_SDIO0,
+	PM_RESET_SDIO1,
+	PM_RESET_CAN0,
+	PM_RESET_CAN1,
+	PM_RESET_I2C0,
+	PM_RESET_I2C1,
+	PM_RESET_TTC0,
+	PM_RESET_TTC1,
+	PM_RESET_TTC2,
+	PM_RESET_TTC3,
+	PM_RESET_SWDT_CRL,
+	PM_RESET_NAND,
+	PM_RESET_ADMA,
+	PM_RESET_GPIO,
+	PM_RESET_IOU_CC,
+	PM_RESET_TIMESTAMP,
+	PM_RESET_RPU_R50,
+	PM_RESET_RPU_R51,
+	PM_RESET_RPU_AMBA,
+	PM_RESET_OCM,
+	PM_RESET_RPU_PGE,
+	PM_RESET_USB0_CORERESET,
+	PM_RESET_USB1_CORERESET,
+	PM_RESET_USB0_HIBERRESET,
+	PM_RESET_USB1_HIBERRESET,
+	PM_RESET_USB0_APB,
+	PM_RESET_USB1_APB,
+	PM_RESET_IPI,
+	PM_RESET_APM_LPD,
+	PM_RESET_RTC,
+	PM_RESET_SYSMON,
+	PM_RESET_AFI_FM6,
+	PM_RESET_LPD_SWDT,
+	PM_RESET_FPD,
+	PM_RESET_RPU_DBG1,
+	PM_RESET_RPU_DBG0,
+	PM_RESET_DBG_LPD,
+	PM_RESET_DBG_FPD,
+	PM_RESET_APLL,
+	PM_RESET_DPLL,
+	PM_RESET_VPLL,
+	PM_RESET_IOPLL,
+	PM_RESET_RPLL,
+	PM_RESET_GPO3_PL_0,
+	PM_RESET_GPO3_PL_1,
+	PM_RESET_GPO3_PL_2,
+	PM_RESET_GPO3_PL_3,
+	PM_RESET_GPO3_PL_4,
+	PM_RESET_GPO3_PL_5,
+	PM_RESET_GPO3_PL_6,
+	PM_RESET_GPO3_PL_7,
+	PM_RESET_GPO3_PL_8,
+	PM_RESET_GPO3_PL_9,
+	PM_RESET_GPO3_PL_10,
+	PM_RESET_GPO3_PL_11,
+	PM_RESET_GPO3_PL_12,
+	PM_RESET_GPO3_PL_13,
+	PM_RESET_GPO3_PL_14,
+	PM_RESET_GPO3_PL_15,
+	PM_RESET_GPO3_PL_16,
+	PM_RESET_GPO3_PL_17,
+	PM_RESET_GPO3_PL_18,
+	PM_RESET_GPO3_PL_19,
+	PM_RESET_GPO3_PL_20,
+	PM_RESET_GPO3_PL_21,
+	PM_RESET_GPO3_PL_22,
+	PM_RESET_GPO3_PL_23,
+	PM_RESET_GPO3_PL_24,
+	PM_RESET_GPO3_PL_25,
+	PM_RESET_GPO3_PL_26,
+	PM_RESET_GPO3_PL_27,
+	PM_RESET_GPO3_PL_28,
+	PM_RESET_GPO3_PL_29,
+	PM_RESET_GPO3_PL_30,
+	PM_RESET_GPO3_PL_31,
+	PM_RESET_RPU_LS,
+	PM_RESET_PS_ONLY,
+	PM_RESET_PL,
+	PM_RESET_END
+};
diff --git a/xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h b/xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h
new file mode 100644
index 0000000..4fb1695
--- /dev/null
+++ b/xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h
@@ -0,0 +1,284 @@
+/*
+ * Merge of various auto-generated memory map and register
+ * definition files.
+ */
+
+/* Selected set of memory-map definitions:  */
+#define MM_IOU_S	0xff000000
+#define MM_IPI	0xff300000
+#define MM_LPD_SLCR	0xff410000
+#define MM_LPD_SLCR_SECURE	0xff4b0000
+#define MM_CRL_APB	0xff5e0000
+#define MM_OCM	0xff960000
+#define MM_LPD_XPPU	0xff980000
+#define MM_RPU	0xff9a0000
+#define MM_AFIFM6	0xff9b0000
+#define MM_LPD_XPPU_SINK	0xff9c0000
+#define MM_USB3_0	0xff9d0000
+#define MM_USB3_1	0xff9e0000
+#define MM_APM_INTC_OCM	0xffa00000
+#define MM_APM_LPD_FPD	0xffa10000
+#define MM_AMS_CTRL	0xffa50000
+#define MM_AMS_PS_SYSMON	0xffa50800
+#define MM_AMS_PL_SYSMON	0xffa50c00
+#define MM_RTC	0xffa60000
+#define MM_OCM_XMPU_CFG	0xffa70000
+#define MM_ADMA_CH0	0xffa80000
+#define MM_ADMA_CH1	0xffa90000
+#define MM_ADMA_CH2	0xffaa0000
+#define MM_ADMA_CH3	0xffab0000
+#define MM_ADMA_CH4	0xffac0000
+#define MM_ADMA_CH5	0xffad0000
+#define MM_ADMA_CH6	0xffae0000
+
+#define MM_IOU_GPV	0xfe0fffff
+#define MM_LPD_GPV	0xfe1fffff
+#define MM_USB3_0_XHCI	0xfe2fffff
+#define MM_USB3_1_XHCI	0xfe3fffff
+#define MM_CORESIGHT_SOC_ROM	0xfe80ffff
+#define MM_CORESIGHT_SOC_TSGEN	0xfe90ffff
+#define MM_CORESIGHT_SOC_FUNN_0	0xfe91ffff
+#define MM_CORESIGHT_SOC_FUNN_1	0xfe92ffff
+#define MM_CORESIGHT_SOC_FUNN_2	0xfe93ffff
+#define MM_CORESIGHT_SOC_ETF_1	0xfe94ffff
+#define MM_CORESIGHT_SOC_ETF_2	0xfe95ffff
+#define MM_CORESIGHT_SOC_REPLIC	0xfe96ffff
+#define MM_CORESIGHT_SOC_ETR	0xfe97ffff
+#define MM_CORESIGHT_SOC_TPIU	0xfe98ffff
+#define MM_CORESIGHT_SOC_CTI_0	0xfe99ffff
+#define MM_CORESIGHT_SOC_CTI_1	0xfe9affff
+#define MM_CORESIGHT_SOC_CTI_2	0xfe9bffff
+#define MM_CORESIGHT_SOC_STM	0xfe9cffff
+#define MM_CORESIGHT_SOC_FTM	0xfe9dffff
+#define MM_CORESIGHT_SOC_ATM_0	0xfe9effff
+#define MM_CORESIGHT_SOC_ATM_1	0xfe9fffff
+#define MM_CORESIGHT_R5_ROM	0xfebe0fff
+#define MM_CORESIGHT_R5_DBG_0	0xfebf0fff
+#define MM_CORESIGHT_R5_PMU_0	0xfebf1fff
+#define MM_CORESIGHT_R5_DBG_1	0xfebf2fff
+#define MM_CORESIGHT_R5_PMU_1	0xfebf3fff
+#define MM_CORESIGHT_R5_CTI_0	0xfebf8fff
+#define MM_CORESIGHT_R5_CTI_1	0xfebf9fff
+#define MM_CORESIGHT_R5_ETM_0	0xfebfcfff
+#define MM_CORESIGHT_R5_ETM_1	0xfebfdfff
+#define MM_CORESIGHT_A53_ROM	0xfec0ffff
+#define MM_CORESIGHT_A53_DBG_0	0xfec1ffff
+#define MM_CORESIGHT_A53_CTI_0	0xfec2ffff
+#define MM_CORESIGHT_A53_PMU_0	0xfec3ffff
+#define MM_CORESIGHT_A53_ETM_0	0xfec4ffff
+#define MM_CORESIGHT_A53_DBG_1	0xfed1ffff
+#define MM_CORESIGHT_A53_CTI_1	0xfed2ffff
+#define MM_CORESIGHT_A53_PMU_1	0xfed3ffff
+#define MM_CORESIGHT_A53_ETM_1	0xfed4ffff
+#define MM_CORESIGHT_A53_DBG_2	0xfee1ffff
+#define MM_CORESIGHT_A53_CTI_2	0xfee2ffff
+#define MM_CORESIGHT_A53_PMU_2	0xfee3ffff
+#define MM_CORESIGHT_A53_ETM_2	0xfee4ffff
+#define MM_CORESIGHT_A53_DBG_3	0xfef1ffff
+#define MM_CORESIGHT_A53_CTI_3	0xfef2ffff
+#define MM_CORESIGHT_A53_PMU_3	0xfef3ffff
+
+#define MM_DDRSS	0xfd000000
+#define MM_SATA_AHCI_HBA	0xfd0c0000
+#define MM_SATA_AHCI_VENDOR	0xfd0c00a0
+#define MM_SATA_AHCI_PORT0_CNTRL	0xfd0c0100
+#define MM_SATA_AHCI_PORT1_CNTRL	0xfd0c0180
+#define MM_AXIPCIE_MAIN	0xfd0e0000
+#define MM_AXIPCIE_INGRESS0	0xfd0e0800
+#define MM_AXIPCIE_INGRESS1	0xfd0e0820
+#define MM_AXIPCIE_INGRESS2	0xfd0e0840
+#define MM_AXIPCIE_INGRESS3	0xfd0e0860
+#define MM_AXIPCIE_INGRESS4	0xfd0e0880
+#define MM_AXIPCIE_INGRESS5	0xfd0e08a0
+#define MM_AXIPCIE_INGRESS6	0xfd0e08c0
+#define MM_AXIPCIE_INGRESS7	0xfd0e08e0
+#define MM_AXIPCIE_EGRESS0	0xfd0e0c00
+#define MM_AXIPCIE_EGRESS1	0xfd0e0c20
+#define MM_AXIPCIE_EGRESS2	0xfd0e0c40
+#define MM_AXIPCIE_EGRESS3	0xfd0e0c60
+#define MM_AXIPCIE_EGRESS4	0xfd0e0c80
+#define MM_AXIPCIE_EGRESS5	0xfd0e0ca0
+#define MM_AXIPCIE_EGRESS6	0xfd0e0cc0
+#define MM_AXIPCIE_EGRESS7	0xfd0e0ce0
+#define MM_AXIPCIE_DMA0	0xfd0f0000
+#define MM_AXIPCIE_DMA1	0xfd0f0080
+#define MM_AXIPCIE_DMA2	0xfd0f0100
+#define MM_AXIPCIE_DMA3	0xfd0f0180
+#define MM_AXIPCIE_MSIX_TABLE	0xfd0f1000
+#define MM_AXIPCIE_MSIX_PBA	0xfd0f2000
+#define MM_CRF_APB	0xfd1a0000
+#define MM_AFIFM0	0xfd360000
+#define MM_AFIFM1	0xfd370000
+#define MM_AFIFM2	0xfd380000
+#define MM_AFIFM3	0xfd390000
+#define MM_AFIFM4	0xfd3a0000
+#define MM_AFIFM5	0xfd3b0000
+#define MM_SIOU	0xfd3d0000
+#define MM_SERDES	0xfd400000
+#define MM_PCIE_ATTRIB	0xfd480000
+#define MM_APM_CCI_INTC	0xfd490000
+#define MM_DP	0xfd4a0000
+#define MM_GPU	0xfd4b0000
+#define MM_DPDMA	0xfd4c0000
+#define MM_WDT	0xfd4d0000
+#define MM_FPD_XMPU_SINK	0xfd4f0000
+#define MM_GDMA_CH0	0xfd500000
+#define MM_GDMA_CH1	0xfd510000
+#define MM_GDMA_CH2	0xfd520000
+#define MM_GDMA_CH3	0xfd530000
+#define MM_GDMA_CH4	0xfd540000
+#define MM_GDMA_CH5	0xfd550000
+#define MM_GDMA_CH6	0xfd560000
+#define MM_GDMA_CH7	0xfd570000
+#define MM_APU	0xfd5c0000
+#define MM_FPD_XMPU_CFG	0xfd5d0000
+#define MM_CCI_REG	0xfd5e0000
+#define MM_SMMU_REG	0xfd5f0000
+#define MM_FPD_SLCR	0xfd610000
+#define MM_FPD_SLCR_SECURE	0xfd690000
+#define MM_CCI_GPV	0xfd6e0000
+#define MM_FPD_GPV	0xfd700000
+
+#define MM_QSPI_Linear_Address	0xc0000000
+#define MM_UART0	0xff000000
+#define MM_UART1	0xff010000
+#define MM_I2C0	0xff020000
+#define MM_I2C1	0xff030000
+#define MM_SPI0	0xff040000
+#define MM_SPI1	0xff050000
+#define MM_CAN0	0xff060000
+#define MM_CAN1	0xff070000
+#define MM_GPIO	0xff0a0000
+#define MM_GEM0	0xff0b0000
+#define MM_GEM1	0xff0c0000
+#define MM_GEM2	0xff0d0000
+#define MM_GEM3	0xff0e0000
+#define MM_QSPI	0xff0f0000
+#define MM_NAND	0xff100000
+#define MM_TTC0	0xff110000
+#define MM_TTC1	0xff120000
+#define MM_TTC2	0xff130000
+#define MM_TTC3	0xff140000
+#define MM_SWDT	0xff150000
+#define MM_SD0	0xff160000
+#define MM_SD1	0xff170000
+#define MM_IOU_SLCR	0xff180000
+#define MM_IOU_SECURE_SLCR	0xff240000
+#define MM_IOU_SCNTR	0xff250000
+
+#define MM_alg_vcu_enc_top	0xa0000000
+#define MM_alg_vcu_dec_top	0xa0020000
+
+#define MM_PMU_GLOBAL           0xffd80000
+#define MM_CSU                  0xffca0000
+
+/* Selected set of register definitions:  */
+#define R_CRF_APLL_CTRL           0x20
+#define R_CRF_ACPU_CTRL           0x60
+#define R_CRF_DP_VIDEO_REF_CTRL   0x70
+#define R_CRF_DP_STC_REF_CTRL     0x7c
+#define R_CRF_GPU_REF_CTRL        0x84
+#define R_CRF_SATA_REF_CTRL       0xa0
+#define R_CRF_PCIE_REF_CTRL       0xb4
+#define R_CRF_GDMA_REF_CTRL       0xb8
+#define R_CRF_DPDMA_REF_CTRL      0xbc
+
+#define R_CRL_IOPLL_CTRL          0x20
+#define R_CRL_IOPLL_CFG           0x24
+#define R_CRL_IOPLL_FRAC_CFG      0x28
+#define R_CRL_RPLL_CTRL           0x30
+#define R_CRL_RPLL_CFG            0x34
+#define R_CRL_RPLL_FRAC_CFG       0x38
+#define R_CRL_PLL_STATUS          0x40
+#define R_CRL_IOPLL_TO_FPD_CTRL   0x44
+#define R_CRL_RPLL_TO_FPD_CTRL    0x48
+#define R_CRL_USB3_DUAL_REF_CTRL  0x4c
+#define R_CRL_GEM0_REF_CTRL       0x50
+#define R_CRL_GEM1_REF_CTRL       0x54
+#define R_CRL_GEM2_REF_CTRL       0x58
+#define R_CRL_GEM3_REF_CTRL       0x5c
+#define R_CRL_USB0_BUS_REF_CTRL   0x60
+#define R_CRL_USB1_BUS_REF_CTRL   0x64
+#define R_CRL_QSPI_REF_CTRL       0x68
+#define R_CRL_SDIO0_REF_CTRL      0x6c
+#define R_CRL_SDIO1_REF_CTRL      0x70
+#define R_CRL_UART0_REF_CTRL      0x74
+#define R_CRL_UART1_REF_CTRL      0x78
+#define R_CRL_SPI0_REF_CTRL       0x7c
+#define R_CRL_SPI1_REF_CTRL       0x80
+#define R_CRL_CAN0_REF_CTRL       0x84
+#define R_CRL_CAN1_REF_CTRL       0x88
+#define R_CRL_CPU_R5_CTRL         0x90
+#define R_CRL_IOU_SWITCH_CTRL     0x9c
+#define R_CRL_CSU_PLL_CTRL        0xa0
+#define R_CRL_PCAP_CTRL           0xa4
+#define R_CRL_LPD_SWITCH_CTRL     0xa8
+#define R_CRL_LPD_LSBUS_CTRL      0xac
+#define R_CRL_DBG_LPD_CTRL        0xb0
+#define R_CRL_NAND_REF_CTRL       0xb4
+#define R_CRL_ADMA_REF_CTRL       0xb8
+#define R_CRL_PL0_REF_CTRL        0xc0
+#define R_CRL_PL1_REF_CTRL        0xc4
+#define R_CRL_PL2_REF_CTRL        0xc8
+#define R_CRL_PL3_REF_CTRL        0xcc
+#define R_CRL_PL0_THR_CTRL        0xd0
+#define R_CRL_PL0_THR_CNT         0xd4
+#define R_CRL_PL1_THR_CTRL        0xd8
+#define R_CRL_PL1_THR_CNT         0xdc
+#define R_CRL_PL2_THR_CTRL        0xe0
+#define R_CRL_PL2_THR_CNT         0xe4
+#define R_CRL_PL3_THR_CTRL        0xe8
+#define R_CRL_PL3_THR_CNT         0xfc
+#define R_CRL_GEM_TSU_REF_CTRL    0x100
+#define R_CRL_DLL_REF_CTRL        0x104
+#define R_CRL_AMS_REF_CTRL        0x108
+#define R_CRL_I2C0_REF_CTRL       0x120
+#define R_CRL_I2C1_REF_CTRL       0x124
+#define R_CRL_TIMESTAMP_REF_CTRL  0x128
+
+#define R_PMU_GLOBAL_GLOBAL_GEN_STORAGE0    0x30
+#define R_PMU_GLOBAL_PERS_GLOB_GEN_STORAGE7 0x6c
+
+#define R_PMU_GLOBAL_PWR_STATE              0x100
+
+#define R_CSU_IDCODE                        0x40
+
+#define R_IOU_SLCR_WDT_CLK_SEL            0x300
+#define R_IOU_SLCR_CAN_MIO_CTRL           0x304
+#define R_IOU_SLCR_GEM_CLK_CTRL           0x308
+#define R_IOU_SLCR_SDIO_CLK_CTRL          0x30c
+#define R_IOU_SLCR_CTRL_REG_SD	          0x310
+#define R_IOU_SLCR_SD_ITAPDLY	          0x314
+#define R_IOU_SLCR_SD_OTAPDLYSEL          0x318
+#define R_IOU_SLCR_SD_CONFIG_REG1         0x31c
+#define R_IOU_SLCR_SD_CONFIG_REG2         0x320
+#define R_IOU_SLCR_SD_CONFIG_REG3         0x324
+#define R_IOU_SLCR_SD_INITPRESET          0x328
+#define R_IOU_SLCR_SD_DSPPRESET	          0x32c
+#define R_IOU_SLCR_SD_HSPDPRESET          0x330
+#define R_IOU_SLCR_SD_SDR12PRESET         0x334
+#define R_IOU_SLCR_SD_SDR25PRESET         0x338
+#define R_IOU_SLCR_SD_SDR50PRSET          0x33c
+#define R_IOU_SLCR_SD_SDR104PRST          0x340
+#define R_IOU_SLCR_SD_DDR50PRESET         0x344
+#define R_IOU_SLCR_SD_MAXCUR1P8           0x34c
+#define R_IOU_SLCR_SD_MAXCUR3P0           0x350
+#define R_IOU_SLCR_SD_MAXCUR3P3           0x354
+#define R_IOU_SLCR_SD_DLL_CTRL            0x358
+#define R_IOU_SLCR_SD_CDN_CTRL            0x35c
+#define R_IOU_SLCR_GEM_CTRL               0x360
+#define R_IOU_SLCR_IOU_TTC_APB_CLK        0x380
+#define R_IOU_SLCR_IOU_TAPDLY_BYPASS      0x390
+#define R_IOU_SLCR_IOU_COHERENT_CTRL      0x400
+#define R_IOU_SLCR_VIDEO_PSS_CLK_SEL      0x404
+#define R_IOU_SLCR_IOU_INTERCONNECT_ROUTE 0x408
+#define R_IOU_SLCR_IOU_RAM_GEM0           0x500
+#define R_IOU_SLCR_IOU_RAM_GEM1           0x504
+#define R_IOU_SLCR_IOU_RAM_GEM2           0x508
+#define R_IOU_SLCR_IOU_RAM_GEM3           0x50c
+#define R_IOU_SLCR_IOU_RAM_SD0            0x510
+#define R_IOU_SLCR_IOU_RAM_SD1            0x514
+#define R_IOU_SLCR_IOU_RAM_CAN0           0x518
+#define R_IOU_SLCR_IOU_RAM_CAN1           0x51c
+#define R_IOU_SLCR_IOU_RAM_LQSPI          0x520
+#define R_IOU_SLCR_IOU_RAM_NAND           0x524
-- 
2.7.4


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

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

* [RFC v2 6/6] xen/arm: zynqmp: Remove blacklist of ZynqMP's PM node
  2017-02-07 19:41 [RFC v2 0/6] zynqmp: Add forwarding of platform specific firmware calls Edgar E. Iglesias
                   ` (4 preceding siblings ...)
  2017-02-07 19:42 ` [RFC v2 5/6] xen/arm: zynqmp: Forward plaform specific firmware calls Edgar E. Iglesias
@ 2017-02-07 19:42 ` Edgar E. Iglesias
  2017-02-14  0:03   ` Stefano Stabellini
  5 siblings, 1 reply; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-02-07 19:42 UTC (permalink / raw)
  To: xen-devel; +Cc: edgar.iglesias, julien.grall, sstabellini

From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>

Stop blacklisting ZynqMP's power management node.
This is now possible since we allow the hardware domain to
issue HVC/SMC calls to firmware.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
---
 xen/arch/arm/platforms/xilinx-zynqmp.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/xen/arch/arm/platforms/xilinx-zynqmp.c b/xen/arch/arm/platforms/xilinx-zynqmp.c
index d826282..a2128e2 100644
--- a/xen/arch/arm/platforms/xilinx-zynqmp.c
+++ b/xen/arch/arm/platforms/xilinx-zynqmp.c
@@ -26,13 +26,6 @@ static const char * const zynqmp_dt_compat[] __initconst =
     NULL
 };
 
-static const struct dt_device_match zynqmp_blacklist_dev[] __initconst =
-{
-    /* Power management is not yet supported.  */
-    DT_MATCH_COMPATIBLE("xlnx,zynqmp-pm"),
-    { /* sentinel */ },
-};
-
 bool zynqmp_hvc(struct cpu_user_regs *regs)
 {
     register_t ret[4] = { 0 };
@@ -52,7 +45,6 @@ bool zynqmp_hvc(struct cpu_user_regs *regs)
 PLATFORM_START(xgene_storm, "Xilinx ZynqMP")
     .compatible = zynqmp_dt_compat,
     .hvc = zynqmp_hvc,
-    .blacklist_dev = zynqmp_blacklist_dev,
 PLATFORM_END
 
 /*
-- 
2.7.4


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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-07 19:42 ` [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls Edgar E. Iglesias
@ 2017-02-07 20:38   ` Tamas K Lengyel
  2017-02-07 20:51     ` Julien Grall
  0 siblings, 1 reply; 44+ messages in thread
From: Tamas K Lengyel @ 2017-02-07 20:38 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: Edgar E. Iglesias, Julien Grall, Stefano Stabellini, Xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 1212 bytes --]

On Tue, Feb 7, 2017 at 12:42 PM, Edgar E. Iglesias <edgar.iglesias@gmail.com
> wrote:

> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
>
> Allow platform_hvc to handle guest SMC calls (as well as
> HVC calls) in a platform specific way.
>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> ---
>  xen/arch/arm/traps.c | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index 33950d9..1bedc6e 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -2623,6 +2623,11 @@ static void do_trap_smc(struct cpu_user_regs *regs,
> const union hsr hsr)
>      if ( current->domain->arch.monitor.privileged_call_enabled )
>          rc = monitor_smc();
>
>
I think you should check that rc is still 0 at this point as the vCPU might
already be paused and the event forwarded to a monitor subscriber.


> +    if ( platform_hvc(regs) ) {
> +        advance_pc(regs, hsr);
> +        rc = 1;
> +    }
> +
>      if ( rc != 1 )
>          inject_undef_exception(regs, hsr);
>  }
> --
> 2.7.4
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> https://lists.xen.org/xen-devel
>

[-- Attachment #1.2: Type: text/html, Size: 2122 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-07 20:38   ` Tamas K Lengyel
@ 2017-02-07 20:51     ` Julien Grall
  2017-02-08  0:24       ` Tamas K Lengyel
  0 siblings, 1 reply; 44+ messages in thread
From: Julien Grall @ 2017-02-07 20:51 UTC (permalink / raw)
  To: Tamas K Lengyel, Edgar E. Iglesias
  Cc: Edgar E. Iglesias, Stefano Stabellini, Xen-devel

Hi Tamas,

On 07/02/2017 20:38, Tamas K Lengyel wrote:
>
>
> On Tue, Feb 7, 2017 at 12:42 PM, Edgar E. Iglesias
> <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
>
>     From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com
>     <mailto:edgar.iglesias@xilinx.com>>
>
>     Allow platform_hvc to handle guest SMC calls (as well as
>     HVC calls) in a platform specific way.
>
>     Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com
>     <mailto:edgar.iglesias@xilinx.com>>
>     ---
>      xen/arch/arm/traps.c | 5 +++++
>      1 file changed, 5 insertions(+)
>
>     diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
>     index 33950d9..1bedc6e 100644
>     --- a/xen/arch/arm/traps.c
>     +++ b/xen/arch/arm/traps.c
>     @@ -2623,6 +2623,11 @@ static void do_trap_smc(struct cpu_user_regs
>     *regs, const union hsr hsr)
>          if ( current->domain->arch.monitor.privileged_call_enabled )
>              rc = monitor_smc();
>
>
> I think you should check that rc is still 0 at this point as the vCPU
> might already be paused and the event forwarded to a monitor subscriber.

SMC are used to access the secure firmware (e.g power management) and 
will be used by the guest to access the secure firmware. Today, the code 
is expecting all event to be trapped by the monitor app and software 
emulated. However, some SMCs may be needed to be forwarded to the secure 
firmware, how do you expect it to work together?

It is something I already brought up when SMC trap was added and it is 
probably time to figure out what to do because this will not be the 
first series bringing the problem. For instance if you want to do video 
decoding or even payment on Android you may need to access the secure 
firmware for cryptography. At the same time, you also want to be able to 
monitor your guest.

Cheers,

-- 
Julien Grall

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-07 20:51     ` Julien Grall
@ 2017-02-08  0:24       ` Tamas K Lengyel
  2017-02-08  8:31         ` Edgar E. Iglesias
  0 siblings, 1 reply; 44+ messages in thread
From: Tamas K Lengyel @ 2017-02-08  0:24 UTC (permalink / raw)
  To: Julien Grall
  Cc: Edgar E. Iglesias, Edgar E. Iglesias, Stefano Stabellini, Xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 2745 bytes --]

On Tue, Feb 7, 2017 at 1:51 PM, Julien Grall <julien.grall@arm.com> wrote:

> Hi Tamas,
>
> On 07/02/2017 20:38, Tamas K Lengyel wrote:
>
>>
>>
>> On Tue, Feb 7, 2017 at 12:42 PM, Edgar E. Iglesias
>> <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
>>
>>     From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com
>>     <mailto:edgar.iglesias@xilinx.com>>
>>
>>     Allow platform_hvc to handle guest SMC calls (as well as
>>     HVC calls) in a platform specific way.
>>
>>     Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com
>>     <mailto:edgar.iglesias@xilinx.com>>
>>     ---
>>      xen/arch/arm/traps.c | 5 +++++
>>      1 file changed, 5 insertions(+)
>>
>>     diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
>>     index 33950d9..1bedc6e 100644
>>     --- a/xen/arch/arm/traps.c
>>     +++ b/xen/arch/arm/traps.c
>>     @@ -2623,6 +2623,11 @@ static void do_trap_smc(struct cpu_user_regs
>>     *regs, const union hsr hsr)
>>          if ( current->domain->arch.monitor.privileged_call_enabled )
>>              rc = monitor_smc();
>>
>>
>> I think you should check that rc is still 0 at this point as the vCPU
>> might already be paused and the event forwarded to a monitor subscriber.
>>
>
> SMC are used to access the secure firmware (e.g power management) and will
> be used by the guest to access the secure firmware. Today, the code is
> expecting all event to be trapped by the monitor app and software emulated.
> However, some SMCs may be needed to be forwarded to the secure firmware,
> how do you expect it to work together?
>
> It is something I already brought up when SMC trap was added and it is
> probably time to figure out what to do because this will not be the first
> series bringing the problem. For instance if you want to do video decoding
> or even payment on Android you may need to access the secure firmware for
> cryptography. At the same time, you also want to be able to monitor your
> guest.
>


Hi Julien,
monitoring SMCs using the monitor system should be incompatible with Xen
routing the SMCs elsewhere. Since the monitor system is disabled by default
I think this should be fine for everyone and not get in the way of people
accessing the firmware in other usecases or routing SMCs elsewhere as
needed.

As for applications that want to use SMC monitoring but also access the
firmware, it can be accomplished by the monitor application on behalf of
the VM.  While this adds a detour, this detour is by design as it adds a
layer between untrusted VMs and the TZ so that any potential exploit
targeting the TZ would first have to go through the monitor application
(see https://www.sec.in.tum.de/publications/publication/322 for more info
on the idea).

Tamas

[-- Attachment #1.2: Type: text/html, Size: 4118 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-08  0:24       ` Tamas K Lengyel
@ 2017-02-08  8:31         ` Edgar E. Iglesias
  2017-02-08 16:40           ` Tamas K Lengyel
  0 siblings, 1 reply; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-02-08  8:31 UTC (permalink / raw)
  To: Tamas K Lengyel
  Cc: Edgar E. Iglesias, Julien Grall, Stefano Stabellini, Xen-devel

On Tue, Feb 07, 2017 at 05:24:03PM -0700, Tamas K Lengyel wrote:
> On Tue, Feb 7, 2017 at 1:51 PM, Julien Grall <julien.grall@arm.com> wrote:
> 
> > Hi Tamas,
> >
> > On 07/02/2017 20:38, Tamas K Lengyel wrote:
> >
> >>
> >>
> >> On Tue, Feb 7, 2017 at 12:42 PM, Edgar E. Iglesias
> >> <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
> >>
> >>     From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com
> >>     <mailto:edgar.iglesias@xilinx.com>>
> >>
> >>     Allow platform_hvc to handle guest SMC calls (as well as
> >>     HVC calls) in a platform specific way.
> >>
> >>     Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com
> >>     <mailto:edgar.iglesias@xilinx.com>>
> >>     ---
> >>      xen/arch/arm/traps.c | 5 +++++
> >>      1 file changed, 5 insertions(+)
> >>
> >>     diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> >>     index 33950d9..1bedc6e 100644
> >>     --- a/xen/arch/arm/traps.c
> >>     +++ b/xen/arch/arm/traps.c
> >>     @@ -2623,6 +2623,11 @@ static void do_trap_smc(struct cpu_user_regs
> >>     *regs, const union hsr hsr)
> >>          if ( current->domain->arch.monitor.privileged_call_enabled )
> >>              rc = monitor_smc();
> >>
> >>
> >> I think you should check that rc is still 0 at this point as the vCPU
> >> might already be paused and the event forwarded to a monitor subscriber.
> >>
> >
> > SMC are used to access the secure firmware (e.g power management) and will
> > be used by the guest to access the secure firmware. Today, the code is
> > expecting all event to be trapped by the monitor app and software emulated.
> > However, some SMCs may be needed to be forwarded to the secure firmware,
> > how do you expect it to work together?
> >
> > It is something I already brought up when SMC trap was added and it is
> > probably time to figure out what to do because this will not be the first
> > series bringing the problem. For instance if you want to do video decoding
> > or even payment on Android you may need to access the secure firmware for
> > cryptography. At the same time, you also want to be able to monitor your
> > guest.
> >
> 
> 
> Hi Julien,
> monitoring SMCs using the monitor system should be incompatible with Xen
> routing the SMCs elsewhere. Since the monitor system is disabled by default
> I think this should be fine for everyone and not get in the way of people
> accessing the firmware in other usecases or routing SMCs elsewhere as
> needed.
> 
> As for applications that want to use SMC monitoring but also access the
> firmware, it can be accomplished by the monitor application on behalf of
> the VM.  While this adds a detour, this detour is by design as it adds a
> layer between untrusted VMs and the TZ so that any potential exploit
> targeting the TZ would first have to go through the monitor application
> (see https://www.sec.in.tum.de/publications/publication/322 for more info
> on the idea).

I considered this approach a bit but it has several problems IMO.
These may not be unsolvable or even problems for monitoring but
they do introduce complexity into the solution.

1. Some SMC calls may depend on the core they are issued from.
   If taking a detour to dom0, this becomes messy to guarantee.

2. Overall complexity increases very significantly and it becomes
   quite hard to follow/review how these calls get handled.
   In particular once you consider solving #1.

3. There are certain calls that perhaps not even dom0 should have
   direct access to. This means that Xen may need to filter some of
   them anyway.

Some examples may be:

SMC calls:
* To directly turn off or suspend cores
* To turn off DDR or RAMs that Xen is using
* To a solution specific Trusted OS pinned to a specific core
* For PSCI
* Etc

I would prefer if we could find a way for monitoring to play nicely
with Xen implementing the SMC mediators.
Perhaps we could allow calls that Xen consumes to be monitored/inspected
but not modified. Or there might be other ways.

Best regards,
Edgar

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-08  8:31         ` Edgar E. Iglesias
@ 2017-02-08 16:40           ` Tamas K Lengyel
  2017-02-08 16:58             ` Julien Grall
  0 siblings, 1 reply; 44+ messages in thread
From: Tamas K Lengyel @ 2017-02-08 16:40 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: Edgar E. Iglesias, Julien Grall, Stefano Stabellini, Xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 5236 bytes --]

On Wed, Feb 8, 2017 at 1:31 AM, Edgar E. Iglesias <edgar.iglesias@xilinx.com
> wrote:

> On Tue, Feb 07, 2017 at 05:24:03PM -0700, Tamas K Lengyel wrote:
> > On Tue, Feb 7, 2017 at 1:51 PM, Julien Grall <julien.grall@arm.com>
> wrote:
> >
> > > Hi Tamas,
> > >
> > > On 07/02/2017 20:38, Tamas K Lengyel wrote:
> > >
> > >>
> > >>
> > >> On Tue, Feb 7, 2017 at 12:42 PM, Edgar E. Iglesias
> > >> <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
> > >>
> > >>     From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com
> > >>     <mailto:edgar.iglesias@xilinx.com>>
> > >>
> > >>     Allow platform_hvc to handle guest SMC calls (as well as
> > >>     HVC calls) in a platform specific way.
> > >>
> > >>     Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com
> > >>     <mailto:edgar.iglesias@xilinx.com>>
> > >>     ---
> > >>      xen/arch/arm/traps.c | 5 +++++
> > >>      1 file changed, 5 insertions(+)
> > >>
> > >>     diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> > >>     index 33950d9..1bedc6e 100644
> > >>     --- a/xen/arch/arm/traps.c
> > >>     +++ b/xen/arch/arm/traps.c
> > >>     @@ -2623,6 +2623,11 @@ static void do_trap_smc(struct
> cpu_user_regs
> > >>     *regs, const union hsr hsr)
> > >>          if ( current->domain->arch.monitor.privileged_call_enabled )
> > >>              rc = monitor_smc();
> > >>
> > >>
> > >> I think you should check that rc is still 0 at this point as the vCPU
> > >> might already be paused and the event forwarded to a monitor
> subscriber.
> > >>
> > >
> > > SMC are used to access the secure firmware (e.g power management) and
> will
> > > be used by the guest to access the secure firmware. Today, the code is
> > > expecting all event to be trapped by the monitor app and software
> emulated.
> > > However, some SMCs may be needed to be forwarded to the secure
> firmware,
> > > how do you expect it to work together?
> > >
> > > It is something I already brought up when SMC trap was added and it is
> > > probably time to figure out what to do because this will not be the
> first
> > > series bringing the problem. For instance if you want to do video
> decoding
> > > or even payment on Android you may need to access the secure firmware
> for
> > > cryptography. At the same time, you also want to be able to monitor
> your
> > > guest.
> > >
> >
> >
> > Hi Julien,
> > monitoring SMCs using the monitor system should be incompatible with Xen
> > routing the SMCs elsewhere. Since the monitor system is disabled by
> default
> > I think this should be fine for everyone and not get in the way of people
> > accessing the firmware in other usecases or routing SMCs elsewhere as
> > needed.
> >
> > As for applications that want to use SMC monitoring but also access the
> > firmware, it can be accomplished by the monitor application on behalf of
> > the VM.  While this adds a detour, this detour is by design as it adds a
> > layer between untrusted VMs and the TZ so that any potential exploit
> > targeting the TZ would first have to go through the monitor application
> > (see https://www.sec.in.tum.de/publications/publication/322 for more
> info
> > on the idea).
>
> I considered this approach a bit but it has several problems IMO.
> These may not be unsolvable or even problems for monitoring but
> they do introduce complexity into the solution.
>
> 1. Some SMC calls may depend on the core they are issued from.
>    If taking a detour to dom0, this becomes messy to guarantee.
>
> 2. Overall complexity increases very significantly and it becomes
>    quite hard to follow/review how these calls get handled.
>    In particular once you consider solving #1.
>
> 3. There are certain calls that perhaps not even dom0 should have
>    direct access to. This means that Xen may need to filter some of
>    them anyway.
>
> Some examples may be:
>
> SMC calls:
> * To directly turn off or suspend cores
> * To turn off DDR or RAMs that Xen is using
> * To a solution specific Trusted OS pinned to a specific core
> * For PSCI
> * Etc
>
> I would prefer if we could find a way for monitoring to play nicely
> with Xen implementing the SMC mediators.
> Perhaps we could allow calls that Xen consumes to be monitored/inspected
> but not modified. Or there might be other ways.
>
> Best regards,
> Edgar
>

Hi Edgar,
certainly there are many cases where the system would become very complex
when there is functionality like what you describe in the TZ that needs to
be made accessible via SMC. The setup I described is experimental only, and
the underlying assumption is that the TZ is working jointly with the
monitor application (ie. both are aware of each other). So it is really not
intended to work with just any firmware.

So I think for the sake of reducing complexity, having the monitor system
be exclusive when enabled should make everyone's life simpler. Having a
passive monitoring mode as you suggest is certainly an option, although it
should not be the only option, exclusive routing of SMCs through monitor
applications should still be available to be configured by the user. Since
I really don't know of any usecases where passive monitoring of SMCs is
required, I don't think we should go that route.

Tamas

[-- Attachment #1.2: Type: text/html, Size: 7090 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-08 16:40           ` Tamas K Lengyel
@ 2017-02-08 16:58             ` Julien Grall
  2017-02-08 17:21               ` Tamas K Lengyel
  2017-02-08 17:29               ` Edgar E. Iglesias
  0 siblings, 2 replies; 44+ messages in thread
From: Julien Grall @ 2017-02-08 16:58 UTC (permalink / raw)
  To: Tamas K Lengyel, Edgar E. Iglesias
  Cc: Volodymyr Babchuk, Edgar E. Iglesias, Stefano Stabellini, Xen-devel

Hi Tamas,

On 08/02/17 16:40, Tamas K Lengyel wrote:
> On Wed, Feb 8, 2017 at 1:31 AM, Edgar E. Iglesias
> <edgar.iglesias@xilinx.com <mailto:edgar.iglesias@xilinx.com>> wrote:
>     On Tue, Feb 07, 2017 at 05:24:03PM -0700, Tamas K Lengyel wrote:
>     > On Tue, Feb 7, 2017 at 1:51 PM, Julien Grall <julien.grall@arm.com
>     <mailto:julien.grall@arm.com>> wrote:
>     I considered this approach a bit but it has several problems IMO.
>     These may not be unsolvable or even problems for monitoring but
>     they do introduce complexity into the solution.
>
>     1. Some SMC calls may depend on the core they are issued from.
>        If taking a detour to dom0, this becomes messy to guarantee.
>
>     2. Overall complexity increases very significantly and it becomes
>        quite hard to follow/review how these calls get handled.
>        In particular once you consider solving #1.
>
>     3. There are certain calls that perhaps not even dom0 should have
>        direct access to. This means that Xen may need to filter some of
>        them anyway.
>
>     Some examples may be:
>
>     SMC calls:
>     * To directly turn off or suspend cores
>     * To turn off DDR or RAMs that Xen is using
>     * To a solution specific Trusted OS pinned to a specific core
>     * For PSCI
>     * Etc
>
>     I would prefer if we could find a way for monitoring to play nicely
>     with Xen implementing the SMC mediators.
>     Perhaps we could allow calls that Xen consumes to be monitored/inspected
>     but not modified. Or there might be other ways.
>
>     Best regards,
>     Edgar
>
>
> Hi Edgar,
> certainly there are many cases where the system would become very
> complex when there is functionality like what you describe in the TZ
> that needs to be made accessible via SMC. The setup I described is
> experimental only, and the underlying assumption is that the TZ is
> working jointly with the monitor application (ie. both are aware of each
> other). So it is really not intended to work with just any firmware.

How do you expect TrustZone to work with the monitor application? If you 
think about modifying Trustzone, it seems a requirement difficult to 
achieve as some Trusted OS are proprietary or difficult to replace on a 
phone.

>
> So I think for the sake of reducing complexity, having the monitor
> system be exclusive when enabled should make everyone's life simpler.
> Having a passive monitoring mode as you suggest is certainly an option,
> although it should not be the only option, exclusive routing of SMCs
> through monitor applications should still be available to be configured
> by the user. Since I really don't know of any usecases where passive
> monitoring of SMCs is required, I don't think we should go that route.

I see the SMC trap similar to a register trap. The monitor app will look 
at the register value and potentially modify it. What would be the issue 
to do the same for SMC?

I think a such model would fit the requirement for everyone. The monitor 
app can filter if necessary, and Xen would handle the mediation between 
multiple guests. I would also recommend to read the thread about OP-TEE 
support in Xen (see [1]).

Cheers,

[1] 
https://lists.xenproject.org/archives/html/xen-devel/2016-11/msg02220.html

-- 
Julien Grall

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-08 16:58             ` Julien Grall
@ 2017-02-08 17:21               ` Tamas K Lengyel
  2017-02-08 17:29               ` Edgar E. Iglesias
  1 sibling, 0 replies; 44+ messages in thread
From: Tamas K Lengyel @ 2017-02-08 17:21 UTC (permalink / raw)
  To: Julien Grall
  Cc: Edgar E. Iglesias, Edgar E. Iglesias, Stefano Stabellini,
	Volodymyr Babchuk, Xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 4523 bytes --]

On Wed, Feb 8, 2017 at 9:58 AM, Julien Grall <julien.grall@arm.com> wrote:

> Hi Tamas,
>
> On 08/02/17 16:40, Tamas K Lengyel wrote:
>
>> On Wed, Feb 8, 2017 at 1:31 AM, Edgar E. Iglesias
>> <edgar.iglesias@xilinx.com <mailto:edgar.iglesias@xilinx.com>> wrote:
>>     On Tue, Feb 07, 2017 at 05:24:03PM -0700, Tamas K Lengyel wrote:
>>     > On Tue, Feb 7, 2017 at 1:51 PM, Julien Grall <julien.grall@arm.com
>>     <mailto:julien.grall@arm.com>> wrote:
>>     I considered this approach a bit but it has several problems IMO.
>>     These may not be unsolvable or even problems for monitoring but
>>     they do introduce complexity into the solution.
>>
>>     1. Some SMC calls may depend on the core they are issued from.
>>        If taking a detour to dom0, this becomes messy to guarantee.
>>
>>     2. Overall complexity increases very significantly and it becomes
>>        quite hard to follow/review how these calls get handled.
>>        In particular once you consider solving #1.
>>
>>     3. There are certain calls that perhaps not even dom0 should have
>>        direct access to. This means that Xen may need to filter some of
>>        them anyway.
>>
>>     Some examples may be:
>>
>>     SMC calls:
>>     * To directly turn off or suspend cores
>>     * To turn off DDR or RAMs that Xen is using
>>     * To a solution specific Trusted OS pinned to a specific core
>>     * For PSCI
>>     * Etc
>>
>>     I would prefer if we could find a way for monitoring to play nicely
>>     with Xen implementing the SMC mediators.
>>     Perhaps we could allow calls that Xen consumes to be
>> monitored/inspected
>>     but not modified. Or there might be other ways.
>>
>>     Best regards,
>>     Edgar
>>
>>
>> Hi Edgar,
>> certainly there are many cases where the system would become very
>> complex when there is functionality like what you describe in the TZ
>> that needs to be made accessible via SMC. The setup I described is
>> experimental only, and the underlying assumption is that the TZ is
>> working jointly with the monitor application (ie. both are aware of each
>> other). So it is really not intended to work with just any firmware.
>>
>
> How do you expect TrustZone to work with the monitor application? If you
> think about modifying Trustzone, it seems a requirement difficult to
> achieve as some Trusted OS are proprietary or difficult to replace on a
> phone.
>

It is not intended to work with just any TrustZone. In the proposed system
the TZ is specifically designed to minimize the codebase that is running at
that privilege level. We mostly envisioned critical integrity and security
checks to be in the TZ while all "normal" TZ applications would be
delegated to VMs - still protected from the untrusted guest, but a
potential exploit would just land the attacker in another VM rather then
the TZ. At the moment it is just an experimental setup, so I don't expect
it to be a drop-in solution for off-the-shelf phones in the near future.


>
>
>> So I think for the sake of reducing complexity, having the monitor
>> system be exclusive when enabled should make everyone's life simpler.
>> Having a passive monitoring mode as you suggest is certainly an option,
>> although it should not be the only option, exclusive routing of SMCs
>> through monitor applications should still be available to be configured
>> by the user. Since I really don't know of any usecases where passive
>> monitoring of SMCs is required, I don't think we should go that route.
>>
>
> I see the SMC trap similar to a register trap. The monitor app will look
> at the register value and potentially modify it. What would be the issue to
> do the same for SMC?
>

I don't see an issue with the monitor application modifying register values
on a trapped SMC. The issue I have is if the SMC is still forwarded to the
firmware by Xen afterwards. In the usecase I described the firmware should
under no situation be accessible from an untrusted guest directly.


>
> I think a such model would fit the requirement for everyone. The monitor
> app can filter if necessary, and Xen would handle the mediation between
> multiple guests. I would also recommend to read the thread about OP-TEE
> support in Xen (see [1]).
>

Just modifying registers would not really accomplish filtering. We could
introduce a vm_event response flag so the monitor application would be able
to tell Xen whether it's OK to forward the SMC to the firmware or not. That
is an option, even if I don't have a usecase for it.

Tamas

[-- Attachment #1.2: Type: text/html, Size: 6104 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-08 16:58             ` Julien Grall
  2017-02-08 17:21               ` Tamas K Lengyel
@ 2017-02-08 17:29               ` Edgar E. Iglesias
  2017-02-08 19:40                 ` Edgar E. Iglesias
  1 sibling, 1 reply; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-02-08 17:29 UTC (permalink / raw)
  To: Julien Grall
  Cc: Edgar E. Iglesias, Tamas K Lengyel, Stefano Stabellini,
	Volodymyr Babchuk, Xen-devel

On Wed, Feb 08, 2017 at 04:58:44PM +0000, Julien Grall wrote:
> Hi Tamas,
> 
> On 08/02/17 16:40, Tamas K Lengyel wrote:
> >On Wed, Feb 8, 2017 at 1:31 AM, Edgar E. Iglesias
> ><edgar.iglesias@xilinx.com <mailto:edgar.iglesias@xilinx.com>> wrote:
> >    On Tue, Feb 07, 2017 at 05:24:03PM -0700, Tamas K Lengyel wrote:
> >    > On Tue, Feb 7, 2017 at 1:51 PM, Julien Grall <julien.grall@arm.com
> >    <mailto:julien.grall@arm.com>> wrote:
> >    I considered this approach a bit but it has several problems IMO.
> >    These may not be unsolvable or even problems for monitoring but
> >    they do introduce complexity into the solution.
> >
> >    1. Some SMC calls may depend on the core they are issued from.
> >       If taking a detour to dom0, this becomes messy to guarantee.
> >
> >    2. Overall complexity increases very significantly and it becomes
> >       quite hard to follow/review how these calls get handled.
> >       In particular once you consider solving #1.
> >
> >    3. There are certain calls that perhaps not even dom0 should have
> >       direct access to. This means that Xen may need to filter some of
> >       them anyway.
> >
> >    Some examples may be:
> >
> >    SMC calls:
> >    * To directly turn off or suspend cores
> >    * To turn off DDR or RAMs that Xen is using
> >    * To a solution specific Trusted OS pinned to a specific core
> >    * For PSCI
> >    * Etc
> >
> >    I would prefer if we could find a way for monitoring to play nicely
> >    with Xen implementing the SMC mediators.
> >    Perhaps we could allow calls that Xen consumes to be monitored/inspected
> >    but not modified. Or there might be other ways.
> >
> >    Best regards,
> >    Edgar
> >
> >
> >Hi Edgar,
> >certainly there are many cases where the system would become very
> >complex when there is functionality like what you describe in the TZ
> >that needs to be made accessible via SMC. The setup I described is
> >experimental only, and the underlying assumption is that the TZ is
> >working jointly with the monitor application (ie. both are aware of each
> >other). So it is really not intended to work with just any firmware.
> 
> How do you expect TrustZone to work with the monitor application? If you
> think about modifying Trustzone, it seems a requirement difficult to achieve
> as some Trusted OS are proprietary or difficult to replace on a phone.
> 
> >
> >So I think for the sake of reducing complexity, having the monitor
> >system be exclusive when enabled should make everyone's life simpler.
> >Having a passive monitoring mode as you suggest is certainly an option,
> >although it should not be the only option, exclusive routing of SMCs
> >through monitor applications should still be available to be configured
> >by the user. Since I really don't know of any usecases where passive
> >monitoring of SMCs is required, I don't think we should go that route.
> 
> I see the SMC trap similar to a register trap. The monitor app will look at
> the register value and potentially modify it. What would be the issue to do
> the same for SMC?

Yes, I think this would work if we can keep the SMC processing on the same
core (after it's been accepted by monitor filters). If not accepted by
filters, we'd just ignore the SMC processing and return registers provided
by the monitor (or something along those lines).


> I think a such model would fit the requirement for everyone. The monitor app
> can filter if necessary, and Xen would handle the mediation between multiple
> guests. I would also recommend to read the thread about OP-TEE support in
> Xen (see [1]).
>

We have a similar issue with interrupts from Firmware. I've not implemented
this part in this series but at some point I'm going to have to.

Essentially I'm looking at handling an IPI in Xen and forwarding an SGI or
a virtual inject of the IPI to the guest that was targeted. Future work...

Cheers,
Edgar

> Cheers,
> 
> [1]
> https://lists.xenproject.org/archives/html/xen-devel/2016-11/msg02220.html
> 
> -- 
> Julien Grall

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-08 17:29               ` Edgar E. Iglesias
@ 2017-02-08 19:40                 ` Edgar E. Iglesias
  2017-02-08 20:15                   ` Tamas K Lengyel
  0 siblings, 1 reply; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-02-08 19:40 UTC (permalink / raw)
  To: Julien Grall
  Cc: Edgar E. Iglesias, Tamas K Lengyel, Stefano Stabellini,
	Volodymyr Babchuk, Xen-devel

On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:
> On Wed, Feb 08, 2017 at 04:58:44PM +0000, Julien Grall wrote:
> > Hi Tamas,
> > 
> > On 08/02/17 16:40, Tamas K Lengyel wrote:
> > >On Wed, Feb 8, 2017 at 1:31 AM, Edgar E. Iglesias
> > ><edgar.iglesias@xilinx.com <mailto:edgar.iglesias@xilinx.com>> wrote:
> > >    On Tue, Feb 07, 2017 at 05:24:03PM -0700, Tamas K Lengyel wrote:
> > >    > On Tue, Feb 7, 2017 at 1:51 PM, Julien Grall <julien.grall@arm.com
> > >    <mailto:julien.grall@arm.com>> wrote:
> > >    I considered this approach a bit but it has several problems IMO.
> > >    These may not be unsolvable or even problems for monitoring but
> > >    they do introduce complexity into the solution.
> > >
> > >    1. Some SMC calls may depend on the core they are issued from.
> > >       If taking a detour to dom0, this becomes messy to guarantee.
> > >
> > >    2. Overall complexity increases very significantly and it becomes
> > >       quite hard to follow/review how these calls get handled.
> > >       In particular once you consider solving #1.
> > >
> > >    3. There are certain calls that perhaps not even dom0 should have
> > >       direct access to. This means that Xen may need to filter some of
> > >       them anyway.
> > >
> > >    Some examples may be:
> > >
> > >    SMC calls:
> > >    * To directly turn off or suspend cores
> > >    * To turn off DDR or RAMs that Xen is using
> > >    * To a solution specific Trusted OS pinned to a specific core
> > >    * For PSCI
> > >    * Etc
> > >
> > >    I would prefer if we could find a way for monitoring to play nicely
> > >    with Xen implementing the SMC mediators.
> > >    Perhaps we could allow calls that Xen consumes to be monitored/inspected
> > >    but not modified. Or there might be other ways.
> > >
> > >    Best regards,
> > >    Edgar
> > >
> > >
> > >Hi Edgar,
> > >certainly there are many cases where the system would become very
> > >complex when there is functionality like what you describe in the TZ
> > >that needs to be made accessible via SMC. The setup I described is
> > >experimental only, and the underlying assumption is that the TZ is
> > >working jointly with the monitor application (ie. both are aware of each
> > >other). So it is really not intended to work with just any firmware.
> > 
> > How do you expect TrustZone to work with the monitor application? If you
> > think about modifying Trustzone, it seems a requirement difficult to achieve
> > as some Trusted OS are proprietary or difficult to replace on a phone.
> > 
> > >
> > >So I think for the sake of reducing complexity, having the monitor
> > >system be exclusive when enabled should make everyone's life simpler.
> > >Having a passive monitoring mode as you suggest is certainly an option,
> > >although it should not be the only option, exclusive routing of SMCs
> > >through monitor applications should still be available to be configured
> > >by the user. Since I really don't know of any usecases where passive
> > >monitoring of SMCs is required, I don't think we should go that route.
> > 
> > I see the SMC trap similar to a register trap. The monitor app will look at
> > the register value and potentially modify it. What would be the issue to do
> > the same for SMC?
> 
> Yes, I think this would work if we can keep the SMC processing on the same
> core (after it's been accepted by monitor filters). If not accepted by
> filters, we'd just ignore the SMC processing and return registers provided
> by the monitor (or something along those lines).
> 
> 
> > I think a such model would fit the requirement for everyone. The monitor app
> > can filter if necessary, and Xen would handle the mediation between multiple

Any ideas on how we can support monitor filtering while at the same time
having Xen processing calls? How do we wait for a response from the monitor
and then (if allowed) issue the SMC from the right core?

Or we could make these approaches mutually exclusive.
If platform_hvc() consumes an SMC, it's considered part of the Xen API.
Visible but not filterable by a monitor.

Platforms can then dictate which SMC calls are better handled within Xen and
which ones can be exposed to dom0 user-space.

In addition, there could be a hypercall to disable platform specific handling
in Xen alltogether for a given guest. Then everything goes to dom0 user-space.

It's a little messy...


> > guests. I would also recommend to read the thread about OP-TEE support in
> > Xen (see [1]).
> >

BTW, my comment below was regarding the interrupts discussion in the OP-TEE
thread, in case it seemed totally off-topic :-)

> 
> We have a similar issue with interrupts from Firmware. I've not implemented
> this part in this series but at some point I'm going to have to.
> 
> Essentially I'm looking at handling an IPI in Xen and forwarding an SGI or
> a virtual inject of the IPI to the guest that was targeted. Future work...
> 
> Cheers,
> Edgar
> 
> > Cheers,
> > 
> > [1]
> > https://lists.xenproject.org/archives/html/xen-devel/2016-11/msg02220.html
> > 
> > -- 
> > Julien Grall

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-08 19:40                 ` Edgar E. Iglesias
@ 2017-02-08 20:15                   ` Tamas K Lengyel
  2017-02-08 22:04                     ` Julien Grall
  0 siblings, 1 reply; 44+ messages in thread
From: Tamas K Lengyel @ 2017-02-08 20:15 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: Edgar E. Iglesias, Volodymyr Babchuk, Julien Grall,
	Stefano Stabellini, Xen-devel


[-- Attachment #1.1: Type: text/plain, Size: 5595 bytes --]

On Wed, Feb 8, 2017 at 12:40 PM, Edgar E. Iglesias <edgar.iglesias@gmail.com
> wrote:

> On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:
> > On Wed, Feb 08, 2017 at 04:58:44PM +0000, Julien Grall wrote:
> > > Hi Tamas,
> > >
> > > On 08/02/17 16:40, Tamas K Lengyel wrote:
> > > >On Wed, Feb 8, 2017 at 1:31 AM, Edgar E. Iglesias
> > > ><edgar.iglesias@xilinx.com <mailto:edgar.iglesias@xilinx.com>> wrote:
> > > >    On Tue, Feb 07, 2017 at 05:24:03PM -0700, Tamas K Lengyel wrote:
> > > >    > On Tue, Feb 7, 2017 at 1:51 PM, Julien Grall <
> julien.grall@arm.com
> > > >    <mailto:julien.grall@arm.com>> wrote:
> > > >    I considered this approach a bit but it has several problems IMO.
> > > >    These may not be unsolvable or even problems for monitoring but
> > > >    they do introduce complexity into the solution.
> > > >
> > > >    1. Some SMC calls may depend on the core they are issued from.
> > > >       If taking a detour to dom0, this becomes messy to guarantee.
> > > >
> > > >    2. Overall complexity increases very significantly and it becomes
> > > >       quite hard to follow/review how these calls get handled.
> > > >       In particular once you consider solving #1.
> > > >
> > > >    3. There are certain calls that perhaps not even dom0 should have
> > > >       direct access to. This means that Xen may need to filter some
> of
> > > >       them anyway.
> > > >
> > > >    Some examples may be:
> > > >
> > > >    SMC calls:
> > > >    * To directly turn off or suspend cores
> > > >    * To turn off DDR or RAMs that Xen is using
> > > >    * To a solution specific Trusted OS pinned to a specific core
> > > >    * For PSCI
> > > >    * Etc
> > > >
> > > >    I would prefer if we could find a way for monitoring to play
> nicely
> > > >    with Xen implementing the SMC mediators.
> > > >    Perhaps we could allow calls that Xen consumes to be
> monitored/inspected
> > > >    but not modified. Or there might be other ways.
> > > >
> > > >    Best regards,
> > > >    Edgar
> > > >
> > > >
> > > >Hi Edgar,
> > > >certainly there are many cases where the system would become very
> > > >complex when there is functionality like what you describe in the TZ
> > > >that needs to be made accessible via SMC. The setup I described is
> > > >experimental only, and the underlying assumption is that the TZ is
> > > >working jointly with the monitor application (ie. both are aware of
> each
> > > >other). So it is really not intended to work with just any firmware.
> > >
> > > How do you expect TrustZone to work with the monitor application? If
> you
> > > think about modifying Trustzone, it seems a requirement difficult to
> achieve
> > > as some Trusted OS are proprietary or difficult to replace on a phone.
> > >
> > > >
> > > >So I think for the sake of reducing complexity, having the monitor
> > > >system be exclusive when enabled should make everyone's life simpler.
> > > >Having a passive monitoring mode as you suggest is certainly an
> option,
> > > >although it should not be the only option, exclusive routing of SMCs
> > > >through monitor applications should still be available to be
> configured
> > > >by the user. Since I really don't know of any usecases where passive
> > > >monitoring of SMCs is required, I don't think we should go that route.
> > >
> > > I see the SMC trap similar to a register trap. The monitor app will
> look at
> > > the register value and potentially modify it. What would be the issue
> to do
> > > the same for SMC?
> >
> > Yes, I think this would work if we can keep the SMC processing on the
> same
> > core (after it's been accepted by monitor filters). If not accepted by
> > filters, we'd just ignore the SMC processing and return registers
> provided
> > by the monitor (or something along those lines).
> >
> >
> > > I think a such model would fit the requirement for everyone. The
> monitor app
> > > can filter if necessary, and Xen would handle the mediation between
> multiple
>
> Any ideas on how we can support monitor filtering while at the same time
> having Xen processing calls? How do we wait for a response from the monitor
> and then (if allowed) issue the SMC from the right core?
>

There is a return path from the monitor application when the monitor
request has been processed. See
http://xenbits.xenproject.org/gitweb/?p=xen.git;a=blob;f=xen/common/vm_event.c;h=82ce8f1561384f6059c5ea152e3b0a55e63094a8;hb=HEAD#l402.
We can do a call-down to an ARM specific handler that would then issue the
SMC to the firmware if the monitor app specified that it is OK to do so. It
is relatively easily to implement but I don't think it's a feature that
anyone needs at the moment.


>
> Or we could make these approaches mutually exclusive.
>

That is what I would like to see.


> If platform_hvc() consumes an SMC, it's considered part of the Xen API.
> Visible but not filterable by a monitor.
>

> Platforms can then dictate which SMC calls are better handled within Xen
> and
> which ones can be exposed to dom0 user-space.
>
> In addition, there could be a hypercall to disable platform specific
> handling
> in Xen alltogether for a given guest. Then everything goes to dom0
> user-space.
>
> It's a little messy...
>


That is messy and I would not want any SMCs reaching the firmware when the
monitor application is in use. The monitor interface is disabled by default
and there aren't any known usecases where the SMC has to reach both the
firmware and the monitor application as well. So I think it is safe to just
make the two things mutually exclusive.

Tamas

[-- Attachment #1.2: Type: text/html, Size: 7793 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-08 20:15                   ` Tamas K Lengyel
@ 2017-02-08 22:04                     ` Julien Grall
  2017-02-08 23:28                       ` Tamas K Lengyel
  2017-02-09 14:46                       ` Edgar E. Iglesias
  0 siblings, 2 replies; 44+ messages in thread
From: Julien Grall @ 2017-02-08 22:04 UTC (permalink / raw)
  To: Tamas K Lengyel, Edgar E. Iglesias
  Cc: Edgar E. Iglesias, Volodymyr Babchuk, Stefano Stabellini, Xen-devel

Hi Tamas,

Can you please try to configure your e-mail client to use '>' rather 
than '    '? It makes quite hard to read the e-mail.

On 08/02/2017 20:15, Tamas K Lengyel wrote:
>
>
> On Wed, Feb 8, 2017 at 12:40 PM, Edgar E. Iglesias
> <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
>     On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:

>     If platform_hvc() consumes an SMC, it's considered part of the Xen API.
>     Visible but not filterable by a monitor.
>
>
>     Platforms can then dictate which SMC calls are better handled within
>     Xen and
>     which ones can be exposed to dom0 user-space.
>
>     In addition, there could be a hypercall to disable platform specific
>     handling
>     in Xen alltogether for a given guest. Then everything goes to dom0
>     user-space.
>
>     It's a little messy...
>
>
>
> That is messy and I would not want any SMCs reaching the firmware when
> the monitor application is in use. The monitor interface is disabled by
> default and there aren't any known usecases where the SMC has to reach
> both the firmware and the monitor application as well. So I think it is
> safe to just make the two things mutually exclusive.

If you look at the SMC Calling Convention [1] both HVC and SMC are 
considered a conduit for service call to the secure firmware or 
hypervisor. It would be up to the hypervisor deciding what to do.

Lets imagine the guest is deciding to use HVC to access the secure 
firmware (AFAIU this patch series is adding that), are you going to 
monitor all the HVCs (including hypercall)?

Similarly, non-modified baremetal app could use SMC to power on/off the 
vCPU (see PSCI spec). Will you emulate that in the monitor app?

So I think we need to be consistent across HVC and SMC call. And 
mutually exclusive does not sound right to me for HVC.

Cheers,

[1] 
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0028b/index.html


-- 
Julien Grall

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-08 22:04                     ` Julien Grall
@ 2017-02-08 23:28                       ` Tamas K Lengyel
  2017-02-09  0:08                         ` Julien Grall
  2017-02-09 14:46                       ` Edgar E. Iglesias
  1 sibling, 1 reply; 44+ messages in thread
From: Tamas K Lengyel @ 2017-02-08 23:28 UTC (permalink / raw)
  To: Julien Grall
  Cc: Edgar E. Iglesias, Edgar E. Iglesias, Stefano Stabellini,
	Volodymyr Babchuk, Xen-devel

On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
> Hi Tamas,
>
> Can you please try to configure your e-mail client to use '>' rather than '
> '? It makes quite hard to read the e-mail.

Hm, not sure why it switched but should be fine now.

> On 08/02/2017 20:15, Tamas K Lengyel wrote:
>>
>>
>>
>> On Wed, Feb 8, 2017 at 12:40 PM, Edgar E. Iglesias
>> <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
>>     On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:
>
>
>>     If platform_hvc() consumes an SMC, it's considered part of the Xen
>> API.
>>     Visible but not filterable by a monitor.
>>
>>
>>     Platforms can then dictate which SMC calls are better handled within
>>     Xen and
>>     which ones can be exposed to dom0 user-space.
>>
>>     In addition, there could be a hypercall to disable platform specific
>>     handling
>>     in Xen alltogether for a given guest. Then everything goes to dom0
>>     user-space.
>>
>>     It's a little messy...
>>
>>
>>
>> That is messy and I would not want any SMCs reaching the firmware when
>> the monitor application is in use. The monitor interface is disabled by
>> default and there aren't any known usecases where the SMC has to reach
>> both the firmware and the monitor application as well. So I think it is
>> safe to just make the two things mutually exclusive.
>
>
> If you look at the SMC Calling Convention [1] both HVC and SMC are
> considered a conduit for service call to the secure firmware or hypervisor.
> It would be up to the hypervisor deciding what to do.
>
> Lets imagine the guest is deciding to use HVC to access the secure firmware
> (AFAIU this patch series is adding that), are you going to monitor all the
> HVCs (including hypercall)?

There are some fundamental differences between HVC and SMC calls
though. An HVC can only land in the hypervisor, so as a hypercall, I
would expect it to be something I can deny via XSM. That is a
sufficient option for now to block the path to the firmware. If we end
up needing to support an application that uses that hypercall for
something critical, then yes, it would also need to be hooked into the
monitor system. At the moment this is not necessary.

So if we are landing in do_trap_smc from an HVC call, I think it would
be better to introduce a separate function for it rather then just
bunching the two together here.

>
> Similarly, non-modified baremetal app could use SMC to power on/off the vCPU
> (see PSCI spec). Will you emulate that in the monitor app?

Yes, the underlying setup requires that everything that is expected
from the firmware to be performed either by the monitor app, or have
the monitor app further delegate it somewhere that can perform the
task. That can be either the firmware itself (if its safe), or an
isolated VM if it is possible to perform the task there. I wouldn't
call this emulation necessarily btw.

Tamas

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-08 23:28                       ` Tamas K Lengyel
@ 2017-02-09  0:08                         ` Julien Grall
  2017-02-09  1:20                           ` Stefano Stabellini
                                             ` (2 more replies)
  0 siblings, 3 replies; 44+ messages in thread
From: Julien Grall @ 2017-02-09  0:08 UTC (permalink / raw)
  To: Tamas K Lengyel
  Cc: Edgar E. Iglesias, Edgar E. Iglesias, Stefano Stabellini,
	Volodymyr Babchuk, Xen-devel



On 08/02/2017 23:28, Tamas K Lengyel wrote:
> On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
>> Hi Tamas,
>>
>> Can you please try to configure your e-mail client to use '>' rather than '
>> '? It makes quite hard to read the e-mail.
>
> Hm, not sure why it switched but should be fine now.
>
>> On 08/02/2017 20:15, Tamas K Lengyel wrote:
>>>
>>>
>>>
>>> On Wed, Feb 8, 2017 at 12:40 PM, Edgar E. Iglesias
>>> <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
>>>     On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:
>>
>>
>>>     If platform_hvc() consumes an SMC, it's considered part of the Xen
>>> API.
>>>     Visible but not filterable by a monitor.
>>>
>>>
>>>     Platforms can then dictate which SMC calls are better handled within
>>>     Xen and
>>>     which ones can be exposed to dom0 user-space.
>>>
>>>     In addition, there could be a hypercall to disable platform specific
>>>     handling
>>>     in Xen alltogether for a given guest. Then everything goes to dom0
>>>     user-space.
>>>
>>>     It's a little messy...
>>>
>>>
>>>
>>> That is messy and I would not want any SMCs reaching the firmware when
>>> the monitor application is in use. The monitor interface is disabled by
>>> default and there aren't any known usecases where the SMC has to reach
>>> both the firmware and the monitor application as well. So I think it is
>>> safe to just make the two things mutually exclusive.
>>
>>
>> If you look at the SMC Calling Convention [1] both HVC and SMC are
>> considered a conduit for service call to the secure firmware or hypervisor.
>> It would be up to the hypervisor deciding what to do.
>>
>> Lets imagine the guest is deciding to use HVC to access the secure firmware
>> (AFAIU this patch series is adding that), are you going to monitor all the
>> HVCs (including hypercall)?
>
> There are some fundamental differences between HVC and SMC calls
> though. An HVC can only land in the hypervisor, so as a hypercall, I
> would expect it to be something I can deny via XSM. That is a
> sufficient option for now to block the path to the firmware. If we end
> up needing to support an application that uses that hypercall for
> something critical, then yes, it would also need to be hooked into the
> monitor system. At the moment this is not necessary.

My point is not about what is necessary at the moment. But what is right 
things to do. If you look at the spec, HVC are not only for hypercall, 
but any other kind of services. Why would you deny something that is 
valid from the specification (see 5.2.1)?

"The SMC calling convention, however, does not specify which instruction 
(either SMC or HVC) to use to invoke a
particular service."

>
> So if we are landing in do_trap_smc from an HVC call, I think it would
> be better to introduce a separate function for it rather then just
> bunching the two together here.
>
>>
>> Similarly, non-modified baremetal app could use SMC to power on/off the vCPU
>> (see PSCI spec). Will you emulate that in the monitor app?
>
> Yes, the underlying setup requires that everything that is expected
> from the firmware to be performed either by the monitor app, or have
> the monitor app further delegate it somewhere that can perform the
> task. That can be either the firmware itself (if its safe), or an
> isolated VM if it is possible to perform the task there. I wouldn't
> call this emulation necessarily btw.

You haven't understood my point. Xen is currently emulating PSCI call 
for the guest to allow powering up and down the CPUs and other stuff. If 
you decide to trap all the SMCs, you would have to handle them.

And yes it is emulation as you don't seem to be willing passing those 
SMC to the firmware or even back to Xen. If we expect a VM to emulate a 
trusted firmware, then you have a security problem. Some hardware may be 
only accessible through the secure world and I doubt some trusted app 
vendor will be willing to move cryptography stuff in non secure world. I 
would highly recommend to skim through the OP-TEE thread, it will 
provide you some insights of the constraints.

Cheers,

-- 
Julien Grall

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-09  0:08                         ` Julien Grall
@ 2017-02-09  1:20                           ` Stefano Stabellini
  2017-02-09  9:12                             ` Edgar E. Iglesias
  2017-02-09 16:46                           ` Volodymyr Babchuk
  2017-02-09 18:11                           ` Tamas K Lengyel
  2 siblings, 1 reply; 44+ messages in thread
From: Stefano Stabellini @ 2017-02-09  1:20 UTC (permalink / raw)
  To: Julien Grall
  Cc: Edgar E. Iglesias, Stefano Stabellini, Volodymyr Babchuk,
	Tamas K Lengyel, Xen-devel, Edgar E. Iglesias

On Thu, 9 Feb 2017, Julien Grall wrote:
> On 08/02/2017 23:28, Tamas K Lengyel wrote:
> > On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
> > > Hi Tamas,
> > > 
> > > Can you please try to configure your e-mail client to use '>' rather than
> > > '
> > > '? It makes quite hard to read the e-mail.
> > 
> > Hm, not sure why it switched but should be fine now.
> > 
> > > On 08/02/2017 20:15, Tamas K Lengyel wrote:
> > > > 
> > > > 
> > > > 
> > > > On Wed, Feb 8, 2017 at 12:40 PM, Edgar E. Iglesias
> > > > <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
> > > >     On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:
> > > 
> > > 
> > > >     If platform_hvc() consumes an SMC, it's considered part of the Xen
> > > > API.
> > > >     Visible but not filterable by a monitor.
> > > > 
> > > > 
> > > >     Platforms can then dictate which SMC calls are better handled within
> > > >     Xen and
> > > >     which ones can be exposed to dom0 user-space.
> > > > 
> > > >     In addition, there could be a hypercall to disable platform specific
> > > >     handling
> > > >     in Xen alltogether for a given guest. Then everything goes to dom0
> > > >     user-space.
> > > > 
> > > >     It's a little messy...
> > > > 
> > > > 
> > > > 
> > > > That is messy and I would not want any SMCs reaching the firmware when
> > > > the monitor application is in use. The monitor interface is disabled by
> > > > default and there aren't any known usecases where the SMC has to reach
> > > > both the firmware and the monitor application as well. So I think it is
> > > > safe to just make the two things mutually exclusive.
> > > 
> > > 
> > > If you look at the SMC Calling Convention [1] both HVC and SMC are
> > > considered a conduit for service call to the secure firmware or
> > > hypervisor.
> > > It would be up to the hypervisor deciding what to do.
> > > 
> > > Lets imagine the guest is deciding to use HVC to access the secure
> > > firmware
> > > (AFAIU this patch series is adding that), are you going to monitor all the
> > > HVCs (including hypercall)?
> > 
> > There are some fundamental differences between HVC and SMC calls
> > though. An HVC can only land in the hypervisor, so as a hypercall, I
> > would expect it to be something I can deny via XSM. That is a
> > sufficient option for now to block the path to the firmware. If we end
> > up needing to support an application that uses that hypercall for
> > something critical, then yes, it would also need to be hooked into the
> > monitor system. At the moment this is not necessary.
> 
> My point is not about what is necessary at the moment. But what is right
> things to do. If you look at the spec, HVC are not only for hypercall, but any
> other kind of services. Why would you deny something that is valid from the
> specification (see 5.2.1)?
> 
> "The SMC calling convention, however, does not specify which instruction
> (either SMC or HVC) to use to invoke a
> particular service."

To have a generic solution, we need a way to specify a set of HVC/SMC
calls that get monitored and a set that get handled in Xen (platform
specific or otherwise). I think it is OK not to do both, at least at the
beginning, but we might want to add that feature in the future.

As much as I would like to see that, in respect to this series, I don't
think we should ask Edgar to introduce such a mechanism. However, we do
need to decide what Xen should do when platform_hvc is implemented and
monitor is also enabled.

I think the default should be to only call platform_hvc, because there
are many valid monitoring use-cases which don't require those few
platform specific SMC/HVC calls to be forwarded to the monitor.

However, if we did that, we would break Tamas' scenario. Thus, I suggest
we also introduce a simple compile time option or Xen command line
option to forward all platform_hvc calls to the monitor instead of
implementing them in Xen. Something like "MONITOR_OVERRIDE". In the
future, we can replace it with a more generic framework to dynamically
configure at runtime which SMC/HVC calls get forwarded.

What do you think?


> > So if we are landing in do_trap_smc from an HVC call, I think it would
> > be better to introduce a separate function for it rather then just
> > bunching the two together here.
> > 
> > > 
> > > Similarly, non-modified baremetal app could use SMC to power on/off the
> > > vCPU
> > > (see PSCI spec). Will you emulate that in the monitor app?
> > 
> > Yes, the underlying setup requires that everything that is expected
> > from the firmware to be performed either by the monitor app, or have
> > the monitor app further delegate it somewhere that can perform the
> > task. That can be either the firmware itself (if its safe), or an
> > isolated VM if it is possible to perform the task there. I wouldn't
> > call this emulation necessarily btw.
> 
> You haven't understood my point. Xen is currently emulating PSCI call for the
> guest to allow powering up and down the CPUs and other stuff. If you decide to
> trap all the SMCs, you would have to handle them.
> 
> And yes it is emulation as you don't seem to be willing passing those SMC to
> the firmware or even back to Xen. If we expect a VM to emulate a trusted
> firmware, then you have a security problem. Some hardware may be only
> accessible through the secure world and I doubt some trusted app vendor will
> be willing to move cryptography stuff in non secure world. I would highly
> recommend to skim through the OP-TEE thread, it will provide you some insights
> of the constraints.

Each platform is different. It seems unlikely to me too, and it might
always remain a niche use-case, but it is still a valid scenario to
consider.

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-09  1:20                           ` Stefano Stabellini
@ 2017-02-09  9:12                             ` Edgar E. Iglesias
  2017-02-09  9:27                               ` Edgar E. Iglesias
  0 siblings, 1 reply; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-02-09  9:12 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Edgar E. Iglesias, Tamas K Lengyel, Julien Grall,
	Volodymyr Babchuk, Xen-devel

On Wed, Feb 08, 2017 at 05:20:44PM -0800, Stefano Stabellini wrote:
> On Thu, 9 Feb 2017, Julien Grall wrote:
> > On 08/02/2017 23:28, Tamas K Lengyel wrote:
> > > On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
> > > > Hi Tamas,
> > > > 
> > > > Can you please try to configure your e-mail client to use '>' rather than
> > > > '
> > > > '? It makes quite hard to read the e-mail.
> > > 
> > > Hm, not sure why it switched but should be fine now.
> > > 
> > > > On 08/02/2017 20:15, Tamas K Lengyel wrote:
> > > > > 
> > > > > 
> > > > > 
> > > > > On Wed, Feb 8, 2017 at 12:40 PM, Edgar E. Iglesias
> > > > > <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
> > > > >     On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:
> > > > 
> > > > 
> > > > >     If platform_hvc() consumes an SMC, it's considered part of the Xen
> > > > > API.
> > > > >     Visible but not filterable by a monitor.
> > > > > 
> > > > > 
> > > > >     Platforms can then dictate which SMC calls are better handled within
> > > > >     Xen and
> > > > >     which ones can be exposed to dom0 user-space.
> > > > > 
> > > > >     In addition, there could be a hypercall to disable platform specific
> > > > >     handling
> > > > >     in Xen alltogether for a given guest. Then everything goes to dom0
> > > > >     user-space.
> > > > > 
> > > > >     It's a little messy...
> > > > > 
> > > > > 
> > > > > 
> > > > > That is messy and I would not want any SMCs reaching the firmware when
> > > > > the monitor application is in use. The monitor interface is disabled by
> > > > > default and there aren't any known usecases where the SMC has to reach
> > > > > both the firmware and the monitor application as well. So I think it is
> > > > > safe to just make the two things mutually exclusive.
> > > > 
> > > > 
> > > > If you look at the SMC Calling Convention [1] both HVC and SMC are
> > > > considered a conduit for service call to the secure firmware or
> > > > hypervisor.
> > > > It would be up to the hypervisor deciding what to do.
> > > > 
> > > > Lets imagine the guest is deciding to use HVC to access the secure
> > > > firmware
> > > > (AFAIU this patch series is adding that), are you going to monitor all the
> > > > HVCs (including hypercall)?
> > > 
> > > There are some fundamental differences between HVC and SMC calls
> > > though. An HVC can only land in the hypervisor, so as a hypercall, I
> > > would expect it to be something I can deny via XSM. That is a
> > > sufficient option for now to block the path to the firmware. If we end
> > > up needing to support an application that uses that hypercall for
> > > something critical, then yes, it would also need to be hooked into the
> > > monitor system. At the moment this is not necessary.
> > 
> > My point is not about what is necessary at the moment. But what is right
> > things to do. If you look at the spec, HVC are not only for hypercall, but any
> > other kind of services. Why would you deny something that is valid from the
> > specification (see 5.2.1)?
> > 
> > "The SMC calling convention, however, does not specify which instruction
> > (either SMC or HVC) to use to invoke a
> > particular service."
> 
> To have a generic solution, we need a way to specify a set of HVC/SMC
> calls that get monitored and a set that get handled in Xen (platform
> specific or otherwise). I think it is OK not to do both, at least at the
> beginning, but we might want to add that feature in the future.
> 
> As much as I would like to see that, in respect to this series, I don't
> think we should ask Edgar to introduce such a mechanism. However, we do
> need to decide what Xen should do when platform_hvc is implemented and
> monitor is also enabled.
> 
> I think the default should be to only call platform_hvc, because there
> are many valid monitoring use-cases which don't require those few
> platform specific SMC/HVC calls to be forwarded to the monitor.
> 
> However, if we did that, we would break Tamas' scenario. Thus, I suggest
> we also introduce a simple compile time option or Xen command line
> option to forward all platform_hvc calls to the monitor instead of
> implementing them in Xen. Something like "MONITOR_OVERRIDE". In the
> future, we can replace it with a more generic framework to dynamically
> configure at runtime which SMC/HVC calls get forwarded.
> 
> What do you think?

This could work in some scenarios, but for example on the ZynqMP,
dom0 needs access to Firmware as it boots, otherwise a lot of I/O
will end up non-functional (with recent kernels). Anyway, I think it
would give us a path forward. Future patches could either implement
finer control or something else.

Perhaps a hypercall to allow dom0 to turn off any platform_hvc handling for
a given guest would help. If that mode is enabled, Xen is hands off on
any platform specific HVC/SMC. It still leaves the problem open for
other calls but I must say I find it strange to emulate the Xen Hypercalls
in dom0 user-space.

AFAIK, the monitor is not looking at HVC today. So it is allowing PSCI
firmware calls through Xen's PSCI mediator/emulator. Some of these calls
may sometimes hit firmware, so the point of isolating a guest completely
from Firmware access is not valid today.

Cheers,
Edgar


> > > So if we are landing in do_trap_smc from an HVC call, I think it would
> > > be better to introduce a separate function for it rather then just
> > > bunching the two together here.
> > > 
> > > > 
> > > > Similarly, non-modified baremetal app could use SMC to power on/off the
> > > > vCPU
> > > > (see PSCI spec). Will you emulate that in the monitor app?
> > > 
> > > Yes, the underlying setup requires that everything that is expected
> > > from the firmware to be performed either by the monitor app, or have
> > > the monitor app further delegate it somewhere that can perform the
> > > task. That can be either the firmware itself (if its safe), or an
> > > isolated VM if it is possible to perform the task there. I wouldn't
> > > call this emulation necessarily btw.
> > 
> > You haven't understood my point. Xen is currently emulating PSCI call for the
> > guest to allow powering up and down the CPUs and other stuff. If you decide to
> > trap all the SMCs, you would have to handle them.
> > 
> > And yes it is emulation as you don't seem to be willing passing those SMC to
> > the firmware or even back to Xen. If we expect a VM to emulate a trusted
> > firmware, then you have a security problem. Some hardware may be only
> > accessible through the secure world and I doubt some trusted app vendor will
> > be willing to move cryptography stuff in non secure world. I would highly
> > recommend to skim through the OP-TEE thread, it will provide you some insights
> > of the constraints.
> 
> Each platform is different. It seems unlikely to me too, and it might
> always remain a niche use-case, but it is still a valid scenario to
> consider.



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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-09  9:12                             ` Edgar E. Iglesias
@ 2017-02-09  9:27                               ` Edgar E. Iglesias
  2017-02-09 18:22                                 ` Stefano Stabellini
  0 siblings, 1 reply; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-02-09  9:27 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: Volodymyr Babchuk, Tamas K Lengyel, Julien Grall,
	Stefano Stabellini, Xen-devel

On Thu, Feb 09, 2017 at 10:12:41AM +0100, Edgar E. Iglesias wrote:
> On Wed, Feb 08, 2017 at 05:20:44PM -0800, Stefano Stabellini wrote:
> > On Thu, 9 Feb 2017, Julien Grall wrote:
> > > On 08/02/2017 23:28, Tamas K Lengyel wrote:
> > > > On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
> > > > > Hi Tamas,
> > > > > 
> > > > > Can you please try to configure your e-mail client to use '>' rather than
> > > > > '
> > > > > '? It makes quite hard to read the e-mail.
> > > > 
> > > > Hm, not sure why it switched but should be fine now.
> > > > 
> > > > > On 08/02/2017 20:15, Tamas K Lengyel wrote:
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > On Wed, Feb 8, 2017 at 12:40 PM, Edgar E. Iglesias
> > > > > > <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
> > > > > >     On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:
> > > > > 
> > > > > 
> > > > > >     If platform_hvc() consumes an SMC, it's considered part of the Xen
> > > > > > API.
> > > > > >     Visible but not filterable by a monitor.
> > > > > > 
> > > > > > 
> > > > > >     Platforms can then dictate which SMC calls are better handled within
> > > > > >     Xen and
> > > > > >     which ones can be exposed to dom0 user-space.
> > > > > > 
> > > > > >     In addition, there could be a hypercall to disable platform specific
> > > > > >     handling
> > > > > >     in Xen alltogether for a given guest. Then everything goes to dom0
> > > > > >     user-space.
> > > > > > 
> > > > > >     It's a little messy...
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > That is messy and I would not want any SMCs reaching the firmware when
> > > > > > the monitor application is in use. The monitor interface is disabled by
> > > > > > default and there aren't any known usecases where the SMC has to reach
> > > > > > both the firmware and the monitor application as well. So I think it is
> > > > > > safe to just make the two things mutually exclusive.
> > > > > 
> > > > > 
> > > > > If you look at the SMC Calling Convention [1] both HVC and SMC are
> > > > > considered a conduit for service call to the secure firmware or
> > > > > hypervisor.
> > > > > It would be up to the hypervisor deciding what to do.
> > > > > 
> > > > > Lets imagine the guest is deciding to use HVC to access the secure
> > > > > firmware
> > > > > (AFAIU this patch series is adding that), are you going to monitor all the
> > > > > HVCs (including hypercall)?
> > > > 
> > > > There are some fundamental differences between HVC and SMC calls
> > > > though. An HVC can only land in the hypervisor, so as a hypercall, I
> > > > would expect it to be something I can deny via XSM. That is a
> > > > sufficient option for now to block the path to the firmware. If we end
> > > > up needing to support an application that uses that hypercall for
> > > > something critical, then yes, it would also need to be hooked into the
> > > > monitor system. At the moment this is not necessary.
> > > 
> > > My point is not about what is necessary at the moment. But what is right
> > > things to do. If you look at the spec, HVC are not only for hypercall, but any
> > > other kind of services. Why would you deny something that is valid from the
> > > specification (see 5.2.1)?
> > > 
> > > "The SMC calling convention, however, does not specify which instruction
> > > (either SMC or HVC) to use to invoke a
> > > particular service."
> > 
> > To have a generic solution, we need a way to specify a set of HVC/SMC
> > calls that get monitored and a set that get handled in Xen (platform
> > specific or otherwise). I think it is OK not to do both, at least at the
> > beginning, but we might want to add that feature in the future.
> > 
> > As much as I would like to see that, in respect to this series, I don't
> > think we should ask Edgar to introduce such a mechanism. However, we do
> > need to decide what Xen should do when platform_hvc is implemented and
> > monitor is also enabled.
> > 
> > I think the default should be to only call platform_hvc, because there
> > are many valid monitoring use-cases which don't require those few
> > platform specific SMC/HVC calls to be forwarded to the monitor.
> > 
> > However, if we did that, we would break Tamas' scenario. Thus, I suggest
> > we also introduce a simple compile time option or Xen command line
> > option to forward all platform_hvc calls to the monitor instead of
> > implementing them in Xen. Something like "MONITOR_OVERRIDE". In the
> > future, we can replace it with a more generic framework to dynamically
> > configure at runtime which SMC/HVC calls get forwarded.
> > 
> > What do you think?
> 
> This could work in some scenarios, but for example on the ZynqMP,
> dom0 needs access to Firmware as it boots, otherwise a lot of I/O
> will end up non-functional (with recent kernels). Anyway, I think it
> would give us a path forward. Future patches could either implement
> finer control or something else.

Actually, MONITOR_OVERRIDE could allow dom0 full access to the Firmware
and only block guests. That would work better on the ZynqMP. I probably
overlooked this in your suggestion.

Cheers,
Edgar


> 
> Perhaps a hypercall to allow dom0 to turn off any platform_hvc handling for
> a given guest would help. If that mode is enabled, Xen is hands off on
> any platform specific HVC/SMC. It still leaves the problem open for
> other calls but I must say I find it strange to emulate the Xen Hypercalls
> in dom0 user-space.
> 
> AFAIK, the monitor is not looking at HVC today. So it is allowing PSCI
> firmware calls through Xen's PSCI mediator/emulator. Some of these calls
> may sometimes hit firmware, so the point of isolating a guest completely
> from Firmware access is not valid today.
> 
> Cheers,
> Edgar
> 
> 
> > > > So if we are landing in do_trap_smc from an HVC call, I think it would
> > > > be better to introduce a separate function for it rather then just
> > > > bunching the two together here.
> > > > 
> > > > > 
> > > > > Similarly, non-modified baremetal app could use SMC to power on/off the
> > > > > vCPU
> > > > > (see PSCI spec). Will you emulate that in the monitor app?
> > > > 
> > > > Yes, the underlying setup requires that everything that is expected
> > > > from the firmware to be performed either by the monitor app, or have
> > > > the monitor app further delegate it somewhere that can perform the
> > > > task. That can be either the firmware itself (if its safe), or an
> > > > isolated VM if it is possible to perform the task there. I wouldn't
> > > > call this emulation necessarily btw.
> > > 
> > > You haven't understood my point. Xen is currently emulating PSCI call for the
> > > guest to allow powering up and down the CPUs and other stuff. If you decide to
> > > trap all the SMCs, you would have to handle them.
> > > 
> > > And yes it is emulation as you don't seem to be willing passing those SMC to
> > > the firmware or even back to Xen. If we expect a VM to emulate a trusted
> > > firmware, then you have a security problem. Some hardware may be only
> > > accessible through the secure world and I doubt some trusted app vendor will
> > > be willing to move cryptography stuff in non secure world. I would highly
> > > recommend to skim through the OP-TEE thread, it will provide you some insights
> > > of the constraints.
> > 
> > Each platform is different. It seems unlikely to me too, and it might
> > always remain a niche use-case, but it is still a valid scenario to
> > consider.
> 
> 

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-08 22:04                     ` Julien Grall
  2017-02-08 23:28                       ` Tamas K Lengyel
@ 2017-02-09 14:46                       ` Edgar E. Iglesias
  1 sibling, 0 replies; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-02-09 14:46 UTC (permalink / raw)
  To: Julien Grall
  Cc: Volodymyr Babchuk, Tamas K Lengyel, Xen-devel,
	Stefano Stabellini, Edgar E. Iglesias

On Wed, Feb 08, 2017 at 10:04:53PM +0000, Julien Grall wrote:
> Hi Tamas,
> 
> Can you please try to configure your e-mail client to use '>' rather than '
> '? It makes quite hard to read the e-mail.
> 
> On 08/02/2017 20:15, Tamas K Lengyel wrote:
> >
> >
> >On Wed, Feb 8, 2017 at 12:40 PM, Edgar E. Iglesias
> ><edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
> >    On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:
> 
> >    If platform_hvc() consumes an SMC, it's considered part of the Xen API.
> >    Visible but not filterable by a monitor.
> >
> >
> >    Platforms can then dictate which SMC calls are better handled within
> >    Xen and
> >    which ones can be exposed to dom0 user-space.
> >
> >    In addition, there could be a hypercall to disable platform specific
> >    handling
> >    in Xen alltogether for a given guest. Then everything goes to dom0
> >    user-space.
> >
> >    It's a little messy...
> >
> >
> >
> >That is messy and I would not want any SMCs reaching the firmware when
> >the monitor application is in use. The monitor interface is disabled by
> >default and there aren't any known usecases where the SMC has to reach
> >both the firmware and the monitor application as well. So I think it is
> >safe to just make the two things mutually exclusive.
> 
> If you look at the SMC Calling Convention [1] both HVC and SMC are
> considered a conduit for service call to the secure firmware or hypervisor.
> It would be up to the hypervisor deciding what to do.
> 
> Lets imagine the guest is deciding to use HVC to access the secure firmware
> (AFAIU this patch series is adding that), are you going to monitor all the

Hi Julien,

My patch enables HVC and SMC to reach the platform specific calls. I didn't
connect PSCI over SMC though, I forgot about that but I definitely think
it makes sense to do so. Unmodified guest code would use SMC for everything
when running without a Hypervisor, so preferably the same would work on top
of Xen.

I'll fix that for v3.

Thanks,
Edgar




> HVCs (including hypercall)?
> 
> Similarly, non-modified baremetal app could use SMC to power on/off the vCPU
> (see PSCI spec). Will you emulate that in the monitor app?
> 
> So I think we need to be consistent across HVC and SMC call. And mutually
> exclusive does not sound right to me for HVC.
> 
> Cheers,
> 
> [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0028b/index.html
> 
> 
> -- 
> Julien Grall

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-09  0:08                         ` Julien Grall
  2017-02-09  1:20                           ` Stefano Stabellini
@ 2017-02-09 16:46                           ` Volodymyr Babchuk
  2017-02-09 18:11                           ` Tamas K Lengyel
  2 siblings, 0 replies; 44+ messages in thread
From: Volodymyr Babchuk @ 2017-02-09 16:46 UTC (permalink / raw)
  To: Julien Grall
  Cc: Edgar E. Iglesias, Tamas K Lengyel, Xen-devel,
	Stefano Stabellini, Edgar E. Iglesias

Julien,

You are absolutely right there. I want to add some more concerns about
current state of SMC handling in Xen. After that discussion about
OP-TEE I created small PoC that employs MiniOS to handle SMCs using
monitor mode. Also I did some benchmarking and found that SMC handling
in MiniOS is ten times slower, than handling in XEN. But, still, it is
pretty fast and I don't think this will be a problem. Anyways, I want
to try another approach and handle SMCs in EL0 XEN mode.
Real problem is that dom0 can't have monitor. This is pretty obvious
if you think about it. But this completely ruins OP-TEE use case. As
you remember, idea was to handle all SMCs in one place before they
would reach OP-TEE. Sadly, with current design, you can't handle SMCs
from dom0.

So, as you can see, there are many requirements for proper SMC
handling in hypervisor. Current state is unsatisfactory, there are
different approaches were proposed by me, by Edgar, but looks like
they can't satisfy us all.
Probably, we need completely different approach. Maybe, Xen EL0 apps
can be a good way to offload tasks such as SMC handling, device
emulation, hardware drivers (like cpu freq or thermal management),
etc. Or some framework, where you can register handlers for specific
op types,etc, etc.

Anyways, I feel that we need to gather all requirements to SMC
handling from all interested sides and then we need to develop some
approach, that will satisfy all of us.
I'm going to start new thread on this topic tomorrow, if you don't mind.

On 9 February 2017 at 02:08, Julien Grall <julien.grall@arm.com> wrote:
>
>
> On 08/02/2017 23:28, Tamas K Lengyel wrote:
>>
>> On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
>>>
>>> Hi Tamas,
>>>
>>> Can you please try to configure your e-mail client to use '>' rather than
>>> '
>>> '? It makes quite hard to read the e-mail.
>>
>>
>> Hm, not sure why it switched but should be fine now.
>>
>>> On 08/02/2017 20:15, Tamas K Lengyel wrote:
>>>>
>>>>
>>>>
>>>>
>>>> On Wed, Feb 8, 2017 at 12:40 PM, Edgar E. Iglesias
>>>> <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
>>>>     On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:
>>>
>>>
>>>
>>>>     If platform_hvc() consumes an SMC, it's considered part of the Xen
>>>> API.
>>>>     Visible but not filterable by a monitor.
>>>>
>>>>
>>>>     Platforms can then dictate which SMC calls are better handled within
>>>>     Xen and
>>>>     which ones can be exposed to dom0 user-space.
>>>>
>>>>     In addition, there could be a hypercall to disable platform specific
>>>>     handling
>>>>     in Xen alltogether for a given guest. Then everything goes to dom0
>>>>     user-space.
>>>>
>>>>     It's a little messy...
>>>>
>>>>
>>>>
>>>> That is messy and I would not want any SMCs reaching the firmware when
>>>> the monitor application is in use. The monitor interface is disabled by
>>>> default and there aren't any known usecases where the SMC has to reach
>>>> both the firmware and the monitor application as well. So I think it is
>>>> safe to just make the two things mutually exclusive.
>>>
>>>
>>>
>>> If you look at the SMC Calling Convention [1] both HVC and SMC are
>>> considered a conduit for service call to the secure firmware or
>>> hypervisor.
>>> It would be up to the hypervisor deciding what to do.
>>>
>>> Lets imagine the guest is deciding to use HVC to access the secure
>>> firmware
>>> (AFAIU this patch series is adding that), are you going to monitor all
>>> the
>>> HVCs (including hypercall)?
>>
>>
>> There are some fundamental differences between HVC and SMC calls
>> though. An HVC can only land in the hypervisor, so as a hypercall, I
>> would expect it to be something I can deny via XSM. That is a
>> sufficient option for now to block the path to the firmware. If we end
>> up needing to support an application that uses that hypercall for
>> something critical, then yes, it would also need to be hooked into the
>> monitor system. At the moment this is not necessary.
>
>
> My point is not about what is necessary at the moment. But what is right
> things to do. If you look at the spec, HVC are not only for hypercall, but
> any other kind of services. Why would you deny something that is valid from
> the specification (see 5.2.1)?
>
> "The SMC calling convention, however, does not specify which instruction
> (either SMC or HVC) to use to invoke a
> particular service."
>
>>
>> So if we are landing in do_trap_smc from an HVC call, I think it would
>> be better to introduce a separate function for it rather then just
>> bunching the two together here.
>>
>>>
>>> Similarly, non-modified baremetal app could use SMC to power on/off the
>>> vCPU
>>> (see PSCI spec). Will you emulate that in the monitor app?
>>
>>
>> Yes, the underlying setup requires that everything that is expected
>> from the firmware to be performed either by the monitor app, or have
>> the monitor app further delegate it somewhere that can perform the
>> task. That can be either the firmware itself (if its safe), or an
>> isolated VM if it is possible to perform the task there. I wouldn't
>> call this emulation necessarily btw.
>
>
> You haven't understood my point. Xen is currently emulating PSCI call for
> the guest to allow powering up and down the CPUs and other stuff. If you
> decide to trap all the SMCs, you would have to handle them.
>
> And yes it is emulation as you don't seem to be willing passing those SMC to
> the firmware or even back to Xen. If we expect a VM to emulate a trusted
> firmware, then you have a security problem. Some hardware may be only
> accessible through the secure world and I doubt some trusted app vendor will
> be willing to move cryptography stuff in non secure world. I would highly
> recommend to skim through the OP-TEE thread, it will provide you some
> insights of the constraints.
>
> Cheers,
>
> --
> Julien Grall



-- 
WBR Volodymyr Babchuk aka lorc [+380976646013]
mailto: vlad.babchuk@gmail.com

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-09  0:08                         ` Julien Grall
  2017-02-09  1:20                           ` Stefano Stabellini
  2017-02-09 16:46                           ` Volodymyr Babchuk
@ 2017-02-09 18:11                           ` Tamas K Lengyel
  2017-02-09 18:39                             ` Julien Grall
  2 siblings, 1 reply; 44+ messages in thread
From: Tamas K Lengyel @ 2017-02-09 18:11 UTC (permalink / raw)
  To: Julien Grall
  Cc: Edgar E. Iglesias, Edgar E. Iglesias, Stefano Stabellini,
	Volodymyr Babchuk, Xen-devel

On Wed, Feb 8, 2017 at 5:08 PM, Julien Grall <julien.grall@arm.com> wrote:
>
>
> On 08/02/2017 23:28, Tamas K Lengyel wrote:
>>
>> On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
>>>
>>> Hi Tamas,
>>>
>>> Can you please try to configure your e-mail client to use '>' rather than
>>> '
>>> '? It makes quite hard to read the e-mail.
>>
>>
>> Hm, not sure why it switched but should be fine now.
>>
>>> On 08/02/2017 20:15, Tamas K Lengyel wrote:
>>>>
>>>>
>>>>
>>>>
>>>> On Wed, Feb 8, 2017 at 12:40 PM, Edgar E. Iglesias
>>>> <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
>>>>     On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:
>>>
>>>
>>>
>>>>     If platform_hvc() consumes an SMC, it's considered part of the Xen
>>>> API.
>>>>     Visible but not filterable by a monitor.
>>>>
>>>>
>>>>     Platforms can then dictate which SMC calls are better handled within
>>>>     Xen and
>>>>     which ones can be exposed to dom0 user-space.
>>>>
>>>>     In addition, there could be a hypercall to disable platform specific
>>>>     handling
>>>>     in Xen alltogether for a given guest. Then everything goes to dom0
>>>>     user-space.
>>>>
>>>>     It's a little messy...
>>>>
>>>>
>>>>
>>>> That is messy and I would not want any SMCs reaching the firmware when
>>>> the monitor application is in use. The monitor interface is disabled by
>>>> default and there aren't any known usecases where the SMC has to reach
>>>> both the firmware and the monitor application as well. So I think it is
>>>> safe to just make the two things mutually exclusive.
>>>
>>>
>>>
>>> If you look at the SMC Calling Convention [1] both HVC and SMC are
>>> considered a conduit for service call to the secure firmware or
>>> hypervisor.
>>> It would be up to the hypervisor deciding what to do.
>>>
>>> Lets imagine the guest is deciding to use HVC to access the secure
>>> firmware
>>> (AFAIU this patch series is adding that), are you going to monitor all
>>> the
>>> HVCs (including hypercall)?
>>
>>
>> There are some fundamental differences between HVC and SMC calls
>> though. An HVC can only land in the hypervisor, so as a hypercall, I
>> would expect it to be something I can deny via XSM. That is a
>> sufficient option for now to block the path to the firmware. If we end
>> up needing to support an application that uses that hypercall for
>> something critical, then yes, it would also need to be hooked into the
>> monitor system. At the moment this is not necessary.
>
>
> My point is not about what is necessary at the moment. But what is right
> things to do. If you look at the spec, HVC are not only for hypercall, but
> any other kind of services. Why would you deny something that is valid from
> the specification (see 5.2.1)?
>
> "The SMC calling convention, however, does not specify which instruction
> (either SMC or HVC) to use to invoke a
> particular service."
>
>>
>> So if we are landing in do_trap_smc from an HVC call, I think it would
>> be better to introduce a separate function for it rather then just
>> bunching the two together here.
>>
>>>
>>> Similarly, non-modified baremetal app could use SMC to power on/off the
>>> vCPU
>>> (see PSCI spec). Will you emulate that in the monitor app?
>>
>>
>> Yes, the underlying setup requires that everything that is expected
>> from the firmware to be performed either by the monitor app, or have
>> the monitor app further delegate it somewhere that can perform the
>> task. That can be either the firmware itself (if its safe), or an
>> isolated VM if it is possible to perform the task there. I wouldn't
>> call this emulation necessarily btw.
>
>
> You haven't understood my point. Xen is currently emulating PSCI call for
> the guest to allow powering up and down the CPUs and other stuff. If you
> decide to trap all the SMCs, you would have to handle them.

Sure, it's more work on the monitor side, but other then that, what's
the problem?

>
> And yes it is emulation as you don't seem to be willing passing those SMC to
> the firmware or even back to Xen. If we expect a VM to emulate a trusted
> firmware, then you have a security problem. Some hardware may be only
> accessible through the secure world and I doubt some trusted app vendor will
> be willing to move cryptography stuff in non secure world. I would highly
> recommend to skim through the OP-TEE thread, it will provide you some
> insights of the constraints.

The firmware is not hardware, it's just a piece of code that has been
baked into the board in some manner. Emulation in my book is doing in
software what hardware is supposed to do. I don't expect all vendors
to be happy to move their proprietary whatever to a VM. Again, this is
an experimental setup with no real world applications at the moment.
As for certain hardware being only accessible from the TZ, in that
case the monitor application would have to call into the firmware. My
setup doesn't prohibit using the TZ, it just prohibits it being
accessible from untrusted guests directly.

Tamas

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-09  9:27                               ` Edgar E. Iglesias
@ 2017-02-09 18:22                                 ` Stefano Stabellini
  2017-02-09 18:25                                   ` Tamas K Lengyel
  0 siblings, 1 reply; 44+ messages in thread
From: Stefano Stabellini @ 2017-02-09 18:22 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: Stefano Stabellini, Volodymyr Babchuk, Tamas K Lengyel,
	Xen-devel, Julien Grall, Edgar E. Iglesias

On Thu, 9 Feb 2017, Edgar E. Iglesias wrote:
> On Thu, Feb 09, 2017 at 10:12:41AM +0100, Edgar E. Iglesias wrote:
> > On Wed, Feb 08, 2017 at 05:20:44PM -0800, Stefano Stabellini wrote:
> > > On Thu, 9 Feb 2017, Julien Grall wrote:
> > > > On 08/02/2017 23:28, Tamas K Lengyel wrote:
> > > > > On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
> > > > > > Hi Tamas,
> > > > > > 
> > > > > > Can you please try to configure your e-mail client to use '>' rather than
> > > > > > '
> > > > > > '? It makes quite hard to read the e-mail.
> > > > > 
> > > > > Hm, not sure why it switched but should be fine now.
> > > > > 
> > > > > > On 08/02/2017 20:15, Tamas K Lengyel wrote:
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > On Wed, Feb 8, 2017 at 12:40 PM, Edgar E. Iglesias
> > > > > > > <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
> > > > > > >     On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:
> > > > > > 
> > > > > > 
> > > > > > >     If platform_hvc() consumes an SMC, it's considered part of the Xen
> > > > > > > API.
> > > > > > >     Visible but not filterable by a monitor.
> > > > > > > 
> > > > > > > 
> > > > > > >     Platforms can then dictate which SMC calls are better handled within
> > > > > > >     Xen and
> > > > > > >     which ones can be exposed to dom0 user-space.
> > > > > > > 
> > > > > > >     In addition, there could be a hypercall to disable platform specific
> > > > > > >     handling
> > > > > > >     in Xen alltogether for a given guest. Then everything goes to dom0
> > > > > > >     user-space.
> > > > > > > 
> > > > > > >     It's a little messy...
> > > > > > > 
> > > > > > > 
> > > > > > > 
> > > > > > > That is messy and I would not want any SMCs reaching the firmware when
> > > > > > > the monitor application is in use. The monitor interface is disabled by
> > > > > > > default and there aren't any known usecases where the SMC has to reach
> > > > > > > both the firmware and the monitor application as well. So I think it is
> > > > > > > safe to just make the two things mutually exclusive.
> > > > > > 
> > > > > > 
> > > > > > If you look at the SMC Calling Convention [1] both HVC and SMC are
> > > > > > considered a conduit for service call to the secure firmware or
> > > > > > hypervisor.
> > > > > > It would be up to the hypervisor deciding what to do.
> > > > > > 
> > > > > > Lets imagine the guest is deciding to use HVC to access the secure
> > > > > > firmware
> > > > > > (AFAIU this patch series is adding that), are you going to monitor all the
> > > > > > HVCs (including hypercall)?
> > > > > 
> > > > > There are some fundamental differences between HVC and SMC calls
> > > > > though. An HVC can only land in the hypervisor, so as a hypercall, I
> > > > > would expect it to be something I can deny via XSM. That is a
> > > > > sufficient option for now to block the path to the firmware. If we end
> > > > > up needing to support an application that uses that hypercall for
> > > > > something critical, then yes, it would also need to be hooked into the
> > > > > monitor system. At the moment this is not necessary.
> > > > 
> > > > My point is not about what is necessary at the moment. But what is right
> > > > things to do. If you look at the spec, HVC are not only for hypercall, but any
> > > > other kind of services. Why would you deny something that is valid from the
> > > > specification (see 5.2.1)?
> > > > 
> > > > "The SMC calling convention, however, does not specify which instruction
> > > > (either SMC or HVC) to use to invoke a
> > > > particular service."
> > > 
> > > To have a generic solution, we need a way to specify a set of HVC/SMC
> > > calls that get monitored and a set that get handled in Xen (platform
> > > specific or otherwise). I think it is OK not to do both, at least at the
> > > beginning, but we might want to add that feature in the future.
> > > 
> > > As much as I would like to see that, in respect to this series, I don't
> > > think we should ask Edgar to introduce such a mechanism. However, we do
> > > need to decide what Xen should do when platform_hvc is implemented and
> > > monitor is also enabled.
> > > 
> > > I think the default should be to only call platform_hvc, because there
> > > are many valid monitoring use-cases which don't require those few
> > > platform specific SMC/HVC calls to be forwarded to the monitor.
> > > 
> > > However, if we did that, we would break Tamas' scenario. Thus, I suggest
> > > we also introduce a simple compile time option or Xen command line
> > > option to forward all platform_hvc calls to the monitor instead of
> > > implementing them in Xen. Something like "MONITOR_OVERRIDE". In the
> > > future, we can replace it with a more generic framework to dynamically
> > > configure at runtime which SMC/HVC calls get forwarded.
> > > 
> > > What do you think?
> > 
> > This could work in some scenarios, but for example on the ZynqMP,
> > dom0 needs access to Firmware as it boots, otherwise a lot of I/O
> > will end up non-functional (with recent kernels). Anyway, I think it
> > would give us a path forward. Future patches could either implement
> > finer control or something else.
> 
> Actually, MONITOR_OVERRIDE could allow dom0 full access to the Firmware
> and only block guests. That would work better on the ZynqMP. I probably
> overlooked this in your suggestion.

Yes, the intention is to allow Dom0 full access to the firmware by
default, even when memory introspection is enabled. The MONITOR_OVERRIDE
tunable would change that, but would need to be explicitly enabled.

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-09 18:22                                 ` Stefano Stabellini
@ 2017-02-09 18:25                                   ` Tamas K Lengyel
  2017-02-09 18:43                                     ` Stefano Stabellini
  0 siblings, 1 reply; 44+ messages in thread
From: Tamas K Lengyel @ 2017-02-09 18:25 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Edgar E. Iglesias, Edgar E. Iglesias, Julien Grall,
	Volodymyr Babchuk, Xen-devel

On Thu, Feb 9, 2017 at 11:22 AM, Stefano Stabellini
<sstabellini@kernel.org> wrote:
> On Thu, 9 Feb 2017, Edgar E. Iglesias wrote:
>> On Thu, Feb 09, 2017 at 10:12:41AM +0100, Edgar E. Iglesias wrote:
>> > On Wed, Feb 08, 2017 at 05:20:44PM -0800, Stefano Stabellini wrote:
>> > > On Thu, 9 Feb 2017, Julien Grall wrote:
>> > > > On 08/02/2017 23:28, Tamas K Lengyel wrote:
>> > > > > On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
>> > > > > > Hi Tamas,
>> > > > > >
>> > > > > > Can you please try to configure your e-mail client to use '>' rather than
>> > > > > > '
>> > > > > > '? It makes quite hard to read the e-mail.
>> > > > >
>> > > > > Hm, not sure why it switched but should be fine now.
>> > > > >
>> > > > > > On 08/02/2017 20:15, Tamas K Lengyel wrote:
>> > > > > > >
>> > > > > > >
>> > > > > > >
>> > > > > > > On Wed, Feb 8, 2017 at 12:40 PM, Edgar E. Iglesias
>> > > > > > > <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
>> > > > > > >     On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:
>> > > > > >
>> > > > > >
>> > > > > > >     If platform_hvc() consumes an SMC, it's considered part of the Xen
>> > > > > > > API.
>> > > > > > >     Visible but not filterable by a monitor.
>> > > > > > >
>> > > > > > >
>> > > > > > >     Platforms can then dictate which SMC calls are better handled within
>> > > > > > >     Xen and
>> > > > > > >     which ones can be exposed to dom0 user-space.
>> > > > > > >
>> > > > > > >     In addition, there could be a hypercall to disable platform specific
>> > > > > > >     handling
>> > > > > > >     in Xen alltogether for a given guest. Then everything goes to dom0
>> > > > > > >     user-space.
>> > > > > > >
>> > > > > > >     It's a little messy...
>> > > > > > >
>> > > > > > >
>> > > > > > >
>> > > > > > > That is messy and I would not want any SMCs reaching the firmware when
>> > > > > > > the monitor application is in use. The monitor interface is disabled by
>> > > > > > > default and there aren't any known usecases where the SMC has to reach
>> > > > > > > both the firmware and the monitor application as well. So I think it is
>> > > > > > > safe to just make the two things mutually exclusive.
>> > > > > >
>> > > > > >
>> > > > > > If you look at the SMC Calling Convention [1] both HVC and SMC are
>> > > > > > considered a conduit for service call to the secure firmware or
>> > > > > > hypervisor.
>> > > > > > It would be up to the hypervisor deciding what to do.
>> > > > > >
>> > > > > > Lets imagine the guest is deciding to use HVC to access the secure
>> > > > > > firmware
>> > > > > > (AFAIU this patch series is adding that), are you going to monitor all the
>> > > > > > HVCs (including hypercall)?
>> > > > >
>> > > > > There are some fundamental differences between HVC and SMC calls
>> > > > > though. An HVC can only land in the hypervisor, so as a hypercall, I
>> > > > > would expect it to be something I can deny via XSM. That is a
>> > > > > sufficient option for now to block the path to the firmware. If we end
>> > > > > up needing to support an application that uses that hypercall for
>> > > > > something critical, then yes, it would also need to be hooked into the
>> > > > > monitor system. At the moment this is not necessary.
>> > > >
>> > > > My point is not about what is necessary at the moment. But what is right
>> > > > things to do. If you look at the spec, HVC are not only for hypercall, but any
>> > > > other kind of services. Why would you deny something that is valid from the
>> > > > specification (see 5.2.1)?
>> > > >
>> > > > "The SMC calling convention, however, does not specify which instruction
>> > > > (either SMC or HVC) to use to invoke a
>> > > > particular service."
>> > >
>> > > To have a generic solution, we need a way to specify a set of HVC/SMC
>> > > calls that get monitored and a set that get handled in Xen (platform
>> > > specific or otherwise). I think it is OK not to do both, at least at the
>> > > beginning, but we might want to add that feature in the future.
>> > >
>> > > As much as I would like to see that, in respect to this series, I don't
>> > > think we should ask Edgar to introduce such a mechanism. However, we do
>> > > need to decide what Xen should do when platform_hvc is implemented and
>> > > monitor is also enabled.
>> > >
>> > > I think the default should be to only call platform_hvc, because there
>> > > are many valid monitoring use-cases which don't require those few
>> > > platform specific SMC/HVC calls to be forwarded to the monitor.
>> > >
>> > > However, if we did that, we would break Tamas' scenario. Thus, I suggest
>> > > we also introduce a simple compile time option or Xen command line
>> > > option to forward all platform_hvc calls to the monitor instead of
>> > > implementing them in Xen. Something like "MONITOR_OVERRIDE". In the
>> > > future, we can replace it with a more generic framework to dynamically
>> > > configure at runtime which SMC/HVC calls get forwarded.
>> > >
>> > > What do you think?
>> >
>> > This could work in some scenarios, but for example on the ZynqMP,
>> > dom0 needs access to Firmware as it boots, otherwise a lot of I/O
>> > will end up non-functional (with recent kernels). Anyway, I think it
>> > would give us a path forward. Future patches could either implement
>> > finer control or something else.
>>
>> Actually, MONITOR_OVERRIDE could allow dom0 full access to the Firmware
>> and only block guests. That would work better on the ZynqMP. I probably
>> overlooked this in your suggestion.
>
> Yes, the intention is to allow Dom0 full access to the firmware by
> default, even when memory introspection is enabled. The MONITOR_OVERRIDE
> tunable would change that, but would need to be explicitly enabled.

In principle I have nothing against a command line option, but I don't
really follow how that would help. The monitor system is disabled by
default for all domains, so there is no problem with dom0 booting or
any other domain needing to access the firmware. You specifically have
to enable the monitoring for domains. Why is it a problem to have it
be exclusive for just those domains where it is enabled?

Tamas

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-09 18:11                           ` Tamas K Lengyel
@ 2017-02-09 18:39                             ` Julien Grall
  2017-02-09 19:42                               ` Tamas K Lengyel
  0 siblings, 1 reply; 44+ messages in thread
From: Julien Grall @ 2017-02-09 18:39 UTC (permalink / raw)
  To: Tamas K Lengyel
  Cc: Edgar E. Iglesias, Edgar E. Iglesias, Stefano Stabellini,
	Volodymyr Babchuk, Xen-devel

Hi Tamas,

On 02/09/2017 06:11 PM, Tamas K Lengyel wrote:
> On Wed, Feb 8, 2017 at 5:08 PM, Julien Grall <julien.grall@arm.com> wrote:
>> On 08/02/2017 23:28, Tamas K Lengyel wrote:
>>> On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
>> You haven't understood my point. Xen is currently emulating PSCI call for
>> the guest to allow powering up and down the CPUs and other stuff. If you
>> decide to trap all the SMCs, you would have to handle them.
>
> Sure, it's more work on the monitor side, but other then that, what's
> the problem?

Because you will have to introduce hypercalls to get all the necessary 
information from Xen that will not be available from outside.

Given that SMC has been designed to target different services (PSCI, 
Trusted OS...) it would be normal to have monitor app only monitoring a 
certain set of SMC call. You cannot deny a such use case as it would 
avoid an monitor app to handle every single call that would be consumed 
by XEN but not forwarded to the secure firmware.

>
>>
>> And yes it is emulation as you don't seem to be willing passing those SMC to
>> the firmware or even back to Xen. If we expect a VM to emulate a trusted
>> firmware, then you have a security problem. Some hardware may be only
>> accessible through the secure world and I doubt some trusted app vendor will
>> be willing to move cryptography stuff in non secure world. I would highly
>> recommend to skim through the OP-TEE thread, it will provide you some
>> insights of the constraints.
>
> The firmware is not hardware, it's just a piece of code that has been
> baked into the board in some manner. Emulation in my book is doing in
> software what hardware is supposed to do. I don't expect all vendors
> to be happy to move their proprietary whatever to a VM. Again, this is
> an experimental setup with no real world applications at the moment.
> As for certain hardware being only accessible from the TZ, in that
> case the monitor application would have to call into the firmware. My
> setup doesn't prohibit using the TZ, it just prohibits it being
> accessible from untrusted guests directly.

To be honest, I am not here to criticize your project or else. I am just 
trying to explain you there are other potential use cases and we should 
not ignore them.

I am also not expecting none of the person involved in the thread to 
write the code now. However, it is always good to have a full view and 
get a direction how it should go.

Cheers,

-- 
Julien Grall

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-09 18:25                                   ` Tamas K Lengyel
@ 2017-02-09 18:43                                     ` Stefano Stabellini
  2017-02-09 19:32                                       ` Tamas K Lengyel
  0 siblings, 1 reply; 44+ messages in thread
From: Stefano Stabellini @ 2017-02-09 18:43 UTC (permalink / raw)
  To: Tamas K Lengyel
  Cc: Edgar E. Iglesias, Stefano Stabellini, Volodymyr Babchuk,
	Xen-devel, Julien Grall, Edgar E. Iglesias

On Thu, 9 Feb 2017, Tamas K Lengyel wrote:
> On Thu, Feb 9, 2017 at 11:22 AM, Stefano Stabellini
> <sstabellini@kernel.org> wrote:
> > On Thu, 9 Feb 2017, Edgar E. Iglesias wrote:
> >> On Thu, Feb 09, 2017 at 10:12:41AM +0100, Edgar E. Iglesias wrote:
> >> > On Wed, Feb 08, 2017 at 05:20:44PM -0800, Stefano Stabellini wrote:
> >> > > On Thu, 9 Feb 2017, Julien Grall wrote:
> >> > > > On 08/02/2017 23:28, Tamas K Lengyel wrote:
> >> > > > > On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
> >> > > > > > Hi Tamas,
> >> > > > > >
> >> > > > > > Can you please try to configure your e-mail client to use '>' rather than
> >> > > > > > '
> >> > > > > > '? It makes quite hard to read the e-mail.
> >> > > > >
> >> > > > > Hm, not sure why it switched but should be fine now.
> >> > > > >
> >> > > > > > On 08/02/2017 20:15, Tamas K Lengyel wrote:
> >> > > > > > >
> >> > > > > > >
> >> > > > > > >
> >> > > > > > > On Wed, Feb 8, 2017 at 12:40 PM, Edgar E. Iglesias
> >> > > > > > > <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
> >> > > > > > >     On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:
> >> > > > > >
> >> > > > > >
> >> > > > > > >     If platform_hvc() consumes an SMC, it's considered part of the Xen
> >> > > > > > > API.
> >> > > > > > >     Visible but not filterable by a monitor.
> >> > > > > > >
> >> > > > > > >
> >> > > > > > >     Platforms can then dictate which SMC calls are better handled within
> >> > > > > > >     Xen and
> >> > > > > > >     which ones can be exposed to dom0 user-space.
> >> > > > > > >
> >> > > > > > >     In addition, there could be a hypercall to disable platform specific
> >> > > > > > >     handling
> >> > > > > > >     in Xen alltogether for a given guest. Then everything goes to dom0
> >> > > > > > >     user-space.
> >> > > > > > >
> >> > > > > > >     It's a little messy...
> >> > > > > > >
> >> > > > > > >
> >> > > > > > >
> >> > > > > > > That is messy and I would not want any SMCs reaching the firmware when
> >> > > > > > > the monitor application is in use. The monitor interface is disabled by
> >> > > > > > > default and there aren't any known usecases where the SMC has to reach
> >> > > > > > > both the firmware and the monitor application as well. So I think it is
> >> > > > > > > safe to just make the two things mutually exclusive.
> >> > > > > >
> >> > > > > >
> >> > > > > > If you look at the SMC Calling Convention [1] both HVC and SMC are
> >> > > > > > considered a conduit for service call to the secure firmware or
> >> > > > > > hypervisor.
> >> > > > > > It would be up to the hypervisor deciding what to do.
> >> > > > > >
> >> > > > > > Lets imagine the guest is deciding to use HVC to access the secure
> >> > > > > > firmware
> >> > > > > > (AFAIU this patch series is adding that), are you going to monitor all the
> >> > > > > > HVCs (including hypercall)?
> >> > > > >
> >> > > > > There are some fundamental differences between HVC and SMC calls
> >> > > > > though. An HVC can only land in the hypervisor, so as a hypercall, I
> >> > > > > would expect it to be something I can deny via XSM. That is a
> >> > > > > sufficient option for now to block the path to the firmware. If we end
> >> > > > > up needing to support an application that uses that hypercall for
> >> > > > > something critical, then yes, it would also need to be hooked into the
> >> > > > > monitor system. At the moment this is not necessary.
> >> > > >
> >> > > > My point is not about what is necessary at the moment. But what is right
> >> > > > things to do. If you look at the spec, HVC are not only for hypercall, but any
> >> > > > other kind of services. Why would you deny something that is valid from the
> >> > > > specification (see 5.2.1)?
> >> > > >
> >> > > > "The SMC calling convention, however, does not specify which instruction
> >> > > > (either SMC or HVC) to use to invoke a
> >> > > > particular service."
> >> > >
> >> > > To have a generic solution, we need a way to specify a set of HVC/SMC
> >> > > calls that get monitored and a set that get handled in Xen (platform
> >> > > specific or otherwise). I think it is OK not to do both, at least at the
> >> > > beginning, but we might want to add that feature in the future.
> >> > >
> >> > > As much as I would like to see that, in respect to this series, I don't
> >> > > think we should ask Edgar to introduce such a mechanism. However, we do
> >> > > need to decide what Xen should do when platform_hvc is implemented and
> >> > > monitor is also enabled.
> >> > >
> >> > > I think the default should be to only call platform_hvc, because there
> >> > > are many valid monitoring use-cases which don't require those few
> >> > > platform specific SMC/HVC calls to be forwarded to the monitor.
> >> > >
> >> > > However, if we did that, we would break Tamas' scenario. Thus, I suggest
> >> > > we also introduce a simple compile time option or Xen command line
> >> > > option to forward all platform_hvc calls to the monitor instead of
> >> > > implementing them in Xen. Something like "MONITOR_OVERRIDE". In the
> >> > > future, we can replace it with a more generic framework to dynamically
> >> > > configure at runtime which SMC/HVC calls get forwarded.
> >> > >
> >> > > What do you think?
> >> >
> >> > This could work in some scenarios, but for example on the ZynqMP,
> >> > dom0 needs access to Firmware as it boots, otherwise a lot of I/O
> >> > will end up non-functional (with recent kernels). Anyway, I think it
> >> > would give us a path forward. Future patches could either implement
> >> > finer control or something else.
> >>
> >> Actually, MONITOR_OVERRIDE could allow dom0 full access to the Firmware
> >> and only block guests. That would work better on the ZynqMP. I probably
> >> overlooked this in your suggestion.
> >
> > Yes, the intention is to allow Dom0 full access to the firmware by
> > default, even when memory introspection is enabled. The MONITOR_OVERRIDE
> > tunable would change that, but would need to be explicitly enabled.
> 
> In principle I have nothing against a command line option, but I don't
> really follow how that would help. The monitor system is disabled by
> default for all domains, so there is no problem with dom0 booting or
> any other domain needing to access the firmware. You specifically have
> to enable the monitoring for domains. Why is it a problem to have it
> be exclusive for just those domains where it is enabled?

I am suggesting this solution because I expect many use-cases for memory
introspection that don't actually require any platform_hvc events to be
monitored at all. On the other end, I expect that on platforms where
platform_hvc is implemented, such as the ZynqMP, those calls are
important and should be handled in Xen in most cases.

Looking at the code, does monitor.privileged_call_enabled only cover
SMC? Is monitor.privileged_call_enabled disabled by default?
If so, monitor.privileged_call_enabled could be the tunable I was
talking about. As long as enabling memory introspection doesn't
automatically forward platform_hvc events to the monitor, I am fine with
it.

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-09 18:43                                     ` Stefano Stabellini
@ 2017-02-09 19:32                                       ` Tamas K Lengyel
  2017-07-31 22:23                                         ` Edgar E. Iglesias
  0 siblings, 1 reply; 44+ messages in thread
From: Tamas K Lengyel @ 2017-02-09 19:32 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: Edgar E. Iglesias, Edgar E. Iglesias, Julien Grall,
	Volodymyr Babchuk, Xen-devel

On Thu, Feb 9, 2017 at 11:43 AM, Stefano Stabellini
<sstabellini@kernel.org> wrote:
> On Thu, 9 Feb 2017, Tamas K Lengyel wrote:
>> On Thu, Feb 9, 2017 at 11:22 AM, Stefano Stabellini
>> <sstabellini@kernel.org> wrote:
>> > On Thu, 9 Feb 2017, Edgar E. Iglesias wrote:
>> >> On Thu, Feb 09, 2017 at 10:12:41AM +0100, Edgar E. Iglesias wrote:
>> >> > On Wed, Feb 08, 2017 at 05:20:44PM -0800, Stefano Stabellini wrote:
>> >> > > On Thu, 9 Feb 2017, Julien Grall wrote:
>> >> > > > On 08/02/2017 23:28, Tamas K Lengyel wrote:
>> >> > > > > On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
>> >> > > > > > Hi Tamas,
>> >> > > > > >
>> >> > > > > > Can you please try to configure your e-mail client to use '>' rather than
>> >> > > > > > '
>> >> > > > > > '? It makes quite hard to read the e-mail.
>> >> > > > >
>> >> > > > > Hm, not sure why it switched but should be fine now.
>> >> > > > >
>> >> > > > > > On 08/02/2017 20:15, Tamas K Lengyel wrote:
>> >> > > > > > >
>> >> > > > > > >
>> >> > > > > > >
>> >> > > > > > > On Wed, Feb 8, 2017 at 12:40 PM, Edgar E. Iglesias
>> >> > > > > > > <edgar.iglesias@gmail.com <mailto:edgar.iglesias@gmail.com>> wrote:
>> >> > > > > > >     On Wed, Feb 08, 2017 at 06:29:13PM +0100, Edgar E. Iglesias wrote:
>> >> > > > > >
>> >> > > > > >
>> >> > > > > > >     If platform_hvc() consumes an SMC, it's considered part of the Xen
>> >> > > > > > > API.
>> >> > > > > > >     Visible but not filterable by a monitor.
>> >> > > > > > >
>> >> > > > > > >
>> >> > > > > > >     Platforms can then dictate which SMC calls are better handled within
>> >> > > > > > >     Xen and
>> >> > > > > > >     which ones can be exposed to dom0 user-space.
>> >> > > > > > >
>> >> > > > > > >     In addition, there could be a hypercall to disable platform specific
>> >> > > > > > >     handling
>> >> > > > > > >     in Xen alltogether for a given guest. Then everything goes to dom0
>> >> > > > > > >     user-space.
>> >> > > > > > >
>> >> > > > > > >     It's a little messy...
>> >> > > > > > >
>> >> > > > > > >
>> >> > > > > > >
>> >> > > > > > > That is messy and I would not want any SMCs reaching the firmware when
>> >> > > > > > > the monitor application is in use. The monitor interface is disabled by
>> >> > > > > > > default and there aren't any known usecases where the SMC has to reach
>> >> > > > > > > both the firmware and the monitor application as well. So I think it is
>> >> > > > > > > safe to just make the two things mutually exclusive.
>> >> > > > > >
>> >> > > > > >
>> >> > > > > > If you look at the SMC Calling Convention [1] both HVC and SMC are
>> >> > > > > > considered a conduit for service call to the secure firmware or
>> >> > > > > > hypervisor.
>> >> > > > > > It would be up to the hypervisor deciding what to do.
>> >> > > > > >
>> >> > > > > > Lets imagine the guest is deciding to use HVC to access the secure
>> >> > > > > > firmware
>> >> > > > > > (AFAIU this patch series is adding that), are you going to monitor all the
>> >> > > > > > HVCs (including hypercall)?
>> >> > > > >
>> >> > > > > There are some fundamental differences between HVC and SMC calls
>> >> > > > > though. An HVC can only land in the hypervisor, so as a hypercall, I
>> >> > > > > would expect it to be something I can deny via XSM. That is a
>> >> > > > > sufficient option for now to block the path to the firmware. If we end
>> >> > > > > up needing to support an application that uses that hypercall for
>> >> > > > > something critical, then yes, it would also need to be hooked into the
>> >> > > > > monitor system. At the moment this is not necessary.
>> >> > > >
>> >> > > > My point is not about what is necessary at the moment. But what is right
>> >> > > > things to do. If you look at the spec, HVC are not only for hypercall, but any
>> >> > > > other kind of services. Why would you deny something that is valid from the
>> >> > > > specification (see 5.2.1)?
>> >> > > >
>> >> > > > "The SMC calling convention, however, does not specify which instruction
>> >> > > > (either SMC or HVC) to use to invoke a
>> >> > > > particular service."
>> >> > >
>> >> > > To have a generic solution, we need a way to specify a set of HVC/SMC
>> >> > > calls that get monitored and a set that get handled in Xen (platform
>> >> > > specific or otherwise). I think it is OK not to do both, at least at the
>> >> > > beginning, but we might want to add that feature in the future.
>> >> > >
>> >> > > As much as I would like to see that, in respect to this series, I don't
>> >> > > think we should ask Edgar to introduce such a mechanism. However, we do
>> >> > > need to decide what Xen should do when platform_hvc is implemented and
>> >> > > monitor is also enabled.
>> >> > >
>> >> > > I think the default should be to only call platform_hvc, because there
>> >> > > are many valid monitoring use-cases which don't require those few
>> >> > > platform specific SMC/HVC calls to be forwarded to the monitor.
>> >> > >
>> >> > > However, if we did that, we would break Tamas' scenario. Thus, I suggest
>> >> > > we also introduce a simple compile time option or Xen command line
>> >> > > option to forward all platform_hvc calls to the monitor instead of
>> >> > > implementing them in Xen. Something like "MONITOR_OVERRIDE". In the
>> >> > > future, we can replace it with a more generic framework to dynamically
>> >> > > configure at runtime which SMC/HVC calls get forwarded.
>> >> > >
>> >> > > What do you think?
>> >> >
>> >> > This could work in some scenarios, but for example on the ZynqMP,
>> >> > dom0 needs access to Firmware as it boots, otherwise a lot of I/O
>> >> > will end up non-functional (with recent kernels). Anyway, I think it
>> >> > would give us a path forward. Future patches could either implement
>> >> > finer control or something else.
>> >>
>> >> Actually, MONITOR_OVERRIDE could allow dom0 full access to the Firmware
>> >> and only block guests. That would work better on the ZynqMP. I probably
>> >> overlooked this in your suggestion.
>> >
>> > Yes, the intention is to allow Dom0 full access to the firmware by
>> > default, even when memory introspection is enabled. The MONITOR_OVERRIDE
>> > tunable would change that, but would need to be explicitly enabled.
>>
>> In principle I have nothing against a command line option, but I don't
>> really follow how that would help. The monitor system is disabled by
>> default for all domains, so there is no problem with dom0 booting or
>> any other domain needing to access the firmware. You specifically have
>> to enable the monitoring for domains. Why is it a problem to have it
>> be exclusive for just those domains where it is enabled?
>
> I am suggesting this solution because I expect many use-cases for memory
> introspection that don't actually require any platform_hvc events to be
> monitored at all. On the other end, I expect that on platforms where
> platform_hvc is implemented, such as the ZynqMP, those calls are
> important and should be handled in Xen in most cases.
>
> Looking at the code, does monitor.privileged_call_enabled only cover
> SMC? Is monitor.privileged_call_enabled disabled by default?
> If so, monitor.privileged_call_enabled could be the tunable I was
> talking about. As long as enabling memory introspection doesn't
> automatically forward platform_hvc events to the monitor, I am fine with
> it.

Yes, monitor.privileged_call_enabled only covers SMCs right now and it
is disabled by default. It has to be enabled specifically for a
domain.  Memory introspection is separate from this, that is handled
by the mem_access system and it can be enabled separately from SMC
monitoring.

As for hypercalls that get handled by Xen, I don't really need to
monitor those. If Xen would on the other hand go and call some
firmware as a result of the hypercall, I would need to be able to deny
that. So as long as XSM can be used to control HVC calls, that works
for me just fine too.

Tamas

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-09 18:39                             ` Julien Grall
@ 2017-02-09 19:42                               ` Tamas K Lengyel
  2017-02-09 20:01                                 ` Edgar E. Iglesias
  0 siblings, 1 reply; 44+ messages in thread
From: Tamas K Lengyel @ 2017-02-09 19:42 UTC (permalink / raw)
  To: Julien Grall
  Cc: Edgar E. Iglesias, Edgar E. Iglesias, Stefano Stabellini,
	Volodymyr Babchuk, Xen-devel

On Thu, Feb 9, 2017 at 11:39 AM, Julien Grall <julien.grall@arm.com> wrote:
> Hi Tamas,
>
> On 02/09/2017 06:11 PM, Tamas K Lengyel wrote:
>>
>> On Wed, Feb 8, 2017 at 5:08 PM, Julien Grall <julien.grall@arm.com> wrote:
>>>
>>> On 08/02/2017 23:28, Tamas K Lengyel wrote:
>>>>
>>>> On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com>
>>>> wrote:
>>>
>>> You haven't understood my point. Xen is currently emulating PSCI call for
>>> the guest to allow powering up and down the CPUs and other stuff. If you
>>> decide to trap all the SMCs, you would have to handle them.
>>
>>
>> Sure, it's more work on the monitor side, but other then that, what's
>> the problem?
>
>
> Because you will have to introduce hypercalls to get all the necessary
> information from Xen that will not be available from outside.
>
> Given that SMC has been designed to target different services (PSCI, Trusted
> OS...) it would be normal to have monitor app only monitoring a certain set
> of SMC call. You cannot deny a such use case as it would avoid an monitor
> app to handle every single call that would be consumed by XEN but not
> forwarded to the secure firmware.
>

I have nothing against introducing a fine-tune option to the SMC
monitoring system so the monitor app can determine if it wants all
SMCs or only a subset. At the moment I don't know of any usecase that
would require this option. I certainly don't need it. If this option
gets implemented by someone, I would be happy to take it.

Tamas

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-09 19:42                               ` Tamas K Lengyel
@ 2017-02-09 20:01                                 ` Edgar E. Iglesias
  2017-02-09 20:36                                   ` Tamas K Lengyel
  0 siblings, 1 reply; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-02-09 20:01 UTC (permalink / raw)
  To: Tamas K Lengyel
  Cc: Volodymyr Babchuk, Edgar E. Iglesias, Julien Grall,
	Stefano Stabellini, Xen-devel

On Thu, Feb 09, 2017 at 12:42:09PM -0700, Tamas K Lengyel wrote:
> On Thu, Feb 9, 2017 at 11:39 AM, Julien Grall <julien.grall@arm.com> wrote:
> > Hi Tamas,
> >
> > On 02/09/2017 06:11 PM, Tamas K Lengyel wrote:
> >>
> >> On Wed, Feb 8, 2017 at 5:08 PM, Julien Grall <julien.grall@arm.com> wrote:
> >>>
> >>> On 08/02/2017 23:28, Tamas K Lengyel wrote:
> >>>>
> >>>> On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com>
> >>>> wrote:
> >>>
> >>> You haven't understood my point. Xen is currently emulating PSCI call for
> >>> the guest to allow powering up and down the CPUs and other stuff. If you
> >>> decide to trap all the SMCs, you would have to handle them.
> >>
> >>
> >> Sure, it's more work on the monitor side, but other then that, what's
> >> the problem?
> >
> >
> > Because you will have to introduce hypercalls to get all the necessary
> > information from Xen that will not be available from outside.
>
> > Given that SMC has been designed to target different services (PSCI, Trusted
> > OS...) it would be normal to have monitor app only monitoring a certain set
> > of SMC call. You cannot deny a such use case as it would avoid an monitor
> > app to handle every single call that would be consumed by XEN but not
> > forwarded to the secure firmware.
> >
> 
> I have nothing against introducing a fine-tune option to the SMC
> monitoring system so the monitor app can determine if it wants all
> SMCs or only a subset. At the moment I don't know of any usecase that
> would require this option. I certainly don't need it. If this option
> gets implemented by someone, I would be happy to take it.

Well, the reason it would be useful is the other way around.
On for example ZynqMP, enabling the monitor is useless since it will
turn off the ability to use the vital FW APIs needed for device
passthrough.

So the monitor only works for PV guests that call SMC APIs to some
imaginary Firmware.

While a monitor that didn't insist in consuming all SMC calls,
could very well be useful for monitoring/tracing purposes or
other stuff even with guests that actually use a "real" FW API.

I don't think we need to implement support for the latter right away,
we can incrementally add support for these things (I hope).

Cheers,
Edgar





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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-09 20:01                                 ` Edgar E. Iglesias
@ 2017-02-09 20:36                                   ` Tamas K Lengyel
  0 siblings, 0 replies; 44+ messages in thread
From: Tamas K Lengyel @ 2017-02-09 20:36 UTC (permalink / raw)
  To: Edgar E. Iglesias
  Cc: Volodymyr Babchuk, Edgar E. Iglesias, Julien Grall,
	Stefano Stabellini, Xen-devel

On Thu, Feb 9, 2017 at 1:01 PM, Edgar E. Iglesias
<edgar.iglesias@xilinx.com> wrote:
> On Thu, Feb 09, 2017 at 12:42:09PM -0700, Tamas K Lengyel wrote:
>> On Thu, Feb 9, 2017 at 11:39 AM, Julien Grall <julien.grall@arm.com> wrote:
>> > Hi Tamas,
>> >
>> > On 02/09/2017 06:11 PM, Tamas K Lengyel wrote:
>> >>
>> >> On Wed, Feb 8, 2017 at 5:08 PM, Julien Grall <julien.grall@arm.com> wrote:
>> >>>
>> >>> On 08/02/2017 23:28, Tamas K Lengyel wrote:
>> >>>>
>> >>>> On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com>
>> >>>> wrote:
>> >>>
>> >>> You haven't understood my point. Xen is currently emulating PSCI call for
>> >>> the guest to allow powering up and down the CPUs and other stuff. If you
>> >>> decide to trap all the SMCs, you would have to handle them.
>> >>
>> >>
>> >> Sure, it's more work on the monitor side, but other then that, what's
>> >> the problem?
>> >
>> >
>> > Because you will have to introduce hypercalls to get all the necessary
>> > information from Xen that will not be available from outside.
>>
>> > Given that SMC has been designed to target different services (PSCI, Trusted
>> > OS...) it would be normal to have monitor app only monitoring a certain set
>> > of SMC call. You cannot deny a such use case as it would avoid an monitor
>> > app to handle every single call that would be consumed by XEN but not
>> > forwarded to the secure firmware.
>> >
>>
>> I have nothing against introducing a fine-tune option to the SMC
>> monitoring system so the monitor app can determine if it wants all
>> SMCs or only a subset. At the moment I don't know of any usecase that
>> would require this option. I certainly don't need it. If this option
>> gets implemented by someone, I would be happy to take it.
>
> Well, the reason it would be useful is the other way around.
> On for example ZynqMP, enabling the monitor is useless since it will
> turn off the ability to use the vital FW APIs needed for device
> passthrough.
>
> So the monitor only works for PV guests that call SMC APIs to some
> imaginary Firmware.
>
> While a monitor that didn't insist in consuming all SMC calls,
> could very well be useful for monitoring/tracing purposes or
> other stuff even with guests that actually use a "real" FW API.
>
> I don't think we need to implement support for the latter right away,
> we can incrementally add support for these things (I hope).
>

Certainly, as I said I have nothing against adding such a feature. All
I'm saying is that I don't know of any usecase that requires that
option at the moment, so I would be OK with just making the two
exclusive. If someone finds the time to implement such fine-tuning,
I'm all for it.

Tamas

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

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

* Re: [RFC v2 1/6] xen/arm: traps: Reorder early overwrite of FID
  2017-02-07 19:42 ` [RFC v2 1/6] xen/arm: traps: Reorder early overwrite of FID Edgar E. Iglesias
@ 2017-02-13 22:06   ` Stefano Stabellini
  0 siblings, 0 replies; 44+ messages in thread
From: Stefano Stabellini @ 2017-02-13 22:06 UTC (permalink / raw)
  To: Edgar E. Iglesias; +Cc: edgar.iglesias, julien.grall, sstabellini, xen-devel

On Tue, 7 Feb 2017, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
> 
> Move the early setting of PSCI_RESULT_REG to a later stage
> avoiding the early override of the FID that's stored in
> the same register.
> 
> No functional change.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


>  xen/arch/arm/traps.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index 92b1d80..c5a4d41 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -1335,8 +1335,6 @@ static void do_trap_psci(struct cpu_user_regs *regs)
>  {
>      register_t fid = PSCI_ARG(regs,0);
>  
> -    /* preloading in case psci_mode_check fails */
> -    PSCI_RESULT_REG(regs) = PSCI_INVALID_PARAMETERS;
>      switch( fid )
>      {
>      case PSCI_cpu_off:
> @@ -1369,6 +1367,7 @@ static void do_trap_psci(struct cpu_user_regs *regs)
>      case PSCI_0_2_FN_MIGRATE_INFO_UP_CPU:
>      case PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU:
>          perfc_incr(vpsci_migrate_info_up_cpu);
> +        PSCI_RESULT_REG(regs) = PSCI_INVALID_PARAMETERS;
>          if ( psci_mode_check(current->domain, fid) )
>              PSCI_RESULT_REG(regs) = do_psci_0_2_migrate_info_up_cpu();
>          break;
> @@ -1385,6 +1384,7 @@ static void do_trap_psci(struct cpu_user_regs *regs)
>      case PSCI_0_2_FN_CPU_ON:
>      case PSCI_0_2_FN64_CPU_ON:
>          perfc_incr(vpsci_cpu_on);
> +        PSCI_RESULT_REG(regs) = PSCI_INVALID_PARAMETERS;
>          if ( psci_mode_check(current->domain, fid) )
>          {
>              register_t vcpuid = PSCI_ARG(regs,1);
> @@ -1397,6 +1397,7 @@ static void do_trap_psci(struct cpu_user_regs *regs)
>      case PSCI_0_2_FN_CPU_SUSPEND:
>      case PSCI_0_2_FN64_CPU_SUSPEND:
>          perfc_incr(vpsci_cpu_suspend);
> +        PSCI_RESULT_REG(regs) = PSCI_INVALID_PARAMETERS;
>          if ( psci_mode_check(current->domain, fid) )
>          {
>              uint32_t pstate = PSCI_ARG32(regs,1);
> @@ -1409,6 +1410,7 @@ static void do_trap_psci(struct cpu_user_regs *regs)
>      case PSCI_0_2_FN_AFFINITY_INFO:
>      case PSCI_0_2_FN64_AFFINITY_INFO:
>          perfc_incr(vpsci_cpu_affinity_info);
> +        PSCI_RESULT_REG(regs) = PSCI_INVALID_PARAMETERS;
>          if ( psci_mode_check(current->domain, fid) )
>          {
>              register_t taff = PSCI_ARG(regs,1);
> @@ -1420,6 +1422,7 @@ static void do_trap_psci(struct cpu_user_regs *regs)
>      case PSCI_0_2_FN_MIGRATE:
>      case PSCI_0_2_FN64_MIGRATE:
>          perfc_incr(vpsci_cpu_migrate);
> +        PSCI_RESULT_REG(regs) = PSCI_INVALID_PARAMETERS;
>          if ( psci_mode_check(current->domain, fid) )
>          {
>              uint32_t tcpu = PSCI_ARG32(regs,1);
> -- 
> 2.7.4
> 

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

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

* Re: [RFC v2 2/6] xen/arm: Introduce platform_hvc
  2017-02-07 19:42 ` [RFC v2 2/6] xen/arm: Introduce platform_hvc Edgar E. Iglesias
@ 2017-02-13 22:08   ` Stefano Stabellini
  2017-07-31 21:30     ` Edgar E. Iglesias
  0 siblings, 1 reply; 44+ messages in thread
From: Stefano Stabellini @ 2017-02-13 22:08 UTC (permalink / raw)
  To: Edgar E. Iglesias; +Cc: edgar.iglesias, julien.grall, sstabellini, xen-devel

On Tue, 7 Feb 2017, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
> 
> Introduce platform_hvc as a way to handle hypercalls that
> Xen does not know about in a platform specific way. This
> is particularly useful for implementing the SiP (SoC
> implementation specific) service calls.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> ---
>  xen/arch/arm/platform.c        | 8 ++++++++
>  xen/arch/arm/traps.c           | 3 +++
>  xen/include/asm-arm/platform.h | 5 +++++
>  3 files changed, 16 insertions(+)
> 
> diff --git a/xen/arch/arm/platform.c b/xen/arch/arm/platform.c
> index 0af6d57..90ea6b8 100644
> --- a/xen/arch/arm/platform.c
> +++ b/xen/arch/arm/platform.c
> @@ -127,6 +127,14 @@ void platform_poweroff(void)
>          platform->poweroff();
>  }
>  
> +bool platform_hvc(struct cpu_user_regs *regs)

This is fine, but we need a different name for it, as it can be used to
handle both HVC and SMC calls. Maybe "firmware_call"?


> +{
> +    if ( platform && platform->hvc )
> +        return platform->hvc(regs);
> +
> +    return false;
> +}
> +
>  bool_t platform_has_quirk(uint32_t quirk)
>  {
>      uint32_t quirks = 0;
> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index c5a4d41..33950d9 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -44,6 +44,7 @@
>  #include <asm/cpufeature.h>
>  #include <asm/flushtlb.h>
>  #include <asm/monitor.h>
> +#include <asm/platform.h>
>  
>  #include "decode.h"
>  #include "vtimer.h"
> @@ -1430,6 +1431,8 @@ static void do_trap_psci(struct cpu_user_regs *regs)
>          }
>          break;
>      default:
> +        if ( platform_hvc(regs) )
> +                return;
>          domain_crash_synchronous();
>          return;
>      }
> diff --git a/xen/include/asm-arm/platform.h b/xen/include/asm-arm/platform.h
> index 08010ba..4d51f0a 100644
> --- a/xen/include/asm-arm/platform.h
> +++ b/xen/include/asm-arm/platform.h
> @@ -26,6 +26,10 @@ struct platform_desc {
>      void (*reset)(void);
>      /* Platform power-off */
>      void (*poweroff)(void);
> +    /* Platform specific HVC handler.
> +     * Returns true if the call was handled and false if not.
> +     */
> +    bool (*hvc)(struct cpu_user_regs *regs);
>      /*
>       * Platform quirks
>       * Defined has a function because a platform can support multiple
> @@ -55,6 +59,7 @@ int platform_cpu_up(int cpu);
>  #endif
>  void platform_reset(void);
>  void platform_poweroff(void);
> +bool platform_hvc(struct cpu_user_regs *regs);
>  bool_t platform_has_quirk(uint32_t quirk);
>  bool_t platform_device_is_blacklisted(const struct dt_device_node *node);

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

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

* Re: [RFC v2 4/6] xen/arm: Introduce call_smcc64
  2017-02-07 19:42 ` [RFC v2 4/6] xen/arm: Introduce call_smcc64 Edgar E. Iglesias
@ 2017-02-13 22:11   ` Stefano Stabellini
  0 siblings, 0 replies; 44+ messages in thread
From: Stefano Stabellini @ 2017-02-13 22:11 UTC (permalink / raw)
  To: Edgar E. Iglesias; +Cc: edgar.iglesias, julien.grall, sstabellini, xen-devel

On Tue, 7 Feb 2017, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
> 
> Introduce call_smcc64, a helper function to issue 64-bit SMC
> calls that follow the SMC Calling Convention. This includes
> returning up to 4 64-bit values.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>

Please write it in assembly following the example of the exiting
call_smc.



>  xen/include/asm-arm/processor.h | 40 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
> 
> diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h
> index afc0e9a..a604f8c 100644
> --- a/xen/include/asm-arm/processor.h
> +++ b/xen/include/asm-arm/processor.h
> @@ -706,6 +706,46 @@ void vcpu_regs_user_to_hyp(struct vcpu *vcpu,
>  int call_smc(register_t function_id, register_t arg0, register_t arg1,
>               register_t arg2);
>  
> +/*
> + * Helper to issue a 64-bit SMC according to the SMC Calling Convention.
> + *
> + * @fid:      Function Identifier
> + * @a0 - a5:  6 arguments
> + * @ret:      Pointer to 4 register_t carrying return values
> + */
> +static inline register_t call_smcc64(register_t fid,
> +                                     register_t a0,
> +                                     register_t a1,
> +                                     register_t a2,
> +                                     register_t a3,
> +                                     register_t a4,
> +                                     register_t a5,
> +                                     register_t *ret)
> +{
> +    register register_t x0 asm("x0") = fid;
> +    register register_t x1 asm("x1") = a0;
> +    register register_t x2 asm("x2") = a1;
> +    register register_t x3 asm("x3") = a2;
> +    register register_t x4 asm("x4") = a3;
> +    register register_t x5 asm("x5") = a4;
> +    register register_t x6 asm("x6") = a5;
> +
> +    asm volatile ("smc #0\n"
> +                  : "+r" (x0), "+r" (x1), "+r" (x2), "+r" (x3),
> +                    "+r" (x4), "+r" (x5), "+r" (x6)
> +                  :
> +                  : "x7", "x8", "x9", "x10", "x11", "x12",
> +                    "x13", "x14", "x15", "x16", "x17" );
> +
> +    if (ret) {
> +        ret[0] = x0;
> +        ret[1] = x1;
> +        ret[2] = x2;
> +        ret[3] = x3;
> +    }
> +    return x0;
> +}
> +
>  void do_trap_guest_error(struct cpu_user_regs *regs);
>  
>  #endif /* __ASSEMBLY__ */
> -- 
> 2.7.4
> 

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

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

* Re: [RFC v2 5/6] xen/arm: zynqmp: Forward plaform specific firmware calls
  2017-02-07 19:42 ` [RFC v2 5/6] xen/arm: zynqmp: Forward plaform specific firmware calls Edgar E. Iglesias
@ 2017-02-14  0:02   ` Stefano Stabellini
  2017-02-17 18:47   ` Julien Grall
  1 sibling, 0 replies; 44+ messages in thread
From: Stefano Stabellini @ 2017-02-14  0:02 UTC (permalink / raw)
  To: Edgar E. Iglesias; +Cc: edgar.iglesias, julien.grall, sstabellini, xen-devel

On Tue, 7 Feb 2017, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
> 
> Implement an EEMI mediator and forward platform specific
> firmware calls from guests to firmware.
> 
> The EEMI mediator is responsible for implementing access
> controls modifying or blocking calls that try to operate
> on setup for devices that are not under the calling guest's
> control.
> 
> EEMI:
> https://www.xilinx.com/support/documentation/user_guides/ug1200-eemi-api.pdf
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> ---
>  xen/arch/arm/platforms/Makefile                    |   1 +
>  xen/arch/arm/platforms/xilinx-zynqmp-eemi.c        | 794 +++++++++++++++++++++
>  xen/arch/arm/platforms/xilinx-zynqmp.c             |  18 +
>  xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h | 337 +++++++++
>  xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h   | 284 ++++++++
>  5 files changed, 1434 insertions(+)
>  create mode 100644 xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
>  create mode 100644 xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h
>  create mode 100644 xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h
> 
> diff --git a/xen/arch/arm/platforms/Makefile b/xen/arch/arm/platforms/Makefile
> index 49fa683..b58b71f 100644
> --- a/xen/arch/arm/platforms/Makefile
> +++ b/xen/arch/arm/platforms/Makefile
> @@ -8,3 +8,4 @@ obj-$(CONFIG_ARM_64) += seattle.o
>  obj-$(CONFIG_ARM_32) += sunxi.o
>  obj-$(CONFIG_ARM_64) += xgene-storm.o
>  obj-$(CONFIG_ARM_64) += xilinx-zynqmp.o
> +obj-$(CONFIG_ARM_64) += xilinx-zynqmp-eemi.o
> diff --git a/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c b/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
> new file mode 100644
> index 0000000..c2c184d
> --- /dev/null
> +++ b/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
> @@ -0,0 +1,794 @@
> +/*
> + * xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
> + *
> + * Xilinx ZynqMP EEMI API mediator.
> + *
> + * Copyright (c) 2017 Xilinx Inc.
> + * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +/*
> + * Mediator for the EEMI Power Mangement API.
> + *
> + * Refs:
> + * https://www.xilinx.com/support/documentation/user_guides/ug1200-eemi-api.pdf
> + *
> + * Background:
> + * The ZynqMP has a subsystem named the PMU with a CPU and special devices
> + * dedicated to running Power Management Firmware. Other masters in the
> + * system need to send requests to the PMU in order to for example:
> + * * Manage power state
> + * * Configure clocks
> + * * Program bitstreams for the programmable logic
> + * * etc
> + *
> + * Allthough the details of the setup are configurable, in the common case
> + * the PMU lives in the Secure world. NS World cannot directly communicate
> + * with it and must use proxy services from ARM Trusted Firmware to reach
> + * the PMU.
> + *
> + * Power Management on the ZynqMP is implemented in a layered manner.
> + * The PMU knows about various masters and will enforce access controls
> + * based on a pre-configured partitioning. This configuration dictates
> + * which devices are owned by the various masters and the PMU FW makes sure
> + * that a given master cannot turn off a device that it does not own or that
> + * is in use by other masters.
> + *
> + * The PMU is not aware of multiple execution states in masters.
> + * For example, it treats the ARMv8 cores as single units and does not
> + * distinguish between Secure vs NS OS:s nor does it know about Hypervisors
> + * and multiple guests. It is up to software on the ARMv8 cores to present
> + * a unified view of its power requirements.
> + *
> + * To implement this unified view, ARM Trusted Firmware at EL3 provides
> + * access to the PM API via SMC calls. ARM Trusted Firmware is responsible
> + * for mediating between the Secure and the NS world, rejecting SMC calls
> + * that request changes that are not allowed.
> + *
> + * Xen running above ATF owns the NS world and is responsible for presenting
> + * unified PM requests taking all guests and the hypervisor into account.
> + *
> + * Implementation:
> + * The PM API contains different classes of calls.
> + * Certain calls are harmless to expose to any guest.
> + * These include calls to get the PM API Version, or to read out the version
> + * of the chip we're running on.
> + *
> + * Other calls are more problematic. Here're some:
> + * * Power requests for nodes (i.e turn on or off a given device)
> + * * Reset line control (i.e reset a given device)
> + * * MMIO access (i.e directly access clock and reset registers)
> + *
> + * Power requests for nodes:
> + * In order to correctly mediate these calls, we need to know if
> + * guests issuing these calls have ownership of the given device.
> + * The approach taken here is to map PM API Nodes identifying
> + * a device into base addresses for registers that belong to that
> + * same device.
> + *
> + * If the guest has access to a devices registers, we give the guest
> + * access to PM API calls that affect that device. This is implemented
> + * by pm_node_access and domain_has_node_access().
> + *
> + * Reset lines:
> + * Reset lines are identified by a list of identifiers that do not relate
> + * to device nodes. We can use the same approach here as for nodes, except
> + * that we need a separate table mapping reset lines to base addresses.
> + * This is implemented by pm_reset_access.
> + *
> + * MMIO access:
> + * These calls allow guests to access certain memory ranges. These ranges
> + * are typically protected for secure-world access only and also from
> + * certain masters only, so guests cannot access them directly.
> + * Registers within the memory regions affect certain nodes. In this case,
> + * our imput is an address and we map that address into a node. If the
          ^ input


> + * guest has ownership of that node, the access is allowed.
> + * Some registers contain bitfields and a single register may contain
> + * bits that affect multiple nodes.
> + *
> + * Some of the calls act on more global state. For example acting on
> + * NODE_PS, which affects many a lot of nodes. This higher level
> + * orchestrating is left for the hardware-domain only.
> + */
> +
> +#include <xen/iocap.h>
> +#include <asm/platform.h>
> +#include <asm/platforms/xilinx-zynqmp-eemi.h>
> +#include <asm/platforms/xilinx-zynqmp-mm.h>
> +
> +struct pm_access
> +{
> +    uint64_t addr;
> +    bool hwdom_access;    /* HW domain gets access regardless.  */

If the hardware domain gets access regardless, I don't think we need
this struct field, right? If fact, is_hardware_domain() is basically
used as a blank check in Xen. I would remove hwdom_access, use
is_hardware_domain() instead, and simply comment out any entries we
don't want dom0 to have access to.

For now that would be fine, but in the future we'll need a way to
prevent dom0 access to something, if it has been assigned to another
guest.


> +};
> +
> +/*
> + * This table maps a node into a memory address.
> + * If a guest has access to the address, it has enough control
> + * over the node to grant it access to EEMI calls for that node.
> + */
> +static const struct pm_access pm_node_access[] = {
> +    /* MM_RPU grants access to alll RPU Nodes.  */
                                   ^ all


> +    [NODE_RPU] = { MM_RPU },
> +    [NODE_RPU_0] = { MM_RPU },
> +    [NODE_RPU_1] = { MM_RPU },
> +    [NODE_IPI_RPU_0] = { MM_RPU },
> +
> +    /* GPU nodes.  */
> +    [NODE_GPU] = { MM_GPU },
> +    [NODE_GPU_PP_0] = { MM_GPU },
> +    [NODE_GPU_PP_1] = { MM_GPU },
> +
> +    [NODE_USB_0] = { MM_USB3_0 },
> +    [NODE_USB_1] = { MM_USB3_1 },
> +    [NODE_TTC_0] = { MM_TTC0 },
> +    [NODE_TTC_1] = { MM_TTC1 },
> +    [NODE_TTC_2] = { MM_TTC2 },
> +    [NODE_TTC_3] = { MM_TTC3 },
> +    [NODE_SATA] = { MM_SATA_AHCI_HBA },
> +    [NODE_ETH_0] = { MM_GEM0 },
> +    [NODE_ETH_1] = { MM_GEM1 },
> +    [NODE_ETH_2] = { MM_GEM2 },
> +    [NODE_ETH_3] = { MM_GEM3 },
> +    [NODE_UART_0] = { MM_UART0 },
> +    [NODE_UART_1] = { MM_UART1 },
> +    [NODE_SPI_0] = { MM_SPI0 },
> +    [NODE_SPI_1] = { MM_SPI1 },
> +    [NODE_I2C_0] = { MM_I2C0 },
> +    [NODE_I2C_1] = { MM_I2C1 },
> +    [NODE_SD_0] = { MM_SD0 },
> +    [NODE_SD_1] = { MM_SD1 },
> +    [NODE_DP] = { MM_DP },
> +
> +    /* Guest with GDMA Channel 0 gets PM access. Other guests don't.  */
> +    [NODE_GDMA] = { MM_GDMA_CH0 },
> +    /* Guest with ADMA Channel 0 gets PM access. Other guests don't.  */
> +    [NODE_ADMA] = { MM_ADMA_CH0 },
> +
> +    [NODE_NAND] = { MM_NAND },
> +    [NODE_QSPI] = { MM_QSPI },
> +    [NODE_GPIO] = { MM_GPIO },
> +    [NODE_CAN_0] = { MM_CAN0 },
> +    [NODE_CAN_1] = { MM_CAN1 },
> +
> +    /* Dom0 only.  */
> +    [NODE_AFI] = { .hwdom_access = true },
> +    [NODE_APLL] = { .hwdom_access = true },
> +    [NODE_VPLL] = { .hwdom_access = true },
> +    [NODE_DPLL] = { .hwdom_access = true },
> +    [NODE_RPLL] = { .hwdom_access = true },
> +    [NODE_IOPLL] = { .hwdom_access = true },
> +    [NODE_DDR] = { .hwdom_access = true },
> +    [NODE_IPI_APU] = { .hwdom_access = true },
> +    [NODE_PCAP] = { .hwdom_access = true },
> +
> +    [NODE_PCIE] = { MM_PCIE_ATTRIB },
> +    [NODE_RTC] = { MM_RTC },
> +};
> +
> +/*
> + * This table maps reset line IDs into a memory address.
> + * If a guest has access to the address, it has enough control
> + * over the affected node to grant it access to EEMI calls for
> + * resetting that node.
> + */
> +#define PM_RESET_IDX(n) (n - PM_RESET_PCIE_CFG)
> +static const struct pm_access pm_reset_access[] = {
> +    [PM_RESET_IDX(PM_RESET_PCIE_CFG)] = { MM_AXIPCIE_MAIN },
> +    [PM_RESET_IDX(PM_RESET_PCIE_BRIDGE)] = { MM_PCIE_ATTRIB },
> +    [PM_RESET_IDX(PM_RESET_PCIE_CTRL)] = { MM_PCIE_ATTRIB },
> +
> +    [PM_RESET_IDX(PM_RESET_DP)] = { MM_DP },
> +    [PM_RESET_IDX(PM_RESET_SWDT_CRF)] = { MM_SWDT },
> +    [PM_RESET_IDX(PM_RESET_AFI_FM5)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_AFI_FM4)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_AFI_FM3)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_AFI_FM2)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_AFI_FM1)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_AFI_FM0)] = { .hwdom_access = true },
> +
> +    /* Channel 0 grants PM access.  */
> +    [PM_RESET_IDX(PM_RESET_GDMA)] = { MM_GDMA_CH0 },
> +    [PM_RESET_IDX(PM_RESET_GPU_PP1)] = { MM_GPU },
> +    [PM_RESET_IDX(PM_RESET_GPU_PP0)] = { MM_GPU },
> +    [PM_RESET_IDX(PM_RESET_GT)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_SATA)] = { MM_SATA_AHCI_HBA },
> +
> +    /* We don't allow anyone to turn on/off the ACPUs.  */
> +    [PM_RESET_IDX(PM_RESET_ACPU3_PWRON)] = { 0 },
> +    [PM_RESET_IDX(PM_RESET_ACPU2_PWRON)] = { 0 },
> +    [PM_RESET_IDX(PM_RESET_ACPU1_PWRON)] = { 0 },
> +    [PM_RESET_IDX(PM_RESET_ACPU0_PWRON)] = { 0 },
> +    [PM_RESET_IDX(PM_RESET_APU_L2)] = { 0 },
> +    [PM_RESET_IDX(PM_RESET_ACPU3)] = { 0 },
> +    [PM_RESET_IDX(PM_RESET_ACPU2)] = { 0 },
> +    [PM_RESET_IDX(PM_RESET_ACPU1)] = { 0 },
> +    [PM_RESET_IDX(PM_RESET_ACPU0)] = { 0 },
> +
> +    [PM_RESET_IDX(PM_RESET_DDR)] = { 0 },
> +
> +    [PM_RESET_IDX(PM_RESET_APM_FPD)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_SOFT)] = { .hwdom_access = true },
> +
> +    [PM_RESET_IDX(PM_RESET_GEM0)] = { MM_GEM0 },
> +    [PM_RESET_IDX(PM_RESET_GEM1)] = { MM_GEM1 },
> +    [PM_RESET_IDX(PM_RESET_GEM2)] = { MM_GEM2 },
> +    [PM_RESET_IDX(PM_RESET_GEM3)] = { MM_GEM3 },
> +
> +    [PM_RESET_IDX(PM_RESET_QSPI)] = { MM_QSPI },
> +    [PM_RESET_IDX(PM_RESET_UART0)] = { MM_UART0 },
> +    [PM_RESET_IDX(PM_RESET_UART1)] = { MM_UART1 },
> +    [PM_RESET_IDX(PM_RESET_SPI0)] = { MM_SPI0 },
> +    [PM_RESET_IDX(PM_RESET_SPI1)] = { MM_SPI1 },
> +    [PM_RESET_IDX(PM_RESET_SDIO0)] = { MM_SD0 },
> +    [PM_RESET_IDX(PM_RESET_SDIO1)] = { MM_SD1 },
> +    [PM_RESET_IDX(PM_RESET_CAN0)] = { MM_CAN0 },
> +    [PM_RESET_IDX(PM_RESET_CAN1)] = { MM_CAN1 },
> +    [PM_RESET_IDX(PM_RESET_I2C0)] = { MM_I2C0 },
> +    [PM_RESET_IDX(PM_RESET_I2C1)] = { MM_I2C1 },
> +    [PM_RESET_IDX(PM_RESET_TTC0)] = { MM_TTC0 },
> +    [PM_RESET_IDX(PM_RESET_TTC1)] = { MM_TTC1 },
> +    [PM_RESET_IDX(PM_RESET_TTC2)] = { MM_TTC2 },
> +    [PM_RESET_IDX(PM_RESET_TTC3)] = { MM_TTC3 },
> +    [PM_RESET_IDX(PM_RESET_SWDT_CRL)] = { MM_SWDT },
> +    [PM_RESET_IDX(PM_RESET_NAND)] = { MM_NAND },
> +    /* ADMA Channel 0 grants access to pull the reset signal.  */
> +    [PM_RESET_IDX(PM_RESET_ADMA)] = { MM_ADMA_CH0 },
> +    [PM_RESET_IDX(PM_RESET_GPIO)] = { MM_GPIO },
> +    /* FIXME: What is this?  */
> +    [PM_RESET_IDX(PM_RESET_IOU_CC)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_TIMESTAMP)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_RPU_R50)] = { MM_RPU },
> +    [PM_RESET_IDX(PM_RESET_RPU_R51)] = { MM_RPU },
> +    [PM_RESET_IDX(PM_RESET_RPU_AMBA)] = { MM_RPU },
> +    [PM_RESET_IDX(PM_RESET_OCM)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_RPU_PGE)] = { MM_RPU },
> +
> +    [PM_RESET_IDX(PM_RESET_USB0_CORERESET)] = { MM_USB3_0 },
> +    [PM_RESET_IDX(PM_RESET_USB0_HIBERRESET)] = { MM_USB3_0 },
> +    [PM_RESET_IDX(PM_RESET_USB0_APB)] = { MM_USB3_0 },
> +
> +    [PM_RESET_IDX(PM_RESET_USB1_CORERESET)] = { MM_USB3_1 },
> +    [PM_RESET_IDX(PM_RESET_USB1_HIBERRESET)] = { MM_USB3_1 },
> +    [PM_RESET_IDX(PM_RESET_USB1_APB)] = { MM_USB3_1 },
> +
> +    [PM_RESET_IDX(PM_RESET_IPI)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_APM_LPD)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_RTC)] = { MM_RTC },
> +    [PM_RESET_IDX(PM_RESET_SYSMON)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_AFI_FM6)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_LPD_SWDT)] = { MM_SWDT },
> +    [PM_RESET_IDX(PM_RESET_FPD)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_RPU_DBG1)] = { MM_RPU },
> +    [PM_RESET_IDX(PM_RESET_RPU_DBG0)] = { MM_RPU },
> +    [PM_RESET_IDX(PM_RESET_DBG_LPD)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_DBG_FPD)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_APLL)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_DPLL)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_VPLL)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_IOPLL)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_RPLL)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_0)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_1)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_2)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_3)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_4)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_5)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_6)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_7)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_8)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_9)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_10)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_11)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_12)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_13)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_14)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_15)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_16)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_17)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_18)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_19)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_20)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_21)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_22)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_23)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_24)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_25)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_26)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_27)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_28)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_29)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_30)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_GPO3_PL_31)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_RPU_LS)] = { MM_RPU },
> +    [PM_RESET_IDX(PM_RESET_PS_ONLY)] = { .hwdom_access = true },
> +    [PM_RESET_IDX(PM_RESET_PL)] = { .hwdom_access = true },
> +};
> +
> +/*
> + * This table maps reset line IDs into a memory address.
> + * If a guest has access to the address, it has enough control
> + * over the affected node to grant it access to EEMI calls for
> + * resetting that node.
> + */
> +static const struct {
> +    uint64_t start;
> +    uint64_t end;    /* Inclusive. If not set, single reg entry.  */
> +    uint32_t mask;   /* Zero means no mask, i.e all bits.  */

Please clarify the comment. What is this mask for exactly?


> +    enum pm_node_id node;
> +    bool hwdom_access;

same here


> +    bool readonly;
> +} pm_mmio_access[] = {
> +    {
> +        .start = MM_CRF_APB + R_CRF_APLL_CTRL,
> +        .end = MM_CRF_APB + R_CRF_ACPU_CTRL,
> +        .hwdom_access = true
> +    },
> +    {
> +        .start = MM_CRL_APB + R_CRL_IOPLL_CTRL,
> +        .end = MM_CRL_APB + R_CRL_RPLL_TO_FPD_CTRL,
> +        .hwdom_access = true
> +    },
> +    { .start = MM_CRF_APB + R_CRF_DP_VIDEO_REF_CTRL, .node = NODE_DP },
> +    { .start = MM_CRF_APB + R_CRF_DP_STC_REF_CTRL, .node = NODE_DP },
> +    { .start = MM_CRF_APB + R_CRF_GPU_REF_CTRL, .node = NODE_GPU },
> +    { .start = MM_CRF_APB + R_CRF_SATA_REF_CTRL, .node = NODE_SATA },
> +    { .start = MM_CRF_APB + R_CRF_PCIE_REF_CTRL, .node = NODE_PCIE },
> +    { .start = MM_CRF_APB + R_CRF_GDMA_REF_CTRL, .node = NODE_GDMA },
> +    { .start = MM_CRF_APB + R_CRF_DPDMA_REF_CTRL, .node = NODE_DP },
> +    { .start = MM_CRL_APB + R_CRL_USB3_DUAL_REF_CTRL, .node = NODE_USB_0 },
> +    { .start = MM_CRL_APB + R_CRL_USB0_BUS_REF_CTRL, .node = NODE_USB_0 },
> +    { .start = MM_CRL_APB + R_CRL_USB1_BUS_REF_CTRL, .node = NODE_USB_1 },
> +    { .start = MM_CRL_APB + R_CRL_USB1_BUS_REF_CTRL, .node = NODE_USB_1 },
> +    { .start = MM_CRL_APB + R_CRL_GEM0_REF_CTRL, .node = NODE_ETH_0 },
> +    { .start = MM_CRL_APB + R_CRL_GEM1_REF_CTRL, .node = NODE_ETH_1 },
> +    { .start = MM_CRL_APB + R_CRL_GEM2_REF_CTRL, .node = NODE_ETH_2 },
> +    { .start = MM_CRL_APB + R_CRL_GEM3_REF_CTRL, .node = NODE_ETH_3 },
> +    { .start = MM_CRL_APB + R_CRL_QSPI_REF_CTRL, .node = NODE_QSPI },
> +    { .start = MM_CRL_APB + R_CRL_SDIO0_REF_CTRL, .node = NODE_SD_0 },
> +    { .start = MM_CRL_APB + R_CRL_SDIO1_REF_CTRL, .node = NODE_SD_1 },
> +    { .start = MM_CRL_APB + R_CRL_UART0_REF_CTRL, .node = NODE_UART_0 },
> +    { .start = MM_CRL_APB + R_CRL_UART1_REF_CTRL, .node = NODE_UART_1 },
> +    { .start = MM_CRL_APB + R_CRL_SPI0_REF_CTRL, .node = NODE_SPI_0 },
> +    { .start = MM_CRL_APB + R_CRL_SPI1_REF_CTRL, .node = NODE_SPI_1 },
> +    { .start = MM_CRL_APB + R_CRL_CAN0_REF_CTRL, .node = NODE_CAN_0 },
> +    { .start = MM_CRL_APB + R_CRL_CAN1_REF_CTRL, .node = NODE_CAN_1 },
> +    { .start = MM_CRL_APB + R_CRL_CPU_R5_CTRL, .node = NODE_RPU },
> +    { .start = MM_CRL_APB + R_CRL_IOU_SWITCH_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_CSU_PLL_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_PCAP_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_LPD_SWITCH_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_LPD_LSBUS_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_DBG_LPD_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_NAND_REF_CTRL, .node = NODE_NAND },
> +    { .start = MM_CRL_APB + R_CRL_ADMA_REF_CTRL, .node = NODE_ADMA },
> +    { .start = MM_CRL_APB + R_CRL_PL0_REF_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_PL1_REF_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_PL2_REF_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_PL3_REF_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_PL0_THR_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_PL1_THR_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_PL2_THR_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_PL3_THR_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_PL0_THR_CNT, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_PL1_THR_CNT, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_PL2_THR_CNT, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_PL3_THR_CNT, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_GEM_TSU_REF_CTRL, .node = NODE_ETH_0 },
> +    { .start = MM_CRL_APB + R_CRL_DLL_REF_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_AMS_REF_CTRL, .hwdom_access = true },
> +    { .start = MM_CRL_APB + R_CRL_I2C0_REF_CTRL, .node = NODE_I2C_0 },
> +    { .start = MM_CRL_APB + R_CRL_I2C1_REF_CTRL, .node = NODE_I2C_1 },
> +    { .start = MM_CRL_APB + R_CRL_TIMESTAMP_REF_CTRL, .hwdom_access = true },
> +    { .start = MM_IOU_SLCR + R_IOU_SLCR_WDT_CLK_SEL, .hwdom_access = true },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_CAN_MIO_CTRL,
> +        .mask = 0x1ff, .node = NODE_CAN_0
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_CAN_MIO_CTRL,
> +        .mask = 0x1ff << 15, .node = NODE_CAN_1
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
> +        .mask = 0xf, .node = NODE_ETH_0
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
> +        .mask = 0xf << 5, .node = NODE_ETH_1
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
> +        .mask = 0xf << 10, .node = NODE_ETH_2
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
> +        .mask = 0xf << 15, .node = NODE_ETH_3
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CLK_CTRL,
> +        .mask = 0x7 << 20, .hwdom_access = true
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_SDIO_CLK_CTRL,
> +        .mask = 0x7, .node = NODE_SD_0
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_SDIO_CLK_CTRL,
> +        .mask = 0x7 << 17, .node = NODE_SD_1
> +    },
> +
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_CTRL_REG_SD,
> +        .mask = 0x1, .node = NODE_SD_0
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_CTRL_REG_SD,
> +        .mask = 0x1 << 15, .node = NODE_SD_1
> +    },
> +    /* A series of SD regs with the same layout.  */
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_SD_ITAPDLY,
> +        .end = MM_IOU_SLCR + R_IOU_SLCR_SD_CDN_CTRL,
> +        .mask = 0x3ff << 0, .node = NODE_SD_0
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_SD_ITAPDLY,
> +        .end = MM_IOU_SLCR + R_IOU_SLCR_SD_CDN_CTRL,
> +        .mask = 0x3ff << 16, .node = NODE_SD_1
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CTRL,
> +        .mask = 0x3 << 0, .node = NODE_ETH_0
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CTRL,
> +        .mask = 0x3 << 2, .node = NODE_ETH_1
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CTRL,
> +        .mask = 0x3 << 4, .node = NODE_ETH_2
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_GEM_CTRL,
> +        .mask = 0x3 << 6, .node = NODE_ETH_3
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TTC_APB_CLK,
> +        .mask = 0x3 << 0, .node = NODE_TTC_0
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TTC_APB_CLK,
> +        .mask = 0x3 << 2, .node = NODE_TTC_1
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TTC_APB_CLK,
> +        .mask = 0x3 << 4, .node = NODE_TTC_2
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TTC_APB_CLK,
> +        .mask = 0x3 << 6, .node = NODE_TTC_3
> +    },
> +
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TAPDLY_BYPASS,
> +        .mask = 0x3, .node = NODE_NAND
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_TAPDLY_BYPASS,
> +        .mask = 0x1 << 2, .node = NODE_QSPI
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
> +        .mask = 0xf << 0, .node = NODE_ETH_0
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
> +        .mask = 0xf << 4, .node = NODE_ETH_1
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
> +        .mask = 0xf << 8, .node = NODE_ETH_2
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
> +        .mask = 0xf << 12, .node = NODE_ETH_3
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
> +        .mask = 0xf << 16, .node = NODE_SD_0
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
> +        .mask = 0xf << 20, .node = NODE_SD_1
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
> +        .mask = 0xf << 24, .node = NODE_NAND
> +    },
> +    {
> +        .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_COHERENT_CTRL,
> +        .mask = 0xf << 28, .node = NODE_QSPI
> +    },
> +    { .start = MM_IOU_SLCR + R_IOU_SLCR_VIDEO_PSS_CLK_SEL, .hwdom_access = true },
> +    /* No access to R_IOU_SLCR_IOU_INTERCONNECT_ROUTE at all.  */
> +    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_GEM0, .node = NODE_ETH_0 },
> +    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_GEM1, .node = NODE_ETH_1 },
> +    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_GEM2, .node = NODE_ETH_2 },
> +    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_GEM3, .node = NODE_ETH_3 },
> +    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_SD0, .node = NODE_SD_0 },
> +    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_SD1, .node = NODE_SD_1 },
> +    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_CAN0, .node = NODE_CAN_0 },
> +    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_CAN1, .node = NODE_CAN_1 },
> +    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_LQSPI, .node = NODE_QSPI },
> +    { .start = MM_IOU_SLCR + R_IOU_SLCR_IOU_RAM_NAND, .node = NODE_NAND },
> +    {
> +        .start = MM_PMU_GLOBAL + R_PMU_GLOBAL_PWR_STATE,
> +        .readonly = true,
> +    },
> +    {
> +        .start = MM_PMU_GLOBAL + R_PMU_GLOBAL_GLOBAL_GEN_STORAGE0,
> +        .end = MM_PMU_GLOBAL + R_PMU_GLOBAL_PERS_GLOB_GEN_STORAGE7,
> +        .readonly = true,
> +    },
> +    {
> +        /* Universal read-only access to CRF. Linux CCF needs this.  */
> +        .start = MM_CRF_APB, .end = MM_CRF_APB + 0x104,
> +        .readonly = true,
> +    },
> +    {
> +        /* Universal read-only access to CRL. Linux CCF needs this.  */
> +        .start = MM_CRL_APB, .end = MM_CRL_APB + 0x284,
> +        .readonly = true,
> +    }
> +};
> +
> +static bool pm_check_access(const struct pm_access *acl, struct domain *d, int idx)
> +{
> +    unsigned long mfn;
> +
> +    if ( acl[idx].hwdom_access && is_hardware_domain(d) )
> +        return true;
> +
> +    mfn = paddr_to_pfn(acl[idx].addr);
> +    if ( !mfn )
> +        return false;
> +
> +    return iomem_access_permitted(d, mfn, mfn);

I would write this function as:

    mfn = paddr_to_pfn(acl[idx].addr);
    if ( mfn != 0 )
        return iomem_access_permitted(d, mfn, mfn);

    return is_hardware_domain(d);

This way if addr is valid, then the domain need to have iomem access for
it. Otherwise, it needs to be the the hardware domain.


> +}
> +
> +/* Check if a domain has access to a node.  */
> +static bool domain_has_node_access(struct domain *d, enum pm_node_id node)
> +{
> +    if ( node <= 0 || node > ARRAY_SIZE(pm_node_access) )
> +        return false;
> +
> +    /* NODE_UNKNOWN is treated as a wildcard.  */
> +    if ( node == NODE_UNKNOWN )
> +        return true;
> +
> +    return pm_check_access(pm_node_access, d, node);
> +}
> +
> +/* Check if a domain has access to a reset line.  */
> +static bool domain_has_reset_access(struct domain *d, enum pm_reset rst)
> +{
> +    int rst_idx = PM_RESET_IDX(rst);
> +
> +    if ( rst_idx < 0 || rst_idx > ARRAY_SIZE(pm_reset_access) )
> +        return false;
> +
> +    return pm_check_access(pm_reset_access, d, rst_idx);
> +}
> +
> +/*
> + * Check if a given domain has access to perform an indirect
> + * MMIO access.
> + *
> + * If the provided mask is invalid, it will be fixed up.
> + */
> +static bool domain_mediate_mmio_access(struct domain *d,
> +                                       bool write, uint64_t addr,
> +                                       uint32_t *mask)
> +{
> +    unsigned int i;
> +    bool ret = false;
> +    uint32_t prot_mask = 0;
> +
> +    ASSERT(mask);
> +
> +    /*
> +     * The hardware domain gets read access to everything.
> +     * Lower layers will do further filtering.
> +     */
> +    if ( !write && is_hardware_domain(d) )
> +        return true;
> +    /* Scan the ACL.  */
> +    for ( i = 0; i < ARRAY_SIZE(pm_mmio_access); i++ ) {
> +        bool r;
> +
> +        /* Check if the address is OK.  */
> +        if ( pm_mmio_access[i].end ) {
> +            /* Memory range.  */
> +            if ( addr < pm_mmio_access[i].start )
> +                continue;
> +            if ( addr > pm_mmio_access[i].end )
> +                continue;
> +        } else {
> +            /* Single register.  */
> +            if ( addr != pm_mmio_access[i].start )
> +                continue;
> +        }

Would it make sense to order the entries, so that if addr >
pm_mmio_access[i].start, we can return immediately?


> +        if ( write && pm_mmio_access[i].readonly )
> +            continue;
> +        if ( pm_mmio_access[i].hwdom_access && !is_hardware_domain(d) )
> +            continue;
> +        /* Unlimited access is represented by a zero mask.  */
> +        ASSERT( pm_mmio_access[i].mask != 0xFFFFFFFF );

This is confusing: bits are set in the mask to allow write access,
except in the case of 0, which actually means 0xFFFFFFFF. Did I get this
right? If so, please choose one of the following:

- mask bits are set to allow write access, no exception: instead of 0,
  we would have 0xFFFFFFFF to give full access
- mask bits are set to deny write access: 0 means full access,
  0xFFFFFFFF means no access. Then you just need to apply the mask
  inverted: ~pm_mmio_access[i].mask


> +        r = domain_has_node_access(d, pm_mmio_access[i].node);
> +        if ( r ) {
> +            /* We've got access to this reg (or parts of it).  */
> +            ret = true;
> +            /* Masking only applies to writes, so reads can exit here.  */
> +            if ( !write )
> +                break;

Instead of break, I would just return ret;


> +
> +            /* Permit write access to selected bits.  */
> +            prot_mask |= pm_mmio_access[i].mask ? pm_mmio_access[i].mask : ~0;
> +            printk("match: mask=%x prot_mask=%x\n",
> +                   pm_mmio_access[i].mask, prot_mask);
> +            if ( prot_mask == 0xFFFFFFFF )
> +                break; /* Full access, we're done.  */
> +        } else {
> +            if ( !pm_mmio_access[i].mask ) {
> +                /*
> +                 * The entire reg is tied to a device that we don't have
> +                 * access to. No point in continuing.
> +                 */
> +                return false;
> +            }
> +        }
> +    }
> +
> +    /* Masking only applies to writes.  */
> +    if ( write )
> +        *mask &= prot_mask;
> +    return ret;
> +}
> +
> +bool zynqmp_eemi_mediate(register_t fid,
> +                         register_t a0,
> +                         register_t a1,
> +                         register_t a2,
> +                         register_t a3,
> +                         register_t a4,
> +                         register_t a5,
> +                         register_t *ret)

I think you can declare them as uint64_t, given that the API actually
requires 64bit registers. Also, I would probably just pass "struct
cpu_user_regs *regs" as argument for simplicity.


> +{
> +    bool is_mmio_write = false;
> +    unsigned int pm_fn = fid & 0xFFFF;
> +    uint32_t pm_arg[4];
> +
> +    /* Decode pm args.  */
> +    pm_arg[0] = a0;
> +    pm_arg[1] = a0 >> 32;
> +    pm_arg[2] = a1;
> +    pm_arg[3] = a1 >> 32;
> +
> +    ASSERT(ret);
> +
> +    switch (pm_fn)

code style


> +    {
> +    /*
> +     * We can't allow CPUs to suspend without Xen knowing about it.
> +     * We accept but ignore the request and wait for the guest to issue
> +     * a WFI which Xen will trap and act accordingly upon.
> +     */
> +    case PM_SELF_SUSPEND:
> +        ret[0] = PM_RET_SUCCESS;
> +        goto done;

This is something in addition of the guest calling WFI, right? In that
case we don't actually need to do anything to implement it, correct?


> +    case PM_GET_NODE_STATUS:
> +    /* API for PUs.  */
> +    case PM_REQ_SUSPEND:
> +    case PM_FORCE_POWERDOWN:
> +    case PM_ABORT_SUSPEND:
> +    case PM_REQ_WAKEUP:
> +    case PM_SET_WAKEUP_SOURCE:
> +    /* API for slaves.  */
> +    case PM_REQ_NODE:
> +    case PM_RELEASE_NODE:
> +    case PM_SET_REQUIREMENT:
> +    case PM_SET_MAX_LATENCY:

I cannot easily tell what is the permission check for these functions.
To which pm_node_access entries do they correspond to?


> +        if ( !domain_has_node_access(current->domain, pm_arg[0]) ) {

code style (bracket on newline)


> +            printk("zynqmp-pm: fn=%d No access to node %d\n", pm_fn, pm_arg[0]);
> +            ret[0] = PM_RET_ERROR_ACCESS;
> +            goto done;
> +        }
> +        goto forward_to_fw;
> +
> +    case PM_RESET_ASSERT:
> +    case PM_RESET_GET_STATUS:
> +        if ( !domain_has_reset_access(current->domain, pm_arg[0]) ) {

code style


> +            printk("zynqmp-pm: fn=%d No access to reset %d\n", pm_fn, pm_arg[0]);
> +            ret[0] = PM_RET_ERROR_ACCESS;
> +            goto done;
> +        }
> +        goto forward_to_fw;
> +
> +    /* These calls are safe and always allowed.  */
> +    case ZYNQMP_SIP_SVC_CALL_COUNT:
> +    case ZYNQMP_SIP_SVC_UID:
> +    case ZYNQMP_SIP_SVC_VERSION:
> +    case PM_GET_API_VERSION:
> +    case PM_GET_CHIPID:
> +        goto forward_to_fw;
> +
> +    /* Mediated MMIO access.  */
> +    case PM_MMIO_WRITE:
> +        is_mmio_write = true;
> +    /* Fallthrough.  */
> +    case PM_MMIO_READ:
> +        if ( !domain_mediate_mmio_access(current->domain,
> +                                         is_mmio_write,
> +                                         pm_arg[0], &pm_arg[1]) ) {

code style


> +            printk("eemi: fn=%d No access to MMIO %s %x\n",
> +                   pm_fn, is_mmio_write ? "write" : "read", pm_arg[0]);
> +            ret[0] = PM_RET_ERROR_ACCESS;
> +            goto done;
> +        }
> +        goto forward_to_fw;
> +
> +    /* Exclusive to Dom0.  */
> +    case PM_INIT:
> +    case PM_SET_CONFIGURATION:
> +    case PM_FPGA_LOAD:
> +    case PM_FPGA_GET_STATUS:
> +        if ( !is_hardware_domain(current->domain) ) {

Code style.


> +            printk("eemi: fn=%d No access", pm_fn);
> +            ret[0] = PM_RET_ERROR_ACCESS;
> +            goto done;
> +        }
> +        goto forward_to_fw;
> +
> +    /* These calls are never allowed.  */
> +    case PM_SYSTEM_SHUTDOWN:
> +        ret[0] = PM_RET_ERROR_ACCESS;
> +        goto done;
> +
> +    default:
> +        printk("zynqmp-pm: Unhandled PM Call: %d\n", (u32)fid);
> +        return false;
> +    }
> +
> +forward_to_fw:
> +    /* Re-encode pm args.  */
> +    a0 = ((uint64_t)pm_arg[1] << 32) | pm_arg[0];
> +    a1 = ((uint64_t)pm_arg[3] << 32) | pm_arg[2];
> +    call_smcc64(fid, a0, a1, a2, a3, a4, a5, ret);
> +done:
> +    return true;
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/arm/platforms/xilinx-zynqmp.c b/xen/arch/arm/platforms/xilinx-zynqmp.c
> index 2adee91..d826282 100644
> --- a/xen/arch/arm/platforms/xilinx-zynqmp.c
> +++ b/xen/arch/arm/platforms/xilinx-zynqmp.c
> @@ -18,6 +18,7 @@
>   */
>  
>  #include <asm/platform.h>
> +#include <asm/platforms/xilinx-zynqmp-eemi.h>
>  
>  static const char * const zynqmp_dt_compat[] __initconst =
>  {
> @@ -32,8 +33,25 @@ static const struct dt_device_match zynqmp_blacklist_dev[] __initconst =
>      { /* sentinel */ },
>  };
>  
> +bool zynqmp_hvc(struct cpu_user_regs *regs)
> +{
> +    register_t ret[4] = { 0 };
> +
> +    if ( !zynqmp_eemi_mediate(regs->x0, regs->x1, regs->x2, regs->x3,
> +                              regs->x4, regs->x5, regs->x6, ret) )
> +        return false;
> +
> +    /* Transfer return values into guest registers.  */
> +    regs->x0 = ret[0];
> +    regs->x1 = ret[1];
> +    regs->x2 = ret[2];
> +    regs->x3 = ret[3];
> +    return true;
> +}
> +
>  PLATFORM_START(xgene_storm, "Xilinx ZynqMP")
>      .compatible = zynqmp_dt_compat,
> +    .hvc = zynqmp_hvc,
>      .blacklist_dev = zynqmp_blacklist_dev,
>  PLATFORM_END
>  
> diff --git a/xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h b/xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h
> new file mode 100644
> index 0000000..774593c
> --- /dev/null
> +++ b/xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h
> @@ -0,0 +1,337 @@
> +/* Xen specifics:  */
> +/* Main PM Mediator entry.  */
> +bool zynqmp_eemi_mediate(register_t fid,
> +                         register_t a0,
> +                         register_t a1,
> +                         register_t a2,
> +                         register_t a3,
> +                         register_t a4,
> +                         register_t a5,
> +                         register_t *ret);
> +
> +/* Service calls.  */
> +#define SVC_MASK             0x3F000000
> +#define SVC_SIP              0x02000000    /* SoC Implementation Specific.  */
> +#define PM_SIP_SVC           0xC2000000
> +
> +/* SMC function IDs for SiP Service queries */
> +#define ZYNQMP_SIP_SVC_CALL_COUNT       0xff00
> +#define ZYNQMP_SIP_SVC_UID              0xff01
> +#define ZYNQMP_SIP_SVC_VERSION          0xff03
> +
> +/* Generic PM defs:  */
> +/*
> + * Version number is a 32bit value, like:
> + * (PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR
> + */
> +#define PM_VERSION_MAJOR	0
> +#define PM_VERSION_MINOR	2
> +
> +#define PM_VERSION	((PM_VERSION_MAJOR << 16) | PM_VERSION_MINOR)
> +
> +/* Capabilities for RAM */
> +#define PM_CAP_ACCESS	0x1U
> +#define PM_CAP_CONTEXT	0x2U
> +
> +#define MAX_LATENCY	(~0U)
> +#define MAX_QOS		100U
> +
> +/* State arguments of the self suspend */
> +#define PM_STATE_CPU_IDLE		0x0U
> +#define PM_STATE_SUSPEND_TO_RAM		0xFU
> +
> +enum pm_api_id {
> +	/* Miscellaneous API functions: */

Code style: no tabs please


> +	PM_GET_API_VERSION = 1, /* Do not change or move */
> +	PM_SET_CONFIGURATION,
> +	PM_GET_NODE_STATUS,
> +	PM_GET_OP_CHARACTERISTIC,
> +	PM_REGISTER_NOTIFIER,
> +	/* API for suspending of PUs: */
> +	PM_REQ_SUSPEND,
> +	PM_SELF_SUSPEND,
> +	PM_FORCE_POWERDOWN,
> +	PM_ABORT_SUSPEND,
> +	PM_REQ_WAKEUP,
> +	PM_SET_WAKEUP_SOURCE,
> +	PM_SYSTEM_SHUTDOWN,
> +	/* API for managing PM slaves: */
> +	PM_REQ_NODE,
> +	PM_RELEASE_NODE,
> +	PM_SET_REQUIREMENT,
> +	PM_SET_MAX_LATENCY,
> +	/* Direct control API functions: */
> +	PM_RESET_ASSERT,
> +	PM_RESET_GET_STATUS,
> +	PM_MMIO_WRITE,
> +	PM_MMIO_READ,
> +	PM_INIT,
> +	PM_FPGA_LOAD,
> +	PM_FPGA_GET_STATUS,
> +	PM_GET_CHIPID,
> +	PM_API_MAX
> +};
> +
> +enum pm_node_id {
> +	NODE_UNKNOWN = 0,
> +	NODE_APU,
> +	NODE_APU_0,
> +	NODE_APU_1,
> +	NODE_APU_2,
> +	NODE_APU_3,
> +	NODE_RPU,
> +	NODE_RPU_0,
> +	NODE_RPU_1,
> +	NODE_PL,
> +	NODE_FPD,
> +	NODE_OCM_BANK_0,
> +	NODE_OCM_BANK_1,
> +	NODE_OCM_BANK_2,
> +	NODE_OCM_BANK_3,
> +	NODE_TCM_0_A,
> +	NODE_TCM_0_B,
> +	NODE_TCM_1_A,
> +	NODE_TCM_1_B,
> +	NODE_L2,
> +	NODE_GPU_PP_0,
> +	NODE_GPU_PP_1,
> +	NODE_USB_0,
> +	NODE_USB_1,
> +	NODE_TTC_0,
> +	NODE_TTC_1,
> +	NODE_TTC_2,
> +	NODE_TTC_3,
> +	NODE_SATA,
> +	NODE_ETH_0,
> +	NODE_ETH_1,
> +	NODE_ETH_2,
> +	NODE_ETH_3,
> +	NODE_UART_0,
> +	NODE_UART_1,
> +	NODE_SPI_0,
> +	NODE_SPI_1,
> +	NODE_I2C_0,
> +	NODE_I2C_1,
> +	NODE_SD_0,
> +	NODE_SD_1,
> +	NODE_DP,
> +	NODE_GDMA,
> +	NODE_ADMA,
> +	NODE_NAND,
> +	NODE_QSPI,
> +	NODE_GPIO,
> +	NODE_CAN_0,
> +	NODE_CAN_1,
> +	NODE_AFI,
> +	NODE_APLL,
> +	NODE_VPLL,
> +	NODE_DPLL,
> +	NODE_RPLL,
> +	NODE_IOPLL,
> +	NODE_DDR,
> +	NODE_IPI_APU,
> +	NODE_IPI_RPU_0,
> +	NODE_GPU,
> +	NODE_PCIE,
> +	NODE_PCAP,
> +	NODE_RTC,
> +	NODE_MAX
> +};
> +
> +enum pm_request_ack {
> +	REQ_ACK_NO = 1,
> +	REQ_ACK_BLOCKING,
> +	REQ_ACK_NON_BLOCKING,
> +};
> +
> +enum pm_abort_reason {
> +	ABORT_REASON_WKUP_EVENT = 100,
> +	ABORT_REASON_PU_BUSY,
> +	ABORT_REASON_NO_PWRDN,
> +	ABORT_REASON_UNKNOWN,
> +};
> +
> +enum pm_suspend_reason {
> +	SUSPEND_REASON_PU_REQ = 201,
> +	SUSPEND_REASON_ALERT,
> +	SUSPEND_REASON_SYS_SHUTDOWN,
> +};
> +
> +enum pm_ram_state {
> +	PM_RAM_STATE_OFF = 1,
> +	PM_RAM_STATE_RETENTION,
> +	PM_RAM_STATE_ON,
> +};
> +
> +enum pm_opchar_type {
> +	PM_OPCHAR_TYPE_POWER = 1,
> +	PM_OPCHAR_TYPE_TEMP,
> +	PM_OPCHAR_TYPE_LATENCY,
> +};
> +
> +/**
> + * @PM_RET_SUCCESS:		success
> + * @PM_RET_ERROR_ARGS:		illegal arguments provided
> + * @PM_RET_ERROR_ACCESS:	access rights violation
> + * @PM_RET_ERROR_TIMEOUT:	timeout in communication with PMU
> + * @PM_RET_ERROR_NOTSUPPORTED:	feature not supported
> + * @PM_RET_ERROR_PROC:		node is not a processor node
> + * @PM_RET_ERROR_API_ID:	illegal API ID
> + * @PM_RET_ERROR_OTHER:		other error
> + */
> +enum pm_ret_status {
> +	PM_RET_SUCCESS,
> +	PM_RET_ERROR_ARGS,
> +	PM_RET_ERROR_ACCESS,
> +	PM_RET_ERROR_TIMEOUT,
> +	PM_RET_ERROR_NOTSUPPORTED,
> +	PM_RET_ERROR_PROC,
> +	PM_RET_ERROR_API_ID,
> +	PM_RET_ERROR_FAILURE,
> +	PM_RET_ERROR_COMMUNIC,
> +	PM_RET_ERROR_DOUBLEREQ,
> +	PM_RET_ERROR_OTHER,
> +};
> +
> +/**
> + * @PM_INITIAL_BOOT:	boot is a fresh system startup
> + * @PM_RESUME:		boot is a resume
> + * @PM_BOOT_ERROR:	error, boot cause cannot be identified
> + */
> +enum pm_boot_status {
> +	PM_INITIAL_BOOT,
> +	PM_RESUME,
> +	PM_BOOT_ERROR,
> +};
> +
> +enum pm_shutdown_type {
> +	PMF_SHUTDOWN_TYPE_SHUTDOWN,
> +	PMF_SHUTDOWN_TYPE_RESET,
> +};
> +
> +enum pm_shutdown_subtype {
> +	PMF_SHUTDOWN_SUBTYPE_SUBSYSTEM,
> +	PMF_SHUTDOWN_SUBTYPE_PS_ONLY,
> +	PMF_SHUTDOWN_SUBTYPE_SYSTEM,
> +};
> +
> +enum pm_reset {
> +	PM_RESET_START = 999,
> +	PM_RESET_PCIE_CFG,
> +	PM_RESET_PCIE_BRIDGE,
> +	PM_RESET_PCIE_CTRL,
> +	PM_RESET_DP,
> +	PM_RESET_SWDT_CRF,
> +	PM_RESET_AFI_FM5,
> +	PM_RESET_AFI_FM4,
> +	PM_RESET_AFI_FM3,
> +	PM_RESET_AFI_FM2,
> +	PM_RESET_AFI_FM1,
> +	PM_RESET_AFI_FM0,
> +	PM_RESET_GDMA,
> +	PM_RESET_GPU_PP1,
> +	PM_RESET_GPU_PP0,
> +	PM_RESET_GPU,
> +	PM_RESET_GT,
> +	PM_RESET_SATA,
> +	PM_RESET_ACPU3_PWRON,
> +	PM_RESET_ACPU2_PWRON,
> +	PM_RESET_ACPU1_PWRON,
> +	PM_RESET_ACPU0_PWRON,
> +	PM_RESET_APU_L2,
> +	PM_RESET_ACPU3,
> +	PM_RESET_ACPU2,
> +	PM_RESET_ACPU1,
> +	PM_RESET_ACPU0,
> +	PM_RESET_DDR,
> +	PM_RESET_APM_FPD,
> +	PM_RESET_SOFT,
> +	PM_RESET_GEM0,
> +	PM_RESET_GEM1,
> +	PM_RESET_GEM2,
> +	PM_RESET_GEM3,
> +	PM_RESET_QSPI,
> +	PM_RESET_UART0,
> +	PM_RESET_UART1,
> +	PM_RESET_SPI0,
> +	PM_RESET_SPI1,
> +	PM_RESET_SDIO0,
> +	PM_RESET_SDIO1,
> +	PM_RESET_CAN0,
> +	PM_RESET_CAN1,
> +	PM_RESET_I2C0,
> +	PM_RESET_I2C1,
> +	PM_RESET_TTC0,
> +	PM_RESET_TTC1,
> +	PM_RESET_TTC2,
> +	PM_RESET_TTC3,
> +	PM_RESET_SWDT_CRL,
> +	PM_RESET_NAND,
> +	PM_RESET_ADMA,
> +	PM_RESET_GPIO,
> +	PM_RESET_IOU_CC,
> +	PM_RESET_TIMESTAMP,
> +	PM_RESET_RPU_R50,
> +	PM_RESET_RPU_R51,
> +	PM_RESET_RPU_AMBA,
> +	PM_RESET_OCM,
> +	PM_RESET_RPU_PGE,
> +	PM_RESET_USB0_CORERESET,
> +	PM_RESET_USB1_CORERESET,
> +	PM_RESET_USB0_HIBERRESET,
> +	PM_RESET_USB1_HIBERRESET,
> +	PM_RESET_USB0_APB,
> +	PM_RESET_USB1_APB,
> +	PM_RESET_IPI,
> +	PM_RESET_APM_LPD,
> +	PM_RESET_RTC,
> +	PM_RESET_SYSMON,
> +	PM_RESET_AFI_FM6,
> +	PM_RESET_LPD_SWDT,
> +	PM_RESET_FPD,
> +	PM_RESET_RPU_DBG1,
> +	PM_RESET_RPU_DBG0,
> +	PM_RESET_DBG_LPD,
> +	PM_RESET_DBG_FPD,
> +	PM_RESET_APLL,
> +	PM_RESET_DPLL,
> +	PM_RESET_VPLL,
> +	PM_RESET_IOPLL,
> +	PM_RESET_RPLL,
> +	PM_RESET_GPO3_PL_0,
> +	PM_RESET_GPO3_PL_1,
> +	PM_RESET_GPO3_PL_2,
> +	PM_RESET_GPO3_PL_3,
> +	PM_RESET_GPO3_PL_4,
> +	PM_RESET_GPO3_PL_5,
> +	PM_RESET_GPO3_PL_6,
> +	PM_RESET_GPO3_PL_7,
> +	PM_RESET_GPO3_PL_8,
> +	PM_RESET_GPO3_PL_9,
> +	PM_RESET_GPO3_PL_10,
> +	PM_RESET_GPO3_PL_11,
> +	PM_RESET_GPO3_PL_12,
> +	PM_RESET_GPO3_PL_13,
> +	PM_RESET_GPO3_PL_14,
> +	PM_RESET_GPO3_PL_15,
> +	PM_RESET_GPO3_PL_16,
> +	PM_RESET_GPO3_PL_17,
> +	PM_RESET_GPO3_PL_18,
> +	PM_RESET_GPO3_PL_19,
> +	PM_RESET_GPO3_PL_20,
> +	PM_RESET_GPO3_PL_21,
> +	PM_RESET_GPO3_PL_22,
> +	PM_RESET_GPO3_PL_23,
> +	PM_RESET_GPO3_PL_24,
> +	PM_RESET_GPO3_PL_25,
> +	PM_RESET_GPO3_PL_26,
> +	PM_RESET_GPO3_PL_27,
> +	PM_RESET_GPO3_PL_28,
> +	PM_RESET_GPO3_PL_29,
> +	PM_RESET_GPO3_PL_30,
> +	PM_RESET_GPO3_PL_31,
> +	PM_RESET_RPU_LS,
> +	PM_RESET_PS_ONLY,
> +	PM_RESET_PL,
> +	PM_RESET_END
> +};
> diff --git a/xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h b/xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h
> new file mode 100644
> index 0000000..4fb1695
> --- /dev/null
> +++ b/xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h
> @@ -0,0 +1,284 @@
> +/*
> + * Merge of various auto-generated memory map and register
> + * definition files.
> + */
> +
> +/* Selected set of memory-map definitions:  */
> +#define MM_IOU_S	0xff000000
> +#define MM_IPI	0xff300000
> +#define MM_LPD_SLCR	0xff410000
> +#define MM_LPD_SLCR_SECURE	0xff4b0000
> +#define MM_CRL_APB	0xff5e0000
> +#define MM_OCM	0xff960000
> +#define MM_LPD_XPPU	0xff980000
> +#define MM_RPU	0xff9a0000
> +#define MM_AFIFM6	0xff9b0000
> +#define MM_LPD_XPPU_SINK	0xff9c0000
> +#define MM_USB3_0	0xff9d0000
> +#define MM_USB3_1	0xff9e0000
> +#define MM_APM_INTC_OCM	0xffa00000
> +#define MM_APM_LPD_FPD	0xffa10000
> +#define MM_AMS_CTRL	0xffa50000
> +#define MM_AMS_PS_SYSMON	0xffa50800
> +#define MM_AMS_PL_SYSMON	0xffa50c00
> +#define MM_RTC	0xffa60000
> +#define MM_OCM_XMPU_CFG	0xffa70000
> +#define MM_ADMA_CH0	0xffa80000
> +#define MM_ADMA_CH1	0xffa90000
> +#define MM_ADMA_CH2	0xffaa0000
> +#define MM_ADMA_CH3	0xffab0000
> +#define MM_ADMA_CH4	0xffac0000
> +#define MM_ADMA_CH5	0xffad0000
> +#define MM_ADMA_CH6	0xffae0000
> +
> +#define MM_IOU_GPV	0xfe0fffff
> +#define MM_LPD_GPV	0xfe1fffff
> +#define MM_USB3_0_XHCI	0xfe2fffff
> +#define MM_USB3_1_XHCI	0xfe3fffff
> +#define MM_CORESIGHT_SOC_ROM	0xfe80ffff
> +#define MM_CORESIGHT_SOC_TSGEN	0xfe90ffff
> +#define MM_CORESIGHT_SOC_FUNN_0	0xfe91ffff
> +#define MM_CORESIGHT_SOC_FUNN_1	0xfe92ffff
> +#define MM_CORESIGHT_SOC_FUNN_2	0xfe93ffff
> +#define MM_CORESIGHT_SOC_ETF_1	0xfe94ffff
> +#define MM_CORESIGHT_SOC_ETF_2	0xfe95ffff
> +#define MM_CORESIGHT_SOC_REPLIC	0xfe96ffff
> +#define MM_CORESIGHT_SOC_ETR	0xfe97ffff
> +#define MM_CORESIGHT_SOC_TPIU	0xfe98ffff
> +#define MM_CORESIGHT_SOC_CTI_0	0xfe99ffff
> +#define MM_CORESIGHT_SOC_CTI_1	0xfe9affff
> +#define MM_CORESIGHT_SOC_CTI_2	0xfe9bffff
> +#define MM_CORESIGHT_SOC_STM	0xfe9cffff
> +#define MM_CORESIGHT_SOC_FTM	0xfe9dffff
> +#define MM_CORESIGHT_SOC_ATM_0	0xfe9effff
> +#define MM_CORESIGHT_SOC_ATM_1	0xfe9fffff
> +#define MM_CORESIGHT_R5_ROM	0xfebe0fff
> +#define MM_CORESIGHT_R5_DBG_0	0xfebf0fff
> +#define MM_CORESIGHT_R5_PMU_0	0xfebf1fff
> +#define MM_CORESIGHT_R5_DBG_1	0xfebf2fff
> +#define MM_CORESIGHT_R5_PMU_1	0xfebf3fff
> +#define MM_CORESIGHT_R5_CTI_0	0xfebf8fff
> +#define MM_CORESIGHT_R5_CTI_1	0xfebf9fff
> +#define MM_CORESIGHT_R5_ETM_0	0xfebfcfff
> +#define MM_CORESIGHT_R5_ETM_1	0xfebfdfff
> +#define MM_CORESIGHT_A53_ROM	0xfec0ffff
> +#define MM_CORESIGHT_A53_DBG_0	0xfec1ffff
> +#define MM_CORESIGHT_A53_CTI_0	0xfec2ffff
> +#define MM_CORESIGHT_A53_PMU_0	0xfec3ffff
> +#define MM_CORESIGHT_A53_ETM_0	0xfec4ffff
> +#define MM_CORESIGHT_A53_DBG_1	0xfed1ffff
> +#define MM_CORESIGHT_A53_CTI_1	0xfed2ffff
> +#define MM_CORESIGHT_A53_PMU_1	0xfed3ffff
> +#define MM_CORESIGHT_A53_ETM_1	0xfed4ffff
> +#define MM_CORESIGHT_A53_DBG_2	0xfee1ffff
> +#define MM_CORESIGHT_A53_CTI_2	0xfee2ffff
> +#define MM_CORESIGHT_A53_PMU_2	0xfee3ffff
> +#define MM_CORESIGHT_A53_ETM_2	0xfee4ffff
> +#define MM_CORESIGHT_A53_DBG_3	0xfef1ffff
> +#define MM_CORESIGHT_A53_CTI_3	0xfef2ffff
> +#define MM_CORESIGHT_A53_PMU_3	0xfef3ffff
> +
> +#define MM_DDRSS	0xfd000000
> +#define MM_SATA_AHCI_HBA	0xfd0c0000
> +#define MM_SATA_AHCI_VENDOR	0xfd0c00a0
> +#define MM_SATA_AHCI_PORT0_CNTRL	0xfd0c0100
> +#define MM_SATA_AHCI_PORT1_CNTRL	0xfd0c0180
> +#define MM_AXIPCIE_MAIN	0xfd0e0000
> +#define MM_AXIPCIE_INGRESS0	0xfd0e0800
> +#define MM_AXIPCIE_INGRESS1	0xfd0e0820
> +#define MM_AXIPCIE_INGRESS2	0xfd0e0840
> +#define MM_AXIPCIE_INGRESS3	0xfd0e0860
> +#define MM_AXIPCIE_INGRESS4	0xfd0e0880
> +#define MM_AXIPCIE_INGRESS5	0xfd0e08a0
> +#define MM_AXIPCIE_INGRESS6	0xfd0e08c0
> +#define MM_AXIPCIE_INGRESS7	0xfd0e08e0
> +#define MM_AXIPCIE_EGRESS0	0xfd0e0c00
> +#define MM_AXIPCIE_EGRESS1	0xfd0e0c20
> +#define MM_AXIPCIE_EGRESS2	0xfd0e0c40
> +#define MM_AXIPCIE_EGRESS3	0xfd0e0c60
> +#define MM_AXIPCIE_EGRESS4	0xfd0e0c80
> +#define MM_AXIPCIE_EGRESS5	0xfd0e0ca0
> +#define MM_AXIPCIE_EGRESS6	0xfd0e0cc0
> +#define MM_AXIPCIE_EGRESS7	0xfd0e0ce0
> +#define MM_AXIPCIE_DMA0	0xfd0f0000
> +#define MM_AXIPCIE_DMA1	0xfd0f0080
> +#define MM_AXIPCIE_DMA2	0xfd0f0100
> +#define MM_AXIPCIE_DMA3	0xfd0f0180
> +#define MM_AXIPCIE_MSIX_TABLE	0xfd0f1000
> +#define MM_AXIPCIE_MSIX_PBA	0xfd0f2000
> +#define MM_CRF_APB	0xfd1a0000
> +#define MM_AFIFM0	0xfd360000
> +#define MM_AFIFM1	0xfd370000
> +#define MM_AFIFM2	0xfd380000
> +#define MM_AFIFM3	0xfd390000
> +#define MM_AFIFM4	0xfd3a0000
> +#define MM_AFIFM5	0xfd3b0000
> +#define MM_SIOU	0xfd3d0000
> +#define MM_SERDES	0xfd400000
> +#define MM_PCIE_ATTRIB	0xfd480000
> +#define MM_APM_CCI_INTC	0xfd490000
> +#define MM_DP	0xfd4a0000
> +#define MM_GPU	0xfd4b0000
> +#define MM_DPDMA	0xfd4c0000
> +#define MM_WDT	0xfd4d0000
> +#define MM_FPD_XMPU_SINK	0xfd4f0000
> +#define MM_GDMA_CH0	0xfd500000
> +#define MM_GDMA_CH1	0xfd510000
> +#define MM_GDMA_CH2	0xfd520000
> +#define MM_GDMA_CH3	0xfd530000
> +#define MM_GDMA_CH4	0xfd540000
> +#define MM_GDMA_CH5	0xfd550000
> +#define MM_GDMA_CH6	0xfd560000
> +#define MM_GDMA_CH7	0xfd570000
> +#define MM_APU	0xfd5c0000
> +#define MM_FPD_XMPU_CFG	0xfd5d0000
> +#define MM_CCI_REG	0xfd5e0000
> +#define MM_SMMU_REG	0xfd5f0000
> +#define MM_FPD_SLCR	0xfd610000
> +#define MM_FPD_SLCR_SECURE	0xfd690000
> +#define MM_CCI_GPV	0xfd6e0000
> +#define MM_FPD_GPV	0xfd700000
> +
> +#define MM_QSPI_Linear_Address	0xc0000000
> +#define MM_UART0	0xff000000
> +#define MM_UART1	0xff010000
> +#define MM_I2C0	0xff020000
> +#define MM_I2C1	0xff030000
> +#define MM_SPI0	0xff040000
> +#define MM_SPI1	0xff050000
> +#define MM_CAN0	0xff060000
> +#define MM_CAN1	0xff070000
> +#define MM_GPIO	0xff0a0000
> +#define MM_GEM0	0xff0b0000
> +#define MM_GEM1	0xff0c0000
> +#define MM_GEM2	0xff0d0000
> +#define MM_GEM3	0xff0e0000
> +#define MM_QSPI	0xff0f0000
> +#define MM_NAND	0xff100000
> +#define MM_TTC0	0xff110000
> +#define MM_TTC1	0xff120000
> +#define MM_TTC2	0xff130000
> +#define MM_TTC3	0xff140000
> +#define MM_SWDT	0xff150000
> +#define MM_SD0	0xff160000
> +#define MM_SD1	0xff170000
> +#define MM_IOU_SLCR	0xff180000
> +#define MM_IOU_SECURE_SLCR	0xff240000
> +#define MM_IOU_SCNTR	0xff250000
> +
> +#define MM_alg_vcu_enc_top	0xa0000000
> +#define MM_alg_vcu_dec_top	0xa0020000
> +
> +#define MM_PMU_GLOBAL           0xffd80000
> +#define MM_CSU                  0xffca0000
> +
> +/* Selected set of register definitions:  */
> +#define R_CRF_APLL_CTRL           0x20
> +#define R_CRF_ACPU_CTRL           0x60
> +#define R_CRF_DP_VIDEO_REF_CTRL   0x70
> +#define R_CRF_DP_STC_REF_CTRL     0x7c
> +#define R_CRF_GPU_REF_CTRL        0x84
> +#define R_CRF_SATA_REF_CTRL       0xa0
> +#define R_CRF_PCIE_REF_CTRL       0xb4
> +#define R_CRF_GDMA_REF_CTRL       0xb8
> +#define R_CRF_DPDMA_REF_CTRL      0xbc
> +
> +#define R_CRL_IOPLL_CTRL          0x20
> +#define R_CRL_IOPLL_CFG           0x24
> +#define R_CRL_IOPLL_FRAC_CFG      0x28
> +#define R_CRL_RPLL_CTRL           0x30
> +#define R_CRL_RPLL_CFG            0x34
> +#define R_CRL_RPLL_FRAC_CFG       0x38
> +#define R_CRL_PLL_STATUS          0x40
> +#define R_CRL_IOPLL_TO_FPD_CTRL   0x44
> +#define R_CRL_RPLL_TO_FPD_CTRL    0x48
> +#define R_CRL_USB3_DUAL_REF_CTRL  0x4c
> +#define R_CRL_GEM0_REF_CTRL       0x50
> +#define R_CRL_GEM1_REF_CTRL       0x54
> +#define R_CRL_GEM2_REF_CTRL       0x58
> +#define R_CRL_GEM3_REF_CTRL       0x5c
> +#define R_CRL_USB0_BUS_REF_CTRL   0x60
> +#define R_CRL_USB1_BUS_REF_CTRL   0x64
> +#define R_CRL_QSPI_REF_CTRL       0x68
> +#define R_CRL_SDIO0_REF_CTRL      0x6c
> +#define R_CRL_SDIO1_REF_CTRL      0x70
> +#define R_CRL_UART0_REF_CTRL      0x74
> +#define R_CRL_UART1_REF_CTRL      0x78
> +#define R_CRL_SPI0_REF_CTRL       0x7c
> +#define R_CRL_SPI1_REF_CTRL       0x80
> +#define R_CRL_CAN0_REF_CTRL       0x84
> +#define R_CRL_CAN1_REF_CTRL       0x88
> +#define R_CRL_CPU_R5_CTRL         0x90
> +#define R_CRL_IOU_SWITCH_CTRL     0x9c
> +#define R_CRL_CSU_PLL_CTRL        0xa0
> +#define R_CRL_PCAP_CTRL           0xa4
> +#define R_CRL_LPD_SWITCH_CTRL     0xa8
> +#define R_CRL_LPD_LSBUS_CTRL      0xac
> +#define R_CRL_DBG_LPD_CTRL        0xb0
> +#define R_CRL_NAND_REF_CTRL       0xb4
> +#define R_CRL_ADMA_REF_CTRL       0xb8
> +#define R_CRL_PL0_REF_CTRL        0xc0
> +#define R_CRL_PL1_REF_CTRL        0xc4
> +#define R_CRL_PL2_REF_CTRL        0xc8
> +#define R_CRL_PL3_REF_CTRL        0xcc
> +#define R_CRL_PL0_THR_CTRL        0xd0
> +#define R_CRL_PL0_THR_CNT         0xd4
> +#define R_CRL_PL1_THR_CTRL        0xd8
> +#define R_CRL_PL1_THR_CNT         0xdc
> +#define R_CRL_PL2_THR_CTRL        0xe0
> +#define R_CRL_PL2_THR_CNT         0xe4
> +#define R_CRL_PL3_THR_CTRL        0xe8
> +#define R_CRL_PL3_THR_CNT         0xfc
> +#define R_CRL_GEM_TSU_REF_CTRL    0x100
> +#define R_CRL_DLL_REF_CTRL        0x104
> +#define R_CRL_AMS_REF_CTRL        0x108
> +#define R_CRL_I2C0_REF_CTRL       0x120
> +#define R_CRL_I2C1_REF_CTRL       0x124
> +#define R_CRL_TIMESTAMP_REF_CTRL  0x128
> +
> +#define R_PMU_GLOBAL_GLOBAL_GEN_STORAGE0    0x30
> +#define R_PMU_GLOBAL_PERS_GLOB_GEN_STORAGE7 0x6c
> +
> +#define R_PMU_GLOBAL_PWR_STATE              0x100
> +
> +#define R_CSU_IDCODE                        0x40
> +
> +#define R_IOU_SLCR_WDT_CLK_SEL            0x300
> +#define R_IOU_SLCR_CAN_MIO_CTRL           0x304
> +#define R_IOU_SLCR_GEM_CLK_CTRL           0x308
> +#define R_IOU_SLCR_SDIO_CLK_CTRL          0x30c
> +#define R_IOU_SLCR_CTRL_REG_SD	          0x310
> +#define R_IOU_SLCR_SD_ITAPDLY	          0x314
> +#define R_IOU_SLCR_SD_OTAPDLYSEL          0x318
> +#define R_IOU_SLCR_SD_CONFIG_REG1         0x31c
> +#define R_IOU_SLCR_SD_CONFIG_REG2         0x320
> +#define R_IOU_SLCR_SD_CONFIG_REG3         0x324
> +#define R_IOU_SLCR_SD_INITPRESET          0x328
> +#define R_IOU_SLCR_SD_DSPPRESET	          0x32c
> +#define R_IOU_SLCR_SD_HSPDPRESET          0x330
> +#define R_IOU_SLCR_SD_SDR12PRESET         0x334
> +#define R_IOU_SLCR_SD_SDR25PRESET         0x338
> +#define R_IOU_SLCR_SD_SDR50PRSET          0x33c
> +#define R_IOU_SLCR_SD_SDR104PRST          0x340
> +#define R_IOU_SLCR_SD_DDR50PRESET         0x344
> +#define R_IOU_SLCR_SD_MAXCUR1P8           0x34c
> +#define R_IOU_SLCR_SD_MAXCUR3P0           0x350
> +#define R_IOU_SLCR_SD_MAXCUR3P3           0x354
> +#define R_IOU_SLCR_SD_DLL_CTRL            0x358
> +#define R_IOU_SLCR_SD_CDN_CTRL            0x35c
> +#define R_IOU_SLCR_GEM_CTRL               0x360
> +#define R_IOU_SLCR_IOU_TTC_APB_CLK        0x380
> +#define R_IOU_SLCR_IOU_TAPDLY_BYPASS      0x390
> +#define R_IOU_SLCR_IOU_COHERENT_CTRL      0x400
> +#define R_IOU_SLCR_VIDEO_PSS_CLK_SEL      0x404
> +#define R_IOU_SLCR_IOU_INTERCONNECT_ROUTE 0x408
> +#define R_IOU_SLCR_IOU_RAM_GEM0           0x500
> +#define R_IOU_SLCR_IOU_RAM_GEM1           0x504
> +#define R_IOU_SLCR_IOU_RAM_GEM2           0x508
> +#define R_IOU_SLCR_IOU_RAM_GEM3           0x50c
> +#define R_IOU_SLCR_IOU_RAM_SD0            0x510
> +#define R_IOU_SLCR_IOU_RAM_SD1            0x514
> +#define R_IOU_SLCR_IOU_RAM_CAN0           0x518
> +#define R_IOU_SLCR_IOU_RAM_CAN1           0x51c
> +#define R_IOU_SLCR_IOU_RAM_LQSPI          0x520
> +#define R_IOU_SLCR_IOU_RAM_NAND           0x524
> -- 
> 2.7.4
> 

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

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

* Re: [RFC v2 6/6] xen/arm: zynqmp: Remove blacklist of ZynqMP's PM node
  2017-02-07 19:42 ` [RFC v2 6/6] xen/arm: zynqmp: Remove blacklist of ZynqMP's PM node Edgar E. Iglesias
@ 2017-02-14  0:03   ` Stefano Stabellini
  0 siblings, 0 replies; 44+ messages in thread
From: Stefano Stabellini @ 2017-02-14  0:03 UTC (permalink / raw)
  To: Edgar E. Iglesias; +Cc: edgar.iglesias, julien.grall, sstabellini, xen-devel

On Tue, 7 Feb 2017, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
> 
> Stop blacklisting ZynqMP's power management node.
> This is now possible since we allow the hardware domain to
> issue HVC/SMC calls to firmware.
> 
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>

Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>


>  xen/arch/arm/platforms/xilinx-zynqmp.c | 8 --------
>  1 file changed, 8 deletions(-)
> 
> diff --git a/xen/arch/arm/platforms/xilinx-zynqmp.c b/xen/arch/arm/platforms/xilinx-zynqmp.c
> index d826282..a2128e2 100644
> --- a/xen/arch/arm/platforms/xilinx-zynqmp.c
> +++ b/xen/arch/arm/platforms/xilinx-zynqmp.c
> @@ -26,13 +26,6 @@ static const char * const zynqmp_dt_compat[] __initconst =
>      NULL
>  };
>  
> -static const struct dt_device_match zynqmp_blacklist_dev[] __initconst =
> -{
> -    /* Power management is not yet supported.  */
> -    DT_MATCH_COMPATIBLE("xlnx,zynqmp-pm"),
> -    { /* sentinel */ },
> -};
> -
>  bool zynqmp_hvc(struct cpu_user_regs *regs)
>  {
>      register_t ret[4] = { 0 };
> @@ -52,7 +45,6 @@ bool zynqmp_hvc(struct cpu_user_regs *regs)
>  PLATFORM_START(xgene_storm, "Xilinx ZynqMP")
>      .compatible = zynqmp_dt_compat,
>      .hvc = zynqmp_hvc,
> -    .blacklist_dev = zynqmp_blacklist_dev,
>  PLATFORM_END
>  
>  /*
> -- 
> 2.7.4
> 

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

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

* Re: [RFC v2 5/6] xen/arm: zynqmp: Forward plaform specific firmware calls
  2017-02-07 19:42 ` [RFC v2 5/6] xen/arm: zynqmp: Forward plaform specific firmware calls Edgar E. Iglesias
  2017-02-14  0:02   ` Stefano Stabellini
@ 2017-02-17 18:47   ` Julien Grall
  1 sibling, 0 replies; 44+ messages in thread
From: Julien Grall @ 2017-02-17 18:47 UTC (permalink / raw)
  To: Edgar E. Iglesias, xen-devel; +Cc: edgar.iglesias, nd, sstabellini

Hi Edgar,

On 07/02/17 19:42, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
>
> Implement an EEMI mediator and forward platform specific
> firmware calls from guests to firmware.
>
> The EEMI mediator is responsible for implementing access
> controls modifying or blocking calls that try to operate
> on setup for devices that are not under the calling guest's
> control.
>
> EEMI:
> https://www.xilinx.com/support/documentation/user_guides/ug1200-eemi-api.pdf
>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> ---
>  xen/arch/arm/platforms/Makefile                    |   1 +
>  xen/arch/arm/platforms/xilinx-zynqmp-eemi.c        | 794 +++++++++++++++++++++
>  xen/arch/arm/platforms/xilinx-zynqmp.c             |  18 +
>  xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h | 337 +++++++++
>  xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h   | 284 ++++++++
>  5 files changed, 1434 insertions(+)
>  create mode 100644 xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
>  create mode 100644 xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h
>  create mode 100644 xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h
>
> diff --git a/xen/arch/arm/platforms/Makefile b/xen/arch/arm/platforms/Makefile
> index 49fa683..b58b71f 100644
> --- a/xen/arch/arm/platforms/Makefile
> +++ b/xen/arch/arm/platforms/Makefile
> @@ -8,3 +8,4 @@ obj-$(CONFIG_ARM_64) += seattle.o
>  obj-$(CONFIG_ARM_32) += sunxi.o
>  obj-$(CONFIG_ARM_64) += xgene-storm.o
>  obj-$(CONFIG_ARM_64) += xilinx-zynqmp.o
> +obj-$(CONFIG_ARM_64) += xilinx-zynqmp-eemi.o
> diff --git a/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c b/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
> new file mode 100644
> index 0000000..c2c184d
> --- /dev/null
> +++ b/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c

As you introduce another file for Xilinx, it might be worth considering 
a new directory xilinx in the platforms.

> @@ -0,0 +1,794 @@
> +/*
> + * xen/arch/arm/platforms/xilinx-zynqmp-eemi.c
> + *
> + * Xilinx ZynqMP EEMI API mediator.
> + *
> + * Copyright (c) 2017 Xilinx Inc.
> + * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.

We had a bad habit on ARM to use "either version 2 of the License, or 
(at your option) any later version". However Xen is GPLv2 only (see 
CONTRIBUTING). Could you update the license to:

"This program is free software; you can redistribute it and/or
modify it under the terms and conditions of the GNU General Public
License, version 2, as published by the Free Software Foundation."

> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +/*
> + * Mediator for the EEMI Power Mangement API.

s/Mangement/Management/

> + *
> + * Refs:
> + * https://www.xilinx.com/support/documentation/user_guides/ug1200-eemi-api.pdf
> + *
> + * Background:
> + * The ZynqMP has a subsystem named the PMU with a CPU and special devices
> + * dedicated to running Power Management Firmware. Other masters in the
> + * system need to send requests to the PMU in order to for example:
> + * * Manage power state
> + * * Configure clocks
> + * * Program bitstreams for the programmable logic
> + * * etc
> + *
> + * Allthough the details of the setup are configurable, in the common case

s/Allthough/although/

> + * the PMU lives in the Secure world. NS World cannot directly communicate
> + * with it and must use proxy services from ARM Trusted Firmware to reach
> + * the PMU.
> + *
> + * Power Management on the ZynqMP is implemented in a layered manner.
> + * The PMU knows about various masters and will enforce access controls
> + * based on a pre-configured partitioning. This configuration dictates
> + * which devices are owned by the various masters and the PMU FW makes sure
> + * that a given master cannot turn off a device that it does not own or that
> + * is in use by other masters.
> + *
> + * The PMU is not aware of multiple execution states in masters.
> + * For example, it treats the ARMv8 cores as single units and does not
> + * distinguish between Secure vs NS OS:s nor does it know about Hypervisors
> + * and multiple guests. It is up to software on the ARMv8 cores to present
> + * a unified view of its power requirements.
> + *
> + * To implement this unified view, ARM Trusted Firmware at EL3 provides
> + * access to the PM API via SMC calls. ARM Trusted Firmware is responsible
> + * for mediating between the Secure and the NS world, rejecting SMC calls
> + * that request changes that are not allowed.
> + *
> + * Xen running above ATF owns the NS world and is responsible for presenting
> + * unified PM requests taking all guests and the hypervisor into account.
> + *
> + * Implementation:
> + * The PM API contains different classes of calls.
> + * Certain calls are harmless to expose to any guest.
> + * These include calls to get the PM API Version, or to read out the version
> + * of the chip we're running on.
> + *
> + * Other calls are more problematic. Here're some:

I don't think you can the contraction "here're".

> + * * Power requests for nodes (i.e turn on or off a given device)
> + * * Reset line control (i.e reset a given device)
> + * * MMIO access (i.e directly access clock and reset registers)
> + *
> + * Power requests for nodes:
> + * In order to correctly mediate these calls, we need to know if
> + * guests issuing these calls have ownership of the given device.
> + * The approach taken here is to map PM API Nodes identifying
> + * a device into base addresses for registers that belong to that
> + * same device.
> + *
> + * If the guest has access to a devices registers, we give the guest
> + * access to PM API calls that affect that device. This is implemented
> + * by pm_node_access and domain_has_node_access().
> + *
> + * Reset lines:
> + * Reset lines are identified by a list of identifiers that do not relate
> + * to device nodes. We can use the same approach here as for nodes, except
> + * that we need a separate table mapping reset lines to base addresses.
> + * This is implemented by pm_reset_access.
> + *
> + * MMIO access:
> + * These calls allow guests to access certain memory ranges. These ranges
> + * are typically protected for secure-world access only and also from
> + * certain masters only, so guests cannot access them directly.
> + * Registers within the memory regions affect certain nodes. In this case,
> + * our imput is an address and we map that address into a node. If the
> + * guest has ownership of that node, the access is allowed.
> + * Some registers contain bitfields and a single register may contain
> + * bits that affect multiple nodes.
> + *
> + * Some of the calls act on more global state. For example acting on
> + * NODE_PS, which affects many a lot of nodes. This higher level
> + * orchestrating is left for the hardware-domain only.
> + */
> +
> +#include <xen/iocap.h>
> +#include <asm/platform.h>
> +#include <asm/platforms/xilinx-zynqmp-eemi.h>
> +#include <asm/platforms/xilinx-zynqmp-mm.h>
> +
> +struct pm_access
> +{
> +    uint64_t addr;

Please use paddr_t here.

> +    bool hwdom_access;    /* HW domain gets access regardless.  */
> +};


[...]

> +/*
> + * This table maps reset line IDs into a memory address.
> + * If a guest has access to the address, it has enough control
> + * over the affected node to grant it access to EEMI calls for
> + * resetting that node.
> + */
> +static const struct {
> +    uint64_t start;
> +    uint64_t end;    /* Inclusive. If not set, single reg entry.  */

For both, s/uint64_t/paddr_t/

> +    uint32_t mask;   /* Zero means no mask, i.e all bits.  */
> +    enum pm_node_id node;
> +    bool hwdom_access;
> +    bool readonly;
> +} pm_mmio_access[] = {

Could not we find all those information from the device-tree?

> +static bool pm_check_access(const struct pm_access *acl, struct domain *d, int idx)
> +{
> +    unsigned long mfn;
> +
> +    if ( acl[idx].hwdom_access && is_hardware_domain(d) )
> +        return true;
> +
> +    mfn = paddr_to_pfn(acl[idx].addr);

acl[idx].addr may not be page aligned, so is there any possibility to 
have a same page permitted in multiple domain?

> +    if ( !mfn )
> +        return false;
> +
> +    return iomem_access_permitted(d, mfn, mfn);

Who will give access to the MMIO region? Is it the toolstack via 
iomem="..."?

Also, giving access to the MMIO also means the guest will be able to map 
it. After reading the comment at the top of the file, I am not sure this 
is what you want.

> +}
> +
> +/* Check if a domain has access to a node.  */
> +static bool domain_has_node_access(struct domain *d, enum pm_node_id node)
> +{
> +    if ( node <= 0 || node > ARRAY_SIZE(pm_node_access) )

Some compiler will complain of the first check because the enum is 
always positive.

Also, what are you trying to check given the node is an enum and should 
fall into the array?

> +        return false;
> +
> +    /* NODE_UNKNOWN is treated as a wildcard.  */
> +    if ( node == NODE_UNKNOWN )
> +        return true;

Which means every domain will access to it. I think this is easily 
error-prone because NODE_UNKOWN is 0. So you may give access to anyone 
by mistake.

Looking at the pm_mmio_access list, my understanding is NODE_UNKNOWN 
will be used when only the hardware domain can access it or the region 
is read-only.

So I would use the read-only property to know whether any domain has access.

> +
> +    return pm_check_access(pm_node_access, d, node);
> +}
> +
> +/* Check if a domain has access to a reset line.  */
> +static bool domain_has_reset_access(struct domain *d, enum pm_reset rst)
> +{
> +    int rst_idx = PM_RESET_IDX(rst);
> +
> +    if ( rst_idx < 0 || rst_idx > ARRAY_SIZE(pm_reset_access) )

Same question as above for the bound check.

> +        return false;
> +
> +    return pm_check_access(pm_reset_access, d, rst_idx);
> +}
> +
> +/*
> + * Check if a given domain has access to perform an indirect
> + * MMIO access.
> + *
> + * If the provided mask is invalid, it will be fixed up.
> + */
> +static bool domain_mediate_mmio_access(struct domain *d,
> +                                       bool write, uint64_t addr,

s/uint64_t/paddr_t/

> +                                       uint32_t *mask)
> +{
> +    unsigned int i;
> +    bool ret = false;
> +    uint32_t prot_mask = 0;
> +
> +    ASSERT(mask);
> +
> +    /*
> +     * The hardware domain gets read access to everything.
> +     * Lower layers will do further filtering.
> +     */
> +    if ( !write && is_hardware_domain(d) )
> +        return true;
> +
> +    /* Scan the ACL.  */
> +    for ( i = 0; i < ARRAY_SIZE(pm_mmio_access); i++ ) {
> +        bool r;
> +
> +        /* Check if the address is OK.  */
> +        if ( pm_mmio_access[i].end ) {
> +            /* Memory range.  */
> +            if ( addr < pm_mmio_access[i].start )
> +                continue;
> +            if ( addr > pm_mmio_access[i].end )
> +                continue;
> +        } else {
> +            /* Single register.  */

Are the single register only a byte? If not, in the case of a region is 
it safe to access in a middle of a register?

> +            if ( addr != pm_mmio_access[i].start )
> +                continue;
> +        }

I would drop the single register case and use make .end = .start. This 
would avoid potentially mistake in the code.

If you are concern about the readability of the array, you could use a 
macro.

> +
> +        if ( write && pm_mmio_access[i].readonly )
> +            continue;
> +        if ( pm_mmio_access[i].hwdom_access && !is_hardware_domain(d) )
> +            continue;
> +
> +        /* Unlimited access is represented by a zero mask.  */
> +        ASSERT( pm_mmio_access[i].mask != 0xFFFFFFFF );

Why? Would not it make the logic easier to handle unlimited access using 
0xFFFFFFFF?

You could use macro for that purpose.

> +
> +        r = domain_has_node_access(d, pm_mmio_access[i].node);
> +        if ( r ) {
> +            /* We've got access to this reg (or parts of it).  */
> +            ret = true;
> +            /* Masking only applies to writes, so reads can exit here.  */

If you do that a guest could potentially read some memory it is not 
allowed. Don't you expect sensitive data in the MMIO?

> +            if ( !write )
> +                break;
> +
> +            /* Permit write access to selected bits.  */
> +            prot_mask |= pm_mmio_access[i].mask ? pm_mmio_access[i].mask : ~0;
> +            printk("match: mask=%x prot_mask=%x\n",
> +                   pm_mmio_access[i].mask, prot_mask);
> +            if ( prot_mask == 0xFFFFFFFF )
> +                break; /* Full access, we're done.  */
> +        } else {
> +            if ( !pm_mmio_access[i].mask ) {
> +                /*
> +                 * The entire reg is tied to a device that we don't have
> +                 * access to. No point in continuing.
> +                 */

I am not sure to understand this, above you loop over until you may get 
prot_mask full. But here you exist as soon as one mask may not be valid.

> +                return false;
> +            }
> +        }
> +    }
> +
> +    /* Masking only applies to writes.  */
> +    if ( write )
> +        *mask &= prot_mask;

Newline here please.

> +    return ret;
> +}
> +
> +bool zynqmp_eemi_mediate(register_t fid,
> +                         register_t a0,
> +                         register_t a1,
> +                         register_t a2,
> +                         register_t a3,
> +                         register_t a4,
> +                         register_t a5,
> +                         register_t *ret)
> +{
> +    bool is_mmio_write = false;
> +    unsigned int pm_fn = fid & 0xFFFF;
> +    uint32_t pm_arg[4];
> +
> +    /* Decode pm args.  */
> +    pm_arg[0] = a0;
> +    pm_arg[1] = a0 >> 32;
> +    pm_arg[2] = a1;
> +    pm_arg[3] = a1 >> 32;
> +
> +    ASSERT(ret);
> +
> +    switch (pm_fn)
> +    {
> +    /*
> +     * We can't allow CPUs to suspend without Xen knowing about it.
> +     * We accept but ignore the request and wait for the guest to issue
> +     * a WFI which Xen will trap and act accordingly upon.
> +     */
> +    case PM_SELF_SUSPEND:
> +        ret[0] = PM_RET_SUCCESS;
> +        goto done;
> +
> +    case PM_GET_NODE_STATUS:
> +    /* API for PUs.  */

What PUs stand for?

> +    case PM_REQ_SUSPEND:
> +    case PM_FORCE_POWERDOWN:
> +    case PM_ABORT_SUSPEND:
> +    case PM_REQ_WAKEUP:
> +    case PM_SET_WAKEUP_SOURCE:
> +    /* API for slaves.  */
> +    case PM_REQ_NODE:
> +    case PM_RELEASE_NODE:
> +    case PM_SET_REQUIREMENT:
> +    case PM_SET_MAX_LATENCY:
> +        if ( !domain_has_node_access(current->domain, pm_arg[0]) ) {

Coding style:

if ( ... )
{

> +            printk("zynqmp-pm: fn=%d No access to node %d\n", pm_fn, pm_arg[0]);

Printk is not rate-limited, this means a guest could flood Xen with 
error message if it does not have access to the region.

Please use gprintk() here, it will print the domain ID and also
rate-limit the log.

Also, pm_fn and pm_arg are unsigned, so please use %u.


> +            ret[0] = PM_RET_ERROR_ACCESS;
> +            goto done;
> +        }
> +        goto forward_to_fw;
> +
> +    case PM_RESET_ASSERT:
> +    case PM_RESET_GET_STATUS:
> +        if ( !domain_has_reset_access(current->domain, pm_arg[0]) ) {

Coding style.

> +            printk("zynqmp-pm: fn=%d No access to reset %d\n", pm_fn, pm_arg[0]);

Same as above for the printk.

> +            ret[0] = PM_RET_ERROR_ACCESS;
> +            goto done;
> +        }
> +        goto forward_to_fw;
> +
> +    /* These calls are safe and always allowed.  */
> +    case ZYNQMP_SIP_SVC_CALL_COUNT:
> +    case ZYNQMP_SIP_SVC_UID:
> +    case ZYNQMP_SIP_SVC_VERSION:
> +    case PM_GET_API_VERSION:
> +    case PM_GET_CHIPID:
> +        goto forward_to_fw;
> +
> +    /* Mediated MMIO access.  */
> +    case PM_MMIO_WRITE:
> +        is_mmio_write = true;
> +    /* Fallthrough.  */
> +    case PM_MMIO_READ:
> +        if ( !domain_mediate_mmio_access(current->domain,
> +                                         is_mmio_write,
> +                                         pm_arg[0], &pm_arg[1]) ) {

See above for the coding style.

> +            printk("eemi: fn=%d No access to MMIO %s %x\n",
> +                   pm_fn, is_mmio_write ? "write" : "read", pm_arg[0]);

See above for the printk. Also, please use %#x if you print hexa to not 
confuse with decimal. But why do you print pm_arg in hexa here and 
decimal above?

> +            ret[0] = PM_RET_ERROR_ACCESS;
> +            goto done;
> +        }
> +        goto forward_to_fw;
> +
> +    /* Exclusive to Dom0.  */
> +    case PM_INIT:
> +    case PM_SET_CONFIGURATION:
> +    case PM_FPGA_LOAD:
> +    case PM_FPGA_GET_STATUS:
> +        if ( !is_hardware_domain(current->domain) ) {

See above for the coding style.

> +            printk("eemi: fn=%d No access", pm_fn);

See above for the printk.

> +            ret[0] = PM_RET_ERROR_ACCESS;
> +            goto done;
> +        }
> +        goto forward_to_fw;
> +
> +    /* These calls are never allowed.  */
> +    case PM_SYSTEM_SHUTDOWN:
> +        ret[0] = PM_RET_ERROR_ACCESS;
> +        goto done;
> +
> +    default:
> +        printk("zynqmp-pm: Unhandled PM Call: %d\n", (u32)fid);

See above for the printk. Also why do you cast fid?

> +        return false;
> +    }
> +
> +forward_to_fw:
> +    /* Re-encode pm args.  */
> +    a0 = ((uint64_t)pm_arg[1] << 32) | pm_arg[0];
> +    a1 = ((uint64_t)pm_arg[3] << 32) | pm_arg[2];
> +    call_smcc64(fid, a0, a1, a2, a3, a4, a5, ret);
> +done:
> +    return true;
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/arm/platforms/xilinx-zynqmp.c b/xen/arch/arm/platforms/xilinx-zynqmp.c
> index 2adee91..d826282 100644
> --- a/xen/arch/arm/platforms/xilinx-zynqmp.c
> +++ b/xen/arch/arm/platforms/xilinx-zynqmp.c
> @@ -18,6 +18,7 @@
>   */
>
>  #include <asm/platform.h>
> +#include <asm/platforms/xilinx-zynqmp-eemi.h>
>
>  static const char * const zynqmp_dt_compat[] __initconst =
>  {
> @@ -32,8 +33,25 @@ static const struct dt_device_match zynqmp_blacklist_dev[] __initconst =
>      { /* sentinel */ },
>  };
>
> +bool zynqmp_hvc(struct cpu_user_regs *regs)

This function should be static.

> +{
> +    register_t ret[4] = { 0 };
> +
> +    if ( !zynqmp_eemi_mediate(regs->x0, regs->x1, regs->x2, regs->x3,
> +                              regs->x4, regs->x5, regs->x6, ret) )
> +        return false;
> +
> +    /* Transfer return values into guest registers.  */
> +    regs->x0 = ret[0];
> +    regs->x1 = ret[1];
> +    regs->x2 = ret[2];
> +    regs->x3 = ret[3];

Newline here please.

> +    return true;
> +}
> +
>  PLATFORM_START(xgene_storm, "Xilinx ZynqMP")
>      .compatible = zynqmp_dt_compat,
> +    .hvc = zynqmp_hvc,
>      .blacklist_dev = zynqmp_blacklist_dev,
>  PLATFORM_END
>
> diff --git a/xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h b/xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h
> new file mode 100644
> index 0000000..774593c
> --- /dev/null
> +++ b/xen/include/asm-arm/platforms/xilinx-zynqmp-eemi.h

[...]

> +/**
> + * @PM_RET_SUCCESS:		success
> + * @PM_RET_ERROR_ARGS:		illegal arguments provided
> + * @PM_RET_ERROR_ACCESS:	access rights violation
> + * @PM_RET_ERROR_TIMEOUT:	timeout in communication with PMU
> + * @PM_RET_ERROR_NOTSUPPORTED:	feature not supported
> + * @PM_RET_ERROR_PROC:		node is not a processor node
> + * @PM_RET_ERROR_API_ID:	illegal API ID
> + * @PM_RET_ERROR_OTHER:		other error
> + */
> +enum pm_ret_status {
> +	PM_RET_SUCCESS,

I looked at the spec you provide in the commit message and I cannot find 
those name. Is it related to EEMI_SUCCESS? If so, I would prefer if we 
use the name from the spec.

Furthermore, it does not seem that values are provided in the spec.

> +	PM_RET_ERROR_ARGS,
> +	PM_RET_ERROR_ACCESS,
> +	PM_RET_ERROR_TIMEOUT,
> +	PM_RET_ERROR_NOTSUPPORTED,
> +	PM_RET_ERROR_PROC,
> +	PM_RET_ERROR_API_ID,
> +	PM_RET_ERROR_FAILURE,
> +	PM_RET_ERROR_COMMUNIC,
> +	PM_RET_ERROR_DOUBLEREQ,
> +	PM_RET_ERROR_OTHER,
> +};

[...]

> diff --git a/xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h b/xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h
> new file mode 100644
> index 0000000..4fb1695
> --- /dev/null
> +++ b/xen/include/asm-arm/platforms/xilinx-zynqmp-mm.h

I feel a bit unsure to see that many hardcoded values in Xen. Is it the 
only way to retrieve the mmio/power information?

Regards,

-- 
Julien Grall

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

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

* Re: [RFC v2 2/6] xen/arm: Introduce platform_hvc
  2017-02-13 22:08   ` Stefano Stabellini
@ 2017-07-31 21:30     ` Edgar E. Iglesias
  0 siblings, 0 replies; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-07-31 21:30 UTC (permalink / raw)
  To: Stefano Stabellini; +Cc: edgar.iglesias, julien.grall, xen-devel

On Mon, Feb 13, 2017 at 02:08:43PM -0800, Stefano Stabellini wrote:
> On Tue, 7 Feb 2017, Edgar E. Iglesias wrote:
> > From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
> > 
> > Introduce platform_hvc as a way to handle hypercalls that
> > Xen does not know about in a platform specific way. This
> > is particularly useful for implementing the SiP (SoC
> > implementation specific) service calls.
> > 
> > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
> > ---
> >  xen/arch/arm/platform.c        | 8 ++++++++
> >  xen/arch/arm/traps.c           | 3 +++
> >  xen/include/asm-arm/platform.h | 5 +++++
> >  3 files changed, 16 insertions(+)
> > 
> > diff --git a/xen/arch/arm/platform.c b/xen/arch/arm/platform.c
> > index 0af6d57..90ea6b8 100644
> > --- a/xen/arch/arm/platform.c
> > +++ b/xen/arch/arm/platform.c
> > @@ -127,6 +127,14 @@ void platform_poweroff(void)
> >          platform->poweroff();
> >  }
> >  
> > +bool platform_hvc(struct cpu_user_regs *regs)
> 
> This is fine, but we need a different name for it, as it can be used to
> handle both HVC and SMC calls. Maybe "firmware_call"?

Hi,

Sorry for the super long delay.. I'm looking at this again now.

Yes, you're right. I went with
platform_firmware_call() and platform->firmware_call().

I kept the platform_ prefix in the wrapper function to be
consistent with the other hooks.

Thanks,
Edgar


> 
> 
> > +{
> > +    if ( platform && platform->hvc )
> > +        return platform->hvc(regs);
> > +
> > +    return false;
> > +}
> > +
> >  bool_t platform_has_quirk(uint32_t quirk)
> >  {
> >      uint32_t quirks = 0;
> > diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> > index c5a4d41..33950d9 100644
> > --- a/xen/arch/arm/traps.c
> > +++ b/xen/arch/arm/traps.c
> > @@ -44,6 +44,7 @@
> >  #include <asm/cpufeature.h>
> >  #include <asm/flushtlb.h>
> >  #include <asm/monitor.h>
> > +#include <asm/platform.h>
> >  
> >  #include "decode.h"
> >  #include "vtimer.h"
> > @@ -1430,6 +1431,8 @@ static void do_trap_psci(struct cpu_user_regs *regs)
> >          }
> >          break;
> >      default:
> > +        if ( platform_hvc(regs) )
> > +                return;
> >          domain_crash_synchronous();
> >          return;
> >      }
> > diff --git a/xen/include/asm-arm/platform.h b/xen/include/asm-arm/platform.h
> > index 08010ba..4d51f0a 100644
> > --- a/xen/include/asm-arm/platform.h
> > +++ b/xen/include/asm-arm/platform.h
> > @@ -26,6 +26,10 @@ struct platform_desc {
> >      void (*reset)(void);
> >      /* Platform power-off */
> >      void (*poweroff)(void);
> > +    /* Platform specific HVC handler.
> > +     * Returns true if the call was handled and false if not.
> > +     */
> > +    bool (*hvc)(struct cpu_user_regs *regs);
> >      /*
> >       * Platform quirks
> >       * Defined has a function because a platform can support multiple
> > @@ -55,6 +59,7 @@ int platform_cpu_up(int cpu);
> >  #endif
> >  void platform_reset(void);
> >  void platform_poweroff(void);
> > +bool platform_hvc(struct cpu_user_regs *regs);
> >  bool_t platform_has_quirk(uint32_t quirk);
> >  bool_t platform_device_is_blacklisted(const struct dt_device_node *node);

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-02-09 19:32                                       ` Tamas K Lengyel
@ 2017-07-31 22:23                                         ` Edgar E. Iglesias
  2017-08-01 10:37                                           ` Julien Grall
  0 siblings, 1 reply; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-07-31 22:23 UTC (permalink / raw)
  To: Tamas K Lengyel
  Cc: Edgar E. Iglesias, Volodymyr Babchuk, Julien Grall,
	Stefano Stabellini, Xen-devel

On Thu, Feb 09, 2017 at 12:32:09PM -0700, Tamas K Lengyel wrote:
> On Thu, Feb 9, 2017 at 11:43 AM, Stefano Stabellini
> <sstabellini@kernel.org> wrote:
> > On Thu, 9 Feb 2017, Tamas K Lengyel wrote:
> >> On Thu, Feb 9, 2017 at 11:22 AM, Stefano Stabellini
> >> <sstabellini@kernel.org> wrote:
> >> > On Thu, 9 Feb 2017, Edgar E. Iglesias wrote:
> >> >> On Thu, Feb 09, 2017 at 10:12:41AM +0100, Edgar E. Iglesias wrote:
> >> >> > On Wed, Feb 08, 2017 at 05:20:44PM -0800, Stefano Stabellini wrote:
> >> >> > > On Thu, 9 Feb 2017, Julien Grall wrote:
> >> >> > > > On 08/02/2017 23:28, Tamas K Lengyel wrote:
> >> >> > > > > On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
> >> >> > > > > > Hi Tamas,

......

> >> In principle I have nothing against a command line option, but I don't
> >> really follow how that would help. The monitor system is disabled by
> >> default for all domains, so there is no problem with dom0 booting or
> >> any other domain needing to access the firmware. You specifically have
> >> to enable the monitoring for domains. Why is it a problem to have it
> >> be exclusive for just those domains where it is enabled?
> >
> > I am suggesting this solution because I expect many use-cases for memory
> > introspection that don't actually require any platform_hvc events to be
> > monitored at all. On the other end, I expect that on platforms where
> > platform_hvc is implemented, such as the ZynqMP, those calls are
> > important and should be handled in Xen in most cases.
> >
> > Looking at the code, does monitor.privileged_call_enabled only cover
> > SMC? Is monitor.privileged_call_enabled disabled by default?
> > If so, monitor.privileged_call_enabled could be the tunable I was
> > talking about. As long as enabling memory introspection doesn't
> > automatically forward platform_hvc events to the monitor, I am fine with
> > it.
> 
> Yes, monitor.privileged_call_enabled only covers SMCs right now and it
> is disabled by default. It has to be enabled specifically for a
> domain.  Memory introspection is separate from this, that is handled
> by the mem_access system and it can be enabled separately from SMC
> monitoring.
> 
> As for hypercalls that get handled by Xen, I don't really need to
> monitor those. If Xen would on the other hand go and call some
> firmware as a result of the hypercall, I would need to be able to deny
> that. So as long as XSM can be used to control HVC calls, that works
> for me just fine too.

Hi again!

This was quite a while ago but I think we kind of ended up with
monitor.privileged_call_enabled being a possible flag to conditionalize
the forwarding of firmware calls or not.

There are at least 3 cases to consider at the moment:
1. Firmware calls over SMC (PSCI or other platform calls like EEMI)
2. Firmware calls over HVC Handled by Xen (PSCI and XEN Hypercalls)
3. Firmware calls over HVC Handled by platform specific code (e.g EEMI)


For #1 Firmware calls over SMC:
I've conditionalized all of it on monitor.privileged_call_enabled.
It's either the monitor or the firmware call handling, they
are mutually exclusive. Guests can still do PSCI over HVC.

For #2, things work like today. This is PSCI and the Xen Hypercallsi over HVC.

For #3, only platform code knows if the specific call will be handled
in Xen completely or if it will result in some kind of SMC to lower layers.
If monitor.privileged_call_enabled is on, I've made the ZynqMP
implementation gracefully NACK any call that would result in an SMC
issued by Xen.

Are there any concerns around this?

I'll also send out code for review, it may be easier to follow :-)

Best regards,
Edgar




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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-07-31 22:23                                         ` Edgar E. Iglesias
@ 2017-08-01 10:37                                           ` Julien Grall
  2017-08-01 11:40                                             ` Edgar E. Iglesias
  0 siblings, 1 reply; 44+ messages in thread
From: Julien Grall @ 2017-08-01 10:37 UTC (permalink / raw)
  To: Edgar E. Iglesias, Tamas K Lengyel
  Cc: Edgar E. Iglesias, Volodymyr Babchuk, Stefano Stabellini, Xen-devel

Hi Edgar,

On 31/07/17 23:23, Edgar E. Iglesias wrote:
> On Thu, Feb 09, 2017 at 12:32:09PM -0700, Tamas K Lengyel wrote:
>> On Thu, Feb 9, 2017 at 11:43 AM, Stefano Stabellini
>> <sstabellini@kernel.org> wrote:
>>> On Thu, 9 Feb 2017, Tamas K Lengyel wrote:
>>>> On Thu, Feb 9, 2017 at 11:22 AM, Stefano Stabellini
>>>> <sstabellini@kernel.org> wrote:
>>>>> On Thu, 9 Feb 2017, Edgar E. Iglesias wrote:
>>>>>> On Thu, Feb 09, 2017 at 10:12:41AM +0100, Edgar E. Iglesias wrote:
>>>>>>> On Wed, Feb 08, 2017 at 05:20:44PM -0800, Stefano Stabellini wrote:
>>>>>>>> On Thu, 9 Feb 2017, Julien Grall wrote:
>>>>>>>>> On 08/02/2017 23:28, Tamas K Lengyel wrote:
>>>>>>>>>> On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
>>>>>>>>>>> Hi Tamas,
>
> ......
>
>>>> In principle I have nothing against a command line option, but I don't
>>>> really follow how that would help. The monitor system is disabled by
>>>> default for all domains, so there is no problem with dom0 booting or
>>>> any other domain needing to access the firmware. You specifically have
>>>> to enable the monitoring for domains. Why is it a problem to have it
>>>> be exclusive for just those domains where it is enabled?
>>>
>>> I am suggesting this solution because I expect many use-cases for memory
>>> introspection that don't actually require any platform_hvc events to be
>>> monitored at all. On the other end, I expect that on platforms where
>>> platform_hvc is implemented, such as the ZynqMP, those calls are
>>> important and should be handled in Xen in most cases.
>>>
>>> Looking at the code, does monitor.privileged_call_enabled only cover
>>> SMC? Is monitor.privileged_call_enabled disabled by default?
>>> If so, monitor.privileged_call_enabled could be the tunable I was
>>> talking about. As long as enabling memory introspection doesn't
>>> automatically forward platform_hvc events to the monitor, I am fine with
>>> it.
>>
>> Yes, monitor.privileged_call_enabled only covers SMCs right now and it
>> is disabled by default. It has to be enabled specifically for a
>> domain.  Memory introspection is separate from this, that is handled
>> by the mem_access system and it can be enabled separately from SMC
>> monitoring.
>>
>> As for hypercalls that get handled by Xen, I don't really need to
>> monitor those. If Xen would on the other hand go and call some
>> firmware as a result of the hypercall, I would need to be able to deny
>> that. So as long as XSM can be used to control HVC calls, that works
>> for me just fine too.
>
> Hi again!
>
> This was quite a while ago but I think we kind of ended up with
> monitor.privileged_call_enabled being a possible flag to conditionalize
> the forwarding of firmware calls or not.
>
> There are at least 3 cases to consider at the moment:
> 1. Firmware calls over SMC (PSCI or other platform calls like EEMI)
> 2. Firmware calls over HVC Handled by Xen (PSCI and XEN Hypercalls)
> 3. Firmware calls over HVC Handled by platform specific code (e.g EEMI)
>
>
> For #1 Firmware calls over SMC:
> I've conditionalized all of it on monitor.privileged_call_enabled.
> It's either the monitor or the firmware call handling, they
> are mutually exclusive. Guests can still do PSCI over HVC.
>
> For #2, things work like today. This is PSCI and the Xen Hypercallsi over HVC.
>
> For #3, only platform code knows if the specific call will be handled
> in Xen completely or if it will result in some kind of SMC to lower layers.
> If monitor.privileged_call_enabled is on, I've made the ZynqMP
> implementation gracefully NACK any call that would result in an SMC
> issued by Xen.
>
> Are there any concerns around this?

You may want to have a look at the discussion about SMC and Xen:

https://lists.xenproject.org/archives/html/xen-devel/2017-02/msg01226.html

IIRC, the consensus is to exclusively forward SMC to the monitor if enabled:

"10. Domains on which the monitor privileged call feature is enabled
(which is by default disabled for all domains) should not be able to
issue firmware calls via SMCs/HVCs so that such calls reach the
firmware directly. Xen should not bounce such calls to the firmware on
behalf of the domain. Xen should not alter the state of the domain
automatically (ie. incrementing PC). These calls should be exclusively
transfered to the monitor subscriber for further processing.
Hypercalls, virtual PSCI calls, virtual CPU services calls and virtual
ARM architecture service calls remain unaffected.".

Cheers,

-- 
Julien Grall

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

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

* Re: [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls
  2017-08-01 10:37                                           ` Julien Grall
@ 2017-08-01 11:40                                             ` Edgar E. Iglesias
  0 siblings, 0 replies; 44+ messages in thread
From: Edgar E. Iglesias @ 2017-08-01 11:40 UTC (permalink / raw)
  To: Julien Grall
  Cc: Volodymyr Babchuk, Edgar E. Iglesias, Stefano Stabellini,
	Xen-devel, Tamas K Lengyel

On Tue, Aug 01, 2017 at 11:37:05AM +0100, Julien Grall wrote:
> Hi Edgar,
> 
> On 31/07/17 23:23, Edgar E. Iglesias wrote:
> >On Thu, Feb 09, 2017 at 12:32:09PM -0700, Tamas K Lengyel wrote:
> >>On Thu, Feb 9, 2017 at 11:43 AM, Stefano Stabellini
> >><sstabellini@kernel.org> wrote:
> >>>On Thu, 9 Feb 2017, Tamas K Lengyel wrote:
> >>>>On Thu, Feb 9, 2017 at 11:22 AM, Stefano Stabellini
> >>>><sstabellini@kernel.org> wrote:
> >>>>>On Thu, 9 Feb 2017, Edgar E. Iglesias wrote:
> >>>>>>On Thu, Feb 09, 2017 at 10:12:41AM +0100, Edgar E. Iglesias wrote:
> >>>>>>>On Wed, Feb 08, 2017 at 05:20:44PM -0800, Stefano Stabellini wrote:
> >>>>>>>>On Thu, 9 Feb 2017, Julien Grall wrote:
> >>>>>>>>>On 08/02/2017 23:28, Tamas K Lengyel wrote:
> >>>>>>>>>>On Wed, Feb 8, 2017 at 3:04 PM, Julien Grall <julien.grall@arm.com> wrote:
> >>>>>>>>>>>Hi Tamas,
> >
> >......
> >
> >>>>In principle I have nothing against a command line option, but I don't
> >>>>really follow how that would help. The monitor system is disabled by
> >>>>default for all domains, so there is no problem with dom0 booting or
> >>>>any other domain needing to access the firmware. You specifically have
> >>>>to enable the monitoring for domains. Why is it a problem to have it
> >>>>be exclusive for just those domains where it is enabled?
> >>>
> >>>I am suggesting this solution because I expect many use-cases for memory
> >>>introspection that don't actually require any platform_hvc events to be
> >>>monitored at all. On the other end, I expect that on platforms where
> >>>platform_hvc is implemented, such as the ZynqMP, those calls are
> >>>important and should be handled in Xen in most cases.
> >>>
> >>>Looking at the code, does monitor.privileged_call_enabled only cover
> >>>SMC? Is monitor.privileged_call_enabled disabled by default?
> >>>If so, monitor.privileged_call_enabled could be the tunable I was
> >>>talking about. As long as enabling memory introspection doesn't
> >>>automatically forward platform_hvc events to the monitor, I am fine with
> >>>it.
> >>
> >>Yes, monitor.privileged_call_enabled only covers SMCs right now and it
> >>is disabled by default. It has to be enabled specifically for a
> >>domain.  Memory introspection is separate from this, that is handled
> >>by the mem_access system and it can be enabled separately from SMC
> >>monitoring.
> >>
> >>As for hypercalls that get handled by Xen, I don't really need to
> >>monitor those. If Xen would on the other hand go and call some
> >>firmware as a result of the hypercall, I would need to be able to deny
> >>that. So as long as XSM can be used to control HVC calls, that works
> >>for me just fine too.
> >
> >Hi again!
> >
> >This was quite a while ago but I think we kind of ended up with
> >monitor.privileged_call_enabled being a possible flag to conditionalize
> >the forwarding of firmware calls or not.
> >
> >There are at least 3 cases to consider at the moment:
> >1. Firmware calls over SMC (PSCI or other platform calls like EEMI)
> >2. Firmware calls over HVC Handled by Xen (PSCI and XEN Hypercalls)
> >3. Firmware calls over HVC Handled by platform specific code (e.g EEMI)
> >
> >
> >For #1 Firmware calls over SMC:
> >I've conditionalized all of it on monitor.privileged_call_enabled.
> >It's either the monitor or the firmware call handling, they
> >are mutually exclusive. Guests can still do PSCI over HVC.
> >
> >For #2, things work like today. This is PSCI and the Xen Hypercallsi over HVC.
> >
> >For #3, only platform code knows if the specific call will be handled
> >in Xen completely or if it will result in some kind of SMC to lower layers.
> >If monitor.privileged_call_enabled is on, I've made the ZynqMP
> >implementation gracefully NACK any call that would result in an SMC
> >issued by Xen.
> >
> >Are there any concerns around this?
> 
> You may want to have a look at the discussion about SMC and Xen:
> 
> https://lists.xenproject.org/archives/html/xen-devel/2017-02/msg01226.html
> 
> IIRC, the consensus is to exclusively forward SMC to the monitor if enabled:
> 
> "10. Domains on which the monitor privileged call feature is enabled
> (which is by default disabled for all domains) should not be able to
> issue firmware calls via SMCs/HVCs so that such calls reach the
> firmware directly. Xen should not bounce such calls to the firmware on
> behalf of the domain. Xen should not alter the state of the domain
> automatically (ie. incrementing PC). These calls should be exclusively
> transfered to the monitor subscriber for further processing.
> Hypercalls, virtual PSCI calls, virtual CPU services calls and virtual
> ARM architecture service calls remain unaffected.".
>

Thanks Julien.

I think it's better for EEMI to wait for the SMCC patches to go in and
base the EEMI mediator on top of them. I'll hold back a little more with this.

Cheers,
Edgar 

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

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

end of thread, other threads:[~2017-08-01 11:40 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-07 19:41 [RFC v2 0/6] zynqmp: Add forwarding of platform specific firmware calls Edgar E. Iglesias
2017-02-07 19:42 ` [RFC v2 1/6] xen/arm: traps: Reorder early overwrite of FID Edgar E. Iglesias
2017-02-13 22:06   ` Stefano Stabellini
2017-02-07 19:42 ` [RFC v2 2/6] xen/arm: Introduce platform_hvc Edgar E. Iglesias
2017-02-13 22:08   ` Stefano Stabellini
2017-07-31 21:30     ` Edgar E. Iglesias
2017-02-07 19:42 ` [RFC v2 3/6] xen/arm: Allow platform_hvc to handle guest SMC calls Edgar E. Iglesias
2017-02-07 20:38   ` Tamas K Lengyel
2017-02-07 20:51     ` Julien Grall
2017-02-08  0:24       ` Tamas K Lengyel
2017-02-08  8:31         ` Edgar E. Iglesias
2017-02-08 16:40           ` Tamas K Lengyel
2017-02-08 16:58             ` Julien Grall
2017-02-08 17:21               ` Tamas K Lengyel
2017-02-08 17:29               ` Edgar E. Iglesias
2017-02-08 19:40                 ` Edgar E. Iglesias
2017-02-08 20:15                   ` Tamas K Lengyel
2017-02-08 22:04                     ` Julien Grall
2017-02-08 23:28                       ` Tamas K Lengyel
2017-02-09  0:08                         ` Julien Grall
2017-02-09  1:20                           ` Stefano Stabellini
2017-02-09  9:12                             ` Edgar E. Iglesias
2017-02-09  9:27                               ` Edgar E. Iglesias
2017-02-09 18:22                                 ` Stefano Stabellini
2017-02-09 18:25                                   ` Tamas K Lengyel
2017-02-09 18:43                                     ` Stefano Stabellini
2017-02-09 19:32                                       ` Tamas K Lengyel
2017-07-31 22:23                                         ` Edgar E. Iglesias
2017-08-01 10:37                                           ` Julien Grall
2017-08-01 11:40                                             ` Edgar E. Iglesias
2017-02-09 16:46                           ` Volodymyr Babchuk
2017-02-09 18:11                           ` Tamas K Lengyel
2017-02-09 18:39                             ` Julien Grall
2017-02-09 19:42                               ` Tamas K Lengyel
2017-02-09 20:01                                 ` Edgar E. Iglesias
2017-02-09 20:36                                   ` Tamas K Lengyel
2017-02-09 14:46                       ` Edgar E. Iglesias
2017-02-07 19:42 ` [RFC v2 4/6] xen/arm: Introduce call_smcc64 Edgar E. Iglesias
2017-02-13 22:11   ` Stefano Stabellini
2017-02-07 19:42 ` [RFC v2 5/6] xen/arm: zynqmp: Forward plaform specific firmware calls Edgar E. Iglesias
2017-02-14  0:02   ` Stefano Stabellini
2017-02-17 18:47   ` Julien Grall
2017-02-07 19:42 ` [RFC v2 6/6] xen/arm: zynqmp: Remove blacklist of ZynqMP's PM node Edgar E. Iglesias
2017-02-14  0:03   ` Stefano Stabellini

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