4

I am trying to work with linux softirq. A have a simple program that uses linux system calls defined in linux/interrupt.h:

//
// Created by kivi on 24.09.16.
//

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/stat.h>

#define SHARED_IRQ 17

static int irq = SHARED_IRQ, my_dev_id, irq_counter = 0;
module_param( irq, int, S_IRUGO );

/* The interrupt handler */ 
static irqreturn_t xxx_interrupt( int irq, void *dev_id ) { 
    printk( KERN_INFO "In the top-half: counter = %d\n", irq_counter );
   raise_softirq( XXX_SOFT_IRQ ); 
   return IRQ_HANDLED; 
}

/* The bottom half */ 
void xxx_analyze(struct softirq_action *str) { 
    irq_counter++;
    printk( KERN_INFO "In the bottom-half: counter = %d\n", irq_counter );
}

static int __init my_init( void ) {
    request_irq( irq, xxx_interrupt, 0, "xxx", NULL );
    open_softirq( XXX_SOFT_IRQ, xxx_analyze); 
    printk( KERN_INFO "Successfully set softirq handler on IRQ %d\n", irq );
    return 0;
}

static void __exit my_exit( void ) {
    synchronize_irq( irq );
    free_irq( irq, &my_dev_id );
    printk( KERN_INFO "Successfully unloading, irq_counter = %d\n", irq_counter );
}

module_init( my_init );
module_exit( my_exit );
MODULE_LICENSE( "GPL v2" );

When I try to compile this module I get linker errors that functions open_softirq() and raise_softirq() are not defined:

kivi@kivi-pc:~/sp_labs/irq_exc/softirq$ make
make -C /lib/modules/4.7.5-custom/build M=/home/kivi/sp_labs/irq_exc/softirq modules
make[1]: Entering directory '/home/kivi/Downloads/linux-4.7.5'
  Building modules, stage 2.
  MODPOST 1 modules
WARNING: "open_softirq" [/home/kivi/sp_labs/irq_exc/softirq/softirq.ko] undefined!
WARNING: "raise_softirq" [/home/kivi/sp_labs/irq_exc/softirq/softirq.ko] undefined!
make[1]: Leaving directory '/home/kivi/Downloads/linux-4.7.5'

The interesting thing is that functions request_irq() e.t.c. are also defined in interrupt.h file, but they don't cause any problem.

Here is my Makefile:

obj-m += softirq.o

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

So can anyone help me please with my problem.

P.S. i googled my problem and found some advice that I should add KBUILD_EXTRA_SYMBOLS=*module path*/Module.symvers when compiling, but it didn't help.

2
  • I am no LKM guru, but last time I wrote a kernel module I had a similar problem and I had to set some special #define in order to link symbols marked with EXPORT_SYMBOL_GPL() Commented Sep 25, 2016 at 19:58
  • Can you please give more detailed description how to do it Commented Sep 26, 2016 at 17:07

1 Answer 1

4

The problem is that the open_softirq and raise_softirq functions are not exported, and so you cannot link to them. Exported functions are marked with the EXPORT_SYMBOL or EXPORT_SYMBOL_GPL macros.

On the other side, you will see how request_irq is exported (actually, it is inlined to request_threaded_irq, which is exported).

You can find plenty of information about the EXPORT_SYMBOL macros. For instance, here's an explanation from Robert Love.

Now, you are probably wondering why those functions aren't exported. Well, softirqs are a low-level mechanism, meant to be used by other higher-level facilities, so the intention is to prevent its usage in non-core kernel code.

Modules should use higher-level facilities instead (timers for instance).

It is interesting to check how many softirqs users the kernel has.

$ git grep open_softirq
block/blk-softirq.c:    open_softirq(BLOCK_SOFTIRQ, blk_done_softirq);
include/linux/interrupt.h:extern void open_softirq(int nr, void (*action)(struct softirq_action *));
kernel/rcu/tiny.c:      open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
kernel/rcu/tree.c:      open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
kernel/sched/fair.c:    open_softirq(SCHED_SOFTIRQ, run_rebalance_domains);
kernel/softirq.c:void open_softirq(int nr, void (*action)(struct softirq_action *))
kernel/softirq.c:       open_softirq(TASKLET_SOFTIRQ, tasklet_action);
kernel/softirq.c:       open_softirq(HI_SOFTIRQ, tasklet_hi_action);
kernel/time/timer.c:    open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
lib/irq_poll.c: open_softirq(IRQ_POLL_SOFTIRQ, irq_poll_softirq);
net/core/dev.c: open_softirq(NET_TX_SOFTIRQ, net_tx_action);
net/core/dev.c: open_softirq(NET_RX_SOFTIRQ, net_rx_action);

Just 12!

This pattern repeats across the kernel: stuff that maintainers consider lowish-level is not exported and meant for core kernel code only.

Sign up to request clarification or add additional context in comments.

6 Comments

Can you please give me some example how to use it for linux kernel functions. I googled something and all I found is examples for exporting your own symbols from module. I tried to add EXPORT_SYMBOL for raise_softirq and open_softirq, but now I get compile errors.
Also, google says, that if symbol is already exported somewhere with EXPORT_SYMBOL, then it's available in all kernel modules. open_softirq and raise_softirq are already exported in kernel/softirq.c. So I don't really understand what is happening.
First of all, no open/raise_sofirq are not exported. The open_softirq export was removed ages ago back in 2006, see here lkml.org/lkml/2006/7/11/264.
Second, the build error is maybe the XXX_SOFT_IRQ not being defined anywhere? Or otherwise, point me at your build error. But it would have nothing to do with this particular question ;)
I manually added XXX_SOFT_IRQ into interrupts.h file and rebuilded kernel. THere are two errors when compiling my module: include/linux/export.h:63:39: error: section attribute cannot be specified for local variables __visible const struct kernel_symbol __ksymtab_##sym \ ; include/linux/export.h:63:39: error: declaration of ‘__ksymtab_raise_softirq’ with no linkage follows extern declaration __visible const struct kernel_symbol __ksymtab_##sym \ I can't understand what they are mean
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.