Commit 717db2f9 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] x86-64 updates for 2.5.54

More x86-64 updates for 2.5.54.  Most noticeable change is that the
64bit X server works again.

This only changes x86-64 specific files.  It requires some AGP driver
changes I'm sending separately.

 - Some Makefile cleanups from Sam Ravnborg
 - Make sure extended registers in 32bit processes are zeroed and not
   accessible/changeable from ptrace.  This is to avoid potential
   security bugs with non 64bit clean 32bit emulation functions (they
   often are overflow prone etc.)
 - Some 32bit emulation cleanups from Stephen Rothwell
 - Make copy_*_user source const to fix warnings.
 - Set fs/gs to dummy values when the 64bit segment base is set to not
   confuse the context switch (Karsten Keil, me)
	* still one mysterious bug in this area unfortunately.
 - Make MAP_32BIT for 64bit processes only map in the first 31bit,
   because it is usually used to map small model code.  This fixes the X
   server crashes.  Some cleanups in this area.
 - Don't set O_LARGEFILE for 32bit open
 - Handle ptregs calls from 32bit syscall correctly.
 - Implement aio io_getevents for 32bit.
 - Remove buggy unused command handler in nfsd 32bit emulation.
 - Convert timespec in semtimedop (thanks to Anton for telling me about
   this)
 - Ignore long mode flag from 32bit modify_ldt.  This fixes Wine, which
   left it uninitialized (bug found by Karsten Keil)
 - Merge with i386
 - Handle new kallsyms
 - Remove some superfluous bootup printks
parent 4c55cc62
......@@ -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
......@@ -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;
......
......@@ -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);
......
......@@ -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 */
......
......@@ -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:
......
......@@ -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)
{
......@@ -1662,6 +1663,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 {
......@@ -1757,15 +1783,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;
......@@ -2110,54 +2130,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;
......@@ -2246,10 +2218,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;
......@@ -2306,7 +2274,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;
}
......@@ -2434,7 +2402,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)
{
......
......@@ -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
......
......@@ -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)
......
......@@ -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)) {
......
......@@ -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;
......
......@@ -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;
}
}
......
......@@ -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;
......
......@@ -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) {
......
......@@ -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)
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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;
/* fcntl.h */
struct flock32 {
short l_type;
......@@ -130,7 +119,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];
};
......
......@@ -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
......
......@@ -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.
......
......@@ -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);
......
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