summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2003-01-04 19:28:10 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2003-01-04 19:28:10 -0800
commit2afbee7679de44acd09e5d09549078f960d746f5 (patch)
tree925804d51aa637b48c1e434b1cd85afe09cd2f85
parent4249e4ba95d539d42ae7a706ff7cceccb997161a (diff)
parentb45aba16483d5ddef9d484851d61dac314a3998e (diff)
Merge home.transmeta.com:/home/torvalds/v2.5/x86_64
into home.transmeta.com:/home/torvalds/v2.5/linux
-rw-r--r--arch/x86_64/Makefile17
-rw-r--r--arch/x86_64/ia32/ia32_binfmt.c2
-rw-r--r--arch/x86_64/ia32/ia32_ioctl.c46
-rw-r--r--arch/x86_64/ia32/ia32entry.S17
-rw-r--r--arch/x86_64/ia32/ipc32.c46
-rw-r--r--arch/x86_64/ia32/sys_ia32.c161
-rw-r--r--arch/x86_64/kernel/head.S3
-rw-r--r--arch/x86_64/kernel/msr.c2
-rw-r--r--arch/x86_64/kernel/pci-gart.c9
-rw-r--r--arch/x86_64/kernel/process.c22
-rw-r--r--arch/x86_64/kernel/ptrace.c11
-rw-r--r--arch/x86_64/kernel/smpboot.c5
-rw-r--r--arch/x86_64/kernel/sys_x86_64.c30
-rw-r--r--arch/x86_64/kernel/traps.c3
-rw-r--r--arch/x86_64/kernel/vsyscall.c3
-rw-r--r--drivers/char/agp/agp.h4
-rw-r--r--drivers/char/agp/amd-k8-agp.c15
-rw-r--r--drivers/char/agp/generic.c6
-rw-r--r--include/asm-x86_64/compat.h8
-rw-r--r--include/asm-x86_64/ia32.h13
-rw-r--r--include/asm-x86_64/segment.h3
-rw-r--r--include/asm-x86_64/smp.h5
-rw-r--r--include/asm-x86_64/uaccess.h4
23 files changed, 264 insertions, 171 deletions
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index cf3e9b86d1b8..48cd572db0dc 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -57,30 +57,32 @@ drivers-$(CONFIG_PCI) += arch/x86_64/pci/
# FIXME: is drivers- right ?
drivers-$(CONFIG_OPROFILE) += arch/x86_64/oprofile/
-boot := arch/x86_64/boot
+makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/x86_64/boot $(1)
.PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install \
- archclean
+ clean archclean archmrproper
BOOTIMAGE=arch/x86_64/boot/bzImage
zImage zlilo zdisk: BOOTIMAGE=arch/x86_64/boot/zImage
zImage bzImage: vmlinux
- $(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE)
+ $(call makeboot,$(BOOTIMAGE))
compressed: zImage
zlilo bzlilo: vmlinux
- $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zlilo
+ $(call makeboot,BOOTIMAGE=$(BOOTIMAGE) zlilo)
zdisk bzdisk: vmlinux
- $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk
+ $(call makeboot,BOOTIMAGE=$(BOOTIMAGE) zdisk)
install: vmlinux
- $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) install
+ $(call makeboot,BOOTIMAGE=$(BOOTIMAGE) install)
archclean:
- $(Q)$(MAKE) $(clean)=$(boot)
+ $(Q)$(MAKE) $(clean)=arch/i386/boot
+
+archmrproper:
prepare: include/asm-$(ARCH)/offset.h
@@ -104,3 +106,4 @@ define archhelp
echo ' (distribution) /sbin/installkernel or'
echo ' install to $$(INSTALL_PATH) and run lilo'
endef
+
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index be9f9da4bb2d..9cd341281cb7 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -261,6 +261,8 @@ static void elf32_init(struct pt_regs *regs)
regs->rax = 0;
regs->rbx = 0;
regs->rbp = 0;
+ regs->r8 = regs->r9 = regs->r10 = regs->r11 = regs->r12 =
+ regs->r13 = regs->r14 = regs->r15 = 0;
me->thread.fs = 0;
me->thread.gs = 0;
me->thread.fsindex = 0;
diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c
index 0e1e7a2d2f7e..567d070cd48f 100644
--- a/arch/x86_64/ia32/ia32_ioctl.c
+++ b/arch/x86_64/ia32/ia32_ioctl.c
@@ -450,13 +450,13 @@ struct ifreq32 {
struct ifmap32 ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
char ifru_newname[IFNAMSIZ];
- __kernel_caddr_t32 ifru_data;
+ compat_caddr_t ifru_data;
} ifr_ifru;
};
struct ifconf32 {
int ifc_len; /* size of buffer */
- __kernel_caddr_t32 ifcbuf;
+ compat_caddr_t ifcbuf;
};
#ifdef CONFIG_NET
@@ -876,7 +876,7 @@ static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg)
struct fb_fix_screeninfo32 {
char id[16];
- __kernel_caddr_t32 smem_start;
+ compat_caddr_t smem_start;
__u32 smem_len;
__u32 type;
__u32 type_aux;
@@ -885,7 +885,7 @@ struct fb_fix_screeninfo32 {
__u16 ypanstep;
__u16 ywrapstep;
__u32 line_length;
- __kernel_caddr_t32 mmio_start;
+ compat_caddr_t mmio_start;
__u32 mmio_len;
__u32 accel;
__u16 reserved[3];
@@ -894,10 +894,10 @@ struct fb_fix_screeninfo32 {
struct fb_cmap32 {
__u32 start;
__u32 len;
- __kernel_caddr_t32 red;
- __kernel_caddr_t32 green;
- __kernel_caddr_t32 blue;
- __kernel_caddr_t32 transp;
+ compat_caddr_t red;
+ compat_caddr_t green;
+ compat_caddr_t blue;
+ compat_caddr_t transp;
};
static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
@@ -1036,7 +1036,7 @@ struct floppy_struct32 {
unsigned char rate;
unsigned char spec1;
unsigned char fmt_gap;
- const __kernel_caddr_t32 name;
+ const compat_caddr_t name;
};
struct floppy_drive_params32 {
@@ -1075,7 +1075,7 @@ struct floppy_drive_struct32 {
int fd_ref;
int fd_device;
int last_checked;
- __kernel_caddr_t32 dmabuf;
+ compat_caddr_t dmabuf;
int bufblocks;
};
@@ -1600,7 +1600,7 @@ static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigne
}
struct ppp_option_data32 {
- __kernel_caddr_t32 ptr;
+ compat_caddr_t ptr;
__u32 length;
int transmit;
};
@@ -1681,8 +1681,8 @@ struct mtget32 {
__u32 mt_dsreg;
__u32 mt_gstat;
__u32 mt_erreg;
- __kernel_daddr_t32 mt_fileno;
- __kernel_daddr_t32 mt_blkno;
+ compat_daddr_t mt_fileno;
+ compat_daddr_t mt_blkno;
};
#define MTIOCGET32 _IOR('m', 2, struct mtget32)
@@ -1800,7 +1800,7 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
struct cdrom_read32 {
int cdread_lba;
- __kernel_caddr_t32 cdread_bufaddr;
+ compat_caddr_t cdread_bufaddr;
int cdread_buflen;
};
@@ -1808,16 +1808,16 @@ struct cdrom_read_audio32 {
union cdrom_addr addr;
u_char addr_format;
int nframes;
- __kernel_caddr_t32 buf;
+ compat_caddr_t buf;
};
struct cdrom_generic_command32 {
unsigned char cmd[CDROM_PACKET_SIZE];
- __kernel_caddr_t32 buffer;
+ compat_caddr_t buffer;
unsigned int buflen;
int stat;
- __kernel_caddr_t32 sense;
- __kernel_caddr_t32 reserved[3];
+ compat_caddr_t sense;
+ compat_caddr_t reserved[3];
};
static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
@@ -1826,7 +1826,7 @@ static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar
struct cdrom_read cdread;
struct cdrom_read_audio cdreadaudio;
struct cdrom_generic_command cgc;
- __kernel_caddr_t32 addr;
+ compat_caddr_t addr;
char *data = 0;
void *karg;
int err = 0;
@@ -2124,12 +2124,12 @@ static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long a
struct atmif_sioc32 {
int number;
int length;
- __kernel_caddr_t32 arg;
+ compat_caddr_t arg;
};
struct atm_iobuf32 {
int length;
- __kernel_caddr_t32 buffer;
+ compat_caddr_t buffer;
};
#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32)
@@ -2190,7 +2190,7 @@ static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg)
iobuf.length = iobuf32.length;
- if (iobuf32.buffer == (__kernel_caddr_t32) NULL || iobuf32.length == 0) {
+ if (iobuf32.buffer == (compat_caddr_t) NULL || iobuf32.length == 0) {
iobuf.buffer = (void*)(unsigned long)iobuf32.buffer;
} else {
iobuf.buffer = kmalloc(iobuf.length, GFP_KERNEL);
@@ -2244,7 +2244,7 @@ static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg)
sioc.number = sioc32.number;
sioc.length = sioc32.length;
- if (sioc32.arg == (__kernel_caddr_t32) NULL || sioc32.length == 0) {
+ if (sioc32.arg == (compat_caddr_t) NULL || sioc32.length == 0) {
sioc.arg = (void*)(unsigned long)sioc32.arg;
} else {
sioc.arg = kmalloc(sioc.length, GFP_KERNEL);
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index b5f238bc5533..4cb9273b16e1 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -76,6 +76,7 @@ cstar_do_call:
IA32_ARG_FIXUP 1
call *ia32_sys_call_table(,%rax,8)
.globl cstar_sysret
+ /* label must directly follow call */
cstar_sysret:
movq %rax,RAX-ARGOFFSET(%rsp)
GET_THREAD_INFO(%r10)
@@ -130,7 +131,7 @@ ENTRY(ia32_syscall)
pushq %rax
cld
/* note the registers are not zero extended to the sf.
- this could be a problem */
+ this could be a problem. */
SAVE_ARGS
GET_THREAD_INFO(%r10)
bt $TIF_SYSCALL_TRACE,threadinfo_flags(%r10)
@@ -190,6 +191,8 @@ ENTRY(ia32_ptregs_common)
call *%rax
movq %r15, %r11
RESTORE_REST
+ cmpq $cstar_sysret,%r11
+ je int_ret_from_sys_call /* misbalances the call/ret stack. sorry */
pushq %r11
ret
@@ -202,7 +205,7 @@ ia32_sys_call_table:
.quad stub32_fork
.quad sys_read
.quad sys_write
- .quad sys_open /* 5 */
+ .quad sys32_open /* 5 */
.quad sys_close
.quad sys32_waitpid
.quad sys_creat
@@ -320,13 +323,13 @@ ia32_sys_call_table:
.quad stub32_clone /* 120 */
.quad sys_setdomainname
.quad sys_uname
- .quad sys_modify_ldt
+ .quad sys32_modify_ldt
.quad sys32_adjtimex
.quad sys32_mprotect /* 125 */
.quad sys32_sigprocmask
.quad sys32_module_warning /* create_module */
- .quad sys32_module_warning /* init_module */
- .quad sys32_module_warning /* delete module */
+ .quad sys_init_module
+ .quad sys_delete_module
.quad sys32_module_warning /* 130 get_kernel_syms */
.quad ni_syscall /* quotactl */
.quad sys_getpgid
@@ -444,8 +447,8 @@ ia32_sys_call_table:
.quad sys_get_thread_area
.quad sys32_io_setup
.quad sys_io_destroy
- .quad sys_io_getevents
- .quad sys_io_submit
+ .quad sys32_io_getevents
+ .quad sys32_io_submit
.quad sys_io_cancel
.quad sys_ni_syscall /* 250 alloc_huge_pages */
.quad sys_ni_syscall /* free_huge_pages */
diff --git a/arch/x86_64/ia32/ipc32.c b/arch/x86_64/ia32/ipc32.c
index 380349f596db..c5700dc87b36 100644
--- a/arch/x86_64/ia32/ipc32.c
+++ b/arch/x86_64/ia32/ipc32.c
@@ -40,10 +40,10 @@ struct ipc_perm32 {
struct ipc64_perm32 {
unsigned key;
- __kernel_uid32_t32 uid;
- __kernel_gid32_t32 gid;
- __kernel_uid32_t32 cuid;
- __kernel_gid32_t32 cgid;
+ compat_uid32_t uid;
+ compat_gid32_t gid;
+ compat_uid32_t cuid;
+ compat_gid32_t cgid;
unsigned short mode;
unsigned short __pad1;
unsigned short seq;
@@ -86,8 +86,8 @@ struct msqid_ds32 {
unsigned short msg_cbytes;
unsigned short msg_qnum;
unsigned short msg_qbytes;
- __kernel_ipc_pid_t32 msg_lspid;
- __kernel_ipc_pid_t32 msg_lrpid;
+ compat_ipc_pid_t msg_lspid;
+ compat_ipc_pid_t msg_lrpid;
};
struct msqid64_ds32 {
@@ -113,8 +113,8 @@ struct shmid_ds32 {
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;
+ compat_ipc_pid_t shm_cpid;
+ compat_ipc_pid_t shm_lpid;
unsigned short shm_nattch;
};
@@ -613,6 +613,31 @@ shmctl32 (int first, int second, void *uptr)
return err;
}
+extern int sem_ctls[];
+
+static long semtimedop32(int semid, struct sembuf *sb,
+ unsigned nsops, struct compat_timespec *ts32)
+{
+ struct timespec ts;
+ mm_segment_t oldfs = get_fs();
+ long ret;
+
+ if (nsops > sem_ctls[2])
+ return -E2BIG;
+ if (!access_ok(VERIFY_READ, sb, nsops * sizeof(struct sembuf)))
+ return -EFAULT;
+ if (ts32 &&
+ (get_user(ts.tv_sec, &ts32->tv_sec) ||
+ __get_user(ts.tv_nsec, &ts32->tv_nsec)))
+ return -EFAULT;
+
+ set_fs(KERNEL_DS);
+ ret = sys_semtimedop(semid, sb, nsops, ts32 ? &ts : NULL);
+ set_fs(oldfs);
+ return ret;
+}
+
+
asmlinkage long
sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
{
@@ -627,9 +652,8 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
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));
+ return semtimedop32(first, (struct sembuf *)AA(ptr), second,
+ (struct compat_timespec *)AA(fifth));
case SEMGET:
return sys_semget(first, second, third);
case SEMCTL:
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index bfa49f6bdb34..83306f8ffe0a 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -65,6 +65,7 @@
#include <asm/semaphore.h>
#include <asm/ipc.h>
#include <asm/atomic.h>
+#include <asm/ldt.h>
#include <net/scm.h>
#include <net/sock.h>
@@ -92,6 +93,11 @@ extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
+extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
+extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
+extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
+
+
int cp_compat_stat(struct kstat *kbuf, struct compat_stat *ubuf)
{
if (verify_area(VERIFY_WRITE, ubuf, sizeof(struct compat_stat)) ||
@@ -228,19 +234,12 @@ sys32_mmap(struct mmap_arg_struct *arg)
if (a.prot & PROT_READ)
a.prot |= PROT_EXEC;
- a.flags |= MAP_32BIT;
-
mm = current->mm;
down_write(&mm->mmap_sem);
retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, a.offset>>PAGE_SHIFT);
if (file)
fput(file);
- /* Cannot wrap */
- if (retval+a.len >= IA32_PAGE_OFFSET && (long)retval > 0) {
- do_munmap(mm, retval, a.len);
- retval = -ENOMEM;
- }
up_write(&mm->mmap_sem);
return retval;
@@ -479,6 +478,8 @@ put_tv32(struct compat_timeval *o, struct timeval *i)
return err;
}
+extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
+
asmlinkage long
sys32_alarm(unsigned int seconds)
{
@@ -1638,6 +1639,31 @@ sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count)
return ret;
}
+extern asmlinkage long sys_modify_ldt(int func, void *ptr,
+ unsigned long bytecount);
+
+asmlinkage long sys32_modify_ldt(int func, void *ptr, unsigned long bytecount)
+{
+ long ret;
+ if (func == 0x1 || func == 0x11) {
+ struct user_desc info;
+ mm_segment_t old_fs = get_fs();
+ if (bytecount != sizeof(struct user_desc))
+ return -EINVAL;
+ if (copy_from_user(&info, ptr, sizeof(struct user_desc)))
+ return -EFAULT;
+ /* lm bit was undefined in the 32bit ABI and programs
+ give it random values. Force it to zero here. */
+ info.lm = 0;
+ set_fs(KERNEL_DS);
+ ret = sys_modify_ldt(func, &info, bytecount);
+ set_fs(old_fs);
+ } else {
+ ret = sys_modify_ldt(func, ptr, bytecount);
+ }
+ return ret;
+}
+
/* Handle adjtimex compatability. */
struct timex32 {
@@ -1733,15 +1759,9 @@ asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len,
prot |= PROT_EXEC;
down_write(&mm->mmap_sem);
- error = do_mmap_pgoff(file, addr, len, prot, flags|MAP_32BIT, pgoff);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
up_write(&mm->mmap_sem);
- /* cannot wrap */
- if (error+len >= IA32_PAGE_OFFSET && (long)error >= 0) {
- do_munmap(mm, error, len);
- error = -ENOMEM;
- }
-
if (file)
fput(file);
return error;
@@ -2086,54 +2106,6 @@ static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
return err;
}
-static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
-{
- u32 uaddr;
- int i;
- int err;
-
- memset(karg, 0, sizeof(*karg));
- if(get_user(karg->ca_version, &arg32->ca32_version))
- return -EFAULT;
- karg->ca_umap.ug_ident = (char *)get_zeroed_page(GFP_USER);
- if(!karg->ca_umap.ug_ident)
- return -ENOMEM;
- err = get_user(uaddr, &arg32->ca32_umap.ug32_ident);
- if(strncpy_from_user(karg->ca_umap.ug_ident,
- (char *)A(uaddr), PAGE_SIZE) <= 0)
- return -EFAULT;
- err |= __get_user(karg->ca_umap.ug_uidbase,
- &arg32->ca32_umap.ug32_uidbase);
- err |= __get_user(karg->ca_umap.ug_uidlen,
- &arg32->ca32_umap.ug32_uidlen);
- err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
- if (err)
- return -EFAULT;
- karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
- GFP_USER);
- if(!karg->ca_umap.ug_udimap)
- return -ENOMEM;
- for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
- err |= __get_user(karg->ca_umap.ug_udimap[i],
- &(((compat_pid_t *)A(uaddr))[i]));
- err |= __get_user(karg->ca_umap.ug_gidbase,
- &arg32->ca32_umap.ug32_gidbase);
- err |= __get_user(karg->ca_umap.ug_uidlen,
- &arg32->ca32_umap.ug32_gidlen);
- err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
- if (err)
- return -EFAULT;
- karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
- GFP_USER);
- if(!karg->ca_umap.ug_gdimap)
- return -ENOMEM;
- for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
- err |= __get_user(karg->ca_umap.ug_gdimap[i],
- &(((compat_gid_t *)A(uaddr))[i]));
-
- return err;
-}
-
static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
{
int err;
@@ -2222,10 +2194,6 @@ long asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsc
case NFSCTL_UNEXPORT:
err = nfs_exp32_trans(karg, arg32);
break;
- /* This one is unimplemented, be we're ready for it. */
- case NFSCTL_UGIDUPDATE:
- err = nfs_uud32_trans(karg, arg32);
- break;
case NFSCTL_GETFH:
err = nfs_getfh32_trans(karg, arg32);
break;
@@ -2282,7 +2250,7 @@ long sys32_module_warning(void)
{
static long warn_time = -(60*HZ);
if (time_before(warn_time + 60*HZ,jiffies) && strcmp(current->comm,"klogd")) {
- printk(KERN_INFO "%s: 32bit modutils not supported on 64bit kernel\n",
+ printk(KERN_INFO "%s: 32bit 2.4.x modutils not supported on 64bit kernel\n",
current->comm);
warn_time = jiffies;
}
@@ -2410,7 +2378,64 @@ long sys32_io_submit(aio_context_t ctx_id, unsigned long nr,
return err;
}
-/* XXX aio getevents */
+extern asmlinkage long sys_io_getevents(aio_context_t ctx_id,
+ long min_nr,
+ long nr,
+ struct io_event *events,
+ struct timespec *timeout);
+
+asmlinkage long sys32_io_getevents(aio_context_t ctx_id,
+ unsigned long min_nr,
+ unsigned long nr,
+ struct io_event *events,
+ struct compat_timespec *timeout)
+{
+ long ret;
+ mm_segment_t oldfs;
+ struct timespec t32;
+ /* Harden against bogus ptrace */
+ if (nr >= 0xffffffff ||
+ !access_ok(VERIFY_WRITE, events, nr * sizeof(struct io_event)))
+ return -EFAULT;
+ if (timeout &&
+ (get_user(t32.tv_sec, &timeout->tv_sec) ||
+ __get_user(t32.tv_nsec, &timeout->tv_nsec)))
+ return -EFAULT;
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_io_getevents(ctx_id,min_nr,nr,events,timeout ? &t32 : NULL);
+ set_fs(oldfs);
+ if (timeout &&
+ (__put_user(t32.tv_sec, &timeout->tv_sec) ||
+ __put_user(t32.tv_nsec, &timeout->tv_nsec)))
+ return -EFAULT;
+ return ret;
+}
+
+asmlinkage long sys32_open(const char * filename, int flags, int mode)
+{
+ char * tmp;
+ int fd, error;
+
+ /* don't force O_LARGEFILE */
+ tmp = getname(filename);
+ fd = PTR_ERR(tmp);
+ if (!IS_ERR(tmp)) {
+ fd = get_unused_fd();
+ if (fd >= 0) {
+ struct file *f = filp_open(tmp, flags, mode);
+ error = PTR_ERR(f);
+ if (unlikely(IS_ERR(f))) {
+ put_unused_fd(fd);
+ fd = error;
+ } else
+ fd_install(fd, f);
+ }
+ putname(tmp);
+ }
+ return fd;
+}
+
long sys32_vm86_warning(void)
{
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 201daae8c110..3b6a7d534f05 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -365,7 +365,8 @@ ENTRY(cpu_gdt_table)
.quad 0,0 /* TSS */
.quad 0 /* LDT */
.quad 0,0,0 /* three TLS descriptors */
- .quad 0,0 /* pad to cache line boundary */
+ .quad 0x00cff2000000ffff /* dummy descriptor for long base */
+ .quad 0 /* pad to cache line boundary */
gdt_end:
.globl gdt_end
diff --git a/arch/x86_64/kernel/msr.c b/arch/x86_64/kernel/msr.c
index fc93de86d105..095e86a729ea 100644
--- a/arch/x86_64/kernel/msr.c
+++ b/arch/x86_64/kernel/msr.c
@@ -79,7 +79,7 @@ static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx)
" jmp 2b\n"
".previous\n"
".section __ex_table,\"a\"\n"
- " .align 4\n"
+ " .align 8\n"
" .quad 1b,3b\n"
".previous"
: "=&bDS" (err), "=a" (*eax), "=d" (*edx)
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index 25cb68ee049f..695fa5e59264 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -72,6 +72,7 @@ static unsigned long *iommu_gart_bitmap; /* guarded by iommu_bitmap_lock */
#define EMERGENCY_PAGES 32 /* = 128KB */
#ifdef CONFIG_AGP
+extern int agp_amdk8_init(void);
extern int agp_init(void);
#define AGPEXTERN extern
#else
@@ -453,10 +454,14 @@ void __init pci_iommu_init(void)
unsigned long aper_size;
unsigned long iommu_start;
-#ifndef CONFIG_AGP
+#ifndef CONFIG_AGP_AMD_8151
no_agp = 1;
#else
- no_agp = no_agp || (agp_init() < 0) || (agp_copy_info(&info) < 0);
+ /* Add other K8 AGP bridge drivers here */
+ no_agp = no_agp ||
+ (agp_init() < 0) ||
+ (agp_amdk8_init() < 0) ||
+ (agp_copy_info(&info) < 0);
#endif
if (no_iommu || (!force_mmu && end_pfn < 0xffffffff>>PAGE_SHIFT)) {
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 010e53985ac1..a70c9654d8f0 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -534,43 +534,45 @@ unsigned long get_wchan(struct task_struct *p)
int sys_arch_prctl(int code, unsigned long addr)
{
int ret = 0;
- unsigned long tmp;
switch (code) {
case ARCH_SET_GS:
if (addr >= TASK_SIZE)
return -EPERM;
- load_gs_index(0);
- current->thread.gsindex = 0;
+ get_cpu();
+ load_gs_index(__USER_LONGBASE);
+ current->thread.gsindex = __USER_LONGBASE;
current->thread.gs = addr;
ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr);
+ put_cpu();
break;
case ARCH_SET_FS:
/* Not strictly needed for fs, but do it for symmetry
with gs */
if (addr >= TASK_SIZE)
return -EPERM;
- asm volatile("movl %0,%%fs" :: "r" (0));
- current->thread.fsindex = 0;
+ get_cpu();
+ asm volatile("movl %0,%%fs" :: "r" (__USER_LONGBASE));
+ current->thread.fsindex = __USER_LONGBASE;
current->thread.fs = addr;
ret = checking_wrmsrl(MSR_FS_BASE, addr);
+ put_cpu();
break;
/* Returned value may not be correct when the user changed fs/gs */
case ARCH_GET_FS:
- rdmsrl(MSR_FS_BASE, tmp);
- ret = put_user(tmp, (unsigned long *)addr);
+ ret = put_user(current->thread.fs, (unsigned long *)addr);
break;
case ARCH_GET_GS:
- rdmsrl(MSR_KERNEL_GS_BASE, tmp);
- ret = put_user(tmp, (unsigned long *)addr);
+ ret = put_user(current->thread.gs, (unsigned long *)addr);
break;
default:
ret = -EINVAL;
break;
}
+
return ret;
}
@@ -657,6 +659,7 @@ asmlinkage int sys_set_thread_area(struct user_desc *u_info)
#define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1)
#define GET_PRESENT(desc) (((desc)->b >> 15) & 1)
#define GET_USEABLE(desc) (((desc)->b >> 20) & 1)
+#define GET_LONGMODE(desc) (((desc)->b >> 21) & 1)
asmlinkage int sys_get_thread_area(struct user_desc *u_info)
{
@@ -681,6 +684,7 @@ asmlinkage int sys_get_thread_area(struct user_desc *u_info)
info.limit_in_pages = GET_LIMIT_PAGES(desc);
info.seg_not_present = !GET_PRESENT(desc);
info.useable = GET_USEABLE(desc);
+ info.lm = GET_LONGMODE(desc);
if (copy_to_user(u_info, &info, sizeof(info)))
return -EFAULT;
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index 70308686725b..93f5b66dc316 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -91,6 +91,11 @@ static int putreg(struct task_struct *child,
unsigned long regno, unsigned long value)
{
unsigned long tmp;
+
+ /* Some code in the 64bit emulation may not be 64bit clean.
+ Don't take any chances. */
+ if (test_tsk_thread_flag(child, TIF_IA32))
+ value &= 0xffffffff;
switch (regno) {
case offsetof(struct user_regs_struct,fs):
if (value && (value & 3) != 3)
@@ -145,6 +150,7 @@ static int putreg(struct task_struct *child,
static unsigned long getreg(struct task_struct *child, unsigned long regno)
{
+ unsigned long val;
switch (regno) {
case offsetof(struct user_regs_struct, fs):
return child->thread.fsindex;
@@ -160,7 +166,10 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno)
return child->thread.gs;
default:
regno = regno - sizeof(struct pt_regs);
- return get_stack_long(child, regno);
+ val = get_stack_long(child, regno);
+ if (test_tsk_thread_flag(child, TIF_IA32))
+ val &= 0xffffffff;
+ return val;
}
}
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index a305c3916e64..a93135d3a39f 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -799,11 +799,6 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
printk("CPU%d: ", 0);
print_cpu_info(&cpu_data[0]);
- /*
- * We have the boot CPU online for sure.
- */
- set_bit(0, &cpu_online_map);
- set_bit(0, &cpu_callout_map);
x86_apicid_to_cpu[boot_cpu_id] = 0;
x86_cpu_to_apicid[0] = boot_cpu_id;
current_thread_info()->cpu = 0;
diff --git a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c
index a98b086919f1..72a22946be65 100644
--- a/arch/x86_64/kernel/sys_x86_64.c
+++ b/arch/x86_64/kernel/sys_x86_64.c
@@ -18,6 +18,7 @@
#include <asm/uaccess.h>
#include <asm/ipc.h>
+#include <asm/ia32.h>
/*
* sys_pipe() is the normal C calling standard for creating
@@ -70,18 +71,27 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
struct vm_area_struct *vma;
unsigned long end = TASK_SIZE;
- if (test_thread_flag(TIF_IA32))
- flags |= MAP_32BIT;
- if (flags & MAP_32BIT)
- end = 0xffffffff-1;
- if (len > end)
- return -ENOMEM;
- if (!addr) {
- addr = TASK_UNMAPPED_64;
- if (flags & MAP_32BIT) {
+ if (test_thread_flag(TIF_IA32)) {
+ if (!addr)
addr = TASK_UNMAPPED_32;
+ end = IA32_PAGE_OFFSET;
+ } else if (flags & MAP_32BIT) {
+ /* This is usually used needed to map code in small model, so it needs to
+ be in the first 31bit. Limit it to that.
+ This means we need to move the unmapped base down for this case. This can
+ give conflicts with the heap, but we assume that glibc malloc knows how
+ to fall back to mmap. Give it 1GB of playground for now. -AK */
+ if (!addr)
+ addr = 0x40000000;
+ end = 0x80000000;
+ } else {
+ if (!addr)
+ addr = TASK_UNMAPPED_64;
+ end = TASK_SIZE;
}
- }
+
+ if (len > end)
+ return -ENOMEM;
addr = PAGE_ALIGN(addr);
for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 46a397e924a3..20c4811bad6b 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -87,8 +87,9 @@ int printk_address(unsigned long address)
const char *symname;
char *modname;
char *delim = ":";
+ char namebuf[128];
- symname = kallsyms_lookup(address, &symsize, &offset, &modname);
+ symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
if (!symname)
return printk("[<%016lx>]", address);
if (!modname)
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index f6f3e3ce11c2..efe34103b509 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -151,7 +151,6 @@ static void __init map_vsyscall(void)
static int __init vsyscall_init(void)
{
- printk("VSYSCALL: consistency checks...");
if ((unsigned long) &vgettimeofday != VSYSCALL_ADDR(__NR_vgettimeofday))
panic("vgettimeofday link addr broken");
if ((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime))
@@ -159,9 +158,7 @@ static int __init vsyscall_init(void)
if (VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE))
panic("fixmap first vsyscall %lx should be %lx", __fix_to_virt(VSYSCALL_FIRST_PAGE),
VSYSCALL_ADDR(0));
- printk("passed...mapping...");
map_vsyscall();
- printk("done.\n");
return 0;
}
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index d0fc9f658abf..8639f8bdaf15 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -130,8 +130,8 @@ struct agp_bridge_data {
void *dev_private_data;
struct pci_dev *dev;
struct gatt_mask *masks;
- unsigned long *gatt_table;
- unsigned long *gatt_table_real;
+ u32 *gatt_table;
+ u32 *gatt_table_real;
unsigned long scratch_page;
unsigned long gart_bus_addr;
unsigned long gatt_bus_addr;
diff --git a/drivers/char/agp/amd-k8-agp.c b/drivers/char/agp/amd-k8-agp.c
index 4b9e5994f6b4..aeb657b56c58 100644
--- a/drivers/char/agp/amd-k8-agp.c
+++ b/drivers/char/agp/amd-k8-agp.c
@@ -8,6 +8,12 @@
* removed now).
*/
+/*
+ * On x86-64 the AGP driver needs to be initialized early by the IOMMU
+ * code. When you use this driver as a template for a new K8 AGP bridge
+ * driver don't forget to change arch/x86_64/kernel/pci-gart.c too -AK.
+ */
+
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
@@ -56,7 +62,8 @@ static int x86_64_insert_memory(agp_memory * mem, off_t pg_start, int type)
return -EINVAL;
/* Make sure we can fit the range in the gatt table. */
- if ((pg_start + mem->page_count) > num_entries)
+ /* FIXME: could wrap */
+ if (((unsigned long)pg_start + mem->page_count) > num_entries)
return -EINVAL;
j = pg_start;
@@ -505,7 +512,7 @@ static struct __initdata pci_driver agp_amdk8_pci_driver = {
.probe = agp_amdk8_probe,
};
-static int __init agp_amdk8_init(void)
+int __init agp_amdk8_init(void)
{
int ret_val;
@@ -524,8 +531,12 @@ static void __exit agp_amdk8_cleanup(void)
pci_unregister_driver(&agp_amdk8_pci_driver);
}
+/* On x86-64 the PCI driver needs to initialize this driver early
+ for the IOMMU, so it has to be called via a backdoor. */
+#ifndef CONFIG_GART_IOMMU
module_init(agp_amdk8_init);
module_exit(agp_amdk8_cleanup);
+#endif
MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index 6a55778defc9..c952ec4fc751 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -503,7 +503,7 @@ int agp_generic_create_gatt_table(void)
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
SetPageReserved(page);
- agp_bridge.gatt_table_real = (unsigned long *) table;
+ agp_bridge.gatt_table_real = (u32 *) table;
agp_gatt_table = (void *)table;
CACHE_FLUSH();
agp_bridge.gatt_table = ioremap_nocache(virt_to_phys(table),
@@ -520,6 +520,7 @@ int agp_generic_create_gatt_table(void)
}
agp_bridge.gatt_bus_addr = virt_to_phys(agp_bridge.gatt_table_real);
+ /* AK: bogus, should encode addresses > 4GB */
for (i = 0; i < num_entries; i++)
agp_bridge.gatt_table[i] = (unsigned long) agp_bridge.scratch_page;
@@ -620,6 +621,7 @@ int agp_generic_insert_memory(agp_memory * mem, off_t pg_start, int type)
return -EINVAL;
}
+ /* AK: could wrap */
if ((pg_start + mem->page_count) > num_entries)
return -EINVAL;
@@ -652,6 +654,8 @@ int agp_generic_remove_memory(agp_memory * mem, off_t pg_start, int type)
/* The generic routines know nothing of memory types */
return -EINVAL;
}
+
+ /* AK: bogus, should encode addresses > 4GB */
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
agp_bridge.gatt_table[i] =
(unsigned long) agp_bridge.scratch_page;
diff --git a/include/asm-x86_64/compat.h b/include/asm-x86_64/compat.h
index adc5293b3a2b..140308fb61e7 100644
--- a/include/asm-x86_64/compat.h
+++ b/include/asm-x86_64/compat.h
@@ -10,16 +10,22 @@
typedef u32 compat_size_t;
typedef s32 compat_ssize_t;
typedef s32 compat_time_t;
-typedef s32 compat_suseconds_t;
typedef s32 compat_clock_t;
typedef s32 compat_pid_t;
typedef u16 compat_uid_t;
typedef u16 compat_gid_t;
+typedef u32 compat_uid32_t;
+typedef u32 compat_gid32_t;
typedef u16 compat_mode_t;
typedef u32 compat_ino_t;
typedef u16 compat_dev_t;
typedef s32 compat_off_t;
+typedef s64 compat_loff_t;
typedef u16 compat_nlink_t;
+typedef u16 compat_ipc_pid_t;
+typedef s32 compat_daddr_t;
+typedef u32 compat_caddr_t;
+typedef __kernel_fsid_t compat_fsid_t;
struct compat_timespec {
compat_time_t tv_sec;
diff --git a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h
index 802b85d4750f..7ebb9db48314 100644
--- a/include/asm-x86_64/ia32.h
+++ b/include/asm-x86_64/ia32.h
@@ -11,17 +11,6 @@
* 32 bit structures for IA32 support.
*/
-/* 32bit compatibility types */
-typedef unsigned short __kernel_ipc_pid_t32;
-typedef unsigned __kernel_uid32_t32;
-typedef unsigned __kernel_gid32_t32;
-typedef unsigned short __kernel_umode_t32;
-typedef int __kernel_daddr_t32;
-typedef unsigned int __kernel_caddr_t32;
-typedef long __kernel_loff_t32;
-typedef __kernel_fsid_t __kernel_fsid_t32;
-
-
struct ia32_flock64 {
short l_type;
short l_whence;
@@ -120,7 +109,7 @@ struct statfs32 {
int f_bavail;
int f_files;
int f_ffree;
- __kernel_fsid_t32 f_fsid;
+ compat_fsid_t f_fsid;
int f_namelen; /* SunOS ignores this field. */
int f_spare[6];
};
diff --git a/include/asm-x86_64/segment.h b/include/asm-x86_64/segment.h
index 70cb7cf0808e..64f131070585 100644
--- a/include/asm-x86_64/segment.h
+++ b/include/asm-x86_64/segment.h
@@ -6,6 +6,8 @@
#define __KERNEL32_CS 0x38
+#define __USER_LONGBASE ((GDT_ENTRY_LONGBASE * 8) | 3)
+
/*
* we cannot use the same code segment descriptor for user and kernel
* even not in the long flat model, because of different DPL /kkeil
@@ -23,6 +25,7 @@
#define GDT_ENTRY_LDT 10
#define GDT_ENTRY_TLS_MIN 11
#define GDT_ENTRY_TLS_MAX 13
+#define GDT_ENTRY_LONGBASE 14
#define GDT_ENTRY_TLS_ENTRIES 3
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
index 3af6dbea3d1c..b6a8eb92d2b1 100644
--- a/include/asm-x86_64/smp.h
+++ b/include/asm-x86_64/smp.h
@@ -83,16 +83,17 @@ extern inline int find_first_cpu(void)
return ffz(~cpu_online_map);
}
+/* RED-PEN different from i386 */
#define for_each_cpu(i) \
for((i) = find_first_cpu(); (i)>=0; (i)=find_next_cpu(i))
-extern volatile unsigned long cpu_callout_map;
-/* We don't mark CPUs online until __cpu_up(), so we need another measure */
static inline int num_booting_cpus(void)
{
return hweight32(cpu_callout_map);
}
+extern volatile unsigned long cpu_callout_map;
+
/*
* Some lowlevel functions might want to know about
* the real APIC ID <-> CPU # mapping.
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
index 065eb4c8dafb..47e78d59e27b 100644
--- a/include/asm-x86_64/uaccess.h
+++ b/include/asm-x86_64/uaccess.h
@@ -240,7 +240,7 @@ extern unsigned long copy_user_generic(void *to, const void *from, unsigned len)
extern unsigned long copy_to_user(void *to, const void *from, unsigned len);
extern unsigned long copy_from_user(void *to, const void *from, unsigned len);
-static inline int __copy_from_user(void *dst, void *src, unsigned size)
+static inline int __copy_from_user(void *dst, const void *src, unsigned size)
{
if (!__builtin_constant_p(size))
return copy_user_generic(dst,src,size);
@@ -269,7 +269,7 @@ static inline int __copy_from_user(void *dst, void *src, unsigned size)
}
}
-static inline int __copy_to_user(void *dst, void *src, unsigned size)
+static inline int __copy_to_user(void *dst, const void *src, unsigned size)
{
if (!__builtin_constant_p(size))
return copy_user_generic(dst,src,size);