Commit f3081f5b authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] x86-64 merge

This patch depends on the i386 MTRR driver cleanup I sent earlier.

 - Support non executable mappings for x86-64. data/heap are non executable
   by default now.
 - Beginnings of software suspend from Pavel (not working yet)
 - Support generic compat functions and remove some shared code
   in the 32bit emulation (Stephen Rothwell)
 - Support hugetlbfs
 - Some makefile updates
 - Make sure all 32bit emulation functions return long, not int.
   This fixes some problems with ERESTARTNOSYS.et.al. leaking to userspace.
 - Add new system calls.
 - Fix long standing fs/gs context switch bugs (thanks to Karsten Keil
   for helping to fix that mess). Also make sure the gs selector is
   set to 0 after an exec.
 - Simplify TLS switching
 - Paranoid CPUID check at bootup
 - Reorder scatterlist to be more space efficient (Jes Soerensen)
 - Enlarge 32bit address space to full 4GB.
 - Beginnings of 32bit SYSCALL support (not completely working yet
   and vsyscall page miss yet)
 - Various merges from i386
 - New module loader
 - Support threaded core dump (XMM saving for 32bit programs doesn't
   work, but it appears to be broken on i386 too)
 - Fix bug in signal stack rounding
 - Remove DRM 32bit emulation.
 - Use MTRR driver from i386
 - Use bootflag.c from i386
 - Various other fixes and cleanups.
