linuxlinux-kernellinux-device-driverkernel-modulesoc

Communicate Kernel module and user space (Driver)


I am working with a SoC FPGA. In the past I have been testing some peripherals through polling, and now I want to work with interrupts.

I have followed some tutorials and now I have a driver which can detect interrupts on the IRQ 72. The problem is that I want to reply to that IRQ and I have been trying different things but none seems to work.

The last attempt was about a C program which would do the logic part, I mean, it will perform some action when the Kernel tells it an interrupt is present. This program is writting it's PID on a file, I want the kernel to read the PID to send the program a SIGUSR1 signal, and then the program will do smth.

Kernel module:

#include <linux/module.h>  // Needed by all modules
#include <linux/kernel.h>  // Needed for KERN_INFO
#include <linux/fs.h>      // Needed by filp
#include <asm/uaccess.h>   // Needed by segment descriptors
#include <linux/init.h>   /*Needed for the macros*/
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/of.h>

#define DEVNAME "test_int"

static irq_handler_t __test_isr(int irq, void *dev_id, struct pt_regs *regs){
    printk (KERN_INFO DEVNAME ": ISR\n");
    return (irq_handler_t) IRQ_HANDLED;
}

static int __test_int_driver_probe(struct platform_device* pdev){
    // Create variables
    struct file *f;
    char buf[128];
    mm_segment_t fs;
    int i;
    // Init the buffer with 0
    for(i=0;i<128;i++)
        buf[i] = 0;

    // PID file
    // It is an inteer, so i guess 4Bytes would be better
    f = filp_open("/home/root/modInt/miPID", O_RDONLY, 0);
    if(f == NULL)
        printk(KERN_ALERT "filp_open error!!.\n");
    else{
        // Get current segment descriptor
        fs = get_fs();
        // Set segment descriptor associated to kernel space
        set_fs(get_ds());
        // Read the file
        f->f_op->read(f, buf, 128, &f->f_pos);
        // Restore segment descriptor
        set_fs(fs);
        // See what we read from file
        printk("El PID es buf:%s\n",buf);
    }
    filp_close(f,NULL);
    int irq_num;
    irq_num = platform_get_irq(pdev, 0);
    printk(KERN_INFO DEVNAME ": La IRQ %d va a ser registrada!\n", irq_num);
    return request_irq(irq_num, (irq_handler_t) __test_isr, 0, DEVNAME, NULL);
}

static int __test_int_driver_remove (struct platform_device *pdev){
    int irq_num;
    irq_num = platform_get_irq (pdev, 0);
    printk(KERN_INFO "test_int: Abandonando la captura de la IRQ %d !\n", irq_num);
    free_irq(irq_num, NULL);
    return 0;
}

static const struct of_device_id __test_int_driver_id[] = {
    {.compatible = "altr , socfpga-mysoftip"},
    {}
};

static struct platform_driver __test_int_driver = {
    .driver= {
        .name = DEVNAME,
        .owner = THIS_MODULE,
        .of_match_table = of_match_ptr (__test_int_driver_id),
    },
    .probe = __test_int_driver_probe,
    .remove = __test_int_driver_remove
};

module_platform_driver (__test_int_driver);

MODULE_LICENSE("GPL");

Program:

#include<stdio.h>
#include<signal.h>
#include<unistd.h>

void sig_handler(int signo)
{
  if (signo == SIGUSR1)
    printf("Senal SIGUSR1 recibida\n");
}

int main(void){ 
    int pid=getpid();
    FILE *f = fopen("miPID", "w");
    if (f == NULL){
        printf("Error opening file!\n");
        exit(1);
    }
    fprintf(f, "%d", pid);
    fclose(f);

    printf("My process ID : %d\n", pid);
    if (signal(SIGUSR1, sig_handler) == SIG_ERR)
        printf("\nNo se ha podido capturar SIGINT\n");
    // A long long wait so that we can easily issue a signal to this process
    while(1) 
        sleep(1);
    return 0;
}

Compiles well under ARM arch. Errors when instantiating de module:

