[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [RFC v2 5/6] xen/arm: zynqmp: Forward plaform specific firmware calls



On Tue, 7 Feb 2017, Edgar E. Iglesias wrote:
> From: "Edgar E. Iglesias" <edgar.iglesias@xxxxxxxxxx>
> 
> 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@xxxxxxxxxx>
> ---
>  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@xxxxxxxxxx>
> + *
> + * 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@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.