Commit 251a1272 authored by Anton Blanchard's avatar Anton Blanchard

ppc64: 2.5 module support, from Rusty

parent 37deafa7
......@@ -6,7 +6,7 @@ EXTRA_CFLAGS += -mno-minimal-toc
EXTRA_TARGETS := head.o
export-objs := ppc_ksyms.o
obj-y := ppc_ksyms.o setup.o entry.o traps.o irq.o idle.o \
obj-y := setup.o entry.o traps.o irq.o idle.o \
time.o process.o signal.o syscalls.o misc.o ptrace.o \
align.o semaphore.o bitops.o stab.o htab.o pacaData.o \
udbg.o binfmt_elf32.o sys_ppc32.o sys32.o ioctl32.o \
......@@ -30,3 +30,4 @@ obj-y += open_pic.o xics.o pSeries_htab.o rtas.o \
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PROFILING) += profile.o
obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
......@@ -4495,10 +4495,9 @@ int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, u
{
int i;
if (!additional_ioctls) {
additional_ioctls = module_map(PAGE_SIZE);
additional_ioctls = get_zeroed_page(GFP_KERNEL);
if (!additional_ioctls)
return -ENOMEM;
memset(additional_ioctls, 0, PAGE_SIZE);
}
for (i = 0; i < PAGE_SIZE/sizeof(struct ioctl_trans); i++) {
if (!additional_ioctls[i].cmd)
......
This diff is collapsed.
......@@ -47,9 +47,6 @@
#include <asm/iSeries/HvLpConfig.h>
#endif
/* Tell string.h we don't want memcpy etc. as cpp defines */
#define EXPORT_SYMTAB_STROPS
extern int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
extern int sys_sigreturn(struct pt_regs *regs);
extern int do_signal(sigset_t *, struct pt_regs *);
......@@ -81,6 +78,7 @@ EXPORT_SYMBOL(isa_io_base);
EXPORT_SYMBOL(pci_io_base);
EXPORT_SYMBOL(find_next_zero_bit);
EXPORT_SYMBOL(find_next_zero_le_bit);
EXPORT_SYMBOL(strcpy);
EXPORT_SYMBOL(strncpy);
......@@ -184,7 +182,6 @@ EXPORT_SYMBOL(giveup_fpu);
EXPORT_SYMBOL(enable_kernel_fp);
EXPORT_SYMBOL(flush_icache_range);
EXPORT_SYMBOL(flush_icache_user_range);
EXPORT_SYMBOL(flush_icache_page);
EXPORT_SYMBOL(flush_dcache_page);
#ifdef CONFIG_SMP
#ifdef CONFIG_PPC_ISERIES
......@@ -207,9 +204,6 @@ EXPORT_SYMBOL(find_all_nodes);
EXPORT_SYMBOL(get_property);
EXPORT_SYMBOL_NOVERS(__ashrdi3);
EXPORT_SYMBOL_NOVERS(__ashldi3);
EXPORT_SYMBOL_NOVERS(__lshrdi3);
EXPORT_SYMBOL_NOVERS(memcpy);
EXPORT_SYMBOL_NOVERS(memset);
EXPORT_SYMBOL_NOVERS(memmove);
......
......@@ -934,431 +934,38 @@ asmlinkage long sys32_adjtimex(struct timex32 *utp)
return ret;
}
#ifdef CONFIG_MODULES
extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size);
extern asmlinkage long sys_init_module(void *, unsigned long, const char *);
asmlinkage unsigned long sys32_create_module(const char *name_user, compat_size_t size)
asmlinkage int sys32_init_module(void *umod, u32 len, const char *uargs)
{
return sys_create_module(name_user, (size_t)size);
return sys_init_module(umod, len, uargs);
}
extern asmlinkage long sys_delete_module(const char *, unsigned int);
extern asmlinkage long sys_init_module(const char *name_user, struct module *mod_user);
asmlinkage long sys32_init_module(const char *name_user, struct module *mod_user)
asmlinkage int sys32_delete_module(const char *name_user, unsigned int flags)
{
return sys_init_module(name_user, mod_user);
}
extern asmlinkage long sys_delete_module(const char *name_user);
asmlinkage long sys32_delete_module(const char *name_user)
{
return sys_delete_module(name_user);
}
struct module_info32 {
u32 addr;
u32 size;
u32 flags;
s32 usecount;
};
/* Query various bits about modules. */
static inline long
get_mod_name(const char *user_name, char **buf)
{
unsigned long page;
long retval;
if ((unsigned long)user_name >= TASK_SIZE
&& !segment_eq(get_fs (), KERNEL_DS))
return -EFAULT;
page = __get_free_page(GFP_KERNEL);
if (!page)
return -ENOMEM;
retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
if (retval > 0) {
if (retval < PAGE_SIZE) {
*buf = (char *)page;
return retval;
}
retval = -ENAMETOOLONG;
} else if (!retval)
retval = -EINVAL;
free_page(page);
return retval;
}
static inline void
put_mod_name(char *buf)
{
free_page((unsigned long)buf);
}
static __inline__ struct module *find_module(const char *name)
{
struct module *mod;
for (mod = module_list; mod ; mod = mod->next) {
if (mod->flags & MOD_DELETED)
continue;
if (!strcmp(mod->name, name))
break;
}
return mod;
}
static int
qm_modules(char *buf, size_t bufsize, compat_size_t *ret)
{
struct module *mod;
size_t nmod, space, len;
nmod = space = 0;
for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) {
len = strlen(mod->name)+1;
if (len > bufsize)
goto calc_space_needed;
if (copy_to_user(buf, mod->name, len))
return -EFAULT;
buf += len;
bufsize -= len;
space += len;
}
if (put_user(nmod, ret))
return -EFAULT;
else
return 0;
calc_space_needed:
space += len;
while ((mod = mod->next)->next != NULL)
space += strlen(mod->name)+1;
if (put_user(space, ret))
return -EFAULT;
else
return -ENOSPC;
}
static int
qm_deps(struct module *mod, char *buf, size_t bufsize, compat_size_t *ret)
{
size_t i, space, len;
if (mod->next == NULL)
return -EINVAL;
if (!MOD_CAN_QUERY(mod))
return put_user(0, ret);
space = 0;
for (i = 0; i < mod->ndeps; ++i) {
const char *dep_name = mod->deps[i].dep->name;
len = strlen(dep_name)+1;
if (len > bufsize)
goto calc_space_needed;
if (copy_to_user(buf, dep_name, len))
return -EFAULT;
buf += len;
bufsize -= len;
space += len;
}
return put_user(i, ret);
calc_space_needed:
space += len;
while (++i < mod->ndeps)
space += strlen(mod->deps[i].dep->name)+1;
if (put_user(space, ret))
return -EFAULT;
else
return -ENOSPC;
}
static int
qm_refs(struct module *mod, char *buf, size_t bufsize, compat_size_t *ret)
{
size_t nrefs, space, len;
struct module_ref *ref;
if (mod->next == NULL)
return -EINVAL;
if (!MOD_CAN_QUERY(mod))
if (put_user(0, ret))
return -EFAULT;
else
return 0;
space = 0;
for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
const char *ref_name = ref->ref->name;
len = strlen(ref_name)+1;
if (len > bufsize)
goto calc_space_needed;
if (copy_to_user(buf, ref_name, len))
return -EFAULT;
buf += len;
bufsize -= len;
space += len;
}
if (put_user(nrefs, ret))
return -EFAULT;
else
return 0;
calc_space_needed:
space += len;
while ((ref = ref->next_ref) != NULL)
space += strlen(ref->ref->name)+1;
if (put_user(space, ret))
return -EFAULT;
else
return -ENOSPC;
}
static inline int
qm_symbols(struct module *mod, char *buf, size_t bufsize, compat_size_t *ret)
{
size_t i, space, len;
struct module_symbol *s;
char *strings;
unsigned *vals;
if (!MOD_CAN_QUERY(mod))
if (put_user(0, ret))
return -EFAULT;
else
return 0;
space = mod->nsyms * 2*sizeof(u32);
i = len = 0;
s = mod->syms;
if (space > bufsize)
goto calc_space_needed;
if (!access_ok(VERIFY_WRITE, buf, space))
return -EFAULT;
bufsize -= space;
vals = (unsigned *)buf;
strings = buf+space;
for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
len = strlen(s->name)+1;
if (len > bufsize)
goto calc_space_needed;
if (copy_to_user(strings, s->name, len)
|| __put_user(s->value, vals+0)
|| __put_user(space, vals+1))
return -EFAULT;
strings += len;
bufsize -= len;
space += len;
}
if (put_user(i, ret))
return -EFAULT;
else
return 0;
calc_space_needed:
for (; i < mod->nsyms; ++i, ++s)
space += strlen(s->name)+1;
if (put_user(space, ret))
return -EFAULT;
else
return -ENOSPC;
}
static inline int
qm_info(struct module *mod, char *buf, size_t bufsize, compat_size_t *ret)
{
int error = 0;
if (mod->next == NULL)
return -EINVAL;
if (sizeof(struct module_info32) <= bufsize) {
struct module_info32 info;
info.addr = (unsigned long)mod;
info.size = mod->size;
info.flags = mod->flags;
info.usecount =
((mod_member_present(mod, can_unload)
&& mod->can_unload)
? -1 : atomic_read(&mod->uc.usecount));
if (copy_to_user(buf, &info, sizeof(struct module_info32)))
return -EFAULT;
} else
error = -ENOSPC;
if (put_user(sizeof(struct module_info32), ret))
return -EFAULT;
return error;
}
/* Note: it is necessary to treat which as an unsigned int,
* with the corresponding cast to a signed int to insure that the
* proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
* and the register representation of a signed int (msr in 64-bit mode) is performed.
*/
asmlinkage long sys32_query_module(char *name_user, u32 which, char *buf, compat_size_t bufsize, u32 ret)
{
struct module *mod;
int err;
lock_kernel();
if (name_user == 0) {
/* This finds "kernel_module" which is not exported. */
for(mod = module_list; mod->next != NULL; mod = mod->next)
;
} else {
long namelen;
char *name;
if ((namelen = get_mod_name(name_user, &name)) < 0) {
err = namelen;
goto out;
}
err = -ENOENT;
if (namelen == 0) {
/* This finds "kernel_module" which is not exported. */
for(mod = module_list; mod->next != NULL; mod = mod->next)
;
} else if ((mod = find_module(name)) == NULL) {
put_mod_name(name);
goto out;
}
put_mod_name(name);
}
switch ((int)which)
{
case 0:
err = 0;
break;
case QM_MODULES:
err = qm_modules(buf, bufsize, (compat_size_t *)AA(ret));
break;
case QM_DEPS:
err = qm_deps(mod, buf, bufsize, (compat_size_t *)AA(ret));
break;
case QM_REFS:
err = qm_refs(mod, buf, bufsize, (compat_size_t *)AA(ret));
break;
case QM_SYMBOLS:
err = qm_symbols(mod, buf, bufsize, (compat_size_t *)AA(ret));
break;
case QM_INFO:
err = qm_info(mod, buf, bufsize, (compat_size_t *)AA(ret));
break;
default:
err = -EINVAL;
break;
}
out:
unlock_kernel();
return err;
}
struct kernel_sym32 {
u32 value;
char name[60];
};
extern asmlinkage long sys_get_kernel_syms(struct kernel_sym *table);
asmlinkage long sys32_get_kernel_syms(struct kernel_sym32 *table)
{
int len, i;
struct kernel_sym *tbl;
mm_segment_t old_fs;
len = sys_get_kernel_syms(NULL);
if (!table) return len;
tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
if (!tbl) return -ENOMEM;
old_fs = get_fs();
set_fs (KERNEL_DS);
sys_get_kernel_syms(tbl);
set_fs (old_fs);
for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) {
if (put_user (tbl[i].value, &table->value) ||
copy_to_user (table->name, tbl[i].name, 60))
break;
}
kfree (tbl);
return i;
return sys_delete_module(name_user, flags);
}
#else /* CONFIG_MODULES */
asmlinkage unsigned long sys32_create_module(const char *name_user, size_t size)
{
return -ENOSYS;
}
asmlinkage long sys32_init_module(const char *name_user, struct module *mod_user)
asmlinkage int
sys32_init_module(const char *name_user, struct module *mod_user)
{
return -ENOSYS;
}
asmlinkage long sys32_delete_module(const char *name_user)
{
return -ENOSYS;
}
asmlinkage long sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize, size_t *ret)
{
/* Let the program know about the new interface. Not that it'll do them much good. */
if (which == 0)
return 0;
return -ENOSYS;
}
asmlinkage long sys32_get_kernel_syms(struct kernel_sym *table)
asmlinkage int
sys32_delete_module(const char *name_user)
{
return -ENOSYS;
}
#endif /* CONFIG_MODULES */
/* Stuff for NFS server syscalls... */
struct nfsctl_svc32 {
u16 svc32_port;
......
......@@ -21,10 +21,11 @@ extern struct exception_table_entry __stop___ex_table[];
* The exception table needs to be sorted because we use the macros
* which put things into the exception table in a variety of segments
* as well as the init segment and the main kernel text segment.
*
* Also used for modules.
*/
static inline void
sort_ex_table(struct exception_table_entry *start,
struct exception_table_entry *finish)
void sort_ex_table(struct exception_table_entry *start,
struct exception_table_entry *finish) __init_or_module
{
struct exception_table_entry el, *p, *q;
......
#ifndef _ASM_PPC64_MODULE_H
#define _ASM_PPC64_MODULE_H
/*
* This file contains the PPC architecture specific module code.
*
* Copyright (C) 2001 PPC 64 Team, IBM Corp
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#define module_map(x) vmalloc(x)
#define module_unmap(x) vfree(x)
#define arch_init_modules(x) do { } while (0)
#define module_arch_init(x) (0)
struct mod_arch_specific
{
/* Index of stubs section within module. */
unsigned int stubs_section;
/* What section is the TOC? */
unsigned int toc_section;
};
#define Elf_Shdr Elf64_Shdr
#define Elf_Sym Elf64_Sym
#define Elf_Ehdr Elf64_Ehdr
/* Make empty section for module_frob_arch_sections to expand. */
#ifdef MODULE
asm(".section .stubs,\"ax\",@nobits; .align 3; .previous");
#endif
#endif /* _ASM_PPC64_MODULE_H */
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