Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
e523efb3
Commit
e523efb3
authored
Nov 26, 2002
by
Miles Bader
Committed by
Linus Torvalds
Nov 26, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] Add v850 support for new module loader
Add v850 support for new module loader
parent
69144341
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
269 additions
and
10 deletions
+269
-10
arch/v850/kernel/Makefile
arch/v850/kernel/Makefile
+1
-1
arch/v850/kernel/entry.S
arch/v850/kernel/entry.S
+3
-3
arch/v850/kernel/module.c
arch/v850/kernel/module.c
+225
-0
arch/v850/kernel/v850_ksyms.c
arch/v850/kernel/v850_ksyms.c
+3
-1
include/asm-v850/elf.h
include/asm-v850/elf.h
+2
-1
include/asm-v850/irq.h
include/asm-v850/irq.h
+11
-0
include/asm-v850/module.h
include/asm-v850/module.h
+24
-4
No files found.
arch/v850/kernel/Makefile
View file @
e523efb3
...
...
@@ -15,7 +15,7 @@ obj-y += intv.o entry.o process.o syscalls.o time.o semaphore.o setup.o \
signal.o irq.o mach.o ptrace.o bug.o
export-objs
+=
v850_ksyms.o rte_mb_a_pci.o
obj-$(CONFIG_MODULES)
+=
v850_ksyms.o
obj-$(CONFIG_MODULES)
+=
module.o
v850_ksyms.o
# chip-specific code
obj-$(CONFIG_V850E_MA1)
+=
ma.o nb85e_utils.o nb85e_timer_d.o
obj-$(CONFIG_V850E_NB85E)
+=
nb85e_intc.o
...
...
arch/v850/kernel/entry.S
View file @
e523efb3
...
...
@@ -922,10 +922,10 @@ C_DATA(sys_call_table):
.
long
CSYM
(
sys_adjtimex
)
.
long
CSYM
(
sys_ni_syscall
)
//
125
-
sys_mprotect
.
long
CSYM
(
sys_sigprocmask
)
.
long
CSYM
(
sys_
create_module
)
.
long
CSYM
(
sys_
ni_syscall
)
//
sys_create_module
.
long
CSYM
(
sys_init_module
)
.
long
CSYM
(
sys_delete_module
)
.
long
CSYM
(
sys_
get_kernel_syms
)
//
130
.
long
CSYM
(
sys_
ni_syscall
)
//
130
-
sys_get_kernel_syms
.
long
CSYM
(
sys_quotactl
)
.
long
CSYM
(
sys_getpgid
)
.
long
CSYM
(
sys_fchdir
)
...
...
@@ -962,7 +962,7 @@ C_DATA(sys_call_table):
.
long
CSYM
(
sys_setresuid
)
.
long
CSYM
(
sys_getresuid
)
//
165
.
long
CSYM
(
sys_ni_syscall
)
//
for
vm86
.
long
CSYM
(
sys_
query_module
)
.
long
CSYM
(
sys_
ni_syscall
)
//
sys_query_module
.
long
CSYM
(
sys_poll
)
.
long
CSYM
(
sys_nfsservctl
)
.
long
CSYM
(
sys_setresgid
)
//
170
...
...
arch/v850/kernel/module.c
0 → 100644
View file @
e523efb3
/*
* arch/v850/kernel/module.c -- Architecture-specific module functions
*
* Copyright (C) 2002 NEC Corporation
* Copyright (C) 2002 Miles Bader <miles@gnu.org>
* Copyright (C) 2001 Rusty Russell
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*
* Derived in part from arch/ppc/kernel/module.c
*/
#include <linux/kernel.h>
#include <linux/vmalloc.h>
#include <linux/moduleloader.h>
#include <linux/elf.h>
#if 0
#define DEBUGP printk
#else
#define DEBUGP(fmt , ...)
#endif
void
*
module_alloc
(
unsigned
long
size
)
{
return
size
==
0
?
0
:
vmalloc
(
size
);
}
void
module_free
(
struct
module
*
mod
,
void
*
module_region
)
{
vfree
(
module_region
);
/* FIXME: If module_region == mod->init_region, trim exception
table entries. */
}
int
module_finalize
(
const
Elf_Ehdr
*
hdr
,
const
Elf_Shdr
*
sechdrs
,
struct
module
*
mod
)
{
return
0
;
}
/* Count how many different relocations (different symbol, different
addend) */
static
unsigned
int
count_relocs
(
const
Elf32_Rela
*
rela
,
unsigned
int
num
)
{
unsigned
int
i
,
j
,
ret
=
0
;
/* Sure, this is order(n^2), but it's usually short, and not
time critical */
for
(
i
=
0
;
i
<
num
;
i
++
)
{
for
(
j
=
0
;
j
<
i
;
j
++
)
{
/* If this addend appeared before, it's
already been counted */
if
(
ELF32_R_SYM
(
rela
[
i
].
r_info
)
==
ELF32_R_SYM
(
rela
[
j
].
r_info
)
&&
rela
[
i
].
r_addend
==
rela
[
j
].
r_addend
)
break
;
}
if
(
j
==
i
)
ret
++
;
}
return
ret
;
}
/* Get the potential trampolines size required of the init and
non-init sections */
static
unsigned
long
get_plt_size
(
const
Elf32_Ehdr
*
hdr
,
const
Elf32_Shdr
*
sechdrs
,
const
char
*
secstrings
,
int
is_init
)
{
unsigned
long
ret
=
0
;
unsigned
i
;
/* Everything marked ALLOC (this includes the exported
symbols) */
for
(
i
=
1
;
i
<
hdr
->
e_shnum
;
i
++
)
{
/* If it's called *.init*, and we're not init, we're
not interested */
if
((
strstr
(
secstrings
+
sechdrs
[
i
].
sh_name
,
".init"
)
!=
0
)
!=
is_init
)
continue
;
if
(
sechdrs
[
i
].
sh_type
==
SHT_RELA
)
{
DEBUGP
(
"Found relocations in section %u
\n
"
,
i
);
DEBUGP
(
"Ptr: %p. Number: %u
\n
"
,
(
void
*
)
hdr
+
sechdrs
[
i
].
sh_offset
,
sechdrs
[
i
].
sh_size
/
sizeof
(
Elf32_Rela
));
ret
+=
count_relocs
((
void
*
)
hdr
+
sechdrs
[
i
].
sh_offset
,
sechdrs
[
i
].
sh_size
/
sizeof
(
Elf32_Rela
))
*
sizeof
(
struct
v850_plt_entry
);
}
}
return
ret
;
}
long
module_core_size
(
const
Elf32_Ehdr
*
hdr
,
const
Elf32_Shdr
*
sechdrs
,
const
char
*
secstrings
,
struct
module
*
mod
)
{
mod
->
arch
.
core_plt_offset
=
(
mod
->
core_size
+
3
)
&
~
3
;
return
mod
->
core_size
+
get_plt_size
(
hdr
,
sechdrs
,
secstrings
,
1
);
}
long
module_init_size
(
const
Elf32_Ehdr
*
hdr
,
const
Elf32_Shdr
*
sechdrs
,
const
char
*
secstrings
,
struct
module
*
mod
)
{
mod
->
arch
.
init_plt_offset
=
(
mod
->
init_size
+
3
)
&
~
3
;
return
mod
->
init_size
+
get_plt_size
(
hdr
,
sechdrs
,
secstrings
,
1
);
}
int
apply_relocate
(
Elf32_Shdr
*
sechdrs
,
const
char
*
strtab
,
unsigned
int
symindex
,
unsigned
int
relsec
,
struct
module
*
mod
)
{
printk
(
"Barf
\n
"
);
return
-
ENOEXEC
;
}
/* Set up a trampoline in the PLT to bounce us to the distant function */
static
uint32_t
do_plt_call
(
void
*
location
,
Elf32_Addr
val
,
struct
module
*
mod
)
{
struct
v850_plt_entry
*
entry
;
/* Instructions used to do the indirect jump. */
uint32_t
tramp
[
2
];
/* We have to trash a register, so we assume that any control
transfer more than 21-bits away must be a function call
(so we can use a call-clobbered register). */
tramp
[
0
]
=
0x0621
+
((
val
&
0xffff
)
<<
16
);
/* mov sym, r1 ... */
tramp
[
1
]
=
((
val
>>
16
)
&
0xffff
)
+
0x610000
;
/* ...; jmp r1 */
/* Init, or core PLT? */
if
(
location
>=
mod
->
module_core
&&
location
<
mod
->
module_core
+
mod
->
arch
.
core_plt_offset
)
entry
=
mod
->
module_core
+
mod
->
arch
.
core_plt_offset
;
else
entry
=
mod
->
module_init
+
mod
->
arch
.
init_plt_offset
;
/* Find this entry, or if that fails, the next avail. entry */
while
(
entry
->
tramp
[
0
])
if
(
entry
->
tramp
[
0
]
==
tramp
[
0
]
&&
entry
->
tramp
[
1
]
==
tramp
[
1
])
return
(
uint32_t
)
entry
;
else
entry
++
;
entry
->
tramp
[
0
]
=
tramp
[
0
];
entry
->
tramp
[
1
]
=
tramp
[
1
];
return
(
uint32_t
)
entry
;
}
int
apply_relocate_add
(
Elf32_Shdr
*
sechdrs
,
const
char
*
strtab
,
unsigned
int
symindex
,
unsigned
int
relsec
,
struct
module
*
mod
)
{
unsigned
int
i
;
Elf32_Rela
*
rela
=
(
void
*
)
sechdrs
[
relsec
].
sh_offset
;
DEBUGP
(
"Applying relocate section %u to %u
\n
"
,
relsec
,
sechdrs
[
relsec
].
sh_info
);
for
(
i
=
0
;
i
<
sechdrs
[
relsec
].
sh_size
/
sizeof
(
*
rela
);
i
++
)
{
/* This is where to make the change */
uint32_t
*
loc
=
((
void
*
)
sechdrs
[
sechdrs
[
relsec
].
sh_info
].
sh_offset
+
rela
[
i
].
r_offset
);
/* This is the symbol it is referring to */
Elf32_Sym
*
sym
=
((
Elf32_Sym
*
)
sechdrs
[
symindex
].
sh_offset
+
ELF32_R_SYM
(
rela
[
i
].
r_info
));
uint32_t
val
=
sym
->
st_value
;
if
(
!
val
)
{
printk
(
KERN_WARNING
"%s: Unknown symbol %s
\n
"
,
mod
->
name
,
strtab
+
sym
->
st_name
);
return
-
ENOENT
;
}
val
+=
rela
[
i
].
r_addend
;
switch
(
ELF32_R_TYPE
(
rela
[
i
].
r_info
))
{
case
R_V850_32
:
/* We write two shorts instead of a long because even
32-bit insns only need half-word alignment, but
32-bit data writes need to be long-word aligned. */
val
+=
((
uint16_t
*
)
loc
)[
0
];
val
+=
((
uint16_t
*
)
loc
)[
1
]
<<
16
;
((
uint16_t
*
)
loc
)[
0
]
=
val
&
0xffff
;
((
uint16_t
*
)
loc
)[
1
]
=
(
val
>>
16
)
&
0xffff
;
break
;
case
R_V850_22_PCREL
:
/* Maybe jump indirectly via a PLT table entry. */
if
((
int32_t
)(
val
-
(
uint32_t
)
loc
)
>
0x1fffff
||
(
int32_t
)(
val
-
(
uint32_t
)
loc
)
<
-
0x200000
)
val
=
do_plt_call
(
loc
,
val
,
mod
);
val
-=
(
uint32_t
)
loc
;
/* We write two shorts instead of a long because
even 32-bit insns only need half-word alignment,
but 32-bit data writes need to be long-word
aligned. */
((
uint16_t
*
)
loc
)[
0
]
=
(
*
(
uint16_t
*
)
loc
&
0xffc0
)
/* opcode + reg */
|
((
val
>>
16
)
&
0xffc03f
);
/* offs high */
((
uint16_t
*
)
loc
)[
1
]
=
(
val
&
0xffff
);
/* offs low */
break
;
default:
printk
(
KERN_ERR
"module %s: Unknown reloc: %u
\n
"
,
mod
->
name
,
ELF32_R_TYPE
(
rela
[
i
].
r_info
));
return
-
ENOEXEC
;
}
}
return
0
;
}
arch/v850/kernel/v850_ksyms.c
View file @
e523efb3
...
...
@@ -27,6 +27,9 @@ EXPORT_SYMBOL (trap_table);
extern
void
dump_thread
(
struct
pt_regs
*
,
struct
user
*
);
EXPORT_SYMBOL
(
dump_thread
);
EXPORT_SYMBOL
(
kernel_thread
);
EXPORT_SYMBOL
(
enable_irq
);
EXPORT_SYMBOL
(
disable_irq
);
EXPORT_SYMBOL
(
disable_irq_nosync
);
EXPORT_SYMBOL
(
__bug
);
/* Networking helper routines. */
...
...
@@ -46,7 +49,6 @@ EXPORT_SYMBOL_NOVERS (strchr);
EXPORT_SYMBOL_NOVERS
(
strlen
);
EXPORT_SYMBOL_NOVERS
(
strnlen
);
EXPORT_SYMBOL_NOVERS
(
strpbrk
);
EXPORT_SYMBOL_NOVERS
(
strtok
);
EXPORT_SYMBOL_NOVERS
(
strrchr
);
EXPORT_SYMBOL_NOVERS
(
strstr
);
EXPORT_SYMBOL_NOVERS
(
memset
);
...
...
include/asm-v850/elf.h
View file @
e523efb3
...
...
@@ -19,7 +19,8 @@ typedef struct user_fpu_struct elf_fpregset_t;
/*
* This is used to ensure we don't load something for the wrong architecture.
*/
#define elf_check_arch(x) ( (x)->e_machine == EM_CYGNUS_V850 )
#define elf_check_arch(x) \
((x)->e_machine == EM_V850 || (x)->e_machine == EM_CYGNUS_V850)
/*
* These are used to set parameters in the core dumps.
...
...
include/asm-v850/irq.h
View file @
e523efb3
...
...
@@ -52,6 +52,17 @@ typedef void (*irq_handler_t)(int irq, void *data, struct pt_regs *regs);
interrupt. */
extern
unsigned
int
handle_irq
(
int
irq
,
struct
pt_regs
*
regs
);
/* Enable interrupt handling on an irq. */
extern
void
enable_irq
(
unsigned
int
irq
);
/* Disable an irq and wait for completion. */
extern
void
disable_irq
(
unsigned
int
irq
);
/* Disable an irq without waiting. */
extern
void
disable_irq_nosync
(
unsigned
int
irq
);
#endif
/* !__ASSEMBLY__ */
#endif
/* __V850_IRQ_H__ */
include/asm-v850/module.h
View file @
e523efb3
...
...
@@ -3,20 +3,40 @@
*
* Copyright (C) 2001,02 NEC Corporation
* Copyright (C) 2001,02 Miles Bader <miles@gnu.org>
* Copyright (C) 2001 Rusty Russell
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* Written by Miles Bader <miles@gnu.org>
*
* Derived in part from include/asm-ppc/module.h
*/
#ifndef __V850_MODULE_H__
#define __V850_MODULE_H__
#define arch_init_modules(x) ((void)0)
#define module_arch_init(x) (0)
#define module_map(sz) vmalloc (sz)
#define module_unmap(sz) vfree (sz)
#define MODULE_SYMBOL_PREFIX "_"
struct
v850_plt_entry
{
/* Indirect jump instruction sequence (6-byte mov + 2-byte jr). */
unsigned
long
tramp
[
2
];
};
struct
mod_arch_specific
{
/* How much of the core is actually taken up with core (then
we know the rest is for the PLT). */
unsigned
int
core_plt_offset
;
/* Same for init. */
unsigned
int
init_plt_offset
;
};
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Ehdr Elf32_Ehdr
#endif
/* __V850_MODULE_H__ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment