2011-02-10 15:44:36

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: ARM: relocation out of range (when loading a module)

On Thu, Jan 27, 2011 at 12:43:54AM -0500, Nicolas Pitre wrote:
> The MMU-less kernel should still favor allocations close to the kernel
> text for modules, and anything else away from the kernel going
> downwards.
>
> Otherwise a veneer should be created by the module symbol resolver such
> that if the branch distance to reach, say, printk is too large, then the
> following code would have to be dynamically generated right next to the
> module:
>
> ldr pc, [pc, #-4]
> .word <far_away_symbol>
>
> Then, in your module, you patch the branch relocation for printk so that
> it branches to the code above instead, and then store the address of
> printk at the location represented by the .word directive.

What you're suggesting is what we used to do with the old user-space
module tools, which would've been nice to carry forwards to the new
module code. I never found a way to do it.

The problems:
1. Where do you create those veneers?
2. How many veneers do you allocate space for?
3. How do you determine that you need a veneer?

While you can say "next to the module" for (1), you can only do that at
the point in time when the space for the module is allocated, and you
need to know at that point how much space you require.

For (2), you could always allocate space for one veneer per symbol present
in the module, but that's very wasteful.

(3) is almost impossible to know ahead of time as you don't have the
relocations, realistically you have to allocate one veneer per symbol,
and as you don't know whether it's a data or code symbol, you'll have
to allocate one veneer for every symbol in a module.

I really don't like it, and I don't see that this is sanely solvable
without giving architectures much more control over module loading,
which I don't think will ever happen. It's probably simpler to build
modules with whatever that magic option is to tell GCC to always generate
'far call' veneers for everything rather than trying to 'fix' the kernel
module loader.


2011-02-10 19:41:32

by Nicolas Pitre

[permalink] [raw]
Subject: Re: ARM: relocation out of range (when loading a module)

On Thu, 10 Feb 2011, Russell King - ARM Linux wrote:

> On Thu, Jan 27, 2011 at 12:43:54AM -0500, Nicolas Pitre wrote:
> > The MMU-less kernel should still favor allocations close to the kernel
> > text for modules, and anything else away from the kernel going
> > downwards.
> >
> > Otherwise a veneer should be created by the module symbol resolver such
> > that if the branch distance to reach, say, printk is too large, then the
> > following code would have to be dynamically generated right next to the
> > module:
> >
> > ldr pc, [pc, #-4]
> > .word <far_away_symbol>
> >
> > Then, in your module, you patch the branch relocation for printk so that
> > it branches to the code above instead, and then store the address of
> > printk at the location represented by the .word directive.
>
> What you're suggesting is what we used to do with the old user-space
> module tools, which would've been nice to carry forwards to the new
> module code. I never found a way to do it.
>
> The problems:
> 1. Where do you create those veneers?
> 2. How many veneers do you allocate space for?
> 3. How do you determine that you need a veneer?
>
> While you can say "next to the module" for (1), you can only do that at
> the point in time when the space for the module is allocated, and you
> need to know at that point how much space you require.

You would have to guess of course. Having a guess of 1/2 the module
size should be pretty safe. So allocating 3/2 the space in
module_alloc(), and then suffice to free the unused portion in
module_finalize().

> For (2), you could always allocate space for one veneer per symbol present
> in the module, but that's very wasteful.
>
> (3) is almost impossible to know ahead of time as you don't have the
> relocations, realistically you have to allocate one veneer per symbol,
> and as you don't know whether it's a data or code symbol, you'll have
> to allocate one veneer for every symbol in a module.

I don't think you may know the number of symbols in advance either
anyway.

> I really don't like it, and I don't see that this is sanely solvable
> without giving architectures much more control over module loading,
> which I don't think will ever happen. It's probably simpler to build
> modules with whatever that magic option is to tell GCC to always generate
> 'far call' veneers for everything rather than trying to 'fix' the kernel
> module loader.

Well, this is certainly possible indeed to just use -mlong-calls to
build modules which would solve the issue right away, and with a smaller
cost than if each function calls were going through a veneer, but with a
higher cost than a relocatable direct branch. So this could be decided
with a Kconfig option.


Nicolas

2011-02-11 09:31:09

by Dave Martin

[permalink] [raw]
Subject: Re: ARM: relocation out of range (when loading a module)

On Thu, Feb 10, 2011 at 7:41 PM, Nicolas Pitre <[email protected]> wrote:
> On Thu, 10 Feb 2011, Russell King - ARM Linux wrote:
>
>> On Thu, Jan 27, 2011 at 12:43:54AM -0500, Nicolas Pitre wrote:
>> > The MMU-less kernel should still favor allocations close to the kernel
>> > text for modules, and anything else away from the kernel going
>> > downwards.
>> >
>> > Otherwise a veneer should be created by the module symbol resolver such
>> > that if the branch distance to reach, say, printk is too large, then the
>> > following code would have to be dynamically generated right next to the
>> > module:
>> >
>> > ? ? ldr ? ? pc, [pc, #-4]
>> > ? ? .word ? <far_away_symbol>
>> >
>> > Then, in your module, you patch the branch relocation for printk so that
>> > it branches to the code above instead, and then store the address of
>> > printk at the location represented by the .word directive.
>>
>> What you're suggesting is what we used to do with the old user-space
>> module tools, which would've been nice to carry forwards to the new
>> module code. ?I never found a way to do it.
>>
>> The problems:
>> 1. Where do you create those veneers?
>> 2. How many veneers do you allocate space for?
>> 3. How do you determine that you need a veneer?
>>
>> While you can say "next to the module" for (1), you can only do that at
>> the point in time when the space for the module is allocated, and you
>> need to know at that point how much space you require.
>
> You would have to guess of course. ?Having a guess of 1/2 the module
> size should be pretty safe. ?So allocating 3/2 the space in
> module_alloc(), and then suffice to free the unused portion in
> module_finalize().
>
>> For (2), you could always allocate space for one veneer per symbol present
>> in the module, but that's very wasteful.
>>
>> (3) is almost impossible to know ahead of time as you don't have the
>> relocations, realistically you have to allocate one veneer per symbol,
>> and as you don't know whether it's a data or code symbol, you'll have
>> to allocate one veneer for every symbol in a module.
>
> I don't think you may know the number of symbols in advance either
> anyway.

You could probably cook up a good upper bound based on the size of the
kernel and the number of symbols in the module: i.e., assume that
every undefined symbol in the module needs to be fixed up to point at
the most distant symbol in the kernel.

For people with normal-sized kernels, this bound will probably work
out as zero most of the time (i.e., the current situation). For
people with big kernels, or when many modules are already loaded, it
may work out at 100% -- but that's the price to pay for guaranteed
preallocation of the space required for the veneers. And anyway, you
may really need a substantial chunk of those veneers in such cases.

---Dave

2011-02-11 09:40:08

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: ARM: relocation out of range (when loading a module)

On Fri, Feb 11, 2011 at 09:31:04AM +0000, Dave Martin wrote:
> You could probably cook up a good upper bound based on the size of the
> kernel and the number of symbols in the module: i.e., assume that
> every undefined symbol in the module needs to be fixed up to point at
> the most distant symbol in the kernel.
>
> For people with normal-sized kernels, this bound will probably work
> out as zero most of the time (i.e., the current situation). For
> people with big kernels, or when many modules are already loaded, it
> may work out at 100% -- but that's the price to pay for guaranteed
> preallocation of the space required for the veneers. And anyway, you
> may really need a substantial chunk of those veneers in such cases.

I think it's going to be easier just to re-order the kernel image link
order to solve that problem. That just leaves uclinux...

2011-02-11 09:45:56

by Dave Martin

[permalink] [raw]
Subject: Re: ARM: relocation out of range (when loading a module)

On Fri, Feb 11, 2011 at 9:38 AM, Russell King - ARM Linux
<[email protected]> wrote:
> On Fri, Feb 11, 2011 at 09:31:04AM +0000, Dave Martin wrote:
>> You could probably cook up a good upper bound based on the size of the
>> kernel and the number of symbols in the module: i.e., assume that
>> every undefined symbol in the module needs to be fixed up to point at
>> the most distant symbol in the kernel.
>>
>> For people with normal-sized kernels, this bound will probably work
>> out as zero most of the time (i.e., the current situation). ?For
>> people with big kernels, or when many modules are already loaded, it
>> may work out at 100% -- but that's the price to pay for guaranteed
>> preallocation of the space required for the veneers. ?And anyway, you
>> may really need a substantial chunk of those veneers in such cases.
>
> I think it's going to be easier just to re-order the kernel image link
> order to solve that problem. ?That just leaves uclinux...
>

But if the kernel is big, or there are many modules, changing the
order can't solve the problem surely? Or is the problem purely caused
by having the initramfs in the way, and we think the amount of actual
code will never be big enough to cause a problem?

Cheers
---Dave

2011-02-11 13:51:39

by Nicolas Pitre

[permalink] [raw]
Subject: Re: ARM: relocation out of range (when loading a module)

On Fri, 11 Feb 2011, Dave Martin wrote:

> On Thu, Feb 10, 2011 at 7:41 PM, Nicolas Pitre <[email protected]> wrote:
> > On Thu, 10 Feb 2011, Russell King - ARM Linux wrote:
> >
> >> On Thu, Jan 27, 2011 at 12:43:54AM -0500, Nicolas Pitre wrote:
> >> > The MMU-less kernel should still favor allocations close to the kernel
> >> > text for modules, and anything else away from the kernel going
> >> > downwards.
> >> >
> >> > Otherwise a veneer should be created by the module symbol resolver such
> >> > that if the branch distance to reach, say, printk is too large, then the
> >> > following code would have to be dynamically generated right next to the
> >> > module:
> >> >
> >> > ? ? ldr ? ? pc, [pc, #-4]
> >> > ? ? .word ? <far_away_symbol>
> >> >
> >> > Then, in your module, you patch the branch relocation for printk so that
> >> > it branches to the code above instead, and then store the address of
> >> > printk at the location represented by the .word directive.
> >>
> >> What you're suggesting is what we used to do with the old user-space
> >> module tools, which would've been nice to carry forwards to the new
> >> module code. ?I never found a way to do it.
> >>
> >> The problems:
> >> 1. Where do you create those veneers?
> >> 2. How many veneers do you allocate space for?
> >> 3. How do you determine that you need a veneer?
> >>
> >> While you can say "next to the module" for (1), you can only do that at
> >> the point in time when the space for the module is allocated, and you
> >> need to know at that point how much space you require.
> >
> > You would have to guess of course. ?Having a guess of 1/2 the module
> > size should be pretty safe. ?So allocating 3/2 the space in
> > module_alloc(), and then suffice to free the unused portion in
> > module_finalize().
> >
> >> For (2), you could always allocate space for one veneer per symbol present
> >> in the module, but that's very wasteful.
> >>
> >> (3) is almost impossible to know ahead of time as you don't have the
> >> relocations, realistically you have to allocate one veneer per symbol,
> >> and as you don't know whether it's a data or code symbol, you'll have
> >> to allocate one veneer for every symbol in a module.
> >
> > I don't think you may know the number of symbols in advance either
> > anyway.
>
> You could probably cook up a good upper bound based on the size of the
> kernel and the number of symbols in the module: i.e., assume that
> every undefined symbol in the module needs to be fixed up to point at
> the most distant symbol in the kernel.

Sure... It is just that the memory allocation is currently done before
the number of symbols in the module is known. Changing that would
require non trivial changes in the generic module loading code which
potentially would affect all architectures, and therefore I don't think
we want to go there.

The other solution would be to determine the number of objects in need
of a veneer in apply_relocate(), allocate a replacement area for the
module, copy everything over, and then create the veneers close to the
module. But 1) the second allocation may fail, and 2) this will change
the distance from the kernel potentially requiring more veneers than
initially determined, and 3) the generic module code might still have
pointer references into the old allocation area (didn't check but that
can be expected). That's just too messy.

> For people with normal-sized kernels, this bound will probably work
> out as zero most of the time (i.e., the current situation). For
> people with big kernels, or when many modules are already loaded, it
> may work out at 100% -- but that's the price to pay for guaranteed
> preallocation of the space required for the veneers. And anyway, you
> may really need a substantial chunk of those veneers in such cases.

I still think that compiling modules with -mlong-calls, and making that
conditional on a kernel config option so only those who need it will
have it, is the simplest solution. Nothing in the kernel code would
need to be changed.


Nicolas

2011-02-11 13:55:25

by Nicolas Pitre

[permalink] [raw]
Subject: Re: ARM: relocation out of range (when loading a module)

On Fri, 11 Feb 2011, Dave Martin wrote:

> On Fri, Feb 11, 2011 at 9:38 AM, Russell King - ARM Linux
> <[email protected]> wrote:
> > On Fri, Feb 11, 2011 at 09:31:04AM +0000, Dave Martin wrote:
> >> You could probably cook up a good upper bound based on the size of the
> >> kernel and the number of symbols in the module: i.e., assume that
> >> every undefined symbol in the module needs to be fixed up to point at
> >> the most distant symbol in the kernel.
> >>
> >> For people with normal-sized kernels, this bound will probably work
> >> out as zero most of the time (i.e., the current situation). ?For
> >> people with big kernels, or when many modules are already loaded, it
> >> may work out at 100% -- but that's the price to pay for guaranteed
> >> preallocation of the space required for the veneers. ?And anyway, you
> >> may really need a substantial chunk of those veneers in such cases.
> >
> > I think it's going to be easier just to re-order the kernel image link
> > order to solve that problem. ?That just leaves uclinux...
> >
>
> But if the kernel is big, or there are many modules, changing the
> order can't solve the problem surely? Or is the problem purely caused
> by having the initramfs in the way, and we think the amount of actual
> code will never be big enough to cause a problem?

Right now the biggest problem comes from the size of the initramfs. The
solution for that is simply to move it elsewhere towards the end of the
kernel image instead of at the beginning. And I think we're good for a
couple years before the actual kernel code size becomes an issue.


Nicolas

2011-02-11 14:25:30

by Dave Martin

[permalink] [raw]
Subject: Re: ARM: relocation out of range (when loading a module)

On Fri, Feb 11, 2011 at 1:51 PM, Nicolas Pitre <[email protected]> wrote:
> On Fri, 11 Feb 2011, Dave Martin wrote:
>
>> On Thu, Feb 10, 2011 at 7:41 PM, Nicolas Pitre <[email protected]> wrote:
>> > On Thu, 10 Feb 2011, Russell King - ARM Linux wrote:
>> >
>> >> On Thu, Jan 27, 2011 at 12:43:54AM -0500, Nicolas Pitre wrote:
>> >> > The MMU-less kernel should still favor allocations close to the kernel
>> >> > text for modules, and anything else away from the kernel going
>> >> > downwards.
>> >> >
>> >> > Otherwise a veneer should be created by the module symbol resolver such
>> >> > that if the branch distance to reach, say, printk is too large, then the
>> >> > following code would have to be dynamically generated right next to the
>> >> > module:
>> >> >
>> >> > ? ? ldr ? ? pc, [pc, #-4]
>> >> > ? ? .word ? <far_away_symbol>
>> >> >
>> >> > Then, in your module, you patch the branch relocation for printk so that
>> >> > it branches to the code above instead, and then store the address of
>> >> > printk at the location represented by the .word directive.
>> >>
>> >> What you're suggesting is what we used to do with the old user-space
>> >> module tools, which would've been nice to carry forwards to the new
>> >> module code. ?I never found a way to do it.
>> >>
>> >> The problems:
>> >> 1. Where do you create those veneers?
>> >> 2. How many veneers do you allocate space for?
>> >> 3. How do you determine that you need a veneer?
>> >>
>> >> While you can say "next to the module" for (1), you can only do that at
>> >> the point in time when the space for the module is allocated, and you
>> >> need to know at that point how much space you require.
>> >
>> > You would have to guess of course. ?Having a guess of 1/2 the module
>> > size should be pretty safe. ?So allocating 3/2 the space in
>> > module_alloc(), and then suffice to free the unused portion in
>> > module_finalize().
>> >
>> >> For (2), you could always allocate space for one veneer per symbol present
>> >> in the module, but that's very wasteful.
>> >>
>> >> (3) is almost impossible to know ahead of time as you don't have the
>> >> relocations, realistically you have to allocate one veneer per symbol,
>> >> and as you don't know whether it's a data or code symbol, you'll have
>> >> to allocate one veneer for every symbol in a module.
>> >
>> > I don't think you may know the number of symbols in advance either
>> > anyway.
>>
>> You could probably cook up a good upper bound based on the size of the
>> kernel and the number of symbols in the module: i.e., assume that
>> every undefined symbol in the module needs to be fixed up to point at
>> the most distant symbol in the kernel.
>
> Sure... It is just that the memory allocation is currently done before
> the number of symbols in the module is known. ?Changing that would
> require non trivial changes in the generic module loading code which
> potentially would affect all architectures, and therefore I don't think
> we want to go there.
>
> The other solution would be to determine the number of objects in need
> of a veneer in apply_relocate(), allocate a replacement area for the
> module, copy everything over, and then create the veneers close to the
> module. ?But 1) the second allocation may fail, and 2) this will change
> the distance from the kernel potentially requiring more veneers than
> initially determined, and 3) the generic module code might still have
> pointer references into the old allocation area (didn't check but that
> can be expected). ?That's just too messy.
>
>> For people with normal-sized kernels, this bound will probably work
>> out as zero most of the time (i.e., the current situation). ?For
>> people with big kernels, or when many modules are already loaded, it
>> may work out at 100% -- but that's the price to pay for guaranteed
>> preallocation of the space required for the veneers. ?And anyway, you
>> may really need a substantial chunk of those veneers in such cases.
>
> I still think that compiling modules with -mlong-calls, and making that
> conditional on a kernel config option so only those who need it will
> have it, is the simplest solution. ?Nothing in the kernel code would
> need to be changed.

