Skip to contentSkip to conversation

2.4.6-pre3 unresolved symbol do_softirq

PATCH In review Keith Owens 7 participants 21 messages Jun 13, 2001

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 2.4.6-pre3 unresolved symbol do_softirq

do_softirq is called from asm code which does not get preprocessed. It needs to be exported with no version.

Against 2.4.6-pre3. Note to users: you must run make mrproper after applying this patch.

Index: 6-pre3.1/kernel/ksyms.c

kernel/ksyms.c Wed, 13 Jun 2001 22:04:07 +1000 kaos (linux-2.4/j/46_ksyms.c 1.1.2.2.1.1.2.1.1.8.2.1.2.1 644) renamed from kernel/ksyms.c Sat, 09 Jun 2001 11:25:53 +1000 kaos (linux-2.4/j/46_ksyms.c 1.1.2.2.1.1.2.1.1.8.2.1.2.1 644) +1 -1
@@ -536,7 +536,7 @@ EXPORT_SYMBOL(remove_bh);
 EXPORT_SYMBOL(tasklet_init);
 EXPORT_SYMBOL(tasklet_kill);
 EXPORT_SYMBOL(__run_task_queue);
-EXPORT_SYMBOL(do_softirq);
+EXPORT_SYMBOL_NOVERS(do_softirq);
 EXPORT_SYMBOL(tasklet_schedule);
 EXPORT_SYMBOL(tasklet_hi_schedule);
 
#1 lore raw
Quoted 2 lines · Keith Owens

do_softirq is called from asm code which does not get preprocessed. It needs to be exported with no version.

It can get preprocessed if you know how. Simply use the "i" asm constraint for an extra argument, and use the symbol there. For example:

	__asm__("%0" : : "i" (my_versioned_symbol));

It works and we've been doing it on sparc for ages.

Later,
David S. Miller
[email protected]

#2 lore raw
Quoted 11 lines · David S. Miller
Quoted 2 lines · Keith Owens

do_softirq is called from asm code which does not get preprocessed. It needs to be exported with no version.

It can get preprocessed if you know how. Simply use the "i" asm constraint for an extra argument, and use the symbol there. For example:

	__asm__("%0" : : "i" (my_versioned_symbol));

It works and we've been doing it on sparc for ages.

It works for integers but call do_softirq is more of a problem. I could not find an asm constraint that generated correct code in a single instruction. The closest I could get was
__asm__("call *%%eax" : : "a" (do_softirq));
The 'obvious'
__asm__("call %0" : : "m" (do_softirq));
calls to a location that contains the address of do_softirq, oops.

Any other architectures that call do_softirq inside asm would need similar hard coding of indirect branches. It is simpler to export do_softirq with no version, and have cleaner asm.

#3 lore raw
Quoted 11 lines · Keith Owens

It works for integers but call do_softirq is more of a problem. I could not find an asm constraint that generated correct code in a single instruction. The closest I could get was
__asm__("call *%%eax" : : "a" (do_softirq));
The 'obvious'
__asm__("call %0" : : "m" (do_softirq));
calls to a location that contains the address of do_softirq, oops.

Any other architectures that call do_softirq inside asm would need similar hard coding of indirect branches. It is simpler to export do_softirq with no version, and have cleaner asm.

Why doesn't this work on x86?

#define my_symbol my_symbol_versioned
extern void my_symbol(void);

__asm__("call %0" : : "i" (my_symbol));

Later,
David S. Miller
[email protected]

#4 lore raw
Quoted 6 lines · David S. Miller

Why doesn't this work on x86?

#define my_symbol my_symbol_versioned
extern void my_symbol(void);

__asm__("call %0" : : "i" (my_symbol));

#define my_symbol my_symbol_versioned
extern void my_symbol(void);

void foo(void) { __asm__("call %0" : : "i" (my_symbol)); }

# gcc -o x x.c
/tmp/cclWXduj.s: Assembler messages:
/tmp/cclWXduj.s:12: Error: suffix or operands invalid for `call'
#5 lore raw
Quoted 8 lines · Keith Owens

#define my_symbol my_symbol_versioned
extern void my_symbol(void);

void foo(void) { __asm__("call %0" : : "i" (my_symbol)); }

# gcc -o x x.c
/tmp/cclWXduj.s: Assembler messages:
/tmp/cclWXduj.s:12: Error: suffix or operands invalid for `call'

I can't believe there is no reliable way to get rid of that pesky "$" gcc is adding to the symbol. Oh well...

Later,
David S. Miller
[email protected]

#6 lore raw
In reply to Keith Owens
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

"Keith" == Keith Owens <[email protected]> writes:

Keith> #define my_symbol my_symbol_versioned extern void Keith> my_symbol(void);

Keith> void foo(void) { __asm__("call %0" : : "i" (my_symbol)); }

