Commit f3ef7ee5 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://ldm.bkbits.net/linux-2.5-core

into home.transmeta.com:/home/torvalds/v2.5/linux
parents eeacc936 0c9fffaa
...@@ -87,13 +87,12 @@ process_reloc_for_got(Elf64_Rela *rela, ...@@ -87,13 +87,12 @@ process_reloc_for_got(Elf64_Rela *rela,
} }
int int
module_frob_arch_sections(const Elf64_Ehdr *hdr, const Elf64_Shdr *sechdrs, module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs,
const char *secstrings, struct module *me) char *secstrings, struct module *me)
{ {
struct got_entry *chains; struct got_entry *chains;
Elf64_Rela *rela; Elf64_Rela *rela;
const Elf64_Shdr *esechdrs, *symtab, *s; Elf64_Shdr *esechdrs, *symtab, *s, *got;
Elf64_Shdr *got;
unsigned long nsyms, nrela, i; unsigned long nsyms, nrela, i;
esechdrs = sechdrs + hdr->e_shnum; esechdrs = sechdrs + hdr->e_shnum;
...@@ -106,7 +105,7 @@ module_frob_arch_sections(const Elf64_Ehdr *hdr, const Elf64_Shdr *sechdrs, ...@@ -106,7 +105,7 @@ module_frob_arch_sections(const Elf64_Ehdr *hdr, const Elf64_Shdr *sechdrs,
if (s->sh_type == SHT_SYMTAB) if (s->sh_type == SHT_SYMTAB)
symtab = s; symtab = s;
else if (!strcmp(".got", secstrings + s->sh_name)) { else if (!strcmp(".got", secstrings + s->sh_name)) {
got = (Elf64_Shdr *) s; got = s;
me->arch.gotsecindex = s - sechdrs; me->arch.gotsecindex = s - sechdrs;
} }
......
...@@ -378,17 +378,19 @@ static void setup_frame(int sig, struct k_sigaction *ka, ...@@ -378,17 +378,19 @@ static void setup_frame(int sig, struct k_sigaction *ka,
if (err) if (err)
goto give_sigsegv; goto give_sigsegv;
/* Set up to return from userspace. If provided, use a stub /* Set up to return from userspace. */
already in userspace. */ err |= __put_user(fix_to_virt(FIX_VSYSCALL) + 32, &frame->pretcode);
if (ka->sa.sa_flags & SA_RESTORER) {
err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); /*
} else { * This is popl %eax ; movl $,%eax ; int $0x80
err |= __put_user(frame->retcode, &frame->pretcode); *
/* This is popl %eax ; movl $,%eax ; int $0x80 */ * WE DO NOT USE IT ANY MORE! It's only left here for historical
err |= __put_user(0xb858, (short *)(frame->retcode+0)); * reasons and because gdb uses it as a signature to notice
err |= __put_user(__NR_sigreturn, (int *)(frame->retcode+2)); * signal handler stack frames.
err |= __put_user(0x80cd, (short *)(frame->retcode+6)); */
} err |= __put_user(0xb858, (short *)(frame->retcode+0));
err |= __put_user(__NR_sigreturn, (int *)(frame->retcode+2));
err |= __put_user(0x80cd, (short *)(frame->retcode+6));
if (err) if (err)
goto give_sigsegv; goto give_sigsegv;
...@@ -453,17 +455,19 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -453,17 +455,19 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (err) if (err)
goto give_sigsegv; goto give_sigsegv;
/* Set up to return from userspace. If provided, use a stub /* Set up to return from userspace. */
already in userspace. */ err |= __put_user(fix_to_virt(FIX_VSYSCALL) + 64, &frame->pretcode);
if (ka->sa.sa_flags & SA_RESTORER) {
err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); /*
} else { * This is movl $,%eax ; int $0x80
err |= __put_user(frame->retcode, &frame->pretcode); *
/* This is movl $,%eax ; int $0x80 */ * WE DO NOT USE IT ANY MORE! It's only left here for historical
err |= __put_user(0xb8, (char *)(frame->retcode+0)); * reasons and because gdb uses it as a signature to notice
err |= __put_user(__NR_rt_sigreturn, (int *)(frame->retcode+1)); * signal handler stack frames.
err |= __put_user(0x80cd, (short *)(frame->retcode+5)); */
} err |= __put_user(0xb8, (char *)(frame->retcode+0));
err |= __put_user(__NR_rt_sigreturn, (int *)(frame->retcode+1));
err |= __put_user(0x80cd, (short *)(frame->retcode+5));
if (err) if (err)
goto give_sigsegv; goto give_sigsegv;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <asm/cpufeature.h> #include <asm/cpufeature.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/unistd.h>
extern asmlinkage void sysenter_entry(void); extern asmlinkage void sysenter_entry(void);
...@@ -73,10 +74,23 @@ static int __init sysenter_setup(void) ...@@ -73,10 +74,23 @@ static int __init sysenter_setup(void)
0x59, /* pop %ecx */ 0x59, /* pop %ecx */
0xc3 /* ret */ 0xc3 /* ret */
}; };
static const char sigreturn[] = {
/* 32: sigreturn point */
0x58, /* popl %eax */
0xb8, __NR_sigreturn, 0, 0, 0, /* movl $__NR_sigreturn, %eax */
0xcd, 0x80, /* int $0x80 */
};
static const char rt_sigreturn[] = {
/* 64: rt_sigreturn point */
0xb8, __NR_rt_sigreturn, 0, 0, 0, /* movl $__NR_rt_sigreturn, %eax */
0xcd, 0x80, /* int $0x80 */
};
unsigned long page = get_zeroed_page(GFP_ATOMIC); unsigned long page = get_zeroed_page(GFP_ATOMIC);
__set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY); __set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY);
memcpy((void *) page, int80, sizeof(int80)); memcpy((void *) page, int80, sizeof(int80));
memcpy((void *)(page + 32), sigreturn, sizeof(sigreturn));
memcpy((void *)(page + 64), rt_sigreturn, sizeof(rt_sigreturn));
if (!boot_cpu_has(X86_FEATURE_SEP)) if (!boot_cpu_has(X86_FEATURE_SEP))
return 0; return 0;
......
...@@ -384,8 +384,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -384,8 +384,6 @@ void __init setup_arch(char **cmdline_p)
conswitchp = &dummy_con; conswitchp = &dummy_con;
#endif #endif
#endif #endif
exception_table_check();
} }
#ifndef CONFIG_X86_TSC #ifndef CONFIG_X86_TSC
......
...@@ -397,7 +397,8 @@ static void do_trap(int trapnr, int signr, char *str, ...@@ -397,7 +397,8 @@ static void do_trap(int trapnr, int signr, char *str,
/* kernel trap */ /* kernel trap */
{ {
unsigned long fixup = search_exception_table(regs->rip); const struct exception_table_entry *fixup;
fixup = search_exception_tables(regs->rip);
if (fixup) { if (fixup) {
extern int exception_trace; extern int exception_trace;
if (exception_trace) if (exception_trace)
...@@ -405,7 +406,7 @@ static void do_trap(int trapnr, int signr, char *str, ...@@ -405,7 +406,7 @@ static void do_trap(int trapnr, int signr, char *str,
"%s: fixed kernel exception at %lx err:%ld\n", "%s: fixed kernel exception at %lx err:%ld\n",
current->comm, regs->rip, error_code); current->comm, regs->rip, error_code);
regs->rip = fixup; regs->rip = fixup->fixup;
} else } else
die(str, regs, error_code); die(str, regs, error_code);
return; return;
...@@ -449,8 +450,6 @@ asmlinkage void do_int3(struct pt_regs * regs, long error_code) ...@@ -449,8 +450,6 @@ asmlinkage void do_int3(struct pt_regs * regs, long error_code)
do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); do_trap(3, SIGTRAP, "int3", regs, error_code, NULL);
} }
extern void dump_pagetable(unsigned long);
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
{ {
#ifdef CONFIG_CHECKING #ifdef CONFIG_CHECKING
...@@ -479,13 +478,12 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) ...@@ -479,13 +478,12 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
/* kernel gp */ /* kernel gp */
{ {
unsigned long fixup; const struct exception_table_entry *fixup;
fixup = search_exception_table(regs->rip); fixup = search_exception_tables(regs->rip);
if (fixup) { if (fixup) {
regs->rip = fixup; regs->rip = fixup->fixup;
return; return;
} }
// dump_pagetable(regs->rip);
die("general protection fault", regs, error_code); die("general protection fault", regs, error_code);
} }
} }
......
...@@ -6,32 +6,12 @@ ...@@ -6,32 +6,12 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/init.h>
extern const struct exception_table_entry __start___ex_table[]; /* Simple binary search */
extern const struct exception_table_entry __stop___ex_table[]; const struct exception_table_entry *
search_extable(const struct exception_table_entry *first,
const struct exception_table_entry *last,
void __init exception_table_check(void) unsigned long value)
{
const struct exception_table_entry *e;
unsigned long prev;
prev = 0;
for (e = __start___ex_table; e < __stop___ex_table; e++) {
if (e->insn < prev) {
panic("unordered exception table at %016lx:%016lx and %016lx:%016lx\n",
prev, e[-1].fixup,
e->insn, e->fixup);
}
prev = e->insn;
}
}
static unsigned long
search_one_table(const struct exception_table_entry *first,
const struct exception_table_entry *last,
unsigned long value)
{ {
while (first <= last) { while (first <= last) {
const struct exception_table_entry *mid; const struct exception_table_entry *mid;
...@@ -40,42 +20,11 @@ search_one_table(const struct exception_table_entry *first, ...@@ -40,42 +20,11 @@ search_one_table(const struct exception_table_entry *first,
mid = (last - first) / 2 + first; mid = (last - first) / 2 + first;
diff = mid->insn - value; diff = mid->insn - value;
if (diff == 0) if (diff == 0)
return mid->fixup; return mid;
else if (diff < 0) else if (diff < 0)
first = mid+1; first = mid+1;
else else
last = mid-1; last = mid-1;
} }
return 0; return NULL;
}
extern spinlock_t modlist_lock;
unsigned long
search_exception_table(unsigned long addr)
{
unsigned long ret = 0;
unsigned long flags;
#ifndef CONFIG_MODULES
/* There is only the kernel to search. */
return search_one_table(__start___ex_table, __stop___ex_table-1, addr);
#else
/* The kernel is the last "module" -- no need to treat it special. */
struct list_head *i;
spin_lock_irqsave(&modlist_lock, flags);
list_for_each(i, &extables) {
struct exception_table *ex =
list_entry(i,struct exception_table, list);
if (ex->num_entries == 0)
continue;
ret = search_one_table(ex->entry,
ex->entry + ex->num_entries - 1, addr);
if (ret)
break;
}
spin_unlock_irqrestore(&modlist_lock, flags);
return ret;
#endif
} }
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/vt_kern.h> /* For unblank_screen() */ #include <linux/vt_kern.h> /* For unblank_screen() */
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/module.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -101,7 +102,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -101,7 +102,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
struct mm_struct *mm; struct mm_struct *mm;
struct vm_area_struct * vma; struct vm_area_struct * vma;
unsigned long address; unsigned long address;
unsigned long fixup; const struct exception_table_entry *fixup;
int write; int write;
siginfo_t info; siginfo_t info;
...@@ -239,8 +240,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -239,8 +240,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
no_context: no_context:
/* Are we prepared to handle this kernel fault? */ /* Are we prepared to handle this kernel fault? */
if ((fixup = search_exception_table(regs->rip)) != 0) { fixup = search_exception_tables(regs->rip);
regs->rip = fixup; if (fixup) {
regs->rip = fixup->fixup;
if (0 && exception_trace) if (0 && exception_trace)
printk(KERN_ERR printk(KERN_ERR
"%s: fixed kernel exception at %lx address %lx err:%ld\n", "%s: fixed kernel exception at %lx address %lx err:%ld\n",
......
...@@ -71,9 +71,6 @@ struct exception_table_entry ...@@ -71,9 +71,6 @@ struct exception_table_entry
unsigned long insn, fixup; unsigned long insn, fixup;
}; };
/* Returns 0 if exception not found and fixup otherwise. */
extern unsigned long search_exception_table(unsigned long);
/* /*
* These are the main single-value transfer routines. They automatically * These are the main single-value transfer routines. They automatically
......
...@@ -1109,7 +1109,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags) ...@@ -1109,7 +1109,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct unix_sock *u = unix_sk(sk); struct unix_sock *u;
struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr; struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
int err = 0; int err = 0;
...@@ -1124,6 +1124,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_ ...@@ -1124,6 +1124,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_
sock_hold(sk); sock_hold(sk);
} }
u = unix_sk(sk);
unix_state_rlock(sk); unix_state_rlock(sk);
if (!u->addr) { if (!u->addr) {
sunaddr->sun_family = AF_UNIX; sunaddr->sun_family = AF_UNIX;
......
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