root@socfpga:~/modInt# insmod sigGen.ko
[   63.121696] sigGen: loading out-of-tree module taints kernel.
[   63.129185] Unable to handle kernel NULL pointer dereference at virtual address 00000000
[   63.138088] pgd = ee7b0000
[   63.140801] [00000000] *pgd=3fcb2831
[   63.144381] Internal error: Oops: 80000007 [#1] PREEMPT SMP ARM
[   63.144385] Modules linked in: sigGen(O+)
[   63.144399] CPU: 1 PID: 1350 Comm: insmod Tainted: G           O    4.14.73-rt45-ltsi #2
[   63.144401] Hardware name: Altera SOCFPGA
[   63.144406] task: ee9c3f00 task.stack: ee618000
[   63.144411] PC is at 0x0
[   63.144423] LR is at __test_int_driver_probe+0x80/0x108 [sigGen]
[   63.144427] pc : [<00000000>]    lr : [<bf0000ec>]    psr: a0070013
[   63.144430] sp : ee619c20  ip : c0814080  fp : ee619ccc
[   63.144433] r10: 00000000  r9 : 00000003  r8 : bf000000
[   63.144437] r7 : ef279600  r6 : ee4c6000  r5 : ffffe000  r4 : 00000000
[   63.144441] r3 : ee4c6058  r2 : 00000080  r1 : ee619c28  r0 : ee4c6000
[   63.144446] Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[   63.144450] Control: 10c5387d  Table: 2e7b004a  DAC: 00000051
[   63.144454] Process insmod (pid: 1350, stack limit = 0xee618218)
[   63.144457] Stack: (0xee619c20 to 0xee61a000)
[   63.144465] 9c20: 00000000 c04c3280 00000000 00000000 00000000 00000000 00000000 00000000
[   63.144472] 9c40: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[   63.144478] 9c60: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[   63.144484] 9c80: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[   63.144491] 9ca0: 00000000 00000000 ef279610 ef279610 ef279610 bf002014 fffffdfb bf002014
[   63.144499] 9cc0: ee619cec ee619cd0 c050ffb8 bf000078 ef279610 c0cabf84 c0cabf9c 00000000
[   63.144506] 9ce0: ee619d1c ee619cf0 c050def8 c050ff68 00000000 ef279610 bf002014 ef279644
[   63.144512] 9d00: 00000000 bf0020c8 11b4365c bf002080 ee619d3c ee619d20 c050e084 c050dcf4
[   63.144519] 9d20: 00000000 bf002014 c050dfc8 00000000 ee619d64 ee619d40 c050bf34 c050dfd4
[   63.144526] 9d40: ef02b06c ef28f248 c07afb2c bf002014 ef26a380 c0c56658 ee619d74 ee619d68
[   63.144533] 9d60: c050d86c c050bec4 ee619d9c ee619d78 c050d338 c050d84c bf0012c8 ee619d88
[   63.144540] 9d80: bf002014 bf005000 00000000 00000001 ee619db4 ee619da0 c050edb0 c050d198
[   63.144547] 9da0: bf002080 bf005000 ee619dc4 ee619db8 c050ff08 c050ed34 ee619dd4 ee619dc8
[   63.144554] 9dc0: bf005020 c050fec4 ee619e44 ee619dd8 c0101870 bf00500c ee618000 ef001e40
[   63.144561] 9de0: ee619df8 ee618038 ee619e34 ee619df8 c025d0cc c025bb1c ee619e44 ee619e08
[   63.144569] 9e00: c025bb1c c0257780 00000001 0000001f ee4037c0 ee618008 00000001 bf002080
[   63.144575] 9e20: 00000001 bf002080 00000001 ee72fbc0 bf0020c8 11b4365c ee619e6c ee619e48
[   63.144582] 9e40: c01accac c010182c ee619e6c ee619e58 c024c6a8 ee619f40 00000001 ee4bc9c0
[   63.144590] 9e60: ee619f1c ee619e70 c01aba50 c01acc44 bf00208c 00007fff bf002080 c01a8a04
[   63.144596] 9e80: bf002264 00000000 c0947650 bf0021b0 bf002180 00000000 c0803938 ee619f40
[   63.144603] 9ea0: ee619eec ee619eb0 c026b078 c0264e58 00000001 00000000 00000000 00000000
[   63.144609] 9ec0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[   63.144615] 9ee0: 00000000 00000000 00000000 00000000 7fffffff 00000000 00000003 000188e1
[   63.144622] 9f00: 0000017b c01080c4 ee618000 00000000 ee619fa4 ee619f20 c01ac274 c01a9c24
[   63.144629] 9f20: 7fffffff 00000000 00000003 00000000 00000000 f0b1e000 0001ef00 00000000
[   63.144636] 9f40: f0b1e412 f0b1e000 0001ef00 f0b3c7a8 f0b3c5d4 f0b35a50 00003000 00003080
[   63.144643] 9f60: 00000000 00000000 00000000 000016fc 0000002c 0000002d 00000018 00000000
[   63.144649] 9f80: 00000012 00000000 00000000 00000000 00000000 beb4cd88 00000000 ee619fa8
[   63.144656] 9fa0: c0107ee0 c01ac1e4 00000000 00000000 00000003 000188e1 00000000 00000002
[   63.144662] 9fc0: 00000000 00000000 beb4cd88 0000017b 00000000 00000000 b6f67000 00000000
[   63.144669] 9fe0: beb4cbc0 beb4cbb0 00013fef b6eb7990 60070010 00000003 00000000 00000000
[   63.144695] [<bf0000ec>] (__test_int_driver_probe [sigGen]) from [<c050ffb8>] (platform_drv_probe+0x5c/0xc0)
[   63.144708] [<c050ffb8>] (platform_drv_probe) from [<c050def8>] (driver_probe_device+0x210/0x2e0)
[   63.144718] [<c050def8>] (driver_probe_device) from [<c050e084>] (__driver_attach+0xbc/0xc0)
[   63.144731] [<c050e084>] (__driver_attach) from [<c050bf34>] (bus_for_each_dev+0x7c/0xb0)
[   63.144741] [<c050bf34>] (bus_for_each_dev) from [<c050d86c>] (driver_attach+0x2c/0x30)
[   63.144749] [<c050d86c>] (driver_attach) from [<c050d338>] (bus_add_driver+0x1ac/0x224)
[   63.144757] [<c050d338>] (bus_add_driver) from [<c050edb0>] (driver_register+0x88/0x108)
[   63.144766] [<c050edb0>] (driver_register) from [<c050ff08>] (__platform_driver_register+0x50/0x58)
[   63.144778] [<c050ff08>] (__platform_driver_register) from [<bf005020>] (__test_int_driver_init+0x20/0x1000 [sigGen])
[   63.144792] [<bf005020>] (__test_int_driver_init [sigGen]) from [<c0101870>] (do_one_initcall+0x50/0x178)
[   63.144805] [<c0101870>] (do_one_initcall) from [<c01accac>] (do_init_module+0x74/0x20c)
[   63.144815] [<c01accac>] (do_init_module) from [<c01aba50>] (load_module+0x1e38/0x2468)
[   63.144824] [<c01aba50>] (load_module) from [<c01ac274>] (SyS_finit_module+0x9c/0xac)
[   63.144834] [<c01ac274>] (SyS_finit_module) from [<c0107ee0>] (ret_fast_syscall+0x0/0x5c)
[   63.144843] Code: bad PC value
[   63.487534] dw_mmc ff704000.dwmmc0: Unexpected interrupt latency
[   63.613936] ---[ end trace 0000000000000002 ]---
Segmentation fault
root@socfpga:~/modInt#
Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144381] Internal error: Oops: 80000007 [#1] PREEMPT SMP ARM


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144454] Process insmod (pid: 1350, stack limit = 0xee618218)


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144457] Stack: (0xee619c20 to 0xee61a000)


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144465] 9c20: 00000000 c04c3280 00000000 00000000 00000000 00000000 00000000 00000000


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144472] 9c40: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144478] 9c60: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144484] 9c80: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144491] 9ca0: 00000000 00000000 ef279610 ef279610 ef279610 bf002014 fffffdfb bf002014


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144499] 9cc0: ee619cec ee619cd0 c050ffb8 bf000078 ef279610 c0cabf84 c0cabf9c 00000000


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144506] 9ce0: ee619d1c ee619cf0 c050def8 c050ff68 00000000 ef279610 bf002014 ef279644


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144512] 9d00: 00000000 bf0020c8 11b4365c bf002080 ee619d3c ee619d20 c050e084 c050dcf4


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144519] 9d20: 00000000 bf002014 c050dfc8 00000000 ee619d64 ee619d40 c050bf34 c050dfd4


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144526] 9d40: ef02b06c ef28f248 c07afb2c bf002014 ef26a380 c0c56658 ee619d74 ee619d68


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144533] 9d60: c050d86c c050bec4 ee619d9c ee619d78 c050d338 c050d84c bf0012c8 ee619d88


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144540] 9d80: bf002014 bf005000 00000000 00000001 ee619db4 ee619da0 c050edb0 c050d198


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144547] 9da0: bf002080 bf005000 ee619dc4 ee619db8 c050ff08 c050ed34 ee619dd4 ee619dc8


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144554] 9dc0: bf005020 c050fec4 ee619e44 ee619dd8 c0101870 bf00500c ee618000 ef001e40


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144561] 9de0: ee619df8 ee618038 ee619e34 ee619df8 c025d0cc c025bb1c ee619e44 ee619e08


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144569] 9e00: c025bb1c c0257780 00000001 0000001f ee4037c0 ee618008 00000001 bf002080


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144575] 9e20: 00000001 bf002080 00000001 ee72fbc0 bf0020c8 11b4365c ee619e6c ee619e48


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144582] 9e40: c01accac c010182c ee619e6c ee619e58 c024c6a8 ee619f40 00000001 ee4bc9c0


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144590] 9e60: ee619f1c ee619e70 c01aba50 c01acc44 bf00208c 00007fff bf002080 c01a8a04


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144596] 9e80: bf002264 00000000 c0947650 bf0021b0 bf002180 00000000 c0803938 ee619f40


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144603] 9ea0: ee619eec ee619eb0 c026b078 c0264e58 00000001 00000000 00000000 00000000


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144609] 9ec0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144615] 9ee0: 00000000 00000000 00000000 00000000 7fffffff 00000000 00000003 000188e1


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144622] 9f00: 0000017b c01080c4 ee618000 00000000 ee619fa4 ee619f20 c01ac274 c01a9c24


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144629] 9f20: 7fffffff 00000000 00000003 00000000 00000000 f0b1e000 0001ef00 00000000


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144636] 9f40: f0b1e412 f0b1e000 0001ef00 f0b3c7a8 f0b3c5d4 f0b35a50 00003000 00003080


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144643] 9f60: 00000000 00000000 00000000 000016fc 0000002c 0000002d 00000018 00000000


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144649] 9f80: 00000012 00000000 00000000 00000000 00000000 beb4cd88 00000000 ee619fa8


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144656] 9fa0: c0107ee0 c01ac1e4 00000000 00000000 00000003 000188e1 00000000 00000002


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144662] 9fc0: 00000000 00000000 beb4cd88 0000017b 00000000 00000000 b6f67000 00000000


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144669] 9fe0: beb4cbc0 beb4cbb0 00013fef b6eb7990 60070010 00000003 00000000 00000000


