[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v5 6/7] xen/arm: zynqmp: implement zynqmp_eemi
From: "Edgar E. Iglesias" <edgar.iglesias@xxxxxxxxxx> From: Edgar E. Iglesias <edgar.iglesias@xxxxxxxxxx> zynqmp_eemi uses the defined functions and structs to decide whether to make a call to the firmware, or to simply return a predefined value. Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xxxxxxxxxx> Signed-off-by: Stefano Stabellini <stefanos@xxxxxxxxxx> --- Changes in v5: - remove mmio_access handling Changes in v4: - add #include as needed - improve comment - code style --- xen/arch/arm/platforms/xilinx-zynqmp-eemi.c | 181 +++++++++++++++++++--------- 1 file changed, 125 insertions(+), 56 deletions(-) diff --git a/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c b/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c index 92a02df..9ecf286 100644 --- a/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c +++ b/xen/arch/arm/platforms/xilinx-zynqmp-eemi.c @@ -76,10 +76,10 @@ #include <xen/iocap.h> #include <xen/sched.h> +#include <asm/smccc.h> #include <asm/regs.h> #include <asm/platforms/xilinx-zynqmp-eemi.h> -#if 0 struct pm_access { mfn_t mfn; @@ -309,67 +309,136 @@ static bool domain_has_reset_access(struct domain *d, uint32_t rst) return pm_check_access(pm_reset_access, d, rst); } -/* - * 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_has_mmio_access(struct domain *d, - bool write, paddr_t addr, - uint32_t *mask) +bool zynqmp_eemi(struct cpu_user_regs *regs) { - unsigned int i; - bool ret = false; - uint32_t prot_mask = 0; - - /* - * The hardware domain gets read access to everything. - * Lower layers will do further filtering. - */ - if ( !write && is_hardware_domain(d) ) - return true; + struct arm_smccc_res res; + uint32_t fid = get_user_reg(regs, 0); + uint32_t nodeid = get_user_reg(regs, 1); + unsigned int pm_fn = fid & 0xFFFF; + enum pm_ret_status ret; - /* Scan the ACL. */ - for ( i = 0; i < ARRAY_SIZE(pm_mmio_access); i++ ) + switch ( pm_fn ) { - ASSERT(pm_mmio_access[i].start + pm_mmio_access[i].size >= - pm_mmio_access[i].start); - - if ( addr < pm_mmio_access[i].start ) - return false; - if ( addr >= pm_mmio_access[i].start + pm_mmio_access[i].size ) - continue; - - if ( write && pm_mmio_access[i].readonly ) - return false; - if ( pm_mmio_access[i].hwdom_access && !is_hardware_domain(d) ) - return false; - if ( !domain_has_node_access(d, pm_mmio_access[i].node) ) - return false; - - /* We've got access to this reg (or parts of it). */ - ret = true; - - /* Permit write access to selected bits. */ - prot_mask |= pm_mmio_access[i].mask ?: GENMASK(31, 0); - break; - } - /* - * Masking only applies to writes: values are safe to read, but not - * all bits are writeable. + * 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 or PSCI call which Xen will trap and act accordingly upon. */ - if ( write ) - *mask &= prot_mask; - - return ret; -} -#endif + case PM_SELF_SUSPEND: + ret = XST_PM_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, nodeid) ) + { + gprintk(XENLOG_WARNING, + "zynqmp-pm: fn=%u No access to node %u\n", pm_fn, nodeid); + ret = XST_PM_NO_ACCESS; + goto done; + } + goto forward_to_fw; + + case PM_RESET_ASSERT: + case PM_RESET_GET_STATUS: + if ( !domain_has_reset_access(current->domain, nodeid) ) + { + gprintk(XENLOG_WARNING, + "zynqmp-pm: fn=%u No access to reset %u\n", pm_fn, nodeid); + ret = XST_PM_NO_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_TRUSTZONE_VERSION: + case PM_GET_API_VERSION: + case PM_GET_CHIPID: + goto forward_to_fw; + + /* No MMIO access is allowed from non-secure domains */ + case PM_MMIO_WRITE: + case PM_MMIO_READ: + gprintk(XENLOG_WARNING, + "zynqmp-pm: fn=%u No MMIO access to %u\n", pm_fn, nodeid); + ret = XST_PM_NO_ACCESS; + goto done; + + /* Exclusive to the hardware domain. */ + case PM_INIT: + case PM_SET_CONFIGURATION: + case PM_FPGA_LOAD: + case PM_FPGA_GET_STATUS: + case PM_SECURE_SHA: + case PM_SECURE_RSA: + case PM_PINCTRL_SET_FUNCTION: + case PM_PINCTRL_REQUEST: + case PM_PINCTRL_RELEASE: + case PM_PINCTRL_GET_FUNCTION: + case PM_PINCTRL_CONFIG_PARAM_GET: + case PM_PINCTRL_CONFIG_PARAM_SET: + case PM_IOCTL: + case PM_QUERY_DATA: + case PM_CLOCK_ENABLE: + case PM_CLOCK_DISABLE: + case PM_CLOCK_GETSTATE: + case PM_CLOCK_GETDIVIDER: + case PM_CLOCK_SETDIVIDER: + case PM_CLOCK_SETRATE: + case PM_CLOCK_GETRATE: + case PM_CLOCK_SETPARENT: + case PM_CLOCK_GETPARENT: + if ( !is_hardware_domain(current->domain) ) + { + gprintk(XENLOG_WARNING, "eemi: fn=%u No access", pm_fn); + ret = XST_PM_NO_ACCESS; + goto done; + } + goto forward_to_fw; + + /* These calls are never allowed. */ + case PM_SYSTEM_SHUTDOWN: + ret = XST_PM_NO_ACCESS; + goto done; + + default: + gprintk(XENLOG_WARNING, "zynqmp-pm: Unhandled PM Call: %u\n", fid); + return false; + } -bool zynqmp_eemi(struct cpu_user_regs *regs) -{ - return false; +forward_to_fw: + arm_smccc_1_1_smc(get_user_reg(regs, 0), + get_user_reg(regs, 1), + get_user_reg(regs, 2), + get_user_reg(regs, 3), + get_user_reg(regs, 4), + get_user_reg(regs, 5), + get_user_reg(regs, 6), + get_user_reg(regs, 7), + &res); + + set_user_reg(regs, 0, res.a0); + set_user_reg(regs, 1, res.a1); + set_user_reg(regs, 2, res.a2); + set_user_reg(regs, 3, res.a3); + return true; + +done: + set_user_reg(regs, 0, ret); + return true; } /* -- 1.9.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |