diff options
Diffstat (limited to 'arch')
65 files changed, 2123 insertions, 733 deletions
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile index 309a308a4..6c538f4ba 100644 --- a/arch/alpha/kernel/Makefile +++ b/arch/alpha/kernel/Makefile @@ -132,7 +132,7 @@ asm_offsets: check_asm ./check_asm > $(TOPDIR)/include/asm-alpha/asm_offsets.h check_asm: check_asm.c - gcc -o $@ $< -I$(TOPDIR)/include -D__KERNEL__ -ffixed-8 + $(HOSTCC) -o $@ $< $(CPPFLAGS) -ffixed-8 clean:: rm -f check_asm diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index d9af71414..6a2ff8a9b 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -135,10 +135,8 @@ asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent, { int error; struct file *file; - struct inode *inode; struct osf_dirent_callback buf; - lock_kernel(); error = -EBADF; file = fget(fd); if (!file) @@ -149,18 +147,8 @@ asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent, buf.count = count; buf.error = 0; - error = -ENOTDIR; - if (!file->f_op || !file->f_op->readdir) - goto out_putf; - - /* - * Get the inode's semaphore to prevent changes - * to the directory while we read it. - */ - inode = file->f_dentry->d_inode; - down(&inode->i_sem); - error = file->f_op->readdir(file, &buf, osf_filldir); - up(&inode->i_sem); + lock_kernel(); + error = vfs_readdir(file, osf_filldir, &buf); if (error < 0) goto out_putf; @@ -169,9 +157,9 @@ asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent, error = count - buf.count; out_putf: + unlock_kernel(); fput(file); out: - unlock_kernel(); return error; } diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 0df16ffa4..bb0a34f92 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -100,7 +100,7 @@ ifeq ($(CONFIG_CPU_32),y) endif endif -GCCLIB := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) +LIBGCC := $(shell $(CC) $(CFLAGS) --print-libgcc-file-name) ifeq ($(CONFIG_ARCH_A5K),y) MACHINE = a5k @@ -146,7 +146,7 @@ HEAD := arch/arm/kernel/head-$(PROCESSOR).o \ SUBDIRS += arch/arm/kernel arch/arm/mm arch/arm/lib \ arch/arm/special arch/arm/nwfpe CORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES) -LIBS := arch/arm/lib/lib.o arch/arm/lib/lib.a $(LIBS) $(GCCLIB) +LIBS := arch/arm/lib/lib.o arch/arm/lib/lib.a $(LIBS) $(LIBGCC) DRIVERS += arch/arm/special/special.a ifeq ($(CONFIG_NWFPE),y) diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index d92f2b093..fca3e8c92 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -73,7 +73,7 @@ endif all: vmlinux vmlinux: $(HEAD) $(OBJS) piggy.o vmlinux.lds - $(LD) $(ZLDFLAGS) $(HEAD) $(OBJS) piggy.o $(GCCLIB) -o vmlinux + $(LD) $(ZLDFLAGS) $(HEAD) $(OBJS) piggy.o $(LIBGCC) -o vmlinux $(HEAD): $(HEAD:.o=.S) $(CC) $(AFLAGS) -traditional -c $(HEAD:.o=.S) diff --git a/arch/i386/Makefile b/arch/i386/Makefile index 4ba71ba06..2a84bf05f 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -21,12 +21,10 @@ OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S LDFLAGS=-e stext LINKFLAGS =-T $(TOPDIR)/arch/i386/vmlinux.lds $(LDFLAGS) -CFLAGS_PIPE := -pipe +CFLAGS += -pipe # only work around strength reduction bug(s) on older gcc versions -CFLAGS_NSR := $(shell if $(CC) -march=i486 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo ""; else echo "-fno-strength-reduce"; fi) - -CFLAGS := $(CFLAGS) $(CFLAGS_PIPE) $(CFLAGS_NSR) +CFLAGS += $(shell if ! $(CC) -march=i486 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strength-reduce"; fi) # prevent gcc from keeping the stack 16 byte aligned CFLAGS += $(shell if $(CC) -mpreferred-stack-boundary=2 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mpreferred-stack-boundary=2"; fi) diff --git a/arch/i386/boot/compressed/Makefile b/arch/i386/boot/compressed/Makefile index 6e4b4998d..b4b7de133 100644 --- a/arch/i386/boot/compressed/Makefile +++ b/arch/i386/boot/compressed/Makefile @@ -33,6 +33,9 @@ bvmlinux: piggy.o $(OBJECTS) head.o: head.S $(CC) $(AFLAGS) -traditional -c head.S +misc.o: misc.c + $(CC) $(CFLAGS) -c misc.c + piggy.o: $(SYSTEM) tmppiggy=_tmp_$$$$piggy; \ rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; \ diff --git a/arch/i386/config.in b/arch/i386/config.in index 1d5c0d5f7..11a98fc58 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -47,6 +47,7 @@ if [ "$CONFIG_MK7" = "y" ]; then define_bool CONFIG_X86_TSC y define_bool CONFIG_X86_GOOD_APIC y define_bool CONFIG_X86_USE_3DNOW y + define_bool CONFIG_X86_PGE y fi if [ "$CONFIG_DEVFS_FS" = "y" ]; then diff --git a/arch/i386/defconfig b/arch/i386/defconfig index f2517c27d..aa04c3685 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -76,6 +76,10 @@ CONFIG_BINFMT_MISC=y CONFIG_PM=y CONFIG_ACPI=y # CONFIG_APM is not set + +# +# Parallel port support +# # CONFIG_PARPORT is not set # @@ -282,6 +286,7 @@ CONFIG_NET_ETHERNET=y CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set # CONFIG_DE4X5 is not set # CONFIG_TULIP is not set # CONFIG_DGRS is not set @@ -308,7 +313,7 @@ CONFIG_EEPRO100=y # CONFIG_NET_RADIO is not set # -# Token Ring driver support +# Token Ring devices # # CONFIG_TR is not set # CONFIG_NET_FC is not set diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index 4163626f4..120c861e7 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -199,13 +199,13 @@ static void show(char * str) printk(" %d",local_bh_count(i)); printk(" ]\nStack dumps:"); - for(i=0;i< smp_num_cpus;i++) { + for(i = 0; i < smp_num_cpus; i++) { unsigned long esp; - if(i==cpu) + if (i == cpu) continue; printk("\nCPU %d:",i); esp = init_tss[i].esp0; - if(esp==NULL) { + if (!esp) { /* tss->esp0 is set to NULL in cpu_init(), * it's initialized when the cpu returns to user * space. -- manfreds diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index b9e535a71..c801285eb 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -320,7 +320,7 @@ static void __init pagetable_init(void) if (vaddr >= end) break; #if CONFIG_X86_PAE - pmd = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE); + pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); set_pgd(pgd, __pgd(__pa(pmd) + 0x1)); #else pmd = (pmd_t *)pgd; diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index 7dd3caabc..24e274aa0 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -88,7 +88,7 @@ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot vmlinux: arch/$(ARCH)/vmlinux.lds arch/$(ARCH)/vmlinux.lds: arch/$(ARCH)/vmlinux.lds.S FORCE - gcc -D__ASSEMBLY__ -E -C -P -I$(HPATH) -I$(HPATH)/asm-$(ARCH) \ + $(CPP) -D__ASSEMBLY__ -C -P -I$(HPATH) -I$(HPATH)/asm-$(ARCH) \ arch/$(ARCH)/vmlinux.lds.S > $@ FORCE: ; diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c index 0c07b8dd6..0d0fac150 100644 --- a/arch/mips/kernel/sysirix.c +++ b/arch/mips/kernel/sysirix.c @@ -1,4 +1,4 @@ -/* $Id: sysirix.c,v 1.24 2000/02/05 06:47:08 ralf Exp $ +/* $Id: sysirix.c,v 1.25 2000/03/07 15:45:28 ralf Exp $ * * sysirix.c: IRIX system call emulation. * @@ -2023,12 +2023,10 @@ static int irix_filldir32(void *__buf, const char *name, int namlen, asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count, int *eob) { struct file *file; - struct inode *inode; struct irix_dirent32 *lastdirent; struct irix_dirent32_callback buf; int error; - lock_kernel(); #ifdef DEBUG_GETDENTS printk("[%s:%ld] ngetdents(%d, %p, %d, %p) ", current->comm, current->pid, fd, dirent, count, eob); @@ -2038,26 +2036,14 @@ asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count if (!file) goto out; - inode = file->f_dentry->d_inode; - if (!inode) - goto out_putf; + lock_kernel(); buf.current_dir = (struct irix_dirent32 *) dirent; buf.previous = NULL; buf.count = count; buf.error = 0; - error = -ENOTDIR; - if (!file->f_op || !file->f_op->readdir) - goto out_putf; - - /* - * Get the inode's semaphore to prevent changes - * to the directory while we read it. - */ - down(&inode->i_sem); - error = file->f_op->readdir(file, &buf, irix_filldir32); - up(&inode->i_sem); + error = vfs_readdir(file, irix_filldir32, &buf); if (error < 0) goto out_putf; error = buf.error; @@ -2079,9 +2065,9 @@ asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count error = count - buf.count; out_putf: + unlock_kernel(); fput(file); out: - unlock_kernel(); return error; } @@ -2132,12 +2118,10 @@ static int irix_filldir64(void * __buf, const char * name, int namlen, asmlinkage int irix_getdents64(int fd, void *dirent, int cnt) { struct file *file; - struct inode *inode; struct irix_dirent64 *lastdirent; struct irix_dirent64_callback buf; int error; - lock_kernel(); #ifdef DEBUG_GETDENTS printk("[%s:%d] getdents64(%d, %p, %d) ", current->comm, current->pid, fd, dirent, cnt); @@ -2146,13 +2130,7 @@ asmlinkage int irix_getdents64(int fd, void *dirent, int cnt) if (!(file = fget(fd))) goto out; - inode = file->f_dentry->d_inode; - if (!inode) - goto out_f; - - error = -ENOTDIR; - if (!file->f_op || !file->f_op->readdir) - goto out_f; + lock_kernel(); error = -EFAULT; if(!access_ok(VERIFY_WRITE, dirent, cnt)) @@ -2166,9 +2144,7 @@ asmlinkage int irix_getdents64(int fd, void *dirent, int cnt) buf.previous = NULL; buf.count = cnt; buf.error = 0; - down(&inode->i_sem); - error = file->f_op->readdir(file, &buf, irix_filldir64); - up(&inode->i_sem); + error = vfs_readdir(file, irix_filldir64, &buf); if (error < 0) goto out_f; lastdirent = buf.previous; @@ -2183,21 +2159,19 @@ asmlinkage int irix_getdents64(int fd, void *dirent, int cnt) error = cnt - buf.count; out_f: + unlock_kernel(); fput(file); out: - unlock_kernel(); return error; } asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob) { struct file *file; - struct inode *inode; struct irix_dirent64 *lastdirent; struct irix_dirent64_callback buf; int error; - lock_kernel(); #ifdef DEBUG_GETDENTS printk("[%s:%d] ngetdents64(%d, %p, %d) ", current->comm, current->pid, fd, dirent, cnt); @@ -2206,13 +2180,7 @@ asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob) if (!(file = fget(fd))) goto out; - inode = file->f_dentry->d_inode; - if (!inode) - goto out_f; - - error = -ENOTDIR; - if (!file->f_op || !file->f_op->readdir) - goto out_f; + lock_kernel(); error = -EFAULT; if(!access_ok(VERIFY_WRITE, dirent, cnt) || @@ -2228,9 +2196,7 @@ asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob) buf.previous = NULL; buf.count = cnt; buf.error = 0; - down(&inode->i_sem); - error = file->f_op->readdir(file, &buf, irix_filldir64); - up(&inode->i_sem); + error = vfs_readdir(file, irix_filldir64, &buf); if (error < 0) goto out_f; lastdirent = buf.previous; @@ -2245,9 +2211,9 @@ asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob) error = cnt - buf.count; out_f: + unlock_kernel(); fput(file); out: - unlock_kernel(); return error; } diff --git a/arch/mips64/defconfig b/arch/mips64/defconfig index c4f4ba27a..21623e01f 100644 --- a/arch/mips64/defconfig +++ b/arch/mips64/defconfig @@ -14,6 +14,7 @@ CONFIG_SGI_IP27=y # CONFIG_SGI_SN0_N_MODE is not set # CONFIG_DISCONTIGMEM is not set +# CONFIG_SMP is not set CONFIG_BOOT_ELF64=y CONFIG_ARC64=y CONFIG_COHERENT_IO=y @@ -129,7 +130,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_SD_EXTRA_DEVS=40 # CONFIG_CHR_DEV_ST is not set -CONFIG_ST_EXTRA_DEVS=2 # CONFIG_BLK_DEV_SR is not set # CONFIG_CHR_DEV_SG is not set @@ -207,6 +207,7 @@ CONFIG_NETDEVICES=y # # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set +# CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_NET_SB1000 is not set @@ -221,7 +222,7 @@ CONFIG_SGI_IOC3_ETH=y # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set -# CONFIG_NET_EISA is not set +# CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set # @@ -240,7 +241,7 @@ CONFIG_SGI_IOC3_ETH=y # CONFIG_NET_RADIO is not set # -# Token Ring driver support +# Token Ring devices # # CONFIG_TR is not set # CONFIG_NET_FC is not set @@ -328,7 +329,7 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_USB is not set # -# Filesystems +# File systems # # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set @@ -347,20 +348,17 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems @@ -369,7 +367,6 @@ CONFIG_EXT2_FS=y CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set diff --git a/arch/mips64/defconfig-ip22 b/arch/mips64/defconfig-ip22 index 4caa8e70d..a5de95ca5 100644 --- a/arch/mips64/defconfig-ip22 +++ b/arch/mips64/defconfig-ip22 @@ -159,7 +159,7 @@ CONFIG_NETDEVICES=y # CONFIG_NET_RADIO is not set # -# Token Ring driver support +# Token Ring devices # # CONFIG_TR is not set # CONFIG_NET_FC is not set diff --git a/arch/mips64/defconfig-ip27 b/arch/mips64/defconfig-ip27 index c4f4ba27a..21623e01f 100644 --- a/arch/mips64/defconfig-ip27 +++ b/arch/mips64/defconfig-ip27 @@ -14,6 +14,7 @@ CONFIG_SGI_IP27=y # CONFIG_SGI_SN0_N_MODE is not set # CONFIG_DISCONTIGMEM is not set +# CONFIG_SMP is not set CONFIG_BOOT_ELF64=y CONFIG_ARC64=y CONFIG_COHERENT_IO=y @@ -129,7 +130,6 @@ CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y CONFIG_SD_EXTRA_DEVS=40 # CONFIG_CHR_DEV_ST is not set -CONFIG_ST_EXTRA_DEVS=2 # CONFIG_BLK_DEV_SR is not set # CONFIG_CHR_DEV_SG is not set @@ -207,6 +207,7 @@ CONFIG_NETDEVICES=y # # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set +# CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_NET_SB1000 is not set @@ -221,7 +222,7 @@ CONFIG_SGI_IOC3_ETH=y # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set -# CONFIG_NET_EISA is not set +# CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set # @@ -240,7 +241,7 @@ CONFIG_SGI_IOC3_ETH=y # CONFIG_NET_RADIO is not set # -# Token Ring driver support +# Token Ring devices # # CONFIG_TR is not set # CONFIG_NET_FC is not set @@ -328,7 +329,7 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_USB is not set # -# Filesystems +# File systems # # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set @@ -347,20 +348,17 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems @@ -369,7 +367,6 @@ CONFIG_EXT2_FS=y CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/common_defconfig index 4ba96bde9..c849bac82 100644 --- a/arch/ppc/configs/common_defconfig +++ b/arch/ppc/configs/common_defconfig @@ -92,7 +92,14 @@ CONFIG_BLK_DEV_IDESCSI=y # # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_IDEPCI is not set +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_IDEPCI_SHARE_IRQ is not set +# CONFIG_BLK_DEV_IDEDMA_PCI is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_AEC6210 is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_SL82C105=y CONFIG_BLK_DEV_IDE_PMAC=y CONFIG_BLK_DEV_IDEDMA_PMAC=y @@ -194,6 +201,7 @@ CONFIG_SCSI_CONSTANTS=y # # SCSI low-level drivers # +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set @@ -249,7 +257,6 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20 CONFIG_SCSI_MESH=y CONFIG_SCSI_MESH_SYNC_RATE=5 CONFIG_SCSI_MAC53C94=y -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # # IEEE 1394 (FireWire) support @@ -266,6 +273,7 @@ CONFIG_NETDEVICES=y # # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set +# CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_ETHERTAP is not set # CONFIG_NET_SB1000 is not set @@ -389,7 +397,7 @@ CONFIG_FB_MATROX_MYSTIQUE=y CONFIG_FB_MATROX_G100=y # CONFIG_FB_MATROX_MULTIHEAD is not set CONFIG_FB_ATY=y -CONFIG_FB_ATY128=y +# CONFIG_FB_ATY128 is not set CONFIG_FB_3DFX=y # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set @@ -448,6 +456,7 @@ CONFIG_PSMOUSE=y # CONFIG_WATCHDOG is not set CONFIG_NVRAM=y # CONFIG_RTC is not set +# CONFIG_EFI_RTC is not set # # Video For Linux @@ -496,6 +505,8 @@ CONFIG_USB_OHCI=y # CONFIG_USB_STORAGE is not set # CONFIG_USB_DABUSB is not set # CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RIO500 is not set # # USB HID @@ -503,7 +514,7 @@ CONFIG_USB_OHCI=y # CONFIG_USB_HID is not set CONFIG_USB_KBD=y CONFIG_USB_MOUSE=y -# CONFIG_USB_GRAPHIRE is not set +# CONFIG_USB_WACOM is not set # CONFIG_USB_WMFORCE is not set CONFIG_INPUT_KEYBDEV=y CONFIG_INPUT_MOUSEDEV=y diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig index 4ba96bde9..c849bac82 100644 --- a/arch/ppc/defconfig +++ b/arch/ppc/defconfig @@ -92,7 +92,14 @@ CONFIG_BLK_DEV_IDESCSI=y # # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_IDEPCI is not set +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_IDEPCI_SHARE_IRQ is not set +# CONFIG_BLK_DEV_IDEDMA_PCI is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_AEC6210 is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_SL82C105=y CONFIG_BLK_DEV_IDE_PMAC=y CONFIG_BLK_DEV_IDEDMA_PMAC=y @@ -194,6 +201,7 @@ CONFIG_SCSI_CONSTANTS=y # # SCSI low-level drivers # +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set @@ -249,7 +257,6 @@ CONFIG_SCSI_NCR53C8XX_SYNC=20 CONFIG_SCSI_MESH=y CONFIG_SCSI_MESH_SYNC_RATE=5 CONFIG_SCSI_MAC53C94=y -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # # IEEE 1394 (FireWire) support @@ -266,6 +273,7 @@ CONFIG_NETDEVICES=y # # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set +# CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_ETHERTAP is not set # CONFIG_NET_SB1000 is not set @@ -389,7 +397,7 @@ CONFIG_FB_MATROX_MYSTIQUE=y CONFIG_FB_MATROX_G100=y # CONFIG_FB_MATROX_MULTIHEAD is not set CONFIG_FB_ATY=y -CONFIG_FB_ATY128=y +# CONFIG_FB_ATY128 is not set CONFIG_FB_3DFX=y # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set @@ -448,6 +456,7 @@ CONFIG_PSMOUSE=y # CONFIG_WATCHDOG is not set CONFIG_NVRAM=y # CONFIG_RTC is not set +# CONFIG_EFI_RTC is not set # # Video For Linux @@ -496,6 +505,8 @@ CONFIG_USB_OHCI=y # CONFIG_USB_STORAGE is not set # CONFIG_USB_DABUSB is not set # CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RIO500 is not set # # USB HID @@ -503,7 +514,7 @@ CONFIG_USB_OHCI=y # CONFIG_USB_HID is not set CONFIG_USB_KBD=y CONFIG_USB_MOUSE=y -# CONFIG_USB_GRAPHIRE is not set +# CONFIG_USB_WACOM is not set # CONFIG_USB_WMFORCE is not set CONFIG_INPUT_KEYBDEV=y CONFIG_INPUT_MOUSEDEV=y diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 0f7167622..73db2269e 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -98,7 +98,7 @@ ifeq ($(CONFIG_ALL_PPC),y) OX_OBJS += prep_setup.o endif ifeq ($(CONFIG_GEMINI),y) - O_OBJS += gemini_prom.o gemini_pci.o gemini_setup.o + O_OBJS += gemini_prom.o gemini_pci.o gemini_setup.o open_pic.o endif all: $(KHEAD) kernel.o @@ -114,6 +114,8 @@ ppc_defs.h: mk_defs.c ppc_defs.head \ $(TOPDIR)/include/asm/ptrace.h $(CC) $(CFLAGS) -S mk_defs.c cp ppc_defs.head ppc_defs.h +# for bk, this way we can write to the file even if it's not checked out + chmod u+w ppc_defs.h grep '^#define' mk_defs.s >> ppc_defs.h rm mk_defs.s diff --git a/arch/ppc/kernel/feature.c b/arch/ppc/kernel/feature.c index 156eb187e..d14c7380a 100644 --- a/arch/ppc/kernel/feature.c +++ b/arch/ppc/kernel/feature.c @@ -154,6 +154,9 @@ feature_init(void) { struct device_node *np; + if (_machine != _MACH_Pmac) + return; + np = find_devices("mac-io"); while (np != NULL) { /* KeyLargo contains several (5 ?) FCR registers in mac-io, diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index b6d44ecb3..dab413c15 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -222,7 +222,7 @@ __after_prom_start: mtspr IBAT0L,r8 mtspr IBAT0U,r11 #if 0 /* Useful debug code, please leave in for now so I don't have to - * look at docs when I need to setup a BAT ; + * look at docs when I need to setup a BAT ... */ bl setup_screen_bat #endif @@ -256,6 +256,8 @@ __after_prom_start: * prep needs the mmu to be turned on here, but pmac already has it on. * this shouldn't bother the pmac since it just gets turned on again * as we jump to our code at KERNELBASE. -- Cort + * Actually no, pmac doesn't have it on any more. BootX enters with MMU + * off, and in other cases, we now turn it off before changing BATs above. */ turn_on_mmu: mfmsr r0 @@ -1423,6 +1425,7 @@ start_here: li r3,MSR_KERNEL & ~(MSR_IR|MSR_DR) mtspr SRR0,r4 mtspr SRR1,r3 + SYNC rfi /* Load up the kernel context */ 2: @@ -1433,6 +1436,7 @@ start_here: tlbsync /* ... on all CPUs */ sync #endif + bl load_up_mmu /* Set up for using our exception vectors */ @@ -1448,6 +1452,7 @@ start_here: ori r3,r3,start_kernel@l mtspr SRR0,r3 mtspr SRR1,r4 + SYNC rfi /* enable MMU and jump to start_kernel */ /* @@ -1530,11 +1535,11 @@ setup_screen_bat: li r3,0 mtspr DBAT1U,r3 mtspr IBAT1U,r3 - lis r3, 0x9100 + lis r3, 0x8200 ori r4,r3,0x2a mtspr DBAT1L,r4 mtspr IBAT1L,r4 - ori r3,r3,(BL_8M<<2)|0x2 /* set up BAT registers for 604 */ + ori r3,r3,(BL_16M<<2)|0x2 /* set up BAT registers for 604 */ mtspr DBAT1U,r3 mtspr IBAT1U,r3 blr diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index ffac1871a..f8e11ecc0 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -45,7 +45,9 @@ #include <linux/pci.h> #include <linux/delay.h> #include <linux/irq.h> +#include <linux/proc_fs.h> +#include <asm/uaccess.h> #include <asm/bitops.h> #include <asm/hydra.h> #include <asm/system.h> @@ -611,3 +613,160 @@ void __global_restore_flags(unsigned long flags) } #endif /* __SMP__ */ +static struct proc_dir_entry * root_irq_dir; +static struct proc_dir_entry * irq_dir [NR_IRQS]; +static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; + +unsigned int irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = 0xffffffff}; + +#define HEX_DIGITS 8 + +static int irq_affinity_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + if (count < HEX_DIGITS+1) + return -EINVAL; + return sprintf (page, "%08x\n", irq_affinity[(int)data]); +} + +static unsigned int parse_hex_value (const char *buffer, + unsigned long count, unsigned long *ret) +{ + unsigned char hexnum [HEX_DIGITS]; + unsigned long value; + int i; + + if (!count) + return -EINVAL; + if (count > HEX_DIGITS) + count = HEX_DIGITS; + if (copy_from_user(hexnum, buffer, count)) + return -EFAULT; + + /* + * Parse the first 8 characters as a hex string, any non-hex char + * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same. + */ + value = 0; + + for (i = 0; i < count; i++) { + unsigned int c = hexnum[i]; + + switch (c) { + case '0' ... '9': c -= '0'; break; + case 'a' ... 'f': c -= 'a'-10; break; + case 'A' ... 'F': c -= 'A'-10; break; + default: + goto out; + } + value = (value << 4) | c; + } +out: + *ret = value; + return 0; +} + +static int irq_affinity_write_proc (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + int irq = (int) data, full_count = count, err; + unsigned long new_value; + + if (!irq_desc[irq].handler->set_affinity) + return -EIO; + + err = parse_hex_value(buffer, count, &new_value); + +#if CONFIG_SMP + /* + * Do not allow disabling IRQs completely - it's a too easy + * way to make the system unusable accidentally :-) At least + * one online CPU still has to be targeted. + */ + if (!(new_value & cpu_online_map)) + return -EINVAL; +#endif + + irq_affinity[irq] = new_value; + irq_desc[irq].handler->set_affinity(irq, new_value); + + return full_count; +} + +static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + unsigned long *mask = (unsigned long *) data; + if (count < HEX_DIGITS+1) + return -EINVAL; + return sprintf (page, "%08lx\n", *mask); +} + +static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + unsigned long *mask = (unsigned long *) data, full_count = count, err; + unsigned long new_value; + + err = parse_hex_value(buffer, count, &new_value); + if (err) + return err; + + *mask = new_value; + return full_count; +} + +#define MAX_NAMELEN 10 + +static void register_irq_proc (unsigned int irq) +{ + struct proc_dir_entry *entry; + char name [MAX_NAMELEN]; + + if (!root_irq_dir || (irq_desc[irq].handler == NULL)) + return; + + memset(name, 0, MAX_NAMELEN); + sprintf(name, "%d", irq); + + /* create /proc/irq/1234 */ + irq_dir[irq] = proc_mkdir(name, root_irq_dir); + + /* create /proc/irq/1234/smp_affinity */ + entry = create_proc_entry("smp_affinity", 0700, irq_dir[irq]); + + entry->nlink = 1; + entry->data = (void *)irq; + entry->read_proc = irq_affinity_read_proc; + entry->write_proc = irq_affinity_write_proc; + + smp_affinity_entry[irq] = entry; +} + +unsigned long prof_cpu_mask = -1; + +void init_irq_proc (void) +{ + struct proc_dir_entry *entry; + int i; + + /* create /proc/irq */ + root_irq_dir = proc_mkdir("irq", 0); + + /* create /proc/irq/prof_cpu_mask */ + entry = create_proc_entry("prof_cpu_mask", 0700, root_irq_dir); + + entry->nlink = 1; + entry->data = (void *)&prof_cpu_mask; + entry->read_proc = prof_cpu_mask_read_proc; + entry->write_proc = prof_cpu_mask_write_proc; + + /* + * Create entries for all existing IRQs. + */ + for (i = 0; i < NR_IRQS; i++) { + if (irq_desc[i].handler == NULL) + continue; + register_irq_proc(i); + } +} diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 8326bc369..773c99b5c 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -131,11 +131,6 @@ char __init *pcibios_setup(char *str) return str; } -int pcibios_assign_resource(struct pci_dev *pdev, int resource) -{ - return 0; -} - /* the next two are stolen from the alpha port... */ void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root, @@ -189,48 +184,3 @@ int pcibios_enable_device(struct pci_dev *dev) } return 0; } - -/* - * Assign new address to PCI resource. We hope our resource information - * is complete. We don't re-assign resources unless we are - * forced to do so. - * - * Expects start=0, end=size-1, flags=resource type. - */ - -int pci_assign_resource(struct pci_dev *dev, int i) -{ - struct resource *r = &dev->resource[i]; - struct resource *pr = pci_find_parent_resource(dev, r); - unsigned long size = r->end + 1; - u32 new, check; - - if (!pr) { - printk(KERN_ERR "PCI: Cannot find parent resource for device %s\n", dev->slot_name); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) { - if (allocate_resource(pr, r, size, 0x100, ~0, size, NULL, NULL)) { - printk(KERN_ERR "PCI: Allocation of I/O region %s/%d (%ld bytes) failed\n", dev->slot_name, i, size); - return -EBUSY; - } - } else { - if (allocate_resource(pr, r, size, 0x10000, ~0, size, NULL, NULL)) { - printk(KERN_ERR "PCI: Allocation of memory region %s/%d (%ld bytes) failed\n", dev->slot_name, i, size); - return -EBUSY; - } - } - if (i < 6) { - int reg = PCI_BASE_ADDRESS_0 + 4*i; - new = r->start | (r->flags & PCI_REGION_FLAG_MASK); - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if (new != check) - printk(KERN_ERR "PCI: Error while updating region %s/%d (%08x != %08x)\n", dev->slot_name, i, new, check); - } else if (i == PCI_ROM_RESOURCE) { - r->flags |= PCI_ROM_ADDRESS_ENABLE; - pci_write_config_dword(dev, dev->rom_base_reg, r->start | (r->flags & PCI_REGION_FLAG_MASK)); - } - printk("PCI: Assigned addresses %08lx-%08lx to region %s/%d\n", r->start, r->end, dev->slot_name, i); - return 0; -} diff --git a/arch/ppc/kernel/pmac_pic.c b/arch/ppc/kernel/pmac_pic.c index b0276ca2c..f2794ae5a 100644 --- a/arch/ppc/kernel/pmac_pic.c +++ b/arch/ppc/kernel/pmac_pic.c @@ -10,6 +10,7 @@ #include <asm/io.h> #include <asm/smp.h> #include <asm/prom.h> +#include <asm/pci-bridge.h> #include "pmac_pic.h" /* pmac */struct pmac_irq_hw { diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c index 5fef07e89..c2c4cbbf4 100644 --- a/arch/ppc/kernel/pmac_setup.c +++ b/arch/ppc/kernel/pmac_setup.c @@ -283,8 +283,6 @@ pmac_setup_arch(void) ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000) ? "enabled" : "disabled"); - feature_init(); - #ifdef CONFIG_KGDB zs_kgdb_hook(0); #endif @@ -325,14 +323,15 @@ static void __init init_p2pbridge(void) || p2pbridge->parent == NULL || strcmp(p2pbridge->parent->name, "pci") != 0) return; - if (pci_device_loc(p2pbridge, &bus, &devfn) < 0) return; - - pcibios_read_config_word(bus, devfn, PCI_BRIDGE_CONTROL, &val); + if (ppc_md.pcibios_read_config_word(bus, devfn, PCI_BRIDGE_CONTROL, &val) < 0) { + printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n"); + return; + } val &= ~PCI_BRIDGE_CTL_MASTER_ABORT; - pcibios_write_config_word(bus, devfn, PCI_BRIDGE_CONTROL, val); - pcibios_read_config_word(bus, devfn, PCI_BRIDGE_CONTROL, &val); + ppc_md.pcibios_write_config_word(bus, devfn, PCI_BRIDGE_CONTROL, val); + ppc_md.pcibios_read_config_word(bus, devfn, PCI_BRIDGE_CONTROL, &val); } static void __init ohare_init(void) @@ -703,8 +702,8 @@ pmac_progress(char *s, unsigned short hex) { if (disp_bi == 0) return; - drawstring(s); - drawchar('\n'); + prom_drawstring(s); + prom_drawchar('\n'); } #endif CONFIG_BOOTX_TEXT diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c index da46f3c1c..441310e68 100644 --- a/arch/ppc/kernel/ppc_htab.c +++ b/arch/ppc/kernel/ppc_htab.c @@ -44,12 +44,6 @@ extern unsigned long htab_evicts; extern unsigned long pte_misses; extern unsigned long pte_errors; -struct file_operations ppc_htab_operations = { - llseek: ppc_htab_lseek, - read: ppc_htab_read, - write: ppc_htab_write, -}; - /* these will go into processor.h when I'm done debugging -- Cort */ #define MMCR0 952 #define MMCR0_PMC1_CYCLES (0x1<<7) @@ -63,6 +57,12 @@ struct file_operations ppc_htab_operations = { #define PMC1 953 #define PMC2 954 +struct file_operations ppc_htab_operations = { + llseek: ppc_htab_lseek, + read: ppc_htab_read, + write: ppc_htab_write, +}; + char *pmc1_lookup(unsigned long mmcr0) { switch ( mmcr0 & (0x7f<<7) ) diff --git a/arch/ppc/kernel/prom.c b/arch/ppc/kernel/prom.c index 4ee638f62..310e301e6 100644 --- a/arch/ppc/kernel/prom.c +++ b/arch/ppc/kernel/prom.c @@ -114,9 +114,9 @@ static struct device_node *allnodes = 0; static void clearscreen(void); static void flushscreen(void); -void drawchar(char c); -void drawstring(const char *c); -static void drawhex(unsigned long v); +void prom_drawchar(char c); +void prom_drawstring(const char *c); +void prom_drawhex(unsigned long v); static void scrollscreen(void); static void draw_byte(unsigned char c, long locX, long locY); @@ -134,6 +134,8 @@ static long g_max_loc_Y = 0; static unsigned char vga_font[cmapsz]; +int bootx_text_mapped = 1; + #endif /* CONFIG_BOOTX_TEXT */ @@ -257,7 +259,7 @@ prom_print(const char *msg) { #ifdef CONFIG_BOOTX_TEXT if (RELOC(disp_bi) != 0) - drawstring(msg); + prom_drawstring(msg); #endif return; } @@ -385,6 +387,7 @@ prom_init(int r3, int r4, prom_entry pp) #ifdef CONFIG_BOOTX_TEXT prom_print(RELOC("booting...\n")); flushscreen(); + RELOC(bootx_text_mapped) = 0; #endif return phys; } @@ -633,6 +636,7 @@ prom_init(int r3, int r4, prom_entry pp) prom_welcome(PTRRELOC(RELOC(disp_bi)), phys); prom_print(RELOC("booting...\n")); } + RELOC(bootx_text_mapped) = 0; #endif return phys; @@ -648,28 +652,30 @@ prom_welcome(boot_infos_t* bi, unsigned long phys) prom_print(RELOC("Welcome to Linux, kernel " UTS_RELEASE "\n")); prom_print(RELOC("\nstarted at : 0x")); - drawhex(phys); + prom_drawhex(phys); prom_print(RELOC("\nlinked at : 0x")); - drawhex(KERNELBASE); + prom_drawhex(KERNELBASE); prom_print(RELOC("\nframe buffer at : 0x")); - drawhex((unsigned long)bi->dispDeviceBase); + prom_drawhex((unsigned long)bi->dispDeviceBase); prom_print(RELOC(" (phys), 0x")); - drawhex((unsigned long)bi->logicalDisplayBase); + prom_drawhex((unsigned long)bi->logicalDisplayBase); prom_print(RELOC(" (log)")); + prom_print(RELOC("\nklimit : 0x")); + prom_drawhex(RELOC(klimit)); prom_print(RELOC("\nMSR : 0x")); __asm__ __volatile__ ("mfmsr %0" : "=r" (flags)); - drawhex(flags); + prom_drawhex(flags); __asm__ __volatile__ ("mfspr %0, 287" : "=r" (pvr)); pvr >>= 16; if (pvr > 1) { prom_print(RELOC("\nHID0 : 0x")); __asm__ __volatile__ ("mfspr %0, 1008" : "=r" (flags)); - drawhex(flags); + prom_drawhex(flags); } if (pvr == 8 || pvr == 12) { prom_print(RELOC("\nICTC : 0x")); __asm__ __volatile__ ("mfspr %0, 1019" : "=r" (flags)); - drawhex(flags); + prom_drawhex(flags); } prom_print(RELOC("\n\n")); } @@ -807,13 +813,18 @@ setup_disp_fake_bi(ihandle dp) prom_print(RELOC("Initializing fake screen\n")); - call_prom(RELOC("getprop"), 4, 1, dp, RELOC("width"), &width, sizeof(width)); - call_prom(RELOC("getprop"), 4, 1, dp, RELOC("height"), &height, sizeof(height)); - call_prom(RELOC("getprop"), 4, 1, dp, RELOC("depth"), &len, sizeof(len)); + call_prom(RELOC("getprop"), 4, 1, dp, RELOC("width"), + &width, sizeof(width)); + call_prom(RELOC("getprop"), 4, 1, dp, RELOC("height"), + &height, sizeof(height)); + call_prom(RELOC("getprop"), 4, 1, dp, RELOC("depth"), + &depth, sizeof(depth)); pitch = width * ((depth + 7) / 8); - call_prom(RELOC("getprop"), 4, 1, dp, RELOC("linebytes"), &len, sizeof(len)); + call_prom(RELOC("getprop"), 4, 1, dp, RELOC("linebytes"), + &pitch, sizeof(pitch)); address = 0; - call_prom(RELOC("getprop"), 4, 1, dp, RELOC("address"), &len, sizeof(len)); + call_prom(RELOC("getprop"), 4, 1, dp, RELOC("address"), + &address, sizeof(address)); if (address == 0) { prom_print(RELOC("Failed to get address\n")); return; @@ -837,7 +848,6 @@ setup_disp_fake_bi(ihandle dp) bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0; bi->dispDeviceRect[2] = width; bi->dispDeviceRect[3] = height; - RELOC(disp_bi) = 0; } #endif @@ -1844,6 +1854,7 @@ map_bootx_text(void) disp_bi->logicalDisplayBase = ioremap((unsigned long) disp_bi->dispDeviceBase, disp_bi->dispDeviceRowBytes * disp_bi->dispDeviceRect[3]); + bootx_text_mapped = 1; } /* Calc the base address of a given point (x,y) */ @@ -1940,11 +1951,14 @@ scrollscreen(void) __pmac void -drawchar(char c) +prom_drawchar(char c) { unsigned long offset = reloc_offset(); int cline = 0, x; + if (!RELOC(bootx_text_mapped)) + return; + switch (c) { case '\b': if (RELOC(g_loc_X) > 0) @@ -1988,27 +2002,33 @@ drawchar(char c) __pmac void -drawstring(const char *c) +prom_drawstring(const char *c) { + unsigned long offset = reloc_offset(); + + if (!RELOC(bootx_text_mapped)) + return; while (*c) - drawchar(*c++); + prom_drawchar(*c++); } __pmac -static void -drawhex(unsigned long v) +void +prom_drawhex(unsigned long v) { static char hex_table[] = "0123456789abcdef"; unsigned long offset = reloc_offset(); - drawchar(RELOC(hex_table)[(v >> 28) & 0x0000000FUL]); - drawchar(RELOC(hex_table)[(v >> 24) & 0x0000000FUL]); - drawchar(RELOC(hex_table)[(v >> 20) & 0x0000000FUL]); - drawchar(RELOC(hex_table)[(v >> 16) & 0x0000000FUL]); - drawchar(RELOC(hex_table)[(v >> 12) & 0x0000000FUL]); - drawchar(RELOC(hex_table)[(v >> 8) & 0x0000000FUL]); - drawchar(RELOC(hex_table)[(v >> 4) & 0x0000000FUL]); - drawchar(RELOC(hex_table)[(v >> 0) & 0x0000000FUL]); + if (!RELOC(bootx_text_mapped)) + return; + prom_drawchar(RELOC(hex_table)[(v >> 28) & 0x0000000FUL]); + prom_drawchar(RELOC(hex_table)[(v >> 24) & 0x0000000FUL]); + prom_drawchar(RELOC(hex_table)[(v >> 20) & 0x0000000FUL]); + prom_drawchar(RELOC(hex_table)[(v >> 16) & 0x0000000FUL]); + prom_drawchar(RELOC(hex_table)[(v >> 12) & 0x0000000FUL]); + prom_drawchar(RELOC(hex_table)[(v >> 8) & 0x0000000FUL]); + prom_drawchar(RELOC(hex_table)[(v >> 4) & 0x0000000FUL]); + prom_drawchar(RELOC(hex_table)[(v >> 0) & 0x0000000FUL]); } diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 5a57ba8a2..73a6c2bf7 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -29,6 +29,7 @@ #endif #include <asm/bootx.h> #include <asm/machdep.h> +#include <asm/feature.h> #ifdef CONFIG_OAK #include "oak_setup.h" #endif /* CONFIG_OAK */ @@ -417,7 +418,7 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { parse_bootinfo(); - + if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100); #if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) @@ -687,6 +688,7 @@ void __init setup_arch(char **cmdline_p) ppc_md.setup_arch(); if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); + paging_init(); } void ppc_generic_ide_fix_driveid(struct hd_driveid *id) @@ -733,12 +735,12 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id) id->eide_dma_time = __le16_to_cpu(id->eide_dma_time); id->eide_pio = __le16_to_cpu(id->eide_pio); id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy); - for (i=0; i<2 i++) + for (i=0; i<2; i++) id->words69_70[i] = __le16_to_cpu(id->words69_70[i]); - for (i=0; i<4 i++) + for (i=0; i<4; i++) id->words71_74[i] = __le16_to_cpu(id->words71_74[i]); id->queue_depth = __le16_to_cpu(id->queue_depth); - for (i=0; i<4 i++) + for (i=0; i<4; i++) id->words76_79[i] = __le16_to_cpu(id->words76_79[i]); id->major_rev_num = __le16_to_cpu(id->major_rev_num); id->minor_rev_num = __le16_to_cpu(id->minor_rev_num); diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 2faccd042..eaa5924a2 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -961,8 +961,9 @@ void __init MMU_init(void) } #endif #if 0 - setbat(0, disp_bi->dispDeviceBase, disp_bi->dispDeviceBase, 0x100000, IO_PAGE); - disp_bi->logicalDisplayBase = disp_bi->dispDeviceBase; +// This is bogus, BAT must be aligned. +// setbat(0, disp_bi->dispDeviceBase, disp_bi->dispDeviceBase, 0x100000, IO_PAGE); +// disp_bi->logicalDisplayBase = disp_bi->dispDeviceBase; #endif ioremap_base = 0xf0000000; break; diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c index 8e924699f..95b19ba47 100644 --- a/arch/ppc/xmon/start.c +++ b/arch/ppc/xmon/start.c @@ -17,12 +17,12 @@ static volatile unsigned char *sccc, *sccd; unsigned long TXRDY, RXRDY; extern void xmon_printf(const char *fmt, ...); -extern void drawchar(char); -extern void drawstring(const char *str); +extern void prom_drawchar(char); +extern void prom_drawstring(const char *str); static int xmon_expect(const char *str, unsigned int timeout); static int console = 0; -static int use_screen = 0; +static int use_screen = 1; /* default */ static int via_modem = 0; static int xmon_use_sccb = 0; static struct device_node *macio_node; @@ -48,6 +48,8 @@ xmon_map_scc(void) { volatile unsigned char *base; + use_screen = 0; + if ( _machine == _MACH_Pmac ) { struct device_node *np; @@ -58,7 +60,7 @@ xmon_map_scc(void) /* needs to be hacked if xmon_printk is to be used from within find_via_pmu() */ if (!via_modem && disp_bi && find_via_pmu()) { - drawstring("xmon uses screen and keyboard\n"); + prom_drawstring("xmon uses screen and keyboard\n"); use_screen = 1; return; } @@ -122,7 +124,7 @@ xmon_write(void *handle, void *ptr, int nb) if (use_screen) { /* write it on the screen */ for (i = 0; i < nb; ++i) - drawchar(*p++); + prom_drawchar(*p++); return nb; } #endif @@ -142,6 +144,7 @@ xmon_write(void *handle, void *ptr, int nb) ct = 1; --i; } else { + prom_drawchar(c); if (console) printk("%c", c); ct = 0; @@ -187,15 +190,15 @@ xmon_get_pmu_key(void) do { if (--t < 0) { on = 1 - on; - drawchar(on? 0xdb: 0x20); - drawchar('\b'); + prom_drawchar(on? 0xdb: 0x20); + prom_drawchar('\b'); t = 200000; } pmu_poll(); } while (xmon_pmu_keycode == -1); k = xmon_pmu_keycode; if (on) - drawstring(" \b"); + prom_drawstring(" \b"); /* test for shift keys */ if ((k & 0x7f) == 0x38 || (k & 0x7f) == 0x7b) { @@ -284,6 +287,8 @@ xmon_init_scc() { int i, x; + if (macio_node != 0) + feature_set(macio_node, FEATURE_Serial_enable); if (via_modem && macio_node != 0) { unsigned int t0; @@ -399,15 +404,12 @@ int xmon_expect(const char *str, unsigned int timeout) for (;;) { c = xmon_read_poll(); if (c == -1) { - if (readtb() - t0 > timeout) { - printk("timeout\n"); + if (readtb() - t0 > timeout) return 0; - } continue; } if (c == '\n') break; - printk("%c", c); if (c != '\r' && lineptr < &line[sizeof(line) - 1]) *lineptr++ = c; } diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c index d18d74dfd..620df9aea 100644 --- a/arch/ppc/xmon/xmon.c +++ b/arch/ppc/xmon/xmon.c @@ -119,7 +119,8 @@ void xmon(struct pt_regs *excp) { struct pt_regs regs; - int msr, cmd; + int msr, cmd, i; + unsigned *sp; if (excp == NULL) { asm volatile ("stw 0,0(%0)\n\ @@ -135,6 +136,29 @@ xmon(struct pt_regs *excp) excp = ®s; } + prom_drawstring("xmon pc="); prom_drawhex(excp->nip); + prom_drawstring(" lr="); prom_drawhex(excp->link); + prom_drawstring(" msr="); prom_drawhex(excp->msr); + prom_drawstring(" trap="); prom_drawhex(excp->trap); + prom_drawstring(" sp="); prom_drawhex(excp->gpr[1]); + sp = &excp->gpr[0]; + for (i = 0; i < 32; ++i) { + if ((i & 7) == 0) + prom_drawstring("\n"); + prom_drawstring(" "); + prom_drawhex(sp[i]); + } + sp = (unsigned *) excp->gpr[1]; + for (i = 0; i < 64; ++i) { + if ((i & 7) == 0) { + prom_drawstring("\n"); + prom_drawhex(sp); + prom_drawstring(" "); + } + prom_drawstring(" "); + prom_drawhex(sp[i]); + } + prom_drawstring("\n"); msr = get_msr(); set_msr(msr & ~0x8000); /* disable interrupts */ remove_bpts(); @@ -521,7 +545,7 @@ void excprint(struct pt_regs *fp) { printf("vector: %x at pc = %x %s", - fp->trap, fp->nip,/* pretty_lookup_name(fp->nip)*/""); + fp->trap, fp->nip, pretty_lookup_name(fp->nip)); printf(", msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp); if (fp->trap == 0x300 || fp->trap == 0x600) @@ -1390,6 +1414,10 @@ static char *lookup_name(unsigned long addr) if ( !sysmap || !sysmap_size ) return NULL; + /* adjust if addr is relative to kernelbase */ + if ( addr < PAGE_OFFSET ) + addr += PAGE_OFFSET; + cmp = simple_strtoul(c, &c, 8); strcpy( last, strsep( &c, "\n")); while ( c < (sysmap+sysmap_size) ) diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 31fcf5d69..83591c86c 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.1 1999/09/18 16:55:51 gniibe Exp gniibe $ +# $Id: Makefile,v 1.2 1999/12/23 12:13:53 gniibe Exp gniibe $ # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive @@ -15,21 +15,21 @@ # # Select the object file format to substitute into the linker script. # -tool-prefix = sh-elf +tool-prefix = sh-linux-gnu- ifdef CONFIG_LITTLE_ENDIAN CFLAGS += -ml AFLAGS += -ml # LINKFLAGS += -EL LDFLAGS := -EL - -LD =$(CROSS_COMPILE)ld $(LDFLAGS) - endif -ifdef CONFIG_CROSSCOMPILE +# ifdef CONFIG_CROSSCOMPILE CROSS_COMPILE = $(tool-prefix) -endif +# endif + +LD =$(CROSS_COMPILE)ld $(LDFLAGS) +OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S MODFLAGS += @@ -51,7 +51,7 @@ endif # none has been choosen above. # LINKSCRIPT = arch/sh/vmlinux.lds -LINKFLAGS += -T $(word 1,$(LINKSCRIPT)) -e __stext +LINKFLAGS += -T $(word 1,$(LINKSCRIPT)) -e _stext ifdef LOADADDR LINKFLAGS += -Ttext $(word 1,$(LOADADDR)) @@ -73,7 +73,7 @@ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot vmlinux: arch/sh/vmlinux.lds arch/sh/vmlinux.lds: arch/sh/vmlinux.lds.S FORCE - gcc -E -C -P -I$(HPATH) -Ush arch/sh/vmlinux.lds.S >arch/sh/vmlinux.lds + $(CPP) -C -P -I$(HPATH) -Ush arch/sh/vmlinux.lds.S >arch/sh/vmlinux.lds FORCE: ; diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile index e2ae36bde..8c087beb1 100644 --- a/arch/sh/boot/Makefile +++ b/arch/sh/boot/Makefile @@ -1,5 +1,5 @@ # -# arch/mips/boot/Makefile +# arch/sh/boot/Makefile # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive diff --git a/arch/sh/config.in b/arch/sh/config.in index 6471e7aa8..8b74eeafa 100644 --- a/arch/sh/config.in +++ b/arch/sh/config.in @@ -4,6 +4,10 @@ # mainmenu_name "Linux/SuperH Kernel Configuration" +define_bool CONFIG_SUPERH y + +define_bool CONFIG_UID16 y + mainmenu_option next_comment comment 'Code maturity level options' bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL @@ -29,7 +33,6 @@ if [ "$CONFIG_CPU_SUBTYPE_SH7750" = "y" ]; then fi bool 'Little Endian' CONFIG_LITTLE_ENDIAN hex 'Physical memory start address' CONFIG_MEMORY_START 08000000 -bool 'Use SH CPU internal real time clock' CONFIG_SH_CPU_RTC endmenu mainmenu_option next_comment @@ -43,63 +46,139 @@ endmenu mainmenu_option next_comment comment 'General setup' + bool 'Networking support' CONFIG_NET + +bool 'Directy Connected Compact Flash support' CONFIG_CF_ENABLER + +bool 'PCI support' CONFIG_PCI +if [ "$CONFIG_PCI" = "y" ]; then + choice ' PCI access mode' \ + "BIOS CONFIG_PCI_GOBIOS \ + Direct CONFIG_PCI_GODIRECT \ + Any CONFIG_PCI_GOANY" Any + if [ "$CONFIG_PCI_GOBIOS" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then + define_bool CONFIG_PCI_BIOS y + fi + if [ "$CONFIG_PCI_GODIRECT" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then + define_bool CONFIG_PCI_DIRECT y + fi +fi + +source drivers/pci/Config.in + +bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG + +if [ "$CONFIG_HOTPLUG" = "y" ] ; then + source drivers/pcmcia/Config.in +fi + bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT bool 'Sysctl support' CONFIG_SYSCTL - if [ "$CONFIG_PROC_FS" = "y" ]; then choice 'Kernel core (/proc/kcore) format' \ "ELF CONFIG_KCORE_ELF \ A.OUT CONFIG_KCORE_AOUT" ELF fi - tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC -endmenu -mainmenu_option next_comment -comment 'Character devices' -define_bool CONFIG_SERIAL n -define_bool CONFIG_SERIAL_CONSOLE y -bool 'SuperH SCI support' CONFIG_SH_SCI_SERIAL -bool 'SuperH SCIF support' CONFIG_SH_SCIF_SERIAL +source drivers/parport/Config.in + endmenu -mainmenu_option next_comment -comment 'Floppy, IDE, and other block devices' +source drivers/block/Config.in -tristate 'RAM disk support' CONFIG_BLK_DEV_RAM -if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then - bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD +if [ "$CONFIG_NET" = "y" ]; then + source net/Config.in fi -tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP -tristate 'Network block device support' CONFIG_BLK_DEV_NBD +mainmenu_option next_comment +comment 'SCSI support' + +tristate 'SCSI support' CONFIG_SCSI + +if [ "$CONFIG_SCSI" != "n" ]; then + source drivers/scsi/Config.in +fi endmenu +source drivers/ieee1394/Config.in + if [ "$CONFIG_NET" = "y" ]; then - source net/Config.in mainmenu_option next_comment - comment 'Network device drivers' + comment 'Network device support' + + bool 'Network device support' CONFIG_NETDEVICES + if [ "$CONFIG_NETDEVICES" = "y" ]; then source drivers/net/Config.in + if [ "$CONFIG_ATM" = "y" ]; then + source drivers/atm/Config.in + fi + fi endmenu fi mainmenu_option next_comment +comment 'Character devices' + +bool 'Virtual terminal' CONFIG_VT +if [ "$CONFIG_VT" = "y" ]; then + bool ' Support for console on virtual terminal' CONFIG_VT_CONSOLE +fi + +tristate 'Serial support' CONFIG_SERIAL +if [ "$CONFIG_SERIAL" = "y" -o "$CONFIG_SERIAL" = "m" ]; then + choice 'Serial interface type' \ + "SCI CONFIG_SH_SCI_SERIAL \ + SCIF CONFIG_SH_SCIF_SERIAL" +fi +if [ "$CONFIG_SERIAL" = "y" ]; then + bool ' Support for console on serial port' CONFIG_SERIAL_CONSOLE +fi comment 'Unix 98 PTY support' bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 fi +if [ "$CONFIG_PARPORT" != "n" ]; then + dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT + if [ "$CONFIG_PRINTER" != "n" ]; then + bool ' Support for console on line printer' CONFIG_LP_CONSOLE + fi + dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT +fi endmenu +if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then + source drivers/char/pcmcia/Config.in +fi + +source drivers/misc/Config.in + source fs/Config.in +if [ "$CONFIG_VT" = "y" ]; then + mainmenu_option next_comment + comment 'Console drivers' + bool 'VGA text console' CONFIG_VGA_CONSOLE + bool 'Video mode selection support' CONFIG_VIDEO_SELECT + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE + source drivers/video/Config.in + fi + endmenu +fi + + mainmenu_option next_comment -comment 'Watchdog' +comment 'Sound' -tristate 'Software watchdog' CONFIG_SOFT_WATCHDOG +tristate 'Sound card support' CONFIG_SOUND +if [ "$CONFIG_SOUND" != "n" ]; then + source drivers/sound/Config.in +fi endmenu mainmenu_option next_comment diff --git a/arch/sh/defconfig b/arch/sh/defconfig index 37440e7c0..5fabcdedc 100644 --- a/arch/sh/defconfig +++ b/arch/sh/defconfig @@ -1,6 +1,8 @@ # # Automatically generated make config: don't edit # +CONFIG_SUPERH=y +CONFIG_UID16=y # # Code maturity level options @@ -17,7 +19,6 @@ CONFIG_CPU_SH3=y # CONFIG_CPU_SH4 is not set CONFIG_LITTLE_ENDIAN=y CONFIG_MEMORY_START=0c000000 -CONFIG_SH_CPU_RTC=y # # Loadable module support @@ -28,6 +29,9 @@ CONFIG_SH_CPU_RTC=y # General setup # # CONFIG_NET is not set +CONFIG_CF_ENABLER=y +# CONFIG_PCI is not set +# CONFIG_HOTPLUG is not set # CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_SYSCTL is not set @@ -35,22 +39,56 @@ CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set +# CONFIG_PARPORT is not set # -# Character devices +# Block devices # -# CONFIG_SERIAL is not set -CONFIG_SERIAL_CONSOLE=y -CONFIG_SH_SCI_SERIAL=y -# CONFIG_SH_SCIF_SERIAL is not set +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set # -# Floppy, IDE, and other block devices +# IDE chipset support/bugfixes # +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_IDE_CHIPSETS is not set + +# +# Additional Block Devices +# +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_MD is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_INITRD=y -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL=y +CONFIG_SH_SCI_SERIAL=y +# CONFIG_SH_SCIF_SERIAL is not set +CONFIG_SERIAL_CONSOLE=y # # Unix 98 PTY support @@ -58,16 +96,20 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_UNIX98_PTYS is not set # +# Misc devices +# + +# # Filesystems # # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set # CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set # CONFIG_FAT_FS is not set +# CONFIG_CRAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set -# CONFIG_UDF_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set @@ -75,6 +117,7 @@ CONFIG_PROC_FS=y # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set # CONFIG_UFS_FS is not set # @@ -82,14 +125,12 @@ CONFIG_EXT2_FS=y # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_SGI_PARTITION is not set -# CONFIG_SUN_PARTITION is not set # CONFIG_NLS is not set # -# Watchdog +# Sound # -# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_SOUND is not set # # Kernel hacking diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 6cf0b319e..efa2fb109 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -11,10 +11,19 @@ O_TARGET := kernel.o O_OBJS := process.o signal.o entry.o traps.o irq.o irq_onchip.o \ - ptrace.o setup.o time.o sys_sh.o semaphore.o + ptrace.o setup.o time.o sys_sh.o semaphore.o pci-sh.o \ + irq_imask.o OX_OBJS := sh_ksyms.o MX_OBJS := +ifdef CONFIG_CF_ENABLER +O_OBJS += cf-enabler.o +endif + +ifdef CONFIG_CPU_SH4 +O_OBJS += fpu.o +endif + all: kernel.o head.o init_task.o entry.o: entry.S diff --git a/arch/sh/kernel/cf-enabler.c b/arch/sh/kernel/cf-enabler.c new file mode 100644 index 000000000..80dc511b3 --- /dev/null +++ b/arch/sh/kernel/cf-enabler.c @@ -0,0 +1,30 @@ +/* $Id: cf-enabler.c,v 1.2 1999/12/20 10:14:40 gniibe Exp $ + * + * linux/drivers/block/cf-enabler.c + * + * Copyright (C) 1999 Niibe Yutaka + * + * Enable the CF configuration. + */ + +#include <linux/init.h> + +#include <asm/io.h> +#include <asm/irq.h> + +#define CF_CIS_BASE 0xb8000000 +/* + * 0xB8000000 : Attribute + * 0xB8001000 : Common Memory + * 0xBA000000 : I/O + */ + +int __init cf_init(void) +{ + outw(0x0042, CF_CIS_BASE+0x0200); + make_imask_irq(14); + disable_irq(14); + return 0; +} + +__initcall (cf_init); diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S index a3e5a918c..77bb7938b 100644 --- a/arch/sh/kernel/entry.S +++ b/arch/sh/kernel/entry.S @@ -1,8 +1,8 @@ -/* $Id: entry.S,v 1.19 1999/10/31 13:19:35 gniibe Exp gniibe $ +/* $Id: entry.S,v 1.55 2000/03/05 01:48:58 gniibe Exp $ * * linux/arch/sh/entry.S * - * Copyright (C) 1999 Niibe Yutaka + * Copyright (C) 1999, 2000 Niibe Yutaka * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -54,7 +54,8 @@ sigpending = 8 addr_limit = 12 need_resched = 20 -PF_TRACESYS = 0x20 +PF_TRACESYS = 0x00000020 +PF_USEDFPU = 0x00100000 ENOSYS = 38 @@ -207,37 +208,10 @@ error: 1: .long SYMBOL_NAME(do_exception_error) 2: .long 0xefffffff ! BL=0 -reschedule: - mova SYMBOL_NAME(ret_from_syscall),r0 - mov.l 1f,r1 - jmp @r1 - lds r0,pr - .balign 4 -1: .long SYMBOL_NAME(schedule) - badsys: mov #-ENOSYS,r0 rts ! go to ret_from_syscall.. mov.l r0,@(R0,r15) -signal_return: - ! We can reach here from an interrupt handler, - ! so, we need to unblock interrupt. - /* STI */ - mov.l 1f,r1 - stc sr,r0 - and r1,r0 - ldc r0,sr - ! - mov r15,r4 - mov #0,r5 - mov.l 2f,r1 - mova restore_all,r0 - jmp @r1 - lds r0,pr - .balign 4 -1: .long 0xefffffff ! BL=0 -2: .long SYMBOL_NAME(do_signal) - ! ! ! @@ -274,7 +248,7 @@ system_call: ldc r2,sr ! mov.l __n_sys,r1 - cmp/ge r1,r0 + cmp/hs r1,r0 bt/s badsys mov r0,r2 ! @@ -329,6 +303,9 @@ system_call: 3: .long SYMBOL_NAME(syscall_trace) 2: .long 0xefffffff ! BL=0 1: .long TRA +__n_sys: .long NR_syscalls +__sct: .long SYMBOL_NAME(sys_call_table) +__tsk_flags: .long flags-8192 ! offset from stackbase to tsk->flags led: .long 0xa8000000 ! For my board -- gN .section .fixup,"ax" @@ -343,30 +320,57 @@ fixup_syscall_argerr: .long 8b,fixup_syscall_argerr .previous +reschedule: + mova SYMBOL_NAME(ret_from_syscall),r0 + mov.l 1f,r1 + jmp @r1 + lds r0,pr + .balign 4 +1: .long SYMBOL_NAME(schedule) ENTRY(ret_from_irq) - mov.l @(SR,r15),r0 ! get original stack + mov.l @(SR,r15),r0 ! get status register shll r0 shll r0 ! kernel space? bt restore_all ! Yes, it's from kernel, go back soon - ! XXX: Is it better to run through bottom half? - ! In such a case, we should go "ret_from_syscall" instead + ! STI + mov.l 1f, $r1 + stc $sr, $r2 + and $r1, $r2 + ldc $r2, $sr + ! bra ret_with_reschedule nop +ENTRY(ret_from_exception) + mov.l @(SR,r15),r0 ! get status register + shll r0 + shll r0 ! kernel space? + bt restore_all ! Yes, it's from kernel, go back soon + ! STI + mov.l 1f, $r1 + stc $sr, $r2 + and $r1, $r2 + ldc $r2, $sr + ! + bra ret_from_syscall + nop + .balign 4 +1: .long 0xefffffff ! BL=0 + + .balign 4 ret: add r8,r15 ! pop off the arguments mov.l r0,@(R0,r15) ! save the return value /* fall through */ ENTRY(ret_from_syscall) - mov.l __bh_mask,r0 + mov.l __softirq_state,r0 mov.l @r0,r1 - mov.l __bh_active,r0 - mov.l @r0,r2 + mov.l @(4,r0),r2 tst r2,r1 bt ret_with_reschedule -handle_bottom_half: - mov.l __dbh,r0 +handle_softirq: + mov.l __do_softirq,r0 jsr @r0 nop ret_with_reschedule: @@ -378,11 +382,44 @@ ret_with_reschedule: bf reschedule mov.l @(sigpending,r1),r0 tst #0xff,r0 - bf signal_return - ! + bt restore_all +signal_return: + mov r15,r4 + mov #0,r5 + mov.l __do_signal,r1 + mova restore_all,r0 + jmp @r1 + lds r0,pr + .balign 4 +__do_signal: + .long SYMBOL_NAME(do_signal) +__softirq_state: + .long SYMBOL_NAME(softirq_state) +__do_softirq: + .long SYMBOL_NAME(do_softirq) +__minus8192: + .long -8192 ! offset from stackbase to tsk + + .balign 4 restore_all: - add #4,r15 ! skip syscall number - mov.l @r15+,r11 ! SSR +#if defined(__SH4__) + mov.l __fpu_prepare_fd, $r1 + jsr @$r1 + stc $sr, $r4 +#endif + add #4,r15 ! Skip syscall number + mov.l @r15+,r11 ! Got SSR into R11 +#if defined(__SH4__) + mov $r11, $r12 +#endif + ! + mov.l 1f,r1 + stc sr,r0 + and r1,r0 ! Get IMASK+FD + mov.l 2f,r1 + and r1,r11 + or r0,r11 ! Inherit the IMASK+FD value of SR + ! mov.l @r15+,r10 ! original stack mov.l @r15+,r0 mov.l @r15+,r1 @@ -398,6 +435,9 @@ restore_all: ldc r14,sr ! here, change the register bank mov r10,k0 mov r11,k1 +#if defined(__SH4__) + mov $r12, $k2 +#endif mov.l @r15+,r8 mov.l @r15+,r9 mov.l @r15+,r10 @@ -410,21 +450,69 @@ restore_all: lds.l @r15+,macl lds.l @r15+,pr ldc.l @r15+,spc - mov k0,r15 ldc k1,ssr +#if defined(__SH4__) + shll $k1 + shll $k1 + bf 9f ! user mode + /* Kernel to kernel transition */ + mov.l 3f, $k1 + tst $k1, $k2 + bf 9f ! it hadn't FPU + ! Kernel to kernel and FPU was used + ! There's the case we don't get FPU now + stc $sr, $k2 + tst $k1, $k2 + bt 7f + ! We need to grab FPU here + xor $k1, $k2 + ldc $k2, $sr ! Grab FPU + mov.l __init_task_flags, $k1 + mov.l @$k1, $k2 + mov.l __PF_USEDFPU, $k1 + or $k1, $k2 + mov.l __init_task_flags, $k1 + mov.l $k2, @$k1 ! Set init_task.flags |= PF_USEDFPU + ! + ! Restoring FPU... + ! +7: fmov.s @$r15+, $fr0 + fmov.s @$r15+, $fr1 + fmov.s @$r15+, $fr2 + fmov.s @$r15+, $fr3 + fmov.s @$r15+, $fr4 + fmov.s @$r15+, $fr5 + fmov.s @$r15+, $fr6 + fmov.s @$r15+, $fr7 + fmov.s @$r15+, $fr8 + fmov.s @$r15+, $fr9 + fmov.s @$r15+, $fr10 + fmov.s @$r15+, $fr11 + fmov.s @$r15+, $fr12 + fmov.s @$r15+, $fr13 + fmov.s @$r15+, $fr14 + fmov.s @$r15+, $fr15 + lds.l @$r15+, $fpscr + lds.l @$r15+, $fpul +9: +#endif + mov k0,r15 rte nop .balign 4 -__n_sys: .long NR_syscalls -__sct: .long SYMBOL_NAME(sys_call_table) -__bh_mask: .long SYMBOL_NAME(bh_mask) -__bh_active: .long SYMBOL_NAME(bh_active) -__dbh: .long SYMBOL_NAME(do_bottom_half) __blrb_flags: .long 0x30000000 -__minus8192: .long -8192 ! offset from stackbase to tsk -__tsk_flags: .long flags-8192 ! offset from stackbase to tsk->flags - +#if defined(__SH4__) +__fpu_prepare_fd: + .long SYMBOL_NAME(fpu_prepare_fd) +__init_task_flags: + .long SYMBOL_NAME(init_task_union)+4 +__PF_USEDFPU: + .long PF_USEDFPU +#endif +1: .long 0x000080f0 ! IMASK+FD +2: .long 0xffff7f0f ! ~(IMASK+FD) +3: .long 0x00008000 ! FD=1 ! Exception Vector Base ! @@ -441,43 +529,81 @@ general_exception: bra handle_exception mov.l @k2,k2 .balign 4 -2: .long SYMBOL_NAME(ret_from_syscall) +2: .long SYMBOL_NAME(ret_from_exception) 1: .long EXPEVT ! ! .balign 1024,0,1024 tlb_miss: mov.l 1f,k2 - mov.l 3f,k3 + mov.l 4f,k3 bra handle_exception mov.l @k2,k2 ! .balign 512,0,512 interrupt: mov.l 2f,k2 - mov.l 4f,k3 + mov.l 3f,k3 bra handle_exception mov.l @k2,k2 .balign 4 1: .long EXPEVT 2: .long INTEVT -3: .long SYMBOL_NAME(ret_from_syscall) -4: .long SYMBOL_NAME(ret_from_irq) +3: .long SYMBOL_NAME(ret_from_irq) +4: .long SYMBOL_NAME(ret_from_exception) ! ! handle_exception: - ! Using k0, k1 for scratch registers (r0_bank1, and r1_bank1), + ! Using k0, k1 for scratch registers (r0_bank1, r1_bank), ! save all registers onto stack. ! stc ssr,k0 ! from kernel space? shll k0 ! Check MD bit (bit30) shll k0 - bt/s 1f ! it's from kernel to kernel transition +#if defined(__SH4__) + bf/s 8f ! it's from user to kernel transition + mov $r15, $k0 ! save original stack to k0 + /* Kernel to kernel transition */ + mov.l 2f, $k1 + stc $ssr, $k0 + tst $k1, $k0 + bf/s 9f ! FPU is not used + mov $r15, $k0 ! save original stack to k0 + ! FPU is used, save FPU + ! /* XXX: Need to save another bank of FPU if all FPU feature is used */ + ! /* Currently it's not the case for GCC (only udivsi3_i4, divsi3_i4) */ + sts.l $fpul, @-$r15 + sts.l $fpscr, @-$r15 + fmov.s $fr15, @-$r15 + fmov.s $fr14, @-$r15 + fmov.s $fr13, @-$r15 + fmov.s $fr12, @-$r15 + fmov.s $fr11, @-$r15 + fmov.s $fr10, @-$r15 + fmov.s $fr9, @-$r15 + fmov.s $fr8, @-$r15 + fmov.s $fr7, @-$r15 + fmov.s $fr6, @-$r15 + fmov.s $fr5, @-$r15 + fmov.s $fr4, @-$r15 + fmov.s $fr3, @-$r15 + fmov.s $fr2, @-$r15 + fmov.s $fr1, @-$r15 + fmov.s $fr0, @-$r15 + bra 9f + mov #0, $k1 +#else + bt/s 9f ! it's from kernel to kernel transition mov r15,k0 ! save original stack to k0 anyway - mov kernel_sp,r15 ! change to kernel stack -1: stc.l spc,@-r15 +#endif +8: /* User space to kernel */ + mov kernel_sp, $r15 ! change to kernel stack +#if defined(__SH4__) + mov.l 2f, $k1 ! let kernel release FPU +#endif +9: stc.l spc,@-r15 sts.l pr,@-r15 ! lds k3,pr ! Set the return address to pr @@ -487,9 +613,12 @@ handle_exception: stc.l gbr,@-r15 mov.l r14,@-r15 ! - mov.l 2f,k1 - stc sr,r14 ! back to normal register bank, and - and k1,r14 ! .. + stc sr,r14 ! Back to normal register bank, and +#if defined(__SH4__) + or $k1, $r14 ! may release FPU +#endif + mov.l 3f,k1 + and k1,r14 ! ... ldc r14,sr ! ...changed here. ! mov.l r13,@-r15 @@ -520,7 +649,8 @@ handle_exception: mov.l @r15,r0 ! recovering r0.. .balign 4 1: .long SYMBOL_NAME(exception_handling_table) -2: .long 0xdfffffff ! RB=0, BL=1 +2: .long 0x00008000 ! FD=1 +3: .long 0xdfffffff ! RB=0, leave BL=1 none: rts @@ -537,7 +667,11 @@ ENTRY(exception_handling_table) .long tlb_protection_violation_store .long error ! address_error_load (filled by trap_init) .long error ! address_error_store (filled by trap_init) +#if defined(__SH4__) + .long SYMBOL_NAME(do_fpu_error) +#else .long error ! fpu_exception +#endif .long error .long system_call ! Unconditional Trap .long error ! reserved_instruction (filled by trap_init) @@ -628,8 +762,8 @@ ENTRY(interrupt_table) .long error .long error .long error - .long error ! fpu - .long error ! fpu + .long SYMBOL_NAME(do_fpu_state_restore) + .long SYMBOL_NAME(do_fpu_state_restore) #endif ENTRY(sys_call_table) @@ -649,15 +783,15 @@ ENTRY(sys_call_table) .long SYMBOL_NAME(sys_time) .long SYMBOL_NAME(sys_mknod) .long SYMBOL_NAME(sys_chmod) /* 15 */ - .long SYMBOL_NAME(sys_lchown) + .long SYMBOL_NAME(sys_lchown16) .long SYMBOL_NAME(sys_ni_syscall) /* old break syscall holder */ .long SYMBOL_NAME(sys_stat) .long SYMBOL_NAME(sys_lseek) .long SYMBOL_NAME(sys_getpid) /* 20 */ .long SYMBOL_NAME(sys_mount) .long SYMBOL_NAME(sys_oldumount) - .long SYMBOL_NAME(sys_setuid) - .long SYMBOL_NAME(sys_getuid) + .long SYMBOL_NAME(sys_setuid16) + .long SYMBOL_NAME(sys_getuid16) .long SYMBOL_NAME(sys_stime) /* 25 */ .long SYMBOL_NAME(sys_ptrace) .long SYMBOL_NAME(sys_alarm) @@ -679,13 +813,13 @@ ENTRY(sys_call_table) .long SYMBOL_NAME(sys_times) .long SYMBOL_NAME(sys_ni_syscall) /* old prof syscall holder */ .long SYMBOL_NAME(sys_brk) /* 45 */ - .long SYMBOL_NAME(sys_setgid) - .long SYMBOL_NAME(sys_getgid) + .long SYMBOL_NAME(sys_setgid16) + .long SYMBOL_NAME(sys_getgid16) .long SYMBOL_NAME(sys_signal) - .long SYMBOL_NAME(sys_geteuid) - .long SYMBOL_NAME(sys_getegid) /* 50 */ + .long SYMBOL_NAME(sys_geteuid16) + .long SYMBOL_NAME(sys_getegid16) /* 50 */ .long SYMBOL_NAME(sys_acct) - .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */ + .long SYMBOL_NAME(sys_umount) /* recycled never used phys() */ .long SYMBOL_NAME(sys_ni_syscall) /* old lock syscall holder */ .long SYMBOL_NAME(sys_ioctl) .long SYMBOL_NAME(sys_fcntl) /* 55 */ @@ -703,19 +837,19 @@ ENTRY(sys_call_table) .long SYMBOL_NAME(sys_sigaction) .long SYMBOL_NAME(sys_sgetmask) .long SYMBOL_NAME(sys_ssetmask) - .long SYMBOL_NAME(sys_setreuid) /* 70 */ - .long SYMBOL_NAME(sys_setregid) + .long SYMBOL_NAME(sys_setreuid16) /* 70 */ + .long SYMBOL_NAME(sys_setregid16) .long SYMBOL_NAME(sys_sigsuspend) .long SYMBOL_NAME(sys_sigpending) .long SYMBOL_NAME(sys_sethostname) .long SYMBOL_NAME(sys_setrlimit) /* 75 */ - .long SYMBOL_NAME(sys_getrlimit) + .long SYMBOL_NAME(sys_old_getrlimit) .long SYMBOL_NAME(sys_getrusage) .long SYMBOL_NAME(sys_gettimeofday) .long SYMBOL_NAME(sys_settimeofday) - .long SYMBOL_NAME(sys_getgroups) /* 80 */ - .long SYMBOL_NAME(sys_setgroups) - .long SYMBOL_NAME(sys_ni_syscall) /* old_select */ + .long SYMBOL_NAME(sys_getgroups16) /* 80 */ + .long SYMBOL_NAME(sys_setgroups16) + .long SYMBOL_NAME(sys_ni_syscall) /* sys_oldselect */ .long SYMBOL_NAME(sys_symlink) .long SYMBOL_NAME(sys_lstat) .long SYMBOL_NAME(sys_readlink) /* 85 */ @@ -723,18 +857,18 @@ ENTRY(sys_call_table) .long SYMBOL_NAME(sys_swapon) .long SYMBOL_NAME(sys_reboot) .long SYMBOL_NAME(old_readdir) - .long SYMBOL_NAME(sys_mmap) /* 90 */ + .long SYMBOL_NAME(old_mmap) /* 90 */ .long SYMBOL_NAME(sys_munmap) .long SYMBOL_NAME(sys_truncate) .long SYMBOL_NAME(sys_ftruncate) .long SYMBOL_NAME(sys_fchmod) - .long SYMBOL_NAME(sys_fchown) /* 95 */ + .long SYMBOL_NAME(sys_fchown16) /* 95 */ .long SYMBOL_NAME(sys_getpriority) .long SYMBOL_NAME(sys_setpriority) .long SYMBOL_NAME(sys_ni_syscall) /* old profil syscall holder */ .long SYMBOL_NAME(sys_statfs) .long SYMBOL_NAME(sys_fstatfs) /* 100 */ - .long SYMBOL_NAME(sys_ni_syscall) /* ioperm */ + .long SYMBOL_NAME(sys_ni_syscall) /* ioperm */ .long SYMBOL_NAME(sys_socketcall) .long SYMBOL_NAME(sys_syslog) .long SYMBOL_NAME(sys_setitimer) @@ -771,8 +905,8 @@ ENTRY(sys_call_table) .long SYMBOL_NAME(sys_sysfs) /* 135 */ .long SYMBOL_NAME(sys_personality) .long SYMBOL_NAME(sys_ni_syscall) /* for afs_syscall */ - .long SYMBOL_NAME(sys_setfsuid) - .long SYMBOL_NAME(sys_setfsgid) + .long SYMBOL_NAME(sys_setfsuid16) + .long SYMBOL_NAME(sys_setfsgid16) .long SYMBOL_NAME(sys_llseek) /* 140 */ .long SYMBOL_NAME(sys_getdents) .long SYMBOL_NAME(sys_select) @@ -797,14 +931,14 @@ ENTRY(sys_call_table) .long SYMBOL_NAME(sys_sched_rr_get_interval) .long SYMBOL_NAME(sys_nanosleep) .long SYMBOL_NAME(sys_mremap) - .long SYMBOL_NAME(sys_setresuid) - .long SYMBOL_NAME(sys_getresuid) /* 165 */ - .long SYMBOL_NAME(sys_ni_syscall) /* vm86 */ + .long SYMBOL_NAME(sys_setresuid16) + .long SYMBOL_NAME(sys_getresuid16) /* 165 */ + .long SYMBOL_NAME(sys_ni_syscall) /* vm86 */ .long SYMBOL_NAME(sys_query_module) .long SYMBOL_NAME(sys_poll) .long SYMBOL_NAME(sys_nfsservctl) - .long SYMBOL_NAME(sys_setresgid) /* 170 */ - .long SYMBOL_NAME(sys_getresgid) + .long SYMBOL_NAME(sys_setresgid16) /* 170 */ + .long SYMBOL_NAME(sys_getresgid16) .long SYMBOL_NAME(sys_prctl) .long SYMBOL_NAME(sys_rt_sigreturn) .long SYMBOL_NAME(sys_rt_sigaction) @@ -815,15 +949,42 @@ ENTRY(sys_call_table) .long SYMBOL_NAME(sys_rt_sigsuspend) .long SYMBOL_NAME(sys_pread) /* 180 */ .long SYMBOL_NAME(sys_pwrite) - .long SYMBOL_NAME(sys_chown) + .long SYMBOL_NAME(sys_chown16) .long SYMBOL_NAME(sys_getcwd) .long SYMBOL_NAME(sys_capget) .long SYMBOL_NAME(sys_capset) /* 185 */ .long SYMBOL_NAME(sys_sigaltstack) .long SYMBOL_NAME(sys_sendfile) - .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */ - .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ + .long SYMBOL_NAME(sys_ni_syscall) /* streams1 */ + .long SYMBOL_NAME(sys_ni_syscall) /* streams2 */ .long SYMBOL_NAME(sys_vfork) /* 190 */ + .long SYMBOL_NAME(sys_getrlimit) + .long SYMBOL_NAME(sys_mmap2) + .long SYMBOL_NAME(sys_truncate64) + .long SYMBOL_NAME(sys_ftruncate64) + .long SYMBOL_NAME(sys_stat64) /* 195 */ + .long SYMBOL_NAME(sys_lstat64) + .long SYMBOL_NAME(sys_fstat64) + .long SYMBOL_NAME(sys_lchown) + .long SYMBOL_NAME(sys_getuid) + .long SYMBOL_NAME(sys_getgid) /* 200 */ + .long SYMBOL_NAME(sys_geteuid) + .long SYMBOL_NAME(sys_getegid) + .long SYMBOL_NAME(sys_setreuid) + .long SYMBOL_NAME(sys_setregid) + .long SYMBOL_NAME(sys_getgroups) /* 205 */ + .long SYMBOL_NAME(sys_setgroups) + .long SYMBOL_NAME(sys_fchown) + .long SYMBOL_NAME(sys_setresuid) + .long SYMBOL_NAME(sys_getresuid) + .long SYMBOL_NAME(sys_setresgid) /* 210 */ + .long SYMBOL_NAME(sys_getresgid) + .long SYMBOL_NAME(sys_chown) + .long SYMBOL_NAME(sys_setuid) + .long SYMBOL_NAME(sys_setgid) + .long SYMBOL_NAME(sys_setfsuid) /* 215 */ + .long SYMBOL_NAME(sys_setfsgid) + .long SYMBOL_NAME(sys_pivot_root) /* * NOTE!! This doesn't have to be exact - we just have @@ -831,7 +992,7 @@ ENTRY(sys_call_table) * entries. Don't panic if you notice that this hasn't * been shrunk every time we add a new system call. */ - .rept NR_syscalls-190 + .rept NR_syscalls-217 .long SYMBOL_NAME(sys_ni_syscall) .endr diff --git a/arch/sh/kernel/fpu.c b/arch/sh/kernel/fpu.c new file mode 100644 index 000000000..335902c1d --- /dev/null +++ b/arch/sh/kernel/fpu.c @@ -0,0 +1,266 @@ +/* $Id: fpu.c,v 1.27 2000/03/05 01:48:34 gniibe Exp $ + * + * linux/arch/sh/kernel/fpu.c + * + * Save/restore floating point context for signal handlers. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka + * + * FIXME! These routines can be optimized in big endian case. + */ + +#include <linux/sched.h> +#include <linux/signal.h> +#include <asm/processor.h> +#include <asm/io.h> + +void +save_fpu(struct task_struct *tsk) +{ + asm volatile("sts.l $fpul, @-%0\n\t" + "sts.l $fpscr, @-%0\n\t" + "frchg\n\t" + "fmov.s $fr15, @-%0\n\t" + "fmov.s $fr14, @-%0\n\t" + "fmov.s $fr13, @-%0\n\t" + "fmov.s $fr12, @-%0\n\t" + "fmov.s $fr11, @-%0\n\t" + "fmov.s $fr10, @-%0\n\t" + "fmov.s $fr9, @-%0\n\t" + "fmov.s $fr8, @-%0\n\t" + "fmov.s $fr7, @-%0\n\t" + "fmov.s $fr6, @-%0\n\t" + "fmov.s $fr5, @-%0\n\t" + "fmov.s $fr4, @-%0\n\t" + "fmov.s $fr3, @-%0\n\t" + "fmov.s $fr2, @-%0\n\t" + "fmov.s $fr1, @-%0\n\t" + "fmov.s $fr0, @-%0\n\t" + "frchg\n\t" + "fmov.s $fr15, @-%0\n\t" + "fmov.s $fr14, @-%0\n\t" + "fmov.s $fr13, @-%0\n\t" + "fmov.s $fr12, @-%0\n\t" + "fmov.s $fr11, @-%0\n\t" + "fmov.s $fr10, @-%0\n\t" + "fmov.s $fr9, @-%0\n\t" + "fmov.s $fr8, @-%0\n\t" + "fmov.s $fr7, @-%0\n\t" + "fmov.s $fr6, @-%0\n\t" + "fmov.s $fr5, @-%0\n\t" + "fmov.s $fr4, @-%0\n\t" + "fmov.s $fr3, @-%0\n\t" + "fmov.s $fr2, @-%0\n\t" + "fmov.s $fr1, @-%0\n\t" + "fmov.s $fr0, @-%0" + : /* no output */ + : "r" ((char *)(&tsk->thread.fpu.hard.status)) + : "memory"); + + tsk->flags &= ~PF_USEDFPU; + release_fpu(); +} + +static void +restore_fpu(struct task_struct *tsk) +{ + asm volatile("fmov.s @%0+, $fr0\n\t" + "fmov.s @%0+, $fr1\n\t" + "fmov.s @%0+, $fr2\n\t" + "fmov.s @%0+, $fr3\n\t" + "fmov.s @%0+, $fr4\n\t" + "fmov.s @%0+, $fr5\n\t" + "fmov.s @%0+, $fr6\n\t" + "fmov.s @%0+, $fr7\n\t" + "fmov.s @%0+, $fr8\n\t" + "fmov.s @%0+, $fr9\n\t" + "fmov.s @%0+, $fr10\n\t" + "fmov.s @%0+, $fr11\n\t" + "fmov.s @%0+, $fr12\n\t" + "fmov.s @%0+, $fr13\n\t" + "fmov.s @%0+, $fr14\n\t" + "fmov.s @%0+, $fr15\n\t" + "frchg\n\t" + "fmov.s @%0+, $fr0\n\t" + "fmov.s @%0+, $fr1\n\t" + "fmov.s @%0+, $fr2\n\t" + "fmov.s @%0+, $fr3\n\t" + "fmov.s @%0+, $fr4\n\t" + "fmov.s @%0+, $fr5\n\t" + "fmov.s @%0+, $fr6\n\t" + "fmov.s @%0+, $fr7\n\t" + "fmov.s @%0+, $fr8\n\t" + "fmov.s @%0+, $fr9\n\t" + "fmov.s @%0+, $fr10\n\t" + "fmov.s @%0+, $fr11\n\t" + "fmov.s @%0+, $fr12\n\t" + "fmov.s @%0+, $fr13\n\t" + "fmov.s @%0+, $fr14\n\t" + "fmov.s @%0+, $fr15\n\t" + "frchg\n\t" + "lds.l @%0+, $fpscr\n\t" + "lds.l @%0+, $fpul\n\t" + : /* no output */ + : "r" (&tsk->thread.fpu) + : "memory"); +} + +/* + * Load the FPU with signalling NANS. This bit pattern we're using + * has the property that no matter wether considered as single or as + * double precission represents signaling NANS. + */ +/* Double presision, NANS as NANS, rounding to nearest, no exceptions */ +#define FPU_DEFAULT 0x00080000 + +void fpu_init(void) +{ + asm volatile("lds %0, $fpul\n\t" + "lds %1, $fpscr\n\t" + "fsts $fpul, $fr0\n\t" + "fsts $fpul, $fr1\n\t" + "fsts $fpul, $fr2\n\t" + "fsts $fpul, $fr3\n\t" + "fsts $fpul, $fr4\n\t" + "fsts $fpul, $fr5\n\t" + "fsts $fpul, $fr6\n\t" + "fsts $fpul, $fr7\n\t" + "fsts $fpul, $fr8\n\t" + "fsts $fpul, $fr9\n\t" + "fsts $fpul, $fr10\n\t" + "fsts $fpul, $fr11\n\t" + "fsts $fpul, $fr12\n\t" + "fsts $fpul, $fr13\n\t" + "fsts $fpul, $fr14\n\t" + "fsts $fpul, $fr15\n\t" + "frchg\n\t" + "fsts $fpul, $fr0\n\t" + "fsts $fpul, $fr1\n\t" + "fsts $fpul, $fr2\n\t" + "fsts $fpul, $fr3\n\t" + "fsts $fpul, $fr4\n\t" + "fsts $fpul, $fr5\n\t" + "fsts $fpul, $fr6\n\t" + "fsts $fpul, $fr7\n\t" + "fsts $fpul, $fr8\n\t" + "fsts $fpul, $fr9\n\t" + "fsts $fpul, $fr10\n\t" + "fsts $fpul, $fr11\n\t" + "fsts $fpul, $fr12\n\t" + "fsts $fpul, $fr13\n\t" + "fsts $fpul, $fr14\n\t" + "fsts $fpul, $fr15\n\t" + "frchg" + : /* no output */ + : "r" (0), "r" (FPU_DEFAULT)); +} + +asmlinkage void +do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, + struct pt_regs regs) +{ + struct task_struct *tsk = current; + + regs.syscall_nr = -1; + regs.pc += 2; + + grab_fpu(); + save_fpu(tsk); + tsk->thread.trap_no = 11; + tsk->thread.error_code = 0; + force_sig(SIGFPE, tsk); +} + +asmlinkage void +do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, + unsigned long r7, struct pt_regs regs) +{ + struct task_struct *tsk = current; + + regs.syscall_nr = -1; + + if (!user_mode(®s)) { + if (tsk != &init_task) { + unlazy_fpu(tsk); + } + tsk = &init_task; + if (tsk->flags & PF_USEDFPU) + BUG(); + } + + grab_fpu(); + if (tsk->used_math) { + /* Using the FPU again. */ + restore_fpu(tsk); + } else { + /* First time FPU user. */ + fpu_init(); + tsk->used_math = 1; + } + tsk->flags |= PF_USEDFPU; + release_fpu(); +} + +/* + * Change current FD flag to set FD flag back to exception + */ +asmlinkage void +fpu_prepare_fd(unsigned long sr, unsigned long r5, unsigned long r6, + unsigned long r7, struct pt_regs regs) +{ + __cli(); + if (!user_mode(®s)) { + if (init_task.flags & PF_USEDFPU) + grab_fpu(); + else { + if (!(sr & SR_FD)) { + release_fpu(); + BUG(); + } + } + return; + } + + if (sr & SR_FD) { /* Kernel doesn't grab FPU */ + if (current->flags & PF_USEDFPU) + grab_fpu(); + else { + if (init_task.flags & PF_USEDFPU) { + init_task.flags &= ~PF_USEDFPU; + BUG(); + } + } + } else { + if (init_task.flags & PF_USEDFPU) + save_fpu(&init_task); + else { + release_fpu(); + BUG(); + } + } +} + +/* Short cut for the FPU exception */ +asmlinkage void +enable_fpu_in_danger(void) +{ + struct task_struct *tsk = current; + + if (tsk != &init_task) + unlazy_fpu(tsk); + + tsk = &init_task; + if (tsk->used_math) { + /* Using the FPU again. */ + restore_fpu(tsk); + } else { + /* First time FPU user. */ + fpu_init(); + tsk->used_math = 1; + } + tsk->flags |= PF_USEDFPU; +} diff --git a/arch/sh/kernel/head.S b/arch/sh/kernel/head.S index f6378927e..3f938557a 100644 --- a/arch/sh/kernel/head.S +++ b/arch/sh/kernel/head.S @@ -1,8 +1,8 @@ -/* $Id: head.S,v 1.7 1999/10/27 09:41:42 gniibe Exp gniibe $ +/* $Id: head.S,v 1.16 2000/03/02 00:01:15 gniibe Exp $ * * arch/sh/kernel/head.S * - * Copyright (C) 1999 Niibe Yutaka & Kaz Kojima + * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -34,49 +34,37 @@ ENTRY(empty_zero_page) * Cache may or may not be initialized. * Hardware (including on-chip modules) may or may not be initialized. * - * The register R4&R5 holds the address of the parameter block, which has - * command-line data, etc. - * */ ENTRY(_stext) -#if defined(__SH4__) - ! Initialize FPSCR - /* GCC (as of 2.95.1) assumes FPU with double precision mode. */ - mov.l 7f,r0 - lds r0,fpscr -#endif ! Initialize Status Register - mov.l 1f,r0 ! MD=1, RB=0, BL=1 - ldc r0,sr + mov.l 1f, $r0 ! MD=1, RB=0, BL=1 + ldc $r0, $sr ! - mov.l 2f,r0 - mov r0,r15 ! Set initial r15 (stack pointer) - ldc r0,r4_bank ! and stack base + mov.l 2f, $r0 + mov $r0, $r15 ! Set initial r15 (stack pointer) + ldc $r0, $r4_bank ! and stack base ! ! Enable cache - mov.l 6f,r0 - jsr @r0 + mov.l 6f, $r0 + jsr @$r0 nop ! Clear BSS area - mov.l 3f,r1 - add #4,r1 - mov.l 4f,r2 - mov #0,r0 -9: cmp/hs r2,r1 + mov.l 3f, $r1 + add #4, $r1 + mov.l 4f, $r2 + mov #0, $r0 +9: cmp/hs $r2, $r1 bf/s 9b ! while (r1 < r2) - mov.l r0,@-r2 + mov.l $r0,@-$r2 ! Start kernel - mov.l 5f,r0 - jmp @r0 + mov.l 5f, $r0 + jmp @$r0 nop .balign 4 -1: .long 0x50000000 ! MD=1, RB=0, BL=1 +1: .long 0x50000000 ! MD=1, RB=0, BL=1, FD=0 2: .long SYMBOL_NAME(stack) 3: .long SYMBOL_NAME(__bss_start) 4: .long SYMBOL_NAME(_end) 5: .long SYMBOL_NAME(start_kernel) 6: .long SYMBOL_NAME(cache_init) -#if defined(__SH4__) -7: .long 0x00080000 -#endif diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index e87972c73..a15352389 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.4 1999/10/11 13:12:14 gniibe Exp $ +/* $Id: irq.c,v 1.11 2000/02/29 11:03:40 gniibe Exp $ * * linux/arch/sh/kernel/irq.c * @@ -31,7 +31,7 @@ #include <asm/io.h> #include <asm/bitops.h> #include <asm/smp.h> -#include <asm/pgtable.h> +#include <asm/pgalloc.h> #include <asm/delay.h> #include <asm/irq.h> #include <linux/irq.h> @@ -49,7 +49,8 @@ spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED; /* * Controller mappings for all interrupt sources: */ -irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }}; +irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = + { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }}; /* * Special irq handlers. @@ -112,9 +113,8 @@ int get_irq_list(char *buf) p += sprintf(p, " %14s", irq_desc[i].handler->typename); p += sprintf(p, " %s", action->name); - for (action=action->next; action; action = action->next) { + for (action=action->next; action; action = action->next) p += sprintf(p, ", %s", action->name); - } *p++ = '\n'; } return p - buf; @@ -248,7 +248,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, kstat.irqs[cpu][irq]++; desc = irq_desc + irq; spin_lock(&irq_controller_lock); - irq_desc[irq].handler->ack(irq); + desc->handler->ack(irq); /* REPLAY is when Linux resends an IRQ that was dropped earlier WAITING is used by probe to mark irqs that are being tested @@ -298,21 +298,15 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, spin_unlock(&irq_controller_lock); } desc->status &= ~IRQ_INPROGRESS; - if (!(desc->status & IRQ_DISABLED)){ - irq_desc[irq].handler->end(irq); - } + if (!(desc->status & IRQ_DISABLED)) + desc->handler->end(irq); spin_unlock(&irq_controller_lock); - /* - * This should be conditional: we should really get - * a return code from the irq handler to tell us - * whether the handler wants us to do software bottom - * half handling or not.. - */ - if (1) { - if (bh_active & bh_mask) - do_bottom_half(); - } +#if 1 + __sti(); +#endif + if (softirq_state[cpu].active&softirq_state[cpu].mask) + do_softirq(); return 1; } @@ -347,7 +341,7 @@ int request_irq(unsigned int irq, kfree(action); return retval; } - + void free_irq(unsigned int irq, void *dev_id) { struct irqaction **p; @@ -373,10 +367,6 @@ void free_irq(unsigned int irq, void *dev_id) irq_desc[irq].handler->shutdown(irq); } spin_unlock_irqrestore(&irq_controller_lock,flags); - - /* Wait to make sure it's not being used on another CPU */ - while (irq_desc[irq].status & IRQ_INPROGRESS) - barrier(); kfree(action); return; } @@ -398,6 +388,7 @@ unsigned long probe_irq_on(void) { unsigned int i; unsigned long delay; + unsigned long val; /* * first, enable any unassigned irqs @@ -421,6 +412,7 @@ unsigned long probe_irq_on(void) /* * Now filter out any obviously spurious interrupts */ + val = 0; spin_lock_irq(&irq_controller_lock); for (i=0; i<NR_IRQS; i++) { unsigned int status = irq_desc[i].status; @@ -433,19 +425,19 @@ unsigned long probe_irq_on(void) irq_desc[i].status = status & ~IRQ_AUTODETECT; irq_desc[i].handler->shutdown(i); } + + if (i < 32) + val |= 1 << i; } spin_unlock_irq(&irq_controller_lock); - return 0x12345678; + return val; } -int probe_irq_off(unsigned long unused) +int probe_irq_off(unsigned long val) { int i, irq_found, nr_irqs; - if (unused != 0x12345678) - printk("Bad IRQ probe from %lx\n", (&unused)[-1]); - nr_irqs = 0; irq_found = 0; spin_lock_irq(&irq_controller_lock); diff --git a/arch/sh/kernel/irq_imask.c b/arch/sh/kernel/irq_imask.c new file mode 100644 index 000000000..a3cf78b5f --- /dev/null +++ b/arch/sh/kernel/irq_imask.c @@ -0,0 +1,106 @@ +/* $Id: irq_imask.c,v 1.2 2000/02/11 04:57:40 gniibe Exp $ + * + * linux/arch/sh/kernel/irq_imask.c + * + * Copyright (C) 1999 Niibe Yutaka + * + * Simple interrupt handling using IMASK of SR register. + * + */ + +#include <linux/ptrace.h> +#include <linux/errno.h> +#include <linux/kernel_stat.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/init.h> + +#include <asm/system.h> +#include <asm/irq.h> +#include <asm/bitops.h> + +#include <linux/spinlock.h> +#include <linux/cache.h> +#include <linux/irq.h> + +/* Bitmap of IRQ masked */ +static unsigned long imask_mask = 0x7fff; +static int interrupt_priority = 0; + +static void enable_imask_irq(unsigned int irq); +static void disable_imask_irq(unsigned int irq); +static void shutdown_imask_irq(unsigned int irq); +static void mask_and_ack_imask(unsigned int); +static void end_imask_irq(unsigned int irq); + +#define IMASK_PRIORITY 15 + +static unsigned int startup_imask_irq(unsigned int irq) +{ + enable_imask_irq(irq); + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type imask_irq_type = { + "Interrupt using IMASK of SR register", + startup_imask_irq, + shutdown_imask_irq, + enable_imask_irq, + disable_imask_irq, + mask_and_ack_imask, + end_imask_irq +}; + +void disable_imask_irq(unsigned int irq) +{ + unsigned long __dummy; + + clear_bit(irq, &imask_mask); + if (interrupt_priority < IMASK_PRIORITY - irq) + interrupt_priority = IMASK_PRIORITY - irq; + + asm volatile("stc sr,%0\n\t" + "and %1,%0\n\t" + "or %2,%0\n\t" + "ldc %0,sr" + : "=&r" (__dummy) + : "r" (0xffffff0f), "r" (interrupt_priority << 4)); +} + +static void enable_imask_irq(unsigned int irq) +{ + unsigned long __dummy; + + set_bit(irq, &imask_mask); + interrupt_priority = IMASK_PRIORITY - ffz(imask_mask); + + asm volatile("stc sr,%0\n\t" + "and %1,%0\n\t" + "or %2,%0\n\t" + "ldc %0,sr" + : "=&r" (__dummy) + : "r" (0xffffff0f), "r" (interrupt_priority << 4)); +} + +static void mask_and_ack_imask(unsigned int irq) +{ + disable_imask_irq(irq); +} + +static void end_imask_irq(unsigned int irq) +{ + enable_imask_irq(irq); +} + +static void shutdown_imask_irq(unsigned int irq) +{ + disable_imask_irq(irq); +} + +void make_imask_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &imask_irq_type; + enable_irq(irq); +} diff --git a/arch/sh/kernel/irq_onchip.c b/arch/sh/kernel/irq_onchip.c index cd28d2a59..10c48fd38 100644 --- a/arch/sh/kernel/irq_onchip.c +++ b/arch/sh/kernel/irq_onchip.c @@ -1,4 +1,4 @@ -/* $Id: irq_onchip.c,v 1.5 1999/10/28 02:18:33 gniibe Exp $ +/* $Id: irq_onchip.c,v 1.7 2000-01-09 15:55:55+09 gniibe Exp $ * * linux/arch/sh/kernel/irq_onchip.c * @@ -143,7 +143,18 @@ static void end_onChip_irq(unsigned int irq) */ #define INTC_IRR0 0xa4000004UL -#define INTC_IPRC 0xa4000016UL +#define INTC_IRR1 0xa4000006UL +#define INTC_IRR2 0xa4000008UL + +#define INTC_ICR0 0xfffffee0 +#define INTC_ICR1 0xa4000010 +#define INTC_ICR2 0xa4000012 +#define INTC_INTER 0xa4000014 +#define INTC_IPRA 0xfffffee2 +#define INTC_IPRB 0xfffffee4 +#define INTC_IPRC 0xa4000016 +#define INTC_IPRD 0xa4000018 +#define INTC_IPRE 0xa400001a #define IRQ0_IRQ 32 #define IRQ1_IRQ 33 @@ -248,6 +259,26 @@ void __init init_IRQ(void) } #ifdef CONFIG_CPU_SUBTYPE_SH7709 + + /* + * Initialize the Interrupt Controller (INTC) + * registers to their power on values + */ + + ctrl_outb(0, INTC_IRR0); + ctrl_outb(0, INTC_IRR1); + ctrl_outb(0, INTC_IRR2); + + ctrl_outw(0, INTC_ICR0); + ctrl_outw(0, INTC_ICR1); + ctrl_outw(0, INTC_ICR2); + ctrl_outw(0, INTC_INTER); + ctrl_outw(0, INTC_IPRA); + ctrl_outw(0, INTC_IPRB); + ctrl_outw(0, INTC_IPRC); + ctrl_outw(0, INTC_IPRD); + ctrl_outw(0, INTC_IPRE); + for (i = IRQ0_IRQ; i < NR_IRQS; i++) { irq_desc[i].handler = &onChip2_irq_type; } @@ -263,8 +294,5 @@ void __init init_IRQ(void) set_ipr_data(IRQ3_IRQ, IRQ3_IRP_OFFSET, IRQ3_PRIORITY); set_ipr_data(IRQ4_IRQ, IRQ4_IRP_OFFSET, IRQ4_PRIORITY); set_ipr_data(IRQ5_IRQ, IRQ5_IRP_OFFSET, IRQ5_PRIORITY); - - ctrl_inb(INTC_IRR0); - ctrl_outb(0, INTC_IRR0); #endif /* CONFIG_CPU_SUBTYPE_SH7709 */ } diff --git a/arch/sh/kernel/pci-sh.c b/arch/sh/kernel/pci-sh.c new file mode 100644 index 000000000..3613596f7 --- /dev/null +++ b/arch/sh/kernel/pci-sh.c @@ -0,0 +1,12 @@ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/ioport.h> +#include <linux/errno.h> + +unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, + unsigned long start, unsigned long size) +{ + return start; +} diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 5d2a5696c..2ca91cb40 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -1,10 +1,10 @@ -/* $Id: process.c,v 1.8 1999/10/31 13:19:16 gniibe Exp $ +/* $Id: process.c,v 1.28 2000/03/05 02:16:15 gniibe Exp $ * * linux/arch/sh/kernel/process.c * * Copyright (C) 1995 Linus Torvalds * - * SuperH version: Copyright (C) 1999 Niibe Yutaka & Kaz Kojima + * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima */ /* @@ -42,10 +42,6 @@ #include <linux/irq.h> -#if defined(__SH4__) -struct task_struct *last_task_used_math = NULL; -#endif - static int hlt_counter=0; #define HARD_IDLE_TIMEOUT (HZ / 3) @@ -140,25 +136,25 @@ void free_task_struct(struct task_struct *p) */ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { /* Don't use this in BL=1(cli). Or else, CPU resets! */ - register unsigned long __sc0 __asm__ ("r0") = __NR_clone; - register unsigned long __sc4 __asm__ ("r4") = (long) flags | CLONE_VM; - register unsigned long __sc5 __asm__ ("r5") = 0; - register unsigned long __sc8 __asm__ ("r8") = (long) arg; - register unsigned long __sc9 __asm__ ("r9") = (long) fn; - __asm__ __volatile__( - "trapa #0\n\t" /* Linux/SH system call */ - "tst #0xff,r0\n\t" /* child or parent? */ + register unsigned long __sc0 __asm__ ("$r0") = __NR_clone; + register unsigned long __sc4 __asm__ ("$r4") = (long) flags | CLONE_VM; + register unsigned long __sc5 __asm__ ("$r5") = 0; + register unsigned long __sc8 __asm__ ("$r8") = (long) arg; + register unsigned long __sc9 __asm__ ("$r9") = (long) fn; + + __asm__("trapa #0\n\t" /* Linux/SH system call */ + "tst #0xff, $r0\n\t" /* child or parent? */ "bf 1f\n\t" /* parent - jump */ - "jsr @r9\n\t" /* call fn */ - " mov r8,r4\n\t" /* push argument */ - "mov r0,r4\n\t" /* return value to arg of exit */ - "mov %2,r0\n\t" /* exit */ + "jsr @$r9\n\t" /* call fn */ + " mov $r8, $r4\n\t" /* push argument */ + "mov $r0, $r4\n\t" /* return value to arg of exit */ + "mov %2, $r0\n\t" /* exit */ "trapa #0\n" "1:" - :"=z" (__sc0) - :"0" (__sc0), "i" (__NR_exit), - "r" (__sc4), "r" (__sc5), "r" (__sc8), "r" (__sc9) - :"memory"); + : "=z" (__sc0) + : "0" (__sc0), "i" (__NR_exit), + "r" (__sc4), "r" (__sc5), "r" (__sc8), "r" (__sc9) + : "memory"); return __sc0; } @@ -167,18 +163,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) */ void exit_thread(void) { -#if defined(__sh3__) - /* nothing to do ... */ -#elif defined(__SH4__) -#if 0 /* for the time being... */ - /* Forget lazy fpu state */ - if (last_task_used_math == current) { - set_status_register (SR_FD, 0); - write_system_register (fpscr, FPSCR_PR); - last_task_used_math = NULL; - } -#endif -#endif + /* Nothing to do. */ } void flush_thread(void) @@ -187,14 +172,11 @@ void flush_thread(void) /* do nothing */ /* Possibly, set clear debug registers */ #elif defined(__SH4__) -#if 0 /* for the time being... */ - /* Forget lazy fpu state */ - if (last_task_used_math == current) { - set_status_register (SR_FD, 0); - write_system_register (fpscr, FPSCR_PR); - last_task_used_math = NULL; - } -#endif + struct task_struct *tsk = current; + + /* Forget lazy FPU state */ + clear_fpu(tsk); + tsk->used_math = 0; #endif } @@ -204,18 +186,22 @@ void release_thread(struct task_struct *dead_task) } /* Fill in the fpu structure for a core dump.. */ -int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) { #if defined(__SH4__) -#if 0 /* for the time being... */ - /* We store the FPU info in the task->thread area. */ - if (! (regs->sr & SR_FD)) { - memcpy (r, ¤t->thread.fpu, sizeof (*r)); - return 1; - } -#endif -#endif + int fpvalid; + struct task_struct *tsk = current; + + fpvalid = tsk->used_math; + if (fpvalid) { + unlazy_fpu(tsk); + memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); + } + + return fpvalid; +#else return 0; /* Task didn't use the fpu at all. */ +#endif } asmlinkage void ret_from_fork(void); @@ -224,21 +210,17 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct task_struct *p, struct pt_regs *regs) { struct pt_regs *childregs; + struct task_struct *tsk = current; childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p)) - 1; - *childregs = *regs; + struct_cpy(childregs, regs); #if defined(__SH4__) -#if 0 /* for the time being... */ - if (last_task_used_math == current) { - set_status_register (SR_FD, 0); - sh4_save_fp (p); + if (tsk != &init_task) { + unlazy_fpu(tsk); + struct_cpy(&p->thread.fpu, ¤t->thread.fpu); + p->used_math = tsk->used_math; } - /* New tasks loose permission to use the fpu. This accelerates context - switching for most programs since they don't use the fpu. */ - p->thread.sr = (read_control_register (sr) &~ SR_MD) | SR_FD; - childregs->sr |= SR_FD; -#endif #endif if (user_mode(regs)) { childregs->sp = usp; @@ -246,6 +228,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, childregs->sp = (unsigned long)p+2*PAGE_SIZE; } childregs->regs[0] = 0; /* Set return value for child */ + childregs->sr |= SR_FD; /* Invalidate FPU flag */ p->thread.sp = (unsigned long) childregs; p->thread.pc = (unsigned long) ret_from_fork; @@ -258,7 +241,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, */ void dump_thread(struct pt_regs * regs, struct user * dump) { -/* changed the size calculations - should hopefully work better. lbt */ dump->magic = CMAGIC; dump->start_code = current->mm->start_code; dump->start_data = current->mm->start_data; @@ -271,11 +253,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump) dump->regs = *regs; -#if 0 /* defined(__SH4__) */ - /* FPU */ - memcpy (&dump->regs[EF_SIZE/4], ¤t->thread.fpu, - sizeof (current->thread.fpu)); -#endif + dump->u_fpvalid = dump_fpu(regs, &dump->fpu); } /* @@ -284,11 +262,15 @@ void dump_thread(struct pt_regs * regs, struct user * dump) */ void __switch_to(struct task_struct *prev, struct task_struct *next) { +#if defined(__SH4__) + if (prev != &init_task) + unlazy_fpu(prev); +#endif /* * Restore the kernel stack onto kernel mode register * k4 (r4_bank1) */ - asm volatile("ldc %0,r4_bank" + asm volatile("ldc %0, $r4_bank" : /* no output */ :"r" ((unsigned long)next+8192)); } @@ -341,6 +323,7 @@ asmlinkage int sys_execve(char *ufilename, char **uargv, error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; + error = do_execve(filename, uargv, uenvp, ®s); if (error == 0) current->flags &= ~PF_DTRACE; @@ -349,3 +332,41 @@ out: unlock_kernel(); return error; } + +/* + * These bracket the sleeping functions.. + */ +extern void scheduling_functions_start_here(void); +extern void scheduling_functions_end_here(void); +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) + +unsigned long get_wchan(struct task_struct *p) +{ + unsigned long schedule_frame; + unsigned long pc; + + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + + /* + * The same comment as on the Alpha applies here, too ... + */ + pc = thread_saved_pc(&p->thread); + if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) { + schedule_frame = ((unsigned long *)(long)p->thread.sp)[1]; + return (unsigned long)((unsigned long *)schedule_frame)[1]; + } + return pc; +} + +asmlinkage void print_syscall(int x) +{ + unsigned long flags, sr; + asm("stc $sr, %0": "=r" (sr)); + save_and_cli(flags); + printk("%c: %c %c, %c: SYSCALL\n", (x&63)+32, + (current->flags&PF_USEDFPU)?'C':' ', + (init_task.flags&PF_USEDFPU)?'K':' ', (sr&SR_FD)?' ':'F'); + restore_flags(flags); +} diff --git a/arch/sh/kernel/semaphore.c b/arch/sh/kernel/semaphore.c index b9f565dd8..c958745b5 100644 --- a/arch/sh/kernel/semaphore.c +++ b/arch/sh/kernel/semaphore.c @@ -8,6 +8,8 @@ */ #include <linux/sched.h> +#include <linux/wait.h> +#include <asm/semaphore.h> #include <asm/semaphore-helper.h> /* @@ -131,3 +133,162 @@ int __down_trylock(struct semaphore * sem) { return waking_non_zero_trylock(sem); } + +/* Called when someone has done an up that transitioned from + * negative to non-negative, meaning that the lock has been + * granted to whomever owned the bias. + */ +struct rw_semaphore *rwsem_wake_readers(struct rw_semaphore *sem) +{ + if (xchg(&sem->read_bias_granted, 1)) + BUG(); + wake_up(&sem->wait); + return sem; +} + +struct rw_semaphore *rwsem_wake_writer(struct rw_semaphore *sem) +{ + if (xchg(&sem->write_bias_granted, 1)) + BUG(); + wake_up(&sem->write_bias_wait); + return sem; +} + +struct rw_semaphore * __rwsem_wake(struct rw_semaphore *sem) +{ + if (atomic_read(&sem->count) == 0) + return rwsem_wake_writer(sem); + else + return rwsem_wake_readers(sem); +} + +struct rw_semaphore *down_read_failed_biased(struct rw_semaphore *sem) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + add_wait_queue(&sem->wait, &wait); /* put ourselves at the head of the list */ + + for (;;) { + if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0)) + break; + set_task_state(tsk, TASK_UNINTERRUPTIBLE); + if (!sem->read_bias_granted) + schedule(); + } + + remove_wait_queue(&sem->wait, &wait); + tsk->state = TASK_RUNNING; + + return sem; +} + +struct rw_semaphore *down_write_failed_biased(struct rw_semaphore *sem) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */ + + for (;;) { + if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0)) + break; + set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + if (!sem->write_bias_granted) + schedule(); + } + + remove_wait_queue(&sem->write_bias_wait, &wait); + tsk->state = TASK_RUNNING; + + /* if the lock is currently unbiased, awaken the sleepers + * FIXME: this wakes up the readers early in a bit of a + * stampede -> bad! + */ + if (atomic_read(&sem->count) >= 0) + wake_up(&sem->wait); + + return sem; +} + +/* Wait for the lock to become unbiased. Readers + * are non-exclusive. =) + */ +struct rw_semaphore *down_read_failed(struct rw_semaphore *sem) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + __up_read(sem); /* this takes care of granting the lock */ + + add_wait_queue(&sem->wait, &wait); + + while (atomic_read(&sem->count) < 0) { + set_task_state(tsk, TASK_UNINTERRUPTIBLE); + if (atomic_read(&sem->count) >= 0) + break; + schedule(); + } + + remove_wait_queue(&sem->wait, &wait); + tsk->state = TASK_RUNNING; + + return sem; +} + +/* Wait for the lock to become unbiased. Since we're + * a writer, we'll make ourselves exclusive. + */ +struct rw_semaphore *down_write_failed(struct rw_semaphore *sem) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + __up_write(sem); /* this takes care of granting the lock */ + + add_wait_queue_exclusive(&sem->wait, &wait); + + while (atomic_read(&sem->count) < 0) { + set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + if (atomic_read(&sem->count) >= 0) + break; /* we must attempt to aquire or bias the lock */ + schedule(); + } + + remove_wait_queue(&sem->wait, &wait); + tsk->state = TASK_RUNNING; + + return sem; +} + +struct rw_semaphore *__down_read(struct rw_semaphore *sem, int carry) +{ + if (carry) { + int saved, new; + + do { + down_read_failed(sem); + saved = atomic_read(&sem->count); + if ((new = atomic_dec_return(&sem->count)) >= 0) + return sem; + } while (!(new < 0 && saved >=0)); + } + + return down_read_failed_biased(sem); +} + +struct rw_semaphore *__down_write(struct rw_semaphore *sem, int carry) +{ + if (carry) { + int saved, new; + + do { + down_write_failed(sem); + saved = atomic_read(&sem->count); + if ((new = atomic_sub_return(RW_LOCK_BIAS, &sem->count) ) == 0) + return sem; + } while (!(new < 0 && saved >=0)); + } + + return down_write_failed_biased(sem); +} diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index f97e66585..154283571 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.7 1999/10/23 01:34:50 gniibe Exp gniibe $ +/* $Id: setup.c,v 1.20 2000/03/05 02:44:41 gniibe Exp $ * * linux/arch/sh/kernel/setup.c * @@ -51,6 +51,7 @@ extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ extern int rd_image_start; /* starting block # of image */ #endif +extern void fpu_init(void); extern int root_mountflags; extern int _text, _etext, _edata, _end; @@ -196,82 +197,82 @@ void __init setup_arch(char **cmdline_p) #define PFN_PHYS(x) ((x) << PAGE_SHIFT) /* - * partially used pages are not usable - thus - * we are rounding upwards: - */ - start_pfn = PFN_UP(__pa(&_end)-__MEMORY_START); - - /* * Find the highest page frame number we have available */ - max_pfn = PFN_DOWN(__pa(memory_end)-__MEMORY_START); + max_pfn = PFN_DOWN(__pa(memory_end)); /* * Determine low and high memory ranges: */ max_low_pfn = max_pfn; + /* + * Partially used pages are not usable - thus + * we are rounding upwards: + */ + start_pfn = PFN_UP(__pa(&_end)); /* - * Initialize the boot-time allocator (with low memory only): - */ - bootmap_size = init_bootmem(start_pfn, max_low_pfn, __MEMORY_START); - - /* - * FIXME: what about high memory? + * Find a proper area for the bootmem bitmap. After this + * bootstrap step all allocations (until the page allocator + * is intact) must be done via bootmem_alloc(). */ - ram_resources[1].end = PFN_PHYS(max_low_pfn) + __MEMORY_START; + bootmap_size = init_bootmem_node(0, start_pfn, + __MEMORY_START>>PAGE_SHIFT, + max_low_pfn); /* * Register fully available low RAM pages with the bootmem allocator. */ { - unsigned long curr_pfn, last_pfn, size; + unsigned long curr_pfn, last_pfn, pages; /* * We are rounding up the start address of usable memory: */ - curr_pfn = PFN_UP(0); + curr_pfn = PFN_UP(__MEMORY_START); /* * ... and at the end of the usable range downwards: */ - last_pfn = PFN_DOWN(memory_end-__MEMORY_START); + last_pfn = PFN_DOWN(__pa(memory_end)); if (last_pfn > max_low_pfn) last_pfn = max_low_pfn; - size = last_pfn - curr_pfn; - free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size)); + pages = last_pfn - curr_pfn; + free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(pages)); } + /* * Reserve the kernel text and - * Reserve the bootmem bitmap itself as well. We do this in two - * steps (first step was init_bootmem()) because this catches - * the (very unlikely) case of us accidentally initializing the - * bootmem allocator with an invalid RAM area. + * Reserve the bootmem bitmap.We do this in two steps (first step + * was init_bootmem()), because this catches the (definitely buggy) + * case of us accidentally initializing the bootmem allocator with + * an invalid RAM area. */ - reserve_bootmem(PAGE_SIZE, PFN_PHYS(start_pfn) + bootmap_size); + reserve_bootmem(__MEMORY_START+PAGE_SIZE, (PFN_PHYS(start_pfn) + + bootmap_size + PAGE_SIZE-1) - __MEMORY_START); /* * reserve physical page 0 - it's a special BIOS page on many boxes, * enabling clean reboots, SMP operation, laptop functions. */ - reserve_bootmem(0, PAGE_SIZE); + reserve_bootmem(__MEMORY_START, PAGE_SIZE); #ifdef CONFIG_BLK_DEV_INITRD - if (LOADER_TYPE) { + if (LOADER_TYPE && INITRD_START) { if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) { - reserve_bootmem(INITRD_START, INITRD_SIZE); - initrd_start = - INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0; - initrd_end = initrd_start+INITRD_SIZE; + reserve_bootmem(INITRD_START+__MEMORY_START, INITRD_SIZE); + initrd_start = + INITRD_START ? INITRD_START + PAGE_OFFSET + __MEMORY_START : 0; + initrd_end = initrd_start + INITRD_SIZE; } else { - printk("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx)\ndisabling initrd\n", - INITRD_START + INITRD_SIZE, - max_low_pfn << PAGE_SHIFT); - initrd_start = 0; - } - } + printk("initrd extends beyond end of memory " + "(0x%08lx > 0x%08lx)\ndisabling initrd\n", + INITRD_START + INITRD_SIZE, + max_low_pfn << PAGE_SHIFT); + initrd_start = 0; + } + } #endif #if 0 @@ -298,6 +299,14 @@ void __init setup_arch(char **cmdline_p) conswitchp = &dummy_con; #endif #endif + +#if defined(__SH4__) + init_task.used_math = 1; + init_task.flags |= PF_USEDFPU; + grab_fpu(); + fpu_init(); +#endif + paging_init(); } /* diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c index 7c9fbbf00..0c24acf73 100644 --- a/arch/sh/kernel/signal.c +++ b/arch/sh/kernel/signal.c @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.10 1999/09/27 23:25:44 gniibe Exp $ +/* $Id: signal.c,v 1.16 2000/01/29 11:31:31 gniibe Exp gniibe $ * * linux/arch/sh/kernel/signal.c * @@ -54,7 +54,7 @@ sys_sigsuspend(old_sigset_t mask, while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(®s,&saveset)) + if (do_signal(®s, &saveset)) return -EINTR; } } @@ -73,7 +73,6 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, if (copy_from_user(&newset, unewset, sizeof(newset))) return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); saveset = current->blocked; current->blocked = newset; @@ -188,6 +187,7 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto badframe; + if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1 && __copy_from_user(&set.sig[1], &frame->extramask, @@ -195,6 +195,7 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); current->blocked = set; recalc_sigpending(current); @@ -220,6 +221,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto badframe; + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto badframe; @@ -228,7 +230,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, current->blocked = set; recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); - + if (restore_sigcontext(®s, &frame->uc.uc_mcontext, &r0)) goto badframe; @@ -317,7 +319,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, if (ka->sa.sa_flags & SA_RESTORER) { regs->pr = (unsigned long) ka->sa.sa_restorer; } else { - /* This is ; mov #__NR_sigreturn,r0 ; trapa #0 */ + /* This is : mov #__NR_sigreturn,r0 ; trapa #0 */ #ifdef __LITTLE_ENDIAN__ unsigned long code = 0xc300e000 | (__NR_sigreturn); #else @@ -390,11 +392,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, if (ka->sa.sa_flags & SA_RESTORER) { regs->pr = (unsigned long) ka->sa.sa_restorer; } else { - /* This is ; mov #__NR_sigreturn,r0 ; trapa #0 */ + /* This is : mov #__NR_rt_sigreturn,r0 ; trapa #0 */ #ifdef __LITTLE_ENDIAN__ - unsigned long code = 0xc300e000 | (__NR_sigreturn); + unsigned long code = 0xc300e000 | (__NR_rt_sigreturn); #else - unsigned long code = 0xe000c300 | (__NR_sigreturn << 16); + unsigned long code = 0xe000c300 | (__NR_rt_sigreturn << 16); #endif regs->pr = (unsigned long) frame->retcode; @@ -485,6 +487,15 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) siginfo_t info; struct k_sigaction *ka; + /* + * We want the common case to go fast, which + * is why we may in certain cases get here from + * kernel mode. Just return without doing anything + * if so. + */ + if (!user_mode(regs)) + return 1; + if (!oldset) oldset = ¤t->blocked; @@ -580,6 +591,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) /* NOTREACHED */ } } + /* Whee! Actually deliver the signal. */ handle_signal(signr, ka, &info, oldset, regs); return 1; diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c index 1b708e5a9..0b3d5fc2e 100644 --- a/arch/sh/kernel/sys_sh.c +++ b/arch/sh/kernel/sys_sh.c @@ -28,7 +28,9 @@ * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way Unix traditionally does this, though. */ -asmlinkage int sys_pipe(unsigned long * fildes) +asmlinkage int sys_pipe(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs regs) { int fd[2]; int error; @@ -37,46 +39,62 @@ asmlinkage int sys_pipe(unsigned long * fildes) error = do_pipe(fd); unlock_kernel(); if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) - error = -EFAULT; + regs.regs[1] = fd[1]; + return fd[0]; } return error; } -asmlinkage unsigned long -sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, - unsigned long flags, int fd, unsigned long off) +static inline long +do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, + unsigned long flags, int fd, unsigned long pgoff) { - int error = -EFAULT; + int error = -EBADF; struct file *file = NULL; - down(¤t->mm->mmap_sem); - lock_kernel(); + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { - error = -EBADF; file = fget(fd); if (!file) goto out; } - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - error = do_mmap(file, addr, len, prot, flags, off); - if (file) - fput(file); -out: + down(¤t->mm->mmap_sem); + lock_kernel(); + + error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); unlock_kernel(); up(¤t->mm->mmap_sem); + if (file) + fput(file); +out: return error; } +asmlinkage int old_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + int fd, unsigned long off) +{ + if (off & ~PAGE_MASK) + return -EINVAL; + return do_mmap2(addr, len, prot, flags, fd, off>>PAGE_SHIFT); +} + +asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + return do_mmap2(addr, len, prot, flags, fd, pgoff); +} + /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. * * This is really horribly ugly. */ -asmlinkage int sys_ipc (uint call, int first, int second, - int third, void *ptr, long fifth) +asmlinkage int sys_ipc(uint call, int first, int second, + int third, void *ptr, long fifth) { int version, ret; diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index 49a765f83..fad3a8145 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.7 1999/11/06 02:00:37 gniibe Exp $ +/* $Id: time.c,v 1.20 2000/02/28 12:42:51 gniibe Exp $ * * linux/arch/sh/kernel/time.c * @@ -8,8 +8,6 @@ * Copyright (C) 1991, 1992, 1995 Linus Torvalds */ -#include <linux/config.h> - #include <linux/errno.h> #include <linux/sched.h> #include <linux/kernel.h> @@ -43,10 +41,10 @@ #define TMU0_TCNT 0xfffffe98 /* Long access */ #define TMU0_TCR 0xfffffe9c /* Word access */ -#define INTERVAL 37500 /* (1000000*CLOCK_MHZ/HZ/2) ??? for CqREEK */ -#if 0 /* Takeshi's board */ -#define INTERVAL 83333 -#endif +#define FRQCR 0xffffff80 + +#define RTC_IRQ 22 +#define RTC_IPR_OFFSET 0 /* SH-3 RTC */ #define R64CNT 0xfffffec0 @@ -74,7 +72,10 @@ #define TMU0_TCNT 0xffd8000c /* Long access */ #define TMU0_TCR 0xffd80010 /* Word access */ -#define INTERVAL 83333 +#define FRQCR 0xffc00000 + +#define RTC_IRQ 22 +#define RTC_IPR_OFFSET 0 /* SH-4 RTC */ #define R64CNT 0xffc80000 @@ -145,11 +146,10 @@ void do_settimeofday(struct timeval *tv) static int set_rtc_time(unsigned long nowtime) { -#ifdef CONFIG_SH_CPU_RTC int retval = 0; int real_seconds, real_minutes, cmos_minutes; - ctrl_outb(2, RCR2); /* reset pre-scaler & stop RTC */ + ctrl_outb(0x02, RCR2); /* reset pre-scaler & stop RTC */ cmos_minutes = ctrl_inb(RMINCNT); BCD_TO_BIN(cmos_minutes); @@ -178,13 +178,9 @@ static int set_rtc_time(unsigned long nowtime) retval = -1; } - ctrl_outb(2, RCR2); /* start RTC */ + ctrl_outb(0x01, RCR2); /* start RTC */ return retval; -#else - /* XXX should support other clock devices? */ - return -1; -#endif } /* last time the RTC clock got updated */ @@ -197,7 +193,6 @@ static long last_rtc_update = 0; static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { do_timer(regs); - #ifdef TAKESHI { unsigned long what_is_this=0xa4000124; @@ -248,9 +243,7 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) * locally disabled. -arca */ write_lock(&xtime_lock); - do_timer_interrupt(irq, NULL, regs); - write_unlock(&xtime_lock); } @@ -287,11 +280,10 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon, static unsigned long get_rtc_time(void) { -#ifdef CONFIG_SH_CPU_RTC unsigned int sec, min, hr, wk, day, mon, yr, yr100; again: - ctrl_outb(1, RCR1); /* clear CF bit */ + ctrl_outb(0x01, RCR1); /* clear CF bit */ do { sec = ctrl_inb(RSECCNT); min = ctrl_inb(RMINCNT); @@ -321,7 +313,7 @@ static unsigned long get_rtc_time(void) hr > 23 || min > 59 || sec > 59) { printk(KERN_ERR "SH RTC: invalid value, resetting to 1 Jan 2000\n"); - ctrl_outb(2, RCR2); /* reset, stop */ + ctrl_outb(0x02, RCR2); /* reset, stop */ ctrl_outb(0, RSECCNT); ctrl_outb(0, RMINCNT); ctrl_outb(0, RHRCNT); @@ -333,36 +325,114 @@ static unsigned long get_rtc_time(void) #else ctrl_outb(0, RYRCNT); #endif - ctrl_outb(1, RCR2); /* start */ + ctrl_outb(0x01, RCR2); /* start */ goto again; } return mktime(yr100 * 100 + yr, mon, day, hr, min, sec); +} + +static __init unsigned int get_cpu_mhz(void) +{ + unsigned int count; + unsigned long __dummy; + + sti(); + do {} while (ctrl_inb(R64CNT) != 0); + ctrl_outb(0x11, RCR1); + asm volatile( + "1:\t" + "tst %1,%1\n\t" + "bt/s 1b\n\t" + " add #1,%0" + : "=&r"(count), "=&z" (__dummy) + : "0" (0), "1" (0)); + cli(); + /* + * SH-3: + * CPU clock = 4 stages * loop + * tst rm,rm if id ex + * bt/s 1b if id ex + * add #1,rd if id ex + * (if) pipe line stole + * tst rm,rm if id ex + * .... + * + * + * SH-4: + * CPU clock = 6 stages * loop + * I don't know why. + * .... + */ +#if defined(__SH4__) + return count*6; #else - /* XXX should support other clock devices? */ - return 0; + return count*4; #endif } +static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + ctrl_outb(0x01, RCR1); + regs->regs[0] = 1; +} + static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL}; +static struct irqaction irq1 = { rtc_interrupt, SA_INTERRUPT, 0, "rtc", NULL, NULL}; void __init time_init(void) { + unsigned int cpu_clock, master_clock, module_clock; + unsigned short ifc, pfc; + unsigned long interval; +#if defined(__sh3__) + static int ifc_table[] = { 1, 2, 4, 1, 3, 1, 1, 1 }; + static int pfc_table[] = { 1, 2, 4, 1, 3, 6, 1, 1 }; +#elif defined(__SH4__) + static int ifc_table[] = { 1, 2, 3, 4, 6, 8, 1, 1 }; + static int pfc_table[] = { 2, 3, 4, 6, 8, 2, 2, 2 }; +#endif + xtime.tv_sec = get_rtc_time(); xtime.tv_usec = 0; - set_ipr_data(TIMER_IRQ, TIMER_IRP_OFFSET, TIMER_PRIORITY); + set_ipr_data(TIMER_IRQ, TIMER_IPR_OFFSET, TIMER_PRIORITY); setup_irq(TIMER_IRQ, &irq0); + set_ipr_data(RTC_IRQ, RTC_IPR_OFFSET, TIMER_PRIORITY); + setup_irq(RTC_IRQ, &irq1); - /* Start TMU0 */ - ctrl_outb(TMU_TOCR_INIT,TMU_TOCR); - ctrl_outw(TMU0_TCR_INIT,TMU0_TCR); - ctrl_outl(INTERVAL,TMU0_TCOR); - ctrl_outl(INTERVAL,TMU0_TCNT); - ctrl_outb(TMU_TSTR_INIT,TMU_TSTR); + /* Check how fast it is.. */ + cpu_clock = get_cpu_mhz(); + disable_irq(RTC_IRQ); -#if 0 - /* Start RTC */ - asm volatile(""); + printk("CPU clock: %d.%02dMHz\n", + (cpu_clock / 1000000), (cpu_clock % 1000000)/10000); +#if defined(__sh3__) + { + unsigned short tmp; + tmp = (ctrl_inw(FRQCR) & 0x000c) >> 2; + tmp |= (ctrl_inw(FRQCR) & 0x4000) >> 12; + ifc = ifc_table[tmp & 0x0007]; + tmp = ctrl_inw(FRQCR) & 0x0003; + tmp |= (ctrl_inw(FRQCR) & 0x2000) >> 11; + pfc = pfc_table[ctrl_inw(FRQCR) & 0x0007]; + } +#elif defined(__SH4__) + ifc = ifc_table[(ctrl_inw(FRQCR)>> 6) & 0x0007]; + pfc = pfc_table[ctrl_inw(FRQCR) & 0x0007]; #endif + master_clock = cpu_clock * ifc; + module_clock = master_clock/pfc; + printk("Module clock: %d.%02dMHz\n", + (module_clock/1000000), (module_clock % 1000000)/10000); + interval = (module_clock/400); + + printk("Interval = %ld\n", interval); + + /* Start TMU0 */ + ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); + ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); + ctrl_outl(interval, TMU0_TCOR); + ctrl_outl(interval, TMU0_TCNT); + ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); } diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c index 8a9b3e1f9..98431cb36 100644 --- a/arch/sh/kernel/traps.c +++ b/arch/sh/kernel/traps.c @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.3 1999/09/21 14:37:19 gniibe Exp $ +/* $Id: traps.c,v 1.5 2000/02/27 08:27:55 gniibe Exp $ * * linux/arch/sh/traps.c * @@ -26,6 +26,7 @@ #include <asm/uaccess.h> #include <asm/io.h> #include <asm/atomic.h> +#include <asm/processor.h> static inline void console_verbose(void) { @@ -40,7 +41,7 @@ asmlinkage void do_##name(unsigned long r4, unsigned long r5, \ { \ unsigned long error_code; \ \ - asm volatile("stc r2_bank,%0": "=r" (error_code)); \ + asm volatile("stc $r2_bank, %0": "=r" (error_code)); \ sti(); \ regs.syscall_nr = -1; \ tsk->thread.error_code = error_code; \ @@ -99,7 +100,7 @@ asmlinkage void do_exception_error (unsigned long r4, unsigned long r5, struct pt_regs regs) { long ex; - asm volatile("stc r2_bank,%0" : "=r" (ex)); + asm volatile("stc $r2_bank, %0" : "=r" (ex)); die_if_kernel("exception", ®s, ex); } @@ -117,8 +118,22 @@ void __init trap_init(void) (or P2, virtural "fixed" address space). It's definitely should not in physical address. */ - asm volatile("ldc %0,vbr" + asm volatile("ldc %0, $vbr" : /* no output */ : "r" (&vbr_base) : "memory"); } + +void dump_stack(void) +{ + unsigned long *start; + unsigned long *end; + unsigned long *p; + + asm("mov $r15, %0" : "=r" (start)); + asm("stc $r4_bank, %0" : "=r" (end)); + + printk("%08lx:%08lx\n", (unsigned long)start, (unsigned long)end); + for (p=start; p < end; p++) + printk("%08lx\n", *p); +} diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c index d15c62385..f5c5200be 100644 --- a/arch/sh/mm/cache.c +++ b/arch/sh/mm/cache.c @@ -1,4 +1,4 @@ -/* $Id: cache.c,v 1.7 1999/09/23 11:43:07 gniibe Exp $ +/* $Id: cache.c,v 1.9 2000/02/14 12:45:26 gniibe Exp $ * * linux/arch/sh/mm/cache.c * @@ -283,7 +283,30 @@ void __init cache_init(void) } #if defined(__SH4__) -/* Write back data caches, and invalidates instructiin caches */ +void flush_icache_page(struct vm_area_struct *vma, struct page *pg) +{ + unsigned long flags, __dummy; + unsigned long addr, data, v; + + save_and_cli(flags); + jump_to_p2(__dummy); + + v = page_address(pg); + + /* Write back O Cache */ + asm volatile("ocbwb %0" + : /* no output */ + : "m" (__m(v))); + /* Invalidate I Cache */ + addr = CACHE_IC_ADDRESS_ARRAY | + (v&CACHE_IC_ENTRY_MASK) | 0x8 /* A-bit */; + data = (v&0xfffffc00); /* Valid=0 */ + ctrl_outl(data,addr); + + back_to_p1(__dummy); + restore_flags(flags); +} + void flush_icache_range(unsigned long start, unsigned long end) { unsigned long flags, __dummy; @@ -358,7 +381,7 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long addr) flush_cache_range(vma->vm_mm, addr, addr+PAGE_SIZE); } -void flush_page_to_ram(unsigned long page) +void __flush_page_to_ram(unsigned long page) { /* Page is in physical address */ /* XXX: for the time being... */ flush_cache_all(); diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c index 7f3610a3b..3b8e86e36 100644 --- a/arch/sh/mm/fault.c +++ b/arch/sh/mm/fault.c @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.5 1999/10/31 13:17:31 gniibe Exp $ +/* $Id: fault.c,v 1.12 2000/03/01 11:15:27 gniibe Exp $ * * linux/arch/sh/mm/fault.c * Copyright (C) 1999 Niibe Yutaka @@ -23,7 +23,7 @@ #include <asm/system.h> #include <asm/io.h> #include <asm/uaccess.h> -#include <asm/pgtable.h> +#include <asm/pgalloc.h> #include <asm/hardirq.h> #include <asm/mmu_context.h> @@ -211,10 +211,12 @@ no_context: printk(KERN_ALERT "Unable to handle kernel paging request"); printk(" at virtual address %08lx\n",address); printk(KERN_ALERT "pc = %08lx\n", regs->pc); - page = (unsigned long)mm->pgd; - page = ((unsigned long *) __va(page))[address >> 22]; + asm volatile("mov.l %1,%0" + : "=r" (page) + : "m" (__m(MMU_TTB))); + page = ((unsigned long *) page)[address >> 22]; printk(KERN_ALERT "*pde = %08lx\n", page); - if (page & 1) { + if (page & _PAGE_PRESENT) { page &= PAGE_MASK; address &= 0x003ff000; page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT]; @@ -256,6 +258,7 @@ void update_mmu_cache(struct vm_area_struct * vma, { unsigned long flags; unsigned long pteval; + unsigned long pteaddr; save_and_cli(flags); /* @@ -267,6 +270,9 @@ void update_mmu_cache(struct vm_area_struct * vma, pteval |= _PAGE_FLAGS_HARDWARE_DEFAULT; /* add default flags */ /* Set PTEL register */ ctrl_outl(pteval, MMU_PTEL); + /* Set PTEH register */ + pteaddr = (address & MMU_VPN_MASK) | (vma->vm_mm->context & MMU_CONTEXT_ASID_MASK); + ctrl_outl(pteaddr, MMU_PTEH); /* Load the TLB */ asm volatile("ldtlb": /* no output */ : /* no input */ : "memory"); @@ -277,6 +283,9 @@ static void __flush_tlb_page(struct mm_struct *mm, unsigned long page) { unsigned long addr, data, asid; unsigned long saved_asid = MMU_NO_ASID; +#if defined(__SH4__) + int i; +#endif if (mm->context == NO_CONTEXT) return; @@ -296,8 +305,6 @@ static void __flush_tlb_page(struct mm_struct *mm, unsigned long page) data = (page & 0xfffe0000) | asid; /* VALID bit is off */ ctrl_outl(data, addr); #elif defined(__SH4__) - int i; - addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT; data = page | asid; /* VALID bit is off */ ctrl_outl(data, addr); @@ -305,7 +312,7 @@ static void __flush_tlb_page(struct mm_struct *mm, unsigned long page) for (i=0; i<4; i++) { addr = MMU_ITLB_ADDRESS_ARRAY | (i<<8); data = ctrl_inl(addr); - data &= ~0x30; + data &= ~0x300; if (data == (page | asid)) { ctrl_outl(data, addr); break; diff --git a/arch/sh/mm/init.c b/arch/sh/mm/init.c index 458685f4a..776389cac 100644 --- a/arch/sh/mm/init.c +++ b/arch/sh/mm/init.c @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.4 1999/10/23 01:37:02 gniibe Exp gniibe $ +/* $Id: init.c,v 1.16 2000/02/14 15:19:05 gniibe Exp $ * * linux/arch/sh/mm/init.c * @@ -24,12 +24,14 @@ #ifdef CONFIG_BLK_DEV_INITRD #include <linux/blk.h> #endif +#include <linux/highmem.h> #include <linux/bootmem.h> #include <asm/processor.h> #include <asm/system.h> #include <asm/uaccess.h> #include <asm/pgtable.h> +#include <asm/pgalloc.h> #include <asm/mmu_context.h> #include <asm/io.h> @@ -77,13 +79,13 @@ static pte_t * get_bad_pte_table(void) void __handle_bad_pmd(pmd_t *pmd) { pmd_ERROR(*pmd); - pmd_val(*pmd) = _PAGE_TABLE + __pa(get_bad_pte_table()); + set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(get_bad_pte_table()))); } void __handle_bad_pmd_kernel(pmd_t *pmd) { pmd_ERROR(*pmd); - pmd_val(*pmd) = _KERNPG_TABLE + __pa(get_bad_pte_table()); + set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(get_bad_pte_table()))); } pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset) @@ -94,10 +96,10 @@ pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset) if (pmd_none(*pmd)) { if (pte) { clear_page(pte); - pmd_val(*pmd) = _KERNPG_TABLE + __pa(pte); + set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte))); return pte + offset; } - pmd_val(*pmd) = _KERNPG_TABLE + __pa(get_bad_pte_table()); + set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(get_bad_pte_table()))); return NULL; } free_page((unsigned long)pte); @@ -116,10 +118,10 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) if (pmd_none(*pmd)) { if (pte) { clear_page((void *)pte); - pmd_val(*pmd) = _PAGE_TABLE + __pa(pte); + set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))); return (pte_t *)pte + offset; } - pmd_val(*pmd) = _PAGE_TABLE + __pa(get_bad_pte_table()); + set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(get_bad_pte_table()))); return NULL; } free_page(pte); @@ -133,15 +135,15 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) int do_check_pgt_cache(int low, int high) { int freed = 0; - if(pgtable_cache_size > high) { + if (pgtable_cache_size > high) { do { - if(pgd_quicklist) + if (pgd_quicklist) free_pgd_slow(get_pgd_fast()), freed++; - if(pmd_quicklist) + if (pmd_quicklist) free_pmd_slow(get_pmd_fast()), freed++; - if(pte_quicklist) + if (pte_quicklist) free_pte_slow(get_pte_fast()), freed++; - } while(pgtable_cache_size > low); + } while (pgtable_cache_size > low); } return freed; } @@ -181,6 +183,10 @@ extern char __init_begin, __init_end; pgd_t swapper_pg_dir[1024]; +/* It'd be good if these lines were in the standard header file. */ +#define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT) +#define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn) + /* * paging_init() sets up the page tables * @@ -204,32 +210,55 @@ void __init paging_init(void) mmu_context_cache = MMU_CONTEXT_FIRST_VERSION; set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK); - free_area_init(max_low_pfn); + { + unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; + unsigned long max_dma, low, start_pfn; + + start_pfn = START_PFN; + max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; + low = MAX_LOW_PFN; + + if (low < max_dma) + zones_size[ZONE_DMA] = low - start_pfn; + else { + zones_size[ZONE_DMA] = max_dma - start_pfn; + zones_size[ZONE_NORMAL] = low - max_dma; + } + free_area_init_node(0, 0, zones_size, __MEMORY_START); + } } void __init mem_init(void) { - int codepages = 0; - int reservedpages = 0; - int datapages = 0; - int initpages = 0; + int codesize, reservedpages, datasize, initsize; + int tmp; - max_mapnr = num_physpages = max_low_pfn; - high_memory = (void *) ((unsigned long)__va(max_low_pfn * PAGE_SIZE)+__MEMORY_START); + max_mapnr = num_physpages = MAX_LOW_PFN - START_PFN; + high_memory = (void *)__va(MAX_LOW_PFN * PAGE_SIZE); /* clear the zero-page */ memset(empty_zero_page, 0, PAGE_SIZE); /* this will put all low memory onto the freelists */ totalram_pages += free_all_bootmem(); + reservedpages = 0; + for (tmp = 0; tmp < num_physpages; tmp++) + /* + * Only count reserved RAM pages + */ + if (PageReserved(mem_map+tmp)) + reservedpages++; + codesize = (unsigned long) &_etext - (unsigned long) &_text; + datasize = (unsigned long) &_edata - (unsigned long) &_etext; + initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n", - (unsigned long) nr_free_pages << (PAGE_SHIFT-10), + (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), max_mapnr << (PAGE_SHIFT-10), - codepages << (PAGE_SHIFT-10), + codesize >> 10, reservedpages << (PAGE_SHIFT-10), - datapages << (PAGE_SHIFT-10), - initpages << (PAGE_SHIFT-10)); + datasize >> 10, + initsize >> 10); } void free_initmem(void) @@ -246,14 +275,28 @@ void free_initmem(void) printk ("Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10); } +#ifdef CONFIG_BLK_DEV_INITRD +void free_initrd_mem(unsigned long start, unsigned long end) +{ + unsigned long p; + for (p = start; p < end; p += PAGE_SIZE) { + ClearPageReserved(mem_map + MAP_NR(p)); + set_page_count(mem_map+MAP_NR(p), 1); + free_page(p); + totalram_pages++; + } + printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); +} +#endif + void si_meminfo(struct sysinfo *val) { val->totalram = totalram_pages; val->sharedram = 0; - val->freeram = nr_free_pages; + val->freeram = nr_free_pages(); val->bufferram = atomic_read(&buffermem_pages); val->totalhigh = totalhigh_pages; - val->freehigh = nr_free_highpages; + val->freehigh = nr_free_highpages(); val->mem_unit = PAGE_SIZE; return; } diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c index c12b97d18..2dd1e6ec2 100644 --- a/arch/sh/mm/ioremap.c +++ b/arch/sh/mm/ioremap.c @@ -1,4 +1,4 @@ -/* $Id: ioremap.c,v 1.1 1999/09/18 16:57:48 gniibe Exp $ +/* $Id: ioremap.c,v 1.2 1999/11/25 14:00:28 gniibe Exp $ * * arch/sh/mm/ioremap.c * @@ -11,6 +11,7 @@ #include <linux/vmalloc.h> #include <asm/io.h> +#include <asm/pgalloc.h> static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, unsigned long phys_addr, unsigned long flags) diff --git a/arch/sh/vmlinux.lds.S b/arch/sh/vmlinux.lds.S index 688c4c9c4..53a7fff56 100644 --- a/arch/sh/vmlinux.lds.S +++ b/arch/sh/vmlinux.lds.S @@ -1,4 +1,4 @@ -/* $Id: vmlinux.lds.S,v 1.3 1999/10/05 12:33:48 gniibe Exp $ +/* $Id: vmlinux.lds.S,v 1.4 1999/12/23 11:37:45 gniibe Exp $ * ld script to make SuperH Linux kernel * Written by Niibe Yutaka */ @@ -13,8 +13,8 @@ ENTRY(_start) SECTIONS { . = 0x80000000 + CONFIG_MEMORY_START + 0x1000; - __text = .; /* Text and read-only data */ _text = .; /* Text and read-only data */ + text = .; /* Text and read-only data */ .text : { *(.empty_zero_page) *(.text) @@ -26,41 +26,41 @@ SECTIONS .kstrtab : { *(.kstrtab) } . = ALIGN(16); /* Exception table */ - ___start___ex_table = .; - ___ex_table : { *(__ex_table) } - ___stop___ex_table = .; + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; - ___start___ksymtab = .; /* Kernel symbol table */ - ___ksymtab : { *(__ksymtab) } - ___stop___ksymtab = .; + __start___ksymtab = .; /* Kernel symbol table */ + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; - __etext = .; /* End of text section */ + _etext = .; /* End of text section */ .data : { /* Data */ *(.data) CONSTRUCTORS } - __edata = .; /* End of data section */ + _edata = .; /* End of data section */ . = ALIGN(8192); /* init_task */ .data.init_task : { *(.data.init_task) } /* stack */ - .stack : { _stack = .; __stack = .; } + .stack : { stack = .; _stack = .; } . = ALIGN(4096); /* Init code and data */ - ___init_begin = .; + __init_begin = .; .text.init : { *(.text.init) } .data.init : { *(.data.init) } . = ALIGN(16); - ___setup_start = .; + __setup_start = .; .setup.init : { *(.setup.init) } - ___setup_end = .; - ___initcall_start = .; + __setup_end = .; + __initcall_start = .; .initcall.init : { *(.initcall.init) } - ___initcall_end = .; + __initcall_end = .; . = ALIGN(4096); - ___init_end = .; + __init_end = .; . = ALIGN(4096); .data.page_aligned : { *(.data.idt) } @@ -69,12 +69,12 @@ SECTIONS .data.cacheline_aligned : { *(.data.cacheline_aligned) } . = ALIGN(4); - ___bss_start = .; /* BSS */ + __bss_start = .; /* BSS */ .bss : { *(.bss) } . = ALIGN(4); - __end = . ; + _end = . ; /* Stabs debugging sections. */ .stab 0 : { *(.stab) } diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c index 82b5ac653..54c701768 100644 --- a/arch/sparc/kernel/sys_sunos.c +++ b/arch/sparc/kernel/sys_sunos.c @@ -432,12 +432,10 @@ static int sunos_filldir(void * __buf, const char * name, int namlen, asmlinkage int sunos_getdents(unsigned int fd, void * dirent, int cnt) { struct file * file; - struct inode * inode; struct sunos_dirent * lastdirent; struct sunos_dirent_callback buf; int error = -EBADF; - lock_kernel(); if (fd >= SUNOS_NR_OPEN) goto out; @@ -445,10 +443,7 @@ asmlinkage int sunos_getdents(unsigned int fd, void * dirent, int cnt) if (!file) goto out; - error = -ENOTDIR; - if (!file->f_op || !file->f_op->readdir) - goto out_putf; - + lock_kernel(); error = -EINVAL; if (cnt < (sizeof(struct sunos_dirent) + 255)) goto out_putf; @@ -458,10 +453,7 @@ asmlinkage int sunos_getdents(unsigned int fd, void * dirent, int cnt) buf.count = cnt; buf.error = 0; - inode = file->f_dentry->d_inode; - down(&inode->i_sem); - error = file->f_op->readdir(file, &buf, sunos_filldir); - up(&inode->i_sem); + error = vfs_readdir(file, sunos_filldir, &buf); if (error < 0) goto out_putf; @@ -473,9 +465,9 @@ asmlinkage int sunos_getdents(unsigned int fd, void * dirent, int cnt) } out_putf: + unlock_kernel(); fput(file); out: - unlock_kernel(); return error; } @@ -521,12 +513,10 @@ static int sunos_filldirentry(void * __buf, const char * name, int namlen, asmlinkage int sunos_getdirentries(unsigned int fd, void * dirent, int cnt, unsigned int *basep) { struct file * file; - struct inode * inode; struct sunos_direntry * lastdirent; struct sunos_direntry_callback buf; int error = -EBADF; - lock_kernel(); if (fd >= SUNOS_NR_OPEN) goto out; @@ -534,10 +524,7 @@ asmlinkage int sunos_getdirentries(unsigned int fd, void * dirent, int cnt, unsi if (!file) goto out; - error = -ENOTDIR; - if (!file->f_op || !file->f_op->readdir) - goto out_putf; - + lock_kernel(); error = -EINVAL; if(cnt < (sizeof(struct sunos_direntry) + 255)) goto out_putf; @@ -547,10 +534,7 @@ asmlinkage int sunos_getdirentries(unsigned int fd, void * dirent, int cnt, unsi buf.count = cnt; buf.error = 0; - inode = file->f_dentry->d_inode; - down(&inode->i_sem); - error = file->f_op->readdir(file, &buf, sunos_filldirentry); - up(&inode->i_sem); + error = vfs_readdir(file, sunos_filldirentry, &buf); if (error < 0) goto out_putf; @@ -562,9 +546,9 @@ asmlinkage int sunos_getdirentries(unsigned int fd, void * dirent, int cnt, unsi } out_putf: + unlock_kernel(); fput(file); out: - unlock_kernel(); return error; } diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index df636ec6f..2ab8b70d4 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.112 2000/01/14 07:12:31 davem Exp $ +/* $Id: entry.S,v 1.113 2000/03/06 22:33:42 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -927,7 +927,17 @@ ret_from_syscall: nop ldx [%g6 + AOFF_task_thread + AOFF_thread_pcr_reg], %o7 wr %g0, %o7, %pcr - wr %g0, %g0, %pic + + /* Blackbird errata workaround. See commentary in + * smp.c:smp_percpu_timer_interrupt() for more + * information. + */ + ba,pt %xcc, 99f + nop + .align 64 +99: wr %g0, %g0, %pic + rd %pic, %g0 + 1: b,pt %xcc, ret_sys_call ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0], %o0 sparc_exit: rdpr %otherwin, %g1 diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index 47a170f54..7eefa9f65 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.63 1999/11/19 05:52:49 davem Exp $ +/* $Id: head.S,v 1.64 2000/03/06 22:33:42 davem Exp $ * head.S: Initial boot code for the Sparc64 port of Linux. * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) @@ -262,7 +262,16 @@ sun4u_init: /* Setup "Linux Current Register", thanks Sun 8-) */ wr %g0, 0x1, %pcr - wr %g6, 0x0, %pic + + /* Blackbird errata workaround. See commentary in + * smp.c:smp_percpu_timer_interrupt() for more + * information. + */ + ba,pt %xcc, 99f + nop + .align 64 +99: wr %g6, %g0, %pic + rd %pic, %g0 #endif wr %g0, ASI_P, %asi diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index ed2e8bd81..0d1b968fa 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.51 2000/02/26 04:24:32 davem Exp $ +/* $Id: setup.c,v 1.52 2000/03/03 23:48:41 davem Exp $ * linux/arch/sparc64/kernel/setup.c * * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) @@ -164,9 +164,17 @@ int prom_callback(long *args) } if ((va >= KERNBASE) && (va < (KERNBASE + (4 * 1024 * 1024)))) { + /* Spitfire Errata #32 workaround */ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "flush %%g6" + : /* No outputs */ + : "r" (0), + "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); + /* * Locked down tlb entry 63. */ + tte = spitfire_get_dtlb_data(63); res = PROM_TRUE; goto done; diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index 175372877..96360b010 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c @@ -312,6 +312,13 @@ static inline void xcall_deliver(u64 data0, u64 data1, u64 data2, u64 pstate, un smp_processor_id(), data0, data1, data2, target); #endif again: + /* Ok, this is the real Spitfire Errata #54. + * One must read back from a UDB internal register + * after writes to the UDB interrupt dispatch, but + * before the membar Sync for that write. + * So we use the high UDB control register (ASI 0x7f, + * ADDR 0x20) for the dummy read. -DaveM + */ tmp = 0x40; __asm__ __volatile__(" wrpr %1, %2, %%pstate @@ -321,10 +328,13 @@ again: stxa %6, [%0+%8] %3 membar #Sync stxa %%g0, [%7] %3 + mov 0x20, %%g1 + ldxa [%%g1] 0x7f, %%g0 membar #Sync" : "=r" (tmp) : "r" (pstate), "i" (PSTATE_IE), "i" (ASI_UDB_INTR_W), - "r" (data0), "r" (data1), "r" (data2), "r" (target), "r" (0x10), "0" (tmp)); + "r" (data0), "r" (data1), "r" (data2), "r" (target), "r" (0x10), "0" (tmp) + : "g1"); /* NOTE: PSTATE_IE is still clear. */ stuck = 100000; diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 6e2d566b2..d3f02ae54 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1257,10 +1257,8 @@ asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, { int error = -EBADF; struct file * file; - struct inode * inode; struct readdir_callback32 buf; - lock_kernel(); file = fget(fd); if (!file) goto out; @@ -1268,22 +1266,16 @@ asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, buf.count = 0; buf.dirent = dirent; - error = -ENOTDIR; - if (!file->f_op || !file->f_op->readdir) - goto out_putf; - - inode = file->f_dentry->d_inode; - down(&inode->i_sem); - error = file->f_op->readdir(file, &buf, fillonedir); - up(&inode->i_sem); + lock_kernel(); + error = vfs_readdir(file, fillonedir, &buf); if (error < 0) goto out_putf; error = buf.count; out_putf: + unlock_kernel(); fput(file); out: - unlock_kernel(); return error; } @@ -1328,12 +1320,10 @@ static int filldir(void * __buf, const char * name, int namlen, off_t offset, in asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, unsigned int count) { struct file * file; - struct inode * inode; struct linux_dirent32 * lastdirent; struct getdents_callback32 buf; int error = -EBADF; - lock_kernel(); file = fget(fd); if (!file) goto out; @@ -1343,14 +1333,8 @@ asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, un buf.count = count; buf.error = 0; - error = -ENOTDIR; - if (!file->f_op || !file->f_op->readdir) - goto out_putf; - - inode = file->f_dentry->d_inode; - down(&inode->i_sem); - error = file->f_op->readdir(file, &buf, filldir); - up(&inode->i_sem); + lock_kernel(); + error = vfs_readdir(file, filldir, &buf); if (error < 0) goto out_putf; lastdirent = buf.previous; @@ -1360,9 +1344,9 @@ asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, un error = count - buf.count; } out_putf: + unlock_kernel(); fput(file); out: - unlock_kernel(); return error; } diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c index c5101248a..d977c7952 100644 --- a/arch/sparc64/kernel/sys_sunos32.c +++ b/arch/sparc64/kernel/sys_sunos32.c @@ -388,13 +388,11 @@ static int sunos_filldir(void * __buf, const char * name, int namlen, asmlinkage int sunos_getdents(unsigned int fd, u32 u_dirent, int cnt) { struct file * file; - struct inode * inode; struct sunos_dirent * lastdirent; struct sunos_dirent_callback buf; int error = -EBADF; void *dirent = (void *)A(u_dirent); - lock_kernel(); if(fd >= SUNOS_NR_OPEN) goto out; @@ -402,9 +400,7 @@ asmlinkage int sunos_getdents(unsigned int fd, u32 u_dirent, int cnt) if(!file) goto out; - error = -ENOTDIR; - if (!file->f_op || !file->f_op->readdir) - goto out_putf; + lock_kernel(); error = -EINVAL; if(cnt < (sizeof(struct sunos_dirent) + 255)) @@ -415,10 +411,7 @@ asmlinkage int sunos_getdents(unsigned int fd, u32 u_dirent, int cnt) buf.count = cnt; buf.error = 0; - inode = file->f_dentry->d_inode; - down(&inode->i_sem); - error = file->f_op->readdir(file, &buf, sunos_filldir); - up(&inode->i_sem); + error = vfs_readdir(file, sunos_filldir, &buf); if (error < 0) goto out_putf; @@ -430,9 +423,9 @@ asmlinkage int sunos_getdents(unsigned int fd, u32 u_dirent, int cnt) } out_putf: + unlock_kernel(); fput(file); out: - unlock_kernel(); return error; } @@ -481,12 +474,10 @@ asmlinkage int sunos_getdirentries(unsigned int fd, u32 u_dirent, void *dirent = (void *) A(u_dirent); unsigned int *basep = (unsigned int *)A(u_basep); struct file * file; - struct inode * inode; struct sunos_direntry * lastdirent; int error = -EBADF; struct sunos_direntry_callback buf; - lock_kernel(); if(fd >= SUNOS_NR_OPEN) goto out; @@ -494,9 +485,7 @@ asmlinkage int sunos_getdirentries(unsigned int fd, u32 u_dirent, if(!file) goto out; - error = -ENOTDIR; - if (!file->f_op || !file->f_op->readdir) - goto out_putf; + lock_kernel(); error = -EINVAL; if(cnt < (sizeof(struct sunos_direntry) + 255)) @@ -507,10 +496,7 @@ asmlinkage int sunos_getdirentries(unsigned int fd, u32 u_dirent, buf.count = cnt; buf.error = 0; - inode = file->f_dentry->d_inode; - down(&inode->i_sem); - error = file->f_op->readdir(file, &buf, sunos_filldirentry); - up(&inode->i_sem); + error = vfs_readdir(file, sunos_filldirentry, &buf); if (error < 0) goto out_putf; @@ -522,9 +508,9 @@ asmlinkage int sunos_getdirentries(unsigned int fd, u32 u_dirent, } out_putf: + unlock_kernel(); fput(file); out: - unlock_kernel(); return error; } diff --git a/arch/sparc64/lib/blockops.S b/arch/sparc64/lib/blockops.S index 1aa48643c..1cdbf09da 100644 --- a/arch/sparc64/lib/blockops.S +++ b/arch/sparc64/lib/blockops.S @@ -1,4 +1,4 @@ -/* $Id: blockops.S,v 1.19 1999/11/19 05:52:45 davem Exp $ +/* $Id: blockops.S,v 1.20 2000/03/03 23:48:38 davem Exp $ * blockops.S: UltraSparc block zero optimized routines. * * Copyright (C) 1996,1998 David S. Miller (davem@caip.rutgers.edu) @@ -46,13 +46,37 @@ copy_page: /* %o0=dest, %o1=src */ sethi %hi(TLBTEMP_ENT1), %o3 rdpr %pstate, %g3 wrpr %g3, PSTATE_IE, %pstate + + /* Spitfire Errata #32 workaround */ + mov 0x8, %o4 + stxa %g0, [%o4] ASI_DMMU + flush %g6 + ldxa [%o3] ASI_DTLB_TAG_READ, %o4 + + /* Spitfire Errata #32 workaround */ + mov 0x8, %o5 + stxa %g0, [%o5] ASI_DMMU + flush %g6 + ldxa [%o3] ASI_DTLB_DATA_ACCESS, %o5 stxa %o0, [%o2] ASI_DMMU stxa %g1, [%o3] ASI_DTLB_DATA_ACCESS membar #Sync add %o3, (TLBTEMP_ENTSZ), %o3 + + /* Spitfire Errata #32 workaround */ + mov 0x8, %g5 + stxa %g0, [%g5] ASI_DMMU + flush %g6 + ldxa [%o3] ASI_DTLB_TAG_READ, %g5 + + /* Spitfire Errata #32 workaround */ + mov 0x8, %g7 + stxa %g0, [%g7] ASI_DMMU + flush %g6 + ldxa [%o3] ASI_DTLB_DATA_ACCESS, %g7 stxa %o1, [%o2] ASI_DMMU stxa %g2, [%o3] ASI_DTLB_DATA_ACCESS @@ -120,7 +144,19 @@ clear_page: /* %o0=dest */ sethi %hi(TLBTEMP_ENT2), %o3 rdpr %pstate, %g3 wrpr %g3, PSTATE_IE, %pstate + + /* Spitfire Errata #32 workaround */ + mov 0x8, %g5 + stxa %g0, [%g5] ASI_DMMU + flush %g6 + ldxa [%o3] ASI_DTLB_TAG_READ, %g5 + + /* Spitfire Errata #32 workaround */ + mov 0x8, %g7 + stxa %g0, [%g7] ASI_DMMU + flush %g6 + ldxa [%o3] ASI_DTLB_DATA_ACCESS, %g7 stxa %o0, [%o2] ASI_DMMU stxa %g1, [%o3] ASI_DTLB_DATA_ACCESS diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 58dc224f9..68147d4d4 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.146 2000/02/09 21:11:09 davem Exp $ +/* $Id: init.c,v 1.147 2000/03/03 23:48:44 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) @@ -230,6 +230,14 @@ static void inherit_prom_mappings(void) /* Now fixup OBP's idea about where we really are mapped. */ prom_printf("Remapping the kernel... "); + + /* Spitfire Errata #32 workaround */ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "flush %%g6" + : /* No outputs */ + : "r" (0), + "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); + phys_page = spitfire_get_dtlb_data(63) & _PAGE_PADDR; phys_page += ((unsigned long)&prom_boot_page - (unsigned long)&empty_zero_page); @@ -252,11 +260,27 @@ static void inherit_prom_mappings(void) : "memory"); tte_vaddr = (unsigned long) &empty_zero_page; + + /* Spitfire Errata #32 workaround */ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "flush %%g6" + : /* No outputs */ + : "r" (0), + "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); + kern_locked_tte_data = tte_data = spitfire_get_dtlb_data(63); remap_func = (void *) ((unsigned long) &prom_remap - (unsigned long) &prom_boot_page); + + /* Spitfire Errata #32 workaround */ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "flush %%g6" + : /* No outputs */ + : "r" (0), + "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); + remap_func(spitfire_get_dtlb_data(63) & _PAGE_PADDR, (unsigned long) &empty_zero_page, prom_get_mmu_ihandle()); @@ -319,8 +343,16 @@ static void __flush_nucleus_vptes(void) /* Only DTLB must be checked for VPTE entries. */ for(i = 0; i < 63; i++) { - unsigned long tag = spitfire_get_dtlb_tag(i); + unsigned long tag; + /* Spitfire Errata #32 workaround */ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "flush %%g6" + : /* No outputs */ + : "r" (0), + "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); + + tag = spitfire_get_dtlb_tag(i); if(((tag & ~(PAGE_MASK)) == 0) && ((tag & (PAGE_MASK)) >= prom_reserved_base)) { __asm__ __volatile__("stxa %%g0, [%0] %1" @@ -436,10 +468,26 @@ void inherit_locked_prom_mappings(int save_p) for(i = 0; i < 63; i++) { unsigned long data; + + /* Spitfire Errata #32 workaround */ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "flush %%g6" + : /* No outputs */ + : "r" (0), + "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); + data = spitfire_get_dtlb_data(i); if((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) { - unsigned long tag = spitfire_get_dtlb_tag(i); + unsigned long tag; + + /* Spitfire Errata #32 workaround */ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "flush %%g6" + : /* No outputs */ + : "r" (0), + "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); + tag = spitfire_get_dtlb_tag(i); if(save_p) { prom_dtlb[dtlb_seen].tlb_ent = i; prom_dtlb[dtlb_seen].tlb_tag = tag; @@ -459,10 +507,25 @@ void inherit_locked_prom_mappings(int save_p) for(i = 0; i < 63; i++) { unsigned long data; + /* Spitfire Errata #32 workaround */ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "flush %%g6" + : /* No outputs */ + : "r" (0), + "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); + data = spitfire_get_itlb_data(i); if((data & (_PAGE_L|_PAGE_VALID)) == (_PAGE_L|_PAGE_VALID)) { - unsigned long tag = spitfire_get_itlb_tag(i); + unsigned long tag; + + /* Spitfire Errata #32 workaround */ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "flush %%g6" + : /* No outputs */ + : "r" (0), + "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); + tag = spitfire_get_itlb_tag(i); if(save_p) { prom_itlb[itlb_seen].tlb_ent = i; prom_itlb[itlb_seen].tlb_tag = tag; @@ -544,6 +607,13 @@ void __flush_tlb_all(void) : "=r" (pstate) : "i" (PSTATE_IE)); for(i = 0; i < 64; i++) { + /* Spitfire Errata #32 workaround */ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "flush %%g6" + : /* No outputs */ + : "r" (0), + "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); + if(!(spitfire_get_dtlb_data(i) & _PAGE_L)) { __asm__ __volatile__("stxa %%g0, [%0] %1" : /* no outputs */ @@ -552,6 +622,14 @@ void __flush_tlb_all(void) spitfire_put_dtlb_data(i, 0x0UL); membar("#Sync"); } + + /* Spitfire Errata #32 workaround */ + __asm__ __volatile__("stxa %0, [%1] %2\n\t" + "flush %%g6" + : /* No outputs */ + : "r" (0), + "r" (PRIMARY_CONTEXT), "i" (ASI_DMMU)); + if(!(spitfire_get_itlb_data(i) & _PAGE_L)) { __asm__ __volatile__("stxa %%g0, [%0] %1" : /* no outputs */ diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S index 0825b0585..210db79e6 100644 --- a/arch/sparc64/mm/ultra.S +++ b/arch/sparc64/mm/ultra.S @@ -1,4 +1,4 @@ -/* $Id: ultra.S,v 1.37 2000/02/14 02:52:04 davem Exp $ +/* $Id: ultra.S,v 1.38 2000/03/03 23:48:44 davem Exp $ * ultra.S: Don't expand these all over the place... * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -35,7 +35,7 @@ __flush_tlb_mm: /* %o0=(ctx & 0x3ff), %o1=SECONDARY_CONTEXT */ __flush_tlb_range: /* %o0=(ctx&0x3ff), %o1=start&PAGE_MASK, %o2=SECONDARY_CONTEXT, * %o3=end&PAGE_MASK, %o4=PAGE_SIZE, %o5=(end - start) */ -#define TLB_MAGIC 206 /* Students, do you know how I calculated this? -DaveM */ +#define TLB_MAGIC 207 /* Students, do you know how I calculated this? -DaveM */ /*IC3*/ cmp %o5, %o4 be,pt %xcc, __flush_tlb_page srlx %o5, 13, %g5 @@ -58,6 +58,12 @@ __flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */ wrpr %g1, PSTATE_IE, %pstate mov TLB_TAG_ACCESS, %g3 mov (62 << 3), %g2 + + /* Spitfire Errata #32 workaround. */ + mov 0x8, %o4 + stxa %g0, [%o4] ASI_DMMU + flush %g6 + 1: ldxa [%g2] ASI_ITLB_TAG_READ, %o4 and %o4, 0x3ff, %o5 cmp %o5, %o0 @@ -83,12 +89,27 @@ __flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */ wrpr %g1, 0x0, %pstate 4: stxa %g0, [%g3] ASI_IMMU stxa %g0, [%g2] ASI_ITLB_DATA_ACCESS + flush %g6 + + /* Spitfire Errata #32 workaround. */ + mov 0x8, %o4 + stxa %g0, [%o4] ASI_DMMU + flush %g6 + ba,pt %xcc, 2b - flush %g6 + nop + 5: stxa %g0, [%g3] ASI_DMMU /*IC9*/ stxa %g0, [%g2] ASI_DTLB_DATA_ACCESS + flush %g6 + + /* Spitfire Errata #32 workaround. */ + mov 0x8, %o4 + stxa %g0, [%o4] ASI_DMMU + flush %g6 + ba,pt %xcc, 3b - flush %g6 + nop .align 32 __flush_tlb_mm_slow: @@ -293,28 +314,51 @@ xcall_receive_signal: clr %l6 99: retry + .data + +errata32_hwbug: + .xword 0 + + .text + /* These two are not performance critical... */ .globl xcall_flush_tlb_all xcall_flush_tlb_all: + + /* Spitfire Errata #32 workaround. */ + sethi %hi(errata32_hwbug), %g4 + stx %g0, [%g4 + %lo(errata32_hwbug)] + clr %g2 clr %g3 1: ldxa [%g3] ASI_DTLB_DATA_ACCESS, %g4 and %g4, _PAGE_L, %g5 brnz,pn %g5, 2f mov TLB_TAG_ACCESS, %g7 + stxa %g0, [%g7] ASI_DMMU membar #Sync - stxa %g0, [%g3] ASI_DTLB_DATA_ACCESS membar #Sync + + /* Spitfire Errata #32 workaround. */ + sethi %hi(errata32_hwbug), %g4 + stx %g0, [%g4 + %lo(errata32_hwbug)] + 2: ldxa [%g3] ASI_ITLB_DATA_ACCESS, %g4 and %g4, _PAGE_L, %g5 brnz,pn %g5, 2f mov TLB_TAG_ACCESS, %g7 + stxa %g0, [%g7] ASI_IMMU membar #Sync - stxa %g0, [%g3] ASI_ITLB_DATA_ACCESS + membar #Sync + + /* Spitfire Errata #32 workaround. */ + sethi %hi(errata32_hwbug), %g4 + stx %g0, [%g4 + %lo(errata32_hwbug)] + 2: add %g2, 1, %g2 cmp %g2, 63 ble,pt %icc, 1b |