Keith> # gcc -o x x.c /tmp/cclWXduj.s: Assembler messages:
Keith> /tmp/cclWXduj.s:12: Error: suffix or operands invalid for Keith> `call'

Try ye' olde STRINGIFY and string concatenation? Well, at least I try...

     #define my_symbol my_symbol_versioned
     #define STRINGIFY(a) STRINGIFY1(a)
     #define STRINGIFY1(a) #a
     extern void my_symbol(void);

     void foo(void)
     {
         __asm__("call " STRINGIFY(my_symbol) "\n");
     }

     [bpringle@localhost bpringle]$ gcc -o x x.c
     /usr/lib/crt1.o(.text+0x18): undefined reference to `main'
     /tmp/ccIj9Cit.o: In function `foo':
     /tmp/ccIj9Cit.o(.text+0x4): undefined reference to `my_symbol_versioned'
     collect2: ld returned 1 exit status

regards,
Bill Pringlemeir.

#7 lore raw
Quoted 16 lines · Bill Pringlemeir

Try ye' olde STRINGIFY and string concatenation? Well, at least I try...

    #define my_symbol my_symbol_versioned
    #define STRINGIFY(a) STRINGIFY1(a)
    #define STRINGIFY1(a) #a
    extern void my_symbol(void);

    void foo(void)
    {
        __asm__("call " STRINGIFY(my_symbol) "\n");
    }

    [bpringle@localhost bpringle]$ gcc -o x x.c
    /usr/lib/crt1.o(.text+0x18): undefined reference to `main'
    /tmp/ccIj9Cit.o: In function `foo':
    /tmp/ccIj9Cit.o(.text+0x4): undefined reference to `my_symbol_versioned'

Only at the cost of polluting every .h file that calls a symbol from __asm__. The whole pre-processor kludge for symbol versions goes away in 2.5 so live with _novers for now.

#8 lore raw
In reply to Keith Owens
Quoted 5 lines · David S. Miller
Quoted 3 lines · Keith Owens

#define my_symbol my_symbol_versioned
extern void my_symbol(void);

Quoted 8 lines
Quoted 5 lines

void foo(void) { __asm__("call %0" : : "i" (my_symbol)); }

# gcc -o x x.c
/tmp/cclWXduj.s: Assembler messages:
/tmp/cclWXduj.s:12: Error: suffix or operands invalid for `call'

I can't believe there is no reliable way to get rid of that pesky "$" gcc is adding to the symbol. Oh well...

void foo(void) { __asm__("call %c0" : : "i" (my_symbol)); }

                               ^^^

-

#9 lore raw
In reply to David S. Miller

"David S. Miller" <[email protected]> writes:

