diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2003-01-04 19:28:10 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-01-04 19:28:10 -0800 |
| commit | 2afbee7679de44acd09e5d09549078f960d746f5 (patch) | |
| tree | 925804d51aa637b48c1e434b1cd85afe09cd2f85 | |
| parent | 4249e4ba95d539d42ae7a706ff7cceccb997161a (diff) | |
| parent | b45aba16483d5ddef9d484851d61dac314a3998e (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/Makefile | 17 | ||||
| -rw-r--r-- | arch/x86_64/ia32/ia32_binfmt.c | 2 | ||||
| -rw-r--r-- | arch/x86_64/ia32/ia32_ioctl.c | 46 | ||||
| -rw-r--r-- | arch/x86_64/ia32/ia32entry.S | 17 | ||||
| -rw-r--r-- | arch/x86_64/ia32/ipc32.c | 46 | ||||
| -rw-r--r-- | arch/x86_64/ia32/sys_ia32.c | 161 | ||||
| -rw-r--r-- | arch/x86_64/kernel/head.S | 3 | ||||
| -rw-r--r-- | arch/x86_64/kernel/msr.c | 2 | ||||
| -rw-r--r-- | arch/x86_64/kernel/pci-gart.c | 9 | ||||
| -rw-r--r-- | arch/x86_64/kernel/process.c | 22 | ||||
| -rw-r--r-- | arch/x86_64/kernel/ptrace.c | 11 | ||||
| -rw-r--r-- | arch/x86_64/kernel/smpboot.c | 5 | ||||
| -rw-r--r-- | arch/x86_64/kernel/sys_x86_64.c | 30 | ||||
| -rw-r--r-- | arch/x86_64/kernel/traps.c | 3 | ||||
| -rw-r--r-- | arch/x86_64/kernel/vsyscall.c | 3 | ||||
| -rw-r--r-- | drivers/char/agp/agp.h | 4 | ||||
| -rw-r--r-- | drivers/char/agp/amd-k8-agp.c | 15 | ||||
| -rw-r--r-- | drivers/char/agp/generic.c | 6 | ||||
| -rw-r--r-- | include/asm-x86_64/compat.h | 8 | ||||
| -rw-r--r-- | include/asm-x86_64/ia32.h | 13 | ||||
| -rw-r--r-- | include/asm-x86_64/segment.h | 3 | ||||
| -rw-r--r-- | include/asm-x86_64/smp.h | 5 | ||||
| -rw-r--r-- | include/asm-x86_64/uaccess.h | 4 |
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); |