Yes, this sounds like a reasonable solution for now ... since most
people don't need this turned on anyway, and those that do need it
know who they are.

if we can also move the initramfs somewhere less obstructive in the
future, then so much the better.

Cheers
---Dave

2011-02-11 14:43:43

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: ARM: relocation out of range (when loading a module)

On Fri, Feb 11, 2011 at 02:25:28PM +0000, Dave Martin wrote:
> if we can also move the initramfs somewhere less obstructive in the
> future, then so much the better.

This may do it, and it might even work. Not particularly well tested
yet. It'd be loads easier if we didn't have to worry about XIP.

arch/arm/kernel/etm.c | 2 +-
arch/arm/kernel/smp.c | 4 +-
arch/arm/kernel/vmlinux.lds.S | 133 +++++++++++++++++++++-------------------
arch/arm/mm/init.c | 2 +-
4 files changed, 74 insertions(+), 67 deletions(-)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 11db628..ca477d2 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -114,7 +114,7 @@ static int trace_start(struct tracectx *t)
return -EFAULT;
}

- etm_setup_address_range(t, 1, (unsigned long)_stext,
+ etm_setup_address_range(t, 1, (unsigned long)_text,
(unsigned long)_etext, 0, 0);
etm_writel(t, 0, ETMR_TRACEENCTRL2);
etm_writel(t, 0, ETMR_TRACESSCTRL);
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 4539ebc..8ad77d3 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -95,7 +95,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
#ifndef CONFIG_HOTPLUG_CPU
identity_mapping_add(pgd, __pa(__init_begin), __pa(__init_end));
#endif
- identity_mapping_add(pgd, __pa(_stext), __pa(_etext));
+ identity_mapping_add(pgd, __pa(_text), __pa(_etext));
identity_mapping_add(pgd, __pa(_sdata), __pa(_edata));
}

