diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-07-18 23:31:08 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-07-18 23:31:08 +0000 |
commit | e8f9b6396e79654ea5932f64131cafbe8caadfb1 (patch) | |
tree | 90cf8b3a2475a774369eda22247cab7874fd7bbf /arch/ia64 | |
parent | d4c419dfaa853f5db107973976d4215ae648e976 (diff) |
Merge with Linux 2.4.0-test5-pre2.
Diffstat (limited to 'arch/ia64')
37 files changed, 643 insertions, 420 deletions
diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index a87cb7c08..50357e2f7 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -11,6 +11,8 @@ NM := $(CROSS_COMPILE)nm -B AWK := awk +export AWK + LINKFLAGS = -static -T arch/$(ARCH)/vmlinux.lds AFLAGS += -Wa,-x EXTRA = diff --git a/arch/ia64/config.in b/arch/ia64/config.in index 09131fac7..8b8dd761c 100644 --- a/arch/ia64/config.in +++ b/arch/ia64/config.in @@ -1,6 +1,3 @@ -# For a description of the syntax of this configuration file, -# see Documentation/kbuild/config-language.txt. -# mainmenu_name "Kernel configuration of Linux for IA-64 machines" mainmenu_option next_comment @@ -71,6 +68,8 @@ bool 'Sysctl support' CONFIG_SYSCTL tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC +if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then + bool 'PCI support' CONFIG_PCI source drivers/pci/Config.in @@ -83,17 +82,21 @@ fi source drivers/parport/Config.in +fi # !HP_SIM + endmenu +if [ "$CONFIG_NET" = "y" ]; then + source net/Config.in +fi + +if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then + source drivers/mtd/Config.in source drivers/pnp/Config.in source drivers/block/Config.in source drivers/i2o/Config.in -if [ "$CONFIG_NET" = "y" ]; then - source net/Config.in -fi - mainmenu_option next_comment comment 'ATA/IDE/MFM/RLL support' @@ -107,6 +110,8 @@ else fi endmenu +fi # !HP_SIM + mainmenu_option next_comment comment 'SCSI support' @@ -114,10 +119,11 @@ tristate 'SCSI support' CONFIG_SCSI if [ "$CONFIG_SCSI" != "n" ]; then source drivers/scsi/Config.in - bool 'Simulated SCSI disk' CONFIG_SCSI_SIM fi endmenu +if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then + if [ "$CONFIG_NET" = "y" ]; then mainmenu_option next_comment comment 'Network device support' @@ -149,7 +155,10 @@ if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then fi endmenu +fi # !HP_SIM + source drivers/char/Config.in + #source drivers/misc/Config.in source fs/Config.in @@ -167,6 +176,8 @@ if [ "$CONFIG_VT" = "y" ]; then endmenu fi +if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then + mainmenu_option next_comment comment 'Sound' @@ -178,6 +189,21 @@ endmenu source drivers/usb/Config.in +fi # !HP_SIM + +if [ "$CONFIG_IA64_HP_SIM" != "n" -o "$CONFIG_IA64_GENERIC" != "n" ]; then + mainmenu_option next_comment + comment 'Simulated drivers' + + tristate 'Simulated Ethernet ' CONFIG_SIMETH + bool 'Simulated serial driver support' CONFIG_SIM_SERIAL + if [ "$CONFIG_SCSI" != "n" ]; then + bool 'Simulated SCSI disk' CONFIG_SCSI_SIM + fi + endmenu +fi + + mainmenu_option next_comment comment 'Kernel hacking' diff --git a/arch/ia64/dig/setup.c b/arch/ia64/dig/setup.c index 4d22f46a4..45c1f96f5 100644 --- a/arch/ia64/dig/setup.c +++ b/arch/ia64/dig/setup.c @@ -19,7 +19,6 @@ #include <linux/console.h> #include <linux/timex.h> #include <linux/sched.h> -#include <linux/mc146818rtc.h> #include <asm/io.h> #include <asm/machvec.h> diff --git a/arch/ia64/hp/hpsim_setup.c b/arch/ia64/hp/hpsim_setup.c index dfa83e135..aaa87c4dc 100644 --- a/arch/ia64/hp/hpsim_setup.c +++ b/arch/ia64/hp/hpsim_setup.c @@ -63,6 +63,12 @@ ia64_ctl_trace (long on) } void __init +hpsim_pci_fixup (void) +{ +} + + +void __init hpsim_setup (char **cmdline_p) { ROOT_DEV = to_kdev_t(0x0801); /* default to first SCSI drive */ diff --git a/arch/ia64/ia32/Makefile b/arch/ia64/ia32/Makefile index 1b18cca58..4f3312c01 100644 --- a/arch/ia64/ia32/Makefile +++ b/arch/ia64/ia32/Makefile @@ -10,7 +10,7 @@ all: ia32.o O_TARGET := ia32.o -O_OBJS := ia32_entry.o sys_ia32.o ia32_signal.o ia32_support.o ia32_traps.o binfmt_elf32.o +O_OBJS := ia32_entry.o sys_ia32.o ia32_ioctl.o ia32_signal.o ia32_support.o ia32_traps.o binfmt_elf32.o clean:: diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c index bd29c97e7..6c63e33a7 100644 --- a/arch/ia64/ia32/binfmt_elf32.c +++ b/arch/ia64/ia32/binfmt_elf32.c @@ -6,7 +6,8 @@ * 06/16/00 A. Mallick initialize csd/ssd/tssd/cflg for ia32_load_state */ #include <linux/config.h> -#include <linux/posix_types.h> + +#include <linux/types.h> #include <asm/signal.h> #include <asm/ia32.h> @@ -16,7 +17,9 @@ /* Override some function names */ #undef start_thread #define start_thread ia32_start_thread +#define elf_format elf32_format #define init_elf_binfmt init_elf32_binfmt +#define exit_elf_binfmt exit_elf32_binfmt #undef CONFIG_BINFMT_ELF #ifdef CONFIG_BINFMT_ELF32 @@ -28,10 +31,12 @@ # define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE #endif -void ia64_elf32_init(struct pt_regs *regs); -#define ELF_PLAT_INIT(_r) ia64_elf32_init(_r) +extern void ia64_elf32_init(struct pt_regs *regs); +extern void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address); +#define ELF_PLAT_INIT(_r) ia64_elf32_init(_r) #define setup_arg_pages(bprm) ia32_setup_arg_pages(bprm) +#define elf_map elf_map32 /* Ugly but avoids duplication */ #include "../../../fs/binfmt_elf.c" @@ -201,3 +206,53 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm) return 0; } + +static unsigned long +ia32_mm_addr(unsigned long addr) +{ + struct vm_area_struct *vma; + + if ((vma = find_vma(current->mm, addr)) == NULL) + return(ELF_PAGESTART(addr)); + if (vma->vm_start > addr) + return(ELF_PAGESTART(addr)); + return(ELF_PAGEALIGN(addr)); +} + +/* + * Normally we would do an `mmap' to map in the process's text section. + * This doesn't work with IA32 processes as the ELF file might specify + * a non page size aligned address. Instead we will just allocate + * memory and read the data in from the file. Slightly less efficient + * but it works. + */ +extern long ia32_do_mmap (struct file *filep, unsigned int len, unsigned int prot, + unsigned int flags, unsigned int fd, unsigned int offset); + +static unsigned long +elf_map32 (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type) +{ + unsigned long retval; + + if (eppnt->p_memsz >= (1UL<<32) || addr > (1UL<<32) - eppnt->p_memsz) + return -EINVAL; + +#if 1 + set_brk(ia32_mm_addr(addr), addr + eppnt->p_memsz); + memset((char *) addr + eppnt->p_filesz, 0, eppnt->p_memsz - eppnt->p_filesz); + kernel_read(filep, eppnt->p_offset, (char *) addr, eppnt->p_filesz); + retval = (unsigned long) addr; +#else + /* doesn't work yet... */ +# define IA32_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_EXEC_PAGESIZE-1)) +# define IA32_PAGEOFFSET(_v) ((_v) & (ELF_EXEC_PAGESIZE-1)) +# define IA32_PAGEALIGN(_v) (((_v) + ELF_EXEC_PAGESIZE - 1) & ~(ELF_EXEC_PAGESIZE - 1)) + + down(¤t->mm->mmap_sem); + retval = ia32_do_mmap(filep, IA32_PAGESTART(addr), + eppnt->p_filesz + IA32_PAGEOFFSET(eppnt->p_vaddr), prot, type, + eppnt->p_offset - IA32_PAGEOFFSET(eppnt->p_vaddr)); + up(¤t->mm->mmap_sem); +#endif + return retval; +} diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S index 5bf5ad2c3..a9dc378cf 100644 --- a/arch/ia64/ia32/ia32_entry.S +++ b/arch/ia64/ia32/ia32_entry.S @@ -63,13 +63,13 @@ END(ia32_ret_from_syscall) GLOBAL_ENTRY(ia32_trace_syscall) PT_REGS_UNWIND_INFO(0) br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch syscall args -.Lret4: br.call.sptk.few rp=b6 // do the syscall -.Lret5: cmp.lt p6,p0=r8,r0 // syscall failed? +.ret0: br.call.sptk.few rp=b6 // do the syscall +.ret1: cmp.lt p6,p0=r8,r0 // syscall failed? adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8 ;; st8.spill [r2]=r8 // store return value in slot for r8 br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch return value -.Lret6: br.cond.sptk.many ia64_leave_kernel // rp MUST be != ia64_leave_kernel! +.ret2: br.cond.sptk.many ia64_leave_kernel // rp MUST be != ia64_leave_kernel! END(ia32_trace_syscall) GLOBAL_ENTRY(sys32_vfork) @@ -80,7 +80,7 @@ END(sys32_vfork) GLOBAL_ENTRY(sys32_fork) UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)) - alloc r16=ar.pfs,2,2,3,0 + alloc r16=ar.pfs,2,2,4,0 mov out0=SIGCHLD // out0 = clone_flags ;; .fork1: @@ -90,13 +90,11 @@ GLOBAL_ENTRY(sys32_fork) UNW(.body) - adds out2=IA64_SWITCH_STACK_SIZE+16,sp - adds r2=IA64_SWITCH_STACK_SIZE+IA64_PT_REGS_R12_OFFSET+16,sp - ;; - ld8 out1=[r2] // fetch usp from pt_regs.r12 + mov out1=0 + mov out2=0 + adds out3=IA64_SWITCH_STACK_SIZE+16,sp br.call.sptk.few rp=do_fork -.ret1: - mov ar.pfs=loc1 +.ret3: mov ar.pfs=loc1 UNW(.restore sp) adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack mov rp=loc0 @@ -137,7 +135,7 @@ ia32_syscall_table: data8 sys32_alarm data8 sys_ni_syscall data8 sys_ni_syscall - data8 sys_ni_syscall /* 30 */ + data8 ia32_utime /* 30 */ data8 sys_ni_syscall /* old stty syscall holder */ data8 sys_ni_syscall /* old gtty syscall holder */ data8 sys_access @@ -161,7 +159,7 @@ ia32_syscall_table: data8 sys_acct data8 sys_umount /* recycled never used phys( */ data8 sys_ni_syscall /* old lock syscall holder */ - data8 sys_ioctl + data8 ia32_ioctl data8 sys_fcntl /* 55 */ data8 sys_ni_syscall /* old mpx syscall holder */ data8 sys_setpgid diff --git a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c new file mode 100644 index 000000000..a5cd927b3 --- /dev/null +++ b/arch/ia64/ia32/ia32_ioctl.c @@ -0,0 +1,102 @@ +/* + * IA32 Architecture-specific ioctl shim code + * + * Copyright (C) 2000 VA Linux Co + * Copyright (C) 2000 Don Dugger <n0ano@valinux.com> + */ + +#include <linux/types.h> +#include <linux/dirent.h> +#include <linux/msdos_fs.h> +#include <linux/mtio.h> +#include <linux/ncp_fs.h> +#include <linux/capi.h> +#include <linux/videodev.h> +#include <linux/synclink.h> +#include <linux/atmdev.h> +#include <linux/atm_eni.h> +#include <linux/atm_nicstar.h> +#include <linux/atm_zatm.h> +#include <linux/atm_idt77105.h> +#include <linux/ppp_defs.h> +#include <linux/if_ppp.h> +#include <linux/ixjuser.h> +#include <linux/i2o-dev.h> + +asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); + +asmlinkage long ia32_ioctl(unsigned int fd, unsigned int cmd, unsigned int arg) +{ + + switch (cmd) { + + case VFAT_IOCTL_READDIR_BOTH: + case VFAT_IOCTL_READDIR_SHORT: + case MTIOCGET: + case MTIOCPOS: + case MTIOCGETCONFIG: + case MTIOCSETCONFIG: + case PPPIOCSCOMPRESS: + case PPPIOCGIDLE: + case NCP_IOC_GET_FS_INFO_V2: + case NCP_IOC_GETOBJECTNAME: + case NCP_IOC_SETOBJECTNAME: + case NCP_IOC_GETPRIVATEDATA: + case NCP_IOC_SETPRIVATEDATA: + case NCP_IOC_GETMOUNTUID2: + case CAPI_MANUFACTURER_CMD: + case VIDIOCGTUNER: + case VIDIOCSTUNER: + case VIDIOCGWIN: + case VIDIOCSWIN: + case VIDIOCGFBUF: + case VIDIOCSFBUF: + case MGSL_IOCSPARAMS: + case MGSL_IOCGPARAMS: + case ATM_GETNAMES: + case ATM_GETLINKRATE: + case ATM_GETTYPE: + case ATM_GETESI: + case ATM_GETADDR: + case ATM_RSTADDR: + case ATM_ADDADDR: + case ATM_DELADDR: + case ATM_GETCIRANGE: + case ATM_SETCIRANGE: + case ATM_SETESI: + case ATM_SETESIF: + case ATM_GETSTAT: + case ATM_GETSTATZ: + case ATM_GETLOOP: + case ATM_SETLOOP: + case ATM_QUERYLOOP: + case ENI_SETMULT: + case NS_GETPSTAT: + /* case NS_SETBUFLEV: This is a duplicate case with ZATM_GETPOOLZ */ + case ZATM_GETPOOLZ: + case ZATM_GETPOOL: + case ZATM_SETPOOL: + case ZATM_GETTHIST: + case IDT77105_GETSTAT: + case IDT77105_GETSTATZ: + case IXJCTL_TONE_CADENCE: + case IXJCTL_FRAMES_READ: + case IXJCTL_FRAMES_WRITTEN: + case IXJCTL_READ_WAIT: + case IXJCTL_WRITE_WAIT: + case IXJCTL_DRYBUFFER_READ: + case I2OHRTGET: + case I2OLCTGET: + case I2OPARMSET: + case I2OPARMGET: + case I2OSWDL: + case I2OSWUL: + case I2OSWDEL: + case I2OHTML: + printk("%x:unimplemented IA32 ioctl system call\n", cmd); + return(-EINVAL); + default: + return(sys_ioctl(fd, cmd, (unsigned long)arg)); + + } +} diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 1e9876eb4..cbec84f2b 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -29,6 +29,7 @@ #include <linux/smp_lock.h> #include <linux/sem.h> #include <linux/msg.h> +#include <linux/mm.h> #include <linux/shm.h> #include <linux/malloc.h> #include <linux/uio.h> @@ -207,7 +208,7 @@ sys32_newfstat(unsigned int fd, struct stat32 *statbuf) unsigned long do_mmap_fake(struct file *file, unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, unsigned long off) + unsigned long prot, unsigned long flags, loff_t off) { struct inode *inode; void *front, *back; @@ -224,11 +225,11 @@ do_mmap_fake(struct file *file, unsigned long addr, unsigned long len, back = NULL; if ((baddr = (addr & PAGE_MASK)) != addr && get_user(c, (char *)baddr) == 0) { front = kmalloc(addr - baddr, GFP_KERNEL); - memcpy(front, (void *)baddr, addr - baddr); + __copy_user(front, (void *)baddr, addr - baddr); } if (addr && ((addr + len) & ~PAGE_MASK) && get_user(c, (char *)(addr + len)) == 0) { back = kmalloc(PAGE_SIZE - ((addr + len) & ~PAGE_MASK), GFP_KERNEL); - memcpy(back, (char *)addr + len, PAGE_SIZE - ((addr + len) & ~PAGE_MASK)); + __copy_user(back, (char *)addr + len, PAGE_SIZE - ((addr + len) & ~PAGE_MASK)); } down(¤t->mm->mmap_sem); r = do_mmap(0, baddr, len + (addr - baddr), prot, flags | MAP_ANONYMOUS, 0); @@ -238,15 +239,15 @@ do_mmap_fake(struct file *file, unsigned long addr, unsigned long len, if (addr == 0) addr = r; if (back) { - memcpy((char *)addr + len, back, PAGE_SIZE - ((addr + len) & ~PAGE_MASK)); + __copy_user((char *)addr + len, back, PAGE_SIZE - ((addr + len) & ~PAGE_MASK)); kfree(back); } if (front) { - memcpy((void *)baddr, front, addr - baddr); + __copy_user((void *)baddr, front, addr - baddr); kfree(front); } if (flags & MAP_ANONYMOUS) { - memset((char *)addr, 0, len); + clear_user((char *)addr, len); return(addr); } if (!file) @@ -256,19 +257,39 @@ do_mmap_fake(struct file *file, unsigned long addr, unsigned long len, return -EINVAL; if (!file->f_op->read) return -EINVAL; - lock_kernel(); - if (file->f_op->llseek) { - if (file->f_op->llseek(file,off,0) != off) { - unlock_kernel(); - return -EINVAL; - } - } else - file->f_pos = off; - unlock_kernel(); - r = file->f_op->read(file, (char *)addr, len, &file->f_pos); + r = file->f_op->read(file, (char *)addr, len, &off); return (r < 0) ? -EINVAL : addr; } +long +ia32_do_mmap (struct file *file, unsigned int addr, unsigned int len, unsigned int prot, + unsigned int flags, unsigned int fd, unsigned int offset) +{ + long error = -EFAULT; + unsigned int poff; + + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + + if ((flags & MAP_FIXED) && ((addr & ~PAGE_MASK) || (offset & ~PAGE_MASK))) + error = do_mmap_fake(file, addr, len, prot, flags, (loff_t)offset); + else if (!addr && (offset & ~PAGE_MASK)) { + poff = offset & PAGE_MASK; + len += offset - poff; + + down(¤t->mm->mmap_sem); + error = do_mmap(file, addr, len, prot, flags, poff); + up(¤t->mm->mmap_sem); + + if (!IS_ERR(error)) + error += offset - poff; + } else { + down(¤t->mm->mmap_sem); + error = do_mmap(file, addr, len, prot, flags, offset); + up(¤t->mm->mmap_sem); + } + return error; +} + /* * Linux/i386 didn't use to be able to handle more than * 4 system call parameters, so these system calls used a memory @@ -287,32 +308,22 @@ struct mmap_arg_struct { asmlinkage long sys32_mmap(struct mmap_arg_struct *arg) { - int error = -EFAULT; - struct file * file = NULL; struct mmap_arg_struct a; + struct file *file = NULL; + long retval; if (copy_from_user(&a, arg, sizeof(a))) return -EFAULT; if (!(a.flags & MAP_ANONYMOUS)) { - error = -EBADF; file = fget(a.fd); if (!file) - goto out; - } - a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - if ((a.flags & MAP_FIXED) && ((a.addr & ~PAGE_MASK) || (a.offset & ~PAGE_MASK))) { - error = do_mmap_fake(file, a.addr, a.len, a.prot, a.flags, a.offset); - } else { - down(¤t->mm->mmap_sem); - error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset); - up(¤t->mm->mmap_sem); + return -EBADF; } + retval = ia32_do_mmap(file, a.addr, a.len, a.prot, a.flags, a.fd, a.offset); if (file) fput(file); -out: - return error; + return retval; } asmlinkage long @@ -602,6 +613,40 @@ sys32_alarm(unsigned int seconds) /* Translations due to time_t size differences. Which affects all sorts of things, like timeval and itimerval. */ +struct utimbuf_32 { + int atime; + int mtime; +}; + +extern asmlinkage long sys_utimes(char * filename, struct timeval * utimes); +extern asmlinkage long sys_gettimeofday (struct timeval *tv, struct timezone *tz); + +asmlinkage long +ia32_utime(char * filename, struct utimbuf_32 *times32) +{ + mm_segment_t old_fs = get_fs(); + struct timeval tv[2]; + long ret; + + if (times32) { + get_user(tv[0].tv_sec, ×32->atime); + tv[0].tv_usec = 0; + get_user(tv[1].tv_sec, ×32->mtime); + tv[1].tv_usec = 0; + set_fs (KERNEL_DS); + } else { + set_fs (KERNEL_DS); + ret = sys_gettimeofday(&tv[0], 0); + if (ret < 0) + goto out; + tv[1] = tv[0]; + } + ret = sys_utimes(filename, tv); + out: + set_fs (old_fs); + return ret; +} + extern struct timezone sys_tz; extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz); @@ -2359,7 +2404,7 @@ sys32_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, goto out; } ret = -ESRCH; - if (!(child->flags & PF_PTRACED)) + if (!(child->ptrace & PT_PTRACED)) goto out; if (child->state != TASK_STOPPED) { if (request != PTRACE_KILL) diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 3fb62560d..dfba2529a 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -9,35 +9,20 @@ all: kernel.o head.o init_task.o -O_TARGET := kernel.o -O_OBJS := acpi.o entry.o gate.o efi.o efi_stub.o irq.o irq_ia64.o irq_sapic.o ivt.o \ - pal.o pci-dma.o process.o perfmon.o ptrace.o sal.o semaphore.o setup.o \ - signal.o sys_ia64.o traps.o time.o unaligned.o unwind.o -OX_OBJS := ia64_ksyms.o - -ifdef CONFIG_IA64_GENERIC -O_OBJS += machvec.o -endif - -ifdef CONFIG_IA64_PALINFO -O_OBJS += palinfo.o -endif +obj-y := acpi.o entry.o gate.o efi.o efi_stub.o irq.o irq_ia64.o irq_sapic.o ivt.o \ + pal.o pci-dma.o process.o perfmon.o ptrace.o sal.o semaphore.o setup.o \ + signal.o sys_ia64.o traps.o time.o unaligned.o unwind.o -ifdef CONFIG_PCI -O_OBJS += pci.o -endif +obj-$(CONFIG_IA64_GENERIC) += machvec.o +obj-$(CONFIG_IA64_PALINFO) += palinfo.o +obj-$(CONFIG_PCI) += pci.o +obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_IA64_MCA) += mca.o mca_asm.o +obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o -ifdef CONFIG_SMP -O_OBJS += smp.o -endif - -ifdef CONFIG_IA64_MCA -O_OBJS += mca.o mca_asm.o -endif - -ifdef CONFIG_IA64_BRL_EMU -O_OBJS += brl_emu.o -endif +O_TARGET := kernel.o +O_OBJS := $(obj-y) +OX_OBJS := ia64_ksyms.o clean:: diff --git a/arch/ia64/kernel/efi_stub.S b/arch/ia64/kernel/efi_stub.S index 2bb45c790..1ee6ad05f 100644 --- a/arch/ia64/kernel/efi_stub.S +++ b/arch/ia64/kernel/efi_stub.S @@ -76,17 +76,14 @@ GLOBAL_ENTRY(efi_call_phys) andcm r16=loc3,r16 // get psr with IT, DT, and RT bits cleared mov out3=in4 br.call.sptk.few rp=ia64_switch_mode -.ret0: - mov out4=in5 +.ret0: mov out4=in5 mov out5=in6 mov out6=in7 br.call.sptk.few rp=b6 // call the EFI function -.ret1: - mov ar.rsc=r0 // put RSE in enforced lazy, LE mode +.ret1: mov ar.rsc=r0 // put RSE in enforced lazy, LE mode mov r16=loc3 br.call.sptk.few rp=ia64_switch_mode // return to virtual mode -.ret2: - mov ar.rsc=loc4 // restore RSE configuration +.ret2: mov ar.rsc=loc4 // restore RSE configuration mov ar.pfs=loc1 mov rp=loc0 mov gp=loc2 diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index e56e3fc8e..3aadb43a0 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -17,8 +17,6 @@ * pSys: See entry.h. * pNonSys: !pSys * p2: (Alias of pKern!) True if any signals are pending. - * p16/p17: Used by stubs calling ia64_do_signal to indicate if current task - * has PF_PTRACED flag bit set. p16 is true if so, p17 is the complement. */ #include <linux/config.h> @@ -62,27 +60,41 @@ ENTRY(ia64_execve) br.ret.sptk.few rp END(ia64_execve) -GLOBAL_ENTRY(sys_clone) +GLOBAL_ENTRY(sys_clone2) UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)) - alloc r16=ar.pfs,2,2,3,0;; - mov loc0=rp + alloc r16=ar.pfs,3,2,4,0 DO_SAVE_SWITCH_STACK + mov loc0=rp mov loc1=r16 // save ar.pfs across do_fork UNW(.body) - adds out2=IA64_SWITCH_STACK_SIZE+16,sp - adds r2=IA64_SWITCH_STACK_SIZE+IA64_PT_REGS_R12_OFFSET+16,sp - cmp.eq p8,p9=in1,r0 // usp == 0? + mov out1=in1 + mov out2=in2 + adds out3=IA64_SWITCH_STACK_SIZE+16,sp // out3 = ®s mov out0=in0 // out0 = clone_flags - ;; -(p8) ld8 out1=[r2] // fetch usp from pt_regs.r12 -(p9) mov out1=in1 br.call.sptk.few rp=do_fork -.ret1: +.ret1: UNW(.restore sp) + adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack mov ar.pfs=loc1 - UNW(.restore sp) + mov rp=loc0 + br.ret.sptk.many rp +END(sys_clone2) + +GLOBAL_ENTRY(sys_clone) + UNW(.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2)) + alloc r16=ar.pfs,2,2,4,0 + DO_SAVE_SWITCH_STACK + mov loc0=rp + mov loc1=r16 // save ar.pfs across do_fork + UNW(.body) + mov out1=in1 + mov out2=0 + adds out3=IA64_SWITCH_STACK_SIZE+16,sp // out3 = ®s + mov out0=in0 // out0 = clone_flags + br.call.sptk.few rp=do_fork +.ret2: UNW(.restore sp) adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack + mov ar.pfs=loc1 mov rp=loc0 - ;; br.ret.sptk.many rp END(sys_clone) @@ -387,9 +399,9 @@ GLOBAL_ENTRY(invoke_syscall_trace) ;; // WAW on CFM at the br.call mov loc0=rp br.call.sptk.many rp=save_switch_stack_with_current_frame // must preserve b6!! -.ret2: mov loc2=b6 +.ret4: mov loc2=b6 br.call.sptk.few rp=syscall_trace -.ret3: adds sp=IA64_SWITCH_STACK_SIZE,sp // drop switch_stack frame +.ret5: adds sp=IA64_SWITCH_STACK_SIZE,sp // drop switch_stack frame mov rp=loc0 mov ar.pfs=loc1 mov b6=loc2 @@ -408,26 +420,14 @@ END(invoke_syscall_trace) // r15 = syscall number // b6 = syscall entry point // - .global ia64_trace_syscall .global ia64_strace_leave_kernel -GLOBAL_ENTRY(ia64_strace_clear_r8) - // this is where we return after cloning when PF_TRACESYS is on - PT_REGS_UNWIND_INFO(0) -# ifdef CONFIG_SMP - br.call.sptk.few rp=invoke_schedule_tail -# endif - mov r8=0 - br strace_check_retval -END(ia64_strace_clear_r8) - -ENTRY(ia64_trace_syscall) +GLOBAL_ENTRY(ia64_trace_syscall) PT_REGS_UNWIND_INFO(0) br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch syscall args -.ret4: br.call.sptk.few rp=b6 // do the syscall +.ret6: br.call.sptk.few rp=b6 // do the syscall strace_check_retval: -.ret5: cmp.lt p6,p0=r8,r0 // syscall failed? - ;; + cmp.lt p6,p0=r8,r0 // syscall failed? adds r2=IA64_PT_REGS_R8_OFFSET+16,sp // r2 = &pt_regs.r8 adds r3=IA64_PT_REGS_R8_OFFSET+32,sp // r3 = &pt_regs.r10 mov r10=0 @@ -438,7 +438,7 @@ strace_save_retval: .mem.offset 8,0; st8.spill [r3]=r10 // clear error indication in slot for r10 ia64_strace_leave_kernel: br.call.sptk.few rp=invoke_syscall_trace // give parent a chance to catch return value -.ret6: br.cond.sptk.many ia64_leave_kernel +.rety: br.cond.sptk.many ia64_leave_kernel strace_error: ld8 r3=[r2] // load pt_regs.r8 @@ -468,18 +468,24 @@ END(ia64_trace_syscall) #define rKRBS r22 #define rB6 r21 -GLOBAL_ENTRY(ia64_ret_from_syscall_clear_r8) +GLOBAL_ENTRY(ia64_ret_from_clone) PT_REGS_UNWIND_INFO(0) #ifdef CONFIG_SMP // In SMP mode, we need to call schedule_tail to complete the scheduling process. // Called by ia64_switch_to after do_fork()->copy_thread(). r8 contains the // address of the previously executing task. br.call.sptk.few rp=invoke_schedule_tail -.ret7: -#endif +.ret8: +#endif + adds r2=IA64_TASK_PTRACE_OFFSET,r13 + ;; + ld8 r2=[r2] + ;; mov r8=0 + tbit.nz p6,p0=r2,PT_TRACESYS_BIT +(p6) br strace_check_retval ;; // added stop bits to prevent r8 dependency -END(ia64_ret_from_syscall_clear_r8) +END(ia64_ret_from_clone) // fall through GLOBAL_ENTRY(ia64_ret_from_syscall) PT_REGS_UNWIND_INFO(0) @@ -542,6 +548,7 @@ back_from_resched: 2: // check & deliver pending signals: (p2) br.call.spnt.few rp=handle_signal_delivery +.ret9: #if defined(CONFIG_ITANIUM_ASTEP_SPECIFIC) || defined(CONFIG_IA64_SOFTSDV_HACKS) // Check for lost ticks rsm psr.i @@ -555,6 +562,7 @@ back_from_resched: ;; cmp.ge p6,p7 = r2, r0 (p6) br.call.spnt.few rp=invoke_ia64_reset_itm +.ret10: ;; ssm psr.i #endif @@ -749,8 +757,7 @@ ENTRY(invoke_schedule_tail) mov out0=r8 // Address of previous task ;; br.call.sptk.few rp=schedule_tail -.ret8: - mov ar.pfs=loc1 +.ret11: mov ar.pfs=loc1 mov rp=loc0 br.ret.sptk.many rp END(invoke_schedule_tail) @@ -766,7 +773,7 @@ ENTRY(invoke_ia64_reset_itm) ;; UNW(.body) br.call.sptk.many rp=ia64_reset_itm - ;; +.ret12: ;; mov ar.pfs=loc1 mov rp=loc0 br.ret.sptk.many rp @@ -785,8 +792,7 @@ ENTRY(invoke_do_softirq) ;; UNW(.body) br.call.sptk.few rp=do_softirq -.ret9: - mov ar.pfs=loc1 +.ret13: mov ar.pfs=loc1 mov rp=loc0 br.ret.sptk.many rp END(invoke_do_softirq) @@ -802,8 +808,7 @@ ENTRY(invoke_schedule) ;; UNW(.body) br.call.sptk.few rp=schedule -.ret10: - mov ar.pfs=loc1 +.ret14: mov ar.pfs=loc1 mov rp=loc0 br.ret.sptk.many rp END(invoke_schedule) @@ -829,8 +834,7 @@ ENTRY(handle_signal_delivery) st8 [sp]=r9,-16 // allocate space for ar.unat and save it .body br.call.sptk.few rp=ia64_do_signal -.ret11: - .restore sp +.ret15: .restore sp adds sp=16,sp // pop scratch stack space ;; ld8 r9=[sp] // load new unat from sw->caller_unat @@ -851,8 +855,7 @@ ENTRY(handle_signal_delivery) (pSys) mov out2=1 // out2==1 => we're in a syscall (pNonSys) mov out2=0 // out2==0 => not a syscall br.call.sptk.few rp=ia64_do_signal -.ret11: - // restore the switch stack (ptrace may have modified it) +.ret16: // restore the switch stack (ptrace may have modified it) DO_LOAD_SWITCH_STACK( ) br.ret.sptk.many rp #endif /* !CONFIG_IA64_NEW_UNWIND */ @@ -873,8 +876,7 @@ GLOBAL_ENTRY(sys_rt_sigsuspend) st8 [sp]=r9,-16 // allocate space for ar.unat and save it .body br.call.sptk.few rp=ia64_rt_sigsuspend -.ret12: - .restore sp +.ret17: .restore sp adds sp=16,sp // pop scratch stack space ;; ld8 r9=[sp] // load new unat from sw->caller_unat @@ -893,8 +895,7 @@ GLOBAL_ENTRY(sys_rt_sigsuspend) mov out1=in1 // sigsetsize adds out2=16,sp // out1=&sigscratch br.call.sptk.many rp=ia64_rt_sigsuspend -.ret12: - // restore the switch stack (ptrace may have modified it) +.ret18: // restore the switch stack (ptrace may have modified it) DO_LOAD_SWITCH_STACK( ) br.ret.sptk.many rp #endif /* !CONFIG_IA64_NEW_UNWIND */ @@ -912,8 +913,7 @@ ENTRY(sys_rt_sigreturn) ;; adds out0=16,sp // out0 = &sigscratch br.call.sptk.few rp=ia64_rt_sigreturn -.ret13: - adds sp=16,sp // doesn't drop pt_regs, so don't mark it as restoring sp! +.ret19: adds sp=16,sp // doesn't drop pt_regs, so don't mark it as restoring sp! PT_REGS_UNWIND_INFO(0) // instead, create a new body section with the smaller frame ;; ld8 r9=[sp] // load new ar.unat @@ -937,8 +937,7 @@ ENTRY(sys_rt_sigreturn) adds out0=16,sp // out0 = &sigscratch br.call.sptk.few rp=ia64_rt_sigreturn -.ret13: - adds r3=IA64_SWITCH_STACK_CALLER_UNAT_OFFSET+16,sp +.ret20: adds r3=IA64_SWITCH_STACK_CALLER_UNAT_OFFSET+16,sp ;; ld8 r9=[r3] // load new ar.unat mov b7=r8 @@ -957,9 +956,10 @@ GLOBAL_ENTRY(ia64_prepare_handle_unaligned) // PT_REGS_UNWIND_INFO(0) mov r16=r0 + UNW(.prologue) DO_SAVE_SWITCH_STACK br.call.sptk.few rp=ia64_handle_unaligned // stack frame setup in ivt -.ret14: +.ret21: .body DO_LOAD_SWITCH_STACK(PT_REGS_UNWIND_INFO(0)) br.cond.sptk.many rp // goes to ia64_leave_kernel END(ia64_prepare_handle_unaligned) @@ -1206,7 +1206,7 @@ sys_call_table: data8 sys_newstat // 1210 data8 sys_newlstat data8 sys_newfstat - data8 ia64_ni_syscall + data8 sys_clone2 data8 ia64_ni_syscall data8 ia64_ni_syscall // 1215 data8 ia64_ni_syscall diff --git a/arch/ia64/kernel/fw-emu.c b/arch/ia64/kernel/fw-emu.c index 9e5ec1668..c34bbaeee 100644 --- a/arch/ia64/kernel/fw-emu.c +++ b/arch/ia64/kernel/fw-emu.c @@ -240,7 +240,7 @@ sal_emulator (long index, unsigned long in1, unsigned long in2, if (index == SAL_FREQ_BASE) { switch (in1) { case SAL_FREQ_BASE_PLATFORM: - r9 = 100000000; + r9 = 200000000; break; case SAL_FREQ_BASE_INTERVAL_TIMER: diff --git a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S index f7f8d02ae..2b2a1c29e 100644 --- a/arch/ia64/kernel/gate.S +++ b/arch/ia64/kernel/gate.S @@ -120,8 +120,7 @@ back_from_setup_rbs: stf.spill [base0]=f14,32 stf.spill [base1]=f15,32 br.call.sptk.few rp=b6 // call the signal handler -.ret2: - adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp +.ret0: adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp ;; ld8 r15=[base0],(CFM_OFF-BSP_OFF) // fetch sc_ar_bsp and advance to CFM_OFF mov r14=ar.bsp diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index d0bc7687f..b2abc48a4 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -139,7 +139,7 @@ alive_msg: ;; #ifdef CONFIG_SMP (isAP) br.call.sptk.few rp=smp_callin -.ret1: +.ret0: (isAP) br.cond.sptk.few self #endif @@ -150,11 +150,10 @@ alive_msg: #ifdef CONFIG_IA64_FW_EMU // initialize PAL & SAL emulator: br.call.sptk.few rp=sys_fw_init - ;; +.ret1: #endif br.call.sptk.few rp=start_kernel -.ret2: - addl r2=@ltoff(halt_msg),gp +.ret2: addl r2=@ltoff(halt_msg),gp ;; ld8 out0=[r2] br.call.sptk.few b0=console_print diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index d58cd494e..9f611c5b0 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S @@ -170,10 +170,11 @@ ia64_ivt: * The ITLB basically does the same as the VHPT handler except * that we always insert exactly one instruction TLB entry. */ -#if 0 +#if 1 /* - * This code works, but I don't want to enable it until I have numbers - * that prove this to be a win. + * Attempt to lookup PTE through virtual linear page table. + * The speculative access will fail if there is no TLB entry + * for the L3 page table page we're trying to access. */ mov r31=pr // save predicates ;; @@ -244,10 +245,11 @@ ia64_ivt: * that we always insert exactly one data TLB entry. */ mov r16=cr.ifa // get address that caused the TLB miss -#if 0 +#if 1 /* - * This code works, but I don't want to enable it until I have numbers - * that prove this to be a win. + * Attempt to lookup PTE through virtual linear page table. + * The speculative access will fail if there is no TLB entry + * for the L3 page table page we're trying to access. */ mov r31=pr // save predicates ;; @@ -568,7 +570,7 @@ page_fault: mov r3=255 adds r15=-1024,r15 // r15 contains the syscall number---subtract 1024 - adds r2=IA64_TASK_FLAGS_OFFSET,r13 // r2 = ¤t->flags + adds r2=IA64_TASK_PTRACE_OFFSET,r13 // r2 = ¤t->ptrace ;; cmp.geu.unc p6,p7=r3,r15 // (syscall > 0 && syscall <= 1024+255) ? @@ -581,7 +583,7 @@ page_fault: ld8 r16=[r16] // load address of syscall entry point mov rp=r15 // set the real return addr ;; - ld8 r2=[r2] // r2 = current->flags + ld8 r2=[r2] // r2 = current->ptrace mov b6=r16 // arrange things so we skip over break instruction when returning: @@ -590,7 +592,7 @@ page_fault: adds r17=24,sp // get pointer to cr_iip ;; ld8 r18=[r16] // fetch cr_ipsr - tbit.z p8,p0=r2,5 // (current->flags & PF_TRACESYS) == 0? + tbit.z p8,p0=r2,PT_TRACESYS_BIT // (current->ptrace & PF_TRACESYS) == 0? ;; ld8 r19=[r17] // fetch cr_iip extr.u r20=r18,41,2 // extract ei field @@ -686,7 +688,7 @@ dispatch_illegal_op_fault: SAVE_REST ;; br.call.sptk.few rp=ia64_illegal_op_fault - ;; +.ret0: ;; alloc r14=ar.pfs,0,0,3,0 // must be first in insn group mov out0=r9 mov out1=r10 @@ -755,16 +757,16 @@ dispatch_to_ia32_handler: ld4 out5=[r14],8 // r13 == ebp ;; ld4 out3=[r14],8 // r14 == esi - adds r2=IA64_TASK_FLAGS_OFFSET,r13 // r2 = ¤t->flags + adds r2=IA64_TASK_PTRACE_OFFSET,r13 // r2 = ¤t->ptrace ;; ld4 out4=[r14] // R15 == edi movl r16=ia32_syscall_table ;; (p6) shladd r16=r8,3,r16 // Force ni_syscall if not valid syscall number - ld8 r2=[r2] // r2 = current->flags + ld8 r2=[r2] // r2 = current->ptrace ;; ld8 r16=[r16] - tbit.z p8,p0=r2,5 // (current->flags & PF_TRACESYS) == 0? + tbit.z p8,p0=r2,PT_TRACESYS_BIT // (current->ptrace & PT_TRACESYS) == 0? ;; mov b6=r16 movl r15=ia32_ret_from_syscall @@ -780,8 +782,7 @@ non_ia32_syscall: add out1=16,sp // pointer to pt_regs ;; // avoid WAW on CFM br.call.sptk.few rp=ia32_bad_interrupt - ;; - movl r15=ia64_leave_kernel +.ret1: movl r15=ia64_leave_kernel ;; mov rp=r15 br.ret.sptk.many rp diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 003b8dd69..b57d4702d 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -9,8 +9,7 @@ * Copyright (C) 1999 Silicon Graphics, Inc. * Copyright (C) Vijay Chander(vijay@engr.sgi.com) * - * 00/03/29 C. Fleckenstein Fixed PAL/SAL update issues, began MCA bug fixes, - * logging issues, + * 00/03/29 C. Fleckenstein Fixed PAL/SAL update issues, began MCA bug fixes, logging issues, * added min save state dump, added INIT handler. */ #include <linux/config.h> diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index e4a9f0530..6b714108e 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S @@ -136,8 +136,7 @@ ia64_os_mca_virtual_begin: movl r2=ia64_mca_ucmc_handler;; mov b6=r2;; br.call.sptk.few b0=b6 - ;; - +.ret0: // Revert back to physical mode before going back to SAL PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4) ia64_os_mca_virtual_end: @@ -766,7 +765,7 @@ IVirtual_Switch: ;; br.call.sptk.few rp=ia64_init_handler - ;; +.ret1: return_from_init: br.sptk return_from_init diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S index e6f44cfb6..147e2b8fe 100644 --- a/arch/ia64/kernel/pal.S +++ b/arch/ia64/kernel/pal.S @@ -74,14 +74,14 @@ GLOBAL_ENTRY(ia64_pal_call_static) mov loc3 = psr mov loc0 = rp UNW(.body) - adds r8 = .ret0-1b,r8 + adds r8 = 1f-1b,r8 ;; rsm psr.i mov b7 = loc2 mov rp = r8 ;; br.cond.sptk.few b7 -.ret0: mov psr.l = loc3 +1: mov psr.l = loc3 mov ar.pfs = loc1 mov rp = loc0 ;; @@ -116,8 +116,7 @@ GLOBAL_ENTRY(ia64_pal_call_stacked) mov b7 = loc2 ;; br.call.sptk.many rp=b7 // now make the call -.ret2: - mov psr.l = loc3 +.ret0: mov psr.l = loc3 mov ar.pfs = loc1 mov rp = loc0 ;; @@ -161,7 +160,7 @@ GLOBAL_ENTRY(ia64_pal_call_phys_static) mov r31 = in3 // copy arg3 ;; mov loc3 = psr // save psr - adds r8 = .ret4-1b,r8 // calculate return address for call + adds r8 = 1f-1b,r8 // calculate return address for call ;; mov loc4=ar.rsc // save RSE configuration dep.z loc2=loc2,0,61 // convert pal entry point to physical @@ -176,15 +175,14 @@ GLOBAL_ENTRY(ia64_pal_call_phys_static) ;; andcm r16=loc3,r16 // removes bits to clear from psr br.call.sptk.few rp=ia64_switch_mode -.ret3: - mov rp = r8 // install return address (physical) +.ret1: mov rp = r8 // install return address (physical) br.cond.sptk.few b7 -.ret4: +1: mov ar.rsc=r0 // put RSE in enforced lazy, LE mode mov r16=loc3 // r16= original psr br.call.sptk.few rp=ia64_switch_mode // return to virtual mode - -.ret5: mov psr.l = loc3 // restore init PSR +.ret2: + mov psr.l = loc3 // restore init PSR mov ar.pfs = loc1 mov rp = loc0 diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 30bfcf101..3759e52f8 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -1,8 +1,8 @@ /* * Architecture-specific setup. * - * Copyright (C) 1998, 1999 Hewlett-Packard Co - * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com> + * Copyright (C) 1998-2000 Hewlett-Packard Co + * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com> */ #define __KERNEL_SYSCALLS__ /* see <asm/unistd.h> */ #include <linux/config.h> @@ -13,6 +13,7 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/sched.h> +#include <linux/slab.h> #include <linux/smp_lock.h> #include <linux/stddef.h> #include <linux/unistd.h> @@ -204,24 +205,22 @@ ia64_load_extra (struct task_struct *task) * be copied as well. * * Observe that we copy the unat values that are in pt_regs and - * switch_stack. Since the interpretation of unat is dependent upon - * the address to which the registers got spilled, doing this is valid - * only as long as we preserve the alignment of the stack. Since the - * stack is always page aligned, we know this is the case. - * - * XXX Actually, the above isn't true when we create kernel_threads(). - * If we ever needs to create kernel_threads() that preserve the unat - * values we'll need to fix this. Perhaps an easy workaround would be - * to always clear the unat bits in the child thread. + * switch_stack. Spilling an integer to address X causes bit N in + * ar.unat to be set to the NaT bit of the register, with N=(X & + * 0x1ff)/8. Thus, copying the unat value preserves the NaT bits ONLY + * if the pt_regs structure in the parent is congruent to that of the + * child, modulo 512. Since the stack is page aligned and the page + * size is at least 4KB, this is always the case, so there is nothing + * to worry about. */ int -copy_thread (int nr, unsigned long clone_flags, unsigned long usp, +copy_thread (int nr, unsigned long clone_flags, + unsigned long user_stack_base, unsigned long user_stack_size, struct task_struct *p, struct pt_regs *regs) { unsigned long rbs, child_rbs, rbs_size, stack_offset, stack_top, stack_used; struct switch_stack *child_stack, *stack; - extern char ia64_ret_from_syscall_clear_r8; - extern char ia64_strace_clear_r8; + extern char ia64_ret_from_clone; struct pt_regs *child_ptregs; #ifdef CONFIG_SMP @@ -251,10 +250,14 @@ copy_thread (int nr, unsigned long clone_flags, unsigned long usp, /* copy the parent's register backing store to the child: */ memcpy((void *) child_rbs, (void *) rbs, rbs_size); - child_ptregs->r8 = 0; /* child gets a zero return value */ - if (user_mode(child_ptregs)) - child_ptregs->r12 = usp; /* user stack pointer */ - else { + if (user_mode(child_ptregs)) { + if (user_stack_base) { + child_ptregs->r12 = user_stack_base + user_stack_size; + child_ptregs->ar_bspstore = user_stack_base; + child_ptregs->ar_rnat = 0; + child_ptregs->loadrs = 0; + } + } else { /* * Note: we simply preserve the relative position of * the stack pointer here. There is no need to @@ -265,13 +268,10 @@ copy_thread (int nr, unsigned long clone_flags, unsigned long usp, child_ptregs->r12 = (unsigned long) (child_ptregs + 1); /* kernel sp */ child_ptregs->r13 = (unsigned long) p; /* set `current' pointer */ } - if (p->flags & PF_TRACESYS) - child_stack->b0 = (unsigned long) &ia64_strace_clear_r8; - else - child_stack->b0 = (unsigned long) &ia64_ret_from_syscall_clear_r8; + child_stack->b0 = (unsigned long) &ia64_ret_from_clone; child_stack->ar_bspstore = child_rbs + rbs_size; - /* copy the thread_struct: */ + /* copy parts of thread_struct: */ p->thread.ksp = (unsigned long) child_stack - 16; /* * NOTE: The calling convention considers all floating point @@ -288,18 +288,11 @@ copy_thread (int nr, unsigned long clone_flags, unsigned long usp, * would be a slight deviation from the normal Linux system * call behavior where scratch registers are preserved across * system calls (unless used by the system call itself). - * - * If we wanted to inherit the fph state from the parent to the - * child, we would have to do something along the lines of: - * - * if (ia64_get_fpu_owner() == current && ia64_psr(regs)->mfh) { - * p->thread.flags |= IA64_THREAD_FPH_VALID; - * ia64_save_fpu(&p->thread.fph); - * } else if (current->thread.flags & IA64_THREAD_FPH_VALID) { - * memcpy(p->thread.fph, current->thread.fph, sizeof(p->thread.fph)); - * } */ - p->thread.flags = (current->thread.flags & ~IA64_THREAD_FPH_VALID); +# define THREAD_FLAGS_TO_CLEAR (IA64_THREAD_FPH_VALID | IA64_THREAD_DBG_VALID) +# define THREAD_FLAGS_TO_SET 0 + p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) + | THREAD_FLAGS_TO_SET); return 0; } diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 0efd42bb8..ae8991c51 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -942,9 +942,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, ret = -EPERM; if (request == PTRACE_TRACEME) { /* are we already being traced? */ - if (current->flags & PF_PTRACED) + if (current->ptrace & PT_PTRACED) goto out; - current->flags |= PF_PTRACED; + current->ptrace |= PT_PTRACED; ret = 0; goto out; } @@ -976,9 +976,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) goto out_tsk; /* the same process cannot be attached many times */ - if (child->flags & PF_PTRACED) + if (child->ptrace & PT_PTRACED) goto out_tsk; - child->flags |= PF_PTRACED; + child->ptrace |= PT_PTRACED; if (child->p_pptr != current) { unsigned long flags; @@ -993,7 +993,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, goto out_tsk; } ret = -ESRCH; - if (!(child->flags & PF_PTRACED)) + if (!(child->ptrace & PT_PTRACED)) goto out_tsk; if (child->state != TASK_STOPPED) { if (request != PTRACE_KILL) @@ -1083,9 +1083,9 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, if (data > _NSIG) goto out_tsk; if (request == PTRACE_SYSCALL) - child->flags |= PF_TRACESYS; + child->ptrace |= PT_TRACESYS; else - child->flags &= ~PF_TRACESYS; + child->ptrace &= ~PT_TRACESYS; child->exit_code = data; /* make sure the single step/take-branch tra bits are not set: */ @@ -1126,7 +1126,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, if (data > _NSIG) goto out_tsk; - child->flags &= ~PF_TRACESYS; + child->ptrace &= ~PT_TRACESYS; if (request == PTRACE_SINGLESTEP) { ia64_psr(ia64_task_regs(child))->ss = 1; } else { @@ -1147,7 +1147,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, if (data > _NSIG) goto out_tsk; - child->flags &= ~(PF_PTRACED|PF_TRACESYS); + child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); child->exit_code = data; write_lock_irqsave(&tasklist_lock, flags); REMOVE_LINKS(child); @@ -1180,7 +1180,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data, void syscall_trace (void) { - if ((current->flags & (PF_PTRACED|PF_TRACESYS)) != (PF_PTRACED|PF_TRACESYS)) + if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != (PT_PTRACED|PT_TRACESYS)) return; current->exit_code = SIGTRAP; set_current_state(TASK_STOPPED); diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 09850fdd8..fcb4e6190 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -241,18 +241,18 @@ get_cpuinfo (char *buffer) sprintf(cp, " 0x%lx", mask); p += sprintf(p, - "CPU# %lu\n" - "\tvendor : %s\n" - "\tfamily : %s\n" - "\tmodel : %s\n" - "\trevision : %u\n" - "\tarchrev : %u\n" - "\tfeatures :%s\n" /* don't change this---it _is_ right! */ - "\tcpu number : %lu\n" - "\tcpu regs : %u\n" - "\tcpu MHz : %lu.%06lu\n" - "\titc MHz : %lu.%06lu\n" - "\tBogoMIPS : %lu.%02lu\n\n", + "processor : %lu\n" + "vendor : %s\n" + "family : %s\n" + "model : %s\n" + "revision : %u\n" + "archrev : %u\n" + "features :%s\n" /* don't change this---it _is_ right! */ + "cpu number : %lu\n" + "cpu regs : %u\n" + "cpu MHz : %lu.%06lu\n" + "itc MHz : %lu.%06lu\n" + "BogoMIPS : %lu.%02lu\n\n", c - cpu_data, c->vendor, family, model, c->revision, c->archrev, features, c->ppn, c->number, c->proc_freq / 1000000, c->proc_freq % 1000000, diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 8a46377c9..ca0f7a981 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c @@ -218,7 +218,7 @@ ia64_rt_sigreturn (struct sigscratch *scr) * be corrupted. */ retval = (long) &ia64_leave_kernel; - if (current->flags & PF_TRACESYS) + if (current->ptrace & PT_TRACESYS) /* * strace expects to be notified after sigreturn * returns even though the context to which we return @@ -492,7 +492,7 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) if (!signr) break; - if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; current->thread.siginfo = &info; @@ -570,7 +570,6 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) /* FALLTHRU */ default: - lock_kernel(); sigaddset(¤t->signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c index f6ae656e4..cee60fa97 100644 --- a/arch/ia64/kernel/smp.c +++ b/arch/ia64/kernel/smp.c @@ -183,7 +183,7 @@ handle_IPI(int irq, void *dev_id, struct pt_regs *regs) int wait; /* release the 'pointer lock' */ - data = smp_call_function_data; + data = (struct smp_call_struct *) smp_call_function_data; func = data->func; info = data->info; wait = data->wait; @@ -536,7 +536,7 @@ fork_by_hand(void) * Don't care about the usp and regs settings since we'll never * reschedule the forked task. */ - return do_fork(CLONE_VM|CLONE_PID, 0, 0); + return do_fork(CLONE_VM|CLONE_PID, 0, 0, 0); } /* diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c index 0ccbe24a6..a3e5242fc 100644 --- a/arch/ia64/kernel/sys_ia64.c +++ b/arch/ia64/kernel/sys_ia64.c @@ -95,7 +95,6 @@ sys_pipe (long arg0, long arg1, long arg2, long arg3, static inline unsigned long do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, unsigned long pgoff) { - long start_low, end_low, starting_region, ending_region; unsigned long loff, hoff; struct file *file = 0; /* the virtual address space that is mappable in each region: */ @@ -109,17 +108,15 @@ do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, un return addr; /* Don't permit mappings into or across the address hole in a region: */ - loff = REGION_OFFSET(addr); - hoff = loff - (REGION_SIZE - OCTANT_SIZE/2); + loff = rgn_offset(addr); + hoff = loff - (RGN_SIZE - OCTANT_SIZE/2); if ((len | loff | (loff + len)) >= OCTANT_SIZE/2 && (len | hoff | (hoff + len)) >= OCTANT_SIZE/2) return -EINVAL; /* Don't permit mappings that would cross a region boundary: */ - starting_region = REGION_NUMBER(addr); - ending_region = REGION_NUMBER(addr + len); - if (starting_region != ending_region) + if (rgn_index(addr) != rgn_index(addr + len)) return -EINVAL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c index d14ba0031..95b2b3fc3 100644 --- a/arch/ia64/kernel/time.c +++ b/arch/ia64/kernel/time.c @@ -24,7 +24,7 @@ #include <asm/system.h> extern rwlock_t xtime_lock; -extern volatile unsigned long lost_ticks; +extern unsigned long wall_jiffies; #ifdef CONFIG_IA64_DEBUG_IRQ @@ -80,7 +80,7 @@ gettimeoffset (void) return 0; #else unsigned long now = ia64_get_itc(), last_tick; - unsigned long elapsed_cycles, lost = lost_ticks; + unsigned long elapsed_cycles, lost = jiffies - wall_jiffies; last_tick = (itm.next[smp_processor_id()].count - (lost+1)*itm.delta); # if 1 @@ -101,13 +101,15 @@ do_settimeofday (struct timeval *tv) write_lock_irq(&xtime_lock); { /* - * This is revolting. We need to set the xtime.tv_usec + * This is revolting. We need to set "xtime" * correctly. However, the value in this location is - * is value at the last tick. Discover what - * correction gettimeofday would have done, and then - * undo it! + * the value at the most recent update of wall time. + * Discover what correction gettimeofday would have + * done, and then undo it! */ tv->tv_usec -= gettimeoffset(); + tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ); + while (tv->tv_usec < 0) { tv->tv_usec += 1000000; tv->tv_sec--; diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index a95b78f64..7ca1146a0 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -1428,9 +1428,15 @@ ia64_handle_unaligned(unsigned long ifa, struct pt_regs *regs) if (unalign_count > 5 && jiffies - last_time > 5*HZ) unalign_count = 0; if (++unalign_count < 5) { + char buf[200]; /* comm[] is at most 16 bytes... */ + size_t len; + last_time = jiffies; - printk("%s(%d): unaligned trap accessing %016lx (ip=%016lx)\n", - current->comm, current->pid, ifa, regs->cr_iip + ipsr->ri); + len = sprintf(buf, "%s(%d): unaligned access to 0x%016lx, ip=0x%016lx\n\r", + current->comm, current->pid, ifa, regs->cr_iip + ipsr->ri); + tty_write_message(current->tty, buf); + buf[len-1] = '\0'; /* drop '\r' */ + printk("%s", buf); /* guard against command names containing %s!! */ } } diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c index 7f3c203ad..739007a96 100644 --- a/arch/ia64/kernel/unwind.c +++ b/arch/ia64/kernel/unwind.c @@ -66,9 +66,12 @@ #define UNW_STATS 0 /* WARNING: this disabled interrupts for long time-spans!! */ #if UNW_DEBUG + static long unw_debug_level = 1; +# define debug(level,format...) if (unw_debug_level > level) printk(format) # define dprintk(format...) printk(format) # define inline #else +# define debug(level,format...) # define dprintk(format...) #endif @@ -1600,11 +1603,10 @@ find_save_locs (struct unw_frame_info *info) int have_write_lock = 0; struct unw_script *scr; - if ((info->ip & (my_cpu_data.unimpl_va_mask | 0xf)) - || REGION_NUMBER(info->ip) != REGION_KERNEL) + if ((info->ip & (my_cpu_data.unimpl_va_mask | 0xf)) || rgn_index(info->ip) != RGN_KERNEL) { /* don't let obviously bad addresses pollute the cache */ - dprintk("unwind: rejecting bad ip=0x%lx\n", info->ip); + debug(1, "unwind: rejecting bad ip=0x%lx\n", info->ip); info->rp = 0; return -1; } @@ -1647,7 +1649,7 @@ unw_unwind (struct unw_frame_info *info) /* restore the ip */ if (!info->rp) { - dprintk("unwind: failed to locate return link (ip=0x%lx)!\n", info->ip); + debug(1, "unwind: failed to locate return link (ip=0x%lx)!\n", info->ip); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } @@ -1657,7 +1659,7 @@ unw_unwind (struct unw_frame_info *info) * We don't have unwind info for the gate page, so we consider that part * of user-space for the purpose of unwinding. */ - dprintk("unwind: reached user-space (ip=0x%lx)\n", ip); + debug(1, "unwind: reached user-space (ip=0x%lx)\n", ip); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile index 882bdaed9..318e314cc 100644 --- a/arch/ia64/lib/Makefile +++ b/arch/ia64/lib/Makefile @@ -7,40 +7,26 @@ L_TARGET = lib.a -L_OBJS = __divdi3.o __divsi3.o __udivdi3.o __udivsi3.o \ - __moddi3.o __modsi3.o __umoddi3.o __umodsi3.o \ - checksum.o clear_page.o csum_partial_copy.o copy_page.o \ - copy_user.o clear_user.o memset.o strncpy_from_user.o \ - strlen.o strlen_user.o strnlen_user.o \ +L_OBJS = __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o \ + checksum.o clear_page.o csum_partial_copy.o copy_page.o \ + copy_user.o clear_user.o memcpy.o memset.o strncpy_from_user.o \ + strlen.o strlen_user.o strnlen_user.o \ flush.o do_csum.o LX_OBJS = io.o -IGNORE_FLAGS_OBJS = __divdi3.o __divsi3.o __udivdi3.o __udivsi3.o \ - __moddi3.o __modsi3.o __umoddi3.o __umodsi3.o +IGNORE_FLAGS_OBJS = __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o include $(TOPDIR)/Rules.make __divdi3.o: idiv.S $(CC) $(AFLAGS) -c -o $@ $< -__divsi3.o: idiv.S - $(CC) $(AFLAGS) -c -DSINGLE -c -o $@ $< - __udivdi3.o: idiv.S $(CC) $(AFLAGS) -c -DUNSIGNED -c -o $@ $< -__udivsi3.o: idiv.S - $(CC) $(AFLAGS) -c -DUNSIGNED -DSINGLE -c -o $@ $< - __moddi3.o: idiv.S $(CC) $(AFLAGS) -c -DMODULO -c -o $@ $< -__modsi3.o: idiv.S - $(CC) $(AFLAGS) -c -DMODULO -DSINGLE -c -o $@ $< - __umoddi3.o: idiv.S $(CC) $(AFLAGS) -c -DMODULO -DUNSIGNED -c -o $@ $< - -__umodsi3.o: idiv.S - $(CC) $(AFLAGS) -c -DMODULO -DUNSIGNED -DSINGLE -c -o $@ $< diff --git a/arch/ia64/lib/copy_user.S b/arch/ia64/lib/copy_user.S index 4a0abaed0..e13febb22 100644 --- a/arch/ia64/lib/copy_user.S +++ b/arch/ia64/lib/copy_user.S @@ -116,7 +116,7 @@ GLOBAL_ENTRY(__copy_user) cmp.lt p10,p7=COPY_BREAK,len // if len > COPY_BREAK then long copy xor tmp=src,dst // same alignment test prepare -(p10) br.cond.dptk.few long_memcpy +(p10) br.cond.dptk.few long_copy_user ;; // RAW pr.rot/p16 ? // // Now we do the byte by byte loop with software pipeline @@ -136,7 +136,7 @@ GLOBAL_ENTRY(__copy_user) // // Beginning of long mempcy (i.e. > 16 bytes) // -long_memcpy: +long_copy_user: tbit.nz p6,p7=src1,0 // odd alignement and tmp=7,tmp ;; diff --git a/arch/ia64/lib/idiv.S b/arch/ia64/lib/idiv.S index af424c41b..da96863d3 100644 --- a/arch/ia64/lib/idiv.S +++ b/arch/ia64/lib/idiv.S @@ -1,162 +1,98 @@ /* * Integer division routine. * - * Copyright (C) 1999 Hewlett-Packard Co - * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com> + * Copyright (C) 1999-2000 Hewlett-Packard Co + * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com> */ -/* Simple integer division. It uses the straight forward division - algorithm. This may not be the absolutely fastest way to do it, - but it's not horrible either. According to ski, the worst case - scenario of dividing 0xffffffffffffffff by 1 takes 133 cycles. - - An alternative would be to use an algorithm similar to the - floating point division algorithm (Newton-Raphson iteration), - but that approach is rather tricky (one has to be very careful - to get the last bit right...). - - While this algorithm is straight-forward, it does use a couple - of neat ia-64 specific tricks: - - - it uses the floating point unit to determine the initial - shift amount (shift = floor(ld(x)) - floor(ld(y))) - - - it uses predication to avoid a branch in the case where - x < y (this is what p8 is used for) - - - it uses rotating registers and the br.ctop branch to - implement a software-pipelined loop that's unrolled - twice (without any code expansion!) - - - the code is relatively well scheduled to avoid unnecessary - nops while maximizing parallelism -*/ #include <asm/asmmacro.h> -#include <asm/break.h> - .text - .psr abi64 -#ifdef __BIG_ENDIAN__ - .psr msb - .msb -#else - .psr lsb - .lsb -#endif +/* + * Compute a 64-bit unsigned integer quotient. + * + * Use reciprocal approximation and Newton-Raphson iteration to compute the + * quotient. frcpa gives 8.6 significant bits, so we need 3 iterations + * to get more than the 64 bits of precision that we need for DImode. + * + * Must use max precision for the reciprocal computations to get 64 bits of + * precision. + * + * r32 holds the dividend. r33 holds the divisor. + */ #ifdef MODULO # define OP mod -# define Q r9 -# define R r8 #else -# define OP div -# define Q r8 -# define R r9 -#endif - -#ifdef SINGLE -# define PREC si -#else -# define PREC di +# define OP div #endif #ifdef UNSIGNED -# define SGN u -# define INT_TO_FP(a,b) fma.s0 a=b,f1,f0 -# define FP_TO_INT(a,b) fcvt.fxu.trunc.s0 a=b +# define SGN u +# define INT_TO_FP(a,b) fcvt.xuf.s1 a=b +# define FP_TO_INT(a,b) fcvt.fxu.trunc.s1 a=b #else # define SGN # define INT_TO_FP(a,b) fcvt.xf a=b -# define FP_TO_INT(a,b) fcvt.fx.trunc.s0 a=b +# define FP_TO_INT(a,b) fcvt.fx.trunc.s1 a=b #endif #define PASTE1(a,b) a##b #define PASTE(a,b) PASTE1(a,b) -#define NAME PASTE(PASTE(__,SGN),PASTE(OP,PASTE(PREC,3))) +#define NAME PASTE(PASTE(__,SGN),PASTE(OP,di3)) GLOBAL_ENTRY(NAME) UNW(.prologue) - alloc r2=ar.pfs,2,6,0,8 - UNW(.save pr, r18) - mov r18=pr -#ifdef SINGLE -# ifdef UNSIGNED - zxt4 in0=in0 - zxt4 in1=in1 -# else - sxt4 in0=in0 - sxt4 in1=in1 -# endif - ;; -#endif - -#ifndef UNSIGNED - cmp.lt p6,p0=in0,r0 // x negative? - cmp.lt p7,p0=in1,r0 // y negative? + .regstk 2,0,0,0 + // Transfer inputs to FP registers. + setf.sig f8 = in0 + setf.sig f9 = in1 + UNW(.fframe 16) + UNW(.save.f 0x20) + stf.spill [sp] = f17,-16 + + // Convert the inputs to FP, to avoid FP software-assist faults. + INT_TO_FP(f8, f8) ;; -(p6) sub in0=r0,in0 // make x positive -(p7) sub in1=r0,in1 // ditto for y - ;; -#endif - - setf.sig f8=in0 - UNW(.save ar.lc, r3) + UNW(.save.f 0x10) + stf.spill [sp] = f16 UNW(.body) - - mov r3=ar.lc // save ar.lc - setf.sig f9=in1 + INT_TO_FP(f9, f9) ;; - mov Q=0 // initialize q - mov R=in0 // stash away x in a static register - mov r16=1 // r16 = 1 - INT_TO_FP(f8,f8) - cmp.eq p8,p0=0,in0 // x==0? - cmp.eq p9,p0=0,in1 // y==0? + frcpa.s1 f17, p6 = f8, f9 // y = frcpa(b) ;; - INT_TO_FP(f9,f9) -(p8) br.dpnt.few .L3 -(p9) break __IA64_BREAK_KDB // attempted division by zero (should never happen) - mov ar.ec=r0 // epilogue count = 0 + /* + * This is the magic algorithm described in Section 8.6.2 of "IA-64 + * and Elementary Functions" by Peter Markstein; HP Professional Books + * (http://www.hp.com/go/retailbooks/) + */ +(p6) fmpy.s1 f7 = f8, f17 // q = a*y +(p6) fnma.s1 f6 = f9, f17, f1 // e = -b*y + 1 ;; - getf.exp r14=f8 // r14 = exponent of x - getf.exp r15=f9 // r15 = exponent of y - mov ar.lc=r0 // loop count = 0 +(p6) fma.s1 f16 = f7, f6, f7 // q1 = q*e + q +(p6) fmpy.s1 f7 = f6, f6 // e1 = e*e ;; - sub r17=r14,r15 // r17 = (exp of x - exp y) = shift amount - cmp.ge p8,p0=r14,r15 +(p6) fma.s1 f16 = f16, f7, f16 // q2 = q1*e1 + q1 +(p6) fma.s1 f6 = f17, f6, f17 // y1 = y*e + y ;; - - .rotr y[2], mask[2] // in0 and in1 may no longer be valid after - // the first write to a rotating register! - -(p8) shl y[1]=in1,r17 // y[1] = y<<shift -(p8) shl mask[1]=r16,r17 // mask[1] = 1<<shift - -(p8) mov ar.lc=r17 // loop count = r17 +(p6) fma.s1 f6 = f6, f7, f6 // y2 = y1*e1 + y1 +(p6) fnma.s1 f7 = f9, f16, f8 // r = -b*q2 + a ;; -.L1: -(p8) cmp.geu.unc p9,p0=R,y[1]// p9 = (x >= y[1]) -(p8) shr.u mask[0]=mask[1],1 // prepare mask[0] and y[0] for next -(p8) shr.u y[0]=y[1],1 // iteration +(p6) fma.s1 f17 = f7, f6, f16 // q3 = r*y2 + q2 ;; -(p9) sub R=R,y[1] // if (x >= y[1]), subtract y[1] from x -(p9) add Q=Q,mask[1] // and set corresponding bit in q (Q) - br.ctop.dptk.few .L1 // repeated unless ar.lc-- == 0 +#ifdef MODULO + FP_TO_INT(f17, f17) // round quotient to an unsigned integer + ;; + INT_TO_FP(f17, f17) // renormalize ;; -.L2: -#ifndef UNSIGNED -# ifdef MODULO -(p6) sub R=r0,R // set sign of remainder according to x -# else -(p6) sub Q=r0,Q // set sign of quotient + fnma.s1 f17 = f17, f9, f8 // compute remainder ;; -(p7) sub Q=r0,Q -# endif #endif -.L3: - mov ar.pfs=r2 // restore ar.pfs - mov ar.lc=r3 // restore ar.lc - mov pr=r18,0xffffffffffff0000 // restore p16-p63 - br.ret.sptk.few rp + UNW(.restore sp) + ldf.fill f16 = [sp], 16 + FP_TO_INT(f8, f17) // round result to an (unsigned) integer + ;; + ldf.fill f17 = [sp] + getf.sig r8 = f8 // transfer result to result register + br.ret.sptk rp END(NAME) diff --git a/arch/ia64/lib/memcpy.S b/arch/ia64/lib/memcpy.S new file mode 100644 index 000000000..3b16916d0 --- /dev/null +++ b/arch/ia64/lib/memcpy.S @@ -0,0 +1,86 @@ +#include <asm/asmmacro.h> + +GLOBAL_ENTRY(bcopy) + .regstk 3,0,0,0 + mov r8=in0 + mov in0=in1 + ;; + mov in1=r8 +END(bcopy) + // FALL THROUGH +GLOBAL_ENTRY(memcpy) + +# define MEM_LAT 4 + +# define N MEM_LAT-1 +# define Nrot ((MEM_LAT + 7) & ~7) + +# define dst r2 +# define src r3 +# define len r9 +# define saved_pfs r10 +# define saved_lc r11 +# define saved_pr r16 +# define t0 r17 +# define cnt r18 + + UNW(.prologue) + UNW(.save ar.pfs, saved_pfs) + alloc saved_pfs=ar.pfs,3,Nrot,0,Nrot + lfetch [in1] + + .rotr val[MEM_LAT] + .rotp p[MEM_LAT] + + UNW(.save ar.lc, saved_lc) + mov saved_lc=ar.lc + + or t0=in0,in1 + UNW(.save pr, saved_pr) + mov saved_pr=pr + + UNW(.body) + + mov ar.ec=MEM_LAT + + mov r8=in0 // return dst + shr cnt=in2,3 // number of 8-byte words to copy + mov pr.rot=1<<16 + ;; + cmp.eq p6,p0=in2,r0 // zero length? + or t0=t0,in2 +(p6) br.ret.spnt.many rp // yes, return immediately + + mov dst=in0 // copy because of rotation + mov src=in1 // copy because of rotation + adds cnt=-1,cnt // br.ctop is repeat/until + ;; + and t0=0x7,t0 + mov ar.lc=cnt + ;; + cmp.ne p6,p0=t0,r0 +(p6) br.cond.spnt.few slow_memcpy + +1: +(p[0]) ld8 val[0]=[src],8 +(p[N]) st8 [dst]=val[N],8 + br.ctop.sptk.few 1b + ;; +.exit: + mov ar.lc=saved_lc + mov pr=saved_pr,0xffffffffffff0000 + mov ar.pfs=saved_pfs + br.ret.sptk.many rp + +slow_memcpy: + adds cnt=-1,in2 + ;; + mov ar.lc=cnt + ;; +1: +(p[0]) ld1 val[0]=[src],1 +(p[N]) st1 [dst]=val[N],1 + br.ctop.sptk.few 1b + br.sptk.few .exit + +END(memcpy) diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index 2a57d0ae3..026f88998 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c @@ -182,7 +182,7 @@ flush_tlb_range (struct mm_struct *mm, unsigned long start, unsigned long end) unsigned long nbits; if (mm != current->active_mm) { - /* this doesn't happen often, if at all, so it's not worth optimizing for... */ + /* this does happen, but perhaps it's not worth optimizing for? */ mm->context = 0; return; } diff --git a/arch/ia64/tools/Makefile b/arch/ia64/tools/Makefile index b3d2e74b9..0e6d78450 100644 --- a/arch/ia64/tools/Makefile +++ b/arch/ia64/tools/Makefile @@ -11,10 +11,10 @@ clean: fastdep: offsets.h @if ! cmp -s offsets.h ${TARGET}; then \ - echo "Updating ${TARGET}..."; \ + echo -e "*** Updating ${TARGET}..."; \ cp offsets.h ${TARGET}; \ else \ - echo "${TARGET} is up to date"; \ + echo "*** ${TARGET} is up to date"; \ fi # @@ -31,9 +31,11 @@ ifeq ($(CROSS_COMPILE),) offsets.h: print_offsets ./print_offsets > offsets.h -print_offsets: print_offsets.c +print_offsets: print_offsets.c FORCE_RECOMPILE $(CC) $(CFLAGS) print_offsets.c -o $@ +FORCE_RECOMPILE: + else offsets.h: print_offsets.s diff --git a/arch/ia64/tools/print_offsets.awk b/arch/ia64/tools/print_offsets.awk index 5eb8bcb63..63136aa3a 100644 --- a/arch/ia64/tools/print_offsets.awk +++ b/arch/ia64/tools/print_offsets.awk @@ -9,9 +9,10 @@ BEGIN { print " */" # # This is a cheesy hack. Make sure that - # PF_PTRACED == 1<<PF_PTRACED_BIT. + # PT_PTRACED == 1<<PT_PTRACED_BIT. # - print "#define PF_PTRACED_BIT 4" + print "#define PT_PTRACED_BIT 0" + print "#define PT_TRACESYS_BIT 1" } # look for .tab: diff --git a/arch/ia64/tools/print_offsets.c b/arch/ia64/tools/print_offsets.c index d7d7e3e6f..3a7259b09 100644 --- a/arch/ia64/tools/print_offsets.c +++ b/arch/ia64/tools/print_offsets.c @@ -49,7 +49,7 @@ tab[] = { "UNW_FRAME_INFO_SIZE", sizeof (struct unw_frame_info) }, #endif { "", 0 }, /* spacer */ - { "IA64_TASK_FLAGS_OFFSET", offsetof (struct task_struct, flags) }, + { "IA64_TASK_PTRACE_OFFSET", offsetof (struct task_struct, ptrace) }, { "IA64_TASK_SIGPENDING_OFFSET", offsetof (struct task_struct, sigpending) }, { "IA64_TASK_NEED_RESCHED_OFFSET", offsetof (struct task_struct, need_resched) }, { "IA64_TASK_PROCESSOR_OFFSET", offsetof (struct task_struct, processor) }, @@ -175,10 +175,12 @@ main (int argc, char **argv) "arch/ia64/tools/print_offsets.\n *\n */\n\n"); /* This is stretching things a bit, but entry.S needs the bit number - for PF_PTRACED and it can't include <linux/sched.h> so this seems - like a reasonably solution. At least the code won't break shoudl - PF_PTRACED ever change. */ - printf ("#define PF_PTRACED_BIT\t\t\t%u\n\n", ffs (PF_PTRACED) - 1); + for PT_PTRACED and it can't include <linux/sched.h> so this seems + like a reasonably solution. At least the code won't break in + subtle ways should PT_PTRACED ever change. Ditto for + PT_TRACESYS_BIT. */ + printf ("#define PT_PTRACED_BIT\t\t\t%u\n", ffs (PT_PTRACED) - 1); + printf ("#define PT_TRACESYS_BIT\t\t\t%u\n\n", ffs (PT_TRACESYS) - 1); for (i = 0; i < sizeof (tab) / sizeof (tab[0]); ++i) { diff --git a/arch/ia64/vmlinux.lds.S b/arch/ia64/vmlinux.lds.S index 0e2dc7aaa..5c199bc1a 100644 --- a/arch/ia64/vmlinux.lds.S +++ b/arch/ia64/vmlinux.lds.S @@ -125,6 +125,7 @@ SECTIONS /DISCARD/ : { *(.text.exit) *(.data.exit) + *(.exitcall.exit) } /* Stabs debugging sections. */ |