/* * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of ARM nor the names of its contributors may be used * to endorse or promote products derived from this software without specific * prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __ARCH_HELPERS_H__ #define __ARCH_HELPERS_H__ #include /* for additional register definitions */ #include /* For __dead2 */ #include /********************************************************************** * Macros which create inline functions to read or write CPU system * registers *********************************************************************/ #define _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \ static inline uint64_t read_ ## _name(void) \ { \ uint64_t v; \ __asm__ volatile ("mrs %0, " #_reg_name : "=r" (v)); \ return v; \ } #define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) \ static inline void write_ ## _name(uint64_t v) \ { \ __asm__ volatile ("msr " #_reg_name ", %0" : : "r" (v)); \ } #define _DEFINE_SYSREG_WRITE_CONST_FUNC(_name, _reg_name) \ static inline void write_ ## _name(const uint64_t v) \ { \ __asm__ volatile ("msr " #_reg_name ", %0" : : "i" (v)); \ } /* Define read function for system register */ #define DEFINE_SYSREG_READ_FUNC(_name) \ _DEFINE_SYSREG_READ_FUNC(_name, _name) /* Define read & write function for system register */ #define DEFINE_SYSREG_RW_FUNCS(_name) \ _DEFINE_SYSREG_READ_FUNC(_name, _name) \ _DEFINE_SYSREG_WRITE_FUNC(_name, _name) /* Define read & write function for renamed system register */ #define DEFINE_RENAME_SYSREG_RW_FUNCS(_name, _reg_name) \ _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \ _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) /* Define write function for special system registers */ #define DEFINE_SYSREG_WRITE_CONST_FUNC(_name) \ _DEFINE_SYSREG_WRITE_CONST_FUNC(_name, _name) /********************************************************************** * Macros to create inline functions for system instructions *********************************************************************/ /* Define function for simple system instruction */ #define DEFINE_SYSOP_FUNC(_op) \ static inline void _op(void) \ { \ __asm__ (#_op); \ } /* Define function for system instruction with type specifier */ #define DEFINE_SYSOP_TYPE_FUNC(_op, _type) \ static inline void _op ## _type(void) \ { \ __asm__ (#_op " " #_type); \ } /* Define function for system instruction with register parameter */ #define DEFINE_SYSOP_TYPE_PARAM_FUNC(_op, _type) \ static inline void _op ## _type(uint64_t v) \ { \ __asm__ (#_op " " #_type ", %0" : : "r" (v)); \ } /******************************************************************************* * Aarch64 translation tables manipulation helper prototypes ******************************************************************************/ uint64_t create_table_desc(uint64_t *next_table_ptr); uint64_t create_block_desc(uint64_t desc, uint64_t addr, uint32_t level); uint64_t create_device_block(uint64_t output_addr, uint32_t level, uint32_t ns); uint64_t create_romem_block(uint64_t output_addr, uint32_t level, uint32_t ns); uint64_t create_rwmem_block(uint64_t output_addr, uint32_t level, uint32_t ns); /******************************************************************************* * TLB maintenance accessor prototypes ******************************************************************************/ DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1) DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1is) DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2) DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2is) DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3) DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3is) DEFINE_SYSOP_TYPE_FUNC(tlbi, vmalle1) /******************************************************************************* * Cache maintenance accessor prototypes ******************************************************************************/ DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, isw) DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cisw) DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, csw) DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvac) DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, ivac) DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, civac) DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvau) DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, zva) /******************************************************************************* * Address translation accessor prototypes ******************************************************************************/ DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e1r) DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e1w) DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e0r) DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e0w) void flush_dcache_range(uint64_t, uint64_t); void clean_dcache_range(uint64_t, uint64_t); void inv_dcache_range(uint64_t, uint64_t); void dcsw_op_louis(uint32_t); void dcsw_op_all(uint32_t); void disable_mmu_el3(void); void disable_mmu_icache_el3(void); /******************************************************************************* * Misc. accessor prototypes ******************************************************************************/ DEFINE_SYSREG_WRITE_CONST_FUNC(daifset) DEFINE_SYSREG_WRITE_CONST_FUNC(daifclr) #define enable_irq() write_daifclr(DAIF_IRQ_BIT) #define enable_fiq() write_daifclr(DAIF_FIQ_BIT) #define enable_serror() write_daifclr(DAIF_ABT_BIT) #define enable_debug_exceptions() write_daifclr(DAIF_DBG_BIT) #define disable_irq() write_daifset(DAIF_IRQ_BIT) #define disable_fiq() write_daifset(DAIF_FIQ_BIT) #define disable_serror() write_daifset(DAIF_ABT_BIT) #define disable_debug_exceptions() write_daifset(DAIF_DBG_BIT) DEFINE_SYSREG_READ_FUNC(par_el1) DEFINE_SYSREG_READ_FUNC(id_pfr1_el1) DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1) DEFINE_SYSREG_READ_FUNC(CurrentEl) DEFINE_SYSREG_RW_FUNCS(daif) DEFINE_SYSREG_RW_FUNCS(spsr_el1) DEFINE_SYSREG_RW_FUNCS(spsr_el2) DEFINE_SYSREG_RW_FUNCS(spsr_el3) DEFINE_SYSREG_RW_FUNCS(elr_el1) DEFINE_SYSREG_RW_FUNCS(elr_el2) DEFINE_SYSREG_RW_FUNCS(elr_el3) DEFINE_SYSOP_FUNC(wfi) DEFINE_SYSOP_FUNC(wfe) DEFINE_SYSOP_FUNC(sev) DEFINE_SYSOP_TYPE_FUNC(dsb, sy) DEFINE_SYSOP_TYPE_FUNC(dmb, sy) DEFINE_SYSOP_TYPE_FUNC(dsb, ish) DEFINE_SYSOP_TYPE_FUNC(dmb, ish) DEFINE_SYSOP_FUNC(isb) uint32_t get_afflvl_shift(uint32_t); uint32_t mpidr_mask_lower_afflvls(uint64_t, uint32_t); void __dead2 eret(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7); void __dead2 smc(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7); /******************************************************************************* * System register accessor prototypes ******************************************************************************/ DEFINE_SYSREG_READ_FUNC(midr_el1) DEFINE_SYSREG_READ_FUNC(mpidr_el1) DEFINE_SYSREG_RW_FUNCS(scr_el3) DEFINE_SYSREG_RW_FUNCS(hcr_el2) DEFINE_SYSREG_RW_FUNCS(vbar_el1) DEFINE_SYSREG_RW_FUNCS(vbar_el2) DEFINE_SYSREG_RW_FUNCS(vbar_el3) DEFINE_SYSREG_RW_FUNCS(sctlr_el1) DEFINE_SYSREG_RW_FUNCS(sctlr_el2) DEFINE_SYSREG_RW_FUNCS(sctlr_el3) DEFINE_SYSREG_RW_FUNCS(actlr_el1) DEFINE_SYSREG_RW_FUNCS(actlr_el2) DEFINE_SYSREG_RW_FUNCS(actlr_el3) DEFINE_SYSREG_RW_FUNCS(esr_el1) DEFINE_SYSREG_RW_FUNCS(esr_el2) DEFINE_SYSREG_RW_FUNCS(esr_el3) DEFINE_SYSREG_RW_FUNCS(afsr0_el1) DEFINE_SYSREG_RW_FUNCS(afsr0_el2) DEFINE_SYSREG_RW_FUNCS(afsr0_el3) DEFINE_SYSREG_RW_FUNCS(afsr1_el1) DEFINE_SYSREG_RW_FUNCS(afsr1_el2) DEFINE_SYSREG_RW_FUNCS(afsr1_el3) DEFINE_SYSREG_RW_FUNCS(far_el1) DEFINE_SYSREG_RW_FUNCS(far_el2) DEFINE_SYSREG_RW_FUNCS(far_el3) DEFINE_SYSREG_RW_FUNCS(mair_el1) DEFINE_SYSREG_RW_FUNCS(mair_el2) DEFINE_SYSREG_RW_FUNCS(mair_el3) DEFINE_SYSREG_RW_FUNCS(amair_el1) DEFINE_SYSREG_RW_FUNCS(amair_el2) DEFINE_SYSREG_RW_FUNCS(amair_el3) DEFINE_SYSREG_READ_FUNC(rvbar_el1) DEFINE_SYSREG_READ_FUNC(rvbar_el2) DEFINE_SYSREG_READ_FUNC(rvbar_el3) DEFINE_SYSREG_RW_FUNCS(rmr_el1) DEFINE_SYSREG_RW_FUNCS(rmr_el2) DEFINE_SYSREG_RW_FUNCS(rmr_el3) DEFINE_SYSREG_RW_FUNCS(tcr_el1) DEFINE_SYSREG_RW_FUNCS(tcr_el2) DEFINE_SYSREG_RW_FUNCS(tcr_el3) DEFINE_SYSREG_RW_FUNCS(ttbr0_el1) DEFINE_SYSREG_RW_FUNCS(ttbr0_el2) DEFINE_SYSREG_RW_FUNCS(ttbr0_el3) DEFINE_SYSREG_RW_FUNCS(ttbr1_el1) DEFINE_SYSREG_RW_FUNCS(cptr_el2) DEFINE_SYSREG_RW_FUNCS(cptr_el3) DEFINE_SYSREG_RW_FUNCS(cpacr_el1) DEFINE_SYSREG_RW_FUNCS(cntfrq_el0) DEFINE_SYSREG_RW_FUNCS(cntps_ctl_el1) DEFINE_SYSREG_RW_FUNCS(cntps_tval_el1) DEFINE_SYSREG_RW_FUNCS(cntps_cval_el1) DEFINE_SYSREG_READ_FUNC(cntpct_el0) DEFINE_SYSREG_RW_FUNCS(cnthctl_el2) DEFINE_SYSREG_RW_FUNCS(tpidr_el3) DEFINE_SYSREG_RW_FUNCS(cntvoff_el2) DEFINE_SYSREG_RW_FUNCS(vpidr_el2) DEFINE_SYSREG_RW_FUNCS(vmpidr_el2) DEFINE_SYSREG_READ_FUNC(isr_el1) DEFINE_SYSREG_READ_FUNC(ctr_el0) /* GICv3 System Registers */ DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1) DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el2, ICC_SRE_EL2) DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el3, ICC_SRE_EL3) DEFINE_RENAME_SYSREG_RW_FUNCS(icc_pmr_el1, ICC_PMR_EL1) #define IS_IN_EL(x) \ (GET_EL(read_CurrentEl()) == MODE_EL##x) #define IS_IN_EL1() IS_IN_EL(1) #define IS_IN_EL3() IS_IN_EL(3) /* Previously defined accesor functions with incomplete register names */ #define read_current_el() read_CurrentEl() #define dsb() dsbsy() #define read_midr() read_midr_el1() #define read_mpidr() read_mpidr_el1() #define read_scr() read_scr_el3() #define write_scr(_v) write_scr_el3(_v) #define read_hcr() read_hcr_el2() #define write_hcr(_v) write_hcr_el2(_v) #define read_cpacr() read_cpacr_el1() #define write_cpacr(_v) write_cpacr_el1(_v) #endif /* __ARCH_HELPERS_H__ */