@@ -143,7 +143,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
#ifndef CONFIG_HOTPLUG_CPU
identity_mapping_del(pgd, __pa(__init_begin), __pa(__init_end));
#endif
- identity_mapping_del(pgd, __pa(_stext), __pa(_etext));
+ identity_mapping_del(pgd, __pa(_text), __pa(_etext));
identity_mapping_del(pgd, __pa(_sdata), __pa(_edata));
}

diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 45b5651..9cd098b 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -32,46 +32,98 @@ jiffies = jiffies_64 + 4;

SECTIONS
{
+ /*
+ * unwind exit sections must be discarded before the rest of the
+ * unwind sections get included.
+ */
+ /DISCARD/ : {
+ *(.ARM.exidx.exit.text)
+ *(.ARM.extab.exit.text)
+ ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))
+ ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text))
+#ifndef CONFIG_HOTPLUG
+ *(.ARM.exidx.devexit.text)
+ *(.ARM.extab.devexit.text)
+#endif
+#ifndef CONFIG_MMU
+ *(.fixup)
+ *(__ex_table)
+#endif
+#ifndef CONFIG_SMP_ON_UP
+ *(.alt.smp.init)
+#endif
+ }
+
#ifdef CONFIG_XIP_KERNEL
. = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
#else
. = PAGE_OFFSET + TEXT_OFFSET;
#endif

