diff --git a/scripts/0001-armv7m-support-basepri-primask-interrupt-locking.patch b/scripts/0001-armv7m-support-basepri-primask-interrupt-locking.patch new file mode 100644 index 0000000000..e0f9a1ef7e --- /dev/null +++ b/scripts/0001-armv7m-support-basepri-primask-interrupt-locking.patch @@ -0,0 +1,203 @@ +From ec2838a7609d8b671bfb44ed90d15c1467cc6f32 Mon Sep 17 00:00:00 2001 +From: Yonattan Louise +Date: Tue, 14 Apr 2015 16:38:42 -0500 +Subject: [PATCH] armv7m support basepri + primask interrupt locking + +Interrupt locking is not implemented as part of QEMU for ARM. Until +we are able to properly upstream a patch to the QEMU project, this +change provides a partial solution that enables the Cortex-M3 core. +This has not been tested with other ARM based platforms. + +This solution is for internal use. It is not ready for QEMU upstream. + +Solution created by Benjamin Walsh for qemu v1.5, and ported by +Yonattan Louise for qemu v2.x. + +Signed-off-by: Yonattan Louise +Signed-off-by: Dirk Brandewie +--- + cpu-exec.c | 16 +++++++++++++--- + hw/intc/arm_gic.c | 12 ++++++++++++ + hw/intc/armv7m_nvic.c | 12 ++++++++++++ + hw/intc/gic_internal.h | 2 ++ + pixman | 2 +- + target-arm/cpu-qom.h | 1 + + target-arm/cpu.h | 2 ++ + target-arm/helper.c | 28 +++++++++++++++++++++++++++- + 8 files changed, 70 insertions(+), 5 deletions(-) + +diff --git a/cpu-exec.c b/cpu-exec.c +index 38e5f02..2252f85 100644 +--- a/cpu-exec.c ++++ b/cpu-exec.c +@@ -492,9 +492,19 @@ int cpu_exec(CPUArchState *env) + the stack if an interrupt occurred at the wrong time. + We avoid this by disabling interrupts when + pc contains a magic address. */ +- if (interrupt_request & CPU_INTERRUPT_HARD +- && ((IS_M(env) && env->regs[15] < 0xfffffff0) +- || !(env->daif & PSTATE_I))) { ++ ++ int is_m_do_irq = !IS_M(env) || ( ++ (env->regs[15] < 0xfffffff0) ++#if !defined(TARGET_AARCH64) && !defined(CONFIG_USER_ONLY) ++ && arm_v7m_basepri_check(cpu) ); ++#else ++ ); ++#endif ++ int handle_irq = ( ++ (interrupt_request & CPU_INTERRUPT_HARD) && ++ is_m_do_irq && !(env->daif & PSTATE_I) ); ++ ++ if (handle_irq) { + cpu->exception_index = EXCP_IRQ; + cc->do_interrupt(cpu); + next_tb = 0; +diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c +index 1532ef9..fabe948 100644 +--- a/hw/intc/arm_gic.c ++++ b/hw/intc/arm_gic.c +@@ -177,6 +177,18 @@ static void gic_set_running_irq(GICState *s, int cpu, int irq) + gic_update(s); + } + ++int gic_get_next_irq(GICState *s, int cpu) ++{ ++ int irq = s->current_pending[cpu]; ++ int prio_check = GIC_GET_PRIORITY(irq, cpu) < s->running_priority[cpu]; ++ return prio_check ? irq : 1023; ++} ++ ++int gic_get_priority(GICState *s, int irq, int cpu) ++{ ++ return GIC_GET_PRIORITY(irq, cpu); ++} ++ + uint32_t gic_acknowledge_irq(GICState *s, int cpu) + { + int ret, irq, src; +diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c +index 1a7af45..3ce8733 100644 +--- a/hw/intc/armv7m_nvic.c ++++ b/hw/intc/armv7m_nvic.c +@@ -116,6 +116,12 @@ void armv7m_nvic_set_pending(void *opaque, int irq) + gic_set_pending_private(&s->gic, 0, irq); + } + ++int armv7m_nvic_get_priority(void *opaque, int irq, int cpu) ++{ ++ nvic_state *s = (nvic_state *)opaque; ++ return gic_get_priority(&s->gic, irq, cpu); ++} ++ + /* Make pending IRQ active. */ + int armv7m_nvic_acknowledge_irq(void *opaque) + { +@@ -138,6 +144,12 @@ void armv7m_nvic_complete_irq(void *opaque, int irq) + gic_complete_irq(&s->gic, 0, irq); + } + ++int armv7m_nvic_get_next_irq(void *opaque, int cpu) ++{ ++ nvic_state *s = (nvic_state *)opaque; ++ return gic_get_next_irq(&s->gic, cpu); ++} ++ + static uint32_t nvic_readl(nvic_state *s, uint32_t offset) + { + ARMCPU *cpu; +diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h +index 48a58d7..f1a919f 100644 +--- a/hw/intc/gic_internal.h ++++ b/hw/intc/gic_internal.h +@@ -61,6 +61,8 @@ void gic_complete_irq(GICState *s, int cpu, int irq); + void gic_update(GICState *s); + void gic_init_irqs_and_distributor(GICState *s, int num_irq); + void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val); ++int gic_get_next_irq(GICState *s, int cpu); ++int gic_get_priority(GICState *s, int irq, int cpu); + + static inline bool gic_test_pending(GICState *s, int irq, int cm) + { +diff --git a/pixman b/pixman +index 97336fa..87eea99 160000 +--- a/pixman ++++ b/pixman +@@ -1 +1 @@ +-Subproject commit 97336fad32acf802003855cd8bd6477fa49a12e3 ++Subproject commit 87eea99e443b389c978cf37efc52788bf03a0ee0 +diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h +index ee4fbb1..860fb6d 100644 +--- a/target-arm/cpu-qom.h ++++ b/target-arm/cpu-qom.h +@@ -191,6 +191,7 @@ void init_cpreg_list(ARMCPU *cpu); + + void arm_cpu_do_interrupt(CPUState *cpu); + void arm_v7m_cpu_do_interrupt(CPUState *cpu); ++int arm_v7m_basepri_check(CPUState *cs); + + void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, + int flags); +diff --git a/target-arm/cpu.h b/target-arm/cpu.h +index f101880..1c1ed5b 100644 +--- a/target-arm/cpu.h ++++ b/target-arm/cpu.h +@@ -683,6 +683,8 @@ void arm_cpu_list(FILE *f, fprintf_function cpu_fprintf); + void armv7m_nvic_set_pending(void *opaque, int irq); + int armv7m_nvic_acknowledge_irq(void *opaque); + void armv7m_nvic_complete_irq(void *opaque, int irq); ++int armv7m_nvic_get_priority(void *opaque, int irq, int cpu); ++int armv7m_nvic_get_next_irq(void *opaque, int cpu); + + /* Interface for defining coprocessor registers. + * Registers are defined in tables of arm_cp_reginfo structs +diff --git a/target-arm/helper.c b/target-arm/helper.c +index d343856..6a2a907 100644 +--- a/target-arm/helper.c ++++ b/target-arm/helper.c +@@ -3243,6 +3243,29 @@ static void switch_v7m_sp(CPUARMState *env, int process) + } + } + ++static inline int _get_cur_basepri(CPUARMState *env) ++{ ++ return (int)helper_v7m_mrs(env, 0x11); ++} ++ ++int arm_v7m_basepri_check(CPUState *cs) ++{ ++ ARMCPU *cpu = ARM_CPU(cs); ++ CPUARMState *env = &cpu->env; ++ int irq = armv7m_nvic_get_next_irq(env->nvic, 0); ++ ++ if (irq == 1023) ++ return 0; ++ ++ int basepri = _get_cur_basepri(env); ++ int irqpri = armv7m_nvic_get_priority(env->nvic, irq, 0); ++ ++ if (!basepri || (irqpri < basepri)) ++ return 1; ++ else ++ return 0; ++} ++ + static void do_v7m_exception_exit(CPUARMState *env) + { + uint32_t type; +@@ -3323,8 +3346,11 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) + armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG); + return; + case EXCP_IRQ: +- env->v7m.exception = armv7m_nvic_acknowledge_irq(env->nvic); ++ { ++ int exc = armv7m_nvic_acknowledge_irq(env->nvic); ++ env->v7m.exception = exc; + break; ++ } + case EXCP_EXCEPTION_EXIT: + do_v7m_exception_exit(env); + return; +-- +1.9.1 +