|> Keith Owens writes:
|>  > #define my_symbol       my_symbol_versioned
|>  > extern void my_symbol(void);
|>  > 
|>  > void foo(void) { __asm__("call %0" : : "i" (my_symbol)); }
|>  > 
|>  > # gcc -o x x.c
|>  > /tmp/cclWXduj.s: Assembler messages:
|>  > /tmp/cclWXduj.s:12: Error: suffix or operands invalid for `call'
|> 
|> I can't believe there is no reliable way to get rid of that
|> pesky "$" gcc is adding to the symbol.  Oh well...

Use %c0. *Note Output Templates and Operand Substitution: (gcc)Output Template.

Andreas.

Signature · 5 lines
Andreas Schwab                                  "And now for something
SuSE Labs                                        completely different."
[email protected]
SuSE GmbH, Schanzäckerstr. 10, D-90443 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
#10 lore raw
Quoted 7 lines · Andreas Schwab

"David S. Miller" <[email protected]> writes:

|> I can't believe there is no reliable way to get rid of that |> pesky "$" gcc is adding to the symbol. Oh well...

Use %c0. *Note Output Templates and Operand Substitution: (gcc)Output Template.

Nice, see Keith? There are no excuses :-)

Later,
David S. Miller
[email protected]

#11 lore raw
Quoted 11 lines · David S. Miller
Quoted 7 lines · Andreas Schwab

"David S. Miller" <[email protected]> writes:

|> I can't believe there is no reliable way to get rid of that |> pesky "$" gcc is adding to the symbol. Oh well...

Use %c0. *Note Output Templates and Operand Substitution: (gcc)Output Template.

Nice, see Keith? There are no excuses :-)

Oh, there are always excuses ;). But in this case ...

Index: 6-pre3.1/include/asm-i386/softirq.h

include/asm-i386/softirq.h Thu, 14 Jun 2001 02:26:16 +1000 kaos (linux-2.4/T/51_softirq.h 1.3 644) renamed from include/asm-i386/softirq.h Sat, 09 Jun 2001 11:25:53 +1000 kaos (linux-2.4/T/51_softirq.h 1.3 644) +2 -2
@@ -36,13 +36,13 @@ do {									\
 									\
 			".section .text.lock,\"ax\";"			\
 			"2: pushl %%eax; pushl %%ecx; pushl %%edx;"	\
-			"call do_softirq;"				\
+			"call %c1;"					\
 			"popl %%edx; popl %%ecx; popl %%eax;"		\
 			"jmp 1b;"					\
 			".previous;"					\
 									\
 		: /* no output */					\
-		: "r" (ptr)						\
+		: "r" (ptr), "i" (do_softirq)				\
 		/* no registers clobbered */ );				\
 } while (0)
 

No changes to kernel/ksyms, it still says EXPORT_SYMBOL(do_softirq); I like it.

#12 lore raw
In reply to David S. Miller
Quoted 2 lines · David S. Miller

I can't believe there is no reliable way to get rid of that pesky "$" gcc is adding to the symbol. Oh well...

GCC on ARM does a similar thing - all constants in the assembler are prefixed with '#' or '@'. Using the 'i' constraint adds this. This behaviour is actually useful when you want to pass a constant or a register - it allows GCC to make the decision for you, and do the right thing in the assembler fragment. Eg, the following code used to be in the kernel until 2.3:

extern __inline__ void __outb (unsigned int value, unsigned int port)

{
        unsigned long temp;
        __asm__ __volatile__(
        "tst    %2, #0x80000000\n\t"
        "mov    %0, %4\n\t"
        "addeq  %0, %0, %3\n\t"
        "strb   %1, [%0, %2, lsl #2]    @ outb"
        : "=&r" (temp)
        : "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
        : "cc");
}

%3 and %4 might be a constant:

	mov	r5, #0x03000000

or a real register if the constant can't be loaded in one instruction:

	mov	r5, r1

'I' in this case means "a constant suitable for use with the arithmetic instructions".

--
Russell King ([email protected]) The developer of ARM Linux
http://www.arm.linux.org.uk/personal/aboutme.html

#14 lore raw
In reply to Keith Owens
Quoted 5 lines · David S. Miller
Quoted 2 lines · Keith Owens

do_softirq is called from asm code which does not get preprocessed. It needs to be exported with no version.

Quoted 7 lines

It can get preprocessed if you know how. Simply use the "i" asm constraint for an extra argument, and use the symbol there. For example:

        __asm__("%0" : : "i" (my_versioned_symbol));

It works and we've been doing it on sparc for ages.

how to do this in foo.S code?

Signature · 3 lines
Jeff Garzik      | Andre the Giant has a posse.
Building 1024    |
MandrakeSoft     |
#16 lore raw
In reply to Jeff Garzik
Quoted 5 lines · Jeff Garzik
Quoted 2 lines · David S. Miller

It can get preprocessed if you know how. Simply use the "i" asm constraint for an extra argument, and use the symbol there.

how to do this in foo.S code?

Fortunately it is not a problem for foo.S code - yet. External symbol references only need module version pre-processing when the code is in a module. AFAIK no *.S code is compiled into a module, all *.S code is built into vmlinux, this is why I did not use this argument myself. OTOH if any *.S code is compiled into a module then all symbols it refers to must be EXPORT_SYMBOL_NOVERS().

#17 lore raw
Quoted 2 lines · Keith Owens

OTOH if any *.S code is compiled into a module then all symbols it refers to must be EXPORT_SYMBOL_NOVERS().

Why not just add --include modversions.h to the gcc command line to build it, why wouldn't this work?

Later,
David S. Miller
[email protected]

#18 lore raw
Quoted 7 lines · David S. Miller
Quoted 2 lines · Keith Owens

OTOH if any *.S code is compiled into a module then all symbols it refers to must be EXPORT_SYMBOL_NOVERS().

Why not just add --include modversions.h to the gcc command line to build it, why wouldn't this work?

Assembler code is not hooked into the generic module symbol version handling. Every .S rule is unique and I'm not going to change every one.

#19 lore raw
Quoted 7 lines · Keith Owens
Quoted 5 lines · David S. Miller
Quoted 2 lines · Keith Owens

OTOH if any *.S code is compiled into a module then all symbols it refers to must be EXPORT_SYMBOL_NOVERS().

Quoted 6 lines
Quoted 2 lines

Why not just add --include modversions.h to the gcc command line to build it, why wouldn't this work?

Assembler code is not hooked into the generic module symbol version handling. Every .S rule is unique and I'm not going to change every one.

Why not make a ASM_CPP_DEFINES that all those rules use?

Surely this is a smaller hammer than making them all NOVERS(), I think all of these workarounds with novers for assembly are silly and are merely looking for a solution which nobody (perhaps except me :-) is bothering to look for.

Later,
David S. Miller
[email protected]

#20 lore raw
Quoted 4 lines · David S. Miller

Surely this is a smaller hammer than making them all NOVERS(), I think all of these workarounds with novers for assembly are silly and are merely looking for a solution which nobody (perhaps except me :-) is bothering to look for.

modversions.h will disappear in 2.5 anyway, and be replaced with a cleaner system of symbol versions which does not rely on pre-processor fudging of symbol names. It should be able to handle assembler as well as C.