parent d276c772
......@@ -175,6 +175,14 @@ config MTRR
See <file:Documentation/mtrr.txt> for more information.
config HUGETLB_PAGE
bool "Huge TLB Page Support"
help
This enables support for huge pages. User space applications
can make use of this support with the hugetlbfs file system
To actually use it you need to pass an hugepages= argument
to the kernel at boot time.
config SMP
bool "Symmetric multi-processing support"
---help---
......@@ -285,6 +293,35 @@ config PM
will issue the hlt instruction if nothing is to be done, thereby
sending the processor to sleep and saving power.
config SOFTWARE_SUSPEND
bool "Software Suspend (EXPERIMENTAL)"
depends on EXPERIMENTAL && PM
---help---
Enable the possibilty of suspendig machine. It doesn't need APM.
You may suspend your machine by 'swsusp' or 'shutdown -z <time>'
(patch for sysvinit needed).
It creates an image which is saved in your active swaps. By the next
booting the, pass 'resume=/path/to/your/swap/file' and kernel will
detect the saved image, restore the memory from
it and then it continues to run as before you've suspended.
If you don't want the previous state to continue use the 'noresume'
kernel option. However note that your partitions will be fsck'd and
you must re-mkswap your swap partitions/files.
Right now you may boot without resuming and then later resume but
in meantime you cannot use those swap partitions/files which were
involved in suspending. Also in this case there is a risk that buffers
on disk won't match with saved ones.
SMP is supported ``as-is''. There's a code for it but doesn't work.
There have been problems reported relating SCSI.
This option is about getting stable. However there is still some
absence of features.
For more information take a look at Documentation/swsusp.txt.
source "drivers/acpi/Kconfig"
endmenu
......@@ -425,6 +462,11 @@ config IA32_EMULATION
turn this on, unless you're 100% sure that you don't have any 32bit programs
left.
config COMPAT
bool
depends on IA32_EMULATION
default y
endmenu
source "drivers/mtd/Kconfig"
......@@ -692,6 +734,16 @@ config KALLSYMS
symbolic stack backtraces. This increases the size of the kernel
somewhat, as all symbols have to be loaded into the kernel image.
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
depends on DEBUG_KERNEL
help
If you say Y here the resulting kernel image will be slightly larger
and slower, but it will give very useful debugging information.
If you don't debug the kernel, you can say N, but we may not be able
to solve problems without frame pointers.
Note this is normally not needed on x86-64.
endmenu
source "security/Kconfig"
......
......@@ -36,6 +36,7 @@ export IA32_CC IA32_LD IA32_AS IA32_OBJCOPY IA32_CPP
LDFLAGS := -m elf_x86_64
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
LDFLAGS_vmlinux := -e stext
LDFLAGS_BLOB := --format binary --oformat elf64-x86-64
CFLAGS += -mno-red-zone
CFLAGS += -mcmodel=kernel
......@@ -54,8 +55,7 @@ core-y += arch/x86_64/kernel/ arch/x86_64/mm/
core-$(CONFIG_IA32_EMULATION) += arch/x86_64/ia32/
drivers-$(CONFIG_PCI) += arch/x86_64/pci/
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
makeboot = $(call descend,arch/x86_64/boot,$(1))
makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/x86_64/boot $(1)
.PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install \
clean archclean archmrproper
......@@ -64,21 +64,21 @@ BOOTIMAGE=arch/x86_64/boot/bzImage
zImage zlilo zdisk: BOOTIMAGE=arch/x86_64/boot/zImage
zImage bzImage: vmlinux
+@$(call makeboot,$(BOOTIMAGE))
$(call makeboot,$(BOOTIMAGE))
compressed: zImage
zlilo bzlilo: vmlinux
+@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) zlilo)
$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) zlilo)
zdisk bzdisk: vmlinux
+@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) zdisk)
$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) zdisk)
install: vmlinux
+@$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) install)
$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) install)
archclean:
+@$(call makeboot,clean)
$(call makeboot,clean)
archmrproper:
......
......@@ -32,10 +32,6 @@ CFLAGS += -m32
host-progs := tools/build
# Default
boot: bzImage
# ---------------------------------------------------------------------------
$(obj)/zImage: IMAGE_OFFSET := 0x1000
......@@ -62,9 +58,8 @@ $(obj)/setup $(obj)/bootsect: %: %.o FORCE
$(call if_changed,ld)
$(obj)/compressed/vmlinux: FORCE
+@$(call descend,$(obj)/compressed,IMAGE_OFFSET=$(IMAGE_OFFSET) \
$(obj)/compressed/vmlinux)
$(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed \
IMAGE_OFFSET=$(IMAGE_OFFSET) $@
zdisk: $(BOOTIMAGE)
dd bs=8192 if=$(BOOTIMAGE) of=/dev/fd0
......
......@@ -18,9 +18,9 @@ LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32 -m elf_i386
$(obj)/vmlinux: $(obj)/head.o $(obj)/misc.o $(obj)/piggy.o FORCE
$(call if_changed,ld)
@:
$(obj)/vmlinux.bin: vmlinux FORCE
strip vmlinux
$(call if_changed,objcopy)
$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
......
......@@ -330,6 +330,8 @@ void close_output_buffer_if_we_run_high(struct moveparams *mv)
void check_cpu(void)
{
int res = 0;
int tmp, flags;
asm volatile( " \n\
movl $3,%%edx # at least 386 \n\
pushfl # push EFLAGS \n\
......@@ -395,6 +397,43 @@ void check_cpu(void)
}
if (res !=7)
error( "Sorry, your CPU is not capable of running 64-bit kernel." );
/* check required feature flags */
/* see http://www.x86-64.org/lists/discuss/msg02971.html */
#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|(1<<11)| \
(1<<13)|(1<<15)|(1<<24))
asm("cpuid" : "=d" (flags), "=a" (tmp) : "1" (0x80000001) : "ebx", "ecx");
flags &= REQUIRED_MASK1;
flags ^= REQUIRED_MASK1;
if (flags & (1<<0))
error("CPU misses x87");
if (flags & (1<<3))
error("CPU doesn't support page size extension (PSE)");
if (flags & (1<<4))
error("CPU misses an time stamp counter");
if (flags & (1<<5))
error("CPU misses AMD style MSRs");
if (flags & (1<<6))
error("CPU misses physical address extension (PAE)");
if (flags & (1<<8))
error("CPU misses cmpxchg8");
if (flags & (1<<11))
error("CPU doesn't support SYSCALL/SYSRET");
if (flags & (1<<13))
error("CPU doesn't support PGE");
if (flags & (1<<15))
error("CPU doesn't support CMOV");
if (flags & (1<<24))
error("CPU doesn't support FXSAVE/FXRSTOR");
#define REQUIRED_MASK2 ((1<<25)|(1<<26))
asm("cpuid" : "=d" (flags), "=a" (tmp) : "1" (1) : "ebx", "ecx");
flags &= REQUIRED_MASK2;
flags ^= REQUIRED_MASK2;
if (flags & (1<<25))
error("CPU doesn't support SSE1");
if (flags & (1<<26))
error("CPU doesn't support SSE2");
}
int decompress_kernel(struct moveparams *mv, void *rmode)
......
This diff is collapsed.
......@@ -70,6 +70,10 @@ static inline unsigned long twd_fxsr_to_i387(struct i387_fxsave_struct *fxsave)
return ret;
}
struct s10 {
u64 a;
u16 b;
} __attribute__((packed));
static inline int convert_fxsr_from_user(struct i387_fxsave_struct *fxsave,
struct _fpstate_ia32 *buf)
......@@ -94,7 +98,9 @@ static inline int convert_fxsr_from_user(struct i387_fxsave_struct *fxsave,
to = (struct _fpxreg *)&fxsave->st_space[0];
from = &buf->_st[0];
for (i = 0 ; i < 8 ; i++, to++, from++) {
if (__copy_from_user(to, from, sizeof(*from)))
struct s10 *top = (void *)to, *fromp = (void *)from;
if (__put_user(fromp->a, &top->a) ||
__put_user(fromp->b, &top->b))
return -1;
}
return 0;
......@@ -130,7 +136,9 @@ static inline int convert_fxsr_to_user(struct _fpstate_ia32 *buf,
to = &buf->_st[0];
from = (struct _fpxreg *) &fxsave->st_space[0];
for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
if (__copy_to_user(to, from, sizeof(*to)))
struct s10 *top = (void *)top, *fromp = (void *)from;
if (__get_user(fromp->a, &top->a) ||
__get_user(fromp->b, &top->b))
return -1;
}
return 0;
......
......@@ -6,12 +6,13 @@
* of ugly preprocessor tricks. Talk about very very poor man's inheritance.
*/
#include <linux/types.h>
#include <linux/compat.h>
#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/rwsem.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/binfmts.h>
#include <asm/segment.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
......@@ -19,14 +20,14 @@
#include <asm/sigcontext32.h>
#include <asm/fpu32.h>
#include <asm/i387.h>
#include <asm/uaccess.h>
#include <asm/ia32.h>
struct file;
struct elf_phdr;
#define IA32_EMULATOR 1
#define IA32_PAGE_OFFSET 0xffff0000
#define IA32_STACK_TOP IA32_PAGE_OFFSET
#define ELF_ET_DYN_BASE (IA32_PAGE_OFFSET/3 + 0x1000000)
#undef ELF_ARCH
......@@ -53,11 +54,6 @@ struct elf_siginfo
int si_errno; /* errno */
};
struct timeval32
{
int tv_sec, tv_usec;
};
#define jiffies_to_timeval(a,b) do { (b)->tv_usec = 0; (b)->tv_sec = (a)/HZ; }while(0)
struct elf_prstatus
......@@ -70,10 +66,10 @@ struct elf_prstatus
pid_t pr_ppid;
pid_t pr_pgrp;
pid_t pr_sid;
struct timeval32 pr_utime; /* User time */
struct timeval32 pr_stime; /* System time */
struct timeval32 pr_cutime; /* Cumulative user time */
struct timeval32 pr_cstime; /* Cumulative system time */
struct compat_timeval pr_utime; /* User time */
struct compat_timeval pr_stime; /* System time */
struct compat_timeval pr_cutime; /* Cumulative user time */
struct compat_timeval pr_cstime; /* Cumulative system time */
elf_gregset_t pr_reg; /* GP registers */
int pr_fpvalid; /* True if math co-processor being used. */
};
......@@ -123,15 +119,68 @@ struct elf_prpsinfo
#define user user32
#define dump_fpu dump_fpu_ia32
#define __ASM_X86_64_ELF_H 1
#include <asm/ia32.h>
//#include <asm/ia32.h>
#include <linux/elf.h>
typedef struct user_i387_ia32_struct elf_fpregset_t;
typedef struct user32_fxsr_struct elf_fpxregset_t;
static inline void elf_core_copy_regs(elf_gregset_t *elfregs, struct pt_regs *regs)
{
ELF_CORE_COPY_REGS((*elfregs), regs)
}
static inline int elf_core_copy_task_regs(struct task_struct *t, elf_gregset_t* elfregs)
{
struct pt_regs *pp = (struct pt_regs *)(t->thread.rsp0);
ELF_CORE_COPY_REGS((*elfregs), pp);
/* fix wrong segments */
(*elfregs)[7] = t->thread.ds;
(*elfregs)[9] = t->thread.fsindex;
(*elfregs)[10] = t->thread.gsindex;
(*elfregs)[8] = t->thread.es;
return 1;
}
static inline int
elf_core_copy_task_fpregs(struct task_struct *tsk, elf_fpregset_t *fpu)
{
struct _fpstate_ia32 *fpstate = (void*)fpu;
struct pt_regs *regs = (struct pt_regs *)(tsk->thread.rsp0);
mm_segment_t oldfs = get_fs();
int ret;
if (!tsk->used_math)
return 0;
--regs;
if (tsk == current)
unlazy_fpu(tsk);
set_fs(KERNEL_DS);
ret = save_i387_ia32(tsk, fpstate, regs, 1);
/* Correct for i386 bug. It puts the fop into the upper 16bits of
the tag word (like FXSAVE), not into the fcs*/
fpstate->cssel |= fpstate->tag & 0xffff0000;
set_fs(oldfs);
return ret;
}
#define ELF_CORE_COPY_XFPREGS 1
static inline int
elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregset_t *xfpu)
{
struct pt_regs *regs = ((struct pt_regs *)(t->thread.rsp0))-1;
if (!t->used_math)
return 0;
if (t == current)
unlazy_fpu(t);
memcpy(xfpu, &t->thread.i387.fxsave, sizeof(elf_fpxregset_t));
xfpu->fcs = regs->cs;
xfpu->fos = t->thread.ds; /* right? */
return 1;
}
#undef elf_check_arch
#define elf_check_arch(x) \
((x)->e_machine == EM_386)
......@@ -168,9 +217,9 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm);
#undef start_thread
#define start_thread(regs,new_rip,new_rsp) do { \
__asm__("movl %0,%%fs": :"r" (0)); \
__asm__("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS)); \
wrmsrl(MSR_KERNEL_GS_BASE, 0); \
asm volatile("movl %0,%%fs" :: "r" (0)); \
asm volatile("movl %0,%%es; movl %0,%%ds": :"r" (__USER32_DS)); \
load_gs_index(0); \
(regs)->rip = (new_rip); \
(regs)->rsp = (new_rsp); \
(regs)->eflags = 0x200; \
......@@ -182,6 +231,8 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm);
#define elf_map elf32_map
#include <linux/module.h>
MODULE_DESCRIPTION("Binary format loader for compatibility with IA32 ELF binaries.");
MODULE_AUTHOR("Eric Youngdale, Andi Kleen");
......@@ -245,7 +296,7 @@ int setup_arg_pages(struct linux_binprm *bprm)
mpnt->vm_mm = mm;
mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
mpnt->vm_end = IA32_STACK_TOP;
mpnt->vm_page_prot = PAGE_COPY;
mpnt->vm_page_prot = PAGE_COPY_EXEC;
mpnt->vm_flags = VM_STACK_FLAGS;
mpnt->vm_ops = NULL;
mpnt->vm_pgoff = 0;
......@@ -287,23 +338,3 @@ elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int p
return(map_addr);
}
int dump_fpu_ia32(struct pt_regs *regs, elf_fpregset_t *fp)
{
struct _fpstate_ia32 *fpu = (void*)fp;
struct task_struct *tsk = current;
mm_segment_t oldfs = get_fs();
int ret;
if (!tsk->used_math)
return 0;
if (!(test_thread_flag(TIF_IA32)))
BUG();
unlazy_fpu(tsk);
set_fs(KERNEL_DS);
ret = save_i387_ia32(current, fpu, regs, 1);
/* Correct for i386 bug. It puts the fop into the upper 16bits of
the tag word (like FXSAVE), not into the fcs*/
fpu->cssel |= fpu->tag & 0xffff0000;
set_fs(oldfs);
return ret;
}
This diff is collapsed.
......@@ -76,7 +76,7 @@ static int ia32_copy_siginfo_to_user(siginfo_t32 *to, siginfo_t *from)
}
}
asmlinkage int
asmlinkage long
sys32_sigsuspend(int history0, int history1, old_sigset_t mask, struct pt_regs regs)
{
sigset_t saveset;
......@@ -97,7 +97,7 @@ sys32_sigsuspend(int history0, int history1, old_sigset_t mask, struct pt_regs r
}
}
asmlinkage int
asmlinkage long
sys32_sigaltstack(const stack_ia32_t *uss_ptr, stack_ia32_t *uoss_ptr,
struct pt_regs regs)
{
......@@ -227,7 +227,7 @@ ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 *sc, unsign
return 1;
}
asmlinkage int sys32_sigreturn(struct pt_regs regs)
asmlinkage long sys32_sigreturn(struct pt_regs regs)
{
struct sigframe *frame = (struct sigframe *)(regs.rsp - 8);
sigset_t set;
......@@ -256,7 +256,7 @@ asmlinkage int sys32_sigreturn(struct pt_regs regs)
return 0;
}
asmlinkage int sys32_rt_sigreturn(struct pt_regs regs)
asmlinkage long sys32_rt_sigreturn(struct pt_regs regs)
{
struct rt_sigframe *frame = (struct rt_sigframe *)(regs.rsp - 4);
sigset_t set;
......
/*
* Compatibility mode system call entry point for x86-64.
*
* Copyright 2000,2001 Andi Kleen, SuSE Labs.
* Copyright 2000-2002 Andi Kleen, SuSE Labs.
*
* $Id: ia32entry.S,v 1.31 2002/03/24 13:01:45 ak Exp $
*/
......@@ -9,10 +9,11 @@
#include <asm/calling.h>
#include <asm/offset.h>
#include <asm/current.h>
#include <linux/linkage.h>
#include <asm/errno.h>
#include <asm/ia32_unistd.h>
#include <asm/thread_info.h>
#include <asm/segment.h>
#include <linux/linkage.h>
.macro IA32_ARG_FIXUP
movl %edi,%r8d
......@@ -23,12 +24,73 @@
.endm
/*
* 32bit SYSCALL instruction entry.
* 32bit SYSCALL instruction entry. This is called from the 32bit vsyscall page.
*
* Register setup:
*
* %eax System call number.
* %ebx Arg1
* %ecx return EIP
* %edx Arg3
* %esi Arg4
* %edi Arg5
* %ebp Arg2 [note: not saved in the stack frame, should not be touched]
* %esp user stack
* 0(%esp) Arg6
*
* Interrupts off.
*
* This is purely a fast path. For anything complicated we use the int 0x80
* path below. Set up a complete hardware stack frame to share code
* with the int 0x80 path.
*/
ENTRY(ia32_cstar_target)
movq $-ENOSYS,%rax
swapgs
movl %esp,%r8d
movq %gs:pda_kernelstack,%rsp
sti
SAVE_ARGS 8,1
movl %eax,%eax /* zero extension */
movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
movq %rcx,RIP-ARGOFFSET(%rsp)
movl %ebp,%ecx
movq $__USER32_CS,CS-ARGOFFSET(%rsp)
movq $__USER32_DS,SS-ARGOFFSET(%rsp)
movq %r11,EFLAGS-ARGOFFSET(%rsp)
movq %r8,RSP-ARGOFFSET(%rsp)
/* no need to do an access_ok check here because the 32bit
user space cannot set r8 to a value > 4GB and the kernel has no
memory mapping in the first 4GB. */
/* hardware stack frame is complete now */
1: movl (%r8),%ebp
.section __ex_table,"a"
.quad 1b,cstar_badarg
.previous
GET_THREAD_INFO(%r10)
bt $TIF_SYSCALL_TRACE,threadinfo_flags(%r10)
jc ia32_tracesys
cmpl $IA32_NR_syscalls,%eax
jae ia32_badsys
IA32_ARG_FIXUP
call *ia32_sys_call_table(,%rax,8)
.globl ia32_sysret
cstar_sysret:
movq %rax,RAX-ARGOFFSET(%rsp)
GET_THREAD_INFO(%r10)
cli
testl $_TIF_WORK_MASK,threadinfo_flags(%r10)
jnz int_ret_from_sys_call
RESTORE_ARGS 1,0,1,1 /* could avoid the stack restore here */
movl RIP-SWFRAME(%rsp),%ecx
movl RSP-SWFRAME(%rsp),%esp
movl EFLAGS-SWFRAME(%rsp),%r11d
swapgs
sysretl
cstar_badarg:
movq $-EFAULT,%rax
jmp cstar_sysret
/*
* Emulated IA32 system calls via int 0x80.
*
......@@ -121,7 +183,7 @@ ENTRY(ia32_ptregs_common)
.align 8
.globl ia32_sys_call_table
ia32_sys_call_table:
.quad ni_syscall /* 0 - old "setup" system call*/
.quad sys_restart_syscall
.quad sys_exit
.quad stub32_fork
.quad sys_read
......@@ -151,7 +213,7 @@ ia32_sys_call_table:
.quad sys_alarm /* XXX sign extension??? */
.quad ni_syscall /* (old)fstat */
.quad sys_pause
.quad sys32_utime /* 30 */
.quad compat_sys_utime /* 30 */
.quad ni_syscall /* old stty syscall holder */
.quad ni_syscall /* old gtty syscall holder */
.quad sys_access
......@@ -164,7 +226,7 @@ ia32_sys_call_table:
.quad sys_rmdir /* 40 */
.quad sys_dup
.quad sys32_pipe
.quad sys32_times
.quad compat_sys_times
.quad ni_syscall /* old prof syscall holder */
.quad sys_brk /* 45 */
.quad sys_setgid16
......@@ -225,11 +287,11 @@ ia32_sys_call_table:
.quad sys_ioperm
.quad sys32_socketcall
.quad sys_syslog
.quad sys32_setitimer
.quad sys32_getitimer /* 105 */
.quad sys32_newstat
.quad sys32_newlstat
.quad sys32_newfstat
.quad compat_sys_setitimer
.quad compat_sys_getitimer /* 105 */
.quad compat_sys_newstat
.quad compat_sys_newlstat
.quad compat_sys_newfstat
.quad sys32_uname
.quad stub32_iopl /* 110 */
.quad sys_vhangup
......@@ -283,7 +345,7 @@ ia32_sys_call_table:
.quad sys_sched_get_priority_max
.quad sys_sched_get_priority_min /* 160 */
.quad sys_sched_rr_get_interval
.quad sys32_nanosleep
.quad compat_sys_nanosleep
.quad sys_mremap
.quad sys_setresuid16
.quad sys_getresuid16 /* 165 */
......@@ -361,7 +423,7 @@ ia32_sys_call_table:
.quad sys_fremovexattr
.quad sys_tkill /* 238 */
.quad sys_sendfile64
.quad sys_futex /* 240 */
.quad sys32_futex /* 240 */
.quad sys32_sched_setaffinity
.quad sys32_sched_getaffinity
.quad sys_set_thread_area
......@@ -374,6 +436,14 @@ ia32_sys_call_table:
.quad sys_ni_syscall /* 250 alloc_huge_pages */
.quad sys_ni_syscall /* free_huge_pages */
.quad sys_exit_group /* exit_group */
.quad sys_lookup_dcookie
.quad sys_epoll_create
.quad sys_epoll_ctl
.quad sys_epoll_wait
.quad sys_remap_file_pages
.quad sys_set_tid_address
/* don't forget to change IA32_NR_syscalls */
ia32_syscall_end:
.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
.quad ni_syscall
......
......@@ -8,6 +8,7 @@
#include <linux/shm.h>
#include <linux/slab.h>
#include <linux/ipc.h>
#include <linux/compat.h>
#include <asm/mman.h>
#include <asm/types.h>
#include <asm/uaccess.h>
......@@ -29,10 +30,10 @@ struct msgbuf32 {
struct ipc_perm32 {
int key;
__kernel_uid_t32 uid;
__kernel_gid_t32 gid;
__kernel_uid_t32 cuid;
__kernel_gid_t32 cgid;
compat_uid_t uid;
compat_gid_t gid;
compat_uid_t cuid;
compat_gid_t cgid;
unsigned short mode;
unsigned short seq;
};
......@@ -53,8 +54,8 @@ struct ipc64_perm32 {
struct semid_ds32 {
struct ipc_perm32 sem_perm; /* permissions .. see ipc.h */
__kernel_time_t32 sem_otime; /* last semop time */
__kernel_time_t32 sem_ctime; /* last change time */
compat_time_t sem_otime; /* last semop time */
compat_time_t sem_ctime; /* last change time */
u32 sem_base; /* ptr to first semaphore in array */
u32 sem_pending; /* pending operations to be processed */
u32 sem_pending_last; /* last pending operation */
......@@ -64,9 +65,9 @@ struct semid_ds32 {
struct semid64_ds32 {
struct ipc64_perm32 sem_perm;
__kernel_time_t32 sem_otime;
compat_time_t sem_otime;
unsigned int __unused1;
__kernel_time_t32 sem_ctime;
compat_time_t sem_ctime;
unsigned int __unused2;
unsigned int sem_nsems;
unsigned int __unused3;
......@@ -77,9 +78,9 @@ struct msqid_ds32 {
struct ipc_perm32 msg_perm;
u32 msg_first;
u32 msg_last;
__kernel_time_t32 msg_stime;
__kernel_time_t32 msg_rtime;
__kernel_time_t32 msg_ctime;
compat_time_t msg_stime;
compat_time_t msg_rtime;
compat_time_t msg_ctime;
u32 wwait;
u32 rwait;
unsigned short msg_cbytes;
......@@ -91,17 +92,17 @@ struct msqid_ds32 {
struct msqid64_ds32 {
struct ipc64_perm32 msg_perm;
__kernel_time_t32 msg_stime;
compat_time_t msg_stime;
unsigned int __unused1;
__kernel_time_t32 msg_rtime;
compat_time_t msg_rtime;
unsigned int __unused2;
__kernel_time_t32 msg_ctime;
compat_time_t msg_ctime;
unsigned int __unused3;
unsigned int msg_cbytes;
unsigned int msg_qnum;
unsigned int msg_qbytes;
__kernel_pid_t32 msg_lspid;
__kernel_pid_t32 msg_lrpid;
compat_pid_t msg_lspid;
compat_pid_t msg_lrpid;
unsigned int __unused4;
unsigned int __unused5;
};
......@@ -109,9 +110,9 @@ struct msqid64_ds32 {
struct shmid_ds32 {
struct ipc_perm32 shm_perm;
int shm_segsz;
__kernel_time_t32 shm_atime;
__kernel_time_t32 shm_dtime;
__kernel_time_t32 shm_ctime;
compat_time_t shm_atime;
compat_time_t shm_dtime;
compat_time_t shm_ctime;
__kernel_ipc_pid_t32 shm_cpid;
__kernel_ipc_pid_t32 shm_lpid;
unsigned short shm_nattch;
......@@ -119,15 +120,15 @@ struct shmid_ds32 {
struct shmid64_ds32 {
struct ipc64_perm32 shm_perm;
__kernel_size_t32 shm_segsz;
__kernel_time_t32 shm_atime;
compat_size_t shm_segsz;
compat_time_t shm_atime;
unsigned int __unused1;
__kernel_time_t32 shm_dtime;
compat_time_t shm_dtime;
unsigned int __unused2;
__kernel_time_t32 shm_ctime;
compat_time_t shm_ctime;
unsigned int __unused3;
__kernel_pid_t32 shm_cpid;
__kernel_pid_t32 shm_lpid;
compat_pid_t shm_cpid;
compat_pid_t shm_lpid;
unsigned int shm_nattch;
unsigned int __unused4;
unsigned int __unused5;
......@@ -163,6 +164,7 @@ struct ipc_kludge {
#define SEMOP 1
#define SEMGET 2
#define SEMCTL 3
#define TIMEDSEMOP 4
#define MSGSND 11
#define MSGRCV 12
#define MSGGET 13
......@@ -622,7 +624,12 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
switch (call) {
case SEMOP:
/* struct sembuf is the same on 32 and 64bit :)) */
return sys_semop(first, (struct sembuf *)AA(ptr), second);
return sys_semtimedop(first, (struct sembuf *)AA(ptr), second,
NULL);
case TIMEDSEMOP:
/* struct sembuf is the same on 32 and 64bit :)) */
return sys_semtimedop(first, (struct sembuf *)AA(ptr), second,
(const struct timespec *)AA(fifth));
case SEMGET:
return sys_semget(first, second, third);
case SEMCTL:
......@@ -646,7 +653,6 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
return sys_shmget(first, second, third);
case SHMCTL:
return shmctl32(first, second, (void *)AA(ptr));
default:
return -EINVAL;
}
......
......@@ -19,6 +19,7 @@
#include <linux/icmpv6.h>
#include <linux/socket.h>
#include <linux/filter.h>
#include <linux/compat.h>
#include <net/scm.h>
#include <net/sock.h>
......@@ -29,6 +30,9 @@
#define A(__x) ((unsigned long)(__x))
#define AA(__x) ((unsigned long)(__x))
extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
void * optval, int *optlen);
static inline int iov_from_user32_to_kern(struct iovec *kiov,
struct iovec32 *uiov32,
......@@ -123,7 +127,7 @@ static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
{
struct cmsghdr32 *ucmsg;
struct cmsghdr *kcmsg, *kcmsg_base;
__kernel_size_t32 ucmlen;
compat_size_t ucmlen;
__kernel_size_t kcmlen, tmp;
kcmlen = 0;
......@@ -362,7 +366,7 @@ static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_up
kmsg->msg_control = (void *) orig_cmsg_uptr;
}
asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
asmlinkage long sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
{
struct socket *sock;
char address[MAX_SOCK_ADDR];
......@@ -407,7 +411,7 @@ asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_fl
return err;
}
asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
asmlinkage long sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
{
struct iovec iovstack[UIO_FASTIOV];
struct msghdr kern_msg;
......@@ -489,7 +493,7 @@ asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int use
err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
if(cmsg_ptr != 0 && err >= 0) {
unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
__kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr);
compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr);
err |= __put_user(uclen, &user_msg->msg_controllen);
}
if(err >= 0)
......@@ -575,12 +579,34 @@ static int do_set_icmpv6_filter(int fd, int level, int optname,
return ret;
}
asmlinkage int sys32_setsockopt(int fd, int level, int optname,
static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen)
{
struct compat_timeval *up = (struct compat_timeval *) optval;
struct timeval ktime;
mm_segment_t old_fs;
int err;
if (optlen < sizeof(*up))
return -EINVAL;
if (get_user(ktime.tv_sec, &up->tv_sec) ||
__get_user(ktime.tv_usec, &up->tv_usec))
return -EFAULT;
old_fs = get_fs();
set_fs(KERNEL_DS);
err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime));
set_fs(old_fs);
return err;
}
asmlinkage long sys32_setsockopt(int fd, int level, int optname,
char *optval, int optlen)
{
if (optname == SO_ATTACH_FILTER)
return do_set_attach_filter(fd, level, optname,
optval, optlen);
if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
return do_set_sock_timeout(fd, level, optname, optval, optlen);
if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
return do_set_icmpv6_filter(fd, level, optname,
optval, optlen);
......@@ -588,6 +614,39 @@ asmlinkage int sys32_setsockopt(int fd, int level, int optname,
return sys_setsockopt(fd, level, optname, optval, optlen);
}
static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
{
struct compat_timeval *up = (struct compat_timeval *) optval;
struct timeval ktime;
mm_segment_t old_fs;
int len, err;
if (get_user(len, optlen))
return -EFAULT;
if (len < sizeof(*up))
return -EINVAL;
len = sizeof(ktime);
old_fs = get_fs();
set_fs(KERNEL_DS);
err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
set_fs(old_fs);
if (!err) {
if (put_user(sizeof(*up), optlen) ||
put_user(ktime.tv_sec, &up->tv_sec) ||
__put_user(ktime.tv_usec, &up->tv_usec))
err = -EFAULT;
}
return err;
}
asmlinkage long sys32_getsockopt(int fd, int level, int optname,
char *optval, int *optlen)
{
if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
return do_get_sock_timeout(fd, level, optname, optval, optlen);
return sys_getsockopt(fd, level, optname, optval, optlen);
}
/* Argument list sizes for sys_socketcall */
#define AL(x) ((x) * sizeof(u32))
......@@ -606,14 +665,11 @@ extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr,
extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr,
int *usockaddr_len);
extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags);
extern asmlinkage long sys_sendto(int fd, u32 buff, __kernel_size_t32 len,
extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len,
unsigned flags, u32 addr, int addr_len);
extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags);
extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size,
extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size,
unsigned flags, u32 addr, u32 addr_len);
extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
u32 optval, u32 optlen);
extern asmlinkage long sys_socket(int family, int type, int protocol);
extern asmlinkage long sys_socketpair(int family, int type, int protocol,
int usockvec[2]);
......@@ -678,11 +734,11 @@ asmlinkage long sys32_socketcall(int call, u32 *args)
ret = sys_shutdown(a0,a1);
break;
case SYS_SETSOCKOPT:
ret = sys_setsockopt(a0, a1, a[2], (char *)A(a[3]),
ret = sys32_setsockopt(a0, a1, a[2], (char *)A(a[3]),
a[4]);
break;
case SYS_GETSOCKOPT:
ret = sys_getsockopt(a0, a1, a[2], a[3], a[4]);
ret = sys32_getsockopt(a0, a1, a[2], (char *)(u64)a[3], (int *)(u64)a[4]);
break;
case SYS_SENDMSG:
ret = sys32_sendmsg(a0, (struct msghdr32 *)A(a1),
......
This diff is collapsed.
......@@ -4,23 +4,30 @@
EXTRA_TARGETS := head.o head64.o init_task.o
export-objs := mtrr.o x8664_ksyms.o pci-gart.o pci-dma.o
export-objs := x8664_ksyms.o pci-gart.o pci-dma.o
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \
pci-dma.o x8664_ksyms.o i387.o syscall.o vsyscall.o \
setup64.o bluesmoke.o bootflag.o e820.o reboot.o profile.o
obj-$(CONFIG_MTRR) += mtrr.o
obj-$(CONFIG_MTRR) += mtrr/
obj-$(CONFIG_X86_MSR) += msr.o
obj-$(CONFIG_X86_CPUID) += cpuid.o
obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o suspend_asm.o
obj-$(CONFIG_ACPI) += acpi.o
#obj-$(CONFIG_ACPI_SLEEP) += acpi_wakeup.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o
obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o
obj-$(CONFIG_MODULES) += module.o
$(obj)/bootflag.c:
@ln -sf ../../i386/kernel/bootflag.c $(obj)/bootflag.c
clean-files += bootflag.c
EXTRA_AFLAGS := -traditional
......@@ -443,8 +443,6 @@ acpi_boot_init (
#error not ported to x86-64 yet
#define DEBUG
#ifdef DEBUG
#include <linux/serial.h>
#endif
......
/*
* Implement 'Simple Boot Flag Specification 1.0'
*
*/
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <asm/io.h>
#include <linux/mc146818rtc.h>
#define SBF_RESERVED (0x78)
#define SBF_PNPOS (1<<0)
#define SBF_BOOTING (1<<1)
#define SBF_DIAG (1<<2)
#define SBF_PARITY (1<<7)
struct sbf_boot
{
u8 sbf_signature[4];
u32 sbf_len;
u8 sbf_revision __attribute((packed));
u8 sbf_csum __attribute((packed));
u8 sbf_oemid[6] __attribute((packed));
u8 sbf_oemtable[8] __attribute((packed));
u8 sbf_revdata[4] __attribute((packed));
u8 sbf_creator[4] __attribute((packed));
u8 sbf_crearev[4] __attribute((packed));
u8 sbf_cmos __attribute((packed));
u8 sbf_spare[3] __attribute((packed));
};
static int sbf_port __initdata = -1;
static int __init sbf_struct_valid(unsigned long tptr)
{
u8 *ap;
u8 v;
unsigned int i;
struct sbf_boot sb;
memcpy_fromio(&sb, (void *)tptr, sizeof(sb));
if(sb.sbf_len != 40 && sb.sbf_len != 39)
// 39 on IBM ThinkPad A21m, BIOS version 1.02b (KXET24WW; 2000-12-19).
return 0;
ap = (u8 *)&sb;
v= 0;
for(i=0;i<sb.sbf_len;i++)
v+=*ap++;
if(v)
return 0;
if(memcmp(sb.sbf_signature, "BOOT", 4))
return 0;
if (sb.sbf_len == 39)
printk (KERN_WARNING "SBF: ACPI BOOT descriptor is wrong length (%d)\n",
sb.sbf_len);
sbf_port = sb.sbf_cmos; /* Save CMOS port */
return 1;
}
static int __init parity(u8 v)
{
int x = 0;
int i;
for(i=0;i<8;i++)
{
x^=(v&1);
v>>=1;
}
return x;
}
static void __init sbf_write(u8 v)
{
unsigned long flags;
if(sbf_port != -1)
{
v &= ~SBF_PARITY;
if(!parity(v))
v|=SBF_PARITY;
printk(KERN_INFO "SBF: Setting boot flags 0x%x\n",v);
spin_lock_irqsave(&rtc_lock, flags);
CMOS_WRITE(v, sbf_port);
spin_unlock_irqrestore(&rtc_lock, flags);
}
}
static u8 __init sbf_read(void)
{
u8 v;
unsigned long flags;
if(sbf_port == -1)
return 0;
spin_lock_irqsave(&rtc_lock, flags);
v = CMOS_READ(sbf_port);
spin_unlock_irqrestore(&rtc_lock, flags);
return v;
}
static int __init sbf_value_valid(u8 v)
{
if(v&SBF_RESERVED) /* Reserved bits */
return 0;
if(!parity(v))
return 0;
return 1;
}
static void __init sbf_bootup(void)
{
u8 v;
if(sbf_port == -1)
return;
v = sbf_read();
if(!sbf_value_valid(v))
printk(KERN_WARNING "SBF: Simple boot flag value 0x%x read from CMOS RAM was invalid\n",v);
v &= ~SBF_RESERVED;
v &= ~SBF_BOOTING;
v &= ~SBF_DIAG;
#if defined(CONFIG_ISAPNP)
v |= SBF_PNPOS;
#endif
sbf_write(v);
}
static int __init sbf_init(void)
{
unsigned int i;
void *rsdt;
u32 rsdtlen = 0;
u32 rsdtbase = 0;
u8 sum = 0;
int n;
u8 *p;
for(i=0xE0000; i <= 0xFFFE0; i+=16)
{
p = phys_to_virt(i);
if(memcmp(p, "RSD PTR ", 8))
continue;
sum = 0;
for(n=0; n<20; n++)
sum+=p[n];
if(sum != 0)
continue;
/* So it says RSD PTR and it checksums... */
/*
* Process the RDSP pointer
*/
rsdtbase = *(u32 *)(p+16);
/*
* RSDT length is ACPI 2 only, for ACPI 1 we must map
* and remap.
*/
if(p[15]>1)
rsdtlen = *(u32 *)(p+20);
else
rsdtlen = 36;
if(rsdtlen < 36 || rsdtlen > 1024)
continue;
break;
}
if(i>0xFFFE0)
return 0;
rsdt = ioremap(rsdtbase, rsdtlen);
if(rsdt == 0)
return 0;
i = readl(rsdt + 4);
/*
* Remap if needed
*/
if(i > rsdtlen)
{
rsdtlen = i;
iounmap(rsdt);
rsdt = ioremap(rsdtbase, rsdtlen);
if(rsdt == 0)
return 0;
}
for(n = 0; n < i; n++)
sum += readb(rsdt + n);
if(sum)
{
iounmap(rsdt);
return 0;
}
/* Ok the RSDT checksums too */
for(n = 36; n+3 < i; n += 4)
{
unsigned long rp = readl(rsdt+n);
int len = 4096;
if(rp > 0xFFFFFFFFUL - len)
len = 0xFFFFFFFFUL - rp;
/* Too close to the end!! */
if(len < 20)
continue;
rp = (unsigned long)ioremap(rp, 4096);
if(rp == 0)
continue;
if(sbf_struct_valid(rp))
{
/* Found the BOOT table and processed it */
printk(KERN_INFO "SBF: Simple Boot Flag extension found and enabled.\n");
}
iounmap((void *)rp);
}
iounmap(rsdt);
sbf_bootup();
return 0;
}
module_init(sbf_init);
......@@ -605,6 +605,9 @@ ENTRY(kernel_thread)
movq $-1, %rsi
movq %rsp, %rdx
xorl %r8d,%r8d
xorl %r9d,%r9d
# clone now
call do_fork
......
......@@ -79,13 +79,11 @@ startup_32:
/* Enable System Call */
btsl $_EFER_SCE, %eax
#if 0
/* No Execute supported? */
btl $20,%edi
jnc 1f
btsl $_EFER_NX, %eax
1:
#endif
/* Make changes effective */
wrmsr
......
......@@ -127,3 +127,24 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu )
memcpy(fpu, &tsk->thread.i387.fxsave, sizeof(struct user_i387_struct));
return 1;
}
int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu)
{
int fpvalid = tsk->used_math;
if (fpvalid) {
if (tsk == current)
unlazy_fpu(tsk);
memcpy(fpu, &tsk->thread.i387.fxsave, sizeof(struct user_i387_struct));
}
return fpvalid;
}
#ifdef CONFIG_SMP
void dump_smp_unlazy_fpu(void)
{
unlazy_fpu(current);
return;
}
#endif
......@@ -404,6 +404,45 @@ void reschedule_interrupt(void);
void call_function_interrupt(void);
void invalidate_interrupt(void);
static void setup_timer(void)
{
outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
udelay(10);
outb_p(LATCH & 0xff , 0x40); /* LSB */
udelay(10);
outb(LATCH >> 8 , 0x40); /* MSB */
}
static int timer_resume(struct device *dev, u32 level)
{
if (level == RESUME_POWER_ON)
setup_timer();
return 0;
}
static struct device_driver timer_driver = {
.name = "timer",
.bus = &system_bus_type,
.resume = timer_resume,
};
static struct sys_device device_timer = {
.name = "timer",
.id = 0,
.dev = {
.name = "timer",
.driver = &timer_driver,
},
};
static int __init init_timer_devicefs(void)
{
driver_register(&timer_driver);
return sys_device_register(&device_timer);
}
device_initcall(init_timer_devicefs);
void __init init_IRQ(void)
{
int i;
......@@ -454,9 +493,7 @@ void __init init_IRQ(void)
* Set the clock to HZ Hz, we already have a valid
* vector now:
*/
outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
outb_p(LATCH & 0xff , 0x40); /* LSB */
outb(LATCH >> 8 , 0x40); /* MSB */
setup_timer();
setup_irq(2, &irq2);
}
......@@ -35,6 +35,8 @@
#include <asm/smp.h>
#include <asm/desc.h>
int sis_apic_bug; /* not actually supported, dummy for compile */
#undef APIC_LOCKUP_DEBUG
#define APIC_LOCKUP_DEBUG
......
......@@ -108,13 +108,12 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
}
/*
* No need to lock the MM as we are the last user
*
* Don't touch the LDT register - we're already in the next thread.
*/
void release_segments(struct mm_struct *mm)
void destroy_context(struct mm_struct *mm)
{
if (mm->context.size) {
if (mm == current->active_mm)
clear_LDT();
if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE)
vfree(mm->context.ldt);
else
......@@ -188,11 +187,6 @@ static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
goto out;
}
me->thread.fsindex = 0;
me->thread.gsindex = 0;
me->thread.gs = 0;
me->thread.fs = 0;
down(&mm->context.sem);
if (ldt_info.entry_number >= mm->context.size) {
error = alloc_ldt(&current->mm->context, ldt_info.entry_number+1, 1);
......
/* Kernel module help for x86-64
Copyright (C) 2001 Rusty Russell.
Copyright (C) 2002 Andi Kleen, SuSE Labs.
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.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/moduleloader.h>
#include <linux/elf.h>
#include <linux/vmalloc.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/kernel.h>
#define DEBUGP(fmt...)
/* We don't need anything special. */
long module_core_size(const Elf64_Ehdr *hdr,
const Elf64_Shdr *sechdrs,
const char *secstrings,
struct module *module)
{
return module->core_size;
}
long module_init_size(const Elf64_Ehdr *hdr,
const Elf64_Shdr *sechdrs,
const char *secstrings,
struct module *module)
{
return module->init_size;
}
int apply_relocate_add(Elf64_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *me)
{
unsigned int i;
Elf64_Rela *rel = (void *)sechdrs[relsec].sh_offset;
Elf64_Sym *sym;
void *loc;
u64 val;
DEBUGP("Applying relocate section %u to %u\n", relsec,
sechdrs[relsec].sh_info);
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
/* This is where to make the change */
loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset
+ rel[i].r_offset;
/* This is the symbol it is referring to */
sym = (Elf64_Sym *)sechdrs[symindex].sh_offset
+ ELF64_R_SYM(rel[i].r_info);
if (!sym->st_value) {
printk(KERN_WARNING "%s: Unknown symbol %s\n",
me->name, strtab + sym->st_name);
return -ENOENT;
}
DEBUGP("type %d st_value %Lx r_addend %Lx loc %Lx\n",
(int)ELF64_R_TYPE(rel[i].r_info),
sym->st_value, rel[i].r_addend, (u64)loc);
val = sym->st_value + rel[i].r_addend;
switch (ELF64_R_TYPE(rel[i].r_info)) {
case R_X86_64_NONE:
break;
case R_X86_64_64:
*(u64 *)loc = val;
break;
case R_X86_64_32:
*(u32 *)loc = val;
if (val != *(u32 *)loc)
goto overflow;
break;
case R_X86_64_32S:
*(s32 *)loc = val;
if ((s64)val != *(s32 *)loc)
goto overflow;
break;
case R_X86_64_PC32:
val -= (u64)loc;
*(u32 *)loc = val;
#if 0
if ((s64)val != *(s32 *)loc)
goto overflow;
#endif
break;
default:
printk(KERN_ERR "module %s: Unknown rela relocation: %Lu\n",
me->name, ELF64_R_TYPE(rel[i].r_info));
return -ENOEXEC;
}
}
return 0;
overflow:
printk(KERN_ERR "overflow in relocation type %d val %Lx\n",
(int)ELF64_R_TYPE(rel[i].r_info), val);
printk(KERN_ERR "`%s' likely not compiled with -mcmodel=kernel\n",
me->name);
return -ENOEXEC;
}
int apply_relocate(Elf_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *me)
{
printk("non add relocation not supported\n");
return -ENOSYS;
}
int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
{
return 0;
}
This diff is collapsed.
#
# Reuse the i386 MTRR driver.
#
obj-y := main.o if.o generic.o state.o
obj-y += amd.o
obj-y += cyrix.o
obj-y += centaur.o
export-objs := main.o
$(obj)/main.c: $(obj)/mtrr.h
@ln -sf ../../../i386/kernel/cpu/mtrr/main.c $(obj)/main.c
$(obj)/if.c: $(obj)/mtrr.h
@ln -sf ../../../i386/kernel/cpu/mtrr/if.c $(obj)/if.c
$(obj)/generic.c: $(obj)/mtrr.h
@ln -sf ../../../i386/kernel/cpu/mtrr/generic.c $(obj)/generic.c
$(obj)/state.c: $(obj)/mtrr.h
@ln -sf ../../../i386/kernel/cpu/mtrr/state.c $(obj)/state.c
$(obj)/amd.c: $(obj)/mtrr.h
@ln -sf ../../../i386/kernel/cpu/mtrr/amd.c $(obj)/amd.c
$(obj)/cyrix.c: $(obj)/mtrr.h
@ln -sf ../../../i386/kernel/cpu/mtrr/cyrix.c $(obj)/cyrix.c
$(obj)/centaur.c: $(obj)/mtrr.h
@ln -sf ../../../i386/kernel/cpu/mtrr/centaur.c $(obj)/centaur.c
$(obj)/mtrr.h:
@ln -sf ../../../i386/kernel/cpu/mtrr/mtrr.h $(obj)/mtrr.h
clean-files += main.c if.c generic.c state.c amd.c cyrix.c centaur.c mtrr.h
......@@ -300,12 +300,18 @@ static nmi_callback_t nmi_callback = dummy_nmi_callback;
asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
{
int cpu = smp_processor_id();
int cpu;
nmi_enter();
cpu = smp_processor_id();
add_pda(__nmi_count,1);
if (!nmi_callback(regs, cpu))
default_do_nmi(regs);
nmi_exit();
}
void set_nmi_callback(nmi_callback_t callback)
......
......@@ -245,7 +245,7 @@ static void iommu_full(struct pci_dev *dev, void *addr, size_t size, int dir)
printk(KERN_ERR
"PCI-DMA: Error: ran out out IOMMU space for %p size %lu at device %s[%s]\n",
addr,size, dev ? dev->name : "?", dev ? dev->slot_name : "?");
addr,size, dev ? dev->dev.name : "?", dev ? dev->slot_name : "?");
if (size > PAGE_SIZE*EMERGENCY_PAGES) {
if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
......@@ -286,7 +286,7 @@ dma_addr_t pci_map_single(struct pci_dev *dev, void *addr, size_t size,int dir)
if (!need_iommu(dev, phys_mem, size))
return phys_mem;
npages = round_up(size, PAGE_SIZE) >> PAGE_SHIFT;
npages = round_up(size + ((u64)addr & ~PAGE_MASK), PAGE_SIZE) >> PAGE_SHIFT;
iommu_page = alloc_iommu(npages);
if (iommu_page == -1) {
......@@ -328,7 +328,7 @@ void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
dma_addr > iommu_bus_base + iommu_size)
return;
iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT;
npages = round_up(size, PAGE_SIZE) >> PAGE_SHIFT;
npages = round_up(size + (dma_addr & ~PAGE_MASK), PAGE_SIZE) >> PAGE_SHIFT;
for (i = 0; i < npages; i++) {
iommu_gatt_base[iommu_page + i] = 0;
#ifdef CONFIG_IOMMU_LEAK
......
This diff is collapsed.
/*
* linux/arch/i386/kernel/profile.c
* linux/arch/x86_64/kernel/profile.c
*
* (C) 2002 John Levon <levon@movementarian.org>
*
......
......@@ -41,6 +41,23 @@ struct desc_ptr idt_descr = { 256 * 16, (unsigned long) idt_table };
char boot_cpu_stack[IRQSTACKSIZE] __cacheline_aligned;
unsigned long __supported_pte_mask = ~0UL;
static int do_not_nx = 0;
static int __init nonx_setup(char *str)
{
if (!strncmp(str,"off",3)) {
__supported_pte_mask &= ~_PAGE_NX;
do_not_nx = 1;
} else if (!strncmp(str, "on",3)) {
do_not_nx = 0;
__supported_pte_mask |= _PAGE_NX;
}
return 1;
}
__setup("noexec=", nonx_setup);
#ifndef __GENERIC_PER_CPU
unsigned long __per_cpu_offset[NR_CPUS];
......@@ -127,7 +144,7 @@ void __init cpu_init (void)
int cpu = smp_processor_id();
#endif
struct tss_struct * t = &init_tss[cpu];
unsigned long v;
unsigned long v, efer;
char *estacks;
struct task_struct *me;
......@@ -189,6 +206,11 @@ void __init cpu_init (void)
wrmsrl(MSR_KERNEL_GS_BASE, 0);
barrier();
rdmsrl(MSR_EFER, efer);
if (!(efer & EFER_NX) || do_not_nx) {
__supported_pte_mask &= ~_PAGE_NX;
}
/*
* set up and load the per-CPU TSS
*/
......
This diff is collapsed.
......@@ -18,11 +18,11 @@
#include <linux/smp.h>
#include <linux/kernel_stat.h>
#include <linux/mc146818rtc.h>
#include <linux/interrupt.h>
#include <asm/mtrr.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/hardirq.h>
/*
* the following functions deal with sending IPIs between CPUs.
......
......@@ -323,12 +323,6 @@ void __init smp_callin(void)
local_irq_enable();
#ifdef CONFIG_MTRR
/*
* Must be done before calibration delay is computed
*/
mtrr_init_cpu (cpuid);
#endif
/*
* Get our bogomips.
*/
......@@ -344,6 +338,8 @@ void __init smp_callin(void)
notify_die(DIE_CPUINIT, "cpuinit", NULL, 0);
local_irq_disable();
/*
* Allow the master to continue.
*/
......@@ -436,7 +432,7 @@ static struct task_struct * __init fork_by_hand(void)
* don't care about the rip and regs settings since
* we'll never reschedule the forked task.
*/
return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL);
return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
}
#if APIC_DEBUG
......@@ -969,12 +965,17 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
int __devinit __cpu_up(unsigned int cpu)
{
/* This only works at boot for x86. See "rewrite" above. */
if (test_bit(cpu, &smp_commenced_mask))
if (test_bit(cpu, &smp_commenced_mask)) {
local_irq_enable();
return -ENOSYS;
}
/* In case one didn't come up */
if (!test_bit(cpu, &cpu_callin_map))
if (!test_bit(cpu, &cpu_callin_map)) {
local_irq_enable();
return -EIO;
}
local_irq_enable();
/* Unleash the CPU! */
Dprintk("waiting for cpu %d\n", cpu);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -2,7 +2,6 @@
#include <linux/module.h>
#include <linux/smp.h>
#include <linux/user.h>
#include <linux/mca.h>
#include <linux/sched.h>
#include <linux/in6.h>
#include <linux/interrupt.h>
......@@ -46,7 +45,7 @@ extern unsigned long get_cmos_time(void);
/* platform dependent support */
EXPORT_SYMBOL(boot_cpu_data);
EXPORT_SYMBOL(dump_fpu);
//EXPORT_SYMBOL(dump_fpu);
EXPORT_SYMBOL(__ioremap);
EXPORT_SYMBOL(ioremap_nocache);
EXPORT_SYMBOL(iounmap);
......@@ -120,10 +119,6 @@ EXPORT_SYMBOL(smp_call_function);
#endif
#ifdef CONFIG_MCA
EXPORT_SYMBOL(machine_id);
#endif
#ifdef CONFIG_VT
EXPORT_SYMBOL(screen_info);
#endif
......@@ -199,3 +194,6 @@ void out_of_line_bug(void);
EXPORT_SYMBOL(out_of_line_bug);
EXPORT_SYMBOL(init_level4_pgt);
extern unsigned long __supported_pte_mask;
EXPORT_SYMBOL(__supported_pte_mask);
......@@ -2,12 +2,12 @@
#include <asm/io.h>
#include <linux/module.h>
void *memcpy_toio(void *dst,void*src,unsigned len)
void *memcpy_toio(void *dst,const void*src,unsigned len)
{
return __inline_memcpy(__io_virt(dst),src,len);
}
void *memcpy_fromio(void *dst,void*src,unsigned len)
void *memcpy_fromio(void *dst,const void*src,unsigned len)
{
return __inline_memcpy(dst,__io_virt(src),len);
}
......
......@@ -30,7 +30,7 @@ do { \
" jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
" .align 4\n" \
" .align 8\n" \
" .quad 0b,3b\n" \
".previous" \
: "=r"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1), \
......
......@@ -5,3 +5,4 @@
export-objs := pageattr.o
obj-y := init.o fault.o ioremap.o extable.o modutil.o pageattr.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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