Commit cf34d923 authored by Andi Kleen's avatar Andi Kleen Committed by Christoph Hellwig

[PATCH] x86_64 update

x86-64 updates for 2.5.58. Changes only x86-64 specific files.

 - Rewrote module allocation. Lots of bugs fixed. Module loading
   should work now again.
 - Kconfig help fixes from Randy Dunlap
 - Makefile cleanups from Pavel Machek and Sam Ravnborg
 - Assembly cleanups from Pavel
 - defconfig update
 - Better strlen_user/strnlen_user
 - Merge with i386: new ptrace commands, 32bit vsyscall signal trampolines
		new deactivate_mm, add asm/bug.h
 - Make sure initramfs is freed after booting (thanks to Kai for the hint)
 - User per cpu data for profile counters (Ravikiran Thirumalai)
 - 32bit compat_* updates from Stephen Rothwell
 - Fix race in context switch. The exception handler for bogus segment
   loads in __switch_to needs to keep interrupts disabled, otherwise an
   interrupt can deadlock on scheduler locks.  Also make sure they don't
   printk or set oops_in_progress during printk because printk does a
   wake_up too.
 - Disable 64bit GS base changes for processes.  I cannot get it to work
   reliably.
 - Clear IOPL on kernel entry
parent 188db2b9
This diff is collapsed.
...@@ -54,35 +54,31 @@ libs-y += arch/x86_64/lib/ ...@@ -54,35 +54,31 @@ libs-y += arch/x86_64/lib/
core-y += arch/x86_64/kernel/ arch/x86_64/mm/ core-y += arch/x86_64/kernel/ arch/x86_64/mm/
core-$(CONFIG_IA32_EMULATION) += arch/x86_64/ia32/ core-$(CONFIG_IA32_EMULATION) += arch/x86_64/ia32/
drivers-$(CONFIG_PCI) += arch/x86_64/pci/ drivers-$(CONFIG_PCI) += arch/x86_64/pci/
# FIXME: is drivers- right ?
drivers-$(CONFIG_OPROFILE) += arch/x86_64/oprofile/ drivers-$(CONFIG_OPROFILE) += arch/x86_64/oprofile/
makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/x86_64/boot $(1) boot := arch/x86_64/boot
.PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install \ .PHONY: bzImage bzlilo bzdisk install archmrproper
clean archclean archmrproper
BOOTIMAGE=arch/x86_64/boot/bzImage #Default target when executing "make"
zImage zlilo zdisk: BOOTIMAGE=arch/x86_64/boot/zImage all: bzImage
zImage bzImage: vmlinux BOOTIMAGE := arch/x86_64/boot/bzImage
$(call makeboot,$(BOOTIMAGE))
compressed: zImage bzImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE)
zlilo bzlilo: vmlinux bzlilo: vmlinux
$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) zlilo) $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zlilo
zdisk bzdisk: vmlinux bzdisk: vmlinux
$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) zdisk) $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk
install: vmlinux install: vmlinux
$(call makeboot,BOOTIMAGE=$(BOOTIMAGE) install) $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
archclean: archclean:
$(Q)$(MAKE) $(clean)=arch/i386/boot $(Q)$(MAKE) $(clean)=$(boot)
archmrproper:
prepare: include/asm-$(ARCH)/offset.h prepare: include/asm-$(ARCH)/offset.h
...@@ -90,10 +86,10 @@ arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \ ...@@ -90,10 +86,10 @@ arch/$(ARCH)/kernel/asm-offsets.s: include/asm include/linux/version.h \
include/config/MARKER include/config/MARKER
include/asm-$(ARCH)/offset.h.tmp: arch/$(ARCH)/kernel/asm-offsets.s include/asm-$(ARCH)/offset.h.tmp: arch/$(ARCH)/kernel/asm-offsets.s
@$(generate-asm-offsets.h) < $< > $@
include/asm-$(ARCH)/offset.h: include/asm-$(ARCH)/offset.h.tmp include/asm-$(ARCH)/offset.h: arch/$(ARCH)/kernel/asm-offsets.s
@echo -n ' Generating $@' @echo -n ' Generating $@'
@$(generate-asm-offsets.h) < $< > $@.tmp
@$(update-if-changed) @$(update-if-changed)
CLEAN_FILES += include/asm-$(ARCH)/offset.h.tmp \ CLEAN_FILES += include/asm-$(ARCH)/offset.h.tmp \
......
...@@ -26,16 +26,14 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA ...@@ -26,16 +26,14 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
#RAMDISK := -DRAMDISK=512 #RAMDISK := -DRAMDISK=512
EXTRA_TARGETS := vmlinux.bin bootsect bootsect.o \ EXTRA_TARGETS := vmlinux.bin bootsect bootsect.o \
setup setup.o zImage bzImage setup setup.o bzImage
CFLAGS += -m32 EXTRA_CFLAGS := -m32
host-progs := tools/build host-progs := tools/build
subdir- := compressed #Let make clean descend in compressed/ subdir- := compressed/ #Let make clean descend in compressed/
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
$(obj)/zImage: IMAGE_OFFSET := 0x1000
$(obj)/zImage: EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK)
$(obj)/bzImage: IMAGE_OFFSET := 0x100000 $(obj)/bzImage: IMAGE_OFFSET := 0x100000
$(obj)/bzImage: EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ $(obj)/bzImage: EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__
$(obj)/bzImage: BUILDFLAGS := -b $(obj)/bzImage: BUILDFLAGS := -b
...@@ -44,7 +42,7 @@ quiet_cmd_image = BUILD $@ ...@@ -44,7 +42,7 @@ quiet_cmd_image = BUILD $@
cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \ cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
$(obj)/vmlinux.bin $(ROOT_DEV) > $@ $(obj)/vmlinux.bin $(ROOT_DEV) > $@
$(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \ $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
$(obj)/vmlinux.bin $(obj)/tools/build FORCE $(obj)/vmlinux.bin $(obj)/tools/build FORCE
$(call if_changed,image) $(call if_changed,image)
@echo 'Kernel: $@ is ready' @echo 'Kernel: $@ is ready'
......
...@@ -11,7 +11,7 @@ EXTRA_AFLAGS := -traditional -m32 ...@@ -11,7 +11,7 @@ EXTRA_AFLAGS := -traditional -m32
# cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with # cannot use EXTRA_CFLAGS because base CFLAGS contains -mkernel which conflicts with
# -m32 # -m32
CFLAGS := -m32 -D__KERNEL__ -I$(TOPDIR)/include -O2 CFLAGS := -m32 -D__KERNEL__ -Iinclude -O2
LDFLAGS := -m elf_i386 LDFLAGS := -m elf_i386
LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32 -m elf_i386 LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup_32 -m elf_i386
......
...@@ -19,10 +19,16 @@ CONFIG_EXPERIMENTAL=y ...@@ -19,10 +19,16 @@ CONFIG_EXPERIMENTAL=y
# #
# General setup # General setup
# #
CONFIG_NET=y
CONFIG_SYSVIPC=y CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y CONFIG_SYSCTL=y
# CONFIG_LOG_BUF_SHIFT_17 is not set
CONFIG_LOG_BUF_SHIFT_16=y
# CONFIG_LOG_BUF_SHIFT_15 is not set
# CONFIG_LOG_BUF_SHIFT_14 is not set
# CONFIG_LOG_BUF_SHIFT_13 is not set
# CONFIG_LOG_BUF_SHIFT_12 is not set
CONFIG_LOG_BUF_SHIFT=16
# #
# Loadable module support # Loadable module support
...@@ -85,6 +91,7 @@ CONFIG_ACPI_SYSTEM=y ...@@ -85,6 +91,7 @@ CONFIG_ACPI_SYSTEM=y
# #
CONFIG_PCI=y CONFIG_PCI=y
CONFIG_PCI_DIRECT=y CONFIG_PCI_DIRECT=y
# CONFIG_PCI_LEGACY_PROC is not set
# CONFIG_PCI_NAMES is not set # CONFIG_PCI_NAMES is not set
# CONFIG_HOTPLUG is not set # CONFIG_HOTPLUG is not set
...@@ -163,15 +170,14 @@ CONFIG_BLK_DEV_ADMA=y ...@@ -163,15 +170,14 @@ CONFIG_BLK_DEV_ADMA=y
# CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_ALI15X3 is not set
CONFIG_BLK_DEV_AMD74XX=y CONFIG_BLK_DEV_AMD74XX=y
# CONFIG_AMD74XX_OVERRIDE is not set
# CONFIG_BLK_DEV_CMD64X is not set # CONFIG_BLK_DEV_CMD64X is not set
# CONFIG_BLK_DEV_TRIFLEX is not set
# CONFIG_BLK_DEV_CY82C693 is not set # CONFIG_BLK_DEV_CY82C693 is not set
# CONFIG_BLK_DEV_CS5520 is not set # CONFIG_BLK_DEV_CS5520 is not set
# CONFIG_BLK_DEV_HPT34X is not set # CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set # CONFIG_BLK_DEV_HPT366 is not set
# CONFIG_BLK_DEV_SC1200 is not set # CONFIG_BLK_DEV_SC1200 is not set
# CONFIG_BLK_DEV_PIIX is not set # CONFIG_BLK_DEV_PIIX is not set
# CONFIG_BLK_DEV_NFORCE is not set
# CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_OPTI621 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set
...@@ -211,6 +217,11 @@ CONFIG_BLK_DEV_IDE_MODES=y ...@@ -211,6 +217,11 @@ CONFIG_BLK_DEV_IDE_MODES=y
# #
# CONFIG_IEEE1394 is not set # CONFIG_IEEE1394 is not set
#
# Networking support
#
CONFIG_NET=y
# #
# Networking options # Networking options
# #
...@@ -263,10 +274,6 @@ CONFIG_IPV6_SCTP__=y ...@@ -263,10 +274,6 @@ CONFIG_IPV6_SCTP__=y
# Network testing # Network testing
# #
# CONFIG_NET_PKTGEN is not set # CONFIG_NET_PKTGEN is not set
#
# Network device support
#
CONFIG_NETDEVICES=y CONFIG_NETDEVICES=y
# #
...@@ -286,8 +293,6 @@ CONFIG_NET_ETHERNET=y ...@@ -286,8 +293,6 @@ CONFIG_NET_ETHERNET=y
# CONFIG_HAPPYMEAL is not set # CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set # CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_VENDOR_3COM is not set
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
# #
# Tulip family network device support # Tulip family network device support
...@@ -296,6 +301,7 @@ CONFIG_NET_ETHERNET=y ...@@ -296,6 +301,7 @@ CONFIG_NET_ETHERNET=y
# CONFIG_HP100 is not set # CONFIG_HP100 is not set
CONFIG_NET_PCI=y CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set # CONFIG_PCNET32 is not set
CONFIG_AMD8111_ETH=y
# CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set # CONFIG_B44 is not set
# CONFIG_DGRS is not set # CONFIG_DGRS is not set
...@@ -315,7 +321,6 @@ CONFIG_8139TOO=m ...@@ -315,7 +321,6 @@ CONFIG_8139TOO=m
# CONFIG_SUNDANCE is not set # CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set # CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set # CONFIG_VIA_RHINE is not set
# CONFIG_NET_POCKET is not set
# #
# Ethernet (1000 Mbit) # Ethernet (1000 Mbit)
...@@ -343,7 +348,6 @@ CONFIG_TIGON3=y ...@@ -343,7 +348,6 @@ CONFIG_TIGON3=y
# #
# Token Ring devices (depends on LLC=y) # Token Ring devices (depends on LLC=y)
# #
# CONFIG_NET_FC is not set
# CONFIG_RCPCI is not set # CONFIG_RCPCI is not set
# CONFIG_SHAPER is not set # CONFIG_SHAPER is not set
...@@ -445,12 +449,25 @@ CONFIG_UNIX98_PTY_COUNT=256 ...@@ -445,12 +449,25 @@ CONFIG_UNIX98_PTY_COUNT=256
# #
# CONFIG_I2C is not set # CONFIG_I2C is not set
#
# I2C Hardware Sensors Mainboard support
#
#
# I2C Hardware Sensors Chip support
#
# #
# Mice # Mice
# #
# CONFIG_BUSMOUSE is not set # CONFIG_BUSMOUSE is not set
# CONFIG_QIC02_TAPE is not set # CONFIG_QIC02_TAPE is not set
#
# IPMI
#
# CONFIG_IPMI_HANDLER is not set
# #
# Watchdog Cards # Watchdog Cards
# #
...@@ -470,7 +487,6 @@ CONFIG_RTC=y ...@@ -470,7 +487,6 @@ CONFIG_RTC=y
# CONFIG_FTAPE is not set # CONFIG_FTAPE is not set
# CONFIG_AGP is not set # CONFIG_AGP is not set
# CONFIG_AGP_GART is not set # CONFIG_AGP_GART is not set
# CONFIG_AGP3 is not set
# CONFIG_DRM is not set # CONFIG_DRM is not set
# CONFIG_MWAVE is not set # CONFIG_MWAVE is not set
CONFIG_RAW_DRIVER=y CONFIG_RAW_DRIVER=y
...@@ -544,6 +560,7 @@ CONFIG_NFSD_V3=y ...@@ -544,6 +560,7 @@ CONFIG_NFSD_V3=y
# CONFIG_NFSD_V4 is not set # CONFIG_NFSD_V4 is not set
CONFIG_NFSD_TCP=y CONFIG_NFSD_TCP=y
CONFIG_SUNRPC=y CONFIG_SUNRPC=y
# CONFIG_SUNRPC_GSS is not set
CONFIG_LOCKD=y CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y CONFIG_LOCKD_V4=y
CONFIG_EXPORTFS=y CONFIG_EXPORTFS=y
......
...@@ -80,9 +80,9 @@ static inline int convert_fxsr_from_user(struct i387_fxsave_struct *fxsave, ...@@ -80,9 +80,9 @@ static inline int convert_fxsr_from_user(struct i387_fxsave_struct *fxsave,
int err; int err;
__u32 v; __u32 v;
err = __get_user(fxsave->cwd, (u16 *)&buf->cw); err = __get_user(fxsave->cwd, &buf->cw);
err |= __get_user(fxsave->swd, (u16 *)&buf->sw); err |= __get_user(fxsave->swd, &buf->sw);
err |= __get_user(fxsave->twd, (u16 *)&buf->tag); err |= __get_user(fxsave->twd, &buf->tag);
fxsave->twd = twd_i387_to_fxsr(fxsave->twd); fxsave->twd = twd_i387_to_fxsr(fxsave->twd);
err |= __get_user(fxsave->rip, &buf->ipoff); err |= __get_user(fxsave->rip, &buf->ipoff);
err |= __get_user(fxsave->rdp, &buf->dataoff); err |= __get_user(fxsave->rdp, &buf->dataoff);
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <asm/user32.h> #include <asm/user32.h>
#include <asm/sigcontext32.h> #include <asm/sigcontext32.h>
#include <asm/fpu32.h> #include <asm/fpu32.h>
#include <asm/proto.h>
#define ptr_to_u32(x) ((u32)(u64)(x)) /* avoid gcc warning */ #define ptr_to_u32(x) ((u32)(u64)(x)) /* avoid gcc warning */
...@@ -405,18 +406,30 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka, ...@@ -405,18 +406,30 @@ void ia32_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 /* Return stub is in 32bit vsyscall page */
already in userspace. */ {
if (ka->sa.sa_flags & SA_RESTORER) { void *restorer = syscall32_page + 32;
err |= __put_user((u32)(u64)ka->sa.sa_restorer, &frame->pretcode); if (ka->sa.sa_flags & SA_RESTORER)
} else { restorer = ka->sa.sa_restorer;
err |= __put_user((u32)(u64)frame->retcode, &frame->pretcode); err |= __put_user(ptr_to_u32(restorer), &frame->pretcode);
/* This is popl %eax ; movl $,%eax ; int $0x80 */ }
err |= __put_user((u16)0xb858, (short *)(frame->retcode+0)); /* These are actually not used anymore, but left because some
err |= __put_user((u32)__NR_ia32_sigreturn, (int *)(frame->retcode+2)); gdb versions depend on them as a marker. */
err |= __put_user((u16)0x80cd, (short *)(frame->retcode+6)); {
/* copy_to_user optimizes that into a single 8 byte store */
static const struct {
u16 poplmovl;
u32 val;
u16 int80;
u16 pad;
} __attribute__((packed)) code = {
0xb858, /* popl %eax ; movl $...,%eax */
__NR_ia32_sigreturn,
0x80cd, /* int $0x80 */
0,
};
err |= __copy_to_user(frame->retcode, &code, 8);
} }
if (err) if (err)
goto give_sigsegv; goto give_sigsegv;
...@@ -486,18 +499,33 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -486,18 +499,33 @@ void ia32_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
already in userspace. */ {
if (ka->sa.sa_flags & SA_RESTORER) { void *restorer = syscall32_page + 32;
err |= __put_user((u32)(u64)ka->sa.sa_restorer, &frame->pretcode); if (ka->sa.sa_flags & SA_RESTORER)
} else { restorer = ka->sa.sa_restorer;
err |= __put_user(ptr_to_u32(frame->retcode), &frame->pretcode); err |= __put_user(ptr_to_u32(restorer), &frame->pretcode);
/* This is movl $,%eax ; int $0x80 */
err |= __put_user(0xb8, (char *)(frame->retcode+0));
err |= __put_user((u32)__NR_ia32_rt_sigreturn, (int *)(frame->retcode+1));
err |= __put_user(0x80cd, (short *)(frame->retcode+5));
} }
/* This is movl $,%eax ; int $0x80 */
/* Not actually used anymore, but left because some gdb versions
need it. */
{
/* __copy_to_user optimizes that into a single 8 byte store */
static const struct {
u8 movl;
u32 val;
u16 int80;
u16 pad;
u8 pad2;
} __attribute__((packed)) code = {
0xb8,
__NR_ia32_rt_sigreturn,
0x80cd,
0,
};
err |= __copy_to_user(frame->retcode, &code, 8);
}
if (err) if (err)
goto give_sigsegv; goto give_sigsegv;
......
...@@ -248,7 +248,7 @@ ia32_sys_call_table: ...@@ -248,7 +248,7 @@ ia32_sys_call_table:
.quad sys_brk /* 45 */ .quad sys_brk /* 45 */
.quad sys_setgid16 .quad sys_setgid16
.quad sys_getgid16 .quad sys_getgid16
.quad ni_syscall /* signal */ .quad sys_signal
.quad sys_geteuid16 .quad sys_geteuid16
.quad sys_getegid16 /* 50 */ .quad sys_getegid16 /* 50 */
.quad sys_acct .quad sys_acct
...@@ -299,8 +299,8 @@ ia32_sys_call_table: ...@@ -299,8 +299,8 @@ ia32_sys_call_table:
.quad sys_getpriority .quad sys_getpriority
.quad sys_setpriority .quad sys_setpriority
.quad ni_syscall /* old profil syscall holder */ .quad ni_syscall /* old profil syscall holder */
.quad sys32_statfs .quad compat_sys_statfs
.quad sys32_fstatfs /* 100 */ .quad compat_sys_fstatfs /* 100 */
.quad sys_ioperm .quad sys_ioperm
.quad sys32_socketcall .quad sys32_socketcall
.quad sys_syslog .quad sys_syslog
......
...@@ -404,58 +404,6 @@ sys32_rt_sigprocmask(int how, sigset32_t *set, sigset32_t *oset, ...@@ -404,58 +404,6 @@ sys32_rt_sigprocmask(int how, sigset32_t *set, sigset32_t *oset,
return 0; return 0;
} }
static int
put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
{
if (verify_area(VERIFY_WRITE, ubuf, sizeof(struct statfs32)) ||
__put_user (kbuf->f_type, &ubuf->f_type) ||
__put_user (kbuf->f_bsize, &ubuf->f_bsize) ||
__put_user (kbuf->f_blocks, &ubuf->f_blocks) ||
__put_user (kbuf->f_bfree, &ubuf->f_bfree) ||
__put_user (kbuf->f_bavail, &ubuf->f_bavail) ||
__put_user (kbuf->f_files, &ubuf->f_files) ||
__put_user (kbuf->f_ffree, &ubuf->f_ffree) ||
__put_user (kbuf->f_namelen, &ubuf->f_namelen) ||
__put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
__put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]))
return -EFAULT;
return 0;
}
extern asmlinkage long sys_statfs(const char * path, struct statfs * buf);
asmlinkage long
sys32_statfs(const char * path, struct statfs32 *buf)
{
int ret;
struct statfs s;
mm_segment_t old_fs = get_fs();
set_fs (KERNEL_DS);
ret = sys_statfs((const char *)path, &s);
set_fs (old_fs);
if (put_statfs(buf, &s))
return -EFAULT;
return ret;
}
extern asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf);
asmlinkage long
sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
{
int ret;
struct statfs s;
mm_segment_t old_fs = get_fs();
set_fs (KERNEL_DS);
ret = sys_fstatfs(fd, &s);
set_fs (old_fs);
if (put_statfs(buf, &s))
return -EFAULT;
return ret;
}
static inline long static inline long
get_tv32(struct timeval *o, struct compat_timeval *i) get_tv32(struct timeval *o, struct compat_timeval *i)
{ {
......
/* Copyright 2002 Andi Kleen, SuSE Labs */ /* Copyright 2002,2003 Andi Kleen, SuSE Labs */
/* vsyscall handling for 32bit processes. Map a stub page into it /* vsyscall handling for 32bit processes. Map a stub page into it
on demand because 32bit cannot reach the kernel's fixmaps */ on demand because 32bit cannot reach the kernel's fixmaps */
...@@ -8,8 +8,10 @@ ...@@ -8,8 +8,10 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/stringify.h>
#include <asm/proto.h> #include <asm/proto.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/ia32_unistd.h>
/* 32bit SYSCALL stub mapped into user space. */ /* 32bit SYSCALL stub mapped into user space. */
asm(" .code32\n" asm(" .code32\n"
...@@ -20,11 +22,26 @@ asm(" .code32\n" ...@@ -20,11 +22,26 @@ asm(" .code32\n"
" popl %ebp\n" " popl %ebp\n"
" ret\n" " ret\n"
"syscall32_end:\n" "syscall32_end:\n"
/* signal trampolines */
"sig32_rt_tramp:\n"
" movl $" __stringify(__NR_ia32_rt_sigreturn) ",%eax\n"
" int $0x80\n"
"sig32_rt_tramp_end:\n"
"sig32_tramp:\n"
" popl %eax\n"
" movl $" __stringify(__NR_ia32_sigreturn) ",%eax\n"
" int $0x80\n"
"sig32_tramp_end:\n"
" .code64\n"); " .code64\n");
extern unsigned char syscall32[], syscall32_end[]; extern unsigned char syscall32[], syscall32_end[];
extern unsigned char sig32_rt_tramp[], sig32_rt_tramp_end[];
extern unsigned char sig32_tramp[], sig32_tramp_end[];
static unsigned long syscall32_page; char *syscall32_page;
/* RED-PEN: This knows too much about high level VM */ /* RED-PEN: This knows too much about high level VM */
/* Alternative would be to generate a vma with appropiate backing options /* Alternative would be to generate a vma with appropiate backing options
...@@ -54,11 +71,16 @@ int map_syscall32(struct mm_struct *mm, unsigned long address) ...@@ -54,11 +71,16 @@ int map_syscall32(struct mm_struct *mm, unsigned long address)
static int __init init_syscall32(void) static int __init init_syscall32(void)
{ {
syscall32_page = get_zeroed_page(GFP_KERNEL); syscall32_page = (void *)get_zeroed_page(GFP_KERNEL);
if (!syscall32_page) if (!syscall32_page)
panic("Cannot allocate syscall32 page"); panic("Cannot allocate syscall32 page");
SetPageReserved(virt_to_page(syscall32_page)); SetPageReserved(virt_to_page(syscall32_page));
memcpy((void *)syscall32_page, syscall32, syscall32_end - syscall32); memcpy(syscall32_page, syscall32, syscall32_end - syscall32);
memcpy(syscall32_page + 32, sig32_rt_tramp,
sig32_rt_tramp_end - sig32_rt_tramp);
memcpy(syscall32_page + 64, sig32_tramp,
sig32_tramp_end - sig32_tramp);
return 0;
} }
__initcall(init_syscall32); __initcall(init_syscall32);
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# #
EXTRA_TARGETS := head.o head64.o init_task.o EXTRA_TARGETS := head.o head64.o init_task.o
EXTRA_AFLAGS := -traditional
export-objs := 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 \ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
...@@ -32,4 +32,3 @@ $(obj)/bootflag.c: ...@@ -32,4 +32,3 @@ $(obj)/bootflag.c:
clean-files += bootflag.c clean-files += bootflag.c
EXTRA_AFLAGS := -traditional
...@@ -39,7 +39,7 @@ int dont_enable_local_apic __initdata = 0; ...@@ -39,7 +39,7 @@ int dont_enable_local_apic __initdata = 0;
int prof_multiplier[NR_CPUS] = { 1, }; int prof_multiplier[NR_CPUS] = { 1, };
int prof_old_multiplier[NR_CPUS] = { 1, }; int prof_old_multiplier[NR_CPUS] = { 1, };
int prof_counter[NR_CPUS] = { 1, }; DEFINE_PER_CPU(int, prof_counter) = 1;
int get_maxlvt(void) int get_maxlvt(void)
{ {
...@@ -901,7 +901,7 @@ inline void smp_local_timer_interrupt(struct pt_regs *regs) ...@@ -901,7 +901,7 @@ inline void smp_local_timer_interrupt(struct pt_regs *regs)
x86_do_profile(regs); x86_do_profile(regs);
if (--prof_counter[cpu] <= 0) { if (--per_cpu(prof_counter, cpu) <= 0) {
/* /*
* The multiplier may have changed since the last time we got * The multiplier may have changed since the last time we got
* to this point as a result of the user writing to * to this point as a result of the user writing to
...@@ -910,10 +910,11 @@ inline void smp_local_timer_interrupt(struct pt_regs *regs) ...@@ -910,10 +910,11 @@ inline void smp_local_timer_interrupt(struct pt_regs *regs)
* *
* Interrupts are already masked off at this point. * Interrupts are already masked off at this point.
*/ */
prof_counter[cpu] = prof_multiplier[cpu]; per_cpu(prof_counter, cpu) = prof_multiplier[cpu];
if (prof_counter[cpu] != prof_old_multiplier[cpu]) { if (per_cpu(prof_counter, cpu) != prof_old_multiplier[cpu]) {
__setup_APIC_LVTT(calibration_result/prof_counter[cpu]); __setup_APIC_LVTT(calibration_result/
prof_old_multiplier[cpu] = prof_counter[cpu]; per_cpu(prof_counter, cpu));
prof_old_multiplier[cpu] = per_cpu(prof_counter, cpu);
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
......
...@@ -532,8 +532,10 @@ error_swapgs: ...@@ -532,8 +532,10 @@ error_swapgs:
xorl %ebx,%ebx xorl %ebx,%ebx
swapgs swapgs
error_sti: error_sti:
bt $9,EFLAGS(%rsp)
jnc 1f
sti sti
movq %rdi,RDI(%rsp) 1: movq %rdi,RDI(%rsp)
movq %rsp,%rdi movq %rsp,%rdi
movq ORIG_RAX(%rsp),%rsi /* get error code */ movq ORIG_RAX(%rsp),%rsi /* get error code */
movq $-1,ORIG_RAX(%rsp) movq $-1,ORIG_RAX(%rsp)
......
...@@ -66,7 +66,7 @@ startup_32: ...@@ -66,7 +66,7 @@ startup_32:
movl %eax, %cr4 movl %eax, %cr4
/* Setup early boot stage 4 level pagetables */ /* Setup early boot stage 4 level pagetables */
movl $0x101000, %eax movl $(init_level4_pgt - __START_KERNEL_map), %eax
movl %eax, %cr3 movl %eax, %cr3
/* Setup EFER (Extended Feature Enable Register) */ /* Setup EFER (Extended Feature Enable Register) */
...@@ -89,20 +89,13 @@ startup_32: ...@@ -89,20 +89,13 @@ startup_32:
wrmsr wrmsr
xorl %eax, %eax xorl %eax, %eax
/* Enable paging and in turn activate Long Mode */ btsl $31, %eax /* Enable paging and in turn activate Long Mode */
btsl $31, %eax btsl $0, %eax /* Enable protected mode */
/* Enable protected mode */ btsl $1, %eax /* Enable MP */
btsl $0, %eax btsl $4, %eax /* Enable ET */
/* Enable MP */ btsl $5, %eax /* Enable NE */
btsl $1, %eax btsl $16, %eax /* Enable WP */
/* Enable ET */ btsl $18, %eax /* Enable AM */
btsl $4, %eax
/* Enable NE */
btsl $5, %eax
/* Enable WP */
btsl $16, %eax
/* Enable AM */
btsl $18, %eax
/* Make changes effective */ /* Make changes effective */
movl %eax, %cr0 movl %eax, %cr0
jmp reach_compatibility_mode jmp reach_compatibility_mode
...@@ -120,10 +113,10 @@ reach_compatibility_mode: ...@@ -120,10 +113,10 @@ reach_compatibility_mode:
/* Load new GDT with the 64bit segment using 32bit descriptor */ /* Load new GDT with the 64bit segment using 32bit descriptor */
/* to avoid 32bit relocations we use fixed adresses here */ /* to avoid 32bit relocations we use fixed adresses here */
movl $0x100F00, %eax movl $(pGDT32 - __START_KERNEL_map), %eax
lgdt (%eax) lgdt (%eax)
movl $0x100F10, %eax movl $(ljumpvector - __START_KERNEL_map), %eax
/* Finally jump in 64bit mode */ /* Finally jump in 64bit mode */
ljmp *(%eax) ljmp *(%eax)
...@@ -205,11 +198,11 @@ ENTRY(no_long_mode) ...@@ -205,11 +198,11 @@ ENTRY(no_long_mode)
.org 0xf00 .org 0xf00
pGDT32: pGDT32:
.word gdt32_end-gdt_table32 .word gdt32_end-gdt_table32
.long gdt_table32-__START_KERNEL+0x100000 .long gdt_table32-__START_KERNEL_map
.org 0xf10 .org 0xf10
ljumpvector: ljumpvector:
.long reach_long64-__START_KERNEL+0x100000 .long reach_long64-__START_KERNEL_map
.word __KERNEL_CS .word __KERNEL_CS
ENTRY(stext) ENTRY(stext)
......
/* Kernel module help for x86-64 /* Kernel module help for x86-64
Copyright (C) 2001 Rusty Russell. Copyright (C) 2001 Rusty Russell.
Copyright (C) 2002 Andi Kleen, SuSE Labs. Copyright (C) 2002,2003 Andi Kleen, SuSE Labs.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -22,9 +22,115 @@ ...@@ -22,9 +22,115 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <asm/system.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#define DEBUGP(fmt...) #define DEBUGP(fmt...)
void module_free(struct module *mod, void *module_region)
{
struct vm_struct **prevp, *map;
int i;
unsigned long addr = (unsigned long)module_region;
if (!addr)
return;
write_lock(&vmlist_lock);
for (prevp = &vmlist ; (map = *prevp) ; prevp = &map->next) {
if ((unsigned long)map->addr == addr) {
*prevp = map->next;
write_unlock(&vmlist_lock);
goto found;
}
}
write_unlock(&vmlist_lock);
printk("Trying to unmap nonexistent module vm area (%lx)\n", addr);
return;
found:
unmap_vm_area(map);
if (map->pages) {
for (i = 0; i < map->nr_pages; i++)
if (map->pages[i])
__free_page(map->pages[i]);
kfree(map->pages);
}
kfree(map);
}
void *module_alloc(unsigned long size)
{
struct vm_struct **p, *tmp, *area;
struct page **pages;
void *addr;
unsigned int nr_pages, array_size, i;
if (!size)
return NULL;
size = PAGE_ALIGN(size);
if (size > MODULES_LEN)
return NULL;
area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
if (!area)
return NULL;
memset(area, 0, sizeof(struct vm_struct));
write_lock(&vmlist_lock);
addr = (void *) MODULES_VADDR;
for (p = &vmlist; (tmp = *p); p = &tmp->next) {
void *next;
DEBUGP("vmlist %p %lu addr %p\n", tmp->addr, tmp->size, addr);
if (size + (unsigned long) addr + PAGE_SIZE < (unsigned long) tmp->addr)
break;
next = (void *) (tmp->size + (unsigned long) tmp->addr);
if (next > addr)
addr = next;
}
if ((unsigned long)addr + size >= MODULES_END) {
write_unlock(&vmlist_lock);
kfree(area);
return NULL;
}
DEBUGP("addr %p\n", addr);
area->next = *p;
*p = area;
area->size = size + PAGE_SIZE;
area->addr = addr;
write_unlock(&vmlist_lock);
nr_pages = size >> PAGE_SHIFT;
array_size = (nr_pages * sizeof(struct page *));
area->nr_pages = nr_pages;
area->pages = pages = kmalloc(array_size, GFP_KERNEL);
if (!area->pages)
goto fail;
memset(area->pages, 0, array_size);
for (i = 0; i < nr_pages; i++) {
area->pages[i] = alloc_page(GFP_KERNEL);
if (area->pages[i] == NULL)
goto fail;
}
if (map_vm_area(area, PAGE_KERNEL_EXECUTABLE, &pages))
goto fail;
memset(addr, 0, size);
DEBUGP("module_alloc size %lu = %p\n", size, addr);
return addr;
fail:
module_free(NULL, addr);
return NULL;
}
/* We don't need anything special. */ /* We don't need anything special. */
int module_frob_arch_sections(Elf_Ehdr *hdr, int module_frob_arch_sections(Elf_Ehdr *hdr,
Elf_Shdr *sechdrs, Elf_Shdr *sechdrs,
......
...@@ -537,6 +537,11 @@ int sys_arch_prctl(int code, unsigned long addr) ...@@ -537,6 +537,11 @@ int sys_arch_prctl(int code, unsigned long addr)
switch (code) { switch (code) {
case ARCH_SET_GS: case ARCH_SET_GS:
#if 1
/* For now. We still have one unsolved bug in long gs base context
switch handling. */
return -EINVAL;
#else
if (addr >= TASK_SIZE) if (addr >= TASK_SIZE)
return -EPERM; return -EPERM;
get_cpu(); get_cpu();
...@@ -546,6 +551,7 @@ int sys_arch_prctl(int code, unsigned long addr) ...@@ -546,6 +551,7 @@ int sys_arch_prctl(int code, unsigned long addr)
ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr);
put_cpu(); put_cpu();
break; break;
#endif
case ARCH_SET_FS: case ARCH_SET_FS:
/* Not strictly needed for fs, but do it for symmetry /* Not strictly needed for fs, but do it for symmetry
with gs */ with gs */
...@@ -594,15 +600,15 @@ static int get_free_idx(void) ...@@ -594,15 +600,15 @@ static int get_free_idx(void)
* Set a given TLS descriptor: * Set a given TLS descriptor:
* When you want addresses > 32bit use arch_prctl() * When you want addresses > 32bit use arch_prctl()
*/ */
asmlinkage int sys_set_thread_area(struct user_desc *u_info) int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info)
{ {
struct thread_struct *t = &current->thread;
struct user_desc info; struct user_desc info;
struct n_desc_struct *desc; struct n_desc_struct *desc;
int cpu, idx; int cpu, idx;
if (copy_from_user(&info, u_info, sizeof(info))) if (copy_from_user(&info, u_info, sizeof(info)))
return -EFAULT; return -EFAULT;
idx = info.entry_number; idx = info.entry_number;
/* /*
...@@ -634,12 +640,19 @@ asmlinkage int sys_set_thread_area(struct user_desc *u_info) ...@@ -634,12 +640,19 @@ asmlinkage int sys_set_thread_area(struct user_desc *u_info)
desc->a = LDT_entry_a(&info); desc->a = LDT_entry_a(&info);
desc->b = LDT_entry_b(&info); desc->b = LDT_entry_b(&info);
} }
if (t == &current->thread)
load_TLS(t, cpu); load_TLS(t, cpu);
put_cpu(); put_cpu();
return 0; return 0;
} }
asmlinkage int sys_set_thread_area(struct user_desc *u_info)
{
return do_set_thread_area(&current->thread, u_info);
}
/* /*
* Get the current Thread-Local Storage area: * Get the current Thread-Local Storage area:
*/ */
...@@ -661,7 +674,7 @@ asmlinkage int sys_set_thread_area(struct user_desc *u_info) ...@@ -661,7 +674,7 @@ asmlinkage int sys_set_thread_area(struct user_desc *u_info)
#define GET_USEABLE(desc) (((desc)->b >> 20) & 1) #define GET_USEABLE(desc) (((desc)->b >> 20) & 1)
#define GET_LONGMODE(desc) (((desc)->b >> 21) & 1) #define GET_LONGMODE(desc) (((desc)->b >> 21) & 1)
asmlinkage int sys_get_thread_area(struct user_desc *u_info) int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info)
{ {
struct user_desc info; struct user_desc info;
struct n_desc_struct *desc; struct n_desc_struct *desc;
...@@ -672,7 +685,7 @@ asmlinkage int sys_get_thread_area(struct user_desc *u_info) ...@@ -672,7 +685,7 @@ asmlinkage int sys_get_thread_area(struct user_desc *u_info)
if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
return -EINVAL; return -EINVAL;
desc = ((struct n_desc_struct *)current->thread.tls_array) + idx - GDT_ENTRY_TLS_MIN; desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN;
memset(&info, 0, sizeof(struct user_desc)); memset(&info, 0, sizeof(struct user_desc));
info.entry_number = idx; info.entry_number = idx;
...@@ -691,6 +704,11 @@ asmlinkage int sys_get_thread_area(struct user_desc *u_info) ...@@ -691,6 +704,11 @@ asmlinkage int sys_get_thread_area(struct user_desc *u_info)
return 0; return 0;
} }
asmlinkage int sys_get_thread_area(struct user_desc *u_info)
{
return do_get_thread_area(&current->thread, u_info);
}
/* /*
* Capture the user space registers if the task is not running (in user space) * Capture the user space registers if the task is not running (in user space)
*/ */
......
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/i387.h> #include <asm/i387.h>
#include <asm/debugreg.h> #include <asm/debugreg.h>
#include <asm/ldt.h>
#include <asm/desc.h>
#include <asm/proto.h>
/* /*
* does not yet catch signals sent when the child dies. * does not yet catch signals sent when the child dies.
...@@ -319,6 +322,22 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ...@@ -319,6 +322,22 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
wake_up_process(child); wake_up_process(child);
ret = 0; ret = 0;
break; break;
case PTRACE_SET_THREAD_AREA: {
int old;
get_user(old, &((struct user_desc *)data)->entry_number);
put_user(addr, &((struct user_desc *)data)->entry_number);
ret = do_set_thread_area(&child->thread,
(struct user_desc *)data);
put_user(old, &((struct user_desc *)data)->entry_number);
break;
case PTRACE_GET_THREAD_AREA:
get_user(old, &((struct user_desc *)data)->entry_number);
put_user(addr, &((struct user_desc *)data)->entry_number);
ret = do_get_thread_area(&child->thread,
(struct user_desc *)data);
put_user(old, &((struct user_desc *)data)->entry_number);
break;
}
} }
/* /*
......
...@@ -200,7 +200,7 @@ void __init cpu_init (void) ...@@ -200,7 +200,7 @@ void __init cpu_init (void)
#endif #endif
/* Flags to clear on syscall */ /* Flags to clear on syscall */
wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE); wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000);
wrmsrl(MSR_FS_BASE, 0); wrmsrl(MSR_FS_BASE, 0);
wrmsrl(MSR_KERNEL_GS_BASE, 0); wrmsrl(MSR_KERNEL_GS_BASE, 0);
......
...@@ -772,24 +772,16 @@ static void smp_tune_scheduling (void) ...@@ -772,24 +772,16 @@ static void smp_tune_scheduling (void)
* Cycle through the processors sending APIC IPIs to boot each. * Cycle through the processors sending APIC IPIs to boot each.
*/ */
extern int prof_multiplier[NR_CPUS];
extern int prof_old_multiplier[NR_CPUS];
extern int prof_counter[NR_CPUS];
static void __init smp_boot_cpus(unsigned int max_cpus) static void __init smp_boot_cpus(unsigned int max_cpus)
{ {
int apicid, cpu; int apicid, cpu;
/* /*
* Initialize the logical to physical CPU number mapping * Initialize the logical to physical CPU number mapping
* and the per-CPU profiling counter/multiplier
*/ */
for (apicid = 0; apicid < NR_CPUS; apicid++) { for (apicid = 0; apicid < NR_CPUS; apicid++) {
x86_apicid_to_cpu[apicid] = -1; x86_apicid_to_cpu[apicid] = -1;
prof_counter[apicid] = 1;
prof_old_multiplier[apicid] = 1;
prof_multiplier[apicid] = 1;
} }
/* /*
......
...@@ -450,16 +450,20 @@ asmlinkage void do_int3(struct pt_regs * regs, long error_code) ...@@ -450,16 +450,20 @@ 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
{ {
unsigned long gs; unsigned long gs;
struct x8664_pda *pda = cpu_pda + stack_smp_processor_id(); struct x8664_pda *pda = cpu_pda + hard_smp_processor_id();
rdmsrl(MSR_GS_BASE, gs); rdmsrl(MSR_GS_BASE, gs);
if (gs != (unsigned long)pda) { if (gs != (unsigned long)pda) {
wrmsrl(MSR_GS_BASE, pda); wrmsrl(MSR_GS_BASE, pda);
oops_in_progress++;
printk("general protection handler: wrong gs %lx expected %p\n", gs, pda); printk("general protection handler: wrong gs %lx expected %p\n", gs, pda);
oops_in_progress--;
} }
} }
#endif #endif
......
...@@ -2,18 +2,15 @@ ...@@ -2,18 +2,15 @@
# Makefile for x86_64-specific library files. # Makefile for x86_64-specific library files.
# #
EXTRA_CFLAGS_csum-partial.o := -funroll-loops L_TARGET := lib.a
export-objs := io.o csum-wrappers.o csum-partial.o
CFLAGS_csum-partial.o := -funroll-loops
L_TARGET = lib.a obj-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \
obj-y = csum-partial.o csum-copy.o csum-wrappers.o delay.o \
usercopy.o getuser.o putuser.o \ usercopy.o getuser.o putuser.o \
thunk.o io.o clear_page.o copy_page.o bitstr.o thunk.o io.o clear_page.o copy_page.o bitstr.o
obj-y += memcpy.o obj-y += memcpy.o memmove.o memset.o copy_user.o
obj-y += memmove.o
obj-y += memset.o
obj-y += copy_user.o
export-objs := io.o csum-wrappers.o csum-partial.o
obj-$(CONFIG_IO_DEBUG) += iodebug.o obj-$(CONFIG_IO_DEBUG) += iodebug.o
obj-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o obj-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o
...@@ -109,19 +109,34 @@ unsigned long clear_user(void *to, unsigned long n) ...@@ -109,19 +109,34 @@ unsigned long clear_user(void *to, unsigned long n)
long strnlen_user(const char *s, long n) long strnlen_user(const char *s, long n)
{ {
unsigned long res = 0; long res = 0;
char c; char c;
if (!access_ok(VERIFY_READ, s, n)) if (!access_ok(VERIFY_READ, s, n))
return 0; return 0;
while (1) { while (1) {
if (res>n)
return n+1;
if (__get_user(c, s))
return 0;
if (!c)
return res+1;
res++;
s++;
}
}
long strlen_user(const char *s)
{
long res = 0;
char c;
for (;;) {
if (get_user(c, s)) if (get_user(c, s))
return 0; return 0;
if (!c) if (!c)
return res+1; return res+1;
if (res>n)
return n+1;
res++; res++;
s++; s++;
} }
......
...@@ -4,5 +4,5 @@ ...@@ -4,5 +4,5 @@
export-objs := pageattr.o export-objs := pageattr.o
obj-y := init.o fault.o ioremap.o extable.o modutil.o pageattr.o obj-y := init.o fault.o ioremap.o extable.o pageattr.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
...@@ -161,7 +161,6 @@ static struct temp_map { ...@@ -161,7 +161,6 @@ static struct temp_map {
} temp_mappings[] __initdata = { } temp_mappings[] __initdata = {
{ &temp_boot_pmds[0], (void *)(40UL * 1024 * 1024) }, { &temp_boot_pmds[0], (void *)(40UL * 1024 * 1024) },
{ &temp_boot_pmds[1], (void *)(42UL * 1024 * 1024) }, { &temp_boot_pmds[1], (void *)(42UL * 1024 * 1024) },
{ &temp_boot_pmds[2], (void *)(44UL * 1024 * 1024) },
{} {}
}; };
...@@ -316,8 +315,6 @@ void __init mem_init(void) ...@@ -316,8 +315,6 @@ void __init mem_init(void)
int codesize, reservedpages, datasize, initsize; int codesize, reservedpages, datasize, initsize;
int tmp; int tmp;
printk("mem_init\n");
if (!mem_map) if (!mem_map)
BUG(); BUG();
......
/* arch/x86_64/mm/modutil.c
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
* Based upon code written by Linus Torvalds and others.
*
* Blatantly copied from sparc64 for x86-64 by Andi Kleen.
* Should use direct mapping with 2MB pages. This would need extension
* of the kernel mapping.
*/
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <linux/err.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/page.h>
#include <asm/pgtable.h>
/* FIXME: If module_region == mod->init_region, trim exception
table entries. */
void module_free(struct module *mod, void *module_region)
{
struct vm_struct **p, *tmp;
int i;
unsigned long addr = (unsigned long)module_region;
if (!addr)
return;
if ((PAGE_SIZE-1) & addr) {
printk("Trying to unmap module with bad address (%lx)\n", addr);
return;
}
write_lock(&vmlist_lock);
for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
if ((unsigned long)tmp->addr == addr) {
*p = tmp->next;
write_unlock(&vmlist_lock);
goto found;
}
}
write_unlock(&vmlist_lock);
printk("Trying to unmap nonexistent module vm area (%lx)\n", addr);
return;
found:
unmap_vm_area(tmp);
for (i = 0; i < tmp->nr_pages; i++) {
if (unlikely(!tmp->pages[i]))
BUG();
__free_page(tmp->pages[i]);
}
kfree(tmp->pages);
kfree(tmp);
}
void * module_alloc (unsigned long size)
{
struct vm_struct **p, *tmp, *area;
struct page **pages;
void * addr;
unsigned int nr_pages, array_size, i;
if (!size)
return NULL;
size = PAGE_ALIGN(size);
if (size > MODULES_LEN)
return ERR_PTR(-ENOMEM);
addr = (void *) MODULES_VADDR;
for (p = &vmlist; (tmp = *p) ; p = &tmp->next) {
if (size + (unsigned long) addr < (unsigned long) tmp->addr)
break;
addr = (void *) (tmp->size + (unsigned long) tmp->addr);
}
if ((unsigned long) addr + size >= MODULES_END)
return ERR_PTR(-ENOMEM);
area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL);
if (!area)
return ERR_PTR(-ENOMEM);
area->size = size + PAGE_SIZE;
area->addr = addr;
area->next = *p;
area->pages = NULL;
area->nr_pages = 0;
area->phys_addr = 0;
*p = area;
nr_pages = size >> PAGE_SHIFT;
array_size = (nr_pages * sizeof(struct page *));
area->nr_pages = nr_pages;
area->pages = pages = kmalloc(array_size, GFP_KERNEL);
if (!area->pages)
goto fail;
memset(area->pages, 0, array_size);
for (i = 0; i < area->nr_pages; i++) {
area->pages[i] = alloc_page(GFP_KERNEL);
if (unlikely(!area->pages[i]))
goto fail;
}
if (map_vm_area(area, PAGE_KERNEL_EXECUTABLE, &pages)) {
unmap_vm_area(area);
goto fail;
}
memset(area->addr, 0, size);
return area->addr;
fail:
if (area->pages) {
for (i = 0; i < area->nr_pages; i++) {
if (area->pages[i])
__free_page(area->pages[i]);
}
kfree(area->pages);
}
kfree(area);
return ERR_PTR(-ENOMEM);
}
#
# Makefile for X86_64 specific PCI routines
#
obj-y := x86-64.o obj-y := x86-64.o
obj-$(CONFIG_PCI_DIRECT)+= direct.o
obj-$(CONFIG_PCI_DIRECT) += direct.o
obj-y += fixup.o obj-y += fixup.o
obj-$(CONFIG_ACPI_PCI) += acpi.o
ifdef CONFIG_ACPI_PCI obj-y += legacy.o irq.o common.o
obj-y += acpi.o
endif
obj-y += legacy.o
obj-y += irq.o common.o
...@@ -73,11 +73,6 @@ SECTIONS ...@@ -73,11 +73,6 @@ SECTIONS
. = ALIGN(4096); . = ALIGN(4096);
.data.boot_pgt : { *(.data.boot_pgt) } .data.boot_pgt : { *(.data.boot_pgt) }
. = ALIGN(4096);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
__initramfs_end = .;
. = ALIGN(4096); /* Init code and data */ . = ALIGN(4096); /* Init code and data */
__init_begin = .; __init_begin = .;
.init.text : { *(.init.text) } .init.text : { *(.init.text) }
...@@ -100,6 +95,10 @@ SECTIONS ...@@ -100,6 +95,10 @@ SECTIONS
*(.initcall7.init) *(.initcall7.init)
} }
__initcall_end = .; __initcall_end = .;
. = ALIGN(4096);
__initramfs_start = .;
.init.ramfs : { *(.init.ramfs) }
__initramfs_end = .;
. = ALIGN(32); . = ALIGN(32);
__per_cpu_start = .; __per_cpu_start = .;
.data.percpu : { *(.data.percpu) } .data.percpu : { *(.data.percpu) }
......
#ifndef __ASM_X8664_BUG_H
#define __ASM_X8664_BUG_H 1
#include <linux/stringify.h>
/*
* Tell the user there is some problem. The exception handler decodes
* this frame.
*/
struct bug_frame {
unsigned char ud2[2];
/* should use 32bit offset instead, but the assembler doesn't
like it */
char *filename;
unsigned short line;
} __attribute__((packed));
#define BUG() \
asm volatile("ud2 ; .quad %c1 ; .short %c0" :: \
"i"(__LINE__), "i" (__stringify(KBUILD_BASENAME)))
#define PAGE_BUG(page) BUG()
void out_of_line_bug(void);
#endif
...@@ -68,4 +68,17 @@ struct compat_flock { ...@@ -68,4 +68,17 @@ struct compat_flock {
compat_pid_t l_pid; compat_pid_t l_pid;
}; };
struct compat_statfs {
int f_type;
int f_bsize;
int f_blocks;
int f_bfree;
int f_bavail;
int f_files;
int f_ffree;
compat_fsid_t f_fsid;
int f_namelen; /* SunOS ignores this field. */
int f_spare[6];
};
#endif /* _ASM_X86_64_COMPAT_H */ #endif /* _ASM_X86_64_COMPAT_H */
...@@ -101,19 +101,6 @@ struct stat64 { ...@@ -101,19 +101,6 @@ struct stat64 {
} __attribute__((packed)); } __attribute__((packed));
struct statfs32 {
int f_type;
int f_bsize;
int f_blocks;
int f_bfree;
int f_bavail;
int f_files;
int f_ffree;
compat_fsid_t f_fsid;
int f_namelen; /* SunOS ignores this field. */
int f_spare[6];
};
typedef union sigval32 { typedef union sigval32 {
int sival_int; int sival_int;
unsigned int sival_ptr; unsigned int sival_ptr;
......
...@@ -62,7 +62,10 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, ...@@ -62,7 +62,10 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
#endif #endif
} }
#define deactivate_mm(tsk,mm) do { } while (0) #define deactivate_mm(tsk,mm) do { \
load_gs_index(0); \
asm volatile("movl %0,%%fs"::"r"(0)); \
} while(0)
#define activate_mm(prev, next) \ #define activate_mm(prev, next) \
switch_mm((prev),(next),NULL,smp_processor_id()) switch_mm((prev),(next),NULL,smp_processor_id())
......
...@@ -69,21 +69,7 @@ typedef struct { unsigned long pgprot; } pgprot_t; ...@@ -69,21 +69,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/stringify.h> #include <asm/bug.h>
/*
* Tell the user there is some problem. The exception handler decodes this frame.
*/
struct bug_frame {
unsigned char ud2[2];
char *filename; /* should use 32bit offset instead, but the assembler doesn't like it */
unsigned short line;
} __attribute__((packed));
#define BUG() \
asm volatile("ud2 ; .quad %c1 ; .short %c0" :: \
"i"(__LINE__), "i" (__stringify(KBUILD_BASENAME)))
#define PAGE_BUG(page) BUG()
void out_of_line_bug(void);
/* Pure 2^n version of get_order */ /* Pure 2^n version of get_order */
extern __inline__ int get_order(unsigned long size) extern __inline__ int get_order(unsigned long size)
......
...@@ -43,6 +43,12 @@ extern void exception_table_check(void); ...@@ -43,6 +43,12 @@ extern void exception_table_check(void);
extern int acpi_boot_init(char *); extern int acpi_boot_init(char *);
extern int map_syscall32(struct mm_struct *mm, unsigned long address); extern int map_syscall32(struct mm_struct *mm, unsigned long address);
extern char *syscall32_page;
struct thread_struct;
int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info);
int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info);
#define round_up(x,y) (((x) + (y) - 1) & ~((y)-1)) #define round_up(x,y) (((x) + (y) - 1) & ~((y)-1))
#define round_down(x,y) ((x) & ~((y)-1)) #define round_down(x,y) ((x) & ~((y)-1))
......
...@@ -78,6 +78,10 @@ struct pt_regs { ...@@ -78,6 +78,10 @@ struct pt_regs {
#define PTRACE_GETFPXREGS 18 #define PTRACE_GETFPXREGS 18
#define PTRACE_SETFPXREGS 19 #define PTRACE_SETFPXREGS 19
#define PTRACE_GET_THREAD_AREA 25
#define PTRACE_SET_THREAD_AREA 26
#if defined(__KERNEL__) && !defined(__ASSEMBLY__) #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
#define user_mode(regs) (!!((regs)->cs & 3)) #define user_mode(regs) (!!((regs)->cs & 3))
#define instruction_pointer(regs) ((regs)->rip) #define instruction_pointer(regs) ((regs)->rip)
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
/* /*
* we cannot use the same code segment descriptor for user and kernel * we cannot use the same code segment descriptor for user and kernel
* even not in the long flat model, because of different DPL /kkeil * -- not even in the long flat mode, because of different DPL /kkeil
* The segment offset needs to contain a RPL. Grr. -AK * The segment offset needs to contain a RPL. Grr. -AK
* GDT layout to get 64bit syscall right (sysret hardcodes gdt offsets) * GDT layout to get 64bit syscall right (sysret hardcodes gdt offsets)
*/ */
......
...@@ -299,8 +299,8 @@ static inline int __copy_to_user(void *dst, const void *src, unsigned size) ...@@ -299,8 +299,8 @@ static inline int __copy_to_user(void *dst, const void *src, unsigned size)
long strncpy_from_user(char *dst, const char *src, long count); long strncpy_from_user(char *dst, const char *src, long count);
long __strncpy_from_user(char *dst, const char *src, long count); long __strncpy_from_user(char *dst, const char *src, long count);
#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
long strnlen_user(const char *str, long n); long strnlen_user(const char *str, long n);
long strlen_user(const char *str);
unsigned long clear_user(void *mem, unsigned long len); unsigned long clear_user(void *mem, unsigned long len);
unsigned long __clear_user(void *mem, unsigned long len); unsigned long __clear_user(void *mem, unsigned long len);
......
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