From b36292e2329cb705352fa5f81d998d8bee8835db Mon Sep 17 00:00:00 2001 From: Lionel Sambuc Date: Fri, 15 Feb 2013 01:07:04 +0100 Subject: [PATCH] ARM: Fix interrupt management Interrupts where not correctly masked while in kernel, which breaks one of the current main assumptions. Also remove some duplication on ARM asm files, and add a function to check the status of ARM irqs (not compiled by default) Change-Id: I3c25d2b388f93fd8fe423998b94b3c4f140ba831 --- kernel/arch/earm/Makefile.inc | 2 +- kernel/arch/earm/arch_reset.c | 1 + kernel/arch/earm/arch_system.c | 6 +- kernel/arch/earm/include/cpufunc.h | 247 +++++++++++++++++++---------- kernel/arch/earm/io_intr.S | 14 -- kernel/arch/earm/klib.S | 6 +- kernel/arch/earm/mpx.S | 2 + 7 files changed, 169 insertions(+), 109 deletions(-) delete mode 100644 kernel/arch/earm/io_intr.S diff --git a/kernel/arch/earm/Makefile.inc b/kernel/arch/earm/Makefile.inc index a9c8c6367..141bd2692 100644 --- a/kernel/arch/earm/Makefile.inc +++ b/kernel/arch/earm/Makefile.inc @@ -64,7 +64,7 @@ CLEANFILES+= ${ORIG_UNPAGED_OBJS} SRCS+= mpx.S arch_clock.c arch_do_vmctl.c arch_system.c \ omap_serial.c omap_timer.c omap_intr.c exception.c \ - io_intr.S klib.S memory.c \ + klib.S memory.c \ protect.c direct_tty_utils.c arch_reset.c \ pg_utils.c phys_copy.S phys_memset.S exc.S OBJS.kernel+= ${UNPAGED_OBJS} diff --git a/kernel/arch/earm/arch_reset.c b/kernel/arch/earm/arch_reset.c index 22cc62706..2269711f6 100644 --- a/kernel/arch/earm/arch_reset.c +++ b/kernel/arch/earm/arch_reset.c @@ -25,6 +25,7 @@ halt_cpu(void) asm volatile("dsb"); asm volatile("cpsie i"); asm volatile("wfi"); + asm volatile("cpsid i"); } void diff --git a/kernel/arch/earm/arch_system.c b/kernel/arch/earm/arch_system.c index 7d8357361..8d171e484 100644 --- a/kernel/arch/earm/arch_system.c +++ b/kernel/arch/earm/arch_system.c @@ -159,10 +159,8 @@ struct proc * arch_finish_switch_to_user(void) p = get_cpulocal_var(proc_ptr); *((reg_t *)stk) = (reg_t) p; - /* make sure I bit is clear in PSR so that interrupts won't be disabled - * once p's context is restored. this should not be possible. - */ - assert(!(p->p_reg.psr & PSR_I)); + /* turn interrupts on */ + p->p_reg.psr &= ~(PSR_I|PSR_F); return p; } diff --git a/kernel/arch/earm/include/cpufunc.h b/kernel/arch/earm/include/cpufunc.h index 37366204d..fbdc054a2 100644 --- a/kernel/arch/earm/include/cpufunc.h +++ b/kernel/arch/earm/include/cpufunc.h @@ -1,6 +1,23 @@ #ifndef _ARM_CPUFUNC_H #define _ARM_CPUFUNC_H +#if 0 +/* check interrupt state */ +static inline void check_int(unsigned int state, int line) +{ + unsigned int cpsr = 0; + + asm volatile("mrs %0, cpsr" : "=r" (cpsr)); + + if ((cpsr & PSR_F) != (state & PSR_F)) + printf("%d: FIQs are unexpectedly %s\n", line, (cpsr & PSR_F) ? "MASKED" : "UNMASKED"); + + if ((cpsr & PSR_I) != (state & PSR_I)) + printf("%d: IRQs are unexpectedly %s\n", line, (cpsr & PSR_I) ? "MASKED" : "UNMASKED"); + +} +#endif + /* Data memory barrier */ static inline void dmb(void) { @@ -28,8 +45,29 @@ static inline void barrier(void) static inline void refresh_tlb(void) { dsb(); + /* Invalidate entire unified TLB */ - asm volatile("mcr p15, 0, r0, c8, c7, 0 @ TLBIALL\n\t"); + asm volatile("mcr p15, 0, %[zero], c8, c7, 0 @ TLBIALL\n\t" : : [zero] "r" (0)); + +#if 0 + /* Invalidate entire data TLB */ + asm volatile("mcr p15, 0, %[zero], c8, c6, 0" : : [zero] "r" (0)); + + /* Invalidate entire instruction TLB */ + asm volatile("mcr p15, 0, %[zero], c8, c5, 0" : : [zero] "r" (0)); +#endif + +#if 0 + /* + * Invalidate all instruction caches to PoU. + * Also flushes branch target cache. + */ + asm volatile("mcr p15, 0, %[zero], c7, c5, 0" : : [zero] "r" (0)); + + /* Invalidate entire branch predictor array */ + asm volatile("mcr p15, 0, %[zero], c7, c5, 6" : : [zero] "r" (0)); /* flush BTB */ +#endif + dsb(); isb(); } @@ -38,236 +76,269 @@ static inline void refresh_tlb(void) /* Read System Control Register */ static inline u32_t read_sctlr() { - u32_t ctl; + u32_t ctl; - asm volatile("mrc p15, 0, %[ctl], c1, c0, 0 @ Read SCTLR\n\t" - : [ctl] "=r" (ctl)); - return ctl; + asm volatile("mrc p15, 0, %[ctl], c1, c0, 0 @ Read SCTLR\n\t" + : [ctl] "=r" (ctl)); + + return ctl; } /* Write System Control Register */ static inline void write_sctlr(u32_t ctl) { - asm volatile("mcr p15, 0, %[ctl], c1, c0, 0 @ Write SCTLR\n\t" - : : [ctl] "r" (ctl)); + asm volatile("mcr p15, 0, %[ctl], c1, c0, 0 @ Write SCTLR\n\t" + : : [ctl] "r" (ctl)); + isb(); } /* Read Translation Table Base Register 0 */ static inline u32_t read_ttbr0() { - u32_t bar; + u32_t bar; + + asm volatile("mrc p15, 0, %[bar], c2, c0, 0 @ Read TTBR0\n\t" + : [bar] "=r" (bar)); - asm volatile("mrc p15, 0, %[bar], c2, c0, 0 @ Read TTBR0\n\t" - : [bar] "=r" (bar)); - return bar; + return bar; } /* Write Translation Table Base Register 0 */ static inline void write_ttbr0(u32_t bar) { - barrier(); - asm volatile("mcr p15, 0, %[bar], c2, c0, 0 @ Write TTBR0\n\t" - : : [bar] "r" (bar)); - refresh_tlb(); + barrier(); + + asm volatile("mcr p15, 0, %[bar], c2, c0, 0 @ Write TTBR0\n\t" + : : [bar] "r" (bar)); + + refresh_tlb(); } /* Reload Translation Table Base Register 0 */ static inline void reload_ttbr0(void) { - reg_t ttbr = read_ttbr0(); - write_ttbr0(ttbr); - refresh_tlb(); + reg_t ttbr = read_ttbr0(); + + write_ttbr0(ttbr); } /* Read Translation Table Base Register 1 */ static inline u32_t read_ttbr1() { - u32_t bar; + u32_t bar; - asm volatile("mrc p15, 0, %[bar], c2, c0, 1 @ Read TTBR1\n\t" - : [bar] "=r" (bar)); - return bar; + asm volatile("mrc p15, 0, %[bar], c2, c0, 1 @ Read TTBR1\n\t" + : [bar] "=r" (bar)); + + return bar; } /* Write Translation Table Base Register 1 */ static inline void write_ttbr1(u32_t bar) { - barrier(); - asm volatile("mcr p15, 0, %[bar], c2, c0, 1 @ Write TTBR1\n\t" - : : [bar] "r" (bar)); - refresh_tlb(); + barrier(); + + asm volatile("mcr p15, 0, %[bar], c2, c0, 1 @ Write TTBR1\n\t" + : : [bar] "r" (bar)); + + refresh_tlb(); } /* Reload Translation Table Base Register 1 */ static inline void reload_ttbr1(void) { - reg_t ttbr = read_ttbr1(); - write_ttbr1(ttbr); - refresh_tlb(); + reg_t ttbr = read_ttbr1(); + + write_ttbr1(ttbr); } /* Read Translation Table Base Control Register */ static inline u32_t read_ttbcr() { - u32_t bcr; + u32_t bcr; + + asm volatile("mrc p15, 0, %[bcr], c2, c0, 2 @ Read TTBCR\n\t" + : [bcr] "=r" (bcr)); - asm volatile("mrc p15, 0, %[bcr], c2, c0, 2 @ Read TTBCR\n\t" - : [bcr] "=r" (bcr)); - return bcr; + return bcr; } /* Write Translation Table Base Control Register */ static inline void write_ttbcr(u32_t bcr) { - asm volatile("mcr p15, 0, %[bcr], c2, c0, 2 @ Write TTBCR\n\t" - : : [bcr] "r" (bcr)); + asm volatile("mcr p15, 0, %[bcr], c2, c0, 2 @ Write TTBCR\n\t" + : : [bcr] "r" (bcr)); + + isb(); } /* Read Domain Access Control Register */ static inline u32_t read_dacr() { - u32_t dacr; + u32_t dacr; + + asm volatile("mrc p15, 0, %[dacr], c3, c0, 0 @ Read DACR\n\t" + : [dacr] "=r" (dacr)); - asm volatile("mrc p15, 0, %[dacr], c3, c0, 0 @ Read DACR\n\t" - : [dacr] "=r" (dacr)); - return dacr; + return dacr; } /* Write Domain Access Control Register */ static inline void write_dacr(u32_t dacr) { - asm volatile("mcr p15, 0, %[dacr], c3, c0, 0 @ Write DACR\n\t" - : : [dacr] "r" (dacr)); + asm volatile("mcr p15, 0, %[dacr], c3, c0, 0 @ Write DACR\n\t" + : : [dacr] "r" (dacr)); + + isb(); } /* Read Data Fault Status Register */ static inline u32_t read_dfsr() { - u32_t fsr; + u32_t fsr; + + asm volatile("mrc p15, 0, %[fsr], c5, c0, 0 @ Read DFSR\n\t" + : [fsr] "=r" (fsr)); - asm volatile("mrc p15, 0, %[fsr], c5, c0, 0 @ Read DFSR\n\t" - : [fsr] "=r" (fsr)); - return fsr; + return fsr; } /* Write Data Fault Status Register */ static inline void write_dfsr(u32_t fsr) { - asm volatile("mcr p15, 0, %[fsr], c5, c0, 0 @ Write DFSR\n\t" - : : [fsr] "r" (fsr)); + asm volatile("mcr p15, 0, %[fsr], c5, c0, 0 @ Write DFSR\n\t" + : : [fsr] "r" (fsr)); + + isb(); } /* Read Instruction Fault Status Register */ static inline u32_t read_ifsr() { - u32_t fsr; + u32_t fsr; + + asm volatile("mrc p15, 0, %[fsr], c5, c0, 1 @ Read IFSR\n\t" + : [fsr] "=r" (fsr)); - asm volatile("mrc p15, 0, %[fsr], c5, c0, 1 @ Read IFSR\n\t" - : [fsr] "=r" (fsr)); - return fsr; + return fsr; } /* Write Instruction Fault Status Register */ static inline void write_ifsr(u32_t fsr) { - asm volatile("mcr p15, 0, %[fsr], c5, c0, 1 @ Write IFSR\n\t" - : : [fsr] "r" (fsr)); + asm volatile("mcr p15, 0, %[fsr], c5, c0, 1 @ Write IFSR\n\t" + : : [fsr] "r" (fsr)); + + isb(); } /* Read Data Fault Address Register */ static inline u32_t read_dfar() { - u32_t far; + u32_t far; + + asm volatile("mrc p15, 0, %[far], c6, c0, 0 @ Read DFAR\n\t" + : [far] "=r" (far)); - asm volatile("mrc p15, 0, %[far], c6, c0, 0 @ Read DFAR\n\t" - : [far] "=r" (far)); - return far; + return far; } /* Write Data Fault Address Register */ static inline void write_dfar(u32_t far) { - asm volatile("mcr p15, 0, %[far], c6, c0, 0 @ Write DFAR\n\t" - : : [far] "r" (far)); + asm volatile("mcr p15, 0, %[far], c6, c0, 0 @ Write DFAR\n\t" + : : [far] "r" (far)); + + isb(); } /* Read Instruction Fault Address Register */ static inline u32_t read_ifar() { - u32_t far; + u32_t far; + + asm volatile("mrc p15, 0, %[far], c6, c0, 2 @ Read IFAR\n\t" + : [far] "=r" (far)); - asm volatile("mrc p15, 0, %[far], c6, c0, 2 @ Read IFAR\n\t" - : [far] "=r" (far)); - return far; + return far; } /* Write Instruction Fault Address Register */ static inline void write_ifar(u32_t far) { - asm volatile("mcr p15, 0, %[far], c6, c0, 2 @ Write IFAR\n\t" - : : [far] "r" (far)); + asm volatile("mcr p15, 0, %[far], c6, c0, 2 @ Write IFAR\n\t" + : : [far] "r" (far)); + + isb(); } /* Read Vector Base Address Register */ static inline u32_t read_vbar() { - u32_t vbar; + u32_t vbar; + + asm volatile("mrc p15, 0, %[vbar], c12, c0, 0 @ Read VBAR\n\t" + : [vbar] "=r" (vbar)); - asm volatile("mrc p15, 0, %[vbar], c12, c0, 0 @ Read VBAR\n\t" - : [vbar] "=r" (vbar)); - return vbar; + return vbar; } /* Write Vector Base Address Register */ static inline void write_vbar(u32_t vbar) { - asm volatile("mcr p15, 0, %[vbar], c12, c0, 0 @ Write VBAR\n\t" - : : [vbar] "r" (vbar)); - asm volatile("dsb"); + asm volatile("mcr p15, 0, %[vbar], c12, c0, 0 @ Write VBAR\n\t" + : : [vbar] "r" (vbar)); + + isb(); } /* Read the Main ID Register */ static inline u32_t read_midr() { - u32_t id; + u32_t id; + + asm volatile("mrc p15, 0, %[id], c0, c0, 0 @ read MIDR\n\t" + : [id] "=r" (id)); - asm volatile("mrc p15, 0, %[id], c0, c0, 0 @ read MIDR\n\t" - : [id] "=r" (id)); - return id; + return id; } /* Read Auxiliary Control Register */ static inline u32_t read_actlr() { - u32_t ctl; + u32_t ctl; + + asm volatile("mrc p15, 0, %[ctl], c1, c0, 1 @ Read ACTLR\n\t" + : [ctl] "=r" (ctl)); - asm volatile("mrc p15, 0, %[ctl], c1, c0, 1 @ Read ACTLR\n\t" - : [ctl] "=r" (ctl)); - return ctl; + return ctl; } /* Write Auxiliary Control Register */ static inline void write_actlr(u32_t ctl) { - asm volatile("mcr p15, 0, %[ctl], c1, c0, 1 @ Write ACTLR\n\t" - : : [ctl] "r" (ctl)); + asm volatile("mcr p15, 0, %[ctl], c1, c0, 1 @ Write ACTLR\n\t" + : : [ctl] "r" (ctl)); + + isb(); } /* Read Current Program Status Register */ static inline u32_t read_cpsr() { - u32_t status; + u32_t status; + + asm volatile("mrs %[status], cpsr @ read CPSR" + : [status] "=r" (status)); - asm volatile("mrs %[status], cpsr @ read CPSR" - : [status] "=r" (status)); - return status; + return status; } /* Write Current Program Status Register */ static inline void write_cpsr(u32_t status) { - asm volatile("msr cpsr_c, %[status] @ write CPSR" - : : [status] "r" (status)); + asm volatile("msr cpsr_c, %[status] @ write CPSR" + : : [status] "r" (status)); } #endif /* _ARM_CPUFUNC_H */ diff --git a/kernel/arch/earm/io_intr.S b/kernel/arch/earm/io_intr.S deleted file mode 100644 index 60b420eaa..000000000 --- a/kernel/arch/earm/io_intr.S +++ /dev/null @@ -1,14 +0,0 @@ -/* intr_disable(), intr_enable - Disable/Enable hardware interrupts. */ -/* void intr_disable(void); */ -/* void intr_enable(void); */ -#include - -ENTRY(intr_disable) - dsb - cpsid i - bx lr - -ENTRY(intr_enable) - dsb - cpsie i - bx lr diff --git a/kernel/arch/earm/klib.S b/kernel/arch/earm/klib.S index 95bfa79bc..0294be7dd 100644 --- a/kernel/arch/earm/klib.S +++ b/kernel/arch/earm/klib.S @@ -82,12 +82,14 @@ ENTRY(__user_copy_msg_pointer_failure) mov r0, #-1 bx lr +ENTRY(intr_enable) ENTRY(interrupts_enable) dsb - cpsie i + cpsie if bx lr +ENTRY(intr_disable) ENTRY(interrupts_disable) dsb - cpsid i + cpsid if bx lr diff --git a/kernel/arch/earm/mpx.S b/kernel/arch/earm/mpx.S index bf8b2ed16..96bf3f538 100644 --- a/kernel/arch/earm/mpx.S +++ b/kernel/arch/earm/mpx.S @@ -53,6 +53,8 @@ IMPORT(svc_stack) .macro test_int_in_kernel, label push {r3} ldr r3, [sp, #8] /* spsr */ + orr r3, r3, #(PSR_F | PSR_I) /* mask interrupts on return */ + str r3, [sp, #8] /* spsr */ and r3, r3, #PSR_MODE_MASK cmp r3, #MODE_USR pop {r3} -- 2.44.0