InsaneCoder
InsaneCoder

Reputation: 8268

FIQ handler resulting in kernel panic "Bad Mode"

I am trying to setup an FIQ handler (first time). Its an ARM32 v7 core and kernel version is bit old (3.14.x) - shouldn't matter though. The source of FIQ is a GPIO pin. The core provides a CPU register where I have ensured that irq over this pin are all masked and only FIQ is enabled. Secondly no IRQ handlers are registered for this GPIO pin.

I am setting up FIQ handler from a kernel module (I understand that in-built should be better, but I didn't see a problem yet since code is pretty simple).

As first step, below is how my kernel module defines the FIQ handler. I am trying to increment a counter defined globally (static volatile int fiq_counter = 0;) within the kernel module upon each FIQ received.

asm(
    ".global wdog_fiq_handler_start\n"
    ".global wdog_fiq_handler_end\n"
    "wdog_fiq_handler_start:\n"

    /* Use FIQ-mode-specific register R8_fiq to manipulate the counter */
    "    ldr r9, [r8]\n"         // Load the current value of fiq_counter into r9 (FIQ banked register)
    "    add r9, r9, #1\n"       // Increment the counter                                                   "    str r9, [r8]\n"         // Store the incremented value back into fiq_counter
    "bx lr\n"


    "wdog_fiq_handler_end:\n"
); 

And then finally I register the FIQ handler :

    void *fiqhandler_start;
    unsigned int fiqhandler_length;
    extern unsigned char wdog_fiq_handler_end, wdog_fiq_handler_start;
    fiqhandler_start = &wdog_fiq_handler_start;
    fiqhandler_length = &wdog_fiq_handler_end - &wdog_fiq_handler_start;

    if (claim_fiq(&fh)) {
        pr_err("wdogfiq : couldn't claim FIQ.\n");
        return;
    }
    set_fiq_handler(fiqhandler_start, fiqhandler_length);
    get_fiq_regs(&regs);
    regs.ARM_r8 = (unsigned long)&fiq_counter;
    set_fiq_regs(&regs);
    enable_fiq(88);  /* hwirq 88 corresponding to GPIO pin */

The module loads successfully, no errors and I see my FIQ handler under /proc/interrupts. However, when I fire my FIQ, the kernel panics with error :

[ 4145.425070] Internal error: Oops - bad mode: 0 [#1] SMP ARM
[ 4145.523357] Process swapper/0 (pid: 0, stack limit = 0x808c0240)

Interesting thing is the following line :

[ 4145.719365] Code: e320f000 e320f000 e320f000 e320f000 (e5989000)

Here the value e5989000 in round brackets seem exactly my FIQ code when converted to hex (used armconverter.com) i.e.

009098E5
019089E2
009088E5
1EFF2FE1

So this is a good indication that my FIQ code was hit. But what is wrong here that it says bad mode?

Upvotes: 1

Views: 19

Answers (0)

Related Questions