Broadcast message from systemd-journald@socfpga (Thu 2019-02-14 04:16:01 UTC):

kernel[1283]: [   63.144843] Code: bad PC value

I am sure there are better ways and I would like to hear them. For example, I also tried to implement the logic on the IRQ handler, but... failed.

EDIT:

I changed a little bit my code as @suren99 suggested, I also added some printk to debug, and now i get this:

root@socfpga:~/leer# insmod leer.ko
[  527.785020] Opened the file successfully
[  527.788953] Value of ret is: -22
[  527.792438] The PID is: ▒▒▒8A▒▒�@
[  527.792476] test_int: La IRQ 41 va a ser registrada!

I must add that...

ret = kernel_read(fp, offset, buf, 512);

Why this is "-22"?

printk("The PID is: %s", buf);

If I printk this, then the answer is this: ▒▒▒8A▒▒�@

printk("The PID is: %s", *buf);

And if put this, then the pointer returns "null".

What am I doing wrong?


Solution

  • First of all, you shouldn't check the return value of filp_open with NULL. You should check if the call has succeeded by using IS_ERR()

    if (IS_ERR(f)) {
        pr_err("Error opening file")
    }
    

    I believe the file_open has returned an error pointer and you are trying to dereference it

    f->f_op->read(f, buf, 128, &f->f_pos);
    

    Alternatively, you can use addr2line to find which line has caused the kernel panic