- .init : { /* Init code and data */
- _stext = .;
- _sinittext = .;
- HEAD_TEXT
- INIT_TEXT
- _einittext = .;
+ _text = .;
+ HEAD_TEXT_SECTION
+
+ .text : { /* Real text segment */
+ _stext = .; /* Text and read-only data */
+ __exception_text_start = .;
+ *(.exception.text)
+ __exception_text_end = .;
+ IRQENTRY_TEXT
+ TEXT_TEXT
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+#ifdef CONFIG_MMU
+ *(.fixup)
+#endif
+ *(.gnu.warning)
+ *(.glue_7)
+ *(.glue_7t)
+ . = ALIGN(4);
+ *(.got) /* Global offset table */
+ ARM_CPU_KEEP(PROC_INFO)
+ _etext = .; /* End of text and rodata section */
+ }
+
+#ifndef CONFIG_XIP_KERNEL
+ . = ALIGN(PAGE_SIZE);
+ __init_begin = .;
+#endif
+ INIT_TEXT_SECTION(0)
+ .init.proc.info : {
ARM_CPU_DISCARD(PROC_INFO)
+ }
+ .init.arch.info : {
__arch_info_begin = .;
*(.arch.info.init)
__arch_info_end = .;
+ }
+ .init.tagtable : {
__tagtable_begin = .;
*(.taglist.init)
__tagtable_end = .;
+ }
#ifdef CONFIG_SMP_ON_UP
+ .init.smpalt : {
__smpalt_begin = .;
*(.alt.smp.init)
__smpalt_end = .;
+ }
#endif
-
+ .init.pv_table : {
__pv_table_begin = .;
*(.pv_table)
__pv_table_end = .;
-
+ }
+ .init.data : {
+#ifndef CONFIG_XIP_KERNEL
+ INIT_DATA
+#endif
INIT_SETUP(16)
-
INIT_CALLS
CON_INITCALL
SECURITY_INITCALL
INIT_RAM_FS
-
-#ifndef CONFIG_XIP_KERNEL
- __init_begin = _stext;
- INIT_DATA
-#endif
}

PERCPU(PAGE_SIZE)
@@ -79,49 +131,10 @@ SECTIONS
#ifndef CONFIG_XIP_KERNEL
. = ALIGN(PAGE_SIZE);
__init_end = .;
-#endif

- /*
- * unwind exit sections must be discarded before the rest of the
- * unwind sections get included.
- */
- /DISCARD/ : {
- *(.ARM.exidx.exit.text)
- *(.ARM.extab.exit.text)
- ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))
- ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text))
-#ifndef CONFIG_HOTPLUG
- *(.ARM.exidx.devexit.text)
- *(.ARM.extab.devexit.text)
+ _data = .;
+ _sdata = .;
#endif
-#ifndef CONFIG_MMU
- *(.fixup)
- *(__ex_table)
-#endif
- }
-
- .text : { /* Real text segment */
- _text = .; /* Text and read-only data */
- __exception_text_start = .;
- *(.exception.text)
- __exception_text_end = .;
- IRQENTRY_TEXT
- TEXT_TEXT
- SCHED_TEXT
- LOCK_TEXT
- KPROBES_TEXT
-#ifdef CONFIG_MMU
- *(.fixup)
-#endif
- *(.gnu.warning)
- *(.rodata)
- *(.rodata.*)
- *(.glue_7)
- *(.glue_7t)
- . = ALIGN(4);
- *(.got) /* Global offset table */
- ARM_CPU_KEEP(PROC_INFO)
- }

