diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-16 01:07:24 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-16 01:07:24 +0000 |
commit | 95db6b748fc86297827fbd9c9ef174d491c9ad89 (patch) | |
tree | 27a92a942821cde1edda9a1b088718d436b3efe4 /arch | |
parent | 45b27b0a0652331d104c953a5b192d843fff88f8 (diff) |
Merge with Linux 2.3.40.
Diffstat (limited to 'arch')
179 files changed, 6661 insertions, 5168 deletions
diff --git a/arch/alpha/config.in b/arch/alpha/config.in index 35e9edeb0..ce5c0853e 100644 --- a/arch/alpha/config.in +++ b/arch/alpha/config.in @@ -2,6 +2,9 @@ # For a description of the syntax of this configuration file, # see the Configure script. # + +define_bool CONFIG_UID16 n + mainmenu_name "Kernel configuration of Linux for Alpha machines" mainmenu_option next_comment @@ -180,6 +183,12 @@ 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 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT @@ -250,6 +259,10 @@ endmenu source drivers/char/Config.in +source drivers/usb/Config.in + +source drivers/misc/Config.in + source fs/Config.in if [ "$CONFIG_VT" = "y" ]; then diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig index ba6f0070b..9365dc4e2 100644 --- a/arch/alpha/defconfig +++ b/arch/alpha/defconfig @@ -28,6 +28,7 @@ CONFIG_ALPHA_GENERIC=y # CONFIG_ALPHA_EB64P is not set # CONFIG_ALPHA_EB66 is not set # CONFIG_ALPHA_EB66P is not set +# CONFIG_ALPHA_EIGER is not set # CONFIG_ALPHA_JENSEN is not set # CONFIG_ALPHA_LX164 is not set # CONFIG_ALPHA_MIATA is not set @@ -44,14 +45,15 @@ CONFIG_ALPHA_GENERIC=y # CONFIG_ALPHA_SABLE is not set # CONFIG_ALPHA_TAKARA is not set CONFIG_PCI=y -CONFIG_PCI_NAMES=y # CONFIG_SMP is not set +CONFIG_PCI_NAMES=y +# CONFIG_HOTPLUG is not set CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set -CONFIG_SYSCTL=y CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set @@ -84,6 +86,7 @@ CONFIG_BLK_DEV_FD=y # CONFIG_BLK_DEV_MD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_DEV_DAC960 is not set CONFIG_PARIDE_PARPORT=y # CONFIG_PARIDE is not set # CONFIG_BLK_DEV_IDE_MODES is not set @@ -92,7 +95,8 @@ CONFIG_PARIDE_PARPORT=y # # Networking options # -# CONFIG_PACKET is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set # CONFIG_NETLINK is not set # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set @@ -135,6 +139,7 @@ CONFIG_BLK_DEV_SR=y # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # +# CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set @@ -148,6 +153,7 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_IPS is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set @@ -164,6 +170,7 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_SIM710 is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_NCR53C8XX is not set # CONFIG_SCSI_SYM53C8XX is not set @@ -201,6 +208,7 @@ CONFIG_NET_ETHERNET=y # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set CONFIG_NET_EISA=y # CONFIG_PCNET32 is not set @@ -211,16 +219,27 @@ CONFIG_DE4X5=y # CONFIG_DGRS is not set # CONFIG_EEXPRESS_PRO100 is not set # CONFIG_NE2K_PCI is not set +# CONFIG_SIS900 is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# # CONFIG_NET_RADIO is not set # -# Token ring devices +# Token Ring driver support # # CONFIG_TR is not set # CONFIG_NET_FC is not set @@ -228,13 +247,7 @@ CONFIG_DE4X5=y # # Wan interfaces # -# CONFIG_HOSTESS_SV11 is not set -# CONFIG_COSA is not set -# CONFIG_SEALEVEL_4021 is not set -# CONFIG_DLCI is not set -# CONFIG_WAN_DRIVERS is not set -# CONFIG_LAPBETHER is not set -# CONFIG_X25_ASY is not set +# CONFIG_WAN is not set # # Amateur Radio support @@ -264,6 +277,11 @@ CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 # +# I2C support +# +# CONFIG_I2C is not set + +# # Mice # # CONFIG_BUSMOUSE is not set @@ -271,7 +289,16 @@ CONFIG_MOUSE=y CONFIG_PSMOUSE=y # CONFIG_82C710_MOUSE is not set # CONFIG_PC110_PAD is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set # CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set @@ -280,17 +307,25 @@ CONFIG_PSMOUSE=y # Video For Linux # # CONFIG_VIDEO_DEV is not set - -# -# Joystick support -# -# CONFIG_JOYSTICK is not set # CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set +# CONFIG_DRM is not set +# CONFIG_DRM_TDFX is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Misc devices +# # # Filesystems @@ -298,11 +333,11 @@ CONFIG_PSMOUSE=y # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set +# CONFIG_CRAMFS is not set CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set @@ -313,6 +348,7 @@ CONFIG_DEVPTS_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 # @@ -320,6 +356,7 @@ CONFIG_EXT2_FS=y # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_NFSD is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set @@ -329,16 +366,20 @@ CONFIG_LOCKD=y # Partition Types # # CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y CONFIG_OSF_PARTITION=y -# CONFIG_SMD_DISKLABEL is not set -# CONFIG_SGI_DISKLABEL is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set # CONFIG_NLS is not set # # Console drivers # CONFIG_VGA_CONSOLE=y + +# +# Frame-buffer support +# # CONFIG_FB is not set # diff --git a/arch/alpha/kernel/core_mcpcia.c b/arch/alpha/kernel/core_mcpcia.c index 4b165940d..847958212 100644 --- a/arch/alpha/kernel/core_mcpcia.c +++ b/arch/alpha/kernel/core_mcpcia.c @@ -560,12 +560,14 @@ mcpcia_machine_check(unsigned long vector, unsigned long la_ptr, switch (expected) { case 0: + { /* FIXME: how do we figure out which hose the error was on? */ struct pci_controler *hose; for (hose = hose_head; hose; hose = hose->next) mcpcia_pci_clr_err(hose2mid(hose->index)); break; + } case 1: mcpcia_pci_clr_err(mcheck_extra(cpu)); break; diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 6b37bd23c..af1567fd1 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S @@ -985,9 +985,9 @@ sys_call_table: .quad osf_utsname .quad sys_lchown .quad osf_shmat - .quad sys_shmctlold /* 210 */ + .quad sys_shmctl /* 210 */ .quad sys_shmdt - .quad sys_shmget + .quad osf_shmget .quad alpha_ni_syscall .quad alpha_ni_syscall .quad alpha_ni_syscall /* 215 */ @@ -1150,4 +1150,4 @@ sys_call_table: .quad sys_setresgid .quad sys_getresgid .quad sys_ni_syscall /* sys_dipc */ - .quad sys_shmctl + .quad sys_shmget diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index e81687bdb..95e539d34 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -439,7 +439,7 @@ static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags) dentry = getdev(tmp.devname, 0); retval = PTR_ERR(dentry); - if (IS_ERR(dentry) + if (IS_ERR(dentry)) goto out; retval = do_mount(dentry->d_inode->i_bdev, tmp.devname, dirname, "ext2", flags, NULL); @@ -471,7 +471,6 @@ out: static int osf_procfs_mount(char *dirname, struct procfs_args *args, int flags) { - int retval; struct procfs_args tmp; if (copy_from_user(&tmp, args, sizeof(tmp))) @@ -1401,102 +1400,7 @@ asmlinkage int sys_old_adjtimex(struct timex32 *txc_p) return ret; } -struct shmid_ds_old { - struct ipc_perm shm_perm; /* operation perms */ - int shm_segsz; /* size of segment (bytes) */ - __kernel_time_t shm_atime; /* last attach time */ - __kernel_time_t shm_dtime; /* last detach time */ - __kernel_time_t shm_ctime; /* last change time */ - __kernel_ipc_pid_t shm_cpid; /* pid of creator */ - __kernel_ipc_pid_t shm_lpid; /* pid of last operator */ - unsigned short shm_nattch; /* no. of current attaches */ - unsigned short shm_unused; /* compatibility */ - void *shm_unused2; /* ditto - used by DIPC */ - void *shm_unused3; /* unused */ -}; - -struct shminfo_old { - int shmmax; - int shmmin; - int shmmni; - int shmseg; - int shmall; -}; - -asmlinkage long sys_shmctlold(int shmid, int cmd, struct shmid_ds_old *buf) +asmlinkage long osf_shmget (key_t key, int size, int flag) { - struct shmid_ds arg; - long ret; - mm_segment_t old_fs; - - if (cmd == IPC_SET) { - struct shmid_ds_old tbuf; - - if(copy_from_user (&tbuf, buf, sizeof(*buf))) - return -EFAULT; - arg.shm_perm = tbuf.shm_perm; - arg.shm_segsz = tbuf.shm_segsz; - arg.shm_atime = tbuf.shm_atime; - arg.shm_dtime = tbuf.shm_dtime; - arg.shm_ctime = tbuf.shm_ctime; - arg.shm_cpid = tbuf.shm_cpid; - arg.shm_lpid = tbuf.shm_lpid; - arg.shm_nattch = tbuf.shm_nattch; - arg.shm_unused = tbuf.shm_unused; - arg.shm_unused2 = tbuf.shm_unused2; - arg.shm_unused3 = tbuf.shm_unused3; - } - old_fs = get_fs (); - set_fs (KERNEL_DS); - ret = sys_shmctl(shmid, cmd, &arg); - set_fs (old_fs); - if (ret < 0) - return(ret); - switch(cmd) { - case IPC_INFO: - { - struct shminfo *tbuf = (struct shminfo *) &arg; - struct shminfo_old shminfo_oldst; - - shminfo_oldst.shmmax = (tbuf->shmmax > INT_MAX ? - INT_MAX : tbuf->shmmax); - shminfo_oldst.shmmin = tbuf->shmmin; - shminfo_oldst.shmmni = tbuf->shmmni; - shminfo_oldst.shmseg = tbuf->shmseg; - shminfo_oldst.shmall = tbuf->shmall; - if (copy_to_user(buf, &shminfo_oldst, - sizeof(struct shminfo_old))) - return -EFAULT; - return(ret); - } - case SHM_INFO: - { - struct shm_info *tbuf = (struct shm_info *) &arg; - - if (copy_to_user (buf, tbuf, sizeof(struct shm_info))) - return -EFAULT; - return(ret); - } - case SHM_STAT: - case IPC_STAT: - { - struct shmid_ds_old tbuf; - - tbuf.shm_perm = arg.shm_perm; - tbuf.shm_segsz = arg.shm_segsz; - tbuf.shm_atime = arg.shm_atime; - tbuf.shm_dtime = arg.shm_dtime; - tbuf.shm_ctime = arg.shm_ctime; - tbuf.shm_cpid = arg.shm_cpid; - tbuf.shm_lpid = arg.shm_lpid; - tbuf.shm_nattch = arg.shm_nattch; - tbuf.shm_unused = arg.shm_unused; - tbuf.shm_unused2 = arg.shm_unused2; - tbuf.shm_unused3 = arg.shm_unused3; - if (copy_to_user (buf, &tbuf, sizeof(tbuf))) - return -EFAULT; - return(ret); - } - } - return(ret); + return sys_shmget (key, size, flag); } diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 601cb9401..aa0a8d968 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -251,11 +251,13 @@ pcibios_fixup_bus(struct pci_bus *bus) /* Propogate hose info into the subordinate devices. */ struct pci_controler *hose = (struct pci_controler *) bus->sysdata; - struct pci_dev *dev; + struct list_head *ln; bus->resource[0] = hose->io_space; bus->resource[1] = hose->mem_space; - for (dev = bus->devices; dev; dev = dev->sibling) { + + for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { + struct pci_dev *dev = pci_dev_b(ln); if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) pcibios_fixup_device_resources(dev, bus); } @@ -322,6 +324,13 @@ pcibios_fixup_pbus_ranges(struct pci_bus * bus, ranges->mem_end -= bus->resource[1]->start; } +int __init +pcibios_enable_device(struct pci_dev *dev) +{ + /* Not needed, since we enable all devices at startup. */ + return 0; +} + void __init common_init_pci(void) { @@ -339,8 +348,7 @@ common_init_pci(void) next_busno += 1; } - pci_assign_unassigned_resources(alpha_mv.min_io_address, - alpha_mv.min_mem_address); + pci_assign_unassigned_resources(); pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq); pci_set_bus_ranges(); } diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c index daaa36e09..97bb6df9d 100644 --- a/arch/alpha/mm/init.c +++ b/arch/alpha/mm/init.c @@ -274,7 +274,8 @@ srm_paging_stop (void) } #endif -static void __init printk_memory_info(void) +static void __init +printk_memory_info(void) { unsigned long codesize, reservedpages, datasize, initsize, tmp; extern int page_is_ram(unsigned long) __init; diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 2c81731b9..0df16ffa4 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -136,7 +136,7 @@ MACHINE = nexuspci ARCHDIR = nexuspci endif -ifeq ($(CONFIG_ARCH_SA1100),u) +ifeq ($(CONFIG_ARCH_SA1100),y) MACHINE = sa1100 ARCHDIR = sa1100 endif @@ -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.a $(LIBS) $(GCCLIB) +LIBS := arch/arm/lib/lib.o arch/arm/lib/lib.a $(LIBS) $(GCCLIB) 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 8a100eb77..d2992a491 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -44,9 +44,9 @@ ZTEXTADDR = 0x40200000 ZRELADDR = 0x40008000 endif -ifeq ($(CONFIG_ARCH_SA110),y) +ifeq ($(CONFIG_ARCH_SA1100),y) +OBJS += head-sa1100.o ifeq ($(CONFIG_SA1100_VICTOR),y) -HEAD = head-victor.o ZTEXTADDR = 0x00002000 ZBSSADDR = 0xc0100000 else @@ -91,7 +91,7 @@ font.o: $(FONTC) vmlinux.lds: vmlinux.lds.in @sed "$(SEDFLAGS)" < vmlinux.lds.in > $@ -clean:; rm -f vmlinux core piggy* +clean:; rm -f vmlinux core piggy* vmlinux.lds .PHONY: vmlinux.lds clean diff --git a/arch/arm/boot/compressed/head-sa1100.S b/arch/arm/boot/compressed/head-sa1100.S new file mode 100644 index 000000000..90018e52b --- /dev/null +++ b/arch/arm/boot/compressed/head-sa1100.S @@ -0,0 +1,65 @@ +/* + * linux/arch/arm/boot/compressed/head-sa1100.S + * + * Copyright (C) 1999 Nicolas Pitre <nico@cam.org> + * + * SA1100 specific tweaks. This is merged with head.S by the linker. + */ + +#include <linux/config.h> + + + .section ".start", #alloc, #execinstr + +#ifndef CONFIG_ARCH_SA1100 +#error What am I doing here... +#endif + +#ifdef CONFIG_SA1100_BRUTUS +@ need to enter SVC mode +#define angel_SWIreason_EnterSVC 0x17 /* from arm.h, in angel source */ +#define angel_SWI_ARM (0xEF123456 & 0xffffff) + mov r0, #angel_SWIreason_EnterSVC + swi #angel_SWI_ARM + + @ turn off interrupts to prevent the angel from running + mrs r0, cpsr + orr r0, r0, #0xc0 + msr cpsr, r0 +#endif + +#ifdef CONFIG_SA1100_VICTOR + @ Copy cmdline to 0xc0000000 + mov r1, #0xc0000000 + cmp r0, #0 + moveq r2, #0 +1: ldrneb r2, [r0], #1 + cmpne r2, #0 + strb r2, [r1], #1 + bne 1b +#endif + + @ Data cache might be active. + @ Be sure to flush kernel binary out of the cache, + @ whatever state it is, before it is turned off. + @ This is done by fetching through currently executed + @ memory to be sure we hit the same cache. + bic r2, pc, #0x1f + add r3, r2, #0x4000 @ 16 kb is quite enough... +1: ldr r0, [r2], #32 + teq r2, r3 + bne 1b + mcr p15, 0, r0, c7, c10, 4 @ drain WB + mcr p15, 0, r0, c7, c7, 0 @ flush I & D caches + + @ disabling MMU, enabling I cache + mrc p15, 0, r0, c1, c0, 0 @ read control reg + bic r0, r0, #0x0d @ clear WB, DC, MMU + orr r0, r0, #0x1000 @ set Icache + mcr p15, 0, r0, c1, c0, 0 + + @ set registers for entry + mov r0, #0 + mov r1, #16 + + diff --git a/arch/arm/boot/compressed/head-victor.S b/arch/arm/boot/compressed/head-victor.S deleted file mode 100644 index e556383ba..000000000 --- a/arch/arm/boot/compressed/head-victor.S +++ /dev/null @@ -1,45 +0,0 @@ -/* - * linux/arch/arm/boot/compressed/head-victor.S - * - * Copyright (C) 1998 Nicolas Pitre <nico@visuaide.com> - */ - -#include <linux/linkage.h> - - .text - .globl _start -_start: - @ just in case we still use an a.out loader... - nop - nop - nop - nop - nop - nop - nop - nop - - @ load different addresses - adr r2, LC0 - ldmia r2, {r4, r5, r6, sp} - - @ clear BSS - mov r2, #0 -1: str r2, [r5], #4 - cmp r5, r6 - blt 1b - - @ uncompress the kernel - mov r8, r0 @ save cmdline ptr - mov r0, r4 @ where to put uncompressed data - add r1, r6, #31 - bic r1, r1, #31 @ free memory space - add r2, r1, #65536 @ end of free mem space - bl SYMBOL_NAME(decompress_kernel) - mov r0, r8 @ retrieve cmdline ptr - mov pc, r4 @ call via EXEC entry - -LC0: .word _load_addr - .word __bss_start - .word SYMBOL_NAME(_end) - .word SYMBOL_NAME(user_stack)+4096 diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index e87c0a72e..796f812ab 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -77,10 +77,10 @@ start: cmp r2, r3 blt 1b - eor r1, r6, #0x44 << 24 @ SA-110? + eor r1, r6, #0x44 << 24 @ SA-110 or SA-1100? eor r1, r1, #0x01 << 16 eor r1, r1, #0xa1 << 8 - movs r1, r1, lsr #4 + movs r1, r1, lsr #5 mcreq p15, 0, r1, c7, c7, 0 @ flush I & D-cache mcreq p15, 0, r1, c7, c10, 4 @ drain WB add pc, r5, r0 @ call relocation code @@ -144,10 +144,10 @@ reloc_start: add r8, r5, r0 mov r0, r4 bl memdump #endif - eor r0, r6, #0x44 << 24 @ SA-110? + eor r0, r6, #0x44 << 24 @ SA-110 or SA-1100? eor r0, r0, #0x01 << 16 eor r0, r0, #0xa1 << 8 - movs r0, r0, lsr #4 + movs r0, r0, lsr #5 mcreq p15, 0, r0, c7, c7, 0 @ flush I cache mcreq p15, 0, r1, c7, c10, 4 @ drain WB diff --git a/arch/arm/config.in b/arch/arm/config.in index e1d54c4e7..be7102698 100644 --- a/arch/arm/config.in +++ b/arch/arm/config.in @@ -6,6 +6,8 @@ mainmenu_name "Linux Kernel Configuration" define_bool CONFIG_ARM 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 @@ -44,7 +46,6 @@ if [ "$CONFIG_ADDIN_FOOTBRIDGE" = "y" ]; then fi if [ "$CONFIG_ARCH_SA1100" = "y" ]; then - define_bool CONFIG_CPU_SA1100 y choice 'SA1100 implementation' \ "Brutus CONFIG_SA1100_BRUTUS \ Empeg CONFIG_SA1100_EMPEG \ @@ -93,7 +94,11 @@ else "$CONFIG_FOOTBRIDGE" = "y" -o \ "$CONFIG_ARCH_NEXUSPCI" = "y" ]; then define_bool CONFIG_CPU_32v4 y - define_bool CONFIG_CPU_SA110 y + if [ "$CONFIG_ARCH_SA1100" = "y" ]; then + define_bool CONFIG_CPU_SA1100 y + else + define_bool CONFIG_CPU_SA110 y + fi else if [ "$CONFIG_ARCH_RPC" = "y" ]; then define_bool CONFIG_CPU_32v3 y @@ -110,7 +115,7 @@ fi if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o \ "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then define_bool CONFIG_PCI y - source drivers/pci/Config.h + source drivers/pci/Config.in fi # @@ -123,8 +128,8 @@ else define_bool CONFIG_ISA_DMA n fi -if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool 'Enable kernel-mode alignment trap handler (EXPERIMENTAL)' CONFIG_ALIGNMENT_TRAP +if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then + bool 'Kernel-mode alignment trap handler' CONFIG_ALIGNMENT_TRAP fi #bool 'Split text into discardable sections' CONFIG_TEXT_SECTIONS endmenu @@ -273,11 +278,10 @@ bool 'Verbose user fault messages' CONFIG_DEBUG_USER bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ +if [ "$CONFIG_CPU_26" = "y" ]; then + bool 'Disable pgtable cache' CONFIG_NO_PGT_CACHE +fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - if [ "$CONFIG_CPU_26" = "y" ]; then - bool 'Disable pgtable cache (EXPERIMENTAL)' CONFIG_NO_PGT_CACHE - fi - # These options are only for real kernel hackers # who want to get their hands dirty. bool 'Kernel low-level debugging functions' CONFIG_DEBUG_LL diff --git a/arch/arm/def-configs/a5k b/arch/arm/def-configs/a5k index 8b402a59e..b5fd4b315 100644 --- a/arch/arm/def-configs/a5k +++ b/arch/arm/def-configs/a5k @@ -4,6 +4,11 @@ CONFIG_ARM=y # +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# # System and processor type # # CONFIG_ARCH_ARC is not set @@ -12,22 +17,10 @@ CONFIG_ARCH_A5K=y # CONFIG_ARCH_EBSA110 is not set # CONFIG_FOOTBRIDGE is not set CONFIG_ARCH_ACORN=y -# CONFIG_ISA_DMA is not set # CONFIG_CPU_32 is not set CONFIG_CPU_26=y -# CONFIG_CPU_ARM2 is not set -CONFIG_CPU_ARM3=y -# CONFIG_CPU_ARM6 is not set -# CONFIG_CPU_ARM7 is not set -# CONFIG_CPU_SA110 is not set -CONFIG_PAGESIZE_32=y # CONFIG_PAGESIZE_16 is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y -# CONFIG_TEXT_SECTIONS is not set +# CONFIG_ISA_DMA is not set # # Loadable module support @@ -43,17 +36,38 @@ CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y -# CONFIG_NWFPE is not set +CONFIG_NWFPE=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set CONFIG_BINFMT_AOUT=y -CONFIG_BINFMT_ELF=m +# CONFIG_BINFMT_ELF is not set # CONFIG_BINFMT_MISC is not set -CONFIG_PARPORT=y -CONFIG_PARPORT_PC=y +CONFIG_PARPORT=m +CONFIG_PARPORT_PC=m +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_ARC is not set +# CONFIG_PARPORT_AMIGA is not set +# CONFIG_PARPORT_MFC3 is not set +# CONFIG_PARPORT_ATARI is not set +# CONFIG_PARPORT_SUNBPP is not set +# CONFIG_PARPORT_OTHER is not set +# CONFIG_PARPORT_1284 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set # -# Plug and Play support +# Plug and Play configuration # # CONFIG_PNP is not set +# CONFIG_ISAPNP is not set # # Block devices @@ -66,11 +80,19 @@ CONFIG_BLK_DEV_IDE=y # # 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 + +# +# IDE chipset support/bugfixes +# # CONFIG_BLK_DEV_CMD640 is not set +CONFIG_BLK_DEV_IDE_ICSIDE=y +# CONFIG_BLK_DEV_IDEDMA_ICS is not set +# CONFIG_BLK_DEV_IDE_RAPIDE is not set # CONFIG_IDE_CHIPSETS is not set # @@ -82,16 +104,14 @@ CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_INITRD=y # CONFIG_BLK_DEV_XD is not set -CONFIG_PARIDE_PARPORT=y +CONFIG_PARIDE_PARPORT=m # CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set # CONFIG_BLK_DEV_HD is not set # # Acorn-specific block devices # -CONFIG_BLK_DEV_IDE_CARDS=y -CONFIG_BLK_DEV_IDE_ICSIDE=y -# CONFIG_BLK_DEV_IDE_RAPIDE is not set # CONFIG_BLK_DEV_FD1772 is not set CONFIG_BLK_DEV_MFM=m CONFIG_BLK_DEV_MFM_AUTODETECT=y @@ -102,26 +122,33 @@ CONFIG_BLK_DEV_MFM_AUTODETECT=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set +CONFIG_SERIAL_CONSOLE=y +# CONFIG_ATOMWIDE_SERIAL is not set +# CONFIG_DUALSP_SERIAL is not set # CONFIG_SERIAL_EXTENDED is not set -CONFIG_ATOMWIDE_SERIAL=y -CONFIG_DUALSP_SERIAL=y # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_UNIX98_PTYS is not set -CONFIG_PRINTER=y -CONFIG_PRINTER_READBACK=y -CONFIG_MOUSE=y +# CONFIG_PRINTER is not set +# CONFIG_PPDEV is not set # # Mice # -# CONFIG_ATIXL_BUSMOUSE is not set # CONFIG_BUSMOUSE is not set -# CONFIG_MS_BUSMOUSE is not set +CONFIG_MOUSE=y # CONFIG_PSMOUSE is not set # CONFIG_82C710_MOUSE is not set # CONFIG_PC110_PAD is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set # CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set @@ -130,27 +157,38 @@ CONFIG_MOUSE=y # Video For Linux # # CONFIG_VIDEO_DEV is not set - -# -# Joystick support -# -# CONFIG_JOYSTICK is not set # CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set -CONFIG_KBDMOUSE=y +# CONFIG_DRM is not set +# CONFIG_DRM_TDFX is not set +# CONFIG_AGP is not set + +# +# Support for USB +# +# CONFIG_USB is not set # # Console drivers # CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y CONFIG_FB_ACORN=y # CONFIG_FB_MATROX is not set # CONFIG_FB_ATY is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_3DFX is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set CONFIG_FBCON_MFB=y @@ -158,9 +196,13 @@ CONFIG_FBCON_CFB2=y CONFIG_FBCON_CFB4=y CONFIG_FBCON_CFB8=y # CONFIG_FBCON_FONTWIDTH8_ONLY is not set -# CONFIG_FBCON_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_PEARL_8x8 is not set CONFIG_FONT_ACORN_8x8=y # @@ -168,7 +210,7 @@ CONFIG_FONT_ACORN_8x8=y # # CONFIG_PACKET is not set # CONFIG_NETLINK is not set -# CONFIG_FIREWALL is not set +# CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y @@ -184,15 +226,17 @@ CONFIG_INET=y # # (it is safe to leave these untouched) # -# CONFIG_INET_RARP is not set # CONFIG_SKB_LARGE is not set # CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set # # # # CONFIG_IPX is not set # CONFIG_ATALK is not set +# CONFIG_DECNET is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_BRIDGE is not set @@ -201,7 +245,6 @@ CONFIG_INET=y # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set # CONFIG_NET_HW_FLOWCONTROL is not set -# CONFIG_CPU_IS_SLOW is not set # # QoS and/or fair queueing @@ -214,7 +257,7 @@ CONFIG_INET=y # CONFIG_HAMRADIO is not set # -# IrDA subsystem support +# IrDA (infrared) support # # CONFIG_IRDA is not set @@ -222,9 +265,18 @@ CONFIG_INET=y # Network device support # CONFIG_NETDEVICES=y + +# +# ARCnet devices +# # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_EQUALIZER is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# CONFIG_NET_ETHERNET=y CONFIG_ARM_ETHER1=y CONFIG_ARM_ETHER3=y @@ -234,96 +286,47 @@ CONFIG_ARM_ETHER3=y # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_RTL8139 is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_ACENIC is not set +# CONFIG_DM9102 is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set # CONFIG_NET_EISA is not set # CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set -# CONFIG_DLCI is not set # CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# # CONFIG_NET_RADIO is not set + +# +# Token Ring driver support +# # CONFIG_TR is not set -# CONFIG_SHAPER is not set -# CONFIG_HOSTESS_SV11 is not set -# CONFIG_COSA is not set +# CONFIG_NET_FC is not set # CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set # # SCSI support # -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -CONFIG_BLK_DEV_SR=y -# CONFIG_BLK_DEV_SR_VENDOR is not set -# CONFIG_CHR_DEV_SG is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y - -# -# SCSI low-level drivers -# -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -CONFIG_SCSI_PPA=m -# CONFIG_SCSI_IMM is not set -# CONFIG_SCSI_IZIP_EPP16 is not set -# CONFIG_SCSI_IZIP_SLOW_CTR is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SEAGATE is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set -# CONFIG_SCSI_DEBUG is not set -CONFIG_SCSI_ACORNSCSI_3=y -CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE=y -CONFIG_SCSI_ACORNSCSI_SYNC=y -CONFIG_SCSI_ARXESCSI=m -# CONFIG_SCSI_CUMANA_2 is not set -CONFIG_SCSI_EESOXSCSI=y -# CONFIG_SCSI_POWERTECSCSI is not set - -# -# The following drivers are not fully supported -# -# CONFIG_SCSI_CUMANA_1 is not set -# CONFIG_SCSI_ECOSCSI is not set -# CONFIG_SCSI_OAK1 is not set +# CONFIG_SCSI is not set # # Sound @@ -338,12 +341,14 @@ CONFIG_SCSI_EESOXSCSI=y CONFIG_ADFS_FS=y # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set CONFIG_FAT_FS=m CONFIG_MSDOS_FS=m # CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=m -CONFIG_ISO9660_FS=y -CONFIG_JOLIET=y +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set @@ -352,6 +357,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 # @@ -359,8 +365,7 @@ CONFIG_EXT2_FS=y # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y -CONFIG_NFSD=y -# CONFIG_NFSD_SUN is not set +# CONFIG_NFSD is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set @@ -369,12 +374,10 @@ CONFIG_LOCKD=y # # Partition Types # -# CONFIG_OSF_PARTITION is not set -# CONFIG_MAC_PARTITION is not set +# CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y # CONFIG_SGI_PARTITION is not set # CONFIG_SUN_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set CONFIG_ACORN_PARTITION=y CONFIG_ACORN_PARTITION_ADFS=y CONFIG_ACORN_PARTITION_ICS=y @@ -410,6 +413,7 @@ CONFIG_NLS=y # CONFIG_NLS_ISO8859_7 is not set # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_14 is not set # CONFIG_NLS_ISO8859_15 is not set # CONFIG_NLS_KOI8_R is not set @@ -418,8 +422,8 @@ CONFIG_NLS=y # CONFIG_FRAME_POINTER=y CONFIG_DEBUG_ERRORS=y -# CONFIG_DEBUG_USER is not set +CONFIG_DEBUG_USER=y # CONFIG_DEBUG_INFO is not set CONFIG_MAGIC_SYSRQ=y CONFIG_NO_PGT_CACHE=y -# CONFIG_DEBUG_LL is not set +CONFIG_DEBUG_LL=y diff --git a/arch/arm/def-configs/footbridge b/arch/arm/def-configs/footbridge index fa410d522..d68d0b358 100644 --- a/arch/arm/def-configs/footbridge +++ b/arch/arm/def-configs/footbridge @@ -4,6 +4,11 @@ CONFIG_ARM=y # +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# # System and processor type # # CONFIG_ARCH_ARC is not set @@ -23,11 +28,6 @@ CONFIG_CPU_32v4=y CONFIG_CPU_SA110=y CONFIG_PCI=y CONFIG_ISA_DMA=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y # CONFIG_ALIGNMENT_TRAP is not set # @@ -45,6 +45,8 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_NWFPE=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set @@ -52,7 +54,6 @@ CONFIG_BINFMT_ELF=y CONFIG_PARPORT=y CONFIG_PARPORT_PC=y CONFIG_PARPORT_PC_FIFO=y -# CONFIG_PARPORT_PC_PCMCIA is not set # CONFIG_PARPORT_ARC is not set # CONFIG_PARPORT_AMIGA is not set # CONFIG_PARPORT_MFC3 is not set @@ -60,7 +61,7 @@ CONFIG_PARPORT_PC_FIFO=y # CONFIG_PARPORT_SUNBPP is not set # CONFIG_PARPORT_OTHER is not set CONFIG_PARPORT_1284=y -CONFIG_CMDLINE="root=/dev/hda2 ro mem=32M parport=0x378,7 ide0=autotune" +CONFIG_CMDLINE="root=/dev/hda1 ro mem=32M parport=0x378,7 ide0=autotune" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y # CONFIG_LEDS_CPU is not set @@ -97,15 +98,20 @@ CONFIG_IDEDISK_MULTI_MODE=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set + +# +# IDE chipset support/bugfixes +# # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_RZ1000 is not set CONFIG_BLK_DEV_IDEPCI=y CONFIG_BLK_DEV_IDEDMA_PCI=y CONFIG_IDEDMA_PCI_AUTO=y -# IDEDMA_NEW_DRIVE_LISTINGS is not set -IDEDMA_PCI_EXPERIMENTAL=y +CONFIG_IDEDMA_NEW_DRIVE_LISTINGS=y +CONFIG_IDEDMA_PCI_EXPERIMENTAL=y CONFIG_BLK_DEV_OFFBOARD=y # CONFIG_BLK_DEV_AEC6210 is not set +# CONFIG_BLK_DEV_ALI15X3 is not set # CONFIG_BLK_DEV_CMD646 is not set CONFIG_BLK_DEV_CY82C693=y # CONFIG_BLK_DEV_HPT34X is not set @@ -113,8 +119,8 @@ CONFIG_BLK_DEV_CY82C693=y # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_PDC202XX=y -# PDC202XX_FORCE_BURST_BIT is not set -# PDC202XX_FORCE_MASTER_MODE is not set +# CONFIG_PDC202XX_FORCE_BURST_BIT is not set +# CONFIG_PDC202XX_FORCE_MASTER_MODE is not set # CONFIG_BLK_DEV_TRM290 is not set CONFIG_BLK_DEV_SL82C105=y CONFIG_BLK_DEV_IDEDMA=y @@ -135,6 +141,7 @@ CONFIG_MD_RAID5=m CONFIG_BLK_DEV_RAM=y # CONFIG_BLK_DEV_INITRD is not set # CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_DEV_DAC960 is not set CONFIG_PARIDE_PARPORT=y CONFIG_PARIDE=m @@ -176,7 +183,8 @@ CONFIG_SERIAL=y CONFIG_SERIAL_CONSOLE=y # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_UNIX98_PTYS is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 CONFIG_PRINTER=m # CONFIG_LP_CONSOLE is not set # CONFIG_PPDEV is not set @@ -189,12 +197,17 @@ CONFIG_MOUSE=y CONFIG_PSMOUSE=y # CONFIG_82C710_MOUSE is not set # CONFIG_PC110_PAD is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set # CONFIG_QIC02_TAPE is not set -CONFIG_WATCHDOG=y # # Watchdog Cards # +CONFIG_WATCHDOG=y # CONFIG_WATCHDOG_NOWAYOUT is not set # CONFIG_WDT is not set CONFIG_SOFT_WATCHDOG=y @@ -212,12 +225,33 @@ CONFIG_RTC=y # # Video For Linux # -# CONFIG_VIDEO_DEV is not set - -# -# Joystick support -# -# CONFIG_JOYSTICK is not set +CONFIG_VIDEO_DEV=y +# CONFIG_I2C_PARPORT is not set + +# +# Radio/Video Adapters +# +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_VIDEO_BT848 is not set +# CONFIG_RADIO_GEMTEK is not set +# CONFIG_VIDEO_PMS is not set +# CONFIG_RADIO_MIROPCM20 is not set +# CONFIG_VIDEO_BWQCAM is not set +# CONFIG_VIDEO_CQCAM is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_VIDEO_STRADIS is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set +# CONFIG_VIDEO_ZORAN is not set +# CONFIG_VIDEO_BUZ is not set +# CONFIG_VIDEO_ZR36120 is not set +CONFIG_VIDEO_CYBERPRO=m # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -226,41 +260,64 @@ CONFIG_RTC=y # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set +# CONFIG_DRM is not set +# CONFIG_DRM_TDFX is not set # -# USB drivers - not for the faint of heart +# Support for USB # CONFIG_USB=m + +# +# USB Controllers +# # CONFIG_USB_UHCI is not set CONFIG_USB_OHCI=m CONFIG_USB_OHCI_DEBUG=y CONFIG_USB_OHCI_HCD=m CONFIG_USB_OHCI_VROOTHUB=y + +# +# Miscellaneous USB options +# # CONFIG_USB_DEBUG_ISOC is not set -CONFIG_USB_HUB=m +CONFIG_USB_PROC=y +# CONFIG_USB_EZUSB is not set + +# +# USB Devices +# CONFIG_USB_MOUSE=m +# CONFIG_USB_HP_SCANNER is not set CONFIG_USB_KBD=m CONFIG_USB_AUDIO=m CONFIG_USB_ACM=m CONFIG_USB_PRINTER=m +# CONFIG_USB_SERIAL is not set # CONFIG_USB_CPIA is not set -CONFIG_USB_SCSI=m -CONFIG_USB_SCSI_DEBUG=m -# CONFIG_USB_EZUSB is not set +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_SCSI is not set # CONFIG_USB_USS720 is not set -CONFIG_USB_PROC=y # # Console drivers # CONFIG_VGA_CONSOLE=y CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_RIVA is not set # CONFIG_FB_CLGEN is not set # CONFIG_FB_PM2 is not set CONFIG_FB_CYBER2000=y # CONFIG_FB_MATROX is not set # CONFIG_FB_ATY is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_3DFX is not set # CONFIG_FB_VIRTUAL is not set CONFIG_FBCON_ADVANCED=y # CONFIG_FBCON_MFB is not set @@ -377,12 +434,13 @@ CONFIG_VORTEX=y # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_RTL8139 is not set -# CONFIG_SIS900 is not set -# CONFIG_YELLOWFIN is not set +# CONFIG_DM9102 is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set CONFIG_NET_EISA=y # CONFIG_PCNET32 is not set -# CONFIG_ACENIC is not set +# CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_AC3200 is not set # CONFIG_APRICOT is not set # CONFIG_CS89x0 is not set @@ -393,27 +451,40 @@ CONFIG_DEC_ELCP=m # CONFIG_LNE390 is not set # CONFIG_NE3210 is not set CONFIG_NE2K_PCI=y +# CONFIG_SIS900 is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_ES3210 is not set # CONFIG_EPIC100 is not set # CONFIG_ZNET is not set # CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_PLIP is not set CONFIG_PPP=m CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set CONFIG_PPP_DEFLATE=m CONFIG_PPP_BSDCOMP=m CONFIG_SLIP=m CONFIG_SLIP_COMPRESSED=y CONFIG_SLIP_SMART=y CONFIG_SLIP_MODE_SLIP6=y + +# +# Wireless LAN (non-hamradio) +# # CONFIG_NET_RADIO is not set # -# Token ring devices +# Token Ring driver support # # CONFIG_TR is not set # CONFIG_NET_FC is not set @@ -423,10 +494,7 @@ CONFIG_SLIP_MODE_SLIP6=y # # Wan interfaces # -# CONFIG_HOSTESS_SV11 is not set -# CONFIG_COSA is not set -# CONFIG_SEALEVEL_4021 is not set -# CONFIG_DLCI is not set +# CONFIG_WAN is not set # # SCSI support @@ -441,30 +509,33 @@ CONFIG_SOUND=m # CONFIG_SOUND_ES1370 is not set # CONFIG_SOUND_ES1371 is not set # CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set # CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set CONFIG_SOUND_OSS=m -# CONFIG_SOUND_PAS is not set -CONFIG_SOUND_SB=m -CONFIG_SOUND_ADLIB=m -# CONFIG_SOUND_GUS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_AD1816 is not set +# CONFIG_SOUND_SGALAXY is not set +# CONFIG_SOUND_CS4232 is not set # CONFIG_SOUND_SSCAPE is not set +# CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_VMIDI is not set # CONFIG_SOUND_TRIX is not set +# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_MPU401 is not set +# CONFIG_SOUND_NM256 is not set # CONFIG_SOUND_MAD16 is not set +# CONFIG_SOUND_PAS is not set +# CONFIG_SOUND_PSS is not set +# CONFIG_SOUND_SOFTOSS is not set +CONFIG_SOUND_SB=m # CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_OPL3SA2 is not set # CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_AD1816 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_SOFTOSS is not set +# CONFIG_SOUND_VIA82CXXX is not set # CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_VMIDI is not set +# CONFIG_SOUND_OPL3SA1 is not set +# CONFIG_SOUND_OPL3SA2 is not set # CONFIG_SOUND_UART6850 is not set # CONFIG_SOUND_VIDC is not set CONFIG_SOUND_WAVEARTIST=m @@ -482,10 +553,11 @@ CONFIG_WAVEARTIST_DMA2=7 # Filesystems # # CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS_FS=y CONFIG_ADFS_FS=y # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set CONFIG_FAT_FS=m CONFIG_MSDOS_FS=m # CONFIG_UMSDOS_FS is not set @@ -497,10 +569,12 @@ CONFIG_JOLIET=y # CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y +CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set # 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 # @@ -510,7 +584,7 @@ CONFIG_EXT2_FS=y CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y CONFIG_NFSD=m -# CONFIG_NFSD_SUN 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/arm/def-configs/rpc b/arch/arm/def-configs/rpc index 904bb0724..e801bf641 100644 --- a/arch/arm/def-configs/rpc +++ b/arch/arm/def-configs/rpc @@ -4,6 +4,11 @@ CONFIG_ARM=y # +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# # System and processor type # # CONFIG_ARCH_ARC is not set @@ -12,21 +17,14 @@ CONFIG_ARCH_RPC=y # CONFIG_ARCH_EBSA110 is not set # CONFIG_FOOTBRIDGE is not set CONFIG_ARCH_ACORN=y -# CONFIG_ISA_DMA is not set CONFIG_CPU_32=y # CONFIG_CPU_26 is not set -# CONFIG_CPU_ARM2 is not set -# CONFIG_CPU_ARM3 is not set -# CONFIG_CPU_ARM6 is not set -# CONFIG_CPU_ARM7 is not set +CONFIG_CPU_32v3=y +CONFIG_CPU_ARM6=y +CONFIG_CPU_ARM7=y CONFIG_CPU_SA110=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y +# CONFIG_ISA_DMA is not set # CONFIG_ALIGNMENT_TRAP is not set -# CONFIG_TEXT_SECTIONS is not set # # Loadable module support @@ -43,16 +41,38 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_NWFPE is not set +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set CONFIG_PARPORT=y CONFIG_PARPORT_PC=y +# CONFIG_PARPORT_PC_FIFO is not set +# CONFIG_PARPORT_ARC is not set +# CONFIG_PARPORT_AMIGA is not set +# CONFIG_PARPORT_MFC3 is not set +# CONFIG_PARPORT_ATARI is not set +# CONFIG_PARPORT_SUNBPP is not set +# CONFIG_PARPORT_OTHER is not set +# CONFIG_PARPORT_1284 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set # -# Plug and Play support +# Plug and Play configuration # # CONFIG_PNP is not set +# CONFIG_ISAPNP is not set # # Block devices @@ -65,11 +85,22 @@ CONFIG_BLK_DEV_IDE=y # # CONFIG_BLK_DEV_HD_IDE is not set CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y CONFIG_BLK_DEV_IDECD=y -CONFIG_BLK_DEV_IDETAPE=y -CONFIG_BLK_DEV_IDEFLOPPY=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set + +# +# IDE chipset support/bugfixes +# # CONFIG_BLK_DEV_CMD640 is not set +CONFIG_BLK_DEV_IDE_ICSIDE=y +CONFIG_BLK_DEV_IDEDMA_ICS=y +CONFIG_IDEDMA_ICS_AUTO=y +CONFIG_BLK_DEV_IDE_RAPIDE=y +CONFIG_BLK_DEV_IDEDMA=y +CONFIG_IDEDMA_AUTO=y # CONFIG_IDE_CHIPSETS is not set # @@ -83,14 +114,12 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_BLK_DEV_XD is not set CONFIG_PARIDE_PARPORT=y # CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set # CONFIG_BLK_DEV_HD is not set # # Acorn-specific block devices # -CONFIG_BLK_DEV_IDE_CARDS=y -CONFIG_BLK_DEV_IDE_ICSIDE=y -CONFIG_BLK_DEV_IDE_RAPIDE=y # # Character devices @@ -99,25 +128,36 @@ CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_SERIAL=y # CONFIG_SERIAL_CONSOLE is not set -# CONFIG_SERIAL_EXTENDED is not set CONFIG_ATOMWIDE_SERIAL=y CONFIG_DUALSP_SERIAL=y +# CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set # CONFIG_UNIX98_PTYS is not set CONFIG_PRINTER=m -CONFIG_PRINTER_READBACK=y -CONFIG_MOUSE=y +# CONFIG_LP_CONSOLE is not set +# CONFIG_PPDEV is not set # # Mice # +CONFIG_BUSMOUSE=y # CONFIG_ATIXL_BUSMOUSE is not set -# CONFIG_BUSMOUSE is not set +# CONFIG_LOGIBUSMOUSE is not set # CONFIG_MS_BUSMOUSE is not set +CONFIG_MOUSE=y # CONFIG_PSMOUSE is not set # CONFIG_82C710_MOUSE is not set # CONFIG_PC110_PAD is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set # CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set @@ -126,27 +166,39 @@ CONFIG_MOUSE=y # Video For Linux # # CONFIG_VIDEO_DEV is not set - -# -# Joystick support -# -# CONFIG_JOYSTICK is not set # CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set +# CONFIG_DRM is not set +# CONFIG_DRM_TDFX is not set +# CONFIG_AGP is not set CONFIG_RPCMOUSE=y # +# Support for USB +# +# CONFIG_USB is not set + +# # Console drivers # CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y CONFIG_FB_ACORN=y # CONFIG_FB_MATROX is not set # CONFIG_FB_ATY is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_3DFX is not set # CONFIG_FB_VIRTUAL is not set CONFIG_FBCON_ADVANCED=y CONFIG_FBCON_MFB=y @@ -162,6 +214,7 @@ CONFIG_FBCON_CFB32=y # CONFIG_FBCON_IPLAN2P4 is not set # CONFIG_FBCON_IPLAN2P8 is not set # CONFIG_FBCON_MAC is not set +# CONFIG_FBCON_VGA_PLANES is not set # CONFIG_FBCON_VGA is not set # CONFIG_FBCON_FONTWIDTH8_ONLY is not set CONFIG_FBCON_FONTS=y @@ -178,7 +231,7 @@ CONFIG_FONT_ACORN_8x8=y # # CONFIG_PACKET is not set # CONFIG_NETLINK is not set -# CONFIG_FIREWALL is not set +# CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y @@ -194,15 +247,17 @@ CONFIG_INET=y # # (it is safe to leave these untouched) # -# CONFIG_INET_RARP is not set CONFIG_SKB_LARGE=y # CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set # # # # CONFIG_IPX is not set # CONFIG_ATALK is not set +# CONFIG_DECNET is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_BRIDGE is not set @@ -211,7 +266,6 @@ CONFIG_SKB_LARGE=y # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set # CONFIG_NET_HW_FLOWCONTROL is not set -# CONFIG_CPU_IS_SLOW is not set # # QoS and/or fair queueing @@ -224,7 +278,7 @@ CONFIG_SKB_LARGE=y # CONFIG_HAMRADIO is not set # -# IrDA subsystem support +# IrDA (infrared) support # # CONFIG_IRDA is not set @@ -232,39 +286,67 @@ CONFIG_SKB_LARGE=y # Network device support # CONFIG_NETDEVICES=y + +# +# ARCnet devices +# # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_EQUALIZER is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# CONFIG_NET_ETHERNET=y CONFIG_ARM_ETHER1=m CONFIG_ARM_ETHER3=m -CONFIG_ARM_ETHERH=m +CONFIG_ARM_ETHERH=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_RTL8139 is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_ACENIC is not set +# CONFIG_DM9102 is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set # CONFIG_NET_EISA is not set # CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set -# CONFIG_DLCI is not set # CONFIG_PLIP is not set CONFIG_PPP=m +# CONFIG_PPP_ASYNC is not set +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_SLIP is not set # -# CCP compressors for PPP are only built as modules. +# Wireless LAN (non-hamradio) # -# CONFIG_SLIP is not set # CONFIG_NET_RADIO is not set + +# +# Token Ring driver support +# # CONFIG_TR is not set -# CONFIG_SHAPER is not set -# CONFIG_HOSTESS_SV11 is not set -# CONFIG_COSA is not set +# CONFIG_NET_FC is not set # CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set # # SCSI support @@ -283,6 +365,7 @@ CONFIG_CHR_DEV_SG=y # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # +CONFIG_SCSI_DEBUG_QUEUES=y # CONFIG_SCSI_MULTI_LUN is not set CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y @@ -296,6 +379,7 @@ CONFIG_SCSI_LOGGING=y # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_IPS is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set @@ -314,6 +398,7 @@ CONFIG_SCSI_IMM=m # CONFIG_SCSI_IZIP_SLOW_CTR is not set # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_SIM710 is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set @@ -342,32 +427,37 @@ CONFIG_SCSI_OAK1=m # Sound # CONFIG_SOUND=m +# CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_ES1370 is not set # CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set # CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set CONFIG_SOUND_OSS=m -# CONFIG_SOUND_PAS is not set -# CONFIG_SOUND_SB is not set -# CONFIG_SOUND_ADLIB is not set -# CONFIG_SOUND_GUS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_AD1816 is not set +# CONFIG_SOUND_SGALAXY is not set +# CONFIG_SOUND_CS4232 is not set # CONFIG_SOUND_SSCAPE is not set +# CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_VMIDI is not set # CONFIG_SOUND_TRIX is not set +# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_MPU401 is not set +# CONFIG_SOUND_NM256 is not set # CONFIG_SOUND_MAD16 is not set +# CONFIG_SOUND_PAS is not set +# CONFIG_SOUND_PSS is not set +# CONFIG_SOUND_SOFTOSS is not set +# CONFIG_SOUND_SB is not set # CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_OPL3SA2 is not set # CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_AD1816 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_SOFTOSS is not set +# CONFIG_SOUND_VIA82CXXX is not set # CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_VMIDI is not set +# CONFIG_SOUND_OPL3SA1 is not set +# CONFIG_SOUND_OPL3SA2 is not set # CONFIG_SOUND_UART6850 is not set CONFIG_SOUND_VIDC=m # CONFIG_SOUND_WAVEARTIST is not set @@ -385,10 +475,12 @@ CONFIG_SOUND_VIDC=m CONFIG_ADFS_FS=y # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y +# CONFIG_BFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set -CONFIG_VFAT_FS=y +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set CONFIG_ISO9660_FS=y CONFIG_JOLIET=y # CONFIG_MINIX_FS is not set @@ -399,6 +491,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 # @@ -415,12 +508,17 @@ CONFIG_LOCKD=y # # Partition Types # -# CONFIG_OSF_PARTITION is not set -# CONFIG_MAC_PARTITION is not set +CONFIG_PARTITION_ADVANCED=y +CONFIG_OSF_PARTITION=y +CONFIG_MAC_PARTITION=y CONFIG_MSDOS_PARTITION=y -# CONFIG_SGI_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set +CONFIG_BSD_DISKLABEL=y +CONFIG_SOLARIS_X86_PARTITION=y +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_SGI_PARTITION=y +CONFIG_SUN_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# CONFIG_ATARI_PARTITION is not set CONFIG_ACORN_PARTITION=y CONFIG_ACORN_PARTITION_ADFS=y CONFIG_ACORN_PARTITION_ICS=y @@ -456,6 +554,7 @@ CONFIG_NLS_ISO8859_6=m CONFIG_NLS_ISO8859_7=m CONFIG_NLS_ISO8859_8=m CONFIG_NLS_ISO8859_9=m +# CONFIG_NLS_ISO8859_14 is not set # CONFIG_NLS_ISO8859_15 is not set CONFIG_NLS_KOI8_R=m @@ -467,5 +566,4 @@ CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_INFO is not set CONFIG_MAGIC_SYSRQ=y -# CONFIG_ARTHUR is not set -# CONFIG_DEBUG_LL is not set +CONFIG_DEBUG_LL=y diff --git a/arch/arm/defconfig b/arch/arm/defconfig index 2aba351c2..472c637c3 100644 --- a/arch/arm/defconfig +++ b/arch/arm/defconfig @@ -4,6 +4,11 @@ CONFIG_ARM=y # +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# # System and processor type # # CONFIG_ARCH_ARC is not set @@ -17,23 +22,13 @@ CONFIG_ARCH_EBSA285=y # CONFIG_CATS is not set CONFIG_ARCH_NETWINDER=y # CONFIG_ARCH_ACORN is not set -CONFIG_PCI=y -CONFIG_PCI_NAMES=y -CONFIG_ISA_DMA=y CONFIG_CPU_32=y # CONFIG_CPU_26 is not set -# CONFIG_CPU_ARM2 is not set -# CONFIG_CPU_ARM3 is not set -# CONFIG_CPU_ARM6 is not set -# CONFIG_CPU_ARM7 is not set +CONFIG_CPU_32v4=y CONFIG_CPU_SA110=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y +CONFIG_PCI=y +CONFIG_ISA_DMA=y # CONFIG_ALIGNMENT_TRAP is not set -# CONFIG_TEXT_SECTIONS is not set # # Loadable module support @@ -58,15 +53,34 @@ CONFIG_BINFMT_ELF=y # CONFIG_ARTHUR is not set CONFIG_PARPORT=y CONFIG_PARPORT_PC=y +CONFIG_PARPORT_PC_FIFO=y +# CONFIG_PARPORT_ARC is not set +# CONFIG_PARPORT_AMIGA is not set +# CONFIG_PARPORT_MFC3 is not set +# CONFIG_PARPORT_ATARI is not set +# CONFIG_PARPORT_SUNBPP is not set +# CONFIG_PARPORT_OTHER is not set +CONFIG_PARPORT_1284=y CONFIG_CMDLINE="root=/dev/hda1 ro mem=32M parport=0x378,7 ide0=autotune" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y # CONFIG_LEDS_CPU is not set # -# Plug and Play support +# I2O device support # -# CONFIG_PNP is not set +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Plug and Play configuration +# +CONFIG_PNP=y +CONFIG_ISAPNP=y # # Block devices @@ -79,23 +93,40 @@ CONFIG_BLK_DEV_IDE=y # # CONFIG_BLK_DEV_HD_IDE is not set CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y # 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 + +# +# IDE chipset support/bugfixes +# # CONFIG_BLK_DEV_CMD640 is not set # CONFIG_BLK_DEV_RZ1000 is not set CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_IDEDMA=y -CONFIG_BLK_DEV_OFFBOARD=y +CONFIG_BLK_DEV_IDEDMA_PCI=y CONFIG_IDEDMA_PCI_AUTO=y +CONFIG_IDEDMA_NEW_DRIVE_LISTINGS=y +CONFIG_IDEDMA_PCI_EXPERIMENTAL=y +CONFIG_BLK_DEV_OFFBOARD=y +# CONFIG_BLK_DEV_AEC6210 is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_CMD646 is not set +CONFIG_BLK_DEV_CY82C693=y +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_PDC202XX=y +# CONFIG_PDC202XX_FORCE_BURST_BIT is not set +# CONFIG_PDC202XX_FORCE_MASTER_MODE is not set # CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_VIA82C586 is not set -# CONFIG_BLK_DEV_CMD646 is not set CONFIG_BLK_DEV_SL82C105=y +CONFIG_BLK_DEV_IDEDMA=y +CONFIG_IDEDMA_AUTO=y # CONFIG_IDE_CHIPSETS is not set +# CONFIG_BLK_CPQ_DA is not set # # Additional Block Devices @@ -110,6 +141,7 @@ CONFIG_MD_RAID5=m CONFIG_BLK_DEV_RAM=y # CONFIG_BLK_DEV_INITRD is not set # CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_DEV_DAC960 is not set CONFIG_PARIDE_PARPORT=y CONFIG_PARIDE=m @@ -139,6 +171,7 @@ CONFIG_PARIDE_KBIC=m CONFIG_PARIDE_KTTI=m CONFIG_PARIDE_ON20=m CONFIG_PARIDE_ON26=m +CONFIG_BLK_DEV_IDE_MODES=y # CONFIG_BLK_DEV_HD is not set # @@ -150,31 +183,38 @@ CONFIG_SERIAL=y CONFIG_SERIAL_CONSOLE=y # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_UNIX98_PTYS is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 CONFIG_PRINTER=m -CONFIG_PRINTER_READBACK=y -CONFIG_MOUSE=y +# CONFIG_LP_CONSOLE is not set +# CONFIG_PPDEV is not set # # Mice # -# CONFIG_ATIXL_BUSMOUSE is not set # CONFIG_BUSMOUSE is not set -# CONFIG_MS_BUSMOUSE is not set +CONFIG_MOUSE=y CONFIG_PSMOUSE=y # CONFIG_82C710_MOUSE is not set # CONFIG_PC110_PAD is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set # CONFIG_QIC02_TAPE is not set -CONFIG_WATCHDOG=y # # Watchdog Cards # +CONFIG_WATCHDOG=y # CONFIG_WATCHDOG_NOWAYOUT is not set # CONFIG_WDT is not set CONFIG_SOFT_WATCHDOG=y # CONFIG_PCWATCHDOG is not set # CONFIG_ACQUIRE_WDT is not set +# CONFIG_21285_WATCHDOG is not set +CONFIG_977_WATCHDOG=m CONFIG_DS1620=y CONFIG_NWBUTTON=y CONFIG_NWBUTTON_REBOOT=y @@ -185,29 +225,100 @@ CONFIG_RTC=y # # Video For Linux # -# CONFIG_VIDEO_DEV is not set - -# -# Joystick support -# -# CONFIG_JOYSTICK is not set +CONFIG_VIDEO_DEV=y +# CONFIG_I2C_PARPORT is not set + +# +# Radio/Video Adapters +# +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_VIDEO_BT848 is not set +# CONFIG_RADIO_GEMTEK is not set +# CONFIG_VIDEO_PMS is not set +# CONFIG_RADIO_MIROPCM20 is not set +# CONFIG_VIDEO_BWQCAM is not set +# CONFIG_VIDEO_CQCAM is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_VIDEO_STRADIS is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set +# CONFIG_VIDEO_ZORAN is not set +# CONFIG_VIDEO_BUZ is not set +# CONFIG_VIDEO_ZR36120 is not set +CONFIG_VIDEO_CYBERPRO=m # CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set # # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set +# CONFIG_DRM is not set +# CONFIG_DRM_TDFX is not set +# CONFIG_AGP is not set + +# +# Support for USB +# +CONFIG_USB=m + +# +# USB Controllers +# +# CONFIG_USB_UHCI is not set +CONFIG_USB_OHCI=m +CONFIG_USB_OHCI_DEBUG=y +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_OHCI_VROOTHUB=y + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEBUG_ISOC is not set +CONFIG_USB_PROC=y +# CONFIG_USB_EZUSB is not set + +# +# USB Devices +# +CONFIG_USB_MOUSE=m +# CONFIG_USB_HP_SCANNER is not set +CONFIG_USB_KBD=m +CONFIG_USB_AUDIO=m +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_CPIA is not set +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_SCSI is not set +# CONFIG_USB_USS720 is not set # # Console drivers # CONFIG_VGA_CONSOLE=y CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_RIVA is not set +# CONFIG_FB_CLGEN is not set # CONFIG_FB_PM2 is not set CONFIG_FB_CYBER2000=y # CONFIG_FB_MATROX is not set # CONFIG_FB_ATY is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_3DFX is not set # CONFIG_FB_VIRTUAL is not set CONFIG_FBCON_ADVANCED=y # CONFIG_FBCON_MFB is not set @@ -223,6 +334,7 @@ CONFIG_FBCON_CFB24=y # CONFIG_FBCON_IPLAN2P4 is not set # CONFIG_FBCON_IPLAN2P8 is not set # CONFIG_FBCON_MAC is not set +# CONFIG_FBCON_VGA_PLANES is not set CONFIG_FBCON_VGA=y # CONFIG_FBCON_FONTWIDTH8_ONLY is not set CONFIG_FBCON_FONTS=y @@ -238,8 +350,9 @@ CONFIG_FONT_ACORN_8x8=y # Networking options # CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set # CONFIG_NETLINK is not set -# CONFIG_FIREWALL is not set +# CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y @@ -257,15 +370,17 @@ CONFIG_IP_ALIAS=y # # (it is safe to leave these untouched) # -# CONFIG_INET_RARP is not set CONFIG_SKB_LARGE=y # CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set # # # # CONFIG_IPX is not set # CONFIG_ATALK is not set +# CONFIG_DECNET is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_BRIDGE is not set @@ -274,7 +389,6 @@ CONFIG_SKB_LARGE=y # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set # CONFIG_NET_HW_FLOWCONTROL is not set -# CONFIG_CPU_IS_SLOW is not set # # QoS and/or fair queueing @@ -287,7 +401,7 @@ CONFIG_SKB_LARGE=y # CONFIG_HAMRADIO is not set # -# IrDA subsystem support +# IrDA (infrared) support # # CONFIG_IRDA is not set @@ -295,9 +409,18 @@ CONFIG_SKB_LARGE=y # Network device support # CONFIG_NETDEVICES=y + +# +# ARCnet devices +# # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_EQUALIZER is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# CONFIG_NET_ETHERNET=y # CONFIG_ARM_AM79C961A is not set CONFIG_NET_VENDOR_3COM=y @@ -312,11 +435,13 @@ CONFIG_VORTEX=y # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_RTL8139 is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_ACENIC is not set +# CONFIG_DM9102 is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set CONFIG_NET_EISA=y # CONFIG_PCNET32 is not set +# CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_AC3200 is not set # CONFIG_APRICOT is not set # CONFIG_CS89x0 is not set @@ -327,31 +452,50 @@ CONFIG_DEC_ELCP=m # CONFIG_LNE390 is not set # CONFIG_NE3210 is not set CONFIG_NE2K_PCI=y +# CONFIG_SIS900 is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set # CONFIG_ES3210 is not set # CONFIG_EPIC100 is not set # CONFIG_ZNET is not set # CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set -# CONFIG_DLCI is not set # CONFIG_PLIP is not set CONFIG_PPP=m - -# -# CCP compressors for PPP are only built as modules. -# +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m CONFIG_SLIP=m CONFIG_SLIP_COMPRESSED=y CONFIG_SLIP_SMART=y CONFIG_SLIP_MODE_SLIP6=y + +# +# Wireless LAN (non-hamradio) +# # CONFIG_NET_RADIO is not set + +# +# Token Ring driver support +# # CONFIG_TR is not set -# CONFIG_SHAPER is not set -# CONFIG_HOSTESS_SV11 is not set -# CONFIG_COSA is not set +# CONFIG_NET_FC is not set # CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set # # SCSI support @@ -362,32 +506,37 @@ CONFIG_SLIP_MODE_SLIP6=y # Sound # CONFIG_SOUND=m +# CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_ES1370 is not set # CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set # CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set CONFIG_SOUND_OSS=m -# CONFIG_SOUND_PAS is not set -CONFIG_SOUND_SB=m -CONFIG_SOUND_ADLIB=m -# CONFIG_SOUND_GUS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_AD1816 is not set +# CONFIG_SOUND_SGALAXY is not set +# CONFIG_SOUND_CS4232 is not set # CONFIG_SOUND_SSCAPE is not set +# CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_VMIDI is not set # CONFIG_SOUND_TRIX is not set +# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_MPU401 is not set +# CONFIG_SOUND_NM256 is not set # CONFIG_SOUND_MAD16 is not set +# CONFIG_SOUND_PAS is not set +# CONFIG_SOUND_PSS is not set +# CONFIG_SOUND_SOFTOSS is not set +CONFIG_SOUND_SB=m # CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_OPL3SA2 is not set # CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_AD1816 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_SOFTOSS is not set +# CONFIG_SOUND_VIA82CXXX is not set # CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_VMIDI is not set +# CONFIG_SOUND_OPL3SA1 is not set +# CONFIG_SOUND_OPL3SA2 is not set # CONFIG_SOUND_UART6850 is not set # CONFIG_SOUND_VIDC is not set CONFIG_SOUND_WAVEARTIST=m @@ -405,24 +554,28 @@ CONFIG_WAVEARTIST_DMA2=7 # Filesystems # # CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS_FS=y CONFIG_ADFS_FS=y # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set CONFIG_FAT_FS=m CONFIG_MSDOS_FS=m # CONFIG_UMSDOS_FS is not set CONFIG_VFAT_FS=m +# CONFIG_EFS_FS is not set CONFIG_ISO9660_FS=m CONFIG_JOLIET=y # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y +CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set # 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 # @@ -432,7 +585,7 @@ CONFIG_EXT2_FS=y CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y CONFIG_NFSD=m -# CONFIG_NFSD_SUN is not set +# CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set @@ -441,12 +594,17 @@ CONFIG_LOCKD=y # # Partition Types # +CONFIG_PARTITION_ADVANCED=y # CONFIG_OSF_PARTITION is not set # CONFIG_MAC_PARTITION is not set CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_SGI_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set CONFIG_ACORN_PARTITION=y CONFIG_ACORN_PARTITION_ADFS=y # CONFIG_ACORN_PARTITION_ICS is not set @@ -482,6 +640,7 @@ CONFIG_NLS_ISO8859_2=m # CONFIG_NLS_ISO8859_7 is not set # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_14 is not set CONFIG_NLS_ISO8859_15=m # CONFIG_NLS_KOI8_R is not set @@ -490,7 +649,7 @@ CONFIG_NLS_ISO8859_15=m # CONFIG_FRAME_POINTER=y CONFIG_DEBUG_ERRORS=y -# CONFIG_DEBUG_USER is not set +CONFIG_DEBUG_USER=y # CONFIG_DEBUG_INFO is not set CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUG_LL is not set diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index cdd7a9821..0caf4bf26 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c @@ -16,6 +16,7 @@ #include <asm/dma.h> #include <asm/pgalloc.h> #include <asm/proc-fns.h> +#include <asm/processor.h> #include <asm/semaphore.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -29,8 +30,6 @@ extern void outswb(unsigned int port, const void *to, int len); extern unsigned int local_bh_count[NR_CPUS]; extern unsigned int local_irq_count[NR_CPUS]; -extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); - /* * syscalls */ @@ -125,7 +124,6 @@ EXPORT_SYMBOL(cpu_cache_purge_area); EXPORT_SYMBOL(__machine_arch_type); /* networking */ -EXPORT_SYMBOL(csum_partial_copy); EXPORT_SYMBOL(csum_partial_copy_nocheck); EXPORT_SYMBOL(__csum_ipv6_magic); @@ -172,8 +170,7 @@ EXPORT_SYMBOL_NOVERS(strpbrk); EXPORT_SYMBOL_NOVERS(strtok); EXPORT_SYMBOL_NOVERS(strrchr); EXPORT_SYMBOL_NOVERS(strstr); -EXPORT_SYMBOL_NOVERS(__memset); -EXPORT_SYMBOL_NOVERS(memset); /* needed for some versions of gcc */ +EXPORT_SYMBOL_NOVERS(memset); EXPORT_SYMBOL_NOVERS(memcpy); EXPORT_SYMBOL_NOVERS(memmove); EXPORT_SYMBOL_NOVERS(memcmp); diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index b9b7d57b4..d055ae1fb 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -5,6 +5,7 @@ * * Bits taken from various places. */ +#include <linux/config.h> #include <linux/kernel.h> #include <linux/pci.h> #include <linux/errno.h> @@ -33,8 +34,8 @@ void pcibios_report_device_errors(void) continue; pci_write_config_word(dev, PCI_STATUS, status & 0xf900); - printk(KERN_DEBUG "PCI: status %04X on %s\n", - status, dev->name); + printk(KERN_DEBUG "PCI: %02X:%02X: status %04X on %s\n", + dev->bus->number, dev->devfn, status, dev->name); } } @@ -162,9 +163,10 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq) */ void __init pcibios_fixup_bus(struct pci_bus *bus) { - struct pci_dev *dev; + struct list_head *walk = &bus->devices; - for (dev = bus->devices; dev; dev = dev->sibling) { + for (walk = walk->next; walk != &bus->devices; walk = walk->next) { + struct pci_dev *dev = pci_dev_b(walk); u16 cmd; /* @@ -220,6 +222,7 @@ static u8 __init no_swizzle(struct pci_dev *dev, u8 *pin) return 0; } +#ifdef CONFIG_FOOTBRIDGE /* ebsa285 host-specific stuff */ static int irqmap_ebsa285[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 }; @@ -255,7 +258,7 @@ static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 }; static int __init cats_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { if (dev->irq >= 128) - return 16 + (dev->irq & 0x1f); + return dev->irq & 0x1f; if (dev->irq >= 1 && dev->irq <= 4) return irqmap_cats[dev->irq - 1]; @@ -313,17 +316,53 @@ static struct hw_pci netwinder_pci __initdata = { no_swizzle, netwinder_map_irq }; +#endif + +#ifdef CONFIG_ARCH_NEXUSPCI +/* + * Owing to a PCB cockup, issue A backplanes are wired thus: + * + * Slot 1 2 3 4 5 Bridge + * IRQ D C B A A + * A D C B B + * B A D C C + * C B A D D + * + * ID A31 A30 A29 A28 A27 A26 + */ + +static int irqmap_ftv[] __initdata = { IRQ_PCI_A, IRQ_PCI_B, IRQ_PCI_C, IRQ_PCI_D }; + +static int __init ftv_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + return irqmap_ftv[(slot + pin) & 3]; +} + +/* ftv host-specific stuff */ +static struct hw_pci ftv_pci __initdata = { + plx90x0_init, + 0x9000, + 0x00100000, + no_swizzle, + ftv_map_irq +}; +#endif void __init pcibios_init(void) { struct hw_pci *hw_pci = NULL; +#ifdef CONFIG_FOOTBRIDGE if (machine_is_ebsa285()) hw_pci = &ebsa285_pci; else if (machine_is_cats()) hw_pci = &cats_pci; else if (machine_is_netwinder()) hw_pci = &netwinder_pci; +#endif +#ifdef CONFIG_ARCH_NEXUSPCI + hw_pci = &ftv_pci; +#endif if (hw_pci == NULL) return; @@ -346,12 +385,14 @@ void __init pcibios_init(void) pci_fixup_irqs(hw_pci->swizzle, hw_pci->map_irq); pci_set_bus_ranges(); +#ifdef CONFIG_FOOTBRIDGE /* * Initialise any other hardware after we've got the PCI bus * initialised. We may need the PCI bus to talk to this other * hardware. */ hw_init(); +#endif } char * __init pcibios_setup(char *str) @@ -363,7 +404,17 @@ char * __init pcibios_setup(char *str) return str; } -void __init -pcibios_align_resource(void *data, struct resource *res, unsigned long size) +/* + * Assign new address to PCI resource. We hope our resource information + * is complete. + * + * Expects start=0, end=size-1, flags=resource type. + */ +int pci_assign_resource(struct pci_dev *dev, int i) +{ + return 0; +} + +void pcibios_align_resource(void *data, struct resource *res, unsigned long size) { } diff --git a/arch/arm/kernel/bios32.h b/arch/arm/kernel/bios32.h index fb3117452..9a4380732 100644 --- a/arch/arm/kernel/bios32.h +++ b/arch/arm/kernel/bios32.h @@ -7,3 +7,4 @@ struct hw_pci { }; void __init dc21285_init(void); +void __init plx90x0_init(void); diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 51f3dcde2..d8d416c4e 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -25,19 +25,19 @@ .long SYMBOL_NAME(sys_time) .long SYMBOL_NAME(sys_mknod) /* 15 */ .long SYMBOL_NAME(sys_chmod) - .long SYMBOL_NAME(sys_lchown) + .long SYMBOL_NAME(sys_lchown16) .long SYMBOL_NAME(sys_ni_syscall) /* was sys_break */ - .long SYMBOL_NAME(sys_stat) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_stat */ .long SYMBOL_NAME(sys_lseek) /* 20 */ .long SYMBOL_NAME(sys_getpid) - .long SYMBOL_NAME(sys_mount_wrapper) + .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) /* 25 */ .long SYMBOL_NAME(sys_stime) .long SYMBOL_NAME(sys_ptrace) .long SYMBOL_NAME(sys_alarm) - .long SYMBOL_NAME(sys_fstat) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_fstat */ .long SYMBOL_NAME(sys_pause) /* 30 */ .long SYMBOL_NAME(sys_utime) .long SYMBOL_NAME(sys_ni_syscall) /* was sys_stty */ @@ -55,11 +55,11 @@ .long SYMBOL_NAME(sys_times) .long SYMBOL_NAME(sys_ni_syscall) /* was sys_prof */ /* 45 */ .long SYMBOL_NAME(sys_brk) - .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) -/* 50 */ .long SYMBOL_NAME(sys_getegid) + .long SYMBOL_NAME(sys_geteuid16) +/* 50 */ .long SYMBOL_NAME(sys_getegid16) .long SYMBOL_NAME(sys_acct) .long SYMBOL_NAME(sys_umount) .long SYMBOL_NAME(sys_ni_syscall) /* was sys_lock */ @@ -79,8 +79,8 @@ .long SYMBOL_NAME(sys_sigaction) .long SYMBOL_NAME(sys_sgetmask) .long SYMBOL_NAME(sys_ssetmask) -/* 70 */ .long SYMBOL_NAME(sys_setreuid) - .long SYMBOL_NAME(sys_setregid) +/* 70 */ .long SYMBOL_NAME(sys_setreuid16) + .long SYMBOL_NAME(sys_setregid16) .long SYMBOL_NAME(sys_sigsuspend_wrapper) .long SYMBOL_NAME(sys_sigpending) .long SYMBOL_NAME(sys_sethostname) @@ -89,11 +89,11 @@ .long SYMBOL_NAME(sys_getrusage) .long SYMBOL_NAME(sys_gettimeofday) .long SYMBOL_NAME(sys_settimeofday) -/* 80 */ .long SYMBOL_NAME(sys_getgroups) - .long SYMBOL_NAME(sys_setgroups) +/* 80 */ .long SYMBOL_NAME(sys_getgroups16) + .long SYMBOL_NAME(sys_setgroups16) .long SYMBOL_NAME(old_select) .long SYMBOL_NAME(sys_symlink) - .long SYMBOL_NAME(sys_lstat) + .long SYMBOL_NAME(sys_ni_syscall) /* was sys_lstat */ /* 85 */ .long SYMBOL_NAME(sys_readlink) .long SYMBOL_NAME(sys_uselib) .long SYMBOL_NAME(sys_swapon) @@ -104,7 +104,7 @@ .long SYMBOL_NAME(sys_truncate) .long SYMBOL_NAME(sys_ftruncate) .long SYMBOL_NAME(sys_fchmod) -/* 95 */ .long SYMBOL_NAME(sys_fchown) +/* 95 */ .long SYMBOL_NAME(sys_fchown16) .long SYMBOL_NAME(sys_getpriority) .long SYMBOL_NAME(sys_setpriority) .long SYMBOL_NAME(sys_ni_syscall) /* was sys_profil */ @@ -132,7 +132,7 @@ /* 120 */ .long SYMBOL_NAME(sys_clone_wapper) .long SYMBOL_NAME(sys_setdomainname) .long SYMBOL_NAME(sys_newuname) - .long SYMBOL_NAME(sys_ni_syscall) /* .long SYMBOL_NAME(sys_modify_ldt) */ + .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_adjtimex) /* 125 */ .long SYMBOL_NAME(sys_mprotect) .long SYMBOL_NAME(sys_sigprocmask) @@ -147,9 +147,9 @@ /* 135 */ .long SYMBOL_NAME(sys_sysfs) .long SYMBOL_NAME(sys_personality) .long SYMBOL_NAME(sys_ni_syscall) /* .long _sys_afs_syscall */ - .long SYMBOL_NAME(sys_setfsuid) - .long SYMBOL_NAME(sys_setfsgid) -/* 140 */ .long SYMBOL_NAME(sys_llseek_wrapper) + .long SYMBOL_NAME(sys_setfsuid16) + .long SYMBOL_NAME(sys_setfsgid16) +/* 140 */ .long SYMBOL_NAME(sys_llseek) .long SYMBOL_NAME(sys_getdents) .long SYMBOL_NAME(sys_select) .long SYMBOL_NAME(sys_flock) @@ -173,14 +173,14 @@ .long SYMBOL_NAME(sys_sched_rr_get_interval) .long SYMBOL_NAME(sys_nanosleep) .long SYMBOL_NAME(sys_mremap) - .long SYMBOL_NAME(sys_setresuid) -/* 165 */ .long SYMBOL_NAME(sys_getresuid) + .long SYMBOL_NAME(sys_setresuid16) +/* 165 */ .long SYMBOL_NAME(sys_getresuid16) .long SYMBOL_NAME(sys_ni_syscall) .long SYMBOL_NAME(sys_query_module) .long SYMBOL_NAME(sys_poll) .long SYMBOL_NAME(sys_nfsservctl) -/* 170 */ .long SYMBOL_NAME(sys_setresgid) - .long SYMBOL_NAME(sys_getresgid) +/* 170 */ .long SYMBOL_NAME(sys_setresgid16) + .long SYMBOL_NAME(sys_getresgid16) .long SYMBOL_NAME(sys_prctl) .long SYMBOL_NAME(sys_rt_sigreturn_wrapper) .long SYMBOL_NAME(sys_rt_sigaction) @@ -191,7 +191,7 @@ .long SYMBOL_NAME(sys_rt_sigsuspend_wrapper) /* 180 */ .long SYMBOL_NAME(sys_pread) .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) /* 185 */ .long SYMBOL_NAME(sys_capset) @@ -207,8 +207,27 @@ /* 195 */ .long SYMBOL_NAME(sys_stat64) .long SYMBOL_NAME(sys_lstat64) .long SYMBOL_NAME(sys_fstat64) + .long SYMBOL_NAME(sys_lchown) + .long SYMBOL_NAME(sys_getuid) +/* 200 */ .long SYMBOL_NAME(sys_getgid) + .long SYMBOL_NAME(sys_geteuid) + .long SYMBOL_NAME(sys_getegid) + .long SYMBOL_NAME(sys_setreuid) + .long SYMBOL_NAME(sys_setregid) +/* 205 */ .long SYMBOL_NAME(sys_getgroups) + .long SYMBOL_NAME(sys_setgroups) + .long SYMBOL_NAME(sys_fchown) + .long SYMBOL_NAME(sys_setresuid) + .long SYMBOL_NAME(sys_getresuid) +/* 210 */ .long SYMBOL_NAME(sys_setresgid) + .long SYMBOL_NAME(sys_getresgid) + .long SYMBOL_NAME(sys_chown) + .long SYMBOL_NAME(sys_setuid) + .long SYMBOL_NAME(sys_setgid) +/* 215 */ .long SYMBOL_NAME(sys_setfsuid) + .long SYMBOL_NAME(sys_setfsgid) - .rept NR_syscalls-197 + .rept NR_syscalls-216 .long SYMBOL_NAME(sys_ni_syscall) .endr #endif diff --git a/arch/arm/kernel/debug-armv.S b/arch/arm/kernel/debug-armv.S index fef1489b7..5802dac70 100644 --- a/arch/arm/kernel/debug-armv.S +++ b/arch/arm/kernel/debug-armv.S @@ -134,19 +134,26 @@ #elif defined(CONFIG_ARCH_SA1100) .macro addruart,rx mov \rx, #0xf8000000 - add \rx, \rx, #0x00050000 + add \rx, \rx, #0x00050000 @ Ser3 + @add \rx, \rx, #0x00010000 @ Ser1 .endm .macro senduart,rd,rx - str \rd, [\rx, #0x14] @ UARTDR + str \rd, [\rx, #0x14] @ UTDR .endm - .macro busyuart,rd,rx + .macro waituart,rd,rx 1001: ldr \rd, [\rx, #0x20] @ UTSR1 - tst \rd, #1 << 2 + tst \rd, #1 << 2 @ UTSR1_TNF beq 1001b .endm + .macro busyuart,rd,rx +1001: ldr \rd, [\rx, #0x20] @ UTSR1 + tst \rd, #1 << 0 @ UTSR1_TBY + bne 1001b + .endm + #else #error Unknown architecture #endif diff --git a/arch/arm/kernel/dec21285.c b/arch/arm/kernel/dec21285.c index dc7cc054e..6158e995a 100644 --- a/arch/arm/kernel/dec21285.c +++ b/arch/arm/kernel/dec21285.c @@ -220,7 +220,9 @@ void __init dc21285_init(void) #ifdef CONFIG_HOST_FOOTBRIDGE csrio.flags = IORESOURCE_IO; + csrio.name = "DC21285"; csrmem.flags = IORESOURCE_MEM; + csrmem.name = "DC21285"; allocate_resource(&ioport_resource, &csrio, 128, 0xff00, 0xffff, 128, NULL, NULL); @@ -244,7 +246,7 @@ void __init dc21285_init(void) (1 << 31) | (1 << 29) | (1 << 28) | (1 << 24); #endif - printk(KERN_DEBUG"PCI: DC21285 footbridge, revision %02lX\n", + printk(KERN_DEBUG "PCI: DC21285 footbridge, revision %02lX\n", *CSR_CLASSREV & 0xff); pci_scan_bus(0, &dc21285_ops, NULL); diff --git a/arch/arm/kernel/entry-armo.S b/arch/arm/kernel/entry-armo.S index 5d9ce0ac6..f2dc9e36c 100644 --- a/arch/arm/kernel/entry-armo.S +++ b/arch/arm/kernel/entry-armo.S @@ -535,7 +535,6 @@ Ldata_unknown: @ Part of jumptable mov r0, r1 mov r1, r4 mov r2, r3 - mov r3, lr b baddataabort Ldata_ldrstr_post: diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 6d4107ede..f4f03ee93 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -429,7 +429,10 @@ __und_invalid: sub sp, sp, #S_FRAME_SIZE and r2, r6, #31 @ int mode b SYMBOL_NAME(bad_mode) - +#ifdef CONFIG_NWFPE + /* The FPE is always present */ + .equ fpe_not_present, 0 +#else wfs_mask_data: .word 0x0e200110 @ WFS/RFS .word 0x0fef0fff .word 0x0d0d0100 @ LDF [sp]/STF [sp] @@ -466,6 +469,7 @@ fpe_not_present: add r5, r5, r4, lsl #2 str r5, [sp, r6, lsr #14] @ Save reg mov pc, r9 +#endif /* * SVC mode handlers @@ -685,11 +689,11 @@ ENTRY(__switch_to) stmfd sp!, {r4 - sl, fp, lr} @ Store most regs on stack mrs ip, cpsr stmfd sp!, {ip} @ Save cpsr_SVC - ldr r2, [r1, #TSS_DOMAIN] str sp, [r0, #TSS_SAVE] @ Save sp_SVC ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC - mcr p15, 0, r2, c3, c0 @ Set domain register + ldr r2, [r1, #TSS_DOMAIN] ldmfd sp!, {ip} + mcr p15, 0, r2, c3, c0 @ Set domain register msr spsr, ip @ Save tasks CPSR into SPSR for this return ldmfd sp!, {r4 - sl, fp, pc}^ @ Load all regs saved previously diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index bdf6de6b3..2be1a6012 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -3,6 +3,9 @@ * All exits to user mode from the kernel go through this code. */ +#define S_OFF 8 +#define SYSCALL_REGS r4, r5 + /* * Define to favour ARM8, ARM9 and StrongARM cpus. This says that it is * cheaper to use two LDR instructions than a two-register LDM, if the @@ -16,9 +19,9 @@ .align 5 fast_syscall_return: - str r0, [sp, #S_R0 + 4] @ returned r0 + str r0, [sp, #S_R0 + S_OFF] @ returned r0 slow_syscall_return: - add sp, sp, #4 + add sp, sp, #S_OFF ret_from_sys_call: #ifdef HARVARD_CACHE ldr r0, bh_data @@ -74,65 +77,71 @@ ret_from_exception: /*============================================================================= * SWI handler *----------------------------------------------------------------------------- - * - * We now handle sys-call tracing, and the errno in the task structure. - * Still have a problem with >4 arguments for functions. Theres only - * a couple of functions in the code that have 5 arguments, so Im not - * too worried. */ +/* + * Create some aliases for some registers. These should allow + * us to have in theory up to 7 arguments to a function. + */ +scno .req r9 @ syscall number +tbl .req r8 @ syscall table pointer +tip .req r7 @ temporary IP + .align 5 vector_swi: save_user_regs mask_pc lr, lr mov fp, #0 - ldr r6, [lr, #-4] @ get SWI instruction - arm700_bug_check r6, r7 + ldr scno, [lr, #-4] @ get SWI instruction + arm700_bug_check scno, ip #ifdef CONFIG_ALIGNMENT_TRAP - ldr r7, .LCswi - ldr r7, [r7] - mcr p15, 0, r7, c1, c0 + ldr ip, .LCswi + ldr ip, [ip] + mcr p15, 0, ip, c1, c0 #endif - enable_irqs r7 + enable_irqs ip - str r4, [sp, #-4]! @ new style: (r0 = arg1, r4 = arg5) + stmdb sp!, {SYSCALL_REGS} @ new style: (r0 = arg1, r4 = arg5, r5 = arg6) + @ Note that we dont have to handle + @ sys_syscalls arg7 here adrsvc al, lr, fast_syscall_return - bic r6, r6, #0xff000000 @ mask off SWI op-code - eor r6, r6, #OS_NUMBER<<20 @ check OS number - cmp r6, #NR_syscalls @ check upper syscall limit + bic scno, scno, #0xff000000 @ mask off SWI op-code + eor scno, scno, #OS_NUMBER<<20 @ check OS number + cmp scno, #NR_syscalls @ check upper syscall limit bcs 2f - get_current_task r7 - ldr ip, [r7, #TSK_FLAGS] @ check for syscall tracing - adr r5, SYMBOL_NAME(sys_call_table) + get_current_task ip + ldr ip, [ip, #TSK_FLAGS] @ check for syscall tracing + adr tbl, SYMBOL_NAME(sys_call_table) tst ip, #PF_TRACESYS - ldreq pc, [r5, r6, lsl #2] @ call sys routine + ldreq pc, [tbl, scno, lsl #2] @ call sys routine - ldr r7, [sp, #S_IP + 4] @ save old IP - mov r0, #0 - str r0, [sp, #S_IP + 4] @ trace entry [IP = 0] + ldr tip, [sp, #S_IP + S_OFF] @ save old IP + mov ip, #0 + str ip, [sp, #S_IP + S_OFF] @ trace entry [IP = 0] bl SYMBOL_NAME(syscall_trace) - str r7, [sp, #S_IP + 4] + str tip, [sp, #S_IP + S_OFF] - ldmib sp, {r0 - r3} @ have to reload r0 - r3 + add ip, sp, #S_OFF + ldmia ip, {r0 - r3} @ have to reload r0 - r3 mov lr, pc - ldr pc, [r5, r6, lsl #2] @ call sys routine - str r0, [sp, #S_R0 + 4] @ returned r0 + ldr pc, [tbl, scno, lsl #2] @ call sys routine + str r0, [sp, #S_R0 + S_OFF] @ returned r0 - mov r0, #1 - str r0, [sp, #S_IP + 4] @ trace exit [IP = 1] + mov ip, #1 + str ip, [sp, #S_IP + S_OFF] @ trace exit [IP = 1] bl SYMBOL_NAME(syscall_trace) - str r7, [sp, #S_IP + 4] + str tip, [sp, #S_IP + S_OFF] b slow_syscall_return -2: add r1, sp, #4 - tst r6, #0x00f00000 @ is it a Unix SWI? +2: add r1, sp, #S_OFF + tst scno, #0x00f00000 @ is it a Unix SWI? bne 3f - subs r0, r6, #(KSWI_SYS_BASE - KSWI_BASE) + subs r0, scno, #(KSWI_SYS_BASE - KSWI_BASE) bcs SYMBOL_NAME(arm_syscall) b SYMBOL_NAME(sys_ni_syscall) @ not private func -3: eor r0, r6, #OS_NUMBER <<20 @ Put OS number back +3: eor r0, scno, #OS_NUMBER <<20 @ Put OS number back adrsvc al, lr, slow_syscall_return b SYMBOL_NAME(deferred) @@ -150,67 +159,49 @@ ENTRY(sys_call_table) @ r0 = syscall number @ r5 = syscall table SYMBOL_NAME(sys_syscall): - eor r6, r0, #OS_NUMBER << 20 - cmp r6, #NR_syscalls @ check range - add ip, sp, #4 - ldmleib ip, {r0 - r4} @ get our args - strle r4, [sp] @ Put our arg on the stack - ldrle pc, [r5, r6, lsl #2] + eor scno, r0, #OS_NUMBER << 20 + cmp scno, #NR_syscalls @ check range + add ip, sp, #S_OFF + ldmleib ip, {r0 - r3, SYSCALL_REGS} @ get our args + stmleia sp, {SYSCALL_REGS} @ Put our arg on the stack + ldrle pc, [tbl, scno, lsl #2] mov r0, #-ENOSYS - mov pc, lr + RETINSTR(mov,pc,lr) sys_fork_wrapper: - add r0, sp, #4 + add r0, sp, #S_OFF b SYMBOL_NAME(sys_fork) sys_vfork_wrapper: - add r0, sp, #4 + add r0, sp, #S_OFF b SYMBOL_NAME(sys_vfork) sys_execve_wrapper: - add r3, sp, #4 + add r3, sp, #S_OFF b SYMBOL_NAME(sys_execve) -sys_mount_wrapper: - mov r6, lr - add r5, sp, #4 - str r5, [sp] - str r4, [sp, #-4]! - bl SYMBOL_NAME(sys_compat_mount) - add sp, sp, #4 - RETINSTR(mov,pc,r6) - sys_clone_wapper: - add r2, sp, #4 + add r2, sp, #S_OFF b SYMBOL_NAME(sys_clone) -sys_llseek_wrapper: - mov r6, lr - add r5, sp, #4 - str r5, [sp] - str r4, [sp, #-4]! - bl SYMBOL_NAME(sys_compat_llseek) - add sp, sp, #4 - RETINSTR(mov,pc,r6) - sys_sigsuspend_wrapper: - add r3, sp, #4 + add r3, sp, #S_OFF b SYMBOL_NAME(sys_sigsuspend) sys_rt_sigsuspend_wrapper: - add r2, sp, #4 + add r2, sp, #S_OFF b SYMBOL_NAME(sys_rt_sigsuspend) sys_sigreturn_wrapper: - add r0, sp, #4 + add r0, sp, #S_OFF b SYMBOL_NAME(sys_sigreturn) sys_rt_sigreturn_wrapper: - add r0, sp, #4 + add r0, sp, #S_OFF b SYMBOL_NAME(sys_rt_sigreturn) sys_sigaltstack_wrapper: - ldr r2, [sp, #4 + S_SP] + ldr r2, [sp, #S_OFF + S_SP] b do_sigaltstack .data diff --git a/arch/arm/kernel/head-armv.S b/arch/arm/kernel/head-armv.S index 2996d89af..35e71a4a9 100644 --- a/arch/arm/kernel/head-armv.S +++ b/arch/arm/kernel/head-armv.S @@ -69,7 +69,7 @@ ENTRY(_stext) * r1 contains the unique architecture number. See * linux/arch/arm/kernel/setup.c machine_desc[] array for the complete * list. If you require a new number, please follow the instructions - * given in Documentation/ARM-README. + * given in Documentation/arm/README. */ __entry: teq r0, #0 movne r0, #'i' @@ -83,7 +83,7 @@ __entry: teq r0, #0 moveq r0, #'a' beq __error bl __create_page_tables - adr lr, __aligned_call + adr lr, __ret add pc, r10, #12 @ flush caches (returns ctrl reg) __switch_data: .long __mmap_switched @@ -94,16 +94,11 @@ __switch_data: .long __mmap_switched .long SYMBOL_NAME(cr_alignment) .long SYMBOL_NAME(init_task_union)+8192 - /* - * This needs to be aligned to a cache line. - */ - .align 5 -__aligned_call: - ldr lr, __switch_data -#ifdef CONFIG_ALIGNMENT_TRAP - orr r0, r0, #2 @ ...........A. -#endif +__ret: ldr lr, __switch_data mcr p15, 0, r0, c1, c0 + mov r0, r0 + mov r0, r0 + mov r0, r0 mov pc, lr /* @@ -126,6 +121,9 @@ __mmap_switched: str r9, [r6] @ Save processor ID str r1, [r7] @ Save machine type +#ifdef CONFIG_ALIGNMENT_TRAP + orr r0, r0, #2 @ ...........A. +#endif bic r2, r0, #2 @ Clear 'A' bit stmia r8, {r0, r2} @ Save control register values b SYMBOL_NAME(start_kernel) @@ -137,16 +135,16 @@ __mmap_switched: * amount which are required to get the kernel running, which * generally means mapping in the kernel code. * - * We only map in 2MB of RAM, which should be sufficient in + * We only map in 4MB of RAM, which should be sufficient in * all cases. * - * r4 = physical address of page tables * r5 = physical address of start of RAM * r6 = physical IO address * r7 = byte offset into page tables for IO * r8 = page table flags */ __create_page_tables: + add r4, r5, #SWAPPER_PGDIR_OFFSET mov r0, r4 mov r3, #0 add r2, r0, #0x4000 @ Clear page table @@ -157,13 +155,22 @@ __create_page_tables: teq r0, r2 bne 1b /* - * map in two sections (2MB) for kernel. + * Create identity mapping for first MB of kernel. + * map in four sections (4MB) for kernel. * these are marked cacheable and bufferable. + * + * The identity mapping will be removed by paging_init() */ - add r0, r4, #(TEXTADDR - 0x8000) >> 18 mov r3, #0x0c orr r3, r3, r8 add r3, r3, r5 + add r0, r4, r5, lsr #18 + str r3, [r0] + add r0, r4, #(TEXTADDR - 0x8000) >> 18 + str r3, [r0], #4 + add r3, r3, #1 << 20 + str r3, [r0], #4 + add r3, r3, #1 << 20 str r3, [r0], #4 add r3, r3, #1 << 20 str r3, [r0], #4 @@ -174,8 +181,11 @@ __create_page_tables: * via a serial before paging_init. */ add r0, r4, r7 + rsb r3, r7, #0x4000 @ PTRS_PER_PGD*sizeof(long) + cmp r3, #0x0800 + addge r2, r0, #0x0800 + addlt r2, r0, r3 orr r3, r6, r8 - add r2, r0, #0x0800 1: str r3, [r0], #4 add r3, r3, #1 << 20 teq r0, r2 @@ -273,7 +283,7 @@ __lookup_processor_type: * Lookup machine architecture * r1 = machine architecture number * Returns: - * r4 = physical address of page tables + * r4 = unused word * r5 = physical start address of RAM * r6 = physical address of IO * r7 = byte offset into page tables for IO @@ -284,7 +294,6 @@ __lookup_architecture_type: adr r4, __arch_types_start add r4, r4, r1, lsl #4 ldmia r4, {r4, r5, r6, r7} - add r4, r5, #SWAPPER_PGDIR_OFFSET mov r7, r7, lsr #18 mov pc, lr 1: mov r7, #0 @@ -330,20 +339,20 @@ __arch_types_start: @ 0x04 - DEC EBSA285 .long 0 .long 0 - .long 0x24000000 @ I/O base address (0x42000000 -> 0xfe000000) - .long 0xe0000000 + .long DC21285_ARMCSR_BASE + .long 0xfe000000 @ 0x05 - Rebel.com NetWinder .long 0 .long 0 - .long 0x24000000 @ I/O base address (0x42000000 -> 0xfe000000) - .long 0xe0000000 + .long DC21285_ARMCSR_BASE + .long 0xfe000000 @ 0x06 - CATS .long 0 .long 0 - .long 0x24000000 @ I/O base address (0x42000000 -> 0xfe000000) - .long 0xe0000000 + .long DC21285_ARMCSR_BASE + .long 0xfe000000 @ 0x07 - tbox .long 0 @@ -398,9 +407,16 @@ __arch_types_start: .long 0 .long 0 .long 0 -__arch_types_end: - @ unknown - SA1100 + + @ 0x10 - SA1100 .long 0 .long 0xc0000000 .long 0x80000000 - .long 0xe0000000 + .long 0xf8000000 + + /* + * Don't add anything here unless you have an + * architecture number allocated - see + * Documentation/arm/README + */ +__arch_types_end: diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 9afacbde3..46afd5938 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -50,13 +50,13 @@ void enable_hlt(void) static int __init nohlt_setup(char *__unused) { hlt_counter = 1; - return 0; + return 1; } static int __init hlt_setup(char *__unused) { hlt_counter = 0; - return 0; + return 1; } __setup("nohlt", nohlt_setup); @@ -114,6 +114,7 @@ void machine_halt(void) void machine_power_off(void) { + arch_power_off(); } void show_regs(struct pt_regs * regs) @@ -284,7 +285,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, int dump_fpu (struct pt_regs *regs, struct user_fp *fp) { if (current->used_math) - memcpy(fp, ¤t->thread.fpstate.soft, sizeof (fp)); + memcpy(fp, ¤t->thread.fpstate.soft, sizeof (*fp)); return current->used_math; } diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index a060bf4d9..a2f7292f6 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -54,13 +54,13 @@ struct meminfo meminfo; struct machine_desc { const char *name; /* architecture name */ unsigned int param_offset; /* parameter page */ + unsigned int video_start; /* start of video RAM */ + unsigned int video_end; /* end of video RAM */ unsigned int reserve_lp0 :1; /* never has lp0 */ unsigned int reserve_lp1 :1; /* never has lp1 */ unsigned int reserve_lp2 :1; /* never has lp2 */ unsigned int broken_hlt :1; /* hlt is broken */ unsigned int soft_reboot :1; /* soft reboot */ - unsigned int video_start; /* start of video RAM */ - unsigned int video_end; /* end of video RAM */ void (*fixup)(struct machine_desc *, struct param_struct *, char **); }; @@ -201,7 +201,7 @@ parse_cmdline(char **cmdline_p, char *from) meminfo.nr_banks = 0; } - start = 0; + start = PHYS_OFFSET; size = memparse(from + 4, &from); if (*from == '@') start = memparse(from + 1, &from); @@ -250,17 +250,18 @@ static void __init setup_initrd(unsigned int start, unsigned int size) } #define O_PFN_DOWN(x) ((x) >> PAGE_SHIFT) -#define P_PFN_DOWN(x) O_PFN_DOWN((x) - PHYS_OFFSET) #define V_PFN_DOWN(x) O_PFN_DOWN(__pa(x)) #define O_PFN_UP(x) (PAGE_ALIGN(x) >> PAGE_SHIFT) -#define P_PFN_UP(x) O_PFN_UP((x) - PHYS_OFFSET) #define V_PFN_UP(x) O_PFN_UP(__pa(x)) #define PFN_SIZE(x) ((x) >> PAGE_SHIFT) #define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \ (((unsigned long)(s)) & PAGE_MASK)) +/* + * FIXME: These can be removed when Ingo's cleanup patch goes in + */ #define free_bootmem(s,sz) free_bootmem((s)<<PAGE_SHIFT, (sz)<<PAGE_SHIFT) #define reserve_bootmem(s,sz) reserve_bootmem((s)<<PAGE_SHIFT, (sz)<<PAGE_SHIFT) @@ -277,10 +278,10 @@ static unsigned int __init find_bootmap_pfn(unsigned int bootmap_pages) */ #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) { - if (__pa(initrd_end) > (meminfo.end + PHYS_OFFSET)) { + if (__pa(initrd_end) > meminfo.end) { printk ("initrd extends beyond end of memory " "(0x%08lx > 0x%08lx) - disabling initrd\n", - __pa(initrd_end), meminfo.end + PHYS_OFFSET); + __pa(initrd_end), meminfo.end); initrd_start = 0; initrd_end = 0; } @@ -373,7 +374,7 @@ static void __init setup_bootmem(void) #endif #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) - reserve_bootmem(O_PFN_DOWN(initrd_start), + reserve_bootmem(V_PFN_DOWN(initrd_start), PFN_RANGE(initrd_start, initrd_end)); #endif } @@ -528,16 +529,66 @@ fixup_coebsa285(struct machine_desc *desc, struct param_struct *params, char **cmdline) { #if 0 - if (machine_is_co285()) { - extern unsigned long boot_memory_end; - extern char boot_command_line[]; + extern unsigned long boot_memory_end; + extern char boot_command_line[]; - meminfo.nr_banks = 1; - meminfo.bank[0].start = PHYS_OFFSET; - meminfo.bank[0].size = boot_memory_end; + meminfo.nr_banks = 1; + meminfo.bank[0].start = PHYS_OFFSET; + meminfo.bank[0].size = boot_memory_end; + + *cmdline = boot_command_line; +#endif +} - *cmdline = boot_command_line; +static void __init +fixup_sa1100(struct machine_desc *desc, struct param_struct *params, + char **cmdline) +{ +#ifdef CONFIG_ARCH_SA1100 + int i; + extern struct mem_desc { + unsigned long phys_start; + unsigned long length; + } mem_desc[]; + extern unsigned int mem_desc_size; + + for( i = 0; i < mem_desc_size; i++ ) { + if( i >= NR_BANKS ) { + printk( __FUNCTION__ + ": mem_desc too large for meminfo structure\n"); + break; + } + meminfo.bank[i].start = mem_desc[i].phys_start; + meminfo.bank[i].size = mem_desc[i].length; } + meminfo.nr_banks = i; + +#if defined(CONFIG_SA1100_BRUTUS) + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk( 1, 0, 0, 8192 ); + setup_initrd( __phys_to_virt(0xd8000000), 0x00400000 ); +#elif defined(CONFIG_SA1100_EMPEG) + ROOT_DEV = MKDEV( 3, 1 ); /* /dev/hda1 */ + setup_ramdisk( 1, 0, 0, 4096 ); + setup_initrd( 0xd0000000+((1024-320)*1024), (320*1024) ); +#elif defined(CONFIG_SA1100_TIFON) + ROOT_DEV = MKDEV(UNNAMED_MAJOR, 0); + setup_ramdisk(1, 0, 0, 4096); + setup_initrd( 0xd0000000 + 0x1100004, 0x140000 ); +#elif defined(CONFIG_SA1100_VICTOR) + ROOT_DEV = MKDEV( 60, 2 ); + + /* Get command line parameters passed from the loader (if any) */ + if( *((char*)0xc0000000) ) + strcpy( default_command_line, ((char *)0xc0000000) ); + + /* power off if any problem */ + strcat( default_command_line, " panic=1" ); +#elif defined(CONFIG_SA1100_LART) + ROOT_DEV = MKDEV(RAMDISK_MAJOR,0); + setup_ramdisk(1, 0, 0, 8192); + setup_initrd(0xc0400000, 0x00400000); +#endif #endif } @@ -565,7 +616,7 @@ static struct machine_desc machine_desc[] __initdata = { NO_VIDEO, 0, 0, 0, 0, 0, NULL - }, { "Nexus-FTV/PCI", /* Philip Blundell */ + }, { "FTV/PCI", /* Philip Blundell */ NO_PARAMS, NO_VIDEO, 0, 0, 0, 0, 0, @@ -627,9 +678,15 @@ static struct machine_desc machine_desc[] __initdata = { NULL }, { "Shark", /* Alexander Schulz */ NO_PARAMS, - NO_VIDEO, + /* do you really mean 0x200000? */ + 0x06000000, 0x06000000+0x00200000, 0, 0, 0, 0, 0, NULL + }, { "SA1100-based", /* Nicolas Pitre */ + NO_PARAMS, + NO_VIDEO, + 0, 0, 0, 0, 0, + fixup_sa1100 } }; diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 852bbfac1..f9fbd2536 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -18,6 +18,7 @@ #include <linux/stddef.h> #include <linux/binfmts.h> #include <linux/tty.h> +#include <linux/highuid.h> #include <asm/ucontext.h> #include <asm/uaccess.h> @@ -277,6 +278,7 @@ setup_sigcontext(struct sigcontext *sc, /*struct _fpstate *fpstate,*/ err |= __put_user (current->thread.trap_no, &sc->trap_no); err |= __put_user (current->thread.error_code, &sc->error_code); + err |= __put_user (current->thread.address, &sc->fault_address); err |= __put_user (mask, &sc->oldmask); return err; @@ -500,6 +502,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) info.si_code = SI_USER; info.si_pid = current->p_pptr->pid; info.si_uid = current->p_pptr->uid; + info.si_uid16 = high2lowuid(current->p_pptr->uid); } /* If the (new) signal is now blocked, requeue it. */ diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 408149bc5..5e989663b 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -79,12 +79,26 @@ out: return error; } +#define PGOFF_SHIFT (PAGE_SHIFT - 12) +#define PGOFF_MASK (~((1 << PGOFF_SHIFT) - 1)) + /* - * Perform the select(nd, in, out, ex, tv) and mmap() system - * calls. ARM Linux didn't use to be able to handle more than - * 4 system call parameters, so these system calls used a memory - * block for parameter passing.. + * Note: off_4k is always units of 4K. If we can't do the requested + * offset, we return EINVAL. */ +asmlinkage long +sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, + unsigned long flags, unsigned long fd, unsigned long off_4k) +{ + unsigned long pgoff; + + if (off_4k & ~PGOFF_MASK) + return -EINVAL; + + pgoff = off_4k >> PGOFF_SHIFT; + + return do_mmap2(addr, len, prot, flags, fd, pgoff); +} struct mmap_arg_struct { unsigned long addr; @@ -112,6 +126,10 @@ out: return error; } +/* + * Perform the select(nd, in, out, ex, tv) and mmap() system + * calls. + */ extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); struct sel_arg_struct { @@ -251,48 +269,11 @@ out: return error; } -/* - * Detect the old function calling standard - */ -static inline unsigned long old_calling_standard (struct pt_regs *regs) -{ - unsigned long instr, *pcv = (unsigned long *)(instruction_pointer(regs) - 8); - return (!get_user (instr, pcv) && instr == 0xe1a0300d); -} - /* Compatability functions - we used to pass 5 parameters as r0, r1, r2, *r3, *(r3+4) * We now use r0 - r4, and return an error if the old style calling standard is used. * Eventually these functions will disappear. */ -asmlinkage int -sys_compat_llseek (unsigned int fd, unsigned long offset_high, unsigned long offset_low, - loff_t *result, unsigned int origin, struct pt_regs *regs) -{ - extern int sys_llseek (unsigned int, unsigned long, unsigned long, loff_t *, unsigned int); - - if (old_calling_standard (regs)) { - printk (KERN_NOTICE "%s (%d): unsupported llseek call standard\n", - current->comm, current->pid); - return -EINVAL; - } - return sys_llseek (fd, offset_high, offset_low, result, origin); -} - -asmlinkage int -sys_compat_mount (char *devname, char *dirname, char *type, unsigned long flags, void *data, - struct pt_regs *regs) -{ - extern int sys_mount (char *, char *, char *, unsigned long, void *); - - if (old_calling_standard (regs)) { - printk (KERN_NOTICE "%s (%d): unsupported mount call standard\n", - current->comm, current->pid); - return -EINVAL; - } - return sys_mount (devname, dirname, type, flags, data); -} - -asmlinkage int sys_uname (struct old_utsname * name) +asmlinkage int sys_uname(struct old_utsname * name) { static int warned = 0; int err; @@ -331,15 +312,15 @@ asmlinkage int sys_olduname(struct oldold_utsname * name) down(&uts_sem); error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); - error -= __put_user(0,name->sysname+__OLD_UTS_LEN); - error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); - error -= __put_user(0,name->nodename+__OLD_UTS_LEN); - error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); - error -= __put_user(0,name->release+__OLD_UTS_LEN); - error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); - error -= __put_user(0,name->version+__OLD_UTS_LEN); - error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); - error -= __put_user(0,name->machine+__OLD_UTS_LEN); + error |= __put_user(0,name->sysname+__OLD_UTS_LEN); + error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); + error |= __put_user(0,name->nodename+__OLD_UTS_LEN); + error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); + error |= __put_user(0,name->release+__OLD_UTS_LEN); + error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); + error |= __put_user(0,name->version+__OLD_UTS_LEN); + error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); + error |= __put_user(0,name->machine+__OLD_UTS_LEN); up(&uts_sem); @@ -354,4 +335,3 @@ asmlinkage int sys_pause(void) schedule(); return -ERESTARTNOHAND; } - diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index c48c62108..67c2597e6 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -112,7 +112,7 @@ void do_gettimeofday(struct timeval *tv) /* * xtime is atomically updated in timer_bh. lost_ticks is - * nonzero if the tiemr bottom half hasnt executed yet. + * nonzero if the timer bottom half hasnt executed yet. */ if (lost_ticks) tv->tv_usec += USECS_PER_JIFFY; diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 26ecfa194..ac15651d3 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -187,10 +187,11 @@ void die(const char *str, struct pt_regs *regs, int err) dump_instr(instruction_pointer(regs), 0); } - spin_unlock_irq(&die_lock); + spin_unlock_irq(&die_lock); + do_exit(SIGSEGV); } -static void die_if_kernel(const char *str, struct pt_regs *regs, int err) +void die_if_kernel(const char *str, struct pt_regs *regs, int err) { if (user_mode(regs)) return; @@ -241,11 +242,10 @@ asmlinkage void do_unexp_fiq (struct pt_regs *regs) } /* - * bad_mode handles the impossible case in the vectors. - * If you see one of these, then it's extremely serious, - * and could mean you have buggy hardware. It never - * returns, and never tries to sync. We hope that we - * can dump out some state information... + * bad_mode handles the impossible case in the vectors. If you see one of + * these, then it's extremely serious, and could mean you have buggy hardware. + * It never returns, and never tries to sync. We hope that we can at least + * dump out some state information... */ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode) { @@ -255,7 +255,8 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode) handler[reason], processor_modes[proc_mode]); /* - * Dump out the vectors and stub routines + * Dump out the vectors and stub routines. Maybe a better solution + * would be to dump them out only if we detect that they are corrupted. */ printk(KERN_CRIT "Vectors:\n"); dump_mem(0, 0x40); @@ -279,6 +280,9 @@ asmlinkage void math_state_restore (void) current->used_math = 1; } +/* + * Handle some more esoteric system calls + */ asmlinkage int arm_syscall (int no, struct pt_regs *regs) { switch (no) { @@ -295,7 +299,7 @@ asmlinkage int arm_syscall (int no, struct pt_regs *regs) case 2: /* sys_cacheflush */ #ifdef CONFIG_CPU_32 - /* r0 = start, r1 = length, r2 = flags */ + /* r0 = start, r1 = end, r2 = flags */ cpu_flush_cache_area(regs->ARM_r0, regs->ARM_r1, 1); #endif break; @@ -308,7 +312,7 @@ asmlinkage int arm_syscall (int no, struct pt_regs *regs) if (no <= 0x7ff) return -ENOSYS; #ifdef CONFIG_DEBUG_USER - /* experiance shows that these seem to indicate that + /* experience shows that these seem to indicate that * something catastrophic has happened */ printk("[%d] %s: arm syscall %d\n", current->pid, current->comm, no); @@ -357,16 +361,19 @@ asmlinkage void arm_invalidptr(const char *function, int size) function, __builtin_return_address(0), size); } -#ifdef CONFIG_CPU_26 -asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs) +/* + * A data abort trap was taken, but the instruction was not an instruction + * which should cause the trap to be taken. Try to abort it. Note that + * the while(1) is there because we cannot currently handle returning from + * this function. + */ +asmlinkage void +baddataabort(int code, unsigned long instr, struct pt_regs *regs) { unsigned long phys, addr = instruction_pointer(regs); #ifdef CONFIG_DEBUG_ERRORS - printk("pid=%d\n", current->pid); - - show_regs(regs); - dump_instr(instruction_pointer(regs), 1); + dump_instr(addr, 1); { pgd_t *pgd; @@ -385,10 +392,10 @@ asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs printk ("\n"); } #endif - panic("unknown data abort code %d [pc=%08lx *pc=%08lx lr=%08lx sp=%08lx]", - code, regs->ARM_pc, instr, regs->ARM_lr, regs->ARM_sp); + force_sig(SIGILL, current); + die_if_kernel("unknown data abort code", regs, instr); + while (1); } -#endif void __bug(const char *file, int line, void *data) { @@ -425,6 +432,19 @@ asmlinkage void __div0(void) __backtrace(); } +void abort(void) +{ + void *lr = __builtin_return_address(0); + + printk(KERN_CRIT "abort() called from %p! (Please " + "report to rmk@arm.linux.org.uk)\n", lr); + + *(int *)0 = 0; + + /* if that doesn't kill us, halt */ + panic("Oops failed to kill thread"); +} + void __init trap_init(void) { extern void __trap_init(void); diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 9a22fe08f..5046a3377 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -5,8 +5,14 @@ # L_TARGET := lib.a -L_OBJS := backtrace.o bitops.o checksum.o delay.o \ - string.o system.o uaccess.o +L_OBJS := changebit.o csumipv6.o csumpartial.o csumpartialcopy.o \ + csumpartialcopyuser.o clearbit.o copy_page.o findbit.o \ + memchr.o memcpy.o memset.o memzero.o setbit.o strchr.o \ + strrchr.o testchangebit.o testclearbit.o testsetbit.o \ + uaccess.o + +O_TARGET := lib.o +O_OBJS := backtrace.o delay.o ifeq ($(PROCESSOR),armo) L_OBJS += uaccess-armo.o @@ -25,13 +31,21 @@ endif ifeq ($(MACHINE),ebsa110) L_OBJS += io-ebsa110.o else - LX_OBJS += io.o + OX_OBJS += io.o endif ifeq ($(MACHINE),footbridge) L_OBJS += io-footbridge.o endif +# +# SA1100 IO routines happen to be the +# same as the footbridge routines +# +ifeq ($(MACHINE),sa1100) + L_OBJS += io-footbridge.o +endif + include $(TOPDIR)/Rules.make .S.o: @@ -42,5 +56,3 @@ constants.h: getconsdata.o extractconstants.pl getconsdata.o: getconsdata.c $(CC) $(CFLAGS) -c getconsdata.c - -checksum.o string.o: constants.h diff --git a/arch/arm/lib/bitops.S b/arch/arm/lib/bitops.S deleted file mode 100644 index 4c1f4b0aa..000000000 --- a/arch/arm/lib/bitops.S +++ /dev/null @@ -1,152 +0,0 @@ -/* - * linux/arch/arm/lib/bitops.S - * - * Copyright (C) 1995, 1996 Russell King - */ - -#include <linux/linkage.h> -#include <asm/assembler.h> - .text - -@ Purpose : Function to set a bit -@ Prototype: int set_bit(int bit,int *addr) - -ENTRY(set_bit) - and r2, r0, #7 - mov r3, #1 - mov r3, r3, lsl r2 - SAVEIRQS(ip) - DISABLEIRQS(ip) - ldrb r2, [r1, r0, lsr #3] - orr r2, r2, r3 - strb r2, [r1, r0, lsr #3] - RESTOREIRQS(ip) - RETINSTR(mov,pc,lr) - -ENTRY(test_and_set_bit) - add r1, r1, r0, lsr #3 @ Get byte offset - and r3, r0, #7 @ Get bit offset - mov r0, #1 - SAVEIRQS(ip) - DISABLEIRQS(ip) - ldrb r2, [r1] - tst r2, r0, lsl r3 - orr r2, r2, r0, lsl r3 - moveq r0, #0 - strb r2, [r1] - RESTOREIRQS(ip) - RETINSTR(mov,pc,lr) - -@ Purpose : Function to clear a bit -@ Prototype: int clear_bit(int bit,int *addr) - -ENTRY(clear_bit) - and r2, r0, #7 - mov r3, #1 - mov r3, r3, lsl r2 - SAVEIRQS(ip) - DISABLEIRQS(ip) - ldrb r2, [r1, r0, lsr #3] - bic r2, r2, r3 - strb r2, [r1, r0, lsr #3] - RESTOREIRQS(ip) - RETINSTR(mov,pc,lr) - -ENTRY(test_and_clear_bit) - add r1, r1, r0, lsr #3 @ Get byte offset - and r3, r0, #7 @ Get bit offset - mov r0, #1 - SAVEIRQS(ip) - DISABLEIRQS(ip) - ldrb r2, [r1] - tst r2, r0, lsl r3 - bic r2, r2, r0, lsl r3 - moveq r0, #0 - strb r2, [r1] - RESTOREIRQS(ip) - RETINSTR(mov,pc,lr) - -/* Purpose : Function to change a bit - * Prototype: int change_bit(int bit,int *addr) - */ -ENTRY(change_bit) - and r2, r0, #7 - mov r3, #1 - mov r3, r3, lsl r2 - SAVEIRQS(ip) - DISABLEIRQS(ip) - ldrb r2, [r1, r0, lsr #3] - eor r2, r2, r3 - strb r2, [r1, r0, lsr #3] - RESTOREIRQS(ip) - RETINSTR(mov,pc,lr) - -ENTRY(test_and_change_bit) - add r1, r1, r0, lsr #3 - and r3, r0, #7 - mov r0, #1 - SAVEIRQS(ip) - DISABLEIRQS(ip) - ldrb r2, [r1] - tst r2, r0, lsl r3 - eor r2, r2, r0, lsl r3 - moveq r0, #0 - strb r2, [r1] - RESTOREIRQS(ip) - RETINSTR(mov,pc,lr) - -@ Purpose : Find a 'zero' bit -@ Prototype: int find_first_zero_bit(char *addr,int maxbit); - -ENTRY(find_first_zero_bit) - mov r2, #0 @ Initialise bit position -Lfindzbit1lp: ldrb r3, [r0, r2, lsr #3] @ Check byte, if 0xFF, then all bits set - teq r3, #0xFF - bne Lfoundzbit - add r2, r2, #8 - cmp r2, r1 @ Check to see if we have come to the end - bcc Lfindzbit1lp - add r0, r1, #1 @ Make sure that we flag an error - RETINSTR(mov,pc,lr) -Lfoundzbit: tst r3, #1 @ Check individual bits - moveq r0, r2 - RETINSTR(moveq,pc,lr) - tst r3, #2 - addeq r0, r2, #1 - RETINSTR(moveq,pc,lr) - tst r3, #4 - addeq r0, r2, #2 - RETINSTR(moveq,pc,lr) - tst r3, #8 - addeq r0, r2, #3 - RETINSTR(moveq,pc,lr) - tst r3, #16 - addeq r0, r2, #4 - RETINSTR(moveq,pc,lr) - tst r3, #32 - addeq r0, r2, #5 - RETINSTR(moveq,pc,lr) - tst r3, #64 - addeq r0, r2, #6 - RETINSTR(moveq,pc,lr) - add r0, r2, #7 - RETINSTR(mov,pc,lr) - -@ Purpose : Find next 'zero' bit -@ Prototype: int find_next_zero_bit(char *addr,int maxbit,int offset) - -ENTRY(find_next_zero_bit) - tst r2, #7 - beq Lfindzbit1lp @ If new byte, goto old routine - ldrb r3, [r0, r2, lsr#3] - orr r3, r3, #0xFF00 @ Set top bits so we wont get confused - stmfd sp!, {r4} - and r4, r2, #7 - mov r3, r3, lsr r4 @ Shift right by no. of bits - ldmfd sp!, {r4} - and r3, r3, #0xFF - teq r3, #0xFF - orreq r2, r2, #7 - addeq r2, r2, #1 - beq Lfindzbit1lp @ If all bits are set, goto old routine - b Lfoundzbit diff --git a/arch/arm/lib/changebit.S b/arch/arm/lib/changebit.S new file mode 100644 index 000000000..8005fd49a --- /dev/null +++ b/arch/arm/lib/changebit.S @@ -0,0 +1,26 @@ +/* + * linux/arch/arm/lib/changebit.S + * + * Copyright (C) 1995-1996 Russell King + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + .text + +/* Purpose : Function to change a bit + * Prototype: int change_bit(int bit,int *addr) + */ +ENTRY(change_bit) + and r2, r0, #7 + mov r3, #1 + mov r3, r3, lsl r2 + SAVEIRQS(ip) + DISABLEIRQS(ip) + ldrb r2, [r1, r0, lsr #3] + eor r2, r2, r3 + strb r2, [r1, r0, lsr #3] + RESTOREIRQS(ip) + RETINSTR(mov,pc,lr) + + diff --git a/arch/arm/lib/clearbit.S b/arch/arm/lib/clearbit.S new file mode 100644 index 000000000..d936ab549 --- /dev/null +++ b/arch/arm/lib/clearbit.S @@ -0,0 +1,26 @@ +/* + * linux/arch/arm/lib/clearbit.S + * + * Copyright (C) 1995-1996 Russell King + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + .text + +@ Purpose : Function to clear a bit +@ Prototype: int clear_bit(int bit,int *addr) + +ENTRY(clear_bit) + and r2, r0, #7 + mov r3, #1 + mov r3, r3, lsl r2 + SAVEIRQS(ip) + DISABLEIRQS(ip) + ldrb r2, [r1, r0, lsr #3] + bic r2, r2, r3 + strb r2, [r1, r0, lsr #3] + RESTOREIRQS(ip) + RETINSTR(mov,pc,lr) + + diff --git a/arch/arm/lib/copy_page.S b/arch/arm/lib/copy_page.S new file mode 100644 index 000000000..16c43268a --- /dev/null +++ b/arch/arm/lib/copy_page.S @@ -0,0 +1,35 @@ +/* + * linux/arch/arm/lib/copypage.S + * + * Copyright (C) 1995-1999 Russell King + * + * ASM optimised string functions + * + */ +#include <linux/linkage.h> +#include <asm/assembler.h> +#include "constants.h" + + .text +/* + * StrongARM optimised copy_page routine + * now 1.72bytes/cycle, was 1.60 bytes/cycle + * (50MHz bus -> 86MB/s) + */ + +ENTRY(copy_page) + stmfd sp!, {r4, lr} @ 2 + mov r2, #PAGE_SZ/64 @ 1 +1: ldmia r1!, {r3, r4, ip, lr} @ 4 + subs r2, r2, #1 @ 1 + stmia r0!, {r3, r4, ip, lr} @ 4 + ldmia r1!, {r3, r4, ip, lr} @ 4+1 + stmia r0!, {r3, r4, ip, lr} @ 4 + ldmia r1!, {r3, r4, ip, lr} @ 4+1 + stmia r0!, {r3, r4, ip, lr} @ 4 + ldmia r1!, {r3, r4, ip, lr} @ 4+1 + stmia r0!, {r3, r4, ip, lr} @ 4 + bne 1b @ 1 + LOADREGS(fd, sp!, {r4, pc}) @ 3 + + diff --git a/arch/arm/lib/csumipv6.S b/arch/arm/lib/csumipv6.S new file mode 100644 index 000000000..76e7d26d8 --- /dev/null +++ b/arch/arm/lib/csumipv6.S @@ -0,0 +1,28 @@ +/* + * linux/arch/arm/lib/csumipv6.S + * + * Copyright (C) 1995-1998 Russell King + */ +#include <linux/linkage.h> +#include <asm/assembler.h> + + .text + +ENTRY(__csum_ipv6_magic) + str lr, [sp, #-4]! + adds ip, r2, r3 + ldmia r1, {r1 - r3, lr} + adcs ip, ip, r1 + adcs ip, ip, r2 + adcs ip, ip, r3 + adcs ip, ip, lr + ldmia r0, {r0 - r3} + adcs r0, ip, r0 + adcs r0, r0, r1 + adcs r0, r0, r2 + ldr r2, [sp, #4] + adcs r0, r0, r3 + adcs r0, r0, r2 + adcs r0, r0, #0 + LOADREGS(fd, sp!, {pc}) + diff --git a/arch/arm/lib/csumpartial.S b/arch/arm/lib/csumpartial.S new file mode 100644 index 000000000..2406dfb38 --- /dev/null +++ b/arch/arm/lib/csumpartial.S @@ -0,0 +1,64 @@ +/* + * linux/arch/arm/lib/csumpartial.S + * + * Copyright (C) 1995-1998 Russell King + */ +#include <linux/linkage.h> +#include <asm/assembler.h> + + .text + +/* Function: __u32 csum_partial(const char *src, int len, __u32) + * Params : r0 = buffer, r1 = len, r2 = checksum + * Returns : r0 = new checksum + */ + +ENTRY(csum_partial) + tst r0, #2 + beq 1f + subs r1, r1, #2 + addmi r1, r1, #2 + bmi 3f + bic r0, r0, #3 + ldr r3, [r0], #4 + adds r2, r2, r3, lsr #16 + adcs r2, r2, #0 +1: adds r2, r2, #0 + bics ip, r1, #31 + beq 3f + stmfd sp!, {r4 - r6} +2: ldmia r0!, {r3 - r6} + adcs r2, r2, r3 + adcs r2, r2, r4 + adcs r2, r2, r5 + adcs r2, r2, r6 + ldmia r0!, {r3 - r6} + adcs r2, r2, r3 + adcs r2, r2, r4 + adcs r2, r2, r5 + adcs r2, r2, r6 + sub ip, ip, #32 + teq ip, #0 + bne 2b + adcs r2, r2, #0 + ldmfd sp!, {r4 - r6} +3: ands ip, r1, #0x1c + beq 5f +4: ldr r3, [r0], #4 + sub ip, ip, #4 + adcs r2, r2, r3 + teq ip, #0 + bne 4b + adcs r2, r2, #0 +5: ands ip, r1, #3 + moveq r0, r2 + RETINSTR(moveq,pc,lr) + mov ip, ip, lsl #3 + ldr r3, [r0] + rsb ip, ip, #32 + mov r3, r3, lsl ip + adds r2, r2, r3, lsr ip + adc r0, r2, #0 + RETINSTR(mov,pc,lr) + + diff --git a/arch/arm/lib/csumpartialcopy.S b/arch/arm/lib/csumpartialcopy.S new file mode 100644 index 000000000..7289619da --- /dev/null +++ b/arch/arm/lib/csumpartialcopy.S @@ -0,0 +1,257 @@ +/* + * linux/arch/arm/lib/csumpartialcopy.S + * + * Copyright (C) 1995-1998 Russell King + */ +#include <linux/linkage.h> +#include <asm/assembler.h> + + .text + +/* Function: __u32 csum_partial_copy_nocheck(const char *src, char *dst, int len, __u32 sum) + * Params : r0 = src, r1 = dst, r2 = len, r3 = checksum + * Returns : r0 = new checksum + */ +ENTRY(csum_partial_copy_nocheck) + mov ip, sp + stmfd sp!, {r4 - r8, fp, ip, lr, pc} + sub fp, ip, #4 + cmp r2, #4 + blt Ltoo_small + tst r1, #2 @ Test destination alignment + beq Ldst_aligned + ldrb ip, [r0], #1 + ldrb r8, [r0], #1 + subs r2, r2, #2 @ We do not know if SRC is aligned... + orr ip, ip, r8, lsl #8 + adds r3, r3, ip + adcs r3, r3, #0 + strb ip, [r1], #1 + mov ip, ip, lsr #8 + strb ip, [r1], #1 @ Destination now aligned +Ldst_aligned: tst r0, #3 + bne Lsrc_not_aligned + adds r3, r3, #0 + bics ip, r2, #15 @ Routine for src & dst aligned + beq 3f +1: ldmia r0!, {r4, r5, r6, r7} + stmia r1!, {r4, r5, r6, r7} + adcs r3, r3, r4 + adcs r3, r3, r5 + adcs r3, r3, r6 + adcs r3, r3, r7 + sub ip, ip, #16 + teq ip, #0 + bne 1b +3: ands ip, r2, #12 + beq 5f + tst ip, #8 + beq 4f + ldmia r0!, {r4, r5} + stmia r1!, {r4, r5} + adcs r3, r3, r4 + adcs r3, r3, r5 + tst ip, #4 + beq 5f +4: ldr r4, [r0], #4 + str r4, [r1], #4 + adcs r3, r3, r4 +5: ands r2, r2, #3 + adceq r0, r3, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + ldr r4, [r0], #4 + tst r2, #2 + beq Lexit_r4 + adcs r3, r3, r4, lsl #16 + strb r4, [r1], #1 + mov r4, r4, lsr #8 + strb r4, [r1], #1 + mov r4, r4, lsr #8 + b Lexit_r4 + +Ltoo_small: teq r2, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + cmp r2, #2 + blt Ltoo_small1 + ldrb ip, [r0], #1 + ldrb r8, [r0], #1 + orr ip, ip, r8, lsl #8 + adds r3, r3, ip + strb ip, [r1], #1 + strb r8, [r1], #1 + tst r2, #1 +Ltoo_small1: ldrneb r4, [r0], #1 +Lexit_r4: tst r2, #1 + strneb r4, [r1], #1 + andne r4, r4, #255 + adcnes r3, r3, r4 + adcs r0, r3, #0 + LOADREGS(ea,fp,{r4 - r8, fp, sp, pc}) + +Lsrc_not_aligned: + cmp r2, #4 + blt Ltoo_small + and ip, r0, #3 + bic r0, r0, #3 + ldr r4, [r0], #4 + cmp ip, #2 + beq Lsrc2_aligned + bhi Lsrc3_aligned + mov r4, r4, lsr #8 + adds r3, r3, #0 + bics ip, r2, #15 + beq 2f +1: ldmia r0!, {r5, r6, r7, r8} + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r6, lsl #24 + mov r6, r6, lsr #8 + orr r6, r6, r7, lsl #24 + mov r7, r7, lsr #8 + orr r7, r7, r8, lsl #24 + stmia r1!, {r4, r5, r6, r7} + adcs r3, r3, r4 + adcs r3, r3, r5 + adcs r3, r3, r6 + adcs r3, r3, r7 + mov r4, r8, lsr #8 + sub ip, ip, #16 + teq ip, #0 + bne 1b +2: ands ip, r2, #12 + beq 4f + tst ip, #8 + beq 3f + ldmia r0!, {r5, r6} + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r6, lsl #24 + stmia r1!, {r4, r5} + adcs r3, r3, r4 + adcs r3, r3, r5 + mov r4, r6, lsr #8 + tst ip, #4 + beq 4f +3: ldr r5, [r0], #4 + orr r4, r4, r5, lsl #24 + str r4, [r1], #4 + adcs r3, r3, r4 + mov r4, r5, lsr #8 +4: ands r2, r2, #3 + adceq r0, r3, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + tst r2, #2 + beq Lexit_r4 + adcs r3, r3, r4, lsl #16 + strb r4, [r1], #1 + mov r4, r4, lsr #8 + strb r4, [r1], #1 + mov r4, r4, lsr #8 + b Lexit_r4 + +Lsrc2_aligned: mov r4, r4, lsr #16 + adds r3, r3, #0 + bics ip, r2, #15 + beq 2f +1: ldmia r0!, {r5, r6, r7, r8} + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r6, lsl #16 + mov r6, r6, lsr #16 + orr r6, r6, r7, lsl #16 + mov r7, r7, lsr #16 + orr r7, r7, r8, lsl #16 + stmia r1!, {r4, r5, r6, r7} + adcs r3, r3, r4 + adcs r3, r3, r5 + adcs r3, r3, r6 + adcs r3, r3, r7 + mov r4, r8, lsr #16 + sub ip, ip, #16 + teq ip, #0 + bne 1b +2: ands ip, r2, #12 + beq 4f + tst ip, #8 + beq 3f + ldmia r0!, {r5, r6} + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r6, lsl #16 + stmia r1!, {r4, r5} + adcs r3, r3, r4 + adcs r3, r3, r5 + mov r4, r6, lsr #16 + tst ip, #4 + beq 4f +3: ldr r5, [r0], #4 + orr r4, r4, r5, lsl #16 + str r4, [r1], #4 + adcs r3, r3, r4 + mov r4, r5, lsr #16 +4: ands r2, r2, #3 + adceq r0, r3, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + tst r2, #2 + beq Lexit_r4 + adcs r3, r3, r4, lsl #16 + strb r4, [r1], #1 + mov r4, r4, lsr #8 + strb r4, [r1], #1 + ldrb r4, [r0], #1 + b Lexit_r4 + +Lsrc3_aligned: mov r4, r4, lsr #24 + adds r3, r3, #0 + bics ip, r2, #15 + beq 2f +1: ldmia r0!, {r5, r6, r7, r8} + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r6, lsl #8 + mov r6, r6, lsr #24 + orr r6, r6, r7, lsl #8 + mov r7, r7, lsr #24 + orr r7, r7, r8, lsl #8 + stmia r1!, {r4, r5, r6, r7} + adcs r3, r3, r4 + adcs r3, r3, r5 + adcs r3, r3, r6 + adcs r3, r3, r7 + mov r4, r8, lsr #24 + sub ip, ip, #16 + teq ip, #0 + bne 1b +2: ands ip, r2, #12 + beq 4f + tst ip, #8 + beq 3f + ldmia r0!, {r5, r6} + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r6, lsl #8 + stmia r1!, {r4, r5} + adcs r3, r3, r4 + adcs r3, r3, r5 + mov r4, r6, lsr #24 + tst ip, #4 + beq 4f +3: ldr r5, [r0], #4 + orr r4, r4, r5, lsl #8 + str r4, [r1], #4 + adcs r3, r3, r4 + mov r4, r5, lsr #24 +4: ands r2, r2, #3 + adceq r0, r3, #0 + LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) + tst r2, #2 + beq Lexit_r4 + adcs r3, r3, r4, lsl #16 + strb r4, [r1], #1 + ldr r4, [r0], #4 + strb r4, [r1], #1 + adcs r3, r3, r4, lsl #24 + mov r4, r4, lsr #8 + b Lexit_r4 + + diff --git a/arch/arm/lib/checksum.S b/arch/arm/lib/csumpartialcopyuser.S index ae78b657a..f698c0d26 100644 --- a/arch/arm/lib/checksum.S +++ b/arch/arm/lib/csumpartialcopyuser.S @@ -1,7 +1,7 @@ /* - * linux/arch/arm/lib/checksum.S + * linux/arch/arm/lib/csumpartialcopyuser.S * - * Copyright (C) 1995, 1996, 1997, 1998 Russell King + * Copyright (C) 1995-1998 Russell King */ #include <linux/config.h> #include <linux/linkage.h> @@ -11,59 +11,6 @@ .text -/* Function: __u32 csum_partial(const char *src, int len, __u32) - * Params : r0 = buffer, r1 = len, r2 = checksum - * Returns : r0 = new checksum - */ - -ENTRY(csum_partial) - tst r0, #2 - beq 1f - subs r1, r1, #2 - addmi r1, r1, #2 - bmi 3f - bic r0, r0, #3 - ldr r3, [r0], #4 - adds r2, r2, r3, lsr #16 - adcs r2, r2, #0 -1: adds r2, r2, #0 - bics ip, r1, #31 - beq 3f - stmfd sp!, {r4 - r6} -2: ldmia r0!, {r3 - r6} - adcs r2, r2, r3 - adcs r2, r2, r4 - adcs r2, r2, r5 - adcs r2, r2, r6 - ldmia r0!, {r3 - r6} - adcs r2, r2, r3 - adcs r2, r2, r4 - adcs r2, r2, r5 - adcs r2, r2, r6 - sub ip, ip, #32 - teq ip, #0 - bne 2b - adcs r2, r2, #0 - ldmfd sp!, {r4 - r6} -3: ands ip, r1, #0x1c - beq 5f -4: ldr r3, [r0], #4 - adcs r2, r2, r3 - sub ip, ip, #4 - teq ip, #0 - bne 4b - adcs r2, r2, #0 -5: ands ip, r1, #3 - moveq r0, r2 - RETINSTR(moveq,pc,lr) - mov ip, ip, lsl #3 - rsb ip, ip, #32 - ldr r3, [r0] - mov r3, r3, lsl ip - adds r2, r2, r3, lsr ip - adc r0, r2, #0 - RETINSTR(mov,pc,lr) - /* Function: __u32 csum_partial_copy_from_user (const char *src, char *dst, int len, __u32 sum, int *err_ptr) * Params : r0 = src, r1 = dst, r2 = len, r3 = sum, [sp, #0] = &err * Returns : r0 = checksum, [[sp, #0], #0] = 0 or -EFAULT @@ -209,8 +156,8 @@ ENTRY(csum_partial_copy_from_user) blt .too_small_user tst r1, #2 @ Test destination alignment beq .dst_aligned_user - subs r2, r2, #2 @ We do not know if SRC is aligned... load2b ip, r8 + subs r2, r2, #2 @ We do not know if SRC is aligned... orr ip, ip, r8, lsl #8 adds r3, r3, ip adcs r3, r3, #0 @@ -393,6 +340,9 @@ ENTRY(csum_partial_copy_from_user) strb r4, [r1], #1 mov r4, r4, lsr #8 strb r4, [r1], #1 + tst r2, #1 + adceq r0, r3, #0 + load_regs eqea load1b r4 b .exit @@ -467,268 +417,3 @@ ENTRY(csum_partial_copy_from_user) #if defined(CONFIG_CPU_32) .previous #endif - -/* Function: __u32 csum_partial_copy (const char *src, char *dst, int len, __u32 sum) - * Params : r0 = src, r1 = dst, r2 = len, r3 = checksum - * Returns : r0 = new checksum - */ -ENTRY(csum_partial_copy_nocheck) -ENTRY(csum_partial_copy) - mov ip, sp - stmfd sp!, {r4 - r8, fp, ip, lr, pc} - sub fp, ip, #4 - cmp r2, #4 - blt Ltoo_small - tst r1, #2 @ Test destination alignment - beq Ldst_aligned - subs r2, r2, #2 @ We do not know if SRC is aligned... - ldrb ip, [r0], #1 - ldrb r8, [r0], #1 - orr ip, ip, r8, lsl #8 - adds r3, r3, ip - adcs r3, r3, #0 - strb ip, [r1], #1 - mov ip, ip, lsr #8 - strb ip, [r1], #1 @ Destination now aligned -Ldst_aligned: tst r0, #3 - bne Lsrc_not_aligned - adds r3, r3, #0 - bics ip, r2, #15 @ Routine for src & dst aligned - beq 3f -1: ldmia r0!, {r4, r5, r6, r7} - stmia r1!, {r4, r5, r6, r7} - adcs r3, r3, r4 - adcs r3, r3, r5 - adcs r3, r3, r6 - adcs r3, r3, r7 - sub ip, ip, #16 - teq ip, #0 - bne 1b -3: ands ip, r2, #12 - beq 5f - tst ip, #8 - beq 4f - ldmia r0!, {r4, r5} - stmia r1!, {r4, r5} - adcs r3, r3, r4 - adcs r3, r3, r5 - tst ip, #4 - beq 5f -4: ldr r4, [r0], #4 - str r4, [r1], #4 - adcs r3, r3, r4 -5: ands r2, r2, #3 - adceq r0, r3, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) - ldr r4, [r0], #4 - tst r2, #2 - beq Lexit_r4 - adcs r3, r3, r4, lsl #16 - strb r4, [r1], #1 - mov r4, r4, lsr #8 - strb r4, [r1], #1 - mov r4, r4, lsr #8 - b Lexit_r4 - -Ltoo_small: teq r2, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) - cmp r2, #2 - blt Ltoo_small1 - ldrb ip, [r0], #1 - ldrb r8, [r0], #1 - orr ip, ip, r8, lsl #8 - adds r3, r3, ip - strb ip, [r1], #1 - strb r8, [r1], #1 - tst r2, #1 -Ltoo_small1: ldrneb r4, [r0], #1 -Lexit_r4: tst r2, #1 - strneb r4, [r1], #1 - andne r4, r4, #255 - adcnes r3, r3, r4 - adcs r0, r3, #0 - LOADREGS(ea,fp,{r4 - r8, fp, sp, pc}) - -Lsrc_not_aligned: - cmp r2, #4 - blt Ltoo_small - and ip, r0, #3 - bic r0, r0, #3 - ldr r4, [r0], #4 - cmp ip, #2 - beq Lsrc2_aligned - bhi Lsrc3_aligned - mov r4, r4, lsr #8 - adds r3, r3, #0 - bics ip, r2, #15 - beq 2f -1: ldmia r0!, {r5, r6, r7, r8} - orr r4, r4, r5, lsl #24 - mov r5, r5, lsr #8 - orr r5, r5, r6, lsl #24 - mov r6, r6, lsr #8 - orr r6, r6, r7, lsl #24 - mov r7, r7, lsr #8 - orr r7, r7, r8, lsl #24 - stmia r1!, {r4, r5, r6, r7} - adcs r3, r3, r4 - adcs r3, r3, r5 - adcs r3, r3, r6 - adcs r3, r3, r7 - mov r4, r8, lsr #8 - sub ip, ip, #16 - teq ip, #0 - bne 1b -2: ands ip, r2, #12 - beq 4f - tst ip, #8 - beq 3f - ldmia r0!, {r5, r6} - orr r4, r4, r5, lsl #24 - mov r5, r5, lsr #8 - orr r5, r5, r6, lsl #24 - stmia r1!, {r4, r5} - adcs r3, r3, r4 - adcs r3, r3, r5 - mov r4, r6, lsr #8 - tst ip, #4 - beq 4f -3: ldr r5, [r0], #4 - orr r4, r4, r5, lsl #24 - str r4, [r1], #4 - adcs r3, r3, r4 - mov r4, r5, lsr #8 -4: ands r2, r2, #3 - adceq r0, r3, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) - tst r2, #2 - beq Lexit_r4 - adcs r3, r3, r4, lsl #16 - strb r4, [r1], #1 - mov r4, r4, lsr #8 - strb r4, [r1], #1 - mov r4, r4, lsr #8 - b Lexit_r4 - -Lsrc2_aligned: mov r4, r4, lsr #16 - adds r3, r3, #0 - bics ip, r2, #15 - beq 2f -1: ldmia r0!, {r5, r6, r7, r8} - orr r4, r4, r5, lsl #16 - mov r5, r5, lsr #16 - orr r5, r5, r6, lsl #16 - mov r6, r6, lsr #16 - orr r6, r6, r7, lsl #16 - mov r7, r7, lsr #16 - orr r7, r7, r8, lsl #16 - stmia r1!, {r4, r5, r6, r7} - adcs r3, r3, r4 - adcs r3, r3, r5 - adcs r3, r3, r6 - adcs r3, r3, r7 - mov r4, r8, lsr #16 - sub ip, ip, #16 - teq ip, #0 - bne 1b -2: ands ip, r2, #12 - beq 4f - tst ip, #8 - beq 3f - ldmia r0!, {r5, r6} - orr r4, r4, r5, lsl #16 - mov r5, r5, lsr #16 - orr r5, r5, r6, lsl #16 - stmia r1!, {r4, r5} - adcs r3, r3, r4 - adcs r3, r3, r5 - mov r4, r6, lsr #16 - tst ip, #4 - beq 4f -3: ldr r5, [r0], #4 - orr r4, r4, r5, lsl #16 - str r4, [r1], #4 - adcs r3, r3, r4 - mov r4, r5, lsr #16 -4: ands r2, r2, #3 - adceq r0, r3, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) - tst r2, #2 - beq Lexit_r4 - adcs r3, r3, r4, lsl #16 - strb r4, [r1], #1 - mov r4, r4, lsr #8 - strb r4, [r1], #1 - ldrb r4, [r0], #1 - b Lexit_r4 - -Lsrc3_aligned: mov r4, r4, lsr #24 - adds r3, r3, #0 - bics ip, r2, #15 - beq 2f -1: ldmia r0!, {r5, r6, r7, r8} - orr r4, r4, r5, lsl #8 - mov r5, r5, lsr #24 - orr r5, r5, r6, lsl #8 - mov r6, r6, lsr #24 - orr r6, r6, r7, lsl #8 - mov r7, r7, lsr #24 - orr r7, r7, r8, lsl #8 - stmia r1!, {r4, r5, r6, r7} - adcs r3, r3, r4 - adcs r3, r3, r5 - adcs r3, r3, r6 - adcs r3, r3, r7 - mov r4, r8, lsr #24 - sub ip, ip, #16 - teq ip, #0 - bne 1b -2: ands ip, r2, #12 - beq 4f - tst ip, #8 - beq 3f - ldmia r0!, {r5, r6} - orr r4, r4, r5, lsl #8 - mov r5, r5, lsr #24 - orr r5, r5, r6, lsl #8 - stmia r1!, {r4, r5} - adcs r3, r3, r4 - adcs r3, r3, r5 - mov r4, r6, lsr #24 - tst ip, #4 - beq 4f -3: ldr r5, [r0], #4 - orr r4, r4, r5, lsl #8 - str r4, [r1], #4 - adcs r3, r3, r4 - mov r4, r5, lsr #24 -4: ands r2, r2, #3 - adceq r0, r3, #0 - LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc}) - tst r2, #2 - beq Lexit_r4 - adcs r3, r3, r4, lsl #16 - strb r4, [r1], #1 - ldr r4, [r0], #4 - strb r4, [r1], #1 - adcs r3, r3, r4, lsl #24 - mov r4, r4, lsr #8 - b Lexit_r4 - -ENTRY(__csum_ipv6_magic) - stmfd sp!, {lr} - adds ip, r2, r3 - ldmia r1, {r1 - r3, lr} - adcs ip, ip, r1 - adcs ip, ip, r2 - adcs ip, ip, r3 - adcs ip, ip, lr - ldmia r0, {r0 - r3} - adcs r0, ip, r0 - adcs r0, r0, r1 - adcs r0, r0, r2 - adcs r0, r0, r3 - ldr r3, [sp, #4] - adcs r0, r0, r3 - adcs r0, r0, #0 - LOADREGS(fd, sp!, {pc}) diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S new file mode 100644 index 000000000..e1651904f --- /dev/null +++ b/arch/arm/lib/findbit.S @@ -0,0 +1,65 @@ +/* + * linux/arch/arm/lib/bitops.S + * + * Copyright (C) 1995-1996 Russell King + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + .text + +@ Purpose : Find a 'zero' bit +@ Prototype: int find_first_zero_bit(char *addr,int maxbit); + +ENTRY(find_first_zero_bit) + mov r2, #0 @ Initialise bit position +Lfindzbit1lp: ldrb r3, [r0, r2, lsr #3] @ Check byte, if 0xFF, then all bits set + teq r3, #0xFF + bne Lfoundzbit + add r2, r2, #8 + cmp r2, r1 @ Check to see if we have come to the end + bcc Lfindzbit1lp + add r0, r1, #1 @ Make sure that we flag an error + RETINSTR(mov,pc,lr) +Lfoundzbit: tst r3, #1 @ Check individual bits + moveq r0, r2 + RETINSTR(moveq,pc,lr) + tst r3, #2 + addeq r0, r2, #1 + RETINSTR(moveq,pc,lr) + tst r3, #4 + addeq r0, r2, #2 + RETINSTR(moveq,pc,lr) + tst r3, #8 + addeq r0, r2, #3 + RETINSTR(moveq,pc,lr) + tst r3, #16 + addeq r0, r2, #4 + RETINSTR(moveq,pc,lr) + tst r3, #32 + addeq r0, r2, #5 + RETINSTR(moveq,pc,lr) + tst r3, #64 + addeq r0, r2, #6 + RETINSTR(moveq,pc,lr) + add r0, r2, #7 + RETINSTR(mov,pc,lr) + +@ Purpose : Find next 'zero' bit +@ Prototype: int find_next_zero_bit(char *addr,int maxbit,int offset) + +ENTRY(find_next_zero_bit) + tst r2, #7 + beq Lfindzbit1lp @ If new byte, goto old routine + ldrb r3, [r0, r2, lsr#3] + orr r3, r3, #0xFF00 @ Set top bits so we wont get confused + stmfd sp!, {r4} + and r4, r2, #7 + mov r3, r3, lsr r4 @ Shift right by no. of bits + ldmfd sp!, {r4} + and r3, r3, #0xFF + teq r3, #0xFF + orreq r2, r2, #7 + addeq r2, r2, #1 + beq Lfindzbit1lp @ If all bits are set, goto old routine + b Lfoundzbit diff --git a/arch/arm/lib/getconsdata.c b/arch/arm/lib/getconsdata.c index 5b46baad0..aaa7a7ad2 100644 --- a/arch/arm/lib/getconsdata.c +++ b/arch/arm/lib/getconsdata.c @@ -10,6 +10,16 @@ #include <asm/pgtable.h> #include <asm/uaccess.h> +/* + * Make sure that the compiler and target are compatible + */ +#if (defined(__APCS_32__) && defined(CONFIG_CPU_26)) +#error Your compiler targets APCS-32 but this kernel requires APCS-26. +#endif +#if (defined(__APCS_26__) && defined(CONFIG_CPU_32)) +#error Your compiler targets APCS-26 but this kernel requires APCS-32. +#endif + #undef PAGE_READONLY #define OFF_TSK(n) (unsigned long)&(((struct task_struct *)0)->n) diff --git a/arch/arm/lib/io-footbridge.S b/arch/arm/lib/io-footbridge.S index 0734c6042..98f751258 100644 --- a/arch/arm/lib/io-footbridge.S +++ b/arch/arm/lib/io-footbridge.S @@ -6,7 +6,9 @@ .macro ioaddr, rd,rn add \rd, \rn, #pcio_high + .if pcio_low add \rd, \rd, #pcio_low + .endif .endm ENTRY(insl) diff --git a/arch/arm/lib/memchr.S b/arch/arm/lib/memchr.S new file mode 100644 index 000000000..d52abe57f --- /dev/null +++ b/arch/arm/lib/memchr.S @@ -0,0 +1,24 @@ +/* + * linux/arch/arm/lib/memchr.S + * + * Copyright (C) 1995-1999 Russell King + * + * ASM optimised string functions + * + */ +#include <linux/linkage.h> +#include <asm/assembler.h> +#include "constants.h" + + .text +ENTRY(memchr) + str lr, [sp, #-4]! +1: ldrb r3, [r0], #1 + teq r3, r1 + beq 2f + subs r2, r2, #1 + bpl 1b +2: movne r0, #0 + subeq r0, r0, #1 + LOADREGS(fd, sp!, {pc}) + diff --git a/arch/arm/lib/string.S b/arch/arm/lib/memcpy.S index ff809fd51..ae5307d4b 100644 --- a/arch/arm/lib/string.S +++ b/arch/arm/lib/memcpy.S @@ -1,5 +1,5 @@ /* - * linux/arch/arm/lib/string.S + * linux/arch/arm/lib/memcpy.S * * Copyright (C) 1995-1999 Russell King * @@ -12,207 +12,6 @@ .text -/* - * Prototype: void memzero(void *d, size_t n) - */ -1: @ 4 <= r1 - cmp ip, #2 @ 1 - strltb r2, [r0], #1 @ 1 - strleb r2, [r0], #1 @ 1 - strb r2, [r0], #1 @ 1 - rsb ip, ip, #4 @ 1 - sub r1, r1, ip @ 1 - cmp r1, #3 @ 1 - bgt 2f @ 1 @ +8 - b 4f @ 1 @ +9 - - .align 5 - -ENTRY(__memzero) - mov r2, #0 @ 1 - cmp r1, #4 @ 1 - blt 4f @ 1 @ = 3 - - @ r1 >= 4 - - ands ip, r0, #3 @ 1 - bne 1b @ 1 @ = 5 - -2: @ r1 >= 4 && (r0 & 3) = 0 @ = 5 or 11 - - str lr, [sp, #-4]! @ 1 - mov r3, #0 @ 1 - mov ip, #0 @ 1 - mov lr, #0 @ 1 - - @ 4 <= r1 <= 32 @ = 9 or 15 - -3: subs r1, r1, #32 @ 1 - stmgeia r0!, {r2, r3, ip, lr} @ 4 - stmgeia r0!, {r2, r3, ip, lr} @ 4 - bgt 3b @ 1 - LOADREGS(eqfd, sp!, {pc}) @ 1/2 - - @ -28 <= r1 <= -1 - - cmp r1, #-16 @ 1 - stmgeia r0!, {r2, r3, ip, lr} @ 4 - ldr lr, [sp], #4 @ 1 - addlts r1, r1, #16 @ 1 - RETINSTR(moveq,pc,lr) @ 1 - - @ -12 <= r1 <= -1 - - cmp r1, #-8 @ 1 - stmgeia r0!, {r2, r3} @ 2 - addlts r1, r1, #8 @ 1 - RETINSTR(moveq,pc,lr) @ 1 - - @ -4 <= r1 <= -1 - - cmp r1, #-4 @ 1 - strge r2, [r0], #4 @ 1 - adds r1, r1, #4 @ 1 - RETINSTR(moveq,pc,lr) @ 1 - -4: @ 1 <= r1 <= 3 - cmp r1, #2 @ 1 - strgtb r2, [r0], #1 @ 1 - strgeb r2, [r0], #1 @ 1 - strb r2, [r0], #1 @ 1 - RETINSTR(mov,pc,lr) @ 1 - -/* - * StrongARM optimised copy_page routine - * now 1.72bytes/cycle, was 1.60 bytes/cycle - * (50MHz bus -> 86MB/s) - */ - -ENTRY(copy_page) - stmfd sp!, {r4, lr} @ 2 - mov r2, #PAGE_SZ/64 @ 1 -1: ldmia r1!, {r3, r4, ip, lr} @ 4 - subs r2, r2, #1 @ 1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4+1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4+1 - stmia r0!, {r3, r4, ip, lr} @ 4 - ldmia r1!, {r3, r4, ip, lr} @ 4+1 - stmia r0!, {r3, r4, ip, lr} @ 4 - bne 1b @ 1 - LOADREGS(fd, sp!, {r4, pc}) @ 3 - - .align 5 -ENTRY(memset) /* needed for some versions of gcc */ -ENTRY(__memset) - mov r3, r0 - cmp r2, #16 - blt 6f - ands ip, r3, #3 - beq 1f - cmp ip, #2 - strltb r1, [r3], #1 @ Align destination - strleb r1, [r3], #1 - strb r1, [r3], #1 - rsb ip, ip, #4 - sub r2, r2, ip -1: orr r1, r1, r1, lsl #8 - orr r1, r1, r1, lsl #16 - cmp r2, #256 - blt 4f - stmfd sp!, {r4, r5, lr} - mov r4, r1 - mov r5, r1 - mov lr, r1 - mov ip, r2, lsr #6 - sub r2, r2, ip, lsl #6 -2: stmia r3!, {r1, r4, r5, lr} @ 64 bytes at a time. - stmia r3!, {r1, r4, r5, lr} - stmia r3!, {r1, r4, r5, lr} - stmia r3!, {r1, r4, r5, lr} - subs ip, ip, #1 - bne 2b - teq r2, #0 - LOADREGS(eqfd, sp!, {r4, r5, pc}) @ Now <64 bytes to go. - tst r2, #32 - stmneia r3!, {r1, r4, r5, lr} - stmneia r3!, {r1, r4, r5, lr} - tst r2, #16 - stmneia r3!, {r1, r4, r5, lr} - ldmia sp!, {r4, r5} -3: tst r2, #8 - stmneia r3!, {r1, lr} - tst r2, #4 - strne r1, [r3], #4 - tst r2, #2 - strneb r1, [r3], #1 - strneb r1, [r3], #1 - tst r2, #1 - strneb r1, [r3], #1 - LOADREGS(fd, sp!, {pc}) - -4: movs ip, r2, lsr #3 - beq 3b - sub r2, r2, ip, lsl #3 - stmfd sp!, {lr} - mov lr, r1 - subs ip, ip, #4 -5: stmgeia r3!, {r1, lr} - stmgeia r3!, {r1, lr} - stmgeia r3!, {r1, lr} - stmgeia r3!, {r1, lr} - subges ip, ip, #4 - bge 5b - tst ip, #2 - stmneia r3!, {r1, lr} - stmneia r3!, {r1, lr} - tst ip, #1 - stmneia r3!, {r1, lr} - teq r2, #0 - LOADREGS(eqfd, sp!, {pc}) - b 3b - -6: subs r2, r2, #1 - strgeb r1, [r3], #1 - bgt 6b - RETINSTR(mov, pc, lr) - -ENTRY(strrchr) - stmfd sp!, {lr} - mov r3, #0 -1: ldrb r2, [r0], #1 - teq r2, r1 - moveq r3, r0 - teq r2, #0 - bne 1b - mov r0, r3 - LOADREGS(fd, sp!, {pc}) - -ENTRY(strchr) - stmfd sp!,{lr} - mov r3, #0 -1: ldrb r2, [r0], #1 - teq r2, r1 - teqne r2, #0 - bne 1b - teq r2, #0 - moveq r0, #0 - subne r0, r0, #1 - LOADREGS(fd, sp!, {pc}) - -ENTRY(memchr) - stmfd sp!, {lr} -1: ldrb r3, [r0], #1 - teq r3, r1 - beq 2f - subs r2, r2, #1 - bpl 1b -2: movne r0, #0 - subeq r0, r0, #1 - LOADREGS(fd, sp!, {pc}) - - #define ENTER \ mov ip,sp ;\ stmfd sp!,{r4-r9,fp,ip,lr,pc} ;\ @@ -261,30 +60,30 @@ ENTRY(memmove) blt 6f subs r2, r2, #4 ldrlt r3, [r1], #4 + ldmgeia r1!, {r4, r5} strlt r3, [r0], #4 - ldmgeia r1!, {r3, r4} - stmgeia r0!, {r3, r4} + stmgeia r0!, {r4, r5} subge r2, r2, #4 6: adds r2, r2, #4 EXITEQ cmp r2, #2 ldrb r3, [r1], #1 + ldrgeb r4, [r1], #1 + ldrgtb r5, [r1], #1 strb r3, [r0], #1 - ldrgeb r3, [r1], #1 - strgeb r3, [r0], #1 - ldrgtb r3, [r1], #1 - strgtb r3, [r0], #1 + strgeb r4, [r0], #1 + strgtb r5, [r0], #1 EXIT 7: rsb ip, ip, #4 cmp ip, #2 ldrb r3, [r1], #1 + ldrgeb r4, [r1], #1 + ldrgtb r5, [r1], #1 strb r3, [r0], #1 - ldrgeb r3, [r1], #1 - strgeb r3, [r0], #1 - ldrgtb r3, [r1], #1 - strgtb r3, [r0], #1 + strgeb r4, [r0], #1 + strgtb r5, [r0], #1 subs r2, r2, ip blt 6b ands ip, r1, #3 @@ -314,9 +113,9 @@ ENTRY(memmove) blt 100f 10: mov r3, r7, lsr #8 ldr r7, [r1], #4 + subs r2, r2, #4 orr r3, r3, r7, lsl #24 str r3, [r0], #4 - subs r2, r2, #4 bge 10b 100: sub r1, r1, #3 b 6b @@ -340,9 +139,9 @@ ENTRY(memmove) blt 14f 13: mov r3, r7, lsr #16 ldr r7, [r1], #4 + subs r2, r2, #4 orr r3, r3, r7, lsl #16 str r3, [r0], #4 - subs r2, r2, #4 bge 13b 14: sub r1, r1, #2 b 6b @@ -366,9 +165,9 @@ ENTRY(memmove) blt 18f 17: mov r3, r7, lsr #24 ldr r7, [r1], #4 + subs r2, r2, #4 orr r3, r3, r7, lsl#8 str r3, [r0], #4 - subs r2, r2, #4 bge 17b 18: sub r1, r1, #1 b 6b @@ -403,29 +202,29 @@ ENTRY(memmove) blt 24f subs r2, r2, #4 ldrlt r3, [r1, #-4]! + ldmgedb r1!, {r4, r5} strlt r3, [r0, #-4]! - ldmgedb r1!, {r3, r4} - stmgedb r0!, {r3, r4} + stmgedb r0!, {r4, r5} subge r2, r2, #4 24: adds r2, r2, #4 EXITEQ cmp r2, #2 ldrb r3, [r1, #-1]! + ldrgeb r4, [r1, #-1]! + ldrgtb r5, [r1, #-1]! strb r3, [r0, #-1]! - ldrgeb r3, [r1, #-1]! - strgeb r3, [r0, #-1]! - ldrgtb r3, [r1, #-1]! - strgtb r3, [r0, #-1]! + strgeb r4, [r0, #-1]! + strgtb r5, [r0, #-1]! EXIT 25: cmp ip, #2 ldrb r3, [r1, #-1]! + ldrgeb r4, [r1, #-1]! + ldrgtb r5, [r1, #-1]! strb r3, [r0, #-1]! - ldrgeb r3, [r1, #-1]! - strgeb r3, [r0, #-1]! - ldrgtb r3, [r1, #-1]! - strgtb r3, [r0, #-1]! + strgeb r4, [r0, #-1]! + strgtb r5, [r0, #-1]! subs r2, r2, ip blt 24b ands ip, r1, #3 @@ -455,9 +254,9 @@ ENTRY(memmove) blt 29f 28: mov ip, r3, lsl #8 ldr r3, [r1, #-4]! + subs r2, r2, #4 orr ip, ip, r3, lsr #24 str ip, [r0, #-4]! - subs r2, r2, #4 bge 28b 29: add r1, r1, #3 b 24b @@ -481,9 +280,9 @@ ENTRY(memmove) blt 33f 32: mov ip, r3, lsl #16 ldr r3, [r1, #-4]! + subs r2, r2, #4 orr ip, ip, r3, lsr #16 str ip, [r0, #-4]! - subs r2, r2, #4 bge 32b 33: add r1, r1, #2 b 24b @@ -507,9 +306,9 @@ ENTRY(memmove) blt 37f 36: mov ip, r3, lsl #24 ldr r3, [r1, #-4]! + subs r2, r2, #4 orr ip, ip, r3, lsr #8 str ip, [r0, #-4]! - subs r2, r2, #4 bge 36b 37: add r1, r1, #1 b 24b diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S new file mode 100644 index 000000000..b7202e867 --- /dev/null +++ b/arch/arm/lib/memset.S @@ -0,0 +1,88 @@ +/* + * linux/arch/arm/lib/memset.S + * + * Copyright (C) 1995-1999 Russell King + * + * ASM optimised string functions + * + */ +#include <linux/linkage.h> +#include <asm/assembler.h> +#include "constants.h" + + .text + .align 5 +ENTRY(memset) + mov r3, r0 + cmp r2, #16 + blt 6f + ands ip, r3, #3 + beq 1f + cmp ip, #2 + strltb r1, [r3], #1 @ Align destination + strleb r1, [r3], #1 + strb r1, [r3], #1 + rsb ip, ip, #4 + sub r2, r2, ip +1: orr r1, r1, r1, lsl #8 + orr r1, r1, r1, lsl #16 + cmp r2, #256 + blt 4f + stmfd sp!, {r4, r5, lr} + mov r4, r1 + mov r5, r1 + mov lr, r1 + mov ip, r2, lsr #6 + sub r2, r2, ip, lsl #6 +2: stmia r3!, {r1, r4, r5, lr} @ 64 bytes at a time. + stmia r3!, {r1, r4, r5, lr} + stmia r3!, {r1, r4, r5, lr} + stmia r3!, {r1, r4, r5, lr} + subs ip, ip, #1 + bne 2b + teq r2, #0 + LOADREGS(eqfd, sp!, {r4, r5, pc}) @ Now <64 bytes to go. + tst r2, #32 + stmneia r3!, {r1, r4, r5, lr} + stmneia r3!, {r1, r4, r5, lr} + tst r2, #16 + stmneia r3!, {r1, r4, r5, lr} + ldmia sp!, {r4, r5} +3: tst r2, #8 + stmneia r3!, {r1, lr} + tst r2, #4 + strne r1, [r3], #4 + tst r2, #2 + strneb r1, [r3], #1 + strneb r1, [r3], #1 + tst r2, #1 + strneb r1, [r3], #1 + LOADREGS(fd, sp!, {pc}) + +4: movs ip, r2, lsr #3 + beq 3b + sub r2, r2, ip, lsl #3 + str lr, [sp, #-4]! + mov lr, r1 + subs ip, ip, #4 +5: stmgeia r3!, {r1, lr} + stmgeia r3!, {r1, lr} + stmgeia r3!, {r1, lr} + stmgeia r3!, {r1, lr} + subges ip, ip, #4 + bge 5b + tst ip, #2 + stmneia r3!, {r1, lr} + stmneia r3!, {r1, lr} + tst ip, #1 + stmneia r3!, {r1, lr} + teq r2, #0 + LOADREGS(eqfd, sp!, {pc}) + b 3b + +6: subs r2, r2, #1 + strgeb r1, [r3], #1 + bgt 6b + RETINSTR(mov, pc, lr) + + diff --git a/arch/arm/lib/memzero.S b/arch/arm/lib/memzero.S new file mode 100644 index 000000000..59ec36574 --- /dev/null +++ b/arch/arm/lib/memzero.S @@ -0,0 +1,80 @@ +/* + * linux/arch/arm/lib/memzero.S + * + * Copyright (C) 1995-1999 Russell King + */ +#include <linux/linkage.h> +#include <asm/assembler.h> +#include "constants.h" + + .text + +/* + * Prototype: void memzero(void *d, size_t n) + */ +1: @ 4 <= r1 + cmp ip, #2 @ 1 + strltb r2, [r0], #1 @ 1 + strleb r2, [r0], #1 @ 1 + strb r2, [r0], #1 @ 1 + rsb ip, ip, #4 @ 1 + sub r1, r1, ip @ 1 + cmp r1, #3 @ 1 + bgt 2f @ 1 @ +8 + b 4f @ 1 @ +9 + + .align 5 + +ENTRY(__memzero) + mov r2, #0 @ 1 + cmp r1, #4 @ 1 + blt 4f @ 1 @ = 3 + + @ r1 >= 4 + + ands ip, r0, #3 @ 1 + bne 1b @ 1 @ = 5 + +2: @ r1 >= 4 && (r0 & 3) = 0 @ = 5 or 11 + + str lr, [sp, #-4]! @ 1 + mov r3, #0 @ 1 + mov ip, #0 @ 1 + mov lr, #0 @ 1 + + @ 4 <= r1 <= 32 @ = 9 or 15 + +3: subs r1, r1, #32 @ 1 + stmgeia r0!, {r2, r3, ip, lr} @ 4 + stmgeia r0!, {r2, r3, ip, lr} @ 4 + bgt 3b @ 1 + LOADREGS(eqfd, sp!, {pc}) @ 1/2 + + @ -28 <= r1 <= -1 + + cmp r1, #-16 @ 1 + stmgeia r0!, {r2, r3, ip, lr} @ 4 + ldr lr, [sp], #4 @ 1 + addlts r1, r1, #16 @ 1 + RETINSTR(moveq,pc,lr) @ 1 + + @ -12 <= r1 <= -1 + + cmp r1, #-8 @ 1 + stmgeia r0!, {r2, r3} @ 2 + addlts r1, r1, #8 @ 1 + RETINSTR(moveq,pc,lr) @ 1 + + @ -4 <= r1 <= -1 + + cmp r1, #-4 @ 1 + strge r2, [r0], #4 @ 1 + adds r1, r1, #4 @ 1 + RETINSTR(moveq,pc,lr) @ 1 + +4: @ 1 <= r1 <= 3 + cmp r1, #2 @ 1 + strgtb r2, [r0], #1 @ 1 + strgeb r2, [r0], #1 @ 1 + strb r2, [r0], #1 @ 1 + RETINSTR(mov,pc,lr) @ 1 diff --git a/arch/arm/lib/setbit.S b/arch/arm/lib/setbit.S new file mode 100644 index 000000000..b4319b4c3 --- /dev/null +++ b/arch/arm/lib/setbit.S @@ -0,0 +1,26 @@ +/* + * linux/arch/arm/lib/setbit.S + * + * Copyright (C) 1995-1996 Russell King + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + .text + +@ Purpose : Function to set a bit +@ Prototype: int set_bit(int bit,int *addr) + +ENTRY(set_bit) + and r2, r0, #7 + mov r3, #1 + mov r3, r3, lsl r2 + SAVEIRQS(ip) + DISABLEIRQS(ip) + ldrb r2, [r1, r0, lsr #3] + orr r2, r2, r3 + strb r2, [r1, r0, lsr #3] + RESTOREIRQS(ip) + RETINSTR(mov,pc,lr) + + diff --git a/arch/arm/lib/strchr.S b/arch/arm/lib/strchr.S new file mode 100644 index 000000000..fbde2483f --- /dev/null +++ b/arch/arm/lib/strchr.S @@ -0,0 +1,26 @@ +/* + * linux/arch/arm/lib/strchr.S + * + * Copyright (C) 1995-1999 Russell King + * + * ASM optimised string functions + * + */ +#include <linux/linkage.h> +#include <asm/assembler.h> +#include "constants.h" + + .text +ENTRY(strchr) + str lr, [sp, #-4]! + mov r3, #0 +1: ldrb r2, [r0], #1 + teq r2, r1 + teqne r2, #0 + bne 1b + teq r2, #0 + moveq r0, #0 + subne r0, r0, #1 + LOADREGS(fd, sp!, {pc}) + + diff --git a/arch/arm/lib/strrchr.S b/arch/arm/lib/strrchr.S new file mode 100644 index 000000000..ad5a46089 --- /dev/null +++ b/arch/arm/lib/strrchr.S @@ -0,0 +1,25 @@ +/* + * linux/arch/arm/lib/strrchr.S + * + * Copyright (C) 1995-1999 Russell King + * + * ASM optimised string functions + * + */ +#include <linux/linkage.h> +#include <asm/assembler.h> +#include "constants.h" + + .text +ENTRY(strrchr) + stmfd sp!, {lr} + mov r3, #0 +1: ldrb r2, [r0], #1 + teq r2, r1 + moveq r3, r0 + teq r2, #0 + bne 1b + mov r0, r3 + LOADREGS(fd, sp!, {pc}) + + diff --git a/arch/arm/lib/system.c b/arch/arm/lib/system.c deleted file mode 100644 index f3b32cd82..000000000 --- a/arch/arm/lib/system.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * linux/arch/arm/lib/system.c - * - * Copyright (C) 1999 Russell King - * - * Converted from ASM version 04/09/1999 - */ -#include <linux/kernel.h> - -extern void abort(void) -{ - void *lr = __builtin_return_address(0); - - printk(KERN_CRIT "kernel abort from %p! (Please report to rmk@arm.linux.org.uk)\n", - lr); - - /* force an oops */ - *(int *)0 = 0; - - /* if that doesn't kill us, halt */ - panic("Oops failed to kill thread"); -} diff --git a/arch/arm/lib/testchangebit.S b/arch/arm/lib/testchangebit.S new file mode 100644 index 000000000..d3dd48216 --- /dev/null +++ b/arch/arm/lib/testchangebit.S @@ -0,0 +1,25 @@ +/* + * linux/arch/arm/lib/testchangebit.S + * + * Copyright (C) 1995-1996 Russell King + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + .text + +ENTRY(test_and_change_bit) + add r1, r1, r0, lsr #3 + and r3, r0, #7 + mov r0, #1 + SAVEIRQS(ip) + DISABLEIRQS(ip) + ldrb r2, [r1] + tst r2, r0, lsl r3 + eor r2, r2, r0, lsl r3 + moveq r0, #0 + strb r2, [r1] + RESTOREIRQS(ip) + RETINSTR(mov,pc,lr) + + diff --git a/arch/arm/lib/testclearbit.S b/arch/arm/lib/testclearbit.S new file mode 100644 index 000000000..431865302 --- /dev/null +++ b/arch/arm/lib/testclearbit.S @@ -0,0 +1,25 @@ +/* + * linux/arch/arm/lib/testclearbit.S + * + * Copyright (C) 1995-1996 Russell King + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + .text + +ENTRY(test_and_clear_bit) + add r1, r1, r0, lsr #3 @ Get byte offset + and r3, r0, #7 @ Get bit offset + mov r0, #1 + SAVEIRQS(ip) + DISABLEIRQS(ip) + ldrb r2, [r1] + tst r2, r0, lsl r3 + bic r2, r2, r0, lsl r3 + moveq r0, #0 + strb r2, [r1] + RESTOREIRQS(ip) + RETINSTR(mov,pc,lr) + + diff --git a/arch/arm/lib/testsetbit.S b/arch/arm/lib/testsetbit.S new file mode 100644 index 000000000..760b6649d --- /dev/null +++ b/arch/arm/lib/testsetbit.S @@ -0,0 +1,25 @@ +/* + * linux/arch/arm/lib/testsetbit.S + * + * Copyright (C) 1995-1996 Russell King + */ + +#include <linux/linkage.h> +#include <asm/assembler.h> + .text + +ENTRY(test_and_set_bit) + add r1, r1, r0, lsr #3 @ Get byte offset + and r3, r0, #7 @ Get bit offset + mov r0, #1 + SAVEIRQS(ip) + DISABLEIRQS(ip) + ldrb r2, [r1] + tst r2, r0, lsl r3 + orr r2, r2, r0, lsl r3 + moveq r0, #0 + strb r2, [r1] + RESTOREIRQS(ip) + RETINSTR(mov,pc,lr) + + diff --git a/arch/arm/lib/uaccess.S b/arch/arm/lib/uaccess.S index 898d2ef77..00f987b5f 100644 --- a/arch/arm/lib/uaccess.S +++ b/arch/arm/lib/uaccess.S @@ -12,21 +12,13 @@ #include <asm/errno.h> .text -#ifdef ENTRY + #define USER(x...) \ 9999: x; \ .section __ex_table,"a"; \ .align 3; \ .long 9999b,9001f; \ .previous -#else -#define USER(x...) \ - x -#define ENTRY(x...) \ - .globl _##x; \ -_##x: -#define TESTING -#endif #define PAGE_SHIFT 12 @@ -285,12 +277,10 @@ USER( strgebt r3, [r0], #1) @ May fault USER( strgtbt r3, [r0], #1) @ May fault b .c2u_finished -#ifndef TESTING .section .fixup,"ax" .align 0 9001: LOADREGS(fd,sp!, {r0, r4 - r7, pc}) .previous -#endif /* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n); * Purpose : copy a block from user memory to kernel memory @@ -546,7 +536,6 @@ USER( ldrget r3, [r1], #0) @ May fault strgtb r3, [r0], #1 b .cfu_finished -#ifndef TESTING .section .fixup,"ax" .align 0 /* We took an exception. Zero out the buffer and pretend no @@ -557,7 +546,6 @@ USER( ldrget r3, [r1], #0) @ May fault blne SYMBOL_NAME(__memzero) LOADREGS(fd,sp!, {r0, r4 - r7, pc}) .previous -#endif /* Prototype: int __arch_clear_user(void *addr, size_t sz) * Purpose : clear some user memory @@ -592,7 +580,6 @@ USER( strnebt r2, [r0], #1) mov r0, #0 LOADREGS(fd,sp!, {r1, pc}) -#ifndef TESTING .section .fixup,"ax" .align 0 9001: LOADREGS(fd,sp!, {r0, pc}) @@ -656,5 +643,4 @@ USER( ldrbt r3, [r1], #1) .previous .align -#endif diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 8715ea271..5151591b8 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -29,6 +29,8 @@ #define DO_COW(m) (!((m) & FAULT_CODE_READ)) #define READ_FAULT(m) ((m) & FAULT_CODE_READ) +extern void die_if_kernel(const char *str, struct pt_regs *regs, int err); + #include "fault-common.c" #ifdef DEBUG @@ -118,17 +120,18 @@ static int proc_alignment_read(char *page, char **start, off_t off, * This needs to be done after sysctl_init, otherwise sys/ * will be overwritten. */ -void __init alignment_init(void) +static int __init alignment_init(void) { create_proc_read_entry("sys/debug/alignment", 0, NULL, - proc_alignment_read); + proc_alignment_read, NULL); + return 0; } __initcall(alignment_init); #endif /* CONFIG_SYSCTL */ static int -do_alignment_exception(struct pt_regs *regs) +do_alignment(unsigned long addr, int error_code, struct pt_regs *regs) { unsigned int instr, rd, rn, correction, nr_regs, regbits; unsigned long eaddr; @@ -308,116 +311,99 @@ do_alignment_exception(struct pt_regs *regs) return 0; } +#else + +#define do_alignment NULL + #endif -#define BUG_PROC_MSG \ - "Buggy processor (%08X), trying to continue.\n" \ - "Please read http://www.arm.linux.org.uk/state.html for more information" +#ifdef CONFIG_DEBUG_USER -asmlinkage void -do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs) +static int +do_sect_fault(unsigned long addr, int error_code, struct pt_regs *regs) { if (user_mode(regs)) { - if (addr == regs->ARM_pc) { - static int first = 1; - if (first) { - /* - * I want statistical information on this problem! - */ - printk(KERN_ERR BUG_PROC_MSG, fsr); - first = 0; + printk("%s: permission fault on section, " + "address=0x%08lx, code %d\n", + current->comm, addr, error_code); +#ifdef DEBUG + { + unsigned int i, j; + unsigned long *sp; + + sp = (unsigned long *) (regs->ARM_sp - 128); + for (j = 0; j < 20 && sp_valid(sp); j++) { + printk("%p: ", sp); + for (i = 0; i < 8 && sp_valid(sp); i += 1, sp++) + printk("%08lx ", *sp); + printk("\n"); } - return; + show_regs(regs); + c_backtrace(regs->ARM_fp, regs->ARM_cpsr); } +#endif } + return 1; /* not fixed up */ +} +#else -#define DIE(signr,nam)\ - force_sig(signr, current);\ - die(nam, regs, fsr);\ - do_exit(signr);\ - break - - switch (fsr & 15) { - /* - * 0 - vector exception - */ - case 0: - force_sig(SIGSEGV, current); - if (!user_mode(regs)) { - die("vector exception", regs, fsr); - do_exit(SIGSEGV); - } - break; - - /* - * 15 - permission fault on page - * 5 - page-table entry descriptor fault - * 7 - first-level descriptor fault - */ - case 15: case 5: case 7: - do_page_fault(addr, error_code, regs); - break; +#define do_sect_fault NULL - /* - * 13 - permission fault on section - */ - case 13: - force_sig(SIGSEGV, current); - if (!user_mode(regs)) { - die("section permission fault", regs, fsr); - do_exit(SIGSEGV); - } else { -#ifdef CONFIG_DEBUG_USER - printk("%s: permission fault on section, " - "address=0x%08lx, code %d\n", - current->comm, addr, error_code); -#ifdef DEBUG - { - unsigned int i, j; - unsigned long *sp; - - sp = (unsigned long *) (regs->ARM_sp - 128); - for (j = 0; j < 20 && sp_valid(sp); j++) { - printk("%p: ", sp); - for (i = 0; i < 8 && sp_valid(sp); i += 1, sp++) - printk("%08lx ", *sp); - printk("\n"); - } - show_regs(regs); - c_backtrace(regs->ARM_fp, regs->ARM_cpsr); - } -#endif #endif + +static struct fsr_info { + int (*fn)(unsigned long addr, int error_code, struct pt_regs *regs); + int sig; + char *name; +} fsr_info[] = { + { NULL, SIGSEGV, "vector exception" }, + { do_alignment, SIGBUS, "alignment exception" }, + { NULL, SIGKILL, "terminal exception" }, + { do_alignment, SIGBUS, "alignment exception" }, + { NULL, SIGBUS, "external abort on linefetch" }, + { do_page_fault, SIGSEGV, "page fault" }, + { NULL, SIGBUS, "external abort on linefetch" }, + { do_page_fault, SIGSEGV, "page fault" }, + { NULL, SIGBUS, "external abort on non-linefetch" }, + { NULL, SIGSEGV, "domain fault" }, + { NULL, SIGBUS, "external abort on non-linefetch" }, + { NULL, SIGSEGV, "domain fault" }, + { NULL, SIGBUS, "external abort on translation" }, + { do_sect_fault, SIGSEGV, "section permission fault" }, + { NULL, SIGBUS, "external abort on translation" }, + { do_page_fault, SIGSEGV, "page permission fault" } +}; + +/* + * Currently dropped down to debug level + */ +#define BUG_PROC_MSG \ + KERN_DEBUG "Weird data abort (%08X).\n" \ + KERN_DEBUG "Please see http://www.arm.linux.org.uk/state.html for more information" + +asmlinkage void +do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs) +{ + struct fsr_info *inf; + + if (user_mode(regs) && addr == regs->ARM_pc) { + static int first = 1; + if (first) { + /* + * I want statistical information on this problem, + * but we don't want to hastle the users too much. + */ + printk(BUG_PROC_MSG, fsr); + first = 0; } - break; + return; + } - case 1: - case 3: -#ifdef CONFIG_ALIGNMENT_TRAP - if (!do_alignment_exception(regs)) - break; -#endif - /* - * this should never happen - */ - DIE(SIGBUS, "Alignment exception"); - break; + inf = fsr_info + (fsr & 15); - case 2: - DIE(SIGKILL, "Terminal exception"); - case 12: - case 14: - DIE(SIGBUS, "External abort on translation"); - case 9: - case 11: - DIE(SIGSEGV, "Domain fault"); - - case 4: - case 6: - DIE(SIGBUS, "External abort on linefetch"); - case 8: - case 10: - DIE(SIGBUS, "External abort on non-linefetch"); + if (!inf->fn || inf->fn(addr, error_code, regs)) { + force_sig(inf->sig, current); + die_if_kernel(inf->name, regs, fsr); } } diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c index e516261ed..d04808ffa 100644 --- a/arch/arm/mm/fault-common.c +++ b/arch/arm/mm/fault-common.c @@ -6,7 +6,7 @@ */ #include <linux/config.h> -extern void die(char *msg, struct pt_regs *regs, unsigned int err); +extern void die(const char *msg, struct pt_regs *regs, unsigned int err); /* * This is useful to dump out the page tables associated with @@ -79,7 +79,7 @@ kernel_page_fault(unsigned long addr, int write_access, struct pt_regs *regs, do_exit(SIGKILL); } -static void do_page_fault(unsigned long addr, int mode, struct pt_regs *regs) +static int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs) { struct task_struct *tsk; struct mm_struct *mm; @@ -127,7 +127,7 @@ good_area: goto do_sigbus; up(&mm->mmap_sem); - return; + return 0; /* * Something tried to access memory that isn't in our memory map.. @@ -138,6 +138,7 @@ bad_area: /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { + tsk->thread.address = addr; tsk->thread.error_code = mode; tsk->thread.trap_no = 14; #ifdef CONFIG_DEBUG_USER @@ -145,7 +146,7 @@ bad_area: tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode); #endif force_sig(SIGSEGV, tsk); - return; + return 0; } no_context: @@ -156,11 +157,11 @@ no_context: tsk->comm, regs->ARM_pc, addr, fixup); #endif regs->ARM_pc = fixup; - return; + return 0; } kernel_page_fault(addr, mode, regs, tsk, mm); - return; + return 0; do_sigbus: /* @@ -173,6 +174,7 @@ do_sigbus: * Send a sigbus, regardless of whether we were in kernel * or user mode. */ + tsk->thread.address = addr; tsk->thread.error_code = mode; tsk->thread.trap_no = 14; force_sig(SIGBUS, tsk); @@ -180,6 +182,7 @@ do_sigbus: /* Kernel mode? Handle exceptions or die */ if (!user_mode(regs)) goto no_context; + return 0; } diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 17972e427..bc4cf1ed1 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -168,7 +168,8 @@ void show_mem(void) void __init paging_init(void) { void *zero_page, *bad_page, *bad_table; - unsigned int zone_size[3]; + unsigned int zone_size[MAX_NR_ZONES]; + int i; #ifdef CONFIG_CPU_32 #define TABLE_OFFSET (PTRS_PER_PTE) @@ -193,7 +194,24 @@ void __init paging_init(void) /* * Initialise the zones and mem_map */ - zonesize_init(zone_size); + for (i = 0; i < MAX_NR_ZONES; i++) + zone_size[i] = 0; + + /* + * Calculate the size of the zones. On ARM, we don't have + * any problems with DMA or highmem, so all memory is + * allocated to the DMA zone. + */ + for (i = 0; i < meminfo.nr_banks; i++) { + if (meminfo.bank[i].size) { + unsigned int end; + + end = (meminfo.bank[i].start - PHYS_OFFSET + + meminfo.bank[i].size) >> PAGE_SHIFT; + if (zone_size[0] < end) + zone_size[0] = end; + } + } free_area_init(zone_size); /* @@ -339,10 +357,11 @@ void free_initmem(void) #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { - for (; start < end; start += PAGE_SIZE) { - ClearPageReserved(mem_map + MAP_NR(start)); - set_page_count(mem_map+MAP_NR(start), 1); - free_page(start); + unsigned long addr; + for (addr = start; addr < end; addr += PAGE_SIZE) { + ClearPageReserved(mem_map + MAP_NR(addr)); + set_page_count(mem_map+MAP_NR(addr), 1); + free_page(addr); totalram_pages++; } printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); diff --git a/arch/arm/mm/mm-armo.c b/arch/arm/mm/mm-armo.c index 680a52948..a5d4cdfe8 100644 --- a/arch/arm/mm/mm-armo.c +++ b/arch/arm/mm/mm-armo.c @@ -135,20 +135,6 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) } /* - * Calculate the size of the DMA, normal and highmem zones. - * On 26-bit ARMs, we don't have any real DMA or highmem, - * so we allocate the whole memory as being DMA-capable. - */ -void __init zonesize_init(unsigned int *zone_size) -{ - int i; - - zone_size[0] = max_low_pfn; - zone_size[1] = 0; - zone_size[2] = 0; -} - -/* * This contains the code to setup the memory map on an ARM2/ARM250/ARM3 * machine. This is both processor & architecture specific, and requires * some more work to get it to fit into our separate processor and diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index ee4750c62..76d101507 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -46,6 +46,15 @@ static int __init nowrite_setup(char *__unused) return 1; } +static int __init noalign_setup(char *__unused) +{ + cr_alignment &= ~2; + cr_no_alignment &= ~2; + set_cr(cr_alignment); + return 1; +} + +__setup("noalign", noalign_setup); __setup("nocache", nocache_setup); __setup("nowb", nowrite_setup); @@ -218,7 +227,7 @@ alloc_init_page(unsigned long virt, unsigned long phys, int domain, int prot) * the clearance is done by the middle-level functions (pmd) * rather than the top-level (pgd) functions. */ -static inline void free_init_section(unsigned long virt) +static inline void clear_mapping(unsigned long virt) { pmd_clear(pmd_offset(pgd_offset_k(virt), virt)); } @@ -273,73 +282,76 @@ static void __init create_mapping(struct map_desc *md) } } -/* - * Initial boot-time mapping. This covers just the zero page, kernel and - * the flush area. NB: it must be sorted by virtual address, and no - * virtual address overlaps. - * init_map[2..4] are for architectures with banked memory. - */ -static struct map_desc init_map[] __initdata = { - { 0, 0, PAGE_SIZE, DOMAIN_USER, 0, 0, 1, 0 }, /* zero page */ - { 0, 0, 0, DOMAIN_KERNEL, 0, 1, 1, 1 }, /* kernel memory */ - { 0, 0, 0, DOMAIN_KERNEL, 0, 1, 1, 1 }, /* (4 banks) */ - { 0, 0, 0, DOMAIN_KERNEL, 0, 1, 1, 1 }, - { 0, 0, 0, DOMAIN_KERNEL, 0, 1, 1, 1 }, - { 0, 0, PGDIR_SIZE, DOMAIN_KERNEL, 1, 0, 1, 1 }, /* cache flush 1 */ - { 0, 0, 0, DOMAIN_KERNEL, 1, 0, 1, 0 } /* cache flush 2 */ -}; - -#define NR_INIT_MAPS (sizeof(init_map) / sizeof(init_map[0])) - -/* - * Calculate the size of the DMA, normal and highmem zones. - * On ARM, we don't have any problems with DMA, so all memory - * is allocated to the DMA zone. We also don't have any - * highmem either. - */ -void __init zonesize_init(unsigned int *zone_size) +void __init pagetable_init(void) { + struct map_desc *init_maps, *p; + unsigned long address = 0; int i; - zone_size[0] = 0; - zone_size[1] = 0; - zone_size[2] = 0; + /* + * Setup initial mappings. We use the page we allocated + * for zero page to hold the mappings, which will get + * overwritten by the vectors in traps_init(). The + * mappings must be in virtual address order. + */ + init_maps = p = alloc_bootmem_low_pages(PAGE_SIZE); + + p->physical = virt_to_phys(init_maps); + p->virtual = 0; + p->length = PAGE_SIZE; + p->domain = DOMAIN_USER; + p->prot_read = 0; + p->prot_write = 0; + p->cacheable = 1; + p->bufferable = 0; + + p ++; for (i = 0; i < meminfo.nr_banks; i++) { - if (meminfo.bank[i].size) { - unsigned int end; + if (meminfo.bank[i].size == 0) + continue; - end = (meminfo.bank[i].start - PHYS_OFFSET + - meminfo.bank[i].size) >> PAGE_SHIFT; - if (end > zone_size[0]) - zone_size[0] = end; - } + p->physical = meminfo.bank[i].start; + p->virtual = __phys_to_virt(p->physical); + p->length = meminfo.bank[i].size; + p->domain = DOMAIN_KERNEL; + p->prot_read = 0; + p->prot_write = 1; + p->cacheable = 1; + p->bufferable = 1; + + p ++; } -} -void __init pagetable_init(void) -{ - unsigned long address = 0; - int i; + p->physical = FLUSH_BASE_PHYS; + p->virtual = FLUSH_BASE; + p->length = PGDIR_SIZE; + p->domain = DOMAIN_KERNEL; + p->prot_read = 1; + p->prot_write = 0; + p->cacheable = 1; + p->bufferable = 1; + + p ++; - /* - * Setup the above mappings - */ - init_map[0].physical = virt_to_phys(alloc_bootmem_low_pages(PAGE_SIZE)); - init_map[5].physical = FLUSH_BASE_PHYS; - init_map[5].virtual = FLUSH_BASE; #ifdef FLUSH_BASE_MINICACHE - init_map[6].physical = FLUSH_BASE_PHYS + PGDIR_SIZE; - init_map[6].virtual = FLUSH_BASE_MINICACHE; - init_map[6].length = PGDIR_SIZE; + p->physical = FLUSH_BASE_PHYS + PGDIR_SIZE; + p->virtual = FLUSH_BASE_MINICACHE; + p->length = PGDIR_SIZE; + p->domain = DOMAIN_KERNEL; + p->prot_read = 1; + p->prot_write = 0; + p->cacheable = 1; + p->bufferable = 0; + + p ++; #endif - for (i = 0; i < meminfo.nr_banks; i++) { - init_map[i+1].physical = meminfo.bank[i].start; - init_map[i+1].virtual = meminfo.bank[i].start + - PAGE_OFFSET - PHYS_OFFSET; - init_map[i+1].length = meminfo.bank[i].size; - } + /* + * We may have a mapping in virtual address 0. + * Clear it out. + */ + clear_mapping(0); /* * Go through the initial mappings, but clear out any @@ -347,18 +359,16 @@ void __init pagetable_init(void) */ i = 0; do { - if (address < init_map[i].virtual || i == NR_INIT_MAPS) { - free_init_section(address); + if (address < init_maps->virtual || init_maps == p) { + clear_mapping(address); address += PGDIR_SIZE; } else { - create_mapping(init_map + i); + create_mapping(init_maps); - address = init_map[i].virtual + init_map[i].length; + address = init_maps->virtual + init_maps->length; address = (address + PGDIR_SIZE - 1) & PGDIR_MASK; - do { - i += 1; - } while (init_map[i].length == 0 && i < NR_INIT_MAPS); + init_maps ++; } } while (address != 0); @@ -382,6 +392,7 @@ void __init create_memmap_holes(void) unsigned int i; #define PFN(x) (((x) - PHYS_OFFSET) >> PAGE_SHIFT) +#define free_bootmem(s,sz) free_bootmem(((s)<<PAGE_SHIFT)+PHYS_OFFSET, (sz)<<PAGE_SHIFT) for (i = 0; i < meminfo.nr_banks; i++) { if (meminfo.bank[i].size == 0) @@ -409,7 +420,7 @@ void __init create_memmap_holes(void) end_pfn = PFN(meminfo.bank[i].start + meminfo.bank[i].size); - if (end_pfn != meminfo.end >> PAGE_SHIFT) + if (end_pfn != PFN(meminfo.end)) pg = mem_map + end_pfn; } diff --git a/arch/arm/mm/mm-sa1100.c b/arch/arm/mm/mm-sa1100.c index eba2984b6..c6f9f2e8b 100644 --- a/arch/arm/mm/mm-sa1100.c +++ b/arch/arm/mm/mm-sa1100.c @@ -6,11 +6,11 @@ * Copyright (C) 1998-1999 Russell King * Copyright (C) 1999 Hugo Fiennes * - * 1999/09/12 Nicolas Pitre <nico@visuaide.com> - * Specific RAM implementation details are in - * linux/include/asm/arch-sa1100/memory.h now. - * Allows for better macro optimisations when possible. + * 1999/12/04 Nicolas Pitre <nico@cam.org> + * Converted memory definition for struct meminfo initialisations. + * Memory is listed physically now. */ + #include <linux/config.h> #include <linux/mm.h> #include <linux/init.h> @@ -22,33 +22,37 @@ #define SIZE(x) (sizeof(x) / sizeof(x[0])) + /* - * These are the memory size mappings for the - * SA1100. Note that LART is a special case - - * it doesn't use physical address A23 on the - * DRAM, so we effectively have 4 * 8MB in - * two banks. + * These are the RAM memory mappings for SA1100 implementations. + * Note that LART is a special case - it doesn't use physical + * address line A23 on the DRAM, so we effectively have 4 * 8MB + * in two banks. */ -struct mem_desc mem_desc[] __initdata = { - /* virt start virt end */ +struct mem_desc { + unsigned long phys_start; + unsigned long length; +} mem_desc[] __initdata = { #if defined(CONFIG_SA1100_BRUTUS) - { 0xc0000000, 0xc0400000 }, /* 4MB */ - { 0xc1000000, 0xc1400000 }, /* 4MB */ - { 0xc2000000, 0xc2400000 }, /* 4MB */ - { 0xc3000000, 0xc3400000 } /* 4MB */ + { 0xc0000000, 0x00400000 }, /* 4MB */ + { 0xc8000000, 0x00400000 }, /* 4MB */ +#if 0 /* only two banks until the bootmem stuff is fixed... */ + { 0xd0000000, 0x00400000 }, /* 4MB */ + { 0xd8000000, 0x00400000 } /* 4MB */ +#endif #elif defined(CONFIG_SA1100_EMPEG) - { 0xc0000000, 0xc0400000 }, /* 4MB */ - { 0xc1000000, 0xc1400000 } /* 4MB */ + { 0xc0000000, 0x00400000 }, /* 4MB */ + { 0xc8000000, 0x00400000 } /* 4MB */ #elif defined(CONFIG_SA1100_LART) - { 0xc0000000, 0xc0800000 }, /* 16MB */ - { 0xc1000000, 0xc1800000 }, - { 0xc2000000, 0xc2800000 }, /* 16MB */ - { 0xc3000000, 0xc3800000 } + { 0xc0000000, 0x00800000 }, /* 8MB */ + { 0xc1000000, 0x00800000 }, /* 8MB */ + { 0xc8000000, 0x00800000 }, /* 8MB */ + { 0xc9000000, 0x00800000 } /* 8MB */ #elif defined(CONFIG_SA1100_VICTOR) - { 0xc0000000, 0xc0400000 } /* 4MB */ + { 0xc0000000, 0x00400000 } /* 4MB */ #elif defined(CONFIG_SA1100_TIFON) - { 0xc0000000, 0xc1000000 }, /* 16MB */ - { 0xc1000000, 0xc2000000 } /* 16MB */ + { 0xc0000000, 0x01000000 }, /* 16MB */ + { 0xc8000000, 0x01000000 } /* 16MB */ #else #error missing memory configuration #endif @@ -56,6 +60,7 @@ struct mem_desc mem_desc[] __initdata = { unsigned int __initdata mem_desc_size = SIZE(mem_desc); + struct map_desc io_desc[] __initdata = { /* virtual physical length domain r w c b */ #if defined(CONFIG_SA1100_VICTOR) diff --git a/arch/arm/mm/proc-arm6,7.S b/arch/arm/mm/proc-arm6,7.S index d453269d2..23508c197 100644 --- a/arch/arm/mm/proc-arm6,7.S +++ b/arch/arm/mm/proc-arm6,7.S @@ -134,14 +134,10 @@ ENTRY(cpu_arm7_data_abort) b Ldata_simple @ ldc rd, [rn, #m] b Ldata_unknown Ldata_unknown: @ Part of jumptable - ldr r3, [sp, #15 * 4] @ Get PC - str r3, [sp, #-4]! - mov r1, r1, lsr #2 - mov r3, r4 - mov r2, r0 - adr r0, Lukabttxt - bl SYMBOL_NAME(panic) -Lstop: b Lstop + mov r0, r1 + mov r1, r4 + mov r2, r3 + b baddataabort Ldata_ldmstm: tst r4, #1 << 21 @ check writeback bit beq Ldata_simple @@ -468,7 +464,7 @@ ENTRY(arm6_processor_functions) .word cpu_arm6_cache_wback_area .word cpu_arm6_cache_purge_area .word cpu_arm6_flush_tlb_page - .word cpu_arm7_do_idle + .word cpu_arm6_do_idle .size arm6_processor_functions, . - arm6_processor_functions /* diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S index 2d57b1030..5431f14a0 100644 --- a/arch/arm/mm/proc-sa110.S +++ b/arch/arm/mm/proc-sa110.S @@ -16,6 +16,7 @@ * is larger than this, then we flush the whole cache */ #define MAX_AREA_SIZE 32768 +#define FLUSH_OFFSET 32768 .macro flush_110_dcache rd, ra, re add \re, \ra, #16384 @ only necessary for 16k @@ -56,7 +57,7 @@ cpu_sa110_flush_cache_all_r2: ands r1, r1, #1 eor r1, r1, #1 str r1, [r3] - addne ip, ip, #32768 + addne ip, ip, #FLUSH_OFFSET flush_110_dcache r3, ip, r1 mov ip, #0 teq r2, #0 @@ -74,7 +75,7 @@ cpu_sa1100_flush_cache_all_r2: ands r1, r1, #1 eor r1, r1, #1 str r1, [r3] - addne ip, ip, #32768 + addne ip, ip, #FLUSH_OFFSET flush_1100_dcache r3, ip, r1 mov ip, #0 teq r2, #0 @@ -321,7 +322,7 @@ ENTRY(cpu_sa110_set_pgd) ands r2, r2, #1 eor r2, r2, #1 str r2, [r3] - addne ip, ip, #32768 + addne ip, ip, #FLUSH_OFFSET flush_110_dcache r3, ip, r1 mov r1, #0 mcr p15, 0, r1, c7, c5, 0 @ flush I cache @@ -338,7 +339,7 @@ ENTRY(cpu_sa1100_set_pgd) ands r2, r2, #1 eor r2, r2, #1 str r2, [r3] - addne ip, ip, #32768 + addne ip, ip, #FLUSH_OFFSET flush_1100_dcache r3, ip, r1 mov r1, #0 mcr p15, 0, r1, c7, c5, 0 @ flush I cache @@ -430,8 +431,12 @@ ENTRY(cpu_sa110_do_idle) ENTRY(cpu_sa1100_do_idle) mov r0, #0 mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching - @ load from uncacheable loc? - mcr p15, 0, r0, c15, c8, 2 @ Wait for interrupt + ldr r1, =FLUSH_BASE+FLUSH_OFFSET*2 @ load from uncacheable loc + ldr r1, [r1, #0] + b 1f + + .align 5 +1: mcr p15, 0, r0, c15, c8, 2 @ Wait for interrupt mcr p15, 0, r0, c15, c1, 2 @ Enable clock switching mov pc, lr diff --git a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in index f83109875..93b8946e7 100644 --- a/arch/arm/vmlinux-armv.lds.in +++ b/arch/arm/vmlinux-armv.lds.in @@ -6,82 +6,84 @@ OUTPUT_ARCH(arm) ENTRY(stext) SECTIONS { - . = TEXTADDR; - .text : { } /* Set text start address */ - - __init_begin = .; /* Init code and data */ - .text.init : { *(.text.init) } - __proc_info_begin = .; - .proc.info : { *(.proc.info) } - __proc_info_end = .; - .data.init : { *(.data.init) } - . = ALIGN(16); - __setup_start = .; - .setup.init : { *(.setup.init) } - __setup_end = .; - __initcall_start = .; - .initcall.init : { *(.initcall.init) } - __initcall_end = .; - . = ALIGN(4096); - __init_end = .; - - __ebsa285_begin = .; - .text.ebsa285 : { *(.text.ebsa285) } - .data.ebsa285 : { *(.data.ebsa285) } - . = ALIGN(4096); - __ebsa285_end = .; - - __netwinder_begin = .; - .text.netwinder : { *(.text.netwinder) } - .data.netwinder : { *(.data.netwinder) } - . = ALIGN(4096); - __netwinder_end = .; - - _text = .; /* Text and read-only data */ - .text.real : { /* Real text segment */ - *(.text) - *(.fixup) - *(.gnu.warning) + . = TEXTADDR; + .init : { /* Init code and data */ + __init_begin = .; + *(.text.init) + __proc_info_begin = .; + *(.proc.info) + __proc_info_end = .; + *(.data.init) + . = ALIGN(16); + __setup_start = .; + *(.setup.init) + __setup_end = .; + __initcall_start = .; + *(.initcall.init) + __initcall_end = .; + . = ALIGN(4096); + __init_end = .; } - .text.lock : { *(.text.lock) } /* out-of-line lock text */ - .rodata : { *(.rodata) } - .kstrtab : { *(.kstrtab) } + .ebsa285 : { + __ebsa285_begin = .; + *(.text.ebsa285) + *(.data.ebsa285) + . = ALIGN(4096); + __ebsa285_end = .; + } - . = ALIGN(16); /* Exception table */ - __start___ex_table = .; - __ex_table : { *(__ex_table) } - __stop___ex_table = .; + .netwinder : { + __netwinder_begin = .; + *(.text.netwinder) + *(.data.netwinder) + . = ALIGN(4096); + __netwinder_end = .; + } - __start___ksymtab = .; /* Kernel symbol table */ - __ksymtab : { *(__ksymtab) } - __stop___ksymtab = .; + .text : { /* Real text segment */ + _text = .; /* Text and read-only data */ + *(.text) + *(.fixup) + *(.gnu.warning) + *(.text.lock) /* out-of-line lock text */ + *(.rodata) + *(.kstrtab) + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; - .got : { *(.got) } /* Global offset table */ + __start___ksymtab = .; /* Kernel symbol table */ + *(__ksymtab) + __stop___ksymtab = .; - _etext = .; /* End of text section */ + *(.got) /* Global offset table */ - . = ALIGN(8192); - .data : { /* Data */ - *(.init.task) - *(.data) - CONSTRUCTORS + _etext = .; /* End of text section */ } - _edata = .; /* End of data section */ + . = ALIGN(8192); - __bss_start = .; /* BSS */ - .bss : { - *(.bss) + .data : { /* Data */ + *(.init.task) + *(.data) + CONSTRUCTORS + _edata = .; /* End of data section */ } - _end = . ; - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } + .bss : { + __bss_start = .; /* BSS */ + *(.bss) + *(COMMON) + _end = . ; + } + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } } diff --git a/arch/i386/config.in b/arch/i386/config.in index 654602855..a32b43c65 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -7,6 +7,8 @@ mainmenu_name "Linux Kernel Configuration" define_bool CONFIG_X86 y define_bool CONFIG_ISA 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 @@ -35,6 +37,7 @@ if [ "$CONFIG_M686" = "y" -o "$CONFIG_M586TSC" = "y" ]; then fi if [ "$CONFIG_M686" = "y" ]; then define_bool CONFIG_X86_GOOD_APIC y + define_bool CONFIG_X86_PGE y fi if [ "$CONFIG_MK7" = "y" ]; then define_bool CONFIG_X86_TSC y @@ -57,6 +60,13 @@ fi bool 'Math emulation' CONFIG_MATH_EMULATION bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR bool 'Symmetric multi-processing support' CONFIG_SMP +if [ "$CONFIG_SMP" != "y" ]; then + bool 'APIC and IO-APIC support on uniprocessors' CONFIG_X86_UP_IOAPIC + if [ "$CONFIG_X86_UP_IOAPIC" = "y" ]; then + define_bool CONFIG_X86_IO_APIC y + define_bool CONFIG_X86_LOCAL_APIC y + fi +fi endmenu mainmenu_option next_comment @@ -103,7 +113,11 @@ if [ "$CONFIG_VISWS" != "y" ]; then bool 'MCA support' CONFIG_MCA fi -source drivers/pcmcia/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 @@ -163,6 +177,8 @@ if [ "$CONFIG_SCSI" != "n" ]; then fi endmenu +source drivers/ieee1394/Config.in + source drivers/i2o/Config.in if [ "$CONFIG_NET" = "y" ]; then diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 9b248a6be..91ca9739b 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -3,6 +3,7 @@ # CONFIG_X86=y CONFIG_ISA=y +CONFIG_UID16=y # # Code maturity level options @@ -24,6 +25,7 @@ CONFIG_X86_BSWAP=y CONFIG_X86_POPAD_OK=y CONFIG_X86_TSC=y CONFIG_X86_GOOD_APIC=y +CONFIG_X86_PGE=y CONFIG_NOHIGHMEM=y # CONFIG_HIGHMEM4G is not set # CONFIG_HIGHMEM64G is not set @@ -53,13 +55,13 @@ CONFIG_PCI_BIOS=y CONFIG_PCI_DIRECT=y CONFIG_PCI_NAMES=y # CONFIG_MCA is not set +CONFIG_HOTPLUG=y # # PCMCIA/CardBus support # CONFIG_PCMCIA=y CONFIG_CARDBUS=y -CONFIG_YENTA=y # CONFIG_I82365 is not set CONFIG_TCIC=y CONFIG_SYSVIPC=y @@ -102,11 +104,13 @@ CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_CMD640=y # CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set CONFIG_BLK_DEV_RZ1000=y CONFIG_BLK_DEV_IDEPCI=y # 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_IDE_CHIPSETS is not set # CONFIG_BLK_CPQ_DA is not set @@ -314,6 +318,7 @@ CONFIG_PCMCIA_PCNET=y # CONFIG_PCMCIA_SMC91C92 is not set # CONFIG_PCMCIA_XIRC2PS is not set # CONFIG_AIRONET4500_CS is not set +# CONFIG_ARCNET_COM20020_CS is not set # CONFIG_PCMCIA_3C575 is not set # CONFIG_PCMCIA_TULIP is not set # CONFIG_PCMCIA_EPIC100 is not set @@ -397,6 +402,7 @@ CONFIG_PSMOUSE=y CONFIG_DRM=y CONFIG_DRM_TDFX=y # CONFIG_DRM_GAMMA is not set +CONFIG_PCMCIA_SERIAL=y # # PCMCIA character device support diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index e60e15620..a59e7c71b 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -55,8 +55,12 @@ ifdef CONFIG_SMP O_OBJS += smp.o smpboot.o trampoline.o endif +ifdef CONFIG_X86_LOCAL_APIC +O_OBJS += apic.o +endif + ifdef CONFIG_X86_IO_APIC -O_OBJS += io_apic.o +O_OBJS += io_apic.o mpparse.o endif ifdef CONFIG_X86_VISWS_APIC diff --git a/arch/i386/kernel/acpi.c b/arch/i386/kernel/acpi.c index 49444d258..3fd1704e3 100644 --- a/arch/i386/kernel/acpi.c +++ b/arch/i386/kernel/acpi.c @@ -172,6 +172,14 @@ static struct ctl_table acpi_table[] = &acpi_p_lvl3_lat, sizeof(acpi_p_lvl3_lat), 0644, NULL, &acpi_do_ulong}, + {ACPI_P_LVL2_LAT, "enter_lvl2_lat", + &acpi_enter_lvl2_lat, sizeof(acpi_enter_lvl2_lat), + 0644, NULL, &acpi_do_ulong}, + + {ACPI_ENTER_LVL3_LAT, "enter_lvl3_lat", + &acpi_enter_lvl3_lat, sizeof(acpi_enter_lvl3_lat), + 0644, NULL, &acpi_do_ulong}, + {ACPI_S0_SLP_TYP, "s0_slp_typ", &acpi_slp_typ[ACPI_S0], sizeof(acpi_slp_typ[ACPI_S0]), 0600, NULL, &acpi_do_ulong}, @@ -195,6 +203,17 @@ static struct ctl_table acpi_dir_table[] = {0} }; +static u32 FASTCALL(acpi_read_pm1_control(struct acpi_facp *)); +static u32 FASTCALL(acpi_read_pm1_status(struct acpi_facp *)); +static u32 FASTCALL(acpi_read_pm1_enable(struct acpi_facp *)); +static u32 FASTCALL(acpi_read_gpe_status(struct acpi_facp *)); +static u32 FASTCALL(acpi_read_gpe_enable(struct acpi_facp *)); + +static void FASTCALL(acpi_write_pm1_control(struct acpi_facp *, u32)); +static void FASTCALL(acpi_write_pm1_status(struct acpi_facp *, u32)); +static void FASTCALL(acpi_write_pm1_enable(struct acpi_facp *, u32)); +static void FASTCALL(acpi_write_gpe_status(struct acpi_facp *, u32)); +static void FASTCALL(acpi_write_gpe_enable(struct acpi_facp *, u32)); /* * Get the value of the PM1 control register (SCI_EN, ...) @@ -643,43 +662,49 @@ static int acpi_disable(struct acpi_facp *facp) return 0; } -static inline int bm_activity(void) +static inline int bm_activity(struct acpi_facp *facp) { - return 0 && acpi_read_pm1_status(acpi_facp) & ACPI_BM; + return acpi_read_pm1_status(facp) & ACPI_BM; } -static inline void clear_bm_activity(void) +static inline void clear_bm_activity(struct acpi_facp *facp) { - acpi_write_pm1_status(acpi_facp, ACPI_BM); + acpi_write_pm1_status(facp, ACPI_BM); } -static void sleep_on_busmaster(void) +static void sleep_on_busmaster(struct acpi_facp *facp) { - u32 pm1_cntr = acpi_read_pm1_control(acpi_facp); + u32 pm1_cntr = acpi_read_pm1_control(facp); if (pm1_cntr & ACPI_BM_RLD) { pm1_cntr &= ~ACPI_BM_RLD; - acpi_write_pm1_control(acpi_facp, pm1_cntr); + acpi_write_pm1_control(facp, pm1_cntr); } } -static void wake_on_busmaster(void) +static void wake_on_busmaster(struct acpi_facp *facp) { - u32 pm1_cntr = acpi_read_pm1_control(acpi_facp); + u32 pm1_cntr = acpi_read_pm1_control(facp); if (!(pm1_cntr & ACPI_BM_RLD)) { pm1_cntr |= ACPI_BM_RLD; - acpi_write_pm1_control(acpi_facp, pm1_cntr); + acpi_write_pm1_control(facp, pm1_cntr); } - clear_bm_activity(); + clear_bm_activity(facp); } +/* The ACPI timer is just the low 24 bits */ +#define TIME_BEGIN(tmr) inl(tmr) +#define TIME_END(tmr, begin) ((inl(tmr) - (begin)) & 0x00ffffff) + + /* * Idle loop (uniprocessor only) */ static void acpi_idle_handler(void) { static int sleep_level = 1; + struct acpi_facp *facp = acpi_facp; - if (!acpi_facp->pm_tmr || !acpi_p_blk) + if (!facp || !facp->pm_tmr || !acpi_p_blk) goto not_initialized; /* @@ -687,7 +712,7 @@ static void acpi_idle_handler(void) */ if (sleep_level == 1) goto sleep1; - if (sleep_level == 2 || bm_activity()) + if (sleep_level == 2) goto sleep2; sleep3: sleep_level = 3; @@ -695,37 +720,53 @@ sleep3: printk("ACPI C3 works\n"); acpi_p_lvl3_tested = 1; } - wake_on_busmaster(); - if (acpi_facp->pm2_cnt) + wake_on_busmaster(facp); + if (facp->pm2_cnt) goto sleep3_with_arbiter; for (;;) { unsigned long time; + unsigned int pm_tmr = facp->pm_tmr; + __cli(); if (current->need_resched) goto out; - time = inl(acpi_facp->pm_tmr); + if (bm_activity(facp)) + goto sleep2; + + time = TIME_BEGIN(pm_tmr); inb(acpi_p_blk + ACPI_P_LVL3); - time = inl(acpi_facp->pm_tmr) - time; + inl(pm_tmr); /* Dummy read, force synchronization with the PMU */ + time = TIME_END(pm_tmr, time); + __sti(); - if (time > acpi_p_lvl3_lat || bm_activity()) + if (time < acpi_p_lvl3_lat) goto sleep2; } sleep3_with_arbiter: for (;;) { unsigned long time; - unsigned int pm2_cntr = acpi_facp->pm2_cnt; + u8 arbiter; + unsigned int pm2_cntr = facp->pm2_cnt; + unsigned int pm_tmr = facp->pm_tmr; + __cli(); if (current->need_resched) goto out; - time = inl(acpi_facp->pm_tmr); - outb(inb(pm2_cntr) | ACPI_ARB_DIS, pm2_cntr); + if (bm_activity(facp)) + goto sleep2; + + time = TIME_BEGIN(pm_tmr); + arbiter = inb(pm2_cntr) & ~ACPI_ARB_DIS; + outb(arbiter | ACPI_ARB_DIS, pm2_cntr); /* Disable arbiter, park on CPU */ inb(acpi_p_blk + ACPI_P_LVL3); - outb(inb(pm2_cntr) & ~ACPI_ARB_DIS, pm2_cntr); - time = inl(acpi_facp->pm_tmr) - time; + inl(pm_tmr); /* Dummy read, force synchronization with the PMU */ + time = TIME_END(pm_tmr, time); + outb(arbiter, pm2_cntr); /* Enable arbiter again.. */ + __sti(); - if (time > acpi_p_lvl3_lat || bm_activity()) + if (time < acpi_p_lvl3_lat) goto sleep2; } @@ -735,38 +776,45 @@ sleep2: printk("ACPI C2 works\n"); acpi_p_lvl2_tested = 1; } - wake_on_busmaster(); /* Required to track BM activity.. */ + wake_on_busmaster(facp); /* Required to track BM activity.. */ for (;;) { unsigned long time; + unsigned int pm_tmr = facp->pm_tmr; + __cli(); if (current->need_resched) goto out; - time = inl(acpi_facp->pm_tmr); + + time = TIME_BEGIN(pm_tmr); inb(acpi_p_blk + ACPI_P_LVL2); - time = inl(acpi_facp->pm_tmr) - time; + inl(pm_tmr); /* Dummy read, force synchronization with the PMU */ + time = TIME_END(pm_tmr, time); + __sti(); - if (time > acpi_p_lvl2_lat) + if (time < acpi_p_lvl2_lat) goto sleep1; - if (bm_activity()) { - clear_bm_activity(); + if (bm_activity(facp)) { + clear_bm_activity(facp); continue; } - if (time < acpi_enter_lvl3_lat) + if (time > acpi_enter_lvl3_lat) goto sleep3; } sleep1: sleep_level = 1; - sleep_on_busmaster(); + sleep_on_busmaster(facp); for (;;) { unsigned long time; + unsigned int pm_tmr = facp->pm_tmr; + __cli(); if (current->need_resched) goto out; - time = inl(acpi_facp->pm_tmr); + time = TIME_BEGIN(pm_tmr); __asm__ __volatile__("sti ; hlt": : :"memory"); - time = inl(acpi_facp->pm_tmr) - time; - if (time < acpi_enter_lvl2_lat) + time = TIME_END(pm_tmr, time); + if (time > acpi_enter_lvl2_lat) goto sleep2; } @@ -1221,7 +1269,7 @@ static int __init acpi_init(void) * do this with multiple CPU's, we'd need a per-CPU ACPI * device.. */ -#ifdef __SMP__ +#ifdef CONFIG_SMP if (smp_num_cpus > 1) return 0; #endif diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c new file mode 100644 index 000000000..b8bca05c6 --- /dev/null +++ b/arch/i386/kernel/apic.c @@ -0,0 +1,656 @@ +/* + * Local APIC handling, local APIC timers + * + * (c) 1999, 2000 Ingo Molnar <mingo@redhat.com> + * + */ + +#include <linux/config.h> +#include <linux/init.h> + +#include <linux/mm.h> +#include <linux/irq.h> +#include <linux/delay.h> +#include <linux/bootmem.h> +#include <linux/smp_lock.h> +#include <linux/interrupt.h> +#include <linux/mc146818rtc.h> +#include <linux/kernel_stat.h> + +#include <asm/smp.h> +#include <asm/mtrr.h> +#include <asm/mpspec.h> +#include <asm/pgalloc.h> + +int prof_multiplier[NR_CPUS] = { 1, }; +int prof_old_multiplier[NR_CPUS] = { 1, }; +int prof_counter[NR_CPUS] = { 1, }; + +/* + * IA s/w dev Vol 3, Section 7.4 + */ +#define APIC_DEFAULT_PHYS_BASE 0xfee00000 + +int get_maxlvt(void) +{ + unsigned int v, ver, maxlvt; + + v = apic_read(APIC_LVR); + ver = GET_APIC_VERSION(v); + /* 82489DXs do not report # of LVT entries. */ + maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(v) : 2; + return maxlvt; +} + +void disable_local_APIC (void) +{ + unsigned long value; + int maxlvt; + + /* + * Disable APIC + */ + value = apic_read(APIC_SPIV); + value &= ~(1<<8); + apic_write(APIC_SPIV,value); + + /* + * Clean APIC state for other OSs: + */ + value = apic_read(APIC_SPIV); + value &= ~(1<<8); + apic_write(APIC_SPIV,value); + maxlvt = get_maxlvt(); + apic_write_around(APIC_LVTT, 0x00010000); + apic_write_around(APIC_LVT0, 0x00010000); + apic_write_around(APIC_LVT1, 0x00010000); + if (maxlvt >= 3) + apic_write_around(APIC_LVTERR, 0x00010000); + if (maxlvt >= 4) + apic_write_around(APIC_LVTPC, 0x00010000); +} + +extern void __error_in_apic_c (void); + +void __init setup_local_APIC (void) +{ + unsigned long value, ver, maxlvt; + + if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f) + __error_in_apic_c(); + + /* + * Double-check wether this APIC is really registered. + */ + if (!test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map)) + BUG(); + + value = apic_read(APIC_SPIV); + /* + * Enable APIC + */ + value |= (1<<8); + + /* + * Some unknown Intel IO/APIC (or APIC) errata is biting us with + * certain networking cards. If high frequency interrupts are + * happening on a particular IOAPIC pin, plus the IOAPIC routing + * entry is masked/unmasked at a high rate as well then sooner or + * later IOAPIC line gets 'stuck', no more interrupts are received + * from the device. If focus CPU is disabled then the hang goes + * away, oh well :-( + * + * [ This bug can be reproduced easily with a level-triggered + * PCI Ne2000 networking cards and PII/PIII processors, dual + * BX chipset. ] + */ +#if 0 + /* Enable focus processor (bit==0) */ + value &= ~(1<<9); +#else + /* Disable focus processor (bit==1) */ + value |= (1<<9); +#endif + /* + * Set spurious IRQ vector + */ + value |= SPURIOUS_APIC_VECTOR; + apic_write(APIC_SPIV,value); + + /* + * Set up LVT0, LVT1: + * + * set up through-local-APIC on the BP's LINT0. This is not + * strictly necessery in pure symmetric-IO mode, but sometimes + * we delegate interrupts to the 8259A. + */ + if (!smp_processor_id()) { + value = 0x00000700; + printk("enabled ExtINT on CPU#%d\n", smp_processor_id()); + } else { + value = 0x00010700; + printk("masked ExtINT on CPU#%d\n", smp_processor_id()); + } + apic_write_around(APIC_LVT0,value); + + /* + * only the BP should see the LINT1 NMI signal, obviously. + */ + if (!smp_processor_id()) + value = 0x00000400; // unmask NMI + else + value = 0x00010400; // mask NMI + apic_write_around(APIC_LVT1,value); + + value = apic_read(APIC_LVR); + ver = GET_APIC_VERSION(value); + if (APIC_INTEGRATED(ver)) { /* !82489DX */ + maxlvt = get_maxlvt(); + /* + * Due to the Pentium erratum 3AP. + */ + if (maxlvt > 3) { + apic_readaround(APIC_SPIV); // not strictly necessery + apic_write(APIC_ESR, 0); + } + value = apic_read(APIC_ESR); + printk("ESR value before enabling vector: %08lx\n", value); + + value = apic_read(APIC_LVTERR); + value = ERROR_APIC_VECTOR; // enables sending errors + apic_write(APIC_LVTERR,value); + /* + * spec says clear errors after enabling vector. + */ + if (maxlvt != 3) { + apic_readaround(APIC_SPIV); + apic_write(APIC_ESR, 0); + } + value = apic_read(APIC_ESR); + printk("ESR value after enabling vector: %08lx\n", value); + } else + printk("No ESR for 82489DX.\n"); + + /* + * Set Task Priority to 'accept all'. We never change this + * later on. + */ + value = apic_read(APIC_TASKPRI); + value &= ~APIC_TPRI_MASK; + apic_write(APIC_TASKPRI,value); + + /* + * Set up the logical destination ID and put the + * APIC into flat delivery mode. + */ + value = apic_read(APIC_LDR); + value &= ~APIC_LDR_MASK; + value |= (1<<(smp_processor_id()+24)); + apic_write(APIC_LDR,value); + + value = apic_read(APIC_DFR); + value |= SET_APIC_DFR(0xf); + apic_write(APIC_DFR, value); +} + +void __init init_apic_mappings(void) +{ + unsigned long apic_phys; + + if (smp_found_config) { + apic_phys = mp_lapic_addr; + } else { + /* + * set up a fake all zeroes page to simulate the + * local APIC and another one for the IO-APIC. We + * could use the real zero-page, but it's safer + * this way if some buggy code writes to this page ... + */ + apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); + apic_phys = __pa(apic_phys); + } + set_fixmap_nocache(FIX_APIC_BASE, apic_phys); + Dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys); + +#ifdef CONFIG_X86_IO_APIC + { + unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; + int i; + + for (i = 0; i < nr_ioapics; i++) { + if (smp_found_config) { + ioapic_phys = mp_ioapics[i].mpc_apicaddr; + } else { + ioapic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); + ioapic_phys = __pa(ioapic_phys); + } + set_fixmap_nocache(idx, ioapic_phys); + Dprintk("mapped IOAPIC to %08lx (%08lx)\n", + __fix_to_virt(idx), ioapic_phys); + idx++; + } + } +#endif +} + +/* + * This part sets up the APIC 32 bit clock in LVTT1, with HZ interrupts + * per second. We assume that the caller has already set up the local + * APIC. + * + * The APIC timer is not exactly sync with the external timer chip, it + * closely follows bus clocks. + */ + +/* + * The timer chip is already set up at HZ interrupts per second here, + * but we do not accept timer interrupts yet. We only allow the BP + * to calibrate. + */ +static unsigned int __init get_8254_timer_count(void) +{ + extern rwlock_t xtime_lock; + unsigned long flags; + + unsigned int count; + + write_lock_irqsave(&xtime_lock, flags); + + outb_p(0x00, 0x43); + count = inb_p(0x40); + count |= inb_p(0x40) << 8; + + write_unlock_irqrestore(&xtime_lock, flags); + + return count; +} + +void __init wait_8254_wraparound(void) +{ + unsigned int curr_count, prev_count=~0; + int delta; + + curr_count = get_8254_timer_count(); + + do { + prev_count = curr_count; + curr_count = get_8254_timer_count(); + delta = curr_count-prev_count; + + /* + * This limit for delta seems arbitrary, but it isn't, it's + * slightly above the level of error a buggy Mercury/Neptune + * chipset timer can cause. + */ + + } while (delta<300); +} + +/* + * This function sets up the local APIC timer, with a timeout of + * 'clocks' APIC bus clock. During calibration we actually call + * this function twice on the boot CPU, once with a bogus timeout + * value, second time for real. The other (noncalibrating) CPUs + * call this function only once, with the real, calibrated value. + * + * We do reads before writes even if unnecessary, to get around the + * P5 APIC double write bug. + */ + +#define APIC_DIVISOR 16 + +void __setup_APIC_LVTT(unsigned int clocks) +{ + unsigned int lvtt1_value, tmp_value; + + tmp_value = apic_read(APIC_LVTT); + lvtt1_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | + APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR; + apic_write(APIC_LVTT, lvtt1_value); + + /* + * Divide PICLK by 16 + */ + tmp_value = apic_read(APIC_TDCR); + apic_write(APIC_TDCR, (tmp_value + & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) + | APIC_TDR_DIV_16); + + tmp_value = apic_read(APIC_TMICT); + apic_write(APIC_TMICT, clocks/APIC_DIVISOR); +} + +void setup_APIC_timer(void * data) +{ + unsigned int clocks = (unsigned int) data, slice, t0, t1; + unsigned long flags; + int delta; + + __save_flags(flags); + __sti(); + /* + * ok, Intel has some smart code in their APIC that knows + * if a CPU was in 'hlt' lowpower mode, and this increases + * its APIC arbitration priority. To avoid the external timer + * IRQ APIC event being in synchron with the APIC clock we + * introduce an interrupt skew to spread out timer events. + * + * The number of slices within a 'big' timeslice is smp_num_cpus+1 + */ + + slice = clocks / (smp_num_cpus+1); + printk("cpu: %d, clocks: %d, slice: %d\n", + smp_processor_id(), clocks, slice); + + /* + * Wait for IRQ0's slice: + */ + wait_8254_wraparound(); + + __setup_APIC_LVTT(clocks); + + t0 = apic_read(APIC_TMCCT)*APIC_DIVISOR; + do { + t1 = apic_read(APIC_TMCCT)*APIC_DIVISOR; + delta = (int)(t0 - t1 - slice*(smp_processor_id()+1)); + } while (delta < 0); + + __setup_APIC_LVTT(clocks); + + printk("CPU%d<C0:%d,C:%d,D:%d,S:%d,C:%d>\n", + smp_processor_id(), t0, t1, delta, slice, clocks); + + __restore_flags(flags); +} + +/* + * In this function we calibrate APIC bus clocks to the external + * timer. Unfortunately we cannot use jiffies and the timer irq + * to calibrate, since some later bootup code depends on getting + * the first irq? Ugh. + * + * We want to do the calibration only once since we + * want to have local timer irqs syncron. CPUs connected + * by the same APIC bus have the very same bus frequency. + * And we want to have irqs off anyways, no accidental + * APIC irq that way. + */ + +int __init calibrate_APIC_clock(void) +{ + unsigned long long t1 = 0, t2 = 0; + long tt1, tt2; + long result; + int i; + const int LOOPS = HZ/10; + + printk("calibrating APIC timer ... "); + + /* + * Put whatever arbitrary (but long enough) timeout + * value into the APIC clock, we just want to get the + * counter running for calibration. + */ + __setup_APIC_LVTT(1000000000); + + /* + * The timer chip counts down to zero. Let's wait + * for a wraparound to start exact measurement: + * (the current tick might have been already half done) + */ + + wait_8254_wraparound(); + + /* + * We wrapped around just now. Let's start: + */ + if (cpu_has_tsc) + rdtscll(t1); + tt1 = apic_read(APIC_TMCCT); + + /* + * Let's wait LOOPS wraprounds: + */ + for (i = 0; i < LOOPS; i++) + wait_8254_wraparound(); + + tt2 = apic_read(APIC_TMCCT); + if (cpu_has_tsc) + rdtscll(t2); + + /* + * The APIC bus clock counter is 32 bits only, it + * might have overflown, but note that we use signed + * longs, thus no extra care needed. + * + * underflown to be exact, as the timer counts down ;) + */ + + result = (tt1-tt2)*APIC_DIVISOR/LOOPS; + + if (cpu_has_tsc) + printk("\n..... CPU clock speed is %ld.%04ld MHz.\n", + ((long)(t2-t1)/LOOPS)/(1000000/HZ), + ((long)(t2-t1)/LOOPS)%(1000000/HZ)); + + printk("..... host bus clock speed is %ld.%04ld MHz.\n", + result/(1000000/HZ), + result%(1000000/HZ)); + + return result; +} + +static unsigned int calibration_result; + +void __init setup_APIC_clocks (void) +{ + __cli(); + + calibration_result = calibrate_APIC_clock(); + /* + * Now set up the timer for real. + */ + setup_APIC_timer((void *)calibration_result); + + __sti(); + + /* and update all other cpus */ + smp_call_function(setup_APIC_timer, (void *)calibration_result, 1, 1); +} + +/* + * the frequency of the profiling timer can be changed + * by writing a multiplier value into /proc/profile. + */ +int setup_profiling_timer(unsigned int multiplier) +{ + int i; + + /* + * Sanity check. [at least 500 APIC cycles should be + * between APIC interrupts as a rule of thumb, to avoid + * irqs flooding us] + */ + if ( (!multiplier) || (calibration_result/multiplier < 500)) + return -EINVAL; + + /* + * Set the new multiplier for each CPU. CPUs don't start using the + * new values until the next timer interrupt in which they do process + * accounting. At that time they also adjust their APIC timers + * accordingly. + */ + for (i = 0; i < NR_CPUS; ++i) + prof_multiplier[i] = multiplier; + + return 0; +} + +#undef APIC_DIVISOR + +/* + * Local timer interrupt handler. It does both profiling and + * process statistics/rescheduling. + * + * We do profiling in every local tick, statistics/rescheduling + * happen only every 'profiling multiplier' ticks. The default + * multiplier is 1 and it can be changed by writing the new multiplier + * value into /proc/profile. + */ + +inline void smp_local_timer_interrupt(struct pt_regs * regs) +{ + int user = (user_mode(regs) != 0); + int cpu = smp_processor_id(); + + /* + * The profiling function is SMP safe. (nothing can mess + * around with "current", and the profiling counters are + * updated with atomic operations). This is especially + * useful with a profiling multiplier != 1 + */ + if (!user) + x86_do_profile(regs->eip); + + if (--prof_counter[cpu] <= 0) { + int system = 1 - user; + struct task_struct * p = current; + + /* + * The multiplier may have changed since the last time we got + * to this point as a result of the user writing to + * /proc/profile. In this case we need to adjust the APIC + * timer accordingly. + * + * Interrupts are already masked off at this point. + */ + prof_counter[cpu] = prof_multiplier[cpu]; + if (prof_counter[cpu] != prof_old_multiplier[cpu]) { + __setup_APIC_LVTT(calibration_result/prof_counter[cpu]); + prof_old_multiplier[cpu] = prof_counter[cpu]; + } + + /* + * After doing the above, we need to make like + * a normal interrupt - otherwise timer interrupts + * ignore the global interrupt lock, which is the + * WrongThing (tm) to do. + */ + + irq_enter(cpu, 0); + update_one_process(p, 1, user, system, cpu); + if (p->pid) { + p->counter -= 1; + if (p->counter <= 0) { + p->counter = 0; + p->need_resched = 1; + } + if (p->priority < DEF_PRIORITY) { + kstat.cpu_nice += user; + kstat.per_cpu_nice[cpu] += user; + } else { + kstat.cpu_user += user; + kstat.per_cpu_user[cpu] += user; + } + kstat.cpu_system += system; + kstat.per_cpu_system[cpu] += system; + + } + irq_exit(cpu, 0); + } + + /* + * We take the 'long' return path, and there every subsystem + * grabs the apropriate locks (kernel lock/ irq lock). + * + * we might want to decouple profiling from the 'long path', + * and do the profiling totally in assembly. + * + * Currently this isn't too much of an issue (performance wise), + * we can take more than 100K local irqs per second on a 100 MHz P5. + */ +} + +/* + * Local APIC timer interrupt. This is the most natural way for doing + * local interrupts, but local timer interrupts can be emulated by + * broadcast interrupts too. [in case the hw doesnt support APIC timers] + * + * [ if a single-CPU system runs an SMP kernel then we call the local + * interrupt as well. Thus we cannot inline the local irq ... ] + */ +unsigned int apic_timer_irqs [NR_CPUS] = { 0, }; + +void smp_apic_timer_interrupt(struct pt_regs * regs) +{ + /* + * the NMI deadlock-detector uses this. + */ + apic_timer_irqs[smp_processor_id()]++; + + /* + * NOTE! We'd better ACK the irq immediately, + * because timer handling can be slow. + */ + ack_APIC_irq(); + smp_local_timer_interrupt(regs); +} + +/* + * This interrupt should _never_ happen with our APIC/SMP architecture + */ +asmlinkage void smp_spurious_interrupt(void) +{ + ack_APIC_irq(); + /* see sw-dev-man vol 3, chapter 7.4.13.5 */ + printk("spurious APIC interrupt on CPU#%d, should never happen.\n", + smp_processor_id()); +} + +/* + * This interrupt should never happen with our APIC/SMP architecture + */ + +static spinlock_t err_lock = SPIN_LOCK_UNLOCKED; + +asmlinkage void smp_error_interrupt(void) +{ + unsigned long v; + + spin_lock(&err_lock); + + v = apic_read(APIC_ESR); + printk("APIC error interrupt on CPU#%d, should never happen.\n", + smp_processor_id()); + printk("... APIC ESR0: %08lx\n", v); + + apic_write(APIC_ESR, 0); + v |= apic_read(APIC_ESR); + printk("... APIC ESR1: %08lx\n", v); + /* + * Be a bit more verbose. (multiple bits can be set) + */ + if (v & 0x01) + printk("... bit 0: APIC Send CS Error (hw problem).\n"); + if (v & 0x02) + printk("... bit 1: APIC Receive CS Error (hw problem).\n"); + if (v & 0x04) + printk("... bit 2: APIC Send Accept Error.\n"); + if (v & 0x08) + printk("... bit 3: APIC Receive Accept Error.\n"); + if (v & 0x10) + printk("... bit 4: Reserved!.\n"); + if (v & 0x20) + printk("... bit 5: Send Illegal Vector (kernel bug).\n"); + if (v & 0x40) + printk("... bit 6: Received Illegal Vector.\n"); + if (v & 0x80) + printk("... bit 7: Illegal Register Address.\n"); + + ack_APIC_irq(); + + irq_err_count++; + + spin_unlock(&err_lock); +} + diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index ecfe0697d..e91602aba 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -416,15 +416,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) @@ -446,11 +446,11 @@ 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_ni_syscall) /* old lock syscall holder */ @@ -470,8 +470,8 @@ 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) @@ -480,8 +480,8 @@ ENTRY(sys_call_table) .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_getgroups16) /* 80 */ + .long SYMBOL_NAME(sys_setgroups16) .long SYMBOL_NAME(old_select) .long SYMBOL_NAME(sys_symlink) .long SYMBOL_NAME(sys_lstat) @@ -495,7 +495,7 @@ ENTRY(sys_call_table) .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 */ @@ -538,8 +538,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) @@ -564,14 +564,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_setresuid16) + .long SYMBOL_NAME(sys_getresuid16) /* 165 */ .long SYMBOL_NAME(sys_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) @@ -582,7 +582,7 @@ 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 */ @@ -598,6 +598,25 @@ ENTRY(sys_call_table) .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) /* @@ -606,6 +625,6 @@ 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-197 + .rept NR_syscalls-216 .long SYMBOL_NAME(sys_ni_syscall) .endr diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index 9f75d94bf..2df82ff21 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -23,7 +23,7 @@ extern void dump_thread(struct pt_regs *, struct user *); extern int dump_fpu(elf_fpregset_t *); -#ifdef __SMP__ +#ifdef CONFIG_SMP extern void FASTCALL( __write_lock_failed(rwlock_t *rw)); extern void FASTCALL( __read_lock_failed(rwlock_t *rw)); #endif @@ -92,13 +92,10 @@ EXPORT_SYMBOL(mmx_clear_page); EXPORT_SYMBOL(mmx_copy_page); #endif -#ifdef __SMP__ +#ifdef CONFIG_SMP EXPORT_SYMBOL(cpu_data); EXPORT_SYMBOL(kernel_flag); -EXPORT_SYMBOL(cpu_number_map); -EXPORT_SYMBOL(__cpu_logical_map); EXPORT_SYMBOL(smp_num_cpus); -EXPORT_SYMBOL(cpu_present_map); EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL_NOVERS(__write_lock_failed); EXPORT_SYMBOL_NOVERS(__read_lock_failed); diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c index 3e9097f06..c62e5c2d2 100644 --- a/arch/i386/kernel/i8259.c +++ b/arch/i386/kernel/i8259.c @@ -71,17 +71,16 @@ BUILD_16_IRQS(0xc) BUILD_16_IRQS(0xd) #undef BI -#ifdef __SMP__ /* * The following vectors are part of the Linux architecture, there * is no hardware IRQ pin equivalent for them, they are triggered * through the ICC by us (IPIs) */ +#ifdef CONFIG_SMP BUILD_SMP_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR) BUILD_SMP_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR) BUILD_SMP_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR) -BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR) -BUILD_SMP_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR) +#endif /* * every pentium local APIC has two 'local interrupts', with a @@ -90,8 +89,10 @@ BUILD_SMP_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR) * overflow. Linux uses the local APIC timer interrupt to get * a much simpler SMP time architecture: */ +#ifdef CONFIG_X86_LOCAL_APIC BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR) - +BUILD_SMP_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR) +BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR) #endif #define IRQ(x,y) \ @@ -428,8 +429,7 @@ void __init init_IRQ(void) set_intr_gate(vector, interrupt[i]); } -#ifdef __SMP__ - +#ifdef CONFIG_SMP /* * IRQ0 must be given a fixed assignment and initialized, * because it's used before the IO-APIC is set up. @@ -445,16 +445,18 @@ void __init init_IRQ(void) /* IPI for invalidation */ set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt); - /* self generated IPI for local APIC timer */ - set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); - /* IPI for generic function call */ set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); +#endif + +#ifdef CONFIG_X86_LOCAL_APIC + /* self generated IPI for local APIC timer */ + set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); /* IPI vectors for APIC spurious and error interrupts */ set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); set_intr_gate(ERROR_APIC_VECTOR, error_interrupt); -#endif +#endif /* * Set the clock to HZ Hz, we already have a valid diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 5ed9255f6..fdd4ecda9 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -1,7 +1,7 @@ /* * Intel IO-APIC support for multi-Pentium hosts. * - * Copyright (C) 1997, 1998, 1999 Ingo Molnar, Hajnalka Szabo + * Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo * * Many thanks to Stig Venaas for trying out countless experimental * patches and reporting/debugging problems patiently! @@ -13,142 +13,35 @@ * and Ingo Molnar <mingo@redhat.com> */ -#include <linux/sched.h> -#include <linux/smp_lock.h> +#include <linux/mm.h> +#include <linux/irq.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/sched.h> +#include <linux/config.h> +#include <linux/smp_lock.h> + #include <asm/io.h> +#include <asm/smp.h> #include <asm/desc.h> -#include <linux/irq.h> - -#undef __init -#define __init - -/* - * volatile is justified in this case, IO-APIC register contents - * might change spontaneously, GCC should not cache it - */ -#define IO_APIC_BASE(idx) ((volatile int *)__fix_to_virt(FIX_IO_APIC_BASE_0 + idx)) - -extern int nmi_watchdog; - -/* - * The structure of the IO-APIC: - */ - -struct IO_APIC_reg_00 { - __u32 __reserved_2 : 24, - ID : 4, - __reserved_1 : 4; -} __attribute__ ((packed)); - -struct IO_APIC_reg_01 { - __u32 version : 8, - __reserved_2 : 8, - entries : 8, - __reserved_1 : 8; -} __attribute__ ((packed)); - -struct IO_APIC_reg_02 { - __u32 __reserved_2 : 24, - arbitration : 4, - __reserved_1 : 4; -} __attribute__ ((packed)); - /* * # of IO-APICs and # of IRQ routing registers */ int nr_ioapics = 0; int nr_ioapic_registers[MAX_IO_APICS]; -enum ioapic_irq_destination_types { - dest_Fixed = 0, - dest_LowestPrio = 1, - dest_SMI = 2, - dest__reserved_1 = 3, - dest_NMI = 4, - dest_INIT = 5, - dest__reserved_2 = 6, - dest_ExtINT = 7 -}; - -struct IO_APIC_route_entry { - __u32 vector : 8, - delivery_mode : 3, /* 000: FIXED - * 001: lowest prio - * 111: ExtINT - */ - dest_mode : 1, /* 0: physical, 1: logical */ - delivery_status : 1, - polarity : 1, - irr : 1, - trigger : 1, /* 0: edge, 1: level */ - mask : 1, /* 0: enabled, 1: disabled */ - __reserved_2 : 15; - - union { struct { __u32 - __reserved_1 : 24, - physical_dest : 4, - __reserved_2 : 4; - } physical; - - struct { __u32 - __reserved_1 : 24, - logical_dest : 8; - } logical; - } dest; - -} __attribute__ ((packed)); - -/* - * MP-BIOS irq configuration table structures: - */ +/* I/O APIC entries */ +struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS]; -struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];/* I/O APIC entries */ -int mp_irq_entries = 0; /* # of MP IRQ source entries */ +/* # of MP IRQ source entries */ struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; - /* MP IRQ source entries */ -int mpc_default_type = 0; /* non-0 if default (table-less) - MP configuration */ - - -/* - * This is performance-critical, we want to do it O(1) - * - * the indexing order of this array favors 1:1 mappings - * between pins and IRQs. - */ -static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) -{ - *IO_APIC_BASE(apic) = reg; - return *(IO_APIC_BASE(apic)+4); -} - -static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) -{ - *IO_APIC_BASE(apic) = reg; - *(IO_APIC_BASE(apic)+4) = value; -} - -/* - * Re-write a value: to be used for read-modify-write - * cycles where the read already set up the index register. - */ -static inline void io_apic_modify(unsigned int apic, unsigned int value) -{ - *(IO_APIC_BASE(apic)+4) = value; -} +/* MP IRQ source entries */ +int mp_irq_entries = 0; -/* - * Synchronize the IO-APIC and the CPU by doing - * a dummy read from the IO-APIC - */ -static inline void io_apic_sync(unsigned int apic) -{ - (void) *(IO_APIC_BASE(apic)+4); -} +/* non-0 if default (table-less) MP configuration */ +int mpc_default_type = 0; /* * Rough estimation of how many shared IRQs there are, can @@ -157,6 +50,13 @@ static inline void io_apic_sync(unsigned int apic) #define MAX_PLUS_SHARED_IRQS NR_IRQS #define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS) +/* + * This is performance-critical, we want to do it O(1) + * + * the indexing order of this array favors 1:1 mappings + * between pins and IRQs. + */ + static struct irq_pin_list { int apic, pin, next; } irq_2_pin[PIN_MAP_SIZE]; @@ -239,6 +139,7 @@ static void clear_IO_APIC (void) #define MAX_PIRQS 8 int pirq_entries [MAX_PIRQS]; int pirqs_enabled; +int skip_ioapic_setup = 0; static int __init ioapic_setup(char *str) { @@ -997,7 +898,7 @@ void disable_IO_APIC(void) } } -static void __init setup_ioapic_id(void) +static void __init setup_ioapic_default_id(void) { struct IO_APIC_reg_00 reg_00; @@ -1012,7 +913,7 @@ static void __init setup_ioapic_id(void) * system must have a unique ID or we get lots of nice * 'stuck on smp_invalidate_needed IPI wait' messages. */ - if (cpu_present_map & (1<<0x2)) + if (phys_cpu_present_map & (1<<0x2)) panic("APIC ID 2 already used"); /* @@ -1031,6 +932,47 @@ static void __init setup_ioapic_id(void) panic("could not set ID"); } +/* + * function to set the IO-APIC physical IDs based on the + * values stored in the MPC table. + * + * by Matt Domsch <Matt_Domsch@dell.com> Tue Dec 21 12:25:05 CST 1999 + */ + +static void __init setup_ioapic_ids_from_mpc (void) +{ + struct IO_APIC_reg_00 reg_00; + int apic; + + /* + * Set the IOAPIC ID to the value stored in the MPC table. + */ + for (apic = 0; apic < nr_ioapics; apic++) { + + /* Read the register 0 value */ + *(int *)®_00 = io_apic_read(apic, 0); + + /* + * Read the right value from the MPC table and + * write it into the ID register. + */ + printk("...changing IO-APIC physical APIC ID to %d ...", + mp_ioapics[apic].mpc_apicid); + + reg_00.ID = mp_ioapics[apic].mpc_apicid; + io_apic_write(apic, 0, *(int *)®_00); + + /* + * Sanity check + */ + *(int *)®_00 = io_apic_read(apic, 0); + if (reg_00.ID != mp_ioapics[apic].mpc_apicid) + panic("could not set ID!\n"); + else + printk(" ok.\n"); + } +} + static void __init construct_default_ISA_mptable(void) { int i, pos = 0; @@ -1071,7 +1013,7 @@ static void __init construct_default_ISA_mptable(void) mp_irqs[0].mpc_dstirq = 2; } - setup_ioapic_id(); + setup_ioapic_default_id(); } /* @@ -1320,6 +1262,8 @@ static inline void check_timer(void) pin1 = find_timer_pin(mp_INT); pin2 = find_timer_pin(mp_ExtINT); + printk("..TIMER: vector=%d pin1=%d pin2=%d\n", vector, pin1, pin2); + /* * Ok, does IRQ0 through the IOAPIC work? */ @@ -1405,8 +1349,8 @@ void __init setup_IO_APIC(void) { enable_IO_APIC(); - printk("ENABLING IO-APIC IRQs\n"); io_apic_irqs = ~PIC_IRQS; + printk("ENABLING IO-APIC IRQs\n"); /* * If there are no explicit MP IRQ entries, it's either one of the @@ -1422,8 +1366,25 @@ void __init setup_IO_APIC(void) * Set up the IO-APIC IRQ routing table by parsing the MP-BIOS * mptable: */ + setup_ioapic_ids_from_mpc(); setup_IO_APIC_irqs(); init_IO_APIC_traps(); check_timer(); print_IO_APIC(); } + +#ifndef CONFIG_SMP +/* + * This initializes the IO-APIC and APIC hardware if this is + * a UP kernel. + */ +void IO_APIC_init_uniprocessor (void) +{ + if (!smp_found_config) + return; + phys_cpu_present_map = 0xff; + setup_local_APIC(); + setup_IO_APIC(); + setup_APIC_clocks(); +} +#endif diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c index a111eb516..317d8a8d7 100644 --- a/arch/i386/kernel/irq.c +++ b/arch/i386/kernel/irq.c @@ -1,8 +1,3 @@ -/* mostly architecture independent - some moved to i8259.c - the beautiful visws architecture code needs to be updated too. - and, finally, the BUILD_IRQ and SMP_BUILD macros in irq.h need fixed. - */ /* * linux/arch/i386/kernel/irq.c * @@ -16,6 +11,8 @@ */ /* + * (mostly architecture independent, will move to kernel/irq.c in 2.5.) + * * IRQs are in fact implemented a bit like signal handlers for the kernel. * Naturally it's not a 1:1 relation, but there are similarities. */ @@ -33,15 +30,16 @@ #include <linux/smp_lock.h> #include <linux/init.h> #include <linux/kernel_stat.h> +#include <linux/irq.h> -#include <asm/system.h> #include <asm/io.h> +#include <asm/smp.h> +#include <asm/system.h> #include <asm/bitops.h> #include <asm/pgalloc.h> #include <asm/delay.h> #include <asm/desc.h> #include <asm/irq.h> -#include <linux/irq.h> unsigned int local_bh_count[NR_CPUS]; @@ -99,7 +97,7 @@ static void ack_none(unsigned int irq) */ #if CONFIG_X86 printk("unexpected IRQ trap at vector %02x\n", irq); -#ifdef __SMP__ +#ifdef CONFIG_X86_LOCAL_APIC /* * Currently unexpected vectors happen only on SMP and APIC. * We _must_ ack these because every local APIC has only N @@ -149,7 +147,7 @@ int get_irq_list(char *buf) if (!action) continue; p += sprintf(p, "%3d: ",i); -#ifndef __SMP__ +#ifndef CONFIG_SMP p += sprintf(p, "%10u ", kstat_irqs(i)); #else for (j = 0; j < smp_num_cpus; j++) @@ -186,7 +184,7 @@ int get_irq_list(char *buf) */ spinlock_t i386_bh_lock = SPIN_LOCK_UNLOCKED; -#ifdef __SMP__ +#ifdef CONFIG_SMP unsigned char global_irq_holder = NO_PROC_ID; unsigned volatile int global_irq_lock; atomic_t global_irq_count; @@ -707,7 +705,7 @@ void free_irq(unsigned int irq, void *dev_id) } spin_unlock_irqrestore(&irq_controller_lock,flags); -#ifdef __SMP__ +#ifdef CONFIG_SMP /* Wait to make sure it's not being used on another CPU */ while (irq_desc[irq].status & IRQ_INPROGRESS) barrier(); diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c new file mode 100644 index 000000000..977dd18ba --- /dev/null +++ b/arch/i386/kernel/mpparse.c @@ -0,0 +1,514 @@ +/* + * Intel Multiprocessor Specificiation 1.1 and 1.4 + * compliant MP-table parsing routines. + * + * (c) 1995 Alan Cox, Building #3 <alan@redhat.com> + * (c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com> + * + * Fixes + * Erich Boleyn : MP v1.4 and additional changes. + * Alan Cox : Added EBDA scanning + * Ingo Molnar : various cleanups and rewrites + * Maciej W. Rozycki : Bits for genuine 82489DX timers + */ + +#include <linux/mm.h> +#include <linux/irq.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/config.h> +#include <linux/bootmem.h> +#include <linux/smp_lock.h> +#include <linux/kernel_stat.h> +#include <linux/mc146818rtc.h> + +#include <asm/smp.h> +#include <asm/mtrr.h> +#include <asm/mpspec.h> +#include <asm/pgalloc.h> + +/* Have we found an MP table */ +int smp_found_config = 0; + +/* + * Various Linux-internal data structures created from the + * MP-table. + */ +int apic_version [NR_CPUS]; +int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, }; +int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, }; +int mp_current_pci_id = 0; +int pic_mode; +unsigned long mp_lapic_addr = 0; + +/* Processor that is doing the boot up */ +unsigned int boot_cpu_id = 0; +/* Internal processor count */ +static unsigned int num_processors = 1; + +/* Bitmask of physically existing CPUs */ +unsigned long phys_cpu_present_map = 0; + +/* + * IA s/w dev Vol 3, Section 7.4 + */ +#define APIC_DEFAULT_PHYS_BASE 0xfee00000 + +/* + * Intel MP BIOS table parsing routines: + */ + +#ifndef CONFIG_X86_VISWS_APIC +/* + * Checksum an MP configuration block. + */ + +static int __init mpf_checksum(unsigned char *mp, int len) +{ + int sum=0; + while(len--) + sum+=*mp++; + return sum&0xFF; +} + +/* + * Processor encoding in an MP configuration block + */ + +static char __init *mpc_family(int family,int model) +{ + static char n[32]; + static char *model_defs[]= + { + "80486DX","80486DX", + "80486SX","80486DX/2 or 80487", + "80486SL","80486SX/2", + "Unknown","80486DX/2-WB", + "80486DX/4","80486DX/4-WB" + }; + + switch (family) { + case 0x04: + if (model < 10) + return model_defs[model]; + break; + + case 0x05: + return("Pentium(tm)"); + + case 0x06: + return("Pentium(tm) Pro"); + + case 0x0F: + if (model == 0x0F) + return("Special controller"); + } + sprintf(n,"Unknown CPU [%d:%d]",family, model); + return n; +} + +static void __init MP_processor_info (struct mpc_config_processor *m) +{ + int ver; + + if (!(m->mpc_cpuflag & CPU_ENABLED)) + return; + + printk("Processor #%d %s APIC version %d\n", + m->mpc_apicid, + mpc_family( (m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 , + (m->mpc_cpufeature & CPU_MODEL_MASK)>>4), + m->mpc_apicver); + + if (m->mpc_featureflag&(1<<0)) + Dprintk(" Floating point unit present.\n"); + if (m->mpc_featureflag&(1<<7)) + Dprintk(" Machine Exception supported.\n"); + if (m->mpc_featureflag&(1<<8)) + Dprintk(" 64 bit compare & exchange supported.\n"); + if (m->mpc_featureflag&(1<<9)) + Dprintk(" Internal APIC present.\n"); + + if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) { + Dprintk(" Bootup CPU\n"); + boot_cpu_id = m->mpc_apicid; + } else + /* Boot CPU already counted */ + num_processors++; + + if (m->mpc_apicid > NR_CPUS) { + printk("Processor #%d unused. (Max %d processors).\n", + m->mpc_apicid, NR_CPUS); + return; + } + ver = m->mpc_apicver; + + phys_cpu_present_map |= 1 << m->mpc_apicid; + /* + * Validate version + */ + if (ver == 0x0) { + printk("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid); + ver = 0x10; + } + apic_version[m->mpc_apicid] = ver; +} + +static void __init MP_bus_info (struct mpc_config_bus *m) +{ + char str[7]; + + memcpy(str, m->mpc_bustype, 6); + str[6] = 0; + Dprintk("Bus #%d is %s\n", m->mpc_busid, str); + + if (strncmp(str, "ISA", 3) == 0) { + mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA; + } else { + if (strncmp(str, "EISA", 4) == 0) { + mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA; + } else { + if (strncmp(str, "PCI", 3) == 0) { + mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI; + mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id; + mp_current_pci_id++; + } else { + printk("Unknown bustype %s\n", str); + panic("cannot handle bus - mail to linux-smp@vger.rutgers.edu"); + } } } +} + +static void __init MP_ioapic_info (struct mpc_config_ioapic *m) +{ + if (!(m->mpc_flags & MPC_APIC_USABLE)) + return; + + printk("I/O APIC #%d Version %d at 0x%lX.\n", + m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr); + if (nr_ioapics >= MAX_IO_APICS) { + printk("Max # of I/O APICs (%d) exceeded (found %d).\n", + MAX_IO_APICS, nr_ioapics); + panic("Recompile kernel with bigger MAX_IO_APICS!.\n"); + } + mp_ioapics[nr_ioapics] = *m; + nr_ioapics++; +} + +static void __init MP_intsrc_info (struct mpc_config_intsrc *m) +{ + mp_irqs [mp_irq_entries] = *m; + if (++mp_irq_entries == MAX_IRQ_SOURCES) + panic("Max # of irq sources exceeded!!\n"); +} + +static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m) +{ + /* + * Well it seems all SMP boards in existence + * use ExtINT/LVT1 == LINT0 and + * NMI/LVT2 == LINT1 - the following check + * will show us if this assumptions is false. + * Until then we do not have to add baggage. + */ + if ((m->mpc_irqtype == mp_ExtINT) && + (m->mpc_destapiclint != 0)) + BUG(); + if ((m->mpc_irqtype == mp_NMI) && + (m->mpc_destapiclint != 1)) + BUG(); +} + +/* + * Read/parse the MPC + */ + +static int __init smp_read_mpc(struct mp_config_table *mpc) +{ + char str[16]; + int count=sizeof(*mpc); + unsigned char *mpt=((unsigned char *)mpc)+count; + + if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) + { + panic("SMP mptable: bad signature [%c%c%c%c]!\n", + mpc->mpc_signature[0], + mpc->mpc_signature[1], + mpc->mpc_signature[2], + mpc->mpc_signature[3]); + return 1; + } + if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) + { + panic("SMP mptable: checksum error!\n"); + return 1; + } + if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) + { + printk("Bad Config Table version (%d)!!\n",mpc->mpc_spec); + return 1; + } + memcpy(str,mpc->mpc_oem,8); + str[8]=0; + printk("OEM ID: %s ",str); + + memcpy(str,mpc->mpc_productid,12); + str[12]=0; + printk("Product ID: %s ",str); + + printk("APIC at: 0x%lX\n",mpc->mpc_lapic); + + /* save the local APIC address, it might be non-default */ + mp_lapic_addr = mpc->mpc_lapic; + + /* + * Now process the configuration blocks. + */ + while (count < mpc->mpc_length) { + switch(*mpt) { + case MP_PROCESSOR: + { + struct mpc_config_processor *m= + (struct mpc_config_processor *)mpt; + MP_processor_info(m); + mpt += sizeof(*m); + count += sizeof(*m); + break; + } + case MP_BUS: + { + struct mpc_config_bus *m= + (struct mpc_config_bus *)mpt; + MP_bus_info(m); + mpt += sizeof(*m); + count += sizeof(*m); + break; + } + case MP_IOAPIC: + { + struct mpc_config_ioapic *m= + (struct mpc_config_ioapic *)mpt; + MP_ioapic_info(m); + mpt+=sizeof(*m); + count+=sizeof(*m); + break; + } + case MP_INTSRC: + { + struct mpc_config_intsrc *m= + (struct mpc_config_intsrc *)mpt; + + MP_intsrc_info(m); + mpt+=sizeof(*m); + count+=sizeof(*m); + break; + } + case MP_LINTSRC: + { + struct mpc_config_lintsrc *m= + (struct mpc_config_lintsrc *)mpt; + MP_lintsrc_info(m); + mpt+=sizeof(*m); + count+=sizeof(*m); + break; + } + } + } + return num_processors; +} + +/* + * Scan the memory blocks for an SMP configuration block. + */ +static int __init smp_get_mpf(struct intel_mp_floating *mpf) +{ + printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); + if (mpf->mpf_feature2 & (1<<7)) { + printk(" IMCR and PIC compatibility mode.\n"); + pic_mode = 1; + } else { + printk(" Virtual Wire compatibility mode.\n"); + pic_mode = 0; + } + smp_found_config = 1; + /* + * default CPU id - if it's different in the mptable + * then we change it before first using it. + */ + boot_cpu_id = 0; + /* + * Now see if we need to read further. + */ + if (mpf->mpf_feature1 != 0) { + /* + * local APIC has default address + */ + mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; + + /* + * 2 CPUs, numbered 0 & 1. + */ + phys_cpu_present_map = 3; + num_processors = 2; + + nr_ioapics = 1; + mp_ioapics[0].mpc_apicaddr = 0xFEC00000; + /* + * Save the default type number, we + * need it later to set the IO-APIC + * up properly: + */ + mpc_default_type = mpf->mpf_feature1; + + printk("Bus #0 is "); + } + + switch (mpf->mpf_feature1) { + case 1: + case 5: + printk("ISA\n"); + break; + case 2: + printk("EISA with no IRQ0 and no IRQ13 DMA chaining\n"); + break; + case 6: + case 3: + printk("EISA\n"); + break; + case 4: + case 7: + printk("MCA\n"); + break; + case 0: + if (!mpf->mpf_physptr) + BUG(); + break; + default: + printk("???\nUnknown standard configuration %d\n", + mpf->mpf_feature1); + return 1; + } + if (mpf->mpf_feature1 > 4) { + printk("Bus #1 is PCI\n"); + + /* + * Set local APIC version to the integrated form. + * It's initialized to zero otherwise, representing + * a discrete 82489DX. + */ + apic_version[0] = 0x10; + apic_version[1] = 0x10; + } + /* + * Read the physical hardware table. Anything here will override the + * defaults. + */ + if (mpf->mpf_physptr) + smp_read_mpc((void *)mpf->mpf_physptr); + + printk("Processors: %d\n", num_processors); + /* + * Only use the first configuration found. + */ + return 1; +} + +static int __init smp_scan_config(unsigned long base, unsigned long length) +{ + unsigned long *bp = phys_to_virt(base); + struct intel_mp_floating *mpf; + + Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length); + if (sizeof(*mpf) != 16) + printk("Error: MPF size\n"); + + while (length > 0) { + mpf = (struct intel_mp_floating *)bp; + if ((*bp == SMP_MAGIC_IDENT) && + (mpf->mpf_length == 1) && + !mpf_checksum((unsigned char *)bp, 16) && + ((mpf->mpf_specification == 1) + || (mpf->mpf_specification == 4)) ) { + + printk("found SMP MP-table at %08ld\n", + virt_to_phys(mpf)); + smp_get_mpf(mpf); + return 1; + } + bp += 4; + length -= 16; + } + return 0; +} + +void __init init_intel_smp (void) +{ + unsigned int address; + + /* + * FIXME: Linux assumes you have 640K of base ram.. + * this continues the error... + * + * 1) Scan the bottom 1K for a signature + * 2) Scan the top 1K of base RAM + * 3) Scan the 64K of bios + */ + if (smp_scan_config(0x0,0x400) || + smp_scan_config(639*0x400,0x400) || + smp_scan_config(0xF0000,0x10000)) + return; + /* + * If it is an SMP machine we should know now, unless the + * configuration is in an EISA/MCA bus machine with an + * extended bios data area. + * + * there is a real-mode segmented pointer pointing to the + * 4K EBDA area at 0x40E, calculate and scan it here. + * + * NOTE! There are Linux loaders that will corrupt the EBDA + * area, and as such this kind of SMP config may be less + * trustworthy, simply because the SMP table may have been + * stomped on during early boot. These loaders are buggy and + * should be fixed. + */ + + address = *(unsigned short *)phys_to_virt(0x40E); + address <<= 4; + smp_scan_config(address, 0x1000); + if (smp_found_config) + printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.rutgers.edu if you experience SMP problems!\n"); +} + +#else + +/* + * The Visual Workstation is Intel MP compliant in the hardware + * sense, but it doesnt have a BIOS(-configuration table). + * No problem for Linux. + */ +void __init init_visws_smp(void) +{ + smp_found_config = 1; + + phys_cpu_present_map |= 2; /* or in id 1 */ + apic_version[1] |= 0x10; /* integrated APIC */ + apic_version[0] |= 0x10; + + mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; +} + +#endif + +/* + * - Intel MP Configuration Table + * - or SGI Visual Workstation configuration + */ +void __init init_smp_config (void) +{ +#ifdef CONFIG_X86_IO_APIC + init_intel_smp(); +#endif +#ifdef CONFIG_VISWS + init_visws_smp(); +#endif +} + diff --git a/arch/i386/kernel/pci-i386.c b/arch/i386/kernel/pci-i386.c index e94868cd9..ee2edca1e 100644 --- a/arch/i386/kernel/pci-i386.c +++ b/arch/i386/kernel/pci-i386.c @@ -94,59 +94,56 @@ #include "pci-i386.h" -/* - * Assign new address to PCI resource. We hope our resource information - * is complete. On the PC, 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) +void +pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) { - struct resource *r = &dev->resource[i]; - struct resource *pr = pci_find_parent_resource(dev, r); - unsigned long size = r->end + 1; u32 new, check; + int reg; - if (!pr) { - printk(KERN_ERR "PCI: Cannot find parent resource for device %s\n", dev->slot_name); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) { - /* - * We need to avoid collisions with `mirrored' VGA ports and other strange - * ISA hardware, so we always want the addresses kilobyte aligned. - */ - if (size > 0x100) { - printk(KERN_ERR "PCI: I/O Region %s/%d too large (%ld bytes)\n", dev->slot_name, i, size); - return -EFBIG; - } - if (allocate_resource(pr, r, size, 0x1000, ~0, 1024, NULL, NULL)) { - printk(KERN_ERR "PCI: Allocation of I/O region %s/%d (%ld bytes) failed\n", dev->slot_name, i, size); - return -EBUSY; - } + new = res->start | (res->flags & PCI_REGION_FLAG_MASK); + if (resource < 6) { + reg = PCI_BASE_ADDRESS_0 + 4*resource; + } else if (resource == PCI_ROM_RESOURCE) { + res->flags |= PCI_ROM_ADDRESS_ENABLE; + reg = dev->rom_base_reg; } else { - if (allocate_resource(pr, r, size, 0x10000000, ~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; - } + /* Somebody might have asked allocation of a non-standard resource */ + return; } - 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)); + + pci_write_config_dword(dev, reg, new); + pci_read_config_dword(dev, reg, &check); + if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { + printk(KERN_ERR "PCI: Error while updating region " + "%s/%d (%08x != %08x)\n", dev->slot_name, resource, + new, check); } - printk("PCI: Assigned addresses %08lx-%08lx to region %s/%d\n", r->start, r->end, dev->slot_name, i); - return 0; } +void +pcibios_align_resource(void *data, struct resource *res, unsigned long size) +{ + struct pci_dev *dev = data; + + if (res->flags & IORESOURCE_IO) { + unsigned long start = res->start; + + /* We need to avoid collisions with `mirrored' VGA ports + and other strange ISA hardware, so we always want the + addresses kilobyte aligned. */ + if (size >= 0x100) { + printk(KERN_ERR "PCI: I/O Region %s/%d too large" + " (%ld bytes)\n", dev->slot_name, + dev->resource - res, size); + } + + start = (start + 1024 - 1) & ~(1024 - 1); + res->start = start; + } +} + + /* * Handle resources of PCI devices. If the world were perfect, we could * just allocate all the resource regions and do nothing more. It isn't. diff --git a/arch/i386/kernel/pci-pc.c b/arch/i386/kernel/pci-pc.c index 6b7d65589..601ffd3bf 100644 --- a/arch/i386/kernel/pci-pc.c +++ b/arch/i386/kernel/pci-pc.c @@ -23,6 +23,7 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2; static struct pci_bus *pci_root_bus; +static struct pci_ops *pci_root_ops; /* * IRQ routing table provided by the BIOS @@ -876,9 +877,9 @@ static void __init pci_fixup_i450nx(struct pci_dev *d) pci_read_config_byte(d, reg++, &subb); DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb); if (busno) - pci_scan_bus(busno, pci_root_bus->ops, NULL); /* Bus A */ + pci_scan_bus(busno, pci_root_ops, NULL); /* Bus A */ if (suba < subb) - pci_scan_bus(suba+1, pci_root_bus->ops, NULL); /* Bus B */ + pci_scan_bus(suba+1, pci_root_ops, NULL); /* Bus B */ } } @@ -891,7 +892,7 @@ static void __init pci_fixup_rcc(struct pci_dev *d) u8 busno; pci_read_config_byte(d, 0x44, &busno); printk("PCI: RCC host bridge: secondary bus %02x\n", busno); - pci_scan_bus(busno, pci_root_bus->ops, NULL); + pci_scan_bus(busno, pci_root_ops, NULL); } static void __init pci_fixup_compaq(struct pci_dev *d) @@ -903,7 +904,7 @@ static void __init pci_fixup_compaq(struct pci_dev *d) u8 busno; pci_read_config_byte(d, 0xc8, &busno); printk("PCI: Compaq host bridge: secondary bus %02x\n", busno); - pci_scan_bus(busno, pci_root_bus->ops, NULL); + pci_scan_bus(busno, pci_root_ops, NULL); } static void __init pci_fixup_umc_ide(struct pci_dev *d) @@ -1189,7 +1190,6 @@ void __init pcibios_init(void) { struct pci_ops *bios = NULL; struct pci_ops *dir = NULL; - struct pci_ops *ops; #ifdef CONFIG_PCI_BIOS if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) { @@ -1202,16 +1202,16 @@ void __init pcibios_init(void) dir = pci_check_direct(); #endif if (dir) - ops = dir; + pci_root_ops = dir; else if (bios) - ops = bios; + pci_root_ops = bios; else { printk("PCI: No PCI bus detected\n"); return; } printk("PCI: Probing PCI hardware\n"); - pci_root_bus = pci_scan_bus(0, ops, NULL); + pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL); pcibios_fixup_irqs(); if (pci_probe & PCI_PEER_FIXUP) diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index 1e6576860..ed64f15a2 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -198,259 +198,242 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) switch (request) { /* when I and D space are separate, these will need to be fixed. */ - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: { - unsigned long tmp; - int copied; - - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); - ret = -EIO; - if (copied != sizeof(tmp)) - goto out; - ret = put_user(tmp,(unsigned long *) data); - goto out; - } + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA: { + unsigned long tmp; + int copied; + + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + ret = -EIO; + if (copied != sizeof(tmp)) + break; + ret = put_user(tmp,(unsigned long *) data); + break; + } /* read the word at location addr in the USER area. */ - case PTRACE_PEEKUSR: { - unsigned long tmp; + case PTRACE_PEEKUSR: { + unsigned long tmp; - ret = -EIO; - if ((addr & 3) || addr < 0 || - addr > sizeof(struct user) - 3) - goto out; - - tmp = 0; /* Default return condition */ - if(addr < 17*sizeof(long)) - tmp = getreg(child, addr); - if(addr >= (long) &dummy->u_debugreg[0] && - addr <= (long) &dummy->u_debugreg[7]){ - addr -= (long) &dummy->u_debugreg[0]; - addr = addr >> 2; - tmp = child->thread.debugreg[addr]; - }; - ret = put_user(tmp,(unsigned long *) data); - goto out; - } + ret = -EIO; + if ((addr & 3) || addr < 0 || + addr > sizeof(struct user) - 3) + break; - /* when I and D space are separate, this will have to be fixed. */ - case PTRACE_POKETEXT: /* write the word at location addr. */ - case PTRACE_POKEDATA: - ret = 0; - if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) - goto out; - ret = -EIO; - goto out; + tmp = 0; /* Default return condition */ + if(addr < 17*sizeof(long)) + tmp = getreg(child, addr); + if(addr >= (long) &dummy->u_debugreg[0] && + addr <= (long) &dummy->u_debugreg[7]){ + addr -= (long) &dummy->u_debugreg[0]; + addr = addr >> 2; + tmp = child->thread.debugreg[addr]; + } + ret = put_user(tmp,(unsigned long *) data); + break; + } - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ - ret = -EIO; - if ((addr & 3) || addr < 0 || - addr > sizeof(struct user) - 3) - goto out; + /* when I and D space are separate, this will have to be fixed. */ + case PTRACE_POKETEXT: /* write the word at location addr. */ + case PTRACE_POKEDATA: + ret = 0; + if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) + break; + ret = -EIO; + break; - if (addr < 17*sizeof(long)) { - ret = putreg(child, addr, data); - goto out; - } + case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ + ret = -EIO; + if ((addr & 3) || addr < 0 || + addr > sizeof(struct user) - 3) + break; - /* We need to be very careful here. We implicitly - want to modify a portion of the task_struct, and we - have to be selective about what portions we allow someone - to modify. */ + if (addr < 17*sizeof(long)) { + ret = putreg(child, addr, data); + break; + } + /* We need to be very careful here. We implicitly + want to modify a portion of the task_struct, and we + have to be selective about what portions we allow someone + to modify. */ + ret = -EIO; if(addr >= (long) &dummy->u_debugreg[0] && addr <= (long) &dummy->u_debugreg[7]){ - if(addr == (long) &dummy->u_debugreg[4]) return -EIO; - if(addr == (long) &dummy->u_debugreg[5]) return -EIO; + if(addr == (long) &dummy->u_debugreg[4]) break; + if(addr == (long) &dummy->u_debugreg[5]) break; if(addr < (long) &dummy->u_debugreg[4] && - ((unsigned long) data) >= TASK_SIZE-3) return -EIO; + ((unsigned long) data) >= TASK_SIZE-3) break; - ret = -EIO; if(addr == (long) &dummy->u_debugreg[7]) { data &= ~DR_CONTROL_RESERVED; for(i=0; i<4; i++) if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1) goto out; - }; + } addr -= (long) &dummy->u_debugreg; addr = addr >> 2; child->thread.debugreg[addr] = data; ret = 0; - goto out; - }; - ret = -EIO; - goto out; + } + break; - case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: { /* restart after signal. */ - long tmp; + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: { /* restart after signal. */ + long tmp; - ret = -EIO; - if ((unsigned long) data > _NSIG) - goto out; - if (request == PTRACE_SYSCALL) - child->flags |= PF_TRACESYS; - else - child->flags &= ~PF_TRACESYS; - child->exit_code = data; + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + if (request == PTRACE_SYSCALL) + child->flags |= PF_TRACESYS; + else + child->flags &= ~PF_TRACESYS; + child->exit_code = data; /* make sure the single step bit is not set. */ - tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; - put_stack_long(child, EFL_OFFSET,tmp); - wake_up_process(child); - ret = 0; - goto out; - } + tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; + put_stack_long(child, EFL_OFFSET,tmp); + wake_up_process(child); + ret = 0; + break; + } /* * make the child exit. Best I can do is send it a sigkill. * perhaps it should be put in the status that it wants to * exit. */ - case PTRACE_KILL: { - long tmp; + case PTRACE_KILL: { + long tmp; - ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ - goto out; - child->exit_code = SIGKILL; - /* make sure the single step bit is not set. */ - tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; - put_stack_long(child, EFL_OFFSET, tmp); - wake_up_process(child); - goto out; + ret = 0; + if (child->state == TASK_ZOMBIE) /* already dead */ + break; + child->exit_code = SIGKILL; + /* make sure the single step bit is not set. */ + tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; + put_stack_long(child, EFL_OFFSET, tmp); + wake_up_process(child); + break; + } + + case PTRACE_SINGLESTEP: { /* set the trap flag. */ + long tmp; + + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + child->flags &= ~PF_TRACESYS; + if ((child->flags & PF_DTRACE) == 0) { + /* Spurious delayed TF traps may occur */ + child->flags |= PF_DTRACE; } + tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG; + put_stack_long(child, EFL_OFFSET, tmp); + child->exit_code = data; + /* give it a chance to run. */ + wake_up_process(child); + ret = 0; + break; + } + + case PTRACE_DETACH: { /* detach a process that was attached. */ + long tmp; - case PTRACE_SINGLESTEP: { /* set the trap flag. */ - long tmp; + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + child->flags &= ~(PF_PTRACED|PF_TRACESYS); + child->exit_code = data; + write_lock_irqsave(&tasklist_lock, flags); + REMOVE_LINKS(child); + child->p_pptr = child->p_opptr; + SET_LINKS(child); + write_unlock_irqrestore(&tasklist_lock, flags); + /* make sure the single step bit is not set. */ + tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; + put_stack_long(child, EFL_OFFSET, tmp); + wake_up_process(child); + ret = 0; + break; + } + case PTRACE_GETREGS: { /* Get all gp regs from the child. */ + if (!access_ok(VERIFY_WRITE, (unsigned *)data, 17*sizeof(long))) { ret = -EIO; - if ((unsigned long) data > _NSIG) - goto out; - child->flags &= ~PF_TRACESYS; - if ((child->flags & PF_DTRACE) == 0) { - /* Spurious delayed TF traps may occur */ - child->flags |= PF_DTRACE; - } - tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG; - put_stack_long(child, EFL_OFFSET, tmp); - child->exit_code = data; - /* give it a chance to run. */ - wake_up_process(child); - ret = 0; - goto out; + break; } + for ( i = 0; i < 17*sizeof(long); i += sizeof(long) ) { + __put_user(getreg(child, i),(unsigned long *) data); + data += sizeof(long); + } + ret = 0; + break; + } - case PTRACE_DETACH: { /* detach a process that was attached. */ - long tmp; - + case PTRACE_SETREGS: { /* Set all gp regs in the child. */ + unsigned long tmp; + if (!access_ok(VERIFY_READ, (unsigned *)data, 17*sizeof(long))) { ret = -EIO; - if ((unsigned long) data > _NSIG) - goto out; - child->flags &= ~(PF_PTRACED|PF_TRACESYS); - child->exit_code = data; - write_lock_irqsave(&tasklist_lock, flags); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); - /* make sure the single step bit is not set. */ - tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG; - put_stack_long(child, EFL_OFFSET, tmp); - wake_up_process(child); - ret = 0; - goto out; + break; } + for ( i = 0; i < 17*sizeof(long); i += sizeof(long) ) { + __get_user(tmp, (unsigned long *) data); + putreg(child, i, tmp); + data += sizeof(long); + } + ret = 0; + break; + } - case PTRACE_GETREGS: { /* Get all gp regs from the child. */ - if (!access_ok(VERIFY_WRITE, (unsigned *)data, - 17*sizeof(long))) - { - ret = -EIO; - goto out; - } - for ( i = 0; i < 17*sizeof(long); i += sizeof(long) ) - { - __put_user(getreg(child, i),(unsigned long *) data); - data += sizeof(long); - } - ret = 0; - goto out; - }; - - case PTRACE_SETREGS: { /* Set all gp regs in the child. */ - unsigned long tmp; - if (!access_ok(VERIFY_READ, (unsigned *)data, - 17*sizeof(long))) - { - ret = -EIO; - goto out; - } - for ( i = 0; i < 17*sizeof(long); i += sizeof(long) ) - { - __get_user(tmp, (unsigned long *) data); - putreg(child, i, tmp); - data += sizeof(long); - } - ret = 0; - goto out; - }; - - case PTRACE_GETFPREGS: { /* Get the child FPU state. */ - if (!access_ok(VERIFY_WRITE, (unsigned *)data, - sizeof(struct user_i387_struct))) - { - ret = -EIO; - goto out; - } - ret = 0; - if ( !child->used_math ) { - /* Simulate an empty FPU. */ - child->thread.i387.hard.cwd = 0xffff037f; - child->thread.i387.hard.swd = 0xffff0000; - child->thread.i387.hard.twd = 0xffffffff; - } + case PTRACE_GETFPREGS: { /* Get the child FPU state. */ + if (!access_ok(VERIFY_WRITE, (unsigned *)data, sizeof(struct user_i387_struct))) { + ret = -EIO; + break; + } + ret = 0; + if ( !child->used_math ) { + /* Simulate an empty FPU. */ + child->thread.i387.hard.cwd = 0xffff037f; + child->thread.i387.hard.swd = 0xffff0000; + child->thread.i387.hard.twd = 0xffffffff; + } #ifdef CONFIG_MATH_EMULATION - if ( boot_cpu_data.hard_math ) { + if ( boot_cpu_data.hard_math ) { #endif - __copy_to_user((void *)data, &child->thread.i387.hard, - sizeof(struct user_i387_struct)); + __copy_to_user((void *)data, &child->thread.i387.hard, sizeof(struct user_i387_struct)); #ifdef CONFIG_MATH_EMULATION - } else { - save_i387_soft(&child->thread.i387.soft, - (struct _fpstate *)data); - } + } else { + save_i387_soft(&child->thread.i387.soft, (struct _fpstate *)data); + } #endif - goto out; - }; - - case PTRACE_SETFPREGS: { /* Set the child FPU state. */ - if (!access_ok(VERIFY_READ, (unsigned *)data, - sizeof(struct user_i387_struct))) - { - ret = -EIO; - goto out; - } - child->used_math = 1; + break; + } + + case PTRACE_SETFPREGS: { /* Set the child FPU state. */ + if (!access_ok(VERIFY_READ, (unsigned *)data, sizeof(struct user_i387_struct))) { + ret = -EIO; + break; + } + child->used_math = 1; #ifdef CONFIG_MATH_EMULATION - if ( boot_cpu_data.hard_math ) { + if ( boot_cpu_data.hard_math ) { #endif - __copy_from_user(&child->thread.i387.hard, (void *)data, - sizeof(struct user_i387_struct)); + __copy_from_user(&child->thread.i387.hard, (void *)data, sizeof(struct user_i387_struct)); #ifdef CONFIG_MATH_EMULATION - } else { - restore_i387_soft(&child->thread.i387.soft, - (struct _fpstate *)data); - } + } else { + restore_i387_soft(&child->thread.i387.soft, (struct _fpstate *)data); + } #endif - ret = 0; - goto out; - }; + ret = 0; + break; + } - default: - ret = -EIO; - goto out; + default: + ret = -EIO; + break; } out: unlock_kernel(); diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index cd80009d4..d308a1280 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -31,6 +31,11 @@ * * Added proper L2 cache detection for Coppermine * Dragan Stancevic <visitor@valinux.com>, October 1999 + * + * Added the origninal array for capability flags but forgot to credit + * myself :) (~1998) Fixed/cleaned up some cpu_model_info and other stuff + * Jauder Ho <jauderho@carumba.com>, January 2000 + * */ /* @@ -69,6 +74,7 @@ #include <asm/desc.h> #include <asm/e820.h> #include <asm/dma.h> +#include <asm/mpspec.h> /* * Machine setup.. @@ -77,7 +83,7 @@ char ignore_irq13 = 0; /* set if exception 16 works */ struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 }; -unsigned long mmu_cr4_features __initdata = 0; +unsigned long mmu_cr4_features = 0; /* * Bus types .. @@ -691,7 +697,7 @@ void __init setup_arch(char **cmdline_p) */ reserve_bootmem(0, PAGE_SIZE); -#ifdef __SMP__ +#ifdef CONFIG_SMP /* * But first pinch a few for the stack/trampoline stuff * FIXME: Don't need the extra page at 4K, but need to fix @@ -701,7 +707,7 @@ void __init setup_arch(char **cmdline_p) smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ #endif -#ifdef __SMP__ +#ifdef CONFIG_X86_IO_APIC /* * Save possible boot-time SMP configuration: */ @@ -1166,6 +1172,8 @@ void __init get_cpu_vendor(struct cpuinfo_x86 *c) c->x86_vendor = X86_VENDOR_CENTAUR; else if (!strcmp(v, "NexGenDriven")) c->x86_vendor = X86_VENDOR_NEXGEN; + else if (!strcmp(v, "RiseRiseRise")) + c->x86_vendor = X86_VENDOR_RISE; else c->x86_vendor = X86_VENDOR_UNKNOWN; } @@ -1176,6 +1184,7 @@ struct cpu_model_info { char *model_names[16]; }; +/* Naming convention should be: <Name> [(<Codename>)] */ static struct cpu_model_info cpu_models[] __initdata = { { X86_VENDOR_INTEL, 4, { "486 DX-25/33", "486 DX-50", "486 SX", "486 DX/2", "486 SL", @@ -1188,8 +1197,9 @@ static struct cpu_model_info cpu_models[] __initdata = { NULL, NULL, NULL, NULL }}, { X86_VENDOR_INTEL, 6, { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II (Klamath)", - NULL, "Pentium II (Deschutes)", "Mobile Pentium II", "Pentium III (Katmai)", - "Pentium III (Coppermine)", NULL, NULL, NULL, NULL, NULL, NULL }}, + NULL, "Pentium II (Deschutes)", "Mobile Pentium II", + "Pentium III (Katmai)", "Pentium III (Coppermine)", NULL, NULL, + NULL, NULL, NULL, NULL }}, { X86_VENDOR_AMD, 4, { NULL, NULL, NULL, "486 DX/2", NULL, NULL, NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL, "Am5x86-WT", @@ -1210,6 +1220,9 @@ static struct cpu_model_info cpu_models[] __initdata = { { X86_VENDOR_NEXGEN, 5, { "Nx586", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, + { X86_VENDOR_RISE, 5, + { "mP6", "mP6", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, }; void __init identify_cpu(struct cpuinfo_x86 *c) @@ -1300,8 +1313,9 @@ void __init identify_cpu(struct cpuinfo_x86 *c) if (c->x86_model <= 16) p = cpu_models[i].model_names[c->x86_model]; - /* Names for the Pentium II Celeron processors - detectable only by also checking the cache size */ + /* Names for the Pentium II/Celeron processors + detectable only by also checking the cache size. + Dixon is NOT a Celeron. */ if ((cpu_models[i].vendor == X86_VENDOR_INTEL) && (cpu_models[i].x86 == 6)) { @@ -1310,7 +1324,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c) else if(c->x86_model == 6 && c->x86_cache_size == 128) p = "Celeron (Mendocino)"; else if(c->x86_model == 5 && c->x86_cache_size == 256) - p = "Celeron (Dixon)"; + p = "Mobile Pentium II (Dixon)"; } } } @@ -1341,7 +1355,7 @@ void __init dodgy_tsc(void) static char *cpu_vendor_names[] __initdata = { - "Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur" }; + "Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur", "Rise" }; void __init print_cpu_info(struct cpuinfo_x86 *c) @@ -1373,17 +1387,28 @@ int get_cpuinfo(char * buffer) { char *p = buffer; int sep_bug; + + /* + * Flags should be entered into the array ONLY if there is no overlap. + * Else a number should be used and then overridden in the case + * statement below. --Jauder <jauderho@carumba.com> + * + * NOTE: bits 10, 19-22, 26-31 are reserved. + * + * Data courtesy of http://www.sandpile.org/arch/cpuid.htm + * Thanks to the Greasel! + */ static char *x86_cap_flags[] = { "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8", "apic", "10", "sep", "mtrr", "pge", "mca", "cmov", - "pat", "17", "psn", "19", "20", "21", "22", "mmx", - "24", "kni", "26", "27", "28", "29", "30", "31" + "16", "pse36", "psn", "19", "20", "21", "22", "mmx", + "24", "xmm", "26", "27", "28", "29", "30", "31" }; struct cpuinfo_x86 *c = cpu_data; int i, n; - for(n=0; n<NR_CPUS; n++, c++) { -#ifdef __SMP__ + for (n = 0; n < NR_CPUS; n++, c++) { +#ifdef CONFIG_SMP if (!(cpu_online_map & (1<<n))) continue; #endif @@ -1430,9 +1455,8 @@ int get_cpuinfo(char * buffer) break; case X86_VENDOR_INTEL: - x86_cap_flags[17] = "pse36"; - x86_cap_flags[18] = "psn"; - x86_cap_flags[24] = "osfxsr"; + x86_cap_flags[16] = "pat"; + x86_cap_flags[24] = "fxsr"; break; case X86_VENDOR_CENTAUR: @@ -1496,14 +1520,14 @@ void cpu_init (void) int nr = smp_processor_id(); struct tss_struct * t = &init_tss[nr]; - if (test_and_set_bit(nr,&cpu_initialized)) { + if (test_and_set_bit(nr, &cpu_initialized)) { printk("CPU#%d already initialized!\n", nr); for (;;) __sti(); } cpus_initialized++; printk("Initializing CPU#%d\n", nr); - if (boot_cpu_data.x86_capability & X86_FEATURE_PSE) + if (cpu_has_pse) clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE); __asm__ __volatile__("lgdt %0": "=m" (gdt_descr)); diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index a973746b9..18de47dd4 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -19,6 +19,7 @@ #include <linux/ptrace.h> #include <linux/unistd.h> #include <linux/stddef.h> +#include <linux/highuid.h> #include <asm/ucontext.h> #include <asm/uaccess.h> @@ -642,6 +643,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) info.si_code = SI_USER; info.si_pid = current->p_pptr->pid; info.si_uid = current->p_pptr->uid; + info.si_uid16 = high2lowuid(current->p_pptr->uid); } /* If the (new) signal is now blocked, requeue it. */ diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 9acf81556..05e0d1d23 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -2,7 +2,7 @@ * Intel SMP support routines. * * (c) 1995 Alan Cox, Building #3 <alan@redhat.com> - * (c) 1998-99 Ingo Molnar <mingo@redhat.com> + * (c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com> * * This code is released under the GNU public license version 2 or * later. @@ -11,18 +11,18 @@ #include <linux/init.h> #include <linux/mm.h> -#include <linux/spinlock.h> -#include <linux/kernel_stat.h> -#include <linux/smp_lock.h> #include <linux/irq.h> - #include <linux/delay.h> +#include <linux/spinlock.h> +#include <linux/smp_lock.h> +#include <linux/kernel_stat.h> #include <linux/mc146818rtc.h> + #include <asm/mtrr.h> #include <asm/pgalloc.h> /* - * Some notes on processor bugs: + * Some notes on x86 processor bugs affecting SMP operation: * * Pentium, Pentium Pro, II, III (and all CPUs) have bugs. * The Linux implications for SMP are handled as follows: @@ -381,7 +381,7 @@ void flush_tlb_page(struct vm_area_struct * vma, unsigned long va) static inline void do_flush_tlb_all_local(void) { - local_flush_tlb(); + __flush_tlb_all(); if (!current->mm && current->active_mm) { unsigned long cpu = smp_processor_id(); @@ -397,9 +397,7 @@ static void flush_tlb_all_ipi(void* info) void flush_tlb_all(void) { - if (cpu_online_map ^ (1 << smp_processor_id())) - while (smp_call_function (flush_tlb_all_ipi,0,0,1) == -EBUSY) - mb(); + smp_call_function (flush_tlb_all_ipi,0,1,1); do_flush_tlb_all_local(); } @@ -438,50 +436,44 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic, * [SUMMARY] Run a function on all other CPUs. * <func> The function to run. This must be fast and non-blocking. * <info> An arbitrary pointer to pass to the function. - * <nonatomic> If true, we might schedule away to lock the mutex + * <nonatomic> currently unused. * <wait> If true, wait (atomically) until function has completed on other CPUs. * [RETURNS] 0 on success, else a negative status code. Does not return until * remote CPUs are nearly ready to execute <<func>> or are or have executed. + * + * You must not call this function with disabled interrupts or from a + * hardware interrupt handler, you may call it from a bottom half handler. */ { struct call_data_struct data; int ret, cpus = smp_num_cpus-1; - static DECLARE_MUTEX(lock); - unsigned long timeout; + static spinlock_t lock = SPIN_LOCK_UNLOCKED; - if (nonatomic) - down(&lock); - else - if (down_trylock(&lock)) - return -EBUSY; + if(cpus == 0) + return 0; - call_data = &data; data.func = func; data.info = info; atomic_set(&data.started, 0); data.wait = wait; if (wait) atomic_set(&data.finished, 0); - mb(); + spin_lock_bh(&lock); + call_data = &data; /* Send a message to all other CPUs and wait for them to respond */ send_IPI_allbutself(CALL_FUNCTION_VECTOR); /* Wait for response */ - timeout = jiffies + HZ; - while ((atomic_read(&data.started) != cpus) - && time_before(jiffies, timeout)) + /* FIXME: lock-up detection, backtrace on lock-up */ + while(atomic_read(&data.started) != cpus) barrier(); - ret = -ETIMEDOUT; - if (atomic_read(&data.started) != cpus) - goto out; + ret = 0; if (wait) while (atomic_read(&data.finished) != cpus) barrier(); -out: - call_data = NULL; - up(&lock); + spin_unlock_bh(&lock); return 0; } @@ -504,14 +496,12 @@ static void stop_this_cpu (void * dummy) void smp_send_stop(void) { - unsigned long flags; + smp_call_function(stop_this_cpu, NULL, 1, 0); + smp_num_cpus = 1; - __save_flags(flags); __cli(); - smp_call_function(stop_this_cpu, NULL, 1, 0); disable_local_APIC(); - __restore_flags(flags); - + __sti(); } /* @@ -561,431 +551,3 @@ asmlinkage void smp_call_function_interrupt(void) atomic_inc(&call_data->finished); } -/* - * This interrupt should _never_ happen with our APIC/SMP architecture - */ -asmlinkage void smp_spurious_interrupt(void) -{ - ack_APIC_irq(); - /* see sw-dev-man vol 3, chapter 7.4.13.5 */ - printk("spurious APIC interrupt on CPU#%d, should never happen.\n", - smp_processor_id()); -} - -/* - * This interrupt should never happen with our APIC/SMP architecture - */ - -static spinlock_t err_lock = SPIN_LOCK_UNLOCKED; - -asmlinkage void smp_error_interrupt(void) -{ - unsigned long v; - - spin_lock(&err_lock); - - v = apic_read(APIC_ESR); - printk("APIC error interrupt on CPU#%d, should never happen.\n", - smp_processor_id()); - printk("... APIC ESR0: %08lx\n", v); - - apic_write(APIC_ESR, 0); - v |= apic_read(APIC_ESR); - printk("... APIC ESR1: %08lx\n", v); - /* - * Be a bit more verbose. (multiple bits can be set) - */ - if (v & 0x01) - printk("... bit 0: APIC Send CS Error (hw problem).\n"); - if (v & 0x02) - printk("... bit 1: APIC Receive CS Error (hw problem).\n"); - if (v & 0x04) - printk("... bit 2: APIC Send Accept Error.\n"); - if (v & 0x08) - printk("... bit 3: APIC Receive Accept Error.\n"); - if (v & 0x10) - printk("... bit 4: Reserved!.\n"); - if (v & 0x20) - printk("... bit 5: Send Illegal Vector (kernel bug).\n"); - if (v & 0x40) - printk("... bit 6: Received Illegal Vector.\n"); - if (v & 0x80) - printk("... bit 7: Illegal Register Address.\n"); - - ack_APIC_irq(); - - irq_err_count++; - - spin_unlock(&err_lock); -} - -/* - * This part sets up the APIC 32 bit clock in LVTT1, with HZ interrupts - * per second. We assume that the caller has already set up the local - * APIC. - * - * The APIC timer is not exactly sync with the external timer chip, it - * closely follows bus clocks. - */ - -int prof_multiplier[NR_CPUS] = { 1, }; -int prof_old_multiplier[NR_CPUS] = { 1, }; -int prof_counter[NR_CPUS] = { 1, }; - -/* - * The timer chip is already set up at HZ interrupts per second here, - * but we do not accept timer interrupts yet. We only allow the BP - * to calibrate. - */ -static unsigned int __init get_8254_timer_count(void) -{ - extern rwlock_t xtime_lock; - unsigned long flags; - - unsigned int count; - - write_lock_irqsave(&xtime_lock, flags); - - outb_p(0x00, 0x43); - count = inb_p(0x40); - count |= inb_p(0x40) << 8; - - write_unlock_irqrestore(&xtime_lock, flags); - - return count; -} - -void __init wait_8254_wraparound(void) -{ - unsigned int curr_count, prev_count=~0; - int delta; - - curr_count = get_8254_timer_count(); - - do { - prev_count = curr_count; - curr_count = get_8254_timer_count(); - delta = curr_count-prev_count; - - /* - * This limit for delta seems arbitrary, but it isn't, it's - * slightly above the level of error a buggy Mercury/Neptune - * chipset timer can cause. - */ - - } while (delta<300); -} - -/* - * This function sets up the local APIC timer, with a timeout of - * 'clocks' APIC bus clock. During calibration we actually call - * this function twice on the boot CPU, once with a bogus timeout - * value, second time for real. The other (noncalibrating) CPUs - * call this function only once, with the real, calibrated value. - * - * We do reads before writes even if unnecessary, to get around the - * P5 APIC double write bug. - */ - -#define APIC_DIVISOR 16 - -void __setup_APIC_LVTT(unsigned int clocks) -{ - unsigned int lvtt1_value, tmp_value; - - tmp_value = apic_read(APIC_LVTT); - lvtt1_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | - APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR; - apic_write(APIC_LVTT, lvtt1_value); - - /* - * Divide PICLK by 16 - */ - tmp_value = apic_read(APIC_TDCR); - apic_write(APIC_TDCR, (tmp_value - & ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE)) - | APIC_TDR_DIV_16); - - tmp_value = apic_read(APIC_TMICT); - apic_write(APIC_TMICT, clocks/APIC_DIVISOR); -} - -void setup_APIC_timer(void * data) -{ - unsigned int clocks = (unsigned int) data, slice, t0, t1, nr; - unsigned long flags; - int delta; - - __save_flags(flags); - __sti(); - /* - * ok, Intel has some smart code in their APIC that knows - * if a CPU was in 'hlt' lowpower mode, and this increases - * its APIC arbitration priority. To avoid the external timer - * IRQ APIC event being in synchron with the APIC clock we - * introduce an interrupt skew to spread out timer events. - * - * The number of slices within a 'big' timeslice is smp_num_cpus+1 - */ - - slice = clocks / (smp_num_cpus+1); - nr = cpu_number_map[smp_processor_id()] + 1; - printk("cpu: %d, clocks: %d, slice: %d, nr: %d.\n", - smp_processor_id(), clocks, slice, nr); - /* - * Wait for IRQ0's slice: - */ - wait_8254_wraparound(); - - __setup_APIC_LVTT(clocks); - - t0 = apic_read(APIC_TMCCT)*APIC_DIVISOR; - do { - t1 = apic_read(APIC_TMCCT)*APIC_DIVISOR; - delta = (int)(t0 - t1 - slice*nr); - } while (delta < 0); - - __setup_APIC_LVTT(clocks); - - printk("CPU%d<C0:%d,C:%d,D:%d,S:%d,C:%d>\n", - smp_processor_id(), t0, t1, delta, slice, clocks); - - __restore_flags(flags); -} - -/* - * In this function we calibrate APIC bus clocks to the external - * timer. Unfortunately we cannot use jiffies and the timer irq - * to calibrate, since some later bootup code depends on getting - * the first irq? Ugh. - * - * We want to do the calibration only once since we - * want to have local timer irqs syncron. CPUs connected - * by the same APIC bus have the very same bus frequency. - * And we want to have irqs off anyways, no accidental - * APIC irq that way. - */ - -int __init calibrate_APIC_clock(void) -{ - unsigned long long t1 = 0, t2 = 0; - long tt1, tt2; - long result; - int i; - const int LOOPS = HZ/10; - - printk("calibrating APIC timer ... "); - - /* - * Put whatever arbitrary (but long enough) timeout - * value into the APIC clock, we just want to get the - * counter running for calibration. - */ - __setup_APIC_LVTT(1000000000); - - /* - * The timer chip counts down to zero. Let's wait - * for a wraparound to start exact measurement: - * (the current tick might have been already half done) - */ - - wait_8254_wraparound(); - - /* - * We wrapped around just now. Let's start: - */ - if (cpu_has_tsc) - rdtscll(t1); - tt1 = apic_read(APIC_TMCCT); - - /* - * Let's wait LOOPS wraprounds: - */ - for (i = 0; i < LOOPS; i++) - wait_8254_wraparound(); - - tt2 = apic_read(APIC_TMCCT); - if (cpu_has_tsc) - rdtscll(t2); - - /* - * The APIC bus clock counter is 32 bits only, it - * might have overflown, but note that we use signed - * longs, thus no extra care needed. - * - * underflown to be exact, as the timer counts down ;) - */ - - result = (tt1-tt2)*APIC_DIVISOR/LOOPS; - - if (cpu_has_tsc) - printk("\n..... CPU clock speed is %ld.%04ld MHz.\n", - ((long)(t2-t1)/LOOPS)/(1000000/HZ), - ((long)(t2-t1)/LOOPS)%(1000000/HZ)); - - printk("..... host bus clock speed is %ld.%04ld MHz.\n", - result/(1000000/HZ), - result%(1000000/HZ)); - - return result; -} - -static unsigned int calibration_result; - -void __init setup_APIC_clocks(void) -{ - unsigned long flags; - - __save_flags(flags); - __cli(); - - calibration_result = calibrate_APIC_clock(); - - smp_call_function(setup_APIC_timer, (void *)calibration_result, 1, 1); - - /* - * Now set up the timer for real. - */ - setup_APIC_timer((void *)calibration_result); - - __restore_flags(flags); -} - -/* - * the frequency of the profiling timer can be changed - * by writing a multiplier value into /proc/profile. - */ -int setup_profiling_timer(unsigned int multiplier) -{ - int i; - - /* - * Sanity check. [at least 500 APIC cycles should be - * between APIC interrupts as a rule of thumb, to avoid - * irqs flooding us] - */ - if ( (!multiplier) || (calibration_result/multiplier < 500)) - return -EINVAL; - - /* - * Set the new multiplier for each CPU. CPUs don't start using the - * new values until the next timer interrupt in which they do process - * accounting. At that time they also adjust their APIC timers - * accordingly. - */ - for (i = 0; i < NR_CPUS; ++i) - prof_multiplier[i] = multiplier; - - return 0; -} - -#undef APIC_DIVISOR - -/* - * Local timer interrupt handler. It does both profiling and - * process statistics/rescheduling. - * - * We do profiling in every local tick, statistics/rescheduling - * happen only every 'profiling multiplier' ticks. The default - * multiplier is 1 and it can be changed by writing the new multiplier - * value into /proc/profile. - */ - -inline void smp_local_timer_interrupt(struct pt_regs * regs) -{ - int user = (user_mode(regs) != 0); - int cpu = smp_processor_id(); - - /* - * The profiling function is SMP safe. (nothing can mess - * around with "current", and the profiling counters are - * updated with atomic operations). This is especially - * useful with a profiling multiplier != 1 - */ - if (!user) - x86_do_profile(regs->eip); - - if (--prof_counter[cpu] <= 0) { - int system = 1 - user; - struct task_struct * p = current; - - /* - * The multiplier may have changed since the last time we got - * to this point as a result of the user writing to - * /proc/profile. In this case we need to adjust the APIC - * timer accordingly. - * - * Interrupts are already masked off at this point. - */ - prof_counter[cpu] = prof_multiplier[cpu]; - if (prof_counter[cpu] != prof_old_multiplier[cpu]) { - __setup_APIC_LVTT(calibration_result/prof_counter[cpu]); - prof_old_multiplier[cpu] = prof_counter[cpu]; - } - - /* - * After doing the above, we need to make like - * a normal interrupt - otherwise timer interrupts - * ignore the global interrupt lock, which is the - * WrongThing (tm) to do. - */ - - irq_enter(cpu, 0); - update_one_process(p, 1, user, system, cpu); - if (p->pid) { - p->counter -= 1; - if (p->counter <= 0) { - p->counter = 0; - p->need_resched = 1; - } - if (p->priority < DEF_PRIORITY) { - kstat.cpu_nice += user; - kstat.per_cpu_nice[cpu] += user; - } else { - kstat.cpu_user += user; - kstat.per_cpu_user[cpu] += user; - } - kstat.cpu_system += system; - kstat.per_cpu_system[cpu] += system; - - } - irq_exit(cpu, 0); - } - - /* - * We take the 'long' return path, and there every subsystem - * grabs the apropriate locks (kernel lock/ irq lock). - * - * we might want to decouple profiling from the 'long path', - * and do the profiling totally in assembly. - * - * Currently this isn't too much of an issue (performance wise), - * we can take more than 100K local irqs per second on a 100 MHz P5. - */ -} - -/* - * Local APIC timer interrupt. This is the most natural way for doing - * local interrupts, but local timer interrupts can be emulated by - * broadcast interrupts too. [in case the hw doesnt support APIC timers] - * - * [ if a single-CPU system runs an SMP kernel then we call the local - * interrupt as well. Thus we cannot inline the local irq ... ] - */ -unsigned int apic_timer_irqs [NR_CPUS] = { 0, }; - -void smp_apic_timer_interrupt(struct pt_regs * regs) -{ - /* - * the NMI deadlock-detector uses this. - */ - apic_timer_irqs[smp_processor_id()]++; - - /* - * NOTE! We'd better ACK the irq immediately, - * because timer handling can be slow. - */ - ack_APIC_irq(); - smp_local_timer_interrupt(regs); -} - diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 811f00f38..3ff5cc002 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -1,8 +1,8 @@ /* - * Intel MP v1.1/v1.4 specification compliant parsing routines. + * x86 SMP booting functions * * (c) 1995 Alan Cox, Building #3 <alan@redhat.com> - * (c) 1998, 1999 Ingo Molnar <mingo@redhat.com> + * (c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com> * * Much of the core SMP work is based on previous work by Thomas Radke, to * whom a great many thanks are extended. @@ -26,10 +26,8 @@ * Alan Cox : Dumb bug: 'B' step PPro's are fine * Ingo Molnar : Added APIC timers, based on code * from Jose Renau - * Alan Cox : Added EBDA scanning * Ingo Molnar : various cleanups and rewrites * Tigran Aivazian : fixed "0.00 in /proc/uptime on SMP" bug. - * Maciej W. Rozycki : Bits for genuine 82489DX timers */ #include <linux/config.h> @@ -51,72 +49,28 @@ static int smp_b_stepping = 0; /* Setup configured maximum number of CPUs to activate */ static int max_cpus = -1; -/* 1 if "noapic" boot option passed */ -int skip_ioapic_setup = 0; /* Total count of live CPUs */ -int smp_num_cpus = 0; -/* Internal processor count */ -static unsigned int num_processors = 1; +int smp_num_cpus = 1; -/* Have we found an SMP box */ -int smp_found_config = 0; - -/* Bitmask of physically existing CPUs */ -unsigned long cpu_present_map = 0; /* Bitmask of currently online CPUs */ unsigned long cpu_online_map = 0; -/* which CPU maps to which logical number */ -volatile int cpu_number_map[NR_CPUS]; -/* which logical number maps to which CPU */ -volatile int __cpu_logical_map[NR_CPUS]; +/* which CPU (physical APIC ID) maps to which logical CPU number */ +volatile int x86_apicid_to_cpu[NR_CPUS]; +/* which logical CPU number maps to which CPU (physical APIC ID) */ +volatile int x86_cpu_to_apicid[NR_CPUS]; static volatile unsigned long cpu_callin_map = 0; static volatile unsigned long cpu_callout_map = 0; /* Per CPU bogomips and other parameters */ struct cpuinfo_x86 cpu_data[NR_CPUS]; -/* Processor that is doing the boot up */ -static unsigned int boot_cpu_id = 0; -/* Tripped once we need to start cross invalidating */ -static int smp_activated = 0; /* Set when the idlers are all forked */ int smp_threads_ready = 0; /* - * Various Linux-internal data structures created from the - * MP-table. - */ -int apic_version [NR_CPUS]; -int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, }; -extern int nr_ioapics; -extern struct mpc_config_ioapic mp_ioapics [MAX_IO_APICS]; -extern int mp_irq_entries; -extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES]; -extern int mpc_default_type; -int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, }; -int mp_current_pci_id = 0; -unsigned long mp_lapic_addr = 0; -int pic_mode; - -extern void cache_APIC_registers (void); - -#define SMP_DEBUG 1 - -#if SMP_DEBUG -#define dprintk(x...) printk(##x) -#else -#define dprintk(x...) -#endif - -/* - * IA s/w dev Vol 3, Section 7.4 - */ -#define APIC_DEFAULT_PHYS_BASE 0xfee00000 - -/* * Setup routine for controlling SMP activation * * Command-line option of "nosmp" or "maxcpus=0" will disable SMP @@ -144,471 +98,6 @@ static int __init maxcpus(char *str) __setup("maxcpus=", maxcpus); /* - * Intel MP BIOS table parsing routines: - */ - -#ifndef CONFIG_X86_VISWS_APIC -/* - * Checksum an MP configuration block. - */ - -static int __init mpf_checksum(unsigned char *mp, int len) -{ - int sum=0; - while(len--) - sum+=*mp++; - return sum&0xFF; -} - -/* - * Processor encoding in an MP configuration block - */ - -static char __init *mpc_family(int family,int model) -{ - static char n[32]; - static char *model_defs[]= - { - "80486DX","80486DX", - "80486SX","80486DX/2 or 80487", - "80486SL","80486SX/2", - "Unknown","80486DX/2-WB", - "80486DX/4","80486DX/4-WB" - }; - - switch (family) { - case 0x04: - if (model < 10) - return model_defs[model]; - break; - - case 0x05: - return("Pentium(tm)"); - - case 0x06: - return("Pentium(tm) Pro"); - - case 0x0F: - if (model == 0x0F) - return("Special controller"); - } - sprintf(n,"Unknown CPU [%d:%d]",family, model); - return n; -} - -static void __init MP_processor_info (struct mpc_config_processor *m) -{ - int ver; - - if (!(m->mpc_cpuflag & CPU_ENABLED)) - return; - - printk("Processor #%d %s APIC version %d\n", - m->mpc_apicid, - mpc_family( (m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 , - (m->mpc_cpufeature & CPU_MODEL_MASK)>>4), - m->mpc_apicver); - -#ifdef SMP_DEBUG - if (m->mpc_featureflag&(1<<0)) - printk(" Floating point unit present.\n"); - if (m->mpc_featureflag&(1<<7)) - printk(" Machine Exception supported.\n"); - if (m->mpc_featureflag&(1<<8)) - printk(" 64 bit compare & exchange supported.\n"); - if (m->mpc_featureflag&(1<<9)) - printk(" Internal APIC present.\n"); -#endif - - if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) { - dprintk(" Bootup CPU\n"); - boot_cpu_id = m->mpc_apicid; - } else - /* Boot CPU already counted */ - num_processors++; - - if (m->mpc_apicid > NR_CPUS) { - printk("Processor #%d unused. (Max %d processors).\n", - m->mpc_apicid, NR_CPUS); - return; - } - ver = m->mpc_apicver; - - cpu_present_map |= (1<<m->mpc_apicid); - /* - * Validate version - */ - if (ver == 0x0) { - printk("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid); - ver = 0x10; - } - apic_version[m->mpc_apicid] = ver; -} - -static void __init MP_bus_info (struct mpc_config_bus *m) -{ - char str[7]; - - memcpy(str, m->mpc_bustype, 6); - str[6] = 0; - dprintk("Bus #%d is %s\n", m->mpc_busid, str); - - if (strncmp(str, "ISA", 3) == 0) { - mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA; - } else { - if (strncmp(str, "EISA", 4) == 0) { - mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA; - } else { - if (strncmp(str, "PCI", 3) == 0) { - mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI; - mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id; - mp_current_pci_id++; - } else { - printk("Unknown bustype %s\n", str); - panic("cannot handle bus - mail to linux-smp@vger.rutgers.edu"); - } } } -} - -static void __init MP_ioapic_info (struct mpc_config_ioapic *m) -{ - if (!(m->mpc_flags & MPC_APIC_USABLE)) - return; - - printk("I/O APIC #%d Version %d at 0x%lX.\n", - m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr); - if (nr_ioapics >= MAX_IO_APICS) { - printk("Max # of I/O APICs (%d) exceeded (found %d).\n", - MAX_IO_APICS, nr_ioapics); - panic("Recompile kernel with bigger MAX_IO_APICS!.\n"); - } - mp_ioapics[nr_ioapics] = *m; - nr_ioapics++; -} - -static void __init MP_intsrc_info (struct mpc_config_intsrc *m) -{ - mp_irqs [mp_irq_entries] = *m; - if (++mp_irq_entries == MAX_IRQ_SOURCES) - panic("Max # of irq sources exceeded!!\n"); -} - -static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m) -{ - /* - * Well it seems all SMP boards in existence - * use ExtINT/LVT1 == LINT0 and - * NMI/LVT2 == LINT1 - the following check - * will show us if this assumptions is false. - * Until then we do not have to add baggage. - */ - if ((m->mpc_irqtype == mp_ExtINT) && - (m->mpc_destapiclint != 0)) - BUG(); - if ((m->mpc_irqtype == mp_NMI) && - (m->mpc_destapiclint != 1)) - BUG(); -} - -/* - * Read/parse the MPC - */ - -static int __init smp_read_mpc(struct mp_config_table *mpc) -{ - char str[16]; - int count=sizeof(*mpc); - unsigned char *mpt=((unsigned char *)mpc)+count; - - if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4)) - { - panic("SMP mptable: bad signature [%c%c%c%c]!\n", - mpc->mpc_signature[0], - mpc->mpc_signature[1], - mpc->mpc_signature[2], - mpc->mpc_signature[3]); - return 1; - } - if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length)) - { - panic("SMP mptable: checksum error!\n"); - return 1; - } - if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04) - { - printk("Bad Config Table version (%d)!!\n",mpc->mpc_spec); - return 1; - } - memcpy(str,mpc->mpc_oem,8); - str[8]=0; - printk("OEM ID: %s ",str); - - memcpy(str,mpc->mpc_productid,12); - str[12]=0; - printk("Product ID: %s ",str); - - printk("APIC at: 0x%lX\n",mpc->mpc_lapic); - - /* save the local APIC address, it might be non-default */ - mp_lapic_addr = mpc->mpc_lapic; - - /* - * Now process the configuration blocks. - */ - while (count < mpc->mpc_length) { - switch(*mpt) { - case MP_PROCESSOR: - { - struct mpc_config_processor *m= - (struct mpc_config_processor *)mpt; - MP_processor_info(m); - mpt += sizeof(*m); - count += sizeof(*m); - break; - } - case MP_BUS: - { - struct mpc_config_bus *m= - (struct mpc_config_bus *)mpt; - MP_bus_info(m); - mpt += sizeof(*m); - count += sizeof(*m); - break; - } - case MP_IOAPIC: - { - struct mpc_config_ioapic *m= - (struct mpc_config_ioapic *)mpt; - MP_ioapic_info(m); - mpt+=sizeof(*m); - count+=sizeof(*m); - break; - } - case MP_INTSRC: - { - struct mpc_config_intsrc *m= - (struct mpc_config_intsrc *)mpt; - - MP_intsrc_info(m); - mpt+=sizeof(*m); - count+=sizeof(*m); - break; - } - case MP_LINTSRC: - { - struct mpc_config_lintsrc *m= - (struct mpc_config_lintsrc *)mpt; - MP_lintsrc_info(m); - mpt+=sizeof(*m); - count+=sizeof(*m); - break; - } - } - } - return num_processors; -} - -/* - * Scan the memory blocks for an SMP configuration block. - */ -static int __init smp_get_mpf(struct intel_mp_floating *mpf) -{ - printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); - if (mpf->mpf_feature2 & (1<<7)) { - printk(" IMCR and PIC compatibility mode.\n"); - pic_mode = 1; - } else { - printk(" Virtual Wire compatibility mode.\n"); - pic_mode = 0; - } - smp_found_config = 1; - /* - * default CPU id - if it's different in the mptable - * then we change it before first using it. - */ - boot_cpu_id = 0; - /* - * Now see if we need to read further. - */ - if (mpf->mpf_feature1 != 0) { - /* - * local APIC has default address - */ - mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; - - /* - * 2 CPUs, numbered 0 & 1. - */ - cpu_present_map = 3; - num_processors = 2; - - nr_ioapics = 1; - mp_ioapics[0].mpc_apicaddr = 0xFEC00000; - /* - * Save the default type number, we - * need it later to set the IO-APIC - * up properly: - */ - mpc_default_type = mpf->mpf_feature1; - - printk("Bus #0 is "); - } - - switch (mpf->mpf_feature1) { - case 1: - case 5: - printk("ISA\n"); - break; - case 2: - printk("EISA with no IRQ0 and no IRQ13 DMA chaining\n"); - break; - case 6: - case 3: - printk("EISA\n"); - break; - case 4: - case 7: - printk("MCA\n"); - break; - case 0: - if (!mpf->mpf_physptr) - BUG(); - break; - default: - printk("???\nUnknown standard configuration %d\n", - mpf->mpf_feature1); - return 1; - } - if (mpf->mpf_feature1 > 4) { - printk("Bus #1 is PCI\n"); - - /* - * Set local APIC version to the integrated form. - * It's initialized to zero otherwise, representing - * a discrete 82489DX. - */ - apic_version[0] = 0x10; - apic_version[1] = 0x10; - } - /* - * Read the physical hardware table. Anything here will override the - * defaults. - */ - if (mpf->mpf_physptr) - smp_read_mpc((void *)mpf->mpf_physptr); - - __cpu_logical_map[0] = boot_cpu_id; - global_irq_holder = boot_cpu_id; - current->processor = boot_cpu_id; - - printk("Processors: %d\n", num_processors); - /* - * Only use the first configuration found. - */ - return 1; -} - -static int __init smp_scan_config(unsigned long base, unsigned long length) -{ - unsigned long *bp = phys_to_virt(base); - struct intel_mp_floating *mpf; - - dprintk("Scan SMP from %p for %ld bytes.\n", bp,length); - if (sizeof(*mpf) != 16) - printk("Error: MPF size\n"); - - while (length > 0) { - mpf = (struct intel_mp_floating *)bp; - if ((*bp == SMP_MAGIC_IDENT) && - (mpf->mpf_length == 1) && - !mpf_checksum((unsigned char *)bp, 16) && - ((mpf->mpf_specification == 1) - || (mpf->mpf_specification == 4)) ) { - - printk("found SMP MP-table at %08ld\n", - virt_to_phys(mpf)); - smp_get_mpf(mpf); - return 1; - } - bp += 4; - length -= 16; - } - return 0; -} - -void __init init_intel_smp (void) -{ - unsigned int address; - - /* - * FIXME: Linux assumes you have 640K of base ram.. - * this continues the error... - * - * 1) Scan the bottom 1K for a signature - * 2) Scan the top 1K of base RAM - * 3) Scan the 64K of bios - */ - if (smp_scan_config(0x0,0x400) || - smp_scan_config(639*0x400,0x400) || - smp_scan_config(0xF0000,0x10000)) - return; - /* - * If it is an SMP machine we should know now, unless the - * configuration is in an EISA/MCA bus machine with an - * extended bios data area. - * - * there is a real-mode segmented pointer pointing to the - * 4K EBDA area at 0x40E, calculate and scan it here. - * - * NOTE! There are Linux loaders that will corrupt the EBDA - * area, and as such this kind of SMP config may be less - * trustworthy, simply because the SMP table may have been - * stomped on during early boot. These loaders are buggy and - * should be fixed. - */ - - address = *(unsigned short *)phys_to_virt(0x40E); - address <<= 4; - smp_scan_config(address, 0x1000); - if (smp_found_config) - printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.rutgers.edu if you experience SMP problems!\n"); -} - -#else - -/* - * The Visual Workstation is Intel MP compliant in the hardware - * sense, but it doesnt have a BIOS(-configuration table). - * No problem for Linux. - */ -void __init init_visws_smp(void) -{ - smp_found_config = 1; - - cpu_present_map |= 2; /* or in id 1 */ - apic_version[1] |= 0x10; /* integrated APIC */ - apic_version[0] |= 0x10; - - mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; -} - -#endif - -/* - * - Intel MP Configuration Table - * - or SGI Visual Workstation configuration - */ -void __init init_smp_config (void) -{ -#ifndef CONFIG_VISWS - init_intel_smp(); -#else - init_visws_smp(); -#endif -} - - - -/* * Trampoline 80x86 program as an array. */ @@ -688,209 +177,12 @@ void __init smp_commence(void) /* * Lets the callins below out of their loop. */ - dprintk("Setting commenced=1, go go go\n"); + Dprintk("Setting commenced=1, go go go\n"); wmb(); atomic_set(&smp_commenced,1); } -extern void __error_in_io_apic_c(void); - - -int get_maxlvt(void) -{ - unsigned int v, ver, maxlvt; - - v = apic_read(APIC_LVR); - ver = GET_APIC_VERSION(v); - /* 82489DXs do not report # of LVT entries. */ - maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(v) : 2; - return maxlvt; -} - -void disable_local_APIC (void) -{ - unsigned long value; - int maxlvt; - - /* - * Disable APIC - */ - value = apic_read(APIC_SPIV); - value &= ~(1<<8); - apic_write(APIC_SPIV,value); - - /* - * Clean APIC state for other OSs: - */ - value = apic_read(APIC_SPIV); - value &= ~(1<<8); - apic_write(APIC_SPIV,value); - maxlvt = get_maxlvt(); - apic_write_around(APIC_LVTT, 0x00010000); - apic_write_around(APIC_LVT0, 0x00010000); - apic_write_around(APIC_LVT1, 0x00010000); - if (maxlvt >= 3) - apic_write_around(APIC_LVTERR, 0x00010000); - if (maxlvt >= 4) - apic_write_around(APIC_LVTPC, 0x00010000); -} - -void __init setup_local_APIC (void) -{ - unsigned long value, ver, maxlvt; - - if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f) - __error_in_io_apic_c(); - - value = apic_read(APIC_SPIV); - /* - * Enable APIC - */ - value |= (1<<8); - - /* - * Some unknown Intel IO/APIC (or APIC) errata is biting us with - * certain networking cards. If high frequency interrupts are - * happening on a particular IOAPIC pin, plus the IOAPIC routing - * entry is masked/unmasked at a high rate as well then sooner or - * later IOAPIC line gets 'stuck', no more interrupts are received - * from the device. If focus CPU is disabled then the hang goes - * away, oh well :-( - * - * [ This bug can be reproduced easily with a level-triggered - * PCI Ne2000 networking cards and PII/PIII processors, dual - * BX chipset. ] - */ -#if 0 - /* Enable focus processor (bit==0) */ - value &= ~(1<<9); -#else - /* Disable focus processor (bit==1) */ - value |= (1<<9); -#endif - /* - * Set spurious IRQ vector - */ - value |= SPURIOUS_APIC_VECTOR; - apic_write(APIC_SPIV,value); - - /* - * Set up LVT0, LVT1: - * - * set up through-local-APIC on the BP's LINT0. This is not - * strictly necessery in pure symmetric-IO mode, but sometimes - * we delegate interrupts to the 8259A. - */ - if (hard_smp_processor_id() == boot_cpu_id) { - value = 0x00000700; - printk("enabled ExtINT on CPU#%d\n", hard_smp_processor_id()); - } else { - value = 0x00010700; - printk("masked ExtINT on CPU#%d\n", hard_smp_processor_id()); - } - apic_write_around(APIC_LVT0,value); - - /* - * only the BP should see the LINT1 NMI signal, obviously. - */ - if (hard_smp_processor_id() == boot_cpu_id) - value = 0x00000400; // unmask NMI - else - value = 0x00010400; // mask NMI - apic_write_around(APIC_LVT1,value); - - value = apic_read(APIC_LVR); - ver = GET_APIC_VERSION(value); - if (APIC_INTEGRATED(ver)) { /* !82489DX */ - maxlvt = get_maxlvt(); - /* - * Due to the Pentium erratum 3AP. - */ - if (maxlvt > 3) { - apic_readaround(APIC_SPIV); // not strictly necessery - apic_write(APIC_ESR, 0); - } - value = apic_read(APIC_ESR); - printk("ESR value before enabling vector: %08lx\n", value); - - value = apic_read(APIC_LVTERR); - value = ERROR_APIC_VECTOR; // enables sending errors - apic_write(APIC_LVTERR,value); - /* - * spec says clear errors after enabling vector. - */ - if (maxlvt != 3) { - apic_readaround(APIC_SPIV); - apic_write(APIC_ESR, 0); - } - value = apic_read(APIC_ESR); - printk("ESR value after enabling vector: %08lx\n", value); - } else - printk("No ESR for 82489DX.\n"); - - /* - * Set Task Priority to 'accept all'. We never change this - * later on. - */ - value = apic_read(APIC_TASKPRI); - value &= ~APIC_TPRI_MASK; - apic_write(APIC_TASKPRI,value); - - /* - * Set up the logical destination ID and put the - * APIC into flat delivery mode. - */ - value = apic_read(APIC_LDR); - value &= ~APIC_LDR_MASK; - value |= (1<<(smp_processor_id()+24)); - apic_write(APIC_LDR,value); - - value = apic_read(APIC_DFR); - value |= SET_APIC_DFR(0xf); - apic_write(APIC_DFR, value); -} - -void __init init_smp_mappings(void) -{ - unsigned long apic_phys; - - if (smp_found_config) { - apic_phys = mp_lapic_addr; - } else { - /* - * set up a fake all zeroes page to simulate the - * local APIC and another one for the IO-APIC. We - * could use the real zero-page, but it's safer - * this way if some buggy code writes to this page ... - */ - apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); - apic_phys = __pa(apic_phys); - } - set_fixmap(FIX_APIC_BASE, apic_phys); - dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys); - -#ifdef CONFIG_X86_IO_APIC - { - unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; - int i; - - for (i = 0; i < nr_ioapics; i++) { - if (smp_found_config) { - ioapic_phys = mp_ioapics[i].mpc_apicaddr; - } else { - ioapic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE); - ioapic_phys = __pa(ioapic_phys); - } - set_fixmap(idx,ioapic_phys); - dprintk("mapped IOAPIC to %08lx (%08lx)\n", - __fix_to_virt(idx), ioapic_phys); - idx++; - } - } -#endif -} - /* * TSC synchronization. * @@ -990,20 +282,14 @@ static void __init synchronize_tsc_bp (void) } sum = 0; - for (i = 0; i < NR_CPUS; i++) { - if (!(cpu_online_map & (1 << i))) - continue; - + for (i = 0; i < smp_num_cpus; i++) { t0 = tsc_values[i]; sum += t0; } avg = div64(sum, smp_num_cpus); sum = 0; - for (i = 0; i < NR_CPUS; i++) { - if (!(cpu_online_map & (1 << i))) - continue; - + for (i = 0; i < smp_num_cpus; i++) { delta = tsc_values[i] - avg; if (delta < 0) delta = -delta; @@ -1059,15 +345,20 @@ extern void calibrate_delay(void); void __init smp_callin(void) { - int cpuid; + int cpuid, phys_id; unsigned long timeout; /* * (This works even if the APIC is not enabled.) */ - cpuid = GET_APIC_ID(apic_read(APIC_ID)); - - dprintk("CPU#%d waiting for CALLOUT\n", cpuid); + phys_id = GET_APIC_ID(apic_read(APIC_ID)); + cpuid = current->processor; + if (test_and_set_bit(cpuid, &cpu_online_map)) { + printk("huh, phys CPU#%d, CPU#%d already present??\n", + phys_id, cpuid); + BUG(); + } + Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id); /* * STARTUP IPIs are fragile beasts as they might sometimes @@ -1102,7 +393,7 @@ void __init smp_callin(void) * boards) */ - dprintk("CALLIN, before setup_local_APIC().\n"); + Dprintk("CALLIN, before setup_local_APIC().\n"); setup_local_APIC(); sti(); @@ -1117,7 +408,7 @@ void __init smp_callin(void) * Get our bogomips. */ calibrate_delay(); - dprintk("Stack at about %p\n",&cpuid); + Dprintk("Stack at about %p\n",&cpuid); /* * Save our processor parameters @@ -1133,7 +424,7 @@ void __init smp_callin(void) * Synchronize the TSC with the BP */ if (cpu_has_tsc) - synchronize_tsc_ap (); + synchronize_tsc_ap(); } int cpucount = 0; @@ -1198,21 +489,21 @@ static int __init fork_by_hand(void) return do_fork(CLONE_VM|CLONE_PID, 0, ®s); } -static void __init do_boot_cpu(int i) +static void __init do_boot_cpu (int apicid) { unsigned long cfg; struct task_struct *idle; unsigned long send_status, accept_status; - int timeout, num_starts, j; + int timeout, num_starts, j, cpu; unsigned long start_eip; - cpucount++; + cpu = ++cpucount; /* * We can't use kernel_thread since we must avoid to * reschedule the child. */ if (fork_by_hand() < 0) - panic("failed fork for CPU %d", i); + panic("failed fork for CPU %d", cpu); /* * We remove it from the pidhash and the runqueue @@ -1220,23 +511,23 @@ static void __init do_boot_cpu(int i) */ idle = init_task.prev_task; if (!idle) - panic("No idle process for CPU %d", i); + panic("No idle process for CPU %d", cpu); - idle->processor = i; - __cpu_logical_map[cpucount] = i; - cpu_number_map[i] = cpucount; + idle->processor = cpu; + x86_cpu_to_apicid[cpu] = apicid; + x86_apicid_to_cpu[apicid] = cpu; idle->has_cpu = 1; /* we schedule the first task manually */ idle->thread.eip = (unsigned long) start_secondary; del_from_runqueue(idle); unhash_process(idle); - init_tasks[cpucount] = idle; + init_tasks[cpu] = idle; /* start_eip had better be page-aligned! */ start_eip = setup_trampoline(); /* So we see what's up */ - printk("Booting processor %d eip %lx\n", i, start_eip); + printk("Booting processor %d eip %lx\n", cpu, start_eip); stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle); /* @@ -1244,21 +535,20 @@ static void __init do_boot_cpu(int i) * the targeted processor. */ - dprintk("Setting warm reset code and vector.\n"); + Dprintk("Setting warm reset code and vector.\n"); CMOS_WRITE(0xa, 0xf); local_flush_tlb(); - dprintk("1.\n"); + Dprintk("1.\n"); *((volatile unsigned short *) phys_to_virt(0x469)) = start_eip >> 4; - dprintk("2.\n"); + Dprintk("2.\n"); *((volatile unsigned short *) phys_to_virt(0x467)) = start_eip & 0xf; - dprintk("3.\n"); + Dprintk("3.\n"); /* * Be paranoid about clearing APIC errors. */ - - if (APIC_INTEGRATED(apic_version[i])) { + if (APIC_INTEGRATED(apic_version[apicid])) { apic_readaround(APIC_SPIV); apic_write(APIC_ESR, 0); accept_status = (apic_read(APIC_ESR) & 0xEF); @@ -1274,7 +564,7 @@ static void __init do_boot_cpu(int i) * Starting actual IPI sequence... */ - dprintk("Asserting INIT.\n"); + Dprintk("Asserting INIT.\n"); /* * Turn INIT on @@ -1285,7 +575,7 @@ static void __init do_boot_cpu(int i) /* * Target chip */ - apic_write(APIC_ICR2, cfg | SET_APIC_DEST_FIELD(i)); + apic_write(APIC_ICR2, cfg | SET_APIC_DEST_FIELD(apicid)); /* * Send IPI @@ -1296,12 +586,12 @@ static void __init do_boot_cpu(int i) apic_write(APIC_ICR, cfg); udelay(200); - dprintk("Deasserting INIT.\n"); + Dprintk("Deasserting INIT.\n"); /* Target chip */ cfg = apic_read(APIC_ICR2); cfg &= 0x00FFFFFF; - apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); + apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(apicid)); /* Send IPI */ cfg = apic_read(APIC_ICR); @@ -1316,8 +606,7 @@ static void __init do_boot_cpu(int i) * If we don't have an integrated APIC, don't * send the STARTUP IPIs. */ - - if (APIC_INTEGRATED(apic_version[i])) + if (APIC_INTEGRATED(apic_version[apicid])) num_starts = 2; else num_starts = 0; @@ -1325,13 +614,14 @@ static void __init do_boot_cpu(int i) /* * Run STARTUP IPI loop. */ + Dprintk("#startup loops: %d.\n", num_starts); for (j = 1; j <= num_starts; j++) { - dprintk("Sending STARTUP #%d.\n",j); + Dprintk("Sending STARTUP #%d.\n",j); apic_readaround(APIC_SPIV); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); - dprintk("After apic_write.\n"); + Dprintk("After apic_write.\n"); /* * STARTUP IPI @@ -1340,7 +630,7 @@ static void __init do_boot_cpu(int i) /* Target chip */ cfg = apic_read(APIC_ICR2); cfg &= 0x00FFFFFF; - apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i)); + apic_write(APIC_ICR2, cfg | SET_APIC_DEST_FIELD(apicid)); /* Boot on the stack */ cfg = apic_read(APIC_ICR); @@ -1350,12 +640,12 @@ static void __init do_boot_cpu(int i) /* Kick the second */ apic_write(APIC_ICR, cfg); - dprintk("Startup point 1.\n"); + Dprintk("Startup point 1.\n"); - dprintk("Waiting for send to finish...\n"); + Dprintk("Waiting for send to finish...\n"); timeout = 0; do { - dprintk("+"); + Dprintk("+"); udelay(100); send_status = apic_read(APIC_ICR) & 0x1000; } while (send_status && (timeout++ < 1000)); @@ -1368,7 +658,7 @@ static void __init do_boot_cpu(int i) if (send_status || accept_status) break; } - dprintk("After Startup.\n"); + Dprintk("After Startup.\n"); if (send_status) printk("APIC never delivered???\n"); @@ -1379,24 +669,24 @@ static void __init do_boot_cpu(int i) /* * allow APs to start initializing. */ - dprintk("Before Callout %d.\n", i); - set_bit(i, &cpu_callout_map); - dprintk("After Callout %d.\n", i); + Dprintk("Before Callout %d.\n", cpu); + set_bit(cpu, &cpu_callout_map); + Dprintk("After Callout %d.\n", cpu); /* * Wait 5s total for a response */ - for (timeout = 0; timeout < 50000; timeout++) { - if (test_bit(i, &cpu_callin_map)) + for (timeout = 0; timeout < 1000000000; timeout++) { + if (test_bit(cpu, &cpu_callin_map)) break; /* It has booted */ udelay(100); } - if (test_bit(i, &cpu_callin_map)) { + if (test_bit(cpu, &cpu_callin_map)) { /* number CPUs logically, starting from 1 (BSP is 0) */ - printk("OK.\n"); - printk("CPU%d: ", i); - print_cpu_info(&cpu_data[i]); + Dprintk("OK.\n"); + printk("CPU%d: ", cpu); + print_cpu_info(&cpu_data[cpu]); } else { if (*((volatile unsigned char *)phys_to_virt(8192)) == 0xA5) /* trampoline code not run */ @@ -1404,10 +694,10 @@ static void __init do_boot_cpu(int i) else printk("CPU booted but not responding.\n"); } - dprintk("CPU has booted.\n"); + Dprintk("CPU has booted.\n"); } else { - __cpu_logical_map[cpucount] = -1; - cpu_number_map[i] = -1; + x86_cpu_to_apicid[cpu] = -1; + x86_apicid_to_cpu[apicid] = -1; cpucount--; } @@ -1462,7 +752,7 @@ extern int prof_counter[NR_CPUS]; void __init smp_boot_cpus(void) { - int i; + int apicid, cpu; #ifdef CONFIG_MTRR /* Must be done before other processors booted */ @@ -1473,58 +763,63 @@ void __init smp_boot_cpus(void) * and the per-CPU profiling counter/multiplier */ - for (i = 0; i < NR_CPUS; i++) { - cpu_number_map[i] = -1; - prof_counter[i] = 1; - prof_old_multiplier[i] = 1; - prof_multiplier[i] = 1; + for (apicid = 0; apicid < NR_CPUS; apicid++) { + x86_apicid_to_cpu[apicid] = -1; + prof_counter[apicid] = 1; + prof_old_multiplier[apicid] = 1; + prof_multiplier[apicid] = 1; } /* * Setup boot CPU information */ - - smp_store_cpu_info(boot_cpu_id); /* Final full version of the data */ - smp_tune_scheduling(); - printk("CPU%d: ", boot_cpu_id); - print_cpu_info(&cpu_data[boot_cpu_id]); + smp_store_cpu_info(0); /* Final full version of the data */ + printk("CPU%d: ", 0); + print_cpu_info(&cpu_data[0]); /* - * not necessary because the MP table should list the boot - * CPU too, but we do it for the sake of robustness anyway. - * (and for the case when a non-SMP board boots an SMP kernel) + * We have the boot CPU online for sure. */ - cpu_present_map |= (1 << hard_smp_processor_id()); - - cpu_number_map[boot_cpu_id] = 0; - + set_bit(0, &cpu_online_map); + x86_apicid_to_cpu[boot_cpu_id] = 0; + x86_cpu_to_apicid[0] = boot_cpu_id; + global_irq_holder = 0; + current->processor = 0; init_idle(); + smp_tune_scheduling(); /* * If we couldnt find an SMP configuration at boot time, * get out of here now! */ - if (!smp_found_config) { printk(KERN_NOTICE "SMP motherboard not detected. Using dummy APIC emulation.\n"); #ifndef CONFIG_VISWS io_apic_irqs = 0; #endif - cpu_online_map = cpu_present_map; + cpu_online_map = phys_cpu_present_map = 1; smp_num_cpus = 1; goto smp_done; } /* - * If SMP should be disabled, then really disable it! + * Should not be necessary because the MP table should list the boot + * CPU too, but we do it for the sake of robustness anyway. */ + if (!test_bit(boot_cpu_id, &phys_cpu_present_map)) { + printk("weird, boot CPU (#%d) not listed by the BIOS.\n", + boot_cpu_id); + phys_cpu_present_map |= (1 << hard_smp_processor_id()); + } + /* + * If SMP should be disabled, then really disable it! + */ if (!max_cpus) { smp_found_config = 0; printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n"); } -#ifdef SMP_DEBUG { int reg; @@ -1536,11 +831,11 @@ void __init smp_boot_cpus(void) */ reg = apic_read(APIC_LVR); - dprintk("Getting VERSION: %x\n", reg); + Dprintk("Getting VERSION: %x\n", reg); apic_write(APIC_LVR, 0); reg = apic_read(APIC_LVR); - dprintk("Getting VERSION: %x\n", reg); + Dprintk("Getting VERSION: %x\n", reg); /* * The two version reads above should print the same @@ -1553,14 +848,12 @@ void __init smp_boot_cpus(void) * compatibility mode, but most boxes are anymore. */ - reg = apic_read(APIC_LVT0); - dprintk("Getting LVT0: %x\n", reg); + Dprintk("Getting LVT0: %x\n", reg); reg = apic_read(APIC_LVT1); - dprintk("Getting LVT1: %x\n", reg); + Dprintk("Getting LVT1: %x\n", reg); } -#endif setup_local_APIC(); @@ -1570,42 +863,33 @@ void __init smp_boot_cpus(void) /* * Now scan the CPU present map and fire up the other CPUs. */ + Dprintk("CPU present map: %lx\n", phys_cpu_present_map); - /* - * Add all detected CPUs. (later on we can down individual - * CPUs which will change cpu_online_map but not necessarily - * cpu_present_map. We are pretty much ready for hot-swap CPUs.) - */ - cpu_online_map = cpu_present_map; - mb(); - - dprintk("CPU map: %lx\n", cpu_present_map); - - for (i = 0; i < NR_CPUS; i++) { + for (apicid = 0; apicid < NR_CPUS; apicid++) { /* * Don't even attempt to start the boot CPU! */ - if (i == boot_cpu_id) + if (apicid == boot_cpu_id) continue; - if ((cpu_online_map & (1 << i)) - && (max_cpus < 0 || max_cpus > cpucount+1)) { - do_boot_cpu(i); - } + if (!(phys_cpu_present_map & (1 << apicid))) + continue; + if ((max_cpus >= 0) && (max_cpus < cpucount+1)) + continue; + + do_boot_cpu(apicid); /* * Make sure we unmap all failed CPUs */ - if (cpu_number_map[i] == -1 && (cpu_online_map & (1 << i))) { - printk("CPU #%d not responding - cannot use it.\n",i); - cpu_online_map &= ~(1 << i); - } + if ((x86_apicid_to_cpu[apicid] == -1) && + (phys_cpu_present_map & (1 << apicid))) + printk("phys CPU #%d not responding - cannot use it.\n",apicid); } /* * Cleanup possible dangling ends... */ - #ifndef CONFIG_VISWS { /* @@ -1627,27 +911,25 @@ void __init smp_boot_cpus(void) * Allow the user to impress friends. */ - dprintk("Before bogomips.\n"); + Dprintk("Before bogomips.\n"); if (!cpucount) { printk(KERN_ERR "Error: only one processor found.\n"); - cpu_online_map = (1<<hard_smp_processor_id()); } else { unsigned long bogosum = 0; - for(i = 0; i < 32; i++) - if (cpu_online_map&(1<<i)) - bogosum+=cpu_data[i].loops_per_sec; + for (cpu = 0; cpu < NR_CPUS; cpu++) + if (cpu_online_map & (1<<cpu)) + bogosum += cpu_data[cpu].loops_per_sec; printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n", cpucount+1, (bogosum+2500)/500000, ((bogosum+2500)/5000)%100); - dprintk("Before bogocount - setting activated=1.\n"); - smp_activated = 1; + Dprintk("Before bogocount - setting activated=1.\n"); } smp_num_cpus = cpucount + 1; if (smp_b_stepping) printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n"); - dprintk("Boot done.\n"); + Dprintk("Boot done.\n"); cache_APIC_registers(); #ifndef CONFIG_VISWS @@ -1661,12 +943,6 @@ void __init smp_boot_cpus(void) smp_done: /* - * now we know the other CPUs have fired off and we know our - * APIC ID, so we can go init the TSS and stuff: - */ - cpu_init(); - - /* * Set up all local APIC timers in the system: */ setup_APIC_clocks(); diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c index 903dcf15d..84e20b225 100644 --- a/arch/i386/kernel/time.c +++ b/arch/i386/kernel/time.c @@ -42,12 +42,14 @@ #include <linux/init.h> #include <linux/smp.h> -#include <asm/processor.h> -#include <asm/uaccess.h> #include <asm/io.h> +#include <asm/smp.h> #include <asm/irq.h> -#include <asm/delay.h> #include <asm/msr.h> +#include <asm/delay.h> +#include <asm/mpspec.h> +#include <asm/uaccess.h> +#include <asm/processor.h> #include <linux/mc146818rtc.h> #include <linux/timex.h> @@ -368,7 +370,7 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *reg * profiling, except when we simulate SMP mode on a uniprocessor * system, in that case we have to call the local interrupt handler. */ -#ifndef __SMP__ +#ifndef CONFIG_X86_LOCAL_APIC if (!user_mode(regs)) x86_do_profile(regs->eip); #else diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 063e9fefb..17cac5019 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -138,7 +138,7 @@ static void show_registers(struct pt_regs *regs) unsigned short ss; unsigned long *stack, addr, module_start, module_end; - esp = (unsigned long) (1+regs); + esp = (unsigned long) (®s->esp); ss = __KERNEL_DS; if (regs->xcs & 3) { in_kernel = 0; @@ -337,7 +337,7 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs) atomic_t nmi_counter[NR_CPUS]; -#if CONFIG_SMP +#if CONFIG_X86_IO_APIC int nmi_watchdog = 1; @@ -388,7 +388,12 @@ inline void nmi_watchdog_tick(struct pt_regs * regs) alert_counter[cpu]++; if (alert_counter[cpu] == 5*HZ) { spin_lock(&nmi_print_lock); - console_lock.lock = 0; // we are in trouble anyway + /* + * We are in trouble anyway, lets at least try + * to get a message out. + */ + spin_trylock(&console_lock); + spin_unlock(&console_lock); printk("NMI Watchdog detected LOCKUP on CPU%d, registers:\n", cpu); show_registers(regs); printk("console shuts up ...\n"); @@ -409,7 +414,7 @@ asmlinkage void do_nmi(struct pt_regs * regs, long error_code) atomic_inc(nmi_counter+smp_processor_id()); if (!(reason & 0xc0)) { -#if CONFIG_SMP +#if CONFIG_X86_IO_APIC /* * Ok, so this is none of the documented NMI sources, * so it must be the NMI watchdog. @@ -600,7 +605,10 @@ void __init trap_init_f00f_bug(void) pte = pte_offset(pmd, page); __free_page(pte_page(*pte)); *pte = mk_pte_phys(__pa(&idt_table), PAGE_KERNEL_RO); - local_flush_tlb(); + /* + * Not that any PGE-capable kernel should have the f00f bug ... + */ + __flush_tlb_all(); /* * "idt" is magic - it overlaps the idt_descr @@ -806,13 +814,9 @@ void __init trap_init(void) set_call_gate(&default_ldt[4],lcall27); /* - * on SMP we do not yet know which CPU is on which TSS, - * so we delay this until smp_init(). (the CPU is already - * in a reasonable state, otherwise we wouldnt have gotten so far :) + * Should be a barrier for any external CPU state. */ -#ifndef __SMP__ cpu_init(); -#endif #ifdef CONFIG_X86_VISWS_APIC superio_init(); diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index 618b36544..21c9cadff 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -16,6 +16,7 @@ #include <linux/smp.h> #include <linux/smp_lock.h> #include <linux/interrupt.h> +#include <linux/init.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -76,7 +77,7 @@ bad_area: return 0; } -static inline void handle_wp_test (void) +static void __init handle_wp_test (void) { const unsigned long vaddr = PAGE_OFFSET; pgd_t *pgd; @@ -91,7 +92,7 @@ static inline void handle_wp_test (void) pmd = pmd_offset(pgd, vaddr); pte = pte_offset(pmd, vaddr); *pte = mk_pte_phys(0, PAGE_KERNEL); - local_flush_tlb(); + __flush_tlb_all(); boot_cpu_data.wp_works_ok = 1; /* @@ -123,6 +124,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) unsigned long page; unsigned long fixup; int write; + int si_code = SEGV_MAPERR; /* get the address */ __asm__("movl %%cr2,%0":"=r" (address)); @@ -164,6 +166,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) */ good_area: write = 0; + si_code = SEGV_ACCERR; + switch (error_code & 3) { default: /* 3: write, present */ #ifdef TEST_VERIFY_AREA @@ -216,10 +220,14 @@ bad_area: /* User mode accesses just cause a SIGSEGV */ if (error_code & 4) { + struct siginfo si; tsk->thread.cr2 = address; tsk->thread.error_code = error_code; tsk->thread.trap_no = 14; - force_sig(SIGSEGV, tsk); + si.si_signo = SIGSEGV; + si.si_code = si_code; + si.si_addr = (void*) address; + force_sig_info(SIGSEGV, &si, tsk); return; } diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index b99daee84..b20ddc2d5 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -34,6 +34,7 @@ #include <asm/dma.h> #include <asm/fixmap.h> #include <asm/e820.h> +#include <asm/apic.h> unsigned long highstart_pfn, highend_pfn; static unsigned long totalram_pages = 0; @@ -194,8 +195,6 @@ void __init kmap_init(void) kmap_pte = kmap_get_fixmap_pte(kmap_vstart); kmap_prot = PAGE_KERNEL; - if (boot_cpu_data.x86_capability & X86_FEATURE_PGE) - pgprot_val(kmap_prot) |= _PAGE_GLOBAL; } #endif @@ -239,7 +238,8 @@ void show_mem(void) extern char _text, _etext, _edata, __bss_start, _end; extern char __init_begin, __init_end; -static void set_pte_phys (unsigned long vaddr, unsigned long phys) +static inline void set_pte_phys (unsigned long vaddr, + unsigned long phys, pgprot_t flags) { pgprot_t prot; pgd_t *pgd; @@ -249,26 +249,25 @@ static void set_pte_phys (unsigned long vaddr, unsigned long phys) pgd = swapper_pg_dir + __pgd_offset(vaddr); pmd = pmd_offset(pgd, vaddr); pte = pte_offset(pmd, vaddr); - prot = PAGE_KERNEL; - if (boot_cpu_data.x86_capability & X86_FEATURE_PGE) - pgprot_val(prot) |= _PAGE_GLOBAL; + pgprot_val(prot) = pgprot_val(PAGE_KERNEL) | pgprot_val(flags); set_pte(pte, mk_pte_phys(phys, prot)); /* * It's enough to flush this one mapping. + * (PGE mappings get flushed as well) */ __flush_tlb_one(vaddr); } -void set_fixmap (enum fixed_addresses idx, unsigned long phys) +void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags) { unsigned long address = __fix_to_virt(idx); if (idx >= __end_of_fixed_addresses) { - printk("Invalid set_fixmap\n"); + printk("Invalid __set_fixmap\n"); return; } - set_pte_phys(address,phys); + set_pte_phys(address, phys, flags); } static void __init fixrange_init (unsigned long start, unsigned long end, pgd_t *pgd_base) @@ -439,10 +438,10 @@ void __init paging_init(void) set_in_cr4(X86_CR4_PAE); #endif - __flush_tlb(); + __flush_tlb_all(); -#ifdef __SMP__ - init_smp_mappings(); +#ifdef CONFIG_X86_LOCAL_APIC + init_apic_mappings(); #endif #ifdef CONFIG_HIGHMEM diff --git a/arch/i386/vmlinux.lds b/arch/i386/vmlinux.lds index 9624cae47..5790bb5d4 100644 --- a/arch/i386/vmlinux.lds +++ b/arch/i386/vmlinux.lds @@ -64,6 +64,12 @@ SECTIONS } _end = . ; + /* Sections to be discarded */ + /DISCARD/ : { + *(.text.exit) + *(.data.exit) + } + /* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c index 81dc17103..cbccf3956 100644 --- a/arch/m68k/atari/stram.c +++ b/arch/m68k/atari/stram.c @@ -1255,6 +1255,8 @@ int __init stram_device_init(void) blksize_size[STRAM_MAJOR] = stram_blocksizes; stram_sizes[STRAM_MINOR] = (swap_end - swap_start)/1024; blk_size[STRAM_MAJOR] = stram_sizes; + register_disk(NULL, MKDEV(STRAM_MAJOR, STRAM_MINOR), 1, &stram_fops, + (swap_end-swap_start)>>9); do_z2_request(); /* to avoid warning */ return( 0 ); } diff --git a/arch/m68k/config.in b/arch/m68k/config.in index 2d6095694..52a083750 100644 --- a/arch/m68k/config.in +++ b/arch/m68k/config.in @@ -2,6 +2,9 @@ # For a description of the syntax of this configuration file, # see the Configure script. # + +define_bool CONFIG_UID16 y + mainmenu_name "Linux/68k Kernel Configuration" mainmenu_option next_comment diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 21acaa218..b3ef8ded3 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S @@ -425,15 +425,15 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_time) .long SYMBOL_NAME(sys_mknod) .long SYMBOL_NAME(sys_chmod) /* 15 */ - .long SYMBOL_NAME(sys_chown) + .long SYMBOL_NAME(sys_chown16) .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) @@ -455,11 +455,11 @@ SYMBOL_NAME_LABEL(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_ni_syscall) /* old lock syscall holder */ @@ -479,18 +479,18 @@ SYMBOL_NAME_LABEL(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_getgroups16) /* 80 */ + .long SYMBOL_NAME(sys_setgroups16) .long SYMBOL_NAME(old_select) .long SYMBOL_NAME(sys_symlink) .long SYMBOL_NAME(sys_lstat) @@ -504,7 +504,7 @@ SYMBOL_NAME_LABEL(sys_call_table) .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 */ @@ -547,8 +547,8 @@ SYMBOL_NAME_LABEL(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) @@ -573,14 +573,14 @@ SYMBOL_NAME_LABEL(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_setresuid16) + .long SYMBOL_NAME(sys_getresuid16) /* 165 */ .long SYMBOL_NAME(sys_ni_syscall) /* for 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) @@ -591,7 +591,7 @@ SYMBOL_NAME_LABEL(sys_call_table) .long SYMBOL_NAME(sys_rt_sigsuspend) .long SYMBOL_NAME(sys_pread) /* 180 */ .long SYMBOL_NAME(sys_pwrite) - .long SYMBOL_NAME(sys_lchown); + .long SYMBOL_NAME(sys_lchown16); .long SYMBOL_NAME(sys_getcwd) .long SYMBOL_NAME(sys_capget) .long SYMBOL_NAME(sys_capset) /* 185 */ @@ -600,6 +600,29 @@ SYMBOL_NAME_LABEL(sys_call_table) .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_chown) /* 195 */ + .long SYMBOL_NAME(sys_getuid) + .long SYMBOL_NAME(sys_getgid) + .long SYMBOL_NAME(sys_geteuid) + .long SYMBOL_NAME(sys_getegid) + .long SYMBOL_NAME(sys_setreuid) /* 200 */ + .long SYMBOL_NAME(sys_setregid) + .long SYMBOL_NAME(sys_getgroups) + .long SYMBOL_NAME(sys_setgroups) + .long SYMBOL_NAME(sys_fchown) + .long SYMBOL_NAME(sys_setresuid) /* 205 */ + .long SYMBOL_NAME(sys_getresuid) + .long SYMBOL_NAME(sys_setresgid) + .long SYMBOL_NAME(sys_getresgid) + .long SYMBOL_NAME(sys_lchown) + .long SYMBOL_NAME(sys_setuid) /* 210 */ + .long SYMBOL_NAME(sys_setgid) + .long SYMBOL_NAME(sys_setfsuid) + .long SYMBOL_NAME(sys_setfsgid) .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4 .long SYMBOL_NAME(sys_ni_syscall) diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 81014d9c8..bbff5d590 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -37,6 +37,7 @@ #include <linux/ptrace.h> #include <linux/unistd.h> #include <linux/stddef.h> +#include <linux/highuid.h> #include <asm/setup.h> #include <asm/uaccess.h> @@ -1048,6 +1049,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) info.si_code = SI_USER; info.si_pid = current->p_pptr->pid; info.si_uid = current->p_pptr->uid; + info.si_uid16 = high2lowuid(current->p_pptr->uid); } /* If the (new) signal is now blocked, requeue it. */ diff --git a/arch/mips64/defconfig b/arch/mips64/defconfig index 3fd8237b7..3c32d6c1a 100644 --- a/arch/mips64/defconfig +++ b/arch/mips64/defconfig @@ -13,6 +13,7 @@ # CONFIG_SGI_IP22 is not set CONFIG_SGI_IP27=y # CONFIG_SGI_SN0_N_MODE is not set +CONFIG_DISCONTIGMEM=y CONFIG_BOOT_ELF64=y CONFIG_ARC64=y CONFIG_COHERENT_IO=y diff --git a/arch/mips64/defconfig-ip27 b/arch/mips64/defconfig-ip27 index 3fd8237b7..3c32d6c1a 100644 --- a/arch/mips64/defconfig-ip27 +++ b/arch/mips64/defconfig-ip27 @@ -13,6 +13,7 @@ # CONFIG_SGI_IP22 is not set CONFIG_SGI_IP27=y # CONFIG_SGI_SN0_N_MODE is not set +CONFIG_DISCONTIGMEM=y CONFIG_BOOT_ELF64=y CONFIG_ARC64=y CONFIG_COHERENT_IO=y diff --git a/arch/mips64/sgi-ip27/ip27-pci.c b/arch/mips64/sgi-ip27/ip27-pci.c index 45e9cd649..80868cf6a 100644 --- a/arch/mips64/sgi-ip27/ip27-pci.c +++ b/arch/mips64/sgi-ip27/ip27-pci.c @@ -1,4 +1,4 @@ -/* $Id: ip27-pci.c,v 1.5 2000/01/31 23:25:06 kanoj Exp $ +/* $Id: ip27-pci.c,v 1.7 2000/02/03 23:30:59 kanoj Exp $ * * 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 @@ -172,6 +172,7 @@ void __init pcibios_fixup_bus(struct pci_bus *b) { unsigned short command; + struct list_head *ln; struct pci_dev *dev; pci_fixup_irqs(pci_swizzle, pci_map_irq); @@ -182,7 +183,8 @@ pcibios_fixup_bus(struct pci_bus *b) * stop working if we program the controllers as not having * PCI_COMMAND_MEMORY, so we have to fudge the mem_flags. */ - for (dev = b->devices; dev; dev = dev->sibling) { + for (ln=b->devices.next; ln != &b->devices; ln=ln->next) { + dev = pci_dev_b(ln); if (PCI_FUNC(dev->devfn) == 0) { if ((PCI_SLOT(dev->devfn) == 0) || (PCI_SLOT(dev->devfn) == 1)) { @@ -208,6 +210,13 @@ pcibios_fixup_pbus_ranges(struct pci_bus * bus, ranges->mem_end -= bus->resource[1]->start; } +int __init +pcibios_enable_device(struct pci_dev *dev) +{ + /* Not needed, since we enable all devices at startup. */ + return 0; +} + void __init pcibios_align_resource(void *data, struct resource *res, unsigned long size) { diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile index 6552a7140..d62c07669 100644 --- a/arch/ppc/Makefile +++ b/arch/ppc/Makefile @@ -155,9 +155,6 @@ oak_config: clean_config walnut_config: clean_config ln -s configs/walnut_defconfig arch/ppc/defconfig -tags: - etags */*.c include/{asm,linux}/*.h arch/ppc/kernel/*.{c,h} - archclean: rm -f arch/ppc/kernel/{mk_defs,ppc_defs.h,find_name,checks} @$(MAKECOFFBOOT) clean diff --git a/arch/ppc/coffboot/Makefile b/arch/ppc/coffboot/Makefile index b9868e6ac..12032930d 100644 --- a/arch/ppc/coffboot/Makefile +++ b/arch/ppc/coffboot/Makefile @@ -39,11 +39,13 @@ ifeq ($(CONFIG_PMAC),y) hack-coff: hack-coff.c $(HOSTCC) $(HOSTCFLAGS) -o hack-coff hack-coff.c -znetboot: vmlinux.coff zImage +znetboot: vmlinux.coff vmlinux.elf zImage cp vmlinux.coff $(TFTPIMAGE) + cp vmlinux.elf $(TFTPIMAGE).elf znetboot.initrd: vmlinux.coff.initrd cp vmlinux.coff.initrd $(TFTPIMAGE) + cp vmlinux.elf.initrd $(TFTPIMAGE).elf floppy: zImage # mount -t hfs /dev/fd0 /mnt diff --git a/arch/ppc/coffboot/chrpmain.c b/arch/ppc/coffboot/chrpmain.c index fc5648944..bffb9d9ee 100644 --- a/arch/ppc/coffboot/chrpmain.c +++ b/arch/ppc/coffboot/chrpmain.c @@ -10,7 +10,6 @@ #include "zlib.h" #include <asm/bootinfo.h> #include <asm/processor.h> -#define __KERNEL__ #include <asm/page.h> extern void *finddevice(const char *); diff --git a/arch/ppc/coffboot/coffmain.c b/arch/ppc/coffboot/coffmain.c index 2bb4ea31d..b76ba5976 100644 --- a/arch/ppc/coffboot/coffmain.c +++ b/arch/ppc/coffboot/coffmain.c @@ -10,7 +10,6 @@ #include "zlib.h" #include <asm/bootinfo.h> #include <asm/processor.h> -#define __KERNEL__ #include <asm/page.h> extern void *finddevice(const char *); diff --git a/arch/ppc/config.in b/arch/ppc/config.in index fa98b5fcf..43a678c6d 100644 --- a/arch/ppc/config.in +++ b/arch/ppc/config.in @@ -2,6 +2,8 @@ # For a description of the syntax of this configuration file, # see the Configure script. # +define_bool CONFIG_UID16 n + mainmenu_name "Linux/PowerPC Kernel Configuration" mainmenu_option next_comment @@ -91,10 +93,9 @@ if [ "$CONFIG_OAK" = "y" ]; then fi if [ "$CONFIG_8xx" = "y" ]; then bool 'QSpan PCI' CONFIG_PCI -else - if [ "$CONFIG_APUS" != "y" ]; then +fi +if [ "$CONFIG_6xx" = "y" -a "$CONFIG_APUS" != "y" ]; then define_bool CONFIG_PCI y - fi fi bool 'Networking support' CONFIG_NET @@ -112,11 +113,15 @@ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC source drivers/pci/Config.in -source drivers/pcmcia/Config.in +bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG + +if [ "$CONFIG_HOTPLUG" = "y" ]; then + source drivers/pcmcia/Config.in +fi source drivers/parport/Config.in -if [ "$CONFIG_8xx" != "y" ]; then +if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then bool 'Support for VGA Console' CONFIG_VGA_CONSOLE bool 'Support for frame buffer devices' CONFIG_FB if [ "$CONFIG_FB" = "y" ]; then @@ -188,6 +193,8 @@ if [ "$CONFIG_SCSI" != "n" ]; then fi endmenu +source drivers/ieee1394/Config.in + if [ "$CONFIG_NET" = "y" ]; then mainmenu_option next_comment comment 'Network device support' diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/common_defconfig index 977626274..795aa5b83 100644 --- a/arch/ppc/configs/common_defconfig +++ b/arch/ppc/configs/common_defconfig @@ -45,11 +45,7 @@ CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y # CONFIG_BINFMT_MISC is not set - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set +# CONFIG_HOTPLUG is not set # CONFIG_PARPORT is not set CONFIG_VGA_CONSOLE=y CONFIG_FB=y diff --git a/arch/ppc/configs/gemini_defconfig b/arch/ppc/configs/gemini_defconfig index b3129c7a5..9850f61d8 100644 --- a/arch/ppc/configs/gemini_defconfig +++ b/arch/ppc/configs/gemini_defconfig @@ -46,11 +46,8 @@ CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y # CONFIG_BINFMT_MISC is not set - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set +# CONFIG_PCI_NAMES is not set +# CONFIG_HOTPLUG is not set # CONFIG_PARPORT is not set # CONFIG_VGA_CONSOLE is not set # CONFIG_FB is not set @@ -161,6 +158,7 @@ CONFIG_BLK_DEV_SR_VENDOR=y # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # +# CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set @@ -243,7 +241,6 @@ CONFIG_NCR885E=y # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_YELLOWFIN is not set # CONFIG_RTL8139 is not set # CONFIG_DM9102 is not set # CONFIG_AT1700 is not set @@ -251,6 +248,13 @@ CONFIG_NCR885E=y # CONFIG_NET_ISA is not set # CONFIG_NET_EISA is not set # CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_PPP is not set @@ -310,10 +314,20 @@ CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 # +# I2C support +# +# CONFIG_I2C is not set + +# # Mice # # CONFIG_BUSMOUSE is not set # CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set # CONFIG_QIC02_TAPE is not set # @@ -327,11 +341,6 @@ CONFIG_UNIX98_PTY_COUNT=256 # Video For Linux # # CONFIG_VIDEO_DEV is not set - -# -# Joystick support -# -# CONFIG_JOYSTICK is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -341,9 +350,10 @@ CONFIG_UNIX98_PTY_COUNT=256 # # CONFIG_FTAPE is not set # CONFIG_DRM is not set +# CONFIG_AGP is not set # -# Support for USB +# USB support # # CONFIG_USB is not set @@ -358,9 +368,9 @@ CONFIG_UNIX98_PTY_COUNT=256 # CONFIG_BFS_FS is not set # CONFIG_FAT_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set CONFIG_ISO9660_FS=y # 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 @@ -370,16 +380,17 @@ CONFIG_DEVPTS_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 # # Network File Systems # # CONFIG_CODA_FS is not set -# CONFIG_NFS_FS is not set +CONFIG_NFS_FS=y # CONFIG_NFSD is not set -# CONFIG_SUNRPC is not set -# CONFIG_LOCKD is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set @@ -403,4 +414,4 @@ CONFIG_MSDOS_PARTITION=y # # CONFIG_MAGIC_SYSRQ is not set # CONFIG_KGDB is not set -# CONFIG_XMON is not set +CONFIG_XMON=y diff --git a/arch/ppc/configs/oak_defconfig b/arch/ppc/configs/oak_defconfig index 1c2daf125..5fe9be376 100644 --- a/arch/ppc/configs/oak_defconfig +++ b/arch/ppc/configs/oak_defconfig @@ -3,41 +3,44 @@ # # +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# # Platform support # CONFIG_PPC=y -CONFIG_4xx=y # CONFIG_6xx is not set +CONFIG_4xx=y # CONFIG_PPC64 is not set # CONFIG_82xx is not set # CONFIG_8xx is not set -CONFIG_403=y -# CONFIG_405 is not set CONFIG_OAK=y +# CONFIG_WALNUT is not set +# CONFIG_PCI is not set # CONFIG_SMP is not set CONFIG_MACH_SPECIFIC=y # CONFIG_MATH_EMULATION is not set # -# General setup +# Loadable module support # -# CONFIG_EXPERIMENTAL is not set CONFIG_MODULES=y # CONFIG_MODVERSIONS is not set CONFIG_KMOD=y -# CONFIG_PCI is not set + +# +# General setup +# CONFIG_NET=y CONFIG_SYSCTL=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y -CONFIG_BINFMT_MISC=y - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_HOTPLUG is not set # CONFIG_PARPORT is not set # CONFIG_VGA_CONSOLE is not set # CONFIG_FB is not set @@ -66,7 +69,6 @@ CONFIG_BINFMT_MISC=y # Please see Documentation/ide.txt for help/info on IDE drives # # CONFIG_BLK_DEV_HD_ONLY is not set -# CONFIG_BLK_CPQ_DA is not set # # Additional Block Devices @@ -77,7 +79,6 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_INITRD=y # CONFIG_BLK_DEV_XD is not set -# CONFIG_BLK_DEV_DAC960 is not set CONFIG_PARIDE_PARPORT=y # CONFIG_PARIDE is not set # CONFIG_BLK_DEV_IDE_MODES is not set @@ -108,12 +109,29 @@ CONFIG_SYN_COOKIES=y # (it is safe to leave these untouched) # # CONFIG_SKB_LARGE is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set # # # # CONFIG_IPX is not set # CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set # # SCSI support @@ -140,15 +158,27 @@ CONFIG_NET_ETHERNET=y # CONFIG_MACE is not set # CONFIG_BMAC is not set # CONFIG_NCR885E is not set +CONFIG_OAKNET=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_RTL8139 is not set +# CONFIG_DM9102 is not set +# CONFIG_AT1700 is not set # CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set # CONFIG_NET_EISA is not set # CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_SK98LIN is not set # CONFIG_FDDI is not set +# CONFIG_HIPPI is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -162,6 +192,8 @@ CONFIG_NET_ETHERNET=y # # CONFIG_TR is not set # CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set # # Wan interfaces @@ -208,6 +240,10 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_BUSMOUSE is not set # CONFIG_MOUSE is not set # CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set @@ -229,9 +265,10 @@ CONFIG_SERIAL_CONSOLE=y # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set +# CONFIG_DRM is not set # -# USB drivers - not for the faint of heart +# Support for USB # # CONFIG_USB is not set @@ -239,13 +276,16 @@ CONFIG_SERIAL_CONSOLE=y # Filesystems # # CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_UDF_FS is not set @@ -253,7 +293,8 @@ CONFIG_AUTOFS_FS=y # CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y -CONFIG_ROMFS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set @@ -274,8 +315,8 @@ CONFIG_LOCKD=y # Partition Types # # CONFIG_PARTITION_ADVANCED is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_NLS is not set diff --git a/arch/ppc/configs/pmac_defconfig b/arch/ppc/configs/pmac_defconfig index 514843d00..e2b7c31bd 100644 --- a/arch/ppc/configs/pmac_defconfig +++ b/arch/ppc/configs/pmac_defconfig @@ -35,6 +35,7 @@ CONFIG_SYSVIPC=y CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y CONFIG_BINFMT_MISC=m +CONFIG_HOTPLUG=y # # PCMCIA/Cardbus support diff --git a/arch/ppc/configs/walnut_defconfig b/arch/ppc/configs/walnut_defconfig index 66edd11b6..931e1a7a9 100644 --- a/arch/ppc/configs/walnut_defconfig +++ b/arch/ppc/configs/walnut_defconfig @@ -3,41 +3,44 @@ # # +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# # Platform support # CONFIG_PPC=y -CONFIG_4xx=y # CONFIG_6xx is not set +CONFIG_4xx=y # CONFIG_PPC64 is not set # CONFIG_82xx is not set # CONFIG_8xx is not set -CONFIG_403=y -# CONFIG_405 is not set -CONFIG_OAK=y +# CONFIG_OAK is not set +CONFIG_WALNUT=y +CONFIG_PCI=y # CONFIG_SMP is not set CONFIG_MACH_SPECIFIC=y # CONFIG_MATH_EMULATION is not set # -# General setup +# Loadable module support # -# CONFIG_EXPERIMENTAL is not set CONFIG_MODULES=y # CONFIG_MODVERSIONS is not set CONFIG_KMOD=y -CONFIG_PCI=y + +# +# General setup +# CONFIG_NET=y CONFIG_SYSCTL=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y -CONFIG_BINFMT_MISC=y - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set +# CONFIG_BINFMT_MISC is not set +# CONFIG_HOTPLUG is not set # CONFIG_PARPORT is not set # CONFIG_VGA_CONSOLE is not set # CONFIG_FB is not set @@ -66,7 +69,6 @@ CONFIG_BINFMT_MISC=y # Please see Documentation/ide.txt for help/info on IDE drives # # CONFIG_BLK_DEV_HD_ONLY is not set -# CONFIG_BLK_CPQ_DA is not set # # Additional Block Devices @@ -77,7 +79,6 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_INITRD=y # CONFIG_BLK_DEV_XD is not set -# CONFIG_BLK_DEV_DAC960 is not set CONFIG_PARIDE_PARPORT=y # CONFIG_PARIDE is not set # CONFIG_BLK_DEV_IDE_MODES is not set @@ -108,12 +109,29 @@ CONFIG_SYN_COOKIES=y # (it is safe to leave these untouched) # # CONFIG_SKB_LARGE is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set # # # # CONFIG_IPX is not set # CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_BRIDGE is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set # # SCSI support @@ -140,15 +158,27 @@ CONFIG_NET_ETHERNET=y # CONFIG_MACE is not set # CONFIG_BMAC is not set # CONFIG_NCR885E is not set +# CONFIG_OAKNET is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_RTL8139 is not set +# CONFIG_DM9102 is not set +# CONFIG_AT1700 is not set # CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set # CONFIG_NET_EISA is not set # CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_SK98LIN is not set # CONFIG_FDDI is not set +# CONFIG_HIPPI is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -162,6 +192,8 @@ CONFIG_NET_ETHERNET=y # # CONFIG_TR is not set # CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set # # Wan interfaces @@ -208,6 +240,10 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_BUSMOUSE is not set # CONFIG_MOUSE is not set # CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# # CONFIG_WATCHDOG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set @@ -229,9 +265,10 @@ CONFIG_SERIAL_CONSOLE=y # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set +# CONFIG_DRM is not set # -# USB drivers - not for the faint of heart +# Support for USB # # CONFIG_USB is not set @@ -239,13 +276,16 @@ CONFIG_SERIAL_CONSOLE=y # Filesystems # # CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_UDF_FS is not set @@ -253,7 +293,8 @@ CONFIG_AUTOFS_FS=y # CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y -CONFIG_ROMFS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig index 2a3aac0f7..795aa5b83 100644 --- a/arch/ppc/defconfig +++ b/arch/ppc/defconfig @@ -35,8 +35,8 @@ CONFIG_KMOD=y # # General setup # +# CONFIG_PCI is not set CONFIG_PCI=y -CONFIG_PCI_NAMES=y CONFIG_NET=y CONFIG_SYSCTL=y CONFIG_SYSVIPC=y @@ -45,11 +45,7 @@ CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y # CONFIG_BINFMT_MISC is not set - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set +# CONFIG_HOTPLUG is not set # CONFIG_PARPORT is not set CONFIG_VGA_CONSOLE=y CONFIG_FB=y diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index a41473fa5..7aaacfadb 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -57,8 +57,11 @@ ifdef CONFIG_SMP O_OBJS += smp.o endif -ifeq ($(CONFIG_OAK),y) - O_OBJS += oak_setup.o +ifeq ($(CONFIG_4xx),y) + O_OBJS += ppc4xx_pic.o + ifeq ($(CONFIG_OAK),y) + O_OBJS += oak_setup.o + endif endif ifeq ($(CONFIG_8xx),y) diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index 5ed04344e..cb92163d6 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -265,37 +265,29 @@ _GLOBAL(_switch) SYNC rfi -/* - * ret_from_int(): - * - * Return from an interrupt (external interrupt and - * decrementer). This checks the first argument so - * we know if rtl_intercept wants us to check for - * a bottom half, signals and so on (normal return) or - * we're returning from a real-time interrupt or have - * interrupts soft disabled so we cannot enter Linux. - * -- Cort - */ - .globl ret_from_int -ret_from_int: - cmpi 0,r3,0 - beq 10f - /* we're allowed to do signal/bh checks */ - b ret_from_syscall #ifdef __SMP__ .globl ret_from_smpfork ret_from_smpfork: bl schedule_tail + b ret_from_except #endif - .globl ret_from_syscall -ret_from_syscall: + .globl ret_from_intercept +ret_from_intercept: + /* + * We may be returning from RTL and cannot do the normal checks + * -- Cort + */ + cmpi 0,r3,0 + beq 10f .globl ret_from_except ret_from_except: -0: mfmsr r30 /* Disable interrupts */ - rlwinm r30,r30,0,17,15 /* clear MSR_EE */ - SYNC /* Some chip revs need this... */ - mtmsr r30 - SYNC +0: /* disable interrupts */ + lis r30,int_control@h + ori r30,r30,int_control@l + lwz r30,0(r30) + mtlr r30 + blrl + lwz r5,_MSR(r1) andi. r5,r5,MSR_EE beq 2f @@ -317,9 +309,13 @@ lost_irq_ret: bl do_bottom_half .globl do_bottom_half_ret do_bottom_half_ret: -2: SYNC - mtmsr r30 /* disable interrupts again */ - SYNC +2: /* disable interrupts */ + lis r30,int_control@h + ori r30,r30,int_control@l + lwz r30,0(r30) + mtlr r30 + blrl + lwz r3,_MSR(r1) /* Returning to user mode? */ andi. r3,r3,MSR_PR beq+ 10f /* if so, check need_resched and signals */ diff --git a/arch/ppc/kernel/gemini_pci.c b/arch/ppc/kernel/gemini_pci.c index 3d6feed13..fb80dc493 100644 --- a/arch/ppc/kernel/gemini_pci.c +++ b/arch/ppc/kernel/gemini_pci.c @@ -229,13 +229,11 @@ __init void layout_bus( struct pci_bus *bus ) { struct pci_dev *dev; - if (!bus->devices && !bus->children) - return; - io_base = ALIGN(io_base, 4*KB); mem_base = ALIGN(mem_base, 4*KB); - for( dev = bus->devices; dev; dev = dev->sibling ) { + pci_for_each_dev(dev) + { if (((dev->class >> 16) != PCI_BASE_CLASS_BRIDGE) || ((dev->class >> 8) == PCI_CLASS_BRIDGE_OTHER)) layout_dev( dev ); diff --git a/arch/ppc/kernel/gemini_setup.c b/arch/ppc/kernel/gemini_setup.c index fadddda8b..d7ca91780 100644 --- a/arch/ppc/kernel/gemini_setup.c +++ b/arch/ppc/kernel/gemini_setup.c @@ -330,7 +330,7 @@ void __init gemini_init_IRQ(void) int i; /* gemini has no 8259 */ - open_pic.irq_offset = 0; + open_pic_irq_offset = 0; for( i=0; i < NR_IRQS; i++ ) irq_desc[i].handler = &open_pic; openpic_init(1); @@ -515,7 +515,7 @@ void gemini_post_irq(int irq) * We do it this way since our irq_desc[irq].handler can change * with RTL and no longer be open_pic -- Cort */ - if ( irq >= open_pic.irq_offset) + if ( irq >= open_pic_irq_offset) openpic_eoi( smp_processor_id() ); } diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index 451a1cad4..a70ba8bfd 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -287,7 +287,8 @@ turn_on_mmu: stw r2,GPR2(r21); \ stw r1,0(r21); \ tovirt(r1,r21); /* set new kernel sp */ \ - SAVE_4GPRS(3, r21); + SAVE_4GPRS(3, r21); \ + SAVE_GPR(7, r21); /* * Note: code which follows this uses cr0.eq (set if from kernel), * r21, r22 (SRR0), and r23 (SRR1). @@ -374,7 +375,7 @@ HardwareInterrupt: .globl do_IRQ_intercept do_IRQ_intercept: .long do_IRQ; - .long ret_from_except + .long ret_from_intercept #else bl apus_interrupt_entry #endif /* CONFIG_APUS */ @@ -424,7 +425,7 @@ Decrementer: .globl timer_interrupt_intercept timer_interrupt_intercept: .long timer_interrupt - .long ret_from_except + .long ret_from_intercept STD_EXCEPTION(0xa00, Trap_0a, UnknownException) STD_EXCEPTION(0xb00, Trap_0b, UnknownException) @@ -674,7 +675,6 @@ DataStoreTLBMiss: transfer_to_handler: stw r22,_NIP(r21) stw r23,_MSR(r21) - SAVE_GPR(7, r21) SAVE_4GPRS(8, r21) SAVE_8GPRS(12, r21) SAVE_8GPRS(24, r21) diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S index abc651218..ba3284ad8 100644 --- a/arch/ppc/kernel/head_4xx.S +++ b/arch/ppc/kernel/head_4xx.S @@ -27,10 +27,8 @@ #include <linux/config.h> #include <asm/processor.h> -#include <asm/4xx.h> -#include <asm/403gcx.h> -#include <asm/405gp.h> #include <asm/page.h> +#include <asm/pgtable.h> #include <asm/mmu.h> #include "ppc_asm.h" @@ -58,7 +56,7 @@ ### execution begins here, the following registers contain valid, yet ### optional, information: ### -### r3 - ??? +### r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.) ### r4 - Starting address of the init RAM disk ### r5 - Ending address of the init RAM disk ### r6 - Start of kernel command line string (e.g. "mem=96m") @@ -80,17 +78,55 @@ _GLOBAL(_start) li r24,0 - ## Establish exception vector base + ## We should still be executing code at physical address 0x0000xxxx + ## at this point. However, start_here is at virtual address + ## 0xC000xxxx. So, set up a TLB mapping to cover this once + ## translation is enabled. + + lis r3,KERNELBASE@h # Load the kernel virtual address + addis r3,r3,KERNELBASE@l + tophys(r4,r3) # Load the kernel physical address + + ## Save the existing PID and load the kernel PID. + + mfspr r7,SPRN_PID # Save the old PID + li r0,0 + mtspr SPRN_PID,r0 # Load the kernel PID + + ## Configure and load entry into TLB slot 0. - lis r0,KERNELBASE@h - mtspr SPRN_EVPR,r0 + clrrwi r4,r4,10 # Mask off the real page number - ## Jump to the main PowerPC kernel start-up code + ## XXX - Temporarily set the TLB_I bit because of cache issues that + ## seem to foul-up the exception handling code. + + ori r4,r4,(TLB_WR | TLB_EX | TLB_I) # Set the write and execute bits -1: lis r7,start_here@ha - addi r7,r7,start_here@l - mtlr r7 - blr + clrrwi r3,r3,10 # Mask off the effective page number + ori r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M)) + + tlbwe r4,r0,TLB_DATA # Load the data portion of the entry + tlbwe r3,r0,TLB_TAG # Load the tag portion of the entry + isync + + mtspr SPRN_PID,r7 # Restore the existing PID + + ## Establish the exception vector base + + lis r4,KERNELBASE@h # EVPR only uses the high 16-bits + tophys(r0,r4) # Use the physical address + mtspr SPRN_EVPR,r0 + + ## Enable the MMU and jump to the main PowerPC kernel start-up code + + mfmsr r0 # Get the machine state register + ori r0,r0,(MSR_DR | MSR_IR) # Enable data and instr. translation + mtspr SPRN_SRR1,r0 # Set up the new machine state register + lis r0,start_here@h + ori r0,r0,start_here@l + mtspr SPRN_SRR0,r0 # Set up the new instruction pointer + rfi # Jump to start_here w/ translation on + ### ### Exception vector entry code. This code runs with address translation @@ -129,7 +165,8 @@ _GLOBAL(_start) stw r2,GPR2(r21); /* Save r2 on the stack */\ stw r1,0(r21); \ tovirt(r1,r21); /* Set-up new kernel stack pointer */\ - SAVE_4GPRS(3, r21); /* Save r3 through r6 on the stack */ + SAVE_4GPRS(3, r21); /* Save r3 through r6 on the stack */\ + SAVE_GPR(7, r21); /* Save r7 on the stack */ ## Common exception code for standard (non-critical) exceptions. @@ -166,7 +203,7 @@ label: START_EXCEPTION(n, label); \ STND_EXCEPTION_PROLOG; \ addi r3,r1,STACK_FRAME_OVERHEAD; \ - li r0,STND_EXC; \ + li r7,STND_EXC; \ li r20,MSR_KERNEL; \ FINISH_EXCEPTION(func) @@ -175,23 +212,10 @@ label: START_EXCEPTION(n, label); \ CRIT_EXCEPTION_PROLOG; \ addi r3,r1,STACK_FRAME_OVERHEAD; \ - li r0,CRIT_EXC; \ + li r7,CRIT_EXC; \ li r20,MSR_KERNEL; \ FINISH_EXCEPTION(func) - -#define INTR_EXCEPTION(n, label, func) \ - START_EXCEPTION(n, label); \ - STND_EXCEPTION_PROLOG; \ - addi r3,r1,STACK_FRAME_OVERHEAD; \ - li r0,STND_EXC; \ - li r20,MSR_KERNEL; \ - li r4,0; \ - bl transfer_to_handler; \ -_GLOBAL(do_IRQ_intercept); \ - .long func; \ - .long ret_from_except - ### ### Exception vectors. @@ -214,7 +238,7 @@ _GLOBAL(do_IRQ_intercept); \ mfspr r4,SPRN_DEAR # Grab the DEAR, save it, pass as arg2 stw r4,_DEAR(r21) addi r3,r1,STACK_FRAME_OVERHEAD - li r0,STND_EXC # This is a standard exception + li r7,STND_EXC # This is a standard exception li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, ESR, DEAR) @@ -226,15 +250,24 @@ _GLOBAL(do_IRQ_intercept); \ mr r4,r22 # Pass SRR0 as arg2 mr r5,r23 # Pass SRR1 as arg3 addi r3,r1,STACK_FRAME_OVERHEAD - li r0,STND_EXC # This is a standard exception + li r7,STND_EXC # This is a standard exception li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, SRR0, SRR1) ### 0x0500 - External Interrupt Exception - INTR_EXCEPTION(0x0500, HardwareInterrupt, do_IRQ) - + START_EXCEPTION(0x0500, HardwareInterrupt) + STND_EXCEPTION_PROLOG + addi r3,r1,STACK_FRAME_OVERHEAD + li r7,STND_EXC + li r20,MSR_KERNEL + li r4,0 + bl transfer_to_handler +_GLOBAL(do_IRQ_intercept) + .long do_IRQ + .long ret_from_intercept + ### 0x0600 - Alignment Exception START_EXCEPTION(0x0600, Alignment) @@ -242,7 +275,7 @@ _GLOBAL(do_IRQ_intercept); \ mfspr r4,SPRN_DEAR # Grab the DEAR and save it stw r4,_DEAR(r21) addi r3,r1,STACK_FRAME_OVERHEAD - li r0,STND_EXC # This is a standard exception + li r7,STND_EXC # This is a standard exception li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR FINISH_EXCEPTION(AlignmentException) @@ -252,7 +285,7 @@ _GLOBAL(do_IRQ_intercept); \ START_EXCEPTION(0x0700, ProgramCheck) STND_EXCEPTION_PROLOG addi r3,r1,STACK_FRAME_OVERHEAD - li r0,STND_EXC # This is a standard exception + li r7,STND_EXC # This is a standard exception li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR FINISH_EXCEPTION(ProgramCheckException) @@ -266,7 +299,7 @@ _GLOBAL(do_IRQ_intercept); \ START_EXCEPTION(0x0C00, SystemCall) STND_EXCEPTION_PROLOG stw r3,ORIG_GPR3(r21) - li r0,STND_EXC # This is a standard exception + li r7,STND_EXC # This is a standard exception li r20,MSR_KERNEL rlwimi r20,r23,0,16,16 # Copy EE bit from the saved MSR FINISH_EXCEPTION(DoSyscall) @@ -275,11 +308,21 @@ _GLOBAL(do_IRQ_intercept); \ STND_EXCEPTION(0x0E00, Trap_0E, UnknownException) STND_EXCEPTION(0x0F00, Trap_0F, UnknownException) -#if 0 ### 0x1000 - Programmable Interval Timer (PIT) Exception - STND_EXCEPTION(0x1000, PITException, UnknownException) + START_EXCEPTION(0x1000, Decrementer) + STND_EXCEPTION_PROLOG + lis r0,TSR_PIS@h # Set-up the PIT exception mask + mtspr SPRN_TSR,r0 # Clear the PIT exception + addi r3,r1,STACK_FRAME_OVERHEAD + li r7,STND_EXC # This is a standard exception + li r20,MSR_KERNEL + bl transfer_to_handler +_GLOBAL(timer_interrupt_intercept) + .long timer_interrupt + .long ret_from_intercept +#if 0 ### 0x1010 - Fixed Interval Timer (FIT) Exception STND_EXCEPTION(0x1010, FITException, UnknownException) @@ -294,7 +337,7 @@ _GLOBAL(do_IRQ_intercept); \ START_EXCEPTION(0x1100, DTLBMiss) STND_EXCEPTION_PROLOG addi r3,r1,STACK_FRAME_OVERHEAD - li r0,STND_EXC + li r7,STND_EXC li r20,MSR_KERNEL FINISH_EXCEPTION(UnknownException) @@ -303,7 +346,7 @@ _GLOBAL(do_IRQ_intercept); \ START_EXCEPTION(0x1200, ITLBMiss) STND_EXCEPTION_PROLOG addi r3,r1,STACK_FRAME_OVERHEAD - li r0,STND_EXC + li r7,STND_EXC li r20,MSR_KERNEL FINISH_EXCEPTION(UnknownException) @@ -341,7 +384,6 @@ _GLOBAL(do_IRQ_intercept); \ _GLOBAL(transfer_to_handler) stw r22,_NIP(r21) # Save the faulting IP on the stack stw r23,_MSR(r21) # Save the exception MSR on the stack - SAVE_GPR(7, r21) # Save r7 on the stack SAVE_4GPRS(8, r21) # Save r8 through r11 on the stack SAVE_8GPRS(12, r21) # Save r12 through r19 on the stack SAVE_8GPRS(24, r21) # Save r24 through r31 on the stack @@ -367,7 +409,7 @@ _GLOBAL(transfer_to_handler) bgt- stack_ovf # If r2 < r1 < r2 + TASK_STRUCT_SIZE lwz r24,0(r23) # Virtual address of the handler lwz r23,4(r23) # Handler return pointer - cmpwi cr0,r0,STND_EXC # What type of exception is this? + cmpwi cr0,r7,STND_EXC # What type of exception is this? bne 3f # It is a critical exception... ## Standard exception jump path @@ -432,67 +474,10 @@ _GLOBAL(giveup_fpu) _GLOBAL(abort) mfspr r13,SPRN_DBCR - ori r13,r13,DBCR_RST(SYSTEM)@h + oris r13,r13,DBCR_RST(DBCR_RST_SYSTEM)@h mtspr SPRN_DBCR,r13 - -### -### This code is jumped-to from the startup code. It copies the kernel -### image from wherever it happens to be currently running at in physical -### address space to physical address 0. -### -### In general, for a running Linux/PPC system: -### Kernel Physical Address (KPA) = 0x00000000 -### Kernel Virtual Address (KVA) = 0xC0000000 -### - -#if 0 -relocate_kernel: - lis r9,0x426f /* if booted from BootX, don't */ - addi r9,r9,0x6f58 /* translate source addr */ - cmpw r31,r9 /* (we have to on chrp) */ - beq 7f - rlwinm r4,r4,0,8,31 /* translate source address */ - add r4,r4,r3 /* to region mapped with BATs */ -7: addis r9,r26,klimit@ha /* fetch klimit */ - lwz r25,klimit@l(r9) - addis r25,r25,-KERNELBASE@h - li r6,0 /* Destination offset */ - li r5,0x4000 /* # bytes of memory to copy */ - bl copy_and_flush /* copy the first 0x4000 bytes */ - addi r0,r3,4f@l /* jump to the address of 4f */ - mtctr r0 /* in copy and do the rest. */ - bctr /* jump to the copy */ -4: mr r5,r25 - bl copy_and_flush /* copy the rest */ - b turn_on_mmu -/* - * Copy routine used to copy the kernel to start at physical address 0 - * and flush and invalidate the caches as needed. - * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset - * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5. - */ -copy_and_flush: - addi r5,r5,-4 - addi r6,r6,-4 -4: li r0,8 - mtctr r0 -3: addi r6,r6,4 /* copy a cache line */ - lwzx r0,r6,r4 - stwx r0,r6,r3 - bdnz 3b - dcbst r6,r3 /* write it to memory */ - sync - icbi r6,r3 /* flush the icache line */ - cmplw 0,r6,r5 - blt 4b - isync - addi r5,r5,4 - addi r6,r6,4 - blr -#endif - ### ### This is where the main kernel code starts. ### diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index c5a55c6a2..94cd67d3b 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S @@ -197,7 +197,8 @@ turn_on_mmu: stw r2,GPR2(r21); \ stw r1,0(r21); \ tovirt(r1,r21); /* set new kernel sp */ \ - SAVE_4GPRS(3, r21); + SAVE_4GPRS(3, r21); \ + SAVE_GPR(7, r21); /* * Note: code which follows this uses cr0.eq (set if from kernel), * r21, r22 (SRR0), and r23 (SRR1). @@ -265,34 +266,6 @@ InstructionAccess: . = 0x500; HardwareInterrupt: EXCEPTION_PROLOG; -#ifdef CONFIG_APUS - /* This is horrible, but there's no way around it. Enable the - data cache so the IRQ hardware register can be accessed - without cache intervention. Then disable interrupts and get - the current emulated m68k IPL value. */ - - mfmsr 20 - xori r20,r20,MSR_DR - sync - mtmsr r20 - sync - - lis r3,APUS_IPL_EMU@h - - li r20,(IPLEMU_SETRESET|IPLEMU_DISABLEINT) - stb r20,APUS_IPL_EMU@l(r3) - eieio - - lbz r3,APUS_IPL_EMU@l(r3) - - mfmsr r20 - xori r20,r20,MSR_DR - sync - mtmsr r20 - sync - - stw r3,(_CCR+4)(r21); -#endif addi r3,r1,STACK_FRAME_OVERHEAD li r20,MSR_KERNEL li r4,0 @@ -300,7 +273,7 @@ HardwareInterrupt: .globl do_IRQ_intercept do_IRQ_intercept: .long do_IRQ; - .long ret_from_except + .long ret_from_intercept /* Alignment exception */ @@ -342,7 +315,7 @@ Decrementer: .globl timer_interrupt_intercept timer_interrupt_intercept: .long timer_interrupt - .long ret_from_except + .long ret_from_intercept STD_EXCEPTION(0xa00, Trap_0a, UnknownException) STD_EXCEPTION(0xb00, Trap_0b, UnknownException) @@ -591,7 +564,6 @@ transfer_to_handler: lis r22,MSR_POW@h andc r23,r23,r22 stw r23,_MSR(r21) - SAVE_GPR(7, r21) SAVE_4GPRS(8, r21) SAVE_8GPRS(12, r21) SAVE_8GPRS(24, r21) diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index a09d6ad98..c2f2d1c11 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -294,11 +294,10 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) } } -asmlinkage void do_IRQ(struct pt_regs *regs, int isfake) +asmlinkage int do_IRQ(struct pt_regs *regs, int isfake) { int cpu = smp_processor_id(); int irq; - hardirq_enter( cpu ); /* every arch is required to have a get_irq -- Cort */ @@ -320,10 +319,9 @@ asmlinkage void do_IRQ(struct pt_regs *regs, int isfake) out: hardirq_exit( cpu ); + return 1; /* lets ret_from_int know we can do checks */ } - - unsigned long probe_irq_on (void) { return 0; diff --git a/arch/ppc/kernel/oak_setup.c b/arch/ppc/kernel/oak_setup.c index a9c9137a0..ad2c224bb 100644 --- a/arch/ppc/kernel/oak_setup.c +++ b/arch/ppc/kernel/oak_setup.c @@ -7,26 +7,74 @@ * Description: * Architecture- / platform-specific boot-time initialization code for * the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original - * code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek - * <dmalek@jlc.net>. + * code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek + * <dan@net4x.com>. * */ #include <linux/config.h> #include <linux/init.h> +#include <linux/smp.h> +#include <linux/threads.h> +#include <linux/interrupt.h> +#include <linux/param.h> #include <linux/string.h> +#include <asm/processor.h> +#include <asm/board.h> #include <asm/machdep.h> #include <asm/page.h> +#include "local_irq.h" +#include "ppc4xx_pic.h" +#include "time.h" #include "oak_setup.h" +/* Function Prototypes */ +extern void abort(void); + +/* Global Variables */ + +unsigned char __res[sizeof(bd_t)]; + + +/* + * void __init oak_init() + * + * Description: + * This routine... + * + * Input(s): + * r3 - Optional pointer to a board information structure. + * r4 - Optional pointer to the physical starting address of the init RAM + * disk. + * r5 - Optional pointer to the physical ending address of the init RAM + * disk. + * r6 - Optional pointer to the physical starting address of any kernel + * command-line parameters. + * r7 - Optional pointer to the physical ending address of any kernel + * command-line parameters. + * + * Output(s): + * N/A + * + * Returns: + * N/A + * + */ void __init oak_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { -#if 0 + /* + * If we were passed in a board information, copy it into the + * residual data area. + */ + if (r3) { + memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t)); + } + #if defined(CONFIG_BLK_DEV_INITRD) /* * If the init RAM disk has been configured in, and there's a valid @@ -44,24 +92,25 @@ oak_init(unsigned long r3, unsigned long r4, unsigned long r5, *(char *)(r7 + KERNELBASE) = 0; strcpy(cmd_line, (char *)(r6 + KERNELBASE)); } -#endif /* 0 */ + + /* Initialize machine-dependency vectors */ ppc_md.setup_arch = oak_setup_arch; - ppc_md.setup_residual = NULL; + ppc_md.setup_residual = oak_setup_residual; ppc_md.get_cpuinfo = NULL; ppc_md.irq_cannonicalize = NULL; - ppc_md.init_IRQ = NULL; - ppc_md.get_irq = NULL; + ppc_md.init_IRQ = oak_init_IRQ; + ppc_md.get_irq = oak_get_irq; ppc_md.init = NULL; - ppc_md.restart = NULL; - ppc_md.power_off = NULL; - ppc_md.halt = NULL; + ppc_md.restart = oak_restart; + ppc_md.power_off = oak_power_off; + ppc_md.halt = oak_halt; - ppc_md.time_init = NULL; - ppc_md.set_rtc_time = NULL; - ppc_md.get_rtc_time = NULL; - ppc_md.calibrate_decr = NULL; + ppc_md.time_init = oak_time_init; + ppc_md.set_rtc_time = oak_set_rtc_time; + ppc_md.get_rtc_time = oak_get_rtc_time; + ppc_md.calibrate_decr = oak_calibrate_decr; ppc_md.kbd_setkeycode = NULL; ppc_md.kbd_getkeycode = NULL; @@ -77,8 +126,168 @@ oak_init(unsigned long r3, unsigned long r4, unsigned long r5, return; } +/* + * Document me. + */ void __init oak_setup_arch(void) { + /* XXX - Implement me */ +} + +/* + * int oak_setup_residual() + * + * Description: + * This routine pretty-prints the platform's internal CPU and bus clock + * frequencies into the buffer for usage in /proc/cpuinfo. + * + * Input(s): + * *buffer - Buffer into which CPU and bus clock frequencies are to be + * printed. + * + * Output(s): + * *buffer - Buffer with the CPU and bus clock frequencies. + * + * Returns: + * The number of bytes copied into 'buffer' if OK, otherwise zero or less + * on error. + */ +int +oak_setup_residual(char *buffer) +{ + int len = 0; + bd_t *bp = (bd_t *)__res; + + len += sprintf(len + buffer, + "clock\t\t: %dMHz\n" + "bus clock\t\t: %dMHz\n", + bp->bi_intfreq / 1000000, + bp->bi_busfreq / 1000000); + + return (len); +} + +/* + * Document me. + */ +void __init +oak_init_IRQ(void) +{ + int i; + + ppc4xx_pic_init(); + + for (i = 0; i < NR_IRQS; i++) { + irq_desc[i].handler = ppc4xx_pic; + } + + return; +} + +/* + * Document me. + */ +int +oak_get_irq(struct pt_regs *regs) +{ + return (ppc4xx_pic_get_irq(regs)); +} + +/* + * Document me. + */ +void +oak_restart(char *cmd) +{ + abort(); +} + +/* + * Document me. + */ +void +oak_power_off(void) +{ + oak_restart(NULL); +} + +/* + * Document me. + */ +void +oak_halt(void) +{ + oak_restart(NULL); +} + +/* + * Document me. + */ +void __init +oak_time_init(void) +{ + /* XXX - Implement me */ +} + +/* + * Document me. + */ +int __init +oak_set_rtc_time(unsigned long time) +{ + /* XXX - Implement me */ + + return (0); +} + +/* + * Document me. + */ +unsigned long __init +oak_get_rtc_time(void) +{ + /* XXX - Implement me */ + + return (0); +} + +/* + * void __init oak_calibrate_decr() + * + * Description: + * This routine retrieves the internal processor frequency from the board + * information structure, sets up the kernel timer decrementer based on + * that value, enables the 403 programmable interval timer (PIT) and sets + * it up for auto-reload. + * + * Input(s): + * N/A + * + * Output(s): + * N/A + * + * Returns: + * N/A + * + */ +void __init +oak_calibrate_decr(void) +{ + unsigned int freq; + bd_t *bip = (bd_t *)__res; + + freq = bip->bi_intfreq; + + decrementer_count = freq / HZ; + count_period_num = 1; + count_period_den = freq; + + /* Enable the PIT and set auto-reload of its value */ + + mtspr(SPRN_TCR, TCR_PIE | TCR_ARE); + + /* Clear any pending timer interrupts */ + mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS); } diff --git a/arch/ppc/kernel/oak_setup.h b/arch/ppc/kernel/oak_setup.h index 10f7d7354..62cfac906 100644 --- a/arch/ppc/kernel/oak_setup.h +++ b/arch/ppc/kernel/oak_setup.h @@ -15,14 +15,32 @@ #ifndef __OAK_SETUP_H__ #define __OAK_SETUP_H__ +#include <asm/ptrace.h> +#include <asm/board.h> + + #ifdef __cplusplus extern "C" { #endif -extern void oak_init(unsigned long r3, - unsigned long ird_start, unsigned long ird_end, - unsigned long cline_start, unsigned long cline_end); -extern void oak_setup_arch(void); +extern unsigned char __res[sizeof(bd_t)]; + +extern void oak_init(unsigned long r3, + unsigned long ird_start, + unsigned long ird_end, + unsigned long cline_start, + unsigned long cline_end); +extern void oak_setup_arch(void); +extern int oak_setup_residual(char *buffer); +extern void oak_init_IRQ(void); +extern int oak_get_irq(struct pt_regs *regs); +extern void oak_restart(char *cmd); +extern void oak_power_off(void); +extern void oak_halt(void); +extern void oak_time_init(void); +extern int oak_set_rtc_time(unsigned long now); +extern unsigned long oak_get_rtc_time(void); +extern void oak_calibrate_decr(void); #ifdef __cplusplus diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c index 02e276729..6857aa36f 100644 --- a/arch/ppc/kernel/open_pic.c +++ b/arch/ppc/kernel/open_pic.c @@ -38,6 +38,7 @@ struct hw_interrupt_type open_pic = { 0, 0 }; +int open_pic_irq_offset; /* * Accesses to the current processor's registers @@ -69,7 +70,7 @@ struct hw_interrupt_type open_pic = { * -- Cort */ #define check_arg_irq(irq) \ - /*if (irq < 0 || irq >= (NumSources+open_pic.irq_offset)) \ + /*if (irq < 0 || irq >= (NumSources+open_pic_irq_offset)) \ printk("openpic.c:%d: illegal irq %d\n", __LINE__, irq);*/ #define check_arg_cpu(cpu) \ if (cpu < 0 || cpu >= NumProcessors) \ @@ -212,11 +213,11 @@ void __init openpic_init(int main_pic) /* Initialize external interrupts */ if ( ppc_md.progress ) ppc_md.progress("openpic ext",0x3bc); /* SIOint (8259 cascade) is special */ - openpic_initirq(0, 8, open_pic.irq_offset, 1, 1); + openpic_initirq(0, 8, open_pic_irq_offset, 1, 1); openpic_mapirq(0, 1<<0); for (i = 1; i < NumSources; i++) { /* Enabled, Priority 8 */ - openpic_initirq(i, 8, open_pic.irq_offset+i, 0, + openpic_initirq(i, 8, open_pic_irq_offset+i, 0, i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1); /* Processor 0 */ openpic_mapirq(i, 1<<0); @@ -416,13 +417,13 @@ void openpic_maptimer(u_int timer, u_int cpumask) void openpic_enable_irq(u_int irq) { check_arg_irq(irq); - openpic_clearfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK); + openpic_clearfield(&OpenPIC->Source[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK); } void openpic_disable_irq(u_int irq) { check_arg_irq(irq); - openpic_setfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK); + openpic_setfield(&OpenPIC->Source[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK); } /* diff --git a/arch/ppc/kernel/open_pic.h b/arch/ppc/kernel/open_pic.h index 2673263cf..3e51ffba3 100644 --- a/arch/ppc/kernel/open_pic.h +++ b/arch/ppc/kernel/open_pic.h @@ -7,4 +7,5 @@ void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs); void openpic_enable_IPI(u_int ipi); void do_openpic_setup_cpu(void); +extern int open_pic_irq_offset; #endif /* _PPC_KERNEL_OPEN_PIC_H */ diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index ec1ff3565..6c98bbf2c 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -9,6 +9,7 @@ #include <linux/string.h> #include <linux/init.h> #include <linux/openpic.h> +#include <linux/errno.h> #include <asm/processor.h> #include <asm/io.h> @@ -21,7 +22,7 @@ #include "pci.h" -static void __init pcibios_claim_resources(struct pci_bus *); +static void __init pcibios_claim_resources(struct list_head *); unsigned long isa_io_base = 0; unsigned long isa_mem_base = 0; @@ -69,10 +70,9 @@ struct pci_ops generic_pci_ops = void __init pcibios_init(void) { printk("PCI: Probing PCI hardware\n"); - ioport_resource.end = ~0L; pci_scan_bus(0, &generic_pci_ops, NULL); - pcibios_claim_resources(pci_root); - if ( ppc_md.pcibios_fixup ) + pcibios_claim_resources(&pci_root_buses); + if (ppc_md.pcibios_fixup) ppc_md.pcibios_fixup(); } @@ -162,3 +162,75 @@ void __init pcibios_align_resource(void *data, struct resource *res, unsigned long size) { } + +int pcibios_enable_device(struct pci_dev *dev) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx=0; idx<6; idx++) { + r = &dev->resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", + dev->slot_name, old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + 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_nvram.c b/arch/ppc/kernel/pmac_nvram.c index 99bfa4f8b..ea3338aef 100644 --- a/arch/ppc/kernel/pmac_nvram.c +++ b/arch/ppc/kernel/pmac_nvram.c @@ -10,6 +10,7 @@ #include <asm/io.h> #include <asm/system.h> #include <asm/prom.h> +#include <asm/machdep.h> #include <linux/adb.h> #include <linux/pmu.h> diff --git a/arch/ppc/kernel/pmac_time.c b/arch/ppc/kernel/pmac_time.c index 60b497cd6..3b7dd283f 100644 --- a/arch/ppc/kernel/pmac_time.c +++ b/arch/ppc/kernel/pmac_time.c @@ -24,6 +24,7 @@ #include <asm/system.h> #include <asm/io.h> #include <asm/pgtable.h> +#include <asm/machdep.h> #include "time.h" diff --git a/arch/ppc/kernel/ppc4xx_pic.c b/arch/ppc/kernel/ppc4xx_pic.c new file mode 100644 index 000000000..8b40080b4 --- /dev/null +++ b/arch/ppc/kernel/ppc4xx_pic.c @@ -0,0 +1,204 @@ +/* + * + * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> + * + * Module name: ppc4xx_pic.c + * + * Description: + * Interrupt controller driver for PowerPC 4xx-based processors. + */ + +/* + * The PowerPC 403 cores' Asynchronous Interrupt Controller (AIC) has + * 32 possible interrupts, a majority of which are not implemented on + * all cores. There are six configurable, external interrupt pins and + * there are eight internal interrupts for the on-chip serial port + * (SPU), DMA controller, and JTAG controller. + * + * The PowerPC 405 cores' Universal Interrupt Controller (UIC) has 32 + * possible interrupts as well. There are seven, configurable external + * interrupt pins and there are 17 internal interrupts for the on-chip + * serial port, DMA controller, on-chip Ethernet controller, PCI, etc. + * + */ + +#include <linux/init.h> +#include <linux/sched.h> +#include <linux/signal.h> +#include <linux/stddef.h> + +#include <asm/processor.h> +#include <asm/system.h> +#include <asm/irq.h> + +#include "local_irq.h" +#include "ppc4xx_pic.h" + + +/* Global Variables */ + +struct hw_interrupt_type *ppc4xx_pic; + + +/* Function Prototypes */ + +static void ppc403_aic_enable(unsigned int irq); +static void ppc403_aic_disable(unsigned int irq); +static void ppc403_aic_disable_and_ack(unsigned int irq); + +static void ppc405_uic_enable(unsigned int irq); +static void ppc405_uic_disable(unsigned int irq); +static void ppc405_uic_disable_and_ack(unsigned int irq); + +static struct hw_interrupt_type ppc403_aic = { + "403GC AIC", + NULL, + NULL, + ppc403_aic_enable, + ppc403_aic_disable, + ppc403_aic_disable_and_ack, + 0 +}; + +static struct hw_interrupt_type ppc405_uic = { + "405GP UIC", + NULL, + NULL, + ppc405_uic_enable, + ppc405_uic_disable, + ppc405_uic_disable_and_ack, + 0 +}; + +/* + * Document me. + */ +void __init +ppc4xx_pic_init(void) +{ + unsigned long ver = PVR_VER(mfspr(SPRN_PVR)); + + switch (ver) { + + case PVR_VER(PVR_403GC): + /* + * Disable all external interrupts until they are + * explicity requested. + */ + ppc_cached_irq_mask[0] = 0; + mtdcr(DCRN_EXIER, 0); + + ppc4xx_pic = &ppc403_aic; + break; + + case PVR_VER(PVR_405GP): + ppc4xx_pic = &ppc405_uic; + break; + } + + return; +} + +/* + * XXX - Currently 403-specific! + * + * Document me. + */ +int +ppc4xx_pic_get_irq(struct pt_regs *regs) +{ + int irq; + unsigned long bits, mask = (1 << 31); + + /* + * Only report the status of those interrupts that are actually + * enabled. + */ + + bits = mfdcr(DCRN_EXISR) & mfdcr(DCRN_EXIER); + + /* + * Walk through the interrupts from highest priority to lowest, and + * report the first pending interrupt found. + */ + + for (irq = 0; irq < NR_IRQS; irq++, mask >>= 1) { + if (bits & mask) + break; + } + + return (irq); +} + +/* + * Document me. + */ +static void +ppc403_aic_enable(unsigned int irq) +{ + int bit, word; + + bit = irq & 0x1f; + word = irq >> 5; + + ppc_cached_irq_mask[word] |= (1 << (31 - bit)); + mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); +} + +/* + * Document me. + */ +static void +ppc403_aic_disable(unsigned int irq) +{ + int bit, word; + + bit = irq & 0x1f; + word = irq >> 5; + + ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); + mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); +} + +/* + * Document me. + */ +static void +ppc403_aic_disable_and_ack(unsigned int irq) +{ + int bit, word; + + bit = irq & 0x1f; + word = irq >> 5; + + ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); + mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); + mtdcr(DCRN_EXISR, (1 << (31 - bit))); +} + +/* + * Document me. + */ +static void +ppc405_uic_enable(unsigned int irq) +{ + /* XXX - Implement me. */ +} + +/* + * Document me. + */ +static void +ppc405_uic_disable(unsigned int irq) +{ + /* XXX - Implement me. */ +} + +/* + * Document me. + */ +static void +ppc405_uic_disable_and_ack(unsigned int irq) +{ + /* XXX - Implement me. */ +} diff --git a/arch/ppc/kernel/ppc4xx_pic.h b/arch/ppc/kernel/ppc4xx_pic.h new file mode 100644 index 000000000..6de862a46 --- /dev/null +++ b/arch/ppc/kernel/ppc4xx_pic.h @@ -0,0 +1,36 @@ +/* + * + * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> + * + * Module name: ppc4xx_pic.h + * + * Description: + * Interrupt controller driver for PowerPC 4xx-based processors. + */ + +#ifndef __PPC4XX_PIC_H__ +#define __PPC4XX_PIC_H__ + +#include <asm/ptrace.h> + + +#ifdef __cplusplus +extern "C" { +#endif + +/* External Global Variables */ + +extern struct hw_interrupt_type *ppc4xx_pic; + + +/* Function Prototypes */ + +extern void ppc4xx_pic_init(void); +extern int ppc4xx_pic_get_irq(struct pt_regs *regs); + + +#ifdef __cplusplus +} +#endif + +#endif /* __PPC4XX_PIC_H__ */ diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 397685d43..65e925034 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -260,10 +260,8 @@ EXPORT_SYMBOL(screen_info); #endif EXPORT_SYMBOL(int_control); -#if !defined(CONFIG_4xx) EXPORT_SYMBOL(timer_interrupt_intercept); EXPORT_SYMBOL(timer_interrupt); -#endif extern unsigned long do_IRQ_intercept; EXPORT_SYMBOL(do_IRQ_intercept); EXPORT_SYMBOL(irq_desc); @@ -272,3 +270,4 @@ EXPORT_SYMBOL(ppc_irq_dispatch_handler); EXPORT_SYMBOL(decrementer_count); EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(console_drivers); +EXPORT_SYMBOL(do_bottom_half); diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index 64b171042..241b7c33c 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -287,11 +287,12 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, struct task_struct * p, struct pt_regs * regs) { + unsigned long msr; struct pt_regs * childregs, *kregs; #ifdef __SMP__ extern void ret_from_smpfork(void); #else - extern void ret_from_syscall(void); + extern void ret_from_except(void); #endif /* Copy registers */ childregs = ((struct pt_regs *) @@ -308,9 +309,10 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, #ifdef __SMP__ kregs->nip = (unsigned long)ret_from_smpfork; #else - kregs->nip = (unsigned long)ret_from_syscall; + kregs->nip = (unsigned long)ret_from_except; #endif - kregs->msr = MSR_KERNEL; + asm volatile("mfmsr %0" : "=r" (msr):); + kregs->msr = msr; kregs->gpr[1] = (unsigned long)childregs - STACK_FRAME_OVERHEAD; kregs->gpr[2] = (unsigned long)p; diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index caffdcf99..dccb066ff 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -29,8 +29,9 @@ #endif #include <asm/bootx.h> #include <asm/machdep.h> - +#ifdef CONFIG_OAK #include "oak_setup.h" +#endif /* CONFIG_OAK */ extern void pmac_init(unsigned long r3, unsigned long r4, @@ -71,7 +72,13 @@ extern void gemini_init(unsigned long r3, extern boot_infos_t *boot_infos; char saved_command_line[256]; unsigned char aux_device_present; -struct int_control_struct int_control; +struct int_control_struct int_control = +{ + __no_use_cli, + __no_use_sti, + __no_use_restore_flags, + __no_use_save_flags +}; struct ide_machdep_calls ppc_ide_md; int parse_bootinfo(void); @@ -89,20 +96,13 @@ unsigned long SYSRQ_KEY; struct machdep_calls ppc_md; -/* copy of the residual data */ -#ifndef CONFIG_8xx -extern unsigned char __res[sizeof(RESIDUAL)]; -#else -extern unsigned char __res[sizeof(bd_t)]; -#endif - /* * Perhaps we can put the pmac screen_info[] here * on pmac as well so we don't need the ifdef's. * Until we get multiple-console support in here * that is. -- Cort */ -#ifndef CONFIG_8xx +#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) struct screen_info screen_info = { 0, 25, /* orig-x, orig-y */ 0, /* unused */ @@ -126,7 +126,7 @@ void __init pmac_find_display(void) { } -#else /* CONFIG_8xx */ +#else /* CONFIG_4xx || CONFIG_8xx */ /* We need this to satisfy some external references until we can * strip the kernel down. @@ -142,7 +142,7 @@ struct screen_info screen_info = { 0, /* orig-video-isVGA */ 16 /* orig-video-points */ }; -#endif /* CONFIG_8xx */ +#endif /* !CONFIG_4xx && !CONFIG_8xx */ void machine_restart(char *cmd) { @@ -193,6 +193,7 @@ int get_cpuinfo(char *buffer) unsigned long len = 0; unsigned long bogosum = 0; unsigned long i; + unsigned int pvr; unsigned short maj, min; #ifdef __SMP__ @@ -215,45 +216,75 @@ int get_cpuinfo(char *buffer) len += sprintf(len+buffer,"processor\t: %lu\n",i); len += sprintf(len+buffer,"cpu\t\t: "); - switch (GET_PVR >> 16) + pvr = GET_PVR; + + switch (PVR_VER(pvr)) { - case 1: + case 0x0001: len += sprintf(len+buffer, "601\n"); break; - case 3: + case 0x0003: len += sprintf(len+buffer, "603\n"); break; - case 4: + case 0x0004: len += sprintf(len+buffer, "604\n"); break; - case 6: + case 0x0006: len += sprintf(len+buffer, "603e\n"); break; - case 7: - len += sprintf(len+buffer, "603ev\n"); + case 0x0007: + len += sprintf(len+buffer, "603"); + if (((pvr >> 12) & 0xF) == 1) { + pvr ^= 0x00001000; /* revision fix-up */ + len += sprintf(len+buffer, "r\n"); + } else { + len += sprintf(len+buffer, "ev\n"); + } break; - case 8: - len += sprintf(len+buffer, "750\n"); + case 0x0008: /* 740/750(P) */ + case 0x1008: + len += sprintf(len+buffer, "750%s\n", + PVR_VER(pvr) == 0x1008 ? "P" : ""); len += sprintf(len+buffer, "temperature \t: %lu C\n", cpu_temp()); break; - case 9: - len += sprintf(len+buffer, "604e\n"); + case 0x0009: /* 604e/604r */ + case 0x000A: + len += sprintf(len+buffer, "604"); + + if (PVR_VER(pvr) == 0x000A || + ((pvr >> 12) & 0xF) != 0) { + pvr &= ~0x00003000; /* revision fix-up */ + len += sprintf(len+buffer, "r\n"); + } else { + len += sprintf(len+buffer, "e\n"); + } break; - case 10: - len += sprintf(len+buffer, "604ev5 (MachV)\n"); + case 0x000C: + len += sprintf(len+buffer, "7400\n"); break; - case 12: - len += sprintf(len+buffer, "7400 (G4)\n"); + case 0x0020: + len += sprintf(len+buffer, "403G"); + switch ((pvr >> 8) & 0xFF) { + case 0x02: + len += sprintf(len+buffer, "C\n"); + break; + case 0x14: + len += sprintf(len+buffer, "CX\n"); + break; + } break; - case 50: + case 0x0050: len += sprintf(len+buffer, "821\n"); - case 80: - len += sprintf(len+buffer, "860\n"); + break; + case 0x0081: + len += sprintf(len+buffer, "8240\n"); + break; + case 0x4011: + len += sprintf(len+buffer, "405GP\n"); break; default: - len += sprintf(len+buffer, "unknown (%lx)\n", - GET_PVR>>16); + len += sprintf(len+buffer, "unknown (%08x)\n", pvr); break; } @@ -292,6 +323,22 @@ int get_cpuinfo(char *buffer) len += ppc_md.setup_residual(buffer + len); } + switch (PVR_VER(pvr)) + { + case 0x0020: + maj = PVR_MAJ(pvr) + 1; + min = PVR_MIN(pvr); + break; + case 0x1008: + maj = ((pvr >> 8) & 0xFF) - 1; + min = pvr & 0xFF; + break; + default: + maj = (pvr >> 8) & 0xFF; + min = pvr & 0xFF; + break; + } + len += sprintf(len+buffer, "revision\t: %hd.%hd\n", maj, min); len += sprintf(buffer+len, "bogomips\t: %lu.%02lu\n", @@ -362,11 +409,6 @@ unsigned long __init identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { - int_control.int_sti = __no_use_sti; - int_control.int_cli = __no_use_cli; - int_control.int_save_flags = __no_use_save_flags; - int_control.int_restore_flags = __no_use_restore_flags; - parse_bootinfo(); if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100); @@ -674,25 +716,25 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id) id->word72 = __le16_to_cpu(id->word72); id->word73 = __le16_to_cpu(id->word73); id->word74 = __le16_to_cpu(id->word74); - id->word75 = __le16_to_cpu(id->word75); + id->queue_depth = __le16_to_cpu(id->queue_depth); id->word76 = __le16_to_cpu(id->word76); id->word77 = __le16_to_cpu(id->word77); id->word78 = __le16_to_cpu(id->word78); id->word79 = __le16_to_cpu(id->word79); - id->word80 = __le16_to_cpu(id->word80); - id->word81 = __le16_to_cpu(id->word81); - id->command_sets = __le16_to_cpu(id->command_sets); - id->word83 = __le16_to_cpu(id->word83); - id->word84 = __le16_to_cpu(id->word84); - id->word85 = __le16_to_cpu(id->word85); - id->word86 = __le16_to_cpu(id->word86); - id->word87 = __le16_to_cpu(id->word87); + id->major_rev_num = __le16_to_cpu(id->major_rev_num); + id->minor_rev_num = __le16_to_cpu(id->minor_rev_num); + id->command_set_1 = __le16_to_cpu(id->command_set_1); + id->command_set_2 = __le16_to_cpu(id->command_set_2); + id->cfsse = __le16_to_cpu(id->cfsse); + id->cfs_enable_1 = __le16_to_cpu(id->cfs_enable_1); + id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2); + id->csf_default = __le16_to_cpu(id->csf_default); id->dma_ultra = __le16_to_cpu(id->dma_ultra); id->word89 = __le16_to_cpu(id->word89); id->word90 = __le16_to_cpu(id->word90); - id->word91 = __le16_to_cpu(id->word91); + id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues); id->word92 = __le16_to_cpu(id->word92); - id->word93 = __le16_to_cpu(id->word93); + id->hw_config = __le16_to_cpu(id->hw_config); id->word94 = __le16_to_cpu(id->word94); id->word95 = __le16_to_cpu(id->word95); id->word96 = __le16_to_cpu(id->word96); @@ -727,7 +769,6 @@ void ppc_generic_ide_fix_driveid(struct hd_driveid *id) id->word125 = __le16_to_cpu(id->word125); id->word126 = __le16_to_cpu(id->word126); id->word127 = __le16_to_cpu(id->word127); - id->security = __le16_to_cpu(id->security); for (i=0; i<127; i++) id->reserved[i] = __le16_to_cpu(id->reserved[i]); } diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index c2891e21f..386764ddd 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -446,6 +446,8 @@ void __init smp_callin(void) */ if ( _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep) ) do_openpic_setup_cpu(); + if ( _machine == _MACH_gemini ) + gemini_init_l2(); while(!smp_commenced) barrier(); __sti(); diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index e21c30e14..b695da797 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c @@ -68,7 +68,7 @@ unsigned count_period_den; /* count_period_num / count_period_den us */ * with interrupts disabled. * We set it up to overflow again in 1/HZ seconds. */ -void timer_interrupt(struct pt_regs * regs) +int timer_interrupt(struct pt_regs * regs) { int dval, d; unsigned long cpu = smp_processor_id(); @@ -141,6 +141,7 @@ void timer_interrupt(struct pt_regs * regs) ppc_md.heartbeat(); hardirq_exit(cpu); + return 1; /* lets ret_from_int know we can do checks */ } /* diff --git a/arch/ppc/kernel/time.h b/arch/ppc/kernel/time.h index a0a5c62d2..05d791546 100644 --- a/arch/ppc/kernel/time.h +++ b/arch/ppc/kernel/time.h @@ -6,8 +6,11 @@ * Paul Mackerras' version and mine for PReP and Pmac. */ +#include <linux/config.h> #include <linux/mc146818rtc.h> +#include <asm/processor.h> + /* time.c */ extern unsigned decrementer_count; extern unsigned count_period_num; @@ -22,13 +25,18 @@ int via_calibrate_decr(void); /* Accessor functions for the decrementer register. */ static __inline__ unsigned int get_dec(void) { - unsigned int ret; - - asm volatile("mfspr %0,22" : "=r" (ret) :); - return ret; +#if defined(CONFIG_4xx) + return (mfspr(SPRN_PIT)); +#else + return (mfspr(SPRN_DEC)); +#endif } static __inline__ void set_dec(unsigned int val) { - asm volatile("mtspr 22,%0" : : "r" (val)); +#if defined(CONFIG_4xx) + mtspr(SPRN_PIT, val); +#else + mtspr(SPRN_DEC, val); +#endif } diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 47fef50d4..04b4e2d36 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -194,7 +194,6 @@ void ProgramCheckException(struct pt_regs *regs) { #if defined(CONFIG_4xx) - unsigned int instr; unsigned int esr = mfspr(SPRN_ESR); if (esr & ESR_PTR) { diff --git a/arch/ppc/mm/4xx_tlb.c b/arch/ppc/mm/4xx_tlb.c new file mode 100644 index 000000000..b9d9d2119 --- /dev/null +++ b/arch/ppc/mm/4xx_tlb.c @@ -0,0 +1,397 @@ +/* + * + * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> + * + * Module name: 4xx_tlb.c + * + * Description: + * Routines for manipulating the TLB on PowerPC 400-class processors. + * + */ + +#include <asm/processor.h> +#include <asm/mmu.h> +#include <asm/pgtable.h> +#include <asm/system.h> + + +/* Preprocessor Defines */ + +#if !defined(TRUE) || TRUE != 1 +#define TRUE 1 +#endif + +#if !defined(FALSE) || FALSE != 0 +#define FALSE 0 +#endif + + +/* Function Macros */ + + +/* Type Definitios */ + +typedef struct pin_entry_s { + unsigned int e_pinned: 1, /* This TLB entry is pinned down. */ + e_used: 23; /* Number of users for this mapping. */ +} pin_entry_t; + + +/* Global Variables */ + +static pin_entry_t pin_table[PPC4XX_TLB_SIZE]; + + +/* Function Prototypes */ + + +void +PPC4xx_tlb_pin(unsigned long va, unsigned long pa, int pagesz, int cache) +{ + int i, found = FALSE; + unsigned long tag, data; + unsigned long opid; + + opid = mfspr(SPRN_PID); + mtspr(SPRN_PID, 0); + + data = (pa & TLB_RPN_MASK) | TLB_WR; + + if (cache) + data |= (TLB_EX | TLB_I); + else + data |= (TLB_G | TLB_I); + + tag = (va & TLB_EPN_MASK) | TLB_VALID | pagesz; + + for (i = 0; i < PPC4XX_TLB_SIZE; i++) { + if (pin_table[i].e_pinned == FALSE) { + found = TRUE; + break; + } + } + + if (found) { + /* printk("Pinning %#x -> %#x in entry %d...\n", va, pa, i); */ + asm("tlbwe %0,%1,1" : : "r" (data), "r" (i)); + asm("tlbwe %0,%1,0" : : "r" (tag), "r" (i)); + asm("isync"); + pin_table[i].e_pinned = found; + } + + mtspr(SPRN_PID, opid); + return; +} + +void +PPC4xx_tlb_unpin(unsigned long va, unsigned long pa, int size) +{ + /* XXX - To beimplemented. */ +} + +void +PPC4xx_tlb_flush_all(void) +{ + int i; + unsigned long flags, opid; + + save_flags(flags); + cli(); + + opid = mfspr(SPRN_PID); + mtspr(SPRN_PID, 0); + + for (i = 0; i < PPC4XX_TLB_SIZE; i++) { + unsigned long ov = 0; + + if (pin_table[i].e_pinned) + continue; + + asm("tlbwe %0,%1,0" : : "r" (ov), "r" (i)); + asm("tlbwe %0,%1,1" : : "r" (ov), "r" (i)); + } + + asm("sync;isync"); + + mtspr(SPRN_PID, opid); + restore_flags(flags); +} + +void +PPC4xx_tlb_flush(unsigned long va, int pid) +{ + unsigned long i, tag, flags, found = 1, opid; + + save_flags(flags); + cli(); + + opid = mfspr(SPRN_PID); + mtspr(SPRN_PID, pid); + + asm("tlbsx. %0,0,%2;beq 1f;li %1,0;1:" : "=r" (i), "=r" (found) : "r" (va)); + + if (found && pin_table[i].e_pinned == 0) { + asm("tlbre %0,%1,0" : "=r" (tag) : "r" (i)); + tag &= ~ TLB_VALID; + asm("tlbwe %0,%1,0" : : "r" (tag), "r" (i)); + } + + mtspr(SPRN_PID, opid); + + restore_flags(flags); +} + +#if 0 +/* + * TLB miss handling code. + */ + +/* + * Handle TLB faults. We should push this back to assembly code eventually. + * Caller is responsible for turning off interrupts ... + */ +static inline void +tlbDropin(unsigned long tlbhi, unsigned long tlblo) { + /* + * Avoid the divide at the slight cost of a little too + * much emphasis on the last few entries. + */ + unsigned long rand = mfspr(SPRN_TBLO); + rand &= 0x3f; + rand += NTLB_WIRED; + if (rand >= NTLB) + rand -= NTLB_WIRED; + + asm("tlbwe %0,%1,1" : : "r" (tlblo), "r" (rand)); + asm("tlbwe %0,%1,0" : : "r" (tlbhi), "r" (rand)); + asm("isync;sync"); +} + +static inline void +mkTlbEntry(unsigned long addr, pte_t *pte) { + unsigned long tlbhi; + unsigned long tlblo; + int found = 1; + int idx; + + /* + * Construct the TLB entry. + */ + tlbhi = addr & ~(PAGE_SIZE-1); + tlblo = virt_to_phys(pte_page(*pte)) & TLBLO_RPN; + if (pte_val(*pte) & _PAGE_HWWRITE) + tlblo |= TLBLO_WR; + if (pte_val(*pte) & _PAGE_NO_CACHE) + tlblo |= TLBLO_I; + tlblo |= TLBLO_EX; + if (addr < KERNELBASE) + tlblo |= TLBLO_Z_USER; + tlbhi |= TLBHI_PGSZ_4K; + tlbhi |= TLBHI_VALID; + + /* + * See if a match already exists in the TLB. + */ + asm("tlbsx. %0,0,%2;beq 1f;li %1,0;1:" : "=r" (idx), "=r" (found) : "r" (tlbhi)); + if (found) { + /* + * Found an existing entry. Just reuse the index. + */ + asm("tlbwe %0,%1,0" : : "r" (tlbhi), "r" (idx)); + asm("tlbwe %0,%1,1" : : "r" (tlblo), "r" (idx)); + } + else { + /* + * Do the more expensive operation + */ + tlbDropin(tlbhi, tlblo); + } +} + +/* + * Mainline of the TLB miss handler. The above inline routines should fold into + * this one, eliminating most function call overhead. + */ +#ifdef TLBMISS_DEBUG +volatile unsigned long miss_start; +volatile unsigned long miss_end; +#endif + +static inline int tlbMiss(struct pt_regs *regs, unsigned long badaddr, int wasWrite) +{ + int spid, ospid; + struct mm_struct *mm; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + + if (!user_mode(regs) && (badaddr >= KERNELBASE)) { + mm = task[0]->mm; + spid = 0; +#ifdef TLBMISS_DEBUG + miss_start = 0; +#endif + } + else { + mm = current->mm; + spid = mfspr(SPRN_PID); +#ifdef TLBMISS_DEBUG + miss_start = 1; +#endif + } +#ifdef TLBMISS_DEBUG + store_cache_range((unsigned long)&miss_start, sizeof(miss_start)); +#endif + + pgd = pgd_offset(mm, badaddr); + if (pgd_none(*pgd)) + goto NOGOOD; + + pmd = pmd_offset(pgd, badaddr); + if (pmd_none(*pmd)) + goto NOGOOD; + + pte = pte_offset(pmd, badaddr); + if (pte_none(*pte)) + goto NOGOOD; + if (!pte_present(*pte)) + goto NOGOOD; +#if 1 + prohibit_if_guarded(badaddr, sizeof(int)); +#endif + if (wasWrite) { + if (!pte_write(*pte)) { + goto NOGOOD; + } + set_pte(pte, pte_mkdirty(*pte)); + } + set_pte(pte, pte_mkyoung(*pte)); + + ospid = mfspr(SPRN_PID); + mtspr(SPRN_PID, spid); + mkTlbEntry(badaddr, pte); + mtspr(SPRN_PID, ospid); + +#ifdef TLBMISS_DEBUG + miss_end = 0; + store_cache_range((unsigned long)&miss_end, sizeof(miss_end)); +#endif + return 0; + +NOGOOD: +#ifdef TLBMISS_DEBUG + miss_end = 1; + store_cache_range((unsigned long)&miss_end, sizeof(miss_end)); +#endif + return 1; +} + +/* + * End TLB miss handling code. + */ +/* ---------- */ + +/* + * Used to flush the TLB if the page fault handler decides to change + * something. + */ +void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) { + int spid; + unsigned long flags; + + save_flags(flags); + cli(); + + if (addr >= KERNELBASE) + spid = 0; + else + spid = vma->vm_mm->context; + tlbFlush1(addr, spid); + + restore_flags(flags); +} + +/* + * Given a virtual address in the current address space, make + * sure the associated physical page is present in memory, + * and if the data is to be modified, that any copy-on-write + * actions have taken place. + */ +unsigned long make_page_present(unsigned long p, int rw) { + pte_t *pte; + char c; + + get_user(c, (char *) p); + + pte = findPTE(current->mm, p); + if (pte_none(*pte) || !pte_present(*pte)) + debug("make_page_present didn't load page", 0); + + if (rw) { + /* + * You have to write-touch the page, so that + * zero-filled pages are forced to be copied + * rather than still pointing at the zero + * page. + */ + extern void tlbFlush1(unsigned long, int); + tlbFlush1(p, get_context()); + put_user(c, (char *) p); + if (!pte_write(*pte)) + debug("make_page_present didn't make page writable", 0); + + tlbFlush1(p, get_context()); + } + return pte_page(*pte); +} + +void DataTLBMissException(struct pt_regs *regs) +{ + unsigned long badaddr = mfspr(SPRN_DEAR); + int wasWrite = mfspr(SPRN_ESR) & 0x800000; + if (tlbMiss(regs, badaddr, wasWrite)) { + sti(); + do_page_fault(regs, badaddr, wasWrite); + cli(); + } +} + +void InstructionTLBMissException(struct pt_regs *regs) +{ + if (!current) { + debug("ITLB Miss with no current task", regs); + sti(); + bad_page_fault(regs, regs->nip); + cli(); + return; + } + if (tlbMiss(regs, regs->nip, 0)) { + sti(); + do_page_fault(regs, regs->nip, 0); + cli(); + } +} + +void DataPageFault(struct pt_regs *regs) +{ + unsigned long badaddr = mfspr(SPRN_DEAR); + int wasWrite = mfspr(SPRN_ESR) & 0x800000; + sti(); + do_page_fault(regs, badaddr, wasWrite); + cli(); +} + +void InstructionPageFault(struct pt_regs *regs) +{ + if (!current) { + debug("ITLB fault with no current task", regs); + sti(); + bad_page_fault(regs, regs->nip); + cli(); + return; + } + sti(); + do_page_fault(regs, regs->nip, 0); + cli(); +} +#endif diff --git a/arch/ppc/mm/4xx_tlb.h b/arch/ppc/mm/4xx_tlb.h new file mode 100644 index 000000000..03fef109f --- /dev/null +++ b/arch/ppc/mm/4xx_tlb.h @@ -0,0 +1,35 @@ +/* + * + * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> + * + * Module name: 4xx_tlb.h + * + * Description: + * Routines for manipulating the TLB on PowerPC 400-class processors. + * + */ + +#ifndef __4XX_TLB_H__ +#define __4XX_TLB_H__ + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Function Prototypes */ + +extern void PPC4xx_tlb_pin(unsigned long va, unsigned long pa, + int pagesz, int cache); +extern void PPC4xx_tlb_unpin(unsigned long va, unsigned long pa, + int size); +extern void PPC4xx_tlb_flush_all(void); +extern void PPC4xx_tlb_flush(unsigned long va, int pid); + + +#ifdef __cplusplus +} +#endif + +#endif /* __4XX_TLB_H__ */ diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c index 34117098e..c558ef051 100644 --- a/arch/ppc/mm/init.c +++ b/arch/ppc/mm/init.c @@ -59,6 +59,10 @@ #include "mem_pieces.h" +#if defined(CONFIG_4xx) +#include "4xx_tlb.h" +#endif + #define PGTOKB(pages) (((pages) * PAGE_SIZE) >> 10) int prom_trashed; @@ -97,6 +101,9 @@ extern unsigned long *find_end_of_memory(void); #ifdef CONFIG_8xx unsigned long *m8xx_find_end_of_memory(void); #endif /* CONFIG_8xx */ +#ifdef CONFIG_4xx +unsigned long *oak_find_end_of_memory(void); +#endif static void mapin_ram(void); void map_page(unsigned long va, unsigned long pa, int flags); extern void die_if_kernel(char *,struct pt_regs *,long); @@ -339,9 +346,7 @@ void si_meminfo(struct sysinfo *val) continue; val->sharedram += atomic_read(&mem_map[i].count) - 1; } - val->totalram <<= PAGE_SHIFT; - val->sharedram <<= PAGE_SHIFT; - return; + val->mem_unit = PAGE_SIZE; } void * @@ -682,7 +687,7 @@ static void __init mapin_ram(void) int i; unsigned long v, p, s, f; -#ifndef CONFIG_8xx +#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) if (!__map_without_bats) { unsigned long tot, mem_base, bl, done; unsigned long max_size = (256<<20); @@ -717,7 +722,7 @@ static void __init mapin_ram(void) RAM_PAGE); } } -#endif /* CONFIG_8xx */ +#endif /* !CONFIG_4xx && !CONFIG_8xx */ for (i = 0; i < phys_mem.n_regions; ++i) { v = (ulong)__va(phys_mem.regions[i].address); @@ -846,6 +851,31 @@ void free_initrd_mem(unsigned long start, unsigned long end) * still be merged. * -- Cort */ +#if defined(CONFIG_4xx) +void __init +MMU_init(void) +{ + PPC4xx_tlb_pin(KERNELBASE, 0, TLB_PAGESZ(PAGESZ_16M), 1); + PPC4xx_tlb_pin(OAKNET_IO_BASE, OAKNET_IO_BASE, TLB_PAGESZ(PAGESZ_4K), 0); + end_of_DRAM = oak_find_end_of_memory(); + + /* Map in all of RAM starting at KERNELBASE */ + + mapin_ram(); + + /* Zone 0 - kernel (above 0x80000000), zone 1 - user */ + + mtspr(SPRN_ZPR, 0x2aaaaaaa); + mtspr(SPRN_DCWR, 0x00000000); /* all caching is write-back */ + + /* Cache 128MB of space starting at KERNELBASE. */ + + mtspr(SPRN_DCCR, 0x00000000); + /* flush_instruction_cache(); XXX */ + mtspr(SPRN_ICCR, 0x00000000); + +} +#else void __init MMU_init(void) { if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111); @@ -947,6 +977,7 @@ void __init MMU_init(void) #endif /* CONFIG_8xx */ if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211); } +#endif /* CONFIG_4xx */ /* * Initialize the bootmem system and give it all the memory we @@ -1037,29 +1068,21 @@ unsigned long __init find_available_memory(void) */ void __init paging_init(void) { + unsigned int zones_size[MAX_NR_ZONES], i; + /* * Grab some memory for bad_page and bad_pagetable to use. */ empty_bad_page = alloc_bootmem_pages(PAGE_SIZE); empty_bad_page_table = alloc_bootmem_pages(PAGE_SIZE); - { - unsigned int zones_size[MAX_NR_ZONES], i; - /* - * All pages are DMA-able so this is wrong - the zone code is - * assuming both regions have a value so this is necessary for - * now. - * -- Cort - */ -#if 1 - for ( i = 1; i < MAX_NR_ZONES; i++ ) - zones_size[i] = 1<<MAX_ORDER; - zones_size[0] = (virt_to_phys(end_of_DRAM) >> PAGE_SHIFT) - - ((MAX_NR_ZONES-1)*(1<<MAX_ORDER)); -#else - zones_size[0] = virt_to_phys(end_of_DRAM) >> PAGE_SHIFT; -#endif - free_area_init(zones_size); - } + + /* + * All pages are DMA-able so we put them all in the DMA zone. + */ + zones_size[0] = virt_to_phys(end_of_DRAM) >> PAGE_SHIFT; + for (i = 1; i < MAX_NR_ZONES; i++) + zones_size[i] = 0; + free_area_init(zones_size); } void __init mem_init(void) @@ -1404,7 +1427,7 @@ static void __init hash_init(void) } if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205); } -#else /* CONFIG_8xx */ +#elif defined(CONFIG_8xx) /* * This is a big hack right now, but it may turn into something real * someday. @@ -1432,4 +1455,29 @@ unsigned long __init *m8xx_find_end_of_memory(void) set_phys_avail(&phys_mem); return ret; } -#endif /* ndef CONFIG_8xx */ +#endif /* !CONFIG_4xx && !CONFIG_8xx */ + +#ifdef CONFIG_OAK +/* + * Return the virtual address representing the top of physical RAM + * on the Oak board. + */ +unsigned long __init * +oak_find_end_of_memory(void) +{ + extern unsigned char __res[]; + + unsigned long *ret; + bd_t *bip = (bd_t *)__res; + + phys_mem.regions[0].address = 0; + phys_mem.regions[0].size = bip->bi_memsize; + phys_mem.n_regions = 1; + + ret = __va(phys_mem.regions[0].address + + phys_mem.regions[0].size); + + set_phys_avail(&phys_mem); + return (ret); +} +#endif diff --git a/arch/ppc/mm/mem_pieces.c b/arch/ppc/mm/mem_pieces.c index 138b2a40f..e695d5a0a 100644 --- a/arch/ppc/mm/mem_pieces.c +++ b/arch/ppc/mm/mem_pieces.c @@ -209,8 +209,6 @@ set_phys_avail(struct mem_pieces *mp) kstart = __pa(_stext); /* should be 0 */ ksize = PAGE_ALIGN(klimit - _stext); - printk("kstart = 0x%08lx, ksize = 0x%08lx\n", kstart, ksize); - mem_pieces_remove(&phys_avail, kstart, ksize, 0); mem_pieces_remove(&phys_avail, 0, 0x4000, 0); diff --git a/arch/ppc/treeboot/Makefile b/arch/ppc/treeboot/Makefile index 405634214..f84810e1e 100644 --- a/arch/ppc/treeboot/Makefile +++ b/arch/ppc/treeboot/Makefile @@ -21,9 +21,9 @@ MKEVIMG = mkevimg -l MKIRIMG = mkirimg CFLAGS = -O -fno-builtin -I$(TOPDIR)/include -LD_ARGS = -e _start -T ld.script -Ttext 80200000 -Bstatic +LD_ARGS = -e _start -T ld.script -Ttext 0x00200000 -Bstatic -OBJS = crt0.o main.o misc.o string.o zlib.o irSect.o +OBJS = crt0.o main.o misc.o irSect.o ../coffboot/string.o ../coffboot/zlib.o LIBS = treeboot: $(OBJS) ld.script diff --git a/arch/ppc/treeboot/crt0.S b/arch/ppc/treeboot/crt0.S index 1f2c1c094..e54ac2331 100644 --- a/arch/ppc/treeboot/crt0.S +++ b/arch/ppc/treeboot/crt0.S @@ -20,7 +20,7 @@ * */ -#include "../kernel/ppc_asm.h" +#include "../kernel/ppc_asm.tmpl" .text diff --git a/arch/ppc/treeboot/main.c b/arch/ppc/treeboot/main.c index 1b5ef3805..277b77047 100644 --- a/arch/ppc/treeboot/main.c +++ b/arch/ppc/treeboot/main.c @@ -24,13 +24,22 @@ * */ -#include "nonstdio.h" -#include "zlib.h" +#include <asm/board.h> + +#include "../coffboot/nonstdio.h" +#include "../coffboot/zlib.h" #include "irSect.h" /* Preprocessor Defines */ +/* + * Location of the IBM boot ROM function pointer address for retrieving + * the board information structure. + */ + +#define BOARD_INFO_VECTOR 0xFFFE0B50 + #define RAM_SIZE (4 * 1024 * 1024) #define RAM_PBASE 0x00000000 @@ -58,6 +67,17 @@ char *avail_ram; /* Indicates start of RAM available for heap */ char *end_avail; /* Indicates end of RAM available for heap */ +bd_t board_info; + +/* + * XXX - Until either the IBM boot ROM provides a way of passing arguments to + * the program it launches or until I/O is working in the boot loader, + * this is a good spot to pass in command line arguments to the kernel + * (e.g. console=tty0). + */ + +static char *cmdline = ""; + /* Function Prototypes */ @@ -75,10 +95,16 @@ void start(void) { void *options; int ns, oh, i; - unsigned sa, len; + unsigned long sa, len; void *dst; unsigned char *im; - unsigned initrd_start, initrd_size; + unsigned long initrd_start, initrd_size; + bd_t *(*get_board_info)(void) = + (bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR); + bd_t *bip = NULL; + + if ((bip = get_board_info()) != NULL) + memcpy(&board_info, bip, sizeof(bd_t)); /* setup_bats(RAM_START); */ @@ -96,6 +122,7 @@ void start(void) end_avail = (char *)initrd_start; } else { + initrd_start = initrd_size = 0; end_avail = (char *)RAM_END; } @@ -117,16 +144,20 @@ void start(void) /* I'm not sure what the 0x200000 parameter is for, but it works. */ - gunzip(dst, 0x200000, cp, &len); + gunzip(dst, 0x200000, cp, (int *)&len); } else { memmove(dst, im, len); } - /* flush_cache(dst, len); */ + flush_cache(dst, len); sa = (unsigned long)dst; - (*(void (*)())sa)(); + (*(void (*)())sa)(&board_info, + initrd_start, + initrd_start + initrd_size, + cmdline, + cmdline + strlen(cmdline)); pause(); } diff --git a/arch/ppc/treeboot/misc.S b/arch/ppc/treeboot/misc.S index 27417563f..c51844329 100644 --- a/arch/ppc/treeboot/misc.S +++ b/arch/ppc/treeboot/misc.S @@ -6,6 +6,9 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ + +#include "../kernel/ppc_asm.tmpl" + .text /* @@ -15,14 +18,23 @@ */ .global flush_cache flush_cache: - addi 4,4,0x1f /* len = (len + 0x1f) / 0x20 */ - rlwinm. 4,4,27,5,31 - mtctr 4 - beqlr -1: dcbf 0,3 - icbi 0,3 - addi 3,3,0x20 - bdnz 1b + mfpvr r5 # Get processor version register + extrwi r5,r5,16,0 # Get the version bits + cmpwi cr0,r5,0x0020 # Is this a 403-based processor? + beq 1f # Yes, it is + li r5,32 # It is not a 403, set to 32 bytes + addi r4,r4,32-1 # len += line_size - 1 + srwi. r4,r4,5 # Convert from bytes to lines + b 2f +1: li r5,16 # It is a 403, set to 16 bytes + addi r4,r4,16-1 # len += line_size - 1 + srwi. r4,r4,4 # Convert from bytes to lines +2: mtctr r4 # Set-up the counter register + beqlr # If it is 0, we are done +3: dcbf r0,r3 # Flush and invalidate the data line + icbi r0,r3 # Invalidate the instruction line + add r3,r3,r5 # Move to the next line + bdnz 3b # Are we done yet? sync isync - blr + blr # Return to the caller diff --git a/arch/ppc/xmon/start.c b/arch/ppc/xmon/start.c index 9fc97b5a9..426f80ff3 100644 --- a/arch/ppc/xmon/start.c +++ b/arch/ppc/xmon/start.c @@ -102,9 +102,11 @@ xmon_write(void *handle, void *ptr, int nb) if (!scc_initialized) xmon_init_scc(); for (i = 0; i < nb; ++i) { +#ifdef CONFIG_ADB while ((*sccc & TXRDY) == 0) if (sys_ctrler == SYS_CTRLER_PMU) pmu_poll(); +#endif /* CONFIG_ADB */ buf_access(); if ( console && (*p != '\r')) printk("%c", *p); @@ -195,9 +197,11 @@ xmon_read(void *handle, void *ptr, int nb) if (!scc_initialized) xmon_init_scc(); for (i = 0; i < nb; ++i) { +#ifdef CONFIG_ADB while ((*sccc & RXRDY) == 0) if (sys_ctrler == SYS_CTRLER_PMU) pmu_poll(); +#endif /* CONFIG_ADB */ buf_access(); #if 0 if ( 0/*console*/ ) diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c index f5a42cc29..1c6a812d2 100644 --- a/arch/ppc/xmon/xmon.c +++ b/arch/ppc/xmon/xmon.c @@ -469,7 +469,7 @@ backtrace(struct pt_regs *excp) unsigned sp; unsigned stack[2]; struct pt_regs regs; - extern char ret_from_int, ret_from_syscall_1, ret_from_syscall_2; + extern char ret_from_intercept, ret_from_syscall_1, ret_from_syscall_2; extern char lost_irq_ret, do_bottom_half_ret, do_signal_ret; extern char ret_from_except; @@ -483,7 +483,7 @@ backtrace(struct pt_regs *excp) if (mread(sp, stack, sizeof(stack)) != sizeof(stack)) break; printf("%x ", stack[1]); - if (stack[1] == (unsigned) &ret_from_int + if (stack[1] == (unsigned) &ret_from_intercept || stack[1] == (unsigned) &ret_from_except || stack[1] == (unsigned) &ret_from_syscall_1 || stack[1] == (unsigned) &ret_from_syscall_2 diff --git a/arch/sparc/ap1000/apmmu.c b/arch/sparc/ap1000/apmmu.c index 5d852f859..425f23b8c 100644 --- a/arch/sparc/ap1000/apmmu.c +++ b/arch/sparc/ap1000/apmmu.c @@ -907,8 +907,7 @@ static void __init map_kernel(void) make_large_page((KERNBASE+phys)>>12, (phys>>12), APMMU_CACHE|APMMU_PRIV|APMMU_VALID); - init_mm.mmap->vm_start = page_offset = KERNBASE; - stack_top = page_offset - PAGE_SIZE; + init_mm.mmap->vm_start = PAGE_OFFSET; } extern unsigned long free_area_init(unsigned long, unsigned long); diff --git a/arch/sparc/config.in b/arch/sparc/config.in index 9ed06dc1f..31e126f33 100644 --- a/arch/sparc/config.in +++ b/arch/sparc/config.in @@ -1,9 +1,11 @@ -# $Id: config.in,v 1.79 1999/12/23 01:46:00 davem Exp $ +# $Id: config.in,v 1.80 2000/01/14 07:12:30 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # mainmenu_name "Linux/SPARC Kernel Configuration" +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 diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig index b02a836b6..26037c33e 100644 --- a/arch/sparc/defconfig +++ b/arch/sparc/defconfig @@ -1,6 +1,7 @@ # # Automatically generated make config: don't edit # +CONFIG_UID16=y # # Code maturity level options @@ -8,28 +9,25 @@ CONFIG_EXPERIMENTAL=y # -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# # General setup # CONFIG_VT=y CONFIG_VT_CONSOLE=y -# CONFIG_AP1000 is not set # CONFIG_SMP is not set +# CONFIG_AP1000 is not set # CONFIG_SUN4 is not set # CONFIG_PCI is not set -# CONFIG_PCI_NAMES is not set # # Console drivers # CONFIG_PROM_CONSOLE=y CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y CONFIG_FB_SBUS=y CONFIG_FB_CGSIX=y @@ -67,6 +65,7 @@ CONFIG_SUN_MOSTEK_RTC=y # CONFIG_SUN_VIDEOPIX is not set CONFIG_SUN_AURORA=m # CONFIG_TADPOLE_TS102_UCTRL is not set +# CONFIG_SUN_JSFLASH is not set # # Linux/SPARC audio subsystem (EXPERIMENTAL) @@ -82,7 +81,6 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m @@ -91,9 +89,17 @@ CONFIG_SUNOS_EMUL=y # CONFIG_PRINTER is not set # +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# # Floppy, IDE, and other block devices # CONFIG_BLK_DEV_FD=y +# CONFIG_BLK_DEV_IDE is not set CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=m CONFIG_MD_STRIPED=m @@ -239,14 +245,15 @@ CONFIG_AUTOFS_FS=m # CONFIG_ADFS_FS is not set CONFIG_AFFS_FS=m # CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set CONFIG_FAT_FS=m CONFIG_MSDOS_FS=m # CONFIG_UMSDOS_FS is not set CONFIG_VFAT_FS=m CONFIG_EFS_FS=m +# CONFIG_CRAMFS is not set CONFIG_ISO9660_FS=m # CONFIG_JOLIET is not set -# CONFIG_UDF_FS is not set CONFIG_MINIX_FS=m # CONFIG_NTFS_FS is not set CONFIG_HPFS_FS=m @@ -256,6 +263,8 @@ CONFIG_DEVPTS_FS=y CONFIG_ROMFS_FS=m CONFIG_EXT2_FS=y CONFIG_SYSV_FS=m +# CONFIG_SYSV_FS_WRITE is not set +# CONFIG_UDF_FS is not set CONFIG_UFS_FS=m CONFIG_UFS_FS_WRITE=y @@ -265,7 +274,7 @@ CONFIG_UFS_FS_WRITE=y CONFIG_CODA_FS=m CONFIG_NFS_FS=y CONFIG_NFSD=m -# CONFIG_NFSD_SUN is not set +# CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_SMB_FS=m @@ -275,7 +284,9 @@ CONFIG_NCP_FS=m # CONFIG_NCPFS_STRONG is not set # CONFIG_NCPFS_NFS_NS is not set # CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set # CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set # CONFIG_NCPFS_NLS is not set # CONFIG_NCPFS_EXTRAS is not set @@ -284,9 +295,6 @@ CONFIG_NCP_FS=m # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -CONFIG_BSD_DISKLABEL=y -CONFIG_SOLARIS_X86_PARTITION=y -# CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_SGI_PARTITION is not set CONFIG_SUN_PARTITION=y CONFIG_NLS=y diff --git a/arch/sparc/kernel/etrap.S b/arch/sparc/kernel/etrap.S index 10d7750d0..33077d99d 100644 --- a/arch/sparc/kernel/etrap.S +++ b/arch/sparc/kernel/etrap.S @@ -1,4 +1,4 @@ -/* $Id: etrap.S,v 1.30 1999/08/14 03:51:08 anton Exp $ +/* $Id: etrap.S,v 1.31 2000/01/08 16:38:18 anton Exp $ * etrap.S: Sparc trap window preparation for entry into the * Linux kernel. * @@ -278,7 +278,7 @@ tsetup_sun4c_onepage: C_LABEL(tsetup_srmmu_stackchk): /* Check results of callers andcc %sp, 0x7, %g0 */ bne trap_setup_user_stack_is_bolixed - GET_PAGE_OFFSET(glob_tmp) + sethi %hi(PAGE_OFFSET), %glob_tmp cmp %glob_tmp, %sp bleu,a 1f diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 195f26df5..1be5a02e3 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.142 1999/12/27 06:08:31 anton Exp $ +/* $Id: process.c,v 1.143 2000/01/09 09:13:28 anton Exp $ * linux/arch/sparc/kernel/process.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -503,6 +503,9 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, #endif p->thread.kwim = current->thread.fork_kwim; + /* This is used for sun4c only */ + atomic_set(&p->thread.refcount, 1); + if(regs->psr & PSR_PS) { extern struct pt_regs fake_swapper_regs; diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S index 7039291f0..7b056b47a 100644 --- a/arch/sparc/kernel/rtrap.S +++ b/arch/sparc/kernel/rtrap.S @@ -1,4 +1,4 @@ -/* $Id: rtrap.S,v 1.52 1999/08/14 03:51:18 anton Exp $ +/* $Id: rtrap.S,v 1.53 2000/01/08 16:38:18 anton Exp $ * rtrap.S: Return from Sparc trap low-level code. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -297,7 +297,7 @@ sun4c_rett_onepage: .globl C_LABEL(srmmu_rett_stackchk) C_LABEL(srmmu_rett_stackchk): bne ret_trap_user_stack_is_bolixed - GET_PAGE_OFFSET(g1) + sethi %hi(PAGE_OFFSET), %g1 cmp %g1, %fp bleu ret_trap_user_stack_is_bolixed mov AC_M_SFSR, %g1 diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 0c955178f..6943aa4e6 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -1,4 +1,4 @@ -/* $Id: sparc_ksyms.c,v 1.84 2000/01/07 18:15:14 jj Exp $ +/* $Id: sparc_ksyms.c,v 1.86 2000/01/09 10:46:49 anton Exp $ * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -123,13 +123,8 @@ EXPORT_SYMBOL_NOVERS(___down_write); EXPORT_SYMBOL_NOVERS(___up_read); EXPORT_SYMBOL_NOVERS(___up_write); -EXPORT_SYMBOL(page_offset); EXPORT_SYMBOL(sparc_valid_addr_bitmap); -#ifndef CONFIG_SUN4 -EXPORT_SYMBOL(stack_top); -#endif - /* Atomic operations. */ EXPORT_SYMBOL_PRIVATE(_atomic_add); EXPORT_SYMBOL_PRIVATE(_atomic_sub); @@ -176,7 +171,6 @@ EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(__smp_processor_id)); EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(enable_irq)); EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(disable_irq)); EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(__irq_itoa)); -EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_v2p)); EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_unlockarea)); EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_lockarea)); EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_get_scsi_sgl)); diff --git a/arch/sparc/kernel/sunos_asm.S b/arch/sparc/kernel/sunos_asm.S index 0c4e9a673..913630e66 100644 --- a/arch/sparc/kernel/sunos_asm.S +++ b/arch/sparc/kernel/sunos_asm.S @@ -1,4 +1,4 @@ -/* $Id: sunos_asm.S,v 1.14 1996/12/04 18:25:48 jj Exp $ +/* $Id: sunos_asm.S,v 1.15 2000/01/11 17:33:21 jj Exp $ * sunos_asm.S: SunOS system calls which must have a low-level * entry point to operate correctly. * @@ -33,10 +33,10 @@ C_LABEL(sunos_getpid): /* SunOS getuid() returns uid in %o0 and euid in %o1 */ .globl C_LABEL(sunos_getuid) C_LABEL(sunos_getuid): - call C_LABEL(sys_geteuid) + call C_LABEL(sys_geteuid16) nop - call C_LABEL(sys_getuid) + call C_LABEL(sys_getuid16) st %o0, [%sp + REGWIN_SZ + PT_I1] b C_LABEL(ret_sys_call) @@ -45,10 +45,10 @@ C_LABEL(sunos_getuid): /* SunOS getgid() returns gid in %o0 and egid in %o1 */ .globl C_LABEL(sunos_getgid) C_LABEL(sunos_getgid): - call C_LABEL(sys_getegid) + call C_LABEL(sys_getegid16) nop - call C_LABEL(sys_getgid) + call C_LABEL(sys_getgid16) st %o0, [%sp + REGWIN_SZ + PT_I1] b C_LABEL(ret_sys_call) diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index d4be69030..6da3c3f21 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.88 1999/12/21 14:09:06 jj Exp $ +/* $Id: systbls.S,v 1.90 2000/01/11 17:33:20 jj Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -20,30 +20,30 @@ sys_call_table: /*0*/ .long sys_nis_syscall, sys_exit, sys_fork, sys_read, sys_write /*5*/ .long sys_open, sys_close, sys_wait4, sys_creat, sys_link -/*10*/ .long sys_unlink, sunos_execv, sys_chdir, sys_chown, sys_mknod -/*15*/ .long sys_chmod, sys_lchown, sparc_brk, sys_nis_syscall, sys_lseek -/*20*/ .long sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid +/*10*/ .long sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys_mknod +/*15*/ .long sys_chmod, sys_lchown16, sparc_brk, sys_nis_syscall, sys_lseek +/*20*/ .long sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16 /*25*/ .long sys_time, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause -/*30*/ .long sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice -/*35*/ .long sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile -/*40*/ .long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall -/*45*/ .long sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid -/*50*/ .long sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys_ioctl +/*30*/ .long sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice +/*35*/ .long sys_chown, sys_sync, sys_kill, sys_newstat, sys_sendfile +/*40*/ .long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_getuid +/*45*/ .long sys_umount, sys_setgid16, sys_getgid16, sys_signal, sys_geteuid16 +/*50*/ .long sys_getegid16, sys_acct, sys_nis_syscall, sys_getgid, sys_ioctl /*55*/ .long sys_reboot, sys_mmap2, sys_symlink, sys_readlink, sys_execve /*60*/ .long sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize -/*65*/ .long sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_nis_syscall -/*70*/ .long sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_munmap, sys_mprotect -/*75*/ .long sys_nis_syscall, sys_vhangup, sys_truncate64, sys_nis_syscall, sys_getgroups -/*80*/ .long sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_ftruncate64 -/*85*/ .long sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall -/*90*/ .long sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall +/*65*/ .long sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_geteuid +/*70*/ .long sys_getegid, sys_mmap, sys_setreuid, sys_munmap, sys_mprotect +/*75*/ .long sys_setregid, sys_vhangup, sys_truncate64, sys_getgroups, sys_getgroups16 +/*80*/ .long sys_setgroups16, sys_getpgrp, sys_setgroups, sys_setitimer, sys_ftruncate64 +/*85*/ .long sys_swapon, sys_getitimer, sys_setuid, sys_sethostname, sys_setgid +/*90*/ .long sys_dup2, sys_setfsuid, sys_fcntl, sys_select, sys_setfsgid /*95*/ .long sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall /*100*/ .long sys_getpriority, sys_rt_sigreturn, sys_rt_sigaction, sys_rt_sigprocmask, sys_rt_sigpending -/*105*/ .long sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall -/*110*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall +/*105*/ .long sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_setresuid, sys_getresuid +/*110*/ .long sys_setresgid, sys_getresgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall /*115*/ .long sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_nis_syscall, sys_getcwd -/*120*/ .long sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod -/*125*/ .long sys_nis_syscall, sys_setreuid, sys_setregid, sys_rename, sys_truncate +/*120*/ .long sys_readv, sys_writev, sys_settimeofday, sys_fchown16, sys_fchmod +/*125*/ .long sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys_truncate /*130*/ .long sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall /*135*/ .long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_stat64 /*140*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit @@ -63,7 +63,7 @@ sys_call_table: /*210*/ .long sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo /*215*/ .long sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex /*220*/ .long sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid -/*225*/ .long sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid +/*225*/ .long sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid16, sys_setfsgid16 /*230*/ .long sys_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall /* "We are the Knights of the Forest of Ni!!" */ /*235*/ .long sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall @@ -83,7 +83,7 @@ sunos_sys_table: .long sys_close, sunos_wait4, sys_creat .long sys_link, sys_unlink, sunos_execv .long sys_chdir, sunos_nosys, sys_mknod - .long sys_chmod, sys_lchown, sunos_brk + .long sys_chmod, sys_lchown16, sunos_brk .long sunos_nosys, sys_lseek, sunos_getpid .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_getuid, sunos_nosys, sys_ptrace @@ -104,8 +104,8 @@ sunos_sys_table: .long sunos_nosys, sunos_sbrk, sunos_sstk .long sunos_mmap, sunos_vadvise, sys_munmap .long sys_mprotect, sunos_madvise, sys_vhangup - .long sunos_nosys, sunos_mincore, sys_getgroups - .long sys_setgroups, sys_getpgrp, sunos_setpgrp + .long sunos_nosys, sunos_mincore, sys_getgroups16 + .long sys_setgroups16, sys_getpgrp, sunos_setpgrp .long sys_setitimer, sunos_nosys, sys_swapon .long sys_getitimer, sys_gethostname, sys_sethostname .long sunos_getdtablesize, sys_dup2, sunos_nop @@ -119,9 +119,9 @@ sunos_sys_table: .long sys_sigstack, sys_recvmsg, sys_sendmsg .long sunos_nosys, sys_gettimeofday, sys_getrusage .long sunos_getsockopt, sunos_nosys, sunos_readv - .long sunos_writev, sys_settimeofday, sys_fchown - .long sys_fchmod, sys_recvfrom, sys_setreuid - .long sys_setregid, sys_rename, sys_truncate + .long sunos_writev, sys_settimeofday, sys_fchown16 + .long sys_fchmod, sys_recvfrom, sys_setreuid16 + .long sys_setregid16, sys_rename, sys_truncate .long sys_ftruncate, sys_flock, sunos_nosys .long sys_sendto, sys_shutdown, sys_socketpair .long sys_mkdir, sys_rmdir, sys_utimes diff --git a/arch/sparc/kernel/wof.S b/arch/sparc/kernel/wof.S index 2fbd15d2f..6c3a697e8 100644 --- a/arch/sparc/kernel/wof.S +++ b/arch/sparc/kernel/wof.S @@ -1,4 +1,4 @@ -/* $Id: wof.S,v 1.39 1999/08/14 03:51:35 anton Exp $ +/* $Id: wof.S,v 1.40 2000/01/08 16:38:18 anton Exp $ * wof.S: Sparc window overflow handler. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -395,7 +395,7 @@ C_LABEL(spwin_srmmu_stackchk): */ /* Check results of callers andcc %sp, 0x7, %g0 */ bne spwin_user_stack_is_bolixed - GET_PAGE_OFFSET(glob_tmp) + sethi %hi(PAGE_OFFSET), %glob_tmp cmp %glob_tmp, %sp bleu spwin_user_stack_is_bolixed mov AC_M_SFSR, %glob_tmp diff --git a/arch/sparc/kernel/wuf.S b/arch/sparc/kernel/wuf.S index 8937e48b3..512c4e79c 100644 --- a/arch/sparc/kernel/wuf.S +++ b/arch/sparc/kernel/wuf.S @@ -1,4 +1,4 @@ -/* $Id: wuf.S,v 1.38 1999/08/14 03:51:36 anton Exp $ +/* $Id: wuf.S,v 1.39 2000/01/08 16:38:18 anton Exp $ * wuf.S: Window underflow trap handler for the Sparc. * * Copyright (C) 1995 David S. Miller @@ -300,7 +300,7 @@ C_LABEL(srmmu_fwin_stackchk): /* Caller did 'andcc %sp, 0x7, %g0' */ bne fwin_user_stack_is_bolixed - GET_PAGE_OFFSET(l5) + sethi %hi(PAGE_OFFSET), %l5 /* Check if the users stack is in kernel vma, then our * trial and error technique below would succeed for diff --git a/arch/sparc/lib/copy_user.S b/arch/sparc/lib/copy_user.S index 728cbf9bd..97c55f02d 100644 --- a/arch/sparc/lib/copy_user.S +++ b/arch/sparc/lib/copy_user.S @@ -14,6 +14,7 @@ #include <asm/cprefix.h> #include <asm/ptrace.h> #include <asm/asmmacro.h> +#include <asm/page.h> #define EX(x,y,a,b,z) \ 98: x,y; \ @@ -355,7 +356,7 @@ short_aligned_end: 97: mov %o2, %g3 fixupretl: - GET_PAGE_OFFSET(g1) + sethi %hi(PAGE_OFFSET), %g1 cmp %o0, %g1 blu 1f cmp %o1, %g1 diff --git a/arch/sparc/mm/asyncd.c b/arch/sparc/mm/asyncd.c index 6ed8a3c99..569940417 100644 --- a/arch/sparc/mm/asyncd.c +++ b/arch/sparc/mm/asyncd.c @@ -1,4 +1,4 @@ -/* $Id: asyncd.c,v 1.18 1999/12/27 06:30:02 anton Exp $ +/* $Id: asyncd.c,v 1.19 2000/01/08 20:22:16 davem Exp $ * The asyncd kernel daemon. This handles paging on behalf of * processes that receive page faults due to remote (async) memory * accesses. @@ -260,10 +260,11 @@ int asyncd(void *unused) save_flags(flags); cli(); while (!async_queue) { - spin_lock_irq(¤t->sigmask_lock); + spin_lock(¤t->sigmask_lock); flush_signals(current); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock(¤t->sigmask_lock); interruptible_sleep_on(&asyncd_wait); + __sti(); cli(); } restore_flags(flags); diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c index 221496f98..817861a19 100644 --- a/arch/sparc/mm/init.c +++ b/arch/sparc/mm/init.c @@ -1,9 +1,10 @@ -/* $Id: init.c,v 1.72 1999/12/27 06:30:06 anton Exp $ +/* $Id: init.c,v 1.73 2000/01/15 00:51:26 anton Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 2000 Anton Blanchard (anton@progsoc.uts.edu.au) */ #include <linux/config.h> @@ -70,8 +71,7 @@ pte_t *__bad_pagetable(void) pte_t __bad_page(void) { memset((void *) &empty_bad_page, 0, PAGE_SIZE); - return pte_mkdirty(mk_pte_phys((((unsigned long) &empty_bad_page) - - PAGE_OFFSET + phys_base), + return pte_mkdirty(mk_pte_phys((unsigned long)__pa(&empty_bad_page) + phys_base, PAGE_SHARED)); } @@ -115,7 +115,7 @@ void __init sparc_context_init(int numctx) add_to_free_ctxlist(ctx_list_pool + ctx); } -#undef DEBUG_BOOTMEM +#define DEBUG_BOOTMEM extern unsigned long cmdline_memory_size; @@ -125,6 +125,10 @@ unsigned long __init bootmem_init(void) unsigned long end_of_phys_memory = 0UL; int i; + /* Limit maximum memory until we implement highmem for sparc */ + if (cmdline_memory_size > 0x9000000) + cmdline_memory_size = 0x9000000; + /* XXX It is a bit ambiguous here, whether we should * XXX treat the user specified mem=xxx as total wanted * XXX physical memory, or as a limit to the upper @@ -161,7 +165,7 @@ unsigned long __init bootmem_init(void) /* Start with page aligned address of last symbol in kernel * image. */ - start_pfn = PAGE_ALIGN((unsigned long) &_end) - PAGE_OFFSET; + start_pfn = (unsigned long)__pa(PAGE_ALIGN((unsigned long) &_end)); /* Adjust up to the physical address where the kernel begins. */ start_pfn += phys_base; @@ -281,8 +285,8 @@ static void __init taint_real_pages(void) unsigned long start, end; start = sp_banks[i].base_addr; - end = start + - sp_banks[i].num_bytes; + end = start + sp_banks[i].num_bytes; + while (start < end) { set_bit (start >> 20, sparc_valid_addr_bitmap); @@ -379,19 +383,17 @@ void __init mem_init(void) } memset(sparc_valid_addr_bitmap, 0, i << 2); - addr = KERNBASE; - last = PAGE_ALIGN((unsigned long)&_end); /* fix this */ - while(addr < last) { #ifdef CONFIG_BLK_DEV_INITRD + addr = __va(phys_base); + last = PAGE_ALIGN((unsigned long)&_end) + phys_base; + while(addr < last) { if (initrd_below_start_ok && addr >= initrd_start && addr < initrd_end) mem_map[MAP_NR(addr)].flags &= ~(1<<PG_reserved); else -#endif - mem_map[MAP_NR(addr)].flags |= (1<<PG_reserved); - set_bit(MAP_NR(addr) >> 8, sparc_valid_addr_bitmap); addr += PAGE_SIZE; } +#endif taint_real_pages(); @@ -444,9 +446,7 @@ void free_initmem (void) unsigned long page; struct page *p; - page = (addr + - ((unsigned long) __va(phys_base)) - - PAGE_OFFSET); + page = addr + phys_base; p = mem_map + MAP_NR(page); ClearPageReserved(p); diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index 1a3476a16..90b4aee69 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c @@ -1,4 +1,4 @@ -/* $Id: io-unit.c,v 1.18 1999/12/28 04:28:55 anton Exp $ +/* $Id: io-unit.c,v 1.20 2000/01/15 00:51:27 anton Exp $ * io-unit.c: IO-UNIT specific routines for memory management. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -102,7 +102,7 @@ nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan); goto nexti; iounit->rotor[j - 1] = (scan < limit) ? scan : iounit->limit[j - 1]; scan -= npages; - iopte = MKIOPTE(mmu_v2p(vaddr & PAGE_MASK)); + iopte = MKIOPTE(__pa(vaddr & PAGE_MASK)); vaddr = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT) + (vaddr & ~PAGE_MASK); for (k = 0; k < npages; k++, iopte = __iopte(iopte_val(iopte) + 0x100), scan++) { set_bit(scan, iounit->bmap); @@ -190,7 +190,7 @@ static void iounit_map_dma_area(unsigned long va, __u32 addr, int len) pmdp = pmd_offset(pgdp, addr); ptep = pte_offset(pmdp, addr); - set_pte(ptep, pte_val(mk_pte(page, dvma_prot))); + set_pte(ptep, pte_val(mk_pte(mem_map + MAP_NR(page), dvma_prot))); i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT); @@ -198,7 +198,7 @@ static void iounit_map_dma_area(unsigned long va, __u32 addr, int len) struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu; iopte = (iopte_t *)(iounit->page_table + i); - *iopte = __iopte(MKIOPTE(mmu_v2p(page))); + *iopte = __iopte(MKIOPTE(__pa(page))); } } addr += PAGE_SIZE; @@ -284,6 +284,6 @@ __u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct sbus_bus *sbus) int scan = (vaddr - IOUNIT_DMA_BASE) >> PAGE_SHIFT; struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu; - iounit->page_table[scan] = MKIOPTE(mmu_v2p(((unsigned long)addr) & PAGE_MASK)); + iounit->page_table[scan] = MKIOPTE(__pa(((unsigned long)addr) & PAGE_MASK)); return vaddr + (((unsigned long)addr) & ~PAGE_MASK); } diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index 041e00c6a..5a8cc8c5b 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -1,4 +1,4 @@ -/* $Id: iommu.c,v 1.16 1999/12/28 04:28:54 anton Exp $ +/* $Id: iommu.c,v 1.18 2000/01/15 00:51:27 anton Exp $ * iommu.c: IOMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -36,13 +36,13 @@ extern void viking_mxcc_flush_page(unsigned long page); static inline void iommu_map_dvma_pages_for_iommu(struct iommu_struct *iommu) { unsigned long kern_end = (unsigned long) high_memory; - unsigned long first = page_offset; + unsigned long first = PAGE_OFFSET; unsigned long last = kern_end; iopte_t *iopte = iommu->page_table; iopte += ((first - iommu->start) >> PAGE_SHIFT); while(first <= last) { - *iopte++ = __iopte(MKIOPTE(mmu_v2p(first))); + *iopte++ = __iopte(MKIOPTE(__pa(first))); first += PAGE_SIZE; } } @@ -71,7 +71,7 @@ iommu_init(int iommund, struct sbus_bus *sbus) vers = (iommu->regs->control & IOMMU_CTRL_VERS) >> 24; tmp = iommu->regs->control; tmp &= ~(IOMMU_CTRL_RNGE); - switch(page_offset & 0xf0000000) { + switch(PAGE_OFFSET & 0xf0000000) { case 0xf0000000: tmp |= (IOMMU_RNGE_256MB | IOMMU_CTRL_ENAB); iommu->plow = iommu->start = 0xf0000000; @@ -135,7 +135,7 @@ iommu_init(int iommund, struct sbus_bus *sbus) } } flush_tlb_all(); - iommu->regs->base = mmu_v2p((unsigned long) iommu->page_table) >> 4; + iommu->regs->base = __pa((unsigned long) iommu->page_table) >> 4; iommu_invalidate(iommu->regs); sbus->iommu = iommu; @@ -241,18 +241,18 @@ static void iommu_map_dma_area(unsigned long va, __u32 addr, int len) else if (viking_flush) viking_flush_page(page); else - flush_page_to_ram(page); + __flush_page_to_ram(page); pgdp = pgd_offset(&init_mm, addr); pmdp = pmd_offset(pgdp, addr); ptep = pte_offset(pmdp, addr); - set_pte(ptep, pte_val(mk_pte(page, dvma_prot))); + set_pte(ptep, mk_pte(mem_map + MAP_NR(page), dvma_prot)); if (ipte_cache != 0) { - iopte_val(*iopte++) = MKIOPTE(mmu_v2p(page)); + iopte_val(*iopte++) = MKIOPTE(__pa(page)); } else { iopte_val(*iopte++) = - MKIOPTE(mmu_v2p(page)) & ~IOPTE_CACHE; + MKIOPTE(__pa(page)) & ~IOPTE_CACHE; } } addr += PAGE_SIZE; diff --git a/arch/sparc/mm/loadmmu.c b/arch/sparc/mm/loadmmu.c index c5fc4a7a9..3338666e8 100644 --- a/arch/sparc/mm/loadmmu.c +++ b/arch/sparc/mm/loadmmu.c @@ -1,4 +1,4 @@ -/* $Id: loadmmu.c,v 1.51 1999/08/31 06:54:35 davem Exp $ +/* $Id: loadmmu.c,v 1.53 2000/01/09 10:46:50 anton Exp $ * loadmmu.c: This code loads up all the mm function pointers once the * machine type has been determined. It also sets the static * mmu values such as PAGE_NONE, etc. @@ -19,9 +19,6 @@ #include <asm/mmu_context.h> #include <asm/oplib.h> -unsigned long page_offset = 0xf0000000; -unsigned long stack_top = 0xf0000000 - PAGE_SIZE; - struct ctx_list *ctx_list_pool; struct ctx_list ctx_free; struct ctx_list ctx_used; diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index c365cf0d5..77e9aa841 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -1,10 +1,11 @@ -/* $Id: srmmu.c,v 1.199 1999/12/23 02:00:51 davem Exp $ +/* $Id: srmmu.c,v 1.203 2000/01/15 00:51:28 anton Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 Pete Zaitcev * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + * Copyright (C) 1999 Anton Blanchard (anton@progsoc.uts.edu.au) */ #include <linux/config.h> @@ -16,8 +17,10 @@ #include <linux/init.h> #include <linux/blk.h> #include <linux/spinlock.h> +#include <linux/bootmem.h> #include <asm/page.h> +#include <asm/pgalloc.h> #include <asm/pgtable.h> #include <asm/io.h> #include <asm/kdebug.h> @@ -44,9 +47,6 @@ #include <asm/btfixup.h> -/* #define DEBUG_MAP_KERNEL */ -/* #define PAGESKIP_DEBUG */ - enum mbus_module srmmu_modtype; unsigned int hwbug_bitmask; int vac_cache_size; @@ -55,6 +55,8 @@ int vac_badbits; extern struct resource sparc_iomap; +extern unsigned long last_valid_pfn; + #ifdef __SMP__ #define FLUSH_BEGIN(mm) #define FLUSH_END @@ -63,9 +65,6 @@ extern struct resource sparc_iomap; #define FLUSH_END } #endif -static int phys_mem_contig; -BTFIXUPDEF_SETHI(page_contig_offset) - BTFIXUPDEF_CALL(void, ctxd_set, ctxd_t *, pgd_t *) BTFIXUPDEF_CALL(void, pmd_set, pmd_t *, pte_t *) @@ -96,95 +95,9 @@ char *srmmu_name; ctxd_t *srmmu_ctx_table_phys; ctxd_t *srmmu_context_table; -/* Don't change this without changing access to this - * in arch/sparc/mm/viking.S - */ -static struct srmmu_trans { - unsigned long vbase; - unsigned long pbase; - unsigned long size; -} srmmu_map[SPARC_PHYS_BANKS]; - -#define SRMMU_HASHSZ 256 - -/* Not static, viking.S uses it. */ -unsigned long srmmu_v2p_hash[SRMMU_HASHSZ]; -static unsigned long srmmu_p2v_hash[SRMMU_HASHSZ]; - -#define srmmu_ahashfn(addr) ((addr) >> 24) - int viking_mxcc_present = 0; static spinlock_t srmmu_context_spinlock = SPIN_LOCK_UNLOCKED; -/* Physical memory can be _very_ non-contiguous on the sun4m, especially - * the SS10/20 class machines and with the latest openprom revisions. - * So we have to do a quick lookup. - * We use the same for SS1000/SC2000 as a fall back, when phys memory is - * non-contiguous. - */ -static inline unsigned long srmmu_v2p(unsigned long vaddr) -{ - unsigned long off = srmmu_v2p_hash[srmmu_ahashfn(vaddr)]; - - return (vaddr + off); -} - -static inline unsigned long srmmu_p2v(unsigned long paddr) -{ - unsigned long off = srmmu_p2v_hash[srmmu_ahashfn(paddr)]; - - if (off != 0xffffffffUL) - return (paddr - off); - else - return 0xffffffffUL; -} - -/* Physical memory on most SS1000/SC2000 can be contiguous, so we handle that case - * as a special case to make things faster. - */ -/* FIXME: gcc is stupid here and generates very very bad code in this - * heavily used routine. So we help it a bit. */ -static inline unsigned long srmmu_c_v2p(unsigned long vaddr) -{ -#if KERNBASE != 0xf0000000 - if (vaddr >= KERNBASE) return vaddr - KERNBASE; - return vaddr - BTFIXUP_SETHI(page_contig_offset); -#else - register unsigned long kernbase; - - __asm__ ("sethi %%hi(0xf0000000), %0" : "=r"(kernbase)); - return vaddr - ((vaddr >= kernbase) ? kernbase : BTFIXUP_SETHI(page_contig_offset)); -#endif -} - -static inline unsigned long srmmu_c_p2v(unsigned long paddr) -{ -#if KERNBASE != 0xf0000000 - if (paddr < (0xfd000000 - KERNBASE)) return paddr + KERNBASE; - return (paddr + BTFIXUP_SETHI(page_contig_offset)); -#else - register unsigned long kernbase; - register unsigned long limit; - - __asm__ ("sethi %%hi(0x0d000000), %0" : "=r"(limit)); - __asm__ ("sethi %%hi(0xf0000000), %0" : "=r"(kernbase)); - - return paddr + ((paddr < limit) ? kernbase : BTFIXUP_SETHI(page_contig_offset)); -#endif -} - -/* On boxes where there is no lots_of_ram, KERNBASE is mapped to PA<0> and highest - PA is below 0x0d000000, we can optimize even more :) */ -static inline unsigned long srmmu_s_v2p(unsigned long vaddr) -{ - return vaddr - PAGE_OFFSET; -} - -static inline unsigned long srmmu_s_p2v(unsigned long paddr) -{ - return paddr + PAGE_OFFSET; -} - /* In general all page table modifications should use the V8 atomic * swap instruction. This insures the mmu and the cpu are in sync * with respect to ref/mod bits in the page tables. @@ -198,91 +111,6 @@ static inline unsigned long srmmu_swap(unsigned long *addr, unsigned long value) /* Functions really use this, not srmmu_swap directly. */ #define srmmu_set_entry(ptr, newentry) srmmu_swap((unsigned long *) (ptr), (newentry)) -#ifdef PAGESKIP_DEBUG -#define PGSKIP_DEBUG(from,to) prom_printf("PG_skip %ld->%ld\n", (long)(from), (long)(to)); printk("PG_skip %ld->%ld\n", (long)(from), (long)(to)) -#else -#define PGSKIP_DEBUG(from,to) do { } while (0) -#endif - -void __init srmmu_frob_mem_map(unsigned long start_mem) -{ - unsigned long bank_start, bank_end = 0; - unsigned long addr; - int i; - - /* First, mark all pages as invalid. */ - for(addr = PAGE_OFFSET; MAP_NR(addr) < max_mapnr; addr += PAGE_SIZE) - mem_map[MAP_NR(addr)].flags |= (1<<PG_reserved); - - /* Next, pg[0-3] is sun4c cruft, so we can free it... */ - mem_map[MAP_NR(pg0)].flags &= ~(1<<PG_reserved); - mem_map[MAP_NR(pg1)].flags &= ~(1<<PG_reserved); - mem_map[MAP_NR(pg2)].flags &= ~(1<<PG_reserved); - mem_map[MAP_NR(pg3)].flags &= ~(1<<PG_reserved); - - start_mem = PAGE_ALIGN(start_mem); - for(i = 0; srmmu_map[i].size; i++) { - bank_start = srmmu_map[i].vbase; - - /* Making a one or two pages PG_skip holes - * is not necessary. We add one more because - * we must set the PG_skip flag on the first - * two mem_map[] entries for the hole. Go and - * see the mm/filemap.c:shrink_mmap() loop for - * details. -DaveM - */ - if (i && bank_start - bank_end > 3 * PAGE_SIZE) { - mem_map[MAP_NR(bank_end)].flags |= (1<<PG_skip); - mem_map[MAP_NR(bank_end)].next_hash = mem_map + MAP_NR(bank_start); - mem_map[MAP_NR(bank_end)+1UL].flags |= (1<<PG_skip); - mem_map[MAP_NR(bank_end)+1UL].next_hash = mem_map + MAP_NR(bank_start); - PGSKIP_DEBUG(MAP_NR(bank_end), MAP_NR(bank_start)); - if (bank_end > KERNBASE && bank_start < KERNBASE) { - mem_map[0].flags |= (1<<PG_skip); - mem_map[0].next_hash = mem_map + MAP_NR(bank_start); - mem_map[1].flags |= (1<<PG_skip); - mem_map[1].next_hash = mem_map + MAP_NR(bank_start); - PGSKIP_DEBUG(0, MAP_NR(bank_start)); - } - } - - bank_end = bank_start + srmmu_map[i].size; - while(bank_start < bank_end) { - set_bit(MAP_NR(bank_start) >> 8, sparc_valid_addr_bitmap); - if((bank_start >= KERNBASE) && - (bank_start < start_mem)) { - bank_start += PAGE_SIZE; - continue; - } - mem_map[MAP_NR(bank_start)].flags &= ~(1<<PG_reserved); - bank_start += PAGE_SIZE; - } - - if (bank_end == 0xfd000000) - bank_end = PAGE_OFFSET; - } - - if (bank_end < KERNBASE) { - mem_map[MAP_NR(bank_end)].flags |= (1<<PG_skip); - mem_map[MAP_NR(bank_end)].next_hash = mem_map + MAP_NR(KERNBASE); - mem_map[MAP_NR(bank_end)+1UL].flags |= (1<<PG_skip); - mem_map[MAP_NR(bank_end)+1UL].next_hash = mem_map + MAP_NR(KERNBASE); - PGSKIP_DEBUG(MAP_NR(bank_end), MAP_NR(KERNBASE)); - } else if (MAP_NR(bank_end) < max_mapnr) { - mem_map[MAP_NR(bank_end)].flags |= (1<<PG_skip); - mem_map[MAP_NR(bank_end)+1UL].flags |= (1<<PG_skip); - if (mem_map[0].flags & (1 << PG_skip)) { - mem_map[MAP_NR(bank_end)].next_hash = mem_map[0].next_hash; - mem_map[MAP_NR(bank_end)+1UL].next_hash = mem_map[0].next_hash; - PGSKIP_DEBUG(MAP_NR(bank_end), mem_map[0].next_hash - mem_map); - } else { - mem_map[MAP_NR(bank_end)].next_hash = mem_map; - mem_map[MAP_NR(bank_end)+1UL].next_hash = mem_map; - PGSKIP_DEBUG(MAP_NR(bank_end), 0); - } - } -} - /* The very generic SRMMU page table operations. */ static inline int srmmu_device_memory(unsigned long x) { @@ -290,31 +118,13 @@ static inline int srmmu_device_memory(unsigned long x) } static unsigned long srmmu_pgd_page(pgd_t pgd) -{ return srmmu_device_memory(pgd_val(pgd))?~0:srmmu_p2v((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4); } +{ return srmmu_device_memory(pgd_val(pgd))?~0:(unsigned long)__va((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4); } static unsigned long srmmu_pmd_page(pmd_t pmd) -{ return srmmu_device_memory(pmd_val(pmd))?~0:srmmu_p2v((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4); } +{ return srmmu_device_memory(pmd_val(pmd))?~0:(unsigned long)__va((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4); } -static unsigned long srmmu_pte_page(pte_t pte) -{ return srmmu_device_memory(pte_val(pte))?~0:srmmu_p2v((pte_val(pte) & SRMMU_PTE_PMASK) << 4); } - -static unsigned long srmmu_c_pgd_page(pgd_t pgd) -{ return srmmu_device_memory(pgd_val(pgd))?~0:srmmu_c_p2v((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4); } - -static unsigned long srmmu_c_pmd_page(pmd_t pmd) -{ return srmmu_device_memory(pmd_val(pmd))?~0:srmmu_c_p2v((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4); } - -static unsigned long srmmu_c_pte_page(pte_t pte) -{ return srmmu_device_memory(pte_val(pte))?~0:srmmu_c_p2v((pte_val(pte) & SRMMU_PTE_PMASK) << 4); } - -static unsigned long srmmu_s_pgd_page(pgd_t pgd) -{ return srmmu_device_memory(pgd_val(pgd))?~0:srmmu_s_p2v((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4); } - -static unsigned long srmmu_s_pmd_page(pmd_t pmd) -{ return srmmu_device_memory(pmd_val(pmd))?~0:srmmu_s_p2v((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4); } - -static unsigned long srmmu_s_pte_page(pte_t pte) -{ return srmmu_device_memory(pte_val(pte))?~0:srmmu_s_p2v((pte_val(pte) & SRMMU_PTE_PMASK) << 4); } +static unsigned long srmmu_pte_pagenr(pte_t pte) +{ return srmmu_device_memory(pte_val(pte))?~0:(((pte_val(pte) & SRMMU_PTE_PMASK) << 4) >> PAGE_SHIFT); } static inline int srmmu_pte_none(pte_t pte) { return !(pte_val(pte) & 0xFFFFFFF); } @@ -359,14 +169,8 @@ static inline pte_t srmmu_pte_mkyoung(pte_t pte) { return __pte(pte_val(pte) * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. */ -static pte_t srmmu_mk_pte(unsigned long page, pgprot_t pgprot) -{ return __pte(((srmmu_v2p(page)) >> 4) | pgprot_val(pgprot)); } - -static pte_t srmmu_c_mk_pte(unsigned long page, pgprot_t pgprot) -{ return __pte(((srmmu_c_v2p(page)) >> 4) | pgprot_val(pgprot)); } - -static pte_t srmmu_s_mk_pte(unsigned long page, pgprot_t pgprot) -{ return __pte(((srmmu_s_v2p(page)) >> 4) | pgprot_val(pgprot)); } +static pte_t srmmu_mk_pte(struct page *page, pgprot_t pgprot) +{ return __pte((((page - mem_map) << PAGE_SHIFT) >> 4) | pgprot_val(pgprot)); } static pte_t srmmu_mk_pte_phys(unsigned long page, pgprot_t pgprot) { return __pte(((page) >> 4) | pgprot_val(pgprot)); } @@ -378,47 +182,17 @@ static pte_t srmmu_mk_pte_io(unsigned long page, pgprot_t pgprot, int space) static void srmmu_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp) { - set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (srmmu_v2p((unsigned long) pgdp) >> 4))); + set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (__pa((unsigned long) pgdp) >> 4))); } static void srmmu_pgd_set(pgd_t * pgdp, pmd_t * pmdp) { - set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (srmmu_v2p((unsigned long) pmdp) >> 4))); + set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (__pa((unsigned long) pmdp) >> 4))); } static void srmmu_pmd_set(pmd_t * pmdp, pte_t * ptep) { - set_pte((pte_t *)pmdp, (SRMMU_ET_PTD | (srmmu_v2p((unsigned long) ptep) >> 4))); -} - -static void srmmu_c_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp) -{ - set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (srmmu_c_v2p((unsigned long) pgdp) >> 4))); -} - -static void srmmu_c_pgd_set(pgd_t * pgdp, pmd_t * pmdp) -{ - set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (srmmu_c_v2p((unsigned long) pmdp) >> 4))); -} - -static void srmmu_c_pmd_set(pmd_t * pmdp, pte_t * ptep) -{ - set_pte((pte_t *)pmdp, (SRMMU_ET_PTD | (srmmu_c_v2p((unsigned long) ptep) >> 4))); -} - -static void srmmu_s_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp) -{ - set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (srmmu_s_v2p((unsigned long) pgdp) >> 4))); -} - -static void srmmu_s_pgd_set(pgd_t * pgdp, pmd_t * pmdp) -{ - set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (srmmu_s_v2p((unsigned long) pmdp) >> 4))); -} - -static void srmmu_s_pmd_set(pmd_t * pmdp, pte_t * ptep) -{ - set_pte((pte_t *)pmdp, (SRMMU_ET_PTD | (srmmu_s_v2p((unsigned long) ptep) >> 4))); + set_pte((pte_t *)pmdp, (SRMMU_ET_PTD | (__pa((unsigned long) ptep) >> 4))); } static inline pte_t srmmu_pte_modify(pte_t pte, pgprot_t newprot) @@ -444,26 +218,6 @@ static inline pte_t *srmmu_pte_offset(pmd_t * dir, unsigned long address) return (pte_t *) srmmu_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1)); } -static inline pmd_t *srmmu_c_pmd_offset(pgd_t * dir, unsigned long address) -{ - return (pmd_t *) srmmu_c_pgd_page(*dir) + ((address >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1)); -} - -static inline pte_t *srmmu_c_pte_offset(pmd_t * dir, unsigned long address) -{ - return (pte_t *) srmmu_c_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1)); -} - -static inline pmd_t *srmmu_s_pmd_offset(pgd_t * dir, unsigned long address) -{ - return (pmd_t *) srmmu_s_pgd_page(*dir) + ((address >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1)); -} - -static inline pte_t *srmmu_s_pte_offset(pmd_t * dir, unsigned long address) -{ - return (pte_t *) srmmu_s_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1)); -} - static inline pte_t *srmmu_get_pte_fast(void) { struct page *ret; @@ -841,7 +595,7 @@ void srmmu_mapioaddr(unsigned long physaddr, unsigned long virt_addr, int bus_ty tmp |= SRMMU_PRIV_RDONLY; else tmp |= SRMMU_PRIV; - flush_page_to_ram(virt_addr); + __flush_page_to_ram(virt_addr); set_pte(ptep, __pte(tmp)); flush_tlb_all(); } @@ -857,7 +611,7 @@ void srmmu_unmapioaddr(unsigned long virt_addr) ptep = pte_offset(pmdp, virt_addr); /* No need to flush uncacheable page. */ - set_pte(ptep, mk_pte((unsigned long) EMPTY_PGE, PAGE_SHARED)); + pte_clear(ptep); flush_tlb_all(); } @@ -879,6 +633,11 @@ static void srmmu_free_task_struct(struct task_struct *tsk) free_pages((unsigned long)tsk, 1); } +static void srmmu_get_task_struct(struct task_struct *tsk) +{ + atomic_inc(&mem_map[MAP_NR(tsk)].count); +} + /* tsunami.S */ extern void tsunami_flush_cache_all(void); extern void tsunami_flush_cache_mm(struct mm_struct *mm); @@ -1235,8 +994,6 @@ extern void viking_flush_sig_insns(struct mm_struct *mm, unsigned long addr); extern void viking_flush_page(unsigned long page); extern void viking_mxcc_flush_page(unsigned long page); extern void viking_flush_chunk(unsigned long chunk); -extern void viking_c_flush_chunk(unsigned long chunk); -extern void viking_s_flush_chunk(unsigned long chunk); extern void viking_mxcc_flush_chunk(unsigned long chunk); extern void viking_flush_tlb_all(void); extern void viking_flush_tlb_mm(struct mm_struct *mm); @@ -1276,7 +1033,7 @@ static void srmmu_set_pte_nocache_hyper(pte_t *ptep, pte_t pteval) static void hypersparc_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp) { - srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) pgdp) >> 4)))); + srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (__pa((unsigned long) pgdp) >> 4)))); hypersparc_flush_page_to_ram((unsigned long)ctxp); hyper_flush_whole_icache(); } @@ -1291,57 +1048,23 @@ static void hypersparc_switch_mm(struct mm_struct *old_mm, alloc_context(old_mm, mm); spin_unlock(&srmmu_context_spinlock); ctxp = &srmmu_context_table[mm->context]; - srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) mm->pgd) >> 4)))); + srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (__pa((unsigned long) mm->pgd) >> 4)))); hypersparc_flush_page_to_ram((unsigned long)ctxp); } hyper_flush_whole_icache(); srmmu_set_context(mm->context); } -static unsigned long mempool; - /* NOTE: All of this startup code assumes the low 16mb (approx.) of * kernel mappings are done with one single contiguous chunk of * ram. On small ram machines (classics mainly) we only get * around 8mb mapped for us. */ -static unsigned long kbpage; - -/* Some dirty hacks to abstract away the painful boot up init. */ -static inline unsigned long srmmu_early_paddr(unsigned long vaddr) +void __init early_pgtable_allocfail(char *type) { - return ((vaddr - KERNBASE) + kbpage); -} - -static inline void srmmu_early_pgd_set(pgd_t *pgdp, pmd_t *pmdp) -{ - set_pte((pte_t *)pgdp, __pte((SRMMU_ET_PTD | (srmmu_early_paddr((unsigned long) pmdp) >> 4)))); -} - -static inline void srmmu_early_pmd_set(pmd_t *pmdp, pte_t *ptep) -{ - set_pte((pte_t *)pmdp, __pte((SRMMU_ET_PTD | (srmmu_early_paddr((unsigned long) ptep) >> 4)))); -} - -static inline unsigned long srmmu_early_pgd_page(pgd_t pgd) -{ - return (((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4) - kbpage) + KERNBASE; -} - -static inline unsigned long srmmu_early_pmd_page(pmd_t pmd) -{ - return (((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4) - kbpage) + KERNBASE; -} - -static inline pmd_t *srmmu_early_pmd_offset(pgd_t *dir, unsigned long address) -{ - return (pmd_t *) srmmu_early_pgd_page(*dir) + ((address >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1)); -} - -static inline pte_t *srmmu_early_pte_offset(pmd_t *dir, unsigned long address) -{ - return (pte_t *) srmmu_early_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1)); + prom_printf("inherit_prom_mappings: Cannot alloc kernel %s.\n", type); + prom_halt(); } static inline void srmmu_allocate_ptable_skeleton(unsigned long start, unsigned long end) @@ -1353,13 +1076,20 @@ static inline void srmmu_allocate_ptable_skeleton(unsigned long start, unsigned while(start < end) { pgdp = srmmu_pgd_offset(&init_mm, start); if(srmmu_pgd_none(*pgdp)) { - pmdp = sparc_init_alloc(&mempool, SRMMU_PMD_TABLE_SIZE); - srmmu_early_pgd_set(pgdp, pmdp); + pmdp = __alloc_bootmem(SRMMU_PMD_TABLE_SIZE, + SRMMU_PMD_TABLE_SIZE, 0UL); + if (pmdp == NULL) + early_pgtable_allocfail("pmd"); + memset(pmdp, 0, SRMMU_PMD_TABLE_SIZE); + srmmu_pgd_set(pgdp, pmdp); } - pmdp = srmmu_early_pmd_offset(pgdp, start); + pmdp = srmmu_pmd_offset(pgdp, start); if(srmmu_pmd_none(*pmdp)) { - ptep = sparc_init_alloc(&mempool, SRMMU_PTE_TABLE_SIZE); - srmmu_early_pmd_set(pmdp, ptep); + ptep = __alloc_bootmem(SRMMU_PTE_TABLE_SIZE, SRMMU_PTE_TABLE_SIZE, 0UL); + if (ptep == NULL) + early_pgtable_allocfail("pte"); + memset(ptep, 0, SRMMU_PTE_TABLE_SIZE); + srmmu_pmd_set(pmdp, ptep); } start = (start + SRMMU_PMD_SIZE) & SRMMU_PMD_MASK; } @@ -1408,94 +1138,34 @@ void __init srmmu_inherit_prom_mappings(unsigned long start,unsigned long end) continue; } if(srmmu_pgd_none(*pgdp)) { - pmdp = sparc_init_alloc(&mempool, SRMMU_PMD_TABLE_SIZE); - srmmu_early_pgd_set(pgdp, pmdp); + pmdp = __alloc_bootmem(SRMMU_PMD_TABLE_SIZE, + SRMMU_PMD_TABLE_SIZE, 0UL); + if (pmdp == NULL) + early_pgtable_allocfail("pmd"); + memset(pmdp, 0, SRMMU_PMD_TABLE_SIZE); + srmmu_pgd_set(pgdp, pmdp); } - pmdp = srmmu_early_pmd_offset(pgdp, start); + pmdp = srmmu_pmd_offset(pgdp, start); if(what == 1) { *pmdp = __pmd(prompte); start += SRMMU_PMD_SIZE; continue; } if(srmmu_pmd_none(*pmdp)) { - ptep = sparc_init_alloc(&mempool, SRMMU_PTE_TABLE_SIZE); - srmmu_early_pmd_set(pmdp, ptep); + ptep = __alloc_bootmem(SRMMU_PTE_TABLE_SIZE, SRMMU_PTE_TABLE_SIZE, 0UL); + if (ptep == NULL) + early_pgtable_allocfail("pte"); + memset(ptep, 0, SRMMU_PTE_TABLE_SIZE); + srmmu_pmd_set(pmdp, ptep); } - ptep = srmmu_early_pte_offset(pmdp, start); + ptep = srmmu_pte_offset(pmdp, start); *ptep = __pte(prompte); start += PAGE_SIZE; } } -#ifdef DEBUG_MAP_KERNEL -#define MKTRACE(foo) prom_printf foo -#else -#define MKTRACE(foo) -#endif - -static int lots_of_ram __initdata = 0; -static int srmmu_low_pa __initdata = 0; static unsigned long end_of_phys_memory __initdata = 0; -void __init srmmu_end_memory(unsigned long memory_size, unsigned long *end_mem_p) -{ - unsigned int sum = 0; - unsigned long last = 0xff000000; - long first, cur; - unsigned long pa; - unsigned long total = 0; - int i; - - pa = srmmu_hwprobe(KERNBASE + PAGE_SIZE); - pa = (pa & SRMMU_PTE_PMASK) << 4; - if (!sp_banks[0].base_addr && pa == PAGE_SIZE) { - for(i = 0; sp_banks[i].num_bytes != 0; i++) { - if (sp_banks[i].base_addr + sp_banks[i].num_bytes > 0x0d000000) - break; - } - if (!sp_banks[i].num_bytes) { - srmmu_low_pa = 1; - end_of_phys_memory = SRMMU_PGDIR_ALIGN(sp_banks[i-1].base_addr + sp_banks[i-1].num_bytes); - *end_mem_p = KERNBASE + end_of_phys_memory; - if (sp_banks[0].num_bytes >= (6 * 1024 * 1024) || end_of_phys_memory <= 0x06000000) { - /* Make sure there will be enough memory for the whole mem_map (even if sparse) */ - return; - } - } - } - for(i = 0; sp_banks[i].num_bytes != 0; i++) { - pa = sp_banks[i].base_addr; - first = (pa & (~SRMMU_PGDIR_MASK)); - cur = (sp_banks[i].num_bytes + first - SRMMU_PGDIR_SIZE); - if (cur < 0) cur = 0; - if (!first || last != (pa & SRMMU_PGDIR_MASK)) - total += SRMMU_PGDIR_SIZE; - sum += sp_banks[i].num_bytes; - if (memory_size) { - if (sum > memory_size) { - sp_banks[i].num_bytes -= - (sum - memory_size); - cur = (sp_banks[i].num_bytes + first - SRMMU_PGDIR_SIZE); - if (cur < 0) cur = 0; - total += SRMMU_PGDIR_ALIGN(cur); - sum = memory_size; - sp_banks[++i].base_addr = 0xdeadbeef; - sp_banks[i].num_bytes = 0; - break; - } - } - total += SRMMU_PGDIR_ALIGN(cur); - last = (sp_banks[i].base_addr + sp_banks[i].num_bytes - 1) & SRMMU_PGDIR_MASK; - } - if (total <= 0x0d000000) - *end_mem_p = KERNBASE + total; - else { - *end_mem_p = 0xfd000000; - lots_of_ram = 1; - } - end_of_phys_memory = total; -} - #define KERNEL_PTE(page_shifted) ((page_shifted)|SRMMU_CACHE|SRMMU_PRIV|SRMMU_VALID) /* Create a third-level SRMMU 16MB page mapping. */ @@ -1504,44 +1174,10 @@ static void __init do_large_mapping(unsigned long vaddr, unsigned long phys_base pgd_t *pgdp = srmmu_pgd_offset(&init_mm, vaddr); unsigned long big_pte; - MKTRACE(("dlm[v<%08lx>-->p<%08lx>]", vaddr, phys_base)); big_pte = KERNEL_PTE(phys_base >> 4); *pgdp = __pgd(big_pte); } -/* Look in the sp_bank for the given physical page, return the - * index number the entry was found in, or -1 for not found. - */ -static inline int find_in_spbanks(unsigned long phys_page) -{ - int entry; - - for(entry = 0; sp_banks[entry].num_bytes; entry++) { - unsigned long start = sp_banks[entry].base_addr; - unsigned long end = start + sp_banks[entry].num_bytes; - - if((start <= phys_page) && (phys_page < end)) - return entry; - } - return -1; -} - -/* Find an spbank entry not mapped as of yet, TAKEN_VECTOR is an - * array of char's, each member indicating if that spbank is mapped - * yet or not. - */ -static int __init find_free_spbank(char *taken_vector) -{ - int entry; - - for(entry = 0; sp_banks[entry].num_bytes; entry++) - if(!taken_vector[entry]) - break; - return entry; -} - -static unsigned long map_spbank_last_pa __initdata = 0xff000000; - /* Map sp_bank entry SP_ENTRY, starting at virtual address VBASE. */ static unsigned long __init map_spbank(unsigned long vbase, int sp_entry) @@ -1549,20 +1185,11 @@ static unsigned long __init map_spbank(unsigned long vbase, int sp_entry) unsigned long pstart = (sp_banks[sp_entry].base_addr & SRMMU_PGDIR_MASK); unsigned long vstart = (vbase & SRMMU_PGDIR_MASK); unsigned long vend = SRMMU_PGDIR_ALIGN(vbase + sp_banks[sp_entry].num_bytes); - static int srmmu_bank = 0; - MKTRACE(("map_spbank %d[v<%08lx>p<%08lx>s<%08lx>]", sp_entry, vbase, sp_banks[sp_entry].base_addr, sp_banks[sp_entry].num_bytes)); - MKTRACE(("map_spbank2 %d[p%08lx v%08lx-%08lx]", sp_entry, pstart, vstart, vend)); while(vstart < vend) { do_large_mapping(vstart, pstart); vstart += SRMMU_PGDIR_SIZE; pstart += SRMMU_PGDIR_SIZE; } - srmmu_map[srmmu_bank].vbase = vbase; - srmmu_map[srmmu_bank].pbase = sp_banks[sp_entry].base_addr; - srmmu_map[srmmu_bank].size = sp_banks[sp_entry].num_bytes; - if (srmmu_map[srmmu_bank].size) - srmmu_bank++; - map_spbank_last_pa = pstart - SRMMU_PGDIR_SIZE; return vstart; } @@ -1573,251 +1200,35 @@ static inline void memprobe_error(char *msg) prom_halt(); } -/* Assumptions: The bank given to the kernel from the prom/bootloader - * is part of a full bank which is at least 4MB in size and begins at - * 0xf0000000 (ie. KERNBASE). - */ static inline void map_kernel(void) { - unsigned long raw_pte, physpage; - unsigned long vaddr, low_base; - char etaken[SPARC_PHYS_BANKS]; - int entry; - - /* Step 1: Clear out sp_banks taken map. */ - MKTRACE(("map_kernel: clearing etaken vector... ")); - for(entry = 0; entry < SPARC_PHYS_BANKS; entry++) - etaken[entry] = 0; - - low_base = KERNBASE; - - /* Step 2: Fill in KERNBASE base pgd. Lots of sanity checking here. */ - raw_pte = srmmu_hwprobe(KERNBASE + PAGE_SIZE); - if((raw_pte & SRMMU_ET_MASK) != SRMMU_ET_PTE) - memprobe_error("Wheee, kernel not mapped at all by boot loader.\n"); - physpage = (raw_pte & SRMMU_PTE_PMASK) << 4; - physpage -= PAGE_SIZE; - if(physpage & ~(SRMMU_PGDIR_MASK)) - memprobe_error("Wheee, kernel not mapped on 16MB physical boundry.\n"); - entry = find_in_spbanks(physpage); - if(entry == -1 || (sp_banks[entry].base_addr != physpage)) - memprobe_error("Kernel mapped in non-existant memory.\n"); - MKTRACE(("map_kernel: map_spbank(vbase=%08x, entry<%d>)[%08lx,%08lx]\n", KERNBASE, entry, sp_banks[entry].base_addr, sp_banks[entry].num_bytes)); - if (sp_banks[entry].num_bytes > 0x0d000000) { - unsigned long orig_base = sp_banks[entry].base_addr; - unsigned long orig_len = sp_banks[entry].num_bytes; - unsigned long can_map = 0x0d000000; - - /* Map a partial bank in this case, adjust the base - * and the length, but don't mark it used. - */ - sp_banks[entry].num_bytes = can_map; - MKTRACE(("wheee really big mapping [%08lx,%08lx]", orig_base, can_map)); - vaddr = map_spbank(KERNBASE, entry); - MKTRACE(("vaddr now %08lx ", vaddr)); - sp_banks[entry].base_addr = orig_base + can_map; - sp_banks[entry].num_bytes = orig_len - can_map; - MKTRACE(("adjust[%08lx,%08lx]\n", (orig_base + can_map), (orig_len - can_map))); - MKTRACE(("map_kernel: skipping first loop\n")); - goto loop_skip; - } - vaddr = map_spbank(KERNBASE, entry); - etaken[entry] = 1; - - /* Step 3: Map what we can above KERNBASE. */ - MKTRACE(("map_kernel: vaddr=%08lx, entering first loop\n", vaddr)); - for(;;) { - unsigned long bank_size; - - MKTRACE(("map_kernel: ffsp()")); - entry = find_free_spbank(&etaken[0]); - bank_size = sp_banks[entry].num_bytes; - MKTRACE(("<%d> base=%08lx bs=%08lx ", entry, sp_banks[entry].base_addr, bank_size)); - if(!bank_size) - break; - if (srmmu_low_pa) - vaddr = KERNBASE + sp_banks[entry].base_addr; - else if (sp_banks[entry].base_addr & (~SRMMU_PGDIR_MASK)) { - if (map_spbank_last_pa == (sp_banks[entry].base_addr & SRMMU_PGDIR_MASK)) - vaddr -= SRMMU_PGDIR_SIZE; - vaddr += (sp_banks[entry].base_addr & (~SRMMU_PGDIR_MASK)); - } - if ((vaddr + bank_size - KERNBASE) > 0x0d000000) { - unsigned long orig_base = sp_banks[entry].base_addr; - unsigned long orig_len = sp_banks[entry].num_bytes; - unsigned long can_map = (0xfd000000 - vaddr); - - /* Map a partial bank in this case, adjust the base - * and the length, but don't mark it used. - */ - sp_banks[entry].num_bytes = can_map; - MKTRACE(("wheee really big mapping [%08lx,%08lx]", orig_base, can_map)); - vaddr = map_spbank(vaddr, entry); - MKTRACE(("vaddr now %08lx ", vaddr)); - sp_banks[entry].base_addr = orig_base + can_map; - sp_banks[entry].num_bytes = orig_len - can_map; - MKTRACE(("adjust[%08lx,%08lx]\n", (orig_base + can_map), (orig_len - can_map))); - break; - } - - /* Ok, we can map this one, do it. */ - MKTRACE(("map_spbank(%08lx,entry<%d>) ", vaddr, entry)); - vaddr = map_spbank(vaddr, entry); - etaken[entry] = 1; - MKTRACE(("vaddr now %08lx\n", vaddr)); - } - MKTRACE(("\n")); - /* If not lots_of_ram, assume we did indeed map it all above. */ -loop_skip: - if(!lots_of_ram) - goto check_and_return; - - /* Step 4: Map the rest (if any) right below KERNBASE. */ - MKTRACE(("map_kernel: doing low mappings... ")); - low_base = (KERNBASE - end_of_phys_memory + 0x0d000000); - MKTRACE(("end_of_phys_memory=%08lx low_base=%08lx\n", end_of_phys_memory, low_base)); - - /* Ok, now map 'em. */ - MKTRACE(("map_kernel: Allocate pt skeleton (%08lx, %08x)\n",low_base,KERNBASE)); - srmmu_allocate_ptable_skeleton(low_base, KERNBASE); - vaddr = low_base; - map_spbank_last_pa = 0xff000000; - MKTRACE(("map_kernel: vaddr=%08lx Entering second loop for low maps.\n", vaddr)); - for(;;) { - unsigned long bank_size; - - entry = find_free_spbank(&etaken[0]); - bank_size = sp_banks[entry].num_bytes; - MKTRACE(("map_kernel: e<%d> base=%08lx bs=%08lx ", entry, sp_banks[entry].base_addr, bank_size)); - if(!bank_size) - break; - if (sp_banks[entry].base_addr & (~SRMMU_PGDIR_MASK)) { - if (map_spbank_last_pa == (sp_banks[entry].base_addr & SRMMU_PGDIR_MASK)) - vaddr -= SRMMU_PGDIR_SIZE; - vaddr += (sp_banks[entry].base_addr & (~SRMMU_PGDIR_MASK)); - } - if((vaddr + bank_size) > KERNBASE) - memprobe_error("Wheee, kernel low mapping overflow.\n"); - MKTRACE(("map_spbank(%08lx, %d) ", vaddr, entry)); - vaddr = map_spbank(vaddr, entry); - etaken[entry] = 1; - MKTRACE(("Now, vaddr=%08lx end_of_phys_memory=%08lx\n", vaddr, end_of_phys_memory)); - } - MKTRACE(("\n")); - -check_and_return: - /* Step 5: Sanity check, make sure we did it all. */ - MKTRACE(("check_and_return: ")); - for(entry = 0; sp_banks[entry].num_bytes; entry++) { - MKTRACE(("e[%d]=%d ", entry, etaken[entry])); - if(!etaken[entry]) { - MKTRACE(("oops\n")); - memprobe_error("Some bank did not get mapped.\n"); - } - } - MKTRACE(("success\n")); - init_mm.mmap->vm_start = page_offset = low_base; - stack_top = page_offset - PAGE_SIZE; - BTFIXUPSET_SETHI(page_offset, low_base); - BTFIXUPSET_SETHI(stack_top, page_offset - PAGE_SIZE); - BTFIXUPSET_SIMM13(user_ptrs_per_pgd, page_offset / SRMMU_PGDIR_SIZE); - -#if 1 - for(entry = 0; srmmu_map[entry].size; entry++) { - printk("[%d]: v[%08lx,%08lx](%lx) p[%08lx]\n", entry, - srmmu_map[entry].vbase, - srmmu_map[entry].vbase + srmmu_map[entry].size, - srmmu_map[entry].size, - srmmu_map[entry].pbase); - } -#endif + int i; - /* Now setup the p2v/v2p hash tables. */ - for(entry = 0; entry < SRMMU_HASHSZ; entry++) - srmmu_v2p_hash[entry] = ((0xff - entry) << 24); - for(entry = 0; entry < SRMMU_HASHSZ; entry++) - srmmu_p2v_hash[entry] = 0xffffffffUL; - for(entry = 0; srmmu_map[entry].size; entry++) { - unsigned long addr; - - for(addr = srmmu_map[entry].vbase; - addr < (srmmu_map[entry].vbase + srmmu_map[entry].size); - addr += (1 << 24)) - srmmu_v2p_hash[srmmu_ahashfn(addr)] = - srmmu_map[entry].pbase - srmmu_map[entry].vbase; - for(addr = srmmu_map[entry].pbase; - addr < (srmmu_map[entry].pbase + srmmu_map[entry].size); - addr += (1 << 24)) - srmmu_p2v_hash[srmmu_ahashfn(addr)] = - srmmu_map[entry].pbase - srmmu_map[entry].vbase; + for (i = 0; sp_banks[i].num_bytes != 0; i++) { + map_spbank(__va(sp_banks[i].base_addr), i); } - BTFIXUPSET_SETHI(page_contig_offset, page_offset - (0xfd000000 - KERNBASE)); - if (srmmu_low_pa) - phys_mem_contig = 0; - else { - phys_mem_contig = 1; - for(entry = 0; srmmu_map[entry].size; entry++) - if (srmmu_map[entry].pbase != srmmu_c_v2p (srmmu_map[entry].vbase)) { - phys_mem_contig = 0; - break; - } - } - if (phys_mem_contig) { - printk ("SRMMU: Physical memory is contiguous, bypassing VA<->PA hashes.\n"); - BTFIXUPSET_CALL(pte_page, srmmu_c_pte_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(pmd_page, srmmu_c_pmd_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(pgd_page, srmmu_c_pgd_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mk_pte, srmmu_c_mk_pte, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(pte_offset, srmmu_c_pte_offset, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(pmd_offset, srmmu_c_pmd_offset, BTFIXUPCALL_NORM); - if (BTFIXUPVAL_CALL(ctxd_set) == (unsigned long)srmmu_ctxd_set) - BTFIXUPSET_CALL(ctxd_set, srmmu_c_ctxd_set, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(pgd_set, srmmu_c_pgd_set, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(pmd_set, srmmu_c_pmd_set, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mmu_v2p, srmmu_c_v2p, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mmu_p2v, srmmu_c_p2v, BTFIXUPCALL_NORM); - if (BTFIXUPVAL_CALL(flush_chunk) == (unsigned long)viking_flush_chunk) - BTFIXUPSET_CALL(flush_chunk, viking_c_flush_chunk, BTFIXUPCALL_NORM); - } else if (srmmu_low_pa) { - printk ("SRMMU: Compact physical memory. Using strightforward VA<->PA translations.\n"); - BTFIXUPSET_CALL(pte_page, srmmu_s_pte_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(pmd_page, srmmu_s_pmd_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(pgd_page, srmmu_s_pgd_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mk_pte, srmmu_s_mk_pte, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(pte_offset, srmmu_s_pte_offset, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(pmd_offset, srmmu_s_pmd_offset, BTFIXUPCALL_NORM); - if (BTFIXUPVAL_CALL(ctxd_set) == (unsigned long)srmmu_ctxd_set) - BTFIXUPSET_CALL(ctxd_set, srmmu_s_ctxd_set, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(pgd_set, srmmu_s_pgd_set, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(pmd_set, srmmu_s_pmd_set, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mmu_v2p, srmmu_s_v2p, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mmu_p2v, srmmu_s_p2v, BTFIXUPCALL_NORM); - if (BTFIXUPVAL_CALL(flush_chunk) == (unsigned long)viking_flush_chunk) - BTFIXUPSET_CALL(flush_chunk, viking_s_flush_chunk, BTFIXUPCALL_NORM); - } - btfixup(); - - return; /* SUCCESS! */ + init_mm.mmap->vm_start = PAGE_OFFSET; + BTFIXUPSET_SIMM13(user_ptrs_per_pgd, PAGE_OFFSET / SRMMU_PGDIR_SIZE); } /* Paging initialization on the Sparc Reference MMU. */ -extern unsigned long free_area_init(unsigned long, unsigned long); -extern unsigned long sparc_context_init(unsigned long, int); +extern void sparc_context_init(int); -extern int physmem_mapped_contig; extern int linux_num_cpus; void (*poke_srmmu)(void) __initdata = NULL; -unsigned long __init srmmu_paging_init(unsigned long start_mem, unsigned long end_mem) +extern unsigned long bootmem_init(void); +extern void sun_serial_setup(void); + +void __init srmmu_paging_init(void) { - unsigned long ptables_start; int i, cpunode; char node_str[128]; + unsigned long end_pfn; sparc_iomap.start = 0xfd000000; /* 16MB of IOSPACE on all sun4m's. */ - physmem_mapped_contig = 0; /* for init.c:taint_real_pages() */ if (sparc_cpu_model == sun4d) num_contexts = 65536; /* We know it is Viking */ @@ -1840,32 +1251,42 @@ unsigned long __init srmmu_paging_init(unsigned long start_mem, unsigned long en prom_halt(); } - ptables_start = mempool = PAGE_ALIGN(start_mem); memset(swapper_pg_dir, 0, PAGE_SIZE); - kbpage = srmmu_hwprobe(KERNBASE + PAGE_SIZE); - kbpage = (kbpage & SRMMU_PTE_PMASK) << 4; - kbpage -= PAGE_SIZE; - srmmu_allocate_ptable_skeleton(KERNBASE, end_mem); + last_valid_pfn = end_pfn = bootmem_init(); + + srmmu_allocate_ptable_skeleton(KERNBASE, __va(end_of_phys_memory)); #if CONFIG_SUN_IO srmmu_allocate_ptable_skeleton(sparc_iomap.start, IOBASE_END); srmmu_allocate_ptable_skeleton(DVMA_VADDR, DVMA_END); #endif - mempool = PAGE_ALIGN(mempool); + /* This does not logically belong here, but we need to + * call it at the moment we are able to use the bootmem + * allocator. + */ + sun_serial_setup(); + srmmu_inherit_prom_mappings(0xfe400000,(LINUX_OPPROM_ENDVM-PAGE_SIZE)); map_kernel(); - srmmu_context_table = sparc_init_alloc(&mempool, num_contexts*sizeof(ctxd_t)); - srmmu_ctx_table_phys = (ctxd_t *) srmmu_v2p((unsigned long) srmmu_context_table); + +#define BOOTMEM_BROKEN +#ifdef BOOTMEM_BROKEN + srmmu_context_table = __alloc_bootmem(num_contexts*sizeof(ctxd_t)*2, SMP_CACHE_BYTES, 0UL); + (unsigned long)srmmu_context_table += num_contexts*sizeof(ctxd_t); + (unsigned long)srmmu_context_table &= ~(num_contexts*sizeof(ctxd_t)-1); +#else + srmmu_context_table = __alloc_bootmem(num_contexts*sizeof(ctxd_t), num_contexts*sizeof(ctxd_t), 0UL); +#endif + + srmmu_ctx_table_phys = (ctxd_t *) __pa((unsigned long) srmmu_context_table); for(i = 0; i < num_contexts; i++) ctxd_set(&srmmu_context_table[i], swapper_pg_dir); - start_mem = PAGE_ALIGN(mempool); - flush_cache_all(); if(BTFIXUPVAL_CALL(flush_page_for_dma) == (unsigned long)viking_flush_page) { - unsigned long start = ptables_start; - unsigned long end = start_mem; + unsigned long start = (unsigned long)srmmu_context_table; + unsigned long end = PAGE_ALIGN((unsigned long)srmmu_context_table + num_contexts*sizeof(ctxd_t)); while(start < end) { viking_flush_page(start); @@ -1876,22 +1297,27 @@ unsigned long __init srmmu_paging_init(unsigned long start_mem, unsigned long en flush_tlb_all(); poke_srmmu(); - start_mem = sparc_context_init(start_mem, num_contexts); - start_mem = free_area_init(start_mem, end_mem); + sparc_context_init(num_contexts); + + { + unsigned int zones_size[MAX_NR_ZONES] = { 0, 0, 0}; + + zones_size[ZONE_DMA] = end_pfn; + free_area_init(zones_size); + } #ifdef CONFIG_BLK_DEV_INITRD /* If initial ramdisk was specified with physical address, translate it here, as the p2v translation in srmmu is not straightforward. */ if (initrd_start && initrd_start < KERNBASE) { - initrd_start = srmmu_p2v(initrd_start); - initrd_end = srmmu_p2v(initrd_end); + initrd_start = __va(initrd_start); + initrd_end = __va(initrd_end); if (initrd_end <= initrd_start) initrd_start = 0; } #endif - return PAGE_ALIGN(start_mem); } static int srmmu_mmu_info(char *buf) @@ -2012,7 +1438,7 @@ static void hypersparc_destroy_context(struct mm_struct *mm) flush_cache_mm(mm); ctxp = &srmmu_context_table[mm->context]; - srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) swapper_pg_dir) >> 4)))); + srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (__pa((unsigned long) swapper_pg_dir) >> 4)))); hypersparc_flush_page_to_ram((unsigned long)ctxp); flush_tlb_mm(mm); @@ -2127,7 +1553,7 @@ static void __init init_hypersparc(void) BTFIXUPSET_CALL(flush_tlb_range, hypersparc_flush_tlb_range, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_page, hypersparc_flush_tlb_page, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_page_to_ram, hypersparc_flush_page_to_ram, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(__flush_page_to_ram, hypersparc_flush_page_to_ram, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_sig_insns, hypersparc_flush_sig_insns, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_page_for_dma, hypersparc_flush_page_for_dma, BTFIXUPCALL_NOP); @@ -2201,7 +1627,7 @@ static void __init init_cypress_common(void) BTFIXUPSET_CALL(flush_chunk, cypress_flush_chunk, BTFIXUPCALL_NORM); /* local flush _only_ */ - BTFIXUPSET_CALL(flush_page_to_ram, cypress_flush_page_to_ram, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(__flush_page_to_ram, cypress_flush_page_to_ram, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_sig_insns, cypress_flush_sig_insns, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(flush_page_for_dma, cypress_flush_page_for_dma, BTFIXUPCALL_NOP); @@ -2315,7 +1741,7 @@ static void __init init_swift(void) BTFIXUPSET_CALL(flush_tlb_page, swift_flush_tlb_page, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_range, swift_flush_tlb_range, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_page_to_ram, swift_flush_page_to_ram, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(__flush_page_to_ram, swift_flush_page_to_ram, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_sig_insns, swift_flush_sig_insns, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_page_for_dma, swift_flush_page_for_dma, BTFIXUPCALL_NORM); @@ -2475,7 +1901,7 @@ static void __init init_turbosparc(void) BTFIXUPSET_CALL(flush_tlb_page, turbosparc_flush_tlb_page, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_range, turbosparc_flush_tlb_range, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_page_to_ram, turbosparc_flush_page_to_ram, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(__flush_page_to_ram, turbosparc_flush_page_to_ram, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_chunk, turbosparc_flush_chunk, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_sig_insns, turbosparc_flush_sig_insns, BTFIXUPCALL_NOP); @@ -2517,7 +1943,7 @@ static void __init init_tsunami(void) BTFIXUPSET_CALL(flush_tlb_page, tsunami_flush_tlb_page, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_range, tsunami_flush_tlb_range, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_page_to_ram, tsunami_flush_page_to_ram, BTFIXUPCALL_NOP); + BTFIXUPSET_CALL(__flush_page_to_ram, tsunami_flush_page_to_ram, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(flush_sig_insns, tsunami_flush_sig_insns, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_page_for_dma, tsunami_flush_page_for_dma, BTFIXUPCALL_NORM); @@ -2574,7 +2000,7 @@ static void __init poke_viking(void) BTFIXUPCOPY_CALL(flush_cache_mm, local_flush_cache_mm); BTFIXUPCOPY_CALL(flush_cache_range, local_flush_cache_range); BTFIXUPCOPY_CALL(flush_cache_page, local_flush_cache_page); - BTFIXUPCOPY_CALL(flush_page_to_ram, local_flush_page_to_ram); + BTFIXUPCOPY_CALL(__flush_page_to_ram, local_flush_page_to_ram); BTFIXUPCOPY_CALL(flush_sig_insns, local_flush_sig_insns); BTFIXUPCOPY_CALL(flush_page_for_dma, local_flush_page_for_dma); btfixup(); @@ -2637,7 +2063,7 @@ static void __init init_viking(void) BTFIXUPSET_CALL(flush_tlb_range, viking_flush_tlb_range, BTFIXUPCALL_NORM); } - BTFIXUPSET_CALL(flush_page_to_ram, viking_flush_page_to_ram, BTFIXUPCALL_NOP); + BTFIXUPSET_CALL(__flush_page_to_ram, viking_flush_page_to_ram, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(flush_sig_insns, viking_flush_sig_insns, BTFIXUPCALL_NOP); poke_srmmu = poke_viking; @@ -2883,7 +2309,7 @@ void __init ld_mmu_srmmu(void) BTFIXUPSET_CALL(set_pte, srmmu_set_pte_cacheable, BTFIXUPCALL_SWAPO0O1); BTFIXUPSET_CALL(switch_mm, srmmu_switch_mm, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(pte_page, srmmu_pte_page, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(pte_pagenr, srmmu_pte_pagenr, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pmd_page, srmmu_pmd_page, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(pgd_page, srmmu_pgd_page, BTFIXUPCALL_NORM); @@ -2934,12 +2360,11 @@ void __init ld_mmu_srmmu(void) BTFIXUPSET_CALL(destroy_context, srmmu_destroy_context, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(mmu_info, srmmu_mmu_info, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mmu_v2p, srmmu_v2p, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mmu_p2v, srmmu_p2v, BTFIXUPCALL_NORM); /* Task struct and kernel stack allocating/freeing. */ BTFIXUPSET_CALL(alloc_task_struct, srmmu_alloc_task_struct, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(free_task_struct, srmmu_free_task_struct, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(get_task_struct, srmmu_get_task_struct, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(quick_kernel_fault, srmmu_quick_kernel_fault, BTFIXUPCALL_NORM); @@ -2966,7 +2391,7 @@ void __init ld_mmu_srmmu(void) BTFIXUPCOPY_CALL(local_flush_tlb_mm, flush_tlb_mm); BTFIXUPCOPY_CALL(local_flush_tlb_range, flush_tlb_range); BTFIXUPCOPY_CALL(local_flush_tlb_page, flush_tlb_page); - BTFIXUPCOPY_CALL(local_flush_page_to_ram, flush_page_to_ram); + BTFIXUPCOPY_CALL(local_flush_page_to_ram, __flush_page_to_ram); BTFIXUPCOPY_CALL(local_flush_sig_insns, flush_sig_insns); BTFIXUPCOPY_CALL(local_flush_page_for_dma, flush_page_for_dma); @@ -2980,7 +2405,7 @@ void __init ld_mmu_srmmu(void) BTFIXUPSET_CALL(flush_tlb_range, smp_flush_tlb_range, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_page, smp_flush_tlb_page, BTFIXUPCALL_NORM); } - BTFIXUPSET_CALL(flush_page_to_ram, smp_flush_page_to_ram, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(__flush_page_to_ram, smp_flush_page_to_ram, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_sig_insns, smp_flush_sig_insns, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_page_for_dma, smp_flush_page_for_dma, BTFIXUPCALL_NORM); #endif diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index 0530e635f..e0bd738d6 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.182 1999/12/27 06:30:04 anton Exp $ +/* $Id: sun4c.c,v 1.185 2000/01/15 00:51:32 anton Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -68,20 +68,6 @@ extern int num_segmaps, num_contexts; struct sun4c_vac_props sun4c_vacinfo; unsigned long sun4c_kernel_faults; -/* convert a virtual address to a physical address and vice - * versa. Easy on the 4c - */ -static unsigned long sun4c_v2p(unsigned long vaddr) -{ - return (vaddr - PAGE_OFFSET); -} - -static unsigned long sun4c_p2v(unsigned long vaddr) -{ - return (vaddr + PAGE_OFFSET); -} - - /* Invalidate every sun4c cache line tag. */ void sun4c_flush_all(void) { @@ -1162,21 +1148,23 @@ static void sun4c_free_task_struct_hw(struct task_struct *tsk) unsigned long pages = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr)); int entry = BUCKET_NUM(tsaddr); - /* We are deleting a mapping, so the flush here is mandatory. */ - sun4c_flush_page_hw(tsaddr); + if (atomic_dec_and_test(&(tsk)->thread.refcount)) { + /* We are deleting a mapping, so the flush here is mandatory. */ + sun4c_flush_page_hw(tsaddr); #ifndef CONFIG_SUN4 - sun4c_flush_page_hw(tsaddr + PAGE_SIZE); + sun4c_flush_page_hw(tsaddr + PAGE_SIZE); #endif - sun4c_put_pte(tsaddr, 0); + sun4c_put_pte(tsaddr, 0); #ifndef CONFIG_SUN4 - sun4c_put_pte(tsaddr + PAGE_SIZE, 0); + sun4c_put_pte(tsaddr + PAGE_SIZE, 0); #endif - sun4c_bucket[entry] = BUCKET_EMPTY; - if (entry < sun4c_lowbucket_avail) - sun4c_lowbucket_avail = entry; + sun4c_bucket[entry] = BUCKET_EMPTY; + if (entry < sun4c_lowbucket_avail) + sun4c_lowbucket_avail = entry; - free_pages(pages, TASK_STRUCT_ORDER); - garbage_collect(entry); + free_pages(pages, TASK_STRUCT_ORDER); + garbage_collect(entry); + } } static void sun4c_free_task_struct_sw(struct task_struct *tsk) @@ -1185,21 +1173,28 @@ static void sun4c_free_task_struct_sw(struct task_struct *tsk) unsigned long pages = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr)); int entry = BUCKET_NUM(tsaddr); - /* We are deleting a mapping, so the flush here is mandatory. */ - sun4c_flush_page_sw(tsaddr); + if (atomic_dec_and_test(&(tsk)->thread.refcount)) { + /* We are deleting a mapping, so the flush here is mandatory. */ + sun4c_flush_page_sw(tsaddr); #ifndef CONFIG_SUN4 - sun4c_flush_page_sw(tsaddr + PAGE_SIZE); + sun4c_flush_page_sw(tsaddr + PAGE_SIZE); #endif - sun4c_put_pte(tsaddr, 0); + sun4c_put_pte(tsaddr, 0); #ifndef CONFIG_SUN4 - sun4c_put_pte(tsaddr + PAGE_SIZE, 0); + sun4c_put_pte(tsaddr + PAGE_SIZE, 0); #endif - sun4c_bucket[entry] = BUCKET_EMPTY; - if (entry < sun4c_lowbucket_avail) - sun4c_lowbucket_avail = entry; + sun4c_bucket[entry] = BUCKET_EMPTY; + if (entry < sun4c_lowbucket_avail) + sun4c_lowbucket_avail = entry; - free_pages(pages, TASK_STRUCT_ORDER); - garbage_collect(entry); + free_pages(pages, TASK_STRUCT_ORDER); + garbage_collect(entry); + } +} + +static void sun4c_get_task_struct(struct task_struct *tsk) +{ + atomic_inc(&(tsk)->thread.refcount); } static void __init sun4c_init_buckets(void) @@ -1568,13 +1563,12 @@ static void sun4c_flush_cache_page_hw(struct vm_area_struct *vma, unsigned long } } -static void sun4c_flush_page_to_ram_hw(struct page *page) +static void sun4c_flush_page_to_ram_hw(unsigned long page) { unsigned long flags; - unsigned long addr = page_address(page); save_and_cli(flags); - sun4c_flush_page_hw(addr); + sun4c_flush_page_hw(page); restore_flags(flags); } @@ -1691,13 +1685,12 @@ static void sun4c_flush_cache_page_sw(struct vm_area_struct *vma, unsigned long } } -static void sun4c_flush_page_to_ram_sw(struct page *page) +static void sun4c_flush_page_to_ram_sw(unsigned long page) { unsigned long flags; - unsigned long addr = page_address(page); save_and_cli(flags); - sun4c_flush_page_sw(addr); + sun4c_flush_page_sw(page); restore_flags(flags); } @@ -2643,7 +2636,7 @@ void __init ld_mmu_sun4c(void) BTFIXUPSET_CALL(flush_cache_mm, sun4c_flush_cache_mm_hw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_cache_range, sun4c_flush_cache_range_hw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_cache_page, sun4c_flush_cache_page_hw, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_page_to_ram, sun4c_flush_page_to_ram_hw, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(__flush_page_to_ram, sun4c_flush_page_to_ram_hw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_mm, sun4c_flush_tlb_mm_hw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_range, sun4c_flush_tlb_range_hw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_page, sun4c_flush_tlb_page_hw, BTFIXUPCALL_NORM); @@ -2654,7 +2647,7 @@ void __init ld_mmu_sun4c(void) BTFIXUPSET_CALL(flush_cache_mm, sun4c_flush_cache_mm_sw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_cache_range, sun4c_flush_cache_range_sw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_cache_page, sun4c_flush_cache_page_sw, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(flush_page_to_ram, sun4c_flush_page_to_ram_sw, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(__flush_page_to_ram, sun4c_flush_page_to_ram_sw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_mm, sun4c_flush_tlb_mm_sw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_range, sun4c_flush_tlb_range_sw, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(flush_tlb_page, sun4c_flush_tlb_page_sw, BTFIXUPCALL_NORM); @@ -2731,11 +2724,9 @@ void __init ld_mmu_sun4c(void) BTFIXUPSET_CALL(mmu_flush_dma_area, sun4c_flush_dma_area, BTFIXUPCALL_NOP); BTFIXUPSET_CALL(mmu_inval_dma_area, sun4c_inval_dma_area, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mmu_v2p, sun4c_v2p, BTFIXUPCALL_NORM); - BTFIXUPSET_CALL(mmu_p2v, sun4c_p2v, BTFIXUPCALL_NORM); - /* Task struct and kernel stack allocating/freeing. */ BTFIXUPSET_CALL(alloc_task_struct, sun4c_alloc_task_struct, BTFIXUPCALL_NORM); + BTFIXUPSET_CALL(get_task_struct, sun4c_get_task_struct, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(quick_kernel_fault, sun4c_quick_kernel_fault, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(mmu_info, sun4c_mmu_info, BTFIXUPCALL_NORM); diff --git a/arch/sparc/mm/viking.S b/arch/sparc/mm/viking.S index f8959a0ac..bee2865dc 100644 --- a/arch/sparc/mm/viking.S +++ b/arch/sparc/mm/viking.S @@ -1,4 +1,4 @@ -/* $Id: viking.S,v 1.14 1999/08/14 03:51:50 anton Exp $ +/* $Id: viking.S,v 1.15 2000/01/15 00:51:36 anton Exp $ * viking.S: High speed Viking cache/mmu operations * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -35,37 +35,14 @@ sun4dsmp_flush_tlb_spin: .globl viking_flush_tlb_all, viking_flush_tlb_mm .globl viking_flush_tlb_range, viking_flush_tlb_page - .globl viking_c_flush_chunk, viking_s_flush_chunk - -viking_s_flush_chunk: - sethi %hi(KERNBASE), %g2 - ba 2f - sub %o0, %g2, %g3 - -viking_c_flush_chunk: - sethi %hi(KERNBASE), %g2 - cmp %o0, %g2 - bgeu 2f - sub %o0, %g2, %g3 - sethi BTFIXUP_SETHI(page_contig_offset), %g2 - ba 2f - sub %o0, %g2, %g3 - -viking_flush_page: viking_flush_chunk: - sethi %hi(C_LABEL(srmmu_v2p_hash)), %g2 - srl %o0, 24, %o1 - or %g2, %lo(C_LABEL(srmmu_v2p_hash)), %g2 - sll %o1, 2, %o1 - ld [%g2 + %o1], %g3 - and %o0, PAGE_MASK, %o0 - cmp %g3, -1 - be 9f - add %o0, %g3, %g3 -2: srl %g3, 12, %g1 ! ppage >> 12 +viking_flush_page: + sethi %hi(PAGE_OFFSET), %g2 + sub %o0, %g2, %g3 + srl %g3, 12, %g1 ! ppage >> 12 clr %o1 ! set counter, 0 - 127 - sethi %hi(KERNBASE + PAGE_SIZE - 0x80000000), %o3 + sethi %hi(PAGE_OFFSET + PAGE_SIZE - 0x80000000), %o3 sethi %hi(0x80000000), %o4 sethi %hi(VIKING_PTAG_VALID), %o5 sethi %hi(2*PAGE_SIZE), %o0 @@ -85,7 +62,7 @@ viking_flush_chunk: andcc %g2, %o5, %g0 ! ptag VALID? be 7f - add %g4, %o3, %g2 ! (KERNBASE + PAGE_SIZE) | (set << 5) + add %g4, %o3, %g2 ! (PAGE_OFFSET + PAGE_SIZE) | (set << 5) ld [%g2], %g3 ld [%g2 + %g7], %g3 add %g2, %o0, %g2 @@ -113,16 +90,9 @@ viking_flush_chunk: nop viking_mxcc_flush_page: - sethi %hi(C_LABEL(srmmu_v2p_hash)), %g2 - srl %o0, 24, %o1 - or %g2, %lo(C_LABEL(srmmu_v2p_hash)), %g2 - sll %o1, 2, %o1 - ld [%g2 + %o1], %g3 - and %o0, PAGE_MASK, %o0 - cmp %g3, -1 - be 9f - add %o0, %g3, %g3 -2: sub %g3, -PAGE_SIZE, %g3 ! ppage + PAGE_SIZE + sethi %hi(PAGE_OFFSET), %g2 + sub %o0, %g2, %g3 + sub %g3, -PAGE_SIZE, %g3 ! ppage + PAGE_SIZE sethi %hi(MXCC_SRCSTREAM), %o3 ! assume %hi(MXCC_SRCSTREAM) == %hi(MXCC_DESTSTREAM) mov 0x10, %g2 ! set cacheable bit or %o3, %lo(MXCC_SRCSTREAM), %o2 diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in index c1ef46648..448dad773 100644 --- a/arch/sparc64/config.in +++ b/arch/sparc64/config.in @@ -110,7 +110,7 @@ if [ "$CONFIG_PCI" = "y" ]; then define_bool CONFIG_IDEDMA_AUTO y define_bool CONFIG_IDEDMA_NEW_DRIVE_LISTINGS y define_bool CONFIG_BLK_DEV_NS87415 y - define_bool CONFIG_BLK_DEV_CMD646 y + define_bool CONFIG_BLK_DEV_CMD64X y fi fi diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 848984fef..59db5d4bc 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -139,7 +139,7 @@ CONFIG_BLK_DEV_IDEDMA=y CONFIG_IDEDMA_AUTO=y CONFIG_IDEDMA_NEW_DRIVE_LISTINGS=y CONFIG_BLK_DEV_NS87415=y -CONFIG_BLK_DEV_CMD646=y +CONFIG_BLK_DEV_CMD64X=y # # Networking options diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c index 252a685f4..76516f2f2 100644 --- a/arch/sparc64/kernel/binfmt_elf32.c +++ b/arch/sparc64/kernel/binfmt_elf32.c @@ -129,6 +129,13 @@ struct elf_prpsinfo32 char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ }; +#include <linux/highuid.h> + +#undef NEW_TO_OLD_UID +#undef NEW_TO_OLD_GID +#define NEW_TO_OLD_UID(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid) +#define NEW_TO_OLD_GID(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid) + #define elf_addr_t u32 #define elf_caddr_t u32 #undef start_thread diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index f62e3506d..df636ec6f 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.110 1999/11/19 05:52:50 davem Exp $ +/* $Id: entry.S,v 1.112 2000/01/14 07:12:31 davem Exp $ * arch/sparc64/kernel/entry.S: Sparc64 trap low-level entry points. * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -768,9 +768,9 @@ sunos_getpid: /* SunOS getuid() returns uid in %o0 and euid in %o1 */ .globl sunos_getuid sunos_getuid: - call sys_geteuid + call sys32_geteuid16 nop - call sys_getuid + call sys32_getuid16 stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1] b,pt %xcc, ret_sys_call stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] @@ -778,9 +778,9 @@ sunos_getuid: /* SunOS getgid() returns gid in %o0 and egid in %o1 */ .globl sunos_getgid sunos_getgid: - call sys_getegid + call sys32_getegid16 nop - call sys_getgid + call sys32_getgid16 stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1] b,pt %xcc, ret_sys_call stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0] diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c index ef0fb3e94..cba5cfac3 100644 --- a/arch/sparc64/kernel/ioctl32.c +++ b/arch/sparc64/kernel/ioctl32.c @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.72 2000/01/04 15:43:45 davem Exp $ +/* $Id: ioctl32.c,v 1.73 2000/01/11 01:06:47 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -594,6 +594,8 @@ static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long ar err |= __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq)); err |= __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma)); err |= __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port)); + if (err) + err = -EFAULT; break; } } @@ -667,7 +669,7 @@ static inline int hdio_getgeo(unsigned int fd, unsigned long arg) err = copy_to_user ((struct hd_geometry32 *)arg, &geo, 4); err |= __put_user (geo.start, &(((struct hd_geometry32 *)arg)->start)); } - return err; + return err ? -EFAULT : 0; } struct fbcmap32 { @@ -715,7 +717,7 @@ static inline int fbiogetputcmap(unsigned int fd, unsigned int cmd, unsigned lon ret |= copy_to_user ((char *)A(g), green, f.count); ret |= copy_to_user ((char *)A(b), blue, f.count); } - return ret; + return ret ? -EFAULT : 0; } struct fbcursor32 { @@ -826,8 +828,10 @@ static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) err |= __get_user(green, &((struct fb_cmap32 *)arg)->green); err |= __get_user(blue, &((struct fb_cmap32 *)arg)->blue); err |= __get_user(transp, &((struct fb_cmap32 *)arg)->transp); - if (err) + if (err) { + err = -EFAULT; goto out; + } err = -ENOMEM; cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); if (!cmap.red) @@ -851,8 +855,10 @@ static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) err |= __copy_from_user(cmap.green, (char *)A(green), cmap.len * sizeof(__u16)); err |= __copy_from_user(cmap.blue, (char *)A(blue), cmap.len * sizeof(__u16)); if (cmap.transp) err |= __copy_from_user(cmap.transp, (char *)A(transp), cmap.len * sizeof(__u16)); - if (err) + if (err) { + err = -EFAULT; goto out; + } break; default: do { @@ -896,6 +902,9 @@ static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) case FBIOPUTCMAP: break; } + if (err) + err = -EFAULT; + out: if (cmap.red) kfree(cmap.red); if (cmap.green) kfree(cmap.green); if (cmap.blue) kfree(cmap.blue); @@ -1064,8 +1073,10 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) err |= __get_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1); err |= __get_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap); err |= __get_user((u64)f->name, &((struct floppy_struct32 *)arg)->name); - if (err) + if (err) { + err = -EFAULT; goto out; + } break; } case FDSETDRVPRM32: @@ -1097,8 +1108,10 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) err |= __copy_from_user(f->autodetect, ((struct floppy_drive_params32 *)arg)->autodetect, sizeof(f->autodetect)); err |= __get_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq); err |= __get_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format); - if (err) + if (err) { + err = -EFAULT; goto out; + } break; } case FDGETDRVSTAT32: @@ -1221,6 +1234,9 @@ static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) default: break; } + if (err) + err = -EFAULT; + out: if (karg) kfree(karg); return err; } @@ -1396,8 +1412,7 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) return err; switch (cmd) { case MTIOCPOS32: - if (__put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno)) - return -EFAULT; + err = __put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno); break; case MTIOCGET32: err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type); @@ -1422,7 +1437,7 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) case MTIOCSETCONFIG32: break; } - return err; + return err ? -EFAULT: 0; } struct cdrom_read32 { @@ -1438,11 +1453,21 @@ struct cdrom_read_audio32 { __kernel_caddr_t32 buf; }; +struct cdrom_generic_command32 { + unsigned char cmd[CDROM_PACKET_SIZE]; + __kernel_caddr_t32 buffer; + unsigned int buflen; + int stat; + __kernel_caddr_t32 sense; + __kernel_caddr_t32 reserved[3]; +}; + static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); struct cdrom_read cdread; struct cdrom_read_audio cdreadaudio; + struct cdrom_generic_command cgc; __kernel_caddr_t32 addr; char *data = 0; void *karg; @@ -1477,6 +1502,17 @@ static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar return -ENOMEM; cdreadaudio.buf = data; break; + case CDROM_SEND_PACKET: + karg = &cgc; + err = copy_from_user(cgc.cmd, &((struct cdrom_generic_command32 *)arg)->cmd, sizeof(cgc.cmd)); + err |= __get_user(addr, &((struct cdrom_generic_command32 *)arg)->buffer); + err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen); + if (err) + return -EFAULT; + if ((data = kmalloc(cgc.buflen, GFP_KERNEL)) == NULL) + return -ENOMEM; + cgc.buffer = data; + break; default: do { static int count = 0; @@ -1502,11 +1538,15 @@ static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long ar case CDROMREADAUDIO: err = copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352); break; + case CDROM_SEND_PACKET: + err = copy_to_user((char *)A(addr), data, cgc.buflen); + break; default: break; } -out: if (data) kfree(data); - return err; +out: if (data) + kfree(data); + return err ? -EFAULT : 0; } struct loop_info32 { @@ -1558,7 +1598,7 @@ static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg) } break; } - return err; + return err ? -EFAULT : 0; } extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); @@ -1835,6 +1875,7 @@ asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) case CDROMREADCOOKED: case CDROMREADAUDIO: case CDROMREADALL: + case CDROM_SEND_PACKET: error = cdrom_ioctl_trans(fd, cmd, arg); goto out; diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index c102a6205..01fea4f59 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -1,4 +1,4 @@ -/* $Id: pci.c,v 1.13 2000/01/06 23:51:49 davem Exp $ +/* $Id: pci.c,v 1.14 2000/01/13 00:05:43 davem Exp $ * pci.c: UltraSparc PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com) @@ -228,6 +228,11 @@ int pci_assign_resource(struct pci_dev *dev, int i) return -ENOSYS; /* :-)... actually implement this soon */ } +int pcibios_enable_device(struct pci_dev *pdev) +{ + return 0; +} + char * __init pcibios_setup(char *str) { if (!strcmp(str, "onboardfirst")) { diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index d66086bfa..c12b5182d 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c @@ -1,4 +1,4 @@ -/* $Id: pci_psycho.c,v 1.7 1999/12/17 12:31:57 jj Exp $ +/* $Id: pci_psycho.c,v 1.9 2000/01/11 23:38:32 davem Exp $ * pci_psycho.c: PSYCHO/U2P specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -1278,6 +1278,11 @@ static void __init psycho_iommu_init(struct pci_controller_info *p) p->iommu.page_table = (iopte_t *)tsbbase; p->iommu.page_table_sz_bits = 17; p->iommu.page_table_map_base = 0xc0000000; +#ifndef NEW_PCI_DMA_MAP + memset((char *)tsbbase, 0, PAGE_SIZE << 5); +#else + memset((char *)tsbbase, 0, PAGE_SIZE << 7); +#endif #ifndef NEW_PCI_DMA_MAP iopte = (iopte_t *)tsbbase; diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 3788f71d3..7409b3164 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c @@ -1,4 +1,4 @@ -/* $Id: pci_sabre.c,v 1.8 2000/01/06 23:51:49 davem Exp $ +/* $Id: pci_sabre.c,v 1.10 2000/01/11 23:38:35 davem Exp $ * pci_sabre.c: Sabre specific PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu) @@ -1148,6 +1148,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p, } p->iommu.page_table = (iopte_t *)tsbbase; p->iommu.page_table_map_base = dvma_offset; + memset((char *)tsbbase, 0, PAGE_SIZE << order); #ifndef NEW_PCI_DMA_MAP iopte = (iopte_t *)tsbbase; diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 66e2b0bbe..f0e512666 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -1,4 +1,4 @@ -/* $Id: signal32.c,v 1.56 1999/12/20 01:16:16 davem Exp $ +/* $Id: signal32.c,v 1.58 2000/01/14 09:40:08 jj Exp $ * arch/sparc64/kernel/signal32.c * * Copyright (C) 1991, 1992 Linus Torvalds diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S index 4b461fbee..34db8d056 100644 --- a/arch/sparc64/kernel/sys32.S +++ b/arch/sparc64/kernel/sys32.S @@ -1,4 +1,4 @@ -/* $Id: sys32.S,v 1.9 1999/12/21 14:09:18 jj Exp $ +/* $Id: sys32.S,v 1.11 2000/01/11 17:33:29 jj Exp $ * sys32.S: I-cache tricks for 32-bit compatability layer simple * conversions. * @@ -20,7 +20,7 @@ sys32_mmap: .align 32 .globl sys32_lseek - .globl sys32_chmod, sys32_chown, sys32_lchown, sys32_mknod + .globl sys32_chmod, sys32_mknod sys32_lseek: sra %o1, 0, %o1 sethi %hi(sys_lseek), %g1 @@ -32,20 +32,6 @@ sys32_chmod: orcc %g2, %lo(0xffff), %g2 jmpl %g1 + %lo(sys_chmod), %g0 and %o1, %g2, %o1 -sys32_chown: - sethi %hi(0xffff), %g2 - sethi %hi(sys_chown), %g1 - orcc %g2, %lo(0xffff), %g2 - and %o1, %g2, %o1 - jmpl %g1 + %lo(sys_chown), %g0 - and %o2, %g2, %o2 -sys32_lchown: - sethi %hi(0xffff), %g2 - sethi %hi(sys_lchown), %g1 - orcc %g2, %lo(0xffff), %g2 - and %o1, %g2, %o1 - jmpl %g1 + %lo(sys_lchown), %g0 - and %o2, %g2, %o2 sys32_mknod: sethi %hi(0xffff), %g2 sethi %hi(sys_mknod), %g1 diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c index 486a09d99..af4743ec1 100644 --- a/arch/sparc64/kernel/sys_sparc.c +++ b/arch/sparc64/kernel/sys_sparc.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.32 2000/01/05 01:00:40 davem Exp $ +/* $Id: sys_sparc.c,v 1.33 2000/01/11 17:33:25 jj Exp $ * linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that @@ -22,6 +22,7 @@ #include <linux/smp.h> #include <linux/smp_lock.h> #include <linux/malloc.h> +#include <linux/ipc.h> #include <asm/uaccess.h> #include <asm/ipc.h> @@ -98,7 +99,7 @@ asmlinkage int sys_ipc (unsigned call, int first, int second, unsigned long thir err = -EFAULT; if(get_user(fourth.__pad, (void **)ptr)) goto out; - err = sys_semctl (first, second, (int)third, fourth); + err = sys_semctl (first, second | IPC_64, (int)third, fourth); goto out; } default: @@ -118,7 +119,7 @@ asmlinkage int sys_ipc (unsigned call, int first, int second, unsigned long thir err = sys_msgget ((key_t) first, second); goto out; case MSGCTL: - err = sys_msgctl (first, second, (struct msqid_ds *) ptr); + err = sys_msgctl (first, second | IPC_64, (struct msqid_ds *) ptr); goto out; default: err = -EINVAL; @@ -136,7 +137,7 @@ asmlinkage int sys_ipc (unsigned call, int first, int second, unsigned long thir err = sys_shmget (first, second, (int)third); goto out; case SHMCTL: - err = sys_shmctl (first, second, (struct shmid_ds *) ptr); + err = sys_shmctl (first, second | IPC_64, (struct shmid_ds *) ptr); goto out; default: err = -EINVAL; diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index f9be1320e..408368060 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.127 2000/01/04 23:54:41 davem Exp $ +/* $Id: sys_sparc32.c,v 1.130 2000/01/14 09:40:07 jj Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -43,6 +43,7 @@ #include <linux/stat.h> #include <linux/filter.h> #include <linux/highmem.h> +#include <linux/highuid.h> #include <asm/types.h> #include <asm/ipc.h> @@ -76,6 +77,181 @@ __ret; \ }) +extern asmlinkage long sys_chown(const char *, uid_t,gid_t); +extern asmlinkage long sys_lchown(const char *, uid_t,gid_t); +extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t); +extern asmlinkage long sys_setregid(gid_t, gid_t); +extern asmlinkage long sys_setgid(gid_t); +extern asmlinkage long sys_setreuid(uid_t, uid_t); +extern asmlinkage long sys_setuid(uid_t); +extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t); +extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t); +extern asmlinkage long sys_setfsuid(uid_t); +extern asmlinkage long sys_setfsgid(gid_t); + +/* For this source file, we want overflow handling. */ + +#undef high2lowuid +#undef high2lowgid +#undef low2highuid +#undef low2highgid +#undef SET_UID16 +#undef SET_GID16 +#undef NEW_TO_OLD_UID +#undef NEW_TO_OLD_GID +#undef SET_OLDSTAT_UID +#undef SET_OLDSTAT_GID +#undef SET_STAT_UID +#undef SET_STAT_GID + +#define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid) +#define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid) +#define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid) +#define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid) +#define SET_UID16(var, uid) var = high2lowuid(uid) +#define SET_GID16(var, gid) var = high2lowgid(gid) +#define NEW_TO_OLD_UID(uid) high2lowuid(uid) +#define NEW_TO_OLD_GID(gid) high2lowgid(gid) +#define SET_OLDSTAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid) +#define SET_OLDSTAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid) +#define SET_STAT_UID(stat, uid) (stat).st_uid = high2lowuid(uid) +#define SET_STAT_GID(stat, gid) (stat).st_gid = high2lowgid(gid) + +asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group) +{ + return sys_chown(filename, low2highuid(user), low2highgid(group)); +} + +asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group) +{ + return sys_lchown(filename, low2highuid(user), low2highgid(group)); +} + +asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group) +{ + return sys_fchown(fd, low2highuid(user), low2highgid(group)); +} + +asmlinkage long sys32_setregid16(u16 rgid, u16 egid) +{ + return sys_setregid(low2highgid(rgid), low2highgid(egid)); +} + +asmlinkage long sys32_setgid16(u16 gid) +{ + return sys_setgid((gid_t)gid); +} + +asmlinkage long sys32_setreuid16(u16 ruid, u16 euid) +{ + return sys_setreuid(low2highuid(ruid), low2highuid(euid)); +} + +asmlinkage long sys32_setuid16(u16 uid) +{ + return sys_setuid((uid_t)uid); +} + +asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid) +{ + return sys_setresuid(low2highuid(ruid), low2highuid(euid), + low2highuid(suid)); +} + +asmlinkage long sys32_getresuid16(u16 *ruid, u16 *euid, u16 *suid) +{ + int retval; + + if (!(retval = put_user(high2lowuid(current->uid), ruid)) && + !(retval = put_user(high2lowuid(current->euid), euid))) + retval = put_user(high2lowuid(current->suid), suid); + + return retval; +} + +asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid) +{ + return sys_setresgid(low2highgid(rgid), low2highgid(egid), + low2highgid(sgid)); +} + +asmlinkage long sys32_getresgid16(u16 *rgid, u16 *egid, u16 *sgid) +{ + int retval; + + if (!(retval = put_user(high2lowgid(current->gid), rgid)) && + !(retval = put_user(high2lowgid(current->egid), egid))) + retval = put_user(high2lowgid(current->sgid), sgid); + + return retval; +} + +asmlinkage long sys32_setfsuid16(u16 uid) +{ + return sys_setfsuid((uid_t)uid); +} + +asmlinkage long sys32_setfsgid16(u16 gid) +{ + return sys_setfsgid((gid_t)gid); +} + +asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist) +{ + u16 groups[NGROUPS]; + int i,j; + + if (gidsetsize < 0) + return -EINVAL; + i = current->ngroups; + if (gidsetsize) { + if (i > gidsetsize) + return -EINVAL; + for(j=0;j<i;j++) + groups[j] = current->groups[j]; + if (copy_to_user(grouplist, groups, sizeof(u16)*i)) + return -EFAULT; + } + return i; +} + +asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist) +{ + u16 groups[NGROUPS]; + int i; + + if (!capable(CAP_SETGID)) + return -EPERM; + if ((unsigned) gidsetsize > NGROUPS) + return -EINVAL; + if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16))) + return -EFAULT; + for (i = 0 ; i < gidsetsize ; i++) + current->groups[i] = (gid_t)groups[i]; + current->ngroups = gidsetsize; + return 0; +} + +asmlinkage long sys32_getuid16(void) +{ + return high2lowuid(current->uid); +} + +asmlinkage long sys32_geteuid16(void) +{ + return high2lowuid(current->euid); +} + +asmlinkage long sys32_getgid16(void) +{ + return high2lowgid(current->gid); +} + +asmlinkage long sys32_getegid16(void) +{ + return high2lowgid(current->egid); +} + /* In order to reduce some races, while at the same time doing additional * checking and hopefully speeding things up, we copy filenames to the * kernel data space before using them.. @@ -191,6 +367,17 @@ struct semid_ds32 { unsigned short sem_nsems; /* no. of semaphores in array */ }; +struct semid64_ds32 { + struct ipc64_perm sem_perm; /* this structure is the same on sparc32 and sparc64 */ + unsigned int __pad1; + __kernel_time_t32 sem_otime; + unsigned int __pad2; + __kernel_time_t32 sem_ctime; + u32 sem_nsems; + u32 __unused1; + u32 __unused2; +}; + struct msqid_ds32 { struct ipc_perm32 msg_perm; @@ -208,16 +395,51 @@ struct msqid_ds32 __kernel_ipc_pid_t32 msg_lrpid; }; +struct msqid64_ds32 { + struct ipc64_perm msg_perm; + unsigned int __pad1; + __kernel_time_t32 msg_stime; + unsigned int __pad2; + __kernel_time_t32 msg_rtime; + unsigned int __pad3; + __kernel_time_t32 msg_ctime; + unsigned int msg_cbytes; + unsigned int msg_qnum; + unsigned int msg_qbytes; + __kernel_pid_t32 msg_lspid; + __kernel_pid_t32 msg_lrpid; + unsigned int __unused1; + unsigned int __unused2; +}; + + struct shmid_ds32 { - struct ipc_perm32 shm_perm; - int shm_segsz; - __kernel_time_t32 shm_atime; - __kernel_time_t32 shm_dtime; - __kernel_time_t32 shm_ctime; - __kernel_ipc_pid_t32 shm_cpid; - __kernel_ipc_pid_t32 shm_lpid; - unsigned short shm_nattch; + struct ipc_perm32 shm_perm; + int shm_segsz; + __kernel_time_t32 shm_atime; + __kernel_time_t32 shm_dtime; + __kernel_time_t32 shm_ctime; + __kernel_ipc_pid_t32 shm_cpid; + __kernel_ipc_pid_t32 shm_lpid; + unsigned short shm_nattch; +}; + +struct shmid64_ds32 { + struct ipc64_perm shm_perm; + unsigned int __pad1; + __kernel_time_t32 shm_atime; + unsigned int __pad2; + __kernel_time_t32 shm_dtime; + unsigned int __pad3; + __kernel_time_t32 shm_ctime; + __kernel_size_t32 shm_segsz; + __kernel_pid_t32 shm_cpid; + __kernel_pid_t32 shm_lpid; + unsigned int shm_nattch; + unsigned int __unused1; + unsigned int __unused2; }; + /* * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.. @@ -245,6 +467,34 @@ static int do_sys32_semctl(int first, int second, int third, void *uptr) IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) | IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | IPCOP_MASK (IPC_RMID))) { err = sys_semctl (first, second, third, fourth); + } else if (third & IPC_64) { + struct semid64_ds s; + struct semid64_ds32 *usp = (struct semid64_ds32 *)A(pad); + mm_segment_t old_fs; + int need_back_translation; + + if (third == (IPC_SET|IPC_64)) { + err = get_user (s.sem_perm.uid, &usp->sem_perm.uid); + err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid); + err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode); + if (err) + goto out; + fourth.__pad = &s; + } + need_back_translation = + (IPCOP_MASK (third) & + (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0; + if (need_back_translation) + fourth.__pad = &s; + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_semctl (first, second, third, fourth); + set_fs (old_fs); + if (need_back_translation) { + int err2 = copy_to_user (&usp->sem_perm, &s.sem_perm, sizeof(struct ipc64_perm) + 2*sizeof(time_t)); + err2 |= __put_user (s.sem_nsems, &usp->sem_nsems); + if (err2) err = -EFAULT; + } } else { struct semid_ds s; struct semid_ds32 *usp = (struct semid_ds32 *)A(pad); @@ -270,10 +520,10 @@ static int do_sys32_semctl(int first, int second, int third, void *uptr) set_fs (old_fs); if (need_back_translation) { int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key); - err2 |= __put_user (s.sem_perm.uid, &usp->sem_perm.uid); - err2 |= __put_user (s.sem_perm.gid, &usp->sem_perm.gid); - err2 |= __put_user (s.sem_perm.cuid, &usp->sem_perm.cuid); - err2 |= __put_user (s.sem_perm.cgid, &usp->sem_perm.cgid); + err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid); + err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid); + err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid); + err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid); err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode); err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq); err2 |= __put_user (s.sem_otime, &usp->sem_otime); @@ -357,6 +607,34 @@ static int do_sys32_msgctl (int first, int second, void *uptr) (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) | IPCOP_MASK (IPC_RMID))) { err = sys_msgctl (first, second, (struct msqid_ds *)uptr); + } else if (second & IPC_64) { + struct msqid64_ds m; + struct msqid64_ds32 *up = (struct msqid64_ds32 *)uptr; + mm_segment_t old_fs; + + if (second == (IPC_SET|IPC_64)) { + err = get_user (m.msg_perm.uid, &up->msg_perm.uid); + err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid); + err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode); + err |= __get_user (m.msg_qbytes, &up->msg_qbytes); + if (err) + goto out; + } + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_msgctl (first, second, (struct msqid_ds *)&m); + set_fs (old_fs); + if (IPCOP_MASK (second) & + (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) { + int err2 = copy_to_user(&up->msg_perm, &m.msg_perm, sizeof(struct ipc64_perm) + 3*sizeof(time_t)); + err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes); + err2 |= __put_user (m.msg_qnum, &up->msg_qnum); + err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes); + err2 |= __put_user (m.msg_lspid, &up->msg_lspid); + err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid); + if (err2) + err = -EFAULT; + } } else { struct msqid_ds m; struct msqid_ds32 *up = (struct msqid_ds32 *)uptr; @@ -377,10 +655,10 @@ static int do_sys32_msgctl (int first, int second, void *uptr) if (IPCOP_MASK (second) & (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) { int err2 = put_user (m.msg_perm.key, &up->msg_perm.key); - err2 |= __put_user (m.msg_perm.uid, &up->msg_perm.uid); - err2 |= __put_user (m.msg_perm.gid, &up->msg_perm.gid); - err2 |= __put_user (m.msg_perm.cuid, &up->msg_perm.cuid); - err2 |= __put_user (m.msg_perm.cgid, &up->msg_perm.cgid); + err2 |= __put_user (high2lowuid(m.msg_perm.uid), &up->msg_perm.uid); + err2 |= __put_user (high2lowgid(m.msg_perm.gid), &up->msg_perm.gid); + err2 |= __put_user (high2lowuid(m.msg_perm.cuid), &up->msg_perm.cuid); + err2 |= __put_user (high2lowgid(m.msg_perm.cgid), &up->msg_perm.cgid); err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode); err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq); err2 |= __put_user (m.msg_stime, &up->msg_stime); @@ -423,12 +701,45 @@ static int do_sys32_shmctl (int first, int second, void *uptr) if (IPCOP_MASK (second) & (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) | IPCOP_MASK (SHM_UNLOCK) | IPCOP_MASK (IPC_RMID))) { + if (second == (IPC_INFO|IPC_64)) + second = IPC_INFO; /* So that we don't have to translate it */ err = sys_shmctl (first, second, (struct shmid_ds *)uptr); + } else if ((second & IPC_64) && second != (SHM_INFO|IPC_64)) { + struct shmid64_ds s; + struct shmid64_ds32 *up = (struct shmid64_ds32 *)uptr; + mm_segment_t old_fs; + + if (second == (IPC_SET|IPC_64)) { + err = get_user (s.shm_perm.uid, &up->shm_perm.uid); + err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid); + err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode); + if (err) + goto out; + } + old_fs = get_fs (); + set_fs (KERNEL_DS); + err = sys_shmctl (first, second, (struct shmid_ds *)&s); + set_fs (old_fs); + if (err < 0) + goto out; + + /* Mask it even in this case so it becomes a CSE. */ + if (IPCOP_MASK (second) & + (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) { + int err2 = copy_to_user (&up->shm_perm, &s.shm_perm, sizeof(struct ipc64_perm) + 3*sizeof(time_t)); + err2 |= __put_user (s.shm_segsz, &up->shm_segsz); + err2 |= __put_user (s.shm_nattch, &up->shm_nattch); + err2 |= __put_user (s.shm_cpid, &up->shm_cpid); + err2 |= __put_user (s.shm_lpid, &up->shm_lpid); + if (err2) + err = -EFAULT; + } } else { struct shmid_ds s; struct shmid_ds32 *up = (struct shmid_ds32 *)uptr; mm_segment_t old_fs; + second &= ~IPC_64; if (second == IPC_SET) { err = get_user (s.shm_perm.uid, &up->shm_perm.uid); err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid); @@ -462,10 +773,10 @@ static int do_sys32_shmctl (int first, int second, void *uptr) } else if (IPCOP_MASK (second) & (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) { int err2 = put_user (s.shm_perm.key, &up->shm_perm.key); - err2 |= __put_user (s.shm_perm.uid, &up->shm_perm.uid); - err2 |= __put_user (s.shm_perm.gid, &up->shm_perm.gid); - err2 |= __put_user (s.shm_perm.cuid, &up->shm_perm.cuid); - err2 |= __put_user (s.shm_perm.cgid, &up->shm_perm.cgid); + err2 |= __put_user (high2lowuid(s.shm_perm.uid), &up->shm_perm.uid); + err2 |= __put_user (high2lowuid(s.shm_perm.gid), &up->shm_perm.gid); + err2 |= __put_user (high2lowuid(s.shm_perm.cuid), &up->shm_perm.cuid); + err2 |= __put_user (high2lowuid(s.shm_perm.cgid), &up->shm_perm.cgid); err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode); err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq); err2 |= __put_user (s.shm_atime, &up->shm_atime); @@ -1244,8 +1555,8 @@ static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf) err |= put_user(ino, &statbuf->st_ino); err |= put_user(mode, &statbuf->st_mode); err |= put_user(nlink, &statbuf->st_nlink); - err |= put_user(uid, &statbuf->st_uid); - err |= put_user(gid, &statbuf->st_gid); + err |= put_user(high2lowuid(uid), &statbuf->st_uid); + err |= put_user(high2lowgid(gid), &statbuf->st_gid); err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev); err |= put_user(size, &statbuf->st_size); err |= put_user(atime, &statbuf->st_atime); @@ -1392,11 +1703,11 @@ static void *do_ncp_super_data_conv(void *raw_data) n->dir_mode = n32->dir_mode; n->file_mode = n32->file_mode; - n->gid = n32->gid; - n->uid = n32->uid; + n->gid = low2highgid(n32->gid); + n->uid = low2highuid(n32->uid); memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int))); n->wdog_pid = n32->wdog_pid; - n->mounted_uid = n32->mounted_uid; + n->mounted_uid = low2highuid(n32->mounted_uid); return raw_data; } @@ -1415,9 +1726,9 @@ static void *do_smb_super_data_conv(void *raw_data) struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data; s->version = s32->version; - s->mounted_uid = s32->mounted_uid; - s->uid = s32->uid; - s->gid = s32->gid; + s->mounted_uid = low2highuid(s32->mounted_uid); + s->uid = low2highuid(s32->uid); + s->gid = low2highgid(s32->gid); s->file_mode = s32->file_mode; s->dir_mode = s32->dir_mode; return raw_data; @@ -1853,91 +2164,6 @@ sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo) return ret; } -extern asmlinkage int sys_setreuid(uid_t ruid, uid_t euid); - -asmlinkage int sys32_setreuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid) -{ - uid_t sruid, seuid; - - sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid); - seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid); - return sys_setreuid(sruid, seuid); -} - -extern asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid); - -asmlinkage int sys32_setresuid(__kernel_uid_t32 ruid, - __kernel_uid_t32 euid, - __kernel_uid_t32 suid) -{ - uid_t sruid, seuid, ssuid; - - sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid); - seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid); - ssuid = (suid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)suid); - return sys_setresuid(sruid, seuid, ssuid); -} - -extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); - -asmlinkage int sys32_getresuid(__kernel_uid_t32 *ruid, __kernel_uid_t32 *euid, __kernel_uid_t32 *suid) -{ - uid_t a, b, c; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_getresuid(&a, &b, &c); - set_fs (old_fs); - if (put_user (a, ruid) || put_user (b, euid) || put_user (c, suid)) - return -EFAULT; - return ret; -} - -extern asmlinkage int sys_setregid(gid_t rgid, gid_t egid); - -asmlinkage int sys32_setregid(__kernel_gid_t32 rgid, __kernel_gid_t32 egid) -{ - gid_t srgid, segid; - - srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid); - segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid); - return sys_setregid(srgid, segid); -} - -extern asmlinkage int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid); - -asmlinkage int sys32_setresgid(__kernel_gid_t32 rgid, - __kernel_gid_t32 egid, - __kernel_gid_t32 sgid) -{ - gid_t srgid, segid, ssgid; - - srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid); - segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid); - ssgid = (sgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)sgid); - return sys_setresgid(srgid, segid, ssgid); -} - -extern asmlinkage int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); - -asmlinkage int sys32_getresgid(__kernel_gid_t32 *rgid, __kernel_gid_t32 *egid, __kernel_gid_t32 *sgid) -{ - gid_t a, b, c; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_getresgid(&a, &b, &c); - set_fs (old_fs); - if (!ret) { - ret = put_user (a, rgid); - ret |= put_user (b, egid); - ret |= put_user (c, sgid); - } - return ret; -} - struct tms32 { __kernel_clock_t32 tms_utime; __kernel_clock_t32 tms_stime; @@ -1968,43 +2194,6 @@ asmlinkage long sys32_times(struct tms32 *tbuf) return ret; } -extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist); - -asmlinkage int sys32_getgroups(int gidsetsize, __kernel_gid_t32 *grouplist) -{ - gid_t gl[NGROUPS]; - int ret, i; - mm_segment_t old_fs = get_fs (); - - set_fs (KERNEL_DS); - ret = sys_getgroups(gidsetsize, gl); - set_fs (old_fs); - if (gidsetsize && ret > 0 && ret <= NGROUPS) - for (i = 0; i < ret; i++, grouplist++) - if (__put_user (gl[i], grouplist)) - return -EFAULT; - return ret; -} - -extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist); - -asmlinkage int sys32_setgroups(int gidsetsize, __kernel_gid_t32 *grouplist) -{ - gid_t gl[NGROUPS]; - int ret, i; - mm_segment_t old_fs = get_fs (); - - if ((unsigned) gidsetsize > NGROUPS) - return -EINVAL; - for (i = 0; i < gidsetsize; i++, grouplist++) - if (__get_user (gl[i], grouplist)) - return -EFAULT; - set_fs (KERNEL_DS); - ret = sys_setgroups(gidsetsize, gl); - set_fs (old_fs); - return ret; -} - #define RLIM_INFINITY32 0x7fffffff #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) @@ -3554,6 +3743,8 @@ static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) &arg32->ca32_export.ex32_anon_uid); err |= __get_user(karg->ca_export.ex_anon_gid, &arg32->ca32_export.ex32_anon_gid); + karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid); + karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid); return err; } diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 27355da96..b66a116b4 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.62 2000/01/04 23:54:43 davem Exp $ +/* $Id: systbls.S,v 1.65 2000/01/14 07:12:34 davem Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -21,30 +21,30 @@ sys_call_table32: /*0*/ .word sys_nis_syscall, sparc_exit, sys_fork, sys_read, sys_write /*5*/ .word sparc32_open, sys_close, sys32_wait4, sys_creat, sys_link -/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown, sys32_mknod -/*15*/ .word sys32_chmod, sys32_lchown, sparc_brk, sys_perfctr, sys32_lseek -/*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid +/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod +/*15*/ .word sys32_chmod, sys32_lchown16, sparc_brk, sys_perfctr, sys32_lseek +/*20*/ .word sys_getpid, sys_capget, sys_capset, sys32_setuid16, sys32_getuid16 /*25*/ .word sys_time, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause -/*30*/ .word sys32_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice - .word sys_nis_syscall, sys_sync, sys_kill, sys32_newstat, sys32_sendfile -/*40*/ .word sys32_newlstat, sys_dup, sys_pipe, sys32_times, sys_nis_syscall - .word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid -/*50*/ .word sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl +/*30*/ .word sys32_utime, sys_lchown, sys_fchown, sys_access, sys_nice + .word sys_chown, sys_sync, sys_kill, sys32_newstat, sys32_sendfile +/*40*/ .word sys32_newlstat, sys_dup, sys_pipe, sys32_times, sys_getuid + .word sys_umount, sys32_setgid16, sys32_getgid16, sys_signal, sys32_geteuid16 +/*50*/ .word sys32_getegid16, sys_acct, sys_nis_syscall, sys_getgid, sys32_ioctl .word sys_reboot, sys32_mmap2, sys_symlink, sys_readlink, sys32_execve /*60*/ .word sys_umask, sys_chroot, sys32_newfstat, sys_fstat64, sys_getpagesize - .word sys_msync, sys_vfork, sys32_pread, sys32_pwrite, sys_nis_syscall -/*70*/ .word sys_nis_syscall, sys32_mmap, sys_nis_syscall, sys_munmap, sys_mprotect - .word sys_nis_syscall, sys_vhangup, sys32_truncate64, sys_nis_syscall, sys32_getgroups -/*80*/ .word sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys32_ftruncate64 - .word sys_swapon, sys32_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall -/*90*/ .word sys_dup2, sys_nis_syscall, sys32_fcntl, sys32_select, sys_nis_syscall + .word sys_msync, sys_vfork, sys32_pread, sys32_pwrite, sys_geteuid +/*70*/ .word sys_getegid, sys32_mmap, sys_setreuid, sys_munmap, sys_mprotect + .word sys_setregid, sys_vhangup, sys32_truncate64, sys_getgroups, sys32_getgroups16 +/*80*/ .word sys32_setgroups16, sys_getpgrp, sys_setgroups, sys32_setitimer, sys32_ftruncate64 + .word sys_swapon, sys32_getitimer, sys_setuid, sys_sethostname, sys_setgid +/*90*/ .word sys_dup2, sys_setfsuid, sys32_fcntl, sys32_select, sys_setfsgid .word sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall /*100*/ .word sys_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending - .word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall -/*110*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall + .word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid +/*110*/ .word sys_setresgid, sys_getresgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall .word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd -/*120*/ .word sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod - .word sys_nis_syscall, sys32_setreuid, sys32_setregid, sys_rename, sys_truncate +/*120*/ .word sys32_readv, sys32_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod + .word sys_nis_syscall, sys32_setreuid16, sys32_setregid16, sys_rename, sys_truncate /*130*/ .word sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall .word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_stat64 /*140*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit @@ -64,7 +64,7 @@ sys_call_table32: /*210*/ .word sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys32_sysinfo .word sys32_ipc, sys32_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex /*220*/ .word sys32_sigprocmask, sys32_create_module, sys32_delete_module, sys32_get_kernel_syms, sys_getpgid - .word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid + .word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16 /*230*/ .word sys32_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall .word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall /*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler @@ -99,8 +99,8 @@ sys_call_table: /*90*/ .word sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall .word sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept /*100*/ .word sys_getpriority, sys_rt_sigreturn, sys_rt_sigaction, sys_rt_sigprocmask, sys_rt_sigpending - .word sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall -/*110*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_recvmsg, sys_sendmsg + .word sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_setresuid, sys_getresuid +/*110*/ .word sys_setresgid, sys_getresgid, sys_nis_syscall, sys_recvmsg, sys_sendmsg .word sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_getcwd /*120*/ .word sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod .word sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate @@ -143,7 +143,7 @@ sunos_sys_table: .word sys_close, sunos_wait4, sys_creat .word sys_link, sys_unlink, sunos_execv .word sys_chdir, sunos_nosys, sys32_mknod - .word sys32_chmod, sys32_lchown, sunos_brk + .word sys32_chmod, sys32_lchown16, sunos_brk .word sunos_nosys, sys32_lseek, sunos_getpid .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_getuid, sunos_nosys, sys_ptrace @@ -164,8 +164,8 @@ sunos_sys_table: .word sunos_nosys, sunos_sbrk, sunos_sstk .word sunos_mmap, sunos_vadvise, sys_munmap .word sys_mprotect, sunos_madvise, sys_vhangup - .word sunos_nosys, sunos_mincore, sys32_getgroups - .word sys32_setgroups, sys_getpgrp, sunos_setpgrp + .word sunos_nosys, sunos_mincore, sys32_getgroups16 + .word sys32_setgroups16, sys_getpgrp, sunos_setpgrp .word sys32_setitimer, sunos_nosys, sys_swapon .word sys32_getitimer, sys_gethostname, sys_sethostname .word sunos_getdtablesize, sys_dup2, sunos_nop @@ -179,9 +179,9 @@ sunos_sys_table: .word sys32_sigstack, sys32_recvmsg, sys32_sendmsg .word sunos_nosys, sys32_gettimeofday, sys32_getrusage .word sunos_getsockopt, sunos_nosys, sunos_readv - .word sunos_writev, sys32_settimeofday, sys_fchown - .word sys_fchmod, sys32_recvfrom, sys32_setreuid - .word sys_setregid, sys_rename, sys_truncate + .word sunos_writev, sys32_settimeofday, sys32_fchown16 + .word sys_fchmod, sys32_recvfrom, sys32_setreuid16 + .word sys32_setregid16, sys_rename, sys_truncate .word sys_ftruncate, sys_flock, sunos_nosys .word sys32_sendto, sys_shutdown, sys_socketpair .word sys_mkdir, sys_rmdir, sys32_utimes diff --git a/arch/sparc64/mm/asyncd.c b/arch/sparc64/mm/asyncd.c index a64b09e86..f23a04ede 100644 --- a/arch/sparc64/mm/asyncd.c +++ b/arch/sparc64/mm/asyncd.c @@ -1,4 +1,4 @@ -/* $Id: asyncd.c,v 1.10 1999/12/15 22:25:02 davem Exp $ +/* $Id: asyncd.c,v 1.11 2000/01/08 20:22:19 davem Exp $ * The asyncd kernel daemon. This handles paging on behalf of * processes that receive page faults due to remote (async) memory * accesses. @@ -263,10 +263,11 @@ int asyncd(void *unused) save_flags(flags); cli(); while (!async_queue) { - spin_lock_irq(¤t->sigmask_lock); + spin_lock(¤t->sigmask_lock); flush_signals(current); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock(¤t->sigmask_lock); interruptible_sleep_on(&asyncd_wait); + __sti(); cli(); /* acquire gloabl_irq_lock */ } restore_flags(flags); diff --git a/arch/sparc64/solaris/entry64.S b/arch/sparc64/solaris/entry64.S index 53d825e6d..eb9cf3d26 100644 --- a/arch/sparc64/solaris/entry64.S +++ b/arch/sparc64/solaris/entry64.S @@ -1,4 +1,4 @@ -/* $Id: entry64.S,v 1.5 1998/03/26 08:46:15 jj Exp $ +/* $Id: entry64.S,v 1.6 2000/01/12 02:59:26 davem Exp $ * entry64.S: Solaris syscall emulation entry point. * * Copyright (C) 1996,1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -183,15 +183,15 @@ solaris_getpid: .globl solaris_getuid solaris_getuid: - lduh [%g6 + AOFF_task_euid], %o1 - lduh [%g6 + AOFF_task_uid], %o0 + lduw [%g6 + AOFF_task_euid], %o1 + lduw [%g6 + AOFF_task_uid], %o0 b,pt %xcc, ret_from_solaris stx %o1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1] .globl solaris_getgid solaris_getgid: - lduh [%g6 + AOFF_task_egid], %o1 - lduh [%g6 + AOFF_task_gid], %o0 + lduw [%g6 + AOFF_task_egid], %o1 + lduw [%g6 + AOFF_task_gid], %o0 b,pt %xcc, ret_from_solaris stx %o1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1] diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c index 86b0df283..e15ef157c 100644 --- a/arch/sparc64/solaris/fs.c +++ b/arch/sparc64/solaris/fs.c @@ -1,4 +1,4 @@ -/* $Id: fs.c,v 1.15 2000/01/04 23:54:47 davem Exp $ +/* $Id: fs.c,v 1.16 2000/01/12 02:59:27 davem Exp $ * fs.c: fs related syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -708,71 +708,6 @@ asmlinkage int solaris_ulimit(int cmd, int val) return -EINVAL; } -static int chown_common(struct dentry * dentry, uid_t user, gid_t group) -{ - struct inode * inode; - struct iattr newattrs; - int error; - - error = -ENOENT; - if (!(inode = dentry->d_inode)) { - printk("chown_common: NULL inode\n"); - goto out; - } - error = -EROFS; - if (IS_RDONLY(inode)) - goto out; - error = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - goto out; - if (user == (uid_t) -1) - user = inode->i_uid; - if (group == (gid_t) -1) - group = inode->i_gid; - newattrs.ia_mode = inode->i_mode; - newattrs.ia_uid = user; - newattrs.ia_gid = group; - newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME; - /* - * If the owner has been changed, remove the setuid bit - */ - if (inode->i_mode & S_ISUID) { - newattrs.ia_mode &= ~S_ISUID; - newattrs.ia_valid |= ATTR_MODE; - } - /* - * If the group has been changed, remove the setgid bit - * - * Don't remove the setgid bit if no group execute bit. - * This is a file marked for mandatory locking. - */ - if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) { - newattrs.ia_mode &= ~S_ISGID; - newattrs.ia_valid |= ATTR_MODE; - } - error = DQUOT_TRANSFER(dentry, &newattrs); -out: - return error; -} - -/* Linux chown works like Solaris lchown. Solaris chown does follow symlink */ -asmlinkage int solaris_chown(u32 filename, s32 user, s32 group) -{ - struct dentry * dentry; - int error; - - lock_kernel(); - dentry = namei((const char *)A(filename)); - - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { - error = chown_common(dentry, user, group); - dput(dentry); - } - unlock_kernel(); - return error; -} - /* At least at the time I'm writing this, Linux doesn't have ACLs, so we just fake this */ asmlinkage int solaris_acl(u32 filename, int cmd, int nentries, u32 aclbufp) diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c index a07fc7cc2..04e676907 100644 --- a/arch/sparc64/solaris/misc.c +++ b/arch/sparc64/solaris/misc.c @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.19 1999/12/15 17:51:25 jj Exp $ +/* $Id: misc.c,v 1.20 2000/01/12 02:59:26 davem Exp $ * misc.c: Miscelaneous syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -401,18 +401,6 @@ asmlinkage int solaris_sysconf(int id) } } -asmlinkage int solaris_setreuid(s32 ruid, s32 euid) -{ - int (*sys_setreuid)(uid_t, uid_t) = (int (*)(uid_t, uid_t))SYS(setreuid); - return sys_setreuid(ruid, euid); -} - -asmlinkage int solaris_setregid(s32 rgid, s32 egid) -{ - int (*sys_setregid)(gid_t, gid_t) = (int (*)(gid_t, gid_t))SYS(setregid); - return sys_setregid(rgid, egid); -} - asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid) { int ret; diff --git a/arch/sparc64/solaris/systbl.S b/arch/sparc64/solaris/systbl.S index 7c7c7b8b1..17562bafd 100644 --- a/arch/sparc64/solaris/systbl.S +++ b/arch/sparc64/solaris/systbl.S @@ -1,4 +1,4 @@ -/* $Id: systbl.S,v 1.8 1999/02/11 18:34:02 davem Exp $ +/* $Id: systbl.S,v 1.10 2000/01/12 02:59:26 davem Exp $ * systbl.S: System call entry point table for Solaris compatibility. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -40,7 +40,7 @@ solaris_sys_table: .word CHAIN(time) /* time 13 */ .word solaris_mknod /* mknod sox 14 */ .word CHAIN(chmod) /* chmod so 15 */ - .word solaris_chown /* chown sdd 16 */ + .word CHAIN(chown) /* chown sdd 16 */ .word solaris_brk /* brk/break x 17 */ .word solaris_stat /* stat sp 18 */ .word CHAIN(lseek) /* seek/lseek ddd 19 */ @@ -230,8 +230,8 @@ solaris_sys_table: .word CHAIN(nanosleep) /* nanosleep dd 199 */ .word solaris_facl /* facl dddp 200 */ .word solaris_unimplemented /* 201 */ - .word solaris_setreuid /* setreuid dd 202 */ - .word solaris_setregid /* setregid dd 203 */ + .word CHAIN(setreuid) /* setreuid dd 202 */ + .word CHAIN(setregid) /* setregid dd 203 */ .word solaris_unimplemented /* 204 */ .word solaris_unimplemented /* 205 */ .word solaris_unimplemented /* 206 */ |