From: Brian Cain <bc...@quicinc.com> ciad is the clear interrupt auto disable instruction.
Signed-off-by: Brian Cain <brian.c...@oss.qualcomm.com> --- target/hexagon/op_helper.c | 45 +++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/target/hexagon/op_helper.c b/target/hexagon/op_helper.c index a03fd078be..c38107d5a8 100644 --- a/target/hexagon/op_helper.c +++ b/target/hexagon/op_helper.c @@ -34,6 +34,12 @@ #include "op_helper.h" #include "cpu_helper.h" #include "translate.h" +#ifndef CONFIG_USER_ONLY +#include "hw/hexagon/hexagon_globalreg.h" +#include "hex_mmu.h" +#include "hw/intc/l2vic.h" +#include "hex_interrupts.h" +#endif #define SF_BIAS 127 #define SF_MANTBITS 23 @@ -1338,9 +1344,41 @@ void HELPER(vwhist128qm)(CPUHexagonState *env, int32_t uiV) } #ifndef CONFIG_USER_ONLY +static void hexagon_set_vid(CPUHexagonState *env, uint32_t offset, uint32_t val) +{ + g_assert((offset == L2VIC_VID_0) || (offset == L2VIC_VID_1)); + CPUState *cs = env_cpu(env); + HexagonCPU *cpu = HEXAGON_CPU(cs); + const hwaddr pend_mem = cpu->l2vic_base_addr + offset; + cpu_physical_memory_write(pend_mem, &val, sizeof(val)); +} + +static void hexagon_clear_last_irq(CPUHexagonState *env, uint32_t offset) +{ + hexagon_set_vid(env, offset, L2VIC_CIAD_INSTRUCTION); +} + +/* + * ciad - clear interrupt auto disable + * - When taking an interrupt the hardware will set ipend.iad to + * prevent another thread from servicing the interrupt. At the completion + * of service software uses ciad to clear the bit indicating the + * interrupt can be accepted again. + * - ciad also handshakes with the l2vic allowing a new vid on the vector + * port. + */ void HELPER(ciad)(CPUHexagonState *env, uint32_t mask) { - g_assert_not_reached(); + uint32_t ipendad; + uint32_t iad; + + BQL_LOCK_GUARD(); + ipendad = READ_SREG(HEX_SREG_IPENDAD); + iad = fGET_FIELD(ipendad, IPENDAD_IAD); + fSET_FIELD(ipendad, IPENDAD_IAD, iad & ~(mask)); + arch_set_system_reg(env, HEX_SREG_IPENDAD, ipendad); + hexagon_clear_last_irq(env, L2VIC_VID_0); + hex_interrupt_update(env); } void HELPER(siad)(CPUHexagonState *env, uint32_t mask) @@ -1416,11 +1454,6 @@ static void modify_syscfg(CPUHexagonState *env, uint32_t val) g_assert_not_reached(); } -static void hexagon_set_vid(CPUHexagonState *env, uint32_t offset, int val) -{ - g_assert_not_reached(); -} - static uint32_t hexagon_find_last_irq(CPUHexagonState *env, uint32_t vid) { g_assert_not_reached(); -- 2.34.1