RO_DATA(PAGE_SIZE)

@@ -142,8 +155,6 @@ SECTIONS
}
#endif

- _etext = .; /* End of text and rodata section */
-
#ifdef CONFIG_XIP_KERNEL
__data_loc = ALIGN(4); /* location in binary */
. = PAGE_OFFSET + TEXT_OFFSET;
@@ -153,8 +164,10 @@ SECTIONS
#endif

.data : AT(__data_loc) {
+#ifdef CONFIG_XIP_KERNEL
_data = .; /* address in memory */
_sdata = .;
+#endif

/*
* first, the init task union, aligned
@@ -259,12 +272,6 @@ SECTIONS

/* Default discards */
DISCARDS
-
-#ifndef CONFIG_SMP_ON_UP
- /DISCARD/ : {
- *(.alt.smp.init)
- }
-#endif
}

/*
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index cddd684..9e3c3c3 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -294,7 +294,7 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
#ifdef CONFIG_XIP_KERNEL
memblock_reserve(__pa(_sdata), _end - _sdata);
#else
- memblock_reserve(__pa(_stext), _end - _stext);
+ memblock_reserve(__pa(_text), _end - _text);
#endif
#ifdef CONFIG_BLK_DEV_INITRD
if (phys_initrd_size &&

2011-02-12 19:52:44

by Nicolas Pitre

[permalink] [raw]
Subject: Re: ARM: relocation out of range (when loading a module)

On Fri, 11 Feb 2011, Russell King - ARM Linux wrote:

> On Fri, Feb 11, 2011 at 02:25:28PM +0000, Dave Martin wrote:
> > if we can also move the initramfs somewhere less obstructive in the
> > future, then so much the better.
>
> This may do it, and it might even work. Not particularly well tested
> yet. It'd be loads easier if we didn't have to worry about XIP.

Is anyone actually still using XIP these days? Now that NOR flash is
not that much used anymore, if maintaining XIP support is more trouble
than it is worth we could simply deprecate it. The linker script has
become quite more hairy than it used to be, and from a quick look I'm
not even sure if all the stuff in there is properly located for XIP.

Otherwise, for the __init stuff move:

Acked-by: Nicolas Pitre <[email protected]>


Nicolas