Commit 1fa5e012 authored by David Howells's avatar David Howells Committed by Linus Torvalds

[PATCH] GP-REL data support

The attached patch makes it possible to support gp-rel addressing for small
variables.  Since the FR-V cpu's have fixed-length instructions and plenty of
general-purpose registers, one register is nominated as a base for the small
data area.  This makes it possible to use single-insn accesses to access
global and static variables instead of having to use multiple instructions.

This, however, causes problems with small variables used to pinpoint the
beginning and end of sections.  The compiler assumes it can use gp-rel
addressing for these, but the linker then complains because the displacement
is out of range.

By declaring certain variables as arrays or by forcing them into named
sections, the compiler is persuaded to access them as if they can be outside
the displacement range.  Declaring the variables as "const void" type also
works.
Signed-Off-By: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent fc1d4be6
...@@ -2903,8 +2903,8 @@ void __init console_init(void) ...@@ -2903,8 +2903,8 @@ void __init console_init(void)
So I haven't moved it. dwmw2 */ So I haven't moved it. dwmw2 */
rs_360_init(); rs_360_init();
#endif #endif
call = &__con_initcall_start; call = __con_initcall_start;
while (call < &__con_initcall_end) { while (call < __con_initcall_end) {
(*call)(); (*call)();
call++; call++;
} }
......
...@@ -256,7 +256,6 @@ static struct file_operations fragmentation_file_operations = { ...@@ -256,7 +256,6 @@ static struct file_operations fragmentation_file_operations = {
static int version_read_proc(char *page, char **start, off_t off, static int version_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data) int count, int *eof, void *data)
{ {
extern char *linux_banner;
int len; int len;
strcpy(page, linux_banner); strcpy(page, linux_banner);
......
...@@ -8,5 +8,6 @@ extern char _data[], _sdata[], _edata[]; ...@@ -8,5 +8,6 @@ extern char _data[], _sdata[], _edata[];
extern char __bss_start[], __bss_stop[]; extern char __bss_start[], __bss_stop[];
extern char __init_begin[], __init_end[]; extern char __init_begin[], __init_end[];
extern char _sinittext[], _einittext[]; extern char _sinittext[], _einittext[];
extern char _end[];
#endif /* _ASM_GENERIC_SECTIONS_H_ */ #endif /* _ASM_GENERIC_SECTIONS_H_ */
...@@ -17,7 +17,6 @@ extern char __start_gate_vtop_patchlist[], __end_gate_vtop_patchlist[]; ...@@ -17,7 +17,6 @@ extern char __start_gate_vtop_patchlist[], __end_gate_vtop_patchlist[];
extern char __start_gate_fsyscall_patchlist[], __end_gate_fsyscall_patchlist[]; extern char __start_gate_fsyscall_patchlist[], __end_gate_fsyscall_patchlist[];
extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_bubble_down_patchlist[]; extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_bubble_down_patchlist[];
extern char __start_unwind[], __end_unwind[]; extern char __start_unwind[], __end_unwind[];
extern char _end[]; /* end of kernel image */
#endif /* _ASM_IA64_SECTIONS_H */ #endif /* _ASM_IA64_SECTIONS_H */
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
#include <asm-generic/sections.h> #include <asm-generic/sections.h>
extern char _end[];
#define __pmac __attribute__ ((__section__ (".pmac.text"))) #define __pmac __attribute__ ((__section__ (".pmac.text")))
#define __pmacdata __attribute__ ((__section__ (".pmac.data"))) #define __pmacdata __attribute__ ((__section__ (".pmac.data")))
#define __pmacfunc(__argpmac) \ #define __pmacfunc(__argpmac) \
......
...@@ -4,6 +4,6 @@ ...@@ -4,6 +4,6 @@
/* nothing to see, move along */ /* nothing to see, move along */
#include <asm-generic/sections.h> #include <asm-generic/sections.h>
extern char _end[], _start[]; extern char _start[];
#endif #endif
...@@ -64,8 +64,8 @@ ...@@ -64,8 +64,8 @@
typedef int (*initcall_t)(void); typedef int (*initcall_t)(void);
typedef void (*exitcall_t)(void); typedef void (*exitcall_t)(void);
extern initcall_t __con_initcall_start, __con_initcall_end; extern initcall_t __con_initcall_start[], __con_initcall_end[];
extern initcall_t __security_initcall_start, __security_initcall_end; extern initcall_t __security_initcall_start[], __security_initcall_end[];
/* Defined in init/main.c */ /* Defined in init/main.c */
extern char saved_command_line[]; extern char saved_command_line[];
......
...@@ -70,13 +70,19 @@ ...@@ -70,13 +70,19 @@
/* a value TUSEC for TICK_USEC (can be set bij adjtimex) */ /* a value TUSEC for TICK_USEC (can be set bij adjtimex) */
#define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV (TUSEC * USER_HZ * 1000, ACTHZ, 8)) #define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV (TUSEC * USER_HZ * 1000, ACTHZ, 8))
/* some arch's have a small-data section that can be accessed register-relative
* but that can only take up to, say, 4-byte variables. jiffies being part of
* an 8-byte variable may not be correctly accessed unless we force the issue
*/
#define __jiffy_data __attribute__((section(".data")))
/* /*
* The 64-bit value is not volatile - you MUST NOT read it * The 64-bit value is not volatile - you MUST NOT read it
* without sampling the sequence number in xtime_lock. * without sampling the sequence number in xtime_lock.
* get_jiffies_64() will do this for you as appropriate. * get_jiffies_64() will do this for you as appropriate.
*/ */
extern u64 jiffies_64; extern u64 __jiffy_data jiffies_64;
extern unsigned long volatile jiffies; extern unsigned long volatile __jiffy_data jiffies;
#if (BITS_PER_LONG < 64) #if (BITS_PER_LONG < 64)
u64 get_jiffies_64(void); u64 get_jiffies_64(void);
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/bug.h> #include <asm/bug.h>
extern const char linux_banner[];
#define INT_MAX ((int)(~0U>>1)) #define INT_MAX ((int)(~0U>>1))
#define INT_MIN (-INT_MAX - 1) #define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (~0U) #define UINT_MAX (~0U)
......
...@@ -460,15 +460,15 @@ char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only) ...@@ -460,15 +460,15 @@ char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
return message; return message;
} }
extern char __initramfs_start, __initramfs_end; extern char __initramfs_start[], __initramfs_end[];
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
#include <linux/initrd.h> #include <linux/initrd.h>
#endif #endif
void __init populate_rootfs(void) void __init populate_rootfs(void)
{ {
char *err = unpack_to_rootfs(&__initramfs_start, char *err = unpack_to_rootfs(__initramfs_start,
&__initramfs_end - &__initramfs_start, 0); __initramfs_end - __initramfs_start, 0);
if (err) if (err)
panic(err); panic(err);
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
......
...@@ -75,8 +75,6 @@ ...@@ -75,8 +75,6 @@
#error Sorry, your GCC is too old. It builds incorrect kernels. #error Sorry, your GCC is too old. It builds incorrect kernels.
#endif #endif
extern char *linux_banner;
static int init(void *); static int init(void *);
extern void init_IRQ(void); extern void init_IRQ(void);
...@@ -157,12 +155,13 @@ static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; ...@@ -157,12 +155,13 @@ static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
static const char *panic_later, *panic_param; static const char *panic_later, *panic_param;
extern struct obs_kernel_param __setup_start[], __setup_end[];
static int __init obsolete_checksetup(char *line) static int __init obsolete_checksetup(char *line)
{ {
struct obs_kernel_param *p; struct obs_kernel_param *p;
extern struct obs_kernel_param __setup_start, __setup_end;
p = &__setup_start; p = __setup_start;
do { do {
int n = strlen(p->str); int n = strlen(p->str);
if (!strncmp(line, p->str, n)) { if (!strncmp(line, p->str, n)) {
...@@ -179,7 +178,7 @@ static int __init obsolete_checksetup(char *line) ...@@ -179,7 +178,7 @@ static int __init obsolete_checksetup(char *line)
return 1; return 1;
} }
p++; p++;
} while (p < &__setup_end); } while (p < __setup_end);
return 0; return 0;
} }
...@@ -453,9 +452,8 @@ static void noinline rest_init(void) ...@@ -453,9 +452,8 @@ static void noinline rest_init(void)
static int __init do_early_param(char *param, char *val) static int __init do_early_param(char *param, char *val)
{ {
struct obs_kernel_param *p; struct obs_kernel_param *p;
extern struct obs_kernel_param __setup_start, __setup_end;
for (p = &__setup_start; p < &__setup_end; p++) { for (p = __setup_start; p < __setup_end; p++) {
if (p->early && strcmp(param, p->str) == 0) { if (p->early && strcmp(param, p->str) == 0) {
if (p->setup_func(val) != 0) if (p->setup_func(val) != 0)
printk(KERN_WARNING printk(KERN_WARNING
...@@ -592,14 +590,14 @@ __setup("initcall_debug", initcall_debug_setup); ...@@ -592,14 +590,14 @@ __setup("initcall_debug", initcall_debug_setup);
struct task_struct *child_reaper = &init_task; struct task_struct *child_reaper = &init_task;
extern initcall_t __initcall_start, __initcall_end; extern initcall_t __initcall_start[], __initcall_end[];
static void __init do_initcalls(void) static void __init do_initcalls(void)
{ {
initcall_t *call; initcall_t *call;
int count = preempt_count(); int count = preempt_count();
for (call = &__initcall_start; call < &__initcall_end; call++) { for (call = __initcall_start; call < __initcall_end; call++) {
char *msg; char *msg;
if (initcall_debug) { if (initcall_debug) {
......
...@@ -28,6 +28,6 @@ struct new_utsname system_utsname = { ...@@ -28,6 +28,6 @@ struct new_utsname system_utsname = {
EXPORT_SYMBOL(system_utsname); EXPORT_SYMBOL(system_utsname);
const char *linux_banner = const char linux_banner[] =
"Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@"
LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n"; LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n";
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/sections.h>
#ifdef CONFIG_KALLSYMS_ALL #ifdef CONFIG_KALLSYMS_ALL
#define all_var 1 #define all_var 1
#else #else
...@@ -28,7 +30,7 @@ ...@@ -28,7 +30,7 @@
/* These will be re-linked against their real values during the second link stage */ /* These will be re-linked against their real values during the second link stage */
extern unsigned long kallsyms_addresses[] __attribute__((weak)); extern unsigned long kallsyms_addresses[] __attribute__((weak));
extern unsigned long kallsyms_num_syms __attribute__((weak)); extern unsigned long kallsyms_num_syms __attribute__((weak,section("data")));
extern u8 kallsyms_names[] __attribute__((weak)); extern u8 kallsyms_names[] __attribute__((weak));
extern u8 kallsyms_token_table[] __attribute__((weak)); extern u8 kallsyms_token_table[] __attribute__((weak));
...@@ -36,9 +38,6 @@ extern u16 kallsyms_token_index[] __attribute__((weak)); ...@@ -36,9 +38,6 @@ extern u16 kallsyms_token_index[] __attribute__((weak));
extern unsigned long kallsyms_markers[] __attribute__((weak)); extern unsigned long kallsyms_markers[] __attribute__((weak));
/* Defined by the linker script. */
extern char _stext[], _etext[], _sinittext[], _einittext[], _end[];
static inline int is_kernel_inittext(unsigned long addr) static inline int is_kernel_inittext(unsigned long addr)
{ {
if (addr >= (unsigned long)_sinittext if (addr >= (unsigned long)_sinittext
......
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
#include "power.h" #include "power.h"
/* References to section boundaries */ /* References to section boundaries */
extern char __nosave_begin, __nosave_end; extern const void __nosave_begin, __nosave_end;
/* Variables to be preserved over suspend */ /* Variables to be preserved over suspend */
static int pagedir_order_check; static int pagedir_order_check;
......
...@@ -38,8 +38,8 @@ static inline int verify(struct security_operations *ops) ...@@ -38,8 +38,8 @@ static inline int verify(struct security_operations *ops)
static void __init do_security_initcalls(void) static void __init do_security_initcalls(void)
{ {
initcall_t *call; initcall_t *call;
call = &__security_initcall_start; call = __security_initcall_start;
while (call < &__security_initcall_end) { while (call < __security_initcall_end) {
(*call) (); (*call) ();
